[mathgl] 01/02: upstream release 2.4

Alastair McKinstry mckinstry at moszumanska.debian.org
Thu Sep 21 13:39:42 UTC 2017


This is an automated email from the git hooks/post-receive script.

mckinstry pushed a commit to branch debian/master
in repository mathgl.

commit b940052e1e0b2382c2ea7df62b08e3f8fc3cbac5
Author: Alastair McKinstry <mckinstry at debian.org>
Date:   Tue Aug 1 09:03:38 2017 +0100

    upstream release 2.4
---
 AUTHORS                                 |    9 +
 CMakeLists.txt                          |  788 ++++
 COPYING                                 |  674 ++++
 COPYING_LGPL                            |  165 +
 ChangeLog.txt                           |  482 +++
 FindMathGL2.cmake                       |  148 +
 INSTALL                                 |   10 +
 MathGLConfig.cmake.in                   |   18 +
 MathGLConfigVersion.cmake.in            |   11 +
 README                                  |   24 +
 README_V2                               |   51 +
 addons/getopt/CMakeLists.txt            |    2 +
 addons/getopt/getopt.c                  |  969 +++++
 addons/getopt/getopt.h                  |  121 +
 brush.ods                               |  Bin 0 -> 19306 bytes
 cmake-qt4.txt                           |   14 +
 cmake-qt5.txt                           |   22 +
 emblem.mgl                              |   40 +
 examples/CMakeLists.txt                 |   47 +
 examples/Equirectangular-projection.jpg |  Bin 0 -> 959921 bytes
 examples/FractInt.ifs                   |  158 +
 examples/fltk_example.cpp               |  150 +
 examples/full_test.cpp                  |  560 +++
 examples/glut_example.cpp               |   94 +
 examples/iris.dat                       |  151 +
 examples/mgl_module.cpp                 |   35 +
 examples/mpi_test.cpp                   |   39 +
 examples/qgl_example.cpp                |   64 +
 examples/qgl_example.h                  |   22 +
 examples/qt_example.cpp                 |  163 +
 examples/samples.cpp                    | 3159 +++++++++++++++
 examples/wnd_samples.cpp                |  519 +++
 examples/wx_example.cpp                 |   81 +
 fonts/CMakeLists.txt                    |   23 +
 fonts/STIX.vfm                          |  Bin 0 -> 931857 bytes
 fonts/STIX_b.vfm                        |  Bin 0 -> 577874 bytes
 fonts/STIX_bi.vfm                       |  Bin 0 -> 467229 bytes
 fonts/STIX_i.vfm                        |  Bin 0 -> 471933 bytes
 fonts/adventor.vfm                      |  Bin 0 -> 266241 bytes
 fonts/adventor_b.vfm                    |  Bin 0 -> 258872 bytes
 fonts/adventor_bi.vfm                   |  Bin 0 -> 271197 bytes
 fonts/adventor_i.vfm                    |  Bin 0 -> 278121 bytes
 fonts/bonum.vfm                         |  Bin 0 -> 525818 bytes
 fonts/bonum_b.vfm                       |  Bin 0 -> 500685 bytes
 fonts/bonum_bi.vfm                      |  Bin 0 -> 549356 bytes
 fonts/bonum_i.vfm                       |  Bin 0 -> 555506 bytes
 fonts/chorus.vfm                        |  Bin 0 -> 521710 bytes
 fonts/cursor.vfm                        |  Bin 0 -> 580080 bytes
 fonts/cursor_b.vfm                      |  Bin 0 -> 651531 bytes
 fonts/cursor_bi.vfm                     |  Bin 0 -> 671869 bytes
 fonts/cursor_i.vfm                      |  Bin 0 -> 631711 bytes
 fonts/heros.vfm                         |  Bin 0 -> 285750 bytes
 fonts/heros_b.vfm                       |  Bin 0 -> 285026 bytes
 fonts/heros_bi.vfm                      |  Bin 0 -> 311011 bytes
 fonts/heros_i.vfm                       |  Bin 0 -> 315904 bytes
 fonts/heroscn.vfm                       |  Bin 0 -> 270313 bytes
 fonts/heroscn_b.vfm                     |  Bin 0 -> 261330 bytes
 fonts/heroscn_bi.vfm                    |  Bin 0 -> 285968 bytes
 fonts/heroscn_i.vfm                     |  Bin 0 -> 292114 bytes
 fonts/make_bin.cpp                      |   51 +
 fonts/pagella.vfm                       |  Bin 0 -> 551258 bytes
 fonts/pagella_b.vfm                     |  Bin 0 -> 542842 bytes
 fonts/pagella_bi.vfm                    |  Bin 0 -> 634397 bytes
 fonts/pagella_i.vfm                     |  Bin 0 -> 622419 bytes
 fonts/schola.vfm                        |  Bin 0 -> 541994 bytes
 fonts/schola_b.vfm                      |  Bin 0 -> 545310 bytes
 fonts/schola_bi.vfm                     |  Bin 0 -> 588460 bytes
 fonts/schola_i.vfm                      |  Bin 0 -> 585632 bytes
 fonts/termes.vfm                        |  Bin 0 -> 554688 bytes
 fonts/termes_b.vfm                      |  Bin 0 -> 526340 bytes
 fonts/termes_bi.vfm                     |  Bin 0 -> 584270 bytes
 fonts/termes_i.vfm                      |  Bin 0 -> 588928 bytes
 include/CMakeLists.txt                  |   35 +
 include/config.h.in                     |   46 +
 include/mgl2/Fl_MathGL.h                |  184 +
 include/mgl2/abstract.h                 |  330 ++
 include/mgl2/addon.h                    |   63 +
 include/mgl2/base.h                     |  710 ++++
 include/mgl2/base_cf.h                  |  233 ++
 include/mgl2/canvas.h                   |  529 +++
 include/mgl2/canvas_cf.h                |  715 ++++
 include/mgl2/canvas_wnd.h               |   83 +
 include/mgl2/cont.h                     |  249 ++
 include/mgl2/data.h                     | 1022 +++++
 include/mgl2/data_cf.h                  |  531 +++
 include/mgl2/datac.h                    |  584 +++
 include/mgl2/datac_cf.h                 |  393 ++
 include/mgl2/define.h                   |  386 ++
 include/mgl2/eval.h                     |   60 +
 include/mgl2/evalc.h                    |   49 +
 include/mgl2/fit.h                      |   90 +
 include/mgl2/fltk.h                     |   71 +
 include/mgl2/font.h                     |  144 +
 include/mgl2/glut.h                     |   85 +
 include/mgl2/gsl.fs                     | 1276 ++++++
 include/mgl2/mathgl.fs                  |  472 +++
 include/mgl2/mgl.fs                     |  608 +++
 include/mgl2/mgl.h                      | 2321 +++++++++++
 include/mgl2/mgl_cf.h                   |   55 +
 include/mgl2/mgl_pas.pas                | 1630 ++++++++
 include/mgl2/mglplot.fs                 |  562 +++
 include/mgl2/mpi.h                      |   57 +
 include/mgl2/opengl.h                   |   68 +
 include/mgl2/other.h                    |  184 +
 include/mgl2/parser.h                   |  200 +
 include/mgl2/pde.h                      |   84 +
 include/mgl2/plot.h                     |  260 ++
 include/mgl2/prim.h                     |  261 ++
 include/mgl2/qmathgl.h                  |  253 ++
 include/mgl2/qt.h                       |   64 +
 include/mgl2/surf.h                     |  165 +
 include/mgl2/thread.h                   |   86 +
 include/mgl2/type.h                     |  175 +
 include/mgl2/vect.h                     |  222 ++
 include/mgl2/vectors.fs                 |  161 +
 include/mgl2/volume.h                   |  135 +
 include/mgl2/window.h                   |   61 +
 include/mgl2/wnd.h                      |  137 +
 include/mgl2/wx.h                       |  138 +
 include/xpm/alpha.xpm                   |  126 +
 include/xpm/arc.xpm                     |   21 +
 include/xpm/arrow_a.xpm                 |   21 +
 include/xpm/arrow_d.xpm                 |   21 +
 include/xpm/arrow_i.xpm                 |   21 +
 include/xpm/arrow_k.xpm                 |   21 +
 include/xpm/arrow_n.xpm                 |   21 +
 include/xpm/arrow_o.xpm                 |   21 +
 include/xpm/arrow_s.xpm                 |   21 +
 include/xpm/arrow_t.xpm                 |   21 +
 include/xpm/arrow_v.xpm                 |   21 +
 include/xpm/axis.xpm                    |   21 +
 include/xpm/axis_sh.xpm                 |   22 +
 include/xpm/barrow_a.xpm                |   21 +
 include/xpm/barrow_d.xpm                |   21 +
 include/xpm/barrow_i.xpm                |   21 +
 include/xpm/barrow_k.xpm                |   21 +
 include/xpm/barrow_n.xpm                |   21 +
 include/xpm/barrow_o.xpm                |   21 +
 include/xpm/barrow_s.xpm                |   21 +
 include/xpm/barrow_t.xpm                |   21 +
 include/xpm/barrow_v.xpm                |   21 +
 include/xpm/box.xpm                     |   22 +
 include/xpm/comment.xpm                 |   21 +
 include/xpm/cons.xpm                    |   23 +
 include/xpm/copy.xpm                    |   23 +
 include/xpm/crop.xpm                    |   21 +
 include/xpm/curve.xpm                   |   21 +
 include/xpm/dash_d.xpm                  |   21 +
 include/xpm/dash_e.xpm                  |   21 +
 include/xpm/dash_i.xpm                  |   21 +
 include/xpm/dash_j.xpm                  |   21 +
 include/xpm/dash_l.xpm                  |   21 +
 include/xpm/dash_m.xpm                  |   21 +
 include/xpm/dash_s.xpm                  |   21 +
 include/xpm/delete.xpm                  |   21 +
 include/xpm/diff.xpm                    |   21 +
 include/xpm/diff2.xpm                   |   22 +
 include/xpm/down_1.xpm                  |   22 +
 include/xpm/fileprint.xpm               |   24 +
 include/xpm/first.xpm                   |   21 +
 include/xpm/folder.xpm                  |  130 +
 include/xpm/func.xpm                    |   21 +
 include/xpm/hist.xpm                    |   21 +
 include/xpm/insert.xpm                  |   23 +
 include/xpm/integr.xpm                  |   22 +
 include/xpm/last.xpm                    |   21 +
 include/xpm/left_1.xpm                  |   22 +
 include/xpm/light.xpm                   |   42 +
 include/xpm/line.xpm                    |   21 +
 include/xpm/mark_.xpm                   |   21 +
 include/xpm/mark_a.xpm                  |   21 +
 include/xpm/mark_cf.xpm                 |   21 +
 include/xpm/mark_d.xpm                  |   21 +
 include/xpm/mark_df.xpm                 |   21 +
 include/xpm/mark_l.xpm                  |   21 +
 include/xpm/mark_lf.xpm                 |   21 +
 include/xpm/mark_n.xpm                  |   20 +
 include/xpm/mark_o.xpm                  |   21 +
 include/xpm/mark_of.xpm                 |   21 +
 include/xpm/mark_p.xpm                  |   21 +
 include/xpm/mark_pf.xpm                 |   21 +
 include/xpm/mark_r.xpm                  |   21 +
 include/xpm/mark_rf.xpm                 |   21 +
 include/xpm/mark_s.xpm                  |   21 +
 include/xpm/mark_sf.xpm                 |   21 +
 include/xpm/mark_t.xpm                  |   21 +
 include/xpm/mark_tf.xpm                 |   21 +
 include/xpm/mark_v.xpm                  |   21 +
 include/xpm/mark_vf.xpm                 |   21 +
 include/xpm/mark_x.xpm                  |   21 +
 include/xpm/mark_y.xpm                  |   21 +
 include/xpm/mask_a.xpm                  |   21 +
 include/xpm/mask_d.xpm                  |   21 +
 include/xpm/mask_d_.xpm                 |   21 +
 include/xpm/mask_e.xpm                  |   21 +
 include/xpm/mask_i.xpm                  |   21 +
 include/xpm/mask_j.xpm                  |   21 +
 include/xpm/mask_l.xpm                  |   21 +
 include/xpm/mask_m.xpm                  |   21 +
 include/xpm/mask_o.xpm                  |   21 +
 include/xpm/mask_o_.xpm                 |   21 +
 include/xpm/mask_p.xpm                  |   21 +
 include/xpm/mask_r.xpm                  |   21 +
 include/xpm/mask_s.xpm                  |   21 +
 include/xpm/mask_s_.xpm                 |   21 +
 include/xpm/mask_t.xpm                  |   21 +
 include/xpm/mask_u.xpm                  |   21 +
 include/xpm/next.xpm                    |   21 +
 include/xpm/next_sl.xpm                 |   24 +
 include/xpm/none.xpm                    |   21 +
 include/xpm/norm_1.xpm                  |   22 +
 include/xpm/ok.xpm                      |   22 +
 include/xpm/oper.xpm                    |   21 +
 include/xpm/oper_a.xpm                  |   21 +
 include/xpm/oper_d.xpm                  |   21 +
 include/xpm/oper_dir.xpm                |   21 +
 include/xpm/oper_m.xpm                  |   22 +
 include/xpm/oper_of.xpm                 |   22 +
 include/xpm/oper_s.xpm                  |   21 +
 include/xpm/option.xpm                  |   22 +
 include/xpm/other.xpm                   |  117 +
 include/xpm/pause.xpm                   |   22 +
 include/xpm/plot.xpm                    |   23 +
 include/xpm/polygon.xpm                 |   21 +
 include/xpm/prev_sl.xpm                 |   24 +
 include/xpm/preview.xpm                 |  193 +
 include/xpm/right_1.xpm                 |   22 +
 include/xpm/rotate.xpm                  |   22 +
 include/xpm/show_sl.xpm                 |   22 +
 include/xpm/size.xpm                    |   21 +
 include/xpm/squize.xpm                  |   22 +
 include/xpm/stop.xpm                    |   23 +
 include/xpm/style.xpm                   |   22 +
 include/xpm/table.xpm                   |   24 +
 include/xpm/text.xpm                    |   21 +
 include/xpm/tiles.xpm                   |  132 +
 include/xpm/tran.xpm                    |   23 +
 include/xpm/udav.xpm                    |  416 ++
 include/xpm/unused/smth.xpm             |   22 +
 include/xpm/unused/sum.xpm              |   21 +
 include/xpm/unused/swap.xpm             |   23 +
 include/xpm/up_1.xpm                    |   22 +
 include/xpm/update.xpm                  |   21 +
 include/xpm/vect.xpm                    |   60 +
 include/xpm/window.xpm                  |   29 +
 include/xpm/wire.xpm                    |   21 +
 include/xpm/zoom_1.xpm                  |   22 +
 include/xpm/zoom_in.xpm                 |  124 +
 include/xpm/zoom_out.xpm                |  130 +
 json/Backend.cpp                        |   90 +
 json/Backend.hpp                        |   22 +
 json/CMakeLists.txt                     |   54 +
 json/MainWindow.cpp                     |   55 +
 json/MainWindow.hpp                     |   23 +
 json/MainWindow.ui                      |   44 +
 json/RotationExample.py                 |   25 +
 json/index.html                         |   26 +
 json/main.js                            |   38 +
 json/mathgl.Backend.js                  |   13 +
 json/mathgl.Graph.js                    |  750 ++++
 json/mathgl.View.js                     |  266 ++
 json/mathgl.WebkitBackend.js            |   32 +
 json/mathgl.js                          |   29 +
 json/sylvester.src.js                   | 1254 ++++++
 lang/CMakeLists.txt                     |  136 +
 lang/DESCRIPTION                        |   13 +
 lang/INDEX                              |    0
 lang/PKG_ADD_template                   |    2 +
 lang/data.i                             |  585 +++
 lang/mathgl.i                           |  100 +
 lang/mgl.i                              | 2258 +++++++++++
 lang/numpy.i                            | 1634 ++++++++
 lang/sed_rules                          |   13 +
 lang/type.i                             |  101 +
 mathgl-2x.cbp                           |  129 +
 mathgl_en.po                            | 6307 ++++++++++++++++++++++++++++++
 mathgl_es.po                            | 6345 ++++++++++++++++++++++++++++++
 mathgl_ru.po                            | 6513 +++++++++++++++++++++++++++++++
 mgllab/CMakeLists.txt                   |   59 +
 mgllab/dialogs.cpp                      | 1541 ++++++++
 mgllab/editor.cpp                       |  692 ++++
 mgllab/fltk_test.fl                     | 2662 +++++++++++++
 mgllab/grid.cpp                         |  137 +
 mgllab/help.cpp                         |  489 +++
 mgllab/mathgl.cpp                       |  478 +++
 mgllab/mgl.xml.in                       |   10 +
 mgllab/mgllab.cpp                       |  676 ++++
 mgllab/mgllab.desktop                   |   13 +
 mgllab/mgllab.h                         |  271 ++
 mgllab/mgllab.rc                        |   25 +
 mgllab/table.cpp                        |  933 +++++
 mgllab/todo.txt                         |    8 +
 mgllab/udav.ico                         |  Bin 0 -> 16958 bytes
 mgllab/udav.png                         |  Bin 0 -> 4139 bytes
 mgllab/udav48.ico                       |  Bin 0 -> 9662 bytes
 mgllab/xpm/accessories-calculator.xpm   |  103 +
 mgllab/xpm/alpha.xpm                    |  126 +
 mgllab/xpm/arc.xpm                      |   21 +
 mgllab/xpm/arrow-down-double.xpm        |  129 +
 mgllab/xpm/arrow-down.xpm               |   85 +
 mgllab/xpm/arrow-left-double.xpm        |  128 +
 mgllab/xpm/arrow-left.xpm               |   86 +
 mgllab/xpm/arrow-right-double.xpm       |  128 +
 mgllab/xpm/arrow-right.xpm              |   92 +
 mgllab/xpm/arrow-up-double.xpm          |  132 +
 mgllab/xpm/arrow-up.xpm                 |   86 +
 mgllab/xpm/arrow_a.xpm                  |   21 +
 mgllab/xpm/arrow_d.xpm                  |   21 +
 mgllab/xpm/arrow_i.xpm                  |   21 +
 mgllab/xpm/arrow_k.xpm                  |   21 +
 mgllab/xpm/arrow_n.xpm                  |   21 +
 mgllab/xpm/arrow_o.xpm                  |   21 +
 mgllab/xpm/arrow_s.xpm                  |   21 +
 mgllab/xpm/arrow_t.xpm                  |   21 +
 mgllab/xpm/arrow_v.xpm                  |   21 +
 mgllab/xpm/axis.xpm                     |   21 +
 mgllab/xpm/axis_sh.xpm                  |   22 +
 mgllab/xpm/barrow_a.xpm                 |   21 +
 mgllab/xpm/barrow_d.xpm                 |   21 +
 mgllab/xpm/barrow_i.xpm                 |   21 +
 mgllab/xpm/barrow_k.xpm                 |   21 +
 mgllab/xpm/barrow_n.xpm                 |   21 +
 mgllab/xpm/barrow_o.xpm                 |   21 +
 mgllab/xpm/barrow_s.xpm                 |   21 +
 mgllab/xpm/barrow_t.xpm                 |   21 +
 mgllab/xpm/barrow_v.xpm                 |   21 +
 mgllab/xpm/box.xpm                      |   22 +
 mgllab/xpm/comment.xpm                  |   21 +
 mgllab/xpm/cons.xpm                     |   23 +
 mgllab/xpm/copy.xpm                     |   23 +
 mgllab/xpm/crop.xpm                     |   21 +
 mgllab/xpm/curve.xpm                    |   21 +
 mgllab/xpm/dash_d.xpm                   |   21 +
 mgllab/xpm/dash_e.xpm                   |   21 +
 mgllab/xpm/dash_i.xpm                   |   21 +
 mgllab/xpm/dash_j.xpm                   |   21 +
 mgllab/xpm/dash_l.xpm                   |   21 +
 mgllab/xpm/dash_m.xpm                   |   21 +
 mgllab/xpm/dash_s.xpm                   |   21 +
 mgllab/xpm/delete.xpm                   |   21 +
 mgllab/xpm/dialog-information.xpm       |  138 +
 mgllab/xpm/diff.xpm                     |   21 +
 mgllab/xpm/diff2.xpm                    |   22 +
 mgllab/xpm/document-export.xpm          |  169 +
 mgllab/xpm/document-import.xpm          |  197 +
 mgllab/xpm/document-new.xpm             |   97 +
 mgllab/xpm/document-open-folder.xpm     |  179 +
 mgllab/xpm/document-open.xpm            |  168 +
 mgllab/xpm/document-print.xpm           |   95 +
 mgllab/xpm/document-properties.xpm      |   63 +
 mgllab/xpm/document-revert.xpm          |  164 +
 mgllab/xpm/document-save.xpm            |  129 +
 mgllab/xpm/down_1.xpm                   |   22 +
 mgllab/xpm/edit-clear.xpm               |  130 +
 mgllab/xpm/edit-copy.xpm                |   74 +
 mgllab/xpm/edit-cut.xpm                 |   40 +
 mgllab/xpm/edit-delete.xpm              |  158 +
 mgllab/xpm/edit-find.xpm                |   86 +
 mgllab/xpm/edit-paste.xpm               |  120 +
 mgllab/xpm/edit-redo.xpm                |  113 +
 mgllab/xpm/edit-select-all.xpm          |  108 +
 mgllab/xpm/edit-undo.xpm                |  131 +
 mgllab/xpm/edit_xpm                     |    9 +
 mgllab/xpm/fileprint.xpm                |   24 +
 mgllab/xpm/first.xpm                    |   21 +
 mgllab/xpm/folder.xpm                   |  130 +
 mgllab/xpm/format-indent-more.xpm       |   56 +
 mgllab/xpm/format-stroke-color.xpm      |   87 +
 mgllab/xpm/func.xpm                     |   21 +
 mgllab/xpm/go-bottom.xpm                |  108 +
 mgllab/xpm/go-down.xpm                  |  122 +
 mgllab/xpm/go-first-view.xpm            |  138 +
 mgllab/xpm/go-first.xpm                 |  119 +
 mgllab/xpm/go-jump-locationbar.xpm      |  103 +
 mgllab/xpm/go-last-view.xpm             |  139 +
 mgllab/xpm/go-last.xpm                  |  116 +
 mgllab/xpm/go-next-view-page.xpm        |   99 +
 mgllab/xpm/go-next-view.xpm             |  102 +
 mgllab/xpm/go-next.xpm                  |  128 +
 mgllab/xpm/go-previous-view-page.xpm    |   97 +
 mgllab/xpm/go-previous-view.xpm         |  102 +
 mgllab/xpm/go-previous.xpm              |  123 +
 mgllab/xpm/go-top.xpm                   |  116 +
 mgllab/xpm/go-up.xpm                    |  123 +
 mgllab/xpm/help-contents.xpm            |  126 +
 mgllab/xpm/help-faq.xpm                 |   95 +
 mgllab/xpm/hist.xpm                     |   21 +
 mgllab/xpm/insert.xpm                   |   23 +
 mgllab/xpm/integr.xpm                   |   22 +
 mgllab/xpm/last.xpm                     |   21 +
 mgllab/xpm/layer-visible-off.xpm        |   97 +
 mgllab/xpm/layer-visible-on.xpm         |  118 +
 mgllab/xpm/left_1.xpm                   |   22 +
 mgllab/xpm/light.xpm                    |   42 +
 mgllab/xpm/line.xpm                     |   21 +
 mgllab/xpm/list-add.xpm                 |  115 +
 mgllab/xpm/list-remove.xpm              |   68 +
 mgllab/xpm/mark_.xpm                    |   21 +
 mgllab/xpm/mark_a.xpm                   |   21 +
 mgllab/xpm/mark_cf.xpm                  |   21 +
 mgllab/xpm/mark_d.xpm                   |   21 +
 mgllab/xpm/mark_df.xpm                  |   21 +
 mgllab/xpm/mark_l.xpm                   |   21 +
 mgllab/xpm/mark_lf.xpm                  |   21 +
 mgllab/xpm/mark_n.xpm                   |   20 +
 mgllab/xpm/mark_o.xpm                   |   21 +
 mgllab/xpm/mark_of.xpm                  |   21 +
 mgllab/xpm/mark_p.xpm                   |   21 +
 mgllab/xpm/mark_pf.xpm                  |   21 +
 mgllab/xpm/mark_r.xpm                   |   21 +
 mgllab/xpm/mark_rf.xpm                  |   21 +
 mgllab/xpm/mark_s.xpm                   |   21 +
 mgllab/xpm/mark_sf.xpm                  |   21 +
 mgllab/xpm/mark_t.xpm                   |   21 +
 mgllab/xpm/mark_tf.xpm                  |   21 +
 mgllab/xpm/mark_v.xpm                   |   21 +
 mgllab/xpm/mark_vf.xpm                  |   21 +
 mgllab/xpm/mark_x.xpm                   |   21 +
 mgllab/xpm/mark_y.xpm                   |   21 +
 mgllab/xpm/mask_a.xpm                   |   21 +
 mgllab/xpm/mask_d.xpm                   |   21 +
 mgllab/xpm/mask_d_.xpm                  |   21 +
 mgllab/xpm/mask_e.xpm                   |   21 +
 mgllab/xpm/mask_i.xpm                   |   21 +
 mgllab/xpm/mask_j.xpm                   |   21 +
 mgllab/xpm/mask_l.xpm                   |   21 +
 mgllab/xpm/mask_m.xpm                   |   21 +
 mgllab/xpm/mask_o.xpm                   |   21 +
 mgllab/xpm/mask_o_.xpm                  |   21 +
 mgllab/xpm/mask_p.xpm                   |   21 +
 mgllab/xpm/mask_r.xpm                   |   21 +
 mgllab/xpm/mask_s.xpm                   |   21 +
 mgllab/xpm/mask_s_.xpm                  |   21 +
 mgllab/xpm/mask_t.xpm                   |   21 +
 mgllab/xpm/mask_u.xpm                   |   21 +
 mgllab/xpm/media-playback-start.xpm     |  108 +
 mgllab/xpm/media-seek-backward.xpm      |  112 +
 mgllab/xpm/media-seek-forward.xpm       |  109 +
 mgllab/xpm/next.xpm                     |   21 +
 mgllab/xpm/next_sl.xpm                  |   24 +
 mgllab/xpm/none.xpm                     |   21 +
 mgllab/xpm/norm_1.xpm                   |   22 +
 mgllab/xpm/object-group.xpm             |   46 +
 mgllab/xpm/object-order-lower.xpm       |  101 +
 mgllab/xpm/object-order-raise.xpm       |  102 +
 mgllab/xpm/object-rotate-down.xpm       |  105 +
 mgllab/xpm/object-rotate-left.xpm       |  104 +
 mgllab/xpm/object-rotate-right.xpm      |  105 +
 mgllab/xpm/object-rotate-up.xpm         |  104 +
 mgllab/xpm/object-ungroup.xpm           |   46 +
 mgllab/xpm/office-chart-bar.xpm         |   84 +
 mgllab/xpm/office-chart-line.xpm        |   71 +
 mgllab/xpm/office-chart-scatter.xpm     |   44 +
 mgllab/xpm/ok.xpm                       |   22 +
 mgllab/xpm/oper.xpm                     |   21 +
 mgllab/xpm/oper_a.xpm                   |   21 +
 mgllab/xpm/oper_d.xpm                   |   21 +
 mgllab/xpm/oper_dir.xpm                 |   21 +
 mgllab/xpm/oper_m.xpm                   |   22 +
 mgllab/xpm/oper_of.xpm                  |   22 +
 mgllab/xpm/oper_s.xpm                   |   21 +
 mgllab/xpm/option.xpm                   |   22 +
 mgllab/xpm/other.xpm                    |  117 +
 mgllab/xpm/package-x-generic.xpm        |  107 +
 mgllab/xpm/pause.xpm                    |   22 +
 mgllab/xpm/plot.xpm                     |   23 +
 mgllab/xpm/polygon.xpm                  |   21 +
 mgllab/xpm/preferences-system.xpm       |  115 +
 mgllab/xpm/prev_sl.xpm                  |   24 +
 mgllab/xpm/preview.xpm                  |  193 +
 mgllab/xpm/process-stop.xpm             |  144 +
 mgllab/xpm/right_1.xpm                  |   22 +
 mgllab/xpm/rotate.xpm                   |   22 +
 mgllab/xpm/show_sl.xpm                  |   22 +
 mgllab/xpm/size.xpm                     |   21 +
 mgllab/xpm/squize.xpm                   |   22 +
 mgllab/xpm/stop.xpm                     |   23 +
 mgllab/xpm/style.xpm                    |   22 +
 mgllab/xpm/system-file-manager.xpm      |   44 +
 mgllab/xpm/tab-close.xpm                |   91 +
 mgllab/xpm/table.xpm                    |   24 +
 mgllab/xpm/text-csv.xpm                 |  112 +
 mgllab/xpm/text-field.xpm               |   25 +
 mgllab/xpm/text-plain.xpm               |  109 +
 mgllab/xpm/text-x-generic.xpm           |   43 +
 mgllab/xpm/text.xpm                     |   21 +
 mgllab/xpm/tiles.xpm                    |  132 +
 mgllab/xpm/tools-wizard.xpm             |   82 +
 mgllab/xpm/tran.xpm                     |   23 +
 mgllab/xpm/transform-crop.xpm           |  133 +
 mgllab/xpm/transform-move.xpm           |   86 +
 mgllab/xpm/transform-rotate.xpm         |   41 +
 mgllab/xpm/transform-scale.xpm          |   80 +
 mgllab/xpm/udav.xpm                     |  416 ++
 mgllab/xpm/unused/smth.xpm              |   22 +
 mgllab/xpm/unused/sum.xpm               |   21 +
 mgllab/xpm/unused/swap.xpm              |   23 +
 mgllab/xpm/up_1.xpm                     |   22 +
 mgllab/xpm/update.xpm                   |   21 +
 mgllab/xpm/vect.xpm                     |   60 +
 mgllab/xpm/view-filter.xpm              |   64 +
 mgllab/xpm/view-fullscreen.xpm          |   63 +
 mgllab/xpm/view-grid.xpm                |  124 +
 mgllab/xpm/view-group.xpm               |   51 +
 mgllab/xpm/view-refresh.xpm             |  116 +
 mgllab/xpm/weather-clear.xpm            |  101 +
 mgllab/xpm/weather-clear_old.xpm        |   98 +
 mgllab/xpm/weather-clouds.xpm           |  125 +
 mgllab/xpm/window.xpm                   |   29 +
 mgllab/xpm/wire.xpm                     |   21 +
 mgllab/xpm/zoom-draw.xpm                |  167 +
 mgllab/xpm/zoom-in.xpm                  |  124 +
 mgllab/xpm/zoom-original.xpm            |  117 +
 mgllab/xpm/zoom-out.xpm                 |  123 +
 mgllab/xpm/zoom_1.xpm                   |   22 +
 mgllab/xpm/zoom_in.xpm                  |  124 +
 mgllab/xpm/zoom_out.xpm                 |  130 +
 mgltex/CMakeLists.txt                   |   54 +
 mgltex/Recompilation_decision.eps       | 1940 +++++++++
 mgltex/Recompilation_decision.pdf       |  Bin 0 -> 77735 bytes
 mgltex/Recompilation_decision.svg       | 1711 ++++++++
 mgltex/mgltex.dtx                       | 3093 +++++++++++++++
 mgltex/mgltex.ins                       |   63 +
 mgltex/mgltex.pdf                       |  Bin 0 -> 546058 bytes
 mgltex/sample.tex                       |  276 ++
 src/CMakeLists.txt                      |   61 +
 src/addon.cpp                           |  261 ++
 src/axis.cpp                            | 1127 ++++++
 src/base.cpp                            | 1598 ++++++++
 src/base_cf.cpp                         |  318 ++
 src/canvas.cpp                          | 1208 ++++++
 src/canvas_cf.cpp                       |  518 +++
 src/complex.cpp                         | 1536 ++++++++
 src/complex_ex.cpp                      |  706 ++++
 src/complex_io.cpp                      |  946 +++++
 src/cont.cpp                            | 1653 ++++++++
 src/cont.hpp                            |   42 +
 src/crust.cpp                           |  775 ++++
 src/data.cpp                            | 2457 ++++++++++++
 src/data_ex.cpp                         | 1072 +++++
 src/data_gr.cpp                         |  131 +
 src/data_io.cpp                         | 1408 +++++++
 src/data_png.cpp                        |  247 ++
 src/def_font.cc                         | 1236 ++++++
 src/eval.cpp                            |  753 ++++
 src/evalc.cpp                           |  331 ++
 src/evalp.cpp                           | 1067 +++++
 src/exec_dat.cpp                        | 1617 ++++++++
 src/exec_gr.cpp                         | 1106 ++++++
 src/exec_prm.cpp                        |  617 +++
 src/exec_set.cpp                        |  762 ++++
 src/export.cpp                          |  645 +++
 src/export_2d.cpp                       |  743 ++++
 src/export_3d.cpp                       | 1327 +++++++
 src/fft.cpp                             | 1316 +++++++
 src/fit.cpp                             |  603 +++
 src/font.cpp                            |  994 +++++
 src/fractal.cpp                         |  860 ++++
 src/interp.hpp                          |  252 ++
 src/mpi.cpp                             |   50 +
 src/obj.cpp                             |  959 +++++
 src/opengl.cpp                          |  487 +++
 src/other.cpp                           |  415 ++
 src/parser.cpp                          | 1442 +++++++
 src/pde.cpp                             | 1500 +++++++
 src/pixel.cpp                           | 1490 +++++++
 src/pixel_gen.cpp                       |  573 +++
 src/pixel_pix.cpp                       |  398 ++
 src/plot.cpp                            | 2076 ++++++++++
 src/prc.cpp                             |  991 +++++
 src/prc/PRC.h                           |  516 +++
 src/prc/PRCbitStream.cc                 |  404 ++
 src/prc/PRCbitStream.h                  |   88 +
 src/prc/PRCdouble.cc                    | 2121 ++++++++++
 src/prc/PRCdouble.h                     |  140 +
 src/prc/oPRCFile.cc                     | 2461 ++++++++++++
 src/prc/oPRCFile.h                      |  850 ++++
 src/prc/writePRC.cc                     | 2097 ++++++++++
 src/prc/writePRC.h                      | 1649 ++++++++
 src/prim.cpp                            | 1264 ++++++
 src/s_hull/COPYING.txt                  |   49 +
 src/s_hull/s_hull_pro.cpp               | 2159 ++++++++++
 src/s_hull/s_hull_pro.h                 |  149 +
 src/surf.cpp                            |  944 +++++
 src/tex_table.cc                        | 1951 +++++++++
 src/vect.cpp                            | 1515 +++++++
 src/volume.cpp                          |  681 ++++
 src/window.cpp                          |  253 ++
 texinfo/CMakeLists.txt                  |  219 ++
 texinfo/appendix_en.texi                |   69 +
 texinfo/appendix_ru.texi                |   67 +
 texinfo/classes.dia                     |  Bin 0 -> 4561 bytes
 texinfo/classes.pdf                     |  Bin 0 -> 12984 bytes
 texinfo/classes.png                     |  Bin 0 -> 138494 bytes
 texinfo/concept_en.texi                 |  396 ++
 texinfo/concept_ru.texi                 |  393 ++
 texinfo/copyright.texi                  |   11 +
 texinfo/core_en.texi                    | 3803 ++++++++++++++++++
 texinfo/core_ru.texi                    | 3772 ++++++++++++++++++
 texinfo/data_en.texi                    | 2104 ++++++++++
 texinfo/data_ru.texi                    | 2086 ++++++++++
 texinfo/datadvance.png                  |  Bin 0 -> 7077 bytes
 texinfo/doc_en.texi                     |  215 +
 texinfo/doc_ru.texi                     |  217 +
 texinfo/emblem_sm.png                   |  Bin 0 -> 8370 bytes
 texinfo/ex_mgl_en.texi                  | 3249 +++++++++++++++
 texinfo/ex_mgl_ru.texi                  | 3249 +++++++++++++++
 texinfo/example_en.texi                 | 4634 ++++++++++++++++++++++
 texinfo/example_ru.texi                 | 4619 ++++++++++++++++++++++
 texinfo/fdl.texi                        |  451 +++
 texinfo/filter.py                       |   25 +
 texinfo/fltk.png                        |  Bin 0 -> 49099 bytes
 texinfo/formats_en.texi                 |  141 +
 texinfo/formats_ru.texi                 |  141 +
 texinfo/glut.png                        |  Bin 0 -> 26774 bytes
 texinfo/gpl-2.0.texi                    |  389 ++
 texinfo/gpl-3.0.texi                    |  717 ++++
 texinfo/gplv3-127x51.png                |  Bin 0 -> 4429 bytes
 texinfo/index.html                      |   11 +
 texinfo/json.html                       |  124 +
 texinfo/lgplv3-147x51.png               |  Bin 0 -> 4224 bytes
 texinfo/mathgl.js                       |  557 +++
 texinfo/mathgl.texi                     |    0
 texinfo/mathgl_en.texi                  |  153 +
 texinfo/mathgl_ru.texi                  |  152 +
 texinfo/mgl.5                           |   18 +
 texinfo/mgl.cgi.1                       |   17 +
 texinfo/mgl_en.texi                     |  101 +
 texinfo/mgl_ru.texi                     |  103 +
 texinfo/mglconv.1                       |   48 +
 texinfo/mglview.1                       |   37 +
 texinfo/other_en.texi                   |  565 +++
 texinfo/other_ru.texi                   |  565 +++
 texinfo/overview_en.texi                |  248 ++
 texinfo/overview_ru.texi                |  252 ++
 texinfo/parse_en.texi                   |  505 +++
 texinfo/parse_ru.texi                   |  517 +++
 texinfo/qt.png                          |  Bin 0 -> 46186 bytes
 texinfo/symbols_en.texi                 |  800 ++++
 texinfo/symbols_ru.texi                 |  800 ++++
 texinfo/time.texi                       |  133 +
 texinfo/time_big.texi                   |  133 +
 texinfo/udav.1                          |   20 +
 texinfo/udav/udav_anim.png              |  Bin 0 -> 23136 bytes
 texinfo/udav/udav_arg.png               |  Bin 0 -> 18514 bytes
 texinfo/udav/udav_calc.png              |  Bin 0 -> 135630 bytes
 texinfo/udav/udav_cmd.png               |  Bin 0 -> 73819 bytes
 texinfo/udav/udav_data.png              |  Bin 0 -> 62476 bytes
 texinfo/udav/udav_gen_set.png           |  Bin 0 -> 37646 bytes
 texinfo/udav/udav_help.png              |  Bin 0 -> 104574 bytes
 texinfo/udav/udav_inplot.png            |  Bin 0 -> 50679 bytes
 texinfo/udav/udav_light.png             |  Bin 0 -> 49240 bytes
 texinfo/udav/udav_main.png              |  Bin 0 -> 138291 bytes
 texinfo/udav/udav_mask.png              |  Bin 0 -> 27025 bytes
 texinfo/udav/udav_opt.png               |  Bin 0 -> 21210 bytes
 texinfo/udav/udav_pen.png               |  Bin 0 -> 32751 bytes
 texinfo/udav/udav_prop.png              |  Bin 0 -> 55987 bytes
 texinfo/udav/udav_sch.png               |  Bin 0 -> 50834 bytes
 texinfo/udav/udav_txt.png               |  Bin 0 -> 32231 bytes
 texinfo/udav/udav_var.png               |  Bin 0 -> 17253 bytes
 texinfo/udav_en.texi                    |  146 +
 texinfo/udav_ru.texi                    |  146 +
 texinfo/version.texi.in                 |    4 +
 texinfo/version_hist.txt                |   53 +
 texinfo/web_en.texi                     |  412 ++
 texinfo/web_fr.texi                     |  614 +++
 texinfo/web_ru.texi                     |  412 ++
 texinfo/widget_en.texi                  |  723 ++++
 texinfo/widget_ru.texi                  |  727 ++++
 todo.txt                                |  114 +
 translations/mathgl_en.mo               |  Bin 0 -> 66 bytes
 translations/mathgl_es.mo               |  Bin 0 -> 9458 bytes
 translations/mathgl_ru.mo               |  Bin 0 -> 138490 bytes
 udav/CMakeLists.txt                     |   59 +
 udav/anim_dlg.cpp                       |  141 +
 udav/anim_dlg.h                         |   58 +
 udav/args_dlg.cpp                       |   89 +
 udav/args_dlg.h                         |   41 +
 udav/calc_dlg.cpp                       |  264 ++
 udav/calc_dlg.h                         |   87 +
 udav/dat_pnl.cpp                        |  840 ++++
 udav/dat_pnl.h                          |  104 +
 udav/data_dlg.cpp                       |  145 +
 udav/data_dlg.h                         |   55 +
 udav/files_dlg.cpp                      |   96 +
 udav/files_dlg.h                        |   50 +
 udav/find_dlg.cpp                       |   76 +
 udav/find_dlg.h                         |   58 +
 udav/help_pnl.cpp                       |   86 +
 udav/help_pnl.h                         |   46 +
 udav/hint_dlg.cpp                       |   85 +
 udav/hint_dlg.h                         |   50 +
 udav/info_dlg.cpp                       |   84 +
 udav/info_dlg.h                         |   58 +
 udav/mem_pnl.cpp                        |  188 +
 udav/mem_pnl.h                          |   49 +
 udav/mgl.xml.in                         |   10 +
 udav/newcmd_dlg.cpp                     |  393 ++
 udav/newcmd_dlg.h                       |   76 +
 udav/open_dlg.cpp                       |  179 +
 udav/open_dlg.h                         |   49 +
 udav/opt_dlg.cpp                        |  131 +
 udav/opt_dlg.h                          |   50 +
 udav/plot_pnl.cpp                       |  686 ++++
 udav/plot_pnl.h                         |  110 +
 udav/png/accessories-calculator.png     |  Bin 0 -> 606 bytes
 udav/png/alpha.png                      |  Bin 0 -> 762 bytes
 udav/png/arrow-down-double.png          |  Bin 0 -> 586 bytes
 udav/png/arrow-down.png                 |  Bin 0 -> 414 bytes
 udav/png/arrow-left-double.png          |  Bin 0 -> 580 bytes
 udav/png/arrow-left.png                 |  Bin 0 -> 413 bytes
 udav/png/arrow-right-double.png         |  Bin 0 -> 579 bytes
 udav/png/arrow-right.png                |  Bin 0 -> 438 bytes
 udav/png/arrow-up-double.png            |  Bin 0 -> 582 bytes
 udav/png/arrow-up.png                   |  Bin 0 -> 415 bytes
 udav/png/dialog-information.png         |  Bin 0 -> 863 bytes
 udav/png/document-export.png            |  Bin 0 -> 1000 bytes
 udav/png/document-import.png            |  Bin 0 -> 788 bytes
 udav/png/document-new.png               |  Bin 0 -> 516 bytes
 udav/png/document-open-folder.png       |  Bin 0 -> 659 bytes
 udav/png/document-open.png              |  Bin 0 -> 701 bytes
 udav/png/document-print.png             |  Bin 0 -> 566 bytes
 udav/png/document-properties.png        |  Bin 0 -> 464 bytes
 udav/png/document-revert.png            |  Bin 0 -> 737 bytes
 udav/png/document-save.png              |  Bin 0 -> 911 bytes
 udav/png/edit-clear.png                 |  Bin 0 -> 741 bytes
 udav/png/edit-copy.png                  |  Bin 0 -> 436 bytes
 udav/png/edit-cut.png                   |  Bin 0 -> 368 bytes
 udav/png/edit-delete.png                |  Bin 0 -> 783 bytes
 udav/png/edit-find.png                  |  Bin 0 -> 559 bytes
 udav/png/edit-paste.png                 |  Bin 0 -> 598 bytes
 udav/png/edit-redo.png                  |  Bin 0 -> 753 bytes
 udav/png/edit-select-all.png            |  Bin 0 -> 463 bytes
 udav/png/edit-undo.png                  |  Bin 0 -> 810 bytes
 udav/png/folder.png                     |  Bin 0 -> 652 bytes
 udav/png/format-indent-more.png         |  Bin 0 -> 427 bytes
 udav/png/format-stroke-color.png        |  Bin 0 -> 694 bytes
 udav/png/go-bottom.png                  |  Bin 0 -> 655 bytes
 udav/png/go-down.png                    |  Bin 0 -> 604 bytes
 udav/png/go-first-view.png              |  Bin 0 -> 790 bytes
 udav/png/go-first.png                   |  Bin 0 -> 619 bytes
 udav/png/go-jump-locationbar.png        |  Bin 0 -> 541 bytes
 udav/png/go-last-view.png               |  Bin 0 -> 793 bytes
 udav/png/go-last.png                    |  Bin 0 -> 623 bytes
 udav/png/go-next-view-page.png          |  Bin 0 -> 565 bytes
 udav/png/go-next-view.png               |  Bin 0 -> 495 bytes
 udav/png/go-next.png                    |  Bin 0 -> 667 bytes
 udav/png/go-previous-view-page.png      |  Bin 0 -> 557 bytes
 udav/png/go-previous-view.png           |  Bin 0 -> 484 bytes
 udav/png/go-previous.png                |  Bin 0 -> 588 bytes
 udav/png/go-top.png                     |  Bin 0 -> 591 bytes
 udav/png/go-up.png                      |  Bin 0 -> 630 bytes
 udav/png/help-contents.png              |  Bin 0 -> 612 bytes
 udav/png/help-faq.png                   |  Bin 0 -> 744 bytes
 udav/png/layer-visible-off.png          |  Bin 0 -> 666 bytes
 udav/png/layer-visible-on.png           |  Bin 0 -> 691 bytes
 udav/png/list-add.png                   |  Bin 0 -> 516 bytes
 udav/png/list-remove.png                |  Bin 0 -> 258 bytes
 udav/png/media-playback-start.png       |  Bin 0 -> 501 bytes
 udav/png/media-seek-backward.png        |  Bin 0 -> 505 bytes
 udav/png/media-seek-forward.png         |  Bin 0 -> 506 bytes
 udav/png/object-group.png               |  Bin 0 -> 244 bytes
 udav/png/object-order-lower.png         |  Bin 0 -> 441 bytes
 udav/png/object-order-raise.png         |  Bin 0 -> 435 bytes
 udav/png/object-rotate-down.png         |  Bin 0 -> 841 bytes
 udav/png/object-rotate-left.png         |  Bin 0 -> 648 bytes
 udav/png/object-rotate-right.png        |  Bin 0 -> 648 bytes
 udav/png/object-rotate-up.png           |  Bin 0 -> 843 bytes
 udav/png/object-ungroup.png             |  Bin 0 -> 275 bytes
 udav/png/office-chart-bar.png           |  Bin 0 -> 479 bytes
 udav/png/office-chart-line.png          |  Bin 0 -> 555 bytes
 udav/png/office-chart-scatter.png       |  Bin 0 -> 459 bytes
 udav/png/package-x-generic.png          |  Bin 0 -> 540 bytes
 udav/png/preferences-system.png         |  Bin 0 -> 728 bytes
 udav/png/process-stop.png               |  Bin 0 -> 618 bytes
 udav/png/system-file-manager.png        |  Bin 0 -> 378 bytes
 udav/png/tab-close.png                  |  Bin 0 -> 531 bytes
 udav/png/table.png                      |  Bin 0 -> 590 bytes
 udav/png/text-csv.png                   |  Bin 0 -> 547 bytes
 udav/png/text-field.png                 |  Bin 0 -> 263 bytes
 udav/png/text-plain.png                 |  Bin 0 -> 540 bytes
 udav/png/text-x-generic.png             |  Bin 0 -> 333 bytes
 udav/png/tools-wizard.png               |  Bin 0 -> 661 bytes
 udav/png/transform-crop.png             |  Bin 0 -> 721 bytes
 udav/png/transform-move.png             |  Bin 0 -> 766 bytes
 udav/png/transform-rotate.png           |  Bin 0 -> 409 bytes
 udav/png/transform-scale.png            |  Bin 0 -> 436 bytes
 udav/png/udav.png                       |  Bin 0 -> 4139 bytes
 udav/png/view-filter.png                |  Bin 0 -> 429 bytes
 udav/png/view-fullscreen.png            |  Bin 0 -> 329 bytes
 udav/png/view-grid.png                  |  Bin 0 -> 625 bytes
 udav/png/view-group.png                 |  Bin 0 -> 283 bytes
 udav/png/view-refresh.png               |  Bin 0 -> 912 bytes
 udav/png/weather-clear.png              |  Bin 0 -> 855 bytes
 udav/png/weather-clear_old.png          |  Bin 0 -> 682 bytes
 udav/png/weather-clouds.png             |  Bin 0 -> 775 bytes
 udav/png/zoom-draw.png                  |  Bin 0 -> 730 bytes
 udav/png/zoom-in.png                    |  Bin 0 -> 750 bytes
 udav/png/zoom-original.png              |  Bin 0 -> 744 bytes
 udav/png/zoom-out.png                   |  Bin 0 -> 778 bytes
 udav/prop_dlg.cpp                       |  293 ++
 udav/prop_dlg.h                         |   67 +
 udav/qmglsyntax.cpp                     |  121 +
 udav/qmglsyntax.h                       |   45 +
 udav/setup_dlg.cpp                      |  300 ++
 udav/setup_dlg.h                        |   60 +
 udav/style_dlg.cpp                      |  550 +++
 udav/style_dlg.h                        |   73 +
 udav/subplot_dlg.cpp                    |  358 ++
 udav/subplot_dlg.h                      |   68 +
 udav/text_pnl.cpp                       |  601 +++
 udav/text_pnl.h                         |  106 +
 udav/textedit.cpp                       |  326 ++
 udav/textedit.h                         |  100 +
 udav/tree_pnl.cpp                       |    0
 udav/tree_pnl.h                         |   57 +
 udav/udav.desktop                       |   13 +
 udav/udav.ico                           |  Bin 0 -> 16958 bytes
 udav/udav.png                           |  Bin 0 -> 4139 bytes
 udav/udav.qrc                           |   67 +
 udav/udav.rc                            |    1 +
 udav/udav_ru.qm                         |  Bin 0 -> 71709 bytes
 udav/udav_ru.ts                         | 4425 +++++++++++++++++++++
 udav/udav_wnd.cpp                       |  779 ++++
 udav/udav_wnd.h                         |  121 +
 utils/CMakeLists.txt                    |   54 +
 utils/make_forth.cpp                    |  168 +
 utils/make_pas.cpp                      |  511 +++
 utils/mgl_test.html                     |   14 +
 utils/mglcgi.cpp                        |   91 +
 utils/mglconv.cpp                       |  164 +
 utils/mglview.cpp                       |  131 +
 widgets/CMakeLists.txt                  |   29 +
 widgets/fltk.cpp                        | 1035 +++++
 widgets/glut.cpp                        |  277 ++
 widgets/image.cpp                       | 2877 ++++++++++++++
 widgets/image.h                         |   71 +
 widgets/qt.cpp                          | 1302 ++++++
 widgets/qt4/CMakeLists.txt              |   22 +
 widgets/qt5/CMakeLists.txt              |   21 +
 widgets/wx.cpp                          |  421 ++
 win32-install-deps/CMakeLists.txt       |   10 +
 win32-install-deps/install-deps.txt     |   36 +
 843 files changed, 205125 insertions(+)

diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..7c587e5
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,9 @@
+Author of MathGL:
+
+Alexey Balakin <balakin at appl.sci-nnov.ru>
+
+Some extensions was written by:
+Dmitriy Kulagin	- cmake script
+Mikhail Vidassov - U3D/PDF/OBJ export
+Mikhail Barg	- Pascal/Delphi interface
+Sergey Plis	- Forth interface
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..fbe2e6e
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,788 @@
+cmake_minimum_required(VERSION 2.8.12)
+if(POLICY CMP0043)
+    cmake_policy(SET CMP0043 OLD)
+endif()
+
+project( MathGL2 )
+
+set(mgl_clean_files )
+set(MGL_DEP_LIBS)
+add_definitions(-DMGL_SRC)
+
+if(NOT CMAKE_BUILD_TYPE)
+	set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are:
+		None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel." FORCE)
+endif(NOT CMAKE_BUILD_TYPE)
+
+set(CMAKE_VERBOSE_MAKEFILE ON)
+set(MathGL_VERSION_MAJOR 2)
+set(MathGL_VERSION_MINOR 4)
+set(MathGL_PATCH_VERSION 0)
+set(MathGL_VERSION ${MathGL_VERSION_MAJOR}.${MathGL_VERSION_MINOR}.${MathGL_PATCH_VERSION})
+set(MathGL_SOVERSION 7.5.0)
+
+set(MathGL_INSTALL_LIB_DIR "lib" CACHE PATH "Installation directory for libraries")
+set(MathGL_INSTALL_BIN_DIR "bin" CACHE PATH "Installation directory for executables")
+set(MathGL_INSTALL_INCLUDE_DIR "include" CACHE PATH "Installation directory for headers")
+if(WIN32 AND NOT CYGWIN)
+  set(DEF_INSTALL_CMAKE_DIR cmake)
+else()
+  set(DEF_INSTALL_CMAKE_DIR lib/cmake/mathgl)
+endif()
+set(MathGL_INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files")
+# Make relative paths absolute (needed later on)
+foreach(p LIB BIN INCLUDE CMAKE)
+  set(var MathGL_INSTALL_${p}_DIR)
+  if(NOT IS_ABSOLUTE "${${var}}")
+    set(${var} "${CMAKE_INSTALL_PREFIX}/${${var}}")
+  endif()
+endforeach()
+
+macro(mgl_po_src)
+    set(l_files )
+    foreach(src_file ${ARGN})
+        get_filename_component(fp ${src_file} ABSOLUTE)
+        file(RELATIVE_PATH rel ${CMAKE_SOURCE_DIR} ${fp})
+        list(APPEND l_files "${rel}")
+    endforeach(src_file ${ARGN})
+    set(po_files ${po_files} ${l_files} PARENT_SCOPE)
+endmacro(mgl_po_src)
+
+function(mgl_add_lib mgl_tmp_lib)
+       if(${mgl_tmp_lib} MATCHES mgl)
+               set(mgllib mgl)
+               set(mgllib2 mgl2)
+       else(${mgl_tmp_lib} MATCHES mgl)
+               set(mgllib mgl-${mgl_tmp_lib})
+               set(mgllib2 mgl2-${mgl_tmp_lib})
+       endif(${mgl_tmp_lib} MATCHES mgl)
+       set(mgl_src_lst ${ARGV})
+       list(REMOVE_AT mgl_src_lst 0)
+       add_library(${mgllib} SHARED ${mgl_src_lst})
+       add_library(${mgllib}-static STATIC ${mgl_src_lst})
+       set_target_properties(${mgllib} PROPERTIES SOVERSION ${MathGL_SOVERSION})
+       set_target_properties(${mgllib} PROPERTIES DEFINE_SYMBOL "mgl_EXPORTS")
+       set_target_properties(${mgllib} PROPERTIES C_VISIBILITY_PRESET hidden)
+       set_target_properties(${mgllib} PROPERTIES CXX_VISIBILITY_PRESET hidden)
+       set_target_properties(${mgllib} PROPERTIES VISIBILITY_INLINES_HIDDEN 1)
+       target_compile_definitions(${mgllib}-static PUBLIC MGL_STATIC_DEFINE)
+       if(MSVC)
+	   set(mgl_lib_static "-static")
+           if(CMAKE_BUILD_TYPE STREQUAL "Debug")
+               set(mgl_lib_end "d")
+	   else(CMAKE_BUILD_TYPE STREQUAL "Debug")
+               set(mgl_lib_end)
+           endif(CMAKE_BUILD_TYPE STREQUAL "Debug")
+       elseif(MSVC)
+	   set(mgl_lib_static)
+           set_target_properties(${mgllib} PROPERTIES CLEAN_DIRECT_OUTPUT 1)
+	   set_target_properties(${mgllib}-static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
+       endif(MSVC)
+       if(enable-mgl2)
+               set_target_properties(${mgllib} PROPERTIES OUTPUT_NAME "${mgllib2}${mgl_lib_end}")
+               set_target_properties(${mgllib}-static PROPERTIES OUTPUT_NAME "${mgllib2}${mgl_lib_static}${mgl_lib_end}")
+       else(enable-mgl2)
+               set_target_properties(${mgllib} PROPERTIES OUTPUT_NAME "${mgllib}${mgl_lib_end}")
+               set_target_properties(${mgllib}-static PROPERTIES OUTPUT_NAME "${mgllib}${mgl_lib_static}${mgl_lib_end}")
+       endif(enable-mgl2)
+
+       install(
+               TARGETS ${mgllib} ${mgllib}-static
+               EXPORT MathGLTargets
+               RUNTIME DESTINATION ${MathGL_INSTALL_BIN_DIR}
+               ARCHIVE DESTINATION ${MathGL_INSTALL_LIB_DIR}
+               LIBRARY DESTINATION ${MathGL_INSTALL_LIB_DIR}
+       )
+endfunction(mgl_add_lib mgl_tmp_lib)
+
+MACRO(MGL_DEPENDENT_OPTION option doc default depends1 force1 depends2 force2)
+  IF(${option}_ISSET MATCHES "^${option}_ISSET$")
+    SET(${option}_AVAILABLE 1)
+    IF(${force1})
+    FOREACH(d ${depends1})
+      STRING(REGEX REPLACE " +" ";" CMAKE_DEPENDENT_OPTION_DEP "${d}")
+      IF(${CMAKE_DEPENDENT_OPTION_DEP})
+      ELSE(${CMAKE_DEPENDENT_OPTION_DEP})
+          SET(${option}_AVAILABLE 0)
+          SET(depends1_AVAILABLE 1)
+      ENDIF(${CMAKE_DEPENDENT_OPTION_DEP})
+    ENDFOREACH(d)
+    ENDIF(${force1})
+    IF(${force2})
+    FOREACH(d ${depends2})
+      STRING(REGEX REPLACE " +" ";" CMAKE_DEPENDENT_OPTION_DEP "${d}")
+      IF(${CMAKE_DEPENDENT_OPTION_DEP})
+      ELSE(${CMAKE_DEPENDENT_OPTION_DEP})
+          SET(${option}_AVAILABLE 0)
+          SET(depends2_AVAILABLE 1)
+      ENDIF(${CMAKE_DEPENDENT_OPTION_DEP})
+    ENDFOREACH(d)
+    ENDIF(${force2})
+    IF(${option}_AVAILABLE)
+      OPTION(${option} "${doc}" "${default}")
+      SET(${option} "${${option}}" CACHE BOOL "${doc}" FORCE)
+    ELSE(${option}_AVAILABLE)
+      IF(${option} MATCHES "^${option}$")
+      ELSE(${option} MATCHES "^${option}$")
+        SET(${option} "${${option}}" CACHE INTERNAL "${doc}")
+      ENDIF(${option} MATCHES "^${option}$")
+        IF(depends1_AVAILABLE)
+          SET(${option} OFF)
+        ELSEIF(depends2_AVAILABLE)
+          SET(${option} ON)
+        ENDIF(depends1_AVAILABLE)
+    ENDIF(${option}_AVAILABLE)
+  ELSE(${option}_ISSET MATCHES "^${option}_ISSET$")
+    SET(${option} "${${option}_ISSET}")
+  ENDIF(${option}_ISSET MATCHES "^${option}_ISSET$")
+ENDMACRO(MGL_DEPENDENT_OPTION)
+include(CMakeDependentOption)
+
+string(TIMESTAMP MGL_NIGHT "%d.%m.%y")
+
+if(WIN32)
+	option(enable-dep-dll "Enable copying off all dependent dll libraries to the install directory" OFF)
+endif(WIN32)
+
+option(enable-double "Enable double precision in MathGL library" ON)
+option(enable-mpi "Enable mpi")
+option(enable-opengl "Enable OpenGL support" ON)
+option(enable-all-docs "Enable all documentation building")
+#option(enable-doc "Enable documentation building")
+option(enable-all "Enable all core features")
+option(enable-all-widgets "Enable all Widgets")
+option(enable-all-swig "Enable all SWIG based interfaces")
+option(enable-rvalue "Enable move constructor support (need C++11)" OFF)
+option(enable-pthread "Enable POSIX threads support" OFF)
+option(enable-pthr-widget "Enable POSIX threads for widgets" ON)
+option(enable-openmp "Enable OpenMP support" ON)
+
+if(enable-pthread AND enable-openmp)
+	message(SEND_ERROR "You can't enable POSIX threads and OpenMP at the same time!")
+endif(enable-pthread AND enable-openmp)
+
+option(enable-lgpl "Enable only LGPL part of MathGL")
+option(enable-mgl2 "Use names 'libmgl2-*' instead of 'libmgl-*'")
+option(enable-ltdl "Enable loading modules support")
+option(enable-doc-site "Enable HTML documentation for website")
+#CMAKE_DEPENDENT_OPTION(enable-doc-site "Enable HTML documentation for website" OFF "NOT enable-all-docs" ON)
+CMAKE_DEPENDENT_OPTION(enable-doc-html "Enable HTML documentation" OFF "NOT enable-all-docs" ON)
+CMAKE_DEPENDENT_OPTION(enable-doc-info "Enable INFO documentation" OFF "NOT enable-all-docs" ON)
+CMAKE_DEPENDENT_OPTION(enable-doc-pdf-ru "Enable Russian PDF documentation" OFF "NOT enable-all-docs" ON)
+CMAKE_DEPENDENT_OPTION(enable-doc-pdf-en "Enable English PDF documentation" OFF "NOT enable-all-docs" ON)
+#CMAKE_DEPENDENT_OPTION(enable-doc-prc "Enable PDF samples for HTML docs" OFF "NOT enable-all-docs" ON)
+#CMAKE_DEPENDENT_OPTION(enable-doc-json "Enable JSON samples for HTML docs" OFF "NOT enable-all-docs" ON)
+option(enable-texi2html "Use texi2html (obsolete package) instead of texi2any" OFF)
+CMAKE_DEPENDENT_OPTION(enable-mgltex "Enable installation of mgltex package (MGL scripts in LATEX document)" OFF "NOT enable-lgpl" OFF)
+
+CMAKE_DEPENDENT_OPTION(enable-zlib "Enable zlib support" ON "NOT enable-all" ON)
+CMAKE_DEPENDENT_OPTION(enable-png "Enable png support" ON "NOT enable-all" ON)
+CMAKE_DEPENDENT_OPTION(enable-jpeg "Enable jpeg support" OFF "NOT enable-all" ON)
+MGL_DEPENDENT_OPTION(enable-gsl "Enable gsl support" OFF "NOT enable-lgpl" ON "NOT enable-all" ON)
+MGL_DEPENDENT_OPTION(enable-hdf4 "Enable hdf4 support" OFF "NOT enable-lgpl" ON "NOT enable-all" ON)
+MGL_DEPENDENT_OPTION(enable-hdf5 "Enable hdf5 support" OFF "NOT enable-lgpl" ON "NOT enable-all" ON)
+CMAKE_DEPENDENT_OPTION(enable-pdf "Enable pdf support" OFF "NOT enable-all" ON)
+CMAKE_DEPENDENT_OPTION(enable-gif "Enable gif support" OFF "NOT enable-all" ON)
+CMAKE_DEPENDENT_OPTION(enable-glut "Enable glut support" OFF "NOT enable-all-widgets" ON)
+CMAKE_DEPENDENT_OPTION(enable-fltk "Enable fltk widget" OFF "NOT enable-all-widgets" ON)
+CMAKE_DEPENDENT_OPTION(enable-wx "Enable wxWidget widget" OFF "NOT enable-all-widgets" ON)
+CMAKE_DEPENDENT_OPTION(enable-qt4 "Enable Qt4 widget" OFF "NOT enable-all-widgets" ON)
+CMAKE_DEPENDENT_OPTION(enable-qt4asqt "Set Qt4 as default libmgl-qt" OFF "enable-qt4" OFF)
+CMAKE_DEPENDENT_OPTION(enable-qt5 "Enable Qt5 widget" OFF "NOT enable-all-widgets" ON)
+CMAKE_DEPENDENT_OPTION(enable-qt5asqt "Set Qt5 as default libmgl-qt" OFF "enable-qt5" OFF)
+
+# msvc fwprintf print char* for the specifier of "%s" format
+if(MSVC AND MSVC_VERSION GREATER 1899)
+	SET(CMAKE_CXX_FLAGS "/EHsc -D_CRT_STDIO_ISO_WIDE_SPECIFIERS ${CMAKE_CXX_FLAGS}")
+	SET(CMAKE_C_FLAGS "-D_CRT_STDIO_ISO_WIDE_SPECIFIERS ${CMAKE_C_FLAGS}")
+endif(MSVC AND MSVC_VERSION GREATER 1899)
+
+include(CheckCXXSourceCompiles)
+
+if(${CMAKE_SIZEOF_VOID_P} EQUAL 4)
+	set(CMAKE_REQUIRED_FLAGS -msse2 -mfpmath=sse)
+	CHECK_CXX_SOURCE_COMPILES("
+		int main(void){}" mgl_sse)
+	if(mgl_sse)
+		SET(CMAKE_CXX_FLAGS "-msse2 -mfpmath=sse ${CMAKE_CXX_FLAGS}")
+		SET(CMAKE_C_FLAGS "-msse2 -mfpmath=sse ${CMAKE_C_FLAGS}")
+	endif(mgl_sse)
+	unset(CMAKE_REQUIRED_FLAGS)
+endif(${CMAKE_SIZEOF_VOID_P} EQUAL 4)
+
+if(enable-qt4 OR enable-qt5)
+	set(QT_ENABLED ON)
+	if(enable-qt4asqt AND enable-qt5asqt)
+		message(SEND_ERROR "You cannot make Qt4 and Qt5 as qt at the same time.")
+	endif(enable-qt4asqt AND enable-qt5asqt)
+	if(enable-qt4 AND NOT enable-qt5)
+		set(enable-qt4asqt TRUE)
+	endif(enable-qt4 AND NOT enable-qt5)
+	if(enable-qt5 AND NOT enable-qt4)
+		set(enable-qt5asqt TRUE)
+	endif(enable-qt5 AND NOT enable-qt4)
+# 	if(NOT enable-opengl)
+# 		message(SEND_ERROR "You cannot build MathGL with Qt4 or Qt5 without OpenGL enabled.")
+# 	endif(NOT enable-opengl)
+endif(enable-qt4 OR enable-qt5)
+
+CMAKE_DEPENDENT_OPTION(enable-json-sample "Enable JSON sample (WebKit variant is the default)." ON "QT_ENABLED" OFF)
+CMAKE_DEPENDENT_OPTION(enable-json-sample-we "Enable JSON sample (WebEngine variant)." OFF "enable-json-sample" OFF)
+MGL_DEPENDENT_OPTION(enable-python "Enable python interface" OFF "NOT enable-lgpl" ON "NOT enable-all-swig" ON)
+MGL_DEPENDENT_OPTION(enable-lua "Enable Lua (v.5.1) interface" OFF "NOT enable-lgpl" ON "NOT enable-all-swig" ON)
+MGL_DEPENDENT_OPTION(enable-octave "Enable octave interface" OFF "NOT enable-lgpl" ON "NOT enable-all-swig" ON)
+MGL_DEPENDENT_OPTION(enable-octave-install "Octave interface will install for all users" ON "NOT enable-lgpl" ON "NOT enable-all-swig" ON)
+
+include_directories( ${MathGL2_SOURCE_DIR}/include ${MathGL2_BINARY_DIR}/include)
+set(MGL_INCLUDE_PATH "${CMAKE_INSTALL_PREFIX}/include/mgl2")
+set(MGL_CGI_PATH "${CMAKE_INSTALL_PREFIX}/share/mathgl" CACHE STRING "Set CGI install directory")
+set(MGL_DEF_FONT "STIX" CACHE STRING "Set default font name")
+
+if(NOT WIN32)
+#	set(MGL_CGI_PATH "${CMAKE_INSTALL_PREFIX}/share/mathgl")
+	set(MGL_DATA_PATH "${CMAKE_INSTALL_PREFIX}/share/mathgl")
+	set(MGL_DOC_PATH "${CMAKE_INSTALL_PREFIX}/share/doc/mathgl")
+	set(MGL_MAN_PATH "${CMAKE_INSTALL_PREFIX}/share/man")
+	set(MGL_INFO_PATH "${CMAKE_INSTALL_PREFIX}/share/info")
+	set(MGL_FONT_PATH "${MGL_DATA_PATH}/fonts")
+else(NOT WIN32)
+	set(MGL_FONT_PATH "${CMAKE_INSTALL_PREFIX}/fonts")
+endif(NOT WIN32)
+
+include(CheckFunctionExists)
+include(CMakePushCheckState)
+include(TestBigEndian)
+
+TEST_BIG_ENDIAN(WORDS_BIGENDIAN)
+if(WORDS_BIGENDIAN)
+	ADD_DEFINITIONS(-DWORDS_BIGENDIAN)
+endif(WORDS_BIGENDIAN)
+
+CHECK_FUNCTION_EXISTS(sin MGL_SIN)
+CHECK_FUNCTION_EXISTS(memrchr HAVE_MEMRCHR)
+if(NOT MGL_SIN)
+	cmake_push_check_state()
+	set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} m)
+	CHECK_FUNCTION_EXISTS(sin MGL_SIN_M)
+	cmake_pop_check_state()
+	if(MGL_SIN_M)
+		set(M_LIB m)
+	elseif(MGL_SIN_M)
+		message(SEND_ERROR "Math library not found")
+	endif(MGL_SIN_M)
+endif(NOT MGL_SIN)
+set(MGL_DEP_LIBS ${M_LIB} ${MGL_DEP_LIBS})
+
+if(HAVE_MEMRCHR)
+	ADD_DEFINITIONS(-DHAVE_MEMRCHR)
+endif(HAVE_MEMRCHR)
+
+include(CheckTypeSize)
+check_type_size("long" SIZEOF_LONG)
+
+#unset(MGL_HAVE_C99_COMPLEX)
+CHECK_CXX_SOURCE_COMPILES(
+"#include <complex>
+#include <complex.h>
+int main(int argc, char *args[])
+{std::complex<double> c(2.0, 1.0);
+double _Complex i=1.0i;
+double _Complex *a = reinterpret_cast<double _Complex *>(&c);
+std::complex<double> b(*a);return 0;}" MGL_HAVE_C99_COMPLEX)
+if(NOT MGL_HAVE_C99_COMPLEX)
+	set(MGL_HAVE_C99_COMPLEX 0)
+endif(NOT MGL_HAVE_C99_COMPLEX)
+
+#unset(MGL_HAVE_NAN_INF)
+CHECK_CXX_SOURCE_COMPILES(
+"#include <math.h>
+int main(){double a=NAN, b=INFINITY;return 0;}" MGL_HAVE_NAN_INF)
+if(NOT MGL_HAVE_NAN_INF)
+	set(MGL_HAVE_NAN_INF 0)
+endif(NOT MGL_HAVE_NAN_INF)
+
+#unset(MGL_HAVE_ATTRIBUTE)
+CHECK_CXX_SOURCE_COMPILES(
+"int __attribute__((pure)) test1() {return 0;}
+int __attribute__((const)) test2(int x) {return x*x;}
+int main(int argc, char* argv[]) {return 0;}" MGL_HAVE_ATTRIBUTE)
+if(NOT MGL_HAVE_ATTRIBUTE)
+	set(MGL_HAVE_ATTRIBUTE 0)
+endif(NOT MGL_HAVE_ATTRIBUTE)
+
+if(NOT MSVC AND enable-rvalue)
+	SET(CMAKE_CXX_FLAGS "-std=gnu++11 ${CMAKE_CXX_FLAGS}")
+	unset(MGL_HAVE_RVAL CACHE)
+	CHECK_CXX_SOURCE_COMPILES(
+	"struct test { test() {} test(test&& a){} };
+	int main() { test t;	return 0; }" MGL_HAVE_RVAL)
+	if(NOT MGL_HAVE_RVAL)
+		message(SEND_ERROR "Couldn't enable rvalue.")
+#		set(MGL_HAVE_RVAL 0)
+	endif(NOT MGL_HAVE_RVAL)
+else(NOT MSVC AND enable-rvalue)
+	set(MGL_HAVE_RVAL 0)
+endif(NOT MSVC AND enable-rvalue)
+
+
+
+CHECK_CXX_SOURCE_COMPILES(
+"#include <getopt.h>
+int main(int argc, char *args[]) {
+int ch = getopt(argc, args, \"1:2:3:4:5:6:7:8:9:hno:L:C:A:s:S:q:\"); return 0; }" MGL_HAVE_GETOPT)
+if(NOT MGL_HAVE_GETOPT)
+	include_directories(${MathGL2_SOURCE_DIR}/addons/getopt)
+	set(getopt_lib-static getopt-static)
+endif(NOT MGL_HAVE_GETOPT)
+
+if(enable-double)
+	set(MGL_USE_DOUBLE 1)
+else(enable-double)
+	set(MGL_USE_DOUBLE 0)
+endif(enable-double)
+
+if(enable-qt4 OR enable-qt5)
+	set(MGL_HAVE_QT 1)
+endif(enable-qt4 OR enable-qt5)
+
+if(enable-openmp)
+	find_package(OpenMP)
+	if(OPENMP_FOUND)
+		set(MGL_HAVE_OMP 1)
+		set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
+		set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
+	else(OPENMP_FOUND)
+		message(SEND_ERROR "Couldn't find OpenMP. You can enable POSIX threads instead.")
+		set(MGL_HAVE_OMP 0)
+	endif(OPENMP_FOUND)
+else(enable-openmp)
+	set(MGL_HAVE_OMP 0)
+endif(enable-openmp)
+
+if(enable-mpi)
+	set(MGL_HAVE_MPI 1)
+	find_package(MPI REQUIRED)
+	set(CMAKE_CXX_COMPILE_FLAGS ${CMAKE_CXX_COMPILE_FLAGS} ${MPI_COMPILE_FLAGS})
+	set(CMAKE_CXX_LINK_FLAGS ${CMAKE_CXX_LINK_FLAGS} ${MPI_LINK_FLAGS})
+	include_directories(${MPI_INCLUDE_PATH})
+else(enable-mpi)
+	set(MGL_HAVE_MPI 0)
+endif(enable-mpi)
+
+
+if(enable-pthr-widget OR enable-pthread)
+	if(enable-pthread)
+		set(MGL_HAVE_PTHREAD 1)
+	else(enable-pthread)
+		set(MGL_HAVE_PTHREAD 0)
+	endif(enable-pthread)
+	set(MGL_HAVE_PTHR_WIDGET 1)
+	include(FindThreads)
+	if(NOT CMAKE_USE_PTHREADS_INIT)
+		message(SEND_ERROR "Couldn't find POSIX threads library.")
+	endif(NOT CMAKE_USE_PTHREADS_INIT)
+	set(MGL_DEP_LIBS ${CMAKE_THREAD_LIBS_INIT} ${MGL_DEP_LIBS})
+else(enable-pthr-widget OR enable-pthread)
+	set(MGL_HAVE_PTHR_WIDGET 0)
+	set(MGL_HAVE_PTHREAD 0)
+endif(enable-pthr-widget OR enable-pthread)
+
+if(enable-gsl)
+	set(MGL_HAVE_GSL 1)
+	find_library(GSL_LIB gsl)
+	find_library(GSL_CBLAS_LIB gslcblas)
+	find_path(GSL_INCLUDE_DIR gsl/gsl_fft_complex.h)
+	if(NOT GSL_LIB OR NOT GSL_CBLAS_LIB OR NOT GSL_INCLUDE_DIR)
+		message(SEND_ERROR "${GSL_LIB}")
+		message(SEND_ERROR "${GSL_CBLAS_LIB}")
+		message(SEND_ERROR "${GSL_INCLUDE_DIR}")
+		message(SEND_ERROR "Couldn't find GSL libraries.")
+	else(NOT GSL_LIB OR NOT GSL_CBLAS_LIB OR NOT GSL_INCLUDE_DIR)
+		set(CMAKE_REQUIRED_INCLUDES ${GSL_INCLUDE_DIR})
+		set(CMAKE_REQUIRED_LIBRARIES ${GSL_LIB} ${GSL_CBLAS_LIB})
+		CHECK_CXX_SOURCE_COMPILES("#include <gsl/gsl_multifit_nlin.h>
+		int main(){gsl_multifit_fdfsolver *s=0;gsl_matrix *J = 0;
+		gsl_multifit_fdfsolver_jac(s, J);}" MGL_HAVE_GSL2)
+	endif(NOT GSL_LIB OR NOT GSL_CBLAS_LIB OR NOT GSL_INCLUDE_DIR)
+	set(MGL_DEP_LIBS ${GSL_LIB} ${GSL_CBLAS_LIB} ${MGL_DEP_LIBS})
+	include_directories(${GSL_INCLUDE_DIR})
+else(enable-gsl)
+	set(MGL_HAVE_GSL 0)
+endif(enable-gsl)
+
+if(enable-all OR enable-ltdl)
+	set(MGL_HAVE_LTDL 1)
+	find_library(LTDL_LIB ltdl)
+	find_path(LTDL_INCLUDE_DIR ltdl.h)
+	if(NOT LTDL_LIB OR NOT LTDL_INCLUDE_DIR)
+		message(SEND_ERROR "${LTDL_LIB}")
+		message(SEND_ERROR "${LTDL_INCLUDE_DIR}")
+		message(SEND_ERROR "Couldn't find LTDL library.")
+	endif(NOT LTDL_LIB OR NOT LTDL_INCLUDE_DIR)
+	set(MGL_DEP_LIBS ${LTDL_LIB} ${MGL_DEP_LIBS})
+	include_directories(${LTDL_INCLUDE_DIR})
+else(enable-all OR enable-ltdl)
+	set(MGL_HAVE_LTDL 0)
+endif(enable-all OR enable-ltdl)
+
+if(enable-hdf4)
+	set(MGL_HAVE_HDF4 1)
+	find_library(HDF4_LIB df)
+	find_library(HDF4MF_LIB mfhdf)
+	find_path(HDF4_INCLUDE_DIR hdf/mfhdf.h)
+	if(NOT HDF4_LIB OR NOT HDF4MF_LIB OR NOT HDF4_INCLUDE_DIR)
+		message(SEND_ERROR "${HDF4_LIB}")
+		message(SEND_ERROR "${HDF4MF_LIB}")
+		message(SEND_ERROR "${HDF4_INCLUDE_DIR}")
+		message(SEND_ERROR "Couldn't find HDF4 libraries.")
+	endif(NOT HDF4_LIB OR NOT HDF4MF_LIB OR NOT HDF4_INCLUDE_DIR)
+	set(MGL_DEP_LIBS ${HDF4MF_LIB} ${HDF4_LIB} ${MGL_DEP_LIBS})
+	include_directories(${HDF4_INCLUDE_DIR})
+else(enable-hdf4)
+	set(MGL_HAVE_HDF4 0)
+endif(enable-hdf4)
+
+if(enable-hdf5)
+	set(MGL_HAVE_HDF5 1)
+	find_package(HDF5)
+	if(NOT HDF5_FOUND)
+		find_package(HDF5 NAMES hdf5 COMPONENTS C shared static)
+		if(NOT HDF5_FOUND)
+			message(SEND_ERROR "Couldn't find HDF5 library.")
+		endif(NOT HDF5_FOUND)
+	endif(NOT HDF5_FOUND)
+	set(MGL_DEP_LIBS ${HDF5_LIBRARIES} ${HDF5_C_SHARED_LIBRARY} ${MGL_DEP_LIBS})
+	include_directories(${HDF5_INCLUDE_DIRS})
+else(enable-hdf5)
+	set(MGL_HAVE_HDF5 0)
+endif(enable-hdf5)
+
+if(enable-jpeg)
+	set(MGL_HAVE_JPEG 1)
+	include(FindJPEG)
+	if(NOT JPEG_FOUND)
+		message(SEND_ERROR "Couldn't find JPEG library.")
+	endif(NOT JPEG_FOUND)
+	set(MGL_DEP_LIBS ${JPEG_LIBRARIES} ${MGL_DEP_LIBS})
+	include_directories(${JPEG_INCLUDE_DIR})
+else(enable-jpeg)
+	set(MGL_HAVE_JPEG 0)
+endif(enable-jpeg)
+
+
+if(enable-zlib)
+	set(MGL_HAVE_ZLIB 1)
+	include(FindZLIB)
+	if(NOT ZLIB_FOUND)
+		message(SEND_ERROR "Couldn't find ZLib library.")
+	endif(NOT ZLIB_FOUND)
+	set(MGL_DEP_LIBS ${ZLIB_LIBRARIES} ${MGL_DEP_LIBS})
+	include_directories(${ZLIB_INCLUDE_DIR})
+else(enable-zlib)
+	set(MGL_HAVE_ZLIB 0)
+endif(enable-zlib)
+
+if(enable-png)
+	set(MGL_HAVE_PNG 1)
+	if(NOT MGL_HAVE_ZLIB)
+		message(SEND_ERROR "You have to enable ZLib if you plan to use PNG export.")
+	endif(NOT MGL_HAVE_ZLIB)
+	include(FindPNG)
+	if(NOT PNG_FOUND)
+		message(SEND_ERROR "Couldn't find PNG library.")
+	endif(NOT PNG_FOUND)
+	set(MGL_DEP_LIBS ${PNG_LIBRARIES} ${MGL_DEP_LIBS})
+	include_directories(${PNG_INCLUDE_DIR})
+else(enable-png)
+	set(MGL_HAVE_PNG 0)
+endif(enable-png)
+
+
+if(enable-pdf)
+	set(MGL_HAVE_PDF 1)
+	if(NOT MGL_HAVE_PNG)
+		message(SEND_ERROR "You have to enable PNG if you plan to use PDF export.")
+	endif(NOT MGL_HAVE_PNG)
+	find_library(HPDF_LIB hpdf)
+	if(NOT HPDF_LIB)
+		message(SEND_ERROR "Couldn't find libHaru or libhpdf.")
+	endif(NOT HPDF_LIB)
+	find_path(HPDF_INCLUDE_DIR hpdf_u3d.h)
+	if(NOT HPDF_INCLUDE_DIR)
+		message(SEND_ERROR "Couldn't find headers of 3d-enabled version of libhpdf.")
+	endif(NOT HPDF_INCLUDE_DIR)
+	include_directories(${HPDF_INCLUDE_DIR})
+	set(MGL_DEP_LIBS ${HPDF_LIB} ${MGL_DEP_LIBS})
+else(enable-pdf)
+	set(MGL_HAVE_PDF 0)
+endif(enable-pdf)
+
+if(enable-gif)
+	set(MGL_HAVE_GIF 1)
+	include(FindGIF)
+	if(NOT GIF_FOUND)
+		message(SEND_ERROR "Couldn't find GIF library.")
+	endif(NOT GIF_FOUND)
+	set(MGL_DEP_LIBS ${GIF_LIBRARIES} ${MGL_DEP_LIBS})
+	include_directories(${GIF_INCLUDE_DIR})
+else(enable-gif)
+	set(MGL_HAVE_GIF 0)
+endif(enable-gif)
+
+if(enable-opengl)
+	set(MGL_HAVE_OPENGL 1)
+	include(FindOpenGL)
+	if(NOT OPENGL_FOUND)
+		message(SEND_ERROR "Couldn't find OpenGL libraries.")
+	endif(NOT OPENGL_FOUND)
+	set(MGL_DEP_LIBS ${OPENGL_LIBRARIES} ${MGL_DEP_LIBS})
+	include_directories(${OPENGL_INCLUDE_DIR} )
+else(enable-opengl)
+	set(MGL_HAVE_OPENGL 0)
+endif(enable-opengl)
+
+if(enable-glut)
+	set(MGL_HAVE_GLUT 1)
+	if(NOT MGL_HAVE_OPENGL)
+		message(SEND_ERROR "You have to enable OpenGL if you plan to use GLUT.")
+	endif(NOT MGL_HAVE_OPENGL)
+	include(FindGLUT)
+	if(NOT GLUT_FOUND)
+		message(SEND_ERROR "Couldn't find GLUT library.")
+	endif(NOT GLUT_FOUND)
+else(enable-glut)
+	set(MGL_HAVE_GLUT 0)
+endif(enable-glut)
+
+if(enable-fltk)
+	set(MGL_HAVE_FLTK 1)
+	FIND_PACKAGE(FLTK)
+	if(NOT FLTK_FOUND)
+		message(SEND_ERROR "Couldn't find FLTK library.")
+	else(NOT FLTK_FOUND)
+		include_directories(${FLTK_INCLUDE_DIR})
+		CHECK_CXX_SOURCE_COMPILES(
+		"#include <FL/Fl_Copy_Surface.H>
+		int main(){return 0;}" MGL_HAVE_FL_COPY)
+	endif(NOT FLTK_FOUND)
+	if(NOT MGL_HAVE_FL_COPY)
+		set(MGL_HAVE_FL_COPY 0)
+	endif(NOT MGL_HAVE_FL_COPY)
+else(enable-fltk)
+	set(MGL_HAVE_FLTK 0)
+endif(enable-fltk)
+
+if(enable-wx)
+	set(MGL_HAVE_WX 1)
+	FIND_PACKAGE(wxWidgets COMPONENTS base core gl)
+	if(NOT wxWidgets_FOUND)
+		message(SEND_ERROR "Couldn't find wxWidgets library.")
+	endif(NOT wxWidgets_FOUND)
+else(enable-wx)
+	set(MGL_HAVE_WX 0)
+endif(enable-wx)
+
+
+find_program(findxgettext xgettext)
+find_program(findmsgmerge msgmerge)
+find_program(findmsgfmt msgfmt)
+find_program(findmsgcat msgcat)
+if(NOT findmsgfmt OR NOT findxgettext OR NOT findmsgmerge OR NOT findmsgcat )
+	message("Building of translation files was disabled, because xgettext, msgmerge, msgcat or msgfmt was not found. Current translations will be just coped.")
+	set(USE_GETTEXT 0)
+else(NOT findmsgfmt  OR NOT findxgettext OR NOT findmsgmerge OR NOT findmsgcat )
+	set(USE_GETTEXT 1)
+endif(NOT findmsgfmt  OR NOT findxgettext OR NOT findmsgmerge OR NOT findmsgcat )
+find_package(Intl)
+if(NOT Intl_FOUND)
+	set(MGL_USE_LIBINTL 0)
+	message("Gettext and translations was fully disabled, because libintl was not found.")
+else(NOT Intl_FOUND)
+	set(MGL_USE_LIBINTL 1)
+	set(MGL_DEP_LIBS ${Intl_LIBRARIES} ${MGL_DEP_LIBS})
+	include_directories(${Intl_INCLUDE_DIRS})
+endif(NOT Intl_FOUND)
+set(po_files )
+if(WIN32)
+	set(USE_GETTEXT 0)
+	set(MGL_USE_LIBINTL 0)
+endif(WIN32)
+
+if(enable-doc-info)
+	set(MGL_HAVE_DOC_INFO 1)
+	find_program(findmi makeinfo)
+	if(NOT findmi)
+		message(SEND_ERROR "Couldn't find makeinfo needed for documentation building.")
+	endif(NOT findmi)
+else(enable-doc-info)
+	set(MGL_HAVE_DOC_INFO 0)
+endif(enable-doc-info)
+
+if(enable-doc-html OR enable-doc-site)
+	if(enable-texi2html)
+		find_program(findth texi2html)
+		if(NOT findth)
+			message(SEND_ERROR "Couldn't find texi2html needed for documentation building.")
+		endif(NOT findth)
+	else(enable-texi2html)
+		find_program(findth texi2any)
+		if(NOT findth)
+			message(SEND_ERROR "Couldn't find texi2any needed for documentation building.")
+		endif(NOT findth)
+	endif(enable-texi2html)
+endif(enable-doc-html OR enable-doc-site)
+
+if(enable-texi2html)
+	set(site_en ${CMAKE_BINARY_DIR}/texinfo/doc_en/doc_en.html)
+	set(site_ru ${CMAKE_BINARY_DIR}/texinfo/doc_ru/doc_ru.html)
+	set(th_opt )
+else(enable-texi2html)
+	set(th_opt --html)
+	set(site_en ${CMAKE_BINARY_DIR}/texinfo/doc_en/index.html)
+	set(site_ru ${CMAKE_BINARY_DIR}/texinfo/doc_ru/index.html)
+endif(enable-texi2html)
+
+if(enable-doc-html)
+	set(MGL_HAVE_DOC_HTML 1)
+else(enable-doc-html)
+	set(MGL_HAVE_DOC_HTML 0)
+endif(enable-doc-html)
+
+if(enable-doc-site)
+	set(MGL_HAVE_DOC_SITE 1)
+else(enable-doc-site)
+	set(MGL_HAVE_DOC_SITE 0)
+endif(enable-doc-site)
+
+if(enable-doc-pdf-ru)
+	set(MGL_HAVE_DOC_PDF_RU 1)
+	find_program(findtp texi2pdf)
+	if(NOT findtp)
+		message(SEND_ERROR "Couldn't find texi2pdf needed for documentation building.")
+	endif(NOT findtp)
+else(enable-doc-pdf-ru)
+	set(MGL_HAVE_DOC_PDF_RU 0)
+endif(enable-doc-pdf-ru)
+
+if(enable-doc-pdf-en)
+	set(MGL_HAVE_DOC_PDF_EN 1)
+	find_program(findtp texi2pdf)
+	if(NOT findtp)
+		message(SEND_ERROR "Couldn't find texi2pdf needed for documentation building.")
+	endif(NOT findtp)
+else(enable-doc-pdf-en)
+	set(MGL_HAVE_DOC_PDF_EN 0)
+endif(enable-doc-pdf-en)
+
+if(enable-doc-site)
+	set(MGL_HAVE_DOC_JSON 1)
+else(enable-doc-site)
+	set(MGL_HAVE_DOC_JSON 0)
+endif(enable-doc-site)
+
+if(enable-doc-site)
+	set(MGL_HAVE_DOC_PRC 1)
+	if(NOT enable-pdf)
+		message(SEND_ERROR "You need to enable pdf support for MathGL.")
+	endif(NOT enable-pdf)
+else(enable-doc-site)
+	set(MGL_HAVE_DOC_PRC 0)
+endif(enable-doc-site)
+
+if(UNIX)
+	add_definitions(-DNO_COLOR_ARRAY)
+endif(UNIX)
+
+if(WIN32)
+	add_definitions(-DWIN32)
+endif(WIN32)
+
+if(NOT MGL_HAVE_GETOPT)
+	add_subdirectory( addons/getopt )
+endif(NOT MGL_HAVE_GETOPT)
+
+add_subdirectory( src )
+add_subdirectory( widgets )
+add_subdirectory( include )
+if(NOT enable-lgpl)
+	if(MGL_HAVE_QT)
+		add_subdirectory( udav )
+		if(enable-json-sample)
+			add_subdirectory( json )
+		endif(enable-json-sample)
+	endif(MGL_HAVE_QT)
+	if(enable-python OR enable-lua OR enable-octave)
+		add_subdirectory( lang )
+	endif(enable-python OR enable-lua OR enable-octave)
+add_subdirectory( utils )
+add_subdirectory( examples )
+if(NOT WIN32)
+	add_subdirectory( fonts )
+endif(NOT WIN32)
+add_subdirectory( mgllab )
+endif(NOT enable-lgpl)
+
+if(NOT MSVC AND NOT BORLAND)
+
+	if(MGL_HAVE_DOC_HTML OR MGL_HAVE_DOC_SITE OR MGL_HAVE_DOC_INFO OR MGL_HAVE_DOC_PDF_RU OR MGL_HAVE_DOC_PDF_EN )
+		add_subdirectory( texinfo )
+	endif(MGL_HAVE_DOC_HTML OR MGL_HAVE_DOC_SITE OR MGL_HAVE_DOC_INFO OR MGL_HAVE_DOC_PDF_RU OR MGL_HAVE_DOC_PDF_EN )
+
+endif(NOT MSVC AND NOT BORLAND)
+
+if(enable-mgltex)
+	add_subdirectory( mgltex )
+endif(enable-mgltex)
+
+if(WIN32)
+	install(FILES ${CMAKE_SOURCE_DIR}/FindMathGL2.cmake DESTINATION ${CMAKE_INSTALL_PREFIX} RENAME mathgl2-config.cmake)
+else(WIN32)
+	install(FILES ${CMAKE_SOURCE_DIR}/FindMathGL2.cmake DESTINATION ${MGL_LIB_INSTALL_DIR}/cmake/mathgl2/ RENAME mathgl2-config.cmake)
+endif(WIN32)
+
+#export(TARGETS MathGLTargets FILE "${PROJECT_BINARY_DIR}/MathGLTargets.cmake")
+#export(PACKAGE MathGL2)
+
+#configure_file(MathGLConfig.cmake.in "${MathGL2_BINARY_DIR}/MathGLConfig.cmake" @ONLY)
+#configure_file(MathGLConfigVersion.cmake.in "${MathGL2_BINARY_DIR}/MathGLConfigVersion.cmake" @ONLY)
+
+#install(FILES
+#	"${MathGL2_BINARY_DIR}/MathGLConfig.cmake"
+#	"${MathGL2_BINARY_DIR}/MathGLConfigVersion.cmake"
+#	DESTINATION "${MathGL_INSTALL_CMAKE_DIR}" COMPONENT dev)
+
+#install(EXPORT MathGLTargets DESTINATION "${MathGL_INSTALL_CMAKE_DIR}" COMPONENT dev)
+
+
+if(MGL_USE_LIBINTL)
+	if(USE_GETTEXT)
+		add_custom_target(mathgl.pot ALL
+			COMMAND ${findxgettext} -s --keyword=_ -C -c --package-name=MathGL2 --package-version=${MathGL_VERSION} -o ${MathGL2_BINARY_DIR}/mathgl.pot ${po_files}
+			WORKING_DIRECTORY ${MathGL2_SOURCE_DIR}/
+			DEPENDS ${po_files} )
+		set(mgl_clean_files mathgl.pot ${mgl_clean_files})
+		foreach(tl ru es en)
+			add_custom_target(mathgl_${tl}.po ALL
+				COMMAND ${findmsgmerge} -U mathgl_${tl}.po ${MathGL2_BINARY_DIR}/mathgl.pot
+				WORKING_DIRECTORY ${MathGL2_SOURCE_DIR}/
+				DEPENDS mathgl.pot )
+			add_custom_target(mathgl_${tl}.mo ALL
+				COMMAND ${findmsgfmt} -o mathgl_${tl}.mo ${MathGL2_SOURCE_DIR}/mathgl_${tl}.po
+				DEPENDS mathgl_${tl}.po)
+			install( FILES ${MathGL2_BINARY_DIR}/mathgl_${tl}.mo DESTINATION "${CMAKE_INSTALL_PREFIX}/share/locale/${tl}/LC_MESSAGES/" RENAME mathgl.mo )
+			set(mgl_clean_files mathgl_${tl}.mo ${mgl_clean_files})
+		endforeach(tl)
+	else(USE_GETTEXT)
+		foreach(tl ru es en)
+			install( FILES ${MathGL2_SOURCE_DIR}/translations/mathgl_${tl}.mo DESTINATION "${CMAKE_INSTALL_PREFIX}/share/locale/${tl}/LC_MESSAGES/" RENAME mathgl.mo )
+		endforeach(tl)
+	endif(USE_GETTEXT)
+endif(MGL_USE_LIBINTL)
+
+set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${mgl_clean_files}")
+
+# WARNING!!! DO NOT ADD ANYTHING AFTER THIS LINE!
+
+if(enable-dep-dll)
+	add_subdirectory ( win32-install-deps )
+endif(enable-dep-dll)
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  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
+them 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 prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  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.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey 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;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU 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 that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  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.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+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.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     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
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program 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, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU 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 Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/COPYING_LGPL b/COPYING_LGPL
new file mode 100644
index 0000000..65c5ca8
--- /dev/null
+++ b/COPYING_LGPL
@@ -0,0 +1,165 @@
+                   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser 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
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/ChangeLog.txt b/ChangeLog.txt
new file mode 100644
index 0000000..d1e4f79
--- /dev/null
+++ b/ChangeLog.txt
@@ -0,0 +1,482 @@
+2.4 Released 17 May 2017
+
+* Add mgllab executable, which is FLTK based version of UDAV. Most things mgllab do faster.
+* Add string manipulation in MGL language:
+	o 'str'[n] -- get string of only n-th symbol;
+	o 'str'+v -- add value v to the last character of the string;
+	o 'str',val || 'str',!val -- append numeric value to the string (as before).
+* Add time value to MGL language in format: "hh-mm-ss_DD.MM.YYYY" or "hh-mm-ss" or "DD.MM.YYYY".
+* Add 'iris' plot to show cross-dependencies of several data arrays.
+* Add 'flame2d' to draw flame fractals.
+* Add 'bbox' to set bounding box for 2D output.
+* Add 'section' to get part of data between specified values.
+* Add 'detect' to found curves along data maximums.
+* Add 'dilate' to extend the region of 1-th value.
+* Add 'erode' to narrow the region of 1-th value.
+* Add 'apde' to solve PDE equation in inhomogeneous nonlinear media with spatial dispersion.
+* Add 'symbol' to draw the glyphs defined by 'addsymbol'.
+* Add 'addsymbol' to declare user-defined symbol (or glyph), which can be used as markers for plot (with style '&') or drawn itself by 'symbol' command.
+* Add 'openhdf' to open all data arrays from HDF file.
+* Extend 'crop' to cut to optimal size for FFT (i.e. to closest of 2^n*3^m*5^l).
+* Add function mgl_data_max_first() and data suffixes .m[xyz][fl] to find first/last maximum along direction.
+* Add function mgl_datac_diff_par() to parametric derivative of complex data.
+* Add style 'F' for 'bars' and 'barh' to set fixed bar widths.
+* Add style 'a' for 'plot', 'tens', 'area' and 'region' to accurate drawing of data, which partially lie out of axis range.
+* Add style '#' for 'region' to draw wired plot.
+* Add possibility of manual shift in 'multiplot'.
+* Add parsing arguments of options for MGL commands.
+* MGL command 'correl' now can perform 2d and 3d correlations.
+* Option 'meshnum' now change the number of drawn markers for 'plot', 'tens', 'step, 'mark' and 'textmark'.
+* Function 'step' handle data with x.nx>y.nx similarly to 'bars'.
+* Extend 'tile' and 'tiles' by adding manual coloring and face orientation.
+* Add variant of MGL command 'copy' to copy data with "incorrect" names.
+* Improve tick labels drawing.
+* Improve time-ticks (add weeks) and add subticks to its.
+* Improve 'fplot' to handle several singularities.
+* Add LaTeX command \dfrac{}{}. This is full-sized version of \frac{}{}. Unfortunately, there is no support of nesting (i.e. \dfrac{\dfrac{}{}}{} not working). Contrary, \frac{}{} allow nesting.
+* Add mglODEc() -- ODE solver for complex variables.
+* Add cmplx(a,b)=a+i*b to the list of known functions in formula parsing
+* Update CMake find_package to find MathGL.
+* Increase line width for wired text.
+* Update documentation: add description of new commands, add hint @ref{Mixing bitmap and vector output}.
+* Add translation to Russian for most of labels and messages.
+* Name 'all' are reserved in MGL scripts now as synonym of -1.
+
+* INCOMPATIBLE: Replace libmgl-qt by libmgl-qt4 and libmgl-qt5 for resolving conflicts of simultaneously installed both Qt4 and Qt5.
+* Minor bugfixes.
+
+
+2.3.5.1 Released 20 June 2016
+
+* INCOMPATIBLE: library libmgl-qt is removed. You need to use libmgl-qt4 or libmgl-qt5 explicitly now.
+* Compatibility changes for latest MS VisualStudio.
+* Bugfixes.
+
+2.3.5 Released 16 May 2016
+
+* Greatly update mgltex (by Diego Sejas Viscarra)
+	o \MGL at codes: Bugfix: category code for tabulators is changed too
+	o \MGL at quality: 9 is accepted as quality value now
+	o \MGL at scale: Now accepts any positive value
+	o \MGL at test@switch: New command to verify and validate switching arguments
+	o \mglTeX: Add a small negative space in the logo, between the "mgl" and "TEX"
+	o \mglTeX: Declared now as robust command
+	o \mglcomments: Now accepts arguments 0 (equivalent to off) and 1 (equivalent to on), besides the usual off and on
+	o \mglgraphics: New command options: gray, mglscale, quality, variant
+	o \mglname: Now writes the MGL code line setsize 600 400 to the main script
+	o \mglplot: Added \bgroup and \egroup in order to keep changes private
+	o New command options: gray, mglscale, quality, variant
+	o \mglsettings: Added options gray and variant
+	o Now calls the \mglswitch and \mglcomments commands for the switch and comments options, respectively
+	o \mglswitch: Now accepts arguments 0 (equivalent to off) and 1 (equivalent to on), besides the usual off and on
+	o mglTeX now depends on the ifpdf package
+	o Change definition of \mglcommentname from MGL comment to mglTEX comment
+	o Introduce the concept of global, local and private settings in the documentation
+	o New commands: \mglgray (to activate/deactivate) gray-scale mode locally, and \mglvariant (to set variant of arguments in MGL scripts locally)
+	o New package option 9q for setting quality to 9 (for testing purposes of the author)
+	o New package options 0v, 1v, 2v to select variant of arguments in MGL scripts
+	o New package options gray, color to activate/deactivate gray-scale mode for graphics
+	o Remove the \MGL at setkeys command, since it isn’t needed as first thought
+	o Rename \MGL at document@scripts to \MGL at doc@scripts
+	o Rename \MGL at script@name to \MGL at script
+	o Rename command \MGL at graph@ext to \MGL at imgext
+	o Rename command \mglcommonscriptname to mglsetupscriptname
+	o Rename environment mglcommon to mglsetupscript (mglcommon is still available, but deprecated)
+	o Rename family MGL at keys as MGL at gr@keys for consistency
+	o Reorganize and update documentation
+	o Some minor bugfixes
+	o The MGL code line "setsize 600 400" is now automatically written to the main script in order for the scaling options and commands to work
+	o mgl: New environment options: gray, mglscale, quality, variant
+	o mglcode: New environment options: gray, mglscale, quality, variant
+* Add MGL command 'variant' to select proper variant of arguments (like "var1?var2?var3?...") in MGL commands.
+* Remove limitation of maximal number (was 1000) of arguments for MGL commands. This is actual for 'list' command.
+* Add mglWnd::Widget() for accessing widget which is used for drawing.
+* Add Gray() for producing gray-scaled image.
+* Add MGL command 'setsizescl' for scaling all further 'setsize'.
+* Add Shear() for shearing plot.
+* Add ShearPlot() for placing plots side-by-side with some shearing.
+* Add mglData::Limit() for limit maximal absolute value of data.
+* Add mglTridMat() for tridiagonal matrix algorithm.
+* Add MGL command 'diffract' for single step diffraction calculation.
+* Add 'ifsfile' for reading IFS fractal parameters from *.ifs file.
+* Add style '*' for 2d versions of Pipe() and Flow() to draw threads from points inside axis range.
+* Add "norm()" to the list of known functions
+* Compatibility changes for MS VisualStudio, MacOS, Win64.
+* Bugfix for legend export into EPS and SVG.
+* Bugfix for importing data from std::vector.
+* Improve Surf3*() drawing.
+* Force NAN if divided by 0 in formulas.
+* Option "-S" of mglconv now perform scaling in any cases
+
+
+2.3.4 Released 13 February 2016
+
+* Add mglData::Pulse() for determining pulse parameters.
+* Add mglData::ScanFile() for getting formated data from textual file.
+* Add mglData::SetList() for setting data from variable argument list of double values.
+* Add mglIFS2d() and mglIFS3d() for fractal generation using iterated function system (thanks to Diego Sejas Viscarra).
+* Add option to SetSize() for scaling only primitives but don't erase it.
+* Add Pmap() plot for Poincare map.
+* Add Lamerey() plot for Lamerey diagram.
+* Add Bifurcation() plot for Bifurcation diagram.
+* Add mglGraph::SetPenDelta() for changing size of semi-transparent area around lines, marks, glyphs, ...
+
+* Add MGL command 'echo' for printing the content of data.
+* Add MGL command 'print' -- like 'info' but print immediately in stdout.
+* Allow MGL command 'save' append textual strings to a file.
+* Add option to rewrite file in 'savehdf'.
+
+* Add callback functions to mglQt, mglFLTK, and extend mglDraw class for simpler drawing in parallel with calculation (see @ref{Draw and calculate}).
+
+* Force set focus for editor in UDAV.
+* Add line numbers to UDAV editor. Cyan number denote current line, red numbers denote lines with errors.
+* Disable mouse wheel for zooming in UDAV by default.
+
+* Update mgltex (thanks to Diego Sejas Viscarra).
+
+* INCOMPATIBLE: Scale internally d1,d2 arguments in Curve() to be exactly the same as Bezier curve (P0=p1, P1=d1+p1, P2=p2-d2, P3=p2).
+
+* Minor bugfixes and improvements.
+
+2.3.3 Released 01 June 2015
+
+* Add SurfCA() and Surf3CA() plots.
+* Add wavelet transforms.
+* Add AttachLight() for attaching light settings to inplots.
+* Add manual rotation angle for axis ticks (by "value" option).
+* Add mglDataS class which is similar to std::vector<double> one.
+* Add missing mglDataC functions.
+
+* Add style '%' for color scheme along 2 coordinates (as in Map()).
+* If tick template start with '&' then long integer is passed instead of double.
+* Add style 'V' for drawing text centered vertically.
+* Add style "dN" in Smooth() for averaging over (2*N+1)-th points.
+* Add TeX symbols "\quote", "--" and Cyrillic ones.
+
+* Add complex numbers in MGL -- any expression started with '!' will have complex value(s).
+* Add 'rkstep' command for Runge-Kutta step in MGL script.
+* Add functions 'min()', 'max()' to MGL parser and formula evaluation.
+* MGL command 'join' now can join arbitrary number of data arrays.
+* Command 'stop' is not required to be placed before 'func'.
+* Add warning about writing to temporary arrays in MGL scripts.
+* Names 'rnd','nan','inf' are reserved in MGL scripts now.
+
+* Add annotation for plot styles and options into header files.
+* Greatly improve the speed of formula parsing for MGL scripts
+* Update JS interface
+* Add binary font files for speeding up initialization and font loading
+* Exclude "pure" attribute for function due to compatibility reasons
+* Add mgl_set_size_scl() for additional scaling width and height of the image
+* Add options -S, -q for mglconv
+* Rearrange toolbuttons in UDAV.
+* Bugfix for Flow() and Pipe() functions
+* Other minor improvements, bugfixes and compatibility changes
+
+2.3.2 Released 2 February 2015
+
+* Update mgltex (thanks to Diego Sejas Viscarra)
+* Add reading files with complex numbers by 'read' command.
+* Parallelize reading textual data files.
+* Add 'i','j','k' variables for data filling.
+* Add 2-color style for candle and ohlc plot.
+* Add saving images in QMathGL even if corresponding format support is disabled.
+* Add cmake option MGL_DEF_FONT to change default font name or use built-in one (if MGL_DEF_FONT is empty).
+* Compatibility changes and bugfixes.
+
+2.3.1 Released 21 October 2014
+
+* Add MGL command 'load' for loading MGL commands from external DLL (or .so) module.
+* Add Logo() function to draw bitmap (logo), which is stretched along whole axis range
+* Add MGL command 'reset' which restore default settings and clear image (i.e. call DefaultPlotParam()).
+* Change y coordinate at x-z projection.
+* Improve projection of 'unrotatable' objects (like legend, title, ...).
+* Add projection (Ternary&8) which is the same as usual (Ternary&4) but don't print text on projections
+* Improve orientation of axis ticks and labels.
+* Add mglWnd::SetDrawFunc().
+* Add mgl_set_global_warn() and mgl_get_global_warn() for set/get messages of global scope.
+* Make copying private of mglGraph and derived.
+* Add virtual destructors.
+* Add some static functions for mglGraph.
+* Add option "-n" to mglconv to disable automatic saving of the image.
+* Add option "-s" to mglview and mglconv to run setup script before the main one.
+* Become compatible with giflib 5.1.
+* Add light scaling at MGLD import.
+* Add scaling of frames at Adjust().
+* Possible bugfix for 32bit gcc.
+* Update docs.
+
+
+2.3 Released 7 August 2014
+
+* Add background image, which allow in particular semi-transparent background color. Correspondingly add function Rasterize() for saving current image as background, and function LoadBackground() for loading background image from PNG or JPEG file.
+* Add primitives to draw polygon and angle arc.
+* Allow arbitrary factor for axis ticks (like, gr->SetTicks('x',M_PI,0,NAN,"\\pi");).
+* Add function AddTick() for adding manual tick to existed ones.
+* Add new styles and symbols:
+  - arrow style 'X';
+  - color gradient (color scheme) of glyphs in text;
+  - manual dash style, like "{df090}";
+  - manual mask style, like "{s00ff00182424f800}";
+  - Add styles 'fFE0123456789+-' for printing numbers in functions Axis(), Colorbar(), Table() and Label();
+  - style '!' to disable ticks tuning in Axis() and Colorbar();
+  - special symbol '\b' which will be ignored at printing;
+  - calligraphic TeX symbols, like \calB, \calE, \calF, \calH, \calI, \calL, \calM, \calR, \ell, \scrg, \scro.
+
+* Add ODE solving functions for textual formulas
+* Add function for global cubic spline interpolation, and function to refill using global spline.
+* Add functions "random(dat)" and "gamma_inc(a,x)" to the list of known functions for formula parsing
+* Add 'inf' variable to the MGL and formula parsing
+* Allow reading JPEG files for mglData::Import().
+* Function mgl_data_subdata_ext() handle NULL argument(s). Add variants of SubData() with 1 and 2 arguments.
+* Warning messages and information are printed to stderr until call of mgl_suppress_warn(true) will disable it.
+* Add function mgl_check_version() and MGL command 'version' to check if MathGL version is valid.
+* Add move constructor(s) if compiler support C++11 rvalues.
+
+* Changes in algorithms:
+  - Greatly increase speed of formula parsing (i.e. of functions mglData::Modify(), mglData::Fill() and similar), and speeding up many other places;
+  - Improve algorithm for contours drawing and filling, taking special attention to quasi-random data.
+  - Spline() now use 5-th order polynomials to keep continuity of 2nd derivative too.
+  - Add function attributes 'pure' or 'const', which potentially can speed up drawing.
+  - Use spline instead of linear interpolation in functions Flow() and Pipe().
+  - Adjust columnplot and gridplot positions for non-zero distance between the inplots.
+  - Improve colorbar labels drawing at SetRotatedText(false)
+  - Choose new scales for perspective.
+  - Allow 'negative' angles for text rotation
+  - Use new s-hull version for triangulation.
+* Make function mgl_get_curvs() to be exported. This function is used internally to connect line segments to a set of curves (in particular, for contour lines).
+* Add ViewAsRotate() function which handle arguments of View() by the same way as Rotate() function, i.e View(tetx,tetz,tety) <=> ViewAsRotate(-tetz,-tetx,-tety)
+* Function mglWindow::Adjust() for Quality&4==0 now show image in widgets even if draw function is absent (i.e. =NULL).
+
+* improvements in UDAV:
+  - Rearrange tool buttons;
+  - Add features for manual dashing and manual mask in Style dialog;
+  - Add dialog for new dialog for new inplots (including subplot, multiplot, columnplot, stickplot, gridplot);
+  - Add option to use dots plot at image refreshing (for faster rotation etc);
+  - Add new primitives (arc,polygon,rotated text) as mouse handled ones;
+  - Add close button to data tabs;
+  - Add button to stop script drawing  and stop() slot for QMathGL;
+  - Allow to delete/hide/unhide selected plot;
+  - Allow to move selected plot between inplots;
+  - Improve NewCommand dialog -- now it replace the script command if user change arguments only;
+  - MGL commands 'perspective' and 'fog' now work correctly in UDAV;
+  - Update UDAV icons to use Oxygen ones.
+
+2.2.2.1 Released 19 March 2014
+
+* Compatibility changes for MS VisualStudio 2010 and early.
+* Function SetRange(v1,v2) ignore NAN values now.
+* Add enable-json-sample for building json-samples on demand only.
+* Update docs.
+
+
+2.2.2 Released 10 March 2014
+
+* Add mgl_region_3d() to draw region (or ribbon) between 2 curves. Correspondingly extend mglGraph::Region() function and MGL command 'region'.
+* Allow LGPL for MathGL widgets.
+* Improve export to TeX.
+* Add missing functions to Fortran interface.
+* Bugfix for legend with enabled lighting.
+* Minor bugfixes and memory leaks.
+
+
+2.2.1 Released 22 January 2014
+
+* Add Qt5 support.
+* Add Pascal interface.
+* Improve JavaScript interface.
+* Add function AddRange(char dir, mreal v1, mreal v2) and extend corresponding MGL commands '[xyzc]range'.
+* Add 'hypot' function for known functions in formula parsing.
+* Add style '~' to disable colorbar or axis labels. NOTE, axis style '_' is obsolete and should be replaced by '~'.
+* Change Aspect() if Ax=NAN. Now, Ay and Az set the ratio to optimal aspect (not exact value as previously).
+* Disable changes by View(),Zoom(),Perspective() for position of Title(), Legend(), Colorbar().
+* Partial support of perspective in CalcXYZ().
+* Speed up PDE solving.
+* Add complex versions of PDE, QO2d, QO3d.
+* Correct filled background for Box() in curved coordinates.
+* Allow nx=1 for Stem and Error.
+* Bugfix for drawing single axis.
+* Bugfix for missing options parsing for some of MGL commands.
+* Bugfix for .pmin suffix in MGL. Add mglData::MaximalNeg() and mglData::MinimalPos() functions. Add .nmin and .nmax suffixes.
+* Bugfix for colorbar labels.
+* Force using python 2.7 by default due to bug in Ubuntu. Debian sid works well with python 3.* too.
+* Minor bugfixes and memory leaks.
+
+
+2.2 Released 11 November 2013
+
+* Add OpenMP calls mostly everywhere (can work as replacement of pthreads - a bit faster since more loops is parallelized).
+* Greatly speed up consequent FFT and Hankel transforms. Add mgl_clear_fft() function for manual clearing of saved FFT/Hankel data.
+* Add OHLC() plot for drawing Open-High-Low-Close diagram
+* Add wxMathGL widget.
+* Add interface for Lua v.5.1.
+* Add mask for face drawing if one of symbols "-+=;oOsS~<>jdD*^" is specified in color scheme. This work only for export in bitmap images.
+* Add Quality=8 for dots drawing (extremely fast).
+* Add styles '4','6','8' for Cone() and Cones() to produce square, hex-, octo-prism.
+* Add style 't' for Cones() to produce tubes (cylinders).
+* Add style '^' for Legend() to left/right align legend if its coordinates are right/left from the center
+* Add style '<', '^', '>' for aligning/centering boxes in Bars(), Barh(), BoxPlot(), Cones(). Also this plots become centered by default if nx sizes are the same for all data.
+* Add Dots() function which set independently both color and alpha of dots
+* Improve automatic axis position. Add style '^' for inverse automatic axis position.
+* Improve tick labeling. Add style TuneTicks&4 for zero filling of tick labels.
+* Add mglData::Refill() for filling by interpolation of parametrically dependent data
+* Add transparency for Area() and Region() plots.
+* Add mgl_clf_chr() function and extend 'clf' command.
+* Fourier now perform true inverse Fourier transform (instead of backward one).
+* Improve/change lighting from local sources. Add SetDiffuse() function.
+* C functions now return NULL if HMDT data cannot be created for given input argument(s).
+* Enable line width for Mesh() and Fall() plots.
+* Replace +INF and -INF by NAN in textual formula output.
+* Add manual compression of JSON.
+* Define WORDS_BIGENDIAN and HAVE_MEMRCHR (thanks to Dinar Valeev).
+* Bugfix for cleaning unused points.
+* Fix 'setsize' command at UDAV starting.
+* Rewrite MGL parsing by using std::wstring for avoiding possible bugs of wcs*() functions.
+* Minor bugfixes.
+* Update docs.
+
+2.1.3.1 Released 8 May 2013
+
+* Compatibility changes for MS VS.
+* Bugfixes for cmake options enable-double=OFF, enable-zlib=OFF.
+* Enable mouse actions for Firefox in JS sample.
+
+2.1.3 Released 2 May 2013
+
+* Functions SinFFT, CosFFT, Hankel and so on, become multi-threaded
+* Use DFT instead of FFT if GSL support is disabled (much slow!).
+* Add Join() function for joining mglData arrays
+* Add Roots() function for root finding of nonlinear equation using provided guess(es)
+* Add mglExprC for parsing formula with complex numbers
+* Correctly read #QNAN values in data files
+* Speed up Dots() drawing
+* Add flag to disable tick labels at axis origin (see SetOriginTick())
+* Add MGL commands 'origintick', 'tickshift'
+* WriteJSON now use zlib if filename end at 'z' (like "test.jsonz")
+* Make separate libmgl-mpi
+* Add SetAutoRanges() function (duplicate corresponding options)
+* Add JSON sample usage via QtWebKit (thanks to DATADVANCE)
+* Bugfixes and memory leaks
+
+2.1.2 Released 28 January 2013
+
+* Exclude "local" functions from resulting library.
+* String in MGL script now can be concatenated with another string or data/numbers (like 'max(u)=',u.max,' a.u.').
+* Bugfix for colors in 3D PDF.
+* Bugfix for drawing in MPI mode.
+* If Aspect() function have NAN argument(s) then it try to select optimal aspect ratio.
+* Option 'size' in Legend() now change only text size (not mark size).
+* Option 'meshnum' now influence on Boxs() and Belt() functions
+* Adjust marks drawing (line width and dots).
+* Minor improvements and bugfixes.
+
+2.1.1 Released 24 December 2012
+
+* Bugfix for SetRange(val,val) function
+* Exclude export MGL to CPP
+* MGL parsing now produce errors for any wrong list of arguments
+* Add help message to mgl.cgi
+* Improve text rotation at View()
+* Make compatible with GIF library v.5.0.
+* Bugfix for making MPI interface.
+* Bugfix for running in Win32 mode.
+* Update docs and MGL samples
+
+2.1 Released 13 December 2012
+
+* Add class mglDataC for complex data arrays.
+* Add mglData::Solve() for finding x-value where dat(x)=val.
+* Add mglData::Clean() for removing rows with duplicate values for given column.
+* Add Vect3() plot for drawing vectors on slice of 3d vector field.
+* Add Table() function for drawing table with data values.
+* Add ZoomAxis() for zooming/shifting axis range as whole.
+* Add WriteJSON() function for exporting in JSON format suitable for later drawing by JavaScript
+* Add JavaScript code for visualizing JSON data.
+* Add mgl.cgi tool which return PNG image for CGI request in form of MGL script.
+* Add MGL commands 'errbox', 'face'
+
+* Color can be specified as its RGB[A] values, i.e. like "{xFFFFFF}" or "{xFFFFFFFF}".
+* Color in color scheme  may have position in range [0,1]. Format is {CN,pos} or {xFFFFFF,pos}.
+* Now pen width for marks is proportional to pen width of line multiplied by size of marks.
+* Now you can use different font-faces in the plot simultaneously.
+* Now Legend() automatically use several columns if it contain too many legend entries.
+* Add style '-' for legend for drawing them horizontally.
+* Vectors is drawn now even if only starting or ending points are placed in bounding box.
+* Strongly rewrite the algorithm of vector field plotting.
+
+* Grid lines for NAN origin values are always located at far-away edges.
+* Try correctly place axis and tick labels even for axis with inverse range (i.e. for v2<v1).
+  Note, it work well for 2D axis. One should use Aspect() with negative values to do it correctly in general case.
+* Axis style 'XYZ' draw corresponding axis with ticks labels from other side of axis. This also influence on followng Label() calls.
+* Text is drawn for initially invisible axis (like z-axis) too.
+
+* Add functions GetFrame(), AddFrame() for replacing or adding data from given frame. Work if MGL_VECT_FRAME is set on (by default is on).
+* Frames now save 3D information if MGL_VECT_FRAME is set (by default).
+* CalcXYZ() function now use data from z-buffer for better determining {x,y,z} coordinates.
+
+* Add dialog for data arguments in "New command" dialog of UDAV.
+* Value of arguments are saved while the kind of command is changed in "New command" dialog of UDAV.
+* Extend classification of commands in "New command" dialog of UDAV and make it automatic.
+* Mouse position at an object click now is displayed on the image itself.
+* Add zoom in/out by mouse wheel.
+* Add zoom in/out of axis range by mouse wheel, and shift of axis range by middle button.
+* Text editor in UDAV now highlight current line.
+* Completer can be switched off correctly now.
+* Multi-line strings (i.e. separated by "\" symbol) are highlighted correctly now.
+* Add option to enable/disable selected plot in UDAV.
+* Rearrange hot-keys in UDAV and in QMathGL.
+
+* Make code compilable by Borland compiler too.
+* Improve output in OpenGL mode.
+* Add fog at export in EPS/SVG formats.
+* Add mglParse::AllowFileIO() for enable/disable I/O commands in MGL scripts.
+
+* Export functions now can write in stdout if file name is "-".
+* Picture drawing now use multi-threading for each stage.
+
+* Functions mglData::Spline*, mglData::Linear* now can return gradient at the point.
+* mglFourier now make true inverse transform
+
+* Add annotation for all pure C functions.
+* Update list of built-in glyphs
+* Update samples
+* Update documentation
+* Different bugfixes
+
+* INCOMPATIBLE CHANGES in the arguments of functions: mgl_axis, mgl_axis_grid, mgl_label, mgl_labelw, mgl_legend_pos, mgl_legend; and in functions for MGL parsing.
+* MINOR INCOMPATIBLE: plotting functions now use double argument always.
+
+2.0.3 Released 27 July 2012
+
+* Make code compilable by compilers GNU/MinGW GCC, Clang, MS VisualStudio
+* Add mglTriangulation() using s_hull_pro algorithm
+* Add mglData::Grid() and mglGraph::DataGrid() for filling regular data by values of triangulated surface
+* Add cmake options 'enable-png' and 'enable-zlib'
+* Add SetTimeUTC() for using UTC time instead of local one
+* Add SetTickShift() for additional shift of tick labels
+* Add mglGraph::MPI_Send() and mglGraph::MPI_Recv()
+* Vector plots now draw vector at edges, which are directed out of bounding box
+* Add gap between 1d plots for avoiding possible undetermined overlapping.
+* Add parallel build for documentation
+* Bugfixes for memory leaks and uninitialized variables
+* Bugfix for setting text size
+* Bugfix for handling NAN color value
+* Bugfix for missing lines in export to EPS/SVG
+
+2.0.2 Released 24 May 2012
+
+* Add 'U' style for Axis() which disable ticks rotation.
+* Bugfix for enable-opengl option.
+* Bugfix for lighting.
+
+2.0.1 Released 23 May 2012
+
+* Improve speed of drawing
+* Add reading 3d data files using mglData::ReadMat()
+* Exclude unnecessary dependencies/inclusions
+* Improve build system
+	- Add multithreading
+	- Add install for Octave
+	- Separate enable-doc option from enable-all
+* Minor bugfixes
+
+2.0 Released 12 April 2012
diff --git a/FindMathGL2.cmake b/FindMathGL2.cmake
new file mode 100644
index 0000000..2003379
--- /dev/null
+++ b/FindMathGL2.cmake
@@ -0,0 +1,148 @@
+# - FindMathGL2.cmake
+# This module can be used to find MathGL v.2.* and several of its optional components.
+#
+# You can specify one or more component as you call this find module.
+# Possible components are: FLTK, GLUT, Qt, WX.
+#
+# The following variables will be defined for your use:
+#
+#  MATHGL2_FOUND           = MathGL v.2 and all specified components found
+#  MATHGL2_INCLUDE_DIRS    = The MathGL v.2 include directories
+#  MATHGL2_LIBRARIES       = The libraries to link against to use MathGL v.2
+#                           and all specified components
+#  MATHGL2_VERSION_STRING  = A human-readable version of the MathGL v.2 (e.g. 2.1)
+#  MATHGL2_XXX_FOUND       = Component XXX found (replace XXX with uppercased
+#                           component name -- for example, QT or FLTK)
+#
+# The minimum required version and needed components can be specified using
+# the standard find_package()-syntax, here are some examples:
+#  find_package(MathGL2 REQUIRED)				- v.2.* (no interfaces), required
+#  find_package(MathGL2 REQUIRED Qt)		- v.2.1 + Qt interface, required
+#  find_package(MathGL2 2.1 REQUIRED)			- v.2.1 (no interfaces), required
+#  find_package(MathGL2 COMPONENTS Qt WX)	- v.2.0 + Qt and WX interfaces, optional
+#
+# Note, some cmake builds require to write "COMPONENTS" always, like
+#  find_package(MathGL2 REQUIRED COMPONENTS Qt)	- v.2.* + Qt interface, required
+#
+# Typical usage could be something like this:
+#   find_package(MathGL REQUIRED FLTK)
+#   include_directories(${MATHGL2_INCLUDE_DIRS})
+#   add_executable(myexe main.cpp)
+#   target_link_libraries(myexe ${MATHGL2_LIBRARIES} ${MATHGL2_FLTK_LIBRARIES})
+#
+
+#=============================================================================
+# Copyright (c) 2011 Denis Pesotsky <denis at kde.ru>, 2014 Alexey Balakin <mathgl.abalakin at gmail.com>
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file COPYING-CMAKE-MODULES for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+
+FIND_PATH(MATHGL2_INCLUDE_DIR
+		NAMES mgl2/mgl.h
+		DOC "The MathGL2 v.2.* include directory")
+FIND_LIBRARY(MATHGL2_LIBRARY
+		NAMES mgl
+		PATHS ${MATHGL2_LIBRARY_DIR}
+		DOC "The MathGL v.2.* include directory")
+
+GET_FILENAME_COMPONENT(MATHGL2_LIBRARY_DIR ${MATHGL2_LIBRARY} PATH)
+
+SET(MATHGL2_LIBRARIES ${MATHGL2_LIBRARY})
+SET(MATHGL2_INCLUDE_DIRS ${MATHGL2_INCLUDE_DIR})
+
+IF(MATHGL2_INCLUDE_DIR)
+	SET(_CONFIG_FILE_PATH "${MATHGL2_INCLUDE_DIR}/mgl2/define.h")
+	SET(_VERSION_ERR "Cannot determine MathGL v.2.* version")
+	IF(EXISTS "${_CONFIG_FILE_PATH}")
+		FILE(STRINGS "${_CONFIG_FILE_PATH}"
+			MATHGL2_VERSION_STRING REGEX "^#define MGL_VER2.*$")
+		IF(MATHGL2_VERSION_STRING)
+			STRING(REGEX
+				REPLACE "#define MGL_VER2" ""
+				MATHGL2_VERSION_STRING ${MATHGL2_VERSION_STRING})
+			STRING(REGEX
+				REPLACE "//.*" ""
+				MATHGL2_VERSION_STRING ${MATHGL2_VERSION_STRING})
+			STRING(STRIP ${MATHGL2_VERSION_STRING} MATHGL2_VERSION_STRING)
+			SET(MATHGL2_VERSION_STRING 2.${MATHGL2_VERSION_STRING})
+#			MESSAGE(STATUS "Find MathGL version -- ${MATHGL2_VERSION_STRING}")
+		ELSE()
+			SET(_ERR_MESSAGE "${_VERSION_ERR}: ${_CONFIG_FILE_PATH} parse error")
+		ENDIF()
+	ELSE()
+		SET(_ERR_MESSAGE "${_VERSION_ERR}: ${_CONFIG_FILE_PATH} not found")
+	ENDIF()
+	IF(_ERR_MESSAGE)
+		UNSET(_ERR_MESSAGE)
+		SET(_CONFIG_FILE_PATH "${MATHGL2_INCLUDE_DIR}/mgl2/config.h")
+		SET(_VERSION_ERR "Cannot determine MathGL v.2.* version")
+		IF(EXISTS "${_CONFIG_FILE_PATH}")
+			FILE(STRINGS "${_CONFIG_FILE_PATH}"
+				MATHGL2_VERSION_STRING REGEX "^#define MGL_VER2.*$")
+			IF(MATHGL2_VERSION_STRING)
+				STRING(REGEX
+					REPLACE "#define MGL_VER2" ""
+					MATHGL2_VERSION_STRING ${MATHGL2_VERSION_STRING})
+				STRING(REGEX
+					REPLACE "//.*" ""
+					MATHGL2_VERSION_STRING ${MATHGL2_VERSION_STRING})
+				STRING(STRIP ${MATHGL2_VERSION_STRING} MATHGL2_VERSION_STRING)
+				SET(MATHGL2_VERSION_STRING 2.${MATHGL2_VERSION_STRING})
+	#			MESSAGE(STATUS "Find MathGL version -- ${MATHGL2_VERSION_STRING}")
+			ELSE()
+				SET(_ERR_MESSAGE "${_VERSION_ERR}: ${_CONFIG_FILE_PATH} parse error")
+			ENDIF()
+		ELSE()
+			SET(_ERR_MESSAGE "${_VERSION_ERR}: ${_CONFIG_FILE_PATH} not found")
+		ENDIF()
+	ENDIF(_ERR_MESSAGE)
+
+	if(_ERR_MESSAGE)
+		MESSAGE(FATAL_ERROR ${_ERR_MESSAGE})
+	endif(_ERR_MESSAGE)
+ENDIF()
+
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(MathGL2
+		REQUIRED_VARS MATHGL2_LIBRARY MATHGL2_INCLUDE_DIR
+		VERSION_VAR MATHGL2_VERSION_STRING)
+
+FOREACH(_Component ${MathGL2_FIND_COMPONENTS})
+	STRING(TOLOWER ${_Component} _component)
+	STRING(TOUPPER ${_Component} _COMPONENT)
+
+	SET(MATHGL2_${_Component}_FIND_REQUIRED ${MATHGL2_FIND_REQUIRED})
+	SET(MATHGL2_${_Component}_FIND_QUIETLY true)
+	if(${_component} STREQUAL "qt4" OR ${_component} STREQUAL "qt5")
+		FIND_PATH(MATHGL2_${_COMPONENT}_INCLUDE_DIR
+					NAMES mgl2/qt.h
+					PATHS ${MATHGL2_INCLUDE_DIR} NO_DEFAULT_PATH)
+	else(${_component} STREQUAL "qt4" OR ${_component} STREQUAL "qt5")
+		FIND_PATH(MATHGL2_${_COMPONENT}_INCLUDE_DIR
+				NAMES mgl2/${_component}.h
+				PATHS ${MATHGL2_INCLUDE_DIR} NO_DEFAULT_PATH)
+	endif(${_component} STREQUAL "qt4" OR ${_component} STREQUAL "qt5")
+	FIND_LIBRARY(MATHGL2_${_COMPONENT}_LIBRARY
+				NAMES mgl-${_component}
+				PATHS ${MATHGL2_LIBRARY_DIR} NO_DEFAULT_PATH)
+
+	FIND_PACKAGE_HANDLE_STANDARD_ARGS(MATHGL2_${_Component} DEFAULT_MSG
+										MATHGL2_${_COMPONENT}_LIBRARY
+										MATHGL2_${_COMPONENT}_INCLUDE_DIR)
+
+	IF(MATHGL2_${_COMPONENT}_FOUND)
+		SET(MATHGL2_LIBRARIES
+			${MATHGL2_LIBRARIES} ${MATHGL2_${_COMPONENT}_LIBRARY})
+		SET(MATHGL2_INCLUDE_DIRS
+			${MATHGL2_INCLUDE_DIRS} ${MATHGL2_${_COMPONENT}_INCLUDE_DIR})
+	ENDIF()
+
+	MARK_AS_ADVANCED(MATHGL2_${_COMPONENT}_INCLUDE_DIR MATHGL2_${_COMPONENT}_LIBRARY)
+ENDFOREACH()
+
+MARK_AS_ADVANCED(MATHGL2_INCLUDE_DIR MATHGL2_LIBRARY MATHGL2_VERSION_STRING)
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..9b5bef2
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,10 @@
+Installation is simple. Just execute:
+cmake .
+cmake .
+make
+sudo make install
+
+Sometimes you also need to execute:
+sudo ldconfig
+
+See MathGL documentation for more details.
diff --git a/MathGLConfig.cmake.in b/MathGLConfig.cmake.in
new file mode 100644
index 0000000..1231020
--- /dev/null
+++ b/MathGLConfig.cmake.in
@@ -0,0 +1,18 @@
+# - Config file for the MathGL package
+# It defines the following variables
+ 
+set(MathGL_INCLUDE_DIRS "@MathGL_INSTALL_INCLUDE_DIR@")
+set(MathGL_LIBRARIES_DIRS "@MathGL_INSTALL_LIB_DIR@")
+set(MathGL_HAVE_QT5 "@enable-qt5@")
+set(MathGL_HAVE_QT4 "@enable-qt4@")
+set(MathGL_HAVE_WX "@enable-wx@")
+set(MathGL_HAVE_FLTK "@enable-fltk@")
+set(MathGL_HAVE_GLUT "@enable-glut@")
+
+# Compute paths
+get_filename_component(MathGL_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
+
+# Our library dependencies (contains definitions for IMPORTED targets)
+if(NOT TARGET mgl AND NOT MathGL_BINARY_DIR)
+  include("${MathGL_CMAKE_DIR}/MathGLTargets.cmake")
+endif()
diff --git a/MathGLConfigVersion.cmake.in b/MathGLConfigVersion.cmake.in
new file mode 100644
index 0000000..ef66b05
--- /dev/null
+++ b/MathGLConfigVersion.cmake.in
@@ -0,0 +1,11 @@
+set(PACKAGE_VERSION "@MathGL_VERSION@")
+ 
+# Check whether the requested PACKAGE_FIND_VERSION is compatible
+if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
+  set(PACKAGE_VERSION_COMPATIBLE FALSE)
+else()
+  set(PACKAGE_VERSION_COMPATIBLE TRUE)
+  if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
+    set(PACKAGE_VERSION_EXACT TRUE)
+  endif()
+endif()
diff --git a/README b/README
new file mode 100644
index 0000000..38176b9
--- /dev/null
+++ b/README
@@ -0,0 +1,24 @@
+MathGL is a free library of fast C++ routines for the plotting of the data 
+varied in one or more dimensions. MathGL has more than 50 general types 
+of graphics for 1d, 2d and 3d data arrays. It can export graphics to bitmap 
+and vector (EPS, SVG etc) files. It has OpenGL interface and can be used from 
+console programs. It has functions for data handling and script MGL language 
+for simplification of data plotting. Also it has several types of transparency 
+and smoothed lightning, vector fonts and TeX-like symbol parsing, arbitrary 
+curvilinear coordinate system and many over useful things. Finally it is 
+platform independent and free (under GPL v.2.0 or later license).
+Installation instructions are provided in the manual (don't worry, it
+is straightforward).
+
+About LGPL and GPL licenses.
+Generally, MathGL is GPL library. However, you can use LGPL license for MathGL 
+core and widget libraries if you don't use SWIG-based interfaces and disable GSL 
+and HDF features. This can be done by using 'enable-lgpl' option at build time.
+However, I ask you to put the information of used MathGL version and link to 
+MathGL website into "About" section of yours program.
+
+CONTACTS
+--------
+MathGL was written by Alexey Balakin. You can contact me at 
+mathgl.abalakin at gmail.com . The latest version of MathGL can be found at
+the sourceforge.net page (http://mathgl.sourceforge.net).
diff --git a/README_V2 b/README_V2
new file mode 100644
index 0000000..b3ee778
--- /dev/null
+++ b/README_V2
@@ -0,0 +1,51 @@
+README for changes from v.1.*
+
+There are few key changes at end-user level.
+
+1. The structure of library is changed sufficiently.
+   There are 4 levels now:
+
+(a) Developer level (for people who want to improve library) contain
+    classes for base plotting functions:
+
+mglBase --> mglCanvas --> mglCanvasW  --> mglCanvasQT, mglCanvasFL
+               |
+               ---------> mglCanvasGL --> mglCanvasGLUT
+
+(b) C&Fortran interface for plotting and data handlinng functions
+
+(c) Unified "inline" classes (mglGraph, mglData, mglWindow, ...), which
+    contain only inline members, which call C-functions. This make
+    MathGL completely cross-platform, i.e. the same binary files can be
+    used in any compiler (MinGW, MSVS, Borland, ...). Moreover it give
+    the same classes for all interfaces (Python/Octave/...).
+
+(d) MGL scripts use mglGraph's functions but give some extra
+    capabilities for axis setup or textual plot editing
+
+2. There is unified class mglGraph instead of set of mglGraphZB,
+   mglGraphPS, ... The quality<->speed level of plot is specified by
+   SetQuality() function.
+
+3. There is abstract class mglDataA which allow to derive classes with
+   its own data representation. However, I recommend to use mglData for
+   usual cases -- it have large set of built in functions.
+
+4. All plotting functions now have unified interface for arguments:
+   data objects or numbers; string with style; string with options.
+   Options (the same as ones in MGL v.1.*) allows one to make fine
+   tuning of plot. I.e. easily set the range of coordinates, plot
+   position, font size and so on.
+
+5. The last big change is style representation. There are differences
+   for colors and for text style:
+
+*  Colors may have "brighted" version everywhere -- just specify '{cN}'
+   instead of 'c'. Here 'c' is base color id, 'N' is digit 1,2...9 for
+   brightness. Also the transparency can be changed by adding '{AN}'.
+
+*  Text styles is reverted now -- to be unified with any other styles.
+   Color is placed firstly, then separator ':', and after it font styles
+   (bold, italic, wire, ...).
+
+Also there are a lot of other (not so general) changes and improvements.
diff --git a/addons/getopt/CMakeLists.txt b/addons/getopt/CMakeLists.txt
new file mode 100644
index 0000000..679b761
--- /dev/null
+++ b/addons/getopt/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_library(getopt-static STATIC getopt.c getopt.h)
+target_compile_definitions(getopt-static PUBLIC MGL_STATIC_DEFINE)
diff --git a/addons/getopt/getopt.c b/addons/getopt/getopt.c
new file mode 100644
index 0000000..dd21231
--- /dev/null
+++ b/addons/getopt/getopt.c
@@ -0,0 +1,969 @@
+/* Getopt for Microsoft C
+This code is a modification of the Free Software Foundation, Inc.
+Getopt library for parsing command line argument the purpose was
+to provide a Microsoft Visual C friendly derivative. This code
+provides functionality for both Unicode and Multibyte builds.
+
+Date: 02/03/2011 - Ludvik Jerabek - Initial Release
+Version: 1.0
+Comment: Supports getopt, getopt_long, and getopt_long_only
+and POSIXLY_CORRECT environment flag
+License: LGPL
+
+Revisions:
+
+02/03/2011 - Ludvik Jerabek - Initial Release
+02/20/2011 - Ludvik Jerabek - Fixed compiler warnings at Level 4
+07/05/2011 - Ludvik Jerabek - Added no_argument, required_argument, optional_argument defs
+08/03/2011 - Ludvik Jerabek - Fixed non-argument runtime bug which caused runtime exception
+08/09/2011 - Ludvik Jerabek - Added code to export functions for DLL and LIB
+02/15/2012 - Ludvik Jerabek - Fixed _GETOPT_THROW definition missing in implementation file
+08/01/2012 - Ludvik Jerabek - Created separate functions for char and wchar_t characters so single dll can do both unicode and ansi
+10/15/2012 - Ludvik Jerabek - Modified to match latest GNU features
+06/19/2015 - Ludvik Jerabek - Fixed maximum option limitation caused by option_a (255) and option_w (65535) structure val variable
+
+**DISCLAIMER**
+THIS MATERIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
+EITHER EXPRESS OR IMPLIED, INCLUDING, BUT Not LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE, OR NON-INFRINGEMENT. SOME JURISDICTIONS DO NOT ALLOW THE
+EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT
+APPLY TO YOU. IN NO EVENT WILL I BE LIABLE TO ANY PARTY FOR ANY
+DIRECT, INDIRECT, SPECIAL OR OTHER CONSEQUENTIAL DAMAGES FOR ANY
+USE OF THIS MATERIAL INCLUDING, WITHOUT LIMITATION, ANY LOST
+PROFITS, BUSINESS INTERRUPTION, LOSS OF PROGRAMS OR OTHER DATA ON
+YOUR INFORMATION HANDLING SYSTEM OR OTHERWISE, EVEN If WE ARE
+EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+*/
+#define _CRT_SECURE_NO_WARNINGS
+#include <stdlib.h>
+#include <stdio.h>
+#include <malloc.h>
+#include "getopt.h"
+
+#ifdef __cplusplus
+	#define _GETOPT_THROW throw()
+#else
+	#define _GETOPT_THROW
+#endif
+
+int optind = 1;
+int opterr = 1;
+int optopt = '?';
+enum ENUM_ORDERING { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER };
+
+//
+//
+//		Ansi structures and functions follow
+//
+//
+
+static struct _getopt_data_a
+{
+	int optind;
+	int opterr;
+	int optopt;
+	char *optarg;
+	int __initialized;
+	char *__nextchar;
+	enum ENUM_ORDERING __ordering;
+	int __posixly_correct;
+	int __first_nonopt;
+	int __last_nonopt;
+} getopt_data_a;
+char *optarg_a;
+
+static void exchange_a(char **argv, struct _getopt_data_a *d)
+{
+	int bottom = d->__first_nonopt;
+	int middle = d->__last_nonopt;
+	int top = d->optind;
+	char *tem;
+	while (top > middle && middle > bottom)
+	{
+		if (top - middle > middle - bottom)
+		{
+			int len = middle - bottom;
+			for (int i = 0; i < len; i++)
+			{
+				tem = argv[bottom + i];
+				argv[bottom + i] = argv[top - (middle - bottom) + i];
+				argv[top - (middle - bottom) + i] = tem;
+			}
+			top -= len;
+		}
+		else
+		{
+			int len = top - middle;
+			for (int i = 0; i < len; i++)
+			{
+				tem = argv[bottom + i];
+				argv[bottom + i] = argv[middle + i];
+				argv[middle + i] = tem;
+			}
+			bottom += len;
+		}
+	}
+	d->__first_nonopt += (d->optind - d->__last_nonopt);
+	d->__last_nonopt = d->optind;
+}
+static const char *_getopt_initialize_a (const char *optstring, struct _getopt_data_a *d, int posixly_correct)
+{
+	d->__first_nonopt = d->__last_nonopt = d->optind;
+	d->__nextchar = NULL;
+	d->__posixly_correct = posixly_correct | !!getenv("POSIXLY_CORRECT");
+	if (optstring[0] == '-')
+	{
+		d->__ordering = RETURN_IN_ORDER;
+		++optstring;
+	}
+	else if (optstring[0] == '+')
+	{
+		d->__ordering = REQUIRE_ORDER;
+		++optstring;
+	}
+	else if (d->__posixly_correct)
+		d->__ordering = REQUIRE_ORDER;
+	else
+		d->__ordering = PERMUTE;
+	return optstring;
+}
+int _getopt_internal_r_a (int argc, char *const *argv, const char *optstring, const struct option_a *longopts, int *longind, int long_only, struct _getopt_data_a *d, int posixly_correct)
+{
+	int print_errors = d->opterr;
+	if (argc < 1)
+		return -1;
+	d->optarg = NULL;
+	if (d->optind == 0 || !d->__initialized)
+	{
+		if (d->optind == 0)
+			d->optind = 1;
+		optstring = _getopt_initialize_a (optstring, d, posixly_correct);
+		d->__initialized = 1;
+	}
+	else if (optstring[0] == '-' || optstring[0] == '+')
+		optstring++;
+	if (optstring[0] == ':')
+		print_errors = 0;
+	if (d->__nextchar == NULL || *d->__nextchar == '\0')
+	{
+		if (d->__last_nonopt > d->optind)
+			d->__last_nonopt = d->optind;
+		if (d->__first_nonopt > d->optind)
+			d->__first_nonopt = d->optind;
+		if (d->__ordering == PERMUTE)
+		{
+			if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind)
+				exchange_a ((char **) argv, d);
+			else if (d->__last_nonopt != d->optind)
+				d->__first_nonopt = d->optind;
+			while (d->optind < argc && (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0'))
+				d->optind++;
+			d->__last_nonopt = d->optind;
+		}
+		if (d->optind != argc && !strcmp(argv[d->optind], "--"))
+		{
+			d->optind++;
+			if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind)
+				exchange_a((char **) argv, d);
+			else if (d->__first_nonopt == d->__last_nonopt)
+				d->__first_nonopt = d->optind;
+			d->__last_nonopt = argc;
+			d->optind = argc;
+		}
+		if (d->optind == argc)
+		{
+			if (d->__first_nonopt != d->__last_nonopt)
+				d->optind = d->__first_nonopt;
+			return -1;
+		}
+		if ((argv[d->optind][0] != '-' || argv[d->optind][1] == '\0'))
+		{
+			if (d->__ordering == REQUIRE_ORDER)
+				return -1;
+			d->optarg = argv[d->optind++];
+			return 1;
+		}
+		d->__nextchar = (argv[d->optind] + 1 + (longopts != NULL && argv[d->optind][1] == '-'));
+	}
+	if (longopts != NULL && (argv[d->optind][1] == '-' || (long_only && (argv[d->optind][2] || !strchr(optstring, argv[d->optind][1])))))
+	{
+		char *nameend;
+		unsigned int namelen;
+		const struct option_a *p;
+		const struct option_a *pfound = NULL;
+		struct option_list
+		{
+			const struct option_a *p;
+			struct option_list *next;
+		} *ambig_list = NULL;
+		int exact = 0;
+		int indfound = -1;
+		int option_index;
+		for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++);
+		namelen = (unsigned int)(nameend - d->__nextchar);
+		for (p = longopts, option_index = 0; p->name; p++, option_index++)
+			if (!strncmp(p->name, d->__nextchar, namelen))
+			{
+				if (namelen == (unsigned int)strlen(p->name))
+				{
+					pfound = p;
+					indfound = option_index;
+					exact = 1;
+					break;
+				}
+				else if (pfound == NULL)
+				{
+					pfound = p;
+					indfound = option_index;
+				}
+				else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val)
+				{
+					struct option_list *newp = (struct option_list*)alloca(sizeof(*newp));
+					newp->p = p;
+					newp->next = ambig_list;
+					ambig_list = newp;
+				}
+			}
+			if (ambig_list != NULL && !exact)
+			{
+				if (print_errors)
+				{
+					struct option_list first;
+					first.p = pfound;
+					first.next = ambig_list;
+					ambig_list = &first;
+					fprintf (stderr, "%s: option '%s' is ambiguous; possibilities:", argv[0], argv[d->optind]);
+					do
+					{
+						fprintf (stderr, " '--%s'", ambig_list->p->name);
+						ambig_list = ambig_list->next;
+					}
+					while (ambig_list != NULL);
+					fputc ('\n', stderr);
+				}
+				d->__nextchar += strlen(d->__nextchar);
+				d->optind++;
+				d->optopt = 0;
+				return '?';
+			}
+			if (pfound != NULL)
+			{
+				option_index = indfound;
+				d->optind++;
+				if (*nameend)
+				{
+					if (pfound->has_arg)
+						d->optarg = nameend + 1;
+					else
+					{
+						if (print_errors)
+						{
+							if (argv[d->optind - 1][1] == '-')
+							{
+								fprintf(stderr, "%s: option '--%s' doesn't allow an argument\n",argv[0], pfound->name);
+							}
+							else
+							{
+								fprintf(stderr, "%s: option '%c%s' doesn't allow an argument\n",argv[0], argv[d->optind - 1][0],pfound->name);
+							}
+						}
+						d->__nextchar += strlen(d->__nextchar);
+						d->optopt = pfound->val;
+						return '?';
+					}
+				}
+				else if (pfound->has_arg == 1)
+				{
+					if (d->optind < argc)
+						d->optarg = argv[d->optind++];
+					else
+					{
+						if (print_errors)
+						{
+							fprintf(stderr,"%s: option '--%s' requires an argument\n",argv[0], pfound->name);
+						}
+						d->__nextchar += strlen(d->__nextchar);
+						d->optopt = pfound->val;
+						return optstring[0] == ':' ? ':' : '?';
+					}
+				}
+				d->__nextchar += strlen(d->__nextchar);
+				if (longind != NULL)
+					*longind = option_index;
+				if (pfound->flag)
+				{
+					*(pfound->flag) = pfound->val;
+					return 0;
+				}
+				return pfound->val;
+			}
+			if (!long_only || argv[d->optind][1] == '-' || strchr(optstring, *d->__nextchar) == NULL)
+			{
+				if (print_errors)
+				{
+					if (argv[d->optind][1] == '-')
+					{
+						fprintf(stderr, "%s: unrecognized option '--%s'\n",argv[0], d->__nextchar);
+					}
+					else
+					{
+						fprintf(stderr, "%s: unrecognized option '%c%s'\n",argv[0], argv[d->optind][0], d->__nextchar);
+					}
+				}
+				d->__nextchar = (char *)"";
+				d->optind++;
+				d->optopt = 0;
+				return '?';
+			}
+	}
+	{
+		char c = *d->__nextchar++;
+		char *temp = (char*)strchr(optstring, c);
+		if (*d->__nextchar == '\0')
+			++d->optind;
+		if (temp == NULL || c == ':' || c == ';')
+		{
+			if (print_errors)
+			{
+				fprintf(stderr, "%s: invalid option -- '%c'\n", argv[0], c);
+			}
+			d->optopt = c;
+			return '?';
+		}
+		if (temp[0] == 'W' && temp[1] == ';')
+		{
+			char *nameend;
+			const struct option_a *p;
+			const struct option_a *pfound = NULL;
+			int exact = 0;
+			int ambig = 0;
+			int indfound = 0;
+			int option_index;
+			if (longopts == NULL)
+				goto no_longs;
+			if (*d->__nextchar != '\0')
+			{
+				d->optarg = d->__nextchar;
+				d->optind++;
+			}
+			else if (d->optind == argc)
+			{
+				if (print_errors)
+				{
+					fprintf(stderr,"%s: option requires an argument -- '%c'\n",argv[0], c);
+				}
+				d->optopt = c;
+				if (optstring[0] == ':')
+					c = ':';
+				else
+					c = '?';
+				return c;
+			}
+			else
+				d->optarg = argv[d->optind++];
+			for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '='; nameend++);
+			for (p = longopts, option_index = 0; p->name; p++, option_index++)
+				if (!strncmp(p->name, d->__nextchar, nameend - d->__nextchar))
+				{
+					if ((unsigned int) (nameend - d->__nextchar) == strlen(p->name))
+					{
+						pfound = p;
+						indfound = option_index;
+						exact = 1;
+						break;
+					}
+					else if (pfound == NULL)
+					{
+						pfound = p;
+						indfound = option_index;
+					}
+					else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val)
+						ambig = 1;
+				}
+				if (ambig && !exact)
+				{
+					if (print_errors)
+					{
+						fprintf(stderr, "%s: option '-W %s' is ambiguous\n",argv[0], d->optarg);
+					}
+					d->__nextchar += strlen(d->__nextchar);
+					d->optind++;
+					return '?';
+				}
+				if (pfound != NULL)
+				{
+					option_index = indfound;
+					if (*nameend)
+					{
+						if (pfound->has_arg)
+							d->optarg = nameend + 1;
+						else
+						{
+							if (print_errors)
+							{
+								fprintf(stderr, "%s: option '-W %s' doesn't allow an argument\n",argv[0], pfound->name);
+							}
+							d->__nextchar += strlen(d->__nextchar);
+							return '?';
+						}
+					}
+					else if (pfound->has_arg == 1)
+					{
+						if (d->optind < argc)
+							d->optarg = argv[d->optind++];
+						else
+						{
+							if (print_errors)
+							{
+								fprintf(stderr, "%s: option '-W %s' requires an argument\n",argv[0], pfound->name);
+							}
+							d->__nextchar += strlen(d->__nextchar);
+							return optstring[0] == ':' ? ':' : '?';
+						}
+					}
+					else
+						d->optarg = NULL;
+					d->__nextchar += strlen(d->__nextchar);
+					if (longind != NULL)
+						*longind = option_index;
+					if (pfound->flag)
+					{
+						*(pfound->flag) = pfound->val;
+						return 0;
+					}
+					return pfound->val;
+				}
+no_longs:
+				d->__nextchar = NULL;
+				return 'W';
+		}
+		if (temp[1] == ':')
+		{
+			if (temp[2] == ':')
+			{
+				if (*d->__nextchar != '\0')
+				{
+					d->optarg = d->__nextchar;
+					d->optind++;
+				}
+				else
+					d->optarg = NULL;
+				d->__nextchar = NULL;
+			}
+			else
+			{
+				if (*d->__nextchar != '\0')
+				{
+					d->optarg = d->__nextchar;
+					d->optind++;
+				}
+				else if (d->optind == argc)
+				{
+					if (print_errors)
+					{
+						fprintf(stderr,"%s: option requires an argument -- '%c'\n",argv[0], c);
+					}
+					d->optopt = c;
+					if (optstring[0] == ':')
+						c = ':';
+					else
+						c = '?';
+				}
+				else
+					d->optarg = argv[d->optind++];
+				d->__nextchar = NULL;
+			}
+		}
+		return c;
+	}
+}
+int _getopt_internal_a (int argc, char *const *argv, const char *optstring, const struct option_a *longopts, int *longind, int long_only, int posixly_correct)
+{
+	int result;
+	getopt_data_a.optind = optind;
+	getopt_data_a.opterr = opterr;
+	result = _getopt_internal_r_a (argc, argv, optstring, longopts,longind, long_only, &getopt_data_a,posixly_correct);
+	optind = getopt_data_a.optind;
+	optarg_a = getopt_data_a.optarg;
+	optopt = getopt_data_a.optopt;
+	return result;
+}
+int getopt_a (int argc, char *const *argv, const char *optstring) _GETOPT_THROW
+{
+	return _getopt_internal_a (argc, argv, optstring, (const struct option_a *) 0, (int *) 0, 0, 0);
+}
+int getopt_long_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW
+{
+	return _getopt_internal_a (argc, argv, options, long_options, opt_index, 0, 0);
+}
+int getopt_long_only_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW
+{
+	return _getopt_internal_a (argc, argv, options, long_options, opt_index, 1, 0);
+}
+int _getopt_long_r_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index, struct _getopt_data_a *d)
+{
+	return _getopt_internal_r_a (argc, argv, options, long_options, opt_index,0, d, 0);
+}
+int _getopt_long_only_r_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index, struct _getopt_data_a *d)
+{
+	return _getopt_internal_r_a (argc, argv, options, long_options, opt_index, 1, d, 0);
+}
+
+//
+//
+//	Unicode Structures and Functions
+//
+//
+
+static struct _getopt_data_w
+{
+	int optind;
+	int opterr;
+	int optopt;
+	wchar_t *optarg;
+	int __initialized;
+	wchar_t *__nextchar;
+	enum ENUM_ORDERING __ordering;
+	int __posixly_correct;
+	int __first_nonopt;
+	int __last_nonopt;
+} getopt_data_w;
+wchar_t *optarg_w;
+
+static void exchange_w(wchar_t **argv, struct _getopt_data_w *d)
+{
+	int bottom = d->__first_nonopt;
+	int middle = d->__last_nonopt;
+	int top = d->optind;
+	wchar_t *tem;
+	while (top > middle && middle > bottom)
+	{
+		if (top - middle > middle - bottom)
+		{
+			int len = middle - bottom;
+			for (int i = 0; i < len; i++)
+			{
+				tem = argv[bottom + i];
+				argv[bottom + i] = argv[top - (middle - bottom) + i];
+				argv[top - (middle - bottom) + i] = tem;
+			}
+			top -= len;
+		}
+		else
+		{
+			int len = top - middle;
+			for (int i = 0; i < len; i++)
+			{
+				tem = argv[bottom + i];
+				argv[bottom + i] = argv[middle + i];
+				argv[middle + i] = tem;
+			}
+			bottom += len;
+		}
+	}
+	d->__first_nonopt += (d->optind - d->__last_nonopt);
+	d->__last_nonopt = d->optind;
+}
+static const wchar_t *_getopt_initialize_w (const wchar_t *optstring, struct _getopt_data_w *d, int posixly_correct)
+{
+	d->__first_nonopt = d->__last_nonopt = d->optind;
+	d->__nextchar = NULL;
+	d->__posixly_correct = posixly_correct | !!_wgetenv(L"POSIXLY_CORRECT");
+	if (optstring[0] == L'-')
+	{
+		d->__ordering = RETURN_IN_ORDER;
+		++optstring;
+	}
+	else if (optstring[0] == L'+')
+	{
+		d->__ordering = REQUIRE_ORDER;
+		++optstring;
+	}
+	else if (d->__posixly_correct)
+		d->__ordering = REQUIRE_ORDER;
+	else
+		d->__ordering = PERMUTE;
+	return optstring;
+}
+int _getopt_internal_r_w (int argc, wchar_t *const *argv, const wchar_t *optstring, const struct option_w *longopts, int *longind, int long_only, struct _getopt_data_w *d, int posixly_correct)
+{
+	int print_errors = d->opterr;
+	if (argc < 1)
+		return -1;
+	d->optarg = NULL;
+	if (d->optind == 0 || !d->__initialized)
+	{
+		if (d->optind == 0)
+			d->optind = 1;
+		optstring = _getopt_initialize_w (optstring, d, posixly_correct);
+		d->__initialized = 1;
+	}
+	else if (optstring[0] == L'-' || optstring[0] == L'+')
+		optstring++;
+	if (optstring[0] == L':')
+		print_errors = 0;
+	if (d->__nextchar == NULL || *d->__nextchar == L'\0')
+	{
+		if (d->__last_nonopt > d->optind)
+			d->__last_nonopt = d->optind;
+		if (d->__first_nonopt > d->optind)
+			d->__first_nonopt = d->optind;
+		if (d->__ordering == PERMUTE)
+		{
+			if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind)
+				exchange_w((wchar_t **) argv, d);
+			else if (d->__last_nonopt != d->optind)
+				d->__first_nonopt = d->optind;
+			while (d->optind < argc && (argv[d->optind][0] != L'-' || argv[d->optind][1] == L'\0'))
+				d->optind++;
+			d->__last_nonopt = d->optind;
+		}
+		if (d->optind != argc && !wcscmp(argv[d->optind], L"--"))
+		{
+			d->optind++;
+			if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind)
+				exchange_w((wchar_t **) argv, d);
+			else if (d->__first_nonopt == d->__last_nonopt)
+				d->__first_nonopt = d->optind;
+			d->__last_nonopt = argc;
+			d->optind = argc;
+		}
+		if (d->optind == argc)
+		{
+			if (d->__first_nonopt != d->__last_nonopt)
+				d->optind = d->__first_nonopt;
+			return -1;
+		}
+		if ((argv[d->optind][0] != L'-' || argv[d->optind][1] == L'\0'))
+		{
+			if (d->__ordering == REQUIRE_ORDER)
+				return -1;
+			d->optarg = argv[d->optind++];
+			return 1;
+		}
+		d->__nextchar = (argv[d->optind] + 1 + (longopts != NULL && argv[d->optind][1] == L'-'));
+	}
+	if (longopts != NULL && (argv[d->optind][1] == L'-' || (long_only && (argv[d->optind][2] || !wcschr(optstring, argv[d->optind][1])))))
+	{
+		wchar_t *nameend;
+		unsigned int namelen;
+		const struct option_w *p;
+		const struct option_w *pfound = NULL;
+		struct option_list
+		{
+			const struct option_w *p;
+			struct option_list *next;
+		} *ambig_list = NULL;
+		int exact = 0;
+		int indfound = -1;
+		int option_index;
+		for (nameend = d->__nextchar; *nameend && *nameend != L'='; nameend++);
+		namelen = (unsigned int)(nameend - d->__nextchar);
+		for (p = longopts, option_index = 0; p->name; p++, option_index++)
+			if (!wcsncmp(p->name, d->__nextchar, namelen))
+			{
+				if (namelen == (unsigned int)wcslen(p->name))
+				{
+					pfound = p;
+					indfound = option_index;
+					exact = 1;
+					break;
+				}
+				else if (pfound == NULL)
+				{
+					pfound = p;
+					indfound = option_index;
+				}
+				else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val)
+				{
+					struct option_list *newp = (struct option_list*)alloca(sizeof(*newp));
+					newp->p = p;
+					newp->next = ambig_list;
+					ambig_list = newp;
+				}
+			}
+			if (ambig_list != NULL && !exact)
+			{
+				if (print_errors)
+				{
+					struct option_list first;
+					first.p = pfound;
+					first.next = ambig_list;
+					ambig_list = &first;
+					fwprintf(stderr, L"%ls: option '%ls' is ambiguous; possibilities:", argv[0], argv[d->optind]);
+					do
+					{
+						fwprintf (stderr, L" '--%ls'", ambig_list->p->name);
+						ambig_list = ambig_list->next;
+					}
+					while (ambig_list != NULL);
+					fputwc (L'\n', stderr);
+				}
+				d->__nextchar += wcslen(d->__nextchar);
+				d->optind++;
+				d->optopt = 0;
+				return L'?';
+			}
+			if (pfound != NULL)
+			{
+				option_index = indfound;
+				d->optind++;
+				if (*nameend)
+				{
+					if (pfound->has_arg)
+						d->optarg = nameend + 1;
+					else
+					{
+						if (print_errors)
+						{
+							if (argv[d->optind - 1][1] == L'-')
+							{
+								fwprintf(stderr, L"%ls: option '--%ls' doesn't allow an argument\n",argv[0], pfound->name);
+							}
+							else
+							{
+								fwprintf(stderr, L"%ls: option '%c%ls' doesn't allow an argument\n",argv[0], argv[d->optind - 1][0],pfound->name);
+							}
+						}
+						d->__nextchar += wcslen(d->__nextchar);
+						d->optopt = pfound->val;
+						return L'?';
+					}
+				}
+				else if (pfound->has_arg == 1)
+				{
+					if (d->optind < argc)
+						d->optarg = argv[d->optind++];
+					else
+					{
+						if (print_errors)
+						{
+							fwprintf(stderr,L"%ls: option '--%ls' requires an argument\n",argv[0], pfound->name);
+						}
+						d->__nextchar += wcslen(d->__nextchar);
+						d->optopt = pfound->val;
+						return optstring[0] == L':' ? L':' : L'?';
+					}
+				}
+				d->__nextchar += wcslen(d->__nextchar);
+				if (longind != NULL)
+					*longind = option_index;
+				if (pfound->flag)
+				{
+					*(pfound->flag) = pfound->val;
+					return 0;
+				}
+				return pfound->val;
+			}
+			if (!long_only || argv[d->optind][1] == L'-' || wcschr(optstring, *d->__nextchar) == NULL)
+			{
+				if (print_errors)
+				{
+					if (argv[d->optind][1] == L'-')
+					{
+						fwprintf(stderr, L"%ls: unrecognized option '--%ls'\n",argv[0], d->__nextchar);
+					}
+					else
+					{
+						fwprintf(stderr, L"%ls: unrecognized option '%c%ls'\n",argv[0], argv[d->optind][0], d->__nextchar);
+					}
+				}
+				d->__nextchar = (wchar_t *)L"";
+				d->optind++;
+				d->optopt = 0;
+				return L'?';
+			}
+	}
+	{
+		wchar_t c = *d->__nextchar++;
+		wchar_t *temp = (wchar_t*)wcschr(optstring, c);
+		if (*d->__nextchar == L'\0')
+			++d->optind;
+		if (temp == NULL || c == L':' || c == L';')
+		{
+			if (print_errors)
+			{
+				fwprintf(stderr, L"%ls: invalid option -- '%c'\n", argv[0], c);
+			}
+			d->optopt = c;
+			return L'?';
+		}
+		if (temp[0] == L'W' && temp[1] == L';')
+		{
+			wchar_t *nameend;
+			const struct option_w *p;
+			const struct option_w *pfound = NULL;
+			int exact = 0;
+			int ambig = 0;
+			int indfound = 0;
+			int option_index;
+			if (longopts == NULL)
+				goto no_longs;
+			if (*d->__nextchar != L'\0')
+			{
+				d->optarg = d->__nextchar;
+				d->optind++;
+			}
+			else if (d->optind == argc)
+			{
+				if (print_errors)
+				{
+					fwprintf(stderr,L"%ls: option requires an argument -- '%c'\n",argv[0], c);
+				}
+				d->optopt = c;
+				if (optstring[0] == L':')
+					c = L':';
+				else
+					c = L'?';
+				return c;
+			}
+			else
+				d->optarg = argv[d->optind++];
+			for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != L'='; nameend++);
+			for (p = longopts, option_index = 0; p->name; p++, option_index++)
+				if (!wcsncmp(p->name, d->__nextchar, nameend - d->__nextchar))
+				{
+					if ((unsigned int) (nameend - d->__nextchar) == wcslen(p->name))
+					{
+						pfound = p;
+						indfound = option_index;
+						exact = 1;
+						break;
+					}
+					else if (pfound == NULL)
+					{
+						pfound = p;
+						indfound = option_index;
+					}
+					else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val)
+						ambig = 1;
+				}
+				if (ambig && !exact)
+				{
+					if (print_errors)
+					{
+						fwprintf(stderr, L"%ls: option '-W %ls' is ambiguous\n",argv[0], d->optarg);
+					}
+					d->__nextchar += wcslen(d->__nextchar);
+					d->optind++;
+					return L'?';
+				}
+				if (pfound != NULL)
+				{
+					option_index = indfound;
+					if (*nameend)
+					{
+						if (pfound->has_arg)
+							d->optarg = nameend + 1;
+						else
+						{
+							if (print_errors)
+							{
+								fwprintf(stderr, L"%ls: option '-W %ls' doesn't allow an argument\n",argv[0], pfound->name);
+							}
+							d->__nextchar += wcslen(d->__nextchar);
+							return L'?';
+						}
+					}
+					else if (pfound->has_arg == 1)
+					{
+						if (d->optind < argc)
+							d->optarg = argv[d->optind++];
+						else
+						{
+							if (print_errors)
+							{
+								fwprintf(stderr, L"%ls: option '-W %ls' requires an argument\n",argv[0], pfound->name);
+							}
+							d->__nextchar += wcslen(d->__nextchar);
+							return optstring[0] == L':' ? L':' : L'?';
+						}
+					}
+					else
+						d->optarg = NULL;
+					d->__nextchar += wcslen(d->__nextchar);
+					if (longind != NULL)
+						*longind = option_index;
+					if (pfound->flag)
+					{
+						*(pfound->flag) = pfound->val;
+						return 0;
+					}
+					return pfound->val;
+				}
+no_longs:
+				d->__nextchar = NULL;
+				return L'W';
+		}
+		if (temp[1] == L':')
+		{
+			if (temp[2] == L':')
+			{
+				if (*d->__nextchar != L'\0')
+				{
+					d->optarg = d->__nextchar;
+					d->optind++;
+				}
+				else
+					d->optarg = NULL;
+				d->__nextchar = NULL;
+			}
+			else
+			{
+				if (*d->__nextchar != L'\0')
+				{
+					d->optarg = d->__nextchar;
+					d->optind++;
+				}
+				else if (d->optind == argc)
+				{
+					if (print_errors)
+					{
+						fwprintf(stderr,L"%ls: option requires an argument -- '%c'\n",argv[0], c);
+					}
+					d->optopt = c;
+					if (optstring[0] == L':')
+						c = L':';
+					else
+						c = L'?';
+				}
+				else
+					d->optarg = argv[d->optind++];
+				d->__nextchar = NULL;
+			}
+		}
+		return c;
+	}
+}
+int _getopt_internal_w (int argc, wchar_t *const *argv, const wchar_t *optstring, const struct option_w *longopts, int *longind, int long_only, int posixly_correct)
+{
+	int result;
+	getopt_data_w.optind = optind;
+	getopt_data_w.opterr = opterr;
+	result = _getopt_internal_r_w (argc, argv, optstring, longopts,longind, long_only, &getopt_data_w,posixly_correct);
+	optind = getopt_data_w.optind;
+	optarg_w = getopt_data_w.optarg;
+	optopt = getopt_data_w.optopt;
+	return result;
+}
+int getopt_w (int argc, wchar_t *const *argv, const wchar_t *optstring) _GETOPT_THROW
+{
+	return _getopt_internal_w (argc, argv, optstring, (const struct option_w *) 0, (int *) 0, 0, 0);
+}
+int getopt_long_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW
+{
+	return _getopt_internal_w (argc, argv, options, long_options, opt_index, 0, 0);
+}
+int getopt_long_only_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW
+{
+	return _getopt_internal_w (argc, argv, options, long_options, opt_index, 1, 0);
+}
+int _getopt_long_r_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index, struct _getopt_data_w *d)
+{
+	return _getopt_internal_r_w (argc, argv, options, long_options, opt_index,0, d, 0);
+}
+int _getopt_long_only_r_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index, struct _getopt_data_w *d)
+{
+	return _getopt_internal_r_w (argc, argv, options, long_options, opt_index, 1, d, 0);
+}
diff --git a/addons/getopt/getopt.h b/addons/getopt/getopt.h
new file mode 100644
index 0000000..9b52559
--- /dev/null
+++ b/addons/getopt/getopt.h
@@ -0,0 +1,121 @@
+/* Getopt for Microsoft C
+This code is a modification of the Free Software Foundation, Inc.
+Getopt library for parsing command line argument the purpose was
+to provide a Microsoft Visual C friendly derivative. This code
+provides functionality for both Unicode and Multibyte builds.
+
+Date: 02/03/2011 - Ludvik Jerabek - Initial Release
+Version: 1.0
+Comment: Supports getopt, getopt_long, and getopt_long_only
+and POSIXLY_CORRECT environment flag
+License: LGPL
+
+Revisions:
+
+02/03/2011 - Ludvik Jerabek - Initial Release
+02/20/2011 - Ludvik Jerabek - Fixed compiler warnings at Level 4
+07/05/2011 - Ludvik Jerabek - Added no_argument, required_argument, optional_argument defs
+08/03/2011 - Ludvik Jerabek - Fixed non-argument runtime bug which caused runtime exception
+08/09/2011 - Ludvik Jerabek - Added code to export functions for DLL and LIB
+02/15/2012 - Ludvik Jerabek - Fixed _GETOPT_THROW definition missing in implementation file
+08/01/2012 - Ludvik Jerabek - Created separate functions for char and wchar_t characters so single dll can do both unicode and ansi
+10/15/2012 - Ludvik Jerabek - Modified to match latest GNU features
+06/19/2015 - Ludvik Jerabek - Fixed maximum option limitation caused by option_a (255) and option_w (65535) structure val variable
+
+**DISCLAIMER**
+THIS MATERIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
+EITHER EXPRESS OR IMPLIED, INCLUDING, BUT Not LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE, OR NON-INFRINGEMENT. SOME JURISDICTIONS DO NOT ALLOW THE
+EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT
+APPLY TO YOU. IN NO EVENT WILL I BE LIABLE TO ANY PARTY FOR ANY
+DIRECT, INDIRECT, SPECIAL OR OTHER CONSEQUENTIAL DAMAGES FOR ANY
+USE OF THIS MATERIAL INCLUDING, WITHOUT LIMITATION, ANY LOST
+PROFITS, BUSINESS INTERRUPTION, LOSS OF PROGRAMS OR OTHER DATA ON
+YOUR INFORMATION HANDLING SYSTEM OR OTHERWISE, EVEN If WE ARE
+EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+*/
+#ifndef __GETOPT_H_
+	#define __GETOPT_H_
+	#include <mgl2/dllexport.h>
+	#define _GETOPT_API MGL_EXPORT
+
+	// Change behavior for C\C++
+	#ifdef __cplusplus
+		#define _BEGIN_EXTERN_C extern "C" {
+		#define _END_EXTERN_C }
+		#define _GETOPT_THROW throw()
+	#else
+		#define _BEGIN_EXTERN_C
+		#define _END_EXTERN_C
+		#define _GETOPT_THROW
+	#endif
+
+	// Standard GNU options
+	#define	null_argument		0	/*Argument Null*/
+	#define	no_argument			0	/*Argument Switch Only*/
+	#define required_argument	1	/*Argument Required*/
+	#define optional_argument	2	/*Argument Optional*/	
+
+	// Shorter Options
+	#define ARG_NULL	0	/*Argument Null*/
+	#define ARG_NONE	0	/*Argument Switch Only*/
+	#define ARG_REQ		1	/*Argument Required*/
+	#define ARG_OPT		2	/*Argument Optional*/
+
+	#include <string.h>
+	#include <wchar.h>
+
+_BEGIN_EXTERN_C
+
+	extern _GETOPT_API int optind;
+	extern _GETOPT_API int opterr;
+	extern _GETOPT_API int optopt;
+
+	// Ansi
+	struct option_a
+	{
+		const char* name;
+		int has_arg;
+		int *flag;
+		int val;
+	};
+	extern _GETOPT_API char *optarg_a;
+	extern _GETOPT_API int getopt_a(int argc, char *const *argv, const char *optstring) _GETOPT_THROW;
+	extern _GETOPT_API int getopt_long_a(int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW;
+	extern _GETOPT_API int getopt_long_only_a(int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW;
+
+	// Unicode
+	struct option_w
+	{
+		const wchar_t* name;
+		int has_arg;
+		int *flag;
+		int val;
+	};
+	extern _GETOPT_API wchar_t *optarg_w;
+	extern _GETOPT_API int getopt_w(int argc, wchar_t *const *argv, const wchar_t *optstring) _GETOPT_THROW;
+	extern _GETOPT_API int getopt_long_w(int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW;
+	extern _GETOPT_API int getopt_long_only_w(int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW;	
+	
+_END_EXTERN_C
+
+	#undef _BEGIN_EXTERN_C
+	#undef _END_EXTERN_C
+	#undef _GETOPT_THROW
+	#undef _GETOPT_API
+
+	#ifdef _UNICODE
+		#define getopt getopt_w
+		#define getopt_long getopt_long_w
+		#define getopt_long_only getopt_long_only_w
+		#define option option_w
+		#define optarg optarg_w
+	#else
+		#define getopt getopt_a
+		#define getopt_long getopt_long_a
+		#define getopt_long_only getopt_long_only_a
+		#define option option_a
+		#define optarg optarg_a
+	#endif
+#endif  // __GETOPT_H_
diff --git a/brush.ods b/brush.ods
new file mode 100644
index 0000000..ae9110c
Binary files /dev/null and b/brush.ods differ
diff --git a/cmake-qt4.txt b/cmake-qt4.txt
new file mode 100644
index 0000000..c38c7da
--- /dev/null
+++ b/cmake-qt4.txt
@@ -0,0 +1,14 @@
+set(MGL_HAVE_QT4 1)
+set(MGL_QT4_LIBS_FIND QtCore QtGui QtOpenGL)
+set(MGL_QT4_LIBS_FIND_JSON QtNetwork QtWebKit)
+
+FIND_PACKAGE(Qt4 4.8 REQUIRED ${MGL_QT4_LIBS_FIND})
+
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTOUIC ON)
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(MGL_QT4_LIBS)
+foreach(mgl_qt4_lib ${MGL_QT4_LIBS_FIND})
+	set(MGL_QT4_LIBS ${MGL_QT4_LIBS} Qt4::${mgl_qt4_lib})
+endforeach(mgl_qt4_lib)
diff --git a/cmake-qt5.txt b/cmake-qt5.txt
new file mode 100644
index 0000000..ceec34a
--- /dev/null
+++ b/cmake-qt5.txt
@@ -0,0 +1,22 @@
+set(MGL_HAVE_QT5 1)
+
+macro(find_qt5_libs qt5_lib_req qt5_lib_add)
+	foreach(mgl_qt5_lib ${ARGN})
+		find_package(Qt5${mgl_qt5_lib} QUIET)
+		if(NOT Qt5${mgl_qt5_lib}_FOUND)
+			if(${qt5_lib_req})
+				message(SEND_ERROR "Couldn't find Qt5 ${mgl_qt5_lib} library.")
+			endif(${qt5_lib_req})
+		else(NOT Qt5${mgl_qt5_lib}_FOUND)
+			if(${qt5_lib_add})
+				set(MGL_QT5_LIBS ${MGL_QT5_LIBS} Qt5::${mgl_qt5_lib})
+			endif(${qt5_lib_add})
+		endif(NOT Qt5${mgl_qt5_lib}_FOUND)
+	endforeach(mgl_qt5_lib)
+endmacro(find_qt5_libs qt5_lib_req)
+
+find_qt5_libs(ON ON Core Gui Widgets PrintSupport OpenGL)
+
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTOUIC ON)
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
diff --git a/emblem.mgl b/emblem.mgl
new file mode 100644
index 0000000..a3f2473
--- /dev/null
+++ b/emblem.mgl
@@ -0,0 +1,40 @@
+setsize 1000 500
+text 0.95 0.8 'MathGL' ':RiA' -4
+text 0.05 0.15 'library\n for scientific graphics' ':LiA' -2.
+#rect 0.05 0.9 2 1.5 1.34 2 'w'
+xtick -3:ytick -3:ztick -3
+subplot 1 1 0 '^_'
+
+stickplot 3 0 60 20:box
+new y 50: fill y '-cos(pi*x-pi/4)'
+new x 50: fill x '-sin(pi*x-pi/4)'
+new z 50: fill z '2*x^2-1'
+
+area x y z 'lG'
+plot x y z 'B2s'
+
+stickplot 3 1 60 20:box
+
+new aa 50 40
+modify aa '0.6*sin(2*pi*x)*sin(3*pi*y) + 0.4*cos(3*pi*(x*y))'
+mirror aa 'y'
+light on :alpha on
+surf aa 'BbcyrR';alpha 0.8
+cont aa 'y'
+
+stickplot 3 2 60 20:box
+rotate 0 20
+
+new a 61 51 40
+modify a '-2*((2*x-1)^2 + (2*y-1)^2 + (2*z-1)^4 - (2*z-1)^2 - 0.1)'
+
+alpha on:light off
+cloud a 'wyrRk'
+
+stop
+cut 0 -1 -1 1 0 1.1
+surf3 a -1 'BbcyrR'
+contf3 a 'x' -1
+contf3 a 'y' -1
+contf3 a 'z' 0
+contf3 a 'z' 39
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
new file mode 100644
index 0000000..0fa52bc
--- /dev/null
+++ b/examples/CMakeLists.txt
@@ -0,0 +1,47 @@
+file(COPY ${CMAKE_SOURCE_DIR}/examples/iris.dat DESTINATION ${CMAKE_BINARY_DIR}/examples)
+file(COPY ${CMAKE_SOURCE_DIR}/examples/Equirectangular-projection.jpg DESTINATION ${CMAKE_BINARY_DIR}/examples)
+add_executable(mgl_example wnd_samples.cpp full_test.cpp samples.cpp)
+target_link_libraries(mgl_example mgl-static ${getopt_lib-static})
+
+if(MGL_HAVE_FLTK)
+	include_directories(${FLTK_INCLUDE_DIR})
+	add_executable(mgl_fltk_example wnd_samples.cpp fltk_example.cpp)
+	target_link_libraries(mgl_fltk_example mgl-fltk)
+endif(MGL_HAVE_FLTK)
+
+if(MGL_HAVE_GLUT)
+	add_executable(mgl_glut_example wnd_samples.cpp glut_example.cpp)
+	target_link_libraries(mgl_glut_example mgl-glut)
+endif(MGL_HAVE_GLUT)
+
+if(MGL_HAVE_WX)
+	include(${wxWidgets_USE_FILE})
+	add_executable(mgl_wx_example wnd_samples.cpp wx_example.cpp)
+	target_link_libraries(mgl_wx_example mgl-wx)
+endif(MGL_HAVE_WX)
+
+if(QT_ENABLED)
+	add_executable(mgl_qt_example wnd_samples.cpp qt_example.cpp)
+	if(enable-qt5)
+		include(../cmake-qt5.txt)
+		target_link_libraries(mgl_qt_example mgl-qt5)
+	else(enable-qt5)
+		include(../cmake-qt4.txt)
+		target_link_libraries(mgl_qt_example mgl-qt4)
+	endif(enable-qt5)
+	
+	if(MGL_HAVE_OPENGL)
+		add_executable(mgl_qgl_example wnd_samples.cpp qgl_example.cpp)
+		if(enable-qt5)
+			target_link_libraries(mgl_qgl_example mgl ${MGL_QT5_LIBS})
+		else(enable-qt5)
+			target_link_libraries(mgl_qgl_example mgl ${MGL_QT4_LIBS})
+		endif(enable-qt5)
+	endif(MGL_HAVE_OPENGL)
+endif(QT_ENABLED)
+
+if(MGL_HAVE_LTDL)
+	add_library(mgl_module MODULE mgl_module.cpp)
+	target_link_libraries(mgl_module mgl)	# for compatibility with win32
+endif(MGL_HAVE_LTDL)
+
diff --git a/examples/Equirectangular-projection.jpg b/examples/Equirectangular-projection.jpg
new file mode 100644
index 0000000..bfc62ab
Binary files /dev/null and b/examples/Equirectangular-projection.jpg differ
diff --git a/examples/FractInt.ifs b/examples/FractInt.ifs
new file mode 100644
index 0000000..5503b66
--- /dev/null
+++ b/examples/FractInt.ifs
@@ -0,0 +1,158 @@
+
+ binary
+ { ; comment allowed here
+  ; and here
+  .5  .0 .0 .5 -2.563477 -0.000003 .333333   ; also comment allowed here
+  .5  .0 .0 .5  2.436544 -0.000003 .333333
+  .0 -.5 .5 .0  4.873085  7.563492 .333333
+  }
+
+coral{.307692 -.531469 -.461538 -.293706  5.401953 8.655175 .40 ; also comment
+  .307692 -.076923  .153846 -.447552 -1.295248 4.152990 .15
+  .000000  .545455  .692308 -.195804 -4.893637 7.269794 .45
+  }
+
+crystal {
+  .696970 -.481061 -.393939 -.662879 2.147003 10.310288 .747826
+  .090909 -.443182  .515152 -.094697 4.286558  2.925762 .252174
+  }
+
+dragon {
+  .824074 .281482 -.212346  .864198 -1.882290 -0.110607 .787473
+  .088272 .520988 -.463889 -.377778  0.785360  8.095795 .212527
+  }
+
+fern {0  0    0  .16 0   0 .01
+   .85  .04 -.04 .85 0 1.6 .85
+   .2  -.26  .23 .22 0 1.6 .07
+  -.15  .28  .26 .24 0 .44 .07
+  }
+
+3dfern (3D) {
+   .00  .00 0 .0 .18 .0 0  0.0 0.00 0 0.0 0 .01
+   .85  .00 0 .0 .85 .1 0 -0.1 0.85 0 1.6 0 .85
+   .20 -.20 0 .2 .20 .0 0  0.0 0.30 0 0.8 0 .07
+  -.20  .20 0 .2 .20 .0 0  0.0 0.30 0 0.8 0 .07
+  }
+
+floor {
+  .0 -.5  .5 .0 -1.732366 3.366182 .333333
+  .5  .0  .0 .5 -0.027891 5.014877 .333333
+  .0  .5 -.5 .0  1.620804 3.310401 .333333
+  }
+
+koch3 {
+  .307692 -.000000  .000000  .294118  4.119164 1.604278 .151515
+  .192308 -.205882  .653846  .088235 -0.688840 5.978916 .253788
+  .192308  .205882 -.653846  .088235  0.668580 5.962514 .253788
+  .307692 -.000000  .000000  .294118 -4.136530 1.604278 .151515
+  .384615 -.000000  .000000 -.294118 -0.007718 2.941176 .189394
+  }
+
+spiral {   
+   .787879 -.424242 .242424 .859848  1.758647 1.408065 .895652
+  -.121212  .257576 .151515 .053030 -6.721654 1.377236 .052174
+   .181818 -.136364 .090909 .181818  6.086107 1.568035 .052174
+  }
+
+swirl5 {
+   .745455 -.459091  .406061  .887121 1.460279 0.691072 .912675
+  -.424242 -.065152 -.175758 -.218182 3.809567 6.741476 .087325
+  }
+
+tree {
+    0  0   0  .5   0   0  .05
+  .42 -.42  .42 .42  0  .2  .4
+  .42  .42 -.42 .42  0  .2  .4
+   .1  0   0  .1   0  .2  .15
+  }
+
+triangle {
+  .5  0  0  .5  0  0  .33
+  .5  0  0  .5  0  1  .33
+  .5  0  0  .5  1  1  .34
+  }
+
+zigzag2 {
+  -.632407 -.614815 -.545370 .659259 3.840822 1.282321 .888128
+  -.036111  .444444  .210185 .037037 2.071081 8.330552 .111872
+  }
+
+
+3dTetrahedron (3D) { ; by Alex Matulich
+  0.50  0  0  0  0.50  0  0  0  0.50  0.00  0.00  1.00  0.25
+  0.50  0  0  0  0.50  0  0  0  0.50  0.00  0.87 -0.50  0.25
+  0.50  0  0  0  0.50  0  0  0  0.50 -0.87 -0.50 -0.50  0.25
+  0.50  0  0  0  0.50  0  0  0  0.50  0.87 -0.50 -0.50  0.25
+}
+3d5Tetrahedron (3D) { ; by Alex Matulich
+  0.44  0  0  0  0.44  0  0  0  0.44  0.00  0.00  1.00  0.20
+  0.44  0  0  0  0.44  0  0  0  0.44  0.00  0.87 -0.50  0.20
+  0.44  0  0  0  0.44  0  0  0  0.44 -0.87 -0.50 -0.50  0.20
+  0.44  0  0  0  0.44  0  0  0  0.44  0.87 -0.50 -0.50  0.20
+  0.44  0  0  0  0.44  0  0  0  0.44  0.00  0.00  0.00  0.20
+}
+3dHexahedron (3D) { ; by Alex Matulich
+  0.44  0  0  0  0.44  0  0  0  0.44  0.00  0.00  0.90  0.20
+  0.44  0  0  0  0.44  0  0  0  0.44  0.87 -0.50  0.00  0.20
+  0.44  0  0  0  0.44  0  0  0  0.44 -0.87 -0.50  0.00  0.20
+  0.44  0  0  0  0.44  0  0  0  0.44  0.00  1.00  0.00  0.20
+  0.44  0  0  0  0.44  0  0  0  0.44  0.00  0.00 -0.90  0.20
+}
+3dCube (3d) { ; by Alex Matulich
+  0.35  0  0  0  0.35  0  0  0  0.35  1.00  1.00  1.00  0.12
+  0.35  0  0  0  0.35  0  0  0  0.35  1.00  1.00 -1.00  0.13
+  0.35  0  0  0  0.35  0  0  0  0.35  1.00 -1.00  1.00  0.12
+  0.35  0  0  0  0.35  0  0  0  0.35  1.00 -1.00 -1.00  0.13
+  0.35  0  0  0  0.35  0  0  0  0.35 -1.00  1.00  1.00  0.12
+  0.35  0  0  0  0.35  0  0  0  0.35 -1.00  1.00 -1.00  0.13
+  0.35  0  0  0  0.35  0  0  0  0.35 -1.00 -1.00  1.00  0.12
+  0.35  0  0  0  0.35  0  0  0  0.35 -1.00 -1.00 -1.00  0.13
+}
+3dOctahedron (3D) { ; by Alex Matulich
+  0.40  0  0  0  0.40  0  0  0  0.40  0.00  0.00  1.00  0.17
+  0.40  0  0  0  0.40  0  0  0  0.40  1.00  0.00  0.00  0.16
+  0.40  0  0  0  0.40  0  0  0  0.40  0.00  1.00  0.00  0.17
+  0.40  0  0  0  0.40  0  0  0  0.40 -1.00  0.00  0.00  0.17
+  0.40  0  0  0  0.40  0  0  0  0.40  0.00 -1.00  0.00  0.16
+  0.40  0  0  0  0.40  0  0  0  0.40  0.00  0.00 -1.00  0.17
+}
+3dDuodecahedron (3D) { ; by Alex Matulich
+  0.28  0  0  0  0.28  0  0  0  0.28  0.00  0.00  0.96  0.09
+  0.28  0  0  0  0.28  0  0  0  0.28  0.00  0.85  0.43  0.08
+  0.28  0  0  0  0.28  0  0  0  0.28  0.81  0.26  0.43  0.08
+  0.28  0  0  0  0.28  0  0  0  0.28 -0.81  0.26  0.43  0.09
+  0.28  0  0  0  0.28  0  0  0  0.28  0.50 -0.69  0.43  0.08
+  0.28  0  0  0  0.28  0  0  0  0.28 -0.50 -0.69  0.43  0.08
+  0.28  0  0  0  0.28  0  0  0  0.28  0.50  0.69 -0.43  0.09
+  0.28  0  0  0  0.28  0  0  0  0.28 -0.50  0.69 -0.43  0.08
+  0.28  0  0  0  0.28  0  0  0  0.28  0.81 -0.26 -0.43  0.08
+  0.28  0  0  0  0.28  0  0  0  0.28 -0.81 -0.26 -0.43  0.09
+  0.28  0  0  0  0.28  0  0  0  0.28  0.00 -0.85 -0.43  0.08
+  0.28  0  0  0  0.28  0  0  0  0.28  0.00  0.00 -0.96  0.08
+}
+
+fractint { ; by Pieter Branderhorst
+  0.00 -0.11  0.22  0.00 -6.25 4.84 0.06
+  0.11  0.02  0.00  0.11 -6.30 5.99 0.03
+  0.06  0.02  0.00  0.10 -6.25 4.51 0.02
+  0.00 -0.11  0.22  0.00 -4.34 4.84 0.06
+  0.08  0.00  0.00  0.11 -4.50 5.99 0.02
+  0.00  0.11 -0.08  0.00 -4.30 6.15 0.02
+ -0.09  0.00 -0.01 -0.13 -4.15 5.94 0.02
+  0.06  0.11 -0.13  0.00 -4.69 4.15 0.04
+  0.03 -0.11  0.23  0.11 -2.26 4.43 0.07
+  0.03  0.11 -0.25  0.00 -2.57 4.99 0.07
+  0.06  0.00  0.00  0.11 -2.40 4.46 0.02
+  0.00  0.11 -0.19  0.00 -1.62 4.99 0.06
+  0.09 -0.01  0.00  0.10 -0.58 2.96 0.03
+ -0.09  0.00  0.00 -0.11 -0.65 7.10 0.03
+  0.12  0.00 -0.00  0.11  1.24 6.00 0.03
+  0.00  0.11 -0.22  0.00  0.68 4.80 0.06
+ -0.12  0.00  0.00 -0.13  6.17 7.18 0.03
+  0.00 -0.11  0.22  0.00  6.78 4.84 0.06
+  0.00  0.08 -0.25  0.02  2.21 4.95 0.07
+  0.00 -0.11  0.22  0.00  4.10 4.84 0.06
+  0.00 -0.11  0.22  0.00  5.25 5.23 0.06
+  0.08  0.11 -0.25  0.00  3.57 4.99 0.08
+  }
diff --git a/examples/fltk_example.cpp b/examples/fltk_example.cpp
new file mode 100644
index 0000000..7670da3
--- /dev/null
+++ b/examples/fltk_example.cpp
@@ -0,0 +1,150 @@
+/***************************************************************************
+ * fltk_example.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include "mgl2/fltk.h"
+//-----------------------------------------------------------------------------
+#if defined(WIN32) || defined(_MSC_VER) || defined(__BORLANDC__)
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+void long_calculations()	// just delay which correspond to simulate calculations
+{
+#if defined(WIN32) || defined(_MSC_VER) || defined(__BORLANDC__)
+	Sleep(1000);
+#else
+	sleep(1);	// which can be very long
+#endif
+}
+//-----------------------------------------------------------------------------
+#if defined(PTHREAD_SAMPLE1)	// first variant of multi-threading usage of mglFLTK window
+mglFLTK *gr=NULL;
+void *calc(void *)
+{
+	mglPoint pnt;
+	for(int i=0;i<10;i++)		// do calculation
+	{
+		long_calculations();	// which can be very long
+		pnt.Set(2*mgl_rnd()-1,2*mgl_rnd()-1);
+		if(gr)
+		{
+			gr->Clf();			// make new drawing
+			gr->Line(mglPoint(),pnt,"Ar2");
+			char str[10] = "i=0";	str[2] = '0'+i;
+			gr->Puts(mglPoint(),str);
+			gr->Update();		// update window
+		}
+	}
+	exit(0);
+}
+int main(int argc,char **argv)
+{
+	mgl_textdomain(argv?argv[0]:NULL);
+	static pthread_t thr;
+	pthread_create(&thr,0,calc,0);
+	pthread_detach(thr);
+	gr = new mglFLTK;
+	gr->Run();	return 0;
+}
+#elif defined(PTHREAD_SAMPLE2)	// another variant of multi-threading usage of mglFLTK window. Work only if pthread was enabled for MathGL
+mglPoint pnt;	// some global variable for changeable data
+int main(int argc,char **argv)
+{
+	mgl_textdomain(argv?argv[0]:NULL);
+	mglFLTK gr("test");
+	gr.RunThr();	// <-- need MathGL version which use pthread
+	for(int i=0;i<10;i++)	// do calculation
+	{
+		long_calculations();// which can be very long
+		pnt.Set(2*mgl_rnd()-1,2*mgl_rnd()-1);
+		gr.Clf();			// make new drawing
+		gr.Line(mglPoint(),pnt,"Ar2");
+		char str[10] = "i=0";	str[3] = '0'+i;
+		gr->Puts(mglPoint(),str);
+		gr.Update();		// update window
+	}
+	return 0;	// finish calculations and close the window
+}
+#else		// just default samples
+//-----------------------------------------------------------------------------
+int test_wnd(mglGraph *gr);
+int sample(mglGraph *gr);
+int sample_1(mglGraph *gr);
+int sample_2(mglGraph *gr);
+int sample_3(mglGraph *gr);
+int sample_d(mglGraph *gr);
+//-----------------------------------------------------------------------------
+#if MGL_HAVE_PTHR_WIDGET
+class myDraw : public mglDraw
+{
+	mglPoint pnt;	// some variable for changeable data
+	long i;			// another variable to be shown
+	mglWnd *wnd;	// external window for plotting
+public:
+	myDraw(mglWnd *w=0) : mglDraw()	{	wnd=w;	}
+	void SetWnd(mglWnd *w)	{	wnd=w;	}
+	int Draw(mglGraph *gr)
+	{
+		gr->Line(mglPoint(),pnt,"Ar2");
+		char str[16];	snprintf(str,15,"i=%ld",i);
+		gr->Puts(mglPoint(),str);
+		return 0;
+	}
+	void Calc()
+	{
+		for(i=0;;i++)	// do calculation
+		{
+			Check();	// check if need pause
+			long_calculations();// which can be very long
+			pnt.Set(2*mgl_rnd()-1,2*mgl_rnd()-1);
+			if(wnd)	wnd->Update();
+		}
+	}
+} dr;
+#endif
+//-----------------------------------------------------------------------------
+int main(int argc,char **argv)
+{
+	mgl_textdomain(argv?argv[0]:NULL,"");
+	mglFLTK *gr;
+	char key = 0;
+	if(argc>1)	key = argv[1][0]!='-' ? argv[1][0]:argv[1][1];
+	else	printf("You may specify argument '1', '2', '3', 'd' for viewing examples of 1d, 2d, 3d, dual plotting,\nor 'm' for multi-threading sample.\n");
+	switch(key)
+	{
+	case '0':	gr = new mglFLTK((mglDraw *)NULL,"1D plots");
+				gr->Rotate(40,60);	gr->Box();	gr->Light(true);
+				gr->FSurf("sin(4*pi*x*y)");	gr->Update();	break;
+	case '1':	gr = new mglFLTK(sample_1,"1D plots");	break;
+	case '2':	gr = new mglFLTK(sample_2,"2D plots");	break;
+	case '3':	gr = new mglFLTK(sample_3,"3D plots");	break;
+	case 'd':	gr = new mglFLTK(sample_d,"Dual plots");break;
+	case 't':	gr = new mglFLTK(test_wnd,"Testing");	break;
+	case 'f':	gr = new mglFLTK("Frame drawing");
+				gr->NewFrame();	gr->Box();	gr->EndFrame();	break;
+#if MGL_HAVE_PTHR_WIDGET
+	case 'm':	gr = new mglFLTK(&dr,"Multi-threading test");
+	dr.SetWnd(gr);	dr.Run();	break;
+#endif
+	default:	gr = new mglFLTK(sample,"Drop and waves");	break;
+	}
+	gr->Run();	return 0;
+}
+#endif
+//-----------------------------------------------------------------------------
diff --git a/examples/full_test.cpp b/examples/full_test.cpp
new file mode 100644
index 0000000..e9821e0
--- /dev/null
+++ b/examples/full_test.cpp
@@ -0,0 +1,560 @@
+/***************************************************************************
+ * full_test.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <time.h>
+#include <locale.h>
+#include <time.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#include "mgl2/mgl.h"
+#include "mgl2/font.h"
+#include "mgl2/eval.h"
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_create_cpp_font(HMGL gr, const wchar_t *how);
+long MGL_EXPORT mgl_check_tex_table();
+//-----------------------------------------------------------------------------
+struct mglSample	/// Structure for list of samples
+{
+	const char *name;
+	void (*func)(mglGraph*);
+	const char *mgl;
+};
+extern mglSample samp[];
+extern const char *mmgl_dat_prepare;
+//-----------------------------------------------------------------------------
+int MGL_LOCAL_PURE mgl_cmd_smp(const void *a, const void *b)
+{
+	const mglSample *aa = (const mglSample *)a;
+	const mglSample *bb = (const mglSample *)b;
+	return strcmp(aa->name, bb->name);
+}
+//-----------------------------------------------------------------------------
+int type = 0;
+int dotest  = 0;
+int width  = 800;
+int height = 600;
+int big  = 0;
+int srnd = 0;
+int use_mgl = 0;
+int verbose = 0;
+int quality  = MGL_DRAW_NORM;
+//-----------------------------------------------------------------------------
+void mgls_prepare1d(mglData *y, mglData *y1=0, mglData *y2=0, mglData *x1=0, mglData *x2=0);
+void mgls_prepare2d(mglData *a, mglData *b=0, mglData *v=0);
+void mgls_prepare3d(mglData *a, mglData *b=0);
+void mgls_prepare2v(mglData *a, mglData *b);
+void mgls_prepare3v(mglData *ex, mglData *ey, mglData *ez);
+//-----------------------------------------------------------------------------
+void save(mglGraph *gr,const char *name,const char *suf);
+void test(mglGraph *gr)
+{
+	mglParse par;
+	par.Execute(gr,"text 0 -0.2 'abcde'\ntext 0 0 'abcde'[2]\n"
+	"text 0 0.2 'abcde'+2\ntext 0 0.4 'abcde',2\ntext 0 0.6 'abcde',2,'k'"
+	"text 0 0.8 'abcde',2,'k'+1\ntext 0 1 'abcde',2,'k'[5]\ntext 0 1 'abcde''k'[5]");
+	return;
+
+	gr->SubPlot(2,2,0);	gr->Axis();
+	gr->SubPlot(2,2,1);	gr->Rotate(40,60);	gr->Axis();
+	gr->SetRotatedText(false);	gr->SubPlot(2,2,2);	gr->Axis();
+	gr->SubPlot(2,2,3);	gr->Rotate(40,60);	gr->Axis();	return;
+	mglData a;	a.SetList(5,0.,1.,0.,1.,-1.,2.);
+	gr->Plot(a);
+	return;
+	par.Execute(gr,"call 'test' -1\n func 'test' 1\nline $1 0 1 1 'b'\nreturn\n");
+//	par.Execute(gr,"load '/home/balakin/mathgl-code/mathgl-2x/build/examples/libmgl_module.so':baxis\n");
+//	par.Execute(gr,"subplot 1 1 0:#rotate 40 60\nperspective 1.22:box:axis\n");
+	return;
+}
+//-----------------------------------------------------------------------------
+static struct option longopts[] =
+{
+	{ "big",	no_argument,	&big,		1 },
+	{ "web",	no_argument,	&big,		2 },
+	{ "mini",	no_argument,	&big,		3 },
+	{ "help",	no_argument,	NULL,		'?' },
+	{ "height",	required_argument,	NULL,	'h' },
+	{ "kind",	required_argument,	NULL,	'k' },
+	{ "list",	no_argument,	NULL,		'l' },
+	{ "mgl",	no_argument,	&use_mgl,	1 },
+	{ "srnd",	no_argument,	&srnd,		1 },
+
+	{ "png",	no_argument,	&type,		0 },
+	{ "eps",	no_argument,	&type,		1 },
+	{ "svg",	no_argument,	&type,		2 },
+	{ "solid",	no_argument,	&type,		3 },
+	{ "jpeg",	no_argument,	&type,		4 },
+	{ "prc",	no_argument,	&type,		5 },
+	{ "gif",	no_argument,	&type,		6 },
+	{ "none",	no_argument,	&type,		7 },
+	{ "bps",	no_argument,	&type,		8 },
+	{ "pdf",	no_argument,	&type,		9 },
+	{ "obj_old",no_argument,	&type,		10 },
+	{ "obj",	no_argument,	&type,		11 },
+	{ "off",	no_argument,	&type,		12 },
+	{ "stl",	no_argument,	&type,		13 },
+	{ "tex",	no_argument,	&type,		14 },
+	{ "json",	no_argument,	&type,		15 },
+	{ "jsonz",	no_argument,	&type,		16 },
+	{ "docs",	no_argument,	&type,		17 },
+
+	{ "test",	no_argument,	&dotest,	1 },
+	{ "font",	no_argument,	&dotest,	2 },
+	{ "time",	no_argument,	&dotest,	3 },
+	{ "fexport",no_argument,	&dotest,	4 },
+	{ "textbl",	no_argument,	&dotest,	5 },
+
+	{ "thread",	required_argument,	NULL,	't' },
+	{ "verbose",no_argument,	&verbose,	1 },
+	{ "width",	required_argument,	NULL,	'w' },
+	{ "quality",required_argument,	NULL,	'q' },
+	{ NULL,		0,				NULL,		0 }
+};
+//-----------------------------------------------------------------------------
+void usage()
+{
+	puts (
+//		"--png		- output png\n"
+		"--width=num	- png picture width\n"
+		"--height=num	- png picture height\n"
+		"--mini		- png picture is 200x150\n"
+		"--big		- png picture is 1920x1440\n"
+		"--web		- png picture is 640x480\n"
+		"--prc		- output prc\n"
+		"--pdf		- output pdf\n"
+		"--eps		- output EPS\n"
+		"--tex		- output LaTeX\n"
+		"--jpeg		- output JPEG\n"
+		"--json		- output JSON\n"
+		"--jsonz		- output JSONz\n"
+		"--solid	- output solid PNG\n"
+		"--svg		- output SVG\n"
+		"--obj		- output obj/mtl\n"
+		"--obj_old	- output obj/mtl in old way\n"
+		"--off		- output off\n"
+		"--stl		- output stl\n"
+		"--docs		- output in png, prc/pdf and json\n"
+		"--none		- none output\n"
+		"--srnd		- use the same random numbers in any run\n"
+		"--list		- print list of sample names\n"
+		"--kind=name	- produce only this sample\n"
+		"--thread=num	- number of threads used\n"
+		"--mgl		- use MGL scripts for samples\n"
+		"--test		- run in test mode\n"
+		"--time		- measure execution time for all samples\n"
+		"--font		- write current font as C++ file\n"
+		"--quality=val	- use specified quality for plot(s)\n"
+		"--fexport	- test most of output formats\n"
+	);
+}
+//-----------------------------------------------------------------------------
+void save(mglGraph *gr,const char *name,const char *suf="")
+{
+	//	return;
+	char buf[128];
+	switch(type)
+	{
+		case 1:	// EPS
+			snprintf(buf,128,"%s%s.eps",name,suf);
+			gr->WriteEPS(buf);
+			break;
+		case 2:	// SVG
+			snprintf(buf,128,"%s%s.svg",name,suf);
+			gr->WriteSVG(buf);	break;
+		case 3:	// PNG
+			snprintf(buf,128,"%s%s.png",name,suf);
+			gr->WritePNG(buf,0,true);	break;
+		case 4:	// JPEG
+			snprintf(buf,128,"%s%s.jpg",name,suf);
+			gr->WriteJPEG(buf);	break;
+		case 5:	// PRC
+			snprintf(buf,128,"%s%s.prc",name,suf);
+			gr->WritePRC(buf,"",false);	break;
+		case 6:	// GIF
+			snprintf(buf,128,"%s%s.gif",name,suf);
+			gr->WriteGIF(buf);	break;
+		case 7:	gr->Finish();	// none
+			break;
+		case 8:	// EPS to PNG
+			snprintf(buf,128,"%s%s.png",name,suf);
+			gr->WritePNG(buf,0,false);
+			break;
+ 		case 9:	// PDF
+			snprintf(buf,128,"%s%s.prc",name,suf);
+			gr->WritePRC(buf);	remove(buf);	break;
+		case 10:	// old OBJ
+			snprintf(buf,128,"%s%s.obj",name,suf);
+			gr->WriteOBJold(buf);	break;
+		case 11:	// OBJ
+			snprintf(buf,128,"%s%s.obj",name,suf);
+			gr->WriteOBJ(buf);	break;
+		case 12:	// OFF
+			snprintf(buf,128,"%s%s.off",name,suf);
+			gr->WriteOFF(buf);	break;
+		case 13:	// STL
+			snprintf(buf,128,"%s%s.stl",name,suf);
+			gr->WriteSTL(buf);	break;
+		case 14:	// TeX
+			snprintf(buf,128,"%s%s.tex",name,suf);
+			gr->WriteTEX(buf);	break;
+		case 15:	// JSON
+			snprintf(buf,128,"%s%s.json",name,suf);
+			gr->WriteJSON(buf);	break;
+		case 16:	// JSON
+			snprintf(buf,128,"%s%s.jsonz",name,suf);
+			gr->WriteJSON(buf,"",true);	break;
+		case 17:	// PNG + JSON + PDF
+			snprintf(buf,128,"%s%s.png",name,suf);
+			gr->WritePNG(buf,0,true);
+			snprintf(buf,128,"%s%s.json",name,suf);
+			gr->WriteJSON(buf);
+			gr->SetSize(height,height,false);
+			snprintf(buf,128,"%s%s.prc",name,suf);
+			gr->WritePRC(buf);	remove(buf);	break;
+		default:// PNG (no alpha)
+#if MGL_HAVE_PNG
+			snprintf(buf,128,"%s%s.png",name,suf);
+			gr->WritePNG(buf,0,false);	break;
+#else
+			snprintf(buf,128,"%s%s.bmp",name,suf);
+			gr->WriteBMP(buf);	break;
+#endif
+	}
+}
+//-----------------------------------------------------------------------------
+void smgl_fexport(mglGraph *gr)	// test file export
+{
+	gr->SubPlot(3,2,0);
+	double d,x1,x2,x0,y=0.95;
+	d=0.3, x0=0.2, x1=0.5, x2=0.6;
+	gr->Line(mglPoint(x0,1-0*d),mglPoint(x1,1-0*d),"k-");	gr->Puts(mglPoint(x2,y-0*d),"Solid '-'",":rL");
+	gr->Line(mglPoint(x0,1-1*d),mglPoint(x1,1-1*d),"k|");	gr->Puts(mglPoint(x2,y-1*d),"Long Dash '|'",":rL");
+	gr->Line(mglPoint(x0,1-2*d),mglPoint(x1,1-2*d),"k;");	gr->Puts(mglPoint(x2,y-2*d),"Dash ';'",":rL");
+	gr->Line(mglPoint(x0,1-3*d),mglPoint(x1,1-3*d),"k=");	gr->Puts(mglPoint(x2,y-3*d),"Small dash '='",":rL");
+	gr->Line(mglPoint(x0,1-4*d),mglPoint(x1,1-4*d),"kj");	gr->Puts(mglPoint(x2,y-4*d),"Dash-dot 'j'",":rL");
+	gr->Line(mglPoint(x0,1-5*d),mglPoint(x1,1-5*d),"ki");	gr->Puts(mglPoint(x2,y-5*d),"Small dash-dot 'i'",":rL");
+	gr->Line(mglPoint(x0,1-6*d),mglPoint(x1,1-6*d),"k:");	gr->Puts(mglPoint(x2,y-6*d),"Dots ':'",":rL");
+	gr->Line(mglPoint(x0,1-7*d),mglPoint(x1,1-7*d),"k ");	gr->Puts(mglPoint(x2,y-7*d),"None ' '",":rL");
+
+	d=0.25; x1=-1; x0=-0.8;	y = -0.05;
+	gr->Mark(mglPoint(x1,5*d),"k.");	gr->Puts(mglPoint(x0,y+5*d),"'.'",":rL");
+	gr->Mark(mglPoint(x1,4*d),"k+");	gr->Puts(mglPoint(x0,y+4*d),"'+'",":rL");
+	gr->Mark(mglPoint(x1,3*d),"kx");	gr->Puts(mglPoint(x0,y+3*d),"'x'",":rL");
+	gr->Mark(mglPoint(x1,2*d),"k*");	gr->Puts(mglPoint(x0,y+2*d),"'*'",":rL");
+	gr->Mark(mglPoint(x1,d),"ks");		gr->Puts(mglPoint(x0,y+d),"'s'",":rL");
+	gr->Mark(mglPoint(x1,0),"kd");		gr->Puts(mglPoint(x0,y),"'d'",":rL");
+	gr->Mark(mglPoint(x1,-d,0),"ko");	gr->Puts(mglPoint(x0,y-d),"'o'",":rL");
+	gr->Mark(mglPoint(x1,-2*d,0),"k^");	gr->Puts(mglPoint(x0,y-2*d),"'\\^'",":rL");
+	gr->Mark(mglPoint(x1,-3*d,0),"kv");	gr->Puts(mglPoint(x0,y-3*d),"'v'",":rL");
+	gr->Mark(mglPoint(x1,-4*d,0),"k<");	gr->Puts(mglPoint(x0,y-4*d),"'<'",":rL");
+	gr->Mark(mglPoint(x1,-5*d,0),"k>");	gr->Puts(mglPoint(x0,y-5*d),"'>'",":rL");
+
+	d=0.25; x1=-0.5; x0=-0.3;	y = -0.05;
+	gr->Mark(mglPoint(x1,5*d),"k#.");	gr->Puts(mglPoint(x0,y+5*d),"'\\#.'",":rL");
+	gr->Mark(mglPoint(x1,4*d),"k#+");	gr->Puts(mglPoint(x0,y+4*d),"'\\#+'",":rL");
+	gr->Mark(mglPoint(x1,3*d),"k#x");	gr->Puts(mglPoint(x0,y+3*d),"'\\#x'",":rL");
+	gr->Mark(mglPoint(x1,2*d),"k#*");	gr->Puts(mglPoint(x0,y+2*d),"'\\#*'",":rL");
+	gr->Mark(mglPoint(x1,d),"k#s");		gr->Puts(mglPoint(x0,y+d),"'\\#s'",":rL");
+	gr->Mark(mglPoint(x1,0),"k#d");		gr->Puts(mglPoint(x0,y),"'\\#d'",":rL");
+	gr->Mark(mglPoint(x1,-d,0),"k#o");	gr->Puts(mglPoint(x0,y-d),"'\\#o'",":rL");
+	gr->Mark(mglPoint(x1,-2*d,0),"k#^");	gr->Puts(mglPoint(x0,y-2*d),"'\\#\\^'",":rL");
+	gr->Mark(mglPoint(x1,-3*d,0),"k#v");	gr->Puts(mglPoint(x0,y-3*d),"'\\#v'",":rL");
+	gr->Mark(mglPoint(x1,-4*d,0),"k#<");	gr->Puts(mglPoint(x0,y-4*d),"'\\#<'",":rL");
+	gr->Mark(mglPoint(x1,-5*d,0),"k#>");	gr->Puts(mglPoint(x0,y-5*d),"'\\#>'",":rL");
+
+	gr->SubPlot(3,2,1);
+	double a=0.1,b=0.4,c=0.5;
+	gr->Line(mglPoint(a,1),mglPoint(b,1),"k-A");		gr->Puts(mglPoint(c,1),"Style 'A' or 'A\\_'",":rL");
+	gr->Line(mglPoint(a,0.8),mglPoint(b,0.8),"k-V");	gr->Puts(mglPoint(c,0.8),"Style 'V' or 'V\\_'",":rL");
+	gr->Line(mglPoint(a,0.6),mglPoint(b,0.6),"k-K");	gr->Puts(mglPoint(c,0.6),"Style 'K' or 'K\\_'",":rL");
+	gr->Line(mglPoint(a,0.4),mglPoint(b,0.4),"k-I");	gr->Puts(mglPoint(c,0.4),"Style 'I' or 'I\\_'",":rL");
+	gr->Line(mglPoint(a,0.2),mglPoint(b,0.2),"k-D");	gr->Puts(mglPoint(c,0.2),"Style 'D' or 'D\\_'",":rL");
+	gr->Line(mglPoint(a,0),mglPoint(b,0),"k-S");		gr->Puts(mglPoint(c,0),"Style 'S' or 'S\\_'",":rL");
+	gr->Line(mglPoint(a,-0.2),mglPoint(b,-0.2),"k-O");	gr->Puts(mglPoint(c,-0.2),"Style 'O' or 'O\\_'",":rL");
+	gr->Line(mglPoint(a,-0.4),mglPoint(b,-0.4),"k-T");	gr->Puts(mglPoint(c,-0.4),"Style 'T' or 'T\\_'",":rL");
+	gr->Line(mglPoint(a,-0.6),mglPoint(b,-0.6),"k-_");	gr->Puts(mglPoint(c,-0.6),"Style '\\_' or none",":rL");
+	gr->Line(mglPoint(a,-0.8),mglPoint(b,-0.8),"k-AS");	gr->Puts(mglPoint(c,-0.8),"Style 'AS'",":rL");
+	gr->Line(mglPoint(a,-1),mglPoint(b,-1),"k-_A");		gr->Puts(mglPoint(c,-1),"Style '\\_A'",":rL");
+
+	a=-1;	b=-0.7;	c=-0.6;
+	gr->Line(mglPoint(a,1),mglPoint(b,1),"kAA");		gr->Puts(mglPoint(c,1),"Style 'AA'",":rL");
+	gr->Line(mglPoint(a,0.8),mglPoint(b,0.8),"kVV");	gr->Puts(mglPoint(c,0.8),"Style 'VV'",":rL");
+	gr->Line(mglPoint(a,0.6),mglPoint(b,0.6),"kKK");	gr->Puts(mglPoint(c,0.6),"Style 'KK'",":rL");
+	gr->Line(mglPoint(a,0.4),mglPoint(b,0.4),"kII");	gr->Puts(mglPoint(c,0.4),"Style 'II'",":rL");
+	gr->Line(mglPoint(a,0.2),mglPoint(b,0.2),"kDD");	gr->Puts(mglPoint(c,0.2),"Style 'DD'",":rL");
+	gr->Line(mglPoint(a,0),mglPoint(b,0),"kSS");		gr->Puts(mglPoint(c,0),"Style 'SS'",":rL");
+	gr->Line(mglPoint(a,-0.2),mglPoint(b,-0.2),"kOO");	gr->Puts(mglPoint(c,-0.2),"Style 'OO'",":rL");
+	gr->Line(mglPoint(a,-0.4),mglPoint(b,-0.4),"kTT");	gr->Puts(mglPoint(c,-0.4),"Style 'TT'",":rL");
+	gr->Line(mglPoint(a,-0.6),mglPoint(b,-0.6),"k-__");	gr->Puts(mglPoint(c,-0.6),"Style '\\_\\_'",":rL");
+	gr->Line(mglPoint(a,-0.8),mglPoint(b,-0.8),"k-VA");	gr->Puts(mglPoint(c,-0.8),"Style 'VA'",":rL");
+	gr->Line(mglPoint(a,-1),mglPoint(b,-1),"k-AV");		gr->Puts(mglPoint(c,-1),"Style 'AV'",":rL");
+
+	gr->SubPlot(3,2,2);
+	//#LENUQ
+	gr->FaceZ(mglPoint(-1,	-1), 0.4, 0.3, "L#");	gr->Puts(mglPoint(-0.8,-0.9), "L", "w:C", -1.4);
+	gr->FaceZ(mglPoint(-0.6,-1), 0.4, 0.3, "E#");	gr->Puts(mglPoint(-0.4,-0.9), "E", "w:C", -1.4);
+	gr->FaceZ(mglPoint(-0.2,-1), 0.4, 0.3, "N#");	gr->Puts(mglPoint(0,  -0.9), "N", "w:C", -1.4);
+	gr->FaceZ(mglPoint(0.2,	-1), 0.4, 0.3, "U#");	gr->Puts(mglPoint(0.4,-0.9), "U", "w:C", -1.4);
+	gr->FaceZ(mglPoint(0.6,	-1), 0.4, 0.3, "Q#");	gr->Puts(mglPoint(0.8,-0.9), "Q", "w:C", -1.4);
+	//#lenuq
+	gr->FaceZ(mglPoint(-1,	-0.7), 0.4, 0.3, "l#");	gr->Puts(mglPoint(-0.8,-0.6), "l", "k:C", -1.4);
+	gr->FaceZ(mglPoint(-0.6,-0.7), 0.4, 0.3, "e#");	gr->Puts(mglPoint(-0.4,-0.6), "e", "k:C", -1.4);
+	gr->FaceZ(mglPoint(-0.2,-0.7), 0.4, 0.3, "n#");	gr->Puts(mglPoint(0,  -0.6), "n", "k:C", -1.4);
+	gr->FaceZ(mglPoint(0.2,	-0.7), 0.4, 0.3, "u#");	gr->Puts(mglPoint(0.4,-0.6), "u", "k:C", -1.4);
+	gr->FaceZ(mglPoint(0.6,	-0.7), 0.4, 0.3, "q#");	gr->Puts(mglPoint(0.8,-0.6), "q", "k:C", -1.4);
+	//#CMYkP
+	gr->FaceZ(mglPoint(-1,	-0.4), 0.4, 0.3, "C#");	gr->Puts(mglPoint(-0.8,-0.3), "C", "w:C", -1.4);
+	gr->FaceZ(mglPoint(-0.6,-0.4), 0.4, 0.3, "M#");	gr->Puts(mglPoint(-0.4,-0.3), "M", "w:C", -1.4);
+	gr->FaceZ(mglPoint(-0.2,-0.4), 0.4, 0.3, "Y#");	gr->Puts(mglPoint(0,  -0.3), "Y", "w:C", -1.4);
+	gr->FaceZ(mglPoint(0.2,	-0.4), 0.4, 0.3, "k#");	gr->Puts(mglPoint(0.4,-0.3), "k", "w:C", -1.4);
+	gr->FaceZ(mglPoint(0.6,	-0.4), 0.4, 0.3, "P#");	gr->Puts(mglPoint(0.8,-0.3), "P", "w:C", -1.4);
+	//#cmywp
+	gr->FaceZ(mglPoint(-1,	-0.1), 0.4, 0.3, "c#");	gr->Puts(mglPoint(-0.8, 0), "c", "k:C", -1.4);
+	gr->FaceZ(mglPoint(-0.6,-0.1), 0.4, 0.3, "m#");	gr->Puts(mglPoint(-0.4, 0), "m", "k:C", -1.4);
+	gr->FaceZ(mglPoint(-0.2,-0.1), 0.4, 0.3, "y#");	gr->Puts(mglPoint(0,   0), "y", "k:C", -1.4);
+	gr->FaceZ(mglPoint(0.2,	-0.1), 0.4, 0.3, "w#");	gr->Puts(mglPoint(0.4, 0), "w", "k:C", -1.4);
+	gr->FaceZ(mglPoint(0.6,	-0.1), 0.4, 0.3, "p#");	gr->Puts(mglPoint(0.8, 0), "p", "k:C", -1.4);
+	//#BGRHW
+	gr->FaceZ(mglPoint(-1,	0.2), 0.4, 0.3, "B#");	gr->Puts(mglPoint(-0.8, 0.3), "B", "w:C", -1.4);
+	gr->FaceZ(mglPoint(-0.6,0.2), 0.4, 0.3, "G#");	gr->Puts(mglPoint(-0.4, 0.3), "G", "w:C", -1.4);
+	gr->FaceZ(mglPoint(-0.2,0.2), 0.4, 0.3, "R#");	gr->Puts(mglPoint(0,   0.3), "R", "w:C", -1.4);
+	gr->FaceZ(mglPoint(0.2,	0.2), 0.4, 0.3, "H#");	gr->Puts(mglPoint(0.4, 0.3), "H", "w:C", -1.4);
+	gr->FaceZ(mglPoint(0.6,	0.2), 0.4, 0.3, "W#");	gr->Puts(mglPoint(0.8, 0.3), "W", "w:C", -1.4);
+	//#bgrhw
+	gr->FaceZ(mglPoint(-1,	0.5), 0.4, 0.3, "b#");	gr->Puts(mglPoint(-0.8, 0.6), "b", "k:C", -1.4);
+	gr->FaceZ(mglPoint(-0.6,0.5), 0.4, 0.3, "g#");	gr->Puts(mglPoint(-0.4, 0.6), "g", "k:C", -1.4);
+	gr->FaceZ(mglPoint(-0.2,0.5), 0.4, 0.3, "r#");	gr->Puts(mglPoint(0,   0.6), "r", "k:C", -1.4);
+	gr->FaceZ(mglPoint(0.2,	0.5), 0.4, 0.3, "h#");	gr->Puts(mglPoint(0.4, 0.6), "h", "k:C", -1.4);
+	gr->FaceZ(mglPoint(0.6,	0.5), 0.4, 0.3, "w#");	gr->Puts(mglPoint(0.8, 0.6), "w", "k:C", -1.4);
+	//#brighted
+	gr->FaceZ(mglPoint(-1,	0.8), 0.4, 0.3, "{r1}#");	gr->Puts(mglPoint(-0.8, 0.9), "\\{r1\\}", "w:C", -1.4);
+	gr->FaceZ(mglPoint(-0.6,0.8), 0.4, 0.3, "{r3}#");	gr->Puts(mglPoint(-0.4, 0.9), "\\{r3\\}", "w:C", -1.4);
+	gr->FaceZ(mglPoint(-0.2,0.8), 0.4, 0.3, "{r5}#");	gr->Puts(mglPoint(0,   0.9), "\\{r5\\}", "k:C", -1.4);
+	gr->FaceZ(mglPoint(0.2,	0.8), 0.4, 0.3, "{r7}#");	gr->Puts(mglPoint(0.4, 0.9), "\\{r7\\}", "k:C", -1.4);
+	gr->FaceZ(mglPoint(0.6,	0.8), 0.4, 0.3, "{r9}#");	gr->Puts(mglPoint(0.8, 0.9), "\\{r9\\}", "k:C", -1.4);
+	// HEX
+	gr->FaceZ(mglPoint(-1, -1.3), 1, 0.3, "{xff9966}#");	gr->Puts(mglPoint(-0.5,-1.2), "\\{xff9966\\}", "k:C", -1.4);
+	gr->FaceZ(mglPoint(0,  -1.3), 1, 0.3, "{x83CAFF}#");	gr->Puts(mglPoint( 0.5,-1.2), "\\{x83CAFF\\}", "k:C", -1.4);
+
+	gr->SubPlot(3,2,3);
+	char stl[3]="r1", txt[4]="'1'";
+	for(int i=0;i<10;i++)
+	{
+		txt[1]=stl[1]='0'+i;
+		gr->Line(mglPoint(-1,0.2*i-1),mglPoint(1,0.2*i-1),stl);
+		gr->Puts(mglPoint(1.05,0.2*i-1),txt,":L");
+	}
+
+	gr->SubPlot(3,2,4);	gr->Title("TriPlot sample");	gr->Rotate(50,60);
+	double t[] = {0,1,2, 0,1,3, 0,2,3, 1,2,3};
+	double xt[] = {-1,1,0,0}, yt[] = {-1,-1,1,0}, zt[] = {-1,-1,-1,1};
+	mglData tt(4,3,t), uu(4,xt), vv(4,yt), ww(4,zt);
+	gr->TriPlot(tt,uu,vv,ww,"b");
+	gr->TriPlot(tt,uu,vv,ww,"k#");
+
+	gr->SubPlot(3,2,5);
+	mglData r(4);	r.Fill(1,4);
+	gr->SetRanges(1,4,1,4);	gr->Axis();
+	gr->Mark(r,r,"s");
+	gr->Plot(r,"b");
+
+	gr->WriteJPEG("fexport.jpg");
+//	gr->WritePNG("fexport.png");
+	gr->WriteBMP("fexport.bmp");
+	gr->WriteTGA("fexport.tga");
+	gr->WriteEPS("fexport.eps");
+	gr->WriteSVG("fexport.svg");
+	gr->WriteGIF("fexport.gif");
+
+	gr->WriteXYZ("fexport.xyz");
+	gr->WriteSTL("fexport.stl");
+	gr->WriteOFF("fexport.off");
+	gr->WriteTEX("fexport.tex");
+	gr->WriteOBJ("fexport.obj");
+	gr->WritePRC("fexport.prc");
+	gr->WriteJSON("fexport.json");
+
+	gr->ExportMGLD("fexport.mgld");
+	gr->Clf();
+	gr->ImportMGLD("fexport.mgld");
+}
+//-----------------------------------------------------------------------------
+int main(int argc,char **argv)
+{
+// const char *f = strrchr(argv[0],'/');
+// std::string p(argv[0],f-argv[0]);
+// printf("getcwd = '%s', argv = '%s', path = '%s', inst = '%s'\n", getcwd(NULL,0), argv[0], p.c_str(), MGL_INSTALL_DIR);
+// fflush(stdout);
+
+	mgl_textdomain(argv?argv[0]:NULL,"");
+	mgl_suppress_warn(true);
+	const char *suf = "";
+	char name[256]="", *tmp;
+	int ch;
+	time_t st,en;	time(&st);
+	mglGraph *gr = NULL;
+	mglSample *s=samp;
+	while(( ch = getopt_long_only(argc, argv, "", longopts, NULL)) != -1)
+		switch(ch)
+		{
+			case 0:		break;
+			case 'w':	width =atoi(optarg);	break;
+			case 'h':	height=atoi(optarg);	break;
+			case 'q':	quality =atoi(optarg);	break;
+			case 'k':	strncpy(name, optarg,256);
+						tmp=strchr(name,'.');	if(tmp)	*tmp=0;
+						tmp=strchr(name,'-');	if(tmp)	*tmp=0;
+						break;
+			case 't':	mgl_set_num_thr(atoi(optarg));	break;
+			case 'l':
+				while(s->name[0])	{	printf("%s ",s->name);	s++;	}
+				printf("\n");	return 0;
+			case '?':
+			default:	usage();	return 0;
+		}
+
+	if(dotest==1)	printf("Global (before):%s\n",mglGlobalMess.c_str());
+	gr = new mglGraph;
+	if(	type==11|| type==12|| type==5 || type==9)	width=height;
+	switch(big)
+	{
+	case 1:	gr->SetSize(1920,1440);	suf = "-lg";	break;
+	case 2:	gr->SetSize(640,480);	break;
+	case 3:	gr->SetSize(192,144);	suf = "-sm";	break;
+	default:	gr->SetSize(width,height);
+	}
+	gr->SetQuality(quality);
+
+	if(dotest==1)
+	{
+		mgl_set_test_mode(true);	test(gr);
+		time(&en);	printf("time is %g sec\n",difftime(en,st));
+#if MGL_HAVE_PNG
+		gr->WritePNG("test.png","",false);
+#else
+		gr->WriteBMP("test.bmp");
+#endif
+		gr->WriteSVG("test.svg");
+		gr->WriteEPS("test.eps");
+		printf("Messages:%s\n",gr->Message());
+		printf("Global:%s\n",mglGlobalMess.c_str());
+		delete gr;	return 0;
+	}
+	else if(dotest==2)	// NOTE mgl_gen_fnt[###][6] have to be updated if new glyphs will be added to built-in font
+	{	mgl_create_cpp_font(gr->Self(), L"!-~,¡-ÿ,̀-̏,Α-ω,ϑ,ϕ,ϖ,ϰ,ϱ,ϵ,А-я,ℏ,ℑ,ℓ,ℜ,←-↙,∀-∯,≠-≯,⟂");
+		delete gr;	return 0;	}
+	else if(dotest==3)
+	{
+		int qual[7]={0,1,2,4,5,6,8};
+		size_t ll=strlen(mmgl_dat_prepare)+1;
+		mglParse par;
+		par.AllowSetSize(true);
+		FILE *fp = fopen(big?"time_big.texi":"time.texi","w");
+		fprintf(fp,"@multitable @columnfractions .16 .12 .12 .12 .12 .12 .12 .12\n");
+		fprintf(fp,"@headitem Name");
+		for(int i=0;i<7;i++)	fprintf(fp," @tab q=%d",qual[i]);
+		clock_t beg,end;
+		while(s->name[0])	// all samples
+		{
+			char *buf = new char[strlen(s->mgl)+ll];
+			strcpy(buf,s->mgl);	strcat(buf,mmgl_dat_prepare);
+			fprintf(fp,"\n at item %s",s->name);
+
+			printf("%s",s->name);
+			for(int i=0;i<7;i++)
+			{
+				gr->DefaultPlotParam();
+				gr->SetQuality(qual[i]);	gr->Clf();
+				beg = clock();
+				if(!use_mgl)	s->func(gr);
+				else 	par.Execute(gr,buf);
+				gr->Finish();
+				end = clock();
+				fprintf(fp," @tab %.3g",double(end-beg)/CLOCKS_PER_SEC);
+				printf("\t%d->%g",qual[i],double(end-beg)/CLOCKS_PER_SEC);
+				fflush(fp);	fflush(stdout);
+			}
+			printf("\n");	delete []buf;	s++;
+		}
+		fprintf(fp,"\n at end multitable\n");	fclose(fp);
+	}
+	else if(dotest==4)
+	{	smgl_fexport(gr);	delete gr;	return 0;	}
+	else if(dotest==5)
+	{
+		mgl_check_tex_table();
+		delete gr;	return 0;
+	}
+
+	if(type==15 || type==16)	big=3;	// save mini version for json
+
+	if(srnd)	mgl_srnd(1);
+	gr->VertexColor(false);	gr->Compression(false);
+	if(name[0]==0)
+	{
+		while(s->name[0])	// all samples
+		{
+			gr->DefaultPlotParam();	gr->Clf();
+			if(use_mgl)
+			{
+				mglParse par;
+				par.AllowSetSize(true);
+				char *buf = new char[strlen(s->mgl)+strlen(mmgl_dat_prepare)+1];
+				strcpy(buf,s->mgl);		strcat(buf,mmgl_dat_prepare);
+				if(type!=7)	printf("\n-------\n%s\n-------\n",verbose?buf:s->mgl);
+				par.Execute(gr,buf);	delete []buf;
+				const char *mess = gr->Message();
+				if(*mess)	printf("Warnings: %s\n-------\n",mess);
+			}
+			else	s->func(gr);
+			save(gr, s->name, suf);
+			printf("%s ",s->name);	fflush(stdout);	s++;
+			gr->SetQuality(quality);
+		}
+		printf("\n");
+	}
+	else	// manual sample
+	{
+		mglSample tst;	tst.name=name;
+		int i=0;
+		for(i=0;samp[i].name[0];i++);	// determine the number of samples
+		s = (mglSample *) bsearch(&tst, samp, i, sizeof(mglSample), mgl_cmd_smp);
+		if(s)
+		{
+			gr->DefaultPlotParam();	gr->Clf();
+			if(use_mgl)
+			{
+				mglParse par;
+				par.AllowSetSize(true);
+				char *buf = new char[strlen(s->mgl)+strlen(mmgl_dat_prepare)+1];
+				strcpy(buf,s->mgl);		strcat(buf,mmgl_dat_prepare);
+				if(type!=7)	printf("\n-------\n%s\n-------\n",verbose?buf:s->mgl);
+				par.Execute(gr,buf);	delete []buf;
+				const char *mess = gr->Message();
+				if(*mess)	printf("Warnings: %s\n-------\n",mess);
+			}
+			else	s->func(gr);
+			save(gr, s->name, suf);
+		}
+		else	printf("no sample %s\n",name);
+	}
+	delete gr;	return 0;
+}
+//-----------------------------------------------------------------------------
diff --git a/examples/glut_example.cpp b/examples/glut_example.cpp
new file mode 100644
index 0000000..07a70f5
--- /dev/null
+++ b/examples/glut_example.cpp
@@ -0,0 +1,94 @@
+/***************************************************************************
+ * glut_example.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include "mgl2/glut.h"
+//-----------------------------------------------------------------------------
+#if defined(WIN32) || defined(_MSC_VER) || defined(__BORLANDC__)
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+void long_calculations()	// just delay which correspond to simulate calculations
+{
+#if defined(WIN32) || defined(_MSC_VER) || defined(__BORLANDC__)
+	Sleep(1000);
+#else
+	sleep(1);	// which can be very long
+#endif
+}
+//-----------------------------------------------------------------------------
+#if defined(PTHREAD_SAMPLE)
+mglGLUT *gr=NULL;
+void *calc(void *)
+{
+	mglPoint pnt;
+	for(int i=0;i<10;i++)	// do calculation
+	{
+		sleep(1);           // which can be very long
+		pnt.Set(2*mgl_rnd()-1,2*mgl_rnd()-1);
+printf("i=%d, gr=%p\n",i,gr);	fflush(stdout);
+		if(gr)
+		{
+			gr->Clf();			// make new drawing
+			gr->Line(mglPoint(),pnt,"Ar2");
+			char str[10] = "i=0";	str[2] = '0'+i;
+			gr->Puts(mglPoint(),str);
+			gr->Update();		// update window
+		}
+	}
+	exit(0);
+}
+int main(int argc,char **argv)
+{
+	mgl_textdomain(argv?argv[0]:NULL);
+	static pthread_t thr;
+	pthread_create(&thr,0,calc,0);
+	pthread_detach(thr);
+	gr = new mglGLUT;
+printf("Create gr=%p\n",gr);	fflush(stdout);
+	gr->Run();	return 0;
+}
+#else
+int test_wnd(mglGraph *gr);
+int sample(mglGraph *gr);
+int sample_m(mglGraph *gr);
+int sample_1(mglGraph *gr);
+int sample_2(mglGraph *gr);
+int sample_3(mglGraph *gr);
+int sample_d(mglGraph *gr);
+//-----------------------------------------------------------------------------
+typedef int (*draw_func)(mglGraph *gr);
+int main(int argc,char **argv)
+{
+	mgl_textdomain(argv?argv[0]:NULL,"");
+	char key = 0;
+	if(argc>1)	key = argv[1][0]!='-' ? argv[1][0] : argv[1][1];
+	else	printf("You may specify argument '1', '2', '3' or 'd' for viewing examples of 1d, 2d, 3d or dual plotting\n");
+	switch(key)
+	{
+	case '1':	new mglGLUT(sample_1, "1D plots");	break;
+	case '2':	new mglGLUT(sample_2, "2D plots");	break;
+	case '3':	new mglGLUT(sample_3, "3D plots");	break;
+	case 'd':	new mglGLUT(sample_d, "Dual plots");	break;
+	case 't':	new mglGLUT(test_wnd, "Testing");	break;
+	default:	new mglGLUT(sample, "Example of molecules");	break;
+	}
+	return 0;
+}
+#endif
diff --git a/examples/iris.dat b/examples/iris.dat
new file mode 100644
index 0000000..5c4316c
--- /dev/null
+++ b/examples/iris.dat
@@ -0,0 +1,151 @@
+5.1,3.5,1.4,0.2,Iris-setosa
+4.9,3.0,1.4,0.2,Iris-setosa
+4.7,3.2,1.3,0.2,Iris-setosa
+4.6,3.1,1.5,0.2,Iris-setosa
+5.0,3.6,1.4,0.2,Iris-setosa
+5.4,3.9,1.7,0.4,Iris-setosa
+4.6,3.4,1.4,0.3,Iris-setosa
+5.0,3.4,1.5,0.2,Iris-setosa
+4.4,2.9,1.4,0.2,Iris-setosa
+4.9,3.1,1.5,0.1,Iris-setosa
+5.4,3.7,1.5,0.2,Iris-setosa
+4.8,3.4,1.6,0.2,Iris-setosa
+4.8,3.0,1.4,0.1,Iris-setosa
+4.3,3.0,1.1,0.1,Iris-setosa
+5.8,4.0,1.2,0.2,Iris-setosa
+5.7,4.4,1.5,0.4,Iris-setosa
+5.4,3.9,1.3,0.4,Iris-setosa
+5.1,3.5,1.4,0.3,Iris-setosa
+5.7,3.8,1.7,0.3,Iris-setosa
+5.1,3.8,1.5,0.3,Iris-setosa
+5.4,3.4,1.7,0.2,Iris-setosa
+5.1,3.7,1.5,0.4,Iris-setosa
+4.6,3.6,1.0,0.2,Iris-setosa
+5.1,3.3,1.7,0.5,Iris-setosa
+4.8,3.4,1.9,0.2,Iris-setosa
+5.0,3.0,1.6,0.2,Iris-setosa
+5.0,3.4,1.6,0.4,Iris-setosa
+5.2,3.5,1.5,0.2,Iris-setosa
+5.2,3.4,1.4,0.2,Iris-setosa
+4.7,3.2,1.6,0.2,Iris-setosa
+4.8,3.1,1.6,0.2,Iris-setosa
+5.4,3.4,1.5,0.4,Iris-setosa
+5.2,4.1,1.5,0.1,Iris-setosa
+5.5,4.2,1.4,0.2,Iris-setosa
+4.9,3.1,1.5,0.1,Iris-setosa
+5.0,3.2,1.2,0.2,Iris-setosa
+5.5,3.5,1.3,0.2,Iris-setosa
+4.9,3.1,1.5,0.1,Iris-setosa
+4.4,3.0,1.3,0.2,Iris-setosa
+5.1,3.4,1.5,0.2,Iris-setosa
+5.0,3.5,1.3,0.3,Iris-setosa
+4.5,2.3,1.3,0.3,Iris-setosa
+4.4,3.2,1.3,0.2,Iris-setosa
+5.0,3.5,1.6,0.6,Iris-setosa
+5.1,3.8,1.9,0.4,Iris-setosa
+4.8,3.0,1.4,0.3,Iris-setosa
+5.1,3.8,1.6,0.2,Iris-setosa
+4.6,3.2,1.4,0.2,Iris-setosa
+5.3,3.7,1.5,0.2,Iris-setosa
+5.0,3.3,1.4,0.2,Iris-setosa
+7.0,3.2,4.7,1.4,Iris-versicolor
+6.4,3.2,4.5,1.5,Iris-versicolor
+6.9,3.1,4.9,1.5,Iris-versicolor
+5.5,2.3,4.0,1.3,Iris-versicolor
+6.5,2.8,4.6,1.5,Iris-versicolor
+5.7,2.8,4.5,1.3,Iris-versicolor
+6.3,3.3,4.7,1.6,Iris-versicolor
+4.9,2.4,3.3,1.0,Iris-versicolor
+6.6,2.9,4.6,1.3,Iris-versicolor
+5.2,2.7,3.9,1.4,Iris-versicolor
+5.0,2.0,3.5,1.0,Iris-versicolor
+5.9,3.0,4.2,1.5,Iris-versicolor
+6.0,2.2,4.0,1.0,Iris-versicolor
+6.1,2.9,4.7,1.4,Iris-versicolor
+5.6,2.9,3.6,1.3,Iris-versicolor
+6.7,3.1,4.4,1.4,Iris-versicolor
+5.6,3.0,4.5,1.5,Iris-versicolor
+5.8,2.7,4.1,1.0,Iris-versicolor
+6.2,2.2,4.5,1.5,Iris-versicolor
+5.6,2.5,3.9,1.1,Iris-versicolor
+5.9,3.2,4.8,1.8,Iris-versicolor
+6.1,2.8,4.0,1.3,Iris-versicolor
+6.3,2.5,4.9,1.5,Iris-versicolor
+6.1,2.8,4.7,1.2,Iris-versicolor
+6.4,2.9,4.3,1.3,Iris-versicolor
+6.6,3.0,4.4,1.4,Iris-versicolor
+6.8,2.8,4.8,1.4,Iris-versicolor
+6.7,3.0,5.0,1.7,Iris-versicolor
+6.0,2.9,4.5,1.5,Iris-versicolor
+5.7,2.6,3.5,1.0,Iris-versicolor
+5.5,2.4,3.8,1.1,Iris-versicolor
+5.5,2.4,3.7,1.0,Iris-versicolor
+5.8,2.7,3.9,1.2,Iris-versicolor
+6.0,2.7,5.1,1.6,Iris-versicolor
+5.4,3.0,4.5,1.5,Iris-versicolor
+6.0,3.4,4.5,1.6,Iris-versicolor
+6.7,3.1,4.7,1.5,Iris-versicolor
+6.3,2.3,4.4,1.3,Iris-versicolor
+5.6,3.0,4.1,1.3,Iris-versicolor
+5.5,2.5,4.0,1.3,Iris-versicolor
+5.5,2.6,4.4,1.2,Iris-versicolor
+6.1,3.0,4.6,1.4,Iris-versicolor
+5.8,2.6,4.0,1.2,Iris-versicolor
+5.0,2.3,3.3,1.0,Iris-versicolor
+5.6,2.7,4.2,1.3,Iris-versicolor
+5.7,3.0,4.2,1.2,Iris-versicolor
+5.7,2.9,4.2,1.3,Iris-versicolor
+6.2,2.9,4.3,1.3,Iris-versicolor
+5.1,2.5,3.0,1.1,Iris-versicolor
+5.7,2.8,4.1,1.3,Iris-versicolor
+6.3,3.3,6.0,2.5,Iris-virginica
+5.8,2.7,5.1,1.9,Iris-virginica
+7.1,3.0,5.9,2.1,Iris-virginica
+6.3,2.9,5.6,1.8,Iris-virginica
+6.5,3.0,5.8,2.2,Iris-virginica
+7.6,3.0,6.6,2.1,Iris-virginica
+4.9,2.5,4.5,1.7,Iris-virginica
+7.3,2.9,6.3,1.8,Iris-virginica
+6.7,2.5,5.8,1.8,Iris-virginica
+7.2,3.6,6.1,2.5,Iris-virginica
+6.5,3.2,5.1,2.0,Iris-virginica
+6.4,2.7,5.3,1.9,Iris-virginica
+6.8,3.0,5.5,2.1,Iris-virginica
+5.7,2.5,5.0,2.0,Iris-virginica
+5.8,2.8,5.1,2.4,Iris-virginica
+6.4,3.2,5.3,2.3,Iris-virginica
+6.5,3.0,5.5,1.8,Iris-virginica
+7.7,3.8,6.7,2.2,Iris-virginica
+7.7,2.6,6.9,2.3,Iris-virginica
+6.0,2.2,5.0,1.5,Iris-virginica
+6.9,3.2,5.7,2.3,Iris-virginica
+5.6,2.8,4.9,2.0,Iris-virginica
+7.7,2.8,6.7,2.0,Iris-virginica
+6.3,2.7,4.9,1.8,Iris-virginica
+6.7,3.3,5.7,2.1,Iris-virginica
+7.2,3.2,6.0,1.8,Iris-virginica
+6.2,2.8,4.8,1.8,Iris-virginica
+6.1,3.0,4.9,1.8,Iris-virginica
+6.4,2.8,5.6,2.1,Iris-virginica
+7.2,3.0,5.8,1.6,Iris-virginica
+7.4,2.8,6.1,1.9,Iris-virginica
+7.9,3.8,6.4,2.0,Iris-virginica
+6.4,2.8,5.6,2.2,Iris-virginica
+6.3,2.8,5.1,1.5,Iris-virginica
+6.1,2.6,5.6,1.4,Iris-virginica
+7.7,3.0,6.1,2.3,Iris-virginica
+6.3,3.4,5.6,2.4,Iris-virginica
+6.4,3.1,5.5,1.8,Iris-virginica
+6.0,3.0,4.8,1.8,Iris-virginica
+6.9,3.1,5.4,2.1,Iris-virginica
+6.7,3.1,5.6,2.4,Iris-virginica
+6.9,3.1,5.1,2.3,Iris-virginica
+5.8,2.7,5.1,1.9,Iris-virginica
+6.8,3.2,5.9,2.3,Iris-virginica
+6.7,3.3,5.7,2.5,Iris-virginica
+6.7,3.0,5.2,2.3,Iris-virginica
+6.3,2.5,5.0,1.9,Iris-virginica
+6.5,3.0,5.2,2.0,Iris-virginica
+6.2,3.4,5.4,2.3,Iris-virginica
+5.9,3.0,5.1,1.8,Iris-virginica
+
diff --git a/examples/mgl_module.cpp b/examples/mgl_module.cpp
new file mode 100644
index 0000000..15616f7
--- /dev/null
+++ b/examples/mgl_module.cpp
@@ -0,0 +1,35 @@
+#include "mgl2/mgl.h"
+#include "mgl2/base.h"
+#include "mgl2/parser.h"
+//-----------------------------------------------------------------------------
+int test1(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,""))	{	gr->Box();	gr->Axis();	}
+	else if(!strcmp(k,"s"))	{	gr->Box();	gr->Axis(a[0].s.c_str());	}
+	else res = 1;
+	return res;
+}
+//-----------------------------------------------------------------------------
+int test2(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"nnnns"))
+	{
+		gr->FaceZ(mglPoint(a[0].v-a[2].v/2,a[1].v-a[3].v/2),a[2].v,a[3].v,"r");
+		gr->Putsw(mglPoint(a[0].v,a[1].v),a[4].w.c_str());
+	}
+	else if(!strcmp(k,"nnnnss"))
+	{
+		gr->FaceZ(mglPoint(a[0].v-a[2].v/2,a[1].v-a[3].v/2),a[2].v,a[3].v,a[5].s.c_str());
+		gr->Putsw(mglPoint(a[0].v,a[1].v),a[4].w.c_str());
+	}
+	else res = 1;
+	return res;
+}
+//-----------------------------------------------------------------------------
+mglCommand mgl_cmd_extra[] = {
+	{"baxis","Box + axis","baxis ['stl'='']", test1, 12},
+	{"trect","Box + text","trect x0 y0 dx dy 'text' ['stl'='']", test2, 13},
+	{"",0,0,0,0}};
+//-----------------------------------------------------------------------------
diff --git a/examples/mpi_test.cpp b/examples/mpi_test.cpp
new file mode 100644
index 0000000..f21539a
--- /dev/null
+++ b/examples/mpi_test.cpp
@@ -0,0 +1,39 @@
+#include <stdio.h>
+#include <mgl2/mpi.h>
+#include <mpi.h>
+
+int main(int argc, char *argv[])
+{
+	mgl_textdomain(argv?argv[0]:NULL);
+	// initialize MPI
+	int rank=0, numproc=1;
+	MPI_Init(&argc, &argv);
+	MPI_Comm_size(MPI_COMM_WORLD,&numproc);
+	MPI_Comm_rank(MPI_COMM_WORLD,&rank);
+	if(rank==0)	printf("Use %d processes.\n", numproc);
+
+	// initialize data similarly for all ranks
+	mglData a(128,128);
+	mglGraphMPI gr;
+	// do the same plot for its own range
+	char buf[64];
+	sprintf(buf,"xrange %g %g",2.*rank/numproc-1,2.*(rank+1)/numproc-1);
+	gr.Fill(a,"sin(2*pi*x)",buf);
+	// plot data in each rank
+	gr.Rotate(40,60);
+	gr.Surf(a,"",buf);
+	// collect information
+	if(rank!=0)	gr.MPI_Send(0);
+	else	for(int i=1;i<numproc;i++)	gr.MPI_Recv(i);
+
+	if(rank==0)
+	{
+		gr.Box();	gr.Axis();		// some post processing
+		gr.WritePNG("test.png");	// save result
+	}
+	sprintf(buf,"test%d.png",rank);
+	gr.WritePNG(buf);
+
+	MPI_Finalize();
+	return 0;
+}
diff --git a/examples/qgl_example.cpp b/examples/qgl_example.cpp
new file mode 100644
index 0000000..b0f0d5c
--- /dev/null
+++ b/examples/qgl_example.cpp
@@ -0,0 +1,64 @@
+/***************************************************************************
+ * qt_example.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include "qgl_example.h"
+#include <QApplication>
+//#include <GL/gl.h>
+//-----------------------------------------------------------------------------
+int main(int argc, char *argv[])
+{
+	mgl_textdomain(argv?argv[0]:NULL,"");
+	QApplication a(argc, argv);
+	MainWindow w;
+	w.show();
+	return a.exec();
+}
+//-----------------------------------------------------------------------------
+MainWindow::MainWindow(QWidget *parent) : QGLWidget(parent)	{	gr=0;	}
+//-----------------------------------------------------------------------------
+MainWindow::~MainWindow()	{	if(gr)	delete gr;	}
+//-----------------------------------------------------------------------------
+void MainWindow::initializeGL()
+{
+	if(gr)	delete gr;
+	gr = new mglGraph(1);
+}
+//-----------------------------------------------------------------------------
+void MainWindow::paintGL()
+{
+	gr->Clf();
+	gr->SubPlot(1,1,0);
+	gr->Rotate(40,60);
+	gr->Light(true);
+	gr->AddLight(0,mglPoint(0,0,10),mglPoint(0,0,-1));
+	gr->Axis();
+	gr->Box();
+	gr->FPlot("sin(pi*x)","i2");
+	gr->FPlot("cos(pi*x)","|");
+	gr->FSurf("cos(2*pi*(x^2+y^2))");
+	gr->Finish();
+	swapBuffers();
+}
+//-----------------------------------------------------------------------------
+void MainWindow::resizeGL(int w, int h)
+{
+	QGLWidget::resizeGL(w, h);
+	glViewport (0, 0, w, h);
+}
+//-----------------------------------------------------------------------------
diff --git a/examples/qgl_example.h b/examples/qgl_example.h
new file mode 100644
index 0000000..1d3ca0f
--- /dev/null
+++ b/examples/qgl_example.h
@@ -0,0 +1,22 @@
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+//#include <QMainWindow>
+#include <QGLWidget>
+#include <QtOpenGL>
+#include <mgl2/mgl.h>
+
+class MainWindow : public QGLWidget
+{
+	Q_OBJECT
+protected:
+	mglGraph *gr;
+	void resizeGL(int nWidth, int nHeight); // Метод вызываемый после каждого изменения размера окна
+	void paintGL(); // Метод для вывода изображения на экран
+void initializeGL(); // Метод для инициализирования opengl
+public:
+	MainWindow(QWidget *parent = 0);
+	~MainWindow();
+};
+
+#endif // MAINWINDOW_H
diff --git a/examples/qt_example.cpp b/examples/qt_example.cpp
new file mode 100644
index 0000000..2f80129
--- /dev/null
+++ b/examples/qt_example.cpp
@@ -0,0 +1,163 @@
+/***************************************************************************
+ * qt_example.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include "mgl2/qt.h"
+//-----------------------------------------------------------------------------
+#if defined(WIN32) || defined(_MSC_VER) || defined(__BORLANDC__)
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+void long_calculations()	// just delay which correspond to simulate calculations
+{
+#if defined(WIN32) || defined(_MSC_VER) || defined(__BORLANDC__)
+	Sleep(1000);
+#else
+	sleep(1);           // which can be very long
+#endif
+}
+//-----------------------------------------------------------------------------
+#if defined(PTHREAD_SAMPLE1)	// first variant of multi-threading usage of mglQT window
+mglQT *gr=NULL;
+void *calc(void *)
+{
+	mglPoint pnt;
+	for(int i=0;i<10;i++)	// do calculation
+	{
+		long_calculations();       // which can be very long
+		pnt.Set(2*mgl_rnd()-1,2*mgl_rnd()-1);
+		if(gr)
+		{
+			gr->Clf();			// make new drawing
+			gr->Line(mglPoint(),pnt,"Ar2");
+			char str[10] = "i=0";	str[2] = '0'+i;
+			gr->Puts(mglPoint(),str);
+			gr->Update();		// update window
+		}
+	}
+	exit(0);
+}
+int main(int argc,char **argv)
+{
+	mgl_textdomain(argv?argv[0]:NULL);
+	static pthread_t thr;
+	pthread_create(&thr,0,calc,0);
+	pthread_detach(thr);
+	gr = new mglQT;
+	gr->Run();	return 0;
+}
+#elif defined(PTHREAD_SAMPLE2)	// another variant of multi-threading usage of mglQT window. Work only if pthread was enabled for MathGL
+class Foo : public mglDraw
+{
+	mglPoint pnt;  // some result of calculation
+public:
+	mglWnd *Gr;  // graphics to be updated
+	int Draw(mglGraph *gr);
+	void Calc();
+};
+void Foo::Calc()
+{
+	for(int i=0;i<30;i++)   	// do calculation
+	{
+		long_calculations();	// which can be very long
+		pnt.Set(2*mgl_rnd()-1,2*mgl_rnd()-1);
+		Gr->Update();			// update window
+	}
+}
+int Foo::Draw(mglGraph *gr)
+{
+	gr->Line(mglPoint(),pnt,"Ar2");
+	gr->Box();
+	return 0;
+}
+int main(int argc,char **argv)
+{
+	mgl_textdomain(argv?argv[0]:NULL);
+	Foo *foo = new Foo;
+	mglQT gr(foo,"MathGL examples");
+	foo->Gr = &gr;
+	foo->Run();	// <-- need MathGL version which use pthread
+	return gr.Run();
+}
+#else		// just default samples
+//-----------------------------------------------------------------------------
+int test_wnd(mglGraph *gr);
+int sample(mglGraph *gr);
+int sample_1(mglGraph *gr);
+int sample_2(mglGraph *gr);
+int sample_3(mglGraph *gr);
+int sample_d(mglGraph *gr);
+//-----------------------------------------------------------------------------
+#if MGL_HAVE_PTHR_WIDGET
+class myDraw : public mglDraw
+{
+	mglPoint pnt;	// some variable for changeable data
+	long i;			// another variable to be shown
+	mglWnd *wnd;	// external window for plotting
+public:
+	myDraw(mglWnd *w=0) : mglDraw()	{	wnd=w;	}
+	void SetWnd(mglWnd *w)	{	wnd=w;	}
+	int Draw(mglGraph *gr)
+	{
+		gr->Line(mglPoint(),pnt,"Ar2");
+		char str[16];	snprintf(str,15,"i=%ld",i);
+		gr->Puts(mglPoint(),str);
+		return 0;
+	}
+	void Calc()
+	{
+		for(i=0;;i++)	// do calculation
+		{
+			Check();	// check if need pause
+			long_calculations();// which can be very long
+			pnt.Set(2*mgl_rnd()-1,2*mgl_rnd()-1);
+			if(wnd)	wnd->Update();
+		}
+	}
+} dr;
+#endif
+//-----------------------------------------------------------------------------
+int main(int argc,char **argv)
+{
+	mgl_textdomain(argv?argv[0]:NULL,"");
+	mglQT *gr;
+	char key = 0;
+	if(argc>1)	key = argv[1][0]!='-' ? argv[1][0]:argv[1][1];
+	else	printf("You may specify argument '1', '2', '3', 'd' for viewing examples of 1d, 2d, 3d, dual plotting,\nor 'm' for multi-threading sample.\n");
+	switch(key)
+	{
+	case '0':	gr = new mglQT((mglDraw *)NULL,"1D plots");
+				gr->Rotate(40,60);	gr->Box();	gr->Light(true);
+				gr->FSurf("sin(4*pi*x*y)");	gr->Update();	break;
+	case '1':	gr = new mglQT(sample_1,"1D plots");	break;
+	case '2':	gr = new mglQT(sample_2,"2D plots");	break;
+	case '3':	gr = new mglQT(sample_3,"3D plots");	break;
+	case 'd':	gr = new mglQT(sample_d,"Dual plots");	break;
+	case 't':	gr = new mglQT(test_wnd,"Testing");		break;
+	case 'f':	gr = new mglQT("Frame drawing");
+				gr->NewFrame();	gr->Box();	gr->EndFrame();	break;
+#if MGL_HAVE_PTHR_WIDGET
+	case 'm':	gr = new mglQT(&dr,"Multi-threading test");
+	dr.SetWnd(gr);	dr.Run();	break;
+#endif
+	default: 	gr = new mglQT(sample,"Drop and waves");	break;
+	}
+	gr->Run();	return 0;
+}
+#endif
diff --git a/examples/samples.cpp b/examples/samples.cpp
new file mode 100644
index 0000000..7d2f8b0
--- /dev/null
+++ b/examples/samples.cpp
@@ -0,0 +1,3159 @@
+/***************************************************************************
+ * samples.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include "mgl2/mgl.h"
+//-----------------------------------------------------------------------------
+void mgls_prepare1d(mglData *y, mglData *y1=0, mglData *y2=0, mglData *x1=0, mglData *x2=0);
+void mgls_prepare2d(mglData *a, mglData *b=0, mglData *v=0);
+void mgls_prepare3d(mglData *a, mglData *b=0);
+void mgls_prepare2v(mglData *a, mglData *b);
+void mgls_prepare3v(mglData *ex, mglData *ey, mglData *ez);
+extern int big;
+//-----------------------------------------------------------------------------
+struct mglSample	/// Structure for list of samples
+{
+	const char *name;
+	void (*func)(mglGraph*);
+	const char *mgl;
+};
+//-----------------------------------------------------------------------------
+//		MGL functions for preparing data
+//-----------------------------------------------------------------------------
+const char *mmgl_dat_prepare = "\nstop\n\nfunc 'prepare1d'\n\
+new y 50 3\nmodify y '0.7*sin(2*pi*x)+0.5*cos(3*pi*x)+0.2*sin(pi*x)'\n\
+modify y 'sin(2*pi*x)' 1\nmodify y 'cos(2*pi*x)' 2\n\
+new x1 50 'x'\nnew x2 50 '0.05-0.03*cos(pi*x)'\n\
+new y1 50 '0.5-0.3*cos(pi*x)'\nnew y2 50 '-0.3*sin(pi*x)'\n\
+return\n\nfunc 'prepare2d'\n\
+new a 50 40 '0.6*sin(pi*(x+1))*sin(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'\n\
+new b 50 40 '0.6*cos(pi*(x+1))*cos(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'\n\
+return\n\nfunc 'prepare3d'\n\
+new c 61 50 40 '-2*(x^2+y^2+z^4-z^2)+0.2'\n\
+new d 61 50 40 '1-2*tanh((x+y)*(x+y))'\n\
+return\n\nfunc 'prepare2v'\n\
+new a 20 30 '0.6*sin(pi*(x+1))*sin(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'\n\
+new b 20 30 '0.6*cos(pi*(x+1))*cos(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'\n\
+return\n\nfunc 'prepare3v'\n\
+define $1 pow(x*x+y*y+(z-0.3)*(z-0.3)+0.03,1.5)\n\
+define $2 pow(x*x+y*y+(z+0.3)*(z+0.3)+0.03,1.5)\n\
+new ex 10 10 10 '0.2*x/$1-0.2*x/$2'\n\
+new ey 10 10 10 '0.2*y/$1-0.2*y/$2'\n\
+new ez 10 10 10 '0.2*(z-0.3)/$1-0.2*(z+0.3)/$2'\nreturn";
+//-----------------------------------------------------------------------------
+//		Sample functions (v.2.*)
+//-----------------------------------------------------------------------------
+const char *mmgl_refill="new x 10 '0.5+rnd':cumsum x 'x':norm x -1 1\ncopy y sin(pi*x)/1.5\n"
+"subplot 2 2 0 '<_':title 'Refill sample'\nbox:axis:plot x y 'o ':fplot 'sin(pi*x)/1.5' 'B:'\n"
+"new r 100:refill r x y:plot r 'r'\n\n"
+"subplot 2 2 1 '<_':title 'Global spline'\nbox:axis:plot x y 'o ':fplot 'sin(pi*x)/1.5' 'B:'\n"
+"new r 100:gspline r x y:plot r 'r'\n\nnew y 10 '0.5+rnd':cumsum y 'x':norm y -1 1\n"
+"copy xx x:extend xx 10\ncopy yy y:extend yy 10:transpose yy\ncopy z sin(pi*xx*yy)/1.5\n"
+"alpha on:light on\n"
+"subplot 2 2 2:title '2d regular':rotate 40 60\nbox:axis:mesh xx yy z 'k'\n"
+"new rr 100 100:refill rr x y z:surf rr\n\n"
+"new xx 10 10 '(x+1)/2*cos(y*pi/2-1)':new yy 10 10 '(x+1)/2*sin(y*pi/2-1)'\ncopy z sin(pi*xx*yy)/1.5\n"
+"subplot 2 2 3:title '2d non-regular':rotate 40 60\nbox:axis:plot xx yy z 'ko '\n"
+"new rr 100 100:refill rr xx yy z:surf rr";
+void smgl_refill(mglGraph *gr)
+{
+	mglData x(10), y(10), r(100);
+	x.Modify("0.5+rnd");	x.CumSum("x");	x.Norm(-1,1);
+	y.Modify("sin(pi*v)/1.5",x);
+	if(big!=3)	{	gr->SubPlot(2,2,0,"<_");	gr->Title("Refill sample");	}
+	gr->Axis();	gr->Box();	gr->Plot(x,y,"o ");
+	gr->Refill(r,x,y);	// or you can use r.Refill(x,y,-1,1);
+	gr->Plot(r,"r");	gr->FPlot("sin(pi*x)/1.5","B:");
+	if(big==3)	return;
+	gr->SubPlot(2,2,1,"<_");	gr->Title("Global spline");
+	gr->Axis();	gr->Box();	gr->Plot(x,y,"o ");
+	r.RefillGS(x,y,-1,1);	gr->Plot(r,"r");
+	gr->FPlot("sin(pi*x)/1.5","B:");
+
+	gr->Alpha(true);	gr->Light(true);
+	mglData z(10,10), xx(10,10), yy(10,10), rr(100,100);
+	y.Modify("0.5+rnd");	y.CumSum("x");	y.Norm(-1,1);
+	for(int i=0;i<10;i++)	for(int j=0;j<10;j++)
+		z.a[i+10*j] = sin(M_PI*x.a[i]*y.a[j])/1.5;
+	gr->SubPlot(2,2,2);	gr->Title("2d regular");	gr->Rotate(40,60);
+	gr->Axis();	gr->Box();	gr->Mesh(x,y,z,"k");
+	gr->Refill(rr,x,y,z);	gr->Surf(rr);
+
+	gr->Fill(xx,"(x+1)/2*cos(y*pi/2-1)");
+	gr->Fill(yy,"(x+1)/2*sin(y*pi/2-1)");
+	for(int i=0;i<10*10;i++)
+		z.a[i] = sin(M_PI*xx.a[i]*yy.a[i])/1.5;
+	gr->SubPlot(2,2,3);	gr->Title("2d non-regular");	gr->Rotate(40,60);
+	gr->Axis();	gr->Box();	gr->Plot(xx,yy,z,"ko ");
+	gr->Refill(rr,xx,yy,z);	gr->Surf(rr);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_indirect="subplot 1 1 0 '':title 'SubData vs Evaluate'\n"
+"new in 9 'x^3/1.1':plot in 'ko ':box\nnew arg 99 '4*x+4'\n"
+"evaluate e in arg off:plot e 'b.'; legend 'Evaluate'\n"
+"subdata s in arg:plot s 'r.';legend 'SubData'\nlegend 2";
+void smgl_indirect(mglGraph *gr)
+{
+	gr->SubPlot(1,1,0,"");	gr->Title("SubData vs Evaluate");
+	mglData in(9), arg(99), e, s;
+	gr->Fill(in,"x^3/1.1");	gr->Fill(arg,"4*x+4");
+	gr->Plot(in,"ko ");		gr->Box();
+	e = in.Evaluate(arg,false);	gr->Plot(e,"b.","legend 'Evaluate'");
+	s = in.SubData(arg);	gr->Plot(s,"r.","legend 'SubData'");
+	gr->Legend(2);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_ode="subplot 2 2 0 '<_':title 'Cont':box\naxis:xlabel 'x':ylabel '\\dot{x}'\n"
+"new f 100 100 'y^2+2*x^3-x^2-0.5':cont f\n\n"
+"subplot 2 2 1 '<_':title 'Flow':box\naxis:xlabel 'x':ylabel '\\dot{x}'\n"
+"new fx 100 100 'x-3*x^2'\nnew fy 100 100 'y'\nflow fy fx 'v';value 7\n\n"
+"subplot 2 2 2 '<_':title 'ODE':box\naxis:xlabel 'x':ylabel '\\dot{x}'\n"
+"for $x -1 1 0.1\n  ode r 'y;x-3*x^2' 'xy' [$x,0]\n  plot r(0) r(1)\n"
+"  ode r '-y;-x+3*x^2' 'xy' [$x,0]\n  plot r(0) r(1)\nnext";
+void smgl_ode(mglGraph *gr)
+{
+	gr->SubPlot(2,2,0,"<_");	gr->Title("Cont");	gr->Box();
+	gr->Axis();	gr->Label('x',"x");	gr->Label('y',"\\dot{x}");
+	mglData f(100,100);	gr->Fill(f,"y^2+2*x^3-x^2-0.5");
+	gr->Cont(f);
+	gr->SubPlot(2,2,1,"<_");	gr->Title("Flow");	gr->Box();
+	gr->Axis();	gr->Label('x',"x");	gr->Label('y',"\\dot{x}");
+	mglData fx(100,100), fy(100,100);	gr->Fill(fx,"x-3*x^2");	gr->Fill(fy,"y");
+	gr->Flow(fy,fx,"v","value 7");
+	gr->SubPlot(2,2,2,"<_");	gr->Title("ODE");	gr->Box();
+	gr->Axis();	gr->Label('x',"x");	gr->Label('y',"\\dot{x}");
+	for(double x=-1;x<1;x+=0.1)
+	{
+		mglData in(2), r;	in.a[0]=x;
+		r = mglODE("y;x-3*x^2","xy",in);
+		gr->Plot(r.SubData(0), r.SubData(1));
+		r = mglODE("-y;-x+3*x^2","xy",in);
+		gr->Plot(r.SubData(0), r.SubData(1));
+	}
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_correl="new a 100 'exp(-10*x^2)'\n"
+"new b 100 'exp(-10*(x+0.5)^2)'\n"
+"yrange 0 1\nsubplot 1 2 0 '_':title 'Input fields'\n"
+"plot a:plot b:box:axis\n"
+"correl r a b 'x'\nnorm r 0 1:swap r 'x' # make it human readable\n"
+"subplot 1 2 1 '_':title 'Correlation of a and b'\n"
+"plot r 'r':axis:box\nline 0.5 0 0.5 1 'B|'";
+void smgl_correl(mglGraph *gr)
+{
+	mglData a(100),b(100);
+	gr->Fill(a,"exp(-10*x^2)");	gr->Fill(b,"exp(-10*(x+0.5)^2)");
+	gr->SetRange('y',0,1);
+	gr->SubPlot(1,2,0,"_");	gr->Title("Input fields");
+	gr->Plot(a);	gr->Plot(b);	gr->Axis();	gr->Box();
+	mglData r = a.Correl(b,"x");
+	r.Norm(0,1);	r.Swap("x");	// make it human readable
+	gr->SubPlot(1,2,1,"_");	gr->Title("Correlation of a and b");
+	gr->Plot(r,"r");	gr->Axis();	gr->Box();
+	gr->Line(mglPoint(0.5,0),mglPoint(0.5,1),"B|");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_mask="new a 10 10 'x'\n"
+"subplot 5 4 0 '':title '\"-\" mask':dens a '3-'\n"
+"subplot 5 4 1 '':title '\"+\" mask':dens a '3+'\n"
+"subplot 5 4 2 '':title '\"=\" mask':dens a '3='\n"
+"subplot 5 4 3 '':title '\";\" mask':dens a '3;'\n"
+"subplot 5 4 4 '':title '\";I\" mask':dens a '3;I'\n"
+"subplot 5 4 5 '':title '\"o\" mask':dens a '3o'\n"
+"subplot 5 4 6 '':title '\"O\" mask':dens a '3O'\n"
+"subplot 5 4 7 '':title '\"s\" mask':dens a '3s'\n"
+"subplot 5 4 8 '':title '\"S\" mask':dens a '3S'\n"
+"subplot 5 4 9 '':title '\";/\" mask':dens a '3;/'\n"
+"subplot 5 4 10 '':title '\"~\" mask':dens a '3~'\n"
+"subplot 5 4 11 '':title '\"<\" mask':dens a '3<'\n"
+"subplot 5 4 12 '':title '\">\" mask':dens a '3>'\n"
+"subplot 5 4 13 '':title '\"j\" mask':dens a '3j'\n"
+"subplot 5 4 14 '':title '\"-;\\\" mask':dens a '3;\\ '\n"
+"subplot 5 4 15 '':title '\"d\" mask':dens a '3d'\n"
+"subplot 5 4 16 '':title '\"D\" mask':dens a '3D'\n"
+"subplot 5 4 17 '':title '\"*\" mask':dens a '3*'\n"
+"subplot 5 4 18 '':title '\"^\" mask':dens a '3^'\n"
+"subplot 5 4 19 '':title 'manual mask'\n"
+"mask '+' 'ff00182424f800':dens a '3+'";
+void smgl_mask(mglGraph *gr)
+{
+	mglData a(10,10);	a.Fill(-1,1);
+	gr->SubPlot(5,4,0,"");	gr->Title("'-' mask");	gr->Dens(a,"3-");
+	gr->SubPlot(5,4,1,"");	gr->Title("'+' mask");	gr->Dens(a,"3+");
+	gr->SubPlot(5,4,2,"");	gr->Title("'=' mask");	gr->Dens(a,"3=");
+	gr->SubPlot(5,4,3,"");	gr->Title("';' mask");	gr->Dens(a,"3;");
+	gr->SubPlot(5,4,4,"");	gr->Title("';I' mask");	gr->Dens(a,"3;I");
+	gr->SubPlot(5,4,5,"");	gr->Title("'o' mask");	gr->Dens(a,"3o");
+	gr->SubPlot(5,4,6,"");	gr->Title("'O' mask");	gr->Dens(a,"3O");
+	gr->SubPlot(5,4,7,"");	gr->Title("'s' mask");	gr->Dens(a,"3s");
+	gr->SubPlot(5,4,8,"");	gr->Title("'S' mask");	gr->Dens(a,"3S");
+	gr->SubPlot(5,4,9,"");	gr->Title("';/' mask");	gr->Dens(a,"3;/");
+	gr->SubPlot(5,4,10,"");	gr->Title("'~' mask");	gr->Dens(a,"3~");
+	gr->SubPlot(5,4,11,"");	gr->Title("'<' mask");	gr->Dens(a,"3<");
+	gr->SubPlot(5,4,12,"");	gr->Title("'>' mask");	gr->Dens(a,"3>");
+	gr->SubPlot(5,4,13,"");	gr->Title("'j' mask");	gr->Dens(a,"3j");
+	gr->SubPlot(5,4,14,"");	gr->Title("';\\\\' mask");	gr->Dens(a,"3;\\");
+	gr->SubPlot(5,4,15,"");	gr->Title("'d' mask");	gr->Dens(a,"3d");
+	gr->SubPlot(5,4,16,"");	gr->Title("'D' mask");	gr->Dens(a,"3D");
+	gr->SubPlot(5,4,17,"");	gr->Title("'*' mask");	gr->Dens(a,"3*");
+	gr->SubPlot(5,4,18,"");	gr->Title("'^' mask");	gr->Dens(a,"3^");
+	gr->SubPlot(5,4,19,"");	gr->Title("manual mask");
+	gr->SetMask('+', "ff00182424f80000");	gr->Dens(a,"3+");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_export="new a 100 100 'x^2*y':new b 100 100\n"
+"export a 'test_data.png' 'BbcyrR' -1 1\n"
+"import b 'test_data.png' 'BbcyrR' -1 1\n"
+"subplot 2 1 0 '':title 'initial':box:dens a\n"
+"subplot 2 1 1 '':title 'imported':box:dens b";
+void smgl_export(mglGraph *gr)	// basic data operations
+{
+	mglData a(100,100), b; gr->Fill(a,"x^2*y");
+	a.Export("test_data.png","BbcyrR");
+	b.Import("test_data.png","BbcyrR",-1,1);
+	gr->SubPlot(2,1,0,"");	gr->Title("initial");	gr->Box();	gr->Dens(a);
+	gr->SubPlot(2,1,1,"");	gr->Title("imported");	gr->Box();	gr->Dens(b);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_data1="new a 40 50 60 'exp(-x^2-4*y^2-16*z^2)'\n"
+"light on:alpha on\n"
+"copy b a:diff b 'x':subplot 5 3 0:call 'splot'\n"
+"copy b a:diff2 b 'x':subplot 5 3 1:call 'splot'\n"
+"copy b a:cumsum b 'x':subplot 5 3 2:call 'splot'\n"
+"copy b a:integrate b 'x':subplot 5 3 3:call 'splot'\n"
+"mirror b 'x':subplot 5 3 4:call 'splot'\n"
+"copy b a:diff b 'y':subplot 5 3 5:call 'splot'\n"
+"copy b a:diff2 b 'y':subplot 5 3 6:call 'splot'\n"
+"copy b a:cumsum b 'y':subplot 5 3 7:call 'splot'\n"
+"copy b a:integrate b 'y':subplot 5 3 8:call 'splot'\n"
+"mirror b 'y':subplot 5 3 9:call 'splot'\n"
+"copy b a:diff b 'z':subplot 5 3 10:call 'splot'\n"
+"copy b a:diff2 b 'z':subplot 5 3 11:call 'splot'\n"
+"copy b a:cumsum b 'z':subplot 5 3 12:call 'splot'\n"
+"copy b a:integrate b 'z':subplot 5 3 13:call 'splot'\n"
+"mirror b 'z':subplot 5 3 14:call 'splot'\n"
+"stop\nfunc splot 0\n"
+"title 'max=',b.max:norm b -1 1 on:rotate 70 60:box:surf3 b\n"
+"return";
+inline void splot1(mglGraph *gr, mglData &b)
+{b.Norm(-1,1,true);gr->Rotate(70,60);gr->Box();gr->Surf3(b);}
+void smgl_data1(mglGraph *gr)	// basic data operations
+{
+	mglData a(40,50,60),b;	gr->Fill(a,"exp(-x^2-4*y^2-16*z^2)");
+	gr->Light(true);		gr->Alpha(true);
+	b.Set(a);	b.Diff("x");	gr->SubPlot(5,3,0);	splot1(gr,b);
+	b.Set(a);	b.Diff2("x");	gr->SubPlot(5,3,1);	splot1(gr,b);
+	b.Set(a);	b.CumSum("x");	gr->SubPlot(5,3,2);	splot1(gr,b);
+	b.Set(a);	b.Integral("x");gr->SubPlot(5,3,3);	splot1(gr,b);
+	b.Mirror("x");	gr->SubPlot(5,3,4);	splot1(gr,b);
+	b.Set(a);	b.Diff("y");	gr->SubPlot(5,3,5);	splot1(gr,b);
+	b.Set(a);	b.Diff2("y");	gr->SubPlot(5,3,6);	splot1(gr,b);
+	b.Set(a);	b.CumSum("y");	gr->SubPlot(5,3,7);	splot1(gr,b);
+	b.Set(a);	b.Integral("y");gr->SubPlot(5,3,8);	splot1(gr,b);
+	b.Mirror("y");	gr->SubPlot(5,3,9);	splot1(gr,b);
+	b.Set(a);	b.Diff("z");	gr->SubPlot(5,3,10);splot1(gr,b);
+	b.Set(a);	b.Diff2("z");	gr->SubPlot(5,3,11);splot1(gr,b);
+	b.Set(a);	b.CumSum("z");	gr->SubPlot(5,3,12);splot1(gr,b);
+	b.Set(a);	b.Integral("z");gr->SubPlot(5,3,13);splot1(gr,b);
+	b.Mirror("z");	gr->SubPlot(5,3,14);splot1(gr,b);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_data2="new a 40 50 60 'exp(-x^2-4*y^2-16*z^2)'\n"
+"light on:alpha on\n"
+"copy b a:sinfft b 'x':subplot 5 3 0:call 'splot'\n"
+"copy b a:cosfft b 'x':subplot 5 3 1:call 'splot'\n"
+"copy b a:hankel b 'x':subplot 5 3 2:call 'splot'\n"
+"copy b a:swap b 'x':subplot 5 3 3:call 'splot'\n"
+"copy b a:smooth b 'x':subplot 5 3 4:call 'splot'\n"
+"copy b a:sinfft b 'y':subplot 5 3 5:call 'splot'\n"
+"copy b a:cosfft b 'y':subplot 5 3 6:call 'splot'\n"
+"copy b a:hankel b 'y':subplot 5 3 7:call 'splot'\n"
+"copy b a:swap b 'y':subplot 5 3 8:call 'splot'\n"
+"copy b a:smooth b 'y':subplot 5 3 9:call 'splot'\n"
+"copy b a:sinfft b 'z':subplot 5 3 10:call 'splot'\n"
+"copy b a:cosfft b 'z':subplot 5 3 11:call 'splot'\n"
+"copy b a:hankel b 'z':subplot 5 3 12:call 'splot'\n"
+"copy b a:swap b 'z':subplot 5 3 13:call 'splot'\n"
+"copy b a:smooth b 'z':subplot 5 3 14:call 'splot'\n"
+"stop\nfunc splot 0\n"
+"title 'max=',b.max:norm b -1 1 on:rotate 70 60:box\n"
+"surf3 b 0.5:surf3 b -0.5\nreturn";
+inline void splot2(mglGraph *gr, mglData &b)
+{b.Norm(-1,1,true);gr->Rotate(70,60);gr->Box();gr->Surf3(0.5,b);gr->Surf3(-0.5,b);}
+void smgl_data2(mglGraph *gr)	// data transforms
+{
+	mglData a(40,50,60),b;	gr->Fill(a,"exp(-x^2-4*y^2-16*z^2)");
+	gr->Light(true);		gr->Alpha(true);
+	b.Set(a);	b.SinFFT("x");	gr->SubPlot(5,3,0);	splot2(gr,b);
+	b.Set(a);	b.CosFFT("x");	gr->SubPlot(5,3,1);	splot2(gr,b);
+	b.Set(a);	b.Hankel("x");	gr->SubPlot(5,3,2);	splot2(gr,b);
+	b.Set(a);	b.Swap("x");	gr->SubPlot(5,3,3);	splot2(gr,b);
+	b.Set(a);	b.Smooth("x");	gr->SubPlot(5,3,4);	splot2(gr,b);
+	b.Set(a);	b.SinFFT("y");	gr->SubPlot(5,3,5);	splot2(gr,b);
+	b.Set(a);	b.CosFFT("y");	gr->SubPlot(5,3,6);	splot2(gr,b);
+	b.Set(a);	b.Hankel("y");	gr->SubPlot(5,3,7);	splot2(gr,b);
+	b.Set(a);	b.Swap("y");	gr->SubPlot(5,3,8);	splot2(gr,b);
+	b.Set(a);	b.Smooth("y");	gr->SubPlot(5,3,9);	splot2(gr,b);
+	b.Set(a);	b.SinFFT("z");	gr->SubPlot(5,3,10);splot2(gr,b);
+	b.Set(a);	b.CosFFT("z");	gr->SubPlot(5,3,11);splot2(gr,b);
+	b.Set(a);	b.Hankel("z");	gr->SubPlot(5,3,12);splot2(gr,b);
+	b.Set(a);	b.Swap("z");	gr->SubPlot(5,3,13);splot2(gr,b);
+	b.Set(a);	b.Smooth("z");	gr->SubPlot(5,3,14);splot2(gr,b);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_param1="new x 100 'sin(pi*x)'\nnew y 100 'cos(pi*x)'\n"
+"new z 100 'sin(2*pi*x)'\nnew c 100 'cos(2*pi*x)'\n\n"
+"subplot 4 3 0:rotate 40 60:box:plot x y z\n"
+"subplot 4 3 1:rotate 40 60:box:area x y z\n"
+"subplot 4 3 2:rotate 40 60:box:tens x y z c\n"
+"subplot 4 3 3:rotate 40 60:box:bars x y z\n"
+"subplot 4 3 4:rotate 40 60:box:stem x y z\n"
+"subplot 4 3 5:rotate 40 60:box:textmark x y z c*2 '\\alpha'\n"
+"subplot 4 3 6:rotate 40 60:box:tube x y z c/10\n"
+"subplot 4 3 7:rotate 40 60:box:mark x y z c 's'\n"
+"subplot 4 3 8:box:error x y z/10 c/10\n"
+"subplot 4 3 9:rotate 40 60:box:step x y z\n"
+"subplot 4 3 10:rotate 40 60:box:torus x z 'z';light on\n"
+"subplot 4 3 11:rotate 40 60:box:label x y z '%z'";
+void smgl_param1(mglGraph *gr)	// 1d parametric plots
+{
+	mglData x(100), y(100), z(100), c(100);
+	gr->Fill(x,"sin(pi*x)");	gr->Fill(y,"cos(pi*x)");
+	gr->Fill(z,"sin(2*pi*x)");	gr->Fill(c,"cos(2*pi*x)");
+
+	gr->SubPlot(4,3,0);	gr->Rotate(40,60);	gr->Box();	gr->Plot(x,y,z);
+	gr->SubPlot(4,3,1);	gr->Rotate(40,60);	gr->Box();	gr->Area(x,y,z);
+	gr->SubPlot(4,3,2);	gr->Rotate(40,60);	gr->Box();	gr->Tens(x,y,z,c);
+	gr->SubPlot(4,3,3);	gr->Rotate(40,60);	gr->Box();	gr->Bars(x,y,z);
+	gr->SubPlot(4,3,4);	gr->Rotate(40,60);	gr->Box();	gr->Stem(x,y,z);
+	gr->SubPlot(4,3,5);	gr->Rotate(40,60);	gr->Box();	gr->TextMark(x,y,z,c*2,"\\alpha");
+	gr->SubPlot(4,3,6);	gr->Rotate(40,60);	gr->Box();	gr->Tube(x,y,z,c/10,"","light on");
+	gr->SubPlot(4,3,7);	gr->Rotate(40,60);	gr->Box();	gr->Mark(x,y,z,c,"s");
+	gr->SubPlot(4,3,8);	gr->Rotate(40,60);	gr->Box();	gr->Error(x,y,z/10,c/10);
+	gr->SubPlot(4,3,9);	gr->Rotate(40,60);	gr->Box();	gr->Step(x,y,z);
+	gr->SubPlot(4,3,10);gr->Rotate(40,60);	gr->Box();	gr->Torus(x,z,"z","light on");
+	gr->SubPlot(4,3,11);gr->Rotate(40,60);	gr->Box();	gr->Label(x,y,z,"%z");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_param2="new x 100 100 'sin(pi*(x+y)/2)*cos(pi*y/2)'\n"
+"new y 100 100 'cos(pi*(x+y)/2)*cos(pi*y/2)'\n"
+"new z 100 100 'sin(pi*y/2)'\nnew c 100 100 'cos(pi*x)'\n\n"
+"subplot 4 4 0:rotate 40 60:box:surf x y z\n"
+"subplot 4 4 1:rotate 40 60:box:surfc x y z c\n"
+"subplot 4 4 2:rotate 40 60:box:surfa x y z c;alpha 1\n"
+"subplot 4 4 3:rotate 40 60:box:mesh x y z;meshnum 10\n"
+"subplot 4 4 4:rotate 40 60:box:tile x y z;meshnum 10\n"
+"subplot 4 4 5:rotate 40 60:box:tiles x y z c;meshnum 10\n"
+"subplot 4 4 6:rotate 40 60:box:axial x y z;alpha 0.5;light on\n"
+"subplot 4 4 7:rotate 40 60:box:cont x y z\n"
+"subplot 4 4 8:rotate 40 60:box:contf x y z;light on:contv x y z;light on\n"
+"subplot 4 4 9:rotate 40 60:box:belt x y z 'x';meshnum 10;light on\n"
+"subplot 4 4 10:rotate 40 60:box:dens x y z;alpha 0.5\n"
+"subplot 4 4 11:rotate 40 60:box\n"
+"fall x y z 'g';meshnum 10:fall x y z 'rx';meshnum 10\n"
+"subplot 4 4 12:rotate 40 60:box:belt x y z '';meshnum 10;light on\n"
+"subplot 4 4 13:rotate 40 60:box:boxs x y z '';meshnum 10;light on\n"
+"subplot 4 4 14:rotate 40 60:box:boxs x y z '#';meshnum 10;light on\n"
+"subplot 4 4 15:rotate 40 60:box:boxs x y z '@';meshnum 10;light on";
+void smgl_param2(mglGraph *gr)	// 2d parametric plots
+{
+	mglData x(100,100), y(100,100), z(100,100), c(100,100);
+	gr->Fill(x,"sin(pi*(x+y)/2)*cos(pi*y/2)");	gr->Fill(y,"cos(pi*(x+y)/2)*cos(pi*y/2)");
+	gr->Fill(z,"sin(pi*y/2)");	gr->Fill(c,"cos(pi*x)");
+
+	gr->SubPlot(4,4,0);	gr->Rotate(40,60);	gr->Box();	gr->Surf(x,y,z);
+	gr->SubPlot(4,4,1);	gr->Rotate(40,60);	gr->Box();	gr->SurfC(x,y,z,c);
+	gr->SubPlot(4,4,2);	gr->Rotate(40,60);	gr->Box();	gr->SurfA(x,y,z,c,"","alpha 1");
+	gr->SubPlot(4,4,3);	gr->Rotate(40,60);	gr->Box();	gr->Mesh(x,y,z,"","meshnum 10");
+	gr->SubPlot(4,4,4);	gr->Rotate(40,60);	gr->Box();	gr->Tile(x,y,z,"","meshnum 10");
+	gr->SubPlot(4,4,5);	gr->Rotate(40,60);	gr->Box();	gr->TileS(x,y,z,c,"","meshnum 10");
+	gr->SubPlot(4,4,6);	gr->Rotate(40,60);	gr->Box();	gr->Axial(x,y,z,"","alpha 0.5;light on");
+	gr->SubPlot(4,4,7);	gr->Rotate(40,60);	gr->Box();	gr->Cont(x,y,z);
+	gr->SubPlot(4,4,8);	gr->Rotate(40,60);	gr->Box();	gr->ContF(x,y,z,"","light on");	gr->ContV(x,y,z,"","light on");
+	gr->SubPlot(4,4,9);	gr->Rotate(40,60);	gr->Box();	gr->Belt(x,y,z,"x","meshnum 10;light on");
+	gr->SubPlot(4,4,10);gr->Rotate(40,60);	gr->Box();	gr->Dens(x,y,z,"","alpha 0.5");
+	gr->SubPlot(4,4,11);gr->Rotate(40,60);	gr->Box();
+	gr->Fall(x,y,z,"g","meshnum 10");	gr->Fall(x,y,z,"rx","meshnum 10");
+	gr->SubPlot(4,4,12);	gr->Rotate(40,60);	gr->Box();	gr->Belt(x,y,z,"","meshnum 10;light on");
+	gr->SubPlot(4,4,13);	gr->Rotate(40,60);	gr->Box();	gr->Boxs(x,y,z,"","meshnum 10;light on");
+	gr->SubPlot(4,4,14);	gr->Rotate(40,60);	gr->Box();	gr->Boxs(x,y,z,"#","meshnum 10");
+	gr->SubPlot(4,4,15);	gr->Rotate(40,60);	gr->Box();	gr->Boxs(x,y,z,"@","meshnum 10;light on");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_param3="new x 50 50 50 '(x+2)/3*sin(pi*y/2)'\n"
+"new y 50 50 50 '(x+2)/3*cos(pi*y/2)'\nnew z 50 50 50 'z'\n"
+"new c 50 50 50 '-2*(x^2+y^2+z^4-z^2)+0.2'\n"
+"new d 50 50 50 '1-2*tanh(2*(x+y)^2)'\n\n"
+"alpha on:light on\n"
+"subplot 4 3 0:rotate 40 60:box:surf3 x y z c\n"
+"subplot 4 3 1:rotate 40 60:box:surf3c x y z c d\n"
+"subplot 4 3 2:rotate 40 60:box:surf3a x y z c d\n"
+"subplot 4 3 3:rotate 40 60:box:cloud x y z c\n"
+"subplot 4 3 4:rotate 40 60:box:cont3 x y z c:cont3 x y z c 'x':cont3 x y z c 'z'\n"
+"subplot 4 3 5:rotate 40 60:box:contf3 x y z c:contf3 x y z c 'x':contf3 x y z c 'z'\n"
+"subplot 4 3 6:rotate 40 60:box:dens3 x y z c:dens3 x y z c 'x':dens3 x y z c 'z'\n"
+"subplot 4 3 7:rotate 40 60:box:dots x y z c;meshnum 15\n"
+"subplot 4 3 8:rotate 40 60:box:densx c '' 0:densy c '' 0:densz c '' 0\n"
+"subplot 4 3 9:rotate 40 60:box:contx c '' 0:conty c '' 0:contz c '' 0\n"
+"subplot 4 3 10:rotate 40 60:box:contfx c '' 0:contfy c '' 0:contfz c '' 0";
+void smgl_param3(mglGraph *gr)	// 3d parametric plots
+{
+	mglData x(50,50,50), y(50,50,50), z(50,50,50), c(50,50,50), d(50,50,50);
+	gr->Fill(x,"(x+2)/3*sin(pi*y/2)");	gr->Fill(y,"(x+2)/3*cos(pi*y/2)");	gr->Fill(z,"z");
+	gr->Fill(c,"-2*(x^2+y^2+z^4-z^2)+0.2");	gr->Fill(d,"1-2*tanh(2*(x+y)^2)");
+
+	gr->Light(true);	gr->Alpha(true);
+	gr->SubPlot(4,3,0);	gr->Rotate(40,60);	gr->Box();	gr->Surf3(x,y,z,c);
+	gr->SubPlot(4,3,1);	gr->Rotate(40,60);	gr->Box();	gr->Surf3C(x,y,z,c,d);
+	gr->SubPlot(4,3,2);	gr->Rotate(40,60);	gr->Box();	gr->Surf3A(x,y,z,c,d);
+	gr->SubPlot(4,3,3);	gr->Rotate(40,60);	gr->Box();	gr->Cloud(x,y,z,c);
+	gr->SubPlot(4,3,4);	gr->Rotate(40,60);	gr->Box();	gr->Cont3(x,y,z,c);	gr->Cont3(x,y,z,c,"x");	gr->Cont3(x,y,z,c,"z");
+	gr->SubPlot(4,3,5);	gr->Rotate(40,60);	gr->Box();	gr->ContF3(x,y,z,c);gr->ContF3(x,y,z,c,"x");gr->ContF3(x,y,z,c,"z");
+	gr->SubPlot(4,3,6);	gr->Rotate(40,60);	gr->Box();	gr->Dens3(x,y,z,c);	gr->Dens3(x,y,z,c,"x");	gr->Dens3(x,y,z,c,"z");
+	gr->SubPlot(4,3,7);	gr->Rotate(40,60);	gr->Box();	gr->Dots(x,y,z,c,"","meshnum 15");
+	gr->SubPlot(4,3,8);	gr->Rotate(40,60);	gr->Box();	gr->DensX(c,"",0);	gr->DensY(c,"",0);	gr->DensZ(c,"",0);
+	gr->SubPlot(4,3,9);	gr->Rotate(40,60);	gr->Box();	gr->ContX(c,"",0);	gr->ContY(c,"",0);	gr->ContZ(c,"",0);
+	gr->SubPlot(4,3,10);gr->Rotate(40,60);	gr->Box();	gr->ContFX(c,"",0);	gr->ContFY(c,"",0);	gr->ContFZ(c,"",0);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_paramv="new x 20 20 20 '(x+2)/3*sin(pi*y/2)'\n"
+"new y 20 20 20 '(x+2)/3*cos(pi*y/2)'\nnew z 20 20 20 'z+x'\n"
+"new ex 20 20 20 'x'\nnew ey 20 20 20 'x^2+y'\nnew ez 20 20 20 'y^2+z'\n\n"
+"new x1 50 50 '(x+2)/3*sin(pi*y/2)'\n"
+"new y1 50 50 '(x+2)/3*cos(pi*y/2)'\n"
+"new e1 50 50 'x'\nnew e2 50 50 'x^2+y'\n\n"
+"subplot 3 3 0:rotate 40 60:box:vect x1 y1 e1 e2\n"
+"subplot 3 3 1:rotate 40 60:box:flow x1 y1 e1 e2\n"
+"subplot 3 3 2:rotate 40 60:box:pipe x1 y1 e1 e2\n"
+"subplot 3 3 3:rotate 40 60:box:dew x1 y1 e1 e2\n"
+"subplot 3 3 4:rotate 40 60:box:vect x y z ex ey ez\n"
+"subplot 3 3 5:rotate 40 60:box\n"
+"vect3 x y z ex ey ez:vect3 x y z ex ey ez 'x':vect3 x y z ex ey ez 'z'\n"
+"grid3 x y z z '{r9}':grid3 x y z z '{g9}x':grid3 x y z z '{b9}z'\n"
+"subplot 3 3 6:rotate 40 60:box:flow x y z ex ey ez\n"
+"subplot 3 3 7:rotate 40 60:box:pipe x y z ex ey ez";
+void smgl_paramv(mglGraph *gr)	// parametric plots for vector field
+{
+	mglData x(20,20,20), y(20,20,20), z(20,20,20), ex(20,20,20), ey(20,20,20), ez(20,20,20);
+	gr->Fill(x,"(x+2)/3*sin(pi*y/2)");	gr->Fill(y,"(x+2)/3*cos(pi*y/2)");	gr->Fill(z,"x+z");
+	gr->Fill(ex,"x");	gr->Fill(ey,"x^2+y");	gr->Fill(ez,"y^2+z");
+	mglData x1(20,20), y1(20,20), e1(20,20), e2(20,20);
+	gr->Fill(x1,"(x+2)/3*sin(pi*y/2)");	gr->Fill(y1,"(x+2)/3*cos(pi*y/2)");
+	gr->Fill(e1,"x");	gr->Fill(e2,"x^2+y");
+
+	gr->SubPlot(3,3,0);	gr->Rotate(40,60);	gr->Box();	gr->Vect(x1,y1,e1,e2);
+	gr->SubPlot(3,3,1);	gr->Rotate(40,60);	gr->Box();	gr->Flow(x1,y1,e1,e2);
+	gr->SubPlot(3,3,2);	gr->Rotate(40,60);	gr->Box();	gr->Pipe(x1,y1,e1,e2);
+	gr->SubPlot(3,3,3);	gr->Rotate(40,60);	gr->Box();	gr->Dew(x1,y1,e1,e2);
+	gr->SubPlot(3,3,4);	gr->Rotate(40,60);	gr->Box();	gr->Vect(x,y,z,ex,ey,ez);
+	gr->SubPlot(3,3,5);	gr->Rotate(40,60);	gr->Box();
+	gr->Vect3(x,y,z,ex,ey,ez);	gr->Vect3(x,y,z,ex,ey,ez,"x");	gr->Vect3(x,y,z,ex,ey,ez,"z");
+	gr->Grid3(x,y,z,z,"{r9}");	gr->Grid3(x,y,z,z,"{g9}x");		gr->Grid3(x,y,z,z,"{b9}z");
+	gr->SubPlot(3,3,6);	gr->Rotate(40,60);	gr->Box();	gr->Flow(x,y,z,ex,ey,ez);
+	gr->SubPlot(3,3,7);	gr->Rotate(40,60);	gr->Box();	gr->Pipe(x,y,z,ex,ey,ez);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_solve="zrange 0 1\nnew x 20 30 '(x+2)/3*cos(pi*y)'\n"
+"new y 20 30 '(x+2)/3*sin(pi*y)'\nnew z 20 30 'exp(-6*x^2-2*sin(pi*y)^2)'\n\n"
+"subplot 2 1 0:title 'Cartesian space':rotate 30 -40\naxis 'xyzU':box\nxlabel 'x':ylabel 'y'\n"
+"origin 1 1:grid 'xy'\nmesh x y z\n\n"
+"# section along 'x' direction\nsolve u x 0.5 'x'\nvar v u.nx 0 1\n"
+"evaluate yy y u v\nevaluate xx x u v\nevaluate zz z u v\nplot xx yy zz 'k2o'\n\n"
+"# 1st section along 'y' direction\nsolve u1 x -0.5 'y'\nvar v1 u1.nx 0 1\n"
+"evaluate yy y v1 u1\nevaluate xx x v1 u1\nevaluate zz z v1 u1\nplot xx yy zz 'b2^'\n\n"
+"# 2nd section along 'y' direction\nsolve u2 x -0.5 'y' u1\n"
+"evaluate yy y v1 u2\nevaluate xx x v1 u2\nevaluate zz z v1 u2\nplot xx yy zz 'r2v'\n\n"
+"subplot 2 1 1:title 'Accompanied space'\nranges 0 1 0 1:origin 0 0\n"
+"axis:box:xlabel 'i':ylabel 'j':grid2 z 'h'\n\n"
+"plot u v 'k2o':line 0.4 0.5 0.8 0.5 'kA'\n"
+"plot v1 u1 'b2^':line 0.5 0.15 0.5 0.3 'bA'\n"
+"plot v1 u2 'r2v':line 0.5 0.7 0.5 0.85 'rA'";
+void smgl_solve(mglGraph *gr)	// solve and evaluate
+{
+	gr->SetRange('z',0,1);
+	mglData x(20,30), y(20,30), z(20,30), xx,yy,zz;
+	gr->Fill(x,"(x+2)/3*cos(pi*y)");
+	gr->Fill(y,"(x+2)/3*sin(pi*y)");
+	gr->Fill(z,"exp(-6*x^2-2*sin(pi*y)^2)");
+
+	gr->SubPlot(2,1,0);	gr->Title("Cartesian space");	gr->Rotate(30,-40);
+	gr->Axis("xyzU");	gr->Box();	gr->Label('x',"x");	gr->Label('y',"y");
+	gr->SetOrigin(1,1);	gr->Grid("xy");
+	gr->Mesh(x,y,z);
+
+	// section along 'x' direction
+	mglData u = x.Solve(0.5,'x');
+	mglData v(u.nx);	v.Fill(0,1);
+	xx = x.Evaluate(u,v);	yy = y.Evaluate(u,v);	zz = z.Evaluate(u,v);
+	gr->Plot(xx,yy,zz,"k2o");
+
+	// 1st section along 'y' direction
+	mglData u1 = x.Solve(-0.5,'y');
+	mglData v1(u1.nx);	v1.Fill(0,1);
+	xx = x.Evaluate(v1,u1);	yy = y.Evaluate(v1,u1);	zz = z.Evaluate(v1,u1);
+	gr->Plot(xx,yy,zz,"b2^");
+
+	// 2nd section along 'y' direction
+	mglData u2 = x.Solve(-0.5,'y',u1);
+	xx = x.Evaluate(v1,u2);	yy = y.Evaluate(v1,u2);	zz = z.Evaluate(v1,u2);
+	gr->Plot(xx,yy,zz,"r2v");
+
+	gr->SubPlot(2,1,1);	gr->Title("Accompanied space");
+	gr->SetRanges(0,1,0,1);	gr->SetOrigin(0,0);
+	gr->Axis();	gr->Box();	gr->Label('x',"i");	gr->Label('y',"j");
+	gr->Grid(z,"h");
+
+	gr->Plot(u,v,"k2o");	gr->Line(mglPoint(0.4,0.5),mglPoint(0.8,0.5),"kA");
+	gr->Plot(v1,u1,"b2^");	gr->Line(mglPoint(0.5,0.15),mglPoint(0.5,0.3),"bA");
+	gr->Plot(v1,u2,"r2v");	gr->Line(mglPoint(0.5,0.7),mglPoint(0.5,0.85),"rA");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_triangulation="new x 100 '2*rnd-1':new y 100 '2*rnd-1':copy z x^2-y^2\n"
+"new g 30 30:triangulate d x y\n"
+"title 'Triangulation'\nrotate 50 60:box:light on\n"
+"triplot d x y z:triplot d x y z '#k'\ndatagrid g x y z:mesh g 'm'";
+void smgl_triangulation(mglGraph *gr)	// surface triangulation
+{
+	mglData x(100), y(100), z(100);
+	gr->Fill(x,"2*rnd-1");	gr->Fill(y,"2*rnd-1");	gr->Fill(z,"v^2-w^2",x,y);
+	mglData d = mglTriangulation(x,y), g(30,30);
+
+	if(big!=3)	gr->Title("Triangulation");
+	gr->Rotate(40,60);	gr->Box();	gr->Light(true);
+	gr->TriPlot(d,x,y,z);	gr->TriPlot(d,x,y,z,"#k");
+
+	gr->DataGrid(g,x,y,z);	gr->Mesh(g,"m");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_alpha="call 'prepare2d'\nsubplot 2 2 0:title 'default':rotate 50 60:box\nsurf a\n"
+"subplot 2 2 1:title 'light on':rotate 50 60:box\nlight on:surf a\n"
+"subplot 2 2 3:title 'light on; alpha on':rotate 50 60:box\nalpha on:surf a\n"
+"subplot 2 2 2:title 'alpha on':rotate 50 60:box\nlight off:surf a";
+void smgl_alpha(mglGraph *gr)	// alpha and lighting
+{
+	mglData a;	mgls_prepare2d(&a);
+	gr->SubPlot(2,2,0);	gr->Title("default");	gr->Rotate(50,60);
+	gr->Box();	gr->Surf(a);
+	gr->SubPlot(2,2,1);	gr->Title("light on");	gr->Rotate(50,60);
+	gr->Box();	gr->Light(true);	gr->Surf(a);
+	gr->SubPlot(2,2,3);	gr->Title("alpha on; light on");	gr->Rotate(50,60);
+	gr->Box();	gr->Alpha(true);	gr->Surf(a);
+	gr->SubPlot(2,2,2);	gr->Title("alpha on");	gr->Rotate(50,60);
+	gr->Box();	gr->Light(false);	gr->Surf(a);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_schemes="new x 100 100 'x':new y 100 100 'y'\n"
+"call 'sch' 0 'kw'\ncall 'sch' 1 '%gbrw'\ncall 'sch' 2 'kHCcw'\ncall 'sch' 3 'kBbcw'\n"
+"call 'sch' 4 'kRryw'\ncall 'sch' 5 'kGgew'\ncall 'sch' 6 'BbwrR'\ncall 'sch' 7 'BbwgG'\n"
+"call 'sch' 8 'GgwmM'\ncall 'sch' 9 'UuwqR'\ncall 'sch' 10 'QqwcC'\ncall 'sch' 11 'CcwyY'\n"
+"call 'sch' 12 'bcwyr'\ncall 'sch' 13 'bwr'\ncall 'sch' 14 'wUrqy'\ncall 'sch' 15 'UbcyqR'\n"
+"call 'sch' 16 'BbcyrR'\ncall 'sch' 17 'bgr'\ncall 'sch' 18 'BbcyrR|'\ncall 'sch' 19 'b{g,0.3}r'\n"
+"stop\nfunc 'sch' 2\nsubplot 2 10 $1 '<>_^' 0.2 0:surfa x y $2\n"
+"text 0.07+0.5*mod($1,2) 0.92-0.1*int($1/2) $2 'A'\nreturn";
+void smgl_schemes(mglGraph *gr)	// Color table
+{
+	mglData a(256,2), b(256,2);	a.Fill(-1,1);	b.Fill(-1,1,'y');
+	gr->SubPlot(2,10,0,NULL,0.2);	gr->Dens(a,"kw");		gr->Puts(0.07, 0.92, "kw", "A");
+	gr->SubPlot(2,10,1,NULL,0.2);	gr->SurfA(a,b,"%gbrw");	gr->Puts(0.57, 0.92, "%gbrw", "A");
+	gr->SubPlot(2,10,2,NULL,0.2);	gr->Dens(a,"kHCcw");	gr->Puts(0.07, 0.82, "kHCcw", "A");
+	gr->SubPlot(2,10,3,NULL,0.2);	gr->Dens(a,"kBbcw");	gr->Puts(0.57, 0.82, "kBbcw", "A");
+	gr->SubPlot(2,10,4,NULL,0.2);	gr->Dens(a,"kRryw");	gr->Puts(0.07, 0.72, "kRryw", "A");
+	gr->SubPlot(2,10,5,NULL,0.2);	gr->Dens(a,"kGgew");	gr->Puts(0.57, 0.72, "kGgew", "A");
+	gr->SubPlot(2,10,6,NULL,0.2);	gr->Dens(a,"BbwrR");	gr->Puts(0.07, 0.62, "BbwrR", "A");
+	gr->SubPlot(2,10,7,NULL,0.2);	gr->Dens(a,"BbwgG");	gr->Puts(0.57, 0.62, "BbwgG", "A");
+	gr->SubPlot(2,10,8,NULL,0.2);	gr->Dens(a,"GgwmM");	gr->Puts(0.07, 0.52, "GgwmM", "A");
+	gr->SubPlot(2,10,9,NULL,0.2);	gr->Dens(a,"UuwqR");	gr->Puts(0.57, 0.52, "UuwqR", "A");
+	gr->SubPlot(2,10,10,NULL,0.2);	gr->Dens(a,"QqwcC");	gr->Puts(0.07, 0.42, "QqwcC", "A");
+	gr->SubPlot(2,10,11,NULL,0.2);	gr->Dens(a,"CcwyY");	gr->Puts(0.57, 0.42, "CcwyY", "A");
+	gr->SubPlot(2,10,12,NULL,0.2);	gr->Dens(a,"bcwyr");	gr->Puts(0.07, 0.32, "bcwyr", "A");
+	gr->SubPlot(2,10,13,NULL,0.2);	gr->Dens(a,"bwr");		gr->Puts(0.57, 0.32, "bwr", "A");
+	gr->SubPlot(2,10,14,NULL,0.2);	gr->Dens(a,"wUrqy");	gr->Puts(0.07, 0.22, "wUrqy", "A");
+	gr->SubPlot(2,10,15,NULL,0.2);	gr->Dens(a,"UbcyqR");	gr->Puts(0.57, 0.22, "UbcyqR", "A");
+	gr->SubPlot(2,10,16,NULL,0.2);	gr->Dens(a,"BbcyrR");	gr->Puts(0.07, 0.12, "BbcyrR", "A");
+	gr->SubPlot(2,10,17,NULL,0.2);	gr->Dens(a,"bgr");		gr->Puts(0.57, 0.12, "bgr", "A");
+	gr->SubPlot(2,10,18,NULL,0.2);	gr->Dens(a,"BbcyrR|");	gr->Puts(0.07, 0.02, "BbcyrR|", "A");
+	gr->SubPlot(2,10,19,NULL,0.2);	gr->Dens(a,"b{g,0.3}r");		gr->Puts(0.57, 0.02, "b\\{g,0.3\\}r", "A");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_curvcoor="origin -1 1 -1\nsubplot 2 2 0:title 'Cartesian':rotate 50 60:fplot '2*t-1' '0.5' '0' '2r':axis:grid\n"
+"axis 'y*sin(pi*x)' 'y*cos(pi*x)' '':subplot 2 2 1:title 'Cylindrical':rotate 50 60:fplot '2*t-1' '0.5' '0' '2r':axis:grid\n"
+"axis '2*y*x' 'y*y - x*x' '':subplot 2 2 2:title 'Parabolic':rotate 50 60:fplot '2*t-1' '0.5' '0' '2r':axis:grid\n"
+"axis 'y*sin(pi*x)' 'y*cos(pi*x)' 'x+z':subplot 2 2 3:title 'Spiral':rotate 50 60:fplot '2*t-1' '0.5' '0' '2r':axis:grid";
+void smgl_curvcoor(mglGraph *gr)	// curvilinear coordinates
+{
+	gr->SetOrigin(-1,1,-1);
+
+	gr->SubPlot(2,2,0);	gr->Title("Cartesian");	gr->Rotate(50,60);
+	gr->FPlot("2*t-1","0.5","0","r2");
+	gr->Axis(); gr->Grid();
+
+	gr->SetFunc("y*sin(pi*x)","y*cos(pi*x)",0);
+	gr->SubPlot(2,2,1);	gr->Title("Cylindrical");	gr->Rotate(50,60);
+	gr->FPlot("2*t-1","0.5","0","r2");
+	gr->Axis(); gr->Grid();
+
+	gr->SetFunc("2*y*x","y*y - x*x",0);
+	gr->SubPlot(2,2,2);	gr->Title("Parabolic");	gr->Rotate(50,60);
+	gr->FPlot("2*t-1","0.5","0","r2");
+	gr->Axis(); gr->Grid();
+
+	gr->SetFunc("y*sin(pi*x)","y*cos(pi*x)","x+z");
+	gr->SubPlot(2,2,3);	gr->Title("Spiral");	gr->Rotate(50,60);
+	gr->FPlot("2*t-1","0.5","0","r2");
+	gr->Axis(); gr->Grid();
+	gr->SetFunc(0,0,0);	// set to default Cartesian
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_style="";
+void smgl_style(mglGraph *gr)	// pen styles
+{
+	gr->SubPlot(2,2,0);
+	double d,x1,x2,x0,y=1.1, y1=1.15;
+	d=0.3, x0=0.2, x1=0.5, x2=0.6;
+	gr->Line(mglPoint(x0,y1-0*d),mglPoint(x1,y1-0*d),"k-");	gr->Puts(mglPoint(x2,y-0*d),"Solid '-'",":rL");
+	gr->Line(mglPoint(x0,y1-1*d),mglPoint(x1,y1-1*d),"k|");	gr->Puts(mglPoint(x2,y-1*d),"Long Dash '|'",":rL");
+	gr->Line(mglPoint(x0,y1-2*d),mglPoint(x1,y1-2*d),"k;");	gr->Puts(mglPoint(x2,y-2*d),"Dash ';'",":rL");
+	gr->Line(mglPoint(x0,y1-3*d),mglPoint(x1,y1-3*d),"k=");	gr->Puts(mglPoint(x2,y-3*d),"Small dash '='",":rL");
+	gr->Line(mglPoint(x0,y1-4*d),mglPoint(x1,y1-4*d),"kj");	gr->Puts(mglPoint(x2,y-4*d),"Dash-dot 'j'",":rL");
+	gr->Line(mglPoint(x0,y1-5*d),mglPoint(x1,y1-5*d),"ki");	gr->Puts(mglPoint(x2,y-5*d),"Small dash-dot 'i'",":rL");
+	gr->Line(mglPoint(x0,y1-6*d),mglPoint(x1,y1-6*d),"k:");	gr->Puts(mglPoint(x2,y-6*d),"Dots ':'",":rL");
+	gr->Line(mglPoint(x0,y1-7*d),mglPoint(x1,y1-7*d),"k ");	gr->Puts(mglPoint(x2,y-7*d),"None ' '",":rL");
+	gr->Line(mglPoint(x0,y1-8*d),mglPoint(x1,y1-8*d),"k{df090}");	gr->Puts(mglPoint(x2,y-8*d),"Manual '{df090}'",":rL");
+
+	d=0.25; x1=-1; x0=-0.8;	y = -0.05;
+	gr->Mark(mglPoint(x1,5*d),"k.");		gr->Puts(mglPoint(x0,y+5*d),"'.'",":rL");
+	gr->Mark(mglPoint(x1,4*d),"k+");		gr->Puts(mglPoint(x0,y+4*d),"'+'",":rL");
+	gr->Mark(mglPoint(x1,3*d),"kx");		gr->Puts(mglPoint(x0,y+3*d),"'x'",":rL");
+	gr->Mark(mglPoint(x1,2*d),"k*");		gr->Puts(mglPoint(x0,y+2*d),"'*'",":rL");
+	gr->Mark(mglPoint(x1,d),"ks");		gr->Puts(mglPoint(x0,y+d),"'s'",":rL");
+	gr->Mark(mglPoint(x1,0),"kd");		gr->Puts(mglPoint(x0,y),"'d'",":rL");
+	gr->Mark(mglPoint(x1,-d,0),"ko");	gr->Puts(mglPoint(x0,y-d),"'o'",":rL");
+	gr->Mark(mglPoint(x1,-2*d,0),"k^");	gr->Puts(mglPoint(x0,y-2*d),"'\\^'",":rL");
+	gr->Mark(mglPoint(x1,-3*d,0),"kv");	gr->Puts(mglPoint(x0,y-3*d),"'v'",":rL");
+	gr->Mark(mglPoint(x1,-4*d,0),"k<");	gr->Puts(mglPoint(x0,y-4*d),"'<'",":rL");
+	gr->Mark(mglPoint(x1,-5*d,0),"k>");	gr->Puts(mglPoint(x0,y-5*d),"'>'",":rL");
+
+	d=0.25; x1=-0.5; x0=-0.3;	y = -0.05;
+	gr->Mark(mglPoint(x1,5*d),"k#.");	gr->Puts(mglPoint(x0,y+5*d),"'\\#.'",":rL");
+	gr->Mark(mglPoint(x1,4*d),"k#+");	gr->Puts(mglPoint(x0,y+4*d),"'\\#+'",":rL");
+	gr->Mark(mglPoint(x1,3*d),"k#x");	gr->Puts(mglPoint(x0,y+3*d),"'\\#x'",":rL");
+	gr->Mark(mglPoint(x1,2*d),"k#*");	gr->Puts(mglPoint(x0,y+2*d),"'\\#*'",":rL");
+	gr->Mark(mglPoint(x1,d),"k#s");		gr->Puts(mglPoint(x0,y+d),"'\\#s'",":rL");
+	gr->Mark(mglPoint(x1,0),"k#d");		gr->Puts(mglPoint(x0,y),"'\\#d'",":rL");
+	gr->Mark(mglPoint(x1,-d,0),"k#o");	gr->Puts(mglPoint(x0,y-d),"'\\#o'",":rL");
+	gr->Mark(mglPoint(x1,-2*d,0),"k#^");	gr->Puts(mglPoint(x0,y-2*d),"'\\#\\^'",":rL");
+	gr->Mark(mglPoint(x1,-3*d,0),"k#v");	gr->Puts(mglPoint(x0,y-3*d),"'\\#v'",":rL");
+	gr->Mark(mglPoint(x1,-4*d,0),"k#<");	gr->Puts(mglPoint(x0,y-4*d),"'\\#<'",":rL");
+	gr->Mark(mglPoint(x1,-5*d,0),"k#>");	gr->Puts(mglPoint(x0,y-5*d),"'\\#>'",":rL");
+
+	gr->SubPlot(2,2,1);
+	double a=0.1,b=0.4,c=0.5;
+	gr->Line(mglPoint(a,1),mglPoint(b,1),"k-A");		gr->Puts(mglPoint(c,1),"Style 'A' or 'A\\_'",":rL");
+	gr->Line(mglPoint(a,0.8),mglPoint(b,0.8),"k-V");	gr->Puts(mglPoint(c,0.8),"Style 'V' or 'V\\_'",":rL");
+	gr->Line(mglPoint(a,0.6),mglPoint(b,0.6),"k-K");	gr->Puts(mglPoint(c,0.6),"Style 'K' or 'K\\_'",":rL");
+	gr->Line(mglPoint(a,0.4),mglPoint(b,0.4),"k-I");	gr->Puts(mglPoint(c,0.4),"Style 'I' or 'I\\_'",":rL");
+	gr->Line(mglPoint(a,0.2),mglPoint(b,0.2),"k-D");	gr->Puts(mglPoint(c,0.2),"Style 'D' or 'D\\_'",":rL");
+	gr->Line(mglPoint(a,0),mglPoint(b,0),"k-S");		gr->Puts(mglPoint(c,0),"Style 'S' or 'S\\_'",":rL");
+	gr->Line(mglPoint(a,-0.2),mglPoint(b,-0.2),"k-O");	gr->Puts(mglPoint(c,-0.2),"Style 'O' or 'O\\_'",":rL");
+	gr->Line(mglPoint(a,-0.4),mglPoint(b,-0.4),"k-T");	gr->Puts(mglPoint(c,-0.4),"Style 'T' or 'T\\_'",":rL");
+	gr->Line(mglPoint(a,-0.6),mglPoint(b,-0.6),"k-X");	gr->Puts(mglPoint(c,-0.6),"Style 'X' or 'X\\_'",":rL");
+	gr->Line(mglPoint(a,-0.8),mglPoint(b,-0.8),"k-_");	gr->Puts(mglPoint(c,-0.8),"Style '\\_' or none",":rL");
+	gr->Line(mglPoint(a,-1),mglPoint(b,-1),"k-AS");		gr->Puts(mglPoint(c,-1),"Style 'AS'",":rL");
+	gr->Line(mglPoint(a,-1.2),mglPoint(b,-1.2),"k-_A");	gr->Puts(mglPoint(c,-1.2),"Style '\\_A'",":rL");
+
+	a=-1;	b=-0.7;	c=-0.6;
+	gr->Line(mglPoint(a,1),mglPoint(b,1),"kAA");		gr->Puts(mglPoint(c,1),"Style 'AA'",":rL");
+	gr->Line(mglPoint(a,0.8),mglPoint(b,0.8),"kVV");	gr->Puts(mglPoint(c,0.8),"Style 'VV'",":rL");
+	gr->Line(mglPoint(a,0.6),mglPoint(b,0.6),"kKK");	gr->Puts(mglPoint(c,0.6),"Style 'KK'",":rL");
+	gr->Line(mglPoint(a,0.4),mglPoint(b,0.4),"kII");	gr->Puts(mglPoint(c,0.4),"Style 'II'",":rL");
+	gr->Line(mglPoint(a,0.2),mglPoint(b,0.2),"kDD");	gr->Puts(mglPoint(c,0.2),"Style 'DD'",":rL");
+	gr->Line(mglPoint(a,0),mglPoint(b,0),"kSS");		gr->Puts(mglPoint(c,0),"Style 'SS'",":rL");
+	gr->Line(mglPoint(a,-0.2),mglPoint(b,-0.2),"kOO");	gr->Puts(mglPoint(c,-0.2),"Style 'OO'",":rL");
+	gr->Line(mglPoint(a,-0.4),mglPoint(b,-0.4),"kTT");	gr->Puts(mglPoint(c,-0.4),"Style 'TT'",":rL");
+	gr->Line(mglPoint(a,-0.6),mglPoint(b,-0.6),"kXX");	gr->Puts(mglPoint(c,-0.6),"Style 'XX'",":rL");
+	gr->Line(mglPoint(a,-0.8),mglPoint(b,-0.8),"k-__");	gr->Puts(mglPoint(c,-0.8),"Style '\\_\\_'",":rL");
+	gr->Line(mglPoint(a,-1),mglPoint(b,-1),"k-VA");		gr->Puts(mglPoint(c,-1),"Style 'VA'",":rL");
+	gr->Line(mglPoint(a,-1.2),mglPoint(b,-1.2),"k-AV");	gr->Puts(mglPoint(c,-1.2),"Style 'AV'",":rL");
+
+	gr->SubPlot(2,2,2);
+	//#LENUQ
+	gr->FaceZ(mglPoint(-1,	-1), 0.4, 0.3, "L#");	gr->Puts(mglPoint(-0.8,-0.9), "L", "w:C", -1.4);
+	gr->FaceZ(mglPoint(-0.6,-1), 0.4, 0.3, "E#");	gr->Puts(mglPoint(-0.4,-0.9), "E", "w:C", -1.4);
+	gr->FaceZ(mglPoint(-0.2,-1), 0.4, 0.3, "N#");	gr->Puts(mglPoint(0,  -0.9), "N", "w:C", -1.4);
+	gr->FaceZ(mglPoint(0.2,	-1), 0.4, 0.3, "U#");	gr->Puts(mglPoint(0.4,-0.9), "U", "w:C", -1.4);
+	gr->FaceZ(mglPoint(0.6,	-1), 0.4, 0.3, "Q#");	gr->Puts(mglPoint(0.8,-0.9), "Q", "w:C", -1.4);
+	//#lenuq
+	gr->FaceZ(mglPoint(-1,	-0.7), 0.4, 0.3, "l#");	gr->Puts(mglPoint(-0.8,-0.6), "l", "k:C", -1.4);
+	gr->FaceZ(mglPoint(-0.6,-0.7), 0.4, 0.3, "e#");	gr->Puts(mglPoint(-0.4,-0.6), "e", "k:C", -1.4);
+	gr->FaceZ(mglPoint(-0.2,-0.7), 0.4, 0.3, "n#");	gr->Puts(mglPoint(0,  -0.6), "n", "k:C", -1.4);
+	gr->FaceZ(mglPoint(0.2,	-0.7), 0.4, 0.3, "u#");	gr->Puts(mglPoint(0.4,-0.6), "u", "k:C", -1.4);
+	gr->FaceZ(mglPoint(0.6,	-0.7), 0.4, 0.3, "q#");	gr->Puts(mglPoint(0.8,-0.6), "q", "k:C", -1.4);
+	//#CMYkP
+	gr->FaceZ(mglPoint(-1,	-0.4), 0.4, 0.3, "C#");	gr->Puts(mglPoint(-0.8,-0.3), "C", "w:C", -1.4);
+	gr->FaceZ(mglPoint(-0.6,-0.4), 0.4, 0.3, "M#");	gr->Puts(mglPoint(-0.4,-0.3), "M", "w:C", -1.4);
+	gr->FaceZ(mglPoint(-0.2,-0.4), 0.4, 0.3, "Y#");	gr->Puts(mglPoint(0,  -0.3), "Y", "w:C", -1.4);
+	gr->FaceZ(mglPoint(0.2,	-0.4), 0.4, 0.3, "k#");	gr->Puts(mglPoint(0.4,-0.3), "k", "w:C", -1.4);
+	gr->FaceZ(mglPoint(0.6,	-0.4), 0.4, 0.3, "P#");	gr->Puts(mglPoint(0.8,-0.3), "P", "w:C", -1.4);
+	//#cmywp
+	gr->FaceZ(mglPoint(-1,	-0.1), 0.4, 0.3, "c#");	gr->Puts(mglPoint(-0.8, 0), "c", "k:C", -1.4);
+	gr->FaceZ(mglPoint(-0.6,-0.1), 0.4, 0.3, "m#");	gr->Puts(mglPoint(-0.4, 0), "m", "k:C", -1.4);
+	gr->FaceZ(mglPoint(-0.2,-0.1), 0.4, 0.3, "y#");	gr->Puts(mglPoint(0,   0), "y", "k:C", -1.4);
+	gr->FaceZ(mglPoint(0.2,	-0.1), 0.4, 0.3, "w#");	gr->Puts(mglPoint(0.4, 0), "w", "k:C", -1.4);
+	gr->FaceZ(mglPoint(0.6,	-0.1), 0.4, 0.3, "p#");	gr->Puts(mglPoint(0.8, 0), "p", "k:C", -1.4);
+	//#BGRHW
+	gr->FaceZ(mglPoint(-1,	0.2), 0.4, 0.3, "B#");	gr->Puts(mglPoint(-0.8, 0.3), "B", "w:C", -1.4);
+	gr->FaceZ(mglPoint(-0.6,0.2), 0.4, 0.3, "G#");	gr->Puts(mglPoint(-0.4, 0.3), "G", "w:C", -1.4);
+	gr->FaceZ(mglPoint(-0.2,0.2), 0.4, 0.3, "R#");	gr->Puts(mglPoint(0,   0.3), "R", "w:C", -1.4);
+	gr->FaceZ(mglPoint(0.2,	0.2), 0.4, 0.3, "H#");	gr->Puts(mglPoint(0.4, 0.3), "H", "w:C", -1.4);
+	gr->FaceZ(mglPoint(0.6,	0.2), 0.4, 0.3, "W#");	gr->Puts(mglPoint(0.8, 0.3), "W", "w:C", -1.4);
+	//#bgrhw
+	gr->FaceZ(mglPoint(-1,	0.5), 0.4, 0.3, "b#");	gr->Puts(mglPoint(-0.8, 0.6), "b", "k:C", -1.4);
+	gr->FaceZ(mglPoint(-0.6,0.5), 0.4, 0.3, "g#");	gr->Puts(mglPoint(-0.4, 0.6), "g", "k:C", -1.4);
+	gr->FaceZ(mglPoint(-0.2,0.5), 0.4, 0.3, "r#");	gr->Puts(mglPoint(0,   0.6), "r", "k:C", -1.4);
+	gr->FaceZ(mglPoint(0.2,	0.5), 0.4, 0.3, "h#");	gr->Puts(mglPoint(0.4, 0.6), "h", "k:C", -1.4);
+	gr->FaceZ(mglPoint(0.6,	0.5), 0.4, 0.3, "w#");	gr->Puts(mglPoint(0.8, 0.6), "w", "k:C", -1.4);
+	//#brighted
+	gr->FaceZ(mglPoint(-1,	0.8), 0.4, 0.3, "{r1}#");	gr->Puts(mglPoint(-0.8, 0.9), "\\{r1\\}", "w:C", -1.4);
+	gr->FaceZ(mglPoint(-0.6,0.8), 0.4, 0.3, "{r3}#");	gr->Puts(mglPoint(-0.4, 0.9), "\\{r3\\}", "w:C", -1.4);
+	gr->FaceZ(mglPoint(-0.2,0.8), 0.4, 0.3, "{r5}#");	gr->Puts(mglPoint(0,   0.9), "\\{r5\\}", "k:C", -1.4);
+	gr->FaceZ(mglPoint(0.2,	0.8), 0.4, 0.3, "{r7}#");	gr->Puts(mglPoint(0.4, 0.9), "\\{r7\\}", "k:C", -1.4);
+	gr->FaceZ(mglPoint(0.6,	0.8), 0.4, 0.3, "{r9}#");	gr->Puts(mglPoint(0.8, 0.9), "\\{r9\\}", "k:C", -1.4);
+	// HEX
+	gr->FaceZ(mglPoint(-1, -1.3), 1, 0.3, "{xff9966}#");	gr->Puts(mglPoint(-0.5,-1.2), "\\{xff9966\\}", "k:C", -1.4);
+	gr->FaceZ(mglPoint(0,  -1.3), 1, 0.3, "{x83CAFF}#");	gr->Puts(mglPoint( 0.5,-1.2), "\\{x83CAFF\\}", "k:C", -1.4);
+
+	gr->SubPlot(2,2,3);
+	char stl[3]="r1", txt[4]="'1'";
+	for(int i=0;i<10;i++)
+	{
+		txt[1]=stl[1]='0'+i;
+		gr->Line(mglPoint(-1,0.2*i-1),mglPoint(1,0.2*i-1),stl);
+		gr->Puts(mglPoint(1.05,0.2*i-1),txt,":L");
+	}
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_text="call 'prepare1d'\nsubplot 2 2 0 ''\ntext 0 1 'Text can be in ASCII and in Unicode'\n"
+"text 0 0.6 'It can be \\wire{wire}, \\big{big} or #r{colored}'\n"
+"text 0 0.2 'One can change style in string: \\b{bold}, \\i{italic, \\b{both}}'\n"
+"text 0 -0.2 'Easy to \\a{overline} or \\u{underline}'\n"
+"text 0 -0.6 'Easy to change indexes ^{up} _{down} @{center}'\n"
+"text 0 -1 'It parse TeX: \\int \\alpha \\cdot \\\n\\sqrt3{sin(\\pi x)^2 + \\gamma_{i_k}} dx'\n"
+"subplot 2 2 1 ''\n text 0 0.5 '\\sqrt{\\frac{\\alpha^{\\gamma^2}+\\overset 1{\\big\\infty}}{\\sqrt3{2+b}}}' '@' -2\n"
+"text 0 -0.3 'Text can be printed\\n{}on several lines'\n"
+"text 0 -0.7 'or with color gradient' 'BbcyrR'\n"
+"subplot 2 2 2 '':box:plot y(:,0)\ntext y 'This is very very long string drawn along a curve' 'k'\ntext y 'Another string drawn above a curve' 'Tr'\n"
+"subplot 2 2 3 '':line -1 -1 1 -1 'rA':text 0 -1 1 -1 'Horizontal'\n"
+"line -1 -1 1 1 'rA':text 0 0 1 1 'At angle' '@'\nline -1 -1 -1 1 'rA':text -1 0 -1 1 'Vertical'";
+void smgl_text(mglGraph *gr)	// text drawing
+{
+	if(big!=3)	gr->SubPlot(2,2,0,"");
+	gr->Putsw(mglPoint(0,1),L"Text can be in ASCII and in Unicode");
+	gr->Puts(mglPoint(0,0.6),"It can be \\wire{wire}, \\big{big} or #r{colored}");
+	gr->Puts(mglPoint(0,0.2),"One can change style in string: "
+	"\\b{bold}, \\i{italic, \\b{both}}");
+	gr->Puts(mglPoint(0,-0.2),"Easy to \\a{overline} or "
+	"\\u{underline}");
+	gr->Puts(mglPoint(0,-0.6),"Easy to change indexes ^{up} _{down} @{center}");
+	gr->Puts(mglPoint(0,-1),"It parse TeX: \\int \\alpha \\cdot "
+	"\\sqrt3{sin(\\pi x)^2 + \\gamma_{i_k}} dx");
+	if(big==3)	return;
+
+	gr->SubPlot(2,2,1,"");
+	gr->Puts(mglPoint(0,0.5), "\\sqrt{\\frac{\\alpha^{\\gamma^2}+\\overset 1{\\big\\infty}}{\\sqrt3{2+b}}}", "@", -2);
+	gr->Puts(mglPoint(0,-0.3),"Text can be printed\non several lines");
+	gr->Puts(mglPoint(0,-0.7),"or with col\bor gradient","BbcyrR");
+
+	gr->SubPlot(2,2,2,"");
+	mglData y;	mgls_prepare1d(&y);
+	gr->Box();	gr->Plot(y.SubData(-1,0));
+	gr->Text(y,"This is very very long string drawn along a curve","k");
+	gr->Text(y,"Another string drawn under a curve","Tr");
+
+	gr->SubPlot(2,2,3,"");
+	gr->Line(mglPoint(-1,-1),mglPoint(1,-1),"rA");	gr->Puts(mglPoint(0,-1),mglPoint(1,-1),"Horizontal");
+	gr->Line(mglPoint(-1,-1),mglPoint(1,1),"rA");	gr->Puts(mglPoint(0,0),mglPoint(1,1),"At angle","@");
+	gr->Line(mglPoint(-1,-1),mglPoint(-1,1),"rA");	gr->Puts(mglPoint(-1,0),mglPoint(-1,1),"Vertical");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_text2="call 'prepare1d'\n"
+"subplot 1 3 0 '':box:plot y(:,0)\ntext y 'This is very very long string drawn along a curve' 'k'\ntext y 'Another string drawn under a curve' 'Tr'\n"
+"subplot 1 3 1 '':box:plot y(:,0)\ntext y 'This is very very long string drawn along a curve' 'k:C'\ntext y 'Another string drawn under a curve' 'Tr:C'\n"
+"subplot 1 3 2 '':box:plot y(:,0)\ntext y 'This is very very long string drawn along a curve' 'k:R'\ntext y 'Another string drawn under a curve' 'Tr:R'";
+void smgl_text2(mglGraph *gr)	// text drawing
+{
+	mglData y;	mgls_prepare1d(&y);
+	if(big!=3)	gr->SubPlot(1,3,0,"");
+	gr->Box();	gr->Plot(y.SubData(-1,0));
+	gr->Text(y,"This is very very long string drawn along a curve","k");
+	gr->Text(y,"Another string drawn under a curve","Tr");
+	if(big==3)	return;
+
+	gr->SubPlot(1,3,1,"");
+	gr->Box();	gr->Plot(y.SubData(-1,0));
+	gr->Text(y,"This is very very long string drawn along a curve","k:C");
+	gr->Text(y,"Another string drawn under a curve","Tr:C");
+
+	gr->SubPlot(1,3,2,"");
+	gr->Box();	gr->Plot(y.SubData(-1,0));
+	gr->Text(y,"This is very very long string drawn along a curve","k:R");
+	gr->Text(y,"Another string drawn under a curve","Tr:R");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_fonts="define d 0.25\nloadfont 'STIX':text 0 1.1 'default font (STIX)'\nloadfont 'adventor':text 0 1.1-d 'adventor font'\n"
+"loadfont 'bonum':text 0 1.1-2*d 'bonum font'\nloadfont 'chorus':text 0 1.1-3*d 'chorus font'\nloadfont 'cursor':text 0 1.1-4*d 'cursor font'\n"
+"loadfont 'heros':text 0 1.1-5*d 'heros font'\nloadfont 'heroscn':text 0 1.1-6*d 'heroscn font'\nloadfont 'pagella':text 0 1.1-7*d 'pagella font'\n"
+"loadfont 'schola':text 0 1.1-8*d 'schola font'\nloadfont 'termes':text 0 1.1-9*d 'termes font'\nloadfont ''";
+void smgl_fonts(mglGraph *gr)	// font typefaces
+{
+	double h=1.1, d=0.25;
+	gr->LoadFont("STIX");		gr->Puts(mglPoint(0,h), "default font (STIX)");
+	gr->LoadFont("adventor");	gr->Puts(mglPoint(0,h-d), "adventor font");
+	gr->LoadFont("bonum");		gr->Puts(mglPoint(0,h-2*d), "bonum font");
+	gr->LoadFont("chorus");		gr->Puts(mglPoint(0,h-3*d), "chorus font");
+	gr->LoadFont("cursor");		gr->Puts(mglPoint(0,h-4*d), "cursor font");
+	gr->LoadFont("heros");		gr->Puts(mglPoint(0,h-5*d), "heros font");
+	gr->LoadFont("heroscn");	gr->Puts(mglPoint(0,h-6*d), "heroscn font");
+	gr->LoadFont("pagella");	gr->Puts(mglPoint(0,h-7*d), "pagella font");
+	gr->LoadFont("schola");		gr->Puts(mglPoint(0,h-8*d), "schola font");
+	gr->LoadFont("termes");		gr->Puts(mglPoint(0,h-9*d), "termes font");
+	gr->LoadFont("");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_bars="new ys 10 3 '0.8*sin(pi*(x+y/4+1.25))+0.2*rnd':origin 0 0 0\n"
+"subplot 3 2 0 '':title 'Bars plot (default)':box:bars ys\nsubplot 3 2 1 '':title '2 colors':box:bars ys 'cbgGyr'\n"
+"subplot 3 2 4 '':title '\"\\#\" style':box:bars ys '#'\n"
+"new yc 30 'sin(pi*x)':new xc 30 'cos(pi*x)':new z 30 'x'\nsubplot 3 2 5:title '3d variant':rotate 50 60:box:bars xc yc z 'r'\n"
+"ranges -1 1 -3 3:subplot 3 2 2 '':title '\"a\" style':box:bars ys 'a'\nsubplot 3 2 3 '':title '\"f\" style':box:bars ys 'f'";
+void smgl_bars(mglGraph *gr)
+{
+	mglData ys(10,3);	ys.Modify("0.8*sin(pi*(2*x+y/2))+0.2*rnd");
+	gr->SetOrigin(0,0,0);
+	if(big!=3)	{	gr->SubPlot(3,2,0,"");	gr->Title("Bars plot (default)");	}
+	gr->Box();	gr->Bars(ys);
+	if(big==3)	return;
+	gr->SubPlot(3,2,1,"");	gr->Title("2 colors");	gr->Box();	gr->Bars(ys,"cbgGyr");
+	gr->SubPlot(3,2,4,"");	gr->Title("'\\#' style");	gr->Box();	gr->Bars(ys,"#");
+	gr->SubPlot(3,2,5);	gr->Title("3d variant");	gr->Rotate(50,60);	gr->Box();
+	mglData yc(30), xc(30), z(30);	z.Modify("2*x-1");
+	yc.Modify("sin(pi*(2*x-1))");	xc.Modify("cos(pi*2*x-pi)");
+	gr->Bars(xc,yc,z,"r");
+	gr->SetRanges(-1,1,-3,3);	// increase range since summation can exceed [-1,1]
+	gr->SubPlot(3,2,2,"");	gr->Title("'a' style");	gr->Box();	gr->Bars(ys,"a");
+	gr->SubPlot(3,2,3,"");	gr->Title("'f' style");	gr->Box();	gr->Bars(ys,"f");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_barh="new ys 10 3 '0.8*sin(pi*(x+y/4+1.25))+0.2*rnd':origin 0 0 0\n"
+"subplot 2 2 0 '':title 'Barh plot (default)':box:barh ys\nsubplot 2 2 1 '':title '2 colors':box:barh ys 'cbgGyr'\n"
+"ranges -3 3 -1 1:subplot 2 2 2 '':title '\"a\" style':box:barh ys 'a'\nsubplot 2 2 3 '': title '\"f\" style':box:barh ys 'f'";
+void smgl_barh(mglGraph *gr)
+{
+	mglData ys(10,3);	ys.Modify("0.8*sin(pi*(2*x+y/2))+0.2*rnd");
+	gr->SetOrigin(0,0,0);
+	if(big!=3)	{	gr->SubPlot(2,2,0,"");	gr->Title("Barh plot (default)");	}
+	gr->Box();	gr->Barh(ys);
+	if(big==3)	return;
+	gr->SubPlot(2,2,1,"");	gr->Title("2 colors");	gr->Box();	gr->Barh(ys,"cbgGyr");
+	gr->SetRanges(-3,3,-1,1);	// increase range since summation can exceed [-1,1]
+	gr->SubPlot(2,2,2,"");	gr->Title("'a' style");	gr->Box();	gr->Barh(ys,"a");
+	gr->SubPlot(2,2,3,"");	gr->Title("'f' style");	gr->Box();	gr->Barh(ys,"f");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_area="call 'prepare1d'\norigin 0 0 0\nsubplot 2 2 0 '':title 'Area plot (default)':box:area y\n"
+"subplot 2 2 1 '':title '2 colors':box:area y 'cbgGyr'\nsubplot 2 2 2 '':title '\"!\" style':box:area y '!'\n"
+"new yc 30 'sin(pi*x)':new xc 30 'cos(pi*x)':new z 30 'x'\nsubplot 2 2 3:title '3d variant':rotate 50 60:box\n"
+"area xc yc z 'r'\narea xc -yc z 'b#'";
+void smgl_area(mglGraph *gr)
+{
+	mglData y;	mgls_prepare1d(&y);	gr->SetOrigin(0,0,0);
+	if(big!=3)	{	gr->SubPlot(2,2,0,"");	gr->Title("Area plot (default)");	}
+	gr->Box();	gr->Area(y);
+	if(big==3)	return;
+	gr->SubPlot(2,2,1,"");	gr->Title("2 colors");	gr->Box();	gr->Area(y,"cbgGyr");
+	gr->SubPlot(2,2,2,"");	gr->Title("'!' style");	gr->Box();	gr->Area(y,"!");
+	gr->SubPlot(2,2,3);	gr->Title("3d variant");	gr->Rotate(50,60);	gr->Box();
+	mglData yc(30), xc(30), z(30);	z.Modify("2*x-1");
+	yc.Modify("sin(pi*(2*x-1))");	xc.Modify("cos(pi*2*x-pi)");
+	gr->Area(xc,yc,z,"r");
+	yc.Modify("-sin(pi*(2*x-1))");	gr->Area(xc,yc,z,"b#");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_plot="call 'prepare1d'\nsubplot 2 2 0 '':title 'Plot plot (default)':box:plot y\n"
+"subplot 2 2 2 '':title ''!' style; 'rgb' palette':box:plot y 'o!rgb'\nsubplot 2 2 3 '':title 'just markers':box:plot y ' +'\n"
+"new yc 30 'sin(pi*x)':new xc 30 'cos(pi*x)':new z 30 'x'\nsubplot 2 2 1:title '3d variant':rotate 50 60:box:plot xc yc z 'rs'";
+void smgl_plot(mglGraph *gr)
+{
+	mglData y;	mgls_prepare1d(&y);	gr->SetOrigin(0,0,0);
+	if(big!=3)	{	gr->SubPlot(2,2,0,"");	gr->Title("Plot plot (default)");	}
+	gr->Box();	gr->Plot(y);
+	if(big==3)	return;
+	gr->SubPlot(2,2,2,"");	gr->Title("'!' style; 'rgb' palette");	gr->Box();	gr->Plot(y,"o!rgb");
+	gr->SubPlot(2,2,3,"");	gr->Title("just markers");	gr->Box();	gr->Plot(y," +");
+	gr->SubPlot(2,2,1);	gr->Title("3d variant");	gr->Rotate(50,60);	gr->Box();
+	mglData yc(30), xc(30), z(30);	z.Modify("2*x-1");
+	yc.Modify("sin(pi*(2*x-1))");	xc.Modify("cos(pi*2*x-pi)");
+	gr->Plot(xc,yc,z,"rs");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_tens="call 'prepare1d'\nsubplot 2 2 0 '':title 'Tens plot (default)':box:tens y(:,0) y(:,1)\n"
+"subplot 2 2 2 '':title '\" \" style':box:tens y(:,0) y(:,1) 'o '\n"
+"new yc 30 'sin(pi*x)':new xc 30 'cos(pi*x)':new z 30 'x'\n"
+"subplot 2 2 1:title '3d variant':rotate 50 60:box:tens xc yc z z 's'";
+void smgl_tens(mglGraph *gr)
+{
+	mglData y;	mgls_prepare1d(&y);	gr->SetOrigin(0,0,0);
+	if(big!=3)	{	gr->SubPlot(2,2,0,"");	gr->Title("Tens plot (default)");	}
+	gr->Box();	gr->Tens(y.SubData(-1,0), y.SubData(-1,1));
+	if(big==3)	return;
+	gr->SubPlot(2,2,2,"");	gr->Title("' ' style");	gr->Box();	gr->Tens(y.SubData(-1,0), y.SubData(-1,1),"o ");
+	gr->SubPlot(2,2,1);	gr->Title("3d variant");	gr->Rotate(50,60);	gr->Box();
+	mglData yc(30), xc(30), z(30);	z.Modify("2*x-1");
+	yc.Modify("sin(pi*(2*x-1))");	xc.Modify("cos(pi*2*x-pi)");
+	gr->Tens(xc,yc,z,z,"s");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_region="call 'prepare1d'\ncopy y1 y(:,1):copy y2 y(:,2)\n"
+"subplot 2 2 0 '':title 'Region plot (default)':box:region y1 y2:plot y1 'k2':plot y2 'k2'\n"
+"subplot 2 2 1 '':title '2 colors':box:region y1 y2 'yr':plot y1 'k2':plot y2 'k2'\n"
+"subplot 2 2 2 '':title '\"i\" style':box:region y1 y2 'ir':plot y1 'k2':plot y2 'k2'\n"
+"subplot 2 2 3 '^_':title '3d variant':rotate 40 60:box\n"
+"new x1 100 'sin(pi*x)':new y1 100 'cos(pi*x)':new z 100 'x'\n"
+"new x2 100 'sin(pi*x+pi/3)':new y2 100 'cos(pi*x+pi/3)'\n"
+"plot x1 y1 z 'r2':plot x2 y2 z 'b2'\nregion x1 y1 z x2 y2 z 'cmy!'";
+void smgl_region(mglGraph *gr)
+{
+	mglData y;	mgls_prepare1d(&y);
+	mglData y1 = y.SubData(-1,1), y2 = y.SubData(-1,2);	gr->SetOrigin(0,0,0);
+	if(big!=3)	{	gr->SubPlot(2,2,0,"");	gr->Title("Region plot (default)");	}
+	gr->Box();	gr->Region(y1,y2);	gr->Plot(y1,"k2");	gr->Plot(y2,"k2");
+	if(big==3)	return;
+	gr->SubPlot(2,2,1,"");	gr->Title("2 colors");	gr->Box();	gr->Region(y1,y2,"yr");	gr->Plot(y1,"k2");	gr->Plot(y2,"k2");
+	gr->SubPlot(2,2,2,"");	gr->Title("'i' style");	gr->Box();	gr->Region(y1,y2,"ir");	gr->Plot(y1,"k2");	gr->Plot(y2,"k2");
+	gr->SubPlot(2,2,3,"^_");	gr->Title("3d variant");	gr->Rotate(40,60);	gr->Box();
+	gr->Fill(y1,"cos(pi*x)");	gr->Fill(y2,"cos(pi*x+pi/3)");
+	mglData x1(y1.nx), x2(y1.nx), z(y1.nx);
+	gr->Fill(x1,"sin(pi*x)");	gr->Fill(x2,"sin(pi*x+pi/3)");	gr->Fill(z,"x");
+	gr->Plot(x1,y1,z,"r2");		gr->Plot(x2,y2,z,"b2");
+	gr->Region(x1,y1,z,x2,y2,z,"cmy!");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_stem="call 'prepare1d'\norigin 0 0 0:subplot 2 2 0 '':title 'Stem plot (default)':box:stem y\n"
+"new yc 30 'sin(pi*x)':new xc 30 'cos(pi*x)':new z 30 'x'\nsubplot 2 2 1:title '3d variant':rotate 50 60:box:stem xc yc z 'rx'\n"
+"subplot 2 2 2 '':title '\"!\" style':box:stem y 'o!rgb'";
+void smgl_stem(mglGraph *gr)
+{
+	mglData y;	mgls_prepare1d(&y);	gr->SetOrigin(0,0,0);
+	mglData yc(30), xc(30), z(30);	z.Modify("2*x-1");
+	yc.Modify("sin(pi*(2*x-1))");	xc.Modify("cos(pi*2*x-pi)");
+	if(big!=3)	{	gr->SubPlot(2,2,0,"");	gr->Title("Stem plot (default)");	}
+	gr->Box();	gr->Stem(y);
+	if(big==3)	return;
+	gr->SubPlot(2,2,1);	gr->Title("3d variant");	gr->Rotate(50,60);
+	gr->Box();	gr->Stem(xc,yc,z,"rx");
+	gr->SubPlot(2,2,2,"");	gr->Title("'!' style");	gr->Box();	gr->Stem(y,"o!rgb");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_step="call 'prepare1d'\norigin 0 0 0:subplot 2 2 0 '':title 'Step plot (default)':box:step y\n"
+"new yc 30 'sin(pi*x)':new xc 30 'cos(pi*x)':new z 30 'x'\nsubplot 2 2 1:title '3d variant':rotate 50 60:box:step xc yc z 'r'\n"
+"subplot 2 2 2 '':title '\"!\" style':box:step y 's!rgb'";
+void smgl_step(mglGraph *gr)
+{
+	mglData y;	mgls_prepare1d(&y);	gr->SetOrigin(0,0,0);
+	mglData yc(30), xc(30), z(30);	z.Modify("2*x-1");
+	yc.Modify("sin(pi*(2*x-1))");	xc.Modify("cos(pi*2*x-pi)");
+	if(big!=3)	{	gr->SubPlot(2,2,0,"");	gr->Title("Step plot (default)");	}
+	gr->Box();	gr->Step(y);
+	if(big==3)	return;
+	gr->SubPlot(2,2,1);	gr->Title("3d variant");	gr->Rotate(50,60);
+	gr->Box();	gr->Step(xc,yc,z,"r");
+	gr->SubPlot(2,2,2,"");	gr->Title("'!' style");	gr->Box();	gr->Step(y,"s!rgb");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_boxplot="new a 10 7 '(2*rnd-1)^3/2'\nsubplot 1 1 0 '':title 'Boxplot plot':box:boxplot a";
+void smgl_boxplot(mglGraph *gr)	// flow threads and density plot
+{
+	mglData a(10,7);	a.Modify("(2*rnd-1)^3/2");
+	if(big!=3)	{	gr->SubPlot(1,1,0,"");	gr->Title("Boxplot plot");	}
+	gr->Box();	gr->BoxPlot(a);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_ohlc="new o 10 '0.5*sin(pi*x)'\nnew c 10 '0.5*sin(pi*(x+2/9))'\n"
+"new l 10 '0.3*rnd-0.8'\nnew h 10 '0.3*rnd+0.5'\n"
+"subplot 1 1 0 '':title 'OHLC plot':box:ohlc o h l c";
+void smgl_ohlc(mglGraph *gr)	// flow threads and density plot
+{
+	mglData o(10), h(10), l(10), c(10);
+	gr->Fill(o,"0.5*sin(pi*x)");	gr->Fill(c,"0.5*sin(pi*(x+2/9))");
+	gr->Fill(l,"0.3*rnd-0.8");		gr->Fill(h,"0.3*rnd+0.5");
+	if(big!=3)	{	gr->SubPlot(1,1,0,"");	gr->Title("OHLC plot");	}
+	gr->Box();	gr->OHLC(o,h,l,c);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_type0="call 'prepare2d'\nalpha on:light on:transptype 0:clf\nsubplot 2 2 0:rotate 50 60:surf a:box\n"
+"subplot 2 2 1:rotate 50 60:dens a:box\nsubplot 2 2 2:rotate 50 60:cont a:box\n"
+"subplot 2 2 3:rotate 50 60:axial a:box";
+void smgl_type0(mglGraph *gr)	// TranspType = 0
+{
+	gr->Alpha(true);	gr->Light(true);
+	mglData a;	mgls_prepare2d(&a);
+	gr->SetTranspType(0);	gr->Clf();
+	gr->SubPlot(2,2,0);	gr->Rotate(50,60);	gr->Surf(a);	gr->Box();
+	gr->SubPlot(2,2,1);	gr->Rotate(50,60);	gr->Dens(a);	gr->Box();
+	gr->SubPlot(2,2,2);	gr->Rotate(50,60);	gr->Cont(a);	gr->Box();
+	gr->SubPlot(2,2,3);	gr->Rotate(50,60);	gr->Axial(a);	gr->Box();
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_type1="call 'prepare2d'\nalpha on:light on:transptype 1:clf\nsubplot 2 2 0:rotate 50 60:surf a:box\n"
+"subplot 2 2 1:rotate 50 60:dens a:box\nsubplot 2 2 2:rotate 50 60:cont a:box\n"
+"subplot 2 2 3:rotate 50 60:axial a:box";
+void smgl_type1(mglGraph *gr)	// TranspType = 1
+{
+	gr->Alpha(true);	gr->Light(true);
+	mglData a;	mgls_prepare2d(&a);
+	gr->SetTranspType(1);	gr->Clf();
+	gr->SubPlot(2,2,0);	gr->Rotate(50,60);	gr->Surf(a);	gr->Box();
+	gr->SubPlot(2,2,1);	gr->Rotate(50,60);	gr->Dens(a);	gr->Box();
+	gr->SubPlot(2,2,2);	gr->Rotate(50,60);	gr->Cont(a);	gr->Box();
+	gr->SubPlot(2,2,3);	gr->Rotate(50,60);	gr->Axial(a);	gr->Box();
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_type2="call 'prepare2d'\nalpha on:light on:transptype 2:clf\nsubplot 2 2 0:rotate 50 60:surf a:box\n"
+"subplot 2 2 1:rotate 50 60:dens a:box\nsubplot 2 2 2:rotate 50 60:cont a:box\n"
+"subplot 2 2 3:rotate 50 60:axial a:box";
+void smgl_type2(mglGraph *gr)	// TranspType = 2
+{
+	gr->Alpha(true);	gr->Light(true);
+	mglData a;	mgls_prepare2d(&a);
+	gr->SetTranspType(2);	gr->Clf();
+	gr->SubPlot(2,2,0);	gr->Rotate(50,60);	gr->Surf(a);	gr->Box();
+	gr->SubPlot(2,2,1);	gr->Rotate(50,60);	gr->Dens(a);	gr->Box();
+	gr->SubPlot(2,2,2);	gr->Rotate(50,60);	gr->Cont(a);	gr->Box();
+	gr->SubPlot(2,2,3);	gr->Rotate(50,60);	gr->Axial(a);	gr->Box();
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_molecule="alpha on:light on\n"
+"subplot 2 2 0 '':title 'Methane, CH_4':rotate 60 120\n"
+"sphere 0 0 0 0.25 'k':drop 0 0 0 0 0 1 0.35 'h' 1 2:sphere 0 0 0.7 0.25 'g'\n"
+"drop 0 0 0 -0.94 0 -0.33 0.35 'h' 1 2:sphere -0.66 0 -0.23 0.25 'g'\n"
+"drop 0 0 0 0.47 0.82 -0.33 0.35 'h' 1 2:sphere 0.33 0.57 -0.23 0.25 'g'\n"
+"drop 0 0 0 0.47 -0.82 -0.33 0.35 'h' 1 2:sphere 0.33 -0.57 -0.23 0.25 'g'\n"
+"subplot 2 2 1 '':title 'Water, H{_2}O':rotate 60 100\n"
+"sphere 0 0 0 0.25 'r':drop 0 0 0 0.3 0.5 0 0.3 'm' 1 2:sphere 0.3 0.5 0 0.25 'g'\n"
+"drop 0 0 0 0.3 -0.5 0 0.3 'm' 1 2:sphere 0.3 -0.5 0 0.25 'g'\n"
+"subplot 2 2 2 '':title 'Oxygen, O_2':rotate 60 120\n"
+"drop 0 0.5 0 0 -0.3 0 0.3 'm' 1 2:sphere 0 0.5 0 0.25 'r'\n"
+"drop 0 -0.5 0 0 0.3 0 0.3 'm' 1 2:sphere 0 -0.5 0 0.25 'r'\n"
+"subplot 2 2 3 '':title 'Ammonia, NH_3':rotate 60 120\n"
+"sphere 0 0 0 0.25 'b':drop 0 0 0 0.33 0.57 0 0.32 'n' 1 2\n"
+"sphere 0.33 0.57 0 0.25 'g':drop 0 0 0 0.33 -0.57 0 0.32 'n' 1 2\n"
+"sphere 0.33 -0.57 0 0.25 'g':drop 0 0 0 -0.65 0 0 0.32 'n' 1 2\n"
+"sphere -0.65 0 0 0.25 'g'";
+void smgl_molecule(mglGraph *gr)	// example of moleculas
+{
+	gr->VertexColor(false);	gr->Compression(false); // per-vertex colors and compression are detrimental to transparency
+	gr->DoubleSided(false); // we do not get into atoms, while rendering internal surface has negative impact on trasparency
+	gr->Alpha(true);	gr->Light(true);
+
+	gr->SubPlot(2,2,0,"");	gr->Title("Methane, CH_4");
+	gr->StartGroup("Methane");
+	gr->Rotate(60,120);
+	gr->Sphere(mglPoint(0,0,0),0.25,"k");
+	gr->Drop(mglPoint(0,0,0),mglPoint(0,0,1),0.35,"h",1,2);
+	gr->Sphere(mglPoint(0,0,0.7),0.25,"g");
+	gr->Drop(mglPoint(0,0,0),mglPoint(-0.94,0,-0.33),0.35,"h",1,2);
+	gr->Sphere(mglPoint(-0.66,0,-0.23),0.25,"g");
+	gr->Drop(mglPoint(0,0,0),mglPoint(0.47,0.82,-0.33),0.35,"h",1,2);
+	gr->Sphere(mglPoint(0.33,0.57,-0.23),0.25,"g");
+	gr->Drop(mglPoint(0,0,0),mglPoint(0.47,-0.82,-0.33),0.35,"h",1,2);
+	gr->Sphere(mglPoint(0.33,-0.57,-0.23),0.25,"g");
+	gr->EndGroup();
+
+	gr->SubPlot(2,2,1,"");	gr->Title("Water, H_{2}O");
+	gr->StartGroup("Water");
+	gr->Rotate(60,100);
+	gr->StartGroup("Water_O");
+	gr->Sphere(mglPoint(0,0,0),0.25,"r");
+	gr->EndGroup();
+	gr->StartGroup("Water_Bond_1");
+	gr->Drop(mglPoint(0,0,0),mglPoint(0.3,0.5,0),0.3,"m",1,2);
+	gr->EndGroup();
+	gr->StartGroup("Water_H_1");
+	gr->Sphere(mglPoint(0.3,0.5,0),0.25,"g");
+	gr->EndGroup();
+	gr->StartGroup("Water_Bond_2");
+	gr->Drop(mglPoint(0,0,0),mglPoint(0.3,-0.5,0),0.3,"m",1,2);
+	gr->EndGroup();
+	gr->StartGroup("Water_H_2");
+	gr->Sphere(mglPoint(0.3,-0.5,0),0.25,"g");
+	gr->EndGroup();
+	gr->EndGroup();
+
+	gr->SubPlot(2,2,2,"");	gr->Title("Oxygen, O_2");
+	gr->StartGroup("Oxygen");
+	gr->Rotate(60,120);
+	gr->Drop(mglPoint(0,0.5,0),mglPoint(0,-0.3,0),0.3,"m",1,2);
+	gr->Sphere(mglPoint(0,0.5,0),0.25,"r");
+	gr->Drop(mglPoint(0,-0.5,0),mglPoint(0,0.3,0),0.3,"m",1,2);
+	gr->Sphere(mglPoint(0,-0.5,0),0.25,"r");
+	gr->EndGroup();
+
+	gr->SubPlot(2,2,3,"");	gr->Title("Ammonia, NH_3");
+	gr->StartGroup("Ammonia");
+	gr->Rotate(60,120);
+	gr->Sphere(mglPoint(0,0,0),0.25,"b");
+	gr->Drop(mglPoint(0,0,0),mglPoint(0.33,0.57,0),0.32,"n",1,2);
+	gr->Sphere(mglPoint(0.33,0.57,0),0.25,"g");
+	gr->Drop(mglPoint(0,0,0),mglPoint(0.33,-0.57,0),0.32,"n",1,2);
+	gr->Sphere(mglPoint(0.33,-0.57,0),0.25,"g");
+	gr->Drop(mglPoint(0,0,0),mglPoint(-0.65,0,0),0.32,"n",1,2);
+	gr->Sphere(mglPoint(-0.65,0,0),0.25,"g");
+	gr->EndGroup();
+	gr->DoubleSided( true ); // put back
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_error2="new x0 10 'rnd':new ex 10 '0.1'\nnew y0 10 'rnd':new ey 10 '0.1'\nranges 0 1 0 1\n"
+"subplot 4 3 0 '':box:error x0 y0 ex ey '#+@'\n"
+"subplot 4 3 1 '':box:error x0 y0 ex ey '#x@'\n"
+"subplot 4 3 2 '':box:error x0 y0 ex ey '#s@'; alpha 0.5\n"
+"subplot 4 3 3 '':box:error x0 y0 ex ey 's@'\n"
+"subplot 4 3 4 '':box:error x0 y0 ex ey 'd@'\n"
+"subplot 4 3 5 '':box:error x0 y0 ex ey '#d@'; alpha 0.5\n"
+"subplot 4 3 6 '':box:error x0 y0 ex ey '+@'\n"
+"subplot 4 3 7 '':box:error x0 y0 ex ey 'x@'\n"
+"subplot 4 3 8 '':box:error x0 y0 ex ey 'o@'\n"
+"subplot 4 3 9 '':box:error x0 y0 ex ey '#o@'; alpha 0.5\n"
+"subplot 4 3 10 '':box:error x0 y0 ex ey '#.@'\n"
+"subplot 4 3 11 '':box:error x0 y0 ex ey; alpha 0.5";
+void smgl_error2(mglGraph *gr)
+{
+	mglData x0(10), y0(10), ex(10), ey(10);
+	for(int i=0;i<10;i++)
+	{	x0.a[i] = mgl_rnd();	y0.a[i] = mgl_rnd();	ey.a[i] = ex.a[i] = 0.1;	}
+	gr->SetRanges(0,1,0,1);	gr->Alpha(true);
+	gr->SubPlot(4,3,0,"");	gr->Box();	gr->Error(x0,y0,ex,ey,"#+@");
+	gr->SubPlot(4,3,1,"");	gr->Box();	gr->Error(x0,y0,ex,ey,"#x@");
+	gr->SubPlot(4,3,2,"");	gr->Box();	gr->Error(x0,y0,ex,ey,"#s@","alpha 0.5");
+	gr->SubPlot(4,3,3,"");	gr->Box();	gr->Error(x0,y0,ex,ey,"s@");
+	gr->SubPlot(4,3,4,"");	gr->Box();	gr->Error(x0,y0,ex,ey,"d@");
+	gr->SubPlot(4,3,5,"");	gr->Box();	gr->Error(x0,y0,ex,ey,"#d@","alpha 0.5");
+	gr->SubPlot(4,3,6,"");	gr->Box();	gr->Error(x0,y0,ex,ey,"+@");
+	gr->SubPlot(4,3,7,"");	gr->Box();	gr->Error(x0,y0,ex,ey,"x@");
+	gr->SubPlot(4,3,8,"");	gr->Box();	gr->Error(x0,y0,ex,ey,"o@");
+	gr->SubPlot(4,3,9,"");	gr->Box();	gr->Error(x0,y0,ex,ey,"#o@","alpha 0.5");
+	gr->SubPlot(4,3,10,"");	gr->Box();	gr->Error(x0,y0,ex,ey,"#.@");
+	gr->SubPlot(4,3,11,"");	gr->Box();	gr->Error(x0,y0,ex,ey);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_error="call 'prepare1d'\nnew y 50 '0.7*sin(pi*x-pi) + 0.5*cos(3*pi*(x+1)/2) + 0.2*sin(pi*(x+1)/2)'\n"
+"new x0 10 'x + 0.1*rnd-0.05':new ex 10 '0.1':new ey 10 '0.2'\n"
+"new y0 10 '0.7*sin(pi*x-pi) + 0.5*cos(3*pi*(x+1)/2) + 0.2*sin(pi*(x+1)/2) + 0.2*rnd-0.1'\n"
+"subplot 2 2 0 '':title 'Error plot (default)':box:plot y:error x0 y0 ex ey 'k'\n"
+"subplot 2 2 1 '':title '\"!\" style; no e_x':box:plot y:error x0 y0 ey 'o!rgb'\n"
+"subplot 2 2 2 '':title '\"\\@\" style':alpha on:box:plot y:error x0 y0 ex ey '@'; alpha 0.5\n"
+"subplot 2 2 3:title '3d variant':rotate 50 60:axis\n"
+"for $1 0 9\n\terrbox 2*rnd-1 2*rnd-1 2*rnd-1 0.2 0.2 0.2 'bo'\nnext";
+void smgl_error(mglGraph *gr)
+{
+	mglData y;	mgls_prepare1d(&y);
+	mglData x0(10), y0(10), ex0(10), ey0(10);
+	for(int i=0;i<10;i++)
+	{
+		double x = i/9.;
+		x0.a[i] = 2*x-1 + 0.1*mgl_rnd()-0.05;
+		y0.a[i] = 0.7*sin(2*M_PI*x)+0.5*cos(3*M_PI*x)+0.2*sin(M_PI*x)+0.2*mgl_rnd()-0.1;
+		ey0.a[i]=0.2;	ex0.a[i]=0.1;
+	}
+	if(big!=3)	{	gr->SubPlot(2,2,0,"");	gr->Title("Error plot (default)");	}
+	gr->Box();	gr->Plot(y.SubData(-1,0));	gr->Error(x0,y0,ex0,ey0,"ko");
+	if(big==3)	return;
+	gr->SubPlot(2,2,1,"");	gr->Title("'!' style; no e_x");
+	gr->Box();	gr->Plot(y.SubData(-1,0));	gr->Error(x0,y0,ey0,"o!rgb");
+	gr->SubPlot(2,2,2,"");	gr->Title("'\\@' style");	gr->Alpha(true);
+	gr->Box();	gr->Plot(y.SubData(-1,0));	gr->Error(x0,y0,ex0,ey0,"@","alpha 0.5");
+	gr->SubPlot(2,2,3);	gr->Title("3d variant");	gr->Rotate(50,60);
+	for(int i=0;i<10;i++)
+		gr->Error(mglPoint(2*mgl_rnd()-1,2*mgl_rnd()-1,2*mgl_rnd()-1), mglPoint(0.2,0.2,0.2),"bo");
+	gr->Axis();
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_chart="new ch 7 2 'rnd+0.1':light on\n"
+"subplot 2 2 0:title 'Chart plot (default)':rotate 50 60:box:chart ch\n"
+"subplot 2 2 1:title '\"\\#\" style':rotate 50 60:box:chart ch '#'\n"
+"subplot 2 2 2:title 'Pie chart; \" \" color':rotate 50 60:\n"
+"axis '(y+1)/2*cos(pi*x)' '(y+1)/2*sin(pi*x)' '':box:chart ch 'bgr cmy#'\n"
+"subplot 2 2 3:title 'Ring chart; \" \" color':rotate 50 60:\n"
+"axis '(y+2)/3*cos(pi*x)' '(y+2)/3*sin(pi*x)' '':box:chart ch 'bgr cmy#'";
+void smgl_chart(mglGraph *gr)
+{
+	mglData ch(7,2);	for(int i=0;i<7*2;i++)	ch.a[i]=mgl_rnd()+0.1;
+	if(big!=3)	{	gr->SubPlot(2,2,0);	gr->Title("Chart plot (default)");	}
+	gr->Light(true);	gr->Rotate(50,60);	gr->Box();	gr->Chart(ch);
+	if(big==3)	return;
+	gr->SubPlot(2,2,1);	gr->Title("'\\#' style");
+	gr->Rotate(50,60);	gr->Box();	gr->Chart(ch,"#");
+	gr->SubPlot(2,2,2);	gr->Title("Pie chart; ' ' color");
+	gr->SetFunc("(y+1)/2*cos(pi*x)","(y+1)/2*sin(pi*x)","");
+	gr->Rotate(50,60);	gr->Box();	gr->Chart(ch,"bgr cmy#");
+	gr->SubPlot(2,2,3);	gr->Title("Ring chart; ' ' color");
+	gr->SetFunc("(y+2)/3*cos(pi*x)","(y+2)/3*sin(pi*x)","");
+	gr->Rotate(50,60);	gr->Box();	gr->Chart(ch,"bgr cmy#");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_mark="call 'prepare1d'\nsubplot 1 1 0 '':title 'Mark plot (default)':box:mark y y1 's'";
+void smgl_mark(mglGraph *gr)
+{
+	mglData y,y1;	mgls_prepare1d(&y,&y1);
+	if(big!=3)	{	gr->SubPlot(1,1,0,"");	gr->Title("Mark plot (default)");	}
+	gr->Box();	gr->Mark(y,y1,"s");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_radar="new yr 10 3 '0.4*sin(pi*(x+1.5+y/2)+0.1*rnd)'\n"
+"subplot 1 1 0 '':title 'Radar plot (with grid, \"\\#\")':radar yr '#'";
+void smgl_radar(mglGraph *gr)
+{
+	mglData yr(10,3);	yr.Modify("0.4*sin(pi*(2*x+y))+0.1*rnd");
+	if(big!=3)	{	gr->SubPlot(1,1,0,"");	gr->Title("Radar plot (with grid, '\\#')");	}
+	gr->Radar(yr,"#");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_candle="new y 30 'sin(pi*x/2)^2'\n"
+"subplot 1 1 0 '':title 'Candle plot (default)'\nyrange 0 1:box\ncandle y y/2 (y+1)/2";
+void smgl_candle(mglGraph *gr)
+{
+	mglData y(30);	gr->Fill(y,"sin(pi*x/2)^2");
+	mglData y1(30);	gr->Fill(y1,"v/2",y);
+	mglData y2(30);	gr->Fill(y2,"(1+v)/2",y);
+	if(big!=3)	{	gr->SubPlot(1,1,0,"");	gr->Title("Candle plot (default)");	}
+	gr->SetRange('y',0,1);	gr->Box();	gr->Candle(y,y1,y2);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_textmark="call 'prepare1d'\nsubplot 1 1 0 '':title 'TextMark plot (default)':box:textmark y y1 '\\gamma' 'r'";
+void smgl_textmark(mglGraph *gr)
+{
+	mglData y,y1;	mgls_prepare1d(&y,&y1);
+	if(big!=3)	{	gr->SubPlot(1,1,0,"");	gr->Title("TextMark plot (default)");	}
+	gr->Box();	gr->TextMark(y,y1,"\\gamma","r");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_tube="call 'prepare1d'\nlight on\n"
+"new yc 50 'sin(pi*x)':new xc 50 'cos(pi*x)':new z 50 'x':divto y1 20\n"
+"subplot 2 2 0 '':title 'Tube plot (default)':box:tube y 0.05\n"
+"subplot 2 2 1 '':title 'variable radius':box:tube y y1\n"
+"subplot 2 2 2 '':title '\"\\#\" style':box:tube y 0.05 '#'\n"
+"subplot 2 2 3:title '3d variant':rotate 50 60:box:tube xc yc z y2 'r'";
+void smgl_tube(mglGraph *gr)
+{
+	mglData y,y1,y2;	mgls_prepare1d(&y,&y1,&y2);	y1/=20;
+	if(big!=3)	{	gr->SubPlot(2,2,0,"");	gr->Title("Tube plot (default)");	}
+	gr->Light(true);	gr->Box();	gr->Tube(y,0.05);
+	if(big==3)	return;
+	gr->SubPlot(2,2,1,"");	gr->Title("variable radius");	gr->Box();	gr->Tube(y,y1);
+	gr->SubPlot(2,2,2,"");	gr->Title("'\\#' style");	gr->Box();	gr->Tube(y,0.05,"#");
+	mglData yc(50), xc(50), z(50);	z.Modify("2*x-1");
+	yc.Modify("sin(pi*(2*x-1))");	xc.Modify("cos(pi*2*x-pi)");
+	gr->SubPlot(2,2,3);	gr->Title("3d variant");	gr->Rotate(50,60);	gr->Box();	gr->Tube(xc,yc,z,y2,"r");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_tape="call 'prepare1d'\nnew yc 50 'sin(pi*x)':new xc 50 'cos(pi*x)':new z 50 'x'\n"
+"subplot 2 2 0 '':title 'Tape plot (default)':box:tape y:plot y 'k'\n"
+"subplot 2 2 1:title '3d variant, 2 colors':rotate 50 60:light on\n"
+"box:plot xc yc z 'k':tape xc yc z 'rg'\n"
+"subplot 2 2 2:title '3d variant, x only':rotate 50 60\n"
+"box:plot xc yc z 'k':tape xc yc z 'xr':tape xc yc z 'xr#'\n"
+"subplot 2 2 3:title '3d variant, z only':rotate 50 60\n"
+"box:plot xc yc z 'k':tape xc yc z 'zg':tape xc yc z 'zg#'";
+void smgl_tape(mglGraph *gr)
+{
+	mglData y;	mgls_prepare1d(&y);
+	mglData xc(50), yc(50), z(50);
+	yc.Modify("sin(pi*(2*x-1))");
+	xc.Modify("cos(pi*2*x-pi)");	z.Fill(-1,1);
+	if(big!=3)	{	gr->SubPlot(2,2,0,"");	gr->Title("Tape plot (default)");	}
+	gr->Box();	gr->Tape(y);	gr->Plot(y,"k");
+	if(big==3)	return;
+	gr->SubPlot(2,2,1);	gr->Title("3d variant, 2 colors");	gr->Rotate(50,60);	gr->Light(true);
+	gr->Box();	gr->Plot(xc,yc,z,"k");	gr->Tape(xc,yc,z,"rg");
+	gr->SubPlot(2,2,2);	gr->Title("3d variant, x only");	gr->Rotate(50,60);
+	gr->Box();	gr->Plot(xc,yc,z,"k");	gr->Tape(xc,yc,z,"xr");	gr->Tape(xc,yc,z,"xr#");
+	gr->SubPlot(2,2,3);	gr->Title("3d variant, z only");	gr->Rotate(50,60);
+	gr->Box();	gr->Plot(xc,yc,z,"k");	gr->Tape(xc,yc,z,"zg");	gr->Tape(xc,yc,z,"zg#");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_fog="call 'prepare2d'\ntitle 'Fog sample':rotate 50 60:light on:fog 1\nbox:surf a:cont a 'y'";
+void smgl_fog(mglGraph *gr)
+{
+	mglData a;	mgls_prepare2d(&a);
+	if(big!=3)	gr->Title("Fog sample");
+	gr->Light(true);	gr->Rotate(50,60);	gr->Fog(1);	gr->Box();
+	gr->Surf(a);	gr->Cont(a,"y");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_map="new a 50 40 'x':new b 50 40 'y':zrange -2 2:text 0 0 '\\to'\n"
+"subplot 2 1 0:text 0 1.1 '\\{x, y\\}' '' -2:box:map a b 'brgk'\n"
+"subplot 2 1 1:text 0 1.1 '\\{\\frac{x^3+y^3}{2}, \\frac{x-y}{2}\\}' '' -2\n"
+"box:fill a '(x^3+y^3)/2':fill b '(x-y)/2':map a b 'brgk'";
+void smgl_map(mglGraph *gr)	// example of mapping
+{
+	mglData a(50, 40), b(50, 40);
+	gr->Puts(mglPoint(0, 0), "\\to", ":C", -1.4);
+	gr->SetRanges(-1,1,-1,1,-2,2);
+
+	gr->SubPlot(2, 1, 0);
+	gr->Fill(a,"x");	gr->Fill(b,"y");
+	gr->Puts(mglPoint(0, 1.1), "\\{x, y\\}", ":C", -2);		gr->Box();
+	gr->Map(a, b, "brgk");
+
+	gr->SubPlot(2, 1, 1);
+	gr->Fill(a,"(x^3+y^3)/2");	gr->Fill(b,"(x-y)/2");
+	gr->Puts(mglPoint(0, 1.1), "\\{\\frac{x^3+y^3}{2}, \\frac{x-y}{2}\\}", ":C", -2);
+	gr->Box();
+	gr->Map(a, b, "brgk");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_stfa="new a 2000:new b 2000\nfill a 'cos(50*pi*x)*(x<-.5)+cos(100*pi*x)*(x<0)*(x>-.5)+\\\n"
+"cos(200*pi*x)*(x<.5)*(x>0)+cos(400*pi*x)*(x>.5)'\n"
+"subplot 1 2 0 '<_':title 'Initial signal':plot a:axis:xlabel '\\i t'\n"
+"subplot 1 2 1 '<_':title 'STFA plot':stfa a b 64:axis:ylabel '\\omega' 0:xlabel '\\i t'";
+void smgl_stfa(mglGraph *gr)	// STFA sample
+{
+	mglData a(2000), b(2000);
+	gr->Fill(a,"cos(50*pi*x)*(x<-.5)+cos(100*pi*x)*(x<0)*(x>-.5)+\
+	cos(200*pi*x)*(x<.5)*(x>0)+cos(400*pi*x)*(x>.5)");
+	gr->SubPlot(1, 2, 0,"<_");	gr->Title("Initial signal");
+	gr->Plot(a);
+	gr->Axis();
+	gr->Label('x', "\\i t");
+
+	gr->SubPlot(1, 2, 1,"<_");	gr->Title("STFA plot");
+	gr->STFA(a, b, 64);
+	gr->Axis();
+	gr->Label('x', "\\i t");
+	gr->Label('y', "\\omega", 0);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_qo2d="define $1 'p^2+q^2-x-1+i*0.5*(y+x)*(y>-x)'\n"
+"subplot 1 1 0 '<_':title 'Beam and ray tracing'\n"
+"ray r $1 -0.7 -1 0 0 0.5 0 0.02 2:plot r(0) r(1) 'k'\naxis:xlabel '\\i x':ylabel '\\i z'\n"
+"new re 128 'exp(-48*x^2)':new im 128\nnew xx 1:new yy 1\nqo2d a $1 re im r 1 30 xx yy\n"
+"crange 0 1:dens xx yy a 'wyrRk':fplot '-x' 'k|'\n"
+"text 0 0.85 'absorption: (x+y)/2 for x+y>0'\ntext 0.7 -0.05 'central ray'";
+void smgl_qo2d(mglGraph *gr)
+{
+	mglData r, xx, yy, a, im(128), re(128);
+	const char *ham = "p^2+q^2-x-1+i*0.5*(y+x)*(y>-x)";
+	r = mglRay(ham, mglPoint(-0.7, -1), mglPoint(0, 0.5), 0.02, 2);
+	if(big!=3)	{gr->SubPlot(1,1,0,"<_");	gr->Title("Beam and ray tracing");}
+	gr->Plot(r.SubData(0), r.SubData(1), "k");
+	gr->Axis();	gr->Label('x', "\\i x");	gr->Label('y', "\\i y");
+	// now start beam tracing
+	gr->Fill(re,"exp(-48*x^2)");
+	a = mglQO2d(ham, re, im, r, xx, yy, 1, 30);
+	gr->SetRange('c',0, 1);
+	gr->Dens(xx, yy, a, "wyrRk");
+	gr->FPlot("-x", "k|");
+	gr->Puts(mglPoint(0, 0.85), "absorption: (x+y)/2 for x+y>0");
+	gr->Puts(mglPoint(0.7, -0.05), "central ray");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_pde="new re 128 'exp(-48*(x+0.7)^2)':new im 128\n"
+"pde a 'p^2+q^2-x-1+i*0.5*(z+x)*(z>-x)' re im 0.01 30\ntranspose a\n"
+"subplot 1 1 0 '<_':title 'PDE solver'\n"
+"axis:xlabel '\\i x':ylabel '\\i z'\ncrange 0 1:dens a 'wyrRk'\n"
+"fplot '-x' 'k|'\n"
+"text 0 0.95 'Equation: ik_0\\partial_zu + \\Delta u + x\\cdot u + i \\frac{x+z}{2}\\cdot u = 0\\n{}absorption: (x+z)/2 for x+z>0'";
+void smgl_pde(mglGraph *gr)	// PDE sample
+{
+	mglData a,re(128),im(128);
+	gr->Fill(re,"exp(-48*(x+0.7)^2)");
+	a = gr->PDE("p^2+q^2-x-1+i*0.5*(z+x)*(z>-x)", re, im, 0.01, 30);
+	a.Transpose("yxz");
+	if(big!=3)	{gr->SubPlot(1,1,0,"<_");	gr->Title("PDE solver");	}
+	gr->SetRange('c',0,1);	gr->Dens(a,"wyrRk");
+	gr->Axis();	gr->Label('x', "\\i x");	gr->Label('y', "\\i z");
+	gr->FPlot("-x", "k|");
+	gr->Puts(mglPoint(0, 0.95), "Equation: ik_0\\partial_zu + \\Delta u + x\\cdot u + i \\frac{x+z}{2}\\cdot u = 0\nabsorption: (x+z)/2 for x+z>0");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_conta="call 'prepare3d'\ntitle 'Cont3 sample':rotate 50 60:box\ncont3 c 'x':cont3 c:cont3 c 'z'";
+void smgl_conta(mglGraph *gr)
+{
+	mglData c;	mgls_prepare3d(&c);
+	if(big!=3)	gr->Title("Cont3 sample");
+	gr->Rotate(50,60);	gr->Box();
+	gr->Cont3(c,"x");	gr->Cont3(c);	gr->Cont3(c,"z");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_contfa="call 'prepare3d'\ntitle 'Cont3 sample':rotate 50 60:box:light on\n"
+"contf3 c 'x':contf3 c:contf3 c 'z'\ncont3 c 'xk':cont3 c 'k':cont3 c 'zk'";
+void smgl_contfa(mglGraph *gr)
+{
+	mglData c;	mgls_prepare3d(&c);
+	if(big!=3)	gr->Title("ContF3 sample");
+	gr->Rotate(50,60);	gr->Light(true);	gr->Box();
+	gr->ContF3(c,"x");	gr->ContF3(c);		gr->ContF3(c,"z");
+	gr->Cont3(c,"kx");	gr->Cont3(c,"k");	gr->Cont3(c,"kz");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_densa="call 'prepare3d'\ntitle 'Dens3 sample':rotate 50 60:alpha on:alphadef 0.7\n"
+"origin 0 0 0:box:axis '_xyz'\ndens3 c 'x':dens3 c ':y':dens3 c 'z'";
+void smgl_densa(mglGraph *gr)
+{
+	mglData c;	mgls_prepare3d(&c);
+	if(big!=3)	gr->Title("Dens3 sample");
+	gr->Rotate(50,60);	gr->Alpha(true);	gr->SetAlphaDef(0.7);
+	gr->SetOrigin(0,0,0);	gr->Axis("_xyz");	gr->Box();
+	gr->Dens3(c,"x");	gr->Dens3(c);	gr->Dens3(c,"z");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_dens_xyz="call 'prepare3d'\ntitle 'Dens[XYZ] sample':rotate 50 60:box\n"
+"densx {sum c 'x'} '' -1:densy {sum c 'y'} '' 1:densz {sum c 'z'} '' -1";
+void smgl_dens_xyz(mglGraph *gr)
+{
+	mglData c;	mgls_prepare3d(&c);
+	if(big!=3)	gr->Title("Dens[XYZ] sample");
+	gr->Rotate(50,60);	gr->Box();	gr->DensX(c.Sum("x"),0,-1);
+	gr->DensY(c.Sum("y"),0,1);		gr->DensZ(c.Sum("z"),0,-1);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_cont_xyz="call 'prepare3d'\ntitle 'Cont[XYZ] sample':rotate 50 60:box\n"
+"contx {sum c 'x'} '' -1:conty {sum c 'y'} '' 1:contz {sum c 'z'} '' -1";
+void smgl_cont_xyz(mglGraph *gr)
+{
+	mglData c;	mgls_prepare3d(&c);
+	if(big!=3)	gr->Title("Cont[XYZ] sample");
+	gr->Rotate(50,60);	gr->Box();	gr->ContX(c.Sum("x"),"",-1);
+	gr->ContY(c.Sum("y"),"",1);		gr->ContZ(c.Sum("z"),"",-1);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_contf_xyz="call 'prepare3d'\ntitle 'ContF[XYZ] sample':rotate 50 60:box\n"
+"contfx {sum c 'x'} '' -1:contfy {sum c 'y'} '' 1:contfz {sum c 'z'} '' -1";
+void smgl_contf_xyz(mglGraph *gr)
+{
+	mglData c;	mgls_prepare3d(&c);
+	if(big!=3)	gr->Title("ContF[XYZ] sample");
+	gr->Rotate(50,60);	gr->Box();	gr->ContFX(c.Sum("x"),"",-1);
+	gr->ContFY(c.Sum("y"),"",1);	gr->ContFZ(c.Sum("z"),"",-1);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_cloud="call 'prepare3d'\nsubplot 2 2 0:title 'Cloud plot':rotate 50 60:alpha on:box:cloud c 'wyrRk'\n"
+"subplot 2 2 1:title '\"i\" style':rotate 50 60:box:cloud c 'iwyrRk'\n"
+"subplot 2 2 2:title '\".\" style':rotate 50 60:box:cloud c '.wyrRk'\n"
+"subplot 2 2 3:title 'meshnum 10':rotate 50 60:box:cloud c 'wyrRk'; meshnum 10";
+void smgl_cloud(mglGraph *gr)
+{
+	mglData c;	mgls_prepare3d(&c);
+	if(big!=3)	{	gr->SubPlot(2,2,0);	gr->Title("Cloud plot");	}
+	gr->Rotate(50,60);	gr->Alpha(true);
+	gr->Box();	gr->Cloud(c,"wyrRk");
+	if(big==3)	return;
+	gr->SubPlot(2,2,1);	gr->Title("'i' style");
+	gr->Rotate(50,60);	gr->Box();	gr->Cloud(c,"iwyrRk");
+	gr->SubPlot(2,2,2);	gr->Title("'.' style");
+	gr->Rotate(50,60);	gr->Box();	gr->Cloud(c,".wyrRk");
+	gr->SubPlot(2,2,3);	gr->Title("meshnum 10");
+	gr->Rotate(50,60);	gr->Box();	gr->Cloud(c,"wyrRk","meshnum 10");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_cont="call 'prepare2d'\nlist v -0.5 -0.15 0 0.15 0.5\nsubplot 2 2 0:title 'Cont plot (default)':rotate 50 60:box:cont a\n"
+"subplot 2 2 1:title 'manual levels':rotate 50 60:box:cont v a\n"
+"subplot 2 2 2:title '\"\\_\" style':rotate 50 60:box:cont a '_'\n"
+"subplot 2 2 3 '':title '\"t\" style':box:cont a 't'";
+void smgl_cont(mglGraph *gr)
+{
+	mglData a,v(5);	mgls_prepare2d(&a);	v.a[0]=-0.5;	v.a[1]=-0.15;	v.a[2]=0;	v.a[3]=0.15;	v.a[4]=0.5;
+	if(big!=3)	{	gr->SubPlot(2,2,0);	gr->Title("Cont plot (default)");	}
+	gr->Rotate(50,60);	gr->Box();	gr->Cont(a);
+	if(big==3)	return;
+	gr->SubPlot(2,2,1);	gr->Title("manual levels");
+	gr->Rotate(50,60);	gr->Box();	gr->Cont(v,a);
+	gr->SubPlot(2,2,2);	gr->Title("'\\_' style");
+	gr->Rotate(50,60);	gr->Box();	gr->Cont(a,"_");
+	gr->SubPlot(2,2,3,"");	gr->Title("'t' style");
+	gr->Box();	gr->Cont(a,"t");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_contf="call 'prepare2d'\nlist v -0.5 -0.15 0 0.15 0.5\n"
+"new a1 30 40 3 '0.6*sin(2*pi*x+pi*(z+1)/2)*sin(3*pi*y+pi*z) + 0.4*cos(3*pi*(x*y)+pi*(z+1)^2/2)'\n"
+"subplot 2 2 0:title 'ContF plot (default)':rotate 50 60:box:contf a\n"
+"subplot 2 2 1:title 'manual levels':rotate 50 60:box:contf v a\n"
+"subplot 2 2 2:title '\"\\_\" style':rotate 50 60:box:contf a '_'\n"
+"subplot 2 2 3:title 'several slices':rotate 50 60:box:contf a1";
+void smgl_contf(mglGraph *gr)
+{
+	mglData a,v(5),a1(30,40,3);	mgls_prepare2d(&a);	v.a[0]=-0.5;
+	v.a[1]=-0.15;	v.a[2]=0;	v.a[3]=0.15;	v.a[4]=0.5;
+	gr->Fill(a1,"0.6*sin(2*pi*x+pi*(z+1)/2)*sin(3*pi*y+pi*z) + 0.4*cos(3*pi*(x*y)+pi*(z+1)^2/2)");
+
+	if(big!=3)	{	gr->SubPlot(2,2,0);	gr->Title("ContF plot (default)");	}
+	gr->Rotate(50,60);	gr->Box();	gr->ContF(a);
+	if(big==3)	return;
+	gr->SubPlot(2,2,1);	gr->Title("manual levels");
+	gr->Rotate(50,60);	gr->Box();	gr->ContF(v,a);
+	gr->SubPlot(2,2,2);	gr->Title("'\\_' style");
+	gr->Rotate(50,60);	gr->Box();	gr->ContF(a,"_");
+	gr->SubPlot(2,2,3);	gr->Title("several slices");
+	gr->Rotate(50,60);	gr->Box();	gr->ContF(a1);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_contd="call 'prepare2d'\nlist v -0.5 -0.15 0 0.15 0.5\n"
+"new a1 30 40 3 '0.6*sin(2*pi*x+pi*(z+1)/2)*sin(3*pi*y+pi*z) + 0.4*cos(3*pi*(x*y)+pi*(z+1)^2/2)'\n"
+"subplot 2 2 0:title 'ContD plot (default)':rotate 50 60:box:contd a\n"
+"subplot 2 2 1:title 'manual levels':rotate 50 60:box:contd v a\n"
+"subplot 2 2 2:title '\"\\_\" style':rotate 50 60:box:contd a '_'\n"
+"subplot 2 2 3:title 'several slices':rotate 50 60:box:contd a1";
+void smgl_contd(mglGraph *gr)
+{
+	mglData a,v(5),a1(30,40,3);	mgls_prepare2d(&a);	v.a[0]=-0.5;
+	v.a[1]=-0.15;	v.a[2]=0;	v.a[3]=0.15;	v.a[4]=0.5;
+	gr->Fill(a1,"0.6*sin(2*pi*x+pi*(z+1)/2)*sin(3*pi*y+pi*z) + 0.4*cos(3*pi*(x*y)+pi*(z+1)^2/2)");
+
+	if(big!=3)	{	gr->SubPlot(2,2,0);	gr->Title("ContD plot (default)");	}
+	gr->Rotate(50,60);	gr->Box();	gr->ContD(a);
+	if(big==3)	return;
+	gr->SubPlot(2,2,1);	gr->Title("manual levels");
+	gr->Rotate(50,60);	gr->Box();	gr->ContD(v,a);
+	gr->SubPlot(2,2,2);	gr->Title("'\\_' style");
+	gr->Rotate(50,60);	gr->Box();	gr->ContD(a,"_");
+	gr->SubPlot(2,2,3);	gr->Title("several slices");
+	gr->Rotate(50,60);	gr->Box();	gr->ContD(a1);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_contv="call 'prepare2d'\nlist v -0.5 -0.15 0 0.15 0.5\n"
+"subplot 2 2 0:title 'ContV plot (default)':rotate 50 60:box:contv a\n"
+"subplot 2 2 1:title 'manual levels':rotate 50 60:box:contv v a\n"
+"subplot 2 2 2:title '\"\\_\" style':rotate 50 60:box:contv a '_'\n"
+"subplot 2 2 3:title 'ContV and ContF':rotate 50 60:light on:box\ncontv a:contf a:cont a 'k'";
+void smgl_contv(mglGraph *gr)
+{
+	mglData a,v(5);	mgls_prepare2d(&a);	v.a[0]=-0.5;
+	v.a[1]=-0.15;	v.a[2]=0;	v.a[3]=0.15;	v.a[4]=0.5;
+	if(big!=3)	{	gr->SubPlot(2,2,0);	gr->Title("ContV plot (default)");	}
+	gr->Rotate(50,60);	gr->Box();	gr->ContV(a);
+	if(big==3)	return;
+	gr->SubPlot(2,2,1);	gr->Title("manual levels");
+	gr->Rotate(50,60);	gr->Box();	gr->ContV(v,a);
+	gr->SubPlot(2,2,2);	gr->Title("'\\_' style");
+	gr->Rotate(50,60);	gr->Box();	gr->ContV(a,"_");
+	gr->SubPlot(2,2,3);	gr->Title("ContV and ContF");
+	gr->Rotate(50,60);	gr->Box();	gr->Light(true);
+	gr->ContV(a);	gr->ContF(a);	gr->Cont(a,"k");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_torus="call 'prepare1d'\nsubplot 2 2 0:title 'Torus plot (default)':light on:rotate 50 60:box:torus y1 y2\n"
+"subplot 2 2 1:title '\"x\" style':light on:rotate 50 60:box:torus y1 y2 'x'\n"
+"subplot 2 2 2:title '\"z\" style':light on:rotate 50 60:box:torus y1 y2 'z'\n"
+"subplot 2 2 3:title '\"\\#\" style':light on:rotate 50 60:box:torus y1 y2 '#'";
+void smgl_torus(mglGraph *gr)
+{
+	mglData y1,y2;	mgls_prepare1d(0,&y1,&y2);
+	if(big!=3)	{	gr->SubPlot(2,2,0);	gr->Title("Torus plot (default)");	}
+	gr->Light(true);	gr->Rotate(50,60);	gr->Box();	gr->Torus(y1,y2);
+	if(big==3)	return;
+	gr->SubPlot(2,2,1);	gr->Title("'x' style");	gr->Rotate(50,60);	gr->Box();	gr->Torus(y1,y2,"x");
+	gr->SubPlot(2,2,2);	gr->Title("'z' style");	gr->Rotate(50,60);	gr->Box();	gr->Torus(y1,y2,"z");
+	gr->SubPlot(2,2,3);	gr->Title("'\\#' style");	gr->Rotate(50,60);	gr->Box();	gr->Torus(y1,y2,"#");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_axial="call 'prepare2d'\nsubplot 2 2 0:title 'Axial plot (default)':light on:alpha on:rotate 50 60:box:axial a\n"
+"subplot 2 2 1:title '\"x\" style;\".\" style':light on:rotate 50 60:box:axial a 'x.'\n"
+"subplot 2 2 2:title '\"z\" style':light on:rotate 50 60:box:axial a 'z'\n"
+"subplot 2 2 3:title '\"\\#\" style':light on:rotate 50 60:box:axial a '#'";
+void smgl_axial(mglGraph *gr)
+{
+	mglData a;	mgls_prepare2d(&a);
+	if(big!=3)	{	gr->SubPlot(2,2,0);	gr->Title("Axial plot (default)");	}
+	gr->Light(true);	gr->Alpha(true);	gr->Rotate(50,60);	gr->Box();	gr->Axial(a);
+	if(big==3)	return;
+	gr->SubPlot(2,2,1);	gr->Title("'x' style; '.'style");	gr->Rotate(50,60);	gr->Box();	gr->Axial(a,"x.");
+	gr->SubPlot(2,2,2);	gr->Title("'z' style");	gr->Rotate(50,60);	gr->Box();	gr->Axial(a,"z");
+	gr->SubPlot(2,2,3);	gr->Title("'\\#' style");	gr->Rotate(50,60);	gr->Box();	gr->Axial(a,"#");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_several_light="call 'prepare2d'\ntitle 'Several light sources':rotate 50 60:light on\n"
+"light 1 0 1 0 'c':light 2 1 0 0 'y':light 3 0 -1 0 'm'\nbox:surf a 'h'";
+void smgl_several_light(mglGraph *gr)	// several light sources
+{
+	mglData a;	mgls_prepare2d(&a);
+	if(big!=3)	gr->Title("Several light sources");
+	gr->Rotate(50,60);	gr->Light(true);	gr->AddLight(1,mglPoint(0,1,0),'c');
+	gr->AddLight(2,mglPoint(1,0,0),'y');	gr->AddLight(3,mglPoint(0,-1,0),'m');
+	gr->Box();	gr->Surf(a,"h");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_light="light on:attachlight on\ncall 'prepare2d'\n"
+"subplot 2 2 0:title 'Default':rotate 50 60:box:surf a\nline -1 -0.7 1.7 -1 -0.7 0.7 'BA'\n\n"
+"subplot 2 2 1:title 'Local':rotate 50 60\nlight 0 1 0 1 -2 -1 -1\nline 1 0 1 -1 -1 0 'BAO':box:surf a\n\n"
+"subplot 2 2 2:title 'no diffuse':rotate 50 60\ndiffuse 0\nline 1 0 1 -1 -1 0 'BAO':box:surf a\n\n"
+"subplot 2 2 3:title 'diffusive only':rotate 50 60\ndiffuse 0.5:light 0 1 0 1 -2 -1 -1 'w' 0\n"
+"line 1 0 1 -1 -1 0 'BAO':box:surf a";
+void smgl_light(mglGraph *gr)	// local light sources
+{
+	mglData a;	mgls_prepare2d(&a);
+	gr->Light(true);	gr->AttachLight(true);
+	if(big==3)
+	{	gr->Rotate(50,60);	gr->Box();	gr->Surf(a);	return;	}
+	gr->SubPlot(2,2,0);	gr->Title("Default");	gr->Rotate(50,60);
+	gr->Line(mglPoint(-1,-0.7,1.7),mglPoint(-1,-0.7,0.7),"BA");	gr->Box();	gr->Surf(a);
+	gr->SubPlot(2,2,1);	gr->Title("Local");	gr->Rotate(50,60);
+	gr->AddLight(0,mglPoint(1,0,1),mglPoint(-2,-1,-1));
+	gr->Line(mglPoint(1,0,1),mglPoint(-1,-1,0),"BAO");	gr->Box();	gr->Surf(a);
+	gr->SubPlot(2,2,2);	gr->Title("no diffuse");	gr->Rotate(50,60);
+	gr->SetDiffuse(0);
+	gr->Line(mglPoint(1,0,1),mglPoint(-1,-1,0),"BAO");	gr->Box();	gr->Surf(a);
+	gr->SubPlot(2,2,3);	gr->Title("diffusive only");	gr->Rotate(50,60);
+	gr->SetDiffuse(0.5);
+	gr->AddLight(0,mglPoint(1,0,1),mglPoint(-2,-1,-1),'w',0);
+	gr->Line(mglPoint(1,0,1),mglPoint(-1,-1,0),"BAO");	gr->Box();	gr->Surf(a);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_surf3="call 'prepare3d'\nlight on:alpha on\n"
+"subplot 2 2 0:title 'Surf3 plot (default)'\nrotate 50 60:box:surf3 c\n"
+"subplot 2 2 1:title '\"\\#\" style'\nrotate 50 60:box:surf3 c '#'\n"
+"subplot 2 2 2:title '\".\" style'\nrotate 50 60:box:surf3 c '.'";
+void smgl_surf3(mglGraph *gr)
+{
+	mglData c;	mgls_prepare3d(&c);
+	if(big!=3)	{	gr->SubPlot(2,2,0);	gr->Title("Surf3 plot (default)");	}
+	gr->Rotate(50,60);	gr->Light(true);	gr->Alpha(true);
+	gr->Box();	gr->Surf3(c);
+	if(big==3)	return;
+	gr->SubPlot(2,2,1);	gr->Title("'\\#' style");
+	gr->Rotate(50,60);	gr->Box();	gr->Surf3(c,"#");
+	gr->SubPlot(2,2,2);	gr->Title("'.' style");
+	gr->Rotate(50,60);	gr->Box();	gr->Surf3(c,".");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_surf3a="call 'prepare3d'\ntitle 'Surf3A plot':rotate 50 60:light on:alpha on:box:surf3a c d";
+void smgl_surf3a(mglGraph *gr)
+{
+	mglData c,d;	mgls_prepare3d(&c,&d);
+	if(big!=3)	gr->Title("Surf3A plot");
+	gr->Rotate(50,60);	gr->Light(true);	gr->Alpha(true);
+	gr->Box();	gr->Surf3A(c,d);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_surf3c="call 'prepare3d'\ntitle 'Surf3C plot':rotate 50 60:light on:alpha on:box:surf3c c d";
+void smgl_surf3c(mglGraph *gr)
+{
+	mglData c,d;	mgls_prepare3d(&c,&d);
+	if(big!=3)	gr->Title("Surf3C plot");
+	gr->Rotate(50,60);	gr->Light(true);	gr->Alpha(true);
+	gr->Box();	gr->Surf3C(c,d);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_surf3ca="call 'prepare3d'\ntitle 'Surf3CA plot':rotate 50 60:light on:alpha on:box:surf3ca c d c";
+void smgl_surf3ca(mglGraph *gr)
+{
+	mglData c,d;	mgls_prepare3d(&c,&d);
+	if(big!=3)	gr->Title("Surf3CA plot");
+	gr->Rotate(50,60);	gr->Light(true);	gr->Alpha(true);
+	gr->Box();	gr->Surf3CA(c,d,c);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_cut="call 'prepare2d'\ncall 'prepare3d'\nsubplot 2 2 0:title 'Cut on (default)':rotate 50 60:light on:box:surf a; zrange -1 0.5\n"
+"subplot 2 2 1:title 'Cut off':rotate 50 60:box:surf a; zrange -1 0.5; cut off\n"
+"subplot 2 2 2:title 'Cut in box':rotate 50 60:box:alpha on\ncut 0 -1 -1 1 0 1.1:surf3 c\ncut 0 0 0 0 0 0\t# restore back\n"
+"subplot 2 2 3:title 'Cut by formula':rotate 50 60:box\ncut '(z>(x+0.5*y-1)^2-1) & (z>(x-0.5*y-1)^2-1)':surf3 c";
+void smgl_cut(mglGraph *gr)	// cutting
+{
+	mglData a,c,v(1);	mgls_prepare2d(&a);	mgls_prepare3d(&c);	v.a[0]=0.5;
+	gr->SubPlot(2,2,0);	gr->Title("Cut on (default)");	gr->Rotate(50,60);	gr->Light(true);
+	gr->Box();	gr->Surf(a,"","zrange -1 0.5");
+	gr->SubPlot(2,2,1);	gr->Title("Cut off");		gr->Rotate(50,60);
+	gr->Box();	gr->Surf(a,"","zrange -1 0.5; cut off");
+	gr->SubPlot(2,2,2);	gr->Title("Cut in box");	gr->Rotate(50,60);
+	gr->SetCutBox(mglPoint(0,-1,-1), mglPoint(1,0,1.1));
+	gr->Alpha(true);	gr->Box();	gr->Surf3(c);
+	gr->SetCutBox(mglPoint(0), mglPoint(0));	// switch it off
+	gr->SubPlot(2,2,3);	gr->Title("Cut by formula");	gr->Rotate(50,60);
+	gr->CutOff("(z>(x+0.5*y-1)^2-1) & (z>(x-0.5*y-1)^2-1)");
+	gr->Box();	gr->Surf3(c);	gr->CutOff("");	// switch it off
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_traj="call 'prepare1d'\nsubplot 1 1 0 '':title 'Traj plot':box:plot x1 y:traj x1 y y1 y2";
+void smgl_traj(mglGraph *gr)
+{
+	mglData x,y,y1,y2;	mgls_prepare1d(&y,&y1,&y2,&x);
+	if(big!=3)	{gr->SubPlot(1,1,0,"");	gr->Title("Traj plot");}
+	gr->Box();	gr->Plot(x,y);	gr->Traj(x,y,y1,y2);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_mesh="call 'prepare2d'\ntitle 'Mesh plot':rotate 50 60:box:mesh a";
+void smgl_mesh(mglGraph *gr)
+{
+	mglData a;	mgls_prepare2d(&a);
+	if(big!=3)	gr->Title("Mesh plot");
+	gr->Rotate(50,60);	gr->Box();	gr->Mesh(a);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_fall="call 'prepare2d'\ntitle 'Fall plot':rotate 50 60:box:fall a";
+void smgl_fall(mglGraph *gr)
+{
+	mglData a;	mgls_prepare2d(&a);
+	if(big!=3)	gr->Title("Fall plot");
+	gr->Rotate(50,60);	gr->Box();	gr->Fall(a);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_surf="call 'prepare2d'\nsubplot 2 2 0:title 'Surf plot (default)':rotate 50 60:light on:box:surf a\n"
+"subplot 2 2 1:title '\"\\#\" style; meshnum 10':rotate 50 60:box:surf a '#'; meshnum 10\n"
+"subplot 2 2 2:title '\".\" style':rotate 50 60:box:surf a '.'\n"
+"new x 50 40 '0.8*sin(pi*x)*sin(pi*(y+1)/2)'\nnew y 50 40 '0.8*cos(pi*x)*sin(pi*(y+1)/2)'\nnew z 50 40 '0.8*cos(pi*(y+1)/2)'\n"
+"subplot 2 2 3:title 'parametric form':rotate 50 60:box:surf x y z 'BbwrR'";
+void smgl_surf(mglGraph *gr)
+{
+	mglData a;	mgls_prepare2d(&a);
+	if(big!=3)	{	gr->SubPlot(2,2,0);	gr->Title("Surf plot (default)");	}
+	gr->Light(true);	gr->Rotate(50,60);	gr->Box();	gr->Surf(a);
+	if(big==3)	return;
+	gr->SubPlot(2,2,1);	gr->Title("'\\#' style; meshnum 10");
+	gr->Rotate(50,60);	gr->Box();	gr->Surf(a,"#","meshnum 10");
+	gr->SubPlot(2,2,2);	gr->Title("'.' style");
+	gr->Rotate(50,60);	gr->Box();	gr->Surf(a,".");
+	gr->SubPlot(2,2,3);	gr->Title("parametric form");
+	mglData x(50,40),y(50,40),z(50,40);
+	gr->Fill(x,"0.8*sin(pi*x)*sin(pi*(y+1)/2)");
+	gr->Fill(y,"0.8*cos(pi*x)*sin(pi*(y+1)/2)");
+	gr->Fill(z,"0.8*cos(pi*(y+1)/2)");
+	gr->Rotate(50,60);	gr->Box();	gr->Surf(x,y,z,"BbwrR");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_parser="title 'MGL parser sample'\ncall 'sample'\nstop\nfunc 'sample'\n"
+"new dat 100 'sin(2*pi*(x+1))'\nplot dat; xrange 0 1\nbox\naxis\n"
+"xlabel 'x'\nylabel 'y'\nbox\nfor $0 -1 1 0.1\nif $0<0\n"
+"line 0 0 -1 $0 'r':else:line 0 0 -1 $0 'g'\nendif\nnext";
+void smgl_parser(mglGraph *gr)	// example of MGL parsing
+{
+	gr->Title("MGL parser sample");
+	double a[100];   // let a_i = sin(4*pi*x), x=0...1
+	for(int i=0;i<100;i++)a[i]=sin(4*M_PI*i/99);
+	mglParse *parser = new mglParse;
+	mglData *d = dynamic_cast<mglData*>(parser->AddVar("dat"));
+	if(d)	d->Set(a,100); // set data to variable
+	parser->Execute(gr, "plot dat; xrange 0 1\nbox\naxis");
+	// you may break script at any line do something
+	// and continue after that
+	parser->Execute(gr, "xlabel 'x'\nylabel 'y'\nbox");
+	// also you may use cycles or conditions in script
+	parser->Execute(gr, "for $0 -1 1 0.1\nif $0<0\n"
+		"line 0 0 -1 $0 'r':else:line 0 0 -1 $0 'g'\n"
+		"endif\nnext");
+	delete parser;
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_belt="call 'prepare2d'\ntitle 'Belt plot':rotate 50 60:box:belt a";
+void smgl_belt(mglGraph *gr)
+{
+	mglData a;	mgls_prepare2d(&a);
+	if(big!=3)	gr->Title("Belt plot");
+	gr->Rotate(50,60);	gr->Box();	gr->Belt(a);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_dens="call 'prepare2d'\nnew a1 30 40 3 '0.6*sin(2*pi*x+pi*(z+1)/2)*sin(3*pi*y+pi*z) + 0.4*cos(3*pi*(x*y)+pi*(z+1)^2/2)'\n"
+"subplot 2 2 0 '':title 'Dens plot (default)':box:dens a\n"
+"subplot 2 2 1:title '3d variant':rotate 50 60:box:dens a\n"
+"subplot 2 2 2 '':title '\"\\#\" style; meshnum 10':box:dens a '#'; meshnum 10\n"
+"subplot 2 2 3:title 'several slices':rotate 50 60:box:dens a1";
+void smgl_dens(mglGraph *gr)
+{
+	mglData a,a1(30,40,3);	mgls_prepare2d(&a);
+	gr->Fill(a1,"0.6*sin(2*pi*x+pi*(z+1)/2)*sin(3*pi*y+pi*z) + 0.4*cos(3*pi*(x*y)+pi*(z+1)^2/2)");
+	if(big!=3)	{gr->SubPlot(2,2,0,"");	gr->Title("Dens plot (default)");}
+	gr->Box();	gr->Dens(a);
+	if(big==3)	return;
+	gr->SubPlot(2,2,1);	gr->Title("3d variant");
+	gr->Rotate(50,60);	gr->Box();	gr->Dens(a);
+	gr->SubPlot(2,2,2,"");	gr->Title("'\\#' style; meshnum 10");
+	gr->Box();	gr->Dens(a,"#","meshnum 10");
+	gr->SubPlot(2,2,3);	gr->Title("several slices");
+	gr->Rotate(50,60);		gr->Box();	gr->Dens(a1);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_surfc="call 'prepare2d'\ntitle 'SurfC plot':rotate 50 60:light on:box:surfc a b";
+void smgl_surfc(mglGraph *gr)
+{
+	mglData a,b;	mgls_prepare2d(&a,&b);
+	if(big!=3)	gr->Title("SurfC plot");
+	gr->Rotate(50,60);	gr->Light(true);	gr->Box();	gr->SurfC(a,b);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_surfca="call 'prepare2d'\ntitle 'SurfCA plot':rotate 50 60:light on:alpha on:box:surfca a b a";
+void smgl_surfca(mglGraph *gr)
+{
+	mglData a,b;	mgls_prepare2d(&a,&b);
+	if(big!=3)	gr->Title("SurfCA plot");
+	gr->Rotate(50,60);	gr->Alpha(true);	gr->Light(true);	gr->Box();
+	gr->SurfCA(a,b,a);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_surfa="call 'prepare2d'\ntitle 'SurfA plot':rotate 50 60:light on:alpha on:box:surfa a b";
+void smgl_surfa(mglGraph *gr)
+{
+	mglData a,b;	mgls_prepare2d(&a,&b);
+	if(big!=3)	gr->Title("SurfA plot");
+	gr->Rotate(50,60);	gr->Alpha(true);	gr->Light(true);	gr->Box();
+	gr->SurfA(a,b);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_tile="call 'prepare2d'\ntitle 'Tile plot':rotate 50 60:box:tile a";
+void smgl_tile(mglGraph *gr)
+{
+	mglData a;	mgls_prepare2d(&a);
+	if(big!=3)	gr->Title("Tile plot");
+	gr->Rotate(40,60);	gr->Box();	gr->Tile(a);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_tiles="call 'prepare2d'\nsubplot 1 1 0 '':title 'Tiles plot':box:tiles a b";
+void smgl_tiles(mglGraph *gr)
+{
+	mglData a,b;	mgls_prepare2d(&a,&b);
+	if(big!=3)	{gr->SubPlot(1,1,0,"");	gr->Title("TileS plot");}
+	gr->Box();	gr->TileS(a,b);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_boxs="call 'prepare2d'\norigin 0 0 0\nsubplot 2 2 0:title 'Boxs plot (default)':rotate 40 60:light on:box:boxs a\n"
+"subplot 2 2 1:title '\"\\@\" style':rotate 50 60:box:boxs a '@'\n"
+"subplot 2 2 2:title '\"\\#\" style':rotate 50 60:box:boxs a '#'\n"
+"subplot 2 2 3:title 'compare with Tile':rotate 50 60:box:tile a";
+void smgl_boxs(mglGraph *gr)
+{
+	mglData a;	mgls_prepare2d(&a);
+	gr->SetOrigin(0,0,0);	gr->Light(true);
+	if(big!=3)	{gr->SubPlot(2,2,0);	gr->Title("Boxs plot (default)");}
+	gr->Rotate(40,60);	gr->Box();	gr->Boxs(a);
+	if(big==3)	return;
+	gr->SubPlot(2,2,1);	gr->Title("'\\@' style");
+	gr->Rotate(50,60);	gr->Box();	gr->Boxs(a,"@");
+	gr->SubPlot(2,2,2);	gr->Title("'\\#' style");
+	gr->Rotate(50,60);	gr->Box();	gr->Boxs(a,"#");
+	gr->SubPlot(2,2,3);	gr->Title("compare with Tile");
+	gr->Rotate(50,60);	gr->Box();	gr->Tile(a);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_fit="new dat 100 '0.4*rnd+0.1+sin(2*pi*x)'\nnew in 100 '0.3+sin(2*pi*x)'\n"
+"list ini 1 1 3:fit res dat 'a+b*sin(c*x)' 'abc' ini\n"
+"title 'Fitting sample':yrange -2 2:box:axis:plot dat 'k. '\n"
+"plot res 'r':plot in 'b'\ntext -0.9 -1.3 'fitted:' 'r:L'\n"
+"putsfit 0 -1.8 'y = ' 'r':text 0 2.2 'initial: y = 0.3+sin(2\\pi x)' 'b'";
+void smgl_fit(mglGraph *gr)	// nonlinear fitting
+{
+	mglData dat(100), in(100), res;
+	gr->Fill(dat,"0.4*rnd+0.1+sin(2*pi*x)");
+	gr->Fill(in,"0.3+sin(2*pi*x)");
+	double ini[3] = {1,1,3};
+	mglData Ini(3,ini);
+	res = gr->Fit(dat, "a+b*sin(c*x)", "abc", Ini);
+	if(big!=3)	gr->Title("Fitting sample");
+	gr->SetRange('y',-2,2);	gr->Box();	gr->Plot(dat, "k. ");
+	gr->Axis();		gr->Plot(res, "r");	gr->Plot(in, "b");
+	gr->Puts(mglPoint(-0.9, -1.3), "fitted:", "r:L");
+	gr->PutsFit(mglPoint(0, -1.8), "y = ", "r");
+	gr->Puts(mglPoint(0, 2.2), "initial: y = 0.3+sin(2\\pi x)", "b");
+//	gr->SetRanges(mglPoint(-1,-1,-1),mglPoint(1,1,1));	gr->SetOrigin(0,0,0);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_vecta="call 'prepare3v'\nsubplot 2 1 0:title 'Vect3 sample':rotate 50 60\n"
+"origin 0 0 0:box:axis '_xyz'\nvect3 ex ey ez 'x':vect3 ex ey ez:vect3 ex ey ez 'z'\n"
+"subplot 2 1 1:title '\"f\" style':rotate 50 60\n"
+"origin 0 0 0:box:axis '_xyz'\nvect3 ex ey ez 'fx':vect3 ex ey ez 'f':vect3 ex ey ez 'fz'\n"
+"grid3 ex 'Wx':grid3 ex 'W':grid3 ex 'Wz'";
+void smgl_vecta(mglGraph *gr)
+{
+	mglData ex,ey,ez;	mgls_prepare3v(&ex,&ey,&ez);
+	if(big!=3)	{	gr->SubPlot(2,1,0);	gr->Title("Vect3 sample");	}
+	gr->Rotate(50,60);	gr->SetOrigin(0,0,0);	gr->Axis("_xyz");	gr->Box();
+	gr->Vect3(ex,ey,ez,"x");	gr->Vect3(ex,ey,ez);	gr->Vect3(ex,ey,ez,"z");
+	if(big==3)	return;
+	gr->SubPlot(2,1,1);	gr->Title("'f' style");
+	gr->Rotate(50,60);	gr->SetOrigin(0,0,0);	gr->Axis("_xyz");	gr->Box();
+	gr->Vect3(ex,ey,ez,"fx");	gr->Vect3(ex,ey,ez,"f");	gr->Vect3(ex,ey,ez,"fz");
+	gr->Grid3(ex,"Wx");	gr->Grid3(ex,"W");	gr->Grid3(ex,"Wz");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_vect="call 'prepare2v'\ncall 'prepare3v'\nsubplot 3 2 0 '':title 'Vect plot (default)':box:vect a b\n"
+"subplot 3 2 1 '':title '\".\" style; \"=\" style':box:vect a b '.='\n"
+"subplot 3 2 2 '':title '\"f\" style':box:vect a b 'f'\n"
+"subplot 3 2 3 '':title '\">\" style':box:vect a b '>'\n"
+"subplot 3 2 4 '':title '\"<\" style':box:vect a b '<'\n"
+"subplot 3 2 5:title '3d variant':rotate 50 60:box:vect ex ey ez";
+void smgl_vect(mglGraph *gr)
+{
+	mglData a,b;	mgls_prepare2v(&a,&b);
+	if(big!=3)	{gr->SubPlot(3,2,0,"");	gr->Title("Vect plot (default)");}
+	gr->Box();	gr->Vect(a,b);
+	if(big==3)	return;
+	gr->SubPlot(3,2,1,"");	gr->Title("'.' style; '=' style");	gr->Box();	gr->Vect(a,b,"=.");
+	gr->SubPlot(3,2,2,"");	gr->Title("'f' style");	gr->Box();	gr->Vect(a,b,"f");
+	gr->SubPlot(3,2,3,"");	gr->Title("'>' style");	gr->Box();	gr->Vect(a,b,">");
+	gr->SubPlot(3,2,4,"");	gr->Title("'<' style");	gr->Box();	gr->Vect(a,b,"<");
+	mglData ex,ey,ez;	mgls_prepare3v(&ex,&ey,&ez);
+	gr->SubPlot(3,2,5);	gr->Title("3d variant");	gr->Rotate(50,60);
+	gr->Box();	gr->Vect(ex,ey,ez);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_flow="call 'prepare2v'\ncall 'prepare3v'\nsubplot 2 2 0 '':title 'Flow plot (default)':box:flow a b\n"
+"subplot 2 2 1 '':title '\"v\" style':box:flow a b 'v'\n"
+"subplot 2 2 2 '':title 'from edges only':box:flow a b '#'\n"
+"subplot 2 2 3:title '3d variant':rotate 50 60:box:flow ex ey ez";
+void smgl_flow(mglGraph *gr)
+{
+	mglData a,b;	mgls_prepare2v(&a,&b);
+	if(big!=3)	{gr->SubPlot(2,2,0,"");	gr->Title("Flow plot (default)");}
+	gr->Box();	gr->Flow(a,b);
+	if(big==3)	return;
+	gr->SubPlot(2,2,1,"");	gr->Title("'v' style");	gr->Box();	gr->Flow(a,b,"v");
+	gr->SubPlot(2,2,2,"");	gr->Title("'\\#' style");	gr->Box();	gr->Flow(a,b,"#");
+	mglData ex,ey,ez;	mgls_prepare3v(&ex,&ey,&ez);
+	gr->SubPlot(2,2,3);	gr->Title("3d variant");	gr->Rotate(50,60);
+	gr->Box();	gr->Flow(ex,ey,ez);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_pipe="call 'prepare2v'\ncall 'prepare3v'\nsubplot 2 2 0 '':title 'Pipe plot (default)':light on:box:pipe a b\n"
+"subplot 2 2 1 '':title '\"i\" style':box:pipe a b 'i'\n"
+"subplot 2 2 2 '':title 'from edges only':box:pipe a b '#'\n"
+"subplot 2 2 3:title '3d variant':rotate 50 60:box:pipe ex ey ez '' 0.1";
+void smgl_pipe(mglGraph *gr)
+{
+	mglData a,b;	mgls_prepare2v(&a,&b);
+	if(big!=3)	{gr->SubPlot(2,2,0,"");	gr->Title("Pipe plot (default)");}
+	gr->Light(true);	gr->Box();	gr->Pipe(a,b);
+	if(big==3)	return;
+	gr->SubPlot(2,2,1,"");	gr->Title("'i' style");	gr->Box();	gr->Pipe(a,b,"i");
+	gr->SubPlot(2,2,2,"");	gr->Title("'\\#' style");	gr->Box();	gr->Pipe(a,b,"#");
+	mglData ex,ey,ez;	mgls_prepare3v(&ex,&ey,&ez);
+	gr->SubPlot(2,2,3);	gr->Title("3d variant");	gr->Rotate(50,60);
+	gr->Box();	gr->Pipe(ex,ey,ez,"",0.1);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_dew="call 'prepare2v'\nsubplot 1 1 0 '':title 'Dew plot':light on:box:dew a b";
+void smgl_dew(mglGraph *gr)
+{
+	mglData a,b;	mgls_prepare2v(&a,&b);
+	if(big!=3)	{gr->SubPlot(1,1,0,"");	gr->Title("Dew plot");}
+	gr->Box();	gr->Light(true);	gr->Dew(a,b);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_grad="call 'prepare2d'\nsubplot 1 1 0 '':title 'Grad plot':box:grad a:dens a '{u8}w{q8}'";
+void smgl_grad(mglGraph *gr)
+{
+	mglData a;	mgls_prepare2d(&a);
+	if(big!=3)	{gr->SubPlot(1,1,0,"");	gr->Title("Grad plot");}
+	gr->Box();	gr->Grad(a);	gr->Dens(a,"{u8}w{q8}");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_cones="new ys 10 3 '0.8*sin(pi*(x+y/4+1.25))+0.2*rnd'\nlight on:origin 0 0 0\n"
+"subplot 3 2 0:title 'Cones plot':rotate 50 60:box:cones ys\n"
+"subplot 3 2 1:title '2 colors':rotate 50 60:box:cones ys 'cbgGyr'\n"
+"subplot 3 2 2:title '\"\\#\" style':rotate 50 60:box:cones ys '#'\n"
+"subplot 3 2 3:title '\"a\" style':rotate 50 60:zrange -2 2:box:cones ys 'a'\n"
+"subplot 3 2 4:title '\"t\" style':rotate 50 60:box:cones ys 't'\n"
+"subplot 3 2 5:title '\"4\" style':rotate 50 60:box:cones ys '4'";
+void smgl_cones(mglGraph *gr)
+{
+	mglData ys(10,3);	ys.Modify("0.8*sin(pi*(2*x+y/2))+0.2*rnd");
+	gr->Light(true);	gr->SetOrigin(0,0,0);
+	if(big!=3)	{	gr->SubPlot(3,2,0);	gr->Title("Cones plot");	}
+	gr->Rotate(50,60);	gr->Box();	gr->Cones(ys);
+	if(big==3)	return;
+	gr->SubPlot(3,2,1);	gr->Title("2 colors");
+	gr->Rotate(50,60);	gr->Box();	gr->Cones(ys,"cbgGyr");
+	gr->SubPlot(3,2,2);	gr->Title("'\\#' style");
+	gr->Rotate(50,60);	gr->Box();	gr->Cones(ys,"#");
+	gr->SubPlot(3,2,3);	gr->Title("'a' style");
+	gr->SetRange('z',-2,2);	// increase range since summation can exceed [-1,1]
+	gr->Rotate(50,60);	gr->Box();	gr->Cones(ys,"a");
+	gr->SubPlot(3,2,4);	gr->Title("'t' style");
+	gr->Rotate(50,60);	gr->Box();	gr->Cones(ys,"t");
+	gr->SubPlot(3,2,5);	gr->Title("'4' style");
+	gr->Rotate(50,60);	gr->Box();	gr->Cones(ys,"4");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_aspect="subplot 2 2 0:box:text -1 1.1 'Just box' ':L'\n"
+"inplot 0.2 0.5 0.7 1 off:box:text 0 1.2 'InPlot example'\n"
+"subplot 2 2 1:title 'Rotate only':rotate 50 60:box\n"
+"subplot 2 2 2:title 'Rotate and Aspect':rotate 50 60:aspect 1 1 2:box\n"
+"subplot 2 2 3:title 'Shear':box 'c':shear 0.2 0.1:box";
+void smgl_aspect(mglGraph *gr)	// transformation
+{
+	gr->SubPlot(2,2,0);	gr->Box();
+	gr->Puts(mglPoint(-1,1.1),"Just box",":L");
+	gr->InPlot(0.2,0.5,0.7,1,false);	gr->Box();
+	gr->Puts(mglPoint(0,1.2),"InPlot example");
+	gr->SubPlot(2,2,1);	gr->Title("Rotate only");
+	gr->Rotate(50,60);	gr->Box();
+	gr->SubPlot(2,2,2);	gr->Title("Rotate and Aspect");
+	gr->Rotate(50,60);	gr->Aspect(1,1,2);	gr->Box();
+	gr->SubPlot(2,2,3);	gr->Title("Shear");
+	gr->Box("c");		gr->Shear(0.2,0.1);	gr->Box();
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_inplot="subplot 3 2 0:title 'StickPlot'\nstickplot 3 0 20 30:box 'r':text 0 0 0 '0' 'r'\n"
+"stickplot 3 1 20 30:box 'g':text 0 0 0 '1' 'g'\nstickplot 3 2 20 30:box 'b':text 0 9 0 '2' 'b'\n"
+"subplot 3 2 3 '':title 'ColumnPlot'\ncolumnplot 3 0:box 'r':text 0 0 '0' 'r'\n"
+"columnplot 3 1:box 'g':text 0 0 '1' 'g'\ncolumnplot 3 2:box 'b':text 0 0 '2' 'b'\n"
+"subplot 3 2 4 '':title 'GridPlot'\ngridplot 2 2 0:box 'r':text 0 0 '0' 'r'\n"
+"gridplot 2 2 1:box 'g':text 0 0 '1' 'g'\ngridplot 2 2 2:box 'b':text 0 0 '2' 'b'\n"
+"gridplot 2 2 3:box 'm':text 0 0 '3' 'm'\nsubplot 3 2 5 '':title 'InPlot':box\n"
+"inplot 0.4 1 0.6 1 on:box 'r'\nmultiplot 3 2 1 2 1 '':title 'MultiPlot and ShearPlot':box\n"
+"shearplot 3 0 0.2 0.1:box 'r':text 0 0 '0' 'r'\nshearplot 3 1 0.2 0.1:box 'g':text 0 0 '1' 'g'\n"
+"shearplot 3 2 0.2 0.1:box 'b':text 0 0 '2' 'b'";
+void smgl_inplot(mglGraph *gr)
+{
+	gr->SubPlot(3,2,0);	gr->Title("StickPlot");
+	gr->StickPlot(3, 0, 20, 30);	gr->Box("r");	gr->Puts(mglPoint(0),"0","r");
+	gr->StickPlot(3, 1, 20, 30);	gr->Box("g");	gr->Puts(mglPoint(0),"1","g");
+	gr->StickPlot(3, 2, 20, 30);	gr->Box("b");	gr->Puts(mglPoint(0),"2","b");
+	gr->SubPlot(3,2,3,"");	gr->Title("ColumnPlot");
+	gr->ColumnPlot(3, 0);	gr->Box("r");	gr->Puts(mglPoint(0),"0","r");
+	gr->ColumnPlot(3, 1);	gr->Box("g");	gr->Puts(mglPoint(0),"1","g");
+	gr->ColumnPlot(3, 2);	gr->Box("b");	gr->Puts(mglPoint(0),"2","b");
+	gr->SubPlot(3,2,4,"");	gr->Title("GridPlot");
+	gr->GridPlot(2, 2, 0);	gr->Box("r");	gr->Puts(mglPoint(0),"0","r");
+	gr->GridPlot(2, 2, 1);	gr->Box("g");	gr->Puts(mglPoint(0),"1","g");
+	gr->GridPlot(2, 2, 2);	gr->Box("b");	gr->Puts(mglPoint(0),"2","b");
+	gr->GridPlot(2, 2, 3);	gr->Box("m");	gr->Puts(mglPoint(0),"3","m");
+	gr->SubPlot(3,2,5,"");	gr->Title("InPlot");	gr->Box();
+	gr->InPlot(0.4, 1, 0.6, 1, true);	gr->Box("r");
+	gr->MultiPlot(3,2,1, 2, 1,"");	gr->Title("MultiPlot and ShearPlot");	gr->Box();
+	gr->ShearPlot(3, 0, 0.2, 0.1);	gr->Box("r");	gr->Puts(mglPoint(0),"0","r");
+	gr->ShearPlot(3, 1, 0.2, 0.1);	gr->Box("g");	gr->Puts(mglPoint(0),"1","g");
+	gr->ShearPlot(3, 2, 0.2, 0.1);	gr->Box("b");	gr->Puts(mglPoint(0),"2","b");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_combined="call 'prepare2v'\ncall 'prepare3d'\nnew v 10:fill v -0.5 1:copy d sqrt(a^2+b^2)\n"
+"subplot 2 2 0:title 'Surf + Cont':rotate 50 60:light on:box:surf a:cont a 'y'\n"
+"subplot 2 2 1 '':title 'Flow + Dens':light off:box:flow a b 'br':dens d\n"
+"subplot 2 2 2:title 'Mesh + Cont':rotate 50 60:box:mesh a:cont a '_'\n"
+"subplot 2 2 3:title 'Surf3 + ContF3':rotate 50 60:light on\n"
+"box:contf3 v c 'z' 0:contf3 v c 'x':contf3 v c\ncut 0 -1 -1 1 0 1.1\ncontf3 v c 'z' c.nz-1:surf3 c -0.5";
+void smgl_combined(mglGraph *gr)	// flow threads and density plot
+{
+	mglData a,b,d;	mgls_prepare2v(&a,&b);	d = a;
+	for(int i=0;i<a.nx*a.ny;i++)	d.a[i] = hypot(a.a[i],b.a[i]);
+	mglData c;	mgls_prepare3d(&c);
+	mglData v(10);	v.Fill(-0.5,1);
+	gr->SubPlot(2,2,1,"");	gr->Title("Flow + Dens");
+	gr->Flow(a,b,"br");	gr->Dens(d);	gr->Box();
+	gr->SubPlot(2,2,0);	gr->Title("Surf + Cont");	gr->Rotate(50,60);
+	gr->Light(true);	gr->Surf(a);	gr->Cont(a,"y");	gr->Box();
+	gr->SubPlot(2,2,2);	gr->Title("Mesh + Cont");	gr->Rotate(50,60);
+	gr->Box();	gr->Mesh(a);	gr->Cont(a,"_");
+	gr->SubPlot(2,2,3);	gr->Title("Surf3 + ContF3");gr->Rotate(50,60);
+	gr->Box();	gr->ContF3(v,c,"z",0);	gr->ContF3(v,c,"x");	gr->ContF3(v,c);
+	gr->SetCutBox(mglPoint(0,-1,-1), mglPoint(1,0,1.1));
+	gr->ContF3(v,c,"z",c.nz-1);	gr->Surf3(-0.5,c);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_axis="subplot 2 2 0:title 'Axis origin, Grid':origin 0 0:axis:grid:fplot 'x^3'\n"
+"subplot 2 2 1:title '2 axis':ranges -1 1 -1 1:origin -1 -1:axis:ylabel 'axis_1':fplot 'sin(pi*x)' 'r2'\n"
+"ranges 0 1 0 1:origin 1 1:axis:ylabel 'axis_2':fplot 'cos(pi*x)'\n"
+"subplot 2 2 3:title 'More axis':origin nan nan:xrange -1 1:axis:xlabel 'x' 0:ylabel 'y_1' 0:fplot 'x^2' 'k'\n"
+"yrange -1 1:origin -1.3 -1:axis 'y' 'r':ylabel '#r{y_2}' 0.2:fplot 'x^3' 'r'\n\n"
+"subplot 2 2 2:title '4 segments, inverted axis':origin 0 0:\n"
+"inplot 0.5 1 0.5 1 on:ranges 0 10 0 2:axis\nfplot 'sqrt(x/2)':xlabel 'W' 1:ylabel 'U' 1\n"
+"inplot 0 0.5 0.5 1 on:ranges 1 0 0 2:axis 'x':fplot 'sqrt(x)+x^3':xlabel '\\tau' 1\n"
+"inplot 0.5 1 0 0.5 on:ranges 0 10 4 0:axis 'y':fplot 'x/4':ylabel 'L' -1\n"
+"inplot 0 0.5 0 0.5 on:ranges 1 0 4 0:fplot '4*x^2'";
+void smgl_axis(mglGraph *gr)
+{
+	gr->SubPlot(2,2,0);	gr->Title("Axis origin, Grid");	gr->SetOrigin(0,0);
+	gr->Axis();	gr->Grid();	gr->FPlot("x^3");
+
+	gr->SubPlot(2,2,1);	gr->Title("2 axis");
+	gr->SetRanges(-1,1,-1,1);	gr->SetOrigin(-1,-1,-1);	// first axis
+	gr->Axis();	gr->Label('y',"axis 1",0);	gr->FPlot("sin(pi*x)","r2");
+	gr->SetRanges(0,1,0,1);		gr->SetOrigin(1,1,1);		// second axis
+	gr->Axis();	gr->Label('y',"axis 2",0);	gr->FPlot("cos(pi*x)");
+
+	gr->SubPlot(2,2,3);	gr->Title("More axis");	gr->SetOrigin(NAN,NAN);	gr->SetRange('x',-1,1);
+	gr->Axis();	gr->Label('x',"x",0);	gr->Label('y',"y_1",0);	gr->FPlot("x^2","k");
+	gr->SetRanges(-1,1,-1,1);	gr->SetOrigin(-1.3,-1);	// second axis
+	gr->Axis("y","r");	gr->Label('y',"#r{y_2}",0.2);	gr->FPlot("x^3","r");
+
+	gr->SubPlot(2,2,2);	gr->Title("4 segments, inverted axis");		gr->SetOrigin(0,0);
+	gr->InPlot(0.5,1,0.5,1);	gr->SetRanges(0,10,0,2);	gr->Axis();
+	gr->FPlot("sqrt(x/2)");		gr->Label('x',"W",1);	gr->Label('y',"U",1);
+	gr->InPlot(0,0.5,0.5,1);	gr->SetRanges(1,0,0,2);	gr->Axis("x");
+	gr->FPlot("sqrt(x)+x^3");	gr->Label('x',"\\tau",-1);
+	gr->InPlot(0.5,1,0,0.5);	gr->SetRanges(0,10,4,0);	gr->Axis("y");
+	gr->FPlot("x/4");	gr->Label('y',"L",-1);
+	gr->InPlot(0,0.5,0,0.5);	gr->SetRanges(1,0,4,0);	gr->FPlot("4*x^2");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_ticks="subplot 3 3 0:title 'Usual axis'\naxis\n\n"
+"subplot 3 3 1:title 'Too big/small range'\nranges -1000 1000 0 0.001:axis\n\n"
+"subplot 3 3 2:title 'LaTeX-like labels'\naxis 'F!'\n\n"
+"subplot 3 3 3:title 'Too narrow range'\nranges 100 100.1 10 10.01:axis\n\n"
+"subplot 3 3 4:title 'No tuning, manual \"+\"'\naxis '+!'\n"
+"# for version <2.3 you can use\n#tuneticks off:axis\n\n"
+"subplot 3 3 5:title 'Template for ticks'\nxtick 'xxx:%g':ytick 'y:%g'\naxis\n\n"
+"xtick '':ytick '' # switch it off for other plots\n\n"
+"subplot 3 3 6:title 'No tuning, higher precision'\naxis '!4'\n\n"
+"subplot 3 3 7:title 'Manual ticks'\nranges -pi pi 0 2\n"
+"xtick pi 3 '\\pi'\nxtick 0.886 'x^*' on # note this will disable subticks drawing\n"
+"# or you can use\n#xtick -pi '\\pi' -pi/2 '-\\pi/2' 0 '0' 0.886 'x^*' pi/2 '\\pi/2' pi 'pi'\n"
+"# or you can use\n#list v -pi -pi/2 0 0.886 pi/2 pi:xtick v '-\\pi\\n-\\pi/2\\n{}0\\n{}x^*\\n\\pi/2\\n\\pi'\n"
+"axis:grid:fplot '2*cos(x^2)^2' 'r2'\n\n"
+"subplot 3 3 8:title 'Time ticks'\nxrange 0 3e5:ticktime 'x':axis";
+void smgl_ticks(mglGraph *gr)
+{
+	gr->SubPlot(3,3,0);	gr->Title("Usual axis");	gr->Axis();
+	gr->SubPlot(3,3,1);	gr->Title("Too big/small range");
+	gr->SetRanges(-1000,1000,0,0.001);	gr->Axis();
+	gr->SubPlot(3,3,2);	gr->Title("LaTeX-like labels");
+	gr->Axis("F!");
+	gr->SubPlot(3,3,3);	gr->Title("Too narrow range");
+	gr->SetRanges(100,100.1,10,10.01);	gr->Axis();
+	gr->SubPlot(3,3,4);	gr->Title("No tuning, manual '+'");
+	// for version<2.3 you need first call gr->SetTuneTicks(0);
+	gr->Axis("+!");
+	gr->SubPlot(3,3,5);	gr->Title("Template for ticks");
+	gr->SetTickTempl('x',"xxx:%g");	gr->SetTickTempl('y',"y:%g");
+	gr->Axis();
+	// now switch it off for other plots
+	gr->SetTickTempl('x',"");	gr->SetTickTempl('y',"");
+	gr->SubPlot(3,3,6);	gr->Title("No tuning, higher precision");
+	gr->Axis("!4");
+	gr->SubPlot(3,3,7);	gr->Title("Manual ticks");	gr->SetRanges(-M_PI,M_PI, 0, 2);
+	gr->SetTicks('x',M_PI,0,0,"\\pi");	gr->AddTick('x',0.886,"x^*");
+	// alternatively you can use following lines
+	//double val[]={-M_PI, -M_PI/2, 0, 0.886, M_PI/2, M_PI};
+	//gr->SetTicksVal('x', mglData(6,val), "-\\pi\n-\\pi/2\n0\nx^*\n\\pi/2\n\\pi");
+	gr->Axis();	gr->Grid();	gr->FPlot("2*cos(x^2)^2", "r2");
+	gr->SubPlot(3,3,8);	gr->Title("Time ticks");	gr->SetRange('x',0,3e5);
+	gr->SetTicksTime('x',0);	gr->Axis();
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_box="subplot 2 2 0:title 'Box (default)':rotate 50 60:box\n"
+"subplot 2 2 1:title 'colored':rotate 50 60:box 'r'\n"
+"subplot 2 2 2:title 'with faces':rotate 50 60:box '@'\n"
+"subplot 2 2 3:title 'both':rotate 50 60:box '@cm'";
+void smgl_box(mglGraph *gr)
+{
+	gr->SubPlot(2,2,0);	gr->Title("Box (default)");	gr->Rotate(50,60);	gr->Box();
+	gr->SubPlot(2,2,1);	gr->Title("colored");		gr->Rotate(50,60);	gr->Box("r");
+	gr->SubPlot(2,2,2);	gr->Title("with faces");	gr->Rotate(50,60);	gr->Box("@");
+	gr->SubPlot(2,2,3);	gr->Title("both");	gr->Rotate(50,60);	gr->Box("@cm");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_loglog="subplot 2 2 0 '<_':title 'Semi-log axis':ranges 0.01 100 -1 1:axis 'lg(x)' '' ''\n"
+"axis:grid 'xy' 'g':fplot 'sin(1/x)':xlabel 'x' 0:ylabel 'y = sin 1/x' 0\n"
+"subplot 2 2 1 '<_':title 'Log-log axis':ranges 0.01 100 0.1 100:axis 'lg(x)' 'lg(y)' ''\n"
+"axis:grid '!' 'h=':grid:fplot 'sqrt(1+x^2)'\nxlabel 'x' 0:ylabel 'y = \\sqrt{1+x^2}' 0\n"
+"subplot 2 2 2 '<_':title 'Minus-log axis':ranges -100 -0.01 -100 -0.1:axis '-lg(-x)' '-lg(-y)' ''\n"
+"axis:fplot '-sqrt(1+x^2)':xlabel 'x' 0:ylabel 'y = -\\sqrt{1+x^2}' 0\n"
+"subplot 2 2 3 '<_':title 'Log-ticks':ranges 0.01 100 0 100:axis 'sqrt(x)' '' ''\n"
+"axis:fplot 'x':xlabel 'x' 1:ylabel 'y = x' 0";
+void smgl_loglog(mglGraph *gr)	// log-log axis
+{
+	gr->SubPlot(2,2,0,"<_");	gr->Title("Semi-log axis");	gr->SetRanges(0.01,100,-1,1);	gr->SetFunc("lg(x)","");
+	gr->Axis();	gr->Grid("xy","g");	gr->FPlot("sin(1/x)");	gr->Label('x',"x",0); gr->Label('y', "y = sin 1/x",0);
+	gr->SubPlot(2,2,1,"<_");	gr->Title("Log-log axis");	gr->SetRanges(0.01,100,0.1,100);	gr->SetFunc("lg(x)","lg(y)");
+	gr->Axis();	gr->Grid("!","h=");	gr->Grid();	gr->FPlot("sqrt(1+x^2)");	gr->Label('x',"x",0); gr->Label('y', "y = \\sqrt{1+x^2}",0);
+	gr->SubPlot(2,2,2,"<_");	gr->Title("Minus-log axis");	gr->SetRanges(-100,-0.01,-100,-0.1);	gr->SetFunc("-lg(-x)","-lg(-y)");
+	gr->Axis();	gr->FPlot("-sqrt(1+x^2)");	gr->Label('x',"x",0); gr->Label('y', "y = -\\sqrt{1+x^2}",0);
+	gr->SubPlot(2,2,3,"<_");	gr->Title("Log-ticks");	gr->SetRanges(0.1,100,0,100);	gr->SetFunc("sqrt(x)","");
+	gr->Axis();	gr->FPlot("x");	gr->Label('x',"x",1); gr->Label('y', "y = x",0);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_venn="list x -0.3 0 0.3:list y 0.3 -0.3 0.3:list e 0.7 0.7 0.7\n"
+"subplot 1 1 0:title 'Venn-like diagram'\ntransptype 1:alpha on:error x y e e '!rgb@#o';alpha 0.1";
+void smgl_venn(mglGraph *gr)
+{
+	double xx[3]={-0.3,0,0.3}, yy[3]={0.3,-0.3,0.3}, ee[3]={0.7,0.7,0.7};
+	mglData x(3,xx), y(3,yy), e(3,ee);
+	gr->SubPlot(1,1,0);	gr->Title("Venn-like diagram");
+	gr->SetTranspType(1);	gr->Alpha(true);	gr->Error(x,y,e,e,"!rgb@#o","alpha 0.1");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_stereo="call 'prepare2d'\nlight on\nsubplot 2 1 0:rotate 50 60+1:box:surf a\nsubplot 2 1 1:rotate 50 60-1:box:surf a";
+void smgl_stereo(mglGraph *gr)
+{
+	mglData a;	mgls_prepare2d(&a);
+	gr->Light(true);
+	gr->SubPlot(2,1,0);	gr->Rotate(50,60+1);
+	gr->Box();	gr->Surf(a);
+	gr->SubPlot(2,1,1);	gr->Rotate(50,60-1);
+	gr->Box();	gr->Surf(a);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_hist="new x 10000 '2*rnd-1':new y 10000 '2*rnd-1':copy z exp(-6*(x^2+y^2))\n"
+"hist xx x z:norm xx 0 1:hist yy y z:norm yy 0 1\nmultiplot 3 3 3 2 2 '':ranges -1 1 -1 1 0 1:box:dots x y z 'wyrRk'\n"
+"multiplot 3 3 0 2 1 '':ranges -1 1 0 1:box:bars xx\nmultiplot 3 3 5 1 2 '':ranges 0 1 -1 1:box:barh yy\n"
+"subplot 3 3 2:text 0.5 0.5 'Hist and\\n{}MultiPlot\\n{}sample' 'a' -3";
+void smgl_hist(mglGraph *gr)
+{
+	mglData x(10000), y(10000), z(10000);	gr->Fill(x,"2*rnd-1");	gr->Fill(y,"2*rnd-1");	gr->Fill(z,"exp(-6*(v^2+w^2))",x,y);
+	mglData xx=gr->Hist(x,z), yy=gr->Hist(y,z);	xx.Norm(0,1);	yy.Norm(0,1);
+	gr->MultiPlot(3,3,3,2,2,"");	gr->SetRanges(-1,1,-1,1,0,1);	gr->Box();	gr->Dots(x,y,z,"wyrRk");
+	gr->MultiPlot(3,3,0,2,1,"");	gr->SetRanges(-1,1,0,1);	gr->Box();	gr->Bars(xx);
+	gr->MultiPlot(3,3,5,1,2,"");	gr->SetRanges(0,1,-1,1);	gr->Box();	gr->Barh(yy);
+	gr->SubPlot(3,3,2);		gr->Puts(mglPoint(0.5,0.5),"Hist and\nMultiPlot\nsample","a",-3);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_primitives="subplot 2 2 0 '':title 'Line, Curve, Rhomb, Ellipse' '' -1.5\n"
+"line -1 -1 -0.5 1 'qAI'\ncurve -0.6 -1 1 1 0 1 1 1 'rA'\nball 0 -0.5 '*':ball 1 -0.1 '*'\n"
+"rhomb 0 0.4 1 0.9 0.2 'b#'\nrhomb 0 0 1 0.4 0.2 'cg@'\n"
+"ellipse 0 -0.5 1 -0.1 0.2 'u#'\nellipse 0 -1 1 -0.6 0.2 'm@'\n\n"
+"light on\nsubplot 2 2 1:title 'Face[xyz]':rotate 50 60:box\n"
+"facex 1 0 -1 1 1 'r':facey -1 -1 -1 1 1 'g':facez 1 -1 -1 -1 1 'b'\n"
+"face -1 -1 1 -1 1 1 1 -1 0 1 1 1 'bmgr'\n\n"
+"subplot 2 2 3 '':title 'Cone'\n"
+"cone -0.7 -0.3 0 -0.7 0.7 0.5 0.2 0.1 'b':text -0.7 -0.7 'no edges\\n(default)'\n"
+"cone 0 -0.3 0 0 0.7 0.5 0.2 0.1 'g@':text 0 -0.7 'with edges\\n('\\@' style)'\n"
+"cone 0.7 -0.3 0 0.7 0.7 0.5 0.2 0.1 'ry':text 0.7 -0.7 '\"arrow\" with\\n{}gradient'\n\n"
+"subplot 2 2 2 '':title 'Sphere and Drop'\nline -0.9 0 1 0.9 0 1\n"
+"text -0.9 0.4 'sh=0':drop -0.9 0 0 1 0.5 'r' 0:ball -0.9 0 1 'k'\n"
+"text -0.3 0.6 'sh=0.33':drop -0.3 0 0 1 0.5 'r' 0.33:ball -0.3 0 1 'k'\n"
+"text 0.3 0.8 'sh=0.67':drop 0.3 0 0 1 0.5 'r' 0.67:ball 0.3 0 1 'k'\n"
+"text 0.9 1. 'sh=1':drop 0.9 0 0 1 0.5 'r' 1:ball 0.9 0 1 'k'\n\n"
+"text -0.9 -1.1 'asp=0.33':drop -0.9 -0.7 0 1 0.5 'b' 0 0.33\n"
+"text -0.3 -1.1 'asp=0.67':drop -0.3 -0.7 0 1 0.5 'b' 0 0.67\n"
+"text 0.3 -1.1 'asp=1':drop 0.3 -0.7 0 1 0.5 'b' 0 1\n"
+"text 0.9 -1.1 'asp=1.5':drop 0.9 -0.7 0 1 0.5 'b' 0 1.5";
+void smgl_primitives(mglGraph *gr)	// flag #
+{
+	gr->SubPlot(2,2,0,"");	gr->Title("Line, Curve, Rhomb, Ellipse","",-1.5);
+	gr->Line(mglPoint(-1,-1),mglPoint(-0.5,1),"qAI");
+	gr->Curve(mglPoint(-0.6,-1),mglPoint(1,1),mglPoint(0,1),mglPoint(1,1),"rA");
+	gr->Rhomb(mglPoint(0,0.4),mglPoint(1,0.9),0.2,"b#");
+	gr->Rhomb(mglPoint(0,0),mglPoint(1,0.4),0.2,"cg@");
+	gr->Ellipse(mglPoint(0,-0.5),mglPoint(1,-0.1),0.2,"u#");
+	gr->Ellipse(mglPoint(0,-1),mglPoint(1,-0.6),0.2,"m@");
+	gr->Mark(mglPoint(0,-0.5),"*");	gr->Mark(mglPoint(1,-0.1),"*");
+
+	gr->Light(true);
+	gr->SubPlot(2,2,1);	gr->Title("Face[xyz]");	gr->Rotate(50,60);	gr->Box();
+	gr->FaceX(mglPoint(1,0,-1),1,1,"r");
+	gr->FaceY(mglPoint(-1,-1,-1),1,1,"g");
+	gr->FaceZ(mglPoint(1,-1,-1),-1,1,"b");
+	gr->Face(mglPoint(-1,-1,1),mglPoint(-1,1,1),mglPoint(1,-1,0),mglPoint(1,1,1),"bmgr");
+
+	gr->SubPlot(2,2,3,"");	gr->Title("Cone");
+	gr->Cone(mglPoint(-0.7,-0.3),mglPoint(-0.7,0.7,0.5),0.2,0.1,"b");
+	gr->Puts(mglPoint(-0.7,-0.7),"no edges\n(default)");
+	gr->Cone(mglPoint(0,-0.3),mglPoint(0,0.7,0.5),0.2,0.1,"g@");
+	gr->Puts(mglPoint(0,-0.7),"with edges\n('\\@' style)");
+	gr->Cone(mglPoint(0.7,-0.3),mglPoint(0.7,0.7,0.5),0.2,0,"ry");
+	gr->Puts(mglPoint(0.7,-0.7),"'arrow' with\ngradient");
+
+	gr->SubPlot(2,2,2,"");	gr->Title("Sphere and Drop");	gr->Alpha(false);
+	gr->Puts(mglPoint(-0.9,0.4),"sh=0");		gr->Ball(mglPoint(-0.9,0,1),'k');
+	gr->Drop(mglPoint(-0.9,0),mglPoint(0,1),0.5,"r",0);
+	gr->Puts(mglPoint(-0.3,0.6),"sh=0.33");	gr->Ball(mglPoint(-0.3,0,1),'k');
+	gr->Drop(mglPoint(-0.3,0),mglPoint(0,1),0.5,"r",0.33);
+	gr->Puts(mglPoint(0.3,0.8),"sh=0.67");		gr->Ball(mglPoint(0.3,0,1),'k');
+	gr->Drop(mglPoint(0.3,0),mglPoint(0,1),0.5,"r",0.67);
+	gr->Puts(mglPoint(0.9,1),"sh=1");			gr->Ball(mglPoint(0.9,0,1),'k');
+	gr->Drop(mglPoint(0.9,0),mglPoint(0,1),0.5,"r",1);
+	gr->Line(mglPoint(-0.9,0,1),mglPoint(0.9,0,1),"b");
+
+	gr->Puts(mglPoint(-0.9,-1.1),"asp=0.33");
+	gr->Drop(mglPoint(-0.9,-0.7),mglPoint(0,1),0.5,"b",0,0.33);
+	gr->Puts(mglPoint(-0.3,-1.1),"asp=0.67");
+	gr->Drop(mglPoint(-0.3,-0.7),mglPoint(0,1),0.5,"b",0,0.67);
+	gr->Puts(mglPoint(0.3,-1.1),"asp=1");
+	gr->Drop(mglPoint(0.3,-0.7),mglPoint(0,1),0.5,"b",0,1);
+	gr->Puts(mglPoint(0.9,-1.1),"asp=1.5");
+	gr->Drop(mglPoint(0.9,-0.7),mglPoint(0,1),0.5,"b",0,1.5);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_table="new ys 10 3 '0.8*sin(pi*(x+y/4+1.25))+0.2*rnd'\n"
+"subplot 2 2 0:title 'Table sample':box\ntable ys 'y_1\\n{}y_2\\n{}y_3'\n\n"
+"subplot 2 2 1:title 'no borders, colored'\ntable ys 'y_1\\n{}y_2\\n{}y_3' 'r|'\n\n"
+"subplot 2 2 2:title 'no font decrease'\ntable ys 'y_1\\n{}y_2\\n{}y_3' '#'\n\n"
+"subplot 2 2 3:title 'manual width and position':box\n"
+"table 0.5 0.95 ys 'y_1\\n{}y_2\\n{}y_3' '#';value 0.7";
+void smgl_table(mglGraph *gr)
+{
+	mglData ys(10,3);	ys.Modify("0.8*sin(pi*(2*x+y/2))+0.2*rnd");
+	if(big!=3)	{	gr->SubPlot(2,2,0);	gr->Title("Table plot");	}
+	gr->Table(ys,"y_1\ny_2\ny_3");	gr->Box();
+	if(big==3)	return;
+	gr->SubPlot(2,2,1);	gr->Title("no borders, colored");
+	gr->Table(ys,"y_1\ny_2\ny_3","r|");
+	gr->SubPlot(2,2,2);	gr->Title("no font decrease");
+	gr->Table(ys,"y_1\ny_2\ny_3","#");
+	gr->SubPlot(2,2,3);	gr->Title("manual width, position");
+	gr->Table(0.5, 0.95, ys,"y_1\ny_2\ny_3","#", "value 0.7");	gr->Box();
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_label="new ys 10 '0.2*rnd-0.8*sin(pi*x)'\n"
+"subplot 1 1 0 '':title 'Label plot':box:plot ys ' *':label ys 'y=%y'";
+void smgl_label(mglGraph *gr)
+{
+	mglData ys(10);	ys.Modify("0.8*sin(pi*2*x)+0.2*rnd");
+	if(big!=3)	{	gr->SubPlot(1,1,0,"");	gr->Title("Label plot");	}
+	gr->Box();	gr->Plot(ys," *");	gr->Label(ys,"y=%y");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_colorbar="call 'prepare2d'\nnew v 9 'x'\nsubplot 2 2 0:title 'Colorbar out of box':box\n"
+"colorbar '<':colorbar '>':colorbar '_':colorbar '^'\n"
+"subplot 2 2 1:title 'Colorbar near box':box\n"
+"colorbar '<I':colorbar '>I':colorbar '_I':colorbar '^I'\n"
+"subplot 2 2 2:title 'manual colors':box:contd v a\n"
+"colorbar v '<':colorbar v '>':colorbar v '_':colorbar v '^'\n"
+"subplot 2 2 3:title '':text -0.5 1.55 'Color positions' ':C' -2\n"
+"colorbar 'bwr>' 0.25 0:text -0.9 1.2 'Default'\n"
+"colorbar 'b{w,0.3}r>' 0.5 0:text -0.1 1.2 'Manual'\ncrange 0.01 1e3\n"
+"colorbar '>' 0.75 0:text 0.65 1.2 'Normal scale':colorbar '>':text 1.35 1.2 'Log scale'";
+void smgl_colorbar(mglGraph *gr)
+{
+	gr->SubPlot(2,2,0);	gr->Title("Colorbar out of box");	gr->Box();
+	gr->Colorbar("<");	gr->Colorbar(">");	gr->Colorbar("_");	gr->Colorbar("^");
+	gr->SubPlot(2,2,1);	gr->Title("Colorbar near box");		gr->Box();
+	gr->Colorbar("<I");	gr->Colorbar(">I");	gr->Colorbar("_I");	gr->Colorbar("^I");
+	gr->SubPlot(2,2,2);	gr->Title("manual colors");
+	mglData a,v;	mgls_prepare2d(&a,0,&v);
+	gr->Box();	gr->ContD(v,a);
+	gr->Colorbar(v,"<");	gr->Colorbar(v,">");	gr->Colorbar(v,"_");	gr->Colorbar(v,"^");
+
+	gr->SubPlot(2,2,3);	gr->Title(" ");
+	gr->Puts(mglPoint(-0.5,1.55),"Color positions",":C",-2);
+	gr->Colorbar("bwr>",0.25,0);	gr->Puts(mglPoint(-0.9,1.2),"Default");
+	gr->Colorbar("b{w,0.3}r>",0.5,0);	gr->Puts(mglPoint(-0.1,1.2),"Manual");
+
+	gr->Puts(mglPoint(1,1.55),"log-scale",":C",-2);
+	gr->SetRange('c',0.01,1e3);
+	gr->Colorbar(">",0.75,0);	gr->Puts(mglPoint(0.65,1.2),"Normal scale");
+	gr->SetFunc("","","","lg(c)");
+	gr->Colorbar(">");		gr->Puts(mglPoint(1.35,1.2),"Log scale");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_legend="addlegend 'sin(\\pi {x^2})' 'b':addlegend 'sin(\\pi x)' 'g*'\n"
+"addlegend 'sin(\\pi \\sqrt{x})' 'rd':addlegend 'jsut text' ' ':addlegend 'no indent for this' ''\n"
+"subplot 2 2 0 '':title 'Legend (default)':box:legend\n"
+"legend 3 'A#':text 0.75 0.65 'Absolute position' 'A'\n"
+"subplot 2 2 2 '':title 'coloring':box:legend 0 'r#':legend 1 'Wb#':legend 2 'ygr#'\n"
+"subplot 2 2 3 '':title 'manual position':box\n"
+"legend 0.5 1:text 0.5 0.55 'at x=0.5, y=1' 'a'\n"
+"legend 1 '#-':text 0.75 0.25 'Horizontal legend' 'a'";
+void smgl_legend(mglGraph *gr)
+{
+	gr->AddLegend("sin(\\pi {x^2})","b");
+	gr->AddLegend("sin(\\pi x)","g*");
+	gr->AddLegend("sin(\\pi \\sqrt{x})","rd");
+	gr->AddLegend("just text"," ");
+	gr->AddLegend("no indent for this","");
+	if(big!=3)	{gr->SubPlot(2,2,0,"");	gr->Title("Legend (default)");}
+	gr->Box();	gr->Legend();
+	if(big==3)	return;
+	gr->Legend(3,"A#");
+	gr->Puts(mglPoint(0.75,0.65),"Absolute position","A");
+	gr->SubPlot(2,2,2,"");	gr->Title("coloring");	gr->Box();
+	gr->Legend(0,"r#");	gr->Legend(1,"Wb#");	gr->Legend(2,"ygr#");
+	gr->SubPlot(2,2,3,"");	gr->Title("manual position");	gr->Box();
+	gr->Legend(0.5,1);
+	gr->Puts(mglPoint(0.5,0.55),"at x=0.5, y=1","a");
+	gr->Legend(1,"#-");
+	gr->Puts(mglPoint(0.75,0.25),"Horizontal legend","a");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_dat_diff="ranges 0 1 0 1 0 1:new a 30 40 'x*y'\n"
+"subplot 2 2 0:title 'a(x,y)':rotate 60 40:surf a:box\n"
+"subplot 2 2 1:title 'da/dx':rotate 60 40:diff a 'x':surf a:box\n"
+"subplot 2 2 2:title '\\int da/dx dxdy':rotate 60 40:integrate a 'xy':surf a:box\n"
+"subplot 2 2 3:title '\\int {d^2}a/dxdy dx':rotate 60 40:diff2 a 'y':surf a:box";
+void smgl_dat_diff(mglGraph *gr)	// differentiate
+{
+	gr->SetRanges(0,1,0,1,0,1);
+	mglData a(30,40);	a.Modify("x*y");
+	gr->SubPlot(2,2,0);	gr->Title("a(x,y)");	gr->Rotate(60,40);
+	gr->Surf(a);		gr->Box();
+	gr->SubPlot(2,2,1);	gr->Title("da/dx");		gr->Rotate(60,40);
+	a.Diff("x");		gr->Surf(a);	gr->Box();
+	gr->SubPlot(2,2,2);	gr->Title("\\int da/dx dxdy");	gr->Rotate(60,40);
+	a.Integral("xy");	gr->Surf(a);	gr->Box();
+	gr->SubPlot(2,2,3);	gr->Title("\\int {d^2}a/dxdy dx");	gr->Rotate(60,40);
+	a.Diff2("y");	gr->Surf(a);	gr->Box();
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_dat_extra="subplot 2 2 0 '':title 'Envelop sample':new d1 1000 'exp(-8*x^2)*sin(10*pi*x)'\n"
+"axis:plot d1 'b':envelop d1 'x':plot d1 'r'\n"
+"subplot 2 2 1 '':title 'Smooth sample':ranges 0 1 0 1\nnew y0 30 '0.4*sin(pi*x) + 0.3*cos(1.5*pi*x) - 0.4*sin(2*pi*x)+0.5*rnd'\n"
+"copy y1 y0:smooth y1 'x3':plot y1 'r';legend '\"3\" style'\ncopy y2 y0:smooth y2 'x5':plot y2 'g';legend '\"5\" style'\n"
+"copy y3 y0:smooth y3 'x':plot y3 'b';legend 'default'\nplot y0 '{m7}:s';legend 'none'\nlegend:box\n"
+"subplot 2 2 2:title 'Sew sample':rotate 50 60:light on:alpha on\nnew d2 100 100 'mod((y^2-(1-x)^2)/2,0.1)'\n"
+"box:surf d2 'b':sew d2 'xy' 0.1:surf d2 'r'\n"
+"subplot 2 2 3:title 'Resize sample (interpolation)'\nnew x0 10 'rnd':new v0 10 'rnd'\n"
+"resize x1 x0 100:resize v1 v0 100\nplot x0 v0 'b+ ':plot x1 v1 'r-':label x0 v0 '%n'";
+void smgl_dat_extra(mglGraph *gr)	// differentiate
+{
+	gr->SubPlot(2,2,0,"");	gr->Title("Envelop sample");
+	mglData d1(1000);	gr->Fill(d1,"exp(-8*x^2)*sin(10*pi*x)");
+	gr->Axis();			gr->Plot(d1, "b");
+	d1.Envelop('x');	gr->Plot(d1, "r");
+
+	gr->SubPlot(2,2,1,"");	gr->Title("Smooth sample");
+	mglData y0(30),y1,y2,y3;
+	gr->SetRanges(0,1,0,1);
+	gr->Fill(y0, "0.4*sin(pi*x) + 0.3*cos(1.5*pi*x) - 0.4*sin(2*pi*x)+0.5*rnd");
+
+	y1=y0;	y1.Smooth("x3");
+	y2=y0;	y2.Smooth("x5");
+	y3=y0;	y3.Smooth("x");
+
+	gr->Plot(y0,"{m7}:s", "legend 'none'");	//gr->AddLegend("none","k");
+	gr->Plot(y1,"r", "legend ''3' style'");
+	gr->Plot(y2,"g", "legend ''5' style'");
+	gr->Plot(y3,"b", "legend 'default'");
+	gr->Legend();		gr->Box();
+
+	gr->SubPlot(2,2,2);		gr->Title("Sew sample");
+	mglData d2(100, 100);	gr->Fill(d2, "mod((y^2-(1-x)^2)/2,0.1)");
+	gr->Rotate(50, 60);	gr->Light(true);	gr->Alpha(true);
+	gr->Box();			gr->Surf(d2, "b");
+	d2.Sew("xy", 0.1);	gr->Surf(d2, "r");
+
+	gr->SubPlot(2,2,3);		gr->Title("Resize sample (interpolation)");
+	mglData x0(10), v0(10), x1, v1;
+	gr->Fill(x0,"rnd");		gr->Fill(v0,"rnd");
+	x1 = x0.Resize(100);	v1 = v0.Resize(100);
+	gr->Plot(x0,v0,"b+ ");	gr->Plot(x1,v1,"r-");
+	gr->Label(x0,v0,"%n");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_ternary="ranges 0 1 0 1 0 1\nnew x 50 '0.25*(1+cos(2*pi*x))'\n"
+"new y 50 '0.25*(1+sin(2*pi*x))'\nnew z 50 'x'\nnew a 20 30 '30*x*y*(1-x-y)^2*(x+y<1)'\n"
+"new rx 10 'rnd':new ry 10:fill ry '(1-v)*rnd' rx\nlight on\n\n"
+"subplot 2 2 0:title 'Ordinary axis 3D':rotate 50 60\nbox:axis:grid\n"
+"plot x y z 'r2':surf a '#'\nxlabel 'B':ylabel 'C':zlabel 'Z'\n\n"
+"subplot 2 2 1:title 'Ternary axis (x+y+t=1)':ternary 1\nbox:axis:grid 'xyz' 'B;'\n"
+"plot x y 'r2':plot rx ry 'q^ ':cont a:line 0.5 0 0 0.75 'g2'\nxlabel 'B':ylabel 'C':tlabel 'A'\n\n"
+"subplot 2 2 2:title 'Quaternary axis 3D':rotate 50 60:ternary 2\nbox:axis:grid 'xyz' 'B;'\n"
+"plot x y z 'r2':surf a '#'\nxlabel 'B':ylabel 'C':tlabel 'A':zlabel 'D'\n\n"
+"subplot 2 2 3:title 'Ternary axis 3D':rotate 50 60:ternary 1\nbox:axis:grid 'xyz' 'B;'\n"
+"plot x y z 'r2':surf a '#'\nxlabel 'B':ylabel 'C':tlabel 'A':zlabel 'Z'";
+void smgl_ternary(mglGraph *gr)	// flag #
+{
+	gr->SetRanges(0,1,0,1,0,1);
+	mglData x(50),y(50),z(50),rx(10),ry(10), a(20,30);
+	a.Modify("30*x*y*(1-x-y)^2*(x+y<1)");
+	x.Modify("0.25*(1+cos(2*pi*x))");
+	y.Modify("0.25*(1+sin(2*pi*x))");
+	rx.Modify("rnd"); ry.Modify("(1-v)*rnd",rx);
+	z.Modify("x");
+
+	gr->SubPlot(2,2,0);	gr->Title("Ordinary axis 3D");
+	gr->Rotate(50,60);		gr->Light(true);
+	gr->Plot(x,y,z,"r2");	gr->Surf(a,"BbcyrR#");
+	gr->Axis(); gr->Grid();	gr->Box();
+	gr->Label('x',"B",1);	gr->Label('y',"C",1);	gr->Label('z',"Z",1);
+
+	gr->SubPlot(2,2,1);	gr->Title("Ternary axis (x+y+t=1)");
+	gr->Ternary(1);
+	gr->Plot(x,y,"r2");	gr->Plot(rx,ry,"q^ ");	gr->Cont(a);
+	gr->Line(mglPoint(0.5,0), mglPoint(0,0.75), "g2");
+	gr->Axis(); gr->Grid("xyz","B;");
+	gr->Label('x',"B");	gr->Label('y',"C");	gr->Label('t',"A");
+
+	gr->SubPlot(2,2,2);	gr->Title("Quaternary axis 3D");
+	gr->Rotate(50,60);		gr->Light(true);
+	gr->Ternary(2);
+	gr->Plot(x,y,z,"r2");	gr->Surf(a,"BbcyrR#");
+	gr->Axis(); gr->Grid();	gr->Box();
+	gr->Label('t',"A",1);	gr->Label('x',"B",1);
+	gr->Label('y',"C",1);	gr->Label('z',"D",1);
+
+	gr->SubPlot(2,2,3);	gr->Title("Ternary axis 3D");
+	gr->Rotate(50,60);		gr->Light(true);
+	gr->Ternary(1);
+	gr->Plot(x,y,z,"r2");	gr->Surf(a,"BbcyrR#");
+	gr->Axis(); gr->Grid();	gr->Box();
+	gr->Label('t',"A",1);	gr->Label('x',"B",1);
+	gr->Label('y',"C",1);	gr->Label('z',"Z",1);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_projection="ranges 0 1 0 1 0 1\nnew x 50 '0.25*(1+cos(2*pi*x))'\n"
+"new y 50 '0.25*(1+sin(2*pi*x))'\nnew z 50 'x'\nnew a 20 30 '30*x*y*(1-x-y)^2*(x+y<1)'\n"
+"new rx 10 'rnd':new ry 10:fill ry '(1-v)*rnd' rx\nlight on\n\n"
+"title 'Projection sample':ternary 4:rotate 50 60\nbox:axis:grid\n"
+"plot x y z 'r2':surf a '#'\nxlabel 'X':ylabel 'Y':zlabel 'Z'";
+void smgl_projection(mglGraph *gr)	// flag #
+{
+	gr->SetRanges(0,1,0,1,0,1);
+	mglData x(50),y(50),z(50),rx(10),ry(10), a(20,30);
+	a.Modify("30*x*y*(1-x-y)^2*(x+y<1)");
+	x.Modify("0.25*(1+cos(2*pi*x))");
+	y.Modify("0.25*(1+sin(2*pi*x))");
+	rx.Modify("rnd"); ry.Modify("(1-v)*rnd",rx);
+	z.Modify("x");
+
+	if(big!=3)	gr->Title("Projection sample");
+	gr->Ternary(4);
+	gr->Rotate(50,60);		gr->Light(true);
+	gr->Plot(x,y,z,"r2");	gr->Surf(a,"#");
+	gr->Axis(); gr->Grid();	gr->Box();
+	gr->Label('x',"X",1);	gr->Label('y',"Y",1);	gr->Label('z',"Z",1);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_projection5="ranges 0 1 0 1 0 1\nnew x 50 '0.25*(1+cos(2*pi*x))'\n"
+"new y 50 '0.25*(1+sin(2*pi*x))'\nnew z 50 'x'\nnew a 20 30 '30*x*y*(1-x-y)^2*(x+y<1)'\n"
+"new rx 10 'rnd':new ry 10:fill ry '(1-v)*rnd' rx\nlight on\n\n"
+"title 'Projection sample (ternary)':ternary 5:rotate 50 60\nbox:axis:grid\n"
+"plot x y z 'r2':surf a '#'\nxlabel 'X':ylabel 'Y':zlabel 'Z'";
+void smgl_projection5(mglGraph *gr)	// flag #
+{
+	gr->SetRanges(0,1,0,1,0,1);
+	mglData x(50),y(50),z(50),rx(10),ry(10), a(20,30);
+	a.Modify("30*x*y*(1-x-y)^2*(x+y<1)");
+	x.Modify("0.25*(1+cos(2*pi*x))");
+	y.Modify("0.25*(1+sin(2*pi*x))");
+	rx.Modify("rnd"); ry.Modify("(1-v)*rnd",rx);
+	z.Modify("x");
+
+	if(big!=3)	gr->Title("Projection sample (ternary)");
+	gr->Ternary(5);
+	gr->Rotate(50,60);		gr->Light(true);
+	gr->Plot(x,y,z,"r2");	gr->Surf(a,"#");
+	gr->Axis(); gr->Grid();	gr->Box();
+	gr->Label('x',"X",1);	gr->Label('y',"Y",1);	gr->Label('z',"Z",1);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_triplot="list q 0 1 2 3 | 4 5 6 7 | 0 2 4 6 | 1 3 5 7 | 0 4 1 5 | 2 6 3 7\n"
+"list xq -1 1 -1 1 -1 1 -1 1\nlist yq -1 -1 1 1 -1 -1 1 1\nlist zq -1 -1 -1 -1 1 1 1 1\nlight on\n"
+"subplot 2 2 0:title 'QuadPlot sample':rotate 50 60\n"
+"quadplot q xq yq zq 'yr'\nquadplot q xq yq zq '#k'\n"
+"subplot 2 2 2:title 'QuadPlot coloring':rotate 50 60\n"
+"quadplot q xq yq zq yq 'yr'\nquadplot q xq yq zq '#k'\n"
+"list t 0 1 2 | 0 1 3 | 0 2 3 | 1 2 3\n"
+"list xt -1 1 0 0\nlist yt -1 -1 1 0\nlist zt -1 -1 -1 1\n"
+"subplot 2 2 1:title 'TriPlot sample':rotate 50 60\n"
+"triplot t xt yt zt 'b'\ntriplot t xt yt zt '#k'\n"
+"subplot 2 2 3:title 'TriPlot coloring':rotate 50 60\n"
+"triplot t xt yt zt yt 'cb'\ntriplot t xt yt zt '#k'\ntricont t xt yt zt 'B'";
+void smgl_triplot(mglGraph *gr)
+{
+	double q[] = {0,1,2,3, 4,5,6,7, 0,2,4,6, 1,3,5,7, 0,4,1,5, 2,6,3,7};
+	double xc[] = {-1,1,-1,1,-1,1,-1,1}, yc[] = {-1,-1,1,1,-1,-1,1,1}, zc[] = {-1,-1,-1,-1,1,1,1,1};
+	mglData qq(6,4,q), xx(8,xc), yy(8,yc), zz(8,zc);
+	gr->Light(true);	//gr->Alpha(true);
+	gr->SubPlot(2,2,0);	gr->Title("QuadPlot sample");	gr->Rotate(50,60);
+	gr->QuadPlot(qq,xx,yy,zz,"yr");
+	gr->QuadPlot(qq,xx,yy,zz,"k#");
+	gr->SubPlot(2,2,2);	gr->Title("QuadPlot coloring");	gr->Rotate(50,60);
+	gr->QuadPlot(qq,xx,yy,zz,yy,"yr");
+	gr->QuadPlot(qq,xx,yy,zz,"k#");
+
+	double t[] = {0,1,2, 0,1,3, 0,2,3, 1,2,3};
+	double xt[] = {-1,1,0,0}, yt[] = {-1,-1,1,0}, zt[] = {-1,-1,-1,1};
+	mglData tt(4,3,t), uu(4,xt), vv(4,yt), ww(4,zt);
+	gr->SubPlot(2,2,1);	gr->Title("TriPlot sample");	gr->Rotate(50,60);
+	gr->TriPlot(tt,uu,vv,ww,"b");
+	gr->TriPlot(tt,uu,vv,ww,"k#");
+	gr->SubPlot(2,2,3);	gr->Title("TriPlot coloring");	gr->Rotate(50,60);
+	gr->TriPlot(tt,uu,vv,ww,vv,"cb");
+	gr->TriPlot(tt,uu,vv,ww,"k#");
+	gr->TriCont(tt,uu,vv,ww,"B");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_dots="new t 2000 'pi*(rnd-0.5)':new f 2000 '2*pi*rnd'\n"
+"copy x 0.9*cos(t)*cos(f):copy y 0.9*cos(t)*sin(f):copy z 0.6*sin(t):copy c cos(2*t)\n"
+"subplot 2 2 0:title 'Dots sample':rotate 50 60\nbox:dots x y z\nalpha on\n"
+"subplot 2 2 1:title 'add transparency':rotate 50 60\nbox:dots x y z c\n"
+"subplot 2 2 2:title 'add colorings':rotate 50 60\nbox:dots x y z x c\n"
+"subplot 2 2 3:title 'Only coloring':rotate 50 60\nbox:tens x y z x ' .'";
+void smgl_dots(mglGraph *gr)
+{
+	int i, n=1000;
+	mglData x(n),y(n),z(n),c(n);
+	for(i=0;i<n;i++)
+	{
+		double t=M_PI*(mgl_rnd()-0.5), f=2*M_PI*mgl_rnd();
+		x.a[i] = 0.9*cos(t)*cos(f);
+		y.a[i] = 0.9*cos(t)*sin(f);
+		z.a[i] = 0.6*sin(t);
+		c.a[i] = cos(2*t);
+	}
+	if(big!=3)	{	gr->SubPlot(2,2,0);	gr->Title("Dots sample");	}
+	gr->Rotate(50,60);	gr->Box();	gr->Dots(x,y,z);
+	if(big==3)	return;
+	gr->Alpha(true);
+	gr->SubPlot(2,2,1);	gr->Title("add transparency");		gr->Rotate(50,60);	gr->Box();	gr->Dots(x,y,z,c);
+	gr->SubPlot(2,2,2);	gr->Title("add coloring");	gr->Rotate(50,60);	gr->Box();	gr->Dots(x,y,z,x,c);
+	gr->SubPlot(2,2,3);	gr->Title("Only coloring");		gr->Rotate(50,60);	gr->Box();	gr->Tens(x,y,z,x," .");
+}
+//-----------------------------------------------------------------------------
+/*void smgl_surf3_rgbd(mglGraph *gr)
+{
+	mglData c;	mgls_prepare3d(&c);
+	gr->Rotate(40,60);	gr->VertexColor(true);
+	gr->Box();	gr->Surf3(c,"bgrd");
+}*/
+//-----------------------------------------------------------------------------
+const char *mmgl_mirror="new a 31 41 '-pi*x*exp(-(y+1)^2-4*x^2)'\n"
+"subplot 2 2 0:title 'Options for coordinates':alpha on:light on:rotate 40 60:box\n"
+"surf a 'r';yrange 0 1:surf a 'b';yrange 0 -1\n"
+"subplot 2 2 1:title 'Option \"meshnum\"':rotate 40 60:box\n"
+"mesh a 'r'; yrange 0 1:mesh a 'b';yrange 0 -1; meshnum 5\n"
+"subplot 2 2 2:title 'Option \"alpha\"':rotate 40 60:box\n"
+"surf a 'r';yrange 0 1; alpha 0.7:surf a 'b';yrange 0 -1; alpha 0.3\n"
+"subplot 2 2 3 '<_':title 'Option \"legend\"'\n"
+"fplot 'x^3' 'r'; legend 'y = x^3':fplot 'cos(pi*x)' 'b'; legend 'y = cos \\pi x'\n"
+"box:axis:legend 2";
+void smgl_mirror(mglGraph *gr)	// flag #
+{
+	mglData a(31,41);
+	gr->Fill(a,"-pi*x*exp(-(y+1)^2-4*x^2)");
+
+	if(big!=3)	{	gr->SubPlot(2,2,0);	gr->Title("Options for coordinates");	}
+	gr->Alpha(true);	gr->Light(true);
+	gr->Rotate(40,60);	gr->Box();
+	gr->Surf(a,"r","yrange 0 1"); gr->Surf(a,"b","yrange 0 -1");
+	if(big==3)	return;
+	gr->SubPlot(2,2,1);	gr->Title("Option 'meshnum'");
+	gr->Rotate(40,60);	gr->Box();
+	gr->Mesh(a,"r","yrange 0 1"); gr->Mesh(a,"b","yrange 0 -1; meshnum 5");
+	gr->SubPlot(2,2,2);	gr->Title("Option 'alpha'");
+	gr->Rotate(40,60);	gr->Box();
+	gr->Surf(a,"r","yrange 0 1; alpha 0.7"); gr->Surf(a,"b","yrange 0 -1; alpha 0.3");
+	gr->SubPlot(2,2,3,"<_");	gr->Title("Option 'legend'");
+	gr->FPlot("x^3","r","legend 'y = x^3'"); gr->FPlot("cos(pi*x)","b","legend 'y = cos \\pi x'");
+	gr->Box();	gr->Axis();	gr->Legend(2,"");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_pulse="subplot 1 1 0 '<_':title 'Pulse sample'\n"
+"new a 100 'exp(-6*x^2)':ranges 0 a.nx-1 0 1\naxis:plot a\n\n"
+"pulse b a 'x'\n\ndefine m a.max\n\nline b(1) 0 b(1) m 'r='\n"
+"line b(1)-b(3)/2 0  b(1)-b(3)/2 m 'm|'\nline b(1)+b(3)/2 0  b(1)+b(3)/2 m 'm|'\n"
+"line 0 0.5*m a.nx-1 0.5*m 'h'\nnew x 100 'x'\nplot b(0)*(1-((x-b(1))/b(2))^2) 'g'";
+void smgl_pulse(mglGraph *gr)
+{
+	gr->SubPlot(1,1,0,"<_");
+	if(big!=3)	gr->Title("Pulse sample");
+	mglData a(100);	gr->Fill(a,"exp(-6*x^2)");
+	gr->SetRanges(0, a.nx-1, 0, 1);
+	gr->Axis();	gr->Plot(a);
+	mglData b(a.Pulse('x'));
+	double m = b[0];
+	gr->Line(mglPoint(b[1],0), mglPoint(b[1],m),"r=");
+	gr->Line(mglPoint(b[1]-b[3]/2,0), mglPoint(b[1]-b[3]/2,m),"m|");
+	gr->Line(mglPoint(b[1]+b[3]/2,0), mglPoint(b[1]+b[3]/2,m),"m|");
+	gr->Line(mglPoint(0,m/2), mglPoint(a.nx-1,m/2),"h");
+	char func[128];	sprintf(func,"%g*(1-((x-%g)/%g)^2)",b[0],b[1],b[2]);
+	gr->FPlot(func,"g");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_scanfile="subplot 1 1 0 '<_':title 'Save and scanfile sample'\n"
+"list a 1 -1 0\nsave 'This is test: 0 -> ',a(0),' q' 'test.txt' 'w'\n"
+"save 'This is test: 1 -> ',a(1),' q' 'test.txt'\nsave 'This is test: 2 -> ',a(2),' q' 'test.txt'\n"
+"\nscanfile a 'test.txt' 'This is test: %g -> %g'\nranges a(0) a(1):axis:plot a(0) a(1) 'o'";
+void smgl_scanfile(mglGraph *gr)
+{
+	gr->SubPlot(1,1,0,"<_");
+	if(big!=3)	gr->Title("Save and scanfile sample");
+	FILE *fp=fopen("test.txt","w");
+	fprintf(fp,"This is test: 0 -> 1 q\n");
+	fprintf(fp,"This is test: 1 -> -1 q\n");
+	fprintf(fp,"This is test: 2 -> 0 q\n");
+	fclose(fp);
+
+	mglData a;
+	a.ScanFile("test.txt","This is test: %g -> %g");
+	gr->SetRanges(a.SubData(0), a.SubData(1));
+	gr->Axis();	gr->Plot(a.SubData(0),a.SubData(1),"o");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_pendelta="quality 6\nlist a 0.25 0.5 1 2 4\nfor $0 0 4\n"
+"pendelta a($0)\ndefine $1 0.5*$0-1\nline -1 $1 1 $1 'r'\ntext 0 $1 'delta=',a($0)\nnext";
+void smgl_pendelta(mglGraph *gr)
+{
+	double a[5]={0.25,0.5,1,2,4};
+	gr->SetQuality(6);
+	char buf[64];
+	for(int i=0;i<5;i++)
+	{
+		gr->SetPenDelta(a[i]);
+		gr->Line(mglPoint(-1,0.5*i-1), mglPoint(1,0.5*i-1),"r");
+		sprintf(buf,"delta=%g",a[i]);
+		gr->Puts(mglPoint(0,0.5*i-1),buf);
+	}
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_bifurcation="subplot 1 1 0 '<_':title 'Bifurcation sample'\n"
+"ranges 0 4 0 1:axis\nbifurcation 0.005 'x*y*(1-y)' 'r'";
+void smgl_bifurcation(mglGraph *gr)
+{
+	gr->SubPlot(1,1,0,"<_");
+	if(big!=3)	gr->Title("Bifurcation sample");
+	gr->SetRanges(0,4,0,1);	gr->Axis();
+	gr->Bifurcation(0.005,"x*y*(1-y)","r");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_lamerey="subplot 1 1 0 '<_':title 'Lamerey sample'\n"
+"axis:xlabel '\\i x':ylabel '\\bar{\\i x} = 2 \\i{x}'\nfplot 'x' 'k='\nfplot '2*x' 'b'\n"
+"lamerey 0.00097 '2*x' 'rv~';size 2\nlamerey -0.00097 '2*x' 'rv~';size 2";
+void smgl_lamerey(mglGraph *gr)
+{
+	gr->SubPlot(1,1,0,"<_");
+	if(big!=3)	gr->Title("Lamerey sample");
+	gr->Axis();	gr->Label('x',"\\i x");	gr->Label('y',"\\bar{\\i x} = 2 \\i{x}");
+	gr->FPlot("x","k=");	gr->FPlot("2*x","b");
+	gr->Lamerey( 0.00097,"2*x","rv~");
+	gr->Lamerey(-0.00097,"2*x","rv~");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_pmap="subplot 1 1 0 '<_^':title 'Poincare map sample'\n"
+"ode r 'cos(y)+sin(z);cos(z)+sin(x);cos(x)+sin(y)' 'xyz' [0.1,0,0] 0.1 100\n"
+"rotate 40 60:copy x r(0):copy y r(1):copy z r(2)\nranges x y z\naxis:plot x y z 'b'\n"
+"xlabel '\\i x' 0:ylabel '\\i y' 0:zlabel '\\i z'\n"
+"pmap x y z z 'b#o'\nfsurf '0'";
+void smgl_pmap(mglGraph *gr)
+{
+	gr->SubPlot(1,1,0,"<_^");
+	if(big!=3)	gr->Title("Poincare map sample");
+	mglData ini(3);	ini[0]=0.1;
+	mglData r(mglODE("cos(y)+sin(z);cos(z)+sin(x);cos(x)+sin(y)","xyz",ini,0.1,100));
+	mglData x(r.SubData(0)),y(r.SubData(1)), z(r.SubData(2));
+	gr->Rotate(40,60);	gr->SetRanges(x,y,z);
+	gr->Axis();	gr->FSurf("0");	gr->Plot(x,y,z,"b");
+	gr->Label('x',"\\i x",0);	gr->Label('y',"\\i y",0);	gr->Label('z',"\\i z",0);
+	gr->Pmap(x,y,z,z, "b#o");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_apde="ranges -1 1 0 2 0 2\nnew ar 256 'exp(-2*(x+0.0)^2)'\nnew ai 256\n\n"
+"apde res1 'exp(-x^2-p^2)' ar ai 0.01:transpose res1\npde res2 'exp(-x^2-p^2)' ar ai 0.01\n\n"
+"subplot 1 2 0 '_':title 'Advanced PDE solver'\nranges 0 2 -1 1:crange res1\ndens res1:box\n"
+"axis:xlabel '\\i z':ylabel '\\i x'\n"
+"text -0.5 0.2 'i\\partial_z\\i u = exp(-\\i x^2+\\partial_x^2)[\\i u]' 'y'\n\n"
+"subplot 1 2 1 '_':title 'Simplified PDE solver'\n"
+"dens res2:box\naxis:xlabel '\\i z':ylabel '\\i x'\n"
+"text -0.5 0.2 'i\\partial_z\\i u \\approx\\ exp(-\\i x^2)\\i u+exp(\\partial_x^2)[\\i u]' 'y'";
+void smgl_apde(mglGraph *gr)
+{
+	gr->SetRanges(-1,1,0,2,0,2);
+	mglData ar(256), ai(256);	gr->Fill(ar,"exp(-2*(x+0.0)^2)");
+
+	mglData res1(gr->APDE("exp(-x^2-p^2)",ar,ai,0.01));	res1.Transpose();
+	mglData res2(gr->PDE("exp(-x^2-p^2)",ar,ai,0.01));
+
+	gr->SubPlot(1,2,0,"_");	gr->Title("Advanced PDE solver");
+	gr->SetRanges(0,2,-1,1);	gr->SetRange('c',res1);
+	gr->Dens(res1);	gr->Axis();	gr->Box();
+	gr->Label('x',"\\i z");	gr->Label('y',"\\i x");
+	gr->Puts(mglPoint(-0.5,0.2),"i\\partial_z\\i u = exp(-\\i x^2+\\partial_x^2)[\\i u]","y");
+
+	gr->SubPlot(1,2,1,"_");	gr->Title("Simplified PDE solver");
+	gr->Dens(res2);	gr->Axis();	gr->Box();
+	gr->Label('x',"\\i z");	gr->Label('y',"\\i x");
+	gr->Puts(mglPoint(-0.5,0.2),"i\\partial_z\\i u \\approx\\ exp(-\\i x^2)\\i u+exp(\\partial_x^2)[\\i u]","y");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_ifs2d="list A [0.33,0,0,0.33,0,0,0.2] [0.33,0,0,0.33,0.67,0,0.2] [0.33,0,0,0.33,0.33,0.33,0.2]\\\n\t"
+"[0.33,0,0,0.33,0,0.67,0.2] [0.33,0,0,0.33,0.67,0.67,0.2]\nifs2d fx fy A 100000\n"
+"subplot 1 1 0 '<_':title 'IFS 2d sample'\nranges fx fy:axis\nplot fx fy 'r#o ';size 0.05";
+void smgl_ifs2d(mglGraph *gr)
+{
+	mglData A;
+	A.SetList(35, 0.33,0.,0.,0.33,0.,0.,0.2, 0.33,0.,0.,0.33,0.67,0.,0.2, 0.33,0.,0.,0.33,0.33,0.33,0.2, 0.33,0.,0.,0.33,0.,0.67,0.2, 0.33,0.,0.,0.33,0.67,0.67,0.2);
+	A.Rearrange(7);
+	mglData f(mglIFS2d(A,100000));
+	gr->SubPlot(1,1,0,"<_");
+	if(big!=3)	gr->Title("IFS 2d sample");
+	gr->SetRanges(f.SubData(0), f.SubData(1));
+	gr->Axis();	gr->Plot(f.SubData(0), f.SubData(1),"r#o ","size 0.05");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_ifs3d="list A [0,0,0,0,.18,0,0,0,0,0,0,0,.01] [.85,0,0,0,.85,.1,0,-0.1,0.85,0,1.6,0,.85]\\\n"
+"\t[.2,-.2,0,.2,.2,0,0,0,0.3,0,0.8,0,.07] [-.2,.2,0,.2,.2,0,0,0,0.3,0,0.8,0,.07]\n"
+"ifs3d f A 100000\ntitle 'IFS 3d sample':rotate 50 60\n"
+"ranges f(0) f(1) f(2):axis:box\ndots f(0) f(1) f(2) 'G#o';size 0.05";
+void smgl_ifs3d(mglGraph *gr)
+{
+	mglData A;
+	A.SetList(52, 0.,0.,0.,0.,.18,0.,0.,0.,0.,0.,0.,0.,.01, .85,0.,0.,0.,.85,.1,0.,-0.1,0.85,0.,1.6,0.,.85,
+			.2,-.2,0.,.2,.2,0.,0.,0.,0.3,0.,0.8,0.,.07, -.2,.2,0.,.2,.2,0.,0.,0.,0.3,0.,0.8,0.,.07);
+	A.Rearrange(13);
+	mglData f(mglIFS3d(A,100000));
+	if(big!=3)	gr->Title("IFS 3d sample");
+	gr->SetRanges(f.SubData(0), f.SubData(1), f.SubData(2));
+	gr->Rotate(50,60);	gr->Axis();	gr->Box();
+	gr->Dots(f.SubData(0), f.SubData(1), f.SubData(2),"G#o","size 0.05");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_flame2d="list A [0.33,0,0,0.33,0,0,0.2] [0.33,0,0,0.33,0.67,0,0.2] [0.33,0,0,0.33,0.33,0.33,0.2]\\\n"
+"\t[0.33,0,0,0.33,0,0.67,0.2] [0.33,0,0,0.33,0.67,0.67,0.2]\n"
+"new B 2 3 A.ny '0.3'\nput B 3 0 0 -1\nput B 3 0 1 -1\nput B 3 0 2 -1\n"
+"flame2d fx fy A B 1000000\nsubplot 1 1 0 '<_':title 'Flame2d sample'\n"
+"ranges fx fy:box:axis\nplot fx fy 'r#o ';size 0.05";
+void smgl_flame2d(mglGraph *gr)
+{
+	mglData A, B(2,3,5);
+	A.SetList(35, 0.33,0.,0.,0.33,0.,0.,0.2, 0.33,0.,0.,0.33,0.67,0.,0.2, 0.33,0.,0.,0.33,0.33,0.33,0.2,
+			0.33,0.,0.,0.33,0.,0.67,0.2, 0.33,0.,0.,0.33,0.67,0.67,0.2);
+	A.Rearrange(7);
+	for(long i=0;i<2*3*5;i++)	B.a[i] = 0.3;
+	for(long i=0;i<5;i++)	B.a[2*3*i] = B.a[2*3*i+1*2] = B.a[2*3*i+2*2] = 3;
+	mglData f(mglFlame2d(A,B,1000000));
+	gr->SubPlot(1,1,0,"<_");
+	if(big!=3)	gr->Title("Flame2d sample");
+	gr->SetRanges(f.SubData(0), f.SubData(1));
+	gr->Axis();	gr->Box();
+	gr->Plot(f.SubData(0), f.SubData(1),"r#o ","size 0.05");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_detect="subplot 1 1 0 '':title 'Detect sample'\n"
+"new a 200 100 'exp(-30*(y-0.5*sin(pi*x))^2-rnd/10)+exp(-30*(y+0.5*sin(pi*x))^2-rnd/10)+exp(-30*(x+y)^2-rnd/10)'\n"
+"ranges 0 a.nx 0 a.ny:box\nalpha on:crange a:dens a\n\n"
+"detect r a 0.1 5\nplot r(0) r(1) '.'";
+void smgl_detect(mglGraph *gr)
+{
+	mglData a(200, 100);
+	gr->Fill(a,"exp(-30*(y-0.5*sin(pi*x))^2-rnd/10)+exp(-30*(y+0.5*sin(pi*x))^2-rnd/10)+exp(-30*(x+y)^2-rnd/10)");
+	gr->SubPlot(1,1,0,"");
+	if(big!=3)	gr->Title("Detect sample");
+	gr->SetRanges(0,a.nx,0,a.ny);	gr->SetRange('c',a);
+	gr->Alpha(true);	gr->Box();	gr->Dens(a);
+	mglData r(a.Detect(0.1,5));
+	gr->Plot(r.SubData(0), r.SubData(1), ".");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_iris="read a 'iris.dat'\ncrop a 0 4 'x':rearrange a a.nx 50\n"
+"subplot 1 1 0 '':title 'Iris plot'\n"
+"iris a 'sepal\\n length;sepal\\n width;petal\\n length;petal\\n width' '. ';value -1.5;size -2";
+void smgl_iris(mglGraph *gr)
+{
+	mglData a("iris.dat");	a.Crop(0,4,'x');	a.Rearrange(4,50);
+	gr->SubPlot(1,1,0,"");
+	if(big!=3)	gr->Title("Iris sample");
+	gr->Iris(a, "sepal\nlength;sepal\nwidth;petal\nlength;petal\nwidth", ". ", "value -1.5;size -2");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_dilate="subplot 2 2 0:title 'Dilate&Erode 1D sample'\n"
+"new y 11:put y 1 5\nranges 0 10 0 1:axis:box\nplot y 'b*'\n"
+"dilate y 0.5 2\nplot y 'rs'\nerode y 0.5 1\nplot y 'g#o'\n\n"
+"subplot 2 2 1:title 'Dilate&Erode 2D sample':rotate 40 60\n"
+"ranges 0 10 0 10 0 3\naxis:box\nnew z 11 11:put z 3 5 5\n"
+"boxs z 'b':boxs z 'k#'\ndilate z 1 2\nboxs z 'r':boxs z 'k#'\n"
+"erode z 1 1\nboxs 2*z 'g':boxs 2*z 'k#'\n\n"
+"subplot 2 2 2\ntext 0.5 0.7 'initial' 'ba';size -2\n"
+"text 0.5 0.5 'dilate=2' 'ra';size -2\ntext 0.5 0.3 'erode=1' 'ga';size -2\n\n"
+"subplot 2 2 3:title 'Dilate&Erode 3D sample'\nrotate 60 50:light on:alpha on\n"
+"ranges 0 10 0 10 0 10:crange 0 3\naxis:box\nnew a 11 11 11:put a 3 5 5 5\n"
+"surf3a a a 1.5 'b'\ndilate a 1 2\nsurf3a a a 0.5 'r'\n"
+"erode a 1 1\nsurf3a 2*a 2*a 1 'g'";
+void smgl_dilate(mglGraph *gr)
+{
+	mglData y(11),	z(11,11), a(11,11,11);
+	y.a[5]=1;	z.a[5+11*5]=a.a[5+11*(5+11*5)] = 3;
+
+	if(big!=3)	{	gr->SubPlot(2,2,0);	gr->Title("Dilate&Erode 1D sample");	}
+	else	gr->SubPlot(1,1,0,"");
+	gr->SetRanges(0,10,0,1);	gr->Axis();	gr->Box();	gr->Plot(y,"b*");
+	y.Dilate(1,2);	gr->Plot(y,"rs");
+	y.Erode(1,1);	gr->Plot(y,"g#o");
+	if(big==3)	return;
+	
+	gr->SubPlot(2,2,1);	gr->Title("Dilate&Erode 2D sample");
+	gr->Rotate(40,60);	gr->SetRanges(0,10,0,10,0,3);
+	gr->Axis();	gr->Box();	gr->Boxs(z,"b");	gr->Boxs(z,"k#");
+	z.Dilate(1,2);			gr->Boxs(z,"r");	gr->Boxs(z,"k#");
+	z.Erode(1,1);	z*=2;	gr->Boxs(z,"g");	gr->Boxs(z,"k#");
+	
+	gr->SubPlot(2,2,2);
+	gr->Puts(0.5,0.7,"initial","ba",-2);
+	gr->Puts(0.5,0.5,"dilate=2","ra",-2);
+	gr->Puts(0.5,0.3,"erode=1","ga",-2);
+	
+	gr->SubPlot(2,2,3);	gr->Title("Dilate&Erode 3D sample");
+	gr->Rotate(60,50);	gr->Alpha(true);	gr->Light(true);
+	gr->SetRanges(0,10,0,10,0,10);	gr->SetRange('c',0,3);
+	gr->Axis();	gr->Box();	gr->Surf3A(1.5,a,a,"b");
+	a.Dilate(1,2);			gr->Surf3A(0.5,a,a,"r");
+	a.Erode(1,1);	a*=2;	gr->Surf3A(1,a,a,"g");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_section="subplot 1 1 0 '<_':title 'Section&Join sample'\n"
+"axis:box:line -1 0 1 0 'h:'\n# first lets demonstrate 'join'\n"
+"new aa 11 'x^2':new a1 3 '-x':new a2 15 'x^3'\njoin aa a1:join aa a2\n"
+"# add x-coordinate\nnew xx aa.nx 'x':join aa xx\nplot aa(:,1) aa(:,0) '2y'\n"
+"# now select 1-st (id=0) section between zeros\n"
+"section b1 aa 0 'x' 0\nplot b1(:,1) b1(:,0) 'bo'\n"
+"# next, select 3-d (id=2) section between zeros\n"
+"section b3 aa 2 'x' 0\nplot b3(:,1) b3(:,0) 'gs'\n"
+"# finally, select 2-nd (id=-2) section from the end\n"
+"section b4 aa -2 'x' 0\nplot b4(:,1) b4(:,0) 'r#o'";
+void smgl_section(mglGraph *gr)
+{
+	gr->SubPlot(1,1,0,"<_");
+	if(big!=3)	gr->Title("Section&Join sample");
+	gr->Axis();	gr->Box();	gr->Line(mglPoint(-1,0),mglPoint(1,0),"h:");
+	// first lets demonstrate 'join'
+	mglData aa(11), a1(3), a2(15);
+	gr->Fill(aa,"x^2");	gr->Fill(a1,"-x");	gr->Fill(a2,"x^3");
+	aa.Join(a1);	aa.Join(a2);
+	// add x-coordinate
+	mglData xx(aa.nx);	gr->Fill(xx,"x");	aa.Join(xx);
+	gr->Plot(aa.SubData(-1,1), aa.SubData(-1,0), "2y");
+	// now select 1-st (id=0) section between zeros
+	mglData b1(aa.Section(0,'x',0));
+	gr->Plot(b1.SubData(-1,1), b1.SubData(-1,0), "bo");
+	// next, select 3-d (id=2) section between zeros
+	mglData b2(aa.Section(2,'x',0));
+	gr->Plot(b2.SubData(-1,1), b2.SubData(-1,0), "gs");
+	// finally, select 2-nd (id=-2) section from the end
+	mglData b3(aa.Section(-2,'x',0));
+	gr->Plot(b3.SubData(-1,1), b3.SubData(-1,0), "r#o");
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_3wave="define t 50\n"
+"ode !r '-b*f;a*conj(f);a*conj(b)-0.1*f' 'abf' [1,1e-3,0] 0.1 t\n"
+"ranges 0 t 0 r.max\nplot r(0) 'b';legend 'a'\n"
+"plot r(1) 'g';legend 'b'\nplot r(2) 'r';legend 'f'\n"
+"axis:box:legend";
+void smgl_3wave(mglGraph *gr)
+{
+	gr->SubPlot(1,1,0,"<_");
+	if(big!=3)	gr->Title("Complex ODE sample");
+	double t=50;
+	mglData ini;	ini.SetList(3, 1., 1e-3, 0.);
+	mglDataC r(mglODEc("-b*f;a*conj(f);a*conj(b)-0.1*f","abf",ini,0.1,t));
+	gr->SetRanges(0, t, 0, r.Maximal());
+	gr->Plot(r.SubData(0),"b","legend 'a'");
+	gr->Plot(r.SubData(1),"g","legend 'b'");
+	gr->Plot(r.SubData(2),"r","legend 'f'");
+	gr->Axis();	gr->Box();	gr->Legend();
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_diffract="define n 32	#number of points\ndefine m 20 # number of iterations\n"
+"define dt 0.01 # time step\nnew res n m+1\nranges -1 1 0 m*dt 0 1\n\n"
+"#tridmat periodic variant\nnew !a n 'i',dt*(n/2)^2/2\ncopy !b !(1-2*a)\n\n"
+"new !u n 'exp(-6*x^2)'\nput res u all 0\nfor $i 0 m\ntridmat u a b a u 'xdc'\n"
+"put res u all $i+1\nnext\nsubplot 2 2 0 '<_':title 'Tridmat, periodic b.c.'\naxis:box:dens res\n\n"
+"#fourier variant\nnew k n:fillsample k 'xk'\ncopy !e !exp(-i1*dt*k^2)\n\n"
+"new !u n 'exp(-6*x^2)'\nput res u all 0\nfor $i 0 m\nfourier u 'x'\nmulto u e\nfourier u 'ix'\n"
+"put res u all $i+1\nnext\nsubplot 2 2 1 '<_':title 'Fourier method'\naxis:box:dens res\n\n"
+"#tridmat zero variant\nnew !u n 'exp(-6*x^2)'\nput res u all 0\nfor $i 0 m\ntridmat u a b a u 'xd'\n"
+"put res u all $i+1\nnext\nsubplot 2 2 2 '<_':title 'Tridmat, zero b.c.'\naxis:box:dens res\n\n"
+"#diffract exp variant\nnew !u n 'exp(-6*x^2)'\ndefine q dt*(n/2)^2/8 # need q<0.4 !!!\n"
+"put res u all 0\nfor $i 0 m\nfor $j 1 8	# due to smaller dt\ndiffract u 'xe' q\nnext\n"
+"put res u all $i+1\nnext\nsubplot 2 2 3 '<_':title 'Diffract, exp b.c.'\naxis:box:dens res";
+void smgl_diffract(mglGraph *gr)
+{
+	long n=32;	// number of points
+	long m=20;	// number of iterations
+	double dt=0.01;	// time step
+	mglData res(n,m+1);
+	gr->SetRanges(-1,1, 0,m*dt, 0,1);
+
+	// tridmat periodic variant
+	mglDataC a(n), b(n);	a = dual(0,dt*n*n/8);
+	for(long i=0;i<n;i++)	b.a[i] = mreal(1)-mreal(2)*a.a[i];
+	mglDataC u(n);	gr->Fill(u,"exp(-6*x^2)");	res.Put(u,-1,0);
+	for(long i=0;i<m;i++)
+	{
+		u = mglTridMatC(a,b,a,u,"xdc");
+		res.Put(u,-1,i+1);
+	}
+	gr->SubPlot(2,2,0,"<_");	gr->Title("Tridmat, periodic b.c.");
+	gr->Axis();	gr->Box();	gr->Dens(res);
+
+	// fourier variant
+	mglData k(n);	k.FillSample("xk");
+	mglDataC e(n);	for(long i=0;i<n;i++)	e.a[i] = exp(-dual(0,dt*k.a[i]*k.a[i]));
+	gr->Fill(u,"exp(-6*x^2)");	res.Put(u,-1,0);
+	for(long i=0;i<m;i++)
+	{
+		u.FFT("x");	u *= e;	u.FFT("ix");
+		res.Put(u,-1,i+1);
+	}
+	gr->SubPlot(2,2,1,"<_");	gr->Title("Fourier method");
+	gr->Axis();	gr->Box();	gr->Dens(res);
+
+	// tridmat zero variant
+	gr->Fill(u,"exp(-6*x^2)");	res.Put(u,-1,0);
+	for(long i=0;i<m;i++)
+	{
+		u = mglTridMatC(a,b,a,u,"xd");
+		res.Put(u,-1,i+1);
+	}
+	gr->SubPlot(2,2,2,"<_");	gr->Title("Tridmat, zero b.c.");
+	gr->Axis();	gr->Box();	gr->Dens(res);
+	
+	// diffract exp variant
+	gr->Fill(u,"exp(-6*x^2)");	res.Put(u,-1,0);
+	double q=dt*n*n/4/8;	// NOTE: need q<0.4 !!!
+	for(long i=0;i<m;i++)
+	{
+		for(long j=0;j<8;j++)	// due to smaller dt
+			u.Diffraction("xe",q);
+		res.Put(u,-1,i+1);
+	}
+	gr->SubPlot(2,2,3,"<_");	gr->Title("Diffract, exp b.c.");
+	gr->Axis();	gr->Box();	gr->Dens(res);
+}
+//-----------------------------------------------------------------------------
+const char *mmgl_earth="import dat 'Equirectangular-projection.jpg' 'BbGYw' -1 1\n"
+"subplot 1 1 0 '<>':title 'Earth in 3D':rotate 40 60\n"
+"copy phi dat 'pi*x':copy tet dat 'pi*y/2'\n"
+"copy x cos(tet)*cos(phi)\ncopy y cos(tet)*sin(phi)\ncopy z sin(tet)\n\n"
+"light on\nsurfc x y z dat 'BbGYw'\ncontp [-0.5,-0.5] x y z dat 'y'";
+void smgl_earth(mglGraph *gr)
+{
+	mglData dat;	dat.Import("Equirectangular-projection.jpg","BbGYw",-1,1);
+	// Calc proper 3d coordinates from projection
+	mglData phi(dat.nx,dat.ny);	phi.Fill(-M_PI,M_PI);
+	mglData tet(dat.nx,dat.ny);	tet.Fill(-M_PI/2,M_PI/2,'y');
+	mglData x(dat.nx,dat.ny), y(dat.nx,dat.ny), z(dat.nx,dat.ny);
+#pragma omp parallel for
+	for(long i=0;i<dat.nx*dat.ny;i++)
+	{	x.a[i] = cos(tet.a[i])*cos(phi.a[i]);
+		y.a[i] = cos(tet.a[i])*sin(phi.a[i]);
+		z.a[i] = sin(tet.a[i]);	}
+
+	gr->SubPlot(1,1,0,"<>");
+	if(big!=3)	gr->Title("Earth in 3D");
+	gr->Rotate(40,60);	gr->Light(true);
+	gr->SurfC(x,y,z,dat,"BbGYw");
+	mglData vals(2);	vals.a[0]=-0.5;
+	gr->ContP(vals, x,y,z,dat,"y");
+}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+mglSample samp[] = {
+	{"3wave", smgl_3wave, mmgl_3wave},
+	{"alpha", smgl_alpha, mmgl_alpha},
+	{"apde", smgl_apde, mmgl_apde},
+	{"area", smgl_area, mmgl_area},
+	{"aspect", smgl_aspect, mmgl_aspect},
+	{"axial", smgl_axial, mmgl_axial},
+	{"axis", smgl_axis, mmgl_axis},
+	{"barh", smgl_barh, mmgl_barh},
+	{"bars", smgl_bars, mmgl_bars},
+	{"belt", smgl_belt, mmgl_belt},
+	{"bifurcation", smgl_bifurcation, mmgl_bifurcation},
+	{"box", smgl_box, mmgl_box},
+	{"boxplot", smgl_boxplot, mmgl_boxplot},
+	{"boxs", smgl_boxs, mmgl_boxs},
+	{"candle", smgl_candle, mmgl_candle},
+	{"chart", smgl_chart, mmgl_chart},
+	{"cloud", smgl_cloud, mmgl_cloud },
+	{"colorbar", smgl_colorbar, mmgl_colorbar},
+	{"combined", smgl_combined, mmgl_combined },
+	{"cones", smgl_cones, mmgl_cones},
+	{"cont", smgl_cont, mmgl_cont},
+	{"cont_xyz", smgl_cont_xyz, mmgl_cont_xyz},
+	{"conta", smgl_conta, mmgl_conta},
+	{"contd", smgl_contd, mmgl_contd},
+	{"contf", smgl_contf, mmgl_contf},
+	{"contf_xyz", smgl_contf_xyz, mmgl_contf_xyz},
+	{"contfa", smgl_contfa, mmgl_contfa},
+	{"contv", smgl_contv, mmgl_contv},
+	{"correl", smgl_correl, mmgl_correl},
+//	{"crust", smgl_crust, mmgl_crust},	// TODO: open after triangulation
+	{"curvcoor", smgl_curvcoor, mmgl_curvcoor},
+	{"cut", smgl_cut, mmgl_cut},
+	{"dat_diff", smgl_dat_diff, mmgl_dat_diff},
+	{"dat_extra", smgl_dat_extra, mmgl_dat_extra },
+	{"data1", smgl_data1, mmgl_data1},
+	{"data2", smgl_data2, mmgl_data2},
+	{"dens", smgl_dens, mmgl_dens},
+	{"dens_xyz", smgl_dens_xyz, mmgl_dens_xyz},
+	{"densa", smgl_densa, mmgl_densa},
+	{"detect", smgl_detect, mmgl_detect},
+	{"dew", smgl_dew, mmgl_dew},
+	{"diffract", smgl_diffract, mmgl_diffract},
+	{"dilate", smgl_dilate, mmgl_dilate},
+	{"dots", smgl_dots, mmgl_dots},
+	{"earth", smgl_earth, mmgl_earth},
+	{"error", smgl_error, mmgl_error},
+	{"error2", smgl_error2, mmgl_error2},
+	{"export", smgl_export, mmgl_export},
+	{"fall", smgl_fall, mmgl_fall},
+	{"fit", smgl_fit, mmgl_fit},
+	{"flame2d", smgl_flame2d, mmgl_flame2d},
+	{"flow", smgl_flow, mmgl_flow},
+	{"fog", smgl_fog, mmgl_fog},
+	{"fonts", smgl_fonts, mmgl_fonts},
+	{"grad", smgl_grad, mmgl_grad},
+	{"hist", smgl_hist, mmgl_hist},
+	{"ifs2d", smgl_ifs2d, mmgl_ifs2d},
+	{"ifs3d", smgl_ifs3d, mmgl_ifs3d},
+	{"indirect",smgl_indirect,mmgl_indirect},
+	{"inplot", smgl_inplot, mmgl_inplot},
+	{"iris", smgl_iris, mmgl_iris},
+	{"label", smgl_label, mmgl_label},
+	{"lamerey", smgl_lamerey, mmgl_lamerey},
+	{"legend", smgl_legend, mmgl_legend },
+	{"light", smgl_light, mmgl_light},
+	{"loglog", smgl_loglog, mmgl_loglog},
+	{"map", smgl_map, mmgl_map},
+	{"mark", smgl_mark, mmgl_mark},
+	{"mask", smgl_mask, mmgl_mask},
+	{"mesh", smgl_mesh, mmgl_mesh},
+	{"mirror", smgl_mirror, mmgl_mirror },
+	{"molecule", smgl_molecule, mmgl_molecule },
+	{"ode", smgl_ode, mmgl_ode},
+	{"ohlc", smgl_ohlc, mmgl_ohlc},
+	{"param1", smgl_param1, mmgl_param1},
+	{"param2", smgl_param2, mmgl_param2},
+	{"param3", smgl_param3, mmgl_param3},
+	{"paramv", smgl_paramv, mmgl_paramv},
+	{"parser", smgl_parser, mmgl_parser},
+	{"pde", smgl_pde, mmgl_pde},
+	{"pendelta", smgl_pendelta, mmgl_pendelta},
+	{"pipe", smgl_pipe, mmgl_pipe},
+	{"plot", smgl_plot, mmgl_plot},
+	{"pmap", smgl_pmap, mmgl_pmap},
+	{"primitives", smgl_primitives, mmgl_primitives },
+	{"projection", smgl_projection, mmgl_projection },
+	{"projection5", smgl_projection5, mmgl_projection5 },
+	{"pulse", smgl_pulse, mmgl_pulse },
+	{"qo2d", smgl_qo2d, mmgl_qo2d},
+	{"radar", smgl_radar, mmgl_radar},
+	{"refill", smgl_refill, mmgl_refill},
+	{"region", smgl_region, mmgl_region},
+	{"scanfile", smgl_scanfile, mmgl_scanfile },
+	{"schemes", smgl_schemes, mmgl_schemes },
+	{"section", smgl_section, mmgl_section},
+	{"several_light", smgl_several_light, mmgl_several_light },
+	{"solve", smgl_solve, mmgl_solve},
+	{"stem", smgl_stem, mmgl_stem},
+	{"step", smgl_step, mmgl_step},
+	{"stereo", smgl_stereo, mmgl_stereo},
+	{"stfa", smgl_stfa, mmgl_stfa},
+	{"style", smgl_style, mmgl_style },
+	{"surf", smgl_surf, mmgl_surf},
+	{"surf3", smgl_surf3, mmgl_surf3},
+	{"surf3a", smgl_surf3a, mmgl_surf3a},
+	{"surf3c", smgl_surf3c, mmgl_surf3c},
+	{"surf3ca", smgl_surf3ca, mmgl_surf3ca},
+	{"surfa", smgl_surfa, mmgl_surfa},
+	{"surfc", smgl_surfc, mmgl_surfc},
+	{"surfca", smgl_surfca, mmgl_surfca},
+	{"table", smgl_table, mmgl_table},
+	{"tape", smgl_tape, mmgl_tape},
+	{"tens", smgl_tens, mmgl_tens},
+	{"ternary", smgl_ternary, mmgl_ternary },
+	{"text", smgl_text, mmgl_text},
+	{"text2", smgl_text2, mmgl_text2},
+	{"textmark", smgl_textmark, mmgl_textmark},
+	{"ticks", smgl_ticks, mmgl_ticks},
+	{"tile", smgl_tile, mmgl_tile},
+	{"tiles", smgl_tiles, mmgl_tiles},
+	{"torus", smgl_torus, mmgl_torus },
+	{"traj", smgl_traj, mmgl_traj},
+	{"triangulation",smgl_triangulation, mmgl_triangulation },
+	{"triplot", smgl_triplot, mmgl_triplot},
+	{"tube", smgl_tube, mmgl_tube},
+	{"type0", smgl_type0, mmgl_type0},
+	{"type1", smgl_type1, mmgl_type1},
+	{"type2", smgl_type2, mmgl_type2},
+	{"vect", smgl_vect, mmgl_vect},
+	{"vecta", smgl_vecta, mmgl_vecta},
+	{"venn", smgl_venn, mmgl_venn},
+{"", NULL, NULL}};
+//-----------------------------------------------------------------------------
diff --git a/examples/wnd_samples.cpp b/examples/wnd_samples.cpp
new file mode 100644
index 0000000..c054f0c
--- /dev/null
+++ b/examples/wnd_samples.cpp
@@ -0,0 +1,519 @@
+/***************************************************************************
+ * wnd_sample.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+//-----------------------------------------------------------------------------
+#include "mgl2/mgl.h"
+//-----------------------------------------------------------------------------
+void mgls_prepare1d(mglData *y, mglData *y1=0, mglData *y2=0, mglData *x1=0, mglData *x2=0);
+void mgls_prepare2d(mglData *a, mglData *b=0, mglData *v=0);
+void mgls_prepare3d(mglData *a, mglData *b=0);
+void mgls_prepare2v(mglData *a, mglData *b);
+void mgls_prepare3v(mglData *ex, mglData *ey, mglData *ez);
+//-----------------------------------------------------------------------------
+int test_wnd(mglGraph *gr)
+{
+mgl_set_test_mode(true);
+//	gr->SetQuality(6);
+	gr->NewFrame();	// 0
+	gr->Box();
+	gr->EndFrame();
+	gr->NewFrame();	// 1
+	gr->Axis();
+	gr->EndFrame();
+	gr->NewFrame();	// 2
+	gr->Label('x',"XXXX",0);
+	gr->Label('y',"YYYY",0);
+	gr->EndFrame();
+	gr->NewFrame();	// 3
+	gr->Puts(mglPoint(0,0),"0");
+	gr->EndFrame();
+
+	gr->Clf();
+	gr->ShowFrame(0);
+	gr->ShowFrame(1);
+	gr->ShowFrame(2);
+	gr->ShowFrame(3);
+//	gr->Puts(mglPoint(0,1),"1");
+	gr->Finish();
+	return 0;
+}
+//-----------------------------------------------------------------------------
+int sample(mglGraph *gr)
+{
+	gr->Rotate(20,40);
+	gr->SetRanges(-2,2,-2,2,-1,3);
+	gr->FSurf("cos(2*pi*(x^2+y^2))/(x^2+y^2+1)^2/(x^2+y^2<4)");
+	gr->Drop(mglPoint(0,0,3),mglPoint(0,0,-1),0.7,"b");
+	return 0;
+}
+//-----------------------------------------------------------------------------
+int sample_m(mglGraph *gr)
+{
+//	gr->Rotate(0,0);	gr->Axis();	gr->Box();	return 0;
+//	gr->Alpha(true); gr->Light(true);
+
+	gr->SubPlot(2,2,0);
+	gr->Puts(mglPoint(0,1.1),"Methane, CH_4",0,-2); gr->Rotate(60,120);
+	gr->Sphere(mglPoint(0,0,0),0.25,"k");
+	gr->Drop(mglPoint(0,0,0),mglPoint(0,0,1),0.35,"h",1,2);
+	gr->Sphere(mglPoint(0,0,0.7),0.25,"g");
+	gr->Drop(mglPoint(0,0,0),mglPoint(-0.94,0,-0.33),0.35,"h",1,2);
+	gr->Sphere(mglPoint(-0.66,0,-0.23),0.25,"g");
+	gr->Drop(mglPoint(0,0,0),mglPoint(0.47,0.82,-0.33),0.35,"h",1,2);
+	gr->Sphere(mglPoint(0.33,0.57,-0.23),0.25,"g");
+	gr->Drop(mglPoint(0,0,0),mglPoint(0.47,-0.82,-0.33),0.35,"h",1,2);
+	gr->Sphere(mglPoint(0.33,-0.57,-0.23),0.25,"g");
+
+	gr->SubPlot(2,2,1);
+	gr->Puts(mglPoint(0,1.1),"Water, H{_2}O",0,-2); gr->Rotate(60,100);
+	gr->Sphere(mglPoint(0,0,0),0.25,"r");
+	gr->Drop(mglPoint(0,0,0),mglPoint(0.3,0.5,0),0.3,"m",1,2);
+	gr->Sphere(mglPoint(0.3,0.5,0),0.25,"g");
+	gr->Drop(mglPoint(0,0,0),mglPoint(0.3,-0.5,0),0.3,"m",1,2);
+	gr->Sphere(mglPoint(0.3,-0.5,0),0.25,"g");
+
+	gr->SubPlot(2,2,2);
+	gr->Puts(mglPoint(0,1.1),"Oxygen, O_2",0,-2); gr->Rotate(60,120);
+	gr->Drop(mglPoint(0,0.5,0),mglPoint(0,-0.3,0),0.3,"m",1,2);
+	gr->Sphere(mglPoint(0,0.5,0),0.25,"r");
+	gr->Drop(mglPoint(0,-0.5,0),mglPoint(0,0.3,0),0.3,"m",1,2);
+	gr->Sphere(mglPoint(0,-0.5,0),0.25,"r");
+
+	gr->SubPlot(2,2,3);
+	gr->Puts(mglPoint(0,1.1),"Ammonia, NH_3",0,-2); gr->Rotate(60,120);
+	gr->Sphere(mglPoint(0,0,0),0.25,"b");
+	gr->Drop(mglPoint(0,0,0),mglPoint(0.33,0.57,0),0.32,"n",1,2);
+	gr->Sphere(mglPoint(0.33,0.57,0),0.25,"g");
+	gr->Drop(mglPoint(0,0,0),mglPoint(0.33,-0.57,0),0.32,"n",1,2);
+	gr->Sphere(mglPoint(0.33,-0.57,0),0.25,"g");
+	gr->Drop(mglPoint(0,0,0),mglPoint(-0.65,0,0),0.32,"n",1,2);
+	gr->Sphere(mglPoint(-0.65,0,0),0.25,"g");
+ 	return 0;
+}
+//-----------------------------------------------------------------------------
+int sample_1(mglGraph *gr)
+{
+	mglData  a(50,15),d(50),d1(50),d2(50);
+	d.Modify("0.7*sin(2*pi*x) + 0.5*cos(3*pi*x) + 0.2*sin(pi*x)");
+	d1.Modify("cos(2*pi*x)");
+	d2.Modify("sin(2*pi*x)");
+	a.Modify("pow(x,4*y)");
+
+	gr->NewFrame();
+	gr->Box();	gr->Axis("xy");	gr->Label('x',"x");	gr->Label('y',"y");
+	gr->Puts(mglPoint(0,1.2,1),"Simple plot of one curve");
+	gr->Plot(d);
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->Box();	gr->Axis("xy");	gr->Label('x',"x");	gr->Label('y',"y");
+	gr->Puts(mglPoint(0,1.2,1),"Three curves with manual styles");
+	gr->Plot(d,"b");
+	gr->Plot(d1,"ri");
+	gr->Plot(d2,"m|^");
+	gr->Plot(d,"l o");
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->Box();	gr->Axis("xy");	gr->Label('x',"x");	gr->Label('y',"y");
+	gr->Puts(mglPoint(0,1.2,1),"Three curves with automatic styles");
+	gr->Plot(d);
+	gr->Plot(d1);
+	gr->Plot(d2);
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->Box();	gr->Axis("xy");	gr->Label('x',"x");	gr->Label('y',"y");
+	gr->Puts(mglPoint(0,1.2,1),"Curves from matrix");
+	gr->Plot(a);
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->Box();	gr->Axis("xy");	gr->Label('x',"x");	gr->Label('y',"y");
+	gr->Puts(mglPoint(0,1.2,1),"Parametrical curves in 2D");
+	gr->Plot(d1,d2,"b");
+	gr->Plot(d1,d,"ri");
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->Puts(mglPoint(0,1.2,1),"Parametrical curves in 3D");
+	gr->Rotate(60,40);
+	gr->Box();	gr->Axis();	gr->Label('x',"x");	gr->Label('y',"y");	gr->Label('z',"z");
+	gr->Plot(d1,d2,d,"b");
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->SubPlot(2,2,0);
+	gr->Box();	gr->Axis("xy");	gr->Label('x',"x");	gr->Label('y',"y");
+	gr->Puts(mglPoint(0,1.2,1),"Area plot");
+	gr->Area(d);
+	gr->SubPlot(2,2,1);
+	gr->Box();	gr->Axis("xy");	gr->Label('x',"x");	gr->Label('y',"y");
+	gr->Puts(mglPoint(0,1.2,1),"Step plot");
+	gr->Step(d);
+	gr->SubPlot(2,2,2);
+	gr->Box();	gr->Axis("xy");	gr->Label('x',"x");	gr->Label('y',"y");
+	gr->Puts(mglPoint(0,1.2,1),"Stem plot");
+	gr->Stem(d);
+	gr->SubPlot(2,2,3);
+	gr->Box();	gr->Axis("xy");	gr->Label('x',"x");	gr->Label('y',"y");
+	gr->Puts(mglPoint(0,1.2,1),"Bars plot");
+	gr->Bars(d);
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->SubPlot(2,2,0);
+	gr->Puts(mglPoint(0,1.2,1),"Area plot in 3D");
+	gr->Rotate(60,40);
+	gr->Box();	gr->Axis();	gr->Label('x',"x");	gr->Label('y',"y");
+	gr->Area(d1,d2,d);
+	gr->SubPlot(2,2,1);
+	gr->Puts(mglPoint(0,1.2,1),"Step plot in 3D");
+	gr->Rotate(60,40);
+	gr->Box();	gr->Axis();	gr->Label('x',"x");	gr->Label('y',"y");
+	gr->Step(d1,d2,d);
+	gr->SubPlot(2,2,2);
+	gr->Puts(mglPoint(0,1.2,1),"Stem plot in 3D");
+	gr->Rotate(60,40);
+	gr->Box();	gr->Axis();	gr->Label('x',"x");	gr->Label('y',"y");
+	gr->Stem(d1,d2,d);
+	gr->SubPlot(2,2,3);
+	gr->Puts(mglPoint(0,1.2,1),"Bars plot in 3D");
+	gr->Rotate(60,40);
+	gr->Box();	gr->Axis();	gr->Label('x',"x");	gr->Label('y',"y");
+	gr->Bars(d1,d2,d);
+	gr->EndFrame();
+	return gr->GetNumFrame();
+}
+//-----------------------------------------------------------------------------
+int sample_2(mglGraph *gr)
+{
+	mglData  a(50,50),b(50,50),c(50,50),d(50,50),m(50,50),c1(50,50,7),
+		d1(50),d2(50);
+	d1.Modify("2*x*x-1");	d2.Modify("sin(pi*(x-0.5))");
+	a.Modify("0.6*sin(2*pi*x)*sin(3*pi*y) + 0.4*cos(3*pi*(x*y))");
+	b.Modify("(2+sin(2*pi*x))*cos(2*pi*y)/3");
+	c.Modify("(2+sin(2*pi*x))*sin(2*pi*y)/3");
+	d.Modify("cos(2*pi*x)");
+	m.Modify("cos(pi*x)");
+	c1.Modify("(2-z)*(2*x-1)^2 + (z+1)*(2*y-1)^2");
+
+	gr->NewFrame();
+	gr->Puts(mglPoint(0,1.2,1),"Simple surface");
+	gr->Rotate(40,60);
+	gr->Box();	gr->Axis();
+	gr->Surf(a);
+//	gr->Colorbar();
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->SubPlot(2,2,0);
+	gr->Puts(mglPoint(0,1.2,1),"Gray color scheme 'kw'");
+	gr->Rotate(40,60);
+	gr->Box();	gr->Axis();
+	gr->Surf(a,"kw");
+	gr->SubPlot(2,2,1);
+	gr->Puts(mglPoint(0,1.2,1),"Hot color scheme 'wyrRk'");
+	gr->Rotate(40,60);
+	gr->Box();	gr->Axis();
+	gr->Surf(a,"wyrRk");
+	gr->SubPlot(2,2,2);
+	gr->Puts(mglPoint(0,1.2,1),"Along coordiantes 'rgbd'");
+	gr->Rotate(40,60);
+	gr->Box();	gr->Axis();
+	gr->Surf(a,"rgbd");
+	gr->SubPlot(2,2,3);
+	gr->Puts(mglPoint(0,1.2,1),"Bicolor scheme 'BbwrR'");
+	gr->Rotate(40,60);
+	gr->Box();	gr->Axis();
+	gr->Surf(a,"BbwrR");
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->Box();	gr->Axis();
+	gr->Puts(mglPoint(0,1.2,1),"Density plot");
+	gr->Dens(a);
+	gr->InPlot(0.6,1,0.6,1,false);	// new axis in upper right corner
+	gr->Box();	gr->Axis();
+	gr->Puts(mglPoint(0,1.2,1),"... with bicolor");
+	gr->Dens(a,"BbwrR");
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->Puts(mglPoint(0,1.2,1),"Mesh lines (previous scheme by default)");
+	gr->Rotate(40,60);
+	gr->Box();	gr->Axis();
+	gr->Mesh(a);
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->Puts(mglPoint(0,1.2,1),"Surface of boxes");
+	gr->Rotate(40,60);
+	gr->Box();	gr->Axis();
+	gr->Boxs(a);
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->Puts(mglPoint(0,1.2,1),"Contour plot");
+	gr->Rotate(40,60);
+	gr->Box();	gr->Axis();
+	gr->Cont(a);
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->Puts(mglPoint(0,1.2,1),"Contour isosurface y-rotation");
+	gr->Rotate(40,60);
+	gr->Box();	gr->Axis();
+	gr->Axial(a,":y");
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->Puts(mglPoint(0,1.2,1),"Contour isosurface x-rotation");
+	gr->Rotate(40,60);
+	gr->Box();	gr->Axis();
+	gr->Axial(a,"x");
+	a.Transpose();
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->Puts(mglPoint(0,1.2,1),"Surface and contours");
+	gr->Rotate(40,60);
+	gr->Box();	gr->Axis();
+	gr->Cont(a,"BbcyrR_");
+	gr->Surf(a);
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->Puts(mglPoint(0,1.2,1),"Parametrical surface (1)");
+	gr->Rotate(40,60);
+	gr->Box();	gr->Axis();
+	gr->Mesh(d1,d2,b);
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->Puts(mglPoint(0,1.2,1),"Parametrical surface (vase)");
+	gr->Rotate(40,60);
+	gr->Box();	gr->Axis();
+	gr->Surf(b,c,m);
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->Puts(mglPoint(0,1.2,1),"Parametrical surface (torus)");
+	gr->Rotate(40,60);
+	gr->Box();	gr->Axis();
+	gr->Surf(b,c,d);
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->Puts(mglPoint(0,1.2,1),"Contours for 3-tensor");
+	gr->Rotate(40,60);
+	gr->Box();	gr->Axis();
+	gr->Cont(c1);
+	gr->EndFrame();
+	return gr->GetNumFrame();
+}
+//-----------------------------------------------------------------------------
+int sample_3(mglGraph *gr)
+{
+	mglData  a(50,50,50),b(50,50,50), c(50,50,50),d(50,50,50), d1(50),d2(50),d3(50);
+	d1.Modify("cos(2*pi*x)");
+	d2.Modify("sin(2*pi*x)");
+	d3.Modify("2*x*x-1");
+	a.Modify("(-2*((2*x-1)^2 + (2*y-1)^2 + (2*z-1)^4 - (2*z-1)^2 + 0.1))");
+	b.Modify("-2*((2*x-1)^2 + (2*y-1)^2)");
+	c.Modify("exp(-8*((2*x-1)^2+(2*y-1)^2)/(1+z*z*4))");
+	d.Modify("cos(32*z*((2*x-1)^2+(2*y-1)^2)/(1+z*z*4))");
+//	c.Modify("0.5*sin(2*pi*x)*sin(3*pi*y)*sin(3*pi*z) + 0.5*cos(4*pi*(x*y*z-(x*y+y*z+z*x)/2))");
+
+	gr->NewFrame();
+	gr->Puts(mglPoint(0,1.2,1),"Isosurface (try lightning!)");
+	gr->Rotate(40,60);
+	gr->Box();	gr->Axis();
+	gr->Surf3(a);
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->Puts(mglPoint(0,1.2,1),"Isosurface with 'rgbd' scheme");
+	gr->Rotate(40,60);
+	gr->Box();	gr->Axis();
+	gr->Surf3(a,"rgbd");
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->Puts(mglPoint(0,1.2,1),"Cloud plot (switch alpha !!!)");
+	gr->Rotate(40,60);
+	gr->Box();	gr->Axis();
+	gr->Cloud(a);
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->Puts(mglPoint(0,1.2,1),"Density at central slices");
+	gr->Rotate(40,60);
+	gr->Box();	gr->Axis();
+	gr->Dens3(a,"x");	gr->Dens3(a);	gr->Dens3(a,"z");
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->Puts(mglPoint(0,1.2,1),"Contours at central slices");
+	gr->Rotate(40,60);
+	gr->Box();	gr->Axis();
+	gr->Cont3(a,"x");	gr->Cont3(a);	gr->Cont3(a,"z");
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->SubPlot(2,1,0);
+	gr->Puts(mglPoint(0,1.2,1),"Gauss difraction");
+	gr->Rotate(40,60);
+	gr->Box();	gr->Axis();
+	gr->SetRange('c',0,1);
+	gr->Surf3(0.5,c,"g");
+	gr->SubPlot(2,1,1);
+	gr->Puts(mglPoint(0,1.2,1),"and its phase");
+	gr->Rotate(40,60);
+	gr->Box();	gr->Axis();
+	gr->Surf3A(sin(M_PI/4),d,c,"q");
+	gr->Surf3A(-sin(M_PI/4),d,c,"q");
+	gr->EndFrame();
+
+	return gr->GetNumFrame();
+}
+//-----------------------------------------------------------------------------
+int sample_d(mglGraph *gr)
+{
+	mglData  a(50,50),b(50,50);
+	mglData cx(50,50,50),cy(50,50,50),cz(50,50,50);
+	a.Modify("0.6*sin(2*pi*x)*sin(3*pi*y) + 0.4*cos(3*pi*(x*y))");
+	b.Modify("0.6*cos(2*pi*x)*cos(3*pi*y) + 0.4*cos(3*pi*(x*y))");
+	cx.Modify("0.01*(x-0.3)/pow((x-0.3)^2+(y-0.5)^2+(z-0.5)^2,1.5) - 0.01*(x-0.7)/pow((x-0.7)^2+(y-0.5)^2+(z-0.5)^2,1.5)");
+	cy.Modify("0.01*(y-0.5)/pow((x-0.3)^2+(y-0.5)^2+(z-0.5)^2,1.5) - 0.01*(y-0.5)/pow((x-0.7)^2+(y-0.5)^2+(z-0.5)^2,1.5)");
+	cz.Modify("0.01*(z-0.5)/pow((x-0.3)^2+(y-0.5)^2+(z-0.5)^2,1.5) - 0.01*(z-0.5)/pow((x-0.7)^2+(y-0.5)^2+(z-0.5)^2,1.5)");
+
+	gr->NewFrame();
+	gr->Box();	gr->Axis("xy");
+	gr->Puts(mglPoint(0,1.2,1),"Vector field (color ~ \\sqrt{a^2})",":rC",8);
+	gr->Vect(a,b,"","value 50");
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->Box();	gr->Axis("xy");
+	gr->Puts(mglPoint(0,1.2,1),"Vector field (length ~ \\sqrt{a^2})",":rC",8);
+	gr->Vect(a,b);
+	gr->EndFrame();
+
+	gr->NewFrame();
+	gr->Box();	gr->Axis("xy");
+	gr->Puts(mglPoint(0,1.2,1),"Flow chart (blue - source)",":rC",8);
+	gr->Flow(a,b);
+	gr->EndFrame();
+
+	return gr->GetNumFrame();
+}
+//-----------------------------------------------------------------------------
+void mgls_prepare1d(mglData *y, mglData *y1, mglData *y2, mglData *x1, mglData *x2)
+{
+	long n=50;
+	if(y)	y->Create(n,3);
+	if(x1)	x1->Create(n);
+	if(x2)	x2->Create(n);
+	if(y1)	y1->Create(n);
+	if(y2)	y2->Create(n);
+	for(long i=0;i<n;i++)
+	{
+		double xx = i/(n-1.);
+		if(y)
+		{
+			y->a[i] = 0.7*sin(2*M_PI*xx) + 0.5*cos(3*M_PI*xx) + 0.2*sin(M_PI*xx);
+			y->a[i+n] = sin(2*M_PI*xx);
+			y->a[i+2*n] = cos(2*M_PI*xx);
+		}
+		if(y1)	y1->a[i] = 0.5+0.3*cos(2*M_PI*xx);
+		if(y2)	y2->a[i] = 0.3*sin(2*M_PI*xx);
+		if(x1)	x1->a[i] = xx*2-1;
+		if(x2)	x2->a[i] = 0.05+0.03*cos(2*M_PI*xx);
+	}
+}
+//-----------------------------------------------------------------------------
+void mgls_prepare2d(mglData *a, mglData *b, mglData *v)
+{
+	long n=50,m=40;
+	if(a)	a->Create(n,m);
+	if(b)	b->Create(n,m);
+	if(v)	{	v->Create(9);	v->Fill(-1,1);	}
+	for(long j=0;j<m;j++)	for(long i=0;i<n;i++)
+	{
+		double x = i/(n-1.), y = j/(m-1.);
+		long i0 = i+n*j;
+		if(a)	a->a[i0] = 0.6*sin(2*M_PI*x)*sin(3*M_PI*y)+0.4*cos(3*M_PI*x*y);
+		if(b)	b->a[i0] = 0.6*cos(2*M_PI*x)*cos(3*M_PI*y)+0.4*cos(3*M_PI*x*y);
+	}
+}
+//-----------------------------------------------------------------------------
+void mgls_prepare3d(mglData *a, mglData *b)
+{
+	long n=61,m=50,l=40;
+	if(a)	a->Create(n,m,l);
+	if(b)	b->Create(n,m,l);
+	for(long k=0;k<l;k++)	for(long j=0;j<m;j++)	for(long i=0;i<n;i++)
+	{
+		double x=2*i/(n-1.)-1, y=2*j/(m-1.)-1, z=2*k/(l-1.)-1;
+		long i0 = i+n*(j+m*k);
+		if(a)	a->a[i0] = -2*(x*x + y*y + z*z*z*z - z*z - 0.1);
+		if(b)	b->a[i0] = 1-2*tanh((x+y)*(x+y));
+	}
+}
+//-----------------------------------------------------------------------------
+void mgls_prepare2v(mglData *a, mglData *b)
+{
+	long n=20,m=30;
+	if(a)	a->Create(n,m);
+	if(b)	b->Create(n,m);
+	for(long j=0;j<m;j++)	for(long i=0;i<n;i++)
+	{
+		double x=i/(n-1.), y=j/(m-1.);
+		long i0 = i+n*j;
+		if(a)	a->a[i0] = 0.6*sin(2*M_PI*x)*sin(3*M_PI*y)+0.4*cos(3*M_PI*x*y);
+		if(b)	b->a[i0] = 0.6*cos(2*M_PI*x)*cos(3*M_PI*y)+0.4*cos(3*M_PI*x*y);
+	}
+}
+//-----------------------------------------------------------------------------
+void mgls_prepare3v(mglData *ex, mglData *ey, mglData *ez)
+{
+	long n=10;
+	double z0=0.3;
+	if(!ex || !ey || !ez)	return;
+	ex->Create(n,n,n);	ey->Create(n,n,n);	ez->Create(n,n,n);
+	for(long k=0;k<n;k++)	for(long j=0;j<n;j++)	for(long i=0;i<n;i++)
+	{
+		double x=2*i/(n-1.)-1, y=2*j/(n-1.)-1, z=2*k/(n-1.)-1;
+		long i0 = i+n*(j+k*n);
+/* 		r1 = 1./(x*x+y*y+z*z+0.01);	r2=exp(-0.01/r1/r1)*r1;
+ 		ex->a[i0]=z*y*r2*r2;
+ 		ey->a[i0]=x*y*r2*r2+1;
+ 		ez->a[i0]=y*x*r2*r2;*/
+/*		ex->a[i0]=3*z;
+		ey->a[i0]=1;
+		ez->a[i0]=-3*x;*/
+		double r1 = pow(x*x+y*y+(z-z0)*(z-z0)+0.03,1.5);
+		double r2 = pow(x*x+y*y+(z+z0)*(z+z0)+0.03,1.5);
+		ex->a[i0]=0.2*x/r1 - 0.2*x/r2;
+		ey->a[i0]=0.2*y/r1 - 0.2*y/r2;
+		ez->a[i0]=0.2*(z-z0)/r1 - 0.2*(z+z0)/r2;
+	}
+}
+//-----------------------------------------------------------------------------
diff --git a/examples/wx_example.cpp b/examples/wx_example.cpp
new file mode 100644
index 0000000..2f82765
--- /dev/null
+++ b/examples/wx_example.cpp
@@ -0,0 +1,81 @@
+/***************************************************************************
+ * wx_example.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <wx/wx.h>
+#undef _
+#include "mgl2/wx.h"
+//-----------------------------------------------------------------------------
+int test_wnd(mglGraph *gr);
+int sample(mglGraph *gr);
+int sample_1(mglGraph *gr);
+int sample_2(mglGraph *gr);
+int sample_3(mglGraph *gr);
+int sample_d(mglGraph *gr);
+//-----------------------------------------------------------------------------
+class testApp : public wxApp
+{
+public:
+	virtual bool OnInit();
+};
+//-----------------------------------------------------------------------------
+class testFrame: public wxFrame
+{
+public:
+	testFrame(wxFrame *frame, const wxString& title);
+	~testFrame() {}
+private:
+	enum	{	idMenuQuit = 1000	};
+	void OnClose(wxCloseEvent& )	{	Destroy();	}
+	void OnQuit(wxCommandEvent& )	{	Destroy();	}
+
+	wxScrolledWindow *scroll;
+	wxMathGL *mgl;
+	DECLARE_EVENT_TABLE()
+};
+//-----------------------------------------------------------------------------
+IMPLEMENT_APP(testApp)
+//-----------------------------------------------------------------------------
+bool testApp::OnInit()
+{
+	testFrame* frame = new testFrame(0L, _("MathGL + wxWidgets sample"));
+	frame->Show();
+	return true;
+}
+//-----------------------------------------------------------------------------
+BEGIN_EVENT_TABLE(testFrame, wxFrame)
+	EVT_CLOSE(testFrame::OnClose)
+	EVT_MENU(idMenuQuit, testFrame::OnQuit)
+END_EVENT_TABLE()
+//-----------------------------------------------------------------------------
+testFrame::testFrame(wxFrame *frame, const wxString& title) : wxFrame(frame, -1, title)
+{
+	// create a menu bar
+	wxMenuBar* mbar = new wxMenuBar();
+	wxMenu* fileMenu = new wxMenu(_T(""));
+	fileMenu->Append(idMenuQuit, _("&Quit\tAlt-F4"), _("Quit the application"));
+	mbar->Append(fileMenu, _("&File"));
+	SetMenuBar(mbar);
+	SetSize(800,620);
+
+	scroll = new wxScrolledWindow(this);
+	mgl = new wxMathGL(scroll);
+	mgl->SetDraw(mgl_draw_graph,(void*)sample);
+	mgl->Update();
+}
+//-----------------------------------------------------------------------------
diff --git a/fonts/CMakeLists.txt b/fonts/CMakeLists.txt
new file mode 100644
index 0000000..f529c18
--- /dev/null
+++ b/fonts/CMakeLists.txt
@@ -0,0 +1,23 @@
+include_directories( ${MathGL2_SOURCE_DIR}/include ${MathGL2_BINARY_DIR}/include)
+set(hdrF ../include/mgl2/font.h ../include/mgl2/define.h ${MathGL2_BINARY_DIR}/include/mgl2/config.h)
+add_executable(make_bin make_bin.cpp ../src/font.cpp ${hdrF})
+#target_link_libraries(make_bin mgl-static ${getopt_lib-static})
+target_link_libraries(make_bin ${MGL_DEP_LIBS})
+
+set(MGL_FONTS STIX adventor  bonum  cursor  heroscn  heros  pagella  schola  termes)
+set(MGL_FONTS_BIN )
+set(MGL_FONTS_SRC )
+
+foreach(SAMPLE ${MGL_FONTS})
+	set(MGL_FONTS_BIN ${MGL_FONTS_BIN} ${MathGL2_BINARY_DIR}/fonts/${SAMPLE}.vfmb)
+	add_custom_command(OUTPUT ${MathGL2_BINARY_DIR}/fonts/${SAMPLE}.vfmb
+		COMMAND make_bin -p ${MathGL2_SOURCE_DIR}/fonts/ -o ${MathGL2_BINARY_DIR}/fonts/${SAMPLE}.vfmb ${SAMPLE}
+		DEPENDS ${SAMPLE}.vfm make_bin )
+endforeach(SAMPLE)
+
+add_custom_target(fonts ALL DEPENDS ${MGL_FONTS_BIN})
+
+install(DIRECTORY ${MathGL2_BINARY_DIR}/fonts/ DESTINATION ${MGL_FONT_PATH}
+			PATTERN "*[mM]ake*" EXCLUDE
+			PATTERN ".svn" EXCLUDE
+			PATTERN "*.vfmb")
diff --git a/fonts/STIX.vfm b/fonts/STIX.vfm
new file mode 100644
index 0000000..b07ac2d
Binary files /dev/null and b/fonts/STIX.vfm differ
diff --git a/fonts/STIX_b.vfm b/fonts/STIX_b.vfm
new file mode 100644
index 0000000..6bec32c
Binary files /dev/null and b/fonts/STIX_b.vfm differ
diff --git a/fonts/STIX_bi.vfm b/fonts/STIX_bi.vfm
new file mode 100644
index 0000000..9ce6241
Binary files /dev/null and b/fonts/STIX_bi.vfm differ
diff --git a/fonts/STIX_i.vfm b/fonts/STIX_i.vfm
new file mode 100644
index 0000000..ea51c6c
Binary files /dev/null and b/fonts/STIX_i.vfm differ
diff --git a/fonts/adventor.vfm b/fonts/adventor.vfm
new file mode 100644
index 0000000..22b9ea7
Binary files /dev/null and b/fonts/adventor.vfm differ
diff --git a/fonts/adventor_b.vfm b/fonts/adventor_b.vfm
new file mode 100644
index 0000000..c2eac39
Binary files /dev/null and b/fonts/adventor_b.vfm differ
diff --git a/fonts/adventor_bi.vfm b/fonts/adventor_bi.vfm
new file mode 100644
index 0000000..30ffd68
Binary files /dev/null and b/fonts/adventor_bi.vfm differ
diff --git a/fonts/adventor_i.vfm b/fonts/adventor_i.vfm
new file mode 100644
index 0000000..b885858
Binary files /dev/null and b/fonts/adventor_i.vfm differ
diff --git a/fonts/bonum.vfm b/fonts/bonum.vfm
new file mode 100644
index 0000000..c6aa626
Binary files /dev/null and b/fonts/bonum.vfm differ
diff --git a/fonts/bonum_b.vfm b/fonts/bonum_b.vfm
new file mode 100644
index 0000000..bc58c44
Binary files /dev/null and b/fonts/bonum_b.vfm differ
diff --git a/fonts/bonum_bi.vfm b/fonts/bonum_bi.vfm
new file mode 100644
index 0000000..e4197a0
Binary files /dev/null and b/fonts/bonum_bi.vfm differ
diff --git a/fonts/bonum_i.vfm b/fonts/bonum_i.vfm
new file mode 100644
index 0000000..12aecf0
Binary files /dev/null and b/fonts/bonum_i.vfm differ
diff --git a/fonts/chorus.vfm b/fonts/chorus.vfm
new file mode 100644
index 0000000..ee1b049
Binary files /dev/null and b/fonts/chorus.vfm differ
diff --git a/fonts/cursor.vfm b/fonts/cursor.vfm
new file mode 100644
index 0000000..e11ac80
Binary files /dev/null and b/fonts/cursor.vfm differ
diff --git a/fonts/cursor_b.vfm b/fonts/cursor_b.vfm
new file mode 100644
index 0000000..ab7145a
Binary files /dev/null and b/fonts/cursor_b.vfm differ
diff --git a/fonts/cursor_bi.vfm b/fonts/cursor_bi.vfm
new file mode 100644
index 0000000..763bc0a
Binary files /dev/null and b/fonts/cursor_bi.vfm differ
diff --git a/fonts/cursor_i.vfm b/fonts/cursor_i.vfm
new file mode 100644
index 0000000..ef4aff1
Binary files /dev/null and b/fonts/cursor_i.vfm differ
diff --git a/fonts/heros.vfm b/fonts/heros.vfm
new file mode 100644
index 0000000..5f40a94
Binary files /dev/null and b/fonts/heros.vfm differ
diff --git a/fonts/heros_b.vfm b/fonts/heros_b.vfm
new file mode 100644
index 0000000..0fab5dd
Binary files /dev/null and b/fonts/heros_b.vfm differ
diff --git a/fonts/heros_bi.vfm b/fonts/heros_bi.vfm
new file mode 100644
index 0000000..92e5d31
Binary files /dev/null and b/fonts/heros_bi.vfm differ
diff --git a/fonts/heros_i.vfm b/fonts/heros_i.vfm
new file mode 100644
index 0000000..94e487b
Binary files /dev/null and b/fonts/heros_i.vfm differ
diff --git a/fonts/heroscn.vfm b/fonts/heroscn.vfm
new file mode 100644
index 0000000..342334f
Binary files /dev/null and b/fonts/heroscn.vfm differ
diff --git a/fonts/heroscn_b.vfm b/fonts/heroscn_b.vfm
new file mode 100644
index 0000000..06e7aa3
Binary files /dev/null and b/fonts/heroscn_b.vfm differ
diff --git a/fonts/heroscn_bi.vfm b/fonts/heroscn_bi.vfm
new file mode 100644
index 0000000..bcc180b
Binary files /dev/null and b/fonts/heroscn_bi.vfm differ
diff --git a/fonts/heroscn_i.vfm b/fonts/heroscn_i.vfm
new file mode 100644
index 0000000..c20bdfd
Binary files /dev/null and b/fonts/heroscn_i.vfm differ
diff --git a/fonts/make_bin.cpp b/fonts/make_bin.cpp
new file mode 100644
index 0000000..600745f
--- /dev/null
+++ b/fonts/make_bin.cpp
@@ -0,0 +1,51 @@
+/***************************************************************************
+ * make_bin.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <getopt.h>
+#include "mgl2/font.h"
+//-----------------------------------------------------------------------------
+int main(int argc, char *argv[])
+{
+	mglFont fnt;
+	std::string path, base, fname;
+
+	while(1)
+	{
+		int ch = getopt(argc, argv, "p:o:h");
+		if(ch=='p')	path = optarg;
+		else if(ch=='o')	fname = optarg;
+		else if(ch=='h' || (ch==-1 && optind>=argc))
+		{
+			printf("make_bin convert mgl font to binary file.\nCurrent version is 2.%g\n",MGL_VER2);
+			printf("Usage:\tmake_bin [parameter(s)] base\n");
+			printf(
+				"\t-p path      set specific path for base font files\n"
+				"\t-o fname     set output filename (use ${base}.vfmb by default)\n"
+				"\t-h           print this message\n" );
+			return 0;
+		}
+		else if(ch==-1 && optind<argc)	{	base = argv[optind];	break;	}
+	}
+	if(fname.empty())	fname = base + ".vfmb";
+	fnt.Load(base.c_str(),path.c_str());
+	size_t size = fnt.SaveBin(fname.c_str());
+	printf("Output size of %s should be %zu\n", fname.c_str(), size);
+	return 0;
+}
+//-----------------------------------------------------------------------------
diff --git a/fonts/pagella.vfm b/fonts/pagella.vfm
new file mode 100644
index 0000000..87a0061
Binary files /dev/null and b/fonts/pagella.vfm differ
diff --git a/fonts/pagella_b.vfm b/fonts/pagella_b.vfm
new file mode 100644
index 0000000..8da8bd1
Binary files /dev/null and b/fonts/pagella_b.vfm differ
diff --git a/fonts/pagella_bi.vfm b/fonts/pagella_bi.vfm
new file mode 100644
index 0000000..4f47168
Binary files /dev/null and b/fonts/pagella_bi.vfm differ
diff --git a/fonts/pagella_i.vfm b/fonts/pagella_i.vfm
new file mode 100644
index 0000000..bd0dc24
Binary files /dev/null and b/fonts/pagella_i.vfm differ
diff --git a/fonts/schola.vfm b/fonts/schola.vfm
new file mode 100644
index 0000000..ee36d40
Binary files /dev/null and b/fonts/schola.vfm differ
diff --git a/fonts/schola_b.vfm b/fonts/schola_b.vfm
new file mode 100644
index 0000000..84d58f7
Binary files /dev/null and b/fonts/schola_b.vfm differ
diff --git a/fonts/schola_bi.vfm b/fonts/schola_bi.vfm
new file mode 100644
index 0000000..5b009ce
Binary files /dev/null and b/fonts/schola_bi.vfm differ
diff --git a/fonts/schola_i.vfm b/fonts/schola_i.vfm
new file mode 100644
index 0000000..87710b8
Binary files /dev/null and b/fonts/schola_i.vfm differ
diff --git a/fonts/termes.vfm b/fonts/termes.vfm
new file mode 100644
index 0000000..2e0404d
Binary files /dev/null and b/fonts/termes.vfm differ
diff --git a/fonts/termes_b.vfm b/fonts/termes_b.vfm
new file mode 100644
index 0000000..5039e9b
Binary files /dev/null and b/fonts/termes_b.vfm differ
diff --git a/fonts/termes_bi.vfm b/fonts/termes_bi.vfm
new file mode 100644
index 0000000..67110c6
Binary files /dev/null and b/fonts/termes_bi.vfm differ
diff --git a/fonts/termes_i.vfm b/fonts/termes_i.vfm
new file mode 100644
index 0000000..ec85e7e
Binary files /dev/null and b/fonts/termes_i.vfm differ
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
new file mode 100644
index 0000000..ddc3b4d
--- /dev/null
+++ b/include/CMakeLists.txt
@@ -0,0 +1,35 @@
+configure_file(${MathGL2_SOURCE_DIR}/include/config.h.in ${MathGL2_BINARY_DIR}/include/mgl2/config.h)
+
+install(DIRECTORY mgl2/ DESTINATION ${MGL_INCLUDE_PATH}
+                        PATTERN ".svn" EXCLUDE
+                        PATTERN "fltk.h" EXCLUDE
+                        PATTERN "glut.h" EXCLUDE
+                        PATTERN "wx.h" EXCLUDE
+                        PATTERN "qt.h" EXCLUDE
+                        PATTERN "qmathgl.h" EXCLUDE
+                        PATTERN "window.h" EXCLUDE
+                        PATTERN "*old.h" EXCLUDE
+                        PATTERN "*~" EXCLUDE
+                        PATTERN "*.fs"
+                        PATTERN "*.pas"
+                        PATTERN "*.h")
+
+install(FILES ${MathGL2_BINARY_DIR}/include/mgl2/config.h DESTINATION ${MGL_INCLUDE_PATH})
+if(MGL_HAVE_FLTK)
+	install(FILES mgl2/fltk.h DESTINATION ${MGL_INCLUDE_PATH})
+endif(MGL_HAVE_FLTK)
+if(MGL_HAVE_GLUT)
+	install(FILES mgl2/glut.h DESTINATION ${MGL_INCLUDE_PATH})
+endif(MGL_HAVE_GLUT)
+if(MGL_HAVE_WX)
+	install(FILES mgl2/wx.h DESTINATION ${MGL_INCLUDE_PATH})
+endif(MGL_HAVE_WX)
+if(MGL_HAVE_QT)
+	install(FILES mgl2/qt.h mgl2/qmathgl.h DESTINATION ${MGL_INCLUDE_PATH})
+endif(MGL_HAVE_QT)
+
+#if(MGL_HAVE_FLTK AND MGL_HAVE_WX AND MGL_HAVE_QT)
+if(MGL_HAVE_FLTK AND MGL_HAVE_QT AND MGL_HAVE_WX)
+	install(FILES mgl2/window.h DESTINATION ${MGL_INCLUDE_PATH})
+#endif(MGL_HAVE_FLTK AND MGL_HAVE_WX AND MGL_HAVE_QT)
+endif(MGL_HAVE_FLTK AND MGL_HAVE_QT AND MGL_HAVE_WX)
diff --git a/include/config.h.in b/include/config.h.in
new file mode 100644
index 0000000..412f647
--- /dev/null
+++ b/include/config.h.in
@@ -0,0 +1,46 @@
+#ifndef _MGL_CONFIG_H_
+#define _MGL_CONFIG_H_
+
+#define MGL_VER2 	${MathGL_VERSION_MINOR}.${MathGL_PATCH_VERSION}	// minor version of MathGL 2.* (like 1.3 for v.2.1.3)
+
+#define MGL_USE_DOUBLE	${MGL_USE_DOUBLE}
+
+#ifdef WIN32	// a man ask to use built-in font under Windows
+#define MGL_DEF_FONT_NAME	""
+#else
+#define MGL_DEF_FONT_NAME	"${MGL_DEF_FONT}"
+#endif
+#define MGL_INSTALL_DIR	"${CMAKE_INSTALL_PREFIX}"
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+#define MGL_SYS_NAN		0
+#define MGL_HAVE_PTHREAD	0
+#define MGL_HAVE_PTHR_WIDGET	0
+#define MGL_HAVE_ATTRIBUTE	0
+#define MGL_HAVE_C99_COMPLEX	0
+#else
+#define MGL_SYS_NAN			${MGL_HAVE_NAN_INF}
+#define MGL_HAVE_PTHREAD	${MGL_HAVE_PTHREAD}
+#define MGL_HAVE_PTHR_WIDGET	${MGL_HAVE_PTHR_WIDGET}
+#define MGL_HAVE_ATTRIBUTE	${MGL_HAVE_ATTRIBUTE}
+#define MGL_HAVE_C99_COMPLEX	${MGL_HAVE_C99_COMPLEX}
+#endif
+
+#define MGL_SIZEOF_LONG	${SIZEOF_LONG}
+#define MGL_HAVE_LTDL	${MGL_HAVE_LTDL}
+#define MGL_HAVE_RVAL	${MGL_HAVE_RVAL}
+#define MGL_HAVE_ZLIB	${MGL_HAVE_ZLIB}
+#define MGL_HAVE_PNG	${MGL_HAVE_PNG}
+#define MGL_HAVE_GSL	${MGL_HAVE_GSL}
+#define MGL_HAVE_OPENGL	${MGL_HAVE_OPENGL}
+#define MGL_HAVE_OMP	${MGL_HAVE_OMP}
+#define MGL_HAVE_JPEG	${MGL_HAVE_JPEG}
+#define MGL_HAVE_GIF	${MGL_HAVE_GIF}
+#define MGL_HAVE_PDF	${MGL_HAVE_PDF}
+#define MGL_HAVE_HDF4	${MGL_HAVE_HDF4}
+#define MGL_HAVE_HDF5	${MGL_HAVE_HDF5}
+#define MGL_USE_GETTEXT	${MGL_USE_LIBINTL}
+#define MGL_FONT_PATH	"${MGL_FONT_PATH}"
+#define MGL_HAVE_FL_COPY	${MGL_HAVE_FL_COPY}
+
+#endif
diff --git a/include/mgl2/Fl_MathGL.h b/include/mgl2/Fl_MathGL.h
new file mode 100644
index 0000000..b41ef44
--- /dev/null
+++ b/include/mgl2/Fl_MathGL.h
@@ -0,0 +1,184 @@
+/***************************************************************************
+ * Fl_MathGL.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_FL_MATHGL_H_
+#define _MGL_FL_MATHGL_H_
+
+#ifdef __MWERKS__
+# define FL_DLL
+#endif
+
+#include <FL/Fl.H>
+#include <FL/Fl_Window.H>
+#include <FL/Fl_Scroll.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Counter.H>
+#include <FL/Fl_Menu_Bar.H>
+#include <mgl2/fltk.h>
+class mglCanvas;
+//-----------------------------------------------------------------------------
+/// Class is FLTK widget which display MathGL graphics
+class MGL_EXPORT Fl_MathGL : public Fl_Widget
+{
+	friend class Fl_MGLView;
+public:
+	Fl_Valuator	*tet_val;	///< pointer to external tet-angle validator
+	Fl_Valuator	*phi_val;	///< pointer to external phi-angle validator
+	mglCanvas *gr;			///< Built-in mglCanvas instance (mglCanvasFLTK is used by default)
+	std::string prim;		///< manual primitives
+	bool use_pthr;			///< use pthread for update plot
+
+	Fl_MathGL(int x, int y, int w, int h, const char *label=0);
+	virtual ~Fl_MathGL();
+	
+	/// Set drawing functions and its parameter
+	inline void set_draw(int (*func)(mglBase *gr, void *par), void *par)
+	{	if(draw_cl)	delete draw_cl;	draw_cl=0;	draw_func=func;	draw_par=par;	}
+	/// Set drawing functions pointed on mglGraph
+	inline void set_draw(int (*dr)(mglGraph *gr))
+	{	set_draw(dr?mgl_draw_graph:0,(void*)dr);	}
+	/// Set drawing based on instance of mglDraw class
+	inline void set_draw(mglDraw *dr)	{	if(draw_cl)	delete draw_cl;	draw_cl=dr;	draw_func=0;	}
+
+	/// Update (redraw) plot
+	virtual void update();
+	/// Set angles for additional plot rotation
+	inline void set_angle(mreal t, mreal p){	tet = t;	phi = p;	}
+	/// Set bitwise flags for general state (1-Alpha, 2-Light)
+	inline void set_flag(int f)	{	flag = f;	}
+	/// Set flags for handling mouse
+	void set_state(bool z, bool r, bool g=false)	{	zoom = z;	rotate = r;	grid = g;	}
+	/// Set zoom in/out region
+	inline void set_zoom(mreal X1, mreal Y1, mreal X2, mreal Y2)
+	{	x1 = X1;	x2 = X2;	y1 = Y1;	y2 = Y2;	update();	}
+	/// Get zoom region
+	inline void get_zoom(mreal *X1, mreal *Y1, mreal *X2, mreal *Y2)
+	{	*X1 = x1;	*X2 = x2;	*Y1 = y1;	*Y2 = y2;	}
+	/// Set popup menu pointer
+	inline void set_popup(const Fl_Menu_Item *pmenu, Fl_Widget *wdg, void *v)
+	{	popup = pmenu;	wpar = wdg;	vpar = v;	}
+
+	/// Set grapher object instead of built-in one. 
+	/// NOTE: Fl_MathGL will automatically delete this object
+	void set_graph(HMGL gr);
+	/// Set grapher object instead of built-in one. 
+	/// NOTE: Fl_MathGL will automatically delete this object
+	inline void set_graph(mglGraph *Gr)
+	{	set_graph(Gr->Self());	}
+	/// Get pointer to grapher
+	inline HMGL get_graph()	{	return (HMGL)gr;	}
+
+	/// Get mglDraw pointer or NULL
+	inline mglDraw *get_class()
+	{	mglDraw *d=0;
+		if(draw_func==mgl_draw_class)	d = (mglDraw*)draw_par;
+		if(draw_cl)	d = draw_cl;
+		return d;	}
+	
+	/// Show window with warnings after script parsing
+	inline void set_show_warn(bool s)	{	show_warn=s;	}
+	/// Ask to stop of script parsing
+	void stop(bool stop=true);
+	/// Enable/disable key handling as in mglview (default is false)
+	inline void set_handle_key(bool val)	{	handle_keys=true;	}
+	/// Get id of last clicked object
+	inline int get_last_id()	{	return last_id;	}
+	void draw_plot();	///< Single thread drawing itself
+	/// Check if script is parsing now or not
+	inline bool running()	{	return run;	}
+
+protected:
+	void *draw_par;		///< Parameters for drawing function mglCanvasWnd::DrawFunc.
+	/// Drawing function for window procedure. It should return the number of frames.
+	int (*draw_func)(mglBase *gr, void *par);
+	mglDraw *draw_cl;
+	int last_id;					///< last selected object id
+
+	const Fl_Menu_Item *popup;	///< pointer to popup menu items
+	Fl_Widget *wpar;			///< widget for popup menu
+	void *vpar;					///< parameter for popup menu
+	mreal tet,phi;				///< rotation angles
+	bool rotate;				///< flag for handle mouse
+	bool zoom;					///< flag for zoom by mouse
+	bool grid;					///< flag to draw grid and edit prim
+	bool show_warn;				///< show window with warnings
+	bool handle_keys;
+	mreal x1,x2,y1,y2;			///< zoom region
+	int flag;					///< bitwise flag for general state (1-Alpha, 2-Light)
+	int x0,y0,xe,ye;			///< mouse position
+	char pos[128];
+	bool run;					///< flag that drawing in progress
+	const unsigned char *img;	///< image for drawing
+#if (MGL_HAVE_PTHREAD|MGL_HAVE_PTHR_WIDGET)
+	pthread_t thr;				///< main thread for drawing
+#endif
+
+	virtual void draw();		///< quick drawing function
+	int handle(int code);		///< handle mouse events
+	void resize(int x, int y, int w, int h);	///< resize control
+};
+//-----------------------------------------------------------------------------
+class MGL_EXPORT Fl_MGLView : public Fl_Window
+{
+public:
+	Fl_MathGL *FMGL;		///< Control which draw graphics
+	Fl_Scroll *scroll;
+	Fl_Menu_Bar	*menu;
+
+	void *par;				///< Parameter for handling animation
+	void (*next)(void*);	///< Callback function for next frame
+	void (*prev)(void*);	///< Callback function for prev frame
+	mreal (*delay)(void*);	///< Callback function for delay
+	void (*reload)(void*);	///< Callback function for reloading
+
+	void toggle_alpha()	{	toggle(alpha, alpha_bt, _("Graphics/Alpha"));	}
+	void toggle_light()	{	toggle(light, light_bt, _("Graphics/Light"));	}
+	void toggle_sshow()	{	toggle(sshow, anim_bt, _("Graphics/Animation/Slideshow"));	}
+	void toggle_grid()	{	toggle(grid, grid_bt, _("Graphics/Grid"));	}
+	void toggle_zoom()	{	toggle(zoom, zoom_bt);	}
+	void toggle_rotate(){	toggle(rotate, rotate_bt);	}
+	void setoff_zoom()	{	setoff(zoom, zoom_bt);	}
+	void setoff_rotate(){	setoff(rotate, rotate_bt);	}
+	bool is_sshow()		{	return sshow;	}
+	void toggle_pause()	{	toggle(pauseC, pause_bt, _("Graphics/Pause calc"));	exec_pause();	}
+	void adjust()
+	{	mgl_set_size(FMGL->get_graph(),scroll->w(),scroll->h());	FMGL->size(scroll->w(),scroll->h());	update();	}
+	HMGL get_graph()	{	return FMGL->get_graph();	}
+
+	Fl_MGLView(int x, int y, int w, int h, const char *label=0);
+	virtual ~Fl_MGLView();
+	void update();			///< Update picture by calling user drawing function
+protected:
+	Fl_Button *alpha_bt, *light_bt, *rotate_bt, *anim_bt, *zoom_bt, *grid_bt, *pause_bt;
+//	Fl_Counter *tet, *phi;
+
+	int grid, alpha, light;	///< Current states of wire, alpha, light switches (toggle buttons)
+	int sshow, rotate, zoom;///< Current states of slideshow, rotate, zoom switches (toggle buttons)
+	int pauseC;	///< Current state of pause for calculations
+
+	void toggle(int &val, Fl_Button *b, const char *txt=NULL);
+	void setoff(int &val, Fl_Button *b, const char *txt=NULL);
+	void exec_pause();
+};
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_makemenu_fltk(Fl_Menu_ *m, Fl_MGLView *w);
+MGL_EXPORT const char *mgl_file_chooser(const char *mess, const char *filter="", bool save=false);
+MGL_EXPORT const char *mgl_dir_chooser(const char *mess, const char *path);
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/abstract.h b/include/mgl2/abstract.h
new file mode 100644
index 0000000..f689baf
--- /dev/null
+++ b/include/mgl2/abstract.h
@@ -0,0 +1,330 @@
+/***************************************************************************
+ * abstract.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_ABSTRACT_H_
+#define _MGL_ABSTRACT_H_
+
+#include "mgl2/define.h"
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+#include "mgl2/type.h"
+#define MGL_TO_WCS(str,code)	if(str && *str){size_t s=mbstowcs(0,str,0); wchar_t *wcs=new wchar_t[s+1]; mbstowcs(wcs,str,s); wcs[s]=0; code; delete []wcs;}else{const wchar_t *wcs=L""; code;}
+//-----------------------------------------------------------------------------
+class mglBase;
+class mglData;
+class mglDataA;
+class mglDataC;
+class mglParser;
+class mglFormula;
+class mglFormulaC;
+class mglFont;
+typedef mglBase* HMGL;
+typedef mglData* HMDT;
+typedef mglDataC* HADT;
+typedef mglParser* HMPR;
+typedef mglFormula* HMEX;
+typedef mglFormulaC* HAEX;
+typedef const mglDataA* HCDT;
+
+std::string MGL_EXPORT mgl_data_to_string(HCDT d, long ns);
+std::string MGL_EXPORT mgl_datac_to_string(HCDT d, long ns);
+/// Get section separated by symbol ch. This is analog of QString::section().
+std::string MGL_EXPORT mgl_str_arg(const std::string &str, char ch, int n1, int n2=-1);
+/// Get sections separated by symbol ch
+std::vector<std::string> MGL_EXPORT mgl_str_args(const std::string &str, char ch);
+/// Get string from real number
+std::string MGL_EXPORT mgl_str_num(double val);
+/// Get string from complex number
+std::string MGL_EXPORT mgl_str_num(dual val);
+
+extern "C" {
+
+#else
+#define mglDataA void
+typedef void *HMGL;
+typedef void *HMDT;
+typedef void *HADT;
+typedef void *HMEX;
+typedef void *HAEX;
+typedef void *HMPR;
+typedef const void *HCDT;
+#endif
+
+/// Set seed for random numbers
+void MGL_EXPORT mgl_srnd(long seed);
+void MGL_EXPORT mgl_srnd_(int *seed);
+/// Get random number
+double MGL_EXPORT mgl_rnd();
+double MGL_EXPORT mgl_rnd_();
+
+/// Set name for data variable (can be used in mgl_formula_calc() or in MGL scripts)
+void MGL_EXPORT mgl_data_set_name(mglDataA *dat, const char *name);
+void MGL_EXPORT mgl_data_set_name_(uintptr_t *dat, const char *name,int);
+void MGL_EXPORT mgl_data_set_name_w(mglDataA *dat, const wchar_t *name);
+/// Set callback function which is called at deleting variable
+void MGL_EXPORT mgl_data_set_func(mglDataA *dat, void (*func)(void *), void *par);
+
+/// Save whole data array (for ns=-1) or only ns-th slice to text file
+void MGL_EXPORT mgl_data_save(HCDT dat, const char *fname,long ns);
+void MGL_EXPORT mgl_data_save_(uintptr_t *dat, const char *fname,int *ns,int);
+/// Export data array (for ns=-1) or only ns-th slice to PNG file according color scheme
+void MGL_EXPORT mgl_data_export(HCDT dat, const char *fname, const char *scheme,mreal v1,mreal v2,long ns);
+void MGL_EXPORT mgl_data_export_(uintptr_t *dat, const char *fname, const char *scheme,mreal *v1,mreal *v2,int *ns,int,int);
+/// Save data to HDF file
+void MGL_EXPORT mgl_data_save_hdf(HCDT d,const char *fname,const char *data,int rewrite);
+void MGL_EXPORT mgl_data_save_hdf_(uintptr_t *d, const char *fname, const char *data, int *rewrite,int l,int n);
+/// Get information about the data (sizes and momentum) to string
+MGL_EXPORT const char *mgl_data_info(HCDT dat);
+int MGL_EXPORT mgl_data_info_(uintptr_t *dat, char *out, int len);
+/// Put HDF data names into buf as '\t' separated.
+long MGL_EXPORT mgl_datas_hdf(const char *fname, char *buf, long size);
+long MGL_EXPORT mgl_datas_hdf_(const char *fname, char *buf, int l, int size);
+/// Put HDF data names as list of strings (last one is "").
+MGL_EXPORT const char * const * mgl_datas_hdf_str(const char *fname);
+
+/// Get maximal value of the data
+mreal MGL_EXPORT mgl_data_max(HCDT dat);
+mreal MGL_EXPORT mgl_data_max_(uintptr_t *dat);
+/// Get maximal value of the data which is less than 0
+mreal MGL_EXPORT mgl_data_neg_max(HCDT dat);
+mreal MGL_EXPORT mgl_data_neg_max_(uintptr_t *dat);
+/// Get minimal value of the data
+mreal MGL_EXPORT mgl_data_min(HCDT dat);
+mreal MGL_EXPORT mgl_data_min_(uintptr_t *dat);
+/// Get minimal value of the data which is larger than 0
+mreal MGL_EXPORT mgl_data_pos_min(HCDT dat);
+mreal MGL_EXPORT mgl_data_pos_min_(uintptr_t *dat);
+/// Find position (after specified in i,j,k) of first nonzero value of formula
+mreal MGL_EXPORT mgl_data_first(HCDT dat, const char *cond, long *i, long *j, long *k);
+mreal MGL_EXPORT mgl_data_first_(uintptr_t *dat, const char *cond, int *i, int *j, int *k, int);
+/// Find position (before specified in i,j,k) of last nonzero value of formula
+mreal MGL_EXPORT mgl_data_last(HCDT dat, const char *cond, long *i, long *j, long *k);
+mreal MGL_EXPORT mgl_data_last_(uintptr_t *dat, const char *cond, int *i, int *j, int *k, int);
+/// Find position of first in direction 'dir' nonzero value of formula
+long MGL_EXPORT mgl_data_find(HCDT dat, const char *cond, char dir, long i, long j, long k);
+int MGL_EXPORT mgl_data_find_(uintptr_t *dat, const char *cond, char *dir, int *i, int *j, int *k, int,int);
+/// Find if any nonzero value of formula
+int MGL_EXPORT mgl_data_find_any(HCDT dat, const char *cond);
+int MGL_EXPORT mgl_data_find_any_(uintptr_t *dat, const char *cond, int);
+/// Get maximal value of the data and its position
+mreal MGL_EXPORT mgl_data_max_int(HCDT dat, long *i, long *j, long *k);
+mreal MGL_EXPORT mgl_data_max_int_(uintptr_t *dat, int *i, int *j, int *k);
+/// Get maximal value of the data and its approximated position
+mreal MGL_EXPORT mgl_data_max_real(HCDT dat, mreal *x, mreal *y, mreal *z);
+mreal MGL_EXPORT mgl_data_max_real_(uintptr_t *dat, mreal *x, mreal *y, mreal *z);
+/// Get minimal value of the data and its position
+mreal MGL_EXPORT mgl_data_min_int(HCDT dat, long *i, long *j, long *k);
+mreal MGL_EXPORT mgl_data_min_int_(uintptr_t *dat, int *i, int *j, int *k);
+/// Get minimal value of the data and its approximated position
+mreal MGL_EXPORT mgl_data_min_real(HCDT dat, mreal *x, mreal *y, mreal *z);
+mreal MGL_EXPORT mgl_data_min_real_(uintptr_t *dat, mreal *x, mreal *y, mreal *z);
+/// Get "energy and find 4 momenta of data: median, width, skewness, kurtosis
+mreal MGL_EXPORT mgl_data_momentum_val(HCDT d, char dir, mreal *m, mreal *w, mreal *s, mreal *k);
+mreal MGL_EXPORT mgl_data_momentum_val_(uintptr_t *dat, char *dir, mreal *m, mreal *w, mreal *s, mreal *k,int);
+/// Get first (last if from<0) maximum along direction dir, and save its orthogonal coordinates in p1, p2
+long MGL_EXPORT mgl_data_max_first(HCDT d, char dir, long from, long *p1, long *p2);
+long MGL_EXPORT mgl_data_max_first_(uintptr_t *d, const char *dir, long *from, long *p1, long *p2,int);
+
+/// Interpolate by linear function the data to given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+mreal MGL_EXPORT mgl_data_linear(HCDT dat, mreal x,mreal y,mreal z);
+mreal MGL_EXPORT mgl_data_linear_(uintptr_t *dat, mreal *x,mreal *y,mreal *z);
+/// Interpolate by linear function the data and return its derivatives at given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+mreal MGL_EXPORT mgl_data_linear_ext(HCDT dat, mreal x,mreal y,mreal z, mreal *dx,mreal *dy,mreal *dz);
+mreal MGL_EXPORT mgl_data_linear_ext_(uintptr_t *dat, mreal *x,mreal *y,mreal *z, mreal *dx,mreal *dy,mreal *dz);
+
+/// Internal function for (un-)locking mutex in mglStack
+void MGL_EXPORT mgl_mutex_lock(void *);
+void MGL_EXPORT mgl_mutex_unlock(void *);
+
+//-----------------------------------------------------------------------------
+/// Callback function for asking user a question. Result shouldn't exceed 1024.
+extern MGL_EXPORT void (*mgl_ask_func)(const wchar_t *quest, wchar_t *res);
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+}
+//-----------------------------------------------------------------------------
+/// Structure for the number handling (see mglParse class).
+struct MGL_EXPORT mglNum
+{
+	mreal d;		///< Number itself
+	dual c;
+	std::wstring s;	///< Number name
+	mglNum(mreal val=0):d(val),c(val)	{}
+	mglNum(const mglNum &n):d(n.d),c(n.c),s(n.s) {}
+	const mglNum &operator=(const mglNum &n)
+	{	d=n.d;	c=n.c;	s=n.s;	return n;	}
+};
+//-----------------------------------------------------------------------------
+/// Abstract class for data array
+class MGL_EXPORT mglDataA
+{
+public:
+	std::wstring s;	///< Data name
+	bool temp;		///< This is temporary variable
+	void (*func)(void *);	///< Callback function for destroying
+	void *o; 		///< Pointer to external object
+
+	mglDataA()	{	temp=false;	func=0;	o=0;	}
+	virtual ~mglDataA()	{	if(func)	func(o);	}
+	virtual void set_v(mreal /*val*/, long /*i*/,long /*j*/=0,long /*k*/=0)	{}
+	/// Get the interpolated value and its derivatives in given data cell without border checking
+	virtual mreal valueD(mreal x,mreal y=0,mreal z=0,mreal *dx=0,mreal *dy=0,mreal *dz=0) const =0;
+	/// Get the interpolated value in given data cell without border checking
+	virtual mreal value(mreal x,mreal y=0,mreal z=0) const =0;
+	/// Interpolate by linear function the data to given point
+	inline mreal linear(mreal x,mreal y=0,mreal z=0)	const
+	{	return mgl_data_linear_ext(this,x,y,z,0,0,0);	}
+	/// Interpolate by linear function the data to given point and get the gradient
+	inline mreal linearD(mreal x,mreal y=0,mreal z=0,mreal *dx=0,mreal *dy=0,mreal *dz=0)	const
+	{	return mgl_data_linear_ext(this,x,y,z,dx,dy,dz);	}
+	virtual mreal v(long i,long j=0,long k=0) const = 0;
+	virtual mreal vthr(long i) const
+	{	return v(i%GetNx(), (i/GetNx())%GetNy(), i/(GetNx()*GetNy()));	}
+	virtual dual vc(long i,long j=0,long k=0) const	{	return v(i,j,k);	}
+	virtual dual vcthr(long i) const	{	return vthr(i);	}
+	virtual long GetNx() const = 0;
+	virtual long GetNy() const = 0;
+	virtual long GetNz() const = 0;
+	inline long GetNN() const {	return GetNx()*GetNy()*GetNz();	}
+	virtual mreal dvx(long i,long j=0,long k=0) const = 0;
+//	{	return i>0 ? (i<GetNx()-1 ? (v(i+1,j,k)-v(i-1,j,k))/2 : v(i,j,k)-v(i-1,j,k)) : v(1,j,k)-v(0,j,k);	}
+	virtual mreal dvy(long i,long j=0,long k=0) const = 0;
+//	{	return j>0 ? (j<GetNy()-1 ? (v(i,j+1,k)-v(i,j-1,k))/2 : v(i,j,k)-v(i,j-1,k)) : v(i,1,k)-v(i,0,k);	}
+	virtual mreal dvz(long i,long j=0,long k=0) const = 0;
+//	{	return k>0 ? (k<GetNz()-1 ? (v(i,j,k+1)-v(i,j,k-1))/2 : v(i,j,k)-v(i,j,k-1)) : v(i,j,1)-v(i,j,0);	}
+
+	// Now some common function which applicable for most of data types
+	/// Save whole data array (for ns=-1) or only ns-th slice to text file
+	virtual void Save(const char *fname,long ns=-1) const
+	{	mgl_data_save(this,fname,ns);	}
+	/// Get whole data array (for ns=-1) or only ns-th slice to string
+	virtual std::string Get(long ns=-1) const
+	{	return mgl_data_to_string(this,ns);	}
+	/// Export data array (for ns=-1) or only ns-th slice to PNG file according color scheme
+	inline void Export(const char *fname,const char *scheme,mreal v1=0,mreal v2=0,long ns=-1) const
+	{	mgl_data_export(this,fname,scheme,v1,v2,ns);	}
+	/// Save data to HDF file
+	virtual void SaveHDF(const char *fname,const char *data,bool rewrite=false) const
+	{	mgl_data_save_hdf(this,fname,data,rewrite);	}
+	/// Put HDF data names into buf as '\t' separated.
+	inline static int DatasHDF(const char *fname, char *buf, long size)
+	{	return mgl_datas_hdf(fname,buf,size);	}
+	/// Put HDF data names as list of strings (last one is "").
+	inline static const char * const * DatasHDF(const char *fname)
+	{	return mgl_datas_hdf_str(fname);	}
+
+	/// Get information about the data (sizes and momentum) to string
+	inline const char *PrintInfo() const	{	return mgl_data_info(this);	}
+	/// Print information about the data (sizes and momentum) to FILE (for example, stdout)
+	inline void PrintInfo(FILE *fp) const
+	{	if(fp)	{	fprintf(fp,"%s",mgl_data_info(this));	fflush(fp);	}	}
+	/// Get maximal value of the data
+	virtual mreal Maximal() const	{	return mgl_data_max(this);	}
+	/// Get minimal value of the data
+	virtual mreal Minimal() const	{	return mgl_data_min(this);	}
+	/// Get maximal value of the data which is less than 0
+	inline mreal MaximalNeg() const	{	return mgl_data_neg_max(this);	}
+	/// Get minimal value of the data which is larger than 0
+	inline mreal MinimalPos() const	{	return mgl_data_pos_min(this);	}
+	/// Get maximal value of the data and its position
+	inline mreal Maximal(long &i,long &j,long &k) const
+	{	return mgl_data_max_int(this,&i,&j,&k);	}
+	/// Get minimal value of the data and its position
+	inline mreal Minimal(long &i,long &j,long &k) const
+	{	return mgl_data_min_int(this,&i,&j,&k);	}
+	/// Get maximal value of the data and its approximated position
+	inline mreal Maximal(mreal &x,mreal &y,mreal &z) const
+	{	return mgl_data_max_real(this,&x,&y,&z);	}
+	/// Get minimal value of the data and its approximated position
+	inline mreal Minimal(mreal &x,mreal &y,mreal &z) const
+	{	return mgl_data_min_real(this,&x,&y,&z);	}
+	/// Get first (last if from<0) maximum along direction dir, and save its orthogonal coordinates in p1, p2
+	inline long Maximal(char dir, long from, long &p1, long &p2) const
+	{	return mgl_data_max_first(this,dir,from,&p1,&p2);	}
+	inline long Maximal(char dir, long from) const
+	{	return mgl_data_max_first(this,dir,from,0,0);	}
+	/// Get "energy" and find first (median) and second (width) momenta of data
+	inline mreal Momentum(char dir,mreal &m,mreal &w) const
+	{	return mgl_data_momentum_val(this,dir,&m,&w,0,0);	}
+	/// Get "energy and find 4 momenta of data: median, width, skewness, kurtosis
+	inline mreal Momentum(char dir,mreal &m,mreal &w,mreal &s,mreal &k) const
+	{	return mgl_data_momentum_val(this,dir,&m,&w,&s,&k);	}
+	/// Find position (after specified in i,j,k) of first nonzero value of formula
+	inline mreal Find(const char *cond, long &i, long &j, long &k) const
+	{	return mgl_data_first(this,cond,&i,&j,&k);	}
+	/// Find position (before specified in i,j,k) of last nonzero value of formula
+	inline mreal Last(const char *cond, long &i, long &j, long &k) const
+	{	return mgl_data_last(this,cond,&i,&j,&k);	}
+	/// Find position of first in direction 'dir' nonzero value of formula
+	inline long Find(const char *cond, char dir, long i=0, long j=0, long k=0) const
+	{	return mgl_data_find(this,cond,dir,i,j,k);	}
+	/// Find if any nonzero value of formula
+	inline bool FindAny(const char *cond) const
+	{	return mgl_data_find_any(this,cond);	}
+
+	/// Interpolate by cubic spline the data to given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+	inline mreal Spline(mreal x,mreal y=0,mreal z=0) const
+	{	return value(x,y,z);	}
+	/// Interpolate by cubic spline the data to given point x,\a y,\a z which normalized in range [0, 1]
+	inline mreal Spline1(mreal x,mreal y=0,mreal z=0) const
+	{	return value(x*(GetNx()-1),y*(GetNy()-1),z*(GetNz()-1));	}
+	/// Interpolate by cubic spline the data and return its derivatives at given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+	inline mreal Spline(mglPoint &dif, mreal x,mreal y=0,mreal z=0) const
+	{	return valueD(x,y,z, &(dif.x),&(dif.y), &(dif.z));	}
+	/// Interpolate by cubic spline the data and return its derivatives at given point x,\a y,\a z which normalized in range [0, 1]
+	inline mreal Spline1(mglPoint &dif, mreal x,mreal y=0,mreal z=0) const
+	{	mreal res=valueD(x*(GetNx()-1),y*(GetNy()-1),z*(GetNz()-1), &(dif.x),&(dif.y), &(dif.z));
+		dif.x*=GetNx()>1?GetNx()-1:1;	dif.y*=GetNy()>1?GetNy()-1:1;	dif.z*=GetNz()>1?GetNz()-1:1;	return res;	}
+
+	/// Interpolate by linear function the data to given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+	inline mreal Linear(mreal x,mreal y=0,mreal z=0)	const
+	{	return mgl_data_linear_ext(this,x,y,z,0,0,0);	}
+	/// Interpolate by line the data to given point x,\a y,\a z which normalized in range [0, 1]
+	inline mreal Linear1(mreal x,mreal y=0,mreal z=0) const
+	{	return mgl_data_linear_ext(this,x*(GetNx()-1),y*(GetNy()-1),z*(GetNz()-1),0,0,0);	}
+	/// Interpolate by linear function the data and return its derivatives at given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+	inline mreal Linear(mglPoint &dif, mreal x,mreal y=0,mreal z=0)	const
+	{	return mgl_data_linear_ext(this,x,y,z, &(dif.x),&(dif.y), &(dif.z));	}
+	/// Interpolate by line the data and return its derivatives at given point x,\a y,\a z which normalized in range [0, 1]
+	inline mreal Linear1(mglPoint &dif, mreal x,mreal y=0,mreal z=0) const
+	{	mreal res=mgl_data_linear_ext(this,x*(GetNx()-1),y*(GetNy()-1),z*(GetNz()-1), &(dif.x),&(dif.y), &(dif.z));
+		dif.x*=GetNx()>1?GetNx()-1:1;	dif.y*=GetNy()>1?GetNy()-1:1;	dif.z*=GetNz()>1?GetNz()-1:1;	return res;	}
+};
+//-----------------------------------------------------------------------------
+/// Structure for color ID
+struct MGL_EXPORT mglColorID
+{
+	char id;
+	mglColor col;
+};
+MGL_EXPORT extern mglColorID mglColorIds[31];
+MGL_EXPORT extern std::string mglGlobalMess;	///< Buffer for receiving global messages
+//-----------------------------------------------------------------------------
+#endif
+
+#ifdef MGL_SRC
+#define _Da_(d)	(*((const mglDataA *)(d)))
+#define _DA_(a)	((const mglDataA *)*(a))
+#define _GR_	((mglBase *)(*gr))
+//#define _D_(d)	*((mglData *)*(d))
+#define _DM_(a)	((mglData *)*(a))
+#define _DT_	((mglData *)*d)
+#endif
+
+#endif
diff --git a/include/mgl2/addon.h b/include/mgl2/addon.h
new file mode 100644
index 0000000..2e9d98f
--- /dev/null
+++ b/include/mgl2/addon.h
@@ -0,0 +1,63 @@
+/***************************************************************************
+ * addon.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_ADDON_H_
+#define _MGL_ADDON_H_
+//-----------------------------------------------------------------------------
+#include "mgl2/define.h"
+#ifdef __cplusplus
+//-----------------------------------------------------------------------------
+/// Explicit scheme for 1 step of axial diffraction
+void MGL_EXPORT mgl_difr_axial(dual *a,int n,int step,dual q,int Border,dual *tmp,int kk, double di);
+void MGL_EXPORT mgl_difr_axial_old(dual *a,int n,int step,dual q,int Border,dual *tmp1,dual *tmp2,int kk, double di);	// restore for backward compatibility
+/// Explicit scheme for 1 step of plane diffraction
+void MGL_EXPORT mgl_difr_grid(dual *a,int n,int step,dual q,int Border,dual *tmp,int kk);
+void MGL_EXPORT mgl_difr_grid_old(dual *a,int n,int step,dual q,int Border,dual *tmp1,dual *tmp2,int kk);	// restore for backward compatibility
+//-----------------------------------------------------------------------------
+extern "C" {
+#endif
+/// Get random number with Gaussian distribution
+double MGL_EXPORT mgl_gauss_rnd();
+/// Fill frequencies for FFT
+void MGL_EXPORT mgl_fft_freq(double *freq,long nn);
+
+/// Remove double spaces from the string
+void MGL_EXPORT mgl_strcls(char *str);
+/// Get position of substring or return -1 if not found
+long MGL_EXPORT mgl_strpos(const char *str,char *fnd);
+/// Get position of symbol or return -1 if not found
+long MGL_EXPORT mgl_chrpos(const char *str,char fnd);
+
+/// Get uncommented string from file (NOTE: it is not thread safe!!!)
+MGL_EXPORT char *mgl_fgetstr(FILE *fp);
+/// Get parameters from uncommented strings of file (NOTE: it is not thread safe!!!)
+void MGL_EXPORT mgl_fgetpar(FILE *fp, const char *str, ...);
+/// Check if symbol denote true
+int MGL_EXPORT_CONST mgl_istrue(char ch);
+/// Print test message
+void MGL_EXPORT mgl_test(const char *str, ...);
+/// Print info message
+void MGL_EXPORT mgl_info(const char *str, ...);
+/// Locate next data block (block started by -----)
+MGL_EXPORT FILE *mgl_next_data(const char *fname,int p);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/mgl2/base.h b/include/mgl2/base.h
new file mode 100644
index 0000000..13594a3
--- /dev/null
+++ b/include/mgl2/base.h
@@ -0,0 +1,710 @@
+/***************************************************************************
+ * base.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_BASE_H_
+#define _MGL_BASE_H_
+//#if !defined(_MSC_VER) && !defined(__BORLANDC__)
+#include "mgl2/abstract.h"
+
+#ifdef __cplusplus
+
+#if (MGL_HAVE_PTHREAD|MGL_HAVE_PTHR_WIDGET)
+#include <pthread.h>
+#endif
+
+#if MGL_HAVE_PTHREAD
+#define MGL_PUSH(a,v,m)	{pthread_mutex_lock(&m);	a.push_back(v);	pthread_mutex_unlock(&m);}
+#else
+#define MGL_PUSH(a,v,m)	a.push_back(v);
+#endif
+//-----------------------------------------------------------------------------
+inline mreal mgl_d(mreal v,mreal v1,mreal v2) { return v2!=v1?(v-v1)/(v2-v1):NAN; }
+//-----------------------------------------------------------------------------
+mglPoint GetX(HCDT x, int i, int j, int k=0);
+mglPoint GetY(HCDT y, int i, int j, int k=0);
+mglPoint GetZ(HCDT z, int i, int j, int k=0);
+//-----------------------------------------------------------------------------
+/// Class for replacement of std::vector
+// NOTE memcpy is used --> no memory allocation in T
+template <class T> class mglStack
+{
+	T** dat;
+	size_t pb;	///< size of buffer (real size is 2^pb == 1L<<pb)
+	size_t np;	///< allocated pointers
+	size_t m;	///< used pointers (allocated size is m*nb)
+	size_t n;	///< used cells
+	void *mutex;
+public:
+	mglStack(const mglStack<T> &st)
+	{	np=st.np;	dat = (T**)malloc(np*sizeof(T*));
+		pb=st.pb;	m=n=0;	reserve(st.n);
+		for(size_t i=0;i<m;i++)	memcpy(dat[i],st.dat[i],((size_t)1<<pb)*sizeof(T));
+		n=st.n;		mutex = 0;	}
+	mglStack(size_t Pbuf=10)
+	{	np=16;	pb=Pbuf;	dat = (T**)malloc(np*sizeof(T*));
+		dat[0] = new T[(size_t)1<<pb];	n=0;	m=1;	mutex = 0;	}
+	~mglStack()	{	clear();	delete [](dat[0]);	free(dat);	}
+	inline void set_mutex(void *mtx)	{	mutex = mtx;	}
+	void reserve(size_t num)
+	{
+		num+=n;
+		if(num>(m<<pb))
+		{
+			num = 1+ (num>>pb);
+			if(num>np)
+			{	dat = (T**)realloc(dat, num*sizeof(T*));	np=num;	}
+			for(size_t i=m;i<num;i++)	dat[i] = new T[(size_t)1<<pb];
+			m = num;
+		}
+	}
+	void clear()
+	{
+		if(mutex)	mgl_mutex_lock(mutex);
+		for(size_t i=0;i<m;i++)	delete [](dat[i]);
+		dat[0] = new T[(size_t)1<<pb];	n=0;	m=1;
+		if(mutex)	mgl_mutex_unlock(mutex);
+	}
+	T &operator[](size_t i)	{	size_t d=i>>pb;	return dat[d][i-(d<<pb)];	}
+	const T &operator[](size_t i)	const	{	size_t d=i>>pb;	return dat[d][i-(d<<pb)];	}
+	void push_back(const T &t)
+	{
+		if(n>=(m<<pb))	reserve(1);
+		size_t d=n>>pb;
+		dat[d][n-(d<<pb)] = t;	n++;
+	}
+	size_t size()	const	{	return n;	}
+	const mglStack<T> &operator=(const mglStack<T> &st)
+	{
+		pb=st.pb;	clear();	reserve(st.n);
+		for(size_t i=0;i<st.m && i<m;i++)	memcpy(dat[i],st.dat[i],((size_t)1<<pb)*sizeof(T));
+		n = st.n;	return st;
+	}
+};
+//-----------------------------------------------------------------------------
+/// Structure for transformation matrix
+struct MGL_EXPORT mglMatrix
+{
+	mreal b[9];
+	mreal x,y,z,pf;
+	bool norot;	// flag to disable pnts rotation
+	mglMatrix()	{	memset(this,0,sizeof(mglMatrix));	clear();	}
+	mglMatrix(const mglMatrix &aa) : x(aa.x),y(aa.y),z(aa.z),pf(aa.pf),norot(aa.norot) 	{	memcpy(b,aa.b,9*sizeof(mreal));	}
+	void Rotate(mreal tetz,mreal tetx,mreal tety);
+	void RotateN(mreal Tet,mreal x,mreal y,mreal z);
+	inline void clear()	{	x=y=z=pf=0;	memset(b,0,9*sizeof(mreal));	b[0]=b[4]=b[8]=1;	norot=false;	}
+	inline const mglMatrix &operator=(const mglMatrix &a)
+	{	x=a.x;	y=a.y;	z=a.z;	pf=a.pf;	memcpy(b,a.b,9*sizeof(mreal));	norot=false;	return a;	}
+};
+inline bool operator==(const mglMatrix &a, const mglMatrix &b)
+{	return ((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z)+(a.pf-b.pf)*(a.pf-b.pf)==0)&&!memcmp(b.b,a.b,9*sizeof(mreal));}
+inline bool operator!=(const mglMatrix &a, const mglMatrix &b)
+{	return ((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z)+(a.pf-b.pf)*(a.pf-b.pf)!=0)||memcmp(b.b,a.b,9*sizeof(mreal));	}
+//-----------------------------------------------------------------------------
+/// Structure for simplest primitives
+struct MGL_EXPORT mglPrim	// NOTE: use float for reducing memory size
+{
+	// NOTE: n4 is used as mark; n3 -- as pen style for type=0,1,4
+	// NOTE: n3 is used as position of txt,font in Ptxt for type=6
+	long n1,n2,n3,n4;	///< coordinates of corners
+	short type;	///< primitive type (0-point, 1-line, 2-trig, 3-quad, 4-glyph, 6-text)
+	short angl;	///< rotation angle for mask
+	int id;		///< object id
+	float z;	///< z-position
+	float w;	///< width (if applicable) or ftet
+	union
+	{
+		struct
+		{
+			float s;		///< size (if applicable) or fscl
+			float p;
+		};
+		uint64_t m;
+	};
+	mglPrim(int t=0):n1(0),n2(0),n3(0),n4(0),type(t),angl(0),id(0),z(0),w(0),m(0)	{}
+	mglPrim(const mglPrim &aa) : n1(aa.n1),n2(aa.n2),n3(aa.n3),n4(aa.n4),type(aa.type),angl(aa.angl),id(aa.id),z(aa.z),w(aa.w),m(aa.m) 	{}
+	const mglPrim &operator=(const mglPrim &aa)	{	memcpy(this, &aa, sizeof(mglPrim));	return aa;	}
+};
+bool operator<(const mglPrim &a,const mglPrim &b);
+bool operator>(const mglPrim &a,const mglPrim &b);
+//-----------------------------------------------------------------------------
+/// Structure for light source
+struct MGL_EXPORT mglLight
+{
+	mglLight():n(false),a(0),b(0)	{}
+	mglLight(const mglLight &aa) : n(aa.n),d(aa.d),r(aa.r),q(aa.q),p(aa.p),a(aa.a),b(aa.b),c(aa.c)	{}
+	const mglLight &operator=(const mglLight &aa)
+	{	memcpy(this,&aa,sizeof(mglLight));	return aa;	}
+
+	bool n;			///< Availability of light sources
+	mglPoint d;		///< Direction of light sources
+	mglPoint r;		///< Position of light sources (NAN for infinity)
+	mglPoint q;		///< Actual position of light sources (filled by LightScale() function)
+	mglPoint p;		///< Actual direction of light sources (filled by LightScale() function)
+	mreal a;		///< Aperture of light sources
+	mreal b;		///< Brightness of light sources
+	mglColor c;		///< Color of light sources
+};
+//-----------------------------------------------------------------------------
+/// Structure for inplot
+struct MGL_EXPORT mglBlock
+{
+	int id;		///< object id
+	long n1,n2,n3,n4;	///< coordinates of corners {n1=x1,n2=x2,n3=y1,n4=y2}
+
+	mglLight light[10];	///< Light sources
+	mreal AmbBr;		///< Default ambient light brightness
+	mreal DifBr;		///< Default diffusive light brightness
+	mglMatrix B;		///< Transformation matrix
+
+	mglBlock():id(0),n1(0),n2(0),n3(0),n4(0),AmbBr(0.5),DifBr(0.5)	{}
+	mglBlock(const mglBlock &aa)	{	memcpy(this, &aa, sizeof(mglBlock));	}
+	const mglBlock &operator=(const mglBlock &aa)	{	memcpy(this, &aa, sizeof(mglBlock));	return aa;	}
+};
+//-----------------------------------------------------------------------------
+/// Structure for group of primitives
+struct MGL_EXPORT mglGroup
+{
+	std::vector<long> p;	///< list of primitives (not filled!!!)
+	int Id;					///< Current list of primitives
+	std::string Lbl;		///< Group label
+	mglGroup(const char *lbl="", int id=0) : Id(id), Lbl(lbl)	{}
+	mglGroup(const mglGroup &aa) : p(aa.p),Id(aa.Id),Lbl(aa.Lbl)	{}
+#if MGL_HAVE_RVAL
+	mglGroup(mglGroup &&aa) : p(aa.p),Id(aa.Id),Lbl(aa.Lbl)	{}
+#endif
+	inline const mglGroup &operator=(const mglGroup &aa)	{	Lbl = aa.Lbl;	Id = aa.Id;	p = aa.p;	return aa;	}
+};
+//-----------------------------------------------------------------------------
+/// Structure for text label
+struct MGL_EXPORT mglText
+{
+	std::wstring text;
+	std::string stl;
+	mreal val;
+	mglText(const wchar_t *txt=L"", const char *fnt="", mreal v=0) : text(txt), stl(fnt), val(v) {}
+	mglText(const std::wstring &txt, mreal v=0): text(txt), val(v)	{}
+	mglText(const mglText &aa) : text(aa.text),stl(aa.stl),val(aa.val)	{}
+#if MGL_HAVE_RVAL
+	mglText(mglText &&aa) : text(aa.text),stl(aa.stl),val(aa.val)	{}
+#endif
+	const mglText&operator=(const mglText &aa)	{ text=aa.text;	stl=aa.stl;	val=aa.val;	return aa;	}
+};
+//-----------------------------------------------------------------------------
+/// Structure for internal point representation
+struct MGL_EXPORT mglPnt	// NOTE: use float for reducing memory size
+{
+	union {	float dat[16];	struct {
+		float x,y,z;	// coordinates
+		float u,v,w;	// normales
+		float r,g,b,a;	// RGBA color
+		float xx,yy,zz;	// original coordinates
+		float c,t,ta;	// index in color scheme
+	}; };
+	short sub;		// subplot id and rotation information (later will be in subplot)
+	mglPnt(float X, float Y=0, float Z=0, float U=0, float V=0, float W=0, float R=0, float G=0, float B=0, float A=0):x(X),y(Y),z(Z),u(U),v(V),w(W),r(R),g(G),b(B),a(A),xx(X),yy(Y),zz(Z),c(0),t(0),ta(0),sub(0)	{}
+	mglPnt():x(0),y(0),z(0),u(0),v(0),w(0),r(0),g(0),b(0),a(0),xx(0),yy(0),zz(0),c(0),t(0),ta(0),sub(0)	{}
+	mglPnt(const mglPnt &aa) : sub(aa.sub)	{	memcpy(dat,aa.dat,16*sizeof(float));	}
+	inline const mglPnt&operator=(const mglPnt &aa)	{ sub=aa.sub;	memcpy(dat,aa.dat,16*sizeof(float));	return aa;	}
+	inline bool same(const mglPnt &p, mreal d)	const {	return fabs(x-p.x)<d && fabs(y-p.y)<d;	}
+};
+inline mglPnt operator+(const mglPnt &a, const mglPnt &b)
+{	mglPnt p;	for(long i=0;i<10;i++)	p.dat[i] = a.dat[i]+b.dat[i];	p.sub=a.sub;	return p;	}
+//{	return mglPnt(a.x+b.x,a.y+b.y,a.z+b.z, a.u+b.u,a.v+b.v,a.w+b.w, a.r+b.r,a.g+b.g,a.b+b.b,a.a+b.a);	}
+inline mglPnt operator-(const mglPnt &a, const mglPnt &b)
+{	mglPnt p;	for(long i=0;i<10;i++)	p.dat[i] = a.dat[i]-b.dat[i];	p.sub=a.sub;	return p;	}
+//{	return mglPnt(a.x-b.x,a.y-b.y,a.z-b.z, a.u-b.u,a.v-b.v,a.w-b.w, a.r-b.r,a.g-b.g,a.b-b.b,a.a-b.a);	}
+inline mglPnt operator*(const mglPnt &a, float b)
+{	mglPnt p;	for(long i=0;i<10;i++)	p.dat[i] = a.dat[i]*b;	p.sub=a.sub;	return p;	}
+//{	return mglPnt(a.x*b,a.y*b,a.z*b, a.u*b,a.v*b,a.w*b, a.r*b,a.g*b,a.b*b,a.a*b);	}
+inline mglPnt operator*(float b, const mglPnt &a)
+{	mglPnt p;	for(long i=0;i<10;i++)	p.dat[i] = a.dat[i]*b;	p.sub=a.sub;	return p;	}
+//{	return mglPnt(a.x*b,a.y*b,a.z*b, a.u*b,a.v*b,a.w*b, a.r*b,a.g*b,a.b*b,a.a*b);	}
+//-----------------------------------------------------------------------------
+/// Structure for glyph representation
+struct MGL_EXPORT mglGlyph
+{	// NOTE nt<0 is used to set char id for user-defined glyphs
+	long nt, nl;		///< number of triangles and lines
+	short *trig, *line;	///< vertexes of triangles and lines
+
+	mglGlyph():nt(0),nl(0),trig(0),line(0)	{}
+	mglGlyph(const mglGlyph &a):nt(0),nl(0),trig(0),line(0)	{	*this=a;	}
+	mglGlyph(long Nt, long Nl):nt(0),nl(0),trig(0),line(0)	{	Create(Nt,Nl);	}
+	~mglGlyph()	{	if(trig)	delete []trig;	if(line)	delete []line;	}
+
+	void Create(long Nt, long Nl);
+	bool operator==(const mglGlyph &g) const MGL_FUNC_PURE;
+	inline bool operator!=(const mglGlyph &g) const MGL_FUNC_PURE
+	{	return !(*this==g);	}
+	inline const mglGlyph &operator=(const mglGlyph &a)
+	{	Create(a.nt, a.nl);
+		if(a.trig)	memcpy(trig, a.trig, 6*nt*sizeof(short));
+		if(a.line)	memcpy(line, a.line, 2*nl*sizeof(short));
+		return a;	}
+};
+//-----------------------------------------------------------------------------
+#define MGL_TEXTURE_COLOURS 512
+/// Structure for texture (color scheme + palette) representation
+struct MGL_EXPORT mglTexture
+{
+	mglColor *col;	///< Colors itself
+	long n;				///< Number of initial colors along u
+
+	char Sch[260];		///< Color scheme used
+	int Smooth;			///< Type of texture (smoothing and so on)
+	mreal Alpha;			///< Transparency
+
+	mglTexture():n(0),Smooth(0),Alpha(1)
+	{	col = new mglColor[MGL_TEXTURE_COLOURS];	}
+	mglTexture(const char *cols, int smooth=0,mreal alpha=1):n(0)
+	{	col = new mglColor[MGL_TEXTURE_COLOURS];	Set(cols,smooth,alpha);	}
+	mglTexture(const mglTexture &aa) : n(aa.n),Smooth(aa.Smooth),Alpha(aa.Alpha)
+	{	col = new mglColor[MGL_TEXTURE_COLOURS];	memcpy(Sch,aa.Sch,260);
+		memcpy(col,aa.col,MGL_TEXTURE_COLOURS*sizeof(mglColor));	}
+#if MGL_HAVE_RVAL
+	mglTexture(mglTexture &&aa) : n(aa.n),Smooth(aa.Smooth),Alpha(aa.Alpha)
+	{	col = aa.col;	memcpy(Sch,aa.Sch,260);	aa.col=0;	}
+#endif
+	~mglTexture()	{	if(col)	delete []col;	}
+	void Clear()	{	n=0;	}
+	void Set(const char *cols, int smooth=0,mreal alpha=1);
+	void Set(HCDT val, const char *cols);
+	void GetC(mreal u,mreal v,mglPnt &p) const;
+	mglColor GetC(mreal u,mreal v=0) const MGL_FUNC_PURE;
+	inline bool IsSame(const mglTexture &t) const
+	{	return n==t.n && !memcmp(col,t.col,MGL_TEXTURE_COLOURS*sizeof(mglColor));	}
+	void GetRGBA(unsigned char *f) const;
+	void GetRGBAPRC(unsigned char *f) const;
+	void GetRGBAOBJ(unsigned char *f) const;	// Export repeating border colors, since OBJ by default wraps textures and we need an extra boundary to work around implementation quirks
+	inline const mglTexture &operator=(const mglTexture &aa)
+	{	n=aa.n;	Smooth=aa.Smooth;	Alpha=aa.Alpha;
+		memcpy(col,aa.col,MGL_TEXTURE_COLOURS*sizeof(mglColor));
+		memcpy(Sch,aa.Sch,260);	return aa;	}
+};
+//-----------------------------------------------------------------------------
+const mglColor NC(-1,-1,-1);
+const mglColor BC( 0, 0, 0);
+const mglColor WC( 1, 1, 1);
+const mglColor RC( 1, 0, 0);
+//-----------------------------------------------------------------------------
+/// Structure active points
+struct MGL_EXPORT mglActivePos
+{
+	int x,y;	///< coordinates of active point
+	int id;		///< object id for active point
+	int n;		///< position of active point in command (object id)
+};
+//-----------------------------------------------------------------------------
+#if defined(_MSC_VER)
+template class MGL_EXPORT mglStack<mglPnt>;
+template class MGL_EXPORT mglStack<mglPrim>;
+template class MGL_EXPORT std::vector<mglGroup>;
+template class MGL_EXPORT std::vector<mglText>;
+template class MGL_EXPORT std::vector<mglTexture>;
+template class MGL_EXPORT std::vector<mglGlyph>;
+template class MGL_EXPORT std::vector<mglBlock>;
+template class MGL_EXPORT std::vector<mglMatrix>;
+template class MGL_EXPORT mglStack<mglActivePos>;
+#endif
+//-----------------------------------------------------------------------------
+/// Base class for canvas which handle all basic drawing
+class MGL_EXPORT mglBase
+{
+public:
+	mglBase();
+	virtual ~mglBase();
+
+	mglPoint Min;		///< Lower edge of bounding box for graphics.
+	mglPoint Max;		///< Upper edge of bounding box for graphics.
+	mreal ZMin;			///< Adjusted minimal z-value 1D plots
+	std::string Mess;	///< Buffer for receiving messages
+	int ObjId;			///< object id for mglPrim
+	int HighId;			///< object id to be highlited
+	std::vector<mglGroup> Grp;	///< List of groups with names -- need for export
+	mglStack<mglActivePos> Act;	///< Position of active points
+	std::string PlotId;	///< Id of plot for saving filename (in GLUT window for example)
+	int BBoxX1, BBoxY1, BBoxX2, BBoxY2;	///< BBox region for exporting 2d graphics
+	std::vector<mglGlyph> UserGlf;	///< User-defined glyphs data
+
+	mreal CDef;			///< Default (current) color in texture
+	mreal AlphaDef;		///< Default value of alpha channel (transparency)
+	mreal BarWidth;		///< Relative width of rectangles in Bars().
+	int MeshNum;		///< Set approximate number of lines in Mesh and Grid. By default (=0) it draw all lines.
+	int FaceNum;		///< Set approximate number of visible faces and lines. By default (=0) it draw everything.
+	char Arrow1, Arrow2;///< Style of arrows at end and at start of curve
+	long InUse;			///< Smart pointer (number of users)
+	uint32_t Flag;		///< Flags for controlling drawing
+	mreal size_opt;		///< Value of size option (or NAN if not specified)
+
+	inline bool get(uint32_t fl) const	{	return Flag&fl;	}
+	inline void set(uint32_t fl)	{	Flag |= fl;	}
+	inline void clr(uint32_t fl)	{	Flag &=~fl;	}
+	inline void set(bool v,uint32_t fl)	{	Flag = v ? Flag|fl : Flag&(~fl);	}
+
+	/// Set axis range scaling -- simplified way to shift/zoom axis range -- need to replot whole image!
+	inline void ZoomAxis(mglPoint p1=mglPoint(0,0,0,0), mglPoint p2=mglPoint(1,1,1,1))	{	AMin = p1;	AMax = p2;	}
+	/// Set values of mglGraph::Min and mglGraph::Max
+	inline void SetRanges(mreal x1, mreal x2, mreal y1, mreal y2, mreal z1=0, mreal z2=0, mreal c1=0, mreal c2=0)
+	{	SetRanges(mglPoint(x1,y1,z1,c1),mglPoint(x2,y2,z2,c2));	}
+	void SetRanges(mglPoint v1, mglPoint v2);
+	/// Set values of mglGraph::Cmin and mglGraph::Cmax as minimal and maximal values of data a
+	void CRange(HCDT a, bool add = false, mreal fact=0);
+	void CRange(mreal v1,mreal v2,bool add=false);
+	/// Set values of mglGraph::Min.x and mglGraph::Max.x as minimal and maximal values of data a
+	void XRange(HCDT a, bool add = false, mreal fact=0);
+	void XRange(mreal v1,mreal v2,bool add=false);
+	/// Set values of mglGraph::Min.x and mglGraph::Max.x as minimal and maximal values of data a
+	void YRange(HCDT a, bool add = false, mreal fact=0);
+	void YRange(mreal v1,mreal v2,bool add=false);
+	/// Set values of mglGraph::Min.x and mglGraph::Max.x as minimal and maximal values of data a
+	void ZRange(HCDT a, bool add = false, mreal fact=0);
+	void ZRange(mreal v1,mreal v2,bool add=false);
+	/// Set ranges for automatic variables
+	void SetAutoRanges(mreal x1, mreal x2, mreal y1=0, mreal y2=0, mreal z1=0, mreal z2=0, mreal c1=0, mreal c2=0);
+	/// Set axis origin
+	void SetOrigin(mreal x0, mreal y0, mreal z0=NAN, mreal c0=NAN);
+	/// Save ranges into internal variable and put parsed
+	mreal SaveState(const char *opt);
+	/// Load ranges from internal variable
+	void LoadState();
+	/// Increase ZMin
+	mreal AdjustZMin()	{	ZMin /= MGL_FEPSILON;	return Max.z - ZMin*(Max.z-Min.z);	}
+
+	/// Safetly set the transformation formulas for coordinate.
+	void SetFunc(const char *EqX, const char *EqY, const char *EqZ=0, const char *EqA=0);
+	/// Set one of predefined transformation rule
+	void SetCoor(int how);
+	/// Safetly set the cutting off condition (formula).
+	void CutOff(const char *EqCut);
+	/// Set to draw Ternary axis (triangle like axis, grid and so on)
+	void Ternary(int tern);
+
+	/// Set cutting for points outside of bounding box
+	inline void SetCut(bool val)	{	set(val, MGL_ENABLE_CUT);	}
+	/// Set additional cutting box
+	inline void SetCutBox(mreal x1, mreal y1, mreal z1, mreal x2, mreal y2, mreal z2)
+	{	CutMin.Set(x1,y1,z1);	CutMax.Set(x2,y2,z2);	}
+	inline void SetCutBox(mglPoint v1, mglPoint v2)	{	CutMin=v1;	CutMax=v2;	}
+	/// Reset mask to solid state
+	inline void ResetMask()	{	mask = MGL_SOLID_MASK;	MaskAn = DefMaskAn;	}
+	/// Set default mask rotation angle
+	inline void SetMaskAngle(int angle)	{	DefMaskAn = angle;	}
+
+	/// Set the using of light on/off.
+	virtual bool Light(bool enable)
+	{	bool t=get(MGL_ENABLE_LIGHT);	set(enable,MGL_ENABLE_LIGHT);	return t;	}
+	/// Set to attach light sources to inplot.
+	virtual bool AttachLight(bool enable)
+	{	bool t=get(MGL_LOCAL_LIGHT);	set(enable,MGL_LOCAL_LIGHT);	return t;	}
+	/// Set ambient light brightness
+	virtual void SetAmbient(mreal bright=0.5);
+	/// Set diffusive light brightness
+	virtual void SetDiffuse(mreal bright=0.5);
+	/// Use diffusive light (only for local light sources)
+	inline void SetDifLight(bool dif)	{	SetDiffuse(dif?0.5:0);	}
+	/// Set the transparency on/off.
+	virtual bool Alpha(bool enable)
+	{	bool t=get(MGL_ENABLE_ALPHA);	set(enable,MGL_ENABLE_ALPHA);	return t;	}
+	/// Set default value of alpha-channel
+	inline void SetAlphaDef(mreal val)	{	AlphaDef=val;	}
+	/// Set default palette
+	inline void SetPalette(const char *colors)
+	{	Txt[0].Set(mgl_have_color(colors)?colors:MGL_DEF_PAL,-1);	}
+	inline void ResetPal()	{	CurrPal=0;	}
+	inline long GetNumPal(long id) const	{	return Txt[labs(id)/256].n;	}
+	/// Set default color scheme
+	inline void SetDefScheme(const char *colors)
+	{	Txt[1].Set(mgl_have_color(colors)?colors:MGL_DEF_SCH);	}
+
+	/// Set number of mesh lines
+	inline void SetMeshNum(int val)	{	MeshNum=val;	}
+	/// Set relative width of rectangles in Bars, Barh, BoxPlot
+	inline void SetBarWidth(mreal val)	{	BarWidth=val;	}
+	/// Set size of marks
+	inline void SetMarkSize(mreal val)	{	MarkSize=0.02*val;	}
+	/// Set size of arrows
+	inline void SetArrowSize(mreal val)	{	ArrowSize=0.03*val;	}
+	/// Get unscaled arrow size
+	inline mreal GetArrowSize() const	{	return ArrowSize/0.03;	}
+
+	/// Set warning code ant fill Message
+	void SetWarn(int code, const char *who);
+	int inline GetWarn() const	{	return WarnCode;	}
+
+	virtual void StartAutoGroup (const char *)=0;
+	void StartGroup(const char *name, int id);
+	virtual void EndGroup()=0;	//	{	LoadState();	}
+	/// Highlight group
+	inline void Highlight(int id)	{	HighId=id;	}
+
+	/// Set FontSize by size in pt and picture DPI (default is 16 pt for dpi=72)
+	virtual void SetFontSizePT(mreal pt, int dpi=72){	FontSize = pt*27.f/dpi;	}
+	/// Set FontSize by size in centimeters and picture DPI (default is 0.56 cm = 16 pt)
+	inline void SetFontSizeCM(mreal cm, int dpi=72)	{	SetFontSizePT(cm*28.45f,dpi);	}
+	/// Set FontSize by size in inch and picture DPI (default is 0.22 in = 16 pt)
+	inline void SetFontSizeIN(mreal in, int dpi=72)	{	SetFontSizePT(in*72.27f,dpi);	}
+	/// Set font typeface. Note that each mglFont instance can be used with ONLY ONE mglGraph instance at a moment of time!
+	void SetFont(mglFont *f);
+	/// Get current typeface. Note that this variable can be deleted at next SetFont() call!
+	inline mglFont *GetFont()	{	return fnt;	}
+	/// Restore font
+	void RestoreFont();
+	/// Load font from file
+	void LoadFont (const char *name, const char *path=NULL);
+	/// Copy font from another mglGraph instance
+	void CopyFont(mglBase *gr);
+	/// Set default font size
+	inline void SetFontSize(mreal val)	{	FontSize=val>0 ? val:-FontSize*val;	}
+	inline mreal GetFontSize() const	{	return FontSize;	}
+	mreal TextWidth(const char *text, const char *font, mreal size) const MGL_FUNC_PURE;
+	mreal TextWidth(const wchar_t *text, const char *font, mreal size) const MGL_FUNC_PURE;
+	mreal TextHeight(const char *font, mreal size) const MGL_FUNC_PURE;
+	inline mreal FontFactor() const		{	return font_factor;	}
+	virtual mreal GetRatio() const MGL_FUNC_CONST;
+	virtual int GetWidth() const MGL_FUNC_CONST;
+	virtual int GetHeight() const MGL_FUNC_CONST;
+	/// Add user-defined glyph
+	void DefineGlyph(HCDT x, HCDT y, unsigned char id=0);
+
+	/// Set to use or not text rotation
+	inline void SetRotatedText(bool val)	{	set(val,MGL_ENABLE_RTEXT);	}
+	/// Set default font style and color
+	void SetFontDef(const char *font);
+	/// Set to use or not text rotation
+	inline void SetTickRotate(bool val)	{	set(val,MGL_TICKS_ROTATE);	}
+	/// Set to use or not text rotation
+	inline void SetTickSkip(bool val)	{	set(val,MGL_TICKS_SKIP);	}
+
+	/// Add string to legend
+	void AddLegend(const char *text,const char *style);
+	void AddLegend(const wchar_t *text,const char *style);
+	/// Clear saved legend string
+	inline void ClearLegend()	{	Leg.clear();	}
+
+	/// Set plot quality
+	virtual void SetQuality(int qual=MGL_DRAW_NORM)	{	Quality=qual;	}
+	inline int GetQuality() const	{	return Quality;	}
+	inline void SetDrawReg(long nx=1, long ny=1, long m=0)	{	dr_x=nx;	dr_y=ny;	dr_p=m;	}
+
+	// ~~~~~~~~~~~~~~~~~~~~~~ Developer functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+	/// Add point to the Pnt and return its position
+	inline long AddPnt(mglPoint p, mreal c=-1, mglPoint n=mglPoint(NAN), mreal a=-1, int scl=1)
+	{	return AddPnt(&B,p,c,n,a,scl);	}
+	long AddPnt(const mglMatrix *M, mglPoint p, mreal c=-1, mglPoint n=mglPoint(NAN), mreal a=-1, int scl=1);
+	long CopyNtoC(long k, mreal c);
+	long CopyProj(long from, mglPoint p, mglPoint n, short sub=0);
+	void SetRGBA(long k, const mglColor &c)
+	{	mglPnt &p=Pnt[k];	p.r = c.r;	p.g = c.g;	p.b = c.b;	p.a = c.a;	}
+	virtual void Reserve(long n);		///< Allocate n-cells for Pnt and return current position
+	/// Set to reduce accuracy of points (to reduce size of output files)
+	inline void SetReduceAcc(bool val)	{	set(val, MGL_REDUCEACC);	}
+	/// Add glyph of current font to the Glf and return its position
+	long AddGlyph(int s, long j);
+	/// Add glyph to the Glf and return its position
+	long AddGlyph(unsigned char id);
+	/// Add active point as k-th element of Pnt
+	void AddActive(long k,int n=0);
+	/// Clear unused points and primitives
+	void ClearUnused();
+
+	inline mreal GetPenWidth()	{	return PenWidth;	}
+
+	inline const mglMatrix *GetB()	const	{	return &B;	}
+	inline mglPoint GetPntP(long i) const
+	{	const mglPnt &p=Pnt[i];	return mglPoint(p.x,p.y,p.z);	}
+	inline mglPoint GetPntN(long i) const
+	{	const mglPnt &p=Pnt[i];	return mglPoint(p.u,p.v,p.w);	}
+	inline mglColor GetPntC(long i) const
+	{	const mglPnt &p=Pnt[i];	return mglColor(p.r,p.g,p.b,p.a);	}
+	inline float GetClrC(long i) const	{	return Pnt[i].c;	}
+	inline const mglGlyph &GetGlf(long i) const	{	return Glf[i];	}
+	inline long GetGlfNum() const		{	return Glf.size();	}
+	inline const mglPnt &GetPnt(long i) const	{	return Pnt[i];		}
+	inline long GetPntNum() const		{	return Pnt.size();	}
+	inline bool SamePnt(long i, long j) const
+	{
+		if(i<0 || j<0)	return true;
+		const mglPnt &p=Pnt[i], &q=Pnt[j];
+//		return GetWidth()>1 ? (long(p.x)==long(q.x) && long(p.y)==long(q.y)): (p.x==q.x && p.y==q.y);
+		return p.x==q.x && p.y==q.y;	
+	}
+//	inline mglPrim &GetPrm(long i)		{	return Prm[i];		}
+	inline mglPrim &GetPrm(long i, bool sort=true)
+	{	return (sort && PrmInd) ? Prm[PrmInd[i]]:Prm[i];	}
+	inline const mglPrim &GetPrm(long i, bool sort=true) const
+	{	return (sort && PrmInd) ? Prm[PrmInd[i]]:Prm[i];	}
+	inline long GetPrmNum() const		{	return Prm.size();	}
+	inline const mglText &GetPtx(long i) const	{	return Ptx[i];		}
+	inline long GetPtxNum() const		{	return Ptx.size();	}
+	inline const mglTexture &GetTxt(long i) const	{	return Txt[i];	}
+	inline long GetTxtNum() const		{	return Txt.size();	}
+	/// Scale coordinates and cut off some points
+	virtual bool ScalePoint(const mglMatrix *M, mglPoint &p, mglPoint &n, bool use_nan=true) const;
+
+	virtual mreal GetOrgX(char dir, bool inv=false) const=0;	///< Get Org.x (parse NAN value)
+	virtual mreal GetOrgY(char dir, bool inv=false) const=0;	///< Get Org.y (parse NAN value)
+	virtual mreal GetOrgZ(char dir, bool inv=false) const=0;	///< Get Org.z (parse NAN value)
+
+	/// Get color depending on single variable z, which should be scaled if scale=true
+	inline mreal GetC(long s,mreal z,bool scale = true) const
+	{	return s+(scale?GetA(z):(z>0?z/MGL_FEPSILON:0));	}
+	/// Get alpha value depending on single variable a
+	mreal GetA(mreal a) const MGL_FUNC_PURE;
+	/// Set pen/palette
+	char SetPenPal(const char *stl, long *id=0, bool pal=true);
+	/// Add texture (like color scheme) and return the position of first color
+	long AddTexture(const char *cols, int smooth=0);
+//	inline mreal AddTexture(char col)	{	return AddTexture(mglColor(col));	}
+	mreal AddTexture(mglColor col);
+	inline void DefColor(mglColor col)	{	CDef = AddTexture(col);	}
+	/// Set mask for face coloring
+	void SetMask(const char *mask);
+	/// Set next color from palette
+	mreal NextColor(long &id);
+	mreal NextColor(long id, long sh);
+
+	virtual void mark_plot(long p, char type, mreal size=1)=0;
+	virtual void arrow_plot(long p1, long p2, char st)=0;
+	virtual void line_plot(long p1, long p2)=0;
+	virtual void trig_plot(long p1, long p2, long p3)=0;
+	virtual void quad_plot(long p1, long p2, long p3, long p4)=0;
+	virtual void smbl_plot(long p1, char id, double size)=0;
+	virtual void Glyph(mreal x, mreal y, mreal f, int style, long icode, mreal col)=0;
+	virtual float GetGlyphPhi(const mglPnt &q, float phi)=0;
+	virtual mreal text_plot(long p,const wchar_t *text,const char *fnt,mreal size=-1,mreal sh=0,mreal  col=-('k'),bool rot=true)=0;
+	void vect_plot(long p1, long p2, mreal s=1);
+	
+	// check if visible
+	virtual bool trig_vis(const mglPnt &p1, const mglPnt &p2, const mglPnt &p3) const =0;
+	virtual bool quad_vis(const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, const mglPnt &p4) const =0;
+
+	inline mreal mark_size()	{	return MarkSize*font_factor;	}
+//	inline char last_color()	{	return last_style[1];	}
+	inline const char *last_line()	{	return last_style;	}
+	int PrmCmp(size_t i, size_t j) const MGL_FUNC_PURE;	// compare 2 primitives with indexes i,j
+	/// Check if plot termination is asked
+	bool NeedStop()	{	if(event_cb)	event_cb(event_par);	return Stop;	}
+	/// Ask to stop drawing
+	void AskStop(bool stop=true)	{	Stop = stop;	}
+	/// Set callback function for event processing
+	void SetEventFunc(void (*func)(void *), void *par)	{	event_cb=func;	event_par=par;	}
+
+protected:
+	volatile bool Stop;	///< Flag that execution should be terminated.
+	void (*event_cb)(void *);	///< Function to be called for event processing
+	void *event_par;	///< Parameter for event processing function
+
+	mglPoint OMin;		///< Lower edge for original axis (before scaling)
+	mglPoint OMax;		///< Upper edge for original axis (before scaling)
+	mglPoint AMin;		///< Lower edge for axis scaling
+	mglPoint AMax;		///< Upper edge for axis scaling
+	mglPoint FMin;		///< Actual lower edge after transformation formulas.
+	mglPoint FMax;		///< Actual upper edge after transformation formulas.
+	mglPoint Org;		///< Center of axis cross section.
+	int WarnCode;		///< Warning code
+	size_t *PrmInd;		///< Indexes of sorted primitives
+	mglStack<mglPnt> Pnt; 	///< Internal points
+	mglStack<mglPrim> Prm;	///< Primitives (lines, triangles and so on) -- need for export
+	std::vector<mglBlock> Sub;	///< InPlot regions
+	std::vector<mglText> Ptx;	///< Text labels for mglPrim
+	std::vector<mglText> Leg;	///< Text labels for legend
+	std::vector<mglGlyph> Glf;	///< Glyphs data
+	std::vector<mglTexture> Txt;	///< Pointer to textures
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_t mutexPnt, mutexTxt, mutexLeg, mutexGlf, mutexAct, mutexDrw;
+	pthread_mutex_t mutexSub, mutexPrm, mutexPtx, mutexStk, mutexGrp, mutexClf;
+#endif
+	void *lockClf;		///< pointer to mutex for mglStack
+
+	int TernAxis;		///< Flag that Ternary axis is used
+	unsigned PDef;		///< Pen bit mask
+	mreal pPos;			///< Current position in pen mask
+	mreal PenWidth;		///< Pen width for further line plotting (must be >0 !!!)
+//	long numT;			///< Number of textures
+	mreal AmbBr;		///< Default ambient light brightness
+	mreal DifBr;		///< Default diffusive light brightness
+
+	mreal persp;		///< Original value for perspective
+	mglMatrix Bp;		///< Transformation matrix for View() and Zoom()
+	mglMatrix B;		///< Transformation matrix
+	mglMatrix B1;		///< Transformation matrix for colorbar
+
+	mglFont *fnt;		///< Class for printing vector text
+	mreal FontSize;		///< The size of font for tick and axis labels
+	char FontDef[32];	///< Font specification (see mglGraph::Puts). Default is Roman with align at center.
+	int Quality;		///< Quality of plot (0x0-pure, 0x1-fast; 0x2-fine; 0x4 - low memory)
+
+	mglFormula *fx;		///< Transformation formula for x direction.
+	mglFormula *fy;		///< Transformation formula for y direction.
+	mglFormula *fz;		///< Transformation formula for z direction.
+	mglFormula *fa;		///< Transformation formula for coloring.
+	mglFormula *fc;		///< Cutting off condition (formula).
+
+	long CurrPal;		///< Current palette index
+	mreal MarkSize;		///< The size of marks for 1D plots.
+	mreal ArrowSize;	///< The size of arrows.
+	char last_style[64];///< Last pen style
+	mreal font_factor;	///< Font scaling factor
+
+	long dr_x, dr_y, dr_p;	///< default drawing region for quality&4 mode
+
+	virtual void LightScale(const mglMatrix *M)=0;			///< Scale positions of light sources
+	void ClearPrmInd();
+
+	// block for SaveState()
+	mglPoint MinS;		///< Saved lower edge of bounding box for graphics.
+	mglPoint MaxS;		///< Saved upper edge of bounding box for graphics.
+	mreal MSS, ASS, FSS, ADS, MNS, LSS;	///< Saved state
+	mreal PrevState;		///< Previous value of SaveState()
+	long CSS;			///< Saved flags
+	bool saved;			///< State is saved
+	std::string leg_str;///< text to be save in legend
+
+	union
+	{
+		uint64_t mask;	///< Mask to be used for coloring
+		unsigned char mask_ch[8];
+	};
+	int MaskAn;		///< Mask rotation angle in degrees
+	int DefMaskAn;	///< Default mask rotation angle in degrees
+
+private:
+	mglBase(const mglBase &){}	// copying is not allowed
+	const mglBase &operator=(const mglBase &t){return t;}	// copying is not allowed
+
+	mglPoint CutMin;	///< Lower edge of bounding box for cut off.
+	mglPoint CutMax;	///< Upper edge of bounding box for cut off.
+
+	bool RecalcCRange();	///< Recalculate internal parameter for correct coloring.
+	void RecalcBorder();	///< Recalculate internal parameter for correct transformation rules.
+	bool SetFBord(mreal x,mreal y,mreal z);	///< Set internal boundng box depending on transformation formula
+	void ClearEq();			///< Clear the used variables for axis transformation
+};
+//-----------------------------------------------------------------------------
+bool MGL_EXPORT mgl_check_dim0(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT r, const char *name, bool less=false);
+bool MGL_EXPORT mgl_check_dim1(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT r, const char *name, bool less=false);
+bool MGL_EXPORT mgl_check_dim2(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, const char *name, bool less=false);
+bool MGL_EXPORT mgl_check_dim3(HMGL gr, bool both, HCDT x, HCDT y, HCDT z, HCDT a, HCDT b, const char *name);
+bool MGL_EXPORT mgl_check_vec3(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT ax, HCDT ay, HCDT az, const char *name);
+bool MGL_EXPORT mgl_check_trig(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, HCDT a, const char *name, int d=3);
+bool MGL_EXPORT mgl_isnboth(HCDT x, HCDT y, HCDT z, HCDT a);
+bool MGL_EXPORT mgl_isboth(HCDT x, HCDT y, HCDT z, HCDT a);
+inline bool mgl_islog(mreal a,mreal b)	{	return (a>0 && b>10*a) || (b<0 && a<10*b);	}
+//-----------------------------------------------------------------------------
+#endif
+#endif
diff --git a/include/mgl2/base_cf.h b/include/mgl2/base_cf.h
new file mode 100644
index 0000000..2a23d20
--- /dev/null
+++ b/include/mgl2/base_cf.h
@@ -0,0 +1,233 @@
+/***************************************************************************
+ * base_cf.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_BASE_CF_H_
+#define _MGL_BASE_CF_H_
+#include "mgl2/abstract.h"
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// Check if MathGL version is valid (return 0) or not (return 1)
+int MGL_EXPORT mgl_check_version(const char *ver);
+int MGL_EXPORT mgl_check_version_(const char *ver, int);
+/// Suppress printing warnings to stderr
+void MGL_EXPORT mgl_suppress_warn(int on);
+void MGL_EXPORT mgl_suppress_warn_(int *on);
+/// Get last warning code
+int MGL_EXPORT mgl_get_warn(HMGL gr);
+int MGL_EXPORT mgl_get_warn_(uintptr_t *gr);
+/// Set warning code ant fill message
+void MGL_EXPORT mgl_set_warn(HMGL gr, int code, const char *text);
+void MGL_EXPORT mgl_set_warn_(uintptr_t *gr, int *code, const char *text,int);
+/// Get text of warning message(s)
+MGL_EXPORT const char *mgl_get_mess(HMGL gr);
+int MGL_EXPORT mgl_get_mess_(uintptr_t *gr, char *out, int len);
+
+/// Set name of plot for saving filename
+void MGL_EXPORT mgl_set_plotid(HMGL gr, const char *id);
+void MGL_EXPORT mgl_set_plotid_(uintptr_t *gr, const char *id,int);
+/// Get name of plot for saving filename
+MGL_EXPORT const char *mgl_get_plotid(HMGL gr);
+int MGL_EXPORT mgl_get_plotid_(uintptr_t *gr, char *out, int len);
+
+/// Ask to stop drawing
+void MGL_EXPORT mgl_ask_stop(HMGL gr, int stop);
+void MGL_EXPORT mgl_ask_stop_(uintptr_t *gr, int *stop);
+/// Check if plot termination is asked
+int MGL_EXPORT mgl_need_stop(HMGL gr);
+int MGL_EXPORT mgl_need_stop_(uintptr_t *gr);
+/// Set callback function for event processing
+void MGL_EXPORT mgl_set_event_func(HMGL gr, void (*func)(void *), void *par);
+
+/// Get plot quality
+int MGL_EXPORT mgl_get_quality(HMGL gr);
+int MGL_EXPORT mgl_get_quality_(uintptr_t *gr);
+/// Set plot quality
+/** qual=0 -- no face drawing (fastest),
+ *  qual=1 -- no color interpolation (fast),
+ *  qual=2 -- high quality (normal),
+ *  qual|4 -- direct bitmap drawing (low memory usage);
+ *  qual|8 for dots drawing instead of primitives (extremely fast). */
+void MGL_EXPORT mgl_set_quality(HMGL gr, int qual);
+void MGL_EXPORT mgl_set_quality_(uintptr_t *gr, int *qual);
+/// Set drawing region for Quality&4
+void MGL_EXPORT mgl_set_draw_reg(HMGL gr, long nx, long ny, long m);
+void MGL_EXPORT mgl_set_draw_reg_(uintptr_t *gr, int *nx, int *ny, int *m);
+
+/// Check if support of frames is enabled (i.e. MGL_VECT_FRAME is set and Quality&MGL_DRAW_LMEM==0)
+int MGL_EXPORT mgl_is_frames(HMGL gr);
+/// Get bit-value flag of HMGL state (for advanced users only)
+int MGL_EXPORT mgl_get_flag(HMGL gr, uint32_t flag);
+int MGL_EXPORT mgl_get_flag_(uintptr_t *gr, unsigned long *flag);
+/// Set bit-value flag of HMGL state (for advanced users only)
+void MGL_EXPORT mgl_set_flag(HMGL gr, int val, uint32_t flag);
+void MGL_EXPORT mgl_set_flag_(uintptr_t *gr, int *val, unsigned long *flag);
+/// Change counter of HMGL uses (for advanced users only). Non-zero counter prevent automatic object removing.
+long MGL_EXPORT mgl_use_graph(HMGL gr, int inc);
+long MGL_EXPORT mgl_use_graph_(uintptr_t *gr, int *inc);
+void MGL_EXPORT mgl_set_rdc_acc(HMGL gr, int reduce);
+void MGL_EXPORT mgl_set_rdc_acc_(uintptr_t *gr, int *reduce);
+
+/// Start group of objects
+void MGL_EXPORT mgl_start_group(HMGL gr, const char *name);
+void MGL_EXPORT mgl_start_group_(uintptr_t *gr, const char *name,int);
+/// End group of objects
+void MGL_EXPORT mgl_end_group(HMGL gr);
+void MGL_EXPORT mgl_end_group_(uintptr_t *gr);
+/// Highlight objects with given id
+void MGL_EXPORT mgl_highlight(HMGL gr, int id);
+void MGL_EXPORT mgl_highlight_(uintptr_t *gr, int *id);
+
+/// Set default palette
+void MGL_EXPORT mgl_set_palette(HMGL gr, const char *colors);
+void MGL_EXPORT mgl_set_palette_(uintptr_t *gr, const char *colors, int);
+void MGL_EXPORT mgl_set_pal_color_(uintptr_t *gr, int *n, mreal *r, mreal *g, mreal *b);
+void MGL_EXPORT mgl_set_pal_num_(uintptr_t *gr, int *num);
+/// Sets RGB values for color with given id
+void MGL_EXPORT mgl_set_color(char id, double r, double g, double b);
+void MGL_EXPORT mgl_set_color_(char *id, mreal *r, mreal *g, mreal *b, int);
+/// Set default color scheme
+void MGL_EXPORT mgl_set_def_sch(HMGL gr, const char *sch);
+void MGL_EXPORT mgl_set_def_sch_(uintptr_t *gr, const char *sch,int);
+/// Set mask for face coloring as array of type 'unsigned char[8]'
+void MGL_EXPORT mgl_set_mask(char id, const char *mask);
+void MGL_EXPORT mgl_set_mask_(const char *id, const char *mask,int,int);
+/// Set mask for face coloring as unsigned long number
+void MGL_EXPORT mgl_set_mask_val(char id, uint64_t mask);
+void MGL_EXPORT mgl_set_mask_val_(const char *id, uint64_t *mask,int);
+/// Set default mask rotation angle
+void MGL_EXPORT mgl_set_mask_angle(HMGL gr, int angle);
+void MGL_EXPORT mgl_set_mask_angle_(uintptr_t *gr, int *angle);
+
+/// Set default value of alpha-channel
+void MGL_EXPORT mgl_set_alpha_default(HMGL gr, double alpha);
+void MGL_EXPORT mgl_set_alpha_default_(uintptr_t *gr, mreal *alpha);
+/// Set relative width of rectangles in Bars, Barh, BoxPlot, Candle, OHLC (default is 0.7)
+void MGL_EXPORT mgl_set_bar_width(HMGL gr, double width);
+void MGL_EXPORT mgl_set_bar_width_(uintptr_t *gr, mreal *width);
+/// Set number of mesh lines (use 0 to draw all of them)
+void MGL_EXPORT mgl_set_meshnum(HMGL gr, int num);
+void MGL_EXPORT mgl_set_meshnum_(uintptr_t *gr, int *num);
+/// Set number of visible faces (use 0 to draw all of them)
+void MGL_EXPORT mgl_set_facenum(HMGL gr, int num);
+void MGL_EXPORT mgl_set_facenum_(uintptr_t *gr, int *num);
+/// Clear unused points and primitives. Useful only in combination with mgl_set_facenum().
+void MGL_EXPORT mgl_clear_unused(HMGL gr);
+void MGL_EXPORT mgl_clear_unused_(uintptr_t *gr);
+
+/// Set ambient light brightness
+void MGL_EXPORT mgl_set_ambbr(HMGL gr, double i);
+void MGL_EXPORT mgl_set_ambbr_(uintptr_t *gr, mreal *i);
+/// Set diffusive light brightness
+void MGL_EXPORT mgl_set_difbr(HMGL gr, double i);
+void MGL_EXPORT mgl_set_difbr_(uintptr_t *gr, mreal *i);
+/// Use diffusive light (only for local light sources) -- OBSOLETE
+void MGL_EXPORT mgl_set_light_dif(HMGL gr, int enable);
+void MGL_EXPORT mgl_set_light_dif_(uintptr_t *gr, int *enable);
+
+/// Set cutting for points outside of bounding box
+void MGL_EXPORT mgl_set_cut(HMGL gr, int cut);
+void MGL_EXPORT mgl_set_cut_(uintptr_t *gr, int *cut);
+/// Set additional cutting box
+void MGL_EXPORT mgl_set_cut_box(HMGL gr, double x1,double y1,double z1,double x2,double y2,double z2);
+void MGL_EXPORT mgl_set_cut_box_(uintptr_t *gr, mreal *x1, mreal *y1, mreal *z1, mreal *x2, mreal *y2, mreal *z2);
+/// Set the cutting off condition (formula)
+void MGL_EXPORT mgl_set_cutoff(HMGL gr, const char *EqC);
+void MGL_EXPORT mgl_set_cutoff_(uintptr_t *gr, const char *EqC, int);
+
+/// Set values of axis range
+void MGL_EXPORT mgl_set_ranges(HMGL gr, double x1, double x2, double y1, double y2, double z1, double z2);
+void MGL_EXPORT mgl_set_ranges_(uintptr_t *gr, mreal *x1, mreal *x2, mreal *y1, mreal *y2, mreal *z1, mreal *z2);
+/// Set range in direction dir as [v1, v2]
+void MGL_EXPORT mgl_set_range_val(HMGL gr, char dir, double v1,double v2);
+void MGL_EXPORT mgl_set_range_val_(uintptr_t *gr, const char *dir, mreal *v1, mreal *v2,int);
+/// Add [v1, v2] to the current range in direction dir
+void MGL_EXPORT mgl_add_range_val(HMGL gr, char dir, double v1,double v2);
+void MGL_EXPORT mgl_add_range_val_(uintptr_t *gr, const char *dir, mreal *v1, mreal *v2,int);
+/// Set range in direction dir as minimal and maximal values of data a
+void MGL_EXPORT mgl_set_range_dat(HMGL gr, char dir, HCDT a, int add);
+void MGL_EXPORT mgl_set_range_dat_(uintptr_t *gr, const char *dir, uintptr_t *a, int *add,int);
+/// Set ranges for automatic variables
+void MGL_EXPORT mgl_set_auto_ranges(HMGL gr, double x1, double x2, double y1, double y2, double z1, double z2, double c1, double c2);
+void MGL_EXPORT mgl_set_auto_ranges_(uintptr_t *gr, mreal *x1, mreal *x2, mreal *y1, mreal *y2, mreal *z1, mreal *z2, mreal *c1, mreal *c2);
+/// Set axis range scaling -- simplified way to shift/zoom axis range -- need to redraw whole image!
+void MGL_EXPORT mgl_zoom_axis(HMGL gr, double x1,double y1,double z1,double c1,double x2,double y2,double z2,double c2);
+void MGL_EXPORT mgl_zoom_axis_(uintptr_t *gr, mreal *x1, mreal *y1, mreal *z1, mreal *c1, mreal *x2, mreal *y2, mreal *z2, mreal *c2);
+
+/// Set axis origin
+void MGL_EXPORT mgl_set_origin(HMGL gr, double x0, double y0, double z0);
+void MGL_EXPORT mgl_set_origin_(uintptr_t *gr, mreal *x0, mreal *y0, mreal *z0);
+/// Set the transformation formulas for coordinate. Use "" or NULL for built-in ones
+void MGL_EXPORT mgl_set_func(HMGL gr, const char *EqX,const char *EqY,const char *EqZ,const char *EqA);
+void MGL_EXPORT mgl_set_func_(uintptr_t *gr, const char *EqX, const char *EqY, const char *EqZ, const char *EqA, int, int, int, int);
+/// Set one of predefined transformation rule
+void MGL_EXPORT mgl_set_coor(HMGL gr, int how);
+void MGL_EXPORT mgl_set_coor_(uintptr_t *gr, int *how);
+/// Set to draw Ternary axis (triangle like axis, grid and so on)
+/** val=1 for Ternary axis (a+b+c=1, z=z),
+ *  val=2 for Quaternary axis (a+b+c+d=1),
+ *  val|4 for projections. */
+void MGL_EXPORT mgl_set_ternary(HMGL gr, int kind);
+void MGL_EXPORT mgl_set_ternary_(uintptr_t *gr, int *kind);
+
+/// Set to use or not tick labels rotation
+void MGL_EXPORT mgl_set_tick_rotate(HMGL gr, int enable);
+void MGL_EXPORT mgl_set_tick_rotate_(uintptr_t *gr, int *enable);
+/// Set to use or not tick labels skipping
+void MGL_EXPORT mgl_set_tick_skip(HMGL gr, int enable);
+void MGL_EXPORT mgl_set_tick_skip_(uintptr_t *gr, int *enable);
+
+/// Set default font for all new HMGL objects
+void MGL_EXPORT mgl_def_font(const char *name, const char *path);
+void MGL_EXPORT mgl_def_font_(const char *name, const char *path,int,int);
+/// Set default size of marks (locally you can use "size" option)
+void MGL_EXPORT mgl_set_mark_size(HMGL gr, double size);
+void MGL_EXPORT mgl_set_mark_size_(uintptr_t *gr, mreal *size);
+/// Set default size of arrows (locally you can use "size" option)
+void MGL_EXPORT mgl_set_arrow_size(HMGL gr, double size);
+void MGL_EXPORT mgl_set_arrow_size_(uintptr_t *gr, mreal *size);
+/// Set default font size
+void MGL_EXPORT mgl_set_font_size(HMGL gr, double size);
+void MGL_EXPORT mgl_set_font_size_(uintptr_t *gr, mreal *size);
+/// Set default font style and color
+void MGL_EXPORT mgl_set_font_def(HMGL gr, const char *fnt);
+void MGL_EXPORT mgl_set_font_def_(uintptr_t *gr, const char *fnt, int);
+/// Set to use or not text rotation
+void MGL_EXPORT mgl_set_rotated_text(HMGL gr, int enable);
+void MGL_EXPORT mgl_set_rotated_text_(uintptr_t *gr, int *enable);
+/// Load font from file
+void MGL_EXPORT mgl_load_font(HMGL gr, const char *name, const char *path);
+void MGL_EXPORT mgl_load_font_(uintptr_t *gr, char *name, char *path, int l, int n);
+/// Copy font from another mglGraph instance
+void MGL_EXPORT mgl_copy_font(HMGL gr, HMGL gr_from);
+void MGL_EXPORT mgl_copy_font_(uintptr_t *gr, uintptr_t *gr_from);
+/// Restore font (load default font for new HMGL objects)
+void MGL_EXPORT mgl_restore_font(HMGL gr);
+void MGL_EXPORT mgl_restore_font_(uintptr_t *gr);
+/// Add user-defined glyph for symbol and set its optional id
+void MGL_EXPORT mgl_define_symbol(HMGL gr, char id, HCDT x, HCDT y);
+void MGL_EXPORT mgl_define_symbol_(uintptr_t *gr, char *id, uintptr_t *x, uintptr_t *y,int);
+
+#ifdef __cplusplus
+}
+#endif
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/canvas.h b/include/mgl2/canvas.h
new file mode 100644
index 0000000..ddf8db2
--- /dev/null
+++ b/include/mgl2/canvas.h
@@ -0,0 +1,529 @@
+/***************************************************************************
+ * canvas.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef MGL_CANVAS_H
+#define MGL_CANVAS_H
+#include "mgl2/base.h"
+//-----------------------------------------------------------------------------
+struct GifFileType;
+//-----------------------------------------------------------------------------
+/// Structure for drawing axis and ticks
+struct MGL_EXPORT mglAxis
+{
+	mglAxis() : dv(0),ds(0),d(0),ns(0),	v0(0),v1(0),v2(0),o(NAN),	f(0),	ch(0),	pos('t'),sh(0),inv(false)	{}
+	mglAxis(const mglAxis &aa) : dv(aa.dv),ds(aa.ds),d(aa.d),ns(aa.ns),	t(aa.t),fact(aa.fact),stl(aa.stl),	dir(aa.dir),a(aa.a),b(aa.b),org(aa.org), v0(aa.v0),v1(aa.v1),v2(aa.v2),o(aa.o),	f(aa.f),txt(aa.txt),	ch(aa.ch),	pos(aa.pos),sh(aa.sh),inv(aa.inv)	{}
+#if MGL_HAVE_RVAL
+	mglAxis(mglAxis &&aa) : dv(aa.dv),ds(aa.ds),d(aa.d),ns(aa.ns),	t(aa.t),fact(aa.fact),stl(aa.stl),	dir(aa.dir),a(aa.a),b(aa.b),org(aa.org), v0(aa.v0),v1(aa.v1),v2(aa.v2),o(aa.o),	f(aa.f),txt(aa.txt),	ch(aa.ch),	pos(aa.pos),sh(aa.sh),inv(aa.inv)	{}
+#endif
+
+	const mglAxis &operator=(const mglAxis &aa)
+	{	dv=aa.dv; ds=aa.ds; d=aa.d; ns=aa.ns; t=aa.t; fact=aa.fact; stl=aa.stl;
+		dir=aa.dir; a=aa.a; b=aa.b; org=aa.org; v0=aa.v0; v1=aa.v1; v2=aa.v2; o=aa.o;
+		f=aa.f; txt=aa.txt; 	ch=aa.ch; pos=aa.pos; sh=aa.sh; inv=aa.inv;	return aa;	}
+	inline void AddLabel(const std::wstring &lbl, mreal v)
+	{	if(mgl_isfin(v))	txt.push_back(mglText(L' '+lbl+L' ',v));	}
+	inline void Clear()
+	{	dv=ds=d=v0=v1=v2=sh=0;	o=NAN;	ns=f=0;	pos = 't';	inv=false;
+		fact.clear();	stl.clear();	t.clear();	txt.clear();	}
+
+	mreal dv,ds;	///< Actual step for ticks and subticks.
+	mreal d;		///< Step for axis ticks (if positive) or its number (if negative).
+	int ns;			///< Number of axis subticks.
+	std::wstring t;	///< Tick template (set "" to use default one ("%.2g" in simplest case))
+	std::wstring fact;	///< Factor which should be placed after number (like L"\pi")
+	std::string stl;	///< Tick styles (default is ""=>"3m")
+	mglPoint dir;	///< Axis direction
+	mglPoint a,b;	///< Directions of over axis
+	mglPoint org;
+	mreal v0;		///< Center of axis cross section
+	mreal v1;		///< Minimal axis range.
+	mreal v2;		///< Maximal axis range.
+	mreal o;		///< Point of starting ticks numbering (if NAN then Org is used).
+	int f;			///< Flag 0x1 - time, 0x2 - manual, 0x4 - fixed dv
+	std::vector<mglText> txt;	///< Axis labels
+	char ch;		///< Character of axis (like 'x','y','z','c')
+	char pos;		///< Text position ('t' by default, or 'T' for opposite)
+	mreal sh;		///< Extra shift of ticks and axis labels
+	bool inv;		///< Inverse automatic origin position
+	mreal angl;		///< Manual for ticks rotation (if not NAN)
+};
+//-----------------------------------------------------------------------------
+class mglCanvas;
+/// Structure for drawing region
+struct MGL_EXPORT mglDrawReg
+{
+	mglDrawReg() {}
+	mglDrawReg(const mglDrawReg &aa) : PDef(aa.PDef),angle(aa.angle),ObjId(aa.ObjId),PenWidth(aa.PenWidth),pPos(aa.pPos) ,x1(aa.x1),x2(aa.x2),y1(aa.y1),y2(aa.y2)	{}
+#if MGL_HAVE_RVAL
+	mglDrawReg(mglDrawReg &&aa) : PDef(aa.PDef),angle(aa.angle),ObjId(aa.ObjId),PenWidth(aa.PenWidth),pPos(aa.pPos) ,x1(aa.x1),x2(aa.x2),y1(aa.y1),y2(aa.y2)	{}
+#endif
+	inline void copy(const mglPrim &p)
+	{	PDef = p.n3;	pPos = p.s;	ObjId = p.id;	PenWidth=p.w;	angle = p.angl;
+		if(p.type==2 || p.type==3) PDef = p.m;	}
+	inline const mglDrawReg &operator=(const mglDrawReg &aa)
+	{	memcpy(this,&aa,sizeof(mglDrawReg));	return aa;	}
+	union
+	{
+		uint64_t PDef;
+		unsigned char m[8];
+	};
+	int angle;	///< mask rotation values in degrees
+	int ObjId;
+	mreal PenWidth, pPos;
+	int x1,x2,y1,y2;
+	void set(mglCanvas *gr, int nx, int ny, int m);
+};
+//-----------------------------------------------------------------------------
+/// Structure contains everything for drawing
+struct MGL_EXPORT mglDrawDat
+{
+	mglDrawDat() {}
+	mglDrawDat(const mglDrawDat &aa) : Pnt(aa.Pnt),Prm(aa.Prm),Sub(aa.Sub),Ptx(aa.Ptx),Glf(aa.Glf),Txt(aa.Txt)	{}
+#if MGL_HAVE_RVAL
+	mglDrawDat(mglDrawDat &&aa) : Pnt(aa.Pnt),Prm(aa.Prm),Sub(aa.Sub),Ptx(aa.Ptx),Glf(aa.Glf),Txt(aa.Txt)	{}
+#endif
+	inline const mglDrawDat&operator=(const mglDrawDat &aa)
+	{	Pnt=aa.Pnt;	Prm=aa.Prm;	Ptx=aa.Ptx;	Glf=aa.Glf;	Txt=aa.Txt;	Sub=aa.Sub;	return aa;	}
+	mglStack<mglPnt>  Pnt;	///< Internal points
+	mglStack<mglPrim> Prm;	///< Primitives (lines, triangles and so on) -- need for export
+	std::vector<mglBlock> Sub;	///< InPlot regions
+	std::vector<mglText> Ptx;	///< Text labels for mglPrim
+	std::vector<mglGlyph> Glf;	///< Glyphs data
+	std::vector<mglTexture> Txt;	///< Pointer to textures
+};
+#if defined(_MSC_VER)
+template class MGL_EXPORT std::vector<mglDrawDat>;
+#endif
+//-----------------------------------------------------------------------------
+union mglRGBA	{	uint32_t c; unsigned char r[4];	};
+//-----------------------------------------------------------------------------
+/// Class contains all functionality for creating different mathematical plots
+class MGL_EXPORT mglCanvas : public mglBase
+{
+friend struct mglPrim;
+friend struct mglDrawReg;
+public:
+using mglBase::Light;
+
+	mglCanvas(int w=800, int h=600);
+	virtual ~mglCanvas();
+
+	/// Set default parameter for plotting
+	void DefaultPlotParam();
+
+	/// Set angle of view indepently from mglCanvas::Rotate()
+	virtual void View(mreal tetx,mreal tetz,mreal tety=0);
+	/// Zoom in or zoom out (if Zoom(0, 0, 1, 1)) a part of picture
+	virtual void Zoom(mreal x1, mreal y1, mreal x2, mreal y2);
+	/// Restore image after View() and Zoom()
+	inline void Restore()	{	Zoom(0,0,1,1);	}
+
+	/// Clear transformation matrix.
+	inline void Identity(bool rel=false)	{	InPlot(0,1,0,1,rel);	}
+	inline void Identity(mglMatrix &M, bool rel=false)	{	InPlot(M,0,1,0,1,rel);	}
+	/// Push transformation matrix into stack
+	void Push();
+	/// Set PlotFactor
+	inline void SetPlotFactor(mreal val)
+	{	if(val<=0)	{B.pf=1.55;	set(MGL_AUTO_FACTOR);}	else {B.pf=val;	clr(MGL_AUTO_FACTOR);}	}
+	/// Get PlotFactor
+	inline mreal GetPlotFactor()	{	return B.pf;	}
+	/// Pop transformation matrix from stack
+	inline void Pop()	{	B = stack.back(); stack.pop_back();	}
+	/// Clear up the frame
+	virtual void Clf(mglColor back=NC);
+	virtual void Clf(const char *col);
+
+	/// Put further plotting in cell of stick rotated on angles tet, phi
+	void StickPlot(int num, int i, mreal tet, mreal phi);
+	/// Put further plotting in cell of stick sheared on sx, sy
+	void ShearPlot(int num, int i, mreal sx, mreal sy, mreal xd, mreal yd);
+	/// Put further plotting in some region of whole frame surface.
+	inline void InPlot(mreal x1,mreal x2,mreal y1,mreal y2,bool rel=true)
+	{	InPlot(B,x1,x2,y1,y2,rel);	}
+	void InPlot(mreal x1,mreal x2,mreal y1,mreal y2, const char *style);
+	void InPlot(mglMatrix &M,mreal x1,mreal x2,mreal y1,mreal y2,bool rel=true);
+	/// Add title for current subplot/inplot
+	void Title(const char *title,const char *stl="#",mreal size=-2);
+	void Title(const wchar_t *title,const char *stl="#",mreal size=-2);
+	/// Set aspect ratio for further plotting.
+	void Aspect(mreal Ax,mreal Ay,mreal Az);
+	/// Shear a further plotting.
+	void Shear(mreal Sx,mreal Sy);
+	/// Rotate a further plotting.
+	void Rotate(mreal TetX,mreal TetZ,mreal TetY=0);
+	/// Rotate a further plotting around vector {x,y,z}.
+	void RotateN(mreal Tet,mreal x,mreal y,mreal z);
+	/// Set perspective (in range [0,1)) for plot. Set to zero for switching off. Return the current perspective.
+	void Perspective(mreal a, bool req=true)
+	{	if(req)	persp = Bp.pf = a;	else	Bp.pf = persp?persp:fabs(a);	}
+
+	/// Set size of frame in pixels. Normally this function is called internaly.
+	virtual void SetSize(int w,int h,bool clf=true);
+	/// Get ratio (mreal width)/(mreal height).
+	mreal GetRatio() const MGL_FUNC_PURE;
+	/// Get bitmap data prepared for saving to file
+	virtual unsigned char **GetRGBLines(long &w, long &h, unsigned char *&f, bool alpha=false);
+	/// Get RGB bitmap of current state image.
+	virtual const unsigned char *GetBits();
+	/// Get RGBA bitmap of background image.
+	const unsigned char *GetBackground()	{	return GB;	};
+	/// Get RGBA bitmap of current state image.
+	const unsigned char *GetRGBA()	{	Finish();	return G4;	}
+	/// Get width of the image
+	int GetWidth() const	{	return Width;	}
+	/// Get height of the image
+	int GetHeight() const	{	return Height;	}
+	/// Combine plots from 2 canvases. Result will be saved into this.
+	void Combine(const mglCanvas *gr);
+	/// Set boundary box for export graphics into 2D file formats
+	void SetBBox(int x1=0, int y1=0, int x2=-1, int y2=-1)
+	{	BBoxX1=x1;	BBoxY1=y1;	BBoxX2=x2;	BBoxY2=y2;	}
+
+	/// Rasterize current plot and set it as background image
+	void Rasterize();
+	/// Load image for background from file
+	void LoadBackground(const char *fname, double alpha=1);
+	/// Fill background image by specified color
+	void FillBackground(const mglColor &cc);
+
+	inline mreal GetDelay() const	{	return Delay;	}
+	inline void SetDelay(mreal d)	{	Delay=d;	}
+
+	/// Calculate 3D coordinate {x,y,z} for screen point {xs,ys}
+	mglPoint CalcXYZ(int xs, int ys, bool real=false) const MGL_FUNC_PURE;
+	/// Calculate screen point {xs,ys} for 3D coordinate {x,y,z}
+	void CalcScr(mglPoint p, int *xs, int *ys) const;
+	mglPoint CalcScr(mglPoint p) const;
+	/// Set object/subplot id
+	inline void SetObjId(long id)	{	ObjId = id;	}
+	/// Get object id
+	inline int GetObjId(long xs,long ys) const
+	{	long i=xs+Width*ys;	return (i>=0 && i<Width*Height)?OI[i]:-1;	}
+	/// Get subplot id
+	int GetSplId(long xs,long ys) const MGL_FUNC_PURE;
+	/// Check if there is active point or primitive (n=-1)
+	int IsActive(int xs, int ys,int &n);
+
+	/// Create new frame.
+	virtual int NewFrame();
+	/// Finish frame drawing
+	virtual void EndFrame();
+	/// Get the number of created frames
+	inline int GetNumFrame() const	{	return CurFrameId;	}
+	/// Reset frames counter (start it from zero)
+	virtual void ResetFrames();
+	/// Delete primitives for i-th frame
+	virtual void DelFrame(long i);
+	/// Get drawing data for i-th frame.
+	void GetFrame(long i);
+	/// Set drawing data for i-th frame. This work as EndFrame() but don't add frame to GIF image.
+	virtual void SetFrame(long i);
+	/// Add drawing data from i-th frame to the current drawing
+	void ShowFrame(long i);
+	/// Clear list of primitives for current drawing
+	void ClearFrame();
+
+	/// Start write frames to cinema using GIF format
+	void StartGIF(const char *fname, int ms=100);
+	/// Stop writing cinema using GIF format
+	void CloseGIF();
+	/// Finish plotting. Normally this function is called internaly.
+	virtual void Finish();
+	/// Export points and primitives in file using MGLD format
+	bool ExportMGLD(const char *fname, const char *descr=0);
+	/// Import points and primitives from file using MGLD format
+	bool ImportMGLD(const char *fname, bool add=false);
+	/// Export in JSON format suitable for later drawing by JavaScript
+	bool WriteJSON(const char *fname, bool force_zlib=false);
+	std::string GetJSON();
+
+	/// Set the transparency type
+	inline void SetTranspType(int val)
+	{	Flag=(Flag&(~3)) + (val&3);	SetAxisStl(val==2?"w-":"k-");	}
+	/// Set the fog distance or switch it off (if d=0).
+	virtual void Fog(mreal d, mreal dz=0.25);
+	/// Switch on/off the specified light source.
+	virtual void Light(int n, bool enable);
+	/// Add a light source.
+	virtual void AddLight(int n,mglPoint r, mglPoint d, char c='w', mreal bright=0.5, mreal ap=0);
+	inline void AddLight(int n,mglPoint d, char c='w', mreal bright=0.5, mreal ap=0)
+	{	AddLight(n,mglPoint(NAN),d,c,bright,ap);	}
+
+	/// Set ticks position and text (\n separated). Use n=0 to disable this feature.
+	void SetTicksVal(char dir, const char *lbl, bool add=false);
+	void SetTicksVal(char dir, HCDT v, const char *lbl, bool add=false);
+	void SetTicksVal(char dir, HCDT v, const char **lbl, bool add=false);
+	void SetTicksVal(char dir, const wchar_t *lbl, bool add=false);
+	void SetTicksVal(char dir, HCDT v, const wchar_t *lbl, bool add=false);
+	void SetTicksVal(char dir, HCDT v, const wchar_t **lbl, bool add=false);
+		/// Add manual tick at given position. Use "" to disable this feature.
+	void AddTick(char dir, double val, const char *lbl);
+	void AddTick(char dir, double val, const wchar_t *lbl);
+
+	/// Set templates for ticks
+	void SetTickTempl(char dir, const wchar_t *t);
+	void SetTickTempl(char dir, const char *t);
+	/// Set time templates for ticks
+	void SetTickTime(char dir, mreal d=0, const char *t="");
+	/// Set the ticks parameters
+	void SetTicks(char dir, mreal d=0, int ns=0, mreal org=NAN, const wchar_t *lbl=0);
+	/// Auto adjust ticks
+	void AdjustTicks(const char *dir="xyzc", bool force=false, std::string stl="");
+	/// Tune ticks
+	inline void SetTuneTicks(int tune, mreal pos=1.15)
+	{	TuneTicks = tune;	FactorPos = pos;	}
+	/// Set ticks styles
+	void SetAxisStl(const char *stl="k", const char *tck=0, const char *sub=0);
+	/// Set ticks length
+	void SetTickLen(mreal tlen, mreal stt=1.);
+
+	/// Draws bounding box outside the plotting volume with color c.
+	void Box(const char *col=0, bool ticks=true);
+	/// Draw axises with ticks in directions determined by string parameter dir.
+	void Axis(const char *dir="xyzt", const char *stl="", const char *opt="");
+	/// Draw grid lines perpendicular to direction determined by string parameter dir.
+	void Grid(const char *dir="xyzt",const char *pen="B-", const char *opt="");
+	/// Print the label text for axis dir.
+	void Label(char dir, const char *text, mreal pos=0, const char *opt="");
+	void Labelw(char dir, const wchar_t *text, mreal pos=0, const char *opt="");
+
+	/// Draw colorbar at edge of axis
+	void Colorbar(const char *sch=0);
+	void Colorbar(const char *sch, mreal x, mreal y, mreal w, mreal h);
+	/// Draw colorbar at edge of axis for manual colors
+	void Colorbar(HCDT v, const char *sch=0);
+	void Colorbar(HCDT v, const char *sch, mreal x, mreal y, mreal w, mreal h);
+
+	/// Draw legend of accumulated strings at position (x, y) by font with size
+	inline void Legend(mreal x, mreal y, const char *font="#", const char *opt="")
+	{	Legend(Leg,x,y,font,opt);	}
+	/// Draw legend of accumulated strings by font with size
+	inline void Legend(int where=0x3, const char *font="#", const char *opt="")
+	{	Legend(Leg,(where&1)?1:0,(where&2)?1:0,font,opt);	}
+	/// Draw legend of accumulated strings by font with size
+	inline void Legend(const std::vector<mglText> &leg, int where=3, const char *font="#", const char *opt="")
+	{	Legend(leg,(where&1)?1:0,(where&2)?1:0,font,opt);	}
+	/// Draw legend strings text at position (x, y) by font with size
+	void Legend(const std::vector<mglText> &leg, mreal x, mreal y, const char *font="#", const char *opt="");
+	/// Number of marks in legend sample
+	inline void SetLegendMarks(int num=1)	{	LegendMarks = num>0?num:1;	}
+
+	/// Draw table for values val along given direction with row labels text at given position
+	void Table(mreal x, mreal y, HCDT val, const wchar_t *text, const char *fnt, const char *opt);
+
+	void StartAutoGroup (const char *);
+	void EndGroup();
+	/// Set extra shift for tick and axis labels
+	inline void SetTickShift(mglPoint p)
+	{	ax.sh = p.x;	ay.sh = p.y;	az.sh = p.z;	ac.sh = p.c;	}
+	/// Get rotation angle for glyph
+	float GetGlyphPhi(const mglPnt &q, float phi);
+
+	// Following arrays are open for advanced users only. It is not recommended to change them directly
+	float *Z;			///< Height for given level in Z-direction (size 3*width*height)
+	unsigned char *C;	///< Picture for given level in Z-direction (size 3*4*width*height)
+	int *OI;			///< ObjId arrays (size width*height)
+	/// Plot point p with color c
+	void pnt_plot(long x,long y,mreal z,const unsigned char c[4], int obj_id);
+	void pnt_fast(long x,long y,mreal z,const unsigned char c[4], int obj_id);
+	/// preparing primitives for 2d export or bitmap drawing (0 default, 1 for 2d vector, 2 for 3d vector)
+	void PreparePrim(int fast);
+	inline uint32_t GetPntCol(long i) const	{	return pnt_col[i];	}
+	inline uint32_t GetPrmCol(long i, bool sort=true) const	{	return GetColor(GetPrm(i, sort));	}
+	/// Set the size of semi-transparent area around lines, marks, ...
+	inline void SetPenDelta(float d)	{	pen_delta = 1.5*fabs(d);	}
+
+protected:
+	mreal Delay;		///< Delay for animation in seconds
+	// NOTE: Z should be float for reducing space and for compatibility reasons
+	unsigned char *G4;	///< Final picture in RGBA format. Prepared in Finish().
+	unsigned char *G;	///< Final picture in RGB format. Prepared in Finish().
+	unsigned char *GB;	///< Background picture in RGBA format.
+	std::vector<mglDrawDat> DrwDat;	///< Set of ALL drawing data for each frames
+
+	int LegendMarks;	///< Number of marks in the Legend
+	unsigned char BDef[4];	///< Background color
+	mglAxis ax,ay,az,ac;///< Axis parameters
+
+	int TuneTicks;		///< Draw tuned ticks with extracted common component
+	mreal FactorPos;	///< Position of axis ticks factor (0 at Min, 1 at Max, 1.1 is default)
+	mreal TickLen;		///< Length of tiks (subticks length is sqrt(1+st_t)=1.41... times smaller)
+	char AxisStl[32];	///< Axis line style. Default is "k"
+	char TickStl[32];	///< Tick line style. Default is "k"
+	char SubTStl[32];	///< Subtick line style. Default is "k"
+	mreal st_t;			///< Subtick-to-tick ratio (ls=lt/sqrt(1+st_t)). Default is 1.
+
+	int CurFrameId;		///< Number of automaticle created frames
+	int Width;			///< Width of the image
+	int Height;			///< Height of the image
+	int Depth;			///< Depth of the image
+	mreal inW, inH;		///< Width and height of last InPlot
+	mreal inX, inY;		///< Coordinates of last InPlot
+	mglLight light[10];	///< Light sources
+	mreal FogDist;		///< Inverse fog distance (fog ~ exp(-FogDist*Z))
+	mreal FogDz;		///< Relative shift of fog
+
+	/// Auto adjust ticks
+	void AdjustTicks(mglAxis &aa, bool ff);
+	/// Prepare labels for ticks
+	void LabelTicks(mglAxis &aa);
+	/// Draw axis
+	void DrawAxis(mglAxis &aa, bool text=true, char arr=0,const char *stl="",mreal angl=NAN);
+	/// Draw axis grid lines
+	void DrawGrid(mglAxis &aa, bool at_tick=false);
+	/// Update axis ranges
+	inline void UpdateAxis()
+	{	ax.v0=Org.x;	ay.v0=Org.y;	az.v0=Org.z;	ac.v0=Org.c;
+		ax.v1=Min.x;	ay.v1=Min.y;	az.v1=Min.z;	ac.v1=Min.c;
+		ax.v2=Max.x;	ay.v2=Max.y;	az.v2=Max.z;	ac.v2=Max.c;	}
+
+	/// Clear ZBuffer only
+	void ClfZB(bool force=false);
+	/// Scale coordinates and cut off some points
+	bool ScalePoint(const mglMatrix *M, mglPoint &p, mglPoint &n, bool use_nan=true) const;
+	void LightScale(const mglMatrix *M);	///< Additionally scale positions of light sources
+	void LightScale(const mglMatrix *M, mglLight &l);	///< Additionally scale positions of light
+	/// Push drawing data (for frames only). NOTE: can be VERY large
+	long PushDrwDat();
+	/// Retur color for primitive depending lighting
+	uint32_t GetColor(const mglPrim &p) const MGL_FUNC_PURE;
+
+	mreal GetOrgX(char dir, bool inv=false) const MGL_FUNC_PURE;	///< Get Org.x (parse NAN value)
+	mreal GetOrgY(char dir, bool inv=false) const MGL_FUNC_PURE;	///< Get Org.y (parse NAN value)
+	mreal GetOrgZ(char dir, bool inv=false) const MGL_FUNC_PURE;	///< Get Org.z (parse NAN value)
+
+	void mark_plot(long p, char type, mreal size=1);
+	void arrow_plot(long p1, long p2, char st);
+	void line_plot(long p1, long p2);
+	void trig_plot(long p1, long p2, long p3);
+	void quad_plot(long p1, long p2, long p3, long p4);
+	void Glyph(mreal x, mreal y, mreal f, int style, long icode, mreal col);
+	void smbl_plot(long p1, char id, double size);
+	mreal text_plot(long p,const wchar_t *text,const char *fnt,mreal size=-1,mreal sh=0,mreal  col=-('k'), bool rot=true);
+
+	void add_prim(mglPrim &a);	///< add primitive to list
+	void arrow_draw(const mglPnt &p1, const mglPnt &p2, char st, mreal size, const mglDrawReg *d);
+	virtual void mark_draw(const mglPnt &p, char type, mreal size, mglDrawReg *d);
+	virtual void line_draw(const mglPnt &p1, const mglPnt &p2, const mglDrawReg *d);
+	virtual void trig_draw(const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, bool anorm, const mglDrawReg *d);
+	virtual void quad_draw(const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, const mglPnt &p4, const mglDrawReg *d);
+	virtual void pnt_draw(const mglPnt &p, const mglDrawReg *d);
+	void arrow_draw(long n1, long n2, char st, float ll);
+	void arrow_plot_3d(long n1, long n2, char st, float ll);
+	void glyph_draw(const mglPrim &P, mglDrawReg *d);
+	void glyph_draw_new(const mglPrim &P, mglDrawReg *d);
+	bool IsSame(const mglPrim &pr,mreal wp,mglColor cp,int st);
+
+	// check if visible
+	bool trig_vis(const mglPnt &p1, const mglPnt &p2, const mglPnt &p3) const;
+	bool quad_vis(const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, const mglPnt &p4) const;
+
+	// functions for glyph drawing
+	virtual void glyph_fill(mreal phi, const mglPnt &p, mreal f, const mglGlyph &g, const mglDrawReg *d);
+	void glyph_wire(mreal phi, const mglPnt &p, mreal f, const mglGlyph &g, const mglDrawReg *d);
+	void glyph_line(mreal phi, const mglPnt &p, mreal f, bool solid, const mglDrawReg *d);
+
+	// restore normalized coordinates from screen ones
+	mglPoint RestorePnt(mglPoint ps, bool norm=false) const MGL_FUNC_PURE;
+
+	// functions for multi-threading
+	void pxl_pntcol(long id, long n, const void *);
+	void pxl_combine(long id, long n, const void *);
+	void pxl_memcpy(long id, long n, const void *);
+	void pxl_backgr(long id, long n, const void *);
+	void pxl_primdr(long id, long n, const void *);
+	void pxl_dotsdr(long id, long n, const void *);
+	void pxl_primpx(long id, long n, const void *);
+	void pxl_transform(long id, long n, const void *);
+	void pxl_setz(long id, long n, const void *);
+	void pxl_setz_adv(long id, long n, const void *);
+	void pxl_other(long id, long n, const void *p);
+	/// Put drawing from other mglCanvas (for multithreading, like subplots)
+	void PutDrawReg(mglDrawReg *d, const mglCanvas *gr);
+
+private:
+    mglCanvas(const mglCanvas &){}	// copying is not allowed
+	const mglCanvas &operator=(const mglCanvas &t){return t;}	// copying is not allowed
+
+	uint32_t *pnt_col;
+//	mreal _tetx,_tety,_tetz;		// extra angles
+	std::vector<mglMatrix> stack;	///< stack for transformation matrices
+	GifFileType *gif;
+	mreal fscl,ftet;	///< last scale and rotation for glyphs
+	long forg;			///< original point (for directions)
+	size_t grp_counter;	///< Counter for StartGroup(); EndGroup();
+	mglMatrix Bt;		///< temporary matrix for text
+	float pen_delta;	///< delta pen width (dpw) -- the size of semi-transparent region for lines, marks, ...
+
+	/// Draw generic colorbar
+	void colorbar(HCDT v, const mreal *s, int where, mreal x, mreal y, mreal w, mreal h, bool text);
+	/// Draw labels for ticks
+	void DrawLabels(mglAxis &aa, bool inv=false, const mglMatrix *M=0);
+	/// Get label style
+	char GetLabelPos(mreal c, long kk, mglAxis &aa);
+	/// Draw tick
+	void tick_draw(mglPoint o, mglPoint d1, mglPoint d2, int f);
+	mreal FindOptOrg(char dir, int ind) const MGL_FUNC_PURE;
+	/// Transform mreal color and alpha to bits format
+	unsigned char* col2int(const mglPnt &p, unsigned char *r, int obj_id) const;
+	/// Combine colors in 2 plane.
+	void combine(unsigned char *c1, const unsigned char *c2) const;
+	/// Fast drawing of line between 2 points
+	void fast_draw(const mglPnt &p1, const mglPnt &p2, const mglDrawReg *d);
+
+	/// Additionally scale points p for positioning in image
+	void PostScale(const mglMatrix *M, mglPoint &p) const;
+	/// Scale points p for projection to the face number nface in image
+	long ProjScale(int nface, long p, bool text=false);
+	/// Set coordinate and add the point, return its id
+	long setPp(mglPnt &q, const mglPoint &p);
+
+	// fill pixel for given primitive
+	void mark_pix(long i,long j,const mglPnt &p, char type, mreal size, mglDrawReg *d);
+	void arrow_pix(long i,long j,const mglPnt &p1, const mglPnt &p2, char st, mreal size, const mglDrawReg *d);
+	void line_pix(long i,long j,const mglPnt &p1, const mglPnt &p2, const mglDrawReg *d);
+	void trig_pix(long i,long j,const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, bool anorm, const mglDrawReg *d);
+	void quad_pix(long i,long j,const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, const mglPnt &p4, const mglDrawReg *d);
+	void glyph_pix(long i,long j,const mglPrim &P, mglDrawReg *d);
+	void pnt_pix(long i,long j,const mglPnt &p, const mglDrawReg *d);
+	void glyph_fpix(long i,long j,const mglMatrix *M, const mglPnt &p, mreal f, const mglGlyph &g, const mglDrawReg *d);
+	void glyph_wpix(long i,long j,const mglMatrix *M, const mglPnt &p, mreal f, const mglGlyph &g, const mglDrawReg *d);
+	void glyph_lpix(long i,long j,const mglMatrix *M, const mglPnt &p, mreal f, bool solid, const mglDrawReg *d);
+};
+//-----------------------------------------------------------------------------
+struct mglThreadG
+{
+	mglCanvas *gr;		// grapher
+	void (mglCanvas::*f)(long i, long n, const void *);
+	unsigned id;		// thread id
+	long n;	// total number of iteration
+	const void *p;		// external parameter
+};
+/// Start several thread for the task
+void mglStartThread(void (mglCanvas::*func)(long i, long n), mglCanvas *gr, long n);
+//-----------------------------------------------------------------------------
+inline mreal get_persp(float pf, float z, float Depth)
+//{	return (1-pf)/(1-pf*z/Depth);	}
+{	return (1-pf/1.37)/(1-pf*z/Depth);	}
+inline mreal get_pfact(float pf, float Depth)
+//{	return pf/(1-pf)/Depth;	}
+{	return pf/(1-pf/1.37)/Depth;	}
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/canvas_cf.h b/include/mgl2/canvas_cf.h
new file mode 100644
index 0000000..7dcec57
--- /dev/null
+++ b/include/mgl2/canvas_cf.h
@@ -0,0 +1,715 @@
+/***************************************************************************
+ * canvas_cf.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef MGL_CANVAS_CF_H
+#define MGL_CANVAS_CF_H
+#include "mgl2/abstract.h"
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// Create HMGL object with specified sizes
+HMGL MGL_EXPORT mgl_create_graph(int width, int height);
+uintptr_t MGL_EXPORT mgl_create_graph_(int *width, int *height);
+/// Delete HMGL object
+void MGL_EXPORT mgl_delete_graph(HMGL gr);
+void MGL_EXPORT mgl_delete_graph_(uintptr_t *gr);
+/// Set size of frame in pixels. Normally this function is called internally.
+void MGL_EXPORT mgl_set_size(HMGL gr, int width, int height);
+void MGL_EXPORT mgl_set_size_(uintptr_t *gr, int *width, int *height);
+/// Set size of frame in pixels, but don't erase primitives
+void MGL_EXPORT mgl_scale_size(HMGL gr, int width, int height);
+void MGL_EXPORT mgl_scale_size_(uintptr_t *gr, int *width, int *height);
+/// Scaling for all further set size calls.
+void MGL_EXPORT mgl_set_size_scl(double scl);
+void MGL_EXPORT mgl_set_size_scl_(double *scl);
+/// Set default parameters for plotting
+void MGL_EXPORT mgl_set_def_param(HMGL gr);
+void MGL_EXPORT mgl_set_def_param_(uintptr_t *gr);
+/// Combine plots from 2 canvases. Result will be saved into gr
+void MGL_EXPORT mgl_combine_gr(HMGL gr, HMGL gr2);
+void MGL_EXPORT mgl_combine_gr_(uintptr_t *gr, uintptr_t *gr2);
+/// Force preparing the image. It can be useful for OpenGL mode mostly.
+void MGL_EXPORT mgl_finish(HMGL gr);
+void MGL_EXPORT mgl_finish_(uintptr_t *gr);
+/// Force preparing the image and save result into background one.
+void MGL_EXPORT mgl_rasterize(HMGL gr);
+void MGL_EXPORT mgl_rasterize_(uintptr_t *gr);
+/// Set boundary box for export graphics into 2D file formats.
+/** If x2<0 (y2<0) then full width (height) will be used.
+ *  If x1<0 or y1<0 or x1>=x2|Width or y1>=y2|Height then cropping will be disabled. */
+void MGL_EXPORT mgl_set_bbox(HMGL gr, int x1, int y1, int x2, int y2);
+void MGL_EXPORT mgl_set_bbox_(uintptr_t *gr, int *x1, int *y1, int *x2, int *y2);
+
+/// Set the size of semi-transparent area around lines, marks, glyphs, ... Default is 1.
+void MGL_EXPORT mgl_pen_delta(HMGL gr, double d);
+void MGL_EXPORT mgl_pen_delta_(uintptr_t *gr, double *d);
+
+/// Set tick length
+void MGL_EXPORT mgl_set_tick_len(HMGL gr, double len, double stt);
+void MGL_EXPORT mgl_set_tick_len_(uintptr_t *gr, mreal *len, mreal *stt);
+/// Set axis and ticks style
+void MGL_EXPORT mgl_set_axis_stl(HMGL gr, const char *stl, const char *tck, const char *sub);
+void MGL_EXPORT mgl_set_axis_stl_(uintptr_t *gr, const char *stl, const char *tck, const char *sub, int,int,int);
+
+/// Auto adjust ticks
+void MGL_EXPORT mgl_adjust_ticks(HMGL gr, const char *dir);
+void MGL_EXPORT mgl_adjust_ticks_(uintptr_t *gr, const char *dir, int);
+/// Auto adjust ticks and set ticks format ("+E0123456789-fF")
+void MGL_EXPORT mgl_adjust_ticks_ext(HMGL gr, const char *dir, const char *stl);
+void MGL_EXPORT mgl_adjust_ticks_ext_(uintptr_t *gr, const char *dir, const char *stl, int, int);
+/// Set the ticks parameters
+void MGL_EXPORT mgl_set_ticks(HMGL gr, char dir, double d, int ns, double org);
+void MGL_EXPORT mgl_set_ticks_(uintptr_t *gr, char *dir, mreal *d, int *ns, mreal *org, int);
+/// Set the ticks parameters and specify ticks factor string
+void MGL_EXPORT mgl_set_ticks_fact(HMGL gr, char dir, double d, int ns, double org, const char *fact);
+void MGL_EXPORT mgl_set_ticks_factw(HMGL gr, char dir, double d, int ns, double org, const wchar_t *fact);
+void MGL_EXPORT mgl_set_ticks_fact_(uintptr_t *gr, char *dir, double *d, int *ns, double *org, const char *fact,int,int);
+
+/// Set manual ticks text (\n separated). Use "" to disable this feature.
+void MGL_EXPORT mgl_set_ticks_str(HMGL gr, char dir, const char *lbl, int add);
+void MGL_EXPORT mgl_set_ticks_str_(uintptr_t *gr, const char *dir, const char *lbl, int *add,int,int);
+void MGL_EXPORT mgl_set_ticks_wcs(HMGL gr, char dir, const wchar_t *lbl, int add);
+/// Set manual ticks position and text (\n separated). Use "" to disable this feature.
+void MGL_EXPORT mgl_set_ticks_val(HMGL gr, char dir, HCDT val, const char *lbl, int add);
+void MGL_EXPORT mgl_set_ticks_val_(uintptr_t *gr, const char *dir, uintptr_t *val, const char *lbl, int *add,int,int);
+void MGL_EXPORT mgl_set_ticks_valw(HMGL gr, char dir, HCDT val, const wchar_t *lbl, int add);
+/// Add manual tick at given position. Use "" to disable this feature.
+void MGL_EXPORT mgl_add_tick(HMGL gr, char dir, double val, const char *lbl);
+void MGL_EXPORT mgl_add_tick_(uintptr_t *gr, const char *dir, mreal *val, const char *lbl,int,int);
+void MGL_EXPORT mgl_add_tickw(HMGL gr, char dir, double val, const wchar_t *lbl);
+/// Tune ticks (tune|1 for common multiplier, tune|2 for common component)
+void MGL_EXPORT mgl_tune_ticks(HMGL gr, int tune, double fact_pos);
+void MGL_EXPORT mgl_tune_ticks_(uintptr_t *gr, int *tune, mreal *fact_pos);
+/// Set templates for ticks
+void MGL_EXPORT mgl_set_tick_templ(HMGL gr, char dir, const char *templ);
+void MGL_EXPORT mgl_set_tick_templ_(uintptr_t *gr, const char *dir, const char *templ,int,int);
+void MGL_EXPORT mgl_set_tick_templw(HMGL gr, char dir, const wchar_t *templ);
+/// Set time templates for ticks
+void MGL_EXPORT mgl_set_ticks_time(HMGL gr, char dir, double d, const char *t);
+void MGL_EXPORT mgl_set_ticks_time_(uintptr_t *gr, const char *dir, mreal *d, const char *t,int,int);
+/// Set additional shift of tick labels
+void MGL_EXPORT mgl_set_tick_shift(HMGL gr, double sx, double sy, double sz, double sc);
+void MGL_EXPORT mgl_set_tick_shift_(uintptr_t *gr, mreal *sx, mreal *sy, mreal *sz, mreal *sc);
+
+/// Draws bounding box outside the plotting volume
+void MGL_EXPORT mgl_box(HMGL gr);
+void MGL_EXPORT mgl_box_(uintptr_t *gr);
+/// Draws bounding box outside the plotting volume with color c
+/** Style ‘@’ produce filled back faces. */
+void MGL_EXPORT mgl_box_str(HMGL gr, const char *col, int ticks);
+void MGL_EXPORT mgl_box_str_(uintptr_t *gr, const char *col, int *ticks, int);
+/// Draw axises with ticks in direction(s) dir.
+/** Parameter \a dir may contain:
+ *	‘xyzt’for drawing axis in corresponding direction;
+ *	‘XYZT’ for drawing axis in corresponding direction but with inverted positions of labels;
+ *	‘~’, ‘_’ for disabling tick labels;
+ *	‘U’ for disabling rotation of tick labels;
+ *	‘^’ for inverting default axis origin;
+ *	‘!’ for disabling ticks tuning;
+ *	‘AKDTVISO’ for drawing arrow at the end of axis;
+ *	‘a’ for forced adjusting of axis ticks;
+ *	‘f’ for printing ticks labels in fixed format;
+ *	‘E’ for using ‘E’ instead of ‘e’ in ticks labels;
+ *	‘F’ for printing ticks labels in LaTeX format;
+ *	‘+’ for printing ‘+’ for positive ticks;
+ *	‘-’ for printing usual ‘-’ in ticks labels;
+ *	‘0123456789’ for precision at printing ticks labels.
+ *	 Option "value" set the manual rotation angle for the ticks.*/
+void MGL_EXPORT mgl_axis(HMGL gr, const char *dir, const char *stl, const char *opt);
+void MGL_EXPORT mgl_axis_(uintptr_t *gr, const char *dir, const char *stl, const char *opt,int,int,int);
+/// Draw grid lines perpendicular to direction(s) dir.
+void MGL_EXPORT mgl_axis_grid(HMGL gr, const char *dir,const char *pen, const char *opt);
+void MGL_EXPORT mgl_axis_grid_(uintptr_t *gr, const char *dir,const char *pen, const char *opt,int,int,int);
+/// Print the label text for axis dir.
+/** Option "value" set additional shifting of the label. */
+void MGL_EXPORT mgl_label(HMGL gr, char dir, const char *text, double pos, const char *opt);
+void MGL_EXPORT mgl_label_(uintptr_t *gr, const char *dir, const char *text, mreal *pos, const char *opt,int,int,int);
+/// Print the label text for axis dir.
+/** Option "value" set additional shifting of the label. */
+void MGL_EXPORT mgl_labelw(HMGL gr, char dir, const wchar_t *text, double pos, const char *opt);
+
+/// Draw colorbar at edge of axis
+/** Parameter \a sch may contain:
+ *	 ‘<>^_’ for positioning at left, at right, at top or at bottom correspondingly;
+ *	 ‘I’ for positioning near bounding (by default, at edges of subplot);
+ *	 ‘A’ for using absolute coordinates;
+ *	 ‘~’ for disabling tick labels.
+ *	 ‘!’ for disabling ticks tuning;
+ *	 ‘f’ for printing ticks labels in fixed format;
+ *	 ‘E’ for using ‘E’ instead of ‘e’ in ticks labels;
+ *	 ‘F’ for printing ticks labels in LaTeX format;
+ *	 ‘+’ for printing ‘+’ for positive ticks;
+ *	 ‘-’ for printing usual ‘-’ in ticks labels;
+ *	 ‘0123456789’ for precision at printing ticks labels.*/
+void MGL_EXPORT mgl_colorbar(HMGL gr, const char *sch);
+void MGL_EXPORT mgl_colorbar_(uintptr_t *gr, const char *sch,int);
+/// Draw colorbar at manual position
+/** Parameter \a sch may contain:
+ *	 ‘<>^_’ for positioning at left, at right, at top or at bottom correspondingly;
+ *	 ‘I’ for positioning near bounding (by default, at edges of subplot);
+ *	 ‘A’ for using absolute coordinates;
+ *	 ‘~’ for disabling tick labels.
+ *	 ‘!’ for disabling ticks tuning;
+ *	 ‘f’ for printing ticks labels in fixed format;
+ *	 ‘E’ for using ‘E’ instead of ‘e’ in ticks labels;
+ *	 ‘F’ for printing ticks labels in LaTeX format;
+ *	 ‘+’ for printing ‘+’ for positive ticks;
+ *	 ‘-’ for printing usual ‘-’ in ticks labels;
+ *	 ‘0123456789’ for precision at printing ticks labels.*/
+void MGL_EXPORT mgl_colorbar_ext(HMGL gr, const char *sch, double x, double y, double w, double h);
+void MGL_EXPORT mgl_colorbar_ext_(uintptr_t *gr, const char *sch, mreal *x, mreal *y, mreal *w, mreal *h, int);
+/// Draw colorbar with manual colors at edge of axis
+/** Parameter \a sch may contain:
+ *	 ‘<>^_’ for positioning at left, at right, at top or at bottom correspondingly;
+ *	 ‘I’ for positioning near bounding (by default, at edges of subplot);
+ *	 ‘A’ for using absolute coordinates;
+ *	 ‘~’ for disabling tick labels.
+ *	 ‘!’ for disabling ticks tuning;
+ *	 ‘f’ for printing ticks labels in fixed format;
+ *	 ‘E’ for using ‘E’ instead of ‘e’ in ticks labels;
+ *	 ‘F’ for printing ticks labels in LaTeX format;
+ *	 ‘+’ for printing ‘+’ for positive ticks;
+ *	 ‘-’ for printing usual ‘-’ in ticks labels;
+ *	 ‘0123456789’ for precision at printing ticks labels.*/
+void MGL_EXPORT mgl_colorbar_val(HMGL gr, HCDT dat, const char *sch);
+void MGL_EXPORT mgl_colorbar_val_(uintptr_t *gr, uintptr_t *dat, const char *sch,int);
+/// Draw colorbar with manual colors at manual position
+/** Parameter \a sch may contain:
+ *	 ‘<>^_’ for positioning at left, at right, at top or at bottom correspondingly;
+ *	 ‘I’ for positioning near bounding (by default, at edges of subplot);
+ *	 ‘A’ for using absolute coordinates;
+ *	 ‘~’ for disabling tick labels.
+ *	 ‘!’ for disabling ticks tuning;
+ *	 ‘f’ for printing ticks labels in fixed format;
+ *	 ‘E’ for using ‘E’ instead of ‘e’ in ticks labels;
+ *	 ‘F’ for printing ticks labels in LaTeX format;
+ *	 ‘+’ for printing ‘+’ for positive ticks;
+ *	 ‘-’ for printing usual ‘-’ in ticks labels;
+ *	 ‘0123456789’ for precision at printing ticks labels.*/
+void MGL_EXPORT mgl_colorbar_val_ext(HMGL gr, HCDT dat, const char *sch,double x, double y, double w, double h);
+void MGL_EXPORT mgl_colorbar_val_ext_(uintptr_t *gr, uintptr_t *dat, const char *sch, mreal *x, mreal *y, mreal *w, mreal *h, int);
+
+/// Add string to legend
+void MGL_EXPORT mgl_add_legend(HMGL gr, const char *text,const char *style);
+void MGL_EXPORT mgl_add_legend_(uintptr_t *gr, const char *text,const char *style,int,int);
+void MGL_EXPORT mgl_add_legendw(HMGL gr, const wchar_t *text,const char *style);
+/// Clear saved legend string
+void MGL_EXPORT mgl_clear_legend(HMGL gr);
+void MGL_EXPORT mgl_clear_legend_(uintptr_t *gr);
+/// Draw legend of accumulated strings at position {x,y}
+/** Parameter fnt may contain:
+ *	 font style for legend text;
+ *	 colors for background (first one), border (second one) and text (last one);
+ *	 ‘A’ for positioning in absolute coordinates;
+ *	 ‘^’ for positioning outside of specified point;
+ *	 ‘-’ for arranging entries horizontally;
+ *	 ‘#’ for drawing box around legend.
+ * Option value set the space between line samples and text (default is 0.1).*/
+void MGL_EXPORT mgl_legend_pos(HMGL gr, double x, double y, const char *font, const char *opt);
+void MGL_EXPORT mgl_legend_pos_(uintptr_t *gr, mreal *x, mreal *y, const char *font, const char *opt,int,int);
+/// Draw legend of accumulated strings
+/** Parameter fnt may contain:
+ *	 font style for legend text;
+ *	 colors for background (first one), border (second one) and text (last one);
+ *	 ‘A’ for positioning in absolute coordinates;
+ *	 ‘^’ for positioning outside of specified point;
+ *	 ‘-’ for arranging entries horizontally;
+ *	 ‘#’ for drawing box around legend.
+ * Option value set the space between line samples and text (default is 0.1).
+ * Parameter \a where sets position: 0 at bottom-left, 1 at bottom-right, 2 at top-left, 3 at top-right (default).*/
+void MGL_EXPORT mgl_legend(HMGL gr, int where, const char *font, const char *opt);
+void MGL_EXPORT mgl_legend_(uintptr_t *gr, int *where, const char *font, const char *opt,int,int);
+/// Set number of marks in legend sample
+void MGL_EXPORT mgl_set_legend_marks(HMGL gr, int num);
+void MGL_EXPORT mgl_set_legend_marks_(uintptr_t *gr, int *num);
+
+/// Show current image
+void MGL_EXPORT mgl_show_image(HMGL gr, const char *viewer, int keep);
+void MGL_EXPORT mgl_show_image_(uintptr_t *gr, const char *viewer, int *keep, int);
+/// Write the frame in file (depending extension, write current frame if fname is empty)
+void MGL_EXPORT mgl_write_frame(HMGL gr, const char *fname,const char *descr);
+void MGL_EXPORT mgl_write_frame_(uintptr_t *gr, const char *fname,const char *descr,int,int);
+/// Write the frame in file using BMP format
+void MGL_EXPORT mgl_write_tga(HMGL gr, const char *fname,const char *descr);
+void MGL_EXPORT mgl_write_tga_(uintptr_t *gr, const char *fname,const char *descr,int,int);
+/// Write the frame in file using BMP format
+void MGL_EXPORT mgl_write_bmp(HMGL gr, const char *fname,const char *descr);
+void MGL_EXPORT mgl_write_bmp_(uintptr_t *gr, const char *fname,const char *descr,int,int);
+/// Write the frame in file using JPEG format
+void MGL_EXPORT mgl_write_jpg(HMGL gr, const char *fname,const char *descr);
+void MGL_EXPORT mgl_write_jpg_(uintptr_t *gr, const char *fname,const char *descr,int,int);
+/// Write the frame in file using PNG format with transparency
+void MGL_EXPORT mgl_write_png(HMGL gr, const char *fname,const char *descr);
+void MGL_EXPORT mgl_write_png_(uintptr_t *gr, const char *fname,const char *descr,int,int);
+/// Write the frame in file using PNG format without transparency
+void MGL_EXPORT mgl_write_png_solid(HMGL gr, const char *fname,const char *descr);
+void MGL_EXPORT mgl_write_png_solid_(uintptr_t *gr, const char *fname,const char *descr,int,int);
+/// Write the frame in file using PostScript format as bitmap
+void MGL_EXPORT mgl_write_bps(HMGL gr, const char *fname,const char *descr);
+void MGL_EXPORT mgl_write_bps_(uintptr_t *gr, const char *fname,const char *descr,int,int);
+/// Write the frame in file using PostScript format
+void MGL_EXPORT mgl_write_eps(HMGL gr, const char *fname,const char *descr);
+void MGL_EXPORT mgl_write_eps_(uintptr_t *gr, const char *fname,const char *descr,int,int);
+/// Write the frame in file using SVG format
+void MGL_EXPORT mgl_write_svg(HMGL gr, const char *fname,const char *descr);
+void MGL_EXPORT mgl_write_svg_(uintptr_t *gr, const char *fname,const char *descr,int,int);
+/// Write the frame in file using LaTeX format
+void MGL_EXPORT mgl_write_tex(HMGL gr, const char *fname,const char *descr);
+void MGL_EXPORT mgl_write_tex_(uintptr_t *gr, const char *fname,const char *descr,int,int);
+/// Write the frame in file using OBJ format
+void MGL_EXPORT mgl_write_obj(HMGL gr, const char *fname,const char *descr, int use_png);
+void MGL_EXPORT mgl_write_obj_(uintptr_t *gr, const char *fname,const char *descr, int *use_png,int,int);
+/// Write the frame in file using OBJ format (old version)
+void MGL_EXPORT mgl_write_obj_old(HMGL gr, const char *fname,const char *descr, int use_png);
+void MGL_EXPORT mgl_write_obj_old_(uintptr_t *gr, const char *fname,const char *descr, int *use_png,int,int);
+/// Write the frame in file using STL format (faces only)
+void MGL_EXPORT mgl_write_stl(HMGL gr, const char *fname,const char *descr);
+void MGL_EXPORT mgl_write_stl_(uintptr_t *gr, const char *fname,const char *descr,int,int);
+/// Write the frame in file using OFF format
+void MGL_EXPORT mgl_write_off(HMGL gr, const char *fname,const char *descr, int colored);
+void MGL_EXPORT mgl_write_off_(uintptr_t *gr, const char *fname,const char *descr,int *colored,int,int);
+/// Write the frame in file using XYZ format
+void MGL_EXPORT mgl_write_xyz(HMGL gr, const char *fname,const char *descr);
+void MGL_EXPORT mgl_write_xyz_(uintptr_t *gr, const char *fname,const char *descr,int,int);
+
+/*void MGL_EXPORT mgl_write_x3d(HMGL gr, const char *fname,const char *descr);
+void MGL_EXPORT mgl_write_x3d_(uintptr_t *gr, const char *fname,const char *descr,int,int);
+void MGL_EXPORT mgl_write_wgl(HMGL gr, const char *fname,const char *descr);
+void MGL_EXPORT mgl_write_wgl_(uintptr_t *gr, const char *fname,const char *descr,int,int);*/
+
+/// Write the frame in file using PRC format
+void MGL_EXPORT mgl_write_prc(HMGL gr, const char *fname,const char *descr, int make_pdf);
+void MGL_EXPORT mgl_write_prc_(uintptr_t *gr, const char *fname,const char *descr, int *make_pdf,int,int);
+/// Write the frame in file using GIF format (only for current frame!)
+void MGL_EXPORT mgl_write_gif(HMGL gr, const char *fname,const char *descr);
+void MGL_EXPORT mgl_write_gif_(uintptr_t *gr, const char *fname,const char *descr,int,int);
+
+/// Start write frames to cinema using GIF format
+void MGL_EXPORT mgl_start_gif(HMGL gr, const char *fname,int ms);
+void MGL_EXPORT mgl_start_gif_(uintptr_t *gr, const char *fname,int *ms,int);
+/// Stop writing cinema using GIF format
+void MGL_EXPORT mgl_close_gif(HMGL gr);
+void MGL_EXPORT mgl_close_gif_(uintptr_t *gr);
+
+/// Export points and primitives in file using MGLD format
+void MGL_EXPORT mgl_export_mgld(HMGL gr, const char *fname,const char *descr);
+void MGL_EXPORT mgl_export_mgld_(uintptr_t *gr, const char *fname,const char *descr,int,int);
+/// Import points and primitives from file using MGLD format
+void MGL_EXPORT mgl_import_mgld(HMGL gr, const char *fname, int add);
+void MGL_EXPORT mgl_import_mgld_(uintptr_t *gr, const char *fname, int *add, int);
+/// Export in JSON format suitable for later drawing by JavaScript
+void MGL_EXPORT mgl_write_json(HMGL gr, const char *fname,const char *descr);
+void MGL_EXPORT mgl_write_json_(uintptr_t *gr, const char *fname,const char *descr,int,int);
+void MGL_EXPORT mgl_write_json_z(HMGL gr, const char *fname,const char *descr);
+void MGL_EXPORT mgl_write_json_z_(uintptr_t *gr, const char *fname,const char *descr,int,int);
+MGL_EXPORT const char *mgl_get_json(HMGL gr);
+
+/// Get RGB values of current bitmap
+/** Position of element {i,j} is [3*i + 3*Width*j]. */
+MGL_EXPORT const unsigned char *mgl_get_rgb(HMGL gr);
+MGL_EXPORT const unsigned char *mgl_get_rgb_(uintptr_t *gr);
+/// Get RGBA values of current bitmap
+/** Position of element {i,j} is [4*i + 4*Width*j]. */
+MGL_EXPORT const unsigned char *mgl_get_rgba(HMGL gr);
+MGL_EXPORT const unsigned char *mgl_get_rgba_(uintptr_t *gr);
+/// Get RGBA values of background image
+/** Position of element {i,j} is [4*i + 4*Width*j]. */
+MGL_EXPORT const unsigned char *mgl_get_background(HMGL gr);
+MGL_EXPORT const unsigned char *mgl_get_background_(uintptr_t *gr);
+/// Set object/subplot id
+void MGL_EXPORT mgl_set_obj_id(HMGL gr, int id);
+void MGL_EXPORT mgl_set_obj_id_(uintptr_t *gr, int *id);
+/// Get object id
+int MGL_EXPORT mgl_get_obj_id(HMGL gr, int x, int y);
+int MGL_EXPORT mgl_get_obj_id_(uintptr_t *gr, int *x, int *y);
+/// Get subplot id
+int MGL_EXPORT mgl_get_spl_id(HMGL gr, int x, int y);
+int MGL_EXPORT mgl_get_spl_id_(uintptr_t *gr, int *x, int *y);
+/// Get width of the image
+int MGL_EXPORT mgl_get_width(HMGL gr);
+int MGL_EXPORT mgl_get_width_(uintptr_t *gr);
+/// Get height of the image
+int MGL_EXPORT mgl_get_height(HMGL gr);
+int MGL_EXPORT mgl_get_height_(uintptr_t *gr);
+/// Calculate 3D coordinate {x,y,z} for screen point {xs,ys}
+void MGL_EXPORT mgl_calc_xyz(HMGL gr, int xs, int ys, mreal *x, mreal *y, mreal *z);
+void MGL_EXPORT mgl_calc_xyz_(uintptr_t *gr, int *xs, int *ys, mreal *x, mreal *y, mreal *z);
+/// Calculate screen point {xs,ys} for 3D coordinate {x,y,z}
+void MGL_EXPORT mgl_calc_scr(HMGL gr, double x, double y, double z, int *xs, int *ys);
+void MGL_EXPORT mgl_calc_scr_(uintptr_t *gr, mreal *x, mreal *y, mreal *z, int *xs, int *ys);
+/// Check if {xs,ys} is close to active point with accuracy d, and return its position or -1
+long MGL_EXPORT mgl_is_active(HMGL gr, int xs, int ys, int d);
+long MGL_EXPORT mgl_is_active_(uintptr_t *gr, int *xs, int *ys, int *d);
+
+/// Create new frame.
+int MGL_EXPORT mgl_new_frame(HMGL gr);
+int MGL_EXPORT mgl_new_frame_(uintptr_t *gr);
+/// Finish frame drawing
+void MGL_EXPORT mgl_end_frame(HMGL gr);
+void MGL_EXPORT mgl_end_frame_(uintptr_t *gr);
+/// Get the number of created frames
+int MGL_EXPORT mgl_get_num_frame(HMGL gr);
+int MGL_EXPORT mgl_get_num_frame_(uintptr_t *gr);
+/// Reset frames counter (start it from zero)
+void MGL_EXPORT mgl_reset_frames(HMGL gr);
+void MGL_EXPORT mgl_reset_frames_(uintptr_t *gr);
+/// Get drawing data for i-th frame (work if MGL_VECT_FRAME is set on)
+void MGL_EXPORT mgl_get_frame(HMGL gr, int i);
+void MGL_EXPORT mgl_get_frame_(uintptr_t *gr, int *i);
+/// Set drawing data for i-th frame (work if MGL_VECT_FRAME is set on)
+void MGL_EXPORT mgl_set_frame(HMGL gr, int i);
+void MGL_EXPORT mgl_set_frame_(uintptr_t *gr, int *i);
+/// Append drawing data from i-th frame (work if MGL_VECT_FRAME is set on)
+void MGL_EXPORT mgl_show_frame(HMGL gr, int i);
+void MGL_EXPORT mgl_show_frame_(uintptr_t *gr, int *i);
+/// Delete primitives for i-th frame (work if MGL_VECT_FRAME is set on)
+void MGL_EXPORT mgl_del_frame(HMGL gr, int i);
+void MGL_EXPORT mgl_del_frame_(uintptr_t *gr, int *i);
+/// Clear list of primitives for current drawing
+void MGL_EXPORT mgl_clear_frame(HMGL gr);
+void MGL_EXPORT mgl_clear_frame_(uintptr_t *gr);
+
+/// Set the transparency type (0 - usual, 1 - glass, 2 - lamp)
+void MGL_EXPORT mgl_set_transp_type(HMGL gr, int kind);
+void MGL_EXPORT mgl_set_transp_type_(uintptr_t *gr, int *kind);
+/// Set the transparency on/off.
+void MGL_EXPORT mgl_set_alpha(HMGL gr, int enable);
+void MGL_EXPORT mgl_set_alpha_(uintptr_t *gr, int *enable);
+/// Set the gray-scale mode on/off.
+void MGL_EXPORT mgl_set_gray(HMGL gr, int enable);
+void MGL_EXPORT mgl_set_gray_(uintptr_t *gr, int *enable);
+/// Set the fog distance or switch it off (if d=0).
+void MGL_EXPORT mgl_set_fog(HMGL gr, double d, double dz);
+void MGL_EXPORT mgl_set_fog_(uintptr_t *gr, mreal *dist, mreal *dz);
+/// Set the using of light on/off.
+void MGL_EXPORT mgl_set_light(HMGL gr, int enable);
+void MGL_EXPORT mgl_set_light_(uintptr_t *gr, int *enable);
+/// Switch on/off the specified light source.
+void MGL_EXPORT mgl_set_light_n(HMGL gr, int n, int enable);
+void MGL_EXPORT mgl_set_light_n_(uintptr_t *gr, int *n, int *enable);
+/// Set to attach light settings to inplot.
+void MGL_EXPORT mgl_set_attach_light(HMGL gr, int enable);
+void MGL_EXPORT mgl_set_attach_light_(uintptr_t *gr, int *enable);
+
+/// Add white light source at infinity.
+void MGL_EXPORT mgl_add_light(HMGL gr, int n, double x, double y, double z);
+void MGL_EXPORT mgl_add_light_(uintptr_t *gr, int *n, mreal *x, mreal *y, mreal *z);
+/// Add light source at infinity (more settings).
+void MGL_EXPORT mgl_add_light_ext(HMGL gr, int n, double x, double y, double z, char c, double br, double ap);
+void MGL_EXPORT mgl_add_light_ext_(uintptr_t *gr, int *n, mreal *x, mreal *y, mreal *z, char *c, mreal *br, mreal *ap, int);
+/// Add local light source.
+void MGL_EXPORT mgl_add_light_loc(HMGL gr, int n, double x, double y, double z, double dx, double dy, double dz, char c, double br, double ap);
+void MGL_EXPORT mgl_add_light_loc_(uintptr_t *gr, int *n, mreal *x, mreal *y, mreal *z, mreal *dx, mreal *dy, mreal *dz, char *c, mreal *br, mreal *ap, int);
+
+/// Pop transformation matrix from stack
+void MGL_EXPORT mgl_mat_pop(HMGL gr);
+void MGL_EXPORT mgl_mat_pop_(uintptr_t *gr);
+/// Push transformation matrix into stack
+void MGL_EXPORT mgl_mat_push(HMGL gr);
+void MGL_EXPORT mgl_mat_push_(uintptr_t *gr);
+
+/// Clear up the frame
+void MGL_EXPORT mgl_clf(HMGL gr);
+void MGL_EXPORT mgl_clf_(uintptr_t *gr);
+/// Clear up the frame but keep fog settings
+void MGL_EXPORT mgl_clf_nfog(HMGL gr);
+void MGL_EXPORT mgl_clf_nfog_(uintptr_t *gr);
+/// Clear up the frame and fill background by specified color
+void MGL_EXPORT mgl_clf_rgb(HMGL gr, double r, double g, double b);
+void MGL_EXPORT mgl_clf_rgb_(uintptr_t *gr, mreal *r, mreal *g, mreal *b);
+/// Clear up the frame and fill background by specified color
+void MGL_EXPORT mgl_clf_chr(HMGL gr, char col);
+void MGL_EXPORT mgl_clf_chr_(uintptr_t *gr, const char *col, int);
+/// Clear up the frame and fill background by specified color with manual transparency
+void MGL_EXPORT mgl_clf_str(HMGL gr, const char *col);
+void MGL_EXPORT mgl_clf_str_(uintptr_t *gr, const char *col, int);
+/// Load background image
+void MGL_EXPORT mgl_load_background(HMGL gr, const char *fname, double alpha);
+void MGL_EXPORT mgl_load_background_(uintptr_t *gr, const char *fname, mreal *alpha, int);
+
+/// Put further plotting in m-th cell of nx*ny grid of the image.
+/** String \a style may contain:
+ *  '<' for reserving space at left
+ *  '>' for reserving space at right
+ *  '^' for reserving space at top
+ *  '_' for reserving space at bottom
+ *  '#' for using whole region. */
+void MGL_EXPORT mgl_subplot(HMGL gr, int nx,int ny,int m,const char *style);
+void MGL_EXPORT mgl_subplot_(uintptr_t *gr, int *nx,int *ny,int *m, const char *s,int);
+/// Put further plotting in m-th cell of nx*ny grid of the image and shift it by distance {dx,dy}.
+/** String \a style may contain:
+ *  '<' for reserving space at left
+ *  '>' for reserving space at right
+ *  '^' for reserving space at top
+ *  '_' for reserving space at bottom
+ *  '#' for using whole region. */
+void MGL_EXPORT mgl_subplot_d(HMGL gr, int nx,int ny,int m,const char *style, double dx, double dy);
+void MGL_EXPORT mgl_subplot_d_(uintptr_t *gr, int *nx,int *ny,int *m, mreal *dx, mreal *dy);
+/// Put further plotting in rectangle of dx*dy cells starting from m-th cell of nx*ny grid of the image.
+/** String \a style may contain:
+ *  '<' for reserving space at left
+ *  '>' for reserving space at right
+ *  '^' for reserving space at top
+ *  '_' for reserving space at bottom
+ *  '#' for using whole region. */
+void MGL_EXPORT mgl_multiplot(HMGL gr, int nx,int ny,int m,int dx,int dy,const char *style);
+void MGL_EXPORT mgl_multiplot_(uintptr_t *gr, int *nx,int *ny,int *m,int *dx,int *dy, const char *s,int);
+/// Put further plotting in rectangle of dx*dy cells starting from m-th cell of nx*ny grid of the image and shift it by distance {sx,sy}..
+/** String \a style may contain:
+ *  '<' for reserving space at left
+ *  '>' for reserving space at right
+ *  '^' for reserving space at top
+ *  '_' for reserving space at bottom
+ *  '#' for using whole region. */
+void MGL_EXPORT mgl_multiplot_d(HMGL gr, int nx,int ny,int m,int dx,int dy,const char *style,double sx,double sy);
+void MGL_EXPORT mgl_multiplot_d_(uintptr_t *gr, int *nx,int *ny,int *m,int *dx,int *dy, const char *s, mreal *sx, mreal *sy,int);
+/// Put further plotting in a region [x1,x2]*[y1,y2] of the image (x1,x2,y1,y2 in range [0, 1]).
+void MGL_EXPORT mgl_inplot(HMGL gr, double x1,double x2,double y1,double y2);
+void MGL_EXPORT mgl_inplot_(uintptr_t *gr, mreal *x1, mreal *x2, mreal *y1, mreal *y2);
+/// Put further plotting in a region [x1,x2]*[y1,y2] of the subplot (x1,x2,y1,y2 in range [0, 1]).
+void MGL_EXPORT mgl_relplot(HMGL gr, double x1,double x2,double y1,double y2);
+void MGL_EXPORT mgl_relplot_(uintptr_t *gr, mreal *x1, mreal *x2, mreal *y1, mreal *y2);
+/// Put further plotting in column cell of previous subplot/inplot.
+void MGL_EXPORT mgl_columnplot(HMGL gr, int num, int ind, double d);
+void MGL_EXPORT mgl_columnplot_(uintptr_t *gr, int *num, int *i, mreal *d);
+/// Put further plotting in matrix cell of previous subplot/inplot.
+void MGL_EXPORT mgl_gridplot(HMGL gr, int nx, int ny, int m, double d);
+void MGL_EXPORT mgl_gridplot_(uintptr_t *gr, int *nx, int *ny, int *m, mreal *d);
+/// Put further plotting in cell of stick rotated on angles tet, phi.
+void MGL_EXPORT mgl_stickplot(HMGL gr, int num, int ind, double tet, double phi);
+void MGL_EXPORT mgl_stickplot_(uintptr_t *gr, int *num, int *i, mreal *tet, mreal *phi);
+/// Put further plotting in cell of stick sheared on sx, sy.
+void MGL_EXPORT mgl_shearplot(HMGL gr, int num, int ind, double sx, double sy, double xd, double yd);
+void MGL_EXPORT mgl_shearplot_(uintptr_t *gr, int *num, int *i, mreal *sy, mreal *sx, mreal *xd, mreal *yd);
+/// Add title for current subplot/inplot.
+/** Style '#' draw box around the title. */
+void MGL_EXPORT mgl_title(HMGL gr, const char *title, const char *stl, double size);
+void MGL_EXPORT mgl_title_(uintptr_t *gr, const char *title, const char *stl, mreal *size, int,int);
+void MGL_EXPORT mgl_titlew(HMGL gr, const wchar_t *title, const char *stl, double size);
+/// Set factor of plot size
+void MGL_EXPORT mgl_set_plotfactor(HMGL gr, double val);
+void MGL_EXPORT mgl_set_plotfactor_(uintptr_t *gr, mreal *val);
+
+/// Set aspect ratio for further plotting.
+void MGL_EXPORT mgl_aspect(HMGL gr, double Ax,double Ay,double Az);
+void MGL_EXPORT mgl_aspect_(uintptr_t *gr, mreal *Ax, mreal *Ay, mreal *Az);
+/// Set aspect ratio for further plotting.
+void MGL_EXPORT mgl_shear(HMGL gr, double Sx,double Sz);
+void MGL_EXPORT mgl_shear_(uintptr_t *gr, mreal *Sx, mreal *Sy);
+/// Rotate a further plotting.
+void MGL_EXPORT mgl_rotate(HMGL gr, double TetX,double TetZ,double TetY);
+void MGL_EXPORT mgl_rotate_(uintptr_t *gr, mreal *TetX, mreal *TetZ, mreal *TetY);
+/// Rotate a further plotting around vector {x,y,z}.
+void MGL_EXPORT mgl_rotate_vector(HMGL gr, double Tet,double x,double y,double z);
+void MGL_EXPORT mgl_rotate_vector_(uintptr_t *gr, mreal *Tet, mreal *x, mreal *y, mreal *z);
+/// Set perspective (in range [0,1)) for plot. Set to zero for switching off.
+void MGL_EXPORT mgl_perspective(HMGL gr, double val);
+void MGL_EXPORT mgl_perspective_(uintptr_t *gr, mreal *val);
+/// Ask to set perspective (in range [0,1)) for plot. Set to zero for switching off.
+void MGL_EXPORT mgl_ask_perspective(HMGL gr, double val);
+void MGL_EXPORT mgl_ask_perspective_(uintptr_t *gr, mreal *val);
+/// Set angle of view independently from Rotate().
+void MGL_EXPORT mgl_view(HMGL gr, double TetX,double TetZ,double TetY);
+void MGL_EXPORT mgl_view_(uintptr_t *gr, mreal *TetX, mreal *TetZ, mreal *TetY);
+/// Zoom in/out a part of picture (use mgl_zoom(0, 0, 1, 1) for restore default)
+void MGL_EXPORT mgl_zoom(HMGL gr, double x1, double y1, double x2, double y2);
+void MGL_EXPORT mgl_zoom_(uintptr_t *gr, mreal *x1, mreal *y1, mreal *x2, mreal *y2);
+
+//-----------------------------------------------------------------------------
+/// Callback function for mouse click
+void MGL_EXPORT mgl_set_click_func(HMGL gr, void (*func)(void *p));
+#if MGL_HAVE_PTHR_WIDGET
+/// Mutex for lock/unlock by widget
+void MGL_EXPORT mgl_wnd_set_mutex(HMGL gr, pthread_mutex_t *mutex);
+#endif
+
+/// Set callback functions for drawing and data reloading
+void MGL_EXPORT mgl_wnd_set_func(HMGL gr, int (*draw)(HMGL gr, void *p), void *par, void (*reload)(void *p));
+/// Set delay for animation in seconds
+void MGL_EXPORT mgl_wnd_set_delay(HMGL gr, double dt);
+void MGL_EXPORT mgl_wnd_set_delay_(uintptr_t *gr, mreal *dt);
+/// Get delay for animation in seconds
+double MGL_EXPORT mgl_wnd_get_delay(HMGL gr);
+double MGL_EXPORT mgl_wnd_get_delay_(uintptr_t *gr);
+/// Set window properties
+void MGL_EXPORT mgl_setup_window(HMGL gr, int clf_upd, int showpos);
+void MGL_EXPORT mgl_setup_window_(uintptr_t *gr, int *clf_upd, int *showpos);
+/// Switch on/off transparency (do not overwrite user settings)
+void MGL_EXPORT mgl_wnd_toggle_alpha(HMGL gr);
+void MGL_EXPORT mgl_wnd_toggle_alpha_(uintptr_t *gr);
+/// Switch on/off lighting (do not overwrite user settings)
+void MGL_EXPORT mgl_wnd_toggle_light(HMGL gr);
+void MGL_EXPORT mgl_wnd_toggle_light_(uintptr_t *gr);
+/// Switch on/off zooming by mouse
+void MGL_EXPORT mgl_wnd_toggle_zoom(HMGL gr);
+void MGL_EXPORT mgl_wnd_toggle_zoom_(uintptr_t *gr);
+/// Switch on/off rotation by mouse
+void MGL_EXPORT mgl_wnd_toggle_rotate(HMGL gr);
+void MGL_EXPORT mgl_wnd_toggle_rotate_(uintptr_t *gr);
+/// Switch off all zooming and rotation
+void MGL_EXPORT mgl_wnd_toggle_no(HMGL gr);
+void MGL_EXPORT mgl_wnd_toggle_no_(uintptr_t *gr);
+/// Update picture by calling user drawing function
+void MGL_EXPORT mgl_wnd_update(HMGL gr);
+void MGL_EXPORT mgl_wnd_update_(uintptr_t *gr);
+/// Reload user data and update picture
+void MGL_EXPORT mgl_wnd_reload(HMGL gr);
+void MGL_EXPORT mgl_wnd_reload_(uintptr_t *gr);
+/// Adjust size of bitmap to window size
+void MGL_EXPORT mgl_wnd_adjust(HMGL gr);
+void MGL_EXPORT mgl_wnd_adjust_(uintptr_t *gr);
+/// Show next frame (if one)
+void MGL_EXPORT mgl_wnd_next_frame(HMGL gr);
+void MGL_EXPORT mgl_wnd_next_frame_(uintptr_t *gr);
+/// Show previous frame (if one)
+void MGL_EXPORT mgl_wnd_prev_frame(HMGL gr);
+void MGL_EXPORT mgl_wnd_prev_frame_(uintptr_t *gr);
+/// Run slideshow (animation) of frames
+void MGL_EXPORT mgl_wnd_animation(HMGL gr);
+void MGL_EXPORT mgl_wnd_animation_(uintptr_t *gr);
+/// Get last mouse position
+void MGL_EXPORT mgl_get_last_mouse_pos(HMGL gr, mreal *x, mreal *y, mreal *z);
+void MGL_EXPORT mgl_get_last_mouse_pos_(uintptr_t *gr, mreal *x, mreal *y, mreal *z);
+//-----------------------------------------------------------------------------
+/// Create HMPR object for parsing MGL scripts
+HMPR MGL_EXPORT mgl_create_parser();
+uintptr_t MGL_EXPORT mgl_create_parser_();
+/// Change counter of HMPR uses (for advanced users only). Non-zero counter prevent automatic object removing.
+long MGL_EXPORT mgl_use_parser(HMPR p, int inc);
+long MGL_EXPORT mgl_use_parser_(uintptr_t* , int *inc);
+/// Delete HMPR object
+void MGL_EXPORT mgl_delete_parser(HMPR p);
+void MGL_EXPORT mgl_delete_parser_(uintptr_t* p);
+/// Set value for parameter $N
+void MGL_EXPORT mgl_parser_add_param(HMPR p, int id, const char *str);
+void MGL_EXPORT mgl_parser_add_param_(uintptr_t* p, int *id, const char *str, int);
+void MGL_EXPORT mgl_parser_add_paramw(HMPR p, int id, const wchar_t *str);
+
+/// Find variable with given name or add a new one
+/// NOTE !!! You must not delete obtained data arrays !!!
+MGL_EXPORT mglDataA *mgl_parser_add_var(HMPR p, const char *name);
+uintptr_t MGL_EXPORT mgl_parser_add_var_(uintptr_t* p, const char *name, int);
+MGL_EXPORT mglDataA *mgl_parser_add_varw(HMPR p, const wchar_t *name);
+/// Find variable with given name or return NULL if no one
+/// NOTE !!! You must not delete obtained data arrays !!!
+MGL_EXPORT mglDataA *mgl_parser_find_var(HMPR p, const char *name);
+uintptr_t MGL_EXPORT mgl_parser_find_var_(uintptr_t* p, const char *name, int);
+MGL_EXPORT mglDataA *mgl_parser_find_varw(HMPR p, const wchar_t *name);
+/// Get variable with given id
+/// NOTE !!! You must not delete obtained data arrays !!!
+MGL_EXPORT mglDataA *mgl_parser_get_var(HMPR p, unsigned long id);
+uintptr_t MGL_EXPORT mgl_parser_get_var_(uintptr_t* p, unsigned long *id);
+/// Get number of variables
+long MGL_EXPORT mgl_parser_num_var(HMPR p);
+long MGL_EXPORT mgl_parser_num_var_(uintptr_t* p);
+
+/// Get constant with given id
+/// NOTE !!! You must not delete obtained data arrays !!!
+MGL_EXPORT mglNum *mgl_parser_get_const(HMPR p, unsigned long id);
+uintptr_t MGL_EXPORT mgl_parser_get_const_(uintptr_t* p, unsigned long *id);
+/// Get number of constants
+long MGL_EXPORT mgl_parser_num_const(HMPR p);
+long MGL_EXPORT mgl_parser_num_const_(uintptr_t* p);
+
+/// Delete variable with name
+void MGL_EXPORT mgl_parser_del_var(HMPR p, const char *name);
+void MGL_EXPORT mgl_parser_del_var_(uintptr_t* p, const char *name, int);
+void MGL_EXPORT mgl_parser_del_varw(HMPR p, const wchar_t *name);
+/// Delete all data variables
+void MGL_EXPORT mgl_parser_del_all(HMPR p);
+void MGL_EXPORT mgl_parser_del_all_(uintptr_t *p);
+
+/// Load new commands from external dynamic Library (must have "const mglCommand *mgl_cmd_extra" variable)
+void MGL_EXPORT mgl_parser_load(HMPR pr, const char *dll_name);
+void MGL_EXPORT mgl_parser_load_(uintptr_t *pr, const char *dll_name,int);
+
+/// Apply one step for equation d vars[i]/dt = eqs[i] using Runge-Kutta method
+void MGL_EXPORT mgl_rk_step(HMPR pr, const char *eqs, const char *vars, mreal dt);
+void MGL_EXPORT mgl_rk_step_w(HMPR pr, const wchar_t *eqs, const wchar_t *vars, mreal dt);
+void MGL_EXPORT mgl_rk_step_(uintptr_t *p, const char *eqs, const char *vars, double *dt, int,int);
+
+// Open all data arrays from HDF file and assign it as variables of parser p
+void MGL_EXPORT mgl_parser_openhdf(HMPR p, const char *fname);
+void MGL_EXPORT mgl_parser_openhdf_(uintptr_t *p, const char *fname,int l);
+
+/// Parse and draw single line of the MGL script
+int MGL_EXPORT mgl_parse_line(HMGL gr, HMPR p, const char *str, int pos);
+int MGL_EXPORT mgl_parse_line_(uintptr_t* gr, uintptr_t* p, const char *str, int *pos, int);
+int MGL_EXPORT mgl_parse_linew(HMGL gr, HMPR p, const wchar_t *str, int pos);
+/// Execute and draw script from the file
+void MGL_EXPORT mgl_parse_file(HMGL gr, HMPR p, FILE *fp, int print);
+/// Execute MGL script text with '\n' separated lines
+void MGL_EXPORT mgl_parse_text(HMGL gr, HMPR p, const char *str);
+void MGL_EXPORT mgl_parse_text_(uintptr_t* gr, uintptr_t* p, const char *str, int);
+void MGL_EXPORT mgl_parse_textw(HMGL gr, HMPR p, const wchar_t *str);
+
+/// Restore once flag
+void MGL_EXPORT mgl_parser_restore_once(HMPR p);
+void MGL_EXPORT mgl_parser_restore_once_(uintptr_t* p);
+/// Allow changing size of the picture
+void MGL_EXPORT mgl_parser_allow_setsize(HMPR p, int a);
+void MGL_EXPORT mgl_parser_allow_setsize_(uintptr_t* p, int *a);
+/// Allow reading/saving files
+void MGL_EXPORT mgl_parser_allow_file_io(HMPR p, int a);
+void MGL_EXPORT mgl_parser_allow_file_io_(uintptr_t* p, int *a);
+/// Allow loading commands from external libraries
+void MGL_EXPORT mgl_parser_allow_dll_call(HMPR p, int a);
+void MGL_EXPORT mgl_parser_allow_dll_call_(uintptr_t* p, int *a);
+/// Set flag to stop script parsing
+void MGL_EXPORT mgl_parser_stop(HMPR p);
+void MGL_EXPORT mgl_parser_stop_(uintptr_t* p);
+/// Set variant of argument(s) separated by '?' to be used
+void MGL_EXPORT mgl_parser_variant(HMPR p, int var);
+void MGL_EXPORT mgl_parser_variant_(uintptr_t* p, int *var);
+/// Set starting object ID
+void MGL_EXPORT mgl_parser_start_id(HMPR p, int id);
+void MGL_EXPORT mgl_parser_start_id_(uintptr_t* p, int *id);
+
+
+/// Return type of command: 0 - not found, 1 - data plot, 2 - other plot,
+///		3 - setup, 4 - data handle, 5 - data create, 6 - subplot, 7 - program
+///		8 - 1d plot, 9 - 2d plot, 10 - 3d plot, 11 - dd plot, 12 - vector plot
+///		13 - axis, 14 - primitives, 15 - axis setup, 16 - text/legend, 17 - data transform
+int MGL_EXPORT mgl_parser_cmd_type(HMPR pr, const char *name);
+int MGL_EXPORT mgl_parser_cmd_type_(uintptr_t* p, const char *name, int);
+/// Return description of MGL command
+MGL_EXPORT const char *mgl_parser_cmd_desc(HMPR pr, const char *name);
+/// Return string of command format (command name and its argument[s])
+MGL_EXPORT const char *mgl_parser_cmd_frmt(HMPR pr, const char *name);
+/// Get name of command with number n
+MGL_EXPORT const char *mgl_parser_cmd_name(HMPR pr, long id);
+/// Get number of defined commands
+long MGL_EXPORT mgl_parser_cmd_num(HMPR pr);
+
+/// Return result of formula evaluation
+HMDT MGL_EXPORT mgl_parser_calc(HMPR pr, const char *formula);
+uintptr_t MGL_EXPORT mgl_parser_calc_(uintptr_t *pr, const char *formula,int);
+HMDT MGL_EXPORT mgl_parser_calcw(HMPR pr, const wchar_t *formula);
+/// Return result of formula evaluation as complex data
+HADT MGL_EXPORT mgl_parser_calc_complex(HMPR pr, const char *formula);
+uintptr_t MGL_EXPORT mgl_parser_calc_complex_(uintptr_t *pr, const char *formula,int);
+HADT MGL_EXPORT mgl_parser_calc_complexw(HMPR pr, const wchar_t *formula);
+
+#ifdef __cplusplus
+}
+#endif
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/canvas_wnd.h b/include/mgl2/canvas_wnd.h
new file mode 100644
index 0000000..19091ed
--- /dev/null
+++ b/include/mgl2/canvas_wnd.h
@@ -0,0 +1,83 @@
+/***************************************************************************
+ * canvas_wnd.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_CANVAS_WND_H_
+#define _MGL_CANVAS_WND_H_
+
+#include "mgl2/canvas.h"
+#include "mgl2/wnd.h"
+//-----------------------------------------------------------------------------
+/// Base class for windows containing MathGL graphics
+class MGL_EXPORT mglCanvasWnd : public mglCanvas
+{
+public:
+	mglPoint LastMousePos;			///< Last mouse position
+	void (*ClickFunc)(void *par);	///< Callback function on click
+#if MGL_HAVE_PTHR_WIDGET
+	pthread_mutex_t *mutex;
+#endif
+
+	mglCanvasWnd();
+	virtual ~mglCanvasWnd();
+
+	void SetSize(int w,int h,bool clf=true);
+	void EndFrame();
+	void SetFrame(long i);
+	void DelFrame(long i);
+	const unsigned char *GetBits();
+	inline int GetNumFig() const	{	return NumFig;	}
+	inline int GetCurFig() const	{	return CurFig;	}
+	void SetCurFig(int c);
+	void ResetFrames();
+	inline mglPoint GetMousePos() const	{	return LastMousePos;}
+	inline void SetMousePos(mglPoint p)	{	LastMousePos=p;	}
+	inline void Setup(bool clf_upd=true, bool showpos=false)
+	{	set(showpos,MGL_SHOW_POS);	set(clf_upd,MGL_CLF_ON_UPD);
+		if(!clf_upd)	ResetFrames();	}
+
+	virtual void ToggleAlpha()=0;	///< Switch on/off transparency (do not overwrite user settings)
+	virtual void ToggleLight()=0;	///< Switch on/off lighting (do not overwrite user settings)
+	virtual void ToggleZoom()=0;		///< Switch on/off zooming by mouse
+	virtual void ToggleRotate()=0;	///< Switch on/off rotation by mouse
+	virtual void ToggleNo()=0;		///< Switch off all zooming and rotation
+	virtual void Update()=0;			///< Update picture by calling user drawing function
+	virtual void Adjust()=0;			///< Adjust size of bitmap to window size
+	virtual void GotoFrame(int d)=0;///< Show arbitrary frame (use relative step)
+	virtual void NextFrame()	{GotoFrame(+1);}	///< Show next frame (if one)
+	virtual void PrevFrame()	{GotoFrame(-1);}	///< Show previous frame (if one)
+	virtual void Animation()=0;		///< Run slideshow (animation) of frames
+	void ReLoad();					///< Reload user data and update picture
+	/// Create a window for plotting based on callback function (can be NULL).
+	virtual void Window(int argc, char **argv, int (*draw)(mglBase *gr, void *p),
+						const char *title, void *par=NULL,
+						void (*reload)(void *p)=NULL, bool maximize=false)=0;
+	void SetDrawFunc(int (*draw)(mglBase *gr, void *p), void *par=NULL, void (*reload)(void *p)=NULL);
+
+private:
+	int CurFig;			///< Current figure in the list.
+
+	unsigned char *GG;	///< images for all frames (may be too LARGE !!!)
+	int NumFig;			///< Number of figures in the list. If 0 then no list and mglCanvas::DrawFunc will called for each drawing.
+	void (*LoadFunc)(void *par);
+	void *FuncPar;		///< Parameters for drawing function mglCanvas::DrawFunc.
+	/// Drawing function for window procedure. It should return the number of frames.
+	int (*DrawFunc)(mglBase *gr, void *par);
+};
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/cont.h b/include/mgl2/cont.h
new file mode 100644
index 0000000..6f52224
--- /dev/null
+++ b/include/mgl2/cont.h
@@ -0,0 +1,249 @@
+/***************************************************************************
+ * cont.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_CONT_H_
+#define _MGL_CONT_H_
+#include "mgl2/abstract.h"
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// Print text along the curve in parametric form {x,y,z}
+void MGL_EXPORT mgl_text_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, const char *text, const char *font, const char *opt);
+void MGL_EXPORT mgl_text_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z,const char *text,const char *font, const char *opt,int,int l,int n);
+void MGL_EXPORT mgl_textw_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, const wchar_t *text, const char *font, const char *opt);
+/// Print text along the curve in parametric form {x,y}
+void MGL_EXPORT mgl_text_xy(HMGL gr, HCDT x, HCDT y, const char *text, const char *font, const char *opt);
+void MGL_EXPORT mgl_text_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, const char *text, const char *font, const char *opt,int, int l,int n);
+void MGL_EXPORT mgl_textw_xy(HMGL gr, HCDT x, HCDT y, const wchar_t *text, const char *font, const char *opt);
+/// Print text along the curve
+void MGL_EXPORT mgl_text_y(HMGL gr, HCDT y, const char *text, const char *font, const char *opt);
+void MGL_EXPORT mgl_text_y_(uintptr_t *gr, uintptr_t *y, const char *text, const char *font, const char *opt,int, int l,int n);
+void MGL_EXPORT mgl_textw_y(HMGL gr, HCDT y, const wchar_t *text, const char *font, const char *opt);
+
+void MGL_EXPORT mgl_cont_gen(HMGL gr, double val, HCDT a, HCDT x, HCDT y, HCDT z, const char *stl);
+void MGL_EXPORT mgl_contf_gen(HMGL gr, double v1, double v2, HCDT a, HCDT x, HCDT y, HCDT z, const char *stl);
+//void MGL_EXPORT mgl_contv_gen(HMGL gr, double v1, double v2, HCDT a, HCDT x, HCDT y, HCDT z, const char *stl);
+//void MGL_EXPORT mgl_axial_gen(HMGL gr, double v1, double v2, HCDT a, HCDT x, HCDT y, HCDT z, const char *stl);
+
+/// Draw contour lines at manual levels for 2d data specified parametrically
+/** Style ‘_’ to draw contours at bottom of axis box.
+ * Style ‘t’/‘T’ draw contour labels below/above contours. */
+void MGL_EXPORT mgl_cont_xy_val(HMGL gr, HCDT v, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_cont_xy_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw contour lines at manual levels for 2d data
+/** Style ‘_’ to draw contours at bottom of axis box.
+ * Style ‘t’/‘T’ draw contour labels below/above contours. */
+void MGL_EXPORT mgl_cont_val(HMGL gr, HCDT v, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_cont_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw contour lines for 2d data specified parametrically
+/** Style ‘_’ to draw contours at bottom of axis box.
+ * Style ‘t’/‘T’ draw contour labels below/above contours.
+ * Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_cont_xy(HMGL gr, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_cont_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw contour lines for 2d data
+/** Style ‘_’ to draw contours at bottom of axis box.
+ * Style ‘t’/‘T’ draw contour labels below/above contours.
+ * Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_cont(HMGL gr, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_cont_(uintptr_t *gr, uintptr_t *z, const char *sch, const char *opt,int,int);
+
+/// Draw solid contours at manual levels for 2d data specified parametrically
+/** Style ‘_’ to draw contours at bottom of axis box. */
+void MGL_EXPORT mgl_contf_xy_val(HMGL gr, HCDT v, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_contf_xy_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw solid contours at manual levels for 2d data
+/** Style ‘_’ to draw contours at bottom of axis box. */
+void MGL_EXPORT mgl_contf_val(HMGL gr, HCDT v, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_contf_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw solid contours for 2d data specified parametrically
+/** Style ‘_’ to draw contours at bottom of axis box.
+ * Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_contf_xy(HMGL gr, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_contf_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw solid contours for 2d data
+/** Style ‘_’ to draw contours at bottom of axis box.
+ * Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_contf(HMGL gr, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_contf_(uintptr_t *gr, uintptr_t *z, const char *sch, const char *opt,int,int);
+
+/// Draw solid contours at manual levels for 2d data specified parametrically with specified colors
+/** Style ‘_’ to draw contours at bottom of axis box. */
+void MGL_EXPORT mgl_contd_xy_val(HMGL gr, HCDT v, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_contd_xy_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw solid contours at manual levels for 2d data with specified colors
+/** Style ‘_’ to draw contours at bottom of axis box. */
+void MGL_EXPORT mgl_contd_val(HMGL gr, HCDT v, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_contd_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw solid contours for 2d data specified parametrically with specified colors
+/** Style ‘_’ to draw contours at bottom of axis box.
+ * Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_contd_xy(HMGL gr, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_contd_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw solid contours for 2d data with specified colors
+/** Style ‘_’ to draw contours at bottom of axis box.
+ * Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_contd(HMGL gr, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_contd_(uintptr_t *gr, uintptr_t *z, const char *sch, const char *opt,int,int);
+
+/// Draw contour tubes between manual levels for 2d data specified parametrically
+/** Style ‘_’ to draw contours at bottom of axis box. */
+void MGL_EXPORT mgl_contv_xy_val(HMGL gr, HCDT v, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_contv_xy_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw contour tubes between manual levels for 2d data
+/** Style ‘_’ to draw contours at bottom of axis box. */
+void MGL_EXPORT mgl_contv_val(HMGL gr, HCDT v, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_contv_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw contour tubes for 2d data specified parametrically
+/** Style ‘_’ to draw contours at bottom of axis box.
+ * Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_contv_xy(HMGL gr, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_contv_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw contour tubes for 2d data
+/** Style ‘_’ to draw contours at bottom of axis box.
+ * Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_contv(HMGL gr, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_contv_(uintptr_t *gr, uintptr_t *z, const char *sch, const char *opt,int,int);
+
+
+/// Draw contour lines on parametric surface at manual levels for 2d data specified parametrically
+/** Style ‘f’ to draw solid contours.
+ * Style ‘t’/‘T’ draw contour labels below/above contours. */
+void MGL_EXPORT mgl_contp_val(HMGL gr, HCDT v, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt);
+void MGL_EXPORT mgl_contp_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, const char *opt,int,int);
+/// Draw contour lines on parametric surface for 2d data specified parametrically
+/** Style ‘f’ to draw solid contours.
+ * Style ‘t’/‘T’ draw contour labels below/above contours.
+ * Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_contp(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt);
+void MGL_EXPORT mgl_contp_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, const char *opt,int,int);
+
+
+/// Draw axial-symmetric isosurfaces at manual levels for 2d data specified parametrically
+/** String \a sch may contain:
+ * ‘#’ for wired plot;
+ * ‘.’ for plot by dots;
+ * ‘x’, ‘z’ for rotation around x-, z-axis correspondingly (default is y-axis). */
+void MGL_EXPORT mgl_axial_xy_val(HMGL gr, HCDT v, HCDT x, HCDT y, HCDT a, const char *sch, const char *opt);
+void MGL_EXPORT mgl_axial_xy_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *x, uintptr_t *y, uintptr_t *a, const char *sch, const char *opt,int,int);
+/// Draw axial-symmetric isosurfaces at manual levels for 2d data
+/** String \a sch may contain:
+ * ‘#’ for wired plot;
+ * ‘.’ for plot by dots;
+ * ‘x’, ‘z’ for rotation around x-, z-axis correspondingly (default is y-axis). */
+void MGL_EXPORT mgl_axial_val(HMGL gr, HCDT v, HCDT a, const char *sch, const char *opt);
+void MGL_EXPORT mgl_axial_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *a, const char *sch, const char *opt,int,int);
+/// Draw axial-symmetric isosurfaces for 2d data specified parametrically
+/** String \a sch may contain:
+ * ‘#’ for wired plot;
+ * ‘.’ for plot by dots;
+ * ‘x’, ‘z’ for rotation around x-, z-axis correspondingly (default is y-axis).
+ * Option "value" set the number of isosurfaces (default is 3). */
+void MGL_EXPORT mgl_axial_xy(HMGL gr, HCDT x, HCDT y, HCDT a, const char *sch, const char *opt);
+void MGL_EXPORT mgl_axial_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *a, const char *sch, const char *opt,int,int);
+/// Draw axial-symmetric isosurfaces for 2d data
+/** String \a sch may contain:
+ * ‘#’ for wired plot;
+ * ‘.’ for plot by dots;
+ * ‘x’, ‘z’ for rotation around x-, z-axis correspondingly (default is y-axis).
+ * Option "value" set the number of isosurfaces (default is 3). */
+void MGL_EXPORT mgl_axial(HMGL gr, HCDT a, const char *sch, const char *opt);
+void MGL_EXPORT mgl_axial_(uintptr_t *gr, uintptr_t *a, const char *sch, const char *opt,int,int);
+
+/// Draw surface of curve {r,z} rotation around axis
+/** Style ‘#’ produce wire plot. Style ‘.’ produce plot by dots.*/
+void MGL_EXPORT mgl_torus(HMGL gr, HCDT r, HCDT z, const char *col, const char *opt);
+void MGL_EXPORT mgl_torus_(uintptr_t *gr, uintptr_t *r, uintptr_t *z, const char *pen, const char *opt,int,int);
+
+/// Draw grid lines for density plot at slice for 3d data specified parametrically
+/** Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.*/
+void MGL_EXPORT mgl_grid3_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, const char *stl, double sVal, const char *opt);
+void MGL_EXPORT mgl_grid3_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int,int);
+/// Draw grid lines for density plot at slice for 3d data
+/** Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.*/
+void MGL_EXPORT mgl_grid3(HMGL gr, HCDT a, const char *stl, double sVal, const char *opt);
+void MGL_EXPORT mgl_grid3_(uintptr_t *gr, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int,int);
+
+/// Draw density plot at slice for 3d data specified parametrically
+/** Style ‘#’ draw grid lines. Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.*/
+void MGL_EXPORT mgl_dens3_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, const char *stl, double sVal, const char *opt);
+void MGL_EXPORT mgl_dens3_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int,int);
+/// Draw density plot at slice for 3d data
+/** Style ‘#’ draw grid lines. Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.*/
+void MGL_EXPORT mgl_dens3(HMGL gr, HCDT a, const char *stl, double sVal, const char *opt);
+void MGL_EXPORT mgl_dens3_(uintptr_t *gr, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int,int);
+
+/// Draw contour lines at manual levels along slice for 3d data specified parametrically
+/** Style ‘#’ draw grid lines.
+ * Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.
+ * Style ‘t’/‘T’ draw contour labels below/above contours. */
+void MGL_EXPORT mgl_cont3_xyz_val(HMGL gr, HCDT v, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, double sVal, const char *opt);
+void MGL_EXPORT mgl_cont3_xyz_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int,int);
+/// Draw contour lines at manual levels along slice for 3d data
+/** Style ‘#’ draw grid lines.
+ * Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.
+ * Style ‘t’/‘T’ draw contour labels below/above contours. */
+void MGL_EXPORT mgl_cont3_val(HMGL gr, HCDT v, HCDT a, const char *sch, double sVal, const char *opt);
+void MGL_EXPORT mgl_cont3_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int,int);
+/// Draw contour lines along slice for 3d data specified parametrically
+/** Style ‘#’ draw grid lines.
+ * Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.
+ * Style ‘t’/‘T’ draw contour labels below/above contours.
+ * Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_cont3_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, double sVal, const char *opt);
+void MGL_EXPORT mgl_cont3_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int,int);
+/// Draw contour lines along slice for 3d data
+/** Style ‘#’ draw grid lines.
+ * Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.
+ * Style ‘t’/‘T’ draw contour labels below/above contours.
+ * Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_cont3(HMGL gr, HCDT a, const char *sch, double sVal, const char *opt);
+void MGL_EXPORT mgl_cont3_(uintptr_t *gr, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int,int);
+
+/// Draw solid contours at manual levels along slice for 3d data specified parametrically
+/** Style ‘#’ draw grid lines.
+ * Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly. */
+void MGL_EXPORT mgl_contf3_xyz_val(HMGL gr, HCDT v, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, double sVal, const char *opt);
+void MGL_EXPORT mgl_contf3_xyz_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int,int);
+/// Draw solid contours at manual levels along slice for 3d data
+/** Style ‘#’ draw grid lines.
+ * Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly. */
+void MGL_EXPORT mgl_contf3_val(HMGL gr, HCDT v, HCDT a, const char *sch, double sVal, const char *opt);
+void MGL_EXPORT mgl_contf3_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int,int);
+/// Draw solid contours along slice for 3d data specified parametrically
+/** Style ‘#’ draw grid lines.
+ * Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.
+ * Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_contf3_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, double sVal, const char *opt);
+void MGL_EXPORT mgl_contf3_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int,int);
+/// Draw solid contours along slice for 3d data
+/** Style ‘#’ draw grid lines.
+ * Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.
+ * Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_contf3(HMGL gr, HCDT a, const char *sch, double sVal, const char *opt);
+void MGL_EXPORT mgl_contf3_(uintptr_t *gr, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int,int);
+
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+}
+#endif
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/data.h b/include/mgl2/data.h
new file mode 100644
index 0000000..9241882
--- /dev/null
+++ b/include/mgl2/data.h
@@ -0,0 +1,1022 @@
+/***************************************************************************
+ * data.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_DATA_H_
+#define _MGL_DATA_H_
+
+#include "mgl2/data_cf.h"
+#include "mgl2/pde.h"
+//-----------------------------------------------------------------------------
+#include <stdarg.h>
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mglLinear(const mreal *a, long nx, long ny, long nz, mreal x, mreal y, mreal z);
+mreal MGL_EXPORT mglSpline3(const mreal *a, long nx, long ny, long nz, mreal x, mreal y, mreal z,mreal *dx=0, mreal *dy=0, mreal *dz=0);
+mreal MGL_EXPORT mglSpline3s(const mreal *a, long nx, long ny, long nz, mreal x, mreal y, mreal z);
+std::string MGL_EXPORT mgl_data_to_string(HCDT d, long ns);
+//-----------------------------------------------------------------------------
+/// Class for working with data array
+class MGL_EXPORT mglData : public mglDataA
+{
+public:
+using mglDataA::Momentum;
+	long nx;		///< number of points in 1st dimensions ('x' dimension)
+	long ny;		///< number of points in 2nd dimensions ('y' dimension)
+	long nz;		///< number of points in 3d dimensions ('z' dimension)
+	mreal *a;		///< data array
+	std::string id;	///< column (or slice) names
+	bool link;		///< use external data (i.e. don't free it)
+
+	/// Initiate by other mglData variable
+	mglData(const mglData &d)	{	a=0;	mgl_data_set(this,&d);		}	// NOTE: must be constructor for mglData& to exclude copy one
+#if MGL_HAVE_RVAL
+	mglData(mglData &&d):nx(d.nx),ny(d.ny),nz(d.nz),a(d.a),id(d.id),link(d.link)
+	{	s=d.s;	temp=d.temp;	func=d.func;	o=d.o;	d.a=0;	d.func=0;	}
+#endif
+	mglData(const mglDataA *d)
+	{	a=0;	if(d)	mgl_data_set(this, d);	else	mgl_data_create(this,1,1,1);		}
+	mglData(bool, mglData *d)	// NOTE: Variable d will be deleted!!!
+	{	if(d)
+		{	nx=d->nx;	ny=d->ny;	nz=d->nz;	a=d->a;	d->a=0;
+			temp=d->temp;	func=d->func;	o=d->o;	s=d->s;
+			id=d->id;	link=d->link;	delete d;	}
+		else	{	a=0;	Create(1);	}	}
+	/// Initiate by flat array
+	mglData(int size, const float *d)	{	a=0;	Set(d,size);	}
+	mglData(int rows, int cols, const float *d)	{	a=0;	Set(d,cols,rows);	}
+	mglData(int size, const double *d)	{	a=0;	Set(d,size);	}
+	mglData(int rows, int cols, const double *d)	{	a=0;	Set(d,cols,rows);	}
+	mglData(const double *d, int size)	{	a=0;	Set(d,size);	}
+	mglData(const double *d, int rows, int cols)	{	a=0;	Set(d,cols,rows);	}
+	mglData(const float *d, int size)	{	a=0;	Set(d,size);	}
+	mglData(const float *d, int rows, int cols)	{	a=0;	Set(d,cols,rows);	}
+	/// Allocate memory and copy data from std::vector<T>
+	mglData(const std::vector<int> &d)		{	a=0;	Set(d);	}
+	mglData(const std::vector<float> &d)	{	a=0;	Set(d);	}
+	mglData(const std::vector<double> &d)	{	a=0;	Set(d);	}
+	/// Read data from file
+	mglData(const char *fname)			{	a=0;	Read(fname);	}
+	/// Allocate the memory for data array and initialize it zero
+	mglData(long xx=1,long yy=1,long zz=1)	{	a=0;	Create(xx,yy,zz);	}
+	/// Delete the array
+	virtual ~mglData()	{	if(!link && a)	delete []a;	}
+
+	/// Move all data from variable d, and delete this variable.
+	inline void Move(mglData *d)	// NOTE: Variable d will be deleted!!!
+	{	if(d && d->GetNN()>1)
+		{	bool l=link;	mreal *b=a;
+			nx=d->nx;	ny=d->ny;	nz=d->nz;	a=d->a;	d->a=b;
+			temp=d->temp;	func=d->func;	o=d->o;	s=d->s;
+			id=d->id;	link=d->link;	d->link=l;	delete d;	}
+		else if(d)	{	*this = d->a[0];	delete d;	}
+	}
+
+	inline mreal GetVal(long i, long j=0, long k=0) const
+	{	return mgl_data_get_value(this,i,j,k);}
+	inline void SetVal(mreal f, long i, long j=0, long k=0)
+	{	mgl_data_set_value(this,f,i,j,k);	}
+	/// Get sizes
+	long GetNx() const	{	return nx;	}
+	long GetNy() const	{	return ny;	}
+	long GetNz() const	{	return nz;	}
+
+	/// Link external data array (don't delete it at exit)
+	inline void Link(mreal *A, long NX, long NY=1, long NZ=1)
+	{	mgl_data_link(this,A,NX,NY,NZ);	}
+	inline void Link(mglData &d)	{	Link(d.a,d.nx,d.ny,d.nz);	}
+	/// Allocate memory and copy the data from the gsl_vector
+	inline void Set(gsl_vector *m)	{	mgl_data_set_vector(this,m);	}
+	/// Allocate memory and copy the data from the gsl_matrix
+	inline void Set(gsl_matrix *m)	{	mgl_data_set_matrix(this,m);	}
+
+	/// Allocate memory and copy the data from the (float *) array
+	inline void Set(const float *A,long NX,long NY=1,long NZ=1)
+	{	mgl_data_set_float(this,A,NX,NY,NZ);	}
+	/// Allocate memory and copy the data from the (double *) array
+	inline void Set(const double *A,long NX,long NY=1,long NZ=1)
+	{	mgl_data_set_double(this,A,NX,NY,NZ);	}
+	/// Allocate memory and copy the data from the (float **) array
+	inline void Set(float const * const *A,long N1,long N2)
+	{	mgl_data_set_float2(this,A,N1,N2);	}
+	/// Allocate memory and copy the data from the (double **) array
+	inline void Set(double const * const *A,long N1,long N2)
+	{	mgl_data_set_double2(this,A,N1,N2);	}
+	/// Allocate memory and copy the data from the (float ***) array
+	inline void Set(float const * const * const *A,long N1,long N2,long N3)
+	{	mgl_data_set_float3(this,A,N1,N2,N3);	}
+	/// Allocate memory and copy the data from the (double ***) array
+	inline void Set(double const * const * const *A,long N1,long N2,long N3)
+	{	mgl_data_set_double3(this,A,N1,N2,N3);	}
+	/// Allocate memory and scanf the data from the string
+	inline void Set(const char *str,long NX,long NY=1,long NZ=1)
+	{	mgl_data_set_values(this,str,NX,NY,NZ);	}
+	/// Import data from abstract type
+	inline void Set(HCDT dat)	{	mgl_data_set(this, dat);	}
+	inline void Set(const mglDataA &dat)	{	mgl_data_set(this, &dat);	}
+	/// Allocate memory and copy data from std::vector<T>
+	inline void Set(const std::vector<int> &d)
+	{	if(d.size()>0)	{	Create(d.size());	for(long i=0;i<nx;i++)	a[i] = d[i];	}
+		else	Create(1);	}
+	inline void Set(const std::vector<float> &d)
+	{	if(d.size()>0)	Set(&(d[0]),d.size());	else	Create(1);	}
+	inline void Set(const std::vector<double> &d)
+	{	if(d.size()>0)	Set(&(d[0]),d.size());	else	Create(1);	}
+	/// Allocate memory and set data from variable argument list of double values
+	inline void SetList(long n, ...)
+	{
+		if(n<1)	return;
+		mgl_data_create(this,n,1,1);
+		va_list vl;	va_start(vl,n);
+		for(long i=0;i<n;i++)	a[i] = va_arg(vl,double);
+	}
+
+	/// Create or recreate the array with specified size and fill it by zero
+	inline void Create(long mx,long my=1,long mz=1)
+	{	mgl_data_create(this,mx,my,mz);	}
+	/// Rearange data dimensions
+	inline void Rearrange(long mx, long my=0, long mz=0)
+	{	mgl_data_rearrange(this,mx,my,mz);	}
+	/// Transpose dimensions of the data (generalization of Transpose)
+	inline void Transpose(const char *dim="yx")
+	{	mgl_data_transpose(this,dim);	}
+	/// Extend data dimensions
+	inline void Extend(long n1, long n2=0)
+	{	mgl_data_extend(this,n1,n2);	}
+	/// Reduce size of the data
+	inline void Squeeze(long rx,long ry=1,long rz=1,bool smooth=false)
+	{	mgl_data_squeeze(this,rx,ry,rz,smooth);	}
+	/// Crop the data
+	inline void Crop(long n1, long n2,char dir='x')
+	{	mgl_data_crop(this,n1,n2,dir);	}
+	/// Crop the data to be most optimal for FFT (i.e. to closest value of 2^n*3^m*5^l)
+	inline void Crop(const char *how="235x")
+	{	mgl_data_crop_opt(this, how);	}
+	/// Insert data rows/columns/slices
+	inline void Insert(char dir, long at=0, long num=1)
+	{	mgl_data_insert(this,dir,at,num);	}
+	/// Delete data rows/columns/slices
+	inline void Delete(char dir, long at=0, long num=1)
+	{	mgl_data_delete(this,dir,at,num);	}
+	/// Remove rows with duplicate values in column clmn
+	inline void Clean(long clmn)
+	{	mgl_data_clean(this,clmn);	}
+	/// Join with another data array
+	inline void Join(const mglDataA &d)
+	{	mgl_data_join(this,&d);	}
+
+	/// Modify the data by specified formula
+	inline void Modify(const char *eq,long dim=0)
+	{	mgl_data_modify(this, eq, dim);	}
+	/// Modify the data by specified formula
+	inline void Modify(const char *eq,const mglDataA &vdat, const mglDataA &wdat)
+	{	mgl_data_modify_vw(this,eq,&vdat,&wdat);	}
+	/// Modify the data by specified formula
+	inline void Modify(const char *eq,const mglDataA &vdat)
+	{	mgl_data_modify_vw(this,eq,&vdat,0);	}
+	/// Modify the data by specified formula assuming x,y,z in range [r1,r2]
+	inline void Fill(HMGL gr, const char *eq, const char *opt="")
+	{	mgl_data_fill_eq(gr,this,eq,0,0,opt);	}
+	inline void Fill(HMGL gr, const char *eq, const mglDataA &vdat, const char *opt="")
+	{	mgl_data_fill_eq(gr,this,eq,&vdat,0,opt);	}
+	inline void Fill(HMGL gr, const char *eq, const mglDataA &vdat, const mglDataA &wdat,const char *opt="")
+	{	mgl_data_fill_eq(gr,this,eq,&vdat,&wdat,opt);	}
+	/// Equidistantly fill the data to range [x1,x2] in direction dir
+	inline void Fill(mreal x1,mreal x2=mglNaN,char dir='x')
+	{	mgl_data_fill(this,x1,x2,dir);	}
+	/// Fill the data by interpolated values of vdat parametrically depended on xdat,ydat,zdat for x,y,z in range [p1,p2] using global spline
+	inline void RefillGS(const mglDataA &xdat, const mglDataA &vdat, mreal x1, mreal x2,long sl=-1)
+	{	mgl_data_refill_gs(this,&xdat,&vdat,x1,x2,sl);	}
+	/// Fill the data by interpolated values of vdat parametrically depended on xdat,ydat,zdat for x,y,z in range [p1,p2]
+	inline void Refill(const mglDataA &xdat, const mglDataA &vdat, mreal x1, mreal x2,long sl=-1)
+	{	mgl_data_refill_x(this,&xdat,&vdat,x1,x2,sl);	}
+	inline void Refill(const mglDataA &xdat, const mglDataA &vdat, mglPoint p1, mglPoint p2,long sl=-1)
+	{	mgl_data_refill_x(this,&xdat,&vdat,p1.x,p2.x,sl);	}
+	inline void Refill(const mglDataA &xdat, const mglDataA &ydat, const mglDataA &vdat, mglPoint p1, mglPoint p2,long sl=-1)
+	{	mgl_data_refill_xy(this,&xdat,&ydat,&vdat,p1.x,p2.x,p1.y,p2.y,sl);	}
+	inline void Refill(const mglDataA &xdat, const mglDataA &ydat, const mglDataA &zdat, const mglDataA &vdat, mglPoint p1, mglPoint p2)
+	{	mgl_data_refill_xyz(this,&xdat,&ydat,&zdat,&vdat,p1.x,p2.x,p1.y,p2.y,p1.z,p2.z);	}
+	/// Fill the data by interpolated values of vdat parametrically depended on xdat,ydat,zdat for x,y,z in axis range of gr
+	inline void Refill(HMGL gr, const mglDataA &xdat, const mglDataA &vdat, long sl=-1, const char *opt="")
+	{	mgl_data_refill_gr(gr,this,&xdat,0,0,&vdat,sl,opt);	}
+	inline void Refill(HMGL gr, const mglDataA &xdat, const mglDataA &ydat, const mglDataA &vdat, long sl=-1, const char *opt="")
+	{	mgl_data_refill_gr(gr,this,&xdat,&ydat,0,&vdat,sl,opt);	}
+	inline void Refill(HMGL gr, const mglDataA &xdat, const mglDataA &ydat, const mglDataA &zdat, const mglDataA &vdat, const char *opt="")
+	{	mgl_data_refill_gr(gr,this,&xdat,&ydat,&zdat,&vdat,-1,opt);	}
+	/// Set the data by triangulated surface values assuming x,y,z in axis range of gr
+	inline void Grid(HMGL gr, const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *opt="")
+	{	mgl_data_grid(gr,this,&x,&y,&z,opt);	}
+	/// Set the data by triangulated surface values assuming x,y,z in range [p1, p2]
+	inline void Grid(const mglDataA &xdat, const mglDataA &ydat, const mglDataA &vdat, mglPoint p1, mglPoint p2)
+	{	mgl_data_grid_xy(this,&xdat,&ydat,&vdat,p1.x,p2.x,p1.y,p2.y);	}
+	/// Put value to data element(s)
+	inline void Put(mreal val, long i=-1, long j=-1, long k=-1)
+	{	mgl_data_put_val(this,val,i,j,k);	}
+	/// Put array to data element(s)
+	inline void Put(const mglDataA &dat, long i=-1, long j=-1, long k=-1)
+	{	mgl_data_put_dat(this,&dat,i,j,k);	}
+	/// Set names for columns (slices)
+	inline void SetColumnId(const char *ids)
+	{	mgl_data_set_id(this,ids);	}
+	/// Make new id
+	inline void NewId()	{	id.clear();	}
+
+	/// Read data from tab-separated text file with auto determining size
+	inline bool Read(const char *fname)
+	{	return mgl_data_read(this,fname); }
+	/// Read data from text file with specifeid size
+	inline bool Read(const char *fname,long mx,long my=1,long mz=1)
+	{	return mgl_data_read_dim(this,fname,mx,my,mz);	}
+	/// Import data array from PNG file according color scheme
+	inline void Import(const char *fname,const char *scheme,mreal v1=0,mreal v2=1)
+	{	mgl_data_import(this,fname,scheme,v1,v2);	}
+	/// Read data from tab-separated text files with auto determining size which filenames are result of sprintf(fname,templ,t) where t=from:step:to
+	inline bool ReadRange(const char *templ, double from, double to, double step=1, bool as_slice=false)
+	{	return mgl_data_read_range(this,templ,from,to,step,as_slice);	}
+	/// Read data from tab-separated text files with auto determining size which filenames are satisfied to template (like "t_*.dat")
+	inline bool ReadAll(const char *templ, bool as_slice=false)
+	{	return mgl_data_read_all(this, templ, as_slice);	}
+	/// Read data from text file with size specified at beginning of the file
+	inline bool ReadMat(const char *fname, long dim=2)
+	{	return mgl_data_read_mat(this,fname,dim);	}
+	/// Read data array from HDF file (parse HDF4 and HDF5 files)
+	inline int ReadHDF(const char *fname,const char *data)
+	{	return mgl_data_read_hdf(this,fname,data);	}
+	/// Scan textual file for template and fill data array
+	inline int ScanFile(const char *fname, const char *templ)
+	{	return mgl_data_scan_file(this,fname, templ);	}
+
+
+	/// Get column (or slice) of the data filled by formulas of named columns
+	inline mglData Column(const char *eq) const
+	{	return mglData(true,mgl_data_column(this,eq));	}
+	/// Get momentum (1D-array) of data along direction 'dir'. String looks like "x1" for median in x-direction, "x2" for width in x-dir and so on.
+	inline mglData Momentum(char dir, const char *how) const
+	{	return mglData(true,mgl_data_momentum(this,dir,how));	}
+	/// Get pulse properties: pulse maximum and its position, pulse duration near maximum and by half height, energy in first pulse.
+	inline mglData Pulse(char dir) const
+	{	return mglData(true,mgl_data_pulse(this,dir));	}
+	/// Get sub-array of the data with given fixed indexes
+	inline mglData SubData(long xx,long yy=-1,long zz=-1) const
+	{	return mglData(true,mgl_data_subdata(this,xx,yy,zz));	}
+	inline mglData SubData(const mglDataA &xx, const mglDataA &yy, const mglDataA &zz) const
+	{	return mglData(true,mgl_data_subdata_ext(this,&xx,&yy,&zz));	}
+	inline mglData SubData(const mglDataA &xx, const mglDataA &yy) const
+	{	return mglData(true,mgl_data_subdata_ext(this,&xx,&yy,0));	}
+	inline mglData SubData(const mglDataA &xx) const
+	{	return mglData(true,mgl_data_subdata_ext(this,&xx,0,0));	}
+	/// Get data from sections ids, separated by value val along specified direction.
+	/** If section id is negative then reverse order is used (i.e. -1 give last section). */
+	inline mglData Section(const mglDataA &ids, char dir='y', mreal val=NAN) const
+	{	return mglData(true,mgl_data_section(this,&ids,dir,val));	}
+	inline mglData Section(long id, char dir='y', mreal val=NAN) const
+	{	return mglData(true,mgl_data_section_val(this,id,dir,val));	}
+
+	/// Get trace of the data array
+	inline mglData Trace() const
+	{	return mglData(true,mgl_data_trace(this));	}
+	/// Create n-th points distribution of this data values in range [v1, v2]
+	inline mglData Hist(long n,mreal v1=0,mreal v2=1, long nsub=0) const
+	{	return mglData(true,mgl_data_hist(this,n,v1,v2,nsub));	}
+	/// Create n-th points distribution of this data values in range [v1, v2] with weight w
+	inline mglData Hist(const mglDataA &w, long n,mreal v1=0,mreal v2=1, long nsub=0) const
+	{	return mglData(true,mgl_data_hist_w(this,&w,n,v1,v2,nsub));	}
+	/// Get array which is result of summation in given direction or directions
+	inline mglData Sum(const char *dir) const
+	{	return mglData(true,mgl_data_sum(this,dir));	}
+	/// Get array which is result of maximal values in given direction or directions
+	inline mglData Max(const char *dir) const
+	{	return mglData(true,mgl_data_max_dir(this,dir));	}
+	/// Get array which is result of minimal values in given direction or directions
+	inline mglData Min(const char *dir) const
+	{	return mglData(true,mgl_data_min_dir(this,dir));	}
+	/// Get the data which is direct multiplication (like, d[i,j] = this[i]*a[j] and so on)
+	inline mglData Combine(const mglDataA &dat) const
+	{	return mglData(true,mgl_data_combine(this,&dat));	}
+	/// Resize the data to new size of box [x1,x2]*[y1,y2]*[z1,z2]
+	inline mglData Resize(long mx,long my=0,long mz=0, mreal x1=0,mreal x2=1, mreal y1=0,mreal y2=1, mreal z1=0,mreal z2=1) const
+	{	return mglData(true,mgl_data_resize_box(this,mx,my,mz,x1,x2,y1,y2,z1,z2));	}
+	/// Get array which values is result of interpolation this for coordinates from other arrays
+	inline mglData Evaluate(const mglData &idat, bool norm=true) const
+	{	return mglData(true,mgl_data_evaluate(this,&idat,0,0,norm));	}
+	inline mglData Evaluate(const mglData &idat, const mglData &jdat, bool norm=true) const
+	{	return mglData(true,mgl_data_evaluate(this,&idat,&jdat,0,norm));	}
+	inline mglData Evaluate(const mglData &idat, const mglData &jdat, const mglData &kdat, bool norm=true) const
+	{	return mglData(true,mgl_data_evaluate(this,&idat,&jdat,&kdat,norm));	}
+	/// Find roots for set of nonlinear equations defined by textual formula
+	inline mglData Roots(const char *eq, char var='x') const
+	{	return mglData(true,mgl_data_roots(eq, this, var));	}
+	/// Find correlation with another data arrays
+	inline mglData Correl(const mglDataA &dat, const char *dir) const
+	{	return mglData(true,mgl_data_correl(this,&dat,dir));	}
+	/// Find auto correlation function
+	inline mglData AutoCorrel(const char *dir) const
+	{	return mglData(true,mgl_data_correl(this,this,dir));	}
+	/// Get curves, separated by NAN, for maximal values of array d as function of x coordinate.
+	/** Noises below lvl amplitude are ignored.
+	 * Parameter dy \in [0,ny] set the "attraction" distance of points to curve. */
+	inline mglData Detect(mreal lvl, mreal dj, mreal di=0, mreal min_len=0) const
+	{	return mglData(true,mgl_data_detect(this,lvl,dj,di,min_len));	}
+
+	/// Cumulative summation the data in given direction or directions
+	inline void CumSum(const char *dir)	{	mgl_data_cumsum(this,dir);	}
+	/// Integrate (cumulative summation) the data in given direction or directions
+	inline void Integral(const char *dir)	{	mgl_data_integral(this,dir);	}
+	/// Differentiate the data in given direction or directions
+	inline void Diff(const char *dir)	{	mgl_data_diff(this,dir);	}
+	/// Differentiate the parametrically specified data along direction v1
+	inline void Diff(const mglDataA &v1)
+	{	mgl_data_diff_par(this,&v1,0,0);	}
+	/// Differentiate the parametrically specified data along direction v1 with v2=const
+	inline void Diff(const mglDataA &v1, const mglDataA &v2)
+	{	mgl_data_diff_par(this,&v1,&v2,0);	}
+	/// Differentiate the parametrically specified data along direction v1 with v2,v3=const
+	inline void Diff(const mglDataA &v1, const mglDataA &v2, const mglDataA &v3)
+	{	mgl_data_diff_par(this,&v1,&v2,&v3);	}
+	/// Double-differentiate (like Laplace operator) the data in given direction
+	inline void Diff2(const char *dir)	{	mgl_data_diff2(this,dir);	}
+
+	/// Swap left and right part of the data in given direction (useful for Fourier spectrum)
+	inline void Swap(const char *dir)		{	mgl_data_swap(this,dir);	}
+	/// Roll data along direction dir by num slices
+	inline void Roll(char dir, long num)	{	mgl_data_roll(this,dir,num);	}
+	/// Mirror the data in given direction (useful for Fourier spectrum)
+	inline void Mirror(const char *dir)		{	mgl_data_mirror(this,dir);	}
+	/// Sort rows (or slices) by values of specified column
+	inline void Sort(long idx, long idy=-1)	{	mgl_data_sort(this,idx,idy);	}
+	/// Return dilated array of 0 or 1 for data values larger val
+	inline void Dilate(mreal val=1, long step=1)
+	{	mgl_data_dilate(this, val, step);	}
+	/// Return eroded array of 0 or 1 for data values larger val
+	inline void Erode(mreal val=1, long step=1)
+	{	mgl_data_erode(this, val, step);	}
+
+	/// Set as the data envelop
+	inline void Envelop(char dir='x')
+	{	mgl_data_envelop(this,dir);	}
+	/// Remove phase jump
+	inline void Sew(const char *dirs="xyz", mreal da=2*mglPi)
+	{	mgl_data_sew(this,dirs,da);	}
+	/// Smooth the data on specified direction or directions
+	/** String \a dir may contain:
+	 *  ‘x’, ‘y’, ‘z’ for 1st, 2nd or 3d dimension;
+	 *  ‘dN’ for linear averaging over N points;
+	 *  ‘3’ for linear averaging over 3 points;
+	 *  ‘5’ for linear averaging over 5 points.
+	 *  By default quadratic averaging over 5 points is used. */
+	inline void Smooth(const char *dirs="xyz",mreal delta=0)
+	{	mgl_data_smooth(this,dirs,delta);	}
+	/// Normalize the data to range [v1,v2]
+	inline void Norm(mreal v1=0,mreal v2=1,bool sym=false,long dim=0)
+	{	mgl_data_norm(this,v1,v2,sym,dim);	}
+	/// Normalize the data to range [v1,v2] slice by slice
+	inline void NormSl(mreal v1=0,mreal v2=1,char dir='z',bool keep_en=true,bool sym=false)
+	{	mgl_data_norm_slice(this,v1,v2,dir,keep_en,sym);	}
+	/// Limit the data to be inside [-v,v], keeping the original sign
+	inline void Limit(mreal v)
+	{	mgl_data_limit(this, v);	}
+
+	/// Apply Hankel transform
+	inline void Hankel(const char *dir)	{	mgl_data_hankel(this,dir);	}
+	/// Apply Sin-Fourier transform
+	inline void SinFFT(const char *dir)	{	mgl_data_sinfft(this,dir);	}
+	/// Apply Cos-Fourier transform
+	inline void CosFFT(const char *dir)	{	mgl_data_cosfft(this,dir);	}
+	/// Fill data by coordinates/momenta samples for Hankel ('h') or Fourier ('f') transform
+	/** Parameter \a how may contain:
+	 * ‘x‘,‘y‘,‘z‘ for direction (only one will be used),
+	 * ‘k‘ for momenta samples,
+	 * ‘h‘ for Hankel samples,
+	 * ‘f‘ for Cartesian/Fourier samples (default). */
+	inline void FillSample(const char *how)
+	{	mgl_data_fill_sample(this,how);	}
+	/// Apply wavelet transform
+	/** Parameter \a dir may contain:
+	 * ‘x‘,‘y‘,‘z‘ for directions,
+	 * ‘d‘ for daubechies, ‘D‘ for centered daubechies,
+	 * ‘h‘ for haar, ‘H‘ for centered haar,
+	 * ‘b‘ for bspline, ‘B‘ for centered bspline,
+	 * ‘i‘ for applying inverse transform. */
+	inline void Wavelet(const char *how, int k)	{	mgl_data_wavelet(this, how, k);	}
+
+	/// Return an approximated x-value (root) when dat(x) = val
+	inline mreal Solve(mreal val, bool use_spline=true, long i0=0) const
+	{	return mgl_data_solve_1d(this, val, use_spline, i0);		}
+	/// Return an approximated value (root) when dat(x) = val
+	inline mglData Solve(mreal val, char dir, bool norm=true) const
+	{	return mglData(true,mgl_data_solve(this, val, dir, 0, norm));	}
+	inline mglData Solve(mreal val, char dir, const mglData &i0, bool norm=true) const
+	{	return mglData(true,mgl_data_solve(this, val, dir, &i0, norm));	}
+
+	/// Copy data from other mglData variable
+	inline const mglDataA &operator=(const mglDataA &d)
+	{	if(this!=&d)	mgl_data_set(this,&d);	return d;	}
+	inline const mglData &operator=(const mglData &d)
+	{	if(this!=&d)	mgl_data_set(this,&d);	return d;	}
+	inline mreal operator=(mreal val)
+	{	mgl_data_fill(this,val,val,'x');	return val;	}
+	/// Multiply the data by other one for each element
+	inline void operator*=(const mglDataA &d)	{	mgl_data_mul_dat(this,&d);	}
+	/// Divide the data by other one for each element
+	inline void operator/=(const mglDataA &d)	{	mgl_data_div_dat(this,&d);	}
+	/// Add the other data
+	inline void operator+=(const mglDataA &d)	{	mgl_data_add_dat(this,&d);	}
+	/// Subtract the other data
+	inline void operator-=(const mglDataA &d)	{	mgl_data_sub_dat(this,&d);	}
+	/// Multiply each element by the number
+	inline void operator*=(mreal d)		{	mgl_data_mul_num(this,d);	}
+	/// Divide each element by the number
+	inline void operator/=(mreal d)		{	mgl_data_div_num(this,d);	}
+	/// Add the number
+	inline void operator+=(mreal d)		{	mgl_data_add_num(this,d);	}
+	/// Subtract the number
+	inline void operator-=(mreal d)		{	mgl_data_sub_num(this,d);	}
+#ifndef SWIG
+	/// Direct access to the data cell
+	inline mreal &operator[](long i)	{	return a[i];	}
+	// NOTE see 13.10 for operator(), operator[] -- m.b. I should add it ???
+#endif
+
+#ifndef DEBUG
+	/// Get the value in given cell of the data
+	mreal v(long i,long j=0,long k=0) const	{	return a[i+nx*(j+ny*k)];	}
+	/// Set the value in given cell of the data
+	void set_v(mreal val, long i,long j=0,long k=0)	{	a[i+nx*(j+ny*k)]=val;	}
+#else
+	/// Get the value in given cell of the data with border checking
+	mreal v(long i,long j=0,long k=0) const	{	return mgl_data_get_value(this,i,j,k);	}
+	/// Set the value in given cell of the data
+	void set_v(mreal val, long i,long j=0,long k=0)	{	mgl_data_set_value(this,val,i,j,k);	}
+#endif
+	/// Get the interpolated value and its derivatives in given data cell without border checking
+	mreal valueD(mreal x,mreal y=0,mreal z=0,mreal *dx=0,mreal *dy=0,mreal *dz=0) const
+	{	return mglSpline3(a,nx,ny,nz,x,y,z,dx,dy,dz);	}
+	/// Get the interpolated value in given data cell without border checking
+	mreal value(mreal x,mreal y=0,mreal z=0) const
+	{	return mglSpline3s(a,nx,ny,nz,x,y,z);	}
+	mreal vthr(long i) const {	return a[i];	}
+	// add for speeding up !!!
+	mreal dvx(long i,long j=0,long k=0) const
+	{   long i0=i+nx*(j+ny*k);
+		return i>0? (i<nx-1? (a[i0+1]-a[i0-1])/2:a[i0]-a[i0-1]) : a[i0+1]-a[i0];	}
+	mreal dvy(long i,long j=0,long k=0) const
+	{   long i0=i+nx*(j+ny*k);
+		return j>0? (j<ny-1? (a[i0+nx]-a[i0-nx])/2:a[i0]-a[i0-nx]) : a[i0+nx]-a[i0];}
+	mreal dvz(long i,long j=0,long k=0) const
+	{   long i0=i+nx*(j+ny*k), n=nx*ny;
+		return k>0? (k<nz-1? (a[i0+n]-a[i0-n])/2:a[i0]-a[i0-n]) : a[i0+n]-a[i0];	}
+};
+//-----------------------------------------------------------------------------
+#ifndef SWIG
+inline mglData operator*(const mglDataA &b, const mglDataA &d)
+{	mglData a(&b);	a*=d;	return a;	}
+inline mglData operator*(mreal b, const mglDataA &d)
+{	mglData a(&d);	a*=b;	return a;	}
+inline mglData operator*(const mglDataA &d, mreal b)
+{	mglData a(&d);	a*=b;	return a;	}
+inline mglData operator-(const mglDataA &b, const mglDataA &d)
+{	mglData a(&b);	a-=d;	return a;	}
+inline mglData operator-(mreal b, const mglDataA &d)
+{	mglData a(&d);	a-=b;	return a;	}
+inline mglData operator-(const mglDataA &d, mreal b)
+{	mglData a(&d);	a-=b;	return a;	}
+inline mglData operator+(const mglDataA &b, const mglDataA &d)
+{	mglData a(&b);	a+=d;	return a;	}
+inline mglData operator+(mreal b, const mglDataA &d)
+{	mglData a(&d);	a+=b;	return a;	}
+inline mglData operator+(const mglDataA &d, mreal b)
+{	mglData a(&d);	a+=b;	return a;	}
+inline mglData operator/(const mglDataA &b, const mglDataA &d)
+{	mglData a(&b);	a/=d;	return a;	}
+inline mglData operator/(const mglDataA &d, mreal b)
+{	mglData a(&d);	a/=b;	return a;	}
+inline bool operator==(const mglData &b, const mglData &d)
+{	if(b.nx!=d.nx || b.ny!=d.ny || b.nz!=d.nz)	return false;
+	return !memcmp(b.a,d.a,b.nx*b.ny*b.nz*sizeof(mreal));	}
+inline bool operator<(const mglDataA &b, const mglDataA &d)
+{	return b.Maximal()<d.Maximal();	}
+inline bool operator>(const mglDataA &b, const mglDataA &d)
+{	return b.Minimal()>d.Minimal();	}
+//-----------------------------------------------------------------------------
+/// Integral data transformation (like Fourier 'f' or 'i', Hankel 'h' or None 'n') for amplitude and phase
+inline mglData mglTransformA(const mglDataA &am, const mglDataA &ph, const char *tr)
+{	return mglData(true,mgl_transform_a(&am,&ph,tr));	}
+/// Integral data transformation (like Fourier 'f' or 'i', Hankel 'h' or None 'n') for real and imaginary parts
+inline mglData mglTransform(const mglDataA &re, const mglDataA &im, const char *tr)
+{	return mglData(true,mgl_transform(&re,&im,tr));	}
+/// Apply Fourier transform for the data and save result into it
+inline void mglFourier(mglData &re, mglData &im, const char *dir)
+{	mgl_data_fourier(&re,&im,dir);	}
+/// Short time Fourier analysis for real and imaginary parts. Output is amplitude of partial Fourier (result will have size {dn, floor(nx/dn), ny} for dir='x'
+inline mglData mglSTFA(const mglDataA &re, const mglDataA &im, long dn, char dir='x')
+{	return mglData(true, mgl_data_stfa(&re,&im,dn,dir));	}
+//-----------------------------------------------------------------------------
+/// Saves result of PDE solving (|u|^2) for "Hamiltonian" ham with initial conditions ini
+inline mglData mglPDE(HMGL gr, const char *ham, const mglDataA &ini_re, const mglDataA &ini_im, mreal dz=0.1, mreal k0=100,const char *opt="")
+{	return mglData(true, mgl_pde_solve(gr,ham, &ini_re, &ini_im, dz, k0,opt));	}
+/// Saves result of PDE solving for "Hamiltonian" ham with initial conditions ini along a curve ray (must have nx>=7 - x,y,z,px,py,pz,tau or nx=5 - x,y,px,py,tau)
+inline mglData mglQO2d(const char *ham, const mglDataA &ini_re, const mglDataA &ini_im, const mglDataA &ray, mreal r=1, mreal k0=100)
+{	return mglData(true, mgl_qo2d_solve(ham, &ini_re, &ini_im, &ray, r, k0, 0, 0));	}
+inline mglData mglQO2d(const char *ham, const mglDataA &ini_re, const mglDataA &ini_im, const mglDataA &ray, mglData &xx, mglData &yy, mreal r=1, mreal k0=100)
+{	return mglData(true, mgl_qo2d_solve(ham, &ini_re, &ini_im, &ray, r, k0, &xx, &yy));	}
+/// Saves result of PDE solving for "Hamiltonian" ham with initial conditions ini along a curve ray (must have nx>=7 - x,y,z,px,py,pz,tau or nx=5 - x,y,px,py,tau)
+inline mglData mglQO3d(const char *ham, const mglDataA &ini_re, const mglDataA &ini_im, const mglDataA &ray, mreal r=1, mreal k0=100)
+{	return mglData(true, mgl_qo3d_solve(ham, &ini_re, &ini_im, &ray, r, k0, 0, 0, 0));	}
+inline mglData mglQO3d(const char *ham, const mglDataA &ini_re, const mglDataA &ini_im, const mglDataA &ray, mglData &xx, mglData &yy, mglData &zz, mreal r=1, mreal k0=100)
+{	return mglData(true, mgl_qo3d_solve(ham, &ini_re, &ini_im, &ray, r, k0, &xx, &yy, &zz));	}
+/// Finds ray with starting point r0, p0 (and prepares ray data for mglQO2d)
+inline mglData mglRay(const char *ham, mglPoint r0, mglPoint p0, mreal dt=0.1, mreal tmax=10)
+{	return mglData(true, mgl_ray_trace(ham, r0.x, r0.y, r0.z, p0.x, p0.y, p0.z, dt, tmax));	}
+/// Saves result of ODE solving for var complex variables with right part func (separated by ';') and initial conditions x0 over time interval [0,tmax] with time step dt
+inline mglData mglODE(const char *func, const char *var, const mglDataA &ini, mreal dt=0.1, mreal tmax=10)
+{	return mglData(true, mgl_ode_solve_str(func,var, &ini, dt, tmax));	}
+//-----------------------------------------------------------------------------
+/// Get array as solution of tridiagonal system of equations a[i]*x[i-1]+b[i]*x[i]+c[i]*x[i+1]=d[i]
+/** String \a how may contain:
+ * 'x', 'y', 'z' for solving along x-,y-,z-directions, or
+ * 'h' for solving along hexagonal direction at x-y plain (need nx=ny),
+ * 'c' for using periodical boundary conditions,
+ * 'd' for diffraction/diffuse calculation. */
+inline mglData mglTridMat(const mglDataA &A, const mglDataA &B, const mglDataA &C, const mglDataA &D, const char *how)
+{	return mglData(true, mgl_data_tridmat(&A, &B, &C, &D, how));	}
+//-----------------------------------------------------------------------------
+/// Calculate Jacobian determinant for D{x(u,v), y(u,v)} = dx/du*dy/dv-dx/dv*dy/du
+inline mglData mglJacobian(const mglDataA &x, const mglDataA &y)
+{	return mglData(true, mgl_jacobian_2d(&x, &y));	}
+/// Calculate Jacobian determinant for D{x(u,v,w), y(u,v,w), z(u,v,w)}
+inline mglData mglJacobian(const mglDataA &x, const mglDataA &y, const mglDataA &z)
+{	return mglData(true, mgl_jacobian_3d(&x, &y, &z));	}
+/// Do something like Delone triangulation
+inline mglData mglTriangulation(const mglDataA &x, const mglDataA &y, const mglDataA &z)
+{	return mglData(true,mgl_triangulation_3d(&x,&y,&z));	}
+inline mglData mglTriangulation(const mglDataA &x, const mglDataA &y)
+{	return mglData(true,mgl_triangulation_2d(&x,&y));	}
+/// Get curves, separated by NAN, for maximal values of array d as function of x coordinate.
+/** Noises below lvl amplitude are ignored.
+ * Parameter dy \in [0,ny] set the "attraction" distance of points to curve. */
+inline mglData mglDetect(const mglDataA &d, mreal lvl, mreal dj, mreal di=0, mreal min_len=0)
+{	return mglData(true,mgl_data_detect(&d, lvl, dj, di, min_len));	}
+//-----------------------------------------------------------------------------
+/// Get array which is n-th pairs {x[i],y[i]} for iterated function system (fractal) generated by A
+inline mglData mglIFS2d(const mglDataA &A, long n, long skip=20)
+{	return mglData(true,mgl_data_ifs_2d(&A,n,skip));	}
+/// Get array which is n-th points {x[i],y[i],z[i]} for iterated function system (fractal) generated by A
+inline mglData mglIFS3d(const mglDataA &A, long n, long skip=20)
+{	return mglData(true,mgl_data_ifs_3d(&A,n,skip));	}
+/// Get array which is n-th points {x[i],y[i],z[i]} for iterated function system (fractal) defined in *.ifs file 'fname' and named as 'name'
+inline mglData mglIFSfile(const char *fname, const char *name, long n, long skip=20)
+{	return mglData(true,mgl_data_ifs_file(fname,name,n,skip));	}
+/// Get array which is n-th pairs {x[i],y[i]} for Flame fractal generated by A with functions F
+/** NOTE: A.nx must be >= 7 and F.nx >= 2 and F.nz=A.ny.
+ * F[0,i,j] denote function id. F[1,i,j] give function weight, F(2:5,i,j) provide function parameters.
+ * Resulting point is {xnew,ynew} = sum_i F[1,i,j]*F[0,i,j]{IFS2d(A[j]){x,y}}. */
+inline mglData mglFlame2d(const mglDataA &A, const mglDataA &F, long n, long skip=20)
+{	return mglData(true,mgl_data_flame_2d(&A,&F,n,skip));	}
+//-----------------------------------------------------------------------------
+/// Get sub-array of the data with given fixed indexes
+inline mglData mglSubData(const mglDataA &dat, long xx, long yy=-1, long zz=-1)
+{	return mglData(true,mgl_data_subdata(&dat,xx,yy,zz));	}
+inline mglData mglSubData(const mglDataA &dat, const mglDataA &xx, const mglDataA &yy, const mglDataA &zz)
+{	return mglData(true,mgl_data_subdata_ext(&dat,&xx,&yy,&zz));	}
+inline mglData mglSubData(const mglDataA &dat, const mglDataA &xx, const mglDataA &yy)
+{	return mglData(true,mgl_data_subdata_ext(&dat,&xx,&yy,0));	}
+inline mglData mglSubData(const mglDataA &dat, const mglDataA &xx)
+{	return mglData(true,mgl_data_subdata_ext(&dat,&xx,0,0));	}
+//-----------------------------------------------------------------------------
+/// Prepare coefficients for global spline interpolation
+inline mglData mglGSplineInit(const mglDataA &xdat, const mglDataA &ydat)
+{	return mglData(true,mgl_gspline_init(&xdat, &ydat));	}
+/// Evaluate global spline (and its derivatives d1, d2 if not NULL) using prepared coefficients \a coef
+inline mreal mglGSpline(const mglDataA &coef, mreal dx, mreal *d1=0, mreal *d2=0)
+{	return mgl_gspline(&coef, dx, d1,d2);	}
+//-----------------------------------------------------------------------------
+/// Wrapper class for expression evaluating
+class MGL_EXPORT mglExpr
+{
+	HMEX ex;
+	mglExpr(const mglExpr &){}	// copying is not allowed
+	const mglExpr &operator=(const mglExpr &t){return t;}	// copying is not allowed
+public:
+	mglExpr(const char *expr)		{	ex = mgl_create_expr(expr);	}
+#if MGL_HAVE_RVAL
+	mglExpr(mglExpr &&d):ex(d.ex)	{	d.ex=0;	}
+#endif
+	~mglExpr()	{	mgl_delete_expr(ex);	}
+	/// Return value of expression for given x,y,z variables
+	inline double Eval(double x, double y=0, double z=0)
+	{	return mgl_expr_eval(ex,x,y,z);	}
+	/// Return value of expression differentiation over variable dir for given x,y,z variables
+	inline double Diff(char dir, double x, double y=0, double z=0)
+	{	return mgl_expr_diff(ex,dir, x,y,z);	}
+#ifndef SWIG
+	/// Return value of expression for given variables
+	inline double Eval(mreal var[26])
+	{	return mgl_expr_eval_v(ex,var);	}
+	/// Return value of expression differentiation over variable dir for given variables
+	inline double Diff(char dir, mreal var[26])
+	{	return mgl_expr_diff_v(ex,dir, var);	}
+#endif
+};
+//-----------------------------------------------------------------------------
+/// Class which present equidistantly distributed data
+class MGL_EXPORT mglDataV : public mglDataA
+{
+	long nx;	///< number of points in 1st dimensions ('x' dimension)
+	long ny;	///< number of points in 2nd dimensions ('y' dimension)
+	long nz;	///< number of points in 3d dimensions ('z' dimension)
+	mreal di, dj, dk, a0;
+public:
+	mglDataV(long xx=1,long yy=1,long zz=1,mreal x1=0,mreal x2=mglNaN,char dir='x'):nx(xx),ny(yy),nz(zz)
+	{	Fill(x1,x2,dir);	}
+	mglDataV(const mglDataV &d):nx(d.nx),ny(d.ny),nz(d.nz),di(d.di),dj(d.dj),dk(d.dk),a0(d.a0)	{}
+#if MGL_HAVE_RVAL
+	mglDataV(mglDataV &&d):nx(d.nx),ny(d.ny),nz(d.nz),di(d.di),dj(d.dj),dk(d.dk),a0(d.a0)
+	{	s=d.s;	temp=d.temp;	func=d.func;	o=d.o;	d.func=0;	}
+#endif
+	virtual ~mglDataV()	{}
+
+	/// Get sizes
+	long GetNx() const	{	return nx;	}
+	long GetNy() const	{	return ny;	}
+	long GetNz() const	{	return nz;	}
+
+	/// Create or recreate the array with specified size and fill it by zero
+	inline void Create(long mx,long my=1,long mz=1)
+	{	di=mx>1?di*(nx-1)/(mx-1):0;	dj=my>1?dj*(ny-1)/(my-1):0;
+		dk=mz>1?dk*(nz-1)/(mz-1):0;	nx=mx;	ny=my;	nz=mz;	}
+	/// For going throw all elements
+	inline void All()	{	di=dj=dk=1;	a0=0;	}
+	/// Equidistantly fill the data to range [x1,x2] in direction dir
+	inline void Fill(mreal x1,mreal x2=mglNaN,char dir='x')
+	{
+		di=dj=dk=0;	a0=x1;
+		if(mgl_isnum(x2))
+		{
+			if(dir=='x' && nx>1)	di=(x2-x1)/(nx-1);
+			if(dir=='y' && ny>1)	dj=(x2-x1)/(ny-1);
+			if(dir=='z' && nz>1)	dk=(x2-x1)/(nz-1);
+		}
+	}
+	mreal Maximal() const
+	{	return a0+mgl_max(mgl_max(di*(nx-1),dj*(ny-1)),mgl_max(dk*(nz-1),0));	}
+	mreal Minimal() const
+	{	return a0+mgl_min(mgl_min(di*(nx-1),dj*(ny-1)),mgl_min(dk*(nz-1),0));	}
+
+	/// Copy data from other mglDataV variable
+	inline const mglDataV &operator=(const mglDataV &d)
+	{	nx=d.nx;	ny=d.ny;	nz=d.nz;	a0=d.a0;
+		di=d.di;	dj=d.dj;	dk=d.dk;	return d;	}
+	inline mreal operator=(mreal val)
+	{	di=dj=dk=0;	a0=val;	return val;	}
+	/// Get the interpolated value and its derivatives in given data cell without border checking
+	mreal valueD(mreal x,mreal y=0,mreal z=0,mreal *dx=0,mreal *dy=0,mreal *dz=0) const
+	{	if(dx)	*dx=di;	if(dy)	*dy=dj;	if(dz)	*dz=dk;
+		return a0+di*x+dj*y+dk*z;	}
+	/// Get the interpolated value in given data cell without border checking
+	mreal value(mreal x,mreal y=0,mreal z=0) const	{	return a0+di*x+dj*y+dk*z;	}
+	mreal v(long i,long j=0,long k=0) const		{	return a0+di*i+dj*j+dk*k;	}
+	mreal vthr(long ii) const
+	{	long i=ii%nx, j=(ii/nx)%ny, k=ii/(nx*ny);	return a0+di*i+dj*j+dk*k;	}
+	// add for speeding up !!!
+	mreal dvx(long ,long =0,long =0) const	{	return di;	}
+	mreal dvy(long ,long =0,long =0) const	{	return dj;	}
+	mreal dvz(long ,long =0,long =0) const	{	return dk;	}
+};
+//-----------------------------------------------------------------------------
+/// Class which present FFT frequency as data array
+class MGL_EXPORT mglDataW : public mglDataA
+{
+	long nx;	///< number of points in 1st dimensions ('x' dimension)
+	long ny;	///< number of points in 2nd dimensions ('y' dimension)
+	long nz;	///< number of points in 3d dimensions ('z' dimension)
+	mreal di, dj, dk;
+public:
+
+	mglDataW(long xx=1,long yy=1,long zz=1,mreal dp=0,char dir='x'):nx(xx),ny(yy),nz(zz)
+	{	Freq(dp,dir);	}
+	mglDataW(const mglDataW &d):nx(d.nx),ny(d.ny),nz(d.nz),di(d.di),dj(d.dj),dk(d.dk)	{}
+#if MGL_HAVE_RVAL
+	mglDataW(mglDataW &&d):nx(d.nx),ny(d.ny),nz(d.nz),di(d.di),dj(d.dj),dk(d.dk)
+	{	s=d.s;	temp=d.temp;	func=d.func;	o=d.o;	d.func=0;	}
+#endif
+	virtual ~mglDataW()	{}
+
+	/// Get sizes
+	long GetNx() const	{	return nx;	}
+	long GetNy() const	{	return ny;	}
+	long GetNz() const	{	return nz;	}
+
+	/// Create or recreate the array with specified size and fill it by zero
+	inline void Create(long mx,long my=1,long mz=1)
+	{	nx=mx;	ny=my;	nz=mz;	}
+	/// For going throw all elements
+	inline void All()	{	di=dj=dk=1;	}
+	/// Equidistantly fill the data to range [x1,x2] in direction dir
+	inline void Freq(mreal dp,char dir='x')
+	{
+		di=dj=dk=0;
+		if(dir=='x')	di=dp;
+		if(dir=='y')	dj=dp;
+		if(dir=='z')	dk=dp;
+	}
+	mreal Maximal() const
+	{	return mgl_max(mgl_max(di*(nx-1),dj*(ny-1)),mgl_max(dk*(nz-1),0));	}
+	mreal Minimal() const
+	{	return mgl_min(mgl_min(di*(nx-1),dj*(ny-1)),mgl_min(dk*(nz-1),0));	}
+
+	/// Copy data from other mglDataV variable
+	inline const mglDataW &operator=(const mglDataW &d)
+	{	nx=d.nx;	ny=d.ny;	nz=d.nz;	di=d.di;	dj=d.dj;	dk=d.dk;	return d;	}
+	/// Get the interpolated value and its derivatives in given data cell without border checking
+	mreal valueD(mreal x,mreal y=0,mreal z=0,mreal *dx=0,mreal *dy=0,mreal *dz=0) const
+	{	if(dx)	*dx=di;	if(dy)	*dy=dj;	if(dz)	*dz=dk;
+		return di*(x<nx/2?x:x-nx)+dj*(y<ny/2?y:y-ny)+dk*(z<nz/2?z:z-nz);	}
+	/// Get the interpolated value in given data cell without border checking
+	mreal value(mreal x,mreal y=0,mreal z=0) const
+	{	return di*(x<nx/2?x:x-nx)+dj*(y<ny/2?y:y-ny)+dk*(z<nz/2?z:z-nz);	}
+	mreal v(long i,long j=0,long k=0) const
+	{	return di*(i<nx/2?i:i-nx)+dj*(j<ny/2?j:j-ny)+dk*(k<nz/2?k:k-nz);	}
+	mreal vthr(long ii) const
+	{	long i=ii%nx, j=(ii/nx)%ny, k=ii/(nx*ny);
+		return di*(i<nx/2?i:i-nx)+dj*(j<ny/2?j:j-ny)+dk*(k<nz/2?k:k-nz);	}
+	// add for speeding up !!!
+	mreal dvx(long ,long =0,long =0) const	{	return di;	}
+	mreal dvy(long ,long =0,long =0) const	{	return dj;	}
+	mreal dvz(long ,long =0,long =0) const	{	return dk;	}
+};
+//-----------------------------------------------------------------------------
+/// Class which present function as data array
+class MGL_EXPORT mglDataF : public mglDataA
+{
+	long nx;	///< number of points in 1st dimensions ('x' dimension)
+	long ny;	///< number of points in 2nd dimensions ('y' dimension)
+	long nz;	///< number of points in 3d dimensions ('z' dimension)
+	std::string str;	///< function as string
+	mglPoint v1, v2;	///< ranges for coordinates
+	HMEX ex;			///< parsed variant
+	mreal dx,dy,dz;
+	inline void setD()
+	{
+		dx = nx>1?(v2.x-v1.x)/(nx-1):0;
+		dy = ny>1?(v2.y-v1.y)/(ny-1):0;
+		dz = nz>1?(v2.z-v1.z)/(nz-1):0;
+	}
+	mreal (*dfunc)(mreal i, mreal j, mreal k, void *par);
+	void *par;
+public:
+
+	mglDataF(long xx=1,long yy=1,long zz=1):nx(xx),ny(yy),nz(zz), dfunc(0),par(0)
+	{	ex=0;	v2.Set(1,1,1);	setD();	}
+	mglDataF(const mglDataF &d) : nx(d.nx), ny(d.ny), nz(d.nz), str(d.str), v1(d.v1), v2(d.v2), dx(d.dx),dy(d.dy),dz(d.dz), dfunc(d.dfunc),par(d.par)
+	{	ex = mgl_create_expr(str.c_str());	}
+#if MGL_HAVE_RVAL
+	mglDataF(mglDataF &&d):nx(d.nx),ny(d.ny),nz(d.nz), str(d.str), v1(d.v1),v2(d.v2), ex(d.ex), dx(d.dx),dy(d.dy),dz(d.dz), dfunc(d.dfunc),par(d.par)
+	{	s=d.s;	temp=d.temp;	func=d.func;	o=d.o;	d.ex=0;	d.func=0;	}
+#endif
+	virtual ~mglDataF()	{	mgl_delete_expr(ex);	}
+
+	/// Get sizes
+	long GetNx() const	{	return nx;	}
+	long GetNy() const	{	return ny;	}
+	long GetNz() const	{	return nz;	}
+
+	/// Create or recreate the array with specified size and fill it by zero
+	inline void Create(long mx,long my=1,long mz=1)	{	nx=mx;	ny=my;	nz=mz;	setD();	}
+	inline void SetRanges(mglPoint p1, mglPoint p2)	{	v1=p1;	v2=p2;	setD();	}
+	/// Set formula to be used as dfunction
+	inline void SetFormula(const char *eq)
+	{
+		mgl_delete_expr(ex);	dfunc=0;	par=0;
+		if(eq && *eq)	{	ex = mgl_create_expr(eq);	str=eq;	}
+		else	{	ex=0;	str="";	}
+	}
+	/// Set function and coordinates range [r1,r2]
+	inline void SetFunc(mreal (*f)(mreal,mreal,mreal,void*), void *p=NULL)
+	{	mgl_delete_expr(ex);	ex=0;	dfunc=f;	par=p;	}
+
+	/// Get the interpolated value and its derivatives in given data cell without border checking
+	mreal valueD(mreal i,mreal j=0,mreal k=0, mreal *di=0,mreal *dj=0,mreal *dk=0) const
+	{
+		mreal res=0, x=v1.x+dx*i, y=v1.y+dy*j, z=v1.z+dz*k;
+		if(di)	*di = 0;
+		if(dj)	*dj = 0;
+		if(dk)	*dk = 0;
+		if(dfunc)
+		{
+			res = dfunc(x,y,z, par);
+			if(di)	*di = dfunc(x+dx,y,z, par)-res;
+			if(dj)	*dj = dfunc(x,y+dy,z, par)-res;
+			if(dk)	*dk = dfunc(x,y,z+dz, par)-res;
+		}
+		else if(ex)
+		{
+			if(di)	*di = mgl_expr_diff(ex,'x',x,y,z)*dx;
+			if(dj)	*dj = mgl_expr_diff(ex,'y',x,y,z)*dy;
+			if(dk)	*dk = mgl_expr_diff(ex,'z',x,y,z)*dz;
+			res = mgl_expr_eval(ex,x,y,z);
+		}
+		return res;
+	}
+	/// Get the interpolated value in given data cell without border checking
+	mreal value(mreal i,mreal j=0,mreal k=0) const
+	{
+		mreal res=0, x=v1.x+dx*i, y=v1.y+dy*j, z=v1.z+dz*k;
+		if(dfunc)	res = dfunc(x,y,z, par);
+		else if(ex)	res = mgl_expr_eval(ex,x,y,z);
+		return res;
+	}
+	/// Copy data from other mglDataV variable
+	inline const mglDataF &operator=(const mglDataF &d)
+	{	nx=d.nx;	ny=d.ny;	nz=d.nz;	v1=d.v1;	v2=d.v2;	setD();	mgl_delete_expr(ex);
+		str=d.str;	ex = mgl_create_expr(str.c_str());	dfunc=d.dfunc;	par=d.par;	return d;	}
+	/// Get the value in given cell of the data without border checking
+	mreal v(long i,long j=0,long k=0) const
+	{
+		mreal res=0, x=v1.x+dx*i, y=v1.y+dy*j, z=v1.z+dz*k;
+		if(dfunc)	res = dfunc(x,y,z, par);
+		else if(ex)	res = mgl_expr_eval(ex,x,y,z);
+		return res;
+	}
+	mreal vthr(long i) const
+	{
+		mreal res=0, x=v1.x+dx*(i%nx), y=v1.y+dy*((i/nx)%ny), z=v1.z+dz*(i/(nx*ny));
+		if(dfunc)	res = dfunc(x,y,z, par);
+		else if(ex)	res = mgl_expr_eval(ex,x,y,z);
+		return res;
+	}
+	// add for speeding up !!!
+	mreal dvx(long i,long j=0,long k=0) const
+	{
+		mreal res=0, x=v1.x+dx*i, y=v1.y+dy*j, z=v1.z+dz*k;
+		if(dfunc)	res = dfunc(x+dx,y,z, par)-dfunc(x,y,z, par);
+		else if(ex)	res = mgl_expr_eval(ex,x+dx,y,z)-mgl_expr_eval(ex,x,y,z);
+		return res;
+	}
+	mreal dvy(long i,long j=0,long k=0) const
+	{
+		mreal res=0, x=v1.x+dx*i, y=v1.y+dy*j, z=v1.z+dz*k;
+		if(dfunc)	res = dfunc(x,y+dy,z, par)-dfunc(x,y,z, par);
+		else if(ex)	res = mgl_expr_eval(ex,x,y+dy,z)-mgl_expr_eval(ex,x,y,z);
+		return res;
+	}
+	mreal dvz(long i,long j=0,long k=0) const
+	{
+		mreal res=0, x=v1.x+dx*i, y=v1.y+dy*j, z=v1.z+dz*k;
+		if(dfunc)	res = dfunc(x,y,z+dz, par)-dfunc(x,y,z, par);
+		else if(ex)	res = mgl_expr_eval(ex,x,y,z+dz)-mgl_expr_eval(ex,x,y,z);
+		return res;
+	}
+};
+//-----------------------------------------------------------------------------
+/// Class which present column of another data as data array
+class MGL_EXPORT mglDataT : public mglDataA
+{
+	const mglDataA &dat;
+	long ind;
+	const mglDataT &operator=(const mglDataT &d)	{	return d;	}
+public:
+	mglDataT(const mglDataT &d) : dat(d.dat), ind(d.ind)	{	s = d.s;	}
+	mglDataT(const mglDataA &d, long col=0) : dat(d), ind(col)	{}
+	mglDataT(HCDT d, long col=0) : dat(*d), ind(col)	{}
+#if MGL_HAVE_RVAL
+	mglDataT(mglDataT &&d):dat(d.dat),ind(d.ind)
+	{	s=d.s;	temp=d.temp;	func=d.func;	o=d.o;	d.func=0;	}
+#endif
+	virtual ~mglDataT()	{}
+
+	/// Get sizes
+	long GetNx() const	{	return dat.GetNy();	}
+	long GetNy() const	{	return dat.GetNz();	}
+	long GetNz() const	{	return 1;	}
+
+	mreal Maximal() const
+	{	return mglSubData(dat,ind).Maximal();	}
+	mreal Minimal() const
+	{	return mglSubData(dat,ind).Minimal();	}
+	inline void SetInd(long i, const wchar_t *name)
+	{	ind = i;	s = name;	}
+	inline void SetInd(long i, wchar_t name)
+	{	ind = i;	s = name;	}
+
+	/// Get the interpolated value and its derivatives in given data cell without border checking
+	mreal valueD(mreal x,mreal y=0,mreal =0,mreal *dx=0,mreal *dy=0,mreal *dz=0) const
+	{	if(dz)	*dz=0;	return dat.valueD(ind,x,y,0,dx,dy);	}
+	/// Get the interpolated value in given data cell without border checking
+	mreal value(mreal x,mreal y=0,mreal =0) const
+	{	return dat.value(ind,x,y);	}
+	/// Get the value in given cell of the data without border checking
+	mreal v(long i,long j=0,long =0) const
+	{	return dat.v(ind,i,j);	}
+	mreal vthr(long i) const
+	{	return dat.vthr(ind+dat.GetNx()*i);	}
+	// add for speeding up !!!
+	mreal dvx(long i,long j=0,long =0) const
+	{	return	dat.dvy(ind,i,j);	}
+	mreal dvy(long i,long j=0,long =0) const
+	{	return dat.dvz(ind,i,j);	}
+	mreal dvz(long ,long =0,long =0) const
+	{	return 0;	}
+};
+//-----------------------------------------------------------------------------
+/// Class which present row of another data as data array
+class MGL_EXPORT mglDataR : public mglDataA
+{
+	const mglDataA &dat;
+	long ind;
+	const mglDataR &operator=(const mglDataR &d)	{	return d;	}
+public:
+	mglDataR(const mglDataR &d) : dat(d.dat), ind(d.ind)	{	s = d.s;	}
+	mglDataR(const mglDataA &d, long row=0) : dat(d), ind(row)	{}
+	mglDataR(HCDT d, long row=0) : dat(*d), ind(row)	{}
+#if MGL_HAVE_RVAL
+	mglDataR(mglDataR &&d):dat(d.dat),ind(d.ind)
+	{	s=d.s;	temp=d.temp;	func=d.func;	o=d.o;	d.func=0;	}
+#endif
+	virtual ~mglDataR()	{}
+
+	/// Get sizes
+	long GetNx() const	{	return dat.GetNx();	}
+	long GetNy() const	{	return 1;	}
+	long GetNz() const	{	return 1;	}
+
+	mreal Maximal() const
+	{	return mglSubData(dat,-1,ind).Maximal();	}
+	mreal Minimal() const
+	{	return mglSubData(dat,-1,ind).Minimal();	}
+	inline void SetInd(long i, const wchar_t *name)
+	{	ind = i;	s = name;	}
+	inline void SetInd(long i, wchar_t name)
+	{	ind = i;	s = name;	}
+
+	/// Get the interpolated value and its derivatives in given data cell without border checking
+	mreal valueD(mreal x,mreal =0,mreal =0,mreal *dx=0,mreal *dy=0,mreal *dz=0) const
+	{	if(dy)	*dy=0;	if(dz)	*dz=0;	return dat.valueD(x,ind,0,dx);	}
+	/// Get the interpolated value in given data cell without border checking
+	mreal value(mreal x,mreal =0,mreal =0) const
+	{	return dat.value(x,ind,0);	}
+	/// Get the value in given cell of the data without border checking
+	mreal v(long i,long =0,long =0) const
+	{	return dat.v(i,ind,0);	}
+	mreal vthr(long i) const
+	{	return dat.vthr(i+dat.GetNx()*ind);	}
+	// add for speeding up !!!
+	mreal dvx(long i,long =0,long =0) const
+	{	return	dat.dvx(i,ind,0);	}
+	mreal dvy(long ,long =0,long =0) const
+	{	return 0;	}
+	mreal dvz(long ,long =0,long =0) const
+	{	return 0;	}
+};
+//-----------------------------------------------------------------------------
+/// Class which present std::vector as data array
+class MGL_EXPORT mglDataS : public mglDataA
+{
+public:
+	std::vector<mreal> dat;
+
+	mglDataS(const mglDataS &st) : dat(st.dat)	{}
+	mglDataS(const std::vector<mreal> &d) : dat(d)	{}
+	mglDataS(size_t s=1)	{	dat.resize(s);	}
+	~mglDataS()	{}
+	inline void reserve(size_t num)	{	dat.reserve(num);	}
+	inline void clear()	{	dat.clear();	}
+	inline double operator[](size_t i)	{	return dat[i];	}
+	inline void push_back(double t)	{	dat.push_back(t);	}
+	inline size_t size() const	{	return dat.size();	}
+	const mglDataS &operator=(const mglDataS &st)	{	dat = st.dat;	return st;	}
+	const std::vector<mreal> &operator=(const std::vector<mreal> &st)	{	dat = st;	return st;	}
+
+	/// Get the interpolated value and its derivatives in given data cell without border checking
+	mreal valueD(mreal x,mreal =0,mreal =0,mreal *dx=0,mreal *dy=0,mreal *dz=0) const
+	{	return mglSpline3(dat.data(),dat.size(),1,1,x,0,0,dx,dy,dz);	}
+	/// Get the interpolated value in given data cell without border checking
+	mreal value(mreal x,mreal =0,mreal =0) const
+	{	return mglSpline3s(dat.data(),dat.size(),1,1,x,0,0);	}
+
+	mreal v(long i,long =0,long =0) const		{	return dat[i];	}
+	mreal vthr(long i) const	{	return dat[i];	}
+	long GetNx() const	{	return dat.size();	}
+	long GetNy() const	{	return 1;	}
+	long GetNz() const	{	return 1;	}
+	mreal dvx(long i,long =0,long =0) const
+	{	return i>0? (i<long(dat.size()-1)? (dat[i+1]-dat[i-1])/2:dat[i]-dat[i-1]) : dat[i+1]-dat[i];	}
+	mreal dvy(long ,long =0,long =0) const	{	return 0;	}
+	mreal dvz(long ,long =0,long =0) const	{	return 0;	}
+};
+//-----------------------------------------------------------------------------
+#endif
+#endif
diff --git a/include/mgl2/data_cf.h b/include/mgl2/data_cf.h
new file mode 100644
index 0000000..ecb83d0
--- /dev/null
+++ b/include/mgl2/data_cf.h
@@ -0,0 +1,531 @@
+/***************************************************************************
+ * data_cf.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_DATA_CF_H_
+#define _MGL_DATA_CF_H_
+//-----------------------------------------------------------------------------
+#include "mgl2/abstract.h"
+//-----------------------------------------------------------------------------
+#if MGL_HAVE_GSL
+#include <gsl/gsl_vector.h>
+#include <gsl/gsl_matrix.h>
+#else
+#ifdef __cplusplus
+struct gsl_vector;
+struct gsl_matrix;
+#else
+typedef void gsl_vector;
+typedef void gsl_matrix;
+#endif
+#endif
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+extern "C" {
+#endif
+/// Get integer power of x
+double MGL_EXPORT_CONST mgl_ipow(double x,int n);
+double MGL_EXPORT mgl_ipow_(mreal *x,int *n);
+/// Get number of seconds since 1970 for given string
+double MGL_EXPORT mgl_get_time(const char *time, const char *fmt);
+double MGL_EXPORT mgl_get_time_(const char *time, const char *fmt,int,int);
+
+/// Create HMDT object
+HMDT MGL_EXPORT mgl_create_data();
+uintptr_t MGL_EXPORT mgl_create_data_();
+/// Create HMDT object with specified sizes
+HMDT MGL_EXPORT mgl_create_data_size(long nx, long ny, long nz);
+uintptr_t MGL_EXPORT mgl_create_data_size_(int *nx, int *ny, int *nz);
+/// Create HMDT object with data from file
+HMDT MGL_EXPORT mgl_create_data_file(const char *fname);
+uintptr_t MGL_EXPORT mgl_create_data_file_(const char *fname, int len);
+/// Delete HMDT object
+void MGL_EXPORT mgl_delete_data(HMDT dat);
+void MGL_EXPORT mgl_delete_data_(uintptr_t *dat);
+
+/// Rearange data dimensions
+void MGL_EXPORT mgl_data_rearrange(HMDT dat, long mx,long my,long mz);
+void MGL_EXPORT mgl_data_rearrange_(uintptr_t *dat, int *mx, int *my, int *mz);
+/// Link external data array (don't delete it at exit)
+void MGL_EXPORT mgl_data_link(HMDT dat, mreal *A,long mx,long my,long mz);
+void MGL_EXPORT mgl_data_link_(uintptr_t *d, mreal *A, int *nx,int *ny,int *nz);
+/// Allocate memory and copy the data from the (float *) array
+void MGL_EXPORT mgl_data_set_float(HMDT dat, const float *A,long mx,long my,long mz);
+void MGL_EXPORT mgl_data_set_float_(uintptr_t *dat, const float *A,int *NX,int *NY,int *NZ);
+void MGL_EXPORT mgl_data_set_float1_(uintptr_t *d, const float *A,int *N1);
+/// Allocate memory and copy the data from the (double *) array
+void MGL_EXPORT mgl_data_set_double(HMDT dat, const double *A,long mx,long my,long mz);
+void MGL_EXPORT mgl_data_set_double_(uintptr_t *dat, const double *A,int *NX,int *NY,int *NZ);
+void MGL_EXPORT mgl_data_set_double1_(uintptr_t *d, const double *A,int *N1);
+/// Allocate memory and copy the data from the (float **) array
+void MGL_EXPORT mgl_data_set_float2(HMDT d, float const * const *A,long N1,long N2);
+void MGL_EXPORT mgl_data_set_float2_(uintptr_t *d, const float *A,int *N1,int *N2);
+/// Allocate memory and copy the data from the (double **) array
+void MGL_EXPORT mgl_data_set_double2(HMDT d, double const * const *A,long N1,long N2);
+void MGL_EXPORT mgl_data_set_double2_(uintptr_t *d, const double *A,int *N1,int *N2);
+/// Allocate memory and copy the data from the (float ***) array
+void MGL_EXPORT mgl_data_set_float3(HMDT d, float const * const * const *A,long N1,long N2,long N3);
+void MGL_EXPORT mgl_data_set_float3_(uintptr_t *d, const float *A,int *N1,int *N2,int *N3);
+/// Allocate memory and copy the data from the (double ***) array
+void MGL_EXPORT mgl_data_set_double3(HMDT d, double const * const * const *A,long N1,long N2,long N3);
+void MGL_EXPORT mgl_data_set_double3_(uintptr_t *d, const double *A,int *N1,int *N2,int *N3);
+/// Import data from abstract type
+void MGL_EXPORT mgl_data_set(HMDT dat, HCDT a);
+void MGL_EXPORT mgl_data_set_(uintptr_t *dat, uintptr_t *a);
+/// Allocate memory and copy the data from the gsl_vector
+void MGL_EXPORT mgl_data_set_vector(HMDT dat, gsl_vector *v);
+/// Allocate memory and copy the data from the gsl_matrix
+void MGL_EXPORT mgl_data_set_matrix(HMDT dat, gsl_matrix *m);
+/// Set value of data element [i,j,k]
+void MGL_EXPORT mgl_data_set_value(HMDT dat, mreal v, long i, long j, long k);
+void MGL_EXPORT mgl_data_set_value_(uintptr_t *d, mreal *v, int *i, int *j, int *k);
+/// Get value of data element [i,j,k]
+mreal MGL_EXPORT mgl_data_get_value(HCDT dat, long i, long j, long k);
+mreal MGL_EXPORT mgl_data_get_value_(uintptr_t *d, int *i, int *j, int *k);
+/// Allocate memory and scanf the data from the string
+void MGL_EXPORT mgl_data_set_values(HMDT dat, const char *val, long nx, long ny, long nz);
+void MGL_EXPORT mgl_data_set_values_(uintptr_t *d, const char *val, int *nx, int *ny, int *nz, int l);
+
+/// Read data array from HDF file (parse HDF4 and HDF5 files)
+int MGL_EXPORT mgl_data_read_hdf(HMDT d,const char *fname,const char *data);
+int MGL_EXPORT mgl_data_read_hdf_(uintptr_t *d, const char *fname, const char *data,int l,int n);
+/// Read data from tab-separated text file with auto determining size
+int MGL_EXPORT mgl_data_read(HMDT dat, const char *fname);
+int MGL_EXPORT mgl_data_read_(uintptr_t *d, const char *fname,int l);
+/// Read data from text file with size specified at beginning of the file
+int MGL_EXPORT mgl_data_read_mat(HMDT dat, const char *fname, long dim);
+int MGL_EXPORT mgl_data_read_mat_(uintptr_t *dat, const char *fname, int *dim, int);
+/// Read data from text file with specifeid size
+int MGL_EXPORT mgl_data_read_dim(HMDT dat, const char *fname,long mx,long my,long mz);
+int MGL_EXPORT mgl_data_read_dim_(uintptr_t *dat, const char *fname,int *mx,int *my,int *mz,int);
+/// Read data from tab-separated text files with auto determining size which filenames are result of sprintf(fname,templ,t) where t=from:step:to
+int MGL_EXPORT mgl_data_read_range(HMDT d, const char *templ, double n1, double n2, double step, int as_slice);
+int MGL_EXPORT mgl_data_read_range_(uintptr_t *d, const char *fname, mreal *n1, mreal *n2, mreal *step, int *as_slice,int l);
+/// Read data from tab-separated text files with auto determining size which filenames are satisfied to template (like "t_*.dat")
+int MGL_EXPORT mgl_data_read_all(HMDT dat, const char *templ, int as_slice);
+int MGL_EXPORT mgl_data_read_all_(uintptr_t *d, const char *fname, int *as_slice,int l);
+/// Import data array from PNG file according color scheme
+void MGL_EXPORT mgl_data_import(HMDT dat, const char *fname, const char *scheme,mreal v1,mreal v2);
+void MGL_EXPORT mgl_data_import_(uintptr_t *dat, const char *fname, const char *scheme,mreal *v1,mreal *v2,int,int);
+/// Scan textual file for template and fill data array
+int MGL_EXPORT mgl_data_scan_file(HMDT dat,const char *fname, const char *templ);
+int MGL_EXPORT mgl_data_scan_file_(uintptr_t *dat,const char *fname, const char *templ,int,int);
+/// Read data array from Tektronix WFM file
+/** Parse Tektronix TDS5000/B, TDS6000/B/C, TDS/CSA7000/B, MSO70000/C, DSA70000/B/C DPO70000/B/C DPO7000/ MSO/DPO5000. */
+int MGL_EXPORT mgl_data_read_wfm(HMDT d,const char *fname, long num, long step, long start);
+int MGL_EXPORT mgl_data_read_wfm_(uintptr_t *d, const char *fname, long *num, long *step, long *start,int l);
+/// Read data array from Matlab MAT file (parse versions 4 and 5)
+int MGL_EXPORT mgl_data_read_matlab(HMDT d,const char *fname,const char *data);
+int MGL_EXPORT mgl_data_read_matlab_(uintptr_t *d, const char *fname, const char *data,int l,int n);
+
+/// Create or recreate the array with specified size and fill it by zero
+void MGL_EXPORT mgl_data_create(HMDT dat, long nx,long ny,long nz);
+void MGL_EXPORT mgl_data_create_(uintptr_t *dat, int *nx,int *ny,int *nz);
+/// Transpose dimensions of the data (generalization of Transpose)
+void MGL_EXPORT mgl_data_transpose(HMDT dat, const char *dim);
+void MGL_EXPORT mgl_data_transpose_(uintptr_t *dat, const char *dim,int);
+/// Normalize the data to range [v1,v2]
+void MGL_EXPORT mgl_data_norm(HMDT dat, mreal v1,mreal v2,int sym,long dim);
+void MGL_EXPORT mgl_data_norm_(uintptr_t *dat, mreal *v1,mreal *v2,int *sym,int *dim);
+/// Normalize the data to range [v1,v2] slice by slice
+void MGL_EXPORT mgl_data_norm_slice(HMDT dat, mreal v1,mreal v2,char dir,long keep_en,long sym);
+void MGL_EXPORT mgl_data_norm_slice_(uintptr_t *dat, mreal *v1,mreal *v2,char *dir,int *keep_en,int *sym,int l);
+/// Limit the data to be inside [-v,v], keeping the original sign
+void MGL_EXPORT mgl_data_limit(HMDT dat, mreal v);
+void MGL_EXPORT mgl_data_limit_(uintptr_t *dat, mreal *v);
+/// Get sub-array of the data with given fixed indexes
+HMDT MGL_EXPORT mgl_data_subdata(HCDT dat, long xx,long yy,long zz);
+uintptr_t MGL_EXPORT mgl_data_subdata_(uintptr_t *dat, int *xx,int *yy,int *zz);
+/// Get sub-array of the data with given fixed indexes (like indirect access)
+HMDT MGL_EXPORT mgl_data_subdata_ext(HCDT dat, HCDT xx, HCDT yy, HCDT zz);
+uintptr_t MGL_EXPORT mgl_data_subdata_ext_(uintptr_t *dat, uintptr_t *xx,uintptr_t *yy,uintptr_t *zz);
+/// Get column (or slice) of the data filled by formulas of named columns
+HMDT MGL_EXPORT mgl_data_column(HCDT dat, const char *eq);
+uintptr_t MGL_EXPORT mgl_data_column_(uintptr_t *dat, const char *eq,int l);
+/// Get data from sections ids, separated by value val along specified direction.
+/** If section id is negative then reverse order is used (i.e. -1 give last section). */
+HMDT MGL_EXPORT mgl_data_section(HCDT dat, HCDT ids, char dir, mreal val);
+uintptr_t MGL_EXPORT mgl_data_section_(uintptr_t *d, uintptr_t *ids, const char *dir, mreal *val,int);
+/// Get data from section id, separated by value val along specified direction.
+/** If section id is negative then reverse order is used (i.e. -1 give last section). */
+HMDT MGL_EXPORT mgl_data_section_val(HCDT dat, long id, char dir, mreal val);
+uintptr_t MGL_EXPORT mgl_data_section_val_(uintptr_t *d, int *id, const char *dir, mreal *val,int);
+
+/// Set names for columns (slices)
+void MGL_EXPORT mgl_data_set_id(HMDT d, const char *id);
+void MGL_EXPORT mgl_data_set_id_(uintptr_t *dat, const char *id,int l);
+/// Equidistantly fill the data to range [x1,x2] in direction dir
+void MGL_EXPORT mgl_data_fill(HMDT dat, mreal x1,mreal x2,char dir);
+void MGL_EXPORT mgl_data_fill_(uintptr_t *dat, mreal *x1,mreal *x2,const char *dir,int);
+/// Modify the data by specified formula assuming x,y,z in range [r1,r2]
+void MGL_EXPORT mgl_data_fill_eq(HMGL gr, HMDT dat, const char *eq, HCDT vdat, HCDT wdat,const char *opt);
+void MGL_EXPORT mgl_data_fill_eq_(uintptr_t *gr, uintptr_t *dat, const char *eq, uintptr_t *vdat, uintptr_t *wdat,const char *opt, int, int);
+/// Fill dat by interpolated values of vdat parametrically depended on xdat for x in range [x1,x2] using global spline
+void MGL_EXPORT mgl_data_refill_gs(HMDT dat, HCDT xdat, HCDT vdat, mreal x1, mreal x2, long sl);
+void MGL_EXPORT mgl_data_refill_gs_(uintptr_t *dat, uintptr_t *xdat, uintptr_t *vdat, mreal *x1, mreal *x2, long *sl);
+/// Fill dat by interpolated values of vdat parametrically depended on xdat for x in range [x1,x2]
+void MGL_EXPORT mgl_data_refill_x(HMDT dat, HCDT xdat, HCDT vdat, mreal x1, mreal x2, long sl);
+void MGL_EXPORT mgl_data_refill_x_(uintptr_t *dat, uintptr_t *xdat, uintptr_t *vdat, mreal *x1, mreal *x2, long *sl);
+/// Fill dat by interpolated values of vdat parametrically depended on xdat,ydat for x,y in range [x1,x2]*[y1,y2]
+void MGL_EXPORT mgl_data_refill_xy(HMDT dat, HCDT xdat, HCDT ydat, HCDT vdat, mreal x1, mreal x2, mreal y1, mreal y2, long sl);
+void MGL_EXPORT mgl_data_refill_xy_(uintptr_t *dat, uintptr_t *xdat, uintptr_t *ydat, uintptr_t *vdat, mreal *x1, mreal *x2, mreal *y1, mreal *y2, long *sl);
+/// Fill dat by interpolated values of vdat parametrically depended on xdat,ydat,zdat for x,y,z in range [x1,x2]*[y1,y2]*[z1,z2]
+void MGL_EXPORT mgl_data_refill_xyz(HMDT dat, HCDT xdat, HCDT ydat, HCDT zdat, HCDT vdat, mreal x1, mreal x2, mreal y1, mreal y2, mreal z1, mreal z2);
+void MGL_EXPORT mgl_data_refill_xyz_(uintptr_t *dat, uintptr_t *xdat, uintptr_t *ydat, uintptr_t *zdat, uintptr_t *vdat, mreal *x1, mreal *x2, mreal *y1, mreal *y2, mreal *z1, mreal *z2);
+/// Fill dat by interpolated values of vdat parametrically depended on xdat,ydat,zdat for x,y,z in axis range
+void MGL_EXPORT mgl_data_refill_gr(HMGL gr, HMDT dat, HCDT xdat, HCDT ydat, HCDT zdat, HCDT vdat, long sl, const char *opt);
+void MGL_EXPORT mgl_data_refill_gr_(uintptr_t *gr, uintptr_t *dat, uintptr_t *xdat, uintptr_t *ydat, uintptr_t *zdat, uintptr_t *vdat, long *sl, const char *opt,int);
+/// Set the data by triangulated surface values assuming x,y,z in range [r1,r2]
+void MGL_EXPORT mgl_data_grid(HMGL gr, HMDT d, HCDT xdat, HCDT ydat, HCDT zdat,const char *opt);
+void MGL_EXPORT mgl_data_grid_(uintptr_t *gr, uintptr_t *dat, uintptr_t *xdat, uintptr_t *ydat, uintptr_t *zdat, const char *opt,int);
+/// Set the data by triangulated surface values assuming x,y,z in range [x1,x2]*[y1,y2]
+void MGL_EXPORT mgl_data_grid_xy(HMDT d, HCDT xdat, HCDT ydat, HCDT zdat, mreal x1, mreal x2, mreal y1, mreal y2);
+void MGL_EXPORT mgl_data_grid_xy_(uintptr_t *dat, uintptr_t *xdat, uintptr_t *ydat, uintptr_t *zdat, mreal *x1, mreal *x2, mreal *y1, mreal *y2);
+/// Put value to data element(s)
+void MGL_EXPORT mgl_data_put_val(HMDT dat, mreal val, long i, long j, long k);
+void MGL_EXPORT mgl_data_put_val_(uintptr_t *dat, mreal *val, int *i, int *j, int *k);
+/// Put array to data element(s)
+void MGL_EXPORT mgl_data_put_dat(HMDT dat, HCDT val, long i, long j, long k);
+void MGL_EXPORT mgl_data_put_dat_(uintptr_t *dat, uintptr_t *val, int *i, int *j, int *k);
+/// Modify the data by specified formula
+void MGL_EXPORT mgl_data_modify(HMDT dat, const char *eq,long dim);
+void MGL_EXPORT mgl_data_modify_(uintptr_t *dat, const char *eq,int *dim,int);
+/// Modify the data by specified formula
+void MGL_EXPORT mgl_data_modify_vw(HMDT dat, const char *eq,HCDT vdat,HCDT wdat);
+void MGL_EXPORT mgl_data_modify_vw_(uintptr_t *dat, const char *eq, uintptr_t *vdat, uintptr_t *wdat,int);
+/// Reduce size of the data
+void MGL_EXPORT mgl_data_squeeze(HMDT dat, long rx,long ry,long rz,long smooth);
+void MGL_EXPORT mgl_data_squeeze_(uintptr_t *dat, int *rx,int *ry,int *rz,int *smooth);
+
+/// Get array which is n-th pairs {x[i],y[i]} for iterated function system (fractal) generated by A
+/** NOTE: A.nx must be >= 7. */
+HMDT MGL_EXPORT mgl_data_ifs_2d(HCDT A, long n, long skip);
+uintptr_t MGL_EXPORT mgl_data_ifs_2d_(uintptr_t *A, long *n, long *skip);
+/// Get array which is n-th points {x[i],y[i],z[i]} for iterated function system (fractal) generated by A
+/** NOTE: A.nx must be >= 13. */
+HMDT MGL_EXPORT mgl_data_ifs_3d(HCDT A, long n, long skip);
+uintptr_t MGL_EXPORT mgl_data_ifs_3d_(uintptr_t *A, long *n, long *skip);
+/// Get array which is n-th points {x[i],y[i],z[i]} for iterated function system (fractal) defined in *.ifs file 'fname' and named as 'name'
+HMDT MGL_EXPORT mgl_data_ifs_file(const char *fname, const char *name, long n, long skip);
+uintptr_t mgl_data_ifs_file_(const char *fname, const char *name, long *n, long *skip,int l,int m);
+/// Codes for flame fractal functions
+enum {
+	mglFlame2d_linear=0,	mglFlame2d_sinusoidal,	mglFlame2d_spherical,	mglFlame2d_swirl,		mglFlame2d_horseshoe,
+	mglFlame2d_polar,		mglFlame2d_handkerchief,mglFlame2d_heart,		mglFlame2d_disc,		mglFlame2d_spiral,
+	mglFlame2d_hyperbolic,	mglFlame2d_diamond,		mglFlame2d_ex,			mglFlame2d_julia,		mglFlame2d_bent,
+	mglFlame2d_waves,		mglFlame2d_fisheye,		mglFlame2d_popcorn,		mglFlame2d_exponential,	mglFlame2d_power,
+	mglFlame2d_cosine,		mglFlame2d_rings,		mglFlame2d_fan,			mglFlame2d_blob,		mglFlame2d_pdj,
+	mglFlame2d_fan2,		mglFlame2d_rings2,		mglFlame2d_eyefish,		mglFlame2d_bubble,		mglFlame2d_cylinder,
+	mglFlame2d_perspective,	mglFlame2d_noise,		mglFlame2d_juliaN,		mglFlame2d_juliaScope,	mglFlame2d_blur,
+	mglFlame2d_gaussian,	mglFlame2d_radialBlur,	mglFlame2d_pie,			mglFlame2d_ngon,		mglFlame2d_curl,
+	mglFlame2d_rectangles,	mglFlame2d_arch,		mglFlame2d_tangent,		mglFlame2d_square,		mglFlame2d_blade,
+	mglFlame2d_secant,		mglFlame2d_rays,		mglFlame2d_twintrian,	mglFlame2d_cross,		mglFlame2d_disc2,
+	mglFlame2d_supershape,	mglFlame2d_flower,		mglFlame2d_conic,		mglFlame2d_parabola,	mglFlame2d_bent2,
+	mglFlame2d_bipolar,		mglFlame2d_boarders,	mglFlame2d_butterfly,	mglFlame2d_cell,		mglFlame2d_cpow,
+	mglFlame2d_curve,		mglFlame2d_edisc,		mglFlame2d_elliptic,	mglFlame2d_escher,		mglFlame2d_foci,
+	mglFlame2d_lazySusan,	mglFlame2d_loonie,		mglFlame2d_preBlur,		mglFlame2d_modulus,		mglFlame2d_oscope,
+	mglFlame2d_polar2,		mglFlame2d_popcorn2,	mglFlame2d_scry,		mglFlame2d_separation,	mglFlame2d_split,
+	mglFlame2d_splits,		mglFlame2d_stripes,		mglFlame2d_wedge,		mglFlame2d_wedgeJulia,	mglFlame2d_wedgeSph,
+	mglFlame2d_whorl,		mglFlame2d_waves2,		mglFlame2d_exp,			mglFlame2d_log,			mglFlame2d_sin,
+	mglFlame2d_cos,			mglFlame2d_tan,			mglFlame2d_sec,			mglFlame2d_csc,			mglFlame2d_cot,
+	mglFlame2d_sinh,		mglFlame2d_cosh,		mglFlame2d_tanh,		mglFlame2d_sech,		mglFlame2d_csch,
+	mglFlame2d_coth,		mglFlame2d_auger,		mglFlame2d_flux,		mglFlame2dLAST
+};
+/// Get array which is n-th pairs {x[i],y[i]} for Flame fractal generated by A with functions F
+/** NOTE: A.nx must be >= 7 and F.nx >= 2 and F.nz=A.ny.
+ * F[0,i,j] denote function id. F[1,i,j] give function weight. F(2:5,i,j) provide function parameters.
+ * Resulting point is {xnew,ynew} = sum_i F[1,i,j]*F[0,i,j]{IFS2d(A[j]){x,y}}. */
+HMDT MGL_EXPORT mgl_data_flame_2d(HCDT A, HCDT F, long n, long skip);
+uintptr_t MGL_EXPORT mgl_data_flame_2d_(uintptr_t *A, uintptr_t *F, long *n, long *skip);
+
+/// Get curves, separated by NAN, for maximal values of array d as function of x coordinate.
+/** Noises below lvl amplitude are ignored.
+  * Parameter dy \in [0,ny] set the "attraction" distance of points to curve. */
+HMDT MGL_EXPORT mgl_data_detect(HCDT d, mreal lvl, mreal dj, mreal di, mreal min_len);
+uintptr_t MGL_EXPORT mgl_data_detect_(uintptr_t *d, mreal *lvl, mreal *dj, mreal *di, mreal *min_len);
+
+/// Get array as solution of tridiagonal matrix solution a[i]*x[i-1]+b[i]*x[i]+c[i]*x[i+1]=d[i]
+/** String \a how may contain:
+ * 'x', 'y', 'z' for solving along x-,y-,z-directions, or
+ * 'h' for solving along hexagonal direction at x-y plain (need nx=ny),
+ * 'c' for using periodical boundary conditions,
+ * 'd' for diffraction/diffuse calculation.
+ * NOTE: It work for flat data model only (i.e. for a[i,j]==a[i+nx*j]) */
+HMDT MGL_EXPORT mgl_data_tridmat(HCDT A, HCDT B, HCDT C, HCDT D, const char *how);
+uintptr_t MGL_EXPORT mgl_data_tridmat_(uintptr_t *A, uintptr_t *B, uintptr_t *C, uintptr_t *D, const char *how, int);
+
+/// Returns pointer to data element [i,j,k]
+MGL_EXPORT mreal *mgl_data_value(HMDT dat, long i,long j,long k);
+/// Returns pointer to internal data array
+MGL_EXPORT mreal *mgl_data_data(HMDT dat);
+
+/// Gets the x-size of the data.
+long MGL_EXPORT mgl_data_get_nx(HCDT d);
+long MGL_EXPORT mgl_data_get_nx_(uintptr_t *d);
+/// Gets the y-size of the data.
+long MGL_EXPORT mgl_data_get_ny(HCDT d);
+long MGL_EXPORT mgl_data_get_ny_(uintptr_t *d);
+/// Gets the z-size of the data.
+long MGL_EXPORT mgl_data_get_nz(HCDT d);
+long MGL_EXPORT mgl_data_get_nz_(uintptr_t *d);
+
+/// Get the data which is direct multiplication (like, d[i,j] = this[i]*a[j] and so on)
+HMDT MGL_EXPORT mgl_data_combine(HCDT dat1, HCDT dat2);
+uintptr_t MGL_EXPORT mgl_data_combine_(uintptr_t *dat1, uintptr_t *dat2);
+/// Extend data dimensions
+void MGL_EXPORT mgl_data_extend(HMDT dat, long n1, long n2);
+void MGL_EXPORT mgl_data_extend_(uintptr_t *dat, int *n1, int *n2);
+/// Insert data rows/columns/slices
+void MGL_EXPORT mgl_data_insert(HMDT dat, char dir, long at, long num);
+void MGL_EXPORT mgl_data_insert_(uintptr_t *dat, const char *dir, int *at, int *num, int);
+/// Delete data rows/columns/slices
+void MGL_EXPORT mgl_data_delete(HMDT dat, char dir, long at, long num);
+void MGL_EXPORT mgl_data_delete_(uintptr_t *dat, const char *dir, int *at, int *num, int);
+/// Joind another data array
+void MGL_EXPORT mgl_data_join(HMDT dat, HCDT d);
+void MGL_EXPORT mgl_data_join_(uintptr_t *dat, uintptr_t *d);
+
+/// Smooth the data on specified direction or directions
+/** String \a dir may contain:
+ *  ‘x’, ‘y’, ‘z’ for 1st, 2nd or 3d dimension;
+ *  ‘dN’ for linear averaging over N points;
+ *  ‘3’ for linear averaging over 3 points;
+ *  ‘5’ for linear averaging over 5 points.
+ *  By default quadratic averaging over 5 points is used. */
+void MGL_EXPORT mgl_data_smooth(HMDT d, const char *dirs, mreal delta);
+void MGL_EXPORT mgl_data_smooth_(uintptr_t *dat, const char *dirs, mreal *delta,int);
+/// Get array which is result of summation in given direction or directions
+HMDT MGL_EXPORT mgl_data_sum(HCDT dat, const char *dir);
+uintptr_t MGL_EXPORT mgl_data_sum_(uintptr_t *dat, const char *dir,int);
+/// Get array which is result of maximal values in given direction or directions
+HMDT MGL_EXPORT mgl_data_max_dir(HCDT dat, const char *dir);
+uintptr_t MGL_EXPORT mgl_data_max_dir_(uintptr_t *dat, const char *dir,int);
+/// Get array which is result of minimal values in given direction or directions
+HMDT MGL_EXPORT mgl_data_min_dir(HCDT dat, const char *dir);
+uintptr_t MGL_EXPORT mgl_data_min_dir_(uintptr_t *dat, const char *dir,int);
+/// Cumulative summation the data in given direction or directions
+void MGL_EXPORT mgl_data_cumsum(HMDT dat, const char *dir);
+void MGL_EXPORT mgl_data_cumsum_(uintptr_t *dat, const char *dir,int);
+/// Integrate (cumulative summation) the data in given direction or directions
+void MGL_EXPORT mgl_data_integral(HMDT dat, const char *dir);
+void MGL_EXPORT mgl_data_integral_(uintptr_t *dat, const char *dir,int);
+/// Differentiate the data in given direction or directions
+void MGL_EXPORT mgl_data_diff(HMDT dat, const char *dir);
+void MGL_EXPORT mgl_data_diff_(uintptr_t *dat, const char *dir,int);
+/// Differentiate the parametrically specified data along direction v1 with v2,v3=const (v3 can be NULL)
+void MGL_EXPORT mgl_data_diff_par(HMDT dat, HCDT v1, HCDT v2, HCDT v3);
+void MGL_EXPORT mgl_data_diff_par_(uintptr_t *dat, uintptr_t *v1, uintptr_t *v2, uintptr_t *v3);
+/// Double-differentiate (like Laplace operator) the data in given direction
+void MGL_EXPORT mgl_data_diff2(HMDT dat, const char *dir);
+void MGL_EXPORT mgl_data_diff2_(uintptr_t *dat, const char *dir,int);
+/// Swap left and right part of the data in given direction (useful for Fourier spectrum)
+void MGL_EXPORT mgl_data_swap(HMDT dat, const char *dir);
+void MGL_EXPORT mgl_data_swap_(uintptr_t *dat, const char *dir,int);
+/// Roll data along direction dir by num slices
+void MGL_EXPORT mgl_data_roll(HMDT dat, char dir, long num);
+void MGL_EXPORT mgl_data_roll_(uintptr_t *dat, const char *dir, int *num, int);
+/// Mirror the data in given direction (useful for Fourier spectrum)
+void MGL_EXPORT mgl_data_mirror(HMDT dat, const char *dir);
+void MGL_EXPORT mgl_data_mirror_(uintptr_t *dat, const char *dir,int);
+/// Sort rows (or slices) by values of specified column
+void MGL_EXPORT mgl_data_sort(HMDT dat, long idx, long idy);
+void MGL_EXPORT mgl_data_sort_(uintptr_t *dat, int *idx, int *idy);
+/// Return dilated array of 0 or 1 for data values larger val
+void MGL_EXPORT mgl_data_dilate(HMDT dat, mreal val, long step);
+void MGL_EXPORT mgl_data_dilate_(uintptr_t *dat, mreal *val, int *step);
+/// Return eroded array of 0 or 1 for data values larger val
+void MGL_EXPORT mgl_data_erode(HMDT dat, mreal val, long step);
+void MGL_EXPORT mgl_data_erode_(uintptr_t *dat, mreal *val, int *step);
+
+/// Apply Hankel transform
+void MGL_EXPORT mgl_data_hankel(HMDT dat, const char *dir);
+void MGL_EXPORT mgl_data_hankel_(uintptr_t *dat, const char *dir,int);
+/// Apply Sin-Fourier transform
+void MGL_EXPORT mgl_data_sinfft(HMDT dat, const char *dir);
+void MGL_EXPORT mgl_data_sinfft_(uintptr_t *dat, const char *dir,int);
+/// Apply Cos-Fourier transform
+void MGL_EXPORT mgl_data_cosfft(HMDT dat, const char *dir);
+void MGL_EXPORT mgl_data_cosfft_(uintptr_t *dat, const char *dir,int);
+/// Fill data by coordinates/momenta samples for Hankel ('h') or Fourier ('f') transform
+/** Parameter \a how may contain:
+ * ‘x‘,‘y‘,‘z‘ for direction (only one will be used),
+ * ‘k‘ for momenta samples,
+ * ‘h‘ for Hankel samples,
+ * ‘f‘ for Cartesian/Fourier samples (default). */
+void MGL_EXPORT mgl_data_fill_sample(HMDT dat, const char *how);
+void MGL_EXPORT mgl_data_fill_sample_(uintptr_t *dat, const char *how,int);
+/// Find correlation between 2 data arrays
+HMDT MGL_EXPORT mgl_data_correl(HCDT dat1, HCDT dat2, const char *dir);
+uintptr_t MGL_EXPORT mgl_data_correl_(uintptr_t *dat1, uintptr_t *dat2, const char *dir,int);
+/// Apply wavelet transform
+/** Parameter \a dir may contain:
+ * ‘x‘,‘y‘,‘z‘ for directions,
+ * ‘d‘ for daubechies, ‘D‘ for centered daubechies,
+ * ‘h‘ for haar, ‘H‘ for centered haar,
+ * ‘b‘ for bspline, ‘B‘ for centered bspline,
+ * ‘i‘ for applying inverse transform. */
+void MGL_EXPORT mgl_data_wavelet(HMDT dat, const char *how, int k);
+void MGL_EXPORT mgl_data_wavelet_(uintptr_t *d, const char *dir, int *k,int);
+
+/// Allocate and prepare data for Fourier transform by nthr threads
+MGL_EXPORT void *mgl_fft_alloc(long n, void **space, long nthr);
+MGL_EXPORT void *mgl_fft_alloc_thr(long n);
+/// Free data for Fourier transform
+void MGL_EXPORT mgl_fft_free(void *wt, void **ws, long nthr);
+void MGL_EXPORT mgl_fft_free_thr(void *wt);
+/// Make Fourier transform of data x of size n and step s between points
+void MGL_EXPORT mgl_fft(double *x, long s, long n, const void *wt, void *ws, int inv);
+/// Clear internal data for speeding up FFT and Hankel transforms
+void MGL_EXPORT mgl_clear_fft();
+
+/// Interpolate by cubic spline the data to given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+mreal MGL_EXPORT mgl_data_spline(HCDT dat, mreal x,mreal y,mreal z);
+mreal MGL_EXPORT mgl_data_spline_(uintptr_t *dat, mreal *x,mreal *y,mreal *z);
+/// Interpolate by cubic spline the data and return its derivatives at given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+mreal MGL_EXPORT mgl_data_spline_ext(HCDT dat, mreal x,mreal y,mreal z, mreal *dx,mreal *dy,mreal *dz);
+mreal MGL_EXPORT mgl_data_spline_ext_(uintptr_t *dat, mreal *x,mreal *y,mreal *z, mreal *dx,mreal *dy,mreal *dz);
+/// Prepare coefficients for global spline interpolation
+HMDT MGL_EXPORT mgl_gspline_init(HCDT x, HCDT v);
+uintptr_t MGL_EXPORT mgl_gspline_init_(uintptr_t *x, uintptr_t *v);
+/// Evaluate global spline (and its derivatives d1, d2 if not NULL) using prepared coefficients \a coef
+mreal MGL_EXPORT mgl_gspline(HCDT coef, mreal dx, mreal *d1, mreal *d2);
+mreal MGL_EXPORT mgl_gspline_(uintptr_t *c, mreal *dx, mreal *d1, mreal *d2);
+/// Return an approximated x-value (root) when dat(x) = val
+mreal MGL_EXPORT mgl_data_solve_1d(HCDT dat, mreal val, int spl, long i0);
+mreal MGL_EXPORT mgl_data_solve_1d_(uintptr_t *dat, mreal *val, int *spl, int *i0);
+/// Return an approximated value (root) when dat(x) = val
+HMDT MGL_EXPORT mgl_data_solve(HCDT dat, mreal val, char dir, HCDT i0, int norm);
+uintptr_t MGL_EXPORT mgl_data_solve_(uintptr_t *dat, mreal *val, const char *dir, uintptr_t *i0, int *norm,int);
+
+/// Get trace of the data array
+HMDT MGL_EXPORT mgl_data_trace(HCDT d);
+uintptr_t MGL_EXPORT mgl_data_trace_(uintptr_t *d);
+/// Resize the data to new sizes
+HMDT MGL_EXPORT mgl_data_resize(HCDT dat, long mx,long my,long mz);
+uintptr_t MGL_EXPORT mgl_data_resize_(uintptr_t *dat, int *mx,int *my,int *mz);
+/// Resize the data to new sizes of box [x1,x2]*[y1,y2]*[z1,z2]
+HMDT MGL_EXPORT mgl_data_resize_box(HCDT dat, long mx,long my,long mz,mreal x1,mreal x2,mreal y1,mreal y2,mreal z1,mreal z2);
+uintptr_t MGL_EXPORT mgl_data_resize_box_(uintptr_t *dat, int *mx,int *my,int *mz,mreal *x1,mreal *x2,mreal *y1,mreal *y2,mreal *z1,mreal *z2);
+/// Create n-th points distribution of this data values in range [v1, v2]
+HMDT MGL_EXPORT mgl_data_hist(HCDT dat, long n, mreal v1, mreal v2, long nsub);
+uintptr_t MGL_EXPORT mgl_data_hist_(uintptr_t *dat, int *n, mreal *v1, mreal *v2, int *nsub);
+/// Create n-th points distribution of this data values in range [v1, v2] with weight w
+HMDT MGL_EXPORT mgl_data_hist_w(HCDT dat, HCDT weight, long n, mreal v1, mreal v2, long nsub);
+uintptr_t MGL_EXPORT mgl_data_hist_w_(uintptr_t *dat, uintptr_t *weight, int *n, mreal *v1, mreal *v2, int *nsub);
+/// Get momentum (1D-array) of data along direction 'dir'. String looks like "x1" for median in x-direction, "x2" for width in x-dir and so on.
+HMDT MGL_EXPORT mgl_data_momentum(HCDT dat, char dir, const char *how);
+uintptr_t MGL_EXPORT mgl_data_momentum_(uintptr_t *dat, char *dir, const char *how, int,int);
+/// Get pulse properties: pulse maximum and its position, pulse duration near maximum and by half height.
+HMDT MGL_EXPORT mgl_data_pulse(HCDT dat, char dir);
+uintptr_t MGL_EXPORT mgl_data_pulse_(uintptr_t *dat, char *dir,int);
+/// Get array which values is result of interpolation this for coordinates from other arrays
+HMDT MGL_EXPORT mgl_data_evaluate(HCDT dat, HCDT idat, HCDT jdat, HCDT kdat, int norm);
+uintptr_t MGL_EXPORT mgl_data_evaluate_(uintptr_t *dat, uintptr_t *idat, uintptr_t *jdat, uintptr_t *kdat, int *norm);
+/// Set as the data envelop
+void MGL_EXPORT mgl_data_envelop(HMDT dat, char dir);
+void MGL_EXPORT mgl_data_envelop_(uintptr_t *dat, const char *dir, int);
+/// Remove phase jump
+void MGL_EXPORT mgl_data_sew(HMDT dat, const char *dirs, mreal da);
+void MGL_EXPORT mgl_data_sew_(uintptr_t *dat, const char *dirs, mreal *da, int);
+/// Crop the data
+void MGL_EXPORT mgl_data_crop(HMDT dat, long n1, long n2, char dir);
+void MGL_EXPORT mgl_data_crop_(uintptr_t *dat, int *n1, int *n2, const char *dir,int);
+/// Crop the data to be most optimal for FFT (i.e. to closest value of 2^n*3^m*5^l)
+void MGL_EXPORT mgl_data_crop_opt(HMDT dat, const char *how);
+void MGL_EXPORT mgl_data_crop_opt_(uintptr_t *dat, const char *how,int);
+/// Remove rows with duplicate values in column id
+void MGL_EXPORT mgl_data_clean(HMDT dat, long id);
+void MGL_EXPORT mgl_data_clean_(uintptr_t *dat, int *id);
+
+/// Multiply the data by other one for each element
+void MGL_EXPORT mgl_data_mul_dat(HMDT dat, HCDT d);
+void MGL_EXPORT mgl_data_mul_dat_(uintptr_t *dat, uintptr_t *d);
+/// Divide the data by other one for each element
+void MGL_EXPORT mgl_data_div_dat(HMDT dat, HCDT d);
+void MGL_EXPORT mgl_data_div_dat_(uintptr_t *dat, uintptr_t *d);
+/// Add the other data
+void MGL_EXPORT mgl_data_add_dat(HMDT dat, HCDT d);
+void MGL_EXPORT mgl_data_add_dat_(uintptr_t *dat, uintptr_t *d);
+/// Subtract the other data
+void MGL_EXPORT mgl_data_sub_dat(HMDT dat, HCDT d);
+void MGL_EXPORT mgl_data_sub_dat_(uintptr_t *dat, uintptr_t *d);
+/// Multiply each element by the number
+void MGL_EXPORT mgl_data_mul_num(HMDT dat, mreal d);
+void MGL_EXPORT mgl_data_mul_num_(uintptr_t *dat, mreal *d);
+/// Divide each element by the number
+void MGL_EXPORT mgl_data_div_num(HMDT dat, mreal d);
+void MGL_EXPORT mgl_data_div_num_(uintptr_t *dat, mreal *d);
+/// Add the number
+void MGL_EXPORT mgl_data_add_num(HMDT dat, mreal d);
+void MGL_EXPORT mgl_data_add_num_(uintptr_t *dat, mreal *d);
+/// Subtract the number
+void MGL_EXPORT mgl_data_sub_num(HMDT dat, mreal d);
+void MGL_EXPORT mgl_data_sub_num_(uintptr_t *dat, mreal *d);
+
+/// Integral data transformation (like Fourier 'f' or 'i', Hankel 'h' or None 'n') for amplitude and phase
+HMDT MGL_EXPORT mgl_transform_a(HCDT am, HCDT ph, const char *tr);
+uintptr_t MGL_EXPORT mgl_transform_a_(uintptr_t *am, uintptr_t *ph, const char *tr, int);
+/// Integral data transformation (like Fourier 'f' or 'i', Hankel 'h' or None 'n') for real and imaginary parts
+HMDT MGL_EXPORT mgl_transform(HCDT re, HCDT im, const char *tr);
+uintptr_t MGL_EXPORT mgl_transform_(uintptr_t *re, uintptr_t *im, const char *tr, int);
+/// Apply Fourier transform for the data and save result into it
+void MGL_EXPORT mgl_data_fourier(HMDT re, HMDT im, const char *dir);
+void MGL_EXPORT mgl_data_fourier_(uintptr_t *re, uintptr_t *im, const char *dir, int l);
+/// Short time Fourier analysis for real and imaginary parts. Output is amplitude of partial Fourier (result will have size {dn, floor(nx/dn), ny} for dir='x'
+HMDT MGL_EXPORT mgl_data_stfa(HCDT re, HCDT im, long dn, char dir);
+uintptr_t MGL_EXPORT mgl_data_stfa_(uintptr_t *re, uintptr_t *im, int *dn, char *dir, int);
+
+/// Do something like Delone triangulation for 3d points
+HMDT MGL_EXPORT mgl_triangulation_3d(HCDT x, HCDT y, HCDT z);
+uintptr_t MGL_EXPORT mgl_triangulation_3d_(uintptr_t *x, uintptr_t *y, uintptr_t *z);
+/// Do Delone triangulation for 2d points
+HMDT MGL_EXPORT mgl_triangulation_2d(HCDT x, HCDT y);
+uintptr_t MGL_EXPORT mgl_triangulation_2d_(uintptr_t *x, uintptr_t *y);
+
+/// Find root for nonlinear equation
+mreal MGL_EXPORT mgl_find_root(mreal (*func)(mreal val, void *par), mreal ini, void *par);
+/// Find root for nonlinear equation defined by textual formula
+mreal MGL_EXPORT mgl_find_root_txt(const char *func, mreal ini, char var_id);
+mreal MGL_EXPORT mgl_find_root_txt_(const char *func, mreal *ini, const char *var_id,int,int);
+/// Find roots for nonlinear equation defined by textual formula
+HMDT MGL_EXPORT mgl_data_roots(const char *func, HCDT ini, char var_id);
+uintptr_t MGL_EXPORT mgl_data_roots_(const char *func, uintptr_t *ini, const char *var_id,int,int);
+
+//-----------------------------------------------------------------------------
+/// Create HMEX object for expression evaluating
+HMEX MGL_EXPORT mgl_create_expr(const char *expr);
+uintptr_t MGL_EXPORT mgl_create_expr_(const char *expr, int);
+/// Delete HMEX object
+void MGL_EXPORT mgl_delete_expr(HMEX ex);
+void MGL_EXPORT mgl_delete_expr_(uintptr_t *ex);
+/// Return value of expression for given x,y,z variables
+double MGL_EXPORT mgl_expr_eval(HMEX ex, double x, double y,double z);
+double MGL_EXPORT mgl_expr_eval_(uintptr_t *ex, mreal *x, mreal *y, mreal *z);
+/// Return value of expression for given variables
+double MGL_EXPORT mgl_expr_eval_v(HMEX ex, mreal *vars);
+/// Return value of expression differentiation over variable dir for given x,y,z variables
+double MGL_EXPORT mgl_expr_diff(HMEX ex, char dir, double x, double y,double z);
+double MGL_EXPORT mgl_expr_diff_(uintptr_t *ex, const char *dir, mreal *x, mreal *y, mreal *z, int);
+/// Return value of expression differentiation over variable dir for given variables
+double MGL_EXPORT mgl_expr_diff_v(HMEX ex, char dir, mreal *vars);
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+}
+#endif
+#endif
+//-----------------------------------------------------------------------------
diff --git a/include/mgl2/datac.h b/include/mgl2/datac.h
new file mode 100644
index 0000000..5e8f4a8
--- /dev/null
+++ b/include/mgl2/datac.h
@@ -0,0 +1,584 @@
+/***************************************************************************
+ * datac.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_DATAC_H_
+#define _MGL_DATAC_H_
+
+#include "mgl2/data.h"
+#include "mgl2/datac_cf.h"
+//-----------------------------------------------------------------------------
+#include <vector>
+#include <string>
+//-----------------------------------------------------------------------------
+#ifndef SWIG
+dual MGL_EXPORT mglLinearC(const dual *a, long nx, long ny, long nz, mreal x, mreal y, mreal z);
+dual MGL_EXPORT mglSpline3C(const dual *a, long nx, long ny, long nz, mreal x, mreal y, mreal z,dual *dx=0, dual *dy=0, dual *dz=0);
+dual MGL_EXPORT mglSpline3Cs(const dual *a, long nx, long ny, long nz, mreal x, mreal y, mreal z);
+//-----------------------------------------------------------------------------
+/// Class for working with complex data array
+class MGL_EXPORT mglDataC : public mglDataA
+{
+public:
+using mglDataA::Momentum;
+	long nx;		///< number of points in 1st dimensions ('x' dimension)
+	long ny;		///< number of points in 2nd dimensions ('y' dimension)
+	long nz;		///< number of points in 3d dimensions ('z' dimension)
+	dual *a;		///< data array
+	std::string id;	///< column (or slice) names
+	bool link;		///< use external data (i.e. don't free it)
+
+	/// Initiate by other mglDataC variable
+	mglDataC(const mglDataC &d)	{	a=0;	mgl_datac_set(this,&d);		}	// NOTE: must be constructor for mglDataC& to exclude copy one
+	mglDataC(const mglDataA &d)	{	a=0;	mgl_datac_set(this,&d);		}
+#if MGL_HAVE_RVAL
+	mglDataC(mglDataC &&d):nx(d.nx),ny(d.ny),nz(d.nz),a(d.a),id(d.id),link(d.link)
+	{	s=d.s;	temp=d.temp;	func=d.func;	o=d.o;	d.a=0;	d.func=0;	}
+#endif
+	mglDataC(const mglDataA &re, const mglDataA &im)	{	a=0;	mgl_datac_set_ri(this,&re,&im);	}
+	mglDataC(HCDT d)	{	a=0;	mgl_datac_set(this, d);		}
+	mglDataC(HCDT re, HCDT im)	{	a=0;	mgl_datac_set_ri(this, re, im);		}
+	mglDataC(bool, mglDataC *d)	// NOTE: Variable d will be deleted!!!
+	{	if(d)
+		{	nx=d->nx;	ny=d->ny;	nz=d->nz;	a=d->a;	d->a=0;
+			temp=d->temp;	func=d->func;	o=d->o;	s=d->s;
+			id=d->id;	link=d->link;	delete d;	}
+		else	{	a=0;	Create(1);	}	}
+	/// Initiate by flat array
+	mglDataC(int size, const dual *d)	{	a=0;	Set(d,size);	}
+	mglDataC(int rows, int cols, const dual *d)	{	a=0;	Set(d,cols,rows);	}
+	mglDataC(int size, const double *d)	{	a=0;	Set(d,size);	}
+	mglDataC(int rows, int cols, const double *d)	{	a=0;	Set(d,cols,rows);	}
+	mglDataC(int size, const float *d)	{	a=0;	Set(d,size);	}
+	mglDataC(int rows, int cols, const float *d)	{	a=0;	Set(d,cols,rows);	}
+	mglDataC(const dual *d, int size)	{	a=0;	Set(d,size);	}
+	mglDataC(const dual *d, int rows, int cols)	{	a=0;	Set(d,cols,rows);	}
+	mglDataC(const double *d, int size)	{	a=0;	Set(d,size);	}
+	mglDataC(const double *d, int rows, int cols)	{	a=0;	Set(d,cols,rows);	}
+	mglDataC(const float *d, int size)	{	a=0;	Set(d,size);	}
+	mglDataC(const float *d, int rows, int cols)	{	a=0;	Set(d,cols,rows);	}
+	/// Allocate memory and copy data from std::vector<T>
+	mglDataC(const std::vector<int> &d)		{	a=0;	Set(d);	}
+	mglDataC(const std::vector<float> &d)	{	a=0;	Set(d);	}
+	mglDataC(const std::vector<double> &d)	{	a=0;	Set(d);	}
+	mglDataC(const std::vector<std::complex<double> > &d)	{	a=0;	Set(d);	}
+	mglDataC(const std::vector<std::complex<float> > &d)	{	a=0;	Set(d);	}
+	/// Read data from file
+	mglDataC(const char *fname)			{	a=0;	Read(fname);	}
+	/// Allocate the memory for data array and initialize it zero
+	mglDataC(long xx=1,long yy=1,long zz=1)	{	a=0;	Create(xx,yy,zz);	}
+	/// Delete the array
+	virtual ~mglDataC()	{	if(!link && a)	delete []a;	}
+
+	/// Move all data from variable d, and delete this variable.
+	inline void Move(mglDataC *d)	// NOTE: Variable d will be deleted!!!
+	{	if(d && d->GetNN()>1)
+		{	bool l=link;	dual *b=a;
+			nx=d->nx;	ny=d->ny;	nz=d->nz;	a=d->a;	d->a=b;
+			temp=d->temp;	func=d->func;	o=d->o;	s=d->s;
+			id=d->id;	link=d->link;	d->link=l;	delete d;	}
+		else if(d)	{	*this = d->a[0];	delete d;	}
+	}
+
+	inline dual GetVal(long i, long j=0, long k=0) const
+	{	return mgl_datac_get_value(this,i,j,k);}
+	inline void SetVal(dual f, long i, long j=0, long k=0)
+	{	mgl_datac_set_value(this,f,i,j,k);	}
+	/// Get sizes
+	long GetNx() const	{	return nx;	}
+	long GetNy() const	{	return ny;	}
+	long GetNz() const	{	return nz;	}
+
+	/// Link external data array (don't delete it at exit)
+	inline void Link(dual *A, long NX, long NY=1, long NZ=1)
+	{	mgl_datac_link(this,A,NX,NY,NZ);	}
+	inline void Link(mglDataC &d)	{	Link(d.a,d.nx,d.ny,d.nz);	}
+	/// Allocate memory and copy the data from the gsl_vector
+	inline void Set(gsl_vector *m)	{	mgl_datac_set_vector(this,m);	}
+	/// Allocate memory and copy the data from the gsl_matrix
+	inline void Set(gsl_matrix *m)	{	mgl_datac_set_matrix(this,m);	}
+
+	/// Allocate memory and copy the data from the (float *) array
+	inline void Set(const float *A,long NX,long NY=1,long NZ=1)
+	{	mgl_datac_set_float(this,A,NX,NY,NZ);	}
+	/// Allocate memory and copy the data from the (double *) array
+	inline void Set(const double *A,long NX,long NY=1,long NZ=1)
+	{	mgl_datac_set_double(this,A,NX,NY,NZ);	}
+	/// Allocate memory and copy the data from the (complex *) array
+	inline void Set(const dual *A,long NX,long NY=1,long NZ=1)
+	{	mgl_datac_set_complex(this,A,NX,NY,NZ);	}
+	/// Allocate memory and scanf the data from the string
+	inline void Set(const char *str,long NX,long NY=1,long NZ=1)
+	{	mgl_datac_set_values(this,str,NX,NY,NZ);	}
+	/// Import data from abstract type
+	inline void Set(HCDT dat)	{	mgl_datac_set(this, dat);	}
+	inline void Set(const mglDataA &dat)	{	mgl_datac_set(this, &dat);	}
+	inline void Set(const mglDataA &re, const mglDataA &im)	{	mgl_datac_set_ri(this, &re, &im);	}
+	inline void Set(HCDT re, HCDT im)	{	mgl_datac_set_ri(this, re, im);	}
+	inline void SetAmpl(const mglDataA &ampl, const mglDataA &phase)
+	{	mgl_datac_set_ap(this, &ampl, &phase);	}
+	/// Allocate memory and copy data from std::vector<T>
+	inline void Set(const std::vector<int> &d)
+	{	if(d.size()>0)	{	Create(d.size());	for(long i=0;i<nx;i++)	a[i] = d[i];	}
+		else	Create(1);	}
+	inline void Set(const std::vector<float> &d)
+	{	if(d.size()>0)	Set(&(a[0]),d.size());	else	Create(1);	}
+	inline void Set(const std::vector<double> &d)
+	{	if(d.size()>0)	Set(&(a[0]),d.size());	else	Create(1);	}
+	inline void Set(const std::vector<std::complex<double> > &d)
+	{	if(d.size()>0)	{	Create(d.size());	for(long i=0;i<nx;i++)	a[i] = d[i];	}
+		else	Create(1);	}
+	inline void Set(const std::vector<std::complex<float> > &d)
+	{	if(d.size()>0)	{	Create(d.size());	for(long i=0;i<nx;i++)	a[i] = d[i];	}
+		else	Create(1);	}
+
+	/// Create or recreate the array with specified size and fill it by zero
+	inline void Create(long mx,long my=1,long mz=1)
+	{	mgl_datac_create(this,mx,my,mz);	}
+	/// Rearange data dimensions
+	inline void Rearrange(long mx, long my=0, long mz=0)
+	{	mgl_datac_rearrange(this,mx,my,mz);	}
+	/// Transpose dimensions of the data (generalization of Transpose)
+	inline void Transpose(const char *dim="yx")
+	{	mgl_datac_transpose(this,dim);	}
+	/// Extend data dimensions
+	inline void Extend(long n1, long n2=0)
+	{	mgl_datac_extend(this,n1,n2);	}
+	/// Reduce size of the data
+	inline void Squeeze(long rx,long ry=1,long rz=1,bool smooth=false)
+	{	mgl_datac_squeeze(this,rx,ry,rz,smooth);	}
+	/// Crop the data
+	inline void Crop(long n1, long n2,char dir='x')
+	{	mgl_datac_crop(this,n1,n2,dir);	}
+	/// Crop the data to be most optimal for FFT (i.e. to closest value of 2^n*3^m*5^l)
+	inline void Crop(const char *how="235x")
+	{	mgl_datac_crop_opt(this, how);	}
+	/// Insert data
+	inline void Insert(char dir, long at=0, long num=1)
+	{	mgl_datac_insert(this,dir,at,num);	}
+	/// Delete data
+	inline void Delete(char dir, long at=0, long num=1)
+	{	mgl_datac_delete(this,dir,at,num);	}
+	/// Join with another data array
+	inline void Join(const mglDataA &d)
+	{	mgl_datac_join(this,&d);	}
+
+	/// Modify the data by specified formula
+	inline void Modify(const char *eq,long dim=0)
+	{	mgl_datac_modify(this, eq, dim);	}
+	/// Modify the data by specified formula
+	inline void Modify(const char *eq,const mglDataA &vdat, const mglDataA &wdat)
+	{	mgl_datac_modify_vw(this,eq,&vdat,&wdat);	}
+	/// Modify the data by specified formula
+	inline void Modify(const char *eq,const mglDataA &vdat)
+	{	mgl_datac_modify_vw(this,eq,&vdat,0);	}
+	/// Modify the data by specified formula assuming x,y,z in range [r1,r2]
+	inline void Fill(mglBase *gr, const char *eq, const char *opt="")
+	{	mgl_datac_fill_eq(gr,this,eq,0,0,opt);	}
+	inline void Fill(mglBase *gr, const char *eq, const mglDataA &vdat, const char *opt="")
+	{	mgl_datac_fill_eq(gr,this,eq,&vdat,0,opt);	}
+	inline void Fill(mglBase *gr, const char *eq, const mglDataA &vdat, const mglDataA &wdat,const char *opt="")
+	{	mgl_datac_fill_eq(gr,this,eq,&vdat,&wdat,opt);	}
+	/// Equidistantly fill the data to range [x1,x2] in direction dir
+	inline void Fill(dual x1,dual x2=mglNaN,char dir='x')
+	{	mgl_datac_fill(this,x1,x2,dir);	}
+
+		/// Fill the data by interpolated values of vdat parametrically depended on xdat,ydat,zdat for x,y,z in range [p1,p2] using global spline
+	inline void RefillGS(const mglDataA &xdat, const mglDataA &vdat, mreal x1, mreal x2,long sl=-1)
+	{	mgl_datac_refill_gs(this,&xdat,&vdat,x1,x2,sl);	}
+	/// Fill the data by interpolated values of vdat parametrically depended on xdat,ydat,zdat for x,y,z in range [p1,p2]
+	inline void Refill(const mglDataA &xdat, const mglDataA &vdat, mreal x1, mreal x2,long sl=-1)
+	{	mgl_datac_refill_x(this,&xdat,&vdat,x1,x2,sl);	}
+	inline void Refill(const mglDataA &xdat, const mglDataA &vdat, mglPoint p1, mglPoint p2,long sl=-1)
+	{	mgl_datac_refill_x(this,&xdat,&vdat,p1.x,p2.x,sl);	}
+	inline void Refill(const mglDataA &xdat, const mglDataA &ydat, const mglDataA &vdat, mglPoint p1, mglPoint p2,long sl=-1)
+	{	mgl_datac_refill_xy(this,&xdat,&ydat,&vdat,p1.x,p2.x,p1.y,p2.y,sl);	}
+	inline void Refill(const mglDataA &xdat, const mglDataA &ydat, const mglDataA &zdat, const mglDataA &vdat, mglPoint p1, mglPoint p2)
+	{	mgl_datac_refill_xyz(this,&xdat,&ydat,&zdat,&vdat,p1.x,p2.x,p1.y,p2.y,p1.z,p2.z);	}
+	/// Fill the data by interpolated values of vdat parametrically depended on xdat,ydat,zdat for x,y,z in axis range of gr
+	inline void Refill(HMGL gr, const mglDataA &xdat, const mglDataA &vdat, long sl=-1, const char *opt="")
+	{	mgl_datac_refill_gr(gr,this,&xdat,0,0,&vdat,sl,opt);	}
+	inline void Refill(HMGL gr, const mglDataA &xdat, const mglDataA &ydat, const mglDataA &vdat, long sl=-1, const char *opt="")
+	{	mgl_datac_refill_gr(gr,this,&xdat,&ydat,0,&vdat,sl,opt);	}
+	inline void Refill(HMGL gr, const mglDataA &xdat, const mglDataA &ydat, const mglDataA &zdat, const mglDataA &vdat, const char *opt="")
+	{	mgl_datac_refill_gr(gr,this,&xdat,&ydat,&zdat,&vdat,-1,opt);	}
+
+
+		/// Put value to data element(s)
+	inline void Put(dual val, long i=-1, long j=-1, long k=-1)
+	{	mgl_datac_put_val(this,val,i,j,k);	}
+	/// Put array to data element(s)
+	inline void Put(const mglDataA &dat, long i=-1, long j=-1, long k=-1)
+	{	mgl_datac_put_dat(this,&dat,i,j,k);	}
+
+	/// Set names for columns (slices)
+	inline void SetColumnId(const char *ids)
+	{	mgl_datac_set_id(this,ids);	}
+	/// Make new id
+	inline void NewId()	{	id.clear();	}
+
+	/// Read data from tab-separated text file with auto determining size
+	inline bool Read(const char *fname)
+	{	return mgl_datac_read(this,fname); }
+	/// Read data from text file with specifeid size
+	inline bool Read(const char *fname,long mx,long my=1,long mz=1)
+	{	return mgl_datac_read_dim(this,fname,mx,my,mz);	}
+	/// Save whole data array (for ns=-1) or only ns-th slice to text file
+	void Save(const char *fname,long ns=-1) const
+	{	mgl_datac_save(this,fname,ns);	}
+	/// Get whole data array (for ns=-1) or only ns-th slice to string
+	std::string Get(long ns=-1) const
+	{	return mgl_datac_to_string(this,ns);	}
+
+	/// Read data from tab-separated text files with auto determining size which filenames are result of sprintf(fname,templ,t) where t=from:step:to
+	inline bool ReadRange(const char *templ, double from, double to, double step=1, bool as_slice=false)
+	{	return mgl_datac_read_range(this,templ,from,to,step,as_slice);	}
+	/// Read data from tab-separated text files with auto determining size which filenames are satisfied to template (like "t_*.dat")
+	inline bool ReadAll(const char *templ, bool as_slice=false)
+	{	return mgl_datac_read_all(this, templ, as_slice);	}
+	/// Read data from text file with size specified at beginning of the file
+	inline bool ReadMat(const char *fname, long dim=2)
+	{	return mgl_datac_read_mat(this,fname,dim);	}
+
+		/// Read data array from HDF file (parse HDF4 and HDF5 files)
+	inline int ReadHDF(const char *fname,const char *data)
+	{	return mgl_datac_read_hdf(this,fname,data);	}
+	/// Save data to HDF file
+	void SaveHDF(const char *fname,const char *data,bool rewrite=false) const
+	{	mgl_datac_save_hdf(this,fname,data,rewrite);	}
+
+	/// Get real part of data values
+	inline mglData Real() const
+	{	return mglData(true,mgl_datac_real(this));	}
+	/// Get imaginary part of data values
+	inline mglData Imag() const
+	{	return mglData(true,mgl_datac_imag(this));	}
+	/// Get absolute value of data values, i.e. |u|
+	inline mglData Abs() const
+	{	return mglData(true,mgl_datac_abs(this));	}
+	/// Get square of absolute value of data values, i.e. |u|^2
+	inline mglData Norm() const
+	{	return mglData(true,mgl_datac_norm(this));	}
+	/// Get argument of data values
+	inline mglData Arg() const
+	{	return mglData(true,mgl_datac_arg(this));	}
+
+	/// Get column (or slice) of the data filled by formulas of named columns
+	inline mglDataC Column(const char *eq) const
+	{	return mglDataC(true,mgl_datac_column(this,eq));	}
+	/// Get momentum (1D-array) of data along direction 'dir'. String looks like "x1" for median in x-direction, "x2" for width in x-dir and so on.
+	inline mglDataC Momentum(char dir, const char *how) const
+	{	return mglDataC(true,mgl_datac_momentum(this,dir,how));	}
+	/// Get sub-array of the data with given fixed indexes
+	inline mglDataC SubData(long xx,long yy=-1,long zz=-1) const
+	{	return mglDataC(true,mgl_datac_subdata(this,xx,yy,zz));	}
+	inline mglDataC SubData(const mglDataA &xx, const mglDataA &yy, const mglDataA &zz) const
+	{	return mglDataC(true,mgl_datac_subdata_ext(this,&xx,&yy,&zz));	}
+	inline mglDataC SubData(const mglDataA &xx, const mglDataA &yy) const
+	{	return mglDataC(true,mgl_datac_subdata_ext(this,&xx,&yy,0));	}
+	inline mglDataC SubData(const mglDataA &xx) const
+	{	return mglDataC(true,mgl_datac_subdata_ext(this,&xx,0,0));	}
+	/// Get data from sections ids, separated by value val along specified direction.
+	/** If section id is negative then reverse order is used (i.e. -1 give last section). */
+	inline mglDataC Section(const mglDataA &ids, char dir='y', mreal val=NAN) const
+	{	return mglDataC(true,mgl_datac_section(this,&ids,dir,val));	}
+	inline mglDataC Section(long id, char dir='y', mreal val=NAN) const
+	{	return mglDataC(true,mgl_datac_section_val(this,id,dir,val));	}
+
+	/// Get trace of the data array
+	inline mglDataC Trace() const
+	{	return mglDataC(true,mgl_datac_trace(this));	}
+	/// Get array which is result of summation in given direction or directions
+	inline mglDataC Sum(const char *dir) const
+	{	return mglDataC(true,mgl_datac_sum(this,dir));	}
+	/// Get the data which is direct multiplication (like, d[i,j] = this[i]*a[j] and so on)
+	inline mglDataC Combine(const mglDataA &dat) const
+	{	return mglDataC(true,mgl_datac_combine(this,&dat));	}
+	/// Resize the data to new size of box [x1,x2]*[y1,y2]*[z1,z2]
+	inline mglDataC Resize(long mx,long my=1,long mz=1, mreal x1=0,mreal x2=1, mreal y1=0,mreal y2=1, mreal z1=0,mreal z2=1) const
+	{	return mglDataC(true,mgl_datac_resize_box(this,mx,my,mz,x1,x2,y1,y2,z1,z2));	}
+	/// Get array which values is result of interpolation this for coordinates from other arrays
+	inline mglDataC Evaluate(const mglData &idat, bool norm=true) const
+	{	return mglDataC(true,mgl_datac_evaluate(this,&idat,0,0,norm));	}
+	inline mglDataC Evaluate(const mglData &idat, const mglData &jdat, bool norm=true) const
+	{	return mglDataC(true,mgl_datac_evaluate(this,&idat,&jdat,0,norm));	}
+	inline mglDataC Evaluate(const mglData &idat, const mglData &jdat, const mglData &kdat, bool norm=true) const
+	{	return mglDataC(true,mgl_datac_evaluate(this,&idat,&jdat,&kdat,norm));	}
+
+	/// Find correlation with another data arrays
+	inline mglDataC Correl(const mglData &dat, const char *dir) const
+	{	return mglDataC(true,mgl_datac_correl(this,&dat,dir));	}
+	/// Find auto correlation function
+	inline mglDataC AutoCorrel(const char *dir) const
+	{	return mglDataC(true,mgl_datac_correl(this,this,dir));	}
+
+	/// Create n-th points distribution of this data values in range [v1, v2]
+	inline mglData Hist(long n,mreal v1=0,mreal v2=1, long nsub=0) const
+	{	return mglData(true,mgl_data_hist(this,n,v1,v2,nsub));	}
+	/// Create n-th points distribution of this data values in range [v1, v2] with weight w
+	inline mglData Hist(const mglDataA &w, long n,mreal v1=0,mreal v2=1, long nsub=0) const
+	{	return mglData(true,mgl_data_hist_w(this,&w,n,v1,v2,nsub));	}
+	/// Get array which is result of maximal values in given direction or directions
+	inline mglData Max(const char *dir) const
+	{	return mglData(true,mgl_data_max_dir(this,dir));	}
+	/// Get array which is result of minimal values in given direction or directions
+	inline mglData Min(const char *dir) const
+	{	return mglData(true,mgl_data_min_dir(this,dir));	}
+
+	/// Cumulative summation the data in given direction or directions
+	inline void CumSum(const char *dir)	{	mgl_datac_cumsum(this,dir);	}
+	/// Integrate (cumulative summation) the data in given direction or directions
+	inline void Integral(const char *dir)	{	mgl_datac_integral(this,dir);	}
+	/// Differentiate the data in given direction or directions
+	inline void Diff(const char *dir)	{	mgl_datac_diff(this,dir);	}
+	/// Differentiate the parametrically specified data along direction v1
+	inline void Diff(const mglDataA &v1)
+	{	mgl_datac_diff_par(this,&v1,0,0);	}
+	/// Differentiate the parametrically specified data along direction v1 with v2=const
+	inline void Diff(const mglDataA &v1, const mglDataA &v2)
+	{	mgl_datac_diff_par(this,&v1,&v2,0);	}
+	/// Differentiate the parametrically specified data along direction v1 with v2,v3=const
+	inline void Diff(const mglDataA &v1, const mglDataA &v2, const mglDataA &v3)
+	{	mgl_datac_diff_par(this,&v1,&v2,&v3);	}
+	/// Double-differentiate (like laplace operator) the data in given direction
+	inline void Diff2(const char *dir)	{	mgl_datac_diff2(this,dir);	}
+
+	/// Swap left and right part of the data in given direction (useful for fourier spectrums)
+	inline void Swap(const char *dir)		{	mgl_datac_swap(this,dir);	}
+	/// Roll data along direction dir by num slices
+	inline void Roll(char dir, long num)	{	mgl_datac_roll(this,dir,num);	}
+	/// Mirror the data in given direction (useful for fourier spectrums)
+	inline void Mirror(const char *dir)		{	mgl_datac_mirror(this,dir);	}
+	/// Smooth the data on specified direction or directions
+	/** String \a dir may contain:
+	 *  ‘x’, ‘y’, ‘z’ for 1st, 2nd or 3d dimension;
+	 *  ‘dN’ for linear averaging over N points;
+	 *  ‘3’ for linear averaging over 3 points;
+	 *  ‘5’ for linear averaging over 5 points.
+	 *  By default quadratic averaging over 5 points is used. */
+	inline void Smooth(const char *dirs="xyz",mreal delta=0)
+	{	mgl_datac_smooth(this,dirs,delta);	}
+	/// Limit the data to be inside [-v,v], keeping the original sign
+	inline void Limit(mreal v)
+	{	mgl_datac_limit(this, v);	}
+
+	/// Set as the data envelop
+	inline void Envelop(char dir='x')	{	mgl_datac_envelop(this,dir);	}
+	/// Hankel transform
+	inline void Hankel(const char *dir)	{	mgl_datac_hankel(this,dir);	}
+	/// Apply Sin-Fourier transform
+	inline void SinFFT(const char *dir)	{	mgl_datac_sinfft(this,dir);	}
+	/// Apply Cos-Fourier transform
+	inline void CosFFT(const char *dir)	{	mgl_datac_cosfft(this,dir);	}
+	/// Fourier transform
+	inline void FFT(const char *dir)	{	mgl_datac_fft(this,dir);	}
+	/// Calculate one step of diffraction by finite-difference method with parameter q
+	inline void Diffraction(const char *how, mreal q)	{	mgl_datac_diffr(this,how,q);	}
+	/// Apply wavelet transform
+	/** Parameter \a dir may contain:
+	 * ‘x‘,‘y‘,‘z‘ for directions,
+	 * ‘d‘ for daubechies, ‘D‘ for centered daubechies,
+	 * ‘h‘ for haar, ‘H‘ for centered haar,
+	 * ‘b‘ for bspline, ‘B‘ for centered bspline,
+	 * ‘i‘ for applying inverse transform. */
+	inline void Wavelet(const char *how, int k)	{	mgl_datac_wavelet(this, how, k);	}
+
+	/// Interpolate by cubic spline the data to given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+	inline dual Spline(mreal x,mreal y=0,mreal z=0) const
+	{	return mgl_datac_spline(this, x,y,z);	}
+	/// Interpolate by cubic spline the data to given point x,\a y,\a z which normalized in range [0, 1]
+	inline dual Spline1(mreal x,mreal y=0,mreal z=0) const
+	{	return mgl_datac_spline(this, x*(nx-1),y*(ny-1),z*(nz-1));	}
+	/// Interpolate by linear function the data to given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+	inline dual Linear(mreal x,mreal y=0,mreal z=0)	const
+	{	return mgl_datac_linear_ext(this,x,y,z,0,0,0);	}
+	/// Interpolate by line the data to given point x,\a y,\a z which normalized in range [0, 1]
+	inline dual Linear1(mreal x,mreal y=0,mreal z=0) const
+	{	return mgl_datac_linear_ext(this,x*(nx-1),y*(ny-1),z*(nz-1),0,0,0);	}
+	/// Interpolate by linear function the data and return its derivatives at given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+	inline dual Linear(mglPoint &dif, mreal x,mreal y=0,mreal z=0)	const
+	{
+		dual val,dx,dy,dz;
+		val = mgl_datac_linear_ext(this,x,y,z, &dx, &dy, &dz);
+		dif.Set(dx.real(),dy.real(),dz.real());	return val;
+	}
+	/// Interpolate by line the data and return its derivatives at given point x,\a y,\a z which normalized in range [0, 1]
+	inline dual Linear1(mglPoint &dif, mreal x,mreal y=0,mreal z=0) const
+	{
+		dual val,dx,dy,dz;
+		val = mgl_datac_linear_ext(this,x,y,z, &dx, &dy, &dz);
+		dif.Set(dx.real(),dy.real(),dz.real());
+		dif.x/=nx>1?nx-1:1;	dif.y/=ny>1?ny-1:1;	dif.z/=nz>1?nz-1:1;
+		return val;
+	}
+	/// Return an approximated x-value (root) when dat(x) = val
+	inline mreal Solve(mreal val, bool use_spline=true, long i0=0) const
+	{	return mgl_data_solve_1d(this, val, use_spline, i0);		}
+	/// Return an approximated value (root) when dat(x) = val
+	inline mglData Solve(mreal val, char dir, bool norm=true) const
+	{	return mglData(true,mgl_data_solve(this, val, dir, 0, norm));	}
+	inline mglData Solve(mreal val, char dir, const mglData &i0, bool norm=true) const
+	{	return mglData(true,mgl_data_solve(this, val, dir, &i0, norm));	}
+
+	/// Copy data from other mglDataA variable
+	inline const mglDataA &operator=(const mglDataA &d)
+	{	if(this!=&d)	Set(&d);	return d;	}
+	inline const mglDataC &operator=(const mglDataC &d)
+	{	if(this!=&d)	Set(&d);	return d;	}
+	inline dual operator=(dual val)
+	{
+#pragma omp parallel for
+		for(long i=0;i<nx*ny*nz;i++)	a[i]=val;	return val;	}
+	inline dual operator=(mreal val)
+	{
+#pragma omp parallel for
+		for(long i=0;i<nx*ny*nz;i++)	a[i]=val;	return val;	}
+	/// Multiply the data by other one for each element
+	inline void operator*=(const mglDataA &d)	{	mgl_datac_mul_dat(this,&d);	}
+	/// Divide the data by other one for each element
+	inline void operator/=(const mglDataA &d)	{	mgl_datac_div_dat(this,&d);	}
+	/// Add the other data
+	inline void operator+=(const mglDataA &d)	{	mgl_datac_add_dat(this,&d);	}
+	/// Subtract the other data
+	inline void operator-=(const mglDataA &d)	{	mgl_datac_sub_dat(this,&d);	}
+	/// Multiply each element by the number
+	inline void operator*=(dual d)		{	mgl_datac_mul_num(this,d);	}
+	/// Divide each element by the number
+	inline void operator/=(dual d)		{	mgl_datac_div_num(this,d);	}
+	/// Add the number
+	inline void operator+=(dual d)		{	mgl_datac_add_num(this,d);	}
+	/// Subtract the number
+	inline void operator-=(dual d)		{	mgl_datac_sub_num(this,d);	}
+#ifndef SWIG
+	/// Direct access to the data cell
+	inline dual &operator[](long i)	{	return a[i];	}
+#endif
+
+
+#ifndef DEBUG
+	/// Get the value in given cell of the data
+	mreal v(long i,long j=0,long k=0) const	{	return abs(a[i+nx*(j+ny*k)]);	}
+	/// Set the value in given cell of the data
+	void set_v(mreal val, long i,long j=0,long k=0)	{	a[i+nx*(j+ny*k)]=val;	}
+#else
+	/// Get the value in given cell of the data with border checking
+	mreal v(long i,long j=0,long k=0) const	{	return mgl_abs(mgl_datac_get_value(this,i,j,k));	}
+	/// Set the value in given cell of the data
+	void set_v(mreal val, long i,long j=0,long k=0)	{	mgl_datac_set_value(this,val,i,j,k);	}
+#endif
+	/// Get the complex value in given cell of the data
+	dual vc(long i,long j=0,long k=0) const	{	return a[i+nx*(j+ny*k)];	}
+	dual vcthr(long i) const	{	return a[i];	}
+	/// Get the interpolated value and its derivatives in given data cell without border checking
+	mreal valueD(mreal x,mreal y=0,mreal z=0,mreal *dx=0,mreal *dy=0,mreal *dz=0) const
+	{	dual aa,ax,ay,az;	mreal res;
+		aa = mglSpline3C(a,nx,ny,nz,x,y,z,&ax,&ay,&az);	res = abs(aa);
+		if(dx)	*dx = res?(real(aa)*real(ax)+imag(aa)*imag(ax))/res:0;
+		if(dy)	*dy = res?(real(aa)*real(ay)+imag(aa)*imag(ay))/res:0;
+		if(dz)	*dz = res?(real(aa)*real(az)+imag(aa)*imag(az))/res:0;
+		return res;	}
+	/// Get the interpolated value in given data cell without border checking
+	mreal value(mreal x,mreal y=0,mreal z=0) const
+	{	return abs(mglSpline3Cs(a,nx,ny,nz,x,y,z));	}
+	mreal vthr(long i) const {	return abs(a[i]);	}
+	// add for speeding up !!!
+	mreal dvx(long i,long j=0,long k=0) const
+	{   long i0=i+nx*(j+ny*k);
+		return i>0? abs(i<nx-1? (a[i0+1]-a[i0-1])/mreal(2):a[i0]-a[i0-1]) : abs(a[i0+1]-a[i0]);	}
+	mreal dvy(long i,long j=0,long k=0) const
+	{   long i0=i+nx*(j+ny*k);
+		return j>0? abs(j<ny-1? (a[i0+nx]-a[i0-nx])/mreal(2):a[i0]-a[i0-nx]) : abs(a[i0+nx]-a[i0]);}
+	mreal dvz(long i,long j=0,long k=0) const
+	{   long i0=i+nx*(j+ny*k), n=nx*ny;
+		return k>0? abs(k<nz-1? (a[i0+n]-a[i0-n])/mreal(2):a[i0]-a[i0-n]) : abs(a[i0+n]-a[i0]);	}
+};
+//-----------------------------------------------------------------------------
+/// Saves result of PDE solving (|u|^2) for "Hamiltonian" ham with initial conditions ini
+inline mglDataC mglPDEc(mglBase *gr, const char *ham, const mglDataA &ini_re, const mglDataA &ini_im, mreal dz=0.1, mreal k0=100,const char *opt="")
+{	return mglDataC(true, mgl_pde_solve_c(gr,ham, &ini_re, &ini_im, dz, k0,opt));	}
+/// Saves result of PDE solving for "Hamiltonian" ham with initial conditions ini along a curve ray (must have nx>=7 - x,y,z,px,py,pz,tau or nx=5 - x,y,px,py,tau)
+inline mglDataC mglQO2dc(const char *ham, const mglDataA &ini_re, const mglDataA &ini_im, const mglDataA &ray, mreal r=1, mreal k0=100)
+{	return mglDataC(true, mgl_qo2d_solve_c(ham, &ini_re, &ini_im, &ray, r, k0, 0, 0));	}
+inline mglDataC mglQO2dc(const char *ham, const mglDataA &ini_re, const mglDataA &ini_im, const mglDataA &ray, mglData &xx, mglData &yy, mreal r=1, mreal k0=100)
+{	return mglDataC(true, mgl_qo2d_solve_c(ham, &ini_re, &ini_im, &ray, r, k0, &xx, &yy));	}
+/// Saves result of PDE solving for "Hamiltonian" ham with initial conditions ini along a curve ray (must have nx>=7 - x,y,z,px,py,pz,tau or nx=5 - x,y,px,py,tau)
+inline mglDataC mglQO3dc(const char *ham, const mglDataA &ini_re, const mglDataA &ini_im, const mglDataA &ray, mreal r=1, mreal k0=100)
+{	return mglDataC(true, mgl_qo3d_solve_c(ham, &ini_re, &ini_im, &ray, r, k0, 0, 0, 0));	}
+inline mglDataC mglQO3dc(const char *ham, const mglDataA &ini_re, const mglDataA &ini_im, const mglDataA &ray, mglData &xx, mglData &yy, mglData &zz, mreal r=1, mreal k0=100)
+{	return mglDataC(true, mgl_qo3d_solve_c(ham, &ini_re, &ini_im, &ray, r, k0, &xx, &yy, &zz));	}
+/// Saves result of ODE solving for var complex variables with right part func (separated by ';') and initial conditions x0 over time interval [0,tmax] with time step dt
+inline mglDataC mglODEc(const char *func, const char *var, const mglDataA &ini, mreal dt=0.1, mreal tmax=10)
+{	return mglDataC(true, mgl_ode_solve_str_c(func,var, &ini, dt, tmax));	}
+//-----------------------------------------------------------------------------
+/// Get array as solution of tridiagonal system of equations a[i]*x[i-1]+b[i]*x[i]+c[i]*x[i+1]=d[i]
+/** String \a how may contain:
+ * 'x', 'y', 'z' for solving along x-,y-,z-directions, or
+ * 'h' for solving along hexagonal direction at x-y plain (need nx=ny),
+ * 'c' for using periodical boundary conditions,
+ * 'd' for diffraction/diffuse calculation. */
+inline mglDataC mglTridMatC(const mglDataA &A, const mglDataA &B, const mglDataA &C, const mglDataC &D, const char *how)
+{	return mglDataC(true, mgl_datac_tridmat(&A, &B, &C, &D, how));	}
+//-----------------------------------------------------------------------------
+/// Get sub-array of the data with given fixed indexes
+inline mglDataC mglSubDataC(const mglDataA &dat, long xx, long yy=-1, long zz=-1)
+{	return mglDataC(true,mgl_datac_subdata(&dat,xx,yy,zz));	}
+inline mglDataC mglSubDataC(const mglDataA &dat, const mglDataA &xx, const mglDataA &yy, const mglDataA &zz)
+{	return mglDataC(true,mgl_datac_subdata_ext(&dat,&xx,&yy,&zz));	}
+inline mglDataC mglSubDataC(const mglDataA &dat, const mglDataA &xx, const mglDataA &yy)
+{	return mglDataC(true,mgl_datac_subdata_ext(&dat,&xx,&yy,0));	}
+inline mglDataC mglSubDataC(const mglDataA &dat, const mglDataA &xx)
+{	return mglDataC(true,mgl_datac_subdata_ext(&dat,&xx,0,0));	}
+//-----------------------------------------------------------------------------
+/// Prepare coefficients for global spline interpolation
+inline mglDataC mglGSplineCInit(const mglDataA &xdat, const mglDataA &ydat)
+{	return mglDataC(true,mgl_gsplinec_init(&xdat, &ydat));	}
+/// Evaluate global spline (and its derivatives d1, d2 if not NULL) using prepared coefficients \a coef
+inline dual mglGSplineC(const mglDataA &coef, mreal dx, dual *d1=0, dual *d2=0)
+{	return mgl_gsplinec(&coef, dx, d1,d2);	}
+//-----------------------------------------------------------------------------
+#define _DN_(a)	((mglDataC *)*(a))
+#define _DC_		((mglDataC *)*d)
+//-----------------------------------------------------------------------------
+#ifndef SWIG
+/// Wrapper class for complex expression evaluating
+class MGL_EXPORT mglExprC
+{
+	HAEX ex;
+	mglExprC(const mglExprC &){}	// copying is not allowed
+	const mglExprC &operator=(const mglExprC &t){return t;}	// copying is not allowed
+public:
+	mglExprC(const char *expr)		{	ex = mgl_create_cexpr(expr);	}
+	~mglExprC()	{	mgl_delete_cexpr(ex);	}
+	/// Return value of expression for given x,y,z variables
+	inline dual Eval(dual x, dual y=0, dual z=0)
+	{	return mgl_cexpr_eval(ex,x,y,z);	}
+	/// Return value of expression for given x,y,z,u,v,w variables
+	inline dual Eval(dual x, dual y, dual z, dual u, dual v, dual w)
+	{
+		dual var[26];
+		var['x'-'a']=x;	var['y'-'a']=y;	var['z'-'a']=z;
+		var['u'-'a']=u;	var['v'-'a']=v;	var['w'-'a']=w;
+		return mgl_cexpr_eval_v(ex,var);	}
+	/// Return value of expression for given variables
+	inline dual Eval(dual var[26])
+	{	return mgl_cexpr_eval_v(ex,var);	}
+};
+#endif
+//-----------------------------------------------------------------------------
+#endif
+#endif
diff --git a/include/mgl2/datac_cf.h b/include/mgl2/datac_cf.h
new file mode 100644
index 0000000..f2626b5
--- /dev/null
+++ b/include/mgl2/datac_cf.h
@@ -0,0 +1,393 @@
+/***************************************************************************
+ * data_cf.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_DATAC_CF_H_
+#define _MGL_DATAC_CF_H_
+//-----------------------------------------------------------------------------
+#include "mgl2/abstract.h"
+//-----------------------------------------------------------------------------
+#if MGL_HAVE_GSL
+#include <gsl/gsl_vector.h>
+#include <gsl/gsl_matrix.h>
+#else
+struct gsl_vector;
+struct gsl_matrix;
+#endif
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+class mglDataC;
+typedef mglDataC* HADT;
+extern "C" {
+#else
+typedef void *HADT;
+#endif
+/// Get integer power of x
+mdual MGL_EXPORT_CONST mgl_ipowc(dual x,int n);
+mdual MGL_EXPORT mgl_ipowc_(dual *x,int *n);
+/// Get complex number from string. Parse (%g,%g), {%g,%g} and [%g,%g] if adv!=0.
+mdual MGL_EXPORT mgl_atoc(const char *s, int adv);
+/// Get exp(i*a)
+mdual MGL_EXPORT_CONST mgl_expi(dual a);
+
+/// Create HMDT object
+HADT MGL_EXPORT mgl_create_datac();
+uintptr_t MGL_EXPORT mgl_create_datac_();
+/// Create HMDT object with specified sizes
+HADT MGL_EXPORT mgl_create_datac_size(long nx, long ny, long nz);
+uintptr_t MGL_EXPORT mgl_create_datac_size_(int *nx, int *ny, int *nz);
+/// Create HMDT object with data from file
+HADT MGL_EXPORT mgl_create_datac_file(const char *fname);
+uintptr_t MGL_EXPORT mgl_create_datac_file_(const char *fname, int len);
+/// Delete HMDT object
+void MGL_EXPORT mgl_delete_datac(HADT dat);
+void MGL_EXPORT mgl_delete_datac_(uintptr_t *dat);
+
+/// Rearange data dimensions
+void MGL_EXPORT mgl_datac_rearrange(HADT dat, long mx,long my,long mz);
+void MGL_EXPORT mgl_datac_rearrange_(uintptr_t *dat, int *mx, int *my, int *mz);
+/// Link external data array (don't delete it at exit)
+void MGL_EXPORT mgl_datac_link(HADT dat, dual *A,long mx,long my,long mz);
+void MGL_EXPORT mgl_datac_link_(uintptr_t *d, dual *A, int *nx,int *ny,int *nz);
+/// Allocate memory and copy the data from the (float *) array
+void MGL_EXPORT mgl_datac_set_float(HADT dat, const float *A,long mx,long my,long mz);
+void MGL_EXPORT mgl_datac_set_float_(uintptr_t *dat, const float *A,int *NX,int *NY,int *NZ);
+/// Allocate memory and copy the data from the (double *) array
+void MGL_EXPORT mgl_datac_set_double(HADT dat, const double *A,long mx,long my,long mz);
+void MGL_EXPORT mgl_datac_set_double_(uintptr_t *dat, const double *A,int *NX,int *NY,int *NZ);
+/// Allocate memory and copy the data from the (dual *) array
+void MGL_EXPORT mgl_datac_set_complex(HADT dat, const dual *A,long mx,long my,long mz);
+void MGL_EXPORT mgl_datac_set_complex_(uintptr_t *d, const dual *A,int *NX,int *NY,int *NZ);
+/// Import data from abstract type
+void MGL_EXPORT mgl_datac_set(HADT dat, HCDT a);
+void MGL_EXPORT mgl_datac_set_(uintptr_t *dat, uintptr_t *a);
+/// Allocate memory and copy the data from the gsl_vector
+void MGL_EXPORT mgl_datac_set_vector(HADT dat, gsl_vector *v);
+/// Allocate memory and copy the data from the gsl_matrix
+void MGL_EXPORT mgl_datac_set_matrix(HADT dat, gsl_matrix *m);
+/// Set value of data element [i,j,k]
+void MGL_EXPORT mgl_datac_set_value(HADT dat, dual v, long i, long j, long k);
+void MGL_EXPORT mgl_datac_set_value_(uintptr_t *d, dual *v, int *i, int *j, int *k);
+/// Get value of data element [i,j,k]
+mdual MGL_EXPORT mgl_datac_get_value(HCDT dat, long i, long j, long k);
+mdual MGL_EXPORT mgl_datac_get_value_(uintptr_t *d, int *i, int *j, int *k);
+/// Allocate memory and scanf the data from the string
+void MGL_EXPORT mgl_datac_set_values(HADT dat, const char *val, long nx, long ny, long nz);
+void MGL_EXPORT mgl_datac_set_values_(uintptr_t *d, const char *val, int *nx, int *ny, int *nz, int l);
+
+/// Get array as solution of tridiagonal matrix solution a[i]*x[i-1]+b[i]*x[i]+c[i]*x[i+1]=d[i]
+/** String \a how may contain:
+ * 'x', 'y', 'z' for solving along x-,y-,z-directions, or
+ * 'h' for solving along hexagonal direction at x-y plain (need nx=ny),
+ * 'c' for using periodical boundary conditions,
+ * 'd' for diffraction/diffuse calculation.
+ * NOTE: It work for flat data model only (i.e. for a[i,j]==a[i+nx*j]) */
+HADT MGL_EXPORT mgl_datac_tridmat(HCDT A, HCDT B, HCDT C, HCDT D, const char *how);
+uintptr_t MGL_EXPORT mgl_datac_tridmat_(uintptr_t *A, uintptr_t *B, uintptr_t *C, uintptr_t *D, const char *how, int);
+
+/// Returns pointer to internal data array
+MGL_EXPORT dual *mgl_datac_data(HADT dat);
+/// Returns pointer to data element [i,j,k]
+MGL_EXPORT dual *mgl_datac_value(HADT dat, long i,long j,long k);
+
+/// Set the data from HCDT objects for real and imaginary parts
+void MGL_EXPORT mgl_datac_set_ri(HADT dat, HCDT re, HCDT im);
+void MGL_EXPORT mgl_datac_set_ri_(uintptr_t *dat, uintptr_t *re, uintptr_t *im);
+/// Set the data from HCDT objects as amplitude and phase of complex data
+void MGL_EXPORT mgl_datac_set_ap(HADT dat, HCDT abs, HCDT phi);
+void MGL_EXPORT mgl_datac_set_ap_(uintptr_t *dat, uintptr_t *abs, uintptr_t *phi);
+
+/// Read data from tab-separated text file with auto determining size
+int MGL_EXPORT mgl_datac_read(HADT dat, const char *fname);
+int MGL_EXPORT mgl_datac_read_(uintptr_t *d, const char *fname,int l);
+/// Read data from text file with size specified at beginning of the file
+int MGL_EXPORT mgl_datac_read_mat(HADT dat, const char *fname, long dim);
+int MGL_EXPORT mgl_datac_read_mat_(uintptr_t *dat, const char *fname, int *dim, int);
+/// Read data from text file with specifeid size
+int MGL_EXPORT mgl_datac_read_dim(HADT dat, const char *fname,long mx,long my,long mz);
+int MGL_EXPORT mgl_datac_read_dim_(uintptr_t *dat, const char *fname,int *mx,int *my,int *mz,int);
+/// Read data from tab-separated text files with auto determining size which filenames are result of sprintf(fname,templ,t) where t=from:step:to
+int MGL_EXPORT mgl_datac_read_range(HADT d, const char *templ, double from, double to, double step, int as_slice);
+int MGL_EXPORT mgl_datac_read_range_(uintptr_t *d, const char *fname, mreal *from, mreal *to, mreal *step, int *as_slice,int l);
+/// Read data from tab-separated text files with auto determining size which filenames are satisfied to template (like "t_*.dat")
+int MGL_EXPORT mgl_datac_read_all(HADT dat, const char *templ, int as_slice);
+int MGL_EXPORT mgl_datac_read_all_(uintptr_t *d, const char *fname, int *as_slice,int l);
+/// Save whole data array (for ns=-1) or only ns-th slice to text file
+void MGL_EXPORT mgl_datac_save(HCDT dat, const char *fname,long ns);
+void MGL_EXPORT mgl_datac_save_(uintptr_t *dat, const char *fname,int *ns,int);
+
+/// Read data array from HDF file (parse HDF4 and HDF5 files)
+int MGL_EXPORT mgl_datac_read_hdf(HADT d,const char *fname,const char *data);
+int MGL_EXPORT mgl_datac_read_hdf_(uintptr_t *d, const char *fname, const char *data,int l,int n);
+/// Save data to HDF file
+void MGL_EXPORT mgl_datac_save_hdf(HCDT d,const char *fname,const char *data,int rewrite);
+void MGL_EXPORT mgl_datac_save_hdf_(uintptr_t *d, const char *fname, const char *data, int *rewrite,int l,int n);
+
+/// Create or recreate the array with specified size and fill it by zero
+void MGL_EXPORT mgl_datac_create(HADT dat, long nx,long ny,long nz);
+void MGL_EXPORT mgl_datac_create_(uintptr_t *dat, int *nx,int *ny,int *nz);
+/// Transpose dimensions of the data (generalization of Transpose)
+void MGL_EXPORT mgl_datac_transpose(HADT dat, const char *dim);
+void MGL_EXPORT mgl_datac_transpose_(uintptr_t *dat, const char *dim,int);
+
+/// Get sub-array of the data with given fixed indexes
+HADT MGL_EXPORT mgl_datac_subdata(HCDT dat, long xx,long yy,long zz);
+uintptr_t MGL_EXPORT mgl_datac_subdata_(uintptr_t *dat, int *xx,int *yy,int *zz);
+/// Get sub-array of the data with given fixed indexes (like indirect access)
+HADT MGL_EXPORT mgl_datac_subdata_ext(HCDT dat, HCDT xx, HCDT yy, HCDT zz);
+uintptr_t MGL_EXPORT mgl_datac_subdata_ext_(uintptr_t *dat, uintptr_t *xx,uintptr_t *yy,uintptr_t *zz);
+/// Get column (or slice) of the data filled by formulas of named columns
+HADT MGL_EXPORT mgl_datac_column(HCDT dat, const char *eq);
+uintptr_t MGL_EXPORT mgl_datac_column_(uintptr_t *dat, const char *eq,int l);
+/// Get trace of the data array
+HADT MGL_EXPORT mgl_datac_trace(HCDT d);
+uintptr_t MGL_EXPORT mgl_datac_trace_(uintptr_t *d);
+/// Resize the data to new sizes
+HADT MGL_EXPORT mgl_datac_resize(HCDT dat, long mx,long my,long mz);
+uintptr_t MGL_EXPORT mgl_datac_resize_(uintptr_t *dat, int *mx,int *my,int *mz);
+/// Resize the data to new sizes of box [x1,x2]*[y1,y2]*[z1,z2]
+HADT MGL_EXPORT mgl_datac_resize_box(HCDT dat, long mx,long my,long mz,mreal x1,mreal x2,mreal y1,mreal y2,mreal z1,mreal z2);
+uintptr_t MGL_EXPORT mgl_datac_resize_box_(uintptr_t *dat, int *mx,int *my,int *mz,mreal *x1,mreal *x2,mreal *y1,mreal *y2,mreal *z1,mreal *z2);
+/// Get momentum (1D-array) of data along direction 'dir'. String looks like "x1" for median in x-direction, "x2" for width in x-dir and so on.
+HADT MGL_EXPORT mgl_datac_momentum(HCDT dat, char dir, const char *how);
+uintptr_t MGL_EXPORT mgl_datac_momentum_(uintptr_t *dat, char *dir, const char *how, int,int);
+/// Get array which values is result of interpolation this for coordinates from other arrays
+HADT MGL_EXPORT mgl_datac_evaluate(HCDT dat, HCDT idat, HCDT jdat, HCDT kdat, int norm);
+uintptr_t MGL_EXPORT mgl_datac_evaluate_(uintptr_t *dat, uintptr_t *idat, uintptr_t *jdat, uintptr_t *kdat, int *norm);
+/// Get array which is result of summation in given direction or directions
+HADT MGL_EXPORT mgl_datac_sum(HCDT dat, const char *dir);
+uintptr_t MGL_EXPORT mgl_datac_sum_(uintptr_t *dat, const char *dir,int);
+/// Get the data which is direct multiplication (like, d[i,j] = this[i]*a[j] and so on)
+HADT MGL_EXPORT mgl_datac_combine(HCDT dat1, HCDT dat2);
+uintptr_t MGL_EXPORT mgl_datac_combine_(uintptr_t *dat1, uintptr_t *dat2);
+/// Get data from sections ids, separated by value val along specified direction.
+/** If section id is negative then reverse order is used (i.e. -1 give last section). */
+HADT MGL_EXPORT mgl_datac_section(HCDT dat, HCDT ids, char dir, mreal val);
+uintptr_t MGL_EXPORT mgl_datac_section_(uintptr_t *d, uintptr_t *ids, const char *dir, mreal *val,int);
+/// Get data from section id, separated by value val along specified direction.
+/** If section id is negative then reverse order is used (i.e. -1 give last section). */
+HADT MGL_EXPORT mgl_datac_section_val(HCDT dat, long id, char dir, mreal val);
+uintptr_t MGL_EXPORT mgl_datac_section_val_(uintptr_t *d, int *id, const char *dir, mreal *val,int);
+
+/// Set names for columns (slices)
+void MGL_EXPORT mgl_datac_set_id(HADT d, const char *id);
+void MGL_EXPORT mgl_datac_set_id_(uintptr_t *dat, const char *id,int l);
+/// Equidistantly fill the data to range [x1,x2] in direction dir
+void MGL_EXPORT mgl_datac_fill(HADT dat, dual x1,dual x2,char dir);
+void MGL_EXPORT mgl_datac_fill_(uintptr_t *dat, dual *x1,dual *x2,const char *dir,int);
+/// Modify the data by specified formula assuming x,y,z in range [r1,r2]
+void MGL_EXPORT mgl_datac_fill_eq(HMGL gr, HADT dat, const char *eq, HCDT vdat, HCDT wdat,const char *opt);
+void MGL_EXPORT mgl_datac_fill_eq_(uintptr_t *gr, uintptr_t *dat, const char *eq, uintptr_t *vdat, uintptr_t *wdat,const char *opt, int, int);
+/// Fill dat by interpolated values of vdat parametrically depended on xdat for x in range [x1,x2] using global spline
+void MGL_EXPORT mgl_datac_refill_gs(HADT dat, HCDT xdat, HCDT vdat, mreal x1, mreal x2, long sl);
+void MGL_EXPORT mgl_datac_refill_gs_(uintptr_t *dat, uintptr_t *xdat, uintptr_t *vdat, mreal *x1, mreal *x2, long *sl);
+/// Fill dat by interpolated values of vdat parametrically depended on xdat for x in range [x1,x2]
+void MGL_EXPORT mgl_datac_refill_x(HADT dat, HCDT xdat, HCDT vdat, mreal x1, mreal x2, long sl);
+void MGL_EXPORT mgl_datac_refill_x_(uintptr_t *dat, uintptr_t *xdat, uintptr_t *vdat, mreal *x1, mreal *x2, long *sl);
+/// Fill dat by interpolated values of vdat parametrically depended on xdat,ydat for x,y in range [x1,x2]*[y1,y2]
+void MGL_EXPORT mgl_datac_refill_xy(HADT dat, HCDT xdat, HCDT ydat, HCDT vdat, mreal x1, mreal x2, mreal y1, mreal y2, long sl);
+void MGL_EXPORT mgl_datac_refill_xy_(uintptr_t *dat, uintptr_t *xdat, uintptr_t *ydat, uintptr_t *vdat, mreal *x1, mreal *x2, mreal *y1, mreal *y2, long *sl);
+/// Fill dat by interpolated values of vdat parametrically depended on xdat,ydat,zdat for x,y,z in range [x1,x2]*[y1,y2]*[z1,z2]
+void MGL_EXPORT mgl_datac_refill_xyz(HADT dat, HCDT xdat, HCDT ydat, HCDT zdat, HCDT vdat, mreal x1, mreal x2, mreal y1, mreal y2, mreal z1, mreal z2);
+void MGL_EXPORT mgl_datac_refill_xyz_(uintptr_t *dat, uintptr_t *xdat, uintptr_t *ydat, uintptr_t *zdat, uintptr_t *vdat, mreal *x1, mreal *x2, mreal *y1, mreal *y2, mreal *z1, mreal *z2);
+/// Fill dat by interpolated values of vdat parametrically depended on xdat,ydat,zdat for x,y,z in axis range
+void MGL_EXPORT mgl_datac_refill_gr(HMGL gr, HADT dat, HCDT xdat, HCDT ydat, HCDT zdat, HCDT vdat, long sl, const char *opt);
+void MGL_EXPORT mgl_datac_refill_gr_(uintptr_t *gr, uintptr_t *dat, uintptr_t *xdat, uintptr_t *ydat, uintptr_t *zdat, uintptr_t *vdat, long *sl, const char *opt,int);
+
+/// Modify the data by specified formula
+void MGL_EXPORT mgl_datac_modify(HADT dat, const char *eq,long dim);
+void MGL_EXPORT mgl_datac_modify_(uintptr_t *dat, const char *eq,int *dim,int);
+/// Modify the data by specified formula
+void MGL_EXPORT mgl_datac_modify_vw(HADT dat, const char *eq,HCDT vdat,HCDT wdat);
+void MGL_EXPORT mgl_datac_modify_vw_(uintptr_t *dat, const char *eq, uintptr_t *vdat, uintptr_t *wdat,int);
+
+/// Limit the data to be inside [-v,v], keeping the original sign
+void MGL_EXPORT mgl_datac_limit(HADT dat, mreal v);
+void MGL_EXPORT mgl_datac_limit_(uintptr_t *dat, mreal *v);
+
+/// Put value to data element(s)
+void MGL_EXPORT mgl_datac_put_val(HADT dat, dual val, long i, long j, long k);
+void MGL_EXPORT mgl_datac_put_val_(uintptr_t *dat, dual *val, int *i, int *j, int *k);
+/// Put array to data element(s)
+void MGL_EXPORT mgl_datac_put_dat(HADT dat, HCDT val, long i, long j, long k);
+void MGL_EXPORT mgl_datac_put_dat_(uintptr_t *dat, uintptr_t *val, int *i, int *j, int *k);
+
+/// Reduce size of the data
+void MGL_EXPORT mgl_datac_squeeze(HADT dat, long rx,long ry,long rz,long smooth);
+void MGL_EXPORT mgl_datac_squeeze_(uintptr_t *dat, int *rx,int *ry,int *rz,int *smooth);
+/// Extend data dimensions
+void MGL_EXPORT mgl_datac_extend(HADT dat, long n1, long n2);
+void MGL_EXPORT mgl_datac_extend_(uintptr_t *dat, int *n1, int *n2);
+/// Insert data rows/columns/slices
+void MGL_EXPORT mgl_datac_insert(HADT dat, char dir, long at, long num);
+void MGL_EXPORT mgl_datac_insert_(uintptr_t *dat, const char *dir, int *at, int *num, int);
+/// Delete data rows/columns/slices
+void MGL_EXPORT mgl_datac_delete(HADT dat, char dir, long at, long num);
+void MGL_EXPORT mgl_datac_delete_(uintptr_t *dat, const char *dir, int *at, int *num, int);
+/// Joind another data array
+void MGL_EXPORT mgl_datac_join(HADT dat, HCDT d);
+void MGL_EXPORT mgl_datac_join_(uintptr_t *dat, uintptr_t *d);
+
+/// Smooth the data on specified direction or directions
+/** String \a dir may contain:
+ *  ‘x’, ‘y’, ‘z’ for 1st, 2nd or 3d dimension;
+ *  ‘dN’ for linear averaging over N points;
+ *  ‘3’ for linear averaging over 3 points;
+ *  ‘5’ for linear averaging over 5 points.
+ *  By default quadratic averaging over 5 points is used. */
+void MGL_EXPORT mgl_datac_smooth(HADT d, const char *dirs, mreal delta);
+void MGL_EXPORT mgl_datac_smooth_(uintptr_t *dat, const char *dirs, mreal *delta,int);
+/// Cumulative summation the data in given direction or directions
+void MGL_EXPORT mgl_datac_cumsum(HADT dat, const char *dir);
+void MGL_EXPORT mgl_datac_cumsum_(uintptr_t *dat, const char *dir,int);
+/// Integrate (cumulative summation) the data in given direction or directions
+void MGL_EXPORT mgl_datac_integral(HADT dat, const char *dir);
+void MGL_EXPORT mgl_datac_integral_(uintptr_t *dat, const char *dir,int);
+/// Differentiate the data in given direction or directions
+void MGL_EXPORT mgl_datac_diff(HADT dat, const char *dir);
+void MGL_EXPORT mgl_datac_diff_(uintptr_t *dat, const char *dir,int);
+/// Differentiate the parametrically specified data along direction v1 with v2,v3=const (v3 can be NULL)
+void MGL_EXPORT mgl_datac_diff_par(HADT dat, HCDT v1, HCDT v2, HCDT v3);
+void MGL_EXPORT mgl_datac_diff_par_(uintptr_t *dat, uintptr_t *v1, uintptr_t *v2, uintptr_t *v3);
+/// Double-differentiate (like Laplace operator) the data in given direction
+void MGL_EXPORT mgl_datac_diff2(HADT dat, const char *dir);
+void MGL_EXPORT mgl_datac_diff2_(uintptr_t *dat, const char *dir,int);
+/// Swap left and right part of the data in given direction (useful for Fourier spectrum)
+void MGL_EXPORT mgl_datac_swap(HADT dat, const char *dir);
+void MGL_EXPORT mgl_datac_swap_(uintptr_t *dat, const char *dir,int);
+/// Roll data along direction dir by num slices
+void MGL_EXPORT mgl_datac_roll(HADT dat, char dir, long num);
+void MGL_EXPORT mgl_datac_roll_(uintptr_t *dat, const char *dir, int *num, int);
+/// Mirror the data in given direction (useful for Fourier spectrum)
+void MGL_EXPORT mgl_datac_mirror(HADT dat, const char *dir);
+void MGL_EXPORT mgl_datac_mirror_(uintptr_t *dat, const char *dir,int);
+/// Crop the data
+void MGL_EXPORT mgl_datac_crop(HADT dat, long n1, long n2, char dir);
+void MGL_EXPORT mgl_datac_crop_(uintptr_t *dat, int *n1, int *n2, const char *dir,int);
+/// Crop the data to be most optimal for FFT (i.e. to closest value of 2^n*3^m*5^l)
+void MGL_EXPORT mgl_datac_crop_opt(HADT dat, const char *how);
+void MGL_EXPORT mgl_datac_crop_opt_(uintptr_t *dat, const char *how,int);
+
+/// Multiply the data by other one for each element
+void MGL_EXPORT mgl_datac_mul_dat(HADT dat, HCDT d);
+void MGL_EXPORT mgl_datac_mul_dat_(uintptr_t *dat, uintptr_t *d);
+/// Divide the data by other one for each element
+void MGL_EXPORT mgl_datac_div_dat(HADT dat, HCDT d);
+void MGL_EXPORT mgl_datac_div_dat_(uintptr_t *dat, uintptr_t *d);
+/// Add the other data
+void MGL_EXPORT mgl_datac_add_dat(HADT dat, HCDT d);
+void MGL_EXPORT mgl_datac_add_dat_(uintptr_t *dat, uintptr_t *d);
+/// Subtract the other data
+void MGL_EXPORT mgl_datac_sub_dat(HADT dat, HCDT d);
+void MGL_EXPORT mgl_datac_sub_dat_(uintptr_t *dat, uintptr_t *d);
+/// Multiply each element by the number
+void MGL_EXPORT mgl_datac_mul_num(HADT dat, dual d);
+void MGL_EXPORT mgl_datac_mul_num_(uintptr_t *dat, dual *d);
+/// Divide each element by the number
+void MGL_EXPORT mgl_datac_div_num(HADT dat, dual d);
+void MGL_EXPORT mgl_datac_div_num_(uintptr_t *dat, dual *d);
+/// Add the number
+void MGL_EXPORT mgl_datac_add_num(HADT dat, dual d);
+void MGL_EXPORT mgl_datac_add_num_(uintptr_t *dat, dual *d);
+/// Subtract the number
+void MGL_EXPORT mgl_datac_sub_num(HADT dat, dual d);
+void MGL_EXPORT mgl_datac_sub_num_(uintptr_t *dat, dual *d);
+
+/// Apply Hankel transform
+void MGL_EXPORT mgl_datac_hankel(HADT dat, const char *dir);
+void MGL_EXPORT mgl_datac_hankel_(uintptr_t *dat, const char *dir,int);
+/// Apply Sin-Fourier transform
+void MGL_EXPORT mgl_datac_sinfft(HADT dat, const char *dir);
+void MGL_EXPORT mgl_datac_sinfft_(uintptr_t *dat, const char *dir,int);
+/// Apply Cos-Fourier transform
+void MGL_EXPORT mgl_datac_cosfft(HADT dat, const char *dir);
+void MGL_EXPORT mgl_datac_cosfft_(uintptr_t *dat, const char *dir,int);
+/// Apply Fourier transform
+void MGL_EXPORT mgl_datac_fft(HADT dat, const char *dir);
+void MGL_EXPORT mgl_datac_fft_(uintptr_t *dat, const char *dir,int);
+/// Find correlation between 2 data arrays
+HADT MGL_EXPORT mgl_datac_correl(HCDT dat1, HCDT dat2, const char *dir);
+uintptr_t MGL_EXPORT mgl_datac_correl_(uintptr_t *dat1, uintptr_t *dat2, const char *dir,int);
+/// Calculate one step of diffraction by finite-difference method with parameter q
+void MGL_EXPORT mgl_datac_diffr(HADT dat, const char *how, mreal q);
+void MGL_EXPORT mgl_datac_diffr_(uintptr_t *d, const char *how, double q,int l);
+/// Apply wavelet transform
+/** Parameter \a dir may contain:
+ * ‘x‘,‘y‘,‘z‘ for directions,
+ * ‘d‘ for daubechies, ‘D‘ for centered daubechies,
+ * ‘h‘ for haar, ‘H‘ for centered haar,
+ * ‘b‘ for bspline, ‘B‘ for centered bspline,
+ * ‘i‘ for applying inverse transform. */
+void MGL_EXPORT mgl_datac_wavelet(HADT dat, const char *how, int k);
+void MGL_EXPORT mgl_datac_wavelet_(uintptr_t *d, const char *dir, int *k,int);
+/// Set as the data envelop
+void MGL_EXPORT mgl_datac_envelop(HADT dat, char dir);
+void MGL_EXPORT mgl_datac_envelop_(uintptr_t *dat, const char *dir, int);
+
+/// Get real part of data values
+HMDT MGL_EXPORT mgl_datac_real(HCDT dat);
+uintptr_t MGL_EXPORT mgl_datac_real_(uintptr_t *dat);
+/// Get imaginary part of data values
+HMDT MGL_EXPORT mgl_datac_imag(HCDT dat);
+uintptr_t MGL_EXPORT mgl_datac_imag_(uintptr_t *dat);
+/// Get absolute value of data values, i.e. |u|
+HMDT MGL_EXPORT mgl_datac_abs(HCDT dat);
+uintptr_t MGL_EXPORT mgl_datac_abs_(uintptr_t *dat);
+/// Get argument of data values
+HMDT MGL_EXPORT mgl_datac_arg(HCDT dat);
+uintptr_t MGL_EXPORT mgl_datac_arg_(uintptr_t *dat);
+/// Get square of absolute value of data values, i.e. |u|^2
+HMDT MGL_EXPORT mgl_datac_norm(HCDT dat);
+uintptr_t MGL_EXPORT mgl_datac_norm_(uintptr_t *dat);
+
+/// Interpolate by linear function the data to given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+mdual MGL_EXPORT mgl_datac_linear(HCDT d, mreal x,mreal y,mreal z);
+mdual MGL_EXPORT mgl_datac_linear_(uintptr_t *d, mreal *x,mreal *y,mreal *z);
+/// Interpolate by linear function the data and return its derivatives at given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+mdual MGL_EXPORT mgl_datac_linear_ext(HCDT d, mreal x,mreal y,mreal z, dual *dx,dual *dy,dual *dz);
+mdual MGL_EXPORT mgl_datac_linear_ext_(uintptr_t *d, mreal *x,mreal *y,mreal *z, dual *dx,dual *dy,dual *dz);
+/// Interpolate by cubic spline the data to given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+mdual MGL_EXPORT mgl_datac_spline(HCDT dat, mreal x,mreal y,mreal z);
+mdual MGL_EXPORT mgl_datac_spline_(uintptr_t *dat, mreal *x,mreal *y,mreal *z);
+/// Interpolate by cubic spline the data and return its derivatives at given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+mdual MGL_EXPORT mgl_datac_spline_ext(HCDT dat, mreal x,mreal y,mreal z, dual *dx,dual *dy,dual *dz);
+mdual MGL_EXPORT mgl_datac_spline_ext_(uintptr_t *dat, mreal *x,mreal *y,mreal *z, dual *dx,dual *dy,dual *dz);
+/// Prepare coefficients for global spline interpolation
+HADT MGL_EXPORT mgl_gsplinec_init(HCDT x, HCDT v);
+uintptr_t MGL_EXPORT mgl_gspline_init_(uintptr_t *x, uintptr_t *v);
+/// Evaluate global spline (and its derivatives d1, d2 if not NULL) using prepared coefficients \a coef
+mdual MGL_EXPORT mgl_gsplinec(HCDT coef, mreal dx, dual *d1, dual *d2);
+mdual MGL_EXPORT mgl_gsplinec_(uintptr_t *c, mreal *dx, dual *d1, dual *d2);
+//-----------------------------------------------------------------------------
+/// Create HAEX object for expression evaluating
+HAEX MGL_EXPORT mgl_create_cexpr(const char *expr);
+uintptr_t MGL_EXPORT mgl_create_cexpr_(const char *expr, int);
+/// Delete HAEX object
+void MGL_EXPORT mgl_delete_cexpr(HAEX ex);
+void MGL_EXPORT mgl_delete_cexpr_(uintptr_t *ex);
+/// Return value of expression for given x,y,z variables
+mdual MGL_EXPORT mgl_cexpr_eval(HAEX ex, dual x, dual y,dual z);
+mdual MGL_EXPORT mgl_cexpr_eval_(uintptr_t *ex, dual *x, dual *y, dual *z);
+/// Return value of expression for given variables
+mdual MGL_EXPORT mgl_cexpr_eval_v(HAEX ex, dual *vars);
+
+#ifdef __cplusplus
+}
+#endif
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/define.h b/include/mgl2/define.h
new file mode 100644
index 0000000..ee0f002
--- /dev/null
+++ b/include/mgl2/define.h
@@ -0,0 +1,386 @@
+/***************************************************************************
+ * define.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_DEFINE_H_
+#define _MGL_DEFINE_H_
+//-----------------------------------------------------------------------------
+// Disable warnings for MSVC:
+// 4190 - C-linkage of std::complex,
+// 4996 - deprecated abi functions
+// 4786 - disable warnings on 255 char debug symbols
+// 4231 - disable warnings on extern before template instantiation
+// 4800	- "int,uint32_t,etc" forcing value to bool 'true' or 'false' (performance warning)
+// 4244 - conversion from 'mreal,double' to 'float', possible loss of data
+// 4267	- conversion from 'size_t' to 'long,int,etc', possible loss of data
+// 4305	- truncation from 'double' to 'float'
+#if defined(_MSC_VER)
+#pragma warning(disable: 4996 4190 4786 4231 4800 4244 4267 4305)
+#endif
+
+#include "mgl2/config.h"
+#ifndef SWIG
+
+#if MGL_HAVE_PTHR_WIDGET|MGL_HAVE_PTHREAD
+#include <pthread.h>
+#endif
+
+#include "mgl2/dllexport.h"
+#if defined(_MSC_VER)
+#define MGL_OBSOLETE	MGL_NO_EXPORT
+#else
+#define MGL_OBSOLETE	MGL_EXPORT
+#endif
+
+#if MGL_HAVE_ATTRIBUTE
+#define MGL_FUNC_CONST	__attribute__((const))
+#define MGL_FUNC_PURE	__attribute__((pure))
+#else
+#define MGL_FUNC_CONST
+#define MGL_FUNC_PURE
+#endif
+#define MGL_EXPORT_CONST	MGL_EXPORT MGL_FUNC_CONST
+#define MGL_EXPORT_PURE		MGL_EXPORT MGL_FUNC_PURE
+#define MGL_LOCAL_CONST		MGL_NO_EXPORT MGL_FUNC_CONST
+#define MGL_LOCAL_PURE		MGL_NO_EXPORT MGL_FUNC_PURE
+
+#if MGL_HAVE_RVAL	// C++11 don't support register keyword
+#if (!defined(_MSC_VER)) || (defined(_MSC_VER) && (_MSC_VER < 1310))
+#define register
+#endif
+#endif
+
+#endif
+//-----------------------------------------------------------------------------
+#ifdef WIN32 //_MSC_VER needs this before math.h
+#define	_USE_MATH_DEFINES
+#endif
+
+#ifdef MGL_SRC
+
+#if MGL_USE_GETTEXT
+	#include <libintl.h>
+	#define _(x)	gettext(x)
+#else
+	#define _(x)	(x)
+#endif
+
+
+#if MGL_HAVE_ZLIB
+#include <zlib.h>
+#ifndef Z_BEST_COMPRESSION
+#define Z_BEST_COMPRESSION 9
+#endif
+#else
+#define gzFile	FILE*
+#define gzread(fp,buf,size)	fread(buf,1,size,fp)
+#define gzopen	fopen
+#define gzclose	fclose
+#define gzprintf	fprintf
+#define gzgets(fp,str,size)	fgets(str,size,fp)
+#define gzgetc	fgetc
+#endif
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER<1600)) || defined(__BORLANDC__)
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed long int32_t;
+typedef signed long long int64_t;
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned long uint32_t;
+typedef unsigned long long uint64_t;
+#else
+#include <stdint.h>
+#endif
+#if defined(__BORLANDC__)
+typedef unsigned long uintptr_t;
+#endif
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#if defined(_MSC_VER)
+#define collapse(a)	// MSVS don't support OpenMP 3.*
+#if (_MSC_VER<=1800)
+#define strtoull _strtoui64
+//#define hypot	_hypot
+#define getcwd	_getcwd
+#define chdir	_chdir // BORLAND has chdir
+#endif
+#define snprintf _snprintf
+#if (_MSC_VER<1600) // based on https://hg.python.org/cpython/rev/9aedb876c2d7
+#define hypot	_hypot
+#endif
+#endif
+
+#if !MGL_SYS_NAN
+#include <float.h>
+#include <math.h>
+const unsigned long long mgl_nan[2] = {0x7fffffffffffffff, 0x7fffffff};
+const unsigned long long mgl_inf[2] = {0x7ff0000000000000, 0x7f800000};
+#define NANd    (*(double*)mgl_nan)
+#define NANf    (*(float*)(mgl_nan+1))
+#define INFd    (*(double*)mgl_inf)
+#define INFf    (*(float*)(mgl_inf+1))
+
+#if !defined(NAN)
+#if MGL_USE_DOUBLE
+#define NAN		NANd
+#else
+#define NAN		NANf
+#endif
+#endif
+
+#if !defined(INFINITY)
+#if MGL_USE_DOUBLE
+#define INFINITY	INFd
+#else
+#define INFINITY	INFf
+#endif
+#endif
+#endif	// !MGL_SYS_NAN
+
+#ifndef M_PI
+#define M_PI	3.14159265358979323846  /* pi */
+#endif
+//-----------------------------------------------------------------------------
+#ifdef WIN32
+#define mglprintf    _snwprintf
+#else
+#define mglprintf    swprintf
+#endif
+//#define FLT_EPS	1.1920928955078125e-07
+//-----------------------------------------------------------------------------
+#if MGL_USE_DOUBLE
+typedef double mreal;
+#define MGL_EPSILON	(1.+1e-10)
+#define MGL_MIN_VAL 1e-307
+#else
+typedef float mreal;
+#define MGL_EPSILON	(1.+1e-5)
+#define MGL_MIN_VAL 1e-37
+#endif
+#define MGL_FEPSILON	(1.+1e-5)
+//-----------------------------------------------------------------------------
+#ifndef MGL_CMAP_COLOR
+#define MGL_CMAP_COLOR	32
+#endif
+//-----------------------------------------------------------------------------
+#ifndef MGL_DEF_VIEWER
+#define MGL_DEF_VIEWER "evince"
+#endif
+//-----------------------------------------------------------------------------
+enum{	// types of predefined curvelinear coordinate systems
+	mglCartesian = 0,	// no transformation
+	mglPolar,
+	mglSpherical,
+	mglParabolic,
+	mglParaboloidal,
+	mglOblate,
+	mglProlate,
+	mglElliptic,
+	mglToroidal,
+	mglBispherical,
+	mglBipolar,
+	mglLogLog,
+	mglLogX,
+	mglLogY
+};
+//-----------------------------------------------------------------------------
+// types of drawing
+#define MGL_DRAW_WIRE	0	// fastest, no faces
+#define MGL_DRAW_FAST	1	// fast, no color interpolation
+#define MGL_DRAW_NORM	2	// high quality, slower
+#define MGL_DRAW_LMEM	4	// low memory usage (direct to pixel)
+#define MGL_DRAW_DOTS	8	// draw dots instead of primitives
+#define MGL_DRAW_NONE	9	// no ouput (for testing only)
+//-----------------------------------------------------------------------------
+enum{	// Codes for warnings/messages
+	mglWarnNone = 0,// Everything OK
+	mglWarnDim,		// Data dimension(s) is incompatible
+	mglWarnLow,		// Data dimension(s) is too small
+	mglWarnNeg,	 	// Minimal data value is negative
+	mglWarnFile, 	// No file or wrong data dimensions
+	mglWarnMem,		// Not enough memory
+	mglWarnZero, 	// Data values are zero
+	mglWarnLeg,		// No legend entries
+	mglWarnSlc,		// Slice value is out of range
+	mglWarnCnt,		// Number of contours is zero or negative
+	mglWarnOpen, 	// Couldn't open file
+	mglWarnLId,		// Light: ID is out of range
+	mglWarnSize, 	// Setsize: size(s) is zero or negative
+	mglWarnFmt,		// Format is not supported for that build
+	mglWarnTern, 	// Axis ranges are incompatible
+	mglWarnNull, 	// Pointer is NULL
+	mglWarnSpc,		// Not enough space for plot
+	mglScrArg,		// Wrong argument(s) in MGL script
+	mglScrCmd,		// Wrong command in MGL script
+	mglScrLong,		// Too long line in MGL script
+	mglScrStr,		// Unbalanced ' in MGL script
+	mglScrTemp,		// Change temporary data in MGL script
+	mglWarnEnd		// Maximal number of warnings (must be last)
+};
+//-----------------------------------------------------------------------------
+#define MGL_DEF_PAL	"bgrcmyhlnqeupH"	// default palette
+#define MGL_DEF_SCH	"BbcyrR"	// default palette
+#define MGL_COLORS	"kwrgbcymhWRGBCYMHlenpquLENPQU"
+//-----------------------------------------------------------------------------
+/// Brushes for mask with symbol "-+=;oOsS~<>jdD*^" correspondingly
+extern MGL_EXPORT uint64_t mgl_mask_val[16];
+#define MGL_MASK_ID		"-+=;oOsS~<>jdD*^"
+#define MGL_SOLID_MASK	0xffffffffffffffff
+//-----------------------------------------------------------------------------
+#define MGL_TRANSP_NORM		0x000000
+#define MGL_TRANSP_GLASS 	0x000001
+#define MGL_TRANSP_LAMP		0x000002
+#define MGL_ENABLE_CUT		0x000004 	///< Flag which determines how points outside bounding box are drown.
+#define MGL_ENABLE_RTEXT 	0x000008 	///< Use text rotation along axis
+#define MGL_AUTO_FACTOR		0x000010 	///< Enable autochange PlotFactor
+#define MGL_ENABLE_ALPHA 	0x000020 	///< Flag that Alpha is used
+#define MGL_ENABLE_LIGHT 	0x000040 	///< Flag of using lightning
+#define MGL_TICKS_ROTATE 	0x000080 	///< Allow ticks rotation
+#define MGL_TICKS_SKIP		0x000100 	///< Allow ticks rotation
+// flags for internal use only
+#define MGL_DISABLE_SCALE	0x000200 	///< Temporary flag for disable scaling (used for axis)
+#define MGL_FINISHED 		0x000400 	///< Flag that final picture (i.e. mglCanvas::G) is ready
+#define MGL_USE_GMTIME		0x000800 	///< Use gmtime instead of localtime
+#define MGL_SHOW_POS		0x001000 	///< Switch to show or not mouse click position
+#define MGL_CLF_ON_UPD		0x002000 	///< Clear plot before Update()
+#define MGL_NOSUBTICKS		0x004000 	///< Disable subticks drawing (for bounding box)
+#define MGL_LOCAL_LIGHT		0x008000 	///< Keep light sources for each inplot
+#define MGL_VECT_FRAME		0x010000 	///< Use DrwDat to remember all data of frames
+#define MGL_REDUCEACC		0x020000 	///< Reduce accuracy of points (to reduc size of output files)
+#define MGL_PREFERVC 		0x040000 	///< Prefer vertex color instead of texture if output format supports
+#define MGL_ONESIDED 		0x080000 	///< Render only front side of surfaces if output format supports (for debugging)
+#define MGL_NO_ORIGIN 		0x100000 	///< Don't draw tick labels at axis origin
+#define MGL_GRAY_MODE 		0x100000 	///< Convert all colors to gray ones
+//-----------------------------------------------------------------------------
+#if MGL_HAVE_C99_COMPLEX
+#include <complex.h>
+#if MGL_USE_DOUBLE
+typedef double _Complex mdual;
+#else
+typedef float _Complex mdual;
+#endif
+#ifndef _Complex_I
+#define _Complex_I	1.0i
+#endif
+const mdual mgl_I=_Complex_I;
+#define mgl_abs(x)	cabs(x)
+#endif
+#ifdef __cplusplus
+#include <string>
+#include <vector>
+#if defined(_MSC_VER)
+template class MGL_EXPORT std::allocator<char>;
+template class MGL_EXPORT std::allocator<wchar_t>;
+template struct MGL_EXPORT std::char_traits<char>;
+template struct MGL_EXPORT std::char_traits<wchar_t>;
+template class MGL_EXPORT std::basic_string< char, std::char_traits<char>, std::allocator<char> >;
+template class MGL_EXPORT std::basic_string< wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >;
+template class MGL_EXPORT std::vector<long>;
+template class MGL_EXPORT std::vector<mreal>;
+#endif
+//-----------------------------------------------------------------------------
+extern float mgl_cos[360];	///< contain cosine with step 1 degree
+//-----------------------------------------------------------------------------
+#include <complex>
+#if defined(_MSC_VER)
+template class MGL_EXPORT std::complex<float>;
+template class MGL_EXPORT std::complex<double>;
+#endif
+typedef std::complex<mreal> dual;
+typedef std::complex<double> ddual;
+#if !MGL_HAVE_C99_COMPLEX
+#define mdual dual
+#define mgl_I dual(0,1)
+#define mgl_abs(x)	abs(x)
+#endif
+//-----------------------------------------------------------------------------
+inline bool mgl_isrange(double a, double b)
+{	return fabs(a-b)>MGL_MIN_VAL && a-a==0. && b-b==0.;	}
+inline bool mgl_isbad(double a)	{	return a-a!=0;	}
+inline bool mgl_isbad(dual a)	{	return a-a!=mreal(0);	}
+inline bool mgl_isfin(double a)	{	return a-a==0;	}
+inline bool mgl_isfin(dual a)	{	return a-a==mreal(0);	}
+inline bool mgl_isnum(double a)	{	return a==a;	}
+inline bool mgl_isnum(dual a)	{	return a==a;	}
+inline bool mgl_isnan(double a)	{	return a!=a;	}
+inline bool mgl_isnan(dual a)	{	return a!=a;	}
+inline int mgl_sign(double a)	{	return a<0?-1:1;	}
+inline long mgl_int(double a)	{	return long(a+(a>=0?0.5:-0.5));	}
+inline double mgl_min(double a, double b)	{	return a>b?b:a;	}
+inline double mgl_max(double a, double b)	{	return a>b?a:b;	}
+//-----------------------------------------------------------------------------
+extern "C" {
+#else
+#include <complex.h>
+typedef double _Complex ddual;
+#define dual	mdual
+#endif
+/// Find length of wchar_t string (bypass standard wcslen bug)
+double MGL_EXPORT_CONST mgl_hypot(double x, double y);
+/// Find length of wchar_t string (bypass standard wcslen bug)
+size_t MGL_EXPORT mgl_wcslen(const wchar_t *str);
+/// Get RGB values for given color id or fill by -1 if no one found
+void MGL_EXPORT mgl_chrrgb(char id, float rgb[3]);
+/// Get number of colors in the string
+size_t MGL_EXPORT mgl_get_num_color(const char *s, int smooth);
+/// Check if string contain color id and return its number
+long MGL_EXPORT mgl_have_color(const char *stl);
+/// Find symbol in string excluding {} and return its position or NULL
+MGL_EXPORT const char *mglchr(const char *str, char ch);
+/// Find any symbol from chr in string excluding {} and return its position or NULL
+MGL_EXPORT const char *mglchrs(const char *str, const char *chr);
+/// Set number of thread for plotting and data handling (for pthread version only)
+void MGL_EXPORT mgl_set_num_thr(int n);
+void MGL_EXPORT mgl_set_num_thr_(int *n);
+void MGL_EXPORT mgl_test_txt(const char *str, ...);
+void MGL_EXPORT mgl_set_test_mode(int enable);
+/// Remove spaces at begining and at the end of the string
+void MGL_EXPORT mgl_strtrim(char *str);
+void MGL_EXPORT mgl_wcstrim(wchar_t *str);
+/** Change register to lowercase (only for ANSI symbols) */
+void MGL_EXPORT mgl_strlwr(char *str);
+void MGL_EXPORT mgl_wcslwr(wchar_t *str);
+/// Convert wchar_t* string into char* one
+void MGL_EXPORT mgl_wcstombs(char *dst, const wchar_t *src, int size);
+/// Clear internal data for speeding up FFT and Hankel transforms
+void MGL_EXPORT mgl_clear_fft();
+/// Set global warning message
+void MGL_EXPORT mgl_set_global_warn(const char *text);
+void MGL_EXPORT mgl_set_global_warn_(const char *text,int);
+/// Get text of global warning message(s)
+MGL_EXPORT const char *mgl_get_global_warn();
+int MGL_EXPORT mgl_get_global_warn_(char *out, int len);
+/// Setup gettext usage. NOTE: Russian translation MUST be installed.
+void MGL_EXPORT mgl_textdomain(const char *argv0, const char *locale);
+void MGL_EXPORT mgl_textdomain_(const char *locale, int);
+/// size of var array
+const int MGL_VS = 'z'-'a'+1;
+#ifdef __cplusplus
+}
+#endif
+//-----------------------------------------------------------------------------
+#endif
+//-----------------------------------------------------------------------------
diff --git a/include/mgl2/eval.h b/include/mgl2/eval.h
new file mode 100644
index 0000000..0910e93
--- /dev/null
+++ b/include/mgl2/eval.h
@@ -0,0 +1,60 @@
+/***************************************************************************
+ * eval.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_EVAL_H_
+#define _MGL_EVAL_H_
+//-----------------------------------------------------------------------------
+#include "mgl2/define.h"
+/// types of errors
+#define MGL_ERR_LOG		1
+#define MGL_ERR_ARC		2
+#define MGL_ERR_SQRT	3
+//-----------------------------------------------------------------------------
+/// Class for evaluating formula specified by the string
+class MGL_EXPORT mglFormula					// îáúåêò äëÿ ââîäà è âû÷èñëåíèÿ ôîðìóë
+{
+public:
+	/// Evaluates the formula for 'x','r'=\a x, 'y','n'=\a y, 'z','t'=\a z, 'u'=\a u
+	mreal Calc(mreal x,mreal y=0,mreal z=0,mreal u=0) const MGL_FUNC_PURE;
+	/// Evaluates the formula for 'x, y, z, u, v, w'
+	mreal Calc(mreal x,mreal y,mreal z,mreal u,mreal v,mreal w) const MGL_FUNC_PURE;
+	/// Evaluates the formula for variables var
+	mreal Calc(const mreal var[MGL_VS]) const MGL_FUNC_PURE;
+	/// Evaluates the formula for 'x','r'=\a x, 'y','n'=\a y, 'z','t'=\a z, 'u'=\a u
+	mreal CalcD(char diff, mreal x,mreal y=0,mreal z=0,mreal u=0) const MGL_FUNC_PURE;
+	/// Evaluates the formula for 'x, y, z, u, v, w'
+	mreal CalcD(char diff, mreal x,mreal y,mreal z,mreal u,mreal v,mreal w) const MGL_FUNC_PURE;
+	/// Evaluates the derivates of the formula for variables var respect to variable diff
+	mreal CalcD(const mreal var[MGL_VS], char diff) const MGL_FUNC_PURE;
+	/// Return error code
+	inline int GetError() const	{	return Error;	}
+	/// Parse the formula str and create formula-tree
+	mglFormula(const char *str);
+	/// Clean up formula-tree
+	~mglFormula();
+protected:
+	mreal CalcIn(const mreal *a1) const MGL_FUNC_PURE;
+	mreal CalcDIn(int id, const mreal *a1) const MGL_FUNC_PURE;
+	mglFormula *Left,*Right;	// first and second argument of the function
+	int Kod;					// the function ID
+	mreal Res;					// the number or the variable ID
+	static int Error;
+};
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/evalc.h b/include/mgl2/evalc.h
new file mode 100644
index 0000000..36dbeef
--- /dev/null
+++ b/include/mgl2/evalc.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+ * evalc.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_EVALC_H_
+#define _MGL_EVALC_H_
+//-----------------------------------------------------------------------------
+#include "mgl2/eval.h"
+//-----------------------------------------------------------------------------
+/// Class for evaluating formula specified by the string
+class MGL_EXPORT mglFormulaC					// ������ ��� ����� � ���������� ������
+{
+public:
+	/// Evaluates the formula for 'x','r'=\a x, 'y','n'=\a y, 'z','t'=\a z, 'u'=\a u
+	dual Calc(dual x,dual y=0,dual z=0,dual u=0) const MGL_FUNC_PURE;
+	/// Evaluates the formula for 'x, y, z, u, v, w'
+	dual Calc(dual x,dual y,dual z,dual u,dual v,dual w) const MGL_FUNC_PURE;
+	/// Evaluates the formula for variables var
+	dual Calc(const dual var[MGL_VS]) const MGL_FUNC_PURE;
+	/// Return error code
+	inline int GetError() const	{	return Error;	}
+	/// Parse the formula str and create formula-tree
+	mglFormulaC(const char *str);
+	/// Clean up formula-tree
+	virtual ~mglFormulaC();
+protected:
+	dual CalcIn(const dual *a1) const MGL_FUNC_PURE;
+	mglFormulaC *Left,*Right;	// first and second argument of the function
+	int Kod;					// the function ID
+	dual Res;					// the number or the variable ID
+	static int Error;
+};
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/fit.h b/include/mgl2/fit.h
new file mode 100644
index 0000000..5f6f2e2
--- /dev/null
+++ b/include/mgl2/fit.h
@@ -0,0 +1,90 @@
+/***************************************************************************
+ * fit.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_FIT_H_
+#define _MGL_FIT_H_
+#include "mgl2/abstract.h"
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+extern "C" {
+#endif
+//-----------------------------------------------------------------------------
+extern int mglFitPnts;			///< Number of output points in fitting
+extern char mglFitRes[1024];	///< Last fitted formula
+/// Fit data along x-direction for each data row. Return array with values for found formula.
+HMDT MGL_EXPORT mgl_fit_1(HMGL gr, HCDT y, const char *eq, const char *vars, HMDT ini, const char *opt);
+uintptr_t MGL_EXPORT mgl_fit_1_(uintptr_t* gr, uintptr_t* y, const char *eq, const char *vars, uintptr_t *ini, const char *opt,int, int l, int n);
+/// Fit data along x-, y-directions for each data slice. Return array with values for found formula.
+HMDT MGL_EXPORT mgl_fit_2(HMGL gr, HCDT z, const char *eq, const char *vars, HMDT ini, const char *opt);
+uintptr_t MGL_EXPORT mgl_fit_2_(uintptr_t* gr, uintptr_t* z, const char *eq, const char *vars, uintptr_t *ini, const char *opt,int, int l, int n);
+/// Fit data along along all directions. Return array with values for found formula.
+HMDT MGL_EXPORT mgl_fit_3(HMGL gr, HCDT a, const char *eq, const char *vars, HMDT ini, const char *opt);
+uintptr_t MGL_EXPORT mgl_fit_3_(uintptr_t* gr, uintptr_t* a, const char *eq, const char *vars, uintptr_t *ini, const char *opt,int, int l, int n);
+/// Fit data along x-direction for each data row. Return array with values for found formula.
+HMDT MGL_EXPORT mgl_fit_xy(HMGL gr, HCDT x, HCDT y, const char *eq, const char *vars, HMDT ini, const char *opt);
+uintptr_t MGL_EXPORT mgl_fit_xy_(uintptr_t* gr, uintptr_t* x, uintptr_t* y, const char *eq, const char *vars, uintptr_t *ini, const char *opt,int, int l, int n);
+/// Fit data along x-, y-directions for each data slice. Return array with values for found formula.
+HMDT MGL_EXPORT mgl_fit_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, const char *eq, const char *vars, HMDT ini, const char *opt);
+uintptr_t MGL_EXPORT mgl_fit_xyz_(uintptr_t* gr, uintptr_t* x, uintptr_t* y, uintptr_t* z, const char *eq, const char *vars, uintptr_t *ini, const char *opt,int, int l, int n);
+/// Fit data along along all directions. Return array with values for found formula.
+HMDT MGL_EXPORT mgl_fit_xyza(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, const char *eq, const char *vars, HMDT ini, const char *opt);
+uintptr_t MGL_EXPORT mgl_fit_xyza_(uintptr_t* gr, uintptr_t* x, uintptr_t* y, uintptr_t* z, uintptr_t* a, const char *eq, const char *vars, uintptr_t *ini, const char *opt,int, int l, int n);
+	/// Fit data with dispersion s along x-direction for each data row. Return array with values for found formula.
+HMDT MGL_EXPORT mgl_fit_ys(HMGL gr, HCDT y, HCDT s, const char *eq, const char *vars, HMDT ini, const char *opt);
+uintptr_t MGL_EXPORT mgl_fit_ys_(uintptr_t* gr, uintptr_t* y, uintptr_t* ss, const char *eq, const char *vars, uintptr_t *ini, const char *opt,int, int l, int n);
+HMDT MGL_EXPORT mgl_fit_xys(HMGL gr, HCDT x, HCDT y, HCDT s, const char *eq, const char *vars, HMDT ini, const char *opt);
+uintptr_t MGL_EXPORT mgl_fit_xys_(uintptr_t* gr, uintptr_t* x, uintptr_t* y, uintptr_t* ss, const char *eq, const char *vars, uintptr_t *ini, const char *opt,int, int l, int n);
+	/// Fit data with dispersion s along x-, y-directions for each data slice. Return array with values for found formula.
+HMDT MGL_EXPORT mgl_fit_xyzs(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT s, const char *eq, const char *vars, HMDT ini, const char *opt);
+uintptr_t MGL_EXPORT mgl_fit_xyzs_(uintptr_t* gr, uintptr_t* x, uintptr_t* y, uintptr_t* z, uintptr_t* ss, const char *eq, const char *vars, uintptr_t *ini, const char *opt,int, int l, int n);
+HMDT MGL_EXPORT mgl_fit_xyzas(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, HCDT s, const char *eq, const char *vars, HMDT ini, const char *opt);
+uintptr_t MGL_EXPORT mgl_fit_xyzas_(uintptr_t* gr, uintptr_t* x, uintptr_t* y, uintptr_t* z, uintptr_t* a, uintptr_t* ss, const char *eq, const char *vars, uintptr_t *ini, const char *opt,int, int l, int n);
+
+/// Get last fitted formula
+MGL_EXPORT const char *mgl_get_fit(HMGL gr);
+int MGL_EXPORT mgl_get_fit_(uintptr_t *gr, char *out, int len);
+
+/// Make histogram (distribution) of data. This function do not plot data.
+/** Option "value" sets the size of output array (default is mglFitPnts=100). */
+HMDT MGL_EXPORT mgl_hist_x(HMGL gr, HCDT x, HCDT a, const char *opt);
+uintptr_t MGL_EXPORT mgl_hist_x_(uintptr_t* gr, uintptr_t* x, uintptr_t* a, const char *opt,int);
+/// Make histogram (distribution) of data. This function do not plot data.
+/** Option "value" sets the size of output array (default is mglFitPnts=100). */
+HMDT MGL_EXPORT mgl_hist_xy(HMGL gr, HCDT x, HCDT y, HCDT a, const char *opt);
+uintptr_t MGL_EXPORT mgl_hist_xy_(uintptr_t* gr, uintptr_t* x, uintptr_t* y, uintptr_t* a, const char *opt,int);
+/// Make histogram (distribution) of data. This function do not plot data.
+/** Option "value" sets the size of output array (default is mglFitPnts=100). */
+HMDT MGL_EXPORT mgl_hist_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, const char *opt);
+uintptr_t MGL_EXPORT mgl_hist_xyz_(uintptr_t* gr, uintptr_t* x, uintptr_t* y, uintptr_t* z, uintptr_t* a, const char *opt,int);
+
+/// Print fitted last formula (with coefficients)
+void MGL_EXPORT mgl_puts_fit(HMGL gr, double x, double y, double z, const char *prefix, const char *font, double size);
+void MGL_EXPORT mgl_puts_fit_(uintptr_t* gr, mreal *x, mreal *y, mreal *z, const char *prefix, const char *font, mreal *size, int l, int n);
+/// Get chi for last fitted formula
+mreal MGL_EXPORT mgl_get_fit_chi();
+mreal MGL_EXPORT mgl_get_fit_chi_();
+/// Get covariance matrix for last fitted formula
+HCDT MGL_EXPORT mgl_get_fit_covar();
+uintptr_t MGL_EXPORT mgl_get_fit_covar_();
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+}
+#endif
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/fltk.h b/include/mgl2/fltk.h
new file mode 100644
index 0000000..9d4a223
--- /dev/null
+++ b/include/mgl2/fltk.h
@@ -0,0 +1,71 @@
+/***************************************************************************
+ * fltk.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_FLTK_H_
+#define _MGL_FLTK_H_
+
+#include <mgl2/abstract.h>
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+extern "C" {
+#endif
+/// Creates FLTK window for plotting
+HMGL MGL_EXPORT mgl_create_graph_fltk(int (*draw)(HMGL gr, void *p), const char *title, void *par, void (*load)(void *p));
+uintptr_t MGL_EXPORT mgl_create_graph_fltk_(const char *title, int);
+/// Run main FLTK loop for event handling.
+int MGL_EXPORT mgl_fltk_run();
+int MGL_EXPORT mgl_fltk_run_();
+/// Run main FLTK loop for event handling in separate thread.
+int MGL_EXPORT mgl_fltk_thr();
+/// Callback function for asking user.
+void MGL_EXPORT mgl_ask_fltk(const wchar_t *quest, wchar_t *res);
+/// Return pointer to widget (Fl_MGLView*) used for plotting
+MGL_EXPORT void *mgl_fltk_widget(HMGL gr);
+#ifdef __cplusplus
+}
+//-----------------------------------------------------------------------------
+#include <mgl2/wnd.h>
+//-----------------------------------------------------------------------------
+/// Wrapper class for windows displaying graphics
+class MGL_EXPORT mglFLTK : public mglWnd
+{
+	mglFLTK(const mglFLTK &) {}	// copying is not allowed
+	const mglFLTK &operator=(const mglFLTK &t)	{	return t;	}
+public:
+	mglFLTK(const char *title="MathGL") : mglWnd()
+	{	gr = mgl_create_graph_fltk(0,title,0,0);	}
+	mglFLTK(int (*draw)(HMGL gr, void *p), const char *title="MathGL", void *par=NULL, void (*load)(void *p)=0) : mglWnd()
+	{	gr = mgl_create_graph_fltk(draw,title,par,load);	}
+	mglFLTK(int (*draw)(mglGraph *gr), const char *title="MathGL") : mglWnd()
+	{	gr = mgl_create_graph_fltk(draw?mgl_draw_graph:0,title,(void*)draw,0);	}
+	mglFLTK(mglDraw *draw, const char *title="MathGL") : mglWnd()
+	{	gr = mgl_create_graph_fltk(draw?mgl_draw_class:0,title,draw,mgl_reload_class);
+#if MGL_HAVE_PTHR_WIDGET
+		mgl_wnd_set_mutex(gr, &(draw->mutex));
+#endif
+		mgl_set_click_func(gr, mgl_click_class);	}
+    virtual ~mglFLTK() {}
+	int Run()	{	return mgl_fltk_run();	}	///< Run main loop for event handling
+	int RunThr()	{	return mgl_fltk_thr();	}	///< Run main loop for event handling in separate thread
+	/// Return pointer to widget (Fl_MGLView*) used for plotting
+	void *Widget()	{	return mgl_fltk_widget(gr);	}
+};
+//-----------------------------------------------------------------------------
+#endif
+#endif
diff --git a/include/mgl2/font.h b/include/mgl2/font.h
new file mode 100644
index 0000000..1c97868
--- /dev/null
+++ b/include/mgl2/font.h
@@ -0,0 +1,144 @@
+/***************************************************************************
+ * font.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+//-----------------------------------------------------------------------------
+#ifndef _MGL_FONT_H_
+#define _MGL_FONT_H_
+
+#include "mgl2/define.h"
+//-----------------------------------------------------------------------------
+#define MGL_FONT_BOLD		0x01000000	// This value is used binary
+#define MGL_FONT_ITAL		0x02000000	// This value is used binary
+#define MGL_FONT_BOLD_ITAL	0x03000000
+#define MGL_FONT_WIRE		0x04000000
+#define MGL_FONT_OLINE		0x08000000	// This value is used binary
+#define MGL_FONT_ULINE		0x10000000
+#define MGL_FONT_ZEROW		0x20000000	// internal codes
+#define MGL_FONT_UPPER		0x40000000
+#define MGL_FONT_LOWER		0x80000000
+#define MGL_FONT_ROMAN		0xfcffffff
+#define MGL_FONT_MASK		0x00ffffff
+#define MGL_COLOR_MASK		0xffffff00
+#define MGL_FONT_STYLE		0x3f000000
+//-----------------------------------------------------------------------------
+struct mglGlyphDescr
+{
+	wchar_t id;		///< Unicode ID for glyph
+	int tr[4];		///< Shift of glyph description by triangles (for solid font)
+	int ln[4];		///< Shift of glyph description by lines (for wire font)
+	short numt[4];	///< Number of triangles in glyph description (for solid font)
+	short numl[4];	///< Number of lines in glyph description (for wire font)
+	short width[4];	///< Width of glyph for wire font
+	mglGlyphDescr()	{	memset(this,0,sizeof(mglGlyphDescr));	}
+};
+inline bool operator<(const mglGlyphDescr &a,const mglGlyphDescr &b)	{	return a.id<b.id;	}
+inline bool operator>(const mglGlyphDescr &a,const mglGlyphDescr &b)	{	return a.id>b.id;	}
+#if defined(_MSC_VER)
+template class MGL_EXPORT std::vector<mglGlyphDescr>;
+#endif
+//-----------------------------------------------------------------------------
+extern const float mgl_fact;
+struct MGL_EXPORT mglTeXsymb	{	unsigned kod;	const wchar_t *tex;	};
+const float mgl_fgen = 4*14;
+/// Get font color, style and align for internal parser
+bool MGL_EXPORT mglGetStyle(const char *how, int *font, int *align=0);
+long MGL_EXPORT mgl_internal_code(unsigned s, const std::vector<mglGlyphDescr> &glyphs);
+class mglBase;
+//-----------------------------------------------------------------------------
+/// Class for font typeface and text plotting procedures
+class MGL_EXPORT mglFont
+{
+public:
+	mglBase *gr;	///< mglBase class used for drawing characters
+	mglFont(const char *name=0, const char *path=0);
+	virtual ~mglFont();
+	bool parse;		///< Parse LaTeX symbols
+
+	/// Load font data to memory. Normally used by constructor.
+	bool Load(const char *base, const char *path=0);
+	/// Load binary font data to memory. Normally used by constructor.
+	bool LoadBin(const char *base, const char *path=0);
+	/// Save binary font data
+	size_t SaveBin(const char *fname);
+	/// Free memory
+	void Clear();
+	/// Copy data from other font
+	void Copy(mglFont *);
+	/// Restore default font
+	void Restore();
+	/// Return true if font is loaded
+	inline bool Ready() const	{	return GetNumGlyph()!=0;	}
+
+	/// Get height of text
+	float Height(int font) const MGL_FUNC_PURE;
+	/// Get height of text
+	float Height(const char *how) const MGL_FUNC_PURE;
+	/// Print text string for font specified by string
+	float Puts(const char *str,const char *how,float c1,float c2) const;
+	/// Get width of text string for font specified by string
+	float Width(const char *str,const char *how) const;
+	/// Print text string for font specified by string
+	float Puts(const wchar_t *str,const char *how,float c1,float c2) const;
+	/// Get width of text string for font specified by string
+	float Width(const wchar_t *str,const char *how) const;
+
+	/// Get internal code for symbol
+	inline long Internal(unsigned s) const	{	return mgl_internal_code(s,glyphs);	}
+	/// Return number of glyphs
+	inline unsigned GetNumGlyph() const	{	return glyphs.size();	};
+	/// Return some of pointers
+	inline const short *GetTr(int s, long j) const	{	return Buf+glyphs[j].tr[s];	}
+	inline const short *GetLn(int s, long j) const	{	return Buf+glyphs[j].ln[s];	}
+	inline int GetNt(int s, long j) const		{	return glyphs[j].numt[s];	}
+	inline int GetNl(int s, long j) const		{	return glyphs[j].numl[s];	}
+	inline short GetWidth(int s, long j) const	{	return glyphs[j].width[s];	}
+	inline float GetFact(int s) const			{	return fact[s];	}
+	inline wchar_t GetUnicode(long j) const		{	return j>=0?glyphs[j].id:0;	}
+protected:
+	std::vector<mglGlyphDescr> glyphs;	///< information about know glyphs
+	float fact[4];	///< Divider for width of glyph
+	short *Buf;		///< Buffer for glyph descriptions
+	size_t numb;		///< Buffer size
+
+	/// Print text string for font specified by integer constant
+	float Puts(const wchar_t *str,int font,int align, float c1,float c2) const;
+	/// Get width of text string for font specified by integer constant
+	float Width(const wchar_t *str,int font=0) const;
+	/// Replace TeX symbols by its UTF code and add font styles
+	void Convert(const wchar_t *str, unsigned *res) const;
+
+	/// Draw string recursively
+	/* x,y - position, f - factor, style: 0x1 - italic, 0x2 - bold, 0x4 - overline, 0x8 - underline, 0x10 - empty (not draw) */
+	float Puts(const unsigned *str, float x,float y,float f,int style,float c1,float c2) const;
+	/// Parse LaTeX command
+	unsigned Parse(const wchar_t *s) const;
+	/// Get symbol for character ch with given font style
+	unsigned Symbol(char ch) const MGL_FUNC_PURE;
+private:
+	float get_ptr(long &i,unsigned *str, unsigned **b1, unsigned **b2,float &w1,float &w2, float f1, float f2, int st) const;
+	bool read_data(const char *fname, int s, std::vector<short> &buf, std::vector<mglGlyphDescr> &extra);
+	void main_copy();
+	bool read_main(const char *fname, std::vector<short> &buf);
+	inline void mem_alloc(long numg)	{	glyphs.resize(numg);	}
+	bool read_def();
+	void draw_ouline(int st, float x, float y, float f, float g, float ww, float ccol) const;
+};
+//-----------------------------------------------------------------------------
+#endif
+//-----------------------------------------------------------------------------
diff --git a/include/mgl2/glut.h b/include/mgl2/glut.h
new file mode 100644
index 0000000..83c345c
--- /dev/null
+++ b/include/mgl2/glut.h
@@ -0,0 +1,85 @@
+/***************************************************************************
+ * glut.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+//-----------------------------------------------------------------------------
+#ifndef _MGL_GLUT_H_
+#define _MGL_GLUT_H_
+#ifdef __cplusplus
+#include <mgl2/wnd.h>
+//-----------------------------------------------------------------------------
+extern "C" {
+#endif
+void _mgl_key_up(unsigned char ch,int ,int );
+HMGL MGL_EXPORT mgl_create_graph_glut(int (*draw)(HMGL gr, void *p), const char *title, void *par, void (*load)(void *p));
+
+
+/// Switch on/off transparency (do not overwrite user settings)
+void MGL_EXPORT mgl_glut_toggle_alpha(HMGL gr);
+/// Switch on/off lighting (do not overwrite user settings)
+void MGL_EXPORT mgl_glut_toggle_light(HMGL gr);
+/// Switch off all zooming and rotation
+void MGL_EXPORT mgl_glut_toggle_no(HMGL gr);
+/// Update picture by calling user drawing function
+void MGL_EXPORT mgl_glut_update(HMGL gr);
+/// Reload user data and update picture
+void MGL_EXPORT mgl_glut_reload(HMGL gr);
+/// Show next frame (if one)
+void MGL_EXPORT mgl_glut_next_frame(HMGL gr);
+/// Show previous frame (if one)
+void MGL_EXPORT mgl_glut_prev_frame(HMGL gr);
+/// Run slideshow (animation) of frames
+void MGL_EXPORT mgl_glut_animation(HMGL gr);
+
+#ifdef __cplusplus
+}
+//-----------------------------------------------------------------------------
+class MGL_EXPORT mglGLUT: public mglGraph
+{
+	mglGLUT(const mglGLUT &) {}	// copying is not allowed
+	const mglGLUT &operator=(const mglGLUT &t)	{	return t;	}
+public:
+	mglGLUT(int (*draw)(HMGL gr, void *p), const char *title="MathGL", void *par=0, void (*load)(void *p)=0) : mglGraph(-1)
+	{	gr = mgl_create_graph_glut(draw,title,par,load);	}
+	mglGLUT(int (*draw)(mglGraph *gr), const char *title="MathGL") : mglGraph(-1)
+	{	gr = mgl_create_graph_glut(draw?mgl_draw_graph:0,title,(void*)draw,0);	}
+	mglGLUT(mglDraw *draw=0, const char *title="MathGL") : mglGraph(-1)
+	{	gr = mgl_create_graph_glut(draw?mgl_draw_class:0,title,draw,mgl_reload_class);	}
+    virtual ~mglGLUT() {}
+
+	inline void ToggleAlpha()	///< Switch on/off transparency (do not overwrite user settings)
+	{	mgl_glut_toggle_alpha(gr);	}
+	inline void ToggleLight()	///< Switch on/off lighting (do not overwrite user settings)
+	{	mgl_glut_toggle_light(gr);	}
+	inline void ToggleNo()		///< Switch off all zooming and rotation
+	{	mgl_glut_toggle_no(gr);	}
+	inline void Update()		///< Update picture by calling user drawing function
+	{	mgl_glut_update(gr);	}
+	inline void ReLoad()		///< Reload user data and update picture
+	{	mgl_glut_reload(gr);	}
+	inline void NextFrame()		///< Show next frame (if one)
+	{	mgl_glut_next_frame(gr);	}
+	inline void PrevFrame()		///< Show previous frame (if one)
+	{	mgl_glut_prev_frame(gr);	}
+	inline void Animation()		///< Run slideshow (animation) of frames
+	{	mgl_glut_animation(gr);	}
+	inline int Run() {return 0;};		///< Run main loop for event handling (placed for similarity to mglWnd)
+};
+//-----------------------------------------------------------------------------
+#endif
+#endif
diff --git a/include/mgl2/gsl.fs b/include/mgl2/gsl.fs
new file mode 100644
index 0000000..5681829
--- /dev/null
+++ b/include/mgl2/gsl.fs
@@ -0,0 +1,1276 @@
+\ GNU Scientific Library interface              Mon Sep 12 14:40:15 MDT 2005
+\ Copyright (C) 2007, Sergey Plis
+\
+\ 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.
+
+\needs float    import float
+warning off
+\needs locals|  include locals.fs
+warning on
+\needs atlas    include atlas.fs
+\needs callback include callback.fs
+\needs vectors  include vectors.fs
+\needs complex  include complex.fb
+
+Module GSL
+
+\ stole the hash function from hash.fs of bigforth
+| &14 Value Hashbits
+| 1 Hashbits << Value Hashlen
+
+Label (hash ( SI:string -- AX:key )  :R  DX push
+      .b lods  $1F # AX and  AX CX mov  DX DX xor  CX 1 # shr
+      b IF  SI ) AH mov  SI inc  THEN  CX dec
+      0>= IF  BEGIN  .w SI ) DX mov  2 # SI add  CX dec
+                     DX AX *2 I) AX lea  0< UNTIL  THEN
+      & Hashbits A#) CX mov  AX DX mov  AX shr  DX AX add
+      & Hashlen  A#) CX mov  CX dec  CX AX and  DX pop  ret
+| Code Hash ( string -- key )
+       R: SI push  AX SI mov  (hash rel) call  SI pop
+    Next end-code
+
+also dos also complex also float also atlas also vectors
+
+s" libptcblas.so" getlib 0<>
+[IF]
+    library libblas libptcblas.so depends libatlas
+[ELSE]
+    library libblas libcblas.so depends libatlas
+[THEN]
+
+library libgsl libgsl.so.0 depends libblas
+
+legacy off
+
+\ some functions
+libgsl gsl_log1p df (fp) gsl_log1p ( df -- df )
+libgsl gsl_acosh df (fp) gsl_acosh ( df -- df )
+
+\ error handling                         Wed Sep 21 23:04:06 MDT 2005
+libgsl gsl_set_error_handler ptr (int) gsl_set_error_handler
+( function -- function )
+libgsl gsl_strerror int (ptr) gsl_strerror
+
+callback 4:0 (void) int int int int callback;
+: cstr-fstr ( addr -- addr len )
+    0
+    begin 2dup + c@ 0 = not while
+            1+
+    repeat ;
+
+| : .bold-red ." " ;
+| : .red ." " ;
+| : .reset    ." " ;
+| : cb-test
+    cr
+    \ .bold-red
+    ." GSL ERROR: " cr
+    \ .reset cr
+    10 spaces gsl_strerror cstr-fstr type cr 
+    drop \    ." at line: " . cr
+    drop \    ." of file: " cstr-fstr type cr
+    10 spaces cstr-fstr type cr
+    \ .red
+    -1 abort" failed at" ;
+' cb-test 4:0 c_plus
+
+\ 1 2 c_plus 2:1call .
+| variable old_handler
+c_plus gsl_set_error_handler old_handler !
+
+0 Constant GSL_SUCCESS
+
+\ random number generation               Mon Sep 12 22:06:01 MDT 2005
+
+libgsl gsl_rng_types_setup (ptr) gsl_rng_types_setup ( -- *gsl_rng_type)
+libgsl gsl_rng_env_setup (ptr) gsl_rng_env_setup ( -- *gsl_rng)
+libgsl gsl_rng_alloc int (int) gsl_rng_alloc ( *gsl_rng_type -- *gsl_rng )
+libgsl gsl_rng_name int (int) gsl_rng_name ( *gsl_rng -- string )
+libgsl gsl_rng_set int int (void) gsl_rng_set ( *gsl_rng int -- )
+libgsl gsl_rng_uniform int (fp) gsl_rng_uniform ( *gsl_rng -- df )
+libgsl gsl_rng_uniform_pos int (fp) gsl_rng_uniform_pos ( *gsl_rng -- df )
+libgsl gsl_rng_uniform_int int int (int) gsl_rng_uniform_int ( *gsl_rng n --n )
+libgsl gsl_rng_get int (int) gsl_rng_get ( *gsl_rng -- int )
+libgsl gsl_rng_max int (int) gsl_rng_max ( *gsl_rng -- int )
+libgsl gsl_rng_min int (int) gsl_rng_min ( *gsl_rng -- int )
+libgsl gsl_rng_clone int (int) gsl_rng_clone ( *gsl_rng -- *gsl_rng )
+libgsl gsl_rng_free int (int) gsl_rng_free ( *gsl_rng -- )
+
+
+
+\ random number distributions                     Tue Sep 13 00:44:35 MDT 2005
+\ Gaussian
+libgsl gsl_ran_gaussian df int (fp) gsl_ran_gaussian ( *gsl_rng df -- df )
+libgsl gsl_ran_gaussian_ratio_method df int (fp) gsl_ran_gaussian_ratio_method ( *gsl_rng df -- df )
+libgsl gsl_ran_gaussian_pdf df df (fp) gsl_ran_gaussian_pdf ( df df -- df )
+\ sigma = 1
+libgsl gsl_ran_ugaussian int (fp) gsl_ran_ugaussian ( *gsl_rng -- df )
+libgsl gsl_ran_ugaussian_ratio_method int (fp) gsl_ran_ugaussian_ratio_method ( *gsl_rng -- df )
+libgsl gsl_ran_ugaussian_pdf df (fp) gsl_ran_ugaussian_pdf ( df df -- df )
+libgsl gsl_ran_discrete_preproc int int (int) gsl_ran_discrete_preproc ( int int -- int )
+libgsl gsl_ran_discrete int int (int) gsl_ran_discrete
+libgsl gsl_ran_discrete_free int (void) gsl_ran_discrete_free
+libgsl gsl_ran_shuffle int int ptr ptr (void) gsl_ran_shuffle
+\ cdf P(x) = \int_{-\infty}^{x} p(x)dx  Q(x) = \int_{x}^{\infty} p(x)dx
+libgsl gsl_cdf_gaussian_P df df (fp) gsl_cdf_gaussian_P ( df df -- df )
+libgsl gsl_cdf_gaussian_Q df df (fp) gsl_cdf_gaussian_Q ( df df -- df )
+libgsl gsl_cdf_gaussian_Pinv df df (fp) gsl_cdf_gaussian_Pinv ( df df -- df )
+libgsl gsl_cdf_gaussian_Qinv df df (fp) gsl_cdf_gaussian_Qinv ( df df -- df )
+\ sigma = 1 cdf
+libgsl gsl_cdf_ugaussian_P df (fp) gsl_cdf_ugaussian_P ( df -- df )
+libgsl gsl_cdf_ugaussian_Q df (fp) gsl_cdf_ugaussian_Q ( df -- df )
+libgsl gsl_cdf_ugaussian_Pinv df (fp) gsl_cdf_ugaussian_Pinv ( df -- df )
+libgsl gsl_cdf_ugaussian_Qinv df (fp) gsl_cdf_ugaussian_Qinv ( df -- df )
+
+
+\ statistics                                      Tue Sep 13 01:17:35 MDT 2005
+libgsl gsl_stats_mean int int int (fp) gsl_stats_mean ( array{ step size -- df )
+libgsl gsl_stats_variance int int int (fp) gsl_stats_variance ( array{ step size -- df )
+libgsl gsl_stats_variance_m df int int int (fp) gsl_stats_variance_m ( df array{ step size -- df )
+libgsl gsl_stats_sd int int int (fp) gsl_stats_sd ( array{ step size -- df )
+libgsl gsl_stats_sd_m df int int int (fp) gsl_stats_sd_m ( df array{ step size -- df )
+libgsl gsl_stats_skew int int int (fp) gsl_stats_skew ( array{ step size -- df )
+libgsl gsl_stats_kurtosis int int int (fp) gsl_stats_kurtosis ( array{ step size -- df )
+libgsl gsl_stats_lag1_autocorrelation int int int (fp) gsl_stats_lag1_autocorrelation
+( array{ step size -- df )
+libgsl gsl_stats_max int int int (fp) gsl_stats_max ( array{ step size -- df )
+libgsl gsl_stats_min int int int (fp) gsl_stats_min ( array{ step size -- df )
+libgsl gsl_stats_max_index int int int (int) gsl_stats_max_index ( array{ step size -- n )
+libgsl gsl_stats_min_index int int int (int) gsl_stats_min_index ( array{ step size -- n )
+
+\ vectors and matrices                           Wed Sep 14 00:15:36 MDT 2005
+
+\ Vectors 
+libgsl gsl_block_alloc  int (int) gsl_block_alloc ( n -- addr )
+libgsl gsl_block_calloc int (int) gsl_block_calloc ( n -- addr )
+libgsl gsl_block_free   int (int) gsl_block_free ( n -- addr )
+
+libgsl gsl_vector_alloc             int (int) gsl_vector_alloc ( n -- addr )
+libgsl gsl_vector_calloc            int (int) gsl_vector_calloc ( n -- addr )
+libgsl gsl_vector_alloc_from_vector int int int ptr (int) gsl_vector_alloc_from_vector
+libgsl gsl_vector_free          int (void) gsl_vector_free ( addr -- )
+libgsl gsl_vector_get         int int (fp) gsl_vector_get ( addr i -- df )
+libgsl gsl_vector_set df int int (void/fp) gsl_vector_set ( df addr i --  )
+libgsl gsl_vector_set_all    df int (void) gsl_vector_set_all ( df addr -- )
+libgsl gsl_vector_set_zero      int (void) gsl_vector_set_zero ( addr -- )
+libgsl gsl_vector_memcpy     int int (int) gsl_vector_memcpy ( dest_addr src_addr -- n )
+
+libgsl gsl_vector_add           int int (int) gsl_vector_add          ( addr addr -- n )
+libgsl gsl_vector_sub           int int (int) gsl_vector_sub          ( addr addr -- n )
+libgsl gsl_vector_mul           int int (int) gsl_vector_mul          ( addr addr -- n )
+libgsl gsl_vector_div           int int (int) gsl_vector_div          ( addr addr -- n )
+libgsl gsl_vector_scale          df int (int) gsl_vector_scale        ( df addr -- n )
+libgsl gsl_vector_add_constant   df int (int) gsl_vector_add_constant ( df addr -- n )
+libgsl gsl_vector_max                int (fp) gsl_vector_max          ( addr -- df )
+libgsl gsl_vector_min                int (fp) gsl_vector_min          ( addr -- df )
+libgsl gsl_vector_max_index          int (fp) gsl_vector_max_index    ( addr -- df )
+libgsl gsl_vector_min_index          int (fp) gsl_vector_min_index    ( addr -- df )
+libgsl gsl_vector_subvector int int int (int) gsl_vector_subvector
+\ Vector properties
+libgsl gsl_vector_isnull   ptr         (int) gsl_vector_isnull
+libgsl gsl_vector_ispos    ptr         (int) gsl_vector_ispos
+libgsl gsl_vector_isneg    ptr         (int) gsl_vector_isneg
+
+\ permutations
+libgsl gsl_permutation_alloc   int (int) gsl_permutation_alloc ( n -- *gsl_prm)
+libgsl gsl_permutation_calloc int (int) gsl_permutation_calloc ( n -- *gsl_prm)
+libgsl gsl_permutation_init   int (void) gsl_permutation_init ( *gsl_prm -- )
+libgsl gsl_permutation_free   int (void) gsl_permutation_free ( *gsl_prm -- )
+libgsl gsl_permutation_get int int (int) gsl_permutation_get ( *gsl_prm i -- n)
+
+\ Matrices
+\ Allocation
+libgsl gsl_matrix_alloc               int int (int) gsl_matrix_alloc
+libgsl gsl_matrix_calloc              int int (int) gsl_matrix_calloc
+libgsl gsl_matrix_alloc_from_block [ 5 ] ints (int) gsl_matrix_alloc_from_block
+libgsl gsl_matrix_alloc_from_matrix [ 5 ] ints (int) gsl_matrix_alloc_from_matrix
+libgsl gsl_matrix_free     ( *gsl_matrix -- )      int (void) gsl_matrix_free
+\ Accessing matrix elements
+libgsl gsl_matrix_get      int int int (fp) gsl_matrix_get ( *m i j  -- df )
+libgsl gsl_matrix_set df int int int (void) gsl_matrix_set ( df *m i j  -- )
+libgsl gsl_matrix_ptr     int int int (int) gsl_matrix_ptr ( *m i j  -- *[i,j] )
+\ Initializing matrix elements
+libgsl gsl_matrix_set_all      df int (void) gsl_matrix_set_all      ( *m df -- n )
+libgsl gsl_matrix_set_zero     df int (void) gsl_matrix_set_zero     ( *m df -- n )
+libgsl gsl_matrix_set_identity df int (void) gsl_matrix_set_identity ( *m df -- n )
+\ Reading and writing matrices
+libgsl gsl_matrix_fwrite      ptr ptr (int) gsl_matrix_fwrite
+libgsl gsl_matrix_fread       ptr ptr (int) gsl_matrix_fread
+libgsl gsl_matrix_fprintf ptr ptr ptr (int) gsl_matrix_fprintf
+libgsl gsl_matrix_fscanf      ptr ptr (int) gsl_matrix_fscanf
+\ Copying matrices
+libgsl gsl_matrix_memcpy      int int (int) gsl_matrix_memcpy ( *m *m -- n )
+libgsl gsl_matrix_swap        int int (int) gsl_matrix_swap ( *m *m -- n )
+\ Copying Rows and columns
+libgsl gsl_matrix_get_row int int int (int) gsl_matrix_get_row
+libgsl gsl_matrix_set_row int int int (int) gsl_matrix_set_row
+libgsl gsl_matrix_get_col int int int (int) gsl_matrix_get_col
+libgsl gsl_matrix_set_col int int int (int) gsl_matrix_set_col
+\ Exchanging rows and columns
+libgsl gsl_matrix_swap_rows    int int ptr (int) gsl_matrix_swap_rows
+libgsl gsl_matrix_swap_columns int int ptr (int) gsl_matrix_swap_columns
+libgsl gsl_matrix_swap_rowcol  int int ptr (int) gsl_matrix_swap_rowcol
+libgsl gsl_matrix_transpose_memcpy int int (int) gsl_matrix_transpose_memcpy
+libgsl gsl_matrix_transpose            int (int) gsl_matrix_transpose
+\ Matrix operations
+libgsl gsl_matrix_add          int int (int) gsl_matrix_add
+libgsl gsl_matrix_sub          int int (int) gsl_matrix_sub
+libgsl gsl_matrix_mul_elements int int (int) gsl_matrix_mul_elements
+libgsl gsl_matrix_div_elements int int (int) gsl_matrix_div_elements
+libgsl gsl_matrix_scale         df int (int)  gsl_matrix_scale
+libgsl gsl_matrix_add_constant  df int (int) gsl_matrix_add_constant
+\ Finding maximum and minimum elements of matrices
+libgsl gsl_matrix_max                 ptr (fp) gsl_matrix_max 
+libgsl gsl_matrix_min                 ptr (fp) gsl_matrix_min
+libgsl gsl_matrix_minmax    ptr ptr ptr (void) gsl_matrix_minmax
+libgsl gsl_matrix_min_index ptr ptr ptr (void) gsl_matrix_min_index
+libgsl gsl_matrix_max_index ptr ptr ptr (void) gsl_matrix_max_index
+libgsl gsl_matrix_minmax_index ptr ptr ptr ptr ptr (void) gsl_matrix_minmax_index
+\ Matrix properties
+libgsl gsl_matrix_isnull   ptr         (int) gsl_matrix_isnull
+libgsl gsl_matrix_ispos    ptr         (int) gsl_matrix_ispos
+libgsl gsl_matrix_isneg    ptr         (int) gsl_matrix_isneg
+\ libgsl gsl_matrix_isnonneg ptr         (int) gsl_matrix_isnonneg
+
+
+libgsl gsl_matrix_submatrix int int int int int (int) gsl_matrix_submatrix ( *gsl_matrix k1 k2 n1 n2 -- n )
+libgsl gsl_matrix_row int int (int) gsl_matrix_row ( *gsl_matrix idx -- *gsl_vector )
+libgsl gsl_matrix_column int int (int) gsl_matrix_column ( *gsl_matrix idx -- *gsl_vector )
+libgsl gsl_matrix_diagonal int (int) gsl_matrix_diagonal ( *gsl_matrix -- *gsl_vector )
+
+
+\ BLAS                                      Wed Sep 14 16:10:34 MDT 2005
+\ libblas cblas_dgemm int int df int int int
+\ int df int int int int int int (void/fp) cblas_dgemm
+libblas cblas_dgemv int int int int df int
+int df int int int int (void/fp) cblas_dgemv
+libgsl gsl_blas_ddot int int int (int) gsl_blas_ddot
+( *gsl_vector *gsl_vector df -- n )
+libgsl gsl_blas_dgemm int df int int df int int (int/fp) gsl_blas_dgemm
+libgsl gsl_blas_dger int int int df (int/fp) gsl_blas_dger
+( alpha *gsl_vector *gsl_vector *gsl_matrix -- n ) ( A=\alpha x y^T+A )
+libgsl gsl_blas_dgemv int df int int df int (int/fp) gsl_blas_dgemv
+( n alpha *gsl_matrix *gsl_vector beta *gsl_vector -- n )
+
+\ Linear ALgebra                            Wed Sep 14 13:39:22 MDT 2005
+
+libgsl gsl_linalg_LU_decomp int int int (int) gsl_linalg_LU_decomp
+( *gsl_matrix *gsl_permutation *variable -- n )
+libgsl gsl_linalg_LU_invert int int int (int) gsl_linalg_LU_invert
+( *gsl_matrix *gsl_permutation *gsl_matrix -- n )
+libgsl gsl_linalg_SV_decomp int int int int (int) gsl_linalg_SV_decomp
+( *gsl_matrix *gsl_matrix *gsl_vector *gsl_vector -- n )
+libgsl gsl_linalg_SV_decomp_mod int int int int int (int) gsl_linalg_SV_decomp_mod
+( *gsl_matrix *gsl_matrix *gsl_matrix *gsl_vector *gsl_vector -- n )
+
+\ -----------------------------------------------------------------------------
+\                  *** Ordinary Differential Equations ***
+\ --- ODE system
+struct{
+    cell func \ (* function)
+        \ (double t, const double y[], double dydt[], void * params);
+    cell jac \ (* jacobian)
+        \ (double t, const double y[], double * dfdy, double dfdt[],
+        \ void * params);
+    cell dim \ dimension;
+    cell params \ * params;
+} gsl_odeiv_system
+\ constants related to ODE
+ 1 constant GSL_ODEIV_HADJ_INC
+ 0 constant GSL_ODEIV_HADJ_NIL
+-1 constant GSL_ODEIV_HADJ_DEC
+
+callback gsl_odeiv_func4:1     (int) df int int int callback;
+callback gsl_odeiv_jac5:1  (int) df int int int int callback;
+
+\ --- Stepping Functions
+libgsl gsl_odeiv_step_alloc ptr int (ptr) gsl_odeiv_step_alloc
+( *step_type int -- *step )
+libgsl gsl_odeiv_step_reset ptr (int) gsl_odeiv_step_reset ( *step -- r )
+libgsl gsl_odeiv_step_free ptr (void) gsl_odeiv_step_free  ( *step  -- )
+libgsl gsl_odeiv_step_name ptr (ptr) gsl_odeiv_step_name   ( *step -- *str0 )
+libgsl gsl_odeiv_step_order ptr (int) gsl_odeiv_step_order ( *step -- order)
+libgsl gsl_odeiv_step_apply int int int int int df df int (int) gsl_odeiv_step_apply
+( -- )
+\ --- Available algorithms
+libgsl _gsl_odeiv_step_rk2    (int)    gsl_odeiv_step_rk2
+libgsl _gsl_odeiv_step_rk4    (int)    gsl_odeiv_step_rk4
+libgsl _gsl_odeiv_step_rkf45  (int)  gsl_odeiv_step_rkf45
+libgsl _gsl_odeiv_step_rkck   (int)   gsl_odeiv_step_rkck
+libgsl _gsl_odeiv_step_rk8pd  (int)  gsl_odeiv_step_rk8pd
+libgsl _gsl_odeiv_step_rk2imp (int) gsl_odeiv_step_rk2imp
+libgsl _gsl_odeiv_step_rk4imp (int) gsl_odeiv_step_rk4imp
+libgsl _gsl_odeiv_step_bsimp  (int)  gsl_odeiv_step_bsimp
+libgsl _gsl_odeiv_step_gear1  (int)  gsl_odeiv_step_gear1
+libgsl _gsl_odeiv_step_gear2  (int)  gsl_odeiv_step_gear2
+
+: gsl_odeiv_step_rk2    [func']    _gsl_odeiv_step_rk2 @ ;
+: gsl_odeiv_step_rk4    [func']    _gsl_odeiv_step_rk4 @ ;
+: gsl_odeiv_step_rkf45  [func']  _gsl_odeiv_step_rkf45 @ ;
+: gsl_odeiv_step_rkck   [func']   _gsl_odeiv_step_rkck @ ;
+: gsl_odeiv_step_rk8pd  [func']  _gsl_odeiv_step_rk8pd @ ;
+: gsl_odeiv_step_rk2imp [func'] _gsl_odeiv_step_rk2imp @ ;
+: gsl_odeiv_step_rk4imp [func'] _gsl_odeiv_step_rk4imp @ ;
+: gsl_odeiv_step_bsimp  [func']  _gsl_odeiv_step_bsimp @ ;
+: gsl_odeiv_step_gear1  [func']  _gsl_odeiv_step_gear1 @ ;
+: gsl_odeiv_step_gear2  [func']  _gsl_odeiv_step_gear2 @ ;
+
+\ --- Adaptive Step-size Control
+libgsl gsl_odeiv_control_standard_new df df df df (ptr) gsl_odeiv_control_standard_new ( a_dydt a_y eps_rel eps_abs -- *control )
+libgsl gsl_odeiv_control_y_new df df (int) gsl_odeiv_control_y_new
+( eps_abs eps_rel -- *control )
+libgsl gsl_odeiv_control_yp_new df df (ptr) gsl_odeiv_control_yp_new
+( eps_abs eps_rel -- *control )
+libgsl gsl_odeiv_control_free ptr (void) gsl_odeiv_control_free ( *control -- )
+libgsl gsl_odeiv_control_name ptr (ptr) gsl_odeiv_control_name  ( *c -- *str0 )
+
+\ --- Evolution
+libgsl gsl_odeiv_evolve_alloc int (int) gsl_odeiv_evolve_alloc
+( #dimensions -- evolution_func )
+libgsl gsl_odeiv_evolve_apply int int df int int int int int (int) gsl_odeiv_evolve_apply
+( -- )
+libgsl gsl_odeiv_evolve_reset ptr (int) gsl_odeiv_evolve_reset ( *e -- r )
+libgsl gsl_odeiv_evolve_free ptr (void) gsl_odeiv_evolve_free  ( *e --  )
+\ -----------------------------------------------------------------------------
+\                     *** Fast Fourier Transform ***
+\ -- real
+libgsl gsl_fft_real_wavetable_alloc int (ptr) gsl_fft_real_wavetable_alloc
+libgsl gsl_fft_real_wavetable_free  ptr (void) gsl_fft_real_wavetable_free
+libgsl gsl_fft_real_workspace_alloc int (ptr) gsl_fft_real_workspace_alloc
+libgsl gsl_fft_real_workspace_free  ptr (void) gsl_fft_real_workspace_free
+\ in-place
+libgsl gsl_fft_real_transform ptr int int ptr ptr (int) gsl_fft_real_transform
+libgsl gsl_fft_real_unpack    ptr ptr int int (int) gsl_fft_real_unpack
+
+\ -- halfcomplex
+\ - mixed radix
+libgsl gsl_fft_hc_wtbl_alloc int (ptr) gsl_fft_halfcomplex_wavetable_alloc
+libgsl gsl_fft_hc_wtbl_free  ptr (void) gsl_fft_halfcomplex_wavetable_free
+libgsl gsl_fft_hc_backward   ptr int int ptr ptr (int) gsl_fft_halfcomplex_backward
+libgsl gsl_fft_hc_inverse    ptr int int ptr ptr (int) gsl_fft_halfcomplex_inverse
+libgsl gsl_fft_hc_transform  ptr int int ptr ptr (int) gsl_fft_halfcomplex_transform
+libgsl gsl_fft_hc_unpack     ptr ptr int int (int) gsl_fft_halfcomplex_unpack
+\ - radix2
+libgsl gsl_fft_hc_r2_unpack    ptr ptr int int (int) gsl_fft_halfcomplex_radix2_unpack
+libgsl gsl_fft_hc_r2_backward  ptr int int (int) gsl_fft_halfcomplex_radix2_backward
+libgsl gsl_fft_hc_r2_inverse   ptr int int (int) gsl_fft_halfcomplex_radix2_inverse
+libgsl gsl_fft_hc_r2_transform ptr int int (int) gsl_fft_halfcomplex_radix2_transform
+
+
+| hashlen 32 vector fftpre(
+struct{
+    cell next
+    cell size
+    cell workspace
+    cell r_wavetable
+    cell hc_wavetable
+} gsl_fft_precomputes
+| create $buf 255 allot
+| : 2str dup >r abs s>d <# #s r> sign #> $buf 0place ;
+| : s>hash ( n -- key ) 2str $buf hash ;
+| : (cache-fft) ( n -- addr )
+    sizeof gsl_fft_precomputes allocate throw >r
+    0 r@ gsl_fft_precomputes next !
+    dup r@ gsl_fft_precomputes size !
+    dup gsl_fft_real_workspace_alloc r@ gsl_fft_precomputes workspace !
+    dup gsl_fft_real_wavetable_alloc r@ gsl_fft_precomputes r_wavetable !
+        gsl_fft_hc_wtbl_alloc r@ gsl_fft_precomputes hc_wavetable !
+    r> ;
+| : cache-fft ( size -- addr )
+    dup s>hash
+    fftpre( over )@ 0= if
+        swap (cache-fft)
+        fftpre( rot dup >r )!
+        fftpre( r> )@   
+    else
+        swap (cache-fft)
+        swap fftpre( over )@
+        over gsl_fft_precomputes next !
+        fftpre( rot dup >r )!
+        fftpre( r> )@
+    then ;
+\ in case not found addr is just the size
+| : find-fft-cache ( n -- addr 0/1 )
+    dup s>hash fftpre( swap )@ dup
+    begin while
+            2dup gsl_fft_precomputes size @ =
+            if nip true exit then
+            gsl_fft_precomputes next @ dup
+    repeat ;
+
+legacy on
+
+\ Structures
+
+struct{
+    cell name
+    cell max
+    cell min
+    cell size
+    cell set
+    cell get
+    cell get_double
+} gsl_rng_type
+
+struct{
+    cell type
+    cell state
+} gsl_rng
+
+struct{
+    cell size
+    cell data
+} gsl_block
+
+struct{
+    cell size
+    cell stride
+    cell data
+    cell block
+    cell owner
+} gsl_vector
+
+' gsl_block alias gsl_permutation
+
+struct{
+    cell size1
+    cell size2
+    cell tda
+    cell data
+    cell block
+    cell owner
+} gsl_matrix
+
+\ random number generation functions
+: 0-len dup 1- 0 begin 1+ 2dup + c@ 0= until nip ;
+: )gsl-rng ( addr i -- *gsl_rng_type )
+    cells + @ ;
+
+\ setting up all available random number generators
+gsl_rng_types_setup  value gsl_rng_array(
+0 value gsl_rng_default
+: gsl-free ( -- )
+    gsl_rng_default gsl_rng_free ;
+
+: borosh13 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 0 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: cmrg ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 1 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: coveyou ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 2 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: fishman18 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 3 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: fishman20 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 4 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: fishman2x ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 5 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: gfsr4 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 6 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: knuthran ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 7 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: knuthran2 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 8 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: lecuyer21 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 9 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: minstd ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 10 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: mrg ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 11 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: mt19937 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 12 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: mt19937_1999 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 13 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: mt19937_1998 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 14 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: r250 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 15 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: ran0 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 16 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: ran1 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 17 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: ran2 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 18 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: ran3 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 19 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: rand ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 20 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: rand48 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 21 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: random128-bsd ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 22 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: random128-glibc2 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 23 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: random128-libc5 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 24 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: random256-bsd ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 25 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: random256-glibc2 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 26 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: random256-libc5 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 27 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: random32-bsd ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 28 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: random32-glibc2 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 29 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: random32-libc5 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 30 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: random64-bsd ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 31 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: random64-glibc2 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 32 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: random64-libc5 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 33 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: random8-bsd ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 34 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: random8-glibc2 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 35 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: random8-libc5 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 36 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: random-bsd ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 37 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: random-glibc2 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 38 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: random-libc5 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 39 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: randu ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 40 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: ranf ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 41 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: ranlux ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 42 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: ranlux389 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 43 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: ranlxd1 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 44 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: ranlxd2 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 45 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: ranlxs0 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 46 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: ranlxs1 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 47 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: ranlxs2 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 48 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: ranmar ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 49 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: slatec ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 50 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: taus ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 51 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: taus2 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 52 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: taus113 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 53 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: transputer ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 54 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: tt800 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 55 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: uni ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 56 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: uni32 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 57 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: vax ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 58 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: waterman14 ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 59 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+: zuf ( -- *gsl_rng ) gsl_rng_default 0<> if gsl-free then 
+    gsl_rng_array( 60 )gsl-rng gsl_rng_alloc to gsl_rng_default ;
+
+\ words for actual generation of random numbers
+: gsl-randomg ( -- n )
+    gsl_rng_default gsl_rng_get ;
+: gsl-randomu /* -- f \in [0,1) */
+    gsl_rng_default gsl_rng_uniform ;
+: gsl-randomu+ /* -- f \in (0,1) */
+    gsl_rng_default gsl_rng_uniform_pos ;
+: gsl-random-up ( n -- f \in [0,n] )
+    gsl_rng_default swap gsl_rng_uniform_int ;
+: gsl-set-seed ( n -- )
+    gsl_rng_default swap gsl_rng_set ; 
+: gsl-clone ( -- *gsl_rng )
+    gsl_rng_default gsl_rng_clone ;
+: gsl-gaussian ( -- df )
+    gsl_rng_default !1 gsl_ran_gaussian ;
+: gsl-discrete ( *gsl_ran_discrete -- n )
+    gsl_rng_default swap gsl_ran_discrete ;
+
+\ vectors and matrices
+0 constant GSL_VECTOR_TYPE
+1 constant GSL_MATRIX_TYPE
+: gsltypeof ' >body cell + @ ;
+
+: fvector ( n -- | -- id addr )
+    create    
+    gsl_vector_calloc ,
+    GSL_VECTOR_TYPE ,
+  does> @ ;
+
+\ allocate a nameless vector
+: :] ( # -- addr ) gsl_vector_calloc ;
+\ allocate a nameless matrix
+: :]] ( # # -- addr ) gsl_matrix_calloc ;
+
+: ]@ ( addr i -- df ) gsl_vector_get ;
+: ]! ( df addr i -- ) gsl_vector_set ;
+: ]data ( addr -- *data ) gsl_vector data @ ;
+: ]stride ( addr -- *data ) gsl_vector stride @ ;
+: ]fill ( df addr -- ) gsl_vector_set_all ;
+: ]erase ( addr -- ) gsl_vector_set_zero ;
+: ]+ ( *gsl_vector *gsl_vector -- ) gsl_vector_add drop ;
+: ]- ( *gsl_vector *gsl_vector -- ) gsl_vector_sub drop ;
+: ]e*! ( *gsl_vector *gsl_vector -- ) gsl_vector_mul drop ;
+: ]size ( *gsl_vector -- n ) gsl_vector size @ ;
+: ]outer* ( *gsl_vector *gsl_vector -- *gsl_matrix )
+    over ]size over ]size gsl_matrix_calloc dup >r !1
+    gsl_blas_dger drop r> ;
+\ no control for divizion by zero (I get segfaults)
+: ]/ ( *gsl_vector *gsl_vector -- ) gsl_vector_div throw ;
+: ]clone ( *gsl_vector -- *gsl_vector )
+    dup gsl_vector size @ gsl_vector_alloc
+    dup -rot swap gsl_vector_memcpy drop ;
+
+: ]add ( *gsl_vector *gsl_vector -- *gsl_vector )
+    ]clone dup -rot swap ]+ ;
+: ]sub ( *gsl_vector *gsl_vector -- *gsl_vector )
+    swap ]clone dup -rot swap ]- ;
+: ]mul ( *gsl_vector *gsl_vector -- *gsl_vector )
+    swap ]clone dup -rot swap ]e*! ;
+: ]div ( *gsl_vector *gsl_vector -- *gsl_vector )
+    swap ]clone dup -rot swap ]/ ;
+
+: ]*c ( df *gsl_vector -- ) gsl_vector_scale drop ;
+: ]+c ( df *gsl_vector -- ) gsl_vector_add_constant drop ;
+: ]max ( *gsl_vector -- ) gsl_vector_max ;
+: ]min ( *gsl_vector -- ) gsl_vector_min ;
+: ]imax ( *gsl_vector -- ) gsl_vector_max_index ;
+: ]imin ( *gsl_vector -- ) gsl_vector_min_index ;
+: ]copy] ( *gsl_vector_dest *gsl_vector_src -- ) gsl_vector_memcpy drop ;
+: ]negate !-1.0 ]*c ;
+: ]ones ( n -- *gsl_vector ) :] dup 1e ]fill ;
+
+: ]]slice ( *gsl_matrix x y n m -- *gsl_matrix )
+    gsl_matrix_alloc_from_matrix ;
+: ]slice ( *gsl_vector offset length stride -- *gsl_vector )
+    gsl_vector_alloc_from_vector ;
+
+: ]null? ( *gsl_vector -- 0/-1 ) gsl_vector_isnull negate ;
+: ]pos? ( *gsl_vector -- 0/-1 ) gsl_vector_ispos negate ;
+: ]neg? ( *gsl_vector -- 0/-1 ) gsl_vector_isneg negate ;
+
+\ FFT                                                            19jan08sp
+: ]fft! ( *gsl_vector -- )
+    dup ]size >r dup ]stride >r ]data r> r>
+    dup find-fft-cache if
+        dup gsl_fft_precomputes r_wavetable @
+        swap gsl_fft_precomputes workspace @    
+    else
+        drop
+        dup cache-fft
+        dup gsl_fft_precomputes r_wavetable @
+        swap gsl_fft_precomputes workspace @
+    then    
+    gsl_fft_real_transform throw ;
+: ]fft ( *gsl_vector -- *gsl_vector )
+    ]clone dup ]fft! ;
+: ]ifft! ( *gsl_vector --  )
+    dup ]size >r dup ]stride >r ]data r> r>
+    dup find-fft-cache if
+        dup gsl_fft_precomputes hc_wavetable @
+        swap gsl_fft_precomputes workspace @
+    else
+        drop
+        dup cache-fft
+        dup gsl_fft_precomputes hc_wavetable @
+        swap gsl_fft_precomputes workspace @
+    then    
+    gsl_fft_hc_inverse throw ;
+: ]ifft ( *gsl_vector -- *gsl_vector )
+    ]clone dup ]ifft! ;
+\ multiply two half complex vectors
+\ store result in the first
+: ]hc*! ( *gsl_vector *gsl_vector -- )
+    2dup 0 ]@ 0 ]@ f* over 0 ]!
+    dup ]size dup %1 and not + 1 do
+        2dup
+        dup i ]@ i 1+ ]@
+        dup i ]@ i 1+ ]@ z*
+        over dup i 1+ ]! i ]!
+    2 +loop
+    dup ]size %1 and not if
+        2dup
+        dup ]size 1- dup >r ]@ dup r@ ]@ f* r> ]!
+    then
+    2drop ;
+
+\ pseudomatrices and vectors
+: pvector ( *data n -- *gsl_vector )
+    sizeof gsl_vector allocate throw
+    dup >r dup 1 swap gsl_vector stride !
+    gsl_vector size ! r@
+    gsl_vector data ! r@
+    0 swap gsl_vector owner ! r> ;
+
+: pmatrix! ( *data tda n m *pmatrix -- *gsl_matrix )
+    dup >r gsl_matrix size2 !
+    r@ gsl_matrix size1 !
+    r@ gsl_matrix tda !
+    r@ gsl_matrix data !
+    0 r@ gsl_matrix owner !
+    r> ;
+
+: pmatrix ( *data tda n m -- *gsl_matrix )
+    sizeof gsl_matrix allocate throw
+    dup 0 swap gsl_matrix owner !
+    pmatrix! ;
+
+\ permutations
+
+: fpermutation ( n -- | -- id addr )
+    create
+    gsl_permutation_calloc ,
+  does> @ ;
+: }@ ( *gsl_permutation i -- n ) gsl_permutation_get ;
+: }data ( *gsl_permutation -- *data ) gsl_block data @ ;
+: }size ( *gsl_permutation -- *data ) gsl_block size @ ;
+: }free ( *gsl_permutation -- ) gsl_permutation_free ;
+: }sign ( *gsl_permutation -- 1/-1 )
+    1 over dup }size 0 do
+	dup i }@ i <> if swap negate swap then
+    loop drop ;
+    
+\ matrices
+
+: fmatrix ( n m -- | -- id addr )
+    create
+    gsl_matrix_calloc ,
+    GSL_MATRIX_TYPE ,
+  does> @ ;
+
+: free_pseudomatrix ( pmatrix/pvector -- ) free throw ;
+
+create free_matrix ' free_pseudomatrix , ' gsl_matrix_free ,
+create free_vector ' free_pseudomatrix , ' gsl_vector_free ,
+
+: ]]free ( *gsl_matrix -- )
+    dup gsl_matrix owner @
+    cells free_matrix + @ execute ;
+: ]free ( addr -- )
+    dup gsl_vector owner @
+    cells free_vector + @ execute ;
+: ]]@ ( *gsl_matrix i j -- df ) gsl_matrix_get ;
+: ]]*@ ( *gsl_matrix i j -- *[i,j] ) gsl_matrix_ptr ;
+: ]]! ( *gsl_matrix i j df -- ) gsl_matrix_set ;
+: ]]fill ( addr df -- ) gsl_matrix_set_all ;
+: ]]size1 gsl_matrix size1 @ ;
+: ]]size2 gsl_matrix size2 @ ;
+: ]]dim ( *gsl_matrix -- m n ) dup ]]size1 swap ]]size2 ;
+: ]]dim. ( *gsl_matrix -- ) ]]dim swap . ." x" . cr ;
+: ]]data ( *gsl_matrix -- addr) gsl_matrix data @ ;
+: ]]tda gsl_matrix tda @ ;
+: ]]block gsl_matrix block @ ;
+: ]]owner gsl_matrix owner @ ;
+: ]]copy]] ( *gsl_matrix_dest *gsl_matrix_src -- ) gsl_matrix_memcpy drop ;
+: ]]'copy]] ( *gsl_matrix_dest *gsl_matrix_src -- ) gsl_matrix_transpose_memcpy drop ;
+\ : ]]row ( *gsl_matrix idx -- *gsl_vector ) gsl_matrix_row ;
+\ : ]]col ( *gsl_matrix idx -- *gsl_vector ) gsl_matrix_column ;
+: ]]>]  ( *gsl_vector *gsl_matrix i -- ) gsl_matrix_get_col drop ;
+: ]]>]' ( *gsl_vector *gsl_matrix i -- ) gsl_matrix_get_row drop ;
+: ]>]]  ( *gsl_matrix *gsl_vector i -- ) swap gsl_matrix_set_col drop ;
+: ]'>]] ( *gsl_matrix *gsl_vector i -- ) swap gsl_matrix_set_row drop ;
+
+: ]]max gsl_matrix_max ;
+: ]]min gsl_matrix_min ;
+: ]]add! ( *gsl_matrix *gsl_matrix -- )
+    gsl_matrix_add drop ;
+: ]]sub! ( *gsl_matrix *gsl_matrix -- )
+    gsl_matrix_sub drop ;
+: ]]e*! ( *gsl_matrix *gsl_matrix -- )
+    gsl_matrix_mul_elements drop ;
+: ]]*c ( *gsl_matrix df -- )
+    gsl_matrix_scale drop ;
+: ]]+c ( df *gsl_matrix -- ) gsl_matrix_add_constant drop ;
+: ]]clone ( *gsl_matrix -- *gsl_matrix )
+    dup dup gsl_matrix size1 @ swap gsl_matrix size2 @
+    gsl_matrix_alloc
+    dup -rot swap gsl_matrix_memcpy drop ;
+: ]]negate !-1.0 ]]*c ;
+
+: ]]+ ( *gsl_matrix *gsl_matrix -- *gsl_matrix )
+    ]]clone dup -rot swap ]]add! ;
+
+: ]]- ( *gsl_matrix *gsl_matrix -- *gsl_matrix )
+    swap ]]clone dup -rot swap ]]sub! ;
+: ]]null? ( *gsl_matrix -- 0/-1 ) gsl_matrix_isnull negate ;
+: ]]pos? ( *gsl_matrix -- 0/-1 ) gsl_matrix_ispos negate ;
+: ]]neg? ( *gsl_matrix -- 0/-1 ) gsl_matrix_isneg negate ;
+
+\ blas
+
+\ constants
+101 Constant CblasRowMajor
+102 Constant CblasColMajor
+111 Constant CblasNoTrans
+112 Constant CblasTrans
+113 Constant CblasConjTrans
+121 Constant CblasUpper
+122 Constant CblasLower
+131 Constant CblasNonUnit
+132 Constant CblasUnit
+141 Constant CblasLeft
+142 Constant CblasRight
+
+: action? (  *gsl_matrix *gsl_matrix n n n -- )
+    dup 0= if
+        drop
+        2swap 2dup
+        ]]size2 swap ]]size1 swap
+        exit
+    then
+    dup 1 = if
+        drop
+        2swap 2dup
+        ]]size2 swap ]]size2 swap
+        exit
+    then
+    2 = if
+        2swap 2dup
+        ]]size1 swap ]]size1 swap
+        exit
+    then
+    3 = if
+        2swap 2dup
+        ]]size1 swap ]]size2 swap
+        exit
+    then ;
+
+create samemattable ' noop , ' ]]clone ,
+: samemat (  *gsl_matrix *gsl_matrix -- 1/0 *gsl_matrix )
+    dup -rot = abs dup -rot cells samemattable + @ execute ; macro
+
+: ]]mul (  *gsl_matrix *gsl_matrix n n n -- *gsl_matrix )
+    !1 !0 action?
+    gsl_matrix_alloc dup >r
+    gsl_blas_dgemm drop r> ;
+: ]]* (  *gsl_matrix *gsl_matrix -- *gsl_matrix )
+    2dup samemat dup rot 2>r nip
+    CblasNoTrans CblasNoTrans 0 ]]mul
+    2r> if ]]free else drop then ;
+: ]]'* (  *gsl_matrix *gsl_matrix -- *gsl_matrix )
+    2dup samemat dup rot 2>r nip
+    CblasTrans CblasNoTrans 1 ]]mul
+    2r> if ]]free else drop then ;    
+: ]]*' (  *gsl_matrix *gsl_matrix -- *gsl_matrix )
+    2dup samemat dup rot 2>r nip
+    CblasNoTrans CblasTrans 2 ]]mul
+    2r> if ]]free else drop then ;        
+: ]]'*' (  *gsl_matrix *gsl_matrix -- *gsl_matrix )
+    2dup samemat dup rot 2>r nip
+    CblasTrans CblasTrans 3 ]]mul
+    2r> if ]]free else drop then ;        
+
+: ]]mul! (  n n *gsl_matrix *gsl_matrix *gsl_matrix -- )
+    !1 !0 gsl_blas_dgemm drop ;
+: ]]*! (  *gsl_matrix *gsl_matrix *gsl_matrix -- )
+    >r CblasNoTrans CblasNoTrans 2swap r> ]]mul! ;
+: ]]'*! (  *gsl_matrix *gsl_matrix *gsl_matrix --  )
+    >r CblasTrans CblasNoTrans 2swap r> ]]mul! ;
+: ]]*'! (  *gsl_matrix *gsl_matrix *gsl_matrix -- )
+    >r CblasNoTrans CblasTrans 2swap r> ]]mul! ;
+
+
+: ]]*] ( *gsl_matrix *gsl_vector -- *gsl_vector )
+    over ]]size1 gsl_vector_alloc >r
+    CblasNoTrans -rot r@ !1 !0 gsl_blas_dgemv drop r> ;
+: ]]'*] ( *gsl_matrix *gsl_vector -- *gsl_vector )
+    over ]]size1 gsl_vector_alloc >r
+    CblasTrans -rot r@ !1 !0 gsl_blas_dgemv drop r> ;
+
+: ]]i ( *gsl_matrix -- )
+    dup dup ]]size1 swap ]]size2 <> if
+        abort" ERROR: Not a square matrix!"
+    then
+    dup ]]size1 0 do
+        dup i i !1 ]]! 
+    loop drop ;
+: identity ( n -- *gsl_matrix )
+    dup gsl_matrix_calloc dup ]]i ;
+: min-identity ( *gsl_matrix -- *gsl_matrix )
+    dup ]]size1 swap ]]size2 min identity ;
+: left/right' ( *gsl_matrix *gsl_matrix -- *gsl_matrix )
+    over ]]size1 over ]]size1 > if
+        swap ]]*' exit
+    else
+        ]]'* exit
+    then ;
+
+\ original matrix remains intact
+: ]]' ( *gsl_matrix -- *gsl_matrix )
+    dup min-identity dup >r
+    left/right'
+    r> ]]free ;
+: ]]T! ( *gsl_matrix -- )
+    gsl_matrix_transpose drop ;
+
+: ]]T ( *gsl_matrix -- *gsl_matrix )
+    dup ]]dim swap gsl_matrix_alloc dup rot gsl_matrix_transpose_memcpy drop ;
+
+: ]]2T ( *gsl_matr *gsl_matrix -- )
+    gsl_matrix_transpose_memcpy drop ;
+
+: ]]+! ( *gsl_matrix i j df -- ) >r 2dup r@ ]]@ f+ r> ]]! ;
+: ]]scale! ( *gsl_matrix i j df -- ) >r 2dup r@ ]]@ f* r> ]]! ;
+: ]]data_ij ( *gsl_matrix i j -- addr)
+    rot >r swap r@ ]]tda dfloats * swap dfloats + r> ]]data + ;
+\ Cross product can be either calculated through determinant:
+: ]x ( *gsl_vector *gsl_vector -- *gsl_vector )
+    3 gsl_vector_alloc
+    { x1[ x2[ x3[ |
+    x1[ 2 ]@ fnegate x2[ 1 ]@ f* x1[ 1 ]@ x2[ 2 ]@ f* f+ x3[ 0 ]! 
+    x1[ 2 ]@ x2[ 0 ]@ f* x1[ 0 ]@ fnegate x2[ 2 ]@ f* f+ x3[ 1 ]!
+    x1[ 1 ]@ fnegate x2[ 0 ]@ f* x1[ 0 ]@ x2[ 1 ]@ f* f+ x3[ 2 ]!
+    x3[ } ;
+\ or using algebraic form when first vector in the product is
+\ rewritten in a matrix form:
+\ a x b = [C_a] b
+\         [ 0   -a[2]  a[1] ]
+\ [C_a] = [ a[2] 0    -a[0] ]
+\         [-a[1] a[0]  0    ]
+\ a function to convert a vector into such matrix:
+: ]>[x] ( ] -- ]] )
+    [IFDEF] debug
+        dup ]size 3 <> abort" Not a 3D vector!"
+    [THEN]
+    3 3 :]] dup >r
+    swap 2dup 2 ]@ fdup dup fnegate 0 1 ]]! 1 0 ]]!
+    2dup 1 ]@ fdup dup fnegate 2 0 ]]! 0 2 ]]!
+    0 ]@ fdup dup fnegate 1 2 ]]! 2 1 ]]! r> ;
+: ]. ( *gsl_vector *gsl_vector -- f:dot_product )
+    { x1[ x2[ |
+    0 0 sp@ x1[ x2[ rot gsl_blas_ddot drop fd>f } ;
+: ]total ( *gsl_vector -- f:sum )
+    dup ]size gsl_vector_alloc dup !1 ]fill dup rot ]. ]free ;
+\ probability normalize - assures sum is unity
+: ]pnormalize ( *gsl_vector - )
+    dup ]total 1/f ]*c ;
+: |]| ( *gsl_vector -- f:norm ) dup ].  fsqrt ;
+\ assures vector norm is unity
+: ]normalize ( *gsl_vector - )
+    dup |]| 1/f ]*c ;
+: ]distance ( *gsl-vector *gsl-vector -- f )
+    ]sub dup |]| ]free ;
+: ]+! ( *gsl_vector i df -- )
+    2dup ]@ f+ ]! ;
+: ]*! ( *gsl_vector i df -- )
+    2dup ]@ f* ]! ;
+
+: ]]*]m ( *gsl_matrix *gsl_vector -- *gsl_vector )
+    over ]]size1 gsl_vector_calloc 
+    { m[[ x[ y[ |
+    m[[ ]]size1 0 do
+        m[[ ]]size2 0 do
+            m[[ j i ]]@ x[ i ]@ f* y[ j ]+! 
+        loop
+    loop y[ } ;
+
+: >#rows ( -- )
+    swap ]]size1 >= abort" number of rows is bigger than available!" ;
+: >#cols ( -- )
+    swap ]]size2 >= abort" number of columns is bigger than available!" ;
+
+: ]]row ( *gsl_matrix n -- *gsl_vector )
+    2dup >#rows    
+    sizeof gsl_vector allocate throw
+    dup 1 swap gsl_vector stride ! >r
+    over ]]size2 r@ gsl_vector size !
+    0 ]]data_ij r@ gsl_vector data !
+    0 r@ gsl_vector owner ! r> ;
+\ assumes all dimensions are set correctly
+: ]]row! ( *gsl_vector *gsl_matrix n -- )
+    rot >r 2dup >#rows 0 ]]data_ij r> gsl_vector data ! ;
+: ]]col ( *gsl_matrix n -- *gsl_vector )
+    2dup >#cols
+    sizeof gsl_vector allocate throw >r
+    over ]]tda r@ gsl_vector stride ! 
+    over ]]size1 r@ gsl_vector size !
+    over ]]block r@ gsl_vector block !    
+    0 swap ]]data_ij r@ gsl_vector data !
+    0 r@ gsl_vector owner ! r> ;
+: ]]rfill ( f:n *gsl_matrix i -- ) ]]row dup ]fill ]free ;
+: ]]cfill ( f:n *gsl_matrix i -- ) ]]col dup ]fill ]free ;
+
+
+: ]]submat ( *gsl_matrix n1 n2 m1 m2 -- *gsl_matrix )
+    { m[[ n1 n2 m1 m2 |
+    sizeof gsl_matrix allocate throw >r
+    n2 n1 - 1+          r@ gsl_matrix size1 !
+    m2 m1 - 1+          r@ gsl_matrix size2 !
+    m[[ n1 m1 ]]data_ij r@ gsl_matrix data  !
+    m[[ ]]tda           r@ gsl_matrix tda   !    
+    0                   r@ gsl_matrix owner ! r> } ;
+    
+: ?square ( *gsl_matrix -- )
+    dup ]]size1 swap ]]size2 <> abort" ERROR: Not a square matrix!" ;
+: ]]diag ( *gsl_matrix n1 n2 -- *gsl_vector )
+    rot dup ?square -rot
+    sizeof gsl_vector allocate throw { d[ |
+    over - d[ gsl_vector size !
+    2dup dup ]]data_ij d[ gsl_vector data ! drop
+    dup ]]tda d[ gsl_vector stride ! 
+        ]]block d[ gsl_vector block !    
+    0 d[ gsl_vector owner !
+    d[ } ;
+
+\ with input matrix replaced by the result
+: ]]gsl-svd ( *gsl_matrix -- *gsl_matrix *gsl_vector )
+    dup ]]size2 dup dup gsl_matrix_calloc
+    swap dup gsl_vector_calloc swap
+    gsl_vector_calloc
+    { mV vS vW |
+    mV vS vW gsl_linalg_SV_decomp drop
+    vW ]free
+    mV vS } ;
+\ seems to be 30% faster
+: ]]gsl-svdm ( *gsl_matrix -- *gsl_matrix *gsl_vector )
+    dup ]]size2 dup ( a n n -- )
+    dup dup gsl_matrix_calloc swap ( a n a n -- )
+    dup gsl_matrix_calloc rot dup ( a a a n n -- )
+    gsl_vector_calloc swap
+    gsl_vector_calloc
+    { mX mV vS vW |
+    mX mV vS vW gsl_linalg_SV_decomp_mod drop
+    vW ]free mX ]]free
+    mV vS } ;
+
+
+: ]]alu ( *gsl_matrix -- *gsl_permutation ) ( matrix replaced with its lu )
+    { a[[ |
+    CblasRowMajor a[[ ]]size1 a[[ ]]size2 a[[ ]]data a[[ ]]size1 dup
+    gsl_permutation_alloc dup >r }data
+    clapack_dgetrf throw r> } ;
+: ]]ainv ( *gsl_matrix *gsl_permutation -- )
+    \ LU of a matrix replaced with its inverse 
+    { a[[ t{ |
+    CblasRowMajor a[[ ]]size2 a[[ ]]data a[[ ]]size1 t{ }data
+    clapack_dgetri throw } ;
+: ]]ainvert ( *gsl_matrix -- *gsl_matrix )
+    [IFDEF] отладка
+	dup ?square
+    [THEN]
+    ]]clone dup dup >r ]]alu dup >r ]]ainv r> }free r> ;
+: ]]det ( *gsl_matrix -- f:determinant )
+    [IFDEF] отладка
+	dup ?square
+    [THEN]
+    ]]clone dup ]]alu >r 1e0
+    dup ]]size1 0 do dup i dup ]]@ f* loop ]]free
+    \ compute permutation sign
+    r> }sign s>f f* }free ;
+\ calculates the work needed for dgesvd_ ( see man dgesvd )
+: lwork ( m n -- c )
+    2dup max -rot min 3 * over + swap 5 * max ;
+\ this svd returns U MxM so eats a lot of memory
+: ]]asvda ( *gsl_matrix -- *gsl_matrix *gsl_matrix *gsl_vector )
+    ]]clone { A[[ |
+    A[[ ]]size1 dup gsl_matrix_alloc
+    A[[ ]]size2 dup gsl_matrix_alloc
+    A[[ ]]size1 A[[ ]]size2 min gsl_vector_alloc
+    8 cells allocate throw
+    { U[[ V[[ W[ p[ |
+    ascii A p[ 0 cells + ! p[ 0 cells + 
+    ascii A p[ 1 cells + ! p[ 1 cells + 
+    A[[ ]]size1 p[ 2 cells + ! p[ 2 cells +
+    A[[ ]]size2 p[ 3 cells + ! p[ 3 cells +
+    A[[ ]]data
+    p[ 2 cells +
+    W[ ]data
+    U[[ ]]data
+    U[[ ]]size1 p[ 4 cells + ! p[ 4 cells +
+    V[[ ]]data
+    V[[ ]]size1 p[ 5 cells + ! p[ 5 cells +
+    A[[ ]]size1 A[[ ]]size2 lwork
+    dup gsl_vector_alloc dup >r
+    ]data swap p[ 6 cells + ! p[ 6 cells +
+    p[ 7 cells +
+    dgesvd_
+    r> ]free p[ free throw A[[ ]]free
+    U[[ V[[ W[ } } ;
+
+\ performs A=U*S*V^T
+\ A = MxN, where M>N, pass it A^T
+\ returns U^T (MxN), V(NxN) and vector of N eigenvalues
+: ]]asvdO ( *gsl_matrix -- *gsl_matrix *gsl_matrix *gsl_vector )
+    { A[[ |
+    A[[ ]]size2 A[[ ]]size1 min dup gsl_matrix_alloc    
+    A[[ ]]size1 A[[ ]]size2 min gsl_vector_alloc
+    8 cells allocate throw
+    { V[[ W[ p[ |
+    ascii O p[ 0 cells + ! p[ 0 cells + 
+    ascii S p[ 1 cells + ! p[ 1 cells + 
+    A[[ ]]size2 p[ 2 cells + ! p[ 2 cells +
+    A[[ ]]size1 p[ 3 cells + ! p[ 3 cells +
+    A[[ ]]data
+    p[ 2 cells +
+    W[ ]data
+    0
+    p[ 2 cells +
+    V[[ ]]data
+    V[[ ]]size2 p[ 5 cells + ! p[ 5 cells +
+    A[[ ]]size2 A[[ ]]size1 lwork
+    dup gsl_vector_alloc dup >r
+    ]data swap p[ 6 cells + ! p[ 6 cells +
+    p[ 7 cells +
+    dgesvd_
+    r> ]free p[ free throw
+    A[[ V[[ W[ } } ;
+
+
+: ]diag[[ ( *gsl_vector -- *gsl_matrix )
+    dup ]size dup dup gsl_matrix_calloc swap
+    0 do
+        2dup swap i ]@ i i ]]!
+    loop nip ;
+
+: ]print\ ( *gsl_vector -- )
+    dup ]size 0 do dup i ]@ fx. loop drop ;
+: ]print ( *gsl_vector -- ) ]print\ cr ;
+: ]]print ( *gsl_matrix -- )
+    cr precision swap
+    5 set-precision
+    dup ]]size1 0 do
+        \ i . ." :  "
+        dup ]]size2 0 do
+            dup
+            j i ]]@ fs.
+        loop
+        cr
+    loop
+    drop set-precision ;
+: ]]row-print ( *gsl_matrix i -- )
+    cr
+    over gsl_matrix size2 @ 0 do
+        2dup
+         i ]]@ f.
+    loop
+    cr 2drop ;
+
+: ]]col-print ( *gsl_matrix i -- )
+    cr
+    over gsl_matrix size1 @ 0 do
+        2dup
+        i swap ]]@ f.
+    loop
+    cr 2drop ;
+
+: ]]nthrow ( *gsl_matrix n -- addr )
+    over ]]tda * dfloats swap ]]data + ;
+
+: ]]randomize ( *gsl_matrix -- )
+    dup dup ]]size1 swap ]]size2 * 0 do
+            dup
+            gsl-randomu
+            ]]data i dfloats + df!
+    loop drop ;
+: ]randomize ( *gsl_vector -- )
+    dup ]size 0 do
+            dup
+            gsl-randomu
+            i ]!
+    loop drop ;
+: ]mean ( *gsl_vector -- f )
+    dup ]stride swap dup ]size swap ]data
+    rot rot gsl_stats_mean ;
+
+: ]variance ( *gsl_vector -- f )
+    dup ]stride swap dup ]size swap ]data
+    rot rot gsl_stats_variance ;
+
+: ]sd ( *gsl_vector -- f )
+    dup ]stride swap dup ]size swap ]data    
+    rot rot gsl_stats_sd ;
+
+: ]skew ( *gsl_vector -- f )
+    dup ]stride swap dup ]size swap ]data    
+    rot rot gsl_stats_skew ;
+
+: ]kurtosis ( *gsl_vector -- f )
+    dup ]stride swap dup ]size swap ]data        
+    rot rot gsl_stats_kurtosis ;
+
+: ]]gsl-lu ( *gsl_matrix -- *gsl_matrix *gsl_permutation )
+    1 sp@ rot ]]clone dup >r dup ]]size1 gsl_permutation_calloc dup >r rot
+    gsl_linalg_LU_decomp drop r> r> swap rot drop ;
+
+: ]]gsl-invert ( *gsl_matrix -- *gsl_matrix )
+    ]]clone dup dup ]]gsl-lu 2dup >r >r rot
+    gsl_linalg_LU_invert drop r> ]]free r> }free ;
+
+' ]]ainvert alias ]]invert
+' ]]asvdO alias ]]svd
+
+: ]]save ( *gsl_matrix *gsl_matrix_cfa fid -- )
+    -rot { m[[ name[[ |
+    >r
+    name[[ >name count 1+ nip 0 m[[ ]]size2 m[[ ]]size1 0
+    sp@ 5 cells r@ write-file throw
+    2drop 2drop drop
+    name[[ >name count 1+ r@ write-file throw
+    m[[ ]]size1 m[[ ]]size2 * dfloats  m[[ ]]T dup s>f ]]data swap
+    r> write-file throw  f>s ]]free } ;
+
+\ these words do not work with float matrices but are needed for
+\ scientific calculations, that's why they are in this module
+
+: _hmatrix ( n m size -- addr )
+    rot over * 2 pick * [ 2 cells ] literal +
+    allocate throw dup [ 2 cells ] literal + >r
+    rot over ! [ 1 cells ] literal + ! r> ;
+: hmatrix ( n m size -- )
+    create
+    rot over * 2 pick * [ 2 cells ] literal + allocate throw dup ,
+    rot over ! [ 1 cells ] literal + !
+  does> @ [ 2 cells ] literal + ;
+: }}row-size ( hmatrix -- ) [ 2 cells ] literal - @ ;
+: freeHmatrix ( hmatrix -- ) [ 2 cells ] literal - free throw ;
+: }} ( addr i j -- addr[i][j] )    \ word to fetch 2-D array addresses
+    >R >R                          \ indices to return stack temporarily
+    DUP CELL- CELL- 2@             \ &a[0][0] size m
+    R> * R> + *
+    +
+    ALIGNED ;
+: h->[[ ( hmatrix -- gsl_matrix )
+    dup }}row-size 3 swap gsl_matrix_alloc
+    dup ]]size2 0 do
+        3 0 do
+          2dup swap i j }} w@ s>f i j ]]!  
+        loop
+    loop nip ;
+
+\ some sequencing code
+: arange ( f:start f:end f:step -- x[ )
+    f-rot
+    fswap fdup f>r f- fover f/ f>s :] fr>
+    dup ]size 0 do
+        dup fover i s>f f* fover f+ i ]!
+    loop ;
+: product ( x[ -- f:P )
+    !1 dup ]size 0 do
+        dup i ]@ f*
+    loop drop ;
+
+\ initializing random number generator to some value in order to have
+\ it available upon loading of gsl
+mt19937
+: )randperm ( *v( -- )
+    gsl_rng_default swap
+    dup )size over )type 8 / gsl_ran_shuffle ;
+
+previous previous previous previous previous
+
+Module;
diff --git a/include/mgl2/mathgl.fs b/include/mgl2/mathgl.fs
new file mode 100644
index 0000000..bbc3fd8
--- /dev/null
+++ b/include/mgl2/mathgl.fs
@@ -0,0 +1,472 @@
+Module mathgl
+also dos
+
+library libmgl      libmgl.so
+library libmgl-glut libmgl-glut.so
+library libmgl-fltk libmgl-fltk.so
+library libmgl-qt   libmgl-qt.so
+library libmgl-wx   libmgl-wx.so
+
+legacy off
+
+libmgl      mgl_create_graph_gl                                                      (ptr) mgl_create_graph_gl
+libmgl      mgl_create_graph_zb       int int                                        (ptr) mgl_create_graph_zb
+libmgl      mgl_create_graph_ps       int int                                        (ptr) mgl_create_graph_ps
+libmgl      mgl_fortran_func          ptr ptr                                        (int) mgl_fortran_func
+libmgl-glut mgl_create_graph_glut                                        ptr ptr ptr (ptr) mgl_create_graph_glut
+libmgl-fltk mgl_create_graph_fltk                                        ptr ptr ptr (ptr) mgl_create_graph_fltk
+libmgl-qt   mgl_create_graph_qt                                          ptr ptr ptr (ptr) mgl_create_graph_qt
+\ libmgl-glut mgl_create_graph_glut_dr  ptr ptr                                        (ptr) mgl_create_graph_glut_dr
+\ libmgl-fltk mgl_create_graph_fltk_dr  ptr ptr                                        (ptr) mgl_create_graph_fltk_dr
+\ libmgl-qt   mgl_create_graph_qt_dr    ptr ptr                                        (ptr) mgl_create_graph_qt_dr
+libmgl      mgl_create_graph_idtf                                                    (ptr) mgl_create_graph_idtf
+libmgl-fltk mgl_fltk_run                                                            (void) mgl_fltk_run
+libmgl-qt   mgl_qt_run                                                              (void) mgl_qt_run
+libmgl      mgl_set_show_mouse_pos    int ptr                                       (void) mgl_set_show_mouse_pos
+libmgl      mgl_get_last_mouse_pos    sf sf sf ptr                                  (void) mgl_get_last_mouse_pos
+libmgl      mgl_update                ptr                                           (void) mgl_update
+libmgl      mgl_delete_graph          ptr                                           (void) mgl_delete_graph
+libmgl      mgl_create_data                                                          (ptr) mgl_create_data
+libmgl      mgl_create_data_size      int int int                                    (ptr) mgl_create_data_size
+libmgl      mgl_create_data_file      ptr                                            (ptr) mgl_create_data_file
+libmgl      mgl_delete_data           ptr                                           (void) mgl_delete_data
+libmgl      mgl_create_parser                                                        (ptr) mgl_create_parser
+libmgl      mgl_delete_parser         ptr                                           (void) mgl_delete_parser
+libmgl      mgl_add_param             ptr int ptr                                   (void) mgl_add_param
+libmgl      mgl_add_paramw            ptr int ptr                                   (void) mgl_add_paramw
+libmgl      mgl_add_var               ptr ptr                                        (ptr) mgl_add_var
+libmgl      mgl_find_var              ptr ptr                                        (ptr) mgl_find_var
+libmgl      mgl_parse                 int ptr ptr ptr                                (int) mgl_parse
+libmgl      mgl_parsew                int ptr ptr ptr                                (int) mgl_parsew
+libmgl      mgl_parse_text            ptr ptr ptr                                   (void) mgl_parse_text
+libmgl      mgl_parsew_text           ptr ptr ptr                                   (void) mgl_parsew_text
+libmgl      mgl_restore_once          ptr                                           (void) mgl_restore_once
+libmgl      mgl_parser_allow_setsize  int ptr                                       (void) mgl_parser_allow_setsize
+libmgl      mgl_set_def_param         ptr                                           (void) mgl_set_def_param
+libmgl      mgl_set_palette           ptr ptr                                       (void) mgl_set_palette
+libmgl      mgl_set_pal_color         sf sf sf int ptr                              (void) mgl_set_pal_color
+libmgl      mgl_set_pal_num           int ptr                                       (void) mgl_set_pal_num
+libmgl      mgl_set_rotated_text      int ptr                                       (void) mgl_set_rotated_text
+libmgl      mgl_set_cut               int ptr                                       (void) mgl_set_cut
+libmgl      mgl_set_cut_box           sf sf sf sf sf sf ptr                         (void) mgl_set_cut_box
+libmgl      mgl_set_tick_len          sf ptr                                        (void) mgl_set_tick_len
+libmgl      mgl_set_bar_width         sf ptr                                        (void) mgl_set_bar_width
+libmgl      mgl_set_base_line_width   sf ptr                                        (void) mgl_set_base_line_width
+libmgl      mgl_set_mark_size         sf ptr                                        (void) mgl_set_mark_size
+libmgl      mgl_set_arrow_size        sf ptr                                        (void) mgl_set_arrow_size
+libmgl      mgl_set_font_size         sf ptr                                        (void) mgl_set_font_size
+libmgl      mgl_set_font_def          ptr ptr                                       (void) mgl_set_font_def
+libmgl      mgl_set_alpha_default     sf ptr                                        (void) mgl_set_alpha_default
+libmgl      mgl_set_size              int int ptr                                   (void) mgl_set_size
+libmgl      mgl_set_axial_dir         ptr ptr                                       (void) mgl_set_axial_dir
+libmgl      mgl_set_meshnum           int ptr                                       (void) mgl_set_meshnum
+libmgl      mgl_set_zoom              sf sf sf sf ptr                               (void) mgl_set_zoom
+libmgl      mgl_set_plotfactor        sf ptr                                        (void) mgl_set_plotfactor
+libmgl      mgl_set_draw_face         int ptr                                       (void) mgl_set_draw_face
+libmgl      mgl_set_scheme            ptr ptr                                       (void) mgl_set_scheme
+libmgl      mgl_load_font             ptr ptr ptr                                   (void) mgl_load_font
+libmgl      mgl_copy_font             ptr ptr                                       (void) mgl_copy_font
+libmgl      mgl_restore_font          ptr                                           (void) mgl_restore_font
+libmgl      mgl_show_image            int ptr ptr                                   (void) mgl_show_image
+libmgl      mgl_write_frame           ptr ptr ptr                                   (void) mgl_write_frame
+libmgl      mgl_write_bmp             ptr ptr ptr                                   (void) mgl_write_bmp
+libmgl      mgl_write_jpg             ptr ptr ptr                                   (void) mgl_write_jpg
+libmgl      mgl_write_png             ptr ptr ptr                                   (void) mgl_write_png
+libmgl      mgl_write_png_solid       ptr ptr ptr                                   (void) mgl_write_png_solid
+libmgl      mgl_write_eps             ptr ptr ptr                                   (void) mgl_write_eps
+libmgl      mgl_write_svg             ptr ptr ptr                                   (void) mgl_write_svg
+libmgl      mgl_write_idtf            ptr ptr ptr                                   (void) mgl_write_idtf
+libmgl      mgl_write_gif             ptr ptr ptr                                   (void) mgl_write_gif
+libmgl      mgl_start_gif             int ptr ptr                                   (void) mgl_start_gif
+libmgl      mgl_close_gif             ptr                                           (void) mgl_close_gif
+libmgl      mgl_get_rgb               ptr                                            (ptr) mgl_get_rgb
+libmgl      mgl_get_rgba              ptr                                            (ptr) mgl_get_rgba
+libmgl      mgl_get_width             ptr                                            (int) mgl_get_width
+libmgl      mgl_get_height            ptr                                            (int) mgl_get_height
+libmgl      mgl_new_frame             ptr                                            (int) mgl_new_frame
+libmgl      mgl_end_frame             ptr                                           (void) mgl_end_frame
+libmgl      mgl_get_num_frame         ptr                                            (int) mgl_get_num_frame
+libmgl      mgl_reset_frames          ptr                                           (void) mgl_reset_frames
+libmgl      mgl_set_transp_type       int ptr                                       (void) mgl_set_transp_type
+libmgl      mgl_set_transp            int ptr                                       (void) mgl_set_transp
+libmgl      mgl_set_alpha             int ptr                                       (void) mgl_set_alpha
+libmgl      mgl_set_fog               sf sf ptr                                     (void) mgl_set_fog
+libmgl      mgl_set_light             int ptr                                       (void) mgl_set_light
+libmgl      mgl_set_light_n           int int ptr                                   (void) mgl_set_light_n
+libmgl      mgl_add_light             ptr sf sf sf int ptr                          (void) mgl_add_light
+libmgl      mgl_add_light_rgb         sf sf sf sf int sf sf sf int ptr              (void) mgl_add_light_rgb
+libmgl      mgl_set_ambbr             sf ptr                                        (void) mgl_set_ambbr
+libmgl      mgl_identity              ptr                                           (void) mgl_identity
+libmgl      mgl_clf                   ptr                                           (void) mgl_clf
+libmgl      mgl_flush                 ptr                                           (void) mgl_flush
+libmgl      mgl_clf_rgb               sf sf sf ptr                                  (void) mgl_clf_rgb
+libmgl      mgl_subplot               int int int ptr                               (void) mgl_subplot
+libmgl      mgl_subplot_d             sf sf int int int ptr                         (void) mgl_subplot_d
+libmgl      mgl_inplot                sf sf sf sf ptr                               (void) mgl_inplot
+libmgl      mgl_relplot               sf sf sf sf ptr                               (void) mgl_relplot
+libmgl      mgl_columnplot            int int ptr                                   (void) mgl_columnplot
+libmgl      mgl_aspect                sf sf sf ptr                                  (void) mgl_aspect
+libmgl      mgl_rotate                sf sf sf ptr                                  (void) mgl_rotate
+libmgl      mgl_rotate_vector         sf sf sf sf ptr                               (void) mgl_rotate_vector
+libmgl      mgl_perspective           sf ptr                                        (void) mgl_perspective
+libmgl      mgl_set_ticks             sf sf sf ptr                                  (void) mgl_set_ticks
+libmgl      mgl_set_subticks          int int int ptr                               (void) mgl_set_subticks
+libmgl      mgl_set_ticks_dir         sf int sf ptr ptr                             (void) mgl_set_ticks_dir
+\ libmgl      mgl_set_ticks_val          ... ptr  double val int ptr ptr              (void) mgl_set_ticks_val
+libmgl      mgl_set_ticks_vals        ptr sf int ptr ptr                            (void) mgl_set_ticks_vals
+libmgl      mgl_set_caxis             sf sf ptr                                     (void) mgl_set_caxis
+libmgl      mgl_set_axis              sf sf sf sf sf sf sf sf sf ptr                (void) mgl_set_axis
+libmgl      mgl_set_axis_3d           sf sf sf sf sf sf ptr                         (void) mgl_set_axis_3d
+libmgl      mgl_set_axis_2d           sf sf sf sf ptr                               (void) mgl_set_axis_2d
+libmgl      mgl_set_origin            sf sf sf ptr                                  (void) mgl_set_origin
+libmgl      mgl_set_tick_origin       sf sf sf ptr                                  (void) mgl_set_tick_origin
+libmgl      mgl_set_crange            int ptr ptr                                   (void) mgl_set_crange
+libmgl      mgl_set_xrange            int ptr ptr                                   (void) mgl_set_xrange
+libmgl      mgl_set_yrange            int ptr ptr                                   (void) mgl_set_yrange
+libmgl      mgl_set_zrange            int ptr ptr                                   (void) mgl_set_zrange
+libmgl      mgl_set_auto              sf sf sf sf sf sf ptr                         (void) mgl_set_auto
+libmgl      mgl_set_func              ptr ptr ptr ptr                               (void) mgl_set_func
+libmgl      mgl_set_ternary           int ptr                                       (void) mgl_set_ternary
+libmgl      mgl_set_cutoff            ptr ptr                                       (void) mgl_set_cutoff
+libmgl      mgl_box                   int ptr                                       (void) mgl_box
+libmgl      mgl_box_str               int ptr ptr                                   (void) mgl_box_str
+libmgl      mgl_box_rgb               int sf sf sf ptr                              (void) mgl_box_rgb
+libmgl      mgl_axis                  ptr ptr                                       (void) mgl_axis
+libmgl      mgl_axis_grid             ptr ptr ptr                                   (void) mgl_axis_grid
+libmgl      mgl_label                 ptr ptr ptr                                   (void) mgl_label
+libmgl      mgl_label_ext             sf sf int ptr ptr ptr                         (void) mgl_label_ext
+libmgl      mgl_tune_ticks            sf int ptr                                    (void) mgl_tune_ticks
+libmgl      mgl_set_xttw              ptr ptr                                       (void) mgl_set_xttw
+libmgl      mgl_set_yttw              ptr ptr                                       (void) mgl_set_yttw
+libmgl      mgl_set_zttw              ptr ptr                                       (void) mgl_set_zttw
+libmgl      mgl_set_cttw              ptr ptr                                       (void) mgl_set_cttw
+libmgl      mgl_set_xtt               ptr ptr                                       (void) mgl_set_xtt
+libmgl      mgl_set_ytt               ptr ptr                                       (void) mgl_set_ytt
+libmgl      mgl_set_ztt               ptr ptr                                       (void) mgl_set_ztt
+libmgl      mgl_set_ctt               ptr ptr                                       (void) mgl_set_ctt
+libmgl      mgl_ball                  sf sf sf ptr                                  (void) mgl_ball
+libmgl      mgl_ball_rgb              sf sf sf sf sf sf sf ptr                      (void) mgl_ball_rgb
+libmgl      mgl_ball_str              ptr sf sf sf ptr                              (void) mgl_ball_str
+libmgl      mgl_line                  int ptr sf sf sf sf sf sf ptr                 (void) mgl_line
+libmgl      mgl_facex                 sf sf ptr sf sf sf sf sf ptr                  (void) mgl_facex
+libmgl      mgl_facey                 sf sf ptr sf sf sf sf sf ptr                  (void) mgl_facey
+libmgl      mgl_facez                 sf sf ptr sf sf sf sf sf ptr                  (void) mgl_facez
+libmgl      mgl_curve                 int ptr sf sf sf sf sf sf sf sf sf sf sf sf ptr (void) mgl_curve
+libmgl      mgl_puts                  ptr sf sf sf ptr                              (void) mgl_puts
+libmgl      mgl_putsw                 ptr sf sf sf ptr                              (void) mgl_putsw
+libmgl      mgl_puts_dir              sf ptr sf sf sf sf sf sf ptr                  (void) mgl_puts_dir
+libmgl      mgl_putsw_dir             sf ptr sf sf sf sf sf sf ptr                  (void) mgl_putsw_dir
+libmgl      mgl_text                  ptr sf sf sf ptr                              (void) mgl_text
+libmgl      mgl_title                 sf ptr ptr ptr                                (void) mgl_title
+libmgl      mgl_titlew                sf ptr ptr ptr                                (void) mgl_titlew
+libmgl      mgl_putsw_ext             ptr sf ptr ptr sf sf sf ptr                   (void) mgl_putsw_ext
+libmgl      mgl_puts_ext              ptr sf ptr ptr sf sf sf ptr                   (void) mgl_puts_ext
+libmgl      mgl_text_ext              ptr sf ptr ptr sf sf sf ptr                   (void) mgl_text_ext
+libmgl      mgl_colorbar              int ptr ptr                                   (void) mgl_colorbar
+libmgl      mgl_colorbar_ext          sf sf sf sf int ptr ptr                       (void) mgl_colorbar_ext
+libmgl      mgl_simple_plot           ptr int ptr ptr                               (void) mgl_simple_plot
+libmgl      mgl_add_legend            ptr ptr ptr                                   (void) mgl_add_legend
+libmgl      mgl_add_legendw           ptr ptr ptr                                   (void) mgl_add_legendw
+libmgl      mgl_clear_legend          ptr                                           (void) mgl_clear_legend
+libmgl      mgl_legend_xy             sf sf ptr sf sf ptr                           (void) mgl_legend_xy
+libmgl      mgl_legend                sf sf ptr int ptr                             (void) mgl_legend
+libmgl      mgl_set_legend_box        int ptr                                       (void) mgl_set_legend_box
+libmgl      mgl_fplot                 int ptr ptr ptr                               (void) mgl_fplot
+libmgl      mgl_fplot_xyz             int ptr ptr ptr ptr ptr                       (void) mgl_fplot_xyz
+libmgl      mgl_plot_xyz              ptr ptr ptr ptr ptr                           (void) mgl_plot_xyz
+libmgl      mgl_plot_xy               ptr ptr ptr ptr                               (void) mgl_plot_xy
+libmgl      mgl_plot                  ptr ptr ptr                                   (void) mgl_plot
+libmgl      mgl_plot_2                ptr ptr ptr                                   (void) mgl_plot_2
+libmgl      mgl_plot_3                ptr ptr ptr                                   (void) mgl_plot_3
+libmgl      mgl_tens_xyz              ptr ptr ptr ptr ptr ptr                       (void) mgl_tens_xyz
+libmgl      mgl_tens_xy               ptr ptr ptr ptr ptr                           (void) mgl_tens_xy
+libmgl      mgl_tens                  ptr ptr ptr ptr                               (void) mgl_tens
+libmgl      mgl_area_xyz              ptr ptr ptr ptr ptr                           (void) mgl_area_xyz
+libmgl      mgl_area_xy               ptr ptr ptr ptr                               (void) mgl_area_xy
+libmgl      mgl_area_xys              ptr ptr ptr ptr                               (void) mgl_area_xys
+libmgl      mgl_area                  ptr ptr ptr                                   (void) mgl_area
+libmgl      mgl_area_2                ptr ptr ptr                                   (void) mgl_area_2
+libmgl      mgl_area_3                ptr ptr ptr                                   (void) mgl_area_3
+libmgl      mgl_region_xy             int ptr ptr ptr ptr ptr                       (void) mgl_region_xy
+libmgl      mgl_region                int ptr ptr ptr ptr                           (void) mgl_region
+libmgl      mgl_mark                  ptr sf sf sf ptr                              (void) mgl_mark
+libmgl      mgl_stem_xyz              ptr ptr ptr ptr ptr                           (void) mgl_stem_xyz
+libmgl      mgl_stem_xy               ptr ptr ptr ptr                               (void) mgl_stem_xy
+libmgl      mgl_stem                  ptr ptr ptr                                   (void) mgl_stem
+libmgl      mgl_stem_2                ptr ptr ptr                                   (void) mgl_stem_2
+libmgl      mgl_stem_3                ptr ptr ptr                                   (void) mgl_stem_3
+libmgl      mgl_step_xyz              ptr ptr ptr ptr ptr                           (void) mgl_step_xyz
+libmgl      mgl_step_xy               ptr ptr ptr ptr                               (void) mgl_step_xy
+libmgl      mgl_step                  ptr ptr ptr                                   (void) mgl_step
+libmgl      mgl_step_2                ptr ptr ptr                                   (void) mgl_step_2
+libmgl      mgl_step_3                ptr ptr ptr                                   (void) mgl_step_3
+libmgl      mgl_bars_xyz              ptr ptr ptr ptr ptr                           (void) mgl_bars_xyz
+libmgl      mgl_bars_xy               ptr ptr ptr ptr                               (void) mgl_bars_xy
+libmgl      mgl_bars                  ptr ptr ptr                                   (void) mgl_bars
+libmgl      mgl_bars_2                ptr ptr ptr                                   (void) mgl_bars_2
+libmgl      mgl_bars_3                ptr ptr ptr                                   (void) mgl_bars_3
+libmgl      mgl_barh_yx               ptr ptr ptr ptr                               (void) mgl_barh_yx
+libmgl      mgl_barh                  ptr ptr ptr                                   (void) mgl_barh
+libmgl      mgl_torus                 ptr ptr ptr ptr                               (void) mgl_torus
+libmgl      mgl_torus_2               ptr ptr ptr                                   (void) mgl_torus_2
+libmgl      mgl_text_xyz              sf ptr ptr ptr ptr ptr ptr                    (void) mgl_text_xyz
+libmgl      mgl_text_xy               sf ptr ptr ptr ptr ptr                        (void) mgl_text_xy
+libmgl      mgl_text_y                sf ptr ptr ptr ptr                            (void) mgl_text_y
+libmgl      mgl_chart                 ptr ptr ptr                                   (void) mgl_chart
+libmgl      mgl_error                 ptr ptr ptr ptr                               (void) mgl_error
+libmgl      mgl_error_xy              ptr ptr ptr ptr ptr                           (void) mgl_error_xy
+libmgl      mgl_error_exy             ptr ptr ptr ptr ptr ptr                       (void) mgl_error_exy
+libmgl      mgl_mark_xyz              ptr ptr ptr ptr ptr ptr                       (void) mgl_mark_xyz
+libmgl      mgl_mark_xy               ptr ptr ptr ptr ptr                           (void) mgl_mark_xy
+libmgl      mgl_mark_y                ptr ptr ptr ptr                               (void) mgl_mark_y
+libmgl      mgl_tube_xyzr             ptr ptr ptr ptr ptr ptr                       (void) mgl_tube_xyzr
+libmgl      mgl_tube_xyr              ptr ptr ptr ptr ptr                           (void) mgl_tube_xyr
+libmgl      mgl_tube_r                ptr ptr ptr ptr                               (void) mgl_tube_r
+libmgl      mgl_tube_xyz              ptr sf ptr ptr ptr ptr                        (void) mgl_tube_xyz
+libmgl      mgl_tube_xy               ptr sf ptr ptr ptr                            (void) mgl_tube_xy
+libmgl      mgl_tube                  ptr sf ptr ptr                                (void) mgl_tube
+libmgl      mgl_textmark_xyzr         ptr ptr ptr ptr ptr ptr ptr                   (void) mgl_textmark_xyzr
+libmgl      mgl_textmark_xyr          ptr ptr ptr ptr ptr ptr                       (void) mgl_textmark_xyr
+libmgl      mgl_textmark_yr           ptr ptr ptr ptr ptr                           (void) mgl_textmark_yr
+libmgl      mgl_textmark              ptr ptr ptr ptr                               (void) mgl_textmark
+libmgl      mgl_textmarkw_xyzr        ptr ptr ptr ptr ptr ptr ptr                   (void) mgl_textmarkw_xyzr
+libmgl      mgl_textmarkw_xyr         ptr ptr ptr ptr ptr ptr                       (void) mgl_textmarkw_xyr
+libmgl      mgl_textmarkw_yr          ptr ptr ptr ptr ptr                           (void) mgl_textmarkw_yr
+libmgl      mgl_textmarkw             ptr ptr ptr ptr                               (void) mgl_textmarkw
+libmgl      mgl_fsurf                 int ptr ptr ptr                               (void) mgl_fsurf
+libmgl      mgl_fsurf_xyz             int ptr ptr ptr ptr ptr                       (void) mgl_fsurf_xyz
+libmgl      mgl_grid_xy               sf ptr ptr ptr ptr ptr                        (void) mgl_grid_xy
+libmgl      mgl_grid                  sf ptr ptr ptr                                (void) mgl_grid
+libmgl      mgl_mesh_xy               ptr ptr ptr ptr ptr                           (void) mgl_mesh_xy
+libmgl      mgl_mesh                  ptr ptr ptr                                   (void) mgl_mesh
+libmgl      mgl_fall_xy               ptr ptr ptr ptr ptr                           (void) mgl_fall_xy
+libmgl      mgl_fall                  ptr ptr ptr                                   (void) mgl_fall
+libmgl      mgl_belt_xy               ptr ptr ptr ptr ptr                           (void) mgl_belt_xy
+libmgl      mgl_belt                  ptr ptr ptr                                   (void) mgl_belt
+libmgl      mgl_surf_xy               ptr ptr ptr ptr ptr                           (void) mgl_surf_xy
+libmgl      mgl_surf                  ptr ptr ptr                                   (void) mgl_surf
+libmgl      mgl_dens_xy               sf ptr ptr ptr ptr ptr                        (void) mgl_dens_xy
+libmgl      mgl_dens                  sf ptr ptr ptr                                (void) mgl_dens
+libmgl      mgl_boxs_xy               sf ptr ptr ptr ptr ptr                        (void) mgl_boxs_xy
+libmgl      mgl_boxs                  sf ptr ptr ptr                                (void) mgl_boxs
+libmgl      mgl_tile_xy               ptr ptr ptr ptr ptr                           (void) mgl_tile_xy
+libmgl      mgl_tile                  ptr ptr ptr                                   (void) mgl_tile
+libmgl      mgl_tiles_xy              ptr ptr ptr ptr ptr ptr                       (void) mgl_tiles_xy
+libmgl      mgl_tiles                 ptr ptr ptr ptr                               (void) mgl_tiles
+libmgl      mgl_cont_xy_val           sf ptr ptr ptr ptr ptr ptr                    (void) mgl_cont_xy_val
+libmgl      mgl_cont_val              sf ptr ptr ptr ptr                            (void) mgl_cont_val
+libmgl      mgl_cont_xy               sf int ptr ptr ptr ptr ptr                    (void) mgl_cont_xy
+libmgl      mgl_cont                  sf int ptr ptr ptr                            (void) mgl_cont
+libmgl      mgl_contf_xy_val          sf ptr ptr ptr ptr ptr ptr                    (void) mgl_contf_xy_val
+libmgl      mgl_contf_val             sf ptr ptr ptr ptr                            (void) mgl_contf_val
+libmgl      mgl_contf_xy              sf int ptr ptr ptr ptr ptr                    (void) mgl_contf_xy
+libmgl      mgl_contf                 sf int ptr ptr ptr                            (void) mgl_contf
+libmgl      mgl_axial_xy_val          ptr ptr ptr ptr ptr ptr                       (void) mgl_axial_xy_val
+libmgl      mgl_axial_val             ptr ptr ptr ptr                               (void) mgl_axial_val
+libmgl      mgl_axial_xy              int ptr ptr ptr ptr ptr                       (void) mgl_axial_xy
+libmgl      mgl_axial                 int ptr ptr ptr                               (void) mgl_axial
+libmgl      mgl_surfc_xy              ptr ptr ptr ptr ptr ptr                       (void) mgl_surfc_xy
+libmgl      mgl_surfc                 ptr ptr ptr ptr                               (void) mgl_surfc
+libmgl      mgl_surfa_xy              ptr ptr ptr ptr ptr ptr                       (void) mgl_surfa_xy
+libmgl      mgl_surfa                 ptr ptr ptr ptr                               (void) mgl_surfa
+libmgl      mgl_stfa_xy               sf ptr int ptr ptr ptr ptr ptr                (void) mgl_stfa_xy
+libmgl      mgl_stfa                  sf ptr int ptr ptr ptr                        (void) mgl_stfa
+libmgl      mgl_vect_xy               sf ptr ptr ptr ptr ptr ptr                    (void) mgl_vect_xy
+libmgl      mgl_vect_2d               sf ptr ptr ptr ptr                            (void) mgl_vect_2d
+libmgl      mgl_vectl_xy              sf ptr ptr ptr ptr ptr ptr                    (void) mgl_vectl_xy
+libmgl      mgl_vectl_2d              sf ptr ptr ptr ptr                            (void) mgl_vectl_2d
+libmgl      mgl_vectc_xy              sf ptr ptr ptr ptr ptr ptr                    (void) mgl_vectc_xy
+libmgl      mgl_vectc_2d              sf ptr ptr ptr ptr                            (void) mgl_vectc_2d
+libmgl      mgl_vect_xyz              ptr ptr ptr ptr ptr ptr ptr ptr               (void) mgl_vect_xyz
+libmgl      mgl_vect_3d               ptr ptr ptr ptr ptr                           (void) mgl_vect_3d
+libmgl      mgl_vectl_xyz             ptr ptr ptr ptr ptr ptr ptr ptr               (void) mgl_vectl_xyz
+libmgl      mgl_vectl_3d              ptr ptr ptr ptr ptr                           (void) mgl_vectl_3d
+libmgl      mgl_vectc_xyz             ptr ptr ptr ptr ptr ptr ptr ptr               (void) mgl_vectc_xyz
+libmgl      mgl_vectc_3d              ptr ptr ptr ptr ptr                           (void) mgl_vectc_3d
+libmgl      mgl_map_xy                int int ptr ptr ptr ptr ptr ptr               (void) mgl_map_xy
+libmgl      mgl_map                   int int ptr ptr ptr ptr                       (void) mgl_map
+libmgl      mgl_surf3a_xyz_val        ptr ptr ptr ptr ptr ptr sf ptr                (void) mgl_surf3a_xyz_val
+libmgl      mgl_surf3a_val            ptr ptr ptr sf ptr                            (void) mgl_surf3a_val
+libmgl      mgl_surf3a_xyz            int ptr ptr ptr ptr ptr ptr ptr               (void) mgl_surf3a_xyz
+libmgl      mgl_surf3a                int ptr ptr ptr ptr                           (void) mgl_surf3a
+libmgl      mgl_surf3c_xyz_val        ptr ptr ptr ptr ptr ptr sf ptr                (void) mgl_surf3c_xyz_val
+libmgl      mgl_surf3c_val            ptr ptr ptr sf ptr                            (void) mgl_surf3c_val
+libmgl      mgl_surf3c_xyz                                                          (void) mgl_surf3c_xyz
+libmgl      mgl_surf3c                int ptr ptr ptr ptr                           (void) mgl_surf3c
+libmgl      mgl_flow_xy               sf int int ptr ptr ptr ptr ptr ptr            (void) mgl_flow_xy
+libmgl      mgl_flow_2d               sf int int ptr ptr ptr ptr                    (void) mgl_flow_2d
+libmgl      mgl_flow_xyz              int int ptr ptr ptr ptr ptr ptr ptr ptr       (void) mgl_flow_xyz
+libmgl      mgl_flow_3d               int int ptr ptr ptr ptr ptr                   (void) mgl_flow_3d
+libmgl      mgl_pipe_xy               sf int int sf ptr ptr ptr ptr ptr ptr         (void) mgl_pipe_xy
+libmgl      mgl_pipe_2d               sf int int sf ptr ptr ptr ptr                 (void) mgl_pipe_2d
+libmgl      mgl_pipe_xyz              int int sf ptr ptr ptr ptr ptr ptr ptr ptr    (void) mgl_pipe_xyz
+libmgl      mgl_pipe_3d               int int sf ptr ptr ptr ptr ptr                (void) mgl_pipe_3d
+libmgl      mgl_dew_xy                sf ptr ptr ptr ptr ptr ptr                    (void) mgl_dew_xy
+libmgl      mgl_dew_2d                sf ptr ptr ptr ptr                            (void) mgl_dew_2d
+libmgl      mgl_grid3_xyz             ptr int ptr ptr ptr ptr ptr ptr               (void) mgl_grid3_xyz
+libmgl      mgl_grid3                 ptr int ptr ptr ptr                           (void) mgl_grid3
+libmgl      mgl_grid3_all_xyz         ptr ptr ptr ptr ptr ptr                       (void) mgl_grid3_all_xyz
+libmgl      mgl_grid3_all             ptr ptr ptr                                   (void) mgl_grid3_all
+libmgl      mgl_dens3_xyz             ptr int ptr ptr ptr ptr ptr ptr               (void) mgl_dens3_xyz
+libmgl      mgl_dens3                 ptr int ptr ptr ptr                           (void) mgl_dens3
+libmgl      mgl_dens3_all_xyz         ptr ptr ptr ptr ptr ptr                       (void) mgl_dens3_all_xyz
+libmgl      mgl_dens3_all             ptr ptr ptr                                   (void) mgl_dens3_all
+libmgl      mgl_surf3_xyz_val         ptr ptr ptr ptr ptr sf ptr                    (void) mgl_surf3_xyz_val
+libmgl      mgl_surf3_val             ptr ptr sf ptr                                (void) mgl_surf3_val
+libmgl      mgl_surf3_xyz             int ptr ptr ptr ptr ptr ptr                   (void) mgl_surf3_xyz
+libmgl      mgl_surf3                 int ptr ptr ptr                               (void) mgl_surf3
+libmgl      mgl_cont3_xyz_val         ptr int ptr ptr ptr ptr ptr ptr ptr           (void) mgl_cont3_xyz_val
+libmgl      mgl_cont3_val             ptr int ptr ptr ptr ptr                       (void) mgl_cont3_val
+libmgl      mgl_cont3_xyz             int ptr int ptr ptr ptr ptr ptr ptr           (void) mgl_cont3_xyz
+libmgl      mgl_cont3                 int ptr int ptr ptr ptr                       (void) mgl_cont3
+libmgl      mgl_cont_all_xyz          int ptr ptr ptr ptr ptr ptr                   (void) mgl_cont_all_xyz
+libmgl      mgl_cont_all              int ptr ptr ptr                               (void) mgl_cont_all
+libmgl      mgl_cloudp_xyz            sf ptr ptr ptr ptr ptr ptr                    (void) mgl_cloudp_xyz
+libmgl      mgl_cloudp                sf ptr ptr ptr                                (void) mgl_cloudp
+libmgl      mgl_cloud_xyz             sf ptr ptr ptr ptr ptr ptr                    (void) mgl_cloud_xyz
+libmgl      mgl_cloud                 sf ptr ptr ptr                                (void) mgl_cloud
+libmgl      mgl_contf3_xyz_val        ptr int ptr ptr ptr ptr ptr ptr ptr           (void) mgl_contf3_xyz_val
+libmgl      mgl_contf3_val            ptr int ptr ptr ptr ptr                       (void) mgl_contf3_val
+libmgl      mgl_contf3_xyz            int ptr int ptr ptr ptr ptr ptr ptr           (void) mgl_contf3_xyz
+libmgl      mgl_contf3                int ptr int ptr ptr ptr                       (void) mgl_contf3
+libmgl      mgl_contf_all_xyz         int ptr ptr ptr ptr ptr ptr                   (void) mgl_contf_all_xyz
+libmgl      mgl_contf_all             int ptr ptr ptr                               (void) mgl_contf_all
+libmgl      mgl_beam_val              int ptr sf ptr ptr ptr ptr sf ptr             (void) mgl_beam_val
+libmgl      mgl_beam                  int int ptr sf ptr ptr ptr ptr ptr            (void) mgl_beam
+libmgl      mgl_triplot_xyzc          ptr ptr ptr ptr ptr ptr ptr                   (void) mgl_triplot_xyzc
+libmgl      mgl_triplot_xyz           ptr ptr ptr ptr ptr ptr                       (void) mgl_triplot_xyz
+libmgl      mgl_triplot_xy            sf ptr ptr ptr ptr ptr                        (void) mgl_triplot_xy
+libmgl      mgl_dots                  ptr ptr ptr ptr ptr                           (void) mgl_dots
+libmgl      mgl_dots_tr               ptr ptr ptr                                   (void) mgl_dots_tr
+libmgl      mgl_crust                 sf ptr ptr ptr ptr ptr                        (void) mgl_crust
+libmgl      mgl_crust_tr              sf ptr ptr ptr                                (void) mgl_crust_tr
+libmgl      mgl_dens_x                sf ptr ptr ptr                                (void) mgl_dens_x
+libmgl      mgl_dens_y                sf ptr ptr ptr                                (void) mgl_dens_y
+libmgl      mgl_dens_z                sf ptr ptr ptr                                (void) mgl_dens_z
+libmgl      mgl_cont_x                int sf ptr ptr ptr                            (void) mgl_cont_x
+libmgl      mgl_cont_y                int sf ptr ptr ptr                            (void) mgl_cont_y
+libmgl      mgl_cont_z                int sf ptr ptr ptr                            (void) mgl_cont_z
+libmgl      mgl_cont_x_val            sf ptr ptr ptr ptr                            (void) mgl_cont_x_val
+libmgl      mgl_cont_y_val            sf ptr ptr ptr ptr                            (void) mgl_cont_y_val
+libmgl      mgl_cont_z_val            sf ptr ptr ptr ptr                            (void) mgl_cont_z_val
+libmgl      mgl_contf_x               int sf ptr ptr ptr                            (void) mgl_contf_x
+libmgl      mgl_contf_y               int sf ptr ptr ptr                            (void) mgl_contf_y
+libmgl      mgl_contf_z               int sf ptr ptr ptr                            (void) mgl_contf_z
+libmgl      mgl_contf_x_val           sf ptr ptr ptr ptr                            (void) mgl_contf_x_val
+libmgl      mgl_contf_y_val           sf ptr ptr ptr ptr                            (void) mgl_contf_y_val
+libmgl      mgl_contf_z_val           sf ptr ptr ptr ptr                            (void) mgl_contf_z_val
+libmgl      mgl_data_rearrange        int int int ptr                               (void) mgl_data_rearrange
+libmgl      mgl_data_set_float        int int int sf ptr                            (void) mgl_data_set_float
+libmgl      mgl_data_set_double       int int int df ptr                            (void) mgl_data_set_double
+libmgl      mgl_data_set_float2       int int sf ptr                                (void) mgl_data_set_float2
+libmgl      mgl_data_set_double2      int int df ptr                                (void) mgl_data_set_double2
+libmgl      mgl_data_set_float3       int int int sf ptr                            (void) mgl_data_set_float3
+libmgl      mgl_data_set_double3      int int int ptr ptr                           (void) mgl_data_set_double3
+libmgl      mgl_data_set              ptr ptr                                       (void) mgl_data_set
+libmgl      mgl_data_set_vector       ptr ptr                                       (void) mgl_data_set_vector
+libmgl      mgl_data_set_matrix       ptr ptr                                       (void) mgl_data_set_matrix
+libmgl      mgl_data_get_value        int int int ptr                                 (fp) mgl_data_get_value
+libmgl      mgl_data_get_nx           ptr                                            (int) mgl_data_get_nx
+libmgl      mgl_data_get_ny           ptr                                            (int) mgl_data_get_ny
+libmgl      mgl_data_get_nz           ptr                                            (int) mgl_data_get_nz
+libmgl      mgl_data_set_value        int int int sf ptr                            (void) mgl_data_set_value
+libmgl      mgl_data_set_values       int int int ptr ptr                           (void) mgl_data_set_values
+libmgl      mgl_data_read             ptr ptr                                        (int) mgl_data_read
+libmgl      mgl_data_read_mat         int ptr ptr                                    (int) mgl_data_read_mat
+libmgl      mgl_data_read_dim         int int int ptr ptr                            (int) mgl_data_read_dim
+libmgl      mgl_data_save             int ptr ptr                                   (void) mgl_data_save
+libmgl      mgl_data_export           int sf sf ptr ptr ptr                         (void) mgl_data_export
+libmgl      mgl_data_import           sf sf ptr ptr ptr                             (void) mgl_data_import
+libmgl      mgl_data_create           int int int ptr                               (void) mgl_data_create
+libmgl      mgl_data_transpose        ptr ptr                                       (void) mgl_data_transpose
+libmgl      mgl_data_norm             int int sf sf ptr                             (void) mgl_data_norm
+libmgl      mgl_data_norm_slice       int int ptr sf sf ptr                         (void) mgl_data_norm_slice
+libmgl      mgl_data_subdata          int int int ptr                                (ptr) mgl_data_subdata
+libmgl      mgl_data_column           ptr ptr                                        (ptr) mgl_data_column
+libmgl      mgl_data_set_id           ptr ptr                                       (void) mgl_data_set_id
+libmgl      mgl_data_fill             ptr sf sf ptr                                 (void) mgl_data_fill
+libmgl      mgl_data_fill_eq          ptr ptr ptr ptr ptr                           (void) mgl_data_fill_eq
+libmgl      mgl_data_put_val          int int int sf ptr                            (void) mgl_data_put_val
+libmgl      mgl_data_put_dat          int int int ptr ptr                           (void) mgl_data_put_dat
+libmgl      mgl_data_modify           int ptr ptr                                   (void) mgl_data_modify
+libmgl      mgl_data_modify_vw        ptr ptr ptr ptr                               (void) mgl_data_modify_vw
+libmgl      mgl_data_squeeze          int int int int ptr                           (void) mgl_data_squeeze
+libmgl      mgl_data_max              ptr                                             (fp) mgl_data_max
+libmgl      mgl_data_min              ptr                                             (fp) mgl_data_min
+libmgl      mgl_data_value            int int int ptr                                 (fp) mgl_data_value
+libmgl      mgl_data_combine          ptr ptr                                        (ptr) mgl_data_combine
+libmgl      mgl_data_extend           int int ptr                                   (void) mgl_data_extend
+libmgl      mgl_data_insert           int int ptr ptr                               (void) mgl_data_insert
+libmgl      mgl_data_delete           int int ptr ptr                               (void) mgl_data_delete
+libmgl      mgl_data_smooth           ptr sf int ptr                                (void) mgl_data_smooth
+libmgl      mgl_data_sum              ptr ptr                                        (ptr) mgl_data_sum
+libmgl      mgl_data_max_dir          ptr ptr                                        (ptr) mgl_data_max_dir
+libmgl      mgl_data_min_dir          ptr ptr                                        (ptr) mgl_data_min_dir
+libmgl      mgl_data_cumsum           ptr ptr                                       (void) mgl_data_cumsum
+libmgl      mgl_data_integral         ptr ptr                                       (void) mgl_data_integral
+libmgl      mgl_data_diff             ptr ptr                                       (void) mgl_data_diff
+libmgl      mgl_data_diff_par         ptr ptr ptr ptr                               (void) mgl_data_diff_par
+libmgl      mgl_data_diff2            ptr ptr                                       (void) mgl_data_diff2
+libmgl      mgl_data_swap             ptr ptr                                       (void) mgl_data_swap
+libmgl      mgl_data_mirror           ptr ptr                                       (void) mgl_data_mirror
+libmgl      mgl_data_spline           sf sf sf ptr                                    (fp) mgl_data_spline
+libmgl      mgl_data_spline1          sf sf sf ptr                                    (fp) mgl_data_spline1
+libmgl      mgl_data_linear           sf sf sf ptr                                    (fp) mgl_data_linear
+libmgl      mgl_data_linear1          sf sf sf ptr                                    (fp) mgl_data_linear1
+libmgl      mgl_data_resize           int int int ptr                                (ptr) mgl_data_resize
+libmgl      mgl_data_resize_box                                                      (ptr) mgl_data_resize_box
+libmgl      mgl_data_hist             int sf sf int ptr                              (ptr) mgl_data_hist
+libmgl      mgl_data_hist_w           int sf sf int ptr ptr                          (ptr) mgl_data_hist_w
+libmgl      mgl_data_momentum         ptr ptr ptr                                    (ptr) mgl_data_momentum
+libmgl      mgl_data_evaluate_i       int ptr ptr                                    (ptr) mgl_data_evaluate_i
+libmgl      mgl_data_evaluate_ij      int ptr ptr ptr                                (ptr) mgl_data_evaluate_ij
+libmgl      mgl_data_evaluate_ijk     int ptr ptr ptr ptr                            (ptr) mgl_data_evaluate_ijk
+libmgl      mgl_data_envelop          ptr ptr                                       (void) mgl_data_envelop
+libmgl      mgl_data_sew              sf ptr ptr                                    (void) mgl_data_sew
+libmgl      mgl_data_crop             ptr int int ptr                               (void) mgl_data_crop
+libmgl      mgl_data_mul_dat          ptr ptr                                       (void) mgl_data_mul_dat
+libmgl      mgl_data_div_dat          ptr ptr                                       (void) mgl_data_div_dat
+libmgl      mgl_data_add_dat          ptr ptr                                       (void) mgl_data_add_dat
+libmgl      mgl_data_sub_dat          ptr ptr                                       (void) mgl_data_sub_dat
+libmgl      mgl_data_mul_num          sf ptr                                        (void) mgl_data_mul_num
+libmgl      mgl_data_div_num          sf ptr                                        (void) mgl_data_div_num
+libmgl      mgl_data_add_num          sf ptr                                        (void) mgl_data_add_num
+libmgl      mgl_data_sub_num          sf ptr                                        (void) mgl_data_sub_num
+libmgl      mgl_fit_1                 sf ptr ptr ptr ptr ptr                          (fp) mgl_fit_1
+libmgl      mgl_fit_2                 sf ptr ptr ptr ptr ptr                          (fp) mgl_fit_2
+libmgl      mgl_fit_3                 sf ptr ptr ptr ptr ptr                          (fp) mgl_fit_3
+libmgl      mgl_fit_xy                sf ptr ptr ptr ptr ptr ptr                      (fp) mgl_fit_xy
+libmgl      mgl_fit_xyz               sf ptr ptr ptr ptr ptr ptr ptr                  (fp) mgl_fit_xyz
+libmgl      mgl_fit_xyza              sf ptr ptr ptr ptr ptr ptr ptr ptr              (fp) mgl_fit_xyza
+libmgl      mgl_fit_ys                sf ptr ptr ptr ptr ptr ptr                      (fp) mgl_fit_ys
+libmgl      mgl_fit_xys               sf ptr ptr ptr ptr ptr ptr ptr                  (fp) mgl_fit_xys
+libmgl      mgl_fit_xyzs              sf ptr ptr ptr ptr ptr ptr ptr ptr              (fp) mgl_fit_xyzs
+libmgl      mgl_fit_xyzas             sf ptr ptr ptr ptr ptr ptr ptr ptr ptr          (fp) mgl_fit_xyzas
+libmgl      mgl_fit_1_d               ptr ptr ptr ptr ptr ptr                         (fp) mgl_fit_1_d
+libmgl      mgl_fit_2_d               ptr ptr ptr ptr ptr ptr                         (fp) mgl_fit_2_d
+libmgl      mgl_fit_3_d               ptr ptr ptr ptr ptr ptr                         (fp) mgl_fit_3_d
+libmgl      mgl_fit_xy_d              ptr ptr ptr ptr ptr ptr ptr                     (fp) mgl_fit_xy_d
+libmgl      mgl_fit_xyz_d             ptr ptr ptr ptr ptr ptr ptr ptr                 (fp) mgl_fit_xyz_d
+libmgl      mgl_fit_xyza_d            ptr ptr ptr ptr ptr ptr ptr ptr ptr             (fp) mgl_fit_xyza_d
+libmgl      mgl_fit_ys_d              ptr ptr ptr ptr ptr ptr ptr                     (fp) mgl_fit_ys_d
+libmgl      mgl_fit_xys_d             ptr ptr ptr ptr ptr ptr ptr ptr                 (fp) mgl_fit_xys_d
+libmgl      mgl_fit_xyzs_d            ptr ptr ptr ptr ptr ptr ptr ptr ptr             (fp) mgl_fit_xyzs_d
+libmgl      mgl_fit_xyzas_d           ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr         (fp) mgl_fit_xyzas_d
+libmgl      mgl_puts_fit              sf ptr ptr sf sf sf ptr                       (void) mgl_puts_fit
+libmgl      mgl_sphere                ptr sf sf sf sf ptr                           (void) mgl_sphere
+libmgl      mgl_drop                  sf sf ptr sf sf sf sf sf sf sf ptr            (void) mgl_drop
+libmgl      mgl_cone                  int ptr sf sf sf sf sf sf sf sf ptr           (void) mgl_cone
+libmgl      mgl_pde_solve             sf sf ptr ptr ptr ptr                          (ptr) mgl_pde_solve
+libmgl      mgl_qo2d_solve            ptr ptr sf sf ptr ptr ptr ptr                  (ptr) mgl_qo2d_solve
+libmgl      mgl_af2d_solve            ptr ptr sf sf ptr ptr ptr ptr                  (ptr) mgl_af2d_solve
+libmgl      mgl_ray_trace             sf sf sf sf sf sf sf sf ptr                    (ptr) mgl_ray_trace
+libmgl      mgl_jacobian_2d           ptr ptr                                        (ptr) mgl_jacobian_2d
+libmgl      mgl_jacobian_3d           ptr ptr ptr                                    (ptr) mgl_jacobian_3d
+libmgl      mgl_transform_a           ptr ptr ptr                                    (ptr) mgl_transform_a
+libmgl      mgl_transform             ptr ptr ptr                                    (ptr) mgl_transform
+libmgl      mgl_data_stfa             ptr int ptr ptr                                (ptr) mgl_data_stfa
+
+legacy on
+
+previous
+Module;
diff --git a/include/mgl2/mgl.fs b/include/mgl2/mgl.fs
new file mode 100644
index 0000000..32eb460
--- /dev/null
+++ b/include/mgl2/mgl.fs
@@ -0,0 +1,608 @@
+\ Mathgl library wrapper
+\ Copyright (C) 2008-2013, Sergey Plis, Alexey Balakin
+\
+\ 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.
+
+Module mathgl
+library libmgl      libmgl.so
+library libmgl-glut libmgl-glut.so
+library libmgl-fltk libmgl-fltk.so
+library libmgl-qt   libmgl-qt.so
+library libmgl-wx   libmgl-wx.so
+legacy off
+
+libmgl mgl_create_graph_gl		(ptr)	mgl_create_graph_gl
+libmgl-glut mgl_create_graph_glut	ptr ptr ptr	(ptr)	mgl_create_graph_glut
+libmgl-fltk mgl_create_graph_fltk	ptr ptr ptr	(ptr)	mgl_create_graph_fltk
+libmgl-fltk mgl_fltk_run		(void)	mgl_fltk_run
+libmgl-qt   mgl_create_graph_qt	ptr ptr ptr	(ptr)	mgl_create_graph_qt
+libmgl-qt   mgl_qt_run			(void)	mgl_qt_run
+
+libmgl mgl_get_warn				ptr 	(int)	mgl_get_warn
+libmgl mgl_set_warn				ptr int ptr 	(void)	mgl_set_warn
+libmgl gl_get_mess				ptr 	(ptr)	gl_get_mess
+libmgl mgl_set_plotid			ptr ptr 	(void)	mgl_set_plotid
+libmgl gl_get_plotid			ptr 	(ptr)	gl_get_plotid
+libmgl mgl_get_quality			ptr 	(int)	mgl_get_quality
+libmgl mgl_set_quality			int ptr 	(void)	mgl_set_quality
+libmgl mgl_set_draw_reg			int int int ptr 	(void)	mgl_set_draw_reg
+libmgl mgl_is_frames			ptr 	(int)	mgl_is_frames
+libmgl mgl_get_flag				int ptr 	(int)	mgl_get_flag
+libmgl mgl_set_flag				int int ptr 	(void)	mgl_set_flag
+libmgl mgl_use_graph			int ptr 	(int)	mgl_use_graph
+libmgl mgl_start_group			ptr ptr 	(void)	mgl_start_group
+libmgl mgl_end_group			ptr 	(void)	mgl_end_group
+libmgl mgl_highlight			int ptr 	(void)	mgl_highlight
+libmgl mgl_set_palette			ptr ptr 	(void)	mgl_set_palette
+libmgl mgl_set_color			double double double char 	(void)	mgl_set_color
+libmgl mgl_set_def_sch			ptr ptr 	(void)	mgl_set_def_sch
+libmgl mgl_set_mask				ptr char 	(void)	mgl_set_mask
+libmgl mgl_set_mask_angle		int ptr 	(void)	mgl_set_mask_angle
+libmgl mgl_set_alpha_default	double ptr 	(void)	mgl_set_alpha_default
+libmgl mgl_set_bar_width		double ptr 	(void)	mgl_set_bar_width
+libmgl mgl_set_meshnum			int ptr 	(void)	mgl_set_meshnum
+libmgl mgl_set_facenum			int ptr 	(void)	mgl_set_facenum
+libmgl mgl_clear_unused			ptr 	(void)	mgl_clear_unused
+libmgl mgl_set_ambbr			double ptr 	(void)	mgl_set_ambbr
+libmgl mgl_set_difbr			double ptr 	(void)	mgl_set_difbr
+libmgl mgl_set_light_dif		int ptr 	(void)	mgl_set_light_dif
+libmgl mgl_set_cut				int ptr 	(void)	mgl_set_cut
+libmgl mgl_set_cut_box			double double double double double double ptr 	(void)	mgl_set_cut_box
+libmgl mgl_set_cutoff			ptr ptr 	(void)	mgl_set_cutoff
+libmgl mgl_set_ranges			double double double double double double ptr 	(void)	mgl_set_ranges
+libmgl mgl_set_range_val		double double char ptr 	(void)	mgl_set_range_val
+libmgl mgl_set_range_dat		int ptr char ptr 	(void)	mgl_set_range_dat
+libmgl mgl_set_auto_ranges		double double double double double double double double ptr 	(void)	mgl_set_auto_ranges
+libmgl mgl_zoom_axis			double double double double double double double double ptr 	(void)	mgl_zoom_axis
+libmgl mgl_set_origin			double double double ptr 	(void)	mgl_set_origin
+libmgl mgl_set_func				ptr ptr ptr ptr ptr 	(void)	mgl_set_func
+libmgl mgl_set_coor				int ptr 	(void)	mgl_set_coor
+libmgl mgl_set_ternary			int ptr 	(void)	mgl_set_ternary
+libmgl mgl_set_tick_rotate		int ptr 	(void)	mgl_set_tick_rotate
+libmgl mgl_set_tick_skip		int ptr 	(void)	mgl_set_tick_skip
+libmgl mgl_def_font				ptr ptr 	(void)	mgl_def_font
+libmgl mgl_set_mark_size		double ptr 	(void)	mgl_set_mark_size
+libmgl mgl_set_arrow_size		double ptr 	(void)	mgl_set_arrow_size
+libmgl mgl_set_font_size		double ptr 	(void)	mgl_set_font_size
+libmgl mgl_set_font_def			ptr ptr 	(void)	mgl_set_font_def
+libmgl mgl_set_rotated_text		int ptr 	(void)	mgl_set_rotated_text
+libmgl mgl_load_font			ptr ptr ptr 	(void)	mgl_load_font
+libmgl mgl_copy_font			ptr ptr 	(void)	mgl_copy_font
+libmgl mgl_restore_font			ptr 	(void)	mgl_restore_font
+libmgl mgl_srnd					int 	(void)	mgl_srnd
+libmgl mgl_rnd						(double)	mgl_rnd
+libmgl mgl_ipow					int double 	(double)	mgl_ipow
+libmgl mgl_get_time				ptr ptr 	(double)	mgl_get_time
+libmgl mgl_create_data				(ptr)	mgl_create_data
+libmgl mgl_create_data_size		int int int 	(ptr)	mgl_create_data_size
+libmgl mgl_create_data_file		ptr 	(ptr)	mgl_create_data_file
+libmgl mgl_delete_data			ptr 	(void)	mgl_delete_data
+libmgl gl_data_info				ptr 	(ptr)	gl_data_info
+libmgl mgl_data_rearrange		int int int ptr 	(void)	mgl_data_rearrange
+libmgl mgl_data_link			int int int ptr ptr 	(void)	mgl_data_link
+libmgl mgl_data_set_float		int int int ptr ptr 	(void)	mgl_data_set_float
+libmgl mgl_data_set_double		int int int ptr ptr 	(void)	mgl_data_set_double
+libmgl mgl_data_set				ptr ptr 	(void)	mgl_data_set
+libmgl mgl_data_set_vector		ptr ptr 	(void)	mgl_data_set_vector
+libmgl mgl_data_set_matrix		ptr ptr 	(void)	mgl_data_set_matrix
+libmgl mgl_data_set_value		int int int sf ptr 	(void)	mgl_data_set_value
+libmgl mgl_data_get_value		int int int ptr 	(sf)	mgl_data_get_value
+libmgl mgl_data_set_values		int int int ptr ptr 	(void)	mgl_data_set_values
+libmgl mgl_data_read_hdf		ptr ptr ptr 	(int)	mgl_data_read_hdf
+libmgl mgl_data_save_hdf		int ptr ptr ptr 	(void)	mgl_data_save_hdf
+libmgl mgl_datas_hdf			int ptr ptr 	(int)	mgl_datas_hdf
+libmgl mgl_data_read			ptr ptr 	(int)	mgl_data_read
+libmgl mgl_data_read_mat		int ptr ptr 	(int)	mgl_data_read_mat
+libmgl mgl_data_read_dim		int int int ptr ptr 	(int)	mgl_data_read_dim
+libmgl mgl_data_read_range		int double double double ptr ptr 	(int)	mgl_data_read_range
+libmgl mgl_data_read_all		int ptr ptr 	(int)	mgl_data_read_all
+libmgl mgl_data_save			int ptr ptr 	(void)	mgl_data_save
+libmgl mgl_data_export			int sf sf ptr ptr ptr 	(void)	mgl_data_export
+libmgl mgl_data_import			sf sf ptr ptr ptr 	(void)	mgl_data_import
+libmgl mgl_data_create			int int int ptr 	(void)	mgl_data_create
+libmgl mgl_data_transpose		ptr ptr 	(void)	mgl_data_transpose
+libmgl mgl_data_norm			int int sf sf ptr 	(void)	mgl_data_norm
+libmgl mgl_data_norm_slice		int int char sf sf ptr 	(void)	mgl_data_norm_slice
+libmgl mgl_data_subdata			int int int ptr 	(ptr)	mgl_data_subdata
+libmgl mgl_data_subdata_ext		ptr ptr ptr ptr 	(ptr)	mgl_data_subdata_ext
+libmgl mgl_data_column			ptr ptr 	(ptr)	mgl_data_column
+libmgl mgl_data_set_id			ptr ptr 	(void)	mgl_data_set_id
+libmgl mgl_data_fill			char sf sf ptr 	(void)	mgl_data_fill
+libmgl mgl_data_fill_eq			ptr ptr ptr ptr ptr ptr 	(void)	mgl_data_fill_eq
+libmgl mgl_data_refill_x		int sf sf ptr ptr ptr 	(void)	mgl_data_refill_x
+libmgl mgl_data_refill_xy		int sf sf sf sf ptr ptr ptr ptr 	(void)	mgl_data_refill_xy
+libmgl mgl_data_refill_xyz		sf sf sf sf sf sf ptr ptr ptr ptr ptr 	(void)	mgl_data_refill_xyz
+libmgl mgl_data_refill_gr		ptr int ptr ptr ptr ptr ptr ptr 	(void)	mgl_data_refill_gr
+libmgl mgl_data_grid			ptr ptr ptr ptr ptr ptr 	(void)	mgl_data_grid
+libmgl mgl_data_grid_xy			sf sf sf sf ptr ptr ptr ptr 	(void)	mgl_data_grid_xy
+libmgl mgl_data_put_val			int int int sf ptr 	(void)	mgl_data_put_val
+libmgl mgl_data_put_dat			int int int ptr ptr 	(void)	mgl_data_put_dat
+libmgl mgl_data_modify			int ptr ptr 	(void)	mgl_data_modify
+libmgl mgl_data_modify_vw		ptr ptr ptr ptr 	(void)	mgl_data_modify_vw
+libmgl mgl_data_squeeze			int int int int ptr 	(void)	mgl_data_squeeze
+libmgl mgl_data_max				ptr 	(sf)	mgl_data_max
+libmgl mgl_data_min				ptr 	(sf)	mgl_data_min
+libmgl gl_data_value			int int int ptr 	(ptr)	gl_data_value
+libmgl gl_data_data				ptr 	(ptr)	gl_data_data
+libmgl mgl_data_get_nx			ptr 	(int)	mgl_data_get_nx
+libmgl mgl_data_get_ny			ptr 	(int)	mgl_data_get_ny
+libmgl mgl_data_get_nz			ptr 	(int)	mgl_data_get_nz
+libmgl mgl_data_first			ptr ptr ptr ptr ptr 	(sf)	mgl_data_first
+libmgl mgl_data_last			ptr ptr ptr ptr ptr 	(sf)	mgl_data_last
+libmgl mgl_data_find			int int int char ptr ptr 	(int)	mgl_data_find
+libmgl mgl_data_find_any		ptr ptr 	(int)	mgl_data_find_any
+libmgl mgl_data_max_int			ptr ptr ptr ptr 	(sf)	mgl_data_max_int
+libmgl mgl_data_max_real		ptr ptr ptr ptr 	(sf)	mgl_data_max_real
+libmgl mgl_data_min_int			ptr ptr ptr ptr 	(sf)	mgl_data_min_int
+libmgl mgl_data_min_real		ptr ptr ptr ptr 	(sf)	mgl_data_min_real
+libmgl mgl_data_momentum_val	ptr ptr ptr ptr char ptr 	(sf)	mgl_data_momentum_val
+libmgl mgl_data_combine			ptr ptr 	(ptr)	mgl_data_combine
+libmgl mgl_data_extend			int int ptr 	(void)	mgl_data_extend
+libmgl mgl_data_insert			int int char ptr 	(void)	mgl_data_insert
+libmgl mgl_data_delete			int int char ptr 	(void)	mgl_data_delete
+libmgl mgl_data_join			ptr ptr 	(void)	mgl_data_join
+libmgl mgl_data_smooth			sf ptr ptr 	(void)	mgl_data_smooth
+libmgl mgl_data_sum				ptr ptr 	(ptr)	mgl_data_sum
+libmgl mgl_data_max_dir			ptr ptr 	(ptr)	mgl_data_max_dir
+libmgl mgl_data_min_dir			ptr ptr 	(ptr)	mgl_data_min_dir
+libmgl mgl_data_cumsum			ptr ptr 	(void)	mgl_data_cumsum
+libmgl mgl_data_integral		ptr ptr 	(void)	mgl_data_integral
+libmgl mgl_data_diff			ptr ptr 	(void)	mgl_data_diff
+libmgl mgl_data_diff_par		ptr ptr ptr ptr 	(void)	mgl_data_diff_par
+libmgl mgl_data_diff2			ptr ptr 	(void)	mgl_data_diff2
+libmgl mgl_data_swap			ptr ptr 	(void)	mgl_data_swap
+libmgl mgl_data_roll			int char ptr 	(void)	mgl_data_roll
+libmgl mgl_data_mirror			ptr ptr 	(void)	mgl_data_mirror
+libmgl mgl_data_sort			int int ptr 	(void)	mgl_data_sort
+libmgl mgl_data_hankel			ptr ptr 	(void)	mgl_data_hankel
+libmgl mgl_data_sinfft			ptr ptr 	(void)	mgl_data_sinfft
+libmgl mgl_data_cosfft			ptr ptr 	(void)	mgl_data_cosfft
+libmgl mgl_data_fill_sample		ptr ptr 	(void)	mgl_data_fill_sample
+libmgl mgl_data_correl			ptr ptr ptr 	(ptr)	mgl_data_correl
+libmgl mgl_clear_fft				(void)	mgl_clear_fft
+libmgl mgl_data_spline			sf sf sf ptr 	(sf)	mgl_data_spline
+libmgl mgl_data_linear			sf sf sf ptr 	(sf)	mgl_data_linear
+libmgl mgl_data_spline_ext		ptr ptr ptr sf sf sf ptr 	(sf)	mgl_data_spline_ext
+libmgl mgl_data_linear_ext		ptr ptr ptr sf sf sf ptr 	(sf)	mgl_data_linear_ext
+libmgl mgl_data_solve_1d		int int sf ptr 	(sf)	mgl_data_solve_1d
+libmgl mgl_data_solve			int ptr char sf ptr 	(ptr)	mgl_data_solve
+libmgl mgl_data_trace			ptr 	(ptr)	mgl_data_trace
+libmgl mgl_data_resize			int int int ptr 	(ptr)	mgl_data_resize
+libmgl mgl_data_resize_box		sf sf sf sf sf sf int int int ptr 	(ptr)	mgl_data_resize_box
+libmgl mgl_data_hist			int sf sf int ptr 	(ptr)	mgl_data_hist
+libmgl mgl_data_hist_w			int sf sf int ptr ptr 	(ptr)	mgl_data_hist_w
+libmgl mgl_data_momentum		ptr char ptr 	(ptr)	mgl_data_momentum
+libmgl mgl_data_evaluate		int ptr ptr ptr ptr 	(ptr)	mgl_data_evaluate
+libmgl mgl_data_envelop			char ptr 	(void)	mgl_data_envelop
+libmgl mgl_data_sew				sf ptr ptr 	(void)	mgl_data_sew
+libmgl mgl_data_crop			char int int ptr 	(void)	mgl_data_crop
+libmgl mgl_data_clean			int ptr 	(void)	mgl_data_clean
+libmgl mgl_data_mul_dat			ptr ptr 	(void)	mgl_data_mul_dat
+libmgl mgl_data_div_dat			ptr ptr 	(void)	mgl_data_div_dat
+libmgl mgl_data_add_dat			ptr ptr 	(void)	mgl_data_add_dat
+libmgl mgl_data_sub_dat			ptr ptr 	(void)	mgl_data_sub_dat
+libmgl mgl_data_mul_num			sf ptr 	(void)	mgl_data_mul_num
+libmgl mgl_data_div_num			sf ptr 	(void)	mgl_data_div_num
+libmgl mgl_data_add_num			sf ptr 	(void)	mgl_data_add_num
+libmgl mgl_data_sub_num			sf ptr 	(void)	mgl_data_sub_num
+libmgl mgl_transform_a			ptr ptr ptr 	(ptr)	mgl_transform_a
+libmgl mgl_transform			ptr ptr ptr 	(ptr)	mgl_transform
+libmgl mgl_data_fourier			ptr ptr ptr 	(void)	mgl_data_fourier
+libmgl mgl_data_stfa			char int ptr ptr 	(ptr)	mgl_data_stfa
+libmgl mgl_triangulation_3d		ptr ptr ptr 	(ptr)	mgl_triangulation_3d
+libmgl mgl_triangulation_2d		ptr ptr 	(ptr)	mgl_triangulation_2d
+libmgl mgl_find_root_txt		char sf ptr 	(sf)	mgl_find_root_txt
+libmgl mgl_data_roots			char ptr ptr 	(ptr)	mgl_data_roots
+libmgl mgl_datac_save			int ptr ptr 	(void)	mgl_datac_save
+libmgl mgl_datac_save_hdf		int ptr ptr ptr 	(void)	mgl_datac_save_hdf
+libmgl mgl_datac_real			ptr 	(ptr)	mgl_datac_real
+libmgl mgl_datac_imag			ptr 	(ptr)	mgl_datac_imag
+libmgl mgl_datac_abs			ptr 	(ptr)	mgl_datac_abs
+libmgl mgl_datac_arg			ptr 	(ptr)	mgl_datac_arg
+libmgl mgl_text_xyz				ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_text_xyz
+libmgl mgl_textw_xyz			ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_textw_xyz
+libmgl mgl_text_xy				ptr ptr ptr ptr ptr ptr 	(void)	mgl_text_xy
+libmgl mgl_textw_xy				ptr ptr ptr ptr ptr ptr 	(void)	mgl_textw_xy
+libmgl mgl_text_y				ptr ptr ptr ptr ptr 	(void)	mgl_text_y
+libmgl mgl_textw_y				ptr ptr ptr ptr ptr 	(void)	mgl_textw_y
+libmgl mgl_cont_gen				ptr ptr ptr ptr ptr double ptr 	(void)	mgl_cont_gen
+libmgl mgl_contf_gen			ptr ptr ptr ptr ptr double double ptr 	(void)	mgl_contf_gen
+libmgl mgl_cont_xy_val			ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_cont_xy_val
+libmgl mgl_cont_val				ptr ptr ptr ptr ptr 	(void)	mgl_cont_val
+libmgl mgl_cont_xy				ptr ptr ptr ptr ptr ptr 	(void)	mgl_cont_xy
+libmgl mgl_cont					ptr ptr ptr ptr 	(void)	mgl_cont
+libmgl mgl_contf_xy_val			ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_contf_xy_val
+libmgl mgl_contf_val			ptr ptr ptr ptr ptr 	(void)	mgl_contf_val
+libmgl mgl_contf_xy				ptr ptr ptr ptr ptr ptr 	(void)	mgl_contf_xy
+libmgl mgl_contf				ptr ptr ptr ptr 	(void)	mgl_contf
+libmgl mgl_contd_xy_val			ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_contd_xy_val
+libmgl mgl_contd_val			ptr ptr ptr ptr ptr 	(void)	mgl_contd_val
+libmgl mgl_contd_xy				ptr ptr ptr ptr ptr ptr 	(void)	mgl_contd_xy
+libmgl mgl_contd				ptr ptr ptr ptr 	(void)	mgl_contd
+libmgl mgl_contv_xy_val			ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_contv_xy_val
+libmgl mgl_contv_val			ptr ptr ptr ptr ptr 	(void)	mgl_contv_val
+libmgl mgl_contv_xy				ptr ptr ptr ptr ptr ptr 	(void)	mgl_contv_xy
+libmgl mgl_contv				ptr ptr ptr ptr 	(void)	mgl_contv
+libmgl mgl_axial_xy_val			ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_axial_xy_val
+libmgl mgl_axial_val			ptr ptr ptr ptr ptr 	(void)	mgl_axial_val
+libmgl mgl_axial_xy				ptr ptr ptr ptr ptr ptr 	(void)	mgl_axial_xy
+libmgl mgl_axial				ptr ptr ptr ptr 	(void)	mgl_axial
+libmgl mgl_torus				ptr ptr ptr ptr ptr 	(void)	mgl_torus
+libmgl mgl_grid3_xyz			ptr double ptr ptr ptr ptr ptr ptr 	(void)	mgl_grid3_xyz
+libmgl mgl_grid3				ptr double ptr ptr ptr 	(void)	mgl_grid3
+libmgl mgl_dens3_xyz			ptr double ptr ptr ptr ptr ptr ptr 	(void)	mgl_dens3_xyz
+libmgl mgl_dens3				ptr double ptr ptr ptr 	(void)	mgl_dens3
+libmgl mgl_cont3_xyz_val		ptr double ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_cont3_xyz_val
+libmgl mgl_cont3_val			ptr double ptr ptr ptr ptr 	(void)	mgl_cont3_val
+libmgl mgl_cont3_xyz			ptr double ptr ptr ptr ptr ptr ptr 	(void)	mgl_cont3_xyz
+libmgl mgl_cont3				ptr double ptr ptr ptr 	(void)	mgl_cont3
+libmgl mgl_contf3_xyz_val		ptr double ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_contf3_xyz_val
+libmgl mgl_contf3_val			ptr double ptr ptr ptr ptr 	(void)	mgl_contf3_val
+libmgl mgl_contf3_xyz			ptr double ptr ptr ptr ptr ptr ptr 	(void)	mgl_contf3_xyz
+libmgl mgl_contf3				ptr double ptr ptr ptr 	(void)	mgl_contf3
+libmgl mgl_fit_1				ptr ptr ptr ptr ptr ptr 	(ptr)	mgl_fit_1
+libmgl mgl_fit_2				ptr ptr ptr ptr ptr ptr 	(ptr)	mgl_fit_2
+libmgl mgl_fit_3				ptr ptr ptr ptr ptr ptr 	(ptr)	mgl_fit_3
+libmgl mgl_fit_xy				ptr ptr ptr ptr ptr ptr ptr 	(ptr)	mgl_fit_xy
+libmgl mgl_fit_xyz				ptr ptr ptr ptr ptr ptr ptr ptr 	(ptr)	mgl_fit_xyz
+libmgl mgl_fit_xyza				ptr ptr ptr ptr ptr ptr ptr ptr ptr 	(ptr)	mgl_fit_xyza
+libmgl mgl_fit_ys				ptr ptr ptr ptr ptr ptr ptr 	(ptr)	mgl_fit_ys
+libmgl mgl_fit_xys				ptr ptr ptr ptr ptr ptr ptr ptr 	(ptr)	mgl_fit_xys
+libmgl mgl_fit_xyzs				ptr ptr ptr ptr ptr ptr ptr ptr ptr 	(ptr)	mgl_fit_xyzs
+libmgl mgl_fit_xyzas			ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr 	(ptr)	mgl_fit_xyzas
+libmgl gl_get_fit				ptr 	(ptr)	gl_get_fit
+libmgl mgl_hist_x				ptr ptr ptr ptr 	(ptr)	mgl_hist_x
+libmgl mgl_hist_xy				ptr ptr ptr ptr ptr 	(ptr)	mgl_hist_xy
+libmgl mgl_hist_xyz				ptr ptr ptr ptr ptr ptr 	(ptr)	mgl_hist_xyz
+libmgl mgl_puts_fit				double ptr ptr double double double ptr 	(void)	mgl_puts_fit
+libmgl mgl_fplot				ptr ptr ptr ptr 	(void)	mgl_fplot
+libmgl mgl_fplot_xyz			ptr ptr ptr ptr ptr ptr 	(void)	mgl_fplot_xyz
+libmgl mgl_radar				ptr ptr ptr ptr 	(void)	mgl_radar
+libmgl mgl_plot_xyz				ptr ptr ptr ptr ptr ptr 	(void)	mgl_plot_xyz
+libmgl mgl_plot_xy				ptr ptr ptr ptr ptr 	(void)	mgl_plot_xy
+libmgl mgl_plot					ptr ptr ptr ptr 	(void)	mgl_plot
+libmgl mgl_tens_xyz				ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_tens_xyz
+libmgl mgl_tens_xy				ptr ptr ptr ptr ptr ptr 	(void)	mgl_tens_xy
+libmgl mgl_tens					ptr ptr ptr ptr ptr 	(void)	mgl_tens
+libmgl mgl_tape_xyz				ptr ptr ptr ptr ptr ptr 	(void)	mgl_tape_xyz
+libmgl mgl_tape_xy				ptr ptr ptr ptr ptr 	(void)	mgl_tape_xy
+libmgl mgl_tape					ptr ptr ptr ptr 	(void)	mgl_tape
+libmgl mgl_boxplot_xy			ptr ptr ptr ptr ptr 	(void)	mgl_boxplot_xy
+libmgl mgl_boxplot				ptr ptr ptr ptr 	(void)	mgl_boxplot
+libmgl mgl_area_xyz				ptr ptr ptr ptr ptr ptr 	(void)	mgl_area_xyz
+libmgl mgl_area_xy				ptr ptr ptr ptr ptr 	(void)	mgl_area_xy
+libmgl mgl_area					ptr ptr ptr ptr 	(void)	mgl_area
+libmgl mgl_region_xy			ptr ptr ptr ptr ptr ptr 	(void)	mgl_region_xy
+libmgl mgl_region				ptr ptr ptr ptr ptr 	(void)	mgl_region
+libmgl mgl_stem_xyz				ptr ptr ptr ptr ptr ptr 	(void)	mgl_stem_xyz
+libmgl mgl_stem_xy				ptr ptr ptr ptr ptr 	(void)	mgl_stem_xy
+libmgl mgl_stem					ptr ptr ptr ptr 	(void)	mgl_stem
+libmgl mgl_step_xyz				ptr ptr ptr ptr ptr ptr 	(void)	mgl_step_xyz
+libmgl mgl_step_xy				ptr ptr ptr ptr ptr 	(void)	mgl_step_xy
+libmgl mgl_step					ptr ptr ptr ptr 	(void)	mgl_step
+libmgl mgl_bars_xyz				ptr ptr ptr ptr ptr ptr 	(void)	mgl_bars_xyz
+libmgl mgl_bars_xy				ptr ptr ptr ptr ptr 	(void)	mgl_bars_xy
+libmgl mgl_bars					ptr ptr ptr ptr 	(void)	mgl_bars
+libmgl mgl_barh_yx				ptr ptr ptr ptr ptr 	(void)	mgl_barh_yx
+libmgl mgl_barh					ptr ptr ptr ptr 	(void)	mgl_barh
+libmgl mgl_ohlc_x				ptr ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_ohlc_x
+libmgl mgl_ohlc					ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_ohlc
+libmgl mgl_chart				ptr ptr ptr ptr 	(void)	mgl_chart
+libmgl mgl_error_exy			ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_error_exy
+libmgl mgl_error_xy				ptr ptr ptr ptr ptr ptr 	(void)	mgl_error_xy
+libmgl mgl_error				ptr ptr ptr ptr ptr 	(void)	mgl_error
+libmgl mgl_mark_xyz				ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_mark_xyz
+libmgl mgl_mark_xy				ptr ptr ptr ptr ptr ptr 	(void)	mgl_mark_xy
+libmgl mgl_mark_y				ptr ptr ptr ptr ptr 	(void)	mgl_mark_y
+libmgl mgl_tube_xyzr			ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_tube_xyzr
+libmgl mgl_tube_xyr				ptr ptr ptr ptr ptr ptr 	(void)	mgl_tube_xyr
+libmgl mgl_tube_r				ptr ptr ptr ptr ptr 	(void)	mgl_tube_r
+libmgl mgl_tube_xyz				ptr ptr double ptr ptr ptr ptr 	(void)	mgl_tube_xyz
+libmgl mgl_tube_xy				ptr ptr double ptr ptr ptr 	(void)	mgl_tube_xy
+libmgl mgl_tube					ptr ptr double ptr ptr 	(void)	mgl_tube
+libmgl mgl_candle_xyv			ptr ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_candle_xyv
+libmgl mgl_candle_yv			ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_candle_yv
+libmgl mgl_candle				ptr ptr ptr ptr ptr ptr 	(void)	mgl_candle
+libmgl mgl_fsurf				ptr ptr ptr ptr 	(void)	mgl_fsurf
+libmgl mgl_fsurf_xyz			ptr ptr ptr ptr ptr ptr 	(void)	mgl_fsurf_xyz
+libmgl mgl_grid_xy				ptr ptr ptr ptr ptr ptr 	(void)	mgl_grid_xy
+libmgl mgl_grid					ptr ptr ptr ptr 	(void)	mgl_grid
+libmgl mgl_mesh_xy				ptr ptr ptr ptr ptr ptr 	(void)	mgl_mesh_xy
+libmgl mgl_mesh					ptr ptr ptr ptr 	(void)	mgl_mesh
+libmgl mgl_fall_xy				ptr ptr ptr ptr ptr ptr 	(void)	mgl_fall_xy
+libmgl mgl_fall					ptr ptr ptr ptr 	(void)	mgl_fall
+libmgl mgl_belt_xy				ptr ptr ptr ptr ptr ptr 	(void)	mgl_belt_xy
+libmgl mgl_belt					ptr ptr ptr ptr 	(void)	mgl_belt
+libmgl mgl_surf_xy				ptr ptr ptr ptr ptr ptr 	(void)	mgl_surf_xy
+libmgl mgl_surf					ptr ptr ptr ptr 	(void)	mgl_surf
+libmgl mgl_dens_xy				ptr ptr ptr ptr ptr ptr 	(void)	mgl_dens_xy
+libmgl mgl_dens					ptr ptr ptr ptr 	(void)	mgl_dens
+libmgl mgl_boxs_xy				ptr ptr ptr ptr ptr ptr 	(void)	mgl_boxs_xy
+libmgl mgl_boxs					ptr ptr ptr ptr 	(void)	mgl_boxs
+libmgl mgl_tile_xy				ptr ptr ptr ptr ptr ptr 	(void)	mgl_tile_xy
+libmgl mgl_tile					ptr ptr ptr ptr 	(void)	mgl_tile
+libmgl mgl_tiles_xy				ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_tiles_xy
+libmgl mgl_tiles				ptr ptr ptr ptr ptr 	(void)	mgl_tiles
+libmgl mgl_surfc_xy				ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_surfc_xy
+libmgl mgl_surfc				ptr ptr ptr ptr ptr 	(void)	mgl_surfc
+libmgl mgl_surfa_xy				ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_surfa_xy
+libmgl mgl_surfa				ptr ptr ptr ptr ptr 	(void)	mgl_surfa
+libmgl mgl_stfa_xy				ptr ptr int ptr ptr ptr ptr ptr 	(void)	mgl_stfa_xy
+libmgl mgl_stfa					ptr ptr int ptr ptr ptr 	(void)	mgl_stfa
+libmgl mgl_map_xy				ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_map_xy
+libmgl mgl_map					ptr ptr ptr ptr ptr 	(void)	mgl_map
+libmgl mgl_surf3_xyz_val		ptr ptr ptr ptr ptr ptr double ptr 	(void)	mgl_surf3_xyz_val
+libmgl mgl_surf3_val			ptr ptr ptr double ptr 	(void)	mgl_surf3_val
+libmgl mgl_surf3_xyz			ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_surf3_xyz
+libmgl mgl_surf3				ptr ptr ptr ptr 	(void)	mgl_surf3
+libmgl mgl_surf3a_xyz_val		ptr ptr ptr ptr ptr ptr ptr double ptr 	(void)	mgl_surf3a_xyz_val
+libmgl mgl_surf3a_val			ptr ptr ptr ptr double ptr 	(void)	mgl_surf3a_val
+libmgl mgl_surf3a_xyz			ptr ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_surf3a_xyz
+libmgl mgl_surf3a				ptr ptr ptr ptr ptr 	(void)	mgl_surf3a
+libmgl mgl_surf3c_xyz_val		ptr ptr ptr ptr ptr ptr ptr double ptr 	(void)	mgl_surf3c_xyz_val
+libmgl mgl_surf3c_val			ptr ptr ptr ptr double ptr 	(void)	mgl_surf3c_val
+libmgl mgl_surf3c_xyz			ptr ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_surf3c_xyz
+libmgl mgl_surf3c				ptr ptr ptr ptr ptr 	(void)	mgl_surf3c
+libmgl mgl_cloud_xyz			ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_cloud_xyz
+libmgl mgl_cloud				ptr ptr ptr ptr 	(void)	mgl_cloud
+libmgl mgl_beam_val				int ptr double ptr ptr ptr ptr double ptr 	(void)	mgl_beam_val
+libmgl mgl_beam					int int ptr double ptr ptr ptr ptr ptr 	(void)	mgl_beam
+libmgl mgl_traj_xy				ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_traj_xy
+libmgl mgl_traj_xyz				ptr ptr ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_traj_xyz
+libmgl mgl_vect_xy				ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_vect_xy
+libmgl mgl_vect_2d				ptr ptr ptr ptr ptr 	(void)	mgl_vect_2d
+libmgl mgl_vect_xyz				ptr ptr ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_vect_xyz
+libmgl mgl_vect_3d				ptr ptr ptr ptr ptr ptr 	(void)	mgl_vect_3d
+libmgl mgl_flow_xy				ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_flow_xy
+libmgl mgl_flow_2d				ptr ptr ptr ptr ptr 	(void)	mgl_flow_2d
+libmgl mgl_flow_xyz				ptr ptr ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_flow_xyz
+libmgl mgl_flow_3d				ptr ptr ptr ptr ptr ptr 	(void)	mgl_flow_3d
+libmgl mgl_flowp_xy				ptr ptr ptr ptr ptr ptr double double double ptr 	(void)	mgl_flowp_xy
+libmgl mgl_flowp_2d				ptr ptr ptr ptr double double double ptr 	(void)	mgl_flowp_2d
+libmgl mgl_flowp_xyz			ptr ptr ptr ptr ptr ptr ptr ptr double double double ptr 	(void)	mgl_flowp_xyz
+libmgl mgl_flowp_3d				ptr ptr ptr ptr ptr double double double ptr 	(void)	mgl_flowp_3d
+libmgl mgl_pipe_xy				ptr double ptr ptr ptr ptr ptr ptr 	(void)	mgl_pipe_xy
+libmgl mgl_pipe_2d				ptr double ptr ptr ptr ptr 	(void)	mgl_pipe_2d
+libmgl mgl_pipe_xyz				ptr double ptr ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_pipe_xyz
+libmgl mgl_pipe_3d				ptr double ptr ptr ptr ptr ptr 	(void)	mgl_pipe_3d
+libmgl mgl_grad_xyz				ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_grad_xyz
+libmgl mgl_grad_xy				ptr ptr ptr ptr ptr ptr 	(void)	mgl_grad_xy
+libmgl mgl_grad					ptr ptr ptr ptr 	(void)	mgl_grad
+libmgl mgl_vect3_xyz			ptr double ptr ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_vect3_xyz
+libmgl mgl_vect3				ptr double ptr ptr ptr ptr ptr 	(void)	mgl_vect3
+libmgl mgl_mark					ptr double double double ptr 	(void)	mgl_mark
+libmgl mgl_ball					double double double ptr 	(void)	mgl_ball
+libmgl mgl_line					int ptr double double double double double double ptr 	(void)	mgl_line
+libmgl mgl_curve				int ptr double double double double double double double double double double double double ptr 	(void)	mgl_curve
+libmgl mgl_error_box			ptr double double double double double double ptr 	(void)	mgl_error_box
+libmgl mgl_face					ptr double double double double double double double double double double double double ptr 	(void)	mgl_face
+libmgl mgl_facex				double double ptr double double double double double ptr 	(void)	mgl_facex
+libmgl mgl_facey				double double ptr double double double double double ptr 	(void)	mgl_facey
+libmgl mgl_facez				double double ptr double double double double double ptr 	(void)	mgl_facez
+libmgl mgl_sphere				ptr double double double double ptr 	(void)	mgl_sphere
+libmgl mgl_drop					double double ptr double double double double double double double ptr 	(void)	mgl_drop
+libmgl mgl_cone					ptr double double double double double double double double ptr 	(void)	mgl_cone
+libmgl mgl_ellipse				ptr double double double double double double double ptr 	(void)	mgl_ellipse
+libmgl mgl_rhomb				ptr double double double double double double double ptr 	(void)	mgl_rhomb
+libmgl mgl_cones_xyz			ptr ptr ptr ptr ptr ptr 	(void)	mgl_cones_xyz
+libmgl mgl_cones_xz				ptr ptr ptr ptr ptr 	(void)	mgl_cones_xz
+libmgl mgl_cones				ptr ptr ptr ptr 	(void)	mgl_cones
+libmgl mgl_dew_xy				ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_dew_xy
+libmgl mgl_dew_2d				ptr ptr ptr ptr ptr 	(void)	mgl_dew_2d
+libmgl mgl_puts_dir				double ptr ptr double double double double double double ptr 	(void)	mgl_puts_dir
+libmgl mgl_putsw_dir			double ptr ptr double double double double double double ptr 	(void)	mgl_putsw_dir
+libmgl mgl_textmark_xyzr		ptr ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_textmark_xyzr
+libmgl mgl_textmarkw_xyzr		ptr ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_textmarkw_xyzr
+libmgl mgl_textmark_xyr			ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_textmark_xyr
+libmgl mgl_textmarkw_xyr		ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_textmarkw_xyr
+libmgl mgl_textmark_yr			ptr ptr ptr ptr ptr ptr 	(void)	mgl_textmark_yr
+libmgl mgl_textmarkw_yr			ptr ptr ptr ptr ptr ptr 	(void)	mgl_textmarkw_yr
+libmgl mgl_textmark				ptr ptr ptr ptr ptr 	(void)	mgl_textmark
+libmgl mgl_textmarkw			ptr ptr ptr ptr ptr 	(void)	mgl_textmarkw
+libmgl mgl_label_xyz			ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_label_xyz
+libmgl mgl_labelw_xyz			ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_labelw_xyz
+libmgl mgl_label_xy				ptr ptr ptr ptr ptr ptr 	(void)	mgl_label_xy
+libmgl mgl_labelw_xy			ptr ptr ptr ptr ptr ptr 	(void)	mgl_labelw_xy
+libmgl mgl_label_y				ptr ptr ptr ptr ptr 	(void)	mgl_label_y
+libmgl mgl_labelw_y				ptr ptr ptr ptr ptr 	(void)	mgl_labelw_y
+libmgl mgl_table				ptr ptr ptr ptr double double ptr 	(void)	mgl_table
+libmgl mgl_tablew				ptr ptr ptr ptr double double ptr 	(void)	mgl_tablew
+libmgl mgl_triplot_xyzc			ptr ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_triplot_xyzc
+libmgl mgl_triplot_xyz			ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_triplot_xyz
+libmgl mgl_triplot_xy			ptr ptr ptr ptr ptr ptr 	(void)	mgl_triplot_xy
+libmgl mgl_quadplot_xyzc		ptr ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_quadplot_xyzc
+libmgl mgl_quadplot_xyz			ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_quadplot_xyz
+libmgl mgl_quadplot_xy			ptr ptr ptr ptr ptr ptr 	(void)	mgl_quadplot_xy
+libmgl mgl_tricont_xyzcv		ptr ptr ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_tricont_xyzcv
+libmgl mgl_tricont_xycv			ptr ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_tricont_xycv
+libmgl mgl_tricont_xyzc			ptr ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_tricont_xyzc
+libmgl mgl_tricont_xyc			ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_tricont_xyc
+libmgl mgl_dots					ptr ptr ptr ptr ptr ptr 	(void)	mgl_dots
+libmgl mgl_dots_a				ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_dots_a
+libmgl mgl_dots_ca				ptr ptr ptr ptr ptr ptr ptr ptr 	(void)	mgl_dots_ca
+libmgl mgl_crust				ptr ptr ptr ptr ptr ptr 	(void)	mgl_crust
+libmgl mgl_dens_x				ptr double ptr ptr ptr 	(void)	mgl_dens_x
+libmgl mgl_dens_y				ptr double ptr ptr ptr 	(void)	mgl_dens_y
+libmgl mgl_dens_z				ptr double ptr ptr ptr 	(void)	mgl_dens_z
+libmgl mgl_cont_x				ptr double ptr ptr ptr 	(void)	mgl_cont_x
+libmgl mgl_cont_y				ptr double ptr ptr ptr 	(void)	mgl_cont_y
+libmgl mgl_cont_z				ptr double ptr ptr ptr 	(void)	mgl_cont_z
+libmgl mgl_cont_x_val			ptr double ptr ptr ptr ptr 	(void)	mgl_cont_x_val
+libmgl mgl_cont_y_val			ptr double ptr ptr ptr ptr 	(void)	mgl_cont_y_val
+libmgl mgl_cont_z_val			ptr double ptr ptr ptr ptr 	(void)	mgl_cont_z_val
+libmgl mgl_contf_x				ptr double ptr ptr ptr 	(void)	mgl_contf_x
+libmgl mgl_contf_y				ptr double ptr ptr ptr 	(void)	mgl_contf_y
+libmgl mgl_contf_z				ptr double ptr ptr ptr 	(void)	mgl_contf_z
+libmgl mgl_contf_x_val			ptr double ptr ptr ptr ptr 	(void)	mgl_contf_x_val
+libmgl mgl_contf_y_val			ptr double ptr ptr ptr ptr 	(void)	mgl_contf_y_val
+libmgl mgl_contf_z_val			ptr double ptr ptr ptr ptr 	(void)	mgl_contf_z_val
+libmgl mgl_create_graph			int int 	(ptr)	mgl_create_graph
+libmgl mgl_delete_graph			ptr 	(void)	mgl_delete_graph
+libmgl mgl_set_size				int int ptr 	(void)	mgl_set_size
+libmgl mgl_set_def_param		ptr 	(void)	mgl_set_def_param
+libmgl mgl_combine_gr			ptr ptr 	(void)	mgl_combine_gr
+libmgl mgl_finish				ptr 	(void)	mgl_finish
+libmgl mgl_set_tick_len			double double ptr 	(void)	mgl_set_tick_len
+libmgl mgl_set_axis_stl			ptr ptr ptr ptr 	(void)	mgl_set_axis_stl
+libmgl mgl_adjust_ticks			ptr ptr 	(void)	mgl_adjust_ticks
+libmgl mgl_set_ticks			double int double char ptr 	(void)	mgl_set_ticks
+libmgl mgl_set_ticks_str		int ptr char ptr 	(void)	mgl_set_ticks_str
+libmgl mgl_set_ticks_wcs		int ptr char ptr 	(void)	mgl_set_ticks_wcs
+libmgl mgl_set_ticks_val		int ptr ptr char ptr 	(void)	mgl_set_ticks_val
+libmgl mgl_set_ticks_valw		int ptr ptr char ptr 	(void)	mgl_set_ticks_valw
+libmgl mgl_tune_ticks			double int ptr 	(void)	mgl_tune_ticks
+libmgl mgl_set_tick_templ		ptr char ptr 	(void)	mgl_set_tick_templ
+libmgl mgl_set_tick_templw		ptr char ptr 	(void)	mgl_set_tick_templw
+libmgl mgl_set_ticks_time		ptr double char ptr 	(void)	mgl_set_ticks_time
+libmgl mgl_set_tick_shift		double double double double ptr 	(void)	mgl_set_tick_shift
+libmgl mgl_box					ptr 	(void)	mgl_box
+libmgl mgl_box_str				int ptr ptr 	(void)	mgl_box_str
+libmgl mgl_axis					ptr ptr ptr ptr 	(void)	mgl_axis
+libmgl mgl_axis_grid			ptr ptr ptr ptr 	(void)	mgl_axis_grid
+libmgl mgl_label				ptr double ptr char ptr 	(void)	mgl_label
+libmgl mgl_labelw				ptr double ptr char ptr 	(void)	mgl_labelw
+libmgl mgl_colorbar				ptr ptr 	(void)	mgl_colorbar
+libmgl mgl_colorbar_ext			double double double double ptr ptr 	(void)	mgl_colorbar_ext
+libmgl mgl_colorbar_val			ptr ptr ptr 	(void)	mgl_colorbar_val
+libmgl mgl_colorbar_val_ext		double double double double ptr ptr ptr 	(void)	mgl_colorbar_val_ext
+libmgl mgl_add_legend			ptr ptr ptr 	(void)	mgl_add_legend
+libmgl mgl_add_legendw			ptr ptr ptr 	(void)	mgl_add_legendw
+libmgl mgl_clear_legend			ptr 	(void)	mgl_clear_legend
+libmgl mgl_legend_pos			ptr ptr double double ptr 	(void)	mgl_legend_pos
+libmgl mgl_legend				ptr ptr int ptr 	(void)	mgl_legend
+libmgl mgl_set_legend_marks		int ptr 	(void)	mgl_set_legend_marks
+libmgl mgl_show_image			int ptr ptr 	(void)	mgl_show_image
+libmgl mgl_write_frame			ptr ptr ptr 	(void)	mgl_write_frame
+libmgl mgl_write_tga			ptr ptr ptr 	(void)	mgl_write_tga
+libmgl mgl_write_bmp			ptr ptr ptr 	(void)	mgl_write_bmp
+libmgl mgl_write_jpg			ptr ptr ptr 	(void)	mgl_write_jpg
+libmgl mgl_write_png			ptr ptr ptr 	(void)	mgl_write_png
+libmgl mgl_write_png_solid		ptr ptr ptr 	(void)	mgl_write_png_solid
+libmgl mgl_write_bps			ptr ptr ptr 	(void)	mgl_write_bps
+libmgl mgl_write_eps			ptr ptr ptr 	(void)	mgl_write_eps
+libmgl mgl_write_svg			ptr ptr ptr 	(void)	mgl_write_svg
+libmgl mgl_write_tex			ptr ptr ptr 	(void)	mgl_write_tex
+libmgl mgl_write_obj			int ptr ptr ptr 	(void)	mgl_write_obj
+libmgl mgl_write_obj_old		int ptr ptr ptr 	(void)	mgl_write_obj_old
+libmgl mgl_write_stl			ptr ptr ptr 	(void)	mgl_write_stl
+libmgl mgl_write_off			int ptr ptr ptr 	(void)	mgl_write_off
+libmgl mgl_write_xyz			ptr ptr ptr 	(void)	mgl_write_xyz
+libmgl mgl_write_prc			int ptr ptr ptr 	(void)	mgl_write_prc
+libmgl mgl_write_gif			ptr ptr ptr 	(void)	mgl_write_gif
+libmgl mgl_start_gif			int ptr ptr 	(void)	mgl_start_gif
+libmgl mgl_close_gif			ptr 	(void)	mgl_close_gif
+libmgl mgl_export_mgld			ptr ptr ptr 	(void)	mgl_export_mgld
+libmgl mgl_import_mgld			int ptr ptr 	(void)	mgl_import_mgld
+libmgl mgl_write_json			ptr ptr ptr 	(void)	mgl_write_json
+libmgl mgl_write_json_z			ptr ptr ptr 	(void)	mgl_write_json_z
+libmgl gl_get_json				ptr 	(ptr)	gl_get_json
+libmgl gl_get_rgb				ptr 	(ptr)	gl_get_rgb
+libmgl gl_get_rgba				ptr 	(ptr)	gl_get_rgba
+libmgl mgl_set_obj_id			int ptr 	(void)	mgl_set_obj_id
+libmgl mgl_get_obj_id			int int ptr 	(int)	mgl_get_obj_id
+libmgl mgl_get_spl_id			int int ptr 	(int)	mgl_get_spl_id
+libmgl mgl_get_width			ptr 	(int)	mgl_get_width
+libmgl mgl_get_height			ptr 	(int)	mgl_get_height
+libmgl mgl_calc_xyz				ptr ptr ptr int int ptr 	(void)	mgl_calc_xyz
+libmgl mgl_calc_scr				ptr ptr double double double ptr 	(void)	mgl_calc_scr
+libmgl mgl_is_active			int int int ptr 	(int)	mgl_is_active
+libmgl mgl_new_frame			ptr 	(int)	mgl_new_frame
+libmgl mgl_end_frame			ptr 	(void)	mgl_end_frame
+libmgl mgl_get_num_frame		ptr 	(int)	mgl_get_num_frame
+libmgl mgl_reset_frames			ptr 	(void)	mgl_reset_frames
+libmgl mgl_get_frame			int ptr 	(void)	mgl_get_frame
+libmgl mgl_set_frame			int ptr 	(void)	mgl_set_frame
+libmgl mgl_show_frame			int ptr 	(void)	mgl_show_frame
+libmgl mgl_del_frame			int ptr 	(void)	mgl_del_frame
+libmgl mgl_set_transp_type		int ptr 	(void)	mgl_set_transp_type
+libmgl mgl_set_alpha			int ptr 	(void)	mgl_set_alpha
+libmgl mgl_set_fog				double double ptr 	(void)	mgl_set_fog
+libmgl mgl_set_light			int ptr 	(void)	mgl_set_light
+libmgl mgl_set_light_n			int int ptr 	(void)	mgl_set_light_n
+libmgl mgl_add_light			double double double int ptr 	(void)	mgl_add_light
+libmgl mgl_add_light_ext		double double char double double double int ptr 	(void)	mgl_add_light_ext
+libmgl mgl_add_light_loc		double double char double double double double double double int ptr 	(void)	mgl_add_light_loc
+libmgl mgl_mat_pop				ptr 	(void)	mgl_mat_pop
+libmgl mgl_mat_push				ptr 	(void)	mgl_mat_push
+libmgl mgl_clf					ptr 	(void)	mgl_clf
+libmgl mgl_clf_rgb				double double double ptr 	(void)	mgl_clf_rgb
+libmgl mgl_clf_chr				char ptr 	(void)	mgl_clf_chr
+libmgl mgl_subplot				ptr int int int ptr 	(void)	mgl_subplot
+libmgl mgl_subplot_d			double double ptr int int int ptr 	(void)	mgl_subplot_d
+libmgl mgl_multiplot			ptr int int int int int ptr 	(void)	mgl_multiplot
+libmgl mgl_inplot				double double double double ptr 	(void)	mgl_inplot
+libmgl mgl_relplot				double double double double ptr 	(void)	mgl_relplot
+libmgl mgl_columnplot			double int int ptr 	(void)	mgl_columnplot
+libmgl mgl_gridplot				double int int int ptr 	(void)	mgl_gridplot
+libmgl mgl_stickplot			double double int int ptr 	(void)	mgl_stickplot
+libmgl mgl_title				double ptr ptr ptr 	(void)	mgl_title
+libmgl mgl_titlew				double ptr ptr ptr 	(void)	mgl_titlew
+libmgl mgl_set_plotfactor		double ptr 	(void)	mgl_set_plotfactor
+libmgl mgl_aspect				double double double ptr 	(void)	mgl_aspect
+libmgl mgl_rotate				double double double ptr 	(void)	mgl_rotate
+libmgl mgl_rotate_vector		double double double double ptr 	(void)	mgl_rotate_vector
+libmgl mgl_perspective			double ptr 	(void)	mgl_perspective
+libmgl mgl_view					double double double ptr 	(void)	mgl_view
+libmgl mgl_zoom					double double double double ptr 	(void)	mgl_zoom
+libmgl mgl_wnd_set_delay		double ptr 	(void)	mgl_wnd_set_delay
+libmgl mgl_wnd_get_delay		ptr 	(double)	mgl_wnd_get_delay
+libmgl mgl_setup_window			int int ptr 	(void)	mgl_setup_window
+libmgl mgl_wnd_toggle_alpha		ptr 	(void)	mgl_wnd_toggle_alpha
+libmgl mgl_wnd_toggle_light		ptr 	(void)	mgl_wnd_toggle_light
+libmgl mgl_wnd_toggle_zoom		ptr 	(void)	mgl_wnd_toggle_zoom
+libmgl mgl_wnd_toggle_rotate	ptr 	(void)	mgl_wnd_toggle_rotate
+libmgl mgl_wnd_toggle_no		ptr 	(void)	mgl_wnd_toggle_no
+libmgl mgl_wnd_update			ptr 	(void)	mgl_wnd_update
+libmgl mgl_wnd_reload			ptr 	(void)	mgl_wnd_reload
+libmgl mgl_wnd_adjust			ptr 	(void)	mgl_wnd_adjust
+libmgl mgl_wnd_next_frame		ptr 	(void)	mgl_wnd_next_frame
+libmgl mgl_wnd_prev_frame		ptr 	(void)	mgl_wnd_prev_frame
+libmgl mgl_wnd_animation		ptr 	(void)	mgl_wnd_animation
+libmgl mgl_get_last_mouse_pos	ptr ptr ptr ptr 	(void)	mgl_get_last_mouse_pos
+libmgl mgl_create_parser			(ptr)	mgl_create_parser
+libmgl mgl_use_parser			int ptr 	(int)	mgl_use_parser
+libmgl mgl_delete_parser		ptr 	(void)	mgl_delete_parser
+libmgl mgl_parser_add_param		ptr int ptr 	(void)	mgl_parser_add_param
+libmgl mgl_parser_add_paramw	ptr int ptr 	(void)	mgl_parser_add_paramw
+libmgl mgl_parser_add_var		ptr ptr 	(ptr)	mgl_parser_add_var
+libmgl mgl_parser_add_varw		ptr ptr 	(ptr)	mgl_parser_add_varw
+libmgl mgl_parser_find_var		ptr ptr 	(ptr)	mgl_parser_find_var
+libmgl mgl_parser_find_varw		ptr ptr 	(ptr)	mgl_parser_find_varw
+libmgl mgl_parser_del_var		ptr ptr 	(void)	mgl_parser_del_var
+libmgl mgl_parser_del_varw		ptr ptr 	(void)	mgl_parser_del_varw
+libmgl mgl_parser_del_all		ptr 	(void)	mgl_parser_del_all
+libmgl mgl_parse_line			int ptr ptr ptr 	(int)	mgl_parse_line
+libmgl mgl_parse_linew			int ptr ptr ptr 	(int)	mgl_parse_linew
+libmgl mgl_parse_text			ptr ptr ptr 	(void)	mgl_parse_text
+libmgl mgl_parse_textw			ptr ptr ptr 	(void)	mgl_parse_textw
+libmgl mgl_parser_restore_once	ptr 	(void)	mgl_parser_restore_once
+libmgl mgl_parser_allow_setsize	int ptr 	(void)	mgl_parser_allow_setsize
+libmgl mgl_parser_allow_file_io	int ptr 	(void)	mgl_parser_allow_file_io
+libmgl mgl_parser_stop			ptr 	(void)	mgl_parser_stop
+libmgl mgl_parser_cmd_type		ptr ptr 	(int)	mgl_parser_cmd_type
+libmgl gl_parser_cmd_desc		ptr ptr 	(ptr)	gl_parser_cmd_desc
+libmgl gl_parser_cmd_frmt		ptr ptr 	(ptr)	gl_parser_cmd_frmt
+libmgl gl_parser_cmd_name		int ptr 	(ptr)	gl_parser_cmd_name
+libmgl mgl_parser_cmd_num		ptr 	(int)	mgl_parser_cmd_num
+libmgl mgl_parser_calc			ptr ptr 	(ptr)	mgl_parser_calc
+libmgl mgl_parser_calcw			ptr ptr 	(ptr)	mgl_parser_calcw
+libmgl mgl_create_expr			ptr 	(ptr)	mgl_create_expr
+libmgl mgl_delete_expr			ptr 	(void)	mgl_delete_expr
+libmgl mgl_expr_eval			double double double ptr 	(double)	mgl_expr_eval
+libmgl mgl_expr_eval_v			ptr ptr 	(double)	mgl_expr_eval_v
+libmgl mgl_expr_diff			double double double char ptr 	(double)	mgl_expr_diff
+libmgl mgl_expr_diff_v			ptr char ptr 	(double)	mgl_expr_diff_v
+libmgl mgl_gauss_rnd				(double)	mgl_gauss_rnd
+libmgl mgl_fft_freq				int ptr 	(void)	mgl_fft_freq
+libmgl mgl_strcls				ptr 	(void)	mgl_strcls
+libmgl mgl_strpos				ptr ptr 	(int)	mgl_strpos
+libmgl mgl_chrpos				char ptr 	(int)	mgl_chrpos
+libmgl mgl_istrue				char 	(int)	mgl_istrue
diff --git a/include/mgl2/mgl.h b/include/mgl2/mgl.h
new file mode 100644
index 0000000..3d12d9b
--- /dev/null
+++ b/include/mgl2/mgl.h
@@ -0,0 +1,2321 @@
+/***************************************************************************
+ * mgl.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef _MGL_H_
+#define _MGL_H_
+
+#include "mgl2/mgl_cf.h"
+#ifdef __cplusplus
+#include "mgl2/data.h"
+#include "mgl2/datac.h"
+#include <sys/stat.h>
+//-----------------------------------------------------------------------------
+/// Wrapper class for all graphics
+class MGL_EXPORT mglGraph
+{
+	mglGraph(const mglGraph &) {}	// copying is not allowed
+	const mglGraph &operator=(const mglGraph &t)	{	return t;	}
+protected:
+	HMGL gr;
+public:
+	HMPR pr;	///< Pointer to associated MGL parser
+	mglGraph(int kind=0, int width=600, int height=400)
+	{	pr = NULL;
+		if(kind==-1)	gr=NULL;
+#if MGL_HAVE_OPENGL
+		else if(kind==1)	gr=mgl_create_graph_gl();
+#else
+		else if(kind==1)
+		{	gr=mgl_create_graph(width, height);
+			SetGlobalWarn("OpenGL support was disabled. Please, enable it and rebuild MathGL.");	}
+#endif
+		else	gr=mgl_create_graph(width, height);
+	}
+	mglGraph(HMGL graph)
+	{	pr = NULL;	gr = graph;		mgl_use_graph(gr,1);	}
+	virtual ~mglGraph()
+	{	if(mgl_use_graph(gr,-1)<1)	mgl_delete_graph(gr);	}
+	/// Get pointer to internal HMGL object
+	inline HMGL Self()	{	return gr;	}
+	/// Set default parameters for plotting
+	inline void DefaultPlotParam()			{	mgl_set_def_param(gr);	}
+	/// Set name of plot for saving filename
+	inline void SetPlotId(const char *id)	{	mgl_set_plotid(gr,id);	}
+	/// Get name of plot for saving filename
+	inline const char *GetPlotId()	{	return mgl_get_plotid(gr);	}
+
+	/// Ask to stop drawing
+	inline void Stop(bool stop=true)	{	mgl_ask_stop(gr, stop);	}
+	/// Check if plot termination is asked
+	inline bool NeedStop()	{	return mgl_need_stop(gr);	}
+	/// Set callback function for event processing
+	inline void SetEventFunc(void (*func)(void *), void *par=NULL)
+	{	mgl_set_event_func(gr, func, par);	}
+
+	/// Set the transparency on/off.
+	inline void Alpha(bool enable)			{	mgl_set_alpha(gr, enable);	}
+	/// Set the gray-scale mode on/off.
+	inline void Gray(bool enable)			{	mgl_set_gray(gr, enable);	}
+	/// Set default value of alpha-channel
+	inline void SetAlphaDef(double alpha)	{	mgl_set_alpha_default(gr, alpha);	}
+	/// Set the transparency type (0 - usual, 1 - glass, 2 - lamp)
+	inline void SetTranspType(int type)		{	mgl_set_transp_type(gr, type);	}
+	/// Set the size of semi-transparent area around lines, marks, glyphs, ... Default is 1.
+	inline void SetPenDelta(double d)	{	mgl_pen_delta(gr,d);	}
+
+	/// Set the using of light on/off.
+	inline void Light(bool enable)			{	mgl_set_light(gr, enable);	}
+	/// Switch on/off the specified light source.
+	inline void Light(int n,bool enable)	{	mgl_set_light_n(gr, n, enable);	}
+	/// Use diffusive light (only for local light sources) -- OBSOLETE
+	inline void SetDifLight(bool dif)		{	mgl_set_light_dif(gr, dif);	}
+	/// Set to attach light settings to inplot.
+	inline void AttachLight(bool enable)		{	mgl_set_attach_light(gr, enable);	}
+	/// Add a light source.
+	inline void AddLight(int n, mglPoint p, char col='w', double bright=0.5, double ap=0)
+	{	mgl_add_light_ext(gr, n, p.x, p.y, p.z, col, bright, ap);	}
+	inline void AddLight(int n, mglPoint r, mglPoint p, char col='w', double bright=0.5, double ap=0)
+	{	mgl_add_light_loc(gr, n, r.x, r.y, r.z, p.x, p.y, p.z, col, bright, ap);	}
+	/// Set ambient light brightness
+	inline void SetAmbient(double i)			{	mgl_set_ambbr(gr, i);	}
+	/// Set diffusive light brightness
+	inline void SetDiffuse(double i)			{	mgl_set_difbr(gr, i);	}
+	/// Set the fog distance or switch it off (if d=0).
+	inline void Fog(double d, double dz=0.25)	{	mgl_set_fog(gr, d, dz);		}
+
+	/// Set relative width of rectangles in Bars, Barh, BoxPlot, Candle, OHLC (default is 0.7)
+	inline void SetBarWidth(double width)	{	mgl_set_bar_width(gr, width);	}
+	/// Set default size of marks (locally you can use "size" option)
+	inline void SetMarkSize(double size)		{	mgl_set_mark_size(gr, size);	}
+	/// Set default size of arrows (locally you can use "size" option)
+	inline void SetArrowSize(double size)	{	mgl_set_arrow_size(gr, size);	}
+	/// Set number of mesh lines (use 0 to draw all of them)
+	inline void SetMeshNum(int num)			{	mgl_set_meshnum(gr, num);	}
+	/// Set number of visible faces (use 0 to draw all of them)
+	inline void SetFaceNum(int num)			{	mgl_set_facenum(gr, num);	}
+
+	/// Set cutting for points outside of bounding box
+	inline void SetCut(bool cut)				{	mgl_set_cut(gr, cut);	}
+	/// Set additional cutting box
+	inline void SetCutBox(mglPoint p1, mglPoint p2)
+	{	mgl_set_cut_box(gr, p1.x, p1.y, p1.z, p2.x, p2.y, p2.z);	}
+	/// Set the cutting off condition (formula)
+	inline void CutOff(const char *EqC)		{	mgl_set_cutoff(gr, EqC);	}
+
+	/// Set default font size
+	inline void SetFontSize(double size)	{	mgl_set_font_size(gr, size);	}
+	/// Set default font style and color
+	inline void SetFontDef(const char *fnt)	{	mgl_set_font_def(gr, fnt);	}
+	/// Set FontSize by size in pt and picture DPI (default is 16 pt for dpi=72)
+	virtual void SetFontSizePT(double pt, int dpi=72)	{	SetFontSize(pt*27.f/dpi);	}
+	/// Set FontSize by size in centimeters and picture DPI (default is 0.56 cm = 16 pt)
+	inline void SetFontSizeCM(double cm, int dpi=72)	{	SetFontSizePT(cm*28.45f,dpi);	}
+	/// Set FontSize by size in inch and picture DPI (default is 0.22 in = 16 pt)
+	inline void SetFontSizeIN(double in, int dpi=72)	{	SetFontSizePT(in*72.27f,dpi);	}
+	/// Load font from file
+	inline void LoadFont(const char *name, const char *path=NULL)
+	{	mgl_load_font(gr, name, path);	}
+	/// Copy font from another mglGraph instance
+	inline void CopyFont(const mglGraph *GR)	{	mgl_copy_font(gr, GR->gr);}
+	/// Restore font (load default font for new HMGL objects)
+	inline void RestoreFont()				{	mgl_restore_font(gr);	}
+	/// Set to use or not text rotation
+	inline void SetRotatedText(bool rotated)	{	mgl_set_rotated_text(gr, rotated);	}
+	/// Set default font for all new HMGL and mglGraph objects
+	static inline void SetDefFont(const char *name, const char *path=NULL)	{	mgl_def_font(name,path);	}
+	/// Add user-defined glyph for symbol and set its optional id
+	inline void DefineSymbol(char id, const mglDataA &x, const mglDataA &y)
+	{	mgl_define_symbol(gr, id, &x, &y);	}
+
+	/// Set default palette
+	inline void SetPalette(const char *colors)	{	mgl_set_palette(gr, colors);	}
+	/// Set default color scheme
+	inline void SetDefScheme(const char *sch)	{	mgl_set_def_sch(gr, sch);	}
+
+	/// Sets RGB values for color with given id
+	static inline void SetColor(char id, double r, double g, double b)	{	mgl_set_color(id, r, g, b);	}
+	/// Set mask for face coloring as array of type 'unsigned char[8]'
+	static inline void SetMask(char id, const char *mask)	{	mgl_set_mask(id, mask);	}
+	/// Set mask for face coloring as uint64_t number
+	static inline void SetMask(char id, uint64_t mask)	{	mgl_set_mask_val(id, mask);	}
+	/// Set default mask rotation angle
+	inline void SetMaskAngle(int angle)	{	mgl_set_mask_angle(gr, angle);	}
+
+	/// Get last warning code
+	inline int  GetWarn()	{	return mgl_get_warn(gr);}
+	/// Set warning code ant fill message
+	inline void SetWarn(int code, const char *info)	{	mgl_set_warn(gr,code,info);	}
+	/// Get text of warning message(s)
+	inline const char *Message()	{	return mgl_get_mess(gr);	}
+	/// Set global warning message
+	static inline void SetGlobalWarn(const char *text)	{	mgl_set_global_warn(text);	}
+	/// Get text of global warning message(s)
+	static inline const char *GlobalWarn()	{	return mgl_get_global_warn();	}
+	/// Suppress printing warnings to stderr
+	static inline void SuppressWarn(bool on)	{	mgl_suppress_warn(on);	}
+	/// Check if MathGL version is valid (return false) or not (return true)
+	static inline bool CheckVersion(const char *ver)	{	return mgl_check_version(ver);	}
+
+	/// Set axis range scaling -- simplified way to shift/zoom axis range -- need to replot whole image!
+	inline void ZoomAxis(mglPoint p1=mglPoint(0,0,0,0), mglPoint p2=mglPoint(1,1,1,1))
+	{	mgl_zoom_axis(gr, p1.x,p1.y,p1.z,p1.c, p2.x,p2.y,p2.z,p2.c);	}
+	/// Add [v1, v2] to the current range in direction dir
+	inline void AddRange(char dir, double v1, double v2)
+	{	mgl_add_range_val(gr, dir, v1, v2);	}
+	/// Set range in direction dir as [v1, v2]
+	inline void SetRange(char dir, double v1, double v2)
+	{	mgl_set_range_val(gr, dir, v1, v2);	}
+	/// Set range in direction dir as minimal and maximal values of data a
+	inline void SetRange(char dir, const mglDataA &dat, bool add=false)
+	{	mgl_set_range_dat(gr, dir, &dat, add);	}
+	/// Set values of axis range as minimal and maximal values of corresponding data
+	inline void SetRanges(const mglDataA &xx, const mglDataA &yy, const mglDataA &zz, const mglDataA &cc)
+	{	mgl_set_range_dat(gr,'x',&xx,0);	mgl_set_range_dat(gr,'y',&yy,0);
+		mgl_set_range_dat(gr,'z',&zz,0);	mgl_set_range_dat(gr,'c',&cc,0);	}
+	/// Set values of axis range as minimal and maximal values of corresponding data
+	inline void SetRanges(const mglDataA &xx, const mglDataA &yy, const mglDataA &zz)
+	{	mgl_set_range_dat(gr,'x',&xx,0);	mgl_set_range_dat(gr,'y',&yy,0);
+		mgl_set_range_dat(gr,'z',&zz,0);	mgl_set_range_dat(gr,'c',&zz,0);	}
+	/// Set values of axis range as minimal and maximal values of corresponding data
+	inline void SetRanges(const mglDataA &xx, const mglDataA &yy)
+	{	mgl_set_range_dat(gr,'x',&xx,0);	mgl_set_range_dat(gr,'y',&yy,0);	}
+	/// Set values of axis ranges
+	inline void SetRanges(double x1, double x2, double y1, double y2, double z1=0, double z2=0)
+	{	mgl_set_ranges(gr, x1, x2, y1, y2, z1, z2);	}
+	/// Set values of axis ranges
+	inline void SetRanges(mglPoint p1, mglPoint p2)
+	{	mgl_set_ranges(gr, p1.x, p2.x, p1.y, p2.y, p1.z, p2.z);	}
+	/// Set ranges for automatic variables
+	inline void SetAutoRanges(double x1, double x2, double y1=0, double y2=0, double z1=0, double z2=0, double c1=0, double c2=0)
+	{	mgl_set_auto_ranges(gr, x1, x2, y1, y2, z1, z2, c1, c2);	}
+	/// Set ranges for automatic variables
+	inline void SetAutoRanges(mglPoint p1, mglPoint p2)
+	{	mgl_set_auto_ranges(gr, p1.x, p2.x, p1.y, p2.y, p1.z, p2.z, p1.c, p2.c);	}
+	/// Set axis origin
+	inline void SetOrigin(mglPoint p)
+	{	mgl_set_origin(gr, p.x, p.y, p.z);	}
+	inline void SetOrigin(double x0, double y0, double z0=mglNaN)
+	{	mgl_set_origin(gr, x0, y0, z0);	}
+
+	/// Set the transformation formulas for coordinate. Use "" or NULL for built-in ones
+	inline void SetFunc(const char *EqX, const char *EqY, const char *EqZ=NULL, const char *EqA=NULL)
+	{	mgl_set_func(gr, EqX, EqY, EqZ, EqA);	}
+	/// Set one of predefined transformation rule
+	inline void SetCoor(int how)		{	mgl_set_coor(gr, how);	}
+	/// Set to draw Ternary axis (triangle like axis, grid and so on)
+	/** val=1 for Ternary axis (a+b+c=1, z=z),
+	 *  val=2 for Quaternary axis (a+b+c+d=1),
+	 *  val|4 for projections. */
+	inline void Ternary(int val)		{	mgl_set_ternary(gr, val);	}
+
+	/// Set to use or not tick labels rotation
+	inline void SetTickRotate(bool val)	{	mgl_set_tick_rotate(gr,val);	}
+	/// Set to use or not tick labels skipping
+	inline void SetTickSkip(bool val)	{	mgl_set_tick_skip(gr,val);	}
+	/// Set tick length
+	inline void SetTickLen(double len, double stt=1)
+	{	mgl_set_tick_len(gr, len, stt);	}
+	/// Set axis and ticks style
+	inline void SetAxisStl(const char *stl="k", const char *tck=0, const char *sub=0)
+	{	mgl_set_axis_stl(gr, stl, tck, sub);	}
+
+	/// Set time templates for ticks
+	inline void SetTicksTime(char dir, double d=0, const char *t="")
+	{	mgl_set_ticks_time(gr,dir,d,t);	}
+	/// Set ticks text (\n separated). Use "" to disable this feature.
+	inline void SetTicksVal(char dir, const char *lbl, bool add=false)
+	{	mgl_set_ticks_str(gr,dir,lbl,add);	}
+	inline void SetTicksVal(char dir, const wchar_t *lbl, bool add=false)
+	{	mgl_set_ticks_wcs(gr,dir,lbl,add);	}
+	/// Set ticks position and text (\n separated). Use "" to disable this feature.
+	inline void SetTicksVal(char dir, const mglDataA &v, const char *lbl, bool add=false)
+	{	mgl_set_ticks_val(gr,dir,&v,lbl,add);	}
+	inline void SetTicksVal(char dir, const mglDataA &v, const wchar_t *lbl, bool add=false)
+	{	mgl_set_ticks_valw(gr,dir,&v,lbl,add);	}
+	/// Add manual tick at given position. Use "" to disable this feature.
+	inline void AddTick(char dir, double val, const char *lbl)
+	{	mgl_add_tick(gr,dir,val,lbl);	}
+	inline void AddTick(char dir, double val, const wchar_t *lbl)
+	{	mgl_add_tickw(gr,dir,val,lbl);	}
+	/// Set the ticks parameters and string for its factor
+	inline void SetTicks(char dir, double d=0, int ns=0, double org=mglNaN, const char *factor="")
+	{	mgl_set_ticks_fact(gr, dir, d, ns, org, factor);	}
+	inline void SetTicks(char dir, double d, int ns, double org, const wchar_t *factor)
+	{	mgl_set_ticks_factw(gr, dir, d, ns, org, factor);	}
+	/// Auto adjust ticks
+	inline void Adjust(const char *dir="xyzc")
+	{	mgl_adjust_ticks(gr, dir);	}
+	/// Set templates for ticks
+	inline void SetTickTempl(char dir, const char *t)
+	{	mgl_set_tick_templ(gr,dir,t);	}
+	inline void SetTickTempl(char dir, const wchar_t *t)
+	{	mgl_set_tick_templw(gr,dir,t);	}
+	/// Tune ticks (tune|1 for common multiplier, tune|2 for common component)
+	inline void SetTuneTicks(int tune, double fact_pos=1.15)
+	{	mgl_tune_ticks(gr, tune, fact_pos);	}
+	/// Set additional shift of tick labels
+	inline void SetTickShift(mglPoint p)
+	{	mgl_set_tick_shift(gr,p.x,p.y,p.z,p.c);	}
+	/// Set to use UTC time instead of local time
+	inline void SetTimeUTC(bool enable)
+	{	mgl_set_flag(gr,enable, MGL_USE_GMTIME);	}
+	/// Set to draw tick labels at axis origin
+	inline void SetOriginTick(bool enable=true)
+	{	mgl_set_flag(gr,!enable, MGL_NO_ORIGIN);	}
+
+	/// Put further plotting in m-th cell of nx*ny grid of the image.
+	/** String \a style may contain:
+	 *  '<' for reserving space at left
+	 *  '>' for reserving space at right
+	 *  '^' for reserving space at top
+	 *  '_' for reserving space at bottom
+	 *  '#' for using whole region. */
+	inline void SubPlot(int nx,int ny,int m,const char *style="<>_^", double dx=0, double dy=0)
+	{	mgl_subplot_d(gr, nx, ny, m, style, dx, dy);	}
+	/// Put further plotting in rectangle of dx*dy cells starting from m-th cell of nx*ny grid of the image and shift it by distance {sx,sy}.
+	/** String \a style may contain:
+	 *  '<' for reserving space at left
+	 *  '>' for reserving space at right
+	 *  '^' for reserving space at top
+	 *  '_' for reserving space at bottom
+	 *  '#' for using whole region. */
+	inline void MultiPlot(int nx,int ny,int m, int dx, int dy, const char *style="<>_^", double sx=0, double sy=0)
+	{	mgl_multiplot_d(gr, nx, ny, m, dx, dy, style, sx, sy);	}
+	/// Put further plotting in a region [x1,x2]*[y1,y2] of the image or subplot (x1,x2,y1,y2 in range [0, 1]).
+	inline void InPlot(double x1,double x2,double y1,double y2, bool rel=true)
+	{	if(rel)	mgl_relplot(gr, x1, x2, y1, y2);
+		else	mgl_inplot(gr, x1, x2, y1, y2);	}
+	/// Put further plotting in column cell of previous subplot
+	inline void ColumnPlot(int num, int ind, double d=0)
+	{	mgl_columnplot(gr,num,ind,d);	}
+	/// Put further plotting in matrix cell of previous subplot
+	inline void GridPlot(int nx, int ny, int ind, double d=0)
+	{	mgl_gridplot(gr,nx,ny,ind,d);	}
+	/// Put further plotting in cell of stick rotated on angles tet, phi
+	inline void StickPlot(int num, int i, double tet, double phi)
+	{	mgl_stickplot(gr,num,i,tet,phi);	}
+	/// Put further plotting in cell of stick sheared on sx, sy.
+	inline void ShearPlot(int num, int i, mreal sx, mreal sy, mreal xd=1, mreal yd=0)
+	{	mgl_shearplot(gr,num,i,sx,sy,xd,yd);	}
+
+	/// Set factor of plot size
+	inline void SetPlotFactor(double val)
+	{	mgl_set_plotfactor(gr,val);	}
+	/// Push transformation matrix into stack
+	inline void Push()	{	mgl_mat_push(gr);	}
+	/// Pop transformation matrix from stack
+	inline void Pop()	{	mgl_mat_pop(gr);	}
+
+	/// Add title for current subplot/inplot
+	/** Style '#' draw box around the title. */
+	inline 	void Title(const char *title,const char *stl="",double size=-2)
+	{	mgl_title(gr,title,stl,size);	}
+	/// Add title for current subplot/inplot
+	/** Style '#' draw box around the title. */
+	inline 	void Title(const wchar_t *title,const char *stl="",double size=-2)
+	{	mgl_titlew(gr,title,stl,size);	}
+	/// Set aspect ratio for further plotting.
+	inline void Aspect(double Ax,double Ay,double Az=1)
+	{	mgl_aspect(gr, Ax, Ay, Az);		}
+	/// Shear a further plotting.
+	inline void Shear(double Sx,double Sy)
+	{	mgl_shear(gr, Sx, Sy);		}
+	/// Rotate a further plotting.
+	inline void Rotate(double TetX,double TetZ=0,double TetY=0)
+	{	mgl_rotate(gr, TetX, TetZ, TetY);	}
+	/// Rotate a further plotting around vector {x,y,z}.
+	inline void RotateN(double Tet,double x,double y,double z)
+	{	mgl_rotate_vector(gr, Tet, x, y, z);	}
+	/// Set perspective (in range [0,1)) for plot. Set to zero for switching off.
+	inline void Perspective(double val)
+	{	mgl_perspective(gr, val);	}
+	/// Set angle of view independently from Rotate().
+	inline void View(double TetX,double TetZ=0,double TetY=0)
+	{	mgl_view(gr, TetX, TetZ, TetY);	}
+	/// Set angle of view independently from Rotate().
+	inline void ViewAsRotate(double TetZ,double TetX,double TetY=0)
+	{	mgl_view(gr, -TetX, -TetZ, -TetY);	}
+	/// Zoom in/out a part of picture (use Zoom(0, 0, 1, 1) for restore default)
+	inline void Zoom(double x1, double y1, double x2, double y2)
+	{	mgl_zoom(gr, x1, y1, x2, y2);	}
+
+	/// Set size of frame in pixels. Normally this function is called internally.
+	inline void SetSize(int width, int height, bool clf=true)
+	{	if(clf)	mgl_set_size(gr, width, height);
+		else	mgl_scale_size(gr, width, height);	}
+	/// Scaling for all further set size calls.
+	static inline void SetSizeScl(double scl)	{	mgl_set_size_scl(scl);	}
+	/// Set plot quality
+	/** qual=0 -- no face drawing (fastest),
+	 *  qual=1 -- no color interpolation (fast),
+	 *  qual=2 -- high quality (normal),
+	 *  qual|4 -- direct bitmap drawing (low memory usage);
+	 *  qual|8 for dots drawing instead of primitives (extremely fast). */
+	inline void SetQuality(int qual=MGL_DRAW_NORM)	{	mgl_set_quality(gr, qual);	}
+	/// Get plot quality
+	inline int GetQuality()	{	return mgl_get_quality(gr);	}
+	/// Set drawing region for Quality&4
+	inline void SetDrawReg(long nx=1, long ny=1, long m=0)	{	mgl_set_draw_reg(gr,nx,ny,m);	}
+	/// Start group of objects
+	inline void StartGroup(const char *name)	{	mgl_start_group(gr, name);	}
+	/// End group of objects
+	inline void EndGroup()	{	mgl_end_group(gr);	}
+	/// Highlight objects with given id
+	inline void Highlight(int id)	{	mgl_highlight(gr, id);	}
+	/// Set boundary box for export graphics into 2D file formats.
+	/** If x2<0 (y2<0) then full width (height) will be used.
+	 *  If x1<0 or y1<0 or x1>=x2|Width or y1>=y2|Height then cropping will be disabled. */
+	inline void SetBBox(int x1=0, int y1=0, int x2=-1, int y2=-1)
+	{	mgl_set_bbox(gr,x1,y1,x2,y2);	}
+
+	/// Show current image
+	inline void ShowImage(const char *viewer, bool keep=0)
+	{	mgl_show_image(gr, viewer, keep);	}
+	/// Write the frame in file (depending extension, write current frame if fname is empty)
+	inline void WriteFrame(const char *fname=0,const char *descr="")
+	{	mgl_write_frame(gr, fname, descr);	}
+	/// Write the frame in file using JPEG format
+	inline void WriteJPEG(const char *fname,const char *descr="")
+	{	mgl_write_jpg(gr, fname, descr);	}
+	/// Write the frame in file using PNG format with transparency
+	inline void WritePNG(const char *fname,const char *descr="", bool alpha=true)
+	{	if(alpha)	mgl_write_png(gr, fname, descr);
+		else	mgl_write_png_solid(gr, fname, descr);	}
+	/// Write the frame in file using BMP format
+	inline void WriteBMP(const char *fname,const char *descr="")
+	{	mgl_write_bmp(gr, fname, descr);	}
+	/// Write the frame in file using BMP format
+	inline void WriteTGA(const char *fname,const char *descr="")
+	{	mgl_write_tga(gr, fname, descr);	}
+	/// Write the frame in file using PostScript format
+	inline void WriteEPS(const char *fname,const char *descr="")
+	{	mgl_write_eps(gr, fname, descr);	}
+	/// Write the frame in file using LaTeX format
+	inline void WriteTEX(const char *fname,const char *descr="")
+	{	mgl_write_tex(gr, fname, descr);	}
+	/// Write the frame in file using PostScript format as bitmap
+	inline void WriteBPS(const char *fname,const char *descr="")
+	{	mgl_write_bps(gr, fname, descr);	}
+	/// Write the frame in file using SVG format
+	inline void WriteSVG(const char *fname,const char *descr="")
+	{	mgl_write_svg(gr, fname, descr);	}
+	/// Write the frame in file using GIF format (only for current frame!)
+	inline void WriteGIF(const char *fname,const char *descr="")
+	{	mgl_write_gif(gr, fname, descr);	}
+
+	/// Write the frame in file using OBJ format
+	inline void WriteOBJ(const char *fname,const char *descr="",bool use_png=true)
+	{	mgl_write_obj(gr, fname, descr, use_png);	}
+	/// Write the frame in file using OBJ format - Balakin way
+	inline void WriteOBJold(const char *fname,const char *descr="",bool use_png=true)
+	{	mgl_write_obj_old(gr, fname, descr, use_png);	}
+	/// Write the frame in file using XYZ format
+	inline void WriteXYZ(const char *fname,const char *descr="")
+	{	mgl_write_xyz(gr, fname, descr);	}
+	/// Write the frame in file using STL format (faces only)
+	inline void WriteSTL(const char *fname,const char *descr="")
+	{	mgl_write_stl(gr, fname, descr);	}
+	/// Write the frame in file using OFF format
+	inline void WriteOFF(const char *fname,const char *descr="", bool colored=false)
+	{	mgl_write_off(gr, fname, descr,colored);	}
+//	/// Write the frame in file using X3D format
+//	inline void WriteX3D(const char *fname,const char *descr="")
+//	{	mgl_write_x3d(gr, fname, descr);	}
+	/// Write the frame in file using PRC format
+	inline void WritePRC(const char *fname,const char *descr="",bool make_pdf=true)
+	{	mgl_write_prc(gr, fname, descr, make_pdf);	}
+	/// Export in JSON format suitable for later drawing by JavaScript
+	inline void WriteJSON(const char *fname,const char *descr="",bool force_z=false)
+	{	if(force_z)	mgl_write_json_z(gr, fname, descr);
+		else 	mgl_write_json(gr, fname, descr);	}
+	/// Return string of JSON data suitable for later drawing by JavaScript
+	inline const char *GetJSON()	{	return mgl_get_json(gr);	}
+
+	/// Force preparing the image. It can be useful for OpenGL mode mostly.
+	inline void Finish()			{	mgl_finish(gr);	}
+	/// Create new frame.
+	inline void NewFrame()		{	mgl_new_frame(gr);	}
+	/// Finish frame drawing
+	inline void EndFrame()		{	mgl_end_frame(gr);	}
+	/// Get the number of created frames
+	inline int GetNumFrame()	{	return mgl_get_num_frame(gr);	}
+	/// Reset frames counter (start it from zero)
+	inline void ResetFrames()	{	mgl_reset_frames(gr);	}
+	/// Delete primitives for i-th frame (work if MGL_VECT_FRAME is set on)
+	inline void DelFrame(int i)	{	mgl_del_frame(gr, i);	}
+	/// Get drawing data for i-th frame (work if MGL_VECT_FRAME is set on)
+	inline void GetFrame(int i)	{	mgl_get_frame(gr, i);	}
+	/// Set drawing data for i-th frame (work if MGL_VECT_FRAME is set on). Work as EndFrame() but don't add frame to GIF image.
+	inline void SetFrame(int i)	{	mgl_set_frame(gr, i);	}
+	/// Append drawing data from i-th frame (work if MGL_VECT_FRAME is set on)
+	inline void ShowFrame(int i){	mgl_show_frame(gr, i);	}
+	/// Clear list of primitives for current drawing
+	inline void ClearFrame()	{	mgl_clear_frame(gr);	}
+
+	/// Start write frames to cinema using GIF format
+	inline void StartGIF(const char *fname, int ms=100)
+	{	mgl_start_gif(gr, fname,ms);	}
+	/// Stop writing cinema using GIF format
+	inline void CloseGIF()		{	mgl_close_gif(gr);	}
+	/// Export points and primitives in file using MGLD format
+	inline void ExportMGLD(const char *fname, const char *descr=0)
+	{	mgl_export_mgld(gr, fname, descr);	}
+	/// Import points and primitives from file using MGLD format
+	inline void ImportMGLD(const char *fname, bool add=false)
+	{	mgl_import_mgld(gr, fname, add);	}
+
+	/// Copy RGB values into array which is allocated by user
+	/** Position of element {i,j} is [3*i + 3*Width*j]. */
+	inline bool GetRGB(char *imgdata, int imglen)
+	{
+		long w=mgl_get_width(gr), h=mgl_get_height(gr);
+		if(imglen>=3*w*h)	memcpy(imgdata, mgl_get_rgb(gr),3*w*h);
+		return imglen>=3*w*h;
+	}
+	/// Get RGB values of current bitmap
+	/** Position of element {i,j} is [3*i + 3*Width*j]. */
+	inline const unsigned char *GetRGB()		{	return mgl_get_rgb(gr);	}
+	/// Copy RGBA values into array which is allocated by user
+	/** Position of element {i,j} is [4*i + 4*Width*j]. */
+	inline bool GetRGBA(char *imgdata, int imglen)
+	{
+		long w=mgl_get_width(gr), h=mgl_get_height(gr);
+		if(imglen>=4*w*h)	memcpy(imgdata, mgl_get_rgba(gr),4*w*h);
+		return imglen>=4*w*h;
+	}
+	/// Get RGBA values of current bitmap
+	/** Position of element {i,j} is [4*i + 4*Width*j]. */
+	inline const unsigned char *GetRGBA()	{	return mgl_get_rgba(gr);	}
+	/// Copy BGRN values into array which is allocated by user
+	inline bool GetBGRN(unsigned char *imgdata, int imglen)
+	{
+		long w=mgl_get_width(gr), h=mgl_get_height(gr), i;
+		const unsigned char *buf=mgl_get_rgb(gr);
+		if(imglen>=4*w*h)	for(i=0;i<w*h;i++)
+		{
+			imgdata[4*i]   = buf[3*i+2];
+			imgdata[4*i+1] = buf[3*i+1];
+			imgdata[4*i+2] = buf[3*i];
+			imgdata[4*i+3] = 255;
+		}
+		return imglen>=4*w*h;
+	}
+	/// Copy RGBA values of background image into array which is allocated by user
+	/** Position of element {i,j} is [4*i + 4*Width*j]. */
+	inline bool GetBackground(char *imgdata, int imglen)
+	{
+		long w=mgl_get_width(gr), h=mgl_get_height(gr);
+		if(imglen>=4*w*h)	memcpy(imgdata, mgl_get_background(gr),4*w*h);
+		return imglen>=4*w*h;
+	}
+	/// Get RGBA values of background image
+	/** Position of element {i,j} is [4*i + 4*Width*j]. */
+	inline const unsigned char *GetBackground()	{	return mgl_get_background(gr);	}
+	/// Get width of the image
+	inline int GetWidth()	{	return mgl_get_width(gr);	}
+	/// Get height of the image
+	inline int GetHeight()	{	return mgl_get_height(gr);}
+	/// Calculate 3D coordinate {x,y,z} for screen point {xs,ys}
+	inline mglPoint CalcXYZ(int xs, int ys)
+	{
+		mreal x,y,z;
+		mgl_calc_xyz(gr,xs,ys,&x,&y,&z);
+		return mglPoint(x,y,z);
+	}
+	/// Calculate screen point {xs,ys} for 3D coordinate {x,y,z}
+	inline mglPoint CalcScr(mglPoint p)
+	{
+		int xs,ys;
+		mgl_calc_scr(gr,p.x,p.y,p.z,&xs,&ys);
+		return mglPoint(xs,ys);
+	}
+	/// Set object/subplot id
+	inline void SetObjId(int id)		{	mgl_set_obj_id(gr,id);	}
+	/// Get object id
+	inline int GetObjId(long x,long y)	{	return mgl_get_obj_id(gr,x,y);	}
+	/// Get subplot id
+	inline int GetSplId(long x,long y)	{	return mgl_get_spl_id(gr,x,y);	}
+	/// Check if {\a xs,\a ys} is close to active point with accuracy d, and return its position or -1
+	inline long IsActive(int xs, int ys, int d=1)	{	return mgl_is_active(gr,xs,ys,d);	}
+
+	/// Combine plots from 2 canvases. Result will be saved into this
+	inline void Combine(const mglGraph *g)	{	mgl_combine_gr(gr,g->gr);	}
+
+	/// Clear up the frame and fill background by specified color
+	inline void Clf(double r, double g, double b)	{	mgl_clf_rgb(gr, r, g, b);	}
+	/// Clear up the frame and fill background by specified color with manual transparency
+	inline void Clf(const char *col)	{	mgl_clf_str(gr, col);	}
+	/// Clear up the frame and fill background by specified color
+	inline void Clf(char col)	{	mgl_clf_chr(gr, col);	}
+	/// Clear up the frame
+	inline void Clf()	{	mgl_clf(gr);	}
+	/// Clear unused points and primitives. Useful only in combination with SetFaceNum().
+	inline void ClearUnused()	{	mgl_clear_unused(gr);	}
+
+	/// Load background image
+	inline void LoadBackground(const char *fname, double alpha=1)
+	{	mgl_load_background(gr,fname,alpha);	}
+	/// Force drawing the image and use it as background one
+	inline void Rasterize()			{	mgl_rasterize(gr);	}
+
+	/// Draws the point (ball) at position {x,y,z} with color c
+	inline void Ball(mglPoint p, char c='r')
+	{	char s[3]={'.',c,0};	mgl_mark(gr, p.x, p.y, p.z, s);	}
+	/// Draws the mark at position p
+	inline void Mark(mglPoint p, const char *mark)
+	{	mgl_mark(gr, p.x, p.y, p.z, mark);	}
+	/// Draws the line between points by specified pen
+	/** Large \a n (for example, n=100) should be used for geodesic line in curved coordinates */
+	inline void Line(mglPoint p1, mglPoint p2, const char *pen="B",int n=2)
+	{	mgl_line(gr, p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, pen, n);	}
+	/// Draws the spline curve between points by specified pen
+	inline void Curve(mglPoint p1, mglPoint d1, mglPoint p2, mglPoint d2, const char *pen="B", int n=100)
+	{	mgl_curve(gr, p1.x, p1.y, p1.z, d1.x, d1.y, d1.z, p2.x, p2.y, p2.z, d2.x, d2.y, d2.z, pen, n);	}
+	/// Draws the 3d error box e for point p
+	inline void Error(mglPoint p, mglPoint e, const char *pen="k")
+	{	mgl_error_box(gr, p.x, p.y, p.z, e.x, e.y, e.z, pen);	}
+
+	/// Draws Lamerey diagram for mapping x_new = f(x_old)
+	/** String \a stl may contain: ‘v’ for drawing arrows; ‘~’ for disable 1st segment.
+	 *	Option value set the number of segments (default is 20).*/
+	inline void Lamerey(double x0, const mglDataA &f, const char *stl="", const char *opt="")
+	{	mgl_lamerey_dat(gr,x0,&f,stl,opt);	}
+	inline void Lamerey(double x0, const char *func, const char *stl="", const char *opt="")
+	{	mgl_lamerey_str(gr,x0,func,stl,opt);	}
+	/// Draws Bifurcation diagram for mapping x_new = f(x_old) in x-axis range
+	/** Option value set the number of stationary points (default is 1024).*/
+	inline void Bifurcation(double dx, const mglDataA &f, const char *stl="", const char *opt="")
+	{	mgl_bifurcation_dat(gr,dx,&f,stl,opt);	}
+	inline void Bifurcation(double dx, const char *func, const char *stl="", const char *opt="")
+	{	mgl_bifurcation_str(gr,dx,func,stl,opt);	}
+
+	/// Draws Iris plots for determining cross-dependences of data arrays
+	/** NOTE: using the same ranges and empty ids will not draw axis. This will add data to existing Iris plot.
+	 * 	Option value set the size of data labels ids, separated by ';'.*/
+	inline void Iris(mglDataA &dats, const char *ids, const char *stl="", const char *opt="")
+	{	mgl_iris_1(gr,&dats,ids,stl,opt);	}
+	inline void Iris(mglDataA &dats, const wchar_t *ids, const char *stl="", const char *opt="")
+	{	mgl_irisw_1(gr,&dats,ids,stl,opt);	}
+	inline void Iris(mglDataA &dats, mglDataA &ranges, const char *ids, const char *stl="", const char *opt="")
+	{	mgl_iris(gr,&dats,&ranges,ids,stl,opt);	}
+	inline void Iris(mglDataA &dats, mglDataA &ranges, const wchar_t *ids, const char *stl="", const char *opt="")
+	{	mgl_irisw(gr,&dats,&ranges,ids,stl,opt);	}
+
+	/// Draws the face between points with color stl (include interpolation up to 4 colors).
+	inline void Face(mglPoint p1, mglPoint p2, mglPoint p3, mglPoint p4, const char *stl="r")
+	{	mgl_face(gr, p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, p3.x, p3.y, p3.z, p4.x, p4.y, p4.z, stl);	}
+	/// Draws the face in y-z plane at point p with color stl (include interpolation up to 4 colors).
+	inline void FaceX(mglPoint p, double wy, double wz, const char *stl="w", double dx=0, double dy=0)
+	{	mgl_facex(gr, p.x, p.y, p.z, wy, wz, stl, dx, dy);	}
+	/// Draws the face in x-z plane at point p with color stl (include interpolation up to 4 colors).
+	inline void FaceY(mglPoint p, double wx, double wz, const char *stl="w", double dx=0, double dy=0)
+	{	mgl_facey(gr, p.x, p.y, p.z, wx, wz, stl, dx, dy);	}
+	/// Draws the face in x-y plane at point p with color stl (include interpolation up to 4 colors).
+	inline void FaceZ(mglPoint p, double wx, double wy, const char *stl="w", double dx=0, double dy=0)
+	{	mgl_facez(gr, p.x, p.y, p.z, wx, wy, stl, dx, dy);	}
+	/// Draws the drop at point p in direction d with color col and radius r
+	/** Parameter \a shift set the degree of drop oblongness: ‘0’ is sphere, ‘1’ is maximally oblongness drop. Parameter \a ap set relative width of the drop (this is analogue of “ellipticity” for the sphere).*/
+	inline void Drop(mglPoint p, mglPoint d, double r, const char *col="r", double shift=1, double ap=1)
+	{	mgl_drop(gr, p.x, p.y, p.z, d.x, d.y, d.z, r, col, shift, ap);	}
+	/// Draws the sphere at point p with color col and radius r
+	inline void Sphere(mglPoint p, double r, const char *col="r")
+	{	mgl_sphere(gr, p.x, p.y, p.z, r, col);	}
+	/// Draws the cone between points p1,p2 with radius r1,r2 and with style stl
+	/** Parameter \a stl can contain:
+	 * ‘@’ for drawing edges;
+	 * ‘#’ for wired cones;
+	 * ‘t’ for drawing tubes/cylinder instead of cones/prisms;
+	 * ‘4’, ‘6’, ‘8’ for drawing square, hex- or octo-prism instead of cones.*/
+	inline void Cone(mglPoint p1, mglPoint p2, double r1, double r2=-1, const char *stl="r@")
+	{	mgl_cone(gr, p1.x, p1.y, p1.z, p2.x, p2.y, p2.z,r1,r2,stl);	}
+	/// Draws the ellipse between points p1,p2 with color stl and width r
+	/** Parameter \a stl can contain:
+	 * ‘#’ for wired figure (boundary only);
+	 * ‘@’ for filled figure and with boundary (second color or black one is used for boundary).*/
+	inline void Ellipse(mglPoint p1, mglPoint p2, double r, const char *stl="r")
+	{	mgl_ellipse(gr, p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, r,stl);	}
+	/// Draws the circle at point p with color stl and radius r
+	/** Parameter \a stl can contain:
+	 * ‘#’ for wired figure (boundary only);
+	 * ‘@’ for filled figure and with boundary (second color or black one is used for boundary).*/
+	inline void Circle(mglPoint p, double r, const char *stl="r")
+	{	mgl_ellipse(gr, p.x, p.y, p.z, p.x, p.y, p.z, r,stl);	}
+	/// Draws the rhomb between points p1,p2 with color stl and width r
+	/** Parameter \a stl can contain:
+	 * ‘#’ for wired figure (boundary only);
+	 * ‘@’ for filled figure and with boundary (second color or black one is used for boundary).*/
+	inline void Rhomb(mglPoint p1, mglPoint p2, double r, const char *stl="r")
+	{	mgl_rhomb(gr, p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, r,stl);	}
+	/// Draws the polygon based on points p1,p2 with color stl
+	/** Parameter \a stl can contain:
+	 * ‘#’ for wired figure (boundary only);
+	 * ‘@’ for filled figure and with boundary (second color or black one is used for boundary).*/
+	inline void Polygon(mglPoint p1, mglPoint p2, int n, const char *stl="r")
+	{	mgl_polygon(gr, p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, n,stl);	}
+	/// Draws the arc around axis pr with center at p0 and starting from p1, by color stl and angle a (in degrees)
+	inline void Arc(mglPoint p0, mglPoint pa, mglPoint p1, double a, const char *stl="r")
+	{	mgl_arc_ext(gr, p0.x,p0.y,p0.z, pa.x,pa.y,pa.z, p1.x,p1.y,p1.z, a,stl);	}
+	/// Draws the arc around axis 'z' with center at p0 and starting from p1, by color stl and angle a (in degrees)
+	inline void Arc(mglPoint p0, mglPoint p1, double a, const char *stl="r")
+	{	mgl_arc_ext(gr, p0.x,p0.y,p0.z, 0,0,1, p1.x,p1.y,p0.z, a,stl);	}
+	/// Draws bitmap (logo) which is stretched along whole axis range
+	inline void Logo(long w, long h, const unsigned char *rgba, bool smooth=false, const char *opt="")
+	{	mgl_logo(gr, w, h, rgba, smooth, opt);	}
+	inline void Logo(const char *fname, bool smooth=false, const char *opt="")
+	{	mgl_logo_file(gr, fname, smooth, opt);	}
+
+	/// Draw user-defined symbol in position p
+	inline void Symbol(mglPoint p, char id, const char *how="", double size=-1)
+	{	mgl_symbol(gr, p.x, p.y, p.z, id, how, size);	}
+	/// Draw user-defined symbol in position p along direction d
+	inline void Symbol(mglPoint p, mglPoint d, char id, const char *how="", double size=-1)
+	{	mgl_symbol_dir(gr, p.x, p.y, p.z, d.x, d.y, d.z, id, how, size);	}
+
+	/// Print text in position p with specified font
+	inline void Putsw(mglPoint p,const wchar_t *text,const char *font=":C",double size=-1)
+	{	mgl_putsw(gr, p.x, p.y, p.z, text, font, size);	}
+	/// Print text in position p with specified font
+	inline void Puts(mglPoint p,const char *text,const char *font=":C",double size=-1)
+	{	mgl_puts(gr, p.x, p.y, p.z, text, font, size);	}
+	/// Print text in position p with specified font
+	inline void Putsw(double x, double y,const wchar_t *text,const char *font=":AC",double size=-1)
+	{	mgl_putsw(gr, x, y, 0, text, font, size);	}
+	/// Print text in position p with specified font
+	inline void Puts(double x, double y,const char *text,const char *font=":AC",double size=-1)
+	{	mgl_puts(gr, x, y, 0, text, font, size);	}
+	/// Print text in position p along direction d with specified font
+	inline void Putsw(mglPoint p, mglPoint d, const wchar_t *text, const char *font=":L", double size=-1)
+	{	mgl_putsw_dir(gr, p.x, p.y, p.z, d.x, d.y, d.z, text, font, size);	}
+	/// Print text in position p along direction d with specified font
+	inline void Puts(mglPoint p, mglPoint d, const char *text, const char *font=":L", double size=-1)
+	{	mgl_puts_dir(gr, p.x, p.y, p.z, d.x, d.y, d.z, text, font, size);	}
+
+	/// Print text along the curve
+	inline void Text(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *text, const char *font="", const char *opt="")
+	{	mgl_text_xyz(gr, &x, &y, &z, text, font, opt);	}
+	/// Print text along the curve
+	inline void Text(const mglDataA &x, const mglDataA &y, const char *text, const char *font="", const char *opt="")
+	{	mgl_text_xy(gr, &x, &y, text, font, opt);	}
+	/// Print text along the curve
+	inline void Text(const mglDataA &y, const char *text, const char *font="", const char *opt="")
+	{	mgl_text_y(gr, &y, text, font, opt);	}
+	/// Print text along the curve
+	inline void Text(const mglDataA &x, const mglDataA &y, const mglDataA &z, const wchar_t *text, const char *font="", const char *opt="")
+	{	mgl_textw_xyz(gr, &x, &y, &z, text, font, opt);	}
+	/// Print text along the curve
+	inline void Text(const mglDataA &x, const mglDataA &y, const wchar_t *text, const char *font="", const char *opt="")
+	{	mgl_textw_xy(gr, &x, &y, text, font, opt);	}
+	/// Print text along the curve
+	inline void Text(const mglDataA &y, const wchar_t *text, const char *font="", const char *opt="")
+	{	mgl_textw_y(gr, &y, text, font, opt);	}
+
+	/// Draws bounding box outside the plotting volume with color c.
+	/** Style ‘@’ produce filled back faces. */
+	inline void Box(const char *col="", bool ticks=true)
+	{	mgl_box_str(gr, col, ticks);	}
+	/// Draw axises with ticks in direction(s) dir.
+	/** Parameter \a dir may contain:
+	 *	‘xyzt’for drawing axis in corresponding direction;
+	 *	‘XYZT’ for drawing axis in corresponding direction but with inverted positions of labels;
+	 *	‘~’, ‘_’ for disabling tick labels;
+	 *	‘U’ for disabling rotation of tick labels;
+	 *	‘^’ for inverting default axis origin;
+	 *	‘!’ for disabling ticks tuning;
+	 *	‘AKDTVISO’ for drawing arrow at the end of axis;
+	 *	‘a’ for forced adjusting of axis ticks;
+	 *	‘f’ for printing ticks labels in fixed format;
+	 *	‘E’ for using ‘E’ instead of ‘e’ in ticks labels;
+	 *	‘F’ for printing ticks labels in LaTeX format;
+	 *	‘+’ for printing ‘+’ for positive ticks;
+	 *	‘-’ for printing usual ‘-’ in ticks labels;
+	 *	‘0123456789’ for precision at printing ticks labels.
+	 *	 Option "value" set the manual rotation angle for the ticks. */
+	inline void Axis(const char *dir="xyzt", const char *stl="", const char *opt="")
+	{	mgl_axis(gr, dir,stl,opt);	}
+	/// Draw grid lines perpendicular to direction(s) dir.
+	inline void Grid(const char *dir="xyzt",const char *pen="B", const char *opt="")
+	{	mgl_axis_grid(gr, dir, pen, opt);	}
+	/// Print the label text for axis dir.
+	/** Option "value" set additional shifting of the label. */
+	inline void Label(char dir, const char *text, double pos=+1, const char *opt="")
+	{	mgl_label(gr, dir, text, pos, opt);	}
+	/// Print the label text for axis dir.
+	/** Option "value" set additional shifting of the label. */
+	inline void Label(char dir, const wchar_t *text, double pos=+1, const char *opt="")
+	{	mgl_labelw(gr, dir, text, pos, opt);	}
+
+	/// Draw colorbar at edge of axis
+	/** Parameter \a sch may contain:
+	 *	 ‘<>^_’ for positioning at left, at right, at top or at bottom correspondingly;
+	 *	 ‘I’ for positioning near bounding (by default, at edges of subplot);
+	 *	 ‘A’ for using absolute coordinates;
+	 *	 ‘~’ for disabling tick labels.
+	 *	 ‘!’ for disabling ticks tuning;
+	 *	 ‘f’ for printing ticks labels in fixed format;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’ in ticks labels;
+	 *	 ‘F’ for printing ticks labels in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive ticks;
+	 *	 ‘-’ for printing usual ‘-’ in ticks labels;
+	 *	 ‘0123456789’ for precision at printing ticks labels.*/
+	inline void Colorbar(const char *sch="")
+	{	mgl_colorbar(gr, sch);	}
+	/// Draw colorbar at manual position
+	/** Parameter \a sch may contain:
+	 *	 ‘<>^_’ for positioning at left, at right, at top or at bottom correspondingly;
+	 *	 ‘I’ for positioning near bounding (by default, at edges of subplot);
+	 *	 ‘A’ for using absolute coordinates;
+	 *	 ‘~’ for disabling tick labels.
+	 *	 ‘!’ for disabling ticks tuning;
+	 *	 ‘f’ for printing ticks labels in fixed format;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’ in ticks labels;
+	 *	 ‘F’ for printing ticks labels in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive ticks;
+	 *	 ‘-’ for printing usual ‘-’ in ticks labels;
+	 *	 ‘0123456789’ for precision at printing ticks labels.*/
+	inline void Colorbar(const char *sch,double x,double y,double w=1,double h=1)
+	{	mgl_colorbar_ext(gr, sch, x,y,w,h);	}
+	/// Draw colorbar with manual colors at edge of axis
+	/** Parameter \a sch may contain:
+	 *	 ‘<>^_’ for positioning at left, at right, at top or at bottom correspondingly;
+	 *	 ‘I’ for positioning near bounding (by default, at edges of subplot);
+	 *	 ‘A’ for using absolute coordinates;
+	 *	 ‘~’ for disabling tick labels.
+	 *	 ‘!’ for disabling ticks tuning;
+	 *	 ‘f’ for printing ticks labels in fixed format;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’ in ticks labels;
+	 *	 ‘F’ for printing ticks labels in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive ticks;
+	 *	 ‘-’ for printing usual ‘-’ in ticks labels;
+	 *	 ‘0123456789’ for precision at printing ticks labels.*/
+	inline void Colorbar(const mglDataA &val, const char *sch="")
+	{	mgl_colorbar_val(gr, &val, sch);	}
+	/// Draw colorbar with manual colors at manual position
+	/** Parameter \a sch may contain:
+	 *	 ‘<>^_’ for positioning at left, at right, at top or at bottom correspondingly;
+	 *	 ‘I’ for positioning near bounding (by default, at edges of subplot);
+	 *	 ‘A’ for using absolute coordinates;
+	 *	 ‘~’ for disabling tick labels.
+	 *	 ‘!’ for disabling ticks tuning;
+	 *	 ‘f’ for printing ticks labels in fixed format;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’ in ticks labels;
+	 *	 ‘F’ for printing ticks labels in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive ticks;
+	 *	 ‘-’ for printing usual ‘-’ in ticks labels;
+	 *	 ‘0123456789’ for precision at printing ticks labels.*/
+	inline void Colorbar(const mglDataA &val, const char *sch,double x,double y,double w=1,double h=1)
+	{	mgl_colorbar_val_ext(gr, &val, sch, x,y,w,h);	}
+
+	/// Add string to legend
+	inline void AddLegend(const char *text,const char *style)
+	{	mgl_add_legend(gr, text, style);	}
+	inline void AddLegend(const wchar_t *text,const char *style)
+	{	mgl_add_legendw(gr, text, style);	}
+	/// Clear saved legend string
+	inline void ClearLegend()
+	{	mgl_clear_legend(gr);	}
+	/// Draw legend of accumulated strings at position {x,y}
+	/** Parameter fnt may contain:
+	 *	 font style for legend text;
+	 *	 colors for background (first one), border (second one) and text (last one);
+	 *	 ‘A’ for positioning in absolute coordinates;
+	 *	 ‘^’ for positioning outside of specified point;
+	 *	 ‘-’ for arranging entries horizontally;
+	 *	 ‘#’ for drawing box around legend.
+	 * Option value set the space between line samples and text (default is 0.1).*/
+	inline void Legend(double x, double y, const char *font="#", const char *opt="")
+	{	mgl_legend_pos(gr, x, y, font, opt);	}
+	/// Draw legend of accumulated strings
+	/** Parameter fnt may contain:
+	 *	 font style for legend text;
+	 *	 colors for background (first one), border (second one) and text (last one);
+	 *	 ‘A’ for positioning in absolute coordinates;
+	 *	 ‘^’ for positioning outside of specified point;
+	 *	 ‘-’ for arranging entries horizontally;
+	 *	 ‘#’ for drawing box around legend.
+	 * Option value set the space between line samples and text (default is 0.1).
+	 * Parameter \a where sets position: 0 at bottom-left, 1 at bottom-right, 2 at top-left, 3 at top-right (default).*/
+	inline void Legend(int where=3, const char *font="#", const char *opt="")
+	{	mgl_legend(gr, where, font, opt);	}
+	/// Set number of marks in legend sample
+	inline void SetLegendMarks(int num)		{	mgl_set_legend_marks(gr, num);	}
+
+	/// Draw usual curve {x,y,z}
+	inline void Plot(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *pen="", const char *opt="")
+	{	mgl_plot_xyz(gr, &x, &y, &z, pen, opt);	}
+	/// Draw usual curve {x,y}
+	inline void Plot(const mglDataA &x, const mglDataA &y, const char *pen="", const char *opt="")
+	{	mgl_plot_xy(gr, &x, &y, pen,opt);	}
+	/// Draw usual curve {x,y} with x in x-axis range
+	inline void Plot(const mglDataA &y, const char *pen="", const char *opt="")
+	{	mgl_plot(gr, &y, pen,opt);	}
+	/// Draw tapes which rotates as (bi-)normales of curve {x,y,z}
+	/** The width of tape is proportional to barwidth and can be changed by option "value".*/
+	inline void Tape(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *pen="", const char *opt="")
+	{	mgl_tape_xyz(gr, &x, &y, &z, pen, opt);	}
+	/// Draw tapes which rotates as (bi-)normales of curve {x,y}
+	/** The width of tape is proportional to barwidth and can be changed by option "value".*/
+	inline void Tape(const mglDataA &x, const mglDataA &y, const char *pen="", const char *opt="")
+	{	mgl_tape_xy(gr, &x, &y, pen,opt);	}
+	/// Draw tapes which rotates as (bi-)normales of curve {x,y} with x in x-axis range
+	/** The width of tape is proportional to barwidth and can be changed by option "value".*/
+	inline void Tape(const mglDataA &y, const char *pen="", const char *opt="")
+	{	mgl_tape(gr, &y, pen,opt);	}
+	/// Draw radar chart (plot in curved coordinates)
+	/** Option "value" set the additional shift of data (i.e. the data a+value is used instead of a).*/
+	inline void Radar(const mglDataA &a, const char *pen="", const char *opt="")
+	{	mgl_radar(gr, &a, pen, opt);	}
+
+	/// Draw stairs for points in arrays {x,y,z}
+	inline void Step(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *pen="", const char *opt="")
+	{	mgl_step_xyz(gr, &x, &y, &z, pen, opt);	}
+	/// Draw stairs for points in arrays {x,y}
+	inline void Step(const mglDataA &x, const mglDataA &y, const char *pen="", const char *opt="")
+	{	mgl_step_xy(gr, &x, &y, pen, opt);	}
+	/// Draw stairs for points in arrays {x,y} with x in x-axis range
+	inline void Step(const mglDataA &y, const char *pen="", const char *opt="")
+	{	mgl_step(gr, &y, pen, opt);	}
+
+	/// Draw curve {x,y,z} which is colored by c (like tension plot)
+	inline void Tens(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &c, const char *pen="", const char *opt="")
+	{	mgl_tens_xyz(gr, &x, &y, &z, &c, pen, opt);	}
+	/// Draw curve {x,y} which is colored by c (like tension plot)
+	inline void Tens(const mglDataA &x, const mglDataA &y, const mglDataA &c, const char *pen="", const char *opt="")
+	{	mgl_tens_xy(gr, &x, &y, &c, pen, opt);	}
+	/// Draw curve {x,y} with x in x-axis range which is colored by c (like tension plot)
+	inline void Tens(const mglDataA &y, const mglDataA &c, const char *pen="", const char *opt="")
+	{	mgl_tens(gr, &y, &c, pen, opt);	}
+
+	/// Fill area between curve {x,y,z} and axis plane
+	/** Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Area(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *pen="", const char *opt="")
+	{	mgl_area_xyz(gr, &x, &y, &z, pen, opt);	}
+	/// Fill area between curve {x,y} and axis plane
+	/** Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Area(const mglDataA &x, const mglDataA &y, const char *pen="", const char *opt="")
+	{	mgl_area_xy(gr, &x, &y, pen, opt);	}
+	/// Fill area between curve {x,y} with x in x-axis range and axis plane
+	/** Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Area(const mglDataA &y, const char *pen="", const char *opt="")
+	{	mgl_area(gr, &y, pen, opt);	}
+
+	/// Fill area between curves {x,y1} and {x,y2} with x in x-axis range
+	/** Style 'i' will fill area only if y1 < y2.
+	  * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Region(const mglDataA &y1, const mglDataA &y2, const char *pen="", const char *opt="")
+	{	mgl_region(gr, &y1, &y2, pen, opt);	}
+	/// Fill area between curves {x,y1} and {x,y2}
+	/** Style 'i' will fill area only if y1 < y2.
+	  * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Region(const mglDataA &x, const mglDataA &y1, const mglDataA &y2, const char *pen="", const char *opt="")
+	{	mgl_region_xy(gr, &x, &y1, &y2, pen, opt);	}
+	/// Fill area (draw ribbon) between curves {x1,y1,z1} and {x2,y2,z2}
+	/** Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Region(const mglDataA &x1, const mglDataA &y1, const mglDataA &z1, const mglDataA &x2, const mglDataA &y2, const mglDataA &z2, const char *pen="", const char *opt="")
+	{	mgl_region_3d(gr, &x1, &y1, &z1, &x2, &y2, &z2, pen, opt);	}
+	/// Fill area (draw ribbon) between curves {x1,y1} and {x2,y2}
+	/** Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Region(const mglDataA &x1, const mglDataA &y1, const mglDataA &x2, const mglDataA &y2, const char *pen="", const char *opt="")
+	{	mgl_region_3d(gr, &x1, &y1, NULL, &x2, &y2, NULL, pen, opt);	}
+
+	/// Draw vertical lines from points {x,y,z} to axis plane
+	inline void Stem(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *pen="", const char *opt="")
+	{	mgl_stem_xyz(gr, &x, &y, &z, pen, opt);	}
+	/// Draw vertical lines from points {x,y} to axis plane
+	inline void Stem(const mglDataA &x, const mglDataA &y, const char *pen="", const char *opt="")
+	{	mgl_stem_xy(gr, &x, &y, pen, opt);	}
+	/// Draw vertical lines from points {x,y} with x in x-axis range to axis plane
+	inline void Stem(const mglDataA &y, const char *pen="", const char *opt="")
+	{	mgl_stem(gr, &y, pen, opt);	}
+
+	/// Draw vertical bars from points {x,y,z} to axis plane
+	/** String \a pen may contain:
+	 * ‘a’ for drawing boxes one above another (like summation);
+	 * ‘f’ for waterfall chart;
+	 * ‘<’, ‘^’, ‘>’ for aligning boxes: at left, centered, at right.
+	 * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Bars(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *pen="", const char *opt="")
+	{	mgl_bars_xyz(gr, &x, &y, &z, pen, opt);	}
+	/// Draw vertical bars from points {x,y} to axis plane
+	/** String \a pen may contain:
+	 * ‘a’ for drawing boxes one above another (like summation);
+	 * ‘f’ for waterfall chart;
+	 * ‘<’, ‘^’, ‘>’ for aligning boxes: at left, centered, at right.
+	 * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Bars(const mglDataA &x, const mglDataA &y, const char *pen="", const char *opt="")
+	{	mgl_bars_xy(gr, &x, &y, pen, opt);	}
+	/// Draw vertical bars from points {x,y} with x in x-axis range to axis plane
+	/** String \a pen may contain:
+	 * ‘a’ for drawing boxes one above another (like summation);
+	 * ‘f’ for waterfall chart;
+	 * ‘<’, ‘^’, ‘>’ for aligning boxes: at left, centered, at right.
+	 * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Bars(const mglDataA &y, const char *pen="", const char *opt="")
+	{	mgl_bars(gr, &y, pen, opt);	}
+	/// Draw horizontal bars from points {x,y} to axis plane
+	/** String \a pen may contain:
+	 * ‘a’ for drawing boxes one above another (like summation);
+	 * ‘f’ for waterfall chart;
+	 * ‘<’, ‘^’, ‘>’ for aligning boxes: at left, centered, at right.
+	 * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Barh(const mglDataA &y, const mglDataA &v, const char *pen="", const char *opt="")
+	{	mgl_barh_yx(gr, &y, &v, pen, opt);	}
+	/// Draw horizontal bars from points {x,y} with y in y-axis range to axis plane
+	/** String \a pen may contain:
+	 * ‘a’ for drawing boxes one above another (like summation);
+	 * ‘f’ for waterfall chart;
+	 * ‘<’, ‘^’, ‘>’ for aligning boxes: at left, centered, at right.
+	 * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Barh(const mglDataA &v, const char *pen="", const char *opt="")
+	{	mgl_barh(gr, &v, pen, opt);	}
+	/// Draw chart for data a
+	/** Space denote transparent color. Style '#' draw black borders. */
+	inline void Chart(const mglDataA &a, const char *colors="", const char *opt="")
+	{	mgl_chart(gr, &a, colors,opt);	}
+
+	/// Draw Open-High-Low-Close (OHLC) diagram
+	/**  Different colors for up and down values are used if number of specified colors is equal to 2*number of curves. */
+	inline void OHLC(const mglDataA &x, const mglDataA &open, const mglDataA &high, const mglDataA &low, const mglDataA &close, const char *pen="", const char *opt="")
+	{	mgl_ohlc_x(gr, &x, &open,&high,&low,&close,pen,opt);	}
+	/// Draw Open-High-Low-Close (OHLC) diagram with x in x-axis range
+	/**  Different colors for up and down values are used if number of specified colors is equal to 2*number of curves. */
+	inline void OHLC(const mglDataA &open, const mglDataA &high, const mglDataA &low, const mglDataA &close, const char *pen="", const char *opt="")
+	{	mgl_ohlc(gr, &open,&high,&low,&close,pen,opt);	}
+
+	/// Draw box-plot (special 5-value plot used in statistic)
+	/** String \a pen may contain ‘<’, ‘^’, ‘>’ for aligning boxes: at left, centered, at right.*/
+	inline void BoxPlot(const mglDataA &x, const mglDataA &y, const char *pen="", const char *opt="")
+	{	mgl_boxplot_xy(gr, &x, &y, pen,opt);	}
+	/// Draw box-plot (special 5-value plot used in statistic) with x in x-axis range
+	/** String \a pen may contain ‘<’, ‘^’, ‘>’ for aligning boxes: at left, centered, at right.*/
+	inline void BoxPlot(const mglDataA &y, const char *pen="", const char *opt="")
+	{	mgl_boxplot(gr, &y, pen,opt);	}
+
+	/// Draw candle plot
+	/** Different colors are used for up and down values if 2 colors are specified.
+	 *  Style ‘#’ force drawing wire candle even for 2-color scheme. */
+	inline void Candle(const mglDataA &x, const mglDataA &v1, const mglDataA &v2, const mglDataA &y1, const mglDataA &y2, const char *pen="", const char *opt="")
+	{	mgl_candle_xyv(gr, &x, &v1, &v2, &y1, &y2, pen, opt);	}
+	/// Draw candle plot with x in x-axis range
+	/** Different colors are used for up and down values if 2 colors are specified.
+	 *  Style ‘#’ force drawing wire candle even for 2-color scheme. */
+	inline void Candle(const mglDataA &v1, const mglDataA &v2, const mglDataA &y1, const mglDataA &y2, const char *pen="", const char *opt="")
+	{	mgl_candle_yv(gr, &v1, &v2, &y1, &y2, pen, opt);	}
+	inline void Candle(const mglDataA &v1, const mglDataA &v2, const char *pen="", const char *opt="")
+	{	mgl_candle_yv(gr, &v1, &v2, NULL, NULL, pen, opt);	}
+	/// Draw candle plot with v1=v[i], v2=v[i+1]
+	/** Different colors are used for up and down values if 2 colors are specified.
+	 *  Style ‘#’ force drawing wire candle even for 2-color scheme. */
+	inline void Candle(const mglDataA &y, const mglDataA &y1, const mglDataA &y2, const char *pen="", const char *opt="")
+	{	mgl_candle(gr, &y, &y1, &y2, pen, opt);	}
+	/// Draw candle plot with v1=v[i], v2=v[i+1]
+	/** Different colors are used for up and down values if 2 colors are specified.
+	 *  Style ‘#’ force drawing wire candle even for 2-color scheme. */
+	inline void Candle(const mglDataA &y, const char *pen="", const char *opt="")
+	{	mgl_candle(gr, &y, NULL, NULL, pen, opt);	}
+
+	/// Draw cones from points {x,y,z} to axis plane
+	/** String \a pen may contain:
+	 * ‘@’ for drawing edges;
+	 * ‘#’ for wired cones;
+	 * ‘t’ for drawing tubes/cylinders instead of cones/prisms;
+	 * ‘4’, ‘6’, ‘8’ for drawing square, hex- or octo-prism instead of cones;
+	 * ‘<’, ‘^’ or ‘>’ for aligning cones left, right or centering them at its x-coordinates.
+	 * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Cones(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *pen="@", const char *opt="")
+	{	mgl_cones_xyz(gr, &x, &y, &z, pen, opt);	}
+	/// Draw cones from points {x,z} to axis plane
+	/** String \a pen may contain:
+	 * ‘@’ for drawing edges;
+	 * ‘#’ for wired cones;
+	 * ‘t’ for drawing tubes/cylinders instead of cones/prisms;
+	 * ‘4’, ‘6’, ‘8’ for drawing square, hex- or octo-prism instead of cones;
+	 * ‘<’, ‘^’ or ‘>’ for aligning cones left, right or centering them at its x-coordinates.
+	 * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Cones(const mglDataA &x, const mglDataA &z, const char *pen="@", const char *opt="")
+	{	mgl_cones_xz(gr, &x, &z, pen, opt);	}
+	/// Draw cones from points {x,z} with x in x-axis range to axis plane
+	/** String \a pen may contain:
+	 * ‘@’ for drawing edges;
+	 * ‘#’ for wired cones;
+	 * ‘t’ for drawing tubes/cylinders instead of cones/prisms;
+	 * ‘4’, ‘6’, ‘8’ for drawing square, hex- or octo-prism instead of cones;
+	 * ‘<’, ‘^’ or ‘>’ for aligning cones left, right or centering them at its x-coordinates.
+	 * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Cones(const mglDataA &z, const char *pen="@", const char *opt="")
+	{	mgl_cones(gr, &z, pen, opt);	}
+
+	/// Draw error boxes {ey} at points {x,y} with x in x-axis range
+	/** Style ‘@’ set to draw large semitransparent mark instead of error box.*/
+	inline void Error(const mglDataA &y, const mglDataA &ey, const char *pen="", const char *opt="")
+	{	mgl_error(gr, &y, &ey, pen, opt);	}
+	/// Draw error boxes {ey} at points {x,y}
+	/** Style ‘@’ set to draw large semitransparent mark instead of error box.*/
+	inline void Error(const mglDataA &x, const mglDataA &y, const mglDataA &ey, const char *pen="", const char *opt="")
+	{	mgl_error_xy(gr, &x, &y, &ey, pen, opt);	}
+	/// Draw error boxes {ex,ey} at points {x,y}
+	/** Style ‘@’ set to draw large semitransparent mark instead of error box.*/
+	inline void Error(const mglDataA &x, const mglDataA &y, const mglDataA &ex, const mglDataA &ey, const char *pen="", const char *opt="")
+	{	mgl_error_exy(gr, &x, &y, &ex, &ey, pen, opt);	}
+
+	/// Draw marks with size r at points {x,y,z}
+	inline void Mark(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &r, const char *pen, const char *opt="")
+	{	mgl_mark_xyz(gr, &x, &y, &z, &r, pen, opt);	}
+	/// Draw marks with size r at points {x,y}
+	inline void Mark(const mglDataA &x, const mglDataA &y, const mglDataA &r, const char *pen, const char *opt="")
+	{	mgl_mark_xy(gr, &x, &y, &r, pen, opt);	}
+	/// Draw marks with size r at points {x,y} with x in x-axis range
+	inline void Mark(const mglDataA &y, const mglDataA &r, const char *pen, const char *opt="")
+	{	mgl_mark_y(gr, &y, &r, pen, opt);	}
+
+	/// Draw Poincare map at condition s==0 for curve {x,y,z}
+	inline void Pmap(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &s, const char *pen, const char *opt="")
+	{	mgl_pmap_xyz(gr, &x, &y, &z, &s, pen, opt);	}
+	/// Draw Poincare map at condition s==0 for curve {x,y}
+	inline void Pmap(const mglDataA &x, const mglDataA &y, const mglDataA &s, const char *pen, const char *opt="")
+	{	mgl_pmap_xy(gr, &x, &y, &s, pen, opt);	}
+	/// Draw Poincare map at condition s==0 for curve {x,y} with x in x-axis range
+	inline void Pmap(const mglDataA &y, const mglDataA &s, const char *pen, const char *opt="")
+	{	mgl_pmap(gr, &y, &s, pen, opt);	}
+
+	/// Draw textual marks with size r at points {x,y,z}
+	inline void TextMark(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &r, const char *text, const char *fnt="", const char *opt="")
+	{	mgl_textmark_xyzr(gr, &x, &y, &z, &r, text, fnt, opt);	}
+	/// Draw textual marks with size r at points {x,y}
+	inline void TextMark(const mglDataA &x, const mglDataA &y, const mglDataA &r, const char *text, const char *fnt="", const char *opt="")
+	{	mgl_textmark_xyr(gr, &x, &y, &r, text, fnt, opt);	}
+	/// Draw textual marks with size r at points {x,y} with x in x-axis range
+	inline void TextMark(const mglDataA &y, const mglDataA &r, const char *text, const char *fnt="", const char *opt="")
+	{	mgl_textmark_yr(gr, &y, &r, text, fnt, opt);	}
+	/// Draw textual marks at points {x,y} with x in x-axis range
+	inline void TextMark(const mglDataA &y, const char *text, const char *fnt="", const char *opt="")
+	{	mgl_textmark(gr, &y, text, fnt, opt);	}
+	/// Draw textual marks with size r at points {x,y,z}
+	inline void TextMark(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &r, const wchar_t *text, const char *fnt="", const char *opt="")
+	{	mgl_textmarkw_xyzr(gr, &x, &y, &z, &r, text, fnt, opt);	}
+	/// Draw textual marks with size r at points {x,y}
+	inline void TextMark(const mglDataA &x, const mglDataA &y, const mglDataA &r, const wchar_t *text, const char *fnt="", const char *opt="")
+	{	mgl_textmarkw_xyr(gr, &x, &y, &r, text, fnt, opt);	}
+	/// Draw textual marks with size r at points {x,y} with x in x-axis range
+	inline void TextMark(const mglDataA &y, const mglDataA &r, const wchar_t *text, const char *fnt="", const char *opt="")
+	{	mgl_textmarkw_yr(gr, &y, &r, text, fnt, opt);	}
+	/// Draw textual marks at points {x,y} with x in x-axis range
+	inline void TextMark(const mglDataA &y, const wchar_t *text, const char *fnt="", const char *opt="")
+	{	mgl_textmarkw(gr, &y, text, fnt, opt);	}
+
+	/// Draw labels for points coordinate(s) at points {x,y,z}
+	/** String \a fnt may contain:
+	 *	 ‘f’ for fixed format of printed numbers;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’;
+	 *	 ‘F’ for printing in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive numbers;
+	 *	 ‘-’ for printing usual ‘-’;
+	 *	 ‘0123456789’ for precision at printing numbers.*/
+	inline void Label(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *text, const char *fnt="", const char *opt="")
+	{	mgl_label_xyz(gr, &x, &y, &z, text, fnt, opt);	}
+	/// Draw labels for points coordinate(s) at points {x,y}
+	/** String \a fnt may contain:
+	 *	 ‘f’ for fixed format of printed numbers;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’;
+	 *	 ‘F’ for printing in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive numbers;
+	 *	 ‘-’ for printing usual ‘-’;
+	 *	 ‘0123456789’ for precision at printing numbers.*/
+	inline void Label(const mglDataA &x, const mglDataA &y, const char *text, const char *fnt="", const char *opt="")
+	{	mgl_label_xy(gr, &x, &y, text, fnt, opt);	}
+	/// Draw labels for points coordinate(s) at points {x,y} with x in x-axis range
+	/** String \a fnt may contain:
+	 *	 ‘f’ for fixed format of printed numbers;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’;
+	 *	 ‘F’ for printing in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive numbers;
+	 *	 ‘-’ for printing usual ‘-’;
+	 *	 ‘0123456789’ for precision at printing numbers.*/
+	inline void Label(const mglDataA &y, const char *text, const char *fnt="", const char *opt="")
+	{	mgl_label_y(gr, &y, text, fnt, opt);	}
+	/// Draw labels for points coordinate(s) at points {x,y,z}
+	/** String \a fnt may contain:
+	 *	 ‘f’ for fixed format of printed numbers;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’;
+	 *	 ‘F’ for printing in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive numbers;
+	 *	 ‘-’ for printing usual ‘-’;
+	 *	 ‘0123456789’ for precision at printing numbers.*/
+	inline void Label(const mglDataA &x, const mglDataA &y, const mglDataA &z, const wchar_t *text, const char *fnt="", const char *opt="")
+	{	mgl_labelw_xyz(gr, &x, &y, &z, text, fnt, opt);	}
+	/// Draw labels for points coordinate(s) at points {x,y}
+	/** String \a fnt may contain:
+	 *	 ‘f’ for fixed format of printed numbers;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’;
+	 *	 ‘F’ for printing in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive numbers;
+	 *	 ‘-’ for printing usual ‘-’;
+	 *	 ‘0123456789’ for precision at printing numbers.*/
+	inline void Label(const mglDataA &x, const mglDataA &y, const wchar_t *text, const char *fnt="", const char *opt="")
+	{	mgl_labelw_xy(gr, &x, &y, text, fnt, opt);	}
+	/// Draw labels for points coordinate(s) at points {x,y} with x in x-axis range
+	/** String \a fnt may contain:
+	 *	 ‘f’ for fixed format of printed numbers;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’;
+	 *	 ‘F’ for printing in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive numbers;
+	 *	 ‘-’ for printing usual ‘-’;
+	 *	 ‘0123456789’ for precision at printing numbers.*/
+	inline void Label(const mglDataA &y, const wchar_t *text, const char *fnt="", const char *opt="")
+	{	mgl_labelw_y(gr, &y, text, fnt, opt);	}
+
+	/// Draw table for values val along given direction with row labels text
+	/** String \a fnt may contain:
+	 *	 ‘#’ for drawing cell borders;
+	 *	 ‘|’ for limiting table widh by subplot one (equal to option ‘value 1’);
+	 *	 ‘=’ for equal width of all cells;
+	 *	 ‘f’ for fixed format of printed numbers;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’;
+	 *	 ‘F’ for printing in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive numbers;
+	 *	 ‘-’ for printing usual ‘-’;
+	 *	 ‘0123456789’ for precision at printing numbers.
+	 * Option value set the width of the table (default is 1).*/
+	inline void Table(const mglDataA &val, const char *text, const char *fnt="#|", const char *opt="")
+	{	mgl_table(gr, 0, 0, &val, text, fnt, opt);	}
+	/// Draw table for values val along given direction with row labels text
+	/** String \a fnt may contain:
+	 *	 ‘#’ for drawing cell borders;
+	 *	 ‘|’ for limiting table widh by subplot one (equal to option ‘value 1’);
+	 *	 ‘=’ for equal width of all cells;
+	 *	 ‘f’ for fixed format of printed numbers;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’;
+	 *	 ‘F’ for printing in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive numbers;
+	 *	 ‘-’ for printing usual ‘-’;
+	 *	 ‘0123456789’ for precision at printing numbers.
+	 * Option value set the width of the table (default is 1).*/
+	inline void Table(const mglDataA &val, const wchar_t *text, const char *fnt="#|", const char *opt="")
+	{	mgl_tablew(gr, 0, 0, &val, text, fnt, opt);	}
+	/// Draw table for values val along given direction with row labels text at given position
+	/** String \a fnt may contain:
+	 *	 ‘#’ for drawing cell borders;
+	 *	 ‘|’ for limiting table widh by subplot one (equal to option ‘value 1’);
+	 *	 ‘=’ for equal width of all cells;
+	 *	 ‘f’ for fixed format of printed numbers;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’;
+	 *	 ‘F’ for printing in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive numbers;
+	 *	 ‘-’ for printing usual ‘-’;
+	 *	 ‘0123456789’ for precision at printing numbers.
+	 * Option value set the width of the table (default is 1).*/
+	inline void Table(double x, double y, const mglDataA &val, const char *text, const char *fnt="#|", const char *opt="")
+	{	mgl_table(gr, x, y, &val, text, fnt, opt);	}
+	/// Draw table for values val along given direction with row labels text at given position
+	/** String \a fnt may contain:
+	 *	 ‘#’ for drawing cell borders;
+	 *	 ‘|’ for limiting table widh by subplot one (equal to option ‘value 1’);
+	 *	 ‘=’ for equal width of all cells;
+	 *	 ‘f’ for fixed format of printed numbers;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’;
+	 *	 ‘F’ for printing in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive numbers;
+	 *	 ‘-’ for printing usual ‘-’;
+	 *	 ‘0123456789’ for precision at printing numbers.
+	 * Option value set the width of the table (default is 1).*/
+	inline void Table(double x, double y, const mglDataA &val, const wchar_t *text, const char *fnt="#|", const char *opt="")
+	{	mgl_tablew(gr, x, y, &val, text, fnt, opt);	}
+
+	/// Draw tube with radius r around curve {x,y,z}
+	inline void Tube(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &r, const char *pen="", const char *opt="")
+	{	mgl_tube_xyzr(gr, &x, &y, &z, &r, pen, opt);	}
+	/// Draw tube with radius r around curve {x,y,z}
+	inline void Tube(const mglDataA &x, const mglDataA &y, const mglDataA &z, double r, const char *pen="", const char *opt="")
+	{	mgl_tube_xyz(gr, &x, &y, &z, r, pen, opt);	}
+	/// Draw tube with radius r around curve {x,y}
+	inline void Tube(const mglDataA &x, const mglDataA &y, const mglDataA &r, const char *pen="", const char *opt="")
+	{	mgl_tube_xyr(gr, &x, &y, &r, pen, opt);	}
+	/// Draw tube with radius r around curve {x,y}
+	inline void Tube(const mglDataA &x, const mglDataA &y, double r, const char *pen="", const char *opt="")
+	{	mgl_tube_xy(gr, &x, &y, r, pen, opt);	}
+	/// Draw tube with radius r around curve {x,y} with x in x-axis range
+	inline void Tube(const mglDataA &y, const mglDataA &r, const char *pen="", const char *opt="")
+	{	mgl_tube_r(gr, &y, &r, pen, opt);	}
+	/// Draw tube with radius r around curve {x,y} with x in x-axis range
+	inline void Tube(const mglDataA &y, double r, const char *pen="", const char *opt="")
+	{	mgl_tube(gr, &y, r, pen, opt);	}
+	/// Draw surface of curve {r,z} rotation around axis
+	/** Style ‘#’ produce wire plot. Style ‘.’ produce plot by dots.*/
+	inline void Torus(const mglDataA &r, const mglDataA &z, const char *pen="", const char *opt="")
+	{	mgl_torus(gr, &r, &z, pen,opt);	}
+
+	/// Draw mesh lines for 2d data specified parametrically
+	inline void Mesh(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *stl="", const char *opt="")
+	{	mgl_mesh_xy(gr, &x, &y, &z, stl, opt);	}
+	/// Draw mesh lines for 2d data
+	inline void Mesh(const mglDataA &z, const char *stl="", const char *opt="")
+	{	mgl_mesh(gr, &z, stl, opt);	}
+
+	/// Draw waterfall plot for 2d data specified parametrically
+	/** Style 'x' draw lines in x-direction. */
+	inline void Fall(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *stl="", const char *opt="")
+	{	mgl_fall_xy(gr, &x, &y, &z, stl, opt);	}
+	/// Draw waterfall plot for 2d data
+	/** Style 'x' draw lines in x-direction. */
+	inline void Fall(const mglDataA &z, const char *stl="", const char *opt="")
+	{	mgl_fall(gr, &z, stl, opt);	}
+
+	/// Draw belts for 2d data specified parametrically
+	/** Style 'x' draw belts in x-direction. */
+	inline void Belt(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *stl="", const char *opt="")
+	{	mgl_belt_xy(gr, &x, &y, &z, stl, opt);	}
+	/// Draw belts for 2d data
+	/** Style 'x' draw belts in x-direction. */
+	inline void Belt(const mglDataA &z, const char *stl="", const char *opt="")
+	{	mgl_belt(gr, &z, stl, opt);	}
+
+	/// Draw surface for 2d data specified parametrically with color proportional to z
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void Surf(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *stl="", const char *opt="")
+	{	mgl_surf_xy(gr, &x, &y, &z, stl, opt);	}
+	/// Draw surface for 2d data with color proportional to z
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void Surf(const mglDataA &z, const char *stl="", const char *opt="")
+	{	mgl_surf(gr, &z, stl, opt);	}
+
+	/// Draw grid lines for density plot of 2d data specified parametrically
+	inline void Grid(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *stl="", const char *opt="")
+	{	mgl_grid_xy(gr, &x, &y, &z, stl, opt);	}
+	/// Draw grid lines for density plot of 2d data
+	inline void Grid(const mglDataA &z, const char *stl="", const char *opt="")
+	{	mgl_grid(gr, &z, stl, opt);	}
+
+	/// Draw vertical tiles with manual colors c for 2d data specified parametrically
+	inline void Tile(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &c, const char *stl="", const char *opt="")
+	{	mgl_tile_xyc(gr, &x, &y, &z, &c, stl, opt);	}
+	/// Draw vertical tiles for 2d data specified parametrically
+	inline void Tile(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *stl="", const char *opt="")
+	{	mgl_tile_xy(gr, &x, &y, &z, stl, opt);	}
+	/// Draw vertical tiles for 2d data
+	inline void Tile(const mglDataA &z, const char *stl="", const char *opt="")
+	{	mgl_tile(gr, &z, stl, opt);	}
+
+	/// Draw density plot for 2d data specified parametrically
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void Dens(const mglDataA &x, const mglDataA &y, const mglDataA &c, const char *stl="", const char *opt="")
+	{	mgl_dens_xy(gr, &x, &y, &c, stl, opt);	}
+	/// Draw density plot for 2d data
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void Dens(const mglDataA &c, const char *stl="", const char *opt="")
+	{	mgl_dens(gr, &c, stl, opt);	}
+
+	/// Draw vertical boxes for 2d data specified parametrically
+	/** Style ‘#’ draw filled boxes. */
+	inline void Boxs(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *stl="", const char *opt="")
+	{	mgl_boxs_xy(gr, &x, &y, &z, stl, opt);	}
+	/// Draw vertical boxes for 2d data
+	/** Style ‘#’ draw filled boxes. */
+	inline void Boxs(const mglDataA &z, const char *stl="", const char *opt="")
+	{	mgl_boxs(gr, &z, stl, opt);	}
+
+	/// Draw contour lines on parametric surface at manual levels for 2d data specified parametrically
+	/** Style ‘f’ to draw solid contours.
+	 * Style 't'/'T' draw contour labels below/above contours.*/
+	inline void ContP(const mglDataA &v, const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const char *sch="", const char *opt="")
+	{	mgl_contp_val(gr, &v, &x, &y, &z, &a, sch, opt);	}
+	/// Draw contour lines on parametric surface at manual levels for 2d data specified parametrically
+	/** Style ‘f’ to draw solid contours.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void ContP(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const char *sch="", const char *opt="")
+	{	mgl_contp(gr, &x, &y, &z, &a, sch, opt);	}
+
+
+	/// Draw contour lines at manual levels for 2d data specified parametrically
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Style 't'/'T' draw contour labels below/above contours.*/
+	inline void Cont(const mglDataA &v, const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_cont_xy_val(gr, &v, &x, &y, &z, sch, opt);	}
+	/// Draw contour lines for 2d data
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Style 't'/'T' draw contour labels below/above contours.*/
+	inline void Cont(const mglDataA &v, const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_cont_val(gr, &v, &z, sch, opt);	}
+	/// Draw contour lines at manual levels for 2d data specified parametrically
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void Cont(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_cont_xy(gr, &x, &y, &z, sch, opt);	}
+	/// Draw contour lines for 2d data
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void Cont(const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_cont(gr, &z, sch, opt);	}
+
+	/// Draw solid contours at manual levels for 2d data specified parametrically
+	/** Style ‘_’ to draw contours at bottom of axis box. */
+	inline void ContF(const mglDataA &v, const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_contf_xy_val(gr, &v, &x, &y, &z, sch, opt);	}
+	/// Draw solid contours at manual levels for 2d data
+	/** Style ‘_’ to draw contours at bottom of axis box. */
+	inline void ContF(const mglDataA &v, const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_contf_val(gr, &v, &z, sch, opt);	}
+	/// Draw solid contours for 2d data specified parametrically
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void ContF(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_contf_xy(gr, &x, &y, &z, sch, opt);	}
+	/// Draw solid contours for 2d data
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void ContF(const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_contf(gr, &z, sch, opt);	}
+
+	/// Draw solid contours at manual levels for 2d data specified parametrically with specified colors
+	/** Style ‘_’ to draw contours at bottom of axis box. */
+	inline void ContD(const mglDataA &v, const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_contd_xy_val(gr, &v, &x, &y, &z, sch, opt);	}
+	/// Draw solid contours at manual levels for 2d data with specified colors
+	/** Style ‘_’ to draw contours at bottom of axis box. */
+	inline void ContD(const mglDataA &v, const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_contd_val(gr, &v, &z, sch, opt);	}
+	/// Draw solid contours for 2d data specified parametrically with specified colors
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void ContD(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_contd_xy(gr, &x, &y, &z, sch, opt);	}
+	/// Draw solid contours for 2d data with specified colors
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void ContD(const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_contd(gr, &z, sch, opt);	}
+
+	/// Draw contour tubes between manual levels for 2d data specified parametrically
+	/** Style ‘_’ to draw contours at bottom of axis box. */
+	inline void ContV(const mglDataA &v, const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_contv_xy_val(gr, &v, &x, &y, &z, sch, opt);	}
+	/// Draw contour tubes between manual levels for 2d data
+	/** Style ‘_’ to draw contours at bottom of axis box. */
+	inline void ContV(const mglDataA &v, const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_contv_val(gr, &v, &z, sch, opt);	}
+	/// Draw contour tubes for 2d data specified parametrically
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void ContV(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_contv_xy(gr, &x, &y, &z, sch, opt);	}
+	/// Draw contour tubes for 2d data
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void ContV(const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_contv(gr, &z, sch, opt);	}
+
+	/// Draw axial-symmetric isosurfaces at manual levels for 2d data specified parametrically
+	/** String \a sch may contain:
+	 * ‘#’ for wired plot;
+	 * ‘.’ for plot by dots;
+	 * ‘x’, ‘z’ for rotation around x-, z-axis correspondingly (default is y-axis). */
+	inline void Axial(const mglDataA &v, const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_axial_xy_val(gr, &v, &x, &y, &z, sch,opt);	}
+	/// Draw axial-symmetric isosurfaces at manual levels for 2d data
+	/** String \a sch may contain:
+	 * ‘#’ for wired plot;
+	 * ‘.’ for plot by dots;
+	 * ‘x’, ‘z’ for rotation around x-, z-axis correspondingly (default is y-axis). */
+	inline void Axial(const mglDataA &v, const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_axial_val(gr, &v, &z, sch, opt);	}
+	/// Draw axial-symmetric isosurfaces for 2d data specified parametrically
+	/** String \a sch may contain:
+	 * ‘#’ for wired plot;
+	 * ‘.’ for plot by dots;
+	 * ‘x’, ‘z’ for rotation around x-, z-axis correspondingly (default is y-axis).
+	 * Option "value" set the number of isosurfaces (default is 3). */
+	inline void Axial(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_axial_xy(gr, &x, &y, &z, sch, opt);	}
+	/// Draw axial-symmetric isosurfaces for 2d data
+	/** String \a sch may contain:
+	 * ‘#’ for wired plot;
+	 * ‘.’ for plot by dots;
+	 * ‘x’, ‘z’ for rotation around x-, z-axis correspondingly (default is y-axis).
+	 * Option "value" set the number of isosurfaces (default is 3). */
+	inline void Axial(const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_axial(gr, &z, sch, opt);	}
+
+	/// Draw grid lines for density plot at slice for 3d data specified parametrically
+	/** Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.*/
+	inline void Grid3(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const char *stl="", double sVal=-1, const char *opt="")
+	{	mgl_grid3_xyz(gr, &x, &y, &z, &a, stl, sVal, opt);	}
+	/// Draw grid lines for density plot at slice for 3d data
+	/** Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.*/
+	inline void Grid3(const mglDataA &a, const char *stl="", double sVal=-1, const char *opt="")
+	{	mgl_grid3(gr, &a, stl, sVal, opt);	}
+
+	/// Draw density plot at slice for 3d data specified parametrically
+	/** Style ‘#’ draw grid lines. Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.*/
+	inline void Dens3(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const char *stl="", double sVal=-1, const char *opt="")
+	{	mgl_dens3_xyz(gr, &x, &y, &z, &a, stl, sVal, opt);	}
+	/// Draw density plot at slice for 3d data
+	/** Style ‘#’ draw grid lines. Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.*/
+	inline void Dens3(const mglDataA &a, const char *stl="", double sVal=-1, const char *opt="")
+	{	mgl_dens3(gr, &a, stl, sVal, opt);	}
+
+	/// Draw isosurface for 3d data specified parametrically
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.*/
+	inline void Surf3(double Val, const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const char *stl="", const char *opt="")
+	{	mgl_surf3_xyz_val(gr, Val, &x, &y, &z, &a, stl, opt);	}
+	/// Draw isosurface for 3d data
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.*/
+	inline void Surf3(double Val, const mglDataA &a, const char *stl="", const char *opt="")
+	{	mgl_surf3_val(gr, Val, &a, stl, opt);	}
+	/// Draw isosurfaces for 3d data specified parametrically
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+	 * Option "value" set the number of isosurfaces (default is 3). */
+	inline void Surf3(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const char *stl="", const char *opt="")
+	{	mgl_surf3_xyz(gr, &x, &y, &z, &a, stl, opt);	}
+	/// Draw isosurfaces for 3d data
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+	 * Option "value" set the number of isosurfaces (default is 3). */
+	inline void Surf3(const mglDataA &a, const char *stl="", const char *opt="")
+	{	mgl_surf3(gr, &a, stl, opt);	}
+
+	/// Draw a semi-transparent cloud for 3d data specified parametrically
+	/** Style ‘.’ produce plot by dots. Style ‘i’ use inverted values for transparency. */
+	inline void Cloud(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const char *stl="", const char *opt="")
+	{	mgl_cloud_xyz(gr, &x, &y, &z, &a, stl, opt);	}
+	/// Draw a semi-transparent cloud for 3d data
+	/** Style ‘.’ produce plot by dots. Style ‘i’ use inverted values for transparency. */
+	inline void Cloud(const mglDataA &a, const char *stl="", const char *opt="")
+	{	mgl_cloud(gr, &a, stl, opt);	}
+
+	/// Draw contour lines at manual levels along slice for 3d data specified parametrically
+	/** Style ‘#’ draw grid lines.
+	 * Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours. */
+	inline void Cont3(const mglDataA &v, const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const char *sch="", double sVal=-1, const char *opt="")
+	{	mgl_cont3_xyz_val(gr, &v, &x, &y, &z, &a, sch, sVal, opt);	}
+	/// Draw contour lines at manual levels along slice for 3d data
+	/** Style ‘#’ draw grid lines.
+	 * Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours. */
+	inline void Cont3(const mglDataA &v, const mglDataA &a, const char *sch="", double sVal=-1, const char *opt="")
+	{	mgl_cont3_val(gr, &v, &a, sch, sVal, opt);	}
+	/// Draw contour lines along slice for 3d data specified parametrically
+	/** Style ‘#’ draw grid lines.
+	 * Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void Cont3(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const char *sch="", double sVal=-1, const char *opt="")
+	{	mgl_cont3_xyz(gr, &x, &y, &z, &a, sch, sVal, opt);	}
+	/// Draw contour lines along slice for 3d data
+	/** Style ‘#’ draw grid lines.
+	 * Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void Cont3(const mglDataA &a, const char *sch="", double sVal=-1, const char *opt="")
+	{	mgl_cont3(gr, &a, sch, sVal, opt);	}
+
+	/// Draw solid contours at manual levels along slice for 3d data specified parametrically
+	/** Style ‘#’ draw grid lines. Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly. */
+	inline void ContF3(const mglDataA &v, const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const char *sch="", double sVal=-1, const char *opt="")
+	{	mgl_contf3_xyz_val(gr, &v, &x, &y, &z, &a, sch, sVal, opt);	}
+	/// Draw solid contours at manual levels along slice for 3d data
+	/** Style ‘#’ draw grid lines. Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly. */
+	inline void ContF3(const mglDataA &v, const mglDataA &a, const char *sch="", double sVal=-1, const char *opt="")
+	{	mgl_contf3_val(gr, &v, &a, sch, sVal, opt);	}
+	/// Draw solid contours along slice for 3d data specified parametrically
+	/** Style ‘#’ draw grid lines. Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.
+	 *  Option "value" set the number of contour levels (default is 7).*/
+	inline void ContF3(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const char *sch="", double sVal=-1, const char *opt="")
+	{	mgl_contf3_xyz(gr, &x, &y, &z, &a, sch, sVal, opt);	}
+	/// Draw solid contours along slice for 3d data
+	/** Style ‘#’ draw grid lines. Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.
+	 *  Option "value" set the number of contour levels (default is 7).*/
+	inline void ContF3(const mglDataA &a, const char *sch="", double sVal=-1, const char *opt="")
+	{	mgl_contf3(gr, &a, sch, sVal, opt);	}
+
+	/// Draw several isosurfaces for 3d beam in curvilinear coordinates
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.
+	 *  Variable \a flag is bitwise:
+	 * ‘0x1’ - draw in accompanied (not laboratory) coordinates;
+	 * ‘0x2’ - draw projection to \rho-z plane;
+	 * ‘0x4’ - draw normalized in each slice field.*/
+	inline void Beam(const mglDataA &tr, const mglDataA &g1, const mglDataA &g2, const mglDataA &a, double r, const char *stl=0, int flag=0, int num=3)
+	{	mgl_beam(gr, &tr,&g1,&g2,&a,r,stl,flag,num);	}
+	/// Draw isosurface at value \a val for 3d beam in curvilinear coordinates
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.
+	 *  Variable \a flag is bitwise:
+	 * ‘0x1’ - draw in accompanied (not laboratory) coordinates;
+	 * ‘0x2’ - draw projection to \rho-z plane;
+	 * ‘0x4’ - draw normalized in each slice field.*/
+	inline void Beam(double val, const mglDataA &tr, const mglDataA &g1, const mglDataA &g2, const mglDataA &a, double r, const char *stl=NULL, int flag=0)
+	{	mgl_beam_val(gr,val,&tr,&g1,&g2,&a,r,stl,flag);	}
+
+	/// Draw vertical tiles with variable size r and manual colors c for 2d data specified parametrically
+	inline void TileS(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &r, const mglDataA &c, const char *stl="", const char *opt="")
+	{	mgl_tiles_xyc(gr, &x, &y, &z, &r, &c, stl, opt);	}
+	/// Draw vertical tiles with variable size r for 2d data specified parametrically
+	inline void TileS(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &r, const char *stl="", const char *opt="")
+	{	mgl_tiles_xy(gr, &x, &y, &z, &r, stl, opt);	}
+	/// Draw vertical tiles with variable size r for 2d data
+	inline void TileS(const mglDataA &z, const mglDataA &r, const char *stl="", const char *opt="")
+	{	mgl_tiles(gr, &z, &r, stl, opt);	}
+
+	/// Draw surface for 2d data specified parametrically with color proportional to c
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void SurfC(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &c, const char *sch="", const char *opt="")
+	{	mgl_surfc_xy(gr, &x, &y, &z, &c, sch,opt);	}
+	/// Draw surface for 2d data with color proportional to c
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void SurfC(const mglDataA &z, const mglDataA &c, const char *sch="", const char *opt="")
+	{	mgl_surfc(gr, &z, &c, sch,opt);	}
+
+	/// Draw surface for 2d data specified parametrically with alpha proportional to c
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void SurfA(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &c, const char *sch="", const char *opt="")
+	{	mgl_surfa_xy(gr, &x, &y, &z, &c, sch,opt);	}
+	/// Draw surface for 2d data with alpha proportional to c
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void SurfA(const mglDataA &z, const mglDataA &c, const char *sch="", const char *opt="")
+	{	mgl_surfa(gr, &z, &c, sch,opt);	}
+
+	/// Draw surface for 2d data specified parametrically with color proportional to c and alpha proportional to a
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void SurfCA(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &c, const mglDataA &a, const char *sch="", const char *opt="")
+	{	mgl_surfca_xy(gr, &x, &y, &z, &c, &a, sch,opt);	}
+	/// Draw surface for 2d data with color proportional to c and alpha proportional to a
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void SurfCA(const mglDataA &z, const mglDataA &c, const mglDataA &a, const char *sch="", const char *opt="")
+	{	mgl_surfca(gr, &z, &c, &a, sch,opt);	}
+
+	/// Color map of matrix a to matrix b, both matrix can parametrically depend on coordinates
+	/** Style ‘.’ produce plot by dots. */
+	inline void Map(const mglDataA &x, const mglDataA &y, const mglDataA &a, const mglDataA &b, const char *sch="", const char *opt="")
+	{	mgl_map_xy(gr, &x, &y, &a, &b, sch, opt);	}
+	/// Color map of matrix a to matrix b
+	/** Style ‘.’ produce plot by dots. */
+	inline void Map(const mglDataA &a, const mglDataA &b, const char *sch="", const char *opt="")
+	{	mgl_map(gr, &a, &b, sch, opt);	}
+
+	/// Draw density plot for spectra-gramm specified parametrically
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void STFA(const mglDataA &x, const mglDataA &y, const mglDataA &re, const mglDataA &im, int dn, const char *sch="", const char *opt="")
+	{	mgl_stfa_xy(gr, &x, &y, &re, &im, dn, sch, opt);	}
+	/// Draw density plot for spectra-gramm
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void STFA(const mglDataA &re, const mglDataA &im, int dn, const char *sch="", const char *opt="")
+	{	mgl_stfa(gr, &re, &im, dn, sch, opt);	}
+
+	/// Draw isosurface for 3d data specified parametrically with alpha proportional to b
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots. */
+	inline void Surf3A(double Val, const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const mglDataA &b, const char *stl="", const char *opt="")
+	{	mgl_surf3a_xyz_val(gr, Val, &x, &y, &z, &a, &b, stl, opt);	}
+	/// Draw isosurface for 3d data with alpha proportional to b
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots. */
+	inline void Surf3A(double Val, const mglDataA &a, const mglDataA &b, const char *stl="", const char *opt="")
+	{	mgl_surf3a_val(gr, Val, &a, &b, stl, opt);	}
+	/// Draw isosurfaces for 3d data specified parametrically with alpha proportional to b
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+	 * Option "value" set the number of isosurfaces (default is 3). */
+	inline void Surf3A(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const mglDataA &b, const char *stl="", const char *opt="")
+	{	mgl_surf3a_xyz(gr, &x, &y, &z, &a, &b, stl, opt);	}
+	/// Draw isosurfaces for 3d data with alpha proportional to b
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+	 * Option "value" set the number of isosurfaces (default is 3). */
+	inline void Surf3A(const mglDataA &a, const mglDataA &b, const char *stl="", const char *opt="")
+	{	mgl_surf3a(gr, &a, &b, stl, opt);	}
+
+	/// Draw isosurface for 3d data specified parametrically with color proportional to c
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots. */
+	inline void Surf3C(double Val, const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const mglDataA &c, const char *stl="", const char *opt="")
+	{	mgl_surf3c_xyz_val(gr, Val, &x, &y, &z, &a, &c, stl,opt);	}
+	/// Draw isosurface for 3d data with color proportional to c
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots. */
+	inline void Surf3C(double Val, const mglDataA &a, const mglDataA &c, const char *stl="", const char *opt="")
+	{	mgl_surf3c_val(gr, Val, &a, &c, stl, opt);	}
+	/// Draw isosurfaces for 3d data specified parametrically with color proportional to c
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+	 * Option "value" set the number of isosurfaces (default is 3). */
+	inline void Surf3C(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const mglDataA &c, const char *stl="", const char *opt="")
+	{	mgl_surf3c_xyz(gr, &x, &y, &z, &a, &c, stl, opt);	}
+	/// Draw isosurfaces for 3d data specified parametrically with color proportional to c
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+	 * Option "value" set the number of isosurfaces (default is 3). */
+	inline void Surf3C(const mglDataA &a, const mglDataA &c, const char *stl="", const char *opt="")
+	{	mgl_surf3c(gr, &a, &c, stl, opt);	}
+
+	/// Draw isosurface for 3d data specified parametrically with color proportional to c and alpha proportional to b
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots. */
+	inline void Surf3CA(double Val, const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const mglDataA &c, const mglDataA &b, const char *stl="", const char *opt="")
+	{	mgl_surf3ca_xyz_val(gr, Val, &x, &y, &z, &a, &c, &b, stl,opt);	}
+	/// Draw isosurface for 3d data with color proportional to c and alpha proportional to b
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots. */
+	inline void Surf3CA(double Val, const mglDataA &a, const mglDataA &c, const mglDataA &b, const char *stl="", const char *opt="")
+	{	mgl_surf3ca_val(gr, Val, &a, &c, &b, stl, opt);	}
+	/// Draw isosurfaces for 3d data specified parametrically with color proportional to c and alpha proportional to b
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+	 * Option "value" set the number of isosurfaces (default is 3). */
+	inline void Surf3CA(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const mglDataA &c, const mglDataA &b, const char *stl="", const char *opt="")
+	{	mgl_surf3ca_xyz(gr, &x, &y, &z, &a, &c, &b, stl, opt);	}
+	/// Draw isosurfaces for 3d data with color proportional to c and alpha proportional to b
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+	 * Option "value" set the number of isosurfaces (default is 3). */
+	inline void Surf3CA(const mglDataA &a, const mglDataA &c, const mglDataA &b, const char *stl="", const char *opt="")
+	{	mgl_surf3ca(gr, &a, &c, &b, stl, opt);	}
+
+	/// Plot dew drops for vector field {ax,ay} parametrically depended on coordinate {x,y}
+	inline void Dew(const mglDataA &x, const mglDataA &y, const mglDataA &ax, const mglDataA &ay, const char *sch="", const char *opt="")
+	{	mgl_dew_xy(gr, &x, &y, &ax, &ay, sch, opt);	}
+	/// Plot dew drops for vector field {ax,ay}
+	inline void Dew(const mglDataA &ax, const mglDataA &ay, const char *sch="", const char *opt="")
+	{	mgl_dew_2d(gr, &ax, &ay, sch, opt);	}
+
+	/// Plot vectors at position {x,y} along {ax,ay} with length/color proportional to |a|
+	/** Option value set the vector length factor (if non-zero) or vector length to be proportional the distance between curve points (if value=0). */
+	inline void Traj(const mglDataA &x, const mglDataA &y, const mglDataA &ax, const mglDataA &ay, const char *sch="", const char *opt="")
+	{	mgl_traj_xy(gr, &x, &y, &ax, &ay, sch, opt);	}
+	/// Plot vectors at position {x,y,z} along {ax,ay,az} with length/color proportional to |a|
+	/** Option value set the vector length factor (if non-zero) or vector length to be proportional the distance between curve points (if value=0). */
+	inline void Traj(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &ax, const mglDataA &ay, const mglDataA &az, const char *sch="", const char *opt="")
+	{	mgl_traj_xyz(gr, &x, &y, &z, &ax, &ay, &az, sch, opt);	}
+
+	/// Plot vector field {ax,ay} parametrically depended on coordinate {x,y} with length/color proportional to |a|
+	/** String \a sch may contain:
+	 * ‘f’ for drawing arrows with fixed lengths,
+	 * ‘ >’, ‘<’ for drawing arrows to or from the ce*ll point (default is centering),
+	 * ‘.’ for drawing hachures with dots instead of arrows,
+	 * ‘=’ for enabling color gradient along arrows. */
+	inline void Vect(const mglDataA &x, const mglDataA &y, const mglDataA &ax, const mglDataA &ay, const char *sch="", const char *opt="")
+	{	mgl_vect_xy(gr, &x, &y, &ax, &ay, sch, opt);	}
+	/// Plot vector field {ax,ay} with length/color proportional to |a|
+	/** String \a sch may contain:
+	 * ‘f’ for drawing arrows with fixed lengths,
+	 * ‘ >’, ‘<’ for drawing arrows to or from the ce*ll point (default is centering),
+	 * ‘.’ for drawing hachures with dots instead of arrows,
+	 * ‘=’ for enabling color gradient along arrows. */
+	inline void Vect(const mglDataA &ax, const mglDataA &ay, const char *sch="", const char *opt="")
+	{	mgl_vect_2d(gr, &ax, &ay, sch, opt);	}
+	/// Plot vector field {ax,ay,az} parametrically depended on coordinate {x,y,z} with length/color proportional to |a|
+	/** String \a sch may contain:
+	 * ‘f’ for drawing arrows with fixed lengths,
+	 * ‘ >’, ‘<’ for drawing arrows to or from the ce*ll point (default is centering),
+	 * ‘.’ for drawing hachures with dots instead of arrows,
+	 * ‘=’ for enabling color gradient along arrows. */
+	inline void Vect(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &ax, const mglDataA &ay, const mglDataA &az, const char *sch="", const char *opt="")
+	{	mgl_vect_xyz(gr, &x, &y, &z, &ax, &ay, &az, sch, opt);	}
+	/// Plot vector field {ax,ay,az} with length/color proportional to |a|
+	/** String \a sch may contain:
+	 * ‘f’ for drawing arrows with fixed lengths,
+	 * ‘ >’, ‘<’ for drawing arrows to or from the ce*ll point (default is centering),
+	 * ‘.’ for drawing hachures with dots instead of arrows,
+	 * ‘=’ for enabling color gradient along arrows. */
+	inline void Vect(const mglDataA &ax, const mglDataA &ay, const mglDataA &az, const char *sch="", const char *opt="")
+	{	mgl_vect_3d(gr, &ax, &ay, &az, sch, opt);	}
+
+	/// Draw vector plot along slice for 3d data specified parametrically
+	/** String \a sch may contain:
+	 * ‘f’ for drawing arrows with fixed lengths,
+	 * ‘ >’, ‘<’ for drawing arrows to or from the ce*ll point (default is centering),
+	 * ‘.’ for drawing hachures with dots instead of arrows,
+	 * ‘=’ for enabling color gradient along arrows,
+	 * ‘ x’, ‘z’ for producing plot perpendicular to x- or z-direction correspondingly. */
+	inline void Vect3(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &ax, const mglDataA &ay, const mglDataA &az, const char *stl="", double sVal=-1, const char *opt="")
+	{	mgl_vect3_xyz(gr, &x, &y, &z, &ax,&ay,&az, stl, sVal, opt);	}
+	/// Draw vector plot along slice for 3d data
+	/** String \a sch may contain:
+	 * ‘f’ for drawing arrows with fixed lengths,
+	 * ‘ >’, ‘<’ for drawing arrows to or from the ce*ll point (default is centering),
+	 * ‘.’ for drawing hachures with dots instead of arrows,
+	 * ‘=’ for enabling color gradient along arrows,
+	 * ‘ x’, ‘z’ for producing plot perpendicular to x- or z-direction correspondingly. */
+	inline void Vect3(const mglDataA &ax, const mglDataA &ay, const mglDataA &az, const char *stl="", double sVal=-1, const char *opt="")
+	{	mgl_vect3(gr, &ax,&ay,&az, stl, sVal, opt);	}
+
+	/// Plot flows for vector field {ax,ay} parametrically depended on coordinate {x,y} with color proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+	 * Option "value" sets the number of threads (default is 5). */
+	inline void Flow(const mglDataA &x, const mglDataA &y, const mglDataA &ax, const mglDataA &ay, const char *sch="", const char *opt="")
+	{	mgl_flow_xy(gr, &x, &y, &ax, &ay, sch, opt);	}
+	/// Plot flows for vector field {ax,ay} with color proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+	 * Option "value" sets the number of threads (default is 5). */
+	inline void Flow(const mglDataA &ax, const mglDataA &ay, const char *sch="", const char *opt="")
+	{	mgl_flow_2d(gr, &ax, &ay, sch, opt);	}
+	/// Plot flows for vector field {ax,ay,az} parametrically depended on coordinate {x,y,z} with color proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+	 * Option "value" sets the number of threads (default is 5). */
+	inline void Flow(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &ax, const mglDataA &ay, const mglDataA &az, const char *sch="", const char *opt="")
+	{	mgl_flow_xyz(gr, &x, &y, &z, &ax, &ay, &az, sch, opt);	}
+	/// Plot flows for vector field {ax,ay,az} with color proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+	 * Option "value" sets the number of threads (default is 5). */
+	inline void Flow(const mglDataA &ax, const mglDataA &ay, const mglDataA &az, const char *sch="", const char *opt="")
+	{	mgl_flow_3d(gr, &ax, &ay, &az, sch, opt);	}
+
+	/// Plot flow from point p for vector field {ax,ay} parametrically depended on coordinate {x,y} with color proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads. */
+	inline void FlowP(mglPoint p, const mglDataA &x, const mglDataA &y, const mglDataA &ax, const mglDataA &ay, const char *sch="", const char *opt="")
+	{	mgl_flowp_xy(gr, p.x, p.y, p.z, &x, &y, &ax, &ay, sch, opt);	}
+	/// Plot flow from point p for vector field {ax,ay} with color proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads. */
+	inline void FlowP(mglPoint p, const mglDataA &ax, const mglDataA &ay, const char *sch="", const char *opt="")
+	{	mgl_flowp_2d(gr, p.x, p.y, p.z, &ax, &ay, sch, opt);	}
+	/// Plot flow from point p for vector field {ax,ay,az} parametrically depended on coordinate {x,y,z} with color proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly. */
+	inline void FlowP(mglPoint p, const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &ax, const mglDataA &ay, const mglDataA &az, const char *sch="", const char *opt="")
+	{	mgl_flowp_xyz(gr, p.x, p.y, p.z, &x, &y, &z, &ax, &ay, &az, sch, opt);	}
+	/// Plot flow from point p for vector field {ax,ay,az} with color proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly. */
+	inline void FlowP(mglPoint p, const mglDataA &ax, const mglDataA &ay, const mglDataA &az, const char *sch="", const char *opt="")
+	{	mgl_flowp_3d(gr, p.x, p.y, p.z, &ax, &ay, &az, sch, opt);	}
+
+	/// Plot flows for gradient of scalar field phi parametrically depended on coordinate {x,y,z}
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+	 * Option "value" sets the number of threads (default is 5). */
+	inline void Grad(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &phi, const char *sch="", const char *opt="")
+	{	mgl_grad_xyz(gr,&x,&y,&z,&phi,sch,opt);	}
+	/// Plot flows for gradient of scalar field phi parametrically depended on coordinate {x,y}
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+	 * Option "value" sets the number of threads (default is 5). */
+	inline void Grad(const mglDataA &x, const mglDataA &y, const mglDataA &phi, const char *sch="", const char *opt="")
+	{	mgl_grad_xy(gr,&x,&y,&phi,sch,opt);	}
+	/// Plot flows for gradient of scalar field phi
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+	 * Option "value" sets the number of threads (default is 5). */
+	inline void Grad(const mglDataA &phi, const char *sch="", const char *opt="")
+	{	mgl_grad(gr,&phi,sch,opt);	}
+
+	/// Plot flow pipes for vector field {ax,ay} parametrically depended on coordinate {x,y} with color and radius proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘i’ for pipe radius to be inverse proportional to amplitude.
+	 * Option "value" sets the number of threads (default is 5). */
+	inline void Pipe(const mglDataA &x, const mglDataA &y, const mglDataA &ax, const mglDataA &ay, const char *sch="", double r0=0.05, const char *opt="")
+	{	mgl_pipe_xy(gr, &x, &y, &ax, &ay, sch, r0, opt);	}
+	/// Plot flow pipes for vector field {ax,ay} with color and radius proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘i’ for pipe radius to be inverse proportional to amplitude.
+	 * Option "value" sets the number of threads (default is 5). */
+	inline void Pipe(const mglDataA &ax, const mglDataA &ay, const char *sch="", double r0=0.05, const char *opt="")
+	{	mgl_pipe_2d(gr, &ax, &ay, sch, r0, opt);	}
+	/// Plot flow pipes for vector field {ax,ay,az} parametrically depended on coordinate {x,y,z} with color and radius proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘i’ for pipe radius to be inverse proportional to amplitude;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+	 * Option "value" sets the number of threads (default is 5). */
+	inline void Pipe(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &ax, const mglDataA &ay, const mglDataA &az, const char *sch="", double r0=0.05, const char *opt="")
+	{	mgl_pipe_xyz(gr, &x, &y, &z, &ax, &ay, &az, sch, r0, opt);	}
+	/// Plot flow pipes for vector field {ax,ay,az} with color and radius proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘i’ for pipe radius to be inverse proportional to amplitude;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+	 * Option "value" sets the number of threads (default is 5). */
+	inline void Pipe(const mglDataA &ax, const mglDataA &ay, const mglDataA &az, const char *sch="", double r0=0.05, const char *opt="")
+	{	mgl_pipe_3d(gr, &ax, &ay, &az, sch, r0, opt);	}
+
+	/// Draw density plot for data at x = sVal
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void DensX(const mglDataA &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_dens_x(gr, &a, stl, sVal, opt);	}
+	/// Draw density plot for data at y = sVal
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void DensY(const mglDataA &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_dens_y(gr, &a, stl, sVal, opt);	}
+	/// Draw density plot for data at z = sVal
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void DensZ(const mglDataA &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_dens_z(gr, &a, stl, sVal, opt);	}
+
+	/// Draw contour lines for data at x = sVal
+	/** Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void ContX(const mglDataA &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_cont_x(gr, &a, stl, sVal, opt);	}
+	/// Draw contour lines at manual levels for data at x = sVal
+	/** Style ‘t’/‘T’ draw contour labels below/above contours. */
+	inline void ContX(const mglDataA &v, const mglDataA &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_cont_x_val(gr, &v, &a, stl, sVal, opt);	}
+	/// Draw contour lines for data at y = sVal
+	/** Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void ContY(const mglDataA &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_cont_y(gr, &a, stl, sVal, opt);	}
+	/// Draw contour lines at manual levels for data at y = sVal
+	/** Style ‘t’/‘T’ draw contour labels below/above contours. */
+	inline void ContY(const mglDataA &v, const mglDataA &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_cont_y_val(gr, &v, &a, stl, sVal, opt);	}
+	/// Draw contour lines for data at z = sVal
+	/** Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void ContZ(const mglDataA &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_cont_z(gr, &a, stl, sVal, opt);	}
+	/// Draw contour lines at manual levels for data at z = sVal
+	/** Style ‘t’/‘T’ draw contour labels below/above contours. */
+	inline void ContZ(const mglDataA &v, const mglDataA &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_cont_z_val(gr, &v, &a, stl, sVal, opt);	}
+
+	/// Draw solid contours for data at x = sVal
+	/** Option "value" set the number of contour levels (default is 7). */
+	inline void ContFX(const mglDataA &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_contf_x(gr, &a, stl, sVal, opt);	}
+	/// Draw solid contours at manual levels for data at x = sVal
+	inline void ContFX(const mglDataA &v, const mglDataA &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_contf_x_val(gr, &v, &a, stl, sVal, opt);	}
+	/// Draw solid contours for data at y = sVal
+	/** Option "value" set the number of contour levels (default is 7). */
+	inline void ContFY(const mglDataA &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_contf_y(gr, &a, stl, sVal, opt);	}
+	/// Draw solid contours at manual levels for data at y = sVal
+	inline void ContFY(const mglDataA &v, const mglDataA &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_contf_y_val(gr, &v, &a, stl, sVal, opt);	}
+	/// Draw solid contours for data at z = sVal
+	/** Option "value" set the number of contour levels (default is 7). */
+	inline void ContFZ(const mglDataA &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_contf_z(gr, &a, stl, sVal, opt);	}
+	/// Draw solid contours at manual levels for data at z = sVal
+	inline void ContFZ(const mglDataA &v, const mglDataA &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_contf_z_val(gr, &v, &a, stl, sVal, opt);	}
+
+	/// Draw curve for formula with x in x-axis range
+	/** Option "value" set initial number of points. */
+	inline void FPlot(const char *fy, const char *stl="", const char *opt="")
+	{	mgl_fplot(gr, fy, stl, opt);	}
+	/// Draw curve for formulas parametrically depended on t in range [0,1]
+	/** Option "value" set initial number of points. */
+	inline void FPlot(const char *fx, const char *fy, const char *fz, const char *stl, const char *opt="")
+	{	mgl_fplot_xyz(gr, fx, fy, fz, stl, opt);	}
+	/// Draw surface by formula with x,y in axis range
+	/** Option "value" set initial number of points. */
+	inline void FSurf(const char *fz, const char *stl="", const char *opt="")
+	{	mgl_fsurf(gr, fz, stl, opt);	}
+	/// Draw surface by formulas parametrically depended on u,v in range [0,1]
+	/** Option "value" set initial number of points. */
+	inline void FSurf(const char *fx, const char *fy, const char *fz, const char *stl, const char *opt="")
+	{	mgl_fsurf_xyz(gr, fx, fy, fz, stl, opt);	}
+
+	/// Draw triangle mesh for points in arrays {x,y,z} with specified color c.
+	/** Style ‘#’ produce wire plot. If id.ny=c.nx then c set the triangle colors, else vertex colors. */
+	inline void TriPlot(const mglDataA &nums, const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &c, const char *sch="", const char *opt="")
+	{	mgl_triplot_xyzc(gr, &nums, &x, &y, &z, &c, sch, opt);	}
+	/// Draw triangle mesh for points in arrays {x,y,z}
+	/** Style ‘#’ produce wire plot. */
+	inline void TriPlot(const mglDataA &nums, const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_triplot_xyz(gr, &nums, &x, &y, &z, sch, opt);	}
+	/// Draw triangle mesh for points in arrays {x,y}
+	/** Style ‘#’ produce wire plot. */
+	inline void TriPlot(const mglDataA &nums, const mglDataA &x, const mglDataA &y, const char *sch="", const char *opt="")
+	{	mgl_triplot_xy(gr, &nums, &x, &y, sch, opt);	}
+
+	/// Draw quad mesh for points in arrays {x,y,z} with specified color c
+	/** Style ‘#’ produce wire plot. If id.ny=c.nx then c set the quadrangle colors, else vertex colors. */
+	inline void QuadPlot(const mglDataA &nums, const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &c, const char *sch="", const char *opt="")
+	{	mgl_quadplot_xyzc(gr, &nums, &x, &y, &z, &c, sch, opt);	}
+	/// Draw quad mesh for points in arrays {x,y,z}
+	/** Style ‘#’ produce wire plot. */
+	inline void QuadPlot(const mglDataA &nums, const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_quadplot_xyz(gr, &nums, &x, &y, &z, sch, opt);	}
+	/// Draw quad mesh for points in arrays {x,y}
+	/** Style ‘#’ produce wire plot. */
+	inline void QuadPlot(const mglDataA &nums, const mglDataA &x, const mglDataA &y, const char *sch="", const char *opt="")
+	{	mgl_quadplot_xy(gr, &nums, &x, &y, sch, opt);	}
+
+	/// Draw contour lines for triangle mesh for points in arrays {x,y,z}
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * If id.ny=c.nx then c set the quadrangle colors, else vertex colors. */
+	inline void TriCont(const mglDataA &nums, const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_tricont_xyc(gr, &nums, &x, &y, &z, sch, opt);	}
+	/// Draw contour lines for triangle mesh for points in arrays {x,y,z}
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * If id.ny=c.nx then c set the quadrangle colors, else vertex colors.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void TriContV(const mglDataA &v, const mglDataA &nums, const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_tricont_xycv(gr, &v, &nums, &x, &y, &z, sch, opt);	}
+	/// Draw contour lines for triangle mesh for points in arrays {x,y,z} with specified color c.
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * If id.ny=c.nx then c set the quadrangle colors, else vertex colors. */
+	inline void TriCont(const mglDataA &nums, const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const char *sch="", const char *opt="")
+	{	mgl_tricont_xyzc(gr, &nums, &x, &y, &z, &a, sch, opt);	}
+	/// Draw contour lines for triangle mesh for points in arrays {x,y,z} with specified color c.
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * If id.ny=c.nx then c set the quadrangle colors, else vertex colors. */
+	inline void TriContV(const mglDataA &v, const mglDataA &nums, const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const char *sch="", const char *opt="")
+	{	mgl_tricont_xyzcv(gr, &v, &nums, &x, &y, &z, &a, sch, opt);	}
+	/// Draw contour lines for triangle mesh for points in arrays {x,y,z} with specified color c.
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * If id.ny=c.nx then c set the quadrangle colors, else vertex colors. */
+	inline void TriCont(const mglDataA &v, const mglDataA &nums, const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const char *sch="", const char *opt="")
+	{	mgl_tricont_xyzcv(gr, &v, &nums, &x, &y, &z, &a, sch, opt);	}
+
+	/// Draw contour tubes for triangle mesh for points in arrays {x,y,z}
+	/** Option "value" set the number of contour levels (default is 7). */
+	inline void TriContVt(const mglDataA &nums, const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_tricontv_xyc(gr, &nums, &x, &y, &z, sch, opt);	}
+	/// Draw contour tubes for triangle mesh for points in arrays {x,y,z} with specified color c
+	/** Option "value" set the number of contour levels (default is 7). */
+	inline void TriContVt(const mglDataA &nums, const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const char *sch="", const char *opt="")
+	{	mgl_tricontv_xyzc(gr, &nums, &x, &y, &z, &a, sch, opt);	}
+	/// Draw contour tubes for triangle mesh for points in arrays {x,y,z} with specified color c
+	/** If id.ny=c.nx then c set the quadrangle colors, else vertex colors. */
+	inline void TriContVt(const mglDataA &v, const mglDataA &nums, const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const char *sch="", const char *opt="")
+	{	mgl_tricontv_xyzcv(gr, &v, &nums, &x, &y, &z, &a, sch, opt);	}
+
+	/// Draw dots in points {x,y,z}.
+	inline void Dots(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_dots(gr, &x, &y, &z, sch, opt);	}
+	/// Draw semitransparent dots in points {x,y,z} with specified alpha a.
+	inline void Dots(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const char *sch="", const char *opt="")
+	{	mgl_dots_a(gr, &x, &y, &z, &a, sch, opt);	}
+	/// Draw semitransparent dots in points {x,y,z} with specified color c and alpha a.
+	inline void Dots(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &c, const mglDataA &a, const char *sch="", const char *opt="")
+	{	mgl_dots_ca(gr, &x, &y, &z, &c, &a, sch, opt);	}
+	/// Draw surface reconstructed for points in arrays {x,y,z}.
+	/** Style ‘#’ produce wired plot. */
+	inline void Crust(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *sch="", const char *opt="")
+	{	mgl_crust(gr, &x, &y, &z, sch, opt);	}
+
+	/// Fit data along x-direction for each data row. Return array with values for found formula.
+	inline mglData Fit(const mglDataA &y, const char *eq, const char *vars, const char *opt="")
+	{	return mglData(true,mgl_fit_1(gr, &y, eq,vars,0, opt));	}
+	/// Fit data along x-direction for each data row starting from \a ini values. Return array with values for found formula.
+	inline mglData Fit(const mglDataA &y, const char *eq, const char *vars, mglData &ini, const char *opt="")
+	{	return mglData(true,mgl_fit_1(gr, &y, eq, vars, &ini, opt));	}
+	/// Fit data along x-, y-directions for each data slice. Return array with values for found formula.
+	inline mglData Fit2(const mglDataA &z, const char *eq, const char *vars, const char *opt="")
+	{	return mglData(true,mgl_fit_2(gr, &z, eq, vars,0, opt));	}
+	/// Fit data along x-, y-direction for each data slice starting from \a ini values. Return array with values for found formula.
+	inline mglData Fit2(const mglDataA &z, const char *eq, const char *vars, mglData &ini, const char *opt="")
+	{	return mglData(true,mgl_fit_2(gr, &z, eq, vars, &ini, opt));	}
+	/// Fit data along along all directions. Return array with values for found formula.
+	inline mglData Fit3(const mglDataA &a, const char *eq, const char *vars, const char *opt="")
+	{	return mglData(true,mgl_fit_3(gr, &a, eq, vars,0, opt));	}
+	/// Fit data along all directions starting from \a ini values. Return array with values for found formula.
+	inline mglData Fit3(const mglDataA &a, const char *eq, const char *vars, mglData &ini, const char *opt="")
+	{	return mglData(true,mgl_fit_3(gr, &a, eq, vars, &ini, opt));	}
+
+	/// Fit data along x-direction for each data row. Return array with values for found formula.
+	inline mglData Fit(const mglDataA &x, const mglDataA &y, const char *eq, const char *vars, const char *opt="")
+	{	return mglData(true,mgl_fit_xy(gr, &x, &y, eq, vars,0, opt));	}
+	/// Fit data along x-direction for each data row starting from \a ini values. Return array with values for found formula.
+	inline mglData Fit(const mglDataA &x, const mglDataA &y, const char *eq, const char *vars, mglData &ini, const char *opt="")
+	{	return mglData(true,mgl_fit_xy(gr, &x, &y, eq, vars, &ini, opt));	}
+	/// Fit data along x-, y-directions for each data slice. Return array with values for found formula.
+	inline mglData Fit(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *eq, const char *vars, const char *opt="")
+	{	return mglData(true,mgl_fit_xyz(gr, &x, &y, &z, eq, vars,0, opt));	}
+	/// Fit data along x-, y-directions for each data slice starting from \a ini values. Return array with values for found formula.
+	inline mglData Fit(const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *eq, const char *vars, mglData &ini, const char *opt="")
+	{	return mglData(true,mgl_fit_xyz(gr, &x, &y, &z, eq, vars, &ini, opt));	}
+	/// Fit data along along all directions. Return array with values for found formula.
+	inline mglData Fit(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const char *eq, const char *vars, const char *opt="")
+	{	return mglData(true,mgl_fit_xyza(gr, &x, &y, &z, &a, eq, vars,0, opt));	}
+	/// Fit data along along all directions starting from \a ini values. Return array with values for found formula.
+	inline mglData Fit(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const char *eq, const char *vars, mglData &ini, const char *opt="")
+	{	return mglData(true,mgl_fit_xyza(gr, &x, &y, &z, &a, eq,vars, &ini, opt));	}
+
+	/// Fit data with dispersion s along x-direction for each data row. Return array with values for found formula.
+	inline mglData FitS(const mglDataA &y, const mglDataA &s, const char *eq, const char *vars, const char *opt="")
+	{	return mglData(true,mgl_fit_ys(gr, &y, &s, eq, vars,0, opt));	}
+	/// Fit data with dispersion s along x-direction for each data row starting from \a ini values. Return array with values for found formula.
+	inline mglData FitS(const mglDataA &y, const mglDataA &s, const char *eq, const char *vars, mglData &ini, const char *opt="")
+	{	return mglData(true,mgl_fit_ys(gr, &y, &s, eq, vars, &ini, opt));	}
+	/// Fit data with dispersion s along x-direction for each data row. Return array with values for found formula.
+	inline mglData FitS(const mglDataA &x, const mglDataA &y, const mglDataA &s, const char *eq, const char *vars, const char *opt="")
+	{	return mglData(true,mgl_fit_xys(gr, &x, &y, &s, eq, vars,0, opt));	}
+	/// Fit data with dispersion s along x-direction for each data row starting from \a ini values. Return array with values for found formula.
+	inline mglData FitS(const mglDataA &x, const mglDataA &y, const mglDataA &s, const char *eq, const char *vars, mglData &ini, const char *opt="")
+	{	return mglData(true,mgl_fit_xys(gr, &x, &y, &s, eq, vars, &ini, opt));	}
+	/// Fit data with dispersion s along x-, y-directions for each data slice. Return array with values for found formula.
+	inline mglData FitS(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &s, const char *eq, const char *vars, const char *opt="")
+	{	return mglData(true,mgl_fit_xyzs(gr, &x, &y, &z, &s, eq, vars,0, opt));	}
+	/// Fit data with dispersion s along x-, y-directions for each data slice starting from \a ini values. Return array with values for found formula.
+	inline mglData FitS(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &s, const char *eq, const char *vars, mglData &ini, const char *opt="")
+	{	return mglData(true,mgl_fit_xyzs(gr, &x, &y, &z, &s, eq, vars, &ini, opt));	}
+	/// Fit data with dispersion s along all directions. Return array with values for found formula.
+	inline mglData FitS(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const mglDataA &s, const char *eq, const char *vars, const char *opt="")
+	{	return mglData(true,mgl_fit_xyzas(gr, &x, &y, &z, &a, &s, eq, vars,0, opt));	}
+	/// Fit data with dispersion s along all directions starting from \a ini values. Return array with values for found formula.
+	inline mglData FitS(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const mglDataA &s, const char *eq, const char *vars, mglData &ini, const char *opt="")
+	{	return mglData(true,mgl_fit_xyzas(gr, &x, &y, &z, &a, &s, eq, vars, &ini, opt));	}
+
+	/// Print fitted last formula (with coefficients)
+	inline void PutsFit(mglPoint p, const char *prefix=0, const char *font="", double size=-1)
+	{	mgl_puts_fit(gr, p.x, p.y, p.z, prefix, font, size);	}
+	/// Get last fitted formula
+	inline const char *GetFit()	const
+	{	return mgl_get_fit(gr);	}
+	/// Get chi for last fitted formula
+	static inline mreal GetFitChi()
+	{	return mgl_get_fit_chi();	}
+	/// Get covariance matrix for last fitted formula
+	static inline mglData GetFitCovar()
+	{	return mglData(mgl_get_fit_covar());	}
+
+	/// Solve PDE with x,y,z in range axis range
+	inline mglData PDE(const char *ham, const mglDataA &ini_re, const mglDataA &ini_im, double dz=0.1, double k0=100, const char *opt="")
+	{	return mglData(true,mgl_pde_solve(gr,ham,&ini_re,&ini_im,dz,k0, opt));	}
+	/// Solve PDE with x,y,z in range axis range
+	inline mglDataC PDEc(const char *ham, const mglDataA &ini_re, const mglDataA &ini_im, double dz=0.1, double k0=100, const char *opt="")
+	{	return mglDataC(true,mgl_pde_solve_c(gr,ham,&ini_re,&ini_im,dz,k0, opt));	}
+
+	/// Solve PDE with x,y,z in range axis range using advanced (slow!!!) method (2d only)
+	inline mglData APDE(const char *ham, const mglDataA &ini_re, const mglDataA &ini_im, double dz=0.1, double k0=100, const char *opt="")
+	{	return mglData(true,mgl_pde_adv(gr,ham,&ini_re,&ini_im,dz,k0, opt));	}
+	/// Solve PDE with x,y,z in range axis range using advanced (slow!!!) method (2d only)
+	inline mglDataC APDEc(const char *ham, const mglDataA &ini_re, const mglDataA &ini_im, double dz=0.1, double k0=100, const char *opt="")
+	{	return mglDataC(true,mgl_pde_adv_c(gr,ham,&ini_re,&ini_im,dz,k0, opt));	}
+
+	/// Fill data by formula with x,y,z in range axis range
+	inline void Fill(mglData &u, const char *eq, const char *opt="")
+	{	mgl_data_fill_eq(gr, &u, eq, 0, 0, opt);	}
+	inline void Fill(mglData &u, const char *eq, const mglDataA &v, const char *opt="")
+	{	mgl_data_fill_eq(gr, &u, eq, &v, 0, opt);	}
+	inline void Fill(mglData &u, const char *eq, const mglDataA &v, const mglDataA &w, const char *opt="")
+	{	mgl_data_fill_eq(gr, &u, eq, &v, &w, opt);	}
+	/// Fill data by formula with x,y,z in range axis range
+	inline void Fill(mglDataC &u, const char *eq, const char *opt="")
+	{	mgl_datac_fill_eq(gr, &u, eq, 0, 0, opt);	}
+	inline void Fill(mglDataC &u, const char *eq, const mglDataA &v, const char *opt="")
+	{	mgl_datac_fill_eq(gr, &u, eq, &v, 0, opt);	}
+	inline void Fill(mglDataC &u, const char *eq, const mglDataA &v, const mglDataA &w, const char *opt="")
+	{	mgl_datac_fill_eq(gr, &u, eq, &v, &w, opt);	}
+
+	/// Fill dat by interpolated values of vdat parametrically depended on xdat for x in axis range
+	inline void Refill(mglData &dat, const mglDataA &xdat, const mglDataA &vdat, long sl=-1, const char *opt="")
+	{	mgl_data_refill_gr(gr,&dat,&xdat,0,0,&vdat,sl,opt);	}
+	/// Fill dat by interpolated values of vdat parametrically depended on xdat,ydat for x,y in axis range
+	inline void Refill(mglData &dat, const mglDataA &xdat, const mglDataA &ydat, const mglDataA &vdat, long sl=-1, const char *opt="")
+	{	mgl_data_refill_gr(gr,&dat,&xdat,&ydat,0,&vdat,sl,opt);	}
+	/// Fill dat by interpolated values of vdat parametrically depended on xdat,ydat,zdat for x,y,z in axis range
+	inline void Refill(mglData &dat, const mglDataA &xdat, const mglDataA &ydat, const mglDataA &zdat, const mglDataA &vdat, const char *opt="")
+	{	mgl_data_refill_gr(gr,&dat,&xdat,&ydat,&zdat,&vdat,-1,opt);	}
+
+	/// Fill dat by interpolated values of vdat parametrically depended on xdat for x in axis range
+	inline void Refill(mglDataC &dat, const mglDataA &xdat, const mglDataA &vdat, long sl=-1, const char *opt="")
+	{	mgl_datac_refill_gr(gr,&dat,&xdat,0,0,&vdat,sl,opt);	}
+	/// Fill dat by interpolated values of vdat parametrically depended on xdat,ydat for x,y in axis range
+	inline void Refill(mglDataC &dat, const mglDataA &xdat, const mglDataA &ydat, const mglDataA &vdat, long sl=-1, const char *opt="")
+	{	mgl_datac_refill_gr(gr,&dat,&xdat,&ydat,0,&vdat,sl,opt);	}
+	/// Fill dat by interpolated values of vdat parametrically depended on xdat,ydat,zdat for x,y,z in axis range
+	inline void Refill(mglDataC &dat, const mglDataA &xdat, const mglDataA &ydat, const mglDataA &zdat, const mglDataA &vdat, const char *opt="")
+	{	mgl_datac_refill_gr(gr,&dat,&xdat,&ydat,&zdat,&vdat,-1,opt);	}
+
+	/// Set the data by triangulated surface values assuming x,y,z in range axis range
+	inline void DataGrid(mglData &d, const mglDataA &x, const mglDataA &y, const mglDataA &z, const char *opt="")
+	{	mgl_data_grid(gr,&d,&x,&y,&z,opt);	}
+
+	/// Make histogram (distribution) of data. This function do not plot data.
+	/** Option "value" sets the size of output array (default is mglFitPnts=100). */
+	inline mglData Hist(const mglDataA &x, const mglDataA &a, const char *opt="")
+	{	return mglData(true, mgl_hist_x(gr, &x, &a, opt));	}
+	/// Make histogram (distribution) of data. This function do not plot data.
+	/** Option "value" sets the size of output array (default is mglFitPnts=100). */
+	inline mglData Hist(const mglDataA &x, const mglDataA &y, const mglDataA &a, const char *opt="")
+	{	return mglData(true, mgl_hist_xy(gr, &x, &y, &a, opt));	}
+	/// Make histogram (distribution) of data. This function do not plot data.
+	/** Option "value" sets the size of output array (default is mglFitPnts=100). */
+	inline mglData Hist(const mglDataA &x, const mglDataA &y, const mglDataA &z, const mglDataA &a, const char *opt="")
+	{	return mglData(true, mgl_hist_xyz(gr, &x, &y, &z, &a, opt));	}
+
+	inline void Compression(bool){}		// NOTE: Add later -- IDTF
+	/// Set the preference for vertex color on/off (for formats that support it, now only PRC does).
+	inline void VertexColor(bool enable)	{	mgl_set_flag(gr,enable, MGL_PREFERVC);	}
+	/// Render only front side of surfaces for dubugging purposes (for formats that support it, now only PRC does).
+	inline void DoubleSided(bool enable)	{	mgl_set_flag(gr,!enable, MGL_ONESIDED);	}
+//	inline void TextureColor(bool){}	// NOTE: Add later -- IDTF
+};
+//-----------------------------------------------------------------------------
+/// Wrapper class for MGL parsing
+class MGL_EXPORT mglParse
+{
+	HMPR pr;
+	mglParse &operator=(mglParse &p)
+	{	pr = p.pr;	mgl_use_parser(pr,1);	return p;	}
+public:
+	mglParse(HMPR p)		{	pr = p;		mgl_use_parser(pr,1);	}
+	mglParse(mglParse &p)	{	pr = p.pr;	mgl_use_parser(pr,1);	}
+	mglParse(bool setsize=false)
+	{	pr=mgl_create_parser();	mgl_parser_allow_setsize(pr, setsize);	}
+	virtual ~mglParse()
+	{
+#pragma omp critical
+		if(mgl_use_parser(pr,-1)<1)	mgl_delete_parser(pr);
+	}
+	/// Get pointer to internal mglParser object
+	inline HMPR Self()	{	return pr;	}
+	/// Parse and draw single line of the MGL script
+	inline int Parse(mglGraph *gr, const char *str, int pos)
+	{	return mgl_parse_line(gr->Self(), pr, str, pos);	}
+	inline int Parse(mglGraph *gr, const wchar_t *str, int pos)
+	{	return mgl_parse_linew(gr->Self(), pr, str, pos);	}
+	/// Execute MGL script text with '\n' separated lines
+	inline void Execute(mglGraph *gr, const char *str)
+	{	mgl_parse_text(gr->Self(), pr, str);	}
+	inline void Execute(mglGraph *gr, const wchar_t *str)
+	{	mgl_parse_textw(gr->Self(), pr, str);	}
+	/// Execute and draw script from the file
+	inline void Execute(mglGraph *gr, FILE *fp, bool print=false)
+	{	mgl_parse_file(gr->Self(), pr, fp, print);	}
+
+	/// Return type of command: 0 - not found, 1 - other data plot, 2 - func plot,
+	///		3 - setup, 4 - data handle, 5 - data create, 6 - subplot, 7 - program
+	///		8 - 1d plot, 9 - 2d plot, 10 - 3d plot, 11 - dd plot, 12 - vector plot
+	///		13 - axis, 14 - primitives, 15 - axis setup, 16 - text/legend, 17 - data transform
+	inline int CmdType(const char *name)
+	{	return mgl_parser_cmd_type(pr, name);	}
+	/// Return string of command format (command name and its argument[s])
+	inline const char *CmdFormat(const char *name)
+	{	return mgl_parser_cmd_frmt(pr, name);	}
+	/// Return description of MGL command
+	inline const char *CmdDesc(const char *name)
+	{	return mgl_parser_cmd_desc(pr, name);	}
+	/// Get name of command with number n
+	inline const char *GetCmdName(long n)
+	{	return mgl_parser_cmd_name(pr,n);	}
+	/// Get number of defined commands
+	inline long GetCmdNum()
+	{	return mgl_parser_cmd_num(pr);	}
+	/// Load new commands from external dynamic Library (must have "const mglCommand *mgl_cmd_extra" variable)
+	inline void LoadDLL(const char *fname)
+	{	mgl_parser_load(pr, fname);	}
+	/// Apply one step for equation d vars[i]/dt = eqs[i] using Runge-Kutta method
+	inline void RK_Step(const char *eqs, const char *vars, mreal dt=1)
+	{	mgl_rk_step(pr, eqs, vars, dt);	}
+	inline void RK_Step(const wchar_t *eqs, const wchar_t *vars, mreal dt=1)
+	{	mgl_rk_step_w(pr, eqs, vars, dt);	}
+	// Open all data arrays from HDF file and assign it as variables of parser p
+	inline void OpenHDF(const char *fname)
+	{	mgl_parser_openhdf(pr, fname);	}
+
+	/// Set value for parameter $N
+	inline void AddParam(int id, const char *str)
+	{	mgl_parser_add_param(pr, id, str);	}
+	inline void AddParam(int id, const wchar_t *str)
+	{	mgl_parser_add_paramw(pr, id, str);	}
+	/// Restore once flag
+	inline void RestoreOnce()	{	mgl_parser_restore_once(pr);	}
+	/// Allow changing size of the picture
+	inline void AllowSetSize(bool allow)	{	mgl_parser_allow_setsize(pr, allow);	}
+	/// Allow reading/saving files
+	inline void AllowFileIO(bool allow)		{	mgl_parser_allow_file_io(pr, allow);	}
+	/// Allow loading commands from external libraries
+	inline void AllowDllCall(bool allow)	{	mgl_parser_allow_dll_call(pr, allow);	}
+	/// Set flag to stop script parsing
+	inline void Stop()	{	mgl_parser_stop(pr);	}
+	/// Set variant of argument(s) separated by '?' to be used in further commands
+	inline void SetVariant(int var=0)
+	{	mgl_parser_variant(pr, var);	}
+	/// Set starting object ID
+	inline void	StartID(int id=0)
+	{	mgl_parser_start_id(pr, id);	}
+
+	/// Return result of formula evaluation
+	inline mglData Calc(const char *formula)
+	{	return mglData(true,mgl_parser_calc(pr,formula)); 	}
+	inline mglData Calc(const wchar_t *formula)
+	{	return mglData(true,mgl_parser_calcw(pr,formula));	}
+
+	/// Return result of formula evaluation as complex data
+	inline mglDataC CalcComplex(const char *formula)
+	{	return mglDataC(true,mgl_parser_calc_complex(pr,formula)); 	}
+	inline mglDataC CalcComplex(const wchar_t *formula)
+	{	return mglDataC(true,mgl_parser_calc_complexw(pr,formula));	}
+
+	/// Find variable with given name or add a new one
+	/// NOTE !!! You must not delete obtained data arrays !!!
+	inline mglDataA *AddVar(const char *name)
+	{	return mgl_parser_add_var(pr, name);	}
+	inline mglDataA *AddVar(const wchar_t *name)
+	{	return mgl_parser_add_varw(pr, name);	}
+	/// Find variable with given name or return NULL if no one
+	/// NOTE !!! You must not delete obtained data arrays !!!
+	inline mglDataA *FindVar(const char *name)
+	{	return mgl_parser_find_var(pr, name);	}
+	inline mglDataA *FindVar(const wchar_t *name)
+	{	return mgl_parser_find_varw(pr, name);	}
+	/// Get variable with given id. Can be NULL for temporary ones.
+	/// NOTE !!! You must not delete obtained data arrays !!!
+	inline mglDataA *GetVar(unsigned long id)
+	{	return mgl_parser_get_var(pr,id);	}
+	/// Get number of variables
+	inline long GetNumVar()
+	{	return mgl_parser_num_var(pr);	}
+	/// Delete variable with name
+	inline void DeleteVar(const char *name)		{	mgl_parser_del_var(pr, name);		}
+	inline void DeleteVar(const wchar_t *name)	{	mgl_parser_del_varw(pr, name);		}
+	/// Delete all data variables
+	void DeleteAll()	{	mgl_parser_del_all(pr);	}
+
+	/// Get constant with given id. Can be NULL if not found.
+	/// NOTE !!! You must not delete obtained data arrays !!!
+	inline mglNum *GetConst(unsigned long id)
+	{	return mgl_parser_get_const(pr,id);	}
+	/// Get number of constants
+	inline long GetNumConst()
+	{	return mgl_parser_num_const(pr);	}
+};
+//-----------------------------------------------------------------------------
+#endif
+#endif
diff --git a/include/mgl2/mgl_cf.h b/include/mgl2/mgl_cf.h
new file mode 100644
index 0000000..66d3f16
--- /dev/null
+++ b/include/mgl2/mgl_cf.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+ * mgl_cf.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_CF_H_
+#define _MGL_CF_H_
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+#include <mgl2/data.h>
+#include <mgl2/datac.h>
+#endif
+//-----------------------------------------------------------------------------
+#include <mgl2/base_cf.h>
+#include <mgl2/data_cf.h>
+#include <mgl2/datac_cf.h>
+#include <mgl2/cont.h>
+#include <mgl2/fit.h>
+#include <mgl2/plot.h>
+#include <mgl2/surf.h>
+#include <mgl2/volume.h>
+#include <mgl2/vect.h>
+#include <mgl2/prim.h>
+#include <mgl2/other.h>
+#include <mgl2/canvas_cf.h>
+#include <mgl2/addon.h>
+//-----------------------------------------------------------------------------
+#if MGL_HAVE_OPENGL
+#ifdef __cplusplus
+extern "C" {
+#endif
+//-----------------------------------------------------------------------------
+HMGL MGL_EXPORT mgl_create_graph_gl();
+uintptr_t MGL_EXPORT mgl_create_graph_gl_();
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+}
+#endif
+#endif
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/mgl_pas.pas b/include/mgl2/mgl_pas.pas
new file mode 100644
index 0000000..5de4b9c
--- /dev/null
+++ b/include/mgl2/mgl_pas.pas
@@ -0,0 +1,1630 @@
+//**************************************************************************
+// mgl_pas.pas is part of Math Graphic Library                             *
+// Copyright (C) 2008-2013 Mikhail Barg, Alexey Balakin                    *
+//                                                                         *
+//   This program is free software; you can redistribute it and/or modify  *
+//   it under the terms of the GNU Library General Public License as       *
+//   published by the Free Software Foundation; either version 2 of the    *
+//   License, or (at your option) any later version.                       *
+//                                                                         *
+//   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 Library 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.             *
+//**************************************************************************
+
+unit mgl_pas;
+
+{$IFDEF FPC}
+{$MODE DELPHI }
+{$PACKENUM 4}    (* use 4-byte enums *)
+{$PACKRECORDS C} (* C/C++-compatible record packing *)
+{$ELSE}
+{$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+{$IFDEF DARWIN}
+{$linklib libmgl}
+{$ENDIF}
+
+interface
+
+uses
+{$IFDEF MSWINDOWS}
+Windows, Graphics,
+{$ENDIF}
+Math;
+
+const MGL_VER2 = 2.2;
+//* This define enables double precision in MathGL */
+MGL_USE_DOUBLE = 1;
+
+const
+{$IFDEF MSWINDOWS}
+//win - .dll
+libmgl = 'libmgl.dll';
+libmglglut = 'libmgl-glut.dll';
+libmglfltk = 'libmgl-fltk.dll';
+libmglqt   = 'libmgl-qt.dll';
+{$ELSE}
+{$IFDEF LINUX}
+//linux - .so
+libmgl = 'libmgl.so';
+libmglglut = 'libmgl-glut.so';
+libmglfltk = 'libmgl-fltk.so';
+libmglqt   = 'libmgl-qt.so';
+{$ELSE}
+{$IFDEF DARWIN}
+//darwin - .dylib
+libmgl = 'libmgl.dylib';
+libmglglut = 'libmgl-glut.dylib';
+libmglfltk = 'libmgl-fltk.dylib';
+libmglqt   = 'libmgl-qt.dylib';
+{$ELSE}
+// other platforms?
+
+{$ENDIF}
+{$ENDIF}
+{$ENDIF}
+
+{$IF (MGL_USE_DOUBLE = 0)}
+type mreal = double;
+{$ELSE}
+type mreal = real;
+{$IFEND}
+{$IFDEF FPC}
+{$ELSE}
+type QWord = Int64;
+{$ENDIF}
+
+Pmreal = ^mreal;
+
+type TNGLDraw = record
+end;
+type TMGLGraph = record
+end;
+type TMGLData = record
+end;
+type TMGLParse = record
+end;
+type TMGLFormula = record
+end;
+type TMGLFormulaC = record
+end;
+type TMGLDataC = record
+end;
+type HMDR = ^TNGLDraw;
+type HMGL = ^TMGLGraph;
+type HMDT = ^TMGLData;
+type HMPR = ^TMGLParse;
+type PPChar = ^PChar;
+type HMEX = ^TMGLFormula;
+type HAEX = ^TMGLFormulaC;
+type HADT = ^TMGLDataC;
+
+type Preal = ^single;
+type Pdouble = ^double;
+type Pint = ^integer;
+type dual = record
+re, im: mreal;
+end;
+type Pdual = ^dual;
+type TGSLVector = record
+end;
+type TGSLMatrix = record
+end;
+type PGSLVector = ^TGSLVector;
+type PGSLMatrix = ^TGSLMatrix;
+
+type TMglDrawFunction = function (gr: HMGL; p: pointer): integer; cdecl;
+function mgl_create_graph_gl(): HMGL; cdecl; external libmgl;
+function mgl_create_graph_glut(draw: TMglDrawFunction; const title: PChar; par: pointer): HMGL; cdecl; external libmglglut;
+function mgl_create_graph_fltk(draw: TMglDrawFunction; const title: PChar; par: pointer): HMGL; cdecl; external libmglfltk;
+procedure mgl_fltk_run(); cdecl; external libmglfltk;
+function mgl_create_graph_qt(draw: TMglDrawFunction; const title: PChar; par: pointer): HMGL; cdecl; external libmglqt;
+procedure mgl_qt_run(); cdecl; external libmglqt;
+
+{== ../../include/mgl2/abstract.h ==}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+/// Set seed for random numbers
+procedure  mgl_srnd(seed: integer); cdecl; external libmgl;
+/// Get random number
+function  mgl_rnd(): double; cdecl; external libmgl;
+/// Set name for data variable (can be used in mgl_formula_calc() or in MGL scripts)
+procedure  mgl_data_set_name(dat: HMDT;const name: PChar); cdecl; external libmgl;
+procedure  mgl_data_set_name_w(dat: HMDT;const name: PWideChar); cdecl; external libmgl;
+/// Set callback function which is called at deleting variable
+/// Save whole data array (for ns=-1) or only ns-th slice to text file
+procedure  mgl_data_save(const dat: HMDT;const fname: PChar;ns: integer); cdecl; external libmgl;
+/// Export data array (for ns=-1) or only ns-th slice to PNG file according color scheme
+procedure  mgl_data_export(const dat: HMDT;const fname: PChar;const scheme: PChar;v1: mreal;v2: mreal;ns: integer); cdecl; external libmgl;
+/// Save data to HDF file
+procedure  mgl_data_save_hdf(const d: HMDT;const fname: PChar;const data: PChar;rewrite: integer); cdecl; external libmgl;
+/// Get information about the data (sizes and momentum) to string
+function mgl_data_info(const dat: HMDT): PChar; cdecl; external libmgl;
+/// Put HDF data names into buf as '\t' separated.
+function  mgl_datas_hdf(const fname: PChar;buf: PChar;size: integer): integer; cdecl; external libmgl;
+/// Get maximal value of the data
+function  mgl_data_max(const dat: HMDT): mreal; cdecl; external libmgl;
+/// Get maximal value of the data which is less than 0
+function  mgl_data_neg_max(const dat: HMDT): mreal; cdecl; external libmgl;
+/// Get minimal value of the data
+function  mgl_data_min(const dat: HMDT): mreal; cdecl; external libmgl;
+/// Get minimal value of the data which is larger than 0
+function  mgl_data_pos_min(const dat: HMDT): mreal; cdecl; external libmgl;
+/// Find position (after specified in i,j,k) of first nonzero value of formula
+function  mgl_data_first(const dat: HMDT;const cond: PChar;i: Pint;j: Pint;k: Pint): mreal; cdecl; external libmgl;
+/// Find position (before specified in i,j,k) of last nonzero value of formula
+function  mgl_data_last(const dat: HMDT;const cond: PChar;i: Pint;j: Pint;k: Pint): mreal; cdecl; external libmgl;
+/// Find position of first in direction 'dir' nonzero value of formula
+function  mgl_data_find(const dat: HMDT;const cond: PChar;dir: char;i: integer;j: integer;k: integer): integer; cdecl; external libmgl;
+/// Find if any nonzero value of formula
+function  mgl_data_find_any(const dat: HMDT;const cond: PChar): integer; cdecl; external libmgl;
+/// Get maximal value of the data and its position
+function  mgl_data_max_int(const dat: HMDT;i: Pint;j: Pint;k: Pint): mreal; cdecl; external libmgl;
+/// Get maximal value of the data and its approximated position
+function  mgl_data_max_real(const dat: HMDT;x: Pmreal;y: Pmreal;z: Pmreal): mreal; cdecl; external libmgl;
+/// Get minimal value of the data and its position
+function  mgl_data_min_int(const dat: HMDT;i: Pint;j: Pint;k: Pint): mreal; cdecl; external libmgl;
+/// Get minimal value of the data and its approximated position
+function  mgl_data_min_real(const dat: HMDT;x: Pmreal;y: Pmreal;z: Pmreal): mreal; cdecl; external libmgl;
+/// Get "energy and find 4 momenta of data: median, width, skewness, kurtosis
+function  mgl_data_momentum_val(const d: HMDT;dir: char;m: Pmreal;w: Pmreal;s: Pmreal;k: Pmreal): mreal; cdecl; external libmgl;
+//-----------------------------------------------------------------------------
+/// Callback function for asking user a question. Result shouldn't exceed 1024.
+//-----------------------------------------------------------------------------
+/// Abstract class for data array
+//	{	return i>0 ? (i<GetNx()-1 ? (v(i+1,j,k)-v(i-1,j,k))/2 : v(i,j,k)-v(i-1,j,k)) : v(1,j,k)-v(0,j,k) 	}
+//	{	return j>0 ? (j<GetNy()-1 ? (v(i,j+1,k)-v(i,j-1,k))/2 : v(i,j,k)-v(i,j-1,k)) : v(i,1,k)-v(i,0,k) 	}
+//	{	return k>0 ? (k<GetNz()-1 ? (v(i,j,k+1)-v(i,j,k-1))/2 : v(i,j,k)-v(i,j,k-1)) : v(i,j,1)-v(i,j,0) 	}
+//-----------------------------------------------------------------------------
+/// Structure for color ID
+//-----------------------------------------------------------------------------
+{== ../../include/mgl2/base_cf.h ==}
+//-----------------------------------------------------------------------------
+/// Check if MathGL version is valid (return 0) or not (return 1)
+function  mgl_check_version(const ver: PChar): integer; cdecl; external libmgl;
+/// Suppress printing warnings to stderr
+procedure  mgl_suppress_warn(on: integer); cdecl; external libmgl;
+/// Get last warning code
+function  mgl_get_warn(gr: HMGL): integer; cdecl; external libmgl;
+/// Set warning code ant fill message
+procedure  mgl_set_warn(gr: HMGL;code: integer;const text: PChar); cdecl; external libmgl;
+/// Get text of warning message(s)
+function mgl_get_mess(gr: HMGL): PChar; cdecl; external libmgl;
+/// Set name of plot for saving filename
+procedure  mgl_set_plotid(gr: HMGL;const id: PChar); cdecl; external libmgl;
+/// Get name of plot for saving filename
+function mgl_get_plotid(gr: HMGL): PChar; cdecl; external libmgl;
+/// Ask to stop drawing
+procedure  mgl_ask_stop(gr: HMGL;stop: integer); cdecl; external libmgl;
+/// Check if plot termination is asked
+function  mgl_need_stop(gr: HMGL): integer; cdecl; external libmgl;
+/// Set callback function for event processing
+/// Get plot quality
+function  mgl_get_quality(gr: HMGL): integer; cdecl; external libmgl;
+/// Set plot quality
+procedure  mgl_set_quality(gr: HMGL;qual: integer); cdecl; external libmgl;
+/// Set drawing region for Quality&4
+procedure  mgl_set_draw_reg(gr: HMGL;nx: integer;ny: integer;m: integer); cdecl; external libmgl;
+/// Check if support of frames is enabled (i.e. MGL_VECT_FRAME is set and Quality&MGL_DRAW_LMEM==0)
+function  mgl_is_frames(gr: HMGL): integer; cdecl; external libmgl;
+/// Get bit-value flag of HMGL state (for advanced users only)
+function  mgl_get_flag(gr: HMGL;flag: LongWord): integer; cdecl; external libmgl;
+/// Set bit-value flag of HMGL state (for advanced users only)
+procedure  mgl_set_flag(gr: HMGL;val: integer;flag: LongWord); cdecl; external libmgl;
+/// Change counter of HMGL uses (for advanced users only). Non-zero counter prevent automatic object removing.
+function  mgl_use_graph(gr: HMGL;inc: integer): integer; cdecl; external libmgl;
+procedure  mgl_set_rdc_acc(gr: HMGL;reduce: integer); cdecl; external libmgl;
+/// Start group of objects
+procedure  mgl_start_group(gr: HMGL;const name: PChar); cdecl; external libmgl;
+/// End group of objects
+procedure  mgl_end_group(gr: HMGL); cdecl; external libmgl;
+/// Highlight objects with given id
+procedure  mgl_highlight(gr: HMGL;id: integer); cdecl; external libmgl;
+/// Set default palette
+procedure  mgl_set_palette(gr: HMGL;const colors: PChar); cdecl; external libmgl;
+/// Sets RGB values for color with given id
+procedure  mgl_set_color(id: char;r: double;g: double;b: double); cdecl; external libmgl;
+/// Set default color scheme
+procedure  mgl_set_def_sch(gr: HMGL;const sch: PChar); cdecl; external libmgl;
+/// Set mask for face coloring as array of type 'unsigned char[8]'
+procedure  mgl_set_mask(id: char;const mask: PChar); cdecl; external libmgl;
+/// Set mask for face coloring as unsigned long number
+procedure  mgl_set_mask_val(id: char;mask: QWord); cdecl; external libmgl;
+/// Set default mask rotation angle
+procedure  mgl_set_mask_angle(gr: HMGL;angle: integer); cdecl; external libmgl;
+/// Set default value of alpha-channel
+procedure  mgl_set_alpha_default(gr: HMGL;alpha: double); cdecl; external libmgl;
+/// Set relative width of rectangles in Bars, Barh, BoxPlot
+procedure  mgl_set_bar_width(gr: HMGL;width: double); cdecl; external libmgl;
+/// Set number of mesh lines (use 0 to draw all of them)
+procedure  mgl_set_meshnum(gr: HMGL;num: integer); cdecl; external libmgl;
+/// Set number of visible faces (use 0 to draw all of them)
+procedure  mgl_set_facenum(gr: HMGL;num: integer); cdecl; external libmgl;
+/// Clear unused points and primitives. Useful only in combination with mgl_set_facenum().
+procedure  mgl_clear_unused(gr: HMGL); cdecl; external libmgl;
+/// Set ambient light brightness
+procedure  mgl_set_ambbr(gr: HMGL;i: double); cdecl; external libmgl;
+/// Set diffusive light brightness
+procedure  mgl_set_difbr(gr: HMGL;i: double); cdecl; external libmgl;
+/// Use diffusive light (only for local light sources) -- OBSOLETE
+procedure  mgl_set_light_dif(gr: HMGL;enable: integer); cdecl; external libmgl;
+/// Set cutting for points outside of bounding box
+procedure  mgl_set_cut(gr: HMGL;cut: integer); cdecl; external libmgl;
+/// Set additional cutting box
+procedure  mgl_set_cut_box(gr: HMGL;x1: double;y1: double;z1: double;x2: double;y2: double;z2: double); cdecl; external libmgl;
+/// Set the cutting off condition (formula)
+procedure  mgl_set_cutoff(gr: HMGL;const EqC: PChar); cdecl; external libmgl;
+/// Set values of axis range
+procedure  mgl_set_ranges(gr: HMGL;x1: double;x2: double;y1: double;y2: double;z1: double;z2: double); cdecl; external libmgl;
+/// Set range in direction dir as [v1, v2]
+procedure  mgl_set_range_val(gr: HMGL;dir: char;v1: double;v2: double); cdecl; external libmgl;
+/// Add [v1, v2] to the current range in direction dir
+procedure  mgl_add_range_val(gr: HMGL;dir: char;v1: double;v2: double); cdecl; external libmgl;
+/// Set range in direction dir as minimal and maximal values of data a
+procedure  mgl_set_range_dat(gr: HMGL;dir: char;const a: HMDT;add: integer); cdecl; external libmgl;
+/// Set ranges for automatic variables
+procedure  mgl_set_auto_ranges(gr: HMGL;x1: double;x2: double;y1: double;y2: double;z1: double;z2: double;c1: double;c2: double); cdecl; external libmgl;
+/// Set axis range scaling -- simplified way to shift/zoom axis range -- need to redraw whole image!
+procedure  mgl_zoom_axis(gr: HMGL;x1: double;y1: double;z1: double;c1: double;x2: double;y2: double;z2: double;c2: double); cdecl; external libmgl;
+/// Set axis origin
+procedure  mgl_set_origin(gr: HMGL;x0: double;y0: double;z0: double); cdecl; external libmgl;
+/// Set the transformation formulas for coordinate
+procedure  mgl_set_func(gr: HMGL;const EqX: PChar;const EqY: PChar;const EqZ: PChar;const EqA: PChar); cdecl; external libmgl;
+/// Set one of predefined transformation rule
+procedure  mgl_set_coor(gr: HMGL;how: integer); cdecl; external libmgl;
+/// Set to draw Ternary axis (triangle like axis, grid and so on)
+procedure  mgl_set_ternary(gr: HMGL;kind: integer); cdecl; external libmgl;
+/// Set to use or not tick labels rotation
+procedure  mgl_set_tick_rotate(gr: HMGL;enable: integer); cdecl; external libmgl;
+/// Set to use or not tick labels skipping
+procedure  mgl_set_tick_skip(gr: HMGL;enable: integer); cdecl; external libmgl;
+/// Set default font for all new HMGL objects
+procedure  mgl_def_font(const name: PChar;const path: PChar); cdecl; external libmgl;
+/// Set default size of marks (locally you can use "size" option)
+procedure  mgl_set_mark_size(gr: HMGL;size: double); cdecl; external libmgl;
+/// Set default size of arrows (locally you can use "size" option)
+procedure  mgl_set_arrow_size(gr: HMGL;size: double); cdecl; external libmgl;
+/// Set default font size
+procedure  mgl_set_font_size(gr: HMGL;size: double); cdecl; external libmgl;
+/// Set default font style and color
+procedure  mgl_set_font_def(gr: HMGL;const fnt: PChar); cdecl; external libmgl;
+/// Set to use or not text rotation
+procedure  mgl_set_rotated_text(gr: HMGL;enable: integer); cdecl; external libmgl;
+/// Load font from file
+procedure  mgl_load_font(gr: HMGL;const name: PChar;const path: PChar); cdecl; external libmgl;
+/// Copy font from another mglGraph instance
+procedure  mgl_copy_font(gr: HMGL;gr_from: HMGL); cdecl; external libmgl;
+/// Restore font (load default font for new HMGL objects)
+procedure  mgl_restore_font(gr: HMGL); cdecl; external libmgl;
+//-----------------------------------------------------------------------------
+{== ../../include/mgl2/data_cf.h ==}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+/// Get integer power of x
+function  mgl_ipow(x: double;n: integer): double; cdecl; external libmgl;
+/// Get number of seconds since 1970 for given string
+function  mgl_get_time(const time: PChar;const fmt: PChar): double; cdecl; external libmgl;
+/// Create HMDT object
+function  mgl_create_data(): HMDT; cdecl; external libmgl;
+/// Create HMDT object with specified sizes
+function  mgl_create_data_size(nx: integer;ny: integer;nz: integer): HMDT; cdecl; external libmgl;
+/// Create HMDT object with data from file
+function  mgl_create_data_file(const fname: PChar): HMDT; cdecl; external libmgl;
+/// Delete HMDT object
+procedure  mgl_delete_data(dat: HMDT); cdecl; external libmgl;
+/// Rearange data dimensions
+procedure  mgl_data_rearrange(dat: HMDT;mx: integer;my: integer;mz: integer); cdecl; external libmgl;
+/// Link external data array (don't delete it at exit)
+procedure  mgl_data_link(dat: HMDT;A: Pmreal;mx: integer;my: integer;mz: integer); cdecl; external libmgl;
+/// Allocate memory and copy the data from the (float *) array
+procedure  mgl_data_set_float(dat: HMDT;const A: Preal;mx: integer;my: integer;mz: integer); cdecl; external libmgl;
+/// Allocate memory and copy the data from the (double *) array
+procedure  mgl_data_set_double(dat: HMDT;const A: Pdouble;mx: integer;my: integer;mz: integer); cdecl; external libmgl;
+/// Allocate memory and copy the data from the (float **) array
+/// Allocate memory and copy the data from the (double **) array
+/// Allocate memory and copy the data from the (float ***) array
+/// Allocate memory and copy the data from the (double ***) array
+/// Import data from abstract type
+procedure  mgl_data_set(dat: HMDT;const a: HMDT); cdecl; external libmgl;
+/// Allocate memory and copy the data from the gsl_vector
+procedure  mgl_data_set_vector(dat: HMDT;v: PGSLVector); cdecl; external libmgl;
+/// Allocate memory and copy the data from the gsl_matrix
+procedure  mgl_data_set_matrix(dat: HMDT;m: PGSLMatrix); cdecl; external libmgl;
+/// Set value of data element [i,j,k]
+procedure  mgl_data_set_value(dat: HMDT;v: mreal;i: integer;j: integer;k: integer); cdecl; external libmgl;
+/// Get value of data element [i,j,k]
+function  mgl_data_get_value(const dat: HMDT;i: integer;j: integer;k: integer): mreal; cdecl; external libmgl;
+/// Allocate memory and scanf the data from the string
+procedure  mgl_data_set_values(dat: HMDT;const val: PChar;nx: integer;ny: integer;nz: integer); cdecl; external libmgl;
+/// Read data array from HDF file (parse HDF4 and HDF5 files)
+function  mgl_data_read_hdf(d: HMDT;const fname: PChar;const data: PChar): integer; cdecl; external libmgl;
+/// Read data from tab-separated text file with auto determining size
+function  mgl_data_read(dat: HMDT;const fname: PChar): integer; cdecl; external libmgl;
+/// Read data from text file with size specified at beginning of the file
+function  mgl_data_read_mat(dat: HMDT;const fname: PChar;dim: integer): integer; cdecl; external libmgl;
+/// Read data from text file with specifeid size
+function  mgl_data_read_dim(dat: HMDT;const fname: PChar;mx: integer;my: integer;mz: integer): integer; cdecl; external libmgl;
+/// Read data from tab-separated text files with auto determining size which filenames are result of sprintf(fname,templ,t) where t=from:step:to
+function  mgl_data_read_range(d: HMDT;const templ: PChar;n1: double;n2: double;step: double;as_slice: integer): integer; cdecl; external libmgl;
+/// Read data from tab-separated text files with auto determining size which filenames are satisfied to template (like "t_*.dat")
+function  mgl_data_read_all(dat: HMDT;const templ: PChar;as_slice: integer): integer; cdecl; external libmgl;
+/// Import data array from PNG file according color scheme
+procedure  mgl_data_import(dat: HMDT;const fname: PChar;const scheme: PChar;v1: mreal;v2: mreal); cdecl; external libmgl;
+/// Create or recreate the array with specified size and fill it by zero
+procedure  mgl_data_create(dat: HMDT;nx: integer;ny: integer;nz: integer); cdecl; external libmgl;
+/// Transpose dimensions of the data (generalization of Transpose)
+procedure  mgl_data_transpose(dat: HMDT;const dim: PChar); cdecl; external libmgl;
+/// Normalize the data to range [v1,v2]
+procedure  mgl_data_norm(dat: HMDT;v1: mreal;v2: mreal;sym: integer;dim: integer); cdecl; external libmgl;
+/// Normalize the data to range [v1,v2] slice by slice
+procedure  mgl_data_norm_slice(dat: HMDT;v1: mreal;v2: mreal;dir: char;keep_en: integer;sym: integer); cdecl; external libmgl;
+/// Get sub-array of the data with given fixed indexes
+function  mgl_data_subdata(const dat: HMDT;xx: integer;yy: integer;zz: integer): HMDT; cdecl; external libmgl;
+/// Get sub-array of the data with given fixed indexes (like indirect access)
+function  mgl_data_subdata_ext(const dat: HMDT;const xx: HMDT;const yy: HMDT;const zz: HMDT): HMDT; cdecl; external libmgl;
+/// Get column (or slice) of the data filled by formulas of named columns
+function  mgl_data_column(const dat: HMDT;const eq: PChar): HMDT; cdecl; external libmgl;
+/// Set names for columns (slices)
+procedure  mgl_data_set_id(d: HMDT;const id: PChar); cdecl; external libmgl;
+/// Equidistantly fill the data to range [x1,x2] in direction dir
+procedure  mgl_data_fill(dat: HMDT;x1: mreal;x2: mreal;dir: char); cdecl; external libmgl;
+/// Modify the data by specified formula assuming x,y,z in range [r1,r2]
+procedure  mgl_data_fill_eq(gr: HMGL;dat: HMDT;const eq: PChar;const vdat: HMDT;const wdat: HMDT;const opt: PChar); cdecl; external libmgl;
+/// Fill dat by interpolated values of vdat parametrically depended on xdat for x in range [x1,x2] using global spline
+procedure  mgl_data_refill_gs(dat: HMDT;const xdat: HMDT;const vdat: HMDT;x1: mreal;x2: mreal;sl: integer); cdecl; external libmgl;
+/// Fill dat by interpolated values of vdat parametrically depended on xdat for x in range [x1,x2]
+procedure  mgl_data_refill_x(dat: HMDT;const xdat: HMDT;const vdat: HMDT;x1: mreal;x2: mreal;sl: integer); cdecl; external libmgl;
+/// Fill dat by interpolated values of vdat parametrically depended on xdat,ydat for x,y in range [x1,x2]*[y1,y2]
+procedure  mgl_data_refill_xy(dat: HMDT;const xdat: HMDT;const ydat: HMDT;const vdat: HMDT;x1: mreal;x2: mreal;y1: mreal;y2: mreal;sl: integer); cdecl; external libmgl;
+/// Fill dat by interpolated values of vdat parametrically depended on xdat,ydat,zdat for x,y,z in range [x1,x2]*[y1,y2]*[z1,z2]
+procedure  mgl_data_refill_xyz(dat: HMDT;const xdat: HMDT;const ydat: HMDT;const zdat: HMDT;const vdat: HMDT;x1: mreal;x2: mreal;y1: mreal;y2: mreal;z1: mreal;z2: mreal); cdecl; external libmgl;
+/// Fill dat by interpolated values of vdat parametrically depended on xdat,ydat,zdat for x,y,z in axis range
+procedure  mgl_data_refill_gr(gr: HMGL;dat: HMDT;const xdat: HMDT;const ydat: HMDT;const zdat: HMDT;const vdat: HMDT;sl: integer;const opt: PChar); cdecl; external libmgl;
+/// Set the data by triangulated surface values assuming x,y,z in range [r1,r2]
+procedure  mgl_data_grid(gr: HMGL;d: HMDT;const xdat: HMDT;const ydat: HMDT;const zdat: HMDT;const opt: PChar); cdecl; external libmgl;
+/// Set the data by triangulated surface values assuming x,y,z in range [x1,x2]*[y1,y2]
+procedure  mgl_data_grid_xy(d: HMDT;const xdat: HMDT;const ydat: HMDT;const zdat: HMDT;x1: mreal;x2: mreal;y1: mreal;y2: mreal); cdecl; external libmgl;
+/// Put value to data element(s)
+procedure  mgl_data_put_val(dat: HMDT;val: mreal;i: integer;j: integer;k: integer); cdecl; external libmgl;
+/// Put array to data element(s)
+procedure  mgl_data_put_dat(dat: HMDT;const val: HMDT;i: integer;j: integer;k: integer); cdecl; external libmgl;
+/// Modify the data by specified formula
+procedure  mgl_data_modify(dat: HMDT;const eq: PChar;dim: integer); cdecl; external libmgl;
+/// Modify the data by specified formula
+procedure  mgl_data_modify_vw(dat: HMDT;const eq: PChar;const vdat: HMDT;const wdat: HMDT); cdecl; external libmgl;
+/// Reduce size of the data
+procedure  mgl_data_squeeze(dat: HMDT;rx: integer;ry: integer;rz: integer;smooth: integer); cdecl; external libmgl;
+/// Returns pointer to data element [i,j,k]
+function mgl_data_value(dat: HMDT;i: integer;j: integer;k: integer): Pmreal; cdecl; external libmgl;
+/// Returns pointer to internal data array
+function mgl_data_data(dat: HMDT): Pmreal; cdecl; external libmgl;
+/// Gets the x-size of the data.
+function  mgl_data_get_nx(const d: HMDT): integer; cdecl; external libmgl;
+/// Gets the y-size of the data.
+function  mgl_data_get_ny(const d: HMDT): integer; cdecl; external libmgl;
+/// Gets the z-size of the data.
+function  mgl_data_get_nz(const d: HMDT): integer; cdecl; external libmgl;
+/// Get the data which is direct multiplication (like, d[i,j] = this[i]*a[j] and so on)
+function  mgl_data_combine(const dat1: HMDT;const dat2: HMDT): HMDT; cdecl; external libmgl;
+/// Extend data dimensions
+procedure  mgl_data_extend(dat: HMDT;n1: integer;n2: integer); cdecl; external libmgl;
+/// Insert data rows/columns/slices
+procedure  mgl_data_insert(dat: HMDT;dir: char;at: integer;num: integer); cdecl; external libmgl;
+/// Delete data rows/columns/slices
+procedure  mgl_data_delete(dat: HMDT;dir: char;at: integer;num: integer); cdecl; external libmgl;
+/// Joind another data array
+procedure  mgl_data_join(dat: HMDT;const d: HMDT); cdecl; external libmgl;
+/// Smooth the data on specified direction or directions
+procedure  mgl_data_smooth(d: HMDT;const dirs: PChar;delta: mreal); cdecl; external libmgl;
+/// Get array which is result of summation in given direction or directions
+function  mgl_data_sum(const dat: HMDT;const dir: PChar): HMDT; cdecl; external libmgl;
+/// Get array which is result of maximal values in given direction or directions
+function  mgl_data_max_dir(const dat: HMDT;const dir: PChar): HMDT; cdecl; external libmgl;
+/// Get array which is result of minimal values in given direction or directions
+function  mgl_data_min_dir(const dat: HMDT;const dir: PChar): HMDT; cdecl; external libmgl;
+/// Cumulative summation the data in given direction or directions
+procedure  mgl_data_cumsum(dat: HMDT;const dir: PChar); cdecl; external libmgl;
+/// Integrate (cumulative summation) the data in given direction or directions
+procedure  mgl_data_integral(dat: HMDT;const dir: PChar); cdecl; external libmgl;
+/// Differentiate the data in given direction or directions
+procedure  mgl_data_diff(dat: HMDT;const dir: PChar); cdecl; external libmgl;
+/// Differentiate the parametrically specified data along direction v1 with v2,v3=const (v3 can be NULL)
+procedure  mgl_data_diff_par(dat: HMDT;const v1: HMDT;const v2: HMDT;const v3: HMDT); cdecl; external libmgl;
+/// Double-differentiate (like Laplace operator) the data in given direction
+procedure  mgl_data_diff2(dat: HMDT;const dir: PChar); cdecl; external libmgl;
+/// Swap left and right part of the data in given direction (useful for Fourier spectrum)
+procedure  mgl_data_swap(dat: HMDT;const dir: PChar); cdecl; external libmgl;
+/// Roll data along direction dir by num slices
+procedure  mgl_data_roll(dat: HMDT;dir: char;num: integer); cdecl; external libmgl;
+/// Mirror the data in given direction (useful for Fourier spectrum)
+procedure  mgl_data_mirror(dat: HMDT;const dir: PChar); cdecl; external libmgl;
+/// Sort rows (or slices) by values of specified column
+procedure  mgl_data_sort(dat: HMDT;idx: integer;idy: integer); cdecl; external libmgl;
+/// Apply Hankel transform
+procedure  mgl_data_hankel(dat: HMDT;const dir: PChar); cdecl; external libmgl;
+/// Apply Sin-Fourier transform
+procedure  mgl_data_sinfft(dat: HMDT;const dir: PChar); cdecl; external libmgl;
+/// Apply Cos-Fourier transform
+procedure  mgl_data_cosfft(dat: HMDT;const dir: PChar); cdecl; external libmgl;
+/// Fill data by 'x'/'k' samples for Hankel ('h') or Fourier ('f') transform
+procedure  mgl_data_fill_sample(dat: HMDT;const how: PChar); cdecl; external libmgl;
+/// Find correlation between 2 data arrays
+function  mgl_data_correl(const dat1: HMDT;const dat2: HMDT;const dir: PChar): HMDT; cdecl; external libmgl;
+/// Allocate and prepare data for Fourier transform by nthr threads
+/// Free data for Fourier transform
+/// Make Fourier transform of data x of size n and step s between points
+/// Clear internal data for speeding up FFT and Hankel transforms
+procedure  mgl_clear_fft(); cdecl; external libmgl;
+/// Interpolate by cubic spline the data to given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+function  mgl_data_spline(const dat: HMDT;x: mreal;y: mreal;z: mreal): mreal; cdecl; external libmgl;
+/// Interpolate by linear function the data to given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+function  mgl_data_linear(const dat: HMDT;x: mreal;y: mreal;z: mreal): mreal; cdecl; external libmgl;
+/// Interpolate by cubic spline the data and return its derivatives at given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+function  mgl_data_spline_ext(const dat: HMDT;x: mreal;y: mreal;z: mreal;dx: Pmreal;dy: Pmreal;dz: Pmreal): mreal; cdecl; external libmgl;
+/// Prepare coefficients for global spline interpolation
+function  mgl_gspline_init(const x: HMDT;const v: HMDT): HMDT; cdecl; external libmgl;
+/// Evaluate global spline (and its derivatives d1, d2 if not NULL) using prepared coefficients \a coef
+function  mgl_gspline(const coef: HMDT;dx: mreal;d1: Pmreal;d2: Pmreal): mreal; cdecl; external libmgl;
+/// Interpolate by linear function the data and return its derivatives at given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+function  mgl_data_linear_ext(const dat: HMDT;x: mreal;y: mreal;z: mreal;dx: Pmreal;dy: Pmreal;dz: Pmreal): mreal; cdecl; external libmgl;
+/// Return an approximated x-value (root) when dat(x) = val
+function  mgl_data_solve_1d(const dat: HMDT;val: mreal;spl: integer;i0: integer): mreal; cdecl; external libmgl;
+/// Return an approximated value (root) when dat(x) = val
+function  mgl_data_solve(const dat: HMDT;val: mreal;dir: char;const i0: HMDT;norm: integer): HMDT; cdecl; external libmgl;
+/// Get trace of the data array
+function  mgl_data_trace(const d: HMDT): HMDT; cdecl; external libmgl;
+/// Resize the data to new sizes
+function  mgl_data_resize(const dat: HMDT;mx: integer;my: integer;mz: integer): HMDT; cdecl; external libmgl;
+/// Resize the data to new sizes of box [x1,x2]*[y1,y2]*[z1,z2]
+function  mgl_data_resize_box(const dat: HMDT;mx: integer;my: integer;mz: integer;x1: mreal;x2: mreal;y1: mreal;y2: mreal;z1: mreal;z2: mreal): HMDT; cdecl; external libmgl;
+/// Create n-th points distribution of this data values in range [v1, v2]
+function  mgl_data_hist(const dat: HMDT;n: integer;v1: mreal;v2: mreal;nsub: integer): HMDT; cdecl; external libmgl;
+/// Create n-th points distribution of this data values in range [v1, v2] with weight w
+function  mgl_data_hist_w(const dat: HMDT;const weight: HMDT;n: integer;v1: mreal;v2: mreal;nsub: integer): HMDT; cdecl; external libmgl;
+/// Get momentum (1D-array) of data along direction 'dir'. String looks like "x1" for median in x-direction, "x2" for width in x-dir and so on.
+function  mgl_data_momentum(const dat: HMDT;dir: char;const how: PChar): HMDT; cdecl; external libmgl;
+/// Get array which values is result of interpolation this for coordinates from other arrays
+function  mgl_data_evaluate(const dat: HMDT;const idat: HMDT;const jdat: HMDT;const kdat: HMDT;norm: integer): HMDT; cdecl; external libmgl;
+/// Set as the data envelop
+procedure  mgl_data_envelop(dat: HMDT;dir: char); cdecl; external libmgl;
+/// Remove phase jump
+procedure  mgl_data_sew(dat: HMDT;const dirs: PChar;da: mreal); cdecl; external libmgl;
+/// Crop the data
+procedure  mgl_data_crop(dat: HMDT;n1: integer;n2: integer;dir: char); cdecl; external libmgl;
+/// Remove rows with duplicate values in column id
+procedure  mgl_data_clean(dat: HMDT;id: integer); cdecl; external libmgl;
+/// Multiply the data by other one for each element
+procedure  mgl_data_mul_dat(dat: HMDT;const d: HMDT); cdecl; external libmgl;
+/// Divide the data by other one for each element
+procedure  mgl_data_div_dat(dat: HMDT;const d: HMDT); cdecl; external libmgl;
+/// Add the other data
+procedure  mgl_data_add_dat(dat: HMDT;const d: HMDT); cdecl; external libmgl;
+/// Subtract the other data
+procedure  mgl_data_sub_dat(dat: HMDT;const d: HMDT); cdecl; external libmgl;
+/// Multiply each element by the number
+procedure  mgl_data_mul_num(dat: HMDT;d: mreal); cdecl; external libmgl;
+/// Divide each element by the number
+procedure  mgl_data_div_num(dat: HMDT;d: mreal); cdecl; external libmgl;
+/// Add the number
+procedure  mgl_data_add_num(dat: HMDT;d: mreal); cdecl; external libmgl;
+/// Subtract the number
+procedure  mgl_data_sub_num(dat: HMDT;d: mreal); cdecl; external libmgl;
+/// Integral data transformation (like Fourier 'f' or 'i', Hankel 'h' or None 'n') for amplitude and phase
+function  mgl_transform_a(const am: HMDT;const ph: HMDT;const tr: PChar): HMDT; cdecl; external libmgl;
+/// Integral data transformation (like Fourier 'f' or 'i', Hankel 'h' or None 'n') for real and imaginary parts
+function  mgl_transform(const re: HMDT;const im: HMDT;const tr: PChar): HMDT; cdecl; external libmgl;
+/// Apply Fourier transform for the data and save result into it
+procedure  mgl_data_fourier(re: HMDT;im: HMDT;const dir: PChar); cdecl; external libmgl;
+/// Short time Fourier analysis for real and imaginary parts. Output is amplitude of partial Fourier (result will have size {dn, floor(nx/dn), ny} for dir='x'
+function  mgl_data_stfa(const re: HMDT;const im: HMDT;dn: integer;dir: char): HMDT; cdecl; external libmgl;
+/// Do something like Delone triangulation for 3d points
+function  mgl_triangulation_3d(const x: HMDT;const y: HMDT;const z: HMDT): HMDT; cdecl; external libmgl;
+/// Do Delone triangulation for 2d points
+function  mgl_triangulation_2d(const x: HMDT;const y: HMDT): HMDT; cdecl; external libmgl;
+/// Find root for nonlinear equation
+/// Find root for nonlinear equation defined by textual formula
+function  mgl_find_root_txt(const func: PChar;ini: mreal;var_id: char): mreal; cdecl; external libmgl;
+/// Find roots for nonlinear equation defined by textual formula
+function  mgl_data_roots(const func: PChar;const ini: HMDT;var_id: char): HMDT; cdecl; external libmgl;
+//-----------------------------------------------------------------------------
+/// Create HMEX object for expression evaluating
+function  mgl_create_expr(const expr: PChar): HMEX; cdecl; external libmgl;
+/// Delete HMEX object
+procedure  mgl_delete_expr(ex: HMEX); cdecl; external libmgl;
+/// Return value of expression for given x,y,z variables
+function  mgl_expr_eval(ex: HMEX;x: double;y: double;z: double): double; cdecl; external libmgl;
+/// Return value of expression for given variables
+function  mgl_expr_eval_v(ex: HMEX;vars: Pmreal): double; cdecl; external libmgl;
+/// Return value of expression differentiation over variable dir for given x,y,z variables
+function  mgl_expr_diff(ex: HMEX;dir: char;x: double;y: double;z: double): double; cdecl; external libmgl;
+/// Return value of expression differentiation over variable dir for given variables
+function  mgl_expr_diff_v(ex: HMEX;dir: char;vars: Pmreal): double; cdecl; external libmgl;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+{== ../../include/mgl2/datac_cf.h ==}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+/// Get integer power of x
+function  mgl_ipowc(x: dual;n: integer): dual; cdecl; external libmgl;
+/// Get exp(i*a)
+function  mgl_expi(a: dual): dual; cdecl; external libmgl;
+overload;
+/// Create HMDT object
+function  mgl_create_datac(): HADT; cdecl; external libmgl;
+/// Create HMDT object with specified sizes
+function  mgl_create_datac_size(nx: integer;ny: integer;nz: integer): HADT; cdecl; external libmgl;
+/// Create HMDT object with data from file
+function  mgl_create_datac_file(const fname: PChar): HADT; cdecl; external libmgl;
+/// Delete HMDT object
+procedure  mgl_delete_datac(dat: HADT); cdecl; external libmgl;
+/// Rearange data dimensions
+procedure  mgl_datac_rearrange(dat: HADT;mx: integer;my: integer;mz: integer); cdecl; external libmgl;
+/// Link external data array (don't delete it at exit)
+procedure  mgl_datac_link(dat: HADT;A: Pdual;mx: integer;my: integer;mz: integer); cdecl; external libmgl;
+/// Allocate memory and copy the data from the (float *) array
+procedure  mgl_datac_set_float(dat: HADT;const A: Preal;mx: integer;my: integer;mz: integer); cdecl; external libmgl;
+/// Allocate memory and copy the data from the (double *) array
+procedure  mgl_datac_set_double(dat: HADT;const A: Pdouble;mx: integer;my: integer;mz: integer); cdecl; external libmgl;
+/// Allocate memory and copy the data from the (dual *) array
+procedure  mgl_datac_set_complex(dat: HADT;const A: Pdual;mx: integer;my: integer;mz: integer); cdecl; external libmgl;
+/// Import data from abstract type
+procedure  mgl_datac_set(dat: HADT;const a: HMDT); cdecl; external libmgl;
+/// Allocate memory and copy the data from the gsl_vector
+procedure  mgl_datac_set_vector(dat: HADT;v: PGSLVector); cdecl; external libmgl;
+/// Allocate memory and copy the data from the gsl_matrix
+procedure  mgl_datac_set_matrix(dat: HADT;m: PGSLMatrix); cdecl; external libmgl;
+/// Set value of data element [i,j,k]
+procedure  mgl_datac_set_value(dat: HADT;v: dual;i: integer;j: integer;k: integer); cdecl; external libmgl;
+/// Get value of data element [i,j,k]
+function  mgl_datac_get_value(const dat: HMDT;i: integer;j: integer;k: integer): dual; cdecl; external libmgl;
+/// Allocate memory and scanf the data from the string
+procedure  mgl_datac_set_values(dat: HADT;const val: PChar;nx: integer;ny: integer;nz: integer); cdecl; external libmgl;
+/// Returns pointer to internal data array
+function mgl_datac_data(dat: HADT): PDual; cdecl; external libmgl;
+/// Returns pointer to data element [i,j,k]
+function mgl_datac_value(dat: HADT;i: integer;j: integer;k: integer): PDual; cdecl; external libmgl;
+/// Set the data from HCDT objects for real and imaginary parts
+procedure  mgl_datac_set_ri(dat: HADT;const re: HMDT;const im: HMDT); cdecl; external libmgl;
+/// Set the data from HCDT objects as amplitude and phase of complex data
+procedure  mgl_datac_set_ap(dat: HADT;const abs: HMDT;const phi: HMDT); cdecl; external libmgl;
+/// Read data from tab-separated text file with auto determining size
+function  mgl_datac_read(dat: HADT;const fname: PChar): integer; cdecl; external libmgl;
+/// Read data from text file with size specified at beginning of the file
+function  mgl_datac_read_mat(dat: HADT;const fname: PChar;dim: integer): integer; cdecl; external libmgl;
+/// Read data from text file with specifeid size
+function  mgl_datac_read_dim(dat: HADT;const fname: PChar;mx: integer;my: integer;mz: integer): integer; cdecl; external libmgl;
+/// Read data from tab-separated text files with auto determining size which filenames are result of sprintf(fname,templ,t) where t=from:step:to
+function  mgl_datac_read_range(d: HADT;const templ: PChar;from: double;to_: double;step: double;as_slice: integer): integer; cdecl; external libmgl;
+/// Read data from tab-separated text files with auto determining size which filenames are satisfied to template (like "t_*.dat")
+function  mgl_datac_read_all(dat: HADT;const templ: PChar;as_slice: integer): integer; cdecl; external libmgl;
+/// Save whole data array (for ns=-1) or only ns-th slice to text file
+procedure  mgl_datac_save(const dat: HMDT;const fname: PChar;ns: integer); cdecl; external libmgl;
+/// Read data array from HDF file (parse HDF4 and HDF5 files)
+function  mgl_datac_read_hdf(d: HADT;const fname: PChar;const data: PChar): integer; cdecl; external libmgl;
+/// Save data to HDF file
+procedure  mgl_datac_save_hdf(const d: HMDT;const fname: PChar;const data: PChar;rewrite: integer); cdecl; external libmgl;
+/// Create or recreate the array with specified size and fill it by zero
+procedure  mgl_datac_create(dat: HADT;nx: integer;ny: integer;nz: integer); cdecl; external libmgl;
+/// Transpose dimensions of the data (generalization of Transpose)
+procedure  mgl_datac_transpose(dat: HADT;const dim: PChar); cdecl; external libmgl;
+/// Get sub-array of the data with given fixed indexes
+function  mgl_datac_subdata(const dat: HMDT;xx: integer;yy: integer;zz: integer): HADT; cdecl; external libmgl;
+/// Get sub-array of the data with given fixed indexes (like indirect access)
+function  mgl_datac_subdata_ext(const dat: HMDT;const xx: HMDT;const yy: HMDT;const zz: HMDT): HADT; cdecl; external libmgl;
+/// Get column (or slice) of the data filled by formulas of named columns
+function  mgl_datac_column(const dat: HMDT;const eq: PChar): HADT; cdecl; external libmgl;
+/// Get trace of the data array
+function  mgl_datac_trace(const d: HMDT): HADT; cdecl; external libmgl;
+/// Resize the data to new sizes
+function  mgl_datac_resize(const dat: HMDT;mx: integer;my: integer;mz: integer): HADT; cdecl; external libmgl;
+/// Resize the data to new sizes of box [x1,x2]*[y1,y2]*[z1,z2]
+function  mgl_datac_resize_box(const dat: HMDT;mx: integer;my: integer;mz: integer;x1: mreal;x2: mreal;y1: mreal;y2: mreal;z1: mreal;z2: mreal): HADT; cdecl; external libmgl;
+/// Get momentum (1D-array) of data along direction 'dir'. String looks like "x1" for median in x-direction, "x2" for width in x-dir and so on.
+function  mgl_datac_momentum(const dat: HMDT;dir: char;const how: PChar): HADT; cdecl; external libmgl;
+/// Get array which values is result of interpolation this for coordinates from other arrays
+function  mgl_datac_evaluate(const dat: HMDT;const idat: HMDT;const jdat: HMDT;const kdat: HMDT;norm: integer): HADT; cdecl; external libmgl;
+/// Get array which is result of summation in given direction or directions
+function  mgl_datac_sum(const dat: HMDT;const dir: PChar): HADT; cdecl; external libmgl;
+/// Get the data which is direct multiplication (like, d[i,j] = this[i]*a[j] and so on)
+function  mgl_datac_combine(const dat1: HMDT;const dat2: HMDT): HADT; cdecl; external libmgl;
+/// Set names for columns (slices)
+procedure  mgl_datac_set_id(d: HADT;const id: PChar); cdecl; external libmgl;
+/// Equidistantly fill the data to range [x1,x2] in direction dir
+procedure  mgl_datac_fill(dat: HADT;x1: dual;x2: dual;dir: char); cdecl; external libmgl;
+/// Modify the data by specified formula assuming x,y,z in range [r1,r2]
+procedure  mgl_datac_fill_eq(gr: HMGL;dat: HADT;const eq: PChar;const vdat: HMDT;const wdat: HMDT;const opt: PChar); cdecl; external libmgl;
+/// Modify the data by specified formula
+procedure  mgl_datac_modify(dat: HADT;const eq: PChar;dim: integer); cdecl; external libmgl;
+/// Modify the data by specified formula
+procedure  mgl_datac_modify_vw(dat: HADT;const eq: PChar;const vdat: HMDT;const wdat: HMDT); cdecl; external libmgl;
+/// Put value to data element(s)
+procedure  mgl_datac_put_val(dat: HADT;val: dual;i: integer;j: integer;k: integer); cdecl; external libmgl;
+/// Put array to data element(s)
+procedure  mgl_datac_put_dat(dat: HADT;const val: HMDT;i: integer;j: integer;k: integer); cdecl; external libmgl;
+/// Reduce size of the data
+procedure  mgl_datac_squeeze(dat: HADT;rx: integer;ry: integer;rz: integer;smooth: integer); cdecl; external libmgl;
+/// Extend data dimensions
+procedure  mgl_datac_extend(dat: HADT;n1: integer;n2: integer); cdecl; external libmgl;
+/// Insert data rows/columns/slices
+procedure  mgl_datac_insert(dat: HADT;dir: char;at: integer;num: integer); cdecl; external libmgl;
+/// Delete data rows/columns/slices
+procedure  mgl_datac_delete(dat: HADT;dir: char;at: integer;num: integer); cdecl; external libmgl;
+/// Joind another data array
+procedure  mgl_datac_join(dat: HADT;const d: HMDT); cdecl; external libmgl;
+/// Smooth the data on specified direction or directions
+procedure  mgl_datac_smooth(d: HADT;const dirs: PChar;delta: mreal); cdecl; external libmgl;
+/// Cumulative summation the data in given direction or directions
+procedure  mgl_datac_cumsum(dat: HADT;const dir: PChar); cdecl; external libmgl;
+/// Integrate (cumulative summation) the data in given direction or directions
+procedure  mgl_datac_integral(dat: HADT;const dir: PChar); cdecl; external libmgl;
+/// Differentiate the data in given direction or directions
+procedure  mgl_datac_diff(dat: HADT;const dir: PChar); cdecl; external libmgl;
+/// Double-differentiate (like Laplace operator) the data in given direction
+procedure  mgl_datac_diff2(dat: HADT;const dir: PChar); cdecl; external libmgl;
+/// Swap left and right part of the data in given direction (useful for Fourier spectrum)
+procedure  mgl_datac_swap(dat: HADT;const dir: PChar); cdecl; external libmgl;
+/// Roll data along direction dir by num slices
+procedure  mgl_datac_roll(dat: HADT;dir: char;num: integer); cdecl; external libmgl;
+/// Mirror the data in given direction (useful for Fourier spectrum)
+procedure  mgl_datac_mirror(dat: HADT;const dir: PChar); cdecl; external libmgl;
+/// Crop the data
+procedure  mgl_datac_crop(dat: HADT;n1: integer;n2: integer;dir: char); cdecl; external libmgl;
+/// Apply Hankel transform
+procedure  mgl_datac_hankel(dat: HADT;const dir: PChar); cdecl; external libmgl;
+/// Apply Fourier transform
+procedure  mgl_datac_fft(dat: HADT;const dir: PChar); cdecl; external libmgl;
+/// Find correlation between 2 data arrays
+function  mgl_datac_correl(const dat1: HMDT;const dat2: HMDT;const dir: PChar): HADT; cdecl; external libmgl;
+/// Calculate one step of diffraction by finite-difference method with parameter q
+procedure  mgl_datac_diffr(dat: HADT;const how: PChar;q: mreal); cdecl; external libmgl;
+function  mgl_datac_real(const dat: HMDT): HMDT; cdecl; external libmgl;
+function  mgl_datac_imag(const dat: HMDT): HMDT; cdecl; external libmgl;
+function  mgl_datac_abs(const dat: HMDT): HMDT; cdecl; external libmgl;
+function  mgl_datac_arg(const dat: HMDT): HMDT; cdecl; external libmgl;
+/// Interpolate by linear function the data to given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+function  mgl_datac_linear(const d: HMDT;x: mreal;y: mreal;z: mreal): dual; cdecl; external libmgl;
+/// Interpolate by linear function the data and return its derivatives at given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+function  mgl_datac_linear_ext(const d: HMDT;x: mreal;y: mreal;z: mreal;dx: Pdual;dy: Pdual;dz: Pdual): dual; cdecl; external libmgl;
+/// Interpolate by cubic spline the data to given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+function  mgl_datac_spline(const dat: HMDT;x: mreal;y: mreal;z: mreal): dual; cdecl; external libmgl;
+/// Interpolate by cubic spline the data and return its derivatives at given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+function  mgl_datac_spline_ext(const dat: HMDT;x: mreal;y: mreal;z: mreal;dx: Pdual;dy: Pdual;dz: Pdual): dual; cdecl; external libmgl;
+/// Prepare coefficients for global spline interpolation
+function  mgl_gsplinec_init(const x: HMDT;const v: HMDT): HADT; cdecl; external libmgl;
+/// Evaluate global spline (and its derivatives d1, d2 if not NULL) using prepared coefficients \a coef
+function  mgl_gsplinec(const coef: HMDT;dx: mreal;d1: Pdual;d2: Pdual): dual; cdecl; external libmgl;
+//-----------------------------------------------------------------------------
+/// Create HAEX object for expression evaluating
+function  mgl_create_cexpr(const expr: PChar): HAEX; cdecl; external libmgl;
+/// Delete HAEX object
+procedure  mgl_delete_cexpr(ex: HAEX); cdecl; external libmgl;
+/// Return value of expression for given x,y,z variables
+function  mgl_cexpr_eval(ex: HAEX;x: dual;y: dual;z: dual): dual; cdecl; external libmgl;
+/// Return value of expression for given variables
+function  mgl_cexpr_eval_v(ex: HAEX;vars: Pdual): dual; cdecl; external libmgl;
+//-----------------------------------------------------------------------------
+{== ../../include/mgl2/cont.h ==}
+//-----------------------------------------------------------------------------
+/// Print text along the curve in parametric form {x,y,z}
+procedure  mgl_text_xyz(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const text: PChar;const font: PChar;const opt: PChar); cdecl; external libmgl;
+procedure  mgl_textw_xyz(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const text: PWideChar;const font: PChar;const opt: PChar); cdecl; external libmgl;
+/// Print text along the curve in parametric form {x,y}
+procedure  mgl_text_xy(gr: HMGL;const x: HMDT;const y: HMDT;const text: PChar;const font: PChar;const opt: PChar); cdecl; external libmgl;
+procedure  mgl_textw_xy(gr: HMGL;const x: HMDT;const y: HMDT;const text: PWideChar;const font: PChar;const opt: PChar); cdecl; external libmgl;
+/// Print text along the curve
+procedure  mgl_text_y(gr: HMGL;const y: HMDT;const text: PChar;const font: PChar;const opt: PChar); cdecl; external libmgl;
+procedure  mgl_textw_y(gr: HMGL;const y: HMDT;const text: PWideChar;const font: PChar;const opt: PChar); cdecl; external libmgl;
+procedure  mgl_cont_gen(gr: HMGL;val: double;const a: HMDT;const x: HMDT;const y: HMDT;const z: HMDT;const stl: PChar); cdecl; external libmgl;
+procedure  mgl_contf_gen(gr: HMGL;v1: double;v2: double;const a: HMDT;const x: HMDT;const y: HMDT;const z: HMDT;const stl: PChar); cdecl; external libmgl;
+//void MGL_EXPORT mgl_contv_gen(HMGL gr, double v1, double v2, HCDT a, HCDT x, HCDT y, HCDT z, const char *stl)
+//void MGL_EXPORT mgl_axial_gen(HMGL gr, double v1, double v2, HCDT a, HCDT x, HCDT y, HCDT z, const char *stl)
+/// Draw manual contour lines for 2d data specified parametrically
+procedure  mgl_cont_xy_val(gr: HMGL;const v: HMDT;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw manual contour lines for 2d data
+procedure  mgl_cont_val(gr: HMGL;const v: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw contour lines for 2d data specified parametrically
+procedure  mgl_cont_xy(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw contour lines for 2d data
+procedure  mgl_cont(gr: HMGL;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw manual solid contours for 2d data specified parametrically
+procedure  mgl_contf_xy_val(gr: HMGL;const v: HMDT;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw manual solid contours for 2d data
+procedure  mgl_contf_val(gr: HMGL;const v: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw solid contours for 2d data specified parametrically
+procedure  mgl_contf_xy(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw solid contours for 2d data
+procedure  mgl_contf(gr: HMGL;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw manual solid contours for 2d data specified parametrically with manual colors
+procedure  mgl_contd_xy_val(gr: HMGL;const v: HMDT;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw manual solid contours for 2d data with manual colors
+procedure  mgl_contd_val(gr: HMGL;const v: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw solid contours for 2d data specified parametrically with manual colors
+procedure  mgl_contd_xy(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw solid contours for 2d data with manual colors
+procedure  mgl_contd(gr: HMGL;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw manual contour tubes for 2d data specified parametrically
+procedure  mgl_contv_xy_val(gr: HMGL;const v: HMDT;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw manual contour tubes for 2d data
+procedure  mgl_contv_val(gr: HMGL;const v: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw contour tubes for 2d data specified parametrically
+procedure  mgl_contv_xy(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw contour tubes for 2d data
+procedure  mgl_contv(gr: HMGL;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw manual axial-symmetric isosurfaces for 2d data specified parametrically
+procedure  mgl_axial_xy_val(gr: HMGL;const v: HMDT;const x: HMDT;const y: HMDT;const a: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw manual axial-symmetric isosurfaces for 2d data
+procedure  mgl_axial_val(gr: HMGL;const v: HMDT;const a: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw axial-symmetric isosurfaces for 2d data specified parametrically
+procedure  mgl_axial_xy(gr: HMGL;const x: HMDT;const y: HMDT;const a: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw axial-symmetric isosurfaces for 2d data
+procedure  mgl_axial(gr: HMGL;const a: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw surface of curve {r,z} rotatation around axis
+procedure  mgl_torus(gr: HMGL;const r: HMDT;const z: HMDT;const col: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw grid lines for density plot at slice for 3d data specified parametrically
+procedure  mgl_grid3_xyz(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const a: HMDT;const stl: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw grid lines for density plot at slice for 3d data
+procedure  mgl_grid3(gr: HMGL;const a: HMDT;const stl: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw density plot at slice for 3d data specified parametrically
+procedure  mgl_dens3_xyz(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const a: HMDT;const stl: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw density plot at slice for 3d data
+procedure  mgl_dens3(gr: HMGL;const a: HMDT;const stl: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw manual contour lines at slice for 3d data specified parametrically
+procedure  mgl_cont3_xyz_val(gr: HMGL;const v: HMDT;const x: HMDT;const y: HMDT;const z: HMDT;const a: HMDT;const sch: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw manual contour lines at slice for 3d data
+procedure  mgl_cont3_val(gr: HMGL;const v: HMDT;const a: HMDT;const sch: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw contour lines at slice for 3d data specified parametrically
+procedure  mgl_cont3_xyz(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const a: HMDT;const sch: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw contour lines at slice for 3d data
+procedure  mgl_cont3(gr: HMGL;const a: HMDT;const sch: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw manual solid contours at slice for 3d data specified parametrically
+procedure  mgl_contf3_xyz_val(gr: HMGL;const v: HMDT;const x: HMDT;const y: HMDT;const z: HMDT;const a: HMDT;const sch: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw manual solid contours at slice for 3d data
+procedure  mgl_contf3_val(gr: HMGL;const v: HMDT;const a: HMDT;const sch: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw solid contours at slice for 3d data specified parametrically
+procedure  mgl_contf3_xyz(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const a: HMDT;const sch: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw solid contours at slice for 3d data
+procedure  mgl_contf3(gr: HMGL;const a: HMDT;const sch: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+{== ../../include/mgl2/fit.h ==}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+function  mgl_fit_1(gr: HMGL;const y: HMDT;const eq: PChar;const vars: PChar;ini: HMDT;const opt: PChar): HMDT; cdecl; external libmgl;
+function  mgl_fit_2(gr: HMGL;const z: HMDT;const eq: PChar;const vars: PChar;ini: HMDT;const opt: PChar): HMDT; cdecl; external libmgl;
+function  mgl_fit_3(gr: HMGL;const a: HMDT;const eq: PChar;const vars: PChar;ini: HMDT;const opt: PChar): HMDT; cdecl; external libmgl;
+function  mgl_fit_xy(gr: HMGL;const x: HMDT;const y: HMDT;const eq: PChar;const vars: PChar;ini: HMDT;const opt: PChar): HMDT; cdecl; external libmgl;
+function  mgl_fit_xyz(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const eq: PChar;const vars: PChar;ini: HMDT;const opt: PChar): HMDT; cdecl; external libmgl;
+function  mgl_fit_xyza(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const a: HMDT;const eq: PChar;const vars: PChar;ini: HMDT;const opt: PChar): HMDT; cdecl; external libmgl;
+function  mgl_fit_ys(gr: HMGL;const y: HMDT;const s: HMDT;const eq: PChar;const vars: PChar;ini: HMDT;const opt: PChar): HMDT; cdecl; external libmgl;
+function  mgl_fit_xys(gr: HMGL;const x: HMDT;const y: HMDT;const s: HMDT;const eq: PChar;const vars: PChar;ini: HMDT;const opt: PChar): HMDT; cdecl; external libmgl;
+function  mgl_fit_xyzs(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const s: HMDT;const eq: PChar;const vars: PChar;ini: HMDT;const opt: PChar): HMDT; cdecl; external libmgl;
+function  mgl_fit_xyzas(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const a: HMDT;const s: HMDT;const eq: PChar;const vars: PChar;ini: HMDT;const opt: PChar): HMDT; cdecl; external libmgl;
+function mgl_get_fit(gr: HMGL): PChar; cdecl; external libmgl;
+function  mgl_hist_x(gr: HMGL;const x: HMDT;const a: HMDT;const opt: PChar): HMDT; cdecl; external libmgl;
+function  mgl_hist_xy(gr: HMGL;const x: HMDT;const y: HMDT;const a: HMDT;const opt: PChar): HMDT; cdecl; external libmgl;
+function  mgl_hist_xyz(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const a: HMDT;const opt: PChar): HMDT; cdecl; external libmgl;
+procedure  mgl_puts_fit(gr: HMGL;x: double;y: double;z: double;const prefix: PChar;const font: PChar;size: double); cdecl; external libmgl;
+function  mgl_get_fit_chi(): mreal; cdecl; external libmgl;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+{== ../../include/mgl2/plot.h ==}
+//-----------------------------------------------------------------------------
+/// Draw curve for formula with x in x-axis range
+procedure  mgl_fplot(gr: HMGL;const eqY: PChar;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw curve for formulas parametrically depended on t in range [0,1]
+procedure  mgl_fplot_xyz(gr: HMGL;const eqX: PChar;const eqY: PChar;const eqZ: PChar;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw radar chart (plot in curved coordinates)
+procedure  mgl_radar(graph: HMGL;const a: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw usual curve {x,y,z}
+procedure  mgl_plot_xyz(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw usual curve {x,y}
+procedure  mgl_plot_xy(graph: HMGL;const x: HMDT;const y: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw usual curve {x,y} with x in x-axis range
+procedure  mgl_plot(graph: HMGL;const y: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw curve {x,y,z} which is colored by c (like tension plot)
+procedure  mgl_tens_xyz(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const c: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw curve {x,y} which is colored by c (like tension plot)
+procedure  mgl_tens_xy(graph: HMGL;const x: HMDT;const y: HMDT;const c: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw curve {x,y} with x in x-axis range which is colored by c (like tension plot)
+procedure  mgl_tens(graph: HMGL;const y: HMDT;const c: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw tape(s) which rotates as (bi-)normales of curve {x,y,z}
+procedure  mgl_tape_xyz(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw tape(s) which rotates as (bi-)normales of curve {x,y}
+procedure  mgl_tape_xy(graph: HMGL;const x: HMDT;const y: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw tape(s) which rotates as (bi-)normales of curve {x,y} with x in x-axis range
+procedure  mgl_tape(graph: HMGL;const y: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw box-plot (special 5-value plot used in statistic) for data specified parametrically
+procedure  mgl_boxplot_xy(graph: HMGL;const x: HMDT;const a: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw box-plot (special 5-value plot used in statistic)
+procedure  mgl_boxplot(graph: HMGL;const a: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Fill area between curve {x,y,z} and axis plane
+procedure  mgl_area_xyz(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Fill area between curve {x,y} and axis plane
+procedure  mgl_area_xy(graph: HMGL;const x: HMDT;const y: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Fill area between curve {x,y} with x in x-axis range and axis plane
+procedure  mgl_area(graph: HMGL;const y: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Fill area (draw ribbon) between curves {x1,y1,z1} and {x2,y2,z2}
+procedure  mgl_region_3d(graph: HMGL;const x1: HMDT;const y1: HMDT;const z1: HMDT;const x2: HMDT;const y2: HMDT;const z2: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Fill area between curves {x,y1} and {x,y2}
+procedure  mgl_region_xy(graph: HMGL;const x: HMDT;const y1: HMDT;const y2: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Fill area between curves {x,y1} and {x,y2} with x in x-axis range
+procedure  mgl_region(graph: HMGL;const y1: HMDT;const y2: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw vertical lines from points {x,y,z} to axis plane
+procedure  mgl_stem_xyz(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw vertical lines from points {x,y} to axis plane
+procedure  mgl_stem_xy(graph: HMGL;const x: HMDT;const y: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw vertical lines from points {x,y} with x in x-axis range to axis plane
+procedure  mgl_stem(graph: HMGL;const y: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw stairs for points in arrays {x,y,z}
+procedure  mgl_step_xyz(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw stairs for points in arrays {x,y}
+procedure  mgl_step_xy(graph: HMGL;const x: HMDT;const y: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw stairs for points in arrays {x,y} with x in x-axis range
+procedure  mgl_step(graph: HMGL;const y: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw vertical bars from points {x,y,z} to axis plane
+procedure  mgl_bars_xyz(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw vertical bars from points {x,y} to axis plane
+procedure  mgl_bars_xy(graph: HMGL;const x: HMDT;const y: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw vertical bars from points {x,y} with x in x-axis range to axis plane
+procedure  mgl_bars(graph: HMGL;const y: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw horizontal bars from points {v,y} to axis plane
+procedure  mgl_barh_yx(graph: HMGL;const y: HMDT;const v: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw horizontal bars from points {v,y} with y in y-axis range to axis plane
+procedure  mgl_barh(graph: HMGL;const v: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw Open-High-Low-Close (OHLC) diagram
+procedure  mgl_ohlc_x(graph: HMGL;const x: HMDT;const open: HMDT;const high: HMDT;const low: HMDT;const close: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw Open-High-Low-Close (OHLC) diagram with x in x-axis range
+procedure  mgl_ohlc(graph: HMGL;const open: HMDT;const high: HMDT;const low: HMDT;const close: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw chart for data a
+procedure  mgl_chart(graph: HMGL;const a: HMDT;const col: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw error boxes {ex,ey} at points {x,y}
+procedure  mgl_error_exy(graph: HMGL;const x: HMDT;const y: HMDT;const ex: HMDT;const ey: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw error boxes {ey} at points {x,y}
+procedure  mgl_error_xy(graph: HMGL;const x: HMDT;const y: HMDT;const ey: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw error boxes {ey} at points {x,y} with x in x-axis range
+procedure  mgl_error(graph: HMGL;const y: HMDT;const ey: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw marks with size r at points {x,y,z}
+procedure  mgl_mark_xyz(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const r: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw marks with size r at points {x,y}
+procedure  mgl_mark_xy(graph: HMGL;const x: HMDT;const y: HMDT;const r: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw marks with size r at points {x,y} with x in x-axis range
+procedure  mgl_mark_y(graph: HMGL;const y: HMDT;const r: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw tube with variable radius r around curve {x,y,z}
+procedure  mgl_tube_xyzr(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const r: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw tube with variable radius r around curve {x,y}
+procedure  mgl_tube_xyr(graph: HMGL;const x: HMDT;const y: HMDT;const r: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw tube with variable radius r around curve {x,y} with x in x-axis range
+procedure  mgl_tube_r(graph: HMGL;const y: HMDT;const r: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw tube with constant radius r around curve {x,y,z}
+procedure  mgl_tube_xyz(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;r: double;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw tube with constant radius r around curve {x,y}
+procedure  mgl_tube_xy(graph: HMGL;const x: HMDT;const y: HMDT;r: double;const penl: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw tube with constant radius r around curve {x,y} with x in x-axis range
+procedure  mgl_tube(graph: HMGL;const y: HMDT;r: double;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw candle plot for data specified parametrically
+procedure  mgl_candle_xyv(gr: HMGL;const x: HMDT;const v1: HMDT;const v2: HMDT;const y1: HMDT;const y2: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw candle plot
+procedure  mgl_candle_yv(gr: HMGL;const v1: HMDT;const v2: HMDT;const y1: HMDT;const y2: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw candle plot with v1=v[i], v2=v[i+1]
+procedure  mgl_candle(gr: HMGL;const v: HMDT;const y1: HMDT;const y2: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+//-----------------------------------------------------------------------------
+{== ../../include/mgl2/surf.h ==}
+//-----------------------------------------------------------------------------
+/// Draw surface by formula with x,y in axis range
+procedure  mgl_fsurf(graph: HMGL;const fz: PChar;const stl: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw surface by formulas parametrically depended on u,v in range [0,1]
+procedure  mgl_fsurf_xyz(graph: HMGL;const fx: PChar;const fy: PChar;const fz: PChar;const stl: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw grid lines for density plot of 2d data specified parametrically
+procedure  mgl_grid_xy(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const stl: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw grid lines for density plot of 2d data
+procedure  mgl_grid(graph: HMGL;const a: HMDT;const stl: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw mesh lines for 2d data specified parametrically
+procedure  mgl_mesh_xy(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw mesh lines for 2d data
+procedure  mgl_mesh(graph: HMGL;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw mesh lines for 2d data specified parametrically
+procedure  mgl_fall_xy(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw mesh lines for 2d data
+procedure  mgl_fall(graph: HMGL;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw belts for 2d data specified parametrically
+procedure  mgl_belt_xy(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw belts for 2d data
+procedure  mgl_belt(graph: HMGL;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw surface for 2d data specified parametrically with color proportional to z
+procedure  mgl_surf_xy(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw surface for 2d data with color proportional to z
+procedure  mgl_surf(graph: HMGL;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw density plot for 2d data specified parametrically
+procedure  mgl_dens_xy(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw density plot for 2d data
+procedure  mgl_dens(graph: HMGL;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw vertical boxes for 2d data specified parametrically
+procedure  mgl_boxs_xy(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw vertical boxes for 2d data
+procedure  mgl_boxs(graph: HMGL;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw vertical tiles for 2d data specified parametrically
+procedure  mgl_tile_xy(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw vertical tiles for 2d data
+procedure  mgl_tile(graph: HMGL;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw vertical tiles with variable size r for 2d data specified parametrically
+procedure  mgl_tiles_xy(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const r: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw vertical tiles with variable size r for 2d data
+procedure  mgl_tiles(graph: HMGL;const z: HMDT;const r: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw surface for 2d data specified parametrically with color proportional to c
+procedure  mgl_surfc_xy(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const c: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw surface for 2d data with color proportional to c
+procedure  mgl_surfc(graph: HMGL;const z: HMDT;const c: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw surface for 2d data specified parametrically with alpha proportional to c
+procedure  mgl_surfa_xy(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const c: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw surface for 2d data with alpha proportional to c
+procedure  mgl_surfa(graph: HMGL;const z: HMDT;const c: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw density plot for spectra-gramm specified parametrically
+procedure  mgl_stfa_xy(graph: HMGL;const x: HMDT;const y: HMDT;const re: HMDT;const im: HMDT;dn: integer;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw density plot for spectra-gramm
+procedure  mgl_stfa(graph: HMGL;const re: HMDT;const im: HMDT;dn: integer;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Color map of matrix a to matrix b, both matrix can parametrically depend on coordinates
+procedure  mgl_map_xy(graph: HMGL;const x: HMDT;const y: HMDT;const a: HMDT;const b: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Color map of matrix a to matrix b
+procedure  mgl_map(graph: HMGL;const a: HMDT;const b: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+//-----------------------------------------------------------------------------
+{== ../../include/mgl2/volume.h ==}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+/// Draw isosurface for 3d data specified parametrically
+procedure  mgl_surf3_xyz_val(graph: HMGL;Val: double;const x: HMDT;const y: HMDT;const z: HMDT;const a: HMDT;const stl: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw isosurface for 3d data
+procedure  mgl_surf3_val(graph: HMGL;Val: double;const a: HMDT;const stl: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw isosurfaces for 3d data specified parametrically
+procedure  mgl_surf3_xyz(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const a: HMDT;const stl: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw isosurfaces for 3d data
+procedure  mgl_surf3(graph: HMGL;const a: HMDT;const stl: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw isosurface for 3d data specified parametrically with alpha proportional to b
+procedure  mgl_surf3a_xyz_val(graph: HMGL;Val: double;const x: HMDT;const y: HMDT;const z: HMDT;const a: HMDT;const b: HMDT;const stl: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw isosurface for 3d data with alpha proportional to b
+procedure  mgl_surf3a_val(graph: HMGL;Val: double;const a: HMDT;const b: HMDT;const stl: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw isosurfaces for 3d data specified parametrically with alpha proportional to b
+procedure  mgl_surf3a_xyz(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const a: HMDT;const b: HMDT;const stl: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw isosurfaces for 3d data with alpha proportional to b
+procedure  mgl_surf3a(graph: HMGL;const a: HMDT;const b: HMDT;const stl: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw isosurface for 3d data specified parametrically with color proportional to b
+procedure  mgl_surf3c_xyz_val(graph: HMGL;Val: double;const x: HMDT;const y: HMDT;const z: HMDT;const a: HMDT;const b: HMDT;const stl: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw isosurface for 3d data with color proportional to b
+procedure  mgl_surf3c_val(graph: HMGL;Val: double;const a: HMDT;const b: HMDT;const stl: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw isosurfaces for 3d data specified parametrically with color proportional to b
+procedure  mgl_surf3c_xyz(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const a: HMDT;const b: HMDT;const stl: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw isosurfaces for 3d data with color proportional to b
+procedure  mgl_surf3c(graph: HMGL;const a: HMDT;const b: HMDT;const stl: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw a semi-transparent cloud for 3d data specified parametrically
+procedure  mgl_cloud_xyz(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const a: HMDT;const stl: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw a semi-transparent cloud for 3d data
+procedure  mgl_cloud(graph: HMGL;const a: HMDT;const stl: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw isosurface for 3d beam in curvilinear coordinates
+procedure  mgl_beam_val(graph: HMGL;Val: double;const tr: HMDT;const g1: HMDT;const g2: HMDT;const a: HMDT;r: double;const stl: PChar;norm: integer); cdecl; external libmgl;
+/// Draw several isosurfaces for 3d beam in curvilinear coordinates
+procedure  mgl_beam(graph: HMGL;const tr: HMDT;const g1: HMDT;const g2: HMDT;const a: HMDT;r: double;const stl: PChar;norm: integer;num: integer); cdecl; external libmgl;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+{== ../../include/mgl2/vect.h ==}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+/// Plot vectors at position {x,y} along {ax,ay} with length/color proportional to |a|
+procedure  mgl_traj_xy(gr: HMGL;const x: HMDT;const y: HMDT;const ax: HMDT;const ay: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Plot vectors at position {x,y,z} along {ax,ay,az} with length/color proportional to |a|
+procedure  mgl_traj_xyz(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const ax: HMDT;const ay: HMDT;const az: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Plot vector field {ax,ay} parametrically depended on coordinate {x,y} with length/color proportional to |a|
+procedure  mgl_vect_xy(gr: HMGL;const x: HMDT;const y: HMDT;const ax: HMDT;const ay: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Plot vector field {ax,ay} with length/color proportional to |a|
+procedure  mgl_vect_2d(gr: HMGL;const ax: HMDT;const ay: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Plot vector field {ax,ay,az} parametrically depended on coordinate {x,y,z} with length/color proportional to |a|
+procedure  mgl_vect_xyz(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const ax: HMDT;const ay: HMDT;const az: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Plot vector field {ax,ay,az} with length/color proportional to |a|
+procedure  mgl_vect_3d(gr: HMGL;const ax: HMDT;const ay: HMDT;const az: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Plot flows for vector field {ax,ay} parametrically depended on coordinate {x,y} with color proportional to |a|
+procedure  mgl_flow_xy(gr: HMGL;const x: HMDT;const y: HMDT;const ax: HMDT;const ay: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Plot flows for vector field {ax,ay} with color proportional to |a|
+procedure  mgl_flow_2d(gr: HMGL;const ax: HMDT;const ay: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Plot flows for vector field {ax,ay,az} parametrically depended on coordinate {x,y,z} with color proportional to |a|
+procedure  mgl_flow_xyz(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const ax: HMDT;const ay: HMDT;const az: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Plot flows for vector field {ax,ay,az} with color proportional to |a|
+procedure  mgl_flow_3d(gr: HMGL;const ax: HMDT;const ay: HMDT;const az: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Plot flow from point p for vector field {ax,ay} parametrically depended on coordinate {x,y} with color proportional to |a|
+procedure  mgl_flowp_xy(gr: HMGL;x0: double;y0: double;z0: double;const x: HMDT;const y: HMDT;const ax: HMDT;const ay: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Plot flow from point p for vector field {ax,ay} with color proportional to |a|
+procedure  mgl_flowp_2d(gr: HMGL;x0: double;y0: double;z0: double;const ax: HMDT;const ay: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Plot flow from point p for vector field {ax,ay,az} parametrically depended on coordinate {x,y,z} with color proportional to |a|
+procedure  mgl_flowp_xyz(gr: HMGL;x0: double;y0: double;z0: double;const x: HMDT;const y: HMDT;const z: HMDT;const ax: HMDT;const ay: HMDT;const az: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Plot flow from point p for vector field {ax,ay,az} with color proportional to |a|
+procedure  mgl_flowp_3d(gr: HMGL;x0: double;y0: double;z0: double;const ax: HMDT;const ay: HMDT;const az: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Plot flow pipes for vector field {ax,ay} parametrically depended on coordinate {x,y} with color and radius proportional to |a|
+procedure  mgl_pipe_xy(gr: HMGL;const x: HMDT;const y: HMDT;const ax: HMDT;const ay: HMDT;const sch: PChar;r0: double;const opt: PChar); cdecl; external libmgl;
+/// Plot flow pipes for vector field {ax,ay} with color and radius proportional to |a|
+procedure  mgl_pipe_2d(gr: HMGL;const ax: HMDT;const ay: HMDT;const sch: PChar;r0: double;const opt: PChar); cdecl; external libmgl;
+/// Plot flow pipes for vector field {ax,ay,az} parametrically depended on coordinate {x,y,z} with color and radius proportional to |a|
+procedure  mgl_pipe_xyz(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const ax: HMDT;const ay: HMDT;const az: HMDT;const sch: PChar;r0: double;const opt: PChar); cdecl; external libmgl;
+/// Plot flow pipes for vector field {ax,ay,az} with color and radius proportional to |a|
+procedure  mgl_pipe_3d(gr: HMGL;const ax: HMDT;const ay: HMDT;const az: HMDT;const sch: PChar;r0: double;const opt: PChar); cdecl; external libmgl;
+/// Plot flows for gradient of scalar field phi parametrically depended on coordinate {x,y,z}
+procedure  mgl_grad_xyz(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const ph: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Plot flows for gradient of scalar field phi parametrically depended on coordinate {x,y}
+procedure  mgl_grad_xy(gr: HMGL;const x: HMDT;const y: HMDT;const ph: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Plot flows for gradient of scalar field phi
+procedure  mgl_grad(gr: HMGL;const ph: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw vector plot at slice for 3d data specified parametrically
+procedure  mgl_vect3_xyz(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const ax: HMDT;const ay: HMDT;const az: HMDT;const sch: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw vector plot at slice for 3d data
+procedure  mgl_vect3(gr: HMGL;const ax: HMDT;const ay: HMDT;const az: HMDT;const sch: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+{== ../../include/mgl2/prim.h ==}
+//-----------------------------------------------------------------------------
+/// Draws the mark at position {x,y,z}
+procedure  mgl_mark(gr: HMGL;x: double;y: double;z: double;const mark: PChar); cdecl; external libmgl;
+/// Draws red point (ball) at position {x,y,z}
+procedure  mgl_ball(gr: HMGL;x: double;y: double;z: double); cdecl; external libmgl;
+/// Draws the line between 2 points by specified pen
+procedure  mgl_line(gr: HMGL;x1: double;y1: double;z1: double;x2: double;y2: double;z2: double;const pen: PChar;n: integer); cdecl; external libmgl;
+/// Draws the spline curve between 2 points by specified pen
+procedure  mgl_curve(gr: HMGL;x1: double;y1: double;z1: double;dx1: double;dy1: double;dz1: double;x2: double;y2: double;z2: double;dx2: double;dy2: double;dz2: double;const pen: PChar;n: integer); cdecl; external libmgl;
+/// Draws the 3d error box {ex,ey,ez} for point {x,y,z}
+procedure  mgl_error_box(gr: HMGL;x: double;y: double;z: double;ex: double;ey: double;ez: double;const pen: PChar); cdecl; external libmgl;
+/// Draws the face between points with color stl (include interpolation up to 4 colors).
+procedure  mgl_face(gr: HMGL;x0: double;y0: double;z0: double;x1: double;y1: double;z1: double;x2: double;y2: double;z2: double;x3: double;y3: double;z3: double;const stl: PChar); cdecl; external libmgl;
+/// Draws the face in y-z plane at point p with color stl (include interpolation up to 4 colors).
+procedure  mgl_facex(gr: HMGL;x0: double;y0: double;z0: double;wy: double;wz: double;const stl: PChar;dx: double;dy: double); cdecl; external libmgl;
+/// Draws the face in x-z plane at point p with color stl (include interpolation up to 4 colors).
+procedure  mgl_facey(gr: HMGL;x0: double;y0: double;z0: double;wx: double;wz: double;const stl: PChar;dx: double;dy: double); cdecl; external libmgl;
+/// Draws the face in x-y plane at point p with color stl (include interpolation up to 4 colors).
+procedure  mgl_facez(gr: HMGL;x0: double;y0: double;z0: double;wx: double;wy: double;const stl: PChar;dx: double;dy: double); cdecl; external libmgl;
+/// Draws the sphere at point {x,y,z} with color stl and radius r
+procedure  mgl_sphere(gr: HMGL;x: double;y: double;z: double;r: double;const stl: PChar); cdecl; external libmgl;
+/// Draws the drop at point {x,y,z} in direction {dx,dy,dz} with color stl and radius r
+procedure  mgl_drop(gr: HMGL;x: double;y: double;z: double;dx: double;dy: double;dz: double;r: double;const stl: PChar;shift: double;ap: double); cdecl; external libmgl;
+/// Draws the cone between points p1,p2 with radius r1,r2 and with style stl
+procedure  mgl_cone(gr: HMGL;x1: double;y1: double;z1: double;x2: double;y2: double;z2: double;r1: double;r2: double;const stl: PChar); cdecl; external libmgl;
+/// Draws the ellipse between points p1,p2 with color stl and width r
+procedure  mgl_ellipse(gr: HMGL;x1: double;y1: double;z1: double;x2: double;y2: double;z2: double;r: double;const stl: PChar); cdecl; external libmgl;
+/// Draws the rhomb between points p1,p2 with color stl and width r
+procedure  mgl_rhomb(gr: HMGL;x1: double;y1: double;z1: double;x2: double;y2: double;z2: double;r: double;const stl: PChar); cdecl; external libmgl;
+/// Draws the polygon based on points p1,p2 with color stl
+procedure  mgl_polygon(gr: HMGL;x1: double;y1: double;z1: double;x2: double;y2: double;z2: double;n: integer;const stl: PChar); cdecl; external libmgl;
+procedure  mgl_arc_ext(gr: HMGL;x0: double;y0: double;z0: double;xr: double;yr: double;zr: double;x1: double;y1: double;z1: double;a: double;const stl: PChar); cdecl; external libmgl;
+procedure  mgl_arc(gr: HMGL;x0: double;y0: double;x1: double;y1: double;a: double;const stl: PChar); cdecl; external libmgl;
+/// Draw cones from points {x,y,z} to axis plane
+procedure  mgl_cones_xyz(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw cones from points {x,z} to axis plane
+procedure  mgl_cones_xz(graph: HMGL;const x: HMDT;const z: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw cones from points {x,z} with x in x-axis range to axis plane
+procedure  mgl_cones(graph: HMGL;const z: HMDT;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Plot dew drops for vector field {ax,ay} parametrically depended on coordinate {x,y}
+procedure  mgl_dew_xy(gr: HMGL;const x: HMDT;const y: HMDT;const ax: HMDT;const ay: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Plot dew drops for vector field {ax,ay}
+procedure  mgl_dew_2d(gr: HMGL;const ax: HMDT;const ay: HMDT;const sch: PChar;const optl: PChar); cdecl; external libmgl;
+/// Print text in position {x,y,z} with specified font
+procedure  mgl_puts_dir(graph: HMGL;x: double;y: double;z: double;dx: double;dy: double;dz: double;const text: PChar;const font: PChar;size: double); cdecl; external libmgl;
+procedure  mgl_putsw_dir(graph: HMGL;x: double;y: double;z: double;dx: double;dy: double;dz: double;const text: PWideChar;const font: PChar;size: double); cdecl; external libmgl;
+/// Draw textual marks with size r at points {x,y,z}
+procedure  mgl_textmark_xyzr(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const r: HMDT;const text: PChar;const fnt: PChar;const opt: PChar); cdecl; external libmgl;
+procedure  mgl_textmarkw_xyzr(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const r: HMDT;const text: PWideChar;const fnt: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw textual marks with size r at points {x,y}
+procedure  mgl_textmark_xyr(graph: HMGL;const x: HMDT;const y: HMDT;const r: HMDT;const text: PChar;const fnt: PChar;const opt: PChar); cdecl; external libmgl;
+procedure  mgl_textmarkw_xyr(graph: HMGL;const x: HMDT;const y: HMDT;const r: HMDT;const text: PWideChar;const fnt: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw textual marks with size r at points {x,y} with x in x-axis range
+procedure  mgl_textmark_yr(graph: HMGL;const y: HMDT;const r: HMDT;const text: PChar;const fnt: PChar;const opt: PChar); cdecl; external libmgl;
+procedure  mgl_textmarkw_yr(graph: HMGL;const y: HMDT;const r: HMDT;const text: PWideChar;const fnt: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw textual marks with size r=1 at points {x,y} with x in x-axis range
+procedure  mgl_textmark(graph: HMGL;const y: HMDT;const text: PChar;const fnt: PChar;const opt: PChar); cdecl; external libmgl;
+procedure  mgl_textmarkw(graph: HMGL;const y: HMDT;const text: PWideChar;const fnt: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw labels for points coordinate(s) at points {x,y,z}
+procedure  mgl_label_xyz(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const text: PChar;const fnt: PChar;const opt: PChar); cdecl; external libmgl;
+procedure  mgl_labelw_xyz(graph: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const text: PWideChar;const fnt: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw labels for points coordinate(s) at points {x,y}
+procedure  mgl_label_xy(graph: HMGL;const x: HMDT;const y: HMDT;const text: PChar;const fnt: PChar;const opt: PChar); cdecl; external libmgl;
+procedure  mgl_labelw_xy(graph: HMGL;const x: HMDT;const y: HMDT;const text: PWideChar;const fnt: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw labels for points coordinate(s) at points {x,y} with x in x-axis range
+procedure  mgl_label_y(graph: HMGL;const y: HMDT;const text: PChar;const fnt: PChar;const opt: PChar); cdecl; external libmgl;
+procedure  mgl_labelw_y(graph: HMGL;const y: HMDT;const text: PWideChar;const fnt: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw table for values val along given direction with row labels text at position {x,y}
+procedure  mgl_table(gr: HMGL;x: double;y: double;const val: HMDT;const text: PChar;const fnt: PChar;const opt: PChar); cdecl; external libmgl;
+procedure  mgl_tablew(gr: HMGL;x: double;y: double;const val: HMDT;const text: PWideChar;const fnt: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draws bitmap (logo) which is stretched along whole axis range
+procedure  mgl_logo(gr: HMGL;w: integer;h: integer;const rgba: PByte;smooth: integer;const opt: PChar); cdecl; external libmgl;
+procedure  mgl_logo_file(gr: HMGL;const fname: PChar;smooth: integer;const opt: PChar); cdecl; external libmgl;
+//-----------------------------------------------------------------------------
+{== ../../include/mgl2/other.h ==}
+//-----------------------------------------------------------------------------
+/// Draw triangle mesh for points in arrays {x,y,z} with specified color c.
+procedure  mgl_triplot_xyzc(gr: HMGL;const nums: HMDT;const x: HMDT;const y: HMDT;const z: HMDT;const c: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw triangle mesh for points in arrays {x,y,z} with color proportional to z.
+procedure  mgl_triplot_xyz(gr: HMGL;const nums: HMDT;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw triangle mesh for points in arrays {x,y}
+procedure  mgl_triplot_xy(gr: HMGL;const nums: HMDT;const x: HMDT;const y: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw quad mesh for points in arrays {x,y,z} with specified color c.
+procedure  mgl_quadplot_xyzc(gr: HMGL;const nums: HMDT;const x: HMDT;const y: HMDT;const z: HMDT;const c: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw quad mesh for points in arrays {x,y,z} with color proportional to z.
+procedure  mgl_quadplot_xyz(gr: HMGL;const nums: HMDT;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw quad mesh for points in arrays {x,y}.
+procedure  mgl_quadplot_xy(gr: HMGL;const nums: HMDT;const x: HMDT;const y: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw manual contour lines for triangle mesh for points in arrays {x,y,z} with specified color c.
+procedure  mgl_tricont_xyzcv(gr: HMGL;const v: HMDT;const nums: HMDT;const x: HMDT;const y: HMDT;const z: HMDT;const c: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw manual contour lines for triangle mesh for points in arrays {x,y,z}.
+procedure  mgl_tricont_xycv(gr: HMGL;const v: HMDT;const nums: HMDT;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw contour lines for triangle mesh for points in arrays {x,y,z} with specified color c.
+procedure  mgl_tricont_xyzc(gr: HMGL;const nums: HMDT;const x: HMDT;const y: HMDT;const z: HMDT;const c: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw contour lines for triangle mesh for points in arrays {x,y,z}.
+procedure  mgl_tricont_xyc(gr: HMGL;const nums: HMDT;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw manual contour tubes for triangle mesh for points in arrays {x,y,z} with specified color c.
+procedure  mgl_tricontv_xyzcv(gr: HMGL;const v: HMDT;const nums: HMDT;const x: HMDT;const y: HMDT;const z: HMDT;const c: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw manual contour tubes for triangle mesh for points in arrays {x,y,z}.
+procedure  mgl_tricontv_xycv(gr: HMGL;const v: HMDT;const nums: HMDT;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw contour tubes for triangle mesh for points in arrays {x,y,z} with specified color c.
+procedure  mgl_tricontv_xyzc(gr: HMGL;const nums: HMDT;const x: HMDT;const y: HMDT;const z: HMDT;const c: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw contour tubes for triangle mesh for points in arrays {x,y,z}.
+procedure  mgl_tricontv_xyc(gr: HMGL;const nums: HMDT;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw dots in points {x,y,z}.
+procedure  mgl_dots(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw semitransparent dots in points {x,y,z} with specified alpha a.
+procedure  mgl_dots_a(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const a: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw semitransparent dots in points {x,y,z} with specified color c and alpha a.
+procedure  mgl_dots_ca(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const c: HMDT;const a: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw surface reconstructed for points in arrays {x,y,z}.
+procedure  mgl_crust(gr: HMGL;const x: HMDT;const y: HMDT;const z: HMDT;const sch: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw density plot for data at x = sVal
+procedure  mgl_dens_x(graph: HMGL;const a: HMDT;const stl: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw density plot for data at y = sVal
+procedure  mgl_dens_y(graph: HMGL;const a: HMDT;const stl: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw density plot for data at z = sVal
+procedure  mgl_dens_z(graph: HMGL;const a: HMDT;const stl: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw contour lines for data at x = sVal
+procedure  mgl_cont_x(graph: HMGL;const a: HMDT;const stl: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw contour lines for data at y = sVal
+procedure  mgl_cont_y(graph: HMGL;const a: HMDT;const stl: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw contour lines for data at z = sVal
+procedure  mgl_cont_z(graph: HMGL;const a: HMDT;const stl: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw manual contour lines for data at x = sVal
+procedure  mgl_cont_x_val(graph: HMGL;const v: HMDT;const a: HMDT;const stl: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw manual contour lines for data at y = sVal
+procedure  mgl_cont_y_val(graph: HMGL;const v: HMDT;const a: HMDT;const stl: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw manual contour lines for data at z = sVal
+procedure  mgl_cont_z_val(graph: HMGL;const v: HMDT;const a: HMDT;const stl: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw solid contours for data at x = sVal
+procedure  mgl_contf_x(graph: HMGL;const a: HMDT;const stl: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw solid contours for data at y = sVal
+procedure  mgl_contf_y(graph: HMGL;const a: HMDT;const stl: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw solid contours for data at z = sVal
+procedure  mgl_contf_z(graph: HMGL;const a: HMDT;const stl: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw manual solid contours for data at x = sVal
+procedure  mgl_contf_x_val(graph: HMGL;const v: HMDT;const a: HMDT;const stl: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw manual solid contours for data at y = sVal
+procedure  mgl_contf_y_val(graph: HMGL;const v: HMDT;const a: HMDT;const stl: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+/// Draw manual solid contours for data at z = sVal
+procedure  mgl_contf_z_val(graph: HMGL;const v: HMDT;const a: HMDT;const stl: PChar;sVal: double;const opt: PChar); cdecl; external libmgl;
+//-----------------------------------------------------------------------------
+{== ../../include/mgl2/canvas_cf.h ==}
+//-----------------------------------------------------------------------------
+/// Create HMGL object with specified sizes
+function  mgl_create_graph(width: integer;height: integer): HMGL; cdecl; external libmgl;
+/// Delete HMGL object
+procedure  mgl_delete_graph(gr: HMGL); cdecl; external libmgl;
+/// Set size of frame in pixels. Normally this function is called internally.
+procedure  mgl_set_size(gr: HMGL;width: integer;height: integer); cdecl; external libmgl;
+/// Set default parameters for plotting
+procedure  mgl_set_def_param(gr: HMGL); cdecl; external libmgl;
+/// Combine plots from 2 canvases. Result will be saved into gr
+procedure  mgl_combine_gr(gr: HMGL;gr2: HMGL); cdecl; external libmgl;
+/// Force preparing the image. It can be useful for OpenGL mode mostly.
+procedure  mgl_finish(gr: HMGL); cdecl; external libmgl;
+/// Force preparing the image and save result into background one.
+procedure  mgl_rasterize(gr: HMGL); cdecl; external libmgl;
+/// Set tick length
+procedure  mgl_set_tick_len(gr: HMGL;len: double;stt: double); cdecl; external libmgl;
+/// Set axis and ticks style
+procedure  mgl_set_axis_stl(gr: HMGL;const stl: PChar;const tck: PChar;const sub: PChar); cdecl; external libmgl;
+/// Auto adjust ticks
+procedure  mgl_adjust_ticks(gr: HMGL;const dir: PChar); cdecl; external libmgl;
+/// Auto adjust ticks and set ticks format ("+E0123456789-fF")
+procedure  mgl_adjust_ticks_ext(gr: HMGL;const dir: PChar;const stl: PChar); cdecl; external libmgl;
+/// Set the ticks parameters
+procedure  mgl_set_ticks(gr: HMGL;dir: char;d: double;ns: integer;org: double); cdecl; external libmgl;
+/// Set the ticks parameters and specify ticks factor string
+procedure  mgl_set_ticks_fact(gr: HMGL;dir: char;d: double;ns: integer;org: double;const fact: PChar); cdecl; external libmgl;
+procedure  mgl_set_ticks_factw(gr: HMGL;dir: char;d: double;ns: integer;org: double;const fact: PWideChar); cdecl; external libmgl;
+/// Set manual ticks text (\n separated). Use "" to disable this feature.
+procedure  mgl_set_ticks_str(gr: HMGL;dir: char;const lbl: PChar;add: integer); cdecl; external libmgl;
+procedure  mgl_set_ticks_wcs(gr: HMGL;dir: char;const lbl: PWideChar;add: integer); cdecl; external libmgl;
+/// Set manual ticks position and text (\n separated). Use "" to disable this feature.
+procedure  mgl_set_ticks_val(gr: HMGL;dir: char;const val: HMDT;const lbl: PChar;add: integer); cdecl; external libmgl;
+procedure  mgl_set_ticks_valw(gr: HMGL;dir: char;const val: HMDT;const lbl: PWideChar;add: integer); cdecl; external libmgl;
+/// Add manual tick at given position. Use "" to disable this feature.
+procedure  mgl_add_tick(gr: HMGL;dir: char;val: double;const lbl: PChar); cdecl; external libmgl;
+procedure  mgl_add_tickw(gr: HMGL;dir: char;val: double;const lbl: PWideChar); cdecl; external libmgl;
+/// Tune ticks
+procedure  mgl_tune_ticks(gr: HMGL;tune: integer;fact_pos: double); cdecl; external libmgl;
+/// Set templates for ticks
+procedure  mgl_set_tick_templ(gr: HMGL;dir: char;const templ: PChar); cdecl; external libmgl;
+procedure  mgl_set_tick_templw(gr: HMGL;dir: char;const templ: PWideChar); cdecl; external libmgl;
+/// Set time templates for ticks
+procedure  mgl_set_ticks_time(gr: HMGL;dir: char;d: double;const t: PChar); cdecl; external libmgl;
+/// Set additional shift of tick labels
+procedure  mgl_set_tick_shift(gr: HMGL;sx: double;sy: double;sz: double;sc: double); cdecl; external libmgl;
+/// Draws bounding box outside the plotting volume
+procedure  mgl_box(gr: HMGL); cdecl; external libmgl;
+/// Draws bounding box outside the plotting volume with color c
+procedure  mgl_box_str(gr: HMGL;const col: PChar;ticks: integer); cdecl; external libmgl;
+/// Draw axises with ticks in direction(s) dir.
+procedure  mgl_axis(gr: HMGL;const dir: PChar;const stl: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw grid lines perpendicular to direction(s) dir.
+procedure  mgl_axis_grid(gr: HMGL;const dir: PChar;const pen: PChar;const opt: PChar); cdecl; external libmgl;
+/// Print the label text for axis dir.
+procedure  mgl_label(gr: HMGL;dir: char;const text: PChar;pos: double;const opt: PChar); cdecl; external libmgl;
+procedure  mgl_labelw(gr: HMGL;dir: char;const text: PWideChar;pos: double;const opt: PChar); cdecl; external libmgl;
+/// Draw colorbar at edge of axis
+procedure  mgl_colorbar(gr: HMGL;const sch: PChar); cdecl; external libmgl;
+/// Draw colorbar at manual position
+procedure  mgl_colorbar_ext(gr: HMGL;const sch: PChar;x: double;y: double;w: double;h: double); cdecl; external libmgl;
+/// Draw colorbar with manual colors at edge of axis
+procedure  mgl_colorbar_val(gr: HMGL;const dat: HMDT;const sch: PChar); cdecl; external libmgl;
+/// Draw colorbar with manual colors at manual position
+procedure  mgl_colorbar_val_ext(gr: HMGL;const dat: HMDT;const sch: PChar;x: double;y: double;w: double;h: double); cdecl; external libmgl;
+/// Add string to legend
+procedure  mgl_add_legend(gr: HMGL;const text: PChar;const style: PChar); cdecl; external libmgl;
+procedure  mgl_add_legendw(gr: HMGL;const text: PWideChar;const style: PChar); cdecl; external libmgl;
+/// Clear saved legend string
+procedure  mgl_clear_legend(gr: HMGL); cdecl; external libmgl;
+/// Draw legend of accumulated strings at position {x,y}
+procedure  mgl_legend_pos(gr: HMGL;x: double;y: double;const font: PChar;const opt: PChar); cdecl; external libmgl;
+/// Draw legend of accumulated strings
+procedure  mgl_legend(gr: HMGL;where: integer;const font: PChar;const opt: PChar); cdecl; external libmgl;
+/// Set number of marks in legend sample
+procedure  mgl_set_legend_marks(gr: HMGL;num: integer); cdecl; external libmgl;
+/// Show current image
+procedure  mgl_show_image(gr: HMGL;const viewer: PChar;keep: integer); cdecl; external libmgl;
+/// Write the frame in file (depending extension, write current frame if fname is empty)
+procedure  mgl_write_frame(gr: HMGL;const fname: PChar;const descr: PChar); cdecl; external libmgl;
+/// Write the frame in file using BMP format
+procedure  mgl_write_tga(gr: HMGL;const fname: PChar;const descr: PChar); cdecl; external libmgl;
+/// Write the frame in file using BMP format
+procedure  mgl_write_bmp(gr: HMGL;const fname: PChar;const descr: PChar); cdecl; external libmgl;
+/// Write the frame in file using JPEG format
+procedure  mgl_write_jpg(gr: HMGL;const fname: PChar;const descr: PChar); cdecl; external libmgl;
+/// Write the frame in file using PNG format with transparency
+procedure  mgl_write_png(gr: HMGL;const fname: PChar;const descr: PChar); cdecl; external libmgl;
+/// Write the frame in file using PNG format without transparency
+procedure  mgl_write_png_solid(gr: HMGL;const fname: PChar;const descr: PChar); cdecl; external libmgl;
+/// Write the frame in file using PostScript format as bitmap
+procedure  mgl_write_bps(gr: HMGL;const fname: PChar;const descr: PChar); cdecl; external libmgl;
+/// Write the frame in file using PostScript format
+procedure  mgl_write_eps(gr: HMGL;const fname: PChar;const descr: PChar); cdecl; external libmgl;
+/// Write the frame in file using SVG format
+procedure  mgl_write_svg(gr: HMGL;const fname: PChar;const descr: PChar); cdecl; external libmgl;
+/// Write the frame in file using LaTeX format
+procedure  mgl_write_tex(gr: HMGL;const fname: PChar;const descr: PChar); cdecl; external libmgl;
+/// Write the frame in file using OBJ format
+procedure  mgl_write_obj(gr: HMGL;const fname: PChar;const descr: PChar;use_png: integer); cdecl; external libmgl;
+/// Write the frame in file using OBJ format (old version)
+procedure  mgl_write_obj_old(gr: HMGL;const fname: PChar;const descr: PChar;use_png: integer); cdecl; external libmgl;
+/// Write the frame in file using STL format (faces only)
+procedure  mgl_write_stl(gr: HMGL;const fname: PChar;const descr: PChar); cdecl; external libmgl;
+/// Write the frame in file using OFF format
+procedure  mgl_write_off(gr: HMGL;const fname: PChar;const descr: PChar;colored: integer); cdecl; external libmgl;
+/// Write the frame in file using XYZ format
+procedure  mgl_write_xyz(gr: HMGL;const fname: PChar;const descr: PChar); cdecl; external libmgl;
+/// Write the frame in file using PRC format
+procedure  mgl_write_prc(gr: HMGL;const fname: PChar;const descr: PChar;make_pdf: integer); cdecl; external libmgl;
+/// Write the frame in file using GIF format (only for current frame!)
+procedure  mgl_write_gif(gr: HMGL;const fname: PChar;const descr: PChar); cdecl; external libmgl;
+/// Start write frames to cinema using GIF format
+procedure  mgl_start_gif(gr: HMGL;const fname: PChar;ms: integer); cdecl; external libmgl;
+/// Stop writing cinema using GIF format
+procedure  mgl_close_gif(gr: HMGL); cdecl; external libmgl;
+/// Export points and primitives in file using MGLD format
+procedure  mgl_export_mgld(gr: HMGL;const fname: PChar;const descr: PChar); cdecl; external libmgl;
+/// Import points and primitives from file using MGLD format
+procedure  mgl_import_mgld(gr: HMGL;const fname: PChar;add: integer); cdecl; external libmgl;
+/// Export in JSON format suitable for later drawing by JavaScript
+procedure  mgl_write_json(gr: HMGL;const fname: PChar;const descr: PChar); cdecl; external libmgl;
+procedure  mgl_write_json_z(gr: HMGL;const fname: PChar;const descr: PChar); cdecl; external libmgl;
+function mgl_get_json(gr: HMGL): PChar; cdecl; external libmgl;
+/// Get RGB values of current bitmap
+function mgl_get_rgb(gr: HMGL): PByte; cdecl; external libmgl;
+/// Get RGBA values of current bitmap
+function mgl_get_rgba(gr: HMGL): PByte; cdecl; external libmgl;
+/// Get RGB values of current bitmap
+function mgl_get_background(gr: HMGL): PByte; cdecl; external libmgl;
+/// Set object/subplot id
+procedure  mgl_set_obj_id(gr: HMGL;id: integer); cdecl; external libmgl;
+/// Get object id
+function  mgl_get_obj_id(gr: HMGL;x: integer;y: integer): integer; cdecl; external libmgl;
+/// Get subplot id
+function  mgl_get_spl_id(gr: HMGL;x: integer;y: integer): integer; cdecl; external libmgl;
+/// Get width of the image
+function  mgl_get_width(gr: HMGL): integer; cdecl; external libmgl;
+/// Get height of the image
+function  mgl_get_height(gr: HMGL): integer; cdecl; external libmgl;
+/// Calculate 3D coordinate {x,y,z} for screen point {xs,ys}
+procedure  mgl_calc_xyz(gr: HMGL;xs: integer;ys: integer;x: Pmreal;y: Pmreal;z: Pmreal); cdecl; external libmgl;
+/// Calculate screen point {xs,ys} for 3D coordinate {x,y,z}
+procedure  mgl_calc_scr(gr: HMGL;x: double;y: double;z: double;xs: Pint;ys: Pint); cdecl; external libmgl;
+/// Check if {xs,ys} is close to active point with accuracy d, and return its position or -1
+function  mgl_is_active(gr: HMGL;xs: integer;ys: integer;d: integer): integer; cdecl; external libmgl;
+/// Create new frame.
+function  mgl_new_frame(gr: HMGL): integer; cdecl; external libmgl;
+/// Finish frame drawing
+procedure  mgl_end_frame(gr: HMGL); cdecl; external libmgl;
+/// Get the number of created frames
+function  mgl_get_num_frame(gr: HMGL): integer; cdecl; external libmgl;
+/// Reset frames counter (start it from zero)
+procedure  mgl_reset_frames(gr: HMGL); cdecl; external libmgl;
+/// Get drawing data for i-th frame (work if MGL_VECT_FRAME is set on)
+procedure  mgl_get_frame(gr: HMGL;i: integer); cdecl; external libmgl;
+/// Set drawing data for i-th frame (work if MGL_VECT_FRAME is set on)
+procedure  mgl_set_frame(gr: HMGL;i: integer); cdecl; external libmgl;
+/// Append drawing data from i-th frame (work if MGL_VECT_FRAME is set on)
+procedure  mgl_show_frame(gr: HMGL;i: integer); cdecl; external libmgl;
+/// Delete primitives for i-th frame (work if MGL_VECT_FRAME is set on)
+procedure  mgl_del_frame(gr: HMGL;i: integer); cdecl; external libmgl;
+/// Clear list of primitives for current drawing
+procedure  mgl_clear_frame(gr: HMGL); cdecl; external libmgl;
+/// Set the transparency type (0 - usual, 1 - glass, 2 - lamp)
+procedure  mgl_set_transp_type(gr: HMGL;kind: integer); cdecl; external libmgl;
+/// Set the transparency on/off.
+procedure  mgl_set_alpha(gr: HMGL;enable: integer); cdecl; external libmgl;
+/// Set the fog distance or switch it off (if d=0).
+procedure  mgl_set_fog(gr: HMGL;d: double;dz: double); cdecl; external libmgl;
+/// Set the using of light on/off.
+procedure  mgl_set_light(gr: HMGL;enable: integer); cdecl; external libmgl;
+/// Switch on/off the specified light source.
+procedure  mgl_set_light_n(gr: HMGL;n: integer;enable: integer); cdecl; external libmgl;
+/// Add white light source at infinity.
+procedure  mgl_add_light(gr: HMGL;n: integer;x: double;y: double;z: double); cdecl; external libmgl;
+/// Add light source at infinity (more settings).
+procedure  mgl_add_light_ext(gr: HMGL;n: integer;x: double;y: double;z: double;c: char;br: double;ap: double); cdecl; external libmgl;
+/// Add local light source.
+procedure  mgl_add_light_loc(gr: HMGL;n: integer;x: double;y: double;z: double;dx: double;dy: double;dz: double;c: char;br: double;ap: double); cdecl; external libmgl;
+/// Pop transformation matrix from stack
+procedure  mgl_mat_pop(gr: HMGL); cdecl; external libmgl;
+/// Push transformation matrix into stack
+procedure  mgl_mat_push(gr: HMGL); cdecl; external libmgl;
+/// Clear up the frame
+procedure  mgl_clf(gr: HMGL); cdecl; external libmgl;
+/// Clear up the frame but keep fog settings
+procedure  mgl_clf_nfog(gr: HMGL); cdecl; external libmgl;
+/// Clear up the frame and fill background by specified color
+procedure  mgl_clf_rgb(gr: HMGL;r: double;g: double;b: double); cdecl; external libmgl;
+/// Clear up the frame and fill background by specified color
+procedure  mgl_clf_chr(gr: HMGL;col: char); cdecl; external libmgl;
+/// Clear up the frame and fill background by specified color with manual transparency
+procedure  mgl_clf_str(gr: HMGL;const col: PChar); cdecl; external libmgl;
+/// Load background image
+procedure  mgl_load_background(gr: HMGL;const fname: PChar;alpha: double); cdecl; external libmgl;
+/// Put further plotting in some region of whole frame.
+procedure  mgl_subplot(gr: HMGL;nx: integer;ny: integer;m: integer;const style: PChar); cdecl; external libmgl;
+/// Put further plotting in some region of whole frame and shift it by distance {dx,dy}.
+procedure  mgl_subplot_d(gr: HMGL;nx: integer;ny: integer;m: integer;const style: PChar;dx: double;dy: double); cdecl; external libmgl;
+/// Like MGL_EXPORT mgl_subplot() but "join" several cells
+procedure  mgl_multiplot(gr: HMGL;nx: integer;ny: integer;m: integer;dx: integer;dy: integer;const style: PChar); cdecl; external libmgl;
+/// Put further plotting in a region of whole frame.
+procedure  mgl_inplot(gr: HMGL;x1: double;x2: double;y1: double;y2: double); cdecl; external libmgl;
+/// Put further plotting in a region of current subplot/inplot.
+procedure  mgl_relplot(gr: HMGL;x1: double;x2: double;y1: double;y2: double); cdecl; external libmgl;
+/// Put further plotting in column cell of previous subplot/inplot.
+procedure  mgl_columnplot(gr: HMGL;num: integer;ind: integer;d: double); cdecl; external libmgl;
+/// Put further plotting in matrix cell of previous subplot/inplot.
+procedure  mgl_gridplot(gr: HMGL;nx: integer;ny: integer;m: integer;d: double); cdecl; external libmgl;
+/// Put further plotting in cell of stick rotated on angles tet, phi.
+procedure  mgl_stickplot(gr: HMGL;num: integer;ind: integer;tet: double;phi: double); cdecl; external libmgl;
+/// Add title for current subplot/inplot.
+procedure  mgl_title(gr: HMGL;const title: PChar;const stl: PChar;size: double); cdecl; external libmgl;
+procedure  mgl_titlew(gr: HMGL;const title: PWideChar;const stl: PChar;size: double); cdecl; external libmgl;
+/// Set factor of plot size
+procedure  mgl_set_plotfactor(gr: HMGL;val: double); cdecl; external libmgl;
+/// Set aspect ratio for further plotting.
+procedure  mgl_aspect(gr: HMGL;Ax: double;Ay: double;Az: double); cdecl; external libmgl;
+/// Rotate a further plotting.
+procedure  mgl_rotate(gr: HMGL;TetX: double;TetZ: double;TetY: double); cdecl; external libmgl;
+/// Rotate a further plotting around vector {x,y,z}.
+procedure  mgl_rotate_vector(gr: HMGL;Tet: double;x: double;y: double;z: double); cdecl; external libmgl;
+/// Set perspective (in range [0,1)) for plot. Set to zero for switching off.
+procedure  mgl_perspective(gr: HMGL;val: double); cdecl; external libmgl;
+/// Ask to set perspective (in range [0,1)) for plot. Set to zero for switching off.
+procedure  mgl_ask_perspective(gr: HMGL;val: double); cdecl; external libmgl;
+/// Set angle of view independently from Rotate().
+procedure  mgl_view(gr: HMGL;TetX: double;TetZ: double;TetY: double); cdecl; external libmgl;
+/// Zoom in/out a part of picture (use mgl_zoom(0, 0, 1, 1) for restore default)
+procedure  mgl_zoom(gr: HMGL;x1: double;y1: double;x2: double;y2: double); cdecl; external libmgl;
+//-----------------------------------------------------------------------------
+/// Callback function for mouse click
+/// Set callback functions for drawing and data reloading
+/// Set delay for animation in seconds
+procedure  mgl_wnd_set_delay(gr: HMGL;dt: double); cdecl; external libmgl;
+/// Get delay for animation in seconds
+function  mgl_wnd_get_delay(gr: HMGL): double; cdecl; external libmgl;
+/// Set window properties
+procedure  mgl_setup_window(gr: HMGL;clf_upd: integer;showpos: integer); cdecl; external libmgl;
+/// Switch on/off transparency (do not overwrite user settings)
+procedure  mgl_wnd_toggle_alpha(gr: HMGL); cdecl; external libmgl;
+/// Switch on/off lighting (do not overwrite user settings)
+procedure  mgl_wnd_toggle_light(gr: HMGL); cdecl; external libmgl;
+/// Switch on/off zooming by mouse
+procedure  mgl_wnd_toggle_zoom(gr: HMGL); cdecl; external libmgl;
+/// Switch on/off rotation by mouse
+procedure  mgl_wnd_toggle_rotate(gr: HMGL); cdecl; external libmgl;
+/// Switch off all zooming and rotation
+procedure  mgl_wnd_toggle_no(gr: HMGL); cdecl; external libmgl;
+/// Update picture by calling user drawing function
+procedure  mgl_wnd_update(gr: HMGL); cdecl; external libmgl;
+/// Reload user data and update picture
+procedure  mgl_wnd_reload(gr: HMGL); cdecl; external libmgl;
+/// Adjust size of bitmap to window size
+procedure  mgl_wnd_adjust(gr: HMGL); cdecl; external libmgl;
+/// Show next frame (if one)
+procedure  mgl_wnd_next_frame(gr: HMGL); cdecl; external libmgl;
+/// Show previous frame (if one)
+procedure  mgl_wnd_prev_frame(gr: HMGL); cdecl; external libmgl;
+/// Run slideshow (animation) of frames
+procedure  mgl_wnd_animation(gr: HMGL); cdecl; external libmgl;
+/// Get last mouse position
+procedure  mgl_get_last_mouse_pos(gr: HMGL;x: Pmreal;y: Pmreal;z: Pmreal); cdecl; external libmgl;
+//-----------------------------------------------------------------------------
+/// Create HMPR object for parsing MGL scripts
+function  mgl_create_parser(): HMPR; cdecl; external libmgl;
+/// Change counter of HMPR uses (for advanced users only). Non-zero counter prevent automatic object removing.
+function  mgl_use_parser(p: HMPR;inc: integer): integer; cdecl; external libmgl;
+/// Delete HMPR object
+procedure  mgl_delete_parser(p: HMPR); cdecl; external libmgl;
+/// Set value for parameter $N
+procedure  mgl_parser_add_param(p: HMPR;id: integer;const str: PChar); cdecl; external libmgl;
+procedure  mgl_parser_add_paramw(p: HMPR;id: integer;const str: PWideChar); cdecl; external libmgl;
+/// Find variable with given name or add a new one
+/// NOTE !!! You must not delete obtained data arrays !!!
+function  mgl_parser_add_var(p: HMPR;const name: PChar): HMDT; cdecl; external libmgl;
+function  mgl_parser_add_varw(p: HMPR;const name: PWideChar): HMDT; cdecl; external libmgl;
+/// Find variable with given name or return NULL if no one
+/// NOTE !!! You must not delete obtained data arrays !!!
+/// Get variable with given id
+/// NOTE !!! You must not delete obtained data arrays !!!
+/// Get number of variables
+function  mgl_parser_num_var(p: HMPR): integer; cdecl; external libmgl;
+/// Delete variable with name
+procedure  mgl_parser_del_var(p: HMPR;const name: PChar); cdecl; external libmgl;
+procedure  mgl_parser_del_varw(p: HMPR;const name: PWideChar); cdecl; external libmgl;
+/// Delete all data variables
+procedure  mgl_parser_del_all(p: HMPR); cdecl; external libmgl;
+/// Load new commands from external dynamic Library (must have "const mglCommand *mgl_cmd_extra" variable)
+procedure  mgl_parser_load(pr: HMPR;const dll_name: PChar); cdecl; external libmgl;
+/// Parse and draw single line of the MGL script
+function  mgl_parse_line(gr: HMGL;p: HMPR;const str: PChar;pos: integer): integer; cdecl; external libmgl;
+function  mgl_parse_linew(gr: HMGL;p: HMPR;const str: PWideChar;pos: integer): integer; cdecl; external libmgl;
+/// Execute and draw script from the file
+/// Execute MGL script text with '\n' separated lines
+procedure  mgl_parse_text(gr: HMGL;p: HMPR;const str: PChar); cdecl; external libmgl;
+procedure  mgl_parse_textw(gr: HMGL;p: HMPR;const str: PWideChar); cdecl; external libmgl;
+/// Restore once flag
+procedure  mgl_parser_restore_once(p: HMPR); cdecl; external libmgl;
+/// Allow changing size of the picture
+procedure  mgl_parser_allow_setsize(p: HMPR;a: integer); cdecl; external libmgl;
+/// Allow reading/saving files
+procedure  mgl_parser_allow_file_io(p: HMPR;a: integer); cdecl; external libmgl;
+/// Allow loading commands from external libraries
+procedure  mgl_parser_allow_dll_call(p: HMPR;a: integer); cdecl; external libmgl;
+/// Set flag to stop script parsing
+procedure  mgl_parser_stop(p: HMPR); cdecl; external libmgl;
+/// Return type of command: 0 - not found, 1 - data plot, 2 - other plot,
+///		3 - setup, 4 - data handle, 5 - data create, 6 - subplot, 7 - program
+///		8 - 1d plot, 9 - 2d plot, 10 - 3d plot, 11 - dd plot, 12 - vector plot
+///		13 - axis, 14 - primitives, 15 - axis setup, 16 - text/legend, 17 - data transform
+function  mgl_parser_cmd_type(pr: HMPR;const name: PChar): integer; cdecl; external libmgl;
+/// Return description of MGL command
+function mgl_parser_cmd_desc(pr: HMPR;const name: PChar): PChar; cdecl; external libmgl;
+/// Return string of command format (command name and its argument[s])
+function mgl_parser_cmd_frmt(pr: HMPR;const name: PChar): PChar; cdecl; external libmgl;
+/// Get name of command with nmber n
+function mgl_parser_cmd_name(pr: HMPR;id: integer): PChar; cdecl; external libmgl;
+/// Get number of defined commands
+function  mgl_parser_cmd_num(pr: HMPR): integer; cdecl; external libmgl;
+/// Return result of formula evaluation
+function  mgl_parser_calc(pr: HMPR;const formula: PChar): HMDT; cdecl; external libmgl;
+function  mgl_parser_calcw(pr: HMPR;const formula: PWideChar): HMDT; cdecl; external libmgl;
+//-----------------------------------------------------------------------------
+{== ../../include/mgl2/addon.h ==}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+/// Explicit scheme for 1 step of axial diffraction
+procedure  mgl_difr_axial(a: Pdual;n: integer;step: integer;q: dual;Border: integer;tmp: Pdual;kk: integer;di: double); cdecl; external libmgl;
+procedure  mgl_difr_axial_old(a: Pdual;n: integer;step: integer;q: dual;Border: integer;tmp1: Pdual;tmp2: Pdual;kk: integer;di: double); cdecl; external libmgl;
+/// Explicit scheme for 1 step of plane diffraction
+procedure  mgl_difr_grid(a: Pdual;n: integer;step: integer;q: dual;Border: integer;tmp: Pdual;kk: integer); cdecl; external libmgl;
+procedure  mgl_difr_grid_old(a: Pdual;n: integer;step: integer;q: dual;Border: integer;tmp1: Pdual;tmp2: Pdual;kk: integer); cdecl; external libmgl;
+//-----------------------------------------------------------------------------
+/// Get random number with Gaussian distribution
+function  mgl_gauss_rnd(): double; cdecl; external libmgl;
+/// Fill frequencies for FFT
+procedure  mgl_fft_freq(freq: Pdouble;nn: integer); cdecl; external libmgl;
+/// Remove double spaces from the string
+procedure  mgl_strcls(str: PChar); cdecl; external libmgl;
+/// Get position of substring or return -1 if not found
+function  mgl_strpos(const str: PChar;fnd: PChar): integer; cdecl; external libmgl;
+/// Get position of symbol or return -1 if not found
+function  mgl_chrpos(const str: PChar;fnd: char): integer; cdecl; external libmgl;
+/// Get uncommented string from file (NOTE: it is not thread safe!!!)
+/// Get parameters from uncommented strings of file (NOTE: it is not thread safe!!!)
+/// Check if symbol denote true
+function  mgl_istrue(ch: char): integer; cdecl; external libmgl;
+/// Print test message
+/// Print info message
+/// Locate next data block (block started by -----)
+
+
+{$IFDEF MSWINDOWS}
+//*****************************************************************************/
+// Delphi - specific
+//*****************************************************************************/
+procedure mgl_begin();
+procedure mgl_end();
+
+procedure mgl_draw_on_canvas(gr: HMGL; width, height: integer; canvas: TCanvas; switchXY: boolean = false);
+
+implementation
+
+var _FPUCW: word;
+
+procedure mgl_begin();
+ begin
+  _FPUCW := Get8087CW();     // backup current FPU CW
+  Set8087CW(_FPUCW or $3F); // masking all FPU exceptions
+ end;
+
+procedure mgl_end();
+ begin
+  Set8087CW(_FPUCW);         // restore old FPU CW
+ end;
+
+procedure mgl_draw_on_canvas(gr: HMGL; width, height: integer; canvas: TCanvas; switchXY: boolean = false);
+  var i, j: integer;
+      bytes: PByte;
+      col: TColor;
+ begin
+  bytes := mgl_get_rgb(gr);
+
+  if (not switchXY) then
+   for j := 0 to height - 1 do
+    for i := 0 to width - 1 do
+     begin
+      col := 0;
+      col := col or (bytes^);
+      inc(bytes);
+      col := col or (bytes^) shl 8;
+      inc(bytes);
+       col := col or (bytes^) shl 16;
+      inc(bytes);
+      canvas.Pixels[i, j] := col;
+    end
+  else
+   for j := height - 1 downto 0 do
+    for i := 0 to width - 1 do
+     begin
+      col := 0;
+      col := col or (bytes^);
+      inc(bytes);
+      col := col or (bytes^) shl 8;
+      inc(bytes);
+       col := col or (bytes^) shl 16;
+      inc(bytes);
+      canvas.Pixels[j, i] := col;
+     end;
+ end;
+
+{$ENDIF}
+end.
+
diff --git a/include/mgl2/mglplot.fs b/include/mgl2/mglplot.fs
new file mode 100644
index 0000000..76de339
--- /dev/null
+++ b/include/mgl2/mglplot.fs
@@ -0,0 +1,562 @@
+\ Mathgl library wrapper                      Thu Feb 21 12:33:02 MST 2008
+\ Copyright (C) 2008, Sergey Plis
+\
+\ 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.
+
+\needs gsl     include gsl.fs
+\needs mathgl  include mathgl.fs
+\needs vectors include vectors.fs
+\needs $!      include string.fs
+
+Module mglplot
+
+also minos also vectors also gsl also mathgl also float
+
+\ ------------------------------------------------------------------------
+\                               structures
+\ ------------------------------------------------------------------------
+struct{
+    cell transp?
+    cell transp_type
+    cell alpha?
+    cell light
+    cell box
+    cell grid
+    double ambient
+    cell axis?
+    cell axis_str
+    cell rotation[
+    cell aspect[
+    cell colorbar
+    double linewidth
+    double fontsize
+    cell labelx$
+    cell labely$
+    cell labelz$
+    cell textrotate
+} mgl-params
+
+struct{
+    cell next      \ next plot in the list of current figure
+    cell prev
+    cell xrange    \
+    cell yrange    \
+    cell zrange    \
+    cell hmdtlist  \ vector of all data objects used in the plot
+    cell params    \ vector of parameters to the plotting function
+    cell ops       \ vector of xt's of operations to place params
+                   \ list on the stack so the plotting function can
+                   \ be executed
+    cell plotfunc  \ the plotting function
+} a_plot
+
+struct{
+    cell next      \ next figure in the figure structure
+    cell #
+    cell active?   \ True/False
+    cell figure    \ plot object
+} a_figure
+
+: dispose-hmdtlist ( v( -- )
+    dup )size 0 do
+	dup i )@
+	mgl_delete_data
+    loop drop ;
+
+: dispose-a-plot ( *a_plot -- )
+    dup a_plot hmdtlist @ dispose-hmdtlist
+    dup a_plot params @ )free
+    dup a_plot ops @ )free
+    dup a_plot xrange @ ]free
+    dup a_plot yrange @ ]free
+    dup a_plot zrange @ ]free
+    free throw ;
+
+: dispose-all-plots ( *a_plot -- )
+    dup begin while
+	    dup a_plot next @
+	    swap dispose-a-plot
+	    dup
+    repeat drop ;
+
+\ simple aux words
+| : ]@s ( x[ -- f: x[0] .. x[n] )
+    dup ]size 0 do dup i ]@ loop drop ;
+| : ]!s ( x[ f: x[0] .. x[n] -- )
+    dup ]size 0 do dup i ]! loop drop ;
+| create axis-param 0 c, 0 c, 0 c, 0 c, 0 c,
+| create mglstrbuff $FF allot
+: default-rotation ( -- r[ ) 3 :] dup 0e 0e 0e ]!s ;
+: clear-axis-param
+    axis-param dup 'x swap c! 1+ dup 'y swap c! 1+ 'z swap c! ;
+
+: NAN ( -- f: NAN) $7FC00000 sp@ sf@ drop ;
+\ ------------------------------------------------------------------------
+\                                 GUI
+\ ------------------------------------------------------------------------
+
+component class mathplot
+  private:
+    method fill-pixmap
+    method mgl_settings_reset
+    cell var mhold
+  public:
+    early open
+    early dialog
+    early open-app
+
+    method generate-plot
+    method addplot
+    method clear-pixmap
+    method #plots
+    method clf
+    method mgl-rotation!
+    method mgl-colorbar
+
+    method mgl-hold
+    method mgl-holdoff
+    method mgl-holdon
+    method hold@
+    method hold!
+    method mgl-grid
+    method fontsize
+
+    method mgl-xlabel
+    method mgl-ylabel    
+    method mgl-zlabel
+    
+    canvas ptr mCanvas
+    ( [varstart] )
+    \ memory-pixmap ptr pxmap \ the pixmap on the canvas
+    cell var pxmap
+    cell var graph         \ the graph to display
+    cell var plotlist      \ list of plots to display
+    cell var parameters    \ parameter structure
+    ( [varend] )
+  how:
+    : params   DF[ 0 ]DF s" figure" ;
+    : hold@ mhold @ ;
+    : hold! mhold ! ;    
+    : mgl-hold mhold @ not mhold ! ;
+    : mgl-holdoff mhold off ;
+    : mgl-holdon mhold on ;
+    
+    : open     self DF[ 0 ]DF s" bigforth Plot" open-component ;
+    : dialog   new  DF[ 0 ]DF s" bigforth Plot" open-dialog ;
+    : open-app new  DF[ 0 ]DF s" bigforth Plot" open-application ;
+    : clear-pixmap pxmap @ if pxmap @ >o dispose o> 0 pxmap ! then ;
+    : #plots ( -- )
+	    0
+	    plotlist @ begin dup while
+		    swap 1+ swap
+		    a_plot next @
+		    repeat
+	    drop ;
+
+    : assign
+	&600 &400  mgl_create_graph_zb graph !
+	sizeof mgl-params allocate throw parameters !
+	parameters @ sizeof mgl-params erase
+	mgl_settings_reset
+	
+	\ 0 0
+	parameters @ mgl-params labelx$ dup @ if $off else drop then
+	\ 0 0
+	parameters @ mgl-params labely$ dup @ if $off else drop then
+	\ 0 0
+	parameters @ mgl-params labelz$ dup @ if $off else drop then
+	
+	0 pxmap !
+	0 plotlist !
+	mhold off ;
+
+    : fontsize ( f: size -- ) parameters @ mgl-params fontsize sf! ;
+    
+    : mgl-set-params ( -- )
+	graph @
+	dup parameters @ mgl-params rotation[ @ ]@s mgl_rotate
+	dup parameters @ mgl-params ambient     sf@ mgl_set_ambbr
+	dup parameters @ mgl-params fontsize    sf@ mgl_set_font_size
+	dup parameters @ mgl-params linewidth   sf@ mgl_set_base_line_width
+	dup parameters @ mgl-params aspect[   @ ]@s mgl_aspect
+	dup parameters @ mgl-params transp?       @ mgl_set_transp
+	dup parameters @ mgl-params transp_type   @ mgl_set_transp_type
+	dup parameters @ mgl-params alpha?        @ mgl_set_alpha
+	dup parameters @ mgl-params light         @ mgl_set_light
+	dup parameters @ mgl-params textrotate    @ mgl_set_rotated_text
+	dup parameters @ mgl-params box           @ mgl_box
+	    parameters @ mgl-params grid @ if
+	    dup 0" xyz" 0 mgl_axis_grid
+	then
+	drop ;
+    : mgl-post-params ( -- )
+	graph @ 1 mgl_set_rotated_text 
+	parameters @ mgl-params labelx$ @ if
+	    parameters @ mgl-params labelx$ $@ mglstrbuff 0place
+	    parameters @ mgl-params fontsize sf@ 0e0	    
+	    graph @ 'x mglstrbuff 0 mgl_label_ext
+	then 
+	parameters @ mgl-params labely$ @ if
+	    parameters @ mgl-params labely$ $@ mglstrbuff 0place
+	    parameters @ mgl-params fontsize sf@ 0e0	    
+	    graph @ 'y mglstrbuff 0 mgl_label_ext	    
+	then
+	parameters @ mgl-params labelz$ @ drop 0 if
+	    parameters @ mgl-params labelz$ $@ mglstrbuff 0place
+	    parameters @ mgl-params fontsize sf@ 0e0	    
+	    graph @ 'z mglstrbuff 0 mgl_label_ext	    	    
+	then
+	parameters @ mgl-params colorbar @ drop 0 if
+	    dup 0 0 mgl_colorbar
+	then ;
+    : mgl_settings_reset
+	1 parameters @ mgl-params transp? !
+	1 parameters @ mgl-params transp_type !
+	0 parameters @ mgl-params alpha? !
+	0 parameters @ mgl-params box !
+	0 parameters @ mgl-params colorbar !
+	0 parameters @ mgl-params light !
+	1 parameters @ mgl-params axis? !
+	axis-param parameters @ mgl-params axis_str !
+	clear-axis-param
+	parameters @ mgl-params labelx$ dup @ if $off else drop then
+	parameters @ mgl-params labely$ dup @ if $off else drop then
+	parameters @ mgl-params labelz$ dup @ if $off else drop then
+	\ parameters @ mgl-params textrotate off
+	!0.9 parameters @ mgl-params ambient sf!
+	!2.5 parameters @ mgl-params fontsize sf!
+	!1.2 parameters @ mgl-params linewidth sf!
+	parameters @ mgl-params rotation[ @ dup if ]free else drop then
+	default-rotation parameters @ mgl-params rotation[ !
+	parameters @ mgl-params aspect[ @ dup if ]free else drop then
+	3 :] parameters @ mgl-params aspect[ !
+    ;
+
+    : mgl_settings_free
+	parameters @ mgl-params labelx$ dup @ if $off else drop then
+	parameters @ mgl-params labely$ dup @ if $off else drop then
+	parameters @ mgl-params labelz$ dup @ if $off else drop then
+	parameters @ mgl-params rotation[ @ dup if ]free else drop then
+	parameters @ mgl-params aspect[ @ dup if ]free else drop then
+    ;
+    
+    : addplot ( *a_plot -- )
+	mhold @ if
+	    >r plotlist @ r@ a_plot next ! r>
+	    plotlist @ if
+		dup plotlist @ a_plot prev !
+	    then
+	else
+	    plotlist @ dispose-all-plots    
+	then
+	plotlist !
+	generate-plot
+	mcanvas draw ;
+    : display_a_plot ( *a_plot -- )
+	>r graph @
+	r@ a_plot ops @
+	r@ a_plot params @
+	dup )size 0 do
+	    i -rot
+	    2>r
+	    2r@ rot dup >r *) swap r> )@ F execute
+	    2r>
+	loop 2drop
+	r> a_plot plotfunc @
+	F execute ;
+    : xmin ( -- f: xmin )
+	1e20 plotlist @ begin dup while
+		dup a_plot xrange @ ]min fmin
+		a_plot next @
+	repeat
+	drop ;
+    : xmax ( -- f: xmax )
+	-1e20 plotlist @ begin dup while
+		dup a_plot xrange @ ]max fmax
+		a_plot next @
+	repeat
+	drop ;
+    : ymin ( -- f: ymin )
+	1e20 plotlist @ begin dup while
+		dup a_plot yrange @ ]min fmin
+		a_plot next @
+	repeat
+	drop ;
+    : ymax ( -- f: ymax )
+	-1e20 plotlist @ begin dup while
+		dup a_plot yrange @ ]max fmax
+		a_plot next @
+	repeat
+	drop ;
+
+    : zmin ( -- f: zmin )
+	1e20 plotlist @ begin dup while
+		dup a_plot zrange @ ]min fmin
+		a_plot next @
+	repeat
+	drop ;
+    : zmax ( -- f: ymax )
+	-1e20 plotlist @ begin dup while
+		dup a_plot zrange @ ]max fmax
+		a_plot next @
+	repeat
+	drop ;
+
+    : display_plots ( -- )
+	0 plotlist @ begin dup while
+		nip dup a_plot next @
+	repeat
+	drop
+	begin dup while
+		dup display_a_plot
+		a_plot prev @
+	repeat drop ;
+   
+    : create-figure ( -- )
+	graph @ mgl_identity
+	graph @ mgl_clf
+	graph @ mCanvas with w @ h @ endwith mgl_set_size
+	
+\  	parameters @ mgl-params rotation[ @ ]null? if
+\  	    graph @
+\  	    [ 1e 3e fsqrt f/ 1e fswap f- 2e f/ 0.7e f* ] fliteral
+\  	    fdup
+\  	    fdup fdup 1e fswap f- fswap 1e fswap f-
+\  	    mgl_set_zoom
+\  	else
+	    graph @ 0e 0e 0e 0e mgl_set_zoom
+\	    parameters @ mgl-params fontsize sf@	    
+\ 	    1.2e f* parameters @ mgl-params fontsize sf!
+\	then
+	graph @ xmin ymin zmin xmax ymax zmax mgl_set_axis_3d
+\	graph @ xmin ymin zmin mgl_set_origin
+	graph @ NAN NAN NAN mgl_set_origin
+	mgl-set-params
+	mgl-post-params
+	display_plots
+    ;
+    : fill-pixmap
+	    clear-pixmap
+	    graph @ mgl_get_rgb
+	    mCanvas with w @ h @ endwith * 4 * dup allocate throw
+	    dup >r
+	    swap 4 / 3 *  move r@
+	    mCanvas with w @ h @ endwith memory-pixmap new pxmap !
+	    r> free throw ;
+    : generate-plot ( -- )
+	create-figure
+	fill-pixmap ;
+
+    : freeplots plotlist @ dispose-all-plots 0 plotlist ! ;
+
+    : clf freeplots clear-pixmap draw ;
+
+    : mgl-rotation! ( f: x y z )
+	fswap frot parameters @ mgl-params rotation[ @ ]!s
+	generate-plot
+	mcanvas draw ;
+    : mgl-rotation@ ( -- f: x y z )
+	parameters @ mgl-params rotation[ @ ]@s ;
+    : mgl-colorbar ( -- )
+	parameters @ mgl-params colorbar @
+	not
+	parameters @ mgl-params colorbar !
+	generate-plot mcanvas draw ;
+    : mgl-grid parameters @ mgl-params grid dup @ not swap !
+	generate-plot mcanvas draw ;
+    : mgl-xlabel ( addr u -- )
+	parameters @ mgl-params labelx$ dup @
+	if dup $off $! else $! then
+	generate-plot mcanvas draw ;
+    : mgl-ylabel ( addr u -- )
+	parameters @ mgl-params labely$ dup @
+	if dup $off $! else $! then
+	generate-plot mcanvas draw ;	
+    : mgl-zlabel ( addr u -- )
+	parameters @ mgl-params labelz$ dup @
+	if dup $off $! else $! then
+	generate-plot mcanvas draw ;	
+        
+    : dispose
+	clear-pixmap
+	plotlist @ dispose-all-plots
+	graph @ mgl_delete_graph
+	mgl_settings_free
+	parameters @ sizeof mgl-params erase
+	parameters @ free throw
+	super dispose ;
+    : widget
+       CV[
+	outer with pxmap @ endwith 0<> if
+	    outer with pxmap @ endwith icon
+	then
+	]CV
+	^^ CK[ 2drop 2drop ]CK
+	$258 $1 *hfil $190 $1 *vfil canvas new  ^^bind mCanvas
+	$10 $1 *hfill *hglue new
+	^^ S[ s" not done" mCanvas text ]S X"   Save  " button new
+	^^ S[ close ]S X"   Close  " button new
+	&3 habox new vfixbox panel
+	&2 vabox new ;
+class;
+
+sizeof a_figure allocate throw constant current-figure
+
+current-figure sizeof a_figure erase
+
+actor class clear-pointer
+  how:
+    : dispose
+	current-figure a_figure active? off
+	current-figure sizeof a_figure erase
+	super dispose ;
+class;
+
+: init-plot   
+    current-figure a_figure active? @ not if
+	screen self mathplot new
+	current-figure a_figure figure !
+	current-figure a_figure active? on
+	clear-pointer new
+	current-figure a_figure figure @
+	mathplot with >callback open endwith
+    then ;
+
+: s>range[] ( fmin fmax -- :] ) 2 :] dup 1 ]! dup 0 ]! ;
+
+: []plot ( x[ str0 xt -- *a_plot )
+    >r >r dup >r
+    mgl_create_data dup rot mgl_data_set_vector
+    sizeof a_plot allocate throw
+    dup r@ dup ]min ]max s>range[] swap a_plot yrange !
+    dup r> ]size  0e s>f s>range[] swap a_plot xrange !
+    dup            0e 0e s>range[] swap a_plot zrange !
+    dup 0 swap a_plot next !
+    dup 0 swap a_plot prev !
+    over 1 ivector* over a_plot hmdtlist !
+    over r> 2 ivector* over a_plot params !
+    ['] @ ['] @ 2 ivector* over a_plot ops !
+    nip r> over a_plot plotfunc ! ;
+: addplot ( *a_plot -- )
+    init-plot
+    current-figure a_figure figure @
+    mathplot with addplot endwith ;
+: ]plot ( *gsl_vector 0"" -- ) ['] mgl_plot []plot addplot ;
+: ]stem ( *gsl_vector 0"" -- ) ['] mgl_stem []plot addplot ;
+: ]bars ( *gsl_vector 0"" -- ) ['] mgl_bars []plot addplot ;
+: ]step ( *gsl_vector 0"" -- ) ['] mgl_step []plot addplot ;
+: ]area ( *gsl_vector 0"" -- ) ['] mgl_area []plot addplot ;
+
+: [[]]plot ( x[[ str0 xt -- *a_plot )
+    >r >r dup >r
+    mgl_create_data dup rot mgl_data_set_matrix
+    sizeof a_plot allocate throw
+    dup r@ dup ]]min ]]max s>range[] swap a_plot zrange !
+    dup r@ ]]size1  0e s>f s>range[] swap a_plot xrange !
+    dup r> ]]size2  0e s>f s>range[] swap a_plot yrange !
+    dup 0 swap a_plot next !
+    dup 0 swap a_plot prev !
+    over 1 ivector* over a_plot hmdtlist !
+    over r> 2 ivector* over a_plot params !
+    ['] @ ['] @ 2 ivector* over a_plot ops !
+    nip r> over a_plot plotfunc ! ;
+: ]]surf ( *gsl_matrix 0"" -- ) ['] mgl_surf [[]]plot addplot ;
+: ]]tile ( *gsl_matrix 0"" -- ) ['] mgl_tile [[]]plot addplot ;
+: ]]belt ( *gsl_matrix 0"" -- ) ['] mgl_belt [[]]plot addplot ;
+: ]]fall ( *gsl_matrix 0"" -- ) ['] mgl_fall [[]]plot addplot ;
+: ]]mesh ( *gsl_matrix 0"" -- ) ['] mgl_mesh [[]]plot addplot ;
+: ]]msurf ( *gsl_matrix 0"" -- )    
+    init-plot
+    2dup ]]surf
+    current-figure a_figure figure @
+    mathplot with hold@ mgl-holdon endwith
+    >r
+    ]]mesh
+    r>
+    current-figure a_figure figure @
+    mathplot with hold! endwith ;
+
+: [[]]plotf ( f:v x[[ str0 xt -- *a_plot )
+    >r >r dup >r
+    mgl_create_data dup rot mgl_data_set_matrix
+    sizeof a_plot allocate throw
+    dup r@ dup ]]min ]]max s>range[] swap a_plot zrange !
+    dup r@ ]]size1  0e s>f s>range[] swap a_plot xrange !
+    dup r> ]]size2  0e s>f s>range[] swap a_plot yrange !
+    dup 0 swap a_plot next !
+    dup 0 swap a_plot prev !
+    over 1 ivector* over a_plot hmdtlist !
+    over r> f>fs 3 ivector* over a_plot params !
+    ['] @ ['] @ ['] sf@ 3 ivector* over a_plot ops !
+    nip r> over a_plot plotfunc ! ;
+: ]]boxs ( f:v *gsl_matrix 0"" -- ) ['] mgl_boxs [[]]plotf addplot ;
+
+: clf current-figure a_figure active? @ if
+	current-figure a_figure figure @ >o mathplot clf o>
+    then ;
+
+: fontsize! ( f:size -- ) current-figure a_figure active? @ if
+	current-figure a_figure figure @ >o mathplot fontsize o>
+    then ;
+
+: rotation ( F: x y z -- )
+    current-figure a_figure active? @ if
+	current-figure a_figure figure @ >o mathplot mgl-rotation! o>
+    else
+	fdrop fdrop fdrop
+    then ;
+: colorbar current-figure a_figure active? @ if
+	current-figure a_figure figure @
+	>o mathplot mgl-colorbar o>
+    then ;
+
+
+: mglhold current-figure a_figure active? @ if
+	current-figure a_figure figure @
+	>o mathplot mgl-hold o>
+    then ;
+
+: mglholdon current-figure a_figure active? @ if
+	current-figure a_figure figure @
+	>o mathplot mgl-holdon o>
+    then ;
+: mglholdoff current-figure a_figure active? @ if
+	current-figure a_figure figure @
+	>o mathplot mgl-holdoff o>
+    then ;
+
+: mglgrid current-figure a_figure active? @ if
+	current-figure a_figure figure @
+	>o mathplot mgl-grid o>
+    then ;
+
+: xlabel ( addr u -- ) current-figure a_figure active? @ if
+	current-figure a_figure figure @
+	>o mathplot mgl-xlabel o>
+    then ;
+: ylabel ( addr u -- ) current-figure a_figure active? @ if
+	current-figure a_figure figure @
+	>o mathplot mgl-ylabel o>
+    then ;
+: zlabel ( addr u -- ) current-figure a_figure active? @ if
+	current-figure a_figure figure @
+	>o mathplot mgl-zlabel o>
+    then ;
+
+
+clear
+previous previous previous previous previous
+Module;
+
+\\\
+also mglplot also minos also gsl
+100 fvector x[ x[ ]randomize
+x[ 0 ]plot
diff --git a/include/mgl2/mpi.h b/include/mgl2/mpi.h
new file mode 100644
index 0000000..1ad2145
--- /dev/null
+++ b/include/mgl2/mpi.h
@@ -0,0 +1,57 @@
+/***************************************************************************
+ * mpi.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef _MGL_MPI_H_
+#define _MGL_MPI_H_
+
+#include "mgl2/mgl_cf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/// Send graphical information to node id using MPI
+void MGL_EXPORT mgl_mpi_send(HMGL gr, int id);
+void MGL_EXPORT mgl_mpi_send_(uintptr_t *gr, int *id);
+/// Receive graphical information from node id using MPI
+void MGL_EXPORT mgl_mpi_recv(HMGL gr, int id);
+void MGL_EXPORT mgl_mpi_recv_(uintptr_t *gr, int *id);
+#ifdef __cplusplus
+}
+
+#include "mgl2/mgl.h"
+//-----------------------------------------------------------------------------
+/// Wrapper class for all graphics
+class MGL_EXPORT mglGraphMPI:public mglGraph
+{
+	mglGraphMPI(const mglGraphMPI &t) {}	// copying is not allowed
+	const mglGraphMPI &operator=(const mglGraphMPI &t)	{	return t;	}
+public:
+	inline mglGraphMPI(int kind=0, int width=600, int height=400):mglGraph(kind,width,height){}
+	inline mglGraphMPI(HMGL graph):mglGraph(graph){}
+	virtual ~mglGraphMPI(){}
+
+	/// Send graphical information to node id using MPI
+	inline void MPI_Send(int id)	{	mgl_mpi_send(gr,id);	}
+	/// Receive graphical information from node id using MPI
+	inline void MPI_Recv(int id)	{	mgl_mpi_recv(gr,id);	}
+
+};
+#endif
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/opengl.h b/include/mgl2/opengl.h
new file mode 100644
index 0000000..98cf1f4
--- /dev/null
+++ b/include/mgl2/opengl.h
@@ -0,0 +1,68 @@
+/***************************************************************************
+ * opengl.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef MGL_CANVAS_GL_H
+#define MGL_CANVAS_GL_H
+//-----------------------------------------------------------------------------
+#include "mgl2/canvas.h"
+//-----------------------------------------------------------------------------
+class MGL_EXPORT mglCanvasGL : public mglCanvas
+{
+public:
+	mglCanvasGL();
+	virtual ~mglCanvasGL();
+
+	void SetQuality(int =0)	{	Quality=2;	}
+	void Finish();
+	void SetSize(int ,int ,bool clf=true)	{	if(clf)	Clf();	}
+	void View(mreal tetX,mreal tetY,mreal tetZ);
+	void Zoom(mreal x1, mreal y1, mreal x2, mreal y2);
+/*	int NewFrame();
+	void EndFrame();
+	void DelFrame(long ){}*/
+
+	bool Alpha(bool enable);
+	void Fog(mreal d, mreal dz=0.25);
+	bool Light(bool enable);
+	void Light(int n, bool enable);
+	void AddLight(int n,mglPoint r,mglPoint d, char c='w', mreal bright=0.5, mreal ap=0);
+	void Clf(mglColor Back=NC);
+	void Clf(const char *col);
+
+protected:
+	// provide fastest variant for usual points (not glyphs or marks)
+	void line_draw(long n1, long n2);
+	void trig_draw(long n1, long n2, long n3);
+	void quad_draw(long n1, long n2, long n3, long n4);
+	// variant for glyphs or marks
+	void line_draw(const mglPnt &p1, const mglPnt &p2, const mglDrawReg *d);
+	void trig_draw(const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, bool anorm, const mglDrawReg *d);
+	void quad_draw(const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, const mglPnt &p4, const mglDrawReg *d);
+	void pnt_draw(const mglPnt &p, const mglDrawReg *d);
+	void mark_draw(const mglPnt &q, char type, mreal size, mglDrawReg *d);
+	void glyph_fill(mreal phi, const mglPnt &p, mreal f, const mglGlyph &g, const mglDrawReg *d);
+	
+	unsigned char **GetRGBLines(long &w, long &h, unsigned char *&f, bool solid=true);
+	void LightScale(const mglMatrix *M);
+
+	void gl_clf(mglColor Back=WC);
+};
+//-----------------------------------------------------------------------------
+#endif
+
diff --git a/include/mgl2/other.h b/include/mgl2/other.h
new file mode 100644
index 0000000..c299ba7
--- /dev/null
+++ b/include/mgl2/other.h
@@ -0,0 +1,184 @@
+/***************************************************************************
+ * other.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_OTHER_H_
+#define _MGL_OTHER_H_
+#include "mgl2/abstract.h"
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// Draw triangle mesh for points in arrays {x,y,z} with specified color c.
+/** Style ‘#’ produce wire plot. If id.ny=c.nx then c set the triangle colors, else vertex colors. */
+void MGL_EXPORT mgl_triplot_xyzc(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, HCDT c, const char *sch, const char *opt);
+void MGL_EXPORT mgl_triplot_xyzc_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt,int,int);
+/// Draw triangle mesh for points in arrays {x,y,z} with color proportional to z.
+/** Style ‘#’ produce wire plot. */
+void MGL_EXPORT mgl_triplot_xyz(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_triplot_xyz_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw triangle mesh for points in arrays {x,y}
+/** Style ‘#’ produce wire plot. */
+void MGL_EXPORT mgl_triplot_xy(HMGL gr, HCDT nums, HCDT x, HCDT y, const char *sch, const char *opt);
+void MGL_EXPORT mgl_triplot_xy_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, const char *sch, const char *opt,int,int);
+
+/// Draw quad mesh for points in arrays {x,y,z} with specified color c.
+/** Style ‘#’ produce wire plot. If id.ny=c.nx then c set the quadrangle colors, else vertex colors. */
+void MGL_EXPORT mgl_quadplot_xyzc(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, HCDT c, const char *sch, const char *opt);
+void MGL_EXPORT mgl_quadplot_xyzc_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt,int,int);
+/// Draw quad mesh for points in arrays {x,y,z} with color proportional to z.
+/** Style ‘#’ produce wire plot. */
+void MGL_EXPORT mgl_quadplot_xyz(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_quadplot_xyz_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw quad mesh for points in arrays {x,y}.
+/** Style ‘#’ produce wire plot. */
+void MGL_EXPORT mgl_quadplot_xy(HMGL gr, HCDT nums, HCDT x, HCDT y, const char *sch, const char *opt);
+void MGL_EXPORT mgl_quadplot_xy_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, const char *sch, const char *opt,int,int);
+
+/// Draw manual contour lines for triangle mesh for points in arrays {x,y,z} with specified color c.
+/** Style ‘_’ to draw contours at bottom of axis box.
+ * Style ‘t’/‘T’ draw contour labels below/above contours.
+ * If id.ny=c.nx then c set the quadrangle colors, else vertex colors. */
+void MGL_EXPORT mgl_tricont_xyzcv(HMGL gr, HCDT v, HCDT nums, HCDT x, HCDT y, HCDT z, HCDT c, const char *sch, const char *opt);
+void MGL_EXPORT mgl_tricont_xyzcv_(uintptr_t *gr, uintptr_t *v, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt,int,int);
+/// Draw manual contour lines for triangle mesh for points in arrays {x,y,z}.
+/** Style ‘_’ to draw contours at bottom of axis box.
+ * Style ‘t’/‘T’ draw contour labels below/above contours.
+ * If id.ny=c.nx then c set the quadrangle colors, else vertex colors. */
+void MGL_EXPORT mgl_tricont_xycv(HMGL gr, HCDT v, HCDT nums, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_tricont_xycv_(uintptr_t *gr, uintptr_t *v, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw contour lines for triangle mesh for points in arrays {x,y,z} with specified color c.
+/** Style ‘_’ to draw contours at bottom of axis box.
+ * Style ‘t’/‘T’ draw contour labels below/above contours.
+ * If id.ny=c.nx then c set the quadrangle colors, else vertex colors.
+ * Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_tricont_xyzc(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, HCDT c, const char *sch, const char *opt);
+void MGL_EXPORT mgl_tricont_xyzc_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt,int, int);
+/// Draw contour lines for triangle mesh for points in arrays {x,y,z}.
+/** Style ‘_’ to draw contours at bottom of axis box.
+ * Style ‘t’/‘T’ draw contour labels below/above contours.
+ * If id.ny=c.nx then c set the quadrangle colors, else vertex colors.
+ * Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_tricont_xyc(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_tricont_xyc_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int, int);
+
+/// Draw manual contour tubes for triangle mesh for points in arrays {x,y,z} with specified color c.
+/** If id.ny=c.nx then c set the quadrangle colors, else vertex colors. */
+void MGL_EXPORT mgl_tricontv_xyzcv(HMGL gr, HCDT v, HCDT nums, HCDT x, HCDT y, HCDT z, HCDT c, const char *sch, const char *opt);
+void MGL_EXPORT mgl_tricontv_xyzcv_(uintptr_t *gr, uintptr_t *v, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt,int,int);
+/// Draw manual contour tubes for triangle mesh for points in arrays {x,y,z}.
+/** If id.ny=c.nx then c set the quadrangle colors, else vertex colors. */
+void MGL_EXPORT mgl_tricontv_xycv(HMGL gr, HCDT v, HCDT nums, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_tricontv_xycv_(uintptr_t *gr, uintptr_t *v, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw contour tubes for triangle mesh for points in arrays {x,y,z} with specified color c.
+/** If id.ny=c.nx then c set the quadrangle colors, else vertex colors.
+ * Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_tricontv_xyzc(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, HCDT c, const char *sch, const char *opt);
+void MGL_EXPORT mgl_tricontv_xyzc_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt,int, int);
+/// Draw contour tubes for triangle mesh for points in arrays {x,y,z}.
+/** If id.ny=c.nx then c set the quadrangle colors, else vertex colors.
+ * Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_tricontv_xyc(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_tricontv_xyc_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int, int);
+
+/// Draw dots in points {x,y,z}.
+void MGL_EXPORT mgl_dots(HMGL gr, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_dots_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw semitransparent dots in points {x,y,z} with specified alpha a.
+void MGL_EXPORT mgl_dots_a(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt);
+void MGL_EXPORT mgl_dots_a_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, const char *opt,int,int);
+/// Draw semitransparent dots in points {x,y,z} with specified color c and alpha a.
+void MGL_EXPORT mgl_dots_ca(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT c, HCDT a, const char *sch, const char *opt);
+void MGL_EXPORT mgl_dots_ca_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, uintptr_t *a, const char *sch, const char *opt,int,int);
+
+/// Draw surface reconstructed for points in arrays {x,y,z}.
+/** Style ‘#’ produce wired plot. */
+void MGL_EXPORT mgl_crust(HMGL gr, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_crust_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int,int);
+
+/// Draw density plot for data at x = sVal
+/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+void MGL_EXPORT mgl_dens_x(HMGL graph, HCDT a, const char *stl, double sVal, const char *opt);
+void MGL_EXPORT mgl_dens_x_(uintptr_t *graph, uintptr_t *a, const char *stl, mreal *sVal, const char *opt,int,int);
+/// Draw density plot for data at y = sVal
+/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+void MGL_EXPORT mgl_dens_y(HMGL graph, HCDT a, const char *stl, double sVal, const char *opt);
+void MGL_EXPORT mgl_dens_y_(uintptr_t *graph, uintptr_t *a, const char *stl, mreal *sVal, const char *opt,int,int);
+/// Draw density plot for data at z = sVal
+/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+void MGL_EXPORT mgl_dens_z(HMGL graph, HCDT a, const char *stl, double sVal, const char *opt);
+void MGL_EXPORT mgl_dens_z_(uintptr_t *graph, uintptr_t *a, const char *stl, mreal *sVal, const char *opt,int,int);
+
+/// Draw contour lines for data at x = sVal
+/** Style ‘t’/‘T’ draw contour labels below/above contours.
+ * Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_cont_x(HMGL graph, HCDT a, const char *stl, double sVal, const char *opt);
+void MGL_EXPORT mgl_cont_x_(uintptr_t *graph, uintptr_t *a, const char *stl, mreal *sVal, const char *opt,int,int);
+/// Draw contour lines for data at y = sVal
+/** Style ‘t’/‘T’ draw contour labels below/above contours.
+ * Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_cont_y(HMGL graph, HCDT a, const char *stl, double sVal, const char *opt);
+void MGL_EXPORT mgl_cont_y_(uintptr_t *graph, uintptr_t *a, const char *stl, mreal *sVal, const char *opt,int,int);
+/// Draw contour lines for data at z = sVal
+/** Style ‘t’/‘T’ draw contour labels below/above contours.
+ * Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_cont_z(HMGL graph, HCDT a, const char *stl, double sVal, const char *opt);
+void MGL_EXPORT mgl_cont_z_(uintptr_t *graph, uintptr_t *a, const char *stl, mreal *sVal, const char *opt,int,int);
+
+/// Draw manual contour lines for data at x = sVal
+/** Style ‘t’/‘T’ draw contour labels below/above contours. */
+void MGL_EXPORT mgl_cont_x_val(HMGL graph, HCDT v, HCDT a, const char *stl, double sVal, const char *opt);
+void MGL_EXPORT mgl_cont_x_val_(uintptr_t *graph, uintptr_t *v, uintptr_t *a, const char *stl, mreal *sVal, const char *opt,int,int);
+/// Draw manual contour lines for data at y = sVal
+/** Style ‘t’/‘T’ draw contour labels below/above contours. */
+void MGL_EXPORT mgl_cont_y_val(HMGL graph, HCDT v, HCDT a, const char *stl, double sVal, const char *opt);
+void MGL_EXPORT mgl_cont_y_val_(uintptr_t *graph, uintptr_t *v, uintptr_t *a, const char *stl, mreal *sVal, const char *opt,int,int);
+/// Draw manual contour lines for data at z = sVal
+/** Style ‘t’/‘T’ draw contour labels below/above contours. */
+void MGL_EXPORT mgl_cont_z_val(HMGL graph, HCDT v, HCDT a, const char *stl, double sVal, const char *opt);
+void MGL_EXPORT mgl_cont_z_val_(uintptr_t *graph, uintptr_t *v, uintptr_t *a, const char *stl, mreal *sVal, const char *opt,int,int);
+
+/// Draw solid contours for data at x = sVal
+/** Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_contf_x(HMGL graph, HCDT a, const char *stl, double sVal, const char *opt);
+void MGL_EXPORT mgl_contf_x_(uintptr_t *graph, uintptr_t *a, const char *stl, mreal *sVal, const char *opt,int,int);
+/// Draw solid contours for data at y = sVal
+/** Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_contf_y(HMGL graph, HCDT a, const char *stl, double sVal, const char *opt);
+void MGL_EXPORT mgl_contf_y_(uintptr_t *graph, uintptr_t *a, const char *stl, mreal *sVal, const char *opt,int,int);
+/// Draw solid contours for data at z = sVal
+/** Option "value" set the number of contour levels (default is 7). */
+void MGL_EXPORT mgl_contf_z(HMGL graph, HCDT a, const char *stl, double sVal, const char *opt);
+void MGL_EXPORT mgl_contf_z_(uintptr_t *graph, uintptr_t *a, const char *stl, mreal *sVal, const char *opt,int,int);
+
+/// Draw manual solid contours for data at x = sVal
+void MGL_EXPORT mgl_contf_x_val(HMGL graph, HCDT v, HCDT a, const char *stl, double sVal, const char *opt);
+void MGL_EXPORT mgl_contf_x_val_(uintptr_t *graph, uintptr_t *v, uintptr_t *a, const char *stl, mreal *sVal, const char *opt,int,int);
+/// Draw manual solid contours for data at y = sVal
+void MGL_EXPORT mgl_contf_y_val(HMGL graph, HCDT v, HCDT a, const char *stl, double sVal, const char *opt);
+void MGL_EXPORT mgl_contf_y_val_(uintptr_t *graph, uintptr_t *v, uintptr_t *a, const char *stl, mreal *sVal, const char *opt,int,int);
+/// Draw manual solid contours for data at z = sVal
+void MGL_EXPORT mgl_contf_z_val(HMGL graph, HCDT v, HCDT a, const char *stl, double sVal, const char *opt);
+void MGL_EXPORT mgl_contf_z_val_(uintptr_t *graph, uintptr_t *v, uintptr_t *a, const char *stl, mreal *sVal, const char *opt,int,int);
+
+#ifdef __cplusplus
+}
+#endif
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/parser.h b/include/mgl2/parser.h
new file mode 100644
index 0000000..ccf27c9
--- /dev/null
+++ b/include/mgl2/parser.h
@@ -0,0 +1,200 @@
+/***************************************************************************
+ * parser.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_PARSER_H_
+#define _MGL_PARSER_H_
+
+#ifdef __cplusplus
+#include "mgl2/mgl.h"
+#if MGL_HAVE_LTDL
+#include <ltdl.h>
+#endif
+//-----------------------------------------------------------------------------
+/// Structure for the command argument.
+struct mglArg
+{
+	int type;		///< Type of argument {0-data,1-string,2-number}
+	mglDataA *d;	///< Pointer to data (used if type==0)
+	std::wstring w;	///< String with parameters
+	std::string s;	///< String with parameters
+	mreal v;		///< Numerical value (used if type==2)
+	dual c;			///< Numerical complex value (used if type==2)
+	mglArg():type(-1),d(0),v(0),c(0.)	{}
+};
+//-----------------------------------------------------------------------------
+/// Structure for MGL command
+struct mglCommand
+{
+	const char *name;	///< Name of command
+	const char *desc;	///< Short command description (can be NULL)
+	const char *form;	///< Format of command arguments (can be NULL)
+	/// Function for executing (plotting)
+	int (*exec)(mglGraph *gr, long n, mglArg *a, const char *k, const char *opt);
+	/// Type of command: 0 - special plot, 1 - other plot,
+	///	2 - setup, 3 - data handle, 4 - data create, 5 - subplot, 6 - program
+	///	7 - 1d plot, 8 - 2d plot, 9 - 3d plot, 10 - dd plot, 11 - vector plot
+	///	12 - axis, 13 - primitives, 14 - axis setup, 15 - text/legend, 16 - data transform
+	int type;
+};
+extern mglCommand mgls_prg_cmd[], mgls_dat_cmd[], mgls_grf_cmd[], mgls_set_cmd[], mgls_prm_cmd[];
+//-----------------------------------------------------------------------------
+/// Structure for function name and position.
+struct mglFunc
+{
+	long pos;
+	int narg;
+	std::wstring func;
+	mglFunc(long p, const wchar_t *f);
+	mglFunc(const mglFunc &f):pos(f.pos),narg(f.narg),func(f.func)	{}
+	mglFunc():pos(-1),narg(-1)	{}
+	const mglFunc &operator=(const mglFunc &f)
+	{	pos=f.pos;	narg=f.narg;	func=f.func;	return f;	}
+};
+//-----------------------------------------------------------------------------
+/// Structure for stack of functions and its arguments.
+struct mglFnStack
+{
+	long pos;
+	std::wstring par[10];
+	mglFnStack():pos(0)	{}
+};
+//-----------------------------------------------------------------------------
+/// Function for asking question in console mode
+void MGL_EXPORT mgl_ask_gets(const wchar_t *quest, wchar_t *res);
+//-----------------------------------------------------------------------------
+/// Structure for the command argument (see mglGraph::Exec()).
+class mglParser
+{
+friend void mgl_export(wchar_t *out, const wchar_t *in, int type);
+public:
+#if MGL_HAVE_LTDL
+	std::vector<lt_dlhandle> DllOpened;	///< Opened external DLL (keep )
+#endif
+	std::vector<mglDataA*> DataList;	///< List with data and its names
+	std::vector<mglNum*> NumList;	///< List with numbers and its names
+	bool AllowDllCall;	///< Allow calls from external dynamic libraries
+	bool AllowSetSize;	///< Allow using setsize command
+	bool AllowFileIO;	///< Allow reading/saving files
+	volatile bool Stop;	///< Stop command was. Flag prevent further execution
+	mglCommand *Cmd;	///< Table of MGL commands (can be changed by user). It MUST be sorted by 'name'!!!
+	long InUse;			///< Smart pointer (number of users)
+	const mglBase *curGr;	///< Current grapher
+	int StarObhID;		///< staring object id
+
+	mglParser(bool setsize=false);
+	virtual ~mglParser();
+	/// Find the command by the keyword name
+	const mglCommand *FindCommand(const char *name) const MGL_FUNC_PURE;
+	const mglCommand *FindCommand(const wchar_t *name) const MGL_FUNC_PURE;
+	/// Parse and execute the string of MGL script
+	inline int Parse(HMGL gr, const char *str, long pos=0)
+	{	mglGraph GR(gr);	return Parse(&GR,str,pos);	}
+	int Parse(mglGraph *gr, const char *str, long pos=0);
+	/// Parse and execute the unicode string of MGL script
+	inline int Parse(HMGL gr, const wchar_t *str, long pos=0)
+	{	mglGraph GR(gr);	return Parse(&GR,str,pos);	}
+	int Parse(mglGraph *gr, std::wstring str, long pos=0);
+	/// Execute MGL script file fname
+	inline void Execute(HMGL gr, FILE *fp, bool print=false)
+	{	mglGraph GR(gr);	Execute(&GR,fp,print);	}
+	void Execute(mglGraph *gr, FILE *fp, bool print=false);
+	/// Execute MGL script from array of lines
+	inline void Execute(HMGL gr, int num, const wchar_t **text)
+	{	mglGraph GR(gr);	Execute(&GR,num,text);	}
+	void Execute(mglGraph *gr, int num, const wchar_t **text);
+	/// Execute MGL script text with '\n' separated lines
+	inline void Execute(HMGL gr, const wchar_t *text)
+	{	mglGraph GR(gr);	Execute(&GR,text);	}
+	void Execute(mglGraph *gr, const wchar_t *text);
+	/// Execute MGL script text with '\n' separated lines
+	inline void Execute(HMGL gr, const char *text)
+	{	mglGraph GR(gr);	Execute(&GR,text);	}
+	void Execute(mglGraph *gr, const char *text);
+	/// Scan for functions (use NULL for reset)
+	void ScanFunc(const wchar_t *line);
+	/// Check if name is function and return its address (or 0 if no)
+	long IsFunc(const std::wstring &name, int *narg=0);
+	/// Find variable or return 0 if absent
+	mglDataA *FindVar(const char *name) MGL_FUNC_PURE;
+	mglDataA *FindVar(const wchar_t *name) MGL_FUNC_PURE;
+	/// Find variable or create it if absent
+	mglDataA *AddVar(const char *name);
+	mglDataA *AddVar(const wchar_t *name);
+	/// Find number or return 0 if absent
+	mglNum *FindNum(const char *name) MGL_FUNC_PURE;
+	mglNum *FindNum(const wchar_t *name) MGL_FUNC_PURE;
+	/// Find number or create it if absent
+	mglNum *AddNum(const char *name);
+	mglNum *AddNum(const wchar_t *name);
+	/// Add string for parameter $1, ..., $9
+	void AddParam(int n, const char *str);
+	void AddParam(int n, const wchar_t *str);
+	/// Add new MGL command(s) (last command MUST HAVE name[0]=0 !!!)
+	void AddCommand(const mglCommand *cmd);
+	/// Restore Once flag
+	inline void RestoreOnce()	{	Once = true;	}
+	/// Delete variable by its name
+	void DeleteVar(const char *name);
+	void DeleteVar(const wchar_t *name);
+	/// Delete all data variables
+	void DeleteAll();
+	/// Set variant of argument(s) separated by '?' to be used
+	inline void SetVariant(int var=0)	{	Variant = var<=0?0:var;	}
+protected:
+	static mglCommand *BaseCmd;	///< Base table of MGL commands. It MUST be sorted by 'name'!!!
+	static void FillBaseCmd();	///< Fill BaseCmd at initialization stage
+private:
+//	long parlen;		///< Length of parameter strings
+	std::wstring par[40];	///< Parameter for substituting instead of $1, ..., $9
+	bool Once;			///< Flag for command which should be executed only once
+	bool Skip;			///< Flag that commands should be skiped (inside 'once' block)
+	int if_stack[40];	///< Stack for if-else-endif commands
+	int if_pos;			///< position in if_stack
+	std::vector<mglFunc> func;	///< function names and position
+	std::vector<mglFnStack> fn_stack;	///< function calls stack
+//	int fn_pos;			///< position in function stack
+	int if_for[40];		///< position in if_stack for for-cycle start
+	mglData *fval;		///< Values for for-cycle. Note that nx - number of elements, ny - next element, nz - address (or string number) of first cycle command
+	int for_stack[40];	///< The order of for-variables
+	int for_addr;		///< Flag for saving address in variable (for_addr-1)
+	bool for_br;		///< Break is switched on (skip all commands until 'next')
+	unsigned Variant;	///< Select variant of argument(s) separated by '?'
+
+	/// Parse command
+	int Exec(mglGraph *gr, const wchar_t *com, long n, mglArg *a, const std::wstring &var, const wchar_t *opt);
+	/// Fill arguments a from strings
+	void FillArg(mglGraph *gr, int n, std::wstring *arg, mglArg *a);
+	/// PreExecute stage -- parse some commands and create variables
+	int PreExec(mglGraph *gr, long n, std::wstring *arg, mglArg *a);
+	/// Execute program-flow control commands
+	int FlowExec(mglGraph *gr, const std::wstring &com, long n, mglArg *a);
+	/// Parse and execute the unicode string of MGL script
+	int ParseDat(mglGraph *gr, std::wstring str, mglData &res);
+	/// Define '$' parameters or start for loop
+	int ParseDef(std::wstring &str);
+	/// Parse $N arguments
+	void PutArg(std::wstring &str, bool def);
+	/// In skip mode
+	bool inline ifskip()	{	return (if_pos>0 && !(if_stack[if_pos-1]&1));	}
+	bool inline skip()		{	return (Skip || ifskip() || for_br);	}
+	bool CheckForName(const std::wstring &s);	// check if name is valid for new data
+};
+//-----------------------------------------------------------------------------
+#endif
+#endif
diff --git a/include/mgl2/pde.h b/include/mgl2/pde.h
new file mode 100644
index 0000000..6b59eb4
--- /dev/null
+++ b/include/mgl2/pde.h
@@ -0,0 +1,84 @@
+/***************************************************************************
+ * pde.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_PDE_H_
+#define _MGL_PDE_H_
+//-----------------------------------------------------------------------------
+#include "mgl2/abstract.h"
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// Saves result of PDE solving (|u|^2) for "Hamiltonian" ham with initial conditions ini
+HADT MGL_EXPORT mgl_pde_solve_c(HMGL gr, const char *ham, HCDT ini_re, HCDT ini_im, mreal dz, mreal k0,const char *opt);
+uintptr_t MGL_EXPORT mgl_pde_solve_c_(uintptr_t* gr, const char *ham, uintptr_t* ini_re, uintptr_t* ini_im, mreal *dz, mreal *k0,const char *opt,int,int);
+/// Saves result of PDE solving (|u|^2) for "Hamiltonian" ham with initial conditions ini
+HMDT MGL_EXPORT mgl_pde_solve(HMGL gr, const char *ham, HCDT ini_re, HCDT ini_im, mreal dz, mreal k0,const char *opt);
+uintptr_t MGL_EXPORT mgl_pde_solve_(uintptr_t* gr, const char *ham, uintptr_t* ini_re, uintptr_t* ini_im, mreal *dz, mreal *k0,const char *opt,int,int);
+
+/// Saves result of PDE solving (|u|^2) for "Hamiltonian" ham with initial conditions ini. This function use more accurate but slow algorithm.
+HADT MGL_EXPORT mgl_pde_adv_c(HMGL gr, const char *ham, HCDT ini_re, HCDT ini_im, mreal dz, mreal k0,const char *opt);
+uintptr_t MGL_EXPORT mgl_pde_adv_c_(uintptr_t* gr, const char *ham, uintptr_t* ini_re, uintptr_t* ini_im, mreal *dz, mreal *k0,const char *opt,int,int);
+/// Saves result of PDE solving (|u|^2) for "Hamiltonian" ham with initial conditions ini. This function use more accurate but slow algorithm.
+HMDT MGL_EXPORT mgl_pde_adv(HMGL gr, const char *ham, HCDT ini_re, HCDT ini_im, mreal dz, mreal k0,const char *opt);
+uintptr_t MGL_EXPORT mgl_pde_adv_(uintptr_t* gr, const char *ham, uintptr_t* ini_re, uintptr_t* ini_im, mreal *dz, mreal *k0,const char *opt,int,int);
+
+/// Saves result of PDE solving for "Hamiltonian" ham with initial conditions ini along a curve ray (must have nx>=7 - x,y,z,px,py,pz,tau or nx=5 - x,y,px,py,tau)
+HADT MGL_EXPORT mgl_qo2d_solve_c(const char *ham, HCDT ini_re, HCDT ini_im, HCDT ray, mreal r, mreal k0, HMDT xx, HMDT yy);
+HADT MGL_EXPORT mgl_qo2d_func_c(ddual (*ham)(mreal u, mreal x, mreal y, mreal px, mreal py, void *par), void *par, HCDT ini_re, HCDT ini_im, HCDT ray, mreal r, mreal k0, HMDT xx, HMDT yy);
+uintptr_t MGL_EXPORT mgl_qo2d_solve_c_(const char *ham, uintptr_t* ini_re, uintptr_t* ini_im, uintptr_t* ray, mreal *r, mreal *k0, uintptr_t* xx, uintptr_t* yy, int);
+/// Saves result of PDE solving for "Hamiltonian" ham with initial conditions ini along a curve ray (must have nx>=7 - x,y,z,px,py,pz,tau or nx=5 - x,y,px,py,tau)
+HMDT MGL_EXPORT mgl_qo2d_solve(const char *ham, HCDT ini_re, HCDT ini_im, HCDT ray, mreal r, mreal k0, HMDT xx, HMDT yy);
+HMDT MGL_EXPORT mgl_qo2d_func(ddual (*ham)(mreal u, mreal x, mreal y, mreal px, mreal py, void *par), void *par, HCDT ini_re, HCDT ini_im, HCDT ray, mreal r, mreal k0, HMDT xx, HMDT yy);
+uintptr_t MGL_EXPORT mgl_qo2d_solve_(const char *ham, uintptr_t* ini_re, uintptr_t* ini_im, uintptr_t* ray, mreal *r, mreal *k0, uintptr_t* xx, uintptr_t* yy, int);
+
+/// Saves result of PDE solving for "Hamiltonian" ham with initial conditions ini along a curve ray (must have nx>=7 - x,y,z,px,py,pz,tau or nx=5 - x,y,px,py,tau)
+HADT MGL_EXPORT mgl_qo3d_solve_c(const char *ham, HCDT ini_re, HCDT ini_im, HCDT ray, mreal r, mreal k0, HMDT xx, HMDT yy, HMDT zz);
+HADT MGL_EXPORT mgl_qo3d_func_c(ddual (*ham)(mreal u, mreal x, mreal y, mreal z, mreal px, mreal py, mreal pz, void *par), void *par, HCDT ini_re, HCDT ini_im, HCDT ray, mreal r, mreal k0, HMDT xx, HMDT yy, HMDT zz);
+uintptr_t MGL_EXPORT mgl_qo3d_solve_c_(const char *ham, uintptr_t* ini_re, uintptr_t* ini_im, uintptr_t* ray, mreal *r, mreal *k0, uintptr_t* xx, uintptr_t* yy, uintptr_t* zz, int);
+/// Saves result of PDE solving for "Hamiltonian" ham with initial conditions ini along a curve ray (must have nx>=7 - x,y,z,px,py,pz,tau or nx=5 - x,y,px,py,tau)
+HMDT MGL_EXPORT mgl_qo3d_solve(const char *ham, HCDT ini_re, HCDT ini_im, HCDT ray, mreal r, mreal k0, HMDT xx, HMDT yy, HMDT zz);
+HMDT MGL_EXPORT mgl_qo3d_func(ddual (*ham)(mreal u, mreal x, mreal y, mreal z, mreal px, mreal py, mreal pz, void *par), void *par, HCDT ini_re, HCDT ini_im, HCDT ray, mreal r, mreal k0, HMDT xx, HMDT yy, HMDT zz);
+uintptr_t MGL_EXPORT mgl_qo3d_solve_(const char *ham, uintptr_t* ini_re, uintptr_t* ini_im, uintptr_t* ray, mreal *r, mreal *k0, uintptr_t* xx, uintptr_t* yy, uintptr_t* zz, int);
+
+/// Saves result of ODE solving of n equations with right part func and initial conditions x0 over time interval [0,tmax] with time step dt
+HMDT MGL_EXPORT mgl_ode_solve(void (*func)(const mreal *x, mreal *dx, void *par), int n, const mreal *x0, mreal dt, mreal tmax, void *par);
+/// Saves result of ODE solving for var variables with right part func (separated by ';') and initial conditions x0 over time interval [0,tmax] with time step dt
+HMDT MGL_EXPORT mgl_ode_solve_str(const char *func, const char *var, HCDT x0, mreal dt, mreal tmax);
+/// Saves result of ODE solving for var complex variables with right part func (separated by ';') and initial conditions x0 over time interval [0,tmax] with time step dt
+HADT MGL_EXPORT mgl_ode_solve_str_c(const char *func, const char *var, HCDT x0, mreal dt, mreal tmax);
+/// Saves result of ODE solving of n equations with right part func and initial conditions x0 over time interval [0,tmax] with time step dt. Function bord (if not NULL) is called each time step to apply border reflection.
+HMDT MGL_EXPORT mgl_ode_solve_ex(void (*func)(const mreal *x, mreal *dx, void *par), int n, const mreal *x0, mreal dt, mreal tmax, void *par, void (*bord)(mreal *x, const mreal *xp, void *par));
+/// Finds ray with starting point r0, p0 (and prepares ray data for mgl_qo2d_solve)
+HMDT MGL_EXPORT mgl_ray_trace(const char *ham, mreal x0, mreal y0, mreal z0, mreal px, mreal py, mreal pz, mreal dt, mreal tmax);
+uintptr_t MGL_EXPORT mgl_ray_trace_(const char *ham, mreal *x0, mreal *y0, mreal *z0, mreal *px, mreal *py, mreal *pz, mreal *dt, mreal *tmax,int);
+
+/// Calculate Jacobian determinant for D{x(u,v), y(u,v)} = dx/du*dy/dv-dx/dv*dy/du
+HMDT MGL_EXPORT mgl_jacobian_2d(HCDT x, HCDT y);
+uintptr_t MGL_EXPORT mgl_jacobian_2d_(uintptr_t* x, uintptr_t* y);
+/// Calculate Jacobian determinant for D{x(u,v,w), y(u,v,w), z(u,v,w)}
+HMDT MGL_EXPORT mgl_jacobian_3d(HCDT x, HCDT y, HCDT z);
+uintptr_t MGL_EXPORT mgl_jacobian_3d_(uintptr_t* x, uintptr_t* y, uintptr_t* z);
+
+#ifdef __cplusplus
+}
+#endif
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/plot.h b/include/mgl2/plot.h
new file mode 100644
index 0000000..90312df
--- /dev/null
+++ b/include/mgl2/plot.h
@@ -0,0 +1,260 @@
+/***************************************************************************
+ * plot.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_1D_H_
+#define _MGL_1D_H_
+#include "mgl2/abstract.h"
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// Draw curve for formula with x in x-axis range
+/** Option "value" set initial number of points. */
+void MGL_EXPORT mgl_fplot(HMGL gr, const char *eqY, const char *pen, const char *opt);
+void MGL_EXPORT mgl_fplot_(uintptr_t *gr, const char *fy, const char *stl, const char *opt, int ly, int ls, int lo);
+/// Draw curve for formulas parametrically depended on t in range [0,1]
+/** Option "value" set initial number of points. */
+void MGL_EXPORT mgl_fplot_xyz(HMGL gr, const char *eqX, const char *eqY, const char *eqZ, const char *pen, const char *opt);
+void MGL_EXPORT mgl_fplot_xyz_(uintptr_t *gr, const char *fx, const char *fy, const char *fz, const char *stl, const char *opt, int lx, int ly, int lz, int ls, int lo);
+
+/// Draw radar chart (plot in curved coordinates)
+/** Option "value" set the additional shift of data (i.e. the data a+value is used instead of a).*/
+void MGL_EXPORT mgl_radar(HMGL graph, HCDT a, const char *pen, const char *opt);
+void MGL_EXPORT mgl_radar_(uintptr_t *gr, uintptr_t *a, const char *pen, const char *opt, int l,int lo);
+
+/// Draw usual curve {x,y,z}
+void MGL_EXPORT mgl_plot_xyz(HMGL graph, HCDT x, HCDT y, HCDT z, const char *pen, const char *opt);
+void MGL_EXPORT mgl_plot_xyz_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *pen, const char *opt,int,int);
+/// Draw usual curve {x,y}
+void MGL_EXPORT mgl_plot_xy(HMGL graph, HCDT x, HCDT y, const char *pen, const char *opt);
+void MGL_EXPORT mgl_plot_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, const char *pen, const char *opt,int,int);
+/// Draw usual curve {x,y} with x in x-axis range
+void MGL_EXPORT mgl_plot(HMGL graph, HCDT y, const char *pen, const char *opt);
+void MGL_EXPORT mgl_plot_(uintptr_t *graph, uintptr_t *y,	const char *pen, const char *opt,int,int);
+
+/// Draw curve {x,y,z} which is colored by c (like tension plot)
+void MGL_EXPORT mgl_tens_xyz(HMGL graph, HCDT x, HCDT y, HCDT z, HCDT c, const char *pen, const char *opt);
+void MGL_EXPORT mgl_tens_xyz_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *pen, const char *opt,int,int);
+/// Draw curve {x,y} which is colored by c (like tension plot)
+void MGL_EXPORT mgl_tens_xy(HMGL graph, HCDT x, HCDT y, HCDT c, const char *pen, const char *opt);
+void MGL_EXPORT mgl_tens_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *c, const char *pen, const char *opt,int,int);
+/// Draw curve {x,y} with x in x-axis range which is colored by c (like tension plot)
+void MGL_EXPORT mgl_tens(HMGL graph, HCDT y, HCDT c, const char *pen, const char *opt);
+void MGL_EXPORT mgl_tens_(uintptr_t *graph, uintptr_t *y, uintptr_t *c, const char *pen, const char *opt,int,int);
+
+/// Draw tapes which rotates as (bi-)normales of curve {x,y,z}
+/** The width of tape is proportional to barwidth and can be changed by option "value".*/
+void MGL_EXPORT mgl_tape_xyz(HMGL graph, HCDT x, HCDT y, HCDT z, const char *pen, const char *opt);
+void MGL_EXPORT mgl_tape_xyz_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *pen, const char *opt,int,int);
+/// Draw tapes which rotates as (bi-)normales of curve {x,y}
+/** The width of tape is proportional to barwidth and can be changed by option "value".*/
+void MGL_EXPORT mgl_tape_xy(HMGL graph, HCDT x, HCDT y, const char *pen, const char *opt);
+void MGL_EXPORT mgl_tape_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, const char *pen, const char *opt,int,int);
+/// Draw tapes which rotates as (bi-)normales of curve {x,y} with x in x-axis range
+/** The width of tape is proportional to barwidth and can be changed by option "value".*/
+void MGL_EXPORT mgl_tape(HMGL graph, HCDT y, const char *pen, const char *opt);
+void MGL_EXPORT mgl_tape_(uintptr_t *graph, uintptr_t *y,	const char *pen, const char *opt,int,int);
+
+/// Draw box-plot (special 5-value plot used in statistic) for data specified parametrically
+/** String \a pen may contain ‘<’, ‘^’, ‘>’ for aligning boxes: at left, centered, at right.*/
+void MGL_EXPORT mgl_boxplot_xy(HMGL graph, HCDT x, HCDT a, const char *pen, const char *opt);
+void MGL_EXPORT mgl_boxplot_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, const char *pen, const char *opt,int,int);
+/// Draw box-plot (special 5-value plot used in statistic)
+/** String \a pen may contain ‘<’, ‘^’, ‘>’ for aligning boxes: at left, centered, at right.*/
+void MGL_EXPORT mgl_boxplot(HMGL graph, HCDT a, const char *pen, const char *opt);
+void MGL_EXPORT mgl_boxplot_(uintptr_t *graph, uintptr_t *y, const char *pen, const char *opt,int,int);
+
+/// Fill area between curve {x,y,z} and axis plane
+/** Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+void MGL_EXPORT mgl_area_xyz(HMGL graph, HCDT x, HCDT y, HCDT z, const char *pen, const char *opt);
+void MGL_EXPORT mgl_area_xyz_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *pen, const char *opt,int,int);
+/// Fill area between curve {x,y} and axis plane
+/** Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+void MGL_EXPORT mgl_area_xy(HMGL graph, HCDT x, HCDT y, const char *pen, const char *opt);
+void MGL_EXPORT mgl_area_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, const char *pen, const char *opt,int,int);
+/// Fill area between curve {x,y} with x in x-axis range and axis plane
+/** Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+void MGL_EXPORT mgl_area(HMGL graph, HCDT y, const char *pen, const char *opt);
+void MGL_EXPORT mgl_area_(uintptr_t *graph, uintptr_t *y, const char *pen, const char *opt,int,int);
+
+/// Fill area (draw ribbon) between curves {x1,y1,z1} and {x2,y2,z2}
+/** Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+void MGL_EXPORT mgl_region_3d(HMGL graph, HCDT x1, HCDT y1, HCDT z1, HCDT x2, HCDT y2, HCDT z2, const char *pen, const char *opt);
+void MGL_EXPORT mgl_region_3d_(uintptr_t *graph, uintptr_t *x1, uintptr_t *y1, uintptr_t *z1, uintptr_t *x2, uintptr_t *y2, uintptr_t *z2, const char *pen, const char *opt,int,int);
+/// Fill area between curves {x,y1} and {x,y2}
+/** Style 'i' will fill area only if y1 < y2.
+  * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+void MGL_EXPORT mgl_region_xy(HMGL graph, HCDT x, HCDT y1, HCDT y2, const char *pen, const char *opt);
+void MGL_EXPORT mgl_region_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y1, uintptr_t *y2, const char *pen, const char *opt,int, int);
+/// Fill area between curves {x,y1} and {x,y2} with x in x-axis range
+/** Style 'i' will fill area only if y1 < y2.
+  * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+void MGL_EXPORT mgl_region(HMGL graph, HCDT y1, HCDT y2, const char *pen, const char *opt);
+void MGL_EXPORT mgl_region_(uintptr_t *graph, uintptr_t *y1, uintptr_t *y2, const char *pen, const char *opt,int, int);
+
+/// Draw vertical lines from points {x,y,z} to axis plane
+void MGL_EXPORT mgl_stem_xyz(HMGL graph, HCDT x, HCDT y, HCDT z, const char *pen, const char *opt);
+void MGL_EXPORT mgl_stem_xyz_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *pen, const char *opt,int,int);
+/// Draw vertical lines from points {x,y} to axis plane
+void MGL_EXPORT mgl_stem_xy(HMGL graph, HCDT x, HCDT y, const char *pen, const char *opt);
+void MGL_EXPORT mgl_stem_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, const char *pen, const char *opt,int,int);
+/// Draw vertical lines from points {x,y} with x in x-axis range to axis plane
+void MGL_EXPORT mgl_stem(HMGL graph, HCDT y,	const char *pen, const char *opt);
+void MGL_EXPORT mgl_stem_(uintptr_t *graph, uintptr_t *y, const char *pen, const char *opt,int,int);
+
+/// Draw stairs for points in arrays {x,y,z}
+void MGL_EXPORT mgl_step_xyz(HMGL graph, HCDT x, HCDT y, HCDT z, const char *pen, const char *opt);
+void MGL_EXPORT mgl_step_xyz_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *pen, const char *opt,int,int);
+/// Draw stairs for points in arrays {x,y}
+void MGL_EXPORT mgl_step_xy(HMGL graph, HCDT x, HCDT y, const char *pen, const char *opt);
+void MGL_EXPORT mgl_step_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, const char *pen, const char *opt,int,int);
+/// Draw stairs for points in arrays {x,y} with x in x-axis range
+void MGL_EXPORT mgl_step(HMGL graph, HCDT y,	const char *pen, const char *opt);
+void MGL_EXPORT mgl_step_(uintptr_t *graph, uintptr_t *y, const char *pen, const char *opt,int,int);
+
+/// Draw vertical bars from points {x,y,z} to axis plane
+/** String \a pen may contain:
+ * ‘a’ for drawing boxes one above another (like summation);
+ * ‘f’ for waterfall chart;
+ * ‘<’, ‘^’, ‘>’ for aligning boxes: at left, centered, at right.
+ * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+void MGL_EXPORT mgl_bars_xyz(HMGL graph, HCDT x, HCDT y, HCDT z, const char *pen, const char *opt);
+void MGL_EXPORT mgl_bars_xyz_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *pen, const char *opt,int,int);
+/// Draw vertical bars from points {x,y} to axis plane
+/** String \a pen may contain:
+ * ‘a’ for drawing boxes one above another (like summation);
+ * ‘f’ for waterfall chart;
+ * ‘<’, ‘^’, ‘>’ for aligning boxes: at left, centered, at right.
+ * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+void MGL_EXPORT mgl_bars_xy(HMGL graph, HCDT x, HCDT y, const char *pen, const char *opt);
+void MGL_EXPORT mgl_bars_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, const char *pen, const char *opt,int,int);
+/// Draw vertical bars from points {x,y} with x in x-axis range to axis plane
+/** String \a pen may contain:
+ * ‘a’ for drawing boxes one above another (like summation);
+ * ‘f’ for waterfall chart;
+ * ‘<’, ‘^’, ‘>’ for aligning boxes: at left, centered, at right.
+ * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+void MGL_EXPORT mgl_bars(HMGL graph, HCDT y,	const char *pen, const char *opt);
+void MGL_EXPORT mgl_bars_(uintptr_t *graph, uintptr_t *y, const char *pen, const char *opt,int,int);
+
+/// Draw horizontal bars from points {v,y} to axis plane
+/** String \a pen may contain:
+ * ‘a’ for drawing boxes one above another (like summation);
+ * ‘f’ for waterfall chart;
+ * ‘<’, ‘^’, ‘>’ for aligning boxes: at left, centered, at right.
+ * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+void MGL_EXPORT mgl_barh_yx(HMGL graph, HCDT y, HCDT v, const char *pen, const char *opt);
+void MGL_EXPORT mgl_barh_yx_(uintptr_t *graph, uintptr_t *y, uintptr_t *v, const char *pen, const char *opt,int,int);
+/// Draw horizontal bars from points {v,y} with y in y-axis range to axis plane
+/** String \a pen may contain:
+ * ‘a’ for drawing boxes one above another (like summation);
+ * ‘f’ for waterfall chart;
+ * ‘<’, ‘^’, ‘>’ for aligning boxes: at left, centered, at right.
+ * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+void MGL_EXPORT mgl_barh(HMGL graph, HCDT v,	const char *pen, const char *opt);
+void MGL_EXPORT mgl_barh_(uintptr_t *graph, uintptr_t *v, const char *pen, const char *opt,int,int);
+
+/// Draw Open-High-Low-Close (OHLC) diagram
+/**  Different colors for up and down values are used if number of specified colors is equal to 2*number of curves. */
+void MGL_EXPORT mgl_ohlc_x(HMGL graph, HCDT x, HCDT open, HCDT high, HCDT low, HCDT close, const char *pen, const char *opt);
+void MGL_EXPORT mgl_ohlc_x_(uintptr_t *graph, uintptr_t *x, uintptr_t *open, uintptr_t *high, uintptr_t *low, uintptr_t *close, const char *pen, const char *opt,int,int);
+/// Draw Open-High-Low-Close (OHLC) diagram with x in x-axis range
+/**  Different colors for up and down values are used if number of specified colors is equal to 2*number of curves. */
+void MGL_EXPORT mgl_ohlc(HMGL graph, HCDT open, HCDT high, HCDT low, HCDT close, const char *pen, const char *opt);
+void MGL_EXPORT mgl_ohlc_(uintptr_t *graph, uintptr_t *open, uintptr_t *high, uintptr_t *low, uintptr_t *close, const char *pen, const char *opt,int,int);
+
+/// Draw chart for data a
+/** Space denote transparent color. Style '#' draw black borders. */
+void MGL_EXPORT mgl_chart(HMGL graph, HCDT a, const char *col, const char *opt);
+void MGL_EXPORT mgl_chart_(uintptr_t *graph, uintptr_t *a, const char *col, const char *opt,int,int);
+
+/// Draw error boxes {ex,ey} at points {x,y}
+/** Style ‘@’ set to draw large semitransparent mark instead of error box.*/
+void MGL_EXPORT mgl_error_exy(HMGL graph, HCDT x, HCDT y, HCDT ex, HCDT ey, const char *pen, const char *opt);
+void MGL_EXPORT mgl_error_exy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *ex, uintptr_t *ey, const char *pen, const char *opt,int,int);
+/// Draw error boxes {ey} at points {x,y}
+/** Style ‘@’ set to draw large semitransparent mark instead of error box.*/
+void MGL_EXPORT mgl_error_xy(HMGL graph, HCDT x, HCDT y, HCDT ey, const char *pen, const char *opt);
+void MGL_EXPORT mgl_error_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *ey, const char *pen, const char *opt,int,int);
+/// Draw error boxes {ey} at points {x,y} with x in x-axis range
+/** Style ‘@’ set to draw large semitransparent mark instead of error box.*/
+void MGL_EXPORT mgl_error(HMGL graph, HCDT y, HCDT ey, const char *pen, const char *opt);
+void MGL_EXPORT mgl_error_(uintptr_t *graph, uintptr_t *y, uintptr_t *ey, const char *pen, const char *opt,int,int);
+
+/// Draw marks with size r at points {x,y,z}
+void MGL_EXPORT mgl_mark_xyz(HMGL graph, HCDT x, HCDT y, HCDT z, HCDT r, const char *pen, const char *opt);
+void MGL_EXPORT mgl_mark_xyz_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *r, const char *pen, const char *opt,int,int);
+/// Draw marks with size r at points {x,y}
+void MGL_EXPORT mgl_mark_xy(HMGL graph, HCDT x, HCDT y, HCDT r, const char *pen, const char *opt);
+void MGL_EXPORT mgl_mark_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *r, const char *pen, const char *opt,int,int);
+/// Draw marks with size r at points {x,y} with x in x-axis range
+void MGL_EXPORT mgl_mark_y(HMGL graph, HCDT y, HCDT r, const char *pen, const char *opt);
+void MGL_EXPORT mgl_mark_y_(uintptr_t *graph, uintptr_t *y, uintptr_t *r, const char *pen, const char *opt,int,int);
+
+/// Draw Poincare map at condition s==0 for curve {x,y,z}
+void MGL_EXPORT mgl_pmap_xyz(HMGL graph, HCDT x, HCDT y, HCDT z, HCDT s, const char *pen, const char *opt);
+void MGL_EXPORT mgl_pmap_xyz_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *r, const char *pen, const char *opt,int,int);
+/// Draw Poincare map at condition s==0 for curve {x,y}
+void MGL_EXPORT mgl_pmap_xy(HMGL graph, HCDT x, HCDT y, HCDT s, const char *pen, const char *opt);
+void MGL_EXPORT mgl_pmap_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *r, const char *pen, const char *opt,int,int);
+/// Draw Poincare map at condition s==0 for curve {x,y} with x in x-axis range
+void MGL_EXPORT mgl_pmap(HMGL graph, HCDT y, HCDT s, const char *pen, const char *opt);
+void MGL_EXPORT mgl_pmap_(uintptr_t *graph, uintptr_t *y, uintptr_t *r, const char *pen, const char *opt,int,int);
+
+/// Draw tube with variable radius r around curve {x,y,z}
+void MGL_EXPORT mgl_tube_xyzr(HMGL graph, HCDT x, HCDT y, HCDT z, HCDT r, const char *pen, const char *opt);
+void MGL_EXPORT mgl_tube_xyzr_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *r, const char *pen, const char *opt,int,int);
+/// Draw tube with variable radius r around curve {x,y}
+void MGL_EXPORT mgl_tube_xyr(HMGL graph, HCDT x, HCDT y, HCDT r, const char *pen, const char *opt);
+void MGL_EXPORT mgl_tube_xyr_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *r, const char *pen, const char *opt,int,int);
+/// Draw tube with variable radius r around curve {x,y} with x in x-axis range
+void MGL_EXPORT mgl_tube_r(HMGL graph, HCDT y, HCDT r, const char *pen, const char *opt);
+void MGL_EXPORT mgl_tube_r_(uintptr_t *graph, uintptr_t *y, uintptr_t *r, const char *pen, const char *opt,int,int);
+/// Draw tube with constant radius r around curve {x,y,z}
+void MGL_EXPORT mgl_tube_xyz(HMGL graph, HCDT x, HCDT y, HCDT z, double r, const char *pen, const char *opt);
+void MGL_EXPORT mgl_tube_xyz_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, mreal *r, const char *pen, const char *opt,int,int);
+/// Draw tube with constant radius r around curve {x,y}
+void MGL_EXPORT mgl_tube_xy(HMGL graph, HCDT x, HCDT y, double r, const char *penl, const char *opt);
+void MGL_EXPORT mgl_tube_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, mreal *r, const char *pen, const char *opt,int,int);
+/// Draw tube with constant radius r around curve {x,y} with x in x-axis range
+void MGL_EXPORT mgl_tube(HMGL graph, HCDT y, double r, const char *pen, const char *opt);
+void MGL_EXPORT mgl_tube_(uintptr_t *graph, uintptr_t *y, mreal *r, const char *pen, const char *opt,int,int);
+
+/// Draw candle plot for data specified parametrically
+/** Different colors are used for up and down values if 2 colors are specified.
+ *  Style ‘#’ force drawing wire candle even for 2-color scheme. */
+void MGL_EXPORT mgl_candle_xyv(HMGL gr, HCDT x, HCDT v1, HCDT v2, HCDT y1, HCDT y2, const char *pen, const char *opt);
+void MGL_EXPORT mgl_candle_xyv_(uintptr_t *gr, uintptr_t *x, uintptr_t *v1, uintptr_t *v2, uintptr_t *y1, uintptr_t *y2, const char *pen, const char *opt,int,int);
+/// Draw candle plot
+/** Different colors are used for up and down values if 2 colors are specified.
+ *  Style ‘#’ force drawing wire candle even for 2-color scheme. */
+void MGL_EXPORT mgl_candle_yv(HMGL gr, HCDT v1, HCDT v2, HCDT y1, HCDT y2, const char *pen, const char *opt);
+void MGL_EXPORT mgl_candle_yv_(uintptr_t *gr, uintptr_t *v1, uintptr_t *v2, uintptr_t *y1, uintptr_t *y2, const char *pen, const char *opt,int,int);
+/// Draw candle plot with v1=v[i], v2=v[i+1]
+/** Different colors are used for up and down values if 2 colors are specified.
+ *  Style ‘#’ force drawing wire candle even for 2-color scheme. */
+void MGL_EXPORT mgl_candle(HMGL gr, HCDT v, HCDT y1, HCDT y2, const char *pen, const char *opt);
+void MGL_EXPORT mgl_candle_(uintptr_t *gr, uintptr_t *y, uintptr_t *y1, uintptr_t *y2, const char *pen, const char *opt,int,int);
+
+#ifdef __cplusplus
+}
+#endif
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/prim.h b/include/mgl2/prim.h
new file mode 100644
index 0000000..102a76c
--- /dev/null
+++ b/include/mgl2/prim.h
@@ -0,0 +1,261 @@
+/***************************************************************************
+ * prim.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_PRIM_H_
+#define _MGL_PRIM_H_
+#include "mgl2/abstract.h"
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// Draws the mark at position {x,y,z}
+void MGL_EXPORT mgl_mark(HMGL gr, double x,double y,double z,const char *mark);
+void MGL_EXPORT mgl_mark_(uintptr_t *gr, mreal *x, mreal *y, mreal *z,const char *mark,int);
+/// Draws red point (ball) at position {x,y,z}
+void MGL_EXPORT mgl_ball(HMGL gr, double x,double y,double z);
+void MGL_EXPORT mgl_ball_(uintptr_t *gr, mreal *x, mreal *y, mreal *z);
+
+/// Draws the line between 2 points by specified pen
+/** Large \a n (for example, n=100) should be used for geodesic line in curvilinear coordinates */
+void MGL_EXPORT mgl_line(HMGL gr, double x1, double y1, double z1, double x2, double y2, double z2, const char *pen,int n);
+void MGL_EXPORT mgl_line_(uintptr_t *gr, mreal *x1, mreal *y1, mreal *z1, mreal *x2, mreal *y2, mreal *z2, const char *pen,int *n,int);
+/// Draws the spline curve between 2 points by specified pen
+void MGL_EXPORT mgl_curve(HMGL gr, double x1, double y1, double z1, double dx1, double dy1, double dz1, double x2, double y2, double z2, double dx2, double dy2, double dz2, const char *pen,int n);
+void MGL_EXPORT mgl_curve_(uintptr_t* gr, mreal *x1, mreal *y1, mreal *z1, mreal *dx1, mreal *dy1, mreal *dz1, mreal *x2, mreal *y2, mreal *z2, mreal *dx2, mreal *dy2, mreal *dz2, const char *pen,int *n, int l);
+
+/// Draws the 3d error box {ex,ey,ez} for point {x,y,z}
+void MGL_EXPORT mgl_error_box(HMGL gr, double x, double y, double z, double ex, double ey, double ez, const char *pen);
+void MGL_EXPORT mgl_error_box_(uintptr_t* gr, mreal *x, mreal *y, mreal *z, mreal *ex, mreal *ey, mreal *ez, const char *pen, int);
+
+/// Draws the face between points with color stl (include interpolation up to 4 colors).
+void MGL_EXPORT mgl_face(HMGL gr, double x0, double y0, double z0, double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3, const char *stl);
+void MGL_EXPORT mgl_face_(uintptr_t* gr, mreal *x0, mreal *y0, mreal *z0, mreal *x1, mreal *y1, mreal *z1, mreal *x2, mreal *y2, mreal *z2, mreal *x3, mreal *y3, mreal *z3, const char *stl, int);
+/// Draws the face in y-z plane at point p with color stl (include interpolation up to 4 colors).
+void MGL_EXPORT mgl_facex(HMGL gr, double x0, double y0, double z0, double wy, double wz, const char *stl, double dx, double dy);
+void MGL_EXPORT mgl_facex_(uintptr_t* gr, mreal *x0, mreal *y0, mreal *z0, mreal *wy, mreal *wz, const char *stl, mreal *dx, mreal *dy, int l);
+/// Draws the face in x-z plane at point p with color stl (include interpolation up to 4 colors).
+void MGL_EXPORT mgl_facey(HMGL gr, double x0, double y0, double z0, double wx, double wz, const char *stl, double dx, double dy);
+void MGL_EXPORT mgl_facey_(uintptr_t* gr, mreal *x0, mreal *y0, mreal *z0, mreal *wx, mreal *wz, const char *stl, mreal *dx, mreal *dy, int l);
+/// Draws the face in x-y plane at point p with color stl (include interpolation up to 4 colors).
+void MGL_EXPORT mgl_facez(HMGL gr, double x0, double y0, double z0, double wx, double wy, const char *stl, double dx, double dy);
+void MGL_EXPORT mgl_facez_(uintptr_t* gr, mreal *x0, mreal *y0, mreal *z0, mreal *wx, mreal *wy, const char *stl, mreal *dx, mreal *dy, int l);
+
+/// Draws the sphere at point {x,y,z} with color stl and radius r
+void MGL_EXPORT mgl_sphere(HMGL gr, double x, double y, double z, double r, const char *stl);
+void MGL_EXPORT mgl_sphere_(uintptr_t* gr, mreal *x, mreal *y, mreal *z, mreal *r, const char *stl, int);
+/// Draws the drop at point {x,y,z} in direction {dx,dy,dz} with color stl and radius r
+/** Parameter \a shift set the degree of drop oblongness: ‘0’ is sphere, ‘1’ is maximally oblongness drop. Parameter \a ap set relative width of the drop (this is analogue of “ellipticity” for the sphere).*/
+void MGL_EXPORT mgl_drop(HMGL gr, double x, double y, double z, double dx, double dy, double dz, double r, const char *stl, double shift, double ap);
+void MGL_EXPORT mgl_drop_(uintptr_t* gr, mreal *x1, mreal *y1, mreal *z1, mreal *x2, mreal *y2, mreal *z2, mreal *r, const char *stl, mreal *shift, mreal *ap, int);
+/// Draws the cone between points p1,p2 with radius r1,r2 and with style stl
+/** Parameter \a stl can contain:
+ * ‘@’ for drawing edges;
+ * ‘#’ for wired cones;
+ * ‘t’ for drawing tubes/cylinder instead of cones/prisms;
+ * ‘4’, ‘6’, ‘8’ for drawing square, hex- or octo-prism instead of cones.*/
+void MGL_EXPORT mgl_cone(HMGL gr, double x1, double y1, double z1, double x2, double y2, double z2, double r1, double r2, const char *stl);
+void MGL_EXPORT mgl_cone_(uintptr_t* gr, mreal *x1, mreal *y1, mreal *z1, mreal *x2, mreal *y2, mreal *z2, mreal *r1, mreal *r2, const char *stl, int);
+/// Draws the ellipse between points p1,p2 with color stl and width r
+/** Parameter \a stl can contain:
+ * ‘#’ for wired figure (boundary only);
+ * ‘@’ for filled figure and with boundary (second color or black one is used for boundary).*/
+void MGL_EXPORT mgl_ellipse(HMGL gr, double x1, double y1, double z1, double x2, double y2, double z2, double r, const char *stl);
+void MGL_EXPORT mgl_ellipse_(uintptr_t* gr, mreal *x1, mreal *y1, mreal *z1, mreal *x2, mreal *y2, mreal *z2, mreal *r, const char *stl, int);
+/// Draws the rhomb between points p1,p2 with color stl and width r
+/** Parameter \a stl can contain:
+ * ‘#’ for wired figure (boundary only);
+ * ‘@’ for filled figure and with boundary (second color or black one is used for boundary).*/
+void MGL_EXPORT mgl_rhomb(HMGL gr, double x1, double y1, double z1, double x2, double y2, double z2, double r, const char *stl);
+void MGL_EXPORT mgl_rhomb_(uintptr_t* gr, mreal *x1, mreal *y1, mreal *z1, mreal *x2, mreal *y2, mreal *z2, mreal *r, const char *stl, int);
+/// Draws the polygon based on points p1,p2 with color stl
+/** Parameter \a stl can contain:
+ * ‘#’ for wired figure (boundary only);
+ * ‘@’ for filled figure and with boundary (second color or black one is used for boundary).*/
+void MGL_EXPORT mgl_polygon(HMGL gr, double x1, double y1, double z1, double x2, double y2, double z2, int n, const char *stl);
+void MGL_EXPORT mgl_polygon_(uintptr_t* gr, mreal *x1, mreal *y1, mreal *z1, mreal *x2, mreal *y2, mreal *z2, int *n, const char *stl, int);
+	/// Draws the arc around axis pr with center at p0 and starting from p1, by color stl and angle a (in degrees)
+void MGL_EXPORT mgl_arc_ext(HMGL gr, double x0, double y0, double z0, double xr, double yr, double zr, double x1, double y1, double z1, double a, const char *stl);
+void MGL_EXPORT mgl_arc_ext_(uintptr_t* gr, mreal *x0, mreal *y0, mreal *z0, mreal *xr, mreal *yr, mreal *zr, mreal *x1, mreal *y1, mreal *z1, mreal *a, const char *stl, int);
+	/// Draws the arc around axis 'z' with center at p0 and starting from p1, by color stl and angle a (in degrees)
+void MGL_EXPORT mgl_arc(HMGL gr, double x0, double y0, double x1, double y1, double a, const char *stl);
+void MGL_EXPORT mgl_arc_(uintptr_t* gr, mreal *x0, mreal *y0, mreal *x1, mreal *y1, mreal *a, const char *stl,int l);
+
+
+/// Draw cones from points {x,y,z} to axis plane
+/** String \a pen may contain:
+ * ‘@’ for drawing edges;
+ * ‘#’ for wired cones;
+ * ‘t’ for drawing tubes/cylinders instead of cones/prisms;
+ * ‘4’, ‘6’, ‘8’ for drawing square, hex- or octo-prism instead of cones;
+ * ‘<’, ‘^’ or ‘>’ for aligning cones left, right or centering them at its x-coordinates.
+ * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+void MGL_EXPORT mgl_cones_xyz(HMGL graph, HCDT x, HCDT y, HCDT z, const char *pen, const char *opt);
+void MGL_EXPORT mgl_cones_xyz_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *pen, const char *opt,int,int);
+/// Draw cones from points {x,z} to axis plane
+/** String \a pen may contain:
+ * ‘@’ for drawing edges;
+ * ‘#’ for wired cones;
+ * ‘t’ for drawing tubes/cylinders instead of cones/prisms;
+ * ‘4’, ‘6’, ‘8’ for drawing square, hex- or octo-prism instead of cones;
+ * ‘<’, ‘^’ or ‘>’ for aligning cones left, right or centering them at its x-coordinates.
+ * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+void MGL_EXPORT mgl_cones_xz(HMGL graph, HCDT x, HCDT z, const char *pen, const char *opt);
+void MGL_EXPORT mgl_cones_xz_(uintptr_t *graph, uintptr_t *x, uintptr_t *z, const char *pen, const char *opt,int,int);
+/// Draw cones from points {x,z} with x in x-axis range to axis plane
+/** String \a pen may contain:
+ * ‘@’ for drawing edges;
+ * ‘#’ for wired cones;
+ * ‘t’ for drawing tubes/cylinders instead of cones/prisms;
+ * ‘4’, ‘6’, ‘8’ for drawing square, hex- or octo-prism instead of cones;
+ * ‘<’, ‘^’ or ‘>’ for aligning cones left, right or centering them at its x-coordinates.
+ * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+void MGL_EXPORT mgl_cones(HMGL graph, HCDT z,	const char *pen, const char *opt);
+void MGL_EXPORT mgl_cones_(uintptr_t *graph, uintptr_t *z,	const char *pen, const char *opt,int,int);
+
+/// Plot dew drops for vector field {ax,ay} parametrically depended on coordinate {x,y}
+void MGL_EXPORT mgl_dew_xy(HMGL gr, HCDT x, HCDT y, HCDT ax, HCDT ay, const char *sch, const char *opt);
+void MGL_EXPORT mgl_dew_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *ax, uintptr_t *ay, const char *sch, const char *opt,int,int);
+/// Plot dew drops for vector field {ax,ay}
+void MGL_EXPORT mgl_dew_2d(HMGL gr, HCDT ax, HCDT ay, const char *sch, const char *optl);
+void MGL_EXPORT mgl_dew_2d_(uintptr_t *gr, uintptr_t *ax, uintptr_t *ay, const char *sch, const char *opt,int,int l);
+
+/// Print text in position {x,y,z} with specified font
+/* NOTE: Function don't have options because it can be part of group.*/
+void MGL_EXPORT mgl_puts(HMGL graph, double x, double y, double z,const char *text, const char *font, double size);
+void MGL_EXPORT mgl_puts_(uintptr_t *graph, mreal *x, mreal *y, mreal *z,const char *text, const char *font, mreal *size, int, int);
+void MGL_EXPORT mgl_putsw(HMGL graph, double x, double y, double z,const wchar_t *text, const char *font, double size);
+
+/// Print text in position {x,y,z} along direction {dx,dy,dz} with specified font
+/* NOTE: Function don't have options because it can be part of group.*/
+void MGL_EXPORT mgl_puts_dir(HMGL graph, double x, double y, double z, double dx, double dy, double dz, const char *text, const char *font, double size);
+void MGL_EXPORT mgl_puts_dir_(uintptr_t *graph, mreal *x, mreal *y, mreal *z, mreal *dx, mreal *dy, mreal *dz, const char *text, const char *font, mreal *size, int, int);
+void MGL_EXPORT mgl_putsw_dir(HMGL graph, double x, double y, double z, double dx, double dy, double dz, const wchar_t *text, const char *font, double size);
+
+/// Draw user-defined symbol in position p
+void MGL_EXPORT mgl_symbol(HMGL gr, double x, double y, double z, char id, const char *how, double size);
+void MGL_EXPORT mgl_symbol_(uintptr_t *gr, double *x, double *y, double *z, char *id, const char *how, double *size,int,int);
+/// Draw user-defined symbol in position p along direction d
+void MGL_EXPORT mgl_symbol_dir(HMGL gr, double x, double y, double z, double dx, double dy, double dz, char id, const char *how, double size);
+void MGL_EXPORT mgl_symbol_dir_(uintptr_t *gr, double *x, double *y, double *z, double *dx, double *dy, double *dz, char *id, const char *how, double *size,int,int);
+
+/// Draw textual marks with size r at points {x,y,z}
+void MGL_EXPORT mgl_textmark_xyzr(HMGL graph, HCDT x, HCDT y, HCDT z, HCDT r, const char *text, const char *fnt, const char *opt);
+void MGL_EXPORT mgl_textmark_xyzr_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *r, const char *text, const char *fnt, const char *opt,int,int,int);
+void MGL_EXPORT mgl_textmarkw_xyzr(HMGL graph, HCDT x, HCDT y, HCDT z, HCDT r, const wchar_t *text, const char *fnt, const char *opt);
+/// Draw textual marks with size r at points {x,y}
+void MGL_EXPORT mgl_textmark_xyr(HMGL graph, HCDT x, HCDT y, HCDT r, const char *text, const char *fnt, const char *opt);
+void MGL_EXPORT mgl_textmark_xyr_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *r, const char *text, const char *fnt, const char *opt,int,int,int);
+void MGL_EXPORT mgl_textmarkw_xyr(HMGL graph, HCDT x, HCDT y, HCDT r, const wchar_t *text, const char *fnt, const char *opt);
+/// Draw textual marks with size r at points {x,y} with x in x-axis range
+void MGL_EXPORT mgl_textmark_yr(HMGL graph, HCDT y, HCDT r, const char *text, const char *fnt, const char *opt);
+void MGL_EXPORT mgl_textmark_yr_(uintptr_t *graph, uintptr_t *y, uintptr_t *r, const char *text, const char *fnt, const char *opt,int,int,int);
+void MGL_EXPORT mgl_textmarkw_yr(HMGL graph, HCDT y, HCDT r, const wchar_t *text, const char *fnt, const char *opt);
+/// Draw textual marks with size r=1 at points {x,y} with x in x-axis range
+void MGL_EXPORT mgl_textmark(HMGL graph, HCDT y, const char *text, const char *fnt, const char *opt);
+void MGL_EXPORT mgl_textmarkw(HMGL graph, HCDT y, const wchar_t *text, const char *fnt, const char *opt);
+void MGL_EXPORT mgl_textmark_(uintptr_t *graph, uintptr_t *y, const char *text, const char *fnt, const char *opt,int,int,int);
+
+/// Draw labels for points coordinate(s) at points {x,y,z}
+/** String \a fnt may contain:
+ *	 ‘f’ for fixed format of printed numbers;
+ *	 ‘E’ for using ‘E’ instead of ‘e’;
+ *	 ‘F’ for printing in LaTeX format;
+ *	 ‘+’ for printing ‘+’ for positive numbers;
+ *	 ‘-’ for printing usual ‘-’;
+ *	 ‘0123456789’ for precision at printing numbers.*/
+void MGL_EXPORT mgl_label_xyz(HMGL graph, HCDT x, HCDT y, HCDT z, const char *text, const char *fnt, const char *opt);
+void MGL_EXPORT mgl_label_xyz_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *text, const char *fnt, const char *opt,int,int,int);
+void MGL_EXPORT mgl_labelw_xyz(HMGL graph, HCDT x, HCDT y, HCDT z, const wchar_t *text, const char *fnt, const char *opt);
+/// Draw labels for points coordinate(s) at points {x,y}
+/** String \a fnt may contain:
+ *	 ‘f’ for fixed format of printed numbers;
+ *	 ‘E’ for using ‘E’ instead of ‘e’;
+ *	 ‘F’ for printing in LaTeX format;
+ *	 ‘+’ for printing ‘+’ for positive numbers;
+ *	 ‘-’ for printing usual ‘-’;
+ *	 ‘0123456789’ for precision at printing numbers.*/
+void MGL_EXPORT mgl_label_xy(HMGL graph, HCDT x, HCDT y, const char *text, const char *fnt, const char *opt);
+void MGL_EXPORT mgl_label_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, const char *text, const char *fnt, const char *opt,int,int,int);
+void MGL_EXPORT mgl_labelw_xy(HMGL graph, HCDT x, HCDT y, const wchar_t *text, const char *fnt, const char *opt);
+/// Draw labels for points coordinate(s) at points {x,y} with x in x-axis range
+/** String \a fnt may contain:
+ *	 ‘f’ for fixed format of printed numbers;
+ *	 ‘E’ for using ‘E’ instead of ‘e’;
+ *	 ‘F’ for printing in LaTeX format;
+ *	 ‘+’ for printing ‘+’ for positive numbers;
+ *	 ‘-’ for printing usual ‘-’;
+ *	 ‘0123456789’ for precision at printing numbers.*/
+void MGL_EXPORT mgl_label_y(HMGL graph, HCDT y, const char *text, const char *fnt, const char *opt);
+void MGL_EXPORT mgl_labelw_y(HMGL graph, HCDT y, const wchar_t *text, const char *fnt, const char *opt);
+void MGL_EXPORT mgl_label_y_(uintptr_t *graph, uintptr_t *y, const char *text, const char *fnt, const char *opt,int,int,int);
+
+/// Draw table for values val along given direction with row labels text at position {x,y}
+/** String \a fnt may contain:
+ *	 ‘#’ for drawing cell borders;
+ *	 ‘|’ for limiting table width by subplot one (equal to option ‘value 1’);
+ *	 ‘=’ for equal width of all cells;
+ *	 ‘f’ for fixed format of printed numbers;
+ *	 ‘E’ for using ‘E’ instead of ‘e’;
+ *	 ‘F’ for printing in LaTeX format;
+ *	 ‘+’ for printing ‘+’ for positive numbers;
+ *	 ‘-’ for printing usual ‘-’;
+ *	 ‘0123456789’ for precision at printing numbers.
+ * Option value set the width of the table (default is 1).*/
+void MGL_EXPORT mgl_table(HMGL gr, double x, double y, HCDT val, const char *text, const char *fnt, const char *opt);
+void MGL_EXPORT mgl_table_(uintptr_t *gr, mreal *x, mreal *y, uintptr_t *val, const char *text, const char *fnt, const char *opt,int,int,int);
+void MGL_EXPORT mgl_tablew(HMGL gr, double x, double y, HCDT val, const wchar_t *text, const char *fnt, const char *opt);
+
+/// Draws bitmap (logo) which is stretched along whole axis range
+void MGL_EXPORT mgl_logo(HMGL gr, long w, long h, const unsigned char *rgba, int smooth, const char *opt);
+void MGL_EXPORT mgl_logo_file(HMGL gr, const char *fname, int smooth, const char *opt);
+void MGL_EXPORT mgl_logo_file_(uintptr_t *gr, const char *fname, int *smooth, const char *opt,int l,int n);
+
+/// Draws Lamerey diagram for mapping x_new = f(x_old)
+/** String \a stl may contain: ‘v’ for drawing arrows; ‘~’ for disable 1st segment.
+ *	Option value set the number of segments (default is 20).*/
+void MGL_EXPORT mgl_lamerey(HMGL gr, double x0, double (*f)(double,void *), void *par, const char *stl, const char *opt);
+void MGL_EXPORT mgl_lamerey_dat(HMGL gr, double x0, HCDT f, const char *stl, const char *opt);
+void MGL_EXPORT mgl_lamerey_str(HMGL gr, double x0, const char *f, const char *stl, const char *opt);
+void MGL_EXPORT mgl_lamerey_dat_(uintptr_t *gr, double *x0, uintptr_t *f, const char *stl, const char *opt, int,int);
+void MGL_EXPORT mgl_lamerey_str_(uintptr_t *gr, double *x0, const char *f, const char *stl, const char *opt, int,int,int);
+
+/// Draws Bifurcation diagram for mapping x_new = f(x_old) in x-axis range
+/** Option value set the number of stationary points (default is 1024).*/
+void MGL_EXPORT mgl_bifurcation(HMGL gr, double dx, double (*f)(double,double,void *), void *par, const char *stl, const char *opt);
+void MGL_EXPORT mgl_bifurcation_dat(HMGL gr, double dx, HCDT f, const char *stl, const char *opt);
+void MGL_EXPORT mgl_bifurcation_str(HMGL gr, double dx, const char *f, const char *stl, const char *opt);
+void MGL_EXPORT mgl_bifurcation_dat_(uintptr_t *gr, double *dx, uintptr_t *f, const char *stl, const char *opt, int,int);
+void MGL_EXPORT mgl_bifurcation_str_(uintptr_t *gr, double *dx, const char *f, const char *stl, const char *opt, int,int,int);
+
+/// Draws Iris plots for determining cross-dependences of data arrays
+/** NOTE: using the same ranges and empty ids will not draw axis. This will add data to existing Iris plot.
+ * 	Option value set the size of data labels ids, separated by ';'.*/
+void MGL_EXPORT mgl_iris(HMGL gr, HCDT dats, HCDT ranges, const char *ids, const char *stl, const char *opt);
+void MGL_EXPORT mgl_iris_1(HMGL gr, HCDT dats, const char *ids, const char *stl, const char *opt);
+void MGL_EXPORT mgl_irisw(HMGL gr, HCDT dats, HCDT ranges, const wchar_t *ids, const char *stl, const char *opt);
+void MGL_EXPORT mgl_irisw_1(HMGL gr, HCDT dats, const wchar_t *ids, const char *stl, const char *opt);
+void MGL_EXPORT mgl_iris_(uintptr_t *gr, uintptr_t *dats, uintptr_t *ranges, const char *ids, const char *stl, const char *opt,int l,int m,int n);
+void MGL_EXPORT mgl_iris_1_(uintptr_t *gr, uintptr_t *dats, const char *ids, const char *stl, const char *opt,int,int,int);
+
+#ifdef __cplusplus
+}
+#endif
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/qmathgl.h b/include/mgl2/qmathgl.h
new file mode 100644
index 0000000..de95e27
--- /dev/null
+++ b/include/mgl2/qmathgl.h
@@ -0,0 +1,253 @@
+/***************************************************************************
+ * qmathgl.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_QMATHGL_H_
+#define _MGL_QMATHGL_H_
+//-----------------------------------------------------------------------------
+#include <mgl2/wnd.h>
+#include <QWidget>
+#include <QPixmap>
+//-----------------------------------------------------------------------------
+class QTextEdit;
+class QMenu;
+class QMainWindow;
+class QScrollArea;
+class QSpinBox;
+class QTimer;
+class mglCanvas;
+class mglTask;
+//-----------------------------------------------------------------------------
+/// Class is Qt widget which display MathGL graphics
+class MGL_EXPORT QMathGL : public QWidget
+{
+	Q_OBJECT
+public:
+	QString appName; 	///< Application name for message boxes
+	bool autoResize; 	///< Allow auto resizing (default is false)
+	bool enableMouse;	///< Enable mouse handlers
+	bool enableWheel;	///< Enable mouse wheel handlers
+	QString primitives;	///< Manual primitives, defined by user
+	mglCanvas *gr;		///< Built-in mglCanvas instance (mglCanvasQT is used by default)
+
+	QMathGL(QWidget *parent = 0, Qt::WindowFlags f = 0);
+	virtual ~QMathGL();
+	double getRatio();
+	void setPopup(QMenu *p)	{	popup = p;	}	///< Set popup menu pointer
+	void setSize(int w, int h);		///< Set window/picture sizes
+	void setGraph(HMGL GR);	///< Set grapher object
+	inline void setGraph(mglGraph *GR)
+	{	setGraph(GR->Self());	}
+	inline HMGL getGraph()	{	return (HMGL)gr;	}
+	/// Set drawing functions and its parameter
+	void setDraw(int (*func)(mglBase *gr, void *par), void *par);
+	void setDraw(mglDraw *dr);
+	inline void setDraw(int (*func)(mglGraph *gr))
+	{	setDraw(func?mgl_draw_graph:0,(void*)func);	}
+	inline void zoomRegion(mreal xx1,mreal xx2,mreal yy1, mreal yy2)
+	{	x1=xx1;	y1=yy1;	x2=xx2;	y2=yy2;	}
+	/// Get mglDraw pointer or NULL
+	inline mglDraw *getClass()
+	{	mglDraw *d=0;
+		if(draw_func==mgl_draw_class)	d = (mglDraw*)draw_par;
+		if(draw)	d = draw;
+		return d;	}
+
+	int getPer() const	{return int(per);}	///< Get perspective value
+	int getPhi() const	{return int(phi);}	///< Get Phi-angle value
+	int getTet() const	{return int(tet);}	///< Get Theta-angle value
+	bool getAlpha() const	{return alpha;}	///< Get transparency state
+	bool getLight() const	{return light;}	///< Get lightning state
+	bool getZoom() const	{return zoom;}	///< Get mouse zooming state
+	bool getRotate() const	{return rotate;}///< Get mouse rotation state
+	bool getViewYZ() const	{return viewYZ;}///< Get mouse rotation axis
+	bool getPause() const	{return pause;}	///< Get calculation pause state
+	bool isActive(int xs,int ys);	///< Check if active point is pressed
+
+public slots:
+	void refresh();			///< Redraw image with new zoom and view parameters
+	void refreshHQ();		///< Redraw image with HQ (can be slower than refresh())
+	void update();			///< Update picture
+	void copy();			///< copy graphics to clipboard
+	void copyClickCoor();	///< copy click coordinates to clipboard
+	void print();			///< Print plot
+	void stop();			///< Stop execution
+	void setPer(int p);		///< Set perspective value
+	void setPhi(int p);		///< Set Phi-angle value
+	void setTet(int t);		///< Set Theta-angle value
+	void setAlpha(bool a);	///< Switch on/off transparency
+	void setLight(bool l);	///< Switch on/off lightning
+	void setGrid(bool r);	///< Switch on/off grid drawing
+	void imgSize(int w, int h);	///< Set image size
+	void setViewYZ(bool v);	///< Switch on/off rotation around Y and Z axis
+	void setDotsPreview(bool d=true);	///< Set to use dots for image preview/rotation
+
+	void setCustZoom(bool a);	///< Switch on/off using custom zoom
+	void setCustDraw(bool a);	///< Switch on/off using custom draw
+	void setZoom(bool z);	///< Switch on/off mouse zooming
+	void setRotate(bool r);	///< Switch on/off mouse rotation
+	void setPause(bool p);	///< Switch on/off calculation pause
+	void zoomIn();			///< Zoom in graphics
+	void zoomOut();			///< Zoom out graphics
+	void restore();			///< Restore zoom and rotation to default values
+	void setZoomScl(double s=0.5);		///< Set factor for zooming (must be s>0)
+	void setShiftScl(double s=0.25);	///< Set factor for shifting (must be s!=0)
+	//	void reload();			///< Reload data and execute script
+
+	void shiftLeft();		///< Shift graphics to left direction
+	void shiftRight();		///< Shift graphics to right direction
+	void shiftUp();			///< Shift graphics to up direction
+	void shiftDown();		///< Shift graphics to down direction
+
+	void exportPNG(QString fname="");	///< export to PNG file
+	void exportPNGs(QString fname="");	///< export to PNG file (no transparency)
+	void exportGIF(QString fname="");	///< export to GIF file
+	void exportJPG(QString fname="");	///< export to JPEG file
+	void exportBPS(QString fname="");	///< export to bitmap EPS file
+	void exportEPS(QString fname="");	///< export to vector EPS file
+	void exportSVG(QString fname="");	///< export to SVG file
+	void exportTEX(QString fname="");	///< export to SVG file
+	void exportTGA(QString fname="");	///< export to TGA file
+
+	void exportXYZ(QString fname="");	///< export to XYZ file
+	void exportOBJ(QString fname="");	///< export to OBJ file
+	void exportSTL(QString fname="");	///< export to STL file
+	void exportOFF(QString fname="");	///< export to OFF file
+//	void exportX3D(QString fname="");	///< export to XYZ file
+	void exportPRC(QString fname="");	///< export to PRC file
+	void exportMGLD(QString fname="");	///< export to MGLD file
+	void setMGLFont(QString path);		///< restore/load font for graphics
+
+	void addMark();						///< add marker into primitives
+	void addLine();						///< add line into primitives
+	void addRect();						///< add rectangle into primitives
+	void addCurve();					///< add curve into primitives
+	void addRhomb();					///< add rhombus into primitives
+	void addEllipse();					///< add ellipse into primitives
+	void addArc();					///< add arc into primitives
+	void addPolygon(int n=-1);			///< add polygon into primitives
+	void addText(QString txt="");		///< add text into primitives
+	void setStyle(int id, QString stl);///< set style for primitive with id
+
+	void adjust();		///< Adjust plot size to fill entire window
+	void nextSlide();	///< Show next slide
+	void prevSlide();	///< Show previous slide
+	void animation(bool st=true);	///< Start animation
+	void about();		///< Show about information
+	void aboutQt();		///< Show information about Qt version
+
+signals:
+	void gridChanged(int);		///< Grid drawing changed (by mouse or by toolbar)
+	void phiChanged(int);		///< Phi angle changed (by mouse or by toolbar)
+	void tetChanged(int);		///< Tet angle changed (by mouse or by toolbar)
+	void perChanged(int);		///< Perspective changed (by mouse or by toolbar)
+	void alphaChanged(bool);	///< Transparency changed (by toolbar)
+	void lightChanged(bool);	///< Lighting changed (by toolbar)
+	void zoomChanged(bool);		///< Zooming changed (by toolbar)
+	void rotateChanged(bool);	///< Rotation changed (by toolbar)
+	void pauseChanged(bool);	///< Pause changed (by toolbar)
+	void usePrimChanged(bool);	///< Use primitive changed (i.e. have or not drawing function)
+	void viewYZChanged(bool);	///< Rotation axis changed (by toolbar)
+	void mouseClick(mreal,mreal,mreal);	///< Position of mouse click
+	void frameChanged(int);		///< Need another frame to show
+	void showWarn(QString);		///< Show warnings
+	void posChanged(QString message);	///< user click to show mouse position
+	void objChanged(int objId);	///< User click to select object/line
+	void refreshData();
+	void doubleClick(int id);	///< Double mouse click by object with id
+	void askStyle(int id);		///< Update style
+	/// user can define its own zooming function
+	void customZoom(double x1, double y1, double x2, double y2, double tet, double phi, double per);
+	/// user can define its own drawing/setting function which will be called before main drawing
+	void customDraw(double x1, double y1, double x2, double y2, bool draw);
+
+protected:
+	void paintEvent(QPaintEvent *);
+	void resizeEvent(QResizeEvent *);
+	void mousePressEvent(QMouseEvent *);
+	void mouseReleaseEvent(QMouseEvent *);
+	void mouseMoveEvent(QMouseEvent *);
+	void wheelEvent(QWheelEvent *);
+	void mouseDoubleClickEvent(QMouseEvent *);
+
+	void *draw_par;		///< Parameters for drawing function mglCanvasWnd::DrawFunc.
+	/// Drawing function for window procedure. It should return the number of frames.
+	int (*draw_func)(mglBase *gr, void *par);
+	mglDraw *draw;		///< Class for drawing -- need to call directly due to inheritance mechanism
+	QString mousePos;	///< Last mouse position
+	QPixmap pic;		///< Pixmap for drawing (changed by update)
+	QImage img;			///< Last used HQ image
+	double tet, phi;	///< Rotation angles
+	double per;			///< Value of perspective ( must be in [0,1) )
+	bool alpha;			///< Transparency state
+	bool light;			///< Lightning state
+	bool pause;			///< Pause state
+	bool custZoom;		///< Use custom zoom instead of built in
+	bool custDraw;		///< Use custom draw before main drawing
+	bool zoom;			///< Mouse zoom state
+	bool grid;			///< Grid drawing state
+	bool rotate;		///< Mouse rotation state
+	bool viewYZ;		///< Set mouse rotation around Y and Z axis (instead of X and Z)
+	bool dotsRefr;		///< Set dots for image preview/rotation
+	mreal x1,x2,y1,y2;	///< Zoom in region
+	mreal ax1,ax2,ay1,ay2;	///< Axis range zoom
+	bool showMessage;	///< Flag for showing messages (enabled by each execute())
+	QMenu *popup;		///< Pointer to pop-up menu
+	QTimer *timer;		///< Timer for animation
+	QTimer *timerRefr;	///< Timer for redrawing
+private slots:
+	void afterPlot();	///< minor tuning after plot was done
+private:
+	int x0, y0, xe, ye;		///< Temporary variables for mouse
+	double sclZ;			///< Scale factor for zooming
+	double sclS;			///< Scale factor for shifting
+	uchar *grBuf;
+	void drawPrim();
+	int prevQuality;
+//	QThread *thread;
+//	mglTask *task;
+};
+//-----------------------------------------------------------------------------
+/// Class for drawing the MGL script
+class MGL_EXPORT mglDrawScript : public mglDraw
+{
+public:
+	HMPR par;		///< Parser to be used
+	QString text;	///< Script to be drawn
+	long line;		///< Line which will be highlighted
+	mglDrawScript(HMPR p):mglDraw()	{	par=p;	line=-1;	}
+	virtual ~mglDrawScript() {}
+	int Draw(mglGraph *gr)
+	{
+		wchar_t *wtext;
+		wtext = new wchar_t[text.size()+1];
+		text.toWCharArray(wtext);
+		wtext[text.size()] = 0;
+		gr->Highlight(line + 1);
+		mgl_parse_textw(gr->Self(), par, wtext);
+		delete[] wtext;
+		return 0;
+	}
+};
+//-----------------------------------------------------------------------------
+/// Convert bitmap from mglCanvasWnd to QPixmap
+void mglConvertFromGraph(QPixmap &pic, mglCanvas *gr, uchar **buf, QImage *out=NULL);
+/// Make menu, toolbars and return popup menu for MainWindow
+MGL_EXPORT QMenu *mglMakeMenu(QMainWindow* Wnd, QMathGL* QMGL, QSpinBox*& tet, QSpinBox*& phi);
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/qt.h b/include/mgl2/qt.h
new file mode 100644
index 0000000..09bc0dc
--- /dev/null
+++ b/include/mgl2/qt.h
@@ -0,0 +1,64 @@
+/***************************************************************************
+ * qt.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_QT_H_
+#define _MGL_QT_H_
+#include <mgl2/abstract.h>
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+extern "C" {
+#endif
+/// Creates Qt window for plotting
+HMGL MGL_EXPORT mgl_create_graph_qt(int (*draw)(HMGL gr, void *p), const char *title, void *par, void (*load)(void *p));
+uintptr_t MGL_EXPORT mgl_create_graph_qt_(const char *title, int);
+/// Run main Qt loop for event handling.
+int MGL_EXPORT mgl_qt_run();
+int MGL_EXPORT mgl_qt_run_();
+/// Return pointer to widget (QMathGL*) used for plotting
+MGL_EXPORT void *mgl_qt_widget(HMGL gr);
+#ifdef __cplusplus
+}
+//-----------------------------------------------------------------------------
+#include <mgl2/wnd.h>
+//-----------------------------------------------------------------------------
+/// Wrapper class for windows displaying graphics
+class MGL_EXPORT mglQT : public mglWnd
+{
+	mglQT(const mglQT &) {}	// copying is not allowed
+	const mglQT &operator=(const mglQT &t)	{	return t;	}
+public:
+	mglQT(const char *title="MathGL") : mglWnd()
+	{	gr = mgl_create_graph_qt(0,title,0,0);	}
+	mglQT(int (*draw)(HMGL gr, void *p), const char *title="MathGL", void *par=NULL, void (*load)(void *p)=0) : mglWnd()
+	{	gr = mgl_create_graph_qt(draw,title,par,load);	}
+	mglQT(int (*draw)(mglGraph *gr), const char *title="MathGL") : mglWnd()
+	{	gr = mgl_create_graph_qt(draw?mgl_draw_graph:0,title,(void*)draw,0);	}
+	mglQT(mglDraw *draw, const char *title="MathGL") : mglWnd()
+	{	gr = mgl_create_graph_qt(draw?mgl_draw_class:0,title,draw,mgl_reload_class);
+		mgl_set_click_func(gr, mgl_click_class);	}
+	virtual ~mglQT() {}
+	int Run()	{	return mgl_qt_run();	}	///< Run main loop for event handling
+	/// Return pointer to widget (QMathGL*) used for plotting
+	void *Widget()	{	return mgl_qt_widget(gr);	}
+};
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_ask_qt(const wchar_t *quest, wchar_t *res);
+//-----------------------------------------------------------------------------
+#endif
+#endif
diff --git a/include/mgl2/surf.h b/include/mgl2/surf.h
new file mode 100644
index 0000000..046c7e7
--- /dev/null
+++ b/include/mgl2/surf.h
@@ -0,0 +1,165 @@
+/***************************************************************************
+ * surf.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_SURF_H_
+#define _MGL_SURF_H_
+#include "mgl2/abstract.h"
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// Draw surface by formula with x,y in axis range
+/** Option "value" set initial number of points. */
+void MGL_EXPORT mgl_fsurf(HMGL graph, const char *fz, const char *stl, const char *opt);
+void MGL_EXPORT mgl_fsurf_(uintptr_t *graph, const char *fz, const char *stl, const char *opt,int,int,int);
+/// Draw surface by formulas parametrically depended on u,v in range [0,1]
+/** Option "value" set initial number of points. */
+void MGL_EXPORT mgl_fsurf_xyz(HMGL graph, const char *fx, const char *fy, const char *fz, const char *stl, const char *opt);
+void MGL_EXPORT mgl_fsurf_xyz_(uintptr_t *graph, const char *fx, const char *fy, const char *fz, const char *stl, const char *opt, int, int, int, int, int);
+
+/// Draw grid lines for density plot of 2d data specified parametrically
+void MGL_EXPORT mgl_grid_xy(HMGL graph, HCDT x, HCDT y, HCDT z, const char *stl, const char *opt);
+void MGL_EXPORT mgl_grid_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *stl, const char *opt,int,int);
+/// Draw grid lines for density plot of 2d data
+void MGL_EXPORT mgl_grid(HMGL graph, HCDT a,const char *stl, const char *opt);
+void MGL_EXPORT mgl_grid_(uintptr_t *graph, uintptr_t *a,const char *stl, const char *opt,int,int);
+
+/// Draw mesh lines for 2d data specified parametrically
+void MGL_EXPORT mgl_mesh_xy(HMGL graph, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_mesh_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw mesh lines for 2d data
+void MGL_EXPORT mgl_mesh(HMGL graph, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_mesh_(uintptr_t *graph, uintptr_t *z, const char *sch, const char *opt,int,int);
+
+/// Draw waterfall plot for 2d data specified parametrically
+/** Style 'x' draw lines in x-direction. */
+void MGL_EXPORT mgl_fall_xy(HMGL graph, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_fall_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw waterfall plot for 2d data
+/** Style 'x' draw lines in x-direction. */
+void MGL_EXPORT mgl_fall(HMGL graph, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_fall_(uintptr_t *graph, uintptr_t *z, const char *sch, const char *opt,int,int);
+
+/// Draw belts for 2d data specified parametrically
+/** Style 'x' draw belts in x-direction. */
+void MGL_EXPORT mgl_belt_xy(HMGL graph, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_belt_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw belts for 2d data
+/** Style 'x' draw belts in x-direction. */
+void MGL_EXPORT mgl_belt(HMGL graph, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_belt_(uintptr_t *graph, uintptr_t *z, const char *sch, const char *opt,int,int);
+
+/// Draw surface for 2d data specified parametrically with color proportional to z
+/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+void MGL_EXPORT mgl_surf_xy(HMGL graph, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_surf_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw surface for 2d data with color proportional to z
+/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+void MGL_EXPORT mgl_surf(HMGL graph, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_surf_(uintptr_t *graph, uintptr_t *z, const char *sch, const char *opt,int,int);
+
+/// Draw density plot for 2d data specified parametrically
+/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+void MGL_EXPORT mgl_dens_xy(HMGL graph, HCDT x, HCDT y, HCDT c, const char *sch, const char *opt);
+void MGL_EXPORT mgl_dens_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *c, const char *sch, const char *opt,int,int);
+/// Draw density plot for 2d data
+/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+void MGL_EXPORT mgl_dens(HMGL graph, HCDT c, const char *sch, const char *opt);
+void MGL_EXPORT mgl_dens_(uintptr_t *graph, uintptr_t *c, const char *sch, const char *opt,int,int);
+
+/// Draw vertical boxes for 2d data specified parametrically
+/** Style ‘#’ draw filled boxes. */
+void MGL_EXPORT mgl_boxs_xy(HMGL graph, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_boxs_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw vertical boxes for 2d data
+/** Style ‘#’ draw filled boxes. */
+void MGL_EXPORT mgl_boxs(HMGL graph, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_boxs_(uintptr_t *graph, uintptr_t *z, const char *sch, const char *opt,int,int);
+
+/// Draw vertical tiles with manual colors c for 2d data specified parametrically
+void MGL_EXPORT mgl_tile_xyc(HMGL graph, HCDT x, HCDT y, HCDT z, HCDT c, const char *sch, const char *opt);
+void MGL_EXPORT mgl_tile_xyc_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt,int,int);
+/// Draw vertical tiles for 2d data specified parametrically
+void MGL_EXPORT mgl_tile_xy(HMGL graph, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_tile_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int,int);
+/// Draw vertical tiles for 2d data
+void MGL_EXPORT mgl_tile(HMGL graph, HCDT z, const char *sch, const char *opt);
+void MGL_EXPORT mgl_tile_(uintptr_t *graph, uintptr_t *z, const char *sch, const char *opt,int,int);
+
+/// Draw vertical tiles with variable size r and manual colors c for 2d data specified parametrically
+void MGL_EXPORT mgl_tiles_xyc(HMGL graph, HCDT x, HCDT y, HCDT z, HCDT r, HCDT c, const char *sch, const char *opt);
+void MGL_EXPORT mgl_tiles_xyc_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *r, uintptr_t *c, const char *sch, const char *opt,int,int);
+/// Draw vertical tiles with variable size r for 2d data specified parametrically
+void MGL_EXPORT mgl_tiles_xy(HMGL graph, HCDT x, HCDT y, HCDT z, HCDT r, const char *sch, const char *opt);
+void MGL_EXPORT mgl_tiles_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *r, const char *sch, const char *opt,int,int);
+/// Draw vertical tiles with variable size r for 2d data
+void MGL_EXPORT mgl_tiles(HMGL graph, HCDT z, HCDT r, const char *sch, const char *opt);
+void MGL_EXPORT mgl_tiles_(uintptr_t *graph, uintptr_t *z, uintptr_t *r, const char *sch, const char *opt,int,int);
+
+/// Draw surface for 2d data specified parametrically with color proportional to c
+/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+void MGL_EXPORT mgl_surfc_xy(HMGL graph, HCDT x, HCDT y, HCDT z, HCDT c, const char *sch, const char *opt);
+void MGL_EXPORT mgl_surfc_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt,int,int);
+/// Draw surface for 2d data with color proportional to c
+/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+void MGL_EXPORT mgl_surfc(HMGL graph, HCDT z, HCDT c, const char *sch, const char *opt);
+void MGL_EXPORT mgl_surfc_(uintptr_t *graph, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt,int,int);
+
+/// Draw surface for 2d data specified parametrically with alpha proportional to c
+/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+void MGL_EXPORT mgl_surfa_xy(HMGL graph, HCDT x, HCDT y, HCDT z, HCDT c, const char *sch, const char *opt);
+void MGL_EXPORT mgl_surfa_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt,int,int);
+/// Draw surface for 2d data with alpha proportional to c
+/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+void MGL_EXPORT mgl_surfa(HMGL graph, HCDT z, HCDT c, const char *sch, const char *opt);
+void MGL_EXPORT mgl_surfa_(uintptr_t *graph, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt,int,int);
+
+/// Draw surface for 2d data specified parametrically with  color proportional to c and alpha proportional to a
+/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+void MGL_EXPORT mgl_surfca_xy(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT c, HCDT a, const char *sch, const char *opt);
+void MGL_EXPORT mgl_surfca_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, uintptr_t *a, const char *sch, const char *opt,int,int);
+/// Draw surface for 2d data with  color proportional to c and alpha proportional to a
+/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+void MGL_EXPORT mgl_surfca(HMGL gr, HCDT z, HCDT c, HCDT a, const char *sch, const char *opt);
+void MGL_EXPORT mgl_surfca_(uintptr_t *graph, uintptr_t *z, uintptr_t *c, uintptr_t *a, const char *sch, const char *opt,int,int);
+
+/// Draw density plot for spectra-gramm specified parametrically
+/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+void MGL_EXPORT mgl_stfa_xy(HMGL graph, HCDT x, HCDT y, HCDT re, HCDT im, int dn, const char *sch, const char *opt);
+void MGL_EXPORT mgl_stfa_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *re, uintptr_t *im, int *dn, const char *sch, const char *opt,int, int);
+/// Draw density plot for spectra-gramm
+/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+void MGL_EXPORT mgl_stfa(HMGL graph, HCDT re, HCDT im, int dn, const char *sch, const char *opt);
+void MGL_EXPORT mgl_stfa_(uintptr_t *graph, uintptr_t *re, uintptr_t *im, int *dn, const char *sch, const char *opt,int, int);
+
+/// Color map of matrix a to matrix b, both matrix can parametrically depend on coordinates
+/** Style ‘.’ produce plot by dots. */
+void MGL_EXPORT mgl_map_xy(HMGL graph, HCDT x, HCDT y, HCDT a, HCDT b, const char *sch, const char *opt);
+void MGL_EXPORT mgl_map_xy_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *a, uintptr_t *b, const char *sch, const char *opt,int,int);
+/// Color map of matrix a to matrix b
+/** Style ‘.’ produce plot by dots. */
+void MGL_EXPORT mgl_map(HMGL graph, HCDT a, HCDT b, const char *sch, const char *opt);
+void MGL_EXPORT mgl_map_(uintptr_t *graph, uintptr_t *a, uintptr_t *b, const char *sch, const char *opt,int,int);
+
+#ifdef __cplusplus
+}
+#endif
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/thread.h b/include/mgl2/thread.h
new file mode 100644
index 0000000..537c9b0
--- /dev/null
+++ b/include/mgl2/thread.h
@@ -0,0 +1,86 @@
+/***************************************************************************
+ * thread.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_THREAD_H_
+#define _MGL_THREAD_H_
+#include "mgl2/define.h"
+//-----------------------------------------------------------------------------
+#if MGL_HAVE_PTHREAD
+#include <pthread.h>
+#endif
+//-----------------------------------------------------------------------------
+struct mglThreadD
+{
+	mreal *a;		// float* array with parameters or results
+	const mreal *b,*c,*d,*e;	// float* arrays with parameters
+	const long *p;	// long* array with parameters
+	const void *v;	// pointer to data/grapher
+	int id;			// thread id
+	long n;			// total number of iteration
+	const char *s;
+};
+struct mglThreadC
+{
+	dual *a;		// dual* array with parameters or results
+	const dual *b,*c,*d,*e;	// dual* arrays with parameters
+	const long *p;	// long* array with parameters
+	const void *v;	// pointer to data/grapher
+	int id;			// thread id
+	long n;			// total number of iteration
+	const char *s;
+};
+struct mglThreadV
+{
+	mreal *a;		// float* array with parameters or results
+	dual *aa;		// dual* array with parameters or results
+	const void *b,*c;	// float* arrays with parameters
+	const mreal *d;	// float* arrays with parameters
+	const long *p;	// long* array with parameters
+	const void *v;	// pointer to data/grapher
+	int id;			// thread id
+	long n;			// total number of iteration
+};
+struct mglThreadT
+{
+	void *a; 		// dual* or mreal* array with input or results
+	double *b; 		// dual* array with input or results
+	const long *p;	// long* array with parameters
+	const void *v;	// pointer to table/parameter
+	void **w; 		// pointer to workspace
+	int id;			// thread id
+	long n;			// total number of iteration
+	const void *re,*im;
+};
+/// Start several thread for the task
+void MGL_EXPORT mglStartThread(void *(*func)(void *), void (*post)(mglThreadD *,mreal *), long n,
+					mreal *a=0, const mreal *b=0, const mreal *c=0, const long *p=0,
+					const void *v=0, const mreal *d=0, const mreal *e=0, const char *s=0);
+void MGL_EXPORT mglStartThreadV(void *(*func)(void *), long n, mreal *a, const void *b=0,
+					const void *c=0, const long *p=0, const void *v=0, const mreal *d=0);
+void MGL_EXPORT mglStartThreadV(void *(*func)(void *), long n, dual *a, const void *b=0,
+					const void *c=0, const long *p=0, const void *v=0, const mreal *d=0);
+void MGL_EXPORT mglStartThreadC(void *(*func)(void *), void (*post)(mglThreadC *,dual *), long n,
+					dual *a=0, const dual *b=0, const dual *c=0, const long *p=0,
+					const void *v=0, const dual *d=0, const dual *e=0, const char *s=0);
+void MGL_EXPORT mglStartThreadT(void *(*func)(void *), long n, void *a, double *b, const void *v=0,
+					void **w=0, const long *p=0, const void *re=0, const void *im=0);
+MGL_EXPORT extern int mglNumThr;		///< Number of thread for plotting and data handling
+//-----------------------------------------------------------------------------
+#endif
+//-----------------------------------------------------------------------------
diff --git a/include/mgl2/type.h b/include/mgl2/type.h
new file mode 100644
index 0000000..7028484
--- /dev/null
+++ b/include/mgl2/type.h
@@ -0,0 +1,175 @@
+/***************************************************************************
+ * type.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_TYPE_H_
+#define _MGL_TYPE_H_
+
+#include "mgl2/define.h"
+//-----------------------------------------------------------------------------
+const mreal mglPi = M_PI;
+const mreal mglNaN = NAN;
+const mreal mglInf = INFINITY;
+const mreal mgl_min_a = 1./256;
+//-----------------------------------------------------------------------------
+#define MGL_SET_XYZ(p,xx,yy,zz)		{p.x=(xx);p.y=(yy);p.z=(zz);}
+#define MGL_SET_XY(p,xx,yy)			{p.x=(xx);p.y=(yy);p.z=0;}
+#define MGL_SET_RGBA(p,rr,gg,bb,aa)	{p.r=(rr);p.g=(gg);p.b=(bb);p.a=(aa);}
+#define MGL_SET_RGB(p,rr,gg,bb)		{p.r=(rr);p.g=(gg);p.b=(bb);}
+//-----------------------------------------------------------------------------
+/// Class for point in 3D space
+struct MGL_EXPORT mglPoint
+{
+	mreal x,y,z,c;
+	mglPoint(mreal X=0,mreal Y=0,mreal Z=0,mreal C=0):x(X),y(Y),z(Z),c(C) {}
+	mglPoint(const mglPoint &d):x(d.x),y(d.y),z(d.z),c(d.c) {}
+#if MGL_HAVE_RVAL
+	mglPoint(mglPoint &&d):x(d.x),y(d.y),z(d.z),c(d.c)	{}
+#endif
+	inline void Set(mreal X=0,mreal Y=0,mreal Z=0,mreal C=0)	{x=X;y=Y;z=Z;c=C;}
+	inline bool IsNAN()		{	return (x!=x || y!=y || z!=z || c!=c);	}
+	inline mreal val(int i)	{	return (i<2 ? (i==0 ? x:y) : (i==2 ? z:c));	}
+	inline mreal norm()		{	return sqrt(x*x+y*y+z*z);	}
+	inline void Normalize()	{	mreal v=norm();	x/=v;	y/=v;	z/=v;	}
+
+	inline const mglPoint &operator=(const mglPoint &p)
+	{	x=p.x;	y=p.y;	z=p.z;	c=p.c;	return p;	}
+	inline void operator+=(const mglPoint &a)	{	x+=a.x;	y+=a.y;	z+=a.z;	c+=a.c;	}
+	inline void operator-=(const mglPoint &a)	{	x-=a.x;	y-=a.y;	z-=a.z;	c-=a.c;	}
+	inline void operator+=(mreal a)	{	x+=a;	y+=a;	z+=a;	}
+	inline void operator-=(mreal a)	{	x-=a;	y-=a;	z-=a;	}
+	inline void operator*=(mreal a)	{	x*=a;	y*=a;	z*=a;	}
+	inline void operator/=(mreal a)	{	x/=a;	y/=a;	z/=a;	}
+};
+#ifndef SWIG
+inline mglPoint operator+(const mglPoint &a, const mglPoint &b)
+{	return mglPoint(a.x+b.x, a.y+b.y, a.z+b.z, a.c+b.c);	}
+inline mglPoint operator-(const mglPoint &a, const mglPoint &b)
+{	return mglPoint(a.x-b.x, a.y-b.y, a.z-b.z, a.c-b.c);	}
+inline mglPoint operator-(const mglPoint &a)
+{	return mglPoint(-a.x, -a.y, -a.z, -a.c);	}
+inline mglPoint operator*(mreal b, const mglPoint &a)
+{	return mglPoint(a.x*b, a.y*b, a.z*b, a.c*b);	}	// TODO check conficts of a.c*b!!!
+inline mglPoint operator*(const mglPoint &a, mreal b)
+{	return mglPoint(a.x*b, a.y*b, a.z*b, a.c*b);	}	// TODO check conficts of a.c*b!!!
+inline mglPoint operator/(const mglPoint &a, mreal b)
+{	return mglPoint(a.x/b, a.y/b, a.z/b);	}
+inline mreal operator*(const mglPoint &a, const mglPoint &b)
+{	return a.x*b.x+a.y*b.y+a.z*b.z;	}
+inline mglPoint operator/(const mglPoint &a, const mglPoint &b)
+{	return mglPoint(a.x*b.x, a.y*b.y, a.z*b.z);	}
+inline mglPoint operator&(const mglPoint &a, const mglPoint &b)
+{	return a - b*((a*b)/(b*b));	}
+inline mglPoint operator|(const mglPoint &a, const mglPoint &b)
+{	return b*((a*b)/(b*b));	}
+inline mglPoint operator^(const mglPoint &a, const mglPoint &b)
+{	return mglPoint(a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x);	}
+inline mglPoint operator!(const mglPoint &a)
+{	mreal f=mgl_hypot(a.x,a.y);	return f==0?mglPoint(0.,1.,0.):mglPoint(-a.y/f, a.x/f, 0);	}
+inline bool operator==(const mglPoint &a, const mglPoint &b)	// NOTE: exact comparison is used here
+{	return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z)+(a.c-b.c)*(a.c-b.c)==0;	}
+//{	return !memcmp(&a, &b, sizeof(mglPoint));	}
+inline bool operator!=(const mglPoint &a, const mglPoint &b)	// NOTE: exact comparison is used here
+{	return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z)+(a.c-b.c)*(a.c-b.c)!=0;	}
+//{	return memcmp(&a, &b, sizeof(mglPoint));	}
+inline bool operator<(const mglPoint &a, const mglPoint &b)
+{	return a.x<=b.x && a.y<=b.y && a.z<=b.z;	}
+inline bool operator>(const mglPoint &a, const mglPoint &b)
+{	return a.x>=b.x && a.y>=b.y && a.z>=b.z;	}
+inline mreal mgl_norm(const mglPoint &p)
+{	return sqrt(p.x*p.x+p.y*p.y+p.z*p.z);	}
+inline mreal mgl_anorm(const mglPoint &p)
+{	return fabs(p.x)+fabs(p.y)+fabs(p.z);	}
+#endif
+//-----------------------------------------------------------------------------
+/// Class for RGBA color
+struct MGL_EXPORT mglColor
+{
+	float r;	///< Red component of color
+	float g;	///< Green component of color
+	float b;	///< Blue component of color
+	float a;	///< Alpha component of color
+
+	/// Constructor for RGB components manualy
+	mglColor(float R,float G,float B, float A=1):r(R),g(G),b(B),a(A)	{}
+	/// Constructor set default color
+	mglColor():r(0),g(0),b(0),a(1)	{}
+	/// Constructor set color from character id
+	mglColor(char c, float bright=1)		{	Set(c,bright);	}
+	/// Copy constructor
+	mglColor(const mglColor &d):r(d.r),g(d.g),b(d.b),a(d.a)	{}
+#if MGL_HAVE_RVAL
+	mglColor(mglColor &&d):r(d.r),g(d.g),b(d.b),a(d.a)	{}
+#endif
+	/// Set color as Red, Green, Blue values
+	void Set(float R,float G,float B,float A=1)	{	r=R;	g=G;	b=B;	a=A;	}
+	/// Set color as Red, Green, Blue values
+	void Set(mglColor c, float bright=1)
+	{
+		if(bright<0)	bright=0;
+		if(bright>2.f)	bright=2.f;
+		r = bright<=1 ? c.r*bright : 1 - (1-c.r)*(2-bright);
+		g = bright<=1 ? c.g*bright : 1 - (1-c.g)*(2-bright);
+		b = bright<=1 ? c.b*bright : 1 - (1-c.b)*(2-bright);	a = 1;
+	}
+	/// Check if color is valid
+	inline bool Valid()
+	{	return (r>=0 && r<=1 && g>=0 && g<=1 && b>=0 && b<=1 && a>=0 && a<=1);	}
+	/// Get maximal spectral component
+	inline float Norm()
+	{	return r>g ? r : (g>b ? g : b);	}
+	inline float NormS()
+	{	return r*r+g*g+b*b;	}
+	/// Set color from symbolic id
+	inline void Set(char p, float bright=1)
+	{
+		float rgb[3];	mgl_chrrgb(p,rgb);
+		Set(mglColor(rgb[0],rgb[1],rgb[2]),bright);
+	}
+	inline const mglColor &operator=(const mglColor &p)
+	{	r=p.r;	g=p.g;	b=p.b;	a=p.a;	return p;	}
+	/// Copy color from other one
+	inline bool operator==(const mglColor &c) const	// NOTE: exact comparison is used here
+	{	return (r-c.r)*(r-c.r)+(g-c.g)*(g-c.g)+(b-c.b)*(b-c.b)+(a-c.a)*(a-c.a)==0;	}
+//	{	return !memcmp(this, &c, sizeof(mglColor));	}
+	inline bool operator!=(const mglColor &c) const	// NOTE: exact comparison is used here
+	{	return (r-c.r)*(r-c.r)+(g-c.g)*(g-c.g)+(b-c.b)*(b-c.b)+(a-c.a)*(a-c.a)!=0;	}
+//	{	return memcmp(this, &c, sizeof(mglColor));		}
+	inline bool operator<(const mglColor &c) const
+	{	return memcmp(this, &c, sizeof(mglColor))<0;	}
+	// transparency still the same
+	inline void operator*=(float v)				{	r*=v;	g*=v;	b*=v;	a*=v;	}
+	inline void operator+=(const mglColor &c)	{	r+=c.r;	g+=c.g;	b+=c.b;	a+=c.a;	}
+	inline void operator-=(const mglColor &c)	{	r-=c.r;	g-=c.g;	b-=c.b;	a-=c.a;	}
+};
+#ifndef SWIG
+inline mglColor operator+(const mglColor &a, const mglColor &b)
+{	return mglColor(a.r+b.r, a.g+b.g, a.b+b.b, a.a+b.a);	}
+inline mglColor operator-(const mglColor &a, const mglColor &b)
+{	return mglColor(a.r-b.r, a.g-b.g, a.b-b.b, a.a-b.a);	}
+inline mglColor operator*(const mglColor &a, float b)
+{	return mglColor(a.r*b, a.g*b, a.b*b, a.a*b);	}
+inline mglColor operator*(float b, const mglColor &a)
+{	return mglColor(a.r*b, a.g*b, a.b*b, a.a*b);	}
+inline mglColor operator/(const mglColor &a, float b)
+{	return mglColor(a.r/b, a.g/b, a.b/b, a.a/b);	}
+inline mglColor operator!(const mglColor &a)
+{	return mglColor(1-a.r, 1-a.g, 1-a.b, a.a);	}
+#endif
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/vect.h b/include/mgl2/vect.h
new file mode 100644
index 0000000..120fd30
--- /dev/null
+++ b/include/mgl2/vect.h
@@ -0,0 +1,222 @@
+/***************************************************************************
+ * vect.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_VECT_H_
+#define _MGL_VECT_H_
+#include "mgl2/abstract.h"
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+extern "C" {
+#endif
+//-----------------------------------------------------------------------------
+/// Plot vectors at position {x,y} along {ax,ay} with length/color proportional to |a|
+/** Option value set the vector length factor (if non-zero) or vector length to be proportional the distance between curve points (if value=0). */
+void MGL_EXPORT mgl_traj_xy(HMGL gr, HCDT x, HCDT y, HCDT ax, HCDT ay, const char *sch, const char *opt);
+void MGL_EXPORT mgl_traj_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *ax, uintptr_t *ay, const char *sch, const char *opt,int,int);
+/// Plot vectors at position {x,y,z} along {ax,ay,az} with length/color proportional to |a|
+/** Option value set the vector length factor (if non-zero) or vector length to be proportional the distance between curve points (if value=0). */
+void MGL_EXPORT mgl_traj_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT ax, HCDT ay, HCDT az, const char *sch, const char *opt);
+void MGL_EXPORT mgl_traj_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *ax, uintptr_t *ay, uintptr_t *az, const char *sch, const char *opt,int,int);
+
+/// Plot vector field {ax,ay} parametrically depended on coordinate {x,y} with length/color proportional to |a|
+/** String \a sch may contain:
+ * ‘f’ for drawing arrows with fixed lengths,
+ * ‘ >’, ‘<’ for drawing arrows to or from the ce*ll point (default is centering),
+ * ‘.’ for drawing hachures with dots instead of arrows,
+ * ‘=’ for enabling color gradient along arrows. */
+void MGL_EXPORT mgl_vect_xy(HMGL gr, HCDT x, HCDT y, HCDT ax, HCDT ay, const char *sch, const char *opt);
+void MGL_EXPORT mgl_vect_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *ax, uintptr_t *ay, const char *sch, const char *opt,int,int);
+/// Plot vector field {ax,ay} with length/color proportional to |a|
+/** String \a sch may contain:
+ * ‘f’ for drawing arrows with fixed lengths,
+ * ‘ >’, ‘<’ for drawing arrows to or from the ce*ll point (default is centering),
+ * ‘.’ for drawing hachures with dots instead of arrows,
+ * ‘=’ for enabling color gradient along arrows. */
+void MGL_EXPORT mgl_vect_2d(HMGL gr, HCDT ax, HCDT ay, const char *sch, const char *opt);
+void MGL_EXPORT mgl_vect_2d_(uintptr_t *gr, uintptr_t *ax, uintptr_t *ay, const char *sch, const char *opt,int,int);
+/// Plot vector field {ax,ay,az} parametrically depended on coordinate {x,y,z} with length/color proportional to |a|
+/** String \a sch may contain:
+ * ‘f’ for drawing arrows with fixed lengths,
+ * ‘ >’, ‘<’ for drawing arrows to or from the ce*ll point (default is centering),
+ * ‘.’ for drawing hachures with dots instead of arrows,
+ * ‘=’ for enabling color gradient along arrows. */
+void MGL_EXPORT mgl_vect_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT ax, HCDT ay, HCDT az, const char *sch, const char *opt);
+void MGL_EXPORT mgl_vect_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *ax, uintptr_t *ay, uintptr_t *az, const char *sch, const char *opt,int,int);
+/// Plot vector field {ax,ay,az} with length/color proportional to |a|
+/** String \a sch may contain:
+ * ‘f’ for drawing arrows with fixed lengths,
+ * ‘ >’, ‘<’ for drawing arrows to or from the ce*ll point (default is centering),
+ * ‘.’ for drawing hachures with dots instead of arrows,
+ * ‘=’ for enabling color gradient along arrows. */
+void MGL_EXPORT mgl_vect_3d(HMGL gr, HCDT ax, HCDT ay, HCDT az, const char *sch, const char *opt);
+void MGL_EXPORT mgl_vect_3d_(uintptr_t *gr, uintptr_t *ax, uintptr_t *ay, uintptr_t *az, const char *sch, const char *opt,int,int);
+
+/// Plot flows for vector field {ax,ay} parametrically depended on coordinate {x,y} with color proportional to |a|
+/** String \a sch may contain:
+ * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+ * ‘#’ for starting threads from edges only;
+ * ‘v’ for drawing arrows on the threads.
+ * Option "value" sets the number of threads (default is 5). */
+void MGL_EXPORT mgl_flow_xy(HMGL gr, HCDT x, HCDT y, HCDT ax, HCDT ay, const char *sch, const char *opt);
+void MGL_EXPORT mgl_flow_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *ax, uintptr_t *ay, const char *sch, const char *opt,int,int);
+/// Plot flows for vector field {ax,ay} with color proportional to |a|
+/** String \a sch may contain:
+ * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+ * ‘#’ for starting threads from edges only;
+ * ‘v’ for drawing arrows on the threads.
+ * Option "value" sets the number of threads (default is 5). */
+void MGL_EXPORT mgl_flow_2d(HMGL gr, HCDT ax, HCDT ay, const char *sch, const char *opt);
+void MGL_EXPORT mgl_flow_2d_(uintptr_t *gr, uintptr_t *ax, uintptr_t *ay, const char *sch, const char *opt,int,int);
+/// Plot flows for vector field {ax,ay,az} parametrically depended on coordinate {x,y,z} with color proportional to |a|
+/** String \a sch may contain:
+ * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+ * ‘#’ for starting threads from edges only;
+ * ‘v’ for drawing arrows on the threads;
+ * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+ * Option "value" sets the number of threads (default is 5). */
+void MGL_EXPORT mgl_flow_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT ax, HCDT ay, HCDT az, const char *sch, const char *opt);
+void MGL_EXPORT mgl_flow_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *ax, uintptr_t *ay, uintptr_t *az, const char *sch, const char *opt,int,int);
+/// Plot flows for vector field {ax,ay,az} with color proportional to |a|
+/** String \a sch may contain:
+ * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+ * ‘#’ for starting threads from edges only;
+ * ‘v’ for drawing arrows on the threads;
+ * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+ * Option "value" sets the number of threads (default is 5). */
+void MGL_EXPORT mgl_flow_3d(HMGL gr, HCDT ax, HCDT ay, HCDT az, const char *sch, const char *opt);
+void MGL_EXPORT mgl_flow_3d_(uintptr_t *gr, uintptr_t *ax, uintptr_t *ay, uintptr_t *az, const char *sch, const char *opt,int,int);
+
+/// Plot flow from point p for vector field {ax,ay} parametrically depended on coordinate {x,y} with color proportional to |a|
+/** String \a sch may contain:
+ * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+ * ‘#’ for starting threads from edges only;
+ * ‘v’ for drawing arrows on the threads. */
+void MGL_EXPORT mgl_flowp_xy(HMGL gr, double x0, double y0, double z0, HCDT x, HCDT y, HCDT ax, HCDT ay, const char *sch, const char *opt);
+void MGL_EXPORT mgl_flowp_xy_(uintptr_t *gr, mreal *x0, mreal *y0, mreal *z0, uintptr_t *x, uintptr_t *y, uintptr_t *ax, uintptr_t *ay, const char *sch, const char *opt,int, int);
+/// Plot flow from point p for vector field {ax,ay} with color proportional to |a|
+/** String \a sch may contain:
+ * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+ * ‘#’ for starting threads from edges only;
+ * ‘v’ for drawing arrows on the threads. */
+void MGL_EXPORT mgl_flowp_2d(HMGL gr, double x0, double y0, double z0, HCDT ax, HCDT ay, const char *sch, const char *opt);
+void MGL_EXPORT mgl_flowp_2d_(uintptr_t *gr, mreal *x0, mreal *y0, mreal *z0, uintptr_t *ax, uintptr_t *ay, const char *sch, const char *opt,int, int);
+/// Plot flow from point p for vector field {ax,ay,az} parametrically depended on coordinate {x,y,z} with color proportional to |a|
+/** String \a sch may contain:
+ * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+ * ‘#’ for starting threads from edges only;
+ * ‘v’ for drawing arrows on the threads;
+ * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly. */
+void MGL_EXPORT mgl_flowp_xyz(HMGL gr, double x0, double y0, double z0, HCDT x, HCDT y, HCDT z, HCDT ax, HCDT ay, HCDT az, const char *sch, const char *opt);
+void MGL_EXPORT mgl_flowp_xyz_(uintptr_t *gr, mreal *x0, mreal *y0, mreal *z0, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *ax, uintptr_t *ay, uintptr_t *az, const char *sch, const char *opt,int, int);
+/// Plot flow from point p for vector field {ax,ay,az} with color proportional to |a|
+/** String \a sch may contain:
+ * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+ * ‘#’ for starting threads from edges only;
+ * ‘v’ for drawing arrows on the threads;
+ * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly. */
+void MGL_EXPORT mgl_flowp_3d(HMGL gr, double x0, double y0, double z0, HCDT ax, HCDT ay, HCDT az, const char *sch, const char *opt);
+void MGL_EXPORT mgl_flowp_3d_(uintptr_t *gr, mreal *x0, mreal *y0, mreal *z0, uintptr_t *ax, uintptr_t *ay, uintptr_t *az, const char *sch, const char *opt,int,int);
+
+/// Plot flow pipes for vector field {ax,ay} parametrically depended on coordinate {x,y} with color and radius proportional to |a|
+/** String \a sch may contain:
+ * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+ * ‘#’ for starting threads from edges only;
+ * ‘i’ for pipe radius to be inverse proportional to amplitude.
+ * Option "value" sets the number of threads (default is 5). */
+void MGL_EXPORT mgl_pipe_xy(HMGL gr, HCDT x, HCDT y, HCDT ax, HCDT ay, const char *sch, double r0, const char *opt);
+void MGL_EXPORT mgl_pipe_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *ax, uintptr_t *ay, const char *sch, mreal *r0, const char *opt,int,int);
+/// Plot flow pipes for vector field {ax,ay} with color and radius proportional to |a|
+/** String \a sch may contain:
+ * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+ * ‘#’ for starting threads from edges only;
+ * ‘i’ for pipe radius to be inverse proportional to amplitude.
+ * Option "value" sets the number of threads (default is 5). */
+void MGL_EXPORT mgl_pipe_2d(HMGL gr, HCDT ax, HCDT ay, const char *sch, double r0, const char *opt);
+void MGL_EXPORT mgl_pipe_2d_(uintptr_t *gr, uintptr_t *ax, uintptr_t *ay, const char *sch, mreal *r0, const char *opt,int,int);
+/// Plot flow pipes for vector field {ax,ay,az} parametrically depended on coordinate {x,y,z} with color and radius proportional to |a|
+/** String \a sch may contain:
+ * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+ * ‘#’ for starting threads from edges only;
+ * ‘i’ for pipe radius to be inverse proportional to amplitude;
+ * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+ * Option "value" sets the number of threads (default is 5). */
+void MGL_EXPORT mgl_pipe_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT ax, HCDT ay, HCDT az, const char *sch, double r0, const char *opt);
+void MGL_EXPORT mgl_pipe_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *ax, uintptr_t *ay, uintptr_t *az, const char *sch, mreal *r0, const char *opt,int,int);
+/// Plot flow pipes for vector field {ax,ay,az} with color and radius proportional to |a|
+/** String \a sch may contain:
+ * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+ * ‘#’ for starting threads from edges only;
+ * ‘i’ for pipe radius to be inverse proportional to amplitude;
+ * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+ * Option "value" sets the number of threads (default is 5). */
+void MGL_EXPORT mgl_pipe_3d(HMGL gr, HCDT ax, HCDT ay, HCDT az, const char *sch, double r0, const char *opt);
+void MGL_EXPORT mgl_pipe_3d_(uintptr_t *gr, uintptr_t *ax, uintptr_t *ay, uintptr_t *az, const char *sch, mreal *r0, const char *opt,int,int);
+
+/// Plot flows for gradient of scalar field phi parametrically depended on coordinate {x,y,z}
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+	 * Option "value" sets the number of threads (default is 5). */
+void MGL_EXPORT mgl_grad_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT ph, const char *sch, const char *opt);
+void MGL_EXPORT mgl_grad_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *ph, const char *sch, const char *opt,int, int);
+/// Plot flows for gradient of scalar field phi parametrically depended on coordinate {x,y}
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+	 * Option "value" sets the number of threads (default is 5). */
+void MGL_EXPORT mgl_grad_xy(HMGL gr, HCDT x, HCDT y, HCDT ph, const char *sch, const char *opt);
+void MGL_EXPORT mgl_grad_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *ph, const char *sch, const char *opt,int,int);
+/// Plot flows for gradient of scalar field phi
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+	 * Option "value" sets the number of threads (default is 5). */
+void MGL_EXPORT mgl_grad(HMGL gr, HCDT ph, const char *sch, const char *opt);
+void MGL_EXPORT mgl_grad_(uintptr_t *gr, uintptr_t *ph, const char *sch, const char *opt,int,int);
+
+/// Draw vector plot along slice for 3d data specified parametrically
+/** String \a sch may contain:
+ * ‘f’ for drawing arrows with fixed lengths,
+ * ‘ >’, ‘<’ for drawing arrows to or from the ce*ll point (default is centering),
+ * ‘.’ for drawing hachures with dots instead of arrows,
+ * ‘=’ for enabling color gradient along arrows,
+ * ‘ x’, ‘z’ for producing plot perpendicular to x- or z-direction correspondingly. */
+void MGL_EXPORT mgl_vect3_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT ax, HCDT ay, HCDT az, const char *sch, double sVal, const char *opt);
+void MGL_EXPORT mgl_vect3_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *ax, uintptr_t *ay, uintptr_t *az, const char *sch, mreal *sVal, const char *opt,int,int);
+/// Draw vector plot along slice for 3d data
+/** String \a sch may contain:
+ * ‘f’ for drawing arrows with fixed lengths,
+ * ‘ >’, ‘<’ for drawing arrows to or from the ce*ll point (default is centering),
+ * ‘.’ for drawing hachures with dots instead of arrows,
+ * ‘=’ for enabling color gradient along arrows,
+ * ‘ x’, ‘z’ for producing plot perpendicular to x- or z-direction correspondingly. */
+void MGL_EXPORT mgl_vect3(HMGL gr, HCDT ax, HCDT ay, HCDT az, const char *sch, double sVal, const char *opt);
+void MGL_EXPORT mgl_vect3_(uintptr_t *gr, uintptr_t *ax, uintptr_t *ay, uintptr_t *az, const char *sch, mreal *sVal, const char *opt,int,int);
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+}
+#endif
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/vectors.fs b/include/mgl2/vectors.fs
new file mode 100644
index 0000000..b3eb672
--- /dev/null
+++ b/include/mgl2/vectors.fs
@@ -0,0 +1,161 @@
+\ Integer vectors library                     Thu Feb 21 12:46:01 MST 2008
+\ Copyright (C) 2008, Sergey Plis
+\
+\ 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.
+
+\needs float import float
+
+\ vector variables better have names ending with "(" for readability
+Module vectors
+also float
+
+\ fetches
+| create fetch_operations ' c@ , ' w@ , ' @ ,  0 , ' 2@ , ' f@ ,
+
+\ stores
+| create store_operations ' c! , ' w! , ' ! ,  0 , ' 2! , ' f! ,
+| : type-idx ( cell_size -- idx ) 4 >> ; macro
+| : f-op ( cell-size -- cfa ) type-idx cells fetch_operations + @ ;
+| : s-op ( cell-size -- cfa ) type-idx cells store_operations + @ ;
+
+: ^)! ( *vector -- addr ) [ 3 cells ] literal - @ ;
+: ^)@ ( *vector -- addr ) [ 4 cells ] literal - @ ;
+
+\ number of elements
+: )size ( *vector -- size ) [ 1 cells ] literal - @ ;
+
+\ set number of elements - useful for temporal size adjustments in
+\ datastructures such as heaps
+: )size! ( sz *vector -- ) [ 1 cells ] literal - ! ;
+
+\ size of an element in bytes
+: )type ( *vector -- size ) [ 2 cells ] literal - @ ;
+
+: )free ( *vector -- ) [ 4 cells ] literal - free throw ;
+
+\ header | fetch_cfa | store_cfa | el_size | #els |
+\ cell-size in bits
+\ unnamed vector
+: _vector ( n cell-size -- addr )
+    2dup * [ 4 cells ] literal + allocate throw
+    dup >r   over f-op swap !
+    r@ cell+ over s-op swap !
+    r@ [ 2 cells ] literal + ! \ cell size store
+    r@ [ 3 cells ] literal + ! \ #els store
+    r> [ 4 cells ] literal + ;
+
+\ named vector
+: vector ( n cell-size -- )
+    create
+    2dup * [ 4 cells ] literal + allocate throw dup ,
+    dup >r   over f-op swap !
+    r@ cell+ over s-op swap !
+    r@ [ 2 cells ] literal + ! \ cell size store
+    r@ [ 3 cells ] literal + ! \ #els store
+    r> dup
+    \ erasing the content
+    [ 2 cells ] literal + @ over [ 3 cells ] literal + @ *
+    swap [ 4 cells ] literal + swap erase
+  does> @ [ 4 cells ] literal + ;
+
+\ vector of pointers
+: vector*  ( # -- *vector ) cell 8 * _vector ;
+
+| : ?idx-in-range ( *vector idx -- 1/0 ) dup rot )size < swap 0>= and ;
+| : check-range ( *vector idx -- *vector idx | fail )
+    2dup ?idx-in-range not abort" Index is out of range! " ;
+
+\ addr of ith element of the vector
+: *)  ( *vector i -- addr ) over )type 3 >> * + ;
+: )@ ( *vector index -- )
+    [IFDEF] отладка
+	check-range
+    [THEN]
+    over dup ^)@ >r )type 3 >> * + r> execute ;
+: )! ( value *vector index -- )
+    [IFDEF] отладка
+	check-range
+    [THEN]
+    over dup ^)! >r )type 3 >> * + r> execute ;
+\ : test! cell * + ! ;
+| create print-funcs ' . , ' . , ' . , 0 , ' d. , ' f. ,
+: )print ( *v -- cfa ) )type type-idx cells print-funcs + @ execute ;
+: )map ( *v xt -- ) swap dup )size 0 do 2dup  i )@ swap execute loop 2drop ;
+: map ( *v -- ) ( word-to-map ) ' swap dup )size 0 do 2dup  i )@ swap execute loop 2drop ;
+: )initperm ( v( -- )
+    dup )size 0 do
+	dup
+	i swap over )!
+    loop drop ;
+: ). ( *vector -- ) dup )size 0 do dup i )@ over )print loop drop ;
+\ does arbitrary vector contain this element ?
+: )in? ( *v value -- 1/0 )
+    swap dup )size 0 do
+	2dup i )@ = if 2drop True unloop exit then
+    loop 2drop False ;
+: )find ( *v value -- i True/False )
+    swap dup )size 0 do
+	2dup i )@ = if 2drop i True unloop exit then
+    loop 2drop False ;
+: vector->stack ( *v -- n1 n2 .. n# # )
+    dup )size 0 do dup i )@ swap loop )size ;
+\ initialized cell vector
+\ preserve order
+: ivector* ( n1 n2 .. n# # -- *vector )
+    dup vector* swap 1- 0 swap do
+	swap over i )!
+    -1 +loop ;
+\ reversed order
+: irvector* ( n1 n2 .. n# # -- *vector )
+    dup vector* swap 0 do
+	swap over i )!
+    loop ;
+\ does not take care of duplicate elements
+| : overlap ( v1( v2( -- n1 .. n2 # / 0 ) depth 2- >r
+    dup )size 0 do
+	2dup i )@ )in? if
+	    dup i )@ -rot
+	then
+    loop 2drop depth r> - ;
+| : notoverlap ( v1( v2( -- n1 .. n2 # )
+    depth 2- >r
+    dup )size 0 do
+	2dup i )@ )in? not if
+	    dup i )@ -rot
+	then
+    loop 2drop depth r> - ;
+: )union ( *v1( *v2( -- *v3( )
+    over >r
+    notoverlap
+    r> swap >r vector->stack r> +
+    dup 0= abort" empty union!"
+    ivector* ;
+: )intersection ( *v1( *v2( -- *v3(/0 )
+    overlap dup 0<> if ivector* then ;
+\ elementwise comparison of two vectors
+: )= ( *v1( *v2( -- 1/0 ) dup )size >r over )size r>
+    <> if 2drop 0 exit then
+    dup )size 0 do
+	2dup i )@ swap i )@ <> if
+	    2drop unloop 0 exit
+	then
+    loop 2drop -1 ;
+: subset? ( *v( *s( -- 1/0 )
+    2dup )intersection dup 0= if -rot 2drop exit then
+    dup >r )= swap drop r> )free ;
+: )clone ( *v -- *cv )
+    vector->stack ivector* ;
+: )erase ( *v -- ) dup )size over )type 3 >> * erase ;
+: _last ( *v -- *v idx-of-last-element ) dup )size 1- ;
+
+clear
+previous
+Module;
\ No newline at end of file
diff --git a/include/mgl2/volume.h b/include/mgl2/volume.h
new file mode 100644
index 0000000..c5efca9
--- /dev/null
+++ b/include/mgl2/volume.h
@@ -0,0 +1,135 @@
+/***************************************************************************
+ * volume.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_VOL_H_
+#define _MGL_VOL_H_
+#include "mgl2/abstract.h"
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+extern "C" {
+#endif
+//-----------------------------------------------------------------------------
+/// Draw isosurface for 3d data specified parametrically
+/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.*/
+void MGL_EXPORT mgl_surf3_xyz_val(HMGL graph, double Val, HCDT x, HCDT y, HCDT z, HCDT a, const char *stl, const char *opt);
+void MGL_EXPORT mgl_surf3_xyz_val_(uintptr_t *graph, mreal *Val, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *stl, const char *opt,int,int);
+/// Draw isosurface for 3d data
+/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.*/
+void MGL_EXPORT mgl_surf3_val(HMGL graph, double Val, HCDT a, const char *stl, const char *opt);
+void MGL_EXPORT mgl_surf3_val_(uintptr_t *graph, mreal *Val, uintptr_t *a, const char *stl, const char *opt,int,int);
+/// Draw isosurfaces for 3d data specified parametrically
+/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+ * Option "value" set the number of isosurfaces (default is 3). */
+void MGL_EXPORT mgl_surf3_xyz(HMGL graph, HCDT x, HCDT y, HCDT z, HCDT a, const char *stl, const char *opt);
+void MGL_EXPORT mgl_surf3_xyz_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *stl, const char *opt,int,int);
+/// Draw isosurfaces for 3d data
+/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+ * Option "value" set the number of isosurfaces (default is 3). */
+void MGL_EXPORT mgl_surf3(HMGL graph, HCDT a, const char *stl, const char *opt);
+void MGL_EXPORT mgl_surf3_(uintptr_t *graph, uintptr_t *a, const char *stl, const char *opt,int,int);
+
+/// Draw isosurface for 3d data specified parametrically with alpha proportional to b
+/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots. */
+void MGL_EXPORT mgl_surf3a_xyz_val(HMGL graph, double Val, HCDT x, HCDT y, HCDT z, HCDT a, HCDT b, const char *stl, const char *opt);
+void MGL_EXPORT mgl_surf3a_xyz_val_(uintptr_t *graph, mreal *Val, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, uintptr_t *b, const char *stl, const char *opt,int,int);
+/// Draw isosurface for 3d data with alpha proportional to b
+/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots. */
+void MGL_EXPORT mgl_surf3a_val(HMGL graph, double Val, HCDT a, HCDT b, const char *stl, const char *opt);
+void MGL_EXPORT mgl_surf3a_val_(uintptr_t *graph, mreal *Val, uintptr_t *a, uintptr_t *b, const char *stl, const char *opt,int,int);
+/// Draw isosurfaces for 3d data specified parametrically with alpha proportional to b
+/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+ * Option "value" set the number of isosurfaces (default is 3). */
+void MGL_EXPORT mgl_surf3a_xyz(HMGL graph, HCDT x, HCDT y, HCDT z, HCDT a, HCDT b, const char *stl, const char *opt);
+void MGL_EXPORT mgl_surf3a_xyz_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, uintptr_t *b, const char *stl, const char *opt,int,int);
+/// Draw isosurfaces for 3d data with alpha proportional to b
+/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+ * Option "value" set the number of isosurfaces (default is 3). */
+void MGL_EXPORT mgl_surf3a(HMGL graph, HCDT a, HCDT b, const char *stl, const char *opt);
+void MGL_EXPORT mgl_surf3a_(uintptr_t *graph, uintptr_t *a, uintptr_t *b, const char *stl, const char *opt,int,int);
+
+/// Draw isosurface for 3d data specified parametrically with color proportional to b
+/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots. */
+void MGL_EXPORT mgl_surf3c_xyz_val(HMGL graph, double Val, HCDT x, HCDT y, HCDT z, HCDT a, HCDT b, const char *stl, const char *opt);
+void MGL_EXPORT mgl_surf3c_xyz_val_(uintptr_t *graph, mreal *Val, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, uintptr_t *b, const char *stl, const char *opt,int,int);
+/// Draw isosurface for 3d data with color proportional to b
+/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots. */
+void MGL_EXPORT mgl_surf3c_val(HMGL graph, double Val, HCDT a, HCDT b, const char *stl, const char *opt);
+void MGL_EXPORT mgl_surf3c_val_(uintptr_t *graph, mreal *Val, uintptr_t *a, uintptr_t *b, const char *stl, const char *opt,int,int);
+/// Draw isosurfaces for 3d data specified parametrically with color proportional to b
+/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+ * Option "value" set the number of isosurfaces (default is 3). */
+void MGL_EXPORT mgl_surf3c_xyz(HMGL graph, HCDT x, HCDT y, HCDT z, HCDT a, HCDT b, const char *stl, const char *opt);
+void MGL_EXPORT mgl_surf3c_xyz_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, uintptr_t *b, const char *stl, const char *opt,int,int);
+/// Draw isosurfaces for 3d data with color proportional to b
+/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+ * Option "value" set the number of isosurfaces (default is 3). */
+void MGL_EXPORT mgl_surf3c(HMGL graph, HCDT a, HCDT b, const char *stl, const char *opt);
+void MGL_EXPORT mgl_surf3c_(uintptr_t *graph, uintptr_t *a, uintptr_t *b, const char *stl, const char *opt,int,int);
+
+/// Draw isosurface for 3d data specified parametrically with color proportional to c and alpha proportional to b
+/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots. */
+void MGL_EXPORT mgl_surf3ca_xyz_val(HMGL graph, double Val, HCDT x, HCDT y, HCDT z, HCDT a, HCDT c, HCDT b, const char *stl, const char *opt);
+void MGL_EXPORT mgl_surf3ca_xyz_val_(uintptr_t *graph, mreal *Val, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, uintptr_t *c, uintptr_t *b, const char *stl, const char *opt,int,int);
+/// Draw isosurface for 3d data with color proportional to c and alpha proportional to b
+/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots. */
+void MGL_EXPORT mgl_surf3ca_val(HMGL graph, double Val, HCDT a, HCDT c, HCDT b, const char *stl, const char *opt);
+void MGL_EXPORT mgl_surf3ca_val_(uintptr_t *graph, mreal *Val, uintptr_t *a, uintptr_t *c, uintptr_t *b, const char *stl, const char *opt,int,int);
+/// Draw isosurfaces for 3d data specified parametrically with color proportional to c and alpha proportional to b
+/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+ * Option "value" set the number of isosurfaces (default is 3). */
+void MGL_EXPORT mgl_surf3ca_xyz(HMGL graph, HCDT x, HCDT y, HCDT z, HCDT a, HCDT c, HCDT b, const char *stl, const char *opt);
+void MGL_EXPORT mgl_surf3ca_xyz_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, uintptr_t *c, uintptr_t *b, const char *stl, const char *opt,int,int);
+/// Draw isosurfaces for 3d data with color proportional to c and alpha proportional to b
+/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+ * Option "value" set the number of isosurfaces (default is 3). */
+void MGL_EXPORT mgl_surf3ca(HMGL graph, HCDT a, HCDT c, HCDT b, const char *stl, const char *opt);
+void MGL_EXPORT mgl_surf3ca_(uintptr_t *graph, uintptr_t *a, uintptr_t *c, uintptr_t *b, const char *stl, const char *opt,int,int);
+
+/// Draw a semi-transparent cloud for 3d data specified parametrically
+/** Style ‘.’ produce plot by dots. Style ‘i’ use inverted values for transparency. */
+void MGL_EXPORT mgl_cloud_xyz(HMGL graph, HCDT x, HCDT y, HCDT z, HCDT a, const char *stl, const char *opt);
+void MGL_EXPORT mgl_cloud_xyz_(uintptr_t *graph, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *stl, const char *opt,int,int);
+/// Draw a semi-transparent cloud for 3d data
+/** Style ‘.’ produce plot by dots. Style ‘i’ use inverted values for transparency. */
+void MGL_EXPORT mgl_cloud(HMGL graph, HCDT a, const char *stl, const char *opt);
+void MGL_EXPORT mgl_cloud_(uintptr_t *graph, uintptr_t *a, const char *stl, const char *opt,int,int);
+
+/// Draw isosurface for 3d beam in curvilinear coordinates
+/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.
+ *  Variable \a flag is bitwise:
+ * ‘0x1’ - draw in accompanied (not laboratory) coordinates;
+ * ‘0x2’ - draw projection to \rho-z plane;
+ * ‘0x4’ - draw normalized in each slice field.*/
+void MGL_EXPORT mgl_beam_val(HMGL graph, double Val, HCDT tr, HCDT g1, HCDT g2, HCDT a, double r, const char *stl, int norm);
+void MGL_EXPORT mgl_beam_val_(uintptr_t *gr, mreal *val, uintptr_t *tr, uintptr_t *g1, uintptr_t *g2, uintptr_t *a, mreal *r, const char *sch, int *norm,int l);
+/// Draw several isosurfaces for 3d beam in curvilinear coordinates
+/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.
+ * Option "value" set the number of isosurfaces (default is 3).
+ *  Variable \a flag is bitwise:
+ * ‘0x1’ - draw in accompanied (not laboratory) coordinates;
+ * ‘0x2’ - draw projection to \rho-z plane;
+ * ‘0x4’ - draw normalized in each slice field.*/
+void MGL_EXPORT mgl_beam(HMGL graph, HCDT tr, HCDT g1, HCDT g2, HCDT a, double r, const char *stl, int norm, int num);
+void MGL_EXPORT mgl_beam_(uintptr_t *gr, uintptr_t *tr, uintptr_t *g1, uintptr_t *g2, uintptr_t *a, mreal *r, const char *sch, int *norm, int *num,int l);
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+}
+#endif
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/window.h b/include/mgl2/window.h
new file mode 100644
index 0000000..d20f348
--- /dev/null
+++ b/include/mgl2/window.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+ * window.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_WINDOW_H_
+#define _MGL_WINDOW_H_
+
+#include "mgl2/qt.h"
+#include "mgl2/fltk.h"
+//#include "mgl2/wx.h"
+//-----------------------------------------------------------------------------
+/// Wrapper class for all windows displaying graphics
+class MGL_EXPORT mglWindow : public mglWnd
+{
+	mglWindow(const mglWindow &t) {}	// copying is not allowed
+	const mglWindow &operator=(const mglWindow &t)	{	return t;	}
+	int wnd;	///< Type of window
+public:
+	mglWindow(const char *title="MathGL") : mglWnd()
+	{	wnd=1;	gr = mgl_create_graph_fltk(0,title,0,0);	}
+	mglWindow(int (*draw)(HMGL gr, void *p), const char *title="MathGL", void *par=NULL, int kind=0, void (*load)(void *p)=0) : mglWnd()
+	{
+		wnd=kind;
+		if(wnd==1)	gr = mgl_create_graph_qt(draw,title,par,load);
+		else		gr = mgl_create_graph_fltk(draw,title,par,load);
+	}
+	mglWindow(int (*draw)(mglGraph *gr), const char *title="MathGL", int kind=0) : mglWnd()
+	{
+		wnd=kind;
+		if(wnd==1)	gr = mgl_create_graph_qt(draw?mgl_draw_graph:0,title,(void*)draw,0);
+		else		gr = mgl_create_graph_fltk(draw?mgl_draw_graph:0,title,(void*)draw,0);
+	}
+	mglWindow(mglDraw *draw, const char *title="MathGL", int kind=0) : mglWnd()
+	{
+		wnd=kind;
+		if(wnd==1)	gr = mgl_create_graph_qt(draw?mgl_draw_class:0,title,draw,mgl_reload_class);
+		else		gr = mgl_create_graph_fltk(draw?mgl_draw_class:0,title,draw,mgl_reload_class);
+		mgl_set_click_func(gr, mgl_click_class);
+	}
+	/// Run main loop for event handling
+	int Run()	{	return wnd==0? mgl_fltk_run():mgl_qt_run();	}
+	/// Run main loop for event handling in separate thread (for FLTK only)
+	inline int RunThr()	{	return wnd==0 ? mgl_fltk_thr():0;	}
+};
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/wnd.h b/include/mgl2/wnd.h
new file mode 100644
index 0000000..8cadd9c
--- /dev/null
+++ b/include/mgl2/wnd.h
@@ -0,0 +1,137 @@
+/***************************************************************************
+ * wnd.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef _MGL_WND_H_
+#define _MGL_WND_H_
+
+#include "mgl2/mgl.h"
+//-----------------------------------------------------------------------------
+MGL_EXPORT void *mgl_draw_calc(void *p);
+//-----------------------------------------------------------------------------
+/// Class for drawing in windows (like, mglCanvasFL, mglCanvasQT and so on)
+/// Make inherited class and redefine Draw() function if you don't want to use function pointers.
+class MGL_EXPORT mglDraw
+{
+public:
+	virtual int Draw(mglGraph *)=0;	///< Function for drawing
+	virtual void Reload(){}		///< Function for reloading data
+	virtual void Click() {}		///< Callback function on mouse click
+#if MGL_HAVE_PTHR_WIDGET
+	mglDraw()	{	running=false;	pthread_mutex_init(&mutex,NULL);	}
+	virtual ~mglDraw()	{	pthread_mutex_destroy(&mutex);	}
+
+	virtual void Calc()	{}		///< Function for calculations
+	inline void Run()			///< Run/resume calculation in other thread
+	{
+		if(!running)
+		{	pthread_mutex_trylock(&mutex);	pthread_mutex_unlock(&mutex);
+			pthread_create(&thr,0,mgl_draw_calc,this);
+			pthread_detach(thr);	running = true;	}
+	}
+	inline void Cancel()		///< Cancel thread with calculations
+	{	pthread_cancel(thr);	running = false;	}
+	inline void Pause()			///< Pause calculation
+	{	pthread_mutex_lock(&mutex);	}
+	inline void Continue()		///< Continue calculation
+	{	pthread_mutex_trylock(&mutex);	pthread_mutex_unlock(&mutex);	}
+	inline void Check()			///< Check if calculation can be continued (should be called inside Calc() )
+	{	pthread_mutex_lock(&mutex);	pthread_mutex_unlock(&mutex);	}
+//protected:
+	pthread_t thr;
+	bool running;
+	pthread_mutex_t mutex;
+
+#else
+	mglDraw() {}
+	virtual ~mglDraw() {}
+#endif
+};
+//-----------------------------------------------------------------------------
+extern "C" {
+int MGL_EXPORT mgl_draw_graph(HMGL gr, void *p);
+// NOTE: MGL_EXPORT mgl_draw_class() and MGL_EXPORT mgl_draw_load() use mglWindow* only. Don't use it with inherited classes
+int MGL_EXPORT mgl_draw_class(HMGL gr, void *p);
+void MGL_EXPORT mgl_click_class(void *p);
+void MGL_EXPORT mgl_reload_class(void *p);
+}
+//-----------------------------------------------------------------------------
+/// Abstract class for windows displaying graphics
+class MGL_EXPORT mglWnd : public mglGraph
+{
+	mglWnd(const mglWnd &) {}	// copying is not allowed
+	const mglWnd &operator=(const mglWnd &t)	{	return t;	}
+public:
+	mglWnd() : mglGraph(-1)	{}
+	virtual ~mglWnd() {	mgl_use_graph(gr,-255);	}
+	virtual int Run()=0;		///< Run main loop for event handling
+	/// Return pointer to widget used for plotting
+	virtual void *Widget()	{	return NULL;	}
+
+	inline void ToggleAlpha()	///< Switch on/off transparency (do not overwrite user settings)
+	{	mgl_wnd_toggle_alpha(gr);	}
+	inline void ToggleLight()	///< Switch on/off lighting (do not overwrite user settings)
+	{	mgl_wnd_toggle_light(gr);	}
+	inline void ToggleZoom()	///< Switch on/off zooming by mouse
+	{	mgl_wnd_toggle_zoom(gr);	}
+	inline void ToggleRotate()	///< Switch on/off rotation by mouse
+	{	mgl_wnd_toggle_rotate(gr);	}
+	inline void ToggleNo()		///< Switch off all zooming and rotation
+	{	mgl_wnd_toggle_no(gr);	}
+	inline void Update()		///< Update picture by calling user drawing function
+	{	mgl_wnd_update(gr);	}
+	inline void ReLoad()		///< Reload user data and update picture
+	{	mgl_wnd_reload(gr);	}
+	inline void Adjust()		///< Adjust size of bitmap to window size
+	{	mgl_wnd_adjust(gr);	}
+	inline void NextFrame()		///< Show next frame (if one)
+	{	mgl_wnd_next_frame(gr);	}
+	inline void PrevFrame()		///< Show previous frame (if one)
+	{	mgl_wnd_prev_frame(gr);	}
+	inline void Animation()		///< Run slideshow (animation) of frames
+	{	mgl_wnd_animation(gr);	}
+	inline void SetClickFunc(void (*func)(void *p))	///< Callback function for mouse click
+	{	mgl_set_click_func(gr,func);	}
+	/// Set callback functions for drawing and data reloading
+	inline void SetDrawFunc(int (*draw)(mglBase *gr, void *p), void *par=NULL, void (*reload)(void *p)=NULL)
+	{	mgl_wnd_set_func(gr,draw,par,reload);	}
+	inline void SetDrawFunc(int (*draw)(mglGraph *gr))
+	{	mgl_wnd_set_func(gr,draw?mgl_draw_graph:0,(void*)draw,0);	}
+	inline void SetDrawFunc(mglDraw *draw)
+	{	mgl_wnd_set_func(gr,draw?mgl_draw_class:0,draw,mgl_reload_class);
+#if MGL_HAVE_PTHR_WIDGET
+		mgl_wnd_set_mutex(gr, &(draw->mutex));
+#endif
+		mgl_set_click_func(gr, mgl_click_class);	}
+#if MGL_HAVE_PTHR_WIDGET
+	/// Mutex for lock/unlock by widget
+	inline void SetMutex(pthread_mutex_t *mutex)
+	{	mgl_wnd_set_mutex(gr, mutex);	}
+#endif
+
+	inline void SetDelay(double dt)	///< Set delay for animation in seconds
+	{	mgl_wnd_set_delay(gr, dt);	}
+	inline double GetDelay()		///< Get delay for animation in seconds
+	{	return mgl_wnd_get_delay(gr);	}
+	inline void Setup(bool clf_upd=true, bool showpos=false)
+	{	mgl_setup_window(gr, clf_upd, showpos);	}
+	inline mglPoint LastMousePos()		///< Last mouse position
+	{	mreal x,y,z;	mgl_get_last_mouse_pos(gr,&x,&y,&z);	return mglPoint(x,y,z);	}
+};
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/mgl2/wx.h b/include/mgl2/wx.h
new file mode 100644
index 0000000..6e1d051
--- /dev/null
+++ b/include/mgl2/wx.h
@@ -0,0 +1,138 @@
+/***************************************************************************
+ * wx.h.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifndef MGL_WX_H
+#define MGL_WX_H
+//-----------------------------------------------------------------------------
+#include <mgl2/wnd.h>
+#include <wx/window.h>
+#include <wx/image.h>
+#include <wx/timer.h>
+#include <wx/bitmap.h>
+class mglCanvas;
+//-----------------------------------------------------------------------------
+/// Convert MathGL image to wxBitmap
+wxBitmap MGL_EXPORT ConvertFromGraph(HMGL gr);
+//-----------------------------------------------------------------------------
+/// Class is Wx widget which display MathGL graphics
+class MGL_EXPORT wxMathGL : public wxWindow
+{
+public:
+	wxString appName;	///< Application name for message boxes
+	bool AutoResize; 	///< Allow auto resizing (default is false)
+
+	wxMathGL(wxWindow *parent, wxWindowID id=-1, const wxPoint& pos=wxDefaultPosition, const wxSize& size=wxDefaultSize, long style=0, const wxString& name=wxPanelNameStr);
+	virtual ~wxMathGL();
+	double GetRatio();
+	void SetPopup(wxMenu *p)	{	popup = p;	};	///< Set popup menu pointer
+	void SetSize(int w, int h);		///< Set window/picture sizes
+	void SetGraph(HMGL gr);	///< Set grapher object
+	inline void SetGraph(mglGraph *GR)
+	{	SetGraph(GR->Self());	}
+	inline HMGL GetGraph()	{	return (HMGL)gr;	}
+
+	/// Set drawing functions and its parameter
+	inline void SetDraw(int (*func)(mglBase *gr, void *par), void *par=0)
+	{	draw_func = func;	draw_par = par;	}
+	inline void SetDraw(mglDraw *dr)
+	{	draw_cl = dr;	}
+	inline void SetDraw(int (*draw)(mglGraph *gr))
+	{	SetDraw(draw?mgl_draw_graph:0,(void*)draw);	}
+	inline void ZoomRegion(mreal xx1,mreal xx2,mreal yy1, mreal yy2)
+	{	x1=xx1;	y1=yy1;	x2=xx2;	y2=yy2;	}
+
+	int GetPer() 	{return per;};		///< Get perspective value
+	int GetPhi() 	{return phi;};		///< Get Phi-angle value
+	int GetTet() 	{return tet;};		///< Get Theta-angle value
+	bool GetAlpha()	{return alpha;};	///< Get transparency state
+	bool GetLight()	{return light;};	///< Get lightning state
+	bool GetZoom()	{return zoom;};		///< Get mouse zooming state
+	bool GetRotate()	{return rotate;};	///< Get mouse rotation state
+
+	void Repaint();
+	void Update();			///< Update picture
+	void Copy(); 			///< copy graphics to clipboard
+	void Print();			///< Print plot
+//	void Stop();			///< Stop execution
+	void SetPer(int p);		///< Set perspective value
+	void SetPhi(int p);		///< Set Phi-angle value
+	void SetTet(int t);		///< Set Theta-angle value
+	void SetAlpha(bool a);	///< Switch on/off transparency
+	void SetLight(bool l);	///< Switch on/off lightning
+	void SetZoom(bool z);	///< Switch on/off mouse zooming
+	void SetRotate(bool r);	///< Switch on/off mouse rotation
+	void ZoomIn();			///< Zoom in graphics
+	void ZoomOut();			///< Zoom out graphics
+	void Restore();			///< Restore zoom and rotation to default values
+//	void Reload();			///< Reload data and execute script
+	void ShiftLeft();		///< Shift graphics to left direction
+	void ShiftRight();		///< Shift graphics to right direction
+	void ShiftUp();			///< Shift graphics to up direction
+	void ShiftDown();		///< Shift graphics to down direction
+	void ExportPNG(wxString fname=L"");	///< export to PNG file
+	void ExportPNGs(wxString fname=L"");	///< export to PNG file (no transparency)
+	void ExportJPG(wxString fname=L"");	///< export to JPEG file
+	void ExportBPS(wxString fname=L"");	///< export to bitmap EPS file
+	void ExportEPS(wxString fname=L"");	///< export to vector EPS file
+	void ExportSVG(wxString fname=L"");	///< export to SVG file
+
+	void Adjust();		///< Adjust plot size to fill entire window
+	void NextSlide();	///< Show next slide
+	void PrevSlide();	///< Show previous slide
+	void Animation(bool st=true);	///< Start animation
+
+	void About();		///< Show about information
+
+protected:
+	void OnPaint(wxPaintEvent& event);
+	void OnSize(wxSizeEvent& event);
+	void OnNextSlide(wxTimerEvent& evt);	///< Show next slide
+	void OnMouseLeftDown(wxMouseEvent &ev);
+	void OnMouseDown(wxMouseEvent &ev);
+	void OnMouseLeftUp(wxMouseEvent &ev);
+	void OnMouseRightUp(wxMouseEvent &ev);
+	void OnMouseMove(wxMouseEvent &ev);
+//	void MousePressEvent(QMouseEvent *);
+//	void MouseReleaseEvent(QMouseEvent *);
+//	void MouseMoveEvent(QMouseEvent *);
+
+	mglCanvas *gr;		///< pointer to grapher
+	void *draw_par;		///< Parameters for drawing function mglCanvasWnd::DrawFunc.
+	/// Drawing function for window procedure. It should return the number of frames.
+	int (*draw_func)(mglBase *gr, void *par);
+	mglDraw *draw_cl;
+
+	wxString MousePos;	///< Last mouse position
+	wxBitmap pic;		///< Pixmap for drawing (changed by update)
+	double tet, phi;	///< Rotation angles
+	double per;			///< Value of perspective ( must be in [0,1) )
+	bool alpha;			///< Transparency state
+	bool light;			///< Lightning state
+	bool zoom;			///< Mouse zoom state
+	bool rotate;		///< Mouse rotation state
+	mreal x1,x2,y1,y2;	///< Zoom in region
+	bool showMessage;	///< Flag for showing messages (enabled by each execute())
+	wxMenu *popup;		///< Pointer to pop-up menu
+	wxTimer *timer;		///< Timer for animation
+	DECLARE_EVENT_TABLE()
+private:
+	int x0, y0, xe, ye;		///< Temporary variables for mouse
+};
+//-----------------------------------------------------------------------------
+#endif
diff --git a/include/xpm/alpha.xpm b/include/xpm/alpha.xpm
new file mode 100644
index 0000000..102c0e1
--- /dev/null
+++ b/include/xpm/alpha.xpm
@@ -0,0 +1,126 @@
+/* XPM */
+static const char * alpha_xpm[] = {
+"16 16 107 2",
+"  	c None",
+". 	c #395155",
+"+ 	c #3A5155",
+"@ 	c #384F54",
+"# 	c #4C6A71",
+"$ 	c #68929C",
+"% 	c #B8FFFF",
+"& 	c #B1F9FF",
+"* 	c #B7FFFF",
+"= 	c #6B939C",
+"- 	c #113F4A",
+"; 	c #7CADB9",
+"> 	c #B4FCFF",
+", 	c #84BAC8",
+"' 	c #51585B",
+") 	c #78888C",
+"! 	c #79898D",
+"~ 	c #4D4D4D",
+"{ 	c #17B0D6",
+"] 	c #2CE0FF",
+"^ 	c #1D99B8",
+"/ 	c #1F282B",
+"( 	c #A1E2F3",
+"_ 	c #ABF0FF",
+": 	c #ACF2FF",
+"< 	c #658187",
+"[ 	c #E1FFFF",
+"} 	c #D7F8FF",
+"| 	c #D7F9FF",
+"1 	c #D7F7FF",
+"2 	c #428494",
+"3 	c #28D6FF",
+"4 	c #2AD6FF",
+"5 	c #26C3EA",
+"6 	c #1A88A2",
+"7 	c #346974",
+"8 	c #7BB8C6",
+"9 	c #9FDEEE",
+"0 	c #97D4E3",
+"a 	c #C2E2E9",
+"b 	c #D6F8FF",
+"c 	c #C5E6ED",
+"d 	c #2DB7DA",
+"e 	c #2AD1FB",
+"f 	c #23BFE6",
+"g 	c #0B6A81",
+"h 	c #42B0CC",
+"i 	c #4DB0C8",
+"j 	c #3A575C",
+"k 	c #7B878A",
+"l 	c #7D8A8E",
+"m 	c #7D8A8D",
+"n 	c #3B4A4E",
+"o 	c #0586A5",
+"p 	c #00BEED",
+"q 	c #005A70",
+"r 	c #317F93",
+"s 	c #56DFFF",
+"t 	c #47AEC7",
+"u 	c #7ADDF6",
+"v 	c #81ECFF",
+"w 	c #84F0FF",
+"x 	c #2F7E90",
+"y 	c #00DBFF",
+"z 	c #0094B9",
+"A 	c #3FA4BC",
+"B 	c #4CC5E4",
+"C 	c #72D1E7",
+"D 	c #7FE4FE",
+"E 	c #80E5FF",
+"F 	c #78D1E8",
+"G 	c #0EABD1",
+"H 	c #00BBEA",
+"I 	c #51D4F4",
+"J 	c #3A7888",
+"K 	c #85EEFF",
+"L 	c #60C0D8",
+"M 	c #00B7E6",
+"N 	c #0096BB",
+"O 	c #215764",
+"P 	c #3FA7C0",
+"Q 	c #70C6DC",
+"R 	c #83ECFF",
+"S 	c #378599",
+"T 	c #00B1DE",
+"U 	c #4AC5E4",
+"V 	c #447B89",
+"W 	c #82E8FF",
+"X 	c #84E4FD",
+"Y 	c #007696",
+"Z 	c #00556A",
+"` 	c #0A1A1E",
+" .	c #4FC5E2",
+"..	c #75D1E8",
+"+.	c #81E7FF",
+"@.	c #598B98",
+"#.	c #00B1DF",
+"$.	c #235C69",
+"%.	c #6BC4DA",
+"&.	c #82E6FF",
+"*.	c #148099",
+"=.	c #2C5B65",
+"-.	c #74D6F0",
+";.	c #074F61",
+">.	c #13353F",
+",.	c #67B8C9",
+"'.	c #0E191C",
+"            . + + @             ",
+"        # $ % & & * = -         ",
+"      ; > , ' ) ! ~ { ] ^       ",
+"  / ( _ : < [ } | 1 2 3 4 5 6   ",
+"  7 8 9 0 a b } } b c d e f g   ",
+"    h i j k l l l l m n o p q   ",
+"    r s t u v v v v w x y z     ",
+"      A B C D E E E F G H       ",
+"        I J K D E E L M N       ",
+"        O P Q E E R S T         ",
+"          U V W E X Y Z         ",
+"          `  ...+. at .#.          ",
+"            $.%.&.*.            ",
+"              =.-.;.            ",
+"              >.,.              ",
+"                '.              "};
diff --git a/include/xpm/arc.xpm b/include/xpm/arc.xpm
new file mode 100644
index 0000000..28f80a1
--- /dev/null
+++ b/include/xpm/arc.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * arc_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"     ......     ",
+"   ..      ..   ",
+"  .          .  ",
+"              . ",
+"              . ",
+"               .",
+"               .",
+"               .",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/arrow_a.xpm b/include/xpm/arrow_a.xpm
new file mode 100644
index 0000000..457c0aa
--- /dev/null
+++ b/include/xpm/arrow_a.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * arrow_a_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"         ...    ",
+"       ....     ",
+"     .....      ",
+"   ......       ",
+" ...............",
+"   ......       ",
+"     .....      ",
+"       ....     ",
+"         ...    ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/arrow_d.xpm b/include/xpm/arrow_d.xpm
new file mode 100644
index 0000000..834f703
--- /dev/null
+++ b/include/xpm/arrow_d.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * arrow_d_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"     .          ",
+"    ...         ",
+"   .....        ",
+"  .......       ",
+" ...............",
+"  .......       ",
+"   .....        ",
+"    ...         ",
+"     .          ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/arrow_i.xpm b/include/xpm/arrow_i.xpm
new file mode 100644
index 0000000..a8c617e
--- /dev/null
+++ b/include/xpm/arrow_i.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * arrow_i_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+" ..             ",
+" ..             ",
+" ..             ",
+" ..             ",
+" ..             ",
+" ...............",
+" ..             ",
+" ..             ",
+" ..             ",
+" ..             ",
+" ..             ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/arrow_k.xpm b/include/xpm/arrow_k.xpm
new file mode 100644
index 0000000..840d325
--- /dev/null
+++ b/include/xpm/arrow_k.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * arrow_k_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+" ..             ",
+" ..      ...    ",
+" ..    ....     ",
+" ..  .....      ",
+" ........       ",
+" ...............",
+" ........       ",
+" ..  .....      ",
+" ..    ....     ",
+" ..      ...    ",
+" ..             ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/arrow_n.xpm b/include/xpm/arrow_n.xpm
new file mode 100644
index 0000000..305238b
--- /dev/null
+++ b/include/xpm/arrow_n.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * arrow_n_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"  ..............",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/arrow_o.xpm b/include/xpm/arrow_o.xpm
new file mode 100644
index 0000000..6f4b583
--- /dev/null
+++ b/include/xpm/arrow_o.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * arrow_o_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"    ....        ",
+"   ......       ",
+"  ........      ",
+"  ........      ",
+"  ..............",
+"  ........      ",
+"  ........      ",
+"  .......       ",
+"    ....        ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/arrow_s.xpm b/include/xpm/arrow_s.xpm
new file mode 100644
index 0000000..ddeeb7f
--- /dev/null
+++ b/include/xpm/arrow_s.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * arrow_s_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"  ........      ",
+"  ........      ",
+"  ........      ",
+"  ........      ",
+"  ..............",
+"  ........      ",
+"  ........      ",
+"  ........      ",
+"  ........      ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/arrow_t.xpm b/include/xpm/arrow_t.xpm
new file mode 100644
index 0000000..71ff9dc
--- /dev/null
+++ b/include/xpm/arrow_t.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * arrow_t_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"         ..     ",
+"       ....     ",
+"     ......     ",
+"   ........     ",
+" ...............",
+"   ........     ",
+"     ......     ",
+"       ....     ",
+"         ..     ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/arrow_v.xpm b/include/xpm/arrow_v.xpm
new file mode 100644
index 0000000..038a3e5
--- /dev/null
+++ b/include/xpm/arrow_v.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * arrow_v_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"  ...           ",
+"   ....         ",
+"    .....       ",
+"     ......     ",
+"     ...........",
+"     ......     ",
+"    .....       ",
+"   ....         ",
+"  ...           ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/axis.xpm b/include/xpm/axis.xpm
new file mode 100644
index 0000000..65014f1
--- /dev/null
+++ b/include/xpm/axis.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * axis_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+" ..             ",
+"  .             ",
+"  .             ",
+" ..             ",
+"  .             ",
+"  .             ",
+" ..             ",
+"  .             ",
+"  .             ",
+" ..             ",
+"  .             ",
+"  .             ",
+" .............. ",
+"  .   .   .   . ",
+"                "};
diff --git a/include/xpm/axis_sh.xpm b/include/xpm/axis_sh.xpm
new file mode 100644
index 0000000..d09869f
--- /dev/null
+++ b/include/xpm/axis_sh.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * axis_sh_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #000000",
+"+	c #FF0000",
+"                ",
+"  .             ",
+". .      +      ",
+"  .     +++     ",
+"  .      +      ",
+". .   +  +  +   ",
+"  .  +++++++++  ",
+"  .   +  +  +   ",
+". .      +      ",
+"  .     +++     ",
+"  .      +      ",
+". .             ",
+"  .             ",
+"  ............. ",
+".               ",
+"  .  .  .  .  . "};
diff --git a/include/xpm/barrow_a.xpm b/include/xpm/barrow_a.xpm
new file mode 100644
index 0000000..8545b8f
--- /dev/null
+++ b/include/xpm/barrow_a.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+const char * barrow_a_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"    ...         ",
+"     ....       ",
+"      .....     ",
+"       ......   ",
+"............... ",
+"       ......   ",
+"      .....     ",
+"     ....       ",
+"    ...         ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/barrow_d.xpm b/include/xpm/barrow_d.xpm
new file mode 100644
index 0000000..fe133de
--- /dev/null
+++ b/include/xpm/barrow_d.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+const char * barrow_d_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"          .     ",
+"         ...    ",
+"        .....   ",
+"       .......  ",
+"............... ",
+"       .......  ",
+"        .....   ",
+"         ...    ",
+"          .     ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/barrow_i.xpm b/include/xpm/barrow_i.xpm
new file mode 100644
index 0000000..54e91ad
--- /dev/null
+++ b/include/xpm/barrow_i.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+const char * barrow_i_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"             .. ",
+"             .. ",
+"             .. ",
+"             .. ",
+"             .. ",
+"............... ",
+"             .. ",
+"             .. ",
+"             .. ",
+"             .. ",
+"             .. ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/barrow_k.xpm b/include/xpm/barrow_k.xpm
new file mode 100644
index 0000000..be962b1
--- /dev/null
+++ b/include/xpm/barrow_k.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+const char * barrow_k_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"             .. ",
+"    ...      .. ",
+"     ....    .. ",
+"      .....  .. ",
+"       ........ ",
+"............... ",
+"       ........ ",
+"      .....  .. ",
+"     ....    .. ",
+"    ...      .. ",
+"             .. ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/barrow_n.xpm b/include/xpm/barrow_n.xpm
new file mode 100644
index 0000000..7d2b54c
--- /dev/null
+++ b/include/xpm/barrow_n.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+const char * barrow_n_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"..............  ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/barrow_o.xpm b/include/xpm/barrow_o.xpm
new file mode 100644
index 0000000..a0ea264
--- /dev/null
+++ b/include/xpm/barrow_o.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+const char * barrow_o_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"        ....    ",
+"       ......   ",
+"      ........  ",
+"      ........  ",
+"..............  ",
+"      ........  ",
+"      ........  ",
+"       .......  ",
+"        ....    ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/barrow_s.xpm b/include/xpm/barrow_s.xpm
new file mode 100644
index 0000000..f19c4d8
--- /dev/null
+++ b/include/xpm/barrow_s.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+const char * barrow_s_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"      ........  ",
+"      ........  ",
+"      ........  ",
+"      ........  ",
+"..............  ",
+"      ........  ",
+"      ........  ",
+"      ........  ",
+"      ........  ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/barrow_t.xpm b/include/xpm/barrow_t.xpm
new file mode 100644
index 0000000..06e23d5
--- /dev/null
+++ b/include/xpm/barrow_t.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+const char * barrow_t_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"     ..         ",
+"     ....       ",
+"     ......     ",
+"     ........   ",
+"............... ",
+"     ........   ",
+"     ......     ",
+"     ....       ",
+"     ..         ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/barrow_v.xpm b/include/xpm/barrow_v.xpm
new file mode 100644
index 0000000..b31d4d2
--- /dev/null
+++ b/include/xpm/barrow_v.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+const char * barrow_v_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"           ...  ",
+"         ....   ",
+"       .....    ",
+"     ......     ",
+"...........     ",
+"     ......     ",
+"       .....    ",
+"         ....   ",
+"           ...  ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/box.xpm b/include/xpm/box.xpm
new file mode 100644
index 0000000..23260d1
--- /dev/null
+++ b/include/xpm/box.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * box_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #000000",
+"+	c #666666",
+"                ",
+"      ......... ",
+"     .+      .. ",
+"    . +     . . ",
+"   .  +    .  . ",
+"  .   +   .   . ",
+" .........    . ",
+" .    +  .    . ",
+" .    +  .    . ",
+" .    +++.++++. ",
+" .   +   .   .  ",
+" .  +    .  .   ",
+" . +     . .    ",
+" .+      ..     ",
+" .........      ",
+"                "};
diff --git a/include/xpm/comment.xpm b/include/xpm/comment.xpm
new file mode 100644
index 0000000..1aebddd
--- /dev/null
+++ b/include/xpm/comment.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * comment_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #009f00",
+"                ",
+"                ",
+"                ",
+"     .    .     ",
+"     .    .     ",
+"     .    .     ",
+"  ............  ",
+"     .    .     ",
+"     .    .     ",
+"     .    .     ",
+"     .    .     ",
+"  ............  ",
+"     .    .     ",
+"     .    .     ",
+"     .    .     ",
+"                "};
diff --git a/include/xpm/cons.xpm b/include/xpm/cons.xpm
new file mode 100644
index 0000000..b22b0f4
--- /dev/null
+++ b/include/xpm/cons.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char * cons_xpm[] = {
+"16 16 4 1",
+" 	c None",
+".	c #000000",
+"+	c #0000FF",
+"@	c #FF0000",
+"                ",
+" .............. ",
+" .            . ",
+" . . . . . . .. ",
+" .            . ",
+" . . . . . . .. ",
+" .............. ",
+"                ",
+"  +++++++++++++ ",
+"    +++++++++   ",
+"      +++++     ",
+"        +       ",
+" @@@@@@@@@@@@@@ ",
+" @ @ @ @ @ @ @@ ",
+" @@@@@@@@@@@@@@ ",
+"                "};
diff --git a/include/xpm/copy.xpm b/include/xpm/copy.xpm
new file mode 100644
index 0000000..bfaecb1
--- /dev/null
+++ b/include/xpm/copy.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char * copy_xpm[] = {
+"16 16 4 1",
+" 	c None",
+".	c #000000",
+"+	c #FFFFFF",
+"@	c #808080",
+"                ",
+"                ",
+"  ........      ",
+"  .++++++.@     ",
+"  .+@@@@+.@     ",
+"  .++........   ",
+"  .+ at .++++++.@  ",
+"  .++.+....+.@  ",
+"  .+ at .++++++.@  ",
+"  .++.+....+.@  ",
+"  ....++++++.@  ",
+"    @.+....+.@  ",
+"     .++++++.@  ",
+"     ........@  ",
+"      @@@@@@@@  ",
+"                "};
diff --git a/include/xpm/crop.xpm b/include/xpm/crop.xpm
new file mode 100644
index 0000000..e18a730
--- /dev/null
+++ b/include/xpm/crop.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * crop_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"     .          ",
+"                ",
+"     .          ",
+"                ",
+" . . ......     ",
+"     .    .     ",
+"     .    .     ",
+"     .    .     ",
+"     .    .     ",
+"     ...... . . ",
+"                ",
+"          .     ",
+"                ",
+"          .     ",
+"                "};
diff --git a/include/xpm/curve.xpm b/include/xpm/curve.xpm
new file mode 100644
index 0000000..88e37e3
--- /dev/null
+++ b/include/xpm/curve.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * curve_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"               .",
+"               .",
+"              . ",
+"              . ",
+"             .  ",
+"            .   ",
+"          ..    ",
+"        ..      ",
+"      ..        ",
+"    ..          ",
+"   .            ",
+"  .             ",
+" .              ",
+" .              ",
+".               ",
+".               "};
diff --git a/include/xpm/dash_d.xpm b/include/xpm/dash_d.xpm
new file mode 100644
index 0000000..6892ce6
--- /dev/null
+++ b/include/xpm/dash_d.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * dash_d_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+".   .   .   .   ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/dash_e.xpm b/include/xpm/dash_e.xpm
new file mode 100644
index 0000000..13eaf63
--- /dev/null
+++ b/include/xpm/dash_e.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * dash_e_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+". . . . . . . . ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/dash_i.xpm b/include/xpm/dash_i.xpm
new file mode 100644
index 0000000..2ad1f1c
--- /dev/null
+++ b/include/xpm/dash_i.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * dash_i_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+".. . .. . .. . .",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/dash_j.xpm b/include/xpm/dash_j.xpm
new file mode 100644
index 0000000..70a9cc4
--- /dev/null
+++ b/include/xpm/dash_j.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * dash_j_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"....  .  ....  .",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/dash_l.xpm b/include/xpm/dash_l.xpm
new file mode 100644
index 0000000..4346c08
--- /dev/null
+++ b/include/xpm/dash_l.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * dash_l_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"....    ....    ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/dash_m.xpm b/include/xpm/dash_m.xpm
new file mode 100644
index 0000000..7cd2b39
--- /dev/null
+++ b/include/xpm/dash_m.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * dash_m_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"..  ..  ..  ..  ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/dash_s.xpm b/include/xpm/dash_s.xpm
new file mode 100644
index 0000000..4edb6c5
--- /dev/null
+++ b/include/xpm/dash_s.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * dash_s_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"................",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/delete.xpm b/include/xpm/delete.xpm
new file mode 100644
index 0000000..a191ea2
--- /dev/null
+++ b/include/xpm/delete.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * delete_xpm[] = {
+"16 16 2 1",
+" 	c none",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"  ...      ...  ",
+"   ...    ...   ",
+"    ...  ...    ",
+"     ......     ",
+"      ....      ",
+"      ....      ",
+"     ......     ",
+"    ...  ...    ",
+"   ...    ...   ",
+"  ...      ...  ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/diff.xpm b/include/xpm/diff.xpm
new file mode 100644
index 0000000..b90448a
--- /dev/null
+++ b/include/xpm/diff.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * diff_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"   ..           ",
+"  .  .   .      ",
+"     .  .       ",
+"  ....  .       ",
+" .   . .  ..    ",
+" .  .  . .  .   ",
+"  ..  .     .   ",
+"      .  ....   ",
+"     .  .   .   ",
+"     .  .  . . .",
+"    .    ..   . ",
+"             . .",
+"                ",
+"                "};
diff --git a/include/xpm/diff2.xpm b/include/xpm/diff2.xpm
new file mode 100644
index 0000000..7a2d7eb
--- /dev/null
+++ b/include/xpm/diff2.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * diff2_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #000000",
+"+	c #7F7F7F",
+"                ",
+"                ",
+"                ",
+"                ",
+"       .        ",
+"       ..       ",
+"      .+..      ",
+"     +. ..+     ",
+"     .   ..     ",
+"    .+   +..    ",
+"   +.     ..+   ",
+"   .       ..   ",
+"  .+       +..  ",
+"  ............  ",
+"                ",
+"                "};
diff --git a/include/xpm/down_1.xpm b/include/xpm/down_1.xpm
new file mode 100644
index 0000000..e8d3b52
--- /dev/null
+++ b/include/xpm/down_1.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * down_1_xpm[] = {
+"16 16 3 1",
+".	c None",
+"+	c #7F0000",
+"@	c #FF0000",
+"................",
+"................",
+".....+++++++....",
+".....+@@@@@+....",
+".....+@@@@@+....",
+".....+@@@@@+....",
+".....+@@@@@+....",
+".....+@@@@@+....",
+"..++++@@@@@++++.",
+"...+@@@@@@@@@+..",
+"....+@@@@@@@+...",
+".....+@@@@@+....",
+"......+@@@+.....",
+".......+ at +......",
+"........+.......",
+"................"};
diff --git a/include/xpm/fileprint.xpm b/include/xpm/fileprint.xpm
new file mode 100644
index 0000000..6ada912
--- /dev/null
+++ b/include/xpm/fileprint.xpm
@@ -0,0 +1,24 @@
+/* XPM */
+static const char *fileprint[] = {
+"    16    14        6            1",
+". c #000000",
+"# c #848284",
+"a c #c6c3c6",
+"b c #ffff00",
+"c c #ffffff",
+"d c None",
+"ddddd.........dd",
+"dddd.cccccccc.dd",
+"dddd.c.....c.ddd",
+"ddd.cccccccc.ddd",
+"ddd.c.....c....d",
+"dd.cccccccc.a.a.",
+"d..........a.a..",
+".aaaaaaaaaa.a.a.",
+".............aa.",
+".aaaaaa###aa.a.d",
+".aaaaaabbbaa...d",
+".............a.d",
+"d.aaaaaaaaa.a.dd",
+"dd...........ddd"
+};
diff --git a/include/xpm/first.xpm b/include/xpm/first.xpm
new file mode 100644
index 0000000..0265075
--- /dev/null
+++ b/include/xpm/first.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * first_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #0000FF",
+"                ",
+"                ",
+"                ",
+"  ..         .  ",
+"  ..       ...  ",
+"  ..     .....  ",
+"  ..   .......  ",
+"  .. .........  ",
+"  ............  ",
+"  ............  ",
+"  .. .........  ",
+"  ..   .......  ",
+"  ..     .....  ",
+"  ..       ...  ",
+"  ..         .  ",
+"                "};
diff --git a/include/xpm/folder.xpm b/include/xpm/folder.xpm
new file mode 100644
index 0000000..6473918
--- /dev/null
+++ b/include/xpm/folder.xpm
@@ -0,0 +1,130 @@
+/* XPM */
+static const char * folder_xpm[] = {
+"16 16 111 2",
+"  	c None",
+". 	c #7A7A7A",
+"+ 	c #797979",
+"@ 	c #787878",
+"# 	c #C9C9C9",
+"$ 	c #C7C7C7",
+"% 	c #C5C5C5",
+"& 	c #C4C4C4",
+"* 	c #B4B4B4",
+"= 	c #747474",
+"- 	c #737373",
+"; 	c #B0B0B0",
+"> 	c #ADADAD",
+", 	c #ABABAB",
+"' 	c #AAAAAA",
+") 	c #ACACAC",
+"! 	c #8D8D8D",
+"~ 	c #8C8C8C",
+"{ 	c #808080",
+"] 	c #6C6C6C",
+"^ 	c #6E6E6E",
+"/ 	c #C1C1C0",
+"( 	c #A7A7A7",
+"_ 	c #A5A5A5",
+": 	c #A4A4A4",
+"< 	c #B6B6B6",
+"[ 	c #B9B9B9",
+"} 	c #BBBBBB",
+"| 	c #A2A2A2",
+"1 	c #6A6A6A",
+"2 	c #BDBDBD",
+"3 	c #416DA6",
+"4 	c #3666A5",
+"5 	c #3566A4",
+"6 	c #3465A4",
+"7 	c #3768A6",
+"8 	c #656565",
+"9 	c #B7B7B7",
+"0 	c #3566A5",
+"a 	c #BED3EA",
+"b 	c #BFD4EA",
+"c 	c #BED4EA",
+"d 	c #BED3E9",
+"e 	c #B8CFE8",
+"f 	c #3465A5",
+"g 	c #5F5F5F",
+"h 	c #B3B3B3",
+"i 	c #C1D5EA",
+"j 	c #91B4DB",
+"k 	c #91B5DB",
+"l 	c #92B5DB",
+"m 	c #96B8DC",
+"n 	c #B7CFE7",
+"o 	c #3466A4",
+"p 	c #5B5B5B",
+"q 	c #AEAEAE",
+"r 	c #3667A5",
+"s 	c #C4D7EB",
+"t 	c #94B7DC",
+"u 	c #91B4DA",
+"v 	c #B6CDE6",
+"w 	c #565656",
+"x 	c #A9A9A9",
+"y 	c #3666A4",
+"z 	c #C6D8EC",
+"A 	c #99BADD",
+"B 	c #95B7DC",
+"C 	c #8EB2DA",
+"D 	c #8BB0D9",
+"E 	c #B8CFE7",
+"F 	c #515151",
+"G 	c #A5A5A4",
+"H 	c #3767A5",
+"I 	c #BED2E9",
+"J 	c #9BBADD",
+"K 	c #99B9DD",
+"L 	c #95B6DC",
+"M 	c #90B3DA",
+"N 	c #8EB2D9",
+"O 	c #89AED8",
+"P 	c #87ADD7",
+"Q 	c #8BB0D8",
+"R 	c #B1C9E5",
+"S 	c #4C4C4C",
+"T 	c #A1A1A1",
+"U 	c #3868A5",
+"V 	c #A9C4E2",
+"W 	c #81A8D5",
+"X 	c #7AA4D3",
+"Y 	c #7EA7D4",
+"Z 	c #9CBADD",
+"` 	c #484848",
+" .	c #9B9B9B",
+"..	c #3867A4",
+"+.	c #85ABD5",
+"@.	c #6E9CCE",
+"#.	c #6D9CCE",
+"$.	c #709ECF",
+"%.	c #84ABD5",
+"&.	c #494949",
+"*.	c #999999",
+"=.	c #3968A5",
+"-.	c #7EA6D3",
+";.	c #78A3D2",
+">.	c #79A4D3",
+",.	c #7AA5D1",
+"'.	c #788697",
+").	c #3A69A5",
+"!.	c #5083BA",
+"~.	c #4578B2",
+"{.	c #464D53",
+"                                ",
+". + + + + + +                   ",
+"@ # $ % & & * =                 ",
+"- % ; > , ' ) ! ! ~ ~ ~ { ]     ",
+"^ / ) ' ( _ : : ) < [ } | 1     ",
+"1 2 3 4 4 4 4 4 5 5 5 5 6 6 6 7 ",
+"8 9 0 a b b c c c d d d d d e f ",
+"g h 5 i j j k k l l l l l m n o ",
+"p q r s t t t t t t t t t u v 0 ",
+"w x y z A A A A A A A B C D E 0 ",
+"F G H I J K L l M N O P P Q R 0 ",
+"S T U V W X X X X X X X X Y Z 0 ",
+"`  ...+. at .#.#.#.#.#.#.#.#.$.%.0 ",
+"&.*.=.-.;.;.;.;.;.;.;.;.;.>.,.0 ",
+"` '.).!.!.!.!.!.!.!.!.!.!.!.~.4 ",
+"{.6 6 6 6 6 6 6 6 6 6 6 6 6 5   "};
diff --git a/include/xpm/func.xpm b/include/xpm/func.xpm
new file mode 100644
index 0000000..e62cfe7
--- /dev/null
+++ b/include/xpm/func.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * func_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"   .   .    .   ",
+"  .   .      .  ",
+"  .   .      .  ",
+" ... .  .  .  . ",
+"  .  .  .  .  . ",
+"  .  .   ..   . ",
+"  .  .   ..   . ",
+"  .  .  .  .  . ",
+"  .   . .  . .  ",
+"      .      .  ",
+"       .    .   ",
+"                ",
+"                "};
diff --git a/include/xpm/hist.xpm b/include/xpm/hist.xpm
new file mode 100644
index 0000000..5c7eb5c
--- /dev/null
+++ b/include/xpm/hist.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * hist_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #0000FF",
+"                ",
+"                ",
+"        ...     ",
+"        ...     ",
+"        ...     ",
+"    ... ...     ",
+"    ... ...     ",
+"    ... ...     ",
+"    ... ...     ",
+"    ... ...     ",
+"    ... ... ... ",
+"    ... ... ... ",
+"... ... ... ... ",
+"... ... ... ... ",
+"... ... ... ... ",
+"                "};
diff --git a/include/xpm/insert.xpm b/include/xpm/insert.xpm
new file mode 100644
index 0000000..e0143f1
--- /dev/null
+++ b/include/xpm/insert.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char * insert_xpm[] = {
+"16 16 4 1",
+" 	c None",
+".	c #0000FF",
+"#	c #000000",
+"w	c #FFFFFF",
+"                ",
+"                ",
+".  ############ ",
+".. #wwwwwwwwww# ",
+"...#w########w# ",
+"....wwwwwwwwww# ",
+".....########w# ",
+"......wwwwwwww# ",
+".......######w# ",
+"........wwwwww# ",
+".......######w# ",
+"......wwwwwwww# ",
+".....########w# ",
+"....wwwwwwwwww# ",
+"...############ ",
+"..              "};
diff --git a/include/xpm/integr.xpm b/include/xpm/integr.xpm
new file mode 100644
index 0000000..ddccb22
--- /dev/null
+++ b/include/xpm/integr.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * integr_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #000000",
+"+	c #808080",
+"                ",
+"                ",
+"                ",
+"     .          ",
+"    .           ",
+"    .    .      ",
+"    .    .      ",
+"    .    .      ",
+"    .  ... . .  ",
+"    . .  .  .   ",
+"    . .  .  .   ",
+"    .  ... . .  ",
+"   .     +      ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/last.xpm b/include/xpm/last.xpm
new file mode 100644
index 0000000..d774d36
--- /dev/null
+++ b/include/xpm/last.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * last_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #0000FF",
+"                ",
+"                ",
+"                ",
+"  .         ..  ",
+"  ...       ..  ",
+"  .....     ..  ",
+"  .......   ..  ",
+"  ......... ..  ",
+"  ............  ",
+"  ............  ",
+"  ......... ..  ",
+"  .......   ..  ",
+"  .....     ..  ",
+"  ...       ..  ",
+"  .         ..  ",
+"                "};
diff --git a/include/xpm/left_1.xpm b/include/xpm/left_1.xpm
new file mode 100644
index 0000000..679c3ff
--- /dev/null
+++ b/include/xpm/left_1.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * left_1_xpm[] = {
+"16 16 3 1",
+".	c None",
+"+	c #7F0000",
+"@	c #FF0000",
+"................",
+"................",
+".......+........",
+"......++........",
+".....+ at +........",
+"....+@@+++++++..",
+"...+@@@@@@@@@+..",
+"..+@@@@@@@@@@+..",
+".+@@@@@@@@@@@+..",
+"..+@@@@@@@@@@+..",
+"...+@@@@@@@@@+..",
+"....+@@+++++++..",
+".....+ at +........",
+"......++........",
+".......+........",
+"................"};
diff --git a/include/xpm/light.xpm b/include/xpm/light.xpm
new file mode 100644
index 0000000..e813c61
--- /dev/null
+++ b/include/xpm/light.xpm
@@ -0,0 +1,42 @@
+/* XPM */
+static const char * light_xpm[] = {
+"16 16 23 1",
+" 	c None",
+"!	c #000000",
+"#	c #808080",
+"$	c #808000",
+"%	c #606040",
+"&	c #C0C0C0",
+"'	c #808040",
+"(	c #FFFF00",
+")	c #A0A000",
+"*	c #202000",
+"+	c #404000",
+",	c #C0C000",
+"-	c #E0E000",
+".	c #408040",
+"0	c #008080",
+"1	c #408080",
+"2	c #FFFFC0",
+"3	c #C0C080",
+"4	c #FFFFFF",
+"5	c #FFFF80",
+"6	c #FFFF40",
+"7	c #606000",
+"8	c #206040",
+"     #    #     ",
+"    #$%&&'$#    ",
+"    '()*+,-%    ",
+"    $.0000.+    ",
+" #'+01&223.0+'# ",
+"&$(.1455555..($#",
+" %)0&566((-$0)% ",
+" &*055((((-)0*& ",
+" &+056((((-)0+& ",
+" ',035(((-,70,' ",
+"&$-.8,---,,8.-$#",
+" #%*08$))780*%# ",
+"    $.0000.+    ",
+"    '()*+,-%    ",
+"    #$%&&'$#    ",
+"     #    #     "};
diff --git a/include/xpm/line.xpm b/include/xpm/line.xpm
new file mode 100644
index 0000000..aff1af3
--- /dev/null
+++ b/include/xpm/line.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * line_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"               .",
+"              . ",
+"             .  ",
+"            .   ",
+"           .    ",
+"          .     ",
+"         .      ",
+"        .       ",
+"       .        ",
+"      .         ",
+"     .          ",
+"    .           ",
+"   .            ",
+"  .             ",
+" .              ",
+".               "};
diff --git a/include/xpm/mark_.xpm b/include/xpm/mark_.xpm
new file mode 100644
index 0000000..b372f5a
--- /dev/null
+++ b/include/xpm/mark_.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark__xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"       ..       ",
+"       ..       ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/mark_a.xpm b/include/xpm/mark_a.xpm
new file mode 100644
index 0000000..29f34cb
--- /dev/null
+++ b/include/xpm/mark_a.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_a_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"    .       .   ",
+"     .     .    ",
+"      .   .     ",
+"      .   .     ",
+"       . .      ",
+"       ...      ",
+" .............. ",
+"       ...      ",
+"       . .      ",
+"      .   .     ",
+"      .   .     ",
+"     .     .    ",
+"    .       .   ",
+"                ",
+"                "};
diff --git a/include/xpm/mark_cf.xpm b/include/xpm/mark_cf.xpm
new file mode 100644
index 0000000..f743a31
--- /dev/null
+++ b/include/xpm/mark_cf.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_cf_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"     ......     ",
+"   ..      ..   ",
+"  .          .  ",
+" .            . ",
+" .            . ",
+".              .",
+".              .",
+".      ..      .",
+".      ..      .",
+".              .",
+".              .",
+" .            . ",
+" .            . ",
+"  .          .  ",
+"   ..      ..   ",
+"     ......     "};
diff --git a/include/xpm/mark_d.xpm b/include/xpm/mark_d.xpm
new file mode 100644
index 0000000..678d75e
--- /dev/null
+++ b/include/xpm/mark_d.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_d_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"       ..       ",
+"      .  .      ",
+"     .    .     ",
+"    .      .    ",
+"   .        .   ",
+"  .          .  ",
+" .            . ",
+".              .",
+".              .",
+" .            . ",
+"  .          .  ",
+"   .        .   ",
+"    .      .    ",
+"     .    .     ",
+"      .  .      ",
+"       ..       "};
diff --git a/include/xpm/mark_df.xpm b/include/xpm/mark_df.xpm
new file mode 100644
index 0000000..582d420
--- /dev/null
+++ b/include/xpm/mark_df.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_df_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"       ..       ",
+"      ....      ",
+"     ......     ",
+"    ........    ",
+"   ..........   ",
+"  ............  ",
+" .............. ",
+"................",
+"................",
+" .............. ",
+"  ............  ",
+"   ..........   ",
+"    ........    ",
+"     ......     ",
+"      ....      ",
+"       ..       "};
diff --git a/include/xpm/mark_l.xpm b/include/xpm/mark_l.xpm
new file mode 100644
index 0000000..9edd3e0
--- /dev/null
+++ b/include/xpm/mark_l.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_l_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"          ..    ",
+"        .. .    ",
+"       .   .    ",
+"     ..    .    ",
+"    .      .    ",
+"  ..       .    ",
+" .         .    ",
+".          .    ",
+".          .    ",
+" .         .    ",
+"  ..       .    ",
+"    .      .    ",
+"     ..    .    ",
+"       .   .    ",
+"        .. .    ",
+"          ..    "};
diff --git a/include/xpm/mark_lf.xpm b/include/xpm/mark_lf.xpm
new file mode 100644
index 0000000..2585eb4
--- /dev/null
+++ b/include/xpm/mark_lf.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_lf_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"          ..    ",
+"        ....    ",
+"       .....    ",
+"     .......    ",
+"    ........    ",
+"  ..........    ",
+" ...........    ",
+"............    ",
+"............    ",
+" ...........    ",
+"  ..........    ",
+"    ........    ",
+"     .......    ",
+"       .....    ",
+"        ....    ",
+"          ..    "};
diff --git a/include/xpm/mark_n.xpm b/include/xpm/mark_n.xpm
new file mode 100644
index 0000000..efb363e
--- /dev/null
+++ b/include/xpm/mark_n.xpm
@@ -0,0 +1,20 @@
+/* XPM */
+static const char * mark_n_xpm[] = {
+"16 16 1 1",
+" 	c None",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/mark_o.xpm b/include/xpm/mark_o.xpm
new file mode 100644
index 0000000..3154cdc
--- /dev/null
+++ b/include/xpm/mark_o.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_o_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"     ......     ",
+"   ..      ..   ",
+"  .          .  ",
+" .            . ",
+" .            . ",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+" .            . ",
+" .            . ",
+"  .          .  ",
+"   ..      ..   ",
+"     ......     "};
diff --git a/include/xpm/mark_of.xpm b/include/xpm/mark_of.xpm
new file mode 100644
index 0000000..3eeaf38
--- /dev/null
+++ b/include/xpm/mark_of.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_of_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"     ......     ",
+"   ..........   ",
+"  ............  ",
+" .............. ",
+" .............. ",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+" .............. ",
+" .............. ",
+"  ............  ",
+"   ..........   ",
+"     ......     "};
diff --git a/include/xpm/mark_p.xpm b/include/xpm/mark_p.xpm
new file mode 100644
index 0000000..3f40cfb
--- /dev/null
+++ b/include/xpm/mark_p.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_p_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       ",
+"................",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       "};
diff --git a/include/xpm/mark_pf.xpm b/include/xpm/mark_pf.xpm
new file mode 100644
index 0000000..ea9cdac
--- /dev/null
+++ b/include/xpm/mark_pf.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_pf_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"................",
+".       .      .",
+".       .      .",
+".       .      .",
+".       .      .",
+".       .      .",
+".       .      .",
+".       .      .",
+"................",
+".       .      .",
+".       .      .",
+".       .      .",
+".       .      .",
+".       .      .",
+".       .      .",
+"................"};
diff --git a/include/xpm/mark_r.xpm b/include/xpm/mark_r.xpm
new file mode 100644
index 0000000..8459014
--- /dev/null
+++ b/include/xpm/mark_r.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_r_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"    ..          ",
+"    . ..        ",
+"    .   .       ",
+"    .    ..     ",
+"    .      .    ",
+"    .       ..  ",
+"    .         . ",
+"    .          .",
+"    .          .",
+"    .         . ",
+"    .       ..  ",
+"    .      .    ",
+"    .    ..     ",
+"    .   .       ",
+"    . ..        ",
+"    ..          "};
diff --git a/include/xpm/mark_rf.xpm b/include/xpm/mark_rf.xpm
new file mode 100644
index 0000000..cedcd01
--- /dev/null
+++ b/include/xpm/mark_rf.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_rf_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"    ..          ",
+"    ....        ",
+"    .....       ",
+"    .......     ",
+"    ........    ",
+"    ..........  ",
+"    ........... ",
+"    ............",
+"    ............",
+"    ........... ",
+"    ..........  ",
+"    ........    ",
+"    .......     ",
+"    .....       ",
+"    ....        ",
+"    ..          "};
diff --git a/include/xpm/mark_s.xpm b/include/xpm/mark_s.xpm
new file mode 100644
index 0000000..1a4c012
--- /dev/null
+++ b/include/xpm/mark_s.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_s_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"................",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+"................"};
diff --git a/include/xpm/mark_sf.xpm b/include/xpm/mark_sf.xpm
new file mode 100644
index 0000000..5a89f1d
--- /dev/null
+++ b/include/xpm/mark_sf.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_sf_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................"};
diff --git a/include/xpm/mark_t.xpm b/include/xpm/mark_t.xpm
new file mode 100644
index 0000000..1e6b398
--- /dev/null
+++ b/include/xpm/mark_t.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_t_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"       ..       ",
+"      .  .      ",
+"     .    .     ",
+"     .    .     ",
+"    .      .    ",
+"   .        .   ",
+"   .        .   ",
+"  .          .  ",
+" .            . ",
+" .            . ",
+".              .",
+"................",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/mark_tf.xpm b/include/xpm/mark_tf.xpm
new file mode 100644
index 0000000..48f61c1
--- /dev/null
+++ b/include/xpm/mark_tf.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_tf_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"       ..       ",
+"      ....      ",
+"     ......     ",
+"     ......     ",
+"    ........    ",
+"   ..........   ",
+"   ..........   ",
+"  ............  ",
+" .............. ",
+" .............. ",
+"................",
+"................",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/mark_v.xpm b/include/xpm/mark_v.xpm
new file mode 100644
index 0000000..9f03771
--- /dev/null
+++ b/include/xpm/mark_v.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_v_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"................",
+".              .",
+" .            . ",
+" .            . ",
+"  .          .  ",
+"   .        .   ",
+"   .        .   ",
+"    .      .    ",
+"     .    .     ",
+"     .    .     ",
+"      .  .      ",
+"       ..       "};
diff --git a/include/xpm/mark_vf.xpm b/include/xpm/mark_vf.xpm
new file mode 100644
index 0000000..39d7e99
--- /dev/null
+++ b/include/xpm/mark_vf.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_vf_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"................",
+"................",
+" .............. ",
+" .............. ",
+"  ............  ",
+"   ..........   ",
+"   ..........   ",
+"    ........    ",
+"     ......     ",
+"     ......     ",
+"      ....      ",
+"       ..       "};
diff --git a/include/xpm/mark_x.xpm b/include/xpm/mark_x.xpm
new file mode 100644
index 0000000..8d7ee78
--- /dev/null
+++ b/include/xpm/mark_x.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_x_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+".              .",
+" .            . ",
+"  .          .  ",
+"   .        .   ",
+"    .      .    ",
+"     .    .     ",
+"      .  .      ",
+"       ..       ",
+"       ..       ",
+"      .  .      ",
+"     .    .     ",
+"    .      .    ",
+"   .        .   ",
+"  .          .  ",
+" .            . ",
+".              ."};
diff --git a/include/xpm/mark_y.xpm b/include/xpm/mark_y.xpm
new file mode 100644
index 0000000..b5135fd
--- /dev/null
+++ b/include/xpm/mark_y.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_y_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"   .         .  ",
+"    .       .   ",
+"     .     .    ",
+"      .   .     ",
+"       ...      ",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/mask_a.xpm b/include/xpm/mask_a.xpm
new file mode 100644
index 0000000..6949dd9
--- /dev/null
+++ b/include/xpm/mask_a.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_a_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"##............##",
+"##............##",
+"..##........##..",
+"..##........##..",
+"....##....##....",
+"....##....##....",
+"......####......",
+"......####......",
+"......####......",
+"......####......",
+"....##....##....",
+"....##....##....",
+"..##........##..",
+"..##........##..",
+"##............##",
+"##............##"};
diff --git a/include/xpm/mask_d.xpm b/include/xpm/mask_d.xpm
new file mode 100644
index 0000000..dc7f66d
--- /dev/null
+++ b/include/xpm/mask_d.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_d_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"........##......",
+"........##......",
+"......##..##....",
+"......##..##....",
+"....##......##..",
+"....##......##..",
+"......##..##....",
+"......##..##....",
+"........##......",
+"........##......",
+"................",
+"................",
+"................",
+"................"};
diff --git a/include/xpm/mask_d_.xpm b/include/xpm/mask_d_.xpm
new file mode 100644
index 0000000..d3eee46
--- /dev/null
+++ b/include/xpm/mask_d_.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_D_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"........##......",
+"........##......",
+"......######....",
+"......######....",
+"....##########..",
+"....##########..",
+"......######....",
+"......######....",
+"........##......",
+"........##......",
+"................",
+"................",
+"................",
+"................"};
diff --git a/include/xpm/mask_e.xpm b/include/xpm/mask_e.xpm
new file mode 100644
index 0000000..2e6b528
--- /dev/null
+++ b/include/xpm/mask_e.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_e_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"................",
+"................",
+"################",
+"################",
+"................",
+"................",
+"################",
+"################",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................"};
diff --git a/include/xpm/mask_i.xpm b/include/xpm/mask_i.xpm
new file mode 100644
index 0000000..a24c1ca
--- /dev/null
+++ b/include/xpm/mask_i.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_i_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"..######..######",
+"..######..######",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................"};
diff --git a/include/xpm/mask_j.xpm b/include/xpm/mask_j.xpm
new file mode 100644
index 0000000..fcc072f
--- /dev/null
+++ b/include/xpm/mask_j.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_j_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"..##..##########",
+"..##..##########",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................"};
diff --git a/include/xpm/mask_l.xpm b/include/xpm/mask_l.xpm
new file mode 100644
index 0000000..a062db6
--- /dev/null
+++ b/include/xpm/mask_l.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_l_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"..........####..",
+"..........####..",
+"......####..##..",
+"......####..##..",
+"..####......##..",
+"..####......##..",
+"......####..##..",
+"......####..##..",
+"..........####..",
+"..........####..",
+"................",
+"................",
+"................",
+"................"};
diff --git a/include/xpm/mask_m.xpm b/include/xpm/mask_m.xpm
new file mode 100644
index 0000000..e717d96
--- /dev/null
+++ b/include/xpm/mask_m.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_m_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"################",
+"################",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................"};
diff --git a/include/xpm/mask_o.xpm b/include/xpm/mask_o.xpm
new file mode 100644
index 0000000..3664bc4
--- /dev/null
+++ b/include/xpm/mask_o.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_o_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"................",
+"................",
+"......####......",
+"......####......",
+"....##....##....",
+"....##....##....",
+"....##....##....",
+"....##....##....",
+"......####......",
+"......####......",
+"................",
+"................",
+"................",
+"................"};
diff --git a/include/xpm/mask_o_.xpm b/include/xpm/mask_o_.xpm
new file mode 100644
index 0000000..fbecff8
--- /dev/null
+++ b/include/xpm/mask_o_.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_O_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"................",
+"................",
+"......####......",
+"......####......",
+"....########....",
+"....########....",
+"....########....",
+"....########....",
+"......####......",
+"......####......",
+"................",
+"................",
+"................",
+"................"};
diff --git a/include/xpm/mask_p.xpm b/include/xpm/mask_p.xpm
new file mode 100644
index 0000000..d29f774
--- /dev/null
+++ b/include/xpm/mask_p.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_p_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"........##......",
+"........##......",
+"........##......",
+"........##......",
+"........##......",
+"........##......",
+"################",
+"################",
+"........##......",
+"........##......",
+"........##......",
+"........##......",
+"........##......",
+"........##......",
+"........##......",
+"........##......"};
diff --git a/include/xpm/mask_r.xpm b/include/xpm/mask_r.xpm
new file mode 100644
index 0000000..47f2aa5
--- /dev/null
+++ b/include/xpm/mask_r.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_r_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"..####..........",
+"..####..........",
+"..##..####......",
+"..##..####......",
+"..##......####..",
+"..##......####..",
+"..##..####......",
+"..##..####......",
+"..####..........",
+"..####..........",
+"................",
+"................",
+"................",
+"................"};
diff --git a/include/xpm/mask_s.xpm b/include/xpm/mask_s.xpm
new file mode 100644
index 0000000..a5e1e82
--- /dev/null
+++ b/include/xpm/mask_s.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_s_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"................",
+"................",
+"....########....",
+"....########....",
+"....##....##....",
+"....##....##....",
+"....##....##....",
+"....##....##....",
+"....########....",
+"....########....",
+"................",
+"................",
+"................",
+"................"};
diff --git a/include/xpm/mask_s_.xpm b/include/xpm/mask_s_.xpm
new file mode 100644
index 0000000..652db36
--- /dev/null
+++ b/include/xpm/mask_s_.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_S_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"................",
+"................",
+"....########....",
+"....########....",
+"....########....",
+"....########....",
+"....########....",
+"....########....",
+"....########....",
+"....########....",
+"................",
+"................",
+"................",
+"................"};
diff --git a/include/xpm/mask_t.xpm b/include/xpm/mask_t.xpm
new file mode 100644
index 0000000..d153fc8
--- /dev/null
+++ b/include/xpm/mask_t.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_t_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"................",
+"................",
+"..####..........",
+"..####..........",
+"##....##........",
+"##....##........",
+"........##....##",
+"........##....##",
+"..........####..",
+"..........####..",
+"................",
+"................",
+"................",
+"................"};
diff --git a/include/xpm/mask_u.xpm b/include/xpm/mask_u.xpm
new file mode 100644
index 0000000..61996fc
--- /dev/null
+++ b/include/xpm/mask_u.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_u_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"......####......",
+"......####......",
+"....##....##....",
+"....##....##....",
+"..##........##..",
+"..##........##..",
+"................",
+"................",
+"................",
+"................"};
diff --git a/include/xpm/next.xpm b/include/xpm/next.xpm
new file mode 100644
index 0000000..606c733
--- /dev/null
+++ b/include/xpm/next.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * next_xpm[] = {
+"16 16 2 1",
+" 	c #E7E7E7",
+".	c #0000FF",
+"                ",
+"                ",
+"                ",
+"  .             ",
+"  ...           ",
+"  .....         ",
+"  .......       ",
+"  .........     ",
+"  ...........   ",
+"  ...........   ",
+"  .........     ",
+"  .......       ",
+"  .....         ",
+"  ...           ",
+"  .             ",
+"                "};
diff --git a/include/xpm/next_sl.xpm b/include/xpm/next_sl.xpm
new file mode 100644
index 0000000..da4f178
--- /dev/null
+++ b/include/xpm/next_sl.xpm
@@ -0,0 +1,24 @@
+/* XPM */
+static const char * next_sl_xpm[] = {
+"16 16 5 1",
+" 	c None",
+".	c #00007F",
+"+	c #007FFF",
+"@	c #0000FF",
+"#	c #003F80",
+"                ",
+"      ..        ",
+"      .+.       ",
+"      .++.      ",
+"     .++ at +.     ",
+" ....++ at +@+.    ",
+" . at +@+ at +@+ at +.   ",
+" .@@@@@@@@+ at +.  ",
+" .@@@@@@@@@@@@. ",
+" .@@@@@@@@#@#.  ",
+" .@#@#@#@#@#.   ",
+" ....@#@#@#.    ",
+"     .@#@#.     ",
+"      .##.      ",
+"      .#.       ",
+"      ..        "};
diff --git a/include/xpm/none.xpm b/include/xpm/none.xpm
new file mode 100644
index 0000000..e81575f
--- /dev/null
+++ b/include/xpm/none.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * none_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"................",
+"..            ..",
+". .          . .",
+".  .        .  .",
+".   .      .   .",
+".    .    .    .",
+".     .  .     .",
+".      ..      .",
+".      ..      .",
+".     .  .     .",
+".    .    .    .",
+".   .      .   .",
+".  .        .  .",
+". .          . .",
+"..            ..",
+"................"};
diff --git a/include/xpm/norm_1.xpm b/include/xpm/norm_1.xpm
new file mode 100644
index 0000000..a433a58
--- /dev/null
+++ b/include/xpm/norm_1.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * norm_1_xpm[] = {
+"16 16 3 1",
+".	c None",
+"+	c #7F0000",
+"@	c #FF0000",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+".++++++++++++++.",
+".+@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@+.",
+".++++++++++++++.",
+"................",
+"................",
+"................",
+"................",
+"................"};
diff --git a/include/xpm/ok.xpm b/include/xpm/ok.xpm
new file mode 100644
index 0000000..0a1c7dc
--- /dev/null
+++ b/include/xpm/ok.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * ok_xpm[] = {
+"16 16 3 1",
+" 	c None",
+"!	c #000090",
+"#	c #0000FF",
+"                ",
+"              # ",
+"             ## ",
+"            ##! ",
+"           ##!  ",
+"          ##!   ",
+"         ##!    ",
+"         ##!    ",
+"        ##!     ",
+"  ###  ###!     ",
+"   ### ##!      ",
+"    #####!      ",
+"     ###!       ",
+"      ##!       ",
+"       #!       ",
+"        !       "};
diff --git a/include/xpm/oper.xpm b/include/xpm/oper.xpm
new file mode 100644
index 0000000..ca6a51d
--- /dev/null
+++ b/include/xpm/oper.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * oper_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"   .            ",
+"   .            ",
+" .....    ..... ",
+"   .            ",
+"   .            ",
+"                ",
+"                ",
+"                ",
+"    .       .   ",
+"   .      . . . ",
+"   .       ...  ",
+"  .        ...  ",
+"  .       . . . ",
+" .          .   ",
+"                "};
diff --git a/include/xpm/oper_a.xpm b/include/xpm/oper_a.xpm
new file mode 100644
index 0000000..afa1a80
--- /dev/null
+++ b/include/xpm/oper_a.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * oper_a_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"    .           ",
+"    .           ",
+"    .    ...... ",
+" .......        ",
+"    .    ...... ",
+"    .           ",
+"    .           ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/oper_d.xpm b/include/xpm/oper_d.xpm
new file mode 100644
index 0000000..2b89d5e
--- /dev/null
+++ b/include/xpm/oper_d.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * oper_d_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"       .        ",
+"      .         ",
+"      .         ",
+"     .   ...... ",
+"     .          ",
+"    .    ...... ",
+"    .           ",
+"   .            ",
+"   .            ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/oper_dir.xpm b/include/xpm/oper_dir.xpm
new file mode 100644
index 0000000..f6f7b8a
--- /dev/null
+++ b/include/xpm/oper_dir.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * oper_dir_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"   .            ",
+"  .   .         ",
+"  .   .         ",
+"  . .... .      ",
+"  . . . .       ",
+"  . .... .      ",
+" .              ",
+"          ..... ",
+"          .   . ",
+"  ..       .    ",
+" .  .       .   ",
+"    .      .    ",
+" ....     .   . ",
+".   .. .  ..... ",
+".  .  .         ",
+" ..  . .        "};
diff --git a/include/xpm/oper_m.xpm b/include/xpm/oper_m.xpm
new file mode 100644
index 0000000..f2f8db1
--- /dev/null
+++ b/include/xpm/oper_m.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * oper_m_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #000000",
+"+	c #7F7F7F",
+"                ",
+"                ",
+"                ",
+"                ",
+"   .   .        ",
+"   +. .+        ",
+"    +.+  ...... ",
+"  ......        ",
+"    +.+  ...... ",
+"   +. .+        ",
+"   .   .        ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/oper_of.xpm b/include/xpm/oper_of.xpm
new file mode 100644
index 0000000..c22a9ba
--- /dev/null
+++ b/include/xpm/oper_of.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * oper_of_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #000000",
+"+	c #FF0000",
+"   .        ++  ",
+"  .   .     ++  ",
+"  .   .   ++++++",
+"  . .... .++++++",
+"  . . . .   ++  ",
+"  . .... .  ++  ",
+" .              ",
+"          ..... ",
+"          .   . ",
+"  ..       .    ",
+" .  .       .   ",
+"    .      .    ",
+" ....     .   . ",
+".   .. .  ..... ",
+".  .  .         ",
+" ..  . .        "};
diff --git a/include/xpm/oper_s.xpm b/include/xpm/oper_s.xpm
new file mode 100644
index 0000000..6bda134
--- /dev/null
+++ b/include/xpm/oper_s.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * oper_s_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"         ...... ",
+" .......        ",
+"         ...... ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/option.xpm b/include/xpm/option.xpm
new file mode 100644
index 0000000..d7dd6d6
--- /dev/null
+++ b/include/xpm/option.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * option_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #000000",
+"+	c #7F0000",
+"                ",
+"                ",
+"                ",
+"   ..           ",
+"  .++.          ",
+"  .++.          ",
+"   ..           ",
+"                ",
+"                ",
+"   ..           ",
+"  .++.          ",
+"  .++.          ",
+"   .+. ++ ++ ++ ",
+"    .  ++ ++ ++ ",
+"   .            ",
+"                "};
diff --git a/include/xpm/other.xpm b/include/xpm/other.xpm
new file mode 100644
index 0000000..e2d7562
--- /dev/null
+++ b/include/xpm/other.xpm
@@ -0,0 +1,117 @@
+/* XPM */
+static const char * other_xpm[] = {
+"16 16 98 2",
+"  	c None",
+". 	c #FFFFFF",
+"+ 	c #00CAFF",
+"@ 	c #00ADFF",
+"# 	c #0000EB",
+"$ 	c #00007F",
+"% 	c #0000B4",
+"& 	c #0000B9",
+"* 	c #00D1FF",
+"= 	c #73FF8B",
+"- 	c #68FF96",
+"; 	c #00BFFF",
+"> 	c #0000C3",
+", 	c #0000C7",
+"' 	c #01DDFD",
+") 	c #0041FF",
+"! 	c #0DFBF1",
+"~ 	c #3EFFC0",
+"{ 	c #00EEFF",
+"] 	c #0024FF",
+"^ 	c #000082",
+"/ 	c #000083",
+"( 	c #2EFFD0",
+"_ 	c #00E9FF",
+": 	c #0001EA",
+"< 	c #0074FF",
+"[ 	c #009CFF",
+"} 	c #0058FF",
+"| 	c #0000D5",
+"1 	c #009FFF",
+"2 	c #63FF9B",
+"3 	c #0000C1",
+"4 	c #00009D",
+"5 	c #0000F7",
+"6 	c #0042FF",
+"7 	c #0030FF",
+"8 	c #0000DC",
+"9 	c #000080",
+"0 	c #0017FE",
+"a 	c #00E0FF",
+"b 	c #0000F6",
+"c 	c #0075FF",
+"d 	c #0094FF",
+"e 	c #0044FF",
+"f 	c #0000BE",
+"g 	c #000086",
+"h 	c #000BFE",
+"i 	c #004FFF",
+"j 	c #0000AC",
+"k 	c #006EFF",
+"l 	c #10FEEE",
+"m 	c #35FFC9",
+"n 	c #0000C9",
+"o 	c #0083FF",
+"p 	c #0031FF",
+"q 	c #000090",
+"r 	c #0007F9",
+"s 	c #0BF9F3",
+"t 	c #7EFF80",
+"u 	c #58FFA6",
+"v 	c #007DFF",
+"w 	c #000085",
+"x 	c #1FFFDF",
+"y 	c #000081",
+"z 	c #0039FF",
+"A 	c #00DBFF",
+"B 	c #01BDFD",
+"C 	c #0AFEF4",
+"D 	c #0000AA",
+"E 	c #00009A",
+"F 	c #001BFC",
+"G 	c #00C9FE",
+"H 	c #4BFFB3",
+"I 	c #0006F7",
+"J 	c #008FFF",
+"K 	c #6FFF8F",
+"L 	c #F5FF09",
+"M 	c #FFDB00",
+"N 	c #F1FB0D",
+"O 	c #0021FF",
+"P 	c #0000EA",
+"Q 	c #13FCEB",
+"R 	c #F0FF0E",
+"S 	c #FF8700",
+"T 	c #FF5B00",
+"U 	c #EDFC11",
+"V 	c #12FDEC",
+"W 	c #0003E9",
+"X 	c #00B7FF",
+"Y 	c #98FF66",
+"Z 	c #FFDF00",
+"` 	c #FFB300",
+" .	c #00B8FF",
+"..	c #0067FF",
+"+.	c #04E9FA",
+"@.	c #1DFCE1",
+"#.	c #00EDFF",
+"$.	c #000088",
+"            + @ # $ $ %         ",
+"      & * = - ; > $ $ , '       ",
+"  $ $ ) ! ~ { ] ^ $ $ / ( _     ",
+"  $ $ : < [ } | $ $ $ $ 1 2 3   ",
+"  $ $ 4 5 6 7 8 9 $ $ $ 0 a 7 $ ",
+"  $ $ / b c d e f $ $ g h i 8 $ ",
+"  $ $ j k l m * # $ $ n o p q $ ",
+"  $ $ r s t u v w $ $ j x 1 y $ ",
+"  $ $ z A B $ $ $ $ $ $ C ~ D $ ",
+"  $ $ $ $ E F [ G [ 0 E $ H I $ ",
+"  $ $ $ D J K L M N K J D $ O $ ",
+"    $ $ P Q R S T S U V W $ $ $ ",
+"      $ f X Y Z ` Z Y  .f $ $ $ ",
+"        $ > ..+. at .#...> $ $     ",
+"          $ $ y $.^ $           ",
+"            $ $ $               "};
diff --git a/include/xpm/pause.xpm b/include/xpm/pause.xpm
new file mode 100644
index 0000000..e09d88b
--- /dev/null
+++ b/include/xpm/pause.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * pause_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #777777",
+"q	c #000000",
+"                ",
+"                ",
+"                ",
+"   qqq    qqq   ",
+"   q.q    q.q   ",
+"   q.q    q.q   ",
+"   q.q    q.q   ",
+"   q.q    q.q   ",
+"   q.q    q.q   ",
+"   q.q    q.q   ",
+"   q.q    q.q   ",
+"   q.q    q.q   ",
+"   qqq    qqq   ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/plot.xpm b/include/xpm/plot.xpm
new file mode 100644
index 0000000..acc1eea
--- /dev/null
+++ b/include/xpm/plot.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char * plot_xpm[] = {
+"16 16 4 1",
+" 	c None",
+".	c #000000",
+"+	c #0000FF",
+"@	c #FF0000",
+"                ",
+" .              ",
+"..            + ",
+" .          ++  ",
+" .         +    ",
+"..        +     ",
+" .       +      ",
+" .       +      ",
+"..   @@@+       ",
+" .  @  +@     @ ",
+" .@@   + @   @  ",
+"..    +   @@@   ",
+" .  ++          ",
+" .++            ",
+"............... ",
+" .   .   .   .  "};
diff --git a/include/xpm/polygon.xpm b/include/xpm/polygon.xpm
new file mode 100644
index 0000000..ecbdb8f
--- /dev/null
+++ b/include/xpm/polygon.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *polygon_xpm[]={
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"       ..       ",
+"      .  .      ",
+"    ..    ..    ",
+"   .        .   ",
+" ..          .. ",
+".              .",
+".              .",
+" .            . ",
+" .            . ",
+" .            . ",
+"  .          .  ",
+"  .          .  ",
+"  .          .  ",
+"   .        .   ",
+"   ..........   "};
diff --git a/include/xpm/prev_sl.xpm b/include/xpm/prev_sl.xpm
new file mode 100644
index 0000000..3f20e59
--- /dev/null
+++ b/include/xpm/prev_sl.xpm
@@ -0,0 +1,24 @@
+/* XPM */
+static const char * prev_sl_xpm[] = {
+"16 16 5 1",
+" 	c None",
+".	c #00007F",
+"+	c #007FFF",
+"@	c #0000FF",
+"#	c #003F80",
+"                ",
+"        ..      ",
+"       .+.      ",
+"      .++.      ",
+"     .+ at ++.     ",
+"    .+ at +@++.... ",
+"   .+ at +@+ at +@+ at . ",
+"  .+ at +@@@@@@@@. ",
+" .@@@@@@@@@@@@. ",
+"  .#@#@@@@@@@@. ",
+"   .#@#@#@#@#@. ",
+"    .#@#@#@.... ",
+"     .#@#@.     ",
+"      .##.      ",
+"       .#.      ",
+"        ..      "};
diff --git a/include/xpm/preview.xpm b/include/xpm/preview.xpm
new file mode 100644
index 0000000..0446109
--- /dev/null
+++ b/include/xpm/preview.xpm
@@ -0,0 +1,193 @@
+/* XPM */
+static const char *preview_xpm[] = {
+"16 16 174 2",
+"  	c None",
+". 	c #EA6E0E",
+"+ 	c #F67F06",
+"@ 	c #E3BB18",
+"# 	c #A4E757",
+"$ 	c #56E6A3",
+"% 	c #25DAD6",
+"& 	c #11E5EB",
+"* 	c #2AF5D0",
+"= 	c #72F588",
+"- 	c #B0EC4B",
+"; 	c #C7DC34",
+"> 	c #C3E336",
+", 	c #98F563",
+"' 	c #3FF6BC",
+") 	c #07D5F5",
+"! 	c #0E9EEA",
+"~ 	c #F44C0A",
+"{ 	c #FC0E00",
+"] 	c #FB1900",
+"^ 	c #FF5B00",
+"/ 	c #F7C407",
+"( 	c #B5FD49",
+"_ 	c #4BFFB3",
+": 	c #0BF6F3",
+"< 	c #05D9F9",
+"[ 	c #0CD2F2",
+"} 	c #14DEEB",
+"| 	c #1BF0E3",
+"1 	c #20FEDE",
+"2 	c #27FFD7",
+"3 	c #2BFDD3",
+"4 	c #3BEEC3",
+"5 	c #F14F0A",
+"6 	c #FC1400",
+"7 	c #FB1700",
+"8 	c #FF5000",
+"9 	c #FBBA03",
+"0 	c #B8FD46",
+"a 	c #39FCC5",
+"b 	c #01CAFE",
+"c 	c #0088FF",
+"d 	c #0075FF",
+"e 	c #008FFF",
+"f 	c #01CCFE",
+"g 	c #22FCDC",
+"h 	c #73FF8B",
+"i 	c #BAFC44",
+"j 	c #D3E228",
+"k 	c #F47B0A",
+"l 	c #FF8C00",
+"m 	c #F4BA0A",
+"n 	c #CBE733",
+"o 	c #7DFC81",
+"p 	c #2BEDD3",
+"q 	c #03C1FB",
+"r 	c #0090FF",
+"s 	c #0082FF",
+"t 	c #009DFF",
+"u 	c #08D4F7",
+"v 	c #3AFAC4",
+"w 	c #98FF66",
+"x 	c #E7EF18",
+"y 	c #FEBC01",
+"z 	c #F4920A",
+"A 	c #F4AD0B",
+"B 	c #D4F62A",
+"C 	c #63FD9B",
+"D 	c #16D9E9",
+"E 	c #0296FD",
+"F 	c #0063FF",
+"G 	c #0059FF",
+"H 	c #0076FF",
+"I 	c #00B6FF",
+"J 	c #1AF2E4",
+"K 	c #6EFF90",
+"L 	c #C8FD36",
+"M 	c #F9E306",
+"N 	c #FFB900",
+"O 	c #FFA800",
+"P 	c #F4AF0B",
+"Q 	c #EFBD0D",
+"R 	c #A0FF5E",
+"S 	c #1BF3E3",
+"T 	c #009CFF",
+"U 	c #0056FF",
+"V 	c #0041FF",
+"W 	c #005DFF",
+"X 	c #00A0FF",
+"Y 	c #0EEEF0",
+"Z 	c #5FFF9F",
+"` 	c #B7FF47",
+" .	c #F1FA0D",
+"..	c #F9E606",
+"+.	c #F0E70E",
+"@.	c #D4F42A",
+"#.	c #9CF05F",
+"$.	c #F4AA0A",
+"%.	c #DFF01F",
+"&.	c #8DFD71",
+"*.	c #4CF4B2",
+"=.	c #2DDFD1",
+"-.	c #21D5DE",
+";.	c #1CDFE2",
+">.	c #20F4DE",
+",.	c #3BFFC3",
+"'.	c #79FF85",
+").	c #80FF7E",
+"!.	c #72FE8C",
+"~.	c #51FAAD",
+"{.	c #28EFD6",
+"].	c #14CDEA",
+"^.	c #F4760A",
+"/.	c #FF6B00",
+"(.	c #FD6D00",
+"_.	c #F87A05",
+":.	c #F1910C",
+"<.	c #E9B615",
+"[.	c #D8DF26",
+"}.	c #B2FC4C",
+"|.	c #70FF8E",
+"1.	c #2DFED1",
+"2.	c #0BE3F3",
+"3.	c #04B9FB",
+"4.	c #0099FE",
+"5.	c #0085FF",
+"6.	c #007EFF",
+"7.	c #0A84F4",
+"8.	c #F1480A",
+"9.	c #EA0500",
+"0.	c #C50000",
+"a.	c #B30000",
+"b.	c #BB0100",
+"c.	c #DA0600",
+"d.	c #FA3500",
+"e.	c #FCB403",
+"f.	c #ACFD52",
+"g.	c #24F8DA",
+"h.	c #00A5FF",
+"i.	c #0036FF",
+"j.	c #0046FF",
+"k.	c #007FFF",
+"l.	c #11C0EA",
+"m.	c #F4440A",
+"n.	c #E10100",
+"o.	c #B20000",
+"p.	c #990000",
+"q.	c #9B0000",
+"r.	c #B90000",
+"s.	c #EB0500",
+"t.	c #FF6700",
+"u.	c #E9E716",
+"v.	c #75FF89",
+"w.	c #1EE7E0",
+"x.	c #09B9F6",
+"y.	c #06ACF8",
+"z.	c #11C6ED",
+"A.	c #38F0C6",
+"B.	c #8FF26F",
+"C.	c #E9630E",
+"D.	c #F43606",
+"E.	c #E92406",
+"F.	c #E02006",
+"G.	c #DE2006",
+"H.	c #F43706",
+"I.	c #F56806",
+"J.	c #F5A106",
+"K.	c #EBCC11",
+"L.	c #CED92D",
+"M.	c #B9DB41",
+"N.	c #B9DD43",
+"O.	c #C8D933",
+"P.	c #E3CE18",
+"Q.	c #E8AB10",
+"                                ",
+"                                ",
+"                                ",
+". + @ # $ % & * = - ; > , ' ) ! ",
+"~ { ] ^ / ( _ : < [ } | 1 2 3 4 ",
+"5 6 7 8 9 0 a b c d e f g h i j ",
+"k l m n o p q r s t u v w x y z ",
+"A B C D E F G H I J K L M N O P ",
+"Q R S T U V W X Y Z `  ...+. at .#.",
+"$.%.&.*.=.-.;.>.,.Z '.).!.~.{.].",
+"^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.",
+"8.9.0.a.b.c.d.e.f.g.h.U i.j.k.l.",
+"m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.",
+"C.D.E.F.G.E.H.I.J.K.L.M.N.O.P.Q.",
+"                                ",
+"                                "};
diff --git a/include/xpm/right_1.xpm b/include/xpm/right_1.xpm
new file mode 100644
index 0000000..a7b3a67
--- /dev/null
+++ b/include/xpm/right_1.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * right_1_xpm[] = {
+"16 16 3 1",
+".	c None",
+"+	c #7F0000",
+"@	c #FF0000",
+"................",
+"................",
+"........+.......",
+"........++......",
+"........+ at +.....",
+"..+++++++@@+....",
+"..+@@@@@@@@@+...",
+"..+@@@@@@@@@@+..",
+"..+@@@@@@@@@@@+.",
+"..+@@@@@@@@@@+..",
+"..+@@@@@@@@@+...",
+"..+++++++@@+....",
+"........+ at +.....",
+"........++......",
+"........+.......",
+"................"};
diff --git a/include/xpm/rotate.xpm b/include/xpm/rotate.xpm
new file mode 100644
index 0000000..e6b0220
--- /dev/null
+++ b/include/xpm/rotate.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char *rotate_xpm[]={
+"16 16 3 1",
+". c None",
+"# c #000080",
+"a c #8080ff",
+"......#########.",
+"......#aaaaaa#..",
+".......#aaaa##..",
+"..###..#aaaaa#..",
+".#aa#..#aaa#aa#.",
+".#aa#...#a##aa#.",
+"#aa#....#a#.#aa#",
+"#aa#.....#..#aa#",
+"#aa#........#aa#",
+"#aa#........#aa#",
+".#a#........#a#.",
+".#aa#......#aa#.",
+"..#aa##..##aa#..",
+"...#aaa##aaa#...",
+"....##aaaa##....",
+"......####......"};
diff --git a/include/xpm/show_sl.xpm b/include/xpm/show_sl.xpm
new file mode 100644
index 0000000..21e4e90
--- /dev/null
+++ b/include/xpm/show_sl.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * show_sl_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #000000",
+"+	c #007FFF",
+"                ",
+"                ",
+"  ............  ",
+"  . .++++++. .  ",
+"  ...++++++...  ",
+"  . .++++++. .  ",
+"  . .++++++. .  ",
+"  ...++++++...  ",
+"  . .++++++. .  ",
+"  . .++++++. .  ",
+"  ...++++++...  ",
+"  . .++++++. .  ",
+"  . .++++++. .  ",
+"  ...++++++...  ",
+"  . .++++++. .  ",
+"  ............  "};
diff --git a/include/xpm/size.xpm b/include/xpm/size.xpm
new file mode 100644
index 0000000..3a1d846
--- /dev/null
+++ b/include/xpm/size.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * size_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+" .............. ",
+" .     .      . ",
+" .    ...     . ",
+" .     .      . ",
+" .     .      . ",
+" . .   .    . . ",
+" .............. ",
+" . .   .    . . ",
+" .     .      . ",
+" .     .      . ",
+" .     .      . ",
+" .    ...     . ",
+" .     .      . ",
+" .............. "};
diff --git a/include/xpm/squize.xpm b/include/xpm/squize.xpm
new file mode 100644
index 0000000..fa68e6a
--- /dev/null
+++ b/include/xpm/squize.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * squize_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #000000",
+"+	c #7F7F7F",
+"                ",
+"                ",
+"     ......     ",
+"     .    .     ",
+"     .    .     ",
+"  .  .    .  .  ",
+"  +. .    . .+  ",
+"......    ......",
+"  +. .    . .+  ",
+"  .  .    .  .  ",
+"     .    .     ",
+"     .    .     ",
+"     .    .     ",
+"     ......     ",
+"                ",
+"                "};
diff --git a/include/xpm/stop.xpm b/include/xpm/stop.xpm
new file mode 100644
index 0000000..028f468
--- /dev/null
+++ b/include/xpm/stop.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char * stop_xpm[] = {
+"16 16 4 1",
+" 	c None",
+".	c #770000",
+"+	c #FF0000",
+"@	c #FFFFFF",
+"                ",
+"     ......     ",
+"    .++++++.    ",
+"   .++++++++.   ",
+"  .++++++++++.  ",
+" .+++@@++@@+++. ",
+" .+++@@@@@@+++. ",
+" .++++@@@@++++. ",
+" .++++@@@@++++. ",
+" .+++@@@@@@+++. ",
+" .+++@@++@@+++. ",
+"  .++++++++++.  ",
+"   .++++++++.   ",
+"    .++++++.    ",
+"     ......     ",
+"                "};
diff --git a/include/xpm/style.xpm b/include/xpm/style.xpm
new file mode 100644
index 0000000..9125d5f
--- /dev/null
+++ b/include/xpm/style.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * style_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #FF0000",
+"q	c #7F0000",
+"                ",
+"                ",
+"                ",
+"   qqq   qqq    ",
+"   q.q   q.q    ",
+"   q.q   q.q    ",
+"   q.q   q.q    ",
+"    q     q     ",
+"    q     q     ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/include/xpm/table.xpm b/include/xpm/table.xpm
new file mode 100644
index 0000000..43b33a4
--- /dev/null
+++ b/include/xpm/table.xpm
@@ -0,0 +1,24 @@
+/* XPM */
+static const char * table_xpm[] = {
+"16 16 4 1",
+" 	c None",
+"#	c #000000",
+"o	c #777777",
+".	c #FFFFFF",
+"                ",
+" ###############",
+" #ooo#oooo#oooo#",
+" #ooo#oooo#oooo#",
+" ###############",
+" #ooo#....#....#",
+" #ooo#....#....#",
+" ###############",
+" #ooo#....#....#",
+" #ooo#....#....#",
+" ###############",
+" #ooo#....#....#",
+" #ooo#....#....#",
+" ###############",
+"                ",
+"                "};
+
diff --git a/include/xpm/text.xpm b/include/xpm/text.xpm
new file mode 100644
index 0000000..56317c0
--- /dev/null
+++ b/include/xpm/text.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * text_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"  ............  ",
+"  ............  ",
+"  .    ..    .  ",
+"       ..       ",
+"       ..       ",
+"       ..       ",
+"       ..       ",
+"       ..       ",
+"       ..       ",
+"       ..       ",
+"       ..       ",
+"       ..       ",
+"       ..       ",
+"      ....      ",
+"                "};
diff --git a/include/xpm/tiles.xpm b/include/xpm/tiles.xpm
new file mode 100644
index 0000000..505dadd
--- /dev/null
+++ b/include/xpm/tiles.xpm
@@ -0,0 +1,132 @@
+/* XPM */
+static const char * tiles_xpm[] = {
+"16 16 113 2",
+"  	c None",
+". 	c #00D9FB",
+"+ 	c #00FEC7",
+"@ 	c #7DFF1E",
+"# 	c #DBDF08",
+"$ 	c #EAC004",
+"% 	c #E5D403",
+"& 	c #FF5D00",
+"* 	c #FC1600",
+"= 	c #FC2500",
+"- 	c #00EAE9",
+"; 	c #00E9CA",
+"> 	c #05F1B1",
+", 	c #03F8B5",
+"' 	c #00FFC7",
+") 	c #00FFD6",
+"! 	c #FF5900",
+"~ 	c #FD0600",
+"{ 	c #FA0000",
+"] 	c #FF2600",
+"^ 	c #00A1FF",
+"/ 	c #00CEFF",
+"( 	c #00FEE9",
+"_ 	c #00FF71",
+": 	c #80FF12",
+"< 	c #CFFF07",
+"[ 	c #FF7000",
+"} 	c #FF5800",
+"| 	c #FE7200",
+"1 	c #F9B100",
+"2 	c #00EDF2",
+"3 	c #1AFF56",
+"4 	c #C1FA00",
+"5 	c #FDD600",
+"6 	c #FFA700",
+"7 	c #FF9200",
+"8 	c #F3D400",
+"9 	c #A0FD21",
+"0 	c #21F996",
+"a 	c #ECF100",
+"b 	c #FFC900",
+"c 	c #FF9B00",
+"d 	c #FF9300",
+"e 	c #FDA700",
+"f 	c #AEFF05",
+"g 	c #00F9C7",
+"h 	c #00AAFF",
+"i 	c #0052FF",
+"j 	c #FDCA00",
+"k 	c #E6DE00",
+"l 	c #FCA900",
+"m 	c #ADFF00",
+"n 	c #00FCC3",
+"o 	c #00C8FF",
+"p 	c #0089FF",
+"q 	c #0079FE",
+"r 	c #0094FF",
+"s 	c #00CDFF",
+"t 	c #93E71F",
+"u 	c #6BF55F",
+"v 	c #57FA76",
+"w 	c #3EFF80",
+"x 	c #1BFF89",
+"y 	c #00FF84",
+"z 	c #00FF95",
+"A 	c #F52C00",
+"B 	c #F03200",
+"C 	c #F23E00",
+"D 	c #FB5B00",
+"E 	c #F39E00",
+"F 	c #D4EA00",
+"G 	c #3BFF31",
+"H 	c #00FCD9",
+"I 	c #00C2FF",
+"J 	c #FE5500",
+"K 	c #E70200",
+"L 	c #B30000",
+"M 	c #9C0000",
+"N 	c #A30000",
+"O 	c #C30000",
+"P 	c #F61400",
+"Q 	c #FF9600",
+"R 	c #99FD04",
+"S 	c #01FDD5",
+"T 	c #00A6FF",
+"U 	c #0054FF",
+"V 	c #0037FF",
+"W 	c #EC0400",
+"X 	c #BD0000",
+"Y 	c #A20000",
+"Z 	c #A00000",
+"` 	c #B70000",
+" .	c #EA0100",
+"..	c #FF5600",
+"+.	c #EDE300",
+"@.	c #0CF5CC",
+"#.	c #06D2E4",
+"$.	c #09CEE0",
+"%.	c #18E5C1",
+"&.	c #4AFF6C",
+"*.	c #C1EB09",
+"=.	c #FF7200",
+"-.	c #FE4F00",
+";.	c #F73E00",
+">.	c #F03A00",
+",.	c #F03800",
+"'.	c #F63A00",
+").	c #E2BD00",
+"!.	c #D0C10A",
+"~.	c #CDC110",
+"{.	c #DFBB02",
+"].	c #F7B100",
+"^.	c #FF9C00",
+"                                ",
+"                                ",
+"            . + @ # $ %         ",
+"& * =           - ; > , ' )     ",
+"! ~ { ]             ^ / ( _ : < ",
+"[ } | 1               2 3 4 5 6 ",
+"7 8 9 0                 a b c d ",
+"e f g h i                   j k ",
+"l m n o p q r s                 ",
+"      t u v w x y z             ",
+"    A B C D E F G H I           ",
+"J K L M N O P Q R S T U V       ",
+"} W X Y Z `  ...+.  @.#.$.%.&.*.",
+"=.-.;.>.,.'.        ).!.~.{.].^.",
+"                                ",
+"                                "};
diff --git a/include/xpm/tran.xpm b/include/xpm/tran.xpm
new file mode 100644
index 0000000..29fa1ee
--- /dev/null
+++ b/include/xpm/tran.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char * tran_xpm[] = {
+"16 16 4 1",
+" 	c None",
+".	c #000000",
+"+	c #FF0000",
+"@	c #0000FF",
+"                ",
+"                ",
+" ......++++++++ ",
+" .    .       + ",
+" . . ..+ + + ++ ",
+" .    .       + ",
+" . . ..+ + + ++ ",
+" .++++.++++++++ ",
+" . . ..         ",
+" .    .      @  ",
+" . . ..     @@@ ",
+" .    .      @  ",
+" . . ..      @  ",
+" .    .    @@   ",
+" . . .. @@@     ",
+" ......         "};
diff --git a/include/xpm/udav.xpm b/include/xpm/udav.xpm
new file mode 100644
index 0000000..714a7b3
--- /dev/null
+++ b/include/xpm/udav.xpm
@@ -0,0 +1,416 @@
+/* XPM */
+static const char *udav_xpm[]={
+"64 64 349 2",
+"Qt c None",
+"#n c #000080",
+"#h c #010180",
+"#y c #010181",
+"#s c #020281",
+"#c c #020282",
+"dg c #030382",
+".8 c #030383",
+"#r c #040483",
+"#m c #040484",
+"#g c #050584",
+"#M c #050585",
+"#q c #060685",
+"a. c #060686",
+"#p c #070786",
+"ck c #070787",
+"aj c #080887",
+"bm c #080888",
+"aK c #090988",
+"a4 c #090989",
+"aJ c #0a0a89",
+"## c #0a0a8a",
+"#G c #0b0b8a",
+"cx c #0b0b8b",
+"b7 c #0c0c8b",
+"#z c #0c0c8c",
+"b6 c #0d0d8c",
+"b8 c #0d0d8d",
+"#l c #0e0e8d",
+"cj c #0e0e8e",
+"b5 c #0f0f8e",
+"#S c #0f0f8f",
+"ci c #10108f",
+"bE c #101090",
+"b4 c #111190",
+"c2 c #111191",
+"#W c #121291",
+"b9 c #121292",
+"#b c #131392",
+"b3 c #131393",
+"ak c #141493",
+"aD c #141494",
+"bG c #151594",
+"aq c #151595",
+"bF c #161695",
+"#i c #161696",
+"aE c #171796",
+"ae c #171797",
+".5 c #181897",
+"cq c #181898",
+"#L c #191998",
+"bU c #191999",
+"b2 c #1a1a99",
+"aL c #1a1a9a",
+"ds c #1b1b9a",
+"#A c #1b1b9b",
+"#k c #1c1c9b",
+"#f c #1c1c9c",
+"cG c #1d1d9c",
+"bM c #1d1d9d",
+"bN c #1e1e9d",
+"ch c #1e1e9e",
+"bL c #1f1f9e",
+"b1 c #1f1f9f",
+"#j c #20209f",
+"bO c #2020a0",
+"cS c #2121a0",
+"bY c #2121a1",
+"db c #2222a1",
+"bK c #2222a2",
+"bn c #2323a2",
+"a# c #2323a3",
+"bH c #2424a4",
+"bJ c #2525a4",
+"a3 c #2525a5",
+"#o c #2626a5",
+"df c #2626a6",
+"#. c #2727a6",
+"bP c #2727a7",
+"ai c #2828a7",
+"cF c #2828a8",
+"cf c #2929a9",
+"b0 c #2a2aa9",
+"#x c #2a2aaa",
+".7 c #2b2baa",
+"bI c #2b2bab",
+"cy c #2c2cab",
+"a5 c #2c2cac",
+"aI c #2d2dac",
+"#d c #2d2dad",
+"cp c #2e2ead",
+"bo c #2e2eae",
+"ap c #2f2fae",
+"#1 c #3030b0",
+"cg c #3131b1",
+"bZ c #3232b1",
+"de c #3333b2",
+"dw c #3333b3",
+"bQ c #3434b4",
+"bp c #3535b5",
+"c3 c #3636b5",
+"#R c #3636b6",
+"cC c #3737b7",
+"aC c #3838b7",
+"#t c #3838b8",
+"#T c #3939b8",
+"#F c #3939b9",
+"bq c #3a3ab9",
+"#6 c #3a3aba",
+"aM c #3c3cbb",
+"#B c #3d3dbc",
+"cr c #3d3dbd",
+"#N c #3e3ebd",
+"dA c #3e3ebe",
+"ar c #3f3fbe",
+"bA c #3f3fbf",
+"bR c #4040c0",
+"bS c #4141c0",
+"dh c #4141c1",
+"ce c #4242c1",
+"da c #4343c3",
+"br c #4444c3",
+"#X c #4545c4",
+"a6 c #4545c5",
+"cM c #4646c5",
+"bw c #4646c6",
+"#e c #4747c6",
+"bs c #4747c7",
+"bv c #4848c7",
+"aB c #4848c8",
+"bt c #4949c8",
+"bu c #4949c9",
+"bx c #4a4ac9",
+"as c #4a4aca",
+"cs c #4b4bca",
+"ct c #4b4bcb",
+"#u c #4c4ccb",
+"bl c #4c4ccc",
+"dz c #5050cf",
+"c6 c #5151d0",
+"a7 c #5151d1",
+"by c #5252d1",
+"#H c #5353d2",
+"dx c #5454d3",
+"d# c #5454d4",
+"at c #5555d5",
+"aA c #5656d5",
+"cw c #5656d6",
+"dy c #5757d6",
+"bz c #5858d8",
+"#a c #5959d9",
+"cE c #5a5ad9",
+"cL c #5b5bdb",
+"a8 c #5c5cdb",
+"aN c #5c5cdc",
+".6 c #5d5ddd",
+"c5 c #5e5edd",
+"bk c #5e5ede",
+"dt c #5f5fde",
+"cT c #6060df",
+"al c #6262e1",
+"au c #6262e2",
+"az c #6464e4",
+"af c #6565e4",
+"cD c #6565e5",
+"#2 c #6666e6",
+"d. c #6767e7",
+"co c #6868e7",
+".9 c #6868e8",
+"av c #6969e8",
+"cN c #6a6aea",
+"a2 c #6b6bea",
+"c. c #6b6beb",
+"dk c #6c6ceb",
+"aO c #6c6cec",
+"ay c #6d6dec",
+"ad c #6e6eee",
+"ax c #6f6fef",
+"bD c #7070f0",
+"#w c #7171f0",
+"aw c #7171f1",
+"cu c #7272f1",
+"c7 c #7272f2",
+"a9 c #7373f2",
+"aF c #7373f3",
+"dn c #7474f4",
+"b. c #7878f7",
+"#C c #7979f8",
+".4 c #7979f9",
+"aP c #7a7af9",
+"aa c #7b7bfa",
+"b# c #7c7cfb",
+"cd c #7e7efd",
+"bX c #7f7ffe",
+".3 c #800000",
+".1 c #800101",
+"ba c #8080ff",
+".2 c #810101",
+".X c #810202",
+"dp c #8181ff",
+".W c #820202",
+".Y c #820303",
+"#5 c #8282ff",
+".Z c #830303",
+"aH c #8383ff",
+".R c #840505",
+"#v c #8484ff",
+".S c #850606",
+"bb c #8585ff",
+".T c #860707",
+"#K c #8686ff",
+".U c #870808",
+".V c #880808",
+"aQ c #8888ff",
+".Q c #890a0a",
+"dr c #8989ff",
+".K c #8a0a0a",
+"cz c #8a8aff",
+".j c #8b0b0b",
+"cK c #8b8bff",
+"bc c #8c8cff",
+"cU c #8d8dff",
+".B c #8e0e0e",
+".P c #8e0f0f",
+"ao c #8e8eff",
+".L c #8f0f0f",
+"cH c #9090ff",
+"bd c #9292ff",
+".C c #931414",
+"aR c #9393ff",
+".O c #941414",
+"#D c #9494ff",
+"#O c #9595ff",
+"cV c #9696ff",
+".M c #981818",
+"#E c #9898ff",
+".c c #991a1a",
+"cO c #9999ff",
+".N c #9a1b1b",
+".s c #9b1b1b",
+".J c #9d1e1e",
+"be c #9d9dff",
+"aS c #9e9eff",
+"dd c #9f9fff",
+"c8 c #a1a1ff",
+".D c #a32424",
+"#7 c #a3a3ff",
+"#I c #a5a5ff",
+".r c #a72828",
+"aT c #a7a7ff",
+"do c #a8a8ff",
+"cn c #a9a9ff",
+".# c #ab2c2c",
+"c9 c #ababff",
+".A c #ac2c2c",
+"cW c #adadff",
+"#Y c #aeaeff",
+".I c #af2f2f",
+"du c #b0b0ff",
+"#0 c #b1b1ff",
+"c4 c #b2b2ff",
+"bf c #b3b3ff",
+".E c #b43535",
+"cA c #b4b4ff",
+"#Q c #b5b5ff",
+"dv c #b6b6ff",
+"cl c #b7b7ff",
+"cX c #b8b8ff",
+"aU c #b9b9ff",
+"cc c #babaff",
+".i c #bc3c3c",
+"bW c #bcbcff",
+"dm c #bdbdff",
+".H c #be3f3f",
+"aZ c #bebeff",
+"bB c #bfbfff",
+"aV c #c0c0ff",
+".b c #c14141",
+".t c #c14242",
+"bg c #c1c1ff",
+"#V c #c2c2ff",
+".F c #c34343",
+"#9 c #c3c3ff",
+"cY c #c4c4ff",
+"#J c #c5c5ff",
+"cP c #c6c6ff",
+"aW c #c7c7ff",
+"aY c #c8c8ff",
+".a c #c94949",
+"bC c #c9c9ff",
+".k c #ca4a4a",
+"c1 c #cacaff",
+".G c #cb4b4b",
+"aX c #cbcbff",
+"di c #ccccff",
+"dj c #cdcdff",
+"bh c #ceceff",
+"a1 c #d0d0ff",
+"c# c #d1d1ff",
+"c0 c #d2d2ff",
+"cR c #d3d3ff",
+".z c #d45555",
+"cZ c #d4d4ff",
+"bT c #d6d6ff",
+"dl c #d8d8ff",
+"#3 c #dadaff",
+"am c #dbdbff",
+"bi c #dcdcff",
+"ag c #ddddff",
+"#P c #dfdfff",
+"cI c #e1e1ff",
+"bV c #e4e4ff",
+".q c #e66666",
+"dc c #e6e6ff",
+"aG c #e7e7ff",
+".d c #e86969",
+"cb c #e8e8ff",
+"cJ c #eaeaff",
+"ab c #ececff",
+".u c #ed6d6d",
+"bj c #ededff",
+"cB c #efefff",
+"#U c #f0f0ff",
+"cQ c #f1f1ff",
+"cv c #f2f2ff",
+"dq c #f4f4ff",
+"cm c #f5f5ff",
+"ca c #f6f6ff",
+"a0 c #f7f7ff",
+"an c #f9f9ff",
+"ah c #fafaff",
+"#Z c #fbfbff",
+"ac c #fcfcff",
+"#8 c #fdfdff",
+"#4 c #fefeff",
+".y c #ff7f7f",
+".h c #ff8686",
+".v c #ff9292",
+".l c #ff9595",
+".x c #ff9d9d",
+".w c #ffa5a5",
+".p c #ffb0b0",
+".e c #ffb3b3",
+".g c #ffbfbf",
+".f c #ffcece",
+".m c #ffd9d9",
+".o c #ffe8e8",
+".n c #fff8f8",
+".0 c #ffff00",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.#.a.b.cQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.c.d.e.f.g.h.iQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.j.k.l.m.n.o.p.q.rQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.s.t.u.v.w.x.y.z.A.BQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.C.D.E.F.G.a.H.I.J.BQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.K.L.C.M.N.N.M.O.P.QQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.R.S.T.U.V.V.V.U.T.SQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.W.X.W.W.W.W.Y.Y.Z.RQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.1.1.1.1.1.1.2.W.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.3.3.3.3.3.2.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0.0.4.5.2.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0.0.0.6.7.8.0.0.0.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0.0.0.9#..8.0.0.0.0.0.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0###a#b#c.0.0.0.0.0.0.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0#d#e#f#g#h.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0#i#j#k#l#m#h#n#o.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0#p#q#r#s#n#n#m#t#u#v#w#x.0.0.0.0.0.0.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0#y#h#n#m#r#q#z#A#B#C#D#E#F.0.0.0.0.0.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0#r#s#h#h#h#y#r#G#j#H#I#J#K#L.0.0.0.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0.0.0.0#n#n#n#y#M#b#N#O#P#Q#R.0.0.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0.0.0.0.0.0.0#h#n#h#r#S#T#E#U#V#N.0.0.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0#h#h#r#W#X#Y#Z#0#1.0.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0#y#q#k#2#3#4#5.5.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0#c#z#6#7#8#9#X#q.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0a.a#aaabacadae.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0#m.5afagah#Kai.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0.0.0#gaj.0.0.0.0.0.0.0.0.0akalamanaoapaj.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0a.aqa#aparasatauavadawaxayazaAaBaCa#aDaEaFaGanaHaIaJ.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtaKaL#xaM#uaNaOaPaQaRaSaT#0aUaVaWaXaXaYaZ#Y#E#.aSa0a1a2a3a4.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQt###fa5#Ta6a7a8afaOa9b.b#babbbcbdbeaTbfbgbhbiaGbjbk#3#Z#IblaLajbm.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtaDbnbobpbqarbrbsbtbuaBbvbw#e#ebx#ubybzaladaaao#7bAbB#8bCbDapbEa.aObqbF.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtbGbH#dbobI#x.7a5a5#xaibJbK#jbLbMbNbNbObnbP#dbQbRbSaZ#4bTbbarbUa4#ZbVbWbXbr#LQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQt#SbYapbZb0b1b2b2aLbUaEb3b4b5b6b7#G#####Gb7b8#Sb9c.bT#4c#bbbrbL#z#q#Pca#8cbcccdcebFQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQt#icf#taMcgchcicj#Scjb7a4ck#q#g#m#r.8.8.8.8#rblclca#ZaUaF#NbMb8a.#MaQ#0amcmah#Pcncocpa4QtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQt#Gcq.7crcsctcra3b6aJbma.#m.8#c#s#y#y#y#hbJcu#Vcvcvcaaocw#1.5cx#q#rcybSalczcA#PcacBaYaQa6aEQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQt###ka#cCctaNcDazcEbt#tcFch.5cGb0bRazcHbBcIbjbVcJcKcLaCbLbEbm#m.8##bE#AaIcMcNcOcPcbcQcR#EatcSQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtajcj#L#dcCcscTcu#5cUcVbe#IcWcXcYbhcZc0c1cRcUaycsbZbNc2aJ#M.8#ca..8#q##b9bLc3aAbXc4biab#3#7c5#o#pQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQt#qaKb8bGchbSaBc6cE#2c7bX#KbccVc8c9#Qd.d#da#1db#i#laK#M.8#s#sa.#h#y#c#r#pb8cqb0btaF#7a1dccZdda8#o#MQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQt#g#g#paJb8b9.5chbJbI#1c3cC#t#Rde#ddf#jcqb9b6aK#q#r#c#s#y#y.0#h#n#n#h#ydg#M##ak#odhc.dddi#PdjcVd#dbQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQt.8.8#m#M#paK###zcj#SbEbEbE#S#lb7aJaj#q#m.8#c#s#y#h#h#s.0.0.0Qt#m#h#h#y#c#maKb9bndhdkbeaXdldm#vbw#LQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQt#c#c#cdgdg.8#r#m#m#m#m#m#r.8dg#c#s#y#h#h#h#n#h#y.0.0QtQtQtQtQtQtQt#y#y#s#maK#ba3brdndodia1aU#Obyb4QtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQt#s#y#y#y#y#y#y#y#y#y#h#h#h#h#n#n#n#n#n#n#yQtQtQtQtQtQtQtQtQtQtQtQtQt#y#c#maJaDbIa7dpaZdqaha1drbAb3QtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtdg#y#h#h#n#n#n#n#n#n#n#n#n#n#n#n#hdgQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#s#c#Mcxdsc3dtaodudvaScudhdsQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtdg#y#h#h#h#n#n#n#h#y#cQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtdg#pbEb1dwbwdxdydzdA#xaEQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#maJb5bGdsbLbOchaLakb8ckQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#q#qckaKaJ####a4bm#p#pQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#m#c#cdgdgdg.8.8.8#rQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#y#h#h#h#h#h#y#s#rQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#h#n#n#n#n#h#cQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#h#h#yQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt"};
diff --git a/include/xpm/unused/smth.xpm b/include/xpm/unused/smth.xpm
new file mode 100644
index 0000000..a2b9d46
--- /dev/null
+++ b/include/xpm/unused/smth.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * smth_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #000000",
+"+	c #FF0000",
+"                ",
+"                ",
+"                ",
+"                ",
+"    .           ",
+"    .           ",
+"   . .    .     ",
+"   . .    ..    ",
+"  +++.   . .    ",
+" +.  ++  +++.   ",
+"  .   .++   ++  ",
+" .    . .    .+ ",
+" .    . .     . ",
+"       .        ",
+"       .        ",
+"                "};
diff --git a/include/xpm/unused/sum.xpm b/include/xpm/unused/sum.xpm
new file mode 100644
index 0000000..fc017ac
--- /dev/null
+++ b/include/xpm/unused/sum.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * sum_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"   ..........   ",
+"   .        .   ",
+"    .       .   ",
+"     .          ",
+"      .         ",
+"       .        ",
+"        ..      ",
+"       .        ",
+"      .         ",
+"     .          ",
+"    .       .   ",
+"   .        .   ",
+"   ..........   ",
+"                "};
diff --git a/include/xpm/unused/swap.xpm b/include/xpm/unused/swap.xpm
new file mode 100644
index 0000000..6ad367c
--- /dev/null
+++ b/include/xpm/unused/swap.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char * swap_xpm[] = {
+"16 16 4 1",
+" 	c None",
+".	c #0000FF",
+"+	c #000000",
+"@	c #FF0000",
+"                ",
+"  .          .. ",
+"   .        .   ",
+"    .      .    ",
+"    .      .    ",
+"     ......     ",
+"   +         +  ",
+"  +           + ",
+"  +           + ",
+"  + +       + + ",
+"   ++  @@@  ++  ",
+"  +++ @   @ +++ ",
+"     @     @    ",
+"     @     @    ",
+"  @@@       @@@ ",
+"                "};
diff --git a/include/xpm/up_1.xpm b/include/xpm/up_1.xpm
new file mode 100644
index 0000000..472b450
--- /dev/null
+++ b/include/xpm/up_1.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * up_1_xpm[] = {
+"16 16 3 1",
+".	c None",
+"+	c #7F0000",
+"@	c #FF0000",
+"................",
+"................",
+"........+.......",
+".......+ at +......",
+"......+@@@+.....",
+".....+@@@@@+....",
+"....+@@@@@@@+...",
+"...+@@@@@@@@@+..",
+"..++++@@@@@++++.",
+".....+@@@@@+....",
+".....+@@@@@+....",
+".....+@@@@@+....",
+".....+@@@@@+....",
+".....+@@@@@+....",
+".....+++++++....",
+"................"};
diff --git a/include/xpm/update.xpm b/include/xpm/update.xpm
new file mode 100644
index 0000000..5ee1dd6
--- /dev/null
+++ b/include/xpm/update.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *update_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #00007F",
+"                ",
+"                ",
+"      ....      ",
+"     .    .     ",
+"    .   .....   ",
+"    .    ...    ",
+"          .     ",
+"                ",
+"                ",
+"     .          ",
+"    ...    .    ",
+"   .....   .    ",
+"     .    .     ",
+"      ....      ",
+"                ",
+"                "};
diff --git a/include/xpm/vect.xpm b/include/xpm/vect.xpm
new file mode 100644
index 0000000..7d91322
--- /dev/null
+++ b/include/xpm/vect.xpm
@@ -0,0 +1,60 @@
+/* XPM */
+static const char * vect_xpm[] = {
+"16 16 41 1",
+" 	c None",
+".	c #B3FF00",
+"+	c #AEF900",
+"@	c #FBF400",
+"#	c #FEF700",
+"$	c #FFDA00",
+"%	c #AFFB00",
+"&	c #FDF600",
+"*	c #FDF500",
+"=	c #FD9600",
+"-	c #FD9000",
+";	c #FA8F00",
+">	c #FEAB00",
+",	c #FD9500",
+"'	c #FB9400",
+")	c #FE9100",
+"!	c #FBAA00",
+"~	c #FCA900",
+"{	c #FF9700",
+"]	c #FF9200",
+"^	c #FDA900",
+"/	c #FDAB00",
+"(	c #FB9D00",
+"_	c #FC0B00",
+":	c #FF0A00",
+"<	c #FF4400",
+"[	c #FB4200",
+"}	c #FC9E00",
+"|	c #FE9F00",
+"1	c #FD4400",
+"2	c #FC4400",
+"3	c #FFA000",
+"4	c #FB1600",
+"5	c #FCAD00",
+"6	c #D00000",
+"7	c #D20000",
+"8	c #FD1500",
+"9	c #FA1500",
+"0	c #FEAF00",
+"a	c #D10000",
+"b	c #FDAE00",
+" .+    @#     $ ",
+" %     &@     $ ",
+".      &        ",
+"      *         ",
+"  =     -;     >",
+" ,'     )     !~",
+"{      ]      ^ ",
+"      ]      /  ",
+"               (",
+" _:     <[    }|",
+" _     12     3 ",
+"      <      |  ",
+"                ",
+"         4     5",
+" 67     89    50",
+"a     8      b  "};
diff --git a/include/xpm/window.xpm b/include/xpm/window.xpm
new file mode 100644
index 0000000..28ac182
--- /dev/null
+++ b/include/xpm/window.xpm
@@ -0,0 +1,29 @@
+/* XPM */
+static const char * window_xpm[] = {
+"16 16 10 1",
+" 	c None",
+".	c #000000",
+"+	c #333377",
+"@	c #FFFFFF",
+"#	c #777777",
+"$	c #00007F",
+"%	c #4444FF",
+"&	c #FF0000",
+"*	c #007F00",
+"=	c #7F0000",
+"                ",
+"                ",
+"..............  ",
+".++++++++++++.  ",
+".@@@@@#@@@@@@.  ",
+".@$.............",
+".@@.%%%%%%%%%%%.",
+".@$.@@@@@#@@@@@.",
+".@@.@$$@@#@@@@@.",
+".@$.@@@@@#@@@@@.",
+".@@.@$&*@#@@@@@.",
+"....@@@@@#@@@@@.",
+"   .@$&=@#@@@@@.",
+"   .@@@@@#@@@@@.",
+"   .............",
+"                "};
diff --git a/include/xpm/wire.xpm b/include/xpm/wire.xpm
new file mode 100644
index 0000000..b67d50b
--- /dev/null
+++ b/include/xpm/wire.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * wire_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"     .    .     ",
+"     .    .     ",
+"     .    .     ",
+"  ............  ",
+"     .    .     ",
+"     .    .     ",
+"     .    .     ",
+"     .    .     ",
+"  ............  ",
+"     .    .     ",
+"     .    .     ",
+"     .    .     ",
+"                "};
diff --git a/include/xpm/zoom_1.xpm b/include/xpm/zoom_1.xpm
new file mode 100644
index 0000000..c6015ea
--- /dev/null
+++ b/include/xpm/zoom_1.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * zoom_1_xpm[] = {
+"16 16 3 1",
+".	c None",
+"+	c #7F0000",
+"@	c #FF0000",
+"................",
+"................",
+"......++++......",
+"......+@@+......",
+"......+@@+......",
+"......+@@+......",
+"......+@@+......",
+".++++++@@++++++.",
+".+@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@+.",
+".++++++@@++++++.",
+"......+@@+......",
+"......+@@+......",
+"......+@@+......",
+"......+@@+......",
+"......++++......"};
diff --git a/include/xpm/zoom_in.xpm b/include/xpm/zoom_in.xpm
new file mode 100644
index 0000000..22e285b
--- /dev/null
+++ b/include/xpm/zoom_in.xpm
@@ -0,0 +1,124 @@
+/* XPM */
+static const char * zoom_in_xpm[] = {
+"16 16 105 2",
+"  	c None",
+". 	c #878B87",
+"+ 	c #868C8A",
+"@ 	c #888B89",
+"# 	c #ACB6BF",
+"$ 	c #CDD6DD",
+"% 	c #E4E7E9",
+"& 	c #929594",
+"* 	c #CFD8E0",
+"= 	c #D3DDE5",
+"- 	c #A4BFDC",
+"; 	c #99B9DA",
+"> 	c #9AB9DA",
+", 	c #A4BFDD",
+"' 	c #CFDAE5",
+") 	c #B4C9DF",
+"! 	c #9DBDDD",
+"~ 	c #B5CDE6",
+"{ 	c #5C84B8",
+"] 	c #5B84B8",
+"^ 	c #B0CAE4",
+"/ 	c #9ABADD",
+"( 	c #98B9DC",
+"_ 	c #BCD1E8",
+": 	c #5F87B9",
+"< 	c #FFFFFF",
+"[ 	c #5A84B7",
+"} 	c #ABC6E2",
+"| 	c #91B4DA",
+"1 	c #868C8B",
+"2 	c #9DBBDA",
+"3 	c #B6CDE6",
+"4 	c #5D85B8",
+"5 	c #5E86B8",
+"6 	c #5982B7",
+"7 	c #5781B6",
+"8 	c #9FBDDE",
+"9 	c #9EBBDA",
+"0 	c #878B88",
+"a 	c #8EB2D6",
+"b 	c #5983B7",
+"c 	c #507DB4",
+"d 	c #86ACD4",
+"e 	c #89AED4",
+"f 	c #4E7BB3",
+"g 	c #4A78B2",
+"h 	c #878C8B",
+"i 	c #CFD8DE",
+"j 	c #A7C1DD",
+"k 	c #86ADD6",
+"l 	c #4F7CB3",
+"m 	c #89AED6",
+"n 	c #A9C3DE",
+"o 	c #D0D8DE",
+"p 	c #888B87",
+"q 	c #B1BAC1",
+"r 	c #D9E1E8",
+"s 	c #94B6DA",
+"t 	c #96B7DB",
+"u 	c #527EB5",
+"v 	c #537EB5",
+"w 	c #97B8DB",
+"x 	c #DAE2E8",
+"y 	c #B2BBC1",
+"z 	c #8A8C8A",
+"A 	c #D7DDE2",
+"B 	c #CAD8E6",
+"C 	c #A4C0DF",
+"D 	c #A6C2E0",
+"E 	c #A7C3E1",
+"F 	c #D8DEE3",
+"G 	c #949895",
+"H 	c #DADFE3",
+"I 	c #E1E6EA",
+"J 	c #C7D7E8",
+"K 	c #BDD2E6",
+"L 	c #BED2E6",
+"M 	c #C8D8E8",
+"N 	c #DFE5EA",
+"O 	c #DBE0E4",
+"P 	c #959896",
+"Q 	c #9DA09B",
+"R 	c #60625F",
+"S 	c #8A8D8A",
+"T 	c #BCC1C4",
+"U 	c #DCE0E2",
+"V 	c #E9EBEB",
+"W 	c #BDC2C5",
+"X 	c #898C88",
+"Y 	c #878A84",
+"Z 	c #B9BCB6",
+"` 	c #BDBFBC",
+" .	c #61635F",
+"..	c #8A8C88",
+"+.	c #8D918D",
+"@.	c #8B8D89",
+"#.	c #8E918D",
+"$.	c #575955",
+"%.	c #7A7B78",
+"&.	c #B7B8B6",
+"*.	c #595B57",
+"=.	c #555753",
+"-.	c #767873",
+";.	c #A0A29F",
+">.	c #565854",
+"        . + . . + .             ",
+"      @ # $ % % $ # @           ",
+"    & * = - ; > , ' * &         ",
+"  @ * ) ! ~ { ] ^ / ) * @       ",
+". # ' ( _ : < < [ } | ' # .     ",
+"1 $ 2 3 4 5 < < 6 7 8 9 $ +     ",
+"0 % a b < < < < < < c d % .     ",
+"0 % e f < < < < < < g e % .     ",
+"h i j k f f < < l f m n o h     ",
+"p q r s t u < < v ( w x y p     ",
+"  z A B C D 7 7 E D B F .       ",
+"    G H I J K L M N O P Q R     ",
+"      S T U V V U W X Y Z `  .  ",
+"        ..+. at .@.#...  $.%.Y &.*.",
+"                        =.-.;.*.",
+"                          =.>.  "};
diff --git a/include/xpm/zoom_out.xpm b/include/xpm/zoom_out.xpm
new file mode 100644
index 0000000..82b040e
--- /dev/null
+++ b/include/xpm/zoom_out.xpm
@@ -0,0 +1,130 @@
+/* XPM */
+static const char * zoom_out_xpm[] = {
+"16 16 111 2",
+"  	c None",
+". 	c #878B87",
+"+ 	c #868C8A",
+"@ 	c #888B89",
+"# 	c #ACB6BF",
+"$ 	c #CDD6DD",
+"% 	c #E4E7E9",
+"& 	c #929594",
+"* 	c #CFD8E0",
+"= 	c #D3DDE5",
+"- 	c #A4BFDC",
+"; 	c #99B9DA",
+"> 	c #9AB9DA",
+", 	c #A4BFDD",
+"' 	c #CFDAE5",
+") 	c #B4C9DF",
+"! 	c #9DBDDD",
+"~ 	c #B5CDE6",
+"{ 	c #5C84B8",
+"] 	c #5B84B8",
+"^ 	c #B0CAE4",
+"/ 	c #9ABADD",
+"( 	c #98B9DC",
+"_ 	c #BCD1E8",
+": 	c #5F87B9",
+"< 	c #FFFFFF",
+"[ 	c #5A84B7",
+"} 	c #ABC6E2",
+"| 	c #91B4DA",
+"1 	c #868C8B",
+"2 	c #9DBBDA",
+"3 	c #B6CDE6",
+"4 	c #5D85B8",
+"5 	c #5982B7",
+"6 	c #A7C3E1",
+"7 	c #9FBDDE",
+"8 	c #9EBBDA",
+"9 	c #878B88",
+"0 	c #8EB2D6",
+"a 	c #5A83B7",
+"b 	c #5681B6",
+"c 	c #9EBDDE",
+"d 	c #86ACD4",
+"e 	c #89AED4",
+"f 	c #8AAFD7",
+"g 	c #94B6DB",
+"h 	c #547FB5",
+"i 	c #507DB4",
+"j 	c #85ACD5",
+"k 	c #7BA5D2",
+"l 	c #878C8B",
+"m 	c #CFD8DE",
+"n 	c #A7C1DD",
+"o 	c #86ADD6",
+"p 	c #89AED6",
+"q 	c #4E7BB3",
+"r 	c #4F7CB3",
+"s 	c #8BB0D7",
+"t 	c #A9C3DE",
+"u 	c #D0D8DE",
+"v 	c #888B87",
+"w 	c #B1BAC1",
+"x 	c #D9E1E8",
+"y 	c #94B6DA",
+"z 	c #96B7DB",
+"A 	c #527EB5",
+"B 	c #537EB5",
+"C 	c #97B8DB",
+"D 	c #DAE2E8",
+"E 	c #B2BBC1",
+"F 	c #8A8C8A",
+"G 	c #D7DDE2",
+"H 	c #CAD8E6",
+"I 	c #A4C0DF",
+"J 	c #A6C2E0",
+"K 	c #5781B6",
+"L 	c #D8DEE3",
+"M 	c #949895",
+"N 	c #DADFE3",
+"O 	c #E1E6EA",
+"P 	c #C7D7E8",
+"Q 	c #BDD2E6",
+"R 	c #BED2E6",
+"S 	c #C8D8E8",
+"T 	c #DFE5EA",
+"U 	c #DBE0E4",
+"V 	c #959896",
+"W 	c #9DA09B",
+"X 	c #60625F",
+"Y 	c #8A8D8A",
+"Z 	c #BCC1C4",
+"` 	c #DCE0E2",
+" .	c #E9EBEB",
+"..	c #BDC2C5",
+"+.	c #898C88",
+"@.	c #878A84",
+"#.	c #B9BCB6",
+"$.	c #BDBFBC",
+"%.	c #61635F",
+"&.	c #8A8C88",
+"*.	c #8D918D",
+"=.	c #8B8D89",
+"-.	c #8E918D",
+";.	c #575955",
+">.	c #7A7B78",
+",.	c #B7B8B6",
+"'.	c #595B57",
+").	c #555753",
+"!.	c #767873",
+"~.	c #A0A29F",
+"{.	c #565854",
+"        . + . . + .             ",
+"      @ # $ % % $ # @           ",
+"    & * = - ; > , ' * &         ",
+"  @ * ) ! ~ { ] ^ / ) * @       ",
+". # ' ( _ : < < [ } | ' # .     ",
+"1 $ 2 3 4 < < < 5 6 7 8 $ +     ",
+"9 % 0 ^ [ a < < b c | d % .     ",
+"9 % e f g h < < i j k e % .     ",
+"l m n o p q < < r s p t u l     ",
+"v w x y z A < < B ( C D E v     ",
+"  F G H I J K K 6 J H L .       ",
+"    M N O P Q R S T U V W X     ",
+"      Y Z `  . .` ..+. at .#.$.%.  ",
+"        &.*.=.=.-.&.  ;.>. at .,.'.",
+"                        ).!.~.'.",
+"                          ).{.  "};
diff --git a/json/Backend.cpp b/json/Backend.cpp
new file mode 100644
index 0000000..0ef1541
--- /dev/null
+++ b/json/Backend.cpp
@@ -0,0 +1,90 @@
+#include <QMessageBox>
+#include <QTextStream>
+#include <QFile>
+#include <QDebug>
+#include "Backend.hpp"
+#include <mgl2/mgl.h>
+#undef sprintf	// fix libintl bug of defining sprintf
+//-----------------------------------------------------------------------------
+Backend::Backend(QObject *parent) : QObject(parent) { }
+//-----------------------------------------------------------------------------
+QString Backend::show(const QString& text) const
+{
+	qDebug() << __FUNCTION__;
+	const char *tmp = tmpnam(0);
+	wchar_t *wtext;
+	mglGraph gr;
+	gr.SetFaceNum(200);
+	mglParse pr;
+	pr.AllowSetSize(true);
+	setlocale(LC_ALL, "");	setlocale(LC_NUMERIC, "C");
+	wtext = new wchar_t[text.size()+1];
+	text.toWCharArray(wtext);
+	wtext[text.size()] = 0;
+	pr.Execute(&gr,wtext);
+	delete[] wtext;
+	gr.WriteJSON(tmp);
+	setlocale(LC_NUMERIC, "");
+
+	QFile f(tmp);
+	f.open(QIODevice::ReadOnly);
+	QTextStream ts(&f);
+	ts.setAutoDetectUnicode(true);
+	const QString json = ts.readAll();
+	f.remove();
+	return json;
+}
+//-----------------------------------------------------------------------------
+QString Backend::coor(const QString& xy, const QString& text) const
+{
+	wchar_t *wtext;
+	qDebug() << __FUNCTION__;
+	mglGraph gr;
+	mglParse pr;
+	pr.AllowSetSize(true);
+	setlocale(LC_ALL, "");	setlocale(LC_NUMERIC, "C");
+	wtext = new wchar_t[text.size()+1];
+	text.toWCharArray(wtext);
+	wtext[text.size()] = 0;
+	pr.Execute(&gr,wtext);
+	delete[] wtext;
+	gr.Finish();
+
+	int x = (int)xy.section(" ",0,0).toDouble();
+	int y = (int)xy.section(" ",1,1).toDouble();
+	mglPoint p = gr.CalcXYZ(x,y);
+	QString res;
+	res.sprintf("x = %g, y = %g, z = %g for point (%d, %d)\n", p.x, p.y, p.z, x,y);
+	qDebug() << res+"\nask"+xy;
+	return res+"\nask"+xy;
+}
+//-----------------------------------------------------------------------------
+QString Backend::geometry(const QString& mgl) const
+{
+	qDebug() << __FUNCTION__;
+	const char *tmp = tmpnam(0);
+	wchar_t *wmgl;
+	mglGraph gr;
+#if 0
+	gr.SetFaceNum(200);
+#endif
+	mglParse pr;
+	pr.AllowSetSize(true);
+	setlocale(LC_ALL, "");	setlocale(LC_NUMERIC, "C");
+	wmgl = new wchar_t[mgl.size()+1];
+	mgl.toWCharArray(wmgl);
+	wmgl[mgl.size()] = 0;
+	pr.Execute(&gr,wmgl);
+	delete[] wmgl;
+	gr.WriteJSON(tmp);
+	setlocale(LC_NUMERIC, "");
+
+	QFile f(tmp);
+	f.open(QIODevice::ReadOnly);
+	QTextStream ts(&f);
+	ts.setAutoDetectUnicode(true);
+	const QString json = ts.readAll();
+	f.remove();
+	return json;
+}
+//-----------------------------------------------------------------------------
diff --git a/json/Backend.hpp b/json/Backend.hpp
new file mode 100644
index 0000000..3ebb08e
--- /dev/null
+++ b/json/Backend.hpp
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <QObject>
+#include <QStringList>
+#if defined(_MSC_VER)
+#include <mgl2/define.h>
+#endif
+
+class Backend : public QObject
+{
+	Q_OBJECT
+
+public:
+	explicit Backend(QObject *parent = 0);
+
+public:
+//	Q_INVOKABLE QString join(const QStringList list) const;
+	Q_INVOKABLE QString show(const QString& text) const;
+	Q_INVOKABLE QString coor(const QString& xy, const QString& text) const;
+	Q_INVOKABLE QString geometry(const QString& mgl) const;
+};
+
diff --git a/json/CMakeLists.txt b/json/CMakeLists.txt
new file mode 100644
index 0000000..be5b12c
--- /dev/null
+++ b/json/CMakeLists.txt
@@ -0,0 +1,54 @@
+if(enable-qt5)
+	include(../cmake-qt5.txt)
+
+	find_qt5_libs(OFF ON Network)
+	if(TARGET Qt5::Network)
+		set(MGL_QT5_LIBS ${MGL_QT5_LIBS} Qt5::Network)
+		find_qt5_libs(OFF OFF WebKitWidgets WebEngineWidgets)
+		if(enable-json-sample-we)
+			if(TARGET Qt5::WebEngineWidgets)
+				set(MGL_QT5_LIBS ${MGL_QT5_LIBS} Qt5::WebEngineWidgets)
+				set(mgl_qt_def MGL_USE_QT5_WE)
+			else(TARGET Qt5::WebEngineWidgets)
+				message(STATUS "Couldn't find Qt5 WebEngineWidgets library. Trying WebKit.")
+				set(enable-json-sample-we OFF)
+			endif(TARGET Qt5::WebEngineWidgets)
+		endif(enable-json-sample-we)
+		if(TARGET Qt5::WebKitWidgets)
+			set(MGL_QT5_LIBS ${MGL_QT5_LIBS} Qt5::WebKitWidgets)
+		else(TARGET Qt5::WebKitWidgets)
+			message(STATUS "Couldn't find Qt5 WebKitWidgets library. JSON sample disabled.")
+			set(enable-json-sample OFF)
+		endif(TARGET Qt5::WebKitWidgets)
+	else(TARGET Qt5::Network)
+		message(STATUS "Couldn't find Qt5 Network library. JSON sample disabled.")
+		set(enable-json-sample OFF)
+	endif(TARGET Qt5::Network)
+else(enable-qt5)
+	include(../cmake-qt4.txt)
+
+	foreach(mgl_qt4_lib ${MGL_QT4_LIBS_FIND_JSON})
+		if(TARGET Qt4::${mgl_qt4_lib})
+			set(MGL_QT4_LIBS ${MGL_QT4_LIBS} Qt4::${mgl_qt4_lib})
+		else(TARGET Qt4::${mgl_qt4_lib})
+			message(STATUS "Couldn't find Qt4 ${mgl_qt4_lib} library. JSON sample disabled.")
+			set(enable-json-sample OFF)
+		endif(TARGET Qt4::${mgl_qt4_lib})
+	endforeach(mgl_qt4_lib)
+endif(enable-qt5)
+
+if(enable-json-sample)
+
+set(json_src Backend.cpp MainWindow.cpp MainWindow.ui)
+set(json_moc_hdr Backend.hpp MainWindow.hpp)
+
+include_directories(${MathGL2_BINARY_DIR}/json)
+add_executable(MglForJsTestBench ${json_src} ${json_moc_hdr})
+if(enable-qt5)
+	target_compile_definitions(MglForJsTestBench PUBLIC MGL_USE_QT5 ${mgl_qt_def})
+	target_link_libraries(MglForJsTestBench mgl-qt5 ${MGL_QT5_LIBS})
+else(enable-qt5)
+	target_link_libraries(MglForJsTestBench mgl-qt4 ${MGL_QT4_LIBS})
+endif(enable-qt5)
+
+endif(enable-json-sample)
diff --git a/json/MainWindow.cpp b/json/MainWindow.cpp
new file mode 100644
index 0000000..748251d
--- /dev/null
+++ b/json/MainWindow.cpp
@@ -0,0 +1,55 @@
+#include "MainWindow.hpp"
+#include "ui_MainWindow.h"
+#include "mgl2/config.h"
+
+#include <QWebFrame>
+#include <QNetworkDiskCache>
+#include <QDesktopServices>
+//-----------------------------------------------------------------------------
+int main(int argc, char *argv[])
+{
+	QApplication a(argc, argv);
+	MainWindow w;
+	w.show();
+	return a.exec();
+}
+//-----------------------------------------------------------------------------
+MainWindow::MainWindow(QWidget* const parent) : QMainWindow(parent), ui(new Ui::MainWindow)
+{
+	ui->setupUi(this);
+
+	// configure webkit
+	QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
+	QWebSettings::globalSettings()->setAttribute(QWebSettings::JavascriptEnabled, true);
+	QWebSettings::globalSettings()->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, true);
+	QWebSettings::globalSettings()->setAttribute(QWebSettings::LocalContentCanAccessFileUrls, true);
+	QWebSettings::globalSettings()->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, true);
+	QWebSettings::globalSettings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, true);
+	QWebSettings::globalSettings()->setAttribute(QWebSettings::JavascriptCanAccessClipboard, true);
+
+	// create non-cached QNetworkAccessManager and assign to webview
+	QNetworkAccessManager* manager = new QNetworkAccessManager(this);
+	QNetworkDiskCache* diskCache = new QNetworkDiskCache();
+#ifdef MGL_USE_QT5
+	const QString location = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
+#else
+	const QString location = QDesktopServices::storageLocation(QDesktopServices::CacheLocation);
+#endif
+	diskCache->setCacheDirectory(location);
+	diskCache->setMaximumCacheSize(0);
+	manager->setCache(diskCache);
+	ui->webView->page()->setNetworkAccessManager(manager);
+
+	// inject backend object each time javascript object is cleared
+	connect(ui->webView->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(injectBackendObject()));
+	// set url to load
+	ui->webView->load(QUrl(QString("file:///%1/../../json/%2").arg(qApp->applicationDirPath()).arg("index.html")));
+}
+//-----------------------------------------------------------------------------
+void MainWindow::injectBackendObject()
+{
+	ui->webView->page()->mainFrame()->addToJavaScriptWindowObject("globalBackend", &_backend);
+}
+//-----------------------------------------------------------------------------
+MainWindow::~MainWindow()	{	delete ui;	}
+//-----------------------------------------------------------------------------
diff --git a/json/MainWindow.hpp b/json/MainWindow.hpp
new file mode 100644
index 0000000..6aa46f0
--- /dev/null
+++ b/json/MainWindow.hpp
@@ -0,0 +1,23 @@
+#pragma once
+
+#include "Backend.hpp"
+#include <QMainWindow>
+//#include <QObject>
+
+namespace Ui {	class MainWindow;	}
+
+class MainWindow : public QMainWindow {
+	Q_OBJECT
+
+public:
+	explicit MainWindow(QWidget *parent = 0);
+	~MainWindow();
+
+private slots:
+	void injectBackendObject();
+
+private:
+	Ui::MainWindow *ui;
+	Backend _backend;
+};
+
diff --git a/json/MainWindow.ui b/json/MainWindow.ui
new file mode 100644
index 0000000..e808739
--- /dev/null
+++ b/json/MainWindow.ui
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>850</width>
+    <height>650</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>MainWindow</string>
+  </property>
+  <widget class="QWidget" name="centralWidget">
+   <layout class="QGridLayout" name="gridLayout">
+    <item row="0" column="0">
+     <layout class="QVBoxLayout" name="verticalLayout">
+      <item>
+       <widget class="QWebView" name="webView">
+        <property name="url">
+         <url>
+          <string>about:blank</string>
+         </url>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <customwidgets>
+  <customwidget>
+   <class>QWebView</class>
+   <extends>QWidget</extends>
+   <header>QtWebKit/QWebView</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/json/RotationExample.py b/json/RotationExample.py
new file mode 100644
index 0000000..85e2a44
--- /dev/null
+++ b/json/RotationExample.py
@@ -0,0 +1,25 @@
+"""
+.. versionadded:: 1.1.0
+   This demo depends on new features added to contourf3d.
+"""
+
+from mpl_toolkits.mplot3d import axes3d
+import matplotlib.pyplot as plt
+
+fig = plt.figure()
+ax = fig.gca(projection='3d')
+X, Y, Z = axes3d.get_test_data(0.05)
+ax.plot_surface(X, Y, Z, rstride=8, cstride=8, alpha=0.3)
+cset = ax.contourf(X, Y, Z, zdir='z', offset=-100)
+cset = ax.contourf(X, Y, Z, zdir='x', offset=-40)
+cset = ax.contourf(X, Y, Z, zdir='y', offset=40)
+
+ax.set_xlabel('X')
+ax.set_xlim(-40, 40)
+ax.set_ylabel('Y')
+ax.set_ylim(-40, 40)
+ax.set_zlabel('Z')
+ax.set_zlim(-100, 100)
+
+plt.show()
+
diff --git a/json/index.html b/json/index.html
new file mode 100644
index 0000000..2bcda48
--- /dev/null
+++ b/json/index.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+  <script type="text/javascript" src="sylvester.src.js"></script>
+  <script type="text/javascript" src="mathgl.js"></script>
+  <script type="text/javascript" src="mathgl.View.js"></script>
+  <script type="text/javascript" src="mathgl.Backend.js"></script>
+  <script type="text/javascript" src="mathgl.WebkitBackend.js"></script>
+  <script type="text/javascript" src="mathgl.Graph.js"></script>
+  <script type="text/javascript" src="main.js"></script>
+</head>
+
+<body onload="main();">
+  <center>
+    <button type="button" onclick="graph.moveLeft()">Left</button>
+    <button type="button" onclick="graph.moveUp()">Up</button>
+    <button type="button" onclick="graph.zoomIn()">Zoom in</button>
+    <button type="button" onclick="graph.zoomOut()">Zoom out</button>
+    <button type="button" onclick="graph.moveDown()">Down</button>
+    <button type="button" onclick="graph.moveRight()">Right</button><br>
+    <canvas id="canvas" width="800" height="600" style="border:1px solid #d3d3d3;">
+    </canvas>
+  </center>
+</body>
+</html>
diff --git a/json/main.js b/json/main.js
new file mode 100644
index 0000000..3c78b78
--- /dev/null
+++ b/json/main.js
@@ -0,0 +1,38 @@
+var graph;
+
+/**
+ * Entry function.
+ */
+var main = function() {
+  // get canvas to work over from the DOM
+  var canvas = document.getElementById("canvas");
+
+  // get backend injected by from C++ side just to illustrate where it came from
+  // in normal web application it shall be implemented using some transport protocol
+  var backend = new mathgl.WebkitBackend();
+
+  // instantiate mathgl graph instance connecting it with canvas and backend
+  graph = new mathgl.Graph(canvas, backend);
+  graph.setBackgroundFillStyle("#F0F0F0");
+  // initialize it by some sample MGL script
+  graph.loadGeometry(makeSampleScript(),null);
+  graph.setPerspective(0.5);
+}
+
+
+//var script = "rotate 40 60:fsurf 'sin(2*pi*x*y)'\nbox:axis:fplot 'sin(2*pi*t)' 'cos(2*pi*t)' '2*t-1' 'm2o'";
+//var script = "box:axis:fplot 'sin(pi*x)'";
+//var script = "rotate 10 20: box:axis:fsurf 'sin(pi*x*y)'";
+
+var makeSampleScript = function() {
+//	var mgl = "fsurf 'x' 'rgb';value 4";
+
+	var mgl = "origintick off\n";
+	mgl += "title 'qqq' '@k':ranges -2 2 -2 2 -2 2:colorbar '>'\n"   // NOTE: Ranges MUST BE specified for correctly work of zoomaxis feature
+	mgl += "facenum 50:";
+//	mgl += "origin 0 0 0:axis :xlabel 'xxxx':ylabel 'yyyy':zlabel 'zzzz':"
+	mgl += "axis :xlabel 'xxxx':ylabel 'yyyy':zlabel 'zzzz':"
+	mgl += "box:fplot 'sin(x^2)'\n";   // This is just for testing zoomaxis features
+	mgl += "text 0 0 'aaa'";
+	return mgl;
+}
diff --git a/json/mathgl.Backend.js b/json/mathgl.Backend.js
new file mode 100644
index 0000000..69ace4e
--- /dev/null
+++ b/json/mathgl.Backend.js
@@ -0,0 +1,13 @@
+/**
+ * Backend interface. The only responsibility its successors is to return geometry object by given MGL script.
+ */
+
+/** constructor */
+mathgl.Backend = function() {}
+
+/**
+ * Request for geometry data for given MGL script.
+ * @param mgl {String} MGL script to build geometry
+ * @param callback {Function} receiver of geometry must be a function(error, result)
+ */
+mathgl.Backend.prototype.geometry = function(mgl, callback) { throw new Error("abstract method invoked"); }
diff --git a/json/mathgl.Graph.js b/json/mathgl.Graph.js
new file mode 100644
index 0000000..22c8660
--- /dev/null
+++ b/json/mathgl.Graph.js
@@ -0,0 +1,750 @@
+/**
+ * Graph - main MathGL class.
+ */
+
+/**
+ * Constructor - create graph attached to specified canvas and working over provided backend.
+ * @param backend {mathgl.Backend} implementation of backend interface
+ * @param canvas {Canvas} canvas to plot graph on
+ */
+mathgl.Graph = function(canvas, backend) {
+	this.__backend = backend;
+	this.__canvas = canvas;
+	this.__view = null;
+	this.__geometry = null;
+	// indicate whether rendering handlers are in the event queue
+	this.__isDraftRenderingInScheduled = false;
+	this.__isPreciseRenderingScheduled = false;
+	// draft rendering finished timestamp
+	this.__draftFinishedTimestamp = new Date();
+	this.__backgroundFillStyle = '#EEEEFF';
+	this.__preciseRenderingDelay = 700;
+
+	this.__maxDraftPoints = 30000;
+	this.__asp_scl=0;	// inertia of aspect scaling
+	this.__fov = 0;		// perspective
+	this.__x1 = 0;	this.__y1 = 0;	this.__z1 = 0;
+	this.__x2 = 1;	this.__y2 = 1;	this.__z2 = 1;
+	this.__activeTimeoutHandlers = [];
+
+  // create view
+  this.__view = new mathgl.View();
+  // connect method which starts rendering to view object
+  this.__view.setRenderLauncher(mathgl.bind(this.__renderStart, this));
+  // connect pick point handler
+  this.__view.setPickPointHandler(mathgl.bind(this.__pickPointHandler, this));
+  // attach canvas to view
+  this.__view.attachCanvas(this.__canvas);
+};
+
+
+/**
+ * Method uses to wrap native JS setTimeout function to make possible deactivate active callbacks in destroy method
+ *
+ * @param func {Function} Callback function, will be executed after delay
+ * @param delay {Number} Delay before callback call
+ */
+mathgl.Graph.prototype.__setTimeout = function(func, delay) {
+	var me = this;
+	var timeoutFunc = function() {
+		func.call();
+		var index = me.__activeTimeoutHandlers.indexOf(this.setTimeoutId);
+		if (index > -1) {
+			// remove timeout from activeTimeoutHandlers list
+			me.__activeTimeoutHandlers.splice(index, 1);
+		}
+	}
+
+	var timeoutId = setTimeout(mathgl.bind(timeoutFunc, timeoutFunc), delay);
+	// keep timeout handler inside function
+	timeoutFunc.setTimeoutId = timeoutId;
+	this.__activeTimeoutHandlers.push(timeoutId);
+};
+
+/**
+ * Load graph state from JSON string.
+ * @param json {String} string in JSON format with previously saved state
+ */
+mathgl.Graph.prototype.load = function(json) {
+	throw new Error("TODO");
+}
+
+
+/**
+ * Save current graph state to JSON string.
+ * @return {String} state serialized to JSON string
+ */
+mathgl.Graph.prototype.save = function() {
+	throw new Error("TODO");
+}
+
+
+/**
+ * background fill style setter
+ * @param fillStyle something that will be accepted by canvas' 2d context as fill style, e.g. color, gradient, pattern.
+ */
+mathgl.Graph.prototype.setBackgroundFillStyle = function(fillStyle) {
+	this.__backgroundFillStyle = fillStyle;
+}
+
+
+/** @return background fill style */
+mathgl.Graph.prototype.backgroundFillStyle = function() {
+	return this.__backgroundFillStyle;
+}
+
+
+/** called when user picks the point on the graph, point shall be somehow displayed/highlighted */
+mathgl.Graph.prototype.__pickPointHandler = function(x, y) {
+	var obj = this.__geometry;
+	var xy = x*obj.width/this.__canvas.width + " " + y*obj.height/this.__canvas.height;
+	// introduce zoom and view coomand for server side
+	var zoom = "zoom "+(0.5-obj.pf/2)+" "+(0.5-obj.pf/2)+" "+(0.5+obj.pf/2)+" "+(0.5+obj.pf/2)+"\n";
+	var view1 = "view 0 "+this.__view.__pitch*180/Math.PI+" 0"+"\n";
+	var view2 = "view 0 0 "+(-this.__view.__yaw)*180/Math.PI+"\n";
+	var persp = "perspective "+(-this.__fov)+"\n";
+	// now ask server side for proper coordinates
+	var res = this.__backend.coor(xy, zoom+view1+view2+persp+obj.mgl);
+}
+
+
+/** called when user shift axis range */
+mathgl.Graph.prototype.shiftAxis = function(x, y, z) {
+	var dx = x*(this.__x2-this.__x1), dy = y*(this.__y2-this.__y1), dz = z*(this.__z2-this.__z1)
+	this.__x1 += dx; this.__x2 += dx;
+	this.__y1 += dy; this.__y2 += dy;
+	this.__z1 += dz; this.__z2 += dz;
+	// introduce zoomaxis coomand for server side
+	var zoom = "zoomaxis "+this.__x1+" "+this.__y1+" "+this.__z1+" "+this.__x2+" "+this.__y2+" "+this.__z2+"\n";
+
+  this.loadGeometry(zoom + this.__geometry.mgl);
+}
+
+
+/** called when user shift axis range */
+mathgl.Graph.prototype.zoomAxis = function(factor) {
+	var d, c;
+	d=(this.__x2-this.__x1)*factor/2; c=(this.__x2+this.__x1)/2;
+	this.__x1 = c-d; this.__x2 = c+d;
+	d=(this.__y2-this.__y1)*factor/2; c=(this.__y2+this.__y1)/2;
+	this.__y1 = c-d; this.__y2 = c+d;
+	d=(this.__z2-this.__z1)*factor/2; c=(this.__z2+this.__z1)/2;
+	this.__z1 = c-d; this.__z2 = c+d;
+	// introduce zoomaxis coomand for server side
+	var zoom = "zoomaxis "+this.__x1+" "+this.__y1+" "+this.__z1+" "+this.__x2+" "+this.__y2+" "+this.__z2+"\n";
+
+  this.loadGeometry(zoom + this.__geometry.mgl);
+}
+
+
+/** initiate the chains of rendering the geometry to the canvas */
+mathgl.Graph.prototype.__renderStart = function() {
+	// do nothing if processing is already started or no geometry
+	if (!this.__isDraftRenderingInScheduled && this.__geometry) {
+		// enqueue draft rendering step
+		this.__isDraftRenderingInScheduled = true;
+		this.__setTimeout(mathgl.bind(this.__renderDraft, this), 0);
+	}
+}
+
+
+/** draft rendering */
+mathgl.Graph.prototype.__renderDraft = function() {
+	this.__drawMesh(false);
+	this.__isDraftRenderingInScheduled = false;
+
+	// enqueue precise rendering step
+	if (!this.__isPreciseRenderingScheduled) {
+		this.__isPreciseRenderingScheduled = true;
+		this.__setTimeout(mathgl.bind(this.__renderPrecise, this), this.__preciseRenderingDelay);
+	}
+	this.__draftFinishedTimestamp = new Date();
+}
+
+
+/** precise rendering */
+mathgl.Graph.prototype.__renderPrecise = function() {
+	// do nothing if draft rendering is scheduled
+	if (this.__isDraftRenderingInScheduled) {
+		this.__isPreciseRenderingScheduled = false;
+		return;
+	}
+
+	// check that enough time has passed since last occurance of draft rendering finished
+	// rechedule pricese rendering if it is not
+	var current = new Date();
+	if (current - this.__draftFinishedTimestamp < this.__preciseRenderingDelay) {
+		this.__setTimeout(mathgl.bind(this.__renderPrecise, this), this.__preciseRenderingDelay - (current - this.__draftFinishedTimestamp));
+		return;
+	}
+	this.__drawMesh(true);
+	this.__isPreciseRenderingScheduled = false;
+}
+
+
+/** fill canvas background */
+mathgl.Graph.prototype.__drawBackground = function() {
+	var c = this.__canvas.getContext("2d");
+	var h = this.__canvas.height;
+	var w = this.__canvas.width;
+	c.fillStyle = this.__backgroundFillStyle;
+	c.fillRect(0, 0 , w, h);
+}
+
+
+/** auxiliary function to draw mesh */
+mathgl.Graph.prototype.__drawMesh = function(isPrecise) {
+	var c = this.__canvas.getContext("2d");
+	var m = this.__view.viewMatrix().inverse();
+//	var vvv = $M([[1,0,0,1]]);
+	var obj = this.__geometry;
+	var h = this.__canvas.height;
+	var fy = h / obj.height;
+	var w = this.__canvas.width;
+	var fx = w / obj.width;
+//	var df=dx<dy?dx:dy;
+	var dx, dy;
+	if(fx<fy)	{	dx=fx;	dy=fx+(fy-fx)*this.__asp_scl;	}
+	else		{	dy=fy;	dx=fy+(fx-fy)*this.__asp_scl;	}
+	obj.pf = -m.e(4,3);
+	obj.b = [dx*m.e(1,1),	dx*m.e(2,1),	dx*m.e(3,1),
+			dy*m.e(1,2),	dy*m.e(2,2),	dy*m.e(3,2),
+			m.e(1,3),		m.e(2,3),		m.e(3,3),
+			w/2,			h/2,			obj.depth/2,
+			fx,				fy,				1];
+/*	obj.b = [dx*m.e(1,1),	dx*m.e(2,1),	dx*m.e(3,1),
+			dy*m.e(1,2),	dy*m.e(2,2),	dy*m.e(3,2),
+			m.e(1,3),		m.e(2,3),		m.e(3,3),
+			w/2,			h/2,			obj.depth/2,
+			dx,				dy,				1];	*/
+	this.__drawBackground();
+
+	if (!isPrecise) {
+		obj.fast = 1;
+		obj.good = 0;
+		this.__mgl_draw_fast(obj,c,1);
+	} else {
+		obj.fast = 0;
+		obj.good = 1;
+		this.__mgl_draw_good(obj,c,1);
+	}
+}
+
+
+/** perform fast drawing */
+mathgl.Graph.prototype.__mgl_draw_fast = function(obj, ctx, skip) {
+	if(obj.fast==0)	return;
+	this.__mgl_prepare(obj,skip);	// update coordinates
+	var di = 1 + Math.round(obj.nprim / this.__maxDraftPoints);
+	// for each primitive skipping superfluous
+	for(var i=0;i<obj.nprim;i ++)
+	{
+		var prim = obj.prim[i];
+		var n1 = prim[1], nn = obj.pp[n1];
+		if(prim[0]==1 || obj.pnts[n1][3]<0)
+			this.__mgl_draw_prim(obj,ctx,prim,Math.abs(obj.b[12]));
+		else if(obj.prim[i][0]<4 && i%di==0)
+		{
+			ctx.fillStyle = obj.prim[i][10];
+			ctx.fillRect(nn[0], nn[1], 2, 2);
+		}
+	}
+}
+
+
+/** perform high-quality drawing */
+mathgl.Graph.prototype.__mgl_draw_good = function(obj, ctx, skip) {
+	obj.fast = 0;
+	this.__mgl_prepare(obj,skip);	// update coordinates
+//	var scl = 1/Math.abs(obj.z[1]-obj.z[0]);
+	// NOTE: this valid only for current zoom/view. In general case it should be more complicated
+	var s1 = Math.sqrt(obj.b[0]*obj.b[0]+obj.b[1]*obj.b[1]+obj.b[2]*obj.b[2]);
+	var s2 = Math.abs(obj.b[12]);
+	for(var i=0;i<obj.nprim;i++)	// for each primitive
+	{
+		var prim = obj.prim[i];
+		var scl = s1*this.__mgl_pf(obj, prim[9]);
+		if(obj.pnts[prim[1]][3]<0)	scl = s2;
+		this.__mgl_draw_prim(obj,ctx,prim,scl);
+	}
+}
+
+
+mathgl.Graph.prototype.__mgl_pf = function(obj, z) {
+	//	return 1/obj.pf;
+	return (1-this.__fov/1.37)/obj.pf/(1-this.__fov*z/obj.depth);	// TODO: check calc coordinates!!!
+	//	return 1/(1+obj.pf*(1-z/obj.depth));
+}
+
+
+/** perform high-quality drawing */
+mathgl.Graph.prototype.__mgl_draw_prim = function(obj, ctx, prim, scl) {
+	var n1 = prim[1], n2 = prim[2];
+	var n3 = prim[3], n4 = prim[4];
+	var pp = obj.pp;
+	var deg = Math.PI/180;  //0.017453293;
+
+	ctx.strokeStyle = prim[10];
+	ctx.fillStyle = prim[10];
+	ctx.lineWidth = 1;
+	switch(prim[0])		// draw it depending on its type
+	{
+	case 0: // marks
+		ctx.lineWidth = prim[7]*prim[6]*5e-4;
+		this.__mgl_draw_mark(ctx, pp[n1][0], pp[n1][1], n4, prim[6]/100, scl);
+		break;
+	case 1: // lines
+		ctx.beginPath();
+		ctx.moveTo(pp[n1][0],pp[n1][1]);
+		ctx.lineTo(pp[n2][0],pp[n2][1]);
+		ctx.lineWidth = prim[7]/100;
+		ctx.stroke();	break;
+	case 2: // triangles
+		ctx.beginPath();
+		ctx.moveTo(pp[n1][0],pp[n1][1]);
+		ctx.lineTo(pp[n2][0],pp[n2][1]);
+		ctx.lineTo(pp[n3][0],pp[n3][1]);
+		ctx.closePath();	ctx.fill();	break;
+	case 3: // quadrangles
+		ctx.beginPath();
+		ctx.moveTo(pp[n1][0],pp[n1][1]);
+		ctx.lineTo(pp[n2][0],pp[n2][1]);
+		ctx.lineTo(pp[n4][0],pp[n4][1]);
+		ctx.lineTo(pp[n3][0],pp[n3][1]);
+		ctx.closePath();
+		// NOTE: look as alpha is disabled for lines
+		// So, next code should be only for the case alpha=false
+		if(prim[10].charAt(0)=='#')	ctx.stroke();
+		ctx.fill();	break;
+	case 4: // glyphs
+		var t=prim[7]*deg/100;
+		var xx=obj.coor[n2][2]/100,yy=-obj.coor[n2][3]/100,zz=obj.coor[n2][4]/100;
+		var xc = obj.b[0]*xx + obj.b[1]*yy + obj.b[2]*zz;
+		var yc = obj.b[3]*xx + obj.b[4]*yy + obj.b[5]*zz;
+		var zc = obj.b[6]*xx + obj.b[7]*yy + obj.b[8]*zz;
+
+		var dv = this.__mgl_pf(obj, pp[n1][2]);
+		var cv = this.__fov*obj.pf/(1-this.__fov/1.37)/obj.depth;
+		xc += (pp[n1][0]-obj.b[9])*zc*cv;//*dv;
+		yc += (pp[n1][1]-obj.b[10])*zc*cv;//*dv;
+
+		if(obj.pnts[n1][3]<0)	{	xc=xx;	yc=yy;	}
+		var ll = xc*xc+yc*yc;
+		if(ll < 1e-10)	break;
+		if(ll<1e10 && t/deg<1e4)
+		{
+			t = Math.atan2(yc,xc);
+			if(Math.abs(t)>Math.PI/2)	t += Math.PI;
+		}
+		else t=0;
+		var c=Math.cos(t), s=Math.sin(t), d=prim[6]/200;
+
+		var b=[d*c, d*s, d*s, -d*c, pp[n1][0],pp[n1][1]];
+		var x=obj.coor[n2][0]*scl/100, y=obj.coor[n2][1]*scl/100, f=prim[8]*scl/1e5;
+		if(n3&8)
+		{
+			if(!(n3&4))	this.__mgl_line_glyph(ctx, x,y, f,1,b);
+			else this.__mgl_line_glyph(ctx, x,y, f,0,b);
+		}
+		else
+		{
+			if(!(n3&4)) this.__mgl_fill_glyph(ctx, x,y, f,obj.glfs[n4],b);
+			else this.__mgl_wire_glyph(ctx, x,y, f,obj.glfs[n4],b);
+		}
+		break;
+	}
+}
+
+/** change coordinates according current transformations, usually called internally by draw() */
+mathgl.Graph.prototype.__mgl_prepare = function(obj, skip) {
+	// fill transformation matrix
+	if(!skip)
+	{
+		var dx = 1/Math.abs(obj.z[1]-obj.z[0]);
+		var dy = 1/Math.abs(obj.z[3]-obj.z[2]);
+		var cx=Math.cos(obj.tet*deg), sx=Math.sin(obj.tet*deg);	// tetx
+		var cy=Math.cos(obj.phi*deg), sy=Math.sin(obj.phi*deg);	// tety
+		var cz=Math.cos(obj.bet*deg), sz=Math.sin(obj.bet*deg);	// tetz
+		obj.b = [dx*cx*cy, -dx*cy*sx, dx*sy,
+				dy*(cx*sy*sz+cz*sx), dy*(cx*cz-sx*sy*sz), -dy*cy*sz,
+				sx*sz-cx*cz*sy, cx*sz+cz*sx*sy, cy*cz,
+				obj.width/2*(1+dx-obj.z[1]-obj.z[0])/dx,
+				obj.height/2*(1+dy-obj.z[3]-obj.z[2])/dy, obj.depth/2, dx,dy,1];
+	}
+	// now transform points for found transformation matrix
+	var b = obj.b, i;
+	obj.pp = [];
+	for(i=0;i<obj.npnts;i++)
+	{
+		var x = obj.pnts[i][0]-obj.width/2;
+		var y = obj.pnts[i][1]-obj.height/2;
+		var z = obj.pnts[i][2]-obj.depth/2;
+		if(obj.pnts[i][3]>=0)	// TODO: check later when mglInPlot will be ready
+			obj.pp[i] = [b[9]  + b[0]*x + b[1]*y + b[2]*z,
+						b[10] + b[3]*x + b[4]*y + b[5]*z,
+						b[11] + b[6]*x + b[7]*y + b[8]*z];
+		else
+			obj.pp[i] = [b[9]+b[12]*x,b[10]+b[13]*y,b[11]+b[14]*z];
+	}
+	if(obj.pf || this.__fov)	for(var i=0;i<obj.npnts;i++)	// perspective
+	{	// NOTE: it is not supported for coordinate determining now
+		var d = this.__mgl_pf(obj, obj.pp[i][2]);
+		if(obj.pnts[i][3]>=0)	// TODO: check later when mglInPlot will be ready
+		{
+			obj.pp[i][0] = d*obj.pp[i][0] + (1-d)*obj.b[9];
+			obj.pp[i][1] = d*obj.pp[i][1] + (1-d)*obj.b[10];
+		}
+	}
+	// fill z-coordinates for primitives
+	if(!obj.fast)	for(i=0;i<obj.nprim;i++)
+	{
+		var prim = obj.prim[i];
+		var n1 = prim[1], n2 = prim[2], n3 = prim[3], n4 = prim[4];
+		switch(prim[0])
+		{
+		case 1: // lines
+			prim[9] = (obj.pp[n1][2]+obj.pp[n2][2])/2;	break;
+		case 2: // triangles
+			prim[9] = (obj.pp[n1][2]+obj.pp[n2][2]+obj.pp[n3][2])/3;	break;
+		case 3: // quadrangles
+			prim[9] = (obj.pp[n1][2]+obj.pp[n2][2]+obj.pp[n3][2]+obj.pp[n4][2])/4;	break;
+		default:
+			prim[9] = obj.pp[n1][2];	break;
+		}
+	}
+	if(!obj.fast) // sort primitives according its z-coordinate
+		obj.prim.sort(this.__mgl_cmp); // more accurate sorting
+}
+
+
+mathgl.Graph.prototype.__mgl_cmp = function(a,b) {
+	var tt = [0,2,4,5, 1,3,6, 7];
+	if(a[9]!=b[9])	return a[9] - b[9];
+	if(a[0]!=b[0])	return tt[b[0]]-tt[a[0]];
+	if(a[8]!=b[8])	return a[8] - b[8];
+	return a[3]-b[3];
+}
+
+
+/**
+ * Function for drawing markers of type st with given size at position {x,y}
+ * Usually this function is called internally, but it can be called by user as well
+ */
+mathgl.Graph.prototype.__mgl_draw_mark = function(ctx,x,y,st,size,d) {
+	if(size<=0) {	st = 46;	size=1; }
+	var s = size*d;
+	ctx.beginPath();
+	switch(st)
+	{
+	case 111:	// 'o'
+		ctx.arc(x,y,s,0,Math.PI*2);	 ctx.stroke();	break;
+	case 79:	// 'O'
+		ctx.arc(x,y,s,0,Math.PI*2);	 ctx.fill();	 break;
+	case 67:	// 'C'
+		ctx.arc(x,y,s,0,Math.PI*2);	 ctx.stroke();
+		ctx.arc(x,y,0.1*s,0,Math.PI*2); ctx.fill();	 break;
+	case 80:	// 'P'
+		ctx.moveTo(x-s,y-s);	ctx.lineTo(x+s,y-s);
+		ctx.lineTo(x+s,y+s);	ctx.lineTo(x-s,y+s);	ctx.lineTo(x-s,y-s);
+		ctx.moveTo(x-s,y);		ctx.lineTo(x+s,y);
+		ctx.moveTo(x,y-s);		ctx.lineTo(x,y+s);
+		ctx.stroke();	break;
+	case 43:	// '+'
+		ctx.moveTo(x-s,y);		ctx.lineTo(x+s,y);
+		ctx.moveTo(x,y-s);		ctx.lineTo(x,y+s);
+		ctx.stroke();	break;
+	case 88:	// 'X'
+		ctx.moveTo(x-s,y-s);	ctx.lineTo(x+s,y-s);
+		ctx.lineTo(x+s,y+s);	ctx.lineTo(x-s,y+s);	ctx.lineTo(x-s,y-s);
+		ctx.moveTo(x-s,y-s);	ctx.lineTo(x+s,y+s);
+		ctx.moveTo(x+s,y-s);	ctx.lineTo(x-s,y+s);
+		ctx.stroke();	break;
+	case 120:	// 'x'
+		ctx.moveTo(x-s,y-s);	ctx.lineTo(x+s,y+s);
+		ctx.moveTo(x+s,y-s);	ctx.lineTo(x-s,y+s);
+		ctx.stroke();	break;
+	case 115:	// 's'
+		ctx.moveTo(x-s,y-s);	ctx.lineTo(x+s,y-s);
+		ctx.lineTo(x+s,y+s);	ctx.lineTo(x-s,y+s);
+		ctx.closePath();		ctx.stroke();	break;
+	case 83:	// 'S'
+		ctx.moveTo(x-s,y-s);	ctx.lineTo(x+s,y-s);
+		ctx.lineTo(x+s,y+s);	ctx.lineTo(x-s,y+s);
+		ctx.closePath();		ctx.fill();	 break;
+	case 100:	// 'd'
+		ctx.moveTo(x-s,y);		ctx.lineTo(x,y-s);
+		ctx.lineTo(x+s,y);		ctx.lineTo(x,y+s);
+		ctx.closePath();		ctx.stroke();	break;
+	case 68:	// 'D'
+		ctx.moveTo(x-s,y);		ctx.lineTo(x,y-s);
+		ctx.lineTo(x+s,y);		ctx.lineTo(x,y+s);
+		ctx.closePath();		ctx.fill();	 break;
+	case 42:	// '*'
+		ctx.moveTo(x-s,y);		ctx.lineTo(x+s,y);
+		ctx.moveTo(x-0.6*s,y-0.8*s);	ctx.lineTo(x+0.6*s,y+0.8*s);
+		ctx.moveTo(x+0.6*s,y-0.8*s);	ctx.lineTo(x-0.6*s,y+0.8*s);
+		ctx.stroke();	break;
+	case 89:	// 'Y'
+		ctx.moveTo(x,y-s);		ctx.lineTo(x,y);
+		ctx.moveTo(x-0.8*s,y+0.6*s);	ctx.lineTo(x,y);
+		ctx.moveTo(x+0.8*s,y+0.6*s);	ctx.lineTo(x,y);
+		ctx.stroke();	break;
+	case 86:	// 'T'
+		ctx.moveTo(x-s,y-s/2);	ctx.lineTo(x+s,y-s/2);
+		ctx.lineTo(x,y+s);		ctx.closePath();
+		ctx.fill();	 break;
+	case 118:	// '^'
+		ctx.moveTo(x-s,y-s/2);	ctx.lineTo(x+s,y-s/2);
+		ctx.lineTo(x,y+s);		ctx.closePath();
+		ctx.stroke();	break;
+	case 84:	// 'V'
+		ctx.moveTo(x-s,y+s/2);	ctx.lineTo(x+s,y+s/2);
+		ctx.lineTo(x,y-s);		ctx.closePath();
+		ctx.fill();	 break;
+	case 94:	// 'v'
+		ctx.moveTo(x-s,y+s/2);	ctx.lineTo(x+s,y+s/2);
+		ctx.lineTo(x,y-s);		ctx.closePath();
+		ctx.stroke();	break;
+	case 76:	// 'L'
+		ctx.moveTo(x+s/2,y-s);	ctx.lineTo(x+s/2,y+s);
+		ctx.lineTo(x-s,y);		ctx.closePath();
+		ctx.fill();	 break;
+	case 60:	// '<'
+		ctx.moveTo(x+s/2,y-s);	ctx.lineTo(x+s/2,y+s);
+		ctx.lineTo(x-s,y);		ctx.closePath();
+		ctx.stroke();	break;
+	case 82:	// 'R'
+		ctx.moveTo(x-s/2,y-s);	ctx.lineTo(x-s/2,y+s);
+		ctx.lineTo(x+s,y);		ctx.closePath();
+		ctx.fill();	 break;
+	case 62:	// '>'
+		ctx.moveTo(x-s/2,y-s);	ctx.lineTo(x-s/2,y+s);
+		ctx.lineTo(x+s,y);		ctx.closePath();
+		ctx.stroke();	break;
+//	case 46:	// '.'
+	default:
+		ctx.rect(x,y,1,1); ctx.fill();	 break;
+	}
+}
+
+
+/** for internal use only */
+mathgl.Graph.prototype.__mgl_fill_glyph = function(ctx, x,y, f,g,b) {
+	var xx,yy,j;
+	var np=0;	ctx.beginPath();
+	for(j=0;j<g[0];j++)
+	{
+		xx = g[1][2*j]; yy = g[1][2*j+1];
+		if(xx==16383 && yy==16383)
+		{
+			ctx.closePath();	np = 1;
+		}
+		else if(np)
+		{
+			xx = x+f*xx;	yy = y+f*yy;	np = 0;
+			ctx.moveTo(b[4]+b[0]*xx+b[1]*yy, b[5]+b[2]*xx+b[3]*yy);
+		}
+		else
+		{
+			xx = x+f*xx;	yy = y+f*yy;
+			ctx.lineTo(b[4]+b[0]*xx+b[1]*yy, b[5]+b[2]*xx+b[3]*yy);
+		}
+	}
+	ctx.closePath();	ctx.fill('evenodd');
+}
+
+
+/** for internal use only */
+mathgl.Graph.prototype.__mgl_wire_glyph = function(ctx, x,y, f,g,b) {
+	var xx,yy,j;
+	var np=0;	ctx.beginPath();
+	for(j=0;j<g[0];j++)
+	{
+		xx = g[1][2*j]; yy = g[1][2*j+1];
+		if(xx==16383 && yy==16383)
+		{
+			ctx.closePath();	np = 1;
+		}
+		else if(np)
+		{
+			xx = x+f*xx;	yy = y+f*yy;	np = 0;
+			ctx.moveTo(b[4]+b[0]*xx+b[1]*yy, b[5]+b[2]*xx+b[3]*yy);
+		}
+		else
+		{
+			xx = x+f*xx;	yy = y+f*yy;
+			ctx.lineTo(b[4]+b[0]*xx+b[1]*yy, b[5]+b[2]*xx+b[3]*yy);
+		}
+	}
+	ctx.closePath();	ctx.stroke();
+}
+
+
+/** for internal use only */
+mathgl.Graph.prototype.__mgl_line_glyph = function(ctx, x,y, f,solid,b) {
+	var xx,yy,j,xs,ys;
+	var dy = 0.004;
+	ctx.moveTo(b[4]+b[0]*x+b[1]*(y-dy), b[5]+b[2]*x+b[3]*(y-dy));
+	ctx.lineTo(b[4]+b[0]*x+b[1]*(y+dy), b[5]+b[2]*x+b[3]*(y+dy));
+	ctx.lineTo(b[4]+b[0]*(x+f)+b[1]*(y+dy), b[5]+b[2]*(x+f)+b[3]*(y+dy));
+	ctx.lineTo(b[4]+b[0]*(x+f)+b[1]*(y-dy), b[5]+b[2]*(x+f)+b[3]*(y-dy));
+	ctx.closePath();
+	if(solid)	ctx.fill();
+	else		ctx.stroke();
+}
+
+
+/**
+ * Move Left using MGL 'zoomaxis' with geometry reload
+ */
+mathgl.Graph.prototype.moveLeft = function() {
+	var b = this.__geometry.b;
+	var f = 0.1/Math.sqrt(b[0]*b[0]+b[1]*b[1]+b[2]*b[2]);
+	this.shiftAxis(f*b[0],f*b[1],f*b[2]);
+}
+
+
+/**
+ * Move Right using MGL 'zoomaxis' with geometry reload
+ */
+mathgl.Graph.prototype.moveRight = function() {
+	var b = this.__geometry.b;
+	var f = -0.1/Math.sqrt(b[0]*b[0]+b[1]*b[1]+b[2]*b[2]);
+	this.shiftAxis(f*b[0],f*b[1],f*b[2]);
+}
+
+
+/**
+ * Move Up using MGL 'zoomaxis' with geometry reload
+ */
+mathgl.Graph.prototype.moveUp = function() {
+	var b = this.__geometry.b;
+	var f = -0.1/Math.sqrt(b[3]*b[3]+b[4]*b[4]+b[5]*b[5]);
+	this.shiftAxis(-f*b[3],f*b[4],-f*b[5]);
+}
+
+
+/**
+ * Move Down using MGL 'zoomaxis' with geometry reload
+ */
+mathgl.Graph.prototype.moveDown = function() {
+	var b = this.__geometry.b;
+	var f = 0.1/Math.sqrt(b[3]*b[3]+b[4]*b[4]+b[5]*b[5]);
+	this.shiftAxis(-f*b[3],f*b[4],-f*b[5]);
+}
+
+
+/**
+ * Zoom In using MGL 'zoomaxis' with geometry reload
+ */
+mathgl.Graph.prototype.zoomIn = function() {
+	this.zoomAxis(1.1);
+}
+
+
+/**
+ * Zoom Out using MGL 'zoomaxis' with geometry reload
+ */
+mathgl.Graph.prototype.zoomOut = function() {
+	this.zoomAxis(1./1.1);
+}
+
+
+/**
+ * @return mathgl.View instance
+ */
+mathgl.Graph.prototype.getView = function() {
+	return this.__view;
+}
+
+
+/**
+ * Build and load geometry into View
+ * @param mgl {String} MGL script
+ * @param completeCallback {Function|null} optional callback to notify completion
+ */
+mathgl.Graph.prototype.loadGeometry = function(mgl, completeCallback) {
+  this.__backend.geometry(mgl, mathgl.bind(function(error, result) {
+    if (!error) {
+      this.__geometry = result;
+      this.__geometry.mgl = mgl;
+      this.redraw();
+
+      if (typeof completeCallback === "function") {
+        completeCallback();
+      }
+    }
+  }, this));
+}
+
+
+/**
+ * Force reload geometry
+ * @param completeCallback {Function|null} optional callback to notify completion
+ */
+mathgl.Graph.prototype.reloadGeometry = function(completeCallback) {
+  var mgl = (this.__geometry && this.__geometry.mgl) ? this.__geometry.mgl : "";
+  this.loadGeometry(mgl, completeCallback);
+}
+
+
+/**
+ * Force redraw view from current geometry
+ */
+mathgl.Graph.prototype.redraw = function() {
+	this.__renderStart();
+}
+
+
+/**
+ * Shutdown graph instance
+ * Destroy view, cleanup all timers and references
+ */
+mathgl.Graph.prototype.destroy = function() {
+	// clear active timeouts
+	for (var i = 0, l = this.__activeTimeoutHandlers.length; i<l; i++) {
+		var th = this.__activeTimeoutHandlers.pop();
+		clearTimeout(th);
+	}
+	this.__view.destroy();
+	this.__view = null;
+	this.__backend = null;
+	this.__canvas = null;
+	this.__geometry = null;
+}
+
+
+/**
+ * Export image
+ * @param type {String} data url type (e.g. "image/png")
+ * @return {String} HTML Data URL containing graph image
+ **/
+mathgl.Graph.prototype.toDataURL = function(type) {
+	return this.__canvas.toDataURL(type);
+}
+
+
+/**
+ * Set perspective angle of view
+ * @param val {Number} degree of perspective in range 0...1 (0 - use default orthogonal projection)
+ **/
+mathgl.Graph.prototype.setPerspective = function(val) {
+	this.__fov = val;
+}
+
+
+/**
+ * Set maximal number of drawable points in draft mode
+ **/
+mathgl.Graph.prototype.setMaxDraftPoints = function(count) {
+	this.__maxDraftPoints = count;
+}
+
+
+/**
+ * Set delay between draft and precise rendering
+ * @param delayMillisec {Integer} delay in milliseconds
+ */
+mathgl.Graph.prototype.setPreciseRenderingDelay = function(delayMillisec) {
+	this.__preciseRenderingDelay = delayMillisec;
+}
diff --git a/json/mathgl.View.js b/json/mathgl.View.js
new file mode 100644
index 0000000..9291770
--- /dev/null
+++ b/json/mathgl.View.js
@@ -0,0 +1,266 @@
+/**
+ * Standard 3D view - camera flying along the surface of a sphere.
+ */
+
+
+/** @constructor */
+mathgl.View = function() {
+	this.__canvas = null;
+	this.__renderLauncherFunc = null;
+	this.__pickPointHandlerFunc = null;
+	this.__onCameraChanged = null;
+	this.__onMouseMoveFunc = mathgl.bind(this.__onMouseMove, this);
+	this.__onMouseDownFunc = mathgl.bind(this.__onMouseDown, this);
+	this.__onMouseUpFunc = mathgl.bind(this.__onMouseUp, this);
+	this.__onMouseOutFunc = mathgl.bind(this.__onMouseOut, this);
+	this.__onDblClickFunc = mathgl.bind(this.__onDblClick, this);
+	this.__onMouseWheelFunc = mathgl.bind(this.__onMouseWheel, this);
+
+	// mouse state
+	this.__isMouseDown = false;
+	this.__mouseX = -1;
+	this.__mouseY = -1;
+
+	// current camera position
+	this.__distance = 1.0;
+	this.__pitch = 0;
+	this.__yaw = 0;
+	this.__theta = 0;
+	// by default pitch rotation is unlimited
+	this.__limitedPitchRotation = false;
+}
+
+
+/**
+ * Load view state from JSON string.
+ * @param json {String} string in JSON format with previously saved state
+ */
+mathgl.View.prototype.load = function(json) {
+	throw new Error("not implemented");
+}
+
+
+/**
+ * Save view state to JSON string.
+ * @return {String} view state serialized to JSON string
+ */
+mathgl.View.prototype.save = function() {
+	throw new Error("not implemented");
+}
+
+
+/**
+ * Attach given canvas to this view (Bind current view with given canvas). View instance will start procesing
+ * canvas events since it is attached to it.
+ * @param canvas {Canvas} canvas to attach
+ */
+mathgl.View.prototype.attachCanvas = function(canvas) {
+	// remember canvas
+	this.__canvas = canvas;
+	// connect mouse events
+	this.__canvas.addEventListener("mousemove", this.__onMouseMoveFunc, false);
+	this.__canvas.addEventListener("mousedown", this.__onMouseDownFunc, false);
+	this.__canvas.addEventListener("mouseup",   this.__onMouseUpFunc, false);
+	this.__canvas.addEventListener("mouseout",  this.__onMouseOutFunc, false);
+	this.__canvas.addEventListener("dblclick",  this.__onDblClickFunc, false);
+//	this.__canvas.addEventListener("mousewheel",  this.__onMouseWheelFunc, false);
+	if ("onwheel" in document.createElement("div")) {
+		this.__canvas.addEventListener("wheel",  this.__onMouseWheelFunc, false);
+	} else {
+		this.__canvas.addEventListener("mousewheel",  this.__onMouseWheelFunc, false);
+	}
+
+	// initiate redraw
+	this.__renderLauncherFunc();
+}
+
+
+/** Detach any previously attached canvas from this view instance. */
+mathgl.View.prototype.detachCanvas = function() {
+	// disconnect mouse events
+	this.__canvas.removeEventListener("mousemove", this.__onMouseMoveFunc, false);
+	this.__canvas.removeEventListener("mousedown", this.__onMouseDownFunc, false);
+	this.__canvas.removeEventListener("mouseup", this.__onMouseUpFunc, false);
+	this.__canvas.removeEventListener("mouseout", this.__onMouseOutFunc, false);
+	this.__canvas.removeEventListener("dblclick", this.__onDblClickFunc, false);
+//	this.__canvas.removeEventListener("mousewheel",  this.__onMouseWheelFunc, false);
+	if ("onwheel" in document.createElement("div")) {
+		this.__canvas.removeEventListener("wheel",  this.__onMouseWheelFunc, false);
+	} else {
+		this.__canvas.removeEventListener("mousewheel",  this.__onMouseWheelFunc, false);
+	}
+
+	// drop canvas
+	this.__canvas = null;
+}
+
+
+/**
+ * Set render launcher - callback function which is invoked when graph shall be redrawn (after some user actions).
+ * @param renderLauncherFunc {Function} callback function which will be invoked when graph shall be redrawn
+ */
+mathgl.View.prototype.setRenderLauncher = function(renderLauncherFunc) {
+	this.__renderLauncherFunc = renderLauncherFunc;
+}
+
+
+/**
+ * Set pick point handler - callback function which is invoked when user request to highlight or show coordinates of point picked.
+ * @param pickPointHandler {Function} callback function which will be invoked when user pick the point
+ */
+mathgl.View.prototype.setPickPointHandler = function(pickPointHandlerFunc) {
+	this.__pickPointHandlerFunc = pickPointHandlerFunc;
+}
+
+
+/**
+ * Get current view view matrix.
+ * @return {Matrix} view matrix
+ */
+mathgl.View.prototype.viewMatrix = function() {
+	var d = this.__distance;
+	var cp = Math.cos(this.__pitch);
+	var sp = Math.sin(this.__pitch);
+	var cy = Math.cos(this.__yaw);
+	var sy = Math.sin(this.__yaw);
+	var ct = Math.cos(this.__theta);
+	var st = Math.sin(this.__theta);
+	var lh = true; // coordinate system is left handed
+
+	var distanceMatrix = $M([[1, 0,  0, 0],
+							[0, 1,  0, 0],
+							[0, 0,  1, 0],
+							[0, 0, d, 1]]);
+	var pitchMatrix = $M(  [[1,              0,              0, 0],
+							[0,  cp           ,  lh ? sp : -sp, 0],
+							[0,  lh ? -sp : sp,             cp, 0],
+							[0,              0,              0, 1]]);
+	var yawMatrix = $M([[ cy, 0, -sy, 0],
+						[  0, 1,   0, 0],
+						[ sy, 0,  cy, 0],
+						[  0, 0,   0, 1]]);
+	var viewMatrix = $M([[ ct,-st, 0, 0],
+						[  st, ct, 0, 0],
+						[  0,  0,  1, 0],
+						[  0,  0,  0, 1]]);
+	viewMatrix = viewMatrix.x(distanceMatrix);
+	viewMatrix = viewMatrix.x(pitchMatrix);
+	viewMatrix = viewMatrix.x(yawMatrix);
+	return viewMatrix;
+}
+
+/** TODO: add function returning current view area in world (model) coordinates */
+mathgl.View.prototype.viewArea = function() {
+	throw new Error("not implemented");
+}
+
+
+mathgl.View.prototype.__onMouseMove = function(e) {
+	if (this.__isMouseDown) {
+		var x = e.layerX;
+		var y = e.layerY;
+		this.__yaw += 0.5 * (this.__mouseX - x) * Math.PI / 180;
+		this.__pitch += 0.5 * (y - this.__mouseY) * Math.PI / 180;
+		this.__mouseX = x;
+		this.__mouseY = y;
+		if (this.__limitedPitchRotation) {
+			this.__pitch = Math.min(this.__pitch, 0.999*Math.PI/2);
+			this.__pitch = Math.max(this.__pitch, -0.999*Math.PI/2);
+		} else {
+			if (this.__pitch > 63) this.__pitch -= 20*Math.PI;
+			if (this.__pitch < -63) this.__pitch += 20*Math.PI;
+		}
+
+		if(this.__yaw > 63)	this.__yaw -= 20*Math.PI;
+		if(this.__yaw <-63)	this.__yaw += 20*Math.PI;
+// 		this.__yaw = Math.min(this.__yaw, Math.PI);
+// 		this.__yaw = Math.max(this.__yaw, -Math.PI);
+
+    this.__notifyCameraChanged();
+		this.__renderLauncherFunc();
+	}
+}
+
+
+mathgl.View.prototype.__onMouseDown = function(e) {
+	this.__mouseX = e.layerX;
+	this.__mouseY = e.layerY;
+	this.__isMouseDown = true;
+}
+
+
+mathgl.View.prototype.__onMouseUp = function() {
+	this.__isMouseDown = false;
+}
+
+
+mathgl.View.prototype.__onMouseOut = function() {
+	this.__isMouseDown = false;
+}
+
+
+mathgl.View.prototype.__onDblClick = function(e) {
+	this.__pickPointHandlerFunc(e.layerX, e.layerY);
+}
+
+
+mathgl.View.prototype.__onMouseWheel = function(e) {
+	this.__isMouseDown = false;
+//	this.__distance -= 0.1 * e.wheelDelta / 120;
+
+	var wheelSensivity = 0.1;
+	if (e.wheelDelta !== undefined) {
+		// handle deprecated 'mousewheel' event (old webkit in chrome and safari)
+		// wheelDelta is always 120 and inverted to standard deltaY
+		var direction = e.wheelDelta >= 0 ? -1 : 1;
+		this.__distance += -1. * wheelSensivity * direction;
+	} else if (e.deltaY !== undefined) {
+		// handle standard W3C DOM Level 3 'wheel' event
+		var direction = e.deltaY >= 0 ? -1 : 1;
+		this.__distance += wheelSensivity * direction;
+	}
+
+	this.__distance = Math.min(this.__distance, 10.0);
+	this.__distance = Math.max(this.__distance, 0.2);
+  this.__notifyCameraChanged();
+	this.__renderLauncherFunc();
+}
+
+mathgl.View.prototype.getViewpoint = function() {
+	return { 
+		distance : this.__distance, 
+		pitch : this.__pitch, 
+		yaw : this.__yaw
+	}; 
+} 
+
+mathgl.View.prototype.setViewpoint = function(distance, pitch, yaw) { 
+	this.__distance = distance; 
+	this.__pitch = pitch; 
+	this.__yaw = yaw; 
+	this.__renderLauncherFunc(); 
+} 
+
+mathgl.View.prototype.destroy = function() { 
+	this.__renderLauncherFunc = null; 
+	this.__pickPointHandlerFunc = null; 
+	this.detachCanvas(); 
+} 
+
+mathgl.View.prototype.setCameraEventHandler = function(handler) { 
+	this.__onCameraChanged = handler; 
+}
+
+mathgl.View.prototype.__notifyCameraChanged = function() {
+	if(this.__onCameraChanged) {
+		this.__onCameraChanged(this.getViewpoint());
+	}
+}
+
+/**
+ * Limit the pitch control rotation to +-90 degrees
+ * @param limitedPitch {Boolean} enable or disable limit
+ */
+mathgl.View.prototype.setLimitedPitchRotation = function(limitedPitch) {
+	this.__limitedPitchRotation = limitedPitch;
+}
diff --git a/json/mathgl.WebkitBackend.js b/json/mathgl.WebkitBackend.js
new file mode 100644
index 0000000..6b61570
--- /dev/null
+++ b/json/mathgl.WebkitBackend.js
@@ -0,0 +1,32 @@
+/**
+ * Webkit backend. Backend base on the object injected by QWebView.
+ */
+
+/** constructor */
+mathgl.WebkitBackend = function() {}
+
+/** inherit from mathgl.Backend interface */
+mathgl.WebkitBackend.prototype = new mathgl.Backend();
+
+
+/**
+ * Request for geometry data for given MGL script.
+ * @param mgl {String} MGL script to build geometry
+ * @param callback {Function} receiver of geometry must be a function(error, result)
+ */
+mathgl.WebkitBackend.prototype.geometry = function(mgl, callback) {
+	var geometryData = globalBackend.geometry(mgl);
+
+	/*
+	var zlib = require('zlib');
+	zlib.unzip(geometryData, function(err, buffer) {
+		if (!err)	{	geometryData = buffer;	 });
+	 */
+	
+	var obj = JSON.parse(geometryData);
+
+  // simulate async reply
+  setTimeout(function() {
+    callback(null, obj);
+  }, 0);
+}
diff --git a/json/mathgl.js b/json/mathgl.js
new file mode 100644
index 0000000..02fe4a4
--- /dev/null
+++ b/json/mathgl.js
@@ -0,0 +1,29 @@
+/** main mathgl namespace */
+var mathgl = {
+  version: '0.1.0'
+}
+
+
+/**
+ * Auxiliary functions.
+ */
+
+/** trivial bind implementation */
+mathgl.bind = function(func, context) {
+  return function() {
+    func.apply(context, arguments);
+  };
+}
+
+
+/** clone */
+mathgl.clone = function(obj) {
+  if (obj === null || typeof(obj) != 'object') {
+    return obj;
+  }
+  var temp = new obj.constructor();
+  for (var key in obj) {
+    temp[key] = mathgl.clone(obj[key]);
+  }
+  return temp;
+}
diff --git a/json/sylvester.src.js b/json/sylvester.src.js
new file mode 100644
index 0000000..97a6491
--- /dev/null
+++ b/json/sylvester.src.js
@@ -0,0 +1,1254 @@
+// === Sylvester ===
+// Vector and Matrix mathematics modules for JavaScript
+// Copyright (c) 2007 James Coglan
+// 
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+// 
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+var Sylvester = {
+  version: '0.1.3',
+  precision: 1e-6
+};
+
+function Vector() {}
+Vector.prototype = {
+
+  // Returns element i of the vector
+  e: function(i) {
+    return (i < 1 || i > this.elements.length) ? null : this.elements[i-1];
+  },
+
+  // Returns the number of elements the vector has
+  dimensions: function() {
+    return this.elements.length;
+  },
+
+  // Returns the modulus ('length') of the vector
+  modulus: function() {
+    return Math.sqrt(this.dot(this));
+  },
+
+  // Returns true iff the vector is equal to the argument
+  eql: function(vector) {
+    var n = this.elements.length;
+    var V = vector.elements || vector;
+    if (n != V.length) { return false; }
+    do {
+      if (Math.abs(this.elements[n-1] - V[n-1]) > Sylvester.precision) { return false; }
+    } while (--n);
+    return true;
+  },
+
+  // Returns a copy of the vector
+  dup: function() {
+    return Vector.create(this.elements);
+  },
+
+  // Maps the vector to another vector according to the given function
+  map: function(fn) {
+    var elements = [];
+    this.each(function(x, i) {
+      elements.push(fn(x, i));
+    });
+    return Vector.create(elements);
+  },
+  
+  // Calls the iterator for each element of the vector in turn
+  each: function(fn) {
+    var n = this.elements.length, k = n, i;
+    do { i = k - n;
+      fn(this.elements[i], i+1);
+    } while (--n);
+  },
+
+  // Returns a new vector created by normalizing the receiver
+  toUnitVector: function() {
+    var r = this.modulus();
+    if (r === 0) { return this.dup(); }
+    return this.map(function(x) { return x/r; });
+  },
+
+  // Returns the angle between the vector and the argument (also a vector)
+  angleFrom: function(vector) {
+    var V = vector.elements || vector;
+    var n = this.elements.length, k = n, i;
+    if (n != V.length) { return null; }
+    var dot = 0, mod1 = 0, mod2 = 0;
+    // Work things out in parallel to save time
+    this.each(function(x, i) {
+      dot += x * V[i-1];
+      mod1 += x * x;
+      mod2 += V[i-1] * V[i-1];
+    });
+    mod1 = Math.sqrt(mod1); mod2 = Math.sqrt(mod2);
+    if (mod1*mod2 === 0) { return null; }
+    var theta = dot / (mod1*mod2);
+    if (theta < -1) { theta = -1; }
+    if (theta > 1) { theta = 1; }
+    return Math.acos(theta);
+  },
+
+  // Returns true iff the vector is parallel to the argument
+  isParallelTo: function(vector) {
+    var angle = this.angleFrom(vector);
+    return (angle === null) ? null : (angle <= Sylvester.precision);
+  },
+
+  // Returns true iff the vector is antiparallel to the argument
+  isAntiparallelTo: function(vector) {
+    var angle = this.angleFrom(vector);
+    return (angle === null) ? null : (Math.abs(angle - Math.PI) <= Sylvester.precision);
+  },
+
+  // Returns true iff the vector is perpendicular to the argument
+  isPerpendicularTo: function(vector) {
+    var dot = this.dot(vector);
+    return (dot === null) ? null : (Math.abs(dot) <= Sylvester.precision);
+  },
+
+  // Returns the result of adding the argument to the vector
+  add: function(vector) {
+    var V = vector.elements || vector;
+    if (this.elements.length != V.length) { return null; }
+    return this.map(function(x, i) { return x + V[i-1]; });
+  },
+
+  // Returns the result of subtracting the argument from the vector
+  subtract: function(vector) {
+    var V = vector.elements || vector;
+    if (this.elements.length != V.length) { return null; }
+    return this.map(function(x, i) { return x - V[i-1]; });
+  },
+
+  // Returns the result of multiplying the elements of the vector by the argument
+  multiply: function(k) {
+    return this.map(function(x) { return x*k; });
+  },
+
+  x: function(k) { return this.multiply(k); },
+
+  // Returns the scalar product of the vector with the argument
+  // Both vectors must have equal dimensionality
+  dot: function(vector) {
+    var V = vector.elements || vector;
+    var i, product = 0, n = this.elements.length;
+    if (n != V.length) { return null; }
+    do { product += this.elements[n-1] * V[n-1]; } while (--n);
+    return product;
+  },
+
+  // Returns the vector product of the vector with the argument
+  // Both vectors must have dimensionality 3
+  cross: function(vector) {
+    var B = vector.elements || vector;
+    if (this.elements.length != 3 || B.length != 3) { return null; }
+    var A = this.elements;
+    return Vector.create([
+      (A[1] * B[2]) - (A[2] * B[1]),
+      (A[2] * B[0]) - (A[0] * B[2]),
+      (A[0] * B[1]) - (A[1] * B[0])
+    ]);
+  },
+
+  // Returns the (absolute) largest element of the vector
+  max: function() {
+    var m = 0, n = this.elements.length, k = n, i;
+    do { i = k - n;
+      if (Math.abs(this.elements[i]) > Math.abs(m)) { m = this.elements[i]; }
+    } while (--n);
+    return m;
+  },
+
+  // Returns the index of the first match found
+  indexOf: function(x) {
+    var index = null, n = this.elements.length, k = n, i;
+    do { i = k - n;
+      if (index === null && this.elements[i] == x) {
+        index = i + 1;
+      }
+    } while (--n);
+    return index;
+  },
+
+  // Returns a diagonal matrix with the vector's elements as its diagonal elements
+  toDiagonalMatrix: function() {
+    return Matrix.Diagonal(this.elements);
+  },
+
+  // Returns the result of rounding the elements of the vector
+  round: function() {
+    return this.map(function(x) { return Math.round(x); });
+  },
+
+  // Returns a copy of the vector with elements set to the given value if they
+  // differ from it by less than Sylvester.precision
+  snapTo: function(x) {
+    return this.map(function(y) {
+      return (Math.abs(y - x) <= Sylvester.precision) ? x : y;
+    });
+  },
+
+  // Returns the vector's distance from the argument, when considered as a point in space
+  distanceFrom: function(obj) {
+    if (obj.anchor) { return obj.distanceFrom(this); }
+    var V = obj.elements || obj;
+    if (V.length != this.elements.length) { return null; }
+    var sum = 0, part;
+    this.each(function(x, i) {
+      part = x - V[i-1];
+      sum += part * part;
+    });
+    return Math.sqrt(sum);
+  },
+
+  // Returns true if the vector is point on the given line
+  liesOn: function(line) {
+    return line.contains(this);
+  },
+
+  // Return true iff the vector is a point in the given plane
+  liesIn: function(plane) {
+    return plane.contains(this);
+  },
+
+  // Rotates the vector about the given object. The object should be a 
+  // point if the vector is 2D, and a line if it is 3D. Be careful with line directions!
+  rotate: function(t, obj) {
+    var V, R, x, y, z;
+    switch (this.elements.length) {
+      case 2:
+        V = obj.elements || obj;
+        if (V.length != 2) { return null; }
+        R = Matrix.Rotation(t).elements;
+        x = this.elements[0] - V[0];
+        y = this.elements[1] - V[1];
+        return Vector.create([
+          V[0] + R[0][0] * x + R[0][1] * y,
+          V[1] + R[1][0] * x + R[1][1] * y
+        ]);
+        break;
+      case 3:
+        if (!obj.direction) { return null; }
+        var C = obj.pointClosestTo(this).elements;
+        R = Matrix.Rotation(t, obj.direction).elements;
+        x = this.elements[0] - C[0];
+        y = this.elements[1] - C[1];
+        z = this.elements[2] - C[2];
+        return Vector.create([
+          C[0] + R[0][0] * x + R[0][1] * y + R[0][2] * z,
+          C[1] + R[1][0] * x + R[1][1] * y + R[1][2] * z,
+          C[2] + R[2][0] * x + R[2][1] * y + R[2][2] * z
+        ]);
+        break;
+      default:
+        return null;
+    }
+  },
+
+  // Returns the result of reflecting the point in the given point, line or plane
+  reflectionIn: function(obj) {
+    if (obj.anchor) {
+      // obj is a plane or line
+      var P = this.elements.slice();
+      var C = obj.pointClosestTo(P).elements;
+      return Vector.create([C[0] + (C[0] - P[0]), C[1] + (C[1] - P[1]), C[2] + (C[2] - (P[2] || 0))]);
+    } else {
+      // obj is a point
+      var Q = obj.elements || obj;
+      if (this.elements.length != Q.length) { return null; }
+      return this.map(function(x, i) { return Q[i-1] + (Q[i-1] - x); });
+    }
+  },
+
+  // Utility to make sure vectors are 3D. If they are 2D, a zero z-component is added
+  to3D: function() {
+    var V = this.dup();
+    switch (V.elements.length) {
+      case 3: break;
+      case 2: V.elements.push(0); break;
+      default: return null;
+    }
+    return V;
+  },
+
+  // Returns a string representation of the vector
+  inspect: function() {
+    return '[' + this.elements.join(', ') + ']';
+  },
+
+  // Set vector's elements from an array
+  setElements: function(els) {
+    this.elements = (els.elements || els).slice();
+    return this;
+  }
+};
+  
+// Constructor function
+Vector.create = function(elements) {
+  var V = new Vector();
+  return V.setElements(elements);
+};
+
+// i, j, k unit vectors
+Vector.i = Vector.create([1,0,0]);
+Vector.j = Vector.create([0,1,0]);
+Vector.k = Vector.create([0,0,1]);
+
+// Random vector of size n
+Vector.Random = function(n) {
+  var elements = [];
+  do { elements.push(Math.random());
+  } while (--n);
+  return Vector.create(elements);
+};
+
+// Vector filled with zeros
+Vector.Zero = function(n) {
+  var elements = [];
+  do { elements.push(0);
+  } while (--n);
+  return Vector.create(elements);
+};
+
+
+
+function Matrix() {}
+Matrix.prototype = {
+
+  // Returns element (i,j) of the matrix
+  e: function(i,j) {
+    if (i < 1 || i > this.elements.length || j < 1 || j > this.elements[0].length) { return null; }
+    return this.elements[i-1][j-1];
+  },
+
+  // Returns row k of the matrix as a vector
+  row: function(i) {
+    if (i > this.elements.length) { return null; }
+    return Vector.create(this.elements[i-1]);
+  },
+
+  // Returns column k of the matrix as a vector
+  col: function(j) {
+    if (j > this.elements[0].length) { return null; }
+    var col = [], n = this.elements.length, k = n, i;
+    do { i = k - n;
+      col.push(this.elements[i][j-1]);
+    } while (--n);
+    return Vector.create(col);
+  },
+
+  // Returns the number of rows/columns the matrix has
+  dimensions: function() {
+    return {rows: this.elements.length, cols: this.elements[0].length};
+  },
+
+  // Returns the number of rows in the matrix
+  rows: function() {
+    return this.elements.length;
+  },
+
+  // Returns the number of columns in the matrix
+  cols: function() {
+    return this.elements[0].length;
+  },
+
+  // Returns true iff the matrix is equal to the argument. You can supply
+  // a vector as the argument, in which case the receiver must be a
+  // one-column matrix equal to the vector.
+  eql: function(matrix) {
+    var M = matrix.elements || matrix;
+    if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
+    if (this.elements.length != M.length ||
+        this.elements[0].length != M[0].length) { return false; }
+    var ni = this.elements.length, ki = ni, i, nj, kj = this.elements[0].length, j;
+    do { i = ki - ni;
+      nj = kj;
+      do { j = kj - nj;
+        if (Math.abs(this.elements[i][j] - M[i][j]) > Sylvester.precision) { return false; }
+      } while (--nj);
+    } while (--ni);
+    return true;
+  },
+
+  // Returns a copy of the matrix
+  dup: function() {
+    return Matrix.create(this.elements);
+  },
+
+  // Maps the matrix to another matrix (of the same dimensions) according to the given function
+  map: function(fn) {
+    var els = [], ni = this.elements.length, ki = ni, i, nj, kj = this.elements[0].length, j;
+    do { i = ki - ni;
+      nj = kj;
+      els[i] = [];
+      do { j = kj - nj;
+        els[i][j] = fn(this.elements[i][j], i + 1, j + 1);
+      } while (--nj);
+    } while (--ni);
+    return Matrix.create(els);
+  },
+
+  // Returns true iff the argument has the same dimensions as the matrix
+  isSameSizeAs: function(matrix) {
+    var M = matrix.elements || matrix;
+    if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
+    return (this.elements.length == M.length &&
+        this.elements[0].length == M[0].length);
+  },
+
+  // Returns the result of adding the argument to the matrix
+  add: function(matrix) {
+    var M = matrix.elements || matrix;
+    if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
+    if (!this.isSameSizeAs(M)) { return null; }
+    return this.map(function(x, i, j) { return x + M[i-1][j-1]; });
+  },
+
+  // Returns the result of subtracting the argument from the matrix
+  subtract: function(matrix) {
+    var M = matrix.elements || matrix;
+    if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
+    if (!this.isSameSizeAs(M)) { return null; }
+    return this.map(function(x, i, j) { return x - M[i-1][j-1]; });
+  },
+
+  // Returns true iff the matrix can multiply the argument from the left
+  canMultiplyFromLeft: function(matrix) {
+    var M = matrix.elements || matrix;
+    if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
+    // this.columns should equal matrix.rows
+    return (this.elements[0].length == M.length);
+  },
+
+  // Returns the result of multiplying the matrix from the right by the argument.
+  // If the argument is a scalar then just multiply all the elements. If the argument is
+  // a vector, a vector is returned, which saves you having to remember calling
+  // col(1) on the result.
+  multiply: function(matrix) {
+    if (!matrix.elements) {
+      return this.map(function(x) { return x * matrix; });
+    }
+    var returnVector = matrix.modulus ? true : false;
+    var M = matrix.elements || matrix;
+    if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
+    if (!this.canMultiplyFromLeft(M)) { return null; }
+    var ni = this.elements.length, ki = ni, i, nj, kj = M[0].length, j;
+    var cols = this.elements[0].length, elements = [], sum, nc, c;
+    do { i = ki - ni;
+      elements[i] = [];
+      nj = kj;
+      do { j = kj - nj;
+        sum = 0;
+        nc = cols;
+        do { c = cols - nc;
+          sum += this.elements[i][c] * M[c][j];
+        } while (--nc);
+        elements[i][j] = sum;
+      } while (--nj);
+    } while (--ni);
+    var M = Matrix.create(elements);
+    return returnVector ? M.col(1) : M;
+  },
+
+  x: function(matrix) { return this.multiply(matrix); },
+
+  // Returns a submatrix taken from the matrix
+  // Argument order is: start row, start col, nrows, ncols
+  // Element selection wraps if the required index is outside the matrix's bounds, so you could
+  // use this to perform row/column cycling or copy-augmenting.
+  minor: function(a, b, c, d) {
+    var elements = [], ni = c, i, nj, j;
+    var rows = this.elements.length, cols = this.elements[0].length;
+    do { i = c - ni;
+      elements[i] = [];
+      nj = d;
+      do { j = d - nj;
+        elements[i][j] = this.elements[(a+i-1)%rows][(b+j-1)%cols];
+      } while (--nj);
+    } while (--ni);
+    return Matrix.create(elements);
+  },
+
+  // Returns the transpose of the matrix
+  transpose: function() {
+    var rows = this.elements.length, cols = this.elements[0].length;
+    var elements = [], ni = cols, i, nj, j;
+    do { i = cols - ni;
+      elements[i] = [];
+      nj = rows;
+      do { j = rows - nj;
+        elements[i][j] = this.elements[j][i];
+      } while (--nj);
+    } while (--ni);
+    return Matrix.create(elements);
+  },
+
+  // Returns true iff the matrix is square
+  isSquare: function() {
+    return (this.elements.length == this.elements[0].length);
+  },
+
+  // Returns the (absolute) largest element of the matrix
+  max: function() {
+    var m = 0, ni = this.elements.length, ki = ni, i, nj, kj = this.elements[0].length, j;
+    do { i = ki - ni;
+      nj = kj;
+      do { j = kj - nj;
+        if (Math.abs(this.elements[i][j]) > Math.abs(m)) { m = this.elements[i][j]; }
+      } while (--nj);
+    } while (--ni);
+    return m;
+  },
+
+  // Returns the indeces of the first match found by reading row-by-row from left to right
+  indexOf: function(x) {
+    var index = null, ni = this.elements.length, ki = ni, i, nj, kj = this.elements[0].length, j;
+    do { i = ki - ni;
+      nj = kj;
+      do { j = kj - nj;
+        if (this.elements[i][j] == x) { return {i: i+1, j: j+1}; }
+      } while (--nj);
+    } while (--ni);
+    return null;
+  },
+
+  // If the matrix is square, returns the diagonal elements as a vector.
+  // Otherwise, returns null.
+  diagonal: function() {
+    if (!this.isSquare) { return null; }
+    var els = [], n = this.elements.length, k = n, i;
+    do { i = k - n;
+      els.push(this.elements[i][i]);
+    } while (--n);
+    return Vector.create(els);
+  },
+
+  // Make the matrix upper (right) triangular by Gaussian elimination.
+  // This method only adds multiples of rows to other rows. No rows are
+  // scaled up or switched, and the determinant is preserved.
+  toRightTriangular: function() {
+    var M = this.dup(), els;
+    var n = this.elements.length, k = n, i, np, kp = this.elements[0].length, p;
+    do { i = k - n;
+      if (M.elements[i][i] == 0) {
+        for (j = i + 1; j < k; j++) {
+          if (M.elements[j][i] != 0) {
+            els = []; np = kp;
+            do { p = kp - np;
+              els.push(M.elements[i][p] + M.elements[j][p]);
+            } while (--np);
+            M.elements[i] = els;
+            break;
+          }
+        }
+      }
+      if (M.elements[i][i] != 0) {
+        for (j = i + 1; j < k; j++) {
+          var multiplier = M.elements[j][i] / M.elements[i][i];
+          els = []; np = kp;
+          do { p = kp - np;
+            // Elements with column numbers up to an including the number
+            // of the row that we're subtracting can safely be set straight to
+            // zero, since that's the point of this routine and it avoids having
+            // to loop over and correct rounding errors later
+            els.push(p <= i ? 0 : M.elements[j][p] - M.elements[i][p] * multiplier);
+          } while (--np);
+          M.elements[j] = els;
+        }
+      }
+    } while (--n);
+    return M;
+  },
+
+  toUpperTriangular: function() { return this.toRightTriangular(); },
+
+  // Returns the determinant for square matrices
+  determinant: function() {
+    if (!this.isSquare()) { return null; }
+    var M = this.toRightTriangular();
+    var det = M.elements[0][0], n = M.elements.length - 1, k = n, i;
+    do { i = k - n + 1;
+      det = det * M.elements[i][i];
+    } while (--n);
+    return det;
+  },
+
+  det: function() { return this.determinant(); },
+
+  // Returns true iff the matrix is singular
+  isSingular: function() {
+    return (this.isSquare() && this.determinant() === 0);
+  },
+
+  // Returns the trace for square matrices
+  trace: function() {
+    if (!this.isSquare()) { return null; }
+    var tr = this.elements[0][0], n = this.elements.length - 1, k = n, i;
+    do { i = k - n + 1;
+      tr += this.elements[i][i];
+    } while (--n);
+    return tr;
+  },
+
+  tr: function() { return this.trace(); },
+
+  // Returns the rank of the matrix
+  rank: function() {
+    var M = this.toRightTriangular(), rank = 0;
+    var ni = this.elements.length, ki = ni, i, nj, kj = this.elements[0].length, j;
+    do { i = ki - ni;
+      nj = kj;
+      do { j = kj - nj;
+        if (Math.abs(M.elements[i][j]) > Sylvester.precision) { rank++; break; }
+      } while (--nj);
+    } while (--ni);
+    return rank;
+  },
+  
+  rk: function() { return this.rank(); },
+
+  // Returns the result of attaching the given argument to the right-hand side of the matrix
+  augment: function(matrix) {
+    var M = matrix.elements || matrix;
+    if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
+    var T = this.dup(), cols = T.elements[0].length;
+    var ni = T.elements.length, ki = ni, i, nj, kj = M[0].length, j;
+    if (ni != M.length) { return null; }
+    do { i = ki - ni;
+      nj = kj;
+      do { j = kj - nj;
+        T.elements[i][cols + j] = M[i][j];
+      } while (--nj);
+    } while (--ni);
+    return T;
+  },
+
+  // Returns the inverse (if one exists) using Gauss-Jordan
+  inverse: function() {
+    if (!this.isSquare() || this.isSingular()) { return null; }
+    var ni = this.elements.length, ki = ni, i, j;
+    var M = this.augment(Matrix.I(ni)).toRightTriangular();
+    var np, kp = M.elements[0].length, p, els, divisor;
+    var inverse_elements = [], new_element;
+    // Matrix is non-singular so there will be no zeros on the diagonal
+    // Cycle through rows from last to first
+    do { i = ni - 1;
+      // First, normalise diagonal elements to 1
+      els = []; np = kp;
+      inverse_elements[i] = [];
+      divisor = M.elements[i][i];
+      do { p = kp - np;
+        new_element = M.elements[i][p] / divisor;
+        els.push(new_element);
+        // Shuffle of the current row of the right hand side into the results
+        // array as it will not be modified by later runs through this loop
+        if (p >= ki) { inverse_elements[i].push(new_element); }
+      } while (--np);
+      M.elements[i] = els;
+      // Then, subtract this row from those above it to
+      // give the identity matrix on the left hand side
+      for (j = 0; j < i; j++) {
+        els = []; np = kp;
+        do { p = kp - np;
+          els.push(M.elements[j][p] - M.elements[i][p] * M.elements[j][i]);
+        } while (--np);
+        M.elements[j] = els;
+      }
+    } while (--ni);
+    return Matrix.create(inverse_elements);
+  },
+
+  inv: function() { return this.inverse(); },
+
+  // Returns the result of rounding all the elements
+  round: function() {
+    return this.map(function(x) { return Math.round(x); });
+  },
+
+  // Returns a copy of the matrix with elements set to the given value if they
+  // differ from it by less than Sylvester.precision
+  snapTo: function(x) {
+    return this.map(function(p) {
+      return (Math.abs(p - x) <= Sylvester.precision) ? x : p;
+    });
+  },
+
+  // Returns a string representation of the matrix
+  inspect: function() {
+    var matrix_rows = [];
+    var n = this.elements.length, k = n, i;
+    do { i = k - n;
+      matrix_rows.push(Vector.create(this.elements[i]).inspect());
+    } while (--n);
+    return matrix_rows.join('\n');
+  },
+
+  // Set the matrix's elements from an array. If the argument passed
+  // is a vector, the resulting matrix will be a single column.
+  setElements: function(els) {
+    var i, elements = els.elements || els;
+    if (typeof(elements[0][0]) != 'undefined') {
+      var ni = elements.length, ki = ni, nj, kj, j;
+      this.elements = [];
+      do { i = ki - ni;
+        nj = elements[i].length; kj = nj;
+        this.elements[i] = [];
+        do { j = kj - nj;
+          this.elements[i][j] = elements[i][j];
+        } while (--nj);
+      } while(--ni);
+      return this;
+    }
+    var n = elements.length, k = n;
+    this.elements = [];
+    do { i = k - n;
+      this.elements.push([elements[i]]);
+    } while (--n);
+    return this;
+  }
+};
+
+// Constructor function
+Matrix.create = function(elements) {
+  var M = new Matrix();
+  return M.setElements(elements);
+};
+
+// Identity matrix of size n
+Matrix.I = function(n) {
+  var els = [], k = n, i, nj, j;
+  do { i = k - n;
+    els[i] = []; nj = k;
+    do { j = k - nj;
+      els[i][j] = (i == j) ? 1 : 0;
+    } while (--nj);
+  } while (--n);
+  return Matrix.create(els);
+};
+
+// Diagonal matrix - all off-diagonal elements are zero
+Matrix.Diagonal = function(elements) {
+  var n = elements.length, k = n, i;
+  var M = Matrix.I(n);
+  do { i = k - n;
+    M.elements[i][i] = elements[i];
+  } while (--n);
+  return M;
+};
+
+// Rotation matrix about some axis. If no axis is
+// supplied, assume we're after a 2D transform
+Matrix.Rotation = function(theta, a) {
+  if (!a) {
+    return Matrix.create([
+      [Math.cos(theta),  -Math.sin(theta)],
+      [Math.sin(theta),   Math.cos(theta)]
+    ]);
+  }
+  var axis = a.dup();
+  if (axis.elements.length != 3) { return null; }
+  var mod = axis.modulus();
+  var x = axis.elements[0]/mod, y = axis.elements[1]/mod, z = axis.elements[2]/mod;
+  var s = Math.sin(theta), c = Math.cos(theta), t = 1 - c;
+  // Formula derived here: http://www.gamedev.net/reference/articles/article1199.asp
+  // That proof rotates the co-ordinate system so theta
+  // becomes -theta and sin becomes -sin here.
+  return Matrix.create([
+    [ t*x*x + c, t*x*y - s*z, t*x*z + s*y ],
+    [ t*x*y + s*z, t*y*y + c, t*y*z - s*x ],
+    [ t*x*z - s*y, t*y*z + s*x, t*z*z + c ]
+  ]);
+};
+
+// Special case rotations
+Matrix.RotationX = function(t) {
+  var c = Math.cos(t), s = Math.sin(t);
+  return Matrix.create([
+    [  1,  0,  0 ],
+    [  0,  c, -s ],
+    [  0,  s,  c ]
+  ]);
+};
+Matrix.RotationY = function(t) {
+  var c = Math.cos(t), s = Math.sin(t);
+  return Matrix.create([
+    [  c,  0,  s ],
+    [  0,  1,  0 ],
+    [ -s,  0,  c ]
+  ]);
+};
+Matrix.RotationZ = function(t) {
+  var c = Math.cos(t), s = Math.sin(t);
+  return Matrix.create([
+    [  c, -s,  0 ],
+    [  s,  c,  0 ],
+    [  0,  0,  1 ]
+  ]);
+};
+
+// Random matrix of n rows, m columns
+Matrix.Random = function(n, m) {
+  return Matrix.Zero(n, m).map(
+    function() { return Math.random(); }
+  );
+};
+
+// Matrix filled with zeros
+Matrix.Zero = function(n, m) {
+  var els = [], ni = n, i, nj, j;
+  do { i = n - ni;
+    els[i] = [];
+    nj = m;
+    do { j = m - nj;
+      els[i][j] = 0;
+    } while (--nj);
+  } while (--ni);
+  return Matrix.create(els);
+};
+
+
+
+function Line() {}
+Line.prototype = {
+
+  // Returns true if the argument occupies the same space as the line
+  eql: function(line) {
+    return (this.isParallelTo(line) && this.contains(line.anchor));
+  },
+
+  // Returns a copy of the line
+  dup: function() {
+    return Line.create(this.anchor, this.direction);
+  },
+
+  // Returns the result of translating the line by the given vector/array
+  translate: function(vector) {
+    var V = vector.elements || vector;
+    return Line.create([
+      this.anchor.elements[0] + V[0],
+      this.anchor.elements[1] + V[1],
+      this.anchor.elements[2] + (V[2] || 0)
+    ], this.direction);
+  },
+
+  // Returns true if the line is parallel to the argument. Here, 'parallel to'
+  // means that the argument's direction is either parallel or antiparallel to
+  // the line's own direction. A line is parallel to a plane if the two do not
+  // have a unique intersection.
+  isParallelTo: function(obj) {
+    if (obj.normal) { return obj.isParallelTo(this); }
+    var theta = this.direction.angleFrom(obj.direction);
+    return (Math.abs(theta) <= Sylvester.precision || Math.abs(theta - Math.PI) <= Sylvester.precision);
+  },
+
+  // Returns the line's perpendicular distance from the argument,
+  // which can be a point, a line or a plane
+  distanceFrom: function(obj) {
+    if (obj.normal) { return obj.distanceFrom(this); }
+    if (obj.direction) {
+      // obj is a line
+      if (this.isParallelTo(obj)) { return this.distanceFrom(obj.anchor); }
+      var N = this.direction.cross(obj.direction).toUnitVector().elements;
+      var A = this.anchor.elements, B = obj.anchor.elements;
+      return Math.abs((A[0] - B[0]) * N[0] + (A[1] - B[1]) * N[1] + (A[2] - B[2]) * N[2]);
+    } else {
+      // obj is a point
+      var P = obj.elements || obj;
+      var A = this.anchor.elements, D = this.direction.elements;
+      var PA1 = P[0] - A[0], PA2 = P[1] - A[1], PA3 = (P[2] || 0) - A[2];
+      var modPA = Math.sqrt(PA1*PA1 + PA2*PA2 + PA3*PA3);
+      if (modPA === 0) return 0;
+      // Assumes direction vector is normalized
+      var cosTheta = (PA1 * D[0] + PA2 * D[1] + PA3 * D[2]) / modPA;
+      var sin2 = 1 - cosTheta*cosTheta;
+      return Math.abs(modPA * Math.sqrt(sin2 < 0 ? 0 : sin2));
+    }
+  },
+
+  // Returns true iff the argument is a point on the line
+  contains: function(point) {
+    var dist = this.distanceFrom(point);
+    return (dist !== null && dist <= Sylvester.precision);
+  },
+
+  // Returns true iff the line lies in the given plane
+  liesIn: function(plane) {
+    return plane.contains(this);
+  },
+
+  // Returns true iff the line has a unique point of intersection with the argument
+  intersects: function(obj) {
+    if (obj.normal) { return obj.intersects(this); }
+    return (!this.isParallelTo(obj) && this.distanceFrom(obj) <= Sylvester.precision);
+  },
+
+  // Returns the unique intersection point with the argument, if one exists
+  intersectionWith: function(obj) {
+    if (obj.normal) { return obj.intersectionWith(this); }
+    if (!this.intersects(obj)) { return null; }
+    var P = this.anchor.elements, X = this.direction.elements,
+        Q = obj.anchor.elements, Y = obj.direction.elements;
+    var X1 = X[0], X2 = X[1], X3 = X[2], Y1 = Y[0], Y2 = Y[1], Y3 = Y[2];
+    var PsubQ1 = P[0] - Q[0], PsubQ2 = P[1] - Q[1], PsubQ3 = P[2] - Q[2];
+    var XdotQsubP = - X1*PsubQ1 - X2*PsubQ2 - X3*PsubQ3;
+    var YdotPsubQ = Y1*PsubQ1 + Y2*PsubQ2 + Y3*PsubQ3;
+    var XdotX = X1*X1 + X2*X2 + X3*X3;
+    var YdotY = Y1*Y1 + Y2*Y2 + Y3*Y3;
+    var XdotY = X1*Y1 + X2*Y2 + X3*Y3;
+    var k = (XdotQsubP * YdotY / XdotX + XdotY * YdotPsubQ) / (YdotY - XdotY * XdotY);
+    return Vector.create([P[0] + k*X1, P[1] + k*X2, P[2] + k*X3]);
+  },
+
+  // Returns the point on the line that is closest to the given point or line
+  pointClosestTo: function(obj) {
+    if (obj.direction) {
+      // obj is a line
+      if (this.intersects(obj)) { return this.intersectionWith(obj); }
+      if (this.isParallelTo(obj)) { return null; }
+      var D = this.direction.elements, E = obj.direction.elements;
+      var D1 = D[0], D2 = D[1], D3 = D[2], E1 = E[0], E2 = E[1], E3 = E[2];
+      // Create plane containing obj and the shared normal and intersect this with it
+      // Thank you: http://www.cgafaq.info/wiki/Line-line_distance
+      var x = (D3 * E1 - D1 * E3), y = (D1 * E2 - D2 * E1), z = (D2 * E3 - D3 * E2);
+      var N = Vector.create([x * E3 - y * E2, y * E1 - z * E3, z * E2 - x * E1]);
+      var P = Plane.create(obj.anchor, N);
+      return P.intersectionWith(this);
+    } else {
+      // obj is a point
+      var P = obj.elements || obj;
+      if (this.contains(P)) { return Vector.create(P); }
+      var A = this.anchor.elements, D = this.direction.elements;
+      var D1 = D[0], D2 = D[1], D3 = D[2], A1 = A[0], A2 = A[1], A3 = A[2];
+      var x = D1 * (P[1]-A2) - D2 * (P[0]-A1), y = D2 * ((P[2] || 0) - A3) - D3 * (P[1]-A2),
+          z = D3 * (P[0]-A1) - D1 * ((P[2] || 0) - A3);
+      var V = Vector.create([D2 * x - D3 * z, D3 * y - D1 * x, D1 * z - D2 * y]);
+      var k = this.distanceFrom(P) / V.modulus();
+      return Vector.create([
+        P[0] + V.elements[0] * k,
+        P[1] + V.elements[1] * k,
+        (P[2] || 0) + V.elements[2] * k
+      ]);
+    }
+  },
+
+  // Returns a copy of the line rotated by t radians about the given line. Works by
+  // finding the argument's closest point to this line's anchor point (call this C) and
+  // rotating the anchor about C. Also rotates the line's direction about the argument's.
+  // Be careful with this - the rotation axis' direction affects the outcome!
+  rotate: function(t, line) {
+    // If we're working in 2D
+    if (typeof(line.direction) == 'undefined') { line = Line.create(line.to3D(), Vector.k); }
+    var R = Matrix.Rotation(t, line.direction).elements;
+    var C = line.pointClosestTo(this.anchor).elements;
+    var A = this.anchor.elements, D = this.direction.elements;
+    var C1 = C[0], C2 = C[1], C3 = C[2], A1 = A[0], A2 = A[1], A3 = A[2];
+    var x = A1 - C1, y = A2 - C2, z = A3 - C3;
+    return Line.create([
+      C1 + R[0][0] * x + R[0][1] * y + R[0][2] * z,
+      C2 + R[1][0] * x + R[1][1] * y + R[1][2] * z,
+      C3 + R[2][0] * x + R[2][1] * y + R[2][2] * z
+    ], [
+      R[0][0] * D[0] + R[0][1] * D[1] + R[0][2] * D[2],
+      R[1][0] * D[0] + R[1][1] * D[1] + R[1][2] * D[2],
+      R[2][0] * D[0] + R[2][1] * D[1] + R[2][2] * D[2]
+    ]);
+  },
+
+  // Returns the line's reflection in the given point or line
+  reflectionIn: function(obj) {
+    if (obj.normal) {
+      // obj is a plane
+      var A = this.anchor.elements, D = this.direction.elements;
+      var A1 = A[0], A2 = A[1], A3 = A[2], D1 = D[0], D2 = D[1], D3 = D[2];
+      var newA = this.anchor.reflectionIn(obj).elements;
+      // Add the line's direction vector to its anchor, then mirror that in the plane
+      var AD1 = A1 + D1, AD2 = A2 + D2, AD3 = A3 + D3;
+      var Q = obj.pointClosestTo([AD1, AD2, AD3]).elements;
+      var newD = [Q[0] + (Q[0] - AD1) - newA[0], Q[1] + (Q[1] - AD2) - newA[1], Q[2] + (Q[2] - AD3) - newA[2]];
+      return Line.create(newA, newD);
+    } else if (obj.direction) {
+      // obj is a line - reflection obtained by rotating PI radians about obj
+      return this.rotate(Math.PI, obj);
+    } else {
+      // obj is a point - just reflect the line's anchor in it
+      var P = obj.elements || obj;
+      return Line.create(this.anchor.reflectionIn([P[0], P[1], (P[2] || 0)]), this.direction);
+    }
+  },
+
+  // Set the line's anchor point and direction.
+  setVectors: function(anchor, direction) {
+    // Need to do this so that line's properties are not
+    // references to the arguments passed in
+    anchor = Vector.create(anchor);
+    direction = Vector.create(direction);
+    if (anchor.elements.length == 2) {anchor.elements.push(0); }
+    if (direction.elements.length == 2) { direction.elements.push(0); }
+    if (anchor.elements.length > 3 || direction.elements.length > 3) { return null; }
+    var mod = direction.modulus();
+    if (mod === 0) { return null; }
+    this.anchor = anchor;
+    this.direction = Vector.create([
+      direction.elements[0] / mod,
+      direction.elements[1] / mod,
+      direction.elements[2] / mod
+    ]);
+    return this;
+  }
+};
+
+  
+// Constructor function
+Line.create = function(anchor, direction) {
+  var L = new Line();
+  return L.setVectors(anchor, direction);
+};
+
+// Axes
+Line.X = Line.create(Vector.Zero(3), Vector.i);
+Line.Y = Line.create(Vector.Zero(3), Vector.j);
+Line.Z = Line.create(Vector.Zero(3), Vector.k);
+
+
+
+function Plane() {}
+Plane.prototype = {
+
+  // Returns true iff the plane occupies the same space as the argument
+  eql: function(plane) {
+    return (this.contains(plane.anchor) && this.isParallelTo(plane));
+  },
+
+  // Returns a copy of the plane
+  dup: function() {
+    return Plane.create(this.anchor, this.normal);
+  },
+
+  // Returns the result of translating the plane by the given vector
+  translate: function(vector) {
+    var V = vector.elements || vector;
+    return Plane.create([
+      this.anchor.elements[0] + V[0],
+      this.anchor.elements[1] + V[1],
+      this.anchor.elements[2] + (V[2] || 0)
+    ], this.normal);
+  },
+
+  // Returns true iff the plane is parallel to the argument. Will return true
+  // if the planes are equal, or if you give a line and it lies in the plane.
+  isParallelTo: function(obj) {
+    var theta;
+    if (obj.normal) {
+      // obj is a plane
+      theta = this.normal.angleFrom(obj.normal);
+      return (Math.abs(theta) <= Sylvester.precision || Math.abs(Math.PI - theta) <= Sylvester.precision);
+    } else if (obj.direction) {
+      // obj is a line
+      return this.normal.isPerpendicularTo(obj.direction);
+    }
+    return null;
+  },
+  
+  // Returns true iff the receiver is perpendicular to the argument
+  isPerpendicularTo: function(plane) {
+    var theta = this.normal.angleFrom(plane.normal);
+    return (Math.abs(Math.PI/2 - theta) <= Sylvester.precision);
+  },
+
+  // Returns the plane's distance from the given object (point, line or plane)
+  distanceFrom: function(obj) {
+    if (this.intersects(obj) || this.contains(obj)) { return 0; }
+    if (obj.anchor) {
+      // obj is a plane or line
+      var A = this.anchor.elements, B = obj.anchor.elements, N = this.normal.elements;
+      return Math.abs((A[0] - B[0]) * N[0] + (A[1] - B[1]) * N[1] + (A[2] - B[2]) * N[2]);
+    } else {
+      // obj is a point
+      var P = obj.elements || obj;
+      var A = this.anchor.elements, N = this.normal.elements;
+      return Math.abs((A[0] - P[0]) * N[0] + (A[1] - P[1]) * N[1] + (A[2] - (P[2] || 0)) * N[2]);
+    }
+  },
+
+  // Returns true iff the plane contains the given point or line
+  contains: function(obj) {
+    if (obj.normal) { return null; }
+    if (obj.direction) {
+      return (this.contains(obj.anchor) && this.contains(obj.anchor.add(obj.direction)));
+    } else {
+      var P = obj.elements || obj;
+      var A = this.anchor.elements, N = this.normal.elements;
+      var diff = Math.abs(N[0]*(A[0] - P[0]) + N[1]*(A[1] - P[1]) + N[2]*(A[2] - (P[2] || 0)));
+      return (diff <= Sylvester.precision);
+    }
+  },
+
+  // Returns true iff the plane has a unique point/line of intersection with the argument
+  intersects: function(obj) {
+    if (typeof(obj.direction) == 'undefined' && typeof(obj.normal) == 'undefined') { return null; }
+    return !this.isParallelTo(obj);
+  },
+
+  // Returns the unique intersection with the argument, if one exists. The result
+  // will be a vector if a line is supplied, and a line if a plane is supplied.
+  intersectionWith: function(obj) {
+    if (!this.intersects(obj)) { return null; }
+    if (obj.direction) {
+      // obj is a line
+      var A = obj.anchor.elements, D = obj.direction.elements,
+          P = this.anchor.elements, N = this.normal.elements;
+      var multiplier = (N[0]*(P[0]-A[0]) + N[1]*(P[1]-A[1]) + N[2]*(P[2]-A[2])) / (N[0]*D[0] + N[1]*D[1] + N[2]*D[2]);
+      return Vector.create([A[0] + D[0]*multiplier, A[1] + D[1]*multiplier, A[2] + D[2]*multiplier]);
+    } else if (obj.normal) {
+      // obj is a plane
+      var direction = this.normal.cross(obj.normal).toUnitVector();
+      // To find an anchor point, we find one co-ordinate that has a value
+      // of zero somewhere on the intersection, and remember which one we picked
+      var N = this.normal.elements, A = this.anchor.elements,
+          O = obj.normal.elements, B = obj.anchor.elements;
+      var solver = Matrix.Zero(2,2), i = 0;
+      while (solver.isSingular()) {
+        i++;
+        solver = Matrix.create([
+          [ N[i%3], N[(i+1)%3] ],
+          [ O[i%3], O[(i+1)%3]  ]
+        ]);
+      }
+      // Then we solve the simultaneous equations in the remaining dimensions
+      var inverse = solver.inverse().elements;
+      var x = N[0]*A[0] + N[1]*A[1] + N[2]*A[2];
+      var y = O[0]*B[0] + O[1]*B[1] + O[2]*B[2];
+      var intersection = [
+        inverse[0][0] * x + inverse[0][1] * y,
+        inverse[1][0] * x + inverse[1][1] * y
+      ];
+      var anchor = [];
+      for (var j = 1; j <= 3; j++) {
+        // This formula picks the right element from intersection by
+        // cycling depending on which element we set to zero above
+        anchor.push((i == j) ? 0 : intersection[(j + (5 - i)%3)%3]);
+      }
+      return Line.create(anchor, direction);
+    }
+  },
+
+  // Returns the point in the plane closest to the given point
+  pointClosestTo: function(point) {
+    var P = point.elements || point;
+    var A = this.anchor.elements, N = this.normal.elements;
+    var dot = (A[0] - P[0]) * N[0] + (A[1] - P[1]) * N[1] + (A[2] - (P[2] || 0)) * N[2];
+    return Vector.create([P[0] + N[0] * dot, P[1] + N[1] * dot, (P[2] || 0) + N[2] * dot]);
+  },
+
+  // Returns a copy of the plane, rotated by t radians about the given line
+  // See notes on Line#rotate.
+  rotate: function(t, line) {
+    var R = Matrix.Rotation(t, line.direction).elements;
+    var C = line.pointClosestTo(this.anchor).elements;
+    var A = this.anchor.elements, N = this.normal.elements;
+    var C1 = C[0], C2 = C[1], C3 = C[2], A1 = A[0], A2 = A[1], A3 = A[2];
+    var x = A1 - C1, y = A2 - C2, z = A3 - C3;
+    return Plane.create([
+      C1 + R[0][0] * x + R[0][1] * y + R[0][2] * z,
+      C2 + R[1][0] * x + R[1][1] * y + R[1][2] * z,
+      C3 + R[2][0] * x + R[2][1] * y + R[2][2] * z
+    ], [
+      R[0][0] * N[0] + R[0][1] * N[1] + R[0][2] * N[2],
+      R[1][0] * N[0] + R[1][1] * N[1] + R[1][2] * N[2],
+      R[2][0] * N[0] + R[2][1] * N[1] + R[2][2] * N[2]
+    ]);
+  },
+
+  // Returns the reflection of the plane in the given point, line or plane.
+  reflectionIn: function(obj) {
+    if (obj.normal) {
+      // obj is a plane
+      var A = this.anchor.elements, N = this.normal.elements;
+      var A1 = A[0], A2 = A[1], A3 = A[2], N1 = N[0], N2 = N[1], N3 = N[2];
+      var newA = this.anchor.reflectionIn(obj).elements;
+      // Add the plane's normal to its anchor, then mirror that in the other plane
+      var AN1 = A1 + N1, AN2 = A2 + N2, AN3 = A3 + N3;
+      var Q = obj.pointClosestTo([AN1, AN2, AN3]).elements;
+      var newN = [Q[0] + (Q[0] - AN1) - newA[0], Q[1] + (Q[1] - AN2) - newA[1], Q[2] + (Q[2] - AN3) - newA[2]];
+      return Plane.create(newA, newN);
+    } else if (obj.direction) {
+      // obj is a line
+      return this.rotate(Math.PI, obj);
+    } else {
+      // obj is a point
+      var P = obj.elements || obj;
+      return Plane.create(this.anchor.reflectionIn([P[0], P[1], (P[2] || 0)]), this.normal);
+    }
+  },
+
+  // Sets the anchor point and normal to the plane. If three arguments are specified,
+  // the normal is calculated by assuming the three points should lie in the same plane.
+  // If only two are sepcified, the second is taken to be the normal. Normal vector is
+  // normalised before storage.
+  setVectors: function(anchor, v1, v2) {
+    anchor = Vector.create(anchor);
+    anchor = anchor.to3D(); if (anchor === null) { return null; }
+    v1 = Vector.create(v1);
+    v1 = v1.to3D(); if (v1 === null) { return null; }
+    if (typeof(v2) == 'undefined') {
+      v2 = null;
+    } else {
+      v2 = Vector.create(v2);
+      v2 = v2.to3D(); if (v2 === null) { return null; }
+    }
+    var A1 = anchor.elements[0], A2 = anchor.elements[1], A3 = anchor.elements[2];
+    var v11 = v1.elements[0], v12 = v1.elements[1], v13 = v1.elements[2];
+    var normal, mod;
+    if (v2 !== null) {
+      var v21 = v2.elements[0], v22 = v2.elements[1], v23 = v2.elements[2];
+      normal = Vector.create([
+        (v12 - A2) * (v23 - A3) - (v13 - A3) * (v22 - A2),
+        (v13 - A3) * (v21 - A1) - (v11 - A1) * (v23 - A3),
+        (v11 - A1) * (v22 - A2) - (v12 - A2) * (v21 - A1)
+      ]);
+      mod = normal.modulus();
+      if (mod === 0) { return null; }
+      normal = Vector.create([normal.elements[0] / mod, normal.elements[1] / mod, normal.elements[2] / mod]);
+    } else {
+      mod = Math.sqrt(v11*v11 + v12*v12 + v13*v13);
+      if (mod === 0) { return null; }
+      normal = Vector.create([v1.elements[0] / mod, v1.elements[1] / mod, v1.elements[2] / mod]);
+    }
+    this.anchor = anchor;
+    this.normal = normal;
+    return this;
+  }
+};
+
+// Constructor function
+Plane.create = function(anchor, v1, v2) {
+  var P = new Plane();
+  return P.setVectors(anchor, v1, v2);
+};
+
+// X-Y-Z planes
+Plane.XY = Plane.create(Vector.Zero(3), Vector.k);
+Plane.YZ = Plane.create(Vector.Zero(3), Vector.i);
+Plane.ZX = Plane.create(Vector.Zero(3), Vector.j);
+Plane.YX = Plane.XY; Plane.ZY = Plane.YZ; Plane.XZ = Plane.ZX;
+
+// Utility functions
+var $V = Vector.create;
+var $M = Matrix.create;
+var $L = Line.create;
+var $P = Plane.create;
diff --git a/lang/CMakeLists.txt b/lang/CMakeLists.txt
new file mode 100644
index 0000000..5280c1c
--- /dev/null
+++ b/lang/CMakeLists.txt
@@ -0,0 +1,136 @@
+set(src_imp_dep
+../include/mgl2/type.h
+../include/mgl2/data.h
+../include/mgl2/mgl.h
+mgl.i
+data.i
+type.i
+)
+
+set(mgl_clean_files "")
+
+SET_SOURCE_FILES_PROPERTIES(mathgl.i numpy.i PROPERTIES CPLUSPLUS ON)
+
+FIND_PACKAGE(SWIG)
+if(NOT SWIG_FOUND)
+	message(SEND_ERROR "Couldn't find swig needed for interfaces compiling.")
+endif(NOT SWIG_FOUND)
+INCLUDE(${SWIG_USE_FILE})
+
+if(enable-python)
+	set(Python_ADDITIONAL_VERSIONS 2.7)
+	FIND_PACKAGE(PythonInterp)
+	if(NOT PYTHONINTERP_FOUND)
+		message(SEND_ERROR "Couldn't find python interpreter.")
+	endif(NOT PYTHONINTERP_FOUND)
+	FIND_PACKAGE(PythonLibs)
+	if(NOT PYTHONLIBS_FOUND)
+		message(SEND_ERROR "Couldn't find python development libraries.")
+	endif(NOT PYTHONLIBS_FOUND)
+	execute_process(
+		COMMAND ${PYTHON_EXECUTABLE} -c "import numpy; print numpy.get_include()"
+		OUTPUT_VARIABLE NUMPY_INCLUDE_PATH
+		RESULT_VARIABLE NUMPY_ERR
+		OUTPUT_STRIP_TRAILING_WHITESPACE
+	)
+	if(NOT NUMPY_INCLUDE_PATH)
+		message(SEND_ERROR "Couldn't find numpy.")
+	endif(NOT NUMPY_INCLUDE_PATH)
+
+	include_directories(${PYTHON_INCLUDE_DIR}  ${NUMPY_INCLUDE_PATH})
+	execute_process(
+		COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(prefix='${CMAKE_INSTALL_PREFIX}')"
+		OUTPUT_VARIABLE MGL_PYTHON_SITE_PACKAGES
+		OUTPUT_STRIP_TRAILING_WHITESPACE)
+	set(SWIG_MODULE_mathgl_EXTRA_DEPS numpy.i ${src_imp_dep})
+	SWIG_ADD_MODULE(mathgl python mathgl.i)
+	SWIG_LINK_LIBRARIES(mathgl mgl ${PYTHON_LIBRARIES})
+	set_target_properties(_mathgl PROPERTIES BUILD_WITH_INSTALL_RPATH ON)
+	add_custom_command(OUTPUT mathgl.pyc
+		COMMAND ${PYTHON_EXECUTABLE}
+		ARGS -c \"from py_compile import compile\; compile('mathgl.py') \"
+		WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/lang
+		DEPENDS _mathgl
+	)
+	add_custom_target(mgl_python_module ALL DEPENDS _mathgl mathgl.pyc)
+
+	install(FILES ${MathGL2_BINARY_DIR}/lang/mathgl.py ${MathGL2_BINARY_DIR}/lang/mathgl.pyc DESTINATION ${MGL_PYTHON_SITE_PACKAGES})
+	install (TARGETS _mathgl LIBRARY DESTINATION ${MGL_PYTHON_SITE_PACKAGES})
+	set(mgl_clean_files ${mgl_clean_files} mathgl.py)
+endif(enable-python)
+
+if(enable-lua)
+	INCLUDE(FindLua51)
+	if(NOT LUA51_FOUND)
+		message(SEND_ERROR "Couldn't find Lua 5.1 library.")
+	endif(NOT LUA51_FOUND)
+
+	include_directories(${LUA_INCLUDE_DIR})
+	set(SWIG_MODULE_mgl-lua_EXTRA_DEPS numpy.i ${src_imp_dep})
+	SWIG_ADD_MODULE(mgl-lua lua mathgl.i)
+	SWIG_LINK_LIBRARIES(mgl-lua mgl ${LUA_LIBRARIES})
+	set_target_properties(mgl-lua PROPERTIES PREFIX "" BUILD_WITH_INSTALL_RPATH ON)
+
+	install (TARGETS mgl-lua LIBRARY DESTINATION ${MathGL_INSTALL_LIB_DIR})
+endif(enable-lua)
+
+if(enable-octave)
+	find_program(oct_prog octave-config)
+	if(NOT oct_prog)
+		message(SEND_ERROR "Couldn't find octave-config needed for octave interfaces compiling.")
+	endif(NOT oct_prog)
+	find_program(oct_exec octave)
+	if(NOT oct_exec)
+		message(SEND_ERROR "Couldn't find octave needed for octave interfaces compiling.")
+	endif(NOT oct_exec)
+	find_program(oct_mk mkoctfile)
+	if(NOT oct_mk)
+		message(SEND_ERROR "Couldn't find mkoctfile needed for octave interfaces compiling.")
+	endif(NOT oct_mk)
+	find_program(oct_tar tar)
+	if(NOT oct_tar)
+		message(SEND_ERROR "Couldn't find tar needed for octave interfaces creation.")
+	endif(NOT oct_tar)
+
+	execute_process(COMMAND ${oct_prog} -p CANONICAL_HOST_TYPE
+	OUTPUT_VARIABLE oct_host
+	OUTPUT_STRIP_TRAILING_WHITESPACE)
+	execute_process(COMMAND ${oct_prog} -p API_VERSION
+	OUTPUT_VARIABLE oct_api
+	OUTPUT_STRIP_TRAILING_WHITESPACE)
+	execute_process(COMMAND ${oct_mk} -p INCFLAGS
+	OUTPUT_VARIABLE oct_inc
+	OUTPUT_STRIP_TRAILING_WHITESPACE)
+	separate_arguments(oct_inc)
+message(STATUS "${oct_prog} ${oct_host} ${oct_api}")
+	set(oct_arch ${oct_host}-${oct_api})
+	set(pkg_name mathgl)
+	set(mgl_pkg_dir ${MathGL2_BINARY_DIR}/lang/${pkg_name}/inst/${oct_arch})
+
+	add_compile_options(${oct_inc})
+	SET(SWIG_MODULE_mgl-oct_EXTRA_DEPS numpy.i ${src_imp_dep})
+	SWIG_ADD_MODULE(mgl-oct octave mathgl.i)
+	SWIG_LINK_LIBRARIES(mgl-oct mgl)
+	set_target_properties(mgl-oct PROPERTIES OUTPUT_NAME mathgl PREFIX "" SUFFIX ".oct" BUILD_WITH_INSTALL_RPATH ON)
+	add_custom_command(OUTPUT mathgl.tar.gz
+		COMMAND ${CMAKE_COMMAND} -E make_directory ${mgl_pkg_dir}
+		COMMAND ${CMAKE_COMMAND} -E copy ${MathGL2_SOURCE_DIR}/COPYING ${MathGL2_BINARY_DIR}/lang/${pkg_name}
+		COMMAND ${CMAKE_COMMAND} -E copy ${MathGL2_SOURCE_DIR}/lang/DESCRIPTION ${MathGL2_BINARY_DIR}/lang/${pkg_name}
+		COMMAND ${CMAKE_COMMAND} -E copy ${MathGL2_SOURCE_DIR}/lang/INDEX ${MathGL2_BINARY_DIR}/lang/${pkg_name}
+		COMMAND ${CMAKE_COMMAND} -E copy ${MathGL2_SOURCE_DIR}/lang/PKG_ADD_template ${MathGL2_BINARY_DIR}/lang/${pkg_name}
+		COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:mgl-oct> ${mgl_pkg_dir}
+		COMMAND ${oct_tar} cpzf mathgl.tar.gz ${pkg_name}
+		WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/lang
+		DEPENDS mgl-oct
+	)
+	add_custom_target(mgl_octave_module ALL DEPENDS mathgl.tar.gz)
+
+	install(FILES ${CMAKE_BINARY_DIR}/lang/mathgl.tar.gz DESTINATION ${MGL_DATA_PATH})
+	if(enable-octave-install)
+		install(CODE "execute_process(
+			COMMAND ${oct_exec} -q --eval \"pkg install mathgl.tar.gz\"
+			WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/lang )")
+	endif(enable-octave-install)
+	set(mgl_clean_files ${mgl_clean_files} mathgl)
+endif(enable-octave)
+set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${mgl_clean_files}")
diff --git a/lang/DESCRIPTION b/lang/DESCRIPTION
new file mode 100644
index 0000000..b7398da
--- /dev/null
+++ b/lang/DESCRIPTION
@@ -0,0 +1,13 @@
+Name: mathgl
+Version: 2.0
+Date: 2011-08-23
+Author: Alexey Balakin
+Maintainer: Dmitry Kulagin
+Title: MathGL
+Description: Data plotting library
+Depends: octave (>= 2.9.12)
+Autoload: yes
+SystemRequirements: ...
+License: GPL
+Keywords: ...
+Url: http://octave.sf.net http://mathgl.sf.net
diff --git a/lang/INDEX b/lang/INDEX
new file mode 100644
index 0000000..e69de29
diff --git a/lang/PKG_ADD_template b/lang/PKG_ADD_template
new file mode 100644
index 0000000..761b400
--- /dev/null
+++ b/lang/PKG_ADD_template
@@ -0,0 +1,2 @@
+mathgl;
+
diff --git a/lang/data.i b/lang/data.i
new file mode 100644
index 0000000..e61c529
--- /dev/null
+++ b/lang/data.i
@@ -0,0 +1,585 @@
+/***************************************************************************
+ * data.i is part of Math Graphic Library
+ * Copyright (C) 2007-2012 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+//-----------------------------------------------------------------------------
+#include <string>
+class mglData
+{
+public:
+
+	long nx;		///< number of points in 1st dimensions ('x' dimension)
+	long ny;		///< number of points in 2nd dimensions ('y' dimension)
+	long nz;		///< number of points in 3d dimensions ('z' dimension)
+	mreal *a;		///< data array
+	std::string id;	///< column (or slice) names
+	bool link;		///< use external data (i.e. don't free it)
+
+	/// Initiate by other mglData variable
+	mglData(const mglData &d)	{	a=0;	mgl_data_set(this,&d);		}	// NOTE: must be constructor for mglData& to exclude copy one
+	mglData(const mglData *d)	{	a=0;	mgl_data_set(this, d);		}
+	mglData(bool, mglData *d)	// NOTE: Variable d will be deleted!!!
+	{	if(d)
+		{	nx=d->nx;	ny=d->ny;	nz=d->nz;	a=d->a;	d->a=0;
+			id=d->id;	link=d->link;	delete d;	}
+		else	{	a=0;	Create(1);	}	}
+	/// Initiate by flat array
+	mglData(int size, const float *d)	{	a=0;	Set(d,size);	}
+	mglData(int rows, int cols, const float *d)	{	a=0;	Set(d,cols,rows);	}
+	mglData(int size, const double *d)	{	a=0;	Set(d,size);	}
+	mglData(int rows, int cols, const double *d)	{	a=0;	Set(d,cols,rows);	}
+	mglData(const double *d, int size)	{	a=0;	Set(d,size);	}
+	mglData(const double *d, int rows, int cols)	{	a=0;	Set(d,cols,rows);	}
+	mglData(const float *d, int size)	{	a=0;	Set(d,size);	}
+	mglData(const float *d, int rows, int cols)	{	a=0;	Set(d,cols,rows);	}
+	/// Read data from file
+	mglData(const char *fname)			{	a=0;	Read(fname);	}
+	/// Allocate the memory for data array and initialize it zero
+	mglData(long xx=1,long yy=1,long zz=1)	{	a=0;	Create(xx,yy,zz);	}
+	/// Delete the array
+	virtual ~mglData()	{	if(!link && a)	delete []a;	}
+
+	inline mreal GetVal(long i, long j=0, long k=0) const
+	{	return mgl_data_get_value(this,i,j,k);}
+	inline void SetVal(mreal f, long i, long j=0, long k=0)
+	{	mgl_data_set_value(this,f,i,j,k);	}
+	/// Get sizes
+	long GetNx() const	{	return nx;	}
+	long GetNy() const	{	return ny;	}
+	long GetNz() const	{	return nz;	}
+
+	/// Link external data array (don't delete it at exit)
+	inline void Link(mreal *A, long NX, long NY=1, long NZ=1)
+	{	mgl_data_link(this,A,NX,NY,NZ);	}
+	inline void Link(mglData &d)	{	Link(d.a,d.nx,d.ny,d.nz);	}
+	/// Allocate memory and copy the data from the gsl_vector
+	inline void Set(gsl_vector *m)	{	mgl_data_set_vector(this,m);	}
+	/// Allocate memory and copy the data from the gsl_matrix
+	inline void Set(gsl_matrix *m)	{	mgl_data_set_matrix(this,m);	}
+
+	/// Allocate memory and copy the data from the (float *) array
+	inline void Set(const float *A,long NX,long NY=1,long NZ=1)
+	{	mgl_data_set_float(this,A,NX,NY,NZ);	}
+	/// Allocate memory and copy the data from the (double *) array
+	inline void Set(const double *A,long NX,long NY=1,long NZ=1)
+	{	mgl_data_set_double(this,A,NX,NY,NZ);	}
+	/// Allocate memory and copy the data from the (float **) array
+	inline void Set(float const * const *A,long N1,long N2)
+	{	mgl_data_set_float2(this,A,N1,N2);	}
+	/// Allocate memory and copy the data from the (double **) array
+	inline void Set(double const * const *A,long N1,long N2)
+	{	mgl_data_set_double2(this,A,N1,N2);	}
+	/// Allocate memory and copy the data from the (float ***) array
+	inline void Set(float const * const * const *A,long N1,long N2,long N3)
+	{	mgl_data_set_float3(this,A,N1,N2,N3);	}
+	/// Allocate memory and copy the data from the (double ***) array
+	inline void Set(double const * const * const *A,long N1,long N2,long N3)
+	{	mgl_data_set_double3(this,A,N1,N2,N3);	}
+	/// Allocate memory and scanf the data from the string
+	inline void Set(const char *str,long NX,long NY=1,long NZ=1)
+	{	mgl_data_set_values(this,str,NX,NY,NZ);	}
+	/// Import data from abstract type
+	inline void Set(const mglData &dat)	{	mgl_data_set(this, &dat);	}
+
+	/// Create or recreate the array with specified size and fill it by zero
+	inline void Create(long mx,long my=1,long mz=1)
+	{	mgl_data_create(this,mx,my,mz);	}
+	/// Rearange data dimensions
+	inline void Rearrange(long mx, long my=0, long mz=0)
+	{	mgl_data_rearrange(this,mx,my,mz);	}
+	/// Transpose dimensions of the data (generalization of Transpose)
+	inline void Transpose(const char *dim="yx")
+	{	mgl_data_transpose(this,dim);	}
+	/// Extend data dimensions
+	inline void Extend(long n1, long n2=0)
+	{	mgl_data_extend(this,n1,n2);	}
+	/// Reduce size of the data
+	inline void Squeeze(long rx,long ry=1,long rz=1,bool smooth=false)
+	{	mgl_data_squeeze(this,rx,ry,rz,smooth);	}
+	/// Crop the data
+	inline void Crop(long n1, long n2,char dir='x')
+	{	mgl_data_crop(this,n1,n2,dir);	}
+	/// Insert data rows/columns/slices
+	inline void Insert(char dir, long at=0, long num=1)
+	{	mgl_data_insert(this,dir,at,num);	}
+	/// Delete data rows/columns/slices
+	inline void Delete(char dir, long at=0, long num=1)
+	{	mgl_data_delete(this,dir,at,num);	}
+	/// Remove rows with duplicate values in column clmn
+	inline void Clean(long clmn)
+	{	mgl_data_clean(this,clmn);	}
+	/// Join with another data array
+	inline void Join(const mglData &d)
+	{	mgl_data_join(this,&d);	}
+
+	/// Modify the data by specified formula
+	inline void Modify(const char *eq,long dim=0)
+	{	mgl_data_modify(this, eq, dim);	}
+	/// Modify the data by specified formula
+	inline void Modify(const char *eq,const mglData &vdat, const mglData &wdat)
+	{	mgl_data_modify_vw(this,eq,&vdat,&wdat);	}
+	/// Modify the data by specified formula
+	inline void Modify(const char *eq,const mglData &vdat)
+	{	mgl_data_modify_vw(this,eq,&vdat,0);	}
+	/// Modify the data by specified formula assuming x,y,z in range [r1,r2]
+	inline void Fill(HMGL gr, const char *eq, const char *opt="")
+	{	mgl_data_fill_eq(gr,this,eq,0,0,opt);	}
+	inline void Fill(HMGL gr, const char *eq, const mglData &vdat, const char *opt="")
+	{	mgl_data_fill_eq(gr,this,eq,&vdat,0,opt);	}
+	inline void Fill(HMGL gr, const char *eq, const mglData &vdat, const mglData &wdat,const char *opt="")
+	{	mgl_data_fill_eq(gr,this,eq,&vdat,&wdat,opt);	}
+	/// Equidistantly fill the data to range [x1,x2] in direction dir
+	inline void Fill(mreal x1,mreal x2=NaN,char dir='x')
+	{	mgl_data_fill(this,x1,x2,dir);	}
+	/// Fill the data by interpolated values of vdat parametrically depended on xdat,ydat,zdat for x,y,z in range [p1,p2] using global spline
+	inline void RefillGS(const mglData &xdat, const mglData &vdat, mreal x1, mreal x2,long sl=-1)
+	{	mgl_data_refill_gs(this,&xdat,&vdat,x1,x2,sl);	}
+	/// Fill the data by interpolated values of vdat parametrically depended on xdat,ydat,zdat for x,y,z in range [p1,p2]
+	inline void Refill(const mglData &xdat, const mglData &vdat, mreal x1, mreal x2,long sl=-1)
+	{	mgl_data_refill_x(this,&xdat,&vdat,x1,x2,sl);	}
+	inline void Refill(const mglData &xdat, const mglData &vdat, mglPoint p1, mglPoint p2,long sl=-1)
+	{	mgl_data_refill_x(this,&xdat,&vdat,p1.x,p2.x,sl);	}
+	inline void Refill(const mglData &xdat, const mglData &ydat, const mglData &vdat, mglPoint p1, mglPoint p2,long sl=-1)
+	{	mgl_data_refill_xy(this,&xdat,&ydat,&vdat,p1.x,p2.x,p1.y,p2.y,sl);	}
+	inline void Refill(const mglData &xdat, const mglData &ydat, const mglData &zdat, const mglData &vdat, mglPoint p1, mglPoint p2)
+	{	mgl_data_refill_xyz(this,&xdat,&ydat,&zdat,&vdat,p1.x,p2.x,p1.y,p2.y,p1.z,p2.z);	}
+	/// Fill the data by interpolated values of vdat parametrically depended on xdat,ydat,zdat for x,y,z in axis range of gr
+	inline void Refill(HMGL gr, const mglData &xdat, const mglData &vdat, long sl=-1, const char *opt="")
+	{	mgl_data_refill_gr(gr,this,&xdat,0,0,&vdat,sl,opt);	}
+	inline void Refill(HMGL gr, const mglData &xdat, const mglData &ydat, const mglData &vdat, long sl=-1, const char *opt="")
+	{	mgl_data_refill_gr(gr,this,&xdat,&ydat,0,&vdat,sl,opt);	}
+	inline void Refill(HMGL gr, const mglData &xdat, const mglData &ydat, const mglData &zdat, const mglData &vdat, const char *opt="")
+	{	mgl_data_refill_gr(gr,this,&xdat,&ydat,&zdat,&vdat,-1,opt);	}
+	/// Set the data by triangulated surface values assuming x,y,z in axis range of gr
+	inline void Grid(HMGL gr, const mglData &x, const mglData &y, const mglData &z, const char *opt="")
+	{	mgl_data_grid(gr,this,&x,&y,&z,opt);	}
+	/// Set the data by triangulated surface values assuming x,y,z in range [p1, p2]
+	inline void Grid(const mglData &xdat, const mglData &ydat, const mglData &vdat, mglPoint p1, mglPoint p2)
+	{	mgl_data_grid_xy(this,&xdat,&ydat,&vdat,p1.x,p2.x,p1.y,p2.y);	}
+	/// Put value to data element(s)
+	inline void Put(mreal val, long i=-1, long j=-1, long k=-1)
+	{	mgl_data_put_val(this,val,i,j,k);	}
+	/// Put array to data element(s)
+	inline void Put(const mglData &dat, long i=-1, long j=-1, long k=-1)
+	{	mgl_data_put_dat(this,&dat,i,j,k);	}
+	/// Set names for columns (slices)
+	inline void SetColumnId(const char *ids)
+	{	mgl_data_set_id(this,ids);	}
+	/// Make new id
+	inline void NewId()	{	id.clear();	}
+
+	/// Read data from tab-separated text file with auto determining size
+	inline bool Read(const char *fname)
+	{	return mgl_data_read(this,fname); }
+	/// Read data from text file with specifeid size
+	inline bool Read(const char *fname,long mx,long my=1,long mz=1)
+	{	return mgl_data_read_dim(this,fname,mx,my,mz);	}
+	/// Save whole data array (for ns=-1) or only ns-th slice to text file
+	inline void Save(const char *fname,long ns=-1) const
+	{	mgl_data_save(this,fname,ns);	}
+	/// Export data array (for ns=-1) or only ns-th slice to PNG file according color scheme
+	inline void Export(const char *fname,const char *scheme,mreal v1=0,mreal v2=0,long ns=-1) const
+	{	mgl_data_export(this,fname,scheme,v1,v2,ns);	}
+	/// Import data array from PNG file according color scheme
+	inline void Import(const char *fname,const char *scheme,mreal v1=0,mreal v2=1)
+	{	mgl_data_import(this,fname,scheme,v1,v2);	}
+	/// Read data from tab-separated text files with auto determining size which filenames are result of sprintf(fname,templ,t) where t=from:step:to
+	inline bool ReadRange(const char *templ, double from, double to, double step=1, bool as_slice=false)
+	{	return mgl_data_read_range(this,templ,from,to,step,as_slice);	}
+	/// Read data from tab-separated text files with auto determining size which filenames are satisfied to template (like "t_*.dat")
+	inline bool ReadAll(const char *templ, bool as_slice=false)
+	{	return mgl_data_read_all(this, templ, as_slice);	}
+	/// Read data from text file with size specified at beginning of the file
+	inline bool ReadMat(const char *fname, long dim=2)
+	{	return mgl_data_read_mat(this,fname,dim);	}
+	/// Read data array from HDF file (parse HDF4 and HDF5 files)
+	inline int ReadHDF(const char *fname,const char *data)
+	{	return mgl_data_read_hdf(this,fname,data);	}
+	/// Save data to HDF file
+	inline void SaveHDF(const char *fname,const char *data,bool rewrite=false) const
+	{	mgl_data_save_hdf(this,fname,data,rewrite);	}
+	/// Put HDF data names into buf as '\t' separated.
+	inline static int DatasHDF(const char *fname, char *buf, long size)
+	{	return mgl_datas_hdf(fname,buf,size);	}
+	/// Scan textual file for template and fill data array
+	inline int ScanFile(const char *fname, const char *templ)
+	{	return mgl_data_scan_file(this,fname, templ);	}
+
+	/// Get column (or slice) of the data filled by formulas of named columns
+	inline mglData Column(const char *eq) const
+	{	return mglData(true,mgl_data_column(this,eq));	}
+	/// Get momentum (1D-array) of data along direction 'dir'. String looks like "x1" for median in x-direction, "x2" for width in x-dir and so on.
+	inline mglData Momentum(char dir, const char *how) const
+	{	return mglData(true,mgl_data_momentum(this,dir,how));	}
+	/// Get pulse properties: pulse maximum and its position, pulse duration near maximum and by half height, energy in first pulse.
+	inline mglData Pulse(char dir) const
+	{	return mglData(true,mgl_data_pulse(this,dir));	}
+	/// Get sub-array of the data with given fixed indexes
+	inline mglData SubData(long xx,long yy=-1,long zz=-1) const
+	{	return mglData(true,mgl_data_subdata(this,xx,yy,zz));	}
+	inline mglData SubData(const mglData &xx, const mglData &yy, const mglData &zz) const
+	{	return mglData(true,mgl_data_subdata_ext(this,&xx,&yy,&zz));	}
+	inline mglData SubData(const mglData &xx, const mglData &yy) const
+	{	return mglData(true,mgl_data_subdata_ext(this,&xx,&yy,0));	}
+	inline mglData SubData(const mglData &xx) const
+	{	return mglData(true,mgl_data_subdata_ext(this,&xx,0,0));	}
+	/// Get data from sections ids, separated by value val along specified direction.
+	/** If section id is negative then reverse order is used (i.e. -1 give last section). */
+	inline mglData Section(const mglData &ids, char dir='y', mreal val=NAN) const
+	{	return mglData(true,mgl_data_section(this,&ids,dir,val));	}
+	inline mglData Section(long id, char dir='y', mreal val=NAN) const
+	{	return mglData(true,mgl_data_section_val(this,id,dir,val));	}
+
+	/// Get trace of the data array
+	inline mglData Trace() const
+	{	return mglData(true,mgl_data_trace(this));	}
+	/// Create n-th points distribution of this data values in range [v1, v2]
+	inline mglData Hist(long n,mreal v1=0,mreal v2=1, long nsub=0) const
+	{	return mglData(true,mgl_data_hist(this,n,v1,v2,nsub));	}
+	/// Create n-th points distribution of this data values in range [v1, v2] with weight w
+	inline mglData Hist(const mglData &w, long n,mreal v1=0,mreal v2=1, long nsub=0) const
+	{	return mglData(true,mgl_data_hist_w(this,&w,n,v1,v2,nsub));	}
+	/// Get array which is result of summation in given direction or directions
+	inline mglData Sum(const char *dir) const
+	{	return mglData(true,mgl_data_sum(this,dir));	}
+	/// Get array which is result of maximal values in given direction or directions
+	inline mglData Max(const char *dir) const
+	{	return mglData(true,mgl_data_max_dir(this,dir));	}
+	/// Get array which is result of minimal values in given direction or directions
+	inline mglData Min(const char *dir) const
+	{	return mglData(true,mgl_data_min_dir(this,dir));	}
+	/// Get the data which is direct multiplication (like, d[i,j] = this[i]*a[j] and so on)
+	inline mglData Combine(const mglData &dat) const
+	{	return mglData(true,mgl_data_combine(this,&dat));	}
+	/// Resize the data to new size of box [x1,x2]*[y1,y2]*[z1,z2]
+	inline mglData Resize(long mx,long my=0,long mz=0, mreal x1=0,mreal x2=1, mreal y1=0,mreal y2=1, mreal z1=0,mreal z2=1) const
+	{	return mglData(true,mgl_data_resize_box(this,mx,my,mz,x1,x2,y1,y2,z1,z2));	}
+	/// Get array which values is result of interpolation this for coordinates from other arrays
+	inline mglData Evaluate(const mglData &idat, bool norm=true) const
+	{	return mglData(true,mgl_data_evaluate(this,&idat,0,0,norm));	}
+	inline mglData Evaluate(const mglData &idat, const mglData &jdat, bool norm=true) const
+	{	return mglData(true,mgl_data_evaluate(this,&idat,&jdat,0,norm));	}
+	inline mglData Evaluate(const mglData &idat, const mglData &jdat, const mglData &kdat, bool norm=true) const
+	{	return mglData(true,mgl_data_evaluate(this,&idat,&jdat,&kdat,norm));	}
+	/// Find roots for set of nonlinear equations defined by textual formula
+	inline mglData Roots(const char *eq, char var='x') const
+	{	return mglData(true,mgl_data_roots(eq, this, var));	}
+	/// Find correlation with another data arrays
+	inline mglData Correl(const mglData &dat, const char *dir) const
+	{	return mglData(true,mgl_data_correl(this,&dat,dir));	}
+	/// Find auto correlation function
+	inline mglData AutoCorrel(const char *dir) const
+	{	return mglData(true,mgl_data_correl(this,this,dir));	}
+	/// Get curves, separated by NAN, for maximal values of array d as function of x coordinate.
+	/** Noises below lvl amplitude are ignored.
+	 * Parameter dy \in [0,ny] set the "attraction" distance of points to curve. */
+	inline mglData Detect(mreal lvl, mreal dj, mreal di=0, mreal min_len=0) const
+	{	return mglData(true,mgl_data_detect(this,lvl,dj,di,min_len));	}
+
+	/// Cumulative summation the data in given direction or directions
+	inline void CumSum(const char *dir)	{	mgl_data_cumsum(this,dir);	}
+	/// Integrate (cumulative summation) the data in given direction or directions
+	inline void Integral(const char *dir)	{	mgl_data_integral(this,dir);	}
+	/// Differentiate the data in given direction or directions
+	inline void Diff(const char *dir)	{	mgl_data_diff(this,dir);	}
+	/// Differentiate the parametrically specified data along direction v1 with v2=const
+	inline void Diff(const mglData &v1, const mglData &v2)
+	{	mgl_data_diff_par(this,&v1,&v2,0);	}
+	/// Differentiate the parametrically specified data along direction v1 with v2,v3=const
+	inline void Diff(const mglData &v1, const mglData &v2, const mglData &v3)
+	{	mgl_data_diff_par(this,&v1,&v2,&v3);	}
+	/// Double-differentiate (like Laplace operator) the data in given direction
+	inline void Diff2(const char *dir)	{	mgl_data_diff2(this,dir);	}
+
+	/// Swap left and right part of the data in given direction (useful for Fourier spectrum)
+	inline void Swap(const char *dir)		{	mgl_data_swap(this,dir);	}
+	/// Roll data along direction dir by num slices
+	inline void Roll(char dir, long num)	{	mgl_data_roll(this,dir,num);	}
+	/// Mirror the data in given direction (useful for Fourier spectrum)
+	inline void Mirror(const char *dir)		{	mgl_data_mirror(this,dir);	}
+	/// Sort rows (or slices) by values of specified column
+	inline void Sort(long idx, long idy=-1)	{	mgl_data_sort(this,idx,idy);	}
+	/// Return dilated array of 0 or 1 for data values larger val 
+	inline void Dilate(mreal val=1, long step=1)
+	{	mgl_data_dilate(this, val, step);	}
+	/// Return eroded array of 0 or 1 for data values larger val 
+	inline void Erode(mreal val=1, long step=1)
+	{	mgl_data_erode(this, val, step);	}
+	
+
+	/// Set as the data envelop
+	inline void Envelop(char dir='x')
+	{	mgl_data_envelop(this,dir);	}
+	/// Remove phase jump
+	inline void Sew(const char *dirs="xyz", mreal da=2*Pi)
+	{	mgl_data_sew(this,dirs,da);	}
+	/// Smooth the data on specified direction or directions
+	/** String \a dir may contain:
+	 *  ‘x’, ‘y’, ‘z’ for 1st, 2nd or 3d dimension;
+	 *  ‘dN’ for linear averaging over N points;
+	 *  ‘3’ for linear averaging over 3 points;
+	 *  ‘5’ for linear averaging over 5 points.
+	 *  By default quadratic averaging over 5 points is used. */
+	inline void Smooth(const char *dirs="xyz",mreal delta=0)
+	{	mgl_data_smooth(this,dirs,delta);	}
+	/// Normalize the data to range [v1,v2]
+	inline void Norm(mreal v1=0,mreal v2=1,bool sym=false,long dim=0)
+	{	mgl_data_norm(this,v1,v2,sym,dim);	}
+	/// Normalize the data to range [v1,v2] slice by slice
+	inline void NormSl(mreal v1=0,mreal v2=1,char dir='z',bool keep_en=true,bool sym=false)
+	{	mgl_data_norm_slice(this,v1,v2,dir,keep_en,sym);	}
+	/// Limit the data to be inside [-v,v], keeping the original sign
+	inline void Limit(mreal v)
+	{	mgl_data_limit(this, v);	}
+
+	/// Apply Hankel transform
+	inline void Hankel(const char *dir)	{	mgl_data_hankel(this,dir);	}
+	/// Apply Sin-Fourier transform
+	inline void SinFFT(const char *dir)	{	mgl_data_sinfft(this,dir);	}
+	/// Apply Cos-Fourier transform
+	inline void CosFFT(const char *dir)	{	mgl_data_cosfft(this,dir);	}
+	/// Fill data by coordinates/momenta samples for Hankel ('h') or Fourier ('f') transform
+	/** Parameter \a how may contain:
+	 * ‘x‘,‘y‘,‘z‘ for direction (only one will be used),
+	 * ‘k‘ for momenta samples,
+	 * ‘h‘ for Hankel samples,
+	 * ‘f‘ for Cartesian/Fourier samples (default). */
+	inline void FillSample(const char *how)
+	{	mgl_data_fill_sample(this,how);	}
+	/// Apply wavelet transform
+	/** Parameter \a dir may contain:
+	 * ‘x‘,‘y‘,‘z‘ for directions,
+	 * ‘d‘ for daubechies, ‘D‘ for centered daubechies,
+	 * ‘h‘ for haar, ‘H‘ for centered haar,
+	 * ‘b‘ for bspline, ‘B‘ for centered bspline,
+	 * ‘i‘ for applying inverse transform. */
+	inline void Wavelet(const char *how, int k)	{	mgl_data_wavelet(this, how, k);	}
+
+	/// Return an approximated x-value (root) when dat(x) = val
+	inline mreal Solve(mreal val, bool use_spline=true, long i0=0) const
+	{	return mgl_data_solve_1d(this, val, use_spline, i0);		}
+	/// Return an approximated value (root) when dat(x) = val
+	inline mglData Solve(mreal val, char dir, bool norm=true) const
+	{	return mglData(true,mgl_data_solve(this, val, dir, 0, norm));	}
+	inline mglData Solve(mreal val, char dir, const mglData &i0, bool norm=true) const
+	{	return mglData(true,mgl_data_solve(this, val, dir, &i0, norm));	}
+
+	/// Interpolate by cubic spline the data to given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+	inline mreal Spline(mreal x,mreal y=0,mreal z=0) const
+	{	return mgl_data_spline(this, x,y,z);	}
+	/// Interpolate by cubic spline the data to given point x,\a y,\a z which normalized in range [0, 1]
+	inline mreal Spline1(mreal x,mreal y=0,mreal z=0) const
+	{	return mgl_data_spline(this, x*(nx-1),y*(ny-1),z*(nz-1));	}
+	/// Interpolate by linear function the data to given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+	inline mreal Linear(mreal x,mreal y=0,mreal z=0)	const
+	{	return mgl_data_linear(this,x,y,z);	}
+	/// Interpolate by line the data to given point x,\a y,\a z which normalized in range [0, 1]
+	inline mreal Linear1(mreal x,mreal y=0,mreal z=0) const
+	{	return mgl_data_linear(this,x*(nx-1),y*(ny-1),z*(nz-1));	}
+
+	/// Interpolate by cubic spline the data and return its derivatives at given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+	inline mreal Spline(mglPoint &dif, mreal x,mreal y=0,mreal z=0) const
+	{	return mgl_data_spline_ext(this, x,y,z, &(dif.x),&(dif.y), &(dif.z));	}
+	/// Interpolate by cubic spline the data and return its derivatives at given point x,\a y,\a z which normalized in range [0, 1]
+	inline mreal Spline1(mglPoint &dif, mreal x,mreal y=0,mreal z=0) const
+	{	mreal res=mgl_data_spline_ext(this, x*(nx-1),y*(ny-1),z*(nz-1), &(dif.x),&(dif.y), &(dif.z));
+		dif.x*=nx>1?nx-1:1;	dif.y*=ny>1?ny-1:1;	dif.z*=nz>1?nz-1:1;	return res;	}
+	/// Interpolate by linear function the data and return its derivatives at given point x=[0...nx-1], y=[0...ny-1], z=[0...nz-1]
+	inline mreal Linear(mglPoint &dif, mreal x,mreal y=0,mreal z=0)	const
+	{	return mgl_data_linear_ext(this,x,y,z, &(dif.x),&(dif.y), &(dif.z));	}
+	/// Interpolate by line the data and return its derivatives at given point x,\a y,\a z which normalized in range [0, 1]
+	inline mreal Linear1(mglPoint &dif, mreal x,mreal y=0,mreal z=0) const
+	{	mreal res=mgl_data_linear_ext(this,x*(nx-1),y*(ny-1),z*(nz-1), &(dif.x),&(dif.y), &(dif.z));
+		dif.x*=nx>1?nx-1:1;	dif.y*=ny>1?ny-1:1;	dif.z*=nz>1?nz-1:1;	return res;	}
+
+	/// Get information about the data (sizes and momentum) to string
+	inline const char *PrintInfo() const	{	return mgl_data_info(this);	}
+	/// Print information about the data (sizes and momentum) to FILE (for example, stdout)
+	inline void PrintInfo(FILE *fp) const
+	{	if(fp)	{	fprintf(fp,"%s",mgl_data_info(this));	fflush(fp);	}	}
+	/// Get maximal value of the data
+	inline mreal Maximal() const	{	return mgl_data_max(this);	}
+	/// Get minimal value of the data
+	inline mreal Minimal() const	{	return mgl_data_min(this);	}
+	/// Get maximal value of the data which is less than 0
+	inline mreal MaximalNeg() const	{	return mgl_data_neg_max(this);	}
+	/// Get minimal value of the data which is larger than 0
+	inline mreal MinimalPos() const	{	return mgl_data_pos_min(this);	}
+	/// Get maximal value of the data and its position
+	inline mreal Maximal(long &i,long &j,long &k) const
+	{	return mgl_data_max_int(this,&i,&j,&k);	}
+	/// Get minimal value of the data and its position
+	inline mreal Minimal(long &i,long &j,long &k) const
+	{	return mgl_data_min_int(this,&i,&j,&k);	}
+	/// Get maximal value of the data and its approximated position
+	inline mreal Maximal(mreal &x,mreal &y,mreal &z) const
+	{	return mgl_data_max_real(this,&x,&y,&z);	}
+	/// Get minimal value of the data and its approximated position
+	inline mreal Minimal(mreal &x,mreal &y,mreal &z) const
+	{	return mgl_data_min_real(this,&x,&y,&z);	}
+	/// Get "energy" and find first (median) and second (width) momenta of data
+	inline mreal Momentum(char dir,mreal &m,mreal &w) const
+	{	return mgl_data_momentum_val(this,dir,&m,&w,0,0);	}
+	/// Get "energy and find 4 momenta of data: median, width, skewness, kurtosis
+	inline mreal Momentum(char dir,mreal &m,mreal &w,mreal &s,mreal &k) const
+	{	return mgl_data_momentum_val(this,dir,&m,&w,&s,&k);	}
+	/// Find position (after specified in i,j,k) of first nonzero value of formula
+	inline mreal Find(const char *cond, long &i, long &j, long &k) const
+	{	return mgl_data_first(this,cond,&i,&j,&k);	}
+	/// Find position (before specified in i,j,k) of last nonzero value of formula
+	inline mreal Last(const char *cond, long &i, long &j, long &k) const
+	{	return mgl_data_last(this,cond,&i,&j,&k);	}
+	/// Find position of first in direction 'dir' nonzero value of formula
+	inline long Find(const char *cond, char dir, long i=0, long j=0, long k=0) const
+	{	return mgl_data_find(this,cond,dir,i,j,k);	}
+	/// Find if any nonzero value of formula
+	inline bool FindAny(const char *cond) const
+	{	return mgl_data_find_any(this,cond);	}
+
+	/// Copy data from other mglData variable
+	inline const mglData &operator=(const mglData &d)
+	{	if(this!=&d)	mgl_data_set(this,&d);	return d;	}
+	inline mreal operator=(mreal val)
+	{	mgl_data_fill(this,val,val,'x');	return val;	}
+	/// Multiply the data by other one for each element
+	inline void operator*=(const mglData &d)	{	mgl_data_mul_dat(this,&d);	}
+	/// Divide the data by other one for each element
+	inline void operator/=(const mglData &d)	{	mgl_data_div_dat(this,&d);	}
+	/// Add the other data
+	inline void operator+=(const mglData &d)	{	mgl_data_add_dat(this,&d);	}
+	/// Subtract the other data
+	inline void operator-=(const mglData &d)	{	mgl_data_sub_dat(this,&d);	}
+	/// Multiply each element by the number
+	inline void operator*=(mreal d)		{	mgl_data_mul_num(this,d);	}
+	/// Divide each element by the number
+	inline void operator/=(mreal d)		{	mgl_data_div_num(this,d);	}
+	/// Add the number
+	inline void operator+=(mreal d)		{	mgl_data_add_num(this,d);	}
+	/// Subtract the number
+	inline void operator-=(mreal d)		{	mgl_data_sub_num(this,d);	}
+};
+//-----------------------------------------------------------------------------
+/// Integral data transformation (like Fourier 'f' or 'i', Hankel 'h' or None 'n') for amplitude and phase
+inline mglData mglTransformA(const mglData &am, const mglData &ph, const char *tr)
+{	return mglData(true,mgl_transform_a(&am,&ph,tr));	}
+/// Integral data transformation (like Fourier 'f' or 'i', Hankel 'h' or None 'n') for real and imaginary parts
+inline mglData mglTransform(const mglData &re, const mglData &im, const char *tr)
+{	return mglData(true,mgl_transform(&re,&im,tr));	}
+/// Apply Fourier transform for the data and save result into it
+inline void mglFourier(mglData &re, mglData &im, const char *dir)
+{	mgl_data_fourier(&re,&im,dir);	}
+/// Short time Fourier analysis for real and imaginary parts. Output is amplitude of partial Fourier (result will have size {dn, floor(nx/dn), ny} for dir='x'
+inline mglData mglSTFA(const mglData &re, const mglData &im, long dn, char dir='x')
+{	return mglData(true, mgl_data_stfa(&re,&im,dn,dir));	}
+//-----------------------------------------------------------------------------
+/// Saves result of PDE solving (|u|^2) for "Hamiltonian" ham with initial conditions ini
+inline mglData mglPDE(HMGL gr, const char *ham, const mglData &ini_re, const mglData &ini_im, mreal dz=0.1, mreal k0=100,const char *opt="")
+{	return mglData(true, mgl_pde_solve(gr,ham, &ini_re, &ini_im, dz, k0,opt));	}
+/// Saves result of PDE solving for "Hamiltonian" ham with initial conditions ini along a curve ray (must have nx>=7 - x,y,z,px,py,pz,tau or nx=5 - x,y,px,py,tau)
+inline mglData mglQO2d(const char *ham, const mglData &ini_re, const mglData &ini_im, const mglData &ray, mreal r=1, mreal k0=100)
+{	return mglData(true, mgl_qo2d_solve(ham, &ini_re, &ini_im, &ray, r, k0, 0, 0));	}
+inline mglData mglQO2d(const char *ham, const mglData &ini_re, const mglData &ini_im, const mglData &ray, mglData &xx, mglData &yy, mreal r=1, mreal k0=100)
+{	return mglData(true, mgl_qo2d_solve(ham, &ini_re, &ini_im, &ray, r, k0, &xx, &yy));	}
+/// Saves result of PDE solving for "Hamiltonian" ham with initial conditions ini along a curve ray (must have nx>=7 - x,y,z,px,py,pz,tau or nx=5 - x,y,px,py,tau)
+inline mglData mglQO3d(const char *ham, const mglData &ini_re, const mglData &ini_im, const mglData &ray, mreal r=1, mreal k0=100)
+{	return mglData(true, mgl_qo3d_solve(ham, &ini_re, &ini_im, &ray, r, k0, 0, 0, 0));	}
+inline mglData mglQO3d(const char *ham, const mglData &ini_re, const mglData &ini_im, const mglData &ray, mglData &xx, mglData &yy, mglData &zz, mreal r=1, mreal k0=100)
+{	return mglData(true, mgl_qo3d_solve(ham, &ini_re, &ini_im, &ray, r, k0, &xx, &yy, &zz));	}
+/// Finds ray with starting point r0, p0 (and prepares ray data for mglQO2d)
+inline mglData mglRay(const char *ham, mglPoint r0, mglPoint p0, mreal dt=0.1, mreal tmax=10)
+{	return mglData(true, mgl_ray_trace(ham, r0.x, r0.y, r0.z, p0.x, p0.y, p0.z, dt, tmax));	}
+/// Saves result of ODE solving for var complex variables with right part func (separated by ';') and initial conditions x0 over time interval [0,tmax] with time step dt
+inline mglData mglODE(const char *func, const char *var, const mglData &ini, mreal dt=0.1, mreal tmax=10)
+{	return mglData(true, mgl_ode_solve_str(func,var, &ini, dt, tmax));	}
+//-----------------------------------------------------------------------------
+/// Get array as solution of tridiagonal system of equations a[i]*x[i-1]+b[i]*x[i]+c[i]*x[i+1]=d[i]
+/** String \a how may contain:
+ * 'x', 'y', 'z' for solving along x-,y-,z-directions, or
+ * 'h' for solving along hexagonal direction at x-y plain (need nx=ny),
+ * 'c' for using periodical boundary conditions,
+ * 'd' for diffraction/diffuse calculation. */
+inline mglData mglTridMat(const mglData &A, const mglData &B, const mglData &C, const mglData &D, const char *how)
+{	return mglData(true, mgl_data_tridmat(&A, &B, &C, &D, how));	}
+//-----------------------------------------------------------------------------
+/// Calculate Jacobian determinant for D{x(u,v), y(u,v)} = dx/du*dy/dv-dx/dv*dy/du
+inline mglData mglJacobian(const mglData &x, const mglData &y)
+{	return mglData(true, mgl_jacobian_2d(&x, &y));	}
+/// Calculate Jacobian determinant for D{x(u,v,w), y(u,v,w), z(u,v,w)}
+inline mglData mglJacobian(const mglData &x, const mglData &y, const mglData &z)
+{	return mglData(true, mgl_jacobian_3d(&x, &y, &z));	}
+/// Do something like Delone triangulation
+inline mglData mglTriangulation(const mglData &x, const mglData &y, const mglData &z)
+{	return mglData(true,mgl_triangulation_3d(&x,&y,&z));	}
+inline mglData mglTriangulation(const mglData &x, const mglData &y)
+{	return mglData(true,mgl_triangulation_2d(&x,&y));	}
+/// Get curves, separated by NAN, for maximal values of array d as function of x coordinate.
+/** Noises below lvl amplitude are ignored.
+ * Parameter dy \in [0,ny] set the "attraction" distance of points to curve. */
+inline mglData mglDetect(const mglData &d, mreal lvl, mreal dj, mreal di=0, mreal min_len=0)
+{	return mglData(true,mgl_data_detect(&d, lvl, dj, di, min_len));	}
+//-----------------------------------------------------------------------------
+/// Get array which is n-th pairs {x[i],y[i]} for iterated function system (fractal) generated by A
+inline mglData mglIFS2d(const mglData &A, long n, long skip=20)
+{	return mglData(true,mgl_data_ifs_2d(&A,n,skip));	}
+/// Get array which is n-th points {x[i],y[i],z[i]} for iterated function system (fractal) generated by A
+inline mglData mglIFS3d(const mglData &A, long n, long skip=20)
+{	return mglData(true,mgl_data_ifs_3d(&A,n,skip));	}
+/// Get array which is n-th points {x[i],y[i],z[i]} for iterated function system (fractal) defined in *.ifs file 'fname' and named as 'name'
+inline mglData mglIFSfile(const char *fname, const char *name, long n, long skip=20)
+{	return mglData(true,mgl_data_ifs_file(fname,name,n,skip));	}
+/// Get array which is n-th pairs {x[i],y[i]} for Flame fractal generated by A with functions F
+/** NOTE: A.nx must be >= 7 and F.nx >= 2 and F.nz=A.ny.
+ * F[0,i,j] denote function id. F[1,i,j] give function weight, F(2:5,i,j) provide function parameters.
+ * Resulting point is {xnew,ynew} = sum_i F[1,i,j]*F[0,i,j]{IFS2d(A[j]){x,y}}. */
+inline mglData mglFlame2d(const mglData &A, const mglData &F, long n, long skip=20)
+{	return mglData(true,mgl_data_flame_2d(&A,&F,n,skip));	}
+//-----------------------------------------------------------------------------
+/// Get sub-array of the data with given fixed indexes
+inline mglData mglSubData(const mglData &dat, long xx, long yy=-1, long zz=-1)
+{	return mglData(true,mgl_data_subdata(&dat,xx,yy,zz));	}
+inline mglData mglSubData(const mglData &dat, const mglData &xx, const mglData &yy, const mglData &zz)
+{	return mglData(true,mgl_data_subdata_ext(&dat,&xx,&yy,&zz));	}
+inline mglData mglSubData(const mglData &dat, const mglData &xx, const mglData &yy)
+{	return mglData(true,mgl_data_subdata_ext(&dat,&xx,&yy,0));	}
+inline mglData mglSubData(const mglData &dat, const mglData &xx)
+{	return mglData(true,mgl_data_subdata_ext(&dat,&xx,0,0));	}
+//-----------------------------------------------------------------------------
+/// Prepare coefficients for global spline interpolation
+inline mglData mglGSplineInit(const mglData &xdat, const mglData &ydat)
+{	return mglData(true,mgl_gspline_init(&xdat, &ydat));	}
+/// Evaluate global spline (and its derivatives d1, d2 if not NULL) using prepared coefficients \a coef
+inline mreal mglGSpline(const mglData &coef, mreal dx, mreal *d1=0, mreal *d2=0)
+{	return mgl_gspline(&coef, dx, d1,d2);	}
+//-----------------------------------------------------------------------------
+/// Wrapper class for expression evaluating
+class mglExpr
+{
+	HMEX ex;
+	mglExpr(const mglExpr &){}	// copying is not allowed
+	const mglExpr &operator=(const mglExpr &t){return t;}	// copying is not allowed
+public:
+	mglExpr(const char *expr)		{	ex = mgl_create_expr(expr);	}
+	~mglExpr()	{	mgl_delete_expr(ex);	}
+	/// Return value of expression for given x,y,z variables
+	inline double Eval(double x, double y=0, double z=0)
+	{	return mgl_expr_eval(ex,x,y,z);	}
+	/// Return value of expression differentiation over variable dir for given x,y,z variables
+	inline double Diff(char dir, double x, double y=0, double z=0)
+	{	return mgl_expr_diff(ex,dir, x,y,z);	}
+};
+//-----------------------------------------------------------------------------
diff --git a/lang/mathgl.i b/lang/mathgl.i
new file mode 100644
index 0000000..253ea07
--- /dev/null
+++ b/lang/mathgl.i
@@ -0,0 +1,100 @@
+/***************************************************************************
+ * mgl.i is part of Math Graphic Library
+ * Copyright (C) 2007 Alexey Balakin <balakin at appl.sci-nnov.ru>,
+ *   Xavier Delacour <xavier.delacour at gmail.com>,
+ *   Alexander Filov <alexander.filov at gmail.com>                           *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+
+%module mathgl
+#ifdef SWIGOCTAVE
+%feature("autodoc", 1);
+#endif // SWIGOCTAVE
+
+%ignore operator!;
+%ignore operator=;
+%ignore *::operator=;
+%ignore *::operator+=;
+%ignore *::operator-=;
+%ignore *::operator*=;
+%ignore *::operator/=;
+//%ignore mglDataA
+
+%{
+#define SWIG_FILE_WITH_INIT
+#include "mgl2/type.h"
+#include "mgl2/data.h"
+#include "mgl2/mgl.h"
+const double All = -1;
+const double Pi = M_PI;
+const double NaN = NAN;
+const double Inf = INFINITY;
+%}
+
+#if MGL_USE_DOUBLE
+typedef double mreal;
+#else
+typedef float mreal;
+#endif
+
+
+#ifdef SWIGOCTAVE
+%rename(__add) operator+;
+%rename(__sub) operator-;
+%rename(__mul) operator*;
+%rename(__div) operator/;
+%rename(__eq) operator==;
+%rename(__ne) operator!=;
+%typemap(in,noblock=1) (double* d, int rows, int cols) (Matrix tmp) {
+	if (!$input.is_matrix_type())	{	error("A must be a matrix");	SWIG_fail;	}
+	tmp=$input.matrix_value();
+	$1=tmp.data();
+	$2=tmp.rows();
+	$3=tmp.columns();
+}
+#endif
+
+#ifdef SWIGPYTHON
+%rename(__add__) *::operator+(const mglData&, const mglData&);
+%rename(__sub__) *::operator-(const mglData&, const mglData &);
+%rename(__mul__) *::operator*(const mglData &, float);
+%rename(__div__) *::operator/(const mglData &, float);
+
+// Get the NumPy typemaps
+%include "numpy.i"
+%init %{
+import_array();
+%}
+%apply (double* IN_ARRAY1, int DIM1) {(const double* d, int size)};
+%apply (int DIM1, double* IN_ARRAY1) {(int size, const double* d)};
+%apply (double* IN_ARRAY2, int DIM1, int DIM2) {(const double* d, int rows, int cols)};
+%apply (int DIM1, int DIM2, double* IN_ARRAY2) {(int rows, int cols, const double* d)};
+%apply (double* IN_ARRAY3, int DIM1, int DIM2, int DIM3) {(const double* d, int rows, int cols, int slc)};
+%apply (int DIM1, int DIM2, int DIM3, double* IN_ARRAY3) {(int rows, int cols, int slc, const double* d)};
+#endif
+
+%include "type.i"
+%include "data.i"
+%include "mgl.i"
+%extend mglData
+{
+	mreal __getitem__( int i)	{	return self->GetVal(i);	};
+	mreal __paren( int i)		{	return self->GetVal(i);	};
+	void __setitem__( int i, mreal y)	{	self->SetVal(y,i);	};
+	void __paren_asgn( int i, mreal y)	{	self->SetVal(y,i);	};
+};
diff --git a/lang/mgl.i b/lang/mgl.i
new file mode 100644
index 0000000..aad850a
--- /dev/null
+++ b/lang/mgl.i
@@ -0,0 +1,2258 @@
+/***************************************************************************
+ * mgl.h is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+//-----------------------------------------------------------------------------
+/// Wrapper class for all graphics
+class mglGraph
+{
+	mglGraph(const mglGraph &t) {}	// copying is not allowed
+	const mglGraph &operator=(const mglGraph &t)	{	return t;	}
+protected:
+	HMGL gr;
+public:
+	inline mglGraph(int kind=0, int width=600, int height=400)
+	{
+		if(kind==-1)	gr=NULL;
+#if MGL_HAVE_OPENGL
+		else if(kind==1)	gr=mgl_create_graph_gl();
+#else
+		else if(kind==1)
+		{	gr=mgl_create_graph(width, height);
+			mglGlobalMess += "OpenGL support was disabled. Please, enable it and rebuild MathGL.\n";	}
+#endif
+		else	gr=mgl_create_graph(width, height);
+	}
+	inline mglGraph(HMGL graph)
+	{	gr = graph;		mgl_use_graph(gr,1);	}
+	virtual ~mglGraph()
+	{	if(mgl_use_graph(gr,-1)<1)	mgl_delete_graph(gr);	}
+	/// Get pointer to internal HMGL object
+	inline HMGL Self()	{	return gr;	}
+	/// Set default parameters for plotting
+	inline void DefaultPlotParam()			{	mgl_set_def_param(gr);	}
+	/// Set name of plot for saving filename
+	inline void SetPlotId(const char *id)	{	mgl_set_plotid(gr,id);	}
+	/// Get name of plot for saving filename
+	inline const char *GetPlotId()	{	return mgl_get_plotid(gr);	}
+
+	/// Ask to stop drawing
+	inline void Stop(bool stop=true)	{	mgl_ask_stop(gr, stop);	}
+	/// Check if plot termination is asked
+	inline bool NeedStop()	{	return mgl_need_stop(gr);	}
+
+	/// Set the transparency on/off.
+	inline void Alpha(bool enable)			{	mgl_set_alpha(gr, enable);	}
+	/// Set the gray-scale mode on/off.
+	inline void Gray(bool enable)			{	mgl_set_gray(gr, enable);	}
+	/// Set default value of alpha-channel
+	inline void SetAlphaDef(double alpha)	{	mgl_set_alpha_default(gr, alpha);	}
+	/// Set the transparency type (0 - usual, 1 - glass, 2 - lamp)
+	inline void SetTranspType(int type)		{	mgl_set_transp_type(gr, type);	}
+	/// Set the size of semi-transparent area around lines, marks, glyphs, ... Default is 1.
+	inline void SetPenDelta(double d)	{	mgl_pen_delta(gr,d);	}
+
+	/// Set the using of light on/off.
+	inline void Light(bool enable)			{	mgl_set_light(gr, enable);	}
+	/// Switch on/off the specified light source.
+	inline void Light(int n,bool enable)	{	mgl_set_light_n(gr, n, enable);	}
+	/// Use diffusive light (only for local light sources) -- OBSOLETE
+	inline void SetDifLight(bool dif)		{	mgl_set_light_dif(gr, dif);	}
+	/// Set to attach light settings to inplot.
+	inline void AttachLight(bool enable)		{	mgl_set_attach_light(gr, enable);	}
+	/// Add a light source.
+	inline void AddLight(int n, mglPoint p, char col='w', double bright=0.5, double ap=0)
+	{	mgl_add_light_ext(gr, n, p.x, p.y, p.z, col, bright, ap);	}
+	inline void AddLight(int n, mglPoint r, mglPoint p, char col='w', double bright=0.5, double ap=0)
+	{	mgl_add_light_loc(gr, n, r.x, r.y, r.z, p.x, p.y, p.z, col, bright, ap);	}
+	/// Set ambient light brightness
+	inline void SetAmbient(double i)			{	mgl_set_ambbr(gr, i);	}
+	/// Set diffusive light brightness
+	inline void SetDiffuse(double i)			{	mgl_set_difbr(gr, i);	}
+	/// Set the fog distance or switch it off (if d=0).
+	inline void Fog(double d, double dz=0.25)	{	mgl_set_fog(gr, d, dz);		}
+
+	/// Set relative width of rectangles in Bars, Barh, BoxPlot, Candle, OHLC (default is 0.7)
+	inline void SetBarWidth(double width)	{	mgl_set_bar_width(gr, width);	}
+	/// Set default size of marks (locally you can use "size" option)
+	inline void SetMarkSize(double size)		{	mgl_set_mark_size(gr, size);	}
+	/// Set default size of arrows (locally you can use "size" option)
+	inline void SetArrowSize(double size)	{	mgl_set_arrow_size(gr, size);	}
+	/// Set number of mesh lines (use 0 to draw all of them)
+	inline void SetMeshNum(int num)			{	mgl_set_meshnum(gr, num);	}
+	/// Set number of visible faces (use 0 to draw all of them)
+	inline void SetFaceNum(int num)			{	mgl_set_facenum(gr, num);	}
+
+	/// Set cutting for points outside of bounding box
+	inline void SetCut(bool cut)				{	mgl_set_cut(gr, cut);	}
+	/// Set additional cutting box
+	inline void SetCutBox(mglPoint p1, mglPoint p2)
+	{	mgl_set_cut_box(gr, p1.x, p1.y, p1.z, p2.x, p2.y, p2.z);	}
+	/// Set the cutting off condition (formula)
+	inline void CutOff(const char *EqC)		{	mgl_set_cutoff(gr, EqC);	}
+
+	/// Set default font size
+	inline void SetFontSize(double size)	{	mgl_set_font_size(gr, size);	}
+	/// Set default font style and color
+	inline void SetFontDef(const char *fnt)	{	mgl_set_font_def(gr, fnt);	}
+	/// Set FontSize by size in pt and picture DPI (default is 16 pt for dpi=72)
+	virtual void SetFontSizePT(double pt, int dpi=72)	{	SetFontSize(pt*27.f/dpi);	}
+	/// Set FontSize by size in centimeters and picture DPI (default is 0.56 cm = 16 pt)
+	inline void SetFontSizeCM(double cm, int dpi=72)	{	SetFontSizePT(cm*28.45f,dpi);	}
+	/// Set FontSize by size in inch and picture DPI (default is 0.22 in = 16 pt)
+	inline void SetFontSizeIN(double in, int dpi=72)	{	SetFontSizePT(in*72.27f,dpi);	}
+	/// Load font from file
+	inline void LoadFont(const char *name, const char *path=NULL)
+	{	mgl_load_font(gr, name, path);	}
+	/// Copy font from another mglGraph instance
+	inline void CopyFont(const mglGraph *GR)	{	mgl_copy_font(gr, GR->gr);}
+	/// Restore font (load default font for new HMGL objects)
+	inline void RestoreFont()				{	mgl_restore_font(gr);	}
+	/// Set to use or not text rotation
+	inline void SetRotatedText(bool rotated)	{	mgl_set_rotated_text(gr, rotated);	}
+	/// Set default font for all new HMGL and mglGraph objects
+	static inline void SetDefFont(const char *name, const char *path="")	{	mgl_def_font(name,path);	}
+
+	/// Set default palette
+	inline void SetPalette(const char *colors)	{	mgl_set_palette(gr, colors);	}
+	/// Set default color scheme
+	inline void SetDefScheme(const char *sch)	{	mgl_set_def_sch(gr, sch);	}
+
+	/// Sets RGB values for color with given id
+	static inline void SetColor(char id, double r, double g, double b)	{	mgl_set_color(id, r, g, b);	}
+	/// Set mask for face coloring as array of type 'unsigned char[8]'
+	static inline void SetMask(char id, const char *mask)	{	mgl_set_mask(id, mask);	}
+	/// Set mask for face coloring as uint64_t number
+	static inline void SetMask(char id, uint64_t mask)	{	mgl_set_mask_val(id, mask);	}
+	/// Set default mask rotation angle
+	inline void SetMaskAngle(int angle)	{	mgl_set_mask_angle(gr, angle);	}
+
+	/// Get last warning code
+	inline int  GetWarn()	{	return mgl_get_warn(gr);}
+	/// Set warning code ant fill message
+	inline void SetWarn(int code, const char *info)	{	mgl_set_warn(gr,code,info);	}
+	/// Get text of warning message(s)
+	inline const char *Message()	{	return mgl_get_mess(gr);	}
+	/// Set global warning message
+	static inline void SetGlobalWarn(const char *text)	{	mgl_set_global_warn(text);	}
+	/// Get text of global warning message(s)
+	static inline const char *GlobalWarn()	{	return mgl_get_global_warn();	}
+	/// Suppress printing warnings to stderr
+	static inline void SuppressWarn(bool on)	{	mgl_suppress_warn(on);	}
+	/// Check if MathGL version is valid (return false) or not (return true)
+	static inline bool CheckVersion(const char *ver)	{	return mgl_check_version(ver);	}
+
+	/// Set axis range scaling -- simplified way to shift/zoom axis range -- need to replot whole image!
+	inline void ZoomAxis(mglPoint p1=mglPoint(0,0,0,0), mglPoint p2=mglPoint(1,1,1,1))
+	{	mgl_zoom_axis(gr, p1.x,p1.y,p1.z,p1.c, p2.x,p2.y,p2.z,p2.c);	}
+	/// Add [v1, v2] to the current range in direction dir
+	inline void AddRange(char dir, double v1, double v2)
+	{	mgl_add_range_val(gr, dir, v1, v2);	}
+	/// Set range in direction dir as [v1, v2]
+	inline void SetRange(char dir, double v1, double v2)
+	{	mgl_set_range_val(gr, dir, v1, v2);	}
+	/// Set range in direction dir as minimal and maximal values of data a
+	inline void SetRange(char dir, const mglData &dat, bool add=false)
+	{	mgl_set_range_dat(gr, dir, &dat, add);	}
+	/// Set values of axis range as minimal and maximal values of corresponding data
+	inline void SetRanges(const mglData &xx, const mglData &yy, const mglData &zz, const mglData &cc)
+	{	mgl_set_range_dat(gr,'x',&xx,0);	mgl_set_range_dat(gr,'y',&yy,0);
+		mgl_set_range_dat(gr,'z',&zz,0);	mgl_set_range_dat(gr,'c',&cc,0);	}
+	/// Set values of axis range as minimal and maximal values of corresponding data
+	inline void SetRanges(const mglData &xx, const mglData &yy, const mglData &zz)
+	{	mgl_set_range_dat(gr,'x',&xx,0);	mgl_set_range_dat(gr,'y',&yy,0);
+		mgl_set_range_dat(gr,'z',&zz,0);	mgl_set_range_dat(gr,'c',&zz,0);	}
+	/// Set values of axis range as minimal and maximal values of corresponding data
+	inline void SetRanges(const mglData &xx, const mglData &yy)
+	{	mgl_set_range_dat(gr,'x',&xx,0);	mgl_set_range_dat(gr,'y',&yy,0);	}
+	/// Set values of axis ranges
+	inline void SetRanges(double x1, double x2, double y1, double y2, double z1=0, double z2=0)
+	{	mgl_set_ranges(gr, x1, x2, y1, y2, z1, z2);	}
+	/// Set values of axis ranges
+	inline void SetRanges(mglPoint p1, mglPoint p2)
+	{	mgl_set_ranges(gr, p1.x, p2.x, p1.y, p2.y, p1.z, p2.z);	}
+	/// Set ranges for automatic variables
+	inline void SetAutoRanges(double x1, double x2, double y1=0, double y2=0, double z1=0, double z2=0, double c1=0, double c2=0)
+	{	mgl_set_auto_ranges(gr, x1, x2, y1, y2, z1, z2, c1, c2);	}
+	/// Set ranges for automatic variables
+	inline void SetAutoRanges(mglPoint p1, mglPoint p2)
+	{	mgl_set_auto_ranges(gr, p1.x, p2.x, p1.y, p2.y, p1.z, p2.z, p1.c, p2.c);	}
+	/// Set axis origin
+	inline void SetOrigin(mglPoint p)
+	{	mgl_set_origin(gr, p.x, p.y, p.z);	}
+	inline void SetOrigin(double x0, double y0, double z0=NaN)
+	{	mgl_set_origin(gr, x0, y0, z0);	}
+
+	/// Set the transformation formulas for coordinate. Use "" for built-in ones
+	inline void SetFunc(const char *EqX, const char *EqY, const char *EqZ=NULL, const char *EqA=NULL)
+	{	mgl_set_func(gr, EqX, EqY, EqZ, EqA);	}
+	/// Set one of predefined transformation rule
+	inline void SetCoor(int how)		{	mgl_set_coor(gr, how);	}
+	/// Set to draw Ternary axis (triangle like axis, grid and so on)
+	/** val=1 for Ternary axis (a+b+c=1, z=z),
+	 *  val=2 for Quaternary axis (a+b+c+d=1),
+	 *  val|4 for projections. */
+	inline void Ternary(int val)		{	mgl_set_ternary(gr, val);	}
+
+	/// Set to use or not tick labels rotation
+	inline void SetTickRotate(bool val)	{	mgl_set_tick_rotate(gr,val);	}
+	/// Set to use or not tick labels skipping
+	inline void SetTickSkip(bool val)	{	mgl_set_tick_skip(gr,val);	}
+	/// Set tick length
+	inline void SetTickLen(double len, double stt=1)
+	{	mgl_set_tick_len(gr, len, stt);	}
+	/// Set axis and ticks style
+	inline void SetAxisStl(const char *stl="k", const char *tck=0, const char *sub=0)
+	{	mgl_set_axis_stl(gr, stl, tck, sub);	}
+
+	/// Set time templates for ticks
+	inline void SetTicksTime(char dir, double d=0, const char *t="")
+	{	mgl_set_ticks_time(gr,dir,d,t);	}
+	/// Set ticks text (\n separated). Use "" to disable this feature.
+	inline void SetTicksVal(char dir, const char *lbl, bool add=false)
+	{	mgl_set_ticks_str(gr,dir,lbl,add);	}
+	inline void SetTicksVal(char dir, const wchar_t *lbl, bool add=false)
+	{	mgl_set_ticks_wcs(gr,dir,lbl,add);	}
+	/// Set ticks position and text (\n separated). Use "" to disable this feature.
+	inline void SetTicksVal(char dir, const mglData &v, const char *lbl, bool add=false)
+	{	mgl_set_ticks_val(gr,dir,&v,lbl,add);	}
+	inline void SetTicksVal(char dir, const mglData &v, const wchar_t *lbl, bool add=false)
+	{	mgl_set_ticks_valw(gr,dir,&v,lbl,add);	}
+	/// Add manual tick at given position. Use "" to disable this feature.
+	inline void AddTick(char dir, double val, const char *lbl)
+	{	mgl_add_tick(gr,dir,val,lbl);	}
+	inline void AddTick(char dir, double val, const wchar_t *lbl)
+	{	mgl_add_tickw(gr,dir,val,lbl);	}
+	/// Set the ticks parameters and string for its factor
+	inline void SetTicks(char dir, double d=0, int ns=0, double org=NaN, const char *factor="")
+	{	mgl_set_ticks_fact(gr, dir, d, ns, org, factor);	}
+	inline void SetTicks(char dir, double d, int ns, double org, const wchar_t *factor)
+	{	mgl_set_ticks_factw(gr, dir, d, ns, org, factor);	}
+	/// Auto adjust ticks
+	inline void Adjust(const char *dir="xyzc")
+	{	mgl_adjust_ticks(gr, dir);	}
+	/// Set templates for ticks
+	inline void SetTickTempl(char dir, const char *t)
+	{	mgl_set_tick_templ(gr,dir,t);	}
+	inline void SetTickTempl(char dir, const wchar_t *t)
+	{	mgl_set_tick_templw(gr,dir,t);	}
+	/// Tune ticks (tune|1 for common multiplier, tune|2 for common component)
+	inline void SetTuneTicks(int tune, double fact_pos=1.15)
+	{	mgl_tune_ticks(gr, tune, fact_pos);	}
+	/// Set additional shift of tick labels
+	inline void SetTickShift(mglPoint p)
+	{	mgl_set_tick_shift(gr,p.x,p.y,p.z,p.c);	}
+	/// Set to use UTC time instead of local time
+	inline void SetTimeUTC(bool enable)
+	{	mgl_set_flag(gr,enable, MGL_USE_GMTIME);	}
+	/// Set to draw tick labels at axis origin
+	inline void SetOriginTick(bool enable=true)
+	{	mgl_set_flag(gr,!enable, MGL_NO_ORIGIN);	}
+
+	/// Put further plotting in m-th cell of nx*ny grid of the image.
+	/** String \a style may contain:
+	 *  '<' for reserving space at left
+	 *  '>' for reserving space at right
+	 *  '^' for reserving space at top
+	 *  '_' for reserving space at bottom
+	 *  '#' for using whole region. */
+	inline void SubPlot(int nx,int ny,int m,const char *style="<>_^", double dx=0, double dy=0)
+	{	mgl_subplot_d(gr, nx, ny, m, style, dx, dy);	}
+	/// Put further plotting in rectangle of dx*dy cells starting from m-th cell of nx*ny grid of the image and shift it by distance {sx,sy}.
+	/** String \a style may contain:
+	 *  '<' for reserving space at left
+	 *  '>' for reserving space at right
+	 *  '^' for reserving space at top
+	 *  '_' for reserving space at bottom
+	 *  '#' for using whole region. */
+	inline void MultiPlot(int nx,int ny,int m, int dx, int dy, const char *style="<>_^", double sx=0, double sy=0)
+	{	mgl_multiplot_d(gr, nx, ny, m, dx, dy, style, sx, sy);	}
+	/// Put further plotting in a region [x1,x2]*[y1,y2] of the image or subplot (x1,x2,y1,y2 in range [0, 1]).
+	inline void InPlot(double x1,double x2,double y1,double y2, bool rel=true)
+	{	if(rel)	mgl_relplot(gr, x1, x2, y1, y2);
+		else	mgl_inplot(gr, x1, x2, y1, y2);	}
+	/// Put further plotting in column cell of previous subplot
+	inline void ColumnPlot(int num, int ind, double d=0)
+	{	mgl_columnplot(gr,num,ind,d);	}
+	/// Put further plotting in matrix cell of previous subplot
+	inline void GridPlot(int nx, int ny, int ind, double d=0)
+	{	mgl_gridplot(gr,nx,ny,ind,d);	}
+	/// Put further plotting in cell of stick rotated on angles tet, phi
+	inline void StickPlot(int num, int i, double tet, double phi)
+	{	mgl_stickplot(gr,num,i,tet,phi);	}
+	/// Put further plotting in cell of stick sheared on sx, sy.
+	inline void ShearPlot(int num, int i, mreal sx, mreal sy, mreal xd=1, mreal yd=0)
+	{	mgl_shearplot(gr,num,i,sx,sy,xd,yd);	}
+
+	/// Set factor of plot size
+	inline void SetPlotFactor(double val)
+	{	mgl_set_plotfactor(gr,val);	}
+	/// Push transformation matrix into stack
+	inline void Push()	{	mgl_mat_push(gr);	}
+	/// Pop transformation matrix from stack
+	inline void Pop()	{	mgl_mat_pop(gr);	}
+
+	/// Add title for current subplot/inplot
+	/** Style '#' draw box around the title. */
+	inline 	void Title(const char *title,const char *stl="",double size=-2)
+	{	mgl_title(gr,title,stl,size);	}
+	/// Add title for current subplot/inplot
+	/** Style '#' draw box around the title. */
+	inline 	void Title(const wchar_t *title,const char *stl="",double size=-2)
+	{	mgl_titlew(gr,title,stl,size);	}
+	/// Set aspect ratio for further plotting.
+	inline void Aspect(double Ax,double Ay,double Az=1)
+	{	mgl_aspect(gr, Ax, Ay, Az);		}
+	/// Shear a further plotting.
+	inline void Shear(double Sx,double Sy)
+	{	mgl_shear(gr, Sx, Sy);		}
+	/// Rotate a further plotting.
+	inline void Rotate(double TetX,double TetZ=0,double TetY=0)
+	{	mgl_rotate(gr, TetX, TetZ, TetY);	}
+	/// Rotate a further plotting around vector {x,y,z}.
+	inline void RotateN(double Tet,double x,double y,double z)
+	{	mgl_rotate_vector(gr, Tet, x, y, z);	}
+	/// Set perspective (in range [0,1)) for plot. Set to zero for switching off.
+	inline void Perspective(double val)
+	{	mgl_perspective(gr, val);	}
+	/// Set angle of view independently from Rotate().
+	inline void View(double TetX,double TetZ=0,double TetY=0)
+	{	mgl_view(gr, TetX, TetZ, TetY);	}
+	/// Set angle of view independently from Rotate().
+	inline void ViewAsRotate(double TetZ,double TetX,double TetY=0)
+	{	mgl_view(gr, -TetX, -TetZ, -TetY);	}
+	/// Zoom in/out a part of picture (use Zoom(0, 0, 1, 1) for restore default)
+	inline void Zoom(double x1, double y1, double x2, double y2)
+	{	mgl_zoom(gr, x1, y1, x2, y2);	}
+
+	/// Set size of frame in pixels. Normally this function is called internally.
+	inline void SetSize(int width, int height, bool clf=true)
+	{	if(clf)	mgl_set_size(gr, width, height);
+		else	mgl_scale_size(gr, width, height);	}
+	/// Scaling for all further set size calls.
+	static inline void SetSizeScl(double scl)	{	mgl_set_size_scl(scl);	}
+	/// Set plot quality
+	/** qual=0 -- no face drawing (fastest),
+	 *  qual=1 -- no color interpolation (fast),
+	 *  qual=2 -- high quality (normal),
+	 *  qual|4 -- direct bitmap drawing (low memory usage);
+	 *  qual|8 for dots drawing instead of primitives (extremely fast). */
+	inline void SetQuality(int qual=MGL_DRAW_NORM)	{	mgl_set_quality(gr, qual);	}
+	/// Get plot quality
+	inline int GetQuality()	{	return mgl_get_quality(gr);	}
+	/// Set drawing region for Quality&4
+	inline void SetDrawReg(long nx=1, long ny=1, long m=0)	{	mgl_set_draw_reg(gr,nx,ny,m);	}
+	/// Start group of objects
+	inline void StartGroup(const char *name)	{	mgl_start_group(gr, name);	}
+	/// End group of objects
+	inline void EndGroup()	{	mgl_end_group(gr);	}
+	/// Highlight objects with given id
+	inline void Highlight(int id)	{	mgl_highlight(gr, id);	}
+	/// Set boundary box for export graphics into 2D file formats.
+	/** If x2<0 (y2<0) then full width (height) will be used.
+	 *  If x1<0 or y1<0 or x1>=x2|Width or y1>=y2|Height then cropping will be disabled. */
+	inline void SetBBox(int x1=0, int y1=0, int x2=-1, int y2=-1)
+	{	mgl_set_bbox(gr,x1,y1,x2,y2);	}
+
+	/// Show current image
+	inline void ShowImage(const char *viewer, bool keep=0)
+	{	mgl_show_image(gr, viewer, keep);	}
+	/// Write the frame in file (depending extension, write current frame if fname is empty)
+	inline void WriteFrame(const char *fname=0,const char *descr="")
+	{	mgl_write_frame(gr, fname, descr);	}
+	/// Write the frame in file using JPEG format
+	inline void WriteJPEG(const char *fname,const char *descr="")
+	{	mgl_write_jpg(gr, fname, descr);	}
+	/// Write the frame in file using PNG format with transparency
+	inline void WritePNG(const char *fname,const char *descr="", bool alpha=true)
+	{	if(alpha)	mgl_write_png(gr, fname, descr);
+		else	mgl_write_png_solid(gr, fname, descr);	}
+	/// Write the frame in file using BMP format
+	inline void WriteBMP(const char *fname,const char *descr="")
+	{	mgl_write_bmp(gr, fname, descr);	}
+	/// Write the frame in file using BMP format
+	inline void WriteTGA(const char *fname,const char *descr="")
+	{	mgl_write_tga(gr, fname, descr);	}
+	/// Write the frame in file using PostScript format
+	inline void WriteEPS(const char *fname,const char *descr="")
+	{	mgl_write_eps(gr, fname, descr);	}
+	/// Write the frame in file using LaTeX format
+	inline void WriteTEX(const char *fname,const char *descr="")
+	{	mgl_write_tex(gr, fname, descr);	}
+	/// Write the frame in file using PostScript format as bitmap
+	inline void WriteBPS(const char *fname,const char *descr="")
+	{	mgl_write_bps(gr, fname, descr);	}
+	/// Write the frame in file using SVG format
+	inline void WriteSVG(const char *fname,const char *descr="")
+	{	mgl_write_svg(gr, fname, descr);	}
+	/// Write the frame in file using GIF format (only for current frame!)
+	inline void WriteGIF(const char *fname,const char *descr="")
+	{	mgl_write_gif(gr, fname, descr);	}
+
+	/// Write the frame in file using OBJ format
+	inline void WriteOBJ(const char *fname,const char *descr="",bool use_png=true)
+	{	mgl_write_obj(gr, fname, descr, use_png);	}
+	/// Write the frame in file using OBJ format - Balakin way
+	inline void WriteOBJold(const char *fname,const char *descr="",bool use_png=true)
+	{	mgl_write_obj_old(gr, fname, descr, use_png);	}
+	/// Write the frame in file using XYZ format
+	inline void WriteXYZ(const char *fname,const char *descr="")
+	{	mgl_write_xyz(gr, fname, descr);	}
+	/// Write the frame in file using STL format (faces only)
+	inline void WriteSTL(const char *fname,const char *descr="")
+	{	mgl_write_stl(gr, fname, descr);	}
+	/// Write the frame in file using OFF format
+	inline void WriteOFF(const char *fname,const char *descr="", bool colored=false)
+	{	mgl_write_off(gr, fname, descr,colored);	}
+//	/// Write the frame in file using X3D format
+//	inline void WriteX3D(const char *fname,const char *descr="")
+//	{	mgl_write_x3d(gr, fname, descr);	}
+	/// Write the frame in file using PRC format
+	inline void WritePRC(const char *fname,const char *descr="",bool make_pdf=true)
+	{	mgl_write_prc(gr, fname, descr, make_pdf);	}
+	/// Export in JSON format suitable for later drawing by JavaScript
+	inline void WriteJSON(const char *fname,const char *descr="",bool force_z=false)
+	{	if(force_z)	mgl_write_json_z(gr, fname, descr);
+		else 	mgl_write_json(gr, fname, descr);	}
+	/// Return string of JSON data suitable for later drawing by JavaScript
+	inline const char *GetJSON()	{	return mgl_get_json(gr);	}
+
+	/// Force preparing the image. It can be useful for OpenGL mode mostly.
+	inline void Finish()			{	mgl_finish(gr);	}
+	/// Create new frame.
+	inline void NewFrame()		{	mgl_new_frame(gr);	}
+	/// Finish frame drawing
+	inline void EndFrame()		{	mgl_end_frame(gr);	}
+	/// Get the number of created frames
+	inline int GetNumFrame()	{	return mgl_get_num_frame(gr);	}
+	/// Reset frames counter (start it from zero)
+	inline void ResetFrames()	{	mgl_reset_frames(gr);	}
+	/// Delete primitives for i-th frame (work if MGL_VECT_FRAME is set on)
+	inline void DelFrame(int i)	{	mgl_del_frame(gr, i);	}
+	/// Get drawing data for i-th frame (work if MGL_VECT_FRAME is set on)
+	inline void GetFrame(int i)	{	mgl_get_frame(gr, i);	}
+	/// Set drawing data for i-th frame (work if MGL_VECT_FRAME is set on). Work as EndFrame() but don't add frame to GIF image.
+	inline void SetFrame(int i)	{	mgl_set_frame(gr, i);	}
+	/// Append drawing data from i-th frame (work if MGL_VECT_FRAME is set on)
+	inline void ShowFrame(int i){	mgl_show_frame(gr, i);	}
+	/// Clear list of primitives for current drawing
+	inline void ClearFrame()	{	mgl_clear_frame(gr);	}
+
+	/// Start write frames to cinema using GIF format
+	inline void StartGIF(const char *fname, int ms=100)
+	{	mgl_start_gif(gr, fname,ms);	}
+	/// Stop writing cinema using GIF format
+	inline void CloseGIF()		{	mgl_close_gif(gr);	}
+	/// Export points and primitives in file using MGLD format
+	inline void ExportMGLD(const char *fname, const char *descr=0)
+	{	mgl_export_mgld(gr, fname, descr);	}
+	/// Import points and primitives from file using MGLD format
+	inline void ImportMGLD(const char *fname, bool add=false)
+	{	mgl_import_mgld(gr, fname, add);	}
+
+	/// Copy RGB values into array which is allocated by user
+	/** Position of element {i,j} is [3*i + 3*Width*j]. */
+	inline bool GetRGB(char *imgdata, int imglen)
+	{
+		long w=mgl_get_width(gr), h=mgl_get_height(gr);
+		if(imglen>=3*w*h)	memcpy(imgdata, mgl_get_rgb(gr),3*w*h);
+		return imglen>=3*w*h;
+	}
+	/// Get RGB values of current bitmap
+	/** Position of element {i,j} is [3*i + 3*Width*j]. */
+	inline const unsigned char *GetRGB()		{	return mgl_get_rgb(gr);	}
+	/// Copy RGBA values into array which is allocated by user
+	/** Position of element {i,j} is [4*i + 4*Width*j]. */
+	inline bool GetRGBA(char *imgdata, int imglen)
+	{
+		long w=mgl_get_width(gr), h=mgl_get_height(gr);
+		if(imglen>=4*w*h)	memcpy(imgdata, mgl_get_rgba(gr),4*w*h);
+		return imglen>=4*w*h;
+	}
+	/// Get RGBA values of current bitmap
+	/** Position of element {i,j} is [4*i + 4*Width*j]. */
+	inline const unsigned char *GetRGBA()	{	return mgl_get_rgba(gr);	}
+	/// Copy BGRN values into array which is allocated by user
+	inline bool GetBGRN(unsigned char *imgdata, int imglen)
+	{
+		long w=mgl_get_width(gr), h=mgl_get_height(gr), i;
+		const unsigned char *buf=mgl_get_rgb(gr);
+		if(imglen>=4*w*h)	for(i=0;i<w*h;i++)
+		{
+			imgdata[4*i]   = buf[3*i+2];
+			imgdata[4*i+1] = buf[3*i+1];
+			imgdata[4*i+2] = buf[3*i];
+			imgdata[4*i+3] = 255;
+		}
+		return imglen>=4*w*h;
+	}
+	/// Copy RGBA values of background image into array which is allocated by user
+	/** Position of element {i,j} is [4*i + 4*Width*j]. */
+	inline bool GetBackground(char *imgdata, int imglen)
+	{
+		long w=mgl_get_width(gr), h=mgl_get_height(gr);
+		if(imglen>=4*w*h)	memcpy(imgdata, mgl_get_background(gr),4*w*h);
+		return imglen>=4*w*h;
+	}
+	/// Get RGBA values of background image
+	/** Position of element {i,j} is [4*i + 4*Width*j]. */
+	inline const unsigned char *GetBackground()	{	return mgl_get_background(gr);	}
+	/// Get width of the image
+	inline int GetWidth()	{	return mgl_get_width(gr);	}
+	/// Get height of the image
+	inline int GetHeight()	{	return mgl_get_height(gr);}
+	/// Calculate 3D coordinate {x,y,z} for screen point {xs,ys}
+	inline mglPoint CalcXYZ(int xs, int ys)
+	{
+		mreal x,y,z;
+		mgl_calc_xyz(gr,xs,ys,&x,&y,&z);
+		return mglPoint(x,y,z);
+	}
+	/// Calculate screen point {xs,ys} for 3D coordinate {x,y,z}
+	inline mglPoint CalcScr(mglPoint p)
+	{
+		int xs,ys;
+		mgl_calc_scr(gr,p.x,p.y,p.z,&xs,&ys);
+		return mglPoint(xs,ys);
+	}
+	/// Set object/subplot id
+	inline void SetObjId(int id)		{	mgl_set_obj_id(gr,id);	}
+	/// Get object id
+	inline int GetObjId(long x,long y)	{	return mgl_get_obj_id(gr,x,y);	}
+	/// Get subplot id
+	inline int GetSplId(long x,long y)	{	return mgl_get_spl_id(gr,x,y);	}
+	/// Check if {\a xs,\a ys} is close to active point with accuracy d, and return its position or -1
+	inline long IsActive(int xs, int ys, int d=1)	{	return mgl_is_active(gr,xs,ys,d);	}
+
+	/// Combine plots from 2 canvases. Result will be saved into this
+	inline void Combine(const mglGraph *g)	{	mgl_combine_gr(gr,g->gr);	}
+
+	/// Clear up the frame and fill background by specified color
+	inline void Clf(double r, double g, double b)	{	mgl_clf_rgb(gr, r, g, b);	}
+	/// Clear up the frame and fill background by specified color with manual transparency
+	inline void Clf(const char *col)	{	mgl_clf_str(gr, col);	}
+	/// Clear up the frame and fill background by specified color
+	inline void Clf(char col)	{	mgl_clf_chr(gr, col);	}
+	/// Clear up the frame
+	inline void Clf()	{	mgl_clf(gr);	}
+	/// Clear unused points and primitives. Useful only in combination with SetFaceNum().
+	inline void ClearUnused()	{	mgl_clear_unused(gr);	}
+
+	/// Load background image
+	inline void LoadBackground(const char *fname, double alpha=1)
+	{	mgl_load_background(gr,fname,alpha);	}
+	/// Force drawing the image and use it as background one
+	inline void Rasterize()			{	mgl_rasterize(gr);	}
+
+	/// Draws the point (ball) at position {x,y,z} with color c
+	inline void Ball(mglPoint p, char c='r')
+	{	char s[3]={'.',c,0};	mgl_mark(gr, p.x, p.y, p.z, s);	}
+	/// Draws the mark at position p
+	inline void Mark(mglPoint p, const char *mark)
+	{	mgl_mark(gr, p.x, p.y, p.z, mark);	}
+	/// Draws the line between points by specified pen
+	/** Large \a n (for example, n=100) should be used for geodesic line in curved coordinates */
+	inline void Line(mglPoint p1, mglPoint p2, const char *pen="B",int n=2)
+	{	mgl_line(gr, p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, pen, n);	}
+	/// Draws the spline curve between points by specified pen
+	inline void Curve(mglPoint p1, mglPoint d1, mglPoint p2, mglPoint d2, const char *pen="B", int n=100)
+	{	mgl_curve(gr, p1.x, p1.y, p1.z, d1.x, d1.y, d1.z, p2.x, p2.y, p2.z, d2.x, d2.y, d2.z, pen, n);	}
+	/// Draws the 3d error box e for point p
+	inline void Error(mglPoint p, mglPoint e, const char *pen="k")
+	{	mgl_error_box(gr, p.x, p.y, p.z, e.x, e.y, e.z, pen);	}
+
+	/// Draws Lamerey diagram for mapping x_new = f(x_old)
+	/** String \a stl may contain: ‘v’ for drawing arrows; ‘~’ for disable 1st segment.
+	 *	Option value set the number of segments (default is 20).*/
+	inline void Lamerey(double x0, const mglData &f, const char *stl="", const char *opt="")
+	{	mgl_lamerey_dat(gr,x0,&f,stl,opt);	}
+	inline void Lamerey(double x0, const char *func, const char *stl="", const char *opt="")
+	{	mgl_lamerey_str(gr,x0,func,stl,opt);	}
+	/// Draws Bifurcation diagram for mapping x_new = f(x_old) in x-axis range
+	/** Option value set the number of stationary points (default is 1024).*/
+	inline void Bifurcation(double dx, const mglData &f, const char *stl="", const char *opt="")
+	{	mgl_bifurcation_dat(gr,dx,&f,stl,opt);	}
+	inline void Bifurcation(double dx, const char *func, const char *stl="", const char *opt="")
+	{	mgl_bifurcation_str(gr,dx,func,stl,opt);	}
+
+	/// Draws Iris plots for determining cross-dependences of data arrays
+	/** NOTE: using the same ranges and empty ids will not draw axis. This will add data to existing Iris plot.
+	 * 	Option value set the size of data labels ids, separated by ';'.*/
+	inline void Iris(mglData &dats, const char *ids, const char *stl="", const char *opt="")
+	{	mgl_iris_1(gr,&dats,ids,stl,opt);	}
+	inline void Iris(mglData &dats, const wchar_t *ids, const char *stl="", const char *opt="")
+	{	mgl_irisw_1(gr,&dats,ids,stl,opt);	}
+	inline void Iris(mglData &dats, mglData &ranges, const char *ids, const char *stl="", const char *opt="")
+	{	mgl_iris(gr,&dats,&ranges,ids,stl,opt);	}
+	inline void Iris(mglData &dats, mglData &ranges, const wchar_t *ids, const char *stl="", const char *opt="")
+	{	mgl_irisw(gr,&dats,&ranges,ids,stl,opt);	}
+
+	/// Draws the face between points with color stl (include interpolation up to 4 colors).
+	inline void Face(mglPoint p1, mglPoint p2, mglPoint p3, mglPoint p4, const char *stl="r")
+	{	mgl_face(gr, p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, p3.x, p3.y, p3.z, p4.x, p4.y, p4.z, stl);	}
+	/// Draws the face in y-z plane at point p with color stl (include interpolation up to 4 colors).
+	inline void FaceX(mglPoint p, double wy, double wz, const char *stl="w", double dx=0, double dy=0)
+	{	mgl_facex(gr, p.x, p.y, p.z, wy, wz, stl, dx, dy);	}
+	/// Draws the face in x-z plane at point p with color stl (include interpolation up to 4 colors).
+	inline void FaceY(mglPoint p, double wx, double wz, const char *stl="w", double dx=0, double dy=0)
+	{	mgl_facey(gr, p.x, p.y, p.z, wx, wz, stl, dx, dy);	}
+	/// Draws the face in x-y plane at point p with color stl (include interpolation up to 4 colors).
+	inline void FaceZ(mglPoint p, double wx, double wy, const char *stl="w", double dx=0, double dy=0)
+	{	mgl_facez(gr, p.x, p.y, p.z, wx, wy, stl, dx, dy);	}
+	/// Draws the drop at point p in direction d with color col and radius r
+	/** Parameter \a shift set the degree of drop oblongness: ‘0’ is sphere, ‘1’ is maximally oblongness drop. Parameter \a ap set relative width of the drop (this is analogue of “ellipticity” for the sphere).*/
+	inline void Drop(mglPoint p, mglPoint d, double r, const char *col="r", double shift=1, double ap=1)
+	{	mgl_drop(gr, p.x, p.y, p.z, d.x, d.y, d.z, r, col, shift, ap);	}
+	/// Draws the sphere at point p with color col and radius r
+	inline void Sphere(mglPoint p, double r, const char *col="r")
+	{	mgl_sphere(gr, p.x, p.y, p.z, r, col);	}
+	/// Draws the cone between points p1,p2 with radius r1,r2 and with style stl
+	/** Parameter \a stl can contain:
+	 * ‘@’ for drawing edges;
+	 * ‘#’ for wired cones;
+	 * ‘t’ for drawing tubes/cylinder instead of cones/prisms;
+	 * ‘4’, ‘6’, ‘8’ for drawing square, hex- or octo-prism instead of cones.*/
+	inline void Cone(mglPoint p1, mglPoint p2, double r1, double r2=-1, const char *stl="r@")
+	{	mgl_cone(gr, p1.x, p1.y, p1.z, p2.x, p2.y, p2.z,r1,r2,stl);	}
+	/// Draws the ellipse between points p1,p2 with color stl and width r
+	/** Parameter \a stl can contain:
+	 * ‘#’ for wired figure (boundary only);
+	 * ‘@’ for filled figure and with boundary (second color or black one is used for boundary).*/
+	inline void Ellipse(mglPoint p1, mglPoint p2, double r, const char *stl="r")
+	{	mgl_ellipse(gr, p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, r,stl);	}
+	/// Draws the circle at point p with color stl and radius r
+	/** Parameter \a stl can contain:
+	 * ‘#’ for wired figure (boundary only);
+	 * ‘@’ for filled figure and with boundary (second color or black one is used for boundary).*/
+	inline void Circle(mglPoint p, double r, const char *stl="r")
+	{	mgl_ellipse(gr, p.x, p.y, p.z, p.x, p.y, p.z, r,stl);	}
+	/// Draws the rhomb between points p1,p2 with color stl and width r
+	/** Parameter \a stl can contain:
+	 * ‘#’ for wired figure (boundary only);
+	 * ‘@’ for filled figure and with boundary (second color or black one is used for boundary).*/
+	inline void Rhomb(mglPoint p1, mglPoint p2, double r, const char *stl="r")
+	{	mgl_rhomb(gr, p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, r,stl);	}
+	/// Draws the polygon based on points p1,p2 with color stl
+	/** Parameter \a stl can contain:
+	 * ‘#’ for wired figure (boundary only);
+	 * ‘@’ for filled figure and with boundary (second color or black one is used for boundary).*/
+	inline void Polygon(mglPoint p1, mglPoint p2, int n, const char *stl="r")
+	{	mgl_polygon(gr, p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, n,stl);	}
+	/// Draws the arc around axis pr with center at p0 and starting from p1, by color stl and angle a (in degrees)
+	inline void Arc(mglPoint p0, mglPoint pa, mglPoint p1, double a, const char *stl="r")
+	{	mgl_arc_ext(gr, p0.x,p0.y,p0.z, pa.x,pa.y,pa.z, p1.x,p1.y,p1.z, a,stl);	}
+	/// Draws the arc around axis 'z' with center at p0 and starting from p1, by color stl and angle a (in degrees)
+	inline void Arc(mglPoint p0, mglPoint p1, double a, const char *stl="r")
+	{	mgl_arc_ext(gr, p0.x,p0.y,p0.z, 0,0,1, p1.x,p1.y,p0.z, a,stl);	}
+	/// Draws bitmap (logo) which is stretched along whole axis range
+	inline void Logo(long w, long h, const unsigned char *rgba, bool smooth=false, const char *opt="")
+	{	mgl_logo(gr, w, h, rgba, smooth, opt);	}
+	inline void Logo(const char *fname, bool smooth=false, const char *opt="")
+	{	mgl_logo_file(gr, fname, smooth, opt);	}
+
+	/// Print text in position p with specified font
+	inline void Putsw(mglPoint p,const wchar_t *text,const char *font=":C",double size=-1)
+	{	mgl_putsw(gr, p.x, p.y, p.z, text, font, size);	}
+	/// Print text in position p with specified font
+	inline void Puts(mglPoint p,const char *text,const char *font=":C",double size=-1)
+	{	mgl_puts(gr, p.x, p.y, p.z, text, font, size);	}
+	/// Print text in position p with specified font
+	inline void Putsw(double x, double y,const wchar_t *text,const char *font=":AC",double size=-1)
+	{	mgl_putsw(gr, x, y, 0, text, font, size);	}
+	/// Print text in position p with specified font
+	inline void Puts(double x, double y,const char *text,const char *font=":AC",double size=-1)
+	{	mgl_puts(gr, x, y, 0, text, font, size);	}
+	/// Print text in position p along direction d with specified font
+	inline void Putsw(mglPoint p, mglPoint d, const wchar_t *text, const char *font=":L", double size=-1)
+	{	mgl_putsw_dir(gr, p.x, p.y, p.z, d.x, d.y, d.z, text, font, size);	}
+	/// Print text in position p along direction d with specified font
+	inline void Puts(mglPoint p, mglPoint d, const char *text, const char *font=":L", double size=-1)
+	{	mgl_puts_dir(gr, p.x, p.y, p.z, d.x, d.y, d.z, text, font, size);	}
+
+	/// Print text along the curve
+	inline void Text(const mglData &x, const mglData &y, const mglData &z, const char *text, const char *font="", const char *opt="")
+	{	mgl_text_xyz(gr, &x, &y, &z, text, font, opt);	}
+	/// Print text along the curve
+	inline void Text(const mglData &x, const mglData &y, const char *text, const char *font="", const char *opt="")
+	{	mgl_text_xy(gr, &x, &y, text, font, opt);	}
+	/// Print text along the curve
+	inline void Text(const mglData &y, const char *text, const char *font="", const char *opt="")
+	{	mgl_text_y(gr, &y, text, font, opt);	}
+	/// Print text along the curve
+	inline void Text(const mglData &x, const mglData &y, const mglData &z, const wchar_t *text, const char *font="", const char *opt="")
+	{	mgl_textw_xyz(gr, &x, &y, &z, text, font, opt);	}
+	/// Print text along the curve
+	inline void Text(const mglData &x, const mglData &y, const wchar_t *text, const char *font="", const char *opt="")
+	{	mgl_textw_xy(gr, &x, &y, text, font, opt);	}
+	/// Print text along the curve
+	inline void Text(const mglData &y, const wchar_t *text, const char *font="", const char *opt="")
+	{	mgl_textw_y(gr, &y, text, font, opt);	}
+
+	/// Draws bounding box outside the plotting volume with color c.
+	/** Style ‘@’ produce filled back faces. */
+	inline void Box(const char *col="", bool ticks=true)
+	{	mgl_box_str(gr, col, ticks);	}
+	/// Draw axises with ticks in direction(s) dir.
+	/** Parameter \a dir may contain:
+	 *	‘xyzt’for drawing axis in corresponding direction;
+	 *	‘XYZT’ for drawing axis in corresponding direction but with inverted positions of labels;
+	 *	‘~’, ‘_’ for disabling tick labels;
+	 *	‘U’ for disabling rotation of tick labels;
+	 *	‘^’ for inverting default axis origin;
+	 *	‘!’ for disabling ticks tuning;
+	 *	‘AKDTVISO’ for drawing arrow at the end of axis;
+	 *	‘a’ for forced adjusting of axis ticks;
+	 *	‘f’ for printing ticks labels in fixed format;
+	 *	‘E’ for using ‘E’ instead of ‘e’ in ticks labels;
+	 *	‘F’ for printing ticks labels in LaTeX format;
+	 *	‘+’ for printing ‘+’ for positive ticks;
+	 *	‘-’ for printing usual ‘-’ in ticks labels;
+	 *	‘0123456789’ for precision at printing ticks labels.
+	 *	 Option "value" set the manual rotation angle for the ticks. */
+	inline void Axis(const char *dir="xyzt", const char *stl="", const char *opt="")
+	{	mgl_axis(gr, dir,stl,opt);	}
+	/// Draw grid lines perpendicular to direction(s) dir.
+	inline void Grid(const char *dir="xyzt",const char *pen="B", const char *opt="")
+	{	mgl_axis_grid(gr, dir, pen, opt);	}
+	/// Print the label text for axis dir.
+	/** Option "value" set additional shifting of the label. */
+	inline void Label(char dir, const char *text, double pos=+1, const char *opt="")
+	{	mgl_label(gr, dir, text, pos, opt);	}
+	/// Print the label text for axis dir.
+	/** Option "value" set additional shifting of the label. */
+	inline void Label(char dir, const wchar_t *text, double pos=+1, const char *opt="")
+	{	mgl_labelw(gr, dir, text, pos, opt);	}
+
+	/// Draw colorbar at edge of axis
+	/** Parameter \a sch may contain:
+	 *	 ‘<>^_’ for positioning at left, at right, at top or at bottom correspondingly;
+	 *	 ‘I’ for positioning near bounding (by default, at edges of subplot);
+	 *	 ‘A’ for using absolute coordinates;
+	 *	 ‘~’ for disabling tick labels.
+	 *	 ‘!’ for disabling ticks tuning;
+	 *	 ‘f’ for printing ticks labels in fixed format;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’ in ticks labels;
+	 *	 ‘F’ for printing ticks labels in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive ticks;
+	 *	 ‘-’ for printing usual ‘-’ in ticks labels;
+	 *	 ‘0123456789’ for precision at printing ticks labels.*/
+	inline void Colorbar(const char *sch="")
+	{	mgl_colorbar(gr, sch);	}
+	/// Draw colorbar at manual position
+	/** Parameter \a sch may contain:
+	 *	 ‘<>^_’ for positioning at left, at right, at top or at bottom correspondingly;
+	 *	 ‘I’ for positioning near bounding (by default, at edges of subplot);
+	 *	 ‘A’ for using absolute coordinates;
+	 *	 ‘~’ for disabling tick labels.
+	 *	 ‘!’ for disabling ticks tuning;
+	 *	 ‘f’ for printing ticks labels in fixed format;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’ in ticks labels;
+	 *	 ‘F’ for printing ticks labels in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive ticks;
+	 *	 ‘-’ for printing usual ‘-’ in ticks labels;
+	 *	 ‘0123456789’ for precision at printing ticks labels.*/
+	inline void Colorbar(const char *sch,double x,double y,double w=1,double h=1)
+	{	mgl_colorbar_ext(gr, sch, x,y,w,h);	}
+	/// Draw colorbar with manual colors at edge of axis
+	/** Parameter \a sch may contain:
+	 *	 ‘<>^_’ for positioning at left, at right, at top or at bottom correspondingly;
+	 *	 ‘I’ for positioning near bounding (by default, at edges of subplot);
+	 *	 ‘A’ for using absolute coordinates;
+	 *	 ‘~’ for disabling tick labels.
+	 *	 ‘!’ for disabling ticks tuning;
+	 *	 ‘f’ for printing ticks labels in fixed format;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’ in ticks labels;
+	 *	 ‘F’ for printing ticks labels in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive ticks;
+	 *	 ‘-’ for printing usual ‘-’ in ticks labels;
+	 *	 ‘0123456789’ for precision at printing ticks labels.*/
+	inline void Colorbar(const mglData &val, const char *sch="")
+	{	mgl_colorbar_val(gr, &val, sch);	}
+	/// Draw colorbar with manual colors at manual position
+	/** Parameter \a sch may contain:
+	 *	 ‘<>^_’ for positioning at left, at right, at top or at bottom correspondingly;
+	 *	 ‘I’ for positioning near bounding (by default, at edges of subplot);
+	 *	 ‘A’ for using absolute coordinates;
+	 *	 ‘~’ for disabling tick labels.
+	 *	 ‘!’ for disabling ticks tuning;
+	 *	 ‘f’ for printing ticks labels in fixed format;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’ in ticks labels;
+	 *	 ‘F’ for printing ticks labels in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive ticks;
+	 *	 ‘-’ for printing usual ‘-’ in ticks labels;
+	 *	 ‘0123456789’ for precision at printing ticks labels.*/
+	inline void Colorbar(const mglData &val, const char *sch,double x,double y,double w=1,double h=1)
+	{	mgl_colorbar_val_ext(gr, &val, sch, x,y,w,h);	}
+
+	/// Add string to legend
+	inline void AddLegend(const char *text,const char *style)
+	{	mgl_add_legend(gr, text, style);	}
+	inline void AddLegend(const wchar_t *text,const char *style)
+	{	mgl_add_legendw(gr, text, style);	}
+	/// Clear saved legend string
+	inline void ClearLegend()
+	{	mgl_clear_legend(gr);	}
+	/// Draw legend of accumulated strings at position {x,y}
+	/** Parameter fnt may contain:
+	 *	 font style for legend text;
+	 *	 colors for background (first one), border (second one) and text (last one);
+	 *	 ‘A’ for positioning in absolute coordinates;
+	 *	 ‘^’ for positioning outside of specified point;
+	 *	 ‘-’ for arranging entries horizontally;
+	 *	 ‘#’ for drawing box around legend.
+	 * Option value set the space between line samples and text (default is 0.1).*/
+	inline void Legend(double x, double y, const char *font="#", const char *opt="")
+	{	mgl_legend_pos(gr, x, y, font, opt);	}
+	/// Draw legend of accumulated strings
+	/** Parameter fnt may contain:
+	 *	 font style for legend text;
+	 *	 colors for background (first one), border (second one) and text (last one);
+	 *	 ‘A’ for positioning in absolute coordinates;
+	 *	 ‘^’ for positioning outside of specified point;
+	 *	 ‘-’ for arranging entries horizontally;
+	 *	 ‘#’ for drawing box around legend.
+	 * Option value set the space between line samples and text (default is 0.1).
+	 * Parameter \a where sets position: 0 at bottom-left, 1 at bottom-right, 2 at top-left, 3 at top-right (default).*/
+	inline void Legend(int where=3, const char *font="#", const char *opt="")
+	{	mgl_legend(gr, where, font, opt);	}
+	/// Set number of marks in legend sample
+	inline void SetLegendMarks(int num)		{	mgl_set_legend_marks(gr, num);	}
+
+	/// Draw usual curve {x,y,z}
+	inline void Plot(const mglData &x, const mglData &y, const mglData &z, const char *pen="", const char *opt="")
+	{	mgl_plot_xyz(gr, &x, &y, &z, pen, opt);	}
+	/// Draw usual curve {x,y}
+	inline void Plot(const mglData &x, const mglData &y, const char *pen="", const char *opt="")
+	{	mgl_plot_xy(gr, &x, &y, pen,opt);	}
+	/// Draw usual curve {x,y} with x in x-axis range
+	inline void Plot(const mglData &y, const char *pen="", const char *opt="")
+	{	mgl_plot(gr, &y, pen,opt);	}
+	/// Draw tapes which rotates as (bi-)normales of curve {x,y,z}
+	/** The width of tape is proportional to barwidth and can be changed by option "value".*/
+	inline void Tape(const mglData &x, const mglData &y, const mglData &z, const char *pen="", const char *opt="")
+	{	mgl_tape_xyz(gr, &x, &y, &z, pen, opt);	}
+	/// Draw tapes which rotates as (bi-)normales of curve {x,y}
+	/** The width of tape is proportional to barwidth and can be changed by option "value".*/
+	inline void Tape(const mglData &x, const mglData &y, const char *pen="", const char *opt="")
+	{	mgl_tape_xy(gr, &x, &y, pen,opt);	}
+	/// Draw tapes which rotates as (bi-)normales of curve {x,y} with x in x-axis range
+	/** The width of tape is proportional to barwidth and can be changed by option "value".*/
+	inline void Tape(const mglData &y, const char *pen="", const char *opt="")
+	{	mgl_tape(gr, &y, pen,opt);	}
+	/// Draw radar chart (plot in curved coordinates)
+	/** Option "value" set the additional shift of data (i.e. the data a+value is used instead of a).*/
+	inline void Radar(const mglData &a, const char *pen="", const char *opt="")
+	{	mgl_radar(gr, &a, pen, opt);	}
+
+	/// Draw stairs for points in arrays {x,y,z}
+	inline void Step(const mglData &x, const mglData &y, const mglData &z, const char *pen="", const char *opt="")
+	{	mgl_step_xyz(gr, &x, &y, &z, pen, opt);	}
+	/// Draw stairs for points in arrays {x,y}
+	inline void Step(const mglData &x, const mglData &y, const char *pen="", const char *opt="")
+	{	mgl_step_xy(gr, &x, &y, pen, opt);	}
+	/// Draw stairs for points in arrays {x,y} with x in x-axis range
+	inline void Step(const mglData &y, const char *pen="", const char *opt="")
+	{	mgl_step(gr, &y, pen, opt);	}
+
+	/// Draw curve {x,y,z} which is colored by c (like tension plot)
+	inline void Tens(const mglData &x, const mglData &y, const mglData &z, const mglData &c, const char *pen="", const char *opt="")
+	{	mgl_tens_xyz(gr, &x, &y, &z, &c, pen, opt);	}
+	/// Draw curve {x,y} which is colored by c (like tension plot)
+	inline void Tens(const mglData &x, const mglData &y, const mglData &c, const char *pen="", const char *opt="")
+	{	mgl_tens_xy(gr, &x, &y, &c, pen, opt);	}
+	/// Draw curve {x,y} with x in x-axis range which is colored by c (like tension plot)
+	inline void Tens(const mglData &y, const mglData &c, const char *pen="", const char *opt="")
+	{	mgl_tens(gr, &y, &c, pen, opt);	}
+
+	/// Fill area between curve {x,y,z} and axis plane
+	/** Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Area(const mglData &x, const mglData &y, const mglData &z, const char *pen="", const char *opt="")
+	{	mgl_area_xyz(gr, &x, &y, &z, pen, opt);	}
+	/// Fill area between curve {x,y} and axis plane
+	/** Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Area(const mglData &x, const mglData &y, const char *pen="", const char *opt="")
+	{	mgl_area_xy(gr, &x, &y, pen, opt);	}
+	/// Fill area between curve {x,y} with x in x-axis range and axis plane
+	/** Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Area(const mglData &y, const char *pen="", const char *opt="")
+	{	mgl_area(gr, &y, pen, opt);	}
+
+	/// Fill area between curves {x,y1} and {x,y2} with x in x-axis range
+	/** Style 'i' will fill area only if y1 < y2.
+	  * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Region(const mglData &y1, const mglData &y2, const char *pen="", const char *opt="")
+	{	mgl_region(gr, &y1, &y2, pen, opt);	}
+	/// Fill area between curves {x,y1} and {x,y2}
+	/** Style 'i' will fill area only if y1 < y2.
+	  * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Region(const mglData &x, const mglData &y1, const mglData &y2, const char *pen="", const char *opt="")
+	{	mgl_region_xy(gr, &x, &y1, &y2, pen, opt);	}
+	/// Fill area (draw ribbon) between curves {x1,y1,z1} and {x2,y2,z2}
+	/** Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Region(const mglData &x1, const mglData &y1, const mglData &z1, const mglData &x2, const mglData &y2, const mglData &z2, const char *pen="", const char *opt="")
+	{	mgl_region_3d(gr, &x1, &y1, &z1, &x2, &y2, &z2, pen, opt);	}
+	/// Fill area (draw ribbon) between curves {x1,y1} and {x2,y2}
+	/** Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Region(const mglData &x1, const mglData &y1, const mglData &x2, const mglData &y2, const char *pen="", const char *opt="")
+	{	mgl_region_3d(gr, &x1, &y1, NULL, &x2, &y2, NULL, pen, opt);	}
+
+	/// Draw vertical lines from points {x,y,z} to axis plane
+	inline void Stem(const mglData &x, const mglData &y, const mglData &z, const char *pen="", const char *opt="")
+	{	mgl_stem_xyz(gr, &x, &y, &z, pen, opt);	}
+	/// Draw vertical lines from points {x,y} to axis plane
+	inline void Stem(const mglData &x, const mglData &y, const char *pen="", const char *opt="")
+	{	mgl_stem_xy(gr, &x, &y, pen, opt);	}
+	/// Draw vertical lines from points {x,y} with x in x-axis range to axis plane
+	inline void Stem(const mglData &y, const char *pen="", const char *opt="")
+	{	mgl_stem(gr, &y, pen, opt);	}
+
+	/// Draw vertical bars from points {x,y,z} to axis plane
+	/** String \a pen may contain:
+	 * ‘a’ for drawing boxes one above another (like summation);
+	 * ‘f’ for waterfall chart;
+	 * ‘<’, ‘^’, ‘>’ for aligning boxes: at left, centered, at right.
+	 * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Bars(const mglData &x, const mglData &y, const mglData &z, const char *pen="", const char *opt="")
+	{	mgl_bars_xyz(gr, &x, &y, &z, pen, opt);	}
+	/// Draw vertical bars from points {x,y} to axis plane
+	/** String \a pen may contain:
+	 * ‘a’ for drawing boxes one above another (like summation);
+	 * ‘f’ for waterfall chart;
+	 * ‘<’, ‘^’, ‘>’ for aligning boxes: at left, centered, at right.
+	 * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Bars(const mglData &x, const mglData &y, const char *pen="", const char *opt="")
+	{	mgl_bars_xy(gr, &x, &y, pen, opt);	}
+	/// Draw vertical bars from points {x,y} with x in x-axis range to axis plane
+	/** String \a pen may contain:
+	 * ‘a’ for drawing boxes one above another (like summation);
+	 * ‘f’ for waterfall chart;
+	 * ‘<’, ‘^’, ‘>’ for aligning boxes: at left, centered, at right.
+	 * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Bars(const mglData &y, const char *pen="", const char *opt="")
+	{	mgl_bars(gr, &y, pen, opt);	}
+	/// Draw horizontal bars from points {x,y} to axis plane
+	/** String \a pen may contain:
+	 * ‘a’ for drawing boxes one above another (like summation);
+	 * ‘f’ for waterfall chart;
+	 * ‘<’, ‘^’, ‘>’ for aligning boxes: at left, centered, at right.
+	 * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Barh(const mglData &y, const mglData &v, const char *pen="", const char *opt="")
+	{	mgl_barh_yx(gr, &y, &v, pen, opt);	}
+	/// Draw horizontal bars from points {x,y} with y in y-axis range to axis plane
+	/** String \a pen may contain:
+	 * ‘a’ for drawing boxes one above another (like summation);
+	 * ‘f’ for waterfall chart;
+	 * ‘<’, ‘^’, ‘>’ for aligning boxes: at left, centered, at right.
+	 * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Barh(const mglData &v, const char *pen="", const char *opt="")
+	{	mgl_barh(gr, &v, pen, opt);	}
+	/// Draw chart for data a
+	/** Space denote transparent color. Style '#' draw black borders. */
+	inline void Chart(const mglData &a, const char *colors="", const char *opt="")
+	{	mgl_chart(gr, &a, colors,opt);	}
+
+	/// Draw Open-High-Low-Close (OHLC) diagram
+	/**  Different colors for up and down values are used if number of specified colors is equal to 2*number of curves. */
+	inline void OHLC(const mglData &x, const mglData &open, const mglData &high, const mglData &low, const mglData &close, const char *pen="", const char *opt="")
+	{	mgl_ohlc_x(gr, &x, &open,&high,&low,&close,pen,opt);	}
+	/// Draw Open-High-Low-Close (OHLC) diagram with x in x-axis range
+	/**  Different colors for up and down values are used if number of specified colors is equal to 2*number of curves. */
+	inline void OHLC(const mglData &open, const mglData &high, const mglData &low, const mglData &close, const char *pen="", const char *opt="")
+	{	mgl_ohlc(gr, &open,&high,&low,&close,pen,opt);	}
+
+	/// Draw box-plot (special 5-value plot used in statistic)
+	/** String \a pen may contain ‘<’, ‘^’, ‘>’ for aligning boxes: at left, centered, at right.*/
+	inline void BoxPlot(const mglData &x, const mglData &y, const char *pen="", const char *opt="")
+	{	mgl_boxplot_xy(gr, &x, &y, pen,opt);	}
+	/// Draw box-plot (special 5-value plot used in statistic) with x in x-axis range
+	/** String \a pen may contain ‘<’, ‘^’, ‘>’ for aligning boxes: at left, centered, at right.*/
+	inline void BoxPlot(const mglData &y, const char *pen="", const char *opt="")
+	{	mgl_boxplot(gr, &y, pen,opt);	}
+
+	/// Draw candle plot
+	/** Different colors are used for up and down values if 2 colors are specified.
+	 *  Style ‘#’ force drawing wire candle even for 2-color scheme. */
+	inline void Candle(const mglData &x, const mglData &v1, const mglData &v2, const mglData &y1, const mglData &y2, const char *pen="", const char *opt="")
+	{	mgl_candle_xyv(gr, &x, &v1, &v2, &y1, &y2, pen, opt);	}
+	/// Draw candle plot with x in x-axis range
+	/** Different colors are used for up and down values if 2 colors are specified.
+	 *  Style ‘#’ force drawing wire candle even for 2-color scheme. */
+	inline void Candle(const mglData &v1, const mglData &v2, const mglData &y1, const mglData &y2, const char *pen="", const char *opt="")
+	{	mgl_candle_yv(gr, &v1, &v2, &y1, &y2, pen, opt);	}
+	inline void Candle(const mglData &v1, const mglData &v2, const char *pen="", const char *opt="")
+	{	mgl_candle_yv(gr, &v1, &v2, NULL, NULL, pen, opt);	}
+	/// Draw candle plot with v1=v[i], v2=v[i+1]
+	/** Different colors are used for up and down values if 2 colors are specified.
+	 *  Style ‘#’ force drawing wire candle even for 2-color scheme. */
+	inline void Candle(const mglData &y, const mglData &y1, const mglData &y2, const char *pen="", const char *opt="")
+	{	mgl_candle(gr, &y, &y1, &y2, pen, opt);	}
+	/// Draw candle plot with v1=v[i], v2=v[i+1]
+	/** Different colors are used for up and down values if 2 colors are specified.
+	 *  Style ‘#’ force drawing wire candle even for 2-color scheme. */
+	inline void Candle(const mglData &y, const char *pen="", const char *opt="")
+	{	mgl_candle(gr, &y, NULL, NULL, pen, opt);	}
+
+	/// Draw cones from points {x,y,z} to axis plane
+	/** String \a pen may contain:
+	 * ‘@’ for drawing edges;
+	 * ‘#’ for wired cones;
+	 * ‘t’ for drawing tubes/cylinders instead of cones/prisms;
+	 * ‘4’, ‘6’, ‘8’ for drawing square, hex- or octo-prism instead of cones;
+	 * ‘<’, ‘^’ or ‘>’ for aligning cones left, right or centering them at its x-coordinates.
+	 * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Cones(const mglData &x, const mglData &y, const mglData &z, const char *pen="@", const char *opt="")
+	{	mgl_cones_xyz(gr, &x, &y, &z, pen, opt);	}
+	/// Draw cones from points {x,z} to axis plane
+	/** String \a pen may contain:
+	 * ‘@’ for drawing edges;
+	 * ‘#’ for wired cones;
+	 * ‘t’ for drawing tubes/cylinders instead of cones/prisms;
+	 * ‘4’, ‘6’, ‘8’ for drawing square, hex- or octo-prism instead of cones;
+	 * ‘<’, ‘^’ or ‘>’ for aligning cones left, right or centering them at its x-coordinates.
+	 * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Cones(const mglData &x, const mglData &z, const char *pen="@", const char *opt="")
+	{	mgl_cones_xz(gr, &x, &z, pen, opt);	}
+	/// Draw cones from points {x,z} with x in x-axis range to axis plane
+	/** String \a pen may contain:
+	 * ‘@’ for drawing edges;
+	 * ‘#’ for wired cones;
+	 * ‘t’ for drawing tubes/cylinders instead of cones/prisms;
+	 * ‘4’, ‘6’, ‘8’ for drawing square, hex- or octo-prism instead of cones;
+	 * ‘<’, ‘^’ or ‘>’ for aligning cones left, right or centering them at its x-coordinates.
+	 * Gradient filling is used if number of specified colors is equal to 2*number of curves.*/
+	inline void Cones(const mglData &z, const char *pen="@", const char *opt="")
+	{	mgl_cones(gr, &z, pen, opt);	}
+
+	/// Draw error boxes {ey} at points {x,y} with x in x-axis range
+	/** Style ‘@’ set to draw large semitransparent mark instead of error box.*/
+	inline void Error(const mglData &y, const mglData &ey, const char *pen="", const char *opt="")
+	{	mgl_error(gr, &y, &ey, pen, opt);	}
+	/// Draw error boxes {ey} at points {x,y}
+	/** Style ‘@’ set to draw large semitransparent mark instead of error box.*/
+	inline void Error(const mglData &x, const mglData &y, const mglData &ey, const char *pen="", const char *opt="")
+	{	mgl_error_xy(gr, &x, &y, &ey, pen, opt);	}
+	/// Draw error boxes {ex,ey} at points {x,y}
+	/** Style ‘@’ set to draw large semitransparent mark instead of error box.*/
+	inline void Error(const mglData &x, const mglData &y, const mglData &ex, const mglData &ey, const char *pen="", const char *opt="")
+	{	mgl_error_exy(gr, &x, &y, &ex, &ey, pen, opt);	}
+
+	/// Draw marks with size r at points {x,y,z}
+	inline void Mark(const mglData &x, const mglData &y, const mglData &z, const mglData &r, const char *pen, const char *opt="")
+	{	mgl_mark_xyz(gr, &x, &y, &z, &r, pen, opt);	}
+	/// Draw marks with size r at points {x,y}
+	inline void Mark(const mglData &x, const mglData &y, const mglData &r, const char *pen, const char *opt="")
+	{	mgl_mark_xy(gr, &x, &y, &r, pen, opt);	}
+	/// Draw marks with size r at points {x,y} with x in x-axis range
+	inline void Mark(const mglData &y, const mglData &r, const char *pen, const char *opt="")
+	{	mgl_mark_y(gr, &y, &r, pen, opt);	}
+
+	/// Draw Poincare map at condition s==0 for curve {x,y,z}
+	inline void Pmap(const mglData &x, const mglData &y, const mglData &z, const mglData &s, const char *pen, const char *opt="")
+	{	mgl_pmap_xyz(gr, &x, &y, &z, &s, pen, opt);	}
+	/// Draw Poincare map at condition s==0 for curve {x,y}
+	inline void Pmap(const mglData &x, const mglData &y, const mglData &s, const char *pen, const char *opt="")
+	{	mgl_pmap_xy(gr, &x, &y, &s, pen, opt);	}
+	/// Draw Poincare map at condition s==0 for curve {x,y} with x in x-axis range
+	inline void Pmap(const mglData &y, const mglData &s, const char *pen, const char *opt="")
+	{	mgl_pmap(gr, &y, &s, pen, opt);	}
+
+	/// Draw textual marks with size r at points {x,y,z}
+	inline void TextMark(const mglData &x, const mglData &y, const mglData &z, const mglData &r, const char *text, const char *fnt="", const char *opt="")
+	{	mgl_textmark_xyzr(gr, &x, &y, &z, &r, text, fnt, opt);	}
+	/// Draw textual marks with size r at points {x,y}
+	inline void TextMark(const mglData &x, const mglData &y, const mglData &r, const char *text, const char *fnt="", const char *opt="")
+	{	mgl_textmark_xyr(gr, &x, &y, &r, text, fnt, opt);	}
+	/// Draw textual marks with size r at points {x,y} with x in x-axis range
+	inline void TextMark(const mglData &y, const mglData &r, const char *text, const char *fnt="", const char *opt="")
+	{	mgl_textmark_yr(gr, &y, &r, text, fnt, opt);	}
+	/// Draw textual marks at points {x,y} with x in x-axis range
+	inline void TextMark(const mglData &y, const char *text, const char *fnt="", const char *opt="")
+	{	mgl_textmark(gr, &y, text, fnt, opt);	}
+	/// Draw textual marks with size r at points {x,y,z}
+	inline void TextMark(const mglData &x, const mglData &y, const mglData &z, const mglData &r, const wchar_t *text, const char *fnt="", const char *opt="")
+	{	mgl_textmarkw_xyzr(gr, &x, &y, &z, &r, text, fnt, opt);	}
+	/// Draw textual marks with size r at points {x,y}
+	inline void TextMark(const mglData &x, const mglData &y, const mglData &r, const wchar_t *text, const char *fnt="", const char *opt="")
+	{	mgl_textmarkw_xyr(gr, &x, &y, &r, text, fnt, opt);	}
+	/// Draw textual marks with size r at points {x,y} with x in x-axis range
+	inline void TextMark(const mglData &y, const mglData &r, const wchar_t *text, const char *fnt="", const char *opt="")
+	{	mgl_textmarkw_yr(gr, &y, &r, text, fnt, opt);	}
+	/// Draw textual marks at points {x,y} with x in x-axis range
+	inline void TextMark(const mglData &y, const wchar_t *text, const char *fnt="", const char *opt="")
+	{	mgl_textmarkw(gr, &y, text, fnt, opt);	}
+
+	/// Draw labels for points coordinate(s) at points {x,y,z}
+	/** String \a fnt may contain:
+	 *	 ‘f’ for fixed format of printed numbers;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’;
+	 *	 ‘F’ for printing in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive numbers;
+	 *	 ‘-’ for printing usual ‘-’;
+	 *	 ‘0123456789’ for precision at printing numbers.*/
+	inline void Label(const mglData &x, const mglData &y, const mglData &z, const char *text, const char *fnt="", const char *opt="")
+	{	mgl_label_xyz(gr, &x, &y, &z, text, fnt, opt);	}
+	/// Draw labels for points coordinate(s) at points {x,y}
+	/** String \a fnt may contain:
+	 *	 ‘f’ for fixed format of printed numbers;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’;
+	 *	 ‘F’ for printing in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive numbers;
+	 *	 ‘-’ for printing usual ‘-’;
+	 *	 ‘0123456789’ for precision at printing numbers.*/
+	inline void Label(const mglData &x, const mglData &y, const char *text, const char *fnt="", const char *opt="")
+	{	mgl_label_xy(gr, &x, &y, text, fnt, opt);	}
+	/// Draw labels for points coordinate(s) at points {x,y} with x in x-axis range
+	/** String \a fnt may contain:
+	 *	 ‘f’ for fixed format of printed numbers;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’;
+	 *	 ‘F’ for printing in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive numbers;
+	 *	 ‘-’ for printing usual ‘-’;
+	 *	 ‘0123456789’ for precision at printing numbers.*/
+	inline void Label(const mglData &y, const char *text, const char *fnt="", const char *opt="")
+	{	mgl_label_y(gr, &y, text, fnt, opt);	}
+	/// Draw labels for points coordinate(s) at points {x,y,z}
+	/** String \a fnt may contain:
+	 *	 ‘f’ for fixed format of printed numbers;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’;
+	 *	 ‘F’ for printing in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive numbers;
+	 *	 ‘-’ for printing usual ‘-’;
+	 *	 ‘0123456789’ for precision at printing numbers.*/
+	inline void Label(const mglData &x, const mglData &y, const mglData &z, const wchar_t *text, const char *fnt="", const char *opt="")
+	{	mgl_labelw_xyz(gr, &x, &y, &z, text, fnt, opt);	}
+	/// Draw labels for points coordinate(s) at points {x,y}
+	/** String \a fnt may contain:
+	 *	 ‘f’ for fixed format of printed numbers;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’;
+	 *	 ‘F’ for printing in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive numbers;
+	 *	 ‘-’ for printing usual ‘-’;
+	 *	 ‘0123456789’ for precision at printing numbers.*/
+	inline void Label(const mglData &x, const mglData &y, const wchar_t *text, const char *fnt="", const char *opt="")
+	{	mgl_labelw_xy(gr, &x, &y, text, fnt, opt);	}
+	/// Draw labels for points coordinate(s) at points {x,y} with x in x-axis range
+	/** String \a fnt may contain:
+	 *	 ‘f’ for fixed format of printed numbers;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’;
+	 *	 ‘F’ for printing in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive numbers;
+	 *	 ‘-’ for printing usual ‘-’;
+	 *	 ‘0123456789’ for precision at printing numbers.*/
+	inline void Label(const mglData &y, const wchar_t *text, const char *fnt="", const char *opt="")
+	{	mgl_labelw_y(gr, &y, text, fnt, opt);	}
+
+	/// Draw table for values val along given direction with row labels text
+	/** String \a fnt may contain:
+	 *	 ‘#’ for drawing cell borders;
+	 *	 ‘|’ for limiting table widh by subplot one (equal to option ‘value 1’);
+	 *	 ‘=’ for equal width of all cells;
+	 *	 ‘f’ for fixed format of printed numbers;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’;
+	 *	 ‘F’ for printing in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive numbers;
+	 *	 ‘-’ for printing usual ‘-’;
+	 *	 ‘0123456789’ for precision at printing numbers.
+	 * Option value set the width of the table (default is 1).*/
+	inline void Table(const mglData &val, const char *text, const char *fnt="#|", const char *opt="")
+	{	mgl_table(gr, 0, 0, &val, text, fnt, opt);	}
+	/// Draw table for values val along given direction with row labels text
+	/** String \a fnt may contain:
+	 *	 ‘#’ for drawing cell borders;
+	 *	 ‘|’ for limiting table widh by subplot one (equal to option ‘value 1’);
+	 *	 ‘=’ for equal width of all cells;
+	 *	 ‘f’ for fixed format of printed numbers;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’;
+	 *	 ‘F’ for printing in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive numbers;
+	 *	 ‘-’ for printing usual ‘-’;
+	 *	 ‘0123456789’ for precision at printing numbers.
+	 * Option value set the width of the table (default is 1).*/
+	inline void Table(const mglData &val, const wchar_t *text, const char *fnt="#|", const char *opt="")
+	{	mgl_tablew(gr, 0, 0, &val, text, fnt, opt);	}
+	/// Draw table for values val along given direction with row labels text at given position
+	/** String \a fnt may contain:
+	 *	 ‘#’ for drawing cell borders;
+	 *	 ‘|’ for limiting table widh by subplot one (equal to option ‘value 1’);
+	 *	 ‘=’ for equal width of all cells;
+	 *	 ‘f’ for fixed format of printed numbers;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’;
+	 *	 ‘F’ for printing in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive numbers;
+	 *	 ‘-’ for printing usual ‘-’;
+	 *	 ‘0123456789’ for precision at printing numbers.
+	 * Option value set the width of the table (default is 1).*/
+	inline void Table(double x, double y, const mglData &val, const char *text, const char *fnt="#|", const char *opt="")
+	{	mgl_table(gr, x, y, &val, text, fnt, opt);	}
+	/// Draw table for values val along given direction with row labels text at given position
+	/** String \a fnt may contain:
+	 *	 ‘#’ for drawing cell borders;
+	 *	 ‘|’ for limiting table widh by subplot one (equal to option ‘value 1’);
+	 *	 ‘=’ for equal width of all cells;
+	 *	 ‘f’ for fixed format of printed numbers;
+	 *	 ‘E’ for using ‘E’ instead of ‘e’;
+	 *	 ‘F’ for printing in LaTeX format;
+	 *	 ‘+’ for printing ‘+’ for positive numbers;
+	 *	 ‘-’ for printing usual ‘-’;
+	 *	 ‘0123456789’ for precision at printing numbers.
+	 * Option value set the width of the table (default is 1).*/
+	inline void Table(double x, double y, const mglData &val, const wchar_t *text, const char *fnt="#|", const char *opt="")
+	{	mgl_tablew(gr, x, y, &val, text, fnt, opt);	}
+
+	/// Draw tube with radius r around curve {x,y,z}
+	inline void Tube(const mglData &x, const mglData &y, const mglData &z, const mglData &r, const char *pen="", const char *opt="")
+	{	mgl_tube_xyzr(gr, &x, &y, &z, &r, pen, opt);	}
+	/// Draw tube with radius r around curve {x,y,z}
+	inline void Tube(const mglData &x, const mglData &y, const mglData &z, double r, const char *pen="", const char *opt="")
+	{	mgl_tube_xyz(gr, &x, &y, &z, r, pen, opt);	}
+	/// Draw tube with radius r around curve {x,y}
+	inline void Tube(const mglData &x, const mglData &y, const mglData &r, const char *pen="", const char *opt="")
+	{	mgl_tube_xyr(gr, &x, &y, &r, pen, opt);	}
+	/// Draw tube with radius r around curve {x,y}
+	inline void Tube(const mglData &x, const mglData &y, double r, const char *pen="", const char *opt="")
+	{	mgl_tube_xy(gr, &x, &y, r, pen, opt);	}
+	/// Draw tube with radius r around curve {x,y} with x in x-axis range
+	inline void Tube(const mglData &y, const mglData &r, const char *pen="", const char *opt="")
+	{	mgl_tube_r(gr, &y, &r, pen, opt);	}
+	/// Draw tube with radius r around curve {x,y} with x in x-axis range
+	inline void Tube(const mglData &y, double r, const char *pen="", const char *opt="")
+	{	mgl_tube(gr, &y, r, pen, opt);	}
+	/// Draw surface of curve {r,z} rotation around axis
+	/** Style ‘#’ produce wire plot. Style ‘.’ produce plot by dots.*/
+	inline void Torus(const mglData &r, const mglData &z, const char *pen="", const char *opt="")
+	{	mgl_torus(gr, &r, &z, pen,opt);	}
+
+	/// Draw mesh lines for 2d data specified parametrically
+	inline void Mesh(const mglData &x, const mglData &y, const mglData &z, const char *stl="", const char *opt="")
+	{	mgl_mesh_xy(gr, &x, &y, &z, stl, opt);	}
+	/// Draw mesh lines for 2d data
+	inline void Mesh(const mglData &z, const char *stl="", const char *opt="")
+	{	mgl_mesh(gr, &z, stl, opt);	}
+
+	/// Draw waterfall plot for 2d data specified parametrically
+	/** Style 'x' draw lines in x-direction. */
+	inline void Fall(const mglData &x, const mglData &y, const mglData &z, const char *stl="", const char *opt="")
+	{	mgl_fall_xy(gr, &x, &y, &z, stl, opt);	}
+	/// Draw waterfall plot for 2d data
+	/** Style 'x' draw lines in x-direction. */
+	inline void Fall(const mglData &z, const char *stl="", const char *opt="")
+	{	mgl_fall(gr, &z, stl, opt);	}
+
+	/// Draw belts for 2d data specified parametrically
+	/** Style 'x' draw belts in x-direction. */
+	inline void Belt(const mglData &x, const mglData &y, const mglData &z, const char *stl="", const char *opt="")
+	{	mgl_belt_xy(gr, &x, &y, &z, stl, opt);	}
+	/// Draw belts for 2d data
+	/** Style 'x' draw belts in x-direction. */
+	inline void Belt(const mglData &z, const char *stl="", const char *opt="")
+	{	mgl_belt(gr, &z, stl, opt);	}
+
+	/// Draw surface for 2d data specified parametrically with color proportional to z
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void Surf(const mglData &x, const mglData &y, const mglData &z, const char *stl="", const char *opt="")
+	{	mgl_surf_xy(gr, &x, &y, &z, stl, opt);	}
+	/// Draw surface for 2d data with color proportional to z
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void Surf(const mglData &z, const char *stl="", const char *opt="")
+	{	mgl_surf(gr, &z, stl, opt);	}
+
+	/// Draw grid lines for density plot of 2d data specified parametrically
+	inline void Grid(const mglData &x, const mglData &y, const mglData &z, const char *stl="", const char *opt="")
+	{	mgl_grid_xy(gr, &x, &y, &z, stl, opt);	}
+	/// Draw grid lines for density plot of 2d data
+	inline void Grid(const mglData &z, const char *stl="", const char *opt="")
+	{	mgl_grid(gr, &z, stl, opt);	}
+
+	/// Draw vertical tiles with manual colors c for 2d data specified parametrically
+	inline void Tile(const mglData &x, const mglData &y, const mglData &z, const mglData &c, const char *stl="", const char *opt="")
+	{	mgl_tile_xyc(gr, &x, &y, &z, &c, stl, opt);	}
+	/// Draw vertical tiles for 2d data specified parametrically
+	inline void Tile(const mglData &x, const mglData &y, const mglData &z, const char *stl="", const char *opt="")
+	{	mgl_tile_xy(gr, &x, &y, &z, stl, opt);	}
+	/// Draw vertical tiles for 2d data
+	inline void Tile(const mglData &z, const char *stl="", const char *opt="")
+	{	mgl_tile(gr, &z, stl, opt);	}
+
+	/// Draw density plot for 2d data specified parametrically
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void Dens(const mglData &x, const mglData &y, const mglData &c, const char *stl="", const char *opt="")
+	{	mgl_dens_xy(gr, &x, &y, &c, stl, opt);	}
+	/// Draw density plot for 2d data
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void Dens(const mglData &c, const char *stl="", const char *opt="")
+	{	mgl_dens(gr, &c, stl, opt);	}
+
+	/// Draw vertical boxes for 2d data specified parametrically
+	/** Style ‘#’ draw filled boxes. */
+	inline void Boxs(const mglData &x, const mglData &y, const mglData &z, const char *stl="", const char *opt="")
+	{	mgl_boxs_xy(gr, &x, &y, &z, stl, opt);	}
+	/// Draw vertical boxes for 2d data
+	/** Style ‘#’ draw filled boxes. */
+	inline void Boxs(const mglData &z, const char *stl="", const char *opt="")
+	{	mgl_boxs(gr, &z, stl, opt);	}
+
+	/// Draw contour lines at manual levels for 2d data specified parametrically
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Style 't'/'T' draw contour labels below/above contours.*/
+	inline void Cont(const mglData &v, const mglData &x, const mglData &y, const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_cont_xy_val(gr, &v, &x, &y, &z, sch, opt);	}
+	/// Draw contour lines for 2d data
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Style 't'/'T' draw contour labels below/above contours.*/
+	inline void Cont(const mglData &v, const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_cont_val(gr, &v, &z, sch, opt);	}
+	/// Draw contour lines at manual levels for 2d data specified parametrically
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void Cont(const mglData &x, const mglData &y, const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_cont_xy(gr, &x, &y, &z, sch, opt);	}
+	/// Draw contour lines for 2d data
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void Cont(const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_cont(gr, &z, sch, opt);	}
+
+	/// Draw solid contours at manual levels for 2d data specified parametrically
+	/** Style ‘_’ to draw contours at bottom of axis box. */
+	inline void ContF(const mglData &v, const mglData &x, const mglData &y, const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_contf_xy_val(gr, &v, &x, &y, &z, sch, opt);	}
+	/// Draw solid contours at manual levels for 2d data
+	/** Style ‘_’ to draw contours at bottom of axis box. */
+	inline void ContF(const mglData &v, const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_contf_val(gr, &v, &z, sch, opt);	}
+	/// Draw solid contours for 2d data specified parametrically
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void ContF(const mglData &x, const mglData &y, const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_contf_xy(gr, &x, &y, &z, sch, opt);	}
+	/// Draw solid contours for 2d data
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void ContF(const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_contf(gr, &z, sch, opt);	}
+
+	/// Draw solid contours at manual levels for 2d data specified parametrically with specified colors
+	/** Style ‘_’ to draw contours at bottom of axis box. */
+	inline void ContD(const mglData &v, const mglData &x, const mglData &y, const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_contd_xy_val(gr, &v, &x, &y, &z, sch, opt);	}
+	/// Draw solid contours at manual levels for 2d data with specified colors
+	/** Style ‘_’ to draw contours at bottom of axis box. */
+	inline void ContD(const mglData &v, const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_contd_val(gr, &v, &z, sch, opt);	}
+	/// Draw solid contours for 2d data specified parametrically with specified colors
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void ContD(const mglData &x, const mglData &y, const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_contd_xy(gr, &x, &y, &z, sch, opt);	}
+	/// Draw solid contours for 2d data with specified colors
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void ContD(const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_contd(gr, &z, sch, opt);	}
+
+	/// Draw contour tubes between manual levels for 2d data specified parametrically
+	/** Style ‘_’ to draw contours at bottom of axis box. */
+	inline void ContV(const mglData &v, const mglData &x, const mglData &y, const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_contv_xy_val(gr, &v, &x, &y, &z, sch, opt);	}
+	/// Draw contour tubes between manual levels for 2d data
+	/** Style ‘_’ to draw contours at bottom of axis box. */
+	inline void ContV(const mglData &v, const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_contv_val(gr, &v, &z, sch, opt);	}
+	/// Draw contour tubes for 2d data specified parametrically
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void ContV(const mglData &x, const mglData &y, const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_contv_xy(gr, &x, &y, &z, sch, opt);	}
+	/// Draw contour tubes for 2d data
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void ContV(const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_contv(gr, &z, sch, opt);	}
+
+	/// Draw axial-symmetric isosurfaces at manual levels for 2d data specified parametrically
+	/** String \a sch may contain:
+	 * ‘#’ for wired plot;
+	 * ‘.’ for plot by dots;
+	 * ‘x’, ‘z’ for rotation around x-, z-axis correspondingly (default is y-axis). */
+	inline void Axial(const mglData &v, const mglData &x, const mglData &y, const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_axial_xy_val(gr, &v, &x, &y, &z, sch,opt);	}
+	/// Draw axial-symmetric isosurfaces at manual levels for 2d data
+	/** String \a sch may contain:
+	 * ‘#’ for wired plot;
+	 * ‘.’ for plot by dots;
+	 * ‘x’, ‘z’ for rotation around x-, z-axis correspondingly (default is y-axis). */
+	inline void Axial(const mglData &v, const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_axial_val(gr, &v, &z, sch, opt);	}
+	/// Draw axial-symmetric isosurfaces for 2d data specified parametrically
+	/** String \a sch may contain:
+	 * ‘#’ for wired plot;
+	 * ‘.’ for plot by dots;
+	 * ‘x’, ‘z’ for rotation around x-, z-axis correspondingly (default is y-axis).
+	 * Option "value" set the number of isosurfaces (default is 3). */
+	inline void Axial(const mglData &x, const mglData &y, const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_axial_xy(gr, &x, &y, &z, sch, opt);	}
+	/// Draw axial-symmetric isosurfaces for 2d data
+	/** String \a sch may contain:
+	 * ‘#’ for wired plot;
+	 * ‘.’ for plot by dots;
+	 * ‘x’, ‘z’ for rotation around x-, z-axis correspondingly (default is y-axis).
+	 * Option "value" set the number of isosurfaces (default is 3). */
+	inline void Axial(const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_axial(gr, &z, sch, opt);	}
+
+	/// Draw grid lines for density plot at slice for 3d data specified parametrically
+	/** Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.*/
+	inline void Grid3(const mglData &x, const mglData &y, const mglData &z, const mglData &a, const char *stl="", double sVal=-1, const char *opt="")
+	{	mgl_grid3_xyz(gr, &x, &y, &z, &a, stl, sVal, opt);	}
+	/// Draw grid lines for density plot at slice for 3d data
+	/** Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.*/
+	inline void Grid3(const mglData &a, const char *stl="", double sVal=-1, const char *opt="")
+	{	mgl_grid3(gr, &a, stl, sVal, opt);	}
+
+	/// Draw density plot at slice for 3d data specified parametrically
+	/** Style ‘#’ draw grid lines. Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.*/
+	inline void Dens3(const mglData &x, const mglData &y, const mglData &z, const mglData &a, const char *stl="", double sVal=-1, const char *opt="")
+	{	mgl_dens3_xyz(gr, &x, &y, &z, &a, stl, sVal, opt);	}
+	/// Draw density plot at slice for 3d data
+	/** Style ‘#’ draw grid lines. Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.*/
+	inline void Dens3(const mglData &a, const char *stl="", double sVal=-1, const char *opt="")
+	{	mgl_dens3(gr, &a, stl, sVal, opt);	}
+
+	/// Draw isosurface for 3d data specified parametrically
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.*/
+	inline void Surf3(double Val, const mglData &x, const mglData &y, const mglData &z, const mglData &a, const char *stl="", const char *opt="")
+	{	mgl_surf3_xyz_val(gr, Val, &x, &y, &z, &a, stl, opt);	}
+	/// Draw isosurface for 3d data
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.*/
+	inline void Surf3(double Val, const mglData &a, const char *stl="", const char *opt="")
+	{	mgl_surf3_val(gr, Val, &a, stl, opt);	}
+	/// Draw isosurfaces for 3d data specified parametrically
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+	 * Option "value" set the number of isosurfaces (default is 3). */
+	inline void Surf3(const mglData &x, const mglData &y, const mglData &z, const mglData &a, const char *stl="", const char *opt="")
+	{	mgl_surf3_xyz(gr, &x, &y, &z, &a, stl, opt);	}
+	/// Draw isosurfaces for 3d data
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+	 * Option "value" set the number of isosurfaces (default is 3). */
+	inline void Surf3(const mglData &a, const char *stl="", const char *opt="")
+	{	mgl_surf3(gr, &a, stl, opt);	}
+
+	/// Draw a semi-transparent cloud for 3d data specified parametrically
+	/** Style ‘.’ produce plot by dots. Style ‘i’ use inverted values for transparency. */
+	inline void Cloud(const mglData &x, const mglData &y, const mglData &z, const mglData &a, const char *stl="", const char *opt="")
+	{	mgl_cloud_xyz(gr, &x, &y, &z, &a, stl, opt);	}
+	/// Draw a semi-transparent cloud for 3d data
+	/** Style ‘.’ produce plot by dots. Style ‘i’ use inverted values for transparency. */
+	inline void Cloud(const mglData &a, const char *stl="", const char *opt="")
+	{	mgl_cloud(gr, &a, stl, opt);	}
+
+	/// Draw contour lines at manual levels along slice for 3d data specified parametrically
+	/** Style ‘#’ draw grid lines.
+	 * Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours. */
+	inline void Cont3(const mglData &v, const mglData &x, const mglData &y, const mglData &z, const mglData &a, const char *sch="", double sVal=-1, const char *opt="")
+	{	mgl_cont3_xyz_val(gr, &v, &x, &y, &z, &a, sch, sVal, opt);	}
+	/// Draw contour lines at manual levels along slice for 3d data
+	/** Style ‘#’ draw grid lines.
+	 * Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours. */
+	inline void Cont3(const mglData &v, const mglData &a, const char *sch="", double sVal=-1, const char *opt="")
+	{	mgl_cont3_val(gr, &v, &a, sch, sVal, opt);	}
+	/// Draw contour lines along slice for 3d data specified parametrically
+	/** Style ‘#’ draw grid lines.
+	 * Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void Cont3(const mglData &x, const mglData &y, const mglData &z, const mglData &a, const char *sch="", double sVal=-1, const char *opt="")
+	{	mgl_cont3_xyz(gr, &x, &y, &z, &a, sch, sVal, opt);	}
+	/// Draw contour lines along slice for 3d data
+	/** Style ‘#’ draw grid lines.
+	 * Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void Cont3(const mglData &a, const char *sch="", double sVal=-1, const char *opt="")
+	{	mgl_cont3(gr, &a, sch, sVal, opt);	}
+
+	/// Draw solid contours at manual levels along slice for 3d data specified parametrically
+	/** Style ‘#’ draw grid lines. Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly. */
+	inline void ContF3(const mglData &v, const mglData &x, const mglData &y, const mglData &z, const mglData &a, const char *sch="", double sVal=-1, const char *opt="")
+	{	mgl_contf3_xyz_val(gr, &v, &x, &y, &z, &a, sch, sVal, opt);	}
+	/// Draw solid contours at manual levels along slice for 3d data
+	/** Style ‘#’ draw grid lines. Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly. */
+	inline void ContF3(const mglData &v, const mglData &a, const char *sch="", double sVal=-1, const char *opt="")
+	{	mgl_contf3_val(gr, &v, &a, sch, sVal, opt);	}
+	/// Draw solid contours along slice for 3d data specified parametrically
+	/** Style ‘#’ draw grid lines. Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.
+	 *  Option "value" set the number of contour levels (default is 7).*/
+	inline void ContF3(const mglData &x, const mglData &y, const mglData &z, const mglData &a, const char *sch="", double sVal=-1, const char *opt="")
+	{	mgl_contf3_xyz(gr, &x, &y, &z, &a, sch, sVal, opt);	}
+	/// Draw solid contours along slice for 3d data
+	/** Style ‘#’ draw grid lines. Style ‘x’ or ‘z’ produce plot perpendicular to x- or z-direction correspondingly.
+	 *  Option "value" set the number of contour levels (default is 7).*/
+	inline void ContF3(const mglData &a, const char *sch="", double sVal=-1, const char *opt="")
+	{	mgl_contf3(gr, &a, sch, sVal, opt);	}
+
+	/// Draw several isosurfaces for 3d beam in curvilinear coordinates
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.
+	 *  Variable \a flag is bitwise:
+	 * ‘0x1’ - draw in accompanied (not laboratory) coordinates;
+	 * ‘0x2’ - draw projection to \rho-z plane;
+	 * ‘0x4’ - draw normalized in each slice field.*/
+	inline void Beam(const mglData &tr, const mglData &g1, const mglData &g2, const mglData &a, double r, const char *stl=0, int flag=0, int num=3)
+	{	mgl_beam(gr, &tr,&g1,&g2,&a,r,stl,flag,num);	}
+	/// Draw isosurface at value \a val for 3d beam in curvilinear coordinates
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.
+	 *  Variable \a flag is bitwise:
+	 * ‘0x1’ - draw in accompanied (not laboratory) coordinates;
+	 * ‘0x2’ - draw projection to \rho-z plane;
+	 * ‘0x4’ - draw normalized in each slice field.*/
+	inline void Beam(double val, const mglData &tr, const mglData &g1, const mglData &g2, const mglData &a, double r, const char *stl=NULL, int flag=0)
+	{	mgl_beam_val(gr,val,&tr,&g1,&g2,&a,r,stl,flag);	}
+
+	/// Draw vertical tiles with variable size r and manual colors c for 2d data specified parametrically
+	inline void TileS(const mglData &x, const mglData &y, const mglData &z, const mglData &r, const mglData &c, const char *stl="", const char *opt="")
+	{	mgl_tiles_xyc(gr, &x, &y, &z, &r, &c, stl, opt);	}
+	/// Draw vertical tiles with variable size r for 2d data specified parametrically
+	inline void TileS(const mglData &x, const mglData &y, const mglData &z, const mglData &r, const char *stl="", const char *opt="")
+	{	mgl_tiles_xy(gr, &x, &y, &z, &r, stl, opt);	}
+	/// Draw vertical tiles with variable size r for 2d data
+	inline void TileS(const mglData &z, const mglData &r, const char *stl="", const char *opt="")
+	{	mgl_tiles(gr, &z, &r, stl, opt);	}
+
+	/// Draw surface for 2d data specified parametrically with color proportional to c
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void SurfC(const mglData &x, const mglData &y, const mglData &z, const mglData &c, const char *sch="", const char *opt="")
+	{	mgl_surfc_xy(gr, &x, &y, &z, &c, sch,opt);	}
+	/// Draw surface for 2d data with color proportional to c
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void SurfC(const mglData &z, const mglData &c, const char *sch="", const char *opt="")
+	{	mgl_surfc(gr, &z, &c, sch,opt);	}
+
+	/// Draw surface for 2d data specified parametrically with alpha proportional to c
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void SurfA(const mglData &x, const mglData &y, const mglData &z, const mglData &c, const char *sch="", const char *opt="")
+	{	mgl_surfa_xy(gr, &x, &y, &z, &c, sch,opt);	}
+	/// Draw surface for 2d data with alpha proportional to c
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void SurfA(const mglData &z, const mglData &c, const char *sch="", const char *opt="")
+	{	mgl_surfa(gr, &z, &c, sch,opt);	}
+
+	/// Draw surface for 2d data specified parametrically with color proportional to c and alpha proportional to a
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void SurfCA(const mglData &x, const mglData &y, const mglData &z, const mglData &c, const mglData &a, const char *sch="", const char *opt="")
+	{	mgl_surfca_xy(gr, &x, &y, &z, &c, &a, sch,opt);	}
+	/// Draw surface for 2d data with color proportional to c and alpha proportional to a
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void SurfCA(const mglData &z, const mglData &c, const mglData &a, const char *sch="", const char *opt="")
+	{	mgl_surfca(gr, &z, &c, &a, sch,opt);	}
+
+	/// Color map of matrix a to matrix b, both matrix can parametrically depend on coordinates
+	/** Style ‘.’ produce plot by dots. */
+	inline void Map(const mglData &x, const mglData &y, const mglData &a, const mglData &b, const char *sch="", const char *opt="")
+	{	mgl_map_xy(gr, &x, &y, &a, &b, sch, opt);	}
+	/// Color map of matrix a to matrix b
+	/** Style ‘.’ produce plot by dots. */
+	inline void Map(const mglData &a, const mglData &b, const char *sch="", const char *opt="")
+	{	mgl_map(gr, &a, &b, sch, opt);	}
+
+	/// Draw density plot for spectra-gramm specified parametrically
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void STFA(const mglData &x, const mglData &y, const mglData &re, const mglData &im, int dn, const char *sch="", const char *opt="")
+	{	mgl_stfa_xy(gr, &x, &y, &re, &im, dn, sch, opt);	}
+	/// Draw density plot for spectra-gramm
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void STFA(const mglData &re, const mglData &im, int dn, const char *sch="", const char *opt="")
+	{	mgl_stfa(gr, &re, &im, dn, sch, opt);	}
+
+	/// Draw isosurface for 3d data specified parametrically with alpha proportional to b
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots. */
+	inline void Surf3A(double Val, const mglData &x, const mglData &y, const mglData &z, const mglData &a, const mglData &b, const char *stl="", const char *opt="")
+	{	mgl_surf3a_xyz_val(gr, Val, &x, &y, &z, &a, &b, stl, opt);	}
+	/// Draw isosurface for 3d data with alpha proportional to b
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots. */
+	inline void Surf3A(double Val, const mglData &a, const mglData &b, const char *stl="", const char *opt="")
+	{	mgl_surf3a_val(gr, Val, &a, &b, stl, opt);	}
+	/// Draw isosurfaces for 3d data specified parametrically with alpha proportional to b
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+	 * Option "value" set the number of isosurfaces (default is 3). */
+	inline void Surf3A(const mglData &x, const mglData &y, const mglData &z, const mglData &a, const mglData &b, const char *stl="", const char *opt="")
+	{	mgl_surf3a_xyz(gr, &x, &y, &z, &a, &b, stl, opt);	}
+	/// Draw isosurfaces for 3d data with alpha proportional to b
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+	 * Option "value" set the number of isosurfaces (default is 3). */
+	inline void Surf3A(const mglData &a, const mglData &b, const char *stl="", const char *opt="")
+	{	mgl_surf3a(gr, &a, &b, stl, opt);	}
+
+	/// Draw isosurface for 3d data specified parametrically with color proportional to c
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots. */
+	inline void Surf3C(double Val, const mglData &x, const mglData &y, const mglData &z, const mglData &a, const mglData &c, const char *stl="", const char *opt="")
+	{	mgl_surf3c_xyz_val(gr, Val, &x, &y, &z, &a, &c, stl,opt);	}
+	/// Draw isosurface for 3d data with color proportional to c
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots. */
+	inline void Surf3C(double Val, const mglData &a, const mglData &c, const char *stl="", const char *opt="")
+	{	mgl_surf3c_val(gr, Val, &a, &c, stl, opt);	}
+	/// Draw isosurfaces for 3d data specified parametrically with color proportional to c
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+	 * Option "value" set the number of isosurfaces (default is 3). */
+	inline void Surf3C(const mglData &x, const mglData &y, const mglData &z, const mglData &a, const mglData &c, const char *stl="", const char *opt="")
+	{	mgl_surf3c_xyz(gr, &x, &y, &z, &a, &c, stl, opt);	}
+	/// Draw isosurfaces for 3d data specified parametrically with color proportional to c
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+	 * Option "value" set the number of isosurfaces (default is 3). */
+	inline void Surf3C(const mglData &a, const mglData &c, const char *stl="", const char *opt="")
+	{	mgl_surf3c(gr, &a, &c, stl, opt);	}
+
+	/// Draw isosurface for 3d data specified parametrically with color proportional to c and alpha proportional to b
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots. */
+	inline void Surf3CA(double Val, const mglData &x, const mglData &y, const mglData &z, const mglData &a, const mglData &c, const mglData &b, const char *stl="", const char *opt="")
+	{	mgl_surf3ca_xyz_val(gr, Val, &x, &y, &z, &a, &c, &b, stl,opt);	}
+	/// Draw isosurface for 3d data with color proportional to c and alpha proportional to b
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots. */
+	inline void Surf3CA(double Val, const mglData &a, const mglData &c, const mglData &b, const char *stl="", const char *opt="")
+	{	mgl_surf3ca_val(gr, Val, &a, &c, &b, stl, opt);	}
+	/// Draw isosurfaces for 3d data specified parametrically with color proportional to c and alpha proportional to b
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+	 * Option "value" set the number of isosurfaces (default is 3). */
+	inline void Surf3CA(const mglData &x, const mglData &y, const mglData &z, const mglData &a, const mglData &c, const mglData &b, const char *stl="", const char *opt="")
+	{	mgl_surf3ca_xyz(gr, &x, &y, &z, &a, &c, &b, stl, opt);	}
+	/// Draw isosurfaces for 3d data with color proportional to c and alpha proportional to b
+	/** Style ‘#’ draw wired plot. Style ‘.’ produce plot by dots.
+	 * Option "value" set the number of isosurfaces (default is 3). */
+	inline void Surf3CA(const mglData &a, const mglData &c, const mglData &b, const char *stl="", const char *opt="")
+	{	mgl_surf3ca(gr, &a, &c, &b, stl, opt);	}
+
+	/// Plot dew drops for vector field {ax,ay} parametrically depended on coordinate {x,y}
+	inline void Dew(const mglData &x, const mglData &y, const mglData &ax, const mglData &ay, const char *sch="", const char *opt="")
+	{	mgl_dew_xy(gr, &x, &y, &ax, &ay, sch, opt);	}
+	/// Plot dew drops for vector field {ax,ay}
+	inline void Dew(const mglData &ax, const mglData &ay, const char *sch="", const char *opt="")
+	{	mgl_dew_2d(gr, &ax, &ay, sch, opt);	}
+
+	/// Plot vectors at position {x,y} along {ax,ay} with length/color proportional to |a|
+	/** Option value set the vector length factor (if non-zero) or vector length to be proportional the distance between curve points (if value=0). */
+	inline void Traj(const mglData &x, const mglData &y, const mglData &ax, const mglData &ay, const char *sch="", const char *opt="")
+	{	mgl_traj_xy(gr, &x, &y, &ax, &ay, sch, opt);	}
+	/// Plot vectors at position {x,y,z} along {ax,ay,az} with length/color proportional to |a|
+	/** Option value set the vector length factor (if non-zero) or vector length to be proportional the distance between curve points (if value=0). */
+	inline void Traj(const mglData &x, const mglData &y, const mglData &z, const mglData &ax, const mglData &ay, const mglData &az, const char *sch="", const char *opt="")
+	{	mgl_traj_xyz(gr, &x, &y, &z, &ax, &ay, &az, sch, opt);	}
+
+	/// Plot vector field {ax,ay} parametrically depended on coordinate {x,y} with length/color proportional to |a|
+	/** String \a sch may contain:
+	 * ‘f’ for drawing arrows with fixed lengths,
+	 * ‘ >’, ‘<’ for drawing arrows to or from the ce*ll point (default is centering),
+	 * ‘.’ for drawing hachures with dots instead of arrows,
+	 * ‘=’ for enabling color gradient along arrows. */
+	inline void Vect(const mglData &x, const mglData &y, const mglData &ax, const mglData &ay, const char *sch="", const char *opt="")
+	{	mgl_vect_xy(gr, &x, &y, &ax, &ay, sch, opt);	}
+	/// Plot vector field {ax,ay} with length/color proportional to |a|
+	/** String \a sch may contain:
+	 * ‘f’ for drawing arrows with fixed lengths,
+	 * ‘ >’, ‘<’ for drawing arrows to or from the ce*ll point (default is centering),
+	 * ‘.’ for drawing hachures with dots instead of arrows,
+	 * ‘=’ for enabling color gradient along arrows. */
+	inline void Vect(const mglData &ax, const mglData &ay, const char *sch="", const char *opt="")
+	{	mgl_vect_2d(gr, &ax, &ay, sch, opt);	}
+	/// Plot vector field {ax,ay,az} parametrically depended on coordinate {x,y,z} with length/color proportional to |a|
+	/** String \a sch may contain:
+	 * ‘f’ for drawing arrows with fixed lengths,
+	 * ‘ >’, ‘<’ for drawing arrows to or from the ce*ll point (default is centering),
+	 * ‘.’ for drawing hachures with dots instead of arrows,
+	 * ‘=’ for enabling color gradient along arrows. */
+	inline void Vect(const mglData &x, const mglData &y, const mglData &z, const mglData &ax, const mglData &ay, const mglData &az, const char *sch="", const char *opt="")
+	{	mgl_vect_xyz(gr, &x, &y, &z, &ax, &ay, &az, sch, opt);	}
+	/// Plot vector field {ax,ay,az} with length/color proportional to |a|
+	/** String \a sch may contain:
+	 * ‘f’ for drawing arrows with fixed lengths,
+	 * ‘ >’, ‘<’ for drawing arrows to or from the ce*ll point (default is centering),
+	 * ‘.’ for drawing hachures with dots instead of arrows,
+	 * ‘=’ for enabling color gradient along arrows. */
+	inline void Vect(const mglData &ax, const mglData &ay, const mglData &az, const char *sch="", const char *opt="")
+	{	mgl_vect_3d(gr, &ax, &ay, &az, sch, opt);	}
+
+	/// Draw vector plot along slice for 3d data specified parametrically
+	/** String \a sch may contain:
+	 * ‘f’ for drawing arrows with fixed lengths,
+	 * ‘ >’, ‘<’ for drawing arrows to or from the ce*ll point (default is centering),
+	 * ‘.’ for drawing hachures with dots instead of arrows,
+	 * ‘=’ for enabling color gradient along arrows,
+	 * ‘ x’, ‘z’ for producing plot perpendicular to x- or z-direction correspondingly. */
+	inline void Vect3(const mglData &x, const mglData &y, const mglData &z, const mglData &ax, const mglData &ay, const mglData &az, const char *stl="", double sVal=-1, const char *opt="")
+	{	mgl_vect3_xyz(gr, &x, &y, &z, &ax,&ay,&az, stl, sVal, opt);	}
+	/// Draw vector plot along slice for 3d data
+	/** String \a sch may contain:
+	 * ‘f’ for drawing arrows with fixed lengths,
+	 * ‘ >’, ‘<’ for drawing arrows to or from the ce*ll point (default is centering),
+	 * ‘.’ for drawing hachures with dots instead of arrows,
+	 * ‘=’ for enabling color gradient along arrows,
+	 * ‘ x’, ‘z’ for producing plot perpendicular to x- or z-direction correspondingly. */
+	inline void Vect3(const mglData &ax, const mglData &ay, const mglData &az, const char *stl="", double sVal=-1, const char *opt="")
+	{	mgl_vect3(gr, &ax,&ay,&az, stl, sVal, opt);	}
+
+	/// Plot flows for vector field {ax,ay} parametrically depended on coordinate {x,y} with color proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+	 * Option "value" sets the number of threads (default is 5). */
+	inline void Flow(const mglData &x, const mglData &y, const mglData &ax, const mglData &ay, const char *sch="", const char *opt="")
+	{	mgl_flow_xy(gr, &x, &y, &ax, &ay, sch, opt);	}
+	/// Plot flows for vector field {ax,ay} with color proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+	 * Option "value" sets the number of threads (default is 5). */
+	inline void Flow(const mglData &ax, const mglData &ay, const char *sch="", const char *opt="")
+	{	mgl_flow_2d(gr, &ax, &ay, sch, opt);	}
+	/// Plot flows for vector field {ax,ay,az} parametrically depended on coordinate {x,y,z} with color proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+	 * Option "value" sets the number of threads (default is 5). */
+	inline void Flow(const mglData &x, const mglData &y, const mglData &z, const mglData &ax, const mglData &ay, const mglData &az, const char *sch="", const char *opt="")
+	{	mgl_flow_xyz(gr, &x, &y, &z, &ax, &ay, &az, sch, opt);	}
+	/// Plot flows for vector field {ax,ay,az} with color proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+	 * Option "value" sets the number of threads (default is 5). */
+	inline void Flow(const mglData &ax, const mglData &ay, const mglData &az, const char *sch="", const char *opt="")
+	{	mgl_flow_3d(gr, &ax, &ay, &az, sch, opt);	}
+
+	/// Plot flow from point p for vector field {ax,ay} parametrically depended on coordinate {x,y} with color proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads. */
+	inline void FlowP(mglPoint p, const mglData &x, const mglData &y, const mglData &ax, const mglData &ay, const char *sch="", const char *opt="")
+	{	mgl_flowp_xy(gr, p.x, p.y, p.z, &x, &y, &ax, &ay, sch, opt);	}
+	/// Plot flow from point p for vector field {ax,ay} with color proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads. */
+	inline void FlowP(mglPoint p, const mglData &ax, const mglData &ay, const char *sch="", const char *opt="")
+	{	mgl_flowp_2d(gr, p.x, p.y, p.z, &ax, &ay, sch, opt);	}
+	/// Plot flow from point p for vector field {ax,ay,az} parametrically depended on coordinate {x,y,z} with color proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly. */
+	inline void FlowP(mglPoint p, const mglData &x, const mglData &y, const mglData &z, const mglData &ax, const mglData &ay, const mglData &az, const char *sch="", const char *opt="")
+	{	mgl_flowp_xyz(gr, p.x, p.y, p.z, &x, &y, &z, &ax, &ay, &az, sch, opt);	}
+	/// Plot flow from point p for vector field {ax,ay,az} with color proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly. */
+	inline void FlowP(mglPoint p, const mglData &ax, const mglData &ay, const mglData &az, const char *sch="", const char *opt="")
+	{	mgl_flowp_3d(gr, p.x, p.y, p.z, &ax, &ay, &az, sch, opt);	}
+
+	/// Plot flows for gradient of scalar field phi parametrically depended on coordinate {x,y,z}
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+	 * Option "value" sets the number of threads (default is 5). */
+	inline void Grad(const mglData &x, const mglData &y, const mglData &z, const mglData &phi, const char *sch="", const char *opt="")
+	{	mgl_grad_xyz(gr,&x,&y,&z,&phi,sch,opt);	}
+	/// Plot flows for gradient of scalar field phi parametrically depended on coordinate {x,y}
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+	 * Option "value" sets the number of threads (default is 5). */
+	inline void Grad(const mglData &x, const mglData &y, const mglData &phi, const char *sch="", const char *opt="")
+	{	mgl_grad_xy(gr,&x,&y,&phi,sch,opt);	}
+	/// Plot flows for gradient of scalar field phi
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘v’ for drawing arrows on the threads;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+	 * Option "value" sets the number of threads (default is 5). */
+	inline void Grad(const mglData &phi, const char *sch="", const char *opt="")
+	{	mgl_grad(gr,&phi,sch,opt);	}
+
+	/// Plot flow pipes for vector field {ax,ay} parametrically depended on coordinate {x,y} with color and radius proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘i’ for pipe radius to be inverse proportional to amplitude.
+	 * Option "value" sets the number of threads (default is 5). */
+	inline void Pipe(const mglData &x, const mglData &y, const mglData &ax, const mglData &ay, const char *sch="", double r0=0.05, const char *opt="")
+	{	mgl_pipe_xy(gr, &x, &y, &ax, &ay, sch, r0, opt);	}
+	/// Plot flow pipes for vector field {ax,ay} with color and radius proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘i’ for pipe radius to be inverse proportional to amplitude.
+	 * Option "value" sets the number of threads (default is 5). */
+	inline void Pipe(const mglData &ax, const mglData &ay, const char *sch="", double r0=0.05, const char *opt="")
+	{	mgl_pipe_2d(gr, &ax, &ay, sch, r0, opt);	}
+	/// Plot flow pipes for vector field {ax,ay,az} parametrically depended on coordinate {x,y,z} with color and radius proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘i’ for pipe radius to be inverse proportional to amplitude;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+	 * Option "value" sets the number of threads (default is 5). */
+	inline void Pipe(const mglData &x, const mglData &y, const mglData &z, const mglData &ax, const mglData &ay, const mglData &az, const char *sch="", double r0=0.05, const char *opt="")
+	{	mgl_pipe_xyz(gr, &x, &y, &z, &ax, &ay, &az, sch, r0, opt);	}
+	/// Plot flow pipes for vector field {ax,ay,az} with color and radius proportional to |a|
+	/** String \a sch may contain:
+	 * color scheme: up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+	 * ‘#’ for starting threads from edges only;
+	 * ‘i’ for pipe radius to be inverse proportional to amplitude;
+	 * ‘x’, ‘z’ for drawing tapes of normals in x-y and y-z planes correspondingly.
+	 * Option "value" sets the number of threads (default is 5). */
+	inline void Pipe(const mglData &ax, const mglData &ay, const mglData &az, const char *sch="", double r0=0.05, const char *opt="")
+	{	mgl_pipe_3d(gr, &ax, &ay, &az, sch, r0, opt);	}
+
+	/// Draw density plot for data at x = sVal
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void DensX(const mglData &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_dens_x(gr, &a, stl, sVal, opt);	}
+	/// Draw density plot for data at y = sVal
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void DensY(const mglData &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_dens_y(gr, &a, stl, sVal, opt);	}
+	/// Draw density plot for data at z = sVal
+	/** Style ‘#’ draw grid lines. Style ‘.’ produce plot by dots.*/
+	inline void DensZ(const mglData &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_dens_z(gr, &a, stl, sVal, opt);	}
+
+	/// Draw contour lines for data at x = sVal
+	/** Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void ContX(const mglData &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_cont_x(gr, &a, stl, sVal, opt);	}
+	/// Draw contour lines at manual levels for data at x = sVal
+	/** Style ‘t’/‘T’ draw contour labels below/above contours. */
+	inline void ContX(const mglData &v, const mglData &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_cont_x_val(gr, &v, &a, stl, sVal, opt);	}
+	/// Draw contour lines for data at y = sVal
+	/** Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void ContY(const mglData &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_cont_y(gr, &a, stl, sVal, opt);	}
+	/// Draw contour lines at manual levels for data at y = sVal
+	/** Style ‘t’/‘T’ draw contour labels below/above contours. */
+	inline void ContY(const mglData &v, const mglData &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_cont_y_val(gr, &v, &a, stl, sVal, opt);	}
+	/// Draw contour lines for data at z = sVal
+	/** Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void ContZ(const mglData &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_cont_z(gr, &a, stl, sVal, opt);	}
+	/// Draw contour lines at manual levels for data at z = sVal
+	/** Style ‘t’/‘T’ draw contour labels below/above contours. */
+	inline void ContZ(const mglData &v, const mglData &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_cont_z_val(gr, &v, &a, stl, sVal, opt);	}
+
+	/// Draw solid contours for data at x = sVal
+	/** Option "value" set the number of contour levels (default is 7). */
+	inline void ContFX(const mglData &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_contf_x(gr, &a, stl, sVal, opt);	}
+	/// Draw solid contours at manual levels for data at x = sVal
+	inline void ContFX(const mglData &v, const mglData &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_contf_x_val(gr, &v, &a, stl, sVal, opt);	}
+	/// Draw solid contours for data at y = sVal
+	/** Option "value" set the number of contour levels (default is 7). */
+	inline void ContFY(const mglData &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_contf_y(gr, &a, stl, sVal, opt);	}
+	/// Draw solid contours at manual levels for data at y = sVal
+	inline void ContFY(const mglData &v, const mglData &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_contf_y_val(gr, &v, &a, stl, sVal, opt);	}
+	/// Draw solid contours for data at z = sVal
+	/** Option "value" set the number of contour levels (default is 7). */
+	inline void ContFZ(const mglData &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_contf_z(gr, &a, stl, sVal, opt);	}
+	/// Draw solid contours at manual levels for data at z = sVal
+	inline void ContFZ(const mglData &v, const mglData &a, const char *stl="", double sVal=mglNaN, const char *opt="")
+	{	mgl_contf_z_val(gr, &v, &a, stl, sVal, opt);	}
+
+	/// Draw curve for formula with x in x-axis range
+	/** Option "value" set initial number of points. */
+	inline void FPlot(const char *fy, const char *stl="", const char *opt="")
+	{	mgl_fplot(gr, fy, stl, opt);	}
+	/// Draw curve for formulas parametrically depended on t in range [0,1]
+	/** Option "value" set initial number of points. */
+	inline void FPlot(const char *fx, const char *fy, const char *fz, const char *stl, const char *opt="")
+	{	mgl_fplot_xyz(gr, fx, fy, fz, stl, opt);	}
+	/// Draw surface by formula with x,y in axis range
+	/** Option "value" set initial number of points. */
+	inline void FSurf(const char *fz, const char *stl="", const char *opt="")
+	{	mgl_fsurf(gr, fz, stl, opt);	}
+	/// Draw surface by formulas parametrically depended on u,v in range [0,1]
+	/** Option "value" set initial number of points. */
+	inline void FSurf(const char *fx, const char *fy, const char *fz, const char *stl, const char *opt="")
+	{	mgl_fsurf_xyz(gr, fx, fy, fz, stl, opt);	}
+
+	/// Draw triangle mesh for points in arrays {x,y,z} with specified color c.
+	/** Style ‘#’ produce wire plot. If id.ny=c.nx then c set the triangle colors, else vertex colors. */
+	inline void TriPlot(const mglData &nums, const mglData &x, const mglData &y, const mglData &z, const mglData &c, const char *sch="", const char *opt="")
+	{	mgl_triplot_xyzc(gr, &nums, &x, &y, &z, &c, sch, opt);	}
+	/// Draw triangle mesh for points in arrays {x,y,z}
+	/** Style ‘#’ produce wire plot. */
+	inline void TriPlot(const mglData &nums, const mglData &x, const mglData &y, const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_triplot_xyz(gr, &nums, &x, &y, &z, sch, opt);	}
+	/// Draw triangle mesh for points in arrays {x,y}
+	/** Style ‘#’ produce wire plot. */
+	inline void TriPlot(const mglData &nums, const mglData &x, const mglData &y, const char *sch="", const char *opt="")
+	{	mgl_triplot_xy(gr, &nums, &x, &y, sch, opt);	}
+
+	/// Draw quad mesh for points in arrays {x,y,z} with specified color c
+	/** Style ‘#’ produce wire plot. If id.ny=c.nx then c set the quadrangle colors, else vertex colors. */
+	inline void QuadPlot(const mglData &nums, const mglData &x, const mglData &y, const mglData &z, const mglData &c, const char *sch="", const char *opt="")
+	{	mgl_quadplot_xyzc(gr, &nums, &x, &y, &z, &c, sch, opt);	}
+	/// Draw quad mesh for points in arrays {x,y,z}
+	/** Style ‘#’ produce wire plot. */
+	inline void QuadPlot(const mglData &nums, const mglData &x, const mglData &y, const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_quadplot_xyz(gr, &nums, &x, &y, &z, sch, opt);	}
+	/// Draw quad mesh for points in arrays {x,y}
+	/** Style ‘#’ produce wire plot. */
+	inline void QuadPlot(const mglData &nums, const mglData &x, const mglData &y, const char *sch="", const char *opt="")
+	{	mgl_quadplot_xy(gr, &nums, &x, &y, sch, opt);	}
+
+	/// Draw contour lines for triangle mesh for points in arrays {x,y,z}
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * If id.ny=c.nx then c set the quadrangle colors, else vertex colors. */
+	inline void TriCont(const mglData &nums, const mglData &x, const mglData &y, const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_tricont_xyc(gr, &nums, &x, &y, &z, sch, opt);	}
+	/// Draw contour lines for triangle mesh for points in arrays {x,y,z}
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * If id.ny=c.nx then c set the quadrangle colors, else vertex colors.
+	 * Option "value" set the number of contour levels (default is 7). */
+	inline void TriContV(const mglData &v, const mglData &nums, const mglData &x, const mglData &y, const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_tricont_xycv(gr, &v, &nums, &x, &y, &z, sch, opt);	}
+	/// Draw contour lines for triangle mesh for points in arrays {x,y,z} with specified color c.
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * If id.ny=c.nx then c set the quadrangle colors, else vertex colors. */
+	inline void TriCont(const mglData &nums, const mglData &x, const mglData &y, const mglData &z, const mglData &a, const char *sch="", const char *opt="")
+	{	mgl_tricont_xyzc(gr, &nums, &x, &y, &z, &a, sch, opt);	}
+	/// Draw contour lines for triangle mesh for points in arrays {x,y,z} with specified color c.
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * If id.ny=c.nx then c set the quadrangle colors, else vertex colors. */
+	inline void TriContV(const mglData &v, const mglData &nums, const mglData &x, const mglData &y, const mglData &z, const mglData &a, const char *sch="", const char *opt="")
+	{	mgl_tricont_xyzcv(gr, &v, &nums, &x, &y, &z, &a, sch, opt);	}
+	/// Draw contour lines for triangle mesh for points in arrays {x,y,z} with specified color c.
+	/** Style ‘_’ to draw contours at bottom of axis box.
+	 * Style ‘t’/‘T’ draw contour labels below/above contours.
+	 * If id.ny=c.nx then c set the quadrangle colors, else vertex colors. */
+	inline void TriCont(const mglData &v, const mglData &nums, const mglData &x, const mglData &y, const mglData &z, const mglData &a, const char *sch="", const char *opt="")
+	{	mgl_tricont_xyzcv(gr, &v, &nums, &x, &y, &z, &a, sch, opt);	}
+
+	/// Draw contour tubes for triangle mesh for points in arrays {x,y,z}
+	/** Option "value" set the number of contour levels (default is 7). */
+	inline void TriContVt(const mglData &nums, const mglData &x, const mglData &y, const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_tricontv_xyc(gr, &nums, &x, &y, &z, sch, opt);	}
+	/// Draw contour tubes for triangle mesh for points in arrays {x,y,z} with specified color c
+	/** Option "value" set the number of contour levels (default is 7). */
+	inline void TriContVt(const mglData &nums, const mglData &x, const mglData &y, const mglData &z, const mglData &a, const char *sch="", const char *opt="")
+	{	mgl_tricontv_xyzc(gr, &nums, &x, &y, &z, &a, sch, opt);	}
+	/// Draw contour tubes for triangle mesh for points in arrays {x,y,z} with specified color c
+	/** If id.ny=c.nx then c set the quadrangle colors, else vertex colors. */
+	inline void TriContVt(const mglData &v, const mglData &nums, const mglData &x, const mglData &y, const mglData &z, const mglData &a, const char *sch="", const char *opt="")
+	{	mgl_tricontv_xyzcv(gr, &v, &nums, &x, &y, &z, &a, sch, opt);	}
+
+	/// Draw dots in points {x,y,z}.
+	inline void Dots(const mglData &x, const mglData &y, const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_dots(gr, &x, &y, &z, sch, opt);	}
+	/// Draw semitransparent dots in points {x,y,z} with specified alpha a.
+	inline void Dots(const mglData &x, const mglData &y, const mglData &z, const mglData &a, const char *sch="", const char *opt="")
+	{	mgl_dots_a(gr, &x, &y, &z, &a, sch, opt);	}
+	/// Draw semitransparent dots in points {x,y,z} with specified color c and alpha a.
+	inline void Dots(const mglData &x, const mglData &y, const mglData &z, const mglData &c, const mglData &a, const char *sch="", const char *opt="")
+	{	mgl_dots_ca(gr, &x, &y, &z, &c, &a, sch, opt);	}
+	/// Draw surface reconstructed for points in arrays {x,y,z}.
+	/** Style ‘#’ produce wired plot. */
+	inline void Crust(const mglData &x, const mglData &y, const mglData &z, const char *sch="", const char *opt="")
+	{	mgl_crust(gr, &x, &y, &z, sch, opt);	}
+
+	/// Fit data along x-direction for each data row. Return array with values for found formula.
+	inline mglData Fit(const mglData &y, const char *eq, const char *vars, const char *opt="")
+	{	return mglData(true,mgl_fit_1(gr, &y, eq,vars,0, opt));	}
+	/// Fit data along x-direction for each data row starting from \a ini values. Return array with values for found formula.
+	inline mglData Fit(const mglData &y, const char *eq, const char *vars, mglData &ini, const char *opt="")
+	{	return mglData(true,mgl_fit_1(gr, &y, eq, vars, &ini, opt));	}
+	/// Fit data along x-, y-directions for each data slice. Return array with values for found formula.
+	inline mglData Fit2(const mglData &z, const char *eq, const char *vars, const char *opt="")
+	{	return mglData(true,mgl_fit_2(gr, &z, eq, vars,0, opt));	}
+	/// Fit data along x-, y-direction for each data slice starting from \a ini values. Return array with values for found formula.
+	inline mglData Fit2(const mglData &z, const char *eq, const char *vars, mglData &ini, const char *opt="")
+	{	return mglData(true,mgl_fit_2(gr, &z, eq, vars, &ini, opt));	}
+	/// Fit data along along all directions. Return array with values for found formula.
+	inline mglData Fit3(const mglData &a, const char *eq, const char *vars, const char *opt="")
+	{	return mglData(true,mgl_fit_3(gr, &a, eq, vars,0, opt));	}
+	/// Fit data along all directions starting from \a ini values. Return array with values for found formula.
+	inline mglData Fit3(const mglData &a, const char *eq, const char *vars, mglData &ini, const char *opt="")
+	{	return mglData(true,mgl_fit_3(gr, &a, eq, vars, &ini, opt));	}
+
+	/// Fit data along x-direction for each data row. Return array with values for found formula.
+	inline mglData Fit(const mglData &x, const mglData &y, const char *eq, const char *vars, const char *opt="")
+	{	return mglData(true,mgl_fit_xy(gr, &x, &y, eq, vars,0, opt));	}
+	/// Fit data along x-direction for each data row starting from \a ini values. Return array with values for found formula.
+	inline mglData Fit(const mglData &x, const mglData &y, const char *eq, const char *vars, mglData &ini, const char *opt="")
+	{	return mglData(true,mgl_fit_xy(gr, &x, &y, eq, vars, &ini, opt));	}
+	/// Fit data along x-, y-directions for each data slice. Return array with values for found formula.
+	inline mglData Fit(const mglData &x, const mglData &y, const mglData &z, const char *eq, const char *vars, const char *opt="")
+	{	return mglData(true,mgl_fit_xyz(gr, &x, &y, &z, eq, vars,0, opt));	}
+	/// Fit data along x-, y-directions for each data slice starting from \a ini values. Return array with values for found formula.
+	inline mglData Fit(const mglData &x, const mglData &y, const mglData &z, const char *eq, const char *vars, mglData &ini, const char *opt="")
+	{	return mglData(true,mgl_fit_xyz(gr, &x, &y, &z, eq, vars, &ini, opt));	}
+	/// Fit data along along all directions. Return array with values for found formula.
+	inline mglData Fit(const mglData &x, const mglData &y, const mglData &z, const mglData &a, const char *eq, const char *vars, const char *opt="")
+	{	return mglData(true,mgl_fit_xyza(gr, &x, &y, &z, &a, eq, vars,0, opt));	}
+	/// Fit data along along all directions starting from \a ini values. Return array with values for found formula.
+	inline mglData Fit(const mglData &x, const mglData &y, const mglData &z, const mglData &a, const char *eq, const char *vars, mglData &ini, const char *opt="")
+	{	return mglData(true,mgl_fit_xyza(gr, &x, &y, &z, &a, eq,vars, &ini, opt));	}
+
+	/// Fit data with dispersion s along x-direction for each data row. Return array with values for found formula.
+	inline mglData FitS(const mglData &y, const mglData &s, const char *eq, const char *vars, const char *opt="")
+	{	return mglData(true,mgl_fit_ys(gr, &y, &s, eq, vars,0, opt));	}
+	/// Fit data with dispersion s along x-direction for each data row starting from \a ini values. Return array with values for found formula.
+	inline mglData FitS(const mglData &y, const mglData &s, const char *eq, const char *vars, mglData &ini, const char *opt="")
+	{	return mglData(true,mgl_fit_ys(gr, &y, &s, eq, vars, &ini, opt));	}
+	/// Fit data with dispersion s along x-direction for each data row. Return array with values for found formula.
+	inline mglData FitS(const mglData &x, const mglData &y, const mglData &s, const char *eq, const char *vars, const char *opt="")
+	{	return mglData(true,mgl_fit_xys(gr, &x, &y, &s, eq, vars,0, opt));	}
+	/// Fit data with dispersion s along x-direction for each data row starting from \a ini values. Return array with values for found formula.
+	inline mglData FitS(const mglData &x, const mglData &y, const mglData &s, const char *eq, const char *vars, mglData &ini, const char *opt="")
+	{	return mglData(true,mgl_fit_xys(gr, &x, &y, &s, eq, vars, &ini, opt));	}
+	/// Fit data with dispersion s along x-, y-directions for each data slice. Return array with values for found formula.
+	inline mglData FitS(const mglData &x, const mglData &y, const mglData &z, const mglData &s, const char *eq, const char *vars, const char *opt="")
+	{	return mglData(true,mgl_fit_xyzs(gr, &x, &y, &z, &s, eq, vars,0, opt));	}
+	/// Fit data with dispersion s along x-, y-directions for each data slice starting from \a ini values. Return array with values for found formula.
+	inline mglData FitS(const mglData &x, const mglData &y, const mglData &z, const mglData &s, const char *eq, const char *vars, mglData &ini, const char *opt="")
+	{	return mglData(true,mgl_fit_xyzs(gr, &x, &y, &z, &s, eq, vars, &ini, opt));	}
+	/// Fit data with dispersion s along all directions. Return array with values for found formula.
+	inline mglData FitS(const mglData &x, const mglData &y, const mglData &z, const mglData &a, const mglData &s, const char *eq, const char *vars, const char *opt="")
+	{	return mglData(true,mgl_fit_xyzas(gr, &x, &y, &z, &a, &s, eq, vars,0, opt));	}
+	/// Fit data with dispersion s along all directions starting from \a ini values. Return array with values for found formula.
+	inline mglData FitS(const mglData &x, const mglData &y, const mglData &z, const mglData &a, const mglData &s, const char *eq, const char *vars, mglData &ini, const char *opt="")
+	{	return mglData(true,mgl_fit_xyzas(gr, &x, &y, &z, &a, &s, eq, vars, &ini, opt));	}
+
+	/// Print fitted last formula (with coefficients)
+	inline void PutsFit(mglPoint p, const char *prefix=0, const char *font="", double size=-1)
+	{	mgl_puts_fit(gr, p.x, p.y, p.z, prefix, font, size);	}
+	/// Get last fitted formula
+	inline const char *GetFit()	const
+	{	return mgl_get_fit(gr);	}
+	/// Get chi for last fitted formula
+	static inline mreal GetFitChi()
+	{	return mgl_get_fit_chi();	}
+	/// Get covariance matrix for last fitted formula
+	static inline mglData GetFitCovar()
+	{	return mglData(mgl_get_fit_covar());	}
+
+	/// Solve PDE with x,y,z in range axis range
+	inline mglData PDE(const char *ham, const mglData &ini_re, const mglData &ini_im, double dz=0.1, double k0=100, const char *opt="")
+	{	return mglData(true,mgl_pde_solve(gr,ham,&ini_re,&ini_im,dz,k0, opt));	}
+	/// Solve PDE with x,y,z in range axis range
+	inline mglDataC PDEc(const char *ham, const mglData &ini_re, const mglData &ini_im, double dz=0.1, double k0=100, const char *opt="")
+	{	return mglDataC(true,mgl_pde_solve_c(gr,ham,&ini_re,&ini_im,dz,k0, opt));	}
+
+	/// Solve PDE with x,y,z in range axis range using advanced (slow!!!) method (2d only)
+	inline mglData APDE(const char *ham, const mglData &ini_re, const mglData &ini_im, double dz=0.1, double k0=100, const char *opt="")
+	{	return mglData(true,mgl_pde_adv(gr,ham,&ini_re,&ini_im,dz,k0, opt));	}
+	/// Solve PDE with x,y,z in range axis range using advanced (slow!!!) method (2d only)
+	inline mglDataC APDEc(const char *ham, const mglData &ini_re, const mglData &ini_im, double dz=0.1, double k0=100, const char *opt="")
+	{	return mglDataC(true,mgl_pde_adv_c(gr,ham,&ini_re,&ini_im,dz,k0, opt));	}
+
+	/// Fill data by formula with x,y,z in range axis range
+	inline void Fill(mglData &u, const char *eq, const char *opt="")
+	{	mgl_data_fill_eq(gr, &u, eq, 0, 0, opt);	}
+	inline void Fill(mglData &u, const char *eq, const mglData &v, const char *opt="")
+	{	mgl_data_fill_eq(gr, &u, eq, &v, 0, opt);	}
+	inline void Fill(mglData &u, const char *eq, const mglData &v, const mglData &w, const char *opt="")
+	{	mgl_data_fill_eq(gr, &u, eq, &v, &w, opt);	}
+	/// Fill data by formula with x,y,z in range axis range
+	inline void Fill(mglDataC &u, const char *eq, const char *opt="")
+	{	mgl_datac_fill_eq(gr, &u, eq, 0, 0, opt);	}
+	inline void Fill(mglDataC &u, const char *eq, const mglData &v, const char *opt="")
+	{	mgl_datac_fill_eq(gr, &u, eq, &v, 0, opt);	}
+	inline void Fill(mglDataC &u, const char *eq, const mglData &v, const mglData &w, const char *opt="")
+	{	mgl_datac_fill_eq(gr, &u, eq, &v, &w, opt);	}
+
+	/// Fill dat by interpolated values of vdat parametrically depended on xdat for x in axis range
+	inline void Refill(mglData &dat, const mglData &xdat, const mglData &vdat, long sl=-1, const char *opt="")
+	{	mgl_data_refill_gr(gr,&dat,&xdat,0,0,&vdat,sl,opt);	}
+	/// Fill dat by interpolated values of vdat parametrically depended on xdat,ydat for x,y in axis range
+	inline void Refill(mglData &dat, const mglData &xdat, const mglData &ydat, const mglData &vdat, long sl=-1, const char *opt="")
+	{	mgl_data_refill_gr(gr,&dat,&xdat,&ydat,0,&vdat,sl,opt);	}
+	/// Fill dat by interpolated values of vdat parametrically depended on xdat,ydat,zdat for x,y,z in axis range
+	inline void Refill(mglData &dat, const mglData &xdat, const mglData &ydat, const mglData &zdat, const mglData &vdat, const char *opt="")
+	{	mgl_data_refill_gr(gr,&dat,&xdat,&ydat,&zdat,&vdat,-1,opt);	}
+
+	/// Fill dat by interpolated values of vdat parametrically depended on xdat for x in axis range
+	inline void Refill(mglDataC &dat, const mglData &xdat, const mglData &vdat, long sl=-1, const char *opt="")
+	{	mgl_datac_refill_gr(gr,&dat,&xdat,0,0,&vdat,sl,opt);	}
+	/// Fill dat by interpolated values of vdat parametrically depended on xdat,ydat for x,y in axis range
+	inline void Refill(mglDataC &dat, const mglData &xdat, const mglData &ydat, const mglData &vdat, long sl=-1, const char *opt="")
+	{	mgl_datac_refill_gr(gr,&dat,&xdat,&ydat,0,&vdat,sl,opt);	}
+	/// Fill dat by interpolated values of vdat parametrically depended on xdat,ydat,zdat for x,y,z in axis range
+	inline void Refill(mglDataC &dat, const mglData &xdat, const mglData &ydat, const mglData &zdat, const mglData &vdat, const char *opt="")
+	{	mgl_datac_refill_gr(gr,&dat,&xdat,&ydat,&zdat,&vdat,-1,opt);	}
+
+	/// Set the data by triangulated surface values assuming x,y,z in range axis range
+	inline void DataGrid(mglData &d, const mglData &x, const mglData &y, const mglData &z, const char *opt="")
+	{	mgl_data_grid(gr,&d,&x,&y,&z,opt);	}
+
+	/// Make histogram (distribution) of data. This function do not plot data.
+	/** Option "value" sets the size of output array (default is mglFitPnts=100). */
+	inline mglData Hist(const mglData &x, const mglData &a, const char *opt="")
+	{	return mglData(true, mgl_hist_x(gr, &x, &a, opt));	}
+	/// Make histogram (distribution) of data. This function do not plot data.
+	/** Option "value" sets the size of output array (default is mglFitPnts=100). */
+	inline mglData Hist(const mglData &x, const mglData &y, const mglData &a, const char *opt="")
+	{	return mglData(true, mgl_hist_xy(gr, &x, &y, &a, opt));	}
+	/// Make histogram (distribution) of data. This function do not plot data.
+	/** Option "value" sets the size of output array (default is mglFitPnts=100). */
+	inline mglData Hist(const mglData &x, const mglData &y, const mglData &z, const mglData &a, const char *opt="")
+	{	return mglData(true, mgl_hist_xyz(gr, &x, &y, &z, &a, opt));	}
+
+	inline void Compression(bool){}		// NOTE: Add later -- IDTF
+	/// Set the preference for vertex color on/off (for formats that support it, now only PRC does).
+	inline void VertexColor(bool enable)	{	mgl_set_flag(gr,enable, MGL_PREFERVC);	}
+	/// Render only front side of surfaces for dubugging purposes (for formats that support it, now only PRC does).
+	inline void DoubleSided(bool enable)	{	mgl_set_flag(gr,!enable, MGL_ONESIDED);	}
+//	inline void TextureColor(bool){}	// NOTE: Add later -- IDTF
+};
+//-----------------------------------------------------------------------------
+/// Wrapper class for MGL parsing
+class mglParse
+{
+	HMPR pr;
+public:
+	mglParse(HMPR p)		{	pr = p;		mgl_use_parser(pr,1);	}
+	mglParse(mglParse &p)	{	pr = p.pr;	mgl_use_parser(pr,1);	}
+	mglParse(bool setsize=false)
+	{	pr=mgl_create_parser();	mgl_parser_allow_setsize(pr, setsize);	}
+	~mglParse()	{	if(mgl_use_parser(pr,-1)<1)	mgl_delete_parser(pr);	}
+	/// Get pointer to internal mglParser object
+	inline HMPR Self()	{	return pr;	}
+	/// Parse and draw single line of the MGL script
+	inline int Parse(mglGraph *gr, const char *str, int pos)
+	{	return mgl_parse_line(gr->Self(), pr, str, pos);	}
+	inline int Parse(mglGraph *gr, const wchar_t *str, int pos)
+	{	return mgl_parse_linew(gr->Self(), pr, str, pos);	}
+	/// Execute MGL script text with '\n' separated lines
+	inline void Execute(mglGraph *gr, const char *str)
+	{	mgl_parse_text(gr->Self(), pr, str);	}
+	inline void Execute(mglGraph *gr, const wchar_t *str)
+	{	mgl_parse_textw(gr->Self(), pr, str);	}
+	/// Execute and draw script from the file
+	inline void Execute(mglGraph *gr, FILE *fp, bool print=false)
+	{	mgl_parse_file(gr->Self(), pr, fp, print);	}
+
+	/// Return type of command: 0 - not found, 1 - other data plot, 2 - func plot,
+	///		3 - setup, 4 - data handle, 5 - data create, 6 - subplot, 7 - program
+	///		8 - 1d plot, 9 - 2d plot, 10 - 3d plot, 11 - dd plot, 12 - vector plot
+	///		13 - axis, 14 - primitives, 15 - axis setup, 16 - text/legend, 17 - data transform
+	inline int CmdType(const char *name)
+	{	return mgl_parser_cmd_type(pr, name);	}
+	/// Return string of command format (command name and its argument[s])
+	inline const char *CmdFormat(const char *name)
+	{	return mgl_parser_cmd_frmt(pr, name);	}
+	/// Return description of MGL command
+	inline const char *CmdDesc(const char *name)
+	{	return mgl_parser_cmd_desc(pr, name);	}
+	/// Get name of command with nmber n
+	inline const char *GetCmdName(long n)
+	{	return mgl_parser_cmd_name(pr,n);	}
+	/// Get number of defined commands
+	inline long GetCmdNum()
+	{	return mgl_parser_cmd_num(pr);	}
+	/// Load new commands from external dynamic Library (must have "const mglCommand *mgl_cmd_extra" variable)
+	inline void LoadDLL(const char *fname)
+	{	mgl_parser_load(pr, fname);	}
+	/// Apply one step for equation d vars[i]/dt = eqs[i] using Runge-Kutta method
+	inline void RK_Step(const char *eqs, const char *vars, mreal dt=1)
+	{	mgl_rk_step(pr, eqs, vars, dt);	}
+	inline void RK_Step(const wchar_t *eqs, const wchar_t *vars, mreal dt=1)
+	{	mgl_rk_step_w(pr, eqs, vars, dt);	}
+
+	/// Set value for parameter $N
+	inline void AddParam(int id, const char *str)
+	{	mgl_parser_add_param(pr, id, str);	}
+	inline void AddParam(int id, const wchar_t *str)
+	{	mgl_parser_add_paramw(pr, id, str);	}
+	/// Restore once flag
+	inline void RestoreOnce()	{	mgl_parser_restore_once(pr);	}
+	/// Allow changing size of the picture
+	inline void AllowSetSize(bool allow)	{	mgl_parser_allow_setsize(pr, allow);	}
+	/// Allow reading/saving files
+	inline void AllowFileIO(bool allow)		{	mgl_parser_allow_file_io(pr, allow);	}
+	/// Allow loading commands from external libraries
+	inline void AllowDllCall(bool allow)	{	mgl_parser_allow_dll_call(pr, allow);	}
+	/// Set flag to stop script parsing
+	inline void Stop()	{	mgl_parser_stop(pr);	}
+	/// Set variant of argument(s) separated by '?' to be used in further commands
+	inline void SetVariant(int var=0)
+	{	mgl_parser_variant(pr, var);	}
+
+	/// Return result of formula evaluation
+	inline mglData Calc(const char *formula)
+	{	return mglData(true,mgl_parser_calc(pr,formula)); 	}
+	inline mglData Calc(const wchar_t *formula)
+	{	return mglData(true,mgl_parser_calcw(pr,formula));	}
+
+	/// Find variable with given name or add a new one
+	/// NOTE !!! You must not delete obtained data arrays !!!
+	inline mglData *AddVar(const char *name)
+	{	return mgl_parser_add_var(pr, name);	}
+	inline mglData *AddVar(const wchar_t *name)
+	{	return mgl_parser_add_varw(pr, name);	}
+	/// Find variable with given name or return NULL if no one
+	/// NOTE !!! You must not delete obtained data arrays !!!
+	inline mglData *FindVar(const char *name)
+	{	return mgl_parser_find_var(pr, name);	}
+	inline mglData *FindVar(const wchar_t *name)
+	{	return mgl_parser_find_varw(pr, name);	}
+	/// Get variable with given id. Can be NULL for temporary ones.
+	/// NOTE !!! You must not delete obtained data arrays !!!
+	inline mglData *GetVar(unsigned long id)
+	{	return mgl_parser_get_var(pr,id);	}
+	/// Get number of variables
+	inline long GetNumVar()
+	{	return mgl_parser_num_var(pr);	}
+	/// Delete variable with name
+	inline void DeleteVar(const char *name)		{	mgl_parser_del_var(pr, name);		}
+	inline void DeleteVar(const wchar_t *name)	{	mgl_parser_del_varw(pr, name);		}
+	/// Delete all data variables
+	void DeleteAll()	{	mgl_parser_del_all(pr);	}
+};
+//-----------------------------------------------------------------------------
diff --git a/lang/numpy.i b/lang/numpy.i
new file mode 100644
index 0000000..25d1f1a
--- /dev/null
+++ b/lang/numpy.i
@@ -0,0 +1,1634 @@
+/* -*- C -*-  (not really, but good for syntax highlighting) */
+#ifdef SWIGPYTHON
+
+%{
+#ifndef SWIG_FILE_WITH_INIT
+#  define NO_IMPORT_ARRAY
+#endif
+#include "stdio.h"
+#include <numpy/arrayobject.h>
+%}
+
+/**********************************************************************/
+
+%fragment("NumPy_Backward_Compatibility", "header")
+{
+/* Support older NumPy data type names
+*/
+%#if NDARRAY_VERSION < 0x01000000
+%#define NPY_BOOL          PyArray_BOOL
+%#define NPY_BYTE          PyArray_BYTE
+%#define NPY_UBYTE         PyArray_UBYTE
+%#define NPY_SHORT         PyArray_SHORT
+%#define NPY_USHORT        PyArray_USHORT
+%#define NPY_INT           PyArray_INT
+%#define NPY_UINT          PyArray_UINT
+%#define NPY_LONG          PyArray_LONG
+%#define NPY_ULONG         PyArray_ULONG
+%#define NPY_LONGLONG      PyArray_LONGLONG
+%#define NPY_ULONGLONG     PyArray_ULONGLONG
+%#define NPY_FLOAT         PyArray_FLOAT
+%#define NPY_DOUBLE        PyArray_DOUBLE
+%#define NPY_LONGDOUBLE    PyArray_LONGDOUBLE
+%#define NPY_CFLOAT        PyArray_CFLOAT
+%#define NPY_CDOUBLE       PyArray_CDOUBLE
+%#define NPY_CLONGDOUBLE   PyArray_CLONGDOUBLE
+%#define NPY_OBJECT        PyArray_OBJECT
+%#define NPY_STRING        PyArray_STRING
+%#define NPY_UNICODE       PyArray_UNICODE
+%#define NPY_VOID          PyArray_VOID
+%#define NPY_NTYPES        PyArray_NTYPES
+%#define NPY_NOTYPE        PyArray_NOTYPE
+%#define NPY_CHAR          PyArray_CHAR
+%#define NPY_USERDEF       PyArray_USERDEF
+%#define npy_intp          intp
+
+%#define NPY_MAX_BYTE      MAX_BYTE
+%#define NPY_MIN_BYTE      MIN_BYTE
+%#define NPY_MAX_UBYTE     MAX_UBYTE
+%#define NPY_MAX_SHORT     MAX_SHORT
+%#define NPY_MIN_SHORT     MIN_SHORT
+%#define NPY_MAX_USHORT    MAX_USHORT
+%#define NPY_MAX_INT       MAX_INT
+%#define NPY_MIN_INT       MIN_INT
+%#define NPY_MAX_UINT      MAX_UINT
+%#define NPY_MAX_LONG      MAX_LONG
+%#define NPY_MIN_LONG      MIN_LONG
+%#define NPY_MAX_ULONG     MAX_ULONG
+%#define NPY_MAX_LONGLONG  MAX_LONGLONG
+%#define NPY_MIN_LONGLONG  MIN_LONGLONG
+%#define NPY_MAX_ULONGLONG MAX_ULONGLONG
+%#define NPY_MAX_INTP      MAX_INTP
+%#define NPY_MIN_INTP      MIN_INTP
+
+%#define NPY_FARRAY        FARRAY
+%#define NPY_F_CONTIGUOUS  F_CONTIGUOUS
+%#endif
+}
+
+/**********************************************************************/
+
+/* The following code originally appeared in
+ * enthought/kiva/agg/src/numeric.i written by Eric Jones.  It was
+ * translated from C++ to C by John Hunter.  Bill Spotz has modified
+ * it to fix some minor bugs, upgrade from Numeric to numpy (all
+ * versions), add some comments and functionality, and convert from
+ * direct code insertion to SWIG fragments.
+ */
+
+%fragment("NumPy_Macros", "header")
+{
+/* Macros to extract array attributes.
+ */
+%#define is_array(a)            ((a) && PyArray_Check((PyArrayObject *)a))
+%#define array_type(a)          (int)(PyArray_TYPE(a))
+%#define array_numdims(a)       (((PyArrayObject *)a)->nd)
+%#define array_dimensions(a)    (((PyArrayObject *)a)->dimensions)
+%#define array_size(a,i)        (((PyArrayObject *)a)->dimensions[i])
+%#define array_data(a)          (((PyArrayObject *)a)->data)
+%#define array_is_contiguous(a) (PyArray_ISCONTIGUOUS(a))
+%#define array_is_native(a)     (PyArray_ISNOTSWAPPED(a))
+%#define array_is_fortran(a)    (PyArray_ISFORTRAN(a))
+}
+
+/**********************************************************************/
+
+%fragment("NumPy_Utilities", "header")
+{
+  /* Given a PyObject, return a string describing its type.
+   */
+  char* pytype_string(PyObject* py_obj) {
+    if (py_obj == NULL          ) return "C NULL value";
+    if (py_obj == Py_None       ) return "Python None" ;
+    if (PyCallable_Check(py_obj)) return "callable"    ;
+    if (PyString_Check(  py_obj)) return "string"      ;
+    if (PyInt_Check(     py_obj)) return "int"         ;
+    if (PyFloat_Check(   py_obj)) return "float"       ;
+    if (PyDict_Check(    py_obj)) return "dict"        ;
+    if (PyList_Check(    py_obj)) return "list"        ;
+    if (PyTuple_Check(   py_obj)) return "tuple"       ;
+    if (PyFile_Check(    py_obj)) return "file"        ;
+    if (PyModule_Check(  py_obj)) return "module"      ;
+    if (PyInstance_Check(py_obj)) return "instance"    ;
+
+    return "unknow type";
+  }
+
+  /* Given a NumPy typecode, return a string describing the type.
+   */
+  char* typecode_string(int typecode) {
+    static char* type_names[25] = {"bool", "byte", "unsigned byte",
+                                   "short", "unsigned short", "int",
+                                   "unsigned int", "long", "unsigned long",
+                                   "long long", "unsigned long long",
+                                   "float", "double", "long double",
+                                   "complex float", "complex double",
+                                   "complex long double", "object",
+                                   "string", "unicode", "void", "ntypes",
+                                   "notype", "char", "unknown"};
+    return typecode < 24 ? type_names[typecode] : type_names[24];
+  }
+
+  /* Make sure input has correct numpy type.  Allow character and byte
+   * to match.  Also allow int and long to match.  This is deprecated.
+   * You should use PyArray_EquivTypenums() instead.
+   */
+  int type_match(int actual_type, int desired_type) {
+    return PyArray_EquivTypenums(actual_type, desired_type);
+  }
+}
+
+/**********************************************************************/
+
+%fragment("NumPy_Object_to_Array", "header",
+          fragment="NumPy_Backward_Compatibility",
+          fragment="NumPy_Macros",
+          fragment="NumPy_Utilities")
+{
+  /* Given a PyObject pointer, cast it to a PyArrayObject pointer if
+   * legal.  If not, set the python error string appropriately and
+   * return NULL.
+   */
+  PyArrayObject* obj_to_array_no_conversion(PyObject* input, int typecode)
+  {
+    PyArrayObject* ary = NULL;
+    if (is_array(input) && (typecode == NPY_NOTYPE ||
+                            PyArray_EquivTypenums(array_type(input), typecode)))
+    {
+      ary = (PyArrayObject*) input;
+    }
+    else if is_array(input)
+    {
+      char* desired_type = typecode_string(typecode);
+      char* actual_type  = typecode_string(array_type(input));
+      PyErr_Format(PyExc_TypeError,
+                   "Array of type '%s' required.  Array of type '%s' given",
+                   desired_type, actual_type);
+      ary = NULL;
+    }
+    else
+    {
+      char * desired_type = typecode_string(typecode);
+      char * actual_type  = pytype_string(input);
+      PyErr_Format(PyExc_TypeError,
+                   "Array of type '%s' required.  A '%s' was given",
+                   desired_type, actual_type);
+      ary = NULL;
+    }
+    return ary;
+  }
+
+  /* Convert the given PyObject to a NumPy array with the given
+   * typecode.  On success, return a valid PyArrayObject* with the
+   * correct type.  On failure, the python error string will be set and
+   * the routine returns NULL.
+   */
+  PyArrayObject* obj_to_array_allow_conversion(PyObject* input, int typecode,
+                                               int* is_new_object)
+  {
+    PyArrayObject* ary = NULL;
+    PyObject* py_obj;
+    if (is_array(input) && (typecode == NPY_NOTYPE ||
+                            PyArray_EquivTypenums(array_type(input),typecode)))
+    {
+      ary = (PyArrayObject*) input;
+      *is_new_object = 0;
+    }
+    else
+    {
+      py_obj = PyArray_FROMANY(input, typecode, 0, 0, NPY_DEFAULT);
+      /* If NULL, PyArray_FromObject will have set python error value.*/
+      ary = (PyArrayObject*) py_obj;
+      *is_new_object = 1;
+    }
+    return ary;
+  }
+
+  /* Given a PyArrayObject, check to see if it is contiguous.  If so,
+   * return the input pointer and flag it as not a new object.  If it is
+   * not contiguous, create a new PyArrayObject using the original data,
+   * flag it as a new object and return the pointer.
+   */
+  PyArrayObject* make_contiguous(PyArrayObject* ary, int* is_new_object,
+                                 int min_dims, int max_dims)
+  {
+    PyArrayObject* result;
+    if (array_is_contiguous(ary))
+    {
+      result = ary;
+      *is_new_object = 0;
+    }
+    else
+    {
+      result = (PyArrayObject*) PyArray_ContiguousFromObject((PyObject*)ary,
+                                                             array_type(ary),
+                                                             min_dims,
+                                                             max_dims);
+      *is_new_object = 1;
+    }
+    return result;
+  }
+
+  /* Given a PyArrayObject, check to see if it is Fortran-contiguous.
+   * If so, return the input pointer, but do not flag it as not a new
+   * object.  If it is not Fortran-contiguous, create a new
+   * PyArrayObject using the original data, flag it as a new object
+   * and return the pointer.
+   */
+  PyArrayObject* make_fortran(PyArrayObject* ary, int* is_new_object,
+                              int min_dims, int max_dims)
+  {
+    PyArrayObject* result;
+    if (array_is_fortran(ary))
+    {
+      result = ary;
+      *is_new_object = 0;
+    }
+    else
+    {
+      Py_INCREF(ary->descr);
+      result = (PyArrayObject*) PyArray_FromArray(ary, ary->descr, NPY_FORTRAN);
+      *is_new_object = 1;
+    }
+    return result;
+  }
+
+  /* Convert a given PyObject to a contiguous PyArrayObject of the
+   * specified type.  If the input object is not a contiguous
+   * PyArrayObject, a new one will be created and the new object flag
+   * will be set.
+   */
+  PyArrayObject* obj_to_array_contiguous_allow_conversion(PyObject* input,
+                                                          int typecode,
+                                                          int* is_new_object)
+  {
+    int is_new1 = 0;
+    int is_new2 = 0;
+    PyArrayObject* ary2;
+    PyArrayObject* ary1 = obj_to_array_allow_conversion(input, typecode,
+                                                        &is_new1);
+    if (ary1)
+    {
+      ary2 = make_contiguous(ary1, &is_new2, 0, 0);
+      if ( is_new1 && is_new2)
+      {
+        Py_DECREF(ary1);
+      }
+      ary1 = ary2;
+    }
+    *is_new_object = is_new1 || is_new2;
+    return ary1;
+  }
+
+  /* Convert a given PyObject to a Fortran-ordered PyArrayObject of the
+   * specified type.  If the input object is not a Fortran-ordered
+   * PyArrayObject, a new one will be created and the new object flag
+   * will be set.
+   */
+  PyArrayObject* obj_to_array_fortran_allow_conversion(PyObject* input,
+                                                       int typecode,
+                                                       int* is_new_object)
+  {
+    int is_new1 = 0;
+    int is_new2 = 0;
+    PyArrayObject* ary2;
+    PyArrayObject* ary1 = obj_to_array_allow_conversion(input, typecode,
+                                                        &is_new1);
+    if (ary1)
+    {
+      ary2 = make_fortran(ary1, &is_new2, 0, 0);
+      if (is_new1 && is_new2)
+      {
+        Py_DECREF(ary1);
+      }
+      ary1 = ary2;
+    }
+    *is_new_object = is_new1 || is_new2;
+    return ary1;
+  }
+
+} /* end fragment */
+
+
+/**********************************************************************/
+
+%fragment("NumPy_Array_Requirements", "header",
+          fragment="NumPy_Backward_Compatibility",
+          fragment="NumPy_Macros")
+{
+  /* Test whether a python object is contiguous.  If array is
+   * contiguous, return 1.  Otherwise, set the python error string and
+   * return 0.
+   */
+  int require_contiguous(PyArrayObject* ary)
+  {
+    int contiguous = 1;
+    if (!array_is_contiguous(ary))
+    {
+      PyErr_SetString(PyExc_TypeError,
+                      "Array must be contiguous.  A non-contiguous array was given");
+      contiguous = 0;
+    }
+    return contiguous;
+  }
+
+  /* Require that a numpy array is not byte-swapped.  If the array is
+   * not byte-swapped, return 1.  Otherwise, set the python error string
+   * and return 0.
+   */
+  int require_native(PyArrayObject* ary)
+  {
+    int native = 1;
+    if (!array_is_native(ary))
+    {
+      PyErr_SetString(PyExc_TypeError,
+                      "Array must have native byteorder.  "
+                      "A byte-swapped array was given");
+      native = 0;
+    }
+    return native;
+  }
+
+  /* Require the given PyArrayObject to have a specified number of
+   * dimensions.  If the array has the specified number of dimensions,
+   * return 1.  Otherwise, set the python error string and return 0.
+   */
+  int require_dimensions(PyArrayObject* ary, int exact_dimensions)
+  {
+    int success = 1;
+    if (array_numdims(ary) != exact_dimensions)
+    {
+      PyErr_Format(PyExc_TypeError,
+                   "Array must have %d dimensions.  Given array has %d dimensions",
+                   exact_dimensions, array_numdims(ary));
+      success = 0;
+    }
+    return success;
+  }
+
+  /* Require the given PyArrayObject to have one of a list of specified
+   * number of dimensions.  If the array has one of the specified number
+   * of dimensions, return 1.  Otherwise, set the python error string
+   * and return 0.
+   */
+  int require_dimensions_n(PyArrayObject* ary, int* exact_dimensions, int n)
+  {
+    int success = 0;
+    int i;
+    char dims_str[255] = "";
+    char s[255];
+    for (i = 0; i < n && !success; i++)
+    {
+      if (array_numdims(ary) == exact_dimensions[i])
+      {
+        success = 1;
+      }
+    }
+    if (!success)
+    {
+      for (i = 0; i < n-1; i++)
+      {
+        sprintf(s, "%d, ", exact_dimensions[i]);
+        strcat(dims_str,s);
+      }
+      sprintf(s, " or %d", exact_dimensions[n-1]);
+      strcat(dims_str,s);
+      PyErr_Format(PyExc_TypeError,
+                   "Array must have %s dimensions.  Given array has %d dimensions",
+                   dims_str, array_numdims(ary));
+    }
+    return success;
+  }
+
+  /* Require the given PyArrayObject to have a specified shape.  If the
+   * array has the specified shape, return 1.  Otherwise, set the python
+   * error string and return 0.
+   */
+  int require_size(PyArrayObject* ary, npy_intp* size, int n)
+  {
+    int i;
+    int success = 1;
+    int len;
+    char desired_dims[255] = "[";
+    char s[255];
+    char actual_dims[255] = "[";
+    for(i=0; i < n;i++)
+    {
+      if (size[i] != -1 &&  size[i] != array_size(ary,i))
+      {
+        success = 0;
+      }
+    }
+    if (!success)
+    {
+      for (i = 0; i < n; i++)
+      {
+        if (size[i] == -1)
+        {
+          sprintf(s, "*,");
+        }
+        else
+        {
+          sprintf(s, "%ld,", (long int)size[i]);
+        }
+        strcat(desired_dims,s);
+      }
+      len = strlen(desired_dims);
+      desired_dims[len-1] = ']';
+      for (i = 0; i < n; i++)
+      {
+        sprintf(s, "%ld,", (long int)array_size(ary,i));
+        strcat(actual_dims,s);
+      }
+      len = strlen(actual_dims);
+      actual_dims[len-1] = ']';
+      PyErr_Format(PyExc_TypeError,
+                   "Array must have shape of %s.  Given array has shape of %s",
+                   desired_dims, actual_dims);
+    }
+    return success;
+  }
+
+  /* Require the given PyArrayObject to to be FORTRAN ordered.  If the
+   * the PyArrayObject is already FORTRAN ordered, do nothing.  Else,
+   * set the FORTRAN ordering flag and recompute the strides.
+   */
+  int require_fortran(PyArrayObject* ary)
+  {
+    int success = 1;
+    int nd = array_numdims(ary);
+    int i;
+    if (array_is_fortran(ary)) return success;
+    /* Set the FORTRAN ordered flag */
+    ary->flags = NPY_FARRAY;
+    /* Recompute the strides */
+    ary->strides[0] = ary->strides[nd-1];
+    for (i=1; i < nd; ++i)
+      ary->strides[i] = ary->strides[i-1] * array_size(ary,i-1);
+    return success;
+  }
+}
+
+/* Combine all NumPy fragments into one for convenience */
+%fragment("NumPy_Fragments", "header",
+          fragment="NumPy_Backward_Compatibility",
+          fragment="NumPy_Macros",
+          fragment="NumPy_Utilities",
+          fragment="NumPy_Object_to_Array",
+          fragment="NumPy_Array_Requirements") { }
+
+/* End John Hunter translation (with modifications by Bill Spotz)
+ */
+
+/* %numpy_typemaps() macro
+ *
+ * This macro defines a family of 41 typemaps that allow C arguments
+ * of the form
+ *
+ *     (DATA_TYPE IN_ARRAY1[ANY])
+ *     (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1)
+ *     (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1)
+ *
+ *     (DATA_TYPE IN_ARRAY2[ANY][ANY])
+ *     (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+ *     (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2)
+ *     (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+ *     (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2)
+ *
+ *     (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY])
+ *     (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+ *     (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3)
+ *     (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+ *     (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3)
+ *
+ *     (DATA_TYPE INPLACE_ARRAY1[ANY])
+ *     (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1)
+ *     (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1)
+ *
+ *     (DATA_TYPE INPLACE_ARRAY2[ANY][ANY])
+ *     (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+ *     (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2)
+ *     (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+ *     (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2)
+ *
+ *     (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY])
+ *     (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+ *     (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3)
+ *     (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+ *     (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3)
+ *
+ *     (DATA_TYPE ARGOUT_ARRAY1[ANY])
+ *     (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1)
+ *     (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1)
+ *
+ *     (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY])
+ *
+ *     (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY])
+ *
+ *     (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1)
+ *     (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1)
+ *
+ *     (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2)
+ *     (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2)
+ *     (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2)
+ *     (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2)
+ *
+ *     (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3)
+ *     (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3)
+ *     (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3)
+ *     (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3)
+ *
+ * where "DATA_TYPE" is any type supported by the NumPy module, and
+ * "DIM_TYPE" is any int-like type suitable for specifying dimensions.
+ * The difference between "ARRAY" typemaps and "FARRAY" typemaps is
+ * that the "FARRAY" typemaps expect FORTRAN ordering of
+ * multidimensional arrays.  In python, the dimensions will not need
+ * to be specified (except for the "DATA_TYPE* ARGOUT_ARRAY1"
+ * typemaps).  The IN_ARRAYs can be a numpy array or any sequence that
+ * can be converted to a numpy array of the specified type.  The
+ * INPLACE_ARRAYs must be numpy arrays of the appropriate type.  The
+ * ARGOUT_ARRAYs will be returned as new numpy arrays of the
+ * appropriate type.
+ *
+ * These typemaps can be applied to existing functions using the
+ * %apply directive.  For example:
+ *
+ *     %apply (double* IN_ARRAY1, int DIM1) {(double* series, int length)};
+ *     double prod(double* series, int length);
+ *
+ *     %apply (int DIM1, int DIM2, double* INPLACE_ARRAY2)
+ *           {(int rows, int cols, double* matrix        )};
+ *     void floor(int rows, int cols, double* matrix, double f);
+ *
+ *     %apply (double IN_ARRAY3[ANY][ANY][ANY])
+ *           {(double tensor[2][2][2]         )};
+ *     %apply (double ARGOUT_ARRAY3[ANY][ANY][ANY])
+ *           {(double low[2][2][2]                )};
+ *     %apply (double ARGOUT_ARRAY3[ANY][ANY][ANY])
+ *           {(double upp[2][2][2]                )};
+ *     void luSplit(double tensor[2][2][2],
+ *                  double low[2][2][2],
+ *                  double upp[2][2][2]    );
+ *
+ * or directly with
+ *
+ *     double prod(double* IN_ARRAY1, int DIM1);
+ *
+ *     void floor(int DIM1, int DIM2, double* INPLACE_ARRAY2, double f);
+ *
+ *     void luSplit(double IN_ARRAY3[ANY][ANY][ANY],
+ *                  double ARGOUT_ARRAY3[ANY][ANY][ANY],
+ *                  double ARGOUT_ARRAY3[ANY][ANY][ANY]);
+ */
+
+%define %numpy_typemaps(DATA_TYPE, DATA_TYPECODE, DIM_TYPE)
+
+/************************/
+/* Input Array Typemaps */
+/************************/
+
+/* Typemap suite for (DATA_TYPE IN_ARRAY1[ANY])
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DATA_TYPE IN_ARRAY1[ANY])
+{
+  $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DATA_TYPE IN_ARRAY1[ANY])
+  (PyArrayObject* array=NULL, int is_new_object=0)
+{
+  npy_intp size[1] = { $1_dim0 };
+  array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
+                                                   &is_new_object);
+  if (!array || !require_dimensions(array, 1) ||
+      !require_size(array, size, 1)) SWIG_fail;
+  $1 = ($1_ltype) array_data(array);
+}
+%typemap(freearg)
+  (DATA_TYPE IN_ARRAY1[ANY])
+{
+  if (is_new_object$argnum && array$argnum)
+    { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1)
+{
+  $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1)
+  (PyArrayObject* array=NULL, int is_new_object=0)
+{
+  npy_intp size[1] = { -1 };
+  array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
+                                                   &is_new_object);
+  if (!array || !require_dimensions(array, 1) ||
+      !require_size(array, size, 1)) SWIG_fail;
+  $1 = (DATA_TYPE*) array_data(array);
+  $2 = (DIM_TYPE) array_size(array,0);
+}
+%typemap(freearg)
+  (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1)
+{
+  if (is_new_object$argnum && array$argnum)
+    { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1)
+{
+  $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1)
+  (PyArrayObject* array=NULL, int is_new_object=0)
+{
+  npy_intp size[1] = {-1};
+  array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
+                                                   &is_new_object);
+  if (!array || !require_dimensions(array, 1) ||
+      !require_size(array, size, 1)) SWIG_fail;
+  $1 = (DIM_TYPE) array_size(array,0);
+  $2 = (DATA_TYPE*) array_data(array);
+}
+%typemap(freearg)
+  (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1)
+{
+  if (is_new_object$argnum && array$argnum)
+    { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DATA_TYPE IN_ARRAY2[ANY][ANY])
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DATA_TYPE IN_ARRAY2[ANY][ANY])
+{
+  $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DATA_TYPE IN_ARRAY2[ANY][ANY])
+  (PyArrayObject* array=NULL, int is_new_object=0)
+{
+  npy_intp size[2] = { $1_dim0, $1_dim1 };
+  array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
+                                                   &is_new_object);
+  if (!array || !require_dimensions(array, 2) ||
+      !require_size(array, size, 2)) SWIG_fail;
+  $1 = ($1_ltype) array_data(array);
+}
+%typemap(freearg)
+  (DATA_TYPE IN_ARRAY2[ANY][ANY])
+{
+  if (is_new_object$argnum && array$argnum)
+    { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+{
+  $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+  (PyArrayObject* array=NULL, int is_new_object=0)
+{
+  npy_intp size[2] = { -1, -1 };
+  array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
+                                                   &is_new_object);
+  if (!array || !require_dimensions(array, 2) ||
+      !require_size(array, size, 2)) SWIG_fail;
+  $1 = (DATA_TYPE*) array_data(array);
+  $2 = (DIM_TYPE) array_size(array,0);
+  $3 = (DIM_TYPE) array_size(array,1);
+}
+%typemap(freearg)
+  (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+{
+  if (is_new_object$argnum && array$argnum)
+    { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2)
+{
+  $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2)
+  (PyArrayObject* array=NULL, int is_new_object=0)
+{
+  npy_intp size[2] = { -1, -1 };
+  array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
+                                                   &is_new_object);
+  if (!array || !require_dimensions(array, 2) ||
+      !require_size(array, size, 2)) SWIG_fail;
+  $1 = (DIM_TYPE) array_size(array,0);
+  $2 = (DIM_TYPE) array_size(array,1);
+  $3 = (DATA_TYPE*) array_data(array);
+}
+%typemap(freearg)
+  (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2)
+{
+  if (is_new_object$argnum && array$argnum)
+    { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+{
+  $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+  (PyArrayObject* array=NULL, int is_new_object=0)
+{
+  npy_intp size[2] = { -1, -1 };
+  array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE,
+                                                &is_new_object);
+  if (!array || !require_dimensions(array, 2) ||
+      !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail;
+  $1 = (DATA_TYPE*) array_data(array);
+  $2 = (DIM_TYPE) array_size(array,0);
+  $3 = (DIM_TYPE) array_size(array,1);
+}
+%typemap(freearg)
+  (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+{
+  if (is_new_object$argnum && array$argnum)
+    { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2)
+{
+  $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2)
+  (PyArrayObject* array=NULL, int is_new_object=0)
+{
+  npy_intp size[2] = { -1, -1 };
+  array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
+                                                   &is_new_object);
+  if (!array || !require_dimensions(array, 2) ||
+      !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail;
+  $1 = (DIM_TYPE) array_size(array,0);
+  $2 = (DIM_TYPE) array_size(array,1);
+  $3 = (DATA_TYPE*) array_data(array);
+}
+%typemap(freearg)
+  (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2)
+{
+  if (is_new_object$argnum && array$argnum)
+    { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY])
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY])
+{
+  $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY])
+  (PyArrayObject* array=NULL, int is_new_object=0)
+{
+  npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 };
+  array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
+                                                   &is_new_object);
+  if (!array || !require_dimensions(array, 3) ||
+      !require_size(array, size, 3)) SWIG_fail;
+  $1 = ($1_ltype) array_data(array);
+}
+%typemap(freearg)
+  (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY])
+{
+  if (is_new_object$argnum && array$argnum)
+    { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2,
+ *                    DIM_TYPE DIM3)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+{
+  $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+  (PyArrayObject* array=NULL, int is_new_object=0)
+{
+  npy_intp size[3] = { -1, -1, -1 };
+  array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
+                                                   &is_new_object);
+  if (!array || !require_dimensions(array, 3) ||
+      !require_size(array, size, 3)) SWIG_fail;
+  $1 = (DATA_TYPE*) array_data(array);
+  $2 = (DIM_TYPE) array_size(array,0);
+  $3 = (DIM_TYPE) array_size(array,1);
+  $4 = (DIM_TYPE) array_size(array,2);
+}
+%typemap(freearg)
+  (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+{
+  if (is_new_object$argnum && array$argnum)
+    { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3,
+ *                    DATA_TYPE* IN_ARRAY3)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3)
+{
+  $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3)
+  (PyArrayObject* array=NULL, int is_new_object=0)
+{
+  npy_intp size[3] = { -1, -1, -1 };
+  array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
+                                                   &is_new_object);
+  if (!array || !require_dimensions(array, 3) ||
+      !require_size(array, size, 3)) SWIG_fail;
+  $1 = (DIM_TYPE) array_size(array,0);
+  $2 = (DIM_TYPE) array_size(array,1);
+  $3 = (DIM_TYPE) array_size(array,2);
+  $4 = (DATA_TYPE*) array_data(array);
+}
+%typemap(freearg)
+  (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3)
+{
+  if (is_new_object$argnum && array$argnum)
+    { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2,
+ *                    DIM_TYPE DIM3)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+{
+  $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+  (PyArrayObject* array=NULL, int is_new_object=0)
+{
+  npy_intp size[3] = { -1, -1, -1 };
+  array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE,
+                                                &is_new_object);
+  if (!array || !require_dimensions(array, 3) ||
+      !require_size(array, size, 3) | !require_fortran(array)) SWIG_fail;
+  $1 = (DATA_TYPE*) array_data(array);
+  $2 = (DIM_TYPE) array_size(array,0);
+  $3 = (DIM_TYPE) array_size(array,1);
+  $4 = (DIM_TYPE) array_size(array,2);
+}
+%typemap(freearg)
+  (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+{
+  if (is_new_object$argnum && array$argnum)
+    { Py_DECREF(array$argnum); }
+}
+
+/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3,
+ *                    DATA_TYPE* IN_FARRAY3)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3)
+{
+  $1 = is_array($input) || PySequence_Check($input);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3)
+  (PyArrayObject* array=NULL, int is_new_object=0)
+{
+  npy_intp size[3] = { -1, -1, -1 };
+  array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE,
+                                                   &is_new_object);
+  if (!array || !require_dimensions(array, 3) ||
+      !require_size(array, size, 3) || !require_fortran(array)) SWIG_fail;
+  $1 = (DIM_TYPE) array_size(array,0);
+  $2 = (DIM_TYPE) array_size(array,1);
+  $3 = (DIM_TYPE) array_size(array,2);
+  $4 = (DATA_TYPE*) array_data(array);
+}
+%typemap(freearg)
+  (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3)
+{
+  if (is_new_object$argnum && array$argnum)
+    { Py_DECREF(array$argnum); }
+}
+
+/***************************/
+/* In-Place Array Typemaps */
+/***************************/
+
+/* Typemap suite for (DATA_TYPE INPLACE_ARRAY1[ANY])
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DATA_TYPE INPLACE_ARRAY1[ANY])
+{
+  $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+                                                 DATA_TYPECODE);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DATA_TYPE INPLACE_ARRAY1[ANY])
+  (PyArrayObject* array=NULL)
+{
+  npy_intp size[1] = { $1_dim0 };
+  array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+  if (!array || !require_dimensions(array,1) || !require_size(array, size, 1) ||
+      !require_contiguous(array) || !require_native(array)) SWIG_fail;
+  $1 = ($1_ltype) array_data(array);
+}
+
+/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1)
+{
+  $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+                                                 DATA_TYPECODE);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1)
+  (PyArrayObject* array=NULL, int i=1)
+{
+  array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+  if (!array || !require_dimensions(array,1) || !require_contiguous(array)
+      || !require_native(array)) SWIG_fail;
+  $1 = (DATA_TYPE*) array_data(array);
+  $2 = 1;
+  for (i=0; i < array_numdims(array); ++i) $2 *= array_size(array,i);
+}
+
+/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1)
+{
+  $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+                                                 DATA_TYPECODE);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1)
+  (PyArrayObject* array=NULL, int i=0)
+{
+  array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+  if (!array || !require_dimensions(array,1) || !require_contiguous(array)
+      || !require_native(array)) SWIG_fail;
+  $1 = 1;
+  for (i=0; i < array_numdims(array); ++i) $1 *= array_size(array,i);
+  $2 = (DATA_TYPE*) array_data(array);
+}
+
+/* Typemap suite for (DATA_TYPE INPLACE_ARRAY2[ANY][ANY])
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DATA_TYPE INPLACE_ARRAY2[ANY][ANY])
+{
+  $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+                                                 DATA_TYPECODE);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DATA_TYPE INPLACE_ARRAY2[ANY][ANY])
+  (PyArrayObject* array=NULL)
+{
+  npy_intp size[2] = { $1_dim0, $1_dim1 };
+  array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+  if (!array || !require_dimensions(array,2) || !require_size(array, size, 2) ||
+      !require_contiguous(array) || !require_native(array)) SWIG_fail;
+  $1 = ($1_ltype) array_data(array);
+}
+
+/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+{
+  $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+                                                 DATA_TYPECODE);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+  (PyArrayObject* array=NULL)
+{
+  array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+  if (!array || !require_dimensions(array,2) || !require_contiguous(array)
+      || !require_native(array)) SWIG_fail;
+  $1 = (DATA_TYPE*) array_data(array);
+  $2 = (DIM_TYPE) array_size(array,0);
+  $3 = (DIM_TYPE) array_size(array,1);
+}
+
+/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2)
+{
+  $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+                                                 DATA_TYPECODE);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2)
+  (PyArrayObject* array=NULL)
+{
+  array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+  if (!array || !require_dimensions(array,2) || !require_contiguous(array) ||
+      !require_native(array)) SWIG_fail;
+  $1 = (DIM_TYPE) array_size(array,0);
+  $2 = (DIM_TYPE) array_size(array,1);
+  $3 = (DATA_TYPE*) array_data(array);
+}
+
+/* Typemap suite for (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+{
+  $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+                                                 DATA_TYPECODE);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2)
+  (PyArrayObject* array=NULL)
+{
+  array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+  if (!array || !require_dimensions(array,2) || !require_contiguous(array)
+      || !require_native(array) || !require_fortran(array)) SWIG_fail;
+  $1 = (DATA_TYPE*) array_data(array);
+  $2 = (DIM_TYPE) array_size(array,0);
+  $3 = (DIM_TYPE) array_size(array,1);
+}
+
+/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2)
+{
+  $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+                                                 DATA_TYPECODE);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2)
+  (PyArrayObject* array=NULL)
+{
+  array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+  if (!array || !require_dimensions(array,2) || !require_contiguous(array) ||
+      !require_native(array) || !require_fortran(array)) SWIG_fail;
+  $1 = (DIM_TYPE) array_size(array,0);
+  $2 = (DIM_TYPE) array_size(array,1);
+  $3 = (DATA_TYPE*) array_data(array);
+}
+
+/* Typemap suite for (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY])
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY])
+{
+  $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+                                                 DATA_TYPECODE);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY])
+  (PyArrayObject* array=NULL)
+{
+  npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 };
+  array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+  if (!array || !require_dimensions(array,3) || !require_size(array, size, 3) ||
+      !require_contiguous(array) || !require_native(array)) SWIG_fail;
+  $1 = ($1_ltype) array_data(array);
+}
+
+/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2,
+ *                    DIM_TYPE DIM3)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+{
+  $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+                                                 DATA_TYPECODE);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+  (PyArrayObject* array=NULL)
+{
+  array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+  if (!array || !require_dimensions(array,3) || !require_contiguous(array) ||
+      !require_native(array)) SWIG_fail;
+  $1 = (DATA_TYPE*) array_data(array);
+  $2 = (DIM_TYPE) array_size(array,0);
+  $3 = (DIM_TYPE) array_size(array,1);
+  $4 = (DIM_TYPE) array_size(array,2);
+}
+
+/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3,
+ *                    DATA_TYPE* INPLACE_ARRAY3)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3)
+{
+  $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+                                                 DATA_TYPECODE);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3)
+  (PyArrayObject* array=NULL)
+{
+  array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+  if (!array || !require_dimensions(array,3) || !require_contiguous(array)
+      || !require_native(array)) SWIG_fail;
+  $1 = (DIM_TYPE) array_size(array,0);
+  $2 = (DIM_TYPE) array_size(array,1);
+  $3 = (DIM_TYPE) array_size(array,2);
+  $4 = (DATA_TYPE*) array_data(array);
+}
+
+/* Typemap suite for (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2,
+ *                    DIM_TYPE DIM3)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+{
+  $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+                                                 DATA_TYPECODE);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3)
+  (PyArrayObject* array=NULL)
+{
+  array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+  if (!array || !require_dimensions(array,3) || !require_contiguous(array) ||
+      !require_native(array) || !require_fortran(array)) SWIG_fail;
+  $1 = (DATA_TYPE*) array_data(array);
+  $2 = (DIM_TYPE) array_size(array,0);
+  $3 = (DIM_TYPE) array_size(array,1);
+  $4 = (DIM_TYPE) array_size(array,2);
+}
+
+/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3,
+ *                    DATA_TYPE* INPLACE_FARRAY3)
+ */
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
+           fragment="NumPy_Macros")
+  (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3)
+{
+  $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
+                                                 DATA_TYPECODE);
+}
+%typemap(in,
+         fragment="NumPy_Fragments")
+  (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3)
+  (PyArrayObject* array=NULL)
+{
+  array = obj_to_array_no_conversion($input, DATA_TYPECODE);
+  if (!array || !require_dimensions(array,3) || !require_contiguous(array)
+      || !require_native(array) || !require_fortran(array)) SWIG_fail;
+  $1 = (DIM_TYPE) array_size(array,0);
+  $2 = (DIM_TYPE) array_size(array,1);
+  $3 = (DIM_TYPE) array_size(array,2);
+  $4 = (DATA_TYPE*) array_data(array);
+}
+
+/*************************/
+/* Argout Array Typemaps */
+/*************************/
+
+/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY1[ANY])
+ */
+%typemap(in,numinputs=0,
+         fragment="NumPy_Backward_Compatibility,NumPy_Macros")
+  (DATA_TYPE ARGOUT_ARRAY1[ANY])
+  (PyObject * array = NULL)
+{
+  npy_intp dims[1] = { $1_dim0 };
+  array = PyArray_SimpleNew(1, dims, DATA_TYPECODE);
+  if (!array) SWIG_fail;
+  $1 = ($1_ltype) array_data(array);
+}
+%typemap(argout)
+  (DATA_TYPE ARGOUT_ARRAY1[ANY])
+{
+  $result = SWIG_Python_AppendOutput($result,array$argnum);
+}
+
+/* Typemap suite for (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1)
+ */
+%typemap(in,numinputs=1,
+         fragment="NumPy_Fragments")
+  (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1)
+  (PyObject * array = NULL)
+{
+  npy_intp dims[1];
+  if (!PyInt_Check($input))
+  {
+    char* typestring = pytype_string($input);
+    PyErr_Format(PyExc_TypeError,
+                 "Int dimension expected.  '%s' given.",
+                 typestring);
+    SWIG_fail;
+  }
+  $2 = (DIM_TYPE) PyInt_AsLong($input);
+  dims[0] = (npy_intp) $2;
+  array = PyArray_SimpleNew(1, dims, DATA_TYPECODE);
+  if (!array) SWIG_fail;
+  $1 = (DATA_TYPE*) array_data(array);
+}
+%typemap(argout)
+  (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1)
+{
+  $result = SWIG_Python_AppendOutput($result,array$argnum);
+}
+
+/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1)
+ */
+%typemap(in,numinputs=1,
+         fragment="NumPy_Fragments")
+  (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1)
+  (PyObject * array = NULL)
+{
+  npy_intp dims[1];
+  if (!PyInt_Check($input))
+  {
+    char* typestring = pytype_string($input);
+    PyErr_Format(PyExc_TypeError,
+                 "Int dimension expected.  '%s' given.",
+                 typestring);
+    SWIG_fail;
+  }
+  $1 = (DIM_TYPE) PyInt_AsLong($input);
+  dims[0] = (npy_intp) $1;
+  array = PyArray_SimpleNew(1, dims, DATA_TYPECODE);
+  if (!array) SWIG_fail;
+  $2 = (DATA_TYPE*) array_data(array);
+}
+%typemap(argout)
+  (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1)
+{
+  $result = SWIG_Python_AppendOutput($result,array$argnum);
+}
+
+/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY])
+ */
+%typemap(in,numinputs=0,
+         fragment="NumPy_Backward_Compatibility,NumPy_Macros")
+  (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY])
+  (PyObject * array = NULL)
+{
+  npy_intp dims[2] = { $1_dim0, $1_dim1 };
+  array = PyArray_SimpleNew(2, dims, DATA_TYPECODE);
+  if (!array) SWIG_fail;
+  $1 = ($1_ltype) array_data(array);
+}
+%typemap(argout)
+  (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY])
+{
+  $result = SWIG_Python_AppendOutput($result,array$argnum);
+}
+
+/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY])
+ */
+%typemap(in,numinputs=0,
+         fragment="NumPy_Backward_Compatibility,NumPy_Macros")
+  (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY])
+  (PyObject * array = NULL)
+{
+  npy_intp dims[3] = { $1_dim0, $1_dim1, $1_dim2 };
+  array = PyArray_SimpleNew(3, dims, DATA_TYPECODE);
+  if (!array) SWIG_fail;
+  $1 = ($1_ltype) array_data(array);
+}
+%typemap(argout)
+  (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY])
+{
+  $result = SWIG_Python_AppendOutput($result,array$argnum);
+}
+
+/*****************************/
+/* Argoutview Array Typemaps */
+/*****************************/
+
+/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1)
+ */
+%typemap(in,numinputs=0)
+  (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1    )
+  (DATA_TYPE*  data_temp        , DIM_TYPE  dim_temp)
+{
+  $1 = &data_temp;
+  $2 = &dim_temp;
+}
+%typemap(argout,
+         fragment="NumPy_Backward_Compatibility")
+  (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1)
+{
+  npy_intp dims[1] = { *$2 };
+  PyObject * array = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$1));
+  if (!array) SWIG_fail;
+  $result = SWIG_Python_AppendOutput($result,array);
+}
+
+/* Typemap suite for (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1)
+ */
+%typemap(in,numinputs=0)
+  (DIM_TYPE* DIM1    , DATA_TYPE** ARGOUTVIEW_ARRAY1)
+  (DIM_TYPE  dim_temp, DATA_TYPE*  data_temp        )
+{
+  $1 = &dim_temp;
+  $2 = &data_temp;
+}
+%typemap(argout,
+         fragment="NumPy_Backward_Compatibility")
+  (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1)
+{
+  npy_intp dims[1] = { *$1 };
+  PyObject * array = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$2));
+  if (!array) SWIG_fail;
+  $result = SWIG_Python_AppendOutput($result,array);
+}
+
+/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2)
+ */
+%typemap(in,numinputs=0)
+  (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1     , DIM_TYPE* DIM2     )
+  (DATA_TYPE*  data_temp        , DIM_TYPE  dim1_temp, DIM_TYPE  dim2_temp)
+{
+  $1 = &data_temp;
+  $2 = &dim1_temp;
+  $3 = &dim2_temp;
+}
+%typemap(argout,
+         fragment="NumPy_Backward_Compatibility")
+  (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2)
+{
+  npy_intp dims[2] = { *$2, *$3 };
+  PyObject * array = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1));
+  if (!array) SWIG_fail;
+  $result = SWIG_Python_AppendOutput($result,array);
+}
+
+/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2)
+ */
+%typemap(in,numinputs=0)
+  (DIM_TYPE* DIM1     , DIM_TYPE* DIM2     , DATA_TYPE** ARGOUTVIEW_ARRAY2)
+  (DIM_TYPE  dim1_temp, DIM_TYPE  dim2_temp, DATA_TYPE*  data_temp        )
+{
+  $1 = &dim1_temp;
+  $2 = &dim2_temp;
+  $3 = &data_temp;
+}
+%typemap(argout,
+         fragment="NumPy_Backward_Compatibility")
+  (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2)
+{
+  npy_intp dims[2] = { *$1, *$2 };
+  PyObject * array = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3));
+  if (!array) SWIG_fail;
+  $result = SWIG_Python_AppendOutput($result,array);
+}
+
+/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2)
+ */
+%typemap(in,numinputs=0)
+  (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1     , DIM_TYPE* DIM2     )
+  (DATA_TYPE*  data_temp        , DIM_TYPE  dim1_temp, DIM_TYPE  dim2_temp)
+{
+  $1 = &data_temp;
+  $2 = &dim1_temp;
+  $3 = &dim2_temp;
+}
+%typemap(argout,
+         fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements")
+  (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2)
+{
+  npy_intp dims[2] = { *$2, *$3 };
+  PyObject * obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1));
+  PyArrayObject * array = (PyArrayObject*) obj;
+  if (!array || !require_fortran(array)) SWIG_fail;
+  $result = SWIG_Python_AppendOutput($result,obj);
+}
+
+/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2)
+ */
+%typemap(in,numinputs=0)
+  (DIM_TYPE* DIM1     , DIM_TYPE* DIM2     , DATA_TYPE** ARGOUTVIEW_FARRAY2)
+  (DIM_TYPE  dim1_temp, DIM_TYPE  dim2_temp, DATA_TYPE*  data_temp        )
+{
+  $1 = &dim1_temp;
+  $2 = &dim2_temp;
+  $3 = &data_temp;
+}
+%typemap(argout,
+         fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements")
+  (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2)
+{
+  npy_intp dims[2] = { *$1, *$2 };
+  PyObject * obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3));
+  PyArrayObject * array = (PyArrayObject*) obj;
+  if (!array || !require_fortran(array)) SWIG_fail;
+  $result = SWIG_Python_AppendOutput($result,obj);
+}
+
+/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2,
+                      DIM_TYPE* DIM3)
+ */
+%typemap(in,numinputs=0)
+  (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3)
+  (DATA_TYPE* data_temp, DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp)
+{
+  $1 = &data_temp;
+  $2 = &dim1_temp;
+  $3 = &dim2_temp;
+  $4 = &dim3_temp;
+}
+%typemap(argout,
+         fragment="NumPy_Backward_Compatibility")
+  (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3)
+{
+  npy_intp dims[3] = { *$2, *$3, *$4 };
+  PyObject * array = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1));
+  if (!array) SWIG_fail;
+  $result = SWIG_Python_AppendOutput($result,array);
+}
+
+/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3,
+                      DATA_TYPE** ARGOUTVIEW_ARRAY3)
+ */
+%typemap(in,numinputs=0)
+  (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3)
+  (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp)
+{
+  $1 = &dim1_temp;
+  $2 = &dim2_temp;
+  $3 = &dim3_temp;
+  $4 = &data_temp;
+}
+%typemap(argout,
+         fragment="NumPy_Backward_Compatibility")
+  (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3)
+{
+  npy_intp dims[3] = { *$1, *$2, *$3 };
+  PyObject * array = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$3));
+  if (!array) SWIG_fail;
+  $result = SWIG_Python_AppendOutput($result,array);
+}
+
+/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2,
+                      DIM_TYPE* DIM3)
+ */
+%typemap(in,numinputs=0)
+  (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3)
+  (DATA_TYPE* data_temp, DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp)
+{
+  $1 = &data_temp;
+  $2 = &dim1_temp;
+  $3 = &dim2_temp;
+  $4 = &dim3_temp;
+}
+%typemap(argout,
+         fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements")
+  (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3)
+{
+  npy_intp dims[3] = { *$2, *$3, *$4 };
+  PyObject * obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1));
+  PyArrayObject * array = (PyArrayObject*) obj;
+  if (!array || require_fortran(array)) SWIG_fail;
+  $result = SWIG_Python_AppendOutput($result,obj);
+}
+
+/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3,
+                      DATA_TYPE** ARGOUTVIEW_FARRAY3)
+ */
+%typemap(in,numinputs=0)
+  (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3)
+  (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp)
+{
+  $1 = &dim1_temp;
+  $2 = &dim2_temp;
+  $3 = &dim3_temp;
+  $4 = &data_temp;
+}
+%typemap(argout,
+         fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements")
+  (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3)
+{
+  npy_intp dims[3] = { *$1, *$2, *$3 };
+  PyObject * obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$3));
+  PyArrayObject * array = (PyArrayObject*) obj;
+  if (!array || require_fortran(array)) SWIG_fail;
+  $result = SWIG_Python_AppendOutput($result,obj);
+}
+
+%enddef    /* %numpy_typemaps() macro */
+/* *************************************************************** */
+
+/* Concrete instances of the %numpy_typemaps() macro: Each invocation
+ * below applies all of the typemaps above to the specified data type.
+ */
+%numpy_typemaps(signed char       , NPY_BYTE     , int)
+%numpy_typemaps(unsigned char     , NPY_UBYTE    , int)
+%numpy_typemaps(short             , NPY_SHORT    , int)
+%numpy_typemaps(unsigned short    , NPY_USHORT   , int)
+%numpy_typemaps(int               , NPY_INT      , int)
+%numpy_typemaps(unsigned int      , NPY_UINT     , int)
+%numpy_typemaps(long              , NPY_LONG     , int)
+%numpy_typemaps(unsigned long     , NPY_ULONG    , int)
+%numpy_typemaps(long long         , NPY_LONGLONG , int)
+%numpy_typemaps(unsigned long long, NPY_ULONGLONG, int)
+%numpy_typemaps(float             , NPY_FLOAT    , int)
+%numpy_typemaps(double            , NPY_DOUBLE   , int)
+
+/* ***************************************************************
+ * The follow macro expansion does not work, because C++ bool is 4
+ * bytes and NPY_BOOL is 1 byte
+ *
+ *    %numpy_typemaps(bool, NPY_BOOL, int)
+ */
+
+/* ***************************************************************
+ * On my Mac, I get the following warning for this macro expansion:
+ * 'swig/python detected a memory leak of type 'long double *', no destructor found.'
+ *
+ *    %numpy_typemaps(long double, NPY_LONGDOUBLE, int)
+ */
+
+/* ***************************************************************
+ * Swig complains about a syntax error for the following macro
+ * expansions:
+ *
+ *    %numpy_typemaps(complex float,  NPY_CFLOAT , int)
+ *
+ *    %numpy_typemaps(complex double, NPY_CDOUBLE, int)
+ *
+ *    %numpy_typemaps(complex long double, NPY_CLONGDOUBLE, int)
+ */
+
+#endif /* SWIGPYTHON */
diff --git a/lang/sed_rules b/lang/sed_rules
new file mode 100644
index 0000000..8ee5fb6
--- /dev/null
+++ b/lang/sed_rules
@@ -0,0 +1,13 @@
+1,19d
+s/MGL_EXPORT//g
+s/mglDataA/mglData/g
+/SWIG/,/endif/ { s/.*//g }
+s/^.*---.*$//g
+s/^#include.*$//g
+s/^#define.*$//g
+s/^.*public mglData$//g
+s/^#ifndef _MGL_DATA_H_.*$//g
+s/^#ifndef _MGL_H_.*$//g
+s/^#ifdef __cplusplus.*$//g
+/^\s*$/d
+N;$!P;$!D;$d
diff --git a/lang/type.i b/lang/type.i
new file mode 100644
index 0000000..721e227
--- /dev/null
+++ b/lang/type.i
@@ -0,0 +1,101 @@
+/***************************************************************************
+ * type.i is part of Math Graphic Library
+ * Copyright (C) 2007-2012 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include "mgl2/config.h"
+#if MGL_USE_DOUBLE
+typedef double mreal;
+#else
+typedef float mreal;
+#endif
+//-----------------------------------------------------------------------------
+const mreal All = -1;
+const mreal Pi = M_PI;
+const mreal NaN = NAN;
+const mreal Inf = INFINITY;
+const mreal mgl_min_a = 1./256;
+//-----------------------------------------------------------------------------
+/// Class for point in 3D space
+struct mglPoint
+{
+	mreal x,y,z,c;
+	mglPoint(mreal X=0,mreal Y=0,mreal Z=0,mreal C=0){x=X;y=Y;z=Z;c=C;}
+	inline bool IsNAN()		{	return (x!=x || y!=y || z!=z || c!=c);	}
+	inline mreal val(int i)	{	return (i<2 ? (i==0 ? x:y) : (i==2 ? z:c));	}
+	inline mreal norm()		{	return sqrt(x*x+y*y+z*z);	}
+	inline void Normalize()	{	mreal v=norm();	x/=v;	y/=v;	z/=v;	}
+
+	inline void operator+=(const mglPoint &a)	{	x+=a.x;	y+=a.y;	z+=a.z;	c+=a.c;	}
+	inline void operator-=(const mglPoint &a)	{	x-=a.x;	y-=a.y;	z-=a.z;	c-=a.c;	}
+	inline void operator+=(mreal a)	{	x+=a;	y+=a;	z+=a;	}
+	inline void operator-=(mreal a)	{	x-=a;	y-=a;	z-=a;	}
+	inline void operator*=(mreal a)	{	x*=a;	y*=a;	z*=a;	}
+	inline void operator/=(mreal a)	{	x/=a;	y/=a;	z/=a;	}
+};
+//-----------------------------------------------------------------------------
+/// Class for RGBA color
+struct mglColor
+{
+	float r;	///< Red component of color
+	float g;	///< Green component of color
+	float b;	///< Blue component of color
+	float a;	///< Alpha component of color
+
+	/// Constructor for RGB components manualy
+	mglColor(float R,float G,float B, float A=1){	r=R;	g=G;	b=B;	a=A;	}
+	/// Constructor set default color
+	mglColor()		{	r=g=b=0;	a=1;	}
+	/// Constructor set color from character id
+	mglColor(char c, float bright=1)		{	Set(c,bright);	}
+	/// Set color as Red, Green, Blue values
+	void Set(float R,float G,float B,float A=1)	{	r=R;	g=G;	b=B;	a=A;	}
+	/// Set color as Red, Green, Blue values
+	void Set(mglColor c, float bright=1)
+	{
+		if(bright<0)	bright=0;	if(bright>2.f)	bright=2.f;
+		r = bright<=1 ? c.r*bright : 1 - (1-c.r)*(2-bright);
+		g = bright<=1 ? c.g*bright : 1 - (1-c.g)*(2-bright);
+		b = bright<=1 ? c.b*bright : 1 - (1-c.b)*(2-bright);	a = 1;
+	}
+	/// Check if color is valid
+	inline bool Valid()
+	{	return (r>=0 && r<=1 && g>=0 && g<=1 && b>=0 && b<=1 && a>=0 && a<=1);	}
+	/// Get maximal spectral component
+	inline float Norm()
+	{	return r>g ? r : (g>b ? g : b);	}
+	inline float NormS()
+	{	return r*r+g*g+b*b;	}
+	/// Set color from symbolic id
+	inline void Set(char p, float bright=1)
+	{
+		float rgb[3];	mgl_chrrgb(p,rgb);
+		Set(mglColor(rgb[0],rgb[1],rgb[2]),bright);
+	}
+	/// Copy color from other one
+	inline bool operator==(const mglColor &c) const
+	{	return !memcmp(this, &c, sizeof(mglColor));	}
+	inline bool operator!=(const mglColor &c) const
+	{	return memcmp(this, &c, sizeof(mglColor));		}
+	inline bool operator<(const mglColor &c) const
+	{	return memcmp(this, &c, sizeof(mglColor))<0;	}
+	// transparency still the same
+	inline void operator*=(float v)				{	r*=v;	g*=v;	b*=v;	a*=v;	}
+	inline void operator+=(const mglColor &c)	{	r+=c.r;	g+=c.g;	b+=c.b;	a+=c.a;	}
+	inline void operator-=(const mglColor &c)	{	r-=c.r;	g-=c.g;	b-=c.b;	a-=c.a;	}
+};
+//-----------------------------------------------------------------------------
diff --git a/mathgl-2x.cbp b/mathgl-2x.cbp
new file mode 100644
index 0000000..40ea8f6
--- /dev/null
+++ b/mathgl-2x.cbp
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+	<FileVersion major="1" minor="6" />
+	<Project>
+		<Option title="mathgl-2x" />
+		<Option pch_mode="2" />
+		<Option compiler="gcc" />
+		<Build>
+			<Target title="Release">
+				<Option output="bin/Release/mathgl-2x" prefix_auto="1" extension_auto="1" />
+				<Option working_dir="bin/" />
+				<Option object_output="obj/Release/" />
+				<Option type="1" />
+				<Option compiler="gcc" />
+				<Option parameters="-test" />
+				<Compiler>
+					<Add option="-I include/" />
+				</Compiler>
+			</Target>
+		</Build>
+		<Compiler>
+			<Add option="-Wall" />
+			<Add option="-pg" />
+			<Add option="-g" />
+			<Add option="-fexceptions" />
+			<Add option="-DMGL_SRC" />
+		</Compiler>
+		<Linker>
+			<Add option="-pg" />
+			<Add option="-pg -lgsl -lgslcblas" />
+			<Add option="-lpng -ljpeg -lgif -lhpdf" />
+			<Add option="-lhdf5 -lmfhdf -ldf -lmfhdf" />
+		</Linker>
+		<Unit filename="build/include/mgl2/config.h" />
+		<Unit filename="examples/full_test.cpp" />
+		<Unit filename="examples/samples.cpp" />
+		<Unit filename="examples/wnd_samples.cpp" />
+		<Unit filename="include/mgl2/addon.h" />
+		<Unit filename="include/mgl2/base.h" />
+		<Unit filename="include/mgl2/base_cf.h" />
+		<Unit filename="include/mgl2/canvas.h" />
+		<Unit filename="include/mgl2/canvas_cf.h" />
+		<Unit filename="include/mgl2/canvas_wnd.h" />
+		<Unit filename="include/mgl2/cont.h" />
+		<Unit filename="include/mgl2/data.h" />
+		<Unit filename="include/mgl2/data_cf.h" />
+		<Unit filename="include/mgl2/datac.h" />
+		<Unit filename="include/mgl2/datac_cf.h" />
+		<Unit filename="include/mgl2/define.h" />
+		<Unit filename="include/mgl2/eval.h" />
+		<Unit filename="include/mgl2/evalc.h" />
+		<Unit filename="include/mgl2/fit.h" />
+		<Unit filename="include/mgl2/fltk.h" />
+		<Unit filename="include/mgl2/font.h" />
+		<Unit filename="include/mgl2/glut.h" />
+		<Unit filename="include/mgl2/mgl.h" />
+		<Unit filename="include/mgl2/mgl_cf.h" />
+		<Unit filename="include/mgl2/mpi.h" />
+		<Unit filename="include/mgl2/opengl.h" />
+		<Unit filename="include/mgl2/other.h" />
+		<Unit filename="include/mgl2/parser.h" />
+		<Unit filename="include/mgl2/plot.h" />
+		<Unit filename="include/mgl2/prim.h" />
+		<Unit filename="include/mgl2/qmathgl.h" />
+		<Unit filename="include/mgl2/qt.h" />
+		<Unit filename="include/mgl2/surf.h" />
+		<Unit filename="include/mgl2/type.h" />
+		<Unit filename="include/mgl2/vect.h" />
+		<Unit filename="include/mgl2/volume.h" />
+		<Unit filename="include/mgl2/window.h" />
+		<Unit filename="include/mgl2/wnd.h" />
+		<Unit filename="include/mgl2/wx.h" />
+		<Unit filename="src/addon.cpp" />
+		<Unit filename="src/axis.cpp" />
+		<Unit filename="src/base.cpp" />
+		<Unit filename="src/base_cf.cpp" />
+		<Unit filename="src/canvas.cpp" />
+		<Unit filename="src/canvas_cf.cpp" />
+		<Unit filename="src/complex.cpp" />
+		<Unit filename="src/complex_io.cpp" />
+		<Unit filename="src/cont.cpp" />
+		<Unit filename="src/crust.cpp" />
+		<Unit filename="src/data.cpp" />
+		<Unit filename="src/data_io.cpp" />
+		<Unit filename="src/data_new.cpp" />
+		<Unit filename="src/data_png.cpp" />
+		<Unit filename="src/def_font.cpp" />
+		<Unit filename="src/eval.cpp" />
+		<Unit filename="src/evalc.cpp" />
+		<Unit filename="src/evalp.cpp" />
+		<Unit filename="src/exec.cpp" />
+		<Unit filename="src/export.cpp" />
+		<Unit filename="src/export_2d.cpp" />
+		<Unit filename="src/export_3d.cpp" />
+		<Unit filename="src/fft.cpp" />
+		<Unit filename="src/fit.cpp" />
+		<Unit filename="src/font.cpp" />
+		<Unit filename="src/obj.cpp" />
+		<Unit filename="src/other.cpp" />
+		<Unit filename="src/parser.cpp" />
+		<Unit filename="src/pde.cpp" />
+		<Unit filename="src/pixel.cpp" />
+		<Unit filename="src/plot.cpp" />
+		<Unit filename="src/prc.cpp" />
+		<Unit filename="src/prc/PRC.h" />
+		<Unit filename="src/prc/PRCbitStream.cc" />
+		<Unit filename="src/prc/PRCbitStream.h" />
+		<Unit filename="src/prc/PRCdouble.cc" />
+		<Unit filename="src/prc/PRCdouble.h" />
+		<Unit filename="src/prc/oPRCFile.cc" />
+		<Unit filename="src/prc/oPRCFile.h" />
+		<Unit filename="src/prc/writePRC.cc" />
+		<Unit filename="src/prc/writePRC.h" />
+		<Unit filename="src/prim.cpp" />
+		<Unit filename="src/s_hull/s_hull_pro.cpp" />
+		<Unit filename="src/s_hull/s_hull_pro.h" />
+		<Unit filename="src/surf.cpp" />
+		<Unit filename="src/tex_table.cpp" />
+		<Unit filename="src/vect.cpp" />
+		<Unit filename="src/volume.cpp" />
+		<Unit filename="src/window.cpp" />
+		<Extensions>
+			<code_completion />
+			<envvars />
+			<debugger />
+			<lib_finder disable_auto="1" />
+		</Extensions>
+	</Project>
+</CodeBlocks_project_file>
diff --git a/mathgl_en.po b/mathgl_en.po
new file mode 100644
index 0000000..159df64
--- /dev/null
+++ b/mathgl_en.po
@@ -0,0 +1,6307 @@
+#: mgllab/mgllab.cpp:417
+#, c-format
+msgid ""
+"\t-1 str       set str as argument $1 for script\n"
+"\t...          ...\n"
+"\t-9 str       set str as argument $9 for script\n"
+"\t-L loc       set locale to loc\n"
+"\t-h           print this message\n"
+msgstr ""
+
+#: utils/mglconv.cpp:87
+#, c-format
+msgid ""
+"\t-1 str       set str as argument $1 for script\n"
+"\t...          ...\n"
+"\t-9 str       set str as argument $9 for script\n"
+"\t-L loc       set locale to loc\n"
+"\t-s fname     set MGL script for setting up the plot\n"
+"\t-S val       set scaling factor for images\n"
+"\t-q val       set quality for output (val=0...9)\n"
+"\t-g val       set gray-scale mode (val=0|1)\n"
+"\t-v val       set variant of arguments\n"
+"\t-o name      set output file name\n"
+"\t-n           no default output (script should save results by itself)\n"
+"\t-A val       add animation value val\n"
+"\t-C n1:n2:dn  add animation value in range [n1,n2] with step dn\n"
+"\t-C n1:n2     add animation value in range [n1,n2] with step 1\n"
+"\t-            get script from standard input\n"
+"\t-h           print this message\n"
+msgstr ""
+
+#: utils/mglview.cpp:71
+#, c-format
+msgid ""
+"\t-1 str       set str as argument $1 for script\n"
+"\t...          ...\n"
+"\t-9 str       set str as argument $9 for script\n"
+"\t-g val       set gray-scale mode (val=0|1)\n"
+"\t-v val       set variant of arguments\n"
+"\t-s opt       set MGL script for setting up the plot\n"
+"\t-L loc       set locale to loc\n"
+"\t-            get script from standard input\n"
+"\t-h           print this message\n"
+msgstr ""
+
+#: widgets/qt.cpp:859
+msgid ""
+"\n"
+"(c) Alexey Balakin, 2007\n"
+"http://mathgl.sourceforge.net/"
+msgstr ""
+
+#: src/parser.cpp:1010
+#, c-format
+msgid ""
+"\n"
+"Change temporary data in line %ld"
+msgstr ""
+
+#: src/parser.cpp:1008
+#, c-format
+msgid ""
+"\n"
+"String too long in line %ld"
+msgstr ""
+
+#: src/parser.cpp:1009
+#, c-format
+msgid ""
+"\n"
+"Unbalanced ' in line %ld"
+msgstr ""
+
+#: src/parser.cpp:1006
+#, c-format
+msgid ""
+"\n"
+"Wrong argument(s) in line %ld"
+msgstr ""
+
+#: src/parser.cpp:1007
+#, c-format
+msgid ""
+"\n"
+"Wrong command in line %ld"
+msgstr ""
+
+#: udav/mem_pnl.cpp:136 udav/dat_pnl.cpp:153
+msgid " - UDAV preview"
+msgstr ""
+
+#: udav/dat_pnl.cpp:152
+msgid " - UDAV variable"
+msgstr ""
+
+#. o = new Fl_Button(420, 400, 90, 25, _(" Refresh"));	o->callback(mem_update_cb,w);
+#. o->image(img_update);	o->align(FL_ALIGN_IMAGE_NEXT_TO_TEXT);
+#. o->tooltip(_("Refresh list of variables."));
+#: mgllab/help.cpp:176
+msgid " Del.all"
+msgstr ""
+
+#: mgllab/help.cpp:164
+msgid " Delete"
+msgstr ""
+
+#: mgllab/help.cpp:158
+msgid " Edit"
+msgstr ""
+
+#: mgllab/help.cpp:161
+msgid " Info"
+msgstr ""
+
+#: mgllab/help.cpp:167
+msgid " New"
+msgstr ""
+
+#: mgllab/help.cpp:170
+msgid " Save"
+msgstr ""
+
+#: mgllab/mgllab.cpp:227
+msgid " Yes "
+msgstr ""
+
+#: udav/plot_pnl.cpp:191
+#, c-format
+msgid "%d - %d of %d"
+msgstr ""
+
+#. :
+#: udav/style_dlg.cpp:316 mgllab/dialogs.cpp:208
+msgid "' ' none"
+msgstr ""
+
+#: udav/style_dlg.cpp:397
+msgid "'#*' Y-sign"
+msgstr ""
+
+#: udav/style_dlg.cpp:398
+msgid "'#+' squared plus"
+msgstr ""
+
+#: udav/style_dlg.cpp:396
+msgid "'#.' circled dot"
+msgstr ""
+
+#: udav/style_dlg.cpp:405
+msgid "'#<' solid triangle left"
+msgstr ""
+
+#: udav/style_dlg.cpp:406
+msgid "'#>' solid triangle right"
+msgstr ""
+
+#: udav/style_dlg.cpp:404
+msgid "'#^' solid triangle up"
+msgstr ""
+
+#: udav/style_dlg.cpp:402
+msgid "'#d' solid rhomb"
+msgstr ""
+
+#: udav/style_dlg.cpp:407
+msgid "'#o' solid circle"
+msgstr ""
+
+#: udav/style_dlg.cpp:401
+msgid "'#s' solid square"
+msgstr ""
+
+#: udav/style_dlg.cpp:403
+msgid "'#v' solid triangle down"
+msgstr ""
+
+#: udav/style_dlg.cpp:399
+msgid "'#x' squared cross"
+msgstr ""
+
+#. D
+#: udav/style_dlg.cpp:354 mgllab/dialogs.cpp:245
+msgid "'*' cross"
+msgstr ""
+
+#.
+#: udav/style_dlg.cpp:387 mgllab/dialogs.cpp:215
+msgid "'*' star"
+msgstr ""
+
+#. o
+#. -
+#: udav/style_dlg.cpp:341 udav/style_dlg.cpp:385 mgllab/dialogs.cpp:217
+#: mgllab/dialogs.cpp:232
+msgid "'+' plus"
+msgstr ""
+
+#.
+#: udav/style_dlg.cpp:340 mgllab/dialogs.cpp:231
+msgid "'-' lines"
+msgstr ""
+
+#. "-|;=ji: "
+#: udav/style_dlg.cpp:309 mgllab/dialogs.cpp:201
+msgid "'-' solid"
+msgstr ""
+
+#. d
+#: udav/style_dlg.cpp:384 mgllab/dialogs.cpp:221
+msgid "'.' dot"
+msgstr ""
+
+#. =
+#: udav/style_dlg.cpp:315 mgllab/dialogs.cpp:207
+msgid "':' dots"
+msgstr ""
+
+#. j
+#. =
+#: udav/style_dlg.cpp:311 udav/style_dlg.cpp:343 mgllab/dialogs.cpp:204
+#: mgllab/dialogs.cpp:234
+msgid "';' dash"
+msgstr ""
+
+#. ~
+#: udav/style_dlg.cpp:349 mgllab/dialogs.cpp:241
+msgid "'<' left sign"
+msgstr ""
+
+#. v
+#: udav/style_dlg.cpp:392 mgllab/dialogs.cpp:224
+msgid "'<' triangle left"
+msgstr ""
+
+#. +
+#: udav/style_dlg.cpp:342 mgllab/dialogs.cpp:233
+msgid "'=' double lines"
+msgstr ""
+
+#. i
+#: udav/style_dlg.cpp:312 mgllab/dialogs.cpp:206
+msgid "'=' small dash"
+msgstr ""
+
+#. <
+#: udav/style_dlg.cpp:350 mgllab/dialogs.cpp:242
+msgid "'>' right sign"
+msgstr ""
+
+#. <
+#: udav/style_dlg.cpp:393 mgllab/dialogs.cpp:225
+msgid "'>' triangle right"
+msgstr ""
+
+#. _
+#: udav/style_dlg.cpp:265 udav/style_dlg.cpp:288 mgllab/dialogs.cpp:188
+msgid "'A' arrow"
+msgstr ""
+
+#. S
+#: udav/style_dlg.cpp:271 udav/style_dlg.cpp:294 mgllab/dialogs.cpp:194
+msgid "'D' rhomb"
+msgstr ""
+
+#. d
+#: udav/style_dlg.cpp:353 mgllab/dialogs.cpp:244
+msgid "'D' solid rhomb"
+msgstr ""
+
+#. V
+#: udav/style_dlg.cpp:267 udav/style_dlg.cpp:290 mgllab/dialogs.cpp:191
+msgid "'I' stop"
+msgstr ""
+
+#. A
+#: udav/style_dlg.cpp:268 udav/style_dlg.cpp:291 mgllab/dialogs.cpp:189
+msgid "'K' size"
+msgstr ""
+
+#. D
+#: udav/style_dlg.cpp:272 udav/style_dlg.cpp:295 mgllab/dialogs.cpp:195
+msgid "'O' circle"
+msgstr ""
+
+#. o
+#: udav/style_dlg.cpp:345 mgllab/dialogs.cpp:237
+msgid "'O' solid circle"
+msgstr ""
+
+#. s
+#: udav/style_dlg.cpp:347 mgllab/dialogs.cpp:239
+msgid "'S' solid square"
+msgstr ""
+
+#. T
+#: udav/style_dlg.cpp:270 udav/style_dlg.cpp:293 mgllab/dialogs.cpp:193
+msgid "'S' square"
+msgstr ""
+
+#. I
+#: udav/style_dlg.cpp:269 udav/style_dlg.cpp:292 mgllab/dialogs.cpp:192
+msgid "'T' triangle"
+msgstr ""
+
+#. K
+#: udav/style_dlg.cpp:266 udav/style_dlg.cpp:289 mgllab/dialogs.cpp:190
+msgid "'V' back arrow"
+msgstr ""
+
+#. O
+#: mgllab/dialogs.cpp:196
+msgid "'X' cross"
+msgstr ""
+
+#. *
+#: udav/style_dlg.cpp:355 mgllab/dialogs.cpp:246
+msgid "'^' hats"
+msgstr ""
+
+#. .
+#: udav/style_dlg.cpp:391 mgllab/dialogs.cpp:222
+msgid "'^' triangle up"
+msgstr ""
+
+#. "AVIKTSDO"
+#: udav/style_dlg.cpp:264 udav/style_dlg.cpp:287 mgllab/dialogs.cpp:187
+msgid "'_' none"
+msgstr ""
+
+#. s
+#. >
+#: udav/style_dlg.cpp:352 udav/style_dlg.cpp:389 mgllab/dialogs.cpp:220
+#: mgllab/dialogs.cpp:243
+msgid "'d' rhomb"
+msgstr ""
+
+#. ;
+#: udav/style_dlg.cpp:314 mgllab/dialogs.cpp:205
+msgid "'i' small dash dot"
+msgstr ""
+
+#. |
+#. ;
+#: udav/style_dlg.cpp:313 udav/style_dlg.cpp:351 mgllab/dialogs.cpp:203
+#: mgllab/dialogs.cpp:235
+msgid "'j' dash dot"
+msgstr ""
+
+#. *
+#. j
+#: udav/style_dlg.cpp:344 udav/style_dlg.cpp:394 mgllab/dialogs.cpp:216
+#: mgllab/dialogs.cpp:236
+msgid "'o' circle"
+msgstr ""
+
+#. x
+#. O
+#: udav/style_dlg.cpp:346 udav/style_dlg.cpp:388 mgllab/dialogs.cpp:219
+#: mgllab/dialogs.cpp:238
+msgid "'s' square"
+msgstr ""
+
+#. ^
+#: udav/style_dlg.cpp:390 mgllab/dialogs.cpp:223
+msgid "'v' triangle down"
+msgstr ""
+
+#. +
+#: udav/style_dlg.cpp:386 mgllab/dialogs.cpp:218
+msgid "'x' skew cross"
+msgstr ""
+
+#. -
+#: udav/style_dlg.cpp:310 mgllab/dialogs.cpp:202
+msgid "'|' long dash"
+msgstr ""
+
+#. S
+#: udav/style_dlg.cpp:348 mgllab/dialogs.cpp:240
+msgid "'~' waves"
+msgstr ""
+
+#: src/parser.cpp:51
+msgid "0 - special plot"
+msgstr ""
+
+#: src/parser.cpp:51
+msgid "1 - other plot"
+msgstr ""
+
+#: src/parser.cpp:51
+msgid "10 - dd plot"
+msgstr ""
+
+#: src/parser.cpp:51
+msgid "11 - vector plot"
+msgstr ""
+
+#: src/parser.cpp:51
+msgid "12 - axis"
+msgstr ""
+
+#: src/parser.cpp:51
+msgid "13 - primitives"
+msgstr ""
+
+#: src/parser.cpp:51
+msgid "14 - axis setup"
+msgstr ""
+
+#: src/parser.cpp:51
+msgid "15 - text/legend"
+msgstr ""
+
+#: src/parser.cpp:51
+msgid "16 - data transform"
+msgstr ""
+
+#: udav/info_dlg.cpp:47
+msgid "1D plot"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:166 mgllab/dialogs.cpp:707
+msgid "1D plots"
+msgstr ""
+
+#: mgllab/help.cpp:359
+msgid "1D view"
+msgstr ""
+
+#: src/parser.cpp:51
+msgid "2 - setup"
+msgstr ""
+
+#: udav/info_dlg.cpp:47
+msgid "2D plot"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:167 mgllab/dialogs.cpp:708
+msgid "2D plots"
+msgstr ""
+
+#: mgllab/help.cpp:361
+msgid "2D view"
+msgstr ""
+
+#: src/parser.cpp:51
+msgid "3 - data handle"
+msgstr ""
+
+#: udav/open_dlg.cpp:71
+msgid "3D data with sizes from file"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:168 mgllab/dialogs.cpp:709
+msgid "3D plots"
+msgstr ""
+
+#: mgllab/help.cpp:363
+msgid "3D view"
+msgstr ""
+
+#: src/parser.cpp:51
+msgid "4 - data create"
+msgstr ""
+
+#: src/parser.cpp:51
+msgid "5 - subplot"
+msgstr ""
+
+#: src/parser.cpp:51
+msgid "6 - program flow"
+msgstr ""
+
+#: src/parser.cpp:51
+msgid "7 - 1d plot"
+msgstr ""
+
+#: src/parser.cpp:51
+msgid "8 - 2d plot"
+msgstr ""
+
+#: src/parser.cpp:51
+msgid "9 - 3d plot"
+msgstr ""
+
+#: udav/udav_wnd.cpp:455
+msgid ""
+"<br>(c) Alexey Balakin, 2007-present<br><br><a href='http://www.gnu.org/"
+"copyleft/gpl.html'>License is GPL v.2 or later.</a>"
+msgstr ""
+
+#: mgllab/help.cpp:304
+msgid "@<-  Prev"
+msgstr ""
+
+#: widgets/qt.cpp:1277 udav/udav_wnd.cpp:331 mgllab/mgllab.cpp:332
+msgid "About"
+msgstr ""
+
+#. -----------------------------------------------------------------------------
+#: widgets/qt.cpp:863 widgets/qt.cpp:1278 udav/udav_wnd.cpp:332
+#: udav/udav_wnd.cpp:460
+msgid "About Qt"
+msgstr ""
+
+#: widgets/qt.cpp:1156 udav/plot_pnl.cpp:372
+msgid "Add arc"
+msgstr ""
+
+#: widgets/qt.cpp:1159 udav/plot_pnl.cpp:375
+msgid "Add arc which properties can be changed later by mouse."
+msgstr ""
+
+#: mgllab/dialogs.cpp:84
+msgid "Add command option(s)"
+msgstr ""
+
+#: widgets/qt.cpp:1161 udav/plot_pnl.cpp:378
+msgid "Add curve"
+msgstr ""
+
+#: widgets/qt.cpp:1164 udav/plot_pnl.cpp:381
+msgid "Add curve which properties can be changed later by mouse."
+msgstr ""
+
+#: src/exec_dat.cpp:1523
+msgid "Add data or number"
+msgstr ""
+
+#: widgets/qt.cpp:1176 udav/plot_pnl.cpp:396
+msgid "Add ellipse"
+msgstr ""
+
+#: widgets/qt.cpp:1179 udav/plot_pnl.cpp:399 udav/plot_pnl.cpp:405
+msgid "Add ellipse which properties can be changed later by mouse."
+msgstr ""
+
+#: mgllab/dialogs.cpp:1229
+msgid "Add inplot"
+msgstr ""
+
+#: src/exec_set.cpp:690
+msgid "Add legend entry"
+msgstr ""
+
+#: mgllab/dialogs.cpp:119
+msgid "Add legend entry for the plot"
+msgstr ""
+
+#: widgets/qt.cpp:1151 udav/plot_pnl.cpp:366
+msgid "Add line"
+msgstr ""
+
+#: widgets/qt.cpp:1154 udav/plot_pnl.cpp:369
+msgid "Add line which properties can be changed later by mouse."
+msgstr ""
+
+#: widgets/qt.cpp:1186 udav/plot_pnl.cpp:408
+msgid "Add mark"
+msgstr ""
+
+#: widgets/qt.cpp:1189 udav/plot_pnl.cpp:411
+msgid "Add marker which properties can be changed later by mouse."
+msgstr ""
+
+#: widgets/qt.cpp:1181 udav/plot_pnl.cpp:402
+msgid "Add polygon"
+msgstr ""
+
+#: widgets/qt.cpp:1184
+msgid "Add polygon which properties can be changed later by mouse."
+msgstr ""
+
+#: mgllab/dialogs.cpp:1453
+msgid "Add primitive"
+msgstr ""
+
+#: widgets/qt.cpp:1166 udav/plot_pnl.cpp:384
+msgid "Add rect"
+msgstr ""
+
+#: widgets/qt.cpp:1169 udav/plot_pnl.cpp:387
+msgid "Add rectangle which properties can be changed later by mouse."
+msgstr ""
+
+#: widgets/qt.cpp:1171 udav/plot_pnl.cpp:390
+msgid "Add rhombus"
+msgstr ""
+
+#: widgets/qt.cpp:1174 udav/plot_pnl.cpp:393
+msgid "Add rhombus which properties can be changed later by mouse."
+msgstr ""
+
+#: widgets/qt.cpp:1191 udav/plot_pnl.cpp:414
+msgid "Add text"
+msgstr ""
+
+#: widgets/qt.cpp:1194 udav/plot_pnl.cpp:417
+msgid "Add text which properties can be changed later by mouse."
+msgstr ""
+
+#: src/exec_prm.cpp:611
+msgid "Add title for current subplot/inplot"
+msgstr ""
+
+#: mgllab/table.cpp:794
+msgid "Add to"
+msgstr ""
+
+#: src/exec_set.cpp:691
+msgid "Add user-defined symbol"
+msgstr ""
+
+#: widgets/fltk.cpp:851
+msgid "Adjust picture size to fill drawing area"
+msgstr ""
+
+#: widgets/fltk.cpp:814 widgets/qt.cpp:1139 udav/plot_pnl.cpp:337
+msgid "Adjust size"
+msgstr ""
+
+#: src/exec_set.cpp:692
+msgid "Adjust ticks for best view"
+msgstr ""
+
+#: udav/calc_dlg.cpp:193
+msgid "Airy and Gamma"
+msgstr ""
+
+#: udav/hint_dlg.cpp:42 mgllab/help.cpp:276
+msgid ""
+"All indexes (of data arrays, subplots and so on) are always start from 0."
+msgstr ""
+
+#. graphics menu
+#: widgets/qt.cpp:1098 udav/opt_dlg.cpp:51 udav/setup_dlg.cpp:109
+#: udav/plot_pnl.cpp:290 mgllab/dialogs.cpp:109
+msgid "Alpha"
+msgstr ""
+
+#: mgllab/dialogs.cpp:110
+msgid "Alpha value (transparency) of surface or cloud"
+msgstr ""
+
+#: udav/setup_dlg.cpp:93 mgllab/dialogs.cpp:1003
+msgid "AlphaDef"
+msgstr ""
+
+#: udav/opt_dlg.cpp:56 udav/setup_dlg.cpp:95 mgllab/dialogs.cpp:111
+#: mgllab/dialogs.cpp:1004
+msgid "Ambient"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:167
+msgid "Angle around x axis (in degrees)"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:171
+msgid "Angle around z axis (in degrees)"
+msgstr ""
+
+#. animation menu
+#: widgets/qt.cpp:1244 widgets/qt.cpp:1245 udav/plot_pnl.cpp:559
+#: mgllab/mathgl.cpp:183
+msgid "Animation"
+msgstr ""
+
+#: mgllab/table.cpp:786
+msgid "Another"
+msgstr ""
+
+#: mgllab/table.cpp:852
+msgid "Apply operator (smoothing, integration, difference ...) to data"
+msgstr ""
+
+#: mgllab/dialogs.cpp:103
+msgid "Approximate number of mesh lines in plot"
+msgstr ""
+
+#: mgllab/help.cpp:135
+msgid "Are you sure that you want to delete ALL data arrays?"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:67
+msgid "Argument"
+msgstr ""
+
+#: mgllab/dialogs.cpp:738
+msgid "Arguments"
+msgstr ""
+
+#: udav/style_dlg.cpp:63 mgllab/dialogs.cpp:321
+msgid "Arrow at end"
+msgstr ""
+
+#. g->setColStretch(0, 1);	g->setColStretch(1, 1);	g->setColStretch(2, 1);
+#: udav/style_dlg.cpp:61 mgllab/dialogs.cpp:315
+msgid "Arrow at start"
+msgstr ""
+
+#: widgets/qt.cpp:1137
+msgid "Ask to stop plot drawing (F7)."
+msgstr ""
+
+#: udav/subplot_dlg.cpp:175
+msgid "Aspect"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:178
+msgid "Aspect ratio of x-scale to z-scale"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:182
+msgid "Aspect ratio of y-scale to z-scale"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1298
+msgid "Aspect x/z"
+msgstr ""
+
+#: src/exec_set.cpp:698
+msgid "Attach light settings to inplot"
+msgstr ""
+
+#: udav/open_dlg.cpp:60
+msgid "Auto detect data sizes"
+msgstr ""
+
+#: udav/open_dlg.cpp:177
+msgid "Auto detect data sizes (%1 x %2 x %3)"
+msgstr ""
+
+#: udav/prop_dlg.cpp:100
+msgid "AutoKey"
+msgstr ""
+
+#: udav/prop_dlg.cpp:159
+msgid "Automatically execute script after loading"
+msgstr ""
+
+#: udav/prop_dlg.cpp:165
+msgid "Automatically save before redrawing (F5)"
+msgstr ""
+
+#: src/data.cpp:1425
+#, c-format
+msgid ""
+"Averages are:\n"
+"<a> = %g\t<x> = %g\t<y> = %g\t<z> = %g\n"
+msgstr ""
+
+#: udav/style_dlg.cpp:122 mgllab/dialogs.cpp:340
+msgid "Axial direction"
+msgstr ""
+
+#: udav/setup_dlg.cpp:101
+msgid "AxialDir"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1008
+msgid "Axis"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:176 mgllab/dialogs.cpp:717
+msgid "Axis and colorbar"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:177 mgllab/dialogs.cpp:718 mgllab/dialogs.cpp:949
+msgid "Axis setup"
+msgstr ""
+
+#. W
+#: udav/style_dlg.cpp:237 mgllab/dialogs.cpp:45
+msgid "B - navy"
+msgstr ""
+
+#: udav/help_pnl.cpp:48
+msgid "Backward"
+msgstr ""
+
+#: src/font.cpp:947
+#, c-format
+msgid "Bad '%ls' at %zu\n"
+msgstr ""
+
+#: src/parser.cpp:766
+#, c-format
+msgid "Bad arguments for %ls: %ld instead of %d\n"
+msgstr ""
+
+#: udav/setup_dlg.cpp:97
+msgid "BaseWidth"
+msgstr ""
+
+#: udav/calc_dlg.cpp:192
+msgid "Basic"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1461
+msgid "Begin"
+msgstr ""
+
+#: udav/calc_dlg.cpp:193
+msgid "Bessel"
+msgstr ""
+
+#: udav/style_dlg.cpp:157 mgllab/dialogs.cpp:368
+msgid "Bold style"
+msgstr ""
+
+#: udav/opt_dlg.cpp:115
+msgid "Both fields in crange must be filled"
+msgstr ""
+
+#: udav/opt_dlg.cpp:94
+msgid "Both fields in xrange must be filled"
+msgstr ""
+
+#: udav/opt_dlg.cpp:101
+msgid "Both fields in yrange must be filled"
+msgstr ""
+
+#: udav/opt_dlg.cpp:108
+msgid "Both fields in zrange must be filled"
+msgstr ""
+
+#: src/parser.cpp:1423
+msgid "Break for-loop"
+msgstr ""
+
+#: udav/setup_dlg.cpp:122 mgllab/dialogs.cpp:1069
+msgid "Brightness"
+msgstr ""
+
+#: mgllab/dialogs.cpp:401
+msgid "Brightness of i-th color"
+msgstr ""
+
+#: mgllab/table.cpp:766
+msgid "By formula"
+msgstr ""
+
+#. R
+#: udav/style_dlg.cpp:240 mgllab/dialogs.cpp:48
+msgid "C - teal"
+msgstr ""
+
+#: udav/setup_dlg.cpp:51 mgllab/dialogs.cpp:989
+msgid "C axis"
+msgstr ""
+
+#: udav/opt_dlg.cpp:47 mgllab/dialogs.cpp:97
+msgid "C-range"
+msgstr ""
+
+#: widgets/qt.cpp:1263
+msgid "Calculations"
+msgstr ""
+
+#. TODO
+#. connect(hidden,SIGNAL(cursorPositionChanged()),this,SLOT(hiddenClicked()));
+#: udav/udav_wnd.cpp:194 udav/udav_wnd.cpp:206 mgllab/mgllab.cpp:326
+#: mgllab/mgllab.cpp:557
+msgid "Calculator"
+msgstr ""
+
+#: udav/anim_dlg.cpp:67 udav/prop_dlg.cpp:180 udav/args_dlg.cpp:63
+#: udav/newcmd_dlg.cpp:78 udav/open_dlg.cpp:90 udav/dat_pnl.cpp:460
+#: udav/dat_pnl.cpp:510 udav/dat_pnl.cpp:552 udav/dat_pnl.cpp:629
+#: udav/opt_dlg.cpp:78 udav/setup_dlg.cpp:145 udav/files_dlg.cpp:58
+#: udav/style_dlg.cpp:206 udav/data_dlg.cpp:90 udav/subplot_dlg.cpp:219
+#: mgllab/editor.cpp:282 mgllab/mathgl.cpp:164 mgllab/mathgl.cpp:195
+#: mgllab/dialogs.cpp:120 mgllab/dialogs.cpp:164 mgllab/dialogs.cpp:410
+#: mgllab/dialogs.cpp:584 mgllab/dialogs.cpp:749 mgllab/dialogs.cpp:1071
+#: mgllab/dialogs.cpp:1318 mgllab/dialogs.cpp:1473 mgllab/mgllab.cpp:482
+#: mgllab/table.cpp:101 mgllab/table.cpp:179 mgllab/table.cpp:353
+#: mgllab/table.cpp:556 mgllab/table.cpp:619 mgllab/table.cpp:674
+msgid "Cancel"
+msgstr ""
+
+#: src/crust.cpp:557
+msgid "Cannot triangulate this set!"
+msgstr ""
+
+#: udav/udav_wnd.cpp:226 mgllab/mgllab.cpp:355 mgllab/mgllab.cpp:356
+msgid "Canvas"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:59 udav/subplot_dlg.cpp:101 udav/subplot_dlg.cpp:118
+#: udav/subplot_dlg.cpp:135
+msgid "Cell index"
+msgstr ""
+
+#: mgllab/table.cpp:103 mgllab/table.cpp:558 mgllab/table.cpp:770
+msgid "Change"
+msgstr ""
+
+#: mgllab/table.cpp:104
+msgid "Change (resize) data"
+msgstr ""
+
+#: widgets/qt.cpp:1141 udav/plot_pnl.cpp:339
+msgid "Change canvas size to fill whole region (F6)."
+msgstr ""
+
+#: src/exec_set.cpp:702
+msgid "Change current directory"
+msgstr ""
+
+#: mgllab/table.cpp:168
+msgid "Change data"
+msgstr ""
+
+#: mgllab/table.cpp:91
+msgid "Change data sizes"
+msgstr ""
+
+#: mgllab/table.cpp:559 mgllab/table.cpp:622 mgllab/table.cpp:677
+msgid "Change data values and close this window"
+msgstr ""
+
+#: udav/prop_dlg.cpp:71
+msgid "Change font"
+msgstr ""
+
+#: src/exec_set.cpp:751
+msgid "Change view angles - use 'rotate' for plot rotation"
+msgstr ""
+
+#: udav/calc_dlg.cpp:68
+msgid "Clear"
+msgstr ""
+
+#: udav/text_pnl.cpp:527
+msgid "Clear all"
+msgstr ""
+
+#: src/exec_set.cpp:703
+msgid "Clear legend entries"
+msgstr ""
+
+#: src/exec_set.cpp:704
+msgid "Clear picture"
+msgstr ""
+
+#. o = new Fl_Button(180, 130, 25, 25);o->image(img_save);	o->tooltip("img_save");
+#: widgets/qt.cpp:1091 udav/find_dlg.cpp:52 udav/hint_dlg.cpp:70
+#: mgllab/editor.cpp:565 mgllab/help.cpp:308 mgllab/help.cpp:367
+#: mgllab/help.cpp:483
+msgid "Close"
+msgstr ""
+
+#: udav/dat_pnl.cpp:833
+msgid "Close tab"
+msgstr ""
+
+#: udav/dat_pnl.cpp:835
+msgid "Close this data tab."
+msgstr ""
+
+#: udav/setup_dlg.cpp:121 udav/style_dlg.cpp:67 mgllab/dialogs.cpp:1068
+#: mgllab/dialogs.cpp:1459
+msgid "Color"
+msgstr ""
+
+#. g->setColStretch(0, 1);			g->setColStretch(1, 1);
+#: udav/style_dlg.cpp:106
+msgid "Color order"
+msgstr ""
+
+#: udav/style_dlg.cpp:150 mgllab/dialogs.cpp:339
+msgid "Color scheme"
+msgstr ""
+
+#: mgllab/dialogs.cpp:384
+msgid "Color(s) or color scheme"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1002
+msgid "Colors"
+msgstr ""
+
+#: mgllab/table.cpp:879
+msgid ""
+"Colors denote values: magenta - local max, cyan - local min,\n"
+"\tred - Re(v)>0, blue - Re(v)<0, purple - Im(v)>0, teal - Im(v)<0."
+msgstr ""
+
+#: mgllab/dialogs.cpp:577
+msgid "Column expr"
+msgstr ""
+
+#: mgllab/dialogs.cpp:724 mgllab/mgllab.cpp:305
+msgid "Command"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:64 mgllab/dialogs.cpp:740
+msgid ""
+"Command arguments. Bold ones are required arguments.\n"
+"Other are optional arguments but its order is required.\n"
+"You can use '' for default format. See help at right\n"
+"for default values."
+msgstr ""
+
+#: udav/text_pnl.cpp:575
+msgid "Command options"
+msgstr ""
+
+#: udav/prop_dlg.cpp:82
+msgid "Comments"
+msgstr ""
+
+#: src/exec_prm.cpp:599
+msgid "Computes the attractor of an IFS"
+msgstr ""
+
+#: src/exec_prm.cpp:600
+msgid "Computes the attractor of an IFS for 3d case"
+msgstr ""
+
+#: src/exec_prm.cpp:601
+msgid "Computes the attractor of an IFS with parameters from *.ifs file"
+msgstr ""
+
+#: src/exec_prm.cpp:595
+msgid "Computes the flame fractal"
+msgstr ""
+
+#: src/parser.cpp:1431 src/parser.cpp:1435
+msgid "Conditional operator"
+msgstr ""
+
+#: udav/plot_pnl.cpp:358
+msgid "Copy click coor."
+msgstr ""
+
+#: udav/plot_pnl.cpp:360
+msgid "Copy coordinates of last mouse click to clipboard."
+msgstr ""
+
+#: udav/dat_pnl.cpp:707
+msgid "Copy data"
+msgstr ""
+
+#: src/exec_dat.cpp:1528
+msgid "Copy data from another variable"
+msgstr ""
+
+#: widgets/fltk.cpp:811
+msgid "Copy graphics"
+msgstr ""
+
+#: widgets/qt.cpp:1145 udav/plot_pnl.cpp:354
+msgid "Copy graphics to clipboard (Ctrl+Shift+G)."
+msgstr ""
+
+#: widgets/fltk.cpp:855
+msgid "Copy image to clipboard"
+msgstr ""
+
+#: widgets/qt.cpp:1143 udav/plot_pnl.cpp:352
+msgid "Copy plot"
+msgstr ""
+
+#: udav/dat_pnl.cpp:709
+msgid "Copy range of numbers to clipboard (Ctrl+Shift+C)."
+msgstr ""
+
+#: udav/text_pnl.cpp:535
+msgid "Copy selected text or data to clipboard (Ctrl+C)."
+msgstr ""
+
+#: mgllab/editor.cpp:511
+msgid "Copy selection to clipboard"
+msgstr ""
+
+#: udav/text_pnl.cpp:533 mgllab/mgllab.cpp:295
+msgid "Copy text"
+msgstr ""
+
+#: mgllab/table.cpp:778
+msgid "Cos FFT"
+msgstr ""
+
+#: udav/dat_pnl.cpp:621
+msgid "Cos-Fourier transform along direction(s)"
+msgstr ""
+
+#: src/exec_dat.cpp:1530
+msgid "Cos-Fourier transform at some direction"
+msgstr ""
+
+#: mgllab/table.cpp:165
+msgid "Cosine FFT"
+msgstr ""
+
+#: udav/text_pnl.cpp:365 udav/text_pnl.cpp:482
+msgid "Could not write to %1"
+msgstr ""
+
+#: udav/setup_dlg.cpp:159
+msgid "Could not write to file"
+msgstr ""
+
+#: udav/udav_wnd.cpp:570
+msgid "Couldn't change to folder "
+msgstr ""
+
+#: udav/text_pnl.cpp:431
+msgid "Couldn't open file "
+msgstr ""
+
+#: mgllab/dialogs.cpp:1190
+#, c-format
+msgid "Couldn't open file %s"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:173
+msgid "Create data and I/O"
+msgstr ""
+
+#: mgllab/dialogs.cpp:714
+msgid "Create data and IO"
+msgstr ""
+
+#: src/exec_dat.cpp:1555
+msgid "Create histogram (distribution) of data values"
+msgstr ""
+
+#: udav/dat_pnl.cpp:766 mgllab/table.cpp:758
+msgid "Create new"
+msgstr ""
+
+#: src/exec_dat.cpp:1614
+msgid "Create new 1D data and fill it in range"
+msgstr ""
+
+#: src/exec_dat.cpp:1570
+msgid "Create new data"
+msgstr ""
+
+#: udav/mem_pnl.cpp:58
+msgid "Create new data array"
+msgstr ""
+
+#: mgllab/table.cpp:836
+msgid "Create new data with zero filling"
+msgstr ""
+
+#: udav/udav_wnd.cpp:284
+msgid "Create new empty script window (Ctrl+N)."
+msgstr ""
+
+#: src/parser.cpp:1436
+msgid "Creates new variable from list of numbers or data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:784 mgllab/table.cpp:761
+msgid "Crop"
+msgstr ""
+
+#: mgllab/table.cpp:858
+msgid "Crop (cut off edges) data"
+msgstr ""
+
+#: mgllab/table.cpp:607
+msgid "Crop data"
+msgstr ""
+
+#: src/exec_dat.cpp:1531
+msgid "Crop edge of data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:786
+msgid "Crop the data edges. Useful to cut off the zero-filled area."
+msgstr ""
+
+#: mgllab/table.cpp:163 mgllab/table.cpp:772
+msgid "CumSum"
+msgstr ""
+
+#: src/exec_dat.cpp:1532
+msgid "Cumulative summation along direction(s)"
+msgstr ""
+
+#: udav/prop_dlg.cpp:106
+msgid "CurrLine"
+msgstr ""
+
+#: udav/prop_dlg.cpp:68
+msgid "Current font"
+msgstr ""
+
+#: udav/text_pnl.cpp:530
+msgid "Cut selected text to clipboard (Ctrl+X)."
+msgstr ""
+
+#: udav/text_pnl.cpp:528 mgllab/mgllab.cpp:294
+msgid "Cut text"
+msgstr ""
+
+#: udav/opt_dlg.cpp:61 mgllab/dialogs.cpp:106
+msgid "Cutting"
+msgstr ""
+
+#: mgllab/help.cpp:251 mgllab/table.cpp:428 mgllab/table.cpp:457
+msgid ""
+"DAT Files \t*.{dat,csv}\n"
+"HDF Files \t*.{h5,hdf}"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1465
+msgid "Dash"
+msgstr ""
+
+#: udav/style_dlg.cpp:62 mgllab/dialogs.cpp:318
+msgid "Dashing"
+msgstr ""
+
+#: udav/dat_pnl.cpp:66
+msgid "Data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:249 udav/dat_pnl.cpp:271
+msgid ""
+"Data files (*.dat)\n"
+"HDF5 files (*.h5 *.hdf)\n"
+"PNG files (*.png)\n"
+"All files (*.*)"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:175 mgllab/dialogs.cpp:716
+msgid "Data handling"
+msgstr ""
+
+#: mgllab/help.cpp:163 mgllab/table.cpp:849
+msgid "Data information and preview."
+msgstr ""
+
+#: udav/open_dlg.cpp:56 udav/data_dlg.cpp:42 mgllab/dialogs.cpp:566
+msgid "Data name"
+msgstr ""
+
+#: udav/info_dlg.cpp:42
+msgid "Data preview"
+msgstr ""
+
+#: udav/info_dlg.cpp:43
+msgid "Data preview for current slice."
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:174 mgllab/dialogs.cpp:715
+msgid "Data transform"
+msgstr ""
+
+#: udav/plot_pnl.cpp:556
+msgid "Decrease \\phi angle by 10 degrees."
+msgstr ""
+
+#: udav/plot_pnl.cpp:548
+msgid "Decrease \\theta angle by 10 degrees."
+msgstr ""
+
+#: mgllab/help.cpp:105
+msgid "Decrease font size"
+msgstr ""
+
+#: src/parser.cpp:1427
+msgid "Define constant or parameter"
+msgstr ""
+
+#: src/parser.cpp:1426
+msgid "Define parameter as character"
+msgstr ""
+
+#: src/parser.cpp:1428
+msgid "Define parameter as numerical value"
+msgstr ""
+
+#: src/parser.cpp:1422
+msgid "Define parameter from user input"
+msgstr ""
+
+#: udav/anim_dlg.cpp:76
+msgid "Delay (in ms)"
+msgstr ""
+
+#: mgllab/mathgl.cpp:202
+msgid "Delay (in sec)"
+msgstr ""
+
+#: mgllab/help.cpp:178
+msgid "Delete @b all at . data arrays."
+msgstr ""
+
+#: udav/mem_pnl.cpp:64
+msgid "Delete ALL data arrays"
+msgstr ""
+
+#: src/exec_dat.cpp:1535
+msgid "Delete data or slice of data"
+msgstr ""
+
+#: udav/plot_pnl.cpp:426
+msgid "Delete selected"
+msgstr ""
+
+#: udav/mem_pnl.cpp:60
+msgid "Delete selected data array"
+msgstr ""
+
+#: mgllab/help.cpp:166
+msgid "Delete selected data."
+msgstr ""
+
+#: udav/plot_pnl.cpp:428
+msgid "Delete selected plot."
+msgstr ""
+
+#: mgllab/dialogs.cpp:734
+msgid "Description"
+msgstr ""
+
+#: src/exec_dat.cpp:1536
+msgid "Detect curves for maximums of data array"
+msgstr ""
+
+#: mgllab/table.cpp:164 mgllab/table.cpp:774
+msgid "Difference"
+msgstr ""
+
+#: udav/dat_pnl.cpp:616
+msgid "Differentiate data along direction(s)"
+msgstr ""
+
+#: udav/opt_dlg.cpp:58 mgllab/dialogs.cpp:113 mgllab/dialogs.cpp:1005
+msgid "Diffuse"
+msgstr ""
+
+#: src/exec_dat.cpp:1540
+msgid "Dilate data larger val"
+msgstr ""
+
+#: src/exec_dat.cpp:1527
+msgid "Direct multiplication of arrays"
+msgstr ""
+
+#: udav/dat_pnl.cpp:351 udav/dat_pnl.cpp:377 udav/dat_pnl.cpp:424
+#: mgllab/dialogs.cpp:161 mgllab/table.cpp:549
+msgid "Direction"
+msgstr ""
+
+#: mgllab/table.cpp:551
+msgid "Direction along which data will be filled"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:105 udav/subplot_dlg.cpp:122
+msgid "Distance between cells"
+msgstr ""
+
+#: mgllab/table.cpp:797
+msgid "Divide by"
+msgstr ""
+
+#: src/exec_dat.cpp:1541
+msgid "Divide by data or number"
+msgstr ""
+
+#: mgllab/table.cpp:180 mgllab/table.cpp:354 mgllab/table.cpp:676
+msgid "Do"
+msgstr ""
+
+#: src/exec_dat.cpp:1603
+msgid "Do STFA transform"
+msgstr ""
+
+#: src/exec_dat.cpp:1609 src/exec_dat.cpp:1610
+msgid "Do integral transform of data"
+msgstr ""
+
+#: mgllab/table.cpp:102 mgllab/table.cpp:557 mgllab/table.cpp:620
+#: mgllab/table.cpp:675
+msgid "Do nothing and close this window"
+msgstr ""
+
+#: udav/mem_pnl.cpp:122
+msgid "Do you want to delete all data?"
+msgstr ""
+
+#: udav/udav_wnd.cpp:341 udav/udav_wnd.cpp:580 udav/udav_wnd.cpp:622
+msgid "Do you want to save the changes to the document?"
+msgstr ""
+
+#: mgllab/editor.cpp:282
+msgid "Don't Save"
+msgstr ""
+
+#: mgllab/table.cpp:164
+msgid "Double diff."
+msgstr ""
+
+#: src/exec_gr.cpp:1032
+msgid "Draw Bifurcation diagram"
+msgstr ""
+
+#: src/exec_gr.cpp:1067
+msgid "Draw Iris plots"
+msgstr ""
+
+#: src/exec_gr.cpp:1069
+msgid "Draw Lamerey diagram"
+msgstr ""
+
+#: src/exec_gr.cpp:1073
+msgid "Draw Open-High-Low-Close (OHLC) diagram"
+msgstr ""
+
+#: src/exec_gr.cpp:1076
+msgid "Draw Poincare map"
+msgstr ""
+
+#: src/exec_gr.cpp:1082
+msgid "Draw STFA diagram"
+msgstr ""
+
+#: src/exec_gr.cpp:1094
+msgid "Draw TeX mark at point position"
+msgstr ""
+
+#: src/exec_prm.cpp:578
+msgid "Draw angle arc"
+msgstr ""
+
+#: src/exec_gr.cpp:1026
+msgid "Draw area plot for 1D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1029
+msgid "Draw bars for 1D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1031
+msgid "Draw belts"
+msgstr ""
+
+#: src/exec_gr.cpp:1092
+msgid "Draw binormales for 1D data"
+msgstr ""
+
+#: src/exec_prm.cpp:604
+msgid "Draw bitmap (logo) along axis range"
+msgstr ""
+
+#: src/exec_prm.cpp:582
+msgid "Draw bounding box"
+msgstr ""
+
+#: src/exec_gr.cpp:1034
+msgid "Draw boxes"
+msgstr ""
+
+#: src/exec_gr.cpp:1033
+msgid "Draw boxplot for 2D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1035
+msgid "Draw candlestick chart"
+msgstr ""
+
+#: src/exec_gr.cpp:1036
+msgid "Draw chart"
+msgstr ""
+
+#: src/exec_prm.cpp:583
+msgid "Draw circle"
+msgstr ""
+
+#: src/exec_gr.cpp:1037
+msgid "Draw cloud"
+msgstr ""
+
+#: src/exec_prm.cpp:584
+msgid "Draw colorbar"
+msgstr ""
+
+#: src/exec_prm.cpp:585
+msgid "Draw cone"
+msgstr ""
+
+#: src/exec_gr.cpp:1038
+msgid "Draw cones for 1D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1039
+msgid "Draw contour lines"
+msgstr ""
+
+#: src/exec_gr.cpp:1049
+msgid "Draw contour lines at x-slice (or x-plane)"
+msgstr ""
+
+#: src/exec_gr.cpp:1050
+msgid "Draw contour lines at y-slice (or y-plane)"
+msgstr ""
+
+#: src/exec_gr.cpp:1051
+msgid "Draw contour lines at z-slice (or z-plane)"
+msgstr ""
+
+#: src/exec_gr.cpp:1040
+msgid "Draw contour lines for 3D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1099
+msgid "Draw contour lines for surface of triangles"
+msgstr ""
+
+#: src/exec_gr.cpp:1047
+msgid "Draw contour lines on parametric surface"
+msgstr ""
+
+#: src/exec_gr.cpp:1048
+msgid "Draw contour tubes"
+msgstr ""
+
+#: src/exec_gr.cpp:1100
+msgid "Draw contour tubes for surface of triangles"
+msgstr ""
+
+#: src/exec_prm.cpp:586
+msgid "Draw curve"
+msgstr ""
+
+#: src/exec_gr.cpp:1102
+msgid "Draw curve by tube"
+msgstr ""
+
+#: src/exec_gr.cpp:1053
+msgid "Draw density plot"
+msgstr ""
+
+#: src/exec_gr.cpp:1054
+msgid "Draw density plot at slices of 3D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1055
+msgid "Draw density plot at x-slice (or x-plane)"
+msgstr ""
+
+#: src/exec_gr.cpp:1056
+msgid "Draw density plot at y-slice (or y-plane)"
+msgstr ""
+
+#: src/exec_gr.cpp:1057
+msgid "Draw density plot at z-slice (or z-plane)"
+msgstr ""
+
+#: src/exec_gr.cpp:1058
+msgid "Draw dew plot"
+msgstr ""
+
+#: src/exec_gr.cpp:1059
+msgid "Draw dots for arbitrary data points"
+msgstr ""
+
+#: src/exec_prm.cpp:587
+msgid "Draw drop"
+msgstr ""
+
+#: src/exec_prm.cpp:588
+msgid "Draw ellipse"
+msgstr ""
+
+#: src/exec_prm.cpp:589
+msgid "Draw error box"
+msgstr ""
+
+#: src/exec_gr.cpp:1060
+msgid "Draw error boxes"
+msgstr ""
+
+#: src/exec_prm.cpp:590
+msgid "Draw face (quadrangle)"
+msgstr ""
+
+#: src/exec_prm.cpp:591
+msgid "Draw face perpendicular to x-axis"
+msgstr ""
+
+#: src/exec_prm.cpp:592
+msgid "Draw face perpendicular to y-axis"
+msgstr ""
+
+#: src/exec_prm.cpp:593
+msgid "Draw face perpendicular to z-axis"
+msgstr ""
+
+#: src/exec_gr.cpp:1079
+msgid "Draw filled region (ribbon) between 2 curves"
+msgstr ""
+
+#: src/exec_gr.cpp:1074
+msgid "Draw flow pipes for vector field"
+msgstr ""
+
+#: src/exec_gr.cpp:1062
+msgid "Draw flow threads for vector field"
+msgstr ""
+
+#: src/exec_gr.cpp:1064
+msgid "Draw gradient lines for scalar field"
+msgstr ""
+
+#: src/exec_prm.cpp:598
+msgid "Draw grid"
+msgstr ""
+
+#: src/exec_gr.cpp:1066
+msgid "Draw grid at slices of 3D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1065
+msgid "Draw grid for data array(s)"
+msgstr ""
+
+#: src/exec_gr.cpp:1028
+msgid "Draw horizontal bars for 1D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1095
+msgid "Draw horizontal tiles"
+msgstr ""
+
+#: src/exec_gr.cpp:1096
+msgid "Draw horizontal tiles with variable size"
+msgstr ""
+
+#: src/exec_gr.cpp:1084
+msgid "Draw isosurface for 3D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1087
+msgid "Draw isosurface for 3D data colored and transpared by other data"
+msgstr ""
+
+#: src/exec_gr.cpp:1086
+msgid "Draw isosurface for 3D data colored by other data"
+msgstr ""
+
+#: src/exec_gr.cpp:1085
+msgid "Draw isosurface for 3D data transpared by other data"
+msgstr ""
+
+#: src/exec_gr.cpp:1068
+msgid "Draw label at arbitrary position"
+msgstr ""
+
+#: src/exec_prm.cpp:612
+msgid "Draw label for t-axis"
+msgstr ""
+
+#: src/exec_prm.cpp:613
+msgid "Draw label for x-axis"
+msgstr ""
+
+#: src/exec_prm.cpp:614
+msgid "Draw label for y-axis"
+msgstr ""
+
+#: src/exec_prm.cpp:615
+msgid "Draw label for z-axis"
+msgstr ""
+
+#: src/exec_prm.cpp:602
+msgid "Draw legend"
+msgstr ""
+
+#: src/exec_prm.cpp:603
+msgid "Draw line"
+msgstr ""
+
+#: src/exec_gr.cpp:1070
+msgid "Draw mapping plot"
+msgstr ""
+
+#: src/exec_gr.cpp:1071
+msgid "Draw mark plot for 1D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1072
+msgid "Draw mesh surface"
+msgstr ""
+
+#: src/exec_prm.cpp:581
+msgid "Draw point (ball)"
+msgstr ""
+
+#: src/exec_prm.cpp:605
+msgid "Draw polygon"
+msgstr ""
+
+#: src/exec_gr.cpp:1030
+msgid "Draw quasi-optical beam"
+msgstr ""
+
+#: src/exec_gr.cpp:1078
+msgid "Draw radar chart"
+msgstr ""
+
+#: src/exec_gr.cpp:1052
+msgid "Draw reconstructed surface for arbitrary data points"
+msgstr ""
+
+#: src/exec_prm.cpp:606
+msgid "Draw rectangle"
+msgstr ""
+
+#: src/exec_prm.cpp:607
+msgid "Draw rhombus"
+msgstr ""
+
+#: src/exec_gr.cpp:1044
+msgid "Draw solid contour lines at x-slice (or x-plane)"
+msgstr ""
+
+#: src/exec_gr.cpp:1045
+msgid "Draw solid contour lines at y-slice (or y-plane)"
+msgstr ""
+
+#: src/exec_gr.cpp:1046
+msgid "Draw solid contour lines at z-slice (or z-plane)"
+msgstr ""
+
+#: src/exec_gr.cpp:1043
+msgid "Draw solid contour lines for 3D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1042
+msgid "Draw solid contours"
+msgstr ""
+
+#: src/exec_gr.cpp:1041
+msgid "Draw solid contours with manual colors"
+msgstr ""
+
+#: src/exec_gr.cpp:1083
+msgid "Draw solid surface"
+msgstr ""
+
+#: src/exec_gr.cpp:1090
+msgid "Draw solid surface colored and transpared by other data"
+msgstr ""
+
+#: src/exec_gr.cpp:1089
+msgid "Draw solid surface colored by other data"
+msgstr ""
+
+#: src/exec_gr.cpp:1088
+msgid "Draw solid surface transpared by other data"
+msgstr ""
+
+#: src/exec_prm.cpp:608
+msgid "Draw sphere"
+msgstr ""
+
+#: src/exec_gr.cpp:1080
+msgid "Draw stem plot for 1D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1081
+msgid "Draw step plot for 1D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1097
+msgid "Draw surface of curve rotation"
+msgstr ""
+
+#: src/exec_gr.cpp:1077
+msgid "Draw surface of quadrangles"
+msgstr ""
+
+#: src/exec_gr.cpp:1101
+msgid "Draw surface of triangles"
+msgstr ""
+
+#: src/exec_gr.cpp:1027
+msgid "Draw surfaces of contour lines rotation"
+msgstr ""
+
+#: src/exec_gr.cpp:1091
+msgid "Draw table with data values"
+msgstr ""
+
+#: src/exec_gr.cpp:1093
+msgid "Draw tension plot for 1D data"
+msgstr ""
+
+#: src/exec_prm.cpp:610
+msgid "Draw text at some position or along curve"
+msgstr ""
+
+#: src/exec_prm.cpp:609
+msgid "Draw user-defined symbol at given position and direction"
+msgstr ""
+
+#: src/exec_gr.cpp:1075
+msgid "Draw usual plot for 1D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1103
+msgid "Draw vector field"
+msgstr ""
+
+#: src/exec_gr.cpp:1104
+msgid "Draw vector field at slices of 3D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1098
+msgid "Draw vectors along a curve"
+msgstr ""
+
+#: src/exec_gr.cpp:1061
+msgid "Draw waterfalls"
+msgstr ""
+
+#: udav/plot_pnl.cpp:111 udav/plot_pnl.cpp:130
+msgid "Drawing time %1 ms"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:169 mgllab/dialogs.cpp:710
+msgid "Dual plots"
+msgstr ""
+
+#. L
+#: udav/style_dlg.cpp:244 mgllab/dialogs.cpp:52
+msgid "E - darklawn"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1469
+msgid "Edges"
+msgstr ""
+
+#: udav/text_pnl.cpp:84 mgllab/mgllab.cpp:292
+msgid "Edit"
+msgstr ""
+
+#: udav/mem_pnl.cpp:59
+msgid "Edit selected data array"
+msgstr ""
+
+#: udav/calc_dlg.cpp:193
+msgid "Elliptic"
+msgstr ""
+
+#: udav/prop_dlg.cpp:171 mgllab/mgllab.cpp:474
+msgid "Enable keywords completion"
+msgstr ""
+
+#. pure = new QCheckBox(_("Disable face drawing (faster) for mouse rotation/shift/zoom."), this);
+#. pure->setChecked(mglAutoPure);	v->addWidget(pure);	pure->setEnabled(false);
+#: udav/prop_dlg.cpp:169 mgllab/mgllab.cpp:476
+msgid "Enable mouse wheel for zooming"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1463
+msgid "End"
+msgstr ""
+
+#: udav/prop_dlg.cpp:141
+msgid "English"
+msgstr ""
+
+#. TODO show dialog for color scheme
+#: udav/dat_pnl.cpp:255 udav/dat_pnl.cpp:277 mgllab/table.cpp:477
+#: mgllab/table.cpp:490
+msgid "Enter color scheme"
+msgstr ""
+
+#: udav/dat_pnl.cpp:261 udav/dat_pnl.cpp:283
+msgid "Enter data name"
+msgstr ""
+
+#: mgllab/table.cpp:523
+msgid ""
+"Enter formula for data modification\n"
+"Here x, y, z in range [0,1], u is data value"
+msgstr ""
+
+#: udav/mem_pnl.cpp:85 mgllab/help.cpp:242
+msgid "Enter name for new variable"
+msgstr ""
+
+#. this is HDF file
+#. TODO add dialog with choice of HDF names
+#: mgllab/table.cpp:436
+msgid "Enter name of data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:388 udav/dat_pnl.cpp:402 udav/dat_pnl.cpp:436
+msgid "Enter new data sizes"
+msgstr ""
+
+#: mgllab/table.cpp:28
+msgid "Enter number for addition to data values"
+msgstr ""
+
+#: mgllab/table.cpp:58
+msgid "Enter number for division of data values"
+msgstr ""
+
+#: mgllab/table.cpp:48
+msgid "Enter number for multiplication of data values"
+msgstr ""
+
+#: mgllab/table.cpp:38
+msgid "Enter number for subtraction from data values"
+msgstr ""
+
+#: widgets/qt.cpp:936
+msgid "Enter number of vertexes"
+msgstr ""
+
+#: udav/dat_pnl.cpp:351
+msgid "Enter range for data and direction of filling"
+msgstr ""
+
+#: udav/dat_pnl.cpp:366 udav/dat_pnl.cpp:377
+msgid "Enter range for final data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:424
+msgid "Enter range of saved date."
+msgstr ""
+
+#: udav/dat_pnl.cpp:485
+msgid "Enter slice id:"
+msgstr ""
+
+#: udav/dat_pnl.cpp:413
+msgid ""
+"Enter step of saved points. For example, '1' save all, '2' save each 2nd "
+"point, '3' save each 3d and so on."
+msgstr ""
+
+#: widgets/qt.cpp:945
+msgid "Enter text"
+msgstr ""
+
+#: mgllab/dialogs.cpp:860 mgllab/dialogs.cpp:866
+#, c-format
+msgid "Enter value for %s argument"
+msgstr ""
+
+#: mgllab/table.cpp:166 mgllab/table.cpp:784
+msgid "Envelop"
+msgstr ""
+
+#: src/exec_dat.cpp:1544
+msgid "Erode data larger val"
+msgstr ""
+
+#: mgllab/editor.cpp:348
+#, c-format
+msgid ""
+"Error reading from file '%s':\n"
+"%s."
+msgstr ""
+
+#: src/export.cpp:623 src/export.cpp:632 src/export.cpp:639
+#, c-format
+msgid "Error to call external viewer\n"
+msgstr ""
+
+#: mgllab/editor.cpp:359
+#, c-format
+msgid ""
+"Error writing to file '%s':\n"
+"%s."
+msgstr ""
+
+#: src/exec_dat.cpp:1545
+msgid ""
+"Evaluate (interpolate) values of array Dat at points i=idat,j=jdat,k=kdat"
+msgstr ""
+
+#. {"defpal",_("Define parameter as palette color"),"defpal $N val", 0, 6},
+#: src/parser.cpp:1430
+msgid "Execute if condition is false"
+msgstr ""
+
+#: mgllab/mgllab.cpp:472
+msgid "Execute script after loading"
+msgstr ""
+
+#: widgets/qt.cpp:1132 udav/plot_pnl.cpp:333
+msgid "Execute script and redraw graphics (F5)."
+msgstr ""
+
+#: src/parser.cpp:1424
+msgid "Execute script in external file"
+msgstr ""
+
+#: mgllab/help.cpp:146
+msgid "Existed data arrays"
+msgstr ""
+
+#: mgllab/mgllab.cpp:290
+msgid "Exit"
+msgstr ""
+
+#: udav/calc_dlg.cpp:192
+msgid "Exp and log"
+msgstr ""
+
+#: udav/calc_dlg.cpp:194
+msgid "Exp-integrals"
+msgstr ""
+
+#: mgllab/table.cpp:473
+msgid "Export Data?"
+msgstr ""
+
+#: widgets/fltk.cpp:789
+msgid "Export as ..."
+msgstr ""
+
+#: widgets/qt.cpp:1067 udav/plot_pnl.cpp:474
+msgid "Export as 2D ..."
+msgstr ""
+
+#: widgets/qt.cpp:1076 udav/plot_pnl.cpp:484
+msgid "Export as 3D ..."
+msgstr ""
+
+#: src/exec_dat.cpp:1546 mgllab/table.cpp:844
+msgid "Export data to PNG file"
+msgstr ""
+
+#. fname = new QLineEdit(this);	a->addWidget(fname);
+#: udav/anim_dlg.cpp:82
+msgid "Export to GIF"
+msgstr ""
+
+#: mgllab/table.cpp:752
+msgid "Export to PNG"
+msgstr ""
+
+#: src/exec_dat.cpp:1547
+msgid "Extend data array"
+msgstr ""
+
+#: mgllab/table.cpp:343
+msgid "Extract data"
+msgstr ""
+
+#: src/exec_dat.cpp:1604
+msgid "Extract sub-array"
+msgstr ""
+
+#: src/exec_dat.cpp:1596
+msgid "Extract sub-array between values"
+msgstr ""
+
+#: mgllab/dialogs.cpp:962
+msgid "Factor"
+msgstr ""
+
+#. file menu
+#: widgets/qt.cpp:1066 udav/udav_wnd.cpp:281 udav/dat_pnl.cpp:681
+#: mgllab/mgllab.cpp:277 mgllab/table.cpp:748
+msgid "File"
+msgstr ""
+
+#: udav/text_pnl.cpp:405 udav/text_pnl.cpp:489
+msgid "File %1 saved"
+msgstr ""
+
+#: mgllab/mgllab.cpp:227
+msgid "File is exesist. Overwrite it?"
+msgstr ""
+
+#: udav/text_pnl.cpp:583
+msgid "File name"
+msgstr ""
+
+#: mgllab/mgllab.cpp:303
+msgid "File path"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1073
+msgid "File to export"
+msgstr ""
+
+#: mgllab/editor.cpp:267 mgllab/mgllab.cpp:396
+msgid "File/Recent files"
+msgstr ""
+
+#: mgllab/table.cpp:765
+msgid "Fill"
+msgstr ""
+
+#: udav/dat_pnl.cpp:611 mgllab/table.cpp:854
+msgid "Fill data by formula"
+msgstr ""
+
+#: src/exec_dat.cpp:1553
+msgid "Fill data by global spline of Vdat"
+msgstr ""
+
+#: src/exec_dat.cpp:1588
+msgid "Fill data by interpolation of Vdat"
+msgstr ""
+
+#: src/exec_dat.cpp:1533
+msgid "Fill data by triangulated values"
+msgstr ""
+
+#: src/exec_dat.cpp:1548
+msgid "Fill data linearly in range [v1, v2]"
+msgstr ""
+
+#: mgllab/table.cpp:578 mgllab/table.cpp:592
+msgid "Fill in range"
+msgstr ""
+
+#: src/exec_dat.cpp:1549
+msgid "Fill x-,k-samples for transforms"
+msgstr ""
+
+#: udav/find_dlg.cpp:48 mgllab/editor.cpp:559
+msgid "Find"
+msgstr ""
+
+#: src/exec_dat.cpp:1529
+msgid "Find correlation between data arrays"
+msgstr ""
+
+#: src/exec_dat.cpp:1543
+msgid "Find envelop for the data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:624
+msgid "Find envelope along direction(s)"
+msgstr ""
+
+#: udav/dat_pnl.cpp:804
+msgid "Find histogram of data."
+msgstr ""
+
+#: src/exec_dat.cpp:1564
+msgid "Find maximal value over direction"
+msgstr ""
+
+#: src/exec_dat.cpp:1565
+msgid "Find minimal value over direction"
+msgstr ""
+
+#: udav/text_pnl.cpp:551 mgllab/mgllab.cpp:301
+msgid "Find next"
+msgstr ""
+
+#: mgllab/editor.cpp:515
+msgid "Find or replace text"
+msgstr ""
+
+#: src/exec_dat.cpp:1600
+msgid "Find root Dat[i,j,k]=val (inverse evaluate)"
+msgstr ""
+
+#: src/exec_dat.cpp:1592
+msgid "Find roots using data as initial values"
+msgstr ""
+
+#: src/exec_dat.cpp:1606
+msgid "Find summation over direction"
+msgstr ""
+
+#: src/exec_dat.cpp:1612
+msgid "Find triangles of randomly placed points"
+msgstr ""
+
+#: udav/find_dlg.cpp:36 mgllab/editor.cpp:558
+msgid "Find what:"
+msgstr ""
+
+#: udav/text_pnl.cpp:546 mgllab/editor.cpp:557
+msgid "Find/Replace"
+msgstr ""
+
+#: mgllab/mgllab.cpp:300
+msgid "Find|Replace"
+msgstr ""
+
+#: src/parser.cpp:1432
+msgid "Finish if/else block"
+msgstr ""
+
+#: mgllab/table.cpp:804
+msgid "First cell"
+msgstr ""
+
+#: udav/dat_pnl.cpp:721 mgllab/table.cpp:800
+msgid "First slice"
+msgstr ""
+
+#: src/exec_dat.cpp:1550 src/exec_dat.cpp:1551
+msgid "Fit data to formula"
+msgstr ""
+
+#: udav/text_pnl.cpp:567 mgllab/mgllab.cpp:307
+msgid "Fitted formula"
+msgstr ""
+
+#: udav/prop_dlg.cpp:103
+msgid "FlowKey"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1009
+msgid "Fog"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1010
+msgid "Fog dist."
+msgstr ""
+
+#: mgllab/mgllab.cpp:533
+msgid "Folder for help files"
+msgstr ""
+
+#: udav/text_pnl.cpp:587 mgllab/mgllab.cpp:304
+msgid "Folder path"
+msgstr ""
+
+#: udav/setup_dlg.cpp:105 mgllab/dialogs.cpp:1007
+msgid "Font"
+msgstr ""
+
+#: mgllab/mgllab.cpp:524
+msgid "Font file name"
+msgstr ""
+
+#: udav/prop_dlg.cpp:199
+msgid "Font files (*.vfm)"
+msgstr ""
+
+#: mgllab/mgllab.cpp:463
+msgid "Font kind"
+msgstr ""
+
+#: mgllab/mgllab.cpp:465
+msgid "Font size"
+msgstr ""
+
+#: udav/style_dlg.cpp:183
+msgid "Font style"
+msgstr ""
+
+#: udav/setup_dlg.cpp:107
+msgid "FontSize"
+msgstr ""
+
+#: src/parser.cpp:1433
+msgid "For loop"
+msgstr ""
+
+#: udav/help_pnl.cpp:52
+msgid "Forward"
+msgstr ""
+
+#: udav/plot_pnl.cpp:192
+msgid "Frame %1 of %2"
+msgstr ""
+
+#: udav/dat_pnl.cpp:351 udav/dat_pnl.cpp:366 udav/dat_pnl.cpp:377
+#: udav/dat_pnl.cpp:424 udav/dat_pnl.cpp:452 mgllab/table.cpp:608
+msgid "From"
+msgstr ""
+
+#: mgllab/mgllab.cpp:592
+msgid "Function"
+msgstr ""
+
+#. B
+#: udav/style_dlg.cpp:238 mgllab/dialogs.cpp:46
+msgid "G - green"
+msgstr ""
+
+#: src/export.cpp:306 src/export.cpp:375 src/export.cpp:388
+msgid "GIF support was disabled. Please, enable it and rebuild MathGL."
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:178 udav/setup_dlg.cpp:112 mgllab/dialogs.cpp:719
+#: mgllab/dialogs.cpp:1001
+msgid "General setup"
+msgstr ""
+
+#: src/exec_dat.cpp:1561
+msgid "Get Jacobian"
+msgstr ""
+
+#: src/exec_dat.cpp:1526
+msgid "Get data column filled by formula on column ids"
+msgstr ""
+
+#: src/exec_dat.cpp:1595
+msgid "Get formated data from file"
+msgstr ""
+
+#: src/exec_dat.cpp:1568
+msgid "Get momentum along direction"
+msgstr ""
+
+#: src/exec_dat.cpp:1577
+msgid "Get pulse properties"
+msgstr ""
+
+#: src/exec_dat.cpp:1608
+msgid "Get trace of array"
+msgstr ""
+
+#: src/base_cf.cpp:85
+#, c-format
+msgid "Global message - %s\n"
+msgstr ""
+
+#: udav/dat_pnl.cpp:723 mgllab/table.cpp:865
+msgid "Go to first slice for 3D data (Ctrl-F1)."
+msgstr ""
+
+#: udav/dat_pnl.cpp:753 mgllab/table.cpp:869
+msgid "Go to last slice for 3D data (Ctrl-F4)."
+msgstr ""
+
+#: udav/dat_pnl.cpp:740
+msgid "Go to slice"
+msgstr ""
+
+#: udav/dat_pnl.cpp:747
+msgid "Go to the next slice for 3D data."
+msgstr ""
+
+#: udav/dat_pnl.cpp:729
+msgid "Go to the previous slice for 3D data."
+msgstr ""
+
+#: udav/dat_pnl.cpp:735 udav/dat_pnl.cpp:742
+msgid "Go to the specified slice for 3D data."
+msgstr ""
+
+#: widgets/qt.cpp:1095 widgets/qt.cpp:1097 udav/plot_pnl.cpp:66
+#: mgllab/mgllab.cpp:319
+msgid "Graphics"
+msgstr ""
+
+#: udav/text_pnl.cpp:596
+msgid "Graphics setup"
+msgstr ""
+
+#: widgets/fltk.cpp:927
+msgid "Graphics/Adjust size"
+msgstr ""
+
+#. /< Parameter for handling animation
+#. /< Callback function for next frame
+#. /< Callback function for prev frame
+#. /< Callback function for delay
+#. /< Callback function for reloading
+#: widgets/fltk.cpp:921 include/mgl2/Fl_MathGL.h:150
+msgid "Graphics/Alpha"
+msgstr ""
+
+#: widgets/fltk.cpp:956
+msgid "Graphics/Animation/Next frame"
+msgstr ""
+
+#: widgets/fltk.cpp:957
+msgid "Graphics/Animation/Prev frame"
+msgstr ""
+
+#: mgllab/mgllab.cpp:371
+msgid "Graphics/Animation/Setup animation"
+msgstr ""
+
+#: widgets/fltk.cpp:955 include/mgl2/Fl_MathGL.h:152
+msgid "Graphics/Animation/Slideshow"
+msgstr ""
+
+#: widgets/fltk.cpp:931
+msgid "Graphics/Copy click coor."
+msgstr ""
+
+#: widgets/fltk.cpp:930
+msgid "Graphics/Copy graphics"
+msgstr ""
+
+#: widgets/fltk.cpp:944
+msgid "Graphics/Export/as BMP"
+msgstr ""
+
+#: widgets/fltk.cpp:942
+msgid "Graphics/Export/as GIF"
+msgstr ""
+
+#: widgets/fltk.cpp:939
+msgid "Graphics/Export/as JPEG"
+msgstr ""
+
+#: widgets/fltk.cpp:950
+msgid "Graphics/Export/as OBJ"
+msgstr ""
+
+#: widgets/fltk.cpp:951
+msgid "Graphics/Export/as OFF"
+msgstr ""
+
+#: widgets/fltk.cpp:935
+msgid "Graphics/Export/as PNG"
+msgstr ""
+
+#: widgets/fltk.cpp:949
+msgid "Graphics/Export/as PRC"
+msgstr ""
+
+#: widgets/fltk.cpp:952
+msgid "Graphics/Export/as STL"
+msgstr ""
+
+#: widgets/fltk.cpp:945
+msgid "Graphics/Export/as SVG"
+msgstr ""
+
+#: widgets/fltk.cpp:948
+msgid "Graphics/Export/as TeX"
+msgstr ""
+
+#: widgets/fltk.cpp:953
+msgid "Graphics/Export/as XYZ"
+msgstr ""
+
+#: widgets/fltk.cpp:947
+msgid "Graphics/Export/as bitmap EPS"
+msgstr ""
+
+#: widgets/fltk.cpp:936
+msgid "Graphics/Export/as solid PNG"
+msgstr ""
+
+#: widgets/fltk.cpp:946
+msgid "Graphics/Export/as vector EPS"
+msgstr ""
+
+#: widgets/fltk.cpp:923 include/mgl2/Fl_MathGL.h:153
+msgid "Graphics/Grid"
+msgstr ""
+
+#: widgets/fltk.cpp:922 include/mgl2/Fl_MathGL.h:151
+msgid "Graphics/Light"
+msgstr ""
+
+#: widgets/fltk.cpp:932 include/mgl2/Fl_MathGL.h:159 mgllab/mgllab.cpp:372
+msgid "Graphics/Pause calc"
+msgstr ""
+
+#: mgllab/mgllab.cpp:370
+msgid "Graphics/Primitive"
+msgstr ""
+
+#: widgets/fltk.cpp:926
+msgid "Graphics/Redraw"
+msgstr ""
+
+#: widgets/fltk.cpp:928
+msgid "Graphics/Reload data"
+msgstr ""
+
+#: widgets/fltk.cpp:925
+msgid "Graphics/Restore"
+msgstr ""
+
+#: widgets/fltk.cpp:929
+msgid "Graphics/Stop"
+msgstr ""
+
+#: widgets/fltk.cpp:963
+msgid "Graphics/Transform/Move down"
+msgstr ""
+
+#: widgets/fltk.cpp:959
+msgid "Graphics/Transform/Move left"
+msgstr ""
+
+#: widgets/fltk.cpp:964
+msgid "Graphics/Transform/Move right"
+msgstr ""
+
+#: widgets/fltk.cpp:960
+msgid "Graphics/Transform/Move up"
+msgstr ""
+
+#: widgets/fltk.cpp:961
+msgid "Graphics/Transform/Zoom in"
+msgstr ""
+
+#: widgets/fltk.cpp:962
+msgid "Graphics/Transform/Zoom out"
+msgstr ""
+
+#: udav/plot_pnl.cpp:304
+msgid "Grid"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:50 mgllab/dialogs.cpp:705
+msgid "Groups of MGL commands"
+msgstr ""
+
+#. P
+#: udav/style_dlg.cpp:249 mgllab/dialogs.cpp:57
+msgid "H - darkgray"
+msgstr ""
+
+#: src/data_io.cpp:1085
+msgid "HDF4 support was disabled. Please, enable it and rebuild MathGL."
+msgstr ""
+
+#: src/complex_io.cpp:922 src/complex_io.cpp:924 src/data_io.cpp:1184
+#: src/data_io.cpp:1186 src/data_io.cpp:1188 src/data_io.cpp:1190
+msgid "HDF5 support was disabled. Please, enable it and rebuild MathGL."
+msgstr ""
+
+#: mgllab/table.cpp:165 mgllab/table.cpp:779
+msgid "Hankel"
+msgstr ""
+
+#: udav/dat_pnl.cpp:622
+msgid "Hankel transform along direction(s)"
+msgstr ""
+
+#: src/exec_dat.cpp:1554
+msgid "Hankel transform at some direction"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:84
+msgid "Height of selected cells"
+msgstr ""
+
+#: widgets/qt.cpp:1276 udav/help_pnl.cpp:57 udav/udav_wnd.cpp:231
+#: udav/udav_wnd.cpp:323 mgllab/mgllab.cpp:329 mgllab/mgllab.cpp:330
+#: mgllab/mgllab.cpp:358
+msgid "Help"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:73
+msgid ""
+"Here you can specify command options.\n"
+"Options are used for additional plot tunning."
+msgstr ""
+
+#: udav/udav_wnd.cpp:186 mgllab/mgllab.cpp:298
+msgid "Hidden plots"
+msgstr ""
+
+#: udav/plot_pnl.cpp:431
+msgid "Hide selected"
+msgstr ""
+
+#: udav/plot_pnl.cpp:433
+msgid "Hide selected plots."
+msgstr ""
+
+#: udav/prop_dlg.cpp:173 mgllab/mgllab.cpp:475
+msgid "Highlight current object(s)"
+msgstr ""
+
+#: udav/udav_wnd.cpp:328 mgllab/mgllab.cpp:331
+msgid "Hints"
+msgstr ""
+
+#: udav/dat_pnl.cpp:802
+msgid "Histogram (Ctrl+Shift+H)"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:51 udav/subplot_dlg.cpp:68 udav/subplot_dlg.cpp:93
+msgid "Horizontal size"
+msgstr ""
+
+#: udav/calc_dlg.cpp:192
+msgid "Hyperbolic"
+msgstr ""
+
+#: udav/setup_dlg.cpp:116
+msgid "ID"
+msgstr ""
+
+#: mgllab/mgllab.cpp:333
+msgid "Icon list"
+msgstr ""
+
+#: mgllab/table.cpp:867
+msgid "Id of slice on third (z-) dimension"
+msgstr ""
+
+#: udav/prop_dlg.cpp:154
+msgid "Image size"
+msgstr ""
+
+#: src/exec_dat.cpp:1576
+msgid "Immediately print the message"
+msgstr ""
+
+#: mgllab/table.cpp:485
+msgid "Import Data?"
+msgstr ""
+
+#: src/exec_dat.cpp:1557 mgllab/table.cpp:840
+msgid "Import data from PNG file"
+msgstr ""
+
+#: mgllab/table.cpp:750
+msgid "Import from PNG"
+msgstr ""
+
+#: mgllab/table.cpp:767
+msgid "In range"
+msgstr ""
+
+#: src/exec_dat.cpp:1552
+msgid "In-place Fourier transform"
+msgstr ""
+
+#: mgllab/mathgl.cpp:245
+msgid "Incompatible loop parameters!"
+msgstr ""
+
+#: mgllab/table.cpp:503
+msgid "Incorrect type of base data"
+msgstr ""
+
+#: udav/plot_pnl.cpp:552
+msgid "Increase \\phi angle by 10 degrees."
+msgstr ""
+
+#: udav/plot_pnl.cpp:544
+msgid "Increase \\theta angle by 10 degrees."
+msgstr ""
+
+#: mgllab/help.cpp:103
+msgid "Increase font size"
+msgstr ""
+
+#: udav/udav_wnd.cpp:229
+msgid "Info"
+msgstr ""
+
+#: udav/info_dlg.cpp:55 mgllab/help.cpp:353
+msgid "Information"
+msgstr ""
+
+#: mgllab/mgllab.cpp:306
+msgid "Inplot"
+msgstr ""
+
+#. insert menu
+#: udav/text_pnl.cpp:557 mgllab/mgllab.cpp:302
+msgid "Insert"
+msgstr ""
+
+#: mgllab/editor.cpp:518
+msgid "Insert MGL command"
+msgstr ""
+
+#: mgllab/table.cpp:753
+msgid "Insert as 'list'"
+msgstr ""
+
+#: mgllab/editor.cpp:486
+msgid "Insert file content?"
+msgstr ""
+
+#: mgllab/mgllab.cpp:148
+msgid "Insert file name?"
+msgstr ""
+
+#: mgllab/editor.cpp:520
+msgid "Insert filename"
+msgstr ""
+
+#: mgllab/editor.cpp:522
+msgid "Insert inplot command"
+msgstr ""
+
+#: udav/text_pnl.cpp:569
+msgid "Insert last fitted formula with found coefficients."
+msgstr ""
+
+#: src/exec_dat.cpp:1559
+msgid "Insert slice of data"
+msgstr ""
+
+#: mgllab/table.cpp:847
+msgid "Insert to script as 'list' command"
+msgstr ""
+
+#: mgllab/table.cpp:163 mgllab/table.cpp:773
+msgid "Integrate"
+msgstr ""
+
+#: src/exec_dat.cpp:1560 udav/dat_pnl.cpp:615
+msgid "Integrate data along direction(s)"
+msgstr ""
+
+#: mgllab/dialogs.cpp:114
+msgid "Intensity of diffuse light"
+msgstr ""
+
+#: udav/style_dlg.cpp:158 mgllab/dialogs.cpp:369
+msgid "Italic style"
+msgstr ""
+
+#: widgets/qt.cpp:1070 udav/plot_pnl.cpp:477
+msgid "JPEG"
+msgstr ""
+
+#: src/data_png.cpp:162 src/export.cpp:192
+msgid "JPEG support was disabled. Please, enable it and rebuild MathGL."
+msgstr ""
+
+#: udav/calc_dlg.cpp:193
+msgid "Jacobi"
+msgstr ""
+
+#: src/exec_dat.cpp:1562
+msgid "Join data arrays"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1075
+msgid "Keep empty to put at beginning of main script."
+msgstr ""
+
+#: udav/dat_pnl.cpp:780
+msgid "Keep only each n-th element of the data array."
+msgstr ""
+
+#: mgllab/mathgl.cpp:198
+msgid "Keep slides in memory (faster animation but require more memory)"
+msgstr ""
+
+#: udav/prop_dlg.cpp:88
+msgid "Keywords"
+msgstr ""
+
+#: mgllab/dialogs.cpp:354 mgllab/dialogs.cpp:704 mgllab/dialogs.cpp:1457
+msgid "Kind"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:58
+msgid ""
+"Kind of command argument order. The notation is:\n"
+" * Capital arguments are data (like, Ydat);\n"
+" * Argument in '' are strings (like, 'fmt');\n"
+" * Other arguments are numbers (like, zval);\n"
+" * Arguments in [] are optional arguments."
+msgstr ""
+
+#: udav/info_dlg.cpp:50
+msgid "Kind of plots: lines for 1D, density for 2D."
+msgstr ""
+
+#. Y
+#: udav/style_dlg.cpp:243 mgllab/dialogs.cpp:51
+msgid "L - seagreen"
+msgstr ""
+
+#: widgets/qt.cpp:1074 udav/plot_pnl.cpp:481
+msgid "LaTeX"
+msgstr ""
+
+#: udav/setup_dlg.cpp:66 mgllab/dialogs.cpp:954
+msgid "Label"
+msgstr ""
+
+#: udav/prop_dlg.cpp:139
+msgid "Language for UDAV"
+msgstr ""
+
+#: mgllab/mgllab.cpp:478
+msgid "Language for mgllab"
+msgstr ""
+
+#: udav/dat_pnl.cpp:617
+msgid "Laplace transform along direction(s)"
+msgstr ""
+
+#: mgllab/table.cpp:775
+msgid "Laplacian"
+msgstr ""
+
+#: udav/dat_pnl.cpp:751 mgllab/table.cpp:803
+msgid "Last slice"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:144
+msgid "Left bottom edge"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:152
+msgid "Left top edge"
+msgstr ""
+
+#: udav/opt_dlg.cpp:74 mgllab/dialogs.cpp:118
+msgid "Legend"
+msgstr ""
+
+#: widgets/qt.cpp:1104 udav/opt_dlg.cpp:64 udav/setup_dlg.cpp:110
+#: udav/plot_pnl.cpp:297 mgllab/dialogs.cpp:115
+msgid "Light"
+msgstr ""
+
+#: udav/setup_dlg.cpp:190
+msgid "Light position should be filled. Ignore it."
+msgstr ""
+
+#: udav/setup_dlg.cpp:136 mgllab/dialogs.cpp:1053
+msgid "Light settings"
+msgstr ""
+
+#: src/exec_dat.cpp:1563
+msgid "Limit data to be inside [-v,v]"
+msgstr ""
+
+#: udav/style_dlg.cpp:99 mgllab/dialogs.cpp:314
+msgid "Line style"
+msgstr ""
+
+#: udav/style_dlg.cpp:78
+msgid "Line width"
+msgstr ""
+
+#: mgllab/table.cpp:167
+msgid "Linear *3"
+msgstr ""
+
+#: mgllab/table.cpp:167
+msgid "Linear *5"
+msgstr ""
+
+#: mgllab/help.cpp:156
+msgid "List of available data."
+msgstr ""
+
+#: mgllab/table.cpp:427
+msgid "Load Data?"
+msgstr ""
+
+#: src/exec_set.cpp:719
+msgid "Load commands from external DLL"
+msgstr ""
+
+#: udav/dat_pnl.cpp:682
+msgid "Load data"
+msgstr ""
+
+#: mgllab/table.cpp:838
+msgid "Load data from file"
+msgstr ""
+
+#: udav/dat_pnl.cpp:684
+msgid ""
+"Load data from file. Data will be deleted only\n"
+"at exit but UDAV will not ask to save it (Ctrl+Shift+O)."
+msgstr ""
+
+#: src/exec_set.cpp:720
+msgid "Load fontfaces"
+msgstr ""
+
+#: mgllab/table.cpp:749
+msgid "Load from file"
+msgstr ""
+
+#: src/exec_prm.cpp:580
+msgid "Load image for background"
+msgstr ""
+
+#: udav/prop_dlg.cpp:163
+msgid "Load script to new window"
+msgstr ""
+
+#: udav/text_pnl.cpp:467
+msgid "Loaded document "
+msgstr ""
+
+#: udav/text_pnl.cpp:325
+msgid "Loaded document %1"
+msgstr ""
+
+#: udav/udav_wnd.cpp:638
+msgid "Loading aborted"
+msgstr ""
+
+#: mgllab/dialogs.cpp:98
+msgid "Low border for determining color or alpha"
+msgstr ""
+
+#. C
+#: udav/style_dlg.cpp:241 mgllab/dialogs.cpp:49
+msgid "M - purple"
+msgstr ""
+
+#: src/parser.cpp:1018
+msgid "MGL Parser"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:53 mgllab/dialogs.cpp:725
+msgid "MGL commands for selected group"
+msgstr ""
+
+#: mgllab/mgllab.cpp:214
+msgid "MGL files \t*.mgl"
+msgstr ""
+
+#: mgllab/mgllab.cpp:173
+msgid ""
+"MGL files \t*.mgl\n"
+"DAT files \t*.{dat,csv}"
+msgstr ""
+
+#: udav/open_dlg.cpp:102
+msgid "MGL files (*.mgl)"
+msgstr ""
+
+#: udav/udav_wnd.cpp:324
+msgid "MGL help"
+msgstr ""
+
+#: mgllab/mathgl.cpp:421
+msgid "MGL messages"
+msgstr ""
+
+#: mgllab/help.cpp:101
+msgid "MGL samples and hints"
+msgstr ""
+
+#: udav/udav_wnd.cpp:670
+msgid ""
+"MGL scripts (*.mgl)\n"
+"HDF5 files (*.hdf *.h5)\n"
+"All files (*.*)"
+msgstr ""
+
+#: udav/udav_wnd.cpp:635
+msgid ""
+"MGL scripts (*.mgl)\n"
+"HDF5 files (*.hdf *.h5)\n"
+"Text files (*.txt)\n"
+"Data files (*.dat)\n"
+"All files (*.*)"
+msgstr ""
+
+#: widgets/qt.cpp:1077 udav/plot_pnl.cpp:485
+msgid "MGLD"
+msgstr ""
+
+#: udav/dat_pnl.cpp:798
+msgid "Make another data."
+msgstr ""
+
+#: udav/dat_pnl.cpp:796
+msgid "Make new (Ctrl+Shift+M)"
+msgstr ""
+
+#: udav/style_dlg.cpp:83 mgllab/dialogs.cpp:336
+msgid "Manual dashing"
+msgstr ""
+
+#: udav/style_dlg.cpp:196
+msgid "Manual mask"
+msgstr ""
+
+#: udav/text_pnl.cpp:591 mgllab/mgllab.cpp:308
+msgid "Manual primitives"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1467
+msgid "Mark"
+msgstr ""
+
+#: udav/style_dlg.cpp:76 mgllab/dialogs.cpp:324
+msgid "Marks"
+msgstr ""
+
+#: mgllab/dialogs.cpp:352
+msgid "Mask"
+msgstr ""
+
+#: udav/style_dlg.cpp:124
+msgid "Mask for bitmap coloring"
+msgstr ""
+
+#: udav/style_dlg.cpp:125
+msgid "Mask rotation angle"
+msgstr ""
+
+#: udav/style_dlg.cpp:126
+msgid "Mask size"
+msgstr ""
+
+#: udav/find_dlg.cpp:42 mgllab/editor.cpp:562
+msgid "Match case"
+msgstr ""
+
+#: widgets/qt.cpp:860
+msgid "MathGL - about"
+msgstr ""
+
+#: src/base.cpp:250
+#, c-format
+msgid "MathGL message - %s\n"
+msgstr ""
+
+#: widgets/qt.cpp:859
+msgid "MathGL v. 2."
+msgstr ""
+
+#: udav/open_dlg.cpp:70
+msgid "Matrix with sizes from file"
+msgstr ""
+
+#: udav/dat_pnl.cpp:541
+msgid "Max along direction(s)"
+msgstr ""
+
+#: udav/setup_dlg.cpp:57 mgllab/dialogs.cpp:952
+msgid "Maximal"
+msgstr ""
+
+#: mgllab/table.cpp:546
+msgid "Maximal value (v2)"
+msgstr ""
+
+#: mgllab/table.cpp:548
+msgid "Maximal value for resulting data values"
+msgstr ""
+
+#: mgllab/dialogs.cpp:88
+msgid "Maximal value of X for cutting or for coordinate filling"
+msgstr ""
+
+#: mgllab/dialogs.cpp:92
+msgid "Maximal value of Y for cutting or for coordinate filling"
+msgstr ""
+
+#: mgllab/dialogs.cpp:96
+msgid "Maximal value of Z for cutting or for coordinate filling"
+msgstr ""
+
+#: src/data.cpp:1417
+#, c-format
+msgid "Maximum is %g\t at x = %ld\ty = %ld\tz = %ld\n"
+msgstr ""
+
+#: mgllab/table.cpp:342 mgllab/table.cpp:789
+msgid "Maximum of"
+msgstr ""
+
+#: udav/mem_pnl.cpp:68 udav/mem_pnl.cpp:73 mgllab/mgllab.cpp:360
+msgid "Memory"
+msgstr ""
+
+#: udav/opt_dlg.cpp:53
+msgid "Mesh num"
+msgstr ""
+
+#: udav/setup_dlg.cpp:99 mgllab/dialogs.cpp:102
+msgid "MeshNum"
+msgstr ""
+
+#: mgllab/mgllab.cpp:327
+msgid "Messages"
+msgstr ""
+
+#: udav/udav_wnd.cpp:178
+msgid "Messages and warnings"
+msgstr ""
+
+#: udav/dat_pnl.cpp:540
+msgid "Min along direction(s)"
+msgstr ""
+
+#: udav/setup_dlg.cpp:52 mgllab/dialogs.cpp:951
+msgid "Minimal"
+msgstr ""
+
+#: mgllab/table.cpp:543
+msgid "Minimal value (v1)"
+msgstr ""
+
+#: mgllab/table.cpp:545
+msgid "Minimal value for resulting data values"
+msgstr ""
+
+#: mgllab/dialogs.cpp:86
+msgid "Minimal value of X for cutting or for coordinate filling"
+msgstr ""
+
+#: mgllab/dialogs.cpp:90
+msgid "Minimal value of Y for cutting or for coordinate filling"
+msgstr ""
+
+#: mgllab/dialogs.cpp:94
+msgid "Minimal value of Z for cutting or for coordinate filling"
+msgstr ""
+
+#: src/data.cpp:1420
+#, c-format
+msgid "Minimum is %g\t at x = %ld\ty = %ld\tz = %ld\n"
+msgstr ""
+
+#: mgllab/table.cpp:342 mgllab/table.cpp:790
+msgid "Minimum of"
+msgstr ""
+
+#. { _("Wavelet"),	0, wavelet_cb },
+#: mgllab/table.cpp:166 mgllab/table.cpp:781
+msgid "Mirror"
+msgstr ""
+
+#: udav/dat_pnl.cpp:619
+msgid "Mirror data along direction(s)"
+msgstr ""
+
+#: src/exec_dat.cpp:1566
+msgid "Mirror data at some direction"
+msgstr ""
+
+#: src/exec_dat.cpp:1567
+msgid "Modify data values by formula"
+msgstr ""
+
+#: udav/dat_pnl.cpp:542
+msgid "Momentum along 'x' for function"
+msgstr ""
+
+#: udav/dat_pnl.cpp:543
+msgid "Momentum along 'y' for function"
+msgstr ""
+
+#: udav/dat_pnl.cpp:544
+msgid "Momentum along 'z' for function"
+msgstr ""
+
+#: widgets/qt.cpp:1233 udav/plot_pnl.cpp:527
+msgid "Move down"
+msgstr ""
+
+#: widgets/qt.cpp:1219 udav/plot_pnl.cpp:506
+msgid "Move graphics left by 1/3 of its width."
+msgstr ""
+
+#: widgets/qt.cpp:1239 udav/plot_pnl.cpp:536
+msgid "Move graphics right by 1/3 of its width."
+msgstr ""
+
+#: widgets/qt.cpp:1223 udav/plot_pnl.cpp:512
+msgid "Move graphics up by 1/3 of its height."
+msgstr ""
+
+#: widgets/qt.cpp:1235 udav/plot_pnl.cpp:530
+msgid "Move graphics up down 1/3 of its height."
+msgstr ""
+
+#: widgets/qt.cpp:1217 udav/plot_pnl.cpp:503
+msgid "Move left"
+msgstr ""
+
+#: udav/text_pnl.cpp:593
+msgid "Move mouse-handled primitives to script."
+msgstr ""
+
+#: udav/plot_pnl.cpp:454
+msgid "Move plot down"
+msgstr ""
+
+#: udav/plot_pnl.cpp:449
+msgid "Move plot up"
+msgstr ""
+
+#: widgets/qt.cpp:1237 udav/plot_pnl.cpp:533
+msgid "Move right"
+msgstr ""
+
+#: udav/plot_pnl.cpp:456
+msgid "Move selected plot down to next subplot."
+msgstr ""
+
+#: udav/plot_pnl.cpp:451
+msgid "Move selected plot up to previous subplot."
+msgstr ""
+
+#: widgets/qt.cpp:1221 udav/plot_pnl.cpp:509
+msgid "Move up"
+msgstr ""
+
+#: mgllab/table.cpp:796
+msgid "Multiply by"
+msgstr ""
+
+#: src/exec_dat.cpp:1569
+msgid "Multiply by data or number"
+msgstr ""
+
+#. E
+#: udav/style_dlg.cpp:245 mgllab/dialogs.cpp:53
+msgid "N - darkskyblue"
+msgstr ""
+
+#: udav/dat_pnl.cpp:500
+msgid "NOTE: All fields must be filled!"
+msgstr ""
+
+#: udav/mem_pnl.cpp:68
+msgid "Name"
+msgstr ""
+
+#: mgllab/table.cpp:349
+msgid "Name for output"
+msgstr ""
+
+#. navigation menu
+#: udav/dat_pnl.cpp:720 mgllab/table.cpp:799
+msgid "Navigation"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:101 udav/newcmd_dlg.cpp:310 udav/newcmd_dlg.cpp:338
+#: udav/newcmd_dlg.cpp:342 udav/newcmd_dlg.cpp:356 udav/newcmd_dlg.cpp:369
+#: udav/newcmd_dlg.cpp:377 udav/newcmd_dlg.cpp:381 udav/newcmd_dlg.cpp:385
+#: udav/text_pnl.cpp:558 udav/plot_pnl.cpp:439 mgllab/dialogs.cpp:702
+msgid "New command"
+msgstr ""
+
+#: udav/hint_dlg.cpp:40 mgllab/help.cpp:274
+msgid ""
+"New drawing never clears things drawn already. For example, you can make a "
+"surface with contour lines by calling commands 'surf' and 'cont' one after "
+"another (in any order). "
+msgstr ""
+
+#: udav/text_pnl.cpp:562 udav/plot_pnl.cpp:444
+msgid "New inplot"
+msgstr ""
+
+#: mgllab/table.cpp:671
+msgid "New order of dimensions"
+msgstr ""
+
+#: udav/udav_wnd.cpp:282 mgllab/mgllab.cpp:278
+msgid "New script"
+msgstr ""
+
+#: mgllab/table.cpp:95
+msgid "New size of data on 1st dimension (x-direction)"
+msgstr ""
+
+#: mgllab/table.cpp:97
+msgid "New size of data on 2nd dimension (y-direction)"
+msgstr ""
+
+#: mgllab/table.cpp:99
+msgid "New size of data on 3d dimension (z-direction)"
+msgstr ""
+
+#: udav/hint_dlg.cpp:68
+msgid "Next"
+msgstr ""
+
+#: mgllab/help.cpp:306
+msgid "Next @->"
+msgstr ""
+
+#: udav/dat_pnl.cpp:745 mgllab/table.cpp:802
+msgid "Next slice"
+msgstr ""
+
+#: widgets/qt.cpp:1247 udav/plot_pnl.cpp:560
+msgid "Next slide"
+msgstr ""
+
+#: mgllab/help.cpp:135 mgllab/mgllab.cpp:227
+msgid "No"
+msgstr ""
+
+#: udav/dat_pnl.cpp:567 udav/dat_pnl.cpp:644
+msgid "No action is selected. Do nothing."
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:310
+msgid "No argument is selected"
+msgstr ""
+
+#: udav/dat_pnl.cpp:573
+msgid "No direction/formula is entered. Do nothing."
+msgstr ""
+
+#: widgets/qt.cpp:680 widgets/qt.cpp:692 widgets/qt.cpp:704 widgets/qt.cpp:716
+#: widgets/qt.cpp:728 widgets/qt.cpp:736 widgets/qt.cpp:744 widgets/qt.cpp:752
+#: widgets/qt.cpp:760 widgets/qt.cpp:768 widgets/qt.cpp:776 widgets/qt.cpp:784
+#: widgets/qt.cpp:800 widgets/qt.cpp:808 widgets/qt.cpp:816
+msgid "No filename."
+msgstr ""
+
+#: mgllab/editor.cpp:584 mgllab/editor.cpp:606 mgllab/editor.cpp:631
+#, c-format
+msgid "No occurrences of '%s' found!"
+msgstr ""
+
+#: mgllab/mathgl.cpp:260
+msgid "No selection. So nothing to do"
+msgstr ""
+
+#: udav/text_pnl.cpp:202
+msgid "No string occurrence is found"
+msgstr ""
+
+#: udav/setup_dlg.cpp:111
+msgid "No text rotation"
+msgstr ""
+
+#: widgets/fltk.cpp:812
+msgid "Normal view"
+msgstr ""
+
+#: mgllab/table.cpp:768
+msgid "Normalize"
+msgstr ""
+
+#: src/exec_dat.cpp:1571
+msgid "Normalize data"
+msgstr ""
+
+#: src/exec_dat.cpp:1572
+msgid "Normalize data slice by slice"
+msgstr ""
+
+#: mgllab/table.cpp:553
+msgid "Normalize in symmetrical range: -max(|v1|,|v2|) ... max(|v1|,|v2|)"
+msgstr ""
+
+#: udav/udav_wnd.cpp:444
+msgid "Not recognized"
+msgstr ""
+
+#: udav/dat_pnl.cpp:456
+msgid "Number of points"
+msgstr ""
+
+#: udav/prop_dlg.cpp:97
+msgid "Numbers"
+msgstr ""
+
+#: mgllab/table.cpp:176
+msgid "Numeric parameter"
+msgstr ""
+
+#: udav/text_pnl.cpp:579
+msgid "Numeric value"
+msgstr ""
+
+#: src/exec_dat.cpp:1537
+msgid "Numerically differentiate data"
+msgstr ""
+
+#: src/exec_dat.cpp:1538
+msgid "Numerically double differentiate data"
+msgstr ""
+
+#: udav/open_dlg.cpp:64
+msgid "Nx"
+msgstr ""
+
+#: udav/open_dlg.cpp:66
+msgid "Ny"
+msgstr ""
+
+#: udav/open_dlg.cpp:68
+msgid "Nz"
+msgstr ""
+
+#: widgets/qt.cpp:1079 udav/plot_pnl.cpp:487
+msgid "OBJ"
+msgstr ""
+
+#: udav/anim_dlg.cpp:69 udav/prop_dlg.cpp:182 udav/args_dlg.cpp:65
+#: udav/newcmd_dlg.cpp:80 udav/open_dlg.cpp:92 udav/dat_pnl.cpp:462
+#: udav/dat_pnl.cpp:512 udav/dat_pnl.cpp:554 udav/dat_pnl.cpp:631
+#: udav/opt_dlg.cpp:80 udav/files_dlg.cpp:60 udav/style_dlg.cpp:208
+#: udav/data_dlg.cpp:92 udav/subplot_dlg.cpp:221 mgllab/mathgl.cpp:196
+#: mgllab/dialogs.cpp:121 mgllab/dialogs.cpp:165 mgllab/dialogs.cpp:411
+#: mgllab/dialogs.cpp:585 mgllab/dialogs.cpp:750 mgllab/dialogs.cpp:1072
+#: mgllab/dialogs.cpp:1319 mgllab/dialogs.cpp:1474 mgllab/mgllab.cpp:483
+#: mgllab/table.cpp:621
+msgid "OK"
+msgstr ""
+
+#: mgllab/table.cpp:504
+msgid "Only current slice will be inserted"
+msgstr ""
+
+#: mgllab/mgllab.cpp:172
+msgid "Open File?"
+msgstr ""
+
+#: src/exec_dat.cpp:1574
+msgid "Open all data arrays from HDF file"
+msgstr ""
+
+#: udav/udav_wnd.cpp:198
+msgid ""
+"Open and execute/show script or data from file (Ctrl+O).\n"
+"You may switch off automatic exection in UDAV properties."
+msgstr ""
+
+#: mgllab/help.cpp:169
+msgid "Open dialog for new data creation."
+msgstr ""
+
+#: udav/udav_wnd.cpp:196
+msgid "Open file"
+msgstr ""
+
+#: mgllab/mgllab.cpp:279
+msgid "Open file ..."
+msgstr ""
+
+#: widgets/qt.cpp:1088 udav/udav_wnd.cpp:298
+msgid "Open printer dialog and print graphics (Ctrl+P)"
+msgstr ""
+
+#: mgllab/editor.cpp:506
+msgid "Open script or data file"
+msgstr ""
+
+#: mgllab/help.cpp:160
+msgid "Open table with selected data for editing."
+msgstr ""
+
+#: udav/data_dlg.cpp:65 mgllab/dialogs.cpp:578
+msgid "Operation"
+msgstr ""
+
+#: mgllab/table.cpp:231
+msgid "Operation is not supported for this type of data."
+msgstr ""
+
+#: mgllab/table.cpp:793
+msgid "Operations"
+msgstr ""
+
+#: udav/prop_dlg.cpp:91 udav/newcmd_dlg.cpp:72 mgllab/dialogs.cpp:746
+#: mgllab/mgllab.cpp:310
+msgid "Options"
+msgstr ""
+
+#: udav/setup_dlg.cpp:62 mgllab/dialogs.cpp:953
+msgid "Origin"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:171 mgllab/dialogs.cpp:712
+msgid "Other plots"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1025
+msgid "Others"
+msgstr ""
+
+#: udav/style_dlg.cpp:161 mgllab/dialogs.cpp:372
+msgid "Overline"
+msgstr ""
+
+#: mgllab/dialogs.cpp:112
+msgid "Own brightness of the surface"
+msgstr ""
+
+#. Q
+#: udav/style_dlg.cpp:248 mgllab/dialogs.cpp:56
+msgid "P - darkpink"
+msgstr ""
+
+#: src/prc.cpp:981
+msgid "PDF support was disabled. Please, enable it and rebuild MathGL."
+msgstr ""
+
+#: widgets/qt.cpp:1068 udav/plot_pnl.cpp:475
+msgid "PNG"
+msgstr ""
+
+#: mgllab/table.cpp:474 mgllab/table.cpp:486
+msgid "PNG Files \t*.png"
+msgstr ""
+
+#: src/canvas_cf.cpp:502 src/canvas_cf.cpp:504 src/data_png.cpp:122
+#: src/export.cpp:75 src/export.cpp:109
+msgid "PNG support was disabled. Please, enable it and rebuild MathGL."
+msgstr ""
+
+#: widgets/qt.cpp:1078 udav/plot_pnl.cpp:486
+msgid "PRC"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1006
+msgid "Palette"
+msgstr ""
+
+#: mgllab/table.cpp:167
+msgid "Parabolic *5"
+msgstr ""
+
+#: udav/dat_pnl.cpp:713
+msgid "Paste data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:715
+msgid "Paste range of numbers from clipboard (Ctrl+Shift+P)."
+msgstr ""
+
+#: udav/text_pnl.cpp:538 mgllab/mgllab.cpp:296
+msgid "Paste text"
+msgstr ""
+
+#: mgllab/editor.cpp:513
+msgid "Paste text from clipboard"
+msgstr ""
+
+#: udav/text_pnl.cpp:540
+msgid "Paste text or data from clipboard (Ctrl+V)."
+msgstr ""
+
+#: mgllab/mgllab.cpp:469
+msgid "Path for MathGL font (without extension)"
+msgstr ""
+
+#: udav/prop_dlg.cpp:110 mgllab/mgllab.cpp:466
+msgid "Path for help files"
+msgstr ""
+
+#: udav/prop_dlg.cpp:130
+msgid "Path for user MathGL font files"
+msgstr ""
+
+#: widgets/qt.cpp:1265
+msgid "Pause calculation"
+msgstr ""
+
+#. Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(setPause()));
+#: widgets/fltk.cpp:891 widgets/qt.cpp:1270
+msgid "Pause on/off external calculations"
+msgstr ""
+
+#: src/exec_dat.cpp:1590
+msgid "Perform Runge-Kutta step"
+msgstr ""
+
+#: widgets/fltk.cpp:864
+msgid "Phi angle (rotate in x*y plane)"
+msgstr ""
+
+#: udav/prop_dlg.cpp:161
+msgid "Place editor at top"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1050
+msgid "Plot ID"
+msgstr ""
+
+#: src/exec_prm.cpp:596
+msgid "Plot curve by formula"
+msgstr ""
+
+#. o->addSeparator();	bb->addSeparator();
+#. a = new QAction(QPixmap(insert_xpm), _("Insert as list"), this);
+#. connect(a, SIGNAL(triggered()), this, SLOT(list()));
+#. o->addAction(a);
+#. bb = new QToolButton(this);	l->addWidget(bb);	bb->setDefaultAction(a);
+#: udav/dat_pnl.cpp:701
+msgid "Plot data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:703
+msgid ""
+"Plot data in new script window. You may select the kind\n"
+"of plot, its style and so on."
+msgstr ""
+
+#: mgllab/mgllab.cpp:325
+msgid "Plot setup"
+msgstr ""
+
+#: udav/text_pnl.cpp:571 mgllab/dialogs.cpp:312 mgllab/mgllab.cpp:309
+msgid "Plot style"
+msgstr ""
+
+#: src/exec_prm.cpp:597
+msgid "Plot surface by formula"
+msgstr ""
+
+#: mgllab/dialogs.cpp:386
+msgid "Popular color schemes"
+msgstr ""
+
+#: udav/hint_dlg.cpp:66
+msgid "Prev"
+msgstr ""
+
+#: udav/dat_pnl.cpp:727 mgllab/table.cpp:801
+msgid "Prev slice"
+msgstr ""
+
+#: widgets/qt.cpp:1256 udav/plot_pnl.cpp:575
+msgid "Prev slide"
+msgstr ""
+
+#: udav/info_dlg.cpp:51
+msgid "Preview"
+msgstr ""
+
+#: mgllab/mgllab.cpp:566
+msgid "Previous expressions"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:181 mgllab/dialogs.cpp:722
+msgid "Primitives"
+msgstr ""
+
+#: widgets/qt.cpp:1150 udav/plot_pnl.cpp:365
+msgid "Primitives ..."
+msgstr ""
+
+#: src/exec_set.cpp:750
+msgid "Print MathGL version or check if it is valid"
+msgstr ""
+
+#: src/exec_dat.cpp:1542
+msgid "Print content of the data"
+msgstr ""
+
+#: src/exec_dat.cpp:1579
+msgid "Print fitted formula"
+msgstr ""
+
+#: widgets/qt.cpp:1086 udav/udav_wnd.cpp:296
+msgid "Print graphics"
+msgstr ""
+
+#: src/exec_dat.cpp:1534
+msgid "Print list of data names in HDF file"
+msgstr ""
+
+#: src/exec_dat.cpp:1558
+msgid "Print message or information about the data"
+msgstr ""
+
+#: mgllab/mgllab.cpp:282
+msgid "Print plot"
+msgstr ""
+
+#: udav/udav_wnd.cpp:295
+msgid "Print script"
+msgstr ""
+
+#: src/exec_prm.cpp:594
+msgid "Print string from file"
+msgstr ""
+
+#: udav/text_pnl.cpp:178
+msgid "Printing aborted"
+msgstr ""
+
+#: udav/text_pnl.cpp:176
+msgid "Printing completed"
+msgstr ""
+
+#: udav/text_pnl.cpp:174
+msgid "Printing..."
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:180 mgllab/dialogs.cpp:721
+msgid "Program flow"
+msgstr ""
+
+#: udav/udav_wnd.cpp:312 mgllab/mgllab.cpp:322 mgllab/mgllab.cpp:461
+msgid "Properties"
+msgstr ""
+
+#: udav/mem_pnl.cpp:61
+msgid "Properties of selected data array"
+msgstr ""
+
+#: mgllab/table.cpp:342 mgllab/table.cpp:791
+msgid "Pulse prop."
+msgstr ""
+
+#: udav/calc_dlg.cpp:127 mgllab/mgllab.cpp:600
+msgid "Put function"
+msgstr ""
+
+#: udav/dat_pnl.cpp:457
+msgid "Put in variable"
+msgstr ""
+
+#: udav/dat_pnl.cpp:548
+msgid "Put into this data array"
+msgstr ""
+
+#: udav/anim_dlg.cpp:74 mgllab/mathgl.cpp:201
+msgid "Put to script"
+msgstr ""
+
+#: src/exec_dat.cpp:1578
+msgid "Put value (numeric or array) to given data element"
+msgstr ""
+
+#. U
+#: udav/style_dlg.cpp:247 mgllab/dialogs.cpp:55
+msgid "Q - brown"
+msgstr ""
+
+#: udav/udav_wnd.cpp:303
+msgid "Quit"
+msgstr ""
+
+#. G
+#: udav/style_dlg.cpp:239 mgllab/dialogs.cpp:47
+msgid "R - maroon"
+msgstr ""
+
+#: src/exec_set.cpp:733
+msgid "Rasterize plot and save to background"
+msgstr ""
+
+#: src/exec_dat.cpp:1584
+msgid "Read and join data from several files"
+msgstr ""
+
+#: src/exec_dat.cpp:1583
+msgid "Read data from file"
+msgstr ""
+
+#: src/exec_dat.cpp:1586
+msgid "Read data from file with sizes specified in first row"
+msgstr ""
+
+#: src/exec_dat.cpp:1585
+msgid "Read data with name 'id' from HDF file"
+msgstr ""
+
+#: udav/udav_wnd.cpp:268 mgllab/mgllab.cpp:367
+msgid "Ready"
+msgstr ""
+
+#: src/exec_dat.cpp:1587
+msgid "Rearrange data dimensions"
+msgstr ""
+
+#: udav/udav_wnd.cpp:301 mgllab/mgllab.cpp:283
+msgid "Recent files"
+msgstr ""
+
+#: udav/dat_pnl.cpp:768
+msgid "Recreate the data with new sizes and fill it by zeros (Ctrl+Shift+N)."
+msgstr ""
+
+#: udav/text_pnl.cpp:521
+msgid "Redo"
+msgstr ""
+
+#: udav/text_pnl.cpp:523
+msgid "Redo editor change (Ctrl+Shift+Z)."
+msgstr ""
+
+#: widgets/qt.cpp:1130 udav/plot_pnl.cpp:331
+msgid "Redraw"
+msgstr ""
+
+#: udav/anim_dlg.cpp:41 mgllab/mathgl.cpp:184
+msgid "Redraw picture for $0 equal to"
+msgstr ""
+
+#: widgets/fltk.cpp:813
+msgid "Redraw plot"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1320
+msgid "Refresh"
+msgstr ""
+
+#: widgets/fltk.cpp:847
+msgid "Refresh the picture"
+msgstr ""
+
+#: mgllab/dialogs.cpp:404
+msgid "Relative position of i-th color"
+msgstr ""
+
+#: udav/plot_pnl.cpp:342
+msgid "Reload"
+msgstr ""
+
+#: widgets/fltk.cpp:815
+msgid "Reload data"
+msgstr ""
+
+#: widgets/fltk.cpp:853
+msgid "Reload data and refresh the picture"
+msgstr ""
+
+#: src/exec_dat.cpp:1525
+msgid "Remove duplicate rows"
+msgstr ""
+
+#: src/exec_dat.cpp:1597
+msgid "Remove jump into the data, like phase jumps"
+msgstr ""
+
+#: udav/find_dlg.cpp:50 mgllab/editor.cpp:561
+msgid "Replace"
+msgstr ""
+
+#: mgllab/editor.cpp:564
+msgid "Replace all"
+msgstr ""
+
+#: udav/find_dlg.cpp:39 mgllab/editor.cpp:560
+msgid "Replace by:"
+msgstr ""
+
+#: udav/text_pnl.cpp:581
+msgid "Replace expression by its numerical value."
+msgstr ""
+
+#: mgllab/editor.cpp:630
+#, c-format
+msgid "Replaced %ld occurrences."
+msgstr ""
+
+#: mgllab/dialogs.cpp:891
+#, c-format
+msgid "Required argument %s is not specified!"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:186
+msgid "Reserve at"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1303
+msgid "Reserve at:"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:190
+msgid "Reserve space for labels at bottom side (style '_')"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:188
+msgid "Reserve space for labels at left side (style '<')"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:194
+msgid "Reserve space for labels at right side (style '>')"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:192
+msgid "Reserve space for labels at top side (style '^')"
+msgstr ""
+
+#: src/exec_set.cpp:734
+msgid "Reset settings and clear picture"
+msgstr ""
+
+#: udav/dat_pnl.cpp:772 mgllab/table.cpp:759
+msgid "Resize"
+msgstr ""
+
+#: udav/dat_pnl.cpp:774
+msgid "Resize (interpolate) the data to specified sizes (Ctrl+Shift+R)."
+msgstr ""
+
+#: src/exec_dat.cpp:1589
+msgid "Resize data array"
+msgstr ""
+
+#: mgllab/table.cpp:856
+msgid "Resize data with smoothing"
+msgstr ""
+
+#: widgets/qt.cpp:1123 udav/plot_pnl.cpp:325
+msgid "Restore"
+msgstr ""
+
+#: widgets/fltk.cpp:844
+msgid "Restore default graphics rotation, zoom and perspective"
+msgstr ""
+
+#: widgets/qt.cpp:1125
+msgid "Restore default graphics rotation, zoom and perspective (Alt+Space)."
+msgstr ""
+
+#: udav/plot_pnl.cpp:327
+msgid "Restore default graphics rotation, zoom and perspective (Ctrl+Space)."
+msgstr ""
+
+#: udav/plot_pnl.cpp:344
+msgid "Restore status for 'once' command and reload data (F9)."
+msgstr ""
+
+#: udav/calc_dlg.cpp:63 udav/data_dlg.cpp:85 udav/data_dlg.cpp:143
+#: udav/subplot_dlg.cpp:212 mgllab/dialogs.cpp:1315
+msgid "Result"
+msgstr ""
+
+#: udav/data_dlg.cpp:124
+msgid "Result (will have sizes "
+msgstr ""
+
+#: udav/style_dlg.cpp:201 udav/subplot_dlg.cpp:214 mgllab/dialogs.cpp:408
+msgid "Resulting string"
+msgstr ""
+
+#: src/parser.cpp:1439
+msgid "Return from function"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:148
+msgid "Right bottom edge"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:156
+msgid "Right top edge"
+msgstr ""
+
+#: mgllab/table.cpp:166 mgllab/table.cpp:782
+msgid "Roll"
+msgstr ""
+
+#: src/exec_dat.cpp:1591
+msgid "Roll data along direction(s)"
+msgstr ""
+
+#. rotate menu
+#: udav/plot_pnl.cpp:540
+msgid "Rotate"
+msgstr ""
+
+#: widgets/qt.cpp:1110 udav/plot_pnl.cpp:310
+msgid "Rotate by mouse"
+msgstr ""
+
+#: udav/plot_pnl.cpp:545
+msgid "Rotate down"
+msgstr ""
+
+#: udav/plot_pnl.cpp:549
+msgid "Rotate left"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:164 mgllab/dialogs.cpp:1294
+msgid "Rotate on"
+msgstr ""
+
+#: widgets/fltk.cpp:840
+msgid "Rotate picture by holding left mouse button"
+msgstr ""
+
+#: src/exec_set.cpp:735
+msgid "Rotate plot"
+msgstr ""
+
+#: udav/plot_pnl.cpp:553
+msgid "Rotate right"
+msgstr ""
+
+#: udav/plot_pnl.cpp:541
+msgid "Rotate up"
+msgstr ""
+
+#: mgllab/dialogs.cpp:356
+msgid "Rotation"
+msgstr ""
+
+#: widgets/qt.cpp:1254
+msgid "Run slideshow (CTRl+F5)."
+msgstr ""
+
+#: udav/plot_pnl.cpp:570
+msgid ""
+"Run slideshow (Ctrl+F5). If no parameter specified\n"
+"then the dialog with slideshow options will appear."
+msgstr ""
+
+#: widgets/fltk.cpp:885
+msgid "Run/Stop slideshow (graphics animation)"
+msgstr ""
+
+#: udav/prop_dlg.cpp:141
+msgid "Russian"
+msgstr ""
+
+#: widgets/qt.cpp:1080 udav/plot_pnl.cpp:488
+msgid "STL"
+msgstr ""
+
+#: widgets/qt.cpp:1073 udav/plot_pnl.cpp:480
+msgid "SVG"
+msgstr ""
+
+#: udav/style_dlg.cpp:107
+msgid "Saturation"
+msgstr ""
+
+#: udav/setup_dlg.cpp:143 mgllab/editor.cpp:282
+msgid "Save"
+msgstr ""
+
+#: mgllab/help.cpp:250 mgllab/table.cpp:456
+msgid "Save Data?"
+msgstr ""
+
+#: widgets/fltk.cpp:572 mgllab/mgllab.cpp:214
+msgid "Save File As?"
+msgstr ""
+
+#: udav/anim_dlg.cpp:83
+msgid "Save JPEG frames"
+msgstr ""
+
+#: udav/udav_wnd.cpp:290 mgllab/mgllab.cpp:281
+msgid "Save as ..."
+msgstr ""
+
+#: udav/dat_pnl.cpp:688
+msgid "Save data"
+msgstr ""
+
+#: src/exec_dat.cpp:1594
+msgid "Save data to HDF5 file"
+msgstr ""
+
+#: udav/dat_pnl.cpp:690
+msgid "Save data to a file (Ctrl+Shift+S)."
+msgstr ""
+
+#: src/exec_dat.cpp:1593 mgllab/table.cpp:842
+msgid "Save data to file"
+msgstr ""
+
+#: mgllab/mgllab.cpp:280
+msgid "Save file"
+msgstr ""
+
+#: mgllab/mgllab.cpp:473
+msgid "Save file before redrawing"
+msgstr ""
+
+#: udav/udav_wnd.cpp:201
+msgid "Save script"
+msgstr ""
+
+#: udav/udav_wnd.cpp:203
+msgid "Save script to a file (Ctrl+S)"
+msgstr ""
+
+#: mgllab/editor.cpp:508
+msgid "Save script to file"
+msgstr ""
+
+#: mgllab/help.cpp:172
+msgid "Save selected data to file."
+msgstr ""
+
+#: mgllab/table.cpp:751
+msgid "Save to file"
+msgstr ""
+
+#: udav/udav_wnd.cpp:672
+msgid "Saving aborted"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:179 mgllab/dialogs.cpp:720
+msgid "Scale and rotate"
+msgstr ""
+
+#: udav/udav_wnd.cpp:237
+msgid "Script"
+msgstr ""
+
+#: udav/find_dlg.cpp:43 mgllab/editor.cpp:563
+msgid "Search backward"
+msgstr ""
+
+#: udav/text_pnl.cpp:543 mgllab/mgllab.cpp:297
+msgid "Select all"
+msgstr ""
+
+#: udav/text_pnl.cpp:585
+msgid "Select and insert file name."
+msgstr ""
+
+#: udav/text_pnl.cpp:589
+msgid "Select and insert folder name."
+msgstr ""
+
+#: mgllab/dialogs.cpp:565
+msgid "Select data argument"
+msgstr ""
+
+#: mgllab/dialogs.cpp:160
+msgid "Select direction"
+msgstr ""
+
+#: mgllab/editor.cpp:654
+msgid "Select file name"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:339 udav/newcmd_dlg.cpp:357
+msgid "Select first the proper kind of arguments"
+msgstr ""
+
+#: mgllab/editor.cpp:667
+msgid "Select folder name"
+msgstr ""
+
+#: udav/info_dlg.cpp:39
+msgid "Select kind of plot"
+msgstr ""
+
+#: src/exec_set.cpp:749
+msgid "Select variant of plot style(s)"
+msgstr ""
+
+#: mgllab/mathgl.cpp:166
+msgid "Set"
+msgstr ""
+
+#: src/exec_set.cpp:745
+msgid "Set additional tick and axis labels shift"
+msgstr ""
+
+#: src/exec_set.cpp:695
+msgid "Set ambient light brightness"
+msgstr ""
+
+#: src/exec_set.cpp:716
+msgid "Set arbitrary position of plot in picture"
+msgstr ""
+
+#: udav/udav_wnd.cpp:315 mgllab/mgllab.cpp:323
+msgid "Set arguments"
+msgstr ""
+
+#: src/exec_set.cpp:697
+msgid "Set aspect ration"
+msgstr ""
+
+#: src/exec_set.cpp:699
+msgid "Set axis and tick style"
+msgstr ""
+
+#: src/exec_set.cpp:725
+msgid "Set axis origin"
+msgstr ""
+
+#: src/exec_set.cpp:732
+msgid "Set axis ranges"
+msgstr ""
+
+#: src/exec_set.cpp:701
+msgid "Set bounding box for 2d export"
+msgstr ""
+
+#: src/exec_set.cpp:722
+msgid "Set brush for given mask id"
+msgstr ""
+
+#: src/exec_set.cpp:706
+msgid "Set color range"
+msgstr ""
+
+#: src/exec_dat.cpp:1556
+msgid "Set column id for data"
+msgstr ""
+
+#: mgllab/dialogs.cpp:108
+msgid "Set cutting off/on for particular plot"
+msgstr ""
+
+#: udav/open_dlg.cpp:62
+msgid "Set data sizes manually"
+msgstr ""
+
+#: src/exec_set.cpp:700
+msgid "Set default bars width"
+msgstr ""
+
+#: src/exec_set.cpp:730
+msgid "Set default filename"
+msgstr ""
+
+#: src/exec_set.cpp:694
+msgid "Set default transparency"
+msgstr ""
+
+#: src/exec_set.cpp:709
+msgid "Set diffusive light brightness"
+msgstr ""
+
+#: src/exec_set.cpp:710
+msgid "Set draw region for quality&4"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:47 udav/subplot_dlg.cpp:89
+msgid "Set drawing area as cell of matrix nx*ny."
+msgstr ""
+
+#: udav/subplot_dlg.cpp:110
+msgid "Set drawing area as cells of column."
+msgstr ""
+
+#: udav/subplot_dlg.cpp:64 udav/subplot_dlg.cpp:140
+msgid "Set drawing area as cells of matrix nx*ny."
+msgstr ""
+
+#: udav/subplot_dlg.cpp:127
+msgid "Set drawing area as cells of stick."
+msgstr ""
+
+#: mgllab/dialogs.cpp:117
+msgid "Set lighting off/on for particular plot"
+msgstr ""
+
+#: src/exec_set.cpp:723
+msgid "Set number of lines in mesh/fall/vect and so on"
+msgstr ""
+
+#: src/exec_set.cpp:717
+msgid "Set number of marks in the legend"
+msgstr ""
+
+#: src/exec_set.cpp:711
+msgid "Set number of visible faces"
+msgstr ""
+
+#: src/exec_set.cpp:727
+msgid "Set palette for 1D plots"
+msgstr ""
+
+#: src/exec_set.cpp:729
+msgid "Set perspective"
+msgstr ""
+
+#: src/exec_set.cpp:737
+msgid "Set picture size"
+msgstr ""
+
+#: src/exec_set.cpp:731
+msgid "Set plot quality"
+msgstr ""
+
+#: src/exec_set.cpp:742
+msgid "Set position of plot as cell of matrix"
+msgstr ""
+
+#: src/exec_set.cpp:724
+msgid "Set position of plot block in matrix"
+msgstr ""
+
+#: src/exec_set.cpp:705
+msgid "Set position of plot inside cell of column"
+msgstr ""
+
+#: src/exec_set.cpp:715
+msgid "Set position of plot inside cell of matrix"
+msgstr ""
+
+#: src/exec_set.cpp:741
+msgid "Set position of plot inside cell of rotated stick"
+msgstr ""
+
+#: src/exec_set.cpp:740
+msgid "Set position of plot inside cell of sheared stick"
+msgstr ""
+
+#: src/exec_set.cpp:753
+msgid "Set range for x-axis"
+msgstr ""
+
+#: src/exec_set.cpp:755
+msgid "Set range for y-axis"
+msgstr ""
+
+#: src/exec_set.cpp:759
+msgid "Set range for z-axis"
+msgstr ""
+
+#: src/exec_set.cpp:738
+msgid "Set scaling factor for further setsize"
+msgstr ""
+
+#: mgllab/mathgl.cpp:143
+msgid "Set script arguments"
+msgstr ""
+
+#: mgllab/dialogs.cpp:105
+msgid "Set size for text, marks and others"
+msgstr ""
+
+#: src/exec_set.cpp:696
+msgid "Set size of arrows"
+msgstr ""
+
+#: src/exec_set.cpp:721
+msgid "Set size of markers"
+msgstr ""
+
+#: src/exec_set.cpp:728
+msgid "Set size of semi-transparent area around line"
+msgstr ""
+
+#: src/exec_set.cpp:726
+msgid "Set tick labels drawing at origin"
+msgstr ""
+
+#: src/exec_set.cpp:744
+msgid "Set tick length"
+msgstr ""
+
+#: src/exec_set.cpp:707
+msgid "Set ticks for colorbar"
+msgstr ""
+
+#: src/exec_set.cpp:754
+msgid "Set ticks for x-axis"
+msgstr ""
+
+#: src/exec_set.cpp:756
+msgid "Set ticks for y-axis"
+msgstr ""
+
+#: src/exec_set.cpp:760
+msgid "Set ticks for z-axis"
+msgstr ""
+
+#: src/exec_set.cpp:746
+msgid "Set ticks in time format"
+msgstr ""
+
+#: src/exec_set.cpp:748
+msgid "Set ticks tuning"
+msgstr ""
+
+#: src/exec_set.cpp:736
+msgid "Set to auto rotate text or not"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:196
+msgid "Set to use whole area (style '#')"
+msgstr ""
+
+#: src/exec_set.cpp:747
+msgid "Set type transparency"
+msgstr ""
+
+#: widgets/qt.cpp:1209
+msgid "Set value of \\phi angle."
+msgstr ""
+
+#: udav/plot_pnl.cpp:472
+msgid ""
+"Set value of \\phi angle.\n"
+"You can use keys (Shift+Meta+Left or Shift+Meta+Right)."
+msgstr ""
+
+#: widgets/qt.cpp:1203
+msgid "Set value of \\theta angle."
+msgstr ""
+
+#: udav/plot_pnl.cpp:466
+msgid ""
+"Set value of \\theta angle.\n"
+"You can use keys (Shift+Meta+Up or Shift+Meta+Down)."
+msgstr ""
+
+#: udav/udav_wnd.cpp:311
+msgid "Settings"
+msgstr ""
+
+#: mgllab/mgllab.cpp:321
+msgid "Setup"
+msgstr ""
+
+#: mgllab/mgllab.cpp:324
+msgid "Setup animation"
+msgstr ""
+
+#: udav/prop_dlg.cpp:80
+msgid "Setup colors for:"
+msgstr ""
+
+#: src/exec_set.cpp:713
+msgid "Setup font"
+msgstr ""
+
+#: src/exec_set.cpp:718
+msgid "Setup light"
+msgstr ""
+
+#: src/exec_prm.cpp:579
+msgid "Setup or draw axis"
+msgstr ""
+
+#: src/exec_set.cpp:708
+msgid "Setup plot points cutting"
+msgstr ""
+
+#: mgllab/dialogs.cpp:947
+msgid "Setup script"
+msgstr ""
+
+#: udav/plot_pnl.cpp:573
+msgid "Setup show"
+msgstr ""
+
+#: udav/dat_pnl.cpp:623
+msgid "Sew data along direction(s)"
+msgstr ""
+
+#: mgllab/table.cpp:166 mgllab/table.cpp:783
+msgid "Sew phase"
+msgstr ""
+
+#: mgllab/dialogs.cpp:350
+msgid "Sharp colors"
+msgstr ""
+
+#: src/exec_set.cpp:739
+msgid "Shear plot"
+msgstr ""
+
+#: widgets/fltk.cpp:878
+msgid "Shift the picture down"
+msgstr ""
+
+#: widgets/fltk.cpp:870
+msgid "Shift the picture left"
+msgstr ""
+
+#: widgets/fltk.cpp:876
+msgid "Shift the picture right"
+msgstr ""
+
+#: widgets/fltk.cpp:868
+msgid "Shift the picture up"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:56 mgllab/dialogs.cpp:737
+msgid "Short description of selected command"
+msgstr ""
+
+#: udav/info_dlg.cpp:54
+msgid "Short information about the data."
+msgstr ""
+
+#: udav/hint_dlg.cpp:62
+msgid "Show at startup"
+msgstr ""
+
+#: udav/udav_wnd.cpp:210
+msgid ""
+"Show calculator which evaluate and help to type textual formulas.\n"
+"Textual formulas may contain data variables too."
+msgstr ""
+
+#: mgllab/editor.cpp:525 mgllab/editor.cpp:527
+msgid "Show calculator window"
+msgstr ""
+
+#: udav/udav_wnd.cpp:314
+msgid "Show dialog for UDAV properties."
+msgstr ""
+
+#: udav/text_pnl.cpp:560 udav/plot_pnl.cpp:441
+msgid "Show dialog for new command or edit arguments of existed one."
+msgstr ""
+
+#: udav/text_pnl.cpp:564 udav/plot_pnl.cpp:446
+msgid "Show dialog for new inplot and put it into the script."
+msgstr ""
+
+#: udav/text_pnl.cpp:577
+msgid ""
+"Show dialog for options and put it into the script.\n"
+"Options are used for additional setup the plot."
+msgstr ""
+
+#: udav/text_pnl.cpp:598
+msgid ""
+"Show dialog for plot setup and put code into the script.\n"
+"This dialog setup axis, labels, lighting and other general things."
+msgstr ""
+
+#: udav/text_pnl.cpp:573
+msgid ""
+"Show dialog for styles and put it into the script.\n"
+"Styles define the plot view (color scheme, marks, dashing and so on)."
+msgstr ""
+
+#: udav/text_pnl.cpp:548
+msgid "Show dialog for text finding (Ctrl+F)."
+msgstr ""
+
+#: udav/udav_wnd.cpp:326
+msgid "Show help on MGL commands (F1)."
+msgstr ""
+
+#: udav/udav_wnd.cpp:219
+msgid "Show hidden plots"
+msgstr ""
+
+#: mgllab/help.cpp:303
+msgid "Show hint on startup"
+msgstr ""
+
+#: udav/udav_wnd.cpp:330
+msgid "Show hints of MGL usage."
+msgstr ""
+
+#: udav/udav_wnd.cpp:213
+msgid "Show info"
+msgstr ""
+
+#: mgllab/mgllab.cpp:299
+msgid "Show lines"
+msgstr ""
+
+#: widgets/fltk.cpp:886
+msgid "Show next frame in slideshow"
+msgstr ""
+
+#: widgets/qt.cpp:1249 udav/plot_pnl.cpp:563
+msgid "Show next slide (Ctrl+.)."
+msgstr ""
+
+#: widgets/fltk.cpp:881
+msgid "Show previous frame in slideshow"
+msgstr ""
+
+#: widgets/qt.cpp:1258 udav/plot_pnl.cpp:578
+msgid "Show previous slide (Ctrl+,)."
+msgstr ""
+
+#: mgllab/table.cpp:777
+msgid "Sin FFT"
+msgstr ""
+
+#: udav/dat_pnl.cpp:620
+msgid "Sin-Fourier transform along direction(s)"
+msgstr ""
+
+#: src/exec_dat.cpp:1598
+msgid "Sin-Fourier transform at some direction"
+msgstr ""
+
+#: mgllab/table.cpp:165
+msgid "Sinus FFT"
+msgstr ""
+
+#: udav/opt_dlg.cpp:70 mgllab/dialogs.cpp:104 mgllab/dialogs.cpp:359
+msgid "Size"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:114
+msgid "Size of column"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:131
+msgid "Size of stick"
+msgstr ""
+
+#. size menu
+#: udav/mem_pnl.cpp:68 udav/dat_pnl.cpp:765 mgllab/dialogs.cpp:1015
+#: mgllab/table.cpp:757
+msgid "Sizes"
+msgstr ""
+
+#: src/parser.cpp:1425
+msgid "Skip commands and iterate for-loop again"
+msgstr ""
+
+#: widgets/qt.cpp:1251 udav/plot_pnl.cpp:566
+msgid "Slideshow"
+msgstr ""
+
+#: mgllab/table.cpp:163 mgllab/table.cpp:771
+msgid "Smooth"
+msgstr ""
+
+#: src/exec_dat.cpp:1599
+msgid "Smooth data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:613
+msgid "Smooth data along direction(s)"
+msgstr ""
+
+#: src/exec_dat.cpp:1582
+msgid "Solve Hamiltonian ODE (find GO ray or trajectory)"
+msgstr ""
+
+#: src/exec_dat.cpp:1573
+msgid "Solve ODE"
+msgstr ""
+
+#: src/exec_dat.cpp:1575
+msgid "Solve PDE"
+msgstr ""
+
+#: src/exec_dat.cpp:1580
+msgid "Solve PDE in accompanied coordinates for 2d case"
+msgstr ""
+
+#: src/exec_dat.cpp:1581
+msgid "Solve PDE in accompanied coordinates for 3d case"
+msgstr ""
+
+#: src/exec_dat.cpp:1524
+msgid "Solve PDE using advanced method (X-Y only)"
+msgstr ""
+
+#: src/exec_dat.cpp:1613
+msgid "Solve tridiagonal matrix"
+msgstr ""
+
+#: src/exec_dat.cpp:1601
+msgid "Sort data by values in column"
+msgstr ""
+
+#: udav/prop_dlg.cpp:141
+msgid "Spanish"
+msgstr ""
+
+#: udav/calc_dlg.cpp:194
+msgid "Special"
+msgstr ""
+
+#: mgllab/table.cpp:129
+msgid ""
+"Specify new data size\n"
+"Data will be interpolated"
+msgstr ""
+
+#: mgllab/table.cpp:114
+msgid ""
+"Specify new data size\n"
+"Data will be zero filled"
+msgstr ""
+
+#: mgllab/table.cpp:144
+msgid ""
+"Specify the skipping step\n"
+"Each m-th point will be saved only"
+msgstr ""
+
+#: udav/dat_pnl.cpp:778 mgllab/table.cpp:760
+msgid "Squeeze"
+msgstr ""
+
+#: src/exec_dat.cpp:1602
+msgid "Squeeze data"
+msgstr ""
+
+#: udav/setup_dlg.cpp:84
+msgid "Start"
+msgstr ""
+
+#: src/parser.cpp:1434
+msgid "Start function definition and stop execution of main script"
+msgstr ""
+
+#: src/parser.cpp:1437
+msgid "Start next for-loop iteration"
+msgstr ""
+
+#: src/parser.cpp:1438
+msgid "Start/close commands which should executed only once"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:76
+msgid "Starting cell index"
+msgstr ""
+
+#: udav/setup_dlg.cpp:117
+msgid "State"
+msgstr ""
+
+#: src/exec_dat.cpp:1539
+msgid "Step for pulse diffraction"
+msgstr ""
+
+#: widgets/qt.cpp:1135 udav/plot_pnl.cpp:347
+msgid "Stop"
+msgstr ""
+
+#: widgets/fltk.cpp:849
+msgid "Stop drawing"
+msgstr ""
+
+#: src/parser.cpp:1440
+msgid "Stop execution"
+msgstr ""
+
+#: udav/plot_pnl.cpp:349
+msgid "Stop script execution (F7)."
+msgstr ""
+
+#: udav/args_dlg.cpp:59 mgllab/mathgl.cpp:162
+msgid "String for $0"
+msgstr ""
+
+#: udav/args_dlg.cpp:41 mgllab/mathgl.cpp:144
+msgid "String for $1"
+msgstr ""
+
+#: udav/args_dlg.cpp:43 mgllab/mathgl.cpp:146
+msgid "String for $2"
+msgstr ""
+
+#: udav/args_dlg.cpp:45 mgllab/mathgl.cpp:148
+msgid "String for $3"
+msgstr ""
+
+#: udav/args_dlg.cpp:47 mgllab/mathgl.cpp:150
+msgid "String for $4"
+msgstr ""
+
+#: udav/args_dlg.cpp:49 mgllab/mathgl.cpp:152
+msgid "String for $5"
+msgstr ""
+
+#: udav/args_dlg.cpp:51 mgllab/mathgl.cpp:154
+msgid "String for $6"
+msgstr ""
+
+#: udav/args_dlg.cpp:53 mgllab/mathgl.cpp:156
+msgid "String for $7"
+msgstr ""
+
+#: udav/args_dlg.cpp:55 mgllab/mathgl.cpp:158
+msgid "String for $8"
+msgstr ""
+
+#: udav/args_dlg.cpp:57 mgllab/mathgl.cpp:160
+msgid "String for $9"
+msgstr ""
+
+#: udav/files_dlg.cpp:38
+msgid "String for %1"
+msgstr ""
+
+#: udav/files_dlg.cpp:40
+msgid "String for %2"
+msgstr ""
+
+#: udav/files_dlg.cpp:42
+msgid "String for %3"
+msgstr ""
+
+#: udav/files_dlg.cpp:44
+msgid "String for %4"
+msgstr ""
+
+#: udav/files_dlg.cpp:46
+msgid "String for %5"
+msgstr ""
+
+#: udav/files_dlg.cpp:48
+msgid "String for %6"
+msgstr ""
+
+#: udav/files_dlg.cpp:50
+msgid "String for %7"
+msgstr ""
+
+#: udav/files_dlg.cpp:52
+msgid "String for %8"
+msgstr ""
+
+#: udav/files_dlg.cpp:54
+msgid "String for %9"
+msgstr ""
+
+#: udav/prop_dlg.cpp:85
+msgid "Strings"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:208 mgllab/dialogs.cpp:1314
+msgid "Style"
+msgstr ""
+
+#: udav/setup_dlg.cpp:80
+msgid "SubTicks"
+msgstr ""
+
+#: mgllab/dialogs.cpp:959
+msgid "Subticks"
+msgstr ""
+
+#: src/exec_dat.cpp:1605
+msgid "Subtract data or number"
+msgstr ""
+
+#: mgllab/table.cpp:795
+msgid "Subtract to"
+msgstr ""
+
+#: udav/prop_dlg.cpp:94
+msgid "Suffixes"
+msgstr ""
+
+#: udav/dat_pnl.cpp:539
+msgid "Sum along direction(s)"
+msgstr ""
+
+#: udav/dat_pnl.cpp:614
+msgid "Summarize data along direction(s)"
+msgstr ""
+
+#. { _("Histogram of"),	0, hist_cb },
+#: mgllab/table.cpp:342 mgllab/table.cpp:788
+msgid "Summation of"
+msgstr ""
+
+#: src/exec_dat.cpp:1607
+msgid "Swap data (useful after Fourier transform)"
+msgstr ""
+
+#: udav/dat_pnl.cpp:618
+msgid "Swap data along direction(s)"
+msgstr ""
+
+#: mgllab/table.cpp:164 mgllab/table.cpp:776
+msgid "Swap parts"
+msgstr ""
+
+#: src/exec_set.cpp:712
+msgid "Switch on/off fog"
+msgstr ""
+
+#: src/exec_set.cpp:714
+msgid "Switch on/off gray-scale mode"
+msgstr ""
+
+#: widgets/fltk.cpp:836
+msgid "Switch on/off grid drawing"
+msgstr ""
+
+#: udav/plot_pnl.cpp:307
+msgid "Switch on/off grid of absolute coordinates (Ctrl+G)."
+msgstr ""
+
+#: widgets/qt.cpp:1108
+msgid "Switch on/off lightning for the graphics (Alt+L)."
+msgstr ""
+
+#: udav/plot_pnl.cpp:301
+msgid "Switch on/off lightning for the graphics (Ctrl+L)."
+msgstr ""
+
+#: widgets/fltk.cpp:833
+msgid "Switch on/off lightning in the picture"
+msgstr ""
+
+#: widgets/qt.cpp:1114 udav/plot_pnl.cpp:314
+msgid ""
+"Switch on/off mouse handling of the graphics\n"
+"(rotation, shifting, zooming and perspective)."
+msgstr ""
+
+#: widgets/qt.cpp:1120
+msgid "Switch on/off mouse zoom of selected region."
+msgstr ""
+
+#: src/exec_set.cpp:743
+msgid "Switch on/off to use ternary axis"
+msgstr ""
+
+#: src/exec_set.cpp:693
+msgid "Switch on/off transparency"
+msgstr ""
+
+#: widgets/qt.cpp:1102
+msgid "Switch on/off transparency for the graphics (Alt+T)."
+msgstr ""
+
+#: udav/plot_pnl.cpp:294
+msgid "Switch on/off transparency for the graphics (Ctrl+T)."
+msgstr ""
+
+#: widgets/fltk.cpp:830
+msgid "Switch on/off transparency in the picture"
+msgstr ""
+
+#: mgllab/table.cpp:552
+msgid "Symmetrical range"
+msgstr ""
+
+#: udav/dat_pnl.cpp:366
+msgid "Symmetrical?"
+msgstr ""
+
+#: src/addon.cpp:110 src/base_cf.cpp:266
+#, c-format
+msgid "TEST: %s\n"
+msgstr ""
+
+#: udav/open_dlg.cpp:82 udav/setup_dlg.cpp:88 mgllab/dialogs.cpp:961
+msgid "Template"
+msgstr ""
+
+#: udav/setup_dlg.cpp:140
+msgid "Template name"
+msgstr ""
+
+#: udav/setup_dlg.cpp:163
+msgid "Template saved"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1038
+msgid "Ternary"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1472
+msgid "Text"
+msgstr ""
+
+#: udav/style_dlg.cpp:167 mgllab/dialogs.cpp:376
+msgid "Text align"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:172 mgllab/dialogs.cpp:713
+msgid "Text and legend"
+msgstr ""
+
+#: udav/style_dlg.cpp:164
+msgid "Text color"
+msgstr ""
+
+#: udav/style_dlg.cpp:123 mgllab/dialogs.cpp:343
+msgid "Text on contours"
+msgstr ""
+
+#: mgllab/dialogs.cpp:367
+msgid "Text style"
+msgstr ""
+
+#: udav/hint_dlg.cpp:48 mgllab/help.cpp:282
+msgid ""
+"The calculator can help you to put complex expression in the script. Just "
+"type the expression (which may depend on coordinates x,y,z and so on) and "
+"put it into the script."
+msgstr ""
+
+#: mgllab/editor.cpp:280
+msgid ""
+"The current file has not been saved.\n"
+"Would you like to save it now?"
+msgstr ""
+
+#: udav/hint_dlg.cpp:50 mgllab/help.cpp:284
+msgid ""
+"The special dialog (Edit|Insert|New Command) help you select the command, "
+"fill its arguments and put it into the script."
+msgstr ""
+
+#: src/crust.cpp:559
+msgid ""
+"There are duplicated or indistinguishably adjacent points for triangulation."
+msgstr ""
+
+#. mglScrStr
+#: src/base.cpp:236
+msgid "There is changing temporary data in script"
+msgstr ""
+
+#: udav/text_pnl.cpp:124
+msgid "There is manual primitives."
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:343
+msgid "There is no 'fmt' argument for this command"
+msgstr ""
+
+#: udav/text_pnl.cpp:137 mgllab/editor.cpp:681
+msgid "There is no fitted formula."
+msgstr ""
+
+#: utils/mglcgi.cpp:74
+#, c-format
+msgid "There is no query. Exit.\n"
+msgstr ""
+
+#: udav/text_pnl.cpp:109
+msgid "There is no selection to evaluate."
+msgstr ""
+
+#: udav/hint_dlg.cpp:47 mgllab/help.cpp:281
+msgid ""
+"There is powerful calculator with a lot of special functions. You can use "
+"buttons or keyboard to type the expression. Also you can use existed "
+"variables in the expression."
+msgstr ""
+
+#. mglScrCmd
+#: src/base.cpp:234
+msgid "There is too long string(s) in script"
+msgstr ""
+
+#. mglScrLong
+#: src/base.cpp:235
+msgid "There is unbalanced ' in script"
+msgstr ""
+
+#. mglWarnSpc
+#: src/base.cpp:232
+msgid "There is wrong argument(s) in script"
+msgstr ""
+
+#. mglScrArg
+#: src/base.cpp:233
+msgid "There is wrong command(s) in script"
+msgstr ""
+
+#: widgets/fltk.cpp:862
+msgid "Theta angle (tilt z-axis)"
+msgstr ""
+
+#: mgllab/table.cpp:494
+msgid "This operation is not supported for this kind of data."
+msgstr ""
+
+#: udav/setup_dlg.cpp:76 mgllab/dialogs.cpp:955
+msgid "Ticks"
+msgstr ""
+
+#: mgllab/dialogs.cpp:960
+msgid "Ticks start"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1031
+msgid "Time ticks"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:204 mgllab/dialogs.cpp:1313
+msgid "Title"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:206
+msgid "Title for plot. Can be used in SubPlot or MultiPlot only."
+msgstr ""
+
+#: udav/dat_pnl.cpp:351 udav/dat_pnl.cpp:366 udav/dat_pnl.cpp:377
+#: udav/dat_pnl.cpp:424 udav/dat_pnl.cpp:453 mgllab/table.cpp:609
+msgid "To"
+msgstr ""
+
+#: udav/calc_dlg.cpp:66 udav/setup_dlg.cpp:147
+msgid "To script"
+msgstr ""
+
+#: udav/dat_pnl.cpp:790
+msgid "Transform"
+msgstr ""
+
+#: udav/dat_pnl.cpp:792
+msgid "Transform data along dimension(s) (Ctrl+Shift+T)."
+msgstr ""
+
+#: mgllab/dialogs.cpp:346
+msgid "Transparency"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1043
+msgid "Transparency type"
+msgstr ""
+
+#: mgllab/table.cpp:762
+msgid "Transpose"
+msgstr ""
+
+#: mgllab/table.cpp:670
+msgid "Transpose data"
+msgstr ""
+
+#: src/exec_dat.cpp:1611
+msgid "Transpose data array"
+msgstr ""
+
+#: mgllab/table.cpp:860
+msgid "Transpose data dimensions"
+msgstr ""
+
+#: udav/dat_pnl.cpp:612
+msgid "Transpose data with new dimensions"
+msgstr ""
+
+#: udav/calc_dlg.cpp:192
+msgid "Trigonometric"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1034
+msgid "Tune ticks"
+msgstr ""
+
+#: mgllab/table.cpp:169 mgllab/table.cpp:344
+msgid "Type of operation"
+msgstr ""
+
+#: mgllab/table.cpp:174
+msgid "Type of smoothing"
+msgstr ""
+
+#. N
+#: udav/style_dlg.cpp:246 mgllab/dialogs.cpp:54
+msgid "U - indigo"
+msgstr ""
+
+#: udav/text_pnl.cpp:109 udav/text_pnl.cpp:124 udav/text_pnl.cpp:137
+#: udav/udav_wnd.cpp:340
+msgid "UDAV"
+msgstr ""
+
+#: udav/opt_dlg.cpp:31
+msgid "UDAV - Add options"
+msgstr ""
+
+#: udav/anim_dlg.cpp:35
+msgid "UDAV - Animation setup"
+msgstr ""
+
+#: udav/dat_pnl.cpp:388
+msgid "UDAV - Clear data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:424
+msgid "UDAV - Crop data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:255
+msgid "UDAV - Export to PNG"
+msgstr ""
+
+#: udav/dat_pnl.cpp:351
+msgid "UDAV - Fill data"
+msgstr ""
+
+#: udav/find_dlg.cpp:33
+msgid "UDAV - Find"
+msgstr ""
+
+#: udav/dat_pnl.cpp:485
+msgid "UDAV - Go to slice"
+msgstr ""
+
+#: udav/hint_dlg.cpp:55
+msgid "UDAV - Hint"
+msgstr ""
+
+#: udav/dat_pnl.cpp:277
+msgid "UDAV - Import PNG"
+msgstr ""
+
+#: udav/prop_dlg.cpp:192 udav/prop_dlg.cpp:198 udav/newcmd_dlg.cpp:324
+#: udav/text_pnl.cpp:145 udav/open_dlg.cpp:101
+msgid "UDAV - Insert filename"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:329 udav/text_pnl.cpp:152
+msgid "UDAV - Insert path"
+msgstr ""
+
+#: udav/style_dlg.cpp:48 udav/data_dlg.cpp:33
+msgid "UDAV - Insert style/scheme"
+msgstr ""
+
+#: udav/dat_pnl.cpp:270
+msgid "UDAV - Load data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:450
+msgid "UDAV - Make histogram"
+msgstr ""
+
+#: udav/mem_pnl.cpp:84
+msgid "UDAV - New variable"
+msgstr ""
+
+#: udav/dat_pnl.cpp:377
+msgid "UDAV - Normalize by slice"
+msgstr ""
+
+#: udav/dat_pnl.cpp:366
+msgid "UDAV - Normalize data"
+msgstr ""
+
+#: udav/open_dlg.cpp:49
+msgid "UDAV - Open data file"
+msgstr ""
+
+#: udav/udav_wnd.cpp:633
+msgid "UDAV - Open file"
+msgstr ""
+
+#: udav/prop_dlg.cpp:60 udav/prop_dlg.cpp:285
+msgid "UDAV - Properties"
+msgstr ""
+
+#: udav/dat_pnl.cpp:283
+msgid "UDAV - Read from HDF"
+msgstr ""
+
+#: udav/dat_pnl.cpp:436
+msgid "UDAV - Rearrange data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:402
+msgid "UDAV - Resize data"
+msgstr ""
+
+#: udav/setup_dlg.cpp:159 udav/setup_dlg.cpp:163
+msgid "UDAV - Save template"
+msgstr ""
+
+#: udav/dat_pnl.cpp:261
+msgid "UDAV - Save to HDF"
+msgstr ""
+
+#: udav/dat_pnl.cpp:248
+msgid "UDAV - Save/export data"
+msgstr ""
+
+#: udav/args_dlg.cpp:32
+msgid "UDAV - Set script arguments"
+msgstr ""
+
+#: udav/files_dlg.cpp:29
+msgid "UDAV - Set template parameters"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:37
+msgid "UDAV - Setup inplot"
+msgstr ""
+
+#: udav/setup_dlg.cpp:39 udav/setup_dlg.cpp:190
+msgid "UDAV - Setup plot"
+msgstr ""
+
+#: udav/dat_pnl.cpp:413
+msgid "UDAV - Squeeze data"
+msgstr ""
+
+#: udav/udav_wnd.cpp:456
+msgid "UDAV - about"
+msgstr ""
+
+#: udav/anim_dlg.cpp:104
+msgid "UDAV - animation"
+msgstr ""
+
+#: udav/dat_pnl.cpp:608
+msgid "UDAV - change data"
+msgstr ""
+
+#: udav/opt_dlg.cpp:94 udav/opt_dlg.cpp:101 udav/opt_dlg.cpp:108
+#: udav/opt_dlg.cpp:115
+msgid "UDAV - command options"
+msgstr ""
+
+#: udav/mem_pnl.cpp:121
+msgid "UDAV - delete all data"
+msgstr ""
+
+#: udav/text_pnl.cpp:202
+msgid "UDAV - find text"
+msgstr ""
+
+#: udav/dat_pnl.cpp:536 udav/dat_pnl.cpp:566 udav/dat_pnl.cpp:572
+#: udav/dat_pnl.cpp:643
+msgid "UDAV - make new data"
+msgstr ""
+
+#: udav/text_pnl.cpp:431
+msgid "UDAV - open file"
+msgstr ""
+
+#: udav/udav_wnd.cpp:569 udav/udav_wnd.cpp:579 udav/udav_wnd.cpp:621
+msgid "UDAV - save current"
+msgstr ""
+
+#: udav/udav_wnd.cpp:669
+msgid "UDAV - save file"
+msgstr ""
+
+#: udav/style_dlg.cpp:160 mgllab/dialogs.cpp:371
+msgid "Underline"
+msgstr ""
+
+#. edit menu
+#: udav/text_pnl.cpp:516 mgllab/mgllab.cpp:293
+msgid "Undo"
+msgstr ""
+
+#: udav/text_pnl.cpp:518
+msgid "Undo editor change (Ctrl+Z)."
+msgstr ""
+
+#: mgllab/mgllab.cpp:127
+msgid "Untitled"
+msgstr ""
+
+#: mgllab/mgllab.cpp:345 mgllab/mgllab.cpp:349
+msgid "Untitled - mgllab"
+msgstr ""
+
+#: udav/mem_pnl.cpp:62
+msgid "Update list of data arrays"
+msgstr ""
+
+#: mgllab/dialogs.cpp:100
+msgid "Upper border for determining color or alpha"
+msgstr ""
+
+#: utils/mglconv.cpp:85
+#, c-format
+msgid "Usage:\tmglconv [parameter(s)] scriptfile\n"
+msgstr ""
+
+#: mgllab/mgllab.cpp:416
+#, c-format
+msgid "Usage:\tmgllab [parameter(s)] scriptfile\n"
+msgstr ""
+
+#: utils/mglview.cpp:69
+#, c-format
+msgid "Usage:\tmglview [parameter(s)] scriptfile\n"
+msgstr ""
+
+#: widgets/glut.cpp:103
+#, c-format
+msgid ""
+"Use 'a', 'd', 'w', 's', 'q', 'e' for changing view angles\n"
+"Use 'j', 'l', 'i', 'k' for changing light angles\n"
+"Use 'u', 'o' for changing distance to light\n"
+"Use 'r' for switching transparency\n"
+"Use 'f' for switching lightning\n"
+"Use 'E' for exporting to EPS file\n"
+"Use 'S' for exporting to SVG file\n"
+"Use 'J' for exporting to JPEG file\n"
+"Use 'P' for exporting to PNG file\n"
+"Use ',', '.' for show other frames\n"
+"Use 'm' for view movie\n"
+"Use 'h' for view this text\n"
+"Use 'x' for exit\n"
+msgstr ""
+
+#: udav/style_dlg.cpp:162
+msgid "Use color scheme"
+msgstr ""
+
+#: udav/prop_dlg.cpp:175
+msgid "Use dots plot for preview"
+msgstr ""
+
+#: mgllab/mgllab.cpp:477
+msgid "Use multi-threading for drawing"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:67 udav/opt_dlg.cpp:68 mgllab/dialogs.cpp:101
+msgid "Value"
+msgstr ""
+
+#: mgllab/dialogs.cpp:398
+msgid "Value for i-th color"
+msgstr ""
+
+#: mgllab/dialogs.cpp:727 mgllab/dialogs.cpp:1047
+msgid "Variant"
+msgstr ""
+
+#: mgllab/dialogs.cpp:728
+msgid ""
+"Variant of command argument order. The notation is:\n"
+" * Capital arguments are data (like, Ydat);\n"
+" * Argument in '' are strings (like, 'fmt');\n"
+" * Other arguments are numbers (like, zval);\n"
+" * Arguments in [] are optional arguments."
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:170 mgllab/dialogs.cpp:711
+msgid "Vector plots"
+msgstr ""
+
+#: mgllab/dialogs.cpp:379
+msgid "Vertical align"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:55 udav/subplot_dlg.cpp:72 udav/subplot_dlg.cpp:97
+msgid "Vertical size"
+msgstr ""
+
+#. k
+#: udav/style_dlg.cpp:236 mgllab/dialogs.cpp:44
+msgid "W - lightgray"
+msgstr ""
+
+#: src/exec_dat.cpp:1615
+msgid "Wavelet transform at some direction"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:195
+msgid "Whole area"
+msgstr ""
+
+#: mgllab/mgllab.cpp:480
+msgid "Widget scheme"
+msgstr ""
+
+#: mgllab/dialogs.cpp:329
+msgid "Width"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:80
+msgid "Width of selected cells"
+msgstr ""
+
+#: src/data.cpp:1427
+#, c-format
+msgid ""
+"Widths are:\n"
+"Wa = %g\tWx = %g\tWy = %g\tWz = %g\n"
+msgstr ""
+
+#: mgllab/dialogs.cpp:348
+msgid "Wire or mesh"
+msgstr ""
+
+#: udav/style_dlg.cpp:120
+msgid "Wire or mesh plot"
+msgstr ""
+
+#: udav/style_dlg.cpp:159 mgllab/dialogs.cpp:370
+msgid "Wire style"
+msgstr ""
+
+#: src/exec_set.cpp:752
+msgid "Write current image to graphical file"
+msgstr ""
+
+#: udav/setup_dlg.cpp:48 mgllab/dialogs.cpp:950
+msgid "X axis"
+msgstr ""
+
+#: udav/setup_dlg.cpp:118
+msgid "X pos"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1065
+msgid "X position"
+msgstr ""
+
+#: udav/dat_pnl.cpp:413
+msgid "X-direction"
+msgstr ""
+
+#: udav/opt_dlg.cpp:38 mgllab/dialogs.cpp:85
+msgid "X-range"
+msgstr ""
+
+#: udav/dat_pnl.cpp:388 udav/dat_pnl.cpp:402 udav/dat_pnl.cpp:436
+msgid "X-size"
+msgstr ""
+
+#: mgllab/dialogs.cpp:568
+msgid "X-slice from"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:176
+msgid "X/Z"
+msgstr ""
+
+#: widgets/qt.cpp:1081 udav/plot_pnl.cpp:489
+msgid "XYZ"
+msgstr ""
+
+#. M
+#: udav/style_dlg.cpp:242 mgllab/dialogs.cpp:50
+msgid "Y - olive"
+msgstr ""
+
+#: udav/setup_dlg.cpp:49 mgllab/dialogs.cpp:963
+msgid "Y axis"
+msgstr ""
+
+#: udav/setup_dlg.cpp:119
+msgid "Y pos"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1066
+msgid "Y position"
+msgstr ""
+
+#: udav/dat_pnl.cpp:413
+msgid "Y-direction"
+msgstr ""
+
+#: udav/opt_dlg.cpp:41 mgllab/dialogs.cpp:89
+msgid "Y-range"
+msgstr ""
+
+#: udav/dat_pnl.cpp:388 udav/dat_pnl.cpp:402 udav/dat_pnl.cpp:436
+msgid "Y-size"
+msgstr ""
+
+#: mgllab/dialogs.cpp:571
+msgid "Y-slice from"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:180
+msgid "Y/Z"
+msgstr ""
+
+#: mgllab/help.cpp:135
+msgid "Yes"
+msgstr ""
+
+#: udav/hint_dlg.cpp:36 mgllab/help.cpp:270
+msgid ""
+"You can copy the current image to clipboard by pressing Ctrl-Shift-C. Later "
+"you can paste it directly into yours document or presentation."
+msgstr ""
+
+#: udav/hint_dlg.cpp:49 mgllab/help.cpp:283
+msgid ""
+"You can easily insert file or folder names, last fitted formula or numerical "
+"value of selection by using menu Edit|Insert."
+msgstr ""
+
+#: udav/hint_dlg.cpp:43 mgllab/help.cpp:277
+msgid ""
+"You can edit MGL file in any text editor. Also you can run it in console by "
+"help of commands: mglconv, mglview."
+msgstr ""
+
+#: udav/hint_dlg.cpp:37 mgllab/help.cpp:271
+msgid ""
+"You can export image into a set of format (EPS, SVG, PNG, JPEG) by pressing "
+"right mouse button inside image and selecting 'Export as ...'."
+msgstr ""
+
+#: udav/hint_dlg.cpp:41 mgllab/help.cpp:275
+msgid ""
+"You can put several plots in the same image by help of commands 'subplot' or "
+"'inplot'."
+msgstr ""
+
+#: udav/hint_dlg.cpp:51 mgllab/help.cpp:285
+msgid ""
+"You can put several plotting commands in the same line or in separate "
+"function, for highlighting all of them simultaneously."
+msgstr ""
+
+#: udav/hint_dlg.cpp:34 mgllab/help.cpp:268
+msgid ""
+"You can rotate/shift/zoom whole plot by mouse. Just press 'Rotate' "
+"toolbutton, click image and hold a mouse button: left button for rotation, "
+"right button for zoom/perspective, middle button for shift."
+msgstr ""
+
+#: udav/hint_dlg.cpp:39 mgllab/help.cpp:273
+msgid ""
+"You can save the parameter of animation inside MGL script by using comment "
+"started from '##a ' or '##c ' for loops."
+msgstr ""
+
+#: udav/hint_dlg.cpp:38 mgllab/help.cpp:272
+msgid ""
+"You can setup colors for script highlighting in Property dialog. Just select "
+"menu item 'Settings/Properties'."
+msgstr ""
+
+#: udav/hint_dlg.cpp:33 mgllab/help.cpp:267
+msgid ""
+"You can shift axis range by pressing middle button and moving mouse. Also, "
+"you can zoom in/out axis range by using mouse wheel."
+msgstr ""
+
+#: udav/hint_dlg.cpp:46 mgllab/help.cpp:280
+msgid ""
+"You can type arbitrary expression as input argument for data or number. In "
+"last case (for numbers), the first value of data array is used."
+msgstr ""
+
+#: udav/hint_dlg.cpp:44 mgllab/help.cpp:278
+msgid ""
+"You can use command 'once on|off' for marking the block which should be "
+"executed only once. For example, this can be the block of large data reading/"
+"creating/handling. Press F9 (or menu item 'Graphics/Reload') to re-execute "
+"this block."
+msgstr ""
+
+#: udav/hint_dlg.cpp:45 mgllab/help.cpp:279
+msgid ""
+"You can use command 'stop' for terminating script parsing. It is useful if "
+"you don't want to execute a part of script."
+msgstr ""
+
+#: udav/hint_dlg.cpp:35 mgllab/help.cpp:269
+msgid ""
+"You may quickly draw the data from file. Just use: udav 'filename.dat' in "
+"command line."
+msgstr ""
+
+#: mgllab/dialogs.cpp:1529
+msgid "You need to enter text!"
+msgstr ""
+
+#: mgllab/table.cpp:367
+msgid "You need to provide output name"
+msgstr ""
+
+#: udav/prop_dlg.cpp:285
+msgid "You need to restart UDAV for applying the changes."
+msgstr ""
+
+#: mgllab/dialogs.cpp:592
+msgid "You need to select data array"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1489
+msgid "You need to select marker!"
+msgstr ""
+
+#: mgllab/table.cpp:190 mgllab/table.cpp:364
+msgid "You need to specify direction(s)"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:378 udav/newcmd_dlg.cpp:382
+msgid "You should put text inside ' ' for argument "
+msgstr ""
+
+#: udav/anim_dlg.cpp:105
+msgid "You should select one of case"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:386
+msgid "You should specify all optional arguments before "
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:370
+msgid "You should specify required argument "
+msgstr ""
+
+#: udav/setup_dlg.cpp:50 mgllab/dialogs.cpp:976
+msgid "Z axis"
+msgstr ""
+
+#: udav/setup_dlg.cpp:120
+msgid "Z pos"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1067
+msgid "Z position"
+msgstr ""
+
+#: udav/dat_pnl.cpp:413
+msgid "Z-direction"
+msgstr ""
+
+#: udav/opt_dlg.cpp:44 mgllab/dialogs.cpp:93
+msgid "Z-range"
+msgstr ""
+
+#: udav/dat_pnl.cpp:388 udav/dat_pnl.cpp:402 udav/dat_pnl.cpp:436
+msgid "Z-size"
+msgstr ""
+
+#: mgllab/dialogs.cpp:574
+msgid "Z-slice from"
+msgstr ""
+
+#: src/exec_set.cpp:758
+msgid "Zoom axis range"
+msgstr ""
+
+#: widgets/qt.cpp:1116
+msgid "Zoom by mouse"
+msgstr ""
+
+#: widgets/qt.cpp:1215
+msgid "Zoom graphics"
+msgstr ""
+
+#: widgets/qt.cpp:1225 udav/plot_pnl.cpp:515
+msgid "Zoom in"
+msgstr ""
+
+#: widgets/qt.cpp:1227 udav/plot_pnl.cpp:518
+msgid "Zoom in graphics."
+msgstr ""
+
+#: widgets/fltk.cpp:843
+msgid "Zoom in selected region of the picture"
+msgstr ""
+
+#. t->addAction(QPixmap(":/png/help-faq.png"), _("Examples"), this, SLOT(showExamples()));
+#: udav/help_pnl.cpp:55
+msgid "Zoom in text"
+msgstr ""
+
+#: widgets/fltk.cpp:872
+msgid "Zoom in the picture"
+msgstr ""
+
+#: widgets/qt.cpp:1229 udav/plot_pnl.cpp:521
+msgid "Zoom out"
+msgstr ""
+
+#: widgets/qt.cpp:1231 udav/plot_pnl.cpp:524
+msgid "Zoom out graphics."
+msgstr ""
+
+#: udav/help_pnl.cpp:56
+msgid "Zoom out text"
+msgstr ""
+
+#: widgets/fltk.cpp:874
+msgid "Zoom out the picture"
+msgstr ""
+
+#: src/exec_set.cpp:757
+msgid "Zoom plot region"
+msgstr ""
+
+#. zooming menu
+#: widgets/qt.cpp:1214 udav/plot_pnl.cpp:502
+msgid "Zoom/move"
+msgstr ""
+
+#: udav/style_dlg.cpp:131
+msgid "above"
+msgstr ""
+
+#: mgllab/dialogs.cpp:570 mgllab/dialogs.cpp:573 mgllab/dialogs.cpp:576
+msgid "all"
+msgstr ""
+
+#: mgllab/dialogs.cpp:581
+msgid "along"
+msgstr ""
+
+#: mgllab/table.cpp:171 mgllab/table.cpp:346
+msgid "along x"
+msgstr ""
+
+#: mgllab/table.cpp:172 mgllab/table.cpp:347
+msgid "along y"
+msgstr ""
+
+#: mgllab/table.cpp:173 mgllab/table.cpp:348
+msgid "along z"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1012
+msgid "alpha"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1296
+msgid "and"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1456
+msgid "arc"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1018
+msgid "arrows"
+msgstr ""
+
+#: udav/setup_dlg.cpp:72 udav/style_dlg.cpp:170
+msgid "at center"
+msgstr ""
+
+#: udav/setup_dlg.cpp:72
+msgid "at maximum"
+msgstr ""
+
+#: udav/setup_dlg.cpp:72
+msgid "at minimum"
+msgstr ""
+
+#: udav/setup_dlg.cpp:70 mgllab/dialogs.cpp:956
+msgid "at position"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1027
+msgid "attach light"
+msgstr ""
+
+#. mglWarnFmt
+#: src/base.cpp:229
+msgid "axis ranges are incompatible"
+msgstr ""
+
+#. w
+#: udav/style_dlg.cpp:222 mgllab/dialogs.cpp:29
+msgid "b - blue"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1019
+msgid "bars"
+msgstr ""
+
+#: widgets/qt.cpp:1071 udav/plot_pnl.cpp:478
+msgid "bitmap EPS"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1036
+msgid "both"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:189 mgllab/dialogs.cpp:1306
+msgid "bottom"
+msgstr ""
+
+#. r
+#: udav/style_dlg.cpp:225 mgllab/dialogs.cpp:32
+msgid "c - cyan"
+msgstr ""
+
+#: mgllab/dialogs.cpp:957 mgllab/dialogs.cpp:970 mgllab/dialogs.cpp:983
+#: mgllab/dialogs.cpp:996
+msgid "center"
+msgstr ""
+
+#: widgets/fltk.cpp:768
+#, c-format
+msgid "click at %g, %g, %g"
+msgstr ""
+
+#. mglWarnCnt
+#: src/base.cpp:225
+msgid "couldn't open file"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1455
+msgid "curve"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1026
+msgid "cutting"
+msgstr ""
+
+#. -----------------------------------------------------------------------------
+#: src/base.cpp:216
+msgid "data dimension(s) is incompatible"
+msgstr ""
+
+#. mglWarnDim
+#: src/base.cpp:217
+msgid "data dimension(s) is too small"
+msgstr ""
+
+#. mglWarnMem
+#: src/base.cpp:221
+msgid "data values are zero"
+msgstr ""
+
+#: udav/open_dlg.cpp:85 udav/open_dlg.cpp:144 udav/opt_dlg.cpp:63
+#: udav/opt_dlg.cpp:66 mgllab/dialogs.cpp:107 mgllab/dialogs.cpp:116
+#: mgllab/dialogs.cpp:1044
+msgid "default"
+msgstr ""
+
+#: mgllab/help.cpp:149
+msgid "dimensions"
+msgstr ""
+
+#. l
+#: udav/style_dlg.cpp:229 mgllab/dialogs.cpp:36
+msgid "e - lawngreen"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1455
+msgid "ellipse"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1017
+msgid "facenum"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1035
+msgid "factor"
+msgstr ""
+
+#. mglWarnSize
+#: src/base.cpp:228
+msgid "format is not supported for that build"
+msgstr ""
+
+#: src/canvas.cpp:33
+msgid "frame"
+msgstr ""
+
+#: udav/anim_dlg.cpp:55 mgllab/mathgl.cpp:190
+msgid "from"
+msgstr ""
+
+#. b
+#: udav/style_dlg.cpp:223 mgllab/dialogs.cpp:30
+msgid "g - lime"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1044
+msgid "glass-like"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1011
+msgid "grayscale"
+msgstr ""
+
+#. p
+#: udav/style_dlg.cpp:234 mgllab/dialogs.cpp:41
+msgid "h - gray"
+msgstr ""
+
+#: src/parser.cpp:1011
+#, c-format
+msgid "in line %ld"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1036
+msgid "increment"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1236 mgllab/dialogs.cpp:1249 mgllab/dialogs.cpp:1262
+#: mgllab/dialogs.cpp:1271 mgllab/dialogs.cpp:1280
+msgid "ind"
+msgstr ""
+
+#. h
+#: udav/style_dlg.cpp:235 mgllab/dialogs.cpp:43
+msgid "k - black"
+msgstr ""
+
+#. y
+#: udav/style_dlg.cpp:228 mgllab/dialogs.cpp:35
+msgid "l - springgreen"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1045
+msgid "lamp-like"
+msgstr ""
+
+#. vv->addSpacing(11);
+#: udav/style_dlg.cpp:169 udav/subplot_dlg.cpp:187 mgllab/dialogs.cpp:957
+#: mgllab/dialogs.cpp:970 mgllab/dialogs.cpp:983 mgllab/dialogs.cpp:996
+#: mgllab/dialogs.cpp:1304
+msgid "left"
+msgstr ""
+
+#. mglWarnOpen
+#: src/base.cpp:226
+msgid "light: ID is out of range"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1013
+msgid "lighting"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1454
+msgid "line"
+msgstr ""
+
+#. c
+#: udav/style_dlg.cpp:226 mgllab/dialogs.cpp:33
+msgid "m - magenta"
+msgstr ""
+
+#.
+#. ^
+#: udav/style_dlg.cpp:317 udav/style_dlg.cpp:356 mgllab/dialogs.cpp:209
+#: mgllab/dialogs.cpp:247
+msgid "manual"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1454
+msgid "marker"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1020
+msgid "markers"
+msgstr ""
+
+#: udav/data_dlg.cpp:68
+msgid "max"
+msgstr ""
+
+#: mgllab/help.cpp:151
+msgid "mem. usage"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1016
+msgid "meshnum"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:247
+msgid "mgl_en"
+msgstr ""
+
+#: utils/mglconv.cpp:84
+#, c-format
+msgid ""
+"mglconv convert mgl script to image file (default PNG).\n"
+"Current version is 2.%g\n"
+msgstr ""
+
+#: mgllab/mgllab.cpp:415
+#, c-format
+msgid ""
+"mgllab draw mgl script interactively.\n"
+"Current version is 2.%g\n"
+msgstr ""
+
+#: mgllab/help.cpp:78
+#, c-format
+msgid ""
+"mgllab v. 2.%g\n"
+"(c) Alexey Balakin, 2017\n"
+"http://mathgl.sf.net/"
+msgstr ""
+
+#: utils/mglview.cpp:68
+#, c-format
+msgid ""
+"mglview show plot from MGL script or MGLD file.\n"
+"Current version is 2.%g\n"
+msgstr ""
+
+#: udav/data_dlg.cpp:68
+msgid "min"
+msgstr ""
+
+#. mglWarnLow
+#: src/base.cpp:218
+msgid "minimal data value is negative"
+msgstr ""
+
+#. e
+#: udav/style_dlg.cpp:230 mgllab/dialogs.cpp:37
+msgid "n - skyblue"
+msgstr ""
+
+#: mgllab/help.cpp:147
+msgid "name"
+msgstr ""
+
+#. mglWarnNeg
+#: src/base.cpp:219
+msgid "no file or wrong data dimensions"
+msgstr ""
+
+#. mglWarnZero
+#: src/base.cpp:222
+msgid "no legend entries"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1028
+msgid "no origin tick"
+msgstr ""
+
+#. "-+=;oOsS~<>jdD*^"
+#. ".+x*sdv^<>o.*+xsdv^<>o" : nf = 10
+#: udav/style_dlg.cpp:128 udav/style_dlg.cpp:131 udav/style_dlg.cpp:134
+#: udav/style_dlg.cpp:339 udav/style_dlg.cpp:383 udav/data_dlg.cpp:67
+#: mgllab/dialogs.cpp:214 mgllab/dialogs.cpp:230 mgllab/dialogs.cpp:1035
+#: mgllab/dialogs.cpp:1039
+msgid "none"
+msgstr ""
+
+#: udav/style_dlg.cpp:220
+msgid "none or default"
+msgstr ""
+
+#. mglWarnFile
+#: src/base.cpp:220
+msgid "not enough memory"
+msgstr ""
+
+#. mglWarnNull
+#: src/base.cpp:231
+msgid "not enough space for plot"
+msgstr ""
+
+#: mgllab/table.cpp:85
+msgid "not used"
+msgstr ""
+
+#. mglWarnSlc
+#: src/base.cpp:224
+msgid "number of contours is zero or negative"
+msgstr ""
+
+#: udav/opt_dlg.cpp:63 udav/opt_dlg.cpp:66
+msgid "off"
+msgstr ""
+
+#: udav/opt_dlg.cpp:63 udav/opt_dlg.cpp:66 udav/setup_dlg.cpp:128
+msgid "on"
+msgstr ""
+
+#: udav/dat_pnl.cpp:549
+msgid "or enter name for new variable"
+msgstr ""
+
+#. q
+#: udav/style_dlg.cpp:233 mgllab/dialogs.cpp:40
+msgid "p - deeppink"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1023
+msgid "pen blur"
+msgstr ""
+
+#: mgllab/dialogs.cpp:392
+msgid "plain"
+msgstr ""
+
+#. mglWarnTern
+#: src/base.cpp:230
+msgid "pointer is NULL"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1456
+msgid "polygon"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1040
+msgid "projection"
+msgstr ""
+
+#. u
+#: udav/style_dlg.cpp:232 mgllab/dialogs.cpp:39
+msgid "q - orange"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1040
+msgid "quaternary"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1041
+msgid "quaternary proj"
+msgstr ""
+
+#. g
+#: udav/style_dlg.cpp:224 mgllab/dialogs.cpp:31
+msgid "r - red"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1454
+msgid "rectangle"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1455
+msgid "rhomb"
+msgstr ""
+
+#: udav/style_dlg.cpp:172 udav/subplot_dlg.cpp:193 mgllab/dialogs.cpp:958
+#: mgllab/dialogs.cpp:971 mgllab/dialogs.cpp:984 mgllab/dialogs.cpp:997
+#: mgllab/dialogs.cpp:1310
+msgid "right"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1029
+msgid "rotate text"
+msgstr ""
+
+#: mgllab/mathgl.cpp:197
+msgid "save slides"
+msgstr ""
+
+#. mglWarnLId
+#: src/base.cpp:227
+msgid "size(s) is zero or negative"
+msgstr ""
+
+#. mglWarnLeg
+#: src/base.cpp:223
+msgid "slice value is out of range"
+msgstr ""
+
+#: mgllab/table.cpp:144
+msgid "smoothed"
+msgstr ""
+
+#: mgllab/dialogs.cpp:326
+msgid "solid"
+msgstr ""
+
+#: widgets/qt.cpp:1069 udav/plot_pnl.cpp:476
+msgid "solid PNG"
+msgstr ""
+
+#: udav/anim_dlg.cpp:45 mgllab/mathgl.cpp:185
+msgid "strings"
+msgstr ""
+
+#: udav/data_dlg.cpp:67
+msgid "sum"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1039
+msgid "ternary"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1041
+msgid "ternary proj"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1021 mgllab/dialogs.cpp:1456
+msgid "text"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1022
+msgid "ticks"
+msgstr ""
+
+#: udav/anim_dlg.cpp:59 mgllab/mathgl.cpp:191 mgllab/dialogs.cpp:569
+#: mgllab/dialogs.cpp:572 mgllab/dialogs.cpp:575
+msgid "to"
+msgstr ""
+
+#: mgllab/mgllab.cpp:564
+msgid "to script"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:191 mgllab/dialogs.cpp:1308
+msgid "top"
+msgstr ""
+
+#. n
+#: udav/style_dlg.cpp:231 mgllab/dialogs.cpp:38
+msgid "u - blueviolet"
+msgstr ""
+
+#: udav/style_dlg.cpp:131
+msgid "under"
+msgstr ""
+
+#: udav/mem_pnl.cpp:168 mgllab/help.cpp:199
+msgid "unknown"
+msgstr ""
+
+#: udav/udav_wnd.cpp:168 udav/udav_wnd.cpp:560 udav/udav_wnd.cpp:693
+msgid "untitled - UDAV"
+msgstr ""
+
+#: udav/udav_wnd.cpp:686
+msgid "untitled* - UDAV"
+msgstr ""
+
+#: mgllab/dialogs.cpp:327
+msgid "user"
+msgstr ""
+
+#: udav/anim_dlg.cpp:52 mgllab/mathgl.cpp:187
+msgid "values"
+msgstr ""
+
+#: widgets/qt.cpp:1072 udav/plot_pnl.cpp:479
+msgid "vector EPS"
+msgstr ""
+
+#.
+#: udav/style_dlg.cpp:221 mgllab/dialogs.cpp:28
+msgid "w - white"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1312
+msgid "whole area"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1471
+msgid "wire"
+msgstr "wire"
+
+#: udav/anim_dlg.cpp:63 mgllab/mathgl.cpp:192
+msgid "with step"
+msgstr ""
+
+#. m
+#: udav/style_dlg.cpp:227 mgllab/dialogs.cpp:34
+msgid "y - yellow"
+msgstr ""
diff --git a/mathgl_es.po b/mathgl_es.po
new file mode 100644
index 0000000..ec6a946
--- /dev/null
+++ b/mathgl_es.po
@@ -0,0 +1,6345 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the MathGL2 package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: MathGL2 2.4.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-05-17 07:55+0300\n"
+"PO-Revision-Date: 2017-05-11 23:14-0400\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.8.7.1\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: mgllab/mgllab.cpp:417
+#, c-format
+msgid ""
+"\t-1 str       set str as argument $1 for script\n"
+"\t...          ...\n"
+"\t-9 str       set str as argument $9 for script\n"
+"\t-L loc       set locale to loc\n"
+"\t-h           print this message\n"
+msgstr ""
+
+#: utils/mglconv.cpp:87
+#, c-format
+msgid ""
+"\t-1 str       set str as argument $1 for script\n"
+"\t...          ...\n"
+"\t-9 str       set str as argument $9 for script\n"
+"\t-L loc       set locale to loc\n"
+"\t-s fname     set MGL script for setting up the plot\n"
+"\t-S val       set scaling factor for images\n"
+"\t-q val       set quality for output (val=0...9)\n"
+"\t-g val       set gray-scale mode (val=0|1)\n"
+"\t-v val       set variant of arguments\n"
+"\t-o name      set output file name\n"
+"\t-n           no default output (script should save results by itself)\n"
+"\t-A val       add animation value val\n"
+"\t-C n1:n2:dn  add animation value in range [n1,n2] with step dn\n"
+"\t-C n1:n2     add animation value in range [n1,n2] with step 1\n"
+"\t-            get script from standard input\n"
+"\t-h           print this message\n"
+msgstr ""
+
+#: utils/mglview.cpp:71
+#, c-format
+msgid ""
+"\t-1 str       set str as argument $1 for script\n"
+"\t...          ...\n"
+"\t-9 str       set str as argument $9 for script\n"
+"\t-g val       set gray-scale mode (val=0|1)\n"
+"\t-v val       set variant of arguments\n"
+"\t-s opt       set MGL script for setting up the plot\n"
+"\t-L loc       set locale to loc\n"
+"\t-            get script from standard input\n"
+"\t-h           print this message\n"
+msgstr ""
+
+#: widgets/qt.cpp:859
+msgid ""
+"\n"
+"(c) Alexey Balakin, 2007\n"
+"http://mathgl.sourceforge.net/"
+msgstr ""
+
+#: src/parser.cpp:1010
+#, c-format
+msgid ""
+"\n"
+"Change temporary data in line %ld"
+msgstr ""
+"\n"
+"Cambiar datos temporales en linea %ld"
+
+#: src/parser.cpp:1008
+#, c-format
+msgid ""
+"\n"
+"String too long in line %ld"
+msgstr ""
+"\n"
+"Cadena de caracteres demasiado larga en linea %ld"
+
+#: src/parser.cpp:1009
+#, c-format
+msgid ""
+"\n"
+"Unbalanced ' in line %ld"
+msgstr ""
+
+#: src/parser.cpp:1006
+#, c-format
+msgid ""
+"\n"
+"Wrong argument(s) in line %ld"
+msgstr ""
+"\n"
+"Argumento(s) incorrecto(s) en linea %ld"
+
+#: src/parser.cpp:1007
+#, c-format
+msgid ""
+"\n"
+"Wrong command in line %ld"
+msgstr ""
+"\n"
+"Comando incorrecto en linea %ld"
+
+#: udav/mem_pnl.cpp:136 udav/dat_pnl.cpp:153
+msgid " - UDAV preview"
+msgstr " - Vista previa de UDAV"
+
+#: udav/dat_pnl.cpp:152
+msgid " - UDAV variable"
+msgstr " - Variable de UDAV"
+
+#. o = new Fl_Button(420, 400, 90, 25, _(" Refresh"));	o->callback(mem_update_cb,w);
+#. o->image(img_update);	o->align(FL_ALIGN_IMAGE_NEXT_TO_TEXT);
+#. o->tooltip(_("Refresh list of variables."));
+#: mgllab/help.cpp:176
+msgid " Del.all"
+msgstr ""
+
+#: mgllab/help.cpp:164
+msgid " Delete"
+msgstr " Borrar"
+
+#: mgllab/help.cpp:158
+msgid " Edit"
+msgstr " Editar"
+
+#: mgllab/help.cpp:161
+msgid " Info"
+msgstr " Info"
+
+#: mgllab/help.cpp:167
+msgid " New"
+msgstr " Nuevo"
+
+#: mgllab/help.cpp:170
+msgid " Save"
+msgstr " Guardar"
+
+#: mgllab/mgllab.cpp:227
+msgid " Yes "
+msgstr " Si "
+
+#: udav/plot_pnl.cpp:191
+#, c-format
+msgid "%d - %d of %d"
+msgstr "%d - %d de %d"
+
+#. :
+#: udav/style_dlg.cpp:316 mgllab/dialogs.cpp:208
+msgid "' ' none"
+msgstr ""
+
+#: udav/style_dlg.cpp:397
+msgid "'#*' Y-sign"
+msgstr ""
+
+#: udav/style_dlg.cpp:398
+msgid "'#+' squared plus"
+msgstr "'#+' signo mas en cuadrado"
+
+#: udav/style_dlg.cpp:396
+msgid "'#.' circled dot"
+msgstr "'#.' punto en circulo"
+
+#: udav/style_dlg.cpp:405
+msgid "'#<' solid triangle left"
+msgstr "'#<' triangulo solido hacia la izquierda"
+
+#: udav/style_dlg.cpp:406
+msgid "'#>' solid triangle right"
+msgstr "'#>' triangulo solido hacia la derecha"
+
+#: udav/style_dlg.cpp:404
+msgid "'#^' solid triangle up"
+msgstr ""
+
+#: udav/style_dlg.cpp:402
+msgid "'#d' solid rhomb"
+msgstr "'#d' rombo solido"
+
+#: udav/style_dlg.cpp:407
+msgid "'#o' solid circle"
+msgstr "'#o' circulo solido"
+
+#: udav/style_dlg.cpp:401
+msgid "'#s' solid square"
+msgstr "'#s' cuadrado solido"
+
+#: udav/style_dlg.cpp:403
+msgid "'#v' solid triangle down"
+msgstr "'#v' triangulo solido hacia abajo"
+
+#: udav/style_dlg.cpp:399
+msgid "'#x' squared cross"
+msgstr "'#x' cruz en cuadrado"
+
+#. D
+#: udav/style_dlg.cpp:354 mgllab/dialogs.cpp:245
+msgid "'*' cross"
+msgstr "'*' cruz"
+
+#.
+#: udav/style_dlg.cpp:387 mgllab/dialogs.cpp:215
+msgid "'*' star"
+msgstr "'*' estrella"
+
+#. o
+#. -
+#: udav/style_dlg.cpp:341 udav/style_dlg.cpp:385 mgllab/dialogs.cpp:217
+#: mgllab/dialogs.cpp:232
+msgid "'+' plus"
+msgstr "'+' signo mas"
+
+#.
+#: udav/style_dlg.cpp:340 mgllab/dialogs.cpp:231
+msgid "'-' lines"
+msgstr "'-' lineas"
+
+#. "-|;=ji: "
+#: udav/style_dlg.cpp:309 mgllab/dialogs.cpp:201
+msgid "'-' solid"
+msgstr "'-' solido"
+
+#. d
+#: udav/style_dlg.cpp:384 mgllab/dialogs.cpp:221
+msgid "'.' dot"
+msgstr "'.' punto"
+
+#. =
+#: udav/style_dlg.cpp:315 mgllab/dialogs.cpp:207
+msgid "':' dots"
+msgstr "':' puntos"
+
+#. j
+#. =
+#: udav/style_dlg.cpp:311 udav/style_dlg.cpp:343 mgllab/dialogs.cpp:204
+#: mgllab/dialogs.cpp:234
+msgid "';' dash"
+msgstr "';' guion"
+
+#. ~
+#: udav/style_dlg.cpp:349 mgllab/dialogs.cpp:241
+msgid "'<' left sign"
+msgstr ""
+
+#. v
+#: udav/style_dlg.cpp:392 mgllab/dialogs.cpp:224
+msgid "'<' triangle left"
+msgstr ""
+
+#. +
+#: udav/style_dlg.cpp:342 mgllab/dialogs.cpp:233
+msgid "'=' double lines"
+msgstr ""
+
+#. i
+#: udav/style_dlg.cpp:312 mgllab/dialogs.cpp:206
+msgid "'=' small dash"
+msgstr "'=' guion pequeno"
+
+#. <
+#: udav/style_dlg.cpp:350 mgllab/dialogs.cpp:242
+msgid "'>' right sign"
+msgstr ""
+
+#. <
+#: udav/style_dlg.cpp:393 mgllab/dialogs.cpp:225
+msgid "'>' triangle right"
+msgstr "'>' triangulo hacia la derecha"
+
+#. _
+#: udav/style_dlg.cpp:265 udav/style_dlg.cpp:288 mgllab/dialogs.cpp:188
+msgid "'A' arrow"
+msgstr "'A' flecha"
+
+#. S
+#: udav/style_dlg.cpp:271 udav/style_dlg.cpp:294 mgllab/dialogs.cpp:194
+msgid "'D' rhomb"
+msgstr "'D' rombo"
+
+#. d
+#: udav/style_dlg.cpp:353 mgllab/dialogs.cpp:244
+msgid "'D' solid rhomb"
+msgstr "'D' rombo solido"
+
+#. V
+#: udav/style_dlg.cpp:267 udav/style_dlg.cpp:290 mgllab/dialogs.cpp:191
+msgid "'I' stop"
+msgstr "'I' detener"
+
+#. A
+#: udav/style_dlg.cpp:268 udav/style_dlg.cpp:291 mgllab/dialogs.cpp:189
+msgid "'K' size"
+msgstr "'K' tamano"
+
+#. D
+#: udav/style_dlg.cpp:272 udav/style_dlg.cpp:295 mgllab/dialogs.cpp:195
+msgid "'O' circle"
+msgstr "'O' circulo"
+
+#. o
+#: udav/style_dlg.cpp:345 mgllab/dialogs.cpp:237
+msgid "'O' solid circle"
+msgstr "'O' circulo solido"
+
+#. s
+#: udav/style_dlg.cpp:347 mgllab/dialogs.cpp:239
+msgid "'S' solid square"
+msgstr "'S' cuadrado solido"
+
+#. T
+#: udav/style_dlg.cpp:270 udav/style_dlg.cpp:293 mgllab/dialogs.cpp:193
+msgid "'S' square"
+msgstr "'S' cuadrado"
+
+#. I
+#: udav/style_dlg.cpp:269 udav/style_dlg.cpp:292 mgllab/dialogs.cpp:192
+msgid "'T' triangle"
+msgstr "'T' triangulo"
+
+#. K
+#: udav/style_dlg.cpp:266 udav/style_dlg.cpp:289 mgllab/dialogs.cpp:190
+msgid "'V' back arrow"
+msgstr "'V' flecha inversa"
+
+#. O
+#: mgllab/dialogs.cpp:196
+msgid "'X' cross"
+msgstr "'X' cruz"
+
+#. *
+#: udav/style_dlg.cpp:355 mgllab/dialogs.cpp:246
+msgid "'^' hats"
+msgstr "'^' sombrero"
+
+#. .
+#: udav/style_dlg.cpp:391 mgllab/dialogs.cpp:222
+msgid "'^' triangle up"
+msgstr "'^' triangulo hacia arriba"
+
+#. "AVIKTSDO"
+#: udav/style_dlg.cpp:264 udav/style_dlg.cpp:287 mgllab/dialogs.cpp:187
+msgid "'_' none"
+msgstr "'_' ninguno"
+
+#. s
+#. >
+#: udav/style_dlg.cpp:352 udav/style_dlg.cpp:389 mgllab/dialogs.cpp:220
+#: mgllab/dialogs.cpp:243
+msgid "'d' rhomb"
+msgstr "'d' rombo"
+
+#. ;
+#: udav/style_dlg.cpp:314 mgllab/dialogs.cpp:205
+msgid "'i' small dash dot"
+msgstr ""
+
+#. |
+#. ;
+#: udav/style_dlg.cpp:313 udav/style_dlg.cpp:351 mgllab/dialogs.cpp:203
+#: mgllab/dialogs.cpp:235
+msgid "'j' dash dot"
+msgstr "'j' guion y punto"
+
+#. *
+#. j
+#: udav/style_dlg.cpp:344 udav/style_dlg.cpp:394 mgllab/dialogs.cpp:216
+#: mgllab/dialogs.cpp:236
+msgid "'o' circle"
+msgstr "'o' circulo"
+
+#. x
+#. O
+#: udav/style_dlg.cpp:346 udav/style_dlg.cpp:388 mgllab/dialogs.cpp:219
+#: mgllab/dialogs.cpp:238
+msgid "'s' square"
+msgstr "'s' cuadrado"
+
+#. ^
+#: udav/style_dlg.cpp:390 mgllab/dialogs.cpp:223
+msgid "'v' triangle down"
+msgstr "'v' triangulo hacia abajo"
+
+#. +
+#: udav/style_dlg.cpp:386 mgllab/dialogs.cpp:218
+msgid "'x' skew cross"
+msgstr "'x' cruz oblicua"
+
+#. -
+#: udav/style_dlg.cpp:310 mgllab/dialogs.cpp:202
+msgid "'|' long dash"
+msgstr "'|' guion largo"
+
+#. S
+#: udav/style_dlg.cpp:348 mgllab/dialogs.cpp:240
+msgid "'~' waves"
+msgstr ""
+
+#: src/parser.cpp:51
+msgid "0 - special plot"
+msgstr "0 - grafico especial"
+
+#: src/parser.cpp:51
+msgid "1 - other plot"
+msgstr "1 - otro grafico"
+
+#: src/parser.cpp:51
+msgid "10 - dd plot"
+msgstr "10 - grafico dd"
+
+#: src/parser.cpp:51
+msgid "11 - vector plot"
+msgstr "11 - grafico de vectores"
+
+#: src/parser.cpp:51
+msgid "12 - axis"
+msgstr "12 - eje"
+
+#: src/parser.cpp:51
+msgid "13 - primitives"
+msgstr "13 - primitivas"
+
+#: src/parser.cpp:51
+msgid "14 - axis setup"
+msgstr "14 - configurar eje"
+
+#: src/parser.cpp:51
+msgid "15 - text/legend"
+msgstr "15 - texto/leyenda"
+
+#: src/parser.cpp:51
+msgid "16 - data transform"
+msgstr "16 - transformar datos"
+
+#: udav/info_dlg.cpp:47
+msgid "1D plot"
+msgstr "Grafico 1D"
+
+#: udav/newcmd_dlg.cpp:166 mgllab/dialogs.cpp:707
+msgid "1D plots"
+msgstr "Graficos 1D"
+
+#: mgllab/help.cpp:359
+msgid "1D view"
+msgstr "Vista 1D"
+
+#: src/parser.cpp:51
+msgid "2 - setup"
+msgstr "2 - configurar"
+
+#: udav/info_dlg.cpp:47
+msgid "2D plot"
+msgstr "Grafico 2D"
+
+#: udav/newcmd_dlg.cpp:167 mgllab/dialogs.cpp:708
+msgid "2D plots"
+msgstr "Graficos 2D"
+
+#: mgllab/help.cpp:361
+msgid "2D view"
+msgstr "Vista 2D"
+
+#: src/parser.cpp:51
+msgid "3 - data handle"
+msgstr ""
+
+#: udav/open_dlg.cpp:71
+msgid "3D data with sizes from file"
+msgstr "Datos 3D con tamaños de archivo"
+
+#: udav/newcmd_dlg.cpp:168 mgllab/dialogs.cpp:709
+msgid "3D plots"
+msgstr "graficos 3D"
+
+#: mgllab/help.cpp:363
+msgid "3D view"
+msgstr "Vista 3D"
+
+#: src/parser.cpp:51
+msgid "4 - data create"
+msgstr "4 - crear datos"
+
+#: src/parser.cpp:51
+msgid "5 - subplot"
+msgstr "5 - subgrafico"
+
+#: src/parser.cpp:51
+msgid "6 - program flow"
+msgstr "6 - flujo de programa"
+
+#: src/parser.cpp:51
+msgid "7 - 1d plot"
+msgstr "7 - grafico 1d"
+
+#: src/parser.cpp:51
+msgid "8 - 2d plot"
+msgstr "8 - grafico 2d"
+
+#: src/parser.cpp:51
+msgid "9 - 3d plot"
+msgstr "9 - grafico 3d"
+
+#: udav/udav_wnd.cpp:455
+msgid ""
+"<br>(c) Alexey Balakin, 2007-present<br><br><a href='http://www.gnu.org/"
+"copyleft/gpl.html'>License is GPL v.2 or later.</a>"
+msgstr ""
+
+#: mgllab/help.cpp:304
+msgid "@<-  Prev"
+msgstr ""
+
+#: widgets/qt.cpp:1277 udav/udav_wnd.cpp:331 mgllab/mgllab.cpp:332
+msgid "About"
+msgstr "Acerca de"
+
+#. -----------------------------------------------------------------------------
+#: widgets/qt.cpp:863 widgets/qt.cpp:1278 udav/udav_wnd.cpp:332
+#: udav/udav_wnd.cpp:460
+msgid "About Qt"
+msgstr "Acerca de Qt"
+
+#: widgets/qt.cpp:1156 udav/plot_pnl.cpp:372
+msgid "Add arc"
+msgstr "Anadir arco"
+
+#: widgets/qt.cpp:1159 udav/plot_pnl.cpp:375
+msgid "Add arc which properties can be changed later by mouse."
+msgstr "Anadir arco cuyas propiedades pueden ser cambiadas luego con el mouse."
+
+#: mgllab/dialogs.cpp:84
+msgid "Add command option(s)"
+msgstr "Anadir opcion(es) de comando"
+
+#: widgets/qt.cpp:1161 udav/plot_pnl.cpp:378
+msgid "Add curve"
+msgstr "Anadir curva"
+
+#: widgets/qt.cpp:1164 udav/plot_pnl.cpp:381
+msgid "Add curve which properties can be changed later by mouse."
+msgstr ""
+"Anadir curva cuyas propiedades pueden ser cambiadas luego con el mouse."
+
+#: src/exec_dat.cpp:1523
+msgid "Add data or number"
+msgstr "Anadir datos o numero"
+
+#: widgets/qt.cpp:1176 udav/plot_pnl.cpp:396
+msgid "Add ellipse"
+msgstr "Anadir elipse"
+
+#: widgets/qt.cpp:1179 udav/plot_pnl.cpp:399 udav/plot_pnl.cpp:405
+msgid "Add ellipse which properties can be changed later by mouse."
+msgstr ""
+"Anadir elipse cuyas propiedades pueden ser cambiadas luego con el  mouse."
+
+#: mgllab/dialogs.cpp:1229
+msgid "Add inplot"
+msgstr "Anadir grafico interno"
+
+#: src/exec_set.cpp:690
+msgid "Add legend entry"
+msgstr "Anadir entrada a leyenda"
+
+#: mgllab/dialogs.cpp:119
+msgid "Add legend entry for the plot"
+msgstr "Anadir entrada a leyenda para grafico"
+
+#: widgets/qt.cpp:1151 udav/plot_pnl.cpp:366
+msgid "Add line"
+msgstr "Anadir linea"
+
+#: widgets/qt.cpp:1154 udav/plot_pnl.cpp:369
+msgid "Add line which properties can be changed later by mouse."
+msgstr ""
+"Anadir linea cuyas propiedades pueden ser cambiadas luego con el mouse."
+
+#: widgets/qt.cpp:1186 udav/plot_pnl.cpp:408
+msgid "Add mark"
+msgstr "Anadir marca"
+
+#: widgets/qt.cpp:1189 udav/plot_pnl.cpp:411
+msgid "Add marker which properties can be changed later by mouse."
+msgstr ""
+"Anadir marca cuyas propiedades pueden ser cambiadas luego con el mouse."
+
+#: widgets/qt.cpp:1181 udav/plot_pnl.cpp:402
+msgid "Add polygon"
+msgstr "Anadir poligono"
+
+#: widgets/qt.cpp:1184
+msgid "Add polygon which properties can be changed later by mouse."
+msgstr ""
+"Anadir poligono cuyas propiedades pueden ser cambiadas luego con el mouse."
+
+#: mgllab/dialogs.cpp:1453
+msgid "Add primitive"
+msgstr "Anadir primitiva"
+
+#: widgets/qt.cpp:1166 udav/plot_pnl.cpp:384
+msgid "Add rect"
+msgstr "Anadir recta"
+
+#: widgets/qt.cpp:1169 udav/plot_pnl.cpp:387
+msgid "Add rectangle which properties can be changed later by mouse."
+msgstr ""
+"Anadir rectangulo cuyas propiedades pueden ser cambiadas luego con el mouse."
+
+#: widgets/qt.cpp:1171 udav/plot_pnl.cpp:390
+msgid "Add rhombus"
+msgstr "Anadir rombo"
+
+#: widgets/qt.cpp:1174 udav/plot_pnl.cpp:393
+msgid "Add rhombus which properties can be changed later by mouse."
+msgstr ""
+"Anadir rombo cuyas propiedades pueden ser cambiadas luego con el mouse."
+
+#: widgets/qt.cpp:1191 udav/plot_pnl.cpp:414
+msgid "Add text"
+msgstr "Anadir texto"
+
+#: widgets/qt.cpp:1194 udav/plot_pnl.cpp:417
+msgid "Add text which properties can be changed later by mouse."
+msgstr ""
+"Anadir texto cuyas propiedades pueden ser cambiadas luego con el mouse."
+
+#: src/exec_prm.cpp:611
+msgid "Add title for current subplot/inplot"
+msgstr "Anadir titulo para el subgrafico/grafico interno actual"
+
+#: mgllab/table.cpp:794
+msgid "Add to"
+msgstr "Anadir a"
+
+#: src/exec_set.cpp:691
+msgid "Add user-defined symbol"
+msgstr "Anadir simbolo definido por el usuario"
+
+#: widgets/fltk.cpp:851
+msgid "Adjust picture size to fill drawing area"
+msgstr "Ajustar tamano de la imagen para llenar el area de grafico"
+
+#: widgets/fltk.cpp:814 widgets/qt.cpp:1139 udav/plot_pnl.cpp:337
+msgid "Adjust size"
+msgstr "Ajustar tamano"
+
+#: src/exec_set.cpp:692
+msgid "Adjust ticks for best view"
+msgstr "Ajustar marcas del eje a la mejor apariencia"
+
+#: udav/calc_dlg.cpp:193
+msgid "Airy and Gamma"
+msgstr ""
+
+#: udav/hint_dlg.cpp:42 mgllab/help.cpp:276
+msgid ""
+"All indexes (of data arrays, subplots and so on) are always start from 0."
+msgstr ""
+"Todos los indices (de vectores de datos, subgraficos, etc.) siempre empiezan "
+"en 0."
+
+#. graphics menu
+#: widgets/qt.cpp:1098 udav/opt_dlg.cpp:51 udav/setup_dlg.cpp:109
+#: udav/plot_pnl.cpp:290 mgllab/dialogs.cpp:109
+msgid "Alpha"
+msgstr "Alfa"
+
+#: mgllab/dialogs.cpp:110
+msgid "Alpha value (transparency) of surface or cloud"
+msgstr "Valor alfa (transparencia) de superficie o nube"
+
+#: udav/setup_dlg.cpp:93 mgllab/dialogs.cpp:1003
+msgid "AlphaDef"
+msgstr ""
+
+#: udav/opt_dlg.cpp:56 udav/setup_dlg.cpp:95 mgllab/dialogs.cpp:111
+#: mgllab/dialogs.cpp:1004
+msgid "Ambient"
+msgstr "Ambiente"
+
+#: udav/subplot_dlg.cpp:167
+msgid "Angle around x axis (in degrees)"
+msgstr "Angulo alrededor del eje x (en grados)"
+
+#: udav/subplot_dlg.cpp:171
+msgid "Angle around z axis (in degrees)"
+msgstr "Angulo alrededor del eje z (en grados)"
+
+#. animation menu
+#: widgets/qt.cpp:1244 widgets/qt.cpp:1245 udav/plot_pnl.cpp:559
+#: mgllab/mathgl.cpp:183
+msgid "Animation"
+msgstr "Animacion"
+
+#: mgllab/table.cpp:786
+msgid "Another"
+msgstr "Otro"
+
+#: mgllab/table.cpp:852
+msgid "Apply operator (smoothing, integration, difference ...) to data"
+msgstr "Aplicar operador (suavizado, integracion, diferencia ...) a datos"
+
+#: mgllab/dialogs.cpp:103
+msgid "Approximate number of mesh lines in plot"
+msgstr "Numero aproximado de numero de lineas de la malla en el grafico"
+
+#: mgllab/help.cpp:135
+msgid "Are you sure that you want to delete ALL data arrays?"
+msgstr "Esta seguro que desea borrar TODOS los vectores de datos?"
+
+#: udav/newcmd_dlg.cpp:67
+msgid "Argument"
+msgstr "Argumento"
+
+#: mgllab/dialogs.cpp:738
+msgid "Arguments"
+msgstr "Argumentos"
+
+#: udav/style_dlg.cpp:63 mgllab/dialogs.cpp:321
+msgid "Arrow at end"
+msgstr "Flecha al final"
+
+#. g->setColStretch(0, 1);	g->setColStretch(1, 1);	g->setColStretch(2, 1);
+#: udav/style_dlg.cpp:61 mgllab/dialogs.cpp:315
+msgid "Arrow at start"
+msgstr "Flecha al principio"
+
+#: widgets/qt.cpp:1137
+msgid "Ask to stop plot drawing (F7)."
+msgstr "Solicitar detener graficacion (F7)."
+
+#: udav/subplot_dlg.cpp:175
+msgid "Aspect"
+msgstr "Aspecto"
+
+#: udav/subplot_dlg.cpp:178
+msgid "Aspect ratio of x-scale to z-scale"
+msgstr "Proporcion de aspecto de  escala-x a escala-z"
+
+#: udav/subplot_dlg.cpp:182
+msgid "Aspect ratio of y-scale to z-scale"
+msgstr "Proporcion de aspecto de  escala-y a escala-z"
+
+#: mgllab/dialogs.cpp:1298
+msgid "Aspect x/z"
+msgstr "Aspecto x/z"
+
+#: src/exec_set.cpp:698
+msgid "Attach light settings to inplot"
+msgstr "Vincular configuracion de luz a grafico interno"
+
+#: udav/open_dlg.cpp:60
+msgid "Auto detect data sizes"
+msgstr "Autodetectar tamanos de datos"
+
+#: udav/open_dlg.cpp:177
+msgid "Auto detect data sizes (%1 x %2 x %3)"
+msgstr ""
+
+#: udav/prop_dlg.cpp:100
+msgid "AutoKey"
+msgstr ""
+
+#: udav/prop_dlg.cpp:159
+msgid "Automatically execute script after loading"
+msgstr ""
+
+#: udav/prop_dlg.cpp:165
+msgid "Automatically save before redrawing (F5)"
+msgstr ""
+
+#: src/data.cpp:1425
+#, c-format
+msgid ""
+"Averages are:\n"
+"<a> = %g\t<x> = %g\t<y> = %g\t<z> = %g\n"
+msgstr ""
+
+#: udav/style_dlg.cpp:122 mgllab/dialogs.cpp:340
+msgid "Axial direction"
+msgstr ""
+
+#: udav/setup_dlg.cpp:101
+msgid "AxialDir"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1008
+msgid "Axis"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:176 mgllab/dialogs.cpp:717
+msgid "Axis and colorbar"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:177 mgllab/dialogs.cpp:718 mgllab/dialogs.cpp:949
+msgid "Axis setup"
+msgstr ""
+
+#. W
+#: udav/style_dlg.cpp:237 mgllab/dialogs.cpp:45
+msgid "B - navy"
+msgstr ""
+
+#: udav/help_pnl.cpp:48
+msgid "Backward"
+msgstr ""
+
+#: src/font.cpp:947
+#, c-format
+msgid "Bad '%ls' at %zu\n"
+msgstr ""
+
+#: src/parser.cpp:766
+#, c-format
+msgid "Bad arguments for %ls: %ld instead of %d\n"
+msgstr ""
+
+#: udav/setup_dlg.cpp:97
+msgid "BaseWidth"
+msgstr ""
+
+#: udav/calc_dlg.cpp:192
+msgid "Basic"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1461
+msgid "Begin"
+msgstr ""
+
+#: udav/calc_dlg.cpp:193
+msgid "Bessel"
+msgstr ""
+
+#: udav/style_dlg.cpp:157 mgllab/dialogs.cpp:368
+msgid "Bold style"
+msgstr ""
+
+#: udav/opt_dlg.cpp:115
+msgid "Both fields in crange must be filled"
+msgstr ""
+
+#: udav/opt_dlg.cpp:94
+msgid "Both fields in xrange must be filled"
+msgstr ""
+
+#: udav/opt_dlg.cpp:101
+msgid "Both fields in yrange must be filled"
+msgstr ""
+
+#: udav/opt_dlg.cpp:108
+msgid "Both fields in zrange must be filled"
+msgstr ""
+
+#: src/parser.cpp:1423
+msgid "Break for-loop"
+msgstr ""
+
+#: udav/setup_dlg.cpp:122 mgllab/dialogs.cpp:1069
+msgid "Brightness"
+msgstr ""
+
+#: mgllab/dialogs.cpp:401
+msgid "Brightness of i-th color"
+msgstr ""
+
+#: mgllab/table.cpp:766
+msgid "By formula"
+msgstr ""
+
+#. R
+#: udav/style_dlg.cpp:240 mgllab/dialogs.cpp:48
+msgid "C - teal"
+msgstr ""
+
+#: udav/setup_dlg.cpp:51 mgllab/dialogs.cpp:989
+msgid "C axis"
+msgstr ""
+
+#: udav/opt_dlg.cpp:47 mgllab/dialogs.cpp:97
+msgid "C-range"
+msgstr ""
+
+#: widgets/qt.cpp:1263
+msgid "Calculations"
+msgstr ""
+
+#. TODO
+#. connect(hidden,SIGNAL(cursorPositionChanged()),this,SLOT(hiddenClicked()));
+#: udav/udav_wnd.cpp:194 udav/udav_wnd.cpp:206 mgllab/mgllab.cpp:326
+#: mgllab/mgllab.cpp:557
+msgid "Calculator"
+msgstr ""
+
+#: udav/anim_dlg.cpp:67 udav/prop_dlg.cpp:180 udav/args_dlg.cpp:63
+#: udav/newcmd_dlg.cpp:78 udav/open_dlg.cpp:90 udav/dat_pnl.cpp:460
+#: udav/dat_pnl.cpp:510 udav/dat_pnl.cpp:552 udav/dat_pnl.cpp:629
+#: udav/opt_dlg.cpp:78 udav/setup_dlg.cpp:145 udav/files_dlg.cpp:58
+#: udav/style_dlg.cpp:206 udav/data_dlg.cpp:90 udav/subplot_dlg.cpp:219
+#: mgllab/editor.cpp:282 mgllab/mathgl.cpp:164 mgllab/mathgl.cpp:195
+#: mgllab/dialogs.cpp:120 mgllab/dialogs.cpp:164 mgllab/dialogs.cpp:410
+#: mgllab/dialogs.cpp:584 mgllab/dialogs.cpp:749 mgllab/dialogs.cpp:1071
+#: mgllab/dialogs.cpp:1318 mgllab/dialogs.cpp:1473 mgllab/mgllab.cpp:482
+#: mgllab/table.cpp:101 mgllab/table.cpp:179 mgllab/table.cpp:353
+#: mgllab/table.cpp:556 mgllab/table.cpp:619 mgllab/table.cpp:674
+msgid "Cancel"
+msgstr ""
+
+#: src/crust.cpp:557
+msgid "Cannot triangulate this set!"
+msgstr ""
+
+#: udav/udav_wnd.cpp:226 mgllab/mgllab.cpp:355 mgllab/mgllab.cpp:356
+msgid "Canvas"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:59 udav/subplot_dlg.cpp:101 udav/subplot_dlg.cpp:118
+#: udav/subplot_dlg.cpp:135
+msgid "Cell index"
+msgstr ""
+
+#: mgllab/table.cpp:103 mgllab/table.cpp:558 mgllab/table.cpp:770
+msgid "Change"
+msgstr ""
+
+#: mgllab/table.cpp:104
+msgid "Change (resize) data"
+msgstr ""
+
+#: widgets/qt.cpp:1141 udav/plot_pnl.cpp:339
+msgid "Change canvas size to fill whole region (F6)."
+msgstr ""
+
+#: src/exec_set.cpp:702
+msgid "Change current directory"
+msgstr ""
+
+#: mgllab/table.cpp:168
+msgid "Change data"
+msgstr ""
+
+#: mgllab/table.cpp:91
+msgid "Change data sizes"
+msgstr ""
+
+#: mgllab/table.cpp:559 mgllab/table.cpp:622 mgllab/table.cpp:677
+msgid "Change data values and close this window"
+msgstr ""
+
+#: udav/prop_dlg.cpp:71
+msgid "Change font"
+msgstr ""
+
+#: src/exec_set.cpp:751
+msgid "Change view angles - use 'rotate' for plot rotation"
+msgstr ""
+
+#: udav/calc_dlg.cpp:68
+msgid "Clear"
+msgstr ""
+
+#: udav/text_pnl.cpp:527
+msgid "Clear all"
+msgstr ""
+
+#: src/exec_set.cpp:703
+msgid "Clear legend entries"
+msgstr ""
+
+#: src/exec_set.cpp:704
+msgid "Clear picture"
+msgstr ""
+
+#. o = new Fl_Button(180, 130, 25, 25);o->image(img_save);	o->tooltip("img_save");
+#: widgets/qt.cpp:1091 udav/find_dlg.cpp:52 udav/hint_dlg.cpp:70
+#: mgllab/editor.cpp:565 mgllab/help.cpp:308 mgllab/help.cpp:367
+#: mgllab/help.cpp:483
+msgid "Close"
+msgstr ""
+
+#: udav/dat_pnl.cpp:833
+msgid "Close tab"
+msgstr ""
+
+#: udav/dat_pnl.cpp:835
+msgid "Close this data tab."
+msgstr ""
+
+#: udav/setup_dlg.cpp:121 udav/style_dlg.cpp:67 mgllab/dialogs.cpp:1068
+#: mgllab/dialogs.cpp:1459
+msgid "Color"
+msgstr ""
+
+#. g->setColStretch(0, 1);			g->setColStretch(1, 1);
+#: udav/style_dlg.cpp:106
+msgid "Color order"
+msgstr ""
+
+#: udav/style_dlg.cpp:150 mgllab/dialogs.cpp:339
+msgid "Color scheme"
+msgstr ""
+
+#: mgllab/dialogs.cpp:384
+msgid "Color(s) or color scheme"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1002
+msgid "Colors"
+msgstr ""
+
+#: mgllab/table.cpp:879
+msgid ""
+"Colors denote values: magenta - local max, cyan - local min,\n"
+"\tred - Re(v)>0, blue - Re(v)<0, purple - Im(v)>0, teal - Im(v)<0."
+msgstr ""
+
+#: mgllab/dialogs.cpp:577
+msgid "Column expr"
+msgstr ""
+
+#: mgllab/dialogs.cpp:724 mgllab/mgllab.cpp:305
+msgid "Command"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:64 mgllab/dialogs.cpp:740
+msgid ""
+"Command arguments. Bold ones are required arguments.\n"
+"Other are optional arguments but its order is required.\n"
+"You can use '' for default format. See help at right\n"
+"for default values."
+msgstr ""
+
+#: udav/text_pnl.cpp:575
+msgid "Command options"
+msgstr ""
+
+#: udav/prop_dlg.cpp:82
+msgid "Comments"
+msgstr ""
+
+#: src/exec_prm.cpp:599
+msgid "Computes the attractor of an IFS"
+msgstr ""
+
+#: src/exec_prm.cpp:600
+msgid "Computes the attractor of an IFS for 3d case"
+msgstr ""
+
+#: src/exec_prm.cpp:601
+msgid "Computes the attractor of an IFS with parameters from *.ifs file"
+msgstr ""
+
+#: src/exec_prm.cpp:595
+msgid "Computes the flame fractal"
+msgstr ""
+
+#: src/parser.cpp:1431 src/parser.cpp:1435
+msgid "Conditional operator"
+msgstr ""
+
+#: udav/plot_pnl.cpp:358
+msgid "Copy click coor."
+msgstr ""
+
+#: udav/plot_pnl.cpp:360
+msgid "Copy coordinates of last mouse click to clipboard."
+msgstr ""
+
+#: udav/dat_pnl.cpp:707
+msgid "Copy data"
+msgstr ""
+
+#: src/exec_dat.cpp:1528
+msgid "Copy data from another variable"
+msgstr ""
+
+#: widgets/fltk.cpp:811
+msgid "Copy graphics"
+msgstr ""
+
+#: widgets/qt.cpp:1145 udav/plot_pnl.cpp:354
+msgid "Copy graphics to clipboard (Ctrl+Shift+G)."
+msgstr ""
+
+#: widgets/fltk.cpp:855
+msgid "Copy image to clipboard"
+msgstr ""
+
+#: widgets/qt.cpp:1143 udav/plot_pnl.cpp:352
+msgid "Copy plot"
+msgstr ""
+
+#: udav/dat_pnl.cpp:709
+msgid "Copy range of numbers to clipboard (Ctrl+Shift+C)."
+msgstr ""
+
+#: udav/text_pnl.cpp:535
+msgid "Copy selected text or data to clipboard (Ctrl+C)."
+msgstr ""
+
+#: mgllab/editor.cpp:511
+msgid "Copy selection to clipboard"
+msgstr ""
+
+#: udav/text_pnl.cpp:533 mgllab/mgllab.cpp:295
+msgid "Copy text"
+msgstr ""
+
+#: mgllab/table.cpp:778
+msgid "Cos FFT"
+msgstr ""
+
+#: udav/dat_pnl.cpp:621
+msgid "Cos-Fourier transform along direction(s)"
+msgstr ""
+
+#: src/exec_dat.cpp:1530
+msgid "Cos-Fourier transform at some direction"
+msgstr ""
+
+#: mgllab/table.cpp:165
+msgid "Cosine FFT"
+msgstr ""
+
+#: udav/text_pnl.cpp:365 udav/text_pnl.cpp:482
+msgid "Could not write to %1"
+msgstr ""
+
+#: udav/setup_dlg.cpp:159
+msgid "Could not write to file"
+msgstr ""
+
+#: udav/udav_wnd.cpp:570
+msgid "Couldn't change to folder "
+msgstr ""
+
+#: udav/text_pnl.cpp:431
+msgid "Couldn't open file "
+msgstr ""
+
+#: mgllab/dialogs.cpp:1190
+#, c-format
+msgid "Couldn't open file %s"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:173
+msgid "Create data and I/O"
+msgstr ""
+
+#: mgllab/dialogs.cpp:714
+msgid "Create data and IO"
+msgstr ""
+
+#: src/exec_dat.cpp:1555
+msgid "Create histogram (distribution) of data values"
+msgstr ""
+
+#: udav/dat_pnl.cpp:766 mgllab/table.cpp:758
+msgid "Create new"
+msgstr ""
+
+#: src/exec_dat.cpp:1614
+msgid "Create new 1D data and fill it in range"
+msgstr ""
+
+#: src/exec_dat.cpp:1570
+msgid "Create new data"
+msgstr ""
+
+#: udav/mem_pnl.cpp:58
+msgid "Create new data array"
+msgstr ""
+
+#: mgllab/table.cpp:836
+msgid "Create new data with zero filling"
+msgstr ""
+
+#: udav/udav_wnd.cpp:284
+msgid "Create new empty script window (Ctrl+N)."
+msgstr ""
+
+#: src/parser.cpp:1436
+msgid "Creates new variable from list of numbers or data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:784 mgllab/table.cpp:761
+msgid "Crop"
+msgstr ""
+
+#: mgllab/table.cpp:858
+msgid "Crop (cut off edges) data"
+msgstr ""
+
+#: mgllab/table.cpp:607
+msgid "Crop data"
+msgstr ""
+
+#: src/exec_dat.cpp:1531
+msgid "Crop edge of data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:786
+msgid "Crop the data edges. Useful to cut off the zero-filled area."
+msgstr ""
+
+#: mgllab/table.cpp:163 mgllab/table.cpp:772
+msgid "CumSum"
+msgstr ""
+
+#: src/exec_dat.cpp:1532
+msgid "Cumulative summation along direction(s)"
+msgstr ""
+
+#: udav/prop_dlg.cpp:106
+msgid "CurrLine"
+msgstr ""
+
+#: udav/prop_dlg.cpp:68
+msgid "Current font"
+msgstr ""
+
+#: udav/text_pnl.cpp:530
+msgid "Cut selected text to clipboard (Ctrl+X)."
+msgstr ""
+
+#: udav/text_pnl.cpp:528 mgllab/mgllab.cpp:294
+msgid "Cut text"
+msgstr ""
+
+#: udav/opt_dlg.cpp:61 mgllab/dialogs.cpp:106
+msgid "Cutting"
+msgstr ""
+
+#: mgllab/help.cpp:251 mgllab/table.cpp:428 mgllab/table.cpp:457
+msgid ""
+"DAT Files \t*.{dat,csv}\n"
+"HDF Files \t*.{h5,hdf}"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1465
+msgid "Dash"
+msgstr ""
+
+#: udav/style_dlg.cpp:62 mgllab/dialogs.cpp:318
+msgid "Dashing"
+msgstr ""
+
+#: udav/dat_pnl.cpp:66
+msgid "Data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:249 udav/dat_pnl.cpp:271
+msgid ""
+"Data files (*.dat)\n"
+"HDF5 files (*.h5 *.hdf)\n"
+"PNG files (*.png)\n"
+"All files (*.*)"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:175 mgllab/dialogs.cpp:716
+msgid "Data handling"
+msgstr ""
+
+#: mgllab/help.cpp:163 mgllab/table.cpp:849
+msgid "Data information and preview."
+msgstr ""
+
+#: udav/open_dlg.cpp:56 udav/data_dlg.cpp:42 mgllab/dialogs.cpp:566
+msgid "Data name"
+msgstr ""
+
+#: udav/info_dlg.cpp:42
+msgid "Data preview"
+msgstr ""
+
+#: udav/info_dlg.cpp:43
+msgid "Data preview for current slice."
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:174 mgllab/dialogs.cpp:715
+msgid "Data transform"
+msgstr ""
+
+#: udav/plot_pnl.cpp:556
+msgid "Decrease \\phi angle by 10 degrees."
+msgstr ""
+
+#: udav/plot_pnl.cpp:548
+msgid "Decrease \\theta angle by 10 degrees."
+msgstr ""
+
+#: mgllab/help.cpp:105
+msgid "Decrease font size"
+msgstr ""
+
+#: src/parser.cpp:1427
+msgid "Define constant or parameter"
+msgstr ""
+
+#: src/parser.cpp:1426
+msgid "Define parameter as character"
+msgstr ""
+
+#: src/parser.cpp:1428
+msgid "Define parameter as numerical value"
+msgstr ""
+
+#: src/parser.cpp:1422
+msgid "Define parameter from user input"
+msgstr ""
+
+#: udav/anim_dlg.cpp:76
+msgid "Delay (in ms)"
+msgstr ""
+
+#: mgllab/mathgl.cpp:202
+msgid "Delay (in sec)"
+msgstr ""
+
+#: mgllab/help.cpp:178
+msgid "Delete @b all at . data arrays."
+msgstr ""
+
+#: udav/mem_pnl.cpp:64
+msgid "Delete ALL data arrays"
+msgstr ""
+
+#: src/exec_dat.cpp:1535
+msgid "Delete data or slice of data"
+msgstr ""
+
+#: udav/plot_pnl.cpp:426
+msgid "Delete selected"
+msgstr ""
+
+#: udav/mem_pnl.cpp:60
+msgid "Delete selected data array"
+msgstr ""
+
+#: mgllab/help.cpp:166
+msgid "Delete selected data."
+msgstr ""
+
+#: udav/plot_pnl.cpp:428
+msgid "Delete selected plot."
+msgstr ""
+
+#: mgllab/dialogs.cpp:734
+msgid "Description"
+msgstr ""
+
+#: src/exec_dat.cpp:1536
+msgid "Detect curves for maximums of data array"
+msgstr ""
+
+#: mgllab/table.cpp:164 mgllab/table.cpp:774
+msgid "Difference"
+msgstr ""
+
+#: udav/dat_pnl.cpp:616
+msgid "Differentiate data along direction(s)"
+msgstr ""
+
+#: udav/opt_dlg.cpp:58 mgllab/dialogs.cpp:113 mgllab/dialogs.cpp:1005
+msgid "Diffuse"
+msgstr ""
+
+#: src/exec_dat.cpp:1540
+msgid "Dilate data larger val"
+msgstr ""
+
+#: src/exec_dat.cpp:1527
+msgid "Direct multiplication of arrays"
+msgstr ""
+
+#: udav/dat_pnl.cpp:351 udav/dat_pnl.cpp:377 udav/dat_pnl.cpp:424
+#: mgllab/dialogs.cpp:161 mgllab/table.cpp:549
+msgid "Direction"
+msgstr ""
+
+#: mgllab/table.cpp:551
+msgid "Direction along which data will be filled"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:105 udav/subplot_dlg.cpp:122
+msgid "Distance between cells"
+msgstr ""
+
+#: mgllab/table.cpp:797
+msgid "Divide by"
+msgstr ""
+
+#: src/exec_dat.cpp:1541
+msgid "Divide by data or number"
+msgstr ""
+
+#: mgllab/table.cpp:180 mgllab/table.cpp:354 mgllab/table.cpp:676
+msgid "Do"
+msgstr ""
+
+#: src/exec_dat.cpp:1603
+msgid "Do STFA transform"
+msgstr ""
+
+#: src/exec_dat.cpp:1609 src/exec_dat.cpp:1610
+msgid "Do integral transform of data"
+msgstr ""
+
+#: mgllab/table.cpp:102 mgllab/table.cpp:557 mgllab/table.cpp:620
+#: mgllab/table.cpp:675
+msgid "Do nothing and close this window"
+msgstr ""
+
+#: udav/mem_pnl.cpp:122
+msgid "Do you want to delete all data?"
+msgstr ""
+
+#: udav/udav_wnd.cpp:341 udav/udav_wnd.cpp:580 udav/udav_wnd.cpp:622
+msgid "Do you want to save the changes to the document?"
+msgstr ""
+
+#: mgllab/editor.cpp:282
+msgid "Don't Save"
+msgstr ""
+
+#: mgllab/table.cpp:164
+msgid "Double diff."
+msgstr ""
+
+#: src/exec_gr.cpp:1032
+msgid "Draw Bifurcation diagram"
+msgstr ""
+
+#: src/exec_gr.cpp:1067
+msgid "Draw Iris plots"
+msgstr ""
+
+#: src/exec_gr.cpp:1069
+msgid "Draw Lamerey diagram"
+msgstr ""
+
+#: src/exec_gr.cpp:1073
+msgid "Draw Open-High-Low-Close (OHLC) diagram"
+msgstr ""
+
+#: src/exec_gr.cpp:1076
+msgid "Draw Poincare map"
+msgstr ""
+
+#: src/exec_gr.cpp:1082
+msgid "Draw STFA diagram"
+msgstr ""
+
+#: src/exec_gr.cpp:1094
+msgid "Draw TeX mark at point position"
+msgstr ""
+
+#: src/exec_prm.cpp:578
+msgid "Draw angle arc"
+msgstr ""
+
+#: src/exec_gr.cpp:1026
+msgid "Draw area plot for 1D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1029
+msgid "Draw bars for 1D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1031
+msgid "Draw belts"
+msgstr ""
+
+#: src/exec_gr.cpp:1092
+msgid "Draw binormales for 1D data"
+msgstr ""
+
+#: src/exec_prm.cpp:604
+msgid "Draw bitmap (logo) along axis range"
+msgstr ""
+
+#: src/exec_prm.cpp:582
+msgid "Draw bounding box"
+msgstr ""
+
+#: src/exec_gr.cpp:1034
+msgid "Draw boxes"
+msgstr ""
+
+#: src/exec_gr.cpp:1033
+msgid "Draw boxplot for 2D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1035
+msgid "Draw candlestick chart"
+msgstr ""
+
+#: src/exec_gr.cpp:1036
+msgid "Draw chart"
+msgstr ""
+
+#: src/exec_prm.cpp:583
+msgid "Draw circle"
+msgstr ""
+
+#: src/exec_gr.cpp:1037
+msgid "Draw cloud"
+msgstr ""
+
+#: src/exec_prm.cpp:584
+msgid "Draw colorbar"
+msgstr ""
+
+#: src/exec_prm.cpp:585
+msgid "Draw cone"
+msgstr ""
+
+#: src/exec_gr.cpp:1038
+msgid "Draw cones for 1D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1039
+msgid "Draw contour lines"
+msgstr ""
+
+#: src/exec_gr.cpp:1049
+msgid "Draw contour lines at x-slice (or x-plane)"
+msgstr ""
+
+#: src/exec_gr.cpp:1050
+msgid "Draw contour lines at y-slice (or y-plane)"
+msgstr ""
+
+#: src/exec_gr.cpp:1051
+msgid "Draw contour lines at z-slice (or z-plane)"
+msgstr ""
+
+#: src/exec_gr.cpp:1040
+msgid "Draw contour lines for 3D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1099
+msgid "Draw contour lines for surface of triangles"
+msgstr ""
+
+#: src/exec_gr.cpp:1047
+msgid "Draw contour lines on parametric surface"
+msgstr ""
+
+#: src/exec_gr.cpp:1048
+msgid "Draw contour tubes"
+msgstr ""
+
+#: src/exec_gr.cpp:1100
+msgid "Draw contour tubes for surface of triangles"
+msgstr ""
+
+#: src/exec_prm.cpp:586
+msgid "Draw curve"
+msgstr ""
+
+#: src/exec_gr.cpp:1102
+msgid "Draw curve by tube"
+msgstr ""
+
+#: src/exec_gr.cpp:1053
+msgid "Draw density plot"
+msgstr ""
+
+#: src/exec_gr.cpp:1054
+msgid "Draw density plot at slices of 3D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1055
+msgid "Draw density plot at x-slice (or x-plane)"
+msgstr ""
+
+#: src/exec_gr.cpp:1056
+msgid "Draw density plot at y-slice (or y-plane)"
+msgstr ""
+
+#: src/exec_gr.cpp:1057
+msgid "Draw density plot at z-slice (or z-plane)"
+msgstr ""
+
+#: src/exec_gr.cpp:1058
+msgid "Draw dew plot"
+msgstr ""
+
+#: src/exec_gr.cpp:1059
+msgid "Draw dots for arbitrary data points"
+msgstr ""
+
+#: src/exec_prm.cpp:587
+msgid "Draw drop"
+msgstr ""
+
+#: src/exec_prm.cpp:588
+msgid "Draw ellipse"
+msgstr ""
+
+#: src/exec_prm.cpp:589
+msgid "Draw error box"
+msgstr ""
+
+#: src/exec_gr.cpp:1060
+msgid "Draw error boxes"
+msgstr ""
+
+#: src/exec_prm.cpp:590
+msgid "Draw face (quadrangle)"
+msgstr ""
+
+#: src/exec_prm.cpp:591
+msgid "Draw face perpendicular to x-axis"
+msgstr ""
+
+#: src/exec_prm.cpp:592
+msgid "Draw face perpendicular to y-axis"
+msgstr ""
+
+#: src/exec_prm.cpp:593
+msgid "Draw face perpendicular to z-axis"
+msgstr ""
+
+#: src/exec_gr.cpp:1079
+msgid "Draw filled region (ribbon) between 2 curves"
+msgstr ""
+
+#: src/exec_gr.cpp:1074
+msgid "Draw flow pipes for vector field"
+msgstr ""
+
+#: src/exec_gr.cpp:1062
+msgid "Draw flow threads for vector field"
+msgstr ""
+
+#: src/exec_gr.cpp:1064
+msgid "Draw gradient lines for scalar field"
+msgstr ""
+
+#: src/exec_prm.cpp:598
+msgid "Draw grid"
+msgstr ""
+
+#: src/exec_gr.cpp:1066
+msgid "Draw grid at slices of 3D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1065
+msgid "Draw grid for data array(s)"
+msgstr ""
+
+#: src/exec_gr.cpp:1028
+msgid "Draw horizontal bars for 1D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1095
+msgid "Draw horizontal tiles"
+msgstr ""
+
+#: src/exec_gr.cpp:1096
+msgid "Draw horizontal tiles with variable size"
+msgstr ""
+
+#: src/exec_gr.cpp:1084
+msgid "Draw isosurface for 3D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1087
+msgid "Draw isosurface for 3D data colored and transpared by other data"
+msgstr ""
+
+#: src/exec_gr.cpp:1086
+msgid "Draw isosurface for 3D data colored by other data"
+msgstr ""
+
+#: src/exec_gr.cpp:1085
+msgid "Draw isosurface for 3D data transpared by other data"
+msgstr ""
+
+#: src/exec_gr.cpp:1068
+msgid "Draw label at arbitrary position"
+msgstr ""
+
+#: src/exec_prm.cpp:612
+msgid "Draw label for t-axis"
+msgstr ""
+
+#: src/exec_prm.cpp:613
+msgid "Draw label for x-axis"
+msgstr ""
+
+#: src/exec_prm.cpp:614
+msgid "Draw label for y-axis"
+msgstr ""
+
+#: src/exec_prm.cpp:615
+msgid "Draw label for z-axis"
+msgstr ""
+
+#: src/exec_prm.cpp:602
+msgid "Draw legend"
+msgstr ""
+
+#: src/exec_prm.cpp:603
+msgid "Draw line"
+msgstr ""
+
+#: src/exec_gr.cpp:1070
+msgid "Draw mapping plot"
+msgstr ""
+
+#: src/exec_gr.cpp:1071
+msgid "Draw mark plot for 1D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1072
+msgid "Draw mesh surface"
+msgstr ""
+
+#: src/exec_prm.cpp:581
+msgid "Draw point (ball)"
+msgstr ""
+
+#: src/exec_prm.cpp:605
+msgid "Draw polygon"
+msgstr ""
+
+#: src/exec_gr.cpp:1030
+msgid "Draw quasi-optical beam"
+msgstr ""
+
+#: src/exec_gr.cpp:1078
+msgid "Draw radar chart"
+msgstr ""
+
+#: src/exec_gr.cpp:1052
+msgid "Draw reconstructed surface for arbitrary data points"
+msgstr ""
+
+#: src/exec_prm.cpp:606
+msgid "Draw rectangle"
+msgstr ""
+
+#: src/exec_prm.cpp:607
+msgid "Draw rhombus"
+msgstr ""
+
+#: src/exec_gr.cpp:1044
+msgid "Draw solid contour lines at x-slice (or x-plane)"
+msgstr ""
+
+#: src/exec_gr.cpp:1045
+msgid "Draw solid contour lines at y-slice (or y-plane)"
+msgstr ""
+
+#: src/exec_gr.cpp:1046
+msgid "Draw solid contour lines at z-slice (or z-plane)"
+msgstr ""
+
+#: src/exec_gr.cpp:1043
+msgid "Draw solid contour lines for 3D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1042
+msgid "Draw solid contours"
+msgstr ""
+
+#: src/exec_gr.cpp:1041
+msgid "Draw solid contours with manual colors"
+msgstr ""
+
+#: src/exec_gr.cpp:1083
+msgid "Draw solid surface"
+msgstr ""
+
+#: src/exec_gr.cpp:1090
+msgid "Draw solid surface colored and transpared by other data"
+msgstr ""
+
+#: src/exec_gr.cpp:1089
+msgid "Draw solid surface colored by other data"
+msgstr ""
+
+#: src/exec_gr.cpp:1088
+msgid "Draw solid surface transpared by other data"
+msgstr ""
+
+#: src/exec_prm.cpp:608
+msgid "Draw sphere"
+msgstr ""
+
+#: src/exec_gr.cpp:1080
+msgid "Draw stem plot for 1D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1081
+msgid "Draw step plot for 1D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1097
+msgid "Draw surface of curve rotation"
+msgstr ""
+
+#: src/exec_gr.cpp:1077
+msgid "Draw surface of quadrangles"
+msgstr ""
+
+#: src/exec_gr.cpp:1101
+msgid "Draw surface of triangles"
+msgstr ""
+
+#: src/exec_gr.cpp:1027
+msgid "Draw surfaces of contour lines rotation"
+msgstr ""
+
+#: src/exec_gr.cpp:1091
+msgid "Draw table with data values"
+msgstr ""
+
+#: src/exec_gr.cpp:1093
+msgid "Draw tension plot for 1D data"
+msgstr ""
+
+#: src/exec_prm.cpp:610
+msgid "Draw text at some position or along curve"
+msgstr ""
+
+#: src/exec_prm.cpp:609
+msgid "Draw user-defined symbol at given position and direction"
+msgstr ""
+
+#: src/exec_gr.cpp:1075
+msgid "Draw usual plot for 1D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1103
+msgid "Draw vector field"
+msgstr ""
+
+#: src/exec_gr.cpp:1104
+msgid "Draw vector field at slices of 3D data"
+msgstr ""
+
+#: src/exec_gr.cpp:1098
+msgid "Draw vectors along a curve"
+msgstr ""
+
+#: src/exec_gr.cpp:1061
+msgid "Draw waterfalls"
+msgstr ""
+
+#: udav/plot_pnl.cpp:111 udav/plot_pnl.cpp:130
+msgid "Drawing time %1 ms"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:169 mgllab/dialogs.cpp:710
+msgid "Dual plots"
+msgstr ""
+
+#. L
+#: udav/style_dlg.cpp:244 mgllab/dialogs.cpp:52
+msgid "E - darklawn"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1469
+msgid "Edges"
+msgstr ""
+
+#: udav/text_pnl.cpp:84 mgllab/mgllab.cpp:292
+msgid "Edit"
+msgstr ""
+
+#: udav/mem_pnl.cpp:59
+msgid "Edit selected data array"
+msgstr ""
+
+#: udav/calc_dlg.cpp:193
+msgid "Elliptic"
+msgstr ""
+
+#: udav/prop_dlg.cpp:171 mgllab/mgllab.cpp:474
+msgid "Enable keywords completion"
+msgstr ""
+
+#. pure = new QCheckBox(_("Disable face drawing (faster) for mouse rotation/shift/zoom."), this);
+#. pure->setChecked(mglAutoPure);	v->addWidget(pure);	pure->setEnabled(false);
+#: udav/prop_dlg.cpp:169 mgllab/mgllab.cpp:476
+msgid "Enable mouse wheel for zooming"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1463
+msgid "End"
+msgstr ""
+
+#: udav/prop_dlg.cpp:141
+msgid "English"
+msgstr ""
+
+#. TODO show dialog for color scheme
+#: udav/dat_pnl.cpp:255 udav/dat_pnl.cpp:277 mgllab/table.cpp:477
+#: mgllab/table.cpp:490
+msgid "Enter color scheme"
+msgstr ""
+
+#: udav/dat_pnl.cpp:261 udav/dat_pnl.cpp:283
+msgid "Enter data name"
+msgstr ""
+
+#: mgllab/table.cpp:523
+msgid ""
+"Enter formula for data modification\n"
+"Here x, y, z in range [0,1], u is data value"
+msgstr ""
+
+#: udav/mem_pnl.cpp:85 mgllab/help.cpp:242
+msgid "Enter name for new variable"
+msgstr ""
+
+#. this is HDF file
+#. TODO add dialog with choice of HDF names
+#: mgllab/table.cpp:436
+msgid "Enter name of data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:388 udav/dat_pnl.cpp:402 udav/dat_pnl.cpp:436
+msgid "Enter new data sizes"
+msgstr ""
+
+#: mgllab/table.cpp:28
+msgid "Enter number for addition to data values"
+msgstr ""
+
+#: mgllab/table.cpp:58
+msgid "Enter number for division of data values"
+msgstr ""
+
+#: mgllab/table.cpp:48
+msgid "Enter number for multiplication of data values"
+msgstr ""
+
+#: mgllab/table.cpp:38
+msgid "Enter number for subtraction from data values"
+msgstr ""
+
+#: widgets/qt.cpp:936
+msgid "Enter number of vertexes"
+msgstr ""
+
+#: udav/dat_pnl.cpp:351
+msgid "Enter range for data and direction of filling"
+msgstr ""
+
+#: udav/dat_pnl.cpp:366 udav/dat_pnl.cpp:377
+msgid "Enter range for final data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:424
+msgid "Enter range of saved date."
+msgstr ""
+
+#: udav/dat_pnl.cpp:485
+msgid "Enter slice id:"
+msgstr ""
+
+#: udav/dat_pnl.cpp:413
+msgid ""
+"Enter step of saved points. For example, '1' save all, '2' save each 2nd "
+"point, '3' save each 3d and so on."
+msgstr ""
+
+#: widgets/qt.cpp:945
+msgid "Enter text"
+msgstr ""
+
+#: mgllab/dialogs.cpp:860 mgllab/dialogs.cpp:866
+#, c-format
+msgid "Enter value for %s argument"
+msgstr ""
+
+#: mgllab/table.cpp:166 mgllab/table.cpp:784
+msgid "Envelop"
+msgstr ""
+
+#: src/exec_dat.cpp:1544
+msgid "Erode data larger val"
+msgstr ""
+
+#: mgllab/editor.cpp:348
+#, c-format
+msgid ""
+"Error reading from file '%s':\n"
+"%s."
+msgstr ""
+
+#: src/export.cpp:623 src/export.cpp:632 src/export.cpp:639
+#, c-format
+msgid "Error to call external viewer\n"
+msgstr ""
+
+#: mgllab/editor.cpp:359
+#, c-format
+msgid ""
+"Error writing to file '%s':\n"
+"%s."
+msgstr ""
+
+#: src/exec_dat.cpp:1545
+msgid ""
+"Evaluate (interpolate) values of array Dat at points i=idat,j=jdat,k=kdat"
+msgstr ""
+
+#. {"defpal",_("Define parameter as palette color"),"defpal $N val", 0, 6},
+#: src/parser.cpp:1430
+msgid "Execute if condition is false"
+msgstr ""
+
+#: mgllab/mgllab.cpp:472
+msgid "Execute script after loading"
+msgstr ""
+
+#: widgets/qt.cpp:1132 udav/plot_pnl.cpp:333
+msgid "Execute script and redraw graphics (F5)."
+msgstr ""
+
+#: src/parser.cpp:1424
+msgid "Execute script in external file"
+msgstr ""
+
+#: mgllab/help.cpp:146
+msgid "Existed data arrays"
+msgstr ""
+
+#: mgllab/mgllab.cpp:290
+msgid "Exit"
+msgstr ""
+
+#: udav/calc_dlg.cpp:192
+msgid "Exp and log"
+msgstr ""
+
+#: udav/calc_dlg.cpp:194
+msgid "Exp-integrals"
+msgstr ""
+
+#: mgllab/table.cpp:473
+msgid "Export Data?"
+msgstr ""
+
+#: widgets/fltk.cpp:789
+msgid "Export as ..."
+msgstr ""
+
+#: widgets/qt.cpp:1067 udav/plot_pnl.cpp:474
+msgid "Export as 2D ..."
+msgstr ""
+
+#: widgets/qt.cpp:1076 udav/plot_pnl.cpp:484
+msgid "Export as 3D ..."
+msgstr ""
+
+#: src/exec_dat.cpp:1546 mgllab/table.cpp:844
+msgid "Export data to PNG file"
+msgstr ""
+
+#. fname = new QLineEdit(this);	a->addWidget(fname);
+#: udav/anim_dlg.cpp:82
+msgid "Export to GIF"
+msgstr ""
+
+#: mgllab/table.cpp:752
+msgid "Export to PNG"
+msgstr ""
+
+#: src/exec_dat.cpp:1547
+msgid "Extend data array"
+msgstr ""
+
+#: mgllab/table.cpp:343
+msgid "Extract data"
+msgstr ""
+
+#: src/exec_dat.cpp:1604
+msgid "Extract sub-array"
+msgstr ""
+
+#: src/exec_dat.cpp:1596
+msgid "Extract sub-array between values"
+msgstr ""
+
+#: mgllab/dialogs.cpp:962
+msgid "Factor"
+msgstr ""
+
+#. file menu
+#: widgets/qt.cpp:1066 udav/udav_wnd.cpp:281 udav/dat_pnl.cpp:681
+#: mgllab/mgllab.cpp:277 mgllab/table.cpp:748
+msgid "File"
+msgstr ""
+
+#: udav/text_pnl.cpp:405 udav/text_pnl.cpp:489
+msgid "File %1 saved"
+msgstr ""
+
+#: mgllab/mgllab.cpp:227
+msgid "File is exesist. Overwrite it?"
+msgstr ""
+
+#: udav/text_pnl.cpp:583
+msgid "File name"
+msgstr ""
+
+#: mgllab/mgllab.cpp:303
+msgid "File path"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1073
+msgid "File to export"
+msgstr ""
+
+#: mgllab/editor.cpp:267 mgllab/mgllab.cpp:396
+msgid "File/Recent files"
+msgstr ""
+
+#: mgllab/table.cpp:765
+msgid "Fill"
+msgstr ""
+
+#: udav/dat_pnl.cpp:611 mgllab/table.cpp:854
+msgid "Fill data by formula"
+msgstr ""
+
+#: src/exec_dat.cpp:1553
+msgid "Fill data by global spline of Vdat"
+msgstr ""
+
+#: src/exec_dat.cpp:1588
+msgid "Fill data by interpolation of Vdat"
+msgstr ""
+
+#: src/exec_dat.cpp:1533
+msgid "Fill data by triangulated values"
+msgstr ""
+
+#: src/exec_dat.cpp:1548
+msgid "Fill data linearly in range [v1, v2]"
+msgstr ""
+
+#: mgllab/table.cpp:578 mgllab/table.cpp:592
+msgid "Fill in range"
+msgstr ""
+
+#: src/exec_dat.cpp:1549
+msgid "Fill x-,k-samples for transforms"
+msgstr ""
+
+#: udav/find_dlg.cpp:48 mgllab/editor.cpp:559
+msgid "Find"
+msgstr ""
+
+#: src/exec_dat.cpp:1529
+msgid "Find correlation between data arrays"
+msgstr ""
+
+#: src/exec_dat.cpp:1543
+msgid "Find envelop for the data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:624
+msgid "Find envelope along direction(s)"
+msgstr ""
+
+#: udav/dat_pnl.cpp:804
+msgid "Find histogram of data."
+msgstr ""
+
+#: src/exec_dat.cpp:1564
+msgid "Find maximal value over direction"
+msgstr ""
+
+#: src/exec_dat.cpp:1565
+msgid "Find minimal value over direction"
+msgstr ""
+
+#: udav/text_pnl.cpp:551 mgllab/mgllab.cpp:301
+msgid "Find next"
+msgstr ""
+
+#: mgllab/editor.cpp:515
+msgid "Find or replace text"
+msgstr ""
+
+#: src/exec_dat.cpp:1600
+msgid "Find root Dat[i,j,k]=val (inverse evaluate)"
+msgstr ""
+
+#: src/exec_dat.cpp:1592
+msgid "Find roots using data as initial values"
+msgstr ""
+
+#: src/exec_dat.cpp:1606
+msgid "Find summation over direction"
+msgstr ""
+
+#: src/exec_dat.cpp:1612
+msgid "Find triangles of randomly placed points"
+msgstr ""
+
+#: udav/find_dlg.cpp:36 mgllab/editor.cpp:558
+msgid "Find what:"
+msgstr ""
+
+#: udav/text_pnl.cpp:546 mgllab/editor.cpp:557
+msgid "Find/Replace"
+msgstr ""
+
+#: mgllab/mgllab.cpp:300
+msgid "Find|Replace"
+msgstr ""
+
+#: src/parser.cpp:1432
+msgid "Finish if/else block"
+msgstr ""
+
+#: mgllab/table.cpp:804
+msgid "First cell"
+msgstr ""
+
+#: udav/dat_pnl.cpp:721 mgllab/table.cpp:800
+msgid "First slice"
+msgstr ""
+
+#: src/exec_dat.cpp:1550 src/exec_dat.cpp:1551
+msgid "Fit data to formula"
+msgstr ""
+
+#: udav/text_pnl.cpp:567 mgllab/mgllab.cpp:307
+msgid "Fitted formula"
+msgstr ""
+
+#: udav/prop_dlg.cpp:103
+msgid "FlowKey"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1009
+msgid "Fog"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1010
+msgid "Fog dist."
+msgstr ""
+
+#: mgllab/mgllab.cpp:533
+msgid "Folder for help files"
+msgstr ""
+
+#: udav/text_pnl.cpp:587 mgllab/mgllab.cpp:304
+msgid "Folder path"
+msgstr ""
+
+#: udav/setup_dlg.cpp:105 mgllab/dialogs.cpp:1007
+msgid "Font"
+msgstr ""
+
+#: mgllab/mgllab.cpp:524
+msgid "Font file name"
+msgstr ""
+
+#: udav/prop_dlg.cpp:199
+msgid "Font files (*.vfm)"
+msgstr ""
+
+#: mgllab/mgllab.cpp:463
+msgid "Font kind"
+msgstr ""
+
+#: mgllab/mgllab.cpp:465
+msgid "Font size"
+msgstr ""
+
+#: udav/style_dlg.cpp:183
+msgid "Font style"
+msgstr ""
+
+#: udav/setup_dlg.cpp:107
+msgid "FontSize"
+msgstr ""
+
+#: src/parser.cpp:1433
+msgid "For loop"
+msgstr ""
+
+#: udav/help_pnl.cpp:52
+msgid "Forward"
+msgstr ""
+
+#: udav/plot_pnl.cpp:192
+msgid "Frame %1 of %2"
+msgstr ""
+
+#: udav/dat_pnl.cpp:351 udav/dat_pnl.cpp:366 udav/dat_pnl.cpp:377
+#: udav/dat_pnl.cpp:424 udav/dat_pnl.cpp:452 mgllab/table.cpp:608
+msgid "From"
+msgstr ""
+
+#: mgllab/mgllab.cpp:592
+msgid "Function"
+msgstr ""
+
+#. B
+#: udav/style_dlg.cpp:238 mgllab/dialogs.cpp:46
+msgid "G - green"
+msgstr ""
+
+#: src/export.cpp:306 src/export.cpp:375 src/export.cpp:388
+msgid "GIF support was disabled. Please, enable it and rebuild MathGL."
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:178 udav/setup_dlg.cpp:112 mgllab/dialogs.cpp:719
+#: mgllab/dialogs.cpp:1001
+msgid "General setup"
+msgstr ""
+
+#: src/exec_dat.cpp:1561
+msgid "Get Jacobian"
+msgstr ""
+
+#: src/exec_dat.cpp:1526
+msgid "Get data column filled by formula on column ids"
+msgstr ""
+
+#: src/exec_dat.cpp:1595
+msgid "Get formated data from file"
+msgstr ""
+
+#: src/exec_dat.cpp:1568
+msgid "Get momentum along direction"
+msgstr ""
+
+#: src/exec_dat.cpp:1577
+msgid "Get pulse properties"
+msgstr ""
+
+#: src/exec_dat.cpp:1608
+msgid "Get trace of array"
+msgstr ""
+
+#: src/base_cf.cpp:85
+#, c-format
+msgid "Global message - %s\n"
+msgstr ""
+
+#: udav/dat_pnl.cpp:723 mgllab/table.cpp:865
+msgid "Go to first slice for 3D data (Ctrl-F1)."
+msgstr ""
+
+#: udav/dat_pnl.cpp:753 mgllab/table.cpp:869
+msgid "Go to last slice for 3D data (Ctrl-F4)."
+msgstr ""
+
+#: udav/dat_pnl.cpp:740
+msgid "Go to slice"
+msgstr ""
+
+#: udav/dat_pnl.cpp:747
+msgid "Go to the next slice for 3D data."
+msgstr ""
+
+#: udav/dat_pnl.cpp:729
+msgid "Go to the previous slice for 3D data."
+msgstr ""
+
+#: udav/dat_pnl.cpp:735 udav/dat_pnl.cpp:742
+msgid "Go to the specified slice for 3D data."
+msgstr ""
+
+#: widgets/qt.cpp:1095 widgets/qt.cpp:1097 udav/plot_pnl.cpp:66
+#: mgllab/mgllab.cpp:319
+msgid "Graphics"
+msgstr ""
+
+#: udav/text_pnl.cpp:596
+msgid "Graphics setup"
+msgstr ""
+
+#: widgets/fltk.cpp:927
+msgid "Graphics/Adjust size"
+msgstr ""
+
+#. /< Parameter for handling animation
+#. /< Callback function for next frame
+#. /< Callback function for prev frame
+#. /< Callback function for delay
+#. /< Callback function for reloading
+#: widgets/fltk.cpp:921 include/mgl2/Fl_MathGL.h:150
+msgid "Graphics/Alpha"
+msgstr ""
+
+#: widgets/fltk.cpp:956
+msgid "Graphics/Animation/Next frame"
+msgstr ""
+
+#: widgets/fltk.cpp:957
+msgid "Graphics/Animation/Prev frame"
+msgstr ""
+
+#: mgllab/mgllab.cpp:371
+msgid "Graphics/Animation/Setup animation"
+msgstr ""
+
+#: widgets/fltk.cpp:955 include/mgl2/Fl_MathGL.h:152
+msgid "Graphics/Animation/Slideshow"
+msgstr ""
+
+#: widgets/fltk.cpp:931
+msgid "Graphics/Copy click coor."
+msgstr ""
+
+#: widgets/fltk.cpp:930
+msgid "Graphics/Copy graphics"
+msgstr ""
+
+#: widgets/fltk.cpp:944
+msgid "Graphics/Export/as BMP"
+msgstr ""
+
+#: widgets/fltk.cpp:942
+msgid "Graphics/Export/as GIF"
+msgstr ""
+
+#: widgets/fltk.cpp:939
+msgid "Graphics/Export/as JPEG"
+msgstr ""
+
+#: widgets/fltk.cpp:950
+msgid "Graphics/Export/as OBJ"
+msgstr ""
+
+#: widgets/fltk.cpp:951
+msgid "Graphics/Export/as OFF"
+msgstr ""
+
+#: widgets/fltk.cpp:935
+msgid "Graphics/Export/as PNG"
+msgstr ""
+
+#: widgets/fltk.cpp:949
+msgid "Graphics/Export/as PRC"
+msgstr ""
+
+#: widgets/fltk.cpp:952
+msgid "Graphics/Export/as STL"
+msgstr ""
+
+#: widgets/fltk.cpp:945
+msgid "Graphics/Export/as SVG"
+msgstr ""
+
+#: widgets/fltk.cpp:948
+msgid "Graphics/Export/as TeX"
+msgstr ""
+
+#: widgets/fltk.cpp:953
+msgid "Graphics/Export/as XYZ"
+msgstr ""
+
+#: widgets/fltk.cpp:947
+msgid "Graphics/Export/as bitmap EPS"
+msgstr ""
+
+#: widgets/fltk.cpp:936
+msgid "Graphics/Export/as solid PNG"
+msgstr ""
+
+#: widgets/fltk.cpp:946
+msgid "Graphics/Export/as vector EPS"
+msgstr ""
+
+#: widgets/fltk.cpp:923 include/mgl2/Fl_MathGL.h:153
+msgid "Graphics/Grid"
+msgstr ""
+
+#: widgets/fltk.cpp:922 include/mgl2/Fl_MathGL.h:151
+msgid "Graphics/Light"
+msgstr ""
+
+#: widgets/fltk.cpp:932 include/mgl2/Fl_MathGL.h:159 mgllab/mgllab.cpp:372
+msgid "Graphics/Pause calc"
+msgstr ""
+
+#: mgllab/mgllab.cpp:370
+msgid "Graphics/Primitive"
+msgstr ""
+
+#: widgets/fltk.cpp:926
+msgid "Graphics/Redraw"
+msgstr ""
+
+#: widgets/fltk.cpp:928
+msgid "Graphics/Reload data"
+msgstr ""
+
+#: widgets/fltk.cpp:925
+msgid "Graphics/Restore"
+msgstr ""
+
+#: widgets/fltk.cpp:929
+msgid "Graphics/Stop"
+msgstr ""
+
+#: widgets/fltk.cpp:963
+msgid "Graphics/Transform/Move down"
+msgstr ""
+
+#: widgets/fltk.cpp:959
+msgid "Graphics/Transform/Move left"
+msgstr ""
+
+#: widgets/fltk.cpp:964
+msgid "Graphics/Transform/Move right"
+msgstr ""
+
+#: widgets/fltk.cpp:960
+msgid "Graphics/Transform/Move up"
+msgstr ""
+
+#: widgets/fltk.cpp:961
+msgid "Graphics/Transform/Zoom in"
+msgstr ""
+
+#: widgets/fltk.cpp:962
+msgid "Graphics/Transform/Zoom out"
+msgstr ""
+
+#: udav/plot_pnl.cpp:304
+msgid "Grid"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:50 mgllab/dialogs.cpp:705
+msgid "Groups of MGL commands"
+msgstr ""
+
+#. P
+#: udav/style_dlg.cpp:249 mgllab/dialogs.cpp:57
+msgid "H - darkgray"
+msgstr ""
+
+#: src/data_io.cpp:1085
+msgid "HDF4 support was disabled. Please, enable it and rebuild MathGL."
+msgstr ""
+
+#: src/complex_io.cpp:922 src/complex_io.cpp:924 src/data_io.cpp:1184
+#: src/data_io.cpp:1186 src/data_io.cpp:1188 src/data_io.cpp:1190
+msgid "HDF5 support was disabled. Please, enable it and rebuild MathGL."
+msgstr ""
+
+#: mgllab/table.cpp:165 mgllab/table.cpp:779
+msgid "Hankel"
+msgstr ""
+
+#: udav/dat_pnl.cpp:622
+msgid "Hankel transform along direction(s)"
+msgstr ""
+
+#: src/exec_dat.cpp:1554
+msgid "Hankel transform at some direction"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:84
+msgid "Height of selected cells"
+msgstr ""
+
+#: widgets/qt.cpp:1276 udav/help_pnl.cpp:57 udav/udav_wnd.cpp:231
+#: udav/udav_wnd.cpp:323 mgllab/mgllab.cpp:329 mgllab/mgllab.cpp:330
+#: mgllab/mgllab.cpp:358
+msgid "Help"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:73
+msgid ""
+"Here you can specify command options.\n"
+"Options are used for additional plot tunning."
+msgstr ""
+
+#: udav/udav_wnd.cpp:186 mgllab/mgllab.cpp:298
+msgid "Hidden plots"
+msgstr ""
+
+#: udav/plot_pnl.cpp:431
+msgid "Hide selected"
+msgstr ""
+
+#: udav/plot_pnl.cpp:433
+msgid "Hide selected plots."
+msgstr ""
+
+#: udav/prop_dlg.cpp:173 mgllab/mgllab.cpp:475
+msgid "Highlight current object(s)"
+msgstr ""
+
+#: udav/udav_wnd.cpp:328 mgllab/mgllab.cpp:331
+msgid "Hints"
+msgstr ""
+
+#: udav/dat_pnl.cpp:802
+msgid "Histogram (Ctrl+Shift+H)"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:51 udav/subplot_dlg.cpp:68 udav/subplot_dlg.cpp:93
+msgid "Horizontal size"
+msgstr ""
+
+#: udav/calc_dlg.cpp:192
+msgid "Hyperbolic"
+msgstr ""
+
+#: udav/setup_dlg.cpp:116
+msgid "ID"
+msgstr ""
+
+#: mgllab/mgllab.cpp:333
+msgid "Icon list"
+msgstr ""
+
+#: mgllab/table.cpp:867
+msgid "Id of slice on third (z-) dimension"
+msgstr ""
+
+#: udav/prop_dlg.cpp:154
+msgid "Image size"
+msgstr ""
+
+#: src/exec_dat.cpp:1576
+msgid "Immediately print the message"
+msgstr ""
+
+#: mgllab/table.cpp:485
+msgid "Import Data?"
+msgstr ""
+
+#: src/exec_dat.cpp:1557 mgllab/table.cpp:840
+msgid "Import data from PNG file"
+msgstr ""
+
+#: mgllab/table.cpp:750
+msgid "Import from PNG"
+msgstr ""
+
+#: mgllab/table.cpp:767
+msgid "In range"
+msgstr ""
+
+#: src/exec_dat.cpp:1552
+msgid "In-place Fourier transform"
+msgstr ""
+
+#: mgllab/mathgl.cpp:245
+msgid "Incompatible loop parameters!"
+msgstr ""
+
+#: mgllab/table.cpp:503
+msgid "Incorrect type of base data"
+msgstr ""
+
+#: udav/plot_pnl.cpp:552
+msgid "Increase \\phi angle by 10 degrees."
+msgstr ""
+
+#: udav/plot_pnl.cpp:544
+msgid "Increase \\theta angle by 10 degrees."
+msgstr ""
+
+#: mgllab/help.cpp:103
+msgid "Increase font size"
+msgstr ""
+
+#: udav/udav_wnd.cpp:229
+msgid "Info"
+msgstr ""
+
+#: udav/info_dlg.cpp:55 mgllab/help.cpp:353
+msgid "Information"
+msgstr ""
+
+#: mgllab/mgllab.cpp:306
+msgid "Inplot"
+msgstr ""
+
+#. insert menu
+#: udav/text_pnl.cpp:557 mgllab/mgllab.cpp:302
+msgid "Insert"
+msgstr ""
+
+#: mgllab/editor.cpp:518
+msgid "Insert MGL command"
+msgstr ""
+
+#: mgllab/table.cpp:753
+msgid "Insert as 'list'"
+msgstr ""
+
+#: mgllab/editor.cpp:486
+msgid "Insert file content?"
+msgstr ""
+
+#: mgllab/mgllab.cpp:148
+msgid "Insert file name?"
+msgstr ""
+
+#: mgllab/editor.cpp:520
+msgid "Insert filename"
+msgstr ""
+
+#: mgllab/editor.cpp:522
+msgid "Insert inplot command"
+msgstr ""
+
+#: udav/text_pnl.cpp:569
+msgid "Insert last fitted formula with found coefficients."
+msgstr ""
+
+#: src/exec_dat.cpp:1559
+msgid "Insert slice of data"
+msgstr ""
+
+#: mgllab/table.cpp:847
+msgid "Insert to script as 'list' command"
+msgstr ""
+
+#: mgllab/table.cpp:163 mgllab/table.cpp:773
+msgid "Integrate"
+msgstr ""
+
+#: src/exec_dat.cpp:1560 udav/dat_pnl.cpp:615
+msgid "Integrate data along direction(s)"
+msgstr ""
+
+#: mgllab/dialogs.cpp:114
+msgid "Intensity of diffuse light"
+msgstr ""
+
+#: udav/style_dlg.cpp:158 mgllab/dialogs.cpp:369
+msgid "Italic style"
+msgstr ""
+
+#: widgets/qt.cpp:1070 udav/plot_pnl.cpp:477
+msgid "JPEG"
+msgstr ""
+
+#: src/data_png.cpp:162 src/export.cpp:192
+msgid "JPEG support was disabled. Please, enable it and rebuild MathGL."
+msgstr ""
+
+#: udav/calc_dlg.cpp:193
+msgid "Jacobi"
+msgstr ""
+
+#: src/exec_dat.cpp:1562
+msgid "Join data arrays"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1075
+msgid "Keep empty to put at beginning of main script."
+msgstr ""
+
+#: udav/dat_pnl.cpp:780
+msgid "Keep only each n-th element of the data array."
+msgstr ""
+
+#: mgllab/mathgl.cpp:198
+msgid "Keep slides in memory (faster animation but require more memory)"
+msgstr ""
+
+#: udav/prop_dlg.cpp:88
+msgid "Keywords"
+msgstr ""
+
+#: mgllab/dialogs.cpp:354 mgllab/dialogs.cpp:704 mgllab/dialogs.cpp:1457
+msgid "Kind"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:58
+msgid ""
+"Kind of command argument order. The notation is:\n"
+" * Capital arguments are data (like, Ydat);\n"
+" * Argument in '' are strings (like, 'fmt');\n"
+" * Other arguments are numbers (like, zval);\n"
+" * Arguments in [] are optional arguments."
+msgstr ""
+
+#: udav/info_dlg.cpp:50
+msgid "Kind of plots: lines for 1D, density for 2D."
+msgstr ""
+
+#. Y
+#: udav/style_dlg.cpp:243 mgllab/dialogs.cpp:51
+msgid "L - seagreen"
+msgstr ""
+
+#: widgets/qt.cpp:1074 udav/plot_pnl.cpp:481
+msgid "LaTeX"
+msgstr ""
+
+#: udav/setup_dlg.cpp:66 mgllab/dialogs.cpp:954
+msgid "Label"
+msgstr ""
+
+#: udav/prop_dlg.cpp:139
+msgid "Language for UDAV"
+msgstr ""
+
+#: mgllab/mgllab.cpp:478
+msgid "Language for mgllab"
+msgstr ""
+
+#: udav/dat_pnl.cpp:617
+msgid "Laplace transform along direction(s)"
+msgstr ""
+
+#: mgllab/table.cpp:775
+msgid "Laplacian"
+msgstr ""
+
+#: udav/dat_pnl.cpp:751 mgllab/table.cpp:803
+msgid "Last slice"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:144
+msgid "Left bottom edge"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:152
+msgid "Left top edge"
+msgstr ""
+
+#: udav/opt_dlg.cpp:74 mgllab/dialogs.cpp:118
+msgid "Legend"
+msgstr ""
+
+#: widgets/qt.cpp:1104 udav/opt_dlg.cpp:64 udav/setup_dlg.cpp:110
+#: udav/plot_pnl.cpp:297 mgllab/dialogs.cpp:115
+msgid "Light"
+msgstr ""
+
+#: udav/setup_dlg.cpp:190
+msgid "Light position should be filled. Ignore it."
+msgstr ""
+
+#: udav/setup_dlg.cpp:136 mgllab/dialogs.cpp:1053
+msgid "Light settings"
+msgstr ""
+
+#: src/exec_dat.cpp:1563
+msgid "Limit data to be inside [-v,v]"
+msgstr ""
+
+#: udav/style_dlg.cpp:99 mgllab/dialogs.cpp:314
+msgid "Line style"
+msgstr ""
+
+#: udav/style_dlg.cpp:78
+msgid "Line width"
+msgstr ""
+
+#: mgllab/table.cpp:167
+msgid "Linear *3"
+msgstr ""
+
+#: mgllab/table.cpp:167
+msgid "Linear *5"
+msgstr ""
+
+#: mgllab/help.cpp:156
+msgid "List of available data."
+msgstr ""
+
+#: mgllab/table.cpp:427
+msgid "Load Data?"
+msgstr ""
+
+#: src/exec_set.cpp:719
+msgid "Load commands from external DLL"
+msgstr ""
+
+#: udav/dat_pnl.cpp:682
+msgid "Load data"
+msgstr ""
+
+#: mgllab/table.cpp:838
+msgid "Load data from file"
+msgstr ""
+
+#: udav/dat_pnl.cpp:684
+msgid ""
+"Load data from file. Data will be deleted only\n"
+"at exit but UDAV will not ask to save it (Ctrl+Shift+O)."
+msgstr ""
+
+#: src/exec_set.cpp:720
+msgid "Load fontfaces"
+msgstr ""
+
+#: mgllab/table.cpp:749
+msgid "Load from file"
+msgstr ""
+
+#: src/exec_prm.cpp:580
+msgid "Load image for background"
+msgstr ""
+
+#: udav/prop_dlg.cpp:163
+msgid "Load script to new window"
+msgstr ""
+
+#: udav/text_pnl.cpp:467
+msgid "Loaded document "
+msgstr ""
+
+#: udav/text_pnl.cpp:325
+msgid "Loaded document %1"
+msgstr ""
+
+#: udav/udav_wnd.cpp:638
+msgid "Loading aborted"
+msgstr ""
+
+#: mgllab/dialogs.cpp:98
+msgid "Low border for determining color or alpha"
+msgstr ""
+
+#. C
+#: udav/style_dlg.cpp:241 mgllab/dialogs.cpp:49
+msgid "M - purple"
+msgstr ""
+
+#: src/parser.cpp:1018
+msgid "MGL Parser"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:53 mgllab/dialogs.cpp:725
+msgid "MGL commands for selected group"
+msgstr ""
+
+#: mgllab/mgllab.cpp:214
+msgid "MGL files \t*.mgl"
+msgstr ""
+
+#: mgllab/mgllab.cpp:173
+msgid ""
+"MGL files \t*.mgl\n"
+"DAT files \t*.{dat,csv}"
+msgstr ""
+
+#: udav/open_dlg.cpp:102
+msgid "MGL files (*.mgl)"
+msgstr ""
+
+#: udav/udav_wnd.cpp:324
+msgid "MGL help"
+msgstr ""
+
+#: mgllab/mathgl.cpp:421
+msgid "MGL messages"
+msgstr ""
+
+#: mgllab/help.cpp:101
+msgid "MGL samples and hints"
+msgstr ""
+
+#: udav/udav_wnd.cpp:670
+msgid ""
+"MGL scripts (*.mgl)\n"
+"HDF5 files (*.hdf *.h5)\n"
+"All files (*.*)"
+msgstr ""
+
+#: udav/udav_wnd.cpp:635
+msgid ""
+"MGL scripts (*.mgl)\n"
+"HDF5 files (*.hdf *.h5)\n"
+"Text files (*.txt)\n"
+"Data files (*.dat)\n"
+"All files (*.*)"
+msgstr ""
+
+#: widgets/qt.cpp:1077 udav/plot_pnl.cpp:485
+msgid "MGLD"
+msgstr ""
+
+#: udav/dat_pnl.cpp:798
+msgid "Make another data."
+msgstr ""
+
+#: udav/dat_pnl.cpp:796
+msgid "Make new (Ctrl+Shift+M)"
+msgstr ""
+
+#: udav/style_dlg.cpp:83 mgllab/dialogs.cpp:336
+msgid "Manual dashing"
+msgstr ""
+
+#: udav/style_dlg.cpp:196
+msgid "Manual mask"
+msgstr ""
+
+#: udav/text_pnl.cpp:591 mgllab/mgllab.cpp:308
+msgid "Manual primitives"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1467
+msgid "Mark"
+msgstr ""
+
+#: udav/style_dlg.cpp:76 mgllab/dialogs.cpp:324
+msgid "Marks"
+msgstr ""
+
+#: mgllab/dialogs.cpp:352
+msgid "Mask"
+msgstr ""
+
+#: udav/style_dlg.cpp:124
+msgid "Mask for bitmap coloring"
+msgstr ""
+
+#: udav/style_dlg.cpp:125
+msgid "Mask rotation angle"
+msgstr ""
+
+#: udav/style_dlg.cpp:126
+msgid "Mask size"
+msgstr ""
+
+#: udav/find_dlg.cpp:42 mgllab/editor.cpp:562
+msgid "Match case"
+msgstr ""
+
+#: widgets/qt.cpp:860
+msgid "MathGL - about"
+msgstr ""
+
+#: src/base.cpp:250
+#, c-format
+msgid "MathGL message - %s\n"
+msgstr ""
+
+#: widgets/qt.cpp:859
+msgid "MathGL v. 2."
+msgstr ""
+
+#: udav/open_dlg.cpp:70
+msgid "Matrix with sizes from file"
+msgstr ""
+
+#: udav/dat_pnl.cpp:541
+msgid "Max along direction(s)"
+msgstr ""
+
+#: udav/setup_dlg.cpp:57 mgllab/dialogs.cpp:952
+msgid "Maximal"
+msgstr ""
+
+#: mgllab/table.cpp:546
+msgid "Maximal value (v2)"
+msgstr ""
+
+#: mgllab/table.cpp:548
+msgid "Maximal value for resulting data values"
+msgstr ""
+
+#: mgllab/dialogs.cpp:88
+msgid "Maximal value of X for cutting or for coordinate filling"
+msgstr ""
+
+#: mgllab/dialogs.cpp:92
+msgid "Maximal value of Y for cutting or for coordinate filling"
+msgstr ""
+
+#: mgllab/dialogs.cpp:96
+msgid "Maximal value of Z for cutting or for coordinate filling"
+msgstr ""
+
+#: src/data.cpp:1417
+#, c-format
+msgid "Maximum is %g\t at x = %ld\ty = %ld\tz = %ld\n"
+msgstr ""
+
+#: mgllab/table.cpp:342 mgllab/table.cpp:789
+msgid "Maximum of"
+msgstr ""
+
+#: udav/mem_pnl.cpp:68 udav/mem_pnl.cpp:73 mgllab/mgllab.cpp:360
+msgid "Memory"
+msgstr ""
+
+#: udav/opt_dlg.cpp:53
+msgid "Mesh num"
+msgstr ""
+
+#: udav/setup_dlg.cpp:99 mgllab/dialogs.cpp:102
+msgid "MeshNum"
+msgstr ""
+
+#: mgllab/mgllab.cpp:327
+msgid "Messages"
+msgstr ""
+
+#: udav/udav_wnd.cpp:178
+msgid "Messages and warnings"
+msgstr ""
+
+#: udav/dat_pnl.cpp:540
+msgid "Min along direction(s)"
+msgstr ""
+
+#: udav/setup_dlg.cpp:52 mgllab/dialogs.cpp:951
+msgid "Minimal"
+msgstr ""
+
+#: mgllab/table.cpp:543
+msgid "Minimal value (v1)"
+msgstr ""
+
+#: mgllab/table.cpp:545
+msgid "Minimal value for resulting data values"
+msgstr ""
+
+#: mgllab/dialogs.cpp:86
+msgid "Minimal value of X for cutting or for coordinate filling"
+msgstr ""
+
+#: mgllab/dialogs.cpp:90
+msgid "Minimal value of Y for cutting or for coordinate filling"
+msgstr ""
+
+#: mgllab/dialogs.cpp:94
+msgid "Minimal value of Z for cutting or for coordinate filling"
+msgstr ""
+
+#: src/data.cpp:1420
+#, c-format
+msgid "Minimum is %g\t at x = %ld\ty = %ld\tz = %ld\n"
+msgstr ""
+
+#: mgllab/table.cpp:342 mgllab/table.cpp:790
+msgid "Minimum of"
+msgstr ""
+
+#. { _("Wavelet"),	0, wavelet_cb },
+#: mgllab/table.cpp:166 mgllab/table.cpp:781
+msgid "Mirror"
+msgstr ""
+
+#: udav/dat_pnl.cpp:619
+msgid "Mirror data along direction(s)"
+msgstr ""
+
+#: src/exec_dat.cpp:1566
+msgid "Mirror data at some direction"
+msgstr ""
+
+#: src/exec_dat.cpp:1567
+msgid "Modify data values by formula"
+msgstr ""
+
+#: udav/dat_pnl.cpp:542
+msgid "Momentum along 'x' for function"
+msgstr ""
+
+#: udav/dat_pnl.cpp:543
+msgid "Momentum along 'y' for function"
+msgstr ""
+
+#: udav/dat_pnl.cpp:544
+msgid "Momentum along 'z' for function"
+msgstr ""
+
+#: widgets/qt.cpp:1233 udav/plot_pnl.cpp:527
+msgid "Move down"
+msgstr ""
+
+#: widgets/qt.cpp:1219 udav/plot_pnl.cpp:506
+msgid "Move graphics left by 1/3 of its width."
+msgstr ""
+
+#: widgets/qt.cpp:1239 udav/plot_pnl.cpp:536
+msgid "Move graphics right by 1/3 of its width."
+msgstr ""
+
+#: widgets/qt.cpp:1223 udav/plot_pnl.cpp:512
+msgid "Move graphics up by 1/3 of its height."
+msgstr ""
+
+#: widgets/qt.cpp:1235 udav/plot_pnl.cpp:530
+msgid "Move graphics up down 1/3 of its height."
+msgstr ""
+
+#: widgets/qt.cpp:1217 udav/plot_pnl.cpp:503
+msgid "Move left"
+msgstr ""
+
+#: udav/text_pnl.cpp:593
+msgid "Move mouse-handled primitives to script."
+msgstr ""
+
+#: udav/plot_pnl.cpp:454
+msgid "Move plot down"
+msgstr ""
+
+#: udav/plot_pnl.cpp:449
+msgid "Move plot up"
+msgstr ""
+
+#: widgets/qt.cpp:1237 udav/plot_pnl.cpp:533
+msgid "Move right"
+msgstr ""
+
+#: udav/plot_pnl.cpp:456
+msgid "Move selected plot down to next subplot."
+msgstr ""
+
+#: udav/plot_pnl.cpp:451
+msgid "Move selected plot up to previous subplot."
+msgstr ""
+
+#: widgets/qt.cpp:1221 udav/plot_pnl.cpp:509
+msgid "Move up"
+msgstr ""
+
+#: mgllab/table.cpp:796
+msgid "Multiply by"
+msgstr ""
+
+#: src/exec_dat.cpp:1569
+msgid "Multiply by data or number"
+msgstr ""
+
+#. E
+#: udav/style_dlg.cpp:245 mgllab/dialogs.cpp:53
+msgid "N - darkskyblue"
+msgstr ""
+
+#: udav/dat_pnl.cpp:500
+msgid "NOTE: All fields must be filled!"
+msgstr ""
+
+#: udav/mem_pnl.cpp:68
+msgid "Name"
+msgstr ""
+
+#: mgllab/table.cpp:349
+msgid "Name for output"
+msgstr ""
+
+#. navigation menu
+#: udav/dat_pnl.cpp:720 mgllab/table.cpp:799
+msgid "Navigation"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:101 udav/newcmd_dlg.cpp:310 udav/newcmd_dlg.cpp:338
+#: udav/newcmd_dlg.cpp:342 udav/newcmd_dlg.cpp:356 udav/newcmd_dlg.cpp:369
+#: udav/newcmd_dlg.cpp:377 udav/newcmd_dlg.cpp:381 udav/newcmd_dlg.cpp:385
+#: udav/text_pnl.cpp:558 udav/plot_pnl.cpp:439 mgllab/dialogs.cpp:702
+msgid "New command"
+msgstr ""
+
+#: udav/hint_dlg.cpp:40 mgllab/help.cpp:274
+msgid ""
+"New drawing never clears things drawn already. For example, you can make a "
+"surface with contour lines by calling commands 'surf' and 'cont' one after "
+"another (in any order). "
+msgstr ""
+
+#: udav/text_pnl.cpp:562 udav/plot_pnl.cpp:444
+msgid "New inplot"
+msgstr ""
+
+#: mgllab/table.cpp:671
+msgid "New order of dimensions"
+msgstr ""
+
+#: udav/udav_wnd.cpp:282 mgllab/mgllab.cpp:278
+msgid "New script"
+msgstr ""
+
+#: mgllab/table.cpp:95
+msgid "New size of data on 1st dimension (x-direction)"
+msgstr ""
+
+#: mgllab/table.cpp:97
+msgid "New size of data on 2nd dimension (y-direction)"
+msgstr ""
+
+#: mgllab/table.cpp:99
+msgid "New size of data on 3d dimension (z-direction)"
+msgstr ""
+
+#: udav/hint_dlg.cpp:68
+msgid "Next"
+msgstr ""
+
+#: mgllab/help.cpp:306
+msgid "Next @->"
+msgstr ""
+
+#: udav/dat_pnl.cpp:745 mgllab/table.cpp:802
+msgid "Next slice"
+msgstr ""
+
+#: widgets/qt.cpp:1247 udav/plot_pnl.cpp:560
+msgid "Next slide"
+msgstr ""
+
+#: mgllab/help.cpp:135 mgllab/mgllab.cpp:227
+msgid "No"
+msgstr ""
+
+#: udav/dat_pnl.cpp:567 udav/dat_pnl.cpp:644
+msgid "No action is selected. Do nothing."
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:310
+msgid "No argument is selected"
+msgstr ""
+
+#: udav/dat_pnl.cpp:573
+msgid "No direction/formula is entered. Do nothing."
+msgstr ""
+
+#: widgets/qt.cpp:680 widgets/qt.cpp:692 widgets/qt.cpp:704 widgets/qt.cpp:716
+#: widgets/qt.cpp:728 widgets/qt.cpp:736 widgets/qt.cpp:744 widgets/qt.cpp:752
+#: widgets/qt.cpp:760 widgets/qt.cpp:768 widgets/qt.cpp:776 widgets/qt.cpp:784
+#: widgets/qt.cpp:800 widgets/qt.cpp:808 widgets/qt.cpp:816
+msgid "No filename."
+msgstr ""
+
+#: mgllab/editor.cpp:584 mgllab/editor.cpp:606 mgllab/editor.cpp:631
+#, c-format
+msgid "No occurrences of '%s' found!"
+msgstr ""
+
+#: mgllab/mathgl.cpp:260
+msgid "No selection. So nothing to do"
+msgstr ""
+
+#: udav/text_pnl.cpp:202
+msgid "No string occurrence is found"
+msgstr ""
+
+#: udav/setup_dlg.cpp:111
+msgid "No text rotation"
+msgstr ""
+
+#: widgets/fltk.cpp:812
+msgid "Normal view"
+msgstr ""
+
+#: mgllab/table.cpp:768
+msgid "Normalize"
+msgstr ""
+
+#: src/exec_dat.cpp:1571
+msgid "Normalize data"
+msgstr ""
+
+#: src/exec_dat.cpp:1572
+msgid "Normalize data slice by slice"
+msgstr ""
+
+#: mgllab/table.cpp:553
+msgid "Normalize in symmetrical range: -max(|v1|,|v2|) ... max(|v1|,|v2|)"
+msgstr ""
+
+#: udav/udav_wnd.cpp:444
+msgid "Not recognized"
+msgstr ""
+
+#: udav/dat_pnl.cpp:456
+msgid "Number of points"
+msgstr ""
+
+#: udav/prop_dlg.cpp:97
+msgid "Numbers"
+msgstr ""
+
+#: mgllab/table.cpp:176
+msgid "Numeric parameter"
+msgstr ""
+
+#: udav/text_pnl.cpp:579
+msgid "Numeric value"
+msgstr ""
+
+#: src/exec_dat.cpp:1537
+msgid "Numerically differentiate data"
+msgstr ""
+
+#: src/exec_dat.cpp:1538
+msgid "Numerically double differentiate data"
+msgstr ""
+
+#: udav/open_dlg.cpp:64
+msgid "Nx"
+msgstr ""
+
+#: udav/open_dlg.cpp:66
+msgid "Ny"
+msgstr ""
+
+#: udav/open_dlg.cpp:68
+msgid "Nz"
+msgstr ""
+
+#: widgets/qt.cpp:1079 udav/plot_pnl.cpp:487
+msgid "OBJ"
+msgstr ""
+
+#: udav/anim_dlg.cpp:69 udav/prop_dlg.cpp:182 udav/args_dlg.cpp:65
+#: udav/newcmd_dlg.cpp:80 udav/open_dlg.cpp:92 udav/dat_pnl.cpp:462
+#: udav/dat_pnl.cpp:512 udav/dat_pnl.cpp:554 udav/dat_pnl.cpp:631
+#: udav/opt_dlg.cpp:80 udav/files_dlg.cpp:60 udav/style_dlg.cpp:208
+#: udav/data_dlg.cpp:92 udav/subplot_dlg.cpp:221 mgllab/mathgl.cpp:196
+#: mgllab/dialogs.cpp:121 mgllab/dialogs.cpp:165 mgllab/dialogs.cpp:411
+#: mgllab/dialogs.cpp:585 mgllab/dialogs.cpp:750 mgllab/dialogs.cpp:1072
+#: mgllab/dialogs.cpp:1319 mgllab/dialogs.cpp:1474 mgllab/mgllab.cpp:483
+#: mgllab/table.cpp:621
+msgid "OK"
+msgstr ""
+
+#: mgllab/table.cpp:504
+msgid "Only current slice will be inserted"
+msgstr ""
+
+#: mgllab/mgllab.cpp:172
+msgid "Open File?"
+msgstr ""
+
+#: src/exec_dat.cpp:1574
+msgid "Open all data arrays from HDF file"
+msgstr ""
+
+#: udav/udav_wnd.cpp:198
+msgid ""
+"Open and execute/show script or data from file (Ctrl+O).\n"
+"You may switch off automatic exection in UDAV properties."
+msgstr ""
+
+#: mgllab/help.cpp:169
+msgid "Open dialog for new data creation."
+msgstr ""
+
+#: udav/udav_wnd.cpp:196
+msgid "Open file"
+msgstr ""
+
+#: mgllab/mgllab.cpp:279
+msgid "Open file ..."
+msgstr ""
+
+#: widgets/qt.cpp:1088 udav/udav_wnd.cpp:298
+msgid "Open printer dialog and print graphics (Ctrl+P)"
+msgstr ""
+
+#: mgllab/editor.cpp:506
+msgid "Open script or data file"
+msgstr ""
+
+#: mgllab/help.cpp:160
+msgid "Open table with selected data for editing."
+msgstr ""
+
+#: udav/data_dlg.cpp:65 mgllab/dialogs.cpp:578
+msgid "Operation"
+msgstr ""
+
+#: mgllab/table.cpp:231
+msgid "Operation is not supported for this type of data."
+msgstr ""
+
+#: mgllab/table.cpp:793
+msgid "Operations"
+msgstr ""
+
+#: udav/prop_dlg.cpp:91 udav/newcmd_dlg.cpp:72 mgllab/dialogs.cpp:746
+#: mgllab/mgllab.cpp:310
+msgid "Options"
+msgstr ""
+
+#: udav/setup_dlg.cpp:62 mgllab/dialogs.cpp:953
+msgid "Origin"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:171 mgllab/dialogs.cpp:712
+msgid "Other plots"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1025
+msgid "Others"
+msgstr ""
+
+#: udav/style_dlg.cpp:161 mgllab/dialogs.cpp:372
+msgid "Overline"
+msgstr ""
+
+#: mgllab/dialogs.cpp:112
+msgid "Own brightness of the surface"
+msgstr ""
+
+#. Q
+#: udav/style_dlg.cpp:248 mgllab/dialogs.cpp:56
+msgid "P - darkpink"
+msgstr ""
+
+#: src/prc.cpp:981
+msgid "PDF support was disabled. Please, enable it and rebuild MathGL."
+msgstr ""
+
+#: widgets/qt.cpp:1068 udav/plot_pnl.cpp:475
+msgid "PNG"
+msgstr ""
+
+#: mgllab/table.cpp:474 mgllab/table.cpp:486
+msgid "PNG Files \t*.png"
+msgstr ""
+
+#: src/canvas_cf.cpp:502 src/canvas_cf.cpp:504 src/data_png.cpp:122
+#: src/export.cpp:75 src/export.cpp:109
+msgid "PNG support was disabled. Please, enable it and rebuild MathGL."
+msgstr ""
+
+#: widgets/qt.cpp:1078 udav/plot_pnl.cpp:486
+msgid "PRC"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1006
+msgid "Palette"
+msgstr ""
+
+#: mgllab/table.cpp:167
+msgid "Parabolic *5"
+msgstr ""
+
+#: udav/dat_pnl.cpp:713
+msgid "Paste data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:715
+msgid "Paste range of numbers from clipboard (Ctrl+Shift+P)."
+msgstr ""
+
+#: udav/text_pnl.cpp:538 mgllab/mgllab.cpp:296
+msgid "Paste text"
+msgstr ""
+
+#: mgllab/editor.cpp:513
+msgid "Paste text from clipboard"
+msgstr ""
+
+#: udav/text_pnl.cpp:540
+msgid "Paste text or data from clipboard (Ctrl+V)."
+msgstr ""
+
+#: mgllab/mgllab.cpp:469
+msgid "Path for MathGL font (without extension)"
+msgstr ""
+
+#: udav/prop_dlg.cpp:110 mgllab/mgllab.cpp:466
+msgid "Path for help files"
+msgstr ""
+
+#: udav/prop_dlg.cpp:130
+msgid "Path for user MathGL font files"
+msgstr ""
+
+#: widgets/qt.cpp:1265
+msgid "Pause calculation"
+msgstr ""
+
+#. Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(setPause()));
+#: widgets/fltk.cpp:891 widgets/qt.cpp:1270
+msgid "Pause on/off external calculations"
+msgstr ""
+
+#: src/exec_dat.cpp:1590
+msgid "Perform Runge-Kutta step"
+msgstr ""
+
+#: widgets/fltk.cpp:864
+msgid "Phi angle (rotate in x*y plane)"
+msgstr ""
+
+#: udav/prop_dlg.cpp:161
+msgid "Place editor at top"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1050
+msgid "Plot ID"
+msgstr ""
+
+#: src/exec_prm.cpp:596
+msgid "Plot curve by formula"
+msgstr ""
+
+#. o->addSeparator();	bb->addSeparator();
+#. a = new QAction(QPixmap(insert_xpm), _("Insert as list"), this);
+#. connect(a, SIGNAL(triggered()), this, SLOT(list()));
+#. o->addAction(a);
+#. bb = new QToolButton(this);	l->addWidget(bb);	bb->setDefaultAction(a);
+#: udav/dat_pnl.cpp:701
+msgid "Plot data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:703
+msgid ""
+"Plot data in new script window. You may select the kind\n"
+"of plot, its style and so on."
+msgstr ""
+
+#: mgllab/mgllab.cpp:325
+msgid "Plot setup"
+msgstr ""
+
+#: udav/text_pnl.cpp:571 mgllab/dialogs.cpp:312 mgllab/mgllab.cpp:309
+msgid "Plot style"
+msgstr ""
+
+#: src/exec_prm.cpp:597
+msgid "Plot surface by formula"
+msgstr ""
+
+#: mgllab/dialogs.cpp:386
+msgid "Popular color schemes"
+msgstr ""
+
+#: udav/hint_dlg.cpp:66
+msgid "Prev"
+msgstr ""
+
+#: udav/dat_pnl.cpp:727 mgllab/table.cpp:801
+msgid "Prev slice"
+msgstr ""
+
+#: widgets/qt.cpp:1256 udav/plot_pnl.cpp:575
+msgid "Prev slide"
+msgstr ""
+
+#: udav/info_dlg.cpp:51
+msgid "Preview"
+msgstr ""
+
+#: mgllab/mgllab.cpp:566
+msgid "Previous expressions"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:181 mgllab/dialogs.cpp:722
+msgid "Primitives"
+msgstr ""
+
+#: widgets/qt.cpp:1150 udav/plot_pnl.cpp:365
+msgid "Primitives ..."
+msgstr ""
+
+#: src/exec_set.cpp:750
+msgid "Print MathGL version or check if it is valid"
+msgstr ""
+
+#: src/exec_dat.cpp:1542
+msgid "Print content of the data"
+msgstr ""
+
+#: src/exec_dat.cpp:1579
+msgid "Print fitted formula"
+msgstr ""
+
+#: widgets/qt.cpp:1086 udav/udav_wnd.cpp:296
+msgid "Print graphics"
+msgstr ""
+
+#: src/exec_dat.cpp:1534
+msgid "Print list of data names in HDF file"
+msgstr ""
+
+#: src/exec_dat.cpp:1558
+msgid "Print message or information about the data"
+msgstr ""
+
+#: mgllab/mgllab.cpp:282
+msgid "Print plot"
+msgstr ""
+
+#: udav/udav_wnd.cpp:295
+msgid "Print script"
+msgstr ""
+
+#: src/exec_prm.cpp:594
+msgid "Print string from file"
+msgstr ""
+
+#: udav/text_pnl.cpp:178
+msgid "Printing aborted"
+msgstr ""
+
+#: udav/text_pnl.cpp:176
+msgid "Printing completed"
+msgstr ""
+
+#: udav/text_pnl.cpp:174
+msgid "Printing..."
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:180 mgllab/dialogs.cpp:721
+msgid "Program flow"
+msgstr ""
+
+#: udav/udav_wnd.cpp:312 mgllab/mgllab.cpp:322 mgllab/mgllab.cpp:461
+msgid "Properties"
+msgstr ""
+
+#: udav/mem_pnl.cpp:61
+msgid "Properties of selected data array"
+msgstr ""
+
+#: mgllab/table.cpp:342 mgllab/table.cpp:791
+msgid "Pulse prop."
+msgstr ""
+
+#: udav/calc_dlg.cpp:127 mgllab/mgllab.cpp:600
+msgid "Put function"
+msgstr ""
+
+#: udav/dat_pnl.cpp:457
+msgid "Put in variable"
+msgstr ""
+
+#: udav/dat_pnl.cpp:548
+msgid "Put into this data array"
+msgstr ""
+
+#: udav/anim_dlg.cpp:74 mgllab/mathgl.cpp:201
+msgid "Put to script"
+msgstr ""
+
+#: src/exec_dat.cpp:1578
+msgid "Put value (numeric or array) to given data element"
+msgstr ""
+
+#. U
+#: udav/style_dlg.cpp:247 mgllab/dialogs.cpp:55
+msgid "Q - brown"
+msgstr ""
+
+#: udav/udav_wnd.cpp:303
+msgid "Quit"
+msgstr ""
+
+#. G
+#: udav/style_dlg.cpp:239 mgllab/dialogs.cpp:47
+msgid "R - maroon"
+msgstr ""
+
+#: src/exec_set.cpp:733
+msgid "Rasterize plot and save to background"
+msgstr ""
+
+#: src/exec_dat.cpp:1584
+msgid "Read and join data from several files"
+msgstr ""
+
+#: src/exec_dat.cpp:1583
+msgid "Read data from file"
+msgstr ""
+
+#: src/exec_dat.cpp:1586
+msgid "Read data from file with sizes specified in first row"
+msgstr ""
+
+#: src/exec_dat.cpp:1585
+msgid "Read data with name 'id' from HDF file"
+msgstr ""
+
+#: udav/udav_wnd.cpp:268 mgllab/mgllab.cpp:367
+msgid "Ready"
+msgstr ""
+
+#: src/exec_dat.cpp:1587
+msgid "Rearrange data dimensions"
+msgstr ""
+
+#: udav/udav_wnd.cpp:301 mgllab/mgllab.cpp:283
+msgid "Recent files"
+msgstr ""
+
+#: udav/dat_pnl.cpp:768
+msgid "Recreate the data with new sizes and fill it by zeros (Ctrl+Shift+N)."
+msgstr ""
+
+#: udav/text_pnl.cpp:521
+msgid "Redo"
+msgstr ""
+
+#: udav/text_pnl.cpp:523
+msgid "Redo editor change (Ctrl+Shift+Z)."
+msgstr ""
+
+#: widgets/qt.cpp:1130 udav/plot_pnl.cpp:331
+msgid "Redraw"
+msgstr ""
+
+#: udav/anim_dlg.cpp:41 mgllab/mathgl.cpp:184
+msgid "Redraw picture for $0 equal to"
+msgstr ""
+
+#: widgets/fltk.cpp:813
+msgid "Redraw plot"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1320
+msgid "Refresh"
+msgstr ""
+
+#: widgets/fltk.cpp:847
+msgid "Refresh the picture"
+msgstr ""
+
+#: mgllab/dialogs.cpp:404
+msgid "Relative position of i-th color"
+msgstr ""
+
+#: udav/plot_pnl.cpp:342
+msgid "Reload"
+msgstr ""
+
+#: widgets/fltk.cpp:815
+msgid "Reload data"
+msgstr ""
+
+#: widgets/fltk.cpp:853
+msgid "Reload data and refresh the picture"
+msgstr ""
+
+#: src/exec_dat.cpp:1525
+msgid "Remove duplicate rows"
+msgstr ""
+
+#: src/exec_dat.cpp:1597
+msgid "Remove jump into the data, like phase jumps"
+msgstr ""
+
+#: udav/find_dlg.cpp:50 mgllab/editor.cpp:561
+msgid "Replace"
+msgstr ""
+
+#: mgllab/editor.cpp:564
+msgid "Replace all"
+msgstr ""
+
+#: udav/find_dlg.cpp:39 mgllab/editor.cpp:560
+msgid "Replace by:"
+msgstr ""
+
+#: udav/text_pnl.cpp:581
+msgid "Replace expression by its numerical value."
+msgstr ""
+
+#: mgllab/editor.cpp:630
+#, c-format
+msgid "Replaced %ld occurrences."
+msgstr ""
+
+#: mgllab/dialogs.cpp:891
+#, c-format
+msgid "Required argument %s is not specified!"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:186
+msgid "Reserve at"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1303
+msgid "Reserve at:"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:190
+msgid "Reserve space for labels at bottom side (style '_')"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:188
+msgid "Reserve space for labels at left side (style '<')"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:194
+msgid "Reserve space for labels at right side (style '>')"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:192
+msgid "Reserve space for labels at top side (style '^')"
+msgstr ""
+
+#: src/exec_set.cpp:734
+msgid "Reset settings and clear picture"
+msgstr ""
+
+#: udav/dat_pnl.cpp:772 mgllab/table.cpp:759
+msgid "Resize"
+msgstr ""
+
+#: udav/dat_pnl.cpp:774
+msgid "Resize (interpolate) the data to specified sizes (Ctrl+Shift+R)."
+msgstr ""
+
+#: src/exec_dat.cpp:1589
+msgid "Resize data array"
+msgstr ""
+
+#: mgllab/table.cpp:856
+msgid "Resize data with smoothing"
+msgstr ""
+
+#: widgets/qt.cpp:1123 udav/plot_pnl.cpp:325
+msgid "Restore"
+msgstr ""
+
+#: widgets/fltk.cpp:844
+msgid "Restore default graphics rotation, zoom and perspective"
+msgstr ""
+
+#: widgets/qt.cpp:1125
+msgid "Restore default graphics rotation, zoom and perspective (Alt+Space)."
+msgstr ""
+
+#: udav/plot_pnl.cpp:327
+msgid "Restore default graphics rotation, zoom and perspective (Ctrl+Space)."
+msgstr ""
+
+#: udav/plot_pnl.cpp:344
+msgid "Restore status for 'once' command and reload data (F9)."
+msgstr ""
+
+#: udav/calc_dlg.cpp:63 udav/data_dlg.cpp:85 udav/data_dlg.cpp:143
+#: udav/subplot_dlg.cpp:212 mgllab/dialogs.cpp:1315
+msgid "Result"
+msgstr ""
+
+#: udav/data_dlg.cpp:124
+msgid "Result (will have sizes "
+msgstr ""
+
+#: udav/style_dlg.cpp:201 udav/subplot_dlg.cpp:214 mgllab/dialogs.cpp:408
+msgid "Resulting string"
+msgstr ""
+
+#: src/parser.cpp:1439
+msgid "Return from function"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:148
+msgid "Right bottom edge"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:156
+msgid "Right top edge"
+msgstr ""
+
+#: mgllab/table.cpp:166 mgllab/table.cpp:782
+msgid "Roll"
+msgstr ""
+
+#: src/exec_dat.cpp:1591
+msgid "Roll data along direction(s)"
+msgstr ""
+
+#. rotate menu
+#: udav/plot_pnl.cpp:540
+msgid "Rotate"
+msgstr ""
+
+#: widgets/qt.cpp:1110 udav/plot_pnl.cpp:310
+msgid "Rotate by mouse"
+msgstr ""
+
+#: udav/plot_pnl.cpp:545
+msgid "Rotate down"
+msgstr ""
+
+#: udav/plot_pnl.cpp:549
+msgid "Rotate left"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:164 mgllab/dialogs.cpp:1294
+msgid "Rotate on"
+msgstr ""
+
+#: widgets/fltk.cpp:840
+msgid "Rotate picture by holding left mouse button"
+msgstr ""
+
+#: src/exec_set.cpp:735
+msgid "Rotate plot"
+msgstr ""
+
+#: udav/plot_pnl.cpp:553
+msgid "Rotate right"
+msgstr ""
+
+#: udav/plot_pnl.cpp:541
+msgid "Rotate up"
+msgstr ""
+
+#: mgllab/dialogs.cpp:356
+msgid "Rotation"
+msgstr ""
+
+#: widgets/qt.cpp:1254
+msgid "Run slideshow (CTRl+F5)."
+msgstr ""
+
+#: udav/plot_pnl.cpp:570
+msgid ""
+"Run slideshow (Ctrl+F5). If no parameter specified\n"
+"then the dialog with slideshow options will appear."
+msgstr ""
+
+#: widgets/fltk.cpp:885
+msgid "Run/Stop slideshow (graphics animation)"
+msgstr ""
+
+#: udav/prop_dlg.cpp:141
+msgid "Russian"
+msgstr ""
+
+#: widgets/qt.cpp:1080 udav/plot_pnl.cpp:488
+msgid "STL"
+msgstr ""
+
+#: widgets/qt.cpp:1073 udav/plot_pnl.cpp:480
+msgid "SVG"
+msgstr ""
+
+#: udav/style_dlg.cpp:107
+msgid "Saturation"
+msgstr ""
+
+#: udav/setup_dlg.cpp:143 mgllab/editor.cpp:282
+msgid "Save"
+msgstr ""
+
+#: mgllab/help.cpp:250 mgllab/table.cpp:456
+msgid "Save Data?"
+msgstr ""
+
+#: widgets/fltk.cpp:572 mgllab/mgllab.cpp:214
+msgid "Save File As?"
+msgstr ""
+
+#: udav/anim_dlg.cpp:83
+msgid "Save JPEG frames"
+msgstr ""
+
+#: udav/udav_wnd.cpp:290 mgllab/mgllab.cpp:281
+msgid "Save as ..."
+msgstr ""
+
+#: udav/dat_pnl.cpp:688
+msgid "Save data"
+msgstr ""
+
+#: src/exec_dat.cpp:1594
+msgid "Save data to HDF5 file"
+msgstr ""
+
+#: udav/dat_pnl.cpp:690
+msgid "Save data to a file (Ctrl+Shift+S)."
+msgstr ""
+
+#: src/exec_dat.cpp:1593 mgllab/table.cpp:842
+msgid "Save data to file"
+msgstr ""
+
+#: mgllab/mgllab.cpp:280
+msgid "Save file"
+msgstr ""
+
+#: mgllab/mgllab.cpp:473
+msgid "Save file before redrawing"
+msgstr ""
+
+#: udav/udav_wnd.cpp:201
+msgid "Save script"
+msgstr ""
+
+#: udav/udav_wnd.cpp:203
+msgid "Save script to a file (Ctrl+S)"
+msgstr ""
+
+#: mgllab/editor.cpp:508
+msgid "Save script to file"
+msgstr ""
+
+#: mgllab/help.cpp:172
+msgid "Save selected data to file."
+msgstr ""
+
+#: mgllab/table.cpp:751
+msgid "Save to file"
+msgstr ""
+
+#: udav/udav_wnd.cpp:672
+msgid "Saving aborted"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:179 mgllab/dialogs.cpp:720
+msgid "Scale and rotate"
+msgstr ""
+
+#: udav/udav_wnd.cpp:237
+msgid "Script"
+msgstr ""
+
+#: udav/find_dlg.cpp:43 mgllab/editor.cpp:563
+msgid "Search backward"
+msgstr ""
+
+#: udav/text_pnl.cpp:543 mgllab/mgllab.cpp:297
+msgid "Select all"
+msgstr ""
+
+#: udav/text_pnl.cpp:585
+msgid "Select and insert file name."
+msgstr ""
+
+#: udav/text_pnl.cpp:589
+msgid "Select and insert folder name."
+msgstr ""
+
+#: mgllab/dialogs.cpp:565
+msgid "Select data argument"
+msgstr ""
+
+#: mgllab/dialogs.cpp:160
+msgid "Select direction"
+msgstr ""
+
+#: mgllab/editor.cpp:654
+msgid "Select file name"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:339 udav/newcmd_dlg.cpp:357
+msgid "Select first the proper kind of arguments"
+msgstr ""
+
+#: mgllab/editor.cpp:667
+msgid "Select folder name"
+msgstr ""
+
+#: udav/info_dlg.cpp:39
+msgid "Select kind of plot"
+msgstr ""
+
+#: src/exec_set.cpp:749
+msgid "Select variant of plot style(s)"
+msgstr ""
+
+#: mgllab/mathgl.cpp:166
+msgid "Set"
+msgstr ""
+
+#: src/exec_set.cpp:745
+msgid "Set additional tick and axis labels shift"
+msgstr ""
+
+#: src/exec_set.cpp:695
+msgid "Set ambient light brightness"
+msgstr ""
+
+#: src/exec_set.cpp:716
+msgid "Set arbitrary position of plot in picture"
+msgstr ""
+
+#: udav/udav_wnd.cpp:315 mgllab/mgllab.cpp:323
+msgid "Set arguments"
+msgstr ""
+
+#: src/exec_set.cpp:697
+msgid "Set aspect ration"
+msgstr ""
+
+#: src/exec_set.cpp:699
+msgid "Set axis and tick style"
+msgstr ""
+
+#: src/exec_set.cpp:725
+msgid "Set axis origin"
+msgstr ""
+
+#: src/exec_set.cpp:732
+msgid "Set axis ranges"
+msgstr ""
+
+#: src/exec_set.cpp:701
+msgid "Set bounding box for 2d export"
+msgstr ""
+
+#: src/exec_set.cpp:722
+msgid "Set brush for given mask id"
+msgstr ""
+
+#: src/exec_set.cpp:706
+msgid "Set color range"
+msgstr ""
+
+#: src/exec_dat.cpp:1556
+msgid "Set column id for data"
+msgstr ""
+
+#: mgllab/dialogs.cpp:108
+msgid "Set cutting off/on for particular plot"
+msgstr ""
+
+#: udav/open_dlg.cpp:62
+msgid "Set data sizes manually"
+msgstr ""
+
+#: src/exec_set.cpp:700
+msgid "Set default bars width"
+msgstr ""
+
+#: src/exec_set.cpp:730
+msgid "Set default filename"
+msgstr ""
+
+#: src/exec_set.cpp:694
+msgid "Set default transparency"
+msgstr ""
+
+#: src/exec_set.cpp:709
+msgid "Set diffusive light brightness"
+msgstr ""
+
+#: src/exec_set.cpp:710
+msgid "Set draw region for quality&4"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:47 udav/subplot_dlg.cpp:89
+msgid "Set drawing area as cell of matrix nx*ny."
+msgstr ""
+
+#: udav/subplot_dlg.cpp:110
+msgid "Set drawing area as cells of column."
+msgstr ""
+
+#: udav/subplot_dlg.cpp:64 udav/subplot_dlg.cpp:140
+msgid "Set drawing area as cells of matrix nx*ny."
+msgstr ""
+
+#: udav/subplot_dlg.cpp:127
+msgid "Set drawing area as cells of stick."
+msgstr ""
+
+#: mgllab/dialogs.cpp:117
+msgid "Set lighting off/on for particular plot"
+msgstr ""
+
+#: src/exec_set.cpp:723
+msgid "Set number of lines in mesh/fall/vect and so on"
+msgstr ""
+
+#: src/exec_set.cpp:717
+msgid "Set number of marks in the legend"
+msgstr ""
+
+#: src/exec_set.cpp:711
+msgid "Set number of visible faces"
+msgstr ""
+
+#: src/exec_set.cpp:727
+msgid "Set palette for 1D plots"
+msgstr ""
+
+#: src/exec_set.cpp:729
+msgid "Set perspective"
+msgstr ""
+
+#: src/exec_set.cpp:737
+msgid "Set picture size"
+msgstr ""
+
+#: src/exec_set.cpp:731
+msgid "Set plot quality"
+msgstr ""
+
+#: src/exec_set.cpp:742
+msgid "Set position of plot as cell of matrix"
+msgstr ""
+
+#: src/exec_set.cpp:724
+msgid "Set position of plot block in matrix"
+msgstr ""
+
+#: src/exec_set.cpp:705
+msgid "Set position of plot inside cell of column"
+msgstr ""
+
+#: src/exec_set.cpp:715
+msgid "Set position of plot inside cell of matrix"
+msgstr ""
+
+#: src/exec_set.cpp:741
+msgid "Set position of plot inside cell of rotated stick"
+msgstr ""
+
+#: src/exec_set.cpp:740
+msgid "Set position of plot inside cell of sheared stick"
+msgstr ""
+
+#: src/exec_set.cpp:753
+msgid "Set range for x-axis"
+msgstr ""
+
+#: src/exec_set.cpp:755
+msgid "Set range for y-axis"
+msgstr ""
+
+#: src/exec_set.cpp:759
+msgid "Set range for z-axis"
+msgstr ""
+
+#: src/exec_set.cpp:738
+msgid "Set scaling factor for further setsize"
+msgstr ""
+
+#: mgllab/mathgl.cpp:143
+msgid "Set script arguments"
+msgstr ""
+
+#: mgllab/dialogs.cpp:105
+msgid "Set size for text, marks and others"
+msgstr ""
+
+#: src/exec_set.cpp:696
+msgid "Set size of arrows"
+msgstr ""
+
+#: src/exec_set.cpp:721
+msgid "Set size of markers"
+msgstr ""
+
+#: src/exec_set.cpp:728
+msgid "Set size of semi-transparent area around line"
+msgstr ""
+
+#: src/exec_set.cpp:726
+msgid "Set tick labels drawing at origin"
+msgstr ""
+
+#: src/exec_set.cpp:744
+msgid "Set tick length"
+msgstr ""
+
+#: src/exec_set.cpp:707
+msgid "Set ticks for colorbar"
+msgstr ""
+
+#: src/exec_set.cpp:754
+msgid "Set ticks for x-axis"
+msgstr ""
+
+#: src/exec_set.cpp:756
+msgid "Set ticks for y-axis"
+msgstr ""
+
+#: src/exec_set.cpp:760
+msgid "Set ticks for z-axis"
+msgstr ""
+
+#: src/exec_set.cpp:746
+msgid "Set ticks in time format"
+msgstr ""
+
+#: src/exec_set.cpp:748
+msgid "Set ticks tuning"
+msgstr ""
+
+#: src/exec_set.cpp:736
+msgid "Set to auto rotate text or not"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:196
+msgid "Set to use whole area (style '#')"
+msgstr ""
+
+#: src/exec_set.cpp:747
+msgid "Set type transparency"
+msgstr ""
+
+#: widgets/qt.cpp:1209
+msgid "Set value of \\phi angle."
+msgstr ""
+
+#: udav/plot_pnl.cpp:472
+msgid ""
+"Set value of \\phi angle.\n"
+"You can use keys (Shift+Meta+Left or Shift+Meta+Right)."
+msgstr ""
+
+#: widgets/qt.cpp:1203
+msgid "Set value of \\theta angle."
+msgstr ""
+
+#: udav/plot_pnl.cpp:466
+msgid ""
+"Set value of \\theta angle.\n"
+"You can use keys (Shift+Meta+Up or Shift+Meta+Down)."
+msgstr ""
+
+#: udav/udav_wnd.cpp:311
+msgid "Settings"
+msgstr ""
+
+#: mgllab/mgllab.cpp:321
+msgid "Setup"
+msgstr ""
+
+#: mgllab/mgllab.cpp:324
+msgid "Setup animation"
+msgstr ""
+
+#: udav/prop_dlg.cpp:80
+msgid "Setup colors for:"
+msgstr ""
+
+#: src/exec_set.cpp:713
+msgid "Setup font"
+msgstr ""
+
+#: src/exec_set.cpp:718
+msgid "Setup light"
+msgstr ""
+
+#: src/exec_prm.cpp:579
+msgid "Setup or draw axis"
+msgstr ""
+
+#: src/exec_set.cpp:708
+msgid "Setup plot points cutting"
+msgstr ""
+
+#: mgllab/dialogs.cpp:947
+msgid "Setup script"
+msgstr ""
+
+#: udav/plot_pnl.cpp:573
+msgid "Setup show"
+msgstr ""
+
+#: udav/dat_pnl.cpp:623
+msgid "Sew data along direction(s)"
+msgstr ""
+
+#: mgllab/table.cpp:166 mgllab/table.cpp:783
+msgid "Sew phase"
+msgstr ""
+
+#: mgllab/dialogs.cpp:350
+msgid "Sharp colors"
+msgstr ""
+
+#: src/exec_set.cpp:739
+msgid "Shear plot"
+msgstr ""
+
+#: widgets/fltk.cpp:878
+msgid "Shift the picture down"
+msgstr ""
+
+#: widgets/fltk.cpp:870
+msgid "Shift the picture left"
+msgstr ""
+
+#: widgets/fltk.cpp:876
+msgid "Shift the picture right"
+msgstr ""
+
+#: widgets/fltk.cpp:868
+msgid "Shift the picture up"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:56 mgllab/dialogs.cpp:737
+msgid "Short description of selected command"
+msgstr ""
+
+#: udav/info_dlg.cpp:54
+msgid "Short information about the data."
+msgstr ""
+
+#: udav/hint_dlg.cpp:62
+msgid "Show at startup"
+msgstr ""
+
+#: udav/udav_wnd.cpp:210
+msgid ""
+"Show calculator which evaluate and help to type textual formulas.\n"
+"Textual formulas may contain data variables too."
+msgstr ""
+
+#: mgllab/editor.cpp:525 mgllab/editor.cpp:527
+msgid "Show calculator window"
+msgstr ""
+
+#: udav/udav_wnd.cpp:314
+msgid "Show dialog for UDAV properties."
+msgstr ""
+
+#: udav/text_pnl.cpp:560 udav/plot_pnl.cpp:441
+msgid "Show dialog for new command or edit arguments of existed one."
+msgstr ""
+
+#: udav/text_pnl.cpp:564 udav/plot_pnl.cpp:446
+msgid "Show dialog for new inplot and put it into the script."
+msgstr ""
+
+#: udav/text_pnl.cpp:577
+msgid ""
+"Show dialog for options and put it into the script.\n"
+"Options are used for additional setup the plot."
+msgstr ""
+
+#: udav/text_pnl.cpp:598
+msgid ""
+"Show dialog for plot setup and put code into the script.\n"
+"This dialog setup axis, labels, lighting and other general things."
+msgstr ""
+
+#: udav/text_pnl.cpp:573
+msgid ""
+"Show dialog for styles and put it into the script.\n"
+"Styles define the plot view (color scheme, marks, dashing and so on)."
+msgstr ""
+
+#: udav/text_pnl.cpp:548
+msgid "Show dialog for text finding (Ctrl+F)."
+msgstr ""
+
+#: udav/udav_wnd.cpp:326
+msgid "Show help on MGL commands (F1)."
+msgstr ""
+
+#: udav/udav_wnd.cpp:219
+msgid "Show hidden plots"
+msgstr ""
+
+#: mgllab/help.cpp:303
+msgid "Show hint on startup"
+msgstr ""
+
+#: udav/udav_wnd.cpp:330
+msgid "Show hints of MGL usage."
+msgstr ""
+
+#: udav/udav_wnd.cpp:213
+msgid "Show info"
+msgstr ""
+
+#: mgllab/mgllab.cpp:299
+msgid "Show lines"
+msgstr ""
+
+#: widgets/fltk.cpp:886
+msgid "Show next frame in slideshow"
+msgstr ""
+
+#: widgets/qt.cpp:1249 udav/plot_pnl.cpp:563
+msgid "Show next slide (Ctrl+.)."
+msgstr ""
+
+#: widgets/fltk.cpp:881
+msgid "Show previous frame in slideshow"
+msgstr ""
+
+#: widgets/qt.cpp:1258 udav/plot_pnl.cpp:578
+msgid "Show previous slide (Ctrl+,)."
+msgstr ""
+
+#: mgllab/table.cpp:777
+msgid "Sin FFT"
+msgstr ""
+
+#: udav/dat_pnl.cpp:620
+msgid "Sin-Fourier transform along direction(s)"
+msgstr ""
+
+#: src/exec_dat.cpp:1598
+msgid "Sin-Fourier transform at some direction"
+msgstr ""
+
+#: mgllab/table.cpp:165
+msgid "Sinus FFT"
+msgstr ""
+
+#: udav/opt_dlg.cpp:70 mgllab/dialogs.cpp:104 mgllab/dialogs.cpp:359
+msgid "Size"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:114
+msgid "Size of column"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:131
+msgid "Size of stick"
+msgstr ""
+
+#. size menu
+#: udav/mem_pnl.cpp:68 udav/dat_pnl.cpp:765 mgllab/dialogs.cpp:1015
+#: mgllab/table.cpp:757
+msgid "Sizes"
+msgstr ""
+
+#: src/parser.cpp:1425
+msgid "Skip commands and iterate for-loop again"
+msgstr ""
+
+#: widgets/qt.cpp:1251 udav/plot_pnl.cpp:566
+msgid "Slideshow"
+msgstr ""
+
+#: mgllab/table.cpp:163 mgllab/table.cpp:771
+msgid "Smooth"
+msgstr ""
+
+#: src/exec_dat.cpp:1599
+msgid "Smooth data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:613
+msgid "Smooth data along direction(s)"
+msgstr ""
+
+#: src/exec_dat.cpp:1582
+msgid "Solve Hamiltonian ODE (find GO ray or trajectory)"
+msgstr ""
+
+#: src/exec_dat.cpp:1573
+msgid "Solve ODE"
+msgstr ""
+
+#: src/exec_dat.cpp:1575
+msgid "Solve PDE"
+msgstr ""
+
+#: src/exec_dat.cpp:1580
+msgid "Solve PDE in accompanied coordinates for 2d case"
+msgstr ""
+
+#: src/exec_dat.cpp:1581
+msgid "Solve PDE in accompanied coordinates for 3d case"
+msgstr ""
+
+#: src/exec_dat.cpp:1524
+msgid "Solve PDE using advanced method (X-Y only)"
+msgstr ""
+
+#: src/exec_dat.cpp:1613
+msgid "Solve tridiagonal matrix"
+msgstr ""
+
+#: src/exec_dat.cpp:1601
+msgid "Sort data by values in column"
+msgstr ""
+
+#: udav/prop_dlg.cpp:141
+msgid "Spanish"
+msgstr ""
+
+#: udav/calc_dlg.cpp:194
+msgid "Special"
+msgstr ""
+
+#: mgllab/table.cpp:129
+msgid ""
+"Specify new data size\n"
+"Data will be interpolated"
+msgstr ""
+
+#: mgllab/table.cpp:114
+msgid ""
+"Specify new data size\n"
+"Data will be zero filled"
+msgstr ""
+
+#: mgllab/table.cpp:144
+msgid ""
+"Specify the skipping step\n"
+"Each m-th point will be saved only"
+msgstr ""
+
+#: udav/dat_pnl.cpp:778 mgllab/table.cpp:760
+msgid "Squeeze"
+msgstr ""
+
+#: src/exec_dat.cpp:1602
+msgid "Squeeze data"
+msgstr ""
+
+#: udav/setup_dlg.cpp:84
+msgid "Start"
+msgstr ""
+
+#: src/parser.cpp:1434
+msgid "Start function definition and stop execution of main script"
+msgstr ""
+
+#: src/parser.cpp:1437
+msgid "Start next for-loop iteration"
+msgstr ""
+
+#: src/parser.cpp:1438
+msgid "Start/close commands which should executed only once"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:76
+msgid "Starting cell index"
+msgstr ""
+
+#: udav/setup_dlg.cpp:117
+msgid "State"
+msgstr ""
+
+#: src/exec_dat.cpp:1539
+msgid "Step for pulse diffraction"
+msgstr ""
+
+#: widgets/qt.cpp:1135 udav/plot_pnl.cpp:347
+msgid "Stop"
+msgstr ""
+
+#: widgets/fltk.cpp:849
+msgid "Stop drawing"
+msgstr ""
+
+#: src/parser.cpp:1440
+msgid "Stop execution"
+msgstr ""
+
+#: udav/plot_pnl.cpp:349
+msgid "Stop script execution (F7)."
+msgstr ""
+
+#: udav/args_dlg.cpp:59 mgllab/mathgl.cpp:162
+msgid "String for $0"
+msgstr ""
+
+#: udav/args_dlg.cpp:41 mgllab/mathgl.cpp:144
+msgid "String for $1"
+msgstr ""
+
+#: udav/args_dlg.cpp:43 mgllab/mathgl.cpp:146
+msgid "String for $2"
+msgstr ""
+
+#: udav/args_dlg.cpp:45 mgllab/mathgl.cpp:148
+msgid "String for $3"
+msgstr ""
+
+#: udav/args_dlg.cpp:47 mgllab/mathgl.cpp:150
+msgid "String for $4"
+msgstr ""
+
+#: udav/args_dlg.cpp:49 mgllab/mathgl.cpp:152
+msgid "String for $5"
+msgstr ""
+
+#: udav/args_dlg.cpp:51 mgllab/mathgl.cpp:154
+msgid "String for $6"
+msgstr ""
+
+#: udav/args_dlg.cpp:53 mgllab/mathgl.cpp:156
+msgid "String for $7"
+msgstr ""
+
+#: udav/args_dlg.cpp:55 mgllab/mathgl.cpp:158
+msgid "String for $8"
+msgstr ""
+
+#: udav/args_dlg.cpp:57 mgllab/mathgl.cpp:160
+msgid "String for $9"
+msgstr ""
+
+#: udav/files_dlg.cpp:38
+msgid "String for %1"
+msgstr ""
+
+#: udav/files_dlg.cpp:40
+msgid "String for %2"
+msgstr ""
+
+#: udav/files_dlg.cpp:42
+msgid "String for %3"
+msgstr ""
+
+#: udav/files_dlg.cpp:44
+msgid "String for %4"
+msgstr ""
+
+#: udav/files_dlg.cpp:46
+msgid "String for %5"
+msgstr ""
+
+#: udav/files_dlg.cpp:48
+msgid "String for %6"
+msgstr ""
+
+#: udav/files_dlg.cpp:50
+msgid "String for %7"
+msgstr ""
+
+#: udav/files_dlg.cpp:52
+msgid "String for %8"
+msgstr ""
+
+#: udav/files_dlg.cpp:54
+msgid "String for %9"
+msgstr ""
+
+#: udav/prop_dlg.cpp:85
+msgid "Strings"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:208 mgllab/dialogs.cpp:1314
+msgid "Style"
+msgstr ""
+
+#: udav/setup_dlg.cpp:80
+msgid "SubTicks"
+msgstr ""
+
+#: mgllab/dialogs.cpp:959
+msgid "Subticks"
+msgstr ""
+
+#: src/exec_dat.cpp:1605
+msgid "Subtract data or number"
+msgstr ""
+
+#: mgllab/table.cpp:795
+msgid "Subtract to"
+msgstr ""
+
+#: udav/prop_dlg.cpp:94
+msgid "Suffixes"
+msgstr ""
+
+#: udav/dat_pnl.cpp:539
+msgid "Sum along direction(s)"
+msgstr ""
+
+#: udav/dat_pnl.cpp:614
+msgid "Summarize data along direction(s)"
+msgstr ""
+
+#. { _("Histogram of"),	0, hist_cb },
+#: mgllab/table.cpp:342 mgllab/table.cpp:788
+msgid "Summation of"
+msgstr ""
+
+#: src/exec_dat.cpp:1607
+msgid "Swap data (useful after Fourier transform)"
+msgstr ""
+
+#: udav/dat_pnl.cpp:618
+msgid "Swap data along direction(s)"
+msgstr ""
+
+#: mgllab/table.cpp:164 mgllab/table.cpp:776
+msgid "Swap parts"
+msgstr ""
+
+#: src/exec_set.cpp:712
+msgid "Switch on/off fog"
+msgstr ""
+
+#: src/exec_set.cpp:714
+msgid "Switch on/off gray-scale mode"
+msgstr ""
+
+#: widgets/fltk.cpp:836
+msgid "Switch on/off grid drawing"
+msgstr ""
+
+#: udav/plot_pnl.cpp:307
+msgid "Switch on/off grid of absolute coordinates (Ctrl+G)."
+msgstr ""
+
+#: widgets/qt.cpp:1108
+msgid "Switch on/off lightning for the graphics (Alt+L)."
+msgstr ""
+
+#: udav/plot_pnl.cpp:301
+msgid "Switch on/off lightning for the graphics (Ctrl+L)."
+msgstr ""
+
+#: widgets/fltk.cpp:833
+msgid "Switch on/off lightning in the picture"
+msgstr ""
+
+#: widgets/qt.cpp:1114 udav/plot_pnl.cpp:314
+msgid ""
+"Switch on/off mouse handling of the graphics\n"
+"(rotation, shifting, zooming and perspective)."
+msgstr ""
+
+#: widgets/qt.cpp:1120
+msgid "Switch on/off mouse zoom of selected region."
+msgstr ""
+
+#: src/exec_set.cpp:743
+msgid "Switch on/off to use ternary axis"
+msgstr ""
+
+#: src/exec_set.cpp:693
+msgid "Switch on/off transparency"
+msgstr ""
+
+#: widgets/qt.cpp:1102
+msgid "Switch on/off transparency for the graphics (Alt+T)."
+msgstr ""
+
+#: udav/plot_pnl.cpp:294
+msgid "Switch on/off transparency for the graphics (Ctrl+T)."
+msgstr ""
+
+#: widgets/fltk.cpp:830
+msgid "Switch on/off transparency in the picture"
+msgstr ""
+
+#: mgllab/table.cpp:552
+msgid "Symmetrical range"
+msgstr ""
+
+#: udav/dat_pnl.cpp:366
+msgid "Symmetrical?"
+msgstr ""
+
+#: src/addon.cpp:110 src/base_cf.cpp:266
+#, c-format
+msgid "TEST: %s\n"
+msgstr ""
+
+#: udav/open_dlg.cpp:82 udav/setup_dlg.cpp:88 mgllab/dialogs.cpp:961
+msgid "Template"
+msgstr ""
+
+#: udav/setup_dlg.cpp:140
+msgid "Template name"
+msgstr ""
+
+#: udav/setup_dlg.cpp:163
+msgid "Template saved"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1038
+msgid "Ternary"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1472
+msgid "Text"
+msgstr ""
+
+#: udav/style_dlg.cpp:167 mgllab/dialogs.cpp:376
+msgid "Text align"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:172 mgllab/dialogs.cpp:713
+msgid "Text and legend"
+msgstr ""
+
+#: udav/style_dlg.cpp:164
+msgid "Text color"
+msgstr ""
+
+#: udav/style_dlg.cpp:123 mgllab/dialogs.cpp:343
+msgid "Text on contours"
+msgstr ""
+
+#: mgllab/dialogs.cpp:367
+msgid "Text style"
+msgstr ""
+
+#: udav/hint_dlg.cpp:48 mgllab/help.cpp:282
+msgid ""
+"The calculator can help you to put complex expression in the script. Just "
+"type the expression (which may depend on coordinates x,y,z and so on) and "
+"put it into the script."
+msgstr ""
+
+#: mgllab/editor.cpp:280
+msgid ""
+"The current file has not been saved.\n"
+"Would you like to save it now?"
+msgstr ""
+
+#: udav/hint_dlg.cpp:50 mgllab/help.cpp:284
+msgid ""
+"The special dialog (Edit|Insert|New Command) help you select the command, "
+"fill its arguments and put it into the script."
+msgstr ""
+
+#: src/crust.cpp:559
+msgid ""
+"There are duplicated or indistinguishably adjacent points for triangulation."
+msgstr ""
+
+#. mglScrStr
+#: src/base.cpp:236
+msgid "There is changing temporary data in script"
+msgstr ""
+
+#: udav/text_pnl.cpp:124
+msgid "There is manual primitives."
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:343
+msgid "There is no 'fmt' argument for this command"
+msgstr ""
+
+#: udav/text_pnl.cpp:137 mgllab/editor.cpp:681
+msgid "There is no fitted formula."
+msgstr ""
+
+#: utils/mglcgi.cpp:74
+#, c-format
+msgid "There is no query. Exit.\n"
+msgstr ""
+
+#: udav/text_pnl.cpp:109
+msgid "There is no selection to evaluate."
+msgstr ""
+
+#: udav/hint_dlg.cpp:47 mgllab/help.cpp:281
+msgid ""
+"There is powerful calculator with a lot of special functions. You can use "
+"buttons or keyboard to type the expression. Also you can use existed "
+"variables in the expression."
+msgstr ""
+
+#. mglScrCmd
+#: src/base.cpp:234
+msgid "There is too long string(s) in script"
+msgstr ""
+
+#. mglScrLong
+#: src/base.cpp:235
+msgid "There is unbalanced ' in script"
+msgstr ""
+
+#. mglWarnSpc
+#: src/base.cpp:232
+msgid "There is wrong argument(s) in script"
+msgstr ""
+
+#. mglScrArg
+#: src/base.cpp:233
+msgid "There is wrong command(s) in script"
+msgstr ""
+
+#: widgets/fltk.cpp:862
+msgid "Theta angle (tilt z-axis)"
+msgstr ""
+
+#: mgllab/table.cpp:494
+msgid "This operation is not supported for this kind of data."
+msgstr ""
+
+#: udav/setup_dlg.cpp:76 mgllab/dialogs.cpp:955
+msgid "Ticks"
+msgstr ""
+
+#: mgllab/dialogs.cpp:960
+msgid "Ticks start"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1031
+msgid "Time ticks"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:204 mgllab/dialogs.cpp:1313
+msgid "Title"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:206
+msgid "Title for plot. Can be used in SubPlot or MultiPlot only."
+msgstr ""
+
+#: udav/dat_pnl.cpp:351 udav/dat_pnl.cpp:366 udav/dat_pnl.cpp:377
+#: udav/dat_pnl.cpp:424 udav/dat_pnl.cpp:453 mgllab/table.cpp:609
+msgid "To"
+msgstr ""
+
+#: udav/calc_dlg.cpp:66 udav/setup_dlg.cpp:147
+msgid "To script"
+msgstr ""
+
+#: udav/dat_pnl.cpp:790
+msgid "Transform"
+msgstr ""
+
+#: udav/dat_pnl.cpp:792
+msgid "Transform data along dimension(s) (Ctrl+Shift+T)."
+msgstr ""
+
+#: mgllab/dialogs.cpp:346
+msgid "Transparency"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1043
+msgid "Transparency type"
+msgstr ""
+
+#: mgllab/table.cpp:762
+msgid "Transpose"
+msgstr ""
+
+#: mgllab/table.cpp:670
+msgid "Transpose data"
+msgstr ""
+
+#: src/exec_dat.cpp:1611
+msgid "Transpose data array"
+msgstr ""
+
+#: mgllab/table.cpp:860
+msgid "Transpose data dimensions"
+msgstr ""
+
+#: udav/dat_pnl.cpp:612
+msgid "Transpose data with new dimensions"
+msgstr ""
+
+#: udav/calc_dlg.cpp:192
+msgid "Trigonometric"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1034
+msgid "Tune ticks"
+msgstr ""
+
+#: mgllab/table.cpp:169 mgllab/table.cpp:344
+msgid "Type of operation"
+msgstr ""
+
+#: mgllab/table.cpp:174
+msgid "Type of smoothing"
+msgstr ""
+
+#. N
+#: udav/style_dlg.cpp:246 mgllab/dialogs.cpp:54
+msgid "U - indigo"
+msgstr ""
+
+#: udav/text_pnl.cpp:109 udav/text_pnl.cpp:124 udav/text_pnl.cpp:137
+#: udav/udav_wnd.cpp:340
+msgid "UDAV"
+msgstr ""
+
+#: udav/opt_dlg.cpp:31
+msgid "UDAV - Add options"
+msgstr ""
+
+#: udav/anim_dlg.cpp:35
+msgid "UDAV - Animation setup"
+msgstr ""
+
+#: udav/dat_pnl.cpp:388
+msgid "UDAV - Clear data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:424
+msgid "UDAV - Crop data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:255
+msgid "UDAV - Export to PNG"
+msgstr ""
+
+#: udav/dat_pnl.cpp:351
+msgid "UDAV - Fill data"
+msgstr ""
+
+#: udav/find_dlg.cpp:33
+msgid "UDAV - Find"
+msgstr ""
+
+#: udav/dat_pnl.cpp:485
+msgid "UDAV - Go to slice"
+msgstr ""
+
+#: udav/hint_dlg.cpp:55
+msgid "UDAV - Hint"
+msgstr ""
+
+#: udav/dat_pnl.cpp:277
+msgid "UDAV - Import PNG"
+msgstr ""
+
+#: udav/prop_dlg.cpp:192 udav/prop_dlg.cpp:198 udav/newcmd_dlg.cpp:324
+#: udav/text_pnl.cpp:145 udav/open_dlg.cpp:101
+msgid "UDAV - Insert filename"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:329 udav/text_pnl.cpp:152
+msgid "UDAV - Insert path"
+msgstr ""
+
+#: udav/style_dlg.cpp:48 udav/data_dlg.cpp:33
+msgid "UDAV - Insert style/scheme"
+msgstr ""
+
+#: udav/dat_pnl.cpp:270
+msgid "UDAV - Load data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:450
+msgid "UDAV - Make histogram"
+msgstr ""
+
+#: udav/mem_pnl.cpp:84
+msgid "UDAV - New variable"
+msgstr ""
+
+#: udav/dat_pnl.cpp:377
+msgid "UDAV - Normalize by slice"
+msgstr ""
+
+#: udav/dat_pnl.cpp:366
+msgid "UDAV - Normalize data"
+msgstr ""
+
+#: udav/open_dlg.cpp:49
+msgid "UDAV - Open data file"
+msgstr ""
+
+#: udav/udav_wnd.cpp:633
+msgid "UDAV - Open file"
+msgstr ""
+
+#: udav/prop_dlg.cpp:60 udav/prop_dlg.cpp:285
+msgid "UDAV - Properties"
+msgstr ""
+
+#: udav/dat_pnl.cpp:283
+msgid "UDAV - Read from HDF"
+msgstr ""
+
+#: udav/dat_pnl.cpp:436
+msgid "UDAV - Rearrange data"
+msgstr ""
+
+#: udav/dat_pnl.cpp:402
+msgid "UDAV - Resize data"
+msgstr ""
+
+#: udav/setup_dlg.cpp:159 udav/setup_dlg.cpp:163
+msgid "UDAV - Save template"
+msgstr ""
+
+#: udav/dat_pnl.cpp:261
+msgid "UDAV - Save to HDF"
+msgstr ""
+
+#: udav/dat_pnl.cpp:248
+msgid "UDAV - Save/export data"
+msgstr ""
+
+#: udav/args_dlg.cpp:32
+msgid "UDAV - Set script arguments"
+msgstr ""
+
+#: udav/files_dlg.cpp:29
+msgid "UDAV - Set template parameters"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:37
+msgid "UDAV - Setup inplot"
+msgstr ""
+
+#: udav/setup_dlg.cpp:39 udav/setup_dlg.cpp:190
+msgid "UDAV - Setup plot"
+msgstr ""
+
+#: udav/dat_pnl.cpp:413
+msgid "UDAV - Squeeze data"
+msgstr ""
+
+#: udav/udav_wnd.cpp:456
+msgid "UDAV - about"
+msgstr ""
+
+#: udav/anim_dlg.cpp:104
+msgid "UDAV - animation"
+msgstr ""
+
+#: udav/dat_pnl.cpp:608
+msgid "UDAV - change data"
+msgstr ""
+
+#: udav/opt_dlg.cpp:94 udav/opt_dlg.cpp:101 udav/opt_dlg.cpp:108
+#: udav/opt_dlg.cpp:115
+msgid "UDAV - command options"
+msgstr ""
+
+#: udav/mem_pnl.cpp:121
+msgid "UDAV - delete all data"
+msgstr ""
+
+#: udav/text_pnl.cpp:202
+msgid "UDAV - find text"
+msgstr ""
+
+#: udav/dat_pnl.cpp:536 udav/dat_pnl.cpp:566 udav/dat_pnl.cpp:572
+#: udav/dat_pnl.cpp:643
+msgid "UDAV - make new data"
+msgstr ""
+
+#: udav/text_pnl.cpp:431
+msgid "UDAV - open file"
+msgstr ""
+
+#: udav/udav_wnd.cpp:569 udav/udav_wnd.cpp:579 udav/udav_wnd.cpp:621
+msgid "UDAV - save current"
+msgstr ""
+
+#: udav/udav_wnd.cpp:669
+msgid "UDAV - save file"
+msgstr ""
+
+#: udav/style_dlg.cpp:160 mgllab/dialogs.cpp:371
+msgid "Underline"
+msgstr ""
+
+#. edit menu
+#: udav/text_pnl.cpp:516 mgllab/mgllab.cpp:293
+msgid "Undo"
+msgstr ""
+
+#: udav/text_pnl.cpp:518
+msgid "Undo editor change (Ctrl+Z)."
+msgstr ""
+
+#: mgllab/mgllab.cpp:127
+msgid "Untitled"
+msgstr ""
+
+#: mgllab/mgllab.cpp:345 mgllab/mgllab.cpp:349
+msgid "Untitled - mgllab"
+msgstr ""
+
+#: udav/mem_pnl.cpp:62
+msgid "Update list of data arrays"
+msgstr ""
+
+#: mgllab/dialogs.cpp:100
+msgid "Upper border for determining color or alpha"
+msgstr ""
+
+#: utils/mglconv.cpp:85
+#, c-format
+msgid "Usage:\tmglconv [parameter(s)] scriptfile\n"
+msgstr ""
+
+#: mgllab/mgllab.cpp:416
+#, c-format
+msgid "Usage:\tmgllab [parameter(s)] scriptfile\n"
+msgstr ""
+
+#: utils/mglview.cpp:69
+#, c-format
+msgid "Usage:\tmglview [parameter(s)] scriptfile\n"
+msgstr ""
+
+#: widgets/glut.cpp:103
+#, c-format
+msgid ""
+"Use 'a', 'd', 'w', 's', 'q', 'e' for changing view angles\n"
+"Use 'j', 'l', 'i', 'k' for changing light angles\n"
+"Use 'u', 'o' for changing distance to light\n"
+"Use 'r' for switching transparency\n"
+"Use 'f' for switching lightning\n"
+"Use 'E' for exporting to EPS file\n"
+"Use 'S' for exporting to SVG file\n"
+"Use 'J' for exporting to JPEG file\n"
+"Use 'P' for exporting to PNG file\n"
+"Use ',', '.' for show other frames\n"
+"Use 'm' for view movie\n"
+"Use 'h' for view this text\n"
+"Use 'x' for exit\n"
+msgstr ""
+
+#: udav/style_dlg.cpp:162
+msgid "Use color scheme"
+msgstr ""
+
+#: udav/prop_dlg.cpp:175
+msgid "Use dots plot for preview"
+msgstr ""
+
+#: mgllab/mgllab.cpp:477
+msgid "Use multi-threading for drawing"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:67 udav/opt_dlg.cpp:68 mgllab/dialogs.cpp:101
+msgid "Value"
+msgstr ""
+
+#: mgllab/dialogs.cpp:398
+msgid "Value for i-th color"
+msgstr ""
+
+#: mgllab/dialogs.cpp:727 mgllab/dialogs.cpp:1047
+msgid "Variant"
+msgstr ""
+
+#: mgllab/dialogs.cpp:728
+msgid ""
+"Variant of command argument order. The notation is:\n"
+" * Capital arguments are data (like, Ydat);\n"
+" * Argument in '' are strings (like, 'fmt');\n"
+" * Other arguments are numbers (like, zval);\n"
+" * Arguments in [] are optional arguments."
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:170 mgllab/dialogs.cpp:711
+msgid "Vector plots"
+msgstr ""
+
+#: mgllab/dialogs.cpp:379
+msgid "Vertical align"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:55 udav/subplot_dlg.cpp:72 udav/subplot_dlg.cpp:97
+msgid "Vertical size"
+msgstr ""
+
+#. k
+#: udav/style_dlg.cpp:236 mgllab/dialogs.cpp:44
+msgid "W - lightgray"
+msgstr ""
+
+#: src/exec_dat.cpp:1615
+msgid "Wavelet transform at some direction"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:195
+msgid "Whole area"
+msgstr ""
+
+#: mgllab/mgllab.cpp:480
+msgid "Widget scheme"
+msgstr ""
+
+#: mgllab/dialogs.cpp:329
+msgid "Width"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:80
+msgid "Width of selected cells"
+msgstr ""
+
+#: src/data.cpp:1427
+#, c-format
+msgid ""
+"Widths are:\n"
+"Wa = %g\tWx = %g\tWy = %g\tWz = %g\n"
+msgstr ""
+
+#: mgllab/dialogs.cpp:348
+msgid "Wire or mesh"
+msgstr ""
+
+#: udav/style_dlg.cpp:120
+msgid "Wire or mesh plot"
+msgstr ""
+
+#: udav/style_dlg.cpp:159 mgllab/dialogs.cpp:370
+msgid "Wire style"
+msgstr ""
+
+#: src/exec_set.cpp:752
+msgid "Write current image to graphical file"
+msgstr ""
+
+#: udav/setup_dlg.cpp:48 mgllab/dialogs.cpp:950
+msgid "X axis"
+msgstr ""
+
+#: udav/setup_dlg.cpp:118
+msgid "X pos"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1065
+msgid "X position"
+msgstr ""
+
+#: udav/dat_pnl.cpp:413
+msgid "X-direction"
+msgstr ""
+
+#: udav/opt_dlg.cpp:38 mgllab/dialogs.cpp:85
+msgid "X-range"
+msgstr ""
+
+#: udav/dat_pnl.cpp:388 udav/dat_pnl.cpp:402 udav/dat_pnl.cpp:436
+msgid "X-size"
+msgstr ""
+
+#: mgllab/dialogs.cpp:568
+msgid "X-slice from"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:176
+msgid "X/Z"
+msgstr ""
+
+#: widgets/qt.cpp:1081 udav/plot_pnl.cpp:489
+msgid "XYZ"
+msgstr ""
+
+#. M
+#: udav/style_dlg.cpp:242 mgllab/dialogs.cpp:50
+msgid "Y - olive"
+msgstr ""
+
+#: udav/setup_dlg.cpp:49 mgllab/dialogs.cpp:963
+msgid "Y axis"
+msgstr ""
+
+#: udav/setup_dlg.cpp:119
+msgid "Y pos"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1066
+msgid "Y position"
+msgstr ""
+
+#: udav/dat_pnl.cpp:413
+msgid "Y-direction"
+msgstr ""
+
+#: udav/opt_dlg.cpp:41 mgllab/dialogs.cpp:89
+msgid "Y-range"
+msgstr ""
+
+#: udav/dat_pnl.cpp:388 udav/dat_pnl.cpp:402 udav/dat_pnl.cpp:436
+msgid "Y-size"
+msgstr ""
+
+#: mgllab/dialogs.cpp:571
+msgid "Y-slice from"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:180
+msgid "Y/Z"
+msgstr ""
+
+#: mgllab/help.cpp:135
+msgid "Yes"
+msgstr ""
+
+#: udav/hint_dlg.cpp:36 mgllab/help.cpp:270
+msgid ""
+"You can copy the current image to clipboard by pressing Ctrl-Shift-C. Later "
+"you can paste it directly into yours document or presentation."
+msgstr ""
+
+#: udav/hint_dlg.cpp:49 mgllab/help.cpp:283
+msgid ""
+"You can easily insert file or folder names, last fitted formula or numerical "
+"value of selection by using menu Edit|Insert."
+msgstr ""
+
+#: udav/hint_dlg.cpp:43 mgllab/help.cpp:277
+msgid ""
+"You can edit MGL file in any text editor. Also you can run it in console by "
+"help of commands: mglconv, mglview."
+msgstr ""
+
+#: udav/hint_dlg.cpp:37 mgllab/help.cpp:271
+msgid ""
+"You can export image into a set of format (EPS, SVG, PNG, JPEG) by pressing "
+"right mouse button inside image and selecting 'Export as ...'."
+msgstr ""
+
+#: udav/hint_dlg.cpp:41 mgllab/help.cpp:275
+msgid ""
+"You can put several plots in the same image by help of commands 'subplot' or "
+"'inplot'."
+msgstr ""
+
+#: udav/hint_dlg.cpp:51 mgllab/help.cpp:285
+msgid ""
+"You can put several plotting commands in the same line or in separate "
+"function, for highlighting all of them simultaneously."
+msgstr ""
+
+#: udav/hint_dlg.cpp:34 mgllab/help.cpp:268
+msgid ""
+"You can rotate/shift/zoom whole plot by mouse. Just press 'Rotate' "
+"toolbutton, click image and hold a mouse button: left button for rotation, "
+"right button for zoom/perspective, middle button for shift."
+msgstr ""
+
+#: udav/hint_dlg.cpp:39 mgllab/help.cpp:273
+msgid ""
+"You can save the parameter of animation inside MGL script by using comment "
+"started from '##a ' or '##c ' for loops."
+msgstr ""
+
+#: udav/hint_dlg.cpp:38 mgllab/help.cpp:272
+msgid ""
+"You can setup colors for script highlighting in Property dialog. Just select "
+"menu item 'Settings/Properties'."
+msgstr ""
+
+#: udav/hint_dlg.cpp:33 mgllab/help.cpp:267
+msgid ""
+"You can shift axis range by pressing middle button and moving mouse. Also, "
+"you can zoom in/out axis range by using mouse wheel."
+msgstr ""
+
+#: udav/hint_dlg.cpp:46 mgllab/help.cpp:280
+msgid ""
+"You can type arbitrary expression as input argument for data or number. In "
+"last case (for numbers), the first value of data array is used."
+msgstr ""
+
+#: udav/hint_dlg.cpp:44 mgllab/help.cpp:278
+msgid ""
+"You can use command 'once on|off' for marking the block which should be "
+"executed only once. For example, this can be the block of large data reading/"
+"creating/handling. Press F9 (or menu item 'Graphics/Reload') to re-execute "
+"this block."
+msgstr ""
+
+#: udav/hint_dlg.cpp:45 mgllab/help.cpp:279
+msgid ""
+"You can use command 'stop' for terminating script parsing. It is useful if "
+"you don't want to execute a part of script."
+msgstr ""
+
+#: udav/hint_dlg.cpp:35 mgllab/help.cpp:269
+msgid ""
+"You may quickly draw the data from file. Just use: udav 'filename.dat' in "
+"command line."
+msgstr ""
+
+#: mgllab/dialogs.cpp:1529
+msgid "You need to enter text!"
+msgstr ""
+
+#: mgllab/table.cpp:367
+msgid "You need to provide output name"
+msgstr ""
+
+#: udav/prop_dlg.cpp:285
+msgid "You need to restart UDAV for applying the changes."
+msgstr ""
+
+#: mgllab/dialogs.cpp:592
+msgid "You need to select data array"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1489
+msgid "You need to select marker!"
+msgstr ""
+
+#: mgllab/table.cpp:190 mgllab/table.cpp:364
+msgid "You need to specify direction(s)"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:378 udav/newcmd_dlg.cpp:382
+msgid "You should put text inside ' ' for argument "
+msgstr ""
+
+#: udav/anim_dlg.cpp:105
+msgid "You should select one of case"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:386
+msgid "You should specify all optional arguments before "
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:370
+msgid "You should specify required argument "
+msgstr ""
+
+#: udav/setup_dlg.cpp:50 mgllab/dialogs.cpp:976
+msgid "Z axis"
+msgstr ""
+
+#: udav/setup_dlg.cpp:120
+msgid "Z pos"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1067
+msgid "Z position"
+msgstr ""
+
+#: udav/dat_pnl.cpp:413
+msgid "Z-direction"
+msgstr ""
+
+#: udav/opt_dlg.cpp:44 mgllab/dialogs.cpp:93
+msgid "Z-range"
+msgstr ""
+
+#: udav/dat_pnl.cpp:388 udav/dat_pnl.cpp:402 udav/dat_pnl.cpp:436
+msgid "Z-size"
+msgstr ""
+
+#: mgllab/dialogs.cpp:574
+msgid "Z-slice from"
+msgstr ""
+
+#: src/exec_set.cpp:758
+msgid "Zoom axis range"
+msgstr ""
+
+#: widgets/qt.cpp:1116
+msgid "Zoom by mouse"
+msgstr ""
+
+#: widgets/qt.cpp:1215
+msgid "Zoom graphics"
+msgstr ""
+
+#: widgets/qt.cpp:1225 udav/plot_pnl.cpp:515
+msgid "Zoom in"
+msgstr ""
+
+#: widgets/qt.cpp:1227 udav/plot_pnl.cpp:518
+msgid "Zoom in graphics."
+msgstr ""
+
+#: widgets/fltk.cpp:843
+msgid "Zoom in selected region of the picture"
+msgstr ""
+
+#. t->addAction(QPixmap(":/png/help-faq.png"), _("Examples"), this, SLOT(showExamples()));
+#: udav/help_pnl.cpp:55
+msgid "Zoom in text"
+msgstr ""
+
+#: widgets/fltk.cpp:872
+msgid "Zoom in the picture"
+msgstr ""
+
+#: widgets/qt.cpp:1229 udav/plot_pnl.cpp:521
+msgid "Zoom out"
+msgstr ""
+
+#: widgets/qt.cpp:1231 udav/plot_pnl.cpp:524
+msgid "Zoom out graphics."
+msgstr ""
+
+#: udav/help_pnl.cpp:56
+msgid "Zoom out text"
+msgstr ""
+
+#: widgets/fltk.cpp:874
+msgid "Zoom out the picture"
+msgstr ""
+
+#: src/exec_set.cpp:757
+msgid "Zoom plot region"
+msgstr ""
+
+#. zooming menu
+#: widgets/qt.cpp:1214 udav/plot_pnl.cpp:502
+msgid "Zoom/move"
+msgstr ""
+
+#: udav/style_dlg.cpp:131
+msgid "above"
+msgstr ""
+
+#: mgllab/dialogs.cpp:570 mgllab/dialogs.cpp:573 mgllab/dialogs.cpp:576
+msgid "all"
+msgstr "todo"
+
+#: mgllab/dialogs.cpp:581
+msgid "along"
+msgstr "a lo largo de"
+
+#: mgllab/table.cpp:171 mgllab/table.cpp:346
+msgid "along x"
+msgstr "a lo largo de x"
+
+#: mgllab/table.cpp:172 mgllab/table.cpp:347
+msgid "along y"
+msgstr "a lo largo de y"
+
+#: mgllab/table.cpp:173 mgllab/table.cpp:348
+msgid "along z"
+msgstr "a lo largo de z"
+
+#: mgllab/dialogs.cpp:1012
+msgid "alpha"
+msgstr "alfa"
+
+#: mgllab/dialogs.cpp:1296
+msgid "and"
+msgstr "y"
+
+#: mgllab/dialogs.cpp:1456
+msgid "arc"
+msgstr "arco"
+
+#: mgllab/dialogs.cpp:1018
+msgid "arrows"
+msgstr "flechas"
+
+#: udav/setup_dlg.cpp:72 udav/style_dlg.cpp:170
+msgid "at center"
+msgstr "en el centro"
+
+#: udav/setup_dlg.cpp:72
+msgid "at maximum"
+msgstr "en el maximo"
+
+#: udav/setup_dlg.cpp:72
+msgid "at minimum"
+msgstr "en el minimo"
+
+#: udav/setup_dlg.cpp:70 mgllab/dialogs.cpp:956
+msgid "at position"
+msgstr "en la posicion"
+
+#: mgllab/dialogs.cpp:1027
+msgid "attach light"
+msgstr "vincular luz"
+
+#. mglWarnFmt
+#: src/base.cpp:229
+msgid "axis ranges are incompatible"
+msgstr ""
+
+#. w
+#: udav/style_dlg.cpp:222 mgllab/dialogs.cpp:29
+msgid "b - blue"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1019
+msgid "bars"
+msgstr ""
+
+#: widgets/qt.cpp:1071 udav/plot_pnl.cpp:478
+msgid "bitmap EPS"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1036
+msgid "both"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:189 mgllab/dialogs.cpp:1306
+msgid "bottom"
+msgstr ""
+
+#. r
+#: udav/style_dlg.cpp:225 mgllab/dialogs.cpp:32
+msgid "c - cyan"
+msgstr ""
+
+#: mgllab/dialogs.cpp:957 mgllab/dialogs.cpp:970 mgllab/dialogs.cpp:983
+#: mgllab/dialogs.cpp:996
+msgid "center"
+msgstr ""
+
+#: widgets/fltk.cpp:768
+#, c-format
+msgid "click at %g, %g, %g"
+msgstr ""
+
+#. mglWarnCnt
+#: src/base.cpp:225
+msgid "couldn't open file"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1455
+msgid "curve"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1026
+msgid "cutting"
+msgstr ""
+
+#. -----------------------------------------------------------------------------
+#: src/base.cpp:216
+msgid "data dimension(s) is incompatible"
+msgstr ""
+
+#. mglWarnDim
+#: src/base.cpp:217
+msgid "data dimension(s) is too small"
+msgstr ""
+
+#. mglWarnMem
+#: src/base.cpp:221
+msgid "data values are zero"
+msgstr ""
+
+#: udav/open_dlg.cpp:85 udav/open_dlg.cpp:144 udav/opt_dlg.cpp:63
+#: udav/opt_dlg.cpp:66 mgllab/dialogs.cpp:107 mgllab/dialogs.cpp:116
+#: mgllab/dialogs.cpp:1044
+msgid "default"
+msgstr ""
+
+#: mgllab/help.cpp:149
+msgid "dimensions"
+msgstr ""
+
+#. l
+#: udav/style_dlg.cpp:229 mgllab/dialogs.cpp:36
+msgid "e - lawngreen"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1455
+msgid "ellipse"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1017
+msgid "facenum"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1035
+msgid "factor"
+msgstr ""
+
+#. mglWarnSize
+#: src/base.cpp:228
+msgid "format is not supported for that build"
+msgstr ""
+
+#: src/canvas.cpp:33
+msgid "frame"
+msgstr ""
+
+#: udav/anim_dlg.cpp:55 mgllab/mathgl.cpp:190
+msgid "from"
+msgstr ""
+
+#. b
+#: udav/style_dlg.cpp:223 mgllab/dialogs.cpp:30
+msgid "g - lime"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1044
+msgid "glass-like"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1011
+msgid "grayscale"
+msgstr ""
+
+#. p
+#: udav/style_dlg.cpp:234 mgllab/dialogs.cpp:41
+msgid "h - gray"
+msgstr ""
+
+#: src/parser.cpp:1011
+#, c-format
+msgid "in line %ld"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1036
+msgid "increment"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1236 mgllab/dialogs.cpp:1249 mgllab/dialogs.cpp:1262
+#: mgllab/dialogs.cpp:1271 mgllab/dialogs.cpp:1280
+msgid "ind"
+msgstr ""
+
+#. h
+#: udav/style_dlg.cpp:235 mgllab/dialogs.cpp:43
+msgid "k - black"
+msgstr ""
+
+#. y
+#: udav/style_dlg.cpp:228 mgllab/dialogs.cpp:35
+msgid "l - springgreen"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1045
+msgid "lamp-like"
+msgstr ""
+
+#. vv->addSpacing(11);
+#: udav/style_dlg.cpp:169 udav/subplot_dlg.cpp:187 mgllab/dialogs.cpp:957
+#: mgllab/dialogs.cpp:970 mgllab/dialogs.cpp:983 mgllab/dialogs.cpp:996
+#: mgllab/dialogs.cpp:1304
+msgid "left"
+msgstr ""
+
+#. mglWarnOpen
+#: src/base.cpp:226
+msgid "light: ID is out of range"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1013
+msgid "lighting"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1454
+msgid "line"
+msgstr ""
+
+#. c
+#: udav/style_dlg.cpp:226 mgllab/dialogs.cpp:33
+msgid "m - magenta"
+msgstr ""
+
+#.
+#. ^
+#: udav/style_dlg.cpp:317 udav/style_dlg.cpp:356 mgllab/dialogs.cpp:209
+#: mgllab/dialogs.cpp:247
+msgid "manual"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1454
+msgid "marker"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1020
+msgid "markers"
+msgstr ""
+
+#: udav/data_dlg.cpp:68
+msgid "max"
+msgstr ""
+
+#: mgllab/help.cpp:151
+msgid "mem. usage"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1016
+msgid "meshnum"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:247
+msgid "mgl_en"
+msgstr ""
+
+#: utils/mglconv.cpp:84
+#, c-format
+msgid ""
+"mglconv convert mgl script to image file (default PNG).\n"
+"Current version is 2.%g\n"
+msgstr ""
+
+#: mgllab/mgllab.cpp:415
+#, c-format
+msgid ""
+"mgllab draw mgl script interactively.\n"
+"Current version is 2.%g\n"
+msgstr ""
+
+#: mgllab/help.cpp:78
+#, c-format
+msgid ""
+"mgllab v. 2.%g\n"
+"(c) Alexey Balakin, 2017\n"
+"http://mathgl.sf.net/"
+msgstr ""
+
+#: utils/mglview.cpp:68
+#, c-format
+msgid ""
+"mglview show plot from MGL script or MGLD file.\n"
+"Current version is 2.%g\n"
+msgstr ""
+
+#: udav/data_dlg.cpp:68
+msgid "min"
+msgstr ""
+
+#. mglWarnLow
+#: src/base.cpp:218
+msgid "minimal data value is negative"
+msgstr ""
+
+#. e
+#: udav/style_dlg.cpp:230 mgllab/dialogs.cpp:37
+msgid "n - skyblue"
+msgstr ""
+
+#: mgllab/help.cpp:147
+msgid "name"
+msgstr ""
+
+#. mglWarnNeg
+#: src/base.cpp:219
+msgid "no file or wrong data dimensions"
+msgstr ""
+
+#. mglWarnZero
+#: src/base.cpp:222
+msgid "no legend entries"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1028
+msgid "no origin tick"
+msgstr ""
+
+#. "-+=;oOsS~<>jdD*^"
+#. ".+x*sdv^<>o.*+xsdv^<>o" : nf = 10
+#: udav/style_dlg.cpp:128 udav/style_dlg.cpp:131 udav/style_dlg.cpp:134
+#: udav/style_dlg.cpp:339 udav/style_dlg.cpp:383 udav/data_dlg.cpp:67
+#: mgllab/dialogs.cpp:214 mgllab/dialogs.cpp:230 mgllab/dialogs.cpp:1035
+#: mgllab/dialogs.cpp:1039
+msgid "none"
+msgstr ""
+
+#: udav/style_dlg.cpp:220
+msgid "none or default"
+msgstr ""
+
+#. mglWarnFile
+#: src/base.cpp:220
+msgid "not enough memory"
+msgstr ""
+
+#. mglWarnNull
+#: src/base.cpp:231
+msgid "not enough space for plot"
+msgstr ""
+
+#: mgllab/table.cpp:85
+msgid "not used"
+msgstr ""
+
+#. mglWarnSlc
+#: src/base.cpp:224
+msgid "number of contours is zero or negative"
+msgstr ""
+
+#: udav/opt_dlg.cpp:63 udav/opt_dlg.cpp:66
+msgid "off"
+msgstr ""
+
+#: udav/opt_dlg.cpp:63 udav/opt_dlg.cpp:66 udav/setup_dlg.cpp:128
+msgid "on"
+msgstr ""
+
+#: udav/dat_pnl.cpp:549
+msgid "or enter name for new variable"
+msgstr ""
+
+#. q
+#: udav/style_dlg.cpp:233 mgllab/dialogs.cpp:40
+msgid "p - deeppink"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1023
+msgid "pen blur"
+msgstr ""
+
+#: mgllab/dialogs.cpp:392
+msgid "plain"
+msgstr ""
+
+#. mglWarnTern
+#: src/base.cpp:230
+msgid "pointer is NULL"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1456
+msgid "polygon"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1040
+msgid "projection"
+msgstr ""
+
+#. u
+#: udav/style_dlg.cpp:232 mgllab/dialogs.cpp:39
+msgid "q - orange"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1040
+msgid "quaternary"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1041
+msgid "quaternary proj"
+msgstr ""
+
+#. g
+#: udav/style_dlg.cpp:224 mgllab/dialogs.cpp:31
+msgid "r - red"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1454
+msgid "rectangle"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1455
+msgid "rhomb"
+msgstr ""
+
+#: udav/style_dlg.cpp:172 udav/subplot_dlg.cpp:193 mgllab/dialogs.cpp:958
+#: mgllab/dialogs.cpp:971 mgllab/dialogs.cpp:984 mgllab/dialogs.cpp:997
+#: mgllab/dialogs.cpp:1310
+msgid "right"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1029
+msgid "rotate text"
+msgstr ""
+
+#: mgllab/mathgl.cpp:197
+msgid "save slides"
+msgstr ""
+
+#. mglWarnLId
+#: src/base.cpp:227
+msgid "size(s) is zero or negative"
+msgstr ""
+
+#. mglWarnLeg
+#: src/base.cpp:223
+msgid "slice value is out of range"
+msgstr ""
+
+#: mgllab/table.cpp:144
+msgid "smoothed"
+msgstr ""
+
+#: mgllab/dialogs.cpp:326
+msgid "solid"
+msgstr ""
+
+#: widgets/qt.cpp:1069 udav/plot_pnl.cpp:476
+msgid "solid PNG"
+msgstr ""
+
+#: udav/anim_dlg.cpp:45 mgllab/mathgl.cpp:185
+msgid "strings"
+msgstr ""
+
+#: udav/data_dlg.cpp:67
+msgid "sum"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1039
+msgid "ternary"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1041
+msgid "ternary proj"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1021 mgllab/dialogs.cpp:1456
+msgid "text"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1022
+msgid "ticks"
+msgstr ""
+
+#: udav/anim_dlg.cpp:59 mgllab/mathgl.cpp:191 mgllab/dialogs.cpp:569
+#: mgllab/dialogs.cpp:572 mgllab/dialogs.cpp:575
+msgid "to"
+msgstr ""
+
+#: mgllab/mgllab.cpp:564
+msgid "to script"
+msgstr ""
+
+#: udav/subplot_dlg.cpp:191 mgllab/dialogs.cpp:1308
+msgid "top"
+msgstr ""
+
+#. n
+#: udav/style_dlg.cpp:231 mgllab/dialogs.cpp:38
+msgid "u - blueviolet"
+msgstr ""
+
+#: udav/style_dlg.cpp:131
+msgid "under"
+msgstr ""
+
+#: udav/mem_pnl.cpp:168 mgllab/help.cpp:199
+msgid "unknown"
+msgstr ""
+
+#: udav/udav_wnd.cpp:168 udav/udav_wnd.cpp:560 udav/udav_wnd.cpp:693
+msgid "untitled - UDAV"
+msgstr ""
+
+#: udav/udav_wnd.cpp:686
+msgid "untitled* - UDAV"
+msgstr ""
+
+#: mgllab/dialogs.cpp:327
+msgid "user"
+msgstr ""
+
+#: udav/anim_dlg.cpp:52 mgllab/mathgl.cpp:187
+msgid "values"
+msgstr ""
+
+#: widgets/qt.cpp:1072 udav/plot_pnl.cpp:479
+msgid "vector EPS"
+msgstr ""
+
+#.
+#: udav/style_dlg.cpp:221 mgllab/dialogs.cpp:28
+msgid "w - white"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1312
+msgid "whole area"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1471
+msgid "wire"
+msgstr ""
+
+#: udav/anim_dlg.cpp:63 mgllab/mathgl.cpp:192
+msgid "with step"
+msgstr ""
+
+#. m
+#: udav/style_dlg.cpp:227 mgllab/dialogs.cpp:34
+msgid "y - yellow"
+msgstr ""
diff --git a/mathgl_ru.po b/mathgl_ru.po
new file mode 100644
index 0000000..ee43760
--- /dev/null
+++ b/mathgl_ru.po
@@ -0,0 +1,6513 @@
+# Russian translations for MathGL2 package.
+# Copyright (C) 2017 THE MathGL2'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the MathGL2 package.
+# Alexey Balakin <mathgl.abalakin at gmail.com>, 2017.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: MathGL2 2.4.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-05-17 07:55+0300\n"
+"PO-Revision-Date: 2017-04-19 01:17+0300\n"
+"Last-Translator: Alexey Balakin <mathgl.abalakin at gmail.com>\n"
+"Language-Team: Russian\n"
+"Language: ru\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: mgllab/mgllab.cpp:417
+#, c-format
+msgid ""
+"\t-1 str       set str as argument $1 for script\n"
+"\t...          ...\n"
+"\t-9 str       set str as argument $9 for script\n"
+"\t-L loc       set locale to loc\n"
+"\t-h           print this message\n"
+msgstr ""
+"\t-1 str       установить аргумент $1 равным str\n"
+"\t...          ...\n"
+"\t-9 str       установить аргумент $9 равным str\n"
+"\t-L loc       изменить локаль на loc\n"
+"\t-h           показать справку \n"
+
+#: utils/mglconv.cpp:87
+#, c-format
+msgid ""
+"\t-1 str       set str as argument $1 for script\n"
+"\t...          ...\n"
+"\t-9 str       set str as argument $9 for script\n"
+"\t-L loc       set locale to loc\n"
+"\t-s fname     set MGL script for setting up the plot\n"
+"\t-S val       set scaling factor for images\n"
+"\t-q val       set quality for output (val=0...9)\n"
+"\t-g val       set gray-scale mode (val=0|1)\n"
+"\t-v val       set variant of arguments\n"
+"\t-o name      set output file name\n"
+"\t-n           no default output (script should save results by itself)\n"
+"\t-A val       add animation value val\n"
+"\t-C n1:n2:dn  add animation value in range [n1,n2] with step dn\n"
+"\t-C n1:n2     add animation value in range [n1,n2] with step 1\n"
+"\t-            get script from standard input\n"
+"\t-h           print this message\n"
+msgstr ""
+"\t-1 str       установить аргумент $1 равным str\n"
+"\t...          ...\n"
+"\t-9 str       установить аргумент $9 равным str\n"
+"\t-L loc       изменить локаль на loc\n"
+"\t-s fname     дополнительный скрипт с настройками графика\n"
+"\t-S val       масштабирование для рисунка\n"
+"\t-q val       качество рисунка по умолчанию (val=0...9)\n"
+"\t-g val       режим оттенков серого (val=0|1)\n"
+"\t-v val       задать вариант аргументов\n"
+"\t-o name      имя файла для сохранения рисунка\n"
+"\t-n           нет вывода по умолчанию (скрипт должен сохранить рисунок "
+"сам)\n"
+"\t-A val       добавить значение val в анимацию\n"
+"\t-C n1:n2:dn  добавить диапазон [n1,n2] с шагом dn анимацию\n"
+"\t-C n1:n2     добавить диапазон [n1,n2] с шагом 1 анимацию\n"
+"\t-            загрузить скрипт из стандартного ввода\n"
+"\t-h           показать справку\n"
+
+#: utils/mglview.cpp:71
+#, c-format
+msgid ""
+"\t-1 str       set str as argument $1 for script\n"
+"\t...          ...\n"
+"\t-9 str       set str as argument $9 for script\n"
+"\t-g val       set gray-scale mode (val=0|1)\n"
+"\t-v val       set variant of arguments\n"
+"\t-s opt       set MGL script for setting up the plot\n"
+"\t-L loc       set locale to loc\n"
+"\t-            get script from standard input\n"
+"\t-h           print this message\n"
+msgstr ""
+"\t-1 str       установить аргумент $1 равным str\n"
+"\t...          ...\n"
+"\t-9 str       установить аргумент $9 равным str\n"
+"\t-g val       режим оттенков серого (val=0|1)\n"
+"\t-v val       задать вариант аргументов\n"
+"\t-s opt       дополнительный скрипт с настройками графика\n"
+"\t-L loc       изменить локаль на loc\n"
+"\t-            загрузить скрипт из стандартного ввода\n"
+"\t-h           показать справку\n"
+
+#: widgets/qt.cpp:859
+msgid ""
+"\n"
+"(c) Alexey Balakin, 2007\n"
+"http://mathgl.sourceforge.net/"
+msgstr ""
+"\n"
+"(c) Алексей Балакин, 2007\n"
+"http://mathgl.sourceforge.net/"
+
+#: src/parser.cpp:1010
+#, c-format
+msgid ""
+"\n"
+"Change temporary data in line %ld"
+msgstr ""
+"\n"
+"Попытка изменить временные данные в строке %ld"
+
+#: src/parser.cpp:1008
+#, c-format
+msgid ""
+"\n"
+"String too long in line %ld"
+msgstr ""
+"\n"
+"Строковый аргумент слишком длинный в строке %ld"
+
+#: src/parser.cpp:1009
+#, c-format
+msgid ""
+"\n"
+"Unbalanced ' in line %ld"
+msgstr ""
+"\n"
+"Лишняя кавычка ' в строке %ld"
+
+#: src/parser.cpp:1006
+#, c-format
+msgid ""
+"\n"
+"Wrong argument(s) in line %ld"
+msgstr ""
+"\n"
+"Неправильные аргументы в строке %ld"
+
+#: src/parser.cpp:1007
+#, c-format
+msgid ""
+"\n"
+"Wrong command in line %ld"
+msgstr ""
+"\n"
+"Неправильная команда в строке %ld"
+
+#: udav/mem_pnl.cpp:136 udav/dat_pnl.cpp:153
+msgid " - UDAV preview"
+msgstr " - UDAV предпросмотр"
+
+#: udav/dat_pnl.cpp:152
+msgid " - UDAV variable"
+msgstr " - UDAV переменная"
+
+#. o = new Fl_Button(420, 400, 90, 25, _(" Refresh"));	o->callback(mem_update_cb,w);
+#. o->image(img_update);	o->align(FL_ALIGN_IMAGE_NEXT_TO_TEXT);
+#. o->tooltip(_("Refresh list of variables."));
+#: mgllab/help.cpp:176
+msgid " Del.all"
+msgstr " Удал.все"
+
+#: mgllab/help.cpp:164
+msgid " Delete"
+msgstr " Удалить"
+
+#: mgllab/help.cpp:158
+msgid " Edit"
+msgstr " Правка"
+
+#: mgllab/help.cpp:161
+msgid " Info"
+msgstr " Инфо"
+
+#: mgllab/help.cpp:167
+msgid " New"
+msgstr " Новый"
+
+#: mgllab/help.cpp:170
+msgid " Save"
+msgstr " Сохранить"
+
+#: mgllab/mgllab.cpp:227
+msgid " Yes "
+msgstr "Да"
+
+#: udav/plot_pnl.cpp:191
+#, c-format
+msgid "%d - %d of %d"
+msgstr "%d - %d из %d"
+
+#. :
+#: udav/style_dlg.cpp:316 mgllab/dialogs.cpp:208
+msgid "' ' none"
+msgstr "' ' нет"
+
+#: udav/style_dlg.cpp:397
+msgid "'#*' Y-sign"
+msgstr "'#*' знак Y"
+
+#: udav/style_dlg.cpp:398
+msgid "'#+' squared plus"
+msgstr "'#+' плюс в квадрате"
+
+#: udav/style_dlg.cpp:396
+msgid "'#.' circled dot"
+msgstr "'#.' точка в круге"
+
+#: udav/style_dlg.cpp:405
+msgid "'#<' solid triangle left"
+msgstr "'#<' треуг.влево сплошной"
+
+#: udav/style_dlg.cpp:406
+msgid "'#>' solid triangle right"
+msgstr "'#>' треуг.вправо сплошной"
+
+#: udav/style_dlg.cpp:404
+msgid "'#^' solid triangle up"
+msgstr "'#^' треуг.вверх сплошной"
+
+#: udav/style_dlg.cpp:402
+msgid "'#d' solid rhomb"
+msgstr "'#d' ромб сплошной"
+
+#: udav/style_dlg.cpp:407
+msgid "'#o' solid circle"
+msgstr "'#o' круг"
+
+#: udav/style_dlg.cpp:401
+msgid "'#s' solid square"
+msgstr "'#s' квадрат сплошной"
+
+#: udav/style_dlg.cpp:403
+msgid "'#v' solid triangle down"
+msgstr "'#v' треуг.вниз сплошной"
+
+#: udav/style_dlg.cpp:399
+msgid "'#x' squared cross"
+msgstr "'#x' крест в квадрате"
+
+#. D
+#: udav/style_dlg.cpp:354 mgllab/dialogs.cpp:245
+msgid "'*' cross"
+msgstr "'*' крест"
+
+#.
+#: udav/style_dlg.cpp:387 mgllab/dialogs.cpp:215
+msgid "'*' star"
+msgstr "'*' звезда"
+
+#. o
+#. -
+#: udav/style_dlg.cpp:341 udav/style_dlg.cpp:385 mgllab/dialogs.cpp:217
+#: mgllab/dialogs.cpp:232
+msgid "'+' plus"
+msgstr "'+' плюс"
+
+#.
+#: udav/style_dlg.cpp:340 mgllab/dialogs.cpp:231
+msgid "'-' lines"
+msgstr "'-' линии"
+
+#. "-|;=ji: "
+#: udav/style_dlg.cpp:309 mgllab/dialogs.cpp:201
+msgid "'-' solid"
+msgstr "'-' сплошная"
+
+#. d
+#: udav/style_dlg.cpp:384 mgllab/dialogs.cpp:221
+msgid "'.' dot"
+msgstr "'.' точка"
+
+#. =
+#: udav/style_dlg.cpp:315 mgllab/dialogs.cpp:207
+msgid "':' dots"
+msgstr "':' точками"
+
+#. j
+#. =
+#: udav/style_dlg.cpp:311 udav/style_dlg.cpp:343 mgllab/dialogs.cpp:204
+#: mgllab/dialogs.cpp:234
+msgid "';' dash"
+msgstr "';' пунктир"
+
+#. ~
+#: udav/style_dlg.cpp:349 mgllab/dialogs.cpp:241
+msgid "'<' left sign"
+msgstr "'<' знак влево"
+
+#. v
+#: udav/style_dlg.cpp:392 mgllab/dialogs.cpp:224
+msgid "'<' triangle left"
+msgstr "'<' треуг.влево"
+
+#. +
+#: udav/style_dlg.cpp:342 mgllab/dialogs.cpp:233
+msgid "'=' double lines"
+msgstr "'=' двойные линии"
+
+#. i
+#: udav/style_dlg.cpp:312 mgllab/dialogs.cpp:206
+msgid "'=' small dash"
+msgstr "'=' мелкий пунктир"
+
+#. <
+#: udav/style_dlg.cpp:350 mgllab/dialogs.cpp:242
+msgid "'>' right sign"
+msgstr "'>' знак вправо"
+
+#. <
+#: udav/style_dlg.cpp:393 mgllab/dialogs.cpp:225
+msgid "'>' triangle right"
+msgstr "'>' треуг.вправо"
+
+#. _
+#: udav/style_dlg.cpp:265 udav/style_dlg.cpp:288 mgllab/dialogs.cpp:188
+msgid "'A' arrow"
+msgstr "'A' стрелка"
+
+#. S
+#: udav/style_dlg.cpp:271 udav/style_dlg.cpp:294 mgllab/dialogs.cpp:194
+msgid "'D' rhomb"
+msgstr "'D' ромб"
+
+#. d
+#: udav/style_dlg.cpp:353 mgllab/dialogs.cpp:244
+msgid "'D' solid rhomb"
+msgstr "'D' ромб сплошной"
+
+#. V
+#: udav/style_dlg.cpp:267 udav/style_dlg.cpp:290 mgllab/dialogs.cpp:191
+msgid "'I' stop"
+msgstr "'I' стоп"
+
+#. A
+#: udav/style_dlg.cpp:268 udav/style_dlg.cpp:291 mgllab/dialogs.cpp:189
+msgid "'K' size"
+msgstr "'K' размер"
+
+#. D
+#: udav/style_dlg.cpp:272 udav/style_dlg.cpp:295 mgllab/dialogs.cpp:195
+msgid "'O' circle"
+msgstr "'O' круг"
+
+#. o
+#: udav/style_dlg.cpp:345 mgllab/dialogs.cpp:237
+msgid "'O' solid circle"
+msgstr "'O' круг"
+
+#. s
+#: udav/style_dlg.cpp:347 mgllab/dialogs.cpp:239
+msgid "'S' solid square"
+msgstr "'S' квадрат сплошной"
+
+#. T
+#: udav/style_dlg.cpp:270 udav/style_dlg.cpp:293 mgllab/dialogs.cpp:193
+msgid "'S' square"
+msgstr "'S' квадрат"
+
+#. I
+#: udav/style_dlg.cpp:269 udav/style_dlg.cpp:292 mgllab/dialogs.cpp:192
+msgid "'T' triangle"
+msgstr "'T' треугольник"
+
+#. K
+#: udav/style_dlg.cpp:266 udav/style_dlg.cpp:289 mgllab/dialogs.cpp:190
+msgid "'V' back arrow"
+msgstr "'V' обр.стрелка"
+
+#. O
+#: mgllab/dialogs.cpp:196
+msgid "'X' cross"
+msgstr "'X' крест"
+
+#. *
+#: udav/style_dlg.cpp:355 mgllab/dialogs.cpp:246
+msgid "'^' hats"
+msgstr "'^' шляпы"
+
+#. .
+#: udav/style_dlg.cpp:391 mgllab/dialogs.cpp:222
+msgid "'^' triangle up"
+msgstr "'^' треуг.вверх"
+
+#. "AVIKTSDO"
+#: udav/style_dlg.cpp:264 udav/style_dlg.cpp:287 mgllab/dialogs.cpp:187
+msgid "'_' none"
+msgstr "'_' нет"
+
+#. s
+#. >
+#: udav/style_dlg.cpp:352 udav/style_dlg.cpp:389 mgllab/dialogs.cpp:220
+#: mgllab/dialogs.cpp:243
+msgid "'d' rhomb"
+msgstr "'d' ромб"
+
+#. ;
+#: udav/style_dlg.cpp:314 mgllab/dialogs.cpp:205
+msgid "'i' small dash dot"
+msgstr "'i' точка-пунктир"
+
+#. |
+#. ;
+#: udav/style_dlg.cpp:313 udav/style_dlg.cpp:351 mgllab/dialogs.cpp:203
+#: mgllab/dialogs.cpp:235
+msgid "'j' dash dot"
+msgstr "'j' точка-штрих"
+
+#. *
+#. j
+#: udav/style_dlg.cpp:344 udav/style_dlg.cpp:394 mgllab/dialogs.cpp:216
+#: mgllab/dialogs.cpp:236
+msgid "'o' circle"
+msgstr "'o' окружность"
+
+#. x
+#. O
+#: udav/style_dlg.cpp:346 udav/style_dlg.cpp:388 mgllab/dialogs.cpp:219
+#: mgllab/dialogs.cpp:238
+msgid "'s' square"
+msgstr "'s' квадрат"
+
+#. ^
+#: udav/style_dlg.cpp:390 mgllab/dialogs.cpp:223
+msgid "'v' triangle down"
+msgstr "'v' треуг.вниз"
+
+#. +
+#: udav/style_dlg.cpp:386 mgllab/dialogs.cpp:218
+msgid "'x' skew cross"
+msgstr "'x' косой крест"
+
+#. -
+#: udav/style_dlg.cpp:310 mgllab/dialogs.cpp:202
+msgid "'|' long dash"
+msgstr "'|' штрихи"
+
+#. S
+#: udav/style_dlg.cpp:348 mgllab/dialogs.cpp:240
+msgid "'~' waves"
+msgstr "'~' волны"
+
+#: src/parser.cpp:51
+msgid "0 - special plot"
+msgstr "0 - специальные графики"
+
+#: src/parser.cpp:51
+msgid "1 - other plot"
+msgstr "1 - прочие графики"
+
+#: src/parser.cpp:51
+msgid "10 - dd plot"
+msgstr "10 - двойный графики"
+
+#: src/parser.cpp:51
+msgid "11 - vector plot"
+msgstr "11 - векторные графики"
+
+#: src/parser.cpp:51
+msgid "12 - axis"
+msgstr "12 - оси координат"
+
+#: src/parser.cpp:51
+msgid "13 - primitives"
+msgstr "13 - примитивы"
+
+#: src/parser.cpp:51
+msgid "14 - axis setup"
+msgstr "14 - настройка осей"
+
+#: src/parser.cpp:51
+msgid "15 - text/legend"
+msgstr "15 - текст/легенда"
+
+#: src/parser.cpp:51
+msgid "16 - data transform"
+msgstr "16 - преобразования данных"
+
+#: udav/info_dlg.cpp:47
+msgid "1D plot"
+msgstr "1D график"
+
+#: udav/newcmd_dlg.cpp:166 mgllab/dialogs.cpp:707
+msgid "1D plots"
+msgstr "1D графики"
+
+#: mgllab/help.cpp:359
+msgid "1D view"
+msgstr "1D вид"
+
+#: src/parser.cpp:51
+msgid "2 - setup"
+msgstr "2 - настройки"
+
+#: udav/info_dlg.cpp:47
+msgid "2D plot"
+msgstr "2D график"
+
+#: udav/newcmd_dlg.cpp:167 mgllab/dialogs.cpp:708
+msgid "2D plots"
+msgstr "2D графики"
+
+#: mgllab/help.cpp:361
+msgid "2D view"
+msgstr "2D вид"
+
+#: src/parser.cpp:51
+msgid "3 - data handle"
+msgstr "3 - изменение данных"
+
+#: udav/open_dlg.cpp:71
+msgid "3D data with sizes from file"
+msgstr "3D данные с размерами из файла"
+
+#: udav/newcmd_dlg.cpp:168 mgllab/dialogs.cpp:709
+msgid "3D plots"
+msgstr "3D графики"
+
+#: mgllab/help.cpp:363
+msgid "3D view"
+msgstr "3D вид"
+
+#: src/parser.cpp:51
+msgid "4 - data create"
+msgstr "4 - создание данных"
+
+#: src/parser.cpp:51
+msgid "5 - subplot"
+msgstr "5 - картинка в картинке"
+
+#: src/parser.cpp:51
+msgid "6 - program flow"
+msgstr "6 - команды управления"
+
+#: src/parser.cpp:51
+msgid "7 - 1d plot"
+msgstr "7 - 1D графики"
+
+#: src/parser.cpp:51
+msgid "8 - 2d plot"
+msgstr "8 - 2D графики"
+
+#: src/parser.cpp:51
+msgid "9 - 3d plot"
+msgstr "9 - 3D графики"
+
+#: udav/udav_wnd.cpp:455
+msgid ""
+"<br>(c) Alexey Balakin, 2007-present<br><br><a href='http://www.gnu.org/"
+"copyleft/gpl.html'>License is GPL v.2 or later.</a>"
+msgstr ""
+"<br>(c) Алексей Балакин, 2007-наст.вр.<br><br><a href='http://www.gnu.org/"
+"copyleft/gpl.html'>Лицензия GPL v.2 или более поздняя.</a>"
+
+#: mgllab/help.cpp:304
+msgid "@<-  Prev"
+msgstr "@<-  Пред."
+
+#: widgets/qt.cpp:1277 udav/udav_wnd.cpp:331 mgllab/mgllab.cpp:332
+msgid "About"
+msgstr "О программе"
+
+#. -----------------------------------------------------------------------------
+#: widgets/qt.cpp:863 widgets/qt.cpp:1278 udav/udav_wnd.cpp:332
+#: udav/udav_wnd.cpp:460
+msgid "About Qt"
+msgstr "О версии Qt"
+
+#: widgets/qt.cpp:1156 udav/plot_pnl.cpp:372
+msgid "Add arc"
+msgstr "Добавить дугу"
+
+#: widgets/qt.cpp:1159 udav/plot_pnl.cpp:375
+msgid "Add arc which properties can be changed later by mouse."
+msgstr "Добавить дугу. Ее свойства можно изменить позже мышью."
+
+#: mgllab/dialogs.cpp:84
+msgid "Add command option(s)"
+msgstr "Добавить опции команды"
+
+#: widgets/qt.cpp:1161 udav/plot_pnl.cpp:378
+msgid "Add curve"
+msgstr "Добавить кривую"
+
+#: widgets/qt.cpp:1164 udav/plot_pnl.cpp:381
+msgid "Add curve which properties can be changed later by mouse."
+msgstr "Добавить кривую. Ее свойства можно изменить позже мышью."
+
+#: src/exec_dat.cpp:1523
+msgid "Add data or number"
+msgstr "Прибавить массив или число"
+
+#: widgets/qt.cpp:1176 udav/plot_pnl.cpp:396
+msgid "Add ellipse"
+msgstr "Добавить эллипс"
+
+#: widgets/qt.cpp:1179 udav/plot_pnl.cpp:399 udav/plot_pnl.cpp:405
+msgid "Add ellipse which properties can be changed later by mouse."
+msgstr "Добавить эллипс. Его свойства можно изменить позже мышью."
+
+#: mgllab/dialogs.cpp:1229
+msgid "Add inplot"
+msgstr "Добавить под-график"
+
+#: src/exec_set.cpp:690
+msgid "Add legend entry"
+msgstr "Добавить запись легенды"
+
+#: mgllab/dialogs.cpp:119
+msgid "Add legend entry for the plot"
+msgstr "Добавить запись легенды для графика"
+
+#: widgets/qt.cpp:1151 udav/plot_pnl.cpp:366
+msgid "Add line"
+msgstr "Добавить линию"
+
+#: widgets/qt.cpp:1154 udav/plot_pnl.cpp:369
+msgid "Add line which properties can be changed later by mouse."
+msgstr "Добавить линию. Ее свойства можно изменить позже мышью."
+
+#: widgets/qt.cpp:1186 udav/plot_pnl.cpp:408
+msgid "Add mark"
+msgstr "Добавить маркер"
+
+#: widgets/qt.cpp:1189 udav/plot_pnl.cpp:411
+msgid "Add marker which properties can be changed later by mouse."
+msgstr "Добавить маркер. Его свойства можно изменить позже мышью."
+
+#: widgets/qt.cpp:1181 udav/plot_pnl.cpp:402
+msgid "Add polygon"
+msgstr "Добавить полигон"
+
+#: widgets/qt.cpp:1184
+msgid "Add polygon which properties can be changed later by mouse."
+msgstr "Добавить полигон. Его свойства можно изменить позже мышью."
+
+#: mgllab/dialogs.cpp:1453
+msgid "Add primitive"
+msgstr "Добавить примитивы"
+
+#: widgets/qt.cpp:1166 udav/plot_pnl.cpp:384
+msgid "Add rect"
+msgstr "Добавить прямоугольник"
+
+#: widgets/qt.cpp:1169 udav/plot_pnl.cpp:387
+msgid "Add rectangle which properties can be changed later by mouse."
+msgstr "Добавить прямоугольник. Его свойства можно изменить позже мышью."
+
+#: widgets/qt.cpp:1171 udav/plot_pnl.cpp:390
+msgid "Add rhombus"
+msgstr "Добавить ромб"
+
+#: widgets/qt.cpp:1174 udav/plot_pnl.cpp:393
+msgid "Add rhombus which properties can be changed later by mouse."
+msgstr "Добавить ромб. Его свойства можно изменить позже мышью."
+
+#: widgets/qt.cpp:1191 udav/plot_pnl.cpp:414
+msgid "Add text"
+msgstr "Добавить текст"
+
+#: widgets/qt.cpp:1194 udav/plot_pnl.cpp:417
+msgid "Add text which properties can be changed later by mouse."
+msgstr "Добавить текст. Его свойства можно изменить позже мышью."
+
+#: src/exec_prm.cpp:611
+msgid "Add title for current subplot/inplot"
+msgstr "Добавить заголовок к текущему под-графику"
+
+#: mgllab/table.cpp:794
+msgid "Add to"
+msgstr "Добавить к"
+
+#: src/exec_set.cpp:691
+msgid "Add user-defined symbol"
+msgstr "Добавить пользовательский символ"
+
+#: widgets/fltk.cpp:851
+msgid "Adjust picture size to fill drawing area"
+msgstr "Подогнать размер картинки под область окна"
+
+#: widgets/fltk.cpp:814 widgets/qt.cpp:1139 udav/plot_pnl.cpp:337
+msgid "Adjust size"
+msgstr "Подогнать размер"
+
+#: src/exec_set.cpp:692
+msgid "Adjust ticks for best view"
+msgstr "Подобрать метки осей для лучшего вида"
+
+#: udav/calc_dlg.cpp:193
+msgid "Airy and Gamma"
+msgstr "Эйри и Гамма"
+
+#: udav/hint_dlg.cpp:42 mgllab/help.cpp:276
+msgid ""
+"All indexes (of data arrays, subplots and so on) are always start from 0."
+msgstr "Все индексы (данных, под-графиков и пр.) всегда начинаются с 0."
+
+#. graphics menu
+#: widgets/qt.cpp:1098 udav/opt_dlg.cpp:51 udav/setup_dlg.cpp:109
+#: udav/plot_pnl.cpp:290 mgllab/dialogs.cpp:109
+msgid "Alpha"
+msgstr ""
+
+#: mgllab/dialogs.cpp:110
+msgid "Alpha value (transparency) of surface or cloud"
+msgstr "Значение прозрачности для поверхностей и облаков"
+
+#: udav/setup_dlg.cpp:93 mgllab/dialogs.cpp:1003
+msgid "AlphaDef"
+msgstr ""
+
+#: udav/opt_dlg.cpp:56 udav/setup_dlg.cpp:95 mgllab/dialogs.cpp:111
+#: mgllab/dialogs.cpp:1004
+msgid "Ambient"
+msgstr "Фон.свет"
+
+#: udav/subplot_dlg.cpp:167
+msgid "Angle around x axis (in degrees)"
+msgstr "Угол относительно оси x (в градусах)"
+
+#: udav/subplot_dlg.cpp:171
+msgid "Angle around z axis (in degrees)"
+msgstr "Угол относительно оси z (в градусах)"
+
+#. animation menu
+#: widgets/qt.cpp:1244 widgets/qt.cpp:1245 udav/plot_pnl.cpp:559
+#: mgllab/mathgl.cpp:183
+msgid "Animation"
+msgstr "Анимация"
+
+#: mgllab/table.cpp:786
+msgid "Another"
+msgstr "Другой"
+
+#: mgllab/table.cpp:852
+msgid "Apply operator (smoothing, integration, difference ...) to data"
+msgstr ""
+"Применить к данным оператор (сглаживание, интегрирование, дифференцирование "
+"и пр.)"
+
+#: mgllab/dialogs.cpp:103
+msgid "Approximate number of mesh lines in plot"
+msgstr "Примерное число линий сетки на графике"
+
+#: mgllab/help.cpp:135
+msgid "Are you sure that you want to delete ALL data arrays?"
+msgstr "Вы уверены, что хотите удалит ВСЕ данные?"
+
+#: udav/newcmd_dlg.cpp:67
+msgid "Argument"
+msgstr "Аргумент"
+
+#: mgllab/dialogs.cpp:738
+msgid "Arguments"
+msgstr "Аргументы"
+
+#: udav/style_dlg.cpp:63 mgllab/dialogs.cpp:321
+msgid "Arrow at end"
+msgstr "Стрелка кон."
+
+#. g->setColStretch(0, 1);	g->setColStretch(1, 1);	g->setColStretch(2, 1);
+#: udav/style_dlg.cpp:61 mgllab/dialogs.cpp:315
+msgid "Arrow at start"
+msgstr "Стрелка нач."
+
+#: widgets/qt.cpp:1137
+msgid "Ask to stop plot drawing (F7)."
+msgstr "Запрос на остановку рисования (F7)"
+
+#: udav/subplot_dlg.cpp:175
+msgid "Aspect"
+msgstr "Соотношение сторон"
+
+#: udav/subplot_dlg.cpp:178
+msgid "Aspect ratio of x-scale to z-scale"
+msgstr "Соотношение сторон по x и z"
+
+#: udav/subplot_dlg.cpp:182
+msgid "Aspect ratio of y-scale to z-scale"
+msgstr "Соотношение сторон по y и z"
+
+#: mgllab/dialogs.cpp:1298
+msgid "Aspect x/z"
+msgstr "Стороны x/z"
+
+#: src/exec_set.cpp:698
+msgid "Attach light settings to inplot"
+msgstr "Привязать настройки света к под-графику"
+
+#: udav/open_dlg.cpp:60
+msgid "Auto detect data sizes"
+msgstr "Автоматически определят размер данных"
+
+#: udav/open_dlg.cpp:177
+msgid "Auto detect data sizes (%1 x %2 x %3)"
+msgstr "Автоматически определят размер данных (%1 x %2 x %3)"
+
+#: udav/prop_dlg.cpp:100
+msgid "AutoKey"
+msgstr ""
+
+#: udav/prop_dlg.cpp:159
+msgid "Automatically execute script after loading"
+msgstr "Выполнить скрипт после загрузки"
+
+#: udav/prop_dlg.cpp:165
+msgid "Automatically save before redrawing (F5)"
+msgstr "Сохранять скрипт перед рисованием (F5)"
+
+#: src/data.cpp:1425
+#, c-format
+msgid ""
+"Averages are:\n"
+"<a> = %g\t<x> = %g\t<y> = %g\t<z> = %g\n"
+msgstr "Средние: <a> = %g\t<x> = %g\t<y> = %g\t<z> = %g\n"
+
+#: udav/style_dlg.cpp:122 mgllab/dialogs.cpp:340
+msgid "Axial direction"
+msgstr "Ось вращения"
+
+#: udav/setup_dlg.cpp:101
+msgid "AxialDir"
+msgstr "Ось вращ."
+
+#: mgllab/dialogs.cpp:1008
+msgid "Axis"
+msgstr "Оси"
+
+#: udav/newcmd_dlg.cpp:176 mgllab/dialogs.cpp:717
+msgid "Axis and colorbar"
+msgstr "Оси и цв.шкала"
+
+#: udav/newcmd_dlg.cpp:177 mgllab/dialogs.cpp:718 mgllab/dialogs.cpp:949
+msgid "Axis setup"
+msgstr "Настройка осей"
+
+#. W
+#: udav/style_dlg.cpp:237 mgllab/dialogs.cpp:45
+msgid "B - navy"
+msgstr "B - темно-синий"
+
+#: udav/help_pnl.cpp:48
+msgid "Backward"
+msgstr "Назад"
+
+#: src/font.cpp:947
+#, c-format
+msgid "Bad '%ls' at %zu\n"
+msgstr "Неправильный '%ls' при %zu\n"
+
+#: src/parser.cpp:766
+#, c-format
+msgid "Bad arguments for %ls: %ld instead of %d\n"
+msgstr "Неправильные аргументы для %ls: %ld вместо %d\n"
+
+#: udav/setup_dlg.cpp:97
+msgid "BaseWidth"
+msgstr "Баз.Ширина"
+
+#: udav/calc_dlg.cpp:192
+msgid "Basic"
+msgstr "Базовые"
+
+#: mgllab/dialogs.cpp:1461
+msgid "Begin"
+msgstr "Начало"
+
+#: udav/calc_dlg.cpp:193
+msgid "Bessel"
+msgstr "Бессель"
+
+#: udav/style_dlg.cpp:157 mgllab/dialogs.cpp:368
+msgid "Bold style"
+msgstr "Жирный шрифт"
+
+#: udav/opt_dlg.cpp:115
+msgid "Both fields in crange must be filled"
+msgstr "Оба поля в crange должны быть заполнены"
+
+#: udav/opt_dlg.cpp:94
+msgid "Both fields in xrange must be filled"
+msgstr "Оба поля в xrange должны быть заполнены"
+
+#: udav/opt_dlg.cpp:101
+msgid "Both fields in yrange must be filled"
+msgstr "Оба поля в yrange должны быть заполнены"
+
+#: udav/opt_dlg.cpp:108
+msgid "Both fields in zrange must be filled"
+msgstr "Оба поля в zrange должны быть заполнены"
+
+#: src/parser.cpp:1423
+msgid "Break for-loop"
+msgstr "Прервать выполнение цикла for"
+
+#: udav/setup_dlg.cpp:122 mgllab/dialogs.cpp:1069
+msgid "Brightness"
+msgstr "Яркость"
+
+#: mgllab/dialogs.cpp:401
+msgid "Brightness of i-th color"
+msgstr "Яркость i-го цвета"
+
+#: mgllab/table.cpp:766
+msgid "By formula"
+msgstr "По формуле"
+
+#. R
+#: udav/style_dlg.cpp:240 mgllab/dialogs.cpp:48
+msgid "C - teal"
+msgstr "C - бирюзовый"
+
+#: udav/setup_dlg.cpp:51 mgllab/dialogs.cpp:989
+msgid "C axis"
+msgstr "Цв. ось"
+
+#: udav/opt_dlg.cpp:47 mgllab/dialogs.cpp:97
+msgid "C-range"
+msgstr "Цв.диапазон"
+
+#: widgets/qt.cpp:1263
+msgid "Calculations"
+msgstr "Вычисления"
+
+#. TODO
+#. connect(hidden,SIGNAL(cursorPositionChanged()),this,SLOT(hiddenClicked()));
+#: udav/udav_wnd.cpp:194 udav/udav_wnd.cpp:206 mgllab/mgllab.cpp:326
+#: mgllab/mgllab.cpp:557
+msgid "Calculator"
+msgstr "Калькулятор"
+
+#: udav/anim_dlg.cpp:67 udav/prop_dlg.cpp:180 udav/args_dlg.cpp:63
+#: udav/newcmd_dlg.cpp:78 udav/open_dlg.cpp:90 udav/dat_pnl.cpp:460
+#: udav/dat_pnl.cpp:510 udav/dat_pnl.cpp:552 udav/dat_pnl.cpp:629
+#: udav/opt_dlg.cpp:78 udav/setup_dlg.cpp:145 udav/files_dlg.cpp:58
+#: udav/style_dlg.cpp:206 udav/data_dlg.cpp:90 udav/subplot_dlg.cpp:219
+#: mgllab/editor.cpp:282 mgllab/mathgl.cpp:164 mgllab/mathgl.cpp:195
+#: mgllab/dialogs.cpp:120 mgllab/dialogs.cpp:164 mgllab/dialogs.cpp:410
+#: mgllab/dialogs.cpp:584 mgllab/dialogs.cpp:749 mgllab/dialogs.cpp:1071
+#: mgllab/dialogs.cpp:1318 mgllab/dialogs.cpp:1473 mgllab/mgllab.cpp:482
+#: mgllab/table.cpp:101 mgllab/table.cpp:179 mgllab/table.cpp:353
+#: mgllab/table.cpp:556 mgllab/table.cpp:619 mgllab/table.cpp:674
+msgid "Cancel"
+msgstr "Отмена"
+
+#: src/crust.cpp:557
+msgid "Cannot triangulate this set!"
+msgstr "Не могу построить триангуляцию!"
+
+#: udav/udav_wnd.cpp:226 mgllab/mgllab.cpp:355 mgllab/mgllab.cpp:356
+msgid "Canvas"
+msgstr "График"
+
+#: udav/subplot_dlg.cpp:59 udav/subplot_dlg.cpp:101 udav/subplot_dlg.cpp:118
+#: udav/subplot_dlg.cpp:135
+msgid "Cell index"
+msgstr "Индекс ячейки"
+
+#: mgllab/table.cpp:103 mgllab/table.cpp:558 mgllab/table.cpp:770
+msgid "Change"
+msgstr "Изменить"
+
+#: mgllab/table.cpp:104
+msgid "Change (resize) data"
+msgstr "Изменить размер данных"
+
+#: widgets/qt.cpp:1141 udav/plot_pnl.cpp:339
+msgid "Change canvas size to fill whole region (F6)."
+msgstr "Подогнать размер рисунка под размер окна (F6)."
+
+#: src/exec_set.cpp:702
+msgid "Change current directory"
+msgstr "Сменить директорию"
+
+#: mgllab/table.cpp:168
+msgid "Change data"
+msgstr "Изменить данные"
+
+#: mgllab/table.cpp:91
+msgid "Change data sizes"
+msgstr "Изменить размер данных"
+
+#: mgllab/table.cpp:559 mgllab/table.cpp:622 mgllab/table.cpp:677
+msgid "Change data values and close this window"
+msgstr "Изменить данные и закрыть окно"
+
+#: udav/prop_dlg.cpp:71
+msgid "Change font"
+msgstr "Изменить шрифт"
+
+#: src/exec_set.cpp:751
+msgid "Change view angles - use 'rotate' for plot rotation"
+msgstr "Изменяет углы обзора, а не поворот как 'rotate'"
+
+#: udav/calc_dlg.cpp:68
+msgid "Clear"
+msgstr "Очистить"
+
+#: udav/text_pnl.cpp:527
+msgid "Clear all"
+msgstr "Удалить все"
+
+#: src/exec_set.cpp:703
+msgid "Clear legend entries"
+msgstr "Удалить записи легенды"
+
+#: src/exec_set.cpp:704
+msgid "Clear picture"
+msgstr "Очистить рисунок"
+
+#. o = new Fl_Button(180, 130, 25, 25);o->image(img_save);	o->tooltip("img_save");
+#: widgets/qt.cpp:1091 udav/find_dlg.cpp:52 udav/hint_dlg.cpp:70
+#: mgllab/editor.cpp:565 mgllab/help.cpp:308 mgllab/help.cpp:367
+#: mgllab/help.cpp:483
+msgid "Close"
+msgstr "Закрыть"
+
+#: udav/dat_pnl.cpp:833
+msgid "Close tab"
+msgstr "Закрыть вкладку"
+
+#: udav/dat_pnl.cpp:835
+msgid "Close this data tab."
+msgstr "Закрыть вкладку с данными"
+
+#: udav/setup_dlg.cpp:121 udav/style_dlg.cpp:67 mgllab/dialogs.cpp:1068
+#: mgllab/dialogs.cpp:1459
+msgid "Color"
+msgstr "Цвет"
+
+#. g->setColStretch(0, 1);			g->setColStretch(1, 1);
+#: udav/style_dlg.cpp:106
+msgid "Color order"
+msgstr "Порядок цветов"
+
+#: udav/style_dlg.cpp:150 mgllab/dialogs.cpp:339
+msgid "Color scheme"
+msgstr "Цветовая схема"
+
+#: mgllab/dialogs.cpp:384
+msgid "Color(s) or color scheme"
+msgstr "Цвет(а) или цветовая схема"
+
+#: mgllab/dialogs.cpp:1002
+msgid "Colors"
+msgstr "Цвета"
+
+#: mgllab/table.cpp:879
+msgid ""
+"Colors denote values: magenta - local max, cyan - local min,\n"
+"\tred - Re(v)>0, blue - Re(v)<0, purple - Im(v)>0, teal - Im(v)<0."
+msgstr ""
+"Цветом выделены значения: фуксия - лок.максимум, голубой - лок.минимум,\n"
+"\tкрасный - Re(v)>0, синий - Re(v)<0, пурпурный - Im(v)>0, бирюзовый - "
+"Im(v)<0."
+
+#: mgllab/dialogs.cpp:577
+msgid "Column expr"
+msgstr ""
+
+#: mgllab/dialogs.cpp:724 mgllab/mgllab.cpp:305
+msgid "Command"
+msgstr "Команда"
+
+#: udav/newcmd_dlg.cpp:64 mgllab/dialogs.cpp:740
+msgid ""
+"Command arguments. Bold ones are required arguments.\n"
+"Other are optional arguments but its order is required.\n"
+"You can use '' for default format. See help at right\n"
+"for default values."
+msgstr ""
+"Аргументы команды. Жирным обозначены обязательные аргументы.\n"
+"Прочие - опциональные, но их порядок фиксирован.\n"
+"Можно использовать '' для стиля по умолчанию.\n"
+"См. справку справа для значений по умолчанию."
+
+#: udav/text_pnl.cpp:575
+msgid "Command options"
+msgstr "Опции команды"
+
+#: udav/prop_dlg.cpp:82
+msgid "Comments"
+msgstr "Комментарий"
+
+#: src/exec_prm.cpp:599
+msgid "Computes the attractor of an IFS"
+msgstr "Вычисляет точки фрактала IFS"
+
+#: src/exec_prm.cpp:600
+msgid "Computes the attractor of an IFS for 3d case"
+msgstr "Вычисляет точки фрактала IFS в 3d случае"
+
+#: src/exec_prm.cpp:601
+msgid "Computes the attractor of an IFS with parameters from *.ifs file"
+msgstr "Вычисляет точки фрактала IFS с параметрами из файла"
+
+#: src/exec_prm.cpp:595
+msgid "Computes the flame fractal"
+msgstr "Вычисляет точки фрактала flame"
+
+#: src/parser.cpp:1431 src/parser.cpp:1435
+msgid "Conditional operator"
+msgstr "Условный оператор"
+
+#: udav/plot_pnl.cpp:358
+msgid "Copy click coor."
+msgstr "Копировать коор. мыши"
+
+#: udav/plot_pnl.cpp:360
+msgid "Copy coordinates of last mouse click to clipboard."
+msgstr "Копировать координаты последнего нажатия в буфер обмена"
+
+#: udav/dat_pnl.cpp:707
+msgid "Copy data"
+msgstr "Копировать данные"
+
+#: src/exec_dat.cpp:1528
+msgid "Copy data from another variable"
+msgstr "Копировать данные из другой переменной"
+
+#: widgets/fltk.cpp:811
+msgid "Copy graphics"
+msgstr "Копировать рисунок"
+
+#: widgets/qt.cpp:1145 udav/plot_pnl.cpp:354
+msgid "Copy graphics to clipboard (Ctrl+Shift+G)."
+msgstr "Копировать рисунок в буфер обмена (Ctrl+Shift+G)."
+
+#: widgets/fltk.cpp:855
+msgid "Copy image to clipboard"
+msgstr "Копировать рисунок в буфер обмена"
+
+#: widgets/qt.cpp:1143 udav/plot_pnl.cpp:352
+msgid "Copy plot"
+msgstr "Копировать рисунок"
+
+#: udav/dat_pnl.cpp:709
+msgid "Copy range of numbers to clipboard (Ctrl+Shift+C)."
+msgstr "Копировать диапазон чисел в буфер обмена (Ctrl+Shift+C)."
+
+#: udav/text_pnl.cpp:535
+msgid "Copy selected text or data to clipboard (Ctrl+C)."
+msgstr "Копировать выделенный текст или данные в буфер обмена (Ctrl+C)."
+
+#: mgllab/editor.cpp:511
+msgid "Copy selection to clipboard"
+msgstr "Копировать выделение в буфер обмена"
+
+#: udav/text_pnl.cpp:533 mgllab/mgllab.cpp:295
+msgid "Copy text"
+msgstr "Копировать текст"
+
+#: mgllab/table.cpp:778
+msgid "Cos FFT"
+msgstr "Косинус-Фурье"
+
+#: udav/dat_pnl.cpp:621
+msgid "Cos-Fourier transform along direction(s)"
+msgstr "Косинус-Фурье преобразование вдоль направления(й)"
+
+#: src/exec_dat.cpp:1530
+msgid "Cos-Fourier transform at some direction"
+msgstr "Косинус-Фурье преобразование вдоль направления"
+
+#: mgllab/table.cpp:165
+msgid "Cosine FFT"
+msgstr "Косинус-Фурье"
+
+#: udav/text_pnl.cpp:365 udav/text_pnl.cpp:482
+msgid "Could not write to %1"
+msgstr "Не могу записать в %1"
+
+#: udav/setup_dlg.cpp:159
+msgid "Could not write to file"
+msgstr "Не могу записать в файл"
+
+#: udav/udav_wnd.cpp:570
+msgid "Couldn't change to folder "
+msgstr "Не могу сменить папку "
+
+#: udav/text_pnl.cpp:431
+msgid "Couldn't open file "
+msgstr "Не могу открыть файл "
+
+#: mgllab/dialogs.cpp:1190
+#, c-format
+msgid "Couldn't open file %s"
+msgstr "Не могу открыть файл %s"
+
+#: udav/newcmd_dlg.cpp:173
+msgid "Create data and I/O"
+msgstr "Создание данных и I/O"
+
+#: mgllab/dialogs.cpp:714
+msgid "Create data and IO"
+msgstr "Создание данных и ввод-вывод"
+
+#: src/exec_dat.cpp:1555
+msgid "Create histogram (distribution) of data values"
+msgstr "Создать гистограмму (распределение) значений данных"
+
+#: udav/dat_pnl.cpp:766 mgllab/table.cpp:758
+msgid "Create new"
+msgstr "Создать новый"
+
+#: src/exec_dat.cpp:1614
+msgid "Create new 1D data and fill it in range"
+msgstr "Создать новые 1d данные и заполнить их в диапазоне"
+
+#: src/exec_dat.cpp:1570
+msgid "Create new data"
+msgstr "Создать новый массив данных"
+
+#: udav/mem_pnl.cpp:58
+msgid "Create new data array"
+msgstr "Создать новый массив данных"
+
+#: mgllab/table.cpp:836
+msgid "Create new data with zero filling"
+msgstr "Создать новый массив данных, заполненный нулями"
+
+#: udav/udav_wnd.cpp:284
+msgid "Create new empty script window (Ctrl+N)."
+msgstr "Создать новое окно скрипта (Ctrl+N)."
+
+#: src/parser.cpp:1436
+msgid "Creates new variable from list of numbers or data"
+msgstr "Создать новый массив из списка значений или данных"
+
+#: udav/dat_pnl.cpp:784 mgllab/table.cpp:761
+msgid "Crop"
+msgstr "Обрезать"
+
+#: mgllab/table.cpp:858
+msgid "Crop (cut off edges) data"
+msgstr "Обрезать края массива данных"
+
+#: mgllab/table.cpp:607
+msgid "Crop data"
+msgstr "Обрезать данные"
+
+#: src/exec_dat.cpp:1531
+msgid "Crop edge of data"
+msgstr "Обрезать края массива данных"
+
+#: udav/dat_pnl.cpp:786
+msgid "Crop the data edges. Useful to cut off the zero-filled area."
+msgstr ""
+"Обрезать края массива данных. Полезно для удаления краев заполненных нулями."
+
+#: mgllab/table.cpp:163 mgllab/table.cpp:772
+msgid "CumSum"
+msgstr ""
+
+#: src/exec_dat.cpp:1532
+msgid "Cumulative summation along direction(s)"
+msgstr "Накопительное суммирование данных по направлению"
+
+#: udav/prop_dlg.cpp:106
+msgid "CurrLine"
+msgstr "Тек.строка"
+
+#: udav/prop_dlg.cpp:68
+msgid "Current font"
+msgstr "Текущий шрифт"
+
+#: udav/text_pnl.cpp:530
+msgid "Cut selected text to clipboard (Ctrl+X)."
+msgstr "Вырезать выбранный текст в буфер обмена (Ctrl+X)."
+
+#: udav/text_pnl.cpp:528 mgllab/mgllab.cpp:294
+msgid "Cut text"
+msgstr "Вырезать текст"
+
+#: udav/opt_dlg.cpp:61 mgllab/dialogs.cpp:106
+msgid "Cutting"
+msgstr "Обрезание"
+
+#: mgllab/help.cpp:251 mgllab/table.cpp:428 mgllab/table.cpp:457
+msgid ""
+"DAT Files \t*.{dat,csv}\n"
+"HDF Files \t*.{h5,hdf}"
+msgstr ""
+"DAT файлы \t*.{dat,csv}\n"
+"HDF файлы \t*.{h5,hdf}"
+
+#: mgllab/dialogs.cpp:1465
+msgid "Dash"
+msgstr "Пунктир"
+
+#: udav/style_dlg.cpp:62 mgllab/dialogs.cpp:318
+msgid "Dashing"
+msgstr "Штриховка"
+
+#: udav/dat_pnl.cpp:66
+msgid "Data"
+msgstr "Данные"
+
+#: udav/dat_pnl.cpp:249 udav/dat_pnl.cpp:271
+msgid ""
+"Data files (*.dat)\n"
+"HDF5 files (*.h5 *.hdf)\n"
+"PNG files (*.png)\n"
+"All files (*.*)"
+msgstr ""
+"DAT файлы (*.dat)\n"
+"HDF5 файлы (*.h5 *.hdf)\n"
+"PNG файлы (*.png)\n"
+"Все файлы (*.*)"
+
+#: udav/newcmd_dlg.cpp:175 mgllab/dialogs.cpp:716
+msgid "Data handling"
+msgstr "Изменение данных"
+
+#: mgllab/help.cpp:163 mgllab/table.cpp:849
+msgid "Data information and preview."
+msgstr "Информация и просмотр данных."
+
+#: udav/open_dlg.cpp:56 udav/data_dlg.cpp:42 mgllab/dialogs.cpp:566
+msgid "Data name"
+msgstr "Имя данных"
+
+#: udav/info_dlg.cpp:42
+msgid "Data preview"
+msgstr "Просмотр данных"
+
+#: udav/info_dlg.cpp:43
+msgid "Data preview for current slice."
+msgstr "Просмотр текущего среза данных."
+
+#: udav/newcmd_dlg.cpp:174 mgllab/dialogs.cpp:715
+msgid "Data transform"
+msgstr "Преобразование данных"
+
+#: udav/plot_pnl.cpp:556
+msgid "Decrease \\phi angle by 10 degrees."
+msgstr "Уменьшить угол φ на 10 градусов."
+
+#: udav/plot_pnl.cpp:548
+msgid "Decrease \\theta angle by 10 degrees."
+msgstr "Уменьшить угол θ на 10 градусов."
+
+#: mgllab/help.cpp:105
+msgid "Decrease font size"
+msgstr "Уменьшить размер шрифта"
+
+#: src/parser.cpp:1427
+msgid "Define constant or parameter"
+msgstr "Определит постоянную или параметр"
+
+#: src/parser.cpp:1426
+msgid "Define parameter as character"
+msgstr "Определить параметр как символ"
+
+#: src/parser.cpp:1428
+msgid "Define parameter as numerical value"
+msgstr "Определить параметр как значение выражения"
+
+#: src/parser.cpp:1422
+msgid "Define parameter from user input"
+msgstr "Определить параметр по вводу пользователя"
+
+#: udav/anim_dlg.cpp:76
+msgid "Delay (in ms)"
+msgstr "Задержка, мс"
+
+#: mgllab/mathgl.cpp:202
+msgid "Delay (in sec)"
+msgstr "Задержка, с"
+
+#: mgllab/help.cpp:178
+msgid "Delete @b all at . data arrays."
+msgstr "Удалить @b все@. массивы данных."
+
+#: udav/mem_pnl.cpp:64
+msgid "Delete ALL data arrays"
+msgstr "Удалить ВСЕ массивы данных"
+
+#: src/exec_dat.cpp:1535
+msgid "Delete data or slice of data"
+msgstr "Удалить данные или их срез"
+
+#: udav/plot_pnl.cpp:426
+msgid "Delete selected"
+msgstr "Удалить выбранное"
+
+#: udav/mem_pnl.cpp:60
+msgid "Delete selected data array"
+msgstr "Удалить выбранные данные"
+
+#: mgllab/help.cpp:166
+msgid "Delete selected data."
+msgstr "Удалить выбранные данные."
+
+#: udav/plot_pnl.cpp:428
+msgid "Delete selected plot."
+msgstr "Удалить выбранный график"
+
+#: mgllab/dialogs.cpp:734
+msgid "Description"
+msgstr "Описание"
+
+#: src/exec_dat.cpp:1536
+msgid "Detect curves for maximums of data array"
+msgstr "Найти кривые по максимумам массива данных"
+
+#: mgllab/table.cpp:164 mgllab/table.cpp:774
+msgid "Difference"
+msgstr "Дифференцировать"
+
+#: udav/dat_pnl.cpp:616
+msgid "Differentiate data along direction(s)"
+msgstr "Дифференцировать данные по направлению(ям)"
+
+#: udav/opt_dlg.cpp:58 mgllab/dialogs.cpp:113 mgllab/dialogs.cpp:1005
+msgid "Diffuse"
+msgstr "Расс.свет"
+
+#: src/exec_dat.cpp:1540
+msgid "Dilate data larger val"
+msgstr "Расширить данные большие val"
+
+#: src/exec_dat.cpp:1527
+msgid "Direct multiplication of arrays"
+msgstr "Прямое произведение массивов"
+
+#: udav/dat_pnl.cpp:351 udav/dat_pnl.cpp:377 udav/dat_pnl.cpp:424
+#: mgllab/dialogs.cpp:161 mgllab/table.cpp:549
+msgid "Direction"
+msgstr "Направление"
+
+#: mgllab/table.cpp:551
+msgid "Direction along which data will be filled"
+msgstr "Направление по которому данные будут заполняться"
+
+#: udav/subplot_dlg.cpp:105 udav/subplot_dlg.cpp:122
+msgid "Distance between cells"
+msgstr "Расстояние между ячейками"
+
+#: mgllab/table.cpp:797
+msgid "Divide by"
+msgstr "Разделить на"
+
+#: src/exec_dat.cpp:1541
+msgid "Divide by data or number"
+msgstr "Разделить данные поэлементно на массив или число"
+
+#: mgllab/table.cpp:180 mgllab/table.cpp:354 mgllab/table.cpp:676
+msgid "Do"
+msgstr "OK"
+
+#: src/exec_dat.cpp:1603
+msgid "Do STFA transform"
+msgstr "Выполнить преобразование STFA"
+
+#: src/exec_dat.cpp:1609 src/exec_dat.cpp:1610
+msgid "Do integral transform of data"
+msgstr "Выполнить интегральное преобразование данных"
+
+#: mgllab/table.cpp:102 mgllab/table.cpp:557 mgllab/table.cpp:620
+#: mgllab/table.cpp:675
+msgid "Do nothing and close this window"
+msgstr "Закрыть это окно ничего не выполняя"
+
+#: udav/mem_pnl.cpp:122
+msgid "Do you want to delete all data?"
+msgstr "Вы хотите удалить все данные?"
+
+#: udav/udav_wnd.cpp:341 udav/udav_wnd.cpp:580 udav/udav_wnd.cpp:622
+msgid "Do you want to save the changes to the document?"
+msgstr "Вы хотите сохранить изменения в документе?"
+
+#: mgllab/editor.cpp:282
+msgid "Don't Save"
+msgstr "Не сохранять"
+
+#: mgllab/table.cpp:164
+msgid "Double diff."
+msgstr "Вторая производная"
+
+#: src/exec_gr.cpp:1032
+msgid "Draw Bifurcation diagram"
+msgstr "Нарисовать бифуркационную диаграмму"
+
+#: src/exec_gr.cpp:1067
+msgid "Draw Iris plots"
+msgstr "Нарисовать график Iris"
+
+#: src/exec_gr.cpp:1069
+msgid "Draw Lamerey diagram"
+msgstr "Нарисовать диаграмму Ламерея"
+
+#: src/exec_gr.cpp:1073
+msgid "Draw Open-High-Low-Close (OHLC) diagram"
+msgstr "Нарисовать диаграмму OHLC (Open-High-Low-Close)"
+
+#: src/exec_gr.cpp:1076
+msgid "Draw Poincare map"
+msgstr "Нарисовать диаграмму Пуанкаре"
+
+#: src/exec_gr.cpp:1082
+msgid "Draw STFA diagram"
+msgstr "Нарисовать диаграмму STFA"
+
+#: src/exec_gr.cpp:1094
+msgid "Draw TeX mark at point position"
+msgstr "Нарисовать ТеХ символы в положении точек"
+
+#: src/exec_prm.cpp:578
+msgid "Draw angle arc"
+msgstr "Нарисовать дугу"
+
+#: src/exec_gr.cpp:1026
+msgid "Draw area plot for 1D data"
+msgstr "Закрасить область между кривой и осью"
+
+#: src/exec_gr.cpp:1029
+msgid "Draw bars for 1D data"
+msgstr "Нарисовать график из вертикальных полос"
+
+#: src/exec_gr.cpp:1031
+msgid "Draw belts"
+msgstr "Нарисовать поверхность ленточками"
+
+#: src/exec_gr.cpp:1092
+msgid "Draw binormales for 1D data"
+msgstr "Нарисовать нормаль и бинормаль для кривой"
+
+#: src/exec_prm.cpp:604
+msgid "Draw bitmap (logo) along axis range"
+msgstr "Нарисовать растр (логотип) в области осей координат"
+
+#: src/exec_prm.cpp:582
+msgid "Draw bounding box"
+msgstr "Нарисовать ограничивающий параллелепипед"
+
+#: src/exec_gr.cpp:1034
+msgid "Draw boxes"
+msgstr "Нарисовать поверхность ящиками"
+
+#: src/exec_gr.cpp:1033
+msgid "Draw boxplot for 2D data"
+msgstr "Нарисовать box-and-whisker диаграмму"
+
+#: src/exec_gr.cpp:1035
+msgid "Draw candlestick chart"
+msgstr "Нарисовать свечной график"
+
+#: src/exec_gr.cpp:1036
+msgid "Draw chart"
+msgstr "Нарисовать линейчатую (круговую) диаграмму"
+
+#: src/exec_prm.cpp:583
+msgid "Draw circle"
+msgstr "Нарисовать окружность (круг)"
+
+#: src/exec_gr.cpp:1037
+msgid "Draw cloud"
+msgstr "Нарисовать облако для 3D данных"
+
+#: src/exec_prm.cpp:584
+msgid "Draw colorbar"
+msgstr "Нарисовать цветовую шкалу"
+
+#: src/exec_prm.cpp:585
+msgid "Draw cone"
+msgstr "Нарисовать конус"
+
+#: src/exec_gr.cpp:1038
+msgid "Draw cones for 1D data"
+msgstr "Нарисовать конусы для 1D данных"
+
+#: src/exec_gr.cpp:1039
+msgid "Draw contour lines"
+msgstr "Нарисовать линии уровня"
+
+#: src/exec_gr.cpp:1049
+msgid "Draw contour lines at x-slice (or x-plane)"
+msgstr "Нарисовать линии уровня на x-срезе"
+
+#: src/exec_gr.cpp:1050
+msgid "Draw contour lines at y-slice (or y-plane)"
+msgstr "Нарисовать линии уровня на y-срезе"
+
+#: src/exec_gr.cpp:1051
+msgid "Draw contour lines at z-slice (or z-plane)"
+msgstr "Нарисовать линии уровня на z-срезе"
+
+#: src/exec_gr.cpp:1040
+msgid "Draw contour lines for 3D data"
+msgstr "Нарисовать линии уровня на срезах 3D данных"
+
+#: src/exec_gr.cpp:1099
+msgid "Draw contour lines for surface of triangles"
+msgstr "Нарисовать линии уровня для поверхности из треугольников"
+
+#: src/exec_gr.cpp:1047
+msgid "Draw contour lines on parametric surface"
+msgstr "Нарисовать линии уровня на параметрической поверхности"
+
+#: src/exec_gr.cpp:1048
+msgid "Draw contour tubes"
+msgstr "Нарисовать цилиндры по линиям уровней"
+
+#: src/exec_gr.cpp:1100
+msgid "Draw contour tubes for surface of triangles"
+msgstr "Нарисовать цилиндры по линиям уровней для поверхности из треугольников"
+
+#: src/exec_prm.cpp:586
+msgid "Draw curve"
+msgstr "Нарисовать кривую"
+
+#: src/exec_gr.cpp:1102
+msgid "Draw curve by tube"
+msgstr "Нарисовать трубу около кривой"
+
+#: src/exec_gr.cpp:1053
+msgid "Draw density plot"
+msgstr "Нарисовать график плотности"
+
+#: src/exec_gr.cpp:1054
+msgid "Draw density plot at slices of 3D data"
+msgstr "Нарисовать график плотности на срезе 3D данных"
+
+#: src/exec_gr.cpp:1055
+msgid "Draw density plot at x-slice (or x-plane)"
+msgstr "Нарисовать график плотности на x-срезе"
+
+#: src/exec_gr.cpp:1056
+msgid "Draw density plot at y-slice (or y-plane)"
+msgstr "Нарисовать график плотности на y-срезе"
+
+#: src/exec_gr.cpp:1057
+msgid "Draw density plot at z-slice (or z-plane)"
+msgstr "Нарисовать график плотности на z-срезе"
+
+#: src/exec_gr.cpp:1058
+msgid "Draw dew plot"
+msgstr "Нарисовать векторное поле каплями"
+
+#: src/exec_gr.cpp:1059
+msgid "Draw dots for arbitrary data points"
+msgstr "Нарисовать набор точек"
+
+#: src/exec_prm.cpp:587
+msgid "Draw drop"
+msgstr "Нарисовать каплю"
+
+#: src/exec_prm.cpp:588
+msgid "Draw ellipse"
+msgstr "Нарисовать эллипс"
+
+#: src/exec_prm.cpp:589
+msgid "Draw error box"
+msgstr "Нарисовать размер ошибки"
+
+#: src/exec_gr.cpp:1060
+msgid "Draw error boxes"
+msgstr "Нарисовать размеры ошибок для 1D данных"
+
+#: src/exec_prm.cpp:590
+msgid "Draw face (quadrangle)"
+msgstr "Нарисовать грань (четырехугольник)"
+
+#: src/exec_prm.cpp:591
+msgid "Draw face perpendicular to x-axis"
+msgstr "Нарисовать грань поперек оси x"
+
+#: src/exec_prm.cpp:592
+msgid "Draw face perpendicular to y-axis"
+msgstr "Нарисовать грань поперек оси y"
+
+#: src/exec_prm.cpp:593
+msgid "Draw face perpendicular to z-axis"
+msgstr "Нарисовать грань поперек оси z"
+
+#: src/exec_gr.cpp:1079
+msgid "Draw filled region (ribbon) between 2 curves"
+msgstr "Закрасить область между двумя кривыми"
+
+#: src/exec_gr.cpp:1074
+msgid "Draw flow pipes for vector field"
+msgstr "Нарисовать трубки тока для векторного поля"
+
+#: src/exec_gr.cpp:1062
+msgid "Draw flow threads for vector field"
+msgstr "Нарисовать линии тока для векторного поля"
+
+#: src/exec_gr.cpp:1064
+msgid "Draw gradient lines for scalar field"
+msgstr "Нарисовать линии градиента для скалярного поля"
+
+#: src/exec_prm.cpp:598
+msgid "Draw grid"
+msgstr "Нарисовать сетку осей координат"
+
+#: src/exec_gr.cpp:1066
+msgid "Draw grid at slices of 3D data"
+msgstr "Нарисовать сетку на срезе 3D данных"
+
+#: src/exec_gr.cpp:1065
+msgid "Draw grid for data array(s)"
+msgstr "Нарисовать сетку для массива"
+
+#: src/exec_gr.cpp:1028
+msgid "Draw horizontal bars for 1D data"
+msgstr "Нарисовать график из горизонтальных полос"
+
+#: src/exec_gr.cpp:1095
+msgid "Draw horizontal tiles"
+msgstr "Нарисовать поверхность горизонтальными плитками"
+
+#: src/exec_gr.cpp:1096
+msgid "Draw horizontal tiles with variable size"
+msgstr "Нарисовать поверхность плитками переменного размера"
+
+#: src/exec_gr.cpp:1084
+msgid "Draw isosurface for 3D data"
+msgstr "Нарисовать поверхность постоянного уровня"
+
+#: src/exec_gr.cpp:1087
+msgid "Draw isosurface for 3D data colored and transpared by other data"
+msgstr "Нарисовать поверхность уровня с заданными цветом и прозрачностью"
+
+#: src/exec_gr.cpp:1086
+msgid "Draw isosurface for 3D data colored by other data"
+msgstr "Нарисовать поверхность уровня с заданным цветом"
+
+#: src/exec_gr.cpp:1085
+msgid "Draw isosurface for 3D data transpared by other data"
+msgstr "Нарисовать поверхность уровня с заданной прозрачностью"
+
+#: src/exec_gr.cpp:1068
+msgid "Draw label at arbitrary position"
+msgstr "Вывести надписи для 1D данных"
+
+#: src/exec_prm.cpp:612
+msgid "Draw label for t-axis"
+msgstr "Вывести подпись оси t"
+
+#: src/exec_prm.cpp:613
+msgid "Draw label for x-axis"
+msgstr "Вывести подпись оси x"
+
+#: src/exec_prm.cpp:614
+msgid "Draw label for y-axis"
+msgstr "Вывести подпись оси y"
+
+#: src/exec_prm.cpp:615
+msgid "Draw label for z-axis"
+msgstr "Вывести подпись оси z"
+
+#: src/exec_prm.cpp:602
+msgid "Draw legend"
+msgstr "Нарисовать легенду графика"
+
+#: src/exec_prm.cpp:603
+msgid "Draw line"
+msgstr "Нарисовать прямую линию"
+
+#: src/exec_gr.cpp:1070
+msgid "Draw mapping plot"
+msgstr "Нарисовать отображение матрицы"
+
+#: src/exec_gr.cpp:1071
+msgid "Draw mark plot for 1D data"
+msgstr "Нарисовать маркеры переменного размера"
+
+#: src/exec_gr.cpp:1072
+msgid "Draw mesh surface"
+msgstr "Нарисовать сетчатую поверхность"
+
+#: src/exec_prm.cpp:581
+msgid "Draw point (ball)"
+msgstr "Нарисовать точку"
+
+#: src/exec_prm.cpp:605
+msgid "Draw polygon"
+msgstr "Нарисовать полигон"
+
+#: src/exec_gr.cpp:1030
+msgid "Draw quasi-optical beam"
+msgstr "Нарисовать квазиоптический пучок"
+
+#: src/exec_gr.cpp:1078
+msgid "Draw radar chart"
+msgstr "Нарисовать круговой график"
+
+#: src/exec_gr.cpp:1052
+msgid "Draw reconstructed surface for arbitrary data points"
+msgstr "Нарисовать поверхность по произвольным точкам"
+
+#: src/exec_prm.cpp:606
+msgid "Draw rectangle"
+msgstr "Нарисовать прямоугольник"
+
+#: src/exec_prm.cpp:607
+msgid "Draw rhombus"
+msgstr "Нарисовать ромб"
+
+#: src/exec_gr.cpp:1044
+msgid "Draw solid contour lines at x-slice (or x-plane)"
+msgstr "Закрасить линии уровня на x-срезе"
+
+#: src/exec_gr.cpp:1045
+msgid "Draw solid contour lines at y-slice (or y-plane)"
+msgstr "Закрасить линии уровня на y-срезе"
+
+#: src/exec_gr.cpp:1046
+msgid "Draw solid contour lines at z-slice (or z-plane)"
+msgstr "Закрасить линии уровня на z-срезе"
+
+#: src/exec_gr.cpp:1043
+msgid "Draw solid contour lines for 3D data"
+msgstr "Закрасить линии уровня на 3D данных"
+
+#: src/exec_gr.cpp:1042
+msgid "Draw solid contours"
+msgstr "Закрасить линии уровня"
+
+#: src/exec_gr.cpp:1041
+msgid "Draw solid contours with manual colors"
+msgstr "Закрасить линии уровня заданными цветами"
+
+#: src/exec_gr.cpp:1083
+msgid "Draw solid surface"
+msgstr "Нарисовать поверхность"
+
+#: src/exec_gr.cpp:1090
+msgid "Draw solid surface colored and transpared by other data"
+msgstr "Нарисовать поверхность с заданными цветом и прозрачностью"
+
+#: src/exec_gr.cpp:1089
+msgid "Draw solid surface colored by other data"
+msgstr "Нарисовать поверхность с заданным цветом"
+
+#: src/exec_gr.cpp:1088
+msgid "Draw solid surface transpared by other data"
+msgstr "Нарисовать поверхность с заданной прозрачностью"
+
+#: src/exec_prm.cpp:608
+msgid "Draw sphere"
+msgstr "Нарисовать сферу"
+
+#: src/exec_gr.cpp:1080
+msgid "Draw stem plot for 1D data"
+msgstr "Нарисовать линии от 1D данных до оси"
+
+#: src/exec_gr.cpp:1081
+msgid "Draw step plot for 1D data"
+msgstr "Нарисовать ступеньки"
+
+#: src/exec_gr.cpp:1097
+msgid "Draw surface of curve rotation"
+msgstr "Нарисовать поверхность вращения"
+
+#: src/exec_gr.cpp:1077
+msgid "Draw surface of quadrangles"
+msgstr "Нарисовать поверхность из четырехугольников"
+
+#: src/exec_gr.cpp:1101
+msgid "Draw surface of triangles"
+msgstr "Нарисовать поверхность из треугольников"
+
+#: src/exec_gr.cpp:1027
+msgid "Draw surfaces of contour lines rotation"
+msgstr "Нарисовать поверхность вращения линий уровня"
+
+#: src/exec_gr.cpp:1091
+msgid "Draw table with data values"
+msgstr "Нарисовать таблицу значений данных"
+
+#: src/exec_gr.cpp:1093
+msgid "Draw tension plot for 1D data"
+msgstr "Нарисовать кривую с заданным цветом"
+
+#: src/exec_prm.cpp:610
+msgid "Draw text at some position or along curve"
+msgstr "Вывести текст в точке или вдоль кривой"
+
+#: src/exec_prm.cpp:609
+msgid "Draw user-defined symbol at given position and direction"
+msgstr "Нарисовать символ в заданных точке и направлении"
+
+#: src/exec_gr.cpp:1075
+msgid "Draw usual plot for 1D data"
+msgstr "Нарисовать кривую для 1D данных"
+
+#: src/exec_gr.cpp:1103
+msgid "Draw vector field"
+msgstr "Нарисовать векторное поле"
+
+#: src/exec_gr.cpp:1104
+msgid "Draw vector field at slices of 3D data"
+msgstr "Нарисовать векторное поле на срезах 3D данных"
+
+#: src/exec_gr.cpp:1098
+msgid "Draw vectors along a curve"
+msgstr "Нарисовать вектора вдоль кривой"
+
+#: src/exec_gr.cpp:1061
+msgid "Draw waterfalls"
+msgstr "Нарисовать поверхность набором линий (водопад)"
+
+#: udav/plot_pnl.cpp:111 udav/plot_pnl.cpp:130
+msgid "Drawing time %1 ms"
+msgstr "Время рисования %1 мс"
+
+#: udav/newcmd_dlg.cpp:169 mgllab/dialogs.cpp:710
+msgid "Dual plots"
+msgstr "Двойные графики"
+
+#. L
+#: udav/style_dlg.cpp:244 mgllab/dialogs.cpp:52
+msgid "E - darklawn"
+msgstr "E - темно-салатовый"
+
+#: mgllab/dialogs.cpp:1469
+msgid "Edges"
+msgstr "Края"
+
+#: udav/text_pnl.cpp:84 mgllab/mgllab.cpp:292
+msgid "Edit"
+msgstr "Правка"
+
+#: udav/mem_pnl.cpp:59
+msgid "Edit selected data array"
+msgstr "Редактировать выбранный массив данных"
+
+#: udav/calc_dlg.cpp:193
+msgid "Elliptic"
+msgstr "Эллиптические"
+
+#: udav/prop_dlg.cpp:171 mgllab/mgllab.cpp:474
+msgid "Enable keywords completion"
+msgstr "Разрешить дополнение команд"
+
+#. pure = new QCheckBox(_("Disable face drawing (faster) for mouse rotation/shift/zoom."), this);
+#. pure->setChecked(mglAutoPure);	v->addWidget(pure);	pure->setEnabled(false);
+#: udav/prop_dlg.cpp:169 mgllab/mgllab.cpp:476
+msgid "Enable mouse wheel for zooming"
+msgstr "Колесо мыши приближает график"
+
+#: mgllab/dialogs.cpp:1463
+msgid "End"
+msgstr "Конец"
+
+#: udav/prop_dlg.cpp:141
+msgid "English"
+msgstr "Английский"
+
+#. TODO show dialog for color scheme
+#: udav/dat_pnl.cpp:255 udav/dat_pnl.cpp:277 mgllab/table.cpp:477
+#: mgllab/table.cpp:490
+msgid "Enter color scheme"
+msgstr "Введите цветовую схему"
+
+#: udav/dat_pnl.cpp:261 udav/dat_pnl.cpp:283
+msgid "Enter data name"
+msgstr "Введите имя данных"
+
+#: mgllab/table.cpp:523
+msgid ""
+"Enter formula for data modification\n"
+"Here x, y, z in range [0,1], u is data value"
+msgstr ""
+"Введите формулу для изменения данных\n"
+"x, y, z в диапазоне [0,1], u - сами данные"
+
+#: udav/mem_pnl.cpp:85 mgllab/help.cpp:242
+msgid "Enter name for new variable"
+msgstr "Введите имя для нового массива"
+
+#. this is HDF file
+#. TODO add dialog with choice of HDF names
+#: mgllab/table.cpp:436
+msgid "Enter name of data"
+msgstr "Введите имя данных"
+
+#: udav/dat_pnl.cpp:388 udav/dat_pnl.cpp:402 udav/dat_pnl.cpp:436
+msgid "Enter new data sizes"
+msgstr "Введите новый размер данных"
+
+#: mgllab/table.cpp:28
+msgid "Enter number for addition to data values"
+msgstr "Введите число для добавления"
+
+#: mgllab/table.cpp:58
+msgid "Enter number for division of data values"
+msgstr "Введите число для делителя"
+
+#: mgllab/table.cpp:48
+msgid "Enter number for multiplication of data values"
+msgstr "Введите число для умножения"
+
+#: mgllab/table.cpp:38
+msgid "Enter number for subtraction from data values"
+msgstr "Введите число для вычитания"
+
+#: widgets/qt.cpp:936
+msgid "Enter number of vertexes"
+msgstr "Введите число вершин"
+
+#: udav/dat_pnl.cpp:351
+msgid "Enter range for data and direction of filling"
+msgstr "Введите диапазон и направление заполнения"
+
+#: udav/dat_pnl.cpp:366 udav/dat_pnl.cpp:377
+msgid "Enter range for final data"
+msgstr "Введите диапазон для выходных данных"
+
+#: udav/dat_pnl.cpp:424
+msgid "Enter range of saved date."
+msgstr "Введите диапазон сохраненных данных"
+
+#: udav/dat_pnl.cpp:485
+msgid "Enter slice id:"
+msgstr "Введите номер среза:"
+
+#: udav/dat_pnl.cpp:413
+msgid ""
+"Enter step of saved points. For example, '1' save all, '2' save each 2nd "
+"point, '3' save each 3d and so on."
+msgstr ""
+"Введите шаг сохранения. Например, '1' - все точки, '2' - каждая вторая, и т."
+"д."
+
+#: widgets/qt.cpp:945
+msgid "Enter text"
+msgstr "Введите текст"
+
+#: mgllab/dialogs.cpp:860 mgllab/dialogs.cpp:866
+#, c-format
+msgid "Enter value for %s argument"
+msgstr "Введите значение аргумента %s"
+
+#: mgllab/table.cpp:166 mgllab/table.cpp:784
+msgid "Envelop"
+msgstr "Огибающая"
+
+#: src/exec_dat.cpp:1544
+msgid "Erode data larger val"
+msgstr "Сузить данные большие val"
+
+#: mgllab/editor.cpp:348
+#, c-format
+msgid ""
+"Error reading from file '%s':\n"
+"%s."
+msgstr ""
+"Ошибка чтения файла '%s':\n"
+"%s."
+
+#: src/export.cpp:623 src/export.cpp:632 src/export.cpp:639
+#, c-format
+msgid "Error to call external viewer\n"
+msgstr "Ошибка вызова внешнего просмотра\n"
+
+#: mgllab/editor.cpp:359
+#, c-format
+msgid ""
+"Error writing to file '%s':\n"
+"%s."
+msgstr ""
+"Ошибка записи в файл '%s':\n"
+"%s."
+
+#: src/exec_dat.cpp:1545
+msgid ""
+"Evaluate (interpolate) values of array Dat at points i=idat,j=jdat,k=kdat"
+msgstr "Интерполирует значения в точках i=idat,j=jdat,k=kdat"
+
+#. {"defpal",_("Define parameter as palette color"),"defpal $N val", 0, 6},
+#: src/parser.cpp:1430
+msgid "Execute if condition is false"
+msgstr "Выполнить если условие ложно"
+
+#: mgllab/mgllab.cpp:472
+msgid "Execute script after loading"
+msgstr "Выполнить скрипт после загрузки"
+
+#: widgets/qt.cpp:1132 udav/plot_pnl.cpp:333
+msgid "Execute script and redraw graphics (F5)."
+msgstr "Выполнить скрипт и обновить рисунок (F5)."
+
+#: src/parser.cpp:1424
+msgid "Execute script in external file"
+msgstr "Выполнить скрипт из внешнего файла"
+
+#: mgllab/help.cpp:146
+msgid "Existed data arrays"
+msgstr "Массивы данных"
+
+#: mgllab/mgllab.cpp:290
+msgid "Exit"
+msgstr "Выход"
+
+#: udav/calc_dlg.cpp:192
+msgid "Exp and log"
+msgstr "Exp и log"
+
+#: udav/calc_dlg.cpp:194
+msgid "Exp-integrals"
+msgstr "Exp-интегралы"
+
+#: mgllab/table.cpp:473
+msgid "Export Data?"
+msgstr "Экспорт данных?"
+
+#: widgets/fltk.cpp:789
+msgid "Export as ..."
+msgstr "Экспорт как ..."
+
+#: widgets/qt.cpp:1067 udav/plot_pnl.cpp:474
+msgid "Export as 2D ..."
+msgstr "Экспорт как 2D ..."
+
+#: widgets/qt.cpp:1076 udav/plot_pnl.cpp:484
+msgid "Export as 3D ..."
+msgstr "Экспорт как 3D ..."
+
+#: src/exec_dat.cpp:1546 mgllab/table.cpp:844
+msgid "Export data to PNG file"
+msgstr "Экспорт данных в PNG файл"
+
+#. fname = new QLineEdit(this);	a->addWidget(fname);
+#: udav/anim_dlg.cpp:82
+msgid "Export to GIF"
+msgstr "Экспорт в GIF"
+
+#: mgllab/table.cpp:752
+msgid "Export to PNG"
+msgstr "Экспорт в PNG"
+
+#: src/exec_dat.cpp:1547
+msgid "Extend data array"
+msgstr "Расширить массив данных"
+
+#: mgllab/table.cpp:343
+msgid "Extract data"
+msgstr "Выделить данные"
+
+#: src/exec_dat.cpp:1604
+msgid "Extract sub-array"
+msgstr "Выделить под-массив"
+
+#: src/exec_dat.cpp:1596
+msgid "Extract sub-array between values"
+msgstr "Выделить под-массив в диапазоне между значениями"
+
+#: mgllab/dialogs.cpp:962
+msgid "Factor"
+msgstr "Фактор"
+
+#. file menu
+#: widgets/qt.cpp:1066 udav/udav_wnd.cpp:281 udav/dat_pnl.cpp:681
+#: mgllab/mgllab.cpp:277 mgllab/table.cpp:748
+msgid "File"
+msgstr "Файл"
+
+#: udav/text_pnl.cpp:405 udav/text_pnl.cpp:489
+msgid "File %1 saved"
+msgstr "Файл %1 сохранен."
+
+#: mgllab/mgllab.cpp:227
+msgid "File is exesist. Overwrite it?"
+msgstr "Файл существует. Переписать?"
+
+#: udav/text_pnl.cpp:583
+msgid "File name"
+msgstr "Имя файла"
+
+#: mgllab/mgllab.cpp:303
+msgid "File path"
+msgstr "Путь к файлу"
+
+#: mgllab/dialogs.cpp:1073
+msgid "File to export"
+msgstr "Экспорт в файл"
+
+#: mgllab/editor.cpp:267 mgllab/mgllab.cpp:396
+msgid "File/Recent files"
+msgstr "Файл/Последние файлы"
+
+#: mgllab/table.cpp:765
+msgid "Fill"
+msgstr "Заполнить"
+
+#: udav/dat_pnl.cpp:611 mgllab/table.cpp:854
+msgid "Fill data by formula"
+msgstr "Заполнить по формуле"
+
+#: src/exec_dat.cpp:1553
+msgid "Fill data by global spline of Vdat"
+msgstr "Заполнить данные по глобальному сплайну Vdat"
+
+#: src/exec_dat.cpp:1588
+msgid "Fill data by interpolation of Vdat"
+msgstr "Заполнить данные интерполяцией Vdat"
+
+#: src/exec_dat.cpp:1533
+msgid "Fill data by triangulated values"
+msgstr "Заполнить данные триангуляцией"
+
+#: src/exec_dat.cpp:1548
+msgid "Fill data linearly in range [v1, v2]"
+msgstr "Заполнить данные линейно в диапазоне [v1, v2]"
+
+#: mgllab/table.cpp:578 mgllab/table.cpp:592
+msgid "Fill in range"
+msgstr "Заполнить в диапазоне"
+
+#: src/exec_dat.cpp:1549
+msgid "Fill x-,k-samples for transforms"
+msgstr "Заполнить как x-,k-координаты для трансформации"
+
+#: udav/find_dlg.cpp:48 mgllab/editor.cpp:559
+msgid "Find"
+msgstr "Найти"
+
+#: src/exec_dat.cpp:1529
+msgid "Find correlation between data arrays"
+msgstr "Найти корреляцию между данными"
+
+#: src/exec_dat.cpp:1543
+msgid "Find envelop for the data"
+msgstr "Найти огибающую данных"
+
+#: udav/dat_pnl.cpp:624
+msgid "Find envelope along direction(s)"
+msgstr "Найти огибающую в направлении"
+
+#: udav/dat_pnl.cpp:804
+msgid "Find histogram of data."
+msgstr "Найти гистограмму данных"
+
+#: src/exec_dat.cpp:1564
+msgid "Find maximal value over direction"
+msgstr "Найти максимум по направлению"
+
+#: src/exec_dat.cpp:1565
+msgid "Find minimal value over direction"
+msgstr "Найти минимум по направлению"
+
+#: udav/text_pnl.cpp:551 mgllab/mgllab.cpp:301
+msgid "Find next"
+msgstr "Найти следующее"
+
+#: mgllab/editor.cpp:515
+msgid "Find or replace text"
+msgstr "Найти или заменить"
+
+#: src/exec_dat.cpp:1600
+msgid "Find root Dat[i,j,k]=val (inverse evaluate)"
+msgstr "Найти корень Dat[i,j,k]=val (обратно evaluate)"
+
+#: src/exec_dat.cpp:1592
+msgid "Find roots using data as initial values"
+msgstr "Найти корни используя данные как начальные условия"
+
+#: src/exec_dat.cpp:1606
+msgid "Find summation over direction"
+msgstr "Найти сумму по направлению"
+
+#: src/exec_dat.cpp:1612
+msgid "Find triangles of randomly placed points"
+msgstr "Триангулировать произвольно расположенные точки"
+
+#: udav/find_dlg.cpp:36 mgllab/editor.cpp:558
+msgid "Find what:"
+msgstr "Найти что:"
+
+#: udav/text_pnl.cpp:546 mgllab/editor.cpp:557
+msgid "Find/Replace"
+msgstr "Найти/Заменить"
+
+#: mgllab/mgllab.cpp:300
+msgid "Find|Replace"
+msgstr "Найти|Заменить"
+
+#: src/parser.cpp:1432
+msgid "Finish if/else block"
+msgstr "Окончание блока if/else"
+
+#: mgllab/table.cpp:804
+msgid "First cell"
+msgstr "Первая ячейка"
+
+#: udav/dat_pnl.cpp:721 mgllab/table.cpp:800
+msgid "First slice"
+msgstr "Первый срез"
+
+#: src/exec_dat.cpp:1550 src/exec_dat.cpp:1551
+msgid "Fit data to formula"
+msgstr "Подогнать данные по формуле"
+
+#: udav/text_pnl.cpp:567 mgllab/mgllab.cpp:307
+msgid "Fitted formula"
+msgstr "Подобранная формула"
+
+#: udav/prop_dlg.cpp:103
+msgid "FlowKey"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1009
+msgid "Fog"
+msgstr "Туман"
+
+#: mgllab/dialogs.cpp:1010
+msgid "Fog dist."
+msgstr "глубина"
+
+#: mgllab/mgllab.cpp:533
+msgid "Folder for help files"
+msgstr "Папка для файлов справки"
+
+#: udav/text_pnl.cpp:587 mgllab/mgllab.cpp:304
+msgid "Folder path"
+msgstr "Путь к папке"
+
+#: udav/setup_dlg.cpp:105 mgllab/dialogs.cpp:1007
+msgid "Font"
+msgstr "Шрифт"
+
+#: mgllab/mgllab.cpp:524
+msgid "Font file name"
+msgstr "Имя файла шрифта"
+
+#: udav/prop_dlg.cpp:199
+msgid "Font files (*.vfm)"
+msgstr "Файлы шрифтов (*.vfm)"
+
+#: mgllab/mgllab.cpp:463
+msgid "Font kind"
+msgstr "Шрифт"
+
+#: mgllab/mgllab.cpp:465
+msgid "Font size"
+msgstr "Размер"
+
+#: udav/style_dlg.cpp:183
+msgid "Font style"
+msgstr "Шрифт"
+
+#: udav/setup_dlg.cpp:107
+msgid "FontSize"
+msgstr "Размер"
+
+#: src/parser.cpp:1433
+msgid "For loop"
+msgstr "Цикл for"
+
+#: udav/help_pnl.cpp:52
+msgid "Forward"
+msgstr "Вперед"
+
+#: udav/plot_pnl.cpp:192
+msgid "Frame %1 of %2"
+msgstr "Кадр %1 из %2"
+
+#: udav/dat_pnl.cpp:351 udav/dat_pnl.cpp:366 udav/dat_pnl.cpp:377
+#: udav/dat_pnl.cpp:424 udav/dat_pnl.cpp:452 mgllab/table.cpp:608
+msgid "From"
+msgstr "от"
+
+#: mgllab/mgllab.cpp:592
+msgid "Function"
+msgstr "Функция"
+
+#. B
+#: udav/style_dlg.cpp:238 mgllab/dialogs.cpp:46
+msgid "G - green"
+msgstr "G - зеленый"
+
+#: src/export.cpp:306 src/export.cpp:375 src/export.cpp:388
+msgid "GIF support was disabled. Please, enable it and rebuild MathGL."
+msgstr "GIF поддержка отключена. Включите ее и пересоберите MathGL."
+
+#: udav/newcmd_dlg.cpp:178 udav/setup_dlg.cpp:112 mgllab/dialogs.cpp:719
+#: mgllab/dialogs.cpp:1001
+msgid "General setup"
+msgstr "Общие настройки"
+
+#: src/exec_dat.cpp:1561
+msgid "Get Jacobian"
+msgstr "Вычислить якобиан"
+
+#: src/exec_dat.cpp:1526
+msgid "Get data column filled by formula on column ids"
+msgstr ""
+
+#: src/exec_dat.cpp:1595
+msgid "Get formated data from file"
+msgstr "Загрузить форматированные данные из файла"
+
+#: src/exec_dat.cpp:1568
+msgid "Get momentum along direction"
+msgstr "Вычислить момент по направлению"
+
+#: src/exec_dat.cpp:1577
+msgid "Get pulse properties"
+msgstr "Найти параметры импульса"
+
+#: src/exec_dat.cpp:1608
+msgid "Get trace of array"
+msgstr "Найти след матрицы"
+
+#: src/base_cf.cpp:85
+#, c-format
+msgid "Global message - %s\n"
+msgstr "Общее сообщение - %s\n"
+
+#: udav/dat_pnl.cpp:723 mgllab/table.cpp:865
+msgid "Go to first slice for 3D data (Ctrl-F1)."
+msgstr "Перейти к первому срезу 3D данных (Ctrl-F1)"
+
+#: udav/dat_pnl.cpp:753 mgllab/table.cpp:869
+msgid "Go to last slice for 3D data (Ctrl-F4)."
+msgstr "Перейти к последнему срезу 3D данных (Ctrl-F1)"
+
+#: udav/dat_pnl.cpp:740
+msgid "Go to slice"
+msgstr "Перейти к срезу"
+
+#: udav/dat_pnl.cpp:747
+msgid "Go to the next slice for 3D data."
+msgstr "Перейти к следующему срезу 3D данных"
+
+#: udav/dat_pnl.cpp:729
+msgid "Go to the previous slice for 3D data."
+msgstr "Перейти к предыдущему срезу 3D данных"
+
+#: udav/dat_pnl.cpp:735 udav/dat_pnl.cpp:742
+msgid "Go to the specified slice for 3D data."
+msgstr "Перейти к указанному срезу 3D данных"
+
+#: widgets/qt.cpp:1095 widgets/qt.cpp:1097 udav/plot_pnl.cpp:66
+#: mgllab/mgllab.cpp:319
+msgid "Graphics"
+msgstr "Графика"
+
+#: udav/text_pnl.cpp:596
+msgid "Graphics setup"
+msgstr "Настройка графика"
+
+#: widgets/fltk.cpp:927
+msgid "Graphics/Adjust size"
+msgstr "Графика/Подогнать размер"
+
+#. /< Parameter for handling animation
+#. /< Callback function for next frame
+#. /< Callback function for prev frame
+#. /< Callback function for delay
+#. /< Callback function for reloading
+#: widgets/fltk.cpp:921 include/mgl2/Fl_MathGL.h:150
+msgid "Graphics/Alpha"
+msgstr "Графика/Прозрачность"
+
+#: widgets/fltk.cpp:956
+msgid "Graphics/Animation/Next frame"
+msgstr "Графика/Анимация/Следующий"
+
+#: widgets/fltk.cpp:957
+msgid "Graphics/Animation/Prev frame"
+msgstr "Графика/Анимация/Предыдущий"
+
+#: mgllab/mgllab.cpp:371
+msgid "Graphics/Animation/Setup animation"
+msgstr "Графика/Анимация/Настройка"
+
+#: widgets/fltk.cpp:955 include/mgl2/Fl_MathGL.h:152
+msgid "Graphics/Animation/Slideshow"
+msgstr "Графика/Анимация/Запустить"
+
+#: widgets/fltk.cpp:931
+msgid "Graphics/Copy click coor."
+msgstr "Графика/Копировать коор."
+
+#: widgets/fltk.cpp:930
+msgid "Graphics/Copy graphics"
+msgstr "Графика/Копировать рисунок"
+
+#: widgets/fltk.cpp:944
+msgid "Graphics/Export/as BMP"
+msgstr "Графика/Экспорт/как BMP"
+
+#: widgets/fltk.cpp:942
+msgid "Graphics/Export/as GIF"
+msgstr "Графика/Экспорт/как GIF"
+
+#: widgets/fltk.cpp:939
+msgid "Graphics/Export/as JPEG"
+msgstr "Графика/Экспорт/как JPEG"
+
+#: widgets/fltk.cpp:950
+msgid "Graphics/Export/as OBJ"
+msgstr "Графика/Экспорт/как OBJ"
+
+#: widgets/fltk.cpp:951
+msgid "Graphics/Export/as OFF"
+msgstr "Графика/Экспорт/как OFF"
+
+#: widgets/fltk.cpp:935
+msgid "Graphics/Export/as PNG"
+msgstr "Графика/Экспорт/как PNG"
+
+#: widgets/fltk.cpp:949
+msgid "Graphics/Export/as PRC"
+msgstr "Графика/Экспорт/как PRC"
+
+#: widgets/fltk.cpp:952
+msgid "Graphics/Export/as STL"
+msgstr "Графика/Экспорт/как STL"
+
+#: widgets/fltk.cpp:945
+msgid "Graphics/Export/as SVG"
+msgstr "Графика/Экспорт/как SVG"
+
+#: widgets/fltk.cpp:948
+msgid "Graphics/Export/as TeX"
+msgstr "Графика/Экспорт/как TeX"
+
+#: widgets/fltk.cpp:953
+msgid "Graphics/Export/as XYZ"
+msgstr "Графика/Экспорт/как XYZ"
+
+#: widgets/fltk.cpp:947
+msgid "Graphics/Export/as bitmap EPS"
+msgstr "Графика/Экспорт/как растровый EPS"
+
+#: widgets/fltk.cpp:936
+msgid "Graphics/Export/as solid PNG"
+msgstr "Графика/Экспорт/как PNG с заливкой"
+
+#: widgets/fltk.cpp:946
+msgid "Graphics/Export/as vector EPS"
+msgstr "Графика/Экспорт/как EPS"
+
+#: widgets/fltk.cpp:923 include/mgl2/Fl_MathGL.h:153
+msgid "Graphics/Grid"
+msgstr "Графика/Сетка"
+
+#: widgets/fltk.cpp:922 include/mgl2/Fl_MathGL.h:151
+msgid "Graphics/Light"
+msgstr "Графика/Освещение"
+
+#: widgets/fltk.cpp:932 include/mgl2/Fl_MathGL.h:159 mgllab/mgllab.cpp:372
+msgid "Graphics/Pause calc"
+msgstr "Графика/Пауза расчета"
+
+#: mgllab/mgllab.cpp:370
+msgid "Graphics/Primitive"
+msgstr "Графика/Примитивы"
+
+#: widgets/fltk.cpp:926
+msgid "Graphics/Redraw"
+msgstr "Графика/Перерисовать"
+
+#: widgets/fltk.cpp:928
+msgid "Graphics/Reload data"
+msgstr "Графика/Перезагрузить"
+
+#: widgets/fltk.cpp:925
+msgid "Graphics/Restore"
+msgstr "Графика/Восстановить"
+
+#: widgets/fltk.cpp:929
+msgid "Graphics/Stop"
+msgstr "Графика/Стоп"
+
+#: widgets/fltk.cpp:963
+msgid "Graphics/Transform/Move down"
+msgstr "Графика/Сдвиг/Вниз"
+
+#: widgets/fltk.cpp:959
+msgid "Graphics/Transform/Move left"
+msgstr "Графика/Сдвиг/Влево"
+
+#: widgets/fltk.cpp:964
+msgid "Graphics/Transform/Move right"
+msgstr "Графика/Сдвиг/Вправо"
+
+#: widgets/fltk.cpp:960
+msgid "Graphics/Transform/Move up"
+msgstr "Графика/Сдвиг/Вверх"
+
+#: widgets/fltk.cpp:961
+msgid "Graphics/Transform/Zoom in"
+msgstr "Графика/Сдвиг/Приблизить"
+
+#: widgets/fltk.cpp:962
+msgid "Graphics/Transform/Zoom out"
+msgstr "Графика/Сдвиг/Отдалить"
+
+#: udav/plot_pnl.cpp:304
+msgid "Grid"
+msgstr "Сетка"
+
+#: udav/newcmd_dlg.cpp:50 mgllab/dialogs.cpp:705
+msgid "Groups of MGL commands"
+msgstr "Группы команд MGL"
+
+#. P
+#: udav/style_dlg.cpp:249 mgllab/dialogs.cpp:57
+msgid "H - darkgray"
+msgstr "H - темно-серый"
+
+#: src/data_io.cpp:1085
+msgid "HDF4 support was disabled. Please, enable it and rebuild MathGL."
+msgstr "HDF4 поддержка отключена. Включите ее и пересоберите MathGL."
+
+#: src/complex_io.cpp:922 src/complex_io.cpp:924 src/data_io.cpp:1184
+#: src/data_io.cpp:1186 src/data_io.cpp:1188 src/data_io.cpp:1190
+msgid "HDF5 support was disabled. Please, enable it and rebuild MathGL."
+msgstr "HDF5 поддержка отключена. Включите ее и пересоберите MathGL."
+
+#: mgllab/table.cpp:165 mgllab/table.cpp:779
+msgid "Hankel"
+msgstr "Ханкель"
+
+#: udav/dat_pnl.cpp:622
+msgid "Hankel transform along direction(s)"
+msgstr "Преобразование Ханкеля по направлению(ям)"
+
+#: src/exec_dat.cpp:1554
+msgid "Hankel transform at some direction"
+msgstr "Преобразование Ханкеля по направлению"
+
+#: udav/subplot_dlg.cpp:84
+msgid "Height of selected cells"
+msgstr "Высота выбранных ячеек"
+
+#: widgets/qt.cpp:1276 udav/help_pnl.cpp:57 udav/udav_wnd.cpp:231
+#: udav/udav_wnd.cpp:323 mgllab/mgllab.cpp:329 mgllab/mgllab.cpp:330
+#: mgllab/mgllab.cpp:358
+msgid "Help"
+msgstr "Справка"
+
+#: udav/newcmd_dlg.cpp:73
+msgid ""
+"Here you can specify command options.\n"
+"Options are used for additional plot tunning."
+msgstr ""
+"Здесь можно задать опции команды, \n"
+"которые используются для доп.настройки графика."
+
+#: udav/udav_wnd.cpp:186 mgllab/mgllab.cpp:298
+msgid "Hidden plots"
+msgstr "Скрытые графики"
+
+#: udav/plot_pnl.cpp:431
+msgid "Hide selected"
+msgstr "Скрыть выделенное"
+
+#: udav/plot_pnl.cpp:433
+msgid "Hide selected plots."
+msgstr "Скрыть выделенные графики"
+
+#: udav/prop_dlg.cpp:173 mgllab/mgllab.cpp:475
+msgid "Highlight current object(s)"
+msgstr "Выделить текущие графики"
+
+#: udav/udav_wnd.cpp:328 mgllab/mgllab.cpp:331
+msgid "Hints"
+msgstr "Подсказки"
+
+#: udav/dat_pnl.cpp:802
+msgid "Histogram (Ctrl+Shift+H)"
+msgstr "Гистограмма (Ctrl+Shift+H)"
+
+#: udav/subplot_dlg.cpp:51 udav/subplot_dlg.cpp:68 udav/subplot_dlg.cpp:93
+msgid "Horizontal size"
+msgstr "Горизонтальный размер"
+
+#: udav/calc_dlg.cpp:192
+msgid "Hyperbolic"
+msgstr "Гиперболические"
+
+#: udav/setup_dlg.cpp:116
+msgid "ID"
+msgstr ""
+
+#: mgllab/mgllab.cpp:333
+msgid "Icon list"
+msgstr "Список иконок"
+
+#: mgllab/table.cpp:867
+msgid "Id of slice on third (z-) dimension"
+msgstr "Номер среза в z-направлении"
+
+#: udav/prop_dlg.cpp:154
+msgid "Image size"
+msgstr "Размер рисунка"
+
+#: src/exec_dat.cpp:1576
+msgid "Immediately print the message"
+msgstr "Напечатать это сообщение сразу же"
+
+#: mgllab/table.cpp:485
+msgid "Import Data?"
+msgstr "Импортировать данные?"
+
+#: src/exec_dat.cpp:1557 mgllab/table.cpp:840
+msgid "Import data from PNG file"
+msgstr "Импортировать данные из PNG файла"
+
+#: mgllab/table.cpp:750
+msgid "Import from PNG"
+msgstr "Импортировать из PNG"
+
+#: mgllab/table.cpp:767
+msgid "In range"
+msgstr "В диапазоне"
+
+#: src/exec_dat.cpp:1552
+msgid "In-place Fourier transform"
+msgstr "Фурье преобразование по месту"
+
+#: mgllab/mathgl.cpp:245
+msgid "Incompatible loop parameters!"
+msgstr "Неверные параметры цикла!"
+
+#: mgllab/table.cpp:503
+msgid "Incorrect type of base data"
+msgstr "Неверный тип данных"
+
+#: udav/plot_pnl.cpp:552
+msgid "Increase \\phi angle by 10 degrees."
+msgstr "Увеличить угол φ на 10 градусов"
+
+#: udav/plot_pnl.cpp:544
+msgid "Increase \\theta angle by 10 degrees."
+msgstr "Увеличить угол θ на 10 градусов"
+
+#: mgllab/help.cpp:103
+msgid "Increase font size"
+msgstr "Увеличить размер шрифта"
+
+#: udav/udav_wnd.cpp:229
+msgid "Info"
+msgstr "Инфо"
+
+#: udav/info_dlg.cpp:55 mgllab/help.cpp:353
+msgid "Information"
+msgstr "Информация"
+
+#: mgllab/mgllab.cpp:306
+msgid "Inplot"
+msgstr "Под-график"
+
+#. insert menu
+#: udav/text_pnl.cpp:557 mgllab/mgllab.cpp:302
+msgid "Insert"
+msgstr "Вставить"
+
+#: mgllab/editor.cpp:518
+msgid "Insert MGL command"
+msgstr "Вставить команду MGL"
+
+#: mgllab/table.cpp:753
+msgid "Insert as 'list'"
+msgstr "Вставить как 'list'"
+
+#: mgllab/editor.cpp:486
+msgid "Insert file content?"
+msgstr "Вставить содержимое файла?"
+
+#: mgllab/mgllab.cpp:148
+msgid "Insert file name?"
+msgstr "Вставить имя файла?"
+
+#: mgllab/editor.cpp:520
+msgid "Insert filename"
+msgstr "Вставить имя файла"
+
+#: mgllab/editor.cpp:522
+msgid "Insert inplot command"
+msgstr "Вставить под-график"
+
+#: udav/text_pnl.cpp:569
+msgid "Insert last fitted formula with found coefficients."
+msgstr "Вставить последнюю подогнанную формулу с найденными коэффициентами"
+
+#: src/exec_dat.cpp:1559
+msgid "Insert slice of data"
+msgstr "Вставить срез данных"
+
+#: mgllab/table.cpp:847
+msgid "Insert to script as 'list' command"
+msgstr "Вставить в скрипт как команду 'list'"
+
+#: mgllab/table.cpp:163 mgllab/table.cpp:773
+msgid "Integrate"
+msgstr "Интегрировать"
+
+#: src/exec_dat.cpp:1560 udav/dat_pnl.cpp:615
+msgid "Integrate data along direction(s)"
+msgstr "Интегрировать данные по направлению"
+
+#: mgllab/dialogs.cpp:114
+msgid "Intensity of diffuse light"
+msgstr "Интенсивность рассеянного света"
+
+#: udav/style_dlg.cpp:158 mgllab/dialogs.cpp:369
+msgid "Italic style"
+msgstr "Курсив"
+
+#: widgets/qt.cpp:1070 udav/plot_pnl.cpp:477
+msgid "JPEG"
+msgstr ""
+
+#: src/data_png.cpp:162 src/export.cpp:192
+msgid "JPEG support was disabled. Please, enable it and rebuild MathGL."
+msgstr "JPEG поддержка отключена. Включите ее и пересоберите MathGL."
+
+#: udav/calc_dlg.cpp:193
+msgid "Jacobi"
+msgstr "Якоби"
+
+#: src/exec_dat.cpp:1562
+msgid "Join data arrays"
+msgstr "Объединить массивы данных"
+
+#: mgllab/dialogs.cpp:1075
+msgid "Keep empty to put at beginning of main script."
+msgstr "Оставьте пустым для добавления в начало скрипта."
+
+#: udav/dat_pnl.cpp:780
+msgid "Keep only each n-th element of the data array."
+msgstr "Сохранить каждый n-ый элемент массива данных"
+
+#: mgllab/mathgl.cpp:198
+msgid "Keep slides in memory (faster animation but require more memory)"
+msgstr "Хранить кадры в памяти (быстрее анимация, но требуется больше памяти)"
+
+#: udav/prop_dlg.cpp:88
+msgid "Keywords"
+msgstr "Ключевые слова"
+
+#: mgllab/dialogs.cpp:354 mgllab/dialogs.cpp:704 mgllab/dialogs.cpp:1457
+msgid "Kind"
+msgstr "Тип"
+
+#: udav/newcmd_dlg.cpp:58
+msgid ""
+"Kind of command argument order. The notation is:\n"
+" * Capital arguments are data (like, Ydat);\n"
+" * Argument in '' are strings (like, 'fmt');\n"
+" * Other arguments are numbers (like, zval);\n"
+" * Arguments in [] are optional arguments."
+msgstr ""
+"Вариант аргументов команды. Обозначения:\n"
+" * Заглавные  -- данные (например, Ydat);\n"
+" * В кавычках '' -- строки (например, 'fmt');\n"
+" * Прочие -- числа (например, zval);\n"
+" * В скобках [] -- опциональные аргументы."
+
+#: udav/info_dlg.cpp:50
+msgid "Kind of plots: lines for 1D, density for 2D."
+msgstr "Тип графика: кривые для 1D, график плотности для 2D."
+
+#. Y
+#: udav/style_dlg.cpp:243 mgllab/dialogs.cpp:51
+msgid "L - seagreen"
+msgstr "L - морской волны"
+
+#: widgets/qt.cpp:1074 udav/plot_pnl.cpp:481
+msgid "LaTeX"
+msgstr ""
+
+#: udav/setup_dlg.cpp:66 mgllab/dialogs.cpp:954
+msgid "Label"
+msgstr "Надпись"
+
+#: udav/prop_dlg.cpp:139
+msgid "Language for UDAV"
+msgstr "Язык для UDAV"
+
+#: mgllab/mgllab.cpp:478
+msgid "Language for mgllab"
+msgstr "Язык для mgllab"
+
+#: udav/dat_pnl.cpp:617
+msgid "Laplace transform along direction(s)"
+msgstr "Преобразование Лапласа"
+
+#: mgllab/table.cpp:775
+msgid "Laplacian"
+msgstr "Лапласиан"
+
+#: udav/dat_pnl.cpp:751 mgllab/table.cpp:803
+msgid "Last slice"
+msgstr "Последний срез"
+
+#: udav/subplot_dlg.cpp:144
+msgid "Left bottom edge"
+msgstr "Левый нижний угол"
+
+#: udav/subplot_dlg.cpp:152
+msgid "Left top edge"
+msgstr "Левый верхний угол"
+
+#: udav/opt_dlg.cpp:74 mgllab/dialogs.cpp:118
+msgid "Legend"
+msgstr "Легенда"
+
+#: widgets/qt.cpp:1104 udav/opt_dlg.cpp:64 udav/setup_dlg.cpp:110
+#: udav/plot_pnl.cpp:297 mgllab/dialogs.cpp:115
+msgid "Light"
+msgstr "Свет"
+
+#: udav/setup_dlg.cpp:190
+msgid "Light position should be filled. Ignore it."
+msgstr "Положение источника света должно быть заполнено."
+
+#: udav/setup_dlg.cpp:136 mgllab/dialogs.cpp:1053
+msgid "Light settings"
+msgstr "Настройки освещения"
+
+#: src/exec_dat.cpp:1563
+msgid "Limit data to be inside [-v,v]"
+msgstr "Ограничить данные диапазоном [-v,v]"
+
+#: udav/style_dlg.cpp:99 mgllab/dialogs.cpp:314
+msgid "Line style"
+msgstr "Стиль линии"
+
+#: udav/style_dlg.cpp:78
+msgid "Line width"
+msgstr "Толщина линии"
+
+#: mgllab/table.cpp:167
+msgid "Linear *3"
+msgstr "Линейно *3"
+
+#: mgllab/table.cpp:167
+msgid "Linear *5"
+msgstr "Линейно *5"
+
+#: mgllab/help.cpp:156
+msgid "List of available data."
+msgstr "Список доступных данных."
+
+#: mgllab/table.cpp:427
+msgid "Load Data?"
+msgstr "Загрузить данные?"
+
+#: src/exec_set.cpp:719
+msgid "Load commands from external DLL"
+msgstr "Загрузить команды из внешней DLL"
+
+#: udav/dat_pnl.cpp:682
+msgid "Load data"
+msgstr "Загрузить данные"
+
+#: mgllab/table.cpp:838
+msgid "Load data from file"
+msgstr "Загрузить данные из файла"
+
+#: udav/dat_pnl.cpp:684
+msgid ""
+"Load data from file. Data will be deleted only\n"
+"at exit but UDAV will not ask to save it (Ctrl+Shift+O)."
+msgstr ""
+"Загрузить данные. Данные будут удалены только\n"
+"при выходе из программы без запроса на сохранение (Ctrl+Shift+O)."
+
+#: src/exec_set.cpp:720
+msgid "Load fontfaces"
+msgstr "Загрузить шрифт"
+
+#: mgllab/table.cpp:749
+msgid "Load from file"
+msgstr "Загрузить из файла"
+
+#: src/exec_prm.cpp:580
+msgid "Load image for background"
+msgstr "Загрузить фоновое изображение"
+
+#: udav/prop_dlg.cpp:163
+msgid "Load script to new window"
+msgstr "Загрузить скрипт в новое окно"
+
+#: udav/text_pnl.cpp:467
+msgid "Loaded document "
+msgstr "Загруженные документы "
+
+#: udav/text_pnl.cpp:325
+msgid "Loaded document %1"
+msgstr "Загруженные документы %1"
+
+#: udav/udav_wnd.cpp:638
+msgid "Loading aborted"
+msgstr "Загрузка отменена"
+
+#: mgllab/dialogs.cpp:98
+msgid "Low border for determining color or alpha"
+msgstr "Нижняя граница для цвета или прозрачности"
+
+#. C
+#: udav/style_dlg.cpp:241 mgllab/dialogs.cpp:49
+msgid "M - purple"
+msgstr "M - пурпурный"
+
+#: src/parser.cpp:1018
+msgid "MGL Parser"
+msgstr "MGL парсер"
+
+#: udav/newcmd_dlg.cpp:53 mgllab/dialogs.cpp:725
+msgid "MGL commands for selected group"
+msgstr "Команда MGL для выбранной группы"
+
+#: mgllab/mgllab.cpp:214
+msgid "MGL files \t*.mgl"
+msgstr "MGL файлы \t*.mgl"
+
+#: mgllab/mgllab.cpp:173
+msgid ""
+"MGL files \t*.mgl\n"
+"DAT files \t*.{dat,csv}"
+msgstr ""
+"MGL файлы \t*.mgl\n"
+"DAT файлы \t*.{dat,csv}"
+
+#: udav/open_dlg.cpp:102
+msgid "MGL files (*.mgl)"
+msgstr "MGL файлы (*.mgl)"
+
+#: udav/udav_wnd.cpp:324
+msgid "MGL help"
+msgstr "Справка MGL"
+
+#: mgllab/mathgl.cpp:421
+msgid "MGL messages"
+msgstr "Сообщение MGL"
+
+#: mgllab/help.cpp:101
+msgid "MGL samples and hints"
+msgstr "Примеры и подсказки"
+
+#: udav/udav_wnd.cpp:670
+msgid ""
+"MGL scripts (*.mgl)\n"
+"HDF5 files (*.hdf *.h5)\n"
+"All files (*.*)"
+msgstr ""
+"MGL файлы (*.mgl)\n"
+"HDF5 файлы (*.hdf *.h5)\n"
+"Все файлы (*.*)"
+
+#: udav/udav_wnd.cpp:635
+msgid ""
+"MGL scripts (*.mgl)\n"
+"HDF5 files (*.hdf *.h5)\n"
+"Text files (*.txt)\n"
+"Data files (*.dat)\n"
+"All files (*.*)"
+msgstr ""
+"MGL файлы (*.mgl)\n"
+"HDF5 файлы (*.hdf *.h5)\n"
+"Text файлы (*.txt)\n"
+"Data файлы (*.dat)\n"
+"Все файлы (*.*)"
+
+#: widgets/qt.cpp:1077 udav/plot_pnl.cpp:485
+msgid "MGLD"
+msgstr ""
+
+#: udav/dat_pnl.cpp:798
+msgid "Make another data."
+msgstr "Создание новых данных"
+
+#: udav/dat_pnl.cpp:796
+msgid "Make new (Ctrl+Shift+M)"
+msgstr "Создать новый (Ctrl+Shift+M)"
+
+#: udav/style_dlg.cpp:83 mgllab/dialogs.cpp:336
+msgid "Manual dashing"
+msgstr "Штриховка вручную"
+
+#: udav/style_dlg.cpp:196
+msgid "Manual mask"
+msgstr "Маска вручную"
+
+#: udav/text_pnl.cpp:591 mgllab/mgllab.cpp:308
+msgid "Manual primitives"
+msgstr "Примитивы вручную"
+
+#: mgllab/dialogs.cpp:1467
+msgid "Mark"
+msgstr "Маркер"
+
+#: udav/style_dlg.cpp:76 mgllab/dialogs.cpp:324
+msgid "Marks"
+msgstr "Маркеры"
+
+#: mgllab/dialogs.cpp:352
+msgid "Mask"
+msgstr "Маска"
+
+#: udav/style_dlg.cpp:124
+msgid "Mask for bitmap coloring"
+msgstr "Маска для растровой закраски"
+
+#: udav/style_dlg.cpp:125
+msgid "Mask rotation angle"
+msgstr "Угол поворота маски"
+
+#: udav/style_dlg.cpp:126
+msgid "Mask size"
+msgstr "Размер маски"
+
+#: udav/find_dlg.cpp:42 mgllab/editor.cpp:562
+msgid "Match case"
+msgstr "Учитывать регистр"
+
+#: widgets/qt.cpp:860
+msgid "MathGL - about"
+msgstr "MathGL - о программе"
+
+#: src/base.cpp:250
+#, c-format
+msgid "MathGL message - %s\n"
+msgstr "Сообщение MathGL - %s\n"
+
+#: widgets/qt.cpp:859
+msgid "MathGL v. 2."
+msgstr ""
+
+#: udav/open_dlg.cpp:70
+msgid "Matrix with sizes from file"
+msgstr "Матрица с размерами из файла"
+
+#: udav/dat_pnl.cpp:541
+msgid "Max along direction(s)"
+msgstr "Максимум вдоль направления"
+
+#: udav/setup_dlg.cpp:57 mgllab/dialogs.cpp:952
+msgid "Maximal"
+msgstr "Максимум"
+
+#: mgllab/table.cpp:546
+msgid "Maximal value (v2)"
+msgstr "Максимальное значение (v2)"
+
+#: mgllab/table.cpp:548
+msgid "Maximal value for resulting data values"
+msgstr "Максимальное значение для получившихся данных"
+
+#: mgllab/dialogs.cpp:88
+msgid "Maximal value of X for cutting or for coordinate filling"
+msgstr "Максимум X для обрезания или координат"
+
+#: mgllab/dialogs.cpp:92
+msgid "Maximal value of Y for cutting or for coordinate filling"
+msgstr "Максимум Y для обрезания или координат"
+
+#: mgllab/dialogs.cpp:96
+msgid "Maximal value of Z for cutting or for coordinate filling"
+msgstr "Максимум Z для обрезания или координат"
+
+#: src/data.cpp:1417
+#, c-format
+msgid "Maximum is %g\t at x = %ld\ty = %ld\tz = %ld\n"
+msgstr "Максимум %g\t при x = %ld\ty = %ld\tz = %ld\n"
+
+#: mgllab/table.cpp:342 mgllab/table.cpp:789
+msgid "Maximum of"
+msgstr "Максимум от"
+
+#: udav/mem_pnl.cpp:68 udav/mem_pnl.cpp:73 mgllab/mgllab.cpp:360
+msgid "Memory"
+msgstr "Память"
+
+#: udav/opt_dlg.cpp:53
+msgid "Mesh num"
+msgstr "Число линий"
+
+#: udav/setup_dlg.cpp:99 mgllab/dialogs.cpp:102
+msgid "MeshNum"
+msgstr "Число линий"
+
+#: mgllab/mgllab.cpp:327
+msgid "Messages"
+msgstr "Сообщения"
+
+#: udav/udav_wnd.cpp:178
+msgid "Messages and warnings"
+msgstr "Сообщения"
+
+#: udav/dat_pnl.cpp:540
+msgid "Min along direction(s)"
+msgstr "Минимум по направления"
+
+#: udav/setup_dlg.cpp:52 mgllab/dialogs.cpp:951
+msgid "Minimal"
+msgstr "Минимум"
+
+#: mgllab/table.cpp:543
+msgid "Minimal value (v1)"
+msgstr "Минимальное значение (v1)"
+
+#: mgllab/table.cpp:545
+msgid "Minimal value for resulting data values"
+msgstr "Минимальное значение для получившихся данных"
+
+#: mgllab/dialogs.cpp:86
+msgid "Minimal value of X for cutting or for coordinate filling"
+msgstr "Минимум X для обрезания или координат"
+
+#: mgllab/dialogs.cpp:90
+msgid "Minimal value of Y for cutting or for coordinate filling"
+msgstr "Минимум Y для обрезания или координат"
+
+#: mgllab/dialogs.cpp:94
+msgid "Minimal value of Z for cutting or for coordinate filling"
+msgstr "Минимум Z для обрезания или координат"
+
+#: src/data.cpp:1420
+#, c-format
+msgid "Minimum is %g\t at x = %ld\ty = %ld\tz = %ld\n"
+msgstr "Минимум %g\t при x = %ld\ty = %ld\tz = %ld\n"
+
+#: mgllab/table.cpp:342 mgllab/table.cpp:790
+msgid "Minimum of"
+msgstr "Минимум от"
+
+#. { _("Wavelet"),	0, wavelet_cb },
+#: mgllab/table.cpp:166 mgllab/table.cpp:781
+msgid "Mirror"
+msgstr "Отразить"
+
+#: udav/dat_pnl.cpp:619
+msgid "Mirror data along direction(s)"
+msgstr "Отразить данные по направлению"
+
+#: src/exec_dat.cpp:1566
+msgid "Mirror data at some direction"
+msgstr "Отразить данные по направлению"
+
+#: src/exec_dat.cpp:1567
+msgid "Modify data values by formula"
+msgstr "Изменить данные по формуле"
+
+#: udav/dat_pnl.cpp:542
+msgid "Momentum along 'x' for function"
+msgstr "Момент вдоль 'x' для функции"
+
+#: udav/dat_pnl.cpp:543
+msgid "Momentum along 'y' for function"
+msgstr "Момент вдоль 'y' для функции"
+
+#: udav/dat_pnl.cpp:544
+msgid "Momentum along 'z' for function"
+msgstr "Момент вдоль 'z' для функции"
+
+#: widgets/qt.cpp:1233 udav/plot_pnl.cpp:527
+msgid "Move down"
+msgstr "Сдвиг вниз"
+
+#: widgets/qt.cpp:1219 udav/plot_pnl.cpp:506
+msgid "Move graphics left by 1/3 of its width."
+msgstr "Сдвинуть графику влево на 1/3 ширины"
+
+#: widgets/qt.cpp:1239 udav/plot_pnl.cpp:536
+msgid "Move graphics right by 1/3 of its width."
+msgstr "Сдвинуть графику вправо на 1/3 ширины"
+
+#: widgets/qt.cpp:1223 udav/plot_pnl.cpp:512
+msgid "Move graphics up by 1/3 of its height."
+msgstr "Сдвинуть графику вверх на 1/3 высоты"
+
+#: widgets/qt.cpp:1235 udav/plot_pnl.cpp:530
+msgid "Move graphics up down 1/3 of its height."
+msgstr "Сдвинуть графику вниз на 1/3 высоты"
+
+#: widgets/qt.cpp:1217 udav/plot_pnl.cpp:503
+msgid "Move left"
+msgstr "Сдвиг влево"
+
+#: udav/text_pnl.cpp:593
+msgid "Move mouse-handled primitives to script."
+msgstr "Перенести заданные вручную примитивы в скрипт."
+
+#: udav/plot_pnl.cpp:454
+msgid "Move plot down"
+msgstr "Сдвинуть график вниз"
+
+#: udav/plot_pnl.cpp:449
+msgid "Move plot up"
+msgstr "Сдвинуть график вверх"
+
+#: widgets/qt.cpp:1237 udav/plot_pnl.cpp:533
+msgid "Move right"
+msgstr "Сдвиг вправо"
+
+#: udav/plot_pnl.cpp:456
+msgid "Move selected plot down to next subplot."
+msgstr "Переместить выбранное в следующий под-график."
+
+#: udav/plot_pnl.cpp:451
+msgid "Move selected plot up to previous subplot."
+msgstr "Переместить выбранное в предыдущий под-график."
+
+#: widgets/qt.cpp:1221 udav/plot_pnl.cpp:509
+msgid "Move up"
+msgstr "Сдвиг вверх"
+
+#: mgllab/table.cpp:796
+msgid "Multiply by"
+msgstr "Умножить на"
+
+#: src/exec_dat.cpp:1569
+msgid "Multiply by data or number"
+msgstr "Умножить на массив данных или число"
+
+#. E
+#: udav/style_dlg.cpp:245 mgllab/dialogs.cpp:53
+msgid "N - darkskyblue"
+msgstr "N - грозовой"
+
+#: udav/dat_pnl.cpp:500
+msgid "NOTE: All fields must be filled!"
+msgstr "Все поля должны быть заполнены!"
+
+#: udav/mem_pnl.cpp:68
+msgid "Name"
+msgstr "Имя"
+
+#: mgllab/table.cpp:349
+msgid "Name for output"
+msgstr "Имя для результата"
+
+#. navigation menu
+#: udav/dat_pnl.cpp:720 mgllab/table.cpp:799
+msgid "Navigation"
+msgstr "Навигация"
+
+#: udav/newcmd_dlg.cpp:101 udav/newcmd_dlg.cpp:310 udav/newcmd_dlg.cpp:338
+#: udav/newcmd_dlg.cpp:342 udav/newcmd_dlg.cpp:356 udav/newcmd_dlg.cpp:369
+#: udav/newcmd_dlg.cpp:377 udav/newcmd_dlg.cpp:381 udav/newcmd_dlg.cpp:385
+#: udav/text_pnl.cpp:558 udav/plot_pnl.cpp:439 mgllab/dialogs.cpp:702
+msgid "New command"
+msgstr "Новая команда"
+
+#: udav/hint_dlg.cpp:40 mgllab/help.cpp:274
+msgid ""
+"New drawing never clears things drawn already. For example, you can make a "
+"surface with contour lines by calling commands 'surf' and 'cont' one after "
+"another (in any order). "
+msgstr ""
+
+#: udav/text_pnl.cpp:562 udav/plot_pnl.cpp:444
+msgid "New inplot"
+msgstr "Новый под-график"
+
+#: mgllab/table.cpp:671
+msgid "New order of dimensions"
+msgstr "Новый порядок размерностей"
+
+#: udav/udav_wnd.cpp:282 mgllab/mgllab.cpp:278
+msgid "New script"
+msgstr "Новый скрипт"
+
+#: mgllab/table.cpp:95
+msgid "New size of data on 1st dimension (x-direction)"
+msgstr "Новый размер данных по x"
+
+#: mgllab/table.cpp:97
+msgid "New size of data on 2nd dimension (y-direction)"
+msgstr "Новый размер данных по y"
+
+#: mgllab/table.cpp:99
+msgid "New size of data on 3d dimension (z-direction)"
+msgstr "Новый размер данных по z"
+
+#: udav/hint_dlg.cpp:68
+msgid "Next"
+msgstr "Следующий"
+
+#: mgllab/help.cpp:306
+msgid "Next @->"
+msgstr "Следующий @->"
+
+#: udav/dat_pnl.cpp:745 mgllab/table.cpp:802
+msgid "Next slice"
+msgstr "Следующий срез"
+
+#: widgets/qt.cpp:1247 udav/plot_pnl.cpp:560
+msgid "Next slide"
+msgstr "Следующий кадр"
+
+#: mgllab/help.cpp:135 mgllab/mgllab.cpp:227
+msgid "No"
+msgstr "Нет"
+
+#: udav/dat_pnl.cpp:567 udav/dat_pnl.cpp:644
+msgid "No action is selected. Do nothing."
+msgstr "Действие не выбрано."
+
+#: udav/newcmd_dlg.cpp:310
+msgid "No argument is selected"
+msgstr "Аргумент не выбран"
+
+#: udav/dat_pnl.cpp:573
+msgid "No direction/formula is entered. Do nothing."
+msgstr "Не введено направление/формула"
+
+#: widgets/qt.cpp:680 widgets/qt.cpp:692 widgets/qt.cpp:704 widgets/qt.cpp:716
+#: widgets/qt.cpp:728 widgets/qt.cpp:736 widgets/qt.cpp:744 widgets/qt.cpp:752
+#: widgets/qt.cpp:760 widgets/qt.cpp:768 widgets/qt.cpp:776 widgets/qt.cpp:784
+#: widgets/qt.cpp:800 widgets/qt.cpp:808 widgets/qt.cpp:816
+msgid "No filename."
+msgstr "Отсутствует имя файла."
+
+#: mgllab/editor.cpp:584 mgllab/editor.cpp:606 mgllab/editor.cpp:631
+#, c-format
+msgid "No occurrences of '%s' found!"
+msgstr "Вхождения '%s' не найдены!"
+
+#: mgllab/mathgl.cpp:260
+msgid "No selection. So nothing to do"
+msgstr "Ничего не выбрано."
+
+#: udav/text_pnl.cpp:202
+msgid "No string occurrence is found"
+msgstr "Вхождения не найдены"
+
+#: udav/setup_dlg.cpp:111
+msgid "No text rotation"
+msgstr "Не вращать текст"
+
+#: widgets/fltk.cpp:812
+msgid "Normal view"
+msgstr "Обычный вид"
+
+#: mgllab/table.cpp:768
+msgid "Normalize"
+msgstr "Нормировать"
+
+#: src/exec_dat.cpp:1571
+msgid "Normalize data"
+msgstr "Нормировать данные"
+
+#: src/exec_dat.cpp:1572
+msgid "Normalize data slice by slice"
+msgstr "Нормировать данные по срезам"
+
+#: mgllab/table.cpp:553
+msgid "Normalize in symmetrical range: -max(|v1|,|v2|) ... max(|v1|,|v2|)"
+msgstr "Нормировать симметрично: -max(|v1|,|v2|) ... max(|v1|,|v2|)"
+
+#: udav/udav_wnd.cpp:444
+msgid "Not recognized"
+msgstr "Не распознано"
+
+#: udav/dat_pnl.cpp:456
+msgid "Number of points"
+msgstr "Число точек"
+
+#: udav/prop_dlg.cpp:97
+msgid "Numbers"
+msgstr "Числа"
+
+#: mgllab/table.cpp:176
+msgid "Numeric parameter"
+msgstr "Численный параметр"
+
+#: udav/text_pnl.cpp:579
+msgid "Numeric value"
+msgstr "Численное значение"
+
+#: src/exec_dat.cpp:1537
+msgid "Numerically differentiate data"
+msgstr "Численно дифференцировать данные"
+
+#: src/exec_dat.cpp:1538
+msgid "Numerically double differentiate data"
+msgstr "Численно дифференцировать данные дважды"
+
+#: udav/open_dlg.cpp:64
+msgid "Nx"
+msgstr ""
+
+#: udav/open_dlg.cpp:66
+msgid "Ny"
+msgstr ""
+
+#: udav/open_dlg.cpp:68
+msgid "Nz"
+msgstr ""
+
+#: widgets/qt.cpp:1079 udav/plot_pnl.cpp:487
+msgid "OBJ"
+msgstr ""
+
+#: udav/anim_dlg.cpp:69 udav/prop_dlg.cpp:182 udav/args_dlg.cpp:65
+#: udav/newcmd_dlg.cpp:80 udav/open_dlg.cpp:92 udav/dat_pnl.cpp:462
+#: udav/dat_pnl.cpp:512 udav/dat_pnl.cpp:554 udav/dat_pnl.cpp:631
+#: udav/opt_dlg.cpp:80 udav/files_dlg.cpp:60 udav/style_dlg.cpp:208
+#: udav/data_dlg.cpp:92 udav/subplot_dlg.cpp:221 mgllab/mathgl.cpp:196
+#: mgllab/dialogs.cpp:121 mgllab/dialogs.cpp:165 mgllab/dialogs.cpp:411
+#: mgllab/dialogs.cpp:585 mgllab/dialogs.cpp:750 mgllab/dialogs.cpp:1072
+#: mgllab/dialogs.cpp:1319 mgllab/dialogs.cpp:1474 mgllab/mgllab.cpp:483
+#: mgllab/table.cpp:621
+msgid "OK"
+msgstr ""
+
+#: mgllab/table.cpp:504
+msgid "Only current slice will be inserted"
+msgstr "Только текущий срез будет вставлен"
+
+#: mgllab/mgllab.cpp:172
+msgid "Open File?"
+msgstr "Открыть файл?"
+
+#: src/exec_dat.cpp:1574
+msgid "Open all data arrays from HDF file"
+msgstr "Загрузить все данные из HDF файла"
+
+#: udav/udav_wnd.cpp:198
+msgid ""
+"Open and execute/show script or data from file (Ctrl+O).\n"
+"You may switch off automatic exection in UDAV properties."
+msgstr ""
+"Открыть и выполнить скрипт или данные (Ctrl+O).\n"
+"Вы можете отключить автоматическое выполнение в настройках."
+
+#: mgllab/help.cpp:169
+msgid "Open dialog for new data creation."
+msgstr "Открыть диалог создания новых данных."
+
+#: udav/udav_wnd.cpp:196
+msgid "Open file"
+msgstr "Открыть файл"
+
+#: mgllab/mgllab.cpp:279
+msgid "Open file ..."
+msgstr "Открыть файл ..."
+
+#: widgets/qt.cpp:1088 udav/udav_wnd.cpp:298
+msgid "Open printer dialog and print graphics (Ctrl+P)"
+msgstr "Открыть диалог и напечатать график (CTRl+P)"
+
+#: mgllab/editor.cpp:506
+msgid "Open script or data file"
+msgstr "Загрузить скрипт или файл данных"
+
+#: mgllab/help.cpp:160
+msgid "Open table with selected data for editing."
+msgstr "Открыть таблицу с выбранным массивом данных."
+
+#: udav/data_dlg.cpp:65 mgllab/dialogs.cpp:578
+msgid "Operation"
+msgstr "Операция"
+
+#: mgllab/table.cpp:231
+msgid "Operation is not supported for this type of data."
+msgstr "Операция не поддерживается для данного типа данных."
+
+#: mgllab/table.cpp:793
+msgid "Operations"
+msgstr "Операции"
+
+#: udav/prop_dlg.cpp:91 udav/newcmd_dlg.cpp:72 mgllab/dialogs.cpp:746
+#: mgllab/mgllab.cpp:310
+msgid "Options"
+msgstr "Опции"
+
+#: udav/setup_dlg.cpp:62 mgllab/dialogs.cpp:953
+msgid "Origin"
+msgstr "Начало"
+
+#: udav/newcmd_dlg.cpp:171 mgllab/dialogs.cpp:712
+msgid "Other plots"
+msgstr "Другие графики"
+
+#: mgllab/dialogs.cpp:1025
+msgid "Others"
+msgstr "Другие"
+
+#: udav/style_dlg.cpp:161 mgllab/dialogs.cpp:372
+msgid "Overline"
+msgstr "Надчеркнутый"
+
+#: mgllab/dialogs.cpp:112
+msgid "Own brightness of the surface"
+msgstr "Собственная яркость поверхности"
+
+#. Q
+#: udav/style_dlg.cpp:248 mgllab/dialogs.cpp:56
+msgid "P - darkpink"
+msgstr "P - багровый"
+
+#: src/prc.cpp:981
+msgid "PDF support was disabled. Please, enable it and rebuild MathGL."
+msgstr "PDF поддержка отключена. Включите ее и пересоберите MathGL."
+
+#: widgets/qt.cpp:1068 udav/plot_pnl.cpp:475
+msgid "PNG"
+msgstr ""
+
+#: mgllab/table.cpp:474 mgllab/table.cpp:486
+msgid "PNG Files \t*.png"
+msgstr "PNG файлы \t*.png"
+
+#: src/canvas_cf.cpp:502 src/canvas_cf.cpp:504 src/data_png.cpp:122
+#: src/export.cpp:75 src/export.cpp:109
+msgid "PNG support was disabled. Please, enable it and rebuild MathGL."
+msgstr "PNG поддержка отключена. Включите ее и пересоберите MathGL."
+
+#: widgets/qt.cpp:1078 udav/plot_pnl.cpp:486
+msgid "PRC"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1006
+msgid "Palette"
+msgstr "Палитра"
+
+#: mgllab/table.cpp:167
+msgid "Parabolic *5"
+msgstr "По параболе *5"
+
+#: udav/dat_pnl.cpp:713
+msgid "Paste data"
+msgstr "Вставить данные"
+
+#: udav/dat_pnl.cpp:715
+msgid "Paste range of numbers from clipboard (Ctrl+Shift+P)."
+msgstr "Вставить диапазон значений из буфера обмена (Ctrl+Shift+P)."
+
+#: udav/text_pnl.cpp:538 mgllab/mgllab.cpp:296
+msgid "Paste text"
+msgstr "Вставить текст"
+
+#: mgllab/editor.cpp:513
+msgid "Paste text from clipboard"
+msgstr "Вставить текст из буфера обмена"
+
+#: udav/text_pnl.cpp:540
+msgid "Paste text or data from clipboard (Ctrl+V)."
+msgstr "Вставить текст из буфера обмена (Ctrl+V)."
+
+#: mgllab/mgllab.cpp:469
+msgid "Path for MathGL font (without extension)"
+msgstr "Путь к шрифтам MathGL (без расширения)"
+
+#: udav/prop_dlg.cpp:110 mgllab/mgllab.cpp:466
+msgid "Path for help files"
+msgstr "Путь к файлам справки"
+
+#: udav/prop_dlg.cpp:130
+msgid "Path for user MathGL font files"
+msgstr "Путь к шрифтам MathGL"
+
+#: widgets/qt.cpp:1265
+msgid "Pause calculation"
+msgstr "Пауза вычислений"
+
+#. Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(setPause()));
+#: widgets/fltk.cpp:891 widgets/qt.cpp:1270
+msgid "Pause on/off external calculations"
+msgstr "Пауза вкл/выкл для внешних вычислений"
+
+#: src/exec_dat.cpp:1590
+msgid "Perform Runge-Kutta step"
+msgstr "Выполнить шаг Рунге-Кутта"
+
+#: widgets/fltk.cpp:864
+msgid "Phi angle (rotate in x*y plane)"
+msgstr "Угол Phi (вращать в плоскости x*y)"
+
+#: udav/prop_dlg.cpp:161
+msgid "Place editor at top"
+msgstr "Поместить редактор сверху"
+
+#: mgllab/dialogs.cpp:1050
+msgid "Plot ID"
+msgstr "ID графика"
+
+#: src/exec_prm.cpp:596
+msgid "Plot curve by formula"
+msgstr "Построить кривую по формуле"
+
+#. o->addSeparator();	bb->addSeparator();
+#. a = new QAction(QPixmap(insert_xpm), _("Insert as list"), this);
+#. connect(a, SIGNAL(triggered()), this, SLOT(list()));
+#. o->addAction(a);
+#. bb = new QToolButton(this);	l->addWidget(bb);	bb->setDefaultAction(a);
+#: udav/dat_pnl.cpp:701
+msgid "Plot data"
+msgstr "Нарисовать данные"
+
+#: udav/dat_pnl.cpp:703
+msgid ""
+"Plot data in new script window. You may select the kind\n"
+"of plot, its style and so on."
+msgstr ""
+"Нарисовать данные в новом окне.\n"
+"Вы можете выбрать тип графика, его стиль и т.д."
+
+#: mgllab/mgllab.cpp:325
+msgid "Plot setup"
+msgstr "Настройки графика"
+
+#: udav/text_pnl.cpp:571 mgllab/dialogs.cpp:312 mgllab/mgllab.cpp:309
+msgid "Plot style"
+msgstr "Стиль графика"
+
+#: src/exec_prm.cpp:597
+msgid "Plot surface by formula"
+msgstr "Построить поверхность по формуле"
+
+#: mgllab/dialogs.cpp:386
+msgid "Popular color schemes"
+msgstr "Популярные цв.схемы"
+
+#: udav/hint_dlg.cpp:66
+msgid "Prev"
+msgstr "Предыдущий"
+
+#: udav/dat_pnl.cpp:727 mgllab/table.cpp:801
+msgid "Prev slice"
+msgstr "Предыдущий срез"
+
+#: widgets/qt.cpp:1256 udav/plot_pnl.cpp:575
+msgid "Prev slide"
+msgstr "Предыдущий кадр"
+
+#: udav/info_dlg.cpp:51
+msgid "Preview"
+msgstr "Просмотр"
+
+#: mgllab/mgllab.cpp:566
+msgid "Previous expressions"
+msgstr "Предыдущее выражение"
+
+#: udav/newcmd_dlg.cpp:181 mgllab/dialogs.cpp:722
+msgid "Primitives"
+msgstr "Примитивы"
+
+#: widgets/qt.cpp:1150 udav/plot_pnl.cpp:365
+msgid "Primitives ..."
+msgstr "Примитивы ..."
+
+#: src/exec_set.cpp:750
+msgid "Print MathGL version or check if it is valid"
+msgstr "Вывести версию MathGL или проверить, что она подходит"
+
+#: src/exec_dat.cpp:1542
+msgid "Print content of the data"
+msgstr "Вывести содержимое массива данных"
+
+#: src/exec_dat.cpp:1579
+msgid "Print fitted formula"
+msgstr "Вывести подобранную формулу"
+
+#: widgets/qt.cpp:1086 udav/udav_wnd.cpp:296
+msgid "Print graphics"
+msgstr "Напечатать график"
+
+#: src/exec_dat.cpp:1534
+msgid "Print list of data names in HDF file"
+msgstr "Вывести список имен переменных в HDF файле"
+
+#: src/exec_dat.cpp:1558
+msgid "Print message or information about the data"
+msgstr "Вывести сообщение или информацию о данных"
+
+#: mgllab/mgllab.cpp:282
+msgid "Print plot"
+msgstr "Напечатать график"
+
+#: udav/udav_wnd.cpp:295
+msgid "Print script"
+msgstr "Напечатать скрипт"
+
+#: src/exec_prm.cpp:594
+msgid "Print string from file"
+msgstr "Вывести строку в файл"
+
+#: udav/text_pnl.cpp:178
+msgid "Printing aborted"
+msgstr "Печать отменена"
+
+#: udav/text_pnl.cpp:176
+msgid "Printing completed"
+msgstr "Печать закончена"
+
+#: udav/text_pnl.cpp:174
+msgid "Printing..."
+msgstr "Печатаю ..."
+
+#: udav/newcmd_dlg.cpp:180 mgllab/dialogs.cpp:721
+msgid "Program flow"
+msgstr "Команды управления"
+
+#: udav/udav_wnd.cpp:312 mgllab/mgllab.cpp:322 mgllab/mgllab.cpp:461
+msgid "Properties"
+msgstr "Свойства"
+
+#: udav/mem_pnl.cpp:61
+msgid "Properties of selected data array"
+msgstr "Свойства выбранного массива данных"
+
+#: mgllab/table.cpp:342 mgllab/table.cpp:791
+msgid "Pulse prop."
+msgstr "Свойства импульса"
+
+#: udav/calc_dlg.cpp:127 mgllab/mgllab.cpp:600
+msgid "Put function"
+msgstr "Поместить"
+
+#: udav/dat_pnl.cpp:457
+msgid "Put in variable"
+msgstr "Поместить в переменную"
+
+#: udav/dat_pnl.cpp:548
+msgid "Put into this data array"
+msgstr "Поместить в этот массив данных"
+
+#: udav/anim_dlg.cpp:74 mgllab/mathgl.cpp:201
+msgid "Put to script"
+msgstr "В скрипт"
+
+#: src/exec_dat.cpp:1578
+msgid "Put value (numeric or array) to given data element"
+msgstr "Поместить число или массив в заданный элемент данных"
+
+#. U
+#: udav/style_dlg.cpp:247 mgllab/dialogs.cpp:55
+msgid "Q - brown"
+msgstr "Q - коричневый"
+
+#: udav/udav_wnd.cpp:303
+msgid "Quit"
+msgstr "Выход"
+
+#. G
+#: udav/style_dlg.cpp:239 mgllab/dialogs.cpp:47
+msgid "R - maroon"
+msgstr "R - темно-красный"
+
+#: src/exec_set.cpp:733
+msgid "Rasterize plot and save to background"
+msgstr "Растеризовать график и установить вместо фона"
+
+#: src/exec_dat.cpp:1584
+msgid "Read and join data from several files"
+msgstr "Загрузить и объединить данные из нескольких файлов"
+
+#: src/exec_dat.cpp:1583
+msgid "Read data from file"
+msgstr "Загрузить данные из файла"
+
+#: src/exec_dat.cpp:1586
+msgid "Read data from file with sizes specified in first row"
+msgstr "Загрузить данные из файла с размерами из первой строки"
+
+#: src/exec_dat.cpp:1585
+msgid "Read data with name 'id' from HDF file"
+msgstr "Загрузить данные с именем 'id' из HDF файла"
+
+#: udav/udav_wnd.cpp:268 mgllab/mgllab.cpp:367
+msgid "Ready"
+msgstr "Готов"
+
+#: src/exec_dat.cpp:1587
+msgid "Rearrange data dimensions"
+msgstr "Упорядочить размерности массива данных"
+
+#: udav/udav_wnd.cpp:301 mgllab/mgllab.cpp:283
+msgid "Recent files"
+msgstr "Последние файлы"
+
+#: udav/dat_pnl.cpp:768
+msgid "Recreate the data with new sizes and fill it by zeros (Ctrl+Shift+N)."
+msgstr "Пересоздать данные с новым размером и заполнить нулями (Ctrl+Shift+N)."
+
+#: udav/text_pnl.cpp:521
+msgid "Redo"
+msgstr "Отменить"
+
+#: udav/text_pnl.cpp:523
+msgid "Redo editor change (Ctrl+Shift+Z)."
+msgstr "Отменить правку в редакторе (Ctrl+Shift+Z)."
+
+#: widgets/qt.cpp:1130 udav/plot_pnl.cpp:331
+msgid "Redraw"
+msgstr "Перерисовать"
+
+#: udav/anim_dlg.cpp:41 mgllab/mathgl.cpp:184
+msgid "Redraw picture for $0 equal to"
+msgstr "Перерисовать для $0 равного"
+
+#: widgets/fltk.cpp:813
+msgid "Redraw plot"
+msgstr "Перерисовать график"
+
+#: mgllab/dialogs.cpp:1320
+msgid "Refresh"
+msgstr "Обновить"
+
+#: widgets/fltk.cpp:847
+msgid "Refresh the picture"
+msgstr "Обновить рисунок"
+
+#: mgllab/dialogs.cpp:404
+msgid "Relative position of i-th color"
+msgstr "Положение i-го цвета"
+
+#: udav/plot_pnl.cpp:342
+msgid "Reload"
+msgstr "Перезагрузить"
+
+#: widgets/fltk.cpp:815
+msgid "Reload data"
+msgstr "Перезагрузить"
+
+#: widgets/fltk.cpp:853
+msgid "Reload data and refresh the picture"
+msgstr "Перезагрузить данные и обновить рисунок"
+
+#: src/exec_dat.cpp:1525
+msgid "Remove duplicate rows"
+msgstr "Удалить одинаковые строки"
+
+#: src/exec_dat.cpp:1597
+msgid "Remove jump into the data, like phase jumps"
+msgstr "Убрать скачки данных, например скачки фазы"
+
+#: udav/find_dlg.cpp:50 mgllab/editor.cpp:561
+msgid "Replace"
+msgstr "Заменить"
+
+#: mgllab/editor.cpp:564
+msgid "Replace all"
+msgstr "Заменить все"
+
+#: udav/find_dlg.cpp:39 mgllab/editor.cpp:560
+msgid "Replace by:"
+msgstr "Заменить на:"
+
+#: udav/text_pnl.cpp:581
+msgid "Replace expression by its numerical value."
+msgstr "Заменить выражение на его числовое значение."
+
+#: mgllab/editor.cpp:630
+#, c-format
+msgid "Replaced %ld occurrences."
+msgstr "Заменено %ld вхождений."
+
+#: mgllab/dialogs.cpp:891
+#, c-format
+msgid "Required argument %s is not specified!"
+msgstr "Обязательный аргумент %s не задан!"
+
+#: udav/subplot_dlg.cpp:186
+msgid "Reserve at"
+msgstr "Оставить место"
+
+#: mgllab/dialogs.cpp:1303
+msgid "Reserve at:"
+msgstr "Пустое поле"
+
+#: udav/subplot_dlg.cpp:190
+msgid "Reserve space for labels at bottom side (style '_')"
+msgstr "Оставить место для подписей снизу (стиль '_')"
+
+#: udav/subplot_dlg.cpp:188
+msgid "Reserve space for labels at left side (style '<')"
+msgstr "Оставить место для подписей слева (стиль '<')"
+
+#: udav/subplot_dlg.cpp:194
+msgid "Reserve space for labels at right side (style '>')"
+msgstr "Оставить место для подписей справа (стиль '>')"
+
+#: udav/subplot_dlg.cpp:192
+msgid "Reserve space for labels at top side (style '^')"
+msgstr "Оставить место для подписей сверху (стиль '^')"
+
+#: src/exec_set.cpp:734
+msgid "Reset settings and clear picture"
+msgstr "Сбросить настройки и обновить рисунок"
+
+#: udav/dat_pnl.cpp:772 mgllab/table.cpp:759
+msgid "Resize"
+msgstr "Изменить размер"
+
+#: udav/dat_pnl.cpp:774
+msgid "Resize (interpolate) the data to specified sizes (Ctrl+Shift+R)."
+msgstr "Изменить размер (интерполоировать) данных (Ctrl+Shift+R)."
+
+#: src/exec_dat.cpp:1589
+msgid "Resize data array"
+msgstr "Изменить размер массива данных"
+
+#: mgllab/table.cpp:856
+msgid "Resize data with smoothing"
+msgstr "Изменить размер массива данных со сглаживанием"
+
+#: widgets/qt.cpp:1123 udav/plot_pnl.cpp:325
+msgid "Restore"
+msgstr "Восстановить"
+
+#: widgets/fltk.cpp:844
+msgid "Restore default graphics rotation, zoom and perspective"
+msgstr "Восстановить вращение, приближение и перспективу графика"
+
+#: widgets/qt.cpp:1125
+msgid "Restore default graphics rotation, zoom and perspective (Alt+Space)."
+msgstr "Восстановить вращение, приближение и перспективу графика (Alt+Space)."
+
+#: udav/plot_pnl.cpp:327
+msgid "Restore default graphics rotation, zoom and perspective (Ctrl+Space)."
+msgstr "Восстановить вращение, приближение и перспективу графика (Ctrl+Space)."
+
+#: udav/plot_pnl.cpp:344
+msgid "Restore status for 'once' command and reload data (F9)."
+msgstr "Восстановить статус команды 'once' и перезагрузить данные (F9)"
+
+#: udav/calc_dlg.cpp:63 udav/data_dlg.cpp:85 udav/data_dlg.cpp:143
+#: udav/subplot_dlg.cpp:212 mgllab/dialogs.cpp:1315
+msgid "Result"
+msgstr "Итог"
+
+#: udav/data_dlg.cpp:124
+msgid "Result (will have sizes "
+msgstr "Результат (будет иметь размеры "
+
+#: udav/style_dlg.cpp:201 udav/subplot_dlg.cpp:214 mgllab/dialogs.cpp:408
+msgid "Resulting string"
+msgstr "Итоговая строка"
+
+#: src/parser.cpp:1439
+msgid "Return from function"
+msgstr "Возврат из функции"
+
+#: udav/subplot_dlg.cpp:148
+msgid "Right bottom edge"
+msgstr "Правый нижний угол"
+
+#: udav/subplot_dlg.cpp:156
+msgid "Right top edge"
+msgstr "Правый верхний угол"
+
+#: mgllab/table.cpp:166 mgllab/table.cpp:782
+msgid "Roll"
+msgstr "Сдвинуть"
+
+#: src/exec_dat.cpp:1591
+msgid "Roll data along direction(s)"
+msgstr "Сдвинуть данные по направлению"
+
+#. rotate menu
+#: udav/plot_pnl.cpp:540
+msgid "Rotate"
+msgstr "Вращать"
+
+#: widgets/qt.cpp:1110 udav/plot_pnl.cpp:310
+msgid "Rotate by mouse"
+msgstr "Вращать мышкой"
+
+#: udav/plot_pnl.cpp:545
+msgid "Rotate down"
+msgstr "Вращать вниз"
+
+#: udav/plot_pnl.cpp:549
+msgid "Rotate left"
+msgstr "Вращать влево"
+
+#: udav/subplot_dlg.cpp:164 mgllab/dialogs.cpp:1294
+msgid "Rotate on"
+msgstr "Поворот"
+
+#: widgets/fltk.cpp:840
+msgid "Rotate picture by holding left mouse button"
+msgstr "Вращать рисунок при удержании кнопок мыши"
+
+#: src/exec_set.cpp:735
+msgid "Rotate plot"
+msgstr "Вращать график"
+
+#: udav/plot_pnl.cpp:553
+msgid "Rotate right"
+msgstr "Вращать вправо"
+
+#: udav/plot_pnl.cpp:541
+msgid "Rotate up"
+msgstr "Вращать вверх"
+
+#: mgllab/dialogs.cpp:356
+msgid "Rotation"
+msgstr "Вращение"
+
+#: widgets/qt.cpp:1254
+msgid "Run slideshow (CTRl+F5)."
+msgstr "Запустить анимацию (CTRl+F5)."
+
+#: udav/plot_pnl.cpp:570
+msgid ""
+"Run slideshow (Ctrl+F5). If no parameter specified\n"
+"then the dialog with slideshow options will appear."
+msgstr ""
+"Запустить анимацию (CTRl+F5). Если ее параметры\n"
+"не заданы, то будет показан диалог настройки."
+
+#: widgets/fltk.cpp:885
+msgid "Run/Stop slideshow (graphics animation)"
+msgstr "Запустить/остановить анимацию"
+
+#: udav/prop_dlg.cpp:141
+msgid "Russian"
+msgstr "Русский"
+
+#: widgets/qt.cpp:1080 udav/plot_pnl.cpp:488
+msgid "STL"
+msgstr ""
+
+#: widgets/qt.cpp:1073 udav/plot_pnl.cpp:480
+msgid "SVG"
+msgstr ""
+
+#: udav/style_dlg.cpp:107
+msgid "Saturation"
+msgstr "Насыщенность"
+
+#: udav/setup_dlg.cpp:143 mgllab/editor.cpp:282
+msgid "Save"
+msgstr "Сохранить"
+
+#: mgllab/help.cpp:250 mgllab/table.cpp:456
+msgid "Save Data?"
+msgstr "Сохранить данные?"
+
+#: widgets/fltk.cpp:572 mgllab/mgllab.cpp:214
+msgid "Save File As?"
+msgstr "Сохранить файл?"
+
+#: udav/anim_dlg.cpp:83
+msgid "Save JPEG frames"
+msgstr "Сохранить кадры в JPEG"
+
+#: udav/udav_wnd.cpp:290 mgllab/mgllab.cpp:281
+msgid "Save as ..."
+msgstr "Сохранить как ..."
+
+#: udav/dat_pnl.cpp:688
+msgid "Save data"
+msgstr "Сохранить данные"
+
+#: src/exec_dat.cpp:1594
+msgid "Save data to HDF5 file"
+msgstr "Сохранить данные в HDF5 файл"
+
+#: udav/dat_pnl.cpp:690
+msgid "Save data to a file (Ctrl+Shift+S)."
+msgstr "Сохранить данные в файл (Ctrl+Shift+S)."
+
+#: src/exec_dat.cpp:1593 mgllab/table.cpp:842
+msgid "Save data to file"
+msgstr "Сохранить данные в файл"
+
+#: mgllab/mgllab.cpp:280
+msgid "Save file"
+msgstr "Сохранить файл"
+
+#: mgllab/mgllab.cpp:473
+msgid "Save file before redrawing"
+msgstr "Сохранить файл перед рисованием"
+
+#: udav/udav_wnd.cpp:201
+msgid "Save script"
+msgstr "Сохранить скрипт"
+
+#: udav/udav_wnd.cpp:203
+msgid "Save script to a file (Ctrl+S)"
+msgstr "Сохранить скрипт в файл (Ctrl+S)"
+
+#: mgllab/editor.cpp:508
+msgid "Save script to file"
+msgstr "Сохранить скрипт в файл"
+
+#: mgllab/help.cpp:172
+msgid "Save selected data to file."
+msgstr "Сохранить выбранные данные в файл."
+
+#: mgllab/table.cpp:751
+msgid "Save to file"
+msgstr "Сохранить в файл"
+
+#: udav/udav_wnd.cpp:672
+msgid "Saving aborted"
+msgstr "Сохранение прервано"
+
+#: udav/newcmd_dlg.cpp:179 mgllab/dialogs.cpp:720
+msgid "Scale and rotate"
+msgstr "Масштаб и вращение"
+
+#: udav/udav_wnd.cpp:237
+msgid "Script"
+msgstr "Скрипт"
+
+#: udav/find_dlg.cpp:43 mgllab/editor.cpp:563
+msgid "Search backward"
+msgstr "Искать назад"
+
+#: udav/text_pnl.cpp:543 mgllab/mgllab.cpp:297
+msgid "Select all"
+msgstr "Выделить все"
+
+#: udav/text_pnl.cpp:585
+msgid "Select and insert file name."
+msgstr "Выбрать и вставить имя файла."
+
+#: udav/text_pnl.cpp:589
+msgid "Select and insert folder name."
+msgstr "Выбрать и вставить путь к папке."
+
+#: mgllab/dialogs.cpp:565
+msgid "Select data argument"
+msgstr "Выбрать данные"
+
+#: mgllab/dialogs.cpp:160
+msgid "Select direction"
+msgstr "Выбрать направление"
+
+#: mgllab/editor.cpp:654
+msgid "Select file name"
+msgstr "Выбрать имя файла"
+
+#: udav/newcmd_dlg.cpp:339 udav/newcmd_dlg.cpp:357
+msgid "Select first the proper kind of arguments"
+msgstr "Сначала выберите вариант аргументов"
+
+#: mgllab/editor.cpp:667
+msgid "Select folder name"
+msgstr "Выбрать путь к папке"
+
+#: udav/info_dlg.cpp:39
+msgid "Select kind of plot"
+msgstr "Выбрать тип графика"
+
+#: src/exec_set.cpp:749
+msgid "Select variant of plot style(s)"
+msgstr "Выбрать вариант стиля графика"
+
+#: mgllab/mathgl.cpp:166
+msgid "Set"
+msgstr "Задать"
+
+#: src/exec_set.cpp:745
+msgid "Set additional tick and axis labels shift"
+msgstr "Задает дополнительный сдвиш меток осей"
+
+#: src/exec_set.cpp:695
+msgid "Set ambient light brightness"
+msgstr "Задает яркость фонового освещения"
+
+#: src/exec_set.cpp:716
+msgid "Set arbitrary position of plot in picture"
+msgstr "Задать произвольную область рисования внутри рисунка"
+
+#: udav/udav_wnd.cpp:315 mgllab/mgllab.cpp:323
+msgid "Set arguments"
+msgstr "Задать аргументы"
+
+#: src/exec_set.cpp:697
+msgid "Set aspect ration"
+msgstr "Задать соотношение сторон"
+
+#: src/exec_set.cpp:699
+msgid "Set axis and tick style"
+msgstr "Задать стиль осей и меток"
+
+#: src/exec_set.cpp:725
+msgid "Set axis origin"
+msgstr "Задать начало координат"
+
+#: src/exec_set.cpp:732
+msgid "Set axis ranges"
+msgstr "Задать диапазон осей"
+
+#: src/exec_set.cpp:701
+msgid "Set bounding box for 2d export"
+msgstr "Задать границы для 2d экспорта"
+
+#: src/exec_set.cpp:722
+msgid "Set brush for given mask id"
+msgstr "Задать кисть для маски с выбранным id"
+
+#: src/exec_set.cpp:706
+msgid "Set color range"
+msgstr "Задать диапазон цвета"
+
+#: src/exec_dat.cpp:1556
+msgid "Set column id for data"
+msgstr "Задать id колонок данных"
+
+#: mgllab/dialogs.cpp:108
+msgid "Set cutting off/on for particular plot"
+msgstr "Вкл/выкл обрезание для конкретного графика"
+
+#: udav/open_dlg.cpp:62
+msgid "Set data sizes manually"
+msgstr "Задать размеры данных вручную"
+
+#: src/exec_set.cpp:700
+msgid "Set default bars width"
+msgstr "Задать размер полос по умолчанию"
+
+#: src/exec_set.cpp:730
+msgid "Set default filename"
+msgstr "Задать имя файла по умолчанию"
+
+#: src/exec_set.cpp:694
+msgid "Set default transparency"
+msgstr "Задать прозрачность по умолчанию"
+
+#: src/exec_set.cpp:709
+msgid "Set diffusive light brightness"
+msgstr "Задать яркость рассеянного света"
+
+#: src/exec_set.cpp:710
+msgid "Set draw region for quality&4"
+msgstr "Задать область рисования при quality&4"
+
+#: udav/subplot_dlg.cpp:47 udav/subplot_dlg.cpp:89
+msgid "Set drawing area as cell of matrix nx*ny."
+msgstr "Задать область рисования как ячейку матрицы nx*ny."
+
+#: udav/subplot_dlg.cpp:110
+msgid "Set drawing area as cells of column."
+msgstr "Задать область рисования как ячейку колонки."
+
+#: udav/subplot_dlg.cpp:64 udav/subplot_dlg.cpp:140
+msgid "Set drawing area as cells of matrix nx*ny."
+msgstr "Задать область рисования как ячейки матрицы nx*ny."
+
+#: udav/subplot_dlg.cpp:127
+msgid "Set drawing area as cells of stick."
+msgstr "Задать область рисования как ячейку бруска."
+
+#: mgllab/dialogs.cpp:117
+msgid "Set lighting off/on for particular plot"
+msgstr "Вкл/выкл освещение отдельного графика"
+
+#: src/exec_set.cpp:723
+msgid "Set number of lines in mesh/fall/vect and so on"
+msgstr "Задать примерное число линий в mesh/fall/vect ..."
+
+#: src/exec_set.cpp:717
+msgid "Set number of marks in the legend"
+msgstr "Задать число маркеров в легенде"
+
+#: src/exec_set.cpp:711
+msgid "Set number of visible faces"
+msgstr "Задать число видимых граней"
+
+#: src/exec_set.cpp:727
+msgid "Set palette for 1D plots"
+msgstr "Задать палитру для 1D графиков"
+
+#: src/exec_set.cpp:729
+msgid "Set perspective"
+msgstr "Задать перспективу"
+
+#: src/exec_set.cpp:737
+msgid "Set picture size"
+msgstr "Задать размер рисунка"
+
+#: src/exec_set.cpp:731
+msgid "Set plot quality"
+msgstr "Задать качество рисования картинки"
+
+#: src/exec_set.cpp:742
+msgid "Set position of plot as cell of matrix"
+msgstr "Задать область рисования как ячейку матрицы"
+
+#: src/exec_set.cpp:724
+msgid "Set position of plot block in matrix"
+msgstr "Задать область рисования как блок в матрице"
+
+#: src/exec_set.cpp:705
+msgid "Set position of plot inside cell of column"
+msgstr "Задать область рисования как ячейку колонки"
+
+#: src/exec_set.cpp:715
+msgid "Set position of plot inside cell of matrix"
+msgstr "Задать область рисования внутри ячейки колонки"
+
+#: src/exec_set.cpp:741
+msgid "Set position of plot inside cell of rotated stick"
+msgstr "Задать область рисования как ячейку повернутого бруска"
+
+#: src/exec_set.cpp:740
+msgid "Set position of plot inside cell of sheared stick"
+msgstr "Задать область рисования как ячейку наклоненной колонки"
+
+#: src/exec_set.cpp:753
+msgid "Set range for x-axis"
+msgstr "Задать диапазон по x"
+
+#: src/exec_set.cpp:755
+msgid "Set range for y-axis"
+msgstr "Задать диапазон по y"
+
+#: src/exec_set.cpp:759
+msgid "Set range for z-axis"
+msgstr "Задать диапазон по z"
+
+#: src/exec_set.cpp:738
+msgid "Set scaling factor for further setsize"
+msgstr "Задать множитель для всех 'setsize'"
+
+#: mgllab/mathgl.cpp:143
+msgid "Set script arguments"
+msgstr "Задать аргументы скрипта"
+
+#: mgllab/dialogs.cpp:105
+msgid "Set size for text, marks and others"
+msgstr "Задать размер текста, маркеров и пр."
+
+#: src/exec_set.cpp:696
+msgid "Set size of arrows"
+msgstr "Задать размер стрелок"
+
+#: src/exec_set.cpp:721
+msgid "Set size of markers"
+msgstr "Задать размер маркеров"
+
+#: src/exec_set.cpp:728
+msgid "Set size of semi-transparent area around line"
+msgstr "Задать размер полупрозрачной области около линии"
+
+#: src/exec_set.cpp:726
+msgid "Set tick labels drawing at origin"
+msgstr "Разрешить вывод меток осей в начале координат"
+
+#: src/exec_set.cpp:744
+msgid "Set tick length"
+msgstr "Задать длину меток осей"
+
+#: src/exec_set.cpp:707
+msgid "Set ticks for colorbar"
+msgstr "Задать метки для цветовой шкалы"
+
+#: src/exec_set.cpp:754
+msgid "Set ticks for x-axis"
+msgstr "Задать метки для оси x"
+
+#: src/exec_set.cpp:756
+msgid "Set ticks for y-axis"
+msgstr "Задать метки для оси y"
+
+#: src/exec_set.cpp:760
+msgid "Set ticks for z-axis"
+msgstr "Задать метки для оси z"
+
+#: src/exec_set.cpp:746
+msgid "Set ticks in time format"
+msgstr "Задать метки в формате времени"
+
+#: src/exec_set.cpp:748
+msgid "Set ticks tuning"
+msgstr "Включить оптимизацию меток осей"
+
+#: src/exec_set.cpp:736
+msgid "Set to auto rotate text or not"
+msgstr "Разрешить поворот текста"
+
+#: udav/subplot_dlg.cpp:196
+msgid "Set to use whole area (style '#')"
+msgstr "Задать использование всей области (стиль '#')"
+
+#: src/exec_set.cpp:747
+msgid "Set type transparency"
+msgstr "Задать тип прозрачности"
+
+#: widgets/qt.cpp:1209
+msgid "Set value of \\phi angle."
+msgstr "Задать значени угла φ"
+
+#: udav/plot_pnl.cpp:472
+msgid ""
+"Set value of \\phi angle.\n"
+"You can use keys (Shift+Meta+Left or Shift+Meta+Right)."
+msgstr ""
+"Задать значени угла φ.\n"
+"Вы можете использовать клавиши (Shift+Meta+Left или Shift+Meta+Right)."
+
+#: widgets/qt.cpp:1203
+msgid "Set value of \\theta angle."
+msgstr "Задать значени угла θ"
+
+#: udav/plot_pnl.cpp:466
+msgid ""
+"Set value of \\theta angle.\n"
+"You can use keys (Shift+Meta+Up or Shift+Meta+Down)."
+msgstr ""
+"Задать значени угла θ.\n"
+"Вы можете использовать клавиши (Shift+Meta+Up или Shift+Meta+Down)."
+
+#: udav/udav_wnd.cpp:311
+msgid "Settings"
+msgstr "Настройки"
+
+#: mgllab/mgllab.cpp:321
+msgid "Setup"
+msgstr "Настройки"
+
+#: mgllab/mgllab.cpp:324
+msgid "Setup animation"
+msgstr "Настроить анимацию"
+
+#: udav/prop_dlg.cpp:80
+msgid "Setup colors for:"
+msgstr "Настроить цвета:"
+
+#: src/exec_set.cpp:713
+msgid "Setup font"
+msgstr "Настроить шрифт"
+
+#: src/exec_set.cpp:718
+msgid "Setup light"
+msgstr "Настроить освещение"
+
+#: src/exec_prm.cpp:579
+msgid "Setup or draw axis"
+msgstr "Настроить или нарисовать оси"
+
+#: src/exec_set.cpp:708
+msgid "Setup plot points cutting"
+msgstr "Настроить обрезание точек графика"
+
+#: mgllab/dialogs.cpp:947
+msgid "Setup script"
+msgstr "Настроить скрипт"
+
+#: udav/plot_pnl.cpp:573
+msgid "Setup show"
+msgstr "Настроить анимацию"
+
+#: udav/dat_pnl.cpp:623
+msgid "Sew data along direction(s)"
+msgstr "Сшить данные по направлению"
+
+#: mgllab/table.cpp:166 mgllab/table.cpp:783
+msgid "Sew phase"
+msgstr "Сшить фазу"
+
+#: mgllab/dialogs.cpp:350
+msgid "Sharp colors"
+msgstr "Контрастные"
+
+#: src/exec_set.cpp:739
+msgid "Shear plot"
+msgstr "Наклон графика"
+
+#: widgets/fltk.cpp:878
+msgid "Shift the picture down"
+msgstr "Сдвинуть рисунок вниз"
+
+#: widgets/fltk.cpp:870
+msgid "Shift the picture left"
+msgstr "Сдвинуть рисунок слево"
+
+#: widgets/fltk.cpp:876
+msgid "Shift the picture right"
+msgstr "Сдвинуть рисунок вправо"
+
+#: widgets/fltk.cpp:868
+msgid "Shift the picture up"
+msgstr "Сдвинуть рисунок вверх"
+
+#: udav/newcmd_dlg.cpp:56 mgllab/dialogs.cpp:737
+msgid "Short description of selected command"
+msgstr "Краткое описание выбранной команды"
+
+#: udav/info_dlg.cpp:54
+msgid "Short information about the data."
+msgstr "Краткая информация о данных"
+
+#: udav/hint_dlg.cpp:62
+msgid "Show at startup"
+msgstr "Показать при запуске"
+
+#: udav/udav_wnd.cpp:210
+msgid ""
+"Show calculator which evaluate and help to type textual formulas.\n"
+"Textual formulas may contain data variables too."
+msgstr ""
+"Показать калькулятор, который вычисляет текстовые формулы,\n"
+"которые могут содержать и переменные из скрипта."
+
+#: mgllab/editor.cpp:525 mgllab/editor.cpp:527
+msgid "Show calculator window"
+msgstr "Показать окно калькулятора"
+
+#: udav/udav_wnd.cpp:314
+msgid "Show dialog for UDAV properties."
+msgstr "Показать диалог настроек UDAV"
+
+#: udav/text_pnl.cpp:560 udav/plot_pnl.cpp:441
+msgid "Show dialog for new command or edit arguments of existed one."
+msgstr "Показать диалог ввода новой команды или редактирования существующей"
+
+#: udav/text_pnl.cpp:564 udav/plot_pnl.cpp:446
+msgid "Show dialog for new inplot and put it into the script."
+msgstr "Показать диалог создания под-графика и вставки его в скрипт"
+
+#: udav/text_pnl.cpp:577
+msgid ""
+"Show dialog for options and put it into the script.\n"
+"Options are used for additional setup the plot."
+msgstr ""
+"Показать диалог ввода опций и вставки их в скрипт.\n"
+"Опции используются для дополнительной настройки графика."
+
+#: udav/text_pnl.cpp:598
+msgid ""
+"Show dialog for plot setup and put code into the script.\n"
+"This dialog setup axis, labels, lighting and other general things."
+msgstr "Показать диалог настройки рисунка: осей, подписей, освещения и пр."
+
+#: udav/text_pnl.cpp:573
+msgid ""
+"Show dialog for styles and put it into the script.\n"
+"Styles define the plot view (color scheme, marks, dashing and so on)."
+msgstr ""
+"Показать диалог стиля графика и вставить его в скрипт.\n"
+"Стиль задает цветовую схему, маркеры, штриховку и пр."
+
+#: udav/text_pnl.cpp:548
+msgid "Show dialog for text finding (Ctrl+F)."
+msgstr "Показать диалог поиска текста (Ctrl+F)."
+
+#: udav/udav_wnd.cpp:326
+msgid "Show help on MGL commands (F1)."
+msgstr "Показать справку по командам MGL (F1)."
+
+#: udav/udav_wnd.cpp:219
+msgid "Show hidden plots"
+msgstr "Показать скрытые графики"
+
+#: mgllab/help.cpp:303
+msgid "Show hint on startup"
+msgstr "Показать подсказки при старте"
+
+#: udav/udav_wnd.cpp:330
+msgid "Show hints of MGL usage."
+msgstr "Показать подсказки по использованию MGL."
+
+#: udav/udav_wnd.cpp:213
+msgid "Show info"
+msgstr "Показать информацию"
+
+#: mgllab/mgllab.cpp:299
+msgid "Show lines"
+msgstr "Показать строки"
+
+#: widgets/fltk.cpp:886
+msgid "Show next frame in slideshow"
+msgstr "Показать следующий кадр"
+
+#: widgets/qt.cpp:1249 udav/plot_pnl.cpp:563
+msgid "Show next slide (Ctrl+.)."
+msgstr "Показать следующий кадр (Ctrl+.)."
+
+#: widgets/fltk.cpp:881
+msgid "Show previous frame in slideshow"
+msgstr "Показать предыдущий кадр"
+
+#: widgets/qt.cpp:1258 udav/plot_pnl.cpp:578
+msgid "Show previous slide (Ctrl+,)."
+msgstr "Показать предыдущий кадр (Ctrl+,)."
+
+#: mgllab/table.cpp:777
+msgid "Sin FFT"
+msgstr "Синус-Фурье"
+
+#: udav/dat_pnl.cpp:620
+msgid "Sin-Fourier transform along direction(s)"
+msgstr "Синус-Фурье преобразование вдоль направления"
+
+#: src/exec_dat.cpp:1598
+msgid "Sin-Fourier transform at some direction"
+msgstr "Синус-Фурье преобразование вдоль направления"
+
+#: mgllab/table.cpp:165
+msgid "Sinus FFT"
+msgstr "Синус-Фурье"
+
+#: udav/opt_dlg.cpp:70 mgllab/dialogs.cpp:104 mgllab/dialogs.cpp:359
+msgid "Size"
+msgstr "Размер"
+
+#: udav/subplot_dlg.cpp:114
+msgid "Size of column"
+msgstr "Размер колонки"
+
+#: udav/subplot_dlg.cpp:131
+msgid "Size of stick"
+msgstr "Размер бруска"
+
+#. size menu
+#: udav/mem_pnl.cpp:68 udav/dat_pnl.cpp:765 mgllab/dialogs.cpp:1015
+#: mgllab/table.cpp:757
+msgid "Sizes"
+msgstr "Размеры"
+
+#: src/parser.cpp:1425
+msgid "Skip commands and iterate for-loop again"
+msgstr "Пропустить команды до конца цикла for"
+
+#: widgets/qt.cpp:1251 udav/plot_pnl.cpp:566
+msgid "Slideshow"
+msgstr "Анимация"
+
+#: mgllab/table.cpp:163 mgllab/table.cpp:771
+msgid "Smooth"
+msgstr "Сгладить"
+
+#: src/exec_dat.cpp:1599
+msgid "Smooth data"
+msgstr "Сгладить массив данных"
+
+#: udav/dat_pnl.cpp:613
+msgid "Smooth data along direction(s)"
+msgstr "Сгладить массив данных по направлению"
+
+#: src/exec_dat.cpp:1582
+msgid "Solve Hamiltonian ODE (find GO ray or trajectory)"
+msgstr "Решить гамильтонову ОДУ (найти ГО луч/траекторию)"
+
+#: src/exec_dat.cpp:1573
+msgid "Solve ODE"
+msgstr "Решить систему обыкновенных диф. уравнений"
+
+#: src/exec_dat.cpp:1575
+msgid "Solve PDE"
+msgstr "Решить уравнение в частных производных"
+
+#: src/exec_dat.cpp:1580
+msgid "Solve PDE in accompanied coordinates for 2d case"
+msgstr "Решить PDE в сопровождающей системе координат (2d)"
+
+#: src/exec_dat.cpp:1581
+msgid "Solve PDE in accompanied coordinates for 3d case"
+msgstr "Решить PDE в сопровождающей системе координат (3d)"
+
+#: src/exec_dat.cpp:1524
+msgid "Solve PDE using advanced method (X-Y only)"
+msgstr "Решить PDE (сложные уравнения, 2d случай)"
+
+#: src/exec_dat.cpp:1613
+msgid "Solve tridiagonal matrix"
+msgstr "Решить трехдиагональную систему"
+
+#: src/exec_dat.cpp:1601
+msgid "Sort data by values in column"
+msgstr "Сортировать данные по значениям в колонке"
+
+#: udav/prop_dlg.cpp:141
+msgid "Spanish"
+msgstr ""
+
+#: udav/calc_dlg.cpp:194
+msgid "Special"
+msgstr "Специальные"
+
+#: mgllab/table.cpp:129
+msgid ""
+"Specify new data size\n"
+"Data will be interpolated"
+msgstr ""
+"Укажите новый размер данных.\n"
+"Данные будут интерполированы."
+
+#: mgllab/table.cpp:114
+msgid ""
+"Specify new data size\n"
+"Data will be zero filled"
+msgstr ""
+"Укажите новый размер данных.\n"
+"Данные будут обнулены."
+
+#: mgllab/table.cpp:144
+msgid ""
+"Specify the skipping step\n"
+"Each m-th point will be saved only"
+msgstr ""
+"Укажите шаг пропуска.\n"
+"Только каждая m-ая точка будет сохранена."
+
+#: udav/dat_pnl.cpp:778 mgllab/table.cpp:760
+msgid "Squeeze"
+msgstr "Сжать"
+
+#: src/exec_dat.cpp:1602
+msgid "Squeeze data"
+msgstr "Сжать данные"
+
+#: udav/setup_dlg.cpp:84
+msgid "Start"
+msgstr "Старт"
+
+#: src/parser.cpp:1434
+msgid "Start function definition and stop execution of main script"
+msgstr "Начало определения функции и остановка выполнения основного скрипта"
+
+#: src/parser.cpp:1437
+msgid "Start next for-loop iteration"
+msgstr "Начать новую итерацию цикла for"
+
+#: src/parser.cpp:1438
+msgid "Start/close commands which should executed only once"
+msgstr "Начало/конец блока команд, которые будут выполняться единожды"
+
+#: udav/subplot_dlg.cpp:76
+msgid "Starting cell index"
+msgstr "Индекс начальной ячейки"
+
+#: udav/setup_dlg.cpp:117
+msgid "State"
+msgstr "Состояние"
+
+#: src/exec_dat.cpp:1539
+msgid "Step for pulse diffraction"
+msgstr "Шаг для расчета дифракции импульса"
+
+#: widgets/qt.cpp:1135 udav/plot_pnl.cpp:347
+msgid "Stop"
+msgstr "Стоп"
+
+#: widgets/fltk.cpp:849
+msgid "Stop drawing"
+msgstr "Остановить рисование"
+
+#: src/parser.cpp:1440
+msgid "Stop execution"
+msgstr "Остановить выполнение скрипта"
+
+#: udav/plot_pnl.cpp:349
+msgid "Stop script execution (F7)."
+msgstr "Остановить выполнение скрипта (F7)"
+
+#: udav/args_dlg.cpp:59 mgllab/mathgl.cpp:162
+msgid "String for $0"
+msgstr "Строка для $0"
+
+#: udav/args_dlg.cpp:41 mgllab/mathgl.cpp:144
+msgid "String for $1"
+msgstr "Строка для $1"
+
+#: udav/args_dlg.cpp:43 mgllab/mathgl.cpp:146
+msgid "String for $2"
+msgstr "Строка для $2"
+
+#: udav/args_dlg.cpp:45 mgllab/mathgl.cpp:148
+msgid "String for $3"
+msgstr "Строка для $3"
+
+#: udav/args_dlg.cpp:47 mgllab/mathgl.cpp:150
+msgid "String for $4"
+msgstr "Строка для $4"
+
+#: udav/args_dlg.cpp:49 mgllab/mathgl.cpp:152
+msgid "String for $5"
+msgstr "Строка для $5"
+
+#: udav/args_dlg.cpp:51 mgllab/mathgl.cpp:154
+msgid "String for $6"
+msgstr "Строка для $6"
+
+#: udav/args_dlg.cpp:53 mgllab/mathgl.cpp:156
+msgid "String for $7"
+msgstr "Строка для $7"
+
+#: udav/args_dlg.cpp:55 mgllab/mathgl.cpp:158
+msgid "String for $8"
+msgstr "Строка для $8"
+
+#: udav/args_dlg.cpp:57 mgllab/mathgl.cpp:160
+msgid "String for $9"
+msgstr "Строка для $9"
+
+#: udav/files_dlg.cpp:38
+msgid "String for %1"
+msgstr "Строка для %1"
+
+#: udav/files_dlg.cpp:40
+msgid "String for %2"
+msgstr "Строка для %2"
+
+#: udav/files_dlg.cpp:42
+msgid "String for %3"
+msgstr "Строка для %3"
+
+#: udav/files_dlg.cpp:44
+msgid "String for %4"
+msgstr "Строка для %4"
+
+#: udav/files_dlg.cpp:46
+msgid "String for %5"
+msgstr "Строка для %5"
+
+#: udav/files_dlg.cpp:48
+msgid "String for %6"
+msgstr "Строка для %6"
+
+#: udav/files_dlg.cpp:50
+msgid "String for %7"
+msgstr "Строка для %7"
+
+#: udav/files_dlg.cpp:52
+msgid "String for %8"
+msgstr "Строка для %8"
+
+#: udav/files_dlg.cpp:54
+msgid "String for %9"
+msgstr "Строка для %9"
+
+#: udav/prop_dlg.cpp:85
+msgid "Strings"
+msgstr "Строки"
+
+#: udav/subplot_dlg.cpp:208 mgllab/dialogs.cpp:1314
+msgid "Style"
+msgstr "Стиль"
+
+#: udav/setup_dlg.cpp:80
+msgid "SubTicks"
+msgstr "Подметки"
+
+#: mgllab/dialogs.cpp:959
+msgid "Subticks"
+msgstr "Подметки"
+
+#: src/exec_dat.cpp:1605
+msgid "Subtract data or number"
+msgstr "Вычесть данные или число"
+
+#: mgllab/table.cpp:795
+msgid "Subtract to"
+msgstr "Вычесть"
+
+#: udav/prop_dlg.cpp:94
+msgid "Suffixes"
+msgstr "Суффиксы"
+
+#: udav/dat_pnl.cpp:539
+msgid "Sum along direction(s)"
+msgstr "Суммировать вдоль направления"
+
+#: udav/dat_pnl.cpp:614
+msgid "Summarize data along direction(s)"
+msgstr "Суммировать вдоль направления"
+
+#. { _("Histogram of"),	0, hist_cb },
+#: mgllab/table.cpp:342 mgllab/table.cpp:788
+msgid "Summation of"
+msgstr "Сумма от"
+
+#: src/exec_dat.cpp:1607
+msgid "Swap data (useful after Fourier transform)"
+msgstr "Поменять местами левую и правую части данных"
+
+#: udav/dat_pnl.cpp:618
+msgid "Swap data along direction(s)"
+msgstr "Поменять местами данные по направлению"
+
+#: mgllab/table.cpp:164 mgllab/table.cpp:776
+msgid "Swap parts"
+msgstr "Поменять местами"
+
+#: src/exec_set.cpp:712
+msgid "Switch on/off fog"
+msgstr "Вкл/выкл туман"
+
+#: src/exec_set.cpp:714
+msgid "Switch on/off gray-scale mode"
+msgstr "Вкл/выкл режим оттенков серого"
+
+#: widgets/fltk.cpp:836
+msgid "Switch on/off grid drawing"
+msgstr "Вкл/выкл рисование сетки"
+
+#: udav/plot_pnl.cpp:307
+msgid "Switch on/off grid of absolute coordinates (Ctrl+G)."
+msgstr "Вкл/выкл сетку абсолютных координат (Ctrl+G)."
+
+#: widgets/qt.cpp:1108
+msgid "Switch on/off lightning for the graphics (Alt+L)."
+msgstr "Вкл/выкл освещение графика (Alt+L)."
+
+#: udav/plot_pnl.cpp:301
+msgid "Switch on/off lightning for the graphics (Ctrl+L)."
+msgstr "Вкл/выкл освещение графика (Ctrl+L)."
+
+#: widgets/fltk.cpp:833
+msgid "Switch on/off lightning in the picture"
+msgstr "Вкл/выкл освещение графика"
+
+#: widgets/qt.cpp:1114 udav/plot_pnl.cpp:314
+msgid ""
+"Switch on/off mouse handling of the graphics\n"
+"(rotation, shifting, zooming and perspective)."
+msgstr ""
+"Вкл/выкл изменение графика мышью\n"
+"(вращение, сдвиг, приближение и перспективу)."
+
+#: widgets/qt.cpp:1120
+msgid "Switch on/off mouse zoom of selected region."
+msgstr "Вкл/выкл приближение мышью выбранной области."
+
+#: src/exec_set.cpp:743
+msgid "Switch on/off to use ternary axis"
+msgstr "Указать тип тернарных координат или проекций"
+
+#: src/exec_set.cpp:693
+msgid "Switch on/off transparency"
+msgstr "Вкл/выкл прозрачность"
+
+#: widgets/qt.cpp:1102
+msgid "Switch on/off transparency for the graphics (Alt+T)."
+msgstr "Вкл/выкл прозрачность рисунка (Alt+T)."
+
+#: udav/plot_pnl.cpp:294
+msgid "Switch on/off transparency for the graphics (Ctrl+T)."
+msgstr "Вкл/выкл прозрачность рисунка (Ctrl+T)."
+
+#: widgets/fltk.cpp:830
+msgid "Switch on/off transparency in the picture"
+msgstr "Вкл/выкл прозрачность рисунка"
+
+#: mgllab/table.cpp:552
+msgid "Symmetrical range"
+msgstr "Симметричный диапазон"
+
+#: udav/dat_pnl.cpp:366
+msgid "Symmetrical?"
+msgstr "Симметрично?"
+
+#: src/addon.cpp:110 src/base_cf.cpp:266
+#, c-format
+msgid "TEST: %s\n"
+msgstr "ТЕСТ: %s\n"
+
+#: udav/open_dlg.cpp:82 udav/setup_dlg.cpp:88 mgllab/dialogs.cpp:961
+msgid "Template"
+msgstr "Шаблон"
+
+#: udav/setup_dlg.cpp:140
+msgid "Template name"
+msgstr "Имя шаблона"
+
+#: udav/setup_dlg.cpp:163
+msgid "Template saved"
+msgstr "Шаблон сохранен"
+
+#: mgllab/dialogs.cpp:1038
+msgid "Ternary"
+msgstr "Тернарный"
+
+#: mgllab/dialogs.cpp:1472
+msgid "Text"
+msgstr "Текст"
+
+#: udav/style_dlg.cpp:167 mgllab/dialogs.cpp:376
+msgid "Text align"
+msgstr "Выравнивание"
+
+#: udav/newcmd_dlg.cpp:172 mgllab/dialogs.cpp:713
+msgid "Text and legend"
+msgstr "Текст и легенда"
+
+#: udav/style_dlg.cpp:164
+msgid "Text color"
+msgstr "Цвет текста"
+
+#: udav/style_dlg.cpp:123 mgllab/dialogs.cpp:343
+msgid "Text on contours"
+msgstr "Текст на кривых"
+
+#: mgllab/dialogs.cpp:367
+msgid "Text style"
+msgstr "Стиль текста"
+
+#: udav/hint_dlg.cpp:48 mgllab/help.cpp:282
+msgid ""
+"The calculator can help you to put complex expression in the script. Just "
+"type the expression (which may depend on coordinates x,y,z and so on) and "
+"put it into the script."
+msgstr ""
+"Калькулятор поможет вставить в скрипт сложное выражение. Просто наберите в "
+"калькуляторе выражение (которое может зависеть от координат x,y,z и др.) и "
+"вставьте его в скрипт."
+
+#: mgllab/editor.cpp:280
+msgid ""
+"The current file has not been saved.\n"
+"Would you like to save it now?"
+msgstr "Текущий документ не сохранен. Сохранить сейчас?"
+
+#: udav/hint_dlg.cpp:50 mgllab/help.cpp:284
+msgid ""
+"The special dialog (Edit|Insert|New Command) help you select the command, "
+"fill its arguments and put it into the script."
+msgstr ""
+"Специальный диалог (Правка|Вставить|Новая команда) поможет Вам выбрать "
+"команду, заполнить ее аргументы и вставить в скрипт."
+
+#: src/crust.cpp:559
+msgid ""
+"There are duplicated or indistinguishably adjacent points for triangulation."
+msgstr "Повторяющиеся или близкие точки при триангуляции"
+
+#. mglScrStr
+#: src/base.cpp:236
+msgid "There is changing temporary data in script"
+msgstr "Попытка изменить временные данные в скрипте"
+
+#: udav/text_pnl.cpp:124
+msgid "There is manual primitives."
+msgstr "Есть примитивы, заданные вручную"
+
+#: udav/newcmd_dlg.cpp:343
+msgid "There is no 'fmt' argument for this command"
+msgstr "Отсутствует 'fmt' аргумент для этой команды"
+
+#: udav/text_pnl.cpp:137 mgllab/editor.cpp:681
+msgid "There is no fitted formula."
+msgstr "Нет подобранной формулы."
+
+#: utils/mglcgi.cpp:74
+#, c-format
+msgid "There is no query. Exit.\n"
+msgstr "Нет запроса. Выхожу.\n"
+
+#: udav/text_pnl.cpp:109
+msgid "There is no selection to evaluate."
+msgstr "Ничего не выделено для вычисления."
+
+#: udav/hint_dlg.cpp:47 mgllab/help.cpp:281
+msgid ""
+"There is powerful calculator with a lot of special functions. You can use "
+"buttons or keyboard to type the expression. Also you can use existed "
+"variables in the expression."
+msgstr ""
+"Есть мощный калькулятор с большим числом специальных функций. Выражения "
+"можно набирать кнопками или с клавиатуры. Также можно использовать "
+"переменные из скрипта."
+
+#. mglScrCmd
+#: src/base.cpp:234
+msgid "There is too long string(s) in script"
+msgstr "Слишком длинная строка в скрипте"
+
+#. mglScrLong
+#: src/base.cpp:235
+msgid "There is unbalanced ' in script"
+msgstr "Лишняя кавычка ' в скрипте"
+
+#. mglWarnSpc
+#: src/base.cpp:232
+msgid "There is wrong argument(s) in script"
+msgstr "Неправильные аргументы команды в скрипте"
+
+#. mglScrArg
+#: src/base.cpp:233
+msgid "There is wrong command(s) in script"
+msgstr "В скрипте неправильная команд(ы)"
+
+#: widgets/fltk.cpp:862
+msgid "Theta angle (tilt z-axis)"
+msgstr "Угол Theta (наклон оси z)"
+
+#: mgllab/table.cpp:494
+msgid "This operation is not supported for this kind of data."
+msgstr "Операция не поддерживается для этого типа данных."
+
+#: udav/setup_dlg.cpp:76 mgllab/dialogs.cpp:955
+msgid "Ticks"
+msgstr "Метки"
+
+#: mgllab/dialogs.cpp:960
+msgid "Ticks start"
+msgstr "Начать с"
+
+#: mgllab/dialogs.cpp:1031
+msgid "Time ticks"
+msgstr "Метки времени"
+
+#: udav/subplot_dlg.cpp:204 mgllab/dialogs.cpp:1313
+msgid "Title"
+msgstr "Заголовок"
+
+#: udav/subplot_dlg.cpp:206
+msgid "Title for plot. Can be used in SubPlot or MultiPlot only."
+msgstr "Заголовок для графика. Следует использовать в SubPlot или MultiPlot"
+
+#: udav/dat_pnl.cpp:351 udav/dat_pnl.cpp:366 udav/dat_pnl.cpp:377
+#: udav/dat_pnl.cpp:424 udav/dat_pnl.cpp:453 mgllab/table.cpp:609
+msgid "To"
+msgstr "до"
+
+#: udav/calc_dlg.cpp:66 udav/setup_dlg.cpp:147
+msgid "To script"
+msgstr "В скрипт"
+
+#: udav/dat_pnl.cpp:790
+msgid "Transform"
+msgstr "Трансформация"
+
+#: udav/dat_pnl.cpp:792
+msgid "Transform data along dimension(s) (Ctrl+Shift+T)."
+msgstr "Трансформация данных по направлению (Ctrl+Shift+T)."
+
+#: mgllab/dialogs.cpp:346
+msgid "Transparency"
+msgstr "Прозрачность"
+
+#: mgllab/dialogs.cpp:1043
+msgid "Transparency type"
+msgstr "Тип прозрачности"
+
+#: mgllab/table.cpp:762
+msgid "Transpose"
+msgstr "Транспонировать"
+
+#: mgllab/table.cpp:670
+msgid "Transpose data"
+msgstr "Транспонировать данные"
+
+#: src/exec_dat.cpp:1611
+msgid "Transpose data array"
+msgstr "Транспонировать данные"
+
+#: mgllab/table.cpp:860
+msgid "Transpose data dimensions"
+msgstr "Транспонировать данные"
+
+#: udav/dat_pnl.cpp:612
+msgid "Transpose data with new dimensions"
+msgstr "Транспонировать данные"
+
+#: udav/calc_dlg.cpp:192
+msgid "Trigonometric"
+msgstr "Тригонометрия"
+
+#: mgllab/dialogs.cpp:1034
+msgid "Tune ticks"
+msgstr "Настроить метки"
+
+#: mgllab/table.cpp:169 mgllab/table.cpp:344
+msgid "Type of operation"
+msgstr "Тип операции"
+
+#: mgllab/table.cpp:174
+msgid "Type of smoothing"
+msgstr "Тип сглаживания"
+
+#. N
+#: udav/style_dlg.cpp:246 mgllab/dialogs.cpp:54
+msgid "U - indigo"
+msgstr "U - темно-фиолетовый"
+
+#: udav/text_pnl.cpp:109 udav/text_pnl.cpp:124 udav/text_pnl.cpp:137
+#: udav/udav_wnd.cpp:340
+msgid "UDAV"
+msgstr ""
+
+#: udav/opt_dlg.cpp:31
+msgid "UDAV - Add options"
+msgstr "UDAV - добавить опции"
+
+#: udav/anim_dlg.cpp:35
+msgid "UDAV - Animation setup"
+msgstr "UDAV - настройка анимации"
+
+#: udav/dat_pnl.cpp:388
+msgid "UDAV - Clear data"
+msgstr "UDAV - очистить данные"
+
+#: udav/dat_pnl.cpp:424
+msgid "UDAV - Crop data"
+msgstr "UDAV - обрезать данные"
+
+#: udav/dat_pnl.cpp:255
+msgid "UDAV - Export to PNG"
+msgstr "UDAV - экспорт в PNG"
+
+#: udav/dat_pnl.cpp:351
+msgid "UDAV - Fill data"
+msgstr "UDAV - заполнить данные"
+
+#: udav/find_dlg.cpp:33
+msgid "UDAV - Find"
+msgstr "UDAV - найти"
+
+#: udav/dat_pnl.cpp:485
+msgid "UDAV - Go to slice"
+msgstr "UDAV - перейти к срезу"
+
+#: udav/hint_dlg.cpp:55
+msgid "UDAV - Hint"
+msgstr "UDAV - подсказки"
+
+#: udav/dat_pnl.cpp:277
+msgid "UDAV - Import PNG"
+msgstr "UDAV - импорт PNG"
+
+#: udav/prop_dlg.cpp:192 udav/prop_dlg.cpp:198 udav/newcmd_dlg.cpp:324
+#: udav/text_pnl.cpp:145 udav/open_dlg.cpp:101
+msgid "UDAV - Insert filename"
+msgstr "UDAV - вставить имя файла"
+
+#: udav/newcmd_dlg.cpp:329 udav/text_pnl.cpp:152
+msgid "UDAV - Insert path"
+msgstr "UDAV - вставить путь"
+
+#: udav/style_dlg.cpp:48 udav/data_dlg.cpp:33
+msgid "UDAV - Insert style/scheme"
+msgstr "UDAV - вставить стиль"
+
+#: udav/dat_pnl.cpp:270
+msgid "UDAV - Load data"
+msgstr "UDAV - загрузить данные"
+
+#: udav/dat_pnl.cpp:450
+msgid "UDAV - Make histogram"
+msgstr "UDAV - создать гистограмму"
+
+#: udav/mem_pnl.cpp:84
+msgid "UDAV - New variable"
+msgstr "UDAV - новая переменная"
+
+#: udav/dat_pnl.cpp:377
+msgid "UDAV - Normalize by slice"
+msgstr "UDAV - нормировать по срезам"
+
+#: udav/dat_pnl.cpp:366
+msgid "UDAV - Normalize data"
+msgstr "UDAV - нормировать данные"
+
+#: udav/open_dlg.cpp:49
+msgid "UDAV - Open data file"
+msgstr "UDAV - открыть файл данных"
+
+#: udav/udav_wnd.cpp:633
+msgid "UDAV - Open file"
+msgstr "UDAV - открыть файл"
+
+#: udav/prop_dlg.cpp:60 udav/prop_dlg.cpp:285
+msgid "UDAV - Properties"
+msgstr "UDAV - свойства"
+
+#: udav/dat_pnl.cpp:283
+msgid "UDAV - Read from HDF"
+msgstr "UDAV - загрузить из HDF"
+
+#: udav/dat_pnl.cpp:436
+msgid "UDAV - Rearrange data"
+msgstr "UDAV - упорядочить размеры данных"
+
+#: udav/dat_pnl.cpp:402
+msgid "UDAV - Resize data"
+msgstr "UDAV - изменить размер данных"
+
+#: udav/setup_dlg.cpp:159 udav/setup_dlg.cpp:163
+msgid "UDAV - Save template"
+msgstr "UDAV - сохранить шаблон"
+
+#: udav/dat_pnl.cpp:261
+msgid "UDAV - Save to HDF"
+msgstr "UDAV - сохранить в HDF"
+
+#: udav/dat_pnl.cpp:248
+msgid "UDAV - Save/export data"
+msgstr "UDAV - сохранить/экспортировать данные"
+
+#: udav/args_dlg.cpp:32
+msgid "UDAV - Set script arguments"
+msgstr "UDAV - задать аргументы"
+
+#: udav/files_dlg.cpp:29
+msgid "UDAV - Set template parameters"
+msgstr "UDAV - задать шаблон параметров"
+
+#: udav/subplot_dlg.cpp:37
+msgid "UDAV - Setup inplot"
+msgstr "UDAV - настройки под-графика"
+
+#: udav/setup_dlg.cpp:39 udav/setup_dlg.cpp:190
+msgid "UDAV - Setup plot"
+msgstr "UDAV - настройки графика"
+
+#: udav/dat_pnl.cpp:413
+msgid "UDAV - Squeeze data"
+msgstr "UDAV - сжать данные"
+
+#: udav/udav_wnd.cpp:456
+msgid "UDAV - about"
+msgstr "UDAV - о программе"
+
+#: udav/anim_dlg.cpp:104
+msgid "UDAV - animation"
+msgstr "UDAV - анимация"
+
+#: udav/dat_pnl.cpp:608
+msgid "UDAV - change data"
+msgstr "UDAV - изменить данные"
+
+#: udav/opt_dlg.cpp:94 udav/opt_dlg.cpp:101 udav/opt_dlg.cpp:108
+#: udav/opt_dlg.cpp:115
+msgid "UDAV - command options"
+msgstr "UDAV - опции команды"
+
+#: udav/mem_pnl.cpp:121
+msgid "UDAV - delete all data"
+msgstr "UDAV - удалить все данные"
+
+#: udav/text_pnl.cpp:202
+msgid "UDAV - find text"
+msgstr "UDAV - найти текст"
+
+#: udav/dat_pnl.cpp:536 udav/dat_pnl.cpp:566 udav/dat_pnl.cpp:572
+#: udav/dat_pnl.cpp:643
+msgid "UDAV - make new data"
+msgstr "UDAV - создать новый массив данных"
+
+#: udav/text_pnl.cpp:431
+msgid "UDAV - open file"
+msgstr "UDAV - открыть файл"
+
+#: udav/udav_wnd.cpp:569 udav/udav_wnd.cpp:579 udav/udav_wnd.cpp:621
+msgid "UDAV - save current"
+msgstr "UDAV - сохранить текущий"
+
+#: udav/udav_wnd.cpp:669
+msgid "UDAV - save file"
+msgstr "UDAV - сохранить файл"
+
+#: udav/style_dlg.cpp:160 mgllab/dialogs.cpp:371
+msgid "Underline"
+msgstr "Подчеркивание"
+
+#. edit menu
+#: udav/text_pnl.cpp:516 mgllab/mgllab.cpp:293
+msgid "Undo"
+msgstr "Отмена"
+
+#: udav/text_pnl.cpp:518
+msgid "Undo editor change (Ctrl+Z)."
+msgstr "Отменить изменения в редакторе (Ctrl+Z)."
+
+#: mgllab/mgllab.cpp:127
+msgid "Untitled"
+msgstr "без имени"
+
+#: mgllab/mgllab.cpp:345 mgllab/mgllab.cpp:349
+msgid "Untitled - mgllab"
+msgstr "без имени - mgllab"
+
+#: udav/mem_pnl.cpp:62
+msgid "Update list of data arrays"
+msgstr "Обновить список массивов данных"
+
+#: mgllab/dialogs.cpp:100
+msgid "Upper border for determining color or alpha"
+msgstr "Верхняя граница для цвета или прозрачности"
+
+#: utils/mglconv.cpp:85
+#, c-format
+msgid "Usage:\tmglconv [parameter(s)] scriptfile\n"
+msgstr "Использование:\tmglconv [параметр(ы)] имя_скрипта\n"
+
+#: mgllab/mgllab.cpp:416
+#, c-format
+msgid "Usage:\tmgllab [parameter(s)] scriptfile\n"
+msgstr "Использование:\tmgllab [параметр(ы)] имя_скрипта\n"
+
+#: utils/mglview.cpp:69
+#, c-format
+msgid "Usage:\tmglview [parameter(s)] scriptfile\n"
+msgstr "Использование:\tmglview [параметр(ы)] имя_скрипта\n"
+
+#: widgets/glut.cpp:103
+#, c-format
+msgid ""
+"Use 'a', 'd', 'w', 's', 'q', 'e' for changing view angles\n"
+"Use 'j', 'l', 'i', 'k' for changing light angles\n"
+"Use 'u', 'o' for changing distance to light\n"
+"Use 'r' for switching transparency\n"
+"Use 'f' for switching lightning\n"
+"Use 'E' for exporting to EPS file\n"
+"Use 'S' for exporting to SVG file\n"
+"Use 'J' for exporting to JPEG file\n"
+"Use 'P' for exporting to PNG file\n"
+"Use ',', '.' for show other frames\n"
+"Use 'm' for view movie\n"
+"Use 'h' for view this text\n"
+"Use 'x' for exit\n"
+msgstr ""
+"* 'a', 'd', 'w', 's', 'q', 'e' для изменения углов просмотра\n"
+"* 'j', 'l', 'i', 'k' для изменения углов освещения\n"
+"* 'u', 'o' для изменения расстояния до источника света\n"
+"* 'r' для переключения прозрачности\n"
+"* 'f' для переключения освещения\n"
+"* 'E' для экспорта в EPS\n"
+"* 'S' для экспорта в SVG\n"
+"* 'J' для экспорта в JPEG\n"
+"* 'P' для экспорта в PNG\n"
+"* ',', '.' для показа других кадров\n"
+"* 'm' для запуска анимации\n"
+"* 'h' для этого Сообщения\n"
+"* 'x' для выхода\n"
+
+#: udav/style_dlg.cpp:162
+msgid "Use color scheme"
+msgstr "Использовать цветовую схему"
+
+#: udav/prop_dlg.cpp:175
+msgid "Use dots plot for preview"
+msgstr "Использовать точки для просмотра"
+
+#: mgllab/mgllab.cpp:477
+msgid "Use multi-threading for drawing"
+msgstr "Рисование в отдельном потоке"
+
+#: udav/newcmd_dlg.cpp:67 udav/opt_dlg.cpp:68 mgllab/dialogs.cpp:101
+msgid "Value"
+msgstr "Значение"
+
+#: mgllab/dialogs.cpp:398
+msgid "Value for i-th color"
+msgstr "Значение для i-го цвета"
+
+#: mgllab/dialogs.cpp:727 mgllab/dialogs.cpp:1047
+msgid "Variant"
+msgstr "Вариант"
+
+#: mgllab/dialogs.cpp:728
+msgid ""
+"Variant of command argument order. The notation is:\n"
+" * Capital arguments are data (like, Ydat);\n"
+" * Argument in '' are strings (like, 'fmt');\n"
+" * Other arguments are numbers (like, zval);\n"
+" * Arguments in [] are optional arguments."
+msgstr ""
+"Вариант порядка аргументов команды. Обозначения:\n"
+" * Заглавные -- данные (например, Ydat);\n"
+" * В кавычках '' -- строки (например, 'fmt');\n"
+" * Прочие -- числа (например, zval);\n"
+" * Аргументы в скобках [] -- не обязательные."
+
+#: udav/newcmd_dlg.cpp:170 mgllab/dialogs.cpp:711
+msgid "Vector plots"
+msgstr "Векторные графики"
+
+#: mgllab/dialogs.cpp:379
+msgid "Vertical align"
+msgstr "По вертикали"
+
+#: udav/subplot_dlg.cpp:55 udav/subplot_dlg.cpp:72 udav/subplot_dlg.cpp:97
+msgid "Vertical size"
+msgstr "Вертикальный размер"
+
+#. k
+#: udav/style_dlg.cpp:236 mgllab/dialogs.cpp:44
+msgid "W - lightgray"
+msgstr "W - светло-серый"
+
+#: src/exec_dat.cpp:1615
+msgid "Wavelet transform at some direction"
+msgstr "Wavelet преобразование вдоль направления"
+
+#: udav/subplot_dlg.cpp:195
+msgid "Whole area"
+msgstr "Вся область"
+
+#: mgllab/mgllab.cpp:480
+msgid "Widget scheme"
+msgstr ""
+
+#: mgllab/dialogs.cpp:329
+msgid "Width"
+msgstr "Ширина"
+
+#: udav/subplot_dlg.cpp:80
+msgid "Width of selected cells"
+msgstr "Ширины выбранных ячеек"
+
+#: src/data.cpp:1427
+#, c-format
+msgid ""
+"Widths are:\n"
+"Wa = %g\tWx = %g\tWy = %g\tWz = %g\n"
+msgstr "Ширины: Wa = %g\tWx = %g\tWy = %g\tWz = %g\n"
+
+#: mgllab/dialogs.cpp:348
+msgid "Wire or mesh"
+msgstr "Сетчатый"
+
+#: udav/style_dlg.cpp:120
+msgid "Wire or mesh plot"
+msgstr "Сетчатый график"
+
+#: udav/style_dlg.cpp:159 mgllab/dialogs.cpp:370
+msgid "Wire style"
+msgstr "Контур"
+
+#: src/exec_set.cpp:752
+msgid "Write current image to graphical file"
+msgstr "Сохранить текущий рисунок в файл"
+
+#: udav/setup_dlg.cpp:48 mgllab/dialogs.cpp:950
+msgid "X axis"
+msgstr "Ось X"
+
+#: udav/setup_dlg.cpp:118
+msgid "X pos"
+msgstr "X коор."
+
+#: mgllab/dialogs.cpp:1065
+msgid "X position"
+msgstr "X коор."
+
+#: udav/dat_pnl.cpp:413
+msgid "X-direction"
+msgstr "X-направление"
+
+#: udav/opt_dlg.cpp:38 mgllab/dialogs.cpp:85
+msgid "X-range"
+msgstr "X-диапазон"
+
+#: udav/dat_pnl.cpp:388 udav/dat_pnl.cpp:402 udav/dat_pnl.cpp:436
+msgid "X-size"
+msgstr "Размер по X"
+
+#: mgllab/dialogs.cpp:568
+msgid "X-slice from"
+msgstr "Х срез от"
+
+#: udav/subplot_dlg.cpp:176
+msgid "X/Z"
+msgstr ""
+
+#: widgets/qt.cpp:1081 udav/plot_pnl.cpp:489
+msgid "XYZ"
+msgstr ""
+
+#. M
+#: udav/style_dlg.cpp:242 mgllab/dialogs.cpp:50
+msgid "Y - olive"
+msgstr "Y - оливковый"
+
+#: udav/setup_dlg.cpp:49 mgllab/dialogs.cpp:963
+msgid "Y axis"
+msgstr "Ось Y"
+
+#: udav/setup_dlg.cpp:119
+msgid "Y pos"
+msgstr "Y коор."
+
+#: mgllab/dialogs.cpp:1066
+msgid "Y position"
+msgstr "Y коор."
+
+#: udav/dat_pnl.cpp:413
+msgid "Y-direction"
+msgstr "Y-направление"
+
+#: udav/opt_dlg.cpp:41 mgllab/dialogs.cpp:89
+msgid "Y-range"
+msgstr "Y-диапазон"
+
+#: udav/dat_pnl.cpp:388 udav/dat_pnl.cpp:402 udav/dat_pnl.cpp:436
+msgid "Y-size"
+msgstr "Размер по Y"
+
+#: mgllab/dialogs.cpp:571
+msgid "Y-slice from"
+msgstr "Y срез от"
+
+#: udav/subplot_dlg.cpp:180
+msgid "Y/Z"
+msgstr ""
+
+#: mgllab/help.cpp:135
+msgid "Yes"
+msgstr "Да"
+
+#: udav/hint_dlg.cpp:36 mgllab/help.cpp:270
+msgid ""
+"You can copy the current image to clipboard by pressing Ctrl-Shift-C. Later "
+"you can paste it directly into yours document or presentation."
+msgstr ""
+"Текущий рисунок можно скопировать нажав Ctrl-Shift-C. Позже его можно "
+"вставить в документ или презентацию."
+
+#: udav/hint_dlg.cpp:49 mgllab/help.cpp:283
+msgid ""
+"You can easily insert file or folder names, last fitted formula or numerical "
+"value of selection by using menu Edit|Insert."
+msgstr ""
+"Можно легко вставить имя файла, путь к папке, последнюю подобранную формулу "
+"и т.л., используя меню Правка|Вставить"
+
+#: udav/hint_dlg.cpp:43 mgllab/help.cpp:277
+msgid ""
+"You can edit MGL file in any text editor. Also you can run it in console by "
+"help of commands: mglconv, mglview."
+msgstr ""
+"Скрипт MGL можно редактировать в любом текстовом редакторе. Также его можно "
+"запустить (и просмотреть) прямо из консоли с помошью программ mglconv, "
+"mglview."
+
+#: udav/hint_dlg.cpp:37 mgllab/help.cpp:271
+msgid ""
+"You can export image into a set of format (EPS, SVG, PNG, JPEG) by pressing "
+"right mouse button inside image and selecting 'Export as ...'."
+msgstr ""
+"Текущий рисунок можно экспортировать во множество форматов (EPS, SVG, PNG, "
+"JPEG и др.), просто нажав правой кнопкой на рисунке и выбрать 'Экспорт'"
+
+#: udav/hint_dlg.cpp:41 mgllab/help.cpp:275
+msgid ""
+"You can put several plots in the same image by help of commands 'subplot' or "
+"'inplot'."
+msgstr ""
+"Рисунок может содержать несколько вставок (под-графиков) при использовании "
+"команд 'subplot', 'inplot' и пр."
+
+#: udav/hint_dlg.cpp:51 mgllab/help.cpp:285
+msgid ""
+"You can put several plotting commands in the same line or in separate "
+"function, for highlighting all of them simultaneously."
+msgstr ""
+"Можно сгруппировать несколько графиков поместив их в одну строку с "
+"разделителем ':' или в функцию. Группа графиков будет подсвечиваться и "
+"перемещаться как целое."
+
+#: udav/hint_dlg.cpp:34 mgllab/help.cpp:268
+msgid ""
+"You can rotate/shift/zoom whole plot by mouse. Just press 'Rotate' "
+"toolbutton, click image and hold a mouse button: left button for rotation, "
+"right button for zoom/perspective, middle button for shift."
+msgstr ""
+"График можно вращать/сдвигать/приближать с помощью мыши. Просто нажмите "
+"кнопку 'Вращать' и удерживайте кнопку мыши: левую для вращения, правую для "
+"приближения/перспективы, среднюю для сдвига."
+
+#: udav/hint_dlg.cpp:39 mgllab/help.cpp:273
+msgid ""
+"You can save the parameter of animation inside MGL script by using comment "
+"started from '##a ' or '##c ' for loops."
+msgstr ""
+"Параметры анимации можно сохранить внутри скрипта с помощью комментариев "
+"'##a' или '##c'."
+
+#: udav/hint_dlg.cpp:38 mgllab/help.cpp:272
+msgid ""
+"You can setup colors for script highlighting in Property dialog. Just select "
+"menu item 'Settings/Properties'."
+msgstr "Расцветку скрипта можно настроить в диалоге 'Свойства'."
+
+#: udav/hint_dlg.cpp:33 mgllab/help.cpp:267
+msgid ""
+"You can shift axis range by pressing middle button and moving mouse. Also, "
+"you can zoom in/out axis range by using mouse wheel."
+msgstr ""
+"Диапазон осей координат можно сместить нажав среднюю кнопку мыши, при этом "
+"колесо мыши приближает/отдаляет график."
+
+#: udav/hint_dlg.cpp:46 mgllab/help.cpp:280
+msgid ""
+"You can type arbitrary expression as input argument for data or number. In "
+"last case (for numbers), the first value of data array is used."
+msgstr ""
+"Аргументом может быть любое выражение. Если требуется число, то будет "
+"использован первый элемент массива."
+
+#: udav/hint_dlg.cpp:44 mgllab/help.cpp:278
+msgid ""
+"You can use command 'once on|off' for marking the block which should be "
+"executed only once. For example, this can be the block of large data reading/"
+"creating/handling. Press F9 (or menu item 'Graphics/Reload') to re-execute "
+"this block."
+msgstr ""
+"Команда 'once on|off' позволяет выделить блок, который будет исполняться "
+"только один раз. Например, это могут быть команды чтения больших файлов, "
+"длительные вычисления и т.д. Нажмите F9 (меню 'Графика|Перезагрузить') для "
+"повторного выполнения этого блока команд."
+
+#: udav/hint_dlg.cpp:45 mgllab/help.cpp:279
+msgid ""
+"You can use command 'stop' for terminating script parsing. It is useful if "
+"you don't want to execute a part of script."
+msgstr ""
+"Команда 'stop' останавливает выполение скрипта. Она полезна если Вы не "
+"хотите выполнять часть скрипта."
+
+#: udav/hint_dlg.cpp:35 mgllab/help.cpp:269
+msgid ""
+"You may quickly draw the data from file. Just use: udav 'filename.dat' in "
+"command line."
+msgstr ""
+
+#: mgllab/dialogs.cpp:1529
+msgid "You need to enter text!"
+msgstr "Необходимо ввести текст!"
+
+#: mgllab/table.cpp:367
+msgid "You need to provide output name"
+msgstr "Необходимо ввести имя"
+
+#: udav/prop_dlg.cpp:285
+msgid "You need to restart UDAV for applying the changes."
+msgstr "Необходимо перезапустить UDAV для применения изменений."
+
+#: mgllab/dialogs.cpp:592
+msgid "You need to select data array"
+msgstr "Необходимо выбрать массив данных"
+
+#: mgllab/dialogs.cpp:1489
+msgid "You need to select marker!"
+msgstr "Необходимо выбрать маркер!"
+
+#: mgllab/table.cpp:190 mgllab/table.cpp:364
+msgid "You need to specify direction(s)"
+msgstr "Необходимо указать направление"
+
+#: udav/newcmd_dlg.cpp:378 udav/newcmd_dlg.cpp:382
+msgid "You should put text inside ' ' for argument "
+msgstr "Необходимо ввести текст в ' ' для аргумента"
+
+#: udav/anim_dlg.cpp:105
+msgid "You should select one of case"
+msgstr "Необходимо выбрать один из вариантов"
+
+#: udav/newcmd_dlg.cpp:386
+msgid "You should specify all optional arguments before "
+msgstr "Необходимо ввести все аргументы перед "
+
+#: udav/newcmd_dlg.cpp:370
+msgid "You should specify required argument "
+msgstr "Необходимо ввести обязательный аргумент "
+
+#: udav/setup_dlg.cpp:50 mgllab/dialogs.cpp:976
+msgid "Z axis"
+msgstr "Ось Z"
+
+#: udav/setup_dlg.cpp:120
+msgid "Z pos"
+msgstr "Z коор."
+
+#: mgllab/dialogs.cpp:1067
+msgid "Z position"
+msgstr "Z коор."
+
+#: udav/dat_pnl.cpp:413
+msgid "Z-direction"
+msgstr "Z-направление"
+
+#: udav/opt_dlg.cpp:44 mgllab/dialogs.cpp:93
+msgid "Z-range"
+msgstr "Z-диапазон"
+
+#: udav/dat_pnl.cpp:388 udav/dat_pnl.cpp:402 udav/dat_pnl.cpp:436
+msgid "Z-size"
+msgstr "Размер по Z"
+
+#: mgllab/dialogs.cpp:574
+msgid "Z-slice from"
+msgstr "Z срез от"
+
+#: src/exec_set.cpp:758
+msgid "Zoom axis range"
+msgstr "Увеличить диапазон осей координат"
+
+#: widgets/qt.cpp:1116
+msgid "Zoom by mouse"
+msgstr "Приблизить мышкой"
+
+#: widgets/qt.cpp:1215
+msgid "Zoom graphics"
+msgstr "Приблизить рисунок"
+
+#: widgets/qt.cpp:1225 udav/plot_pnl.cpp:515
+msgid "Zoom in"
+msgstr "Приблизить"
+
+#: widgets/qt.cpp:1227 udav/plot_pnl.cpp:518
+msgid "Zoom in graphics."
+msgstr "Приблизить рисунок"
+
+#: widgets/fltk.cpp:843
+msgid "Zoom in selected region of the picture"
+msgstr "Приблизить выбранную область рисунка"
+
+#. t->addAction(QPixmap(":/png/help-faq.png"), _("Examples"), this, SLOT(showExamples()));
+#: udav/help_pnl.cpp:55
+msgid "Zoom in text"
+msgstr "Увеличить текст"
+
+#: widgets/fltk.cpp:872
+msgid "Zoom in the picture"
+msgstr "Приблизить рисунок"
+
+#: widgets/qt.cpp:1229 udav/plot_pnl.cpp:521
+msgid "Zoom out"
+msgstr "Отдалить"
+
+#: widgets/qt.cpp:1231 udav/plot_pnl.cpp:524
+msgid "Zoom out graphics."
+msgstr "Отдалить рисунок"
+
+#: udav/help_pnl.cpp:56
+msgid "Zoom out text"
+msgstr "Уменьшить текст"
+
+#: widgets/fltk.cpp:874
+msgid "Zoom out the picture"
+msgstr "Отдалить рисунок"
+
+#: src/exec_set.cpp:757
+msgid "Zoom plot region"
+msgstr "Приблизить область рисунка"
+
+#. zooming menu
+#: widgets/qt.cpp:1214 udav/plot_pnl.cpp:502
+msgid "Zoom/move"
+msgstr "Приближение/сдвиг"
+
+#: udav/style_dlg.cpp:131
+msgid "above"
+msgstr "выше"
+
+#: mgllab/dialogs.cpp:570 mgllab/dialogs.cpp:573 mgllab/dialogs.cpp:576
+msgid "all"
+msgstr "все"
+
+#: mgllab/dialogs.cpp:581
+msgid "along"
+msgstr "вдоль"
+
+#: mgllab/table.cpp:171 mgllab/table.cpp:346
+msgid "along x"
+msgstr "вдоль x"
+
+#: mgllab/table.cpp:172 mgllab/table.cpp:347
+msgid "along y"
+msgstr "вдоль y"
+
+#: mgllab/table.cpp:173 mgllab/table.cpp:348
+msgid "along z"
+msgstr "вдоль z"
+
+#: mgllab/dialogs.cpp:1012
+msgid "alpha"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1296
+msgid "and"
+msgstr "и"
+
+#: mgllab/dialogs.cpp:1456
+msgid "arc"
+msgstr "дуга"
+
+#: mgllab/dialogs.cpp:1018
+msgid "arrows"
+msgstr "стрелки"
+
+#: udav/setup_dlg.cpp:72 udav/style_dlg.cpp:170
+msgid "at center"
+msgstr "по центру"
+
+#: udav/setup_dlg.cpp:72
+msgid "at maximum"
+msgstr "в максимуме"
+
+#: udav/setup_dlg.cpp:72
+msgid "at minimum"
+msgstr "в минимуме"
+
+#: udav/setup_dlg.cpp:70 mgllab/dialogs.cpp:956
+msgid "at position"
+msgstr "позиция"
+
+#: mgllab/dialogs.cpp:1027
+msgid "attach light"
+msgstr "прикрепить свет"
+
+#. mglWarnFmt
+#: src/base.cpp:229
+msgid "axis ranges are incompatible"
+msgstr "размеры осей неправильные"
+
+#. w
+#: udav/style_dlg.cpp:222 mgllab/dialogs.cpp:29
+msgid "b - blue"
+msgstr "b - синий"
+
+#: mgllab/dialogs.cpp:1019
+msgid "bars"
+msgstr ""
+
+#: widgets/qt.cpp:1071 udav/plot_pnl.cpp:478
+msgid "bitmap EPS"
+msgstr "растровый EPS"
+
+#: mgllab/dialogs.cpp:1036
+msgid "both"
+msgstr "оба"
+
+#: udav/subplot_dlg.cpp:189 mgllab/dialogs.cpp:1306
+msgid "bottom"
+msgstr "снизу"
+
+#. r
+#: udav/style_dlg.cpp:225 mgllab/dialogs.cpp:32
+msgid "c - cyan"
+msgstr "c - голубой"
+
+#: mgllab/dialogs.cpp:957 mgllab/dialogs.cpp:970 mgllab/dialogs.cpp:983
+#: mgllab/dialogs.cpp:996
+msgid "center"
+msgstr "центр"
+
+#: widgets/fltk.cpp:768
+#, c-format
+msgid "click at %g, %g, %g"
+msgstr "клик в %g, %g, %g"
+
+#. mglWarnCnt
+#: src/base.cpp:225
+msgid "couldn't open file"
+msgstr "не могу открыть файл"
+
+#: mgllab/dialogs.cpp:1455
+msgid "curve"
+msgstr "кривая"
+
+#: mgllab/dialogs.cpp:1026
+msgid "cutting"
+msgstr "обрезание"
+
+#. -----------------------------------------------------------------------------
+#: src/base.cpp:216
+msgid "data dimension(s) is incompatible"
+msgstr "размеры данных несовместимы"
+
+#. mglWarnDim
+#: src/base.cpp:217
+msgid "data dimension(s) is too small"
+msgstr "размеры данных слишком малы"
+
+#. mglWarnMem
+#: src/base.cpp:221
+msgid "data values are zero"
+msgstr "значение данных равно нулю"
+
+#: udav/open_dlg.cpp:85 udav/open_dlg.cpp:144 udav/opt_dlg.cpp:63
+#: udav/opt_dlg.cpp:66 mgllab/dialogs.cpp:107 mgllab/dialogs.cpp:116
+#: mgllab/dialogs.cpp:1044
+msgid "default"
+msgstr "по умолчанию"
+
+#: mgllab/help.cpp:149
+msgid "dimensions"
+msgstr "размерности"
+
+#. l
+#: udav/style_dlg.cpp:229 mgllab/dialogs.cpp:36
+msgid "e - lawngreen"
+msgstr "e - салатовый"
+
+#: mgllab/dialogs.cpp:1455
+msgid "ellipse"
+msgstr "эллипс"
+
+#: mgllab/dialogs.cpp:1017
+msgid "facenum"
+msgstr ""
+
+#: mgllab/dialogs.cpp:1035
+msgid "factor"
+msgstr "множитель"
+
+#. mglWarnSize
+#: src/base.cpp:228
+msgid "format is not supported for that build"
+msgstr "формат не поддерживается для этой сборки"
+
+#: src/canvas.cpp:33
+msgid "frame"
+msgstr "кадр"
+
+#: udav/anim_dlg.cpp:55 mgllab/mathgl.cpp:190
+msgid "from"
+msgstr "от"
+
+#. b
+#: udav/style_dlg.cpp:223 mgllab/dialogs.cpp:30
+msgid "g - lime"
+msgstr "g - липовый"
+
+#: mgllab/dialogs.cpp:1044
+msgid "glass-like"
+msgstr "стеклянная"
+
+#: mgllab/dialogs.cpp:1011
+msgid "grayscale"
+msgstr "черно-белый"
+
+#. p
+#: udav/style_dlg.cpp:234 mgllab/dialogs.cpp:41
+msgid "h - gray"
+msgstr "h - серый"
+
+#: src/parser.cpp:1011
+#, c-format
+msgid "in line %ld"
+msgstr "в строке %ld"
+
+#: mgllab/dialogs.cpp:1036
+msgid "increment"
+msgstr "шаг"
+
+#: mgllab/dialogs.cpp:1236 mgllab/dialogs.cpp:1249 mgllab/dialogs.cpp:1262
+#: mgllab/dialogs.cpp:1271 mgllab/dialogs.cpp:1280
+msgid "ind"
+msgstr "№"
+
+#. h
+#: udav/style_dlg.cpp:235 mgllab/dialogs.cpp:43
+msgid "k - black"
+msgstr "k - черный"
+
+#. y
+#: udav/style_dlg.cpp:228 mgllab/dialogs.cpp:35
+msgid "l - springgreen"
+msgstr "l - весенне-зеленый"
+
+#: mgllab/dialogs.cpp:1045
+msgid "lamp-like"
+msgstr "ламповая"
+
+#. vv->addSpacing(11);
+#: udav/style_dlg.cpp:169 udav/subplot_dlg.cpp:187 mgllab/dialogs.cpp:957
+#: mgllab/dialogs.cpp:970 mgllab/dialogs.cpp:983 mgllab/dialogs.cpp:996
+#: mgllab/dialogs.cpp:1304
+msgid "left"
+msgstr "слева"
+
+#. mglWarnOpen
+#: src/base.cpp:226
+msgid "light: ID is out of range"
+msgstr "light: ID вне диапазона"
+
+#: mgllab/dialogs.cpp:1013
+msgid "lighting"
+msgstr "освещение"
+
+#: mgllab/dialogs.cpp:1454
+msgid "line"
+msgstr "линия"
+
+#. c
+#: udav/style_dlg.cpp:226 mgllab/dialogs.cpp:33
+msgid "m - magenta"
+msgstr "m - фуксия"
+
+#.
+#. ^
+#: udav/style_dlg.cpp:317 udav/style_dlg.cpp:356 mgllab/dialogs.cpp:209
+#: mgllab/dialogs.cpp:247
+msgid "manual"
+msgstr "вручную"
+
+#: mgllab/dialogs.cpp:1454
+msgid "marker"
+msgstr "маркер"
+
+#: mgllab/dialogs.cpp:1020
+msgid "markers"
+msgstr "маркеры"
+
+#: udav/data_dlg.cpp:68
+msgid "max"
+msgstr "max"
+
+#: mgllab/help.cpp:151
+msgid "mem. usage"
+msgstr "исп.памяти"
+
+#: mgllab/dialogs.cpp:1016
+msgid "meshnum"
+msgstr ""
+
+#: udav/newcmd_dlg.cpp:247
+msgid "mgl_en"
+msgstr "mgl_ru"
+
+#: utils/mglconv.cpp:84
+#, c-format
+msgid ""
+"mglconv convert mgl script to image file (default PNG).\n"
+"Current version is 2.%g\n"
+msgstr ""
+"mglconv конвертирует mgl скрипт в рисунок (по умолчанию PNG).\n"
+"Текущая версия 2.%g\n"
+
+#: mgllab/mgllab.cpp:415
+#, c-format
+msgid ""
+"mgllab draw mgl script interactively.\n"
+"Current version is 2.%g\n"
+msgstr ""
+"mgllab рисует mgl скрипт интерактивно.\n"
+"Текущая версия 2.%g\n"
+
+#: mgllab/help.cpp:78
+#, c-format
+msgid ""
+"mgllab v. 2.%g\n"
+"(c) Alexey Balakin, 2017\n"
+"http://mathgl.sf.net/"
+msgstr ""
+"mgllab v. 2.%g\n"
+"(c) Алексей Балакин, 2017\n"
+"http://mathgl.sf.net/"
+
+#: utils/mglview.cpp:68
+#, c-format
+msgid ""
+"mglview show plot from MGL script or MGLD file.\n"
+"Current version is 2.%g\n"
+msgstr ""
+"mglview показывает график MGL скрипта или MGLD файла.\n"
+"Текущая версия 2.%g\n"
+
+#: udav/data_dlg.cpp:68
+msgid "min"
+msgstr "min"
+
+#. mglWarnLow
+#: src/base.cpp:218
+msgid "minimal data value is negative"
+msgstr "минимальное значение отрицательно"
+
+#. e
+#: udav/style_dlg.cpp:230 mgllab/dialogs.cpp:37
+msgid "n - skyblue"
+msgstr "n - небесно-голубой"
+
+#: mgllab/help.cpp:147
+msgid "name"
+msgstr "имя"
+
+#. mglWarnNeg
+#: src/base.cpp:219
+msgid "no file or wrong data dimensions"
+msgstr "нет файла или неверные размеры"
+
+#. mglWarnZero
+#: src/base.cpp:222
+msgid "no legend entries"
+msgstr "нет записей легенды"
+
+#: mgllab/dialogs.cpp:1028
+msgid "no origin tick"
+msgstr ""
+
+#. "-+=;oOsS~<>jdD*^"
+#. ".+x*sdv^<>o.*+xsdv^<>o" : nf = 10
+#: udav/style_dlg.cpp:128 udav/style_dlg.cpp:131 udav/style_dlg.cpp:134
+#: udav/style_dlg.cpp:339 udav/style_dlg.cpp:383 udav/data_dlg.cpp:67
+#: mgllab/dialogs.cpp:214 mgllab/dialogs.cpp:230 mgllab/dialogs.cpp:1035
+#: mgllab/dialogs.cpp:1039
+msgid "none"
+msgstr "нет"
+
+#: udav/style_dlg.cpp:220
+msgid "none or default"
+msgstr "нет или по умолчанию"
+
+#. mglWarnFile
+#: src/base.cpp:220
+msgid "not enough memory"
+msgstr "не хватает памяти"
+
+#. mglWarnNull
+#: src/base.cpp:231
+msgid "not enough space for plot"
+msgstr "не достаточно места для графика"
+
+#: mgllab/table.cpp:85
+msgid "not used"
+msgstr "не используется"
+
+#. mglWarnSlc
+#: src/base.cpp:224
+msgid "number of contours is zero or negative"
+msgstr "число контуров меньше или равно нуля"
+
+#: udav/opt_dlg.cpp:63 udav/opt_dlg.cpp:66
+msgid "off"
+msgstr "выкл."
+
+#: udav/opt_dlg.cpp:63 udav/opt_dlg.cpp:66 udav/setup_dlg.cpp:128
+msgid "on"
+msgstr "вкл."
+
+#: udav/dat_pnl.cpp:549
+msgid "or enter name for new variable"
+msgstr "или введите имя новой переменной"
+
+#. q
+#: udav/style_dlg.cpp:233 mgllab/dialogs.cpp:40
+msgid "p - deeppink"
+msgstr "p - малиновый"
+
+#: mgllab/dialogs.cpp:1023
+msgid "pen blur"
+msgstr "размытие"
+
+#: mgllab/dialogs.cpp:392
+msgid "plain"
+msgstr "карта"
+
+#. mglWarnTern
+#: src/base.cpp:230
+msgid "pointer is NULL"
+msgstr "указатель равен NULL"
+
+#: mgllab/dialogs.cpp:1456
+msgid "polygon"
+msgstr "полигон"
+
+#: mgllab/dialogs.cpp:1040
+msgid "projection"
+msgstr "проекция"
+
+#. u
+#: udav/style_dlg.cpp:232 mgllab/dialogs.cpp:39
+msgid "q - orange"
+msgstr "q - оранжевый"
+
+#: mgllab/dialogs.cpp:1040
+msgid "quaternary"
+msgstr "quaternary"
+
+#: mgllab/dialogs.cpp:1041
+msgid "quaternary proj"
+msgstr "quaternary проекция"
+
+#. g
+#: udav/style_dlg.cpp:224 mgllab/dialogs.cpp:31
+msgid "r - red"
+msgstr "r - красный"
+
+#: mgllab/dialogs.cpp:1454
+msgid "rectangle"
+msgstr "прямоугольник"
+
+#: mgllab/dialogs.cpp:1455
+msgid "rhomb"
+msgstr "ромб"
+
+#: udav/style_dlg.cpp:172 udav/subplot_dlg.cpp:193 mgllab/dialogs.cpp:958
+#: mgllab/dialogs.cpp:971 mgllab/dialogs.cpp:984 mgllab/dialogs.cpp:997
+#: mgllab/dialogs.cpp:1310
+msgid "right"
+msgstr "справа"
+
+#: mgllab/dialogs.cpp:1029
+msgid "rotate text"
+msgstr "вращать текст"
+
+#: mgllab/mathgl.cpp:197
+msgid "save slides"
+msgstr "сохранить кадры"
+
+#. mglWarnLId
+#: src/base.cpp:227
+msgid "size(s) is zero or negative"
+msgstr "размер(ы) меньше или равны нулю"
+
+#. mglWarnLeg
+#: src/base.cpp:223
+msgid "slice value is out of range"
+msgstr "срез вне диапазона"
+
+#: mgllab/table.cpp:144
+msgid "smoothed"
+msgstr "сгладить"
+
+#: mgllab/dialogs.cpp:326
+msgid "solid"
+msgstr "сплош."
+
+#: widgets/qt.cpp:1069 udav/plot_pnl.cpp:476
+msgid "solid PNG"
+msgstr "PNG с заливкой"
+
+#: udav/anim_dlg.cpp:45 mgllab/mathgl.cpp:185
+msgid "strings"
+msgstr "строки"
+
+#: udav/data_dlg.cpp:67
+msgid "sum"
+msgstr "sum"
+
+#: mgllab/dialogs.cpp:1039
+msgid "ternary"
+msgstr "ternary"
+
+#: mgllab/dialogs.cpp:1041
+msgid "ternary proj"
+msgstr "ternary проекция"
+
+#: mgllab/dialogs.cpp:1021 mgllab/dialogs.cpp:1456
+msgid "text"
+msgstr "текст"
+
+#: mgllab/dialogs.cpp:1022
+msgid "ticks"
+msgstr "метки"
+
+#: udav/anim_dlg.cpp:59 mgllab/mathgl.cpp:191 mgllab/dialogs.cpp:569
+#: mgllab/dialogs.cpp:572 mgllab/dialogs.cpp:575
+msgid "to"
+msgstr "до"
+
+#: mgllab/mgllab.cpp:564
+msgid "to script"
+msgstr "в скрипт"
+
+#: udav/subplot_dlg.cpp:191 mgllab/dialogs.cpp:1308
+msgid "top"
+msgstr "сверху"
+
+#. n
+#: udav/style_dlg.cpp:231 mgllab/dialogs.cpp:38
+msgid "u - blueviolet"
+msgstr "u - фиолетовый"
+
+#: udav/style_dlg.cpp:131
+msgid "under"
+msgstr "снизу"
+
+#: udav/mem_pnl.cpp:168 mgllab/help.cpp:199
+msgid "unknown"
+msgstr "не знаю"
+
+#: udav/udav_wnd.cpp:168 udav/udav_wnd.cpp:560 udav/udav_wnd.cpp:693
+msgid "untitled - UDAV"
+msgstr "без имени - UDAV"
+
+#: udav/udav_wnd.cpp:686
+msgid "untitled* - UDAV"
+msgstr "без имени* - UDAV"
+
+#: mgllab/dialogs.cpp:327
+msgid "user"
+msgstr "символ"
+
+#: udav/anim_dlg.cpp:52 mgllab/mathgl.cpp:187
+msgid "values"
+msgstr "значения"
+
+#: widgets/qt.cpp:1072 udav/plot_pnl.cpp:479
+msgid "vector EPS"
+msgstr "векторный EPS"
+
+#.
+#: udav/style_dlg.cpp:221 mgllab/dialogs.cpp:28
+msgid "w - white"
+msgstr "w - белый"
+
+#: mgllab/dialogs.cpp:1312
+msgid "whole area"
+msgstr "без полей"
+
+#: mgllab/dialogs.cpp:1471
+msgid "wire"
+msgstr "сеткой"
+
+#: udav/anim_dlg.cpp:63 mgllab/mathgl.cpp:192
+msgid "with step"
+msgstr "с шагом"
+
+#. m
+#: udav/style_dlg.cpp:227 mgllab/dialogs.cpp:34
+msgid "y - yellow"
+msgstr "y - желтый"
+
+#~ msgid "Lower bound"
+#~ msgstr "Нижняя граница"
+
+#~ msgid "Upper bound"
+#~ msgstr "Верхняя граница"
+
+#~ msgid "Add"
+#~ msgstr "Добавить"
diff --git a/mgllab/CMakeLists.txt b/mgllab/CMakeLists.txt
new file mode 100644
index 0000000..1649104
--- /dev/null
+++ b/mgllab/CMakeLists.txt
@@ -0,0 +1,59 @@
+# cmake_minimum_required(VERSION 2.8.9)
+#
+# project( MGLLAB )
+#
+# include(FindFLTK)
+# if(NOT FLTK_FOUND)
+# 	message(SEND_ERROR "Couldn't find FLTK library.")
+# endif(NOT FLTK_FOUND)
+#
+# include_directories( ${MGLLAB_SOURCE_DIR} ${MGLLAB_BINARY_DIR})
+#
+# find_package(MathGL2 REQUIRED FLTK)
+# #find_package(MathGL REQUIRED FLTK PATHS /usr/local/lib/CMake/MathGL/)
+#
+# find_package(OpenMP)
+# if(OPENMP_FOUND)
+# 	set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
+# 	set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
+# else(OPENMP_FOUND)
+# 	message(SEND_ERROR "Couldn't find OpenMP.")
+# endif(OPENMP_FOUND)
+#
+# include_directories(${FLTK_INCLUDE_DIR})
+# set(mgl_lab_src editor.cpp help.cpp mathgl.cpp grid.cpp dialogs.cpp mgllab.cpp option.cpp table.cpp image.cpp)
+# set(mgl_lab_hdr mgllab.h image.h)
+# add_executable(mgllab ${mgl_lab_src} ${mgl_lab_hdr})
+# target_link_libraries(mgllab ${MATHGL2_FLTK_LIBRARY} ${MATHGL2_LIBRARY} ${FLTK_LIBRARIES})
+# install(
+# 	TARGETS mgllab
+# 	RUNTIME DESTINATION bin	)
+
+if(MGL_HAVE_FLTK)
+	configure_file(${MathGL2_SOURCE_DIR}/mgllab/mgl.xml.in ${MathGL2_BINARY_DIR}/mgllab/mgl.xml)
+	include_directories(${FLTK_INCLUDE_DIR})
+	set(mgllab_src editor.cpp help.cpp mathgl.cpp grid.cpp dialogs.cpp mgllab.cpp table.cpp)
+	set(mgllab_hdr mgllab.h)
+	if(WIN32)
+		set(mgllab_src ${mgllab_src} mgllab.rc)
+	endif(WIN32)
+	add_executable(mgllab ${mgllab_src} ${mgllab_hdr})
+	target_link_libraries(mgllab mgl mgl-fltk ${FLTK_LIBRARIES})
+	install(
+		TARGETS mgllab
+		RUNTIME DESTINATION bin	)
+	install(FILES udav.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps/)
+	find_program(findupddb update-desktop-database)
+	if(findupddb)
+		install(FILES mgllab.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications/)
+		install(CODE "execute_process(COMMAND \"${findupddb}\" \"${CMAKE_INSTALL_PREFIX}/share/applications\")")
+	endif(findupddb)
+	find_program(findupmdb update-mime-database)
+	if(findupmdb)
+		install(FILES ${CMAKE_BINARY_DIR}/mgllab/mgl.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mime/packages/)
+		install(CODE "execute_process(COMMAND \"${findupmdb}\" \"${CMAKE_INSTALL_PREFIX}/share/mime\")")
+	endif(findupmdb)
+
+	mgl_po_src(${mgllab_src} ${mgllab_hdr})
+
+endif(MGL_HAVE_FLTK)
diff --git a/mgllab/dialogs.cpp b/mgllab/dialogs.cpp
new file mode 100644
index 0000000..afada7c
--- /dev/null
+++ b/mgllab/dialogs.cpp
@@ -0,0 +1,1541 @@
+/* setup.cpp is part of UDAV
+ * Copyright (C) 2007-2014 Alexey Balakin <mathgl.abalakin at gmail.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License
+ * as published by the Free Software Foundation
+ *
+ * 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
+ */
+#include "mgl2/mgl.h"
+#include "mgllab.h"
+#include <string.h>
+#include <FL/Fl_Spinner.H>
+#include <FL/Fl_Output.H>
+#include <FL/Fl_Select_Browser.H>
+#include <FL/Fl_Toggle_Button.H>
+//-----------------------------------------------------------------------------
+const char *cols = " wbgrcmylenuqphkWBGRCMYLENUQPH";
+Fl_Menu_Item colors[] = {
+	{"-----", 0,0,0,0,0,0,0, 0},	//
+	{_("w - white"), 0,0,0,0,0,0,0, fl_rgb_color(0,0,0)},			//w
+	{_("b - blue"), 0,0,0,0,0,0,0, fl_rgb_color(0,0,255)},		//b
+	{_("g - lime"), 0,0,0,0,0,0,0, fl_rgb_color(0,255,0)},		//g
+	{_("r - red"), 0,0,0,0,0,0,0, fl_rgb_color(255,0,0)},			//r
+	{_("c - cyan"), 0,0,0,0,0,0,0, fl_rgb_color(0,255,255)},		//c
+	{_("m - magenta"), 0,0,0,0,0,0,0, fl_rgb_color(255,0,255)},	//m
+	{_("y - yellow"), 0,0,0,0,0,0,0, fl_rgb_color(255,255,0)},	//y
+	{_("l - springgreen"), 0,0,0,0,0,0,0, fl_rgb_color(0,255,127)},//l
+	{_("e - lawngreen"), 0,0,0,0,0,0,0, fl_rgb_color(127,255,0)},	//e
+	{_("n - skyblue"), 0,0,0,0,0,0,0, fl_rgb_color(0,127,255)},	//n
+	{_("u - blueviolet"), 0,0,0,0,0,0,0, fl_rgb_color(127,0,255)},//u
+	{_("q - orange"), 0,0,0,0,0,0,0, fl_rgb_color(255,127,0)},	//q
+	{_("p - deeppink"), 0,0,0,0,0,0,0, fl_rgb_color(255,0,127)},	//p
+	{_("h - gray"), 0,0,0,0,0,0,0, fl_rgb_color(127,127,127)},	//h
+
+	{_("k - black"), 0,0,0,0,0,0,0, fl_rgb_color(0,0,0)},			//k
+	{_("W - lightgray"), 0,0,0,0,0,0,0, fl_rgb_color(179,179,179)},//W
+	{_("B - navy"), 0,0,0,0,0,0,0, fl_rgb_color(0,0,127)},		//B
+	{_("G - green"), 0,0,0,0,0,0,0, fl_rgb_color(0,127,0)},		//G
+	{_("R - maroon"), 0,0,0,0,0,0,0, fl_rgb_color(127,0,0)},		//R
+	{_("C - teal"), 0,0,0,0,0,0,0, fl_rgb_color(0,127,127)},		//C
+	{_("M - purple"), 0,0,0,0,0,0,0, fl_rgb_color(127,0,127)},	//M
+	{_("Y - olive"), 0,0,0,0,0,0,0, fl_rgb_color(127,127,0)},		//Y
+	{_("L - seagreen"), 0,0,0,0,0,0,0, fl_rgb_color(0,127,77)},	//L
+	{_("E - darklawn"), 0,0,0,0,0,0,0, fl_rgb_color(77,127,0)},	//E
+	{_("N - darkskyblue"), 0,0,0,0,0,0,0, fl_rgb_color(0,77,127)},//N
+	{_("U - indigo"), 0,0,0,0,0,0,0, fl_rgb_color(77,0,127)},		//U
+	{_("Q - brown"), 0,0,0,0,0,0,0, fl_rgb_color(127,77,0)},		//Q
+	{_("P - darkpink"), 0,0,0,0,0,0,0, fl_rgb_color(127,0,77)},	//P
+	{_("H - darkgray"), 0,0,0,0,0,0,0, fl_rgb_color(77,77,77)},	//H
+{0}};
+//-----------------------------------------------------------------------------
+void cb_dlg_cancel(Fl_Widget*, void *v)	{	if(v)	((GeneralDlg*)v)->hide();	}
+void cb_dlg_ok(Fl_Widget*, void *v)		{	if(v)	((GeneralDlg*)v)->cb_ok();	}
+std::string wcstombs(std::wstring wcs)
+{
+	std::string str;
+	const wchar_t *ss = wcs.c_str();
+	size_t s=wcstombs(0,ss,0);	char *buf=new char[s+1];
+	wcstombs(buf,ss,s); buf[s]=0;
+	str = buf;	delete []buf;	return str;
+}
+//-----------------------------------------------------------------------------
+void cb_option_change(Fl_Widget *, void *);
+class OptionDlg : public GeneralDlg
+{
+	Fl_Input *x1, *x2, *y1, *y2, *z1, *z2, *c1, *c2;
+	Fl_Input *val, *meshnum, *size;
+	Fl_Choice *cut, *light;
+	Fl_Input *alpha, *amb, *dif, *legend;
+public:
+	Fl_Input *ext;
+	OptionDlg() : GeneralDlg()
+	{
+		e=NULL;	ext=NULL;
+		Fl_Button *o;
+		w = new Fl_Double_Window(640, 185, _("Add command option(s)"));
+		x1 = new Fl_Input(95, 5, 85, 25, _("X-range"));
+		x1->tooltip(_("Minimal value of X for cutting or for coordinate filling"));
+		x2 = new Fl_Input(190, 5, 85, 25, "-");
+		x2->tooltip(_("Maximal value of X for cutting or for coordinate filling"));
+		y1 = new Fl_Input(95, 35, 85, 25, _("Y-range"));
+		y1->tooltip(_("Minimal value of Y for cutting or for coordinate filling"));
+		y2 = new Fl_Input(190, 35, 85, 25, "-");
+		y2->tooltip(_("Maximal value of Y for cutting or for coordinate filling"));
+		z1 = new Fl_Input(95, 65, 85, 25, _("Z-range"));
+		z1->tooltip(_("Minimal value of Z for cutting or for coordinate filling"));
+		z2 = new Fl_Input(190, 65, 85, 25, "-");
+		z2->tooltip(_("Maximal value of Z for cutting or for coordinate filling"));
+		c1 = new Fl_Input(95, 95, 85, 25, _("C-range"));	c1->deactivate();
+		c1->tooltip(_("Low border for determining color or alpha"));
+		c2 = new Fl_Input(190, 95, 85, 25, "-");		c2->deactivate();
+		c2->tooltip(_("Upper border for determining color or alpha"));
+		val = new Fl_Input(375, 5, 85, 25, _("Value"));	val->labelfont(1);
+		meshnum = new Fl_Input(375, 35, 85, 25, _("MeshNum"));
+		meshnum->tooltip(_("Approximate number of mesh lines in plot"));
+		size = new Fl_Input(375, 65, 85, 25, _("Size"));
+		size->tooltip(_("Set size for text, marks and others"));
+		cut = new Fl_Choice(375, 95, 85, 25, _("Cutting"));
+		cut->add(_("default"));	cut->add("on");	cut->add("off");
+		cut->tooltip(_("Set cutting off/on for particular plot"));
+		alpha = new Fl_Input(550, 5, 85, 25, _("Alpha"));
+		alpha->tooltip(_("Alpha value (transparency) of surface or cloud"));
+		amb = new Fl_Input(550, 35, 85, 25, _("Ambient"));
+		amb->tooltip(_("Own brightness of the surface"));
+		dif = new Fl_Input(550, 65, 85, 25, _("Diffuse"));
+		dif->tooltip(_("Intensity of diffuse light"));
+		light = new Fl_Choice(550, 95, 85, 25, _("Light"));
+		light->add(_("default"));	light->add("on");	light->add("off");
+		cut->tooltip(_("Set lighting off/on for particular plot"));
+		legend = new Fl_Input(95, 125, 540, 25, _("Legend"));
+		cut->tooltip(_("Add legend entry for the plot"));
+		o = new Fl_Button(455, 155, 85, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
+		o = new Fl_Return_Button(550, 155, 85, 25, _("OK"));	o->callback(cb_dlg_ok,this);
+		w->set_modal();	w->end();
+	}
+	void cb_ok()
+	{
+		int v;	const char *s1, *s2;	result.clear();
+		s1=val->value();	if(s1 && *s1)	result = result+";value "+s1;
+		s1=x1->value();	s2=x2->value();	if(s1 && *s1 && s2 && *s2)	result = result+";xrange "+s1+' '+s2;
+		s1=y1->value();	s2=y2->value();	if(s1 && *s1 && s2 && *s2)	result = result+";yrange "+s1+' '+s2;
+		s1=z1->value();	s2=z2->value();	if(s1 && *s1 && s2 && *s2)	result = result+";zrange "+s1+' '+s2;
+//		s1=c1->value();	s2=c2->value();	if(s1 && *s1 && s2 && *s2)	result = result+";crange "+s1+' '+s2;
+		s1=legend->value();	if(s1 && *s1)	result = result+";legend '"+s1+"'";
+		s1=size->value();	if(s1 && *s1)	result = result+";size "+s1;
+		s1=alpha->value();	if(s1 && *s1)	result = result+";alpha "+s1;
+		s1=amb->value();	if(s1 && *s1)	result = result+";ambient "+s1;
+		s1=dif->value();	if(s1 && *s1)	result = result+";diffuse "+s1;
+		s1=meshnum->value();if(s1 && *s1)	result = result+";meshnum "+s1;
+		v=cut->value();		if(v==1 || v==2)	result = result+";cut "+cut->text();
+		v=light->value();	if(v==1 || v==2)	result = result+";light "+light->text();
+		if(e)	e->editor->insert(result.c_str());
+		if(ext)	ext->value(result.c_str());
+		hide();
+	}
+} option_dlg;
+//-----------------------------------------------------------------------------
+void option_dlg_cb(Fl_Widget *, void *v)
+{	option_dlg.ext=NULL;	option_dlg.e=(ScriptWindow *)v;	option_dlg.show();	}
+//-----------------------------------------------------------------------------
+void option_in_cb(Fl_Widget *, void *v)
+{	option_dlg.ext=(Fl_Input*)v;	option_dlg.e=NULL;	option_dlg.show();	}
+//-----------------------------------------------------------------------------
+class DirSelDlg : public GeneralDlg
+{
+	Fl_Choice *dir;
+public:
+	Fl_Input *ext;
+	DirSelDlg() : GeneralDlg()
+	{
+		Fl_Button *o;
+		w = new Fl_Double_Window(220, 85, _("Select direction"));
+		dir = new Fl_Choice(80, 10, 135, 25, _("Direction"));
+		dir->add("xyz");	dir->add("x");	dir->add("y");	dir->add("z");
+		dir->add("xy");	dir->add("xz");	dir->add("yz");
+		o = new Fl_Button(55, 50, 75, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
+		o = new Fl_Return_Button(140, 50, 75, 25, _("OK"));	o->callback(cb_dlg_ok,this);
+		w->set_modal();	w->end();
+	}
+	void cb_ok()
+	{
+		const char *s = dir->text();
+		if(s && *s)	result = std::string("'")+s+"'";
+		if(e)	e->editor->insert(result.c_str());
+		else if(ext)	ext->value(result.c_str());
+		else	cb_args_set(result.c_str());
+		hide();
+	}
+} dirsel_dlg;
+//-----------------------------------------------------------------------------
+void dirsel_dlg_cb(Fl_Widget *, void *v)
+{	dirsel_dlg.ext=NULL;	dirsel_dlg.e=(ScriptWindow *)v;	dirsel_dlg.show();	}
+//-----------------------------------------------------------------------------
+void dirsel_in_cb(Fl_Widget *, void *v)
+{	dirsel_dlg.ext=(Fl_Input*)v;	dirsel_dlg.e=NULL;	dirsel_dlg.show();	}
+//-----------------------------------------------------------------------------
+//const char *arr = "_AKVITSDOX";
+Fl_Menu_Item arrows[] = {
+	{_("'_' none")},		//_
+	{_("'A' arrow")},	//A
+	{_("'K' size")},		//K
+	{_("'V' back arrow")},//V
+	{_("'I' stop")},		//I
+	{_("'T' triangle")},	//T
+	{_("'S' square")},	//S
+	{_("'D' rhomb")},	//D
+	{_("'O' circle")},	//O
+	{_("'X' cross")},	//X
+	{0}};
+//-----------------------------------------------------------------------------
+//const char *stl = "-|j;i=: d";
+Fl_Menu_Item dashing[] = {
+	{_("'-' solid")},		//-
+	{_("'|' long dash")},	//|
+	{_("'j' dash dot")},	//j
+	{_("';' dash")},		//;
+	{_("'i' small dash dot")},	//i
+	{_("'=' small dash")},	//=
+	{_("':' dots")},		//:
+	{_("' ' none")},		//
+	{_("manual")},			// d
+	{0}};
+//-----------------------------------------------------------------------------
+//const char *mrk = "*o+xsd.^v<>";
+Fl_Menu_Item markers[] = {
+	{_("none")},			//
+	{_("'*' star")},		//*
+	{_("'o' circle")},		//o
+	{_("'+' plus")},		//+
+	{_("'x' skew cross")},	//x
+	{_("'s' square")},		//s
+	{_("'d' rhomb")},		//d
+	{_("'.' dot")},			//.
+	{_("'^' triangle up")},	//^
+	{_("'v' triangle down")},//v
+	{_("'<' triangle left")},//<
+	{_("'>' triangle right")},//>
+	{0}};
+//-----------------------------------------------------------------------------
+//const char *msk = " -+=;joOsS~<>dD*^M";
+Fl_Menu_Item masks[] = {
+	{_("none")},			//
+	{_("'-' lines")},		//-
+	{_("'+' plus")},		//+
+	{_("'=' double lines")},//=
+	{_("';' dash")},		//;
+	{_("'j' dash dot")},	//j
+	{_("'o' circle")},		//o
+	{_("'O' solid circle")},//O
+	{_("'s' square")},		//s
+	{_("'S' solid square")},//S
+	{_("'~' waves")},		//~
+	{_("'<' left sign")},	//<
+	{_("'>' right sign")},	//>
+	{_("'d' rhomb")},		//d
+	{_("'D' solid rhomb")},	//D
+	{_("'*' cross")},		//*
+	{_("'^' hats")},		//^
+	{_("manual")},			//M
+	{0}};
+//-----------------------------------------------------------------------------
+std::string get_color(Fl_Choice *c, Fl_Spinner *s, Fl_Input *p)
+{
+	std::string res;
+	const char *ps = p->value();
+	int cv = c->value(), sv = s->value();
+	int pv = ps?10*atof(ps):-1;
+	if(pv<0 || pv>9)	ps = NULL;
+	if(cv>0 && cv<long(strlen(cols)))
+	{
+		if(ps)
+		{
+			if(sv>0 && sv<10 && sv!=5)
+			{
+				char buf[16];	snprintf(buf,16,"{%c%d,0.%d}",cols[cv],sv,pv);
+				res = buf;
+			}
+			else	res = cols[cv];
+		}
+		else
+		{
+			if(sv>0 && sv<10 && sv!=5)
+			{
+				char buf[16];	snprintf(buf,16,"{%c%d}",cols[cv],sv);
+				res = buf;
+			}
+			else	res = cols[cv];
+		}
+	}
+	return res;
+}
+//-----------------------------------------------------------------------------
+void cb_style_upd(Fl_Widget *, void *);
+void cb_style_sch(Fl_Widget *, void *);
+class StyleDlg : public GeneralDlg
+{
+	Fl_Choice *arr1, *dash, *arr2;
+	Fl_Choice *mark;
+	Fl_Check_Button *solid, *user;
+	Fl_Spinner *width;
+	Fl_Button *dash_m[16];
+
+	Fl_Choice *c[8], *sch;
+	Fl_Spinner *s[8];
+	Fl_Input *p[8];
+	Fl_Choice *axial, *contt, *mask, *angle;
+	Fl_Spinner *msize;
+	Fl_Input *alpha;
+	Fl_Button *mask_m[64];
+	Fl_Check_Button *wire, *sharp;
+
+	Fl_Check_Button *bold, *ital, *twire, *uline, *oline, *plain;
+	Fl_Choice *align, *vert;
+
+	Fl_Group *gline, *gsurf, *gfont;
+	Fl_Output *res;
+	Fl_MathGL *gr;
+	std::string script;
+public:
+	Fl_Input *ext;
+	StyleDlg() : GeneralDlg()
+	{
+		Fl_Group *g;	Fl_Button *o;
+		w = new Fl_Double_Window(380, 540, _("Plot style"));
+		Fl_Tabs* tt = new Fl_Tabs(0, 5, 375, 235);
+		gline = new Fl_Group(0, 30, 375, 210, _("Line style"));
+			arr1 = new Fl_Choice(5, 50, 110, 25, _("Arrow at start"));
+			arr1->align(FL_ALIGN_TOP_LEFT);	arr1->copy(arrows);
+			arr1->callback(cb_style_upd);
+			dash = new Fl_Choice(125, 50, 110, 25, _("Dashing"));
+			dash->align(FL_ALIGN_TOP_LEFT);	dash->copy(dashing);
+			dash->callback(cb_style_upd);
+			arr2 = new Fl_Choice(245, 50, 110, 25, _("Arrow at end"));
+			arr2->align(FL_ALIGN_TOP_LEFT);	arr2->copy(arrows);
+			arr2->callback(cb_style_upd);
+			mark = new Fl_Choice(125, 80, 110, 25, _("Marks"));
+			mark->copy(markers);	mark->callback(cb_style_upd);
+			solid = new Fl_Check_Button(240, 80, 55, 25, _("solid"));
+			user = new Fl_Check_Button(300, 80, 55, 25, _("user"));
+			solid->callback(cb_style_upd);	user->callback(cb_style_upd);
+			width = new Fl_Spinner(125, 110, 110, 25, _("Width"));
+			width->range(1,9);	width->value(1);	width->callback(cb_style_upd);
+			for(int i=0;i<16;i++)
+			{
+				dash_m[i] = new Fl_Toggle_Button(10+20*i, 210, 20, 20);
+				dash_m[i]->callback(cb_style_upd);
+			}
+			dash_m[0]->label(_("Manual dashing"));
+			dash_m[0]->align(FL_ALIGN_TOP_LEFT);
+			gline->end();
+		gsurf = new Fl_Group(0, 30, 375, 210, _("Color scheme"));	gsurf->hide();
+			axial = new Fl_Choice(5, 50, 110, 25, _("Axial direction"));
+			axial->align(FL_ALIGN_TOP_LEFT);	axial->callback(cb_style_upd);
+			axial->add("none");	axial->add("x");	axial->add("y");	axial->add("z");
+			contt = new Fl_Choice(125, 50, 110, 25, _("Text on contours"));
+			contt->add("none");	contt->add("under");	contt->add("above");
+			contt->align(FL_ALIGN_TOP_LEFT);	contt->callback(cb_style_upd);
+			alpha = new Fl_Input(255, 50, 110, 25, _("Transparency"));
+			alpha->align(FL_ALIGN_TOP_LEFT);	alpha->callback(cb_style_upd);
+			wire = new Fl_Check_Button(125, 80, 115, 25, _("Wire or mesh"));
+			wire->callback(cb_style_upd);
+			sharp = new Fl_Check_Button(250, 80, 110, 25, _("Sharp colors"));
+			sharp->callback(cb_style_upd);
+			g = new Fl_Group(10, 105, 360, 130, _("Mask"));
+				g->box(FL_ENGRAVED_BOX);	g->align(FL_ALIGN_TOP_LEFT);
+				mask = new Fl_Choice(100, 110, 95, 25, _("Kind"));
+				mask->copy(masks);	mask->callback(cb_style_upd);
+				angle = new Fl_Choice(100, 140, 95, 25, _("Rotation"));
+				angle->add("none");	angle->add("+45");	angle->add("90");	angle->add("-45");
+				angle->callback(cb_style_upd);
+				msize = new Fl_Spinner(100, 170, 95, 25, _("Size"));
+				msize->range(1,9);	msize->value(1);	msize->callback(cb_style_upd);
+				for(int i=0;i<8;i++)	for(int j=0;j<8;j++)
+				{
+					mask_m[i+8*j] = new Fl_Toggle_Button(240+15*i, 110+15*(7-j), 15, 15);
+					mask_m[i+8*j]->callback(cb_style_upd);
+				}
+			g->end();	gsurf->end();
+		gfont = new Fl_Group(0, 30, 375, 210, _("Text style"));	gfont->hide();
+			bold = new Fl_Check_Button(5, 40, 150, 25, _("Bold style"));
+			ital = new Fl_Check_Button(5, 65, 150, 25, _("Italic style"));
+			twire = new Fl_Check_Button(5, 90, 150, 25, _("Wire style"));
+			uline = new Fl_Check_Button(5, 115, 150, 25, _("Underline"));
+			oline = new Fl_Check_Button(5, 140, 150, 25, _("Overline"));
+			bold->callback(cb_style_upd);	ital->callback(cb_style_upd);
+			twire->callback(cb_style_upd);	uline->callback(cb_style_upd);
+			oline->callback(cb_style_upd);
+			align = new Fl_Choice(270, 40, 95, 25, _("Text align"));
+			align->add("left");	align->add("center");	align->add("right");
+			align->value(1);	align->callback(cb_style_upd);
+			vert = new Fl_Choice(270, 75, 95, 25, _("Vertical align"));
+			vert->add("default");	vert->add("center");	vert->add("under");
+			vert->value(0);	vert->callback(cb_style_upd);
+		gfont->end();	tt->end();	tt->callback(cb_style_upd);
+
+		g = new Fl_Group(0, 265, 375, 155, _("Color(s) or color scheme"));
+		g->box(FL_ENGRAVED_BOX);	g->align(FL_ALIGN_TOP_LEFT);
+			sch = new Fl_Choice(170, 270, 115, 25, _("Popular color schemes"));
+			sch->add("BbcyrR");	sch->add("kw");		sch->add("wk");		sch->add("bwr");
+			sch->add("kHCcw");	sch->add("kBbcw");	sch->add("kRryw");	sch->add("kGgew");
+			sch->add("BbwrR");	sch->add("BbwgG");	sch->add("GgwmM");	sch->add("UuwqR");
+			sch->add("QqwcC");	sch->add("CcwyY");	sch->add("bcwyr");	sch->add("wUrqy");
+			sch->add("UbcyqR");	sch->add("bgr");	sch->callback(cb_style_sch);
+			plain = new Fl_Check_Button(290, 270, 80, 25, _("plain"));
+			plain->callback(cb_style_upd);
+			for(int i=0;i<8;i++)
+			{
+				c[i] = new Fl_Choice(5+185*(i/4), 300+30*(i%4), 95, 25);
+				c[i]->copy(colors);	c[i]->callback(cb_style_upd);
+				c[i]->tooltip(_("Value for i-th color"));
+				s[i] = new Fl_Spinner(105+185*(i/4), 300+30*(i%4), 40, 25);
+				s[i]->range(1,9);	s[i]->value(5);
+				s[i]->tooltip(_("Brightness of i-th color"));
+				s[i]->callback(cb_style_upd);
+				p[i] = new Fl_Input(145+185*(i/4), 300+30*(i%4), 40, 25);
+				p[i]->tooltip(_("Relative position of i-th color"));
+				p[i]->callback(cb_style_upd);
+			}
+			g->end();
+		res = new Fl_Output(5, 440, 370, 25, _("Resulting string"));
+		res->align(FL_ALIGN_TOP_LEFT);
+		o = new Fl_Button(300, 475, 75, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
+		o = new Fl_Return_Button(300, 505, 75, 25, _("OK"));	o->callback(cb_dlg_ok,this);
+		gr = new Fl_MathGL(5, 470, 285, 65);	gr->box(FL_ENGRAVED_BOX);	gr->use_pthr = false;
+		mgl_set_size(gr->get_graph(),285,65);	gr->align(FL_ALIGN_LEFT);
+		w->set_modal();	w->end();
+	}
+	void init()	{	update();	}
+	void set_scheme()
+	{
+		const char *ss = sch->text();
+		if(!ss || *ss==0)	return;
+		for(int i=0;i<8;i++)
+		{	p[i]->value(NULL);	s[i]->value(5);	c[i]->value(0);	}
+		for(int i=0;i<8;i++)
+		{
+			if(ss[i]==0)	break;
+			size_t pos = strchr(cols,ss[i])-cols;
+			c[i]->value(pos);
+		}
+		update();
+	}
+	void stl_color()
+	{
+		result.clear();
+		for(int i=0;i<8;i++)
+			result += get_color(c[i],s[i],p[i]);
+	}
+	void stl_line()
+	{
+		stl_color();
+		char dsh = dash->text()[1];
+		char a1 = arr1->text()[1], a2 = arr2->text()[1];
+		const char *s = mark->text();
+		if(*s=='\'')
+		{
+			if(user->value())	result += '&';
+			if(solid->value())	result += '#';
+			result += s[1];
+		}
+		int v = width->value();
+		if(v>1)	result += char(v+'0');
+		if(a1!='_')	result = result + a1 + a2;
+		else if(a2!='_')	result += a2;
+		if(dsh=='a')
+		{
+			unsigned long mask=0;
+			for(int i=0;i<16;i++)	if(dash_m[i]->value())	mask += 1<<i;
+			char buf[128];	snprintf(buf,128,"{d%lX}",mask);	// TODO: %llX in 32bit!
+			result += buf;
+		}
+		else if(dsh!='-')	result += dsh;
+		result = '\''+result+'\'';
+		script = "new a 5 5 'y':plot a "+result+";size 8";
+	}
+	void stl_surf()
+	{
+		stl_color();
+		int v = contt->value();	const char *tt="Tt";
+		if(v>0 && v<3)	result += tt[v-1];
+		const char *m = mask->text();
+		if(*m=='\'')
+		{
+			v = angle->value();	const char *rr="/I\\";
+			if(v>0 && v<4)	result += rr[v-1];
+			v = msize->value();	if(v>1)	result += char(v+'0');
+			result += m[1];
+		}
+		if(*m=='m')
+		{
+			v = angle->value();	const char *rr="/I\\";
+			if(v>0 && v<4)	result += rr[v-1];
+			v = msize->value();	if(v>1)	result += char(v+'0');
+			uint64_t mask=0;
+			for(int i=0;i<64;i++)	if(mask_m[i]->value())	mask += uint64_t(1)<<i;
+#ifdef WIN32
+			char buf[128];	snprintf(buf,128,"{s%llX}",mask);
+#else
+			char buf[128];	snprintf(buf,128,"{s%lX}",mask);
+#endif
+			result += buf;
+		}
+		if(wire->value())	result += '#';
+		if(sharp->value())	result += '|';
+		if(plain->value())	result += '%';
+		v = atoi(alpha->value());
+		if(v>0 && v<10)	result = result + "{A"+char(v+'0')+'}';
+		v = axial->value();	const char *ax="xyz";
+		if(v>0 && v<4)	result = result+':'+ax[v-1];
+		result = '\''+result+'\'';
+		script = "fsurf 'x' "+result;
+	}
+	void stl_font()
+	{
+		stl_color();
+		const char *a="LCR";
+		result = result+':'+a[align->value()];
+		if(bold->value())	result += 'b';
+		if(ital->value())	result += 'i';
+		if(twire->value())	result += 'w';
+		if(uline->value())	result += 'u';
+		if(oline->value())	result += 'o';
+		if(vert->value()==1)	result += 'V';
+		if(vert->value()==2)	result += 'T';
+		result = '\''+result+'\'';
+		script = "text 0 0 'Font test' "+result+";size -8";
+	}
+	void update()
+	{
+		static int busy=0;
+		if(!busy)	{	busy=1;
+			result.clear();
+			if(gline->visible())		stl_line();
+			else if(gfont->visible())	stl_font();
+			else	stl_surf();
+			res->value(result.c_str());
+			mglParse pr;
+			script = "clf:subplot 1 1 0 '':"+script;
+			mgl_parse_text(gr->get_graph(), pr.Self(), script.c_str());
+			gr->update();
+		busy=0;	}
+	}
+	void cb_ok()
+	{
+		update();
+		if(e)	e->editor->insert(result.c_str());
+		else if(ext)	ext->value(result.c_str());
+		else	cb_args_set(result.c_str());
+		hide();
+	}
+} style_dlg;
+//-----------------------------------------------------------------------------
+void cb_style_upd(Fl_Widget *, void *)	{	style_dlg.update();	}
+void cb_style_sch(Fl_Widget *, void *)	{	style_dlg.set_scheme();	}
+//-----------------------------------------------------------------------------
+void style_dlg_cb(Fl_Widget *, void *v)
+{	style_dlg.ext=NULL;	style_dlg.e=(ScriptWindow *)v;	style_dlg.show();	}
+//-----------------------------------------------------------------------------
+void style_in_cb(Fl_Widget *, void *v)
+{	style_dlg.ext=(Fl_Input*)v;	style_dlg.e=NULL;	style_dlg.show();	}
+//-----------------------------------------------------------------------------
+void cb_datsel_upd(Fl_Widget *, void *);
+void cb_datsel_act(Fl_Widget *, void *);
+class DatSelDlg : public GeneralDlg
+{
+	Fl_Choice *name;
+	Fl_Choice *oper;
+	Fl_Choice *dir;
+	Fl_Spinner *x1, *x2, *y1, *y2, *z1, *z2;
+	Fl_Input *clmn;
+	Fl_Check_Button *ax, *ay, *az;
+public:
+	Fl_Input *ext;
+	DatSelDlg() : GeneralDlg()
+	{
+		Fl_Button *o;
+		w = new Fl_Double_Window(355, 255, _("Select data argument"));
+		name = new Fl_Choice(105, 5, 145, 25, _("Data name"));
+		name->callback(cb_datsel_upd);
+		x1 = new Fl_Spinner(105, 35, 60, 25, _("X-slice from"));
+		x2 = new Fl_Spinner(190, 35, 60, 25, _("to"));
+		ax = new Fl_Check_Button(260, 35, 90, 25, _("all"));	ax->callback(cb_datsel_act);
+		y1 = new Fl_Spinner(105, 65, 60, 25, _("Y-slice from"));
+		y2 = new Fl_Spinner(190, 65, 60, 25, _("to"));
+		ay = new Fl_Check_Button(260, 65, 90, 25, _("all"));	ay->callback(cb_datsel_act);
+		z1 = new Fl_Spinner(105, 95, 60, 25, _("Z-slice from"));
+		z2 = new Fl_Spinner(190, 95, 60, 25, _("to"));
+		az = new Fl_Check_Button(260, 95, 90, 25, _("all"));	az->callback(cb_datsel_act);
+		clmn = new Fl_Input(105, 125, 245, 25, _("Column expr"));
+		oper = new Fl_Choice(105, 155, 130, 25, _("Operation"));
+		oper->add("none");	oper->add("max");	oper->add("min");	oper->add("sum");
+		oper->add("trace");	oper->add("pulse");	oper->value(0);
+		dir = new Fl_Choice(285, 155, 65, 25, _("along"));
+		dir->add("none");	dir->add("x");	dir->add("y");	dir->add("z");
+		dir->add("xy");		dir->add("xz");	dir->add("yz");
+		o = new Fl_Button(190, 190, 75, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
+		o = new Fl_Return_Button(275, 190, 75, 25, _("OK"));	o->callback(cb_dlg_ok,this);
+		w->set_modal();	w->end();
+	}
+	void cb_ok()
+	{
+		result.clear();
+		if(name->value()<0)
+		{	fl_alert(_("You need to select data array"));	return;	}
+		std::string data = name->text();
+		const char *eq = clmn->value();
+		int rx=ax->value(), ry=ay->value(), rz=az->value();
+		int vx1=x1->value(), vy1=y1->value(), vz1=z1->value();
+		int vx2=x2->value(), vy2=y2->value(), vz2=z2->value();
+		if(eq && *eq)	data = data+"('"+eq+"')";
+		else	if(!rx || !ry || !rz)
+		{
+			char bx[256],by[256],bz[256];
+			if(rx)	strcpy(bx,"(:");
+			else if(vx2<=vx1)	snprintf(bx,255,"(%d",vx1);
+			else	snprintf(bx,255,"(%d:%d",vx1,vx2);
+			if(ry)	strcpy(by,",:");
+			else if(vy2<=vy1)	snprintf(by,255,",%d",vy1);
+			else	snprintf(by,255,",%d:%d",vy1,vy2);
+			if(vz2<=vz1)	snprintf(bz,255,",%d)",vz1);
+			else	snprintf(bz,255,",%d:%d)",vz1,vz2);
+			if(!rz)	data = data+bx+by+bz;
+			else if(!ry)	data = data+bx+by+')';
+			else if(!rx)	data = data+bx+')';
+		}
+		if(oper->value()>0)
+		{
+			result = result+'{'+oper->text()+' '+data;
+			if(dir->value()>0)	result = result+" '"+dir->text()+"'}";
+			else	result += '}';
+		}
+		else	result = data;
+		if(e)	e->editor->insert(result.c_str());
+		else if(ext)	ext->value(result.c_str());
+		else	cb_args_set(result.c_str());
+		hide();
+	}
+	void init()
+	{
+		name->clear();
+		long n = Parse->GetNumVar();
+		for(long i=0;i<n;i++)
+		{
+			HCDT d = Parse->GetVar(i);
+			if(!d->temp)	name->add(wcstombs(d->s).c_str());
+		}
+		x1->value(0);	x2->value(0);
+		y1->value(0);	y2->value(0);
+		z1->value(0);	z2->value(0);
+	}
+	void update()
+	{
+		HCDT d = Parse->FindVar(name->text());
+		if(d)
+		{
+			long nx=d->GetNx()-1, ny=d->GetNy()-1, nz=d->GetNz()-1;
+			x1->range(0,nx);	if(x1->value()>nx)	x1->value(0);
+			x2->range(0,nx);	if(x2->value()>nx)	x2->value(0);
+			y1->range(0,ny);	if(y1->value()>ny)	y1->value(0);
+			y2->range(0,ny);	if(y2->value()>ny)	y2->value(0);
+			z1->range(0,nz);	if(z1->value()>nz)	z1->value(0);
+			z2->range(0,nz);	if(z2->value()>nz)	z2->value(0);
+			ax->value(1);	ay->value(1);	az->value(1);
+			x1->deactivate();	y1->deactivate();	z1->deactivate();
+			x2->deactivate();	y2->deactivate();	z2->deactivate();
+			clmn->value("");
+		}
+	}
+	void activate()
+	{
+		if(!ax->value())	{	x1->activate();	x2->activate();	}
+		else	{	x1->deactivate();	x2->deactivate();	}
+		if(!ay->value())	{	y1->activate();	y2->activate();	}
+		else	{	y1->deactivate();	y2->deactivate();	}
+		if(!az->value())	{	z1->activate();	z2->activate();	}
+		else	{	z1->deactivate();	z2->deactivate();	}
+	}
+} datsel_dlg;
+//-----------------------------------------------------------------------------
+void cb_datsel_upd(Fl_Widget *, void *)	{	datsel_dlg.update();	}
+void cb_datsel_act(Fl_Widget *, void *)	{	datsel_dlg.activate();	}
+//-----------------------------------------------------------------------------
+void datsel_dlg_cb(Fl_Widget *, void *v)
+{	datsel_dlg.ext=NULL;	datsel_dlg.e=(ScriptWindow *)v;	datsel_dlg.show();	}
+//-----------------------------------------------------------------------------
+void datsel_in_cb(Fl_Widget *, void *v)
+{	datsel_dlg.ext=(Fl_Input*)v;	datsel_dlg.e=NULL;	datsel_dlg.show();	}
+//-----------------------------------------------------------------------------
+std::string with_arg(std::string ss, std::vector<std::string> prev)
+{
+	size_t l=ss.length(), n=prev.size();
+	for(size_t i=0;i<n;i++)
+		if(!strncmp(prev[i].c_str(),ss.c_str(),l))
+		{	ss = prev[i];	break;	}
+	return ss;
+}
+//-----------------------------------------------------------------------------
+void cb_cmd_type(Fl_Widget*, void*);
+void cb_cmd_cmd(Fl_Widget*, void*);
+void cb_cmd_var(Fl_Widget*, void*);
+void cb_cmd_args(Fl_Widget*, void*);
+class NewCmdDlg : public GeneralDlg
+{
+	Fl_Choice *type, *cmd, *var;
+	Fl_Group *desc;
+	Fl_Select_Browser *args;
+	Fl_Input *opt;
+	Fl_Help_View *help;
+	std::vector<std::string> cmds[17];	///< commands divided by type
+public:
+	NewCmdDlg() : GeneralDlg()
+	{
+		Fl_Button *o;
+		w = new Fl_Double_Window(780, 300, _("New command"));
+		Fl_Group *g = new Fl_Group(5,5,315,320);
+		type = new Fl_Choice(80, 5, 270, 25, _("Kind"));
+		type->tooltip(_("Groups of MGL commands"));
+		type->callback(cb_cmd_type);
+		type->add(_("1D plots"));
+		type->add(_("2D plots"));
+		type->add(_("3D plots"));
+		type->add(_("Dual plots"));
+		type->add(_("Vector plots"));
+		type->add(_("Other plots"));
+		type->add(_("Text and legend"));
+		type->add(_("Create data and IO"));
+		type->add(_("Data transform"));
+		type->add(_("Data handling"));
+		type->add(_("Axis and colorbar"));
+		type->add(_("Axis setup"));
+		type->add(_("General setup"));
+		type->add(_("Scale and rotate"));
+		type->add(_("Program flow"));
+		type->add(_("Primitives"));
+
+		cmd = new Fl_Choice(80, 35, 270, 25, _("Command"));
+		cmd->tooltip(_("MGL commands for selected group"));
+		cmd->callback(cb_cmd_cmd);
+		var = new Fl_Choice(80, 95, 270, 25, _("Variant"));
+		var->tooltip(_("Variant of command argument order. The notation is:\n"
+								" * Capital arguments are data (like, Ydat);\n"
+								" * Argument in '' are strings (like, 'fmt');\n"
+								" * Other arguments are numbers (like, zval);\n"
+								" * Arguments in [] are optional arguments."));
+		var->callback(cb_cmd_var);
+		desc = new Fl_Group(0, 65, 350, 25, _("Description"));
+		desc->box(FL_ENGRAVED_BOX);	desc->labelsize(12);
+		desc->align(FL_ALIGN_CENTER);	desc->end();
+		desc->tooltip(_("Short description of selected command"));
+		args = new Fl_Select_Browser(5, 140, 345, 95, _("Arguments"));
+		args->align(FL_ALIGN_TOP_LEFT);	args->callback(cb_cmd_args);
+		args->tooltip(_("Command arguments. Bold ones are required arguments.\n"
+			"Other are optional arguments but its order is required.\n"
+			"You can use '' for default format. See help at right\nfor default values."));
+		static int widths[] = { 95, 250, 0 };  // widths for each column
+		args->column_widths(widths);	args->column_char('\t');
+
+		opt = new Fl_Input(60, 240, 265, 25, _("Options"));
+		o = new Fl_Button(325, 240, 25, 25, "...");	o->callback(option_in_cb,opt);
+
+		o = new Fl_Button(190, 270, 75, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
+		o = new Fl_Return_Button(275, 270, 75, 25, _("OK"));	o->callback(cb_dlg_ok,this);
+		g->end();	g->resizable(args);
+
+		help = new Fl_Help_View(360, 5, 415, 290);	help->labelsize(12);
+		w->set_modal();	w->end();	w->resizable(help);
+	}
+	void init()	// fill cmds from parser for all categories
+	{
+		long i, n = Parse->GetCmdNum();
+		for(i=0;i<n;i++)
+		{
+			std::string name = Parse->GetCmdName(i);
+			switch(Parse->CmdType(name.c_str()))
+			{
+				case 1:	cmds[5].push_back(name);	break;
+				case 2:	cmds[5].push_back(name);	break;
+				case 3:	cmds[12].push_back(name);	break;
+				case 4:	cmds[9].push_back(name);	break;
+				case 5:	cmds[7].push_back(name);	break;
+				case 6:	cmds[13].push_back(name);	break;
+				case 7:	cmds[14].push_back(name);	break;
+				case 8:	cmds[0].push_back(name);	break;
+				case 9:	cmds[1].push_back(name);	break;
+				case 10:cmds[2].push_back(name);	break;
+				case 11:cmds[3].push_back(name);	break;
+				case 12:cmds[4].push_back(name);	break;
+				case 13:cmds[10].push_back(name);	break;
+				case 14:cmds[15].push_back(name);	break;
+				case 15:cmds[11].push_back(name);	break;
+				case 16:cmds[6].push_back(name);	break;
+				case 17:cmds[8].push_back(name);	break;
+			}
+		}
+		type->value(0);	type_sel();
+	}
+	void type_sel()	// fill list of commands for selected type
+	{
+		int t = type->value();	cmd->clear();
+		for(size_t i=0;i<cmds[t].size();i++)	cmd->add(cmds[t][i].c_str());
+		cmd->value(0);	cmd_sel();
+	}
+	void cmd_sel()	// fill list of variants for selected command
+	{
+		static std::string str;
+		const char *c = cmd->text();
+		desc->label(Parse->CmdDesc(c));
+		str = helpname+c;
+		help->load(str.c_str());
+		std::string par = Parse->CmdFormat(c), cname;
+		std::vector<std::string> vars;
+		size_t isp = par.find_first_of(' ');
+		if(isp<par.length())
+		{
+			cname = par.substr(0,isp+1);
+			par = par.substr(isp+1);
+			while((isp=par.find_first_of('|'))<par.length())
+			{
+				vars.push_back(cname+par.substr(0,isp));
+				par = par.substr(isp+1);
+			}
+			vars.push_back(cname+par);
+		}
+		else	vars.push_back(par);
+		var->clear();
+		for(size_t i=0;i<vars.size();i++)	var->add(vars[i].c_str());
+		var->value(0);	var_sel();
+	}
+	void var_sel()	// fill list of arguments for selected variant
+	{
+		std::string par = var->text(), sec;
+		size_t isp = par.find_first_of(' ');
+		par = par.substr(isp+1);	// remove command name
+		isp = par.find_first_of('[');	// here secional args starts
+		sec = isp<par.length()?par.substr(isp+1,par.length()-isp-2):"";
+		par = isp>0?par.substr(0,isp-1):"";
+		std::vector<std::string> prev_args;
+		for(int i=1;i<=args->size();i++)
+		{
+			const char *s = args->text(i);
+			if(s && *s && strchr(s,'\t'))	prev_args.push_back(s[0]=='@'?s+3:s);
+		}
+		args->clear();
+		while((isp=par.find_first_of(' '))<par.length())
+		{
+			args->add(("@b "+with_arg(par.substr(0,isp), prev_args)).c_str());
+			par = par.substr(isp+1);
+		}
+		if(!par.empty())	args->add(("@b "+with_arg(par, prev_args)).c_str());
+		while((isp=sec.find_first_of(' '))<sec.length())
+		{
+			args->add(with_arg(sec.substr(0,isp), prev_args).c_str());
+			sec = sec.substr(isp+1);
+		}
+		if(!sec.empty())	args->add(with_arg(sec, prev_args).c_str());
+	}
+	void args_sel()	// fill argument by calling external dialog
+	{
+		int a = args->value();
+		const char *s = args->text(a);	if(!s || *s==0)	return;
+		std::string arg = s, val;
+		size_t isp = arg.find_first_of('\t');
+		val = arg.substr(isp+1);	arg = arg.substr(0,isp);
+		if(arg[0]=='@')	arg = arg.substr(3);
+		if(arg[0]>='A' && arg[0]<='Z')	datsel_dlg_cb(0,0);	// this is data
+		else if(arg=="'fmt'")	style_dlg_cb(0,0);	// this is style
+		else if(arg=="'fname'")	ins_fname_cb(0,0);	// this is file name
+		else if(arg=="'path'")	ins_path_cb(0,0);	// this is path
+		else if(arg=="'dir'")	dirsel_dlg_cb(0,0);	// this is path
+		else if(arg[0]=='\'')	// this is general string
+		{
+			const char *s = fl_input(_("Enter value for %s argument"), val.c_str(), arg.c_str());
+			if(s)
+			{	std::string ss=s;	args_set(('\''+ss+'\'').c_str());	}
+		}
+		else	// this is general constant
+		{
+			const char *s = fl_input(_("Enter value for %s argument"), val.c_str(), arg.c_str());
+			if(s)	args_set(s);
+		}
+	}
+	void args_set(const char *val)	// set value for current argument
+	{
+		int a = args->value();
+		const char *s = args->text(a);	if(!s || *s==0)	return;
+		std::string arg = s;
+		size_t isp = arg.find_first_of('\t');
+		arg = arg.substr(0,isp)+'\t'+val;
+		args->text(a,arg.c_str());
+	}
+	void cb_ok()
+	{
+		std::string par = var->text(), a;
+		size_t isp = par.find_first_of(' ');
+		result = par.substr(0,isp);	// command name
+		for(int i=1;i<=args->size();i++)
+		{
+			const char *s = args->text(i);
+			if(!s)	continue;
+			const char *p = strchr(s,'\t');
+			if(s[0]=='@' && !p)
+			{
+				fl_alert(_("Required argument %s is not specified!"),s+3);	return;
+			}
+			if(p)	result = result+' '+(p+1);
+		}
+		result += opt->value();
+		if(e)
+		{
+			int p = textbuf->line_start(e->editor->insert_position());
+			textbuf->insert(p, (result+'\n').c_str());
+		}
+		hide();
+	}
+	void set_cmd(const char *line)	// TODO
+	{}
+} newcmd_dlg;
+//-----------------------------------------------------------------------------
+void cb_cmd_type(Fl_Widget*, void*)	{	newcmd_dlg.type_sel();	}
+void cb_cmd_cmd(Fl_Widget*, void*)	{	newcmd_dlg.cmd_sel();	}
+void cb_cmd_var(Fl_Widget*, void*)	{	newcmd_dlg.var_sel();	}
+void cb_cmd_args(Fl_Widget*, void*)	{	newcmd_dlg.args_sel();	}
+void cb_args_set(const char *val)	{	newcmd_dlg.args_set(val);	}
+//-----------------------------------------------------------------------------
+void newcmd_dlg_cb(Fl_Widget*,void *v)		// TODO parse current line?!?
+{	newcmd_dlg.e=(ScriptWindow *)v;	newcmd_dlg.show();	}
+//-----------------------------------------------------------------------------
+void cb_setup_save(Fl_Widget*,void *v);
+class SetupDlg : public GeneralDlg
+{
+	Fl_Choice *xlpos, *ylpos, *zlpos, *clpos;
+	Fl_Float_Input *x1, *x2, *x0, *xtick, *xstick, *xotick;
+	Fl_Input *xlabel, *xtmpl, *xfact;
+	Fl_Float_Input *y1, *y2, *y0, *ytick, *ystick, *yotick;
+	Fl_Input *ylabel, *ytmpl, *yfact;
+	Fl_Float_Input *z1, *z2, *z0, *ztick, *zstick, *zotick;
+	Fl_Input *zlabel, *ztmpl, *zfact;
+	Fl_Float_Input *c1, *c2, *c0, *ctick;
+	Fl_Input *clabel, *ctmpl, *cfact;
+	Fl_Float_Input *alphadef, *ambient, *diffuse;
+	Fl_Input *palette, *font_stl, *axis_stl, *plotid;
+	Fl_Float_Input *fog, *fog_dz, *pendelta;
+	Fl_Float_Input *meshnum, *facenum, *arr_size, *bar_size;
+	Fl_Float_Input *mrk_size, *txt_size, *tick_size;
+
+	Fl_Check_Button *alpha, *light, *cut, *attach;
+	Fl_Check_Button *origintick, *gray, *rotatetext;
+	Fl_Choice *time, *tunetick, *ternary, *transptype;
+	Fl_Spinner *variant;
+
+	Fl_Toggle_Button *lb[10];
+	Fl_Choice *lc[10];
+	Fl_Float_Input *lx[10], *ly[10], *lz[10], *lbr[10];
+	Fl_Input *fname;
+public:
+	SetupDlg() : GeneralDlg()
+	{
+		Fl_Button *o;	Fl_Group *g, *gg;
+		w = new Fl_Double_Window(525, 395, _("Setup script"));
+		Fl_Tabs* tt = new Fl_Tabs(0, 0, 525, 355);
+		gg = new Fl_Group(0, 25, 525, 330, _("Axis setup"));
+			new Fl_Box(85, 30, 100, 25, _("X axis"));
+			x1 = new Fl_Float_Input(85, 55, 100, 25, _("Minimal"));
+			x2 = new Fl_Float_Input(85, 85, 100, 25, _("Maximal"));
+			x0 = new Fl_Float_Input(85, 115, 100, 25, _("Origin"));
+			xlabel = new Fl_Input(85, 145, 100, 25, _("Label"));
+			xtick = new Fl_Float_Input(85, 205, 100, 25, _("Ticks"));
+			xlpos = new Fl_Choice(85, 175, 100, 25, _("at position"));
+			xlpos->add(_("left"));	xlpos->add(_("center"));
+			xlpos->add(_("right"));	xlpos->value(1);
+			xstick = new Fl_Float_Input(85, 235, 100, 25, _("Subticks"));
+			xotick = new Fl_Float_Input(85, 265, 100, 25, _("Ticks start"));
+			xtmpl = new Fl_Input(85, 295, 100, 25, _("Template"));
+			xfact = new Fl_Input(85, 325, 100, 25, _("Factor"));
+			new Fl_Box(195, 30, 100, 25, _("Y axis"));
+			y1 = new Fl_Float_Input(195, 55, 100, 25);
+			y2 = new Fl_Float_Input(195, 85, 100, 25);
+			y0 = new Fl_Float_Input(195, 115, 100, 25);
+			ylabel = new Fl_Input(195, 145, 100, 25);
+			ytick = new Fl_Float_Input(195, 205, 100, 25);
+			ylpos = new Fl_Choice(195, 175, 100, 25);
+			ylpos->add(_("left"));	ylpos->add(_("center"));
+			ylpos->add(_("right"));	ylpos->value(1);
+			ystick = new Fl_Float_Input(195, 235, 100, 25);
+			yotick = new Fl_Float_Input(195, 265, 100, 25);
+			ytmpl = new Fl_Input(195, 295, 100, 25);
+			yfact = new Fl_Input(195, 325, 100, 25);
+			new Fl_Box(305, 30, 100, 25, _("Z axis"));
+			z1 = new Fl_Float_Input(305, 55, 100, 25);
+			z2 = new Fl_Float_Input(305, 85, 100, 25);
+			z0 = new Fl_Float_Input(305, 115, 100, 25);
+			zlabel = new Fl_Input(305, 145, 100, 25);
+			ztick = new Fl_Float_Input(305, 205, 100, 25);
+			zlpos = new Fl_Choice(305, 175, 100, 25);
+			zlpos->add(_("left"));	zlpos->add(_("center"));
+			zlpos->add(_("right"));	zlpos->value(1);
+			zstick = new Fl_Float_Input(305, 235, 100, 25);
+			zotick = new Fl_Float_Input(305, 265, 100, 25);
+			ztmpl = new Fl_Input(305, 295, 100, 25);
+			zfact = new Fl_Input(305, 325, 100, 25);
+			new Fl_Box(415, 30, 100, 25, _("C axis"));
+			c1 = new Fl_Float_Input(415, 55, 100, 25);
+			c2 = new Fl_Float_Input(415, 85, 100, 25);
+			c0 = new Fl_Float_Input(415, 115, 100, 25);
+			clabel = new Fl_Input(415, 145, 100, 25);
+			ctick = new Fl_Float_Input(415, 205, 100, 25);
+			clpos = new Fl_Choice(415, 175, 100, 25);
+			clpos->add(_("left"));	clpos->add(_("center"));
+			clpos->add(_("right"));	clpos->value(1);
+			ctmpl = new Fl_Input(415, 295, 100, 25);
+			cfact = new Fl_Input(415, 325, 100, 25);
+			gg->end();
+		gg = new Fl_Group(0, 25, 525, 330, _("General setup"));	gg->hide();
+			g = new Fl_Group(5, 45, 180, 305, _("Colors"));	g->box(FL_ENGRAVED_BOX);
+			alphadef = new Fl_Float_Input(80, 55, 100, 25, _("AlphaDef"));
+			ambient = new Fl_Float_Input(80, 85, 100, 25, _("Ambient"));
+			diffuse = new Fl_Float_Input(80, 115, 100, 25, _("Diffuse"));
+			palette = new Fl_Input(80, 145, 100, 25, _("Palette"));
+			font_stl = new Fl_Input(80, 175, 100, 25, _("Font"));
+			axis_stl = new Fl_Input(80, 205, 100, 25, _("Axis"));
+			fog = new Fl_Float_Input(80, 235, 100, 25, _("Fog"));
+			fog_dz = new Fl_Float_Input(80, 265, 100, 25, _("Fog dist."));
+			gray = new Fl_Check_Button(80, 290, 100, 25, _("grayscale"));
+			alpha = new Fl_Check_Button(10, 315, 65, 25, _("alpha"));
+			light = new Fl_Check_Button(80, 315, 100, 25, _("lighting"));
+			g->end();
+			g = new Fl_Group(185, 45, 180, 250, _("Sizes"));	g->box(FL_ENGRAVED_BOX);
+			meshnum = new Fl_Float_Input(260, 55, 100, 25, _("meshnum"));
+			facenum = new Fl_Float_Input(260, 85, 100, 25, _("facenum"));
+			arr_size = new Fl_Float_Input(260, 115, 100, 25, _("arrows"));
+			bar_size = new Fl_Float_Input(260, 145, 100, 25, _("bars"));
+			mrk_size = new Fl_Float_Input(260, 175, 100, 25, _("markers"));
+			txt_size = new Fl_Float_Input(260, 205, 100, 25, _("text"));
+			tick_size = new Fl_Float_Input(260, 235, 100, 25, _("ticks"));
+			pendelta = new Fl_Float_Input(260, 265, 100, 25, _("pen blur"));
+			g->end();
+			g = new Fl_Group(365, 45, 155, 305, _("Others"));	g->box(FL_ENGRAVED_BOX);
+			cut = new Fl_Check_Button(370, 50, 115, 25, _("cutting"));
+			attach = new Fl_Check_Button(370, 70, 115, 25, _("attach light"));
+			origintick = new Fl_Check_Button(370, 90, 115, 25, _("no origin tick"));
+			rotatetext = new Fl_Check_Button(370, 110, 115, 25, _("rotate text"));
+
+			time = new Fl_Choice(370, 150, 145, 25, _("Time ticks"));
+			time->add("none");	time->add("x");	time->add("y");	time->add("z");
+			time->align(FL_ALIGN_TOP_LEFT);	time->value(0);
+			tunetick = new Fl_Choice(370, 195, 145, 25, _("Tune ticks"));
+			tunetick->add(_("none"));	tunetick->add(_("factor"));
+			tunetick->add(_("increment"));	tunetick->add(_("both"));
+			tunetick->align(FL_ALIGN_TOP_LEFT);	tunetick->value(0);
+			ternary = new Fl_Choice(370, 235, 145, 25, _("Ternary"));
+			ternary->add(_("none"));	ternary->add(_("ternary"));
+			ternary->add(_("quaternary"));	ternary->add(_("projection"));
+			ternary->add(_("ternary proj"));	ternary->add(_("quaternary proj"));
+			ternary->align(FL_ALIGN_TOP_LEFT);	ternary->value(0);
+			transptype = new Fl_Choice(370, 275, 145, 25, _("Transparency type"));
+			transptype->add(_("default"));	ternary->add(_("glass-like"));
+			transptype->add(_("lamp-like"));
+			transptype->align(FL_ALIGN_TOP_LEFT);	transptype->value(0);
+			variant = new Fl_Spinner(370, 315, 145, 25, _("Variant"));
+			variant->align(FL_ALIGN_TOP_LEFT);	variant->range(0,100);	variant->value(0);
+			g->end();
+		plotid = new Fl_Input(190, 321, 172, 25, _("Plot ID"));
+		plotid->align(FL_ALIGN_TOP_LEFT);
+		gg->end();
+		gg = new Fl_Group(0, 25, 525, 330, _("Light settings"));	gg->hide();
+			static const char *id[10]={"0:","1:","2:","3:","4:","5:","6:","7:","8:","9:"};
+			for(int i=0;i<10;i++)
+			{
+				lb[i] = new Fl_Toggle_Button(10, 50+30*i, 25, 25, id[i]);
+				lx[i] = new Fl_Float_Input(40, 50+30*i, 90, 25);
+				ly[i] = new Fl_Float_Input(135, 50+30*i, 90, 25);
+				lz[i] = new Fl_Float_Input(230, 50+30*i, 90, 25);
+				lc[i] = new Fl_Choice(325, 50+30*i, 95, 25);
+				lbr[i]= new Fl_Float_Input(425, 50+30*i, 90, 25);
+				lc[i]->copy(colors);	lc[i]->value(0);
+			}
+			lx[0]->label(_("X position"));	lx[0]->align(FL_ALIGN_TOP_LEFT);
+			ly[0]->label(_("Y position"));	ly[0]->align(FL_ALIGN_TOP_LEFT);
+			lz[0]->label(_("Z position"));	lz[0]->align(FL_ALIGN_TOP_LEFT);
+			lc[0]->label(_("Color"));			lc[0]->align(FL_ALIGN_TOP_LEFT);
+			lbr[0]->label(_("Brightness"));	lbr[0]->align(FL_ALIGN_TOP_LEFT);
+			gg->end();	tt->end();
+		o = new Fl_Button(365, 365, 75, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
+		o = new Fl_Return_Button(445, 365, 75, 25, _("OK"));	o->callback(cb_dlg_ok,this);
+		fname = new Fl_Input(100, 365, 175, 25, _("File to export"));
+		o = new Fl_Button(275, 365, 25, 25, "@->");	o->callback(cb_setup_save);
+		o->tooltip(_("Keep empty to put at beginning of main script."));
+		w->end();
+	}
+	void prepare()
+	{
+		result.clear();
+		const char *s1, *s2, *s3, *s4;
+		s1=x1->value();	s2=x2->value();
+		if(s1 && *s1 && s2 && *s2)	result = result+"xrange "+s1+' '+s2+'\n';
+		s1=y1->value();	s2=y2->value();
+		if(s1 && *s1 && s2 && *s2)	result = result+"yrange "+s1+' '+s2+'\n';
+		s1=z1->value();	s2=z2->value();
+		if(s1 && *s1 && s2 && *s2)	result = result+"zrange "+s1+' '+s2+'\n';
+		s1=c1->value();	s2=c2->value();
+		if(s1 && *s1 && s2 && *s2)	result = result+"crange "+s1+' '+s2+'\n';
+		s1=x0->value();	s2=y0->value();	s3=z0->value();
+		if(s3 && *s3)	result = result+"origin "+(s1?s1:"nan")+' '+(s2?s2:"nan")+' '+s3+'\n';
+		else if(s2 && *s2)	result = result+"origin "+(s1?s1:"nan")+' '+s2+'\n';
+		else if(s1 && *s1)	result = result+"origin "+s1+"nan\n";
+
+		s1=xtmpl->value();	if(s1 && *s1)	result = result+"xtick '"+s1+"'\n";
+		s1=ytmpl->value();	if(s1 && *s1)	result = result+"ytick '"+s1+"'\n";
+		s1=ztmpl->value();	if(s1 && *s1)	result = result+"ztick '"+s1+"'\n";
+		s1=ctmpl->value();	if(s1 && *s1)	result = result+"ctick '"+s1+"'\n";
+
+		s1=xtick->value();	s2=xstick->value();	s3=xotick->value();	s4=xfact->value();
+		if(s4 && *s4)	result = result+"xtick "+(s1?s1:"0")+' '+(s2?s2:"0")+' '+(s3?s3:"nan")+" '"+s4+"'\n";
+		else if(s3 && *s3)	result = result+"xtick "+(s1?s1:"0")+' '+(s2?s2:"0")+' '+s3+'\n';
+		else if(s2 && *s2)	result = result+"xtick "+(s1?s1:"0")+' '+s2+'\n';
+		else if(s1 && *s1)	result = result+"xtick "+s1+'\n';
+		s1=ytick->value();	s2=ystick->value();	s3=yotick->value();	s4=yfact->value();
+		if(s4 && *s4)	result = result+"ytick "+(s1?s1:"0")+' '+(s2?s2:"0")+' '+(s3?s3:"nan")+" '"+s4+"'\n";
+		else if(s3 && *s3)	result = result+"ytick "+(s1?s1:"0")+' '+(s2?s2:"0")+' '+s3+'\n';
+		else if(s2 && *s2)	result = result+"ytick "+(s1?s1:"0")+' '+s2+'\n';
+		else if(s1 && *s1)	result = result+"ytick "+s1+'\n';
+		s1=ztick->value();	s2=zstick->value();	s3=zotick->value();	s4=zfact->value();
+		if(s4 && *s4)	result = result+"ztick "+(s1?s1:"0")+' '+(s2?s2:"0")+' '+(s3?s3:"nan")+" '"+s4+"'\n";
+		else if(s3 && *s3)	result = result+"ztick "+(s1?s1:"0")+' '+(s2?s2:"0")+' '+s3+'\n';
+		else if(s2 && *s2)	result = result+"ztick "+(s1?s1:"0")+' '+s2+'\n';
+		else if(s1 && *s1)	result = result+"ztick "+s1+'\n';
+		s1=ctick->value();	s4=cfact->value();
+		if(s4 && *s4)	result = result+"ctick "+(s1?s1:"0")+" '"+s4+"'\n";
+		else if(s1 && *s1)	result = result+"ctick "+s1+'\n';
+		const char *pos[3]={"' -1\n","' 0\n","' 1\n"};
+		s1=xlabel->value();	if(s1 && *s1)	result = result+"xlabel '"+s1+pos[xlpos->value()];
+		s1=ylabel->value();	if(s1 && *s1)	result = result+"ylabel '"+s1+pos[ylpos->value()];
+		s1=zlabel->value();	if(s1 && *s1)	result = result+"zlabel '"+s1+pos[zlpos->value()];
+//TODO	s1=clabel->value();	if(s1 && *s1)	result = result+"clabel '"+s1+pos[clpos->value()];
+
+		s1=alphadef->value();	if(s1 && *s1)	result = result+"alphadef "+s1+'\n';
+		s1=ambient->value();	if(s1 && *s1)	result = result+"ambient "+s1+'\n';
+		s1=diffuse->value();	if(s1 && *s1)	result = result+"diffuse "+s1+'\n';
+		s1=palette->value();	if(s1 && *s1)	result = result+"palette '"+s1+"'\n";
+		s1=plotid->value();		if(s1 && *s1)	result = result+"plotid '"+s1+"'\n";
+		s1=axis_stl->value();	if(s1 && *s1)	result = result+"axisstl '"+s1+"'\n";
+		s1=meshnum->value();	if(s1 && *s1)	result = result+"meshnum "+s1+'\n';
+		s1=facenum->value();	if(s1 && *s1)	result = result+"facenum "+s1+'\n';
+		s1=arr_size->value();	if(s1 && *s1)	result = result+"arrowsize "+s1+'\n';
+		s1=bar_size->value();	if(s1 && *s1)	result = result+"barwidth "+s1+'\n';
+		s1=mrk_size->value();	if(s1 && *s1)	result = result+"marksize "+s1+'\n';
+		s1=pendelta->value();	if(s1 && *s1)	result = result+"pendelta "+s1+'\n';
+		s1=tick_size->value();	if(s1 && *s1)	result = result+"ticklen "+s1+'\n';
+
+		s1=font_stl->value();	s2=txt_size->value();
+		if(s2 && *s2)	result = result+"font '"+(s1?s1:"")+"' "+s2+'\n';
+		else if(s1 && *s1)	result = result+"font '"+s1+"'\n";
+		s1=fog->value();	s2=fog_dz->value();
+		if(s1 && *s1 && s2 && *s2)	result = result+"fog "+s1+' '+s2+'\n';
+		else if(s1 && *s1)	result = result+"font "+s1+"\n";
+
+		if(alpha->value())	result = result+"alpha on\n";
+		if(light->value())	result = result+"light on\n";
+		if(cut->value())	result = result+"cut on\n";
+		if(attach->value())	result = result+"attachlight on\n";
+		if(gray->value())	result = result+"gray on\n";
+		if(rotatetext->value())	result = result+"rotatetext on\n";
+		if(origintick->value())	result = result+"origintick off\n";
+		if(variant->value()>0)
+		{	char buf[32];	snprintf(buf,31,"variant %ld\n",mgl_int(variant->value()));	result += buf;	}
+		const char *stime[4]={"''\n","'x'\n","'y'\n","'z'\n"};
+		if(time->value()>0)	result = result+"timetick "+stime[time->value()];
+		const char *stune[4]={" 0\n"," 1\n"," 2\n"," 3\n"};
+		if(tunetick->value()>0)	result = result+"tunetick "+stune[tunetick->value()];
+		const char *stern[6]={" 0\n"," 1\n"," 2\n"," 4\n"," 5\n"," 6\n"};
+		if(ternary->value()>0)	result = result+"ternary "+stern[ternary->value()];
+		const char *stype[3]={" 0\n"," 1\n"," 2\n"};
+		if(transptype->value()>0)	result = result+"ternary "+stype[transptype->value()];
+		for(int i=0;i<10;i++)
+		{
+			if(!lb[i]->value())	continue;
+			s1 = lx[i]->value();	s2 = ly[i]->value();
+			s3 = lz[i]->value();	s4 = lbr[i]->value();
+			char col = cols[lc[i]->value()];	if(col==' ')	col='w';
+			if(s1 && *s1 && s2 && *s2 && s3 && *s3)
+			{
+				result = result+"light "+char('0'+i)+' '+s1+' '+s2+' '+s3+" '"+col+'\'';
+				if(s4 && *s4)	result = result+' '+s4;
+				result += '\n';
+			}
+		}
+	}
+	void cb_ok()
+	{
+		prepare();
+		if(e)	{	e->draw->script=result;	e->graph->update();	}
+		hide();
+	}
+	void save()
+	{
+		prepare();
+		const char *s=fname->value();
+		if(s && *s)
+		{
+			FILE *fp = fl_fopen(s,"wt");
+			if(fp)	{	fputs(result.c_str(),fp);	fclose(fp);	}
+			else	fl_alert(_("Couldn't open file %s"),s);
+		}
+		else
+		{
+			textbuf->insert(0, ("##### setup start #####\n" + result + "##### setup end #####\n").c_str());
+//			if(e)	e->draw->script="";
+		}
+	}
+} setup_dlg;
+//-----------------------------------------------------------------------------
+void setup_dlg_cb(Fl_Widget*,void *v)
+{	setup_dlg.e = (ScriptWindow*)v;	setup_dlg.show();	}
+//-----------------------------------------------------------------------------
+void cb_setup_save(Fl_Widget*,void *v)	{	setup_dlg.save();	}
+//-----------------------------------------------------------------------------
+void cp_inplot_upd(Fl_Widget*,void*);
+void cb_only_inplot(Fl_Widget*,void*);
+class InplotDlg : public GeneralDlg
+{
+	Fl_Round_Button *k1, *k2, *k3, *k4, *k5, *k6;
+	Fl_Spinner *n1, *m1, *i1;
+	Fl_Counter *x1, *y1;
+	Fl_Spinner *n2, *m2, *i2, *x2, *y2;
+	Fl_Spinner *n3, *m3, *i3;
+	Fl_Counter *d3;
+	Fl_Spinner *n4, *i4;
+	Fl_Counter *d4;
+	Fl_Spinner *n5, *i5;
+	Fl_Float_Input *xx1, *xx2, *yy1, *yy2;
+	Fl_Spinner *tet, *phi;
+	Fl_Float_Input *ax, *ay;
+	Fl_Check_Button *rl, *rb, *rt, *rr, *rw;
+	Fl_Input *text;
+	Fl_Output *res;
+	Fl_MathGL *gr;
+public:
+	InplotDlg() : GeneralDlg()
+	{
+		Fl_Button *o;
+		w = new Fl_Double_Window(715, 315, _("Add inplot"));
+		k1 = new Fl_Round_Button(5, 5, 105, 25, "SubPlot");
+		k1->callback(cb_only_inplot,k1);	k1->type(FL_RADIO_BUTTON);
+		n1 = new Fl_Spinner(145, 5, 55, 25, "nx");
+		n1->callback(cp_inplot_upd);	n1->range(1,100);
+		m1 = new Fl_Spinner(230, 5, 55, 25, "ny");
+		m1->callback(cp_inplot_upd);	m1->range(1,100);
+		i1 = new Fl_Spinner(315, 5, 55, 25, _("ind"));
+		i1->callback(cp_inplot_upd);	i1->value(0);
+		x1 = new Fl_Counter(400, 5, 95, 25, "dx");		x1->align(FL_ALIGN_LEFT);
+		x1->callback(cp_inplot_upd);	x1->value(0);	x1->step(0.01);	x1->lstep(0.1);
+		y1 = new Fl_Counter(525, 5, 95, 25, "dy");		y1->align(FL_ALIGN_LEFT);
+		y1->callback(cp_inplot_upd);	y1->value(0);	y1->step(0.01);	y1->lstep(0.1);
+
+		k2 = new Fl_Round_Button(5, 35, 105, 25, "MultiPlot");
+		k2->callback(cb_only_inplot,k2);	k2->type(FL_RADIO_BUTTON);
+		n2 = new Fl_Spinner(145, 35, 55, 25, "nx");
+		n2->callback(cp_inplot_upd);	n2->range(1,100);
+		m2 = new Fl_Spinner(230, 35, 55, 25, "ny");
+		m2->callback(cp_inplot_upd);	m2->range(1,100);
+		i2 = new Fl_Spinner(315, 35, 55, 25, _("ind"));
+		i2->callback(cp_inplot_upd);	i2->value(0);
+		x2 = new Fl_Spinner(425, 35, 70, 25, "x-size");
+		x2->callback(cp_inplot_upd);	x2->value(1);
+		y2 = new Fl_Spinner(550, 35, 70, 25, "y-size");
+		y2->callback(cp_inplot_upd);	y2->value(1);
+
+		k3 = new Fl_Round_Button(5, 65, 105, 25, "GridPlot");
+		k3->callback(cb_only_inplot,k3);	k3->type(FL_RADIO_BUTTON);
+		n3 = new Fl_Spinner(145, 65, 55, 25, "nx");
+		n3->callback(cp_inplot_upd);	n3->range(1,100);
+		m3 = new Fl_Spinner(230, 65, 55, 25, "ny");
+		m3->callback(cp_inplot_upd);	m3->range(1,100);
+		i3 = new Fl_Spinner(315, 65, 55, 25, _("ind"));
+		i3->callback(cp_inplot_upd);	i3->value(0);
+		d3 = new Fl_Counter(400, 65, 95, 25, "d");	d3->align(FL_ALIGN_LEFT);
+		d3->callback(cp_inplot_upd);	d3->step(0.01);	d3->lstep(0.1);
+
+		k4 = new Fl_Round_Button(5, 95, 105, 25, "ColumnPlot");
+		k4->callback(cb_only_inplot,k4);	k4->type(FL_RADIO_BUTTON);
+		n4 = new Fl_Spinner(145, 95, 55, 25, "nx");
+		n4->callback(cp_inplot_upd);	n4->range(1,100);
+		i4 = new Fl_Spinner(315, 95, 55, 25, _("ind"));
+		i4->callback(cp_inplot_upd);	i4->value(0);
+		d4 = new Fl_Counter(400, 95, 95, 25, "d");	d4->align(FL_ALIGN_LEFT);
+		d4->callback(cp_inplot_upd);	d4->step(0.01);	d4->lstep(0.1);
+
+		k5 = new Fl_Round_Button(5, 125, 105, 25, "StickPlot");
+		k5->callback(cb_only_inplot,k5);	k5->type(FL_RADIO_BUTTON);
+		n5 = new Fl_Spinner(145, 125, 55, 25, "nx");
+		n5->callback(cp_inplot_upd);	n5->range(1,100);
+		i5 = new Fl_Spinner(315, 125, 55, 25, _("ind"));
+		i5->callback(cp_inplot_upd);	i5->value(0);
+
+		k6 = new Fl_Round_Button(5, 155, 105, 25, "InPlot");
+		k6->callback(cb_only_inplot,k6);	k6->type(FL_RADIO_BUTTON);
+		xx1 = new Fl_Float_Input(145, 155, 60, 25, "x:");
+		xx1->callback(cp_inplot_upd);	xx1->value("0");
+		xx2 = new Fl_Float_Input(225, 155, 60, 25, "...");
+		xx2->callback(cp_inplot_upd);	xx2->value("1");
+		yy1 = new Fl_Float_Input(315, 155, 60, 25, "y:");
+		yy1->callback(cp_inplot_upd);	yy1->value("0");
+		yy2 = new Fl_Float_Input(400, 155, 60, 25, "...");
+		yy2->callback(cp_inplot_upd);	yy2->value("1");
+
+		tet = new Fl_Spinner(75, 190, 60, 25, _("Rotate on"));
+		tet->callback(cp_inplot_upd);	tet->value(0);	tet->step(5);	tet->range( -90, 90);
+		phi = new Fl_Spinner(170, 190, 60, 25, _("and"));
+		phi->callback(cp_inplot_upd);	phi->value(0);	phi->step(5);	phi->range(-180,180);
+		ax = new Fl_Float_Input(315, 190, 60, 25, _("Aspect x/z"));
+		ax->callback(cp_inplot_upd);	ax->value("1");
+		ay = new Fl_Float_Input(400, 190, 60, 25, "y/z");
+		ay->callback(cp_inplot_upd);	ay->value("1");
+
+		new Fl_Box(0, 225, 90, 25, _("Reserve at:"));
+		rl = new Fl_Check_Button(90, 225, 70, 25, _("left"));
+		rl->callback(cp_inplot_upd);	rl->value(1);
+		rb = new Fl_Check_Button(160, 225, 70, 25, _("bottom"));
+		rb->callback(cp_inplot_upd);	rb->value(1);
+		rt = new Fl_Check_Button(230, 225, 70, 25, _("top"));
+		rt->callback(cp_inplot_upd);	rt->value(1);
+		rr = new Fl_Check_Button(300, 225, 70, 25, _("right"));
+		rr->callback(cp_inplot_upd);	rr->value(1);
+		rw = new Fl_Check_Button(370, 225, 90, 25, _("whole area"));	rw->callback(cp_inplot_upd);
+		text = new Fl_Input(80, 255, 320, 25, _("Title"));	text->callback(cp_inplot_upd);
+		o = new Fl_Button(400, 255, 60, 25, _("Style"));	o->callback(style_dlg_cb,0);
+		res = new Fl_Output(50, 285, 410, 25, _("Result"));
+		gr = new Fl_MathGL(470, 130, 240, 180);	gr->box(FL_ENGRAVED_BOX);	gr->use_pthr = false;
+		mgl_set_size(gr->get_graph(),240,180);	gr->align(FL_ALIGN_LEFT);
+		o = new Fl_Button(545, 95, 75, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
+		o = new Fl_Return_Button(630, 95, 75, 25, _("OK"));	o->callback(cb_dlg_ok,this);
+		o = new Fl_Button(630, 60, 75, 25, _("Refresh"));	o->callback(cp_inplot_upd);
+		w->set_modal();	w->end();
+	}
+	void init()	{	style_dlg.result.clear();	}
+	void update()
+	{
+		std::string how, title, script;
+		if(rw->value())	// prepare space reservation
+			how="#";
+		else
+		{
+			if(rl->value())	how+='<';
+			if(rb->value())	how+='_';
+			if(rt->value())	how+='^';
+			if(rr->value())	how+='>';
+		}
+		char buf[128];	result.clear();
+		const char *s=text->value();
+		if(s && *s)	// prepare title
+		{
+			std::string fmt = style_dlg.result;
+			snprintf(buf,127,"title '%s'",s);	title = buf;
+			if(fmt.empty())	title += ':';
+			else	title += ' '+fmt+':';
+		}
+		if(k1->value())	// subplot
+		{
+			long n=mgl_int(n1->value()), m=mgl_int(m1->value()), k=mgl_int(i1->value());
+			i1->range(0, m*n-1);	// set to be sure if n or m are changed
+			snprintf(buf,127,"subplot %ld %ld %ld '%s' %g %g:", n,m,k, how.c_str(), x1->value(), y1->value());
+			result = buf+title;
+			double t=tet->value(), p=phi->value();
+			if(t!=0 || p!=0)
+			{	snprintf(buf,127,"rotate %g %g:", t,p);	result += buf;	}
+			for(long i=0;i<m*n;i++)	if(i!=k)
+			{	snprintf(buf,127,"subplot %ld %ld %ld:box 'c'\n", n,m,i);	script += buf;	}
+		}
+		else if(k2->value())	// multiplot
+		{
+			long n=mgl_int(n2->value()), m=mgl_int(m2->value()), k=mgl_int(i2->value());
+			long x=mgl_int(x2->value()), y=mgl_int(y2->value());
+			i2->range(0, m*n-1);	x2->range(0, n-1);	y2->range(0, m-1);	// set to be sure if n or m are changed
+			snprintf(buf,127,"multiplot %ld %ld %ld %ld %ld '%s':", n,m,k,x,y, how.c_str());
+			result = buf+title;
+			double t=tet->value(), p=phi->value();
+			if(t!=0 || p!=0)
+			{	snprintf(buf,127,"rotate %g %g:", t,p);	result += buf;	}
+			for(long i=0;i<m*n;i++)	if(i!=k)
+			{	snprintf(buf,127,"subplot %ld %ld %ld:box 'c'\n", n,m,i);	script += buf;	}
+		}
+		else if(k3->value())	// gridplot
+		{
+			long n=mgl_int(n3->value()), m=mgl_int(m3->value()), k=mgl_int(i3->value());
+			double d=d3->value();
+			i3->range(0, m*n-1);	// set to be sure if n or m are changed
+			snprintf(buf,127,"gridplot %ld %ld %ld %g:", n,m,k,d);
+			result = buf;
+			for(long i=0;i<m*n;i++)	if(i!=k)
+			{	snprintf(buf,127,"gridplot %ld %ld %ld %g:box 'c'\n", n,m,k,d);	script += buf;	}
+		}
+		else if(k4->value())	// columnplot
+		{
+			long n=mgl_int(n4->value()), k=mgl_int(i4->value());
+			double d=d4->value();
+			i4->range(0, n-1);	// set to be sure if n or m are changed
+			snprintf(buf,127,"columnplot %ld %ld %g:", n,k,d);	result = buf;
+			double t=tet->value(), p=phi->value();
+			std::string rot="";
+			if(t!=0 || p!=0)
+			{	snprintf(buf,127,"rotate %g %g:", t,p);	result += buf;	rot = buf;	}
+			for(long i=0;i<n;i++)	if(i!=k)
+			{	snprintf(buf,127,"columnplot %ld %ld %g:%sbox 'c'\n", n,k,d,rot.c_str());	script += buf;	}
+		}
+		else if(k5->value())	// stickplot
+		{
+			long n=mgl_int(n5->value()), k=mgl_int(i5->value());
+			i5->range(0, n-1);	// set to be sure if n or m are changed
+			double t=tet->value(), p=phi->value();
+			snprintf(buf,127,"stickplot %ld %ld %g %g:", n,k,t,p);	result = buf;
+			for(long i=0;i<n;i++)	if(i!=k)
+			{	snprintf(buf,127,"stickplot %ld %ld %g %g:box 'c'\n", n,k,t,p);	script += buf;	}
+		}
+		else if(k6->value())	// inplot
+		{
+			std::string sx1=xx1->value(), sx2=xx2->value(), sy1=yy1->value(), sy2=yy2->value();
+			if(!sx1.empty() && !sy1.empty() && !sx2.empty() && !sy2.empty())
+			{
+				snprintf(buf,127,"inplot %s %s %s %s:", sx1.c_str(), sx2.c_str(), sy1.c_str(), sy2.c_str());
+				result = buf;
+				double t=tet->value(), p=phi->value();
+				if(t!=0 || p!=0)	{	snprintf(buf,127,"rotate %g %g:", t,p);	result += buf;	}
+			}
+			script = "subplot 1 1 0:box 'c'\n";
+		}
+		double aspx = atof(ax->value()), aspy = atof(ay->value());
+		snprintf(buf,127,"aspect %g %g 1",aspx,aspy);
+		if(aspx!=0 && aspy!=0 && (aspx!=1 || aspy!=1))	result += buf;
+		script = "clf\n"+script+result+"\nbox\n";
+		res->value(result.c_str());
+
+		mglParse pr;
+		mgl_parse_text(gr->get_graph(), pr.Self(), script.c_str());
+		gr->update();
+	}
+	void cb_ok()
+	{
+		update();
+		if(e)
+		{
+			int p = textbuf->line_start(e->editor->insert_position());
+			textbuf->insert(p, (result+'\n').c_str());
+		}
+		hide();
+	}
+} inplot_dlg;
+//-----------------------------------------------------------------------------
+void cp_inplot_upd(Fl_Widget*,void*)	{	inplot_dlg.update();	}
+void cb_only_inplot(Fl_Widget*,void *v)
+{	((Fl_Round_Button*)v)->setonly();	inplot_dlg.update();	}
+//-----------------------------------------------------------------------------
+void inplot_dlg_cb(Fl_Widget*,void *v)
+{	inplot_dlg.e = (ScriptWindow*)v;	inplot_dlg.show();	}
+//-----------------------------------------------------------------------------
+class PrimDlg : public GeneralDlg
+{
+	Fl_Choice *kind, *col, *arr1, *arr2, *dash, *mark;
+	Fl_Check_Button *fill;
+	Fl_Input *text;
+	Fl_Spinner *num;
+public:
+	PrimDlg() : GeneralDlg()
+	{
+		Fl_Button *o;
+		w = new Fl_Double_Window(295, 200, _("Add primitive"));
+		Fl_Menu_Item k[]={{_("marker")}, {_("line")}, { _("rectangle")},
+			{_("curve")}, {_("rhomb")}, { _("ellipse")},
+			{_("arc")}, {_("polygon")}, { _("text")}, {0}};
+		kind = new Fl_Choice(65, 10, 75, 25, _("Kind"));
+		kind->copy(k);		kind->value(0);
+		col = new Fl_Choice(205, 10, 75, 25, _("Color"));
+		col->copy(colors);	col->value(4);
+		arr1 = new Fl_Choice(65, 40, 75, 25, _("Begin"));
+		arr1->copy(arrows);	arr1->value(0);
+		arr2 = new Fl_Choice(205, 40, 75, 25, _("End"));
+		arr2->copy(arrows);	arr2->value(0);
+		dash = new Fl_Choice(65, 70, 75, 25, _("Dash"));
+		dash->copy(dashing);	dash->value(0);
+		mark = new Fl_Choice(205, 70, 75, 25, _("Mark"));
+		mark->copy(markers);	mark->value(0);	mark->value(2);
+		num = new Fl_Spinner(65, 100, 75, 25, _("Edges"));
+		num->range(1,100);	num->value(5);
+		fill = new Fl_Check_Button(205, 100, 75, 25, _("wire"));	fill->value(1);
+		text = new Fl_Input(65, 130, 215, 25, _("Text"));
+		o = new Fl_Button(120, 165, 75, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
+		o = new Fl_Return_Button(205, 165, 75, 25, _("OK"));	o->callback(cb_dlg_ok,this);
+		w->set_modal();	w->end();
+	}
+	void cb_ok()
+	{
+		result.clear();
+		int k = kind->value();
+		char c = cols[col->value()];	if(c==' ')	c='w';
+		char dsh = dash->text()[1];
+		char a1 = arr1->text()[1], a2 = arr2->text()[1];
+		const char *s = mark->text();
+		char mrk = (s && *s=='\'')? s[1]:0;
+		switch(k)
+		{
+		case 0:
+			if(!mrk)	{	fl_alert(_("You need to select marker!"));	return;	}
+			result = "ball 0 0 '";
+			if(!fill->value())	result += '&';
+			result = result+mrk+c+"'\n";	break;
+		case 1:
+			result = "line -0.2 0 0.2 0 '2";
+			if(dsh!=' ' && dsh!='-')	result += dsh;
+			if(a1!='_')	result = result+a2+a1;
+			else if(a2!='_')	result += a2;
+			result = result+c+"'\n";	break;
+		case 2:
+			result = "rect -0.2 -0.2 0.2 0.2 '2";
+			if(!fill->value())	result += '#';
+			result = result+c+"'\n";	break;
+		case 3:
+			result = "curve -0.2 0 0 0.5 0.2 0 0 0.5 '2";
+			if(dsh!=' ' && dsh!='-')	result += dsh;
+			if(a1!='_')	result = result+a2+a1;
+			else if(a2!='_')	result += a2;
+			result = result+c+"'\n";	break;
+		case 4:
+			result = "rhomb -0.2 0 0.2 0 0.1 '2";
+			if(!fill->value())	result += '#';
+			result = result+c+"'\n";	break;
+		case 5:
+			result = "ellipse -0.2 0 0.2 0 0.1 '2";
+			if(!fill->value())	result += '#';
+			result = result+c+"'\n";	break;
+		case 6:
+			result = "arc 0 0 0.2 0 60 '2";
+			if(dsh!=' ' && dsh!='-')	result += dsh;
+			if(a1!='_')	result = result+a2+a1;
+			else if(a2!='_')	result += a2;
+			result = result+c+"'\n";	break;
+		case 7:
+			result = "polygon 0 0 0 0.2 "+mgl_str_num(num->value())+" '2";
+			if(!fill->value())	result += '#';
+			result = result+c+"'\n";	break;
+		case 8:
+			s = text->value();
+			if(!s || *s==0)	{	fl_alert(_("You need to enter text!"));	return;	}
+			result = result+"text 0 0 0.1 0 '"+s+"' '"+c;
+			if(fill->value())	result += ":w";
+			result = result+"'\n";	break;
+		}
+		if(e)	{	e->graph->FMGL->prim += result;	e->graph->update();	}
+		hide();
+	}
+} prim_dlg;
+//-----------------------------------------------------------------------------
+void prim_dlg_cb(Fl_Widget*, void* v)
+{	prim_dlg.e=(ScriptWindow*)v;	prim_dlg.show();	}
+//-----------------------------------------------------------------------------
diff --git a/mgllab/editor.cpp b/mgllab/editor.cpp
new file mode 100644
index 0000000..f6b87c5
--- /dev/null
+++ b/mgllab/editor.cpp
@@ -0,0 +1,692 @@
+/* editor.cpp is part of UDAV
+ * Copyright (C) 2007-2014 Alexey Balakin <mathgl.abalakin at gmail.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License
+ * as published by the Free Software Foundation
+ *
+ * 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
+ */
+#include <ctype.h>
+#include <errno.h>
+#ifdef __MWERKS__
+# define FL_DLL
+#endif
+#ifdef WIN32
+#include <direct.h>
+#else
+#include <unistd.h>
+#endif
+#include "mgllab.h"
+//-----------------------------------------------------------------------------
+int changed = 0;
+std::string filename;
+Fl_Text_Buffer *textbuf = 0;
+//-----------------------------------------------------------------------------
+// Syntax highlighting
+Fl_Text_Buffer	 *stylebuf = 0;
+Fl_Text_Display::Style_Table_Entry styletable[10] = {	// Style table
+		{ FL_BLACK,		FL_COURIER,		14, 0 },		// A - Plain
+		{ FL_DARK_GREEN,FL_COURIER_ITALIC,	14, 0 },	// B - Line comments
+		{ FL_BLUE,		FL_COURIER,		14, 0 },		// C - Number
+		{ FL_RED,		FL_COURIER,		14, 0 },		// D - Strings
+		{ FL_DARK_BLUE,	FL_COURIER,		14, 0 },		// E - Usual command
+		{ FL_DARK_CYAN,	FL_COURIER,		14, 0 },		// F - Flow command
+		{ FL_DARK_MAGENTA,	FL_COURIER,	14, 0 },		// G - New-data command
+		{ FL_DARK_RED,	FL_COURIER,		14, 0 },		// H - Option
+		{ FL_DARK_GREEN,FL_COURIER,		14, 0 },		// I - Inactive command
+		{ FL_MAGENTA,	FL_COURIER,		14, 0 }			// J - Error line ???
+	};
+int font_kind;	///< Editor font kind
+int font_size;	///< Editor font size
+//-----------------------------------------------------------------------------
+void set_style(int kind, int size)
+{
+	if(kind<0 || kind>2)	kind = 1;
+	if(size<1)	size = 14;
+	for(int i=0;i<10;i++)	// set font for styles
+	{	styletable[i].size = size;	styletable[i].font = 4*kind;	}
+	styletable[1].font = 4*kind+2;
+	font_kind = kind;	font_size = size;
+}
+//-----------------------------------------------------------------------------
+bool is_sfx(const char *s)	// suffix
+{
+	size_t i,n=strlen(s);
+	for(i=0;i<n && s[i]>='a';i++);
+	if(i==1 && s[0]=='a')	return true;
+	if(i==2 && strchr("nmawsk",s[0]) && strchr("axyz",s[1]))	return true;
+	if(i==3 && (!strncmp("fst",s,3) || !strncmp("lst",s,3) || !strncmp("max",s,3) ||
+				!strncmp("min",s,3) || !strncmp("sum",s,3)))
+		return true;
+	if(i==3 && s[0]=='m' && strchr("xyz",s[1]) && strchr("fl",s[2]))	return true;
+	return false;
+//	char *t = new char[i+1];	memcpy(t,s,i*sizeof(char));	t[i]=0;
+}
+//-----------------------------------------------------------------------------
+bool is_opt(const char *s)	// option
+{
+	const char *o[13]={"xrange","yrange","zrange","crange","alpha",
+					"cut","value","meshnum","size","legend",
+					"ambient","diffuse","light"};
+	int l[13] = {6,6,6,6,5, 3,5,7,4,6, 7,7,5};
+	for(size_t i=0;i<13;i++)	if(!strncmp(o[i],s,l[i]) && s[l[i]]<=' ')	return true;
+	return false;
+}
+//-----------------------------------------------------------------------------
+bool is_num(const char *s)	// number
+{
+	size_t n=strlen(s);
+//	if(s[0]==':' && (s[1]<=' ' || s[1]==';'))	return true;
+	if(s[0]<=' ' || s[0]==';' || s[0]==':')	return false;
+	if(n>=2 && (s[2]<=' ' || s[2]==';' || s[2]==':'))
+	{
+		if(!strncmp("pi",s,2))	return true;
+		if(!strncmp("on",s,2))	return true;
+	}
+	if(n>=3 && (s[3]<=' ' || s[3]==';' || s[3]==':'))
+	{
+		if(!strncmp("off",s,3))	return true;
+		if(!strncmp("nan",s,3))	return true;
+		if(!strncmp("inf",s,3))	return true;
+		if(!strncmp("all",s,3))	return true;
+	}
+	for(size_t i=0;i<n;i++)
+	{
+		if(s[i]<=' ' || s[i]==';' || s[i]==':')	break;
+		if(!strchr("+-.eE0123456789",s[i]))	return false;
+	}
+	return true;
+//	char *t = new char[i+1];	memcpy(t,s,i*sizeof(char));	t[i]=0;
+}
+//-----------------------------------------------------------------------------
+char is_cmd(const char *s)	// command
+{
+	register long i,n=strlen(s)+1;
+	char res=0, *w=new char[n];	strcpy(w,s);
+	for(i=0;i<n;i++)	if(!isalnum(s[i]))	w[i]=0;
+	int rts = Parse->CmdType(w);
+	if(rts==5)		res = 'G';
+	else if(rts==7)	res = 'F';
+	else if(rts)	res = 'E';
+	delete []w;		return res;
+}
+//-----------------------------------------------------------------------------
+// Parse text and produce style data.
+void style_parse(const char *text, char *style, int /*length*/)
+{
+	size_t n=strlen(text);
+	bool nl=true;
+	// Style letters:
+	// A - Plain
+	// B - Line comments
+	// C - Number
+	// D - Strings
+	// E - Usual command
+	// F - Flow command
+	// G - New data command
+	// H - Option
+
+	for(size_t i=0;i<n;i++)
+	{
+		char ch = text[i], r;	style[i] = 'A';
+		if(ch=='#')	// comment
+			for(;i<n && text[i]!='\n';i++)	style[i]='B';
+		else if(ch=='\'')	// string
+		{
+			style[i]='D';	i++;
+			for(;i<n && text[i]!='\n' && text[i]!='\'';i++)	style[i]='D';
+			style[i]='D';
+		}
+		else if(ch=='\n' || ch==':')	{	nl=true;	continue;	}
+		else if(nl && (r=is_cmd(text+i)) )	// command name
+		{	for(;i<n && isalnum(text[i]);i++)	style[i]=r;	i--;	}
+		else if(!nl && is_opt(text+i))	// option
+		{	for(;i<n && isalpha(text[i]);i++)	style[i]='H';	i--;	}
+		else if(!nl && is_num(text+i))	// number
+		{
+			for(;i<n && strchr("+-.eE0123456789pionaf",text[i]);i++)	style[i]='C';
+			i--;
+		}
+		else if(ch=='.' && is_sfx(text+i+1))	// option (suffix)
+		{
+			style[i]='H';	i++;
+			for(;i<n && isalpha(text[i]);i++)	style[i]='H';
+		}
+		else if(ch=='.' || (ch>='0' && ch<='9'))
+		{	style[i]='C';	if(text[i+1]=='e' || text[i+1]=='E')	style[i+1]='C';	}
+		nl = false;
+	}
+}
+//-----------------------------------------------------------------------------
+// Initialize the style buffer
+void style_init()
+{
+	long len = textbuf->length();
+	char *style = new char[len + 1];
+	char *text = textbuf->text();
+	memset(style, 'A', len);	style[len] = '\0';
+	if(!stylebuf)	stylebuf = new Fl_Text_Buffer(len);
+	style_parse(text, style, len);
+	stylebuf->text(style);
+	delete []style;	free(text);
+}
+//-----------------------------------------------------------------------------
+// Update unfinished styles.
+void style_unfinished_cb(int, void*) {}
+//-----------------------------------------------------------------------------
+// Update the style buffer...
+void style_update(int pos, int nInserted, int nDeleted, int	/*nRestyled*/, const char */*deletedText*/, void *cbArg)
+{
+	long start, end;	// Start and end of text
+	char last,		// Last style on line
+		*style,		// Style data
+		*text;		// Text data
+
+	// If this is just a selection change, just unselect the style buffer...
+	if (nInserted == 0 && nDeleted == 0) {	stylebuf->unselect();	return;  }
+	// Track changes in the text buffer...
+	if (nInserted > 0)
+	{
+		// Insert characters into the style buffer...
+		style = new char[nInserted + 1];
+		memset(style, 'A', nInserted);
+		style[nInserted] = '\0';
+
+		stylebuf->replace(pos, pos + nDeleted, style);
+		delete[] style;
+	}
+	else	// Just delete characters in the style buffer...
+		stylebuf->remove(pos, pos + nDeleted);
+	// Select the area that was just updated to avoid unnecessary callbacks...
+	stylebuf->select(pos, pos + nInserted - nDeleted);
+	// Re-parse the changed region; we do this by parsing from the
+	// beginning of the previous line of the changed region to the end of
+	// the line of the changed region...  Then we check the last
+	// style character and keep updating if we have a multi-line
+	// comment character...
+	start = textbuf->line_start(pos);
+	end   = textbuf->line_end(pos + nInserted);
+	text  = textbuf->text_range(start, end);
+	style = stylebuf->text_range(start, end);
+	if (start==end)	last = 0;
+	else	last = style[end-start-1];
+	style_parse(text, style, end - start);
+	stylebuf->replace(start, end, style);
+	((Fl_Text_Editor *)cbArg)->redisplay_range(start, end);
+
+	if (start==end || last != style[end-start-1])
+	{
+		// Either the user deleted some text, or the last character on
+		// the line changed styles, so reparse the remainder of the buffer...
+		free(text);	free(style);
+		end   = textbuf->length();
+		text  = textbuf->text_range(start, end);
+		style = stylebuf->text_range(start, end);
+		style_parse(text, style, end - start);
+		stylebuf->replace(start, end, style);
+		((Fl_Text_Editor *)cbArg)->redisplay_range(start, end);
+	}
+	free(text);	free(style);
+}
+//-----------------------------------------------------------------------------
+ScriptWindow::ScriptWindow(int w, int h, const char* t) : Fl_Double_Window(w, h, t)
+{	editor = 0;	}
+//-----------------------------------------------------------------------------
+void set_path(char *buf)
+{
+#ifdef WIN32
+	char sep='\\';
+#else
+	char sep='/';
+#endif
+	for(long i=strlen(buf)-1;i>=0;i--)	if(buf[i]==sep)
+	{	buf[i]=0;	break;	}
+	if(!chdir(buf))	printf("chdir to '%s'\n",buf);
+}
+//-----------------------------------------------------------------------------
+void add_filename(const char *fname, ScriptWindow *e)
+{
+	static char buf[FL_PATH_MAX];
+	fl_filename_absolute(buf, FL_PATH_MAX, fname);	fname=buf;
+	if(!fname || !fname[0] || lastfiles[0]==fname)
+	{	set_path(buf);	return;	}
+	pref.set("last_file",fname);
+	int ii=4;
+	for(int i=1;i<5;i++)
+		if(lastfiles[i]==fname)	{	ii=i;	break;	}
+	for(int i=ii;i>0;i--)	lastfiles[i]=lastfiles[i-1];
+	lastfiles[0]=fname;
+	int ir = e->menu->find_index(_("File/Recent files"));
+	if(ir<0)	ir = 6;
+	e->menu->replace(ir+1, lastfiles[0].c_str());
+	e->menu->replace(ir+2, lastfiles[1].c_str());
+	e->menu->replace(ir+3, lastfiles[2].c_str());
+	e->menu->replace(ir+4, lastfiles[3].c_str());
+	e->menu->replace(ir+5, lastfiles[4].c_str());
+	set_path(buf);	save_pref();
+}
+//-----------------------------------------------------------------------------
+int check_save(void)
+{
+  if (!changed) return 1;
+  int r = fl_choice(_("The current file has not been saved.\n"
+					"Would you like to save it now?"),
+					_("Cancel"), _("Save"), _("Don't Save"));
+  if(r==1)	{	save_cb(0,0);	return !changed;	} // Save the file...
+  return (r==2) ? 1 : 0;
+}
+//-----------------------------------------------------------------------------
+void data_file(const char *fn)
+{
+	static int num=0;
+	static char name[32], res[256];
+	snprintf(name,32,"mgl_%d",num);	num++;
+	mglDataA *v = Parse->AddVar(name);
+	mglData *d = dynamic_cast<mglData*>(v);
+	mglDataC *c = dynamic_cast<mglDataC*>(v);
+	if(d)
+	{
+		d->Read(fn);
+		if(d->nz>1)
+			snprintf(res,256,"#read %s '%s'\nrotate 40 60\ncrange %s\nbox\nsurf3 %s\n", name, fn, name, name);
+		else if(d->ny>1)
+			snprintf(res,256,"#read %s '%s'\nrotate 40 60\ncrange %s\nzrange %s\nbox\nsurf %s\n", name, fn, name, name, name);
+		else
+			snprintf(res,256,"#read %s '%s'\nyrange %s\nbox\nplot %s\n", name, fn, name, name);
+		textbuf->text(res);
+	}
+	else if(c)
+	{
+		c->Read(fn);
+		if(c->nz>1)
+			snprintf(res,256,"#read %s '%s'\nrotate 40 60\ncrange %s\nbox\nsurf3 %s\n", name, fn, name, name);
+		else if(c->ny>1)
+			snprintf(res,256,"#read %s '%s'\nrotate 40 60\ncrange %s\nzrange %s\nbox\nsurf %s\n", name, fn, name, name, name);
+		else
+			snprintf(res,256,"#read %s '%s'\nyrange %s\nbox\nplot %s\n", name, fn, name, name);
+		textbuf->text(res);
+	}
+}
+//-----------------------------------------------------------------------------
+int loading = 0;
+void load_file(const char *newfile, int ipos, ScriptWindow *e)
+{
+	long len = strlen(newfile);
+	if(ipos==-1 && (!strcmp(newfile+len-4,".dat") || !strcmp(newfile+len-4,".csv")))
+	{
+		data_file(newfile);
+		filename = newfile;	filename += ".mgl";
+		add_filename(filename.c_str(),e);
+	}
+	else
+	{
+		loading = 1;
+		int insert = (ipos != -1);
+		changed = insert;
+		if(!insert) filename="";
+		long r;
+		if(!insert)	r = textbuf->loadfile(newfile);
+		else r = textbuf->insertfile(newfile, ipos);
+
+		char *t = textbuf->text();
+#ifndef WIN32
+		register size_t i,l=strlen(t);
+		for(i=0;i<l;i++)	if(t[i]=='\r')	t[i]=' ';
+		textbuf->text(t);
+#endif
+		fill_animate(t, e->draw);	free(t);
+
+		if (r)
+			fl_alert(_("Error reading from file \'%s\':\n%s."), newfile, strerror(errno));
+		else	if(!insert)
+		{	filename = newfile;	add_filename(filename.c_str(),e);	}
+		loading = 0;
+		textbuf->call_modify_callbacks();
+	}
+}
+//-----------------------------------------------------------------------------
+void save_file(const char *newfile, ScriptWindow *e)
+{
+	if (textbuf->savefile(newfile))
+		fl_alert(_("Error writing to file \'%s\':\n%s."), newfile, strerror(errno));
+	else
+	{	filename = newfile;	add_filename(filename.c_str(),e);	}
+	changed = 0;
+	textbuf->call_modify_callbacks();
+}
+//-----------------------------------------------------------------------------
+void undo_cb(Fl_Widget*, void* v)
+{
+	ScriptWindow* e = (ScriptWindow*)v;
+	Fl_Text_Editor::kf_undo(0, e->editor);
+}
+//-----------------------------------------------------------------------------
+void select_all_cb(Fl_Widget *, void *v)
+{
+	ScriptWindow* e = (ScriptWindow*)v;
+	Fl_Text_Editor::kf_select_all(0, e->editor);
+}
+//-----------------------------------------------------------------------------
+void copy_cb(Fl_Widget*, void* v)
+{
+	ScriptWindow* e = (ScriptWindow*)v;
+	Fl_Text_Editor::kf_copy(0, e->editor);
+}
+//-----------------------------------------------------------------------------
+void cut_cb(Fl_Widget*, void* v)
+{
+	ScriptWindow* e = (ScriptWindow*)v;
+	Fl_Text_Editor::kf_cut(0, e->editor);
+}
+//-----------------------------------------------------------------------------
+void hide_cb(Fl_Widget*, void* v)
+{
+	ScriptWindow* e = (ScriptWindow*)v;
+	int p1,p2;
+	textbuf->selection_position(&p1, &p2);
+	if(!textbuf->selected())	p2=p1=e->editor->insert_position();
+	p1 = textbuf->line_start(p1);
+	while(p1<p2)
+	{
+		textbuf->insert(p1,"#h ");
+		int p = textbuf->line_start(textbuf->line_end(p1)+1);
+		if(p!=p1)	p1=p;	else	return;
+	}
+}
+//-----------------------------------------------------------------------------
+void unhide_cb(Fl_Widget*, void* v)
+{
+	ScriptWindow* e = (ScriptWindow*)v;
+	int p1,p2;
+	textbuf->selection_position(&p1, &p2);
+	if(!textbuf->selected())	p2=p1=e->editor->insert_position();
+	p1 = textbuf->line_start(p1);
+	while(p1<p2)
+	{
+		if(textbuf->char_at(p1)=='#')
+		{
+			if(textbuf->char_at(p1+1)=='h' && textbuf->char_at(p1+2)==' ')
+				textbuf->remove(p1,p1+3);
+			else	textbuf->remove(p1,p1+1);
+		}
+		int p = textbuf->line_start(textbuf->line_end(p1)+1);
+		if(p!=p1)	p1=p;	else	return;
+	}
+}
+//-----------------------------------------------------------------------------
+void delete_cb(Fl_Widget*, void*) {	textbuf->remove_selection();	}
+//-----------------------------------------------------------------------------
+void cb_descr(Fl_Widget*,void *v)
+{
+	static size_t len=0;
+	ScriptWindow *w = (ScriptWindow*)v;
+	if(!textbuf || !Parse || !w)	return;
+	int cur = w->editor->insert_position(), br=0;
+	int beg = textbuf->line_start(cur);
+	const char *s = textbuf->text();
+	for(int i=beg;i<cur;i++)
+	{
+		if(strchr("({[",s[i]))	br++;
+		if(strchr(")}]",s[i]))	br--;
+		if(br==0 && s[i]==':' && i+1<cur)	beg=i+1;
+	}
+	for(br=beg;s[br]>' ' && s[br]!=':';br++);
+	std::string cmd(s+beg,br-beg);
+	const char *desc = Parse->CmdDesc(cmd.c_str());
+	const char *form = Parse->CmdFormat(cmd.c_str());
+	static std::string txt;
+	txt = desc?std::string(desc)+":  "+form : "";
+	w->set_status(txt.c_str());
+
+	size_t ll = strlen(s);
+	if(complete_word && br==cur+1 && br-beg>2 && len<ll)	// try complete word
+	{
+		long n = Parse->GetCmdNum();
+		std::vector<std::string> vars;
+		for(long i=0;i<n;i++)
+		{
+			const char *c = Parse->GetCmdName(i);
+			if(!strncmp(c,cmd.c_str(),cmd.length()))	vars.push_back(c);
+		}
+		for(size_t i=0;i<vars.size();i++)
+			if(vars[i].length()>cmd.length())
+			{
+				std::string suggest = vars[i].substr(cmd.length());
+				textbuf->insert(cur+1, suggest.c_str());
+				textbuf->select(cur+1, cur+suggest.length()+1);
+				break;
+			}
+	}
+	len = ll;
+}
+//-----------------------------------------------------------------------------
+void ScriptWindow::set_status(const char *txt)
+{	if(txt && status)	{	status->label(txt);	redraw();	}	}
+//-----------------------------------------------------------------------------
+void changed_cb(int pos, int nInserted, int nDeleted, int nRestyled, const char *deletedText, void* v)
+{
+	if ((nInserted || nDeleted) && !loading) changed = 1;
+	ScriptWindow *w = (ScriptWindow *)v;
+	cb_descr(0,v);
+	set_title(w);
+	style_update(pos, nInserted, nDeleted, nRestyled, deletedText, w->editor);
+	if (loading) w->editor->show_insert_position();
+}
+//-----------------------------------------------------------------------------
+void insert_cb(Fl_Widget*, void *v)
+{
+	const char *newfile = mgl_file_chooser(_("Insert file content?"));
+	ScriptWindow *w = (ScriptWindow *)v;
+	if (newfile != NULL) load_file(newfile, w->editor->insert_position(),w);
+}
+//-----------------------------------------------------------------------------
+void paste_cb(Fl_Widget*, void* v)
+{
+	ScriptWindow* e = (ScriptWindow*)v;
+	Fl_Text_Editor::kf_paste(0, e->editor);
+}
+//-----------------------------------------------------------------------------
+#include "../widgets/image.h"
+#include "xpm/box.xpm"
+Fl_Widget *add_editor(ScriptWindow *w)
+{
+	Fl_Window *w1=new Fl_Window(0,30,300,455,0);
+	Fl_Group *g = new Fl_Group(0,0,290,30);
+	Fl_Button *o;
+
+	o = new Fl_Button(0, 1, 25, 25);	o->image(img_load);	o->callback(open_cb,w);
+	o->tooltip(_("Open script or data file"));
+	o = new Fl_Button(25, 1, 25, 25);	o->image(img_save);	o->callback(save_cb,w);
+	o->tooltip(_("Save script to file"));
+
+	o = new Fl_Button(55, 1, 25, 25);	o->image(img_copy);	o->callback(copy_cb,w);
+	o->tooltip(_("Copy selection to clipboard"));
+	o = new Fl_Button(80, 1, 25, 25);	o->image(img_paste);o->callback(paste_cb,w);
+	o->tooltip(_("Paste text from clipboard"));
+	o = new Fl_Button(105, 1, 25, 25);	o->image(img_find);	o->callback(find_dlg_cb,w);
+	o->tooltip(_("Find or replace text"));
+
+	o = new Fl_Button(135, 1, 25, 25);	o->image(img_insert);	o->callback(newcmd_dlg_cb,w);
+	o->tooltip(_("Insert MGL command"));
+	o = new Fl_Button(160, 1, 25, 25);	o->image(img_fname);	o->callback(ins_fname_cb,w);
+	o->tooltip(_("Insert filename"));
+	o = new Fl_Button(185, 1, 25, 25);	o->image(new Fl_Pixmap(box_xpm));	o->callback(inplot_dlg_cb,w);
+	o->tooltip(_("Insert inplot command"));
+
+	o = new Fl_Button(210, 1, 25, 25);	o->image(img_calc);	o->callback(calc_dlg_cb,w);
+	o->tooltip(_("Show calculator window"));
+	o = new Fl_Button(240, 1, 25, 25);	o->image(img_curve);o->callback(prim_dlg_cb,w);
+	o->tooltip(_("Show calculator window"));
+	g->end();	g->resizable(0);
+
+	w->editor = new Fl_Text_Editor(0, 28, 300, 425);
+	w->editor->textfont(FL_COURIER);
+	w->editor->buffer(textbuf);
+	w->editor->highlight_data(stylebuf, styletable, sizeof(styletable) / sizeof(styletable[0]), 'A', style_unfinished_cb, 0);
+#if MGL_HAVE_FL_COPY
+	w->editor->linenumber_width(30);
+#endif
+//	w->editor->when(FL_WHEN_RELEASE_ALWAYS);	w->editor->callback(cb_descr,w);
+
+	textbuf->add_modify_callback(changed_cb, w);
+	textbuf->call_modify_callbacks();
+
+	w1->end();	w1->resizable(w->editor);
+	return w1;
+}
+//-----------------------------------------------------------------------------
+void cp_find_next(Fl_Widget*,void*);
+void cp_repl_next(Fl_Widget*,void*);
+void cp_repl_all(Fl_Widget*,void*);
+class FindDlg : public GeneralDlg
+{
+	Fl_Input *find, *replace;
+	Fl_Check_Button *mcase, *sback;
+public:
+	FindDlg() : GeneralDlg()
+	{
+		Fl_Button* o;
+		w = new Fl_Double_Window(375, 130, _("Find/Replace"));
+		find = new Fl_Input(90, 10, 180, 25, _("Find what:"));
+		o = new Fl_Return_Button(275, 10, 95, 25, _("Find"));	o->callback(cp_find_next);
+		replace = new Fl_Input(90, 40, 180, 25, _("Replace by:"));
+		o = new Fl_Button(275, 40, 95, 25, _("Replace"));		o->callback(cp_repl_next);
+		mcase = new Fl_Check_Button(5, 70, 265, 25, _("Match case"));
+		sback = new Fl_Check_Button(5, 95, 265, 25, _("Search backward"));
+		o = new Fl_Button(275, 70, 95, 25, _("Replace all"));	o->callback(cp_repl_all);
+		o = new Fl_Button(275, 100, 95, 25, _("Close"));	o->callback(cb_dlg_cancel,this);
+		w->end();
+	}
+	const char *to_find()	{	return find->value();	}
+	void find_next()
+	{
+		const char *s = find->value();
+		int c = mcase->value(), b = sback->value();
+		if(s && *s)
+		{
+			int pos = e->editor->insert_position();
+			int found = b ? textbuf->search_backward(pos,s,&pos,c) : textbuf->search_forward(pos,s,&pos,c);
+			if(found)
+			{	// Found a match; select and update the position...
+				size_t len = strlen(s);
+				textbuf->select(pos, pos+len);
+				e->editor->insert_position(pos+len);
+				e->editor->show_insert_position();
+			}
+			else fl_alert(_("No occurrences of \'%s\' found!"), s);
+		}
+	}
+	void repl_next()
+	{
+		const char *s = find->value();
+		const char *r = replace->value();
+		int c = mcase->value(), b = sback->value();
+		if(s && *s)
+		{
+			int pos = e->editor->insert_position();
+			int found = b ? textbuf->search_backward(pos,s,&pos,c) : textbuf->search_forward(pos,s,&pos,c);
+			if(found)
+			{	// Found a match; select and update the position...
+				size_t len = strlen(r);
+				textbuf->select(pos, pos+strlen(s));
+				textbuf->remove_selection();
+				textbuf->insert(pos, r);
+				textbuf->select(pos, pos+len);
+				e->editor->insert_position(pos+len);
+				e->editor->show_insert_position();
+			}
+			else fl_alert(_("No occurrences of \'%s\' found!"), s);
+		}
+	}
+	void repl_all()
+	{
+		const char *s = find->value();
+		const char *r = replace->value();
+		int c = mcase->value(), b = sback->value();
+		int found = (s && *s)?1:0;
+		long num=0;
+		while(found)
+		{
+			int pos = e->editor->insert_position();
+			int found = b ? textbuf->search_backward(pos,s,&pos,c) : textbuf->search_forward(pos,s,&pos,c);
+			if(!found)	break;
+			size_t len = strlen(r);
+			textbuf->select(pos, pos+strlen(s));
+			textbuf->remove_selection();
+			textbuf->insert(pos, r);
+			textbuf->select(pos, pos+len);
+			e->editor->insert_position(pos+len);
+			e->editor->show_insert_position();
+			num++;
+		}
+		if(num) fl_message(_("Replaced %ld occurrences."), num);
+		else fl_alert(_("No occurrences of \'%s\' found!"), s);
+	}
+} find_dlg;
+//-----------------------------------------------------------------------------
+void cp_find_next(Fl_Widget*,void*)	{	find_dlg.find_next();	}
+void cp_repl_next(Fl_Widget*,void*)	{	find_dlg.repl_next();	}
+void cp_repl_all(Fl_Widget*,void*)	{	find_dlg.repl_all();	}
+//-----------------------------------------------------------------------------
+void find_dlg_cb(Fl_Widget*,void *v)
+{	find_dlg.e = (ScriptWindow*)v;	find_dlg.show();	}
+//-----------------------------------------------------------------------------
+void find_next_cb(Fl_Widget*,void *v)
+{
+	find_dlg.e = (ScriptWindow*)v;
+	const char *s = find_dlg.to_find();
+	if(s && *s)	find_dlg.find_next();
+	else	find_dlg.show();
+}
+//-----------------------------------------------------------------------------
+void ins_fname_cb(Fl_Widget *, void *v)
+{
+	static std::string prev;
+	ScriptWindow* e = (ScriptWindow*)v;
+	const char *s = mgl_file_chooser(_("Select file name"), "DAT files \t*.{dat,csv}\nHDF files \t*.{hdf,h5}");
+	if(s)
+	{
+		std::string ss=prev=s;	ss = '\''+ss+'\'';
+		if(e)	e->editor->insert(ss.c_str());
+		else	cb_args_set(ss.c_str());
+	}
+}
+//-----------------------------------------------------------------------------
+void ins_path_cb(Fl_Widget *, void *v)
+{
+	static std::string prev;
+	ScriptWindow* e = (ScriptWindow*)v;
+	const char *s = mgl_dir_chooser(_("Select folder name"), prev.c_str());
+	if(s)
+	{
+		std::string ss=prev=s;	ss = '\''+ss+'\'';
+		if(e)	e->editor->insert(ss.c_str());
+		else	cb_args_set(ss.c_str());
+	}
+}
+//-----------------------------------------------------------------------------
+void ins_fits_cb(Fl_Widget *, void *v)
+{
+	ScriptWindow* e = (ScriptWindow*)v;
+	HMGL gr = e->graph->get_graph();
+	std::string ss=mgl_get_fit(gr);
+	if(ss.empty())	fl_alert(_("There is no fitted formula."));
+	else	{	ss = '\''+ss+'\'';	e->editor->insert(ss.c_str());	}
+}
+//-----------------------------------------------------------------------------
+void ins_prim_cb(Fl_Widget *, void *v)
+{
+	ScriptWindow* e = (ScriptWindow*)v;
+	std::string ss = "subplot 1 1 0 '#'\n"+e->graph->FMGL->prim+"subplot 1 1 0\n###### end of primitives\n";
+	e->editor->insert(ss.c_str());
+	e->graph->FMGL->prim.clear();
+}
+//-----------------------------------------------------------------------------
diff --git a/mgllab/fltk_test.fl b/mgllab/fltk_test.fl
new file mode 100644
index 0000000..a78e3c9
--- /dev/null
+++ b/mgllab/fltk_test.fl
@@ -0,0 +1,2662 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 1.0303 
+i18n_type 1 
+i18n_include <libintl.h> 
+i18n_function gettext 
+header_name {.h} 
+code_name {.cxx}
+decl {\#include <mgllab.h>} {public local
+} 
+
+Function {make_window()} {
+  comment {Main mgllab window}
+} {
+  Fl_Window {} {
+    label mgllab open
+    xywh {6 393 780 375} type Double align 80 hide resizable
+    code0 {load_pref();}
+    code1 {create_common();}
+  } {
+    Fl_Tile {} {open
+      xywh {0 30 740 320} resizable
+    } {
+      Fl_Group {} {open
+        xywh {0 35 260 310}
+      } {
+        Fl_Text_Editor edit {
+          xywh {0 60 260 285} resizable
+        }
+        Fl_Pack {} {open
+          private xywh {0 35 260 25}
+          code0 {o->type(Fl_Pack::HORIZONTAL);}
+        } {
+          Fl_Button open {
+            image {png/document-open.png} xywh {0 35 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/document-save.png} xywh {25 35 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/accessories-calculator.png} xywh {50 35 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/edit-undo.png} xywh {75 35 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/edit-redo.png} xywh {100 35 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/edit-copy.png} xywh {125 35 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/edit-paste.png} xywh {150 35 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/edit-find.png} xywh {175 35 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/document-properties.png} xywh {200 35 25 25} box ENGRAVED_BOX
+          }
+        }
+      }
+      Fl_Group {} {open
+        xywh {260 35 480 315}
+      } {
+        Fl_Pack {} {open
+          private xywh {260 35 480 25}
+          code0 {o->type(Fl_Pack::HORIZONTAL);}
+        } {
+          Fl_Button {} {
+            image {png/alpha.png} xywh {260 35 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/weather-clear.png} xywh {285 35 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/view-grid.png} xywh {310 35 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/transform-move.png} xywh {335 35 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/zoom-original.png} xywh {360 35 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/view-refresh.png} xywh {385 35 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/process-stop.png} xywh {410 35 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/edit-copy.png} xywh {435 35 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/format-indent-more.png} xywh {460 35 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/document-print.png} xywh {485 35 25 25} box ENGRAVED_BOX
+          }
+        }
+        Fl_Pack {} {open
+          private xywh {260 60 25 285}
+          code0 {o->type(Fl_Pack::VERTICAL);}
+        } {
+          Fl_Button {} {
+            image {png/go-previous.png} xywh {260 60 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/go-up.png} xywh {260 85 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/zoom-in.png} xywh {260 110 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/zoom-out.png} xywh {260 135 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/go-down.png} xywh {260 160 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/go-next.png} xywh {260 185 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/arrow-right-double.png} xywh {260 210 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/media-playback-start.png} xywh {260 235 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/arrow-left-double.png} xywh {260 260 25 25} box ENGRAVED_BOX
+          }
+        }
+        Fl_Tabs {} {open
+          xywh {285 60 425 290} align 289 resizable
+        } {
+          Fl_Scroll {} {
+            label Plot open
+            image {png/office-chart-line.png} xywh {285 85 425 265} align 257 hide
+          } {
+            Fl_Box graph {
+              xywh {285 85 425 265} box ENGRAVED_BOX resizable
+              class Fl_MathGL
+            }
+          }
+          Fl_Group {} {
+            label Data open
+            image {png/system-file-manager.png} xywh {285 85 425 260} hide
+          } {}
+          Fl_Group {} {
+            label Info open
+            image {png/dialog-information.png} xywh {285 85 425 260} hide
+          } {}
+          Fl_Group {} {
+            label Help open
+            image {png/help-contents.png} xywh {285 85 425 260} align 289 resizable
+          } {
+            Fl_Help_View {} {
+              xywh {285 110 425 235} resizable
+            }
+          }
+        }
+        Fl_Pack {} {open
+          private xywh {710 60 25 285}
+          code0 {o->type(Fl_Pack::VERTICAL);}
+        } {
+          Fl_Button {} {
+            image {png/edit-delete.png} xywh {710 60 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/object-order-lower.png} xywh {710 85 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/object-order-raise.png} xywh {710 110 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/layer-visible-on.png} xywh {710 135 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/document-new.png} xywh {710 160 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/document-print.png} xywh {710 185 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/edit-clear.png} xywh {710 210 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/list-add.png} xywh {710 235 25 25} box ENGRAVED_BOX
+          }
+          Fl_Button {} {
+            image {png/list-remove.png} xywh {710 260 25 25} box ENGRAVED_BOX
+          }
+        }
+      }
+    }
+    Fl_Menu_Bar menu {open
+      xywh {0 0 680 25} align 288
+    } {
+      Submenu {} {
+        label File
+        xywh {0 0 100 20}
+      } {
+        MenuItem {} {
+          label {New script}
+          xywh {0 0 100 20}
+        }
+        MenuItem {} {
+          label {Open file ...}
+          xywh {0 0 100 20} shortcut 0x4006f
+        }
+        MenuItem {} {
+          label {Save file}
+          xywh {0 0 100 20} shortcut 0x40073
+        }
+        MenuItem {} {
+          label {Save as ...}
+          xywh {0 0 100 20} divider
+        }
+        MenuItem {} {
+          label {Print script}
+          xywh {0 0 100 20}
+        }
+        MenuItem {} {
+          label {Print plot}
+          xywh {0 0 100 20} divider
+        }
+        Submenu {} {
+          label {Recent files} open
+          xywh {0 0 100 20} divider
+        } {
+          MenuItem {} {
+            label {1.}
+            xywh {0 0 100 20}
+          }
+          MenuItem {} {
+            label {2.}
+            xywh {0 0 100 20}
+          }
+          MenuItem {} {
+            label {3.}
+            xywh {0 0 100 20}
+          }
+          MenuItem {} {
+            label {4.}
+            xywh {0 0 100 20}
+          }
+          MenuItem {} {
+            label {5.}
+            xywh {0 0 100 20}
+          }
+        }
+        MenuItem {} {
+          label Exit
+          callback {exit(0);}
+          xywh {0 0 100 20}
+        }
+      }
+      Submenu {} {
+        label Edit
+        xywh {0 0 100 20}
+      } {
+        MenuItem {} {
+          label Undo
+          xywh {0 0 100 20} shortcut 0x4007a
+        }
+        MenuItem {} {
+          label Redo
+          xywh {0 0 100 20} divider
+        }
+        MenuItem {} {
+          label {Cut text}
+          xywh {0 0 100 20} shortcut 0x40078
+        }
+        MenuItem {} {
+          label {Copy text}
+          xywh {0 0 100 20} shortcut 0x40063
+        }
+        MenuItem {} {
+          label {Paste text}
+          xywh {0 0 100 20} shortcut 0x40076
+        }
+        MenuItem {} {
+          label {Select all}
+          xywh {0 0 100 20} shortcut 0x40061 divider
+        }
+        MenuItem {} {
+          label {Find|Replace}
+          xywh {0 0 100 20} shortcut 0x40066
+        }
+        MenuItem {} {
+          label {Find next}
+          xywh {0 0 100 20} shortcut 0xffc0 divider
+        }
+        Submenu {} {
+          label Insert open
+          xywh {0 0 100 20}
+        } {
+          MenuItem {} {
+            label Command
+            xywh {0 0 100 20} shortcut 0x400063
+          }
+          MenuItem {} {
+            label Inplot
+            xywh {0 0 100 20} shortcut 0x400069
+          }
+          MenuItem {} {
+            label {Fitted formula}
+            xywh {0 0 100 20} shortcut 0x400066
+          }
+          MenuItem {} {
+            label {Plot style}
+            xywh {0 0 100 20}
+          }
+          MenuItem {} {
+            label {Option(s)}
+            xywh {0 0 100 20} shortcut 0x40006f
+          }
+          MenuItem {} {
+            label {File path}
+            xywh {0 0 100 20} shortcut 0x400070
+          }
+          MenuItem {} {
+            label {Folder path}
+            xywh {0 0 100 20}
+          }
+          MenuItem {} {
+            label {Numeric value}
+            xywh {0 0 100 20} shortcut 0x40006e
+          }
+        }
+      }
+      Submenu {} {
+        label Plot
+        xywh {0 0 100 20}
+      } {
+        MenuItem {} {
+          label Alpha
+          xywh {0 0 100 20} shortcut 0x40073
+        }
+        MenuItem {} {
+          label Light
+          xywh {0 0 100 20} shortcut 0x4006c
+        }
+        MenuItem {} {
+          label Grid
+          xywh {0 0 100 20} shortcut 0x40067 divider
+        }
+        MenuItem {} {
+          label {Restore size}
+          xywh {0 0 100 20} shortcut 0x40020
+        }
+        MenuItem {} {
+          label {Update plot}
+          xywh {0 0 100 20} shortcut 0xffc2
+        }
+        MenuItem {} {
+          label {Adjust size}
+          xywh {0 0 100 20} shortcut 0xffc3
+        }
+        MenuItem {} {
+          label Stop
+          xywh {0 0 100 20} divider
+        }
+        MenuItem {} {
+          label {Copy image}
+          xywh {0 0 100 20} shortcut 0x50067
+        }
+        MenuItem {} {
+          label {Copy click coor.}
+          xywh {0 0 100 20} divider
+        }
+        Submenu {} {
+          label {Add objects}
+          xywh {5 5 100 20}
+        } {
+          MenuItem {} {
+            label Line
+            xywh {5 5 100 20}
+          }
+          MenuItem {} {
+            label Arc
+            xywh {5 5 100 20}
+          }
+          MenuItem {} {
+            label Curve
+            xywh {5 5 100 20}
+          }
+          MenuItem {} {
+            label Rectangle
+            xywh {5 5 100 20}
+          }
+          MenuItem {} {
+            label Rhombus
+            xywh {5 5 100 20}
+          }
+          MenuItem {} {
+            label Ellipse
+            xywh {5 5 100 20}
+          }
+          MenuItem {} {
+            label Polygon
+            xywh {5 5 100 20}
+          }
+          MenuItem {} {
+            label Marker
+            xywh {5 5 100 20}
+          }
+          MenuItem {} {
+            label Text
+            xywh {5 5 100 20}
+          }
+        }
+        Submenu {} {
+          label Selection
+          xywh {0 0 100 20}
+        } {
+          MenuItem {} {
+            label Hide
+            xywh {0 0 100 20}
+          }
+          MenuItem {} {
+            label Delete
+            xywh {0 0 100 20}
+          }
+          MenuItem {} {
+            label {Move up}
+            xywh {0 0 100 20}
+          }
+          MenuItem {} {
+            label {Move down}
+            xywh {0 0 100 20}
+          }
+          MenuItem {} {
+            label {Show hidden}
+            xywh {0 0 100 20} shortcut 0xffc5
+          }
+        }
+        Submenu {} {
+          label {Export as 2D}
+          xywh {0 0 100 20}
+        } {
+          MenuItem {} {
+            label PNG
+            xywh {0 0 100 20} shortcut 0x80070
+          }
+          MenuItem {} {
+            label {solid PNG}
+            xywh {0 0 100 20} shortcut 0x80066
+          }
+          MenuItem {} {
+            label JPEG
+            xywh {0 0 100 20} shortcut 0x8006a
+          }
+          MenuItem {} {
+            label GIF
+            xywh {0 0 100 20} shortcut 0x80067
+          }
+          MenuItem {} {
+            label BMP
+            xywh {0 0 100 20} shortcut 0x80062
+          }
+          MenuItem {} {
+            label {bitmap EPS}
+            xywh {0 0 100 20}
+          }
+          MenuItem {} {
+            label {vector EPS}
+            xywh {0 0 100 20} shortcut 0x80065
+          }
+          MenuItem {} {
+            label SVG
+            xywh {0 0 100 20} shortcut 0x80073
+          }
+          MenuItem {} {
+            label LaTeX
+            xywh {0 0 100 20} shortcut 0x40073
+          }
+        }
+        Submenu {} {
+          label {Export as 3D}
+          xywh {0 0 100 20}
+        } {
+          MenuItem {} {
+            label {3D PDF}
+            xywh {0 0 100 20} shortcut 0x80064
+          }
+          MenuItem {} {
+            label PRC
+            xywh {0 0 100 20}
+          }
+          MenuItem {} {
+            label OBJ
+            xywh {0 0 100 20} shortcut 0x8006f
+          }
+          MenuItem {} {
+            label STL
+            xywh {0 0 100 20}
+          }
+          MenuItem {} {
+            label XYZ
+            xywh {0 0 100 20}
+          }
+        }
+        Submenu {} {
+          label Transform
+          xywh {0 0 100 20}
+        } {
+          MenuItem {} {
+            label {Move left}
+            xywh {0 0 100 20} shortcut 0x8ff51
+          }
+          MenuItem {} {
+            label {Move up}
+            xywh {0 0 100 20} shortcut 0x8ff52
+          }
+          MenuItem {} {
+            label {Zoom in}
+            xywh {0 0 100 20} shortcut 0x8003d
+          }
+          MenuItem {} {
+            label {Zoom out}
+            xywh {0 0 100 20} shortcut 0x8002d
+          }
+          MenuItem {} {
+            label {Move down}
+            xywh {0 0 100 20} shortcut 0x8ff54
+          }
+          MenuItem {} {
+            label {Move right}
+            xywh {0 0 100 20} shortcut 0x8ff53 divider
+          }
+          MenuItem {} {
+            label {Rotate up}
+            xywh {0 0 100 20} shortcut 0x41ff52
+          }
+          MenuItem {} {
+            label {Rotate down}
+            xywh {0 0 100 20} shortcut 0x9ff54
+          }
+          MenuItem {} {
+            label {Rotate left}
+            xywh {0 0 100 20} shortcut 0x9ff51
+          }
+          MenuItem {} {
+            label {Rotate right}
+            xywh {0 0 100 20} shortcut 0x9ff53
+          }
+        }
+        Submenu {} {
+          label Animation
+          xywh {0 0 100 20}
+        } {
+          MenuItem {} {
+            label {Next slide}
+            xywh {0 0 100 20} shortcut 0x4002e
+          }
+          MenuItem {} {
+            label Slideshow
+            xywh {0 0 100 20} shortcut 0x4ffc2
+          }
+          MenuItem {} {
+            label {Prev. slide}
+            xywh {0 0 100 20} shortcut 0x4002c
+          }
+          MenuItem {} {
+            label {Setup show}
+            xywh {0 0 100 20} shortcut 0x40077
+          }
+        }
+      }
+      Submenu {} {
+        label Setup
+        xywh {0 0 100 20}
+      } {
+        MenuItem {} {
+          label Properties
+          callback {prop_dlg->show();}
+          xywh {0 0 100 20}
+        }
+        MenuItem {} {
+          label {Set arguments}
+          callback {args_dlg->show();}
+          xywh {0 0 100 20}
+        }
+        MenuItem {} {
+          label {Plot setup}
+          xywh {10 10 100 20} shortcut 0x400067 divider
+        }
+        MenuItem {} {
+          label Calculator
+          xywh {0 0 100 20} shortcut 0xffc1
+        }
+        MenuItem {} {
+          label Messages
+          xywh {0 0 100 20} shortcut 0xffbf
+        }
+      }
+      Submenu {} {
+        label Help
+        xywh {0 0 100 20}
+      } {
+        MenuItem {} {
+          label Help
+          xywh {0 0 100 20} shortcut 0xffbe
+        }
+        MenuItem {} {
+          label Hints
+          xywh {0 0 100 20}
+        }
+        MenuItem {} {
+          label About
+          xywh {0 0 100 20}
+        }
+      }
+    }
+    Fl_Output {} {
+      xywh {0 350 680 25}
+    }
+  }
+} 
+
+Function {create_common()} {return_type void
+} {
+  code {make_prop();
+make_args();
+make_find();} {}
+} 
+
+Function {make_args()} {
+  comment {Dialog to set MGL arguments}
+} {
+  Fl_Window args_dlg {
+    label {Set script arguments}
+    xywh {966 713 290 320} type Double hide
+  } {
+    Fl_Input arg1 {
+      label {String for $1}
+      xywh {5 20 135 30} align 5
+    }
+    Fl_Input arg2 {
+      label {String for $2}
+      xywh {150 20 135 30} align 5
+    }
+    Fl_Input arg3 {
+      label {String for $3}
+      xywh {5 75 135 30} align 5
+    }
+    Fl_Input arg4 {
+      label {String for $4}
+      xywh {150 75 135 30} align 5
+    }
+    Fl_Input arg5 {
+      label {String for $5}
+      xywh {5 130 135 30} align 5
+    }
+    Fl_Input arg6 {
+      label {String for $6}
+      xywh {150 130 135 30} align 5
+    }
+    Fl_Input arg7 {
+      label {String for $7}
+      xywh {5 185 135 30} align 5
+    }
+    Fl_Input arg8 {
+      label {String for $8}
+      xywh {150 185 135 30} align 5
+    }
+    Fl_Input arg9 {
+      label {String for $9}
+      xywh {5 240 135 30} align 5
+    }
+    Fl_Input arg0 {
+      label {String for $0}
+      xywh {150 240 135 30} align 5
+    }
+    Fl_Button {} {
+      label Cancel
+      callback {args_dlg->hide();}
+      xywh {60 290 75 25}
+    }
+    Fl_Return_Button {} {
+      label Set
+      callback {parser.AddParam(0,arg0->value());
+parser.AddParam(1,arg1->value());
+parser.AddParam(2,arg2->value());
+parser.AddParam(3,arg3->value());
+parser.AddParam(4,arg4->value());
+parser.AddParam(5,arg5->value());
+parser.AddParam(6,arg6->value());
+parser.AddParam(7,arg7->value());
+parser.AddParam(8,arg8->value());
+parser.AddParam(9,arg9->value());
+args_dlg->hide();}
+      xywh {155 290 75 25}
+    }
+  }
+} 
+
+Function {make_prop()} {
+  comment {Dialog for mgllab properties}
+} {
+  Fl_Window prop_dlg {
+    label Properties
+    xywh {1026 403 340 365} type Double align 80 hide modal
+  } {
+    Fl_Choice fkind {
+      label {Font kind} open
+      xywh {75 10 90 25} down_box BORDER_BOX
+      code0 {fkind->add("Helvetica");}
+      code1 {fkind->add("Courier");}
+      code2 {fkind->add("Times");}
+      code3 {fkind->value(styletable[0].font/4);}
+    } {}
+    Fl_Spinner fsize {
+      label {Font size}
+      xywh {245 10 90 25}
+      code0 {fsize->value(styletable[0].size);}
+    }
+    Fl_File_Input help_path {
+      label {Path for help files}
+      xywh {5 55 305 35} align 5
+      code0 {help_path->value(docdir.c_str());}
+    }
+    Fl_Button {} {
+      label {...}
+      xywh {310 65 25 25}
+    }
+    Fl_File_Input font_path {
+      label {Path for MathGL font (without extension)}
+      xywh {5 110 305 35} align 5
+      code0 {font_path->value(fontname.c_str());}
+    }
+    Fl_Button {} {
+      label {...}
+      xywh {310 120 25 25}
+    }
+    Fl_Check_Button auto_exec_w {
+      label {Execute script after loading}
+      xywh {5 145 330 25} down_box DOWN_BOX
+    }
+    Fl_Check_Button exec_save_w {
+      label {Save file before redrawing}
+      xywh {5 170 330 25} down_box DOWN_BOX
+    }
+    Fl_Check_Button complete_w {
+      label {Enable keywords completition}
+      xywh {5 195 330 25} down_box DOWN_BOX deactivate
+    }
+    Fl_Check_Button highlight_w {
+      label {Highlight current object(s)}
+      xywh {5 220 330 25} down_box DOWN_BOX
+    }
+    Fl_Check_Button mouse_zoom_w {
+      label {Enable mouse wheel for zooming}
+      xywh {5 245 330 25} down_box DOWN_BOX
+    }
+    Fl_Choice lang_w {
+      label {Language for mgllab} open
+      xywh {160 275 175 25} down_box BORDER_BOX
+      code0 {lang_w->add("C.UTF8");}
+      code1 {lang_w->add("ru_RU.utf8");}
+      code2 {lang_w->add("ru_RU.cp1251");}
+    } {}
+    Fl_Choice scheme_w {
+      label {Widget scheme} open
+      xywh {160 305 175 25} down_box BORDER_BOX
+      code0 {scheme_w->add("base");}
+      code1 {scheme_w->add("gtk+");}
+      code2 {scheme_w->add("plastic");}
+      code3 {scheme_w->add("gleam");}
+    } {}
+    Fl_Button {} {
+      label Cancel
+      callback {prop_dlg->hide();}
+      xywh {85 340 75 25}
+    }
+    Fl_Return_Button {} {
+      label OK
+      callback {set_style(fkind->value(),fsize->value());
+auto_exec = auto_exec_w->value();
+exec_save = exec_save_w->value();
+highlight = highlight_w->value();
+mouse_zoom = mouse_zoom_w->value();
+docdir = help_path->value();
+fontname = font_path->value();
+mgl_load_font(graph->get_graph(),fontname.c_str(),NULL);
+set_scheme_lang(scheme_w->value(),lang_w->value());
+save_pref();
+prop_dlg->hide();}
+      xywh {180 340 75 25}
+    }
+  }
+} 
+
+Function {make_calc()} {
+  comment Calculator
+} {
+  Fl_Window {} {
+    label Calculator open
+    xywh {378 341 275 275} type Double hide
+  } {
+    Fl_Input edit {
+      xywh {5 5 240 25}
+    }
+    Fl_Button {} {
+      label {@>}
+      xywh {245 5 25 25}
+    }
+    Fl_Output result {
+      label Result
+      xywh {55 35 120 25}
+    }
+    Fl_Button {} {
+      label {@-> to script}
+      xywh {180 35 90 25}
+    }
+    Fl_Browser prev {
+      label {Previous expressions}
+      xywh {5 80 265 70} align 5
+    }
+    Fl_Group {} {open
+      xywh {5 155 145 120}
+    } {
+      Fl_Button {} {
+        label 7
+        user_data {"7"}
+        xywh {10 160 25 25}
+      }
+      Fl_Button {} {
+        label 8
+        user_data {"8"}
+        xywh {40 160 25 25}
+      }
+      Fl_Button {} {
+        label 9
+        user_data {"9"}
+        xywh {70 160 25 25}
+      }
+      Fl_Button {} {
+        label {+}
+        user_data {"+"}
+        xywh {100 160 25 25}
+      }
+      Fl_Button {} {
+        label pi
+        user_data {"pi"}
+        xywh {130 160 25 25}
+      }
+      Fl_Button {} {
+        label 4
+        user_data {"4"}
+        xywh {10 190 25 25}
+      }
+      Fl_Button {} {
+        label 5
+        user_data {"5"}
+        xywh {40 190 25 25}
+      }
+      Fl_Button {} {
+        label 6
+        user_data {"6"}
+        xywh {70 190 25 25}
+      }
+      Fl_Button {} {
+        label {-}
+        user_data {"-"}
+        xywh {100 190 25 25}
+      }
+      Fl_Button {} {
+        label {^}
+        user_data {"^"}
+        xywh {130 190 25 25}
+      }
+      Fl_Button {} {
+        label 1
+        user_data {"1"}
+        xywh {10 220 25 25}
+      }
+      Fl_Button {} {
+        label 2
+        user_data {"2"}
+        xywh {40 220 25 25}
+      }
+      Fl_Button {} {
+        label 3
+        user_data {"3"}
+        xywh {70 220 25 25}
+      }
+      Fl_Button {} {
+        label {*}
+        user_data {"8"}
+        xywh {100 220 25 25}
+      }
+      Fl_Button {} {
+        label {(}
+        user_data {"("}
+        xywh {130 220 25 25}
+      }
+      Fl_Button {} {
+        label 0
+        user_data {"0"}
+        xywh {10 250 25 25}
+      }
+      Fl_Button {} {
+        label {.}
+        user_data {"."}
+        xywh {40 250 25 25}
+      }
+      Fl_Button {} {
+        label E
+        xywh {70 250 25 25}
+      }
+      Fl_Button {} {
+        label {/}
+        user_data {"/"}
+        xywh {100 250 25 25}
+      }
+      Fl_Button {} {
+        label {)}
+        user_data {")"}
+        xywh {130 250 25 25}
+      }
+    }
+    Fl_Group {} {
+      label Function open
+      xywh {155 174 115 95} box DOWN_BOX
+    } {
+      Fl_Choice kind {open
+        xywh {160 179 105 25} down_box BORDER_BOX
+      } {}
+      Fl_Choice func {open
+        xywh {160 209 105 25} down_box BORDER_BOX
+      } {}
+      Fl_Button {} {
+        label {Put function}
+        xywh {160 239 105 25}
+      }
+    }
+  }
+} 
+
+Function {make_option()} {} {
+  Fl_Window {} {
+    label {Add command option(s)}
+    xywh {336 575 570 185} type Double hide modal
+  } {
+    Fl_Input x1 {
+      label {X-range}
+      xywh {65 5 85 25}
+    }
+    Fl_Input x2 {
+      label {-}
+      xywh {160 5 85 25}
+    }
+    Fl_Input y1 {
+      label {Y-range}
+      xywh {65 35 85 25}
+    }
+    Fl_Input y2 {
+      label {-}
+      xywh {160 35 85 25}
+    }
+    Fl_Input z1 {
+      label {Z-range}
+      xywh {65 65 85 25}
+    }
+    Fl_Input z2 {
+      label {-}
+      xywh {160 65 85 25}
+    }
+    Fl_Input c1 {
+      label {C-range}
+      xywh {65 95 85 25} deactivate
+    }
+    Fl_Input c2 {
+      label {-}
+      xywh {160 95 85 25} deactivate
+    }
+    Fl_Input val {
+      label Value
+      xywh {325 5 85 25} labelfont 1
+    }
+    Fl_Input meshnum {
+      label MeshNum
+      xywh {325 35 85 25}
+    }
+    Fl_Input size {
+      label Size
+      xywh {325 65 85 25}
+    }
+    Fl_Choice cut {
+      label Cutting open
+      xywh {325 95 85 25} down_box BORDER_BOX
+      code0 {cut->add("default");}
+      code1 {cut->add("on");}
+      code2 {cut->add("off");}
+    } {}
+    Fl_Input alpha {
+      label Alpha
+      xywh {480 5 85 25}
+    }
+    Fl_Input amb {
+      label Ambient
+      xywh {480 35 85 25}
+    }
+    Fl_Input dif {
+      label Diffuse
+      xywh {480 65 85 25}
+    }
+    Fl_Choice light {
+      label Light open
+      xywh {480 95 85 25} down_box BORDER_BOX
+      code0 {light->add("default");}
+      code1 {light->add("on");}
+      code2 {light->add("off");}
+    } {}
+    Fl_Input legend {
+      label Legend
+      xywh {65 125 500 25}
+    }
+    Fl_Button {} {
+      label Cancel
+      xywh {385 155 85 25}
+    }
+    Fl_Return_Button {} {
+      label OK
+      xywh {480 155 85 25}
+    }
+  }
+} 
+
+Function {make_dirsel()} {} {
+  Fl_Window {} {
+    label {Select direction}
+    xywh {454 309 220 85} type Double hide modal
+  } {
+    Fl_Choice dir {
+      label Direction open
+      xywh {80 10 135 25} down_box BORDER_BOX
+      code0 {dir->add("default"); dir->add("xyz");}
+      code1 {dir->add("x"); dir->add("y"); dir->add("z");}
+      code2 {dir->add("xy"); dir->add("xz"); dir->add("yz");}
+    } {}
+    Fl_Button {} {
+      label Cancel
+      xywh {55 50 75 25}
+    }
+    Fl_Return_Button {} {
+      label OK
+      xywh {140 50 75 25}
+    }
+  }
+} 
+
+Function {make_datsel()} {} {
+  Fl_Window {} {
+    label {Select data argument}
+    xywh {440 689 355 255} type Double hide modal
+  } {
+    Fl_Choice name {
+      label {Data name} open
+      xywh {105 5 145 25} down_box BORDER_BOX
+    } {}
+    Fl_Choice oper {
+      label Operation open
+      xywh {105 155 130 25} down_box BORDER_BOX
+      code0 {oper->add("max"); oper->add("min");}
+      code1 {oper->add("sum"); oper->add("trace");}
+      code2 {oper->add("pulse");}
+    } {}
+    Fl_Choice dir {
+      label along open
+      xywh {285 155 65 25} down_box BORDER_BOX
+      code0 {dir->add("none");}
+      code1 {dir->add("x"); dir->add("y"); dir->add("z");}
+      code2 {dir->add("xy"); dir->add("xz"); dir->add("yz");}
+    } {}
+    Fl_Spinner x1 {
+      label {X-slice from}
+      xywh {105 35 60 25}
+    }
+    Fl_Spinner x2 {
+      label to
+      xywh {190 35 60 25}
+    }
+    Fl_Spinner y1 {
+      label {Y-slice from}
+      xywh {105 65 60 25}
+    }
+    Fl_Spinner y2 {
+      label to
+      xywh {190 65 60 25}
+    }
+    Fl_Spinner z1 {
+      label {Z-slice from}
+      xywh {105 95 60 25}
+    }
+    Fl_Spinner z2 {
+      label to
+      xywh {190 95 60 25}
+    }
+    Fl_Output res {
+      label Result
+      xywh {60 190 290 25}
+    }
+    Fl_Button {} {
+      label Cancel
+      xywh {190 225 75 25}
+    }
+    Fl_Return_Button {} {
+      label OK
+      xywh {275 225 75 25}
+    }
+    Fl_Input clmn {
+      label {Column expr}
+      xywh {105 125 245 25}
+    }
+  }
+} 
+
+Function {make_newcmd()} {} {
+  Fl_Window {} {
+    label {New command}
+    xywh {985 165 780 515} type Double hide modal
+  } {
+    Fl_Choice kind {
+      label Kind open
+      xywh {80 5 270 25} down_box BORDER_BOX
+    } {}
+    Fl_Choice cmd {
+      label Command open
+      xywh {80 35 270 25} down_box BORDER_BOX
+    } {}
+    Fl_Choice var {
+      label Variant open
+      xywh {80 95 270 25} down_box BORDER_BOX
+    } {}
+    Fl_Group desc {
+      label Description open
+      xywh {5 65 345 25} box ENGRAVED_BOX labelsize 12 align 0
+    } {}
+    Fl_Browser args {
+      label Arguments
+      xywh {5 140 345 115} align 5
+    }
+    Fl_Output res {
+      label Result
+      xywh {60 295 290 25}
+    }
+    Fl_Input {} {
+      label Options
+      xywh {60 265 265 25}
+    }
+    Fl_Button {} {
+      label {...}
+      xywh {325 265 25 25}
+    }
+    Fl_Button {} {
+      label Cancel
+      xywh {275 450 75 25}
+    }
+    Fl_Return_Button {} {
+      label OK
+      xywh {275 480 75 25}
+    }
+    Fl_Help_View help {
+      xywh {360 5 415 505} labelsize 12
+    }
+    Fl_Box gr {
+      xywh {10 330 240 180} box ENGRAVED_BOX
+    }
+    Fl_Check_Button {} {
+      label Preview
+      xywh {260 330 79 25} down_box DOWN_BOX
+    }
+  }
+} 
+
+Function {make_style()} {} {
+  Fl_Window {} {
+    label {Plot style} open
+    xywh {322 168 380 540} type Double hide
+  } {
+    Fl_Tabs {} {open
+      xywh {0 5 375 235}
+    } {
+      Fl_Group {} {
+        label {Line style} open
+        xywh {0 30 375 210} hide
+      } {
+        Fl_Choice arr1 {
+          label {Arrow at start} open
+          xywh {5 50 110 25} down_box BORDER_BOX align 5
+        } {}
+        Fl_Choice dash {
+          label Dashing open
+          xywh {125 50 110 25} down_box BORDER_BOX align 5
+        } {}
+        Fl_Choice arr2 {
+          label {Arrow at end} open
+          xywh {245 50 110 25} down_box BORDER_BOX align 5
+        } {}
+        Fl_Choice mark {
+          label Marks open
+          xywh {125 80 110 25} down_box BORDER_BOX
+        } {}
+        Fl_Check_Button solid {
+          label solid
+          xywh {240 80 55 25} down_box DOWN_BOX
+        }
+        Fl_Check_Button user {
+          label user
+          xywh {300 80 55 25} down_box DOWN_BOX
+        }
+        Fl_Spinner width {
+          label Width
+          xywh {125 110 110 25}
+          code0 {o->bounds(1,9); o->value(1);}
+        }
+        Fl_Button {} {
+          label {Manual dashing}
+          xywh {10 210 20 20} align 5
+        }
+        Fl_Button {} {
+          xywh {30 210 20 20}
+        }
+        Fl_Button {} {
+          xywh {50 210 20 20}
+        }
+        Fl_Button {} {
+          xywh {70 210 20 20}
+        }
+        Fl_Button {} {
+          xywh {90 210 20 20}
+        }
+        Fl_Button {} {
+          xywh {110 210 20 20}
+        }
+        Fl_Button {} {
+          xywh {130 210 20 20}
+        }
+        Fl_Button {} {
+          xywh {150 210 20 20}
+        }
+        Fl_Button {} {
+          xywh {170 210 20 20}
+        }
+        Fl_Button {} {
+          xywh {190 210 20 20}
+        }
+        Fl_Button {} {
+          xywh {210 210 20 20}
+        }
+        Fl_Button {} {
+          xywh {230 210 20 20}
+        }
+        Fl_Button {} {
+          xywh {250 210 20 20}
+        }
+        Fl_Button {} {
+          xywh {270 210 20 20}
+        }
+        Fl_Button {} {
+          xywh {290 210 20 20}
+        }
+        Fl_Button {} {
+          xywh {310 210 20 20}
+        }
+      }
+      Fl_Group {} {
+        label {Color scheme} open
+        xywh {0 30 375 210}
+      } {
+        Fl_Choice axial {
+          label {Axial direction} open
+          xywh {5 50 110 25} down_box BORDER_BOX align 5
+          code0 {axial->add("none");}
+          code1 {axial->add("x");}
+          code2 {axial->add("y");}
+          code3 {axial->add("z");}
+        } {}
+        Fl_Choice contt {
+          label {Text on contours} open
+          xywh {125 50 110 25} down_box BORDER_BOX align 5
+          code0 {contt->add("none");}
+          code1 {contt->add("under");}
+          code2 {contt->add("above");}
+        } {}
+        Fl_Input alpha {
+          label Transparency
+          xywh {255 50 110 25} align 5
+        }
+        Fl_Check_Button wire {
+          label {Wire or mesh}
+          xywh {125 80 115 25} down_box DOWN_BOX
+        }
+        Fl_Check_Button sharp {
+          label {Sharp colors}
+          xywh {250 80 110 25} down_box DOWN_BOX
+        }
+        Fl_Group {} {
+          label Mask open
+          xywh {10 105 360 130} box ENGRAVED_BOX align 5
+        } {
+          Fl_Choice mask {
+            label Kind open
+            xywh {80 110 95 25} down_box BORDER_BOX
+          } {}
+          Fl_Choice angle {
+            label Rotation open
+            xywh {80 140 95 25} down_box BORDER_BOX
+            code0 {angle->add("none");}
+            code1 {angle->add("+45");}
+            code2 {angle->add("perp");}
+            code3 {angle->add("-45");}
+          } {}
+          Fl_Spinner msize {
+            label Size
+            xywh {80 170 95 25}
+          }
+          Fl_Button {} {
+            xywh {240 110 15 15}
+          }
+          Fl_Button {} {
+            xywh {255 110 15 15}
+          }
+          Fl_Button {} {
+            xywh {270 110 15 15}
+          }
+          Fl_Button {} {
+            xywh {285 110 15 15}
+          }
+          Fl_Button {} {
+            xywh {300 110 15 15}
+          }
+          Fl_Button {} {
+            xywh {315 110 15 15}
+          }
+          Fl_Button {} {
+            xywh {330 110 15 15}
+          }
+          Fl_Button {} {
+            xywh {345 110 15 15}
+          }
+          Fl_Button {} {
+            xywh {240 125 15 15}
+          }
+          Fl_Button {} {
+            xywh {255 125 15 15}
+          }
+          Fl_Button {} {
+            xywh {270 125 15 15}
+          }
+          Fl_Button {} {
+            xywh {285 125 15 15}
+          }
+          Fl_Button {} {
+            xywh {300 125 15 15}
+          }
+          Fl_Button {} {
+            xywh {315 125 15 15}
+          }
+          Fl_Button {} {
+            xywh {330 125 15 15}
+          }
+          Fl_Button {} {
+            xywh {345 125 15 15}
+          }
+          Fl_Button {} {
+            xywh {240 140 15 15}
+          }
+          Fl_Button {} {
+            xywh {255 140 15 15}
+          }
+          Fl_Button {} {
+            xywh {270 140 15 15}
+          }
+          Fl_Button {} {
+            xywh {285 140 15 15}
+          }
+          Fl_Button {} {
+            xywh {300 140 15 15}
+          }
+          Fl_Button {} {
+            xywh {315 140 15 15}
+          }
+          Fl_Button {} {
+            xywh {330 140 15 15}
+          }
+          Fl_Button {} {
+            xywh {345 140 15 15}
+          }
+          Fl_Button {} {
+            xywh {240 155 15 15}
+          }
+          Fl_Button {} {
+            xywh {255 155 15 15}
+          }
+          Fl_Button {} {
+            xywh {270 155 15 15}
+          }
+          Fl_Button {} {
+            xywh {285 155 15 15}
+          }
+          Fl_Button {} {
+            xywh {300 155 15 15}
+          }
+          Fl_Button {} {
+            xywh {315 155 15 15}
+          }
+          Fl_Button {} {
+            xywh {330 155 15 15}
+          }
+          Fl_Button {} {
+            xywh {345 155 15 15}
+          }
+          Fl_Button {} {
+            xywh {240 170 15 15}
+          }
+          Fl_Button {} {
+            xywh {255 170 15 15}
+          }
+          Fl_Button {} {
+            xywh {270 170 15 15}
+          }
+          Fl_Button {} {
+            xywh {285 170 15 15}
+          }
+          Fl_Button {} {
+            xywh {300 170 15 15}
+          }
+          Fl_Button {} {
+            xywh {315 170 15 15}
+          }
+          Fl_Button {} {
+            xywh {330 170 15 15}
+          }
+          Fl_Button {} {
+            xywh {345 170 15 15}
+          }
+          Fl_Button {} {
+            xywh {240 185 15 15}
+          }
+          Fl_Button {} {
+            xywh {255 185 15 15}
+          }
+          Fl_Button {} {
+            xywh {270 185 15 15}
+          }
+          Fl_Button {} {
+            xywh {285 185 15 15}
+          }
+          Fl_Button {} {
+            xywh {300 185 15 15}
+          }
+          Fl_Button {} {
+            xywh {315 185 15 15}
+          }
+          Fl_Button {} {
+            xywh {330 185 15 15}
+          }
+          Fl_Button {} {
+            xywh {345 185 15 15}
+          }
+          Fl_Button {} {
+            xywh {240 200 15 15}
+          }
+          Fl_Button {} {
+            xywh {255 200 15 15}
+          }
+          Fl_Button {} {
+            xywh {270 200 15 15}
+          }
+          Fl_Button {} {
+            xywh {285 200 15 15}
+          }
+          Fl_Button {} {
+            xywh {300 200 15 15}
+          }
+          Fl_Button {} {
+            xywh {315 200 15 15}
+          }
+          Fl_Button {} {
+            xywh {330 200 15 15}
+          }
+          Fl_Button {} {
+            xywh {345 200 15 15}
+          }
+          Fl_Button {} {
+            label {Manual mask}
+            xywh {240 215 15 15} align 4
+          }
+          Fl_Button {} {
+            xywh {255 215 15 15}
+          }
+          Fl_Button {} {
+            xywh {270 215 15 15}
+          }
+          Fl_Button {} {
+            xywh {285 215 15 15}
+          }
+          Fl_Button {} {
+            xywh {300 215 15 15}
+          }
+          Fl_Button {} {
+            xywh {315 215 15 15}
+          }
+          Fl_Button {} {
+            xywh {330 215 15 15}
+          }
+          Fl_Button {} {
+            xywh {345 215 15 15}
+          }
+        }
+      }
+      Fl_Group {} {
+        label {Text style}
+        xywh {0 30 375 210} hide
+      } {
+        Fl_Check_Button bold {
+          label {Bold style}
+          xywh {5 40 150 25} down_box DOWN_BOX
+        }
+        Fl_Check_Button ital {
+          label {Italic style}
+          xywh {5 65 150 25} down_box DOWN_BOX
+        }
+        Fl_Check_Button twire {
+          label {Wire style}
+          xywh {5 90 150 25} down_box DOWN_BOX
+        }
+        Fl_Check_Button uline {
+          label Underline
+          xywh {5 115 150 25} down_box DOWN_BOX
+        }
+        Fl_Check_Button oline {
+          label Overline
+          xywh {5 140 150 25} down_box DOWN_BOX
+        }
+        Fl_Choice align {
+          label {Text align} open
+          xywh {270 40 95 25} down_box BORDER_BOX
+          code0 {align->add("left");}
+          code1 {align->add("center");}
+          code2 {align->add("right");}
+          code3 {align->value(1);}
+        } {}
+        Fl_Choice align {
+          label {Vertical align} open
+          xywh {270 75 95 25} down_box BORDER_BOX
+          code0 {align->add("default");}
+          code1 {align->add("center");}
+          code2 {align->add("right");}
+        } {}
+      }
+    }
+    Fl_Group {} {
+      label {Color(s) or color scheme} open
+      xywh {0 265 375 155} box ENGRAVED_BOX align 5
+    } {
+      Fl_Choice sch {
+        label {Popular color schemes} open
+        xywh {170 270 115 25} down_box BORDER_BOX
+      } {}
+      Fl_Choice c1 {open
+        xywh {5 300 95 25} down_box BORDER_BOX align 5
+      } {}
+      Fl_Spinner s1 {
+        xywh {105 300 40 25} align 1
+        code0 {o->bounds(1,9); o->value(5);}
+      }
+      Fl_Input p1 {
+        xywh {145 300 40 25}
+      }
+      Fl_Choice c2 {open
+        xywh {190 300 95 25} down_box BORDER_BOX
+      } {}
+      Fl_Spinner s2 {
+        xywh {290 300 40 25}
+        code0 {o->bounds(1,9); o->value(5);}
+      }
+      Fl_Input p2 {
+        xywh {330 300 40 25}
+      }
+      Fl_Choice c3 {open
+        xywh {5 330 95 25} down_box BORDER_BOX
+      } {}
+      Fl_Spinner s3 {
+        xywh {105 330 40 25}
+        code0 {o->bounds(1,9); o->value(5);}
+      }
+      Fl_Input p3 {
+        xywh {145 330 40 25}
+      }
+      Fl_Choice c4 {open
+        xywh {190 330 95 25} down_box BORDER_BOX
+      } {}
+      Fl_Input p4 {
+        xywh {330 330 40 25}
+      }
+      Fl_Spinner s4 {
+        xywh {290 330 40 25}
+        code0 {o->bounds(1,9); o->value(5);}
+      }
+      Fl_Choice c5 {open
+        xywh {5 360 95 25} down_box BORDER_BOX
+      } {}
+      Fl_Spinner s5 {
+        xywh {105 360 40 25}
+        code0 {o->bounds(1,9); o->value(5);}
+      }
+      Fl_Input p5 {
+        xywh {145 360 40 25}
+      }
+      Fl_Choice c6 {open
+        xywh {190 360 95 25} down_box BORDER_BOX
+      } {}
+      Fl_Spinner s6 {
+        xywh {290 360 40 25}
+        code0 {o->bounds(1,9); o->value(5);}
+      }
+      Fl_Input p6 {
+        xywh {330 360 40 25}
+      }
+      Fl_Choice c7 {open
+        xywh {5 390 95 25} down_box BORDER_BOX
+      } {}
+      Fl_Spinner s7 {
+        xywh {105 390 40 25}
+        code0 {o->bounds(1,9); o->value(5);}
+      }
+      Fl_Input p7 {
+        xywh {145 390 40 25}
+      }
+      Fl_Choice c8 {open
+        xywh {190 390 95 25} down_box BORDER_BOX
+      } {}
+      Fl_Spinner s8 {
+        xywh {290 390 40 25}
+        code0 {o->bounds(1,9); o->value(5);}
+      }
+      Fl_Input p8 {
+        xywh {330 390 40 25}
+      }
+      Fl_Check_Button sharp {
+        label plain
+        xywh {290 270 80 25} down_box DOWN_BOX
+      }
+    }
+    Fl_Output {} {
+      label {Resulting string}
+      xywh {5 440 370 25} align 5
+    }
+    Fl_Button {} {
+      label Cancel
+      xywh {300 475 75 25}
+    }
+    Fl_Return_Button {} {
+      label OK
+      xywh {300 505 75 25}
+    }
+    Fl_Box {} {
+      xywh {5 470 285 65} box ENGRAVED_BOX align 4
+    }
+  }
+} 
+
+Function {make_setup()} {} {
+  Fl_Window {} {
+    label {Setup script}
+    xywh {838 369 525 395} type Double hide
+  } {
+    Fl_Tabs {} {open
+      xywh {0 0 525 355}
+    } {
+      Fl_Group {} {
+        label {Axis settings} open
+        xywh {0 25 525 330} hide
+      } {
+        Fl_Input x1 {
+          label Minimal
+          xywh {85 55 100 25}
+        }
+        Fl_Box {} {
+          label {X axis}
+          xywh {85 30 100 25}
+        }
+        Fl_Input x2 {
+          label Maximal
+          xywh {85 85 100 25}
+        }
+        Fl_Input x0 {
+          label Origin
+          xywh {85 115 100 25}
+        }
+        Fl_Input xlabel {
+          label Label
+          xywh {85 145 100 25}
+        }
+        Fl_Input xtick {
+          label Ticks
+          xywh {85 205 100 25}
+        }
+        Fl_Choice xlpos {
+          label {at position} open
+          xywh {85 175 100 25} down_box BORDER_BOX
+        } {}
+        Fl_Input xstick {
+          label Subticks
+          xywh {85 235 100 25}
+        }
+        Fl_Input xotick {
+          label {Ticks start}
+          xywh {85 265 100 25}
+        }
+        Fl_Input xtmpl {
+          label Template
+          xywh {85 295 100 25}
+        }
+        Fl_Input y1 {
+          xywh {195 55 100 25}
+        }
+        Fl_Box {} {
+          label {Y axis}
+          xywh {195 30 100 25}
+        }
+        Fl_Input y2 {
+          xywh {195 85 100 25}
+        }
+        Fl_Input y0 {
+          xywh {195 115 100 25}
+        }
+        Fl_Input ylabel {
+          xywh {195 145 100 25}
+        }
+        Fl_Input ytick {
+          xywh {195 205 100 25}
+        }
+        Fl_Choice ylpos {open
+          xywh {195 175 100 25} down_box BORDER_BOX
+        } {}
+        Fl_Input ystick {
+          xywh {195 235 100 25}
+        }
+        Fl_Input yotick {
+          xywh {195 265 100 25}
+        }
+        Fl_Input ytmpl {
+          xywh {195 295 100 25}
+        }
+        Fl_Input z1 {
+          xywh {305 55 100 25}
+        }
+        Fl_Box {} {
+          label {Z axis}
+          xywh {305 30 100 25}
+        }
+        Fl_Input z2 {
+          xywh {305 85 100 25}
+        }
+        Fl_Input z0 {
+          xywh {305 115 100 25}
+        }
+        Fl_Input zlabel {
+          xywh {305 145 100 25}
+        }
+        Fl_Input ztick {
+          xywh {305 205 100 25}
+        }
+        Fl_Choice zlpos {open
+          xywh {305 175 100 25} down_box BORDER_BOX
+        } {}
+        Fl_Input zstick {
+          xywh {305 235 100 25}
+        }
+        Fl_Input zotick {
+          xywh {305 265 100 25}
+        }
+        Fl_Input ztmpl {
+          xywh {305 295 100 25}
+        }
+        Fl_Input ctmpl {
+          xywh {415 295 100 25}
+        }
+        Fl_Input c0 {
+          xywh {415 115 100 25}
+        }
+        Fl_Input clabel {
+          xywh {415 145 100 25}
+        }
+        Fl_Choice clpos {open
+          xywh {415 175 100 25} down_box BORDER_BOX
+        } {}
+        Fl_Input c1 {
+          xywh {415 55 100 25}
+        }
+        Fl_Box {} {
+          label {C axis}
+          xywh {415 30 100 25}
+        }
+        Fl_Input c2 {
+          xywh {415 85 100 25}
+        }
+        Fl_Input xtmpl {
+          label Template
+          xywh {85 325 100 25}
+        }
+        Fl_Input ytmpl {
+          xywh {195 325 100 25}
+        }
+        Fl_Input ztmpl {
+          xywh {305 325 100 25}
+        }
+        Fl_Input ctmpl {
+          xywh {415 325 100 25}
+        }
+      }
+      Fl_Group {} {
+        label {General settings} open
+        xywh {0 25 525 330}
+      } {
+        Fl_Group {} {
+          label Colors open
+          xywh {5 45 180 305} box ENGRAVED_BOX
+        } {
+          Fl_Input alphadef {
+            label AlphaDef
+            xywh {80 55 100 25}
+          }
+          Fl_Input ambient {
+            label Ambient
+            xywh {80 85 100 25}
+          }
+          Fl_Input diffuse {
+            label Diffuse
+            xywh {80 115 100 25}
+          }
+          Fl_Input palette {
+            label Palette
+            xywh {80 145 100 25}
+          }
+          Fl_Input font_stl {
+            label Font
+            xywh {80 175 100 25}
+          }
+          Fl_Input axis_stl {
+            label Axis
+            xywh {80 205 100 25}
+          }
+          Fl_Input fog {
+            label Fog
+            xywh {80 235 100 25}
+          }
+          Fl_Input fog_dz {
+            label {Fog dist.}
+            xywh {80 265 100 25}
+          }
+          Fl_Check_Button gray {
+            label grayscale
+            xywh {80 290 100 25} down_box DOWN_BOX
+          }
+          Fl_Check_Button alpha {
+            label alpha
+            xywh {10 315 64 25} down_box DOWN_BOX
+          }
+          Fl_Check_Button light {
+            label lighting
+            xywh {80 315 100 25} down_box DOWN_BOX
+          }
+        }
+        Fl_Group {} {
+          label Sizes open
+          xywh {185 45 180 250} box ENGRAVED_BOX
+        } {
+          Fl_Input meshnum {
+            label meshnum
+            xywh {260 55 100 25}
+          }
+          Fl_Input arr_size {
+            label arrows
+            xywh {260 85 100 25}
+          }
+          Fl_Input bar_size {
+            label bars
+            xywh {260 115 100 25}
+          }
+          Fl_Input mrk_size {
+            label markers
+            xywh {260 145 100 25}
+          }
+          Fl_Input txt_size {
+            label text
+            xywh {260 175 100 25}
+          }
+          Fl_Input tick_size {
+            label ticks
+            xywh {260 205 100 25}
+          }
+          Fl_Input pendelta {
+            label {pen blur}
+            xywh {260 235 100 25}
+          }
+          Fl_Input facenum {
+            label facenum
+            xywh {260 265 100 25}
+          }
+        }
+        Fl_Group {} {
+          label Others open
+          xywh {365 45 160 305} box ENGRAVED_BOX
+        } {
+          Fl_Check_Button cut {
+            label cutting
+            xywh {370 50 115 25} down_box DOWN_BOX
+          }
+          Fl_Check_Button attach {
+            label {attach light}
+            xywh {370 70 115 25} down_box DOWN_BOX
+          }
+          Fl_Check_Button origintick {
+            label {no origin tick}
+            xywh {370 90 115 25} down_box DOWN_BOX
+          }
+          Fl_Check_Button rotatetext {
+            label {rotate text}
+            xywh {370 110 115 25} down_box DOWN_BOX
+          }
+          Fl_Choice time {
+            label {Time ticks} open
+            xywh {370 150 145 25} down_box BORDER_BOX align 5
+          } {}
+          Fl_Choice tunetick {
+            label {Tune ticks} open
+            xywh {370 195 145 25} down_box BORDER_BOX align 5
+          } {}
+          Fl_Choice ternary {
+            label Ternary open
+            xywh {370 235 145 25} down_box BORDER_BOX align 5
+          } {}
+          Fl_Choice transptype {
+            label {Transparency type} open
+            xywh {370 277 145 25} down_box BORDER_BOX align 5
+          } {}
+          Fl_Spinner variant {
+            label Variant
+            xywh {372 321 145 25} align 5
+          }
+        }
+        Fl_Input plotid {
+          label {Plot ID}
+          xywh {190 321 172 25} align 5
+        }
+      }
+      Fl_Group {} {
+        label {Light settings}
+        xywh {0 25 525 330} hide
+      } {
+        Fl_Button {} {
+          label {0:}
+          xywh {10 50 25 25}
+        }
+        Fl_Input {} {
+          label {X position}
+          xywh {40 50 90 25} align 5
+        }
+        Fl_Input {} {
+          label {Y position}
+          xywh {135 50 90 25} align 5
+        }
+        Fl_Input {} {
+          label {Z position}
+          xywh {230 50 90 25} align 5
+        }
+        Fl_Choice c1 {
+          label Color open
+          xywh {325 50 95 25} down_box BORDER_BOX align 5
+        } {}
+        Fl_Input {} {
+          label Brightness
+          xywh {425 50 90 25} align 5
+        }
+        Fl_Button {} {
+          label {1:}
+          xywh {10 80 25 25}
+        }
+        Fl_Input {} {
+          xywh {40 80 90 25} align 5
+        }
+        Fl_Input {} {
+          xywh {135 80 90 25} align 5
+        }
+        Fl_Input {} {
+          xywh {230 80 90 25} align 5
+        }
+        Fl_Choice c1 {open
+          xywh {325 80 95 25} down_box BORDER_BOX align 5
+        } {}
+        Fl_Input {} {
+          xywh {425 80 90 25} align 5
+        }
+        Fl_Button {} {
+          label {2:}
+          xywh {10 110 25 25}
+        }
+        Fl_Input {} {
+          xywh {40 110 90 25} align 5
+        }
+        Fl_Input {} {
+          xywh {135 110 90 25} align 5
+        }
+        Fl_Input {} {
+          xywh {230 110 90 25} align 5
+        }
+        Fl_Choice c1 {open
+          xywh {325 110 95 25} down_box BORDER_BOX align 5
+        } {}
+        Fl_Input {} {
+          xywh {425 110 90 25} align 5
+        }
+        Fl_Button {} {
+          label {3:}
+          xywh {10 140 25 25}
+        }
+        Fl_Input {} {
+          xywh {40 140 90 25} align 5
+        }
+        Fl_Input {} {
+          xywh {135 140 90 25} align 5
+        }
+        Fl_Input {} {
+          xywh {230 140 90 25} align 5
+        }
+        Fl_Choice c1 {open
+          xywh {325 140 95 25} down_box BORDER_BOX align 5
+        } {}
+        Fl_Input {} {
+          xywh {425 140 90 25} align 5
+        }
+        Fl_Button {} {
+          label {4:}
+          xywh {10 170 25 25}
+        }
+        Fl_Input {} {
+          xywh {40 170 90 25} align 5
+        }
+        Fl_Input {} {
+          xywh {135 170 90 25} align 5
+        }
+        Fl_Input {} {
+          xywh {230 170 90 25} align 5
+        }
+        Fl_Choice c1 {open
+          xywh {325 170 95 25} down_box BORDER_BOX align 5
+        } {}
+        Fl_Input {} {
+          xywh {425 170 90 25} align 5
+        }
+        Fl_Button {} {
+          label {5:}
+          xywh {10 200 25 25}
+        }
+        Fl_Input {} {
+          xywh {40 200 90 25} align 5
+        }
+        Fl_Input {} {
+          xywh {135 200 90 25} align 5
+        }
+        Fl_Input {} {
+          xywh {230 200 90 25} align 5
+        }
+        Fl_Choice c1 {open
+          xywh {325 200 95 25} down_box BORDER_BOX align 5
+        } {}
+        Fl_Input {} {
+          xywh {425 200 90 25} align 5
+        }
+        Fl_Button {} {
+          label {6:}
+          xywh {10 230 25 25}
+        }
+        Fl_Input {} {
+          xywh {40 230 90 25} align 5
+        }
+        Fl_Input {} {
+          xywh {135 230 90 25} align 5
+        }
+        Fl_Input {} {
+          xywh {230 230 90 25} align 5
+        }
+        Fl_Choice c1 {open
+          xywh {325 230 95 25} down_box BORDER_BOX align 5
+        } {}
+        Fl_Input {} {
+          xywh {425 230 90 25} align 5
+        }
+        Fl_Button {} {
+          label {7:}
+          xywh {10 260 25 25}
+        }
+        Fl_Input {} {
+          xywh {40 260 90 25} align 5
+        }
+        Fl_Input {} {
+          xywh {135 260 90 25} align 5
+        }
+        Fl_Input {} {
+          xywh {230 260 90 25} align 5
+        }
+        Fl_Choice c1 {open
+          xywh {325 260 95 25} down_box BORDER_BOX align 5
+        } {}
+        Fl_Input {} {
+          xywh {425 260 90 25} align 5
+        }
+        Fl_Button {} {
+          label {8:}
+          xywh {10 290 25 25}
+        }
+        Fl_Input {} {
+          xywh {40 290 90 25} align 5
+        }
+        Fl_Input {} {
+          xywh {135 290 90 25} align 5
+        }
+        Fl_Input {} {
+          xywh {230 290 90 25} align 5
+        }
+        Fl_Choice c1 {open
+          xywh {325 290 95 25} down_box BORDER_BOX align 5
+        } {}
+        Fl_Input {} {
+          xywh {425 290 90 25} align 5
+        }
+        Fl_Button {} {
+          label {9:}
+          xywh {10 320 25 25}
+        }
+        Fl_Input {} {
+          xywh {40 320 90 25} align 5
+        }
+        Fl_Input {} {
+          xywh {135 320 90 25} align 5
+        }
+        Fl_Input {} {
+          xywh {230 320 90 25} align 5
+        }
+        Fl_Choice c1 {open
+          xywh {325 320 95 25} down_box BORDER_BOX align 5
+        } {}
+        Fl_Input {} {
+          xywh {425 320 90 25} align 5
+        }
+      }
+    }
+    Fl_Button {} {
+      label Cancel
+      xywh {365 365 75 25}
+    }
+    Fl_Return_Button {} {
+      label OK
+      xywh {445 365 75 25}
+    }
+    Fl_Input fname {
+      label {File to export}
+      tooltip {Keep empty to put at beginning of main script.} xywh {100 365 175 25}
+    }
+    Fl_Button {} {
+      label {@->}
+      xywh {275 365 25 25}
+    }
+  }
+} 
+
+Function {make_inplot()} {} {
+  Fl_Window {} {
+    label {Add inplot}
+    xywh {378 449 715 315} type Double hide modal
+  } {
+    Fl_Round_Button k1 {
+      label SubPlot
+      xywh {5 5 105 25} down_box ROUND_DOWN_BOX
+    }
+    Fl_Round_Button k2 {
+      label MultiPlot
+      xywh {5 35 105 25} down_box ROUND_DOWN_BOX
+    }
+    Fl_Round_Button k3 {
+      label GridPlot
+      xywh {5 65 105 25} down_box ROUND_DOWN_BOX
+    }
+    Fl_Round_Button k4 {
+      label ColumnPlot
+      xywh {5 95 105 25} down_box ROUND_DOWN_BOX
+    }
+    Fl_Round_Button k5 {
+      label StickPlot
+      xywh {5 125 105 25} down_box ROUND_DOWN_BOX
+    }
+    Fl_Round_Button k6 {
+      label InPlot
+      xywh {5 155 105 25} down_box ROUND_DOWN_BOX
+    }
+    Fl_Spinner n1 {
+      label nx
+      xywh {145 5 55 25}
+    }
+    Fl_Spinner m1 {
+      label ny
+      xywh {230 5 55 25}
+    }
+    Fl_Spinner i1 {
+      label ind
+      xywh {315 5 55 25}
+    }
+    Fl_Counter x1 {
+      label dx
+      xywh {400 5 95 25} align 4
+    }
+    Fl_Counter y1 {
+      label dy
+      xywh {525 5 95 25} align 4
+    }
+    Fl_Spinner n2 {
+      label nx
+      xywh {145 35 55 25}
+    }
+    Fl_Spinner m2 {
+      label ny
+      xywh {230 35 55 25}
+    }
+    Fl_Spinner i2 {
+      label ind
+      xywh {315 35 55 25}
+    }
+    Fl_Spinner n3 {
+      label nx
+      xywh {145 65 55 25}
+    }
+    Fl_Spinner m3 {
+      label ny
+      xywh {230 65 55 25}
+    }
+    Fl_Spinner i3 {
+      label ind
+      xywh {315 65 55 25}
+    }
+    Fl_Counter d3 {
+      label d
+      xywh {400 65 95 25} align 4
+    }
+    Fl_Spinner n4 {
+      label nx
+      xywh {145 95 55 25}
+    }
+    Fl_Spinner i4 {
+      label ind
+      xywh {315 95 55 25}
+    }
+    Fl_Counter d4 {
+      label d
+      xywh {400 95 95 25} align 4
+    }
+    Fl_Spinner n5 {
+      label nx
+      xywh {145 125 55 25}
+    }
+    Fl_Spinner i5 {
+      label ind
+      xywh {315 125 55 25}
+    }
+    Fl_Input xx1 {
+      label {x:}
+      xywh {145 155 60 25}
+    }
+    Fl_Input xx2 {
+      label {...}
+      xywh {225 155 60 25}
+    }
+    Fl_Input yy1 {
+      label {y:}
+      xywh {315 155 60 25}
+    }
+    Fl_Input yy2 {
+      label {...}
+      xywh {400 155 60 25}
+    }
+    Fl_Spinner tet {
+      label {Rotate on}
+      xywh {75 190 60 25}
+    }
+    Fl_Spinner phi {
+      label and
+      xywh {170 190 60 25}
+    }
+    Fl_Input ax {
+      label {Aspect x/z}
+      xywh {315 190 60 25}
+    }
+    Fl_Input ay {
+      label {y/z}
+      xywh {400 190 60 25}
+    }
+    Fl_Box {} {
+      label {Reserve at:}
+      xywh {0 225 90 25}
+    }
+    Fl_Check_Button rl {
+      label left
+      xywh {90 225 75 25} down_box DOWN_BOX
+    }
+    Fl_Check_Button rb {
+      label bottom
+      xywh {145 225 75 25} down_box DOWN_BOX
+    }
+    Fl_Check_Button rt {
+      label top
+      xywh {225 225 75 25} down_box DOWN_BOX
+    }
+    Fl_Check_Button rr {
+      label right
+      xywh {285 225 75 25} down_box DOWN_BOX
+    }
+    Fl_Check_Button rw {
+      label {whole area}
+      xywh {360 225 100 25} down_box DOWN_BOX
+    }
+    Fl_Input title {
+      label Title
+      xywh {50 255 350 25}
+    }
+    Fl_Button {} {
+      label Style
+      xywh {400 255 60 25}
+    }
+    Fl_Output res {
+      label Result
+      xywh {50 285 410 25}
+    }
+    Fl_Box gr {
+      xywh {470 130 240 180} box ENGRAVED_BOX
+    }
+    Fl_Button {} {
+      label Cancel
+      xywh {545 95 75 25}
+    }
+    Fl_Return_Button {} {
+      label OK
+      xywh {630 95 75 25}
+    }
+    Fl_Button {} {
+      label Refresh
+      xywh {630 60 75 25}
+    }
+    Fl_Spinner {} {
+      label {x-size}
+      xywh {425 35 70 25}
+    }
+    Fl_Spinner {} {
+      label {y-size}
+      xywh {550 35 70 25}
+    }
+  }
+} 
+
+Function {make_find()} {
+  comment {Dialog to Find/Replace text}
+} {
+  Fl_Window find_dlg {
+    label {Find/Replace}
+    xywh {88 605 375 130} type Double hide modal
+  } {
+    Fl_Input find_w {
+      label {Find what:}
+      xywh {90 10 180 25}
+    }
+    Fl_Return_Button {} {
+      label Find
+      xywh {275 10 95 25}
+    }
+    Fl_Input replace_w {
+      label {Replace by:}
+      xywh {90 40 180 25}
+    }
+    Fl_Button {} {
+      label Replace
+      xywh {275 40 95 25}
+    }
+    Fl_Button {} {
+      label {Replace All}
+      xywh {275 70 95 25}
+    }
+    Fl_Check_Button case_w {
+      label {Match case}
+      xywh {5 70 265 25} down_box DOWN_BOX
+    }
+    Fl_Check_Button sback_w {
+      label {Search backward}
+      xywh {5 95 265 25} down_box DOWN_BOX
+    }
+    Fl_Button {} {
+      label Close
+      callback {find_dlg->hide();}
+      xywh {275 100 95 25}
+    }
+  }
+} 
+
+Function {make_animate()} {open
+} {
+  Fl_Window {} {open
+    xywh {360 218 405 405} type Double hide
+  } {}
+} 
+
+Function {make_datinfo()} {} {
+  Fl_Window {} {open
+    xywh {304 146 420 530} type Double hide
+  } {
+    Fl_Output out {
+      label Information
+      xywh {10 26 400 150} align 5
+    }
+    Fl_Box gr {
+      xywh {10 221 400 300} box ENGRAVED_BOX
+    }
+    Fl_Button {} {
+      label {@<-}
+      xywh {10 186 25 25}
+    }
+    Fl_Button {} {
+      label {as 1D}
+      xywh {40 186 75 25}
+    }
+    Fl_Button {} {
+      label {2D view}
+      xywh {120 186 75 25}
+    }
+    Fl_Button {} {
+      label {as 3D}
+      xywh {200 186 75 25}
+    }
+    Fl_Button {} {
+      label {@->}
+      xywh {280 186 25 25}
+    }
+    Fl_Return_Button {} {
+      label Close
+      xywh {335 186 75 25}
+    }
+  }
+} 
+
+Function {make_prim()} {} {
+  Fl_Window {} {
+    label {Add primitive} open
+    xywh {333 270 295 195} type Double hide
+  } {
+    Fl_Choice kind {
+      label Kind open
+      xywh {65 10 75 25} down_box BORDER_BOX
+    } {}
+    Fl_Choice col {
+      label Color open
+      xywh {205 10 75 25} down_box BORDER_BOX
+    } {}
+    Fl_Choice arr1 {
+      label Arrow1 open
+      xywh {65 40 75 25} down_box BORDER_BOX
+    } {}
+    Fl_Choice arr2 {
+      label Arrow2 open
+      xywh {205 40 75 25} down_box BORDER_BOX
+    } {}
+    Fl_Choice dash {
+      label Dash open
+      xywh {65 70 75 25} down_box BORDER_BOX
+    } {}
+    Fl_Choice mark {
+      label Mark open
+      xywh {205 70 75 25} down_box BORDER_BOX
+    } {}
+    Fl_Button {} {
+      label Cancel
+      xywh {120 160 75 25}
+    }
+    Fl_Return_Button {} {
+      label Add
+      xywh {205 160 75 25}
+    }
+    Fl_Check_Button fill {
+      label solid
+      xywh {205 95 75 25} down_box DOWN_BOX
+    }
+    Fl_Input text {
+      label Text
+      xywh {65 125 215 25}
+    }
+    Fl_Spinner {} {
+      label Edges
+      xywh {65 100 75 25}
+    }
+  }
+} 
+
+Function {make_images()} {open
+} {
+  Fl_Window {} {open
+    xywh {507 371 210 190} type Double visible
+  } {
+    Fl_Button {} {selected
+      image {new_icon/media-playback-pause.png} xywh {5 5 25 25}
+    }
+    Fl_Button {} {
+      xywh {30 5 25 25}
+    }
+    Fl_Button {} {
+      xywh {55 5 25 25}
+    }
+    Fl_Button {} {
+      xywh {80 5 25 25}
+    }
+    Fl_Button {} {
+      xywh {105 5 25 25}
+    }
+    Fl_Button {} {
+      xywh {130 5 25 25}
+    }
+    Fl_Button {} {
+      xywh {155 5 25 25}
+    }
+    Fl_Button {} {
+      xywh {180 5 25 25}
+    }
+    Fl_Button {} {
+      xywh {5 30 25 25}
+    }
+    Fl_Button {} {
+      xywh {30 30 25 25}
+    }
+    Fl_Button {} {
+      xywh {55 30 25 25}
+    }
+    Fl_Button {} {
+      xywh {80 30 25 25}
+    }
+    Fl_Button {} {
+      xywh {105 30 25 25}
+    }
+    Fl_Button {} {
+      xywh {130 30 25 25}
+    }
+    Fl_Button {} {
+      xywh {155 30 25 25}
+    }
+    Fl_Button {} {
+      xywh {180 30 25 25}
+    }
+    Fl_Button {} {
+      xywh {5 55 25 25}
+    }
+    Fl_Button {} {
+      xywh {30 55 25 25}
+    }
+    Fl_Button {} {
+      xywh {55 55 25 25}
+    }
+    Fl_Button {} {
+      xywh {80 55 25 25}
+    }
+    Fl_Button {} {
+      xywh {105 55 25 25}
+    }
+    Fl_Button {} {
+      xywh {130 55 25 25}
+    }
+    Fl_Button {} {
+      xywh {155 55 25 25}
+    }
+    Fl_Button {} {
+      xywh {180 55 25 25}
+    }
+    Fl_Button {} {
+      xywh {5 80 25 25}
+    }
+    Fl_Button {} {
+      xywh {30 80 25 25}
+    }
+    Fl_Button {} {
+      xywh {55 80 25 25}
+    }
+    Fl_Button {} {
+      xywh {80 80 25 25}
+    }
+    Fl_Button {} {
+      xywh {105 80 25 25}
+    }
+    Fl_Button {} {
+      xywh {130 80 25 25}
+    }
+    Fl_Button {} {
+      xywh {155 80 25 25}
+    }
+    Fl_Button {} {
+      xywh {180 80 25 25}
+    }
+    Fl_Button {} {
+      xywh {5 105 25 25}
+    }
+    Fl_Button {} {
+      xywh {30 105 25 25}
+    }
+    Fl_Button {} {
+      xywh {55 105 25 25}
+    }
+    Fl_Button {} {
+      xywh {80 105 25 25}
+    }
+    Fl_Button {} {
+      xywh {105 105 25 25}
+    }
+    Fl_Button {} {
+      xywh {130 105 25 25}
+    }
+    Fl_Button {} {
+      xywh {155 105 25 25}
+    }
+    Fl_Button {} {
+      xywh {180 105 25 25}
+    }
+    Fl_Button {} {
+      xywh {5 130 25 25}
+    }
+    Fl_Button {} {
+      xywh {30 130 25 25}
+    }
+    Fl_Button {} {
+      xywh {55 130 25 25}
+    }
+    Fl_Button {} {
+      xywh {80 130 25 25}
+    }
+    Fl_Button {} {
+      xywh {105 130 25 25}
+    }
+    Fl_Button {} {
+      xywh {130 130 25 25}
+    }
+    Fl_Button {} {
+      xywh {155 130 25 25}
+    }
+    Fl_Button {} {
+      xywh {180 130 25 25}
+    }
+    Fl_Output {} {
+      label Name
+      xywh {50 160 75 25}
+    }
+    Fl_Button {} {
+      label Close
+      xywh {130 160 75 25}
+    }
+  }
+} 
diff --git a/mgllab/grid.cpp b/mgllab/grid.cpp
new file mode 100644
index 0000000..e930b29
--- /dev/null
+++ b/mgllab/grid.cpp
@@ -0,0 +1,137 @@
+/* grid.cpp is part of UDAV
+ * Copyright (C) 2007-2014 Alexey Balakin <mathgl.abalakin at gmail.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License
+ * as published by the Free Software Foundation
+ *
+ * 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
+ */
+#include <FL/Fl.H>
+#include <FL/Fl_Window.H>
+#include <FL/Fl_Int_Input.H>
+#include <FL/Fl_Value_Slider.H>
+#include <FL/fl_draw.H>
+#include "mgllab.h"
+//-----------------------------------------------------------------------------
+Fl_Callback input_cb;
+//-----------------------------------------------------------------------------
+void input_cb(Fl_Widget*, void* v)	{ ((Fl_Data_Table*)v)->set_value(); }
+//-----------------------------------------------------------------------------
+Fl_Data_Table::Fl_Data_Table(int x, int y, int w, int h, const char *l) : Fl_Table(x,y,w,h,l)
+{
+	callback(&event_callback, (void*)this);
+	input = new Fl_Input(w/2,h/2,0,0);
+	input->hide();
+	input->callback(input_cb, (void*)this);
+	input->when(FL_WHEN_ENTER_KEY_ALWAYS);
+	input->maximum_size(16);
+	sl = 0;	row=col=-1;
+//	(new Fl_Box(9999,9999,0,0))->hide();  // HACK: prevent flickering in Fl_Scroll
+	end();
+}
+//-----------------------------------------------------------------------------
+// Handle drawing all cells in table
+void Fl_Data_Table::draw_cell(TableContext context, int R, int C, int X, int Y, int W, int H)
+{
+	static char s[64];
+	fl_push_clip(X, Y, W, H);
+	switch ( context )
+	{
+	case CONTEXT_COL_HEADER:
+		fl_draw_box(FL_THIN_UP_BOX, X, Y, W, H, col_header_color());
+		fl_font(FL_HELVETICA | FL_BOLD, 14);
+		fl_color(FL_BLACK);		snprintf(s,32,"%d",C);
+		fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER);
+		break;
+	case CONTEXT_ROW_HEADER:
+		fl_draw_box(FL_THIN_UP_BOX, X, Y, W, H, col_header_color());
+		fl_font(FL_HELVETICA | FL_BOLD, 14);
+		fl_color(FL_BLACK);		snprintf(s,32,"%d",R);
+		fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER);
+		break;
+	case CONTEXT_CELL:
+	    if (R == row && C == col && input->visible())	break;
+		fl_draw_box(FL_THIN_DOWN_BOX, X, Y, W, H, FL_WHITE);
+		fl_pop_clip();
+		fl_push_clip(X+3, Y+3, W-6, H-6);
+		fl_font(FL_HELVETICA, 14);
+		if(mgl_isnan(data->v(C,R,sl)))	strcpy(s,"nan");
+		else if(mgl_isbad(data->v(C,R,sl)))	strcpy(s,data->v(C,R,sl)>0?"inf":"-inf");
+		else	strncpy(s,mgl_str_num(data->vc(C,R,sl)).c_str(),64);
+		{	dual vc = data->vc(C,R,sl);
+			mreal v = data->v(C,R,sl);
+			std::vector<mreal> vn;
+			if(C>0)	vn.push_back(data->v(C-1,R,sl));
+			if(R>0)	vn.push_back(data->v(C,R-1,sl));
+			if(C<data->GetNx()-1)	vn.push_back(data->v(C+1,R,sl));
+			if(R<data->GetNy()-1)	vn.push_back(data->v(C,R+1,sl));
+			bool v1=true, v2=true;
+			for(size_t i=0;i<vn.size();i++)	{	if(vn[i]<=v)	v1=false;	if(vn[i]>=v)	v2=false;	}
+			if(v2)	fl_color(FL_MAGENTA);
+			else if(v1)	fl_color(FL_CYAN);
+			else if(real(vc)>0)		fl_color(FL_RED);
+			else if(real(vc)<0)	fl_color(FL_BLUE);
+			else if(imag(vc)>0)	fl_color(FL_DARK_MAGENTA);
+			else if(imag(vc)<0)	fl_color(FL_DARK_CYAN);
+			else	fl_color(FL_BLACK);	}
+		fl_draw(s, X+3, Y+3, W-6, H-6, FL_ALIGN_RIGHT);
+		break;
+	case CONTEXT_RC_RESIZE:
+		if (!input->visible()) break;
+		find_cell(CONTEXT_TABLE, row, col, X, Y, W, H);
+		if (X!=input->x() || Y!=input->y() || W!=input->w() || H!=input->h())
+			input->resize(X,Y,W,H);
+		break;
+	default:	break;
+	}
+	fl_pop_clip();
+}
+//-----------------------------------------------------------------------------
+void Fl_Data_Table::cell_click()
+{
+    int R = callback_row(), C = callback_col();
+    TableContext context = callback_context();
+
+    if(context==CONTEXT_CELL)
+	{
+		if (input->visible())	set_value();
+		row = R;	col = C;
+		int XX,YY,WW,HH;
+		find_cell(CONTEXT_CELL, R, C, XX, YY, WW, HH);
+		input->resize(XX,YY,WW,HH);
+		std::string s;
+		if(mgl_isnan(data->v(C,R,sl)))	s = "nan";
+		else if(mgl_isbad(data->v(C,R,sl)))	s = data->v(C,R,sl)>0?"inf":"-inf";
+		else	s = mgl_str_num(data->vc(C,R,sl));
+		input->value(s.c_str());	input->show();
+		input->take_focus();
+	}
+}
+//-----------------------------------------------------------------------------
+void Fl_Data_Table::set_value()
+{
+	const char *s = input->value();
+	if(s[0]==0 || !strcmp(s,"nan"))	data->set_v(NAN, col,row,sl);
+	else if(!strcmp(s,"inf"))	data->set_v(INFINITY, col,row,sl);
+	else if(!strcmp(s,"-inf"))	data->set_v(-INFINITY, col,row,sl);
+	else
+	{
+		dual v = mgl_atoc(s,true);
+		if(imag(v)==0)	data->set_v(real(v), col,row,sl);
+		else
+		{
+			HADT c = dynamic_cast<HADT>(data);
+			if(c)	c->a[col+c->nx*(row+c->ny*sl)] = v;
+			else	data->set_v(abs(v),col,row,sl);
+		}
+	}
+}
+//-----------------------------------------------------------------------------
diff --git a/mgllab/help.cpp b/mgllab/help.cpp
new file mode 100644
index 0000000..da9532d
--- /dev/null
+++ b/mgllab/help.cpp
@@ -0,0 +1,489 @@
+/* help.cpp is part of UDAV
+ * Copyright (C) 2007-2014 Alexey Balakin <mathgl.abalakin at gmail.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License
+ * as published by the Free Software Foundation
+ *
+ * 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
+ */
+#include "mgllab.h"
+#include "../widgets/image.h"
+#include <ctype.h>
+#include <FL/Fl_Select_Browser.H>
+//-----------------------------------------------------------------------------
+void help_cb(Fl_Widget*, void*v)
+{
+	ScriptWindow* e = (ScriptWindow*)v;
+	int cur = e->editor->insert_position(), br=0;
+	int beg = textbuf->line_start(cur);
+	const char *s = textbuf->text();
+	for(int i=beg;i<cur;i++)
+	{
+		if(strchr("({[",s[i]))	br++;
+		if(strchr(")}]",s[i]))	br--;
+		if(br==0 && s[i]==':' && i+1<cur)	beg=i+1;
+	}
+	for(br=beg;s[br]>' ' && s[br]!=':';br++);
+	std::string cmd(s+beg,br-beg);
+	e->link_cmd->value(cmd.c_str());
+	static std::string str;
+	str = helpname+cmd;
+	e->hd->load(str.c_str());
+	if(e->rtab)	e->rtab->value(e->ghelp);
+}
+//-----------------------------------------------------------------------------
+void link_cb(Fl_Widget*, void*v)
+{
+	ScriptWindow* e = (ScriptWindow*)v;
+	const char *s = e->link_cmd->value();
+	if(!s)	s="Examples";
+	static std::string str;
+	str = helpname+s;
+	e->hd->load(str.c_str());
+	if(e->rtab)	e->rtab->value(e->ghelp);
+}
+//-----------------------------------------------------------------------------
+void example_cb(Fl_Widget*, void*v)
+{
+	ScriptWindow* e = (ScriptWindow*)v;
+	static std::string str = helpname+"Examples";
+	e->hd->load(str.c_str());	e->rtab->value(e->ghelp);
+	if(e->rtab)	e->rtab->value(e->ghelp);
+}
+//-----------------------------------------------------------------------------
+void help_in_cb(Fl_Widget*, void*v)
+{
+	ScriptWindow* e = (ScriptWindow*)v;
+	e->hd->textsize(e->hd->textsize()+1);
+}
+//-----------------------------------------------------------------------------
+void help_out_cb(Fl_Widget*, void*v)
+{
+	ScriptWindow* e = (ScriptWindow*)v;
+	e->hd->textsize(e->hd->textsize()-1);
+}
+//-----------------------------------------------------------------------------
+#include "xpm/udav.xpm"
+void about_cb(Fl_Widget*, void*)
+{
+	static char s[128];
+	snprintf(s,128,_("mgllab v. 2.%g\n(c) Alexey Balakin, 2017\nhttp://mathgl.sf.net/"), MGL_VER2);
+	Fl_Double_Window* w = new Fl_Double_Window(355, 130, "About UDAV");
+	Fl_Box* o = new Fl_Box(10, 15, 65, 65);
+	o->box(FL_UP_BOX);	o->color(55);	o->image(new Fl_Pixmap(udav_xpm));
+	o = new Fl_Box(85, 15, 260, 65);	o->label(s);
+	Fl_Button *b = new Fl_Return_Button(255, 90, 90, 30, "Close");
+	b->callback(close_dlg_cb,w);
+	w->end();	w->set_modal();	w->show();
+}
+//-----------------------------------------------------------------------------
+#include "xpm/zoom-out.xpm"
+#include "xpm/zoom-in.xpm"
+#include "xpm/help-faq.xpm"
+Fl_Widget *add_help(ScriptWindow *w)
+{
+	Fl_Window *w1=new Fl_Window(300,30,630,430,0);
+	Fl_Group *g = new Fl_Group(0,0,290,30);
+	Fl_Button *o;
+
+	w->link_cmd = new Fl_Input(0,1,150,25);
+	w->link_cmd->when(FL_WHEN_CHANGED);
+	w->link_cmd->callback(link_cb,w);
+
+	o = new Fl_Button(155, 1, 25, 25);	o->tooltip(_("MGL samples and hints"));
+	o->image(new Fl_Pixmap(help_faq_xpm));	o->callback(example_cb,w);
+	o = new Fl_Button(180, 1, 25, 25);	o->tooltip(_("Increase font size"));
+	o->image(new Fl_Pixmap(zoom_in_xpm));	o->callback(help_in_cb,w);
+	o = new Fl_Button(205, 1, 25, 25);	o->tooltip(_("Decrease font size"));
+	o->image(new Fl_Pixmap(zoom_out_xpm));	o->callback(help_out_cb,w);
+
+	g->end();	g->resizable(0);
+
+	w->hd = new Fl_Help_View(0,28,630,400);
+	w1->end();	link_cb(w,w);
+	w1->resizable(w->hd);	return w1;
+}
+//-----------------------------------------------------------------------------
+void mem_dlg_cb0(Fl_Widget *, void *v)
+{	((ScriptWindow*)v)->mem_pressed(0);	}
+//-----------------------------------------------------------------------------
+void mem_dlg_cb1(Fl_Widget *, void *v)
+{	((ScriptWindow*)v)->mem_pressed(1);	}
+//-----------------------------------------------------------------------------
+void mem_dlg_cb2(Fl_Widget *, void *v)
+{	((ScriptWindow*)v)->mem_pressed(2);	}
+//-----------------------------------------------------------------------------
+void mem_dlg_cb3(Fl_Widget *, void *v)
+{	((ScriptWindow*)v)->mem_pressed(3);	}
+//-----------------------------------------------------------------------------
+void mem_dlg_cb4(Fl_Widget *, void *v)
+{	((ScriptWindow*)v)->mem_pressed(4);	}
+//-----------------------------------------------------------------------------
+void mem_update_cb(Fl_Widget *, void *v)
+{	((ScriptWindow*)v)->mem_init();	}
+//-----------------------------------------------------------------------------
+void delete_all_cb(Fl_Widget *, void *v)
+{
+	if(fl_choice(_("Are you sure that you want to delete ALL data arrays?"), _("Yes"), _("No"), NULL) == 0)
+	{	Parse->DeleteAll();	((ScriptWindow*)v)->mem_init();	}
+}
+//-----------------------------------------------------------------------------
+Fl_Widget *add_mem(ScriptWindow *w)
+{
+	static int widths[] = {220,205,0};
+	Fl_Button *o;
+	Fl_Box *b;
+	Fl_Window *wnd = new Fl_Window(300,30,630,430,0);
+
+	b = new Fl_Box(0, 10, 630, 25, _("Existed data arrays"));	b->labeltype(FL_ENGRAVED_LABEL);
+	b = new Fl_Box(0, 35, 220, 25, _("name"));
+	b->box(FL_THIN_UP_BOX);	b->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
+	b = new Fl_Box(220, 35, 205, 25, _("dimensions"));
+	b->box(FL_THIN_UP_BOX);	b->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
+	b = new Fl_Box(425, 35, 205, 25, _("mem. usage"));
+	b->box(FL_THIN_UP_BOX);	b->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
+
+	w->var = new Fl_Select_Browser(0, 60, 630, 335);	w->var->column_char('\t');
+	w->var->align(FL_ALIGN_TOP);	w->var->column_widths(widths);
+	w->var->tooltip(_("List of available data."));
+
+	o = new Fl_Button(20, 400, 90, 25, _(" Edit"));	o->callback(mem_dlg_cb0,w);
+	o->image(img_grid);	o->align(FL_ALIGN_IMAGE_NEXT_TO_TEXT);
+	o->tooltip(_("Open table with selected data for editing."));
+	o = new Fl_Button(120, 400, 90, 25, _(" Info"));	o->callback(mem_dlg_cb1,w);
+	o->image(img_info);	o->align(FL_ALIGN_IMAGE_NEXT_TO_TEXT);
+	o->tooltip(_("Data information and preview."));
+	o = new Fl_Button(220, 400, 90, 25, _(" Delete"));	o->callback(mem_dlg_cb2,w);
+	o->image(img_delete);	o->align(FL_ALIGN_IMAGE_NEXT_TO_TEXT);
+	o->tooltip(_("Delete selected data."));
+	o = new Fl_Button(320, 400, 90, 25, _(" New"));	o->callback(mem_dlg_cb3,w);
+	o->image(img_new);	o->align(FL_ALIGN_IMAGE_NEXT_TO_TEXT);
+	o->tooltip(_("Open dialog for new data creation."));
+	o = new Fl_Button(420, 400, 90, 25, _(" Save"));	o->callback(mem_dlg_cb4,w);
+	o->image(img_save);	o->align(FL_ALIGN_IMAGE_NEXT_TO_TEXT);
+	o->tooltip(_("Save selected data to file."));
+// 	o = new Fl_Button(420, 400, 90, 25, _(" Refresh"));	o->callback(mem_update_cb,w);
+// 	o->image(img_update);	o->align(FL_ALIGN_IMAGE_NEXT_TO_TEXT);
+// 	o->tooltip(_("Refresh list of variables."));
+	o = new Fl_Button(520, 400, 90, 25, _(" Del.all"));	o->callback(delete_all_cb,w);
+	o->image(img_clear);	o->align(FL_ALIGN_IMAGE_NEXT_TO_TEXT);
+	o->tooltip(_("Delete @b all at . data arrays."));
+	wnd->end();	wnd->resizable(w->var);	return wnd;
+}
+//-----------------------------------------------------------------------------
+void ScriptWindow::mem_init()
+{
+	char str[128];
+	var->clear();
+	for(long i=0;i<Parse->GetNumVar();i++)
+	{
+		mglDataA *v = Parse->GetVar(i);
+		if(v && !v->temp)
+		{
+			long sv = 0;
+			if(dynamic_cast<mglData*>(v))	sv = v->GetNN()*sizeof(mreal)+sizeof(mglData);
+			else if(dynamic_cast<mglDataC*>(v))	sv = v->GetNN()*sizeof(dual)+sizeof(mglDataC);
+			else if(dynamic_cast<mglDataV*>(v))	sv = sizeof(mglDataV);
+			else if(dynamic_cast<mglDataW*>(v))	sv = sizeof(mglDataW);
+			else if(dynamic_cast<mglDataF*>(v))	sv = sizeof(mglDataF);
+			else if(dynamic_cast<mglDataR*>(v))	sv = sizeof(mglDataR);
+			else if(dynamic_cast<mglDataT*>(v))	sv = sizeof(mglDataT);
+			const char *ext[]={_("unknown"),"b","Kb","Mb","Gb","Tb","Pb","Eb","Zb","Yb"}, *e;
+			if(sv==0)	e = ext[0];
+#if MGL_SIZEOF_LONG>4
+//			else if((sv>>80L)>0)	{	e=ext[9];	sv = sv>>80L;	}
+//			else if((sv>>70L)>0)	{	e=ext[8];	sv = sv>>70L;	}
+			else if((sv>>60L)>0)	{	e=ext[7];	sv = sv>>60L;	}
+			else if((sv>>50L)>0)	{	e=ext[6];	sv = sv>>50L;	}
+			else if((sv>>40L)>0)	{	e=ext[5];	sv = sv>>40L;	}
+#endif
+			else if((sv>>30L)>0)	{	e=ext[4];	sv = sv>>30L;	}
+			else if((sv>>20L)>0)	{	e=ext[3];	sv = sv>>20L;	}
+			else if((sv>>10L)>0)	{	e=ext[2];	sv = sv>>10L;	}
+			else	e=ext[1];
+			snprintf(str,128,"%ls\t%ld*%ld*%ld\t%ld %s", v->s.c_str(), v->GetNx(), v->GetNy(), v->GetNz(), sv, e);
+			var->add(str,v);
+		}
+	}
+	for(long i=0;i<Parse->GetNumConst();i++)
+	{
+		mglNum *v = Parse->GetConst(i);
+		snprintf(str,128,"%ls\t%s\t%zu b", v->s.c_str(), ("const="+mgl_str_num(v->c)).c_str(), sizeof(mglNum));
+		var->add(str,v);
+	}
+}
+//-----------------------------------------------------------------------------
+void ScriptWindow::mem_pressed(int kind)
+{
+	TableWindow *w;
+	int ind = var->value();
+	mglDataA *v = (mglDataA *)var->data(ind);
+	const char *s = var->text(ind);
+	bool dat = s && !strstr(s,"\tconst");
+	if(!v && kind!=3)	return;
+	if(dat && kind==0)
+	{
+		w = (TableWindow *)v->o;
+		if(!w)	w = new TableWindow(this);
+		w->update(v);	w->show();
+	}
+	else if(dat && kind==1)	info_dlg_cb(v);
+	else if(dat && kind==2)	Parse->DeleteVar(v->s.c_str());
+	else if(kind==3)
+	{
+		const char *name = fl_input(_("Enter name for new variable"),"dat");
+		if(!name)	return;
+		v = Parse->AddVar(name);
+		w = v->o? (TableWindow*)v->o:new TableWindow(this);
+		w->update(v);	w->show();
+	}
+	else if(dat && kind==4)
+	{
+		const char *newfile = mgl_file_chooser(_("Save Data?"),
+				_("DAT Files \t*.{dat,csv}\nHDF Files \t*.{h5,hdf}"), true);
+		if(newfile)
+		{
+			const char *ext = fl_filename_ext(newfile);
+			if(!strcmp(ext,"h5") || !strcmp(ext,"hdf"))	// this is HDF file
+			{
+				std::string name = wcstombs(v->s);
+				v->SaveHDF(newfile, name.c_str());
+			}
+			else	v->Save(newfile);
+		}
+	}
+	mem_init();
+}
+//-----------------------------------------------------------------------------
+const char *hints[] = {
+	_("You can shift axis range by pressing middle button and moving mouse. Also, you can zoom in/out axis range by using mouse wheel."),
+	_("You can rotate/shift/zoom whole plot by mouse. Just press 'Rotate' toolbutton, click image and hold a mouse button: left button for rotation, right button for zoom/perspective, middle button for shift."),
+	_("You may quickly draw the data from file. Just use: udav 'filename.dat' in command line."),
+	_("You can copy the current image to clipboard by pressing Ctrl-Shift-C. Later you can paste it directly into yours document or presentation."),
+	_("You can export image into a set of format (EPS, SVG, PNG, JPEG) by pressing right mouse button inside image and selecting 'Export as ...'."),
+	_("You can setup colors for script highlighting in Property dialog. Just select menu item 'Settings/Properties'."),
+	_("You can save the parameter of animation inside MGL script by using comment started from '##a ' or '##c ' for loops."),
+	_("New drawing never clears things drawn already. For example, you can make a surface with contour lines by calling commands 'surf' and 'cont' one after another (in any order). "),
+	_("You can put several plots in the same image by help of commands 'subplot' or 'inplot'."),
+	_("All indexes (of data arrays, subplots and so on) are always start from 0."),
+	_("You can edit MGL file in any text editor. Also you can run it in console by help of commands: mglconv, mglview."),
+	_("You can use command 'once on|off' for marking the block which should be executed only once. For example, this can be the block of large data reading/creating/handling. Press F9 (or menu item 'Graphics/Reload') to re-execute this block."),
+	_("You can use command 'stop' for terminating script parsing. It is useful if you don't want to execute a part of script."),
+	_("You can type arbitrary expression as input argument for data or number. In last case (for numbers), the first value of data array is used."),
+	_("There is powerful calculator with a lot of special functions. You can use buttons or keyboard to type the expression. Also you can use existed variables in the expression."),
+	_("The calculator can help you to put complex expression in the script. Just type the expression (which may depend on coordinates x,y,z and so on) and put it into the script."),
+	_("You can easily insert file or folder names, last fitted formula or numerical value of selection by using menu Edit|Insert."),
+	_("The special dialog (Edit|Insert|New Command) help you select the command, fill its arguments and put it into the script."),
+	_("You can put several plotting commands in the same line or in separate function, for highlighting all of them simultaneously."),
+	NULL
+};
+//-----------------------------------------------------------------------------
+void cb_hint_prev(Fl_Widget*,void*);
+void cb_hint_next(Fl_Widget*,void*);
+class HintDlg : public GeneralDlg
+{
+	Fl_Help_View *hint;
+	Fl_Check_Button *start;
+	int cur;
+public:
+	HintDlg() : GeneralDlg()
+	{
+		Fl_Button *o;
+		w = new Fl_Double_Window(280, 265);	cur=0;
+		hint = new Fl_Help_View(10, 10, 260, 185);
+		hint->value(hints[0]);
+		start = new Fl_Check_Button(10, 200, 260, 25, _("Show hint on startup"));
+		o = new Fl_Button(10, 230, 80, 25, _("@<-  Prev"));
+		o->callback(cb_hint_prev);
+		o = new Fl_Button(100, 230, 80, 25, _("Next @->"));
+		o->callback(cb_hint_next);
+		o = new Fl_Return_Button(190, 230, 80, 25, _("Close"));
+		o->callback(cb_dlg_ok,this);
+		w->end();
+	}
+	void init()
+	{	int sh;	pref.get("show_hint",sh,1);	start->value(sh);	}
+	void cb_ok()
+	{	pref.set("show_hint",start->value());	hide();	}
+	void prev()
+	{
+		int n=0;	while(hints[n])	n++;
+		cur = cur>0?cur-1:n-1;
+		hint->value(hints[cur]);
+	}
+	void next()
+	{
+		int n=0;	while(hints[n])	n++;
+		cur = cur<n-1?cur+1:0;
+		hint->value(hints[cur]);
+	}
+} hint_dlg;
+//-----------------------------------------------------------------------------
+void cb_hint_prev(Fl_Widget*,void*)	{	hint_dlg.prev();	}
+void cb_hint_next(Fl_Widget*,void*)	{	hint_dlg.next();	}
+//-----------------------------------------------------------------------------
+void hint_dlg_cb(Fl_Widget*,void *)	{	hint_dlg.show();	}
+//-----------------------------------------------------------------------------
+void cb_info_prev(Fl_Widget*,void*);
+void cb_info_next(Fl_Widget*,void*);
+void cb_info_1d(Fl_Widget*,void*);
+void cb_info_2d(Fl_Widget*,void*);
+void cb_info_3d(Fl_Widget*,void*);
+class InfoDlg : public GeneralDlg
+{
+	Fl_Multiline_Output *out;
+	Fl_MathGL *gr;
+	long nx, ny, nz;
+	long sl;
+	int plot;
+	std::string name;
+public:
+	InfoDlg() : GeneralDlg()
+	{
+		Fl_Button *o;
+		w = new Fl_Double_Window(420, 530);
+		out = new Fl_Multiline_Output(10, 25, 400, 150, _("Information"));
+		out->align(FL_ALIGN_TOP_LEFT);
+		gr = new Fl_MathGL(10, 220, 400, 300);	gr->box(FL_ENGRAVED_BOX);	gr->use_pthr = false;
+		mgl_set_size(gr->get_graph(),400,300);
+		o = new Fl_Button(10, 185, 25, 25, "@<-");
+		o->callback(cb_info_prev,this);
+		o = new Fl_Button(40, 185, 75, 25, _("1D view"));
+		o->callback(cb_info_1d,this);
+		o = new Fl_Button(120, 185, 75, 25, _("2D view"));
+		o->callback(cb_info_2d,this);
+		o = new Fl_Button(200, 185, 75, 25, _("3D view"));
+		o->callback(cb_info_3d,this);
+		o = new Fl_Button(280, 185, 25, 25, "@->");
+		o->callback(cb_info_next,this);
+		o = new Fl_Return_Button(335, 185, 75, 25, _("Close"));
+		o->callback(cb_dlg_cancel,this);
+		w->set_modal();	w->end();
+	}
+	void update()
+	{
+		if(!dat)	return;
+		std::string script;
+		char buf[32];
+		switch(plot)
+		{
+		case 0:
+			if(sl<0)	sl=ny-1;
+			if(sl>=ny)	sl=0;
+			snprintf(buf,31,"%ld",sl);
+			script = "subplot 1 1 0 '<_':xrange 0 1:yrange " + name + ":plot " + name + "(:," + buf + "):axis:box:text 1 1 'sl=" + buf + "' 'r:aR'";
+			break;
+		case 1:
+			if(sl<0)	sl=nz-1;
+			if(sl>=nz)	sl=0;
+			snprintf(buf,31,"%ld",sl);
+			script = "subplot 1 1 0 '':crange " + name + ":dens " + name + "(:,:," + buf + "):box:text 1 1 'sl=" + buf + "' 'r:aR'";
+			break;
+		case 2:
+			script = "rotate 40 60:light on:crange " + name + ":surf3 " + name + ":box";
+			break;
+		}
+		script = "clf:"+script;
+		mgl_set_def_param(gr->get_graph());
+		mgl_parse_text(gr->get_graph(), Parse->Self(), script.c_str());
+		gr->update();
+	}
+	void prev()		{	sl--;	update();	}
+	void next()		{	sl++;	update();	}
+	void plot_1d()	{	plot=0;	update();	}
+	void plot_2d()	{	if(ny>1)	{	plot=1;	update();	}	}
+	void plot_3d()	{	if(nz>1)	{	plot=2;	update();	}	}
+	void init()
+	{
+		nx=ny=nz=sl=plot=0;
+		if(dat)
+		{
+			nx=dat->GetNx();	ny=dat->GetNy();	nz=dat->GetNz();
+			result = dat->PrintInfo();	out->value(result.c_str());
+			name = wcstombs(dat->s);
+			if(nz>1)		plot_3d();
+			else if(ny>1)	plot_2d();
+			else			plot_1d();
+		}
+	}
+} info_dlg;
+//-----------------------------------------------------------------------------
+void info_dlg_cb(mglDataA *d)
+{	if(d)	{	info_dlg.dat=d;	info_dlg.show();	}	}
+//-----------------------------------------------------------------------------
+void cb_info_prev(Fl_Widget*,void*)	{	info_dlg.prev();	}
+void cb_info_next(Fl_Widget*,void*)	{	info_dlg.next();	}
+void cb_info_1d(Fl_Widget*,void*)	{	info_dlg.plot_1d();	}
+void cb_info_2d(Fl_Widget*,void*)	{	info_dlg.plot_2d();	}
+void cb_info_3d(Fl_Widget*,void*)	{	info_dlg.plot_3d();	}
+//-----------------------------------------------------------------------------
+class IconListDlg : public GeneralDlg
+{
+public:
+	IconListDlg() : GeneralDlg()
+	{
+		Fl_Button* o;
+		w = new Fl_Double_Window(210, 190, "mgllab icons");
+		o = new Fl_Button(5, 5, 25, 25);	o->image(img_load);	o->tooltip("img_load");
+		o = new Fl_Button(30, 5, 25, 25);	o->image(img_save);	o->tooltip("img_save");
+		o = new Fl_Button(55, 5, 25, 25);	o->image(img_calc);	o->tooltip("img_calc");
+		o = new Fl_Button(80, 5, 25, 25);	o->image(img_undo);	o->tooltip("img_undo");
+		o = new Fl_Button(105, 5, 25, 25);	o->image(img_redo);	o->tooltip("img_redo");
+		o = new Fl_Button(130, 5, 25, 25);	o->image(img_copy);	o->tooltip("img_copy");
+		o = new Fl_Button(155, 5, 25, 25);	o->image(img_paste);o->tooltip("img_paste");
+		o = new Fl_Button(180, 5, 25, 25);	o->image(img_find);	o->tooltip("img_find");
+		o = new Fl_Button(5, 30, 25, 25);	o->image(img_prop);	o->tooltip("img_prop");
+		o = new Fl_Button(30, 30, 25, 25);	o->image(img_alpha);o->tooltip("img_alpha");
+		o = new Fl_Button(55, 30, 25, 25);	o->image(img_light);o->tooltip("img_light");
+		o = new Fl_Button(80, 30, 25, 25);	o->image(img_grid);	o->tooltip("img_grid");
+		o = new Fl_Button(105, 30, 25, 25);	o->image(img_move);	o->tooltip("img_move");
+		o = new Fl_Button(130, 30, 25, 25);	o->image(img_orig);	o->tooltip("img_orig");
+		o = new Fl_Button(155, 30, 25, 25);	o->image(img_update);	o->tooltip("img_update");
+		o = new Fl_Button(180, 30, 25, 25);	o->image(img_stop);	o->tooltip("img_stop");
+		o = new Fl_Button(5, 55, 25, 25);	o->image(img_insert);	o->tooltip("img_insert");
+		o = new Fl_Button(30, 55, 25, 25);	o->image(img_print);o->tooltip("img_print");
+		o = new Fl_Button(55, 55, 25, 25);	o->image(img_goL);	o->tooltip("img_goL");
+		o = new Fl_Button(80, 55, 25, 25);	o->image(img_goU);	o->tooltip("img_goU");
+		o = new Fl_Button(105, 55, 25, 25);	o->image(img_zoomIn);	o->tooltip("img_zoomIn");
+		o = new Fl_Button(130, 55, 25, 25);	o->image(img_zoomOut);	o->tooltip("img_zoomOut");
+		o = new Fl_Button(155, 55, 25, 25);	o->image(img_goD);	o->tooltip("img_goD");
+		o = new Fl_Button(180, 55, 25, 25);	o->image(img_goR);	o->tooltip("img_goR");
+		o = new Fl_Button(5, 80, 25, 25);	o->image(img_next);	o->tooltip("img_next");
+		o = new Fl_Button(30, 80, 25, 25);	o->image(img_play);	o->tooltip("img_play");
+		o = new Fl_Button(55, 80, 25, 25);	o->image(img_prev);	o->tooltip("img_prev");
+		o = new Fl_Button(80, 80, 25, 25);	o->image(img_plot);	o->tooltip("img_plot");
+		o = new Fl_Button(105, 80, 25, 25);	o->image(img_system);	o->tooltip("img_system");
+		o = new Fl_Button(130, 80, 25, 25);	o->image(img_info);	o->tooltip("img_info");
+		o = new Fl_Button(155, 80, 25, 25);	o->image(img_help);	o->tooltip("img_help");
+		o = new Fl_Button(180, 80, 25, 25);	o->image(img_delete);	o->tooltip("img_delete");
+		o = new Fl_Button(5, 105, 25, 25);	o->image(img_objectU);	o->tooltip("img_objectU");
+		o = new Fl_Button(30, 105, 25, 25);	o->image(img_objectD);	o->tooltip("img_objectD");
+		o = new Fl_Button(55, 105, 25, 25);	o->image(img_layer);o->tooltip("img_layer");
+		o = new Fl_Button(80, 105, 25, 25);	o->image(img_new);	o->tooltip("img_new");
+		o = new Fl_Button(105, 105, 25, 25);o->image(img_clear);o->tooltip("img_clear");
+		o = new Fl_Button(130, 105, 25, 25);o->image(img_plus);	o->tooltip("img_plus");
+		o = new Fl_Button(155, 105, 25, 25);o->image(img_minus);o->tooltip("img_minus");
+		o = new Fl_Button(180, 105, 25, 25);o->image(img_fname);o->tooltip("img_fname");
+		o = new Fl_Button(5, 130, 25, 25);	o->image(img_curve);o->tooltip("img_curve");
+		o = new Fl_Button(30, 130, 25, 25);	o->image(img_svn);	o->tooltip("img_svn");
+		o = new Fl_Button(55, 130, 25, 25);	o->image(img_adjust);	o->tooltip("img_adjust");
+		o = new Fl_Button(80, 130, 25, 25);	o->image(img_reload);	o->tooltip("img_reload");
+		o = new Fl_Button(105, 130, 25, 25);o->image(img_zoom12);	o->tooltip("img_zoom12");
+		o = new Fl_Button(130, 130, 25, 25);o->image(img_zoom21);	o->tooltip("img_zoom21");
+		o = new Fl_Button(155, 130, 25, 25);o->image(img_pause);	o->tooltip("img_pause");
+//		o = new Fl_Button(180, 130, 25, 25);o->image(img_save);	o->tooltip("img_save");
+		o = new Fl_Button(130, 160, 75, 25, _("Close"));
+		o->callback(cb_dlg_cancel,this);
+		w->end();
+	}
+} iconlist;
+void iconlist_cb(Fl_Widget*,void*)	{	iconlist.show();	}
+//-----------------------------------------------------------------------------
diff --git a/mgllab/mathgl.cpp b/mgllab/mathgl.cpp
new file mode 100644
index 0000000..bc32806
--- /dev/null
+++ b/mgllab/mathgl.cpp
@@ -0,0 +1,478 @@
+/* mathgl.cpp is part of UDAV
+ * Copyright (C) 2007-2014 Alexey Balakin <mathgl.abalakin at gmail.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License
+ * as published by the Free Software Foundation
+ *
+ * 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
+ */
+#include "mgl2/mgl.h"
+#include "mgllab.h"
+#include "../widgets/image.h"
+//-----------------------------------------------------------------------------
+mglParse *Parse=0;
+//-----------------------------------------------------------------------------
+mreal udav_delay(void *v)
+{	return ((Fl_MGL*)v)->delay;	}
+void udav_reload(void *v)
+{	Parse->RestoreOnce();	((Fl_MGL*)v)->update();	}
+//-----------------------------------------------------------------------------
+void udav_next(void *v)	{	((Fl_MGL*)v)->next_frame();	}
+void Fl_MGL::next_frame()
+{
+	size_t n=anim.size();
+	if(n==0 && animate_cb(this))	{	gr->toggle_sshow();	return;	}
+	n=anim.size();
+	cur = (cur+1)%n;
+	Parse->AddParam(0,anim[cur].c_str());
+	update();
+}
+//-----------------------------------------------------------------------------
+void udav_prev(void *v)	{	((Fl_MGL*)v)->prev_frame();	}
+void Fl_MGL::prev_frame()
+{
+	size_t n=anim.size();
+	if(n==0 && animate_cb(this))	{	gr->toggle_sshow();	return;	}
+	n=anim.size();
+	cur = (cur+n-1)%n;
+	Parse->AddParam(0,anim[cur].c_str());
+	update();
+}
+//-----------------------------------------------------------------------------
+Fl_MGL::Fl_MGL(Fl_MGLView *GR)
+{
+	if(!Parse)	Parse = new mglParse;
+	Parse->AllowSetSize(true);
+	gr = GR;	gr->par = this;	e = 0;
+	gr->next = udav_next;	gr->delay = udav_delay;
+	gr->prev = udav_prev;	gr->reload = udav_reload;
+	gr->FMGL->set_draw(this);
+	gr->FMGL->set_show_warn(false);
+	a1=a2=0;	da=1;	cur=0;	delay=0.5;
+}
+//-----------------------------------------------------------------------------
+Fl_MGL::~Fl_MGL()	{}
+//-----------------------------------------------------------------------------
+void Fl_MGL::Reload()
+{
+	Parse->RestoreOnce();
+	e->graph->update();
+}
+//-----------------------------------------------------------------------------
+void Fl_MGL::Click()
+{
+	int id = e->graph->FMGL->get_last_id();
+	if(id>0)
+	{
+		Fl_Text_Editor::kf_ctrl_move(FL_Home, e->editor);
+		for(int i=0;i<id;i++)	Fl_Text_Editor::kf_down(0, e->editor);
+		Fl_Text_Editor::kf_up(0, e->editor);
+		Fl::focus(e->editor);
+	}
+	e->graph->update();
+}
+//-----------------------------------------------------------------------------
+int Fl_MGL::Draw(mglGraph *gr)
+{
+	if(exec_save)	save_cb(0,e);
+	Parse->Execute(gr,script.c_str());
+	if(textbuf)
+	{
+		char *text = textbuf->text();
+		if(highlight)	gr->Highlight(e->graph->FMGL->get_last_id());		// TODO check highlight
+		Parse->Execute(gr,text);
+//		gr->Highlight(-1);
+		free(text);
+	}
+	// TODO go to line with warning?!!
+	message_set(gr->Message(), e);
+	if(e && e->rtab)	e->rtab->value(e->gplot);
+	return 0;
+}
+//-----------------------------------------------------------------------------
+void Fl_MGL::update()
+{
+	// NOTE: hint for old style View(). May be I should remove it!
+	char *text = textbuf->text();
+	if(script.empty() || !text || !strstr(text,"rotate"))
+		mgl_rotate(gr->get_graph(),0,0,0);
+
+	gr->update();
+	for(long i=0;i<Parse->GetNumVar();i++)
+	{
+		mglDataA *v = Parse->GetVar(i);
+		if(v && v->o)	((TableWindow *)v->o)->update(v);
+	}
+}
+//-----------------------------------------------------------------------------
+void add_suffix(char *fname, const char *ext)
+{
+	long n=strlen(fname);
+	if(n>4 && fname[n-4]=='.')
+	{	fname[n-3]=ext[0];	fname[n-2]=ext[1];	fname[n-1]=ext[2];	}
+	else	{	strcat(fname,".");	strcat(fname,ext);	}
+}
+//-----------------------------------------------------------------------------
+class ArgsDlg : public GeneralDlg
+{
+	Fl_Input *arg[10];
+public:
+	void cb_ok()
+	{
+		for(int i=0;i<10;i++)	Parse->AddParam(i,arg[i]->value());
+		hide();
+	}
+	void set(int id, const char *val)
+	{
+		if(id>=0 && id<10)
+		{	arg[id]->value(val);	Parse->AddParam(id,val);	}
+	}
+	void init()
+	{	// NOTE I'm not sure that I need to get current arguments. So keep function empty.
+	}
+	ArgsDlg() : GeneralDlg()
+	{
+		w = new Fl_Double_Window(290, 320, _("Set script arguments"));
+		arg[1] = new Fl_Input(5, 20, 135, 30, _("String for $1"));
+		arg[1]->align(FL_ALIGN_TOP_LEFT);
+		arg[2] = new Fl_Input(150, 20, 135, 30, _("String for $2"));
+		arg[2]->align(FL_ALIGN_TOP_LEFT);
+		arg[3] = new Fl_Input(5, 75, 135, 30, _("String for $3"));
+		arg[3]->align(FL_ALIGN_TOP_LEFT);
+		arg[4] = new Fl_Input(150, 75, 135, 30, _("String for $4"));
+		arg[4]->align(FL_ALIGN_TOP_LEFT);
+		arg[5] = new Fl_Input(5, 130, 135, 30, _("String for $5"));
+		arg[5]->align(FL_ALIGN_TOP_LEFT);
+		arg[6] = new Fl_Input(150, 130, 135, 30, _("String for $6"));
+		arg[6]->align(FL_ALIGN_TOP_LEFT);
+		arg[7] = new Fl_Input(5, 185, 135, 30, _("String for $7"));
+		arg[7]->align(FL_ALIGN_TOP_LEFT);
+		arg[8] = new Fl_Input(150, 185, 135, 30, _("String for $8"));
+		arg[8]->align(FL_ALIGN_TOP_LEFT);
+		arg[9] = new Fl_Input(5, 240, 135, 30, _("String for $9"));
+		arg[9]->align(FL_ALIGN_TOP_LEFT);
+		arg[0] = new Fl_Input(150, 240, 135, 30, _("String for $0"));
+		arg[0]->align(FL_ALIGN_TOP_LEFT);
+		Fl_Button* o = new Fl_Button(60, 290, 75, 25, _("Cancel"));
+		o->callback(cb_dlg_cancel, this);
+		o = new Fl_Return_Button(155, 290, 75, 25, _("Set"));
+		o->callback(cb_dlg_ok, this);
+		w->set_modal();	w->end();
+	}
+} args_dlg;
+//-----------------------------------------------------------------------------
+void args_dlg_cb(Fl_Widget *, void *)	{	args_dlg.show();	}
+void argument_set(int id, const char *val)	{	args_dlg.set(id,val);	}
+//-----------------------------------------------------------------------------
+void cb_anim_put(Fl_Widget *, void *);
+void cb_dlg_only(Fl_Widget*,void *v)	{	((Fl_Round_Button*)v)->setonly();	}
+class AnimateDlg : public GeneralDlg
+{
+public:
+	Fl_MGL* dr;
+	AnimateDlg() : GeneralDlg()
+	{
+		w = new Fl_Double_Window(335, 350, _("Animation"));
+		new Fl_Box(10, 5, 315, 25, _("Redraw picture for $0 equal to"));
+		rt = new Fl_Round_Button(10, 30, 200, 25, _("strings"));
+		rt->callback(cb_dlg_only, rt);
+		rv = new Fl_Round_Button(220, 30, 105, 25, _("values"));
+		rv->callback(cb_dlg_only, rv);
+		txt = new Fl_Multiline_Input(10, 60, 200, 250);
+		x0 = new Fl_Float_Input(220, 80, 105, 25, _("from"));			x0->align(FL_ALIGN_TOP_LEFT);
+		x1 = new Fl_Float_Input(220, 130, 105, 25, _("to"));			x1->align(FL_ALIGN_TOP_LEFT);
+		dx = new Fl_Float_Input(220, 180, 105, 25, _("with step"));	dx->align(FL_ALIGN_TOP_LEFT);
+
+		Fl_Button *o;
+		o = new Fl_Button(230, 215, 80, 25, _("Cancel"));	o->callback(cb_dlg_cancel, this);
+		o = new Fl_Return_Button(230, 250, 80, 25, _("OK"));o->callback(cb_dlg_ok, this);
+		save = new Fl_Check_Button(220, 285, 105, 25, _("save slides"));
+		save->tooltip(_("Keep slides in memory (faster animation but require more memory)"));
+		save->down_box(FL_DOWN_BOX);	save->deactivate();
+
+		o = new Fl_Button(10, 315, 100, 25, _("Put to script"));	o->callback(cb_anim_put,w);
+		dt = new Fl_Float_Input(220, 315, 105, 25, _("Delay (in sec)"));//	dx->align(FL_ALIGN_TOP_LEFT);
+		w->end();
+	}
+	void init()
+	{
+		if(e)	dr = e->draw;
+		if(dr && dr->da*(dr->a2-dr->a1)>0)
+		{
+			char buf[128];	rv->setonly();
+			snprintf(buf,127,"%g",dr->a1);	x0->value(buf);
+			snprintf(buf,127,"%g",dr->a2);	x1->value(buf);
+			snprintf(buf,127,"%g",dr->da);	dx->value(buf);
+		}
+		else if(dr)
+		{
+			rt->setonly();
+			std::string str;
+			for(size_t i=0;i<dr->anim.size();i++)
+				str += dr->anim[i]+'\n';
+			txt->value(str.c_str());
+		}
+	}
+	void prepare()
+	{
+		result.clear();
+		if(dr)	dr->anim.clear();
+		if(rv->value())
+		{
+			const char *s1=x0->value(), *s2=x1->value(), *s3=dx->value();
+			double a1=s1?atof(s1):NAN, a2=s2?atof(s2):NAN, a3=s3?atof(s3):1;
+			if(a3*(a2-a1)>0)
+			{
+				result = result + "##c "+s1+' '+s2+' '+(s3?s3:"1")+'\n';
+				if(dr)
+				{
+					dr->a1=a1;	dr->a2=a2;	dr->da=a3;
+					for(double a=a1;a3*(a2-a)>=0;a+=a3)
+					{
+						char buf[128];	snprintf(buf,128,"%g",a);
+						dr->anim.push_back(buf);
+					}
+				}
+			}
+			else	fl_alert(_("Incompatible loop parameters!"));
+		}
+		else if(rt->value())
+		{
+			const char *s = txt->value();
+			while(s && *s)
+			{
+				const char *j = strchr(s,'\n');
+				size_t len = j?(j-s):strlen(s);
+				std::string val(s,len);
+				if(dr)	dr->anim.push_back(val);
+				result = result+"##a "+val+'\n';
+				s=j?j+1:NULL;
+			}
+		}
+		else	fl_message(_("No selection. So nothing to do"));
+
+	}
+	void into_script()
+	{
+		prepare();
+		if(e)
+		{
+			int p = textbuf->line_start(e->editor->insert_position());
+			textbuf->insert(p, (result+'\n').c_str());
+		}
+	}
+	void cb_ok()
+	{
+		if(!dr)	return;
+		prepare();
+		const char *s = dt->value();
+		if(s && *s)	dr->delay = atof(s);
+		hide();
+	}
+protected:
+	bool swap;
+	Fl_Round_Button *rt, *rv;
+	Fl_Multiline_Input *txt;
+	Fl_Float_Input *x0, *x1, *dx, *dt;
+	Fl_Check_Button *save;
+	void create_dlg();
+} animate_dlg;
+//-----------------------------------------------------------------------------
+void animate_dlg_cb(Fl_Widget *, void *v)
+{	animate_dlg.e = (ScriptWindow*)v;	animate_dlg.show();	}
+void cb_anim_put(Fl_Widget *, void *)	{	animate_dlg.into_script();	}
+//-----------------------------------------------------------------------------
+bool animate_cb(Fl_MGL *d)
+{	animate_dlg.dr = d;	animate_dlg.show();	return animate_dlg.wait();	}
+//-----------------------------------------------------------------------------
+void fill_animate(const char *text, Fl_MGL *dr)
+{
+	char tmp[4]="#$0";
+	for(int i=0;i<10;i++)	// first read script arguments (if one)
+	{
+		tmp[2] = '0'+i;
+		const char *str=strstr(text,tmp);
+		if(str)
+		{
+			str+=3;
+			while(*str>0 && *str<=' ' && *str!='\n')	str++;
+			if(*str>' ')
+			{
+				size_t j=0;	while(str[j]>' ')	j++;
+				std::string val(str,j);
+				argument_set(i,val.c_str());
+			}
+		}
+	}
+	dr->anim.clear();	dr->a1=dr->a2=0;	dr->da=1;	// reset animation
+	const char *str = strstr(text, "##c");
+	if(str)	// this is animation loop
+	{
+		double a1=0, a2=0, da=1;
+		int res=sscanf(str+3, "%lg%lg%lg", &a1, &a2, &da);
+		da = res<3?1:da;
+		if(res>2 && da*(a2-a1)>0)
+		{
+			dr->a1=a1;	dr->a2=a2;	dr->da=da;
+			for(double a=a1;da*(a2-a)>=0;a+=da)
+			{
+				char buf[128];	snprintf(buf,128,"%g",a);
+				dr->anim.push_back(buf);
+			}
+			return;
+		}
+	}
+	str = strstr(text, "##a");
+	while(str)
+	{
+		str += 3;
+		while(*str>0 && *str<=' ' && *str!='\n')	str++;
+		if(*str>' ')
+		{
+			size_t j=0;	while(str[j]>' ')	j++;
+			std::string val(str,j);
+			dr->anim.push_back(val);
+		}
+		str = strstr(str, "##a");
+	}
+}
+//-----------------------------------------------------------------------------
+Fl_Text_Display::Style_Table_Entry stylemess[2] = {	// Style table
+	{ FL_BLACK,		FL_COURIER,		12, 0 },		// A - Plain
+	{ FL_RED,		FL_COURIER,		12, 0 } };		// B - Strings
+void mess_parse(const char *text, char *style, int /*length*/)
+{
+	size_t n=strlen(text);
+	// Style letters: A - Plain; B - Error
+	for(size_t i=0;i<n;i++)	style[i] = 'A';
+	const char *l1=text, *l2=strchr(l1, '\n');
+	while(l1)
+	{
+		size_t len = l2?l2-l1:strlen(l1), st=l1-text;
+		const char *p = strstr(l1,"in line");
+		if(p && size_t(p-l1)<len)
+			for(size_t i=0;i<len;i++)	style[i+st]='B';
+		l1=l2?l2+1:NULL;	l2=l1?strchr(l1, '\n'):NULL;
+	}
+}
+//-----------------------------------------------------------------------------
+static Fl_Text_Buffer *sbuf=0;
+void mess_update(int pos, int nInserted, int nDeleted, int, const char *, void *cbArg)
+{
+	Fl_Text_Buffer *mbuf=((Fl_Text_Editor *)cbArg)->buffer();
+	long	start, end;	// Start and end of text
+	char last, *style, *text;		// Text data
+	if (nInserted == 0 && nDeleted == 0) {	sbuf->unselect();	return;  }
+	if (nInserted > 0)
+	{
+		style = new char[nInserted + 1];
+		memset(style, 'A', nInserted);
+		style[nInserted] = '\0';
+		sbuf->replace(pos, pos + nDeleted, style);
+		delete[] style;
+	}
+	else	sbuf->remove(pos, pos + nDeleted);
+	sbuf->select(pos, pos + nInserted - nDeleted);
+	start = mbuf->line_start(pos);
+	end   = mbuf->line_end(pos + nInserted);
+	text  = mbuf->text_range(start, end);
+	style = sbuf->text_range(start, end);
+	if (start==end)	last = 0;
+	else	last = style[end-start-1];
+	mess_parse(text, style, end - start);
+	sbuf->replace(start, end, style);
+	((Fl_Text_Editor *)cbArg)->redisplay_range(start, end);
+
+	if (start==end || last != style[end-start-1])
+	{
+		// Either the user deleted some text, or the last character on
+		// the line changed styles, so reparse the remainder of the buffer...
+		free(text);	free(style);
+		end   = mbuf->length();
+		text  = mbuf->text_range(start, end);
+		style = sbuf->text_range(start, end);
+		mess_parse(text, style, end - start);
+		sbuf->replace(start, end, style);
+		((Fl_Text_Editor *)cbArg)->redisplay_range(start, end);
+	}
+	free(text);	free(style);
+}
+//-----------------------------------------------------------------------------
+void style_unfinished_cb(int, void*);
+void cb_mess_copy(Fl_Widget*,void *v);
+void cb_mess_jump(Fl_Widget*,void *v);
+class MessDlg : public GeneralDlg
+{
+	Fl_Text_Display *mess;
+	Fl_Text_Buffer *mbuf;
+	int pos, last;
+public:
+	MessDlg() : GeneralDlg()
+	{
+		Fl_Button *o;
+		w = new Fl_Double_Window(500, 195, _("MGL messages"));
+		mess = new Fl_Text_Display(30, 5, 460, 190);
+		o = new Fl_Return_Button(5,5,25,25);	o->callback(cb_mess_jump,e);
+		o = new Fl_Button(5,35,25,25);	o->callback(cb_mess_copy,e);	o->image(img_copy);
+		w->end();	w->resizable(mess);
+		mbuf = new Fl_Text_Buffer;	sbuf = new Fl_Text_Buffer;
+		mess->buffer(mbuf);	pos=last=0;
+		mess->highlight_data(sbuf, stylemess, sizeof(stylemess) / sizeof(stylemess[0]), 'A', style_unfinished_cb, 0);
+		mbuf->add_modify_callback(mess_update, mess);
+		mbuf->call_modify_callbacks();
+	}
+	void copy()
+	{
+		char *s = mbuf->selection_text();
+		if(s && *s==0)	{	free(s);	s=0;	}
+		if(!s)	s = mbuf->text();
+		Fl::copy(s,strlen(s),1);	free(s);
+	}
+	void jump()
+	{
+		if(!e)	return;
+		char *s = mbuf->text();
+		if(*s==0)	{	free(s);	return;	}
+		int ipos = mess->line_start(mess->insert_position());
+		if(ipos!=last)	last=pos=ipos;
+
+		int id=-1;
+		const char *p = strstr(s+pos,"in line");
+		if(p)	{	pos = p-s+7;	id = atoi(p+8);	}
+		else	// try from beginning
+		{
+			p = strstr(s,"in line");
+			if(p)	{	pos = p-s+7;	id = atoi(p+8);	}
+		}
+		free(s);
+
+		if(id>=0)
+		{
+			Fl_Text_Editor::kf_ctrl_move(FL_Home, e->editor);
+			for(int i=0;i<id;i++)	Fl_Text_Editor::kf_down(0, e->editor);
+			Fl_Text_Editor::kf_up(0, e->editor);
+			Fl::focus(e->editor);
+		}
+	}
+	void set(const char *s)
+	{	mbuf->text(s);	show();	}
+} mess_wnd;
+//-----------------------------------------------------------------------------
+void message_cb(Fl_Widget*,void *v)
+{	animate_dlg.e = (ScriptWindow*)v;	mess_wnd.show();	}
+//-----------------------------------------------------------------------------
+void message_set(const char *s, ScriptWindow *e)
+{	mess_wnd.e = e;	if(s && *s)	mess_wnd.set(s);	else	mess_wnd.hide();	}
+//-----------------------------------------------------------------------------
+void cb_mess_copy(Fl_Widget*,void *v)	{	mess_wnd.copy();	}
+//-----------------------------------------------------------------------------
+void cb_mess_jump(Fl_Widget*,void *v)	{	mess_wnd.jump();	}
+//-----------------------------------------------------------------------------
diff --git a/mgllab/mgl.xml.in b/mgllab/mgl.xml.in
new file mode 100644
index 0000000..325aaac
--- /dev/null
+++ b/mgllab/mgl.xml.in
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
+  <mime-type type="text/mgl">
+    <alias type="text/x.mgl"/>
+    <alias type="text/x-mgl"/>
+    <comment>MGL script</comment>
+    <icon name="${CMAKE_INSTALL_PREFIX}/share/pixmaps/udav.png"/>
+    <glob pattern="*.mgl"/>
+  </mime-type>
+</mime-info>
diff --git a/mgllab/mgllab.cpp b/mgllab/mgllab.cpp
new file mode 100644
index 0000000..425cd27
--- /dev/null
+++ b/mgllab/mgllab.cpp
@@ -0,0 +1,676 @@
+/* main.cpp is part of UDAV
+ * Copyright (C) 2007-2014 Alexey Balakin <mathgl.abalakin at gmail.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License
+ * as published by the Free Software Foundation
+ *
+ * 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
+ */
+#include <ctype.h>
+#include <errno.h>
+#include <locale.h>
+#include <getopt.h>
+#include "mgllab.h"
+#include <Fl/Fl_Spinner.H>
+#include <Fl/Fl_Output.H>
+#include <Fl/Fl_Select_Browser.H>
+#include <Fl/Fl_Printer.H>
+//-----------------------------------------------------------------------------
+#ifndef MGL_DOC_DIR
+#ifdef WIN32
+#define MGL_DOC_DIR ""
+#else
+#define MGL_DOC_DIR "/usr/local/share/doc/mathgl/"
+#endif
+#endif
+//-----------------------------------------------------------------------------
+//int num_windows = 0, auto_exec=1, plastic_scheme=1, internal_font=0;
+int num_windows = 0;
+int auto_exec;
+int exec_save;
+int highlight;
+int mouse_zoom;
+int use_thr;
+int complete_word;
+std::string docdir;
+std::string helpname;
+std::string fontname;
+int lang;
+int scheme;
+std::string lastfiles[5];
+Fl_Preferences pref(Fl_Preferences::USER,"abalakin","mgllab");
+//-----------------------------------------------------------------------------
+#define NUM_LOCALE	4
+const char *sch[4]={"base","gtk+","plastic","gleam"};
+const char *loc[]={"en_EN.UTF8",	"ru_RU.utf8",	"ru_RU.cp1251",	"es_ES.utf8",	""};
+const char *hlp[]={"mgl_en.html#","mgl_ru.html#", "mgl_ru.html#", "mgl_en.html#",	""};
+void set_scheme_lang(int s, int l)
+{
+	if(s<0 || s>3)	s=1;
+	if(l<0 || l>NUM_LOCALE-1)	l=1;
+	mgl_textdomain(NULL,loc[l]);
+	Fl::scheme(sch[s]);
+	scheme = s;	lang = l;
+#ifdef WIN32
+	char sep = '\\';
+#else
+	char sep = '/';
+#endif
+	helpname = docdir+sep+hlp[l];
+}
+//-----------------------------------------------------------------------------
+void save_pref()
+{
+	pref.set("locale",lang);
+	pref.set("scheme",scheme);
+	pref.set("help_dir",docdir.c_str());
+	pref.set("auto_exec",auto_exec);
+	pref.set("exec_save",exec_save);
+	pref.set("highlight",highlight);
+	pref.set("mouse_zoom",mouse_zoom);
+	pref.set("use_thr", use_thr);
+	pref.set("font_kind",font_kind);
+	pref.set("font_size",font_size);
+	pref.set("complete_word",complete_word);
+	pref.set("font_name",fontname.c_str());
+	pref.set("fname1",lastfiles[0].c_str());
+	pref.set("fname2",lastfiles[1].c_str());
+	pref.set("fname3",lastfiles[2].c_str());
+	pref.set("fname4",lastfiles[3].c_str());
+	pref.set("fname5",lastfiles[4].c_str());
+}
+//-----------------------------------------------------------------------------
+void load_pref(ScriptWindow *w)
+{
+	static char *s=0;
+	pref.get("locale",lang,1);
+	pref.get("scheme",scheme,2);
+	pref.get("help_dir",s,MGL_DOC_DIR);
+	if(s)	{	docdir=s;	free(s);	}
+	pref.get("auto_exec",auto_exec,1);
+	pref.get("exec_save",exec_save,1);
+	pref.get("highlight",highlight,1);
+	pref.get("mouse_zoom",mouse_zoom,0);
+	pref.get("use_thr",use_thr,1);
+	pref.get("complete_word",complete_word,1);
+	pref.get("font_kind",font_kind,1);
+	pref.get("font_size",font_size,14);
+	set_style(font_kind, font_size);
+	pref.get("font_name",s,"");
+	if(s)	{	fontname=s;	free(s);	}
+	pref.get("fname1",s,"");	if(s)	{	lastfiles[0]=s;	free(s);	}
+	pref.get("fname2",s,"");	if(s)	{	lastfiles[1]=s;	free(s);	}
+	pref.get("fname3",s,"");	if(s)	{	lastfiles[2]=s;	free(s);	}
+	pref.get("fname4",s,"");	if(s)	{	lastfiles[3]=s;	free(s);	}
+	pref.get("fname5",s,"");	if(s)	{	lastfiles[4]=s;	free(s);	}
+	set_scheme_lang(scheme,lang);	// NOTE: must be after setting docdir
+	if(w && w->graph)
+	{
+		w->graph->FMGL->use_pthr = use_thr;
+		mgl_load_font(w->graph->get_graph(),fontname.c_str(),NULL);
+		example_cb(NULL, w);
+		w->graph->parent()->show();
+	}
+}
+//-----------------------------------------------------------------------------
+void set_title(Fl_Window* w)
+{
+	static std::string title;
+	if (filename.empty()) title=_("Untitled");
+	else
+	{
+		size_t sep = filename.find_last_of('/');
+#ifdef WIN32
+		if(sep==std::string::npos)
+			sep = filename.find_last_of('\\');
+#endif
+		if(sep!=std::string::npos)	title = filename.substr(sep+1);
+		else	title = filename;
+	}
+	if(changed)	title += " *";
+	title = title + " - mgllab";
+	w->label(title.c_str());
+}
+//-----------------------------------------------------------------------------
+void close_dlg_cb(Fl_Widget *, void *v)	{	((Fl_Window *)v)->hide();	}
+//-----------------------------------------------------------------------------
+void fname_cb(Fl_Widget*, void *v)
+{
+	ScriptWindow* e = (ScriptWindow*)v;
+	const char *file = mgl_file_chooser(_("Insert file name?"));
+	if(file)
+	{
+		char *str = new char[strlen(file)+4];
+		snprintf(str,strlen(file)+4," '%s'",file);
+		e->editor->insert(str);
+		delete []str;
+	}
+}
+//-----------------------------------------------------------------------------
+void new_cb(Fl_Widget*, void*)
+{
+	if (!check_save()) return;
+	filename[0] = '\0';
+	textbuf->select(0, textbuf->length());
+	textbuf->remove_selection();
+	changed = 0;
+	textbuf->call_modify_callbacks();
+}
+//-----------------------------------------------------------------------------
+void open_cb(Fl_Widget*, void *v)
+{
+	if (!check_save()) return;
+	char *lastname=0;
+	const char *newfile = mgl_file_chooser(_("Open File?"),
+		_("MGL files \t*.mgl\nDAT files \t*.{dat,csv}"));
+	if(lastname)	free(lastname);
+	if(newfile != NULL)
+	{
+		ScriptWindow* e = (ScriptWindow*)v;
+		load_file(newfile, -1,e);
+		if(auto_exec)	e->graph->update();
+	}
+}
+//-----------------------------------------------------------------------------
+void close_cb(Fl_Widget*, void* v)
+{
+	Fl_Window* w = (Fl_Window*)v;
+	if (num_windows == 1 && !check_save())	return;
+
+	w->hide();
+	textbuf->remove_modify_callback(changed_cb, w);
+	delete w;
+	num_windows--;
+	if (!num_windows) exit(0);
+}
+//-----------------------------------------------------------------------------
+void quit_cb(Fl_Widget*, void*)
+{
+	if (changed && !check_save())	return;
+	exit(0);
+}
+//-----------------------------------------------------------------------------
+void save_cb(Fl_Widget*w, void*v)
+{
+	if(filename.empty())	{	saveas_cb(w,v);	return;	}	// No filename - get one!
+	else save_file(filename.c_str(),(ScriptWindow*)v);
+}
+//-----------------------------------------------------------------------------
+void saveas_cb(Fl_Widget*, void *v)
+{
+	const char *newfile;
+	char *fname=0;
+	FILE *fp=0;
+	while(1)
+	{
+		newfile = mgl_file_chooser(_("Save File As?"), _("MGL files \t*.mgl"), true);
+		if(!newfile || !newfile[0])	break;
+		if(!strchr(newfile,'.'))
+		{
+			if(fname)	delete []fname;
+			fname = new char[strlen(newfile)+5];
+			strcpy(fname,newfile);	strcat(fname,".mgl");
+			newfile = fname;
+		}
+		fp = fl_fopen(newfile,"r");
+		if(fp)
+		{
+			fclose(fp);
+			if(fl_choice(_("File is exesist. Overwrite it?"),0,_("No"),_(" Yes "))==2)
+				break;
+		}
+		else	break;
+	}
+	if (newfile != NULL)	save_file(newfile, (ScriptWindow*)v);
+	if(fname)	delete []fname;
+}
+//-----------------------------------------------------------------------------
+ScriptWindow *new_view();
+void view_cb(Fl_Widget*, void*)
+{	Fl_Window* w = new_view();	w->show();	}
+//-----------------------------------------------------------------------------
+void hint_cb(Fl_Widget*, void*)	{}
+void lastfile1_cb(Fl_Widget*, void *v)
+{	if (!check_save()) return;
+	load_file(lastfiles[0].c_str(),-1,(ScriptWindow*)v);	}
+void lastfile2_cb(Fl_Widget*, void *v)
+{	if (!check_save()) return;
+	load_file(lastfiles[1].c_str(),-1,(ScriptWindow*)v);	}
+void lastfile3_cb(Fl_Widget*, void *v)
+{	if (!check_save()) return;
+	load_file(lastfiles[2].c_str(),-1,(ScriptWindow*)v);	}
+void lastfile4_cb(Fl_Widget*, void *v)
+{	if (!check_save()) return;
+	load_file(lastfiles[3].c_str(),-1,(ScriptWindow*)v);	}
+void lastfile5_cb(Fl_Widget*, void *v)
+{	if (!check_save()) return;
+	load_file(lastfiles[4].c_str(),-1,(ScriptWindow*)v);	}
+//-----------------------------------------------------------------------------
+void print_plot_cb(Fl_Widget*,void *v)
+{
+	ScriptWindow *w = (ScriptWindow*)v;
+	Fl_Printer *p = new Fl_Printer;
+	if(!p->start_job(1) && !p->start_page())
+	{
+		int wp,hp, ww=w->graph->FMGL->w(), hh=w->graph->FMGL->h();
+		p->printable_rect(&wp,&hp);
+		double s=1, sw=double(wp)/ww, sh=double(hp)/hh;
+		if(sw<s)	s=sw;
+		if(sh<s)	s=sh;
+//		if(sw<sh)	p->rotate(90);	// TODO add rotation ???
+		p->scale(s,s);
+		p->print_widget(w->graph->FMGL);
+		p->end_page();		p->end_job();
+	}
+	delete p;
+}
+//-----------------------------------------------------------------------------
+Fl_Menu_Item menuitems[] = {
+	{_("File"), 0, 0, 0, FL_SUBMENU},
+		{_("New script"), 0, new_cb},
+		{_("Open file ..."), FL_CTRL+'o', open_cb},
+		{_("Save file"), FL_CTRL+'s', save_cb},
+		{_("Save as ..."), 0, saveas_cb, 0, FL_MENU_DIVIDER},
+		{_("Print plot"), 0, print_plot_cb, 0, FL_MENU_DIVIDER},
+		{_("Recent files"), 0, 0, 0, FL_SUBMENU|FL_MENU_DIVIDER},
+			{"1.", 0, lastfile1_cb},
+			{"2.", 0, lastfile2_cb},
+			{"3.", 0, lastfile3_cb},
+			{"4.", 0, lastfile4_cb},
+			{"5.", 0, lastfile5_cb},
+			{0},
+		{_("Exit"), 0, quit_cb},
+		{0},
+	{_("Edit"), 0, 0, 0, FL_SUBMENU},
+		{_("Undo"), FL_CTRL+'z', undo_cb},
+		{_("Cut text"), FL_CTRL+'x', cut_cb},
+		{_("Copy text"), FL_CTRL+'c', copy_cb},
+		{_("Paste text"), FL_CTRL+'v', paste_cb},
+		{_("Select all"), FL_CTRL+'a', select_all_cb, 0, FL_MENU_DIVIDER},
+		{_("Hidden plots"), FL_CTRL+'d', hide_cb},
+		{_("Show lines"), FL_CTRL+FL_SHIFT+'d', unhide_cb, 0, FL_MENU_DIVIDER},
+		{_("Find|Replace"), FL_CTRL+'f', find_dlg_cb},
+		{_("Find next"), FL_F+3, find_next_cb, 0, FL_MENU_DIVIDER},
+		{_("Insert"), 0, 0, 0, FL_SUBMENU},
+			{_("File path"), FL_META+'p', ins_path_cb},
+			{_("Folder path"), 0, ins_fname_cb},
+			{_("Command"), FL_META+'c', newcmd_dlg_cb},
+			{_("Inplot"), FL_META+'i', inplot_dlg_cb},
+			{_("Fitted formula"), FL_META+'f', ins_fits_cb},
+			{_("Manual primitives"), 0, ins_prim_cb},
+			{_("Plot style"), 0, style_dlg_cb},
+			{_("Options"), FL_META+'o', option_dlg_cb},
+			{0},
+	// TODO{_("Selection"), 0,  0, 0, FL_SUBMENU|FL_MENU_DIVIDER},
+		// TODO{_("Hide"), 0,  0},
+		// TODO{_("Delete"), 0,  0},
+		// TODO{_("Move up"), 0,  0},
+		// TODO{_("Move down"), 0,  0},
+		// TODO{_("Show hidden"), FL_F+8,  0, 0, FL_MENU_TOGGLE},
+		{0},
+	{_("Graphics"), 0, 0, 0, FL_SUBMENU},
+		{0},
+	{_("Setup"), 0, 0, 0, FL_SUBMENU},
+		{_("Properties"), 0, prop_dlg_cb},
+		{_("Set arguments"), 0, args_dlg_cb},
+		{_("Setup animation"), 0, animate_dlg_cb},
+		{_("Plot setup"), FL_META+'g', setup_dlg_cb, 0, FL_MENU_DIVIDER},
+		{_("Calculator"), FL_F+4, calc_dlg_cb},
+		{_("Messages"), FL_F+2, message_cb},
+		{0},
+	{_("Help"), 0, 0, 0, FL_SUBMENU},
+		{_("Help"), FL_F+1, help_cb},
+		{_("Hints"), 0, hint_dlg_cb},
+		{_("About"), 0, about_cb},
+		{_("Icon list"), 0, iconlist_cb},	// TODO remove before release
+		{0},
+	{0}
+};
+//-----------------------------------------------------------------------------
+void mem_upd_cb(Fl_Widget *, void *v)
+{	((ScriptWindow*)v)->mem_init();	}
+//-----------------------------------------------------------------------------
+extern Fl_RGB_Image img_udav;
+ScriptWindow *new_view()
+{
+	Fl_Group *gg;
+	ScriptWindow *w = new ScriptWindow(930, 510, _("Untitled - mgllab"));
+	w->begin();
+	w->menu = new Fl_Menu_Bar(0, 0, 930, 30);
+	w->menu->copy(menuitems, w);
+	w->label(_("Untitled - mgllab"));
+
+	Fl_Tile *t = new Fl_Tile(0,30,930,455);
+	add_editor(w);
+
+	w->rtab = new Fl_Tabs(300,30,630,455,0);
+	w->gplot = new Fl_Group(300,30,630,430,_("Canvas"));
+	w->graph = new Fl_MGLView(300,30,630,430,_("Canvas"));
+	w->gplot->resizable(w->graph);	w->gplot->end();	w->graph->adjust();
+	w->ghelp = new Fl_Group(300,30,630,430,_("Help"));
+	add_help(w);	w->ghelp->end();	w->ghelp->hide();
+	gg = new Fl_Group(300,30,630,430,_("Memory"));	gg->hide();
+	add_mem(w);		gg->end();
+	w->rtab->end();
+
+//	w->status = new Fl_Output(0,485,930,25);
+	w->status = new Fl_Box(0,485,930,25);	w->status->box(FL_ENGRAVED_BOX);
+	w->status->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
+	w->set_status(_("Ready"));
+	w->draw = new Fl_MGL(w->graph);	w->draw->e = w;
+	mgl_makemenu_fltk(w->menu, w->graph);
+	w->menu->add(_("Graphics/Primitive"), FL_CTRL+'m', prim_dlg_cb, w);
+	w->menu->add(_("Graphics/Animation/Setup animation"), 0, animate_dlg_cb, w);
+	int index = w->menu->find_index(_("Graphics/Pause calc"));
+	if(index>=0)	w->menu->remove(index);
+//	m->add(_("Graphics/Pause calc"), "^t", mgl_pause_cb, w, FL_MENU_TOGGLE);
+
+
+	t->end();	w->end();	w->resizable(t);
+	w->rtab->callback(mem_upd_cb, w);
+	w->callback(close_cb, w);	w->icon(&img_udav);
+	num_windows++;	return w;
+}
+//-----------------------------------------------------------------------------
+void argument_set(int n, const char *s);
+int main(int argc, char **argv)
+{
+//	Fl::lock();
+	mgl_ask_func = mgl_ask_fltk;
+	load_pref(NULL);
+	
+	textbuf = new Fl_Text_Buffer;
+	style_init();
+	textbuf->tab_distance(4);
+	ScriptWindow *w = new_view();
+	Fl::visual(FL_DOUBLE|FL_RGB);
+	load_pref(w);
+	int ir = w->menu->find_index(_("File/Recent files"));
+	if(ir<0)	ir = 6;
+	w->menu->replace(ir+1, lastfiles[0].c_str());
+	w->menu->replace(ir+2, lastfiles[1].c_str());
+	w->menu->replace(ir+3, lastfiles[2].c_str());
+	w->menu->replace(ir+4, lastfiles[3].c_str());
+	w->menu->replace(ir+5, lastfiles[4].c_str());
+	int sh;	pref.get("show_hint",sh,1);
+	if(sh)	hint_dlg_cb(0,0);
+
+	std::string fname;
+	while(1)
+	{
+		char ch = getopt(argc, argv, "1:2:3:4:5:6:7:8:9:ho:L:");
+		if(ch>='1' && ch<='9')	argument_set(ch-'0', optarg);
+		else if(ch=='L')
+		{	setlocale(LC_CTYPE, optarg);	setlocale(LC_NUMERIC, "C");	}
+		else if(ch=='h')
+		{
+			printf(_("mgllab draw mgl script interactively.\nCurrent version is 2.%g\n"),MGL_VER2);
+			printf(_("Usage:\tmgllab [parameter(s)] scriptfile\n"));
+			printf(_("\t-1 str       set str as argument $1 for script\n"
+					"\t...          ...\n"
+					"\t-9 str       set str as argument $9 for script\n"
+					"\t-L loc       set locale to loc\n"
+//					"\t-            get script from standard input\n"
+					"\t-h           print this message\n") );
+			return 0;
+		}
+		// NOTE: I will not parse stdin here
+		else if(ch==-1)
+		{	if(optind<argc)	fname = argv[optind];
+			break;	}
+	}
+
+	w->show(1, argv);
+	if(!fname.empty() && fname[0]!='-')
+	{
+		load_file(fname.c_str(), -1,w);
+		if(auto_exec)	w->graph->update();
+	}
+	return Fl::run();
+}
+//-----------------------------------------------------------------------------
+void cb_filech(Fl_Widget*, void *v);
+class PropDlg : public GeneralDlg
+{
+	friend void cb_filech(Fl_Widget*, void *v);
+	Fl_Choice *fkind;
+	Fl_Spinner *fsize;
+	Fl_File_Input *help_path;
+	Fl_File_Input *font_path;
+	Fl_Check_Button *auto_exec_w;
+	Fl_Check_Button *exec_save_w;
+	Fl_Check_Button *complete_w;
+	Fl_Check_Button *highlight_w;
+	Fl_Check_Button *mouse_zoom_w;
+	Fl_Check_Button *use_thr_w;
+	Fl_Choice *lang_w;
+	Fl_Choice *scheme_w;
+public:
+	HMGL gr;
+	PropDlg() : GeneralDlg()
+	{
+		Fl_Button *o;
+		w = new Fl_Double_Window(340, 390, _("Properties"));
+		w->align(Fl_Align(FL_ALIGN_CLIP|FL_ALIGN_INSIDE));
+		fkind = new Fl_Choice(75, 10, 90, 25, _("Font kind"));
+		fkind->add("Helvetica");	fkind->add("Courier");	fkind->add("Times");
+		fsize = new Fl_Spinner(245, 10, 90, 25, _("Font size"));
+		help_path = new Fl_File_Input(5, 55, 305, 35, _("Path for help files"));
+		help_path->align(FL_ALIGN_TOP_LEFT);
+		o = new Fl_Button(310, 65, 25, 25, "...");	o->callback(cb_filech, 0);
+		font_path = new Fl_File_Input(5, 110, 305, 35, _("Path for MathGL font (without extension)"));
+		font_path->align(FL_ALIGN_TOP_LEFT);
+		o = new Fl_Button(310, 120, 25, 25, "...");	o->callback(cb_filech, (void *)1);
+		auto_exec_w = new Fl_Check_Button(5, 145, 330, 25, _("Execute script after loading"));
+		exec_save_w = new Fl_Check_Button(5, 170, 330, 25, _("Save file before redrawing"));
+		complete_w = new Fl_Check_Button(5, 195, 330, 25, _("Enable keywords completion"));
+		highlight_w = new Fl_Check_Button(5, 220, 330, 25, _("Highlight current object(s)"));
+		mouse_zoom_w = new Fl_Check_Button(5, 245, 330, 25, _("Enable mouse wheel for zooming"));
+		use_thr_w = new Fl_Check_Button(5, 270, 330, 25, _("Use multi-threading for drawing"));
+		lang_w = new Fl_Choice(160, 300, 175, 25, _("Language for mgllab"));
+		for(long i=0;i<NUM_LOCALE;i++)	lang_w->add(loc[i]);
+		scheme_w = new Fl_Choice(160, 330, 175, 25, _("Widget scheme"));
+		scheme_w->add("base");	scheme_w->add("gtk+");	scheme_w->add("plastic");	scheme_w->add("gleam");
+		o = new Fl_Button(85, 360, 75, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
+		o = new Fl_Return_Button(180, 360, 75, 25, _("OK"));	o->callback(cb_dlg_ok,this);
+		w->set_modal();	w->end();
+	}
+	void init()
+	{
+		fkind->value(styletable[0].font/4);
+		fsize->value(styletable[0].size);
+		font_path->value(fontname.c_str());
+		help_path->value(docdir.c_str());
+		auto_exec_w->value(auto_exec);
+		exec_save_w->value(exec_save);
+		complete_w->value(complete_word);
+		highlight_w->value(highlight);
+		mouse_zoom_w->value(mouse_zoom);
+		use_thr_w->value(use_thr);
+		lang_w->value(lang);
+		scheme_w->value(scheme);
+	}
+	void cb_ok()
+	{
+		set_style(fkind->value(),fsize->value());
+		auto_exec = auto_exec_w->value();
+		exec_save = exec_save_w->value();
+		highlight = highlight_w->value();
+		mouse_zoom = mouse_zoom_w->value();
+		complete_word = complete_w->value();
+		use_thr = use_thr_w->value();
+		docdir = help_path->value();
+		fontname = font_path->value();
+		if(e->graph->get_graph())
+			mgl_load_font(e->graph->get_graph(),fontname.c_str(),NULL);
+		set_scheme_lang(scheme_w->value(),lang_w->value());	// NOTE: must be after setting docdir
+		example_cb(NULL, e);	e->graph->parent()->show();
+		save_pref();	hide();
+	}
+} prop_dlg;
+//-----------------------------------------------------------------------------
+void cb_filech(Fl_Widget*, void *v)
+{
+	if(v)
+	{
+		const char *s = mgl_file_chooser(_("Font file name"), "MGL font files \t*.vfm*");
+		if(s)
+		{	std::string ss = s;
+			size_t pos = ss.find(".vfm");
+			if(pos!=std::string::npos)	ss = ss.substr(0,pos);
+			prop_dlg.font_path->value(ss.c_str());	}
+	}
+	else
+	{
+		const char *s = mgl_dir_chooser(_("Folder for help files"), prop_dlg.help_path->value());
+		if(s)	prop_dlg.help_path->value(s);
+	}
+}
+void prop_dlg_cb(Fl_Widget *, void *v)
+{	prop_dlg.e = (ScriptWindow *)v;	prop_dlg.show();	}
+//-----------------------------------------------------------------------------
+void cb_calc_key(Fl_Widget *, void *v);
+void cb_calc_ins(Fl_Widget *, void *);
+void cb_calc_prev(Fl_Widget *, void *);
+void cb_calc_edit(Fl_Widget *, void *);
+void cb_calc_kind(Fl_Widget *, void *);
+void cb_calc_func(Fl_Widget *, void *);
+class CalcDlg : public GeneralDlg
+{
+public:
+	Fl_Input *edit;
+	Fl_Output *output;
+	Fl_Browser *prev;
+	Fl_Choice *kind;
+	Fl_Choice *func;
+	CalcDlg() : GeneralDlg()
+	{
+		Fl_Button *o;	Fl_Group* g, *gg;
+		w = new Fl_Double_Window(275, 275, _("Calculator"));
+		g = new Fl_Group(5, 5, 265, 25);
+		edit = new Fl_Input(5, 5, 240, 25);	//edit->callback(cb_calc_edit);
+		o = new Fl_Return_Button(245, 5, 25, 25, "@>");
+		o->callback(cb_calc_edit);	g->end();	g->resizable(edit);
+		g = new Fl_Group(5, 35, 265, 25);
+		output = new Fl_Output(30, 35, 145, 25, "@->");
+		o = new Fl_Button(180, 35, 90, 25, _("to script"));
+		o->callback(cb_calc_ins);	g->end();	g->resizable(output);
+		prev = new Fl_Select_Browser(5, 80, 265, 70, _("Previous expressions"));
+		prev->align(FL_ALIGN_TOP_LEFT);	prev->callback(cb_calc_prev);
+		static int widths[] = { 200, 65, 0 };  // widths for each column
+		prev->column_widths(widths);	prev->column_char('\t');
+		gg = new Fl_Group(5, 155, 265, 115);
+			o = new Fl_Button(5, 155, 25, 25, "7");		o->callback(cb_calc_key,o);
+			o = new Fl_Button(35, 155, 25, 25, "8");	o->callback(cb_calc_key,o);
+			o = new Fl_Button(65, 155, 25, 25, "9");	o->callback(cb_calc_key,o);
+			o = new Fl_Button(95, 155, 25, 25, "+");	o->callback(cb_calc_key,o);
+			o = new Fl_Button(125, 155, 25, 25, "pi");	o->callback(cb_calc_key,o);
+			o = new Fl_Button(5, 185, 25, 25, "4");		o->callback(cb_calc_key,o);
+			o = new Fl_Button(35, 185, 25, 25, "5");	o->callback(cb_calc_key,o);
+			o = new Fl_Button(65, 185, 25, 25, "6");	o->callback(cb_calc_key,o);
+			o = new Fl_Button(95, 185, 25, 25, "-");	o->callback(cb_calc_key,o);
+			o = new Fl_Button(125, 185, 25, 25, "^");	o->callback(cb_calc_key,o);
+			o = new Fl_Button(5, 215, 25, 25, "1");		o->callback(cb_calc_key,o);
+			o = new Fl_Button(35, 215, 25, 25, "2");	o->callback(cb_calc_key,o);
+			o = new Fl_Button(65, 215, 25, 25, "3");	o->callback(cb_calc_key,o);
+			o = new Fl_Button(95, 215, 25, 25, "*");	o->callback(cb_calc_key,o);
+			o = new Fl_Button(125, 215, 25, 25, "(");	o->callback(cb_calc_key,o);
+			o = new Fl_Button(5, 245, 25, 25, "0");		o->callback(cb_calc_key,o);
+			o = new Fl_Button(35, 245, 25, 25, ".");	o->callback(cb_calc_key,o);
+			o = new Fl_Button(65, 245, 25, 25, "E");	o->callback(cb_calc_key,o);
+			o = new Fl_Button(95, 245, 25, 25, "/");	o->callback(cb_calc_key,o);
+			o = new Fl_Button(125, 245, 25, 25, ")");	o->callback(cb_calc_key,o);
+
+			g = new Fl_Group(155, 175, 115, 95, _("Function"));
+			kind = new Fl_Choice(160, 179, 105, 25);	kind->callback(cb_calc_kind);
+			kind->add("Basic");	kind->add("Exp and log");	kind->add("Trigonometric");
+			kind->add("Hyperbolic");	kind->add("Bessel");	kind->add("Elliptic");
+			kind->add("Jacobi");	 kind->add("Airy and Gamma");
+			kind->add("Exp-integrals"); kind->add("Special");	kind->value(0);
+
+			func = new Fl_Choice(160, 209, 105, 25);
+			o = new Fl_Button(160, 239, 105, 25, _("Put function"));	o->callback(cb_calc_func);
+			g->end();	g->box(FL_DOWN_BOX);
+		gg->end();	gg->resizable(g);
+
+		w->end();	w->resizable(prev);
+	}
+	void eval()
+	{
+		const char *eq = edit->value();
+		mglData d = Parse->Calc(eq);
+		result = mgl_str_num(d.a[0]);
+		output->value(result.c_str());
+		std::string buf = eq+('\t'+result);
+		prev->insert(0,buf.c_str());
+	}
+	void set_kind()
+	{
+		int val = kind->value();	func->clear();
+		switch(val)
+		{
+		case 0:	// basic
+			func->add("abs()");		func->add("sign()");	func->add("step()");	func->add("sqrt()");
+			func->add("mod(,)");	func->add("arg(,)");	break;
+		case 1:	// exp and logarithms
+			func->add("exp()");		func->add("pow(,)");	func->add("ln()");		func->add("lg()");
+			func->add("log(,)");	break;
+		case 2:	// trigonometric
+			func->add("sin()");		func->add("cos()");		func->add("tan()");		func->add("sinc()");
+			func->add("asin()");	func->add("acos()");	func->add("atan()");	break;
+		case 3:	// hyperbolic
+			func->add("sinh()");	func->add("cosh()");	func->add("tanh()");	func->add("asinh()");
+			func->add("acosh()");	func->add("atanh()");	break;
+		case 4:	// bessel
+			func->add("bessel_j(,)");	func->add("bessel_y(,)");	func->add("bessel_i(,)");	func->add("bessel_k(,)");	break;
+		case 5:	// elliptic
+			func->add("elliptic_e(,)");	func->add("elliptic_f(,)");	func->add("elliptic_ec()");	func->add("elliptic_kc()");	break;
+		case 6:	// jacobi
+			func->add("sn(,)");		func->add("cn(,)");		func->add("dn(,)");		func->add("sc(,)");
+			func->add("dc(,)");		func->add("nc(,)");		func->add("cs(,)");		func->add("ds(,)");
+			func->add("ns(,)");		func->add("sd(,)");		func->add("cd(,)");		func->add("nd(,)");	break;
+		case 7:	// airy and gamma
+			func->add("airy_ai()");	func->add("airy_bi()");	func->add("airy_dai()");func->add("airy_dbi()");
+			func->add("gamma()");	func->add("psi()");		func->add("beta(,)");	break;
+		case 8:	// exp integrals
+			func->add("ci()");		func->add("si()");		func->add("ei()");		func->add("e1()");
+			func->add("e2()");		func->add("ei3()");	break;
+		case 9:	// special
+			func->add("erf()");		func->add("z()");		func->add("legendre(,)");	func->add("dilog()");
+			func->add("eta()");		func->add("zeta()");	func->add("w0()");		func->add("w1()");	break;
+		}
+//		func->value(0);
+	}
+} calc_dlg;
+//-----------------------------------------------------------------------------
+void cb_calc_key(Fl_Widget *, void *v)
+{	Fl_Button *o=(Fl_Button *)v;	calc_dlg.edit->insert(o->label());	}
+void cb_calc_ins(Fl_Widget *, void *)
+{	if(calc_dlg.e)	calc_dlg.e->editor->insert(calc_dlg.output->value());	}
+void cb_calc_prev(Fl_Widget *, void *)
+{
+	const char *s = calc_dlg.prev->text(calc_dlg.prev->value());
+	if(s && *s)
+	{
+		std::string ss(s);	size_t l=ss.length();
+		for(size_t i=0;i<l;i++)	if(ss[i]=='\t')	ss[i]=0;
+		calc_dlg.edit->value(ss.c_str());
+	}
+}
+void cb_calc_edit(Fl_Widget *, void *)	{	calc_dlg.eval();	}
+void cb_calc_kind(Fl_Widget *, void *)	{	calc_dlg.set_kind();	}
+void cb_calc_func(Fl_Widget *, void *)
+{	const char *s = calc_dlg.func->text();
+	if(s && *s)	calc_dlg.edit->insert(s);	}
+//-----------------------------------------------------------------------------
+void calc_dlg_cb(Fl_Widget *, void *v)
+{	calc_dlg.e = (ScriptWindow *)v;	calc_dlg.show();	}
+//-----------------------------------------------------------------------------
diff --git a/mgllab/mgllab.desktop b/mgllab/mgllab.desktop
new file mode 100755
index 0000000..a9c86dc
--- /dev/null
+++ b/mgllab/mgllab.desktop
@@ -0,0 +1,13 @@
+[Desktop Entry]
+Version=1.0
+Type=Application
+Terminal=false
+Icon=udav
+Name=mgllab
+Exec=mgllab %f
+MimeType=text/mgl;
+Comment=Data handling and plotting tool
+Comment[en_US]=Data handling and plotting tool
+Comment[ru_RU]=Обработка и отображение данных
+Categories=Education;Science;Math;
+Keywords=Visualization;Data;Array;
diff --git a/mgllab/mgllab.h b/mgllab/mgllab.h
new file mode 100644
index 0000000..c78bc21
--- /dev/null
+++ b/mgllab/mgllab.h
@@ -0,0 +1,271 @@
+/* udav.h is part of UDAV
+ * Copyright (C) 2007-2014 Alexey Balakin <mathgl.abalakin at gmail.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License
+ * as published by the Free Software Foundation
+ *
+ * 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
+ */
+//-----------------------------------------------------------------------------
+#ifndef _UDAV_H_
+#define _UDAV_H_
+//-----------------------------------------------------------------------------
+#ifdef __MWERKS__
+# define FL_DLL
+#endif
+#include <FL/Fl.H>
+#include <FL/Fl_Group.H>
+#include <FL/Fl_Double_Window.H>
+#include <FL/fl_ask.H>
+#include <FL/Fl_File_Chooser.H>
+#include <FL/Fl_Menu_Bar.H>
+#include <FL/Fl_Input.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Return_Button.H>
+#include <FL/Fl_Text_Buffer.H>
+#include <FL/Fl_Text_Editor.H>
+#include <FL/Fl_Pixmap.H>
+#include <FL/Fl_Counter.H>
+#include <Fl/Fl_Scroll.H>
+#include <FL/Fl_Tabs.H>
+#include <FL/Fl_Help_View.H>
+#include <Fl/Fl_Table.H>
+#include <Fl/Fl_Round_Button.H>
+#include <Fl/Fl_Float_Input.H>
+#include <Fl/Fl_Multiline_Input.H>
+#include <Fl/Fl_Multiline_Output.H>
+//-----------------------------------------------------------------------------
+#include "mgl2/Fl_MathGL.h"
+//-----------------------------------------------------------------------------
+extern mglParse *Parse;
+extern Fl_Menu_Item colors[];
+class Fl_MGL;
+//-----------------------------------------------------------------------------
+extern Fl_Preferences pref;
+extern Fl_Text_Display::Style_Table_Entry styletable[10];
+extern int changed;		///< flag of script is changed or not
+extern std::string filename;	///< Current filename
+extern std::string lastfiles[5];///< Last opened files
+extern std::string search;		///< Text to search
+extern Fl_Text_Buffer *textbuf;
+//-----------------------------------------------------------------------------
+extern int auto_exec;	///< Enable auto execution
+extern int exec_save;	///< Save before running
+extern int highlight;	///< Highlight current line
+extern int mouse_zoom;	///< Use mouse wheel for zooming
+extern std::string helpname;	///< Path to help files
+extern std::string fontname;	///< Path to font files
+extern int lang;		///< Locale for script and help files
+extern int scheme;		///< FLTK scheme
+extern int font_kind;	///< Editor font kind
+extern int font_size;	///< Editor font size
+extern int complete_word;	///< enable word completion
+//-----------------------------------------------------------------------------
+void set_scheme_lang(int s, int l);		///< Set FLTK scheme and locale
+void set_style(int fkind, int fsize);	///< Change the style of highlight
+void style_init();		///< Initialize the style buffer
+void save_pref();		///< Apply and save preferences
+void load_pref();		///< Load preferences
+void add_filename(const char *fname);	///< Add filename to lastfiles
+std::string wcstombs(std::wstring wcs);	///< Convert std::wstring to std::string
+//-----------------------------------------------------------------------------
+class Fl_Data_Table : public Fl_Table
+{
+private:
+	int row, col;
+	Fl_Input* input;
+protected:
+	void draw_cell(TableContext context, int R, int C, int X, int Y, int W, int H);
+	static void event_callback(Fl_Widget*, void*v)
+	{	((Fl_Data_Table*)v)->cell_click();	}
+	void cell_click();
+
+public:
+	mglDataA *data;
+	int nx, ny, sl;
+
+	Fl_Data_Table(int x, int y, int w, int h, const char *l=0);
+    ~Fl_Data_Table() { }
+
+	void set_value();
+    void rows(int val) { if (input->visible()) input->do_callback(); Fl_Table::rows(val); }
+    void cols(int val) { if (input->visible()) input->do_callback(); Fl_Table::cols(val); }
+    inline int rows() { return Fl_Table::rows(); }
+    inline int cols() { return Fl_Table::cols(); }
+};
+//-----------------------------------------------------------------------------
+class ScriptWindow;
+struct Fl_MGL : public mglDraw
+{
+	ScriptWindow *e;
+	Fl_MGLView *gr;
+	std::vector<std::string> anim;
+	mreal delay;
+	std::string script;		///< script with settings
+	size_t cur;				///< current frame
+	double a1, a2, da;		///< animation loop parameters
+
+	Fl_MGL(Fl_MGLView *GR);
+	~Fl_MGL();
+
+	void Reload();			///< Function for reloading data
+	void Click();			///< Callback function on mouse click
+	int Draw(mglGraph *);	///< Drawing itself
+	void update();			///< Update (redraw) plot
+	void next_frame();		///< Show next frame
+	void prev_frame();		///< Show prev frame
+	HMGL get_graph()		///< Get pointer to grapher
+	{	return gr->FMGL->get_graph();	}
+};
+//-----------------------------------------------------------------------------
+struct TableWindow
+{
+public:
+	TableWindow(ScriptWindow *e);
+	~TableWindow();
+	void update(mglDataA *v);
+	void refresh();
+	void set_slice(long s);
+	inline long get_slice() {	return sl;	}
+	inline long num_slice()	{	return nz;	}
+	void go_home();
+	void show()	{	w->show();	}
+
+	ScriptWindow *main;
+	Fl_Counter *slice;
+	mglDataA *var;
+protected:
+	Fl_Data_Table *data;
+	Fl_Menu_Bar	*menu;
+	Fl_Double_Window *w;
+//	long nx,ny,nz;
+	long nz;
+	long sl;		// current slice
+	char sl_id[64];	// slice id
+};
+//-----------------------------------------------------------------------------
+class ScriptWindow : public Fl_Double_Window
+{
+public:
+	ScriptWindow(int w, int h, const char* t);
+	~ScriptWindow()	{}
+
+	Fl_Text_Editor *editor;
+	Fl_Menu_Bar *menu;
+	Fl_Tabs  *rtab;
+	Fl_Help_View *hd;
+	Fl_Input *link_cmd;
+	Fl_Group *ghelp, *gplot;
+	Fl_Browser *var;
+	Fl_Box *status;
+
+	void set_status(const char *txt);
+	void mem_init();
+	void mem_pressed(int n);
+	Fl_MGLView *graph;
+	Fl_MGL *draw;
+};
+//-----------------------------------------------------------------------------
+class GeneralDlg
+{
+protected:
+	Fl_Double_Window *w;
+public:
+//	GeneralDlg()	{	mgl_textdomain(NULL);	}
+	mglDataA *dat;
+	ScriptWindow *e;
+	std::string result;
+	virtual void cb_ok(){}
+	virtual void init()	{	result.clear();	}
+	void show()	{	init();	w->show();	}
+	void hide()	{	w->hide();	}
+	bool wait()	{	while(w->shown())	Fl::wait();	return result.empty();	}
+};
+void cb_dlg_cancel(Fl_Widget*, void*);
+void cb_dlg_ok(Fl_Widget*, void*);
+void cb_dlg_only(Fl_Widget*,void *v);
+//-----------------------------------------------------------------------------
+// Editor window functions
+void insert_cb(Fl_Widget *, void *);
+//-----------------------------------------------------------------------------
+void paste_cb(Fl_Widget *, void *);
+void select_all_cb(Fl_Widget *, void *);
+void undo_cb(Fl_Widget *, void *);
+void copy_cb(Fl_Widget *, void *);
+void cut_cb(Fl_Widget *, void *);
+void delete_cb(Fl_Widget *, void *);
+void changed_cb(int, int nInserted, int nDeleted,int, const char*, void* v);
+void ins_fname_cb(Fl_Widget *, void *);
+void ins_path_cb(Fl_Widget *, void *);
+void ins_fits_cb(Fl_Widget *, void *);
+void ins_prim_cb(Fl_Widget *, void *);
+void hide_cb(Fl_Widget*, void *);
+void unhide_cb(Fl_Widget*, void *);
+//-----------------------------------------------------------------------------
+// General callback functions
+void new_cb(Fl_Widget *, void *);
+void open_cb(Fl_Widget *, void *);
+void save_cb(Fl_Widget*, void*);
+void saveas_cb(Fl_Widget*, void*);
+void help_cb(Fl_Widget*, void*);
+//-----------------------------------------------------------------------------
+// Dialogs callback functions
+void close_dlg_cb(Fl_Widget *w, void *);
+void font_cb(Fl_Widget *, void *v);
+void line_cb(Fl_Widget *, void *v);
+void face_cb(Fl_Widget *, void *v);
+void data_cb(Fl_Widget *, void *v);
+//-----------------------------------------------------------------------------
+int check_save(void);
+void load_file(const char *newfile, int ipos, ScriptWindow *e);
+void save_file(const char *newfile, ScriptWindow *e);
+Fl_Widget *add_editor(ScriptWindow *w);
+Fl_Widget *add_mem(ScriptWindow *w);
+void set_title(Fl_Window* w);
+//-----------------------------------------------------------------------------
+// Animation
+bool animate_cb(Fl_MGL *dr);
+void animate_dlg_cb(Fl_Widget *, void *v);
+void fill_animate(const char *text, Fl_MGL *dr);
+void argument_set(int id, const char *val);
+//-----------------------------------------------------------------------------
+Fl_Widget *add_help(ScriptWindow *w);
+void help_cb(Fl_Widget*, void*v);
+void link_cb(Fl_Widget*, void*v);
+void example_cb(Fl_Widget*, void*v);
+void about_cb(Fl_Widget*, void*);
+//-----------------------------------------------------------------------------
+void prop_dlg_cb(Fl_Widget*, void*);
+void calc_dlg_cb(Fl_Widget*, void*);
+void args_dlg_cb(Fl_Widget*, void*);
+void option_dlg_cb(Fl_Widget*, void*);
+void dirsel_dlg_cb(Fl_Widget*, void*);
+void datsel_dlg_cb(Fl_Widget*, void*);
+void style_dlg_cb(Fl_Widget*, void*);
+void newcmd_dlg_cb(Fl_Widget*,void*);
+void setup_dlg_cb(Fl_Widget*,void *);
+void inplot_dlg_cb(Fl_Widget*,void*);
+void find_dlg_cb(Fl_Widget*,void*);
+void find_next_cb(Fl_Widget*,void*);
+void hint_dlg_cb(Fl_Widget*,void*);
+void iconlist_cb(Fl_Widget*,void*);
+void message_cb(Fl_Widget*,void*);
+void message_set(const char *s, ScriptWindow *e);
+void info_dlg_cb(mglDataA *d);
+void prim_dlg_cb(Fl_Widget*, void* v);
+void cb_args_set(const char *val);	///< set value for argument in newcmd_dlg
+//-----------------------------------------------------------------------------
+extern Fl_Text_Buffer *textbuf;
+extern std::string filename;
+extern int	changed;
+//-----------------------------------------------------------------------------
+#endif
+//-----------------------------------------------------------------------------
diff --git a/mgllab/mgllab.rc b/mgllab/mgllab.rc
new file mode 100644
index 0000000..56a99a9
--- /dev/null
+++ b/mgllab/mgllab.rc
@@ -0,0 +1,25 @@
+/* udav.rc is part of UDAV
+ * Copyright (C) 2007 Alexey Balakin <balakin at appl.sci-nnov.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License
+ * as published by the Free Software Foundation
+ *
+ * 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
+ */
+//-----------------------------------------------------------------------------
+#include <windows.h>
+
+#define APPICON 1001
+#define APPICON48 1002
+
+APPICON ICON "udav.ico"
+APPICON48 ICON "udav48.ico"
+IDI_ICON1               ICON    DISCARDABLE     "udav.ico"
diff --git a/mgllab/table.cpp b/mgllab/table.cpp
new file mode 100644
index 0000000..72a90db
--- /dev/null
+++ b/mgllab/table.cpp
@@ -0,0 +1,933 @@
+/* table.cpp is part of UDAV
+ * Copyright (C) 2007-2014 Alexey Balakin <mathgl.abalakin at gmail.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License
+ * as published by the Free Software Foundation
+ *
+ * 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
+ */
+#include <FL/Fl_Spinner.H>
+#include <FL/Fl_Output.H>
+#include <FL/Fl_Float_Input.H>
+#include <FL/Fl_Value_Input.H>
+#include <FL/Fl_Round_Button.H>
+#include "mgllab.h"
+
+//-----------------------------------------------------------------------------
+void addto_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	const char *s = fl_input(_("Enter number for addition to data values"),0);
+	HMDT d = dynamic_cast<HMDT>(e->var);
+	if(d && s)	{	mgl_data_add_num(d, atof(s));	e->refresh();	}
+	HADT c = dynamic_cast<HADT>(e->var);
+	if(c && s)	{	mgl_datac_add_num(c, mgl_atoc(s,true));	e->refresh();	}
+}
+//-----------------------------------------------------------------------------
+void subto_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	const char *s = fl_input(_("Enter number for subtraction from data values"),0);
+	HMDT d = dynamic_cast<HMDT>(e->var);
+	if(d && s)	{	mgl_data_sub_num(d, atof(s));	e->refresh();	}
+	HADT c = dynamic_cast<HADT>(e->var);
+	if(c && s)	{	mgl_datac_sub_num(c, mgl_atoc(s,true));	e->refresh();	}
+}
+//-----------------------------------------------------------------------------
+void multo_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	const char *s = fl_input(_("Enter number for multiplication of data values"),0);
+	HMDT d = dynamic_cast<HMDT>(e->var);
+	if(d && s)	{	mgl_data_mul_num(d, atof(s));	e->refresh();	}
+	HADT c = dynamic_cast<HADT>(e->var);
+	if(c && s)	{	mgl_datac_mul_num(c, mgl_atoc(s,true));	e->refresh();	}
+}
+//-----------------------------------------------------------------------------
+void divto_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	const char *s = fl_input(_("Enter number for division of data values"),0);
+	HMDT d = dynamic_cast<HMDT>(e->var);
+	if(d && s)	{	mgl_data_div_num(d, atof(s));	e->refresh();	}
+	HADT c = dynamic_cast<HADT>(e->var);
+	if(c && s)	{	mgl_datac_div_num(c, mgl_atoc(s,true));	e->refresh();	}
+}
+//-----------------------------------------------------------------------------
+class XYZDlg : public GeneralDlg
+{
+	Fl_Box *box;
+	Fl_Check_Button *wch;
+	Fl_Spinner *wmx, *wmy, *wmz;
+public:
+	bool OK;
+	double rx()	{	return wmx->value();	}
+	double ry()	{	return wmy->value();	}
+	double rz()	{	return wmz->value();	}
+	double nx()	{	return mgl_int(wmx->value());	}
+	double ny()	{	return mgl_int(wmy->value());	}
+	double nz()	{	return mgl_int(wmz->value());	}
+	double ch()	{	return wch->value();	}
+	void setup(const char *desc, const char *ch=NULL)
+	{
+		if(desc)	box->label(desc);
+		if(ch && *ch)
+		{	wch->label(ch);	wch->activate();	}
+		else
+		{	wch->label(_("not used"));
+			wch->deactivate();	}
+	}
+	void init()	{	OK=false;	}
+	XYZDlg() : GeneralDlg()
+	{
+		w = new Fl_Double_Window(325, 125, _("Change data sizes"));
+		box = new Fl_Box(10, 10, 305, 40);
+		box->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
+		wmx = new Fl_Spinner(30, 55, 75, 25, "mx");
+		wmx->tooltip(_("New size of data on 1st dimension (x-direction)"));
+		wmy = new Fl_Spinner(135, 55, 75, 25, "my");
+		wmy->tooltip(_("New size of data on 2nd dimension (y-direction)"));
+		wmz = new Fl_Spinner(240, 55, 75, 25, "mz");
+		wmz->tooltip(_("New size of data on 3d dimension (z-direction)"));
+		wch = new Fl_Check_Button(15, 90, 95, 25);
+		Fl_Button *o = new Fl_Button(125, 90, 85, 25, _("Cancel"));
+		o->tooltip(_("Do nothing and close this window"));	o->callback(cb_dlg_cancel,this);
+		o = new Fl_Return_Button(230, 90, 85, 25, _("Change"));
+		o->tooltip(_("Change (resize) data"));	o->callback(cb_dlg_ok,this);
+		w->end();	w->set_modal();
+	}
+	void cb_ok()	{	OK=true;	hide();	}
+	bool run()	{	OK=false;	w->show();	while(w->shown())	Fl::wait();	return OK;	}
+} xyz_dlg;
+//-----------------------------------------------------------------------------
+void new_dat_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	xyz_dlg.setup(_("Specify new data size\nData will be zero filled"));
+	if(xyz_dlg.run())
+	{
+		HMDT d = dynamic_cast<HMDT>(e->var);
+		if(d)
+		{	d->Create(xyz_dlg.nx(), xyz_dlg.ny(), xyz_dlg.nz());	e->refresh();	}
+		HADT c = dynamic_cast<HADT>(e->var);
+		if(c)
+		{	c->Create(xyz_dlg.nx(), xyz_dlg.ny(), xyz_dlg.nz());	e->refresh();	}
+	}
+}
+//-----------------------------------------------------------------------------
+void resize_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	xyz_dlg.setup(_("Specify new data size\nData will be interpolated"));
+	if(xyz_dlg.run())
+	{
+		HMDT d = dynamic_cast<HMDT>(e->var);
+		if(d)
+		{	*d = d->Resize(xyz_dlg.nx(), xyz_dlg.ny(), xyz_dlg.nz());	e->refresh();	}
+		HADT c = dynamic_cast<HADT>(e->var);
+		if(c)
+		{	*c = c->Resize(xyz_dlg.nx(), xyz_dlg.ny(), xyz_dlg.nz());	e->refresh();	}
+	}
+}
+//-----------------------------------------------------------------------------
+void squeeze_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	xyz_dlg.setup(_("Specify the skipping step\nEach m-th point will be saved only"), _("smoothed"));	if(xyz_dlg.run())
+	{
+		HMDT d = dynamic_cast<HMDT>(e->var);
+		if(d)
+		{	d->Squeeze(xyz_dlg.nx(), xyz_dlg.ny(), xyz_dlg.nz(), xyz_dlg.ch());	e->refresh();	}
+		HADT c = dynamic_cast<HADT>(e->var);
+		if(c)
+		{	c->Squeeze(xyz_dlg.nx(), xyz_dlg.ny(), xyz_dlg.nz(), xyz_dlg.ch());	e->refresh();	}
+	}
+}
+//-----------------------------------------------------------------------------
+class ChngDlg : public GeneralDlg
+{
+	Fl_Check_Button *dx, *dy, *dz;
+	Fl_Choice *kind, *type;
+	Fl_Float_Input *val;
+public:
+	ChngDlg() : GeneralDlg()
+	{
+		Fl_Menu_Item k[]={{_("Smooth")}, {_("CumSum")}, { _("Integrate")},
+		{ _("Difference")}, { _("Double diff.")}, { _("Swap parts")},
+		{ _("Sinus FFT")}, { _("Cosine FFT")}, { _("Hankel")},
+		{ _("Mirror")}, { _("Roll")}, { _("Sew phase")}, { _("Envelop")}, {0}};
+		Fl_Menu_Item t[]={{_("Linear *3")}, {_("Linear *5")}, {_("Parabolic *5")},{0}};
+		w = new Fl_Double_Window(165, 215, _("Change data"));
+		kind = new Fl_Choice(10, 25, 145, 25, _("Type of operation"));
+		kind->align(FL_ALIGN_TOP_LEFT);	kind->copy(k);
+		dx = new Fl_Check_Button(10, 55, 140, 25, _("along x"));
+		dy = new Fl_Check_Button(10, 80, 140, 25, _("along y"));
+		dz = new Fl_Check_Button(10, 105, 140, 25, _("along z"));
+		type = new Fl_Choice(10, 145, 145, 25, _("Type of smoothing"));
+		type->align(FL_ALIGN_TOP_LEFT);	type->copy(t);
+		val = new Fl_Float_Input(10, 145, 145, 25, _("Numeric parameter"));
+		val->align(FL_ALIGN_TOP_LEFT);
+		Fl_Button *o;
+		o = new Fl_Button(10, 180, 65, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
+		o = new Fl_Return_Button(90, 180, 65, 25, _("Do"));	o->callback(cb_dlg_ok,this);
+		w->end();	w->set_modal();
+	}
+	void cb_ok()
+	{
+		result.clear();
+		if(dx->value())	result += 'x';
+		if(dy->value())	result += 'y';
+		if(dz->value())	result += 'z';
+		if(result.empty())
+		{	fl_alert(_("You need to specify direction(s)"));	return;	}
+		if(type->value()==0)	result += '3';
+		if(type->value()==1)	result += '5';
+		HMDT d = dynamic_cast<HMDT>(dat);
+		HADT c = dynamic_cast<HADT>(dat);
+		const char *r = result.c_str();
+		bool err = false;
+		double v = val->value() ? atof(val->value()) : 0;
+		if(d)	switch(kind->value())
+		{
+		case 0:	d->Smooth(r);	break;
+		case 1:	d->CumSum(r);	break;
+		case 2:	d->Integral(r);	break;
+		case 3:	d->Diff(r);		break;
+		case 4:	d->Diff2(r);	break;
+		case 5:	d->Swap(r);		break;
+		case 6:	d->SinFFT(r);	break;
+		case 7:	d->CosFFT(r);	break;
+		case 8:	d->Hankel(r);	break;
+		case 9:	d->Mirror(r);	break;
+		case 10:d->Roll(*r ,v);	break;
+		case 11:d->Sew(r);		break;
+		case 12:d->Envelop(*r);	break;
+		}
+		else if(c)	switch(kind->value())
+		{
+		case 0:	c->Smooth(r);	break;
+		case 1:	c->CumSum(r);	break;
+		case 2:	c->Integral(r);	break;
+		case 3:	c->Diff(r);		break;
+		case 4:	c->Diff2(r);	break;
+		case 5:	c->Swap(r);		break;
+		case 6:	c->SinFFT(r);	break;
+		case 7:	c->CosFFT(r);	break;
+		case 8:	c->Hankel(r);	break;
+		case 9:	c->Mirror(r);	break;
+		case 10:c->Roll(*r, v);	break;
+		case 11:err=true;		break;
+		case 12:c->Envelop(*r);	break;
+		}
+		else	err=true;
+		if(err)	fl_alert(_("Operation is not supported for this type of data."));
+		else	hide();
+	}
+	void run(int k, mglDataA *d)
+	{
+		init();	dat=d;	kind->value(k);
+		if(k)	{	type->hide();	val->show();	}
+		else	{	type->show();	val->hide();	}
+		w->show();	while(w->shown())	Fl::wait();
+	}
+} chng_dlg;
+//-----------------------------------------------------------------------------
+void smooth_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	chng_dlg.run(0, e->var);
+	if(!chng_dlg.result.empty())	e->refresh();
+}
+//-----------------------------------------------------------------------------
+void cumsum_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	chng_dlg.run(1, e->var);
+	if(!chng_dlg.result.empty())	e->refresh();
+}
+//-----------------------------------------------------------------------------
+void integr_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	chng_dlg.run(2, e->var);
+	if(!chng_dlg.result.empty())	e->refresh();
+}
+//-----------------------------------------------------------------------------
+void diff_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	chng_dlg.run(3, e->var);
+	if(!chng_dlg.result.empty())	e->refresh();
+}
+//-----------------------------------------------------------------------------
+void diff2_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	chng_dlg.run(4, e->var);
+	if(!chng_dlg.result.empty())	e->refresh();
+}
+//-----------------------------------------------------------------------------
+void swap_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	chng_dlg.run(5, e->var);
+	if(!chng_dlg.result.empty())	e->refresh();
+}
+//-----------------------------------------------------------------------------
+void sinfft_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	chng_dlg.run(6, e->var);
+	if(!chng_dlg.result.empty())	e->refresh();
+}
+//-----------------------------------------------------------------------------
+void cosfft_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	chng_dlg.run(7, e->var);
+	if(!chng_dlg.result.empty())	e->refresh();
+}
+//-----------------------------------------------------------------------------
+void hankel_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	chng_dlg.run(8, e->var);
+	if(!chng_dlg.result.empty())	e->refresh();
+}
+//-----------------------------------------------------------------------------
+void mirror_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	chng_dlg.run(9, e->var);
+	if(!chng_dlg.result.empty())	e->refresh();
+}
+//-----------------------------------------------------------------------------
+void roll_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	chng_dlg.run(10, e->var);
+	if(!chng_dlg.result.empty())	e->refresh();
+}
+//-----------------------------------------------------------------------------
+void sew_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	chng_dlg.run(11, e->var);
+	if(!chng_dlg.result.empty())	e->refresh();
+}
+//-----------------------------------------------------------------------------
+void envelop_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	chng_dlg.run(12, e->var);
+	if(!chng_dlg.result.empty())	e->refresh();
+}
+//-----------------------------------------------------------------------------
+class NwdtDlg : public GeneralDlg
+{
+	Fl_Check_Button *dx, *dy, *dz;
+	Fl_Choice *kind;
+	Fl_Input *name;
+public:
+	NwdtDlg() : GeneralDlg()
+	{
+		Fl_Menu_Item k[]={{_("Summation of")}, {_("Maximum of")}, { _("Minimum of")}, { _("Pulse prop.")}, {0}};
+		w = new Fl_Double_Window(165, 215, _("Extract data"));
+		kind = new Fl_Choice(10, 25, 145, 25, _("Type of operation"));
+		kind->align(FL_ALIGN_TOP_LEFT);	kind->copy(k);
+		dx = new Fl_Check_Button(10, 55, 140, 25, _("along x"));
+		dy = new Fl_Check_Button(10, 80, 140, 25, _("along y"));
+		dz = new Fl_Check_Button(10, 105, 140, 25, _("along z"));
+		name = new Fl_Input(10, 145, 145, 25, _("Name for output"));
+		name->align(FL_ALIGN_TOP_LEFT);
+
+		Fl_Button *o;
+		o = new Fl_Button(10, 180, 65, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
+		o = new Fl_Return_Button(90, 180, 65, 25, _("Do"));	o->callback(cb_dlg_ok,this);
+		w->set_modal();	w->end();
+	}
+	void cb_ok()
+	{
+		result.clear();
+		if(dx->value())	result += 'x';
+		if(dy->value())	result += 'y';
+		if(dz->value())	result += 'z';
+		if(result.empty())
+		{	fl_alert(_("You need to specify direction(s)"));	return;	}
+		const char *s = name->value();
+		if(!s || !s[0])
+		{	fl_alert(_("You need to provide output name"));	return;	}
+		mglDataA *out = Parse->AddVar(s);
+
+		HMDT d = dynamic_cast<HMDT>(dat);
+		HADT c = dynamic_cast<HADT>(dat);
+		const char *r = result.c_str();
+		if(d)	switch(kind->value())
+		{
+			case 0:	*out = d->Sum(r);	break;
+			case 1:	*out = d->Max(r);	break;
+			case 2:	*out = d->Min(r);	break;
+			case 3:	*out = d->Pulse(*r);break;
+		}
+		if(c)	switch(kind->value())
+		{
+			case 0:	*out = c->Sum(r);	break;
+			case 1:	*out = c->Max(r);	break;
+			case 2:	*out = c->Min(r);	break;
+			case 3:	out = mgl_data_pulse(c,*r);	break;
+		}
+		hide();
+	}
+	void run(int k, mglDataA *d)
+	{
+		init();	dat=d;	kind->value(k);
+		w->show();	while(w->shown())	Fl::wait();
+	}
+} nwdt_dlg;
+//-----------------------------------------------------------------------------
+void asum_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	nwdt_dlg.run(0, e->var);
+	if(!chng_dlg.result.empty())	e->refresh();
+}
+//-----------------------------------------------------------------------------
+void amax_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	nwdt_dlg.run(1, e->var);
+	if(!chng_dlg.result.empty())	e->refresh();
+}
+//-----------------------------------------------------------------------------
+void amin_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	nwdt_dlg.run(2, e->var);
+	if(!chng_dlg.result.empty())	e->refresh();
+}
+//-----------------------------------------------------------------------------
+void pulse_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	nwdt_dlg.run(3, e->var);
+	if(!chng_dlg.result.empty())	e->refresh();
+}
+//-----------------------------------------------------------------------------
+void load_dat_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	const char *newfile = mgl_file_chooser(_("Load Data?"),
+		_("DAT Files \t*.{dat,csv}\nHDF Files \t*.{h5,hdf}"));
+	if(newfile)
+	{
+		const char *ext = fl_filename_ext(newfile);
+		HMDT d = dynamic_cast<HMDT>(e->var);
+		HADT c = dynamic_cast<HADT>(e->var);
+		if(!strcmp(ext,"h5") || !strcmp(ext,"hdf"))	// this is HDF file
+		{	// TODO add dialog with choice of HDF names
+			const char *name = fl_input(_("Enter name of data"),"");
+			if(name)
+			{
+				if(d)	d->ReadHDF(newfile,name);
+				if(c)	c->ReadHDF(newfile,name);
+				e->refresh();
+			}
+		}
+		else
+		{
+			if(d)	d->Read(newfile);
+			if(c)	c->Read(newfile);
+			e->refresh();
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void save_dat_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	const char *newfile = mgl_file_chooser(_("Save Data?"),
+		_("DAT Files \t*.{dat,csv}\nHDF Files \t*.{h5,hdf}"), true);
+	if(newfile)
+	{
+		const char *ext = fl_filename_ext(newfile);
+		if(!strcmp(ext,"h5") || !strcmp(ext,"hdf"))	// this is HDF file
+		{
+			std::string name = wcstombs(e->var->s);
+			e->var->SaveHDF(newfile, name.c_str());
+		}
+		else	e->var->Save(newfile);
+	}
+}
+//-----------------------------------------------------------------------------
+void exp_dat_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	const char *scheme, *newfile = mgl_file_chooser(_("Export Data?"),
+		_("PNG Files \t*.png"), true);
+	if(newfile)
+	{	// TODO show dialog for color scheme
+		scheme = fl_input(_("Enter color scheme"),MGL_DEF_SCH);
+		if(scheme)	e->var->Export(newfile,scheme);
+	}
+}
+//-----------------------------------------------------------------------------
+void imp_dat_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	const char *scheme, *newfile = mgl_file_chooser(_("Import Data?"),
+		_("PNG Files \t*.png"));
+	HMDT d = dynamic_cast<HMDT>(e->var);
+	if(d && newfile)
+	{
+		scheme = fl_input(_("Enter color scheme"),MGL_DEF_SCH);
+		if(scheme)
+		{	d->Import(newfile,scheme);	e->refresh();	}
+	}
+	if(!d)	fl_alert(_("This operation is not supported for this kind of data."));
+}
+//-----------------------------------------------------------------------------
+void list_dat_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	HMDT d = dynamic_cast<HMDT>(e->var);
+	HADT c = dynamic_cast<HADT>(e->var);
+	if(!d && !c)
+	{	fl_message(_("Incorrect type of base data"));	return;	}
+	if(e->var->GetNz()>1)	fl_message(_("Only current slice will be inserted"));
+
+	std::string list = "list " + wcstombs(e->var->s);
+	long k=e->get_slice(), nx=e->var->GetNx(), ny=e->var->GetNy();
+	for(long j=0;j<ny;j++)
+	{
+		for(long i=0;i<nx;i++)
+		{
+			if(d)	list += '\t'+mgl_str_num(d->a[i+nx*(j+k*ny)]);
+			if(c)	list += '\t'+mgl_str_num(c->a[i+nx*(j+k*ny)]);
+		}
+		if(j<ny-1)	list += "\t|";
+	}
+	textbuf->insert(0,list.c_str());
+}
+//-----------------------------------------------------------------------------
+void modify_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	const char *eq=fl_input(_("Enter formula for data modification\nHere x, y, z in range [0,1], u is data value"),0);
+	if(eq)
+	{
+		HMDT d = dynamic_cast<HMDT>(e->var);
+		HADT c = dynamic_cast<HADT>(e->var);
+		if(d)	{	d->Modify(eq);	e->refresh();	}
+		if(c)	{	c->Modify(eq);	e->refresh();	}
+	}
+}
+//-----------------------------------------------------------------------------
+class NrmDlg : public GeneralDlg
+{
+	Fl_Value_Input *wmin, *wmax;
+	Fl_Choice *dir;
+	Fl_Check_Button *wsym;
+public:
+	NrmDlg() : GeneralDlg()
+	{
+		Fl_Menu_Item k[]={{"x"}, {"y"}, { "z"}, {0}};
+		w = new Fl_Double_Window(135, 215);
+		wmin = new Fl_Value_Input(10, 25, 115, 25, _("Minimal value (v1)"));
+		wmin->align(FL_ALIGN_TOP_LEFT);
+		wmin->tooltip(_("Minimal value for resulting data values"));
+		wmax = new Fl_Value_Input(10, 70, 115, 25, _("Maximal value (v2)"));
+		wmax->align(FL_ALIGN_TOP_LEFT);
+		wmax->tooltip(_("Maximal value for resulting data values"));
+		dir = new Fl_Choice(10, 115, 115, 25, _("Direction"));
+		dir->align(FL_ALIGN_TOP_LEFT);	dir->copy(k);	dir->value(0);
+		dir->tooltip(_("Direction along which data will be filled"));
+		wsym = new Fl_Check_Button(10, 115, 115, 25, _("Symmetrical range"));
+		wsym->tooltip(_("Normalize in symmetrical range: -max(|v1|,|v2|) ... max(|v1|,|v2|)"));
+
+		Fl_Button *o;
+		o = new Fl_Button(25, 150, 85, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
+		o->tooltip(_("Do nothing and close this window"));
+		o = new Fl_Return_Button(25, 180, 85, 25, _("Change"));	o->callback(cb_dlg_ok,this);
+		o->tooltip(_("Change data values and close this window"));
+		w->set_modal();	w->end();
+	}
+	double min()	{	return wmin->value();	}
+	double max()	{	return wmax->value();	}
+	int sym()		{	return wsym->value();	}
+	bool ok()		{	return !result.empty();	}
+	void cb_ok()
+	{	result = dir->value();	hide();	}
+	void run(const char *lbl)
+	{
+		init();	w->label(lbl?lbl:"");
+		w->show();	while(w->shown())	Fl::wait();
+	}
+} nrm_dlg;
+//-----------------------------------------------------------------------------
+void fill_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	nrm_dlg.run(_("Fill in range"));
+	if(nrm_dlg.ok())
+	{
+		HMDT d = dynamic_cast<HMDT>(e->var);
+		HADT c = dynamic_cast<HADT>(e->var);
+		char ch = nrm_dlg.result[0];
+		if(d)	{	d->Fill(nrm_dlg.min(),nrm_dlg.max(),ch);	e->refresh();	}
+		if(c)	{	c->Fill(nrm_dlg.min(),nrm_dlg.max(),ch);	e->refresh();	}
+	}
+}
+//-----------------------------------------------------------------------------
+void normal_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	nrm_dlg.run(_("Fill in range"));
+	if(nrm_dlg.ok())
+	{
+		HMDT d = dynamic_cast<HMDT>(e->var);
+		HADT c = dynamic_cast<HADT>(e->var);
+		if(d)	{	d->Norm(nrm_dlg.min(),nrm_dlg.max(),nrm_dlg.sym());	e->refresh();	}
+		if(c)	{	c->Fill(nrm_dlg.min(),nrm_dlg.max(),nrm_dlg.sym());	e->refresh();	}
+	}
+}
+//-----------------------------------------------------------------------------
+struct CropDlg : public GeneralDlg
+{
+	Fl_Spinner *x1,*x2, *y1,*y2, *z1,*z2;
+	CropDlg() : GeneralDlg()
+	{
+		w = new Fl_Double_Window(230, 155, _("Crop data"));
+		x1 = new Fl_Spinner(45, 25, 80, 25, _("From"));	x1->align(FL_ALIGN_TOP);
+		x2 = new Fl_Spinner(140, 25, 80, 25, _("To"));	x2->align(FL_ALIGN_TOP);
+		y1 = new Fl_Spinner(45, 55, 80, 25);
+		y2 = new Fl_Spinner(140, 55, 80, 25);
+		z1 = new Fl_Spinner(45, 85, 80, 25);
+		z2 = new Fl_Spinner(140, 85, 80, 25);
+
+		new Fl_Box(15, 25, 25, 25, "X");
+		new Fl_Box(15, 55, 25, 25, "Y");
+		new Fl_Box(15, 85, 25, 25, "Z");
+		Fl_Button *o;
+		o = new Fl_Button(45, 120, 75, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
+		o->tooltip(_("Do nothing and close this window"));
+		o = new Fl_Return_Button(145, 120, 75, 25, _("OK"));	o->callback(cb_dlg_ok,this);
+		o->tooltip(_("Change data values and close this window"));
+		w->set_modal();	w->end();
+	}
+	void init()
+	{
+		long nx=dat->GetNx(), ny=dat->GetNy(), nz=dat->GetNz();
+		x1->range(0,nx-1);	x1->value(0);
+		x2->range(0,nx-1);	x2->value(nx-1);
+		y1->range(0,nx-1);	y1->value(0);
+		y2->range(0,nx-1);	y2->value(ny-1);
+		z1->range(0,nx-1);	z1->value(0);
+		z2->range(0,nx-1);	z2->value(nz-1);
+	}
+	void cb_ok()
+	{
+		long n1,n2;
+		HMDT d = dynamic_cast<HMDT>(dat);
+		HADT c = dynamic_cast<HADT>(dat);
+		n1=mgl_int(x1->value());	n2=mgl_int(x2->value());
+		if(d)	d->Crop(n1,n2,'x');
+		if(c)	c->Crop(n1,n2,'x');
+		n1=mgl_int(y1->value());	n2=mgl_int(y2->value());
+		if(d)	d->Crop(n1,n2,'y');
+		if(c)	c->Crop(n1,n2,'y');
+		n1=mgl_int(z1->value());	n2=mgl_int(z2->value());
+		if(d)	d->Crop(n1,n2,'z');
+		if(c)	c->Crop(n1,n2,'z');
+	}
+	void run(mglDataA *d)
+	{
+		dat = d;	init();
+		w->show();	while(w->shown())	Fl::wait();
+	}
+} crop_dlg;
+//-----------------------------------------------------------------------------
+void crop_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	crop_dlg.run(e->var);	e->refresh();
+}
+//-----------------------------------------------------------------------------
+struct TrspDlg : public GeneralDlg
+{
+	Fl_Choice *how;
+public:
+	TrspDlg() : GeneralDlg()
+	{
+		Fl_Menu_Item k[]={{"yxz"}, {"zxy"}, {"zyx"}, {"yzx"}, {"xzy"}, {0}};
+		w = new Fl_Double_Window(200, 90, _("Transpose data"));
+		how = new Fl_Choice(10, 20, 180, 25, _("New order of dimensions"));
+		how->align(FL_ALIGN_TOP_LEFT);	how->copy(k);	how->value(0);
+		Fl_Button *o;
+		o = new Fl_Button(30, 55, 75, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
+		o->tooltip(_("Do nothing and close this window"));
+		o = new Fl_Return_Button(115, 55, 75, 25, _("Do"));	o->callback(cb_dlg_ok,this);
+		o->tooltip(_("Change data values and close this window"));
+		w->set_modal();	w->end();
+	}
+	void cb_ok()
+	{
+		HMDT d = dynamic_cast<HMDT>(dat);
+		HADT c = dynamic_cast<HADT>(dat);
+		if(d)	d->Transpose(how->text());
+		if(c)	c->Transpose(how->text());
+	}
+	void run(mglDataA *d)
+	{
+		dat = d;	init();
+		w->show();	while(w->shown())	Fl::wait();
+	}
+} trsp_dlg;
+//-----------------------------------------------------------------------------
+void transp_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	trsp_dlg.run(e->var);	e->refresh();
+}
+//-----------------------------------------------------------------------------
+void first_sl_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	e->slice->value(0);
+	e->set_slice(0);
+	e->go_home();
+}
+//-----------------------------------------------------------------------------
+void last_sl_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	e->slice->value(e->num_slice()-1);
+	e->set_slice(e->num_slice()-1);
+	e->go_home();
+}
+//-----------------------------------------------------------------------------
+void prev_sl_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	int p = int(e->slice->value())-1;
+	if(p<0)	p = 0;
+	e->slice->value(p);		e->set_slice(p);
+	e->go_home();
+}
+//-----------------------------------------------------------------------------
+void next_sl_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	int p = int(e->slice->value())+1;
+	if(p>=e->num_slice())	p = e->num_slice()-1;
+	e->slice->value(p);		e->set_slice(p);
+	e->go_home();
+}
+//-----------------------------------------------------------------------------
+void first_cl_cb(Fl_Widget*, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	e->go_home();
+}
+//-----------------------------------------------------------------------------
+void change_sl_cb(Fl_Widget*w, void*v)
+{
+	TableWindow* e = (TableWindow*)v;
+	e->set_slice(long(e->slice->value()));
+	e->go_home();
+}
+//-----------------------------------------------------------------------------
+Fl_Menu_Item tablemenu[60] = {
+	{ _("File"), 0, 0, 0, FL_SUBMENU },
+		{ _("Load from file"),0, load_dat_cb },
+		{ _("Import from PNG"),0, imp_dat_cb },
+		{ _("Save to file"),	0, save_dat_cb },
+		{ _("Export to PNG"),	0, exp_dat_cb, 0, FL_MENU_DIVIDER },
+		{ _("Insert as 'list'"),0, list_dat_cb },
+//		{ _("Plot data"),		0, plot_dat_cb },
+//		{ _("Info for data"),	0, info_dat_cb },
+		{ 0 },
+	{ _("Sizes"), 0, 0, 0, FL_SUBMENU },
+		{ _("Create new"),	0, new_dat_cb },
+		{ _("Resize"),		0, resize_cb },
+		{ _("Squeeze"),	0, squeeze_cb },
+		{ _("Crop"),		0, crop_cb },
+		{ _("Transpose"),	0, transp_cb },
+//		{ _("Extend"),	0, extend_cb },
+		{ 0 },
+	{ _("Fill"), 0, 0, 0, FL_SUBMENU },
+		{ _("By formula"),	0, modify_cb },
+		{ _("In range"),	0, fill_cb },
+		{ _("Normalize"),	0, normal_cb },
+		{ 0 },
+	{ _("Change"), 0, 0, 0, FL_SUBMENU },
+		{ _("Smooth"),	0, smooth_cb },
+		{ _("CumSum"),	0, cumsum_cb },
+		{ _("Integrate"),	0, integr_cb },
+		{ _("Difference"),0, diff_cb },
+		{ _("Laplacian"),	0, diff2_cb },
+		{ _("Swap parts"),0, swap_cb },
+		{ _("Sin FFT"),	0, sinfft_cb },
+		{ _("Cos FFT"),	0, cosfft_cb },
+		{ _("Hankel"),	0, hankel_cb },
+//		{ _("Wavelet"),	0, wavelet_cb },
+		{ _("Mirror"),	0, mirror_cb },
+		{ _("Roll"),		0, roll_cb },
+		{ _("Sew phase"),	0, sew_cb },
+		{ _("Envelop"),	0, envelop_cb },
+		{ 0 },
+	{ _("Another"), 0, 0, 0, FL_SUBMENU },
+//		{ _("Histogram of"),	0, hist_cb },
+		{ _("Summation of"),	0, asum_cb },
+		{ _("Maximum of"),	0, amax_cb },
+		{ _("Minimum of"),	0, amin_cb },
+		{ _("Pulse prop."),	0, pulse_cb },
+		{ 0 },
+	{ _("Operations"), 0, 0, 0, FL_SUBMENU },
+		{ _("Add to"),		0, addto_cb },
+		{ _("Subtract to"),0, subto_cb },
+		{ _("Multiply by"),0, multo_cb },
+		{ _("Divide by"),	0, divto_cb },
+		{ 0 },
+	{ _("Navigation"), 0, 0, 0, FL_SUBMENU },
+		{ _("First slice"), FL_CTRL + FL_F + 1, first_sl_cb },
+		{ _("Prev slice"), FL_CTRL + FL_F + 2, prev_sl_cb },
+		{ _("Next slice"), FL_CTRL + FL_F + 3, next_sl_cb },
+		{ _("Last slice"),	FL_CTRL + FL_F + 4, last_sl_cb, 0, FL_MENU_DIVIDER },
+		{ _("First cell"), FL_ALT + FL_F + 1, first_cl_cb },
+//		{ _("Last cell"), FL_ALT + FL_F + 2, last_cl_cb },
+//		{ _("Center grid"), FL_ALT + FL_F + 3, center_cl_cb },
+		{ 0 },
+	{ 0 }
+};
+//-----------------------------------------------------------------------------
+void plot_dat_cb(Fl_Widget*,void *v)
+{
+	TableWindow *e=(TableWindow*)v;
+	info_dlg_cb(e->var);
+}
+//-----------------------------------------------------------------------------
+#include "../widgets/image.h"
+#include "xpm/document-import.xpm"
+#include "xpm/document-export.xpm"
+#include "xpm/diff.xpm"
+#include "xpm/func.xpm"
+#include "xpm/size.xpm"
+#include "xpm/tran.xpm"
+#include "xpm/crop.xpm"
+#include "xpm/go-first.xpm"
+#include "xpm/go-last.xpm"
+TableWindow::TableWindow(ScriptWindow *e)
+{
+	main = e;
+	const int ww = 600, hh = 430;	// initial width (>300) and height (>430)
+	w = new Fl_Double_Window(ww,430);		var = 0;
+	menu = new Fl_Menu_Bar(0, 0, ww, 30);	menu->copy(tablemenu, this);
+	Fl_Button *o;
+	Fl_Group *g = new Fl_Group(0,0,30,350);
+	o = new Fl_Button(0, 30, 25, 25);	o->image(img_new);
+	o->callback(new_dat_cb,this);		o->tooltip(_("Create new data with zero filling"));
+	o = new Fl_Button(0, 55, 25, 25);	o->image(img_load);
+	o->callback(load_dat_cb,this);		o->tooltip(_("Load data from file"));
+	o = new Fl_Button(0, 80, 25, 25);	o->image(new Fl_Pixmap(document_import_xpm));
+	o->callback(imp_dat_cb,this);		o->tooltip(_("Import data from PNG file"));
+	o = new Fl_Button(0, 105, 25, 25);	o->image(img_save);
+	o->callback(save_dat_cb,this);		o->tooltip(_("Save data to file"));
+	o = new Fl_Button(0, 130, 25, 25);	o->image(new Fl_Pixmap(document_export_xpm));
+	o->callback(exp_dat_cb,this);		o->tooltip(_("Export data to PNG file"));
+
+	o = new Fl_Button(0, 160, 25, 25);	o->image(img_insert);
+	o->callback(list_dat_cb,this);		o->tooltip(_("Insert to script as 'list' command"));
+	o = new Fl_Button(0, 185, 25, 25);	o->image(img_plot);
+	o->callback(plot_dat_cb,this);		o->tooltip(_("Data information and preview."));
+
+	o = new Fl_Button(0, 215, 25, 25);	o->image(new Fl_Pixmap(diff_xpm));
+	o->callback(smooth_cb,this);		o->tooltip(_("Apply operator (smoothing, integration, difference ...) to data"));
+	o = new Fl_Button(0, 240, 25, 25);	o->image(new Fl_Pixmap(func_xpm));
+	o->callback(modify_cb,this);		o->tooltip(_("Fill data by formula"));
+	o = new Fl_Button(0, 265, 25, 25);	o->image(new Fl_Pixmap(size_xpm));
+	o->callback(resize_cb,this);		o->tooltip(_("Resize data with smoothing"));
+	o = new Fl_Button(0, 290, 25, 25);	o->image(new Fl_Pixmap(crop_xpm));
+	o->callback(crop_cb,this);		o->tooltip(_("Crop (cut off edges) data"));
+	o = new Fl_Button(0, 315, 25, 25);	o->image(new Fl_Pixmap(tran_xpm));
+	o->callback(transp_cb,this);		o->tooltip(_("Transpose data dimensions"));
+	g->end();	g->resizable(0);
+
+	g = new Fl_Group(30, 30, 200, 30);
+	o = new Fl_Button(30, 30, 25, 25);	o->image(new Fl_Pixmap(go_first_xpm));
+	o->callback(first_sl_cb,this);		o->tooltip(_("Go to first slice for 3D data (Ctrl-F1)."));
+	slice = new Fl_Counter(55, 30, 90, 25, 0);	slice->callback(change_sl_cb,this);
+	slice->lstep(10);	slice->step(1);	slice->tooltip(_("Id of slice on third (z-) dimension"));
+	o = new Fl_Button(147, 30, 25, 25);	o->image(new Fl_Pixmap(go_last_xpm));
+	o->callback(last_sl_cb,this);		o->tooltip(_("Go to last slice for 3D data (Ctrl-F4)."));
+	g->end();	g->resizable(0);
+
+	data = new Fl_Data_Table(30,60,ww-30,hh-60);
+	data->row_header(1);	data->row_header_width(80);
+	data->row_resize(1);	data->rows(1);
+	data->row_height_all(25);
+	data->col_header(1);	data->col_header_height(25);
+	data->col_resize(1);	data->cols(1);
+	data->col_width_all(80);
+	data->tooltip(_("Colors denote values: magenta - local max, cyan - local min,\n"
+	"\tred - Re(v)>0, blue - Re(v)<0, purple - Im(v)>0, teal - Im(v)<0."));
+
+	w->end();	w->resizable(data);
+}
+//-----------------------------------------------------------------------------
+TableWindow::~TableWindow()	{	if(var)	var->o=NULL;	Fl::delete_widget(w);	}
+//-----------------------------------------------------------------------------
+void delete_cb(void *v)
+{
+	if(v)
+	{
+		TableWindow *w = (TableWindow *)v;
+		w->var->o=NULL;		delete w;
+	}
+}
+//-----------------------------------------------------------------------------
+void TableWindow::update(mglDataA *v)
+{
+	static std::string name;
+	if(v==0)	return;
+	name = wcstombs(v->s);
+	w->label(name.c_str());
+	v->func = delete_cb;
+	if(var)	var->o = 0;
+	var = v; 	v->o = this;
+	refresh();
+}
+//-----------------------------------------------------------------------------
+void TableWindow::refresh()
+{
+	if(var==0)	return;
+	w->deactivate();	nz = var->GetNz();
+	sl = 0;	slice->range(0,nz-1);
+
+	data->rows(var->GetNy());	data->cols(var->GetNx());
+	data->ny = var->GetNy();	data->nx = var->GetNx();
+	data->data = var;
+	w->activate();
+//	show();
+}
+//-----------------------------------------------------------------------------
+void TableWindow::set_slice(long s)
+{
+	if(s>=0 && s<nz)
+	{
+		data->sl = sl = s;
+		refresh();
+	}
+}
+//-----------------------------------------------------------------------------
+void TableWindow::go_home()
+{
+}
+//-----------------------------------------------------------------------------
diff --git a/mgllab/todo.txt b/mgllab/todo.txt
new file mode 100644
index 0000000..60867bc
--- /dev/null
+++ b/mgllab/todo.txt
@@ -0,0 +1,8 @@
+1. Start/Stop on single button
+2. Update FLTK icons
+3. Flat toolbuttons
+4. Detach data table
+5. Menu items to show/hide extra toolbars
+6. Update help or graph only if paths are changed
+7. Common colors in format dialog
+8. Show graph on update
diff --git a/mgllab/udav.ico b/mgllab/udav.ico
new file mode 100644
index 0000000..27423de
Binary files /dev/null and b/mgllab/udav.ico differ
diff --git a/mgllab/udav.png b/mgllab/udav.png
new file mode 100644
index 0000000..76ba7d9
Binary files /dev/null and b/mgllab/udav.png differ
diff --git a/mgllab/udav48.ico b/mgllab/udav48.ico
new file mode 100644
index 0000000..a286d6d
Binary files /dev/null and b/mgllab/udav48.ico differ
diff --git a/mgllab/xpm/accessories-calculator.xpm b/mgllab/xpm/accessories-calculator.xpm
new file mode 100644
index 0000000..20a11f8
--- /dev/null
+++ b/mgllab/xpm/accessories-calculator.xpm
@@ -0,0 +1,103 @@
+/* XPM */
+static const char *accessories_calculator_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 81 1 ",
+"  c #313131",
+". c #313231",
+"X c gray21",
+"o c #363736",
+"O c gray22",
+"+ c gray23",
+"@ c #3C3C3C",
+"# c gray24",
+"$ c #3E3E3E",
+"% c #414141",
+"& c #424342",
+"* c gray27",
+"= c gray28",
+"- c #494B48",
+"; c #4B4B4B",
+": c #4D4D4C",
+"> c gray30",
+", c #656565",
+"< c gray40",
+"1 c #676965",
+"2 c #686A67",
+"3 c DimGray",
+"4 c #6C6C6C",
+"5 c #6D6D6D",
+"6 c #727371",
+"7 c #747674",
+"8 c #757774",
+"9 c #767676",
+"0 c #777777",
+"q c #797979",
+"w c gray48",
+"e c #7C7C7C",
+"r c #9BAB90",
+"t c #9DAD92",
+"y c gray72",
+"u c gray",
+"i c #B3C2A9",
+"p c #BDCAB5",
+"a c #BFCBB7",
+"s c #C0CCB7",
+"d c #C1C1C1",
+"f c gray76",
+"g c #C3C3C3",
+"h c gray77",
+"j c #C6C6C6",
+"k c gray78",
+"l c #C8C8C8",
+"z c #CACACA",
+"x c gray80",
+"c c #CECECE",
+"v c gray81",
+"b c gray82",
+"n c LightGray",
+"m c gray83",
+"M c #D5D5D5",
+"N c gray84",
+"B c #D7D7D7",
+"V c #D8D8D8",
+"C c gray85",
+"Z c #DADADA",
+"A c gray86",
+"S c gainsboro",
+"D c gray87",
+"F c #DFDFDF",
+"G c gray88",
+"H c #E1E1E1",
+"J c #E2E2E2",
+"K c gray89",
+"L c #E4E4E4",
+"P c gray90",
+"I c #E6E6E6",
+"U c #E7E7E7",
+"Y c gray91",
+"T c #EAEAEA",
+"R c gray92",
+"E c #ECECEC",
+"W c gray93",
+"Q c #EEEEEE",
+"! c gray94",
+"~ c gray95",
+"^ c None",
+/* pixels */
+"^^^*qeqq8080>^^^",
+"^^^c068873->g^^^",
+"^^^n3spsitr1g^^^",
+"^^^c;>&o  @$u^^^",
+"^^^GhlhgggghI^^^",
+"^^^F$$W$OG$$R^^^",
+"^^^AW~RIIRR~R^^^",
+"^^^B$$I$OA$$G^^^",
+"^^^nWWGGGGYEG^^^",
+"^^^n$$G$$A$$G^^^",
+"^^^cIGFAFFIYG^^^",
+"^^^c$$A$OB&$F^^^",
+"^^^lABBBnAXOA^^^",
+"^^^l$OB$OB  B^^^",
+"^^^ynBBBBAGFc^^^",
+"^^^-,,,,,344*^^^"
+};
diff --git a/mgllab/xpm/alpha.xpm b/mgllab/xpm/alpha.xpm
new file mode 100644
index 0000000..102c0e1
--- /dev/null
+++ b/mgllab/xpm/alpha.xpm
@@ -0,0 +1,126 @@
+/* XPM */
+static const char * alpha_xpm[] = {
+"16 16 107 2",
+"  	c None",
+". 	c #395155",
+"+ 	c #3A5155",
+"@ 	c #384F54",
+"# 	c #4C6A71",
+"$ 	c #68929C",
+"% 	c #B8FFFF",
+"& 	c #B1F9FF",
+"* 	c #B7FFFF",
+"= 	c #6B939C",
+"- 	c #113F4A",
+"; 	c #7CADB9",
+"> 	c #B4FCFF",
+", 	c #84BAC8",
+"' 	c #51585B",
+") 	c #78888C",
+"! 	c #79898D",
+"~ 	c #4D4D4D",
+"{ 	c #17B0D6",
+"] 	c #2CE0FF",
+"^ 	c #1D99B8",
+"/ 	c #1F282B",
+"( 	c #A1E2F3",
+"_ 	c #ABF0FF",
+": 	c #ACF2FF",
+"< 	c #658187",
+"[ 	c #E1FFFF",
+"} 	c #D7F8FF",
+"| 	c #D7F9FF",
+"1 	c #D7F7FF",
+"2 	c #428494",
+"3 	c #28D6FF",
+"4 	c #2AD6FF",
+"5 	c #26C3EA",
+"6 	c #1A88A2",
+"7 	c #346974",
+"8 	c #7BB8C6",
+"9 	c #9FDEEE",
+"0 	c #97D4E3",
+"a 	c #C2E2E9",
+"b 	c #D6F8FF",
+"c 	c #C5E6ED",
+"d 	c #2DB7DA",
+"e 	c #2AD1FB",
+"f 	c #23BFE6",
+"g 	c #0B6A81",
+"h 	c #42B0CC",
+"i 	c #4DB0C8",
+"j 	c #3A575C",
+"k 	c #7B878A",
+"l 	c #7D8A8E",
+"m 	c #7D8A8D",
+"n 	c #3B4A4E",
+"o 	c #0586A5",
+"p 	c #00BEED",
+"q 	c #005A70",
+"r 	c #317F93",
+"s 	c #56DFFF",
+"t 	c #47AEC7",
+"u 	c #7ADDF6",
+"v 	c #81ECFF",
+"w 	c #84F0FF",
+"x 	c #2F7E90",
+"y 	c #00DBFF",
+"z 	c #0094B9",
+"A 	c #3FA4BC",
+"B 	c #4CC5E4",
+"C 	c #72D1E7",
+"D 	c #7FE4FE",
+"E 	c #80E5FF",
+"F 	c #78D1E8",
+"G 	c #0EABD1",
+"H 	c #00BBEA",
+"I 	c #51D4F4",
+"J 	c #3A7888",
+"K 	c #85EEFF",
+"L 	c #60C0D8",
+"M 	c #00B7E6",
+"N 	c #0096BB",
+"O 	c #215764",
+"P 	c #3FA7C0",
+"Q 	c #70C6DC",
+"R 	c #83ECFF",
+"S 	c #378599",
+"T 	c #00B1DE",
+"U 	c #4AC5E4",
+"V 	c #447B89",
+"W 	c #82E8FF",
+"X 	c #84E4FD",
+"Y 	c #007696",
+"Z 	c #00556A",
+"` 	c #0A1A1E",
+" .	c #4FC5E2",
+"..	c #75D1E8",
+"+.	c #81E7FF",
+"@.	c #598B98",
+"#.	c #00B1DF",
+"$.	c #235C69",
+"%.	c #6BC4DA",
+"&.	c #82E6FF",
+"*.	c #148099",
+"=.	c #2C5B65",
+"-.	c #74D6F0",
+";.	c #074F61",
+">.	c #13353F",
+",.	c #67B8C9",
+"'.	c #0E191C",
+"            . + + @             ",
+"        # $ % & & * = -         ",
+"      ; > , ' ) ! ~ { ] ^       ",
+"  / ( _ : < [ } | 1 2 3 4 5 6   ",
+"  7 8 9 0 a b } } b c d e f g   ",
+"    h i j k l l l l m n o p q   ",
+"    r s t u v v v v w x y z     ",
+"      A B C D E E E F G H       ",
+"        I J K D E E L M N       ",
+"        O P Q E E R S T         ",
+"          U V W E X Y Z         ",
+"          `  ...+. at .#.          ",
+"            $.%.&.*.            ",
+"              =.-.;.            ",
+"              >.,.              ",
+"                '.              "};
diff --git a/mgllab/xpm/arc.xpm b/mgllab/xpm/arc.xpm
new file mode 100644
index 0000000..28f80a1
--- /dev/null
+++ b/mgllab/xpm/arc.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * arc_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"     ......     ",
+"   ..      ..   ",
+"  .          .  ",
+"              . ",
+"              . ",
+"               .",
+"               .",
+"               .",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/arrow-down-double.xpm b/mgllab/xpm/arrow-down-double.xpm
new file mode 100644
index 0000000..29408f8
--- /dev/null
+++ b/mgllab/xpm/arrow-down-double.xpm
@@ -0,0 +1,129 @@
+/* XPM */
+static const char *arrow_down_double_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 107 2 ",
+"   c #045304",
+".  c #0A5E0A",
+"X  c #185C18",
+"o  c #1A5D1A",
+"O  c #0B600B",
+"+  c #037503",
+"@  c #007800",
+"#  c #007801",
+"$  c #007F01",
+"%  c #0C720C",
+"&  c #146715",
+"*  c #166417",
+"=  c #107411",
+"-  c #117A11",
+";  c #1A781A",
+":  c #197C19",
+">  c #276827",
+",  c #296C29",
+"<  c #2F6A2F",
+"1  c #267626",
+"2  c #307430",
+"3  c #357235",
+"4  c #347B34",
+"5  c #367B36",
+"6  c #3C743C",
+"7  c #008100",
+"8  c #008300",
+"9  c #008201",
+"0  c #008202",
+"q  c #008800",
+"w  c #008900",
+"e  c #008C05",
+"r  c #048608",
+"t  c #0B830B",
+"y  c #048D08",
+"u  c #009600",
+"i  c #009105",
+"p  c #009A00",
+"a  c #009F00",
+"s  c #049F04",
+"d  c #099109",
+"f  c #0A910A",
+"g  c #099C09",
+"h  c #0A9B0C",
+"j  c #0C8A10",
+"k  c #128414",
+"l  c #108A13",
+"z  c #158C17",
+"x  c #1D8B1D",
+"c  c #00A000",
+"v  c #00A400",
+"b  c #00A700",
+"n  c #00AA00",
+"m  c #08A208",
+"M  c #00B200",
+"N  c #00B300",
+"B  c #00B400",
+"V  c #00B800",
+"C  c #00BC00",
+"Z  c #00BE00",
+"A  c #0DB40E",
+"S  c #11A612",
+"D  c #15AC17",
+"F  c #17A118",
+"G  c #1BAE1C",
+"H  c #1ABE1B",
+"J  c #1E8B21",
+"K  c #1E9521",
+"L  c #2D812D",
+"P  c #239823",
+"I  c #249F24",
+"U  c #318E31",
+"Y  c #388138",
+"T  c #3A853A",
+"R  c #3A8F3A",
+"E  c #359635",
+"W  c #309C30",
+"Q  c #379837",
+"!  c #3B9F3B",
+"~  c #1EA321",
+"^  c #27A127",
+"/  c #21A424",
+"(  c #2BA02B",
+")  c #00C500",
+"_  c #00C700",
+"`  c #00D300",
+"'  c #438343",
+"]  c #408840",
+"[  c #418D41",
+"{  c #468B46",
+"}  c #4A964A",
+"|  c #4E9F4E",
+" . c #5F9B5F",
+".. c #40A240",
+"X. c #44A344",
+"o. c #49A249",
+"O. c #4FA04F",
+"+. c #50A050",
+"@. c #58A958",
+"#. c #5DAB5D",
+"$. c #64A464",
+"%. c #63AD63",
+"&. c #72A572",
+"*. c #72B672",
+"=. c #75B675",
+"-. c #80BA80",
+";. c None",
+/* pixels */
+";.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.",
+";.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.",
+";.;.< 6 2 1 ; - # 7 7 7 z J i ;.",
+";.;.X &. .{ L : # 8 w w 7 K ;.;.",
+";.;.;.> $.} U x w u c c F y ;.;.",
+";.;.;.;.5 +.E P u b B A h ;.;.;.",
+";.;.3 ' Y O.! ^ s M ) H D ~ e ;.",
+";.;.X -.*. at ...^ m M _ ` Z / ;.;.",
+";.;.;., =.#.X.( g n B Z G r ;.;.",
+";.;.;.;.5 %.o.W f p b S j ;.;.;.",
+";.;.;.;.;.] | E t w f l ;.;.;.;.",
+";.;.;.;.;.  [ R % + k ;.;.;.;.;.",
+";.;.;.;.;.;.. T O = ;.;.;.;.;.;.",
+";.;.;.;.;.;.;.& * ;.;.;.;.;.;.;.",
+";.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.",
+";.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;."
+};
diff --git a/mgllab/xpm/arrow-down.xpm b/mgllab/xpm/arrow-down.xpm
new file mode 100644
index 0000000..b11d8aa
--- /dev/null
+++ b/mgllab/xpm/arrow-down.xpm
@@ -0,0 +1,85 @@
+/* XPM */
+static const char *arrow_down_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 63 1 ",
+"  c #004D00",
+". c #055205",
+"X c #045D04",
+"o c #0D5D0D",
+"O c #0B620C",
+"+ c #057005",
+"@ c #077A07",
+"# c #0C760E",
+"$ c #0B7F0D",
+"% c #156716",
+"& c #1D6A1E",
+"* c #327032",
+"= c #068206",
+"- c #008A00",
+"; c #008D03",
+": c #09810C",
+"> c #009001",
+", c #029102",
+"< c #009D00",
+"1 c #009E01",
+"2 c #0D920E",
+"3 c #178F17",
+"4 c #16981A",
+"5 c #00A300",
+"6 c #00A500",
+"7 c #00A902",
+"8 c #00AB02",
+"9 c #00AE00",
+"0 c #00B800",
+"q c #00BA00",
+"w c #05B805",
+"e c #15A017",
+"r c #18A11B",
+"t c #16AA18",
+"y c ForestGreen",
+"u c #2D882D",
+"i c #2F942F",
+"p c #2D9D2D",
+"a c #348C34",
+"s c #388238",
+"d c #3A853A",
+"f c #25A425",
+"g c #25A328",
+"h c #2AA22A",
+"j c #3AA23A",
+"k c #3EA33E",
+"l c #00CC00",
+"z c #00D000",
+"x c #418141",
+"c c #458545",
+"v c #4A844A",
+"b c #469246",
+"n c #479C47",
+"m c #4D904D",
+"M c #4E974E",
+"N c #43A043",
+"B c #52A752",
+"V c #57A957",
+"C c #5BA95B",
+"Z c #6BB26B",
+"A c #70B670",
+"S c #83C183",
+"D c None",
+/* pixels */
+"DDDDDDDDDDDDDDDD",
+"DDDDDDDDDDDDDDDD",
+"DDDDDDDDDDDDDDDD",
+"DDDDDDDDDDDDDDDD",
+"D vcduy3;<88tg;D",
+"DD*SZBjf60lzw4DD",
+"DDDxAVkh<9qqrDDD",
+"DDDDmCNp,<6eDDDD",
+"DDDD.Mni=-2:DDDD",
+"DDDDDoba+@$DDDDD",
+"DDDDDD%sX#DDDDDD",
+"DDDDDDD&ODDDDDDD",
+"DDDDDDDDDDDDDDDD",
+"DDDDDDDDDDDDDDDD",
+"DDDDDDDDDDDDDDDD",
+"DDDDDDDDDDDDDDDD"
+};
diff --git a/mgllab/xpm/arrow-left-double.xpm b/mgllab/xpm/arrow-left-double.xpm
new file mode 100644
index 0000000..a687b9b
--- /dev/null
+++ b/mgllab/xpm/arrow-left-double.xpm
@@ -0,0 +1,128 @@
+/* XPM */
+static const char *arrow_left_double_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 106 2 ",
+"   c #034703",
+".  c #004E00",
+"X  c #015B01",
+"o  c #085408",
+"O  c #0D5C0E",
+"+  c #0F5C0F",
+"@  c #016E01",
+"#  c #096809",
+"$  c #007500",
+"%  c #007F00",
+"&  c #0D7D0F",
+"*  c #166517",
+"=  c #1F671F",
+"-  c #0E7010",
+";  c #2C6A2C",
+":  c #237D23",
+">  c #2D792D",
+",  c #337133",
+"<  c #347F34",
+"1  c #3A773A",
+"2  c #3C743C",
+"3  c #397939",
+"4  c #3D7E3D",
+"5  c #008A00",
+"6  c #008C00",
+"7  c #008F00",
+"8  c #038E06",
+"9  c #09820C",
+"0  c #09890A",
+"q  c #009000",
+"w  c #039406",
+"e  c #069706",
+"r  c #009900",
+"t  c #009A00",
+"y  c #009A02",
+"u  c #009D00",
+"i  c #009E00",
+"p  c #0C920D",
+"a  c #108211",
+"s  c #118611",
+"d  c #138513",
+"f  c #1B811B",
+"g  c #0F9611",
+"h  c #159315",
+"j  c #139815",
+"k  c #169518",
+"l  c #19971B",
+"z  c #189B18",
+"x  c #1B9E1B",
+"c  c #189B1C",
+"v  c #1A9A1E",
+"b  c #1E9D1F",
+"n  c #1F9D1F",
+"m  c #00A000",
+"M  c #00A300",
+"N  c #00A500",
+"B  c #01A401",
+"V  c #00AB00",
+"C  c #00AE00",
+"Z  c #07AD07",
+"A  c #00B302",
+"S  c #00B500",
+"D  c #00B600",
+"F  c #00B700",
+"G  c #00B800",
+"H  c #00BA00",
+"J  c #00BB00",
+"K  c #16AB18",
+"L  c #17B819",
+"P  c #278927",
+"I  c #259825",
+"U  c #2B922B",
+"Y  c #2B942B",
+"T  c #299C2C",
+"R  c #308830",
+"E  c #398539",
+"W  c #309B30",
+"Q  c #349F34",
+"!  c #3A9F3A",
+"~  c #3E9D3E",
+"^  c #29A52C",
+"/  c #00C900",
+"(  c #07CD07",
+")  c #408240",
+"_  c #458145",
+"`  c #458245",
+"'  c #468746",
+"]  c #409040",
+"[  c #479447",
+"{  c #439943",
+"}  c #449944",
+"|  c #499149",
+" . c #499F49",
+".. c #509350",
+"X. c #529052",
+"o. c #589B58",
+"O. c #4EA44E",
+"+. c #52A552",
+"@. c #57A557",
+"#. c #5BA45B",
+"$. c #5DA35D",
+"%. c #6BB16B",
+"&. c #70AA70",
+"*. c #70B370",
+"=. c #83C083",
+"-. c None",
+/* pixels */
+"-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.",
+"-.-.-.-.-.-.-.-.-.. -.-.-.. -.-.",
+"-.-.-.-.-.-.-.-., _ -.-.; 2 -.-.",
+"-.-.-.-.-.-.-._ =.) -.4 &.3 -.-.",
+"-.-.-.-.-.o ..*.%.E | $.o.> -.-.",
+"-.-.-.-.+ ..#. at .+.O. .} ] : -.-.",
+"-.-.-.* ' [ { ~ ! Q W Y P f -.-.",
+"-.-.= 1 < R U I I x z h s d -.-.",
+"-.-.+   X @ 5 q m N N t 6 0 -.-.",
+"-.-.-.- # $ 5 i C G A C t p -.-.",
+"-.-.-.-.& & 6 N G ( / G m g -.-.",
+"-.-.-.-.-.& l N J L A A i j -.-.",
+"-.-.-.-.-.-.-.n Z K -.t e k -.-.",
+"-.-.-.-.-.-.-.-.c ^ -.-.c T -.-.",
+"-.-.-.-.-.-.-.-.-.8 -.-.-.w -.-.",
+"-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-."
+};
diff --git a/mgllab/xpm/arrow-left.xpm b/mgllab/xpm/arrow-left.xpm
new file mode 100644
index 0000000..d4de224
--- /dev/null
+++ b/mgllab/xpm/arrow-left.xpm
@@ -0,0 +1,86 @@
+/* XPM */
+static const char *arrow_left_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 64 1 ",
+"  c #034703",
+". c #004E00",
+"X c #075307",
+"o c #015B01",
+"O c #0D5C0E",
+"+ c #0F5C0F",
+"@ c #026F02",
+"# c #096809",
+"$ c #007500",
+"% c #007F00",
+"& c #0D7D0F",
+"* c #186619",
+"= c #1F671F",
+"- c #0E7010",
+"; c #327032",
+": c #337E33",
+"> c #397639",
+", c #008A00",
+"< c #008F00",
+"1 c #038E06",
+"2 c #09820C",
+"3 c #009000",
+"4 c #009D00",
+"5 c #09960A",
+"6 c #108211",
+"7 c #19971B",
+"8 c #1C931C",
+"9 c #1A9A1E",
+"0 c #1E9D1F",
+"q c #00A500",
+"w c #01A401",
+"e c #00AE00",
+"r c #07AD07",
+"t c #0CA40D",
+"y c #00BA00",
+"u c #00BB00",
+"i c #16AB18",
+"p c #0FB011",
+"a c #13B415",
+"s c #248D24",
+"d c #2F872F",
+"f c #2D892D",
+"g c #239E23",
+"h c #279927",
+"j c #2D922D",
+"k c #3A853A",
+"l c #3A9F3A",
+"z c #3E9D3E",
+"x c #29A52C",
+"c c #438143",
+"v c #458545",
+"b c #468746",
+"n c #4A844A",
+"m c #4F8E4F",
+"M c #479447",
+"N c #439943",
+"B c #4F934F",
+"V c #52A552",
+"C c #57A557",
+"Z c #5BA45B",
+"A c #6BB16B",
+"S c #70B370",
+"D c #83C083",
+"F c None",
+/* pixels */
+"FFFFFFFFFFFFFFFF",
+"FFFFFFFFFFF.FFFF",
+"FFFFFFFFFF;nFFFF",
+"FFFFFFFFFcDbFFFF",
+"FFFFFFFXmSAkFFFF",
+"FFFFFF+BZCVfFFFF",
+"FFFFF*bMNzlsFFFF",
+"FFFF=>:djhg8FFFF",
+"FFFF+ o@%345FFFF",
+"FFFFF-#$,4etFFFF",
+"FFFFFF&6<wupFFFF",
+"FFFFFFF27wuaFFFF",
+"FFFFFFFFF0riFFFF",
+"FFFFFFFFFF9xFFFF",
+"FFFFFFFFFFF1FFFF",
+"FFFFFFFFFFFFFFFF"
+};
diff --git a/mgllab/xpm/arrow-right-double.xpm b/mgllab/xpm/arrow-right-double.xpm
new file mode 100644
index 0000000..1e6ee90
--- /dev/null
+++ b/mgllab/xpm/arrow-right-double.xpm
@@ -0,0 +1,128 @@
+/* XPM */
+static const char *arrow_right_double_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 106 2 ",
+"   c #004E00",
+".  c #035C03",
+"X  c #085408",
+"o  c #0F5F0F",
+"O  c #016F01",
+"+  c #0D650E",
+"@  c #007B00",
+"#  c #097B09",
+"$  c #0D7F0F",
+"%  c #166917",
+"&  c #1F6E1F",
+"*  c #0E7610",
+"=  c #117911",
+"-  c #137D13",
+";  c #1B7B1B",
+":  c #2C682C",
+">  c #237723",
+",  c #277F27",
+"<  c #2D752D",
+"1  c #337133",
+"2  c #397539",
+"3  c #3C733C",
+"4  c #3D7C3D",
+"5  c #018001",
+"6  c #008500",
+"7  c #008700",
+"8  c #068206",
+"9  c #008900",
+"0  c #008A00",
+"q  c #008C00",
+"w  c #038E06",
+"e  c #09800A",
+"r  c #09820C",
+"t  c #0C870D",
+"y  c #009000",
+"u  c #009202",
+"i  c #039406",
+"p  c #009900",
+"a  c #009A00",
+"s  c #009D00",
+"d  c #009E00",
+"f  c #0F8B11",
+"g  c #158915",
+"h  c #138D15",
+"j  c #168B18",
+"k  c #109411",
+"l  c #189618",
+"z  c #18961C",
+"x  c #1B9D1B",
+"c  c #1A9C1E",
+"v  c #00A000",
+"b  c #00A300",
+"n  c #00A500",
+"m  c #00A502",
+"M  c #00AB00",
+"N  c #00AE00",
+"B  c #00B600",
+"V  c #00B700",
+"C  c #00B800",
+"Z  c #00BB00",
+"A  c #01BA01",
+"S  c #07B807",
+"D  c #19A21B",
+"F  c #1FA11F",
+"G  c #1EA31F",
+"H  c #16AA18",
+"J  c #17B619",
+"K  c #2B8D2B",
+"L  c #28942B",
+"P  c #2B9C2B",
+"I  c #348B34",
+"U  c #3A833A",
+"Y  c #398539",
+"T  c #309530",
+"R  c #309730",
+"E  c #349E34",
+"W  c #25A125",
+"Q  c #28A42B",
+"!  c #3AA23A",
+"~  c #3EA33E",
+"^  c #00CC00",
+"/  c #07CA07",
+"(  c #00D000",
+")  c #408240",
+"_  c #458145",
+"`  c #458345",
+"'  c #408840",
+"]  c #469246",
+"[  c #449444",
+"{  c #479C47",
+"}  c #499049",
+"|  c #499C49",
+" . c #529452",
+".. c #509950",
+"X. c #589658",
+"o. c #5D9F5D",
+"O. c #43A043",
+"+. c #4EA34E",
+"@. c #52A752",
+"#. c #57A957",
+"$. c #5BA95B",
+"%. c #6BB26B",
+"&. c #70A670",
+"*. c #70B570",
+"=. c #83C183",
+"-. c None",
+/* pixels */
+"-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.",
+"-.-.  -.-.-.  -.-.-.-.-.-.-.-.-.",
+"-.-.3 : -.-._ 1 -.-.-.-.-.-.-.-.",
+"-.-.2 &.4 -.) =._ -.-.-.-.-.-.-.",
+"-.-.< X.o.} Y %.*. .X -.-.-.-.-.",
+"-.-.> ' [ | +. at .$.$...o -.-.-.-.",
+"-.-.; , K R E ! ~ O.{ ] % -.-.-.",
+"-.-.- = g l x F W P R I Y & -.-.",
+"-.-.# @ q a b n s y 5 O . + -.-.",
+"-.-.t 6 a M B Z N s 0 # * -.-.-.",
+"-.-.f 0 s B / ^ Z n k $ -.-.-.-.",
+"-.-.h 0 s m J ( Z D r -.-.-.-.-.",
+"-.-.j 8 y -.H S F -.-.-.-.-.-.-.",
+"-.-.L z -.-.Q c -.-.-.-.-.-.-.-.",
+"-.-.i -.-.-.w -.-.-.-.-.-.-.-.-.",
+"-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-."
+};
diff --git a/mgllab/xpm/arrow-right.xpm b/mgllab/xpm/arrow-right.xpm
new file mode 100644
index 0000000..4b1246f
--- /dev/null
+++ b/mgllab/xpm/arrow-right.xpm
@@ -0,0 +1,92 @@
+/* XPM */
+static const char *arrow_right_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 70 1 ",
+"  c #004E00",
+". c #005700",
+"X c #055905",
+"o c #0D570D",
+"O c #0A5C0A",
+"+ c #195F19",
+"@ c #006200",
+"# c #006300",
+"$ c #026C03",
+"% c #086608",
+"& c #0C630D",
+"* c #066F08",
+"= c #047405",
+"- c #037803",
+"; c #007F00",
+": c #007E02",
+"> c #067C07",
+", c #117A12",
+"< c #236B23",
+"1 c #2D782D",
+"2 c #327A32",
+"3 c #327F32",
+"4 c #018801",
+"5 c #09820C",
+"6 c #0B880E",
+"7 c #0C8D0F",
+"8 c #009400",
+"9 c #009700",
+"0 c #059B05",
+"q c #0C8F11",
+"w c #0F9213",
+"e c #129115",
+"r c #149216",
+"t c #119615",
+"y c #00A100",
+"u c #00A600",
+"i c #04A604",
+"p c #00B000",
+"a c #00B400",
+"s c #06BB06",
+"d c #0CB00C",
+"f c #0BBC0B",
+"g c #16B117",
+"h c #2E992E",
+"j c #368836",
+"k c #319031",
+"l c #25A325",
+"z c #2AA02A",
+"x c #2AA52A",
+"c c #2CA92E",
+"v c #3CA23C",
+"b c #3EA43E",
+"n c #00C400",
+"m c #00C500",
+"M c #08D008",
+"N c #09D509",
+"B c #459E45",
+"V c #499A49",
+"C c #40A240",
+"Z c #55A855",
+"A c #55A955",
+"S c #5CA75C",
+"D c #59A959",
+"F c #6BAF6B",
+"G c #6DB36D",
+"H c #6DB46D",
+"J c #70AC70",
+"K c #7BAD7B",
+"L c #85C185",
+"P c None",
+/* pixels */
+"PPPPPPPPPPPPPPPP",
+"PPPPPPPPPPPPPPPP",
+"PPPP KoPPPPPPPPP",
+"PPPP LJ+PPPPPPPP",
+"PPPP.GHG<PPPPPPP",
+"PPPP at ZZDS1PPPPPP",
+"PPPP$bvCBV3XPPPP",
+"PPPP=xlzhkj2&PPP",
+"PPPP>iy84- at O%PPP",
+"PPPP5sau8;,*PPPP",
+"PPPP6Mmp0;PPPPPP",
+"PPPPqNmdrPPPPPPP",
+"PPPPwfgePPPPPPPP",
+"PPPPtcqPPPPPPPPP",
+"PPPPPPPPPPPPPPPP",
+"PPPPPPPPPPPPPPPP"
+};
diff --git a/mgllab/xpm/arrow-up-double.xpm b/mgllab/xpm/arrow-up-double.xpm
new file mode 100644
index 0000000..bedf985
--- /dev/null
+++ b/mgllab/xpm/arrow-up-double.xpm
@@ -0,0 +1,132 @@
+/* XPM */
+static const char *arrow_up_double_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 110 2 ",
+"   c #0B4C0B",
+".  c #045304",
+"X  c #0A5D0A",
+"o  c #185D18",
+"O  c #1A5D1A",
+"+  c #036103",
+"@  c #0C600C",
+"#  c #007300",
+"$  c #0B720B",
+"%  c #097E09",
+"&  c #146315",
+"*  c #106B11",
+"=  c #127D14",
+"-  c #256426",
+";  c #276927",
+":  c #296B29",
+">  c #2F6B2F",
+",  c #267C26",
+"<  c #277829",
+"1  c #357235",
+"2  c #307930",
+"3  c #367836",
+"4  c #347D34",
+"5  c #3A793A",
+"6  c #3C783C",
+"7  c #008800",
+"8  c #008900",
+"9  c #008E00",
+"0  c #048608",
+"q  c #0A820A",
+"w  c #088609",
+"e  c #048D08",
+"r  c #009600",
+"t  c #009700",
+"y  c #009A00",
+"u  c #009D00",
+"i  c #009F00",
+"p  c #099109",
+"a  c #0B900C",
+"s  c #0A910C",
+"d  c #089C08",
+"f  c #0C8A10",
+"g  c #108613",
+"h  c #168416",
+"j  c #1C801C",
+"k  c #198919",
+"l  c #0F9610",
+"z  c #119412",
+"x  c #129714",
+"c  c #159617",
+"v  c #15971A",
+"b  c #1D951D",
+"n  c #159D1A",
+"m  c #00A000",
+"M  c #00A400",
+"N  c #00A500",
+"B  c #00A700",
+"V  c #04A004",
+"C  c #00AA00",
+"Z  c #00B000",
+"A  c #00B200",
+"S  c #00B300",
+"D  c #00B400",
+"F  c #00B700",
+"G  c #00B800",
+"H  c #00BC00",
+"J  c #15AD17",
+"K  c #1BA21C",
+"L  c #17AD18",
+"P  c #1E9421",
+"I  c #1E9D21",
+"U  c #2D8A2D",
+"Y  c #239E23",
+"T  c #249F24",
+"R  c #279D27",
+"E  c #2B992B",
+"W  c #358B35",
+"Q  c #388138",
+"!  c #3A833A",
+"~  c #309230",
+"^  c #319431",
+"/  c #379C37",
+"(  c #3B9F3B",
+")  c #1EA421",
+"_  c #21A124",
+"`  c #00C500",
+"'  c #00C700",
+"]  c #0DC60E",
+"[  c #1AC11B",
+"{  c #408340",
+"}  c #438343",
+"|  c #418541",
+" . c #469246",
+".. c #449F44",
+"X. c #4E974E",
+"o. c #499B49",
+"O. c #4A9B4A",
+"+. c #5F9F5F",
+"@. c #40A040",
+"#. c #4FA04F",
+"$. c #50A350",
+"%. c #58A758",
+"&. c #5DA85D",
+"*. c #64A764",
+"=. c #63A863",
+"-. c #72A872",
+";. c #72B572",
+":. c #75B475",
+">. c #80BA80",
+",. c None",
+/* pixels */
+",.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.",
+",.,.,.,.,.,.,.,.< ,.,.,.,.,.,.,.",
+",.,.,.,.,.,.,.& - ,.,.,.,.,.,.,.",
+",.,.,.,.,.,.X 5   * ,.,.,.,.,.,.",
+",.,.,.,.,.. | ! @ + = ,.,.,.,.,.",
+",.,.,.,.,.{ X.W $ # % g ,.,.,.,.",
+",.,.,.,.3 =.o.~ q 7 9 z f ,.,.,.",
+",.,.,.: :.&...E p y N N K 0 ,.,.",
+",.,.O >.;.%. at .R d C G H S _ ,.,.",
+",.,.1 | ! #.( T V S ' [ J ) v ,.",
+",.,.,.,.4 #./ Y u S ` ] s ,.,.,.",
+",.,.,.; *.O.^ b r N D D L e ,.,.",
+",.,.O -.+. .U k 7 r m m r I ,.,.",
+",.,.> 6 2 , j h w s l x c P n ,.",
+",.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.",
+",.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,."
+};
diff --git a/mgllab/xpm/arrow-up.xpm b/mgllab/xpm/arrow-up.xpm
new file mode 100644
index 0000000..4d1e744
--- /dev/null
+++ b/mgllab/xpm/arrow-up.xpm
@@ -0,0 +1,86 @@
+/* XPM */
+static const char *arrow_up_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 64 1 ",
+"  c #004D00",
+". c #044804",
+"X c #055205",
+"o c #055D05",
+"O c #0D5A0D",
+"+ c #076707",
+"@ c #007500",
+"# c #067106",
+"$ c #0C710E",
+"% c #0B7D0D",
+"& c #156216",
+"* c #1A661B",
+"= c #1D631E",
+"- c #327032",
+"; c #347F34",
+": c #387638",
+"> c #028002",
+", c #008A00",
+"< c #008F00",
+"1 c #008E03",
+"2 c #038E06",
+"3 c #09810C",
+"4 c #0D810E",
+"5 c #009000",
+"6 c #009D00",
+"7 c #09960A",
+"8 c #159517",
+"9 c #16961A",
+"0 c #1C931C",
+"q c #00A400",
+"w c #00A500",
+"e c #00AE00",
+"r c #05AC05",
+"t c #0CA40D",
+"y c #00BA00",
+"u c #00BB00",
+"i c #16AB18",
+"p c #0FB011",
+"a c #13B415",
+"s c #258D25",
+"d c #2F872F",
+"f c #2D892D",
+"g c #259F25",
+"h c #2D932D",
+"j c #2A9A2A",
+"k c #3A853A",
+"l c #3A9F3A",
+"z c #3E9D3E",
+"x c #27A429",
+"c c #418041",
+"v c #458545",
+"b c #468946",
+"n c #4A844A",
+"m c #4D8C4D",
+"M c #479447",
+"N c #439943",
+"B c #4E924E",
+"V c #52A552",
+"C c #57A557",
+"Z c #5BA45B",
+"A c #6BB16B",
+"S c #70B370",
+"D c #83C083",
+"F c None",
+/* pixels */
+"FFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFF",
+"FFFFFFF=*FFFFFFF",
+"FFFFFF&:.$FFFFFF",
+"FFFFFOb;o+%FFFFF",
+"FFFFXBMd#@43FFFF",
+"FFFFmZNh>,<8FFFF",
+"FFFcSCzj56qq<FFF",
+"FF-DAVlg6euur9FF",
+"F nvkfs07tpaix2F",
+"FFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFF"
+};
diff --git a/mgllab/xpm/arrow_a.xpm b/mgllab/xpm/arrow_a.xpm
new file mode 100644
index 0000000..457c0aa
--- /dev/null
+++ b/mgllab/xpm/arrow_a.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * arrow_a_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"         ...    ",
+"       ....     ",
+"     .....      ",
+"   ......       ",
+" ...............",
+"   ......       ",
+"     .....      ",
+"       ....     ",
+"         ...    ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/arrow_d.xpm b/mgllab/xpm/arrow_d.xpm
new file mode 100644
index 0000000..834f703
--- /dev/null
+++ b/mgllab/xpm/arrow_d.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * arrow_d_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"     .          ",
+"    ...         ",
+"   .....        ",
+"  .......       ",
+" ...............",
+"  .......       ",
+"   .....        ",
+"    ...         ",
+"     .          ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/arrow_i.xpm b/mgllab/xpm/arrow_i.xpm
new file mode 100644
index 0000000..a8c617e
--- /dev/null
+++ b/mgllab/xpm/arrow_i.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * arrow_i_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+" ..             ",
+" ..             ",
+" ..             ",
+" ..             ",
+" ..             ",
+" ...............",
+" ..             ",
+" ..             ",
+" ..             ",
+" ..             ",
+" ..             ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/arrow_k.xpm b/mgllab/xpm/arrow_k.xpm
new file mode 100644
index 0000000..840d325
--- /dev/null
+++ b/mgllab/xpm/arrow_k.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * arrow_k_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+" ..             ",
+" ..      ...    ",
+" ..    ....     ",
+" ..  .....      ",
+" ........       ",
+" ...............",
+" ........       ",
+" ..  .....      ",
+" ..    ....     ",
+" ..      ...    ",
+" ..             ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/arrow_n.xpm b/mgllab/xpm/arrow_n.xpm
new file mode 100644
index 0000000..305238b
--- /dev/null
+++ b/mgllab/xpm/arrow_n.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * arrow_n_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"  ..............",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/arrow_o.xpm b/mgllab/xpm/arrow_o.xpm
new file mode 100644
index 0000000..6f4b583
--- /dev/null
+++ b/mgllab/xpm/arrow_o.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * arrow_o_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"    ....        ",
+"   ......       ",
+"  ........      ",
+"  ........      ",
+"  ..............",
+"  ........      ",
+"  ........      ",
+"  .......       ",
+"    ....        ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/arrow_s.xpm b/mgllab/xpm/arrow_s.xpm
new file mode 100644
index 0000000..ddeeb7f
--- /dev/null
+++ b/mgllab/xpm/arrow_s.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * arrow_s_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"  ........      ",
+"  ........      ",
+"  ........      ",
+"  ........      ",
+"  ..............",
+"  ........      ",
+"  ........      ",
+"  ........      ",
+"  ........      ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/arrow_t.xpm b/mgllab/xpm/arrow_t.xpm
new file mode 100644
index 0000000..71ff9dc
--- /dev/null
+++ b/mgllab/xpm/arrow_t.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * arrow_t_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"         ..     ",
+"       ....     ",
+"     ......     ",
+"   ........     ",
+" ...............",
+"   ........     ",
+"     ......     ",
+"       ....     ",
+"         ..     ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/arrow_v.xpm b/mgllab/xpm/arrow_v.xpm
new file mode 100644
index 0000000..038a3e5
--- /dev/null
+++ b/mgllab/xpm/arrow_v.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * arrow_v_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"  ...           ",
+"   ....         ",
+"    .....       ",
+"     ......     ",
+"     ...........",
+"     ......     ",
+"    .....       ",
+"   ....         ",
+"  ...           ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/axis.xpm b/mgllab/xpm/axis.xpm
new file mode 100644
index 0000000..65014f1
--- /dev/null
+++ b/mgllab/xpm/axis.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * axis_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+" ..             ",
+"  .             ",
+"  .             ",
+" ..             ",
+"  .             ",
+"  .             ",
+" ..             ",
+"  .             ",
+"  .             ",
+" ..             ",
+"  .             ",
+"  .             ",
+" .............. ",
+"  .   .   .   . ",
+"                "};
diff --git a/mgllab/xpm/axis_sh.xpm b/mgllab/xpm/axis_sh.xpm
new file mode 100644
index 0000000..d09869f
--- /dev/null
+++ b/mgllab/xpm/axis_sh.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * axis_sh_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #000000",
+"+	c #FF0000",
+"                ",
+"  .             ",
+". .      +      ",
+"  .     +++     ",
+"  .      +      ",
+". .   +  +  +   ",
+"  .  +++++++++  ",
+"  .   +  +  +   ",
+". .      +      ",
+"  .     +++     ",
+"  .      +      ",
+". .             ",
+"  .             ",
+"  ............. ",
+".               ",
+"  .  .  .  .  . "};
diff --git a/mgllab/xpm/barrow_a.xpm b/mgllab/xpm/barrow_a.xpm
new file mode 100644
index 0000000..8545b8f
--- /dev/null
+++ b/mgllab/xpm/barrow_a.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+const char * barrow_a_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"    ...         ",
+"     ....       ",
+"      .....     ",
+"       ......   ",
+"............... ",
+"       ......   ",
+"      .....     ",
+"     ....       ",
+"    ...         ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/barrow_d.xpm b/mgllab/xpm/barrow_d.xpm
new file mode 100644
index 0000000..fe133de
--- /dev/null
+++ b/mgllab/xpm/barrow_d.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+const char * barrow_d_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"          .     ",
+"         ...    ",
+"        .....   ",
+"       .......  ",
+"............... ",
+"       .......  ",
+"        .....   ",
+"         ...    ",
+"          .     ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/barrow_i.xpm b/mgllab/xpm/barrow_i.xpm
new file mode 100644
index 0000000..54e91ad
--- /dev/null
+++ b/mgllab/xpm/barrow_i.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+const char * barrow_i_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"             .. ",
+"             .. ",
+"             .. ",
+"             .. ",
+"             .. ",
+"............... ",
+"             .. ",
+"             .. ",
+"             .. ",
+"             .. ",
+"             .. ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/barrow_k.xpm b/mgllab/xpm/barrow_k.xpm
new file mode 100644
index 0000000..be962b1
--- /dev/null
+++ b/mgllab/xpm/barrow_k.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+const char * barrow_k_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"             .. ",
+"    ...      .. ",
+"     ....    .. ",
+"      .....  .. ",
+"       ........ ",
+"............... ",
+"       ........ ",
+"      .....  .. ",
+"     ....    .. ",
+"    ...      .. ",
+"             .. ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/barrow_n.xpm b/mgllab/xpm/barrow_n.xpm
new file mode 100644
index 0000000..7d2b54c
--- /dev/null
+++ b/mgllab/xpm/barrow_n.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+const char * barrow_n_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"..............  ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/barrow_o.xpm b/mgllab/xpm/barrow_o.xpm
new file mode 100644
index 0000000..a0ea264
--- /dev/null
+++ b/mgllab/xpm/barrow_o.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+const char * barrow_o_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"        ....    ",
+"       ......   ",
+"      ........  ",
+"      ........  ",
+"..............  ",
+"      ........  ",
+"      ........  ",
+"       .......  ",
+"        ....    ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/barrow_s.xpm b/mgllab/xpm/barrow_s.xpm
new file mode 100644
index 0000000..f19c4d8
--- /dev/null
+++ b/mgllab/xpm/barrow_s.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+const char * barrow_s_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"      ........  ",
+"      ........  ",
+"      ........  ",
+"      ........  ",
+"..............  ",
+"      ........  ",
+"      ........  ",
+"      ........  ",
+"      ........  ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/barrow_t.xpm b/mgllab/xpm/barrow_t.xpm
new file mode 100644
index 0000000..06e23d5
--- /dev/null
+++ b/mgllab/xpm/barrow_t.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+const char * barrow_t_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"     ..         ",
+"     ....       ",
+"     ......     ",
+"     ........   ",
+"............... ",
+"     ........   ",
+"     ......     ",
+"     ....       ",
+"     ..         ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/barrow_v.xpm b/mgllab/xpm/barrow_v.xpm
new file mode 100644
index 0000000..b31d4d2
--- /dev/null
+++ b/mgllab/xpm/barrow_v.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+const char * barrow_v_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"           ...  ",
+"         ....   ",
+"       .....    ",
+"     ......     ",
+"...........     ",
+"     ......     ",
+"       .....    ",
+"         ....   ",
+"           ...  ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/box.xpm b/mgllab/xpm/box.xpm
new file mode 100644
index 0000000..23260d1
--- /dev/null
+++ b/mgllab/xpm/box.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * box_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #000000",
+"+	c #666666",
+"                ",
+"      ......... ",
+"     .+      .. ",
+"    . +     . . ",
+"   .  +    .  . ",
+"  .   +   .   . ",
+" .........    . ",
+" .    +  .    . ",
+" .    +  .    . ",
+" .    +++.++++. ",
+" .   +   .   .  ",
+" .  +    .  .   ",
+" . +     . .    ",
+" .+      ..     ",
+" .........      ",
+"                "};
diff --git a/mgllab/xpm/comment.xpm b/mgllab/xpm/comment.xpm
new file mode 100644
index 0000000..1aebddd
--- /dev/null
+++ b/mgllab/xpm/comment.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * comment_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #009f00",
+"                ",
+"                ",
+"                ",
+"     .    .     ",
+"     .    .     ",
+"     .    .     ",
+"  ............  ",
+"     .    .     ",
+"     .    .     ",
+"     .    .     ",
+"     .    .     ",
+"  ............  ",
+"     .    .     ",
+"     .    .     ",
+"     .    .     ",
+"                "};
diff --git a/mgllab/xpm/cons.xpm b/mgllab/xpm/cons.xpm
new file mode 100644
index 0000000..b22b0f4
--- /dev/null
+++ b/mgllab/xpm/cons.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char * cons_xpm[] = {
+"16 16 4 1",
+" 	c None",
+".	c #000000",
+"+	c #0000FF",
+"@	c #FF0000",
+"                ",
+" .............. ",
+" .            . ",
+" . . . . . . .. ",
+" .            . ",
+" . . . . . . .. ",
+" .............. ",
+"                ",
+"  +++++++++++++ ",
+"    +++++++++   ",
+"      +++++     ",
+"        +       ",
+" @@@@@@@@@@@@@@ ",
+" @ @ @ @ @ @ @@ ",
+" @@@@@@@@@@@@@@ ",
+"                "};
diff --git a/mgllab/xpm/copy.xpm b/mgllab/xpm/copy.xpm
new file mode 100644
index 0000000..bfaecb1
--- /dev/null
+++ b/mgllab/xpm/copy.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char * copy_xpm[] = {
+"16 16 4 1",
+" 	c None",
+".	c #000000",
+"+	c #FFFFFF",
+"@	c #808080",
+"                ",
+"                ",
+"  ........      ",
+"  .++++++.@     ",
+"  .+@@@@+.@     ",
+"  .++........   ",
+"  .+ at .++++++.@  ",
+"  .++.+....+.@  ",
+"  .+ at .++++++.@  ",
+"  .++.+....+.@  ",
+"  ....++++++.@  ",
+"    @.+....+.@  ",
+"     .++++++.@  ",
+"     ........@  ",
+"      @@@@@@@@  ",
+"                "};
diff --git a/mgllab/xpm/crop.xpm b/mgllab/xpm/crop.xpm
new file mode 100644
index 0000000..e18a730
--- /dev/null
+++ b/mgllab/xpm/crop.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * crop_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"     .          ",
+"                ",
+"     .          ",
+"                ",
+" . . ......     ",
+"     .    .     ",
+"     .    .     ",
+"     .    .     ",
+"     .    .     ",
+"     ...... . . ",
+"                ",
+"          .     ",
+"                ",
+"          .     ",
+"                "};
diff --git a/mgllab/xpm/curve.xpm b/mgllab/xpm/curve.xpm
new file mode 100644
index 0000000..88e37e3
--- /dev/null
+++ b/mgllab/xpm/curve.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * curve_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"               .",
+"               .",
+"              . ",
+"              . ",
+"             .  ",
+"            .   ",
+"          ..    ",
+"        ..      ",
+"      ..        ",
+"    ..          ",
+"   .            ",
+"  .             ",
+" .              ",
+" .              ",
+".               ",
+".               "};
diff --git a/mgllab/xpm/dash_d.xpm b/mgllab/xpm/dash_d.xpm
new file mode 100644
index 0000000..6892ce6
--- /dev/null
+++ b/mgllab/xpm/dash_d.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * dash_d_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+".   .   .   .   ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/dash_e.xpm b/mgllab/xpm/dash_e.xpm
new file mode 100644
index 0000000..13eaf63
--- /dev/null
+++ b/mgllab/xpm/dash_e.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * dash_e_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+". . . . . . . . ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/dash_i.xpm b/mgllab/xpm/dash_i.xpm
new file mode 100644
index 0000000..2ad1f1c
--- /dev/null
+++ b/mgllab/xpm/dash_i.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * dash_i_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+".. . .. . .. . .",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/dash_j.xpm b/mgllab/xpm/dash_j.xpm
new file mode 100644
index 0000000..70a9cc4
--- /dev/null
+++ b/mgllab/xpm/dash_j.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * dash_j_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"....  .  ....  .",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/dash_l.xpm b/mgllab/xpm/dash_l.xpm
new file mode 100644
index 0000000..4346c08
--- /dev/null
+++ b/mgllab/xpm/dash_l.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * dash_l_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"....    ....    ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/dash_m.xpm b/mgllab/xpm/dash_m.xpm
new file mode 100644
index 0000000..7cd2b39
--- /dev/null
+++ b/mgllab/xpm/dash_m.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * dash_m_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"..  ..  ..  ..  ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/dash_s.xpm b/mgllab/xpm/dash_s.xpm
new file mode 100644
index 0000000..4edb6c5
--- /dev/null
+++ b/mgllab/xpm/dash_s.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * dash_s_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"................",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/delete.xpm b/mgllab/xpm/delete.xpm
new file mode 100644
index 0000000..a191ea2
--- /dev/null
+++ b/mgllab/xpm/delete.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * delete_xpm[] = {
+"16 16 2 1",
+" 	c none",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"  ...      ...  ",
+"   ...    ...   ",
+"    ...  ...    ",
+"     ......     ",
+"      ....      ",
+"      ....      ",
+"     ......     ",
+"    ...  ...    ",
+"   ...    ...   ",
+"  ...      ...  ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/dialog-information.xpm b/mgllab/xpm/dialog-information.xpm
new file mode 100644
index 0000000..3cad076
--- /dev/null
+++ b/mgllab/xpm/dialog-information.xpm
@@ -0,0 +1,138 @@
+/* XPM */
+static const char *dialog_information_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 116 2 ",
+"   c gray19",
+".  c #393936",
+"X  c #5E5E3E",
+"o  c #3A4A77",
+"O  c #3A4B77",
+"+  c #3B4B77",
+"@  c #3D4C76",
+"#  c #3D4D76",
+"$  c #384978",
+"%  c #384A79",
+"&  c #394A79",
+"*  c #394B7A",
+"=  c #3A4B7A",
+"-  c #3B4C78",
+";  c #3C4D78",
+":  c #3E4E79",
+">  c #464646",
+",  c #435177",
+"<  c #40507A",
+"1  c #41517B",
+"2  c #45547E",
+"3  c #46557F",
+"4  c #4A577A",
+"5  c #80805C",
+"6  c #8A8B66",
+"7  c #475780",
+"8  c #485883",
+"9  c #4B5B83",
+"0  c #495985",
+"q  c #4A5A86",
+"w  c #546083",
+"e  c #586383",
+"r  c #5E6880",
+"t  c #4B7EB2",
+"y  c #5E8DBA",
+"u  c #608EBC",
+"i  c #7E91B1",
+"p  c #7E90B2",
+"a  c #779DC5",
+"s  c #789DC4",
+"d  c #A8AA84",
+"f  c #A6AC98",
+"g  c #A7AD98",
+"h  c #ABB198",
+"j  c #8C9BB8",
+"k  c #8D9CB8",
+"l  c #98A4BD",
+"z  c #9AA5BE",
+"x  c #DDDFAB",
+"c  c #D3D5B0",
+"v  c #E3E6BA",
+"b  c #87A8CC",
+"n  c #91AECD",
+"m  c #9BAEC8",
+"M  c #9DB9D6",
+"N  c #A4ADC3",
+"B  c #A5BED8",
+"V  c #A6BED8",
+"C  c #A9C0D9",
+"Z  c #AAC1D9",
+"A  c #B7C2D5",
+"S  c #B9C4D6",
+"D  c #B5C6DA",
+"F  c #B5C7DB",
+"G  c #B5CAE0",
+"H  c #C1CCD7",
+"J  c #EBEDC1",
+"K  c #F3F6C9",
+"L  c #F5F8CA",
+"P  c #C2D0E0",
+"I  c #C0D0E3",
+"U  c #C5D2E1",
+"Y  c #C1D2E4",
+"T  c #C2D3E4",
+"R  c #C3D3E4",
+"E  c #C5D5E5",
+"W  c #C7D6E5",
+"Q  c #C9D6E7",
+"!  c #C8D7E8",
+"~  c #CBD9E8",
+"^  c #CCD9E8",
+"/  c #CEDBE9",
+"(  c #D0D5E0",
+")  c #D2DAE2",
+"_  c #D0DDEB",
+"`  c #D3DFEB",
+"'  c #D4E0EC",
+"]  c #D4E0ED",
+"[  c #D6E1ED",
+"{  c #D8E2ED",
+"}  c #D9E3EE",
+"|  c #DEE7F1",
+" . c #DFE7F2",
+".. c #DFE8F2",
+"X. c #E0E5ED",
+"o. c #E0E6EC",
+"O. c #E2E7EF",
+"+. c #E0E9F2",
+"@. c #E2EAF3",
+"#. c #E8EFF4",
+"$. c #E8EFF5",
+"%. c #EDEFF4",
+"&. c #EBF0F5",
+"*. c #EBF0F6",
+"=. c #ECF1F7",
+"-. c #EFF3F7",
+";. c #EEF3F8",
+":. c #F3F7FA",
+">. c #F4F7FA",
+",. c #F5F8FA",
+"<. c #F7F9FB",
+"1. c #FAFBFD",
+"2. c #FAFCFD",
+"3. c #FCFCFD",
+"4. c white",
+"5. c None",
+/* pixels */
+"5.5.5.5.5.= o $ $ o # 5.5.5.5.5.",
+"5.5.5.5.- N %.4.,.X.z ; 5.5.5.5.",
+"5.5.5.; ( ,.&. at .} ` [ S 1 5.5.5.",
+"5.5.# N ,.;.:.&.+.[ R E k , 5.5.",
+"5.5.; &.&.>.2.&.| ` Y s U 7 5.5.",
+"5.5.= 1.+.;.4.4.4.4.H 5./ - 5.5.",
+"5.5.= >.[ | 4.&.} ) n 5.Q = 5.5.",
+"5.5.2 X.^ ! 4.I F B 5.y F 0 5.5.",
+"5.5.4 l ' C 4.V b 5.t Z p w 5.5.",
+"5.5.5.9 A I a 4.5.y Z m 0 5.5.5.",
+"5.5.5.5.2 k I ^ E F p 0 5.5.5.5.",
+"5.5.5.5.5.e 9 g g h r 5.5.5.5.5.",
+"5.5.5.5.5.5.X J L x X 5.5.5.5.5.",
+"5.5.5.5.5.5.X 5 d 6 X 5.5.5.5.5.",
+"5.5.5.5.5.5.X v K c X 5.5.5.5.5.",
+"5.5.5.5.5.5.5.. >   5.5.5.5.5.5."
+};
diff --git a/mgllab/xpm/diff.xpm b/mgllab/xpm/diff.xpm
new file mode 100644
index 0000000..b90448a
--- /dev/null
+++ b/mgllab/xpm/diff.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * diff_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"   ..           ",
+"  .  .   .      ",
+"     .  .       ",
+"  ....  .       ",
+" .   . .  ..    ",
+" .  .  . .  .   ",
+"  ..  .     .   ",
+"      .  ....   ",
+"     .  .   .   ",
+"     .  .  . . .",
+"    .    ..   . ",
+"             . .",
+"                ",
+"                "};
diff --git a/mgllab/xpm/diff2.xpm b/mgllab/xpm/diff2.xpm
new file mode 100644
index 0000000..7a2d7eb
--- /dev/null
+++ b/mgllab/xpm/diff2.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * diff2_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #000000",
+"+	c #7F7F7F",
+"                ",
+"                ",
+"                ",
+"                ",
+"       .        ",
+"       ..       ",
+"      .+..      ",
+"     +. ..+     ",
+"     .   ..     ",
+"    .+   +..    ",
+"   +.     ..+   ",
+"   .       ..   ",
+"  .+       +..  ",
+"  ............  ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/document-export.xpm b/mgllab/xpm/document-export.xpm
new file mode 100644
index 0000000..b1119d2
--- /dev/null
+++ b/mgllab/xpm/document-export.xpm
@@ -0,0 +1,169 @@
+/* XPM */
+static const char *document_export_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 147 2 ",
+"   c #4E6A7D",
+".  c #58787A",
+"X  c #667173",
+"o  c #627075",
+"O  c #B30000",
+"+  c #B60000",
+"@  c #BB0000",
+"#  c #E60000",
+"$  c #EE1200",
+"%  c #E21D00",
+"&  c #E92400",
+"*  c #EA2400",
+"=  c #FF3500",
+"-  c #FE3C00",
+";  c #F94100",
+":  c #FA4200",
+">  c #FB4D00",
+",  c #FC5500",
+"<  c #FE5F00",
+"1  c #F86B00",
+"2  c #F97200",
+"3  c #FF7400",
+"4  c #FE7E00",
+"5  c #F88F01",
+"6  c #EF9800",
+"7  c #FF9100",
+"8  c #F89A00",
+"9  c #F99A00",
+"0  c #FF9A00",
+"q  c #ECA307",
+"w  c #FDB701",
+"e  c #FDA917",
+"r  c #BDFB3F",
+"t  c #F2C505",
+"y  c #FAC004",
+"u  c #F0CA07",
+"i  c #F8C805",
+"p  c #F2D10B",
+"a  c #DDE01B",
+"s  c #DDFE1F",
+"d  c #ECEA10",
+"f  c #E3FF18",
+"g  c #D2EA2B",
+"h  c #C7FF34",
+"j  c #E4E822",
+"k  c #BDD552",
+"l  c #AFFA4D",
+"z  c #B7F746",
+"x  c #BBFF41",
+"c  c #B2FA4B",
+"v  c #AAFF53",
+"b  c #94FB69",
+"n  c #8BFF72",
+"m  c #85FE79",
+"M  c #80F87D",
+"N  c #A0FE7E",
+"B  c #0024B3",
+"V  c #38678B",
+"C  c #37698D",
+"Z  c #3D698A",
+"A  c #3B6B8F",
+"S  c #3D6B8E",
+"D  c #3F6C8E",
+"F  c #4A6D85",
+"G  c #436E88",
+"H  c #4A7180",
+"J  c #41749A",
+"K  c #44789F",
+"L  c #547D9B",
+"P  c #6B7F88",
+"I  c #0029CA",
+"U  c #0037E9",
+"Y  c #0037EC",
+"T  c #0035F2",
+"R  c #0039FF",
+"E  c #003DFE",
+"W  c #0041FF",
+"Q  c #0045FC",
+"!  c #0057FF",
+"~  c #006CFF",
+"^  c #006DFF",
+"/  c #0074F6",
+"(  c #5186AF",
+")  c #5892BD",
+"_  c #688BA0",
+"`  c #6E99B6",
+"'  c #7798B0",
+"]  c #719FBF",
+"[  c #6EF18E",
+"{  c #75F389",
+"}  c #59FEA3",
+"|  c #51FFAC",
+" . c #49FEB4",
+".. c #43FABA",
+"X. c #53F8BE",
+"o. c #0082FF",
+"O. c #009FFF",
+"+. c #328AFE",
+"@. c #02ABF0",
+"#. c #00AEFF",
+"$. c #03BDFB",
+"%. c #739FC0",
+"&. c #79A7CA",
+"*. c #21CBDE",
+"=. c #1CFFDF",
+"-. c #2FE6CE",
+";. c #3DF5C0",
+":. c #32FFCA",
+">. c #2BECD2",
+",. c #28FFD3",
+"<. c #17CDE7",
+"1. c #13DBEB",
+"2. c #0ED7F0",
+"3. c #08D3F4",
+"4. c #0BDAF2",
+"5. c #3BC4F1",
+"6. c #16FFE5",
+"7. c #13FFE9",
+"8. c #0BEBF1",
+"9. c #8BA4AF",
+"0. c #92A6AC",
+"q. c #95A9AF",
+"w. c #9AAEB4",
+"e. c #9DE4A5",
+"r. c #CAC6AC",
+"t. c #8FB3CE",
+"y. c #92B7D3",
+"u. c #96BBD8",
+"i. c #9EBFD9",
+"p. c #98BFDC",
+"a. c #ACBCC3",
+"s. c #AABCD1",
+"d. c #9BC2DF",
+"f. c #ABC8DF",
+"g. c #8CFDCB",
+"h. c #9EDEE9",
+"j. c #ABCBE2",
+"k. c #ACCBE3",
+"l. c #B1CEE6",
+"z. c #BFE6E5",
+"x. c #BBF8EA",
+"c. c #C1D9EB",
+"v. c #C5DBEC",
+"b. c #D5DFE5",
+"n. c #D0DFEF",
+"m. c #EEEEEE",
+"M. c None",
+/* pixels */
+"M.M.M.V V V Z H . M.M.M.M.M.M.M.",
+"M.M.M.l.n.v.d._ G M.M.M.M.M.M.M.",
+"P X o F J K i.c.(   M.M.M.M.M.M.",
+"M.M.M.M.M.` V j.y.L b.M.M.M.M.M.",
+"M.M.M.M.M.' V &.t.S a.M.M.M.M.M.",
+"M.M.M.V V V V &.) V V V V M.M.M.",
+"M.6 q k V p.] ] ] %.u.V q. at ./ M.",
+"M.2 - = r.V p.%.%.f.V 0.z.=.:.M.",
+"M.9 3 e j e.C k.p.A 9.h.g.x d M.",
+"M.t c X.5.+.s.D V w.x.N m.y w M.",
+"M.a  .#.R B I ! $.,.m f s h n M.",
+"M.u l } -.*.<.1.7.6...;.>.3.O.M.",
+"M.9 < > , 4 i r | 4.o.Q Y E W M.",
+"M.1 # + O @ $ 0 v 8.~ T U ~ 2.M.",
+"M.5 : * % * : 7 p z M [ { b g M.",
+"M.M.M.M.M.M.M.M.M.M.M.M.M.M.M.M."
+};
diff --git a/mgllab/xpm/document-import.xpm b/mgllab/xpm/document-import.xpm
new file mode 100644
index 0000000..edb07cd
--- /dev/null
+++ b/mgllab/xpm/document-import.xpm
@@ -0,0 +1,197 @@
+/* XPM */
+static const char *document_import_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 175 2 ",
+"   c #001230",
+".  c #001431",
+"X  c #001E45",
+"o  c #0E2A4A",
+"O  c #11345E",
+"+  c #18395B",
+"@  c #224164",
+"#  c #274466",
+"$  c #25466A",
+"%  c #21436D",
+"&  c #2B4B71",
+"*  c #2A4B73",
+"=  c #284C76",
+"-  c #2F527A",
+";  c #30527B",
+":  c #485D78",
+">  c #495F7B",
+",  c #4A5F7C",
+"<  c #C00000",
+"1  c #C40100",
+"2  c #DE1900",
+"3  c #DE1A00",
+"4  c #E00600",
+"5  c #ED1C00",
+"6  c #F32E00",
+"7  c #F42F00",
+"8  c #FF3F00",
+"9  c #FA6201",
+"0  c #FF6200",
+"q  c #FB6801",
+"w  c #FB7E01",
+"e  c #FF8400",
+"r  c #FAA302",
+"t  c #F9A502",
+"y  c #FAA205",
+"u  c #F5A10A",
+"i  c #F1B50D",
+"p  c #E0A31C",
+"a  c #CCB833",
+"s  c #F5CE09",
+"d  c #EDDE11",
+"f  c #E6DE18",
+"g  c #DFE11A",
+"h  c #DDE31D",
+"j  c #EDEC10",
+"k  c #E5E019",
+"l  c #E1FF1B",
+"z  c #C6FB38",
+"x  c #B3DD4C",
+"c  c #BFE240",
+"v  c #B7F047",
+"b  c #91F96D",
+"n  c #91FF6C",
+"m  c #8CFF72",
+"M  c #83FC7B",
+"N  c #85FF79",
+"B  c #0030BE",
+"V  c #3E5E87",
+"C  c #3D6492",
+"Z  c #39679B",
+"A  c #3F74B0",
+"S  c #455F80",
+"D  c #506481",
+"F  c #4A6A90",
+"G  c #4F769F",
+"H  c #51729B",
+"J  c #4A73A7",
+"K  c #4A75A6",
+"L  c #4976AD",
+"P  c #5079A9",
+"I  c #517AAA",
+"U  c #587FAD",
+"Y  c #4074B0",
+"T  c #4076B4",
+"R  c #437AB9",
+"E  c #547FB5",
+"W  c #0032C9",
+"Q  c #004EE6",
+"!  c #0051EC",
+"~  c #0041FF",
+"^  c #0043FF",
+"/  c #004CFC",
+"(  c #004DFF",
+")  c #0062FD",
+"_  c #0064FF",
+"`  c #0066FF",
+"'  c #0374F4",
+"]  c #047CF5",
+"[  c #0070FF",
+"{  c #0170FF",
+"}  c #0279F8",
+"|  c #7EFF81",
+" . c #73F18B",
+".. c #60EA9E",
+"X. c #61F29D",
+"o. c #65FA99",
+"O. c #5AE5A4",
+"+. c #5CFEA1",
+"@. c #59FCA5",
+"#. c #58FFA6",
+"$. c #56FAA8",
+"%. c #43FFBB",
+"&. c #0297FD",
+"*. c #0195FF",
+"=. c #059FF9",
+"-. c #049DFB",
+";. c #10BFEE",
+":. c #0AA6F5",
+">. c #08A6F7",
+",. c #0FB6F0",
+"<. c #5887C2",
+"1. c #7CA3D6",
+"2. c #7DA3D6",
+"3. c #7EA3D6",
+"4. c #7FA6D7",
+"5. c #78A3D9",
+"6. c #79A3D9",
+"7. c #7AA3D8",
+"8. c #7CA3D8",
+"9. c #7DA3D8",
+"0. c #7CA3D9",
+"q. c #7EA3D8",
+"w. c #7EA3D9",
+"e. c #7EA4D8",
+"r. c #7EA4D9",
+"t. c #2CE1D3",
+"y. c #27F0D6",
+"u. c #2DFFD0",
+"i. c #2CFFD1",
+"p. c #08C2F6",
+"a. c #0EC8F0",
+"s. c #07C2F8",
+"d. c #0AD3F4",
+"f. c #0DDEF1",
+"g. c #0FE8EF",
+"h. c #87A2BE",
+"j. c #93B1CB",
+"k. c #80A6D7",
+"l. c #82A6D7",
+"z. c #81A6D8",
+"x. c #80A7D8",
+"c. c #81A7D8",
+"v. c #82A7D8",
+"b. c #83A9DA",
+"n. c #83A9DB",
+"m. c #84A9DA",
+"M. c #85A9DA",
+"N. c #84A9DB",
+"B. c #85A9DB",
+"V. c #86A9DA",
+"C. c #86A9DB",
+"Z. c #87A9DB",
+"A. c #85ABDA",
+"S. c #81A8DD",
+"D. c #83A9DC",
+"F. c #87ADDF",
+"G. c #81A9E0",
+"H. c #87ADE1",
+"J. c #87AEE1",
+"K. c #8AAEE0",
+"L. c #8AB0E3",
+"P. c #89B1E4",
+"I. c #A6CBE9",
+"U. c #A6CCEA",
+"Y. c #A7CCEA",
+"T. c #A7CDEB",
+"R. c #A8CDEA",
+"E. c #A8CDEB",
+"W. c #A9CDEB",
+"Q. c #A8CEEB",
+"!. c #AACEEA",
+"~. c #AACEEB",
+"^. c #BCE0FB",
+"/. c #BCE0FC",
+"(. c None",
+/* pixels */
+"(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.",
+"E = q 8 0 d #.s.[ ` *.d.i.+.(.(.",
+"J H r i c X.;.` ~ { a.#.z s <.(.",
+"C F g $.>.Q W ~ &.y.n l j k L (.",
+"- V h $.,.] ' -.g.%.| m o.t.; (.",
+"& - t u p a x M u.f.=.} ) ( & (.",
+"$ % 9 4 < 1 5 y N p.( B ! >.o (.",
+"@ O w 6 3 3 7 e f b ..O. .v . (.",
+"+ X w 6 3 3 h.T.R.R.T.R.E.R./.j.",
+"G ^.U.T.T.!.R.B.l.l.l.l.x.l.H.: ",
+"P D.3.3.3.3.3.l.l.x.x.x.l.b.H.> ",
+"I K.b.b.B.b.B.B.b.b.C.D.B.B.P.> ",
+"Z A A A A A A A Y A A A A A R # ",
+"U F.b.C.B.B.B.b.B.B.B.B.B.b.L.D ",
+"K D.r.r.w.5.w.r.3.r.6.6.r.w.D.S ",
+"(.(.(.(.(.(.(.    (.(.(.(.(.(.(."
+};
diff --git a/mgllab/xpm/document-new.xpm b/mgllab/xpm/document-new.xpm
new file mode 100644
index 0000000..bb8aa7e
--- /dev/null
+++ b/mgllab/xpm/document-new.xpm
@@ -0,0 +1,97 @@
+/* XPM */
+static const char *document_new_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 75 1 ",
+"  c #007500",
+". c #009300",
+"X c #009B00",
+"o c #099509",
+"O c #03A000",
+"+ c #00A800",
+"@ c #03AD00",
+"# c #02AD02",
+"$ c #0AAF0A",
+"% c #1AA300",
+"& c #00B300",
+"* c #1DB61D",
+"= c #34A000",
+"- c #32AF00",
+"; c #36B000",
+": c #33BC1D",
+"> c #21A621",
+", c #29A829",
+"< c #2AAA2A",
+"1 c #21B421",
+"2 c #3FB429",
+"3 c #36BF36",
+"4 c #64B000",
+"5 c #5ABC29",
+"6 c #23C423",
+"7 c #35C035",
+"8 c #5BC35B",
+"9 c #78D578",
+"0 c #7AD578",
+"q c #7E8181",
+"w c #7E8383",
+"e c #808585",
+"r c #848688",
+"t c #8FCF8F",
+"y c #95DD95",
+"u c #95DF95",
+"i c gray77",
+"p c #C6C6C6",
+"a c gray80",
+"s c #CECFCF",
+"d c gray88",
+"f c #E8E9E9",
+"g c #E8E9EA",
+"h c #E9E9EA",
+"j c #EAEAEA",
+"k c #EAEBEB",
+"l c #EBECEC",
+"z c #ECEDED",
+"x c gray93",
+"c c #EDEEEE",
+"v c #EEEFEF",
+"b c #EFEFF0",
+"n c #EFF0F0",
+"m c #F0F1F1",
+"M c #F1F1F1",
+"N c gray95",
+"B c #F2F3F3",
+"V c #F3F3F3",
+"C c #F3F4F4",
+"Z c #F4F4F4",
+"A c #F4F5F5",
+"S c gray96",
+"D c #F5F6F6",
+"F c #F6F6F6",
+"G c #F6F7F7",
+"H c gray97",
+"J c #F8F8F8",
+"K c #F9F9F9",
+"L c gray98",
+"P c #FBFBFB",
+"I c gray99",
+"U c #FDFDFD",
+"Y c #FEFEFE",
+"T c white",
+"R c None",
+/* pixels */
+"RRRRRRRRRR ,8,RR",
+"RjjjzccnNt39T97R",
+"Rffjccnnn>*2T5:X",
+"RzzzcnNCCoTTTTT.",
+"RcccNNZZG1O=T4-+",
+"RccNNCZGLy@%T;@R",
+"RNnBCZLLLLu6$&RR",
+"RNNZZLLLPLLLTRRR",
+"RZZZLLLLPTPTPRRR",
+"RZGZLLLTTPTTTRRR",
+"RZZLLLTLTPPLbRRR",
+"RGLLLLLTTdpsrRRR",
+"RZLLLTTTLiTeRRRR",
+"RGLLLLLTCaqRRRRR",
+"RZLLLTTTjqRRRRRR",
+"RRRRRRRRRRRRRRRR"
+};
diff --git a/mgllab/xpm/document-open-folder.xpm b/mgllab/xpm/document-open-folder.xpm
new file mode 100644
index 0000000..a4c7dd7
--- /dev/null
+++ b/mgllab/xpm/document-open-folder.xpm
@@ -0,0 +1,179 @@
+/* XPM */
+static const char *document_open_folder_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 157 2 ",
+"   c #00112F",
+".  c #001230",
+"X  c #142E4B",
+"o  c #0A2D56",
+"O  c #0C305A",
+"+  c #0C315A",
+"@  c #0D315B",
+"#  c #0E335D",
+"$  c #0F335D",
+"%  c #10335E",
+"&  c #123763",
+"*  c #1B3F6C",
+"=  c #203E61",
+"-  c #274466",
+";  c #25456A",
+":  c #26456A",
+">  c #2B4A71",
+",  c #2B4C73",
+"<  c #2F5179",
+"1  c #2F517A",
+"2  c #485D78",
+"3  c #495F7B",
+"4  c #4A5F7C",
+"5  c #2F598B",
+"6  c #335F92",
+"7  c #326092",
+"8  c #346092",
+"9  c #3D6392",
+"0  c #366498",
+"q  c #39679B",
+"w  c #3B689E",
+"e  c #3B699E",
+"r  c #3A689F",
+"t  c #3B689F",
+"y  c #3C699F",
+"u  c #3D6AA0",
+"i  c #3D6CA5",
+"p  c #3D6DA5",
+"a  c #3F6DA5",
+"s  c #3F6EA5",
+"d  c #3F74B0",
+"f  c #455F80",
+"g  c #506481",
+"h  c #4F779F",
+"j  c #4371A7",
+"k  c #4972A6",
+"l  c #4A75A7",
+"z  c #4976AD",
+"x  c #5079A9",
+"c  c #517AAA",
+"v  c #587FAD",
+"b  c #4074B0",
+"n  c #4776B2",
+"m  c #4076B4",
+"M  c #4B79B1",
+"N  c #4878B3",
+"B  c #4978B3",
+"V  c #4878B4",
+"C  c #4978B4",
+"Z  c #4A78B4",
+"A  c #4B78B4",
+"S  c #4A79B4",
+"D  c #437AB9",
+"F  c #4E7FBF",
+"G  c #507DB1",
+"H  c #517FB7",
+"J  c #527FB7",
+"K  c #547FB5",
+"L  c #527EB8",
+"P  c #4F81BF",
+"I  c #5180B7",
+"U  c #5180BA",
+"Y  c #5380BA",
+"T  c #5381BA",
+"R  c #5382BA",
+"E  c #5481BB",
+"W  c #5482BA",
+"Q  c #5684BB",
+"!  c #5081BF",
+"~  c #5182BF",
+"^  c #6788AA",
+"/  c #5181C0",
+"(  c #5082C0",
+")  c #5182C0",
+"_  c #5082C1",
+"`  c #5182C1",
+"'  c #5484C1",
+"]  c #5887C2",
+"[  c #5B88C0",
+"{  c #568CCD",
+"}  c #588CCF",
+"|  c #6390C5",
+" . c #6D99D0",
+".. c #76A1D4",
+"X. c #7CA3D6",
+"o. c #7DA3D6",
+"O. c #7EA3D6",
+"+. c #7FA6D7",
+"@. c #79A3D8",
+"#. c #78A3D9",
+"$. c #79A3D9",
+"%. c #7AA3D9",
+"&. c #7CA3D9",
+"*. c #7DA3D9",
+"=. c #7EA3D8",
+"-. c #7EA4D9",
+";. c #7CA7DB",
+":. c #7DA8DD",
+">. c #7CA8DF",
+",. c #93B1CB",
+"<. c #80A6D7",
+"1. c #81A6D7",
+"2. c #81A6D8",
+"3. c #80A7D8",
+"4. c #81A7D8",
+"5. c #82A7D8",
+"6. c #83A9DA",
+"7. c #83A9DB",
+"8. c #84A9DA",
+"9. c #85A9DA",
+"0. c #84A9DB",
+"q. c #85A9DB",
+"w. c #86A9DA",
+"e. c #86A9DB",
+"r. c #87A9DB",
+"t. c #85ABDA",
+"y. c #81A8DD",
+"u. c #80A9DD",
+"i. c #83A9DC",
+"p. c #82ABDE",
+"a. c #84ACDE",
+"s. c #86ADDF",
+"d. c #87ADDF",
+"f. c #86AFDF",
+"g. c #8AAFDF",
+"h. c #81A9E0",
+"j. c #87ADE1",
+"k. c #87AEE1",
+"l. c #86AFE1",
+"z. c #8AAEE0",
+"x. c #8AB0E3",
+"c. c #89B1E4",
+"v. c #8EB6EA",
+"b. c #8FB9EF",
+"n. c #90B8EB",
+"m. c #93BBEF",
+"M. c #AFD1ED",
+"N. c #B7D9F4",
+"B. c #B8DAF5",
+"V. c #B8DBF5",
+"C. c #B9DBF6",
+"Z. c #BADBF6",
+"A. c #B9DCF6",
+"S. c #BBDCF6",
+"D. c #BDE0FB",
+"F. c #BFE1FB",
+"G. c None",
+/* pixels */
+"G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.",
+"K I J J I Q G.G.G.G.G.G.G.G.G.G.",
+"k b.v.v.m.B I U E L U U E E [ G.",
+"9 l.{ } @.g.s.s.s.p.p.:.:.>.z G.",
+"1 ..! ' ( ! P ( ( ( ( ( P  .1 G.",
+"> | n n B B B A V V A V n [ , G.",
+": G p j p p u e u u e u e j : G.",
+"= 0 8 7 6 5 * % $ $ $ $ $ # & G.",
+"X # + + @ o ^ S.B.B.A.A.B.A.D.,.",
+"h D.N.N.A.N.M.0.2.2.1.1.1.1.j.2 ",
+"c 7.O.O.O.O.O.1.2.2.-.5.5.5.j.3 ",
+"c g.0.0.0.0.w.0.0.7.0.0.0.0.c.4 ",
+"q n d d b d b d b b d d d d D - ",
+"I r.t.0.0.0.0.0.0.0.0.0.0.0.x.4 ",
+"l p.o.-.=.#.=.-.2.=. at .@.-.-.j.f ",
+"G.G.G.G.. . .       . . G.G.G.G."
+};
diff --git a/mgllab/xpm/document-open.xpm b/mgllab/xpm/document-open.xpm
new file mode 100644
index 0000000..a2b1312
--- /dev/null
+++ b/mgllab/xpm/document-open.xpm
@@ -0,0 +1,168 @@
+/* XPM */
+static const char *document_open_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 146 2 ",
+"   c #001230",
+".  c #001431",
+"X  c #2A2A29",
+"o  c #001E45",
+"O  c #0E2A4A",
+"+  c #11345E",
+"@  c #18395B",
+"#  c #224164",
+"$  c #274466",
+"%  c #25466A",
+"&  c #21436D",
+"*  c #374F6D",
+"=  c #3B516A",
+"-  c #2B4B71",
+";  c #2A4B73",
+":  c #284C76",
+">  c #2F527A",
+",  c #30527B",
+"<  c #465D79",
+"1  c #485D78",
+"2  c #495F7B",
+"3  c #4A5F7C",
+"4  c #4E6177",
+"5  c #3E5E87",
+"6  c #3D6492",
+"7  c #39679B",
+"8  c #3F74B0",
+"9  c #455F80",
+"0  c #506481",
+"q  c #4A6A90",
+"w  c #4F769F",
+"e  c #51729B",
+"r  c #4A73A7",
+"t  c #4A75A6",
+"y  c #4976AD",
+"u  c #5079A9",
+"i  c #517AAA",
+"p  c #587FAD",
+"a  c #4074B0",
+"s  c #4076B4",
+"d  c #437AB9",
+"f  c #547FB5",
+"g  c #517EB8",
+"h  c #5481BB",
+"j  c #5483BC",
+"k  c #5887C2",
+"l  c #6894CD",
+"z  c #78A2D7",
+"x  c #7CA3D6",
+"c  c #7DA3D6",
+"v  c #7EA3D6",
+"b  c #7FA6D7",
+"n  c #78A3D9",
+"m  c #79A3D9",
+"M  c #7AA3D8",
+"N  c #7CA3D8",
+"B  c #7DA3D8",
+"V  c #7CA3D9",
+"C  c #7EA3D8",
+"Z  c #7EA3D9",
+"A  c #7EA4D8",
+"S  c #7EA4D9",
+"D  c #7CA9E1",
+"F  c #9A9A9A",
+"G  c #87A2BE",
+"H  c #A0A0A0",
+"J  c #A1A0A0",
+"K  c #ADACAC",
+"L  c #B2B0B0",
+"P  c #B4B3B3",
+"I  c gray72",
+"U  c #93B1CB",
+"Y  c #80A6D7",
+"T  c #82A6D7",
+"R  c #81A6D8",
+"E  c #80A7D8",
+"W  c #81A7D8",
+"Q  c #82A7D8",
+"!  c #83A9DA",
+"~  c #83A9DB",
+"^  c #84A9DA",
+"/  c #85A9DA",
+"(  c #84A9DB",
+")  c #85A9DB",
+"_  c #86A9DA",
+"`  c #86A9DB",
+"'  c #87A9DB",
+"]  c #85ABDA",
+"[  c #81A8DD",
+"{  c #83A9DC",
+"}  c #87ADDF",
+"|  c #B5BBC3",
+" . c #81A9E0",
+".. c #87ADE1",
+"X. c #87AEE1",
+"o. c #8AAEE0",
+"O. c #8AB0E3",
+"+. c #89B1E4",
+"@. c #A6CBE9",
+"#. c #A6CCEA",
+"$. c #A7CCEA",
+"%. c #A7CDEB",
+"&. c #A8CDEA",
+"*. c #A8CDEB",
+"=. c #A9CDEB",
+"-. c #A8CEEB",
+";. c #AACEEA",
+":. c #AACEEB",
+">. c #BCE0FB",
+",. c #BCE0FC",
+"<. c gray77",
+"1. c #C1C4CA",
+"2. c #C6C8CE",
+"3. c #C9CDD1",
+"4. c #CCCFD5",
+"5. c #CED1D5",
+"6. c #CED2D6",
+"7. c #CFD3D8",
+"8. c #D0D2D6",
+"9. c #E1DDDB",
+"0. c #E4E1DE",
+"q. c #DFE1E5",
+"w. c #E0E2E5",
+"e. c #E8E7E7",
+"r. c #E8E8EA",
+"t. c gray92",
+"y. c #EFEEEE",
+"u. c #F1EFEF",
+"i. c gray95",
+"p. c #F4F2F0",
+"a. c #F5F4F4",
+"s. c gray96",
+"d. c #F6F6F6",
+"f. c gray97",
+"g. c #F8F7F7",
+"h. c #F8F8F8",
+"j. c #F9F8F8",
+"k. c #F9F9F9",
+"l. c #FAF9F9",
+"z. c #FAF9FA",
+"x. c #FBFAFA",
+"c. c #FBFBFA",
+"v. c #FFFCFA",
+"b. c #FFFFFE",
+"n. c white",
+"m. c None",
+/* pixels */
+"m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.",
+"f : n.n.n.n.n.n.e.X m.m.m.m.m.m.",
+"r e n.d.h.h.a.t.<.n.= g j h k m.",
+"6 q n.h.h.h.d.y.H n.0.4 z D y m.",
+"> 5 n.g.h.h.h.i.F n.u.9.* l , m.",
+"- > n.h.h.h.h.d.H n.n.n.v.< - m.",
+"% & n.d.h.h.v.h.t.I P K L p.O m.",
+"# + n.h.n.h.q.7.6.4.3.2.1.w.. m.",
+"@ o e.5.8.| G &.&.&.&.&.-.&.,.U ",
+"w >.%. at .%.;.&.( T R b T R b o.1 ",
+"u { v v b v v T R ~ b T ~ R X.2 ",
+"u o.~ ~ ( ~ _ ( ( ~ ( ~ ( ( +.2 ",
+"7 s 8 8 8 8 a 8 a a 8 8 8 8 d $ ",
+"p } ( ( ( ( ( ( ( ( ( ( ( ( O.3 ",
+"t { v A Z n Z A T v m m A Z ..9 ",
+"m.m.m.m.m.m.m.    m.m.m.m.m.m.m."
+};
diff --git a/mgllab/xpm/document-print.xpm b/mgllab/xpm/document-print.xpm
new file mode 100644
index 0000000..16fcf4f
--- /dev/null
+++ b/mgllab/xpm/document-print.xpm
@@ -0,0 +1,95 @@
+/* XPM */
+static const char *document_print_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 73 1 ",
+"  c #070707",
+". c #090909",
+"X c #4E4E4E",
+"o c gray34",
+"O c gray35",
+"+ c #5A5A5A",
+"@ c #5B5B5B",
+"# c #606060",
+"$ c #626262",
+"% c #646464",
+"& c #66666A",
+"* c #6E6E71",
+"= c #747474",
+"- c #777777",
+"; c #797979",
+": c gray48",
+"> c gray53",
+", c #888888",
+"< c gray57",
+"1 c #939393",
+"2 c #959595",
+"3 c gray60",
+"4 c gray61",
+"5 c #9E9EA1",
+"6 c #A4A4A4",
+"7 c #A9A9A9",
+"8 c #A9A9AB",
+"9 c #AAAAAA",
+"0 c gray67",
+"q c #ACACAC",
+"w c #AEAEAE",
+"e c #AFAFAF",
+"r c #ADADB3",
+"t c #B2B2B1",
+"y c #B4B4B4",
+"u c #B7B7B7",
+"i c #B6B6BC",
+"p c gray",
+"a c gray75",
+"s c #BCBCC1",
+"d c #BDBDC2",
+"f c #BEBEC3",
+"g c #C0C0C0",
+"h c #C1C1C1",
+"j c #C5C5C5",
+"k c #CACACA",
+"l c #CBCBCF",
+"z c gray80",
+"x c #D3D3D7",
+"c c #D6D6D9",
+"v c #D8D8DB",
+"b c #DCDCDF",
+"n c #DEDEE0",
+"m c #DEDEE1",
+"M c #E2E2E2",
+"N c #E1E1E4",
+"B c #E2E2E4",
+"V c gray90",
+"C c #E5E5E8",
+"Z c #E7E7E9",
+"A c #E9E9EB",
+"S c #EBEBEC",
+"D c #EBEBED",
+"F c #EFEFEF",
+"G c #F1F1F2",
+"H c #F3F3F4",
+"J c #F5F5F6",
+"K c #F8F8F8",
+"L c #FBFBFB",
+"P c #FCFCFD",
+"I c #FDFDFD",
+"U c white",
+"Y c None",
+/* pixels */
+"YYYYYYYYYYYYYYYY",
+"YYYY770000q7YYYY",
+"YYYYUUUUUUUUYYYY",
+"YYYYJUUUUUUUYYYY",
+"YYY,ZHLUUULJ,YYY",
+"Y,<<xNDGGGDN<6<Y",
+",<6>dlcnnncl,y6<",
+"yFF=@@OooO@@;FGy",
+"yJL=XX$$$#XX;LJu",
+"7kkqee3224qt0kk7",
+"eVMjggppppggjMgq",
+"6l3. .      .3y6",
+",,%@&riddsi*O%,,",
+"YYY;5vNZDAN7;YYY",
+"YYY;nJUUUUUD;YYY",
+"YYYYYYYYYYYYYYYY"
+};
diff --git a/mgllab/xpm/document-properties.xpm b/mgllab/xpm/document-properties.xpm
new file mode 100644
index 0000000..d9d27f3
--- /dev/null
+++ b/mgllab/xpm/document-properties.xpm
@@ -0,0 +1,63 @@
+/* XPM */
+static const char *document_properties_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 41 1 ",
+"  c #585858",
+". c gray35",
+"X c #626262",
+"o c #696966",
+"O c DimGray",
+"+ c #6A6A6A",
+"@ c #6C6C6C",
+"# c #777777",
+"$ c #818181",
+"% c gray52",
+"& c #909090",
+"* c #929292",
+"= c #959595",
+"- c gray60",
+"; c #9D9D9D",
+": c gray62",
+"> c gray67",
+", c gray68",
+"< c gray69",
+"1 c gray71",
+"2 c gray73",
+"3 c gray77",
+"4 c #C5C5C5",
+"5 c #C6C6C6",
+"6 c gray78",
+"7 c #C8C8C8",
+"8 c #D2D2CC",
+"9 c #D2D2D2",
+"0 c gray83",
+"q c gray84",
+"w c gainsboro",
+"e c gray88",
+"r c #EAEAEA",
+"t c gray92",
+"y c #ECECEC",
+"u c gray93",
+"i c #EEEEEE",
+"p c #EFEFEF",
+"a c gray94",
+"s c white",
+"d c None",
+/* pixels */
+"d-$$$$$$$$$$$$dd",
+"d$ssssssssssss$d",
+"d$syrrrrrryyas$d",
+"d$sr55555555as$d",
+"d$srryOOO9yaas$d",
+"d$sr55<   57as$d",
+"d$syO9y9Ooyyas$d",
+"d$sr  < @O8yas$d",
+"d$syOOO at OOOqas$d",
+"d$sy<     X at ws$d",
+"d$syyyyaq#%*:s$d",
+"d$sy777771*:>s$d",
+"d$syyyayaae,2s$d",
+"d$ssssssssssss$d",
+"d=$$$$$$$$$$$$=d",
+"dddddddddddddddd"
+};
diff --git a/mgllab/xpm/document-revert.xpm b/mgllab/xpm/document-revert.xpm
new file mode 100644
index 0000000..6b750b2
--- /dev/null
+++ b/mgllab/xpm/document-revert.xpm
@@ -0,0 +1,164 @@
+/* XPM */
+static const char *document_revert_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 142 2 ",
+"   c #7D5718",
+".  c #7A561E",
+"X  c #7C581C",
+"o  c #8D6416",
+"O  c #8D6719",
+"+  c #8E661E",
+"@  c #906A1A",
+"#  c #947217",
+"$  c #94711F",
+"%  c #95731E",
+"&  c #A36C0E",
+"*  c #B4740A",
+"=  c #B67E0E",
+"-  c #836126",
+";  c #926C25",
+":  c #936E26",
+">  c #906A2F",
+",  c #976F2F",
+"<  c #957027",
+"1  c #97732B",
+"2  c #876833",
+"3  c #8E6C31",
+"4  c #886835",
+"5  c #8B6C39",
+"6  c #8C6F3D",
+"7  c #8E6E3E",
+"8  c #95793F",
+"9  c #AA8413",
+"0  c #B18F3B",
+"q  c #BC953B",
+"w  c #CE850A",
+"e  c #D98E0B",
+"r  c #D69D10",
+"t  c #D6AD0E",
+"y  c #E1A02D",
+"u  c #E7B236",
+"i  c #E4BD3B",
+"p  c #DFC81E",
+"a  c #E2C139",
+"s  c #9F865C",
+"d  c #AA8345",
+"f  c #B99741",
+"g  c #BC9940",
+"h  c #8B8477",
+"j  c #848279",
+"k  c #86847B",
+"l  c #8B877B",
+"z  c #A6906B",
+"x  c #AD9978",
+"c  c #CCA055",
+"v  c #DABC59",
+"b  c #EBBF46",
+"n  c #E8B64A",
+"m  c #E9B948",
+"M  c #E9B849",
+"N  c #E9B850",
+"B  c #E9BE55",
+"V  c #DDC058",
+"C  c #E5CD41",
+"Z  c #E5C249",
+"A  c #ECC151",
+"S  c #ECC156",
+"D  c #E7CD52",
+"F  c #E1C759",
+"G  c #E4C45A",
+"H  c #E1C85C",
+"J  c #EACC5C",
+"K  c #F0CD5F",
+"L  c #EBD05D",
+"P  c #EFD263",
+"I  c #EED463",
+"U  c #EED563",
+"Y  c #F1D363",
+"T  c #F2D462",
+"R  c #F4DA65",
+"E  c #F3DC67",
+"W  c #F0D769",
+"Q  c #F3DA68",
+"!  c #F1DF69",
+"~  c #F7E667",
+"^  c #F2E068",
+"/  c #F7E669",
+"(  c #F7E66A",
+")  c #FAEF74",
+"_  c #B8A68A",
+"`  c #B9A78A",
+"'  c #BDAA8D",
+"]  c #C5B290",
+"[  c #C2B195",
+"{  c #C2B298",
+"}  c #C6B69E",
+"|  c #D3C2A6",
+" . c #CEC5B7",
+".. c #CEC7BC",
+"X. c #D2C7B5",
+"o. c #D2C8B5",
+"O. c #E8D9B9",
+"+. c #DBD2C5",
+"@. c #E1DBD1",
+"#. c #EEE8DE",
+"$. c #E8E9E9",
+"%. c #E8E9EA",
+"&. c #EAEAEA",
+"*. c #EAEBEB",
+"=. c #EBECEC",
+"-. c #ECEDED",
+";. c #EDEEEE",
+":. c #EEEFEF",
+">. c #F1EFEB",
+",. c #F2EFEB",
+"<. c #F3F0EC",
+"1. c #F1F0EE",
+"2. c #EFF0F0",
+"3. c #F0F1F1",
+"4. c #F1F1F1",
+"5. c #F1F2F2",
+"6. c gray95",
+"7. c #F3F3F3",
+"8. c #F4F3F1",
+"9. c #F6F5F2",
+"0. c #F3F4F4",
+"q. c #F4F4F4",
+"w. c #F4F5F5",
+"e. c gray96",
+"r. c #F6F6F4",
+"t. c #F6F6F5",
+"y. c #F7F6F5",
+"u. c #F6F6F6",
+"i. c #F6F7F7",
+"p. c gray97",
+"a. c #F8F7F3",
+"s. c #F8F7F4",
+"d. c #F8F9F9",
+"f. c #F9F9F9",
+"g. c #FAFAF9",
+"h. c #FBFAF9",
+"j. c gray98",
+"k. c #FBFBFB",
+"l. c gray99",
+"z. c #FDFDFD",
+"x. c #FEFEFE",
+"c. c None",
+/* pixels */
+"c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.",
+"c.c.c.&.$.&.;.;.;.2.2.4.4.0.0.c.",
+"c.c.c.&.$.&.-.;.2.2.4.4.4.q.q.c.",
+"c.c.c.*.-.-.2.2.4.4.0.q.q.q.q.c.",
+"c.c.c.:. .z 2 . 5 ` @.i.d.i.d.c.",
+"4 c.c.6 0 H ^ ) ^ F f s s.k.k.c.",
+"1 q - v ( ~ ~ ~ ( ~ ( V 3 >.k.c.",
+"1 Q W Q E Y A u Z Y R R G 7 k.c.",
+"< U U Q i r = & * e m K K q { c.",
+"; J L a t O ` +.x > w m S B X c.",
+"+ Z D a p 9 X.h.h.<.d y N n , c.",
+"  o @ < % # 8 ,.z.x.' c ] o.h c.",
+"c.c.c.1.8.d.h.l.x.x.} [ x.l c.c.",
+"c.c.c.q.a.d.l.l.l.a.| ..k c.c.c.",
+"c.c.c.s.a.h.d.x.d.#.O.k c.c.c.c.",
+"c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c."
+};
diff --git a/mgllab/xpm/document-save.xpm b/mgllab/xpm/document-save.xpm
new file mode 100644
index 0000000..759d54e
--- /dev/null
+++ b/mgllab/xpm/document-save.xpm
@@ -0,0 +1,129 @@
+/* XPM */
+static const char *document_save_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 107 2 ",
+"   c #4E6A7D",
+".  c #58787A",
+"X  c #6E706B",
+"o  c #6B716E",
+"O  c #72756B",
+"+  c #667173",
+"@  c #627075",
+"#  c #38678B",
+"$  c #3D698A",
+"%  c #3B6B8F",
+"&  c #3D6B8E",
+"*  c #3F6C8E",
+"=  c #4A6D85",
+"-  c #436E88",
+";  c #4A7180",
+":  c #41749A",
+">  c #44789F",
+",  c #547D9B",
+"<  c #6B7F88",
+"1  c #5186AF",
+"2  c #5892BD",
+"3  c #688BA0",
+"4  c #6E99B6",
+"5  c #7798B0",
+"6  c #719FBF",
+"7  c #739FC0",
+"8  c #79A7CA",
+"9  c #9F9F9F",
+"0  c #92A6AC",
+"q  c #95A9AF",
+"w  c #9AAEB4",
+"e  c #A8A7A7",
+"r  c #A8A7A8",
+"t  c #A9A9A9",
+"y  c #AAAAA9",
+"u  c #AFAFAF",
+"i  c #B4B4B4",
+"p  c #B7B6B6",
+"a  c #B9B9B9",
+"s  c #BCBCBC",
+"d  c #C5CBBF",
+"f  c #8FB3CE",
+"g  c #92B7D3",
+"h  c #96BBD8",
+"j  c #9EBFD9",
+"k  c #98BFDC",
+"l  c #ACBCC3",
+"z  c #9BC2DF",
+"x  c #ABC8DF",
+"c  c #ABCBE2",
+"v  c #ACCBE3",
+"b  c #B1CEE6",
+"n  c gray76",
+"m  c #C3C3C3",
+"M  c gray77",
+"N  c #C5C5C5",
+"B  c #CACFC4",
+"V  c #C8C8C8",
+"C  c gray79",
+"Z  c #CACACA",
+"A  c #CBCBCB",
+"S  c #CDCDCD",
+"D  c #CECECE",
+"F  c gray81",
+"G  c #CED4C8",
+"H  c #C9D6DD",
+"J  c #D0D0D0",
+"K  c gray82",
+"L  c #D2D2D2",
+"P  c #D5D5D5",
+"I  c gray84",
+"U  c gainsboro",
+"Y  c #DDDDDD",
+"T  c #DDE1D6",
+"R  c #DFE2DE",
+"E  c #E2E6DD",
+"W  c #C1D9EB",
+"Q  c #C5DBEC",
+"!  c #D5DFE5",
+"~  c #D0DFEF",
+"^  c gray89",
+"/  c #E4E4E4",
+"(  c #E9E9EA",
+")  c #EAE9EA",
+"_  c gray92",
+"`  c #EBECEC",
+"'  c #ECECEC",
+"]  c gray93",
+"[  c #EDEEED",
+"{  c #EDEDEE",
+"}  c #EDEEEE",
+"|  c #EEEEEE",
+" . c gray94",
+".. c #F1F1F1",
+"X. c gray95",
+"o. c #F3F3F3",
+"O. c #F3F4F3",
+"+. c #F4F4F4",
+"@. c gray97",
+"#. c #F9F9F9",
+"$. c gray98",
+"%. c #FCFBFC",
+"&. c gray99",
+"*. c #FDFDFD",
+"=. c #FEFEFE",
+"-. c white",
+";. c None",
+/* pixels */
+";.;.;.# # # $   . ;.;.;.;.;.;.;.",
+";.;.;.b ~ Q z 3 - ;.;.;.;.;.;.;.",
+"< + @ = : > j W 1   X X X X X X ",
+"o E -.T H 4 # v g 1 U &.-.-.+.X ",
+"O -.| | R 5 # 8 f & l | | | O.X ",
+"X $.` # # # # 8 2 # # # # ` o.X ",
+"X $.( B # k 6 6 6 6 h # q ( o.X ",
+"X $.$.^ d # k 6 6 x # 0 ^ o.o.X ",
+"X $.| $./ d # v k & 0 ^ $.| o.X ",
+"X +.^ | $.$.G & # w $.-.| ^ | X ",
+"X -.-.-.-.-.-.-.-.+.+.( ( ^  .X ",
+"X D C C C C N C C N N N N N I X ",
+"X D N 9 u a N V D t L t L a C X ",
+"X D m t i n M V A e L e L p C X ",
+"X U U U U I I J J D D J J J A X ",
+"X X X X X X X X X X X X X X X X "
+};
diff --git a/mgllab/xpm/down_1.xpm b/mgllab/xpm/down_1.xpm
new file mode 100644
index 0000000..e8d3b52
--- /dev/null
+++ b/mgllab/xpm/down_1.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * down_1_xpm[] = {
+"16 16 3 1",
+".	c None",
+"+	c #7F0000",
+"@	c #FF0000",
+"................",
+"................",
+".....+++++++....",
+".....+@@@@@+....",
+".....+@@@@@+....",
+".....+@@@@@+....",
+".....+@@@@@+....",
+".....+@@@@@+....",
+"..++++@@@@@++++.",
+"...+@@@@@@@@@+..",
+"....+@@@@@@@+...",
+".....+@@@@@+....",
+"......+@@@+.....",
+".......+ at +......",
+"........+.......",
+"................"};
diff --git a/mgllab/xpm/edit-clear.xpm b/mgllab/xpm/edit-clear.xpm
new file mode 100644
index 0000000..1640baf
--- /dev/null
+++ b/mgllab/xpm/edit-clear.xpm
@@ -0,0 +1,130 @@
+/* XPM */
+static const char *edit_clear_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 108 2 ",
+"   c #6C3124",
+".  c #991711",
+"X  c #BD1212",
+"o  c #BD1817",
+"O  c #8A231E",
+"+  c #A62013",
+"@  c #AB211A",
+"#  c #A32C1E",
+"$  c #B62C1F",
+"%  c #842D24",
+"&  c #9F2926",
+"*  c #B22824",
+"=  c #B92B27",
+"-  c #A33331",
+";  c #AB3731",
+":  c #CB0907",
+">  c #C0160F",
+",  c #CE100A",
+"<  c #CC140D",
+"1  c #E70A09",
+"2  c #E01713",
+"3  c #D02F23",
+"4  c #D92E20",
+"5  c #D82A27",
+"6  c #894131",
+"7  c #8F4232",
+"8  c #955036",
+"9  c #C7403B",
+"0  c #CE4C3A",
+"q  c #8F7048",
+"w  c #8D714E",
+"e  c #97774F",
+"r  c #9A6C56",
+"t  c #8D7556",
+"y  c #917555",
+"u  c #9A7A52",
+"i  c #9B7C53",
+"p  c #9F7D51",
+"a  c #9D7B54",
+"s  c #9B7F5A",
+"d  c #AF6047",
+"f  c #A17D51",
+"g  c #B4795E",
+"h  c #977F63",
+"j  c #CB4341",
+"k  c #C64B46",
+"l  c #CE4F4C",
+"z  c #CE5955",
+"x  c #DD6766",
+"c  c #D86864",
+"v  c #DE6B68",
+"b  c #DF6E69",
+"n  c #9F845F",
+"m  c #A48157",
+"M  c #A78456",
+"N  c #A88357",
+"B  c #AA8757",
+"V  c #A08158",
+"C  c #A3815A",
+"Z  c #A5835B",
+"A  c #A1845C",
+"S  c #A7865D",
+"D  c #A88459",
+"F  c #AA8758",
+"G  c #AA885B",
+"H  c #AA885E",
+"J  c #B0885C",
+"K  c #B3885C",
+"L  c #B08A5D",
+"P  c #B5895C",
+"I  c #B28E5C",
+"U  c #B28E5E",
+"Y  c #B48F5D",
+"T  c #B88E5A",
+"R  c #B88C5D",
+"E  c #B5905D",
+"W  c #B8915E",
+"Q  c #BA915E",
+"!  c #BB905F",
+"~  c #BA945F",
+"^  c #9F8567",
+"/  c #AC8A62",
+"(  c #A38D6E",
+")  c #A58E6E",
+"_  c #B68266",
+"`  c #B28F60",
+"'  c #BC8F62",
+"]  c #AF9169",
+"[  c #AD916B",
+"{  c #AC906E",
+"}  c #AD936E",
+"|  c #B39165",
+" . c #BE9161",
+".. c #BB9463",
+"X. c #BD9664",
+"o. c #B3946D",
+"O. c #B39B77",
+"+. c #B79B74",
+"@. c #B89D77",
+"#. c #B69C79",
+"$. c #B39E7D",
+"%. c #B99F7B",
+"&. c #B9A07C",
+"*. c #C59961",
+"=. c #C0A57F",
+"-. c #AB9B82",
+";. c #C8AF8C",
+":. c None",
+/* pixels */
+":.:.:.:.:.:.:.:.:.:.#.:.:.:.:.:.",
+":.:.:.:.:.:.:.:.:.$.;.:.:.:.:.:.",
+":.:.:.:.:.:.:.:.:.&.:.:.:.:.:.:.",
+":.:.:.:.:.:.:.:.-.%.:.:.:.:.:.:.",
+":.:.:.:.:.:.:.:.} h :.:.:.:.:.:.",
+":.:.:.:.:.:.} @.^ r :.:.:.:.:.:.",
+":.:.:.:.:.n =.O./ _ = :.:.9 b :.",
+":.:.:.:.:.[ +.o.H g c O ; x v * ",
+":.:.:.:.w ) ) Z S d j k l z @ :.",
+":.:.:.u A [ s y t 7 $ X o + :.:.",
+":.:.:.p | A u M s # , > : < . :.",
+":.:.Y a N J p I m 4 3   % 1 2 - ",
+":.B q ..P m ! E P 0 6 :.:.& 5 :.",
+":.F '  .! E *.Q X.8 :.:.:.:.:.:.",
+":.:.G J Y ~ T R ` :.:.:.:.:.:.:.",
+":.:.:.:.:.:.f :.:.:.:.:.:.:.:.:."
+};
diff --git a/mgllab/xpm/edit-copy.xpm b/mgllab/xpm/edit-copy.xpm
new file mode 100644
index 0000000..34f56e7
--- /dev/null
+++ b/mgllab/xpm/edit-copy.xpm
@@ -0,0 +1,74 @@
+/* XPM */
+static const char *edit_copy_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 52 1 ",
+"  c black",
+". c #6C6D6C",
+"X c #6F6F6F",
+"o c #737372",
+"O c #797A79",
+"+ c gray69",
+"@ c #B0B1B1",
+"# c #B1B1B1",
+"$ c #B1B2B2",
+"% c gray70",
+"& c #B4B4B4",
+"* c gray71",
+"= c #B7B7B7",
+"- c gray72",
+"; c #E2E2E2",
+": c #E4E4E4",
+"> c #E7E8E7",
+", c #E6EAEB",
+"< c #EAEAE9",
+"1 c #EAEBEA",
+"2 c #EAEBEB",
+"3 c #EBECEC",
+"4 c #ECEDED",
+"5 c #EDEEEE",
+"6 c #EEEEEE",
+"7 c #EFF0F0",
+"8 c gray94",
+"9 c #F0F1F1",
+"0 c #F1F2F2",
+"q c gray95",
+"w c #F2F3F3",
+"e c #F3F3F3",
+"r c #F4F4F3",
+"t c #F1F3F4",
+"y c #F3F4F4",
+"u c #F4F4F4",
+"i c #F4F5F5",
+"p c gray96",
+"a c #F5F6F6",
+"s c #F6F6F6",
+"d c gray97",
+"f c #F7F8F8",
+"g c #F8F8F8",
+"h c #F9F9F9",
+"j c gray98",
+"k c #FBFBFB",
+"l c #FAFCFD",
+"z c gray99",
+"x c #FDFDFD",
+"c c #FEFEFE",
+"v c white",
+"b c None",
+/* pixels */
+"bbbbbbbbbbbbbbbb",
+"bvvvvvvvvvvbbbbb",
+"bv244q7qqqvbbbbb",
+"bv47;++###- bbbb",
+"bv4p#vvvvvvvvvvb",
+"bvqp#v447qyyppvb",
+"bvpk%v4qqppkkpvb",
+"bvpk&vqqpkpkkkvb",
+"bvpk&vqppkkkzkvb",
+"bvkk&vqpklzzvzvb",
+"bvkv&vykkkp:2qtb",
+"bkvv&vpkkv:vvrXb",
+"bbbb vkkkv>vqXbb",
+"bbbbbvpvkv2qobbb",
+"bbbbbkvvvl,Obbbb",
+"bbbbbbbbbbbbbbbb"
+};
diff --git a/mgllab/xpm/edit-cut.xpm b/mgllab/xpm/edit-cut.xpm
new file mode 100644
index 0000000..5fb9079
--- /dev/null
+++ b/mgllab/xpm/edit-cut.xpm
@@ -0,0 +1,40 @@
+/* XPM */
+static const char *edit_cut_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 18 1 ",
+"  c black",
+". c #626262",
+"X c #6A6A6A",
+"o c gray42",
+"O c #8B8B8B",
+"+ c #D2D2D2",
+"@ c LightGray",
+"# c #D7D7D7",
+"$ c gray85",
+"% c gray86",
+"& c #EEEEEE",
+"* c gray94",
+"= c gray96",
+"- c #F8F8F8",
+"; c #F9F9F9",
+": c #FBFBFB",
+"> c #FEFEFE",
+", c None",
+/* pixels */
+",,,,,,,,,,,,,,,,",
+",,,,,o,,,,o,,,,,",
+",,,,,%,,,,%,,,,,",
+",,,,,>o,,o>,,,,,",
+",,,,,#%,,%$,,,,,",
+",,,,,.-oo-.,,,,,",
+",,,,,,@$$#,,,,,,",
+",,,,,,.--.,,,,,,",
+",,,,,,,&*,,,,,,,",
+",,,,,,o==o,,,,,,",
+",,,,,,@@@@,,,,,,",
+",,,,  O..O  ,,,,",
+",,     ,,     ,,",
+",  ,  ,,,,  ,  ,",
+", ,, ,,,,,, ,, ,",
+",   ,,,,,,,,   ,"
+};
diff --git a/mgllab/xpm/edit-delete.xpm b/mgllab/xpm/edit-delete.xpm
new file mode 100644
index 0000000..6af3872
--- /dev/null
+++ b/mgllab/xpm/edit-delete.xpm
@@ -0,0 +1,158 @@
+/* XPM */
+static const char *edit_delete_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 136 2 ",
+"   c #242727",
+".  c #272C2E",
+"X  c #282D2F",
+"o  c #292E30",
+"O  c #2B3132",
+"+  c #2B3133",
+"@  c #2E3434",
+"#  c #2E3436",
+"$  c #313432",
+"%  c #333734",
+"&  c #323838",
+"*  c #353939",
+"=  c #373A38",
+"-  c #393E3B",
+";  c #393D3C",
+":  c #3C4041",
+">  c #424745",
+",  c #434844",
+"<  c #454B47",
+"1  c #424749",
+"2  c #4C5052",
+"3  c #515756",
+"4  c #53585A",
+"5  c #555B59",
+"6  c #54595A",
+"7  c #575C5E",
+"8  c #585E5B",
+"9  c #5A5F60",
+"0  c #5C6362",
+"q  c #5F6764",
+"w  c #616866",
+"e  c #64696A",
+"r  c #686D6E",
+"t  c #6A716D",
+"y  c #69706E",
+"u  c #6B7171",
+"i  c #6E7672",
+"p  c #6E7774",
+"a  c #6F7875",
+"s  c #727373",
+"d  c #7A837E",
+"f  c #7E8785",
+"g  c gray53",
+"h  c #818A88",
+"j  c #878B88",
+"k  c #86898A",
+"l  c #838C89",
+"z  c #848C89",
+"x  c #858D8A",
+"c  c #898D8D",
+"v  c #8B8F8D",
+"b  c #8B8F8F",
+"n  c #8D948F",
+"m  c #899290",
+"M  c #939594",
+"N  c #929595",
+"B  c #909894",
+"V  c #919894",
+"C  c #979A9B",
+"Z  c #969C99",
+"A  c #979F9B",
+"S  c #979E9C",
+"D  c #989B99",
+"F  c #9B9C9B",
+"G  c #9B9D9B",
+"H  c #9A9C9C",
+"J  c #A0A3A1",
+"K  c #A1A4A4",
+"L  c #A0A7A4",
+"P  c #A2A8A0",
+"I  c #A2A8A3",
+"U  c #AAAFA7",
+"Y  c #ABB0A8",
+"T  c #AEB3AD",
+"R  c #ADAFB0",
+"E  c #AFB1B0",
+"W  c #AFB5B3",
+"Q  c #B0B6B4",
+"!  c #B3B8B0",
+"~  c #B3B8B3",
+"^  c #B6BBB3",
+"/  c #B5BAB5",
+"(  c #BABFB7",
+")  c #B7BBBB",
+"_  c #B9BBBB",
+"`  c #BCC0BF",
+"'  c #BFC0BF",
+"]  c #BEC1BF",
+"[  c #BFC1C1",
+"{  c #C2C5C4",
+"}  c #C7CAC4",
+"|  c #CBCEC7",
+" . c #CBCECB",
+".. c #CBCFCB",
+"X. c #CBCECD",
+"o. c #CCCFCF",
+"O. c #CCD0CF",
+"+. c #D2D5CD",
+"@. c #CFD2D0",
+"#. c #D1D4D2",
+"$. c #D2D5D3",
+"%. c #D2D6D2",
+"&. c #D4D7D5",
+"*. c #D6D9D2",
+"=. c #D6D9D3",
+"-. c #D5D8D6",
+";. c #D5D8D7",
+":. c #D6D9D7",
+">. c #D9DBD2",
+",. c #D9DBD4",
+"<. c #D9DBD6",
+"1. c #D8DBD7",
+"2. c #DADCD6",
+"3. c #D8DBD8",
+"4. c #DDDED9",
+"5. c #DDDFDC",
+"6. c #DFE0D8",
+"7. c #E6E6DD",
+"8. c #E0E2E2",
+"9. c #E3E5E0",
+"0. c #E5E5E1",
+"q. c #E5E6E0",
+"w. c #E3E5E4",
+"e. c #E3E5E5",
+"r. c #E4E5E5",
+"t. c #E9EAE3",
+"y. c #ECEDE9",
+"u. c #EEEFEC",
+"i. c #EFF0EE",
+"p. c #F0F0EB",
+"a. c #F0F0ED",
+"s. c #F4F4EF",
+"d. c #F4F3F1",
+"f. c #F3F4F0",
+"g. c #F4F4F1",
+"h. c None",
+/* pixels */
+"h.h.h.h.h.# # # # # + h.h.h.h.h.",
+"h.h.h.# e B t.u.i.$.{ D # h.h.h.",
+"h.h.1 <.} i >   $ d ~ ....# h.h.",
+"h.# =.+.2.T 0 * * 8 n U $./ # h.",
+"h.# 0.a.y.9.4.| ~ P ! ` Y  .+ h.",
+"h.# 8.7.s.d.f.s.p.7.*.B n c # h.",
+"h.# H { ` >.6.<.O.z C k 6 # # h.",
+"h.h.# 9 b R r.e.0.K r : 2 # h.h.",
+"h.h.# u % @ + + o . . - N # h.h.",
+"h.h.# W W y A y - q % w D # h.h.",
+"h.h.# ) 3.f $.f 3 m , a K # h.h.",
+"h.h.# ) 3.x 3.I 5 A < a J # h.h.",
+"h.h.# ) :.l <.I 5 H < p D # h.h.",
+"h.h.# E O._ 4.I 5 L j N s # h.h.",
+"h.h.h.# 7 G :.O.[ ` g 5 # h.h.h.",
+"h.h.h.h.h.# # # # # # h.h.h.h.h."
+};
diff --git a/mgllab/xpm/edit-find.xpm b/mgllab/xpm/edit-find.xpm
new file mode 100644
index 0000000..02cbeb6
--- /dev/null
+++ b/mgllab/xpm/edit-find.xpm
@@ -0,0 +1,86 @@
+/* XPM */
+static const char *edit_find_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 64 1 ",
+"  c black",
+". c #010101",
+"X c #040404",
+"o c gray4",
+"O c #0B0B0B",
+"+ c #0E0E0E",
+"@ c #101010",
+"# c #111111",
+"$ c gray7",
+"% c #131313",
+"& c #151515",
+"* c #161616",
+"= c gray9",
+"- c #181818",
+"; c #1B1B1B",
+": c gray11",
+"> c gray12",
+", c #36281E",
+"< c #36281F",
+"1 c #38281F",
+"2 c #232323",
+"3 c #262523",
+"4 c gray14",
+"5 c #272727",
+"6 c #282828",
+"7 c gray17",
+"8 c #2C2C2C",
+"9 c #2D2D2D",
+"0 c #362A24",
+"q c #392C25",
+"w c #3C3028",
+"e c #323232",
+"r c #343231",
+"t c gray21",
+"y c #482100",
+"u c #4E2909",
+"i c #53331C",
+"p c #59483D",
+"a c #454240",
+"s c gray29",
+"d c gray30",
+"f c #4E4E4E",
+"g c #555352",
+"h c #565656",
+"j c #695746",
+"k c #68584D",
+"l c #766252",
+"z c #686868",
+"x c DimGray",
+"c c #6A6A6A",
+"v c #72706F",
+"b c gray45",
+"n c gray47",
+"m c #844007",
+"M c #86430B",
+"N c #90490B",
+"B c #845734",
+"V c #875B3B",
+"C c #90613D",
+"Z c #91623F",
+"A c #957254",
+"S c #817E7D",
+"D c #AB917A",
+"F c None",
+/* pixels */
+"FFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFF",
+"FFFFF  FF  FFFFF",
+"FFFF2z4FF4z2FFFF",
+"FFF 88&&&&68 FFF",
+"FF;b8s&zh&d8b;FF",
+"F tdzed# dezdt F",
+"F&zSn46;;62nSz&F",
+" hqupv:64:vp10g ",
+"OwiCVk;  &kBZiqX",
+" ,yiNl+FF#lNmu, ",
+" 3jADp FF aDAj3 ",
+"F #rO FFFF Or# F",
+"FFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFF"
+};
diff --git a/mgllab/xpm/edit-paste.xpm b/mgllab/xpm/edit-paste.xpm
new file mode 100644
index 0000000..73f99b0
--- /dev/null
+++ b/mgllab/xpm/edit-paste.xpm
@@ -0,0 +1,120 @@
+/* XPM */
+static const char *edit_paste_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 98 2 ",
+"   c #070707",
+".  c #0C0C0C",
+"X  c #111111",
+"o  c gray8",
+"O  c #161616",
+"+  c gray9",
+"@  c #181818",
+"#  c gray10",
+"$  c #1B1B1B",
+"%  c gray11",
+"&  c #1E1E1E",
+"*  c gray12",
+"=  c gray13",
+"-  c #222222",
+";  c #232323",
+":  c gray14",
+">  c #252525",
+",  c gray15",
+"<  c #272727",
+"1  c #282828",
+"2  c gray18",
+"3  c gray19",
+"4  c #313131",
+"5  c #323232",
+"6  c #353535",
+"7  c #393939",
+"8  c #3A3A3A",
+"9  c gray23",
+"0  c #3E3E3E",
+"q  c gray27",
+"w  c #494949",
+"e  c gray29",
+"r  c #4B4B4B",
+"t  c #4C4D4C",
+"y  c #666766",
+"u  c #686D6D",
+"i  c #848484",
+"p  c gray52",
+"a  c #AEAEAE",
+"s  c #AFAFAF",
+"d  c gray69",
+"f  c #B1B1B1",
+"g  c gray70",
+"h  c #B3B4B3",
+"j  c gray71",
+"k  c #B6B6B6",
+"l  c #B7B7B7",
+"z  c gray72",
+"x  c #BBBBBB",
+"c  c #C5C5C5",
+"v  c #C8C8C8",
+"b  c #CACACA",
+"n  c gray80",
+"m  c #CDCDCD",
+"M  c #CECECE",
+"N  c #D5D5D5",
+"B  c #DADADA",
+"V  c #DCDCDD",
+"C  c #DDDEDF",
+"Z  c gray87",
+"A  c #E1E1E1",
+"S  c #E2E3E3",
+"D  c gray89",
+"F  c #E3E5E5",
+"G  c #E4E4E4",
+"H  c #E5E6E7",
+"J  c #E6E6E6",
+"K  c #E8E9E9",
+"L  c #E9EAEA",
+"P  c #EAEBEB",
+"I  c #EBECEC",
+"U  c #ECECEC",
+"Y  c #ECEDED",
+"T  c gray93",
+"R  c #EDEEEE",
+"E  c #EEEFEF",
+"W  c gray94",
+"Q  c #F0F1F1",
+"!  c #F1F1F1",
+"~  c #F1F2F2",
+"^  c gray95",
+"/  c #F2F3F3",
+"(  c #F3F3F3",
+")  c #F4F4F4",
+"_  c #F4F5F5",
+"`  c gray96",
+"'  c #F6F6F6",
+"]  c gray97",
+"[  c #F8F8F8",
+"{  c #F8F9F9",
+"}  c #F9F9F9",
+"|  c gray98",
+" . c #FBFBFB",
+".. c #FCFCFB",
+"X. c #FDFDFD",
+"o. c #FEFEFE",
+"O. c white",
+"+. c None",
+/* pixels */
+"+.+.+.+.G B B G +.+.+.+.+.+.+.+.",
+"+.8 . N p O.O.p N   8 +.+.+.+.+.",
+"; r o O.W T T W O.; r ; +.+.+.+.",
+"; , n s s f f f f n # ; +.+.+.+.",
+"; ; O.W ] ] D k k n   X +.+.+.+.",
+"& , O.W ] W s O.O.O.O.O.O.O.O.+.",
+"& , O.W W W f O.C D H K P T { +.",
+"# , O.W ] ] f O.F L P Q Q W O.+.",
+"o , O.W ] ] f O.L T Q W ] ] O.+.",
+"o , O.W W { k O.T W ] ] { { O.+.",
+"# , O.] ] { k O.W _ ] { O.O.O.+.",
+"# ; O.) ] { k O._ ] D h f z B +.",
+"; & O.O.O.O.c O.] { C b O.O.y +.",
+", 8 4 0 q r , O.]  .C b  .t +.+.",
+"u 2 4 4 4 4 o O.O.O.F z 6 +.+.+.",
+"+.+.+.+.+.+.+.+.+.+.+.+.+.+.+.+."
+};
diff --git a/mgllab/xpm/edit-redo.xpm b/mgllab/xpm/edit-redo.xpm
new file mode 100644
index 0000000..50b8185
--- /dev/null
+++ b/mgllab/xpm/edit-redo.xpm
@@ -0,0 +1,113 @@
+/* XPM */
+static const char *edit_redo_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 91 1 ",
+"  c #007F00",
+". c #008300",
+"X c #008600",
+"o c #018601",
+"O c #008A00",
+"+ c #028B01",
+"@ c #008C00",
+"# c #018C00",
+"$ c #018D00",
+"% c #018C01",
+"& c #018D01",
+"* c #028C01",
+"= c #028D01",
+"- c #038D01",
+"; c #028D02",
+": c #028E02",
+"> c #038E02",
+", c #048F02",
+"< c #108A0A",
+"1 c #049003",
+"2 c #059003",
+"3 c #079104",
+"4 c #089106",
+"5 c #0B9706",
+"6 c #0A9209",
+"7 c #0F950B",
+"8 c #0E970A",
+"9 c #0D9908",
+"0 c #119D09",
+"q c #109F09",
+"w c #149A0F",
+"e c #149810",
+"r c #179C11",
+"t c #199916",
+"y c #0FAF0A",
+"u c #12AD0D",
+"i c #17AF0F",
+"p c #01B401",
+"a c #03B503",
+"s c #05B505",
+"d c #0FB00A",
+"f c #0BB50B",
+"g c #14B50D",
+"h c #19A110",
+"j c #18A411",
+"k c #12B811",
+"l c #14B912",
+"z c #16B916",
+"x c #18BB17",
+"c c #1DB419",
+"v c #1EBB1D",
+"b c #20A61B",
+"n c #32B21D",
+"m c #33B61F",
+"M c #32AE29",
+"N c #35AE2B",
+"B c #23BE20",
+"V c #23BC22",
+"C c #27BD22",
+"Z c #26BD24",
+"A c #32BC20",
+"S c #36B825",
+"D c #36BA24",
+"F c #39BD21",
+"G c #33C12E",
+"H c #3AC631",
+"J c #38C433",
+"K c #3EC336",
+"L c #3CC834",
+"P c #40C737",
+"I c #48C23F",
+"U c #4CCB43",
+"Y c #4DCB43",
+"T c #50CA46",
+"R c #58C448",
+"E c #5CC64C",
+"W c #5DC64E",
+"Q c #55CF49",
+"! c #5ED254",
+"~ c #64D354",
+"^ c #65D157",
+"/ c #65D455",
+"( c #66D456",
+") c #66D258",
+"_ c #67D658",
+"` c #69D058",
+"' c #72D75E",
+"] c #7FDF67",
+"[ c #85DB6E",
+"{ c #86DB6E",
+"} c None",
+/* pixels */
+"}}}}}&3468}}}}}}",
+"}}}}1MR{{WN,}}&,",
+"}}&r']]]]]]`w,W&",
+"}&e_((QHL!~~~))&",
+"}&UUUvyqjglPYYT,",
+"&tJJx7+&&+hsGJK&",
+"+jZVu+}}}&ikVZC&",
+"&cxf8+}}&FADSmn+",
+"&uap5&}}+&&+X. }",
+"+q}}}X}}}}}}}}}}",
+"}<}}}}}}}}}}}}}}",
+"}}}}}}}}}}}}}}}}",
+"}}}}}}}}}}}}}}}}",
+"}}}}}}}}}}}}}}}}",
+"}}}}}}}}}}}}}}}}",
+"}}}}}}}}}}}}}}}}"
+};
diff --git a/mgllab/xpm/edit-select-all.xpm b/mgllab/xpm/edit-select-all.xpm
new file mode 100644
index 0000000..5d44ccc
--- /dev/null
+++ b/mgllab/xpm/edit-select-all.xpm
@@ -0,0 +1,108 @@
+/* XPM */
+static const char *edit_select_all_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 86 1 ",
+"  c #535453",
+". c #545554",
+"X c #5B5C5A",
+"o c #276CA1",
+"O c #6193B9",
+"+ c #46AFFF",
+"@ c #47AFFF",
+"# c #49B1FF",
+"$ c #4AB1FF",
+"% c #4BB1FF",
+"& c #4CB1FF",
+"* c #4DB2FF",
+"= c #4EB2FF",
+"- c #4FB2FF",
+"; c #4EB3FF",
+": c #4FB3FF",
+"> c #4FB4FF",
+", c #50B3FF",
+"< c #51B4FF",
+"1 c #52B4FF",
+"2 c #54B5FF",
+"3 c #55B5FF",
+"4 c #55B6FF",
+"5 c #56B6FF",
+"6 c #57B6FF",
+"7 c #59B7FE",
+"8 c #58B7FF",
+"9 c #59B7FF",
+"0 c #5EB9FF",
+"q c #5FBAFF",
+"w c #61BBFF",
+"e c #62BBFF",
+"r c #6EC0FF",
+"t c #6FC1FF",
+"y c #7AC6FF",
+"u c #7DC7FF",
+"i c #7EC7FF",
+"p c #7FC8FF",
+"a c #8293A1",
+"s c #B1ADAA",
+"d c #B4B4B4",
+"f c #C3C0BC",
+"g c #80C8FF",
+"h c #91CFFF",
+"j c #92D0FE",
+"k c #99D3FF",
+"l c #A3D7FF",
+"z c #B1DDFF",
+"x c #BCE2FF",
+"c c #CFD7DB",
+"v c #D8DDE0",
+"b c #C9E7FF",
+"n c #CFEAFF",
+"m c #D0EBFF",
+"M c #D3ECFF",
+"N c #DDF0FF",
+"B c #DEF0FF",
+"V c #E3E6E9",
+"C c #E1F2FF",
+"Z c #E5F4FF",
+"A c #E9F6FF",
+"S c #EDF7FF",
+"D c #FCF6F2",
+"F c #FFF9F5",
+"G c #FFFDF4",
+"H c #FFFFF7",
+"J c AliceBlue",
+"K c #F3F9FF",
+"L c #F4F9FF",
+"P c #F8F8F8",
+"I c gray98",
+"U c #FBFBFB",
+"Y c #FFFDF8",
+"T c #FFFFF8",
+"R c #FFFFF9",
+"E c #FFFFFA",
+"W c #FFFFFB",
+"Q c gray99",
+"! c #FDFDFD",
+"~ c #FFFFFC",
+"^ c #FFFFFD",
+"/ c #FDFEFF",
+"( c #FEFEFE",
+") c #FFFFFE",
+"_ c white",
+"` c None",
+/* pixels */
+"````````````````",
+"``____________``",
+"``_0*%*80**%D_``",
+"``_hbJSnLA_tF_``",
+"``_<8883p33<T_``",
+"``_*gy38p3883_``",
+"``_jZCBzmB_Mi_``",
+"``_@**,w*****_``",
+"``_GTTTTT_____``",
+"``_%we,0w*>3T_``",
+"``_kALl_xVaOfv``",
+"``_@**<3<o___ ``",
+"``_TTT___s__X```",
+"``_PI_Q_Id_X````",
+"``_______c.`````",
+"````````````````"
+};
diff --git a/mgllab/xpm/edit-undo.xpm b/mgllab/xpm/edit-undo.xpm
new file mode 100644
index 0000000..82864bb
--- /dev/null
+++ b/mgllab/xpm/edit-undo.xpm
@@ -0,0 +1,131 @@
+/* XPM */
+static const char *edit_undo_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 109 2 ",
+"   c #8C6803",
+".  c #8E6902",
+"X  c #856708",
+"o  c #996505",
+"O  c #976B04",
+"+  c #9C7603",
+"@  c #9E7702",
+"#  c #9F7801",
+"$  c #95780D",
+"%  c #9E7812",
+"&  c #A26B03",
+"*  c #A07B03",
+"=  c #A37D02",
+"-  c #A57E00",
+";  c #A67F00",
+":  c #A67F01",
+">  c #A57E06",
+",  c #A78001",
+"<  c #A78101",
+"1  c #A88001",
+"2  c #A88101",
+"3  c #A98302",
+"4  c #A98203",
+"5  c #AA8303",
+"6  c #A98505",
+"7  c #AD8504",
+"8  c #AB890E",
+"9  c #AD8A0C",
+"0  c #B98F08",
+"q  c #B0900D",
+"w  c #B0910D",
+"e  c #B1910D",
+"r  c #B49210",
+"t  c #B79319",
+"y  c #B99C1D",
+"u  c #AE8833",
+"i  c #CA8403",
+"p  c #C18806",
+"a  c #C58B07",
+"s  c #CD8806",
+"d  c #C78208",
+"f  c #DB8B04",
+"g  c #DC8F0B",
+"h  c #D59C0E",
+"j  c #C89614",
+"k  c #C39D11",
+"l  c #C29C16",
+"z  c #C49F17",
+"x  c #C59019",
+"c  c #DE961A",
+"v  c #E09C1F",
+"b  c #DAB316",
+"n  c #D7BA11",
+"m  c #D1B218",
+"M  c #C39336",
+"N  c #D69D34",
+"B  c #C8A321",
+"V  c #C4A924",
+"C  c #C5AC27",
+"Z  c #CAAA26",
+"A  c #DEAA21",
+"S  c #D5B920",
+"D  c #D0B228",
+"F  c #C9A235",
+"G  c #C3A935",
+"H  c #E2A227",
+"J  c #E3A733",
+"K  c #E4A839",
+"L  c #E8B73A",
+"P  c #E8B73E",
+"I  c #E0B93F",
+"U  c #E1C92E",
+"Y  c #C8AD44",
+"T  c #E3BB40",
+"R  c #E8B448",
+"E  c #DDC548",
+"W  c #E7CF4E",
+"Q  c #ECC155",
+"!  c #ECC156",
+"~  c #E6C850",
+"^  c #EEC854",
+"/  c #EBCD55",
+"(  c #E9CE56",
+")  c #EAC65B",
+"_  c #EBCB5D",
+"`  c #EECA5C",
+"'  c #EBCF5C",
+"]  c #EFCC5F",
+"[  c #EBD354",
+"{  c #EED159",
+"}  c #EFD363",
+"|  c #EFD463",
+" . c #EED164",
+".. c #F3D965",
+"X. c #F3DA65",
+"o. c #F1D967",
+"O. c #F3D966",
+"+. c #F3DB66",
+"@. c #F3DE64",
+"#. c #F5DF67",
+"$. c #F3D969",
+"%. c #F3DA68",
+"&. c #F3DC68",
+"*. c #F4DF69",
+"=. c #F7E567",
+"-. c #F5E069",
+";. c #F9EC71",
+":. c #F9EC72",
+">. c None",
+/* pixels */
+">.>.>.>.>.3 r G Y t 3 >.>.>.>.>.",
+"9 y >.>.V [ #.;.;.#.[ B >.>.>.>.",
+"w o.C E #.=.=.=.=.=.=.-.T 5 >.>.",
+"w $.$.&.+.o.] P L ^ o.o.$.F : >.",
+"w  .} } / A h j x s H ` ] ) % >.",
+"w _ ' ( b k $ = * X o v Q Q u - ",
+"w T ~ W U n 9 >.>.>.> i J R M + ",
+"6 l z Z D S m 4 >.>.3 a c K N   ",
+">.: : : : : : : >.>.3 p f g d   ",
+">.>.>.>.>.>.>.>.>.>.7 >.>.>.& * ",
+">.>.>.>.>.>.>.>.- 3 0 >.>.>.O - ",
+">.>.>.>.>.>.>.>.>.>.>.>.>.>.+ >.",
+">.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.",
+">.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.",
+">.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.",
+">.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>."
+};
diff --git a/mgllab/xpm/edit_xpm b/mgllab/xpm/edit_xpm
new file mode 100755
index 0000000..cc556d6
--- /dev/null
+++ b/mgllab/xpm/edit_xpm
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+for file in *.png
+do
+	convert $file $file.xpm
+	sed 's/_png/_xpm/' $file.xpm > 1.tmp
+	sed 's/static /static const /' 1.tmp > $file.xpm
+done
+rename 's/png.//' *.xpm
diff --git a/mgllab/xpm/fileprint.xpm b/mgllab/xpm/fileprint.xpm
new file mode 100644
index 0000000..6ada912
--- /dev/null
+++ b/mgllab/xpm/fileprint.xpm
@@ -0,0 +1,24 @@
+/* XPM */
+static const char *fileprint[] = {
+"    16    14        6            1",
+". c #000000",
+"# c #848284",
+"a c #c6c3c6",
+"b c #ffff00",
+"c c #ffffff",
+"d c None",
+"ddddd.........dd",
+"dddd.cccccccc.dd",
+"dddd.c.....c.ddd",
+"ddd.cccccccc.ddd",
+"ddd.c.....c....d",
+"dd.cccccccc.a.a.",
+"d..........a.a..",
+".aaaaaaaaaa.a.a.",
+".............aa.",
+".aaaaaa###aa.a.d",
+".aaaaaabbbaa...d",
+".............a.d",
+"d.aaaaaaaaa.a.dd",
+"dd...........ddd"
+};
diff --git a/mgllab/xpm/first.xpm b/mgllab/xpm/first.xpm
new file mode 100644
index 0000000..0265075
--- /dev/null
+++ b/mgllab/xpm/first.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * first_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #0000FF",
+"                ",
+"                ",
+"                ",
+"  ..         .  ",
+"  ..       ...  ",
+"  ..     .....  ",
+"  ..   .......  ",
+"  .. .........  ",
+"  ............  ",
+"  ............  ",
+"  .. .........  ",
+"  ..   .......  ",
+"  ..     .....  ",
+"  ..       ...  ",
+"  ..         .  ",
+"                "};
diff --git a/mgllab/xpm/folder.xpm b/mgllab/xpm/folder.xpm
new file mode 100644
index 0000000..6473918
--- /dev/null
+++ b/mgllab/xpm/folder.xpm
@@ -0,0 +1,130 @@
+/* XPM */
+static const char * folder_xpm[] = {
+"16 16 111 2",
+"  	c None",
+". 	c #7A7A7A",
+"+ 	c #797979",
+"@ 	c #787878",
+"# 	c #C9C9C9",
+"$ 	c #C7C7C7",
+"% 	c #C5C5C5",
+"& 	c #C4C4C4",
+"* 	c #B4B4B4",
+"= 	c #747474",
+"- 	c #737373",
+"; 	c #B0B0B0",
+"> 	c #ADADAD",
+", 	c #ABABAB",
+"' 	c #AAAAAA",
+") 	c #ACACAC",
+"! 	c #8D8D8D",
+"~ 	c #8C8C8C",
+"{ 	c #808080",
+"] 	c #6C6C6C",
+"^ 	c #6E6E6E",
+"/ 	c #C1C1C0",
+"( 	c #A7A7A7",
+"_ 	c #A5A5A5",
+": 	c #A4A4A4",
+"< 	c #B6B6B6",
+"[ 	c #B9B9B9",
+"} 	c #BBBBBB",
+"| 	c #A2A2A2",
+"1 	c #6A6A6A",
+"2 	c #BDBDBD",
+"3 	c #416DA6",
+"4 	c #3666A5",
+"5 	c #3566A4",
+"6 	c #3465A4",
+"7 	c #3768A6",
+"8 	c #656565",
+"9 	c #B7B7B7",
+"0 	c #3566A5",
+"a 	c #BED3EA",
+"b 	c #BFD4EA",
+"c 	c #BED4EA",
+"d 	c #BED3E9",
+"e 	c #B8CFE8",
+"f 	c #3465A5",
+"g 	c #5F5F5F",
+"h 	c #B3B3B3",
+"i 	c #C1D5EA",
+"j 	c #91B4DB",
+"k 	c #91B5DB",
+"l 	c #92B5DB",
+"m 	c #96B8DC",
+"n 	c #B7CFE7",
+"o 	c #3466A4",
+"p 	c #5B5B5B",
+"q 	c #AEAEAE",
+"r 	c #3667A5",
+"s 	c #C4D7EB",
+"t 	c #94B7DC",
+"u 	c #91B4DA",
+"v 	c #B6CDE6",
+"w 	c #565656",
+"x 	c #A9A9A9",
+"y 	c #3666A4",
+"z 	c #C6D8EC",
+"A 	c #99BADD",
+"B 	c #95B7DC",
+"C 	c #8EB2DA",
+"D 	c #8BB0D9",
+"E 	c #B8CFE7",
+"F 	c #515151",
+"G 	c #A5A5A4",
+"H 	c #3767A5",
+"I 	c #BED2E9",
+"J 	c #9BBADD",
+"K 	c #99B9DD",
+"L 	c #95B6DC",
+"M 	c #90B3DA",
+"N 	c #8EB2D9",
+"O 	c #89AED8",
+"P 	c #87ADD7",
+"Q 	c #8BB0D8",
+"R 	c #B1C9E5",
+"S 	c #4C4C4C",
+"T 	c #A1A1A1",
+"U 	c #3868A5",
+"V 	c #A9C4E2",
+"W 	c #81A8D5",
+"X 	c #7AA4D3",
+"Y 	c #7EA7D4",
+"Z 	c #9CBADD",
+"` 	c #484848",
+" .	c #9B9B9B",
+"..	c #3867A4",
+"+.	c #85ABD5",
+"@.	c #6E9CCE",
+"#.	c #6D9CCE",
+"$.	c #709ECF",
+"%.	c #84ABD5",
+"&.	c #494949",
+"*.	c #999999",
+"=.	c #3968A5",
+"-.	c #7EA6D3",
+";.	c #78A3D2",
+">.	c #79A4D3",
+",.	c #7AA5D1",
+"'.	c #788697",
+").	c #3A69A5",
+"!.	c #5083BA",
+"~.	c #4578B2",
+"{.	c #464D53",
+"                                ",
+". + + + + + +                   ",
+"@ # $ % & & * =                 ",
+"- % ; > , ' ) ! ! ~ ~ ~ { ]     ",
+"^ / ) ' ( _ : : ) < [ } | 1     ",
+"1 2 3 4 4 4 4 4 5 5 5 5 6 6 6 7 ",
+"8 9 0 a b b c c c d d d d d e f ",
+"g h 5 i j j k k l l l l l m n o ",
+"p q r s t t t t t t t t t u v 0 ",
+"w x y z A A A A A A A B C D E 0 ",
+"F G H I J K L l M N O P P Q R 0 ",
+"S T U V W X X X X X X X X Y Z 0 ",
+"`  ...+. at .#.#.#.#.#.#.#.#.$.%.0 ",
+"&.*.=.-.;.;.;.;.;.;.;.;.;.>.,.0 ",
+"` '.).!.!.!.!.!.!.!.!.!.!.!.~.4 ",
+"{.6 6 6 6 6 6 6 6 6 6 6 6 6 5   "};
diff --git a/mgllab/xpm/format-indent-more.xpm b/mgllab/xpm/format-indent-more.xpm
new file mode 100644
index 0000000..43f5c81
--- /dev/null
+++ b/mgllab/xpm/format-indent-more.xpm
@@ -0,0 +1,56 @@
+/* XPM */
+static const char *format_indent_more_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 34 1 ",
+"  c #921B18",
+". c #A22320",
+"X c #BE3936",
+"o c #D35451",
+"O c #D35653",
+"+ c #D45552",
+"@ c #D55653",
+"# c #E57471",
+"$ c #E67572",
+"% c #E67772",
+"& c #E67674",
+"* c #498DC7",
+"= c #4C8ECC",
+"- c #4E8FCC",
+"; c #4B90CB",
+": c #F39795",
+"> c #F39B97",
+", c #F49A98",
+"< c #F49A9A",
+"1 c #F39D99",
+"2 c #F8AEAA",
+"3 c #F8AEAC",
+"4 c #F8B0AC",
+"5 c #F8B1AC",
+"6 c #F8B2AE",
+"7 c #F8B3B0",
+"8 c #F9B5B1",
+"9 c #F9B7B3",
+"0 c #FABFBA",
+"q c #FBCAC7",
+"w c #FCD2D2",
+"e c #FEFEFE",
+"r c white",
+"t c None",
+/* pixels */
+"t-************-t",
+"t*rrrrrrrrrrrr;t",
+"t*rrrrrrrrrrrr;t",
+"t*rrrrr;;;;;rr;t",
+"t*rrrrr0rrrrrr*t",
+"t*rrrrr.9rrrrr;t",
+"t*rrrrr. 9rrrr;t",
+"t*w<&@X.  7rrr;t",
+"t*w>&oX.   6rr*t",
+"t*w1$@X.    3r;t",
+"t*w>$oX.   2rr;t",
+"t*w>$oX.  2rrr;t",
+"t*rrrrr. 6rrrr;t",
+"t*rrrrr.4rrrrr;t",
+"t*rrrrrqrrrrrr;t",
+"t-;;;;;;;*;;;*-t"
+};
diff --git a/mgllab/xpm/format-stroke-color.xpm b/mgllab/xpm/format-stroke-color.xpm
new file mode 100644
index 0000000..96c397f
--- /dev/null
+++ b/mgllab/xpm/format-stroke-color.xpm
@@ -0,0 +1,87 @@
+/* XPM */
+static const char *format_stroke_color_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 65 1 ",
+"  c #010101",
+". c gray2",
+"X c #0E0E0E",
+"o c #0B1111",
+"O c #131313",
+"+ c gray8",
+"@ c #171716",
+"# c #1D1D1D",
+"$ c #1E1E1E",
+"% c gray12",
+"& c #2A261A",
+"* c #162323",
+"= c #1D2424",
+"- c #1B2C2C",
+"; c #0F3131",
+": c #202020",
+"> c #222222",
+", c #232323",
+"< c #212424",
+"1 c gray14",
+"2 c #222828",
+"3 c gray16",
+"4 c gray17",
+"5 c #2D2D2D",
+"6 c #353535",
+"7 c #393939",
+"8 c #49301E",
+"9 c #4E273A",
+"0 c #5C2531",
+"q c #662226",
+"w c #693A34",
+"e c #4F6F2E",
+"r c #456238",
+"t c #736433",
+"y c #786836",
+"u c #342A4B",
+"i c #282D55",
+"p c #2B3D53",
+"a c #22335A",
+"s c #402842",
+"d c #33494A",
+"f c #3B4D4D",
+"g c #3C5541",
+"h c gray27",
+"j c #605945",
+"k c #686868",
+"l c red",
+"z c #827B68",
+"x c #00CC00",
+"c c #AB8F33",
+"v c #99FF00",
+"b c #C6AF66",
+"n c #330098",
+"m c #340098",
+"M c #340099",
+"N c #670098",
+"B c #660099",
+"V c #0033CC",
+"C c #0034CD",
+"Z c #CC0099",
+"A c #808080",
+"S c #818181",
+"D c gray58",
+"F c #A9A395",
+"G c None",
+/* pixels */
+"G.GGGGGGGGGGGGGG",
+"X4SGGGGGGGGGGGGG",
+"GDk GCVGGnmGGGGG",
+"G42=oGVGGnmGGGGG",
+"GG;-*6GGGGGGNNGG",
+"GGGf<%hGGGGGNGGG",
+"GGGGS1%GGGGGGGGG",
+"GxxGG7,5GGGGGGZZ",
+"GxGGGG,,4GGGGGZG",
+"GGGGGGO,%%GGGGGG",
+"GvvGGGGO%O&GGGlG",
+"GvvGGGGG at jcGGGlG",
+"GGGGGGGGGFbyGGGG",
+"GGGGGGGGGGztGGGG",
+"GGGGGGGGGGGw8GGG",
+"Gergdpaius90qGGG"
+};
diff --git a/mgllab/xpm/func.xpm b/mgllab/xpm/func.xpm
new file mode 100644
index 0000000..e62cfe7
--- /dev/null
+++ b/mgllab/xpm/func.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * func_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"   .   .    .   ",
+"  .   .      .  ",
+"  .   .      .  ",
+" ... .  .  .  . ",
+"  .  .  .  .  . ",
+"  .  .   ..   . ",
+"  .  .   ..   . ",
+"  .  .  .  .  . ",
+"  .   . .  . .  ",
+"      .      .  ",
+"       .    .   ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/go-bottom.xpm b/mgllab/xpm/go-bottom.xpm
new file mode 100644
index 0000000..1ccde51
--- /dev/null
+++ b/mgllab/xpm/go-bottom.xpm
@@ -0,0 +1,108 @@
+/* XPM */
+static const char *go_bottom_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 86 1 ",
+"  c #122742",
+". c #102746",
+"X c #1F3344",
+"o c #1E3659",
+"O c #233847",
+"+ c #263F5E",
+"@ c #1E3962",
+"# c #233E60",
+"$ c #29446B",
+"% c #384D6A",
+"& c #35576D",
+"* c #36576D",
+"= c #224470",
+"- c #274873",
+"; c #3A577D",
+": c #365788",
+"> c #37598C",
+", c #3A5E8F",
+"< c #3C5E8E",
+"1 c #3C5F8F",
+"2 c #3D5F8F",
+"3 c #386785",
+"4 c #386885",
+"5 c #2558A5",
+"6 c #426084",
+"7 c #456386",
+"8 c #44628A",
+"9 c #42628F",
+"0 c #4F6B8C",
+"q c #526B8D",
+"w c #526D8E",
+"e c #536E8F",
+"r c #4D6D95",
+"t c #4E6D96",
+"y c #4F709B",
+"u c #4F719C",
+"i c #547091",
+"p c #567295",
+"a c #567395",
+"s c #597497",
+"d c #5E7797",
+"f c #577598",
+"g c #54749D",
+"h c #54749E",
+"j c #59789B",
+"k c #617D9C",
+"l c #617E9D",
+"z c #627E9D",
+"x c #436CA2",
+"c c #486FA4",
+"v c #4E73A9",
+"b c #4F74AA",
+"n c #5071A0",
+"m c #5877A4",
+"M c #5778A2",
+"N c #5C7CAB",
+"B c #5C7DAC",
+"V c #5A80B7",
+"C c #5B80B7",
+"Z c #5D83B8",
+"A c #5D83B9",
+"S c #6181AF",
+"D c #6383AE",
+"F c #6C8AAB",
+"G c #6E8CAB",
+"H c #6383B0",
+"J c #6384B3",
+"K c #6586B4",
+"L c #678BB3",
+"P c #6B8FB7",
+"I c #6187BD",
+"U c #648ABC",
+"Y c #7094BE",
+"T c #6B91C2",
+"R c #6C90C6",
+"E c #6C91C6",
+"W c #7498C1",
+"Q c #7599CE",
+"! c #799DD2",
+"~ c #7A9ED2",
+"^ c #7FA6D5",
+"/ c #81A8D7",
+"( c #88ABDE",
+") c #92B5E7",
+"_ c #93B5E7",
+"` c None",
+/* pixels */
+"`````HugyyD`````",
+"````5xkkDdc`````",
+"`>0eiafjffaiedN`",
+"``o;8rgMjgrsq%``",
+"```$9nBJKHm:@```",
+"```.<vVIICb2 ```",
+"````#ZRQQRZ+````",
+"`````6!((!7`````",
+"``````L))P``````",
+"``````X^/O``````",
+"```````**```````",
+"````````````````",
+"```````YW```````",
+"``````,GF<``````",
+"``````=UT-``````",
+"```````44```````"
+};
diff --git a/mgllab/xpm/go-down.xpm b/mgllab/xpm/go-down.xpm
new file mode 100644
index 0000000..4d2c523
--- /dev/null
+++ b/mgllab/xpm/go-down.xpm
@@ -0,0 +1,122 @@
+/* XPM */
+static const char *go_down_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 100 2 ",
+"   c #070E17",
+".  c #030B18",
+"X  c #070E18",
+"o  c #040E1D",
+"O  c #040F1F",
+"+  c #051327",
+"@  c #0E1725",
+"#  c #0F1927",
+"$  c #0C203C",
+"%  c #092041",
+"&  c #0B2244",
+"*  c #0E2444",
+"=  c #0B2449",
+"-  c #1E324E",
+";  c #0D2952",
+":  c #0F2B55",
+">  c #0F2D59",
+",  c #112D57",
+"<  c #102E5B",
+"1  c #11305D",
+"2  c #11315F",
+"3  c #1B365E",
+"4  c #243958",
+"5  c #123261",
+"6  c #143465",
+"7  c #143566",
+"8  c #153769",
+"9  c #15376B",
+"0  c #16396E",
+"q  c #173C72",
+"w  c #173D74",
+"e  c #1A427E",
+"r  c #254470",
+"t  c #264677",
+"y  c #2E4B72",
+"u  c #2C4B7A",
+"i  c #345178",
+"p  c #1D4887",
+"a  c #1F4D90",
+"s  c #385782",
+"d  c #3B5D8E",
+"f  c #204E91",
+"g  c #204E93",
+"h  c #214F95",
+"j  c #215097",
+"k  c #225198",
+"l  c #22529A",
+"z  c #415E83",
+"x  c #445C80",
+"c  c #446287",
+"v  c #4B6387",
+"b  c #4A688D",
+"n  c #476894",
+"m  c #44689C",
+"M  c #4C6F9F",
+"N  c #526F91",
+"B  c #506E93",
+"V  c #557293",
+"C  c #537297",
+"Z  c #567394",
+"A  c #57769B",
+"S  c #58769C",
+"D  c #5F7C9B",
+"F  c #59789E",
+"G  c #607D9B",
+"H  c #617E9C",
+"J  c #627E9C",
+"K  c #496EA3",
+"L  c #4C70A3",
+"P  c #5173A1",
+"I  c #5474A2",
+"U  c #5676A4",
+"Y  c #5578A7",
+"T  c #5779A8",
+"R  c #5378AF",
+"E  c #5478AC",
+"W  c #567CB2",
+"Q  c #5C81B8",
+"!  c #5D83B9",
+"~  c #6E8BA7",
+"^  c #6F8CA8",
+"/  c #708DA9",
+"(  c #7D9AB4",
+")  c #7E9BB5",
+"_  c #7E9CB6",
+"`  c #7F9CB6",
+"'  c #668CC2",
+"]  c #6C90C6",
+"[  c #7297CB",
+"{  c #7398CC",
+"}  c #759ACE",
+"|  c #7A9ED2",
+" . c #85A2BC",
+".. c #86A3BD",
+"X. c #87A4BE",
+"o. c #83A7DA",
+"O. c #88ABDE",
+"+. c #89ACDF",
+"@. c #8CAFE2",
+"#. c None",
+/* pixels */
+"#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.",
+"#.#.#.#.#.l l h h f f #.#.#.#.#.",
+"#.#.#.#.#.f ....X.X.p #.#.#.#.#.",
+"#.#.#.#.#.p ( ) _ _ e #.#.#.#.#.",
+"#.#.#.#.#.e ~ ~ / / w #.#.#.#.#.",
+"#.#.#.#.#.q D G J J 8 #.#.#.#.#.",
+"#.#.0 8 7 7 N V Z Z 5 5 1 < > #.",
+"#.#.5 i z b C S S A B c y ; #.#.",
+"#.#., 3 s n P Y T K d t < = #.#.",
+"#.#.#.* r m R ! ! W K u % #.#.#.",
+"#.#.#.#.$ K ' [ } ] T * #.#.#.#.",
+"#.#.#.#.+ - [ O. at .| 4 #.#.#.#.#.",
+"#.#.#.#.#.O x o.+.v O #.#.#.#.#.",
+"#.#.#.#.#.#.  I U   #.#.#.#.#.#.",
+"#.#.#.#.#.#.#.# @ #.#.#.#.#.#.#.",
+"#.#.#.#.#.#.#.. . #.#.#.#.#.#.#."
+};
diff --git a/mgllab/xpm/go-first-view.xpm b/mgllab/xpm/go-first-view.xpm
new file mode 100644
index 0000000..dff3d3f
--- /dev/null
+++ b/mgllab/xpm/go-first-view.xpm
@@ -0,0 +1,138 @@
+/* XPM */
+static const char *go_first_view_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 116 2 ",
+"   c #081D3E",
+".  c #081E40",
+"X  c #082247",
+"o  c #0B2346",
+"O  c #09264F",
+"+  c #0B2A57",
+"@  c #0E2B58",
+"#  c #0F2C58",
+"$  c #1A355E",
+"%  c #0E2F60",
+"&  c #113161",
+"*  c #153764",
+"=  c #163667",
+"-  c #103369",
+";  c #18396B",
+":  c #1B3E6D",
+">  c #123971",
+",  c #183D73",
+"<  c #143D79",
+"1  c #2B4A74",
+"2  c #2C4B74",
+"3  c #234679",
+"4  c #244E7D",
+"5  c #2D4C7B",
+"6  c #294A7D",
+"7  c #314F7B",
+"8  c #355279",
+"9  c #174282",
+"0  c #19468A",
+"q  c #1C4C93",
+"w  c #2B5083",
+"e  c #2E5285",
+"r  c #2E5788",
+"t  c #36598C",
+"y  c #214F94",
+"u  c #21529D",
+"i  c #395E92",
+"p  c #325C99",
+"a  c #376093",
+"s  c #2355A1",
+"d  c #2255A2",
+"f  c #2356A2",
+"g  c #2257A5",
+"h  c #2B5BA1",
+"j  c #2E5FA7",
+"k  c #265AAA",
+"l  c #265BAA",
+"z  c #4D6C93",
+"x  c #43689D",
+"c  c #446A9E",
+"v  c #5B7898",
+"b  c #4469A0",
+"n  c #416EAC",
+"m  c #4D73A9",
+"M  c #4F75AF",
+"N  c #577EAE",
+"B  c #577DB4",
+"V  c #5D81B3",
+"C  c #5B81B8",
+"Z  c #5981BB",
+"A  c #5883BA",
+"S  c #5A85B9",
+"D  c #5F84BC",
+"F  c #6683A3",
+"G  c #6283A8",
+"H  c #6383AC",
+"J  c #7D91AF",
+"K  c #6F8CB4",
+"L  c #6186BE",
+"P  c #7090B1",
+"I  c #7F9DB8",
+"U  c #7B9BBF",
+"Y  c #628AC3",
+"T  c #688DC3",
+"R  c #6E92C6",
+"E  c #6990C9",
+"W  c #6C98CC",
+"Q  c #7496C1",
+"!  c #7195CB",
+"~  c #7399CF",
+"^  c #779BCF",
+"/  c #789BCF",
+"(  c #7CAEE0",
+")  c #92A1B5",
+"_  c #85A3C0",
+"`  c #89A8C7",
+"'  c #84A5CA",
+"]  c #82A4CE",
+"[  c #8CACCB",
+"{  c #89AACF",
+"}  c #93B0C8",
+"|  c #94B3CB",
+" . c #91B0CF",
+".. c #95B3CD",
+"X. c #8AACD5",
+"o. c #81A5D8",
+"O. c #84A8DB",
+"+. c #8FB0D4",
+"@. c #8FB0DB",
+"#. c #91B4D4",
+"$. c #99B8D0",
+"%. c #99B8D2",
+"&. c #B1B9C6",
+"*. c #89ACE0",
+"=. c #8DB0E3",
+"-. c #8EB1E4",
+";. c #98BEEF",
+":. c #9ABEEF",
+">. c #A5C3D8",
+",. c #A8C6DA",
+"<. c #97C1F1",
+"1. c #ABC3E6",
+"2. c #AFC5E5",
+"3. c #D3D7DE",
+"4. c #C3E1F0",
+"5. c None",
+/* pixels */
+"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.",
+"5.5.5.5.5.5.5.5.5.5.5.5.5.l l 5.",
+"5.2./ 1.5.5.5.5.5.5.5.5.s Z u 5.",
+"5.T 3.E 5.5.5.5.5.5.5.j #.4.q 5.",
+"5.D &.Y 5.5.5.5.5.g n %.>.>.0 5.",
+"5.B ) Z 5.5.5.5.s V }  ...$.9 5.",
+"5.m J M 5.5.5.h G I ) ' [ #.< 5.",
+"5.c K b 5.s p v F P U ' { #.> 5.",
+"5.a S i 5.y w 8 z H U / X. at .- 5.",
+"5.r W e 5.5.5., 4 x Z ! O.-.& 5.",
+"5.4 ( 3 5.5.5.5.= t L ^ =.:.+ 5.",
+"5.: ;.; 5.5.5.5.5.# 5 R o.*.O 5.",
+"5.= <.& 5.5.5.5.5.5.5.$ V ~ X 5.",
+"5.2 @ 1 5.5.5.5.5.5.5.5.o 8 . 5.",
+"5.5.5.5.5.5.5.5.5.5.5.5.5.  . 5.",
+"5.5.5.5.5.5.5.5.5.5.5.5.5.5.5.5."
+};
diff --git a/mgllab/xpm/go-first.xpm b/mgllab/xpm/go-first.xpm
new file mode 100644
index 0000000..7026dfd
--- /dev/null
+++ b/mgllab/xpm/go-first.xpm
@@ -0,0 +1,119 @@
+/* XPM */
+static const char *go_first_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 97 2 ",
+"   c #10263B",
+".  c #102A43",
+"X  c #122F49",
+"o  c #122D56",
+"O  c #183B6F",
+"+  c #204060",
+"@  c #22446F",
+"#  c #23477A",
+"$  c #2D4F7F",
+"%  c #2C5670",
+"&  c #2C517B",
+"*  c #3E5A77",
+"=  c #36547B",
+"-  c #28518F",
+";  c #335880",
+":  c #3D5A82",
+">  c #335788",
+",  c #3A5F8D",
+"<  c #395D8F",
+"1  c #356083",
+"2  c #386484",
+"3  c #3C6988",
+"4  c #3E6195",
+"5  c #3D6397",
+"6  c #3F6594",
+"7  c #3A64A0",
+"8  c #3964A2",
+"9  c #426087",
+"0  c #4D688A",
+"q  c #4C6A8C",
+"w  c #516A8A",
+"e  c #556E8C",
+"r  c #4D6B92",
+"t  c #597696",
+"y  c #657B97",
+"u  c #527DA7",
+"i  c #5378AE",
+"p  c #527BB2",
+"a  c #567CB2",
+"s  c #627FA0",
+"d  c #6282A9",
+"f  c #6686A9",
+"g  c #6D8BAB",
+"h  c #6E8CAB",
+"j  c #6C8BAD",
+"k  c #6387B3",
+"l  c #6386B9",
+"z  c #6289BB",
+"x  c #6D91BD",
+"c  c #6F91BD",
+"v  c #7896B3",
+"b  c #7696BA",
+"n  c #7494BC",
+"m  c #7F9EBC",
+"M  c #5C92C1",
+"N  c #678CC2",
+"B  c #6A8FC4",
+"V  c #6D91C3",
+"C  c #7A99C1",
+"Z  c #7297CC",
+"A  c #7D9FCE",
+"S  c #739DD0",
+"D  c #779CD0",
+"F  c #799DD1",
+"G  c #7B9FD3",
+"H  c #7FA0C5",
+"J  c #7EA2D6",
+"K  c #85A5C4",
+"L  c #8BA9C3",
+"P  c #81A2CA",
+"I  c #86A7CD",
+"U  c #86A8CD",
+"Y  c #88A8C8",
+"T  c #89A9C9",
+"R  c #8AAACA",
+"E  c #8EADC8",
+"W  c #8CACCD",
+"Q  c #91B0CB",
+"!  c #92B1CD",
+"~  c #94B2CC",
+"^  c #8AABD1",
+"/  c #8BABD3",
+"(  c #8AACD1",
+")  c #8CACD7",
+"_  c #85A9DC",
+"`  c #87AADD",
+"'  c #87AEDF",
+"]  c #88ACDE",
+"[  c #95ADD1",
+"{  c #9DBBD3",
+"}  c #9DBCD3",
+"|  c #90B0D8",
+" . c #91B4E6",
+".. c #94B8E9",
+"X. c #AECDE1",
+"o. c #BFDBEE",
+"O. c None",
+/* pixels */
+"O.O.O.O.O.O.O.O.O.O.O.O.O.O.O.O.",
+"O.O.O.O.O.O.O.O.O.O.O.O.O.[ O.O.",
+"O.O.O.O.O.O.O.O.O.O.O.O.c o.- O.",
+"O.O.O.O.O.O.O.O.O.O.8 Y X.X.O O.",
+"O.O.O.O.O.O.O.O.O.p ~ { } } o O.",
+"O.O.O.O.O.O.O.O.k L E ! ! ! e y ",
+"O.c C O.O.O.8 f v m K T W W T 0 ",
+"< h g 6 O.5 t s j b H U ( ^ I w ",
+"@ l V & O.> = r d n P / | ) A : ",
+"O.2 3 O.O.O.# & 5 i N F ` ' G 9 ",
+"O.O.O.O.O.O.O.O.< a V J  ...q * ",
+"O.O.O.O.O.O.O.O.O.= z S ` '   O.",
+"O.O.O.O.O.O.O.O.O.O.+ u Z J . O.",
+"O.O.O.O.O.O.O.O.O.O.O.O.; M X O.",
+"O.O.O.O.O.O.O.O.O.O.O.O.O.% O.O.",
+"O.O.O.O.O.O.O.O.O.O.O.O.O.O.O.O."
+};
diff --git a/mgllab/xpm/go-jump-locationbar.xpm b/mgllab/xpm/go-jump-locationbar.xpm
new file mode 100644
index 0000000..2442811
--- /dev/null
+++ b/mgllab/xpm/go-jump-locationbar.xpm
@@ -0,0 +1,103 @@
+/* XPM */
+static const char *go_jump_locationbar_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 81 1 ",
+"  c #071E3F",
+". c #081F40",
+"X c #081E43",
+"o c #092249",
+"O c #092C61",
+"+ c #0F3668",
+"@ c #193964",
+"# c #15336F",
+"$ c #143D78",
+"% c #1F4573",
+"& c #1D4779",
+"* c #2A4871",
+"= c #194388",
+"- c #194995",
+"; c #335786",
+": c #36598C",
+"> c #21539F",
+", c #22549D",
+"< c #1F53A1",
+"1 c #2354A0",
+"2 c #2557A4",
+"3 c #2558A4",
+"4 c #2559A6",
+"5 c #3B5DA0",
+"6 c #3B5EA5",
+"7 c #3362A9",
+"8 c #3767AE",
+"9 c #3D6BAD",
+"0 c #2467B1",
+"q c #2776BA",
+"w c #2B74B8",
+"e c #406597",
+"r c #466A9F",
+"t c #4567A3",
+"y c #496DA4",
+"u c #4171B5",
+"i c #5179B5",
+"p c #5F80A6",
+"a c #5186B9",
+"s c #5787BF",
+"d c #6185BE",
+"f c #3086C5",
+"g c #3C89C5",
+"h c #3292CC",
+"j c #4692CA",
+"k c #638CC2",
+"l c #6C93C5",
+"z c #6699CA",
+"x c #789DCB",
+"c c #7F9FD1",
+"v c #59A3D8",
+"b c #59A7DD",
+"n c #78A1CE",
+"m c #79A4CF",
+"M c #7CAFDA",
+"N c #6AB1DE",
+"B c #66B1E0",
+"V c #6DB7E2",
+"C c #83A3CF",
+"Z c #80ADD4",
+"A c #97BDDC",
+"S c #99B9DB",
+"D c #9FBEDE",
+"F c #A1BCE1",
+"G c #90C9EE",
+"H c #A5C9E6",
+"J c #AECAE6",
+"K c #AECEE9",
+"L c #B4D2EA",
+"P c #AEDDF9",
+"I c #BDDBF1",
+"U c #BFDCF2",
+"Y c #B2DFF8",
+"T c #BEE6FC",
+"R c #C4E1F5",
+"E c #C7E3F5",
+"W c #C7E5F8",
+"Q c #D1EDFA",
+"! c #C9F0FF",
+"~ c #D4F1FF",
+"^ c None",
+/* pixels */
+"^^^^^^^^^^^^^^^^",
+"^^^24^^^^^^^^^^^",
+"^^^-l1^^^^^^^^^^",
+"^^^t~J7^^^^^^^^^",
+"^^^yQLUi<^^^^^^^",
+"^^^rRKDSd>^^^^^^",
+"^^^eWHmnxC9^^^^^",
+"^^^:IAZzskF64^^^",
+"^^^;Mjgq0uc5,^^^",
+"^^^&vNhfw8=^^^^^",
+"^^^%GYYBa$^^^^^^",
+"^^^+VT!pO^^^^^^^",
+"^^^@bR*^^^^^^^^^",
+"^^^X#o^^^^^^^^^^",
+"^^^..^^^^^^^^^^^",
+"^^^^^^^^^^^^^^^^"
+};
diff --git a/mgllab/xpm/go-last-view.xpm b/mgllab/xpm/go-last-view.xpm
new file mode 100644
index 0000000..b2db855
--- /dev/null
+++ b/mgllab/xpm/go-last-view.xpm
@@ -0,0 +1,139 @@
+/* XPM */
+static const char *go_last_view_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 117 2 ",
+"   c #061D3F",
+".  c #081D3F",
+"X  c #071F42",
+"o  c #061E45",
+"O  c #082042",
+"+  c #06234C",
+"@  c #092956",
+"#  c #0B2957",
+"$  c #0F2D58",
+"%  c #0D2E5F",
+"&  c #153057",
+"*  c #0F3361",
+"=  c #0F3368",
+"-  c #173664",
+";  c #143566",
+":  c #1B3B6B",
+">  c #193D6E",
+",  c #113771",
+"<  c #123C7A",
+"1  c #1B4078",
+"2  c #1B427C",
+"3  c #264673",
+"4  c #254577",
+"5  c #2B4972",
+"6  c #2C4C76",
+"7  c #254778",
+"8  c #234E7F",
+"9  c #2F4F7D",
+"0  c #154083",
+"q  c #1D4784",
+"w  c #16458A",
+"e  c #1A4A93",
+"r  c #1E529D",
+"t  c #2E5385",
+"y  c #2F598D",
+"u  c #3D5A81",
+"i  c #345688",
+"p  c #34578B",
+"a  c #36598C",
+"s  c #23529B",
+"d  c #385D90",
+"f  c #3A6398",
+"g  c #2054A2",
+"h  c #2256A3",
+"j  c #2556A3",
+"k  c #2457A3",
+"l  c #265CAD",
+"z  c #265DAF",
+"x  c #3060A4",
+"c  c #3363AA",
+"v  c #43679C",
+"b  c #45699F",
+"n  c #52739D",
+"m  c #456CA5",
+"M  c #4C71A7",
+"N  c #4D72A8",
+"B  c #4A75AF",
+"V  c #5177AF",
+"C  c #4F78B2",
+"Z  c #577CB3",
+"A  c #5C81B8",
+"S  c #5A85BA",
+"D  c #5E84BA",
+"F  c #5A83BF",
+"G  c #6489B7",
+"H  c #698AB1",
+"J  c #6085BA",
+"K  c #6188BF",
+"L  c #6A8BBB",
+"P  c #728EB6",
+"I  c #6F91B4",
+"U  c #7F92B1",
+"Y  c #668BC1",
+"T  c #638DC7",
+"R  c #698CC0",
+"E  c #6B8FC3",
+"W  c #6892C3",
+"Q  c #6E92C6",
+"!  c #6A92CB",
+"~  c #6E93C8",
+"^  c #6B99CE",
+"/  c #7B9CC1",
+"(  c #7094C9",
+")  c #7296C9",
+"_  c #7398CE",
+"`  c #779BD0",
+"'  c #799DD2",
+"]  c #7BB0E1",
+"[  c #92A0B5",
+"{  c #84A3C1",
+"}  c #87A6C5",
+"|  c #81A2C8",
+" . c #84A6CC",
+".. c #89A9CA",
+"X. c #8BACCC",
+"o. c #98B6CF",
+"O. c #8BACD1",
+"+. c #83A8DC",
+"@. c #84A8DD",
+"#. c #93B3D1",
+"$. c #97B6D2",
+"%. c #98B6D1",
+"&. c #9EBDD7",
+"*. c #9CBEDB",
+"=. c #AFB7C4",
+"-. c #92B5E9",
+";. c #97BFF0",
+":. c #A3C2DA",
+">. c #A8C7DE",
+",. c #97C1F1",
+"<. c #ADC3E5",
+"1. c #AECDE1",
+"2. c #B3CAEA",
+"3. c #A0C4F8",
+"4. c #D1D4DA",
+"5. c #C6E5F3",
+"6. c None",
+/* pixels */
+"6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.",
+"6.z z 6.6.6.6.6.6.6.6.6.6.6.6.6.",
+"6.r W h 6.6.6.6.6.6.6.6.2._ <.6.",
+"6.e 5.*.c 6.6.6.6.6.6.6.! 4.E 6.",
+"6.w 1.>.:.B h 6.6.6.6.6.T =.J 6.",
+"6.0 &.$.%.o.G j 6.6.6.6.F [ Z 6.",
+"6.< #.X...} { I x 6.6.6.C U M 6.",
+"6., O. .| / H n 9 q j 6.m P v 6.",
+"6.; ( E D V m a 4 2 s 6.f S d 6.",
+"6.% ` Q Y A M i 1 6.6.6.y ^ t 6.",
+"6.# @.' ( K i ; 6.6.6.6.8 ] 7 6.",
+"6.+ -.+.Q 3 $ 6.6.6.6.6.> ,.: 6.",
+"6.o 3.L & 6.6.6.6.6.6.6.* ,.- 6.",
+"6.  u X 6.6.6.6.6.6.6.6.6 # 5 6.",
+"6.O . 6.6.6.6.6.6.6.6.6.6.6.6.6.",
+"6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6."
+};
diff --git a/mgllab/xpm/go-last.xpm b/mgllab/xpm/go-last.xpm
new file mode 100644
index 0000000..1bfde69
--- /dev/null
+++ b/mgllab/xpm/go-last.xpm
@@ -0,0 +1,116 @@
+/* XPM */
+static const char *go_last_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 94 2 ",
+"   c #162E44",
+".  c #1D3B5A",
+"X  c #17386A",
+"o  c #1B3A69",
+"O  c #284D6C",
+"+  c #214271",
+"@  c #264B75",
+"#  c #2A4B76",
+"$  c #274778",
+"%  c #31507D",
+"&  c #31557D",
+"*  c #3F5C7C",
+"=  c #345689",
+"-  c #34578A",
+";  c #375A8B",
+":  c #3F5F8B",
+">  c #386484",
+",  c #3C618F",
+"<  c #3C6989",
+"1  c #3E698B",
+"2  c #3B6292",
+"3  c #3E6191",
+"4  c #3C6BAF",
+"5  c #476688",
+"6  c #42638E",
+"7  c #4A6993",
+"8  c #4B6B96",
+"9  c #42659A",
+"0  c #45699E",
+"q  c #51719A",
+"w  c #50719C",
+"e  c #4E73A9",
+"r  c #4E76AD",
+"t  c #5E7EA8",
+"y  c #5D7FAB",
+"u  c #5479B0",
+"i  c #587EB4",
+"p  c #5681AA",
+"a  c #5B80B6",
+"s  c #5F85BB",
+"d  c #6080A6",
+"f  c #6D8BAB",
+"g  c #6E8BAB",
+"h  c #6C89B1",
+"j  c #6F8EB1",
+"k  c #6C8DB6",
+"l  c #6286B9",
+"z  c #618ABB",
+"x  c #6589BE",
+"c  c #678BBF",
+"v  c #6E91BD",
+"b  c #7494B8",
+"n  c #7395BE",
+"m  c #7999BE",
+"M  c #7E9DBD",
+"N  c #658AC0",
+"B  c #688DC3",
+"V  c #6A8EC2",
+"C  c #6B8FC2",
+"Z  c #6E91C4",
+"A  c #6C91C6",
+"S  c #6893CB",
+"D  c #6E92C8",
+"F  c #6F94C9",
+"G  c #7799C3",
+"H  c #7B9BC0",
+"J  c #7B9AC2",
+"K  c #7C9DC2",
+"L  c #7D9EC3",
+"P  c #799CC5",
+"I  c #799CC6",
+"U  c #7D9FC7",
+"Y  c #7094C9",
+"T  c #7599CE",
+"R  c #6995D7",
+"E  c #789CD0",
+"W  c #7BA0D3",
+"Q  c #81A0C0",
+"!  c #83A2C3",
+"~  c #84A3C4",
+"^  c #84A4C4",
+"/  c #86A5C4",
+"(  c #8CABC7",
+")  c #8CABC8",
+"_  c #90ADC9",
+"`  c #98B6CF",
+"'  c #80A4D8",
+"]  c #85AADC",
+"[  c #85ACDD",
+"{  c #9EBBD2",
+"}  c #81B6E1",
+"|  c #8DB6E6",
+" . c #AFC9DE",
+".. c None",
+/* pixels */
+"................................",
+"....R ..........................",
+".... .S ........................",
+"....{ ` ! 4 ....................",
+"...._ ( ( / r ..................",
+"h q ~ ^ Q Q Q p ................",
+"w H L L L m b j d - ......Z G ..",
+"7 G I I G n k t 8 % o ..2 f f 6 ",
+", N Z B x a e 9 - $ o ..@ l Z # ",
+"6 Z Z D B s u 0 ; + ......> < ..",
+"* 5 W E Y N i , ................",
+"..  [ ' T z & ..................",
+"....| ] p . ....................",
+"....} 6 ........................",
+"....O ..........................",
+"................................"
+};
diff --git a/mgllab/xpm/go-next-view-page.xpm b/mgllab/xpm/go-next-view-page.xpm
new file mode 100644
index 0000000..eb46032
--- /dev/null
+++ b/mgllab/xpm/go-next-view-page.xpm
@@ -0,0 +1,99 @@
+/* XPM */
+static const char *go_next_view_page_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 77 1 ",
+"  c #18481D",
+". c #1D5617",
+"X c #1B5719",
+"o c #21621E",
+"O c #3E7E18",
+"+ c #184928",
+"@ c #277028",
+"# c #32712D",
+"$ c #328234",
+"% c #3D8E3C",
+"& c #75AC0C",
+"* c #639F38",
+"= c #549D4C",
+"- c #559E4F",
+"; c #55875D",
+": c #5B9D56",
+"> c #64A753",
+", c #77B250",
+"< c #74A477",
+"1 c #7CB378",
+"2 c #85BE20",
+"3 c #99D20B",
+"4 c #A0D70C",
+"5 c #8EC423",
+"6 c #91C824",
+"7 c #A8D06A",
+"8 c #AAD072",
+"9 c #8C8E8F",
+"0 c #8F9091",
+"q c #8F9492",
+"w c #909091",
+"e c #939394",
+"r c #9B9D9E",
+"t c #8BA992",
+"y c #9E9FA0",
+"u c #9F9FA0",
+"i c #9FADA3",
+"p c #A2A3A3",
+"a c #A6A7A8",
+"s c #A7A7A8",
+"d c gray66",
+"f c #B9B9B9",
+"g c gray73",
+"h c #BFDE9A",
+"j c #C5C5C5",
+"k c #C5C6C6",
+"l c #C8CACB",
+"z c #D2D2D2",
+"x c #D2DAD4",
+"c c gray85",
+"v c gray86",
+"b c #D2E2D2",
+"n c #D8E9D6",
+"m c #DFEDDE",
+"M c gray89",
+"N c #EAEAEA",
+"B c #E9EFE9",
+"V c #EEEEEE",
+"C c #EEEFEF",
+"Z c #EFEFEF",
+"A c gray94",
+"S c #F2F7F1",
+"D c #F4F5F5",
+"F c gray96",
+"G c #F5F6F6",
+"H c #F6F6F6",
+"J c gray97",
+"K c #F8F8F8",
+"L c #F8F9F9",
+"P c #F9F9F9",
+"I c gray98",
+"U c #FBFBFB",
+"Y c gray99",
+"T c #FDFDFD",
+"R c #FEFEFE",
+"E c white",
+"W c None",
+/* pixels */
+"WWWWWWWWWWWWWWWW",
+"WEEEEEEEEnmWWWWW",
+"WEDDPPPPP==#WWWW",
+"WEPPPPYPE%h>1SEW",
+"WEPPEPPEE$87,:bW",
+"WEPPPEEEE at 265*<W",
+"WEPEEEEEPo34O;BW",
+"WEEPPEPDZ.&XtPEW",
+"WEYYEENau +pEEEW",
+"WEYYEDsEExwvCZDW",
+"WEYEYAuEDrjsralW",
+"WEYYYZsJizsYEPwW",
+"WEEPEDkpcArEK9WW",
+"WWWWWggMEZsPwWWW",
+"WWWWWEPEEDkeWWWW",
+"WWWWWWWWWWWWWWWW"
+};
diff --git a/mgllab/xpm/go-next-view.xpm b/mgllab/xpm/go-next-view.xpm
new file mode 100644
index 0000000..fabc6cc
--- /dev/null
+++ b/mgllab/xpm/go-next-view.xpm
@@ -0,0 +1,102 @@
+/* XPM */
+static const char *go_next_view_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 80 1 ",
+"  c #071D3B",
+". c #091D3F",
+"X c #081F41",
+"o c #0B2447",
+"O c #0B2449",
+"+ c #0D2850",
+"@ c #0F2D58",
+"# c #122F5C",
+"$ c #19355E",
+"% c #123160",
+"& c #143668",
+"* c #17366A",
+"= c #163A70",
+"- c #183F78",
+"; c #1B4179",
+": c #2A4A78",
+"> c #3C577D",
+", c #1B4380",
+"< c #1D4580",
+"1 c #1D4887",
+"2 c #1F4989",
+"3 c #1F4C8F",
+"4 c #1F4D8F",
+"5 c #2C4E80",
+"6 c #325382",
+"7 c #385B8F",
+"8 c #215197",
+"9 c #23569E",
+"0 c #24559E",
+"q c #395C92",
+"w c #3C5F93",
+"e c #305C9E",
+"r c #2556A3",
+"t c #2457A5",
+"y c #2759A0",
+"u c #2758A2",
+"i c #3663A3",
+"p c #4F709C",
+"a c #496EA3",
+"s c #4D75AA",
+"d c #5076AC",
+"f c #547AB1",
+"g c #5C84B4",
+"h c #5D82B9",
+"j c #5D83B9",
+"k c #6387B2",
+"l c #6687B0",
+"z c #6C8CB1",
+"x c #6388BD",
+"c c #6589BD",
+"v c #6489BF",
+"b c #6B8BBB",
+"n c #7898BF",
+"m c #668BC1",
+"M c #6B8FC5",
+"N c #6B90C5",
+"B c #6F92C6",
+"V c #7E9FC5",
+"C c #7094C9",
+"Z c #779BCF",
+"A c #779CD0",
+"S c #7FA1C6",
+"D c #809FBF",
+"F c #80A2C7",
+"G c #85A4C4",
+"H c #88A8C7",
+"J c #88A7C8",
+"K c #89A8C9",
+"L c #92B1CD",
+"P c #94B3CE",
+"I c #94B3CF",
+"U c #81A5D9",
+"Y c #84A8DB",
+"T c #95B6D1",
+"R c #9CBBD4",
+"E c #91B4E6",
+"W c #A3C2D9",
+"Q c #A4C2DA",
+"! c #B6D6E9",
+"~ c None",
+/* pixels */
+"~~~~~~~~~~~~~~~~",
+"~~~0t~~~~~~~~~~~",
+"~~~8gu~~~~~~~~~~",
+"~~~3!Ti~~~~~~~~~",
+"~~~1WQRsr~~~~~~~",
+"~~~,IIILku~~~~~~",
+"~~~-HKJGDze~~~~~",
+"~~~=SFVnlp629~~~",
+"~~~&vxjfaw5<3~~~",
+"~~~#BNmjdq;~~~~~",
+"~~~#ZZCv7*~~~~~~",
+"~~~@YAB:#~~~~~~~",
+"~~~OEb$~~~~~~~~~",
+"~~~o>o~~~~~~~~~~",
+"~~~. ~~~~~~~~~~~",
+"~~~~~~~~~~~~~~~~"
+};
diff --git a/mgllab/xpm/go-next.xpm b/mgllab/xpm/go-next.xpm
new file mode 100644
index 0000000..30509c8
--- /dev/null
+++ b/mgllab/xpm/go-next.xpm
@@ -0,0 +1,128 @@
+/* XPM */
+static const char *go_next_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 106 2 ",
+"   c #08172B",
+".  c #091B37",
+"X  c #0A1D38",
+"o  c #0D203D",
+"O  c #102130",
+"+  c #11273B",
+"@  c #0B2244",
+"#  c #0B2346",
+"$  c #0F2648",
+"%  c #112747",
+"&  c #122E45",
+"*  c #18304C",
+"=  c #122D54",
+"-  c #122E59",
+";  c #173255",
+":  c #143057",
+">  c #1E3F57",
+",  c #14315C",
+"<  c #133261",
+"1  c #173768",
+"2  c #15386B",
+"3  c #16396E",
+"4  c #183B6F",
+"5  c #29415E",
+"6  c #1F4379",
+"7  c #1F447D",
+"8  c #244760",
+"9  c #23426A",
+"0  c #2B4C7D",
+"q  c #274F8B",
+"w  c #365A89",
+"e  c #35588A",
+"r  c #3A5E8F",
+"t  c #214F93",
+"y  c #2C5592",
+"u  c #235299",
+"i  c #23549D",
+"p  c #315D9E",
+"a  c #3E6393",
+"s  c #2B5CA5",
+"d  c #3865A6",
+"f  c #4E688E",
+"g  c #4D759B",
+"h  c #57749A",
+"j  c #51719C",
+"k  c #436BA5",
+"l  c #496EA2",
+"z  c #4C6FA0",
+"x  c #4B76B0",
+"c  c #547AB0",
+"v  c #557CB0",
+"b  c #5C80B1",
+"n  c #5C85B9",
+"m  c #5F85BB",
+"M  c #6B89AD",
+"N  c #6E8CAD",
+"B  c #6385B1",
+"V  c #6E8FB4",
+"C  c #608BB9",
+"Z  c #658AB8",
+"A  c #688CBD",
+"S  c #6F92BF",
+"D  c #7191B6",
+"F  c #7494B8",
+"G  c #7798BE",
+"H  c #7D9CBC",
+"J  c #658BC0",
+"K  c #648DC1",
+"L  c #688DC3",
+"P  c #6D92C7",
+"I  c #6E96C8",
+"U  c #7094C3",
+"Y  c #7598C6",
+"T  c #7599C7",
+"R  c #7C9DC2",
+"E  c #7D9EC4",
+"W  c #7095CA",
+"Q  c #7299CB",
+"!  c #779AC8",
+"~  c #769CD0",
+"^  c #789DD0",
+"/  c #8AA4BE",
+"(  c #82A2C2",
+")  c #87A4C1",
+"_  c #86A6C7",
+"`  c #8AA8C7",
+"'  c #80A2C8",
+"]  c #81A2C9",
+"[  c #83A5CB",
+"{  c #87A7C8",
+"}  c #89A9CA",
+"|  c #8BAACA",
+" . c #8BABCB",
+".. c #8AAACC",
+"X. c #90AECA",
+"o. c #91B0CD",
+"O. c #93B2CF",
+"+. c #80A6D8",
+"@. c #96B4D0",
+"#. c #97B5D1",
+"$. c #A0BFD7",
+"%. c #81B3E1",
+"&. c #A6C4DA",
+"*. c #B9D5E7",
+"=. c #C1CFE4",
+"-. c None",
+/* pixels */
+"-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.",
+"-.-.-.-.-.-.=.-.-.-.-.-.-.-.-.-.",
+"-.-.-.-.-.-.y k u -.-.-.-.-.-.-.",
+"-.-.-.-.-.-.4 *.{ p -.-.-.-.-.-.",
+"-.-.-.-.-.-.= &.&. at .x -.-.-.-.-.",
+"-.f 3 2 - $ o @.o.o.X.Z s -.-.-.",
+"-.< / ) ` | | ..{ { ( H V d -.-.",
+"-., N F R ' [ [ ' E G D M h q i ",
+"-.= j B P Y ! ! P A v z w 0 4 u ",
+"-.; a v A I Q P L C c l r 0 -.-.",
+"-.5 # # X   O ^ W J n w 2 -.-.-.",
+"-.-.-.-.-.-.+ +.~ C 9 -.-.-.-.-.",
+"-.-.-.-.-.-.& %.g % -.-.-.-.-.-.",
+"-.-.-.-.-.-.> * X -.-.-.-.-.-.-.",
+"-.-.-.-.-.-.8 -.-.-.-.-.-.-.-.-.",
+"-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-."
+};
diff --git a/mgllab/xpm/go-previous-view-page.xpm b/mgllab/xpm/go-previous-view-page.xpm
new file mode 100644
index 0000000..f62b3b0
--- /dev/null
+++ b/mgllab/xpm/go-previous-view-page.xpm
@@ -0,0 +1,97 @@
+/* XPM */
+static const char *go_previous_view_page_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 75 1 ",
+"  c #0B4716",
+". c #16471D",
+"X c #185C1C",
+"o c #20591A",
+"O c #285632",
+"+ c #236E25",
+"@ c #407E17",
+"# c #348335",
+"$ c #3F8F3C",
+"% c #55952A",
+"& c #549D4C",
+"* c #549851",
+"= c #5DA258",
+"- c #73AF4E",
+"; c #61A551",
+": c #5A8A61",
+"> c #75917C",
+", c #74A970",
+"< c #84B70D",
+"1 c #84BD23",
+"2 c #9DD40D",
+"3 c #A1D90C",
+"4 c #89C220",
+"5 c #90C724",
+"6 c #A7D06A",
+"7 c #ABD171",
+"8 c #8C8E8F",
+"9 c #8F9091",
+"0 c #909091",
+"q c #939394",
+"w c #87AF89",
+"e c #9F9FA0",
+"r c #A6A7A8",
+"t c #A7A7A8",
+"y c gray66",
+"u c #AFAFAF",
+"i c gray69",
+"p c #BFDE99",
+"a c #A6C6A4",
+"s c #C0C0C0",
+"d c #C1C1C1",
+"f c #C5C6C6",
+"g c #C8CACB",
+"h c #CAD6CD",
+"j c #D3DCD6",
+"k c #CCE2CA",
+"l c #D6E4D7",
+"z c gray90",
+"x c #E2EEE1",
+"c c #EAEAEA",
+"v c #EAEFEA",
+"b c #EEEEEE",
+"n c #EEEFEF",
+"m c #EFEFEF",
+"M c #EDF2ED",
+"N c #EEF2EF",
+"B c gray94",
+"V c #F4F5F5",
+"C c gray96",
+"Z c #F5F6F5",
+"A c #F5F6F6",
+"S c #F6F6F6",
+"D c #F6F7F6",
+"F c gray97",
+"G c #F8F8F8",
+"H c #F8F9F8",
+"J c #F9F9F9",
+"K c gray98",
+"L c #FBFBFB",
+"P c gray99",
+"I c #FDFDFD",
+"U c #FDFEFD",
+"Y c #FEFEFE",
+"T c white",
+"R c None",
+/* pixels */
+"RRRRRRRRRRRRRRRR",
+"RTTTTTxkTTTRRRRR",
+"RTVVza&=sigRRRRR",
+"RTGM,;p$TTTTTTTR",
+"RTl*-67#VGGTGGTR",
+"RTw%154+VTGGTGTR",
+"RTv:@23XFPTGTGGR",
+"RTGT>o< VTTGTTTR",
+"RTTTuhO.FTTTPTTR",
+"RTGGiTNjLTPVmbVR",
+"RTTTiTTGTPcyergR",
+"RTGTiTGTTVyTTG0R",
+"RTTGiTTTTBqTV8RR",
+"RRRRRTGTTBuG0RRR",
+"RRRRRTGTTVfqRRRR",
+"RRRRRRRRRRRRRRRR"
+};
diff --git a/mgllab/xpm/go-previous-view.xpm b/mgllab/xpm/go-previous-view.xpm
new file mode 100644
index 0000000..1831419
--- /dev/null
+++ b/mgllab/xpm/go-previous-view.xpm
@@ -0,0 +1,102 @@
+/* XPM */
+static const char *go_previous_view_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 80 1 ",
+"  c #071A3A",
+". c #091C3C",
+"X c #081E3F",
+"o c #0B2344",
+"O c #0B2347",
+"+ c #0D2850",
+"@ c #0F2D58",
+"# c #122E59",
+"$ c #153057",
+"% c #123160",
+"& c #163667",
+"* c #143668",
+"= c #163A70",
+"- c #163C73",
+"; c #1E3F71",
+": c #183F78",
+"> c #26426A",
+", c #23426F",
+"< c #25436C",
+"1 c #2A4B7D",
+"2 c #34537C",
+"3 c #1B4380",
+"4 c #1D4887",
+"5 c #1F4C8F",
+"6 c #244B82",
+"7 c #385B8E",
+"8 c #214E92",
+"9 c #215197",
+"0 c #24559E",
+"q c #26589F",
+"w c #2E5A9B",
+"e c #335B93",
+"r c #2357A0",
+"t c #2556A3",
+"y c #2457A5",
+"u c #2758A2",
+"i c #3461A2",
+"p c #4C6C97",
+"a c #577495",
+"s c #5B7797",
+"d c #476FA3",
+"f c #5A7DA5",
+"g c #5075AB",
+"h c #5577A8",
+"j c #557AB1",
+"k c #5A83B3",
+"l c #6180A2",
+"z c #6684A6",
+"x c #6284AE",
+"c c #7491AE",
+"v c #6286BB",
+"b c #7190B3",
+"n c #7B99B7",
+"m c #7A9BBF",
+"M c #658BC0",
+"N c #6C91C6",
+"B c #7497C3",
+"V c #769ACF",
+"C c #7D9FCB",
+"Z c #789CD1",
+"A c #7EA2D6",
+"S c #82A0BF",
+"D c #81A2C7",
+"F c #85A5C4",
+"G c #87A6C6",
+"H c #89A7C0",
+"J c #8DAAC4",
+"K c #8FADC7",
+"L c #84A5CB",
+"P c #80A2CF",
+"I c #8FAEC8",
+"U c #93B3CD",
+"Y c #97B5CD",
+"T c #83A7DA",
+"R c #9FBDD2",
+"E c #9FBDD3",
+"W c #8CAFE2",
+"Q c #99BBEC",
+"! c #B6D5E8",
+"~ c None",
+/* pixels */
+"~~~~~~~~~~~~~~~~",
+"~~~~~~~~~~~y0~~~",
+"~~~~~~~~~~uk9~~~",
+"~~~~~~~~~iU!5~~~",
+"~~~~~~~tdYEE4~~~",
+"~~~~~~qfHJII3~~~",
+"~~~~~wlcnSFF:~~~",
+"~~~reaszbmDL=~~~",
+"~~~86,2pxBCP*~~~",
+"~~~~~-;7gMZT%~~~",
+"~~~~~~&1jNTQ#~~~",
+"~~~~~~~#,vAW+~~~",
+"~~~~~~~~~$hVO~~~",
+"~~~~~~~~~~O>X~~~",
+"~~~~~~~~~~~ .~~~",
+"~~~~~~~~~~~~~~~~"
+};
diff --git a/mgllab/xpm/go-previous.xpm b/mgllab/xpm/go-previous.xpm
new file mode 100644
index 0000000..b016b25
--- /dev/null
+++ b/mgllab/xpm/go-previous.xpm
@@ -0,0 +1,123 @@
+/* XPM */
+static const char *go_previous_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 101 2 ",
+"   c #061020",
+".  c #071428",
+"X  c #071529",
+"o  c #07172E",
+"O  c #071832",
+"+  c #071A34",
+"@  c #071B37",
+"#  c #081A35",
+"$  c #091C38",
+"%  c #0C1E3A",
+"&  c #081F40",
+"*  c #0B2040",
+"=  c #0A2041",
+"-  c #0A2245",
+";  c #0E2444",
+":  c #0A2348",
+">  c #0D2850",
+",  c #0F2D58",
+"<  c #122B52",
+"1  c #112C54",
+"2  c #142E56",
+"3  c #123160",
+"4  c #153565",
+"5  c #153667",
+"6  c #143669",
+"7  c #16396E",
+"8  c #183A6C",
+"9  c #1A3F77",
+"0  c #314A6E",
+"q  c #204070",
+"w  c #274A7E",
+"e  c #1F4A8A",
+"r  c #28518D",
+"t  c #37598C",
+"y  c #204D90",
+"u  c #214F93",
+"i  c #225298",
+"p  c #235299",
+"a  c #23549D",
+"s  c #2C5A9C",
+"d  c #3A5D91",
+"f  c #2557A3",
+"g  c #2658A1",
+"h  c #2959A1",
+"j  c #3C6AAA",
+"k  c #476795",
+"l  c #44689D",
+"z  c #55759D",
+"x  c #476FA1",
+"c  c #4C71A6",
+"v  c #4E72A7",
+"b  c #5A7AA2",
+"n  c #5379AF",
+"m  c #5479AF",
+"M  c #567EB1",
+"N  c #5F85BB",
+"B  c #6688AF",
+"V  c #6C8BAF",
+"C  c #6489BF",
+"Z  c #678CBD",
+"A  c #6F94BC",
+"S  c #7A9ABD",
+"D  c #688DC2",
+"F  c #6C91C7",
+"G  c #6D92C7",
+"H  c #6F94C9",
+"J  c #7499CD",
+"K  c #7A9DCA",
+"L  c #7A9BCC",
+"P  c #779BD0",
+"I  c #809FBD",
+"U  c #82A2C4",
+"Y  c #82A3C7",
+"T  c #86A6C5",
+"R  c #8BA9C4",
+"E  c #8BABCB",
+"W  c #8FAFCB",
+"Q  c #88A9CE",
+"!  c #8CADCE",
+"~  c #8EAECF",
+"^  c #91B0CC",
+"/  c #85A7D0",
+"(  c #80A3D7",
+")  c #8BADD1",
+"_  c #8AACD2",
+"`  c #8FB0D0",
+"'  c #95B4D0",
+"]  c #96B5D2",
+"[  c #96B7D3",
+"{  c #92B3D4",
+"}  c #94B5D5",
+"|  c #98B7D4",
+" . c #99B8D5",
+".. c #9AB9D6",
+"X. c #9ABAD7",
+"o. c #A2C1DA",
+"O. c #A3C2DB",
+"+. c #A3C3DC",
+"@. c #ADCDE3",
+"#. c #AECDE3",
+"$. c None",
+/* pixels */
+"$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.",
+"$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.",
+"$.$.$.$.$.$.$.i y e $.$.$.$.$.$.",
+"$.$.$.$.$.$.i x ' 8 $.$.$.$.$.$.",
+"$.$.$.$.$.h A @.#.< $.$.$.$.$.$.",
+"$.$.$.f j ! O.O.+.% ; 1 6 7 6 $.",
+"$.$.g M W ' | ..X.X...' ^ R 3 $.",
+"a s B I T E ` { } } { ` U b , $.",
+"u r z V S Y Q _ _ / K Z c t > $.",
+"$.$.9 w l m N D G H F C m d : $.",
+"$.$.$.4 q c D G P   X # = - & $.",
+"$.$.$.$.$.2 k J ( X $.$.$.$.$.$.",
+"$.$.$.$.$.$.= 0 L o $.$.$.$.$.$.",
+"$.$.$.$.$.$.$.$ + O $.$.$.$.$.$.",
+"$.$.$.$.$.$.$.$.$.+ $.$.$.$.$.$.",
+"$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$."
+};
diff --git a/mgllab/xpm/go-top.xpm b/mgllab/xpm/go-top.xpm
new file mode 100644
index 0000000..5dae152
--- /dev/null
+++ b/mgllab/xpm/go-top.xpm
@@ -0,0 +1,116 @@
+/* XPM */
+static const char *go_top_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 94 2 ",
+"   c #10243E",
+".  c #102542",
+"X  c #122A47",
+"o  c #152944",
+"O  c #1A365B",
+"+  c #1C365B",
+"@  c #2B4567",
+"#  c #2C536E",
+"$  c #234570",
+"%  c #234777",
+"&  c #274873",
+"*  c #385377",
+"=  c #395E7C",
+"-  c #2F5386",
+";  c #315583",
+":  c #345581",
+">  c #3A5E8F",
+",  c #3B5F8F",
+"<  c #2D5795",
+"1  c #3A6B89",
+"2  c #3B6E8B",
+"3  c #3D6193",
+"4  c #466285",
+"5  c #446286",
+"6  c #456387",
+"7  c #4A6B8F",
+"8  c #446797",
+"9  c #4B6C91",
+"0  c #496A96",
+"q  c #467493",
+"w  c #537396",
+"e  c #537397",
+"r  c #50709B",
+"t  c #55739C",
+"y  c #57769E",
+"u  c #5C7898",
+"i  c #436DA7",
+"p  c #5177AB",
+"a  c #567BAD",
+"s  c #4D77B1",
+"d  c #4C8CB1",
+"f  c #6582A3",
+"g  c #6686A9",
+"h  c #6786AB",
+"j  c #6485AF",
+"k  c #6685AF",
+"l  c #6887AC",
+"z  c #6C8AAB",
+"x  c #6E8CAB",
+"c  c #6085B1",
+"v  c #6187BD",
+"b  c #648ABC",
+"n  c #668CBF",
+"m  c #7291B2",
+"M  c #7392B3",
+"N  c #7091B7",
+"B  c #7191B7",
+"V  c #7896B3",
+"C  c #7996B3",
+"Z  c #7C99B7",
+"A  c #7C9AB7",
+"S  c #7093BE",
+"D  c #7293BE",
+"F  c #7495BF",
+"G  c #7897B9",
+"H  c #7798BE",
+"J  c #7E9CB9",
+"K  c #7A9ABC",
+"L  c #7899BF",
+"P  c #6B90C2",
+"I  c #6F94C9",
+"U  c #7897C0",
+"Y  c #7599C4",
+"T  c #7B9DC4",
+"R  c #7C9DC4",
+"E  c #7497CB",
+"W  c #7A9CC8",
+"Q  c #7E9FC9",
+"!  c #7B9FD2",
+"~  c #7B9FD3",
+"^  c #7FA2CC",
+"/  c #7DA0D3",
+"(  c #7CA0D4",
+")  c #84A1BB",
+"_  c #84A2BB",
+"`  c #84A1BC",
+"'  c #85A2BC",
+"]  c #85A4C3",
+"[  c #82A4CD",
+"{  c #94B2C9",
+"}  c #8BAEE1",
+"|  c #A4C2D8",
+" . c #A4C3D8",
+".. c None",
+/* pixels */
+"..............D U ..............",
+"............> x z > ............",
+"............$ b P & ............",
+"..............1 2 ..............",
+"................................",
+"..............H Y ..............",
+"............0  . .s ............",
+"............` { { ] ............",
+"..........u ` ` ` _ c ..........",
+"........* C J J J Z V i ........",
+"......+ f M G K K G m h < ......",
+"......6 h m K R R K N h r ......",
+"....@ p c F W [ [ W F c t - ....",
+"..# * 0 a b E ! ! E b p 3 ; d ..",
+"....X .   5 ! } } ! 6 o O % ....",
+"..........= 9 e e 9 q .........."
+};
diff --git a/mgllab/xpm/go-up.xpm b/mgllab/xpm/go-up.xpm
new file mode 100644
index 0000000..523aa9d
--- /dev/null
+++ b/mgllab/xpm/go-up.xpm
@@ -0,0 +1,123 @@
+/* XPM */
+static const char *go_up_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 101 2 ",
+"   c #040A14",
+".  c #070C14",
+"X  c #081220",
+"o  c #0A182F",
+"O  c #0C1B32",
+"+  c #081D3B",
+"@  c #081E3E",
+"#  c #081F40",
+"$  c #092041",
+"%  c #0B2142",
+"&  c #0B2244",
+"*  c #0A2245",
+"=  c #0E2547",
+"-  c #0B2448",
+";  c #0C2549",
+":  c #0E274C",
+">  c #0E284D",
+",  c #0F284D",
+"<  c #102749",
+"1  c #10284A",
+"2  c #122D56",
+"3  c #153159",
+"4  c #15305A",
+"5  c #16325A",
+"6  c #12305D",
+"7  c #13325E",
+"8  c #153665",
+"9  c #153667",
+"0  c #143668",
+"q  c #1B3F74",
+"w  c #1B4179",
+"e  c #2A4A77",
+"r  c #2D4C76",
+"t  c #2A4B7B",
+"y  c #1E4887",
+"u  c #385782",
+"i  c #38598B",
+"p  c #215095",
+"a  c #2E5893",
+"s  c #24559F",
+"d  c #26579E",
+"f  c #2657A1",
+"g  c #2558A3",
+"h  c #3260A2",
+"j  c #3663A3",
+"k  c #4B688C",
+"l  c #406498",
+"z  c #4A6E9A",
+"x  c #56769C",
+"c  c #4F74AA",
+"v  c #5073A3",
+"b  c #5375A4",
+"n  c #597FAE",
+"m  c #597DB0",
+"M  c #5A7FB6",
+"N  c #5F84BB",
+"B  c #6687AC",
+"V  c #6E8CAB",
+"C  c #6E8EB2",
+"Z  c #688AB6",
+"A  c #6084B8",
+"S  c #6287BC",
+"D  c #6F90B6",
+"F  c #7392B4",
+"G  c #7594B6",
+"H  c #7596BD",
+"J  c #7897BA",
+"K  c #7998BB",
+"L  c #7E9CBA",
+"P  c #7B9ABD",
+"I  c #678CC2",
+"U  c #698EC3",
+"Y  c #6E92C8",
+"T  c #6F94C8",
+"R  c #7698C0",
+"E  c #7899C0",
+"W  c #7297CC",
+"Q  c #7397CC",
+"!  c #769ACF",
+"~  c #7A9ED2",
+"^  c #7CA0D4",
+"/  c #7DA1D5",
+"(  c #7FA3D6",
+")  c #7FA3D7",
+"_  c #809EBC",
+"`  c #81A0BD",
+"'  c #82A0BD",
+"]  c #87A4BE",
+"[  c #87A6C0",
+"{  c #8AA8C2",
+"}  c #8BA8C2",
+"|  c #88A9C6",
+" . c #8AACCA",
+".. c #98B7CD",
+"X. c #81A5D8",
+"o. c #82A6D8",
+"O. c #8AADE0",
+"+. c #8DB0E2",
+"@. c #8FB2E4",
+"#. c #96B8EA",
+"$. c None",
+/* pixels */
+"$.$.$.$.$.$.$.d p $.$.$.$.$.$.$.",
+"$.$.$.$.$.$.$.h a $.$.$.$.$.$.$.",
+"$.$.$.$.$.$.f  .| w $.$.$.$.$.$.",
+"$.$.$.$.$.g n ....x 0 $.$.$.$.$.",
+"$.$.$.$.$.j [ } } ] r $.$.$.$.$.",
+"$.$.$.$.d C _ ' ' L V 3 $.$.$.$.",
+"$.$.$.y z G K P P K F k : $.$.$.",
+"$.$.q e B D H E R Z b i 3 & $.$.",
+"$.$.3 u v n A S N M c l t % $.$.",
+"$.$.< O X . I Y T U 1 > ; @ + $.",
+"$.$.$.$.$.  ! ( ( ! % $.$.$.$.$.",
+"$.$.$.$.$.o ( o. at .X.& $.$.$.$.$.",
+"$.$.$.$.$.; ~ @.#.X.- $.$.$.$.$.",
+"$.$.$.$.$.6 T ~ ) W & $.$.$.$.$.",
+"$.$.$.$.$.0 8 7 2 > # $.$.$.$.$.",
+"$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$."
+};
diff --git a/mgllab/xpm/help-contents.xpm b/mgllab/xpm/help-contents.xpm
new file mode 100644
index 0000000..028a211
--- /dev/null
+++ b/mgllab/xpm/help-contents.xpm
@@ -0,0 +1,126 @@
+/* XPM */
+static const char *help_contents_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 104 2 ",
+"   c #AB1010",
+".  c #A21B1B",
+"X  c #A11C1B",
+"o  c #B21C1C",
+"O  c #A32827",
+"+  c #A52927",
+"@  c #A62A29",
+"#  c #B32020",
+"$  c #B32221",
+"%  c #B52626",
+"&  c #A37A77",
+"*  c #A57B78",
+"=  c #A47C79",
+"-  c #A47E7B",
+";  c #A47F7B",
+":  c #B27774",
+">  c #B17977",
+",  c #B77B79",
+"<  c #B57D7B",
+"1  c #EB5757",
+"2  c #EC5757",
+"3  c #EB5C5C",
+"4  c #ED5F5F",
+"5  c #A2837F",
+"6  c #A6827E",
+"7  c #888A85",
+"8  c #898B86",
+"9  c #8A8C87",
+"0  c #8D8F8A",
+"q  c #8F918C",
+"w  c #A68481",
+"e  c #B68885",
+"r  c #BA8D8B",
+"t  c #B79693",
+"y  c #B99390",
+"u  c #B89490",
+"i  c #BA9694",
+"p  c #BD9896",
+"a  c #BAA6A2",
+"s  c #BBA6A3",
+"d  c #BAA8A5",
+"f  c #BAA9A6",
+"g  c #BCAEAB",
+"h  c #BFAEAB",
+"j  c #BABDB6",
+"k  c #D78F8E",
+"l  c #D69392",
+"z  c #D79C9B",
+"x  c #EC8C8C",
+"c  c #F08686",
+"v  c #E09392",
+"b  c #EE9897",
+"n  c #E39E9D",
+"m  c #F69090",
+"M  c #F09F9F",
+"N  c #C5ABA8",
+"B  c #C6ABA8",
+"V  c #C5ADA9",
+"C  c #C6ACA8",
+"Z  c #C0AFAC",
+"A  c #DBA4A2",
+"S  c #CAB1AE",
+"D  c #CDB3B1",
+"F  c #D0B4B2",
+"G  c #D0B5B3",
+"H  c #EDA7A7",
+"J  c #E6AAA9",
+"K  c #EFB2B1",
+"L  c #EAB8B7",
+"P  c #F9B1B1",
+"I  c #C0C3BC",
+"U  c #C2C4BE",
+"Y  c #DEE1DB",
+"T  c #DFE2DC",
+"R  c #E0E3DD",
+"E  c #E1E3DE",
+"W  c #E2E4DF",
+"Q  c #E2E5E0",
+"!  c #E3E5E0",
+"~  c #E4E6E1",
+"^  c #E6E8E4",
+"/  c #E6E9E4",
+"(  c #EAECE8",
+")  c #ECEDEA",
+"_  c #EDEEEB",
+"`  c #EDEFEC",
+"'  c #EEEEEC",
+"]  c #EEEEED",
+"[  c #EEF0ED",
+"{  c #EFF0ED",
+"}  c #F0F0EE",
+"|  c #F0F1EE",
+" . c #F0F1EF",
+".. c #F1F2F0",
+"X. c #F2F3F0",
+"o. c #F2F2F1",
+"O. c #F4F5F3",
+"+. c #F5F5F4",
+"@. c #F8F8F7",
+"#. c #F8F8F8",
+"$. c #F8F9F8",
+"%. c #FAFAF9",
+"&. c white",
+"*. c None",
+/* pixels */
+"*.0 8 8 8 7 7 7 7 7 8 7 7 8 q *.",
+"*.8 &.&.&.&.&.&.&.&.&.&.&.&.9 *.",
+"*.7 &.Y I j j j j j j U ( &.8 *.",
+"*.8 &.Y W / ( ' [ | | [ ( &.8 *.",
+"*.8 &.E ! N & 0 0 - S | ` &.8 *.",
+"*.7 &.E > O l ' ` z + < [ &.8 *.",
+"*.7 &.N O c 1 a a 3 M @ D &.7 *.",
+"*.8 &.5 k 2   y y   4 A 6 &.8 *.",
+"*.8 &.0 | f e O.#.p s o.0 &.8 *.",
+"*.8 &.0 o.a t O.#.r g +.0 &.8 *.",
+"*.8 &.- v x . y i . H n w &.7 *.",
+"*.7 &.V o m b Z Z K P # D &.8 *.",
+"*.7 &.W > # J @.#.L % , o.&.8 *.",
+"*.8 &.W ~ V - 0 q * D O.o.&.8 *.",
+"*.8 &.&.&.&.&.&.&.&.&.&.&.&.8 *.",
+"*.0 8 7 7 7 7 7 7 7 7 7 8 8 q *."
+};
diff --git a/mgllab/xpm/help-faq.xpm b/mgllab/xpm/help-faq.xpm
new file mode 100644
index 0000000..77be04e
--- /dev/null
+++ b/mgllab/xpm/help-faq.xpm
@@ -0,0 +1,95 @@
+/* XPM */
+static const char *help_faq_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 73 1 ",
+"  c #7AA5D2",
+". c #7AA5D3",
+"X c #888A85",
+"o c #8A8C88",
+"O c #8B8D88",
+"+ c #8D8F89",
+"@ c #8D8E8A",
+"# c #8D8F8A",
+"$ c #8E8F8B",
+"% c #8D908A",
+"& c #8E908B",
+"* c #8F908B",
+"= c #8F908C",
+"- c #8F918C",
+"; c #90908C",
+": c #90938C",
+"> c #90928D",
+", c #90928E",
+"< c #91928E",
+"1 c #90938E",
+"2 c #93938F",
+"3 c #92948F",
+"4 c #93968F",
+"5 c #939590",
+"6 c #949591",
+"7 c #969994",
+"8 c #979994",
+"9 c #B4B5B1",
+"0 c #B6B8B4",
+"q c #B8B9B7",
+"w c #BBBCBB",
+"e c #BCBDBA",
+"r c #BDBEBB",
+"t c #C0C1BE",
+"y c #8AAFD5",
+"u c #8AAFD6",
+"i c #91B3D5",
+"p c #91B3D6",
+"a c #A0BDDA",
+"s c #A1BDDA",
+"d c #A3BFDB",
+"f c #ADC6DE",
+"g c #ACC6DF",
+"h c #AEC6DE",
+"j c #BFD1E2",
+"k c #BFD1E3",
+"l c #BDD0E5",
+"z c #DFDFDE",
+"x c #DFE0DE",
+"c c #DBE2EB",
+"v c #E1E7EC",
+"b c #EEEEEB",
+"n c #EDEDEC",
+"m c #EEEEEC",
+"M c #EFEFED",
+"N c #F1F1F0",
+"B c #F1F1F1",
+"V c #F2F2F0",
+"C c #F2F2F1",
+"Z c #F4F5F4",
+"A c #F5F5F4",
+"S c #F6F6F5",
+"D c #F8F8F6",
+"F c #F8F8F7",
+"G c #FBFBFA",
+"H c #FBFBFB",
+"J c #FCFCFB",
+"K c gray99",
+"L c #FDFDFD",
+"P c #FEFEFD",
+"I c #FEFEFE",
+"U c white",
+"Y c None",
+/* pixels */
+"YYYYYYYYYYYYYYYY",
+"YYYYYYY03XXXX%YY",
+"YYYYYY0rKKKLKKwY",
+"Y+<XXXo69bdgpcK%",
+"YeKKKKKKr0VVhkK<",
+"+KVMpgpvK5AlgAK<",
+"$KZVZChkK<FyFFK3",
+"<KAADkhAK-HJJKK-",
+"<KFHFyFHK<K.KKK+",
+"<KJKHHJKK<KKKKK5",
+"%KKKK KKK+6AKK7Y",
+"YtKKKKKKK5Y<NK-Y",
+"Y%$X5AKK8YYY<z%Y",
+"YYYYY<MK<YYYY;XY",
+"YYYYYY<x%YYYYYYY",
+"YYYYYYY%XYYYYYYY"
+};
diff --git a/mgllab/xpm/hist.xpm b/mgllab/xpm/hist.xpm
new file mode 100644
index 0000000..5c7eb5c
--- /dev/null
+++ b/mgllab/xpm/hist.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * hist_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #0000FF",
+"                ",
+"                ",
+"        ...     ",
+"        ...     ",
+"        ...     ",
+"    ... ...     ",
+"    ... ...     ",
+"    ... ...     ",
+"    ... ...     ",
+"    ... ...     ",
+"    ... ... ... ",
+"    ... ... ... ",
+"... ... ... ... ",
+"... ... ... ... ",
+"... ... ... ... ",
+"                "};
diff --git a/mgllab/xpm/insert.xpm b/mgllab/xpm/insert.xpm
new file mode 100644
index 0000000..e0143f1
--- /dev/null
+++ b/mgllab/xpm/insert.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char * insert_xpm[] = {
+"16 16 4 1",
+" 	c None",
+".	c #0000FF",
+"#	c #000000",
+"w	c #FFFFFF",
+"                ",
+"                ",
+".  ############ ",
+".. #wwwwwwwwww# ",
+"...#w########w# ",
+"....wwwwwwwwww# ",
+".....########w# ",
+"......wwwwwwww# ",
+".......######w# ",
+"........wwwwww# ",
+".......######w# ",
+"......wwwwwwww# ",
+".....########w# ",
+"....wwwwwwwwww# ",
+"...############ ",
+"..              "};
diff --git a/mgllab/xpm/integr.xpm b/mgllab/xpm/integr.xpm
new file mode 100644
index 0000000..ddccb22
--- /dev/null
+++ b/mgllab/xpm/integr.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * integr_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #000000",
+"+	c #808080",
+"                ",
+"                ",
+"                ",
+"     .          ",
+"    .           ",
+"    .    .      ",
+"    .    .      ",
+"    .    .      ",
+"    .  ... . .  ",
+"    . .  .  .   ",
+"    . .  .  .   ",
+"    .  ... . .  ",
+"   .     +      ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/last.xpm b/mgllab/xpm/last.xpm
new file mode 100644
index 0000000..d774d36
--- /dev/null
+++ b/mgllab/xpm/last.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * last_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #0000FF",
+"                ",
+"                ",
+"                ",
+"  .         ..  ",
+"  ...       ..  ",
+"  .....     ..  ",
+"  .......   ..  ",
+"  ......... ..  ",
+"  ............  ",
+"  ............  ",
+"  ......... ..  ",
+"  .......   ..  ",
+"  .....     ..  ",
+"  ...       ..  ",
+"  .         ..  ",
+"                "};
diff --git a/mgllab/xpm/layer-visible-off.xpm b/mgllab/xpm/layer-visible-off.xpm
new file mode 100644
index 0000000..6b2db6f
--- /dev/null
+++ b/mgllab/xpm/layer-visible-off.xpm
@@ -0,0 +1,97 @@
+/* XPM */
+static const char *layer_visible_off_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 75 1 ",
+"  c gray21",
+". c #4B4A4A",
+"X c #555656",
+"o c #656565",
+"O c DimGray",
+"+ c gray43",
+"@ c gray44",
+"# c gray51",
+"$ c #838383",
+"% c #858686",
+"& c #868686",
+"* c #888888",
+"= c #8B8B8B",
+"- c gray56",
+"; c #909090",
+": c gray57",
+"> c #939393",
+", c #959595",
+"< c #989898",
+"1 c gray60",
+"2 c #9A9A9A",
+"3 c #9B9B9B",
+"4 c #9B9C9C",
+"5 c gray61",
+"6 c gray62",
+"7 c #9F9F9F",
+"8 c #9EA0A0",
+"9 c #9FA0A0",
+"0 c gray63",
+"q c #A2A2A2",
+"w c gray64",
+"e c #A4A4A4",
+"r c #A5A5A5",
+"t c #A7A7A7",
+"y c gray66",
+"u c #A9A9A9",
+"i c #ABADAD",
+"p c #ACACAC",
+"a c gray68",
+"s c #AEAEAE",
+"d c #AFAFAF",
+"f c gray69",
+"g c #B1B1B1",
+"h c gray70",
+"j c #B4B4B4",
+"k c gray71",
+"l c #B6B6B6",
+"z c #B7B7B7",
+"x c gray72",
+"c c #B8B9B9",
+"v c #BCBCBC",
+"b c #C1C1C1",
+"n c #C3C3C3",
+"m c #C5C7C7",
+"M c gray78",
+"N c gray79",
+"B c #CBCBCB",
+"V c gray80",
+"C c gray81",
+"Z c #D0D0D0",
+"A c LightGray",
+"S c #D5D5D5",
+"D c gray84",
+"F c #D8D8D8",
+"G c gray85",
+"H c gray86",
+"J c #DDDDDD",
+"K c #E6E6E6",
+"L c gray91",
+"P c #EAEAEA",
+"I c #ECECEC",
+"U c gray93",
+"Y c #F1F1F1",
+"T c gray95",
+"R c None",
+/* pixels */
+"RRRRRRRRRRRRRRRR",
+"RRRRRRRRRRRRRRRR",
+"RRRRjhesjsRRRRRR",
+"RRRq+RRRo,hRRRRR",
+"RR*RRRRRRR+uRRRR",
+"RRRRRRRRRRRR3RRR",
+"RRRRRxvxjRRRRRRR",
+"RRRs3;q6-huRRRRR",
+"RRu*MGSmS*6eRRRR",
+"Re-JBn9&hhZ;eRRR",
+"R3fIM&. 6hLZ-3RR",
+"RRqGBcXOiqYPb;RR",
+"RRReG33#3jUKZ64R",
+"RRRRRs,#sYUGh;RR",
+"RRRRRRRRVj6&RRRR",
+"RRRRRRRRRRRRRRRR"
+};
diff --git a/mgllab/xpm/layer-visible-on.xpm b/mgllab/xpm/layer-visible-on.xpm
new file mode 100644
index 0000000..b35fd8d
--- /dev/null
+++ b/mgllab/xpm/layer-visible-on.xpm
@@ -0,0 +1,118 @@
+/* XPM */
+static const char *layer_visible_on_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 96 2 ",
+"   c #343434",
+".  c #393939",
+"X  c #483A37",
+"o  c #134950",
+"O  c #0E5664",
+"+  c #444444",
+"@  c gray34",
+"#  c #565658",
+"$  c #5B5B5B",
+"%  c gray38",
+"&  c #646464",
+"*  c #656565",
+"=  c #6E6663",
+"-  c #63666C",
+";  c #6A6A6A",
+":  c #6C6C6C",
+">  c #6D6D6C",
+",  c #6D6D6D",
+"<  c #6E6C6C",
+"1  c gray43",
+"2  c #6F6F6F",
+"3  c #606674",
+"4  c #727272",
+"5  c #737272",
+"6  c #767676",
+"7  c #777777",
+"8  c gray47",
+"9  c gray49",
+"0  c #7E7E7E",
+"q  c #387CA9",
+"w  c #3177BD",
+"e  c #415C87",
+"r  c #5A6F90",
+"t  c #5B7896",
+"y  c #767F8F",
+"u  c #587CAE",
+"i  c #7B8586",
+"p  c #4480B1",
+"a  c #7789AB",
+"s  c #7193B6",
+"d  c #3E8FDC",
+"f  c #32A6CE",
+"g  c #72AFD2",
+"h  c #44B1E2",
+"j  c #51B5EC",
+"k  c #808080",
+"l  c #848484",
+"z  c #868585",
+"x  c gray53",
+"c  c #848689",
+"v  c #888888",
+"b  c gray54",
+"n  c #8B8B8B",
+"m  c gray55",
+"M  c #8D8D8D",
+"N  c #8E8E8E",
+"B  c gray56",
+"V  c #808B9D",
+"C  c gray57",
+"Z  c #929292",
+"A  c #959595",
+"S  c gray59",
+"D  c gray60",
+"F  c #9B9B9B",
+"G  c #8892A3",
+"H  c #8E95A2",
+"J  c #A7A7A7",
+"K  c #AAAAAA",
+"L  c #ACB8B6",
+"P  c #AAB4C7",
+"I  c #A0B5D3",
+"U  c #ACBDDA",
+"Y  c #82B6F0",
+"T  c #9CC0F0",
+"R  c #9CD1F5",
+"E  c #ADCCEE",
+"W  c #B1D1F7",
+"Q  c #C0C0C0",
+"!  c #C7C7C5",
+"~  c #C8C7C6",
+"^  c #C3C6CA",
+"/  c #D0CECD",
+"(  c #D0D0D0",
+")  c #D2D2D1",
+"_  c #D2D2D2",
+"`  c #D8D8D8",
+"'  c #DFDFDE",
+"]  c #E2E0E0",
+"[  c #E6E6E6",
+"{  c #EAEAEA",
+"}  c #ECECEC",
+"|  c #EEEEEC",
+" . c #F0EEEE",
+".. c #F4F2F0",
+"X. c #F4F3F1",
+"o. c None",
+/* pixels */
+"o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.",
+"o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.",
+"o.o.o.o.x < @ % 0 B o.o.o.o.o.o.",
+"o.o.o.6 . o.o.o.  $ C o.o.o.o.o.",
+"o.o.* o.o.o.o.o.o.o.+ B o.o.o.o.",
+"o.o.o.o.o.o.o.o.o.o.o.o.v o.o.o.",
+"o.o.o.o.o.5 ; < 6 o.o.o.o.o.o.o.",
+"o.o.o.k @ - V y # < x o.o.o.o.o.",
+"o.o.l & ^ W R E E 3 ; v o.o.o.o.",
+"o.b < ' U g L z g a / 5 Z o.o.o.",
+"o.8 A  .I q = X f s ] ( 0 S o.o.",
+"o.o.5 _ U j o O h t X.{ Q B o.o.",
+"o.o.o.< ~ p d w u H | [ _ D D o.",
+"o.o.o.o.o.v r e a X.| ` J B o.o.",
+"o.o.o.o.o.o.o.o.! K B ; o.o.o.o.",
+"o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o."
+};
diff --git a/mgllab/xpm/left_1.xpm b/mgllab/xpm/left_1.xpm
new file mode 100644
index 0000000..679c3ff
--- /dev/null
+++ b/mgllab/xpm/left_1.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * left_1_xpm[] = {
+"16 16 3 1",
+".	c None",
+"+	c #7F0000",
+"@	c #FF0000",
+"................",
+"................",
+".......+........",
+"......++........",
+".....+ at +........",
+"....+@@+++++++..",
+"...+@@@@@@@@@+..",
+"..+@@@@@@@@@@+..",
+".+@@@@@@@@@@@+..",
+"..+@@@@@@@@@@+..",
+"...+@@@@@@@@@+..",
+"....+@@+++++++..",
+".....+ at +........",
+"......++........",
+".......+........",
+"................"};
diff --git a/mgllab/xpm/light.xpm b/mgllab/xpm/light.xpm
new file mode 100644
index 0000000..e813c61
--- /dev/null
+++ b/mgllab/xpm/light.xpm
@@ -0,0 +1,42 @@
+/* XPM */
+static const char * light_xpm[] = {
+"16 16 23 1",
+" 	c None",
+"!	c #000000",
+"#	c #808080",
+"$	c #808000",
+"%	c #606040",
+"&	c #C0C0C0",
+"'	c #808040",
+"(	c #FFFF00",
+")	c #A0A000",
+"*	c #202000",
+"+	c #404000",
+",	c #C0C000",
+"-	c #E0E000",
+".	c #408040",
+"0	c #008080",
+"1	c #408080",
+"2	c #FFFFC0",
+"3	c #C0C080",
+"4	c #FFFFFF",
+"5	c #FFFF80",
+"6	c #FFFF40",
+"7	c #606000",
+"8	c #206040",
+"     #    #     ",
+"    #$%&&'$#    ",
+"    '()*+,-%    ",
+"    $.0000.+    ",
+" #'+01&223.0+'# ",
+"&$(.1455555..($#",
+" %)0&566((-$0)% ",
+" &*055((((-)0*& ",
+" &+056((((-)0+& ",
+" ',035(((-,70,' ",
+"&$-.8,---,,8.-$#",
+" #%*08$))780*%# ",
+"    $.0000.+    ",
+"    '()*+,-%    ",
+"    #$%&&'$#    ",
+"     #    #     "};
diff --git a/mgllab/xpm/line.xpm b/mgllab/xpm/line.xpm
new file mode 100644
index 0000000..aff1af3
--- /dev/null
+++ b/mgllab/xpm/line.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * line_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"               .",
+"              . ",
+"             .  ",
+"            .   ",
+"           .    ",
+"          .     ",
+"         .      ",
+"        .       ",
+"       .        ",
+"      .         ",
+"     .          ",
+"    .           ",
+"   .            ",
+"  .             ",
+" .              ",
+".               "};
diff --git a/mgllab/xpm/list-add.xpm b/mgllab/xpm/list-add.xpm
new file mode 100644
index 0000000..0620147
--- /dev/null
+++ b/mgllab/xpm/list-add.xpm
@@ -0,0 +1,115 @@
+/* XPM */
+static const char *list_add_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 93 2 ",
+"   c #008200",
+".  c #008300",
+"X  c #008700",
+"o  c #048604",
+"O  c #008B00",
+"+  c #018C00",
+"@  c #048E02",
+"#  c #058F02",
+"$  c #068F04",
+"%  c #079004",
+"&  c #0B9205",
+"*  c #0C9208",
+"=  c #0E9308",
+"-  c #13970A",
+";  c #12960B",
+":  c #17990D",
+">  c #179A0C",
+",  c #1B9C0E",
+"<  c #1C9C0E",
+"1  c #1F9810",
+"2  c #1F9F10",
+"3  c #199914",
+"4  c #1F9319",
+"5  c #209F11",
+"6  c #24A113",
+"7  c #28A415",
+"8  c #2AA419",
+"9  c #2FA819",
+"0  c #30A91B",
+"q  c #37AD1D",
+"w  c #37AD1E",
+"e  c #2AA123",
+"r  c #37AC20",
+"t  c #39AA2C",
+"y  c #3CB023",
+"u  c #3FB126",
+"i  c #33A332",
+"p  c #3BA730",
+"a  c #56AB1D",
+"s  c #40B322",
+"d  c #40B223",
+"f  c #42B326",
+"g  c #43B427",
+"h  c #40B028",
+"j  c #40B128",
+"k  c #43B12E",
+"l  c #45B32D",
+"z  c #49B828",
+"x  c #4FBB2A",
+"c  c #4EB734",
+"v  c #56BD35",
+"b  c #58BE35",
+"n  c #58C031",
+"m  c #46A742",
+"M  c #41A841",
+"N  c #4AAD46",
+"B  c #4FB549",
+"V  c #57BB47",
+"C  c #5ABD47",
+"Z  c #57B848",
+"A  c #5DB553",
+"S  c #5DBC55",
+"D  c #60BD4F",
+"F  c #62BE56",
+"G  c #62B662",
+"H  c #68BA63",
+"J  c #68BD60",
+"K  c #6BBF65",
+"L  c #63C353",
+"P  c #65C454",
+"I  c #6BC352",
+"U  c #67C05E",
+"Y  c #6AC359",
+"T  c #68C25F",
+"R  c #6DC561",
+"E  c #75C864",
+"W  c #7CCD61",
+"Q  c #77CA68",
+"!  c #79CC6B",
+"~  c #7BCD6C",
+"^  c #7CC970",
+"/  c #7ECA74",
+"(  c #83D173",
+")  c #84D174",
+"_  c #91D77C",
+"`  c #92D97E",
+"'  c #9AD686",
+"]  c #9ADB80",
+"[  c #9EDE86",
+"{  c #A1DF8A",
+"}  c #A0D98E",
+"|  c #A1D990",
+" . c None",
+/* pixels */
+" . . . . . . . . . . . . . . . .",
+" . . . . . .^ j g |  . . . . . .",
+" . . . . . .Z } ' I  . . . . . .",
+" . . . . . .6 [ { f  . . . . . .",
+" . . . . . .2 _ ` y  . . . . . .",
+" . . . . . ., ( ) r  . . . . . .",
+" .G M $ * ; : ! ~ 0 w d z W ]  .",
+" .o H J U T R L P E Q / K A n  .",
+" .. m N B S F Z C Y D t e t x  .",
+" . .. X O $ & k c 5 7 9 w s  . .",
+" . . . . . .$ l v <  . . . . . .",
+" . . . . . .@ h b :  . . . . . .",
+" . . . . . .+ 8 h ;  . . . . . .",
+" . . . . . .5 * 4 5  . . . . . .",
+" . . . . . .a * i  . . . . . . .",
+" . . . . . . . . . . . . . . . ."
+};
diff --git a/mgllab/xpm/list-remove.xpm b/mgllab/xpm/list-remove.xpm
new file mode 100644
index 0000000..ed03189
--- /dev/null
+++ b/mgllab/xpm/list-remove.xpm
@@ -0,0 +1,68 @@
+/* XPM */
+static const char *list_remove_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 46 1 ",
+"  c #9B0000",
+". c #9E0000",
+"X c #A50000",
+"o c #A10404",
+"O c #AB0000",
+"+ c #B00000",
+"@ c #B20000",
+"# c #B70000",
+"$ c #B90000",
+"% c #BE0000",
+"& c #BF0000",
+"* c #BE1C1C",
+"= c #BE2222",
+"- c #C40000",
+"; c #C60000",
+": c #CB0000",
+"> c #CD0000",
+", c #D20000",
+"< c #D30000",
+"1 c #D80000",
+"2 c #DA0000",
+"3 c #DF0000",
+"4 c #E50000",
+"5 c #EA0404",
+"6 c #D02828",
+"7 c #BF4141",
+"8 c #C74545",
+"9 c #C84D4D",
+"0 c #DF4949",
+"q c #DE4D4D",
+"w c #C15252",
+"e c #CF5A5A",
+"r c #D25151",
+"t c #D15757",
+"y c #D95050",
+"u c #D75A5A",
+"i c #DC5A5A",
+"p c #EC4141",
+"a c #E14949",
+"s c #E15A5A",
+"d c #E45A5A",
+"f c #C76464",
+"g c #CC6767",
+"h c #E26464",
+"j c #F66262",
+"k c None",
+/* pixels */
+"kkkkkkkkkkkkkkkk",
+"kkkkkkkkkkkkkkkk",
+"kkkkkkkkkkkkkkkk",
+"kkkkkkkkkkkkkkkk",
+"kkkkkkkkkkkkkkkk",
+"kkkkkkkkkkkkkkkk",
+"kkf7+#%-:,13pjkk",
+"kkogeuisddht85kk",
+"kk.w9ryaa06*=4kk",
+"kkk.XO+$-->,1kkk",
+"kkkkkkkkkkkkkkkk",
+"kkkkkkkkkkkkkkkk",
+"kkkkkkkkkkkkkkkk",
+"kkkkkkkkkkkkkkkk",
+"kkkkkkkkkkkkkkkk",
+"kkkkkkkkkkkkkkkk"
+};
diff --git a/mgllab/xpm/mark_.xpm b/mgllab/xpm/mark_.xpm
new file mode 100644
index 0000000..b372f5a
--- /dev/null
+++ b/mgllab/xpm/mark_.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark__xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"       ..       ",
+"       ..       ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/mark_a.xpm b/mgllab/xpm/mark_a.xpm
new file mode 100644
index 0000000..29f34cb
--- /dev/null
+++ b/mgllab/xpm/mark_a.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_a_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"    .       .   ",
+"     .     .    ",
+"      .   .     ",
+"      .   .     ",
+"       . .      ",
+"       ...      ",
+" .............. ",
+"       ...      ",
+"       . .      ",
+"      .   .     ",
+"      .   .     ",
+"     .     .    ",
+"    .       .   ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/mark_cf.xpm b/mgllab/xpm/mark_cf.xpm
new file mode 100644
index 0000000..f743a31
--- /dev/null
+++ b/mgllab/xpm/mark_cf.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_cf_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"     ......     ",
+"   ..      ..   ",
+"  .          .  ",
+" .            . ",
+" .            . ",
+".              .",
+".              .",
+".      ..      .",
+".      ..      .",
+".              .",
+".              .",
+" .            . ",
+" .            . ",
+"  .          .  ",
+"   ..      ..   ",
+"     ......     "};
diff --git a/mgllab/xpm/mark_d.xpm b/mgllab/xpm/mark_d.xpm
new file mode 100644
index 0000000..678d75e
--- /dev/null
+++ b/mgllab/xpm/mark_d.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_d_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"       ..       ",
+"      .  .      ",
+"     .    .     ",
+"    .      .    ",
+"   .        .   ",
+"  .          .  ",
+" .            . ",
+".              .",
+".              .",
+" .            . ",
+"  .          .  ",
+"   .        .   ",
+"    .      .    ",
+"     .    .     ",
+"      .  .      ",
+"       ..       "};
diff --git a/mgllab/xpm/mark_df.xpm b/mgllab/xpm/mark_df.xpm
new file mode 100644
index 0000000..582d420
--- /dev/null
+++ b/mgllab/xpm/mark_df.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_df_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"       ..       ",
+"      ....      ",
+"     ......     ",
+"    ........    ",
+"   ..........   ",
+"  ............  ",
+" .............. ",
+"................",
+"................",
+" .............. ",
+"  ............  ",
+"   ..........   ",
+"    ........    ",
+"     ......     ",
+"      ....      ",
+"       ..       "};
diff --git a/mgllab/xpm/mark_l.xpm b/mgllab/xpm/mark_l.xpm
new file mode 100644
index 0000000..9edd3e0
--- /dev/null
+++ b/mgllab/xpm/mark_l.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_l_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"          ..    ",
+"        .. .    ",
+"       .   .    ",
+"     ..    .    ",
+"    .      .    ",
+"  ..       .    ",
+" .         .    ",
+".          .    ",
+".          .    ",
+" .         .    ",
+"  ..       .    ",
+"    .      .    ",
+"     ..    .    ",
+"       .   .    ",
+"        .. .    ",
+"          ..    "};
diff --git a/mgllab/xpm/mark_lf.xpm b/mgllab/xpm/mark_lf.xpm
new file mode 100644
index 0000000..2585eb4
--- /dev/null
+++ b/mgllab/xpm/mark_lf.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_lf_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"          ..    ",
+"        ....    ",
+"       .....    ",
+"     .......    ",
+"    ........    ",
+"  ..........    ",
+" ...........    ",
+"............    ",
+"............    ",
+" ...........    ",
+"  ..........    ",
+"    ........    ",
+"     .......    ",
+"       .....    ",
+"        ....    ",
+"          ..    "};
diff --git a/mgllab/xpm/mark_n.xpm b/mgllab/xpm/mark_n.xpm
new file mode 100644
index 0000000..efb363e
--- /dev/null
+++ b/mgllab/xpm/mark_n.xpm
@@ -0,0 +1,20 @@
+/* XPM */
+static const char * mark_n_xpm[] = {
+"16 16 1 1",
+" 	c None",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/mark_o.xpm b/mgllab/xpm/mark_o.xpm
new file mode 100644
index 0000000..3154cdc
--- /dev/null
+++ b/mgllab/xpm/mark_o.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_o_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"     ......     ",
+"   ..      ..   ",
+"  .          .  ",
+" .            . ",
+" .            . ",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+" .            . ",
+" .            . ",
+"  .          .  ",
+"   ..      ..   ",
+"     ......     "};
diff --git a/mgllab/xpm/mark_of.xpm b/mgllab/xpm/mark_of.xpm
new file mode 100644
index 0000000..3eeaf38
--- /dev/null
+++ b/mgllab/xpm/mark_of.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_of_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"     ......     ",
+"   ..........   ",
+"  ............  ",
+" .............. ",
+" .............. ",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+" .............. ",
+" .............. ",
+"  ............  ",
+"   ..........   ",
+"     ......     "};
diff --git a/mgllab/xpm/mark_p.xpm b/mgllab/xpm/mark_p.xpm
new file mode 100644
index 0000000..3f40cfb
--- /dev/null
+++ b/mgllab/xpm/mark_p.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_p_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       ",
+"................",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       "};
diff --git a/mgllab/xpm/mark_pf.xpm b/mgllab/xpm/mark_pf.xpm
new file mode 100644
index 0000000..ea9cdac
--- /dev/null
+++ b/mgllab/xpm/mark_pf.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_pf_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"................",
+".       .      .",
+".       .      .",
+".       .      .",
+".       .      .",
+".       .      .",
+".       .      .",
+".       .      .",
+"................",
+".       .      .",
+".       .      .",
+".       .      .",
+".       .      .",
+".       .      .",
+".       .      .",
+"................"};
diff --git a/mgllab/xpm/mark_r.xpm b/mgllab/xpm/mark_r.xpm
new file mode 100644
index 0000000..8459014
--- /dev/null
+++ b/mgllab/xpm/mark_r.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_r_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"    ..          ",
+"    . ..        ",
+"    .   .       ",
+"    .    ..     ",
+"    .      .    ",
+"    .       ..  ",
+"    .         . ",
+"    .          .",
+"    .          .",
+"    .         . ",
+"    .       ..  ",
+"    .      .    ",
+"    .    ..     ",
+"    .   .       ",
+"    . ..        ",
+"    ..          "};
diff --git a/mgllab/xpm/mark_rf.xpm b/mgllab/xpm/mark_rf.xpm
new file mode 100644
index 0000000..cedcd01
--- /dev/null
+++ b/mgllab/xpm/mark_rf.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_rf_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"    ..          ",
+"    ....        ",
+"    .....       ",
+"    .......     ",
+"    ........    ",
+"    ..........  ",
+"    ........... ",
+"    ............",
+"    ............",
+"    ........... ",
+"    ..........  ",
+"    ........    ",
+"    .......     ",
+"    .....       ",
+"    ....        ",
+"    ..          "};
diff --git a/mgllab/xpm/mark_s.xpm b/mgllab/xpm/mark_s.xpm
new file mode 100644
index 0000000..1a4c012
--- /dev/null
+++ b/mgllab/xpm/mark_s.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_s_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"................",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+".              .",
+"................"};
diff --git a/mgllab/xpm/mark_sf.xpm b/mgllab/xpm/mark_sf.xpm
new file mode 100644
index 0000000..5a89f1d
--- /dev/null
+++ b/mgllab/xpm/mark_sf.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_sf_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................"};
diff --git a/mgllab/xpm/mark_t.xpm b/mgllab/xpm/mark_t.xpm
new file mode 100644
index 0000000..1e6b398
--- /dev/null
+++ b/mgllab/xpm/mark_t.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_t_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"       ..       ",
+"      .  .      ",
+"     .    .     ",
+"     .    .     ",
+"    .      .    ",
+"   .        .   ",
+"   .        .   ",
+"  .          .  ",
+" .            . ",
+" .            . ",
+".              .",
+"................",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/mark_tf.xpm b/mgllab/xpm/mark_tf.xpm
new file mode 100644
index 0000000..48f61c1
--- /dev/null
+++ b/mgllab/xpm/mark_tf.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_tf_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"       ..       ",
+"      ....      ",
+"     ......     ",
+"     ......     ",
+"    ........    ",
+"   ..........   ",
+"   ..........   ",
+"  ............  ",
+" .............. ",
+" .............. ",
+"................",
+"................",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/mark_v.xpm b/mgllab/xpm/mark_v.xpm
new file mode 100644
index 0000000..9f03771
--- /dev/null
+++ b/mgllab/xpm/mark_v.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_v_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"................",
+".              .",
+" .            . ",
+" .            . ",
+"  .          .  ",
+"   .        .   ",
+"   .        .   ",
+"    .      .    ",
+"     .    .     ",
+"     .    .     ",
+"      .  .      ",
+"       ..       "};
diff --git a/mgllab/xpm/mark_vf.xpm b/mgllab/xpm/mark_vf.xpm
new file mode 100644
index 0000000..39d7e99
--- /dev/null
+++ b/mgllab/xpm/mark_vf.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_vf_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"................",
+"................",
+" .............. ",
+" .............. ",
+"  ............  ",
+"   ..........   ",
+"   ..........   ",
+"    ........    ",
+"     ......     ",
+"     ......     ",
+"      ....      ",
+"       ..       "};
diff --git a/mgllab/xpm/mark_x.xpm b/mgllab/xpm/mark_x.xpm
new file mode 100644
index 0000000..8d7ee78
--- /dev/null
+++ b/mgllab/xpm/mark_x.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_x_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+".              .",
+" .            . ",
+"  .          .  ",
+"   .        .   ",
+"    .      .    ",
+"     .    .     ",
+"      .  .      ",
+"       ..       ",
+"       ..       ",
+"      .  .      ",
+"     .    .     ",
+"    .      .    ",
+"   .        .   ",
+"  .          .  ",
+" .            . ",
+".              ."};
diff --git a/mgllab/xpm/mark_y.xpm b/mgllab/xpm/mark_y.xpm
new file mode 100644
index 0000000..b5135fd
--- /dev/null
+++ b/mgllab/xpm/mark_y.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * mark_y_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"   .         .  ",
+"    .       .   ",
+"     .     .    ",
+"      .   .     ",
+"       ...      ",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       ",
+"        .       ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/mask_a.xpm b/mgllab/xpm/mask_a.xpm
new file mode 100644
index 0000000..6949dd9
--- /dev/null
+++ b/mgllab/xpm/mask_a.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_a_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"##............##",
+"##............##",
+"..##........##..",
+"..##........##..",
+"....##....##....",
+"....##....##....",
+"......####......",
+"......####......",
+"......####......",
+"......####......",
+"....##....##....",
+"....##....##....",
+"..##........##..",
+"..##........##..",
+"##............##",
+"##............##"};
diff --git a/mgllab/xpm/mask_d.xpm b/mgllab/xpm/mask_d.xpm
new file mode 100644
index 0000000..dc7f66d
--- /dev/null
+++ b/mgllab/xpm/mask_d.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_d_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"........##......",
+"........##......",
+"......##..##....",
+"......##..##....",
+"....##......##..",
+"....##......##..",
+"......##..##....",
+"......##..##....",
+"........##......",
+"........##......",
+"................",
+"................",
+"................",
+"................"};
diff --git a/mgllab/xpm/mask_d_.xpm b/mgllab/xpm/mask_d_.xpm
new file mode 100644
index 0000000..d3eee46
--- /dev/null
+++ b/mgllab/xpm/mask_d_.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_D_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"........##......",
+"........##......",
+"......######....",
+"......######....",
+"....##########..",
+"....##########..",
+"......######....",
+"......######....",
+"........##......",
+"........##......",
+"................",
+"................",
+"................",
+"................"};
diff --git a/mgllab/xpm/mask_e.xpm b/mgllab/xpm/mask_e.xpm
new file mode 100644
index 0000000..2e6b528
--- /dev/null
+++ b/mgllab/xpm/mask_e.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_e_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"................",
+"................",
+"################",
+"################",
+"................",
+"................",
+"################",
+"################",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................"};
diff --git a/mgllab/xpm/mask_i.xpm b/mgllab/xpm/mask_i.xpm
new file mode 100644
index 0000000..a24c1ca
--- /dev/null
+++ b/mgllab/xpm/mask_i.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_i_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"..######..######",
+"..######..######",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................"};
diff --git a/mgllab/xpm/mask_j.xpm b/mgllab/xpm/mask_j.xpm
new file mode 100644
index 0000000..fcc072f
--- /dev/null
+++ b/mgllab/xpm/mask_j.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_j_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"..##..##########",
+"..##..##########",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................"};
diff --git a/mgllab/xpm/mask_l.xpm b/mgllab/xpm/mask_l.xpm
new file mode 100644
index 0000000..a062db6
--- /dev/null
+++ b/mgllab/xpm/mask_l.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_l_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"..........####..",
+"..........####..",
+"......####..##..",
+"......####..##..",
+"..####......##..",
+"..####......##..",
+"......####..##..",
+"......####..##..",
+"..........####..",
+"..........####..",
+"................",
+"................",
+"................",
+"................"};
diff --git a/mgllab/xpm/mask_m.xpm b/mgllab/xpm/mask_m.xpm
new file mode 100644
index 0000000..e717d96
--- /dev/null
+++ b/mgllab/xpm/mask_m.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_m_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"################",
+"################",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................"};
diff --git a/mgllab/xpm/mask_o.xpm b/mgllab/xpm/mask_o.xpm
new file mode 100644
index 0000000..3664bc4
--- /dev/null
+++ b/mgllab/xpm/mask_o.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_o_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"................",
+"................",
+"......####......",
+"......####......",
+"....##....##....",
+"....##....##....",
+"....##....##....",
+"....##....##....",
+"......####......",
+"......####......",
+"................",
+"................",
+"................",
+"................"};
diff --git a/mgllab/xpm/mask_o_.xpm b/mgllab/xpm/mask_o_.xpm
new file mode 100644
index 0000000..fbecff8
--- /dev/null
+++ b/mgllab/xpm/mask_o_.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_O_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"................",
+"................",
+"......####......",
+"......####......",
+"....########....",
+"....########....",
+"....########....",
+"....########....",
+"......####......",
+"......####......",
+"................",
+"................",
+"................",
+"................"};
diff --git a/mgllab/xpm/mask_p.xpm b/mgllab/xpm/mask_p.xpm
new file mode 100644
index 0000000..d29f774
--- /dev/null
+++ b/mgllab/xpm/mask_p.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_p_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"........##......",
+"........##......",
+"........##......",
+"........##......",
+"........##......",
+"........##......",
+"################",
+"################",
+"........##......",
+"........##......",
+"........##......",
+"........##......",
+"........##......",
+"........##......",
+"........##......",
+"........##......"};
diff --git a/mgllab/xpm/mask_r.xpm b/mgllab/xpm/mask_r.xpm
new file mode 100644
index 0000000..47f2aa5
--- /dev/null
+++ b/mgllab/xpm/mask_r.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_r_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"..####..........",
+"..####..........",
+"..##..####......",
+"..##..####......",
+"..##......####..",
+"..##......####..",
+"..##..####......",
+"..##..####......",
+"..####..........",
+"..####..........",
+"................",
+"................",
+"................",
+"................"};
diff --git a/mgllab/xpm/mask_s.xpm b/mgllab/xpm/mask_s.xpm
new file mode 100644
index 0000000..a5e1e82
--- /dev/null
+++ b/mgllab/xpm/mask_s.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_s_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"................",
+"................",
+"....########....",
+"....########....",
+"....##....##....",
+"....##....##....",
+"....##....##....",
+"....##....##....",
+"....########....",
+"....########....",
+"................",
+"................",
+"................",
+"................"};
diff --git a/mgllab/xpm/mask_s_.xpm b/mgllab/xpm/mask_s_.xpm
new file mode 100644
index 0000000..652db36
--- /dev/null
+++ b/mgllab/xpm/mask_s_.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_S_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"................",
+"................",
+"....########....",
+"....########....",
+"....########....",
+"....########....",
+"....########....",
+"....########....",
+"....########....",
+"....########....",
+"................",
+"................",
+"................",
+"................"};
diff --git a/mgllab/xpm/mask_t.xpm b/mgllab/xpm/mask_t.xpm
new file mode 100644
index 0000000..d153fc8
--- /dev/null
+++ b/mgllab/xpm/mask_t.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_t_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"................",
+"................",
+"..####..........",
+"..####..........",
+"##....##........",
+"##....##........",
+"........##....##",
+"........##....##",
+"..........####..",
+"..........####..",
+"................",
+"................",
+"................",
+"................"};
diff --git a/mgllab/xpm/mask_u.xpm b/mgllab/xpm/mask_u.xpm
new file mode 100644
index 0000000..61996fc
--- /dev/null
+++ b/mgllab/xpm/mask_u.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *mask_u_xpm[]={
+"16 16 2 1",
+". c None",
+"# c #000000",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"......####......",
+"......####......",
+"....##....##....",
+"....##....##....",
+"..##........##..",
+"..##........##..",
+"................",
+"................",
+"................",
+"................"};
diff --git a/mgllab/xpm/media-playback-start.xpm b/mgllab/xpm/media-playback-start.xpm
new file mode 100644
index 0000000..0818c88
--- /dev/null
+++ b/mgllab/xpm/media-playback-start.xpm
@@ -0,0 +1,108 @@
+/* XPM */
+static const char *media_playback_start_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 86 1 ",
+"  c #070707",
+". c gray9",
+"X c #181818",
+"o c gray13",
+"O c #252525",
+"+ c gray21",
+"@ c gray23",
+"# c gray25",
+"$ c #484848",
+"% c gray29",
+"& c gray31",
+"* c #505050",
+"= c #515151",
+"- c gray32",
+"; c #535353",
+": c gray33",
+"> c #555555",
+", c #565656",
+"< c #585858",
+"1 c #5B5B5B",
+"2 c #5D5D5D",
+"3 c gray37",
+"4 c #5F5F5F",
+"5 c #606060",
+"6 c gray38",
+"7 c #646464",
+"8 c #656565",
+"9 c gray40",
+"0 c #676767",
+"q c #686868",
+"w c #6A6A6A",
+"e c gray42",
+"r c #6C6C6C",
+"t c #6F6F6F",
+"y c #727272",
+"u c gray45",
+"i c #747474",
+"p c #767676",
+"a c #777777",
+"s c gray47",
+"d c #797979",
+"f c #7B7B7B",
+"g c #7C7C7C",
+"h c gray49",
+"j c gray50",
+"k c #818181",
+"l c #838383",
+"z c #868686",
+"x c #8D8D8D",
+"c c #8E8E8E",
+"v c gray56",
+"b c gray58",
+"n c #9A9A9A",
+"m c #B2B2B2",
+"M c gray72",
+"N c gray73",
+"B c #BBBBBB",
+"V c gray",
+"C c #CBCBCB",
+"Z c gray80",
+"A c #CECECE",
+"S c gray81",
+"D c #D0D0D0",
+"F c LightGray",
+"G c gray83",
+"H c #D5D5D5",
+"J c gray85",
+"K c gray86",
+"L c #DDDDDD",
+"P c #E2E2E2",
+"I c gray91",
+"U c #E9E9E9",
+"Y c #EAEAEA",
+"T c #ECECEC",
+"R c gray93",
+"E c #EFEFEF",
+"W c gray94",
+"Q c #F1F1F1",
+"! c gray95",
+"~ c #F3F3F3",
+"^ c #F6F6F6",
+"/ c gray98",
+"( c gray99",
+") c #FDFDFD",
+"_ c white",
+"` c None",
+/* pixels */
+"`````lljjll`````",
+"````duujjuud````",
+"``dtaNDJJHNdtd``",
+"``ecHUR^WWULce``",
+"`tuHR^mW))/WPae`",
+"e4VR^)czD)))WD5e",
+"77SW))j7<bW)/Ue5",
+"4uDW/)7;#@4C)Rj5",
+"4uHW))+. O>S)Wj4",
+"<5DR))@oXuW)/R7<",
+"4;MU/)%%N)))/J><",
+"`>eLW)bW))))Wa>`",
+"``;lPW))))/Rn&``",
+"``>&7SURWRLu;>``",
+"````;&4ad4&;````",
+"`````;;&;;>`````"
+};
diff --git a/mgllab/xpm/media-seek-backward.xpm b/mgllab/xpm/media-seek-backward.xpm
new file mode 100644
index 0000000..3ee8ae8
--- /dev/null
+++ b/mgllab/xpm/media-seek-backward.xpm
@@ -0,0 +1,112 @@
+/* XPM */
+static const char *media_seek_backward_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 90 1 ",
+"  c #070707",
+". c gray3",
+"X c #191919",
+"o c gray13",
+"O c #252525",
+"+ c #2C2C2C",
+"@ c gray18",
+"# c gray20",
+"$ c #444444",
+"% c #4C4C4C",
+"& c gray31",
+"* c #505050",
+"= c #515151",
+"- c gray32",
+"; c #535353",
+": c gray33",
+"> c #555555",
+", c #565656",
+"< c #5B5B5B",
+"1 c #5D5D5D",
+"2 c #5F5F5F",
+"3 c #606060",
+"4 c gray38",
+"5 c gray39",
+"6 c #646464",
+"7 c #656565",
+"8 c gray40",
+"9 c #676767",
+"0 c #686868",
+"q c #6A6A6A",
+"w c gray42",
+"e c #6C6C6C",
+"r c #6F6F6F",
+"t c #727272",
+"y c gray45",
+"u c #747474",
+"i c #767676",
+"p c #777777",
+"a c gray47",
+"s c #797979",
+"d c #7B7B7B",
+"f c #7C7C7C",
+"g c gray50",
+"h c #818181",
+"j c #838383",
+"k c #868686",
+"l c #8D8D8D",
+"z c #8E8E8E",
+"x c #9A9A9A",
+"c c #9F9F9F",
+"v c #A2A2A2",
+"b c #A5A5A5",
+"n c gray65",
+"m c #AAAAAA",
+"M c #B1B1B1",
+"N c #B2B2B2",
+"B c #B6B6B6",
+"V c gray72",
+"C c gray73",
+"Z c #BCBCBC",
+"A c gray74",
+"S c gray",
+"D c gray76",
+"F c #C3C3C3",
+"G c #CACACA",
+"H c #CECECE",
+"J c #D0D0D0",
+"K c LightGray",
+"L c gray83",
+"P c #D5D5D5",
+"I c gray85",
+"U c gray86",
+"Y c #DDDDDD",
+"T c #E2E2E2",
+"R c gray91",
+"E c #E9E9E9",
+"W c #EAEAEA",
+"Q c #ECECEC",
+"! c gray93",
+"~ c #EFEFEF",
+"^ c #F1F1F1",
+"/ c gray95",
+"( c #F3F3F3",
+") c #F6F6F6",
+"_ c gray98",
+"` c #FBFBFB",
+"' c gray99",
+"] c #FDFDFD",
+"[ c white",
+"{ c None",
+/* pixels */
+"{{{{{jjggjj{{{{{",
+"{{{{syyggyys{{{{",
+"{{srsCJIIPCirs{{",
+"{{wzJR^^^^WYzw{{",
+"{ryPQ)`D]]`^Tiw{",
+"w2SQ)]Ds]]B]^H5w",
+"66H^]Gi5]S:]`W66",
+"2yJ^Ss<%S2@]`^s5",
+"2yP^M*O.M$.]]^g<",
+"<5JQ]m at X]bo]]^6<",
+"<*CW`]v#]]b]`I:<",
+"{:6Y^]]b]]]]^y:{",
+"{{*kT^`]]]`^x*{{",
+"{{:*wJWQ^QIi*:{{",
+"{{{{**2is5**{{{{",
+"{{{{{:****:{{{{{"
+};
diff --git a/mgllab/xpm/media-seek-forward.xpm b/mgllab/xpm/media-seek-forward.xpm
new file mode 100644
index 0000000..c9cc329
--- /dev/null
+++ b/mgllab/xpm/media-seek-forward.xpm
@@ -0,0 +1,109 @@
+/* XPM */
+static const char *media_seek_forward_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 87 1 ",
+"  c #070707",
+". c gray3",
+"X c #191919",
+"o c #252525",
+"O c #313131",
+"+ c gray21",
+"@ c gray23",
+"# c #3F3F3F",
+"$ c gray29",
+"% c #4E4E4E",
+"& c gray31",
+"* c #505050",
+"= c #515151",
+"- c gray32",
+"; c gray33",
+": c #555555",
+"> c #565656",
+", c #5A5A5A",
+"< c #5B5B5B",
+"1 c #5D5D5D",
+"2 c #5F5F5F",
+"3 c #606060",
+"4 c gray38",
+"5 c #646464",
+"6 c #656565",
+"7 c gray40",
+"8 c #676767",
+"9 c #686868",
+"0 c #6A6A6A",
+"q c gray42",
+"w c #6C6C6C",
+"e c #6F6F6F",
+"r c #727272",
+"t c gray45",
+"y c #747474",
+"u c #767676",
+"i c #777777",
+"p c gray47",
+"a c #797979",
+"s c #7B7B7B",
+"d c #7C7C7C",
+"f c gray50",
+"g c #818181",
+"h c #838383",
+"j c #868686",
+"k c #8D8D8D",
+"l c #8E8E8E",
+"z c #909090",
+"x c #959595",
+"c c gray60",
+"v c #9A9A9A",
+"b c gray63",
+"n c gray65",
+"m c #A9A9A9",
+"M c gray67",
+"N c #AEAEAE",
+"B c #B2B2B2",
+"V c gray72",
+"C c gray73",
+"Z c gray74",
+"A c gray",
+"S c #CACACA",
+"D c #CECECE",
+"F c #D0D0D0",
+"G c LightGray",
+"H c gray83",
+"J c #D5D5D5",
+"K c gray85",
+"L c gray86",
+"P c #DDDDDD",
+"I c #E2E2E2",
+"U c gray91",
+"Y c #E9E9E9",
+"T c #EAEAEA",
+"R c #ECECEC",
+"E c gray93",
+"W c #EFEFEF",
+"Q c #F1F1F1",
+"! c gray95",
+"~ c #F3F3F3",
+"^ c #F6F6F6",
+"/ c gray98",
+"( c #FBFBFB",
+") c gray99",
+"_ c #FDFDFD",
+"` c white",
+"' c None",
+/* pixels */
+"'''''hhffhh'''''",
+"''''attfftta''''",
+"''aeiVFLLJViea''",
+"''qlJTRQQQTPlq''",
+"'etJR^__A_/QIiq'",
+"q2AR^S__aB__QD3q",
+"55DQ_lA_q%n_/Tq3",
+"2tFQ_q;V,O+M_Rf3",
+"2tJQ/O.b+.oM_Qf2",
+",3FQ_$z_ at Xx__R5,",
+",;VT/M__$v__/L;,",
+"';5PQ/__N___Qi;'",
+"''*jIQ/___/Qv*''",
+"'';%qFTRQRLi%;''",
+"''''**2aa2%*''''",
+"''''';****;'''''"
+};
diff --git a/mgllab/xpm/next.xpm b/mgllab/xpm/next.xpm
new file mode 100644
index 0000000..606c733
--- /dev/null
+++ b/mgllab/xpm/next.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * next_xpm[] = {
+"16 16 2 1",
+" 	c #E7E7E7",
+".	c #0000FF",
+"                ",
+"                ",
+"                ",
+"  .             ",
+"  ...           ",
+"  .....         ",
+"  .......       ",
+"  .........     ",
+"  ...........   ",
+"  ...........   ",
+"  .........     ",
+"  .......       ",
+"  .....         ",
+"  ...           ",
+"  .             ",
+"                "};
diff --git a/mgllab/xpm/next_sl.xpm b/mgllab/xpm/next_sl.xpm
new file mode 100644
index 0000000..da4f178
--- /dev/null
+++ b/mgllab/xpm/next_sl.xpm
@@ -0,0 +1,24 @@
+/* XPM */
+static const char * next_sl_xpm[] = {
+"16 16 5 1",
+" 	c None",
+".	c #00007F",
+"+	c #007FFF",
+"@	c #0000FF",
+"#	c #003F80",
+"                ",
+"      ..        ",
+"      .+.       ",
+"      .++.      ",
+"     .++ at +.     ",
+" ....++ at +@+.    ",
+" . at +@+ at +@+ at +.   ",
+" .@@@@@@@@+ at +.  ",
+" .@@@@@@@@@@@@. ",
+" .@@@@@@@@#@#.  ",
+" .@#@#@#@#@#.   ",
+" ....@#@#@#.    ",
+"     .@#@#.     ",
+"      .##.      ",
+"      .#.       ",
+"      ..        "};
diff --git a/mgllab/xpm/none.xpm b/mgllab/xpm/none.xpm
new file mode 100644
index 0000000..e81575f
--- /dev/null
+++ b/mgllab/xpm/none.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * none_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"................",
+"..            ..",
+". .          . .",
+".  .        .  .",
+".   .      .   .",
+".    .    .    .",
+".     .  .     .",
+".      ..      .",
+".      ..      .",
+".     .  .     .",
+".    .    .    .",
+".   .      .   .",
+".  .        .  .",
+". .          . .",
+"..            ..",
+"................"};
diff --git a/mgllab/xpm/norm_1.xpm b/mgllab/xpm/norm_1.xpm
new file mode 100644
index 0000000..a433a58
--- /dev/null
+++ b/mgllab/xpm/norm_1.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * norm_1_xpm[] = {
+"16 16 3 1",
+".	c None",
+"+	c #7F0000",
+"@	c #FF0000",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+".++++++++++++++.",
+".+@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@+.",
+".++++++++++++++.",
+"................",
+"................",
+"................",
+"................",
+"................"};
diff --git a/mgllab/xpm/object-group.xpm b/mgllab/xpm/object-group.xpm
new file mode 100644
index 0000000..8b37492
--- /dev/null
+++ b/mgllab/xpm/object-group.xpm
@@ -0,0 +1,46 @@
+/* XPM */
+static const char *object_group_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 24 1 ",
+"  c #75777E",
+". c #78787B",
+"X c #1867ED",
+"o c #1867EE",
+"O c #86868A",
+"+ c #949499",
+"@ c #A1A1A6",
+"# c #ACACB1",
+"$ c #B3B5BD",
+"% c #B7B7BC",
+"& c #B8B8BD",
+"* c gray90",
+"= c #E7E7E7",
+"- c gray91",
+"; c #ECECEC",
+": c gray93",
+"> c #EEEEEE",
+", c #EFEFEF",
+"< c #F3F3F3",
+"1 c #F6F6F6",
+"2 c #FBFBFB",
+"3 c #FEFEFE",
+"4 c white",
+"5 c None",
+/* pixels */
+"5555555555555555",
+"5555555555555555",
+"555Xooooo5555555",
+"55X$#@+O o555555",
+"55o%*-><.oo55555",
+"55X%2%#@+O o5555",
+"55X%4%**><.oo555",
+"55X%4%2&#@+O o55",
+"55X$#%4%**><.X55",
+"555XX%4%2,>>.X55",
+"5555X$#%44<-.X55",
+"55555Xo%4444.X55",
+"555555X$#@+O X55",
+"5555555XoooXX555",
+"5555555555555555",
+"5555555555555555"
+};
diff --git a/mgllab/xpm/object-order-lower.xpm b/mgllab/xpm/object-order-lower.xpm
new file mode 100644
index 0000000..6aa2a11
--- /dev/null
+++ b/mgllab/xpm/object-order-lower.xpm
@@ -0,0 +1,101 @@
+/* XPM */
+static const char *object_order_lower_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 79 1 ",
+"  c #757578",
+". c #747479",
+"X c #7C7C7F",
+"o c #7D7D82",
+"O c #7A869A",
+"+ c #7B869A",
+"@ c #7E8999",
+"# c #7D8BA4",
+"$ c #86868A",
+"% c #8F8F93",
+"& c #838C99",
+"* c #97979C",
+"= c #818CA1",
+"- c #8692A7",
+"; c #8C98AE",
+": c #9F9FA4",
+"> c #919EB5",
+", c #A0A0A6",
+"< c #A6A6AA",
+"1 c #A7A7AC",
+"2 c #AAAAAF",
+"3 c #ACACB2",
+"4 c #B3B3B8",
+"5 c #B4B4BA",
+"6 c #BABABE",
+"7 c #BEBEC2",
+"8 c #80B3FF",
+"9 c #81B3FF",
+"0 c #81B4FF",
+"q c #83B4FF",
+"w c #84B5FF",
+"e c #85B6FF",
+"r c #86B6FF",
+"t c #88B7FF",
+"y c #89B8FF",
+"u c #8AB9FE",
+"i c #8AB8FF",
+"p c #8DBAFE",
+"a c #8DBBFE",
+"s c #92BEFE",
+"d c #96BFFE",
+"f c #9CC3FD",
+"g c #9EC5FD",
+"h c #A5C9FD",
+"j c #A7CBFC",
+"k c #ADCDFA",
+"l c #A9CBFC",
+"z c #AACCFC",
+"x c #ABCDFC",
+"c c #ACCDFC",
+"v c #ACCEFC",
+"b c #ADCEFC",
+"n c #C8C8CC",
+"m c #C8C8CD",
+"M c gray90",
+"N c #E6E6E6",
+"B c #E7E7E7",
+"V c gray91",
+"C c #E9E9E9",
+"Z c #EAEAEA",
+"A c gray92",
+"S c #ECECEC",
+"D c gray93",
+"F c #EEEEEE",
+"G c #EFEFEF",
+"H c gray94",
+"J c #F1F1F1",
+"K c gray95",
+"L c #F3F3F3",
+"P c gray96",
+"I c #F6F6F6",
+"U c gray97",
+"Y c #F9F9F9",
+"T c gray98",
+"R c gray99",
+"E c #FDFDFD",
+"W c #FEFEFE",
+"Q c white",
+"! c None",
+/* pixels */
+"!!!!!!!!!!!!!!!!",
+"!643<:*%$o !!!!!",
+"!6MMVVVVFK !!!!!",
+"!6FVMMFKPP !!!!!",
+"!6YKFVFFKK !!!!!",
+"!6QQPKFVFVX%$o !",
+"!6QQQYPKMM&vgu !",
+"!6QQQQQPKV at t88 !",
+"!6QQQQQQQL+www !",
+"!6QQQQQQQQ+tpz !",
+"!643<1>;-=#dlv !",
+"!!!!!m8qwtfzvv !",
+"!!!!!m88sjxvvv !",
+"!!!!!mpjvvvvvk !",
+"!!!!!m753:*%$o !",
+"!!!!!!!!!!!!!!!!"
+};
diff --git a/mgllab/xpm/object-order-raise.xpm b/mgllab/xpm/object-order-raise.xpm
new file mode 100644
index 0000000..638d527
--- /dev/null
+++ b/mgllab/xpm/object-order-raise.xpm
@@ -0,0 +1,102 @@
+/* XPM */
+static const char *object_order_raise_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 80 1 ",
+"  c #757578",
+". c #747479",
+"X c #7D7D82",
+"o c #86868A",
+"O c #8F8F93",
+"+ c #909095",
+"@ c #97979C",
+"# c #9F9FA4",
+"$ c #A0A0A6",
+"% c #A6A6AA",
+"& c #AAAAAF",
+"* c #ACACB2",
+"= c #B2B2B6",
+"- c #B3B3B8",
+"; c #B4B4BA",
+": c #BABABE",
+"> c #BEBEC2",
+", c #80B3FF",
+"< c #81B3FF",
+"1 c #81B4FF",
+"2 c #83B4FF",
+"3 c #83B5FF",
+"4 c #84B5FF",
+"5 c #85B6FF",
+"6 c #86B6FF",
+"7 c #87B7FF",
+"8 c #88B7FF",
+"9 c #89B8FF",
+"0 c #8AB9FE",
+"q c #8BB9FE",
+"w c #8AB8FF",
+"e c #8BB9FF",
+"r c #8DBAFE",
+"t c #8DBBFE",
+"y c #8FBCFF",
+"u c #92BEFE",
+"i c #96BFFE",
+"p c #95C0FE",
+"a c #99C2FD",
+"s c #9CC3FD",
+"d c #9EC5FD",
+"f c #A5C9FD",
+"g c #A7CBFC",
+"h c #ADCDFA",
+"j c #AECEFB",
+"k c #A9CBFC",
+"l c #AACCFC",
+"z c #ABCDFC",
+"x c #ACCDFC",
+"c c #ACCEFC",
+"v c #ADCEFC",
+"b c #C0C0C4",
+"n c #C2C2C6",
+"m c #C8C8CC",
+"M c #C9C9CC",
+"N c #C8C8CD",
+"B c #D5D5D8",
+"V c #D6D6D9",
+"C c gray90",
+"Z c #E6E6E6",
+"A c #E7E7E7",
+"S c gray91",
+"D c #E9E9E9",
+"F c #EAEAEA",
+"G c gray92",
+"H c #ECECEC",
+"J c gray93",
+"K c #EEEEEE",
+"L c #EFEFEF",
+"P c gray94",
+"I c #F1F1F1",
+"U c gray95",
+"Y c #F3F3F3",
+"T c gray96",
+"R c #F6F6F6",
+"E c #F9F9F9",
+"W c #FDFDFD",
+"Q c #FEFEFE",
+"! c white",
+"~ c None",
+/* pixels */
+"~~~~~~~~~~~~~~~~",
+"~:-*%#@OoX ~~~~~",
+"~:CCASSGLU ~~~~~",
+"~:KSCAJLYR ~~~~~",
+"~:EUKSJLUU ~~~~~",
+"~:!!RBNn:=+OoX ~",
+"~:!!!Bjjjzjjd0 ~",
+"~:!!!Bjjzfa8,, ~",
+"~:!!!Bir668666 ~",
+"~:!!!B,,6008rf ~",
+"~:-*%b,660yikz ~",
+"~~~~~N1160szzj ~",
+"~~~~~N,1ugzzzj ~",
+"~~~~~Nrfjzzjjh ~",
+"~~~~~N>;*$@OoX ~",
+"~~~~~~~~~~~~~~~~"
+};
diff --git a/mgllab/xpm/object-rotate-down.xpm b/mgllab/xpm/object-rotate-down.xpm
new file mode 100644
index 0000000..49352ea
--- /dev/null
+++ b/mgllab/xpm/object-rotate-down.xpm
@@ -0,0 +1,105 @@
+/* XPM */
+static const char *object_rotate_down_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 83 1 ",
+"  c #210F57",
+". c #221057",
+"X c #24105E",
+"o c #331A73",
+"O c #3E2770",
+"+ c #3F2878",
+"@ c #432B79",
+"# c #3E2280",
+"$ c #482D81",
+"% c #4A2F84",
+"& c #422588",
+"* c #4E318C",
+"= c #4E318D",
+"- c #573B97",
+"; c #52329E",
+": c #573B98",
+"> c #5A389F",
+", c #5432A2",
+"< c #5835A7",
+"1 c #5B38A4",
+"2 c #5F3CAD",
+"3 c #5E3AB1",
+"4 c #603BB3",
+"5 c #653FB7",
+"6 c #633DB8",
+"7 c #673FBC",
+"8 c #56408A",
+"9 c #584288",
+"0 c #594094",
+"q c #5A4094",
+"w c #5B4297",
+"e c #6E589D",
+"r c #6247A0",
+"t c #755DA7",
+"y c #755EA9",
+"u c #6C4ABA",
+"i c #6E4DBA",
+"p c #755AB0",
+"a c #785BB9",
+"s c #7C65AB",
+"d c #6941C0",
+"f c #6C44C4",
+"g c #6C44C5",
+"h c #734EC1",
+"j c #826DB0",
+"k c #836EB3",
+"l c #846DB4",
+"z c #8970BF",
+"x c #8F79BD",
+"c c #907CB8",
+"v c #917CBD",
+"b c #9382B5",
+"n c #9584BA",
+"m c #9784BC",
+"M c #9685BD",
+"N c #9884BB",
+"B c #9987BF",
+"V c #998AB8",
+"C c #9A88BF",
+"Z c #9986C0",
+"A c #9F8FC2",
+"S c #A190C6",
+"D c #AA9AC9",
+"F c #AD9DCA",
+"G c #AA9BCD",
+"H c #AEA0CD",
+"J c #B7AAD1",
+"K c #B9ACD1",
+"L c #BBAFD3",
+"P c #BCAFD7",
+"I c #BCB1D4",
+"U c #BFB1D6",
+"Y c #BFB4D6",
+"T c #C5BBDA",
+"R c #C6BCDA",
+"E c #C8BFDC",
+"W c #C9C0DC",
+"Q c #CFC7E0",
+"! c #D0C4E2",
+"~ c #D0C8E1",
+"^ c #D2CAE2",
+"/ c #DCD6E8",
+"( c None",
+/* pixels */
+"((((((((((((((((",
+"((((((((((((((((",
+"(((((>125(((((((",
+"(((*wtsjZa6(((((",
+"(($eCmcAJUx3((((",
+"(%9FDl-wmYRp((((",
+"(@bUv&((onEH<(((",
+"(OK!r((.X8WR,4g(",
+"(OK!r(( VTE~/Pg(",
+"(@bUv&((+IEQ~i((",
+"(%9FGk:(+yTQzd((",
+"(($eZN(((,AGu(((",
+"(((*w(((((uh((((",
+"((((((((((((((((",
+"((((((((((((((((",
+"(((((((((((((((("
+};
diff --git a/mgllab/xpm/object-rotate-left.xpm b/mgllab/xpm/object-rotate-left.xpm
new file mode 100644
index 0000000..1465832
--- /dev/null
+++ b/mgllab/xpm/object-rotate-left.xpm
@@ -0,0 +1,104 @@
+/* XPM */
+static const char *object_rotate_left_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 82 1 ",
+"  c #220F57",
+". c #211057",
+"X c #24105E",
+"o c #331A73",
+"O c #3E2770",
+"+ c #3F2878",
+"@ c #432B79",
+"# c #3E2280",
+"$ c #482D81",
+"% c #4A2F84",
+"& c #422588",
+"* c #4E318C",
+"= c #4E318D",
+"- c #573B97",
+"; c #52329E",
+": c #573B98",
+"> c #5A389F",
+", c #5432A2",
+"< c #5835A7",
+"1 c #5B38A4",
+"2 c #5F3CAD",
+"3 c #5E3AB1",
+"4 c #603BB3",
+"5 c #653FB7",
+"6 c #633DB8",
+"7 c #673FBC",
+"8 c #56408A",
+"9 c #584288",
+"0 c #594094",
+"q c #5A4094",
+"w c #5B4297",
+"e c #6E589D",
+"r c #6247A0",
+"t c #755DA7",
+"y c #755EA9",
+"u c #6C4ABA",
+"i c #6E4DBA",
+"p c #755AB0",
+"a c #785BB9",
+"s c #7C65AB",
+"d c #6941C0",
+"f c #6C44C4",
+"g c #734EC1",
+"h c #826DB0",
+"j c #836EB3",
+"k c #846DB4",
+"l c #8970BF",
+"z c #8F79BD",
+"x c #907CB8",
+"c c #917CBD",
+"v c #9382B5",
+"b c #9584BA",
+"n c #9784BC",
+"m c #9685BD",
+"M c #9884BB",
+"N c #9987BF",
+"B c #998AB8",
+"V c #9A88BF",
+"C c #9986C0",
+"Z c #9F8FC2",
+"A c #A190C6",
+"S c #AA9AC9",
+"D c #AD9DCA",
+"F c #AA9BCD",
+"G c #AEA0CD",
+"H c #B7AAD1",
+"J c #B9ACD1",
+"K c #BBAFD3",
+"L c #BCAFD7",
+"P c #BCB1D4",
+"I c #BFB1D6",
+"U c #BFB4D6",
+"Y c #C5BBDA",
+"T c #C6BCDA",
+"R c #C8BFDC",
+"E c #C9C0DC",
+"W c #CFC7E0",
+"Q c #D0C4E2",
+"! c #D0C8E1",
+"~ c #D2CAE2",
+"^ c #DCD6E8",
+"/ c None",
+/* pixels */
+"////////////////",
+"///////ff///////",
+"/////diL4///////",
+"////ul!^,<//////",
+"///gFWW!TGp3////",
+"///uATREERTz6///",
+"////;yKY8mUPa///",
+"/////#+BXomHC5//",
+"///////. /wZh2//",
+"/////:////-xs1//",
+"////Mj&//&kmt>//",
+"///wNSxrrcSVw///",
+"///=eDYQQPDe*///",
+"////$9xHKv9$////",
+"/////%@OO@%/////",
+"////////////////"
+};
diff --git a/mgllab/xpm/object-rotate-right.xpm b/mgllab/xpm/object-rotate-right.xpm
new file mode 100644
index 0000000..0b701d4
--- /dev/null
+++ b/mgllab/xpm/object-rotate-right.xpm
@@ -0,0 +1,105 @@
+/* XPM */
+static const char *object_rotate_right_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 83 1 ",
+"  c #210F57",
+". c #221057",
+"X c #24105E",
+"o c #331A73",
+"O c #3E2770",
+"+ c #3F2878",
+"@ c #432B79",
+"# c #3E2280",
+"$ c #482D81",
+"% c #4A2F84",
+"& c #422588",
+"* c #4E318C",
+"= c #4E318D",
+"- c #573B97",
+"; c #52329E",
+": c #573B98",
+"> c #5A389F",
+", c #5432A2",
+"< c #5835A7",
+"1 c #5B38A4",
+"2 c #5F3CAD",
+"3 c #5E3AB1",
+"4 c #603BB3",
+"5 c #653FB7",
+"6 c #633DB8",
+"7 c #673FBC",
+"8 c #56408A",
+"9 c #584288",
+"0 c #594094",
+"q c #5A4094",
+"w c #5B4297",
+"e c #6E589D",
+"r c #6247A0",
+"t c #755DA7",
+"y c #755EA9",
+"u c #6C4ABA",
+"i c #6E4DBA",
+"p c #755AB0",
+"a c #785BB9",
+"s c #7C65AB",
+"d c #6941C0",
+"f c #6C44C4",
+"g c #6C44C5",
+"h c #734EC1",
+"j c #826DB0",
+"k c #836EB3",
+"l c #846DB4",
+"z c #8970BF",
+"x c #8F79BD",
+"c c #907CB8",
+"v c #917CBD",
+"b c #9382B5",
+"n c #9584BA",
+"m c #9784BC",
+"M c #9685BD",
+"N c #9884BB",
+"B c #9987BF",
+"V c #998AB8",
+"C c #9A88BF",
+"Z c #9986C0",
+"A c #9F8FC2",
+"S c #A190C6",
+"D c #AA9AC9",
+"F c #AD9DCA",
+"G c #AA9BCD",
+"H c #AEA0CD",
+"J c #B7AAD1",
+"K c #B9ACD1",
+"L c #BBAFD3",
+"P c #BCAFD7",
+"I c #BCB1D4",
+"U c #BFB1D6",
+"Y c #BFB4D6",
+"T c #C5BBDA",
+"R c #C6BCDA",
+"E c #C8BFDC",
+"W c #C9C0DC",
+"Q c #CFC7E0",
+"! c #D0C4E2",
+"~ c #D0C8E1",
+"^ c #D2CAE2",
+"/ c #DCD6E8",
+"( c None",
+/* pixels */
+"((((((((((((((((",
+"(((((((gg(((((((",
+"(((((((4Piu(((((",
+"((((((<,/^z7((((",
+"((((3pHR~QQGh(((",
+"(((6xREWWERSu(((",
+"(((aIYn8TLy,((((",
+"((5ZJMoXV+#(((((",
+"((2jAw(. (((((((",
+"((1sc:((((:(((((",
+"((1tNl&((&kN((((",
+"(((qZDvrrvDZ0(((",
+"(((=eFI!!IFe=(((",
+"(((($9bKKb9$((((",
+"(((((%@O@@%(((((",
+"(((((((((((((((("
+};
diff --git a/mgllab/xpm/object-rotate-up.xpm b/mgllab/xpm/object-rotate-up.xpm
new file mode 100644
index 0000000..e183cde
--- /dev/null
+++ b/mgllab/xpm/object-rotate-up.xpm
@@ -0,0 +1,104 @@
+/* XPM */
+static const char *object_rotate_up_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 82 1 ",
+"  c #220F57",
+". c #211057",
+"X c #24105E",
+"o c #331A73",
+"O c #3E2770",
+"+ c #3F2878",
+"@ c #432B79",
+"# c #3E2280",
+"$ c #482D81",
+"% c #4A2F84",
+"& c #422588",
+"* c #4E318C",
+"= c #4E318D",
+"- c #573B97",
+"; c #52329E",
+": c #573B98",
+"> c #5A389F",
+", c #5432A2",
+"< c #5835A7",
+"1 c #5B38A4",
+"2 c #5F3CAD",
+"3 c #5E3AB1",
+"4 c #603BB3",
+"5 c #653FB7",
+"6 c #633DB8",
+"7 c #673FBC",
+"8 c #56408A",
+"9 c #584288",
+"0 c #594094",
+"q c #5A4094",
+"w c #5B4297",
+"e c #6E589D",
+"r c #6247A0",
+"t c #755DA7",
+"y c #755EA9",
+"u c #6C4ABA",
+"i c #6E4DBA",
+"p c #755AB0",
+"a c #785BB9",
+"s c #7C65AB",
+"d c #6941C0",
+"f c #6C44C4",
+"g c #734EC1",
+"h c #826DB0",
+"j c #836EB3",
+"k c #846DB4",
+"l c #8970BF",
+"z c #8F79BD",
+"x c #907CB8",
+"c c #917CBD",
+"v c #9382B5",
+"b c #9584BA",
+"n c #9784BC",
+"m c #9685BD",
+"M c #9884BB",
+"N c #9987BF",
+"B c #998AB8",
+"V c #9A88BF",
+"C c #9986C0",
+"Z c #9F8FC2",
+"A c #A190C6",
+"S c #AA9AC9",
+"D c #AD9DCA",
+"F c #AA9BCD",
+"G c #AEA0CD",
+"H c #B7AAD1",
+"J c #B9ACD1",
+"K c #BBAFD3",
+"L c #BCAFD7",
+"P c #BCB1D4",
+"I c #BFB1D6",
+"U c #BFB4D6",
+"Y c #C5BBDA",
+"T c #C6BCDA",
+"R c #C8BFDC",
+"E c #C9C0DC",
+"W c #CFC7E0",
+"Q c #D0C4E2",
+"! c #D0C8E1",
+"~ c #D2CAE2",
+"^ c #DCD6E8",
+"/ c None",
+/* pixels */
+"////////////////",
+"////////////////",
+"////////////////",
+"///=0/////ug////",
+"//$eNM///;AF7///",
+"/%9DSj:/#sREld//",
+"/@vIc&//+JT~~i//",
+"/OJQr//.BTR~^Lf/",
+"/@JRr//.X8ET,4f/",
+"/@xYc&//obRG<///",
+"/$9DSk-0mUTp////",
+"//$eNNxZHPz3////",
+"///=qtshCa6/////",
+"/////1125///////",
+"////////////////",
+"////////////////"
+};
diff --git a/mgllab/xpm/object-ungroup.xpm b/mgllab/xpm/object-ungroup.xpm
new file mode 100644
index 0000000..174e137
--- /dev/null
+++ b/mgllab/xpm/object-ungroup.xpm
@@ -0,0 +1,46 @@
+/* XPM */
+static const char *object_ungroup_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 24 1 ",
+"  c #78787B",
+". c #1867ED",
+"X c #1867EE",
+"o c #1868ED",
+"O c #1868EE",
+"+ c #86868A",
+"@ c #949499",
+"# c #A1A1A6",
+"$ c #ACACB1",
+"% c #B7B7BC",
+"& c #B8B8BD",
+"* c gray90",
+"= c #E7E7E7",
+"- c gray91",
+"; c #ECECEC",
+": c gray93",
+"> c #EEEEEE",
+", c #EFEFEF",
+"< c #F3F3F3",
+"1 c #F6F6F6",
+"2 c #FBFBFB",
+"3 c #FEFEFE",
+"4 c white",
+"5 c None",
+/* pixels */
+"5555555555555555",
+"55555OOOOO.55555",
+"5555555555O55555",
+"555%$#@+ 5OO.555",
+"555%**,< 555O555",
+"5.5%2&$#@+ 5OO.5",
+"5O5%2&*-,< 555O5",
+"5O5%2&2&$#@+ 5O5",
+"5O5&$&2%**,< 5O5",
+"5O555&2%2,,< 5O5",
+"5OOO5&$%222- 5.5",
+"555O555%2222 555",
+"555.OO5%$#@+ 555",
+"55555O5555555555",
+"55555.OOOO.55555",
+"5555555555555555"
+};
diff --git a/mgllab/xpm/office-chart-bar.xpm b/mgllab/xpm/office-chart-bar.xpm
new file mode 100644
index 0000000..5eff20a
--- /dev/null
+++ b/mgllab/xpm/office-chart-bar.xpm
@@ -0,0 +1,84 @@
+/* XPM */
+static const char *office_chart_bar_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 62 1 ",
+"  c gray47",
+". c #7F7C7A",
+"X c gray49",
+"o c #7F7E7C",
+"O c #7F7F7E",
+"+ c #807D7B",
+"@ c #807F7D",
+"# c #81807F",
+"$ c #285C9C",
+"% c #2A5F9E",
+"& c #2B60A2",
+"* c #2E64A4",
+"= c #366AA8",
+"- c #3B6EAC",
+"; c #3F71AF",
+": c #4578B4",
+"> c #477AB6",
+", c #5082BD",
+"< c #5182BD",
+"1 c #5182BE",
+"2 c #5A8BC4",
+"3 c #5B8CC6",
+"4 c #5C8DC6",
+"5 c #6393CB",
+"6 c #6696CE",
+"7 c #6796CF",
+"8 c #6C9BD3",
+"9 c #73A1D7",
+"0 c #74A1D7",
+"q c #75A3DA",
+"w c #7FACE1",
+"e c #808080",
+"r c gray51",
+"t c #838383",
+"y c #80ADE1",
+"u c #84B2E7",
+"i c #8AB5E9",
+"p c #8EBAEF",
+"a c #A3C0E4",
+"s c #A3C1E4",
+"d c #A5C2E5",
+"f c #A5C2E6",
+"g c #ADC7E7",
+"h c #AEC8E7",
+"j c #AFC8E7",
+"k c #BDD2EC",
+"l c #C4D6ED",
+"z c #C4D6EE",
+"x c #D5E2F3",
+"c c #D6E2F3",
+"v c #DBE7F4",
+"b c #E0EAF6",
+"n c #E6EDF8",
+"m c #E7EFF8",
+"M c #E9F0F9",
+"N c #F2F5FB",
+"B c #F1F6FB",
+"V c #F4F7FC",
+"C c #F7F9FD",
+"Z c #FDFDFE",
+"A c #FEFEFE",
+"S c None",
+/* pixels */
+"SSSSSSSSSSSSSSSS",
+"SXSSSSSSSSSSSSSS",
+"SXSSSSSSSSSSSSSS",
+"SeSSSSSSpiipSSSS",
+"SeSSSSSSyZZySSSS",
+"StSSSSSSqVNqSSSS",
+" eSuyyuS8Mn8SSSS",
+"SeSqCBqS5vc5SSSS",
+"SeS7mb7S2zk2SSSS",
+" eS2cz4S1jg1SSSS",
+"StS1hg1S>aa>SSSS",
+"SeS:ss>S:aa-SSSS",
+" tS;ff;S=ff=SSSS",
+"SeS*%$*S&$$&SSSS",
+"St#X++ at X@@.@@XXS",
+"SSSS SS SS SSSSS"
+};
diff --git a/mgllab/xpm/office-chart-line.xpm b/mgllab/xpm/office-chart-line.xpm
new file mode 100644
index 0000000..dfff099
--- /dev/null
+++ b/mgllab/xpm/office-chart-line.xpm
@@ -0,0 +1,71 @@
+/* XPM */
+static const char *office_chart_line_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 49 1 ",
+"  c gray47",
+". c #7B7B7B",
+"X c #7D7B78",
+"o c #7C7B79",
+"O c #7A7C7A",
+"+ c #7A7C7B",
+"@ c #7B7D7B",
+"# c #7D7C7A",
+"$ c #7C7C7B",
+"% c #7B7D7C",
+"& c #7C7D7D",
+"* c gray49",
+"= c #7E7D7C",
+"- c #7C7E7C",
+"; c #7F7E7D",
+": c #7E7E7E",
+"> c gray50",
+", c #B4274F",
+"< c #B4294B",
+"1 c #B52A4C",
+"2 c #B42750",
+"3 c #B42354",
+"4 c #B52851",
+"5 c #B7215E",
+"6 c #A7267C",
+"7 c #0969F3",
+"8 c #0B6AF3",
+"9 c #1872F2",
+"0 c #3475E9",
+"q c #2079F5",
+"w c #237CF7",
+"e c #427DE6",
+"r c #B81782",
+"t c #B8148B",
+"y c #B70E9A",
+"u c #B71190",
+"i c #B90DA0",
+"p c #B90CA1",
+"a c #B80CA2",
+"s c #83469C",
+"d c #3F8DF8",
+"f c #448EF7",
+"g c #4F95F8",
+"h c #5398F8",
+"j c #60A0F9",
+"k c #6BA7FA",
+"l c #6EA9FA",
+"z c #78AFFB",
+"x c None",
+/* pixels */
+"xxxxxxxxxxxxxxxx",
+"x.xxxxxxxxxxxxxx",
+"x.xxxxxxxxxxlzxx",
+"x*xxxxxxxxxjkxxx",
+"x*xxxxxxxxhxxxxx",
+"x*xxxxxxxxgxxxxx",
+".*xxxxxxxfxxxxxx",
+"x*xxx143edxxxxxx",
+"x*xx<2x5sxxxxxxx",
+".Ox14xx06xxxxxxx",
+"x%xxxxxwxrxxxixx",
+"x.xxxx9qxtuxixxx",
+".ox778xxxxyaxxxx",
+"x.xxxxxxxxxxxxxx",
+"x;$Xo$*O**.O%..x",
+"xxxx.xx.xx.xxxxx"
+};
diff --git a/mgllab/xpm/office-chart-scatter.xpm b/mgllab/xpm/office-chart-scatter.xpm
new file mode 100644
index 0000000..7ee8b2e
--- /dev/null
+++ b/mgllab/xpm/office-chart-scatter.xpm
@@ -0,0 +1,44 @@
+/* XPM */
+static const char *office_chart_scatter_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 22 1 ",
+"  c gray47",
+". c gray49",
+"X c #B72659",
+"o c #B81F6C",
+"O c #81807E",
+"+ c #056DFF",
+"@ c #0A6EFC",
+"# c #0673FF",
+"$ c #0A72FF",
+"% c #1273FC",
+"& c #1776FD",
+"* c #1579FF",
+"= c #1F7BFD",
+"- c #247EFD",
+"; c #BB1393",
+": c #BC0BA6",
+"> c #2381FF",
+", c #2D88FF",
+"< c #808080",
+"1 c gray51",
+"2 c #838383",
+"3 c None",
+/* pixels */
+"3333333333333333",
+"3.33333333333333",
+"3.33333333333333",
+"3<33X3X33333,333",
+"3<3333333333>333",
+"3233o3o333*&3->3",
+" <3333333333%333",
+"3<3333333333#333",
+"3233333333333333",
+" <333$33333;3;33",
+"32333 at 3333333333",
+"3<3$@3@$333:3:33",
+" 2333$3333333333",
+"3<333+3333333333",
+"322<OO<<<2<<<..3",
+"3333 33 33 33333"
+};
diff --git a/mgllab/xpm/ok.xpm b/mgllab/xpm/ok.xpm
new file mode 100644
index 0000000..0a1c7dc
--- /dev/null
+++ b/mgllab/xpm/ok.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * ok_xpm[] = {
+"16 16 3 1",
+" 	c None",
+"!	c #000090",
+"#	c #0000FF",
+"                ",
+"              # ",
+"             ## ",
+"            ##! ",
+"           ##!  ",
+"          ##!   ",
+"         ##!    ",
+"         ##!    ",
+"        ##!     ",
+"  ###  ###!     ",
+"   ### ##!      ",
+"    #####!      ",
+"     ###!       ",
+"      ##!       ",
+"       #!       ",
+"        !       "};
diff --git a/mgllab/xpm/oper.xpm b/mgllab/xpm/oper.xpm
new file mode 100644
index 0000000..ca6a51d
--- /dev/null
+++ b/mgllab/xpm/oper.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * oper_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"   .            ",
+"   .            ",
+" .....    ..... ",
+"   .            ",
+"   .            ",
+"                ",
+"                ",
+"                ",
+"    .       .   ",
+"   .      . . . ",
+"   .       ...  ",
+"  .        ...  ",
+"  .       . . . ",
+" .          .   ",
+"                "};
diff --git a/mgllab/xpm/oper_a.xpm b/mgllab/xpm/oper_a.xpm
new file mode 100644
index 0000000..afa1a80
--- /dev/null
+++ b/mgllab/xpm/oper_a.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * oper_a_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"    .           ",
+"    .           ",
+"    .    ...... ",
+" .......        ",
+"    .    ...... ",
+"    .           ",
+"    .           ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/oper_d.xpm b/mgllab/xpm/oper_d.xpm
new file mode 100644
index 0000000..2b89d5e
--- /dev/null
+++ b/mgllab/xpm/oper_d.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * oper_d_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"       .        ",
+"      .         ",
+"      .         ",
+"     .   ...... ",
+"     .          ",
+"    .    ...... ",
+"    .           ",
+"   .            ",
+"   .            ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/oper_dir.xpm b/mgllab/xpm/oper_dir.xpm
new file mode 100644
index 0000000..f6f7b8a
--- /dev/null
+++ b/mgllab/xpm/oper_dir.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * oper_dir_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"   .            ",
+"  .   .         ",
+"  .   .         ",
+"  . .... .      ",
+"  . . . .       ",
+"  . .... .      ",
+" .              ",
+"          ..... ",
+"          .   . ",
+"  ..       .    ",
+" .  .       .   ",
+"    .      .    ",
+" ....     .   . ",
+".   .. .  ..... ",
+".  .  .         ",
+" ..  . .        "};
diff --git a/mgllab/xpm/oper_m.xpm b/mgllab/xpm/oper_m.xpm
new file mode 100644
index 0000000..f2f8db1
--- /dev/null
+++ b/mgllab/xpm/oper_m.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * oper_m_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #000000",
+"+	c #7F7F7F",
+"                ",
+"                ",
+"                ",
+"                ",
+"   .   .        ",
+"   +. .+        ",
+"    +.+  ...... ",
+"  ......        ",
+"    +.+  ...... ",
+"   +. .+        ",
+"   .   .        ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/oper_of.xpm b/mgllab/xpm/oper_of.xpm
new file mode 100644
index 0000000..c22a9ba
--- /dev/null
+++ b/mgllab/xpm/oper_of.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * oper_of_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #000000",
+"+	c #FF0000",
+"   .        ++  ",
+"  .   .     ++  ",
+"  .   .   ++++++",
+"  . .... .++++++",
+"  . . . .   ++  ",
+"  . .... .  ++  ",
+" .              ",
+"          ..... ",
+"          .   . ",
+"  ..       .    ",
+" .  .       .   ",
+"    .      .    ",
+" ....     .   . ",
+".   .. .  ..... ",
+".  .  .         ",
+" ..  . .        "};
diff --git a/mgllab/xpm/oper_s.xpm b/mgllab/xpm/oper_s.xpm
new file mode 100644
index 0000000..6bda134
--- /dev/null
+++ b/mgllab/xpm/oper_s.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * oper_s_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"         ...... ",
+" .......        ",
+"         ...... ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/option.xpm b/mgllab/xpm/option.xpm
new file mode 100644
index 0000000..d7dd6d6
--- /dev/null
+++ b/mgllab/xpm/option.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * option_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #000000",
+"+	c #7F0000",
+"                ",
+"                ",
+"                ",
+"   ..           ",
+"  .++.          ",
+"  .++.          ",
+"   ..           ",
+"                ",
+"                ",
+"   ..           ",
+"  .++.          ",
+"  .++.          ",
+"   .+. ++ ++ ++ ",
+"    .  ++ ++ ++ ",
+"   .            ",
+"                "};
diff --git a/mgllab/xpm/other.xpm b/mgllab/xpm/other.xpm
new file mode 100644
index 0000000..e2d7562
--- /dev/null
+++ b/mgllab/xpm/other.xpm
@@ -0,0 +1,117 @@
+/* XPM */
+static const char * other_xpm[] = {
+"16 16 98 2",
+"  	c None",
+". 	c #FFFFFF",
+"+ 	c #00CAFF",
+"@ 	c #00ADFF",
+"# 	c #0000EB",
+"$ 	c #00007F",
+"% 	c #0000B4",
+"& 	c #0000B9",
+"* 	c #00D1FF",
+"= 	c #73FF8B",
+"- 	c #68FF96",
+"; 	c #00BFFF",
+"> 	c #0000C3",
+", 	c #0000C7",
+"' 	c #01DDFD",
+") 	c #0041FF",
+"! 	c #0DFBF1",
+"~ 	c #3EFFC0",
+"{ 	c #00EEFF",
+"] 	c #0024FF",
+"^ 	c #000082",
+"/ 	c #000083",
+"( 	c #2EFFD0",
+"_ 	c #00E9FF",
+": 	c #0001EA",
+"< 	c #0074FF",
+"[ 	c #009CFF",
+"} 	c #0058FF",
+"| 	c #0000D5",
+"1 	c #009FFF",
+"2 	c #63FF9B",
+"3 	c #0000C1",
+"4 	c #00009D",
+"5 	c #0000F7",
+"6 	c #0042FF",
+"7 	c #0030FF",
+"8 	c #0000DC",
+"9 	c #000080",
+"0 	c #0017FE",
+"a 	c #00E0FF",
+"b 	c #0000F6",
+"c 	c #0075FF",
+"d 	c #0094FF",
+"e 	c #0044FF",
+"f 	c #0000BE",
+"g 	c #000086",
+"h 	c #000BFE",
+"i 	c #004FFF",
+"j 	c #0000AC",
+"k 	c #006EFF",
+"l 	c #10FEEE",
+"m 	c #35FFC9",
+"n 	c #0000C9",
+"o 	c #0083FF",
+"p 	c #0031FF",
+"q 	c #000090",
+"r 	c #0007F9",
+"s 	c #0BF9F3",
+"t 	c #7EFF80",
+"u 	c #58FFA6",
+"v 	c #007DFF",
+"w 	c #000085",
+"x 	c #1FFFDF",
+"y 	c #000081",
+"z 	c #0039FF",
+"A 	c #00DBFF",
+"B 	c #01BDFD",
+"C 	c #0AFEF4",
+"D 	c #0000AA",
+"E 	c #00009A",
+"F 	c #001BFC",
+"G 	c #00C9FE",
+"H 	c #4BFFB3",
+"I 	c #0006F7",
+"J 	c #008FFF",
+"K 	c #6FFF8F",
+"L 	c #F5FF09",
+"M 	c #FFDB00",
+"N 	c #F1FB0D",
+"O 	c #0021FF",
+"P 	c #0000EA",
+"Q 	c #13FCEB",
+"R 	c #F0FF0E",
+"S 	c #FF8700",
+"T 	c #FF5B00",
+"U 	c #EDFC11",
+"V 	c #12FDEC",
+"W 	c #0003E9",
+"X 	c #00B7FF",
+"Y 	c #98FF66",
+"Z 	c #FFDF00",
+"` 	c #FFB300",
+" .	c #00B8FF",
+"..	c #0067FF",
+"+.	c #04E9FA",
+"@.	c #1DFCE1",
+"#.	c #00EDFF",
+"$.	c #000088",
+"            + @ # $ $ %         ",
+"      & * = - ; > $ $ , '       ",
+"  $ $ ) ! ~ { ] ^ $ $ / ( _     ",
+"  $ $ : < [ } | $ $ $ $ 1 2 3   ",
+"  $ $ 4 5 6 7 8 9 $ $ $ 0 a 7 $ ",
+"  $ $ / b c d e f $ $ g h i 8 $ ",
+"  $ $ j k l m * # $ $ n o p q $ ",
+"  $ $ r s t u v w $ $ j x 1 y $ ",
+"  $ $ z A B $ $ $ $ $ $ C ~ D $ ",
+"  $ $ $ $ E F [ G [ 0 E $ H I $ ",
+"  $ $ $ D J K L M N K J D $ O $ ",
+"    $ $ P Q R S T S U V W $ $ $ ",
+"      $ f X Y Z ` Z Y  .f $ $ $ ",
+"        $ > ..+. at .#...> $ $     ",
+"          $ $ y $.^ $           ",
+"            $ $ $               "};
diff --git a/mgllab/xpm/package-x-generic.xpm b/mgllab/xpm/package-x-generic.xpm
new file mode 100644
index 0000000..126a075
--- /dev/null
+++ b/mgllab/xpm/package-x-generic.xpm
@@ -0,0 +1,107 @@
+/* XPM */
+static const char *package_x_generic_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 85 1 ",
+"  c #855201",
+". c #8F5902",
+"X c #8F5D0C",
+"o c #945E07",
+"O c #935E08",
+"+ c #93600E",
+"@ c #93600F",
+"# c #95610E",
+"$ c #99630D",
+"% c #9A650E",
+"& c #9B650F",
+"* c #946212",
+"= c #9B6A1B",
+"- c #A06A14",
+"; c #A26D19",
+": c #A87B33",
+"> c #A87C35",
+", c #A87D37",
+"< c #C78C33",
+"1 c #AC8443",
+"2 c #AD8544",
+"3 c #B79255",
+"4 c #BA9861",
+"5 c #D29A46",
+"6 c #DDA858",
+"7 c #C2A26D",
+"8 c #C4A36D",
+"9 c #C3A370",
+"0 c #C4A570",
+"q c #C4A673",
+"w c #C9AB7B",
+"e c #CBAE7F",
+"r c #CDAE7C",
+"t c #D5AE74",
+"y c #D7B074",
+"u c #DAB47B",
+"i c #D8B57E",
+"p c #DDB77E",
+"a c #E7B66A",
+"s c #DFBB83",
+"d c #E3BE87",
+"f c #EDC485",
+"g c #EDC587",
+"h c #E3C08A",
+"j c #EEC78A",
+"k c #EEC98E",
+"l c #E8C792",
+"z c #EFCA90",
+"x c #EFCC94",
+"c c #E0C599",
+"v c #E5CB9F",
+"b c #ECCD9D",
+"n c #ECCD9E",
+"m c #F0CD97",
+"M c #F0CE99",
+"N c #E2CAA6",
+"B c #E2CCA8",
+"V c #E2CEAD",
+"C c #EFD1A1",
+"Z c #EFD3A7",
+"A c #EED3A8",
+"S c #EFD3A8",
+"D c #EFD5AB",
+"F c #EED5AC",
+"G c #EFD6AE",
+"H c #EFD7AE",
+"J c #F0D1A2",
+"K c #F0D4A8",
+"L c #F0D5AB",
+"P c #F0D5AD",
+"I c #F0D7AE",
+"U c #F0D7AF",
+"Y c #E3D0B1",
+"T c #E3D0B2",
+"R c #E5D2B2",
+"E c #E7D3B2",
+"W c #EBDBC0",
+"Q c #EDDDC3",
+"! c #EFE0C7",
+"~ c #F3E7D0",
+"^ c #F1E5D2",
+"/ c #F2E7D3",
+"( c #F6F0E5",
+") c #F9F3EA",
+"_ c None",
+/* pixels */
+"________________",
+"__.........o..__",
+"..(BYYYRREcVN4._",
+".^!O$%o%%-;:)r3*",
+".^W###==,,,7^r8*",
+"oWqPKKKJKAACKqw+",
+".1FJMMmmkjjffA1+",
+".7UUUUPIIFHUFFi.",
+"_.......o......_",
+"_.y<<<<<<<<<<t._",
+"_.p5555555555u._",
+"_.d6666666666s._",
+"_.laaaaaaaaaah._",
+"_.Fnnnnnnnnnnv._",
+"_X............ _",
+"________________"
+};
diff --git a/mgllab/xpm/pause.xpm b/mgllab/xpm/pause.xpm
new file mode 100644
index 0000000..e09d88b
--- /dev/null
+++ b/mgllab/xpm/pause.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * pause_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #777777",
+"q	c #000000",
+"                ",
+"                ",
+"                ",
+"   qqq    qqq   ",
+"   q.q    q.q   ",
+"   q.q    q.q   ",
+"   q.q    q.q   ",
+"   q.q    q.q   ",
+"   q.q    q.q   ",
+"   q.q    q.q   ",
+"   q.q    q.q   ",
+"   q.q    q.q   ",
+"   qqq    qqq   ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/plot.xpm b/mgllab/xpm/plot.xpm
new file mode 100644
index 0000000..acc1eea
--- /dev/null
+++ b/mgllab/xpm/plot.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char * plot_xpm[] = {
+"16 16 4 1",
+" 	c None",
+".	c #000000",
+"+	c #0000FF",
+"@	c #FF0000",
+"                ",
+" .              ",
+"..            + ",
+" .          ++  ",
+" .         +    ",
+"..        +     ",
+" .       +      ",
+" .       +      ",
+"..   @@@+       ",
+" .  @  +@     @ ",
+" .@@   + @   @  ",
+"..    +   @@@   ",
+" .  ++          ",
+" .++            ",
+"............... ",
+" .   .   .   .  "};
diff --git a/mgllab/xpm/polygon.xpm b/mgllab/xpm/polygon.xpm
new file mode 100644
index 0000000..ecbdb8f
--- /dev/null
+++ b/mgllab/xpm/polygon.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *polygon_xpm[]={
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"       ..       ",
+"      .  .      ",
+"    ..    ..    ",
+"   .        .   ",
+" ..          .. ",
+".              .",
+".              .",
+" .            . ",
+" .            . ",
+" .            . ",
+"  .          .  ",
+"  .          .  ",
+"  .          .  ",
+"   .        .   ",
+"   ..........   "};
diff --git a/mgllab/xpm/preferences-system.xpm b/mgllab/xpm/preferences-system.xpm
new file mode 100644
index 0000000..0e5374b
--- /dev/null
+++ b/mgllab/xpm/preferences-system.xpm
@@ -0,0 +1,115 @@
+/* XPM */
+static const char *preferences_system_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 93 2 ",
+"   c #393A37",
+".  c #393938",
+"X  c #3E3E3D",
+"o  c #6F4B00",
+"O  c #444542",
+"+  c #444444",
+"@  c #444544",
+"#  c #454747",
+"$  c #505051",
+"%  c gray32",
+"&  c #555655",
+"*  c #57575A",
+"=  c #585858",
+"-  c gray37",
+";  c #626364",
+":  c #656565",
+">  c #686A69",
+",  c #6A6B6A",
+"<  c #6B6B6A",
+"1  c gray42",
+"2  c gray46",
+"3  c #797979",
+"4  c #AF6F00",
+"5  c #AC6F08",
+"6  c #AE7103",
+"7  c #B27300",
+"8  c #A58732",
+"9  c #CA8400",
+"0  c #C68F05",
+"q  c #C39006",
+"w  c #CB9B00",
+"e  c #D4A602",
+"r  c #D5AC02",
+"t  c #DEA801",
+"y  c #EAB002",
+"u  c #E7B70A",
+"i  c #EABF15",
+"p  c #F3CC0B",
+"a  c #FDD708",
+"s  c #F4CF19",
+"d  c #F4D510",
+"f  c #FAE000",
+"g  c #F2CE24",
+"h  c #FAE224",
+"j  c #D1BB76",
+"k  c #818181",
+"l  c gray51",
+"z  c #848484",
+"x  c gray52",
+"c  c #858685",
+"v  c #898989",
+"b  c #898A89",
+"n  c gray55",
+"m  c #8E8F8E",
+"M  c #90908F",
+"N  c #919190",
+"B  c #939392",
+"V  c #989998",
+"C  c #999998",
+"Z  c #9B9B9B",
+"A  c #9C9E9F",
+"S  c #A2A3A2",
+"D  c #A2A4A3",
+"F  c #A5A5A4",
+"G  c #A7A7A6",
+"H  c gray66",
+"J  c #ACACAC",
+"K  c #AEAEAE",
+"L  c #B1B2B2",
+"P  c gray70",
+"I  c #B6B6B5",
+"U  c #B7B7B7",
+"Y  c #BBBBBA",
+"T  c #BBBBBB",
+"R  c #BCBCBB",
+"E  c #BBBCBD",
+"W  c #C2C3C1",
+"Q  c gray77",
+"!  c #C6C7C8",
+"~  c #C8C9C8",
+"^  c #CACBCB",
+"/  c #CECFCF",
+"(  c #D3D3D2",
+")  c #D4D5D6",
+"_  c gray84",
+"`  c #D9DAD9",
+"'  c #DBDCDC",
+"]  c #DFDFDF",
+"[  c #E1E1E1",
+"{  c #ECECEB",
+"}  c #ECEDEC",
+"|  c #EFEFEF",
+" . c None",
+/* pixels */
+" . . . . . . . . . . . .U  . . .",
+"T | L  . . . . . . .N ` ) I  . .",
+" .E ^  . . . . . . .T { K  . . .",
+" . .* [  . . . . . .Q { ^  . . .",
+" . . .# ]  . . . .z D A ( F N  .",
+" . . . .$ '  . . .T < M W V &  .",
+" . . . . .; )  .K b z 2 < #  . .",
+" . . . . . .z / k b  . . . . . .",
+" . . . . . .G < Q j 5  . . . . .",
+" . . . . .S O 3 8 a y  . . . . .",
+" . . . .C X < = o q f d 6  . . .",
+" . . .m . = :  . . .q h g 7  . .",
+" . .H . # 2  . . . . .e i s 7  .",
+" .Z : 2 k  . . . . . . .r u p 9 ",
+" .I K n  . . . . . . . . .w t  .",
+" .$ -  . . . . . . . . . . . . ."
+};
diff --git a/mgllab/xpm/prev_sl.xpm b/mgllab/xpm/prev_sl.xpm
new file mode 100644
index 0000000..3f20e59
--- /dev/null
+++ b/mgllab/xpm/prev_sl.xpm
@@ -0,0 +1,24 @@
+/* XPM */
+static const char * prev_sl_xpm[] = {
+"16 16 5 1",
+" 	c None",
+".	c #00007F",
+"+	c #007FFF",
+"@	c #0000FF",
+"#	c #003F80",
+"                ",
+"        ..      ",
+"       .+.      ",
+"      .++.      ",
+"     .+ at ++.     ",
+"    .+ at +@++.... ",
+"   .+ at +@+ at +@+ at . ",
+"  .+ at +@@@@@@@@. ",
+" .@@@@@@@@@@@@. ",
+"  .#@#@@@@@@@@. ",
+"   .#@#@#@#@#@. ",
+"    .#@#@#@.... ",
+"     .#@#@.     ",
+"      .##.      ",
+"       .#.      ",
+"        ..      "};
diff --git a/mgllab/xpm/preview.xpm b/mgllab/xpm/preview.xpm
new file mode 100644
index 0000000..0446109
--- /dev/null
+++ b/mgllab/xpm/preview.xpm
@@ -0,0 +1,193 @@
+/* XPM */
+static const char *preview_xpm[] = {
+"16 16 174 2",
+"  	c None",
+". 	c #EA6E0E",
+"+ 	c #F67F06",
+"@ 	c #E3BB18",
+"# 	c #A4E757",
+"$ 	c #56E6A3",
+"% 	c #25DAD6",
+"& 	c #11E5EB",
+"* 	c #2AF5D0",
+"= 	c #72F588",
+"- 	c #B0EC4B",
+"; 	c #C7DC34",
+"> 	c #C3E336",
+", 	c #98F563",
+"' 	c #3FF6BC",
+") 	c #07D5F5",
+"! 	c #0E9EEA",
+"~ 	c #F44C0A",
+"{ 	c #FC0E00",
+"] 	c #FB1900",
+"^ 	c #FF5B00",
+"/ 	c #F7C407",
+"( 	c #B5FD49",
+"_ 	c #4BFFB3",
+": 	c #0BF6F3",
+"< 	c #05D9F9",
+"[ 	c #0CD2F2",
+"} 	c #14DEEB",
+"| 	c #1BF0E3",
+"1 	c #20FEDE",
+"2 	c #27FFD7",
+"3 	c #2BFDD3",
+"4 	c #3BEEC3",
+"5 	c #F14F0A",
+"6 	c #FC1400",
+"7 	c #FB1700",
+"8 	c #FF5000",
+"9 	c #FBBA03",
+"0 	c #B8FD46",
+"a 	c #39FCC5",
+"b 	c #01CAFE",
+"c 	c #0088FF",
+"d 	c #0075FF",
+"e 	c #008FFF",
+"f 	c #01CCFE",
+"g 	c #22FCDC",
+"h 	c #73FF8B",
+"i 	c #BAFC44",
+"j 	c #D3E228",
+"k 	c #F47B0A",
+"l 	c #FF8C00",
+"m 	c #F4BA0A",
+"n 	c #CBE733",
+"o 	c #7DFC81",
+"p 	c #2BEDD3",
+"q 	c #03C1FB",
+"r 	c #0090FF",
+"s 	c #0082FF",
+"t 	c #009DFF",
+"u 	c #08D4F7",
+"v 	c #3AFAC4",
+"w 	c #98FF66",
+"x 	c #E7EF18",
+"y 	c #FEBC01",
+"z 	c #F4920A",
+"A 	c #F4AD0B",
+"B 	c #D4F62A",
+"C 	c #63FD9B",
+"D 	c #16D9E9",
+"E 	c #0296FD",
+"F 	c #0063FF",
+"G 	c #0059FF",
+"H 	c #0076FF",
+"I 	c #00B6FF",
+"J 	c #1AF2E4",
+"K 	c #6EFF90",
+"L 	c #C8FD36",
+"M 	c #F9E306",
+"N 	c #FFB900",
+"O 	c #FFA800",
+"P 	c #F4AF0B",
+"Q 	c #EFBD0D",
+"R 	c #A0FF5E",
+"S 	c #1BF3E3",
+"T 	c #009CFF",
+"U 	c #0056FF",
+"V 	c #0041FF",
+"W 	c #005DFF",
+"X 	c #00A0FF",
+"Y 	c #0EEEF0",
+"Z 	c #5FFF9F",
+"` 	c #B7FF47",
+" .	c #F1FA0D",
+"..	c #F9E606",
+"+.	c #F0E70E",
+"@.	c #D4F42A",
+"#.	c #9CF05F",
+"$.	c #F4AA0A",
+"%.	c #DFF01F",
+"&.	c #8DFD71",
+"*.	c #4CF4B2",
+"=.	c #2DDFD1",
+"-.	c #21D5DE",
+";.	c #1CDFE2",
+">.	c #20F4DE",
+",.	c #3BFFC3",
+"'.	c #79FF85",
+").	c #80FF7E",
+"!.	c #72FE8C",
+"~.	c #51FAAD",
+"{.	c #28EFD6",
+"].	c #14CDEA",
+"^.	c #F4760A",
+"/.	c #FF6B00",
+"(.	c #FD6D00",
+"_.	c #F87A05",
+":.	c #F1910C",
+"<.	c #E9B615",
+"[.	c #D8DF26",
+"}.	c #B2FC4C",
+"|.	c #70FF8E",
+"1.	c #2DFED1",
+"2.	c #0BE3F3",
+"3.	c #04B9FB",
+"4.	c #0099FE",
+"5.	c #0085FF",
+"6.	c #007EFF",
+"7.	c #0A84F4",
+"8.	c #F1480A",
+"9.	c #EA0500",
+"0.	c #C50000",
+"a.	c #B30000",
+"b.	c #BB0100",
+"c.	c #DA0600",
+"d.	c #FA3500",
+"e.	c #FCB403",
+"f.	c #ACFD52",
+"g.	c #24F8DA",
+"h.	c #00A5FF",
+"i.	c #0036FF",
+"j.	c #0046FF",
+"k.	c #007FFF",
+"l.	c #11C0EA",
+"m.	c #F4440A",
+"n.	c #E10100",
+"o.	c #B20000",
+"p.	c #990000",
+"q.	c #9B0000",
+"r.	c #B90000",
+"s.	c #EB0500",
+"t.	c #FF6700",
+"u.	c #E9E716",
+"v.	c #75FF89",
+"w.	c #1EE7E0",
+"x.	c #09B9F6",
+"y.	c #06ACF8",
+"z.	c #11C6ED",
+"A.	c #38F0C6",
+"B.	c #8FF26F",
+"C.	c #E9630E",
+"D.	c #F43606",
+"E.	c #E92406",
+"F.	c #E02006",
+"G.	c #DE2006",
+"H.	c #F43706",
+"I.	c #F56806",
+"J.	c #F5A106",
+"K.	c #EBCC11",
+"L.	c #CED92D",
+"M.	c #B9DB41",
+"N.	c #B9DD43",
+"O.	c #C8D933",
+"P.	c #E3CE18",
+"Q.	c #E8AB10",
+"                                ",
+"                                ",
+"                                ",
+". + @ # $ % & * = - ; > , ' ) ! ",
+"~ { ] ^ / ( _ : < [ } | 1 2 3 4 ",
+"5 6 7 8 9 0 a b c d e f g h i j ",
+"k l m n o p q r s t u v w x y z ",
+"A B C D E F G H I J K L M N O P ",
+"Q R S T U V W X Y Z `  ...+. at .#.",
+"$.%.&.*.=.-.;.>.,.Z '.).!.~.{.].",
+"^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.",
+"8.9.0.a.b.c.d.e.f.g.h.U i.j.k.l.",
+"m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.",
+"C.D.E.F.G.E.H.I.J.K.L.M.N.O.P.Q.",
+"                                ",
+"                                "};
diff --git a/mgllab/xpm/process-stop.xpm b/mgllab/xpm/process-stop.xpm
new file mode 100644
index 0000000..d4faa1d
--- /dev/null
+++ b/mgllab/xpm/process-stop.xpm
@@ -0,0 +1,144 @@
+/* XPM */
+static const char *process_stop_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 122 2 ",
+"   c #890600",
+".  c #8C0600",
+"X  c #950000",
+"o  c #910500",
+"O  c #9A1717",
+"+  c #9E1414",
+"@  c #A30000",
+"#  c #A40000",
+"$  c #AA0000",
+"%  c #AE0000",
+"&  c #B40000",
+"*  c #B00400",
+"=  c #BD0404",
+"-  c #B51300",
+";  c #BE1000",
+":  c #BF1200",
+">  c #BB1400",
+",  c #BF1400",
+"<  c #BF1A0D",
+"1  c #BC1814",
+"2  c #BD1817",
+"3  c #BE1818",
+"4  c #A22929",
+"5  c #A42F2F",
+"6  c #CD0000",
+"7  c #C70E00",
+"8  c #D80500",
+"9  c #D90500",
+"0  c #DA0500",
+"q  c #DC0600",
+"w  c #DD0600",
+"e  c #DF0700",
+"r  c #C01200",
+"t  c #C11601",
+"y  c #C91100",
+"u  c #CB100B",
+"i  c #DC120D",
+"p  c #C11B1A",
+"a  c #C11C1B",
+"s  c #C91E1E",
+"d  c #D01813",
+"f  c #D31C17",
+"g  c #D81913",
+"h  c #DC1912",
+"j  c #D91B15",
+"k  c #DB1A15",
+"l  c #DA1B15",
+"z  c #DC1B15",
+"x  c #DC1C17",
+"c  c #D81E1A",
+"v  c #E00700",
+"b  c #E10700",
+"n  c #D42020",
+"m  c #D32424",
+"M  c #E02925",
+"N  c #E0423E",
+"B  c #DA4848",
+"V  c #DE4F4D",
+"C  c #D1554E",
+"Z  c #D35D58",
+"A  c #D15F5A",
+"S  c #DF5F5F",
+"D  c #E34743",
+"F  c #E55D5B",
+"G  c #EA5E5C",
+"H  c #D76059",
+"J  c #DA605E",
+"K  c #E3615F",
+"L  c #DC6D6C",
+"P  c #DE7E7D",
+"I  c #E96764",
+"U  c #E26E6C",
+"Y  c #E16F6E",
+"T  c #E77574",
+"R  c #E67776",
+"E  c #EB7270",
+"W  c #E97472",
+"Q  c #E97876",
+"!  c #E67A79",
+"~  c #E27D7C",
+"^  c #E27E7D",
+"/  c #E57E7D",
+"(  c #EB7A78",
+")  c #ED7A78",
+"_  c #E1807F",
+"`  c #DD9090",
+"'  c #DF9391",
+"]  c #DE9490",
+"[  c #DD9592",
+"{  c #E68483",
+"}  c #E38584",
+"|  c #E38685",
+" . c #E58887",
+".. c #E58C8B",
+"X. c #E78C8B",
+"o. c #E68F8E",
+"O. c #E88988",
+"+. c #E09A9A",
+"@. c #E09D9B",
+"#. c #E2A4A3",
+"$. c #E3A7A7",
+"%. c #E9B5B4",
+"&. c #E9B6B5",
+"*. c #EAB7B7",
+"=. c #EAB9B9",
+"-. c #F7D0CF",
+";. c #F7D3D2",
+":. c #F8D3D2",
+">. c #F9D6D5",
+",. c #F9DDDC",
+"<. c #F9DEDD",
+"1. c #FADFDE",
+"2. c #FAE1E0",
+"3. c #FAE2E1",
+"4. c #FAE2E2",
+"5. c #FBE2E2",
+"6. c #FBE3E2",
+"7. c #FBE6E5",
+"8. c #FBE6E6",
+"9. c #FBE8E8",
+"0. c white",
+"q. c None",
+/* pixels */
+"q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.",
+"q.q.q.q.q.6 m B J B n q.q.q.q.q.",
+"q.q.q.q.s #.&.*.=.%.$.s q.q.q.q.",
+"q.q.q.a +.o.X. .{ { P ` p q.q.q.",
+"q.q.2 @.| X. .! T / ~ L ' 3 q.q.",
+"q.= [ ^ { 9.7.Q W 5.7.Y J [ = q.",
+"q.& A Y T 5.0.5.5.0.1.F V Z & q.",
+"q.% C K G I 5.0.0.5.E ) ) H % q.",
+"q.$ p f M D 1.0.0.,.N i q 7 # q.",
+"q.# ; 8 j :.0.:.;.0.;.j q y # q.",
+"q.# - 8 k :.:.j g -.>.j q > @ q.",
+"q.q.o : e k j e e h x q : o q.q.",
+"q.q.q.. t e q e w w e , . q.q.q.",
+"q.q.q.q.  * u d f d 1 . q.q.q.q.",
+"q.q.q.q.q.X O 4 5 4 + q.q.q.q.q.",
+"q.q.q.q.q.q.q.q.q.q.q.q.q.q.q.q."
+};
diff --git a/mgllab/xpm/right_1.xpm b/mgllab/xpm/right_1.xpm
new file mode 100644
index 0000000..a7b3a67
--- /dev/null
+++ b/mgllab/xpm/right_1.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * right_1_xpm[] = {
+"16 16 3 1",
+".	c None",
+"+	c #7F0000",
+"@	c #FF0000",
+"................",
+"................",
+"........+.......",
+"........++......",
+"........+ at +.....",
+"..+++++++@@+....",
+"..+@@@@@@@@@+...",
+"..+@@@@@@@@@@+..",
+"..+@@@@@@@@@@@+.",
+"..+@@@@@@@@@@+..",
+"..+@@@@@@@@@+...",
+"..+++++++@@+....",
+"........+ at +.....",
+"........++......",
+"........+.......",
+"................"};
diff --git a/mgllab/xpm/rotate.xpm b/mgllab/xpm/rotate.xpm
new file mode 100644
index 0000000..e6b0220
--- /dev/null
+++ b/mgllab/xpm/rotate.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char *rotate_xpm[]={
+"16 16 3 1",
+". c None",
+"# c #000080",
+"a c #8080ff",
+"......#########.",
+"......#aaaaaa#..",
+".......#aaaa##..",
+"..###..#aaaaa#..",
+".#aa#..#aaa#aa#.",
+".#aa#...#a##aa#.",
+"#aa#....#a#.#aa#",
+"#aa#.....#..#aa#",
+"#aa#........#aa#",
+"#aa#........#aa#",
+".#a#........#a#.",
+".#aa#......#aa#.",
+"..#aa##..##aa#..",
+"...#aaa##aaa#...",
+"....##aaaa##....",
+"......####......"};
diff --git a/mgllab/xpm/show_sl.xpm b/mgllab/xpm/show_sl.xpm
new file mode 100644
index 0000000..21e4e90
--- /dev/null
+++ b/mgllab/xpm/show_sl.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * show_sl_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #000000",
+"+	c #007FFF",
+"                ",
+"                ",
+"  ............  ",
+"  . .++++++. .  ",
+"  ...++++++...  ",
+"  . .++++++. .  ",
+"  . .++++++. .  ",
+"  ...++++++...  ",
+"  . .++++++. .  ",
+"  . .++++++. .  ",
+"  ...++++++...  ",
+"  . .++++++. .  ",
+"  . .++++++. .  ",
+"  ...++++++...  ",
+"  . .++++++. .  ",
+"  ............  "};
diff --git a/mgllab/xpm/size.xpm b/mgllab/xpm/size.xpm
new file mode 100644
index 0000000..3a1d846
--- /dev/null
+++ b/mgllab/xpm/size.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * size_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+" .............. ",
+" .     .      . ",
+" .    ...     . ",
+" .     .      . ",
+" .     .      . ",
+" . .   .    . . ",
+" .............. ",
+" . .   .    . . ",
+" .     .      . ",
+" .     .      . ",
+" .     .      . ",
+" .    ...     . ",
+" .     .      . ",
+" .............. "};
diff --git a/mgllab/xpm/squize.xpm b/mgllab/xpm/squize.xpm
new file mode 100644
index 0000000..fa68e6a
--- /dev/null
+++ b/mgllab/xpm/squize.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * squize_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #000000",
+"+	c #7F7F7F",
+"                ",
+"                ",
+"     ......     ",
+"     .    .     ",
+"     .    .     ",
+"  .  .    .  .  ",
+"  +. .    . .+  ",
+"......    ......",
+"  +. .    . .+  ",
+"  .  .    .  .  ",
+"     .    .     ",
+"     .    .     ",
+"     .    .     ",
+"     ......     ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/stop.xpm b/mgllab/xpm/stop.xpm
new file mode 100644
index 0000000..028f468
--- /dev/null
+++ b/mgllab/xpm/stop.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char * stop_xpm[] = {
+"16 16 4 1",
+" 	c None",
+".	c #770000",
+"+	c #FF0000",
+"@	c #FFFFFF",
+"                ",
+"     ......     ",
+"    .++++++.    ",
+"   .++++++++.   ",
+"  .++++++++++.  ",
+" .+++@@++@@+++. ",
+" .+++@@@@@@+++. ",
+" .++++@@@@++++. ",
+" .++++@@@@++++. ",
+" .+++@@@@@@+++. ",
+" .+++@@++@@+++. ",
+"  .++++++++++.  ",
+"   .++++++++.   ",
+"    .++++++.    ",
+"     ......     ",
+"                "};
diff --git a/mgllab/xpm/style.xpm b/mgllab/xpm/style.xpm
new file mode 100644
index 0000000..9125d5f
--- /dev/null
+++ b/mgllab/xpm/style.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * style_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #FF0000",
+"q	c #7F0000",
+"                ",
+"                ",
+"                ",
+"   qqq   qqq    ",
+"   q.q   q.q    ",
+"   q.q   q.q    ",
+"   q.q   q.q    ",
+"    q     q     ",
+"    q     q     ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/system-file-manager.xpm b/mgllab/xpm/system-file-manager.xpm
new file mode 100644
index 0000000..6c858df
--- /dev/null
+++ b/mgllab/xpm/system-file-manager.xpm
@@ -0,0 +1,44 @@
+/* XPM */
+static const char *system_file_manager_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 22 1 ",
+"  c #5F5B29",
+". c #686326",
+"X c #6C672B",
+"o c #736622",
+"O c #7E6920",
+"+ c #C17D11",
+"@ c #DBB676",
+"# c #D0B782",
+"$ c #D2BA85",
+"% c #D5BC88",
+"& c #D7BF8C",
+"* c #E2BF82",
+"= c #DDC596",
+"- c #DFC696",
+"; c #DFC796",
+": c #E3C082",
+"> c #E3CB9D",
+", c #E3CC9E",
+"< c #E4CC9E",
+"1 c #E4CC9F",
+"2 c #E9D1A6",
+"3 c None",
+/* pixels */
+"33............33",
+"3.2<>>>>>>>>>>.3",
+".;;;;;;;*;;;>=*.",
+".;O..........O=.",
+".=.++++++++++.$X",
+".=.++++++++++.&X",
+".=.++++..++++.&X",
+".=O..........o$.",
+".>++++++++++++&.",
+".&O..........O$.",
+".%.++++++++++.$.",
+".&.++++++++++.$.",
+".%.++++..++++.$.",
+".$O...........$.",
+".@$$$$#$####$#$.",
+" .XXXXXX........"
+};
diff --git a/mgllab/xpm/tab-close.xpm b/mgllab/xpm/tab-close.xpm
new file mode 100644
index 0000000..bf1d497
--- /dev/null
+++ b/mgllab/xpm/tab-close.xpm
@@ -0,0 +1,91 @@
+/* XPM */
+static const char *tab_close_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 69 1 ",
+"  c #741F1E",
+". c #9A2E29",
+"X c #9E2D2A",
+"o c #9A342B",
+"O c #9D362E",
+"+ c #BA2F22",
+"@ c #A1342A",
+"# c #A93A37",
+"$ c #B73834",
+"% c #B63E3A",
+"& c #C40201",
+"* c #C50302",
+"= c #E10202",
+"- c #E10404",
+"; c #C5281A",
+": c #C32C1C",
+"> c #CE2E23",
+", c #C32F2F",
+"< c #D22C24",
+"1 c #C23030",
+"2 c #EE2220",
+"3 c #F02220",
+"4 c #C04734",
+"5 c #C04D3B",
+"6 c #AC6765",
+"7 c #B86261",
+"8 c #BE7675",
+"9 c #CF4E4D",
+"0 c #C85242",
+"q c #CA574C",
+"w c #CB5A4D",
+"e c #C55950",
+"r c #D05151",
+"t c #CE6C64",
+"y c #DB6A62",
+"u c #D46E68",
+"i c #D3716B",
+"p c #DE726C",
+"a c #E8706E",
+"s c #E97675",
+"d c #C3817E",
+"f c #D48C8A",
+"g c #CA9A9A",
+"h c #D39E9B",
+"j c #E0B5B4",
+"k c #DEDADA",
+"l c #DFDFDF",
+"z c #E6C3C3",
+"x c #E7D5D7",
+"c c #EDD2D3",
+"v c gray88",
+"b c #E2E2E2",
+"n c #E6E6E6",
+"m c gray91",
+"M c #E9E9E9",
+"N c #EAEAEA",
+"B c #ECECEC",
+"V c #EDECEC",
+"C c #EEEEEE",
+"Z c #F4F0F0",
+"A c #F6F2F3",
+"S c #F8F6F7",
+"D c #FBFAFA",
+"F c #FBFBFB",
+"G c #FCFAFA",
+"H c gray99",
+"J c #FDFDFD",
+"K c white",
+"L c None",
+/* pixels */
+"LLLLLLLLLLLLLLLL",
+"LLLLLLLLLLLLLLLL",
+"LLLLLLLLMKKKKKML",
+"LLLLLLLLKlllllKL",
+"LLLLLLLLKvHDDlKL",
+"LKKKKKKKKvDHKlKL",
+"LKbbbbbbbbHHKbKL",
+"LxkKKDZHHHHDDnKL",
+"Li7ZSfucHHHHHmKL",
+"+ap68ystHHHHKMKL",
+"L09eqrwjKHHKKCKL",
+"Lz4,,5gCCCCCCCKL",
+"Lh:**;dGKKKKKKKL",
+"L>=@o-< LLLLLLLL",
+"O2$LL%3#LLLLLLLL",
+"L.LLLLXLLLLLLLLL"
+};
diff --git a/mgllab/xpm/table.xpm b/mgllab/xpm/table.xpm
new file mode 100644
index 0000000..43b33a4
--- /dev/null
+++ b/mgllab/xpm/table.xpm
@@ -0,0 +1,24 @@
+/* XPM */
+static const char * table_xpm[] = {
+"16 16 4 1",
+" 	c None",
+"#	c #000000",
+"o	c #777777",
+".	c #FFFFFF",
+"                ",
+" ###############",
+" #ooo#oooo#oooo#",
+" #ooo#oooo#oooo#",
+" ###############",
+" #ooo#....#....#",
+" #ooo#....#....#",
+" ###############",
+" #ooo#....#....#",
+" #ooo#....#....#",
+" ###############",
+" #ooo#....#....#",
+" #ooo#....#....#",
+" ###############",
+"                ",
+"                "};
+
diff --git a/mgllab/xpm/text-csv.xpm b/mgllab/xpm/text-csv.xpm
new file mode 100644
index 0000000..ffbf3e3
--- /dev/null
+++ b/mgllab/xpm/text-csv.xpm
@@ -0,0 +1,112 @@
+/* XPM */
+static const char *text_csv_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 90 1 ",
+"  c gray14",
+". c #252626",
+"X c gray16",
+"o c #2A2A2A",
+"O c #38332B",
+"+ c #39342B",
+"@ c #3A3A3A",
+"# c gray24",
+"$ c #3F3F3F",
+"% c gray25",
+"& c gray33",
+"* c #4F96FF",
+"= c #5195FF",
+"- c #5395FF",
+"; c #5096FF",
+": c #5296FF",
+"> c #5396FF",
+", c #5397FF",
+"< c #569DFF",
+"1 c #5899FF",
+"2 c #589BFF",
+"3 c #5CA3FF",
+"4 c #5DA3FF",
+"5 c #63A1FE",
+"6 c #8C8B8B",
+"7 c #979089",
+"8 c #9A948C",
+"9 c #959494",
+"0 c #959595",
+"q c #9F9F9F",
+"w c #A0A0A0",
+"e c gray65",
+"r c #A9A9A9",
+"t c #B2B2B2",
+"y c gray70",
+"u c #B6B6B6",
+"i c gray72",
+"p c #B9B9B9",
+"a c gray74",
+"s c gray",
+"d c #C7C2BB",
+"f c #C5C3BF",
+"g c #CEC7BA",
+"h c #C9C4BD",
+"j c #CAC5BD",
+"k c #CEC7BC",
+"l c #AAD3FF",
+"z c #B2D7FF",
+"x c #BCD9FF",
+"c c #C0C0C0",
+"v c #C1C1C1",
+"b c #C1C1C2",
+"n c gray76",
+"m c gray77",
+"M c #C6C7C7",
+"N c #C9C7C7",
+"B c #CFCAC3",
+"V c #C8C8C8",
+"C c #CACACA",
+"Z c #CBCBCB",
+"A c #CDCDCD",
+"S c #CECDCD",
+"D c #D4D1CE",
+"F c gray82",
+"G c #D1D2D2",
+"H c #D9D7D7",
+"J c gainsboro",
+"K c #DEDCDC",
+"L c gray87",
+"P c #C3DDFF",
+"I c #EBEAEA",
+"U c gray92",
+"Y c #ECEBEB",
+"T c #ECECEC",
+"R c #EEEEEE",
+"E c #F5EFE7",
+"W c #F6F0E8",
+"Q c #FFFDED",
+"! c gray95",
+"~ c #F4F3F3",
+"^ c #F6F6F6",
+"/ c #FFF9F1",
+"( c #FFFFF3",
+") c gray98",
+"_ c #FCFBFA",
+"` c #FFFFF9",
+"' c gray99",
+"] c #FDFDFD",
+"[ c white",
+"{ c None",
+/* pixels */
+"{{{{{{{{{{{{{{{{",
+"{{[[[[[[[[[[[[{{",
+"{{[6Mcj*>>*gfS{{",
+"{{[_j/Q:PP1zlD{{",
+"{{[7<>>5>>3gfF{{",
+"{{[`>xx>([O[[Z{{",
+"{{[82xx>[[@[[S{{",
+"{{[[>::3O@&#ZF{{",
+"{{[0BEWf[[%$)S{{",
+"{{[[cTTaItqptT{{",
+"{{[0ZSSae[[[~{{{",
+"{{[[cTTpq[RHo{{{",
+"{{[0ZIIur[Ko{{{{",
+"{{[[cccmN^.{{{{{",
+"{{[K[[[!J {{{{{{",
+"{{{{{{{{{{{{{{{{"
+};
diff --git a/mgllab/xpm/text-field.xpm b/mgllab/xpm/text-field.xpm
new file mode 100644
index 0000000..7cb0901
--- /dev/null
+++ b/mgllab/xpm/text-field.xpm
@@ -0,0 +1,25 @@
+/* XPM */
+static const char *text_field_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 3 1 ",
+"  c black",
+". c #8B8B8B",
+"X c None",
+/* pixels */
+"XXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXX",
+"XXX     X....XXX",
+"XXXXX XXXXXXXXXX",
+"XXXXX XXXXXXXXXX",
+"XXXXX XXX....XXX",
+"XXXXX XXXXXXXXXX",
+"XXXXXXXXXXXXXXXX",
+"XXX..........XXX",
+"XXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXX"
+};
diff --git a/mgllab/xpm/text-plain.xpm b/mgllab/xpm/text-plain.xpm
new file mode 100644
index 0000000..598558b
--- /dev/null
+++ b/mgllab/xpm/text-plain.xpm
@@ -0,0 +1,109 @@
+/* XPM */
+static const char *text_plain_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 87 1 ",
+"  c gray14",
+". c #252626",
+"X c gray16",
+"o c #2A2A2A",
+"O c gray52",
+"+ c gray53",
+"@ c #8A8989",
+"# c #8D8B8B",
+"$ c #908F8F",
+"% c gray57",
+"& c #929292",
+"* c #A0A0A0",
+"= c gray68",
+"- c #B0AFAF",
+"; c #B1B1B1",
+": c gray71",
+"> c gray78",
+", c #C8C7C7",
+"< c #C9C8C8",
+"1 c #CAC9C9",
+"2 c #CACACA",
+"3 c #CBCACA",
+"4 c #CCCACA",
+"5 c gray80",
+"6 c #CDCCCC",
+"7 c #CDCDCD",
+"8 c #CECECE",
+"9 c #CFCECE",
+"0 c gray81",
+"q c #D1CECE",
+"w c #D0CFCF",
+"e c #D0D0D0",
+"r c #D0D1D1",
+"t c gray82",
+"y c #D2D1D1",
+"u c LightGray",
+"i c gray84",
+"p c #D9D7D7",
+"a c #D8D8D8",
+"s c #D9D8D8",
+"d c #DADADA",
+"f c #DBDADA",
+"g c gray86",
+"h c #DDDBDB",
+"j c gainsboro",
+"k c #DDDDDD",
+"l c #DEDCDC",
+"z c gray87",
+"x c #E0DFDF",
+"c c #E1E0E0",
+"v c #E2E2E2",
+"b c #E5E4E4",
+"n c gray90",
+"m c #E9E9E9",
+"M c #EAEAEA",
+"N c #ECECEC",
+"B c #EFEDED",
+"V c #EEEEEE",
+"C c #EEEFEF",
+"Z c #EFEFEF",
+"A c #F0EFEF",
+"S c #F1EFEF",
+"D c #F2F0F0",
+"F c #F2F1F1",
+"G c #F3F1F1",
+"H c #F4F3F3",
+"J c #F4F4F4",
+"K c #F6F5F5",
+"L c #F6F6F6",
+"P c #F6F7F7",
+"I c gray97",
+"U c #F8F7F7",
+"Y c #F8F8F8",
+"T c #F9F8F8",
+"R c #F9F9F9",
+"E c #FAF9F9",
+"W c gray98",
+"Q c #FBFAFA",
+"! c #FBFBFB",
+"~ c #FCFBFB",
+"^ c gray99",
+"/ c #FDFCFC",
+"( c #FDFDFD",
+") c #FEFDFD",
+"_ c #FEFEFE",
+"` c white",
+"' c None",
+/* pixels */
+"''''''''''''''''",
+"''````````````''",
+"''`@Gh994q>4gS''",
+"''`USSGGGGKGG`''",
+"''`#g9,t252g2C''",
+"''`~KKEEEEEEE`''",
+"''`$g92tr9tvuK''",
+"''``E````E!YK`''",
+"''`%brrjzz2i2M''",
+"''``E``!M;==:M''",
+"''`%nvz9O```G'''",
+"''``~`!J*`Cpo'''",
+"''`%n9gaO`zo''''",
+"''``EEKN2K.'''''",
+"''`z``ECj ''''''",
+"''''''''''''''''"
+};
diff --git a/mgllab/xpm/text-x-generic.xpm b/mgllab/xpm/text-x-generic.xpm
new file mode 100644
index 0000000..7dd65de
--- /dev/null
+++ b/mgllab/xpm/text-x-generic.xpm
@@ -0,0 +1,43 @@
+/* XPM */
+static const char *text_x_generic_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 21 1 ",
+"  c #818181",
+". c #959595",
+"X c gray60",
+"o c gray77",
+"O c #C5C5C5",
+"+ c #C6C6C6",
+"@ c gray78",
+"# c #C8C8C8",
+"$ c #EDEDE5",
+"% c #EDEDE6",
+"& c #EAEAEA",
+"* c gray92",
+"= c #ECECEC",
+"- c gray93",
+"; c #EEEEEE",
+": c #EFEFEF",
+"> c gray94",
+", c #F1F1F1",
+"< c gray95",
+"1 c white",
+"2 c None",
+/* pixels */
+"X            222",
+" 111111111111 22",
+" 1=&==&====>1 22",
+" 1&oooo#oo#>1 22",
+" 1&=&=====>>1 22",
+" 1=o#oo##o#>1 22",
+" 1&=====%==>1 22",
+" 1=oo#o>:%=>1 22",
+" 1====>=>:>>1 22",
+" 1=##o#####>1 22",
+" 1===>=>>>><1 22",
+" 1=o#####>><1 22",
+" 1===>>>>>>>1 22",
+" 111111111111 22",
+".            .22",
+"2222222222222222"
+};
diff --git a/mgllab/xpm/text.xpm b/mgllab/xpm/text.xpm
new file mode 100644
index 0000000..56317c0
--- /dev/null
+++ b/mgllab/xpm/text.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * text_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"  ............  ",
+"  ............  ",
+"  .    ..    .  ",
+"       ..       ",
+"       ..       ",
+"       ..       ",
+"       ..       ",
+"       ..       ",
+"       ..       ",
+"       ..       ",
+"       ..       ",
+"       ..       ",
+"       ..       ",
+"      ....      ",
+"                "};
diff --git a/mgllab/xpm/tiles.xpm b/mgllab/xpm/tiles.xpm
new file mode 100644
index 0000000..505dadd
--- /dev/null
+++ b/mgllab/xpm/tiles.xpm
@@ -0,0 +1,132 @@
+/* XPM */
+static const char * tiles_xpm[] = {
+"16 16 113 2",
+"  	c None",
+". 	c #00D9FB",
+"+ 	c #00FEC7",
+"@ 	c #7DFF1E",
+"# 	c #DBDF08",
+"$ 	c #EAC004",
+"% 	c #E5D403",
+"& 	c #FF5D00",
+"* 	c #FC1600",
+"= 	c #FC2500",
+"- 	c #00EAE9",
+"; 	c #00E9CA",
+"> 	c #05F1B1",
+", 	c #03F8B5",
+"' 	c #00FFC7",
+") 	c #00FFD6",
+"! 	c #FF5900",
+"~ 	c #FD0600",
+"{ 	c #FA0000",
+"] 	c #FF2600",
+"^ 	c #00A1FF",
+"/ 	c #00CEFF",
+"( 	c #00FEE9",
+"_ 	c #00FF71",
+": 	c #80FF12",
+"< 	c #CFFF07",
+"[ 	c #FF7000",
+"} 	c #FF5800",
+"| 	c #FE7200",
+"1 	c #F9B100",
+"2 	c #00EDF2",
+"3 	c #1AFF56",
+"4 	c #C1FA00",
+"5 	c #FDD600",
+"6 	c #FFA700",
+"7 	c #FF9200",
+"8 	c #F3D400",
+"9 	c #A0FD21",
+"0 	c #21F996",
+"a 	c #ECF100",
+"b 	c #FFC900",
+"c 	c #FF9B00",
+"d 	c #FF9300",
+"e 	c #FDA700",
+"f 	c #AEFF05",
+"g 	c #00F9C7",
+"h 	c #00AAFF",
+"i 	c #0052FF",
+"j 	c #FDCA00",
+"k 	c #E6DE00",
+"l 	c #FCA900",
+"m 	c #ADFF00",
+"n 	c #00FCC3",
+"o 	c #00C8FF",
+"p 	c #0089FF",
+"q 	c #0079FE",
+"r 	c #0094FF",
+"s 	c #00CDFF",
+"t 	c #93E71F",
+"u 	c #6BF55F",
+"v 	c #57FA76",
+"w 	c #3EFF80",
+"x 	c #1BFF89",
+"y 	c #00FF84",
+"z 	c #00FF95",
+"A 	c #F52C00",
+"B 	c #F03200",
+"C 	c #F23E00",
+"D 	c #FB5B00",
+"E 	c #F39E00",
+"F 	c #D4EA00",
+"G 	c #3BFF31",
+"H 	c #00FCD9",
+"I 	c #00C2FF",
+"J 	c #FE5500",
+"K 	c #E70200",
+"L 	c #B30000",
+"M 	c #9C0000",
+"N 	c #A30000",
+"O 	c #C30000",
+"P 	c #F61400",
+"Q 	c #FF9600",
+"R 	c #99FD04",
+"S 	c #01FDD5",
+"T 	c #00A6FF",
+"U 	c #0054FF",
+"V 	c #0037FF",
+"W 	c #EC0400",
+"X 	c #BD0000",
+"Y 	c #A20000",
+"Z 	c #A00000",
+"` 	c #B70000",
+" .	c #EA0100",
+"..	c #FF5600",
+"+.	c #EDE300",
+"@.	c #0CF5CC",
+"#.	c #06D2E4",
+"$.	c #09CEE0",
+"%.	c #18E5C1",
+"&.	c #4AFF6C",
+"*.	c #C1EB09",
+"=.	c #FF7200",
+"-.	c #FE4F00",
+";.	c #F73E00",
+">.	c #F03A00",
+",.	c #F03800",
+"'.	c #F63A00",
+").	c #E2BD00",
+"!.	c #D0C10A",
+"~.	c #CDC110",
+"{.	c #DFBB02",
+"].	c #F7B100",
+"^.	c #FF9C00",
+"                                ",
+"                                ",
+"            . + @ # $ %         ",
+"& * =           - ; > , ' )     ",
+"! ~ { ]             ^ / ( _ : < ",
+"[ } | 1               2 3 4 5 6 ",
+"7 8 9 0                 a b c d ",
+"e f g h i                   j k ",
+"l m n o p q r s                 ",
+"      t u v w x y z             ",
+"    A B C D E F G H I           ",
+"J K L M N O P Q R S T U V       ",
+"} W X Y Z `  ...+.  @.#.$.%.&.*.",
+"=.-.;.>.,.'.        ).!.~.{.].^.",
+"                                ",
+"                                "};
diff --git a/mgllab/xpm/tools-wizard.xpm b/mgllab/xpm/tools-wizard.xpm
new file mode 100644
index 0000000..f02794d
--- /dev/null
+++ b/mgllab/xpm/tools-wizard.xpm
@@ -0,0 +1,82 @@
+/* XPM */
+static const char *tools_wizard_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 60 1 ",
+"  c black",
+". c #020202",
+"X c #060401",
+"o c #040404",
+"O c gray3",
+"+ c #0B0B0B",
+"@ c #0C0C0C",
+"# c #0E0E0E",
+"$ c #140B06",
+"% c #101010",
+"& c gray12",
+"* c #2B2B2A",
+"= c gray17",
+"- c #353535",
+"; c #632B08",
+": c #783500",
+"> c #444444",
+", c #6F6D6C",
+"< c #777777",
+"1 c #A23B00",
+"2 c #904513",
+"3 c #DF6D02",
+"4 c #F07902",
+"5 c #EA6016",
+"6 c #F3741A",
+"7 c #EE7A2D",
+"8 c #E67435",
+"9 c #EB7331",
+"0 c #8C6B50",
+"q c #BE910C",
+"w c #F88903",
+"e c #EC9E0F",
+"r c #F89505",
+"t c #F99C06",
+"y c #EC8618",
+"u c #F69711",
+"i c #FE9713",
+"p c #FEB809",
+"a c #FDAD10",
+"s c #ED8021",
+"d c #F69A2A",
+"f c #EE8731",
+"g c #C5A429",
+"h c #F5CE00",
+"j c #FCDD02",
+"k c #FED20A",
+"l c #F9C41E",
+"z c #FFC91E",
+"x c #FED418",
+"c c #FEC027",
+"v c #FEC327",
+"b c #FBDD21",
+"n c #F2C634",
+"m c #FEC439",
+"M c #FEC23F",
+"N c #FFE923",
+"B c #E48350",
+"V c #CACACA",
+"C c #D5D5D5",
+"Z c None",
+/* pixels */
+"ZZZZZZZZZZZZZZZZ",
+"ZZZZZZZX#ZmzkjZZ",
+"ZZZZZ1Z,VZZZZhNZ",
+"ZZw3ZZZ<CZZZZZbZ",
+"ZeuZ8BZZ&>ZZZlxZ",
+"qMZZZZZZ$*ZrapZZ",
+"gvZZZZZZ;:4itZZZ",
+"Znvd7ys6520ZZZZZ",
+"ZZZZfZZZZO*ZZZZZ",
+"ZZZZZZZZZ%.ZZZZZ",
+"ZZZZZZZZZZ.-Z9ZZ",
+"ZZZZZZZZZZoOZ9ZZ",
+"ZZZZZZZZZZZ.OZZZ",
+"ZZZZZZZZZZZ.#ZZZ",
+"ZZZZZZZZZZZ..ZZZ",
+"ZZZZZZZZZZZZ.ZZZ"
+};
diff --git a/mgllab/xpm/tran.xpm b/mgllab/xpm/tran.xpm
new file mode 100644
index 0000000..29fa1ee
--- /dev/null
+++ b/mgllab/xpm/tran.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char * tran_xpm[] = {
+"16 16 4 1",
+" 	c None",
+".	c #000000",
+"+	c #FF0000",
+"@	c #0000FF",
+"                ",
+"                ",
+" ......++++++++ ",
+" .    .       + ",
+" . . ..+ + + ++ ",
+" .    .       + ",
+" . . ..+ + + ++ ",
+" .++++.++++++++ ",
+" . . ..         ",
+" .    .      @  ",
+" . . ..     @@@ ",
+" .    .      @  ",
+" . . ..      @  ",
+" .    .    @@   ",
+" . . .. @@@     ",
+" ......         "};
diff --git a/mgllab/xpm/transform-crop.xpm b/mgllab/xpm/transform-crop.xpm
new file mode 100644
index 0000000..ff9ac59
--- /dev/null
+++ b/mgllab/xpm/transform-crop.xpm
@@ -0,0 +1,133 @@
+/* XPM */
+static const char *transform_crop_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 111 2 ",
+"   c #2C3335",
+".  c #353A3C",
+"X  c #3B3F41",
+"o  c #414244",
+"O  c #414F5E",
+"+  c #6E6E6C",
+"@  c #7B7C79",
+"#  c #7A7D7F",
+"$  c #807777",
+"%  c #0069FF",
+"&  c #1271FE",
+"*  c #1371FE",
+"=  c #1271FF",
+"-  c #6B8CBE",
+";  c #5F87C2",
+":  c #5F88C4",
+">  c #6088C4",
+",  c #6089C4",
+"<  c #6289C5",
+"1  c #6289C6",
+"2  c #638AC6",
+"3  c #638AC7",
+"4  c #638BC7",
+"5  c #688DC3",
+"6  c #648BC8",
+"7  c #5DA1FF",
+"8  c #67A3FF",
+"9  c #60A4FF",
+"0  c #67A4FE",
+"q  c #68A5FF",
+"w  c #68A6FF",
+"e  c #828484",
+"r  c #858787",
+"t  c #888586",
+"y  c #8C8686",
+"u  c #8B8989",
+"i  c #8F8F8D",
+"p  c #938C8C",
+"a  c #90918E",
+"s  c #91908F",
+"d  c #949492",
+"f  c #9C9996",
+"g  c #9E9A99",
+"h  c #A1A29F",
+"j  c #ADA59E",
+"k  c #9EA2A3",
+"l  c #A2A0A0",
+"z  c #A9A3A3",
+"x  c #ACADAB",
+"c  c #AEAEAE",
+"v  c #B3ACA6",
+"b  c #B1ABAA",
+"n  c #B2AEAE",
+"m  c #B4AFAC",
+"M  c #B5AFAF",
+"N  c #B7B2B2",
+"B  c #B8B2B1",
+"V  c #B9B4B2",
+"C  c #B9B5B5",
+"Z  c #B9B6B4",
+"A  c #BCB8B8",
+"S  c #BFBABA",
+"D  c #BFBDBD",
+"F  c #C0BBBB",
+"G  c #C1BCBC",
+"H  c #C2BFBF",
+"J  c #C3BFBF",
+"K  c #C3C1C1",
+"L  c #C7C3C3",
+"P  c #C3C4C4",
+"I  c #CACACA",
+"U  c #CDCBCB",
+"Y  c #CFCDC8",
+"T  c #CECDCC",
+"R  c #D0CDCE",
+"E  c #D4CECF",
+"W  c #D6D0CF",
+"Q  c #D8D0CB",
+"!  c #D3D3D2",
+"~  c #D7D1D0",
+"^  c gray84",
+"/  c #D7D6D6",
+"(  c #D8D2D1",
+")  c #D8D3D1",
+"_  c #D9D5D5",
+"`  c #D9D8D8",
+"'  c #D9D9DA",
+"]  c #DCDADA",
+"[  c gray87",
+"{  c #E0D6CB",
+"}  c #E0DEDE",
+"|  c #E0E1E1",
+" . c #E3E1E3",
+".. c #E3E2E2",
+"X. c #E4E2E2",
+"o. c #E7E6E7",
+"O. c #EFEFEF",
+"+. c #F1F1F1",
+"@. c #F1F2F2",
+"#. c gray95",
+"$. c #F3F3F3",
+"%. c #F7F3F0",
+"&. c #F7F7F6",
+"*. c gray97",
+"=. c #F9F7F4",
+"-. c #FBFBFB",
+";. c #FDFDFD",
+":. c #FFFFFD",
+">. c #FEFEFE",
+",. c white",
+"<. c None",
+/* pixels */
+"<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.",
+"<.<.<.<.<.<.<.<.<.<.<.<.o.] F <.",
+"8 w <.<.<.<.<.<.<.<.<...} G S <.",
+"& % { : W 2 V 2 g 5 _ ..G C K <.",
+"<.- ,.,.&.=.$.%.$.E X.z n G I <.",
+"<.( ,.,.-.&.$.$.k # b $ p P c <.",
+"<.; ,.,.,.,.-.` r   o u l r <.<.",
+"<.( ,.,.,.,.O.S M y . X e <.<.<.",
+"<.; ,.,.,.-./ U G C + O <.<.<.<.",
+"<.~ ,.,.-...' T i @ ! V <.<.<.<.",
+"<.; ,.,./ T d a [ ,.,.2 <.<.<.<.",
+"<.( ,.L a l O.,.,.,.,.n <.<.<.<.",
+"<.2 Y x &.,.,.,.,.,.,.2 <.<.<.<.",
+"<.Q ,.,.,.,.,.,.,.,.,.v <.<.<.<.",
+"0 7 E - ~ : B 3 f 2 j 9 w <.<.<.",
+"& & <.<.<.<.<.<.<.<.<.& & <.<.<."
+};
diff --git a/mgllab/xpm/transform-move.xpm b/mgllab/xpm/transform-move.xpm
new file mode 100644
index 0000000..38c0952
--- /dev/null
+++ b/mgllab/xpm/transform-move.xpm
@@ -0,0 +1,86 @@
+/* XPM */
+static const char *transform_move_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 64 1 ",
+"  c #0C0D0C",
+". c #121312",
+"X c #191A19",
+"o c #242525",
+"O c #2D2D2D",
+"+ c #2F302F",
+"@ c #333332",
+"# c #343534",
+"$ c #3A3A3A",
+"% c #3E3F3E",
+"& c #3F403F",
+"* c #444544",
+"= c #464845",
+"- c #474847",
+"; c #4F514E",
+": c gray32",
+"> c #5A5A5A",
+", c #5C5D5C",
+"< c #5F615E",
+"1 c #646564",
+"2 c #656764",
+"3 c #666765",
+"4 c #686868",
+"5 c #696B69",
+"6 c #6C6E6C",
+"7 c #717270",
+"8 c #727272",
+"9 c #797B78",
+"0 c #7E7F7C",
+"q c #828281",
+"w c #888A87",
+"e c #8A8B8A",
+"r c #8B8D89",
+"t c #8B8C8A",
+"y c #9D9F9C",
+"u c #A0A19F",
+"i c #A3A5A2",
+"p c #A5A6A4",
+"a c #A5A7A4",
+"s c #ACAEAA",
+"d c #B8B9B7",
+"f c #B9BBB7",
+"g c #BABBB8",
+"h c #BEC0BC",
+"j c #C3C5C2",
+"k c #C4C6C2",
+"l c #CACCC8",
+"z c #CED0CB",
+"x c #D3D5D2",
+"c c #D8DAD7",
+"v c #DCDDDA",
+"b c #DCDDDB",
+"n c #DFE1DD",
+"m c #E0E2DE",
+"M c #E0E3DE",
+"N c #E8ECE5",
+"B c #E9ECE6",
+"V c #E9EDE6",
+"C c #ECEFE8",
+"Z c #EEF1EB",
+"A c #F2F5EF",
+"S c #F3F6EF",
+"D c #F6F9F4",
+"F c None",
+/* pixels */
+"FFFFFFFFFFFFFFFF",
+"FFFFFFF28FFFFFFF",
+"FFFFFFFhnOFFFFFF",
+"FFFFFF0CVpFFFFFF",
+"FFFFFF=fc2FFFFFF",
+"FFFFFFF at -FFFFFFF",
+"FF.t5FFFFFF*p&FF",
+"F>kDb*F2iFFfAMe ",
+"F2lZx%F6sFFyAzqF",
+"FFXt<FFFFFF#w+FF",
+"FFFFFFF$:FFFFFFF",
+"FFFFFF;jM8FFFFFF",
+"FFFFFF9VVuFFFFFF",
+"FFFFFFFgboFFFFFF",
+"FFFFFFF,4FFFFFFF",
+"FFFFFFFFFFFFFFFF"
+};
diff --git a/mgllab/xpm/transform-rotate.xpm b/mgllab/xpm/transform-rotate.xpm
new file mode 100644
index 0000000..e0bc67a
--- /dev/null
+++ b/mgllab/xpm/transform-rotate.xpm
@@ -0,0 +1,41 @@
+/* XPM */
+static const char *transform_rotate_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 19 1 ",
+"  c #4D308B",
+". c #563B91",
+"X c #583D92",
+"o c #5D4395",
+"O c #5E4397",
+"+ c #604796",
+"@ c #624898",
+"# c #654B9C",
+"$ c #674E9D",
+"% c #6C53A1",
+"& c #6F56A3",
+"* c #7159A4",
+"= c #735BA6",
+"- c #765EA8",
+"; c #7861A9",
+": c #7D66AD",
+"> c #8069AF",
+", c #826CB0",
+"< c None",
+/* pixels */
+"<<<<<<<<<<<<<<<<",
+"<<<<<<:*$<<<<<<<",
+"<<<<<>-%@++<<<<<",
+"<<<<,;&#O++++<<<",
+"<<<<<*$OX+++++<<",
+"<<<<<<<. <<+++<<",
+"<<<<<<<<<<<++++<",
+"<<<<<<<<<<<<+++<",
+"<<<<<<<<<<<<+++<",
+"<<<<<<<<<<<<+++<",
+"<<<<<<<<<<<++++<",
+"<<<<<<<<<<<+++<<",
+"<<<<++++++++++<<",
+"<<<++++++++++<<<",
+"<<<<<++++++<<<<<",
+"<<<<<<<<<<<<<<<<"
+};
diff --git a/mgllab/xpm/transform-scale.xpm b/mgllab/xpm/transform-scale.xpm
new file mode 100644
index 0000000..6c90eb0
--- /dev/null
+++ b/mgllab/xpm/transform-scale.xpm
@@ -0,0 +1,80 @@
+/* XPM */
+static const char *transform_scale_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 58 1 ",
+"  c #0A68EE",
+". c #136FEF",
+"X c #146EEE",
+"o c #1F76F0",
+"O c #1271FF",
+"+ c #1371FF",
+"@ c #2077EF",
+"# c #307FF0",
+"$ c #2F80EF",
+"% c #3F88EE",
+"& c #2F80F0",
+"* c #7193C6",
+"= c #609EF5",
+"- c #64A2FF",
+"; c #65A2FF",
+": c #77ACF7",
+"> c #9B9CA3",
+", c #A0A1A7",
+"< c #A4A5AB",
+"1 c #A4A5AC",
+"2 c #AAABB0",
+"3 c #AFB1B4",
+"4 c #AFB1B6",
+"5 c #88A0C7",
+"6 c #92A7C5",
+"7 c #BABBC1",
+"8 c #8FBBF9",
+"9 c #A5C9F9",
+"0 c #B3D1FA",
+"q c #BCD6F9",
+"w c #C4C5CB",
+"e c #DBE6F6",
+"r c #D6E4F8",
+"t c #D1E3FC",
+"y c #D8E7FD",
+"u c #DEEBFC",
+"i c #E4E4E4",
+"p c #E7E7E7",
+"a c #EAEAEA",
+"s c gray92",
+"d c gray93",
+"f c #EEEEEE",
+"g c #EFEFEF",
+"h c #E3E9F2",
+"j c #E1EAF7",
+"k c #E5ECF5",
+"l c #E2ECFA",
+"z c #E4EEFC",
+"x c gray94",
+"c c gray95",
+"v c #F3F3F3",
+"b c #F4F4F4",
+"n c gray96",
+"m c #F6F6F7",
+"M c #FDFDFD",
+"N c #FEFEFE",
+"B c white",
+"V c None",
+/* pixels */
+";;VVVVVVVVVVV;;V",
+"++7*1*,*2*V*V++V",
+"Vwggaaapp3VVVVVV",
+"V*mqhgggv3VVV*VV",
+"VwBl0kvvm3VVVVVV",
+"V*BBl9jmg3VVV*VV",
+"VwBBBu8ev3VVVVVV",
+"V*BBBBy:r3VVV*VV",
+"VwBBBBBt=6V&VVVV",
+"V*731>,<5%#@V*VV",
+"VVVVVVVVV&oXVVVV",
+"V*VVVVVV$@. V*VV",
+"VVVVVVVVVVVVVVVV",
+";-V*V*V*V*V*V;;V",
+"++VVVVVVVVVVV++V",
+"VVVVVVVVVVVVVVVV"
+};
diff --git a/mgllab/xpm/udav.xpm b/mgllab/xpm/udav.xpm
new file mode 100644
index 0000000..714a7b3
--- /dev/null
+++ b/mgllab/xpm/udav.xpm
@@ -0,0 +1,416 @@
+/* XPM */
+static const char *udav_xpm[]={
+"64 64 349 2",
+"Qt c None",
+"#n c #000080",
+"#h c #010180",
+"#y c #010181",
+"#s c #020281",
+"#c c #020282",
+"dg c #030382",
+".8 c #030383",
+"#r c #040483",
+"#m c #040484",
+"#g c #050584",
+"#M c #050585",
+"#q c #060685",
+"a. c #060686",
+"#p c #070786",
+"ck c #070787",
+"aj c #080887",
+"bm c #080888",
+"aK c #090988",
+"a4 c #090989",
+"aJ c #0a0a89",
+"## c #0a0a8a",
+"#G c #0b0b8a",
+"cx c #0b0b8b",
+"b7 c #0c0c8b",
+"#z c #0c0c8c",
+"b6 c #0d0d8c",
+"b8 c #0d0d8d",
+"#l c #0e0e8d",
+"cj c #0e0e8e",
+"b5 c #0f0f8e",
+"#S c #0f0f8f",
+"ci c #10108f",
+"bE c #101090",
+"b4 c #111190",
+"c2 c #111191",
+"#W c #121291",
+"b9 c #121292",
+"#b c #131392",
+"b3 c #131393",
+"ak c #141493",
+"aD c #141494",
+"bG c #151594",
+"aq c #151595",
+"bF c #161695",
+"#i c #161696",
+"aE c #171796",
+"ae c #171797",
+".5 c #181897",
+"cq c #181898",
+"#L c #191998",
+"bU c #191999",
+"b2 c #1a1a99",
+"aL c #1a1a9a",
+"ds c #1b1b9a",
+"#A c #1b1b9b",
+"#k c #1c1c9b",
+"#f c #1c1c9c",
+"cG c #1d1d9c",
+"bM c #1d1d9d",
+"bN c #1e1e9d",
+"ch c #1e1e9e",
+"bL c #1f1f9e",
+"b1 c #1f1f9f",
+"#j c #20209f",
+"bO c #2020a0",
+"cS c #2121a0",
+"bY c #2121a1",
+"db c #2222a1",
+"bK c #2222a2",
+"bn c #2323a2",
+"a# c #2323a3",
+"bH c #2424a4",
+"bJ c #2525a4",
+"a3 c #2525a5",
+"#o c #2626a5",
+"df c #2626a6",
+"#. c #2727a6",
+"bP c #2727a7",
+"ai c #2828a7",
+"cF c #2828a8",
+"cf c #2929a9",
+"b0 c #2a2aa9",
+"#x c #2a2aaa",
+".7 c #2b2baa",
+"bI c #2b2bab",
+"cy c #2c2cab",
+"a5 c #2c2cac",
+"aI c #2d2dac",
+"#d c #2d2dad",
+"cp c #2e2ead",
+"bo c #2e2eae",
+"ap c #2f2fae",
+"#1 c #3030b0",
+"cg c #3131b1",
+"bZ c #3232b1",
+"de c #3333b2",
+"dw c #3333b3",
+"bQ c #3434b4",
+"bp c #3535b5",
+"c3 c #3636b5",
+"#R c #3636b6",
+"cC c #3737b7",
+"aC c #3838b7",
+"#t c #3838b8",
+"#T c #3939b8",
+"#F c #3939b9",
+"bq c #3a3ab9",
+"#6 c #3a3aba",
+"aM c #3c3cbb",
+"#B c #3d3dbc",
+"cr c #3d3dbd",
+"#N c #3e3ebd",
+"dA c #3e3ebe",
+"ar c #3f3fbe",
+"bA c #3f3fbf",
+"bR c #4040c0",
+"bS c #4141c0",
+"dh c #4141c1",
+"ce c #4242c1",
+"da c #4343c3",
+"br c #4444c3",
+"#X c #4545c4",
+"a6 c #4545c5",
+"cM c #4646c5",
+"bw c #4646c6",
+"#e c #4747c6",
+"bs c #4747c7",
+"bv c #4848c7",
+"aB c #4848c8",
+"bt c #4949c8",
+"bu c #4949c9",
+"bx c #4a4ac9",
+"as c #4a4aca",
+"cs c #4b4bca",
+"ct c #4b4bcb",
+"#u c #4c4ccb",
+"bl c #4c4ccc",
+"dz c #5050cf",
+"c6 c #5151d0",
+"a7 c #5151d1",
+"by c #5252d1",
+"#H c #5353d2",
+"dx c #5454d3",
+"d# c #5454d4",
+"at c #5555d5",
+"aA c #5656d5",
+"cw c #5656d6",
+"dy c #5757d6",
+"bz c #5858d8",
+"#a c #5959d9",
+"cE c #5a5ad9",
+"cL c #5b5bdb",
+"a8 c #5c5cdb",
+"aN c #5c5cdc",
+".6 c #5d5ddd",
+"c5 c #5e5edd",
+"bk c #5e5ede",
+"dt c #5f5fde",
+"cT c #6060df",
+"al c #6262e1",
+"au c #6262e2",
+"az c #6464e4",
+"af c #6565e4",
+"cD c #6565e5",
+"#2 c #6666e6",
+"d. c #6767e7",
+"co c #6868e7",
+".9 c #6868e8",
+"av c #6969e8",
+"cN c #6a6aea",
+"a2 c #6b6bea",
+"c. c #6b6beb",
+"dk c #6c6ceb",
+"aO c #6c6cec",
+"ay c #6d6dec",
+"ad c #6e6eee",
+"ax c #6f6fef",
+"bD c #7070f0",
+"#w c #7171f0",
+"aw c #7171f1",
+"cu c #7272f1",
+"c7 c #7272f2",
+"a9 c #7373f2",
+"aF c #7373f3",
+"dn c #7474f4",
+"b. c #7878f7",
+"#C c #7979f8",
+".4 c #7979f9",
+"aP c #7a7af9",
+"aa c #7b7bfa",
+"b# c #7c7cfb",
+"cd c #7e7efd",
+"bX c #7f7ffe",
+".3 c #800000",
+".1 c #800101",
+"ba c #8080ff",
+".2 c #810101",
+".X c #810202",
+"dp c #8181ff",
+".W c #820202",
+".Y c #820303",
+"#5 c #8282ff",
+".Z c #830303",
+"aH c #8383ff",
+".R c #840505",
+"#v c #8484ff",
+".S c #850606",
+"bb c #8585ff",
+".T c #860707",
+"#K c #8686ff",
+".U c #870808",
+".V c #880808",
+"aQ c #8888ff",
+".Q c #890a0a",
+"dr c #8989ff",
+".K c #8a0a0a",
+"cz c #8a8aff",
+".j c #8b0b0b",
+"cK c #8b8bff",
+"bc c #8c8cff",
+"cU c #8d8dff",
+".B c #8e0e0e",
+".P c #8e0f0f",
+"ao c #8e8eff",
+".L c #8f0f0f",
+"cH c #9090ff",
+"bd c #9292ff",
+".C c #931414",
+"aR c #9393ff",
+".O c #941414",
+"#D c #9494ff",
+"#O c #9595ff",
+"cV c #9696ff",
+".M c #981818",
+"#E c #9898ff",
+".c c #991a1a",
+"cO c #9999ff",
+".N c #9a1b1b",
+".s c #9b1b1b",
+".J c #9d1e1e",
+"be c #9d9dff",
+"aS c #9e9eff",
+"dd c #9f9fff",
+"c8 c #a1a1ff",
+".D c #a32424",
+"#7 c #a3a3ff",
+"#I c #a5a5ff",
+".r c #a72828",
+"aT c #a7a7ff",
+"do c #a8a8ff",
+"cn c #a9a9ff",
+".# c #ab2c2c",
+"c9 c #ababff",
+".A c #ac2c2c",
+"cW c #adadff",
+"#Y c #aeaeff",
+".I c #af2f2f",
+"du c #b0b0ff",
+"#0 c #b1b1ff",
+"c4 c #b2b2ff",
+"bf c #b3b3ff",
+".E c #b43535",
+"cA c #b4b4ff",
+"#Q c #b5b5ff",
+"dv c #b6b6ff",
+"cl c #b7b7ff",
+"cX c #b8b8ff",
+"aU c #b9b9ff",
+"cc c #babaff",
+".i c #bc3c3c",
+"bW c #bcbcff",
+"dm c #bdbdff",
+".H c #be3f3f",
+"aZ c #bebeff",
+"bB c #bfbfff",
+"aV c #c0c0ff",
+".b c #c14141",
+".t c #c14242",
+"bg c #c1c1ff",
+"#V c #c2c2ff",
+".F c #c34343",
+"#9 c #c3c3ff",
+"cY c #c4c4ff",
+"#J c #c5c5ff",
+"cP c #c6c6ff",
+"aW c #c7c7ff",
+"aY c #c8c8ff",
+".a c #c94949",
+"bC c #c9c9ff",
+".k c #ca4a4a",
+"c1 c #cacaff",
+".G c #cb4b4b",
+"aX c #cbcbff",
+"di c #ccccff",
+"dj c #cdcdff",
+"bh c #ceceff",
+"a1 c #d0d0ff",
+"c# c #d1d1ff",
+"c0 c #d2d2ff",
+"cR c #d3d3ff",
+".z c #d45555",
+"cZ c #d4d4ff",
+"bT c #d6d6ff",
+"dl c #d8d8ff",
+"#3 c #dadaff",
+"am c #dbdbff",
+"bi c #dcdcff",
+"ag c #ddddff",
+"#P c #dfdfff",
+"cI c #e1e1ff",
+"bV c #e4e4ff",
+".q c #e66666",
+"dc c #e6e6ff",
+"aG c #e7e7ff",
+".d c #e86969",
+"cb c #e8e8ff",
+"cJ c #eaeaff",
+"ab c #ececff",
+".u c #ed6d6d",
+"bj c #ededff",
+"cB c #efefff",
+"#U c #f0f0ff",
+"cQ c #f1f1ff",
+"cv c #f2f2ff",
+"dq c #f4f4ff",
+"cm c #f5f5ff",
+"ca c #f6f6ff",
+"a0 c #f7f7ff",
+"an c #f9f9ff",
+"ah c #fafaff",
+"#Z c #fbfbff",
+"ac c #fcfcff",
+"#8 c #fdfdff",
+"#4 c #fefeff",
+".y c #ff7f7f",
+".h c #ff8686",
+".v c #ff9292",
+".l c #ff9595",
+".x c #ff9d9d",
+".w c #ffa5a5",
+".p c #ffb0b0",
+".e c #ffb3b3",
+".g c #ffbfbf",
+".f c #ffcece",
+".m c #ffd9d9",
+".o c #ffe8e8",
+".n c #fff8f8",
+".0 c #ffff00",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.#.a.b.cQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.c.d.e.f.g.h.iQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.j.k.l.m.n.o.p.q.rQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.s.t.u.v.w.x.y.z.A.BQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.C.D.E.F.G.a.H.I.J.BQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.K.L.C.M.N.N.M.O.P.QQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.R.S.T.U.V.V.V.U.T.SQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.W.X.W.W.W.W.Y.Y.Z.RQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.1.1.1.1.1.1.2.W.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.3.3.3.3.3.2.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0.0.4.5.2.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0.0.0.6.7.8.0.0.0.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0.0.0.9#..8.0.0.0.0.0.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0###a#b#c.0.0.0.0.0.0.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0#d#e#f#g#h.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0#i#j#k#l#m#h#n#o.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0#p#q#r#s#n#n#m#t#u#v#w#x.0.0.0.0.0.0.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0#y#h#n#m#r#q#z#A#B#C#D#E#F.0.0.0.0.0.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0#r#s#h#h#h#y#r#G#j#H#I#J#K#L.0.0.0.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0.0.0.0#n#n#n#y#M#b#N#O#P#Q#R.0.0.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0.0.0.0.0.0.0#h#n#h#r#S#T#E#U#V#N.0.0.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0#h#h#r#W#X#Y#Z#0#1.0.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0#y#q#k#2#3#4#5.5.0.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0#c#z#6#7#8#9#X#q.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0a.a#aaabacadae.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0#m.5afagah#Kai.0.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0.0.0.0.0.0.0.0.0#gaj.0.0.0.0.0.0.0.0.0akalamanaoapaj.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.0.0a.aqa#aparasatauavadawaxayazaAaBaCa#aDaEaFaGanaHaIaJ.0.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtaKaL#xaM#uaNaOaPaQaRaSaT#0aUaVaWaXaXaYaZ#Y#E#.aSa0a1a2a3a4.0.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQt###fa5#Ta6a7a8afaOa9b.b#babbbcbdbeaTbfbgbhbiaGbjbk#3#Z#IblaLajbm.0.0.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtaDbnbobpbqarbrbsbtbuaBbvbw#e#ebx#ubybzaladaaao#7bAbB#8bCbDapbEa.aObqbF.0.0QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtbGbH#dbobI#x.7a5a5#xaibJbK#jbLbMbNbNbObnbP#dbQbRbSaZ#4bTbbarbUa4#ZbVbWbXbr#LQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQt#SbYapbZb0b1b2b2aLbUaEb3b4b5b6b7#G#####Gb7b8#Sb9c.bT#4c#bbbrbL#z#q#Pca#8cbcccdcebFQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQt#icf#taMcgchcicj#Scjb7a4ck#q#g#m#r.8.8.8.8#rblclca#ZaUaF#NbMb8a.#MaQ#0amcmah#Pcncocpa4QtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQt#Gcq.7crcsctcra3b6aJbma.#m.8#c#s#y#y#y#hbJcu#Vcvcvcaaocw#1.5cx#q#rcybSalczcA#PcacBaYaQa6aEQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQt###ka#cCctaNcDazcEbt#tcFch.5cGb0bRazcHbBcIbjbVcJcKcLaCbLbEbm#m.8##bE#AaIcMcNcOcPcbcQcR#EatcSQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtajcj#L#dcCcscTcu#5cUcVbe#IcWcXcYbhcZc0c1cRcUaycsbZbNc2aJ#M.8#ca..8#q##b9bLc3aAbXc4biab#3#7c5#o#pQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQt#qaKb8bGchbSaBc6cE#2c7bX#KbccVc8c9#Qd.d#da#1db#i#laK#M.8#s#sa.#h#y#c#r#pb8cqb0btaF#7a1dccZdda8#o#MQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQt#g#g#paJb8b9.5chbJbI#1c3cC#t#Rde#ddf#jcqb9b6aK#q#r#c#s#y#y.0#h#n#n#h#ydg#M##ak#odhc.dddi#PdjcVd#dbQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQt.8.8#m#M#paK###zcj#SbEbEbE#S#lb7aJaj#q#m.8#c#s#y#h#h#s.0.0.0Qt#m#h#h#y#c#maKb9bndhdkbeaXdldm#vbw#LQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQt#c#c#cdgdg.8#r#m#m#m#m#m#r.8dg#c#s#y#h#h#h#n#h#y.0.0QtQtQtQtQtQtQt#y#y#s#maK#ba3brdndodia1aU#Obyb4QtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQt#s#y#y#y#y#y#y#y#y#y#h#h#h#h#n#n#n#n#n#n#yQtQtQtQtQtQtQtQtQtQtQtQtQt#y#c#maJaDbIa7dpaZdqaha1drbAb3QtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtdg#y#h#h#n#n#n#n#n#n#n#n#n#n#n#n#hdgQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#s#c#Mcxdsc3dtaodudvaScudhdsQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtdg#y#h#h#h#n#n#n#h#y#cQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtdg#pbEb1dwbwdxdydzdA#xaEQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#maJb5bGdsbLbOchaLakb8ckQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#q#qckaKaJ####a4bm#p#pQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#m#c#cdgdgdg.8.8.8#rQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#y#h#h#h#h#h#y#s#rQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#h#n#n#n#n#h#cQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#h#h#yQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt"};
diff --git a/mgllab/xpm/unused/smth.xpm b/mgllab/xpm/unused/smth.xpm
new file mode 100644
index 0000000..a2b9d46
--- /dev/null
+++ b/mgllab/xpm/unused/smth.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * smth_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #000000",
+"+	c #FF0000",
+"                ",
+"                ",
+"                ",
+"                ",
+"    .           ",
+"    .           ",
+"   . .    .     ",
+"   . .    ..    ",
+"  +++.   . .    ",
+" +.  ++  +++.   ",
+"  .   .++   ++  ",
+" .    . .    .+ ",
+" .    . .     . ",
+"       .        ",
+"       .        ",
+"                "};
diff --git a/mgllab/xpm/unused/sum.xpm b/mgllab/xpm/unused/sum.xpm
new file mode 100644
index 0000000..fc017ac
--- /dev/null
+++ b/mgllab/xpm/unused/sum.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * sum_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"   ..........   ",
+"   .        .   ",
+"    .       .   ",
+"     .          ",
+"      .         ",
+"       .        ",
+"        ..      ",
+"       .        ",
+"      .         ",
+"     .          ",
+"    .       .   ",
+"   .        .   ",
+"   ..........   ",
+"                "};
diff --git a/mgllab/xpm/unused/swap.xpm b/mgllab/xpm/unused/swap.xpm
new file mode 100644
index 0000000..6ad367c
--- /dev/null
+++ b/mgllab/xpm/unused/swap.xpm
@@ -0,0 +1,23 @@
+/* XPM */
+static const char * swap_xpm[] = {
+"16 16 4 1",
+" 	c None",
+".	c #0000FF",
+"+	c #000000",
+"@	c #FF0000",
+"                ",
+"  .          .. ",
+"   .        .   ",
+"    .      .    ",
+"    .      .    ",
+"     ......     ",
+"   +         +  ",
+"  +           + ",
+"  +           + ",
+"  + +       + + ",
+"   ++  @@@  ++  ",
+"  +++ @   @ +++ ",
+"     @     @    ",
+"     @     @    ",
+"  @@@       @@@ ",
+"                "};
diff --git a/mgllab/xpm/up_1.xpm b/mgllab/xpm/up_1.xpm
new file mode 100644
index 0000000..472b450
--- /dev/null
+++ b/mgllab/xpm/up_1.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * up_1_xpm[] = {
+"16 16 3 1",
+".	c None",
+"+	c #7F0000",
+"@	c #FF0000",
+"................",
+"................",
+"........+.......",
+".......+ at +......",
+"......+@@@+.....",
+".....+@@@@@+....",
+"....+@@@@@@@+...",
+"...+@@@@@@@@@+..",
+"..++++@@@@@++++.",
+".....+@@@@@+....",
+".....+@@@@@+....",
+".....+@@@@@+....",
+".....+@@@@@+....",
+".....+@@@@@+....",
+".....+++++++....",
+"................"};
diff --git a/mgllab/xpm/update.xpm b/mgllab/xpm/update.xpm
new file mode 100644
index 0000000..5ee1dd6
--- /dev/null
+++ b/mgllab/xpm/update.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char *update_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #00007F",
+"                ",
+"                ",
+"      ....      ",
+"     .    .     ",
+"    .   .....   ",
+"    .    ...    ",
+"          .     ",
+"                ",
+"                ",
+"     .          ",
+"    ...    .    ",
+"   .....   .    ",
+"     .    .     ",
+"      ....      ",
+"                ",
+"                "};
diff --git a/mgllab/xpm/vect.xpm b/mgllab/xpm/vect.xpm
new file mode 100644
index 0000000..7d91322
--- /dev/null
+++ b/mgllab/xpm/vect.xpm
@@ -0,0 +1,60 @@
+/* XPM */
+static const char * vect_xpm[] = {
+"16 16 41 1",
+" 	c None",
+".	c #B3FF00",
+"+	c #AEF900",
+"@	c #FBF400",
+"#	c #FEF700",
+"$	c #FFDA00",
+"%	c #AFFB00",
+"&	c #FDF600",
+"*	c #FDF500",
+"=	c #FD9600",
+"-	c #FD9000",
+";	c #FA8F00",
+">	c #FEAB00",
+",	c #FD9500",
+"'	c #FB9400",
+")	c #FE9100",
+"!	c #FBAA00",
+"~	c #FCA900",
+"{	c #FF9700",
+"]	c #FF9200",
+"^	c #FDA900",
+"/	c #FDAB00",
+"(	c #FB9D00",
+"_	c #FC0B00",
+":	c #FF0A00",
+"<	c #FF4400",
+"[	c #FB4200",
+"}	c #FC9E00",
+"|	c #FE9F00",
+"1	c #FD4400",
+"2	c #FC4400",
+"3	c #FFA000",
+"4	c #FB1600",
+"5	c #FCAD00",
+"6	c #D00000",
+"7	c #D20000",
+"8	c #FD1500",
+"9	c #FA1500",
+"0	c #FEAF00",
+"a	c #D10000",
+"b	c #FDAE00",
+" .+    @#     $ ",
+" %     &@     $ ",
+".      &        ",
+"      *         ",
+"  =     -;     >",
+" ,'     )     !~",
+"{      ]      ^ ",
+"      ]      /  ",
+"               (",
+" _:     <[    }|",
+" _     12     3 ",
+"      <      |  ",
+"                ",
+"         4     5",
+" 67     89    50",
+"a     8      b  "};
diff --git a/mgllab/xpm/view-filter.xpm b/mgllab/xpm/view-filter.xpm
new file mode 100644
index 0000000..de41124
--- /dev/null
+++ b/mgllab/xpm/view-filter.xpm
@@ -0,0 +1,64 @@
+/* XPM */
+static const char *view_filter_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 42 1 ",
+"  c #1E1E1E",
+". c #282828",
+"X c #353535",
+"o c gray28",
+"O c gray34",
+"+ c #5D5D5D",
+"@ c #606060",
+"# c #646464",
+"$ c #656565",
+"% c #686868",
+"& c #6D6D6D",
+"* c #6F6F6F",
+"= c gray44",
+"- c #717171",
+"; c gray57",
+": c #9F9F9F",
+"> c #A4A4A4",
+", c #ACACAC",
+"< c #B2B2B2",
+"1 c gray73",
+"2 c #BBBBBB",
+"3 c gray74",
+"4 c gray77",
+"5 c #CACACA",
+"6 c gray80",
+"7 c gray84",
+"8 c gray87",
+"9 c #E1E1E1",
+"0 c #E6E6E6",
+"q c gray91",
+"w c #E9E9E9",
+"e c #EFEFEF",
+"r c gray94",
+"t c #F1F1F1",
+"y c gray95",
+"u c #F3F3F3",
+"i c #F4F4F4",
+"p c #F6F6F6",
+"a c #F8F8F8",
+"s c #F9F9F9",
+"d c gray98",
+"f c None",
+/* pixels */
+"fffO*-**#Offffff",
+"ff#233333fffffff",
+"ff%,;*+. Xofffff",
+"fff:39ppwfffffff",
+"ffff<5aayfffffff",
+"ffff+2yaefffffff",
+"fffff at 7y0fffffff",
+"ffffff-08fffffff",
+"fffffffy4fffffff",
+"fffffffy6fffffff",
+"fffffffp6fffffff",
+"fffffffy6fffffff",
+"fffffffy6fffffff",
+"fffffffy6fffffff",
+"fffffffw>fffffff",
+"ffffffffffffffff"
+};
diff --git a/mgllab/xpm/view-fullscreen.xpm b/mgllab/xpm/view-fullscreen.xpm
new file mode 100644
index 0000000..d899ac9
--- /dev/null
+++ b/mgllab/xpm/view-fullscreen.xpm
@@ -0,0 +1,63 @@
+/* XPM */
+static const char *view_fullscreen_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 41 1 ",
+"  c #A40000",
+". c #B93C3C",
+"X c #BA3E3E",
+"o c #BC4343",
+"O c #BD4646",
+"+ c #C15252",
+"@ c #C55D5D",
+"# c #C55E5E",
+"$ c #C65E5E",
+"% c #C66060",
+"& c #C86464",
+"* c #C96767",
+"= c #D89393",
+"- c #DA9797",
+"; c #DA9898",
+": c #DB9999",
+"> c #DC9C9C",
+", c #DC9D9D",
+"< c #DC9E9E",
+"1 c #DD9F9F",
+"2 c #DDA0A0",
+"3 c #DEA1A1",
+"4 c #DEA2A2",
+"5 c #DFA5A5",
+"6 c #E0A8A8",
+"7 c #CFCFD1",
+"8 c #DEDEE0",
+"9 c #F5E4E4",
+"0 c #F6E5E5",
+"q c #F6E6E6",
+"w c #F6E7E7",
+"e c #F7E7E7",
+"r c #F7E8E8",
+"t c #F7E9E9",
+"y c #F8EAEA",
+"u c #F3F3F4",
+"i c #FEFCFC",
+"p c #FEFDFD",
+"a c #FEFEFE",
+"s c white",
+"d c None",
+/* pixels */
+"dddddddddddddddd",
+"duuuuuuuuuuuuuud",
+"d88888888888888d",
+"d77777777777777d",
+"dssssssssssssssd",
+"ds. at 2ssssss<@.sd",
+"ds@ <ssssss< %sd",
+"ds2<+ysssse+<2sd",
+"dssseesssseesssd",
+"dsssressss9ysssd",
+"ds5;Orssss9+;6sd",
+"ds* ;ssssss= *sd",
+"dso at 2ssssss<@Osd",
+"dssssssssssssssd",
+"dddddddddddddddd",
+"dddddddddddddddd"
+};
diff --git a/mgllab/xpm/view-grid.xpm b/mgllab/xpm/view-grid.xpm
new file mode 100644
index 0000000..db7228f
--- /dev/null
+++ b/mgllab/xpm/view-grid.xpm
@@ -0,0 +1,124 @@
+/* XPM */
+static const char *view_grid_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 102 2 ",
+"   c #0060FF",
+".  c #0061FF",
+"X  c #0062FF",
+"o  c #AAC7E9",
+"O  c #AECBEC",
+"+  c #B0CEEE",
+"@  c #B2CFEF",
+"#  c #B3D0F0",
+"$  c #B7D4F3",
+"%  c #B7D4F4",
+"&  c #B8D5F5",
+"*  c #BBD7F8",
+"=  c #BDDAF9",
+"-  c #BDD9FA",
+";  c #BEDAFB",
+":  c #E1E0DC",
+">  c #DFDFE0",
+",  c #C1DDFD",
+"<  c #DCE6F1",
+"1  c #DFE8F3",
+"2  c #D1EFFF",
+"3  c #D2EFFF",
+"4  c #D3F0FF",
+"5  c #E0E1E2",
+"6  c #E6E7E7",
+"7  c #E8E5E3",
+"8  c #ECE7E2",
+"9  c #EAE8E4",
+"0  c #EBE8E6",
+"q  c #ECEAE6",
+"w  c #E7E8E8",
+"e  c #EDEBE8",
+"r  c #EEEDE8",
+"t  c #ECECEC",
+"y  c gray93",
+"u  c #EFEEEC",
+"i  c #EEEFEF",
+"p  c #F3F0E9",
+"a  c #F6F1EB",
+"s  c #F3F0EC",
+"d  c #F3F0ED",
+"f  c #F5F2EE",
+"g  c #F6F2EF",
+"h  c #F6F3EF",
+"j  c #FAF6EF",
+"k  c #E1EBF5",
+"l  c #E2EBF4",
+"z  c #E3EDF6",
+"x  c #E2EDF7",
+"c  c #E3EDF7",
+"v  c #E4EDF6",
+"b  c #E4EDF7",
+"n  c #E5EEF7",
+"m  c #E5EEF8",
+"M  c #E6EEF8",
+"N  c #E6EFF9",
+"B  c #E7EFFA",
+"V  c #E7F0FA",
+"C  c #E8F1FB",
+"Z  c #E9F1FB",
+"A  c #E9F2FC",
+"S  c #EAF3FC",
+"D  c #EAF3FD",
+"F  c #EBF3FD",
+"G  c #EBF4FE",
+"H  c #ECF4FE",
+"J  c gray95",
+"K  c #F6F3F0",
+"L  c #F4F3F3",
+"P  c #F6F4F0",
+"I  c #F5F4F2",
+"U  c #F6F5F3",
+"Y  c #F4F4F4",
+"T  c #F4F5F5",
+"R  c #FBF5F0",
+"E  c #FFF8F3",
+"W  c #FBF8F4",
+"Q  c #FAF8F6",
+"!  c #FCF9F5",
+"~  c #FDFBF6",
+"^  c #FEFAF6",
+"/  c #FFFAF6",
+"(  c #FEFBF6",
+")  c #FEFCF7",
+"_  c #F3FFFF",
+"`  c #F4FFFF",
+"'  c #F9F8F8",
+"]  c #FBFAFA",
+"[  c #FBFBFB",
+"{  c #FFFFF8",
+"}  c #FFFFF9",
+"|  c #FDFCFA",
+" . c #FFFEFA",
+".. c #FFFFFB",
+"X. c #FAFFFF",
+"o. c #FFFFFC",
+"O. c #FEFEFD",
+"+. c #FFFEFD",
+"@. c #FFFFFD",
+"#. c #FFFFFE",
+"$. c white",
+"%. c None",
+/* pixels */
+"%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.",
+"%.%.$.$.` $.$.$.` $.$.$.` $.%.%.",
+"%.%.$.: o > > 7 O 6 6 e + $.%.%.",
+"%.%.$.8 1 e q g c g d R v $.%.%.",
+"%.%.` < X l + c X v % B X X.%.%.",
+"%.%.$.9 l u u g B L J R B $.%.%.",
+"%.%.$.9 # u u g % L Y ( * $.%.%.",
+"%.%.$.p c P L E V ( ( { A $.%.%.",
+"%.%._ l X B % B X A - A X X.%.%.",
+"%.%.$.s v Y Y ( A { ] { A $.%.%.",
+"%.%.$.s % Y Y { - ] ] $., $.%.%.",
+"%.%.$.j B ( ( { A $.$.{ H $.%.%.",
+"%.%._ v X A - A X A , H X X.%.%.",
+"%.%.$.P B Q ' { F { $.$.A $.%.%.",
+"%.%.$.$.4 $.$.$.2 $.$.$.2 $.%.%.",
+"%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%."
+};
diff --git a/mgllab/xpm/view-group.xpm b/mgllab/xpm/view-group.xpm
new file mode 100644
index 0000000..b256f34
--- /dev/null
+++ b/mgllab/xpm/view-group.xpm
@@ -0,0 +1,51 @@
+/* XPM */
+static const char *view_group_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 29 1 ",
+"  c #005CC6",
+". c #0050CC",
+"X c #0052CF",
+"o c #0260DF",
+"O c #4A83BE",
+"+ c #4686CF",
+"@ c #5191DC",
+"# c #5192DC",
+"$ c #7DA5CD",
+"% c #78A4D2",
+"& c #8FB9EA",
+"* c #B9CEE2",
+"= c #C9C9CB",
+"- c #C9C9CC",
+"; c #CFCFD1",
+": c #D0D0D1",
+"> c #D3D3D5",
+", c #D4D4D5",
+"< c #DEDEDF",
+"1 c #DFDFE1",
+"2 c gray90",
+"3 c #E6E6E6",
+"4 c #E8E8EB",
+"5 c #EFEFEF",
+"6 c #F4F4F4",
+"7 c #FAFBFA",
+"8 c #FBFBFB",
+"9 c white",
+"0 c None",
+/* pixels */
+"0000000000000000",
+"0999999999999990",
+"0411111111111140",
+"0>=----------=>0",
+"0999999999999990",
+"096,;::::::;,690",
+"09<7999999997<90",
+"0929%*$99%*$9290",
+"0959O+ 99O+ 9590",
+"0979Xo.99XoX9790",
+"0999999999999990",
+"096,;::::::;,690",
+"0929999999997290",
+"0999#&#999999990",
+"0000000000000000",
+"0000000000000000"
+};
diff --git a/mgllab/xpm/view-refresh.xpm b/mgllab/xpm/view-refresh.xpm
new file mode 100644
index 0000000..22fbc9a
--- /dev/null
+++ b/mgllab/xpm/view-refresh.xpm
@@ -0,0 +1,116 @@
+/* XPM */
+static const char *view_refresh_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 94 2 ",
+"   c #3465A4",
+".  c #3565A4",
+"X  c #3566A4",
+"o  c #3566A5",
+"O  c #3667A5",
+"+  c #3767A5",
+"@  c #3767A6",
+"#  c #3768A5",
+"$  c #3768A6",
+"%  c #3868A6",
+"&  c #3869A6",
+"*  c #3969A6",
+"=  c #3969A7",
+"-  c #3A69A7",
+";  c #3A6AA6",
+":  c #3A6AA7",
+">  c #3B6BA7",
+",  c #3C6BA8",
+"<  c #3C6BA9",
+"1  c #3C6CA9",
+"2  c #3D6DA9",
+"3  c #4170AB",
+"4  c #4371AB",
+"5  c #4774AD",
+"6  c #4B77AF",
+"7  c #4C77AF",
+"8  c #4C78AF",
+"9  c #4C78B0",
+"0  c #4D79B0",
+"q  c #4E7AB1",
+"w  c #4F7CB6",
+"e  c #537FB7",
+"r  c #5580B5",
+"t  c #5B84B7",
+"y  c #5D85B7",
+"u  c #5F87B9",
+"i  c #6188B9",
+"p  c #6890C0",
+"a  c #6990C0",
+"s  c #6D94C2",
+"d  c #6891C7",
+"f  c #6C95C9",
+"g  c #7298C5",
+"h  c #82A5CE",
+"j  c #84A6CE",
+"k  c #88A7CE",
+"l  c #88ABD2",
+"z  c #8AACD3",
+"x  c #8FACD0",
+"c  c #8CADD3",
+"v  c #8FADD2",
+"b  c #8EAED3",
+"n  c #8FB0D3",
+"m  c #93B1D4",
+"M  c #95B2D4",
+"N  c #9CB7D7",
+"B  c #97B6D8",
+"V  c #99B9DB",
+"C  c #9DBDDC",
+"Z  c #A1BBD9",
+"A  c #A1BEDD",
+"S  c #A0BEDE",
+"D  c #A8C1DE",
+"F  c #A8C2DF",
+"G  c #B0C9E3",
+"H  c #B4CAE3",
+"J  c #B4CBE5",
+"K  c #BCD1E7",
+"L  c #BFD2E7",
+"P  c #BFD3E9",
+"I  c #C1D2E6",
+"U  c #C7D7E9",
+"Y  c #C4D7EB",
+"T  c #C6D8EB",
+"R  c #C8D8EA",
+"E  c #C9D9EA",
+"W  c #CDDBEB",
+"Q  c #C9DAEC",
+"!  c #CCDCED",
+"~  c #CCDDEE",
+"^  c #D5E2F0",
+"/  c #D8E4F1",
+"(  c #DBE6F2",
+")  c #DDE8F3",
+"_  c #E0E9F4",
+"`  c #E2EBF5",
+"'  c #E3ECF5",
+"]  c #E4ECF5",
+"[  c #E4EDF5",
+"{  c #E5EDF5",
+"}  c #E5EDF6",
+"|  c #E6EEF6",
+" . c #E7EEF6",
+".. c None",
+/* pixels */
+"........% % % % , ..............",
+"......% a n F F m u % ......O ..",
+"....% c C A J P ~ ^ L 0 # 4   ..",
+"..% a g 1 # % y Z / / ) k E % ..",
+"..% 4 1 % ......% i W ` | | % ..",
+"..O % d % ..........  U T ' % ..",
+"..O ..............% x | / | , ..",
+"................  O 6 8 8 8 O ..",
+"..        O   O ................",
+"..  | ' ` N O ..............O ..",
+"..O | U E   ..........O f r   ..",
+"..O | ` | I 0 % ......< w % # ..",
+"..% / M ` ) ! c 9 O % % 1 0 : ..",
+"..O y O 0 J Q K G A z h b % ....",
+"..  O ....% r h B V z s % ......",
+"..O ..........: # O : : ........"
+};
diff --git a/mgllab/xpm/weather-clear.xpm b/mgllab/xpm/weather-clear.xpm
new file mode 100644
index 0000000..2e6676a
--- /dev/null
+++ b/mgllab/xpm/weather-clear.xpm
@@ -0,0 +1,101 @@
+/* XPM */
+static const char *weather_clear_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 79 1 ",
+"  c #E69A0E",
+". c #E7A003",
+"X c #E7A203",
+"o c #E7A407",
+"O c #E8A707",
+"+ c #E8A108",
+"@ c #E9A508",
+"# c #E9A409",
+"$ c #EBA40B",
+"% c #EAA70B",
+"& c #ECA80C",
+"* c #EDAC0E",
+"= c #ECB206",
+"- c #ECB306",
+"; c #ECB507",
+": c #ECB60E",
+"> c #EDB80B",
+", c #ECAA10",
+"< c #EDAB13",
+"1 c #E9AD11",
+"2 c #ECB618",
+"3 c #F0B414",
+"4 c #F3B518",
+"5 c #F5BA19",
+"6 c #F5BE1A",
+"7 c #E8A620",
+"8 c #F0B625",
+"9 c #F1B931",
+"0 c #F0C30D",
+"q c #F0C40D",
+"w c #F0C615",
+"e c #F7C119",
+"r c #F7C318",
+"t c #F8C11A",
+"y c #F4D218",
+"u c #F5D91C",
+"i c #F6DB1C",
+"p c #F6DB22",
+"a c #F2CC3D",
+"s c #F5D63C",
+"d c #F7E021",
+"f c #F8E121",
+"g c #FAEB2E",
+"h c #FAEC2C",
+"j c #FBED31",
+"k c #FBF031",
+"l c #FCF236",
+"z c #FCF337",
+"x c #FDF63F",
+"c c #EBB044",
+"v c #F0BC4B",
+"b c #F0BD4F",
+"n c #EDBC59",
+"m c #F3D042",
+"M c #F7DE45",
+"N c #F3CF5B",
+"B c #F4D55D",
+"V c #F9E74E",
+"C c #FAEC4B",
+"Z c #FDF942",
+"A c #F8E250",
+"S c #FAEA50",
+"D c #FBEE52",
+"F c #FBEE53",
+"G c #F9E85D",
+"H c #FBF054",
+"J c #F7DF63",
+"K c #F4D27E",
+"L c #F5D77F",
+"P c #F6DB7D",
+"I c #F6DC7D",
+"U c #F8E265",
+"Y c #F9E668",
+"T c #F9E769",
+"R c #FDF772",
+"E c #FDF875",
+"W c #FDF696",
+"Q c #FDF79B",
+"! c None",
+/* pixels */
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!8vb9!!!!!!",
+"!!!!tcKPKWn5!!!!",
+"!!!! NJYJJJ<!!!!",
+"!!!4.sVDAAM:*!!!",
+"!!!$=ugllgd0$!!!",
+"!!!&=ihZZkdq%!!!",
+"!!!t.yCREDp;3!!!",
+"!!!!+>AWQGwo!!!!",
+"!!!!!O1am2o!!!!!",
+"!!!!!!r<,e!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!",
+"!!!!!!!!!!!!!!!!"
+};
diff --git a/mgllab/xpm/weather-clear_old.xpm b/mgllab/xpm/weather-clear_old.xpm
new file mode 100644
index 0000000..d56582a
--- /dev/null
+++ b/mgllab/xpm/weather-clear_old.xpm
@@ -0,0 +1,98 @@
+/* XPM */
+static const char *weather_clear_old_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 76 1 ",
+"  c #FCAF3E",
+". c #FBB13E",
+"X c #FBB13F",
+"o c #FCB03E",
+"O c #FCB13E",
+"+ c #FCB23E",
+"@ c #FCB33E",
+"# c #FCB23F",
+"$ c #FCB33F",
+"% c #FAB43F",
+"& c #FBB43F",
+"* c #FCB43F",
+"= c #FAB545",
+"- c #FBB94A",
+"; c #FCB953",
+": c #FBBA57",
+"> c #FCBC57",
+", c #FBBD5B",
+"< c #FBD349",
+"1 c #FCD549",
+"2 c #FCE34E",
+"3 c #FCE956",
+"4 c #FCEA57",
+"5 c #FCE459",
+"6 c #FCE55D",
+"7 c #FCE959",
+"8 c #FCEA5A",
+"9 c #FCC66D",
+"0 c #FCD964",
+"q c #FBDB6C",
+"w c #FCC470",
+"e c #FCC570",
+"r c #FCEB65",
+"t c #FCE768",
+"y c #FCEC68",
+"u c #FCE86E",
+"i c #FCED71",
+"p c #FCCC82",
+"a c #FDCD83",
+"s c #FCCD84",
+"d c #FCEF81",
+"f c #FCEF82",
+"g c #FCEF84",
+"h c #FCEF87",
+"j c #FDF089",
+"k c #FDF08B",
+"l c #FDF08C",
+"z c #FDEAAD",
+"x c #FDF3A1",
+"c c #FDF0A2",
+"v c #FDF3A2",
+"b c #FDF1AA",
+"n c #FCF4AB",
+"m c #FDF4AC",
+"M c #FCF4AD",
+"N c #FDF4AE",
+"B c #FDECB4",
+"V c #FDE6BF",
+"C c #FDF4B0",
+"Z c #FDF5B1",
+"A c #FDF6BE",
+"S c #FDE6C1",
+"D c #FEF8CE",
+"F c #FEF9CF",
+"G c #FEF8D0",
+"H c #FEF9D0",
+"J c #FEF9DF",
+"K c #FEFAE3",
+"L c #FEF8E7",
+"P c #FEF9E7",
+"I c #FEFCEF",
+"U c #FEFCF0",
+"Y c #FEFDF0",
+"T c #FEFCF1",
+"R c #FEFEFB",
+"E c None",
+/* pixels */
+"EEEEEEEEEEEEEEEE",
+"EEEEEEEOOEEEEEEE",
+"EEEEEEE+OEEEEEEE",
+"EEE OEaaw;EOOEEE",
+"EEEO9VPIJz;=OEEE",
+"EEEESRIFCMc=EEEE",
+"EEEaPTIFMjh0OEEE",
+"EOOsTGGAcdyt+OOE",
+"EOOwKCMcji85+OOE",
+"EEE>BMldi84<+EEE",
+"EEEE,bgr442%EEEE",
+"EEEO=-qt61**OEEE",
+"EEEOOEO=+*EOOEEE",
+"EEEEEEEO+EEEEEEE",
+"EEEEEEEO EEEEEEE",
+"EEEEEEEEEEEEEEEE"
+};
diff --git a/mgllab/xpm/weather-clouds.xpm b/mgllab/xpm/weather-clouds.xpm
new file mode 100644
index 0000000..f5e98eb
--- /dev/null
+++ b/mgllab/xpm/weather-clouds.xpm
@@ -0,0 +1,125 @@
+/* XPM */
+static const char *weather_clouds_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 103 2 ",
+"   c #E3960F",
+".  c #E49A0E",
+"X  c #E5A000",
+"o  c #ECA90D",
+"O  c #ECB200",
+"+  c #EEAE13",
+"@  c #F1B210",
+"#  c #F5B715",
+"$  c #EBBC21",
+"%  c #EEB12A",
+"&  c #F7BC24",
+"*  c #FAE318",
+"=  c #FEF21E",
+"-  c #E7D529",
+";  c #EAD636",
+":  c #F8E136",
+">  c #F2ED37",
+",  c #F7E03B",
+"<  c #DAB043",
+"1  c #E9B24E",
+"2  c #EBB55A",
+"3  c #FCEF4B",
+"4  c #FBED4C",
+"5  c #FCF14C",
+"6  c #E9E359",
+"7  c #EAE25F",
+"8  c #DEC57E",
+"9  c #F5D765",
+"0  c #F5D961",
+"q  c #F9E767",
+"w  c #F9E668",
+"e  c #F9E969",
+"r  c #B3B7BB",
+"t  c #B6B9BC",
+"y  c #BCBDBD",
+"u  c #BCBCBE",
+"i  c #F3D38E",
+"p  c #F4D793",
+"a  c #F5DE92",
+"s  c #C0C1C1",
+"d  c #C1C1C1",
+"f  c #C2C2C3",
+"g  c #C4C4C3",
+"h  c #C2C3C4",
+"j  c #C7C7C6",
+"k  c #C6C7C8",
+"l  c #C7C8C8",
+"z  c #C9C9CA",
+"x  c #CCCCCD",
+"c  c #CACCD0",
+"v  c #CDCED1",
+"b  c #CCCFD9",
+"n  c #CFD0D0",
+"m  c #D2D1D2",
+"M  c #D1D2D2",
+"N  c #D3D4D2",
+"B  c #D5D5D4",
+"V  c #D4D4D5",
+"C  c #D4D5D5",
+"Z  c #D5D7D7",
+"A  c #D5D7D9",
+"S  c #D5D8D9",
+"D  c #D7D8DA",
+"F  c #D8D9D9",
+"G  c gray85",
+"H  c #D9D9DA",
+"J  c #DBDADA",
+"K  c #DADADB",
+"L  c #DCDDDB",
+"P  c #DBDBDC",
+"I  c #D9D9DE",
+"U  c #DDDDDE",
+"Y  c #DFDFDE",
+"T  c #DEDFDF",
+"R  c #E0DFDF",
+"E  c #E0E0DF",
+"W  c #CBD1E1",
+"Q  c #D5D9E7",
+"!  c #D9DDE4",
+"~  c #DDDEE4",
+"^  c #DFE1EC",
+"/  c gray88",
+"(  c #E1E1E1",
+")  c #E4E4E3",
+"_  c #E0E3E5",
+"`  c #E5E5E4",
+"'  c #E4E4E5",
+"]  c #E4E4E6",
+"[  c #E7E7E7",
+"{  c #E8E7E7",
+"}  c #E4E5E8",
+"|  c #E7E7E8",
+" . c #E0E3EE",
+".. c #EAEAE9",
+"X. c #EBE9EA",
+"o. c #EBEBEA",
+"O. c #EAEAEB",
+"+. c #ECECEC",
+"@. c #E2E3F4",
+"#. c #EDECF1",
+"$. c #EAE9F4",
+"%. c gray94",
+"&. c None",
+/* pixels */
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.+ % @ &.&.&.&.&.",
+"&.&.&.&.&.&.# 2 p a i 1 &.&.&.&.",
+"&.&.&.&.&.&.  0 w e w 9 . &.&.&.",
+"&.&.&.&.! _ 8 : 5 5 4 , X & &.&.",
+"&.T H ' O.]  .- 6 > = * O o &.&.",
+"/ D A D | O.I ~ @. .7 ; < $ &.&.",
+"&.) +.E [ ../ E R +.$.Q W c &.&.",
+"&.C H ] %.D m P R | E H B B b &.",
+"&.&.z / ..` m H T m m H L C v &.",
+"&.&.&.x l g j f k f u f s u t t ",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&."
+};
diff --git a/mgllab/xpm/window.xpm b/mgllab/xpm/window.xpm
new file mode 100644
index 0000000..28ac182
--- /dev/null
+++ b/mgllab/xpm/window.xpm
@@ -0,0 +1,29 @@
+/* XPM */
+static const char * window_xpm[] = {
+"16 16 10 1",
+" 	c None",
+".	c #000000",
+"+	c #333377",
+"@	c #FFFFFF",
+"#	c #777777",
+"$	c #00007F",
+"%	c #4444FF",
+"&	c #FF0000",
+"*	c #007F00",
+"=	c #7F0000",
+"                ",
+"                ",
+"..............  ",
+".++++++++++++.  ",
+".@@@@@#@@@@@@.  ",
+".@$.............",
+".@@.%%%%%%%%%%%.",
+".@$.@@@@@#@@@@@.",
+".@@.@$$@@#@@@@@.",
+".@$.@@@@@#@@@@@.",
+".@@.@$&*@#@@@@@.",
+"....@@@@@#@@@@@.",
+"   .@$&=@#@@@@@.",
+"   .@@@@@#@@@@@.",
+"   .............",
+"                "};
diff --git a/mgllab/xpm/wire.xpm b/mgllab/xpm/wire.xpm
new file mode 100644
index 0000000..b67d50b
--- /dev/null
+++ b/mgllab/xpm/wire.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * wire_xpm[] = {
+"16 16 2 1",
+" 	c None",
+".	c #000000",
+"                ",
+"                ",
+"                ",
+"     .    .     ",
+"     .    .     ",
+"     .    .     ",
+"  ............  ",
+"     .    .     ",
+"     .    .     ",
+"     .    .     ",
+"     .    .     ",
+"  ............  ",
+"     .    .     ",
+"     .    .     ",
+"     .    .     ",
+"                "};
diff --git a/mgllab/xpm/zoom-draw.xpm b/mgllab/xpm/zoom-draw.xpm
new file mode 100644
index 0000000..c151ca1
--- /dev/null
+++ b/mgllab/xpm/zoom-draw.xpm
@@ -0,0 +1,167 @@
+/* XPM */
+static const char *zoom_draw_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 145 2 ",
+"   c #5D6973",
+".  c #626A6F",
+"X  c #686968",
+"o  c #696D6B",
+"O  c #71797E",
+"+  c #6B7682",
+"@  c #757D85",
+"#  c #4E7DB9",
+"$  c #547DB1",
+"%  c #75808C",
+"&  c #7688A1",
+"*  c #7F90A5",
+"=  c #638CC1",
+"-  c #868681",
+";  c #858683",
+":  c #898986",
+">  c #8F908E",
+",  c #808A96",
+"<  c #92979C",
+"1  c #9B9C9A",
+"2  c #9E9E9C",
+"3  c #8394A8",
+"4  c #8296B0",
+"5  c #8D9CB1",
+"6  c #849ABA",
+"7  c #9EA2A8",
+"8  c #9FA9B8",
+"9  c #98AABE",
+"0  c #A6A6A4",
+"q  c #ABACAB",
+"w  c #A3AAB3",
+"e  c #ABAEB1",
+"r  c #ACAFB1",
+"t  c #A0ABB8",
+"y  c #B1B1B1",
+"u  c #BBB9B7",
+"i  c #B3B6B8",
+"p  c #BEC0BE",
+"a  c #8DA7C7",
+"s  c #90A9CA",
+"d  c #B2BAC5",
+"f  c #A0BED7",
+"g  c #A2BFD6",
+"h  c #A6C3D7",
+"j  c #AAC6DA",
+"k  c #AEC8DD",
+"l  c #B4C6E1",
+"z  c #B0C9E2",
+"x  c #B4CBE6",
+"c  c #B8D3EC",
+"v  c #C4C4C1",
+"b  c gray78",
+"n  c #CBCAC7",
+"m  c #CCCCC8",
+"M  c #CDCCCD",
+"N  c #D2D0CD",
+"B  c #C9D2DF",
+"V  c #D1D2D2",
+"C  c #DBD9D3",
+"Z  c #DDDCD7",
+"A  c #E0DFDE",
+"S  c #DFE0DF",
+"D  c #C3D1E4",
+"F  c #C3DBF6",
+"G  c #C2DDFB",
+"H  c #C1DEFA",
+"J  c #C8DEF8",
+"K  c #D9E1E7",
+"L  c #C9E0F6",
+"P  c #C9E1F9",
+"I  c #CFE2F8",
+"U  c #CFE3F9",
+"Y  c #CFE3FB",
+"T  c #CAE4FB",
+"R  c #CFE5F9",
+"E  c #CCE3FC",
+"W  c #CDE7FC",
+"Q  c #CFE7FC",
+"!  c #D0E3F3",
+"~  c #DDE7F7",
+"^  c #D3E6FA",
+"/  c #D0E6FC",
+"(  c #D5E8FB",
+")  c #D6E8FA",
+"_  c #D9EAFA",
+"`  c #DBEAFA",
+"'  c #DDEBFC",
+"]  c #E3E3E2",
+"[  c #E5E5E4",
+"{  c #E8E9E8",
+"}  c gray92",
+"|  c #EEECEC",
+" . c #EEEDED",
+".. c #EFEFEF",
+"X. c #F2EFEF",
+"o. c #F3F2ED",
+"O. c #E1EEFE",
+"+. c #E0F3F9",
+"@. c #E1F3FA",
+"#. c #E5F5FB",
+"$. c #E2F3FF",
+"%. c #E6F7FF",
+"&. c #ECF1F8",
+"*. c #EBFAFB",
+"=. c #ECFBFB",
+"-. c #EFFBFB",
+";. c #EBF8FF",
+":. c #EAFAFF",
+">. c #EEFAFC",
+",. c #F1F0F0",
+"<. c #F1F1F1",
+"1. c gray95",
+"2. c #F3F2F2",
+"3. c #F6F6F6",
+"4. c #F8F7F7",
+"5. c #FAF9F7",
+"6. c #F1F9FA",
+"7. c #F0FAFA",
+"8. c #F0FAFB",
+"9. c #F3FAFB",
+"0. c #F6F9F9",
+"q. c #F5FAFA",
+"w. c #F4FBFA",
+"e. c #F7FAFA",
+"r. c #F6FBFB",
+"t. c #F0FBFC",
+"y. c #F1FBFC",
+"u. c #F3FAFC",
+"i. c #F2F8FF",
+"p. c #F5FBFC",
+"a. c #F7FBFC",
+"s. c #F0FDFF",
+"d. c #F2FEFF",
+"f. c #F7FFFF",
+"g. c #F9F9F9",
+"h. c #FAF9F9",
+"j. c #F8FBFB",
+"k. c gray98",
+"l. c #FCFBFB",
+"z. c #F8FFFF",
+"x. c #FBFFFF",
+"c. c #FCFFFF",
+"v. c #FDFFFF",
+"b. c white",
+"n. c None",
+/* pixels */
+"n.n.n.n.n.A e 7 i v n.n.n.n.n.n.",
+"n.b.b.5.w d &.i.B t e n.n.n.n.n.",
+"n.b.c 5 O._ _ ) ) I D < n.n.n.n.",
+"n.b.t I / / W W P H ~ 6 m n.n.n.",
+"n.o.s x z k j h h f K a , n.n.n.",
+"n.Z = ' ;.f.x.b.x.x.;.E * n.n.n.",
+"n.N # P @.>.8.9.8.>.=./ 3 n.n.n.",
+"n.C $ P #.t.t.a.9.8.>.( % n.n.n.",
+"n.4.& J +.8.w.k.k.9.8.F : n.n.n.",
+"n.b.9 l L >.8.9.k.k.$.@ 2.n.n.n.",
+"n.b.n 0 3 G %.s.s.! O 2 { n.n.n.",
+"n.n.n.b.u o   + . - } V q n.n.n.",
+"n.n.n.b.k.b.k.,.b.k.3.M S 2 n.n.",
+"n.n.n.b.,.,.,.X.| | | | b [ > n.",
+"n.n.n.b.b.b.b.b.b.b.b.b.b.X ] - ",
+"n.n.n.n.n.n.n.n.n.n.n.n.n.n.y p "
+};
diff --git a/mgllab/xpm/zoom-in.xpm b/mgllab/xpm/zoom-in.xpm
new file mode 100644
index 0000000..7cf298a
--- /dev/null
+++ b/mgllab/xpm/zoom-in.xpm
@@ -0,0 +1,124 @@
+/* XPM */
+static const char *zoom_in_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 102 2 ",
+"   c #223449",
+".  c #314156",
+"X  c #3B5373",
+"o  c #3C5270",
+"O  c #3B5575",
+"+  c #5B5D5A",
+"@  c #5E5F5A",
+"#  c #475E7B",
+"$  c #5D6871",
+"%  c #64696B",
+"&  c #646C73",
+"*  c #65717E",
+"=  c #7F7F7B",
+"-  c #4F6683",
+";  c #5C799D",
+":  c #687C93",
+">  c #78848E",
+",  c #6E8096",
+"<  c #7F8D9D",
+"1  c #5D84BC",
+"2  c #6782A7",
+"3  c #6784A5",
+"4  c #7F8FA5",
+"5  c #718DAC",
+"6  c #738EAC",
+"7  c #6C8DBC",
+"8  c #718CB0",
+"9  c #718DB5",
+"0  c #7C95B3",
+"q  c #7BAEE6",
+"w  c #7FB1EB",
+"e  c #8F908B",
+"r  c #8F918E",
+"t  c #8D959E",
+"y  c #9C9D9A",
+"u  c gray61",
+"i  c #979CA2",
+"p  c #929CA8",
+"a  c #9CA6B4",
+"s  c #9AA6B9",
+"d  c #98A8BE",
+"f  c #A1A5AA",
+"g  c #AAABA9",
+"h  c #A9AEB7",
+"j  c #AFB2B5",
+"k  c #A7B1BD",
+"l  c #B8B7B2",
+"z  c #B3B6B9",
+"x  c #B6B9BB",
+"c  c #BBBBBA",
+"v  c #C3C1BE",
+"b  c #C5C4BF",
+"n  c #94A8C0",
+"m  c #B4B9C0",
+"M  c #A2B8D7",
+"N  c #ABBDD3",
+"B  c #8FBEEE",
+"V  c #92B9E8",
+"C  c #A8CEEF",
+"Z  c #AFD3F8",
+"A  c #B9DBF6",
+"S  c #C8C8C8",
+"D  c #CDCDCA",
+"F  c #CCCDCC",
+"G  c #D2D3D2",
+"H  c #D9DAD9",
+"J  c #DCDDDC",
+"K  c #CDD7E5",
+"L  c #C6D4E9",
+"P  c #C5D5EB",
+"I  c #C1D7F3",
+"U  c #C8DAF2",
+"Y  c #C2E4F7",
+"T  c #D0E1F5",
+"R  c #DCE6F3",
+"E  c #D9E6F6",
+"W  c #DAE7F7",
+"Q  c #D8E9F9",
+"!  c #DEEBF9",
+"~  c #D1F0FF",
+"^  c #D9F0FF",
+"/  c #DFF2FF",
+"(  c #E9E9E7",
+")  c #ECEBE9",
+"_  c #E0E7F0",
+"`  c #E3ECF8",
+"'  c #E8F6FF",
+"]  c #E9F6FF",
+"[  c #EBF6FF",
+"{  c #E7FFFF",
+"}  c #EFF8FF",
+"|  c #EAFCFF",
+" . c #EDFFFF",
+".. c #EEFFFF",
+"X. c #F0FEFF",
+"o. c #F1FFFF",
+"O. c #F3FFFF",
+"+. c #FAFFFF",
+"@. c #FDFFFF",
+"#. c #FEFFFF",
+"$. c white",
+"%. c None",
+/* pixels */
+"%.%.%.%.( z f j D %.%.%.%.%.%.%.",
+"%.%.) h k _ +.K s i %.%.%.%.%.%.",
+"%.%.a R ` X.o ] E P t %.%.%.%.%.",
+"%.m L E ! ] 0 ] Q T M x %.%.%.%.",
+"%.d U / | $.5 %...} A t %.%.%.%.",
+"b 7 ^ . - # n X O   ~ 2 %.%.%.%.",
+"l 1 C { ..$.5 %...O.Y 8 %.%.%.%.",
+"%.9 q %.%.%.3 %.%.%.%., %.%.%.%.",
+"%.p V %.%.%.; %.%.%.Z % %.%.%.%.",
+"%.v N B %.%.$.%.%.%.< %.%.%.%.%.",
+"%.%.e : w %.%.%.A > = %.%.%.%.%.",
+"%.%.%.%.+ $ * & @ %.S c %.%.%.%.",
+"%.%.%.%.%.%.%.%.%.%.%.G g %.%.%.",
+"%.%.%.%.%.%.%.%.%.%.%.%.H y %.%.",
+"%.%.%.%.%.%.%.%.%.%.%.%.%.J r %.",
+"%.%.%.%.%.%.%.%.%.%.%.%.%.u F %."
+};
diff --git a/mgllab/xpm/zoom-original.xpm b/mgllab/xpm/zoom-original.xpm
new file mode 100644
index 0000000..3d3473f
--- /dev/null
+++ b/mgllab/xpm/zoom-original.xpm
@@ -0,0 +1,117 @@
+/* XPM */
+static const char *zoom_original_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 95 2 ",
+"   c #324866",
+".  c #334968",
+"X  c #354A69",
+"o  c #3D526F",
+"O  c #5B5C58",
+"+  c #5D5E58",
+"@  c #5D6770",
+"#  c #64696A",
+"$  c #636B72",
+"%  c #64707D",
+"&  c #7E7E79",
+"*  c #5B769A",
+"=  c #5D799D",
+"-  c #5F799F",
+";  c #5E7A9F",
+":  c #667B92",
+">  c #617C9F",
+",  c #647FA4",
+"<  c #75818D",
+"1  c #6E8096",
+"2  c #7D8C9C",
+"3  c #5C84BC",
+"4  c #6682A6",
+"5  c #6782A8",
+"6  c #6A84A8",
+"7  c #7F8FA4",
+"8  c #7E99A8",
+"9  c #6F8BB4",
+"0  c #6A8ABB",
+"q  c #728EB2",
+"w  c #76AEED",
+"e  c #7CB0E8",
+"r  c #92928C",
+"t  c #8C949D",
+"y  c #919390",
+"u  c gray61",
+"i  c #9E9F9C",
+"p  c #969BA1",
+"a  c #939CA8",
+"s  c #89A0B4",
+"d  c #97A3B7",
+"f  c #9AA4B3",
+"g  c #95A6BC",
+"h  c #A1A5AA",
+"j  c #ADAEAB",
+"k  c #A8ADB6",
+"l  c #A3AEBA",
+"z  c #AFB2B5",
+"x  c #B8B7B2",
+"c  c #B3B6B9",
+"v  c #B9BBBD",
+"b  c #BFBFBE",
+"n  c #C5C4BF",
+"m  c #B5BAC0",
+"M  c #A0B7D8",
+"N  c #91B9E9",
+"B  c #AEC0D6",
+"V  c #A4CBF2",
+"C  c #B0D5FD",
+"Z  c #C9C7C3",
+"A  c #CDCDCA",
+"S  c #CCCDCC",
+"D  c #CDCDCD",
+"F  c #D8D9D8",
+"G  c #DFE0DF",
+"H  c #CFD9E6",
+"J  c #C6D4EA",
+"K  c #C6D7ED",
+"L  c #C3DAF7",
+"P  c #C4DAF6",
+"I  c #CCDEF5",
+"U  c #D1E2F6",
+"Y  c #DAE7F7",
+"T  c #DDE8F5",
+"R  c #DBE8F9",
+"E  c #E2E3E2",
+"W  c #E9E9E7",
+"Q  c #E2E9F1",
+"!  c #E3EDF9",
+"~  c #E1ECFA",
+"^  c #E2EFFB",
+"/  c #E4EDF9",
+"(  c #E4EEF9",
+")  c #E0F0FA",
+"_  c #E2F0FB",
+"`  c #E7F9FF",
+"'  c #E9FAFF",
+"]  c #ECF9FF",
+"[  c #F4F3F0",
+"{  c #F3F9FF",
+"}  c #F5FFFF",
+"|  c #FAFFFF",
+" . c #FEFFFF",
+".. c white",
+"X. c None",
+/* pixels */
+"X.X.X.X.W c h z A X.X.X.X.X.X.X.",
+"X.X.[ k l Q { H d p X.X.X.X.X.X.",
+"X.X.f T / / / ~ R K t X.X.X.X.X.",
+"X.m J Y ] ^ ) ) ' U M v X.X.X.X.",
+"X.g I ' . | |  .X } P 7 X.X.X.X.",
+"n 0 L s 6 X.o 8 4 X.V 5 X.X.X.X.",
+"x 3 X. .= X. . .= X.X.q X.X.X.X.",
+"X.9 e X.> X.  X.4 X.X.1 X.X.X.X.",
+"X.a N X.* X. .X.= X.C # X.X.X.X.",
+"X.Z B X. .X.X.X. .X.2 X.X.X.X.X.",
+"X.X.r : w X.X.X.X.< & X.X.X.X.X.",
+"X.X.X.X.+ @ % $ + X.D b X.X.X.X.",
+"X.X.X.X.X.X.X.X.X.X.X.F j X.X.X.",
+"X.X.X.X.X.X.X.X.X.X.X.X.E i X.X.",
+"X.X.X.X.X.X.X.X.X.X.X.X.X.E y X.",
+"X.X.X.X.X.X.X.X.X.X.X.X.X.u D X."
+};
diff --git a/mgllab/xpm/zoom-out.xpm b/mgllab/xpm/zoom-out.xpm
new file mode 100644
index 0000000..726983a
--- /dev/null
+++ b/mgllab/xpm/zoom-out.xpm
@@ -0,0 +1,123 @@
+/* XPM */
+static const char *zoom_out_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 101 2 ",
+"   c #1A2B41",
+".  c #26364D",
+"X  c #324D6F",
+"o  c #375171",
+"O  c #3F5776",
+"+  c #5B5B55",
+"@  c #5D5D59",
+"#  c #5B5E5C",
+"$  c #445B7A",
+"%  c #485F7E",
+"&  c #5F6974",
+"*  c #636A6F",
+"=  c #636F7B",
+"-  c #64717D",
+";  c #6D757A",
+":  c #61748F",
+">  c #707981",
+",  c #667891",
+"<  c #6780A1",
+"1  c #4F81C6",
+"2  c #5F88C1",
+"3  c #698FC7",
+"4  c #848582",
+"5  c #8A8B87",
+"6  c #8C8C8A",
+"7  c #8E8F8C",
+"8  c #848E99",
+"9  c #959A9F",
+"0  c #989898",
+"q  c #999A98",
+"w  c #8E9AAD",
+"e  c #9A9EA2",
+"r  c #8A9BB2",
+"t  c #939EB2",
+"y  c #9CA4AF",
+"u  c #AEACA5",
+"i  c #A1A5AB",
+"p  c #A9AAA8",
+"a  c #A6AEBA",
+"s  c #ACB0B4",
+"d  c gray70",
+"f  c #B6B5B3",
+"g  c #B6B9BA",
+"h  c #BEBFBC",
+"j  c #C2C3BF",
+"k  c #8DA3C3",
+"l  c #92A7C5",
+"z  c #ACB5C2",
+"x  c #A3BADA",
+"c  c #B6C7DF",
+"v  c #A0C3EF",
+"b  c #ADC9EF",
+"n  c #B1D0EC",
+"m  c #A3C6F0",
+"M  c #AFD5F4",
+"N  c #ABD3F8",
+"B  c #CACAC7",
+"V  c #CCCBC8",
+"C  c #CCCCC8",
+"Z  c #D5D3CD",
+"A  c #C3CDDC",
+"S  c #D7D7D7",
+"D  c #CADCF3",
+"F  c #CFE1F5",
+"G  c #C1E4FA",
+"H  c #CAE9FF",
+"J  c #CDEEFF",
+"K  c #D7E4F7",
+"L  c #DAE7F6",
+"P  c #D6E7F8",
+"I  c #DCE9F9",
+"U  c #DEECFA",
+"Y  c #DFEEFA",
+"T  c #E1E2E1",
+"R  c gray89",
+"E  c #E7E7E3",
+"W  c #E6E6E4",
+"Q  c #ECEBE9",
+"!  c #E0EBF9",
+"~  c #E3EDF9",
+"^  c #E2EFFA",
+"/  c #E5EDF9",
+"(  c #E5EEF9",
+")  c #E2F1FB",
+"_  c #E0F7FF",
+"`  c #E5F7FF",
+"'  c #EAF1F9",
+"]  c #E9F2FD",
+"[  c #EFFFFF",
+"{  c #F0F5FF",
+"}  c azure",
+"|  c #F1FFFF",
+" . c #F4FFFF",
+".. c #F5FFFF",
+"X. c #F6FFFF",
+"o. c #F7FFFF",
+"O. c #F8FFFF",
+"+. c #F9FFFF",
+"@. c #FAFFFF",
+"#. c #FDFFFF",
+"$. c None",
+/* pixels */
+"$.$.$.$.$.T s i g V $.$.$.$.$.$.",
+"$.$.$.Q y z ' { A t e $.$.$.$.$.",
+"$.$.E w ] / / / ! U c 9 $.$.$.$.",
+"$.$.a K L U ) ) Y P D k C $.$.$.",
+"$.Z l D ` } O.#.O.} ..b 8 $.$.$.",
+"$.j 3 _ . % $ O o X   J : $.$.$.",
+"$.f 1 M [ ....O.O.O.O.G , $.$.$.",
+"$.u 2 $.$.$.$.$.$.$.$.N - $.$.$.",
+"$.$.r v $.$.$.$.$.$.$.m @ $.$.$.",
+"$.$.B x $.$.$.$.$.$.H > $.$.$.$.",
+"$.$.$.6 < $.$.$.$.n ; 5 $.$.$.$.",
+"$.$.$.$.$.# & - * + $.S p $.$.$.",
+"$.$.$.$.$.$.$.$.$.$.$.$.R q $.$.",
+"$.$.$.$.$.$.$.$.$.$.$.$.$.W 7 $.",
+"$.$.$.$.$.$.$.$.$.$.$.$.$.q T 4 ",
+"$.$.$.$.$.$.$.$.$.$.$.$.$.$.d h "
+};
diff --git a/mgllab/xpm/zoom_1.xpm b/mgllab/xpm/zoom_1.xpm
new file mode 100644
index 0000000..c6015ea
--- /dev/null
+++ b/mgllab/xpm/zoom_1.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static const char * zoom_1_xpm[] = {
+"16 16 3 1",
+".	c None",
+"+	c #7F0000",
+"@	c #FF0000",
+"................",
+"................",
+"......++++......",
+"......+@@+......",
+"......+@@+......",
+"......+@@+......",
+"......+@@+......",
+".++++++@@++++++.",
+".+@@@@@@@@@@@@+.",
+".+@@@@@@@@@@@@+.",
+".++++++@@++++++.",
+"......+@@+......",
+"......+@@+......",
+"......+@@+......",
+"......+@@+......",
+"......++++......"};
diff --git a/mgllab/xpm/zoom_in.xpm b/mgllab/xpm/zoom_in.xpm
new file mode 100644
index 0000000..22e285b
--- /dev/null
+++ b/mgllab/xpm/zoom_in.xpm
@@ -0,0 +1,124 @@
+/* XPM */
+static const char * zoom_in_xpm[] = {
+"16 16 105 2",
+"  	c None",
+". 	c #878B87",
+"+ 	c #868C8A",
+"@ 	c #888B89",
+"# 	c #ACB6BF",
+"$ 	c #CDD6DD",
+"% 	c #E4E7E9",
+"& 	c #929594",
+"* 	c #CFD8E0",
+"= 	c #D3DDE5",
+"- 	c #A4BFDC",
+"; 	c #99B9DA",
+"> 	c #9AB9DA",
+", 	c #A4BFDD",
+"' 	c #CFDAE5",
+") 	c #B4C9DF",
+"! 	c #9DBDDD",
+"~ 	c #B5CDE6",
+"{ 	c #5C84B8",
+"] 	c #5B84B8",
+"^ 	c #B0CAE4",
+"/ 	c #9ABADD",
+"( 	c #98B9DC",
+"_ 	c #BCD1E8",
+": 	c #5F87B9",
+"< 	c #FFFFFF",
+"[ 	c #5A84B7",
+"} 	c #ABC6E2",
+"| 	c #91B4DA",
+"1 	c #868C8B",
+"2 	c #9DBBDA",
+"3 	c #B6CDE6",
+"4 	c #5D85B8",
+"5 	c #5E86B8",
+"6 	c #5982B7",
+"7 	c #5781B6",
+"8 	c #9FBDDE",
+"9 	c #9EBBDA",
+"0 	c #878B88",
+"a 	c #8EB2D6",
+"b 	c #5983B7",
+"c 	c #507DB4",
+"d 	c #86ACD4",
+"e 	c #89AED4",
+"f 	c #4E7BB3",
+"g 	c #4A78B2",
+"h 	c #878C8B",
+"i 	c #CFD8DE",
+"j 	c #A7C1DD",
+"k 	c #86ADD6",
+"l 	c #4F7CB3",
+"m 	c #89AED6",
+"n 	c #A9C3DE",
+"o 	c #D0D8DE",
+"p 	c #888B87",
+"q 	c #B1BAC1",
+"r 	c #D9E1E8",
+"s 	c #94B6DA",
+"t 	c #96B7DB",
+"u 	c #527EB5",
+"v 	c #537EB5",
+"w 	c #97B8DB",
+"x 	c #DAE2E8",
+"y 	c #B2BBC1",
+"z 	c #8A8C8A",
+"A 	c #D7DDE2",
+"B 	c #CAD8E6",
+"C 	c #A4C0DF",
+"D 	c #A6C2E0",
+"E 	c #A7C3E1",
+"F 	c #D8DEE3",
+"G 	c #949895",
+"H 	c #DADFE3",
+"I 	c #E1E6EA",
+"J 	c #C7D7E8",
+"K 	c #BDD2E6",
+"L 	c #BED2E6",
+"M 	c #C8D8E8",
+"N 	c #DFE5EA",
+"O 	c #DBE0E4",
+"P 	c #959896",
+"Q 	c #9DA09B",
+"R 	c #60625F",
+"S 	c #8A8D8A",
+"T 	c #BCC1C4",
+"U 	c #DCE0E2",
+"V 	c #E9EBEB",
+"W 	c #BDC2C5",
+"X 	c #898C88",
+"Y 	c #878A84",
+"Z 	c #B9BCB6",
+"` 	c #BDBFBC",
+" .	c #61635F",
+"..	c #8A8C88",
+"+.	c #8D918D",
+"@.	c #8B8D89",
+"#.	c #8E918D",
+"$.	c #575955",
+"%.	c #7A7B78",
+"&.	c #B7B8B6",
+"*.	c #595B57",
+"=.	c #555753",
+"-.	c #767873",
+";.	c #A0A29F",
+">.	c #565854",
+"        . + . . + .             ",
+"      @ # $ % % $ # @           ",
+"    & * = - ; > , ' * &         ",
+"  @ * ) ! ~ { ] ^ / ) * @       ",
+". # ' ( _ : < < [ } | ' # .     ",
+"1 $ 2 3 4 5 < < 6 7 8 9 $ +     ",
+"0 % a b < < < < < < c d % .     ",
+"0 % e f < < < < < < g e % .     ",
+"h i j k f f < < l f m n o h     ",
+"p q r s t u < < v ( w x y p     ",
+"  z A B C D 7 7 E D B F .       ",
+"    G H I J K L M N O P Q R     ",
+"      S T U V V U W X Y Z `  .  ",
+"        ..+. at .@.#...  $.%.Y &.*.",
+"                        =.-.;.*.",
+"                          =.>.  "};
diff --git a/mgllab/xpm/zoom_out.xpm b/mgllab/xpm/zoom_out.xpm
new file mode 100644
index 0000000..82b040e
--- /dev/null
+++ b/mgllab/xpm/zoom_out.xpm
@@ -0,0 +1,130 @@
+/* XPM */
+static const char * zoom_out_xpm[] = {
+"16 16 111 2",
+"  	c None",
+". 	c #878B87",
+"+ 	c #868C8A",
+"@ 	c #888B89",
+"# 	c #ACB6BF",
+"$ 	c #CDD6DD",
+"% 	c #E4E7E9",
+"& 	c #929594",
+"* 	c #CFD8E0",
+"= 	c #D3DDE5",
+"- 	c #A4BFDC",
+"; 	c #99B9DA",
+"> 	c #9AB9DA",
+", 	c #A4BFDD",
+"' 	c #CFDAE5",
+") 	c #B4C9DF",
+"! 	c #9DBDDD",
+"~ 	c #B5CDE6",
+"{ 	c #5C84B8",
+"] 	c #5B84B8",
+"^ 	c #B0CAE4",
+"/ 	c #9ABADD",
+"( 	c #98B9DC",
+"_ 	c #BCD1E8",
+": 	c #5F87B9",
+"< 	c #FFFFFF",
+"[ 	c #5A84B7",
+"} 	c #ABC6E2",
+"| 	c #91B4DA",
+"1 	c #868C8B",
+"2 	c #9DBBDA",
+"3 	c #B6CDE6",
+"4 	c #5D85B8",
+"5 	c #5982B7",
+"6 	c #A7C3E1",
+"7 	c #9FBDDE",
+"8 	c #9EBBDA",
+"9 	c #878B88",
+"0 	c #8EB2D6",
+"a 	c #5A83B7",
+"b 	c #5681B6",
+"c 	c #9EBDDE",
+"d 	c #86ACD4",
+"e 	c #89AED4",
+"f 	c #8AAFD7",
+"g 	c #94B6DB",
+"h 	c #547FB5",
+"i 	c #507DB4",
+"j 	c #85ACD5",
+"k 	c #7BA5D2",
+"l 	c #878C8B",
+"m 	c #CFD8DE",
+"n 	c #A7C1DD",
+"o 	c #86ADD6",
+"p 	c #89AED6",
+"q 	c #4E7BB3",
+"r 	c #4F7CB3",
+"s 	c #8BB0D7",
+"t 	c #A9C3DE",
+"u 	c #D0D8DE",
+"v 	c #888B87",
+"w 	c #B1BAC1",
+"x 	c #D9E1E8",
+"y 	c #94B6DA",
+"z 	c #96B7DB",
+"A 	c #527EB5",
+"B 	c #537EB5",
+"C 	c #97B8DB",
+"D 	c #DAE2E8",
+"E 	c #B2BBC1",
+"F 	c #8A8C8A",
+"G 	c #D7DDE2",
+"H 	c #CAD8E6",
+"I 	c #A4C0DF",
+"J 	c #A6C2E0",
+"K 	c #5781B6",
+"L 	c #D8DEE3",
+"M 	c #949895",
+"N 	c #DADFE3",
+"O 	c #E1E6EA",
+"P 	c #C7D7E8",
+"Q 	c #BDD2E6",
+"R 	c #BED2E6",
+"S 	c #C8D8E8",
+"T 	c #DFE5EA",
+"U 	c #DBE0E4",
+"V 	c #959896",
+"W 	c #9DA09B",
+"X 	c #60625F",
+"Y 	c #8A8D8A",
+"Z 	c #BCC1C4",
+"` 	c #DCE0E2",
+" .	c #E9EBEB",
+"..	c #BDC2C5",
+"+.	c #898C88",
+"@.	c #878A84",
+"#.	c #B9BCB6",
+"$.	c #BDBFBC",
+"%.	c #61635F",
+"&.	c #8A8C88",
+"*.	c #8D918D",
+"=.	c #8B8D89",
+"-.	c #8E918D",
+";.	c #575955",
+">.	c #7A7B78",
+",.	c #B7B8B6",
+"'.	c #595B57",
+").	c #555753",
+"!.	c #767873",
+"~.	c #A0A29F",
+"{.	c #565854",
+"        . + . . + .             ",
+"      @ # $ % % $ # @           ",
+"    & * = - ; > , ' * &         ",
+"  @ * ) ! ~ { ] ^ / ) * @       ",
+". # ' ( _ : < < [ } | ' # .     ",
+"1 $ 2 3 4 < < < 5 6 7 8 $ +     ",
+"9 % 0 ^ [ a < < b c | d % .     ",
+"9 % e f g h < < i j k e % .     ",
+"l m n o p q < < r s p t u l     ",
+"v w x y z A < < B ( C D E v     ",
+"  F G H I J K K 6 J H L .       ",
+"    M N O P Q R S T U V W X     ",
+"      Y Z `  . .` ..+. at .#.$.%.  ",
+"        &.*.=.=.-.&.  ;.>. at .,.'.",
+"                        ).!.~.'.",
+"                          ).{.  "};
diff --git a/mgltex/CMakeLists.txt b/mgltex/CMakeLists.txt
new file mode 100644
index 0000000..c583a48
--- /dev/null
+++ b/mgltex/CMakeLists.txt
@@ -0,0 +1,54 @@
+find_program(findpdflatex pdflatex)
+if(NOT findpdflatex)
+	message(SEND_ERROR "Couldn't find pdflatex needed for LATEX example building.")
+endif(NOT findpdflatex)
+find_program(findkpsewhich kpsewhich)
+if(NOT findkpsewhich)
+	message(SEND_ERROR "Couldn't find kpsewhich needed for LATEX example install.")
+endif(NOT findkpsewhich)
+find_program(findmktexlsr mktexlsr)
+if(NOT findmktexlsr)
+	message(SEND_ERROR "Couldn't find mktexlsr needed for LATEX example install.")
+endif(NOT findmktexlsr)
+execute_process(
+	COMMAND ${findkpsewhich} -var-value=TEXMFLOCAL
+	OUTPUT_VARIABLE TEXMFLOCALDIR
+	RESULT_VARIABLE TEXMFLOCAL_ERR
+	OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+if(NOT TEXMFLOCALDIR)
+	message(SEND_ERROR "Couldn't find TEXMFLOCAL directory.")
+endif(NOT TEXMFLOCALDIR)
+
+# set(extramgl Axis_projection Vectorial)
+
+add_custom_command(OUTPUT mgltex.sty
+	COMMAND ${CMAKE_COMMAND} -E copy ${MathGL2_SOURCE_DIR}/mgltex/mgltex.ins ${MathGL2_BINARY_DIR}/mgltex/
+	COMMAND ${CMAKE_COMMAND} -E copy ${MathGL2_SOURCE_DIR}/mgltex/mgltex.dtx ${MathGL2_BINARY_DIR}/mgltex/
+	COMMAND ${CMAKE_COMMAND} -E copy ${MathGL2_SOURCE_DIR}/mgltex/Recompilation_decision.pdf ${MathGL2_BINARY_DIR}/mgltex/
+	COMMAND ${findpdflatex} mgltex.ins
+	COMMAND ${findpdflatex} mgltex.dtx
+	COMMAND ${findpdflatex} mgltex.dtx
+	COMMAND ${findpdflatex} mgltex.dtx
+	DEPENDS mgltex.dtx Recompilation_decision.pdf )
+
+add_custom_command(OUTPUT sample.pdf
+	COMMAND ${CMAKE_COMMAND} -E make_directory ${MathGL2_BINARY_DIR}/mgltex/MGL
+	COMMAND ${CMAKE_COMMAND} -E make_directory ${MathGL2_BINARY_DIR}/mgltex/MGL/scripts
+	COMMAND ${CMAKE_COMMAND} -E make_directory ${MathGL2_BINARY_DIR}/mgltex/MGL/backups
+	COMMAND ${CMAKE_COMMAND} -E make_directory ${MathGL2_BINARY_DIR}/mgltex/MGL/graphics
+	COMMAND ${CMAKE_COMMAND} -E copy ${MathGL2_SOURCE_DIR}/mgltex/sample.tex ${MathGL2_BINARY_DIR}/mgltex/
+# 	COMMAND ${CMAKE_COMMAND} -E copy ${MathGL2_SOURCE_DIR}/mgltex/mgltex.sty ${MathGL2_BINARY_DIR}/mgltex/
+	COMMAND PATH=$<TARGET_FILE_DIR:mglconv> ${findpdflatex} --shell-escape -draftmode sample.tex
+	COMMAND PATH=$<TARGET_FILE_DIR:mglconv> ${findpdflatex} --shell-escape -draftmode sample.tex
+	COMMAND PATH=$<TARGET_FILE_DIR:mglconv> ${findpdflatex} --shell-escape sample.tex
+	DEPENDS mgltex.sty sample.tex )
+add_custom_target(pdf ALL DEPENDS sample.pdf)
+
+get_directory_property(mglconv_clean ADDITIONAL_MAKE_CLEAN_FILES)
+set(mglconv_clean ${mglconv_clean} scripts mgltex.sty sample.tex sample.aux sample.log)
+set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${mglconv_clean}")
+
+install(FILES ${MathGL2_BINARY_DIR}/mgltex/mgltex.sty DESTINATION ${TEXMFLOCALDIR}/tex/latex/mgltex/)
+install(FILES sample.tex mgltex.pdf ${MathGL2_BINARY_DIR}/mgltex/sample.pdf DESTINATION ${TEXMFLOCALDIR}/doc/latex/mgltex/)
+install(CODE "execute_process(COMMAND ${findmktexlsr} ${TEXMFLOCALDIR})")
diff --git a/mgltex/Recompilation_decision.eps b/mgltex/Recompilation_decision.eps
new file mode 100644
index 0000000..c454a17
--- /dev/null
+++ b/mgltex/Recompilation_decision.eps
@@ -0,0 +1,1940 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: cairo 1.13.1 (http://cairographics.org)
+%%CreationDate: Sat Nov  7 15:28:00 2015
+%%Pages: 1
+%%DocumentData: Clean7Bit
+%%LanguageLevel: 3
+%%BoundingBox: 0 -1 631 791
+%%EndComments
+%%BeginProlog
+save
+50 dict begin
+/q { gsave } bind def
+/Q { grestore } bind def
+/cm { 6 array astore concat } bind def
+/w { setlinewidth } bind def
+/J { setlinecap } bind def
+/j { setlinejoin } bind def
+/M { setmiterlimit } bind def
+/d { setdash } bind def
+/m { moveto } bind def
+/l { lineto } bind def
+/c { curveto } bind def
+/h { closepath } bind def
+/re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto
+      0 exch rlineto 0 rlineto closepath } bind def
+/S { stroke } bind def
+/f { fill } bind def
+/f* { eofill } bind def
+/n { newpath } bind def
+/W { clip } bind def
+/W* { eoclip } bind def
+/BT { } bind def
+/ET { } bind def
+/pdfmark where { pop globaldict /?pdfmark /exec load put }
+    { globaldict begin /?pdfmark /pop load def /pdfmark
+    /cleartomark load def end } ifelse
+/BDC { mark 3 1 roll /BDC pdfmark } bind def
+/EMC { mark /EMC pdfmark } bind def
+/cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def
+/Tj { show currentpoint cairo_store_point } bind def
+/TJ {
+  {
+    dup
+    type /stringtype eq
+    { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse
+  } forall
+  currentpoint cairo_store_point
+} bind def
+/cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore
+    cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def
+/Tf { pop /cairo_font exch def /cairo_font_matrix where
+      { pop cairo_selectfont } if } bind def
+/Td { matrix translate cairo_font_matrix matrix concatmatrix dup
+      /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point
+      /cairo_font where { pop cairo_selectfont } if } bind def
+/Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def
+      cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def
+/g { setgray } bind def
+/rg { setrgbcolor } bind def
+/d1 { setcachedevice } bind def
+%%EndProlog
+%%BeginSetup
+%%BeginResource: font DejaVuSans
+11 dict begin
+/FontType 42 def
+/FontName /DejaVuSans def
+/PaintType 0 def
+/FontMatrix [ 1 0 0 1 0 0 ] def
+/FontBBox [ 0 0 0 0 ] def
+/Encoding 256 array def
+0 1 255 { Encoding exch /.notdef put } for
+Encoding 32 /space put
+Encoding 46 /period put
+Encoding 47 /slash put
+Encoding 60 /less put
+Encoding 62 /greater put
+Encoding 63 /question put
+Encoding 64 /at put
+Encoding 65 /A put
+Encoding 67 /C put
+Encoding 68 /D put
+Encoding 69 /E put
+Encoding 70 /F put
+Encoding 71 /G put
+Encoding 73 /I put
+Encoding 76 /L put
+Encoding 77 /M put
+Encoding 78 /N put
+Encoding 82 /R put
+Encoding 83 /S put
+Encoding 85 /U put
+Encoding 89 /Y put
+Encoding 92 /backslash put
+Encoding 97 /a put
+Encoding 99 /c put
+Encoding 100 /d put
+Encoding 101 /e put
+Encoding 104 /h put
+Encoding 105 /i put
+Encoding 108 /l put
+Encoding 109 /m put
+Encoding 110 /n put
+Encoding 111 /o put
+Encoding 112 /p put
+Encoding 113 /q put
+Encoding 114 /r put
+Encoding 115 /s put
+Encoding 116 /t put
+Encoding 117 /u put
+Encoding 118 /v put
+Encoding 119 /w put
+Encoding 121 /y put
+/CharStrings 42 dict dup begin
+/.notdef 0 def
+/S 1 def
+/t 2 def
+/a 3 def
+/r 4 def
+/F 5 def
+/i 6 def
+/n 7 def
+/d 8 def
+/backslash 9 def
+/M 10 def
+/G 11 def
+/L 12 def
+/at 13 def
+/less 14 def
+/s 15 def
+/c 16 def
+/p 17 def
+/greater 18 def
+/I 19 def
+/space 20 def
+/e 21 def
+/question 22 def
+/C 23 def
+/o 24 def
+/m 25 def
+/v 26 def
+/period 27 def
+/R 28 def
+/w 29 def
+/slash 30 def
+/l 31 def
+/U 32 def
+/D 33 def
+/E 34 def
+/A 35 def
+/h 36 def
+/y 37 def
+/q 38 def
+/u 39 def
+/Y 40 def
+/N 41 def
+end readonly def
+/sfnts [
+<0001000000090080000300106376742000691d3900001d14000001fe6670676d7134766a0000
+1f14000000ab676c796600c0787b0000009c00001c7868656164026638f700001fc000000036
+686865610cb8067b00001ff800000024686d7478cb7f16780000201c000000a86c6f63610002
+4608000020c4000000ac6d617870049706710000217000000020707265703b07f10000002190
+0000056800020066fe96046605a400030007001a400c04fb0006fb0108057f0204002fc4d4ec
+310010d4ecd4ec301311211125211121660400fc73031bfce5fe96070ef8f272062900010087
+ffe304a205f00027007e403c0d0c020e0b021e1f1e080902070a021f1f1e420a0b1e1f041501
+0015a11494189511049500942591118c281e0a0b1f1b0700221b190e2d071914222810dcc4ec
+fcece4111239393939310010e4f4e4ec10eef6ee10c6111739304b535807100eed1117390710
+0eed1117395922b20f2901015db61f292f294f29035d01152e012322061514161f011e011514
+0421222627351e013332363534262f012e01353424333216044873cc5fa5b377a67ae2d7fedd
+fee76aef807bec72adbc879a7be2ca0117f569da05a4c53736807663651f192bd9b6d9e0302f
+d04546887e6e7c1f182dc0abc6e4260000010037000002f2059e0013003840190e05080f03a9
+001101bc08870a0b08090204000810120e461410fc3cc4fc3cc432393931002fecf43cc4ec32
+11393930b2af1501015d01112115211114163b01152322263511233533110177017bfe854b73
+bdbdd5a28787059efec28ffda0894e9a9fd202608f013e0000000002007bffe3042d047b000a
+002500bc4027191f0b17090e00a91706b90e1120861fba1cb923b8118c170c001703180d0908
+0b1f030814452610fcecccd4ec323211393931002fc4e4f4fcf4ec10c6ee10ee113911391239
+30406e301d301e301f3020302130223f27401d401e401f402040214022501d501e501f502050
+21502250277027851d871e871f8720872185229027a027f0271e301e301f30203021401e401f
+40204021501e501f50205021601e601f60206021701e701f70207021801e801f80208021185d
+015d0122061514163332363d01371123350e01232226353436332135342623220607353e0133
+321602bedfac816f99b9b8b83fbc88accbfdfb0102a79760b65465be5af3f00233667b6273d9
+b4294cfd81aa6661c1a2bdc0127f8b2e2eaa2727fc00000100ba0000034a047b001100304014
+060b0700110b03870eb809bc070a06080008461210fcc4ec3231002fe4f4ecc4d4cc11123930
+b450139f1302015d012e012322061511231133153e0133321617034a1f492c9ca7b9b93aba85
+132e1c03b41211cbbefdb20460ae666305050000000100c90000042305d50009002940120695
+040295008104ad08050107031c00040a10fcec32d4c431002fecf4ec10ee30b20f0b01015d13
+211521112115211123c9035afd700250fdb0ca05d5aafe48aafd3700000200c1000001790614
+00030007002b400e06be04b100bc020501080400460810fc3cec3231002fe4fcec30400b1009
+400950096009700905015d1333112311331523c1b8b8b8b80460fba00614e900000100ba0000
+0464047b001300364019030900030e0106870e11b80cbc0a010208004e0d09080b461410fcec
+32f4ec31002f3ce4f4c4ec1112173930b46015cf1502015d0111231134262322061511231133
+153e013332160464b87c7c95acb9b942b375c1c602a4fd5c029e9f9ebea4fd870460ae6564ef
+00020071ffe3045a06140010001c003840191ab9000e14b905088c0eb8019703170400080247
+11120b451d10fcecf4ec323231002fece4f4c4ec10c4ee30b6601e801ea01e03015d01113311
+23350e0123220211100033321601141633323635342623220603a2b8b83ab17ccbff00ffcb7c
+b1fdc7a79292a8a89292a703b6025ef9eca86461014401080108014461fe15cbe7e7cbcbe7e7
+00010000ff4202b205d50003002d4014021a010100001a03030242019f008104020001032fc4
+3939310010f4ec304b5358071005ed071005ed592213012301aa0208aafdf805d5f96d069300
+000100c90000061f05d5000c00bf403403110708070211010208080702110302090a0901110a
+0a09420a070203080300af080b050908030201050a061c043e0a1c00040d10fcecfcec111739
+31002f3cc4ec32111739304b5358071005ed071008ed071008ed071005ed5922b2700e01015d
+405603070f080f09020a15021407130a260226072007260a200a3407350a69027c027b07790a
+80028207820a90021604010b0313011b0323012c032708280934013c035608590965086a0976
+08790981018d0395019b03145d005d13210901211123110123011123c9012d017d017f012dc5
+fe7fcbfe7fc405d5fc0803f8fa2b051ffc000400fae1000000010073ffe3058b05f0001d0039
+402000051b0195031b950812a111ae15950e91088c1e02001c1134043318190b101e10fcecfc
+e4fcc4310010e4f4ecf4ec10fed4ee1139393025112135211106042320001110002132041715
+2e0123200011100021323604c3feb6021275fee6a0fea2fe75018b015e9201076f70fc8bfeee
+feed011301126ba8d50191a6fd7f53550199016d016e01994846d75f60fecefed1fed2fece25
+0000000100c90000046a05d500050025400c0295008104011c033a00040610fcecec31002fe4
+ec304009300750078003800404015d133311211521c9ca02d7fc5f05d5fad5aa00020087fe9c
+077105a2000b004c00954032180c0309a919151b03a94c0f34330fac30a93715ac24a937434d
+33341e1a00281206180c281a2b1e2849122b2a28492c3d4d10dcecfcec10fefdfe3cc610ee11
+123939310010d4c4fcec10feedd4c610c5ee3210c4ee11393930004bb009544bb00c545b4bb0
+10545b4bb013545b4bb014545b58bd004dffc00001004d004d0040381137385940090f4e1f4e
+2f4e3f4e04015d011416333236353426232206010e01232226353436333216173533113e0135
+3426272624232206070602151412171604333236371706042322242726023534123736243332
+04171e011510000502fa8e7c7b8d907a798f02213c9b67acd7d8ab679c3b8f92a53f4068fed5
+b07be2609db1736d6901149d81f9685a7dfed998b9feb8808086887e810152bdd4016b7b4b4f
+fec2fee802198fa3a48e8ca5a4fe484d49f9c8c8fa4b4c83fd2016dfb16bbc50838b414066fe
+b5c19ffeea6a686d57516f6167837d7d0149bdb6014a7d7f87aea062e67bfef9fed006000001
+00d9005e05db04a60006004d402a029c030403019c0001040403019c0201050605009c060542
+05040201000503a806a7070102002404230710fcec3239310010f4ec1739304b53580704ed07
+1008ed071008ed071004ed592209021501350105dbfbf80408fafe050203f0fe91fe93b601d1
+a601d1000001006fffe303c7047b002700e7403c0d0c020e0b531f1e080902070a531f1f1e42
+0a0b1e1f041500860189041486158918b91104b925b8118c281e0a0b1f1b0700521b080e0708
+1422452810fcc4ecd4ece4111239393939310010e4f4ec10fef5ee10f5ee121739304b535807
+100eed111739070eed1117395922b2002701015d406d1c0a1c0b1c0c2e092c0a2c0b2c0c3b09
+3b0a3b0b3b0c0b200020012402280a280b2a132f142f152a16281e281f292029212427860a86
+0b860c860d12000000010202060a060b030c030d030e030f03100319031a031b031c041d0927
+2f293f295f297f2980299029a029f029185d005d7101152e012322061514161f011e01151406
+23222627351e013332363534262f012e01353436333216038b4ea85a898962943fc4a5f7d85a
+c36c66c661828c65ab40ab98e0ce66b4043fae282854544049210e2a99899cb62323be353559
+514b50250f2495829eac1e00000000010071ffe303e7047b0019003f401b00860188040e860d
+880ab91104b917b8118c1a07120d004814451a10fce432ec310010e4f4ec10fef4ee10f5ee30
+400b0f1b101b801b901ba01b05015d01152e0123220615141633323637150e01232200111000
+21321603e74e9d50b3c6c6b3509d4e4da55dfdfed6012d010655a20435ac2b2be3cdcde32b2b
+aa2424013e010e0112013a230000000200bafe5604a4047b0010001c003e401b1ab9000e14b9
+0508b80e8c01bd03bc1d11120b471704000802461d10fcec3232f4ec310010e4e4e4f4c4ec10
+c4ee304009601e801ea01ee01e04015d2511231133153e013332001110022322260134262322
+061514163332360173b9b93ab17bcc00ffffcc7bb10238a79292a7a79292a7a8fdae060aaa64
+61febcfef8fef8febc6101ebcbe7e7cbcbe7e7000000000100d9005e05db04a60006004f402b
+069c0006030403059c040403009c010201069c05060202014206050302000504a801a7070602
+240400230710fc3cec39310010f4ec1739304b5358071008ed071004ed071004ed071008ed59
+2213350115013501d90502fafe040603f0b6fe2fa6fe2fb6016d0000000100c90000019305d5
+0003002eb700af02011c00040410fc4bb0105458b9000000403859ec31002fec3001400d3005
+4005500560058f059f05065d13331123c9caca05d5fa2b0000020071ffe3047f047b0014001b
+00704024001501098608880515a90105b90c01bb18b912b80c8c1c1b1502081508004b02120f
+451c10fcecf4ecc4111239310010e4f4ece410ee10ee10f4ee1112393040293f1d701da01dd0
+1df01d053f003f013f023f153f1b052c072f082f092c0a6f006f016f026f156f1b095d71015d
+0115211e0133323637150e01232000111000333200072e0123220607047ffcb20ccdb76ac762
+63d06bfef4fec70129fce20107b802a5889ab90e025e5abec73434ae2a2c0138010a01130143
+feddc497b4ae9e0000020093000003b005f0000300240065402b241e0906040a1d1304001486
+1388109517910083021d1a0d0905040a1e010d1c1a041c05010300261a132510dc4bb00c5458
+b90013ffc03859c4fcecd4ec10ee11393911123911123931002feef6fef4ee10cd1139391739
+3001b679097a0a7a20035d2533152313233534363f013e0135342623220607353e0133321615
+14060f010e01070e01150187cbcbc5bf385a5a3933836c4fb3615ec167b8df485a582f270806
+06fefe01919a65825659355e31596e4643bc3938c29f4c8956562f3519153c34000000010073
+ffe3052705f000190036401a0da10eae0a951101a100ae04951791118c1a07190d003014101a
+10fcec32ec310010e4f4ecf4ec10eef6ee30b40f1b1f1b02015d01152e012320001110002132
+3637150e01232000111000213216052766e782ff00fef00110010082e7666aed84feadfe7a01
+86015386ed0562d55f5efec7fed8fed9fec75e5fd34848019f01670168019f47000000020071
+ffe30475047b000b0017004a401306b91200b90cb8128c1809120f51031215451810fcecf4ec
+310010e4f4ec10ee3040233f197b007b067f077f087f097f0a7f0b7b0c7f0d7f0e7f0f7f107f
+117b12a019f01911015d012206151416333236353426273200111000232200111000027394ac
+ab9593acac93f00112feeef0f1feef011103dfe7c9c9e7e8c8c7e99cfec8feecfeedfec70139
+0113011401380000000100ba0000071d047b0022005a4026061209180f00061d07150c871d20
+03b81bbc19100700110f0808065011080f501c18081a462310fcec32fcfcfcec11123931002f
+3c3ce4f43cc4ec32111217393040133024502470249024a024a024bf24df24ff2409015d013e
+013332161511231134262322061511231134262322061511231133153e01333216042945c082
+afbeb972758fa6b972778da6b9b93fb0797aab03897c76f5e2fd5c029ea19cbea4fd87029ea2
+9bbfa3fd870460ae67627c0000000001003d0000047f0460000600fb40270311040504021101
+0205050402110302060006011100000642020300bf0506050302010504000710d44bb00a5458
+b90000004038594bb014544bb015545b58b90000ffc03859c4173931002fec3239304b535807
+1005ed071008ed071008ed071005ed592201408e48026a027b027f02860280029102a4020806
+00060109030904150015011a031a0426002601290329042008350035013a033a043008460046
+0149034904460548064008560056015903590450086600660169036904670568066008750074
+017b037b0475057a068500850189038904890586069600960197029a03980498059706a805a7
+06b008c008df08ff083e5d005d133309013301233dc3015e015ec3fe5cfa0460fc5403acfba0
+0000000100db000001ae00fe00030011b7008302011900180410fcec31002fec3037331523db
+d3d3fefe000200c90000055405d50013001c00b14035090807030a0611030403051104040342
+06040015030415950914950d810b040506031109001c160e050a191904113f140a1c0c041d10
+fcec32fcc4ec1117391139393931002f3cf4ecd4ec123912391239304b5358071005ed071005
+ed1117395922b2401e01015d40427a1301050005010502060307041500150114021603170425
+002501250226032706260726082609201e360136024601460268057504750577138806880798
+0698071f5d005d011e01171323032e012b01112311212016151406011133323635342623038d
+417b3ecdd9bf4a8b78dcca01c80100fc83fd89fe9295959202bc16907efe68017f9662fd8905
+d5d6d88dba024ffdee878383850000010056000006350460000c01eb404905550605090a0904
+550a0903550a0b0a025501020b0b0a061107080705110405080807021103020c000c01110000
+0c420a050203060300bf0b080c0b0a09080605040302010b07000d10d44bb00a544bb011545b
+4bb012545b4bb013545b4bb00b545b58b9000000403859014bb00c544bb00d545b4bb010545b
+58b90000ffc03859cc173931002f3cec32321739304b5358071005ed071008ed071008ed0710
+05ed071008ed071005ed0705ed071008ed59220140ff050216021605220a350a49024905460a
+400a5b025b05550a500a6e026e05660a79027f0279057f05870299029805940abc02bc05ce02
+c703cf051d0502090306040b050a080b09040b050c1502190316041a051b081b09140b150c25
+00250123022703210425052206220725082709240a210b230c390336043608390c300e460248
+034604400442054006400740084409440a440b400e400e560056015602500451055206520750
+085309540a550b6300640165026a0365046a056a066a076e09610b670c6f0e7500750179027d
+0378047d057a067f067a077f07780879097f097b0a760b7d0c870288058f0e97009701940293
+039c049b05980698079908402f960c9f0ea600a601a402a403ab04ab05a906a907ab08a40caf
+0eb502b103bd04bb05b809bf0ec402c303cc04ca05795d005d13331b01331b013301230b0123
+56b8e6e5d9e6e5b8fedbd9f1f2d90460fc96036afc96036afba00396fc6a00010000ff4202b2
+05d50003002d4014001a010201021a03000342029f008104020001032fc43939310010f4ec30
+4b5358071005ed071005ed5922013301230208aafdf8aa05d5f96d000000000100c100000179
+061400030022b7009702010800460410fcec31002fec30400d10054005500560057005f00506
+015d13331123c1b8b80614f9ec00000100b2ffe3052905d50011004040160802110b0005950e
+8c09008112081c0a38011c00411210fc4bb0105458b90000ffc03859ecfcec310010e432f4ec
+11393939393001b61f138f139f13035d133311141633323635113311100021200011b2cbaec3
+c2aecbfedffee6fee5fedf05d5fc75f0d3d3f0038bfc5cfedcfed6012a012400000200c90000
+05b005d500080011002e4015009509810195100802100a0005190d32001c09041210fcecf4ec
+113939393931002fecf4ec30b2601301015d0111332000111000212521200011100029010193
+f40135011ffee1fecbfe42019f01b20196fe68fe50fe61052ffb770118012e012c0117a6fe97
+fe80fe7efe960000000100c90000048b05d5000b002e401506950402950081089504ad0a0501
+0907031c00040c10fcec32d4c4c431002fececf4ec10ee30b21f0d01015d1321152111211521
+11211521c903b0fd1a02c7fd3902f8fc3e05d5aafe46aafde3aa0000000200100000056805d5
+0002000a00c2404100110100040504021105050401110a030a0011020003030a071105040611
+0505040911030a08110a030a4200030795010381090509080706040302010009050a0b10d4c4
+173931002f3ce4d4ec1239304b5358071005ed0705ed071005ed0705ed071008ed071005ed07
+1005ed071008ed5922b2200c01015d40420f010f020f070f080f005800760070008c00090701
+0802060309041601190256015802500c67016802780176027c0372047707780887018802800c
+980299039604175d005d090121013301230321032302bcfeee0225fe7be50239d288fd5f88d5
+050efd1903aefa2b017ffe810000000100ba000004640614001300344019030900030e010687
+0e11b80c970a010208004e0d09080b461410fcec32f4ec31002f3cecf4c4ec1112173930b260
+1501015d0111231134262322061511231133113e013332160464b87c7c95acb9b942b375c1c6
+02a4fd5c029e9f9ebea4fd870614fd9e6564ef000001003dfe56047f0460000f018b40430708
+020911000f0a110b0a00000f0e110f000f0d110c0d00000f0d110e0d0a0b0a0c110b0b0a420d
+0b0910000b058703bd0e0bbc100e0d0c0a09060300080f040f0b1010d44bb00a544bb008545b
+58b9000b004038594bb0145458b9000bffc03859c4c4111739310010e432f4ec113911391239
+304b5358071005ed071008ed071008ed071005ed071008ed0705ed173259220140f006000508
+0609030d160a170d100d230d350d490a4f0a4e0d5a095a0a6a0a870d800d930d120a000a0906
+0b050c0b0e0b0f1701150210041005170a140b140c1a0e1a0f27002401240220042005290828
+09250a240b240c270d2a0e2a0f201137003501350230043005380a360b360c380d390e390f30
+114100400140024003400440054006400740084209450a470d490e490f401154005101510255
+03500450055606550756085709570a550b550c590e590f501166016602680a690e690f60117b
+08780e780f89008a09850b850c890d890e890f9909950b950c9a0e9a0fa40ba40cab0eab0fb0
+11cf11df11ff11655d005d050e012b01353332363f01013309013302934e947c936c4c543321
+fe3bc3015e015ec368c87a9a488654044efc94036c00000000020071fe56045a047b000b001c
+003e401b03b90c0f09b91815b80f8c1bbd19bc1d180c06081a47001212451d10fcecf4ec3232
+310010e4e4e4f4c4ec10c6ee304009601e801ea01ee01e04015d011416333236353426232206
+010e012322021110003332161735331123012fa79292a8a89292a702733ab17ccbff00ffcb7c
+b13ab8b8022fcbe7e7cbcbe7e7fdae646101440108010801446164aaf9f60000000200aeffe3
+0458047b00130014003b401c030900030e0106870e118c0a01bc14b80c0d0908140b4e020800
+461510fcecf439ec3231002fe4e432f4c4ec1112173930b46f15c01502015d13113311141633
+32363511331123350e0123222601aeb87c7c95adb8b843b175c1c801cf01ba02a6fd619f9fbe
+a4027bfba0ac6663f003a8000001fffc000004e705d500080094402803110405040211010205
+050402110302080008011100000842020300af0602070440051c0040070910d4e4fce4123931
+002fec3239304b5358071005ed071008ed071008ed071005ed5922b2000a01015d403c050214
+02350230023005300846024002400540085102510551086502840293021016011a031f0a2601
+290337013803400a670168037803700a9f0a0d5d005d03330901330111231104d9019e019bd9
+fdf0cb05d5fd9a0266fcf2fd3902c7000000000100c90000053305d500090079401e07110102
+0102110607064207020300af0805060107021c0436071c00040a10fcecfcec11393931002f3c
+ec323939304b5358071004ed071004ed5922b21f0b01015d4030360238074802470769026607
+8002070601090615011a06460149065701580665016906790685018a0695019a069f0b105d00
+5d13210111331121011123c901100296c4fef0fd6ac405d5fb1f04e1fa2b04e1fb1f013500b8
+00cb00cb00c100aa009c01a600b800660000007100cb00a002b20085007500b800c301cb0189
+022d00cb00a600f000d300aa008700cb03aa0400014a003300cb000000d9050200f4015400b4
+009c01390114013907060400044e04b4045204b804e704cd0037047304cd04600473013303a2
+055605a60556053903c5021200c9001f00b801df007300ba03e9033303bc0444040e00df03cd
+03aa00e503aa0404000000cb008f00a4007b00b80014016f007f027b0252008f00c705cd009a
+009a006f00cb00cd019e01d300f000ba018300d5009803040248009e01d500c100cb00f60083
+0354027f00000333026600d300c700a400cd008f009a0073040005d5010a00fe022b00a400b4
+009c00000062009c0000001d032d05d505d505d505f0007f007b005400a406b80614072301d3
+00b800cb00a601c301ec069300a000d3035c037103db0185042304a80448008f013901140139
+0360008f05d5019a0614072306660179046004600460047b009c00000277046001aa00e90460
+0762007b00c5007f027b000000b4025205cd006600bc00660077061000cd013b01850389008f
+007b0000001d00cd074a042f009c009c0000077d006f0000006f0335006a006f007b00ae00b2
+002d0396008f027b00f600830354063705f6008f009c04e10266008f018d02f600cd03440029
+006604ee00730000140000960000b707060504030201002c2010b002254964b040515820c859
+212d2cb002254964b040515820c859212d2c20100720b00050b00d7920b8ffff5058041b0559
+b0051cb0032508b0042523e120b00050b00d7920b8ffff5058041b0559b0051cb0032508e12d
+2c4b505820b0fd454459212d2cb002254560442d2c4b5358b00225b0022545445921212d2c45
+442d2cb00225b0022549b00525b005254960b0206368208a108a233a8a10653a2d0000010000
+0002570ae39778045f0f3cf5001f080000000000cef5cb7600000000cef5cb76f7d6fcae0d72
+095500000008000000010000000000010000076dfe1d00000de2f7d6fa510d72000100000000
+00000000000000000000002a04cd0066051400870323003704e7007b034a00ba049a00c90239
+00c1051200ba0514007102b2000006e700c906330073047500c90800008706b400d9042b006f
+04660071051400ba06b400d9025c00c9028b000004ec0071043f00930596007304e5007107cb
+00ba04bc003d028b00db058f00c9068b005602b20000023900c105db00b2062900c9050e00c9
+05790010051200ba04bc003d05140071051200ae04e3fffc05fc00c900000000000000440000
+013c000001b8000002e400000354000003a8000003f800000470000005080000055400000650
+000006f80000073c000008bc0000093400000a9400000b2c00000bcc00000c4400000c8c0000
+0c8c00000d6000000e3800000ed000000f74000010380000115c0000118400001298000014bc
+0000150800001544000015c800001648000016a8000017a40000181c000019e800001a880000
+1b0c00001bd000001c7800010000002a0354002b0068000c0002001000990008000004150216
+00080004b8028040fffbfe03fa1403f92503f83203f79603f60e03f5fe03f4fe03f32503f20e
+03f19603f02503ef8a4105effe03ee9603ed9603ecfa03ebfa03eafe03e93a03e84203e7fe03
+e63203e5e45305e59603e48a4105e45303e3e22f05e3fa03e22f03e1fe03e0fe03df3203de14
+03dd9603dcfe03db1203da7d03d9bb03d8fe03d68a4105d67d03d5d44705d57d03d44703d3d2
+1b05d3fe03d21b03d1fe03d0fe03cffe03cefe03cd9603cccb1e05ccfe03cb1e03ca3203c9fe
+03c6851105c61c03c51603c4fe03c3fe03c2fe03c1fe03c0fe03bffe03befe03bdfe03bcfe03
+bbfe03ba1103b9862505b9fe03b8b7bb05b8fe03b7b65d05b7bb03b78004b6b52505b65d40ff
+03b64004b52503b4fe03b39603b2fe03b1fe03b0fe03affe03ae6403ad0e03acab2505ac6403
+abaa1205ab2503aa1203a98a4105a9fa03a8fe03a7fe03a6fe03a51203a4fe03a3a20e05a332
+03a20e03a16403a08a4105a096039ffe039e9d0c059efe039d0c039c9b19059c64039b9a1005
+9b19039a1003990a0398fe0397960d0597fe03960d03958a410595960394930e05942803930e
+0392fa039190bb0591fe03908f5d0590bb039080048f8e25058f5d038f40048e25038dfe038c
+8b2e058cfe038b2e038a8625058a410389880b05891403880b03878625058764038685110586
+250385110384fe038382110583fe0382110381fe0380fe037ffe0340ff7e7d7d057efe037d7d
+037c64037b5415057b25037afe0379fe03780e03770c03760a0375fe0374fa0373fa0372fa03
+71fa0370fe036ffe036efe036c21036bfe036a1142056a530369fe03687d036711420566fe03
+65fe0364fe0363fe0362fe03613a0360fa035e0c035dfe035bfe035afe0359580a0559fa0358
+0a035716190557320356fe035554150555420354150353011005531803521403514a130551fe
+03500b034ffe034e4d10054efe034d10034cfe034b4a13054bfe034a4910054a1303491d0d05
+491003480d0347fe0346960345960344fe0343022d0543fa0342bb03414b0340fe033ffe033e
+3d12053e14033d3c0f053d12033c3b0d053c40ff0f033b0d033afe0339fe033837140538fa03
+3736100537140336350b05361003350b03341e03330d0332310b0532fe03310b03302f0b0530
+0d032f0b032e2d09052e10032d09032c32032b2a25052b64032a2912052a2503291203282725
+0528410327250326250b05260f03250b0324fe0323fe03220f03210110052112032064031ffa
+031e1d0d051e64031d0d031c1142051cfe031bfa031a42031911420519fe0318640317161905
+17fe031601100516190315fe0314fe0313fe031211420512fe0311022d05114203107d030f64
+030efe030d0c16050dfe030c0110050c16030bfe030a100309fe0308022d0508fe0307140306
+64030401100504fe03401503022d0503fe0302011005022d0301100300fe0301b80164858d01
+2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
+2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
+2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
+2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
+2b2b2b2b2b2b2b2b2b2b2b2b2b002b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
+2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
+2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
+2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
+2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b1d00>
+] def
+/f-0-0 currentdict end definefont pop
+%%EndResource
+%%BeginResource: font DejaVuSans
+11 dict begin
+/FontType 42 def
+/FontName /DejaVuSans def
+/PaintType 0 def
+/FontMatrix [ 1 0 0 1 0 0 ] def
+/FontBBox [ 0 0 0 0 ] def
+/Encoding 256 array def
+0 1 255 { Encoding exch /.notdef put } for
+Encoding 1 /uniFB01 put
+/CharStrings 2 dict dup begin
+/.notdef 0 def
+/uniFB01 1 def
+end readonly def
+/sfnts [
+<0001000000090080000300106376742000691d3900000184000001fe6670676d7134766a0000
+0384000000ab676c7966aa72abf90000009c000000e868656164026638f70000043000000036
+686865610cb806530000046800000024686d747809d700950000048c000000086c6f63610000
+012c000004940000000c6d617870046f0671000004a000000020707265703b07f100000004c0
+0000056800020066fe96046605a400030007001a400c04fb0006fb0108057f0204002fc4d4ec
+310010d4ecd4ec301311211125211121660400fc73031bfce5fe96070ef8f27206290002002f
+0000044a061400150019005240111b46001708160f1404080803160a064c1a10fc3cc432c4fc
+3cc410fe3cec310040120803a90010870e18be16b10e970900bc05012f3ce632eefeee10ee10
+ee3230400bff1ba01b901b801b101b05015d01112311211123112335333534363b0115232206
+1d0101331523044ab9fe07b9b0b0adb3b9b0634d01f9b9b90460fba003d1fc2f03d18f4eb7af
+9950686301b2e900013500b800cb00cb00c100aa009c01a600b800660000007100cb00a002b2
+0085007500b800c301cb0189022d00cb00a600f000d300aa008700cb03aa0400014a003300cb
+000000d9050200f4015400b4009c01390114013907060400044e04b4045204b804e704cd0037
+047304cd04600473013303a2055605a60556053903c5021200c9001f00b801df007300ba03e9
+033303bc0444040e00df03cd03aa00e503aa0404000000cb008f00a4007b00b80014016f007f
+027b0252008f00c705cd009a009a006f00cb00cd019e01d300f000ba018300d5009803040248
+009e01d500c100cb00f600830354027f00000333026600d300c700a400cd008f009a00730400
+05d5010a00fe022b00a400b4009c00000062009c0000001d032d05d505d505d505f0007f007b
+005400a406b80614072301d300b800cb00a601c301ec069300a000d3035c037103db01850423
+04a80448008f0139011401390360008f05d5019a0614072306660179046004600460047b009c
+00000277046001aa00e904600762007b00c5007f027b000000b4025205cd006600bc00660077
+061000cd013b01850389008f007b0000001d00cd074a042f009c009c0000077d006f0000006f
+0335006a006f007b00ae00b2002d0396008f027b00f600830354063705f6008f009c04e10266
+008f018d02f600cd03440029006604ee00730000140000960000b707060504030201002c2010
+b002254964b040515820c859212d2cb002254964b040515820c859212d2c20100720b00050b0
+0d7920b8ffff5058041b0559b0051cb0032508b0042523e120b00050b00d7920b8ffff505804
+1b0559b0051cb0032508e12d2c4b505820b0fd454459212d2cb002254560442d2c4b5358b002
+25b0022545445921212d2c45442d2cb00225b0022549b00525b005254960b0206368208a108a
+233a8a10653a2d00000100000002570a13d8c3465f0f3cf5001f080000000000cef5cb760000
+0000cef5cb76f7d6fcae0d72095500000008000000010000000000010000076dfe1d00000de2
+f7d6fa510d7200010000000000000000000000000000000204cd0066050a002f000000000000
+0044000000e80001000000020354002b0068000c000200100099000800000415021600080004
+b8028040fffbfe03fa1403f92503f83203f79603f60e03f5fe03f4fe03f32503f20e03f19603
+f02503ef8a4105effe03ee9603ed9603ecfa03ebfa03eafe03e93a03e84203e7fe03e63203e5
+e45305e59603e48a4105e45303e3e22f05e3fa03e22f03e1fe03e0fe03df3203de1403dd9603
+dcfe03db1203da7d03d9bb03d8fe03d68a4105d67d03d5d44705d57d03d44703d3d21b05d3fe
+03d21b03d1fe03d0fe03cffe03cefe03cd9603cccb1e05ccfe03cb1e03ca3203c9fe03c68511
+05c61c03c51603c4fe03c3fe03c2fe03c1fe03c0fe03bffe03befe03bdfe03bcfe03bbfe03ba
+1103b9862505b9fe03b8b7bb05b8fe03b7b65d05b7bb03b78004b6b52505b65d40ff03b64004
+b52503b4fe03b39603b2fe03b1fe03b0fe03affe03ae6403ad0e03acab2505ac6403abaa1205
+ab2503aa1203a98a4105a9fa03a8fe03a7fe03a6fe03a51203a4fe03a3a20e05a33203a20e03
+a16403a08a4105a096039ffe039e9d0c059efe039d0c039c9b19059c64039b9a10059b19039a
+1003990a0398fe0397960d0597fe03960d03958a410595960394930e05942803930e0392fa03
+9190bb0591fe03908f5d0590bb039080048f8e25058f5d038f40048e25038dfe038c8b2e058c
+fe038b2e038a8625058a410389880b05891403880b0387862505876403868511058625038511
+0384fe038382110583fe0382110381fe0380fe037ffe0340ff7e7d7d057efe037d7d037c6403
+7b5415057b25037afe0379fe03780e03770c03760a0375fe0374fa0373fa0372fa0371fa0370
+fe036ffe036efe036c21036bfe036a1142056a530369fe03687d036711420566fe0365fe0364
+fe0363fe0362fe03613a0360fa035e0c035dfe035bfe035afe0359580a0559fa03580a035716
+190557320356fe035554150555420354150353011005531803521403514a130551fe03500b03
+4ffe034e4d10054efe034d10034cfe034b4a13054bfe034a4910054a1303491d0d0549100348
+0d0347fe0346960345960344fe0343022d0543fa0342bb03414b0340fe033ffe033e3d12053e
+14033d3c0f053d12033c3b0d053c40ff0f033b0d033afe0339fe033837140538fa0337361005
+37140336350b05361003350b03341e03330d0332310b0532fe03310b03302f0b05300d032f0b
+032e2d09052e10032d09032c32032b2a25052b64032a2912052a250329120328272505284103
+27250326250b05260f03250b0324fe0323fe03220f03210110052112032064031ffa031e1d0d
+051e64031d0d031c1142051cfe031bfa031a42031911420519fe031864031716190517fe0316
+01100516190315fe0314fe0313fe031211420512fe0311022d05114203107d030f64030efe03
+0d0c16050dfe030c0110050c16030bfe030a100309fe0308022d0508fe030714030664030401
+100504fe03401503022d0503fe0302011005022d0301100300fe0301b80164858d012b2b2b2b
+2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
+2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
+2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
+2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
+2b2b2b2b2b2b2b2b2b002b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
+2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
+2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
+2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b
+2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b1d00>
+] def
+/f-0-1 currentdict end definefont pop
+%%EndResource
+%%EndSetup
+%%Page: 1 1
+%%BeginPageSetup
+%%PageBoundingBox: 0 -1 631 791
+%%EndPageSetup
+q 0 -1 631 792 rectclip q
+Q q
+268.801 790.4 96 -38.398 re W n
+q
+268 790.4 97 -39 re W n
+[ 0.793388 0 0 0.8 268.8 752.000008 ] concat
+/DeviceRGB setcolorspace
+8 dict dup begin
+  /ImageType 1 def
+  /Width 121 def
+  /Height 48 def
+  /Interpolate true def
+  /BitsPerComponent 8 def
+  /Decode [ 0 1 0 1 0 1 ] def
+  /DataSource currentfile /ASCII85Decode filter /FlateDecode filter def
+  /ImageMatrix [ 1 0 0 -1 0 48 ] def
+end
+image
+Gb"/kM-!XM[`AE!Q8p)k#T4-r#lt*Y"Mu-$K[C at n60;;Q"=FBgZ&5L<KG04MMF1D/J=q]X<%
+ HR3lVqkK/t_f_;*3Ri::IX?qsBT"PU`fL%_#Qbg<8Su-0a9Ym!SPOTCY\VT(D`<iUPH"?Ti
+ f3nA at ncNZ:'lVR`t5X<9/PXeI(jriEE%o4PH^Y1p=";>]XucIEA`2,gQ51+KSn$54U2L\W<
+ QHDbFV8K(SqYbs\#rAR3)^\mh`340qb`![6roMWSS1Elma1d6bi^3T5\'tFY$Kk^5/M\jSc
+ /'h!%<lmaQFLdSh3F5co?aY+@[WCWg]mJqfUIUBZq;rWLo/q[ZoYC4sp=jN#pu75/p[>kDn
+ mqWP[8g5g7;6HNV>6%LVlq9N^U7p$j+bRBb,kB.8O4*U]"6>6jY]stQIP>-3U`M]%>VDDa6
+ 5BKcfX?r'i\45L@'t#95!>0.nH8&)crODSf[<`TN8u8H6e5kQ"@lM--(8BM?R$m9"?2l2Kn
+ WMq$6Z]^AS!-%j!jK- at GadnS\P*EW5n-cYq[QM9W]?^:l!CXh6>,+_)I$&+<W8Cg';E7:t>
+ hFcF(OX,jZl3OrYe\NLnWmqoa_T^D<$/QWIlJ(W5$1"=ZlUSm-un$WN;2[kO?).KV50W'iO
+ @gQ8YJTXVd1DB=+"i^cr_j$1<@D;9*^2aI=]sU;-T3#/mG'e#ji8At"_o'6O2T>L@:Hq:qf
+ X#5BS2iA\'4^3*:0G;McBb>^*UB2-k9_dK=kp>t`JJGI#5>P9oka[*M;;h!)V16%25CH%Mc
+ &%na_RVUX!;1U&MCDtd[;"F<N+A_NHBcjb[="RO96 at Din<;9ph.-@<8pC^q$M.B7%USL6',
+ $Uc=_QBnZq`P_J"(L7MVV=N::s!Eci'uRsR3eEmbS)>?;=Do\[E-n$gZ`=(+<<kH5gGQ'K>
+ 10i8=Y.b?N&8%GQKc!F7OEFeC8;`iTZGd-5eRJgbWbhl]iZ)&j`CTb6)05+-Y89_',BOsS-
+ WMZRuF*(ULdA\9PL$GF36Ma;20-9od5;%8?K"COU]!>>JZ]naLIU2bugEq9S-+Y^i&haY*b
+ Z/`-<U>*/<i.r/;9k#>itkG\cO0?*<(Jn7U&^TX_Ic=ub_2qaVPZe[qN'FDHP^Dr$Inh`eE
+ <O!TcH3U$4AYRFHMJrB;-rP at ap`WGAgc<h_0Z\g"?J`Mb;m+8j1dfp[A'=!JZ'BB0*jMhnk
+ _X^YLU*_K>1J"QrdI7(o$Nc.ajDDAss77QK2f4[hCR8Z7Ds``"AI1'q`b5$W`IqtlH43;`a
+ (VYnH)4*UDbff=1iDH'0b>IDp=2_Wn?>h:fJ8mfW=^[9eNO&Pq9YFK`]E=!%k#Pd_JX8L:k
+ r9s(B>I*-<nCed4C^f9&W7^?PbXmh\iQeM-5NbRk,Y2f+A^Lh=&_\U.%cES!EDJnm2#=f?h
+ Et:Ce,32ef[%Wa=`qi<WB&#Q='n)>rq1u:rH5Z[2pDR%rYOJY0u2^lEULR\B4!WE!3SN-r3
+ kQWH3UORJ(tT^@^=0hZGYA7SuanaAr,)3lcdu%KRQh-f\0S at CRH"[Z#O9sq=B62IJ+N[HkG
+ *-*#sZbB?r3/Y1<aOf$CKah,o9!bArWPYJJn9VR=-^:)7)\Hb<FPJHr77<]plA_GE,fD(;'
+ ts-<+lhObA`E1n8Se\GQQS=Kj#kJ=88nE!udZ3n#Th(ABedM'e\>\rjC))KdY1.5ppj<@D+
+ RJ)rd:'+I>7`tG5[d2PJiJ`+9C.^Oi%h3A^f+K)A1*pQg3=".mc7M`-IR_VplLGJ9,f:-gC
+ %<Y at l$Bj'#MptarY.=1%nC`gB8D""o]aI^-[8HZ;E87XLL]75!Z]O:JQt0g%5T#N.UYoh_b
+ rp!S8bTr44B7Uk!mc/&2F>.3UT3Q%fK*T=%R[?iR.)l3$Nj_Z,]I,77FJ:UUY$s*:t1M"f\
+ HHQOgL-aH,1aXG,!HrUb5Zi*n"&9S[-JA=`mL33 at rlH?bL.3&1[cHr,)d3M/$j0OQ$\CLH!
+ \)7hW_:_C&]I6LAN,$E^$jWeX/m1?O6J;EIU`0#$W!c,-H!2&E9#"h at 6_>@*4"5VeqFmHop
+ ^=2X.g6O\A/^<^#?]K2Hop"*?H3NrDr5i_<?3P!58B;KRbk?E(>VO)$#sZG+#p3Z`V=HihJ
+ 57mIJL<`j2XHh?91-HF<ub"XB[Mu8''IIE[&9lL/0>2Q_917r^rjbm4h,FfS_LW'@6RR at h:
+ L7W;,Q?4^rCf,D>Ae&1CMOq>5q>reXQosA!Ko$Sph?UerZL`Ie9#RTHQ7Ol4ke37cM=P,Xr
+ HEnu)8T2t[#^6\cc5_4FbBO+F-9%glQfi^hnF.2a^Gq?nkQ`>gfhP at nUjlQp=[W#KU?T2Y!
+ T(GBrJ>Se7l&0KnmHZr>7)"&hc\#h7nQ>B+c!4Y5hoF]CI3qDV1, at j0e6[srci/[r[1A_Nf
+ pVoKh*7P/Ib*9Q@,<Z>o5Rg$R+W*BeQ at lTEP[g8JSqMu\NBOFR,Cdj\e4uVgj`;6`.P")O.
+ nU5fI;iq_9<FYm3^<G\B4%,eda&V?b\*10NPA;K1;EI72V$Q#a$GV!b%62sU.sVEEYV5#@J
+ C1C.\Vh0ccVhf*9QRnZ)-RIjic[f&O_W%:06&=m&UmMQap_e]PLkmc_a^CatjDg\SGXoiHE
+ ho;su8gT(+f?l"'cQi(qbWYCfPQW)Yt(PoS9eMh9WMDDk[Mm`i*/'\Wh+`X4F2XiS:Ch^>%
+ Dns"l*l>c4VeK%l':=<gg>fDV5Q4t["TB][Jm3en*jW)G6HLfi)E'+AOFE$g$i;>-Ce86bO
+ 1CTQS6CH#N'Hu#Z3XO9%7oS,GMjPj$5GlKe&+82#pWf>-1^(p1X+,*I_MZ?&05#!H6r7;io
+ W5.H`i5q?*d73kmcDS&_\<%R=6GYsh/=td*uMrl0 at +p.2AV2sj-8mh1j5o(B"NJU,OX"OlN
+ 5/(- at g$n-*VLQ=RrRf-k3_4rVBGo71f.4++K5"I!'RcKZ>W891[J,1m[67X(?tlf#f\_GH3
+ J"rXOuI_NAs21HdmuV>kWCs0[*OZ+#D%!p+XFP(=leF"fQ)S^\2cQ_>Oh"Pq"#/mbcTRdqU
+ tTcP6rmdAq=OI&8cQtOHnli#W$jX%sYg6R$;Fm)54TEa<u>c<CK,]^/9eQSE!dDj2s&],#0
+ 1jMHVdg'T_L6R"i,"2nn%SacP&9K.b^"p#89eD4rn(g(0GAgB,4NGSQ>C)IICIOCe04W;u\
+ *HYJ^raRbpb85=KVOC"V&t*X>+,euZ*A\0ckQk&eM+o6<i0P#1q>a6U^S?ZKnmH9Ch;tSZc
+ Pg85MFrlkeVo![1WFjH?/o6XaRg)V8Pb6CjKi\^WoW@&L("oZ*"OD+&3NfY#6+<LZ8Qb)uJ
+ Y\I&1"m/8?^X+WQpRlN3d&omX?J9?0P!$-l4/_Eu(M8=2jj*\Am&*nNmJiR,c'W,WpZT:7c
+ `G')rc2>4Jc8V-HN5^AklR,Z,e;mVO]3l0)jcp&N\:PNb>:ugDYjcr4sACr1](uuT4XS%3\
+ fuLWI[!W.:S;[S2)5Skt8$5jt/df3,9uuOQ:3H63)`P3CfFSc;J>fk*=e+2?kKZkEA%i]%4
+ YbUr3fDq[2!E1,a2+1qW!rqM;61:YC:A]T95mHm:l#KV/,42mbJJg!8(?;Jg;ZS;hV&k_&k
+ LYW7/4p"IA at H-Fqj5U,S at +LIZ=2J6&bqtW8I%09Sa&=>+(*n`=X.$@4o"`NPP!OGFT3[KgS
+ YXCB8\m!E&E$Njcsf$4-WfJ&d%)#Ek[OkLu="]*bnPOk,qS3fe%U:5n+dfm^.eMqn7A7(jY
+ ", at b_#(p*@a=Y<L275eFfp#`boETE.qn8Rj4K9K53pt"U,::stYU"5X6F(V)#5pu8$JI=#i
+ JBf#&@`rPn8"%'HTs2`SVE'X)4h\2<lu?\_L=*MCO4'+[Numug+"8]lORfO0#b+(,?AKgR;
+ Sk\3NrJrS\d7R'TJI>n`k>\e7TPmn+g=cQ-'B?O(^\*DD5L]Ff[Gi8J*)V%1<4m\/[E+)b0
+ />O_91P'_H)TI@:Dmb2k)\['?L_\.>N$XYUAT+ at SW5=+9L-j5`Nt%$UqRm0 at Q#@\OJtgEbI
+ 5:L%+7AF6ZfXokW/;[^9^r]\/Uj*qm$nNco.\4UicK!4tnMs$rY*eGDL8.-uq at V(Xd at B=Qa
+ (,8c^pT[N'W$FQIm)_a#\h77-Xeu$qk`c3Xj;3UOqmFsT<dpcgt9G9?Ke),iqBQ'`21<W[n
+ L0R7]6FdMnr*`\!.t&!E$h&q,NW(WX"k@,T,&4K<l,0ojgR/Ee7eSD0cWrpZ/(^^RmLC3[_
+ b=c_mDERM$$rJ<c/N,S\"7i3.tLk-Cc!tlhbRhE0228BMq(pSB.,T_5e.$2a2k@`GFMt`h1
+ K5*bVCF,-9a'UZY#G^HYWVQ*/;+Pq(fC,R'.#d2jW4QqE!@+$>=_lUVbC1K=K)u5oEP8H8T
+ uQAaGDD.t?@o?<;T%$O2S\P7jmc^+U00)Hn'<kbN=m*c>d%OcA%mH6>nGj_&LVNG?P^meo0
+ 18WIU6^<2XIWq^ZF5u2]7euRJNFi4`r,%XNR:^O6.g99"CggcO=cHDJLl\s8C./#j8N>kR<
+ 'jNPoNLA/9`0F_-[rKGgO&6A&EJ[&h\[fQ.9?+:pEote5KhQ=LBIU:?PD*$?2pdV+`),\"M
+ `jRD5PK-6b88JE:,isj8&oR$Q/9[u+c>DiDQs7CRZ8lbC5XQY at W-+\p/?o5Fn7.s(d3Cqq_
+ mk%3LQj%!=N9#+g=iNkr;o-S5Dc./R!%AJoE\R"Q`O[GD?qUkR<%1kiWqrH+ at DNOW/t$4GL
+ 4d>6CP?")=?f1J0Jj(ccU]AKVs'4&]%RBdV-DaH;ssqtR\"a#5g_%Uiij[Ph+s$uZ.u=@>Y
+ DK0)qG3$8/fBQ at L\,Lj4iZO/SoOInK6+6Od"PI"dQ60Nf=OR0KNP7_hJ&8 at gWj=na`FlTWU
+ oB8Iqo[9=91DeJa]Re)_"V6d4QmEcL#-E]j>UhGKLpt(*(WTd52VX3OgQ/aCb=+d=, at 1):+
+ u*%V6bOEqH'.o=<Ki/YT)niQ$-AOqGi\)A8AtCK0M/e!+''j_aE*oG6AfjR7]$`>A+Y!kad
+ I#):/4.i5/S4W;9'mni/=-&V5srKn*Ot/Ul<s4q6W*A*-3FPb*tmggA"P)(C,)0Y7<^P&AL
+ q9/3u'&eM:7b!KB]Rkln-$8b-OYZ/IXV,_;q4n:`aVAH&OLM\T(O7Wrg+'T,=]-5MLc2a9=
+ pWtj#^.+*5#@d>u?/WC;Ui^.=7DHu5lb;-AC at nX*[b)L%$=M3U%BBm=<o]"6E5b`/VPf2O=
+ <X4WGq%Q_&^+L*cM%lgI_$h]Yj[,,#PQ,Y,G&NWRR66dc_l,t\HT.7FHO?'q`RY:#9?<mp%
+ "s00N2+bIqFuQZjM\Aj:l+Gs`V5uT*RDmLK*Mo^SN;>E',r"X`+'-*hJfhZ<cI;04EDJF3-
+ N^1PcNGpK"779Q];nR&7.m at h9$GfcP?C/?hAKTkkei:&&m2mp^p3p0VjR4J"87gB0KH"(4t
+ WV,RL_4/.g"#I\;7GA,3(LW#K1JB/,I(L_(9[6>/%IPC^!GEIaeG]K=KlcqnAJD*u[/,V1`
+ q5$]Tk8&pX%;C?&6U4d=Hg]7%'%2UDS%NVf]:S=BR`t9\_KVqb%B9Ip\;C6c.;T4=di^brp
+ dM#^gQ at hV7BilLDM8bXu+ScdF*pGU[T*\/rT./'q)\*Ahs10<8Nhq_RKjPCU,;e-b<lV9^R
+ QI"A[!MjZ_FTeDEntU%bD#P^/qEn$0R&A.]1gCbeoFgpF'!$&Hj#Y4@`"Kj-BBH\+]o3iKr
+ #r'1gjFeJn9\2JXd_t7Q:Y/`<*u0E"LF7?cs=YLc.<]qtKO;<s+/T+>_PT/p:XM$(<TW[u<
+ tHF(cU#S84fF/9"9N8f2ke7Y3E0VfTG]9r:!.gYF3C$H3,X6\a9KKJ@=;*_X:8YT,2$9>^h
+ e&[It<eBlE+RL);G'F4iH+<6:1Du;mR^)Z#5^D]'XEP0RF/(B7UipMYm5/AocgR=k5FQ8N#
+ &!\,5:UV-ioI+9c6_I^&$.4Ee-`L"3 at gQ7niB"`1S7=$YRlT/jP)ue>Y])-8+WuYj]6<-QU
+ jbT']DTmC;A+ApX-YK7Bl%,0:lq.2X-B;OOhg3.-n.,1;,plgBM+km#ES#`0ujG)P=5Bk01
+ fQOQnYE)c8P9uUS.^MYq0F?fdC;Ii?h)]`ko!.KRbJtf8]cOmW\U/-Qm8R>MM0`SiG-N[UD
+ qUoX*7B._4&kD_81O[UU6/>F at P+REKkV?4OF#@QQ6JS[Z;7MQlUdf_X=V:%7Wq=Iso;QbXN
+ g<Y6l6_3m_E-3?hMNjUTMD'B_I@'Nfh(67K$"@Ve>5>e3trs,o^6`^~>
+Q
+0 g
+BT
+22 0 0 22 289.473926 763.771396 Tm
+/f-0-0 1 Tf
+[(Start)]TJ
+ET
+Q q
+177.602 708.002 278.457 -71.371 re W n
+q
+177 708.4 280 -72 re W n
+[ 0.797873 0 0 0.793023 177.6 636.627923 ] concat
+/DeviceRGB setcolorspace
+8 dict dup begin
+  /ImageType 1 def
+  /Width 349 def
+  /Height 90 def
+  /Interpolate true def
+  /BitsPerComponent 8 def
+  /Decode [ 0 1 0 1 0 1 ] def
+  /DataSource currentfile /ASCII85Decode filter /FlateDecode filter def
+  /ImageMatrix [ 1 0 0 -1 0 90 ] def
+end
+image
+Gb"0TGuU"%T#^@ckDgbuA(X,(+bY at PCBuXGEfl$'$R(2-(',"9X!e_WPtT(*[>Lo]["*M2;l
+ Q^gUM.J!?5G);)6K664<Ai!3_mk at 4J'i:^*10rleG7_ at X_,2qjc914bnfahrgQnM%DENf8k
+ R9^qdbGa,bRoHb6l#g=tB.1cKp\l/@7")aJ9-NgcE*h).'4B!`*I2LBZ75ekG7mDEE-%b%h
+ fZ14$t`fH0#3H4hQ002-T?t_7'rr.A6SnWhpZ0(#U9_\/WpYS2[n,VkiC/DTTbGn"-`RFG9
+ bL.bR at cCltn^.q'.TL#(87ZtD3\5s+,,S%'_[QOJ=pR*[9G9.*-KCiMa`5^s\;8Y!K`&L,H
+ #mT">I1&Ac^n&_:Ngr+5CE6f;.Y"*"K5@*>8m^=D"`h#S;^SSH)7iZXsfc<^3JMgV5<LD0;
+ nlO(Ta`@L_+kW($3I&/1[,C/Nl*['ccErd:7e",]?Ia;I'$\KnoEkn*KCO<#JBu%a]m8B?s
+ UZ<_U]_H,$RkETt-Y'h^`j>dL?n_gP`=)n)oMhnHgRHY)72aoa^;6>m'_;fB#aVR1R=>*r=
+ ?RMAa&"1[C3.=Jl:$`<@K^#SD.X&+O`c^n"[JgjET+$XX]D_EbNR at 9R$^UX'V'kLV$QLEO4
+ ;-K?NRi%_1)kIujQDY%]Pnh&IHJ5YBl&2F8RE*/G4Y:7 at WM@Uf4<6!q9MM4T1fnH6-.rS\%
+ FNYRU'c%*ku!"'PPmA4ZG\G.JgsU]/`F"UpkZobq)JlnFgl;HIe)RAoB4HaQJpr#_C'^)Au
+ ;A7l#k at +D<ocuc;)]A%Biqjs7l#^PBC*U2XWQ6^ZOOLSX5B)!pp8e+Z$5)joZi[.387uc17
+ 8_8Ws7.V6101:r;DKZi38Tk?V+H\##q3YHO#`!sAJn7un^>e^:Y,HrY]hf;_7cgGaR at 4Y:5
+ _T&Ic9NFs/E/q6pRdrO[?RJk\-ZIWPVXiaV.B18sq=8`0uJoX4<e#Z-1Jpu6bIFu09>T^CR
+ (V3E^<19bUQ`-Dp(RQ<+T;,HN6=hkP':!%@9Y_<$Y[-U3U/[iZ[5HcIIglns'XId(qSe@/%
+ j!iHBfT0k;XDEd<NTU_HYTQ->l!WUWj\\1GL%:Vf)76L.SFL`i]$+el]Z]SBtQA,XnPkLck
+ *upWfk'H-V,b^4dN+e-'R/^:7@:2AZp-\%2,r],!3?&-P8<tg5H at -Q7cCMi8V]`rVc[K9Nl
+ "XT*oQlnBc4Nn:@)\]fY,#n_BkK@/isEkI)Gep#h85r9l3BaH(ftj=qh(WSHIZY5]A?57X_
+ 1_sR9(H8_l(1>I<q<o4FgVaL1=-i_TL^N4jFER]_fn(Enp%Gk?tQkM/^S<(j<T*b5:[T6:-
+ DI.5#n`*+\5(#oklNR'on.p*.:=$1T#?$cG`<(fGNEQuB5?tP_KC$*NOg:I'b6du_.eeZ6?
+ 6f(,3HAnH`l9FY\I+qbdih]3p2_9&(NDkR/:f#r9q-7g:d\Ss0?(+29Rj57br9k?mAl)#S0
+ AP*UrH*ZWg31^',(55$\S6;(2$IS0tcuoU":=UeWqR5iXT]k'k)\<"ZKIkV\$'H69>]!9Aj
+ =q+/Q!@YJ#/KmaJ(0Bk7>%?Np]=]";nIgpo:G($t&IPVg?dY?#7)q!3=<V4iLiZQoJGhqfZ
+ gere,`ajnA+CGEB1R,!!$h2<i%c%VIWCOlZ!nUY8]?M_rQ/L?`V8_Z at JH4JVrqRg@e`AG&0
+ Z,4p#^>@Hb7)YB!3DsK/2^c$p9Y"e3Fa*T3n9I__$h2X(*boGu7"m,ggmn&rnsn?o"@&5HJ
+ #=#[>V6df+ljS/DNHA!abahS.Z9hC+W%K,Qg^&s&ZRu!=fO-])<sO83L`US81-n:A6Ul>Q1
+ nh$+4Z0KLC8.`gi+u<+^k1,Nu'h/`.TS?X/d)#"aF4,#aPWfFOl-?_P9Gl00`O`>H8NGb#=
+ B0+-Oq"jEN"3RRg1ga>khddum?bdf-\h9L4/L8W-'Po,?&W+\dgSE'2eh:6s'"Vb'\K4>s-
+ lGm[lRfPZkqG[CJAm)2d*b;O:AA53nLJn=q!NcBWu%(.Y.caclggCu)Qch/TVjH2*mPN-AQ
+ 8OLd=NP"W.P:Ls"p!*Fi(&c>k*?#YRFiHC+)*UhA]2`C<r'dm_P/1XD['3*CO-\E%]%@4sg
+ :BAN at MkMep`RoT#epKaVa;\JCTQ_lJW/sA,H#/kT79UMN=Q=,K^/ijAKWqh`7J_eB=d_K'S
+ 4Ru-j)SD_t3T9#Z<9&Z_a31P+$(39I2o(@Md8`/7_6F-2BM8"nB(@Mlml=aMG\D1oHO<*P"
+ ;bKUWk?<X/BKd+hAd5BG"u7NM7 at KegH-p),IX(p]eWF1eYf8SV^'Z[s_W$T!G1ea]@d;\iP
+ KOONITgu.K#r.:dmr7eF>8Ol#:-Nb9`i.:^8Sm9j/<\:;3+;G5]icRCWZ>3ENJbfA7LAJ/C
+ FM4,s`mL+Vl2tQ8l3 at qV_5PT[o`6fWoqR>1 at h`O+q>cq<qB87#1TI`GI=P!YrV.OJHC9JQj
+ :Rsel5O7Pl=UV^(1cB-.d9JAa][gKr:bF#1Lq!\V[bH7mD2"p)gPRG;tO!(^.K\1dP)%G">
+ hA8"HsFfKsN4q"UkGNP*\JM/;t4kNuVW7f7G\SZZ';%Ac[O7L?.e]!OFIX;*SuTiI33]R"Z
+ -/qKYF:p\tI!ZS96m5AuA:L(XX5_MCMV]HN"KH4Vb<,6RT`LR at F&K7I+/FOZ?k@^rm_!bT8
+ 8;*SuTiSHU$Qj$,NrOa;.qi*lYfi^:G(hm-GIbkXR%8.6d$^QD at Gs`!!N'Y610H]uZL)=g\
+ K7I*41@"$31#G'-!bR"7W#mq9I.&ZnQj'@\Ib55'^$?eK(79aN at 7/7OSfhDV(kVU06O[VQ+
+ CGt`UOM&2_jN^pQj!m"@Ot\K^ark)&2V^N!bMIcJ/Eud&24J/"N2;0;h/#d+<]g>*e=oiKt
+ 'As6aK&VYT`/(5(CcX"p$F`p#0Brba&FtLCGs[ouU\Zba&FtLCIAhl?gQ&Qn8]q%i\tAl:W
+ 41=iaG:;Tf.7_hOP>qSk5tVC\7/rm%i8rNII-UV:WiK%[FprNII-UV:NfK%[FprNII-UV:E
+ c_V`VTrnQJY!qjHcR#h*00ahU:!qjHc/->Jf at i!:P"mRHE=Tn"'`[mK)$e.rjZ3\t#Mch`0
+ (9!i^A.bcd(:.D?/5SQFa<FG&/7u^\=eL5lO@>g+<Qp&?Z9\Aa+cAU6UmM>WA:aSK6^E?#6
+ 88l1aTD.!L+EE!D.4:)P6L5!%9Wi!X/'WtADn<kPD1UiofY(K8BF1q&:[oskdi2Nc-sd+")
+ 1=M*NA,"Sobjk9nT\Z#lTqS2"W`r at J\#DE_/o!Bh3XT.5tktC6k[8d]u]JjDBkk>q(ktL;>
+ Dt)2u=-S!J0]N+KM:0ZF-es6E,mHJK;V\Z at +?25D[`Hjj/>P<%(:$qX1#BVs2ZZB,XaV%<0
+ XpZ<5 at Gafn2*Uifc\m08b)EFZBT-oeC)Ir:ilU[qF>gXMfJC$sYJV[V760K;)6CW_:-Bc^7
+ a_hhr.K?YTHHG*M/Qu75R"[f&AjI._o5_*q<Ch5*T!=mB>WH_.Up/D-8cB8gp?KbK/NFeH:
+ *u-)%6:UL4uPYJg(>7qAMSSf--]4.#k4@'-BU.(PCp,NCFE?HpRd/&1O>)kC12[F(Fce^j>
+ ,TL`E)?D;DB^1ET'2m/piJ:>F`H4[)=+\`a'H730NXb=!T"@6cm=s`l]<Z,G2ejV]dEF`ch
+ cC5][Qa*INCOWbLr_TeVF at s#jL:-guE=b7u,JMTaP%*'#r_bY\Yu50i1omB)e?L"j)Kp["k
+ SL^=`7fophh<'IJD*Y)@lLXHb5c8aG!=e5`7I\b3FpcZaq5Z/=f[KMeTK#r1hd*TR7?oVp:
+ A>P7/o6ag$d;BNG`X<T9o(B^,Td$p=^m7%9\2ghE at 7h@]h(6 at f*>fX'GOKEZj5,IA88%gL$
+ M8B7]oQrbL]d*-71*p$\DTW8gV7 at 3I@!0\ba+Ff?DPdM*eB99+G>IRp&`-_q95!a.e's2+Z
+ c\:D?q$m.<t at q4/IJhb@?C>ecI5"paB-jI4\-UDAJg,HNs4`il&+'ZkR/"CRLQj&9Hq7:8j
+ PTpNDq)jKDJip*YaCl,?pgik at O97tm-+.eNY4aR_&@&OO8#LRF_f)&Nk-k at T_kVK=LhZp?:
+ 2VrSf0\R?\BN5q)BO)qS6EoE$Odj?(reBlh!$cAd-L$-dS5CE71WTgb+r#D[d(Z$CLKatg`
+ Nh"ErHZ1`f\aM%nX2>(jOhui at iA%I58LH]spLr)M&4/_ePC_].Hp1+9<_!PV+WN[bZ[B<G*
+ ZP?U/TnGkE*t]4a2.iJZ87L_56@%%@8b=dM\e%\qsM))[e":c/60i?\=A%jGII15 at .32fUC
+ aZ[@ZK$g+]$C15DTR56-I.Lj_@)8>.@<Z63n#49Vu&HK_`E>k(`A5:bXC:QVtWmjB?o_Z%O
+ *4B9nh">?Y&cp\aj<Dnl5dL.Nm'VD:8^qR#GZmJ>O?D,QOTSW2*C)[VQMFW:p'ORq+u6?]/
+ lP:3\gGDZfs6^F73CW&RG%2ft:"7sq;3[B%*_*^PVL^hZ:ciePs)cqA*T(Q3Zj1$M&Wk,4q
+ `jKSXSii_!"S1/_*W,^0>$@Ag<.Y%_Ni]K\j/h$Qa%:Nqg\0a7'RWr;J/'Ohr\!/=%_Q$hK
+ \ctC#Nc[Hie3+iE]skC-+12p4'7Enei_OPSCgjChU7RMRICF.gIq-rKpPqm[hu'mSXuE?%<
+ Y+gEoBTE`u41Gq;R>F40UiX/2-1+r\!6mI!1%@X]!5+#e^E;i)b(WG]DZH,[>+d>:TaOGE+
+ RkS_.HM,jos2)>1BpVFLg$D\0+<!FBEsQJfcU%)F\`.A+dr>>8L0$#IWhN-uNN,Woj<,F0]
+ >80ETB!"7p6);L>^B+2uk`W[#sGHuk3jlIDMn5Vs`h(K^SbC\tc.SXJfBW,.AFAZY=/ki6p
+ Lj=oL-bA$DoBdg+No$q!;SJ]gck.Gn7US20*uGS`#mLR>JoRcT$A0rKjp%T5l.s+(ht6(=9
+ ZR9\V%!>$rB3;,k?D.0lKU9/<\.I\?rh85IWe1uAm0Xq>#&ff6KkPfLl>9Tc at B'6\6rbNlK
+ Vbp0KPRB%$1e!&$K<:175dgJB*E$hVN&"Y$J\ZTr"U]eB-$@:4D&Ar&@%,2hEIr#M%62j+8
+ W](`LU-7V@$k?rRe5Qg(ZG=&?#MJH<8\-lBV`g`O0MgqVaugPZVhCCfk5FMY%d>VIlLg<58
+ )iGHI3!mChlir~>
+Q
+0 g
+BT
+22 0 0 22 295.43584 676.569568 Tm
+/f-0-0 1 Tf
+[(F)71(ind)]TJ
+-3.973633 -1 Td
+[(\\MGL@@@<sc)-3(ript>)]TJ
+ET
+Q q
+243.199 600.798 147.57 -135.715 re W n
+q
+243 601.4 148 -137 re W n
+[ 0.797682 0 0 0.798319 243.2 465.085823 ] concat
+/DeviceRGB setcolorspace
+8 dict dup begin
+  /ImageType 1 def
+  /Width 185 def
+  /Height 170 def
+  /Interpolate true def
+  /BitsPerComponent 8 def
+  /Decode [ 0 1 0 1 0 1 ] def
+  /DataSource currentfile /ASCII85Decode filter /FlateDecode filter def
+  /ImageMatrix [ 1 0 0 -1 0 170 ] def
+end
+image
+Gb"0WLK>0kqZlWji0Qio%`6*"0"W[J08kVl.%mdYks\F+'EJSB:de8,9sMWo22N6`,1V8K:b
+ 3HIBVJA>p_l5/<:p1Xm+i[oqhcmT0[H/NPES at SGb*0-kIKJsmgK2,O[U$gA<B:r=_*X`eki
+ DCT0<_VY<\E=egFdPq!d8 at qtE6:4n,ZEmlu:!#lgK\6P_08!==&Ai^J'8pT'W6+$Y5Pr;#q
+ cY?o&[^4#nPh7IkBbWu2sA.<Lo&Ha5&oB&b;8&tT*p[A+SfB#YlIVj!fGNMTj`JaKYhLuak
+ "Mqkq6R0oBs2nj]5f)snNYl&mS\P."l_Ot*[Vsj+Dt!+"gG^ck0R$H,jn;D5XC#1Xp.XMSX
+ )5WOqC<P&hRn;3C)Ma0Sc&6>J+rBeD/6b(lGW3]\[,nF-7)&M\2dYenoAr^@tb-`-:WbdT,
+ Le=ATROlUTG=crqknVpT%Bahn:8B%%fj]rjm0_q*NQE+*XQX,R!pgqi5f=?rCjc$uO2skQV
+ q^6Obib;=4qFgkf>D;,_Z,fQ"(.rdPG#P$3T95pt!M4Se=:mIR4poB4Ad)B%o)a^1>h/L`e
+ 9da,hW`I_T2l=ad;78[^]HtTT at _U`h9Viu7j^X)%blPce(DdC+QC)IM83I1Jnp2@]'SiS_^
+ .l01D+u4,sZIu4Xk+tl:H3JZJqmiqYm-/"2$omBqY&nMb_bo![eZ:0fY*LoIO2ni[P*8BGh
+ md]\e2"B=3Vh^dXkFF9EmdiaiZdu8VO-H.PUsnG)]LI]H?+3(`&M[*5?mDtQCb^VL)Wis/5
+ :b6XR9a]b"D,,(G!s+j5";o,of-kOOQ%=$T9BR#ojhg;Nar<UW\tcDD#8&G"L8:WSCc0Et>
+ BU;OSAmk$o'CY9.5I`O4%uZ./E?X*`2_\P^nJNCR+hI-\X)%eSi?>.QaU81d31`1<t]>-tu
+ UTHHCD=_d`XWu'?*/D+$c\ghI]*-^Gu0pGq'5o*ZheQFQ^5rZSGF!=!-Mlu;ZU1$\4iG'N=
+ $OLDNP_bO9=m=;TNq-aM=g99ZVB0'UZu0a;J\:4d'?4sOF?#Z'4qd%g2itK(T3CSu[+N98V
+ X*GB95T05Q8`*mQ*+P21t'Z;'5=FJ[?B#p1^Zs7Tp+3ja$lN"b_e!EST)6Ii51es at g0uhUl
+ <($3:s])F*gXr^=X"sGOF,7(e-kPm8,M(HQT$YmKUdnq>oa44q'"Q:#4Z>KY<4sL_eXSOBM
+ j&8TV1_74rW/ZDY?HqsoL11MZKu+8f%+Y4^sR+'sJYm@\W2:T<f<q$rt;k.enl:.NY]IB!#
+ `P]R`?5aM*HL=UT*9a=S>:alu(YW3:TR>[T*YPS7bL;ii)l*^?GSM_]VpZfQ7*q6-6FR03+
+ Zb]Gr?j.K#[X0sVl9V.iF#7C?T?379P]X>tQ_chWBe^Z;DlUXY0Lf5RlU#>(FG65mPN#mr)
+ 3mXK2D1V#0I*<.f$pR6`AJsP]99j&bi:lHYS;1D`/oKjnE'lK],7&4!C-C2D4[EQ)(`2aag
+ M+\](tG)`fXXIdLpDp1P)7aD6E7k*@Xhn3 at u-`-.,:a=lG+P3K'*!*%oQi:27u7m7EmgZ68
+ </Z'F6Y#<&/=-Ts?Fhf@'\#u1YT'9g6c'>Y_C;!J)hm6An*q;6;FPo(iFb=&4n2bSKK;j5]
+ d(lRS\9o>X.*>M!^$Zkp'_[fc.2f2o]3D#W@?'Oj:nnuhG%".mW55YlHT)_Y;^ptl?(_#[2
+ _!+,2&."<kJY0Wk<d1e'rmLq<%p;qMU0=q;=ZT(]RRAAPA3d'PeJlL at SWjq-=>hfc3W*hbr
+ qRQ\8+NPE:%a38HJ[N`i"Z6a5kc at nCBs'.!A6ckF!9Hm(L6$Q93cFe$dJp- at t%gX2l<EB8B
+ V3%';Pdi\kn;H;q$cV1.Y$makEK.<H(''5(@-5bb6oi9i\6Tj<aemk')^HjON_WmM=/1*F+
+ O)9d-0t$X/1elUh_u*/&lWie%$K@%Rt^-<3]h5`7dJ,cO5O$[72XZ'@b9G?,Dp=J!,K,O3A
+ (,o?<?*EtRQDjp-o'`obT5(H^a?r!/gKC]-lO at NLd\/l']nZFcT9)r<lKaZ?"GWJK&$[`T'
+ 7[G>Gc5l+5,dJ\Mp5=,o/DjD`De2DfiAGnIGH<j=3br*RjGp9fKq-rQ.d at -\Bnoaq\B2 at E(
+ AQ3eC4WJpdP?BQ/R&ShAcN3_;H^;o&B6>00f';7MN=oCd^!^Y_lAZ&Z3*-k[e at B6UY!Vq3I
+ E4;\\1aU"CjcIj]rM,SF@?G at SYF)74nWnYgFc)W(nK`291^`46[4AgNF>k(2*']oRB\Ef(5
+ sH5,g4`h7(4CGto(#!aD!%=dDlW>7<m-(,F/U^r!ukBhhk*Pda[.SLr*h>nP\.H;2`'F4d9
+ *oRMu5^u'j=2$oc at +=C4ocQ*TF6nL>#=tYYI_4F'!dG7'HF.(`G/0.X3J<r)?ieom at bG%(e
+ 2tqE$`PrS88M,1q#2IG at RM2D/naT!Z/[0A[WPt?\`OQJ3J<&.-T7r&:a9c9pL[V$aG8]:05
+ u_K6.JW@]]hY0&!Oo@'SKJ6eS.NMmCY@%c!a?J:"V9gA>-tO'h\^+U,id[/0%j![="_1:/H
+ Y)5SDd\a,bhWJ'YOC"^UPNJ"Q&RmE^J7W>8KDBJQ`NhZn/S0SBMV*EuA.f$nV_L#^[I*d#h
+ N.V^+:EJ<M#/8^mCmRaTts8`&)Di5)8J2-L.Lj?'mdrC'K"[D6bgrn"/q>#7I3?-=(r#1A)
+ .F:UGp8M+;En;n)?+b]R9ab#d\EL7EH#ad[3jKb/E-^V&+5e`F#n at V*;8UI)".&Q)n[V21h
+ D-C=\\^<;$BNhPS<2AX:Oi+rC\!(![>;D_5cbUsId)j-"EG,pq$e[_<7DSfYrQ/@nblT7O^
+ ;(%P$bWVLZnqnnI>`2!!A&(`L),QIBh-WA=uMV3eQ8 at g:DG=``1::E/FI%s!UO<W/=P;Y"G
+ L[E,2b(mD$IMKCaTk'Lr?jP[CDW=3`+?e(0'^H\*T>njAM,G8gK?1GLF(3r9W^:#BRBqf8b
+ `Cp8pp"Mh%.*L*qE#Jd6DW91956EGgqQq!Vds4dN(ddmAfh8h3J.:rjE-S6W3H3jUm=k\P.
+ gomK!l])[*1l_J*<Doa7WN)d"rWStV1V'7L3WCU/<AT=V,Zq!lObR3^:/+%V0&_g._S\4n7
+ $gkp(.!IdN=:61s&[_ba%0&mNMO3,F*]e#;.QY7(ZXHuNk+qSW5<OMgSbn,6/Yt\O'6,T_j
+ Cf-dF318Q0.B=VHfV!:+KAA]8J`/rhoZQ at A&$lF,"%:*iBOkPe at -'1+r]1]&TpDGA*^r%[1
+ Yh'rc',Z9/CJj:!eKIs3e99k<p"8\ViPjae>4i7 at bi<;VVL2`.5!fZ5/S9gbQ6uPA$)A(YT
+ ZJ-\l=<eh;po>MNA^SC%6cBfXLD.ba'Fn'72qKfg_,[tmd)K_F^>>4s-f>hI)+bmE9!QSKA
+ $^8_rb at F;8[$QdZK8C^&pjVBL0M`\S5%5oShB8\jNP;&RV.u[K&Q8ZT8oKJu<s(X+V==EPA
+ 6(A<e(K-0uOrN-H_H8@"CFBm<!h0jc`LSYb"RI3^_JsH(e.RONfdN^$&*QP9JD`h-B[7&rl
+ c]&uJ93/G4$<=R>5h6.ajr5kc\]_KgppZiUo9K+SeUobMi;^$]I+;g,m8Q-/J[$`4j:fnBd
+ YZlM`[)mTLn[M(iTMaMa<!2M$tuS31$Q)BJ;?QOQT%$Oql[aS2;!NnX\THX at +G9q:t5(QDE
+ AfDO@%0OgDPR-NQr!:FkG#s2.rMBd(fZa=I([]td3lL_Dn04WfPABaFjm#1[rB6OScmWsO-
+ `V1eldkF@?ud%9H3GuSF)R=rr$f1E2=KPY!$7]I5ZiI"Bg at V?;848dGH%qB6n)jX"cS32u$
+ j9fhVWB)3WQYV0((#cj]'l6PO at H[Yg8NZs-U_^M7IB*Ju*sl at lbRek?>K\o8U6_QPcA<)7\
+ pq<&#.kX>6 at 1]L3QcEkdre]O'C9!?T`]e&qb[_:kJf3:"_3ZfL(l6*8k\HM:CcZ2,'$Fh&A
+ m'h),=?<:2UP%-R)a`F!@i2+e1%YQu-t?=:8qNpfaU at TGHs?\+Sio%>.[hs'$t9_q;m at d)h
+ @1B1moK#_fP#:>gBfCFJWikW at PF>'P$>;%*@)3`"TM1o)F:]\BNpjM at bu2CD:m4Fp8YQ'@(
+ aWT\I[oB>P6Y530!:2Z`M,S]#PU/#YZ#`NjW:Qel$#]Xa4,VA4a7=uo37H)@ZhgX<^;*HK^
+ F[gb;+LI2":9Nqc_/mK\WitXN3[_`MRM6tom/eZEL6ED*\ssR1U4p"2S.kGO4c.PUq8!gFj
+ !!03o!5eDC&,(kegt01<F12;\_QMH$l`!hlZ#>0=RkolBHpAJ$Z'+q1:67*O^9Vlj*Mt`;@
+ K0Z-p5UH8VTt+R_f6T8Ps)Ag$G]jF(`ON1F4hcF!AZH2+cg7WC=$joJfDncK/gZAP^cUnaI
+ WE_L#@0Bf9mL#<LPN,.AsVVDK[7H$<uGp>rq@((3n`3$F$],3-f7E?\6fMK;SiKDjZ4QAYG
+ jEl#,%/?$&o'Y1/uQJR_jq!n#gV<NhV9BKal6 at 3NI61^\RMd)Ou(T0,)&jnQ+TtNiA_hnd2
+ 7S(^5U)#kaPG'9aAK$G2cj,%*>`2-d&"?\bUiJo\jq[K]'A/qmaUW^d*1 at Vp:`(M%#sX at Xi
+ D5>d\J(\Q4J7=1d*@.:08Y9a[,A:scA>BY1>nd[QFI2K#\2mjTJ1Q0$F.sl7nRGJ`Q>?\6I
+ ^UZ'05L<qp'[Rr"#&6rX/e=!Rr<7E at 2f]-ZEC>F;D?j:k?ubF<XosnXPE>(4><FdW(K[_:N
+ >4QkHb783hrcZ.QMrP*8f(U>`ae`!MkHbAndJ`eli$[1Kb(Hb"j<8-o5I[8fL#EcU@;h]&S
+ rB4oH(6FQ!6,_`Ld(3d\aqjXCF5&%jI-c4=V(B05*E>YA<+$'/gO$C'P<mJt685"bCZ[>W8
+ ,U`NZKHJ2tPdS"G%1,Tp7#U8%U-uD^n6\]o6a at K[\pRL0.#dP91,Z5/E+)aliMN>pV)e(_T
+ tQ8GH>kB)<Z"Ijq-5NL^"cMnnBZqnhuTAeS3]ftU3&(5:?Kih<kN\.p<nO=WF;j6 at ujYCC#
+ 2l=fu`j.4usjdaOP;`&CaDYa8M)8fXaW#_N/aqq/Ph(eq,o-o&NJ]/Td/FRB\_!D0>jEXek
+ h$VK%OB_[irmCYG.W^G<3:H'E8]0?&blcQ1GjCb7U,BS!:DCb;m=79Yojd.'L#Vb\t:4'VB
+ q`n\f1r7Pe"QS5G?-s2]J>`]qG at HVChUh4lbs$VUO'1Kc?;G3XiZuWuO3Ee3-cU0Lqm&?cH
+ BUVaj:0R2mj_99 at hS":1r;#s-bnkl`=d;!qC>Q&AMIgif']ps;&I-:>M`XSWD9T%59Yt,Z7
+ W\^$'8]Hu*)B*QMJKc>(",F)F"o7dHnFT!rhnpB)-V4',OMFuY#_F+do/3-?$#2[Xa_EUHM
+ ci!T=$p3n)(nKlKG`uV02gP]if'uk+j7:j^tSsR_:[@F at AZ0bF\:eXb@"c-J'o/m]8&hKX"
+ FFaIX*0:ASq;o8^Ce%?dO+!GT(_f,NlW=D7Rc[6/,+[K[sn.%2+`qV80rbo8TJ3o:&Z;>Bq
+ Ml07GbP7Ja!4QUF?XZLf;DGJoubbUL3ZRbUQk9U?$.pIE"i9#A6[iNd(_nMrkl==2('=hO&
+ 8``UJS%Ku3f7SCW^t&[(g#%-OjPOM!Q!!1B?s9-,-.Q.JMNuJ3]&jhCF[s?3G",YFm?gQ<(
+ *;-.A)!:"="dpt_;TG?(ARLWh;&S`5!4;hQds9FbXkS^cHBL_5:8ZYG0fHdQ at 0_@S_ at 4R33
+ @136>'Ra+_9UnBi[4#-_5XY'6Fho>RCU.J`%eLM]g;nQY"\e_q6&!bB5a;E6nuucl,8OF#I
+ (*0cXn=Wp at X/ccJjDgX'p6c5kPU^emF</at.HORfup]CjUkS_H'a0:9(fDKb-a,sN+,Qfk5
+ HDcqM'@8GXDr8oU&HCeCCmiM4XZ-U?(GN=L`,aC$\6IaF1cuP*>l1lo@^bYeY>jH$:(A6YY
+ m?=N-4Uf60[3dTWSTn,$qBK6^(pOYrX&lF9F8HLC*.bTuZ`(Zjkb!A(Bl.Reg9u"Hb`osJZ
+ c_l\k9bp"B#OXF^%57Yn^k6b5JI"&oK:0aI-LbTC;IY"i-[@pqOGp(FJ:<9\<^n3/S>/Nbp
+ 9N+4P7FMMf&L;[d6[Gs,h(plqPTFeXsq0E&/Bn?o6#*k8Tl(g/o`'ig%\^SN?K2feYIh-qF
+ O at jQkF$s7ba):O@<J/Xi/o3k]QFrn>6b$^.:MG-&5QoAf013mdI(JH'jYrXO=g"57@=dug:
+ H(gQ-RbHTAl?kJKrU-p at Q@geeBSI`NE\/b5J>K29Fc61I,d<&uA,^kTSEL+f3#V-q(OdaPY
+ &PV#!9Q`id=jj%^\Fju%GQ7O*`JYOi;h:\NV"Np<gU/DhQE2W>OI]]]YV:9I`58=+"-nR9R
+ ZDX$=24^3*IFnO:DW0L"tl^';^((@!4WRGY(lH:PKu`c3r))l8.1kP2[=p=J#pWfaW%=g#P
+ 0P)VOO3L6JLp@>VO_OaBZp+7,<DLdS0E8W1)VR45.oG*kudnVMAG_YXaDn+N:=mIJXe?.TM
+ rsbXe<D*]0j4fttDGBc5lnl?62bm4:CuP]:R+P%T!A at no5e%\E\+C;RfDak1.+REKsRK_/h
+ <+gl]k'E5eagGfF.Q.(p^2(t:HE<M3%Sg6%n7a\^B)p`]XO1*V_2,^b:(r=YtQEE<t_;$:e
+ BN"5s'7]t+#IZ.T26&oC*??0`cCA3>r]PJbpn[,8U:KM[6/I=[EU.XS(/D.gSn*+hA`E:h5
+ CbtBJu_O0rA8IK%&7i$&@;XM"3YiXl-o*#n<g$u&0'IF- at u,%?o..LXF"t=Su"-%"drEf(s
+ h4Z9O_bJ;b&hdW\LlqV<a)ufJ&UBS9OapI?,I7Ie2]]iopebCL=c$Fo$3tg,12Hd1Hrk'2g
+ $, at f=>!S//[eAP.hAI=XIk]t\:YU5:PT9`]V#^o;%@2?qZbJ]9rk?XHH5[1)h9;#O$!-Wh?
+ I#oo?5G/F'\/QcER51BF%[+R*;dpc*FXKD1AVM5IIbuT;s9BSBP'8&k_ at i+:Q^4,J7UIUA/
+ X0%(Ti"&1)p[6l9l)1)YZ=\?n3JREWKR'nVgoTX+qkd&k94Ut%GT#oXUn3EO]O'\%[YKIGB
+ qQUbe;&rsBd]I!I4G#5LZi9848 at YB/@#12a5V7dZQYjQglmocU).OGj^C3-D6.?OruK9JK4
+ @KB)A.A`n1Q`TDns?p%On$8_P+=P)Ja9+EV.>gW)0X\"jNXA(HU,bMRuTqVbJ_3Rd?bUl9d
+ QC9P]YEIpMCCWht<AM4c"%do%:;(G,`<(KCE4grXkTbfNcKm[:/'8^+&FZa'm,\Se1?g?D9
+ bdi</'mUS0&dVu!69eS(A[^*QU^@'M"^1R93?\-5bhS":+ijmmW[Y7EGEATV[UZqu%X@"u`
+ @;N80-\F8-d?VGc#=I`-n`Fc(T)bn.,\Va7Xs.$Rr%8DD988XOPJs*jS]n_\@g6l#+qK<FC
+ MeQB9i&?T]tm5YI5P6/:*eG at ao'p=#Cc+-m!/?sj_*[nGbO9.]DL-R7h<q9WSd?cg;uNg*6
+ em4W4H58b>:)QJk_m&CmaI!R.!U,(hs8_4NMO'CT3A[T]N&`en)YcK'H_&:=-7$ktV_CR]c
+ 6<c5UC-BraCbV<MQgiCm+TLR58HA:XE+SFi\u`k-H_4FdA.F!!P5.VKL4M\j\]4Lfn+e?P!
+ K9<s`?SBWIB<8 at khoPfh9oGBC:Zq/Pa,QZCh(Y*PYghs5n.cO32F2E"hBq>LU8\V)gN1DlY
+ ;U`Z[_j-tY85\u_V1n_k/BF6!VS;3dDmu<#ILISZMKcDT[.'BKTA722YNFon9pMP8amlMBM
+ @3G)hj,$<#1F4F8sQ15FJ'cD&!<l'_!cm??P8o7PiF$[XVYKJc*bpj1`b[I;.EPS^#8q8I6
+ H_i:Tlj&r7 at Fis*<6##D>:J-k`pQE_+B]X-]NG=Xd90;REOs2aLWOecfc%$jR5-i/C>]"+D
+ $j`J$Ca0#pP)N#D%/)EM;@HCA5:>Uesp[YtLLEEh"\6ROhIYJ#>Z!k#=+fj61'9CR09dLt]
+ bP,dVG!bd*f at R6b_/H^G<<<&-D"AOcIPGQh3-Of'H#$Wb'<]a.9KL=:TkbN.!XGfJL?GCq@
+ U4l=los^dX>%$ZJZs8VMmsnSBMeT^E8H. at 8-_F1g(pZ_S&jh4F/93M^9OjSd-_Ie.V9`=Ql
+ QW3[:=K>L(VZ3+@=0X9_HQFuGJJ-Ml<iq!SA=9?kCgS%__BV002fBFLCZJ]WY=&hg_`LO9B
+ 6qe4=t!/QLd3j=*\2.`[ct^Y*0D'Tfi`m0di9:-_!bN!h3<Q"?*O`kl_`)+bEm*lQTO at CgD
+ _$^hFB=-]/*#@G%(UIH\*K%5.g303%bY)'UrFa.-6T-^B--a at QA);mm at lSFhFIBj+p1,$W6
+ %4O/Z0,,D%i!1XQF[E*Ons(%obiD#1a-gU\(niVkC89Y-)PQ#bM<srhMOHsQ=3`/P.\<]0.
+ [L8>L,2W].=r>G(6I#*U9QSVAZF$8<'V7Q;YW3S?-b'r![8ISgGX*XPV2h2Pqe?u$[g5(+-
+ 9+4</[Q%^,:=m%n`;cNQ/i'BMSCEt<MC6kc at rBY$n^*W3nk6_T>D!"VMT&u6#%!U&jUO?S!
+ 39.E5#fl-cNB^TLlC<3)N'OCgE,<4J4d[e+/$f"[7e.\_+W$;N$X#?u4jdEmboHi_F`VJ0"
+ pB]Ytm*g>cVC$9CI!''Bn8\57>HChODu%&+MdS1?tMeNru83FuJT#Ypfi5eVDUcfbi*OV8D
+ M:;0UCqh6=Hr&<3s[5&?GJt>AKML>V2 at R[]3&&7'lRM4X6(-5#slU=Bco!Li3AX,)(Ch"JF
+ [Y21p+>#q=^I0Ym&e27U"V7el&TWID-KS]3N_TSd`LY at +rM[$>=OhVI8pmTd-TOB3e()u:G
+ Hs at V_TbtH$Pq*GCM=3m)I9.M35i?djZ$,FcsBj$*r]e"`Bc'q1WguM<$\8nH8(T'f)f.m^6
+ UJ"0Pn*eF2AGtjZ=?AcsBk/#B[Hk34;A8Et'q]7^)DBQCt'LTEPkiL85UGUeTdCI^3c;.#d
+ g9kf"S(Q=<KU`eeL6>RM>HpM,PITOiqu\V`Cuc&%5i(Q,d[<S'kI6 at 3:/,2p:mQ53`KOf<^
+ [6T+e.kX6u/(O+l_EtYW2TtRa(Z1+B?[,cQP#]#8%FYTV1ma0=4LMX**k!Y)jFZ_%U3C-Ee
+ if:']-Nee+^U,9+\MCS>"T_mW3%S at Yi,)a6E'dgb#p_K-g!F&.V-*MRCD#q27rdtUWM!:r<
+ 7DI5kd?4.fe'Y]Sen!VM`VRU:/j?_='!EKs!994ak&9b"1m>C<nrNXd0XVaU*T-5(O%WZRh
+ HYc/c6F5156jn0bIP<_HIai=p>QR3DM+n_H>H_N#S:\]i%JB;A%=icEW0Gb91P6`P[2>Q5E
+ :'*p4$!KgcS$dR3mL_G1;LBWnM#EDD0'k?:8F>:RLt&=89W#-7Bd87#uUG7lGk[/\i-1/tT
+ UmJM1*lMB5]6=#t@**P1'dS^Zn?(dL<6)*J!(O(U!)#ND at 9ac_bjC`<jKl%mi-?`,eC"Y3E
+ H_2.P-&f#2[Os&.7Dt%qclP1b@\LK at 8lk_*6^tr)iECo[M1!Wrm194g,c4"!>*lsXp<L=4D
+ .$.MW+O-Ws8=W'k2KQjj':6JW2:>u:8EU;kX:/a0QoE;5p^<GaB/[]O`4&`6jmg:cE"rkDP
+ @g/TtQ6q'g.VPRO'K^(XiFiQUBsF)Gs/`'N$FaZJSQbd(WE+if4A;aAC-E(&gkSEgV)H"Ih
+ e,MJDDUn6`a?'XI7Pg.QTE9L=);Pr((3:?65mj(iL(grmB!L6fi1#lehc#\29A%X)lJkQFV
+ ;8LJp:BlU;V)+Ce$T1RP<?4bHiC$GYo,$CVQi&++Mr7BuMFu$/9fIncniP-mC#>V!^()FmK
+ gdJ5dWU32-d[USsZ*\Yfr7<?ZTtPJ>>RT9/m:rB=J#/ONnGdhWD#52L9 at Hs+-_a^V?g5a@"
+ SCZ,-QLQk;G5`hJ"@El@?I5%OM@,$"a#NrBMn2(DRlHh&lW=\a4j;**=GZmS>j*[#OR?VeL
+ YE<i3[1'SXJCE)R_^dhp\6BkPm"RYUu*C"h$$j6]9_5),cta;Uc_d\fPBqrtS0(S-XSDaM0
+ [Z(#$h_X<kGZMmCWba:7NjSP3X0P"tkO'FOln at cp/S=qW)rl1<W'gsDYU"?%WP(b<u?)9.-
+ %Oq[i,Qq+AL[:%tn.W;OC(`\P<[6-%K?[PU:_%R^#6D6O]HWN5i,`E0!qk[hn'6,bX$#sED
+ E#955M6-9bZlFr<e^B4o,)Vr4&.)k*AB0CumNgW15l\A)c&s".RSi"q''`pYnPmngC^2t('
+ PUi`L%Z:f(O,Af at PWo0c]Y4Q-TQVa_h_fs#H(!G[D[Wb"MU2J3[^ZkM%"EE8#8i;3>"5&Jn
+ ']hs!:Od(jE;g%Ws*o$Z')O>!g#uGYjSPW^V(r-SMhST#a`IEJJ@*qQ4;!'/A).\"uTUAas
+ sCMeM'DU-D;/,,)\D-Y+&Ui$J,f8=1n8N at hdjO^[^X,$YLl?"A`jMO_a1K_Eb!);;--8NeH
+ <H_o@/[Q3da&]Vc&giBcpJF<#)A9d\]G?j*SLHL]mW[7>.Lp;uuS;:l9>EY:hToufg%E;__
+ r;!&"$Ur=&W]Q4L at o^%7BlR]$q-'7S/_HXCTi4C%;([$_HSH'FEg_j!X'C5&Sm:%gF=$=E#
+ Y-<@V^AuO1-#R&"`u>@plB3A0[B0jVTHJpQ2=3rJqpUO(O*qS<]*ODV'7:%U6B"4LD^$^Zl
+ Fr*[8ESD'NFs^RRu.SdN9J"#4%cn>hgJiqnZ;'Q\mcHBNJB3P6"P(lW%8!CG7^b$Vj*AUI!
+ g.+0^4rf]r^`SA7`YO>#8n$LMCd)<a9qZ=K6-F!>9N[tke^cFoQU%t4ccHQkb at +8EYcXEOo
+ gNhF0'/?jGcah!t[g`K3W:@KsgPo$%%LcHWrfKiKbQAT(:l\$i at 1*YATbG?LE).[\U0-4bF
+ +II=9L2eTsp>^1SO3>RkRV)j at fm]B.okpZ&o2OioM9MTE:"T.Y0Cge>6i3QY1<t`d(i)pS1
+ 5TBp,MD];-f[&/kQPH*FpFDaK[JQ6=V"F_T;5XQ9el+(`jhST\/]"e/'t)6U<s#QK*Xfb7Y
+ ^V(W?fKo3Q^f/$jrK(lXrkKFCW;"0r*DK8^@1=3Vl19L3j"rNs='/L!o:bd&KHIHNHml:Gd
+ h+I%$gJR'lW5F3Ut'B.W`WFRhi>O=G6%5HHF[mcBHK at i=ED(?/_di2E"-UcZWI@$RWeM&3#
+ 4S$KnpP4*9JgN at UsXU`rLbKjGBbsWQ_fttkXIOLKj/JDu7J^2I>>N8:U"p($9&QUs_[^t..
+ rTX$%M>"MPNr";XXbgYYmNrjT`p+%gd#"'D/No%$m>#RNg\L;3ea[#bqcK?_>#TfNqVDW$D
+ n:[aRJI%BFYB3[3)arqdnqaI;3$l<G,%R];Dd12Bjn^sA/ID893_kk>=*_W\1f at J]&":$_0
+ D7HLSi=n_?!'LaUl(S.3i\"O0frk_K*#PNKKO=NEP\njK0 at N81-d=7*^Y=<Zdg#RDbZSiFm
+ +>:XulnX_qpMiFo$$B;fEP0[`RCKSAj'(-:?Xo[RbPFiW,i(Z]++D-Y[p=&"FS_kDm+mZ$O
+ Lol\g>[VUa+iVKc!bk3hf[7ATN^,+C<c:$u&;lt!%>2NF!l+!sr4rh22MrsE\](u'%>EAc/
+ 83.V8Ks\L<oB+`4V`/O#5MpSF^e];5PGZ<P"T")s_kQAK1+?gi>)q0GA"9V`fljp41Fc!tm
+ +]/Dm[`*.*^B(Aor=pfLNG:F$;I8P^3pCXqqXL*>eSp=k"J.apI3%O$5UmU'f(&$H:gNLbg
+ [NPnXJ.64`oWFRStU%huET<P:(<'5u%X\IfW^N=%E_3oao?*(GG4Up#hsVJ%sBSq;At/CJG
+ kMg:VFONboT$c8M4Th::'Ko]]<L1Cslh[g)\Q-`b#J'<`O/GOOBS0[H>"p%\(;5O[BQq!d7
+ ;7uo\P4F$\mATr>W3R],Z'`nIl5SDEPPQUehfZ_,c#Bht8#>:@RTna"^BZpL/_.TEj40lpO
+ M_)0T,)\"Xa<HNnZMM!.+/n.L,Q~>
+Q
+0 g
+BT
+22 0 0 22 297.143848 542.838269 Tm
+/f-0-0 1 Tf
+(Is it)Tj
+-1.246094 -1 Td
+(de)Tj
+/f-0-1 1 Tf
+<01>Tj
+/f-0-0 1 Tf
+[(ned?)]TJ
+ET
+Q q
+36 428.798 206.23 -67.715 re W n
+q
+36 429.4 207 -69 re W n
+[ 0.799336 0 0 0.796639 36 361.085705 ] concat
+/DeviceRGB setcolorspace
+8 dict dup begin
+  /ImageType 1 def
+  /Width 258 def
+  /Height 85 def
+  /Interpolate true def
+  /BitsPerComponent 8 def
+  /Decode [ 0 1 0 1 0 1 ] def
+  /DataSource currentfile /ASCII85Decode filter /FlateDecode filter def
+  /ImageMatrix [ 1 0 0 -1 0 85 ] def
+end
+image
+Gb"/gqchP4q1/Ks<JH5q3#Y-m8I-J)KFe1h#QZ*=6APn<;3Xuo&>_f]Ob8OK;%Q#Z/PrQ>`&
+ UXn6rX:Y"[uCt1;D>L.^b3ib4p:nB5aI!\QdHWpa"sLYPUhn,a[B^q`M%^dlVL*^7CXY(`a
+ WFp$1)&7uqPq[Pg'%T)61/k0TgU_\Iq;m]3GA>BOoBc^W't2+AN-J,UgNb4eq:m&`9ii+RE
+ 3g#Fqa9atC!SHArr8BC>knMbCC+ at W1Wos>AL)]S\JgMcs24_hNR[H:<]Nl%n9CK at Qn;FL]l
+ aF2!",d)Ua:4@)@rZ\6dmTRF;o+TL!?iKqQP^#ui\3'Qo*G$EBRHL;0DfLGXablppX:8t=m
+ jkQE4+4$5o>QV(_o'Aq%:NuYT].$J]8&$=K&#_Rp_Bd/i\mu90$%@s0$GdubW2mZ]4sk0V`
+ XL1m)[.R#R@>_"@JUmDou0&*TH$kkHrUacVp)-;+bEqroW@?a,_<X08-fu#>G5`^kq?VFmG
+ 2g<lX95Y2*<DI:Q.1B-fW7Qg^q=[-,;7Fjn`dLs%Y%(_!\IqU"ZVMmq3$CcbKlE+I]mUti6
+ 'UA1R9>\g>Yf-Y*DGY-#[QBp[L_*PH59GpKJ"mD-TT058clLT[^j[jGHgG`uJfU;KeJXrVt
+ km=&H'W!W:2L*Cp`Qkm=HdY+5]f(1`P3Q\q[_rI".83QI&=Ylmb))6n`<7FkHGoUeUO<o3]
+ /qDdJj=NM4"Fe^__N\cXK&;%Vru at Pck(LJBVPVc#hn%fG4*TK(+hiZ*%ij+Z%$tFLei>]r(
+ ;*Ga/K0sonOTY5Q%>Ia?WZ]@M"/8'I;5hL84^,7saL%]$;?ZXj0KJnWLMg]^0Ljf^is=kIB
+ 1s9M8-p:fmC-@"@_RV?Xm*^A@,(IJoV1,\L=bH-t4!)qW((M]7`D]lg at 75st=lmCG74^\X[
+ >o@^4Ddi0KlY77L,np`S^:%Z?9)b1QP]$-;e^@+F7XQTTE?DXoiiY^!n#`lAdS3QYOO)VT"
+ [@cnrCZ.7F_D%Gui#u.%G<EOm4Ylgo+M<=*^:qpoX2>&<Ke1ePF^^M.Zo^(Xj%S!)f?_7MC
+ X at 4tNd=E(Np=X\_"J6.NqIk9=mrD\FCn):SW7hVZ]3^R51`#&Htg"/RH:T,<W!k1fGU9fjj
+ "W^%b8VF6Gg,GZ-7'DIj&uCI?KoGEk-2Rji`L;#m/-JqP_fhdAKd4<`E$$G^=W*(l8iUOkt
+ \uPNBQmHD:Ar(AR;]^^*eELCZR5IXVMH=.u=lH'PU-cHPjT`B'D?@2hjA-Cu2uY.9*.dsT-
+ ?L^P$a"p^b4]+gs\1Aq"ArLP(<>4(Efn)_?FObsbR4[(Aeb7&Jl.pW,r'(oQ*i:E/XroKK4
+ fp)`f1W2*rTB]p%/E)sX>#BOqPfSB*j2[/h%M"MXN"B71nF2'WpPQCro5\A7q2C-Kp)?uZ<
+ 4O-rA,cHM>Bj=Ae9Bk-bKaIlamT7J_a$6K$$d/%IpU5JP0m=AQj9jS]\')J\qu'9OXe/UVP
+ [s5@"@_RL5(Gs\:&^:DQ_'K/TYAL`1.OP0NLa!kV^+U_1[G\5Q'2-0XMYm18-oGSpUT8onP
+ 1belSGRl6VKM9TM[_i'@Qh,XZ>KS;DtEa`hNFD)&+a3?qg?*Qk-Ld8IoU3h&u54GC1C<IK:
+ DBT4CJK%E at Wh&RM)H+ at Ah-E9>mao*X/ots4!q,1Dp;VS[k^@;"q at 6b:2&tqSl%<Ark%*bKm
+ K)$"]Kj^cDF0NZ_MfQ=X#_cahYgXWD4$6ik3Mp2%P+\Ym7)gsD0MDTbo)cnV'l(/M.`gM3K
+ duS5?F\L;Sa>OP at Za*AN.,U])n((1jYUXGJ;[%0(^r"4E&/3^6_P1bDfgY?VEoRupTt)k/%
+ T"`"T_FMKjl3AFEiq`4f;b+OjKit<'Rgr2q,^aatQ6M>cHfl(/Iu(&ogrto2iP-WFb^+d;1
+ 4q5uS+qNJAjWAd#J8rc<94i/Rkb0L*o)L7&6i6N9g4Uf$NC+Z.="U^Ya>aEIL!)I>cV/)Qg
+ ;,I$gH1\PG*BEcT7mEdCTFL0]acY/Bu5b8KCY(l94E&AV=-\&A?IjNlK_L7 at UHG_Jdi1Aq8
+ l']1];%%%]T^CsE$qc5Xg$qk;]V[)PTp-T[=b.+<P`uMI!uRT6*%:<-9<7#@4C!epRgRCSR
+ .C9nXJ[]k1C`b&IMC;KS]M6TmG$f7:aUd!k<Gm8Y!d9<lUV36I]21N"LLm8M^oq+./i/?q#
+ =\OBZ:eN-DVTW?i3_"E<Z1BksjnR5LFs$Xrp<uKIak;c\2>.!o8WRU\'Ign/k`)bE-V+Idt
+ __isKlAdZ)[.hU?sZJZ_;M;>LG>ro4?-#L\U[0*q1l=.fq_DNoT9\Gs&?m(XU8-3&+qJk-L
+ :B3kW'7d1^mocI7crRZ%$^jfSip0VI#1&q9eJi[6ZXl/1g4g'<WU\'H^p)d at drRWJhnK1h_
+ rRVWPoH..br?iW6rPoX\s0;U6!\?S0+'4!ka8Y*+YlE@*>QOO?qi<8CraYtJ"k\=k5HY"`O
+ 8[*6@/mM3\,u"]p)d at drQ"ot$F'Q_Ip<$J+8\:G.j/+F]n:E.B6+61h?6nF\k[PVl'C<9#c
+ rPuSb*E?rPTHK at g/tbhl?h,Fj`?B2\T7X?j3 at lUj%pg,d)[5$:rc?mi^FU>QI\:ORA8q6Fq
+ r^!hq.eh'IK&F9?Z:T19'\];1LLm[ij>mhLrPP!24DFh3>,<^=5hq?Z?"kpH7/_;0(o-!Mb
+ 1K65Ra)*P!m71$H?i/99o!VRU:J1JG7isK`/fRI-,XoS>`)_5T\`t`"^E<WiRlp%WQ=+L7i
+ 'kf(1<l0hMp^OA+q`js-aIfQ,AL1SY_Y#VH#_VR7mmEJ5gf%SdVFLYmU!Ohfc,"A]q[1&1j
+ ]s%5!nCfbX50lNq(p`630</,k at 1-1,r@(/=pWmnd>W^W&7uY?$B2F'UX0F$S&'%i(f'lnW<
+ bCDr\9\i'ZDMknI!2EbQ&I1;@e+R6+j6eZ&INX`IU]a35,e>US0sSQ\43#$=Rs.qI8$+Xso
+ <15man%CY#2;E]EIpC*@EQJ!7`2+3D\"VT/t at Id@rPTHJTV#N&S)Vh_l9N0A3^/@*n\UGo/
+ Shkds#@3qFE6%'UJ3_0ncRL#jG>I+<O4(2`OemN0W6^&M8#JaaSCj1GkH%QFYZRT"9KGNgJ
+ WBe<SEODHQ]7Qci>d$S>@]$]kKb<@eMKUo$nYVjX1B0#T!V5#3m0s<6iMZlSH>>DtoRs4DB
+ ?j('R!7Vm'M_<[QisGETi_<J%ZniH+31>jAUNiYXl>g at R785U`W at Z#KpT$DXGlWUcpnP[Ib
+ iK+\LTmo1#H<9WIPlS\o=X$=bbS?;U/s6 at f7a0#?ag+<<,Gh-ujqCDK&D\Po'oq+J$Z.TGB
+ ed'5ViB%*kmV:3.\%?N<5XBGo#OnR`[GBgrSu7NnA?g8ZW><%p'igu$jjZ=hJr=%>agMN=<
+ ^T=n6dSQUQ[Z:ISLVdT5:ErMHEJIF/AnR)_H[\+h7+<Q4Z#c&,s.Yk2>/=lZ4!iIi/FY&ob
+ <C2TY:h;1&O+e8KD4\G/TuturVP[s5@"@_R`lH)jp at hWh<egI,m>U4aR?gaRV2T,_i_e/ne
+ nT[q$3<kS03</nOM^tr2*=Du5EuHk(^r^+CS^gu)W!DEgrCp*2ksJ&K:1p-Sf._E`]OjNLh
+ CV@[PWjO%6ALgpu()gq"QhR'o\-34W>4t;-b1Y&]V,R3*@1l=QU6nO[%#;MQ[<er>r<aSQ.
+ GK7'^]"ES=n^S["\;%#,md:.VD9-ruOhF]-=@-td at _dS`NbkT6$Fk.*+;#d!4BRXX29YY:"
+ 8^/.o*lKbW$-70"i"lnWM^Ne.Rku)+sR_Y6/U`-bi:#$PRH7Y_^&6+$lJr=2pVtCgD>*4cH
+ Q8)#1).eU(%#,o&2,Y14OSn_jM06D^HBl9NJJ)A9F.jI(RSU1GS&6p;n8dW-ceHruj#VM.^
+ 3T=)^^=K?^PU=di'C/">-/;*n6fBq=B#AM\riJAZ+J7coK8I]WCf?37UR8b0LnPW#VD6nek
+ %%oL*20#81LDN&hM$oj*q'L"DoA^$1KJTl)#Q,D5e, at 5rCNb:\oCX#^mC\*R+\3A-=JQB\&
+ hri9ng#RMshIc>g4[lY9qrAjc*mTqFoeN+M"p0p-OU_-C_'%tc#<,aFm0K&fF?@4B)".He-
+ IY-ZY`Ha@'59]r&bJX7=*F7t?SbDe0H5:?/%n@&bOa1d$$]!&:R[2'i#]@`NgCM@<Pq1)sm
+ i&Lb'6FrkHBscOD(a3=UGdC)>(_!)\WK::%a)!.j\rhMTa>5bc;a7L_c=&:Y71#b9-_ at 9=I
+ F@";4?Q=43qSIV]R9O\X/cnfOI<O881JdkgMdsrg05Kd/I\03)`Ut<3miF+TMo)4(_"g=.7
+ c$6_[pP%ZU2ePZHWf?IU\(d6,$Zp1/h$OGItJLU;Xd(s.t=^KlHd(pP$1WCA!UGjM^9O+N4
+ t5TU>3.cBYt],VEnd(C$W<OBPO`#GdcK.lU;kN:,Y,Q/\"7[:LY2/iT<hlg7.,b1&&>V$a(
+ d5_EZ`2&^l9XK/Z at IJ'#g[7@:?.b)(S(DIR"cHcA6'8+[RaK]"SH+OCj9%CPSWlgEPkTPIG
+ !"onr6>-^>Bc$W,+cMGAU)'=bIm3A`QOit>+5ZDQ\o at h)R2NRt3r88fUK8qn%nVTT*uc/g>
+ (k`UJ\M9]9O7G~>
+Q
+0 g
+BT
+22 0 0 22 88.727771 400.323962 Tm
+/f-0-0 1 Tf
+[(Compar)19(e)]TJ
+-1.365234 -1 Td
+[(script )-3(vs. code)]TJ
+ET
+Q q
+365.602 426.4 250.668 -62.098 re W n
+q
+365 426.4 252 -63 re W n
+[ 0.798306 0 0 0.796111 365.6 364.303344 ] concat
+/DeviceRGB setcolorspace
+8 dict dup begin
+  /ImageType 1 def
+  /Width 314 def
+  /Height 78 def
+  /Interpolate true def
+  /BitsPerComponent 8 def
+  /Decode [ 0 1 0 1 0 1 ] def
+  /DataSource currentfile /ASCII85Decode filter /FlateDecode filter def
+  /ImageMatrix [ 1 0 0 -1 0 78 ] def
+end
+image
+Gb"0Tq,>adrkS&RTSjQ+_%f9B8IR<i7nA/LT/hE5_PK'j`e[fL>/6%r.4S4-Bgkl/.hiMoBL
+ P3T7B,kNWoDF.eT(C?:)A#Oj#C>"]%tuP$#=2Jqq]rVD9XH#jSbLepldN0351u0^#'4us8D
+ QLO$A*nrV,2tpYG&sk`nf-%X3$%2K#^)^UBrVCgN3-0JD`46i&kK^!Vor:S27GWq>Re,X\?
+ DIWKgX')('Y-2qNpWoT\WPWXR>=cdJSjlI6m^/M\GY\N"Z`k!c!g\21b]Qio%]dHUI]Qiu+
+ ji`u=R9pQ]Y=`qPC?k?La'[Z6FnkI"RLO%*MAIqfb:>Fd<gFN'.5c#n0DV8MC%]W3D,mVkb
+ V!a9rE`W(^*uR]e<mWt>GI%=`@Ae]JT$@#UP`*@$KfmhDX'E+kk<*=`5Dd^D1pD"P:G:d.+
+ NtI>0>$TRI]oL^UI`pAOXN!F_t?`3uU$Ghc\FY<84gep2JL3m\]@gB"tcLchX0drCo._nit
+ f6?"#VqbiK1[kjdX&pI^blgt.F8S_:5J%MjI4g?HqU5JQscf-o1DUASJAiPm`*G19L!eo*R
+ Q]5E="Dph*.8<P4 at ZP/X;,V7A3/@IUG>%sHAWPYpl at S.-:AHbZ!$WFnM<2%uB!LZdcH&7F&
+ 3-gNF3^tIeU,^7 at 6?MQVIcSkh5Q'L)e#-51&'ra_cG4)=p9.d!I^E"eZ*Ih?h8YcJeOFCtO
+ Zp<me&oLeO,#pTH0N]DCS*J6H)18u;%0dDB[/8TmJ3KOER4LCmq&Q,$=SO>)^4be0^0#"mp
+ ZtSeQ$B[SN8J`2J2(DMEYg%Z/31Kg")IhdEKp-Br\.=[5:)m7eTF at g;2'?f8d:'kjS;q:tO
+ 0Sh=nO*%Q at As2QRg5r9p32Z1<l8qf0RoFloIi2eo"ZN7@^i=-2'i.unOOIUJ.LcgojsV=Sk
+ qj]<1m/P_3rOo'oS]`NRp>drC&:MQaZV7jS<mbQXDSisDlX_=t7:/5-1I^PlC<\=uK0.H[p
+ HDNe\\>*rt(Pd1k5LVJIEdI*D`fk1sD$;XU1M&/+6*4:@HZOe$[d5-\EM3>U]@Uj)ghi-2U
+ l&qfrp(2B/##$-Ec7N$1R:NAkB\P$$n7+WU,g36`Fupp%@p#V=R at g?dkUX7Ku'$)913#STg
+ >0ONEr'GFQ(U75G%1mYKt)/qZ'Cl*Wu<PSdiMT':c(Re%\0JAnsK9akD'AmGH"rXR/E@[2i
+ WS&'*%h<RA/Ii<DYfJS\uQSDQj4'F&o]$E-gNP]3d0#fiK/Rh`_I/7*#Vmd:u8+.o!jZ<FB
+ oi&s*rjNO%+jbjrF]kE,rjKqb2VNM+r9q*UAar<Fb!FAme:%3cWRsT%\I^LACD^oC*//&2f
+ k0oT3WgrD;ml"D6l^"SE3I%c<Ci%U9=4`jD^]!k':J\HF_)iX693.cB2,(7"Ub at Pp08]0;.
+ +MM[2=P*GcemTT^V39(r0(an,B.)/&!aDP3W*JH]-<E#-)S`RW8UubJ2]pTiM&u$6!)Zn%j
+ +p at l8nP69Bc93jN1nW3GD_&2)A"!)&5u>RueH1=<$?`?j_8RGFu`ZO2/[D\5N]89AoXsf8<
+ /al>lI+nh)@s?:H9ZbM_A8(g7.,QU?*P</-AJ$@3,Nc1*?l?BYPq&T_V at +.A!ONK"?\Bkb5
+ ,p\+4Ac`L at 9UISfANdXqf0:hRnOqA:j*?eUN'N?4HfTO;oba62;>l^5LIP%'I6!kCtc at e",
+ E8D`IAiZB&R>tjo!<!*]WJ=t$d&)Aod&A=c9Cqqj[-V6*,?79oiR5TqFHIqN'<,Y]gdXi:]
+ uQ2pASD"T.-]]RH')!H$n_nWCf%Gj0+^FI#mST2A0)`<_Jp<\d_H_0S56s at h4W=/SQ/%l)G
+ [<k82<"l_o?)/?Z[Z&YYW:g;_n#4H9 at 6,l:26UVJ28\p%:11e[ckj, at XKtjE#Ad`='PnkaM
+ ^'TA7X,6?<Y/RGiB;FK=?,V:1>OE&eAKB`F92T.Xj:!btaD4_eYkJJoD*L`[B>%d5keO\Bk
+ >NT3n\r+Jt]=2J_fH;X?DinT@#H"$&K-)4Vd\RQ7>ZXLGrhFoo&Jo_hI:4]H[E$HBE:g`MS
+ felF/.+g^8Hl<5oA[#A/X]]ne^fqJsb)s7_bb80SV:\bLV3-_f<6j*-0sm[=]GXIU6a$]K/
+ 6hdn3fII,kGHQ(TjY("_AB2uYD)ppYY>=;-'*t;T,W$?Q<KJg[FW#UeN.)me(N2/er-^IlY
+ Xk.gsS3?S!N_n.2<&oE%hd1:Y5GU<,37f>r6>g/_)=[cu?,>^E>W\>UurlqcST-K58H6 at _W
+ ')e_jVNXk:rD]GFg'Xqgh:KU6-UaBiXT#-QM%&`/?2^pRW0MsrcD%B^GP6%jGjRrGKs9d..
+ T>D?q4C^8oZfJkskp%0G5/*RWe!\)@CMWXiD#1n_EJFE\4j at 1%m9u45H"<`*e8Rs)`)Qjg]
+ 5/N)I6tSL![:7]Wq!aKg5Bi!#`N4pci?sulT.6uYZOXj-T1&ZqVmodO$4%`&')<'/i``TGM
+ X]RPOe;"Tf8AN^$24fh`O00b;mLM&CW17j,YAg'MW%<%d4)45_juse;d:i-;^G)7\5j#^8s
+ W4lXVgJj/=kd(1#+47;T6%Q\5Q:IMJL1MVe#&ASndZ=_R8AumC?/#.u$,39;f:#%&Z^`:3!
+ BQmZ^,=P-*=-:_BiFGNt!TP-`^ZV#],)4*A&.ENK_/nB!$o_B[%-3[V]kT3MZJ'A)N:#bQK
+ b+ZrG'X(*?$o#ZUT,]TprMt#[Q(W(O;[5oYO-_FWL0@:AHD:[`NEMrNf.B_5#&3fpN6?mng
+ =DPYXf1Pu%P7-@*r?epi,=elT8k*SGk:;`5G3bjJ"FUL<<P`qi>Y]k9Q=*3&`_ at KI)K)@5e
+ TFNbBYoN]e%9=D*,LnVC<<tgGgsO0N+V0Bh%OV%<hVIsTTj&Dqp1W+(+U6H>4tM'>hGm.*Y
+ \/_i4'->=OueLbD*^u!3W/-Y5sVDWM.-L7MDqUEuI$3JkomL<X';u7jd2-#2Ye^<gMB$Nb]
+ <9(1a9J]NioP72^.GS.O9"&4WF`IDmUb9lY,k4ri+j at 28E<rZOXpUVa6@];3DPcUA<-Tp9r
+ \1?#-1E%D<aQ*;tSb(S[5$T`F#Z:LiY8rr"16>`CHL%Fs=:MQVgT.]la%.Z90Gh+1HcK*:H
+ TemVOiaGUaZmS,JCAL!s*>6YnfW>0+p3P(#cYf8Y9K5Z;dl;"HJP%B(/%fTW2etFM8u>ogO
+ 6'28X`M2?8OV1QolrQ)b"2p!V?Q`3"5Q1tAKKBCrcaJ1b%7e#(d8 at Z*MLgm%f7HD,MF'iUG
+ 0ol5)GYun=B.7T.d=5_#'ijRfrmsr;'rIOb08Ad\F=:&/JQinBaQQ)B6-t;JTXsnV)8Ar]]
+ rkM-kkQ7lAoA+EfCG at lCC@6eQN%RflP;L6WtX]`^M)K[#(P"UW1&H\5qB3WR_9^fh&G&H8M
+ ^s(*8OJ<$rZQC/QQT#bm\oqb3,./k8eSN<XEV=FQ`He,:k`JYOrP>BJq4]P[m=?=K.k3!K$
+ B>jAseU2[OYU<VX*Er.Q3P:-$r4`pPTNI#1n`\g=X"_amU%'`Mrp="M\64>[4eh,h-aJUE%
+ %WK_A at p!4.0<<.3=KYW3iTHlD/=%<R^KkWq=<e2jR at j2)cj-PS]g-BSV)=F'PqNC+%7iY/l
+ aS``\R:'ff]PrV0VuC7_q$;Jl._NbUe-p@<Q;-,^a8<grU@;bN&>0n^(==MeA</0lj)XnJl
+ 9Lo50?YC`_EShiD3ic0X]Z7^\t=B?aU--RWihr,UQ#c*<BS51E^J+1Ddk?,:PM(M\SaD at U9
+ [MI^O[B/Q^BHW)qq3mIa.muW+pR=UE-Fp8D!Vk1 at na4[TVe0VHQ`A6=N9W+?#V^pE&'!KtT
+ G:+GSQ;YRO/L``/\p&OLHtmE=3jli*X6YBCh]+c20gA;a@(N\D:(hJK0T.RTFbsY at U*FZDe
+ /b*;d at Mp!A!SR3'p6sG@@2JBGbnB]/.Q0W69L6YmQ0>!<`LhZK=kh'h46RU\,<leZ&4Y>qO
+ 3P/)c*(i7JkB![A$\#A7FQXi';G8)J,"pmG['f2G<+"$1OY1]P!"&Q>A>6<@a`;2`HQKZXu
+ `_beC`YD4T<B<TpS#:_S+RFB8o`3MW]+noA0fhsto5$M=)92]@%S],s4]J2WtK;Osd%4jT]
+ _]79;+_2]#s_M*":f at Rp.jm'eY6qc)WR-bg[7o?R_,IisTMmtbaB")5Uc$=sq-.LO8k2R*4
+ m5!;RG:`Sp50co4%O4o=db)(sg9iHp$>Iapn5$l(IPO$2mE1^fk2la*r"uu3j$hq:^!3B7n
+ `Xlt4e74QAu!tDq,$..+,8H%bE/K57l)glFQV'0T&V_e9lomuU^$\mU/YoC2P;#Tkih6S@^
+ UZe1Vlg[9T7c:dFks at AU/9u:7WLD#B1MH?T4Yh<T)g[AN3=#<"*gVcMe5b&VGu'J$,t&3cM
+ )C6HomtN?<!V*#q5C>5?27ItC*24VR2<gUI&TIbrqiCNJ$pOsQ"oE\llkUnk&$ZICW*Gbn`
+ #@J2<[M5G]Ik0oK6FX[]Xo?mQ;hn&>kG8E;icD54R1[r-g(;1$#+4TY2_1A3GY5N3S9hc)<
+ cAt.W5-D**0`*aal8)r-\ZZHBJG.UViSb"P*fQ/@UBC"(Z;po7<mcl0~>
+Q
+0 g
+BT
+22 0 0 22 392.355518 400.130603 Tm
+/f-0-0 1 Tf
+[(R)44(ewrite/r)18(ecompile)]TJ
+3.138672 -1 Td
+[(script)]TJ
+ET
+Q q
+352 154.4 278.457 -71.371 re W n
+q
+352 154.4 279 -72 re W n
+[ 0.797873 0 0 0.793023 352 83.027923 ] concat
+/DeviceRGB setcolorspace
+8 dict dup begin
+  /ImageType 1 def
+  /Width 349 def
+  /Height 90 def
+  /Interpolate true def
+  /BitsPerComponent 8 def
+  /Decode [ 0 1 0 1 0 1 ] def
+  /DataSource currentfile /ASCII85Decode filter /FlateDecode filter def
+  /ImageMatrix [ 1 0 0 -1 0 90 ] def
+end
+image
+Gb"0WHVi1(^;ob.cYf(B'(-or,_Q.(KFgJ+J:Jnu,_U+KJKc9^+H)RYFg1OF[8[k$+sJL='Y
+ Js at B9`fP?E1.#Lg,r#0Qo"&AJhMXD67q$Nq5D08D!C5FUq[G(Wc>00E6,&'0gE--TD4D>Bl
+ `&HhR*rdmoH?rU@]8[r1$5HM)#S=4b9SQJK1=lftoqhHXAa;-$h&=[RXTgpjJfN'^`-DFE!
+ S/M0Dd='\j->?st#;cQh(=]np,Zald'r^^g?GB`ehCY*I]^4#bDh8bQu%hB27)8;(f^RaP5
+ '*\[H^]!l\[\H at 7r'+KW;;qF;(X/;4SsD2j0fE at 9d41Ed)Pon<To5H=12URc4/Ri?ZO#M5n
+ (Kl')IpWO-EsGjPG4t.`^EPK.]:5NU1:T.BrQpm\_6:M0E8\fY5Q:qRl>9B\T>fmb4'6.+\
+ h1dlT9=Y*!sKFq1$]89V7Z8]m*l"W[/ag>Pd=Tjbl(!/1N!t'Wj%faJ9LnoPZl79CY('G0#
+ J?0:nMq at Yb<`(NMNVZ"RmbDV^2H/UR4u\T27pBS_nhZq%-s@*A[t0r,-:ekf7BS3&fR6!hj
+ b`?1DI>.1tPD124mT3%=8<GcF)ZE\CBadt(1qmMbHeJ,bjj-EK]_X?]3 at q"!O[:>o(C<]lU
+ ]^h8kYd7g3=K!l[2&>I8XW1\kPc^l:/ui3lSBQbILeMMq`Hj;?ih]'U_1>9A\jGDCQSWEtN
+ ihC):<j8DSii]/$`5aDGjsYN`J_^ST1klK]P-`gcW2Ws>/+s%7IeSiD.5n at ioHc3&V8Dq5o
+ KO'3Ra]1;UkNaDo\BId:ORU8VLK:S#A_.b=RM9/_PmJ$sgsOg.?!n79lcuFJ)EOTN at B%2bG
+ 6ZHLkG+J+ON_B$\b=C2+m#M2)T`OrHQlAU&Z'fMu:NSt)=9Sjo/F]jZ>X7MQj\=HoA*GXqR
+ dL8qC>>>O^i4l<p>6L/gS,!otm9WK?.+X810W`d#S6+S4#:aG)-,TN,#l0N6`+,U'gOsLJt
+ 3_oDCpJZNK(`ja4GOOBIQS+Q*q]mT*DqUkq>KT-&<^gU;<!TjsSSG2'l:=9\8+YW`*o+5JI
+ RQPCBqD#G:1@@DI-"!NEXW_$;mtQ"Q-G1TV-1AGXj>E1B50VuY$@P2\MPUQ;. at J6f\i1F_$
+ M:E.=PMNa4\ehM=!jo3nhS%_].oVDd:%P%La%`_=S1m_83rdVqMLdkBaF:`G:@fO.2jP&fn
+ &,5M'*5h<@:&DOgOg^@M5\1UbT!;E6>-.Tor=,-+;!eY5".2)T?iX%AGJkGhIVS#6Eh,Y9o
+ XI94D_/;ir><cF5?c:Ulf8R/icBCF/h'!U_.BR^@%McQo-3e..qrVQ=<r0E!b$NgJ5c-:TI
+ Au#^b%XAr6OV7,W]X5u_gV5t&'RINIBAWeR!-h,X/&V[bM=^Xcq&`<]]*dT at ir%sE];:@P.
+ Y3#045J5R/on@@F0HF*0XJ+6%j*th1c.VZ`s^tS-+B7G[sAQ*g,CT\n)<C?2^Kk5aJWM/_S
+ Z%W(2.6,/JS9cT]EN>K?qJ`H?NS$O]ndI/X3S>I%A0#MuYfJK]C-p[,Ee)WCcX)bt\08I2%
+ .C@/@NuA>,]*RoU9g`H?tCoiEYko+E8-!o3?5fUX+\rSQN&GCZ<7bE$0%iRkb,p?msG+3*0
+ afGbfW"(U\9^ZE5hQZb@&Cp5=&IfdAEP*7P3l at b1<%P?&`cHFb(j(b]W;)U>`h7ijDUIUBD
+ ao],gO?`^+c0KLp>;XK!+id_'jJ>fM-AVIF9:1XT3GnSS!4MuXL7\rAk<_-l)nsCIY$<rM$
+ YRM:m[T-lbj:2EFS8,L2=%Ymb_!URK#9BQD[)G?+3tH[TB`sma'0P':6 at MknJP476ccS'FC
+ hBp(%q5W2f;lu0FOc,!dP70[T.#d'n0C(S_Q:U>bVn<e"t8g;n-K&9SNf>0XqpZc[dDFZl%
+ _'!h;f3p*;VOroo>/oW.ZgoGcKmE5VbRorq@")^D"0TQc,lCP#qg'IQi!N#MMF6-NdD>\IZ
+ &2)XLXPD/3sBn3*S9V>HrW)&qu>F(5U?H"uf1D!_*_NB5u'aM?Nd&MgY%CBp/PR]apZOSQR
+ n'9#l3$&/,U1'B$b!P(IJGZmOp13Vi'e`e:;@=Is\T[u?G+PinAZ2u1U;VGbTFI/YG`KoHO
+ +\'_K7oL;B5LQ</nBj5.LDPA@(-VLe8R`agf1a(cKX<)piJ\8Tm,m?X>(3\%*d2(AMU?O%a
+ Pkq8Fs"4nF@<1NR2YXf--5kkN,=bRV`hW]_,`GSq9t=j'U)t5YVmX:G\Sl%ZMG at 8.[Bli%"
+ n7*cJcQ6\lXf`YlthKbb0<^pXMN,DGrfbNZlI%DP0Eed3?abruM, at GV2C1I$OuXlj'9O[/;
+ )(0^?L9F%IcRW(7fXsCg5n`)jo&Yd_*n]!>+`PPJ(ll]Gm_$>Ej1PE.srk+?_P_F]#G)`)C
+ c'3pJ1hbE,gW9&=S.eRj\2GE#`$7[`DrT_R*1Vk>j'&CBJ9<UqoXgD4gl>OQ+<ZU84:B1dn
+ 2Y(]K7M<>(,"n2ZjsEm5sWNTlGt at 0Qj!m"69QPZ0Yo;J&.j./"O$oO!MQ*ORXePV+<X>NEY
+ 'o4(^+BS?53Ue!X8[.TRS$dbQ7tL=d7;:!OI;B5Sdi$6,5$Z&C?+)\j=+_?kCZfp1?V+/79
+ %9K_0VC0N#-;)!XOU(+=[u&c,5:^Bp82$j)kOhF\>5$Q'"'0tbIJ?ktF%BY8]X6,5$Z&CC2
+ 07R=g@?kC\01o<RS/79%9q!noHJ6BZ1T^h$4"Tbr[5sXT$*<uVOJ3cG4Nfkae9,;]*:QR+a
+ ViE57PeZGg]a at b*YiI?3rh^q4.b"[=1:'7ARuYjr:gO53bQ?mE3^U#:Gm>lS$f?p@&73N:H
+ A#ToGl]HM$YNq.5 at G53JBSSdgUGBX*7nX8O?'%_op>p,!\tj^miA`b=[;,%ntfh30FPsL:q
+ gqn!bMJ$(!6cA=hlR2o0N2Z0aj?PA3MC`2.clqJBS8[F2fb=(6J?bI)qZYbQ9OAPYW.&J6>
+ /"KC\PA(.OpMXbiDK1q"g)/S5$iJBS8[K>fBL(6J?bI&`P;bQ9OAP`HNbJ6>-LL%9q,(,--
+ ;Hr.OObeb<1_4U%D=[6mIjf>0sAc\Ug.,Uef^apVXK0d:(+S5`X2e[q"$cldS^-8lW=[3aY
+ o%f_EELR-fA/St[]f+"L2_Idg/EDSjX7cCkVC_(,KbcfkeO!=gHl3/ra8]<IABCtkctIi=J
+ .$\eeA2_+e:kdY at hu4Z#]%Ib(@i0 at .NSP0[KO$tA7<4o%`c@$=u\TAL.h'V3$?E:Pl\Q>dY
+ )KYZtl=7%GOGiV!rs!Ek8JU__4iFK.Nssr4$.\=?i-73GXhIpZ2fJW(_laBs:eHc-c$I)!D
+ gI8t:lno5Vc6+H&ScHDB)7DPRT:1si+Sr at 4`UK9amb.1ffVo<-[6njfu>a]u.`4]s+P[u1m
+ joQ%ZHjH:g!D,Bgb;FRf@!\-%2>n+E1E%i2ja1t9Kn^p,'d"O#BVZsg@&d35M32VF2'f8<E
+ W</C\s#j/&.`K#!`QOCMe,mZuY$HRiSYmu4BkCM(N=,2tTndm!U]&tXI%2sfbgfR\",U at Ak
+ PE*:_,)+\X;q&1p-llM(cW at B]Mfp\ECc(<Qe%:?6 at B!$:P)RI0OJo`95l:NYYN0ZPVJp9p-
+ J+g0oP#LA7If+\9[[8I=4h[2U]Ks0)&sQp2QS]jch$6?6$tfeaY8h$\-;8_dWqRQGR9#:b%
+ 5p$E-cd'gcSUaBlr,4q311&h"GWaRR!3`imk_MSe$q''F3t,J]j&AD)4=1/sAC1.H?+_X6+
+ 8mFeg%:8_\a]dFOK-i(9+HJ"AW:;36$*6$THi.!Q=oBpE:OuQS)8'X?gEIcFlK[AqE]o_3#
+ kR7!8pN!pMV"7e'Gbn9-HoXhQFB!3mriW]$0%M"DCOM/IZ*B<_P1hHLH1HX$L?$;bAY`(44
+ 59UPliXa-JaR^?!rE\:o0NV-K?@;Ndj]le1Bma1hY6So5NV_?SF?>J!CH#MpN(m=R1'rCRE
+ p at o$HSJ*)u-6ZcA)aMR[=u7\!OC665GPjDoH;9;j641S"'9OqoCH?behi,:[d)Le(/[fDg&
+ !"hj*@u'=.$(h!$RP6fi0W/n$AoZdqNbC=KmC"7K&!^F`T-.`K"U7>MKn,r->n*&=/B#%!:
+ D7h4M=+5 at 82;seETB/>4d<aJP0DK]&)%qbNooYZFp$k3Z. at 8`JHiSib-GOM+bf=c at pEeW$#
+ ec&?l-H!mScHk$Ac=*XSp.<!DfeV-1&/Me]Xc28@;fR[p]F?>S6>2V)ACd`)A3ONl$c?(W:
+ h3U;>RCtYQYGLA@*>saG,&3``M+YO(3XnGP(0IQ0WE3HW=2#jpg`d;RuMQ58b)=5-Q81Wj5
+ iW%EMAXPaB4C?*^_N`2[CGGSK_A)S0;BS)6j`>UW+Rs+nJ9f3#d5caWVgjcQMBR;\OD92Jt
+ ER4;W=&;HZq)rn!a5LCYJ)fED!4ViL`Sr>cn+8Z=$?8mH%1Y&nGT4'QVM:#ob8 at FF4Q=r<#
+ 1c8U2(;$))b\NgG6(,?jbT1H\E(nW-be&\VDN`M`HefJpK(@;X8%-o%@W3ELVg`ZIiW;L&^
+ Go"IQL=GHgDf9\q6[ing3Q\MlXdHOt>e<4H3n]BqCjfGC.>JN!7[NZ3K=Q.2Tf3NR\BtE6l
+ "!UWVN$@`22C],(Rg=6j1PGd=8%UF`k#@&;1[F?`/A1Lf,=.Ba9s5(#aGUMfM"3 at g7;ZsEN
+ nHV^F+!/,(qKd?R)!mMh)Fc*AfMniQ.&#TX^"?A6`YS?ET<!DV814- at C7+'"&f>r_"##hl/
+ GtTrG#"mIH=9V^=n`j<S2DJX_^UP8DtNki!`ZE"T>qrHKq#U";Vc6fpa*7&E?V7:o!.V,GC
+ `OqYsmaQU_;"pP9*s'<G\Z2cPBiVrfQ]tM,8SXiIa%2C2./!^ppS!u3\7XEYXeCi;L1T)NC
+ K\dO`O`<uLd`JT3\B)V^2)LE*OjT<UOTCogp#3m1<!Lh7%-6'ff at SX'drYNTfoD)Vm3dp:S
+ 2f)Cpb5%uG9Ts@%]\P7)&G:VOJ.fIOjTTb%VF5odpm](UfX?qNupS509m61>]p<@T##u/rk
+ :RLcl3oDq"5f:,3'j\,=?g,89ha at pg::LqLA~>
+Q
+0 g
+BT
+22 0 0 22 442.893213 123.332434 Tm
+/f-0-0 1 Tf
+[(Unde)]TJ
+/f-0-1 1 Tf
+[<01>]TJ
+/f-0-0 1 Tf
+[(n)-3(e)]TJ
+-2.75 -1 Td
+[(\\MGL@@@<sc)-3(ript>)]TJ
+ET
+Q q
+0 154.4 278.457 -71.371 re W n
+q
+0 154.4 279 -72 re W n
+[ 0.797873 0 0 0.793023 0 83.027923 ] concat
+/DeviceRGB setcolorspace
+8 dict dup begin
+  /ImageType 1 def
+  /Width 349 def
+  /Height 90 def
+  /Interpolate true def
+  /BitsPerComponent 8 def
+  /Decode [ 0 1 0 1 0 1 ] def
+  /DataSource currentfile /ASCII85Decode filter /FlateDecode filter def
+  /ImageMatrix [ 1 0 0 -1 0 90 ] def
+end
+image
+Gb"0VHVfoM^;ob.c^l11+iFAk&OHbb&?[/Z&-NV:84!B6J06BE,(fR#U/gNf=qlm8&J,YA'j
+ S]ce4R-+Gf*1NX]g&ka.phO/E=!XeRQ34O39N?rIqVLmV\qs7A#A)IHL4;NtX`rJ%snI0F#
+ k0B@!/5IJVcDhgP+ at 2n*\\\pX<o:J]<QIJ\3Tg:hE. at srcJ:!KR#lKTt/[5A[6%3%2J6r.#
+ :/*Wq6ZEdp1jr2EA=^><9?XLEdB6388rMND]\pF$aIt.L3HhYVRL51Q+%*)i%A+TWNKKFDG
+ >e>0]ld2>[R[WtO/R(&M:<DjjGrZ`[e'+d_#%Ktd;I[:9X#?uQa-Il$b2t"i:4E-MZ-bI*+
+ $99UHdOcO7n4oE7Hrglo]iqsK1<&&bFE/s.erE-eLR,YRQg0)\pjVSh7IkQ5CQ:u1-?M$8.
+ u13#0rf'97ftuDbbb!f%e.?-$)^[QRu>:f&H?QQY^nnBfY_Ode2_FX==fK^Z`_CPcqK2LQ%
+ $_BjO*6G"S-,/.2'6,oa7-<\A=J]t:JOcWUP=*iZ;o,n&dF8/'(HTq\9/<^H0OU;FC*/?W*
+ g at WTMWm8`Iqel9$,DJ6/%^U:dbGC at H%-A9_RBWZcF%&_Y8I57W>ea(>Y2Qp>[O,N/)S3uDD
+ U;E<m:%dT0:<N(eaV2h'?qo+&#7iFl\?L/DlEiCsS#)tI<gV@>?b<_WHrbuIRQ;uO7[9YWS
+ $!3mR1_S7gTW(RBmuA1.eBMVk[SM-*rW1gN'phu8_6gQp/L]Yo9<KYoF1]ZPUSmZV-d]!9H
+ ,%KMcQeSV-N3`OF)6f']c^1[G893j5In2j at 2p^)6?>^YJ0ku%m+rF:RdYbe<;6/D-3EoP\?
+ X$[VF+3c>?QO>&&D-D`RX6`npEdEsK,d(D&p.AmGk6%iGtId[lnOQ5+#s<InT8m_L)u0;%R
+ Ipbu37Ip(IAmd?j&K7fC1(l!g$a\h$'^:m>'mtM"f9+/&k2m1?RC%>/EqjTJbDeo:3K9i"_
+ m=.<@nBf1\/W6q#k,3-#0YM at AHK2N`:m*`Qe^'Y at lAAMI^Zsh.NO-jpoCZm>[.!'h=(^\4V
+ Ss7=@PZu.g(81VL_IRJ'=oq^fT'-XFDGsXoe4'*#6kOA@/U,ESND%AHB'R`4Pu at K?2hGrfk
+ ,ASR/Gn9Wj;r!DkHB at ErFLq^"!@Rj_ZN(YKKnqV(8"3LG`XuD*pP?R\dB::")JWbLnX6Zlr
+ @FRhf7Cnp`#ap:FGa_?eQ=!&q=;U^.Q2.:rg1](lWaDN8XgqTDpA>2%_Xk5P>V'`LXTr4:t
+ !1,Lh0i5"4IhbG!ZS7cH$@tT0PAktXrGO+p3Hg[Cf!71W`huUVl9&:+$Hu/!aJtk1>=(KgX
+ .d!c7RJn1cKGEe?j=b&dq31T;lt)cYr4K,VcM_tUhPK`-"`"nQoVYn6*UW*j8KM,L_j$5cV
+ =a`JV6eEDZX`*FF`.<Y5:,cQ%mIGth!5j1:q0Bg\PUC at pN)<00n]6r5oqYM/ri7W7RjDg]t
+ J9%E.Gg/(TdXAiV)[=C2%D1a2`M:4)6&C[,LSDL.FZ3G?-^'d(CVr?47p'7e&TfonLL$3HB
+ TZk:.RV2XF-RQcBAiPoRK%XV<N)6C&.C+lq>r[Hc>ok5PA7NugHY.LY>:6F(Rj`g=rpp%nG
+ 3El$-OI15**PXo/%pN\R;]d#`Ci%i*Wn@'Xh>6`.1^o:5q/VWemE:K4(:gtZpc`n)FMUAVJ
+ [MVaR_iZ/,."ok--OW7f1VC0]78"s8dK<c&MjY_0c8*,/(RM+X;/P4IE;fX"A=+(&(*5\hI
+ ,i6>VP`(c(mW>$`=V1$)BG1nk at Xs>hMr0hcW at rT&&SA5JYT'G2\ch"^dh>^fMq(+#!EXGM)
+ 9m7?MDrVE\mq0Vnda;lnUkl)Vtn5RH&]<=n6I#0NZ)IPH^9<AcU^km-7,Rf[*G`P:VgEJiY
+ YH^sb^ki_>F?#!"V<_-=)TSX^8tD'e[[$+-.p/HInSE't5Wol.bR-c_8h"%#sJQ3\QY_Efc
+ \`^<`?X9c@$9D3 at o:SgOFYN.!#fO5iH!Ue5G/q_BP]"3JW=jTYfr.Q\EOCrTeO3sRuUuZAb
+ &G>2,To&sr*HigH!?HQh\#eqt$-nss_K^#`#pJU,-<]=nb-54\>Gf4$OPs*j\P/W!SZ#X:c
+ q2pL*g79^Q8b.m8BWPtK#QkCDhHiI8B%X[M_E<`+BK`=RqXn_Hn]S3+ at 5cJ)>]NT1OArJN"
+ B9"1gA,LD1Ko"fG4j16=?Cd02(#t':5X#H7:q=p/sqCoM1R]'h8PpN8i.k!hauf$O=r'AVA
+ MW:&$7S/uQQd]"4&V&A<I[@O]3o,WKUjm3E(5YX!Y_L9sf2Sf9DUZ;;/WBJ>=I=L54b'0=B
+ WAE<SPc3`&K>bd]?;@oS%cVrbb),;-E9+O*oiOr&i,elB-\eVQ%5sQ)!\^c.<qE>::^ark)
+ d):)bf`JL15sXXl++f#G^`Xcl`BOP-Z[b>,'A:.O!4.2A5SM^%"9GiZ5sQ+.F+]!G^`&l&A
+ !B9p/79%97.<N/^ark)ODT?$+CGs=#fp&[F:^,6(^+ArIUs'E$Q'"W9?&4_Qj!m"Z41:\"P
+ _3gL[!E&Jb%,*U$!?c+CGs=#\a-^77"^??kC\0oLaad=hl/Qn`;V2!OI;B5i]h!$Napko$8
+ 5JkBbB=R)iF'r3JlV\L7d$"O$r/+#H<Z6"(<O<#2W5rBVYb)O(J8Jn3i'g%(cl at hoX#;4`@
+ GP(er*E$bmtJ7sr5!alcTU(>DU5KYOa`*a>lHK?P^4_=`$JEVXV]jhg3$]$tp?TMd"Z[h7l
+ nr7,p0FN\#-snoF!OI=?KCW;X(,-,P4t'bpAc]5gk_&FX at hpa+Ld!4o0kLHmJEVXVrF-Ok/
+ dpqe:Wrm7!9MDC/795)I8IX\bQ;AWd0JcK`@PC4&5>tb;To2S!RV/6o>E1f((bmj5"s0%Ac
+ ^9ajccJBbQ:+3P`Lqj0FJ.`5!uot/>.iYnc@/PAcYV"PY[@c0FMQgTmUtSLKQkU#N^"G0/*
+ cI,+s<sisTH"ff$u#2BH9BOA2Hs=lUE4!SJ=42e<(F$clpV^*]=X.p49\&C_T:T3JY+2\Q[
+ gi335W-,E#+I%'VS)3Cu3S;bHc?SYk?_+>l!W.uBJYf;i[b;5rRj"1X-.UK5`Htd0mC`^^8
+ 4qeo.KPgnaNg/L#MBrbRp at KZ+Yt(7%ed0=hd%Q)(P(aHL+R at 462X84,Wc=,Sp^jX)0JC,3C
+ QXdh.7&&>7h/O2BM4+=,OF%!d7!19\OuL_iOmjl#@oX3+'nLgS/Z1Z#sB9U_7g%cLkaG'cU
+ qd314AG0U>h:dK[VddnPKXmJ/RN'1+L8"1:K at LDaT-?Ge+TT7mTin2!^el*]g^u;'Hu9=H3
+ id&#YL`32oEO&.&Cu-ZnUG,6;t%?rI1Z$iJm+l1&kf8r]cGa\.`"_`XHAKe*OsTr(s.$ulk
+ g=%9!hHbA,s_1t/uR.L27iVjP[r^)*:*X:pS/X7QqWHKj59SC\ZbFJ]oG9?%qld.A,:=pEl
+ eIh<J@$i>-c]`IH9%Ia1\I)*%KGEe?'YnqdFE*sR(3]+^2!JL=Xph-;-d%btlg9l#n%*&8T
+ M[ARO<sk6fH6C^_E/pF/eg3u5ufnoKYqEo.b1P\mAO&OV%Uocn9,p*p3TX"F!4K;C_SI\(8
+ M2H7Z3[#mS6ZOK,9lRM,A-IhEZiI$k2dshS$gCeF?i2JgHq+?[efK1V)rg.ll^2_EXL-T4W
+ H+/+=jAK/_mg(')O1/63mH7Yg>a%#<&>Y4OB$5+cDCpEb_Ij+PBDSl*X2#oNbK7kZfJ+kPS
+ L<O]Cpp\3RB2 at E<P4<[ieI(3ZU``0[1K:e5?/7OCE4%DqGl2Ign<ItYu9,UL%9<RAK#4m9B
+ ;C)4LaR?=OIfEK$&:2(*QM?TaOPu;sr+E0c9PL\%>cA;f<XCP[3AFuD0TRC;3sf&5*ZV):<
+ -*D5gYgui)((&?Gl%'sf3a$`eb)4*6*=J:-2.\EJ0fD`;@&X.+')DbB>0Q'DN(eC6.BKZFe
+ jo,dNll^I86S2&ON6\-:<MTk-N5VC=%gY+e8Ia4!TiNi58G"Qr7!ID\kpXZ^o=(PFn&hft%
+ .Nh7I3b'P:cuGkg./HY:Zr?F+7?.QG5gq$f'6.HRhq>XtWPWKFD_rESq/]_N.%EY!IX::O=
+ L/D#\9BZ(1M;'M3,WtCKiO:a(7bTh`aZQeF-$(65^#9PkA_qCX-YZL\Eb/tKk5(/%\9hg at 6
+ <>MZIGkC4Ibo8TFS"!@$As!IR_fYD,0R[5s8/W+(B!dA^+CU\6CiZGp$?hu6i8e&1&43/3+
+ i>Jp8Ioo#q6A$b+\'[$k6039mn&N`[KGF':?:Q5<N@(=WkPu`jl++4'K,u at pssG(E3QtO-n
+ //@8>$p>NpC4/@53-h%%3T5+GZX)0I@/Fd:1;f,u2<$QOAJn$R*D2o8+'c-Ar`K!JATgb-m
+ MD3d<^=o,,7$1 at 7I-AW%=hO;l-R!0pnBr0RY.M]m5SFn93l>>+Lf4E?VDZ0XH1Frns/mcEF
+ VF*%!60nP,'&AF>p`);Fo at 33]"TbeG1n=@XbaIo=K#L?!86KW4A(_0g5)aRBjr1'k>k!nZ6
+ J_D']:Wl#+1ZXhBMifb_"p`6Q*!+OFSS9aIAEUdT6fL_\Agc\#pfT<KGYEe;MdVYB84Rhk#
+ 3E[E+QFXZoB*@#h"(%f9t5<8,.1c9r_jT65H2#UTrkG.c-#/$)/1fT-&J#(K^\6ki[nP24l
+ -$!h.-Sq>i^VNH6HfYA3ONlA4gB/A6*5G)O3'6/VVE.N/gSMBP>K`cP>Z*"o(Y,mbbd/oB+
+ <H-Vh%VZrC+kY?J2QDJ<NF:0(\E7R;2em^*[]cq>T.Z:l\pMp.';MbIq_9+..,)',+d)'Bs
+ &%mPKDA[$X05`Q9U!s;W->j4CmVRu`ha%&>[54W,`B.$%0=!CSK%''1Q)&G:VOJ.fIOjR>#
+ %^]u&os)4GknU2Kj2[5&X-/'sbKeJUF(]0"E*rYho[<.9IK,C3O`?M?OeM_u8/U).r#MrbO
+ M(~>
+Q
+0 g
+BT
+22 0 0 22 104.449866 123.332434 Tm
+/f-0-0 1 Tf
+(De)Tj
+/f-0-1 1 Tf
+<01>Tj
+/f-0-0 1 Tf
+[(ne)]TJ
+-3.366211 -1 Td
+[(\\MGL@@@<sc)-3(ript>)]TJ
+ET
+Q q
+268.801 38.4 96 -38.398 re W n
+q
+268 38.4 97 -39 re W n
+[ 0.793388 0 0 0.799999 268.8 0.0000473848 ] concat
+/DeviceRGB setcolorspace
+8 dict dup begin
+  /ImageType 1 def
+  /Width 121 def
+  /Height 48 def
+  /Interpolate true def
+  /BitsPerComponent 8 def
+  /Decode [ 0 1 0 1 0 1 ] def
+  /DataSource currentfile /ASCII85Decode filter /FlateDecode filter def
+  /ImageMatrix [ 1 0 0 -1 0 48 ] def
+end
+image
+Gb"/kM-!XM[`AE!(7?q5&2KH&O?b/45_(O<&-7nbN5-)pMMN$9d8E5\MJ*a0%`fb]'GOE&W!
+ M,BeQU#I3k[^aT@`7F45F4)gpVFAI<%$<MTT[P?a6'-(Q68T8bW.RID1'sht\8mT(;aBVk:
+ ^'rqin6rqc'=]B at J0g"kJlZ>sYFIeK:71J3PqX-P;=?*eWID0]SmJ3bL2\[-BEL/u7bEH__
+ PEXad*UOjHQbn!bC,LiGi5?XMkI"L!]+*Wp8!$*<?$heNI&A.-PCc&8EmOb7!V&Z76*bOo%
+ O#6WWb9T2NCq+K$r4-%$efGhmoZ?dlp[6kLJ,__'GoFP>]kj3Wgpln2dA(OtS'&m2EmrJR(
+ ?O)4Q`R<kBPj]M/";k:Wh&.QN:l_2*hpi81X8dg]IY_<IUUOUnq+<=ZHe29SSOPYCL0$J^1
+ RDrqVPcW+oa/^QWiZHhd4"'UV=BPH"kP$=f!q7M_jA`&jiK7<7*c$E0WE,>9'XY-(4[0,=@
+ E9V3j^A;@$n^,h1=Cm+o)0_O33hDVZLNs$kolkHDVrlIrX]!sA"nXK7qUSPbW<[:8[C`nH<
+ YF`kl#k9^CKV?Uh9?C?)3A_iKWF[nN_:3LP<[sQ<o^?1?%/XP=.ql%7Mm;d^Rec,7m#I[>T
+ ]4uJIoFP:sLXBs\*^d_.3bfJW9oMaPe].A6N(UosK6Nh_mk&\tZ^`7mrT;AHC>HDie>^4<^
+ 3pr7s7!o:^R@(&q=Doss6.=Rmd at 6XW[2^;)6YWZ]6a;$Q;ofsf!!;T$_9LlCB'SW_qWb7lI
+ g9i^Z2N842*]%HYgUc?0,4KZ_tHu&R(MB>a&nfX%^lAR'kHN^/\*[ITNR,lc3]SESBt4?>*
+ !l2-&-'nE6M_YL7)aEJ.e=LrV%)Wd0eNAZ=W?<V'u611u@=`VD%%<5L>[/D/EWaE$j6nZpT
+ +2f2_W1c0ICk0;dM)iqj`7aAV-gIk-GZI>^QPq?*Fp\M=@Fh,tq(Kut,>1XhM^>Yj#m<=W[
+ \UUpZCeN<PlF_]=[))=?A$;_YY^GSgof4*ni at jF3C,=2MSpIt1q<Vmrk:4o/=2V3YVkH>)=
+ d1UB'\-Q()D6pi/rf=j'=*$e5Z<hID3Uj5,Ua/`jncN"l+(MS_/u5-0.nY1=CY6dJeYit&&
+ -8Q-?WlFa2Y2a[Gois^s,Y>rH5]2LS-h<^3mJtZ[M8sCeICKMXlo^p!p0[=6(Ytm;H9_f,$
+ dQi^D[h*H.P,\E(!a3k0G at i4E?9:++oaDp\CX[F_>D9%Po>8ZKZ&o)i61Bj?f8bW#dHXHu?
+ @KLR7 at fNYH<dR>]Z6;.O1*ZQ0(l1Xne$/^\s?leV%hHj$?SN&X8\pWJfL)&eRRDg'+6g\[H
+ hmN90O6udS:XdRkHMH_3^d!=`YlDer<sPG,n5M\M]3/;Rc7enSAu_9h*jcb1a6Y<6.0Y80Y
+ (mBRj>'(!kg?(cGOBkUmC2,O9hI89FTVaCQRnPC%.M)\7aCU;`9/Me*,\u)IUChgBDPE;<W
+ 9nPo`.3?k$r90g]]Y<IrBbf^2!K(mE;VAgT<s?IM]e"J9(^8OUf5eqr'lj^YVM1f:m/>'j$
+ -1o6iVj8nPSl&Y\,#jZGbOQ92uMl9^s]2gP#W`m^h]IIY8m#]Mo5nNBt]:RsIB[<Q[ZW1e6
+ /1$V4o7U1C_b`T@,=So8hDL-g*!r0g(7h5JN\@3&F/qDnc(s7CSZf%BRkY$;hCekZPAAF=D
+ fUi1m1Z7123*$C<f"plkBUsRXfXO"/<$/rooM5!e7_7'cgg+l<:^a42g*BH;-Ym<t7s"9eO
+ $CW&pJfY<FBlM,\TL8LguRtXR425CQPJW+2OcCmOn8SKihNof!Ug!Y\:44GPeami$$K*qSg
+ `5+%_Yp/MhKqXio^G'dRhl"FFIj*m#6Of39WqahK7C[JaM.;P^Kr:hk)0.MW0m(EAH#Hm9h
+ Xn:r;oA1>JgOIbsXiH$KYhn%fY4jMW)k*Q?"n>.Jb*ntjuW=Q2YET.fVJCWoT<Sf\J^IFLR
+ ?_:<9E'DBA\mO5ruI?AIk&e7CJ at FCkV4#5cSoTSqCTJ_CN<q8BcclER$EU`[$kX^?6jtDYb
+ _l9q9;$*PQ\K*;t"\Ipl;RV`]'s\gSNI_NJ25H0nU%]eDNfQC%YiW!r-AMg(7quN)lC.(Xa
+ I]8DXFoj$-E]u5J]$eD*H<,q(W3sT!]!=a]cE,f at odqpo$;Jg_V8aB8cORJn4DaJHtNlSQj
+ PED@<orGo5mL"]/N1k8s6!GLPRBF&uL_W-)'(oKUcjOqVGMiDLD#s'C$g6"\e05#N&[oYWs
+ XW`HcEBJYaK+b42XD[P+8fCl3OX at GK2trh]c%/AtPCV]Pds at eG_VHBPYf&UXNq0q6(Vs!7V
+ QCX+$+ApC3[[RNM\"B:05a]8!]&\<s%1/?+'&lANqCm?N1:U;kPH/[Cn9C0]uoYh1Sg,<f(
+ 2&Tp%[2\C;RhhaQ;I.__C?`Abfu?u3I!>G'gP86XpOs9IgWtt`5(E("0G;)/3/6+!V;2aj)
+ ks#gn at D'&dk&A-"?XC)&N)gEo+<`'9RDI4.m#Nj(&QH!2o\g5jT!nGT=oa6`3PO=V,38GOY
+ eZ<ODN>eDL6G"YX`u;kj4JN#Of>1LN5lTRH0>+fEe,J':FjUM$LE0ghr.*<?Y2;4I%,H&gJ
+ gqk9S.5"sF.IHb.TM%/X^*i9&&!9,B7Afnpne*-V2TH?6AIjBPl.<^sa<HhFF\.kTmg+1HC
+ _1-"-$IH,gpn6G/qMt8#ck4\uW&FBr at 1`E&]F!k2#2aOgf`3lPs;'N#)O005E"jV:;)'<(F
+ TqOi@]anf_W?*-g]!S6Gh&I<s-0=5`O%hCo>H:CPr?]F6gtio0JD4,QX'qnD]#3KtkC`B$Z
+ r+:er%1C:$c'\EP9qFdgFQtUp_6+JA_Q2BQoQa,n#d[lC']tm%6o(!bhA=4rDcIR^H+*ncO
+ po$@!]=ObGbp3]g(*Kn0.^N%h)t\.G\WR2Vtcto:MV\NA_!!+_-f(ZR5C8"t9$<T5<3K"@7
+ a((i#!2B0FRDj[p+Id#`$EXus'@JuJ.o]D(a*8!bc0i$i\<1'L,DGSDLDV"mZ)FY7I("EuB
+ @E4653HPJT>&Ei]$W0I;!+oK+.6]&Lm!#=5VkK&BU,Rl),NgA$'5<#$c:D6Um"#R<`Wl8Kj
+ 1)`#1\b,Xbc-*MN=AH-;\o;S-DJ[Bn'l0D5CMTFChTCHMg]2aY@='gc=?URO9q!Z=%pL26#
+ =FI\$5M_Z#Rr6Tj\1fbrS/e>2i<E+k9Y;"<3F=dn^bsSfQa;@-ZeO9U at e"1NHf'FDQ8SF1J
+ r at j41+.dknV-m]$i^B*-qN]RPZe)0mnZ$&IPQ@@%l1pMmP:#(`pp/HD&%kZWbA9jM>KTb02
+ uXJ,d2DGALb6rdo2#:,fjJG at i,?$XB3rr"\0/EK\'n<Q-FHEq^nPTHOVbAAaEq at WB1a&>-"
+ f*fV)U7gNBI=Q9pgW`rWSh.?\>8ld^"7*\sg<Q98db,<HUSVGgU3GbaTL`5Gr'_!+`*JlM5
+ !iD_i/W.qJ at Pr%;C1]m_G9B<aWtV0a"ZiNr%]`Fdgj8P%7/_[ZQ98cECIGGI(Wo^,bE68WL
+ S0IG.!#%?;`n;3H12ZMk1EsF?.ah_-?O:mj8.<,XW'4=L5579%Y75LUeVo),SmS`9t\BC10
+ B7js)dI`,Kdj=(T=GF2PO=>%u\*7S1Vc)*C1i$7'5KJA1gXF*%I]NBPr85odA at pDqhQD4u,
+ gIE!Z#tKR*/6j at g3Z5dCMB, at 7#a-Yb6Zq$F")pI!FngUAQN`pd[8INGYc$?!?Y"0W!C0(pT
+ K at 8S.(-b^.R0a)$Lnf\%Mf(o[SK"p>QqKdI":/Ag6W0afB4l&eP-L*^n4_js\$FR*U12Met
+ cHmA=EMP./(nk7H--D"cU<]#JV8"j!=X9J"lq%]Rh.rE5K?nSfMjT&&DO?Ao<mn7._+s,^N
+ WL\_?pbd9f^bci,FcBt+K3i-Hr!tQQ_:]DH`g+A]%rauSo%XN*#t>IR-Q23/%APC1!:tR:Q
+ a,21WTLmr![cto785%F@<bY at 7E_R/O<4t"U4Ih7i48BQg:SkFV7X?[#\@06K\%ZS0Ds=o^d
+ 5Bdi<HrL-`n<P#?;VCl%$.m.mhO-+jfm>>6aTF!COb:fsKJ`QIZ?U^3k^Jf)]VUf8EpMN[!
+ JH2M&F2Bc-crciKo at oQid)g.;[NufEUKSV&p=;au='*Ng0QGI#^X:9ikOQUr#l*,<@WPnip
+ )CSX6MF*jV>%SbRM&J;X3RaS4aZ/F''3Q2m?pkmYS2QAQFRXCKpgS4Wd``&1O[#N_B at 8'pM
+ C0tLJ`a3"H4^komgb!CI]uM&l=!mbNKZ.#H-U.uBtBk&6[d`6WpMDIC'uMM:<F5ImF=>!5E
+ ?^/U0?(5=qc+0K'3[kG,[F*G_h44qb%h&'@VDDYo3^_%Yb^5.$A*/0lh%pb;Mqj>-=WuMZ]
+ []</F7T/KFB5!'JmBH0O<W9`&KjTTEc`jO&B%9S8Fi+K$#['DkadoVX])=R&W)rnBbgE?jW
+ ,TD+)la^<nVBa]YV%?u/;QmY%.9kf8j<`$'qnAa=;m:]E/KSd#4kRB2Nj[0J;\:7:tAr=Hb
+ -"5MCGuS.BF+f@<WFf1cEdQ$)X-lj6<'Z/+(mL-Uo6)&h3NprJ&l4`%7+(Va2QfV>eajbD=
+ :Psu]sighjP.2QHSJVZ)]EH"IU3*P,S*s(Xal:c*N*<-qf8nU_$Le`!B--<V&?!*eBJ<GSi
+ p\,JrOiFihf/%-lPdlHp+Jd'iiuB`CWD*(UG)KKCkp_h)ri*o[nu=1#%lZ-00krPJ#^"5!g
+ WuX[u-L&T2(mD_P=7)emXiJ7W'6TSI+]lngk:bK[A)O)DMEeo$[9]V-Z4UI6>[OY&L!3jHW
+ al9M:)`Eju3flAlp*Zl'gkeos,Ogn6C)3`Q4B7GK=8P6sN#%sZ)0`q7s,.CqLJ2.khl%jA=
+ UD!\N at jBZZ]k#H>7?4X8$m at P7^mdNlg`&ilh>#LBfs["OHYHiY,PKRRoTufP)!=@DRpt9gI
+ 2f!e>EJoF6=c>n+$RrqbpbtGbtp24"`^!*GhA*_c'2UM+N3=u'euFl9><1][K]'R't\=<jK
+ l-Td^D(In[8Z8JSah."t]k$W@,.$)!k7\"EhVj4d+aI[8,^tHdl9<7;e/SJE,>W9=?%sHZq
+ ;*'/Cco&pMJXp0'*BIa1J':F0=,W7sIIlq&II2*nqr(3m\?,uH:]CS5!,#Rb5GAin_$B>i0
+ I7UI?J<p9laY#Z2C=\:r6Hmsf,_.(Ip%lXCG.#gKJY(QP5QtD,H&/RZ#FCR3M:R7-fRi>;N
+ Z"cI,m/3$Eb9RPB2-ad1+AoVQ8n.>0<X0SedqOK,I"N;CTR\3i]]og".RI>n)4iiU[nDsic
+ l,H+!p=G0%HeE6'8*DDE=7T)lu[o2.'OD3Y[/)Blob)["GOA2T0N3Pl$-/smbG?om+=!A:L
+ ["n-_Di\]Hh.El.d[89iq\*lsc/WjNh+?ih6mpc(^nBadES%Fc5lmNqDeHV;KL_rg5A;=$G
+ b/Sq78e<`d]-De at 2-S5"ZeJRCH).2!$u"2ln8#;e,R$m-X+XSIgFAUGgK6;WIGToJZ+J^Lj
+ 0J>22=2fu!qVSYrp9mj%#K=@>6NphK=4#W:7"W[go*(uV9\b-OsXI,Pjd at LIQ$JJmNk\,k7
+ h)*7D'ZomP$#`jGdG[GaKGs;S&7H[u%L.W\@=T1A#)a]q+L/,i*r?DrB+^-EB9G'rL:;*Y*
+ rgjHO/%[VKbk$;&W/fupaT>m294CjeS,/rS=\k3cdB&gikg"=@H:IYG]-">lD&S5;7nb5hO
+ :ALD^N>$F;Wh'k:m)J"N/'K0JnHA%2],6j64H/VJg[5*MUp'KSTfj+JQK_Q8:W7mJHYHhn"
+ (H0+AVi>YBCI7cr!i8gsD#hOY"CM_1b=2XmCaB.O]pjR`R$4]tA3Pg%X_/QubPQCUC3IKH"
+ h_^qk+kVbJ_+^cE0%L.W\@=VOA,?@&?CGNM#lk';n5TkjdiK0RZircjQ/eP`QYY&AMI<Akf
+ 3BRFW:Rq'rF@&d-V=`b.C>9g$>^Kh\,G'4GZ;@T1]/!jD$#^>Z,sB9[0G"WtK>Pu7ed2L'j
+ 4oWFA,$<1;=*T5_E(4O5keJBgLudCJff7%i^IZ%)ckPNVPbA\]MPKpHZ;G?8\p:@WhONR_R
+ c`. at B8XcjUb2`\2id.*4/uJ$#Vf)X6;7r[]>&#`C\6q<jIS87)jNj"-cVP+Cj=H5!hLKf[n
+ dtSbkAFrrf-W+,faQM;dF&Rl;s*Z7mLXhI!&I&?nPRHS3328=P:q?-.*;$L$RNWR18#3]EM
+ !9D at O&-]%T.0cjse32!`!+[bG4d-tbfg(De/5dfXWlpPXpKoh;1@`TBGL5ulW`V:NP,[^QV
+ R><1P~>
+Q
+0 g
+BT
+22 0 0 22 295.822559 11.771399 Tm
+/f-0-0 1 Tf
+[(End)]TJ
+ET
+Q q
+243.199 325.599 147.57 -135.715 re W n
+q
+243 326.4 148 -137 re W n
+[ 0.797682 0 0 0.798319 243.2 189.885823 ] concat
+/DeviceRGB setcolorspace
+8 dict dup begin
+  /ImageType 1 def
+  /Width 185 def
+  /Height 170 def
+  /Interpolate true def
+  /BitsPerComponent 8 def
+  /Decode [ 0 1 0 1 0 1 ] def
+  /DataSource currentfile /ASCII85Decode filter /FlateDecode filter def
+  /ImageMatrix [ 1 0 0 -1 0 170 ] def
+end
+image
+Gb"0WLK>0kqZlWji0Qio?C/+D/laq`779Bi/i<o4`'R<(722#)"A;&d)i6^HeAMUu#Un>jB(
+ $WW;.$q#<:p1Xbj6rdAnG+4G(FqaS/b=bk2jj8Ep(!jHg_ at C<)H(!<E)ga'ie417Fc(P:S0
+ hmqF at 2NId7YN+$P'ss8IFrIm<i]r:S*k+5sCP3E0Dj4^^V5]RJ\ce+<;#gF#dg]R9PGc'pZ
+ ]YC1hIn(ta1?tB4G;C1 at T,6gQagY7&cXZO"0SNCuZdY/(L>$B4A3d(2B*I,8Doa6;%^C;--
+ AGm`O-%gg0#ok\2+$I2]q=:MK-[spbC!Z4<4+GqRZXW0bo($X%2K'uoCi)2\e_+s0nmsfCo
+ _.oR>/jr9-ia/>hjlj<45/$2f2f(WZ=m\%gf`U0:0(u@;d at t@`Zb?<ZY,$<Mi$<iF(O1DK5
+ e3nhrDaqhn477mN&-8lkJUCp<=PS:E8-\gWfum0nJ1&!M6I&`Wh`&RO(mfTqb<5<\i*"FLA
+ @ZR-$,Mk4cK3lo<SGoVB*gdP>tQ3dL8nq5ru7:E2N\ZZ=`hLgY]cQ]._cM,>En*"O,];eHJ
+ *>9dtmRNbE'4(F7iQA/T2Fr$dc?Bl6?c#n/1cC_#AN.ljYSj.RFj6G0l]"7!]OqM4JB$]tm
+ >IIqqo#,hQ*^O\p55$=0edN?nD'rg&2FH"mB7bi'JiQPnD+5'*EiUT>3:urr$gm>GQI/uC-
+ WdH-e5W?iO.SWe at VpEhaf;0@/!EjUVD!MP9]+OP*.4jsVO2&,16nCJb*2$]Nd?R at g'VF1h`
+ @,DqFts)Nh'JIf:S:n;-^=c_44I='J,-&9pdfEjG+Jb'P*Ql/6X+>fsN`?An0];V(p(U2RB
+ JBK2#>I9U14SPW]k at DY+7\qMKI-'?ml!FYM57GB`%^H1^"qV.GmV\<F5rN,?P7EYjD48dMQ
+ q.K/W$UAElVin78Z-5iVid*eGk(HH4WfPA^:;<O;r:Lbl#^u7^hd?6DJD2PNN!](0U`(>.;
+ _XdV`*Q>)MOs5BLR<>/Rp[koe%6p_+TC9BBg@=VkfBPAV^BH="q<G0XeBN*a8S2alR&Tp;<
+ BM*JCke+LmW^5aAP>b=]![cgd8APl(cjZ^;^:9I5:NmO8PDkSWXF:j[hblB0ClfH+*D5:Wr
+ D.D='K2'X`QcD`GD,3s!rp)UR1BU=7%tO9ocKY(K8;0Y%Xq!cItNT6jmg:-nQ[NLn%GI=b\
+ s$gf&Z5DooOa/">/14D6A7^K(a=HbmbWi(.a8O\c!LgP9dgQY/%6L,$iaos<IfM%6!R-E:"
+ 4.T;:jD(%!2V*pihjofb2-(jK+2CIlRf:Ca-ilJ^aO3VV0IrPsGq?T:XK6t5GYuL3_-s5L8
+ 19KCb0u#rnpe1g3K9&=DA6P_&Aq5a'1e`ha3,:l--W<0%$Z')s/L.DP-a5TCEj@$%e*>GQK
+ [@T#=f6HZ*oE2dQ/l/A)tor("FPFurt#2/i6=Q,4!,H%"i#>8?RCDJp)qtu5L&3FH,a]`be
+ JeoR$J".[AcX<*\8$FrUIC$W+jY8-sS.SMcOb$SXL-0EhGB"3]XbHLV6:Y%;Xtk[r)9I4[I
+ ($kiD[cn@/HTL4Vc4;!eYa:'J8-J3jLFgA9ieM,39%Zq%D)[7k)0GabR+ at OY5Z7UcZb_'[.
+ Jac;P^9rlaK at RL/FaZd&CpuI__p*Br#Y$:[oWt'YD!'Yu.G<oRnGZkAV_a.3DB^c,Kdm<#9
+ E*sUZ_ZThr!qNEWXdo/pOa2_\(0+-D2,"B9M8lo!!M,_s5E$>!ZFr5I_lC)ff['^Hfk5ddD
+ -jtjs5H<-V#UC7!'VN#hHU0W[t/n,_=;Kk&dXM<^^1K1aT9FBTOg/DkRI6Y>4RBSD"KHt[(
+ o-IC2mf6>>\Qn8;TDW?^%l<),HR]-V"#6MMrq-l]_?B#nh1Y_!>doFsT+2#946VXb#CE#Ft
+ <SY&jU#X?Qc`PlhNnJLXIbM^so*%Sr"jrch%nS/:&h5E%2?c\0W8NN8E--\hS*QIAl7I^Ce
+ ?InF,/HCg<r+1P'@blPk0:*>TUJ']&53map%9M:3EVWI&)'6,Vn8H]u<-\=<Zf)Lo3_?oTA
+ -cLA#o9QR_&9a^'lh^Sim@,p3:Ab$!=/,mG&BT3B"bI-GKkZ*fT2Z27>qdj/=fUOd-nmD-K
+ $Z\75:Hq7M at Z$8>cB27[p`jmMU7.As6>+6CqrV4$J3BSc at D+]!(=msoYT-Vj!1YE=ATA<\a
+ ZuA7[MOI5:&%k^[^KA[LMKOb<d8YDsr1"'5:pLP;h)>4-;i;CgB4U14rak,+7LqW&Rk5-#m
+ q&Z`<$M^9Z&,X<Ro?+*R#9n%6XMffn0n[rT9P\O[g#3GIY>G=7r,C?a_l3 at V*7GnRq_GGAQ
+ 9b>S!g;5:M>]Hf/u<)m2V>M?MGrFeL`UC6trhuA=f-d]uUHLS!AS6pe'-\>+3`tN0o^t+3=
+ Ml2C]e7'X6cr!u$Zg^>/!@Jn;P]NDn2"+;r2Xp7uJ<T08i,Z-%'2/Ii'1"=j>%$ZJC#K;=W
+ "p*nr7?R)Pc6WdR#B`k9mQ0[h8LDHf)<9=kfET\W08%Qk>&dr'6q,RbDDl-fXgPs(T:mu:J
+ :Q&Vf=&XE at t2/K;i=T5L,^X"E]loi@/"ZE3dB*EdAP-#e4N@?[ZheK4`sai26h<"+9MNK9P
+ 9PfG?LZf)iu=peNu)C>%lEY/Q*gKPBBMFPRHL;Hge(iJ.')P8/%C>Z6r8H=mhq#aju9YVrZ
+ !pBGgR&91SQSe[tpK"uAUY*8I0E^Hqj(Ts&7MacZ2ACCTY`L3E179<oel=4!-rI*VX`J]tH
+ Te1hdp7b=/8MT5#+`I at oA:Ip!O"CG4"9,>=E,pj!V!ADY#\nol4&8ME5kpD<Kk$kBc;\dm-
+ sP)!0eF?&Mjio@;5];+YQULJ7[ukS at 4^$PL/f7 at b+$s7'QEVo)kK1E!BT5N:/7S-3^_m0=,
+ TV>9<?+c8D-I>dE,?P@#FR8ppnmPd86*9(qVakDSDL%Y.YR at RkkPV%"EBuKP5%KAe$d4`cD
+ bX(7kq<$U:9t?ReZ<j4mbanDD,cFV:u-8s'J\LTp9<AF(`D!B)<mPAC%f4#a&Zc4'0UGbk@
+ f0/njO0,?o&YW9OiF at cg8^0D%SplE$dUd?XJ%986E&J+94 at SS\q\i[@ppK^5e%!9pE'++'F
+ SX^dZLX,'ui<OIV>5Ut0InGXk`=HGtcq,spP:LuQgGc%>(=#:;oUP*!-ZHe at -Ps//$9JRlM
+ G=;^F at jh'*p6Eo7:/q\:..EqkbP%_??a#3'CZP>m4Tc*-cOG(#LCND6UIS;lL:EL.N2QK3.
+ ]<\\W_RuQ64h=3'db4T])OfXp%RYRde4E+t_;)&LiV[`f`@8='D4;-ERpa8J&Bg>ZCK+"9U
+ [d/L#PP8[M<XBT^/SJkh3Pd*R4V2P)$d$:UK7J`fH(@I1N)=ZXCLEXZ5'WZ'O59r*J(-R,e
+ uSR at XjU!S8+Wm8:?-O'+'k(N']+mPkbb_]#lLhf9l(;3Qs_JsHITb_Ar[s/47YrGLip/\uk
+ Ucq0$8Nk at DEaB6GLhLK9=G at S$s#ZuXeKOS0]Jp_9/sI-G&pH)B`hq%ajbC$2GQR'IU/#*;1
+ (`072s#Xq'A6:"eKQ!rp-UFZLmCbE>5/+=V$.-sa<5]D%8RN_rIdqMn`5kg30 at Cfs5H_n[>
+ aWs,%QTnW0;"K at 4\r&rhT=Pr)(!Ql'r%U,XSj@,>Y%=Z+\q&4T$Q4mISmS7rt6f-ZFZ3MP1
+ ^"0NOd9OD#5bF&=LoK93?l3[_ctU<n?`EYQhk=m)+C at j7U0OV@9JNZ:rZ;G6 at A5W?^/M3':
+ V?r#XUq!.jaN\+^u45s!rLrU2)UiMSWr81,;'+l^WcsG'jqj-ji&LTtT/CA\dT2'@5?u^(d
+ ^g:o1n:0ep'-R\LELhJHBKrf$nA0oo3Q0NY1R?@D&3.e5>a#A_e=pA&FAe_K-G^"+(d$`I#
+ \nqB3PiDa?D,4Kd3>gd58S8$s/=F6'&(8!%MkYo3I/\g66=jA>Uh"&[S at IbEff4LLgWLBn"
+ WAt>mj5;cZaDXIp#-N=DLcMJ+!OI:;k'&Om>Cr/P)BNaf5h;,+!ud=t0jeRd(BBk]7pn:'S
+ Sf/a8$H_i@#1I2B\sQT.`26MjWWKmui#[P!@OmS_HQ`TCIC>%$[5eY58<C'g9e]V2j6H,OI
+ 6S6WgL"e$eImC-U34-:62O$4q%>!0&]["oLs$g?Bn1ME-ks!c5d(;u2#/[.6\JNDI\</<Mj
+ -?:lJ]5rb3P6P_gqp at gnU;/%C=Ne$1PA5Y.Q\21>qc;*8M0#rkjQ<jcRnAQ:',)/*N[dDen
+ 3d*=BG_,tPO?_%rI($NSBR3IN#bVf`3mD3"k-B8/YY\pS;8!X,f5SfO0%iC+0o`7/m>\;&N
+ 2#5H0O)&6 at 72g3hGiYfG>hn:<(.q,./3=\mW_.U?=oK[#Bt4M-uP,(];WD+cc":DrJpWPZc
+ ?>(:(cuNW^^B_q<@/71(Ug(*b1B7H7XUQ3l,a<B1Ti"^e%3Tb-HaZ;M=/PKGc+nrb1(;PMq
+ ?P[3-MK']ilEe:pPI]PQGeT-PFV94F,WJLEq(IX1FWBOYs(:hMC(;\UoCb.&>3-SEKdNjCj
+ 5,P*Tr8O<BZQ#4>'ZP<?m,1TqqiU#O8=YVo.XWqg>5/+=M3c-NF0Wdiqr"[%[>9S20p/Du9
+ Jg9!=PTn!R*eeg%ur#j:8AD1a+=sj/c:,/3 at BEm`Ei%-U7`8:3%]`'+tRbsq<+Gk(3c&MLT
+ sjlclRW'LcU+3ad5(,,?jm*7&mM9rX6Cbl<jm;ps0?3A>hqAE at 7&#Zq#=:MhJ@"PL%i)GYU
+ Y/$\.>hmUY$<hUcC&=?'Jp'$qdD5_&Lok1-MfCMQl2a!X8FjJ4,Z38oVc,YeOU`f<>7Jm.q
+ r\V7HLK`>Yant6/-EpMGe,B\..M=Zjk/MBK&`>r:+2Rp_sZ0?p4b@*W<(:!@97#R%`_LK:`
+ b4;iL8Vmi<7[N7KC_q9CKeDd)K_BZNal&8>*@H4di\--$eq/VU6<]cO>%$[e<OH3X)qW3K"
+ c7;p:a`;&k:J>h*0#[G?'Q:e=lG$/"s(]]<(++_pMpp\iLU];jTfl7E!D<&A]V]D3.Xe?=a
+ iDROrYXUISn&"nsmmMMVr`2j5eBNH\r0@(>-4fG5gN8iPrFNgc5$YCVcOJ2E(Oci+, at B%kH
+ f;k:Hs&:n#qBHi;WTA]H'Np4HHMUo<3dl&q\C[P$WE@&&Wo)6/4I)qmN+Ieq^%*EtET:JT&
+ (9e=J?:0+4;$d=S>3qli5FE4C'$)*P9%q@%9jB>;Nd'Ac5H"a(4[Jg:Z\h_cuZ64&FctS&+
+ hS":1o&\&9B28H2F8Otl\_3qg-*,KQrfE;,n9s0kd'hh(3d7bl;6m"*:tQ(OBKoJVaV^pBU
+ .$3M7C5I([3ReR5<\J\<3ajjDl'Y]2E+<(9\<6DHLo:Es#khdf at rB#/^VW:p[91eGgOieDV
+ s=.(X8S9St&W=[Bqc7ECO2(IUZDleV;7I`AK/4Ntt9q\FV#1@`euh(r7jnE4,2\M4e$5UBf
+ d`NiB$+94a9[njMkb'5>TaVMo)EOt&D-3dp#_Ms&FFj.jB(Ih5@=I/!]644gZ at BrjD'I-JN
+ 0a`6Xp(RJYc?8ala:Jp9M5:c1]ltjn+7_Y_I^'">"b"sbZ:fIXm"UjOU=,M"DM>T$PUcjV.
+ <tIO<NL!tUq7X>-4'frs?dVne]ToYB,V)o5<]V3-i.1=ZokQNHI."cOJ,e94DnEWnCC]_2B
+ m!0Snq%siQ^;9[B$QJ4or$$?<L`D7ltfgkE3+.)lK#oLaS(!P6[QttkA%i!MJ?!?fIOqh-b
+ `eqIO:5g2isWnW\`C!,LBE/7:3l;:LU!CG]Q5p%k$\-UkI=]juYM?_L;TI'%1QH^Cq)+4`B
+ 5L4+1l,eh,Q*Qf]o)>eW+/e%2W4e@<*4+7C<IrT^TP\phj&pu+.+oEtP_b!Y$p<+^UQM%#9
+ a&8L1mc9:A#rg3b9Foag0pSV0,=CBi>K<]:)I\rT0W.iAnVP5)'Kr$ei4cpTs(AuXm[5W#/
+ LX-QWlT^:7*/OUmpYU%)cYVLMBk_VclBP#"ZI>,XK]FbA]O&)59ikWXc'FFhcN$4;=8q_5p
+ ob/i/jqol4*7/Zj^\p+3dFn4VLs2%YhL17F97krs"--U(h`bnJAHP-g1%MQ1o?GB_#t^GJt
+ ^mWFA7H\G38,Br_Qs/rSkd(Cg`Bg$N-GX4ZuR^5Q9^;?!/&g(+%0T?^k?t_t%A[6P")c^=i
+ "&cc&B#rrdjrk\onlrDu6g,%q;eN<.r?#FpK4m2%DW;H*k&"UjOS:C#.KbOkn$Y2C[SOCe6
+ 4*pZKZj(E;D71NL0k%]pf$59heZ.-NCe/3+:7ZRfaBPM at nF8P[3=0JEt!_3trldh%7LMIG"
+ [!(!B`JK;LdSjYi:R`B1V^2#iR=h]TC3q"m8&#?9OB2(I:#K,)3#%2HD"&fg%n-#QTgh at GO
+ \uSbNtbJPblNef8;mBB'X5RaX>&s51d:b!I at H;SW_(oq`[Yj1MDhj37dC"dT^mT8[MJJtc.
+ ]^F9D>2OYXaDn+R,ltp%:Isr-2H-`WbleT`I=\\LU_!8&kj/D:hn=ZL,]G3H8[jY'>-'"8s
+ cY#C*Nh*!u_s^7`:Y)>]Gm:Z0T\-^58nWPJO/gB*K:Arl_=6f(@T>@7goc(Ds14(g=Wq<Ff
+ ^2'XYOft%Mkg>bj`^1F7([kTcH%J2_e?[M\$:"ZUreu/XU4h-"1Gfu5TP+R+b>bcoLZ5:L*
+ p7%Qe(UcL[E7n4^2;Z>iX.ruX(4a\.E&%mP7>'kJKZ_^,i/BlUY]Nc=*uR(i&"k]uU_ at G4"
+ ]au`Ops/uqGU'p`3ZHG%ElHWQ9/gXZ'8Pe-eRW20NGl!W/YkeaNR4_IUIZUe#,ugH[DSb=0
+ MqVRl>7h>E;aJ(WAdr#C&t#nt-i_jd[7RQQGNQQ`\$><N!^Si'Nn0lTu*V,nq>X"LU$NI5#
+ ?'NjR]A^Q'(th[=_D"J$ZTS1ck["a7]WZ6`Uer]\H64i1l^JDkfu>*Pk`+%s^^8&8)ES;Gs
+ D('`KA*g>%$;U9Q0_FM^\[C))'FS5M'laqB0mb+pnBhG+dMk0lYLB(CkNh]0DYkoDae(OFU
+ CHQ]^qWkUY(qj5B"u]3]23FOq$oEcS3DVXQ/gkMQ:3O4!+0 at eg`M]Q02s.?5B/&o3Bh8dQi
+ >*n\L(bR"'J))U1XT6D18DmC"]ZYsJ*GqrfQb29s&gcjQI\6Fo&S5q$ahjA7t_*#S'iZ&Wq
+ s'HK at jcl>tcI/BX.9"KjM."6&);4=Zq%J?o&$eblm^uLmA8F+k at k/HQg]OY*0<<Lm))%\&f
+ t@@p-hsN/FLtVE&G2=K,"P;K=Wk[*p%6VDI(lY-DAX<-e$1VT/JqK?a,K++_H"hS"",o^Q:
+ 4D[Z:3Zt@]:FB(<oVL]6$@!fd^)m'9[c#Ra9r?:g>LmH.jZTjHcjL]tMX@;9\6Z+PC-`qjW
+ :B$)[SW5OY[jf3hH\R6SYHbAp6ciMIr'\g"QMP at T!PUQEdf/+4kMa;`n2^&Bq&@)Q+:`QGO
+ !"DVdaD+*V;-Rc,[2K6.m5aS4'&!prHgVY=a!t?:>4ChZp-npB;:IT-!QRI\NoQ(rsDM_'S
+ XcQT-8q(5'g at q[DQF2@\P]5Tk$qtY_JL98iXk4AP1tP,=h1W]_V-[bKkV/#ZAJsX2'5+K*V
+ ,h)JV0s(T,-k33[M,Fk&Uu%72$O@;Ngu#9BBO,9\YH;5.7*W9r/Cfa2Ii:a_m$RgM3uG1Vb
+ ];Y;tKnmj/SBaV:*"ZK)#W41O(Pkcn*%6(FrH1pkZ*#>@=Ar3mf9?b`Mh7ME\khqct_Bn_,
+ Ca5C$Y1b]grD9q"388DLK.`RX_u?<S3\Tk2*/kZ$h\8)`peFRVE0BF`&S\3_@%oL2@"L1/_
+ 3(VY at EFnqmC"Qc?=SE.j\+e:m=#1N4bIEFE4%rOR$Oo#2GB#BJX-XM"&)?`Si^#siF($r%u
+ u$g(7F%rH+UX53&qXd`-2iF3RL?eY\AudQHV&OaZj\lL/'@,m!AX,("UM;anAm^/O<=*0J,
+ S6pf`!;Q at 1R*+ZQo`%:4t:mu+ha,#5 at 60m&Ro_/mK3SBQ3,Qt`PBiAko+=3#G=\5nok0J,F
+ N4lfdSl[ih2(N"OAC0;dYjZ"phQZ>hHo33G at QXIm(j<U*&Rommk(IQSEItA?=PL%sR12&8D
+ FWo?<>F55F:b at t3pf\q$\h_#XnoJ)uhukqcW"VXtRneQf7Q at Z:md>j;eVTrbhVMQN/[0B6[
+ (t6]P*TKDb:us(H2'&a]-BNVDJ5)bZ%s("J)ZE,S\QQfErqi`iH0Yd[[>_!fD":DF)ik:FW
+ &PhmuC)"C8/5sJ$X7U^Wc//4Bs/*4lXC"F&MF9J2r2*$+U^oqhDonOVZT\ODBEL$e"-GPNY
+ 'lQAT4%O6#7DFb3AG&LS;W#$GiTo80$Rk%+7XODAhoU,hM=@TpWo!?J$@:5aEd[#cpUao"'
+ =r/r828"JjV\`kYad-rtkL/+8cn,te'c&'Z8n?p(3>q*2N"$/b#,&sd0Dj/BuBgV])#3H$r
+ :Soi\SI(foPN"7;@u!n(rVQWaj'33KfHcodV+*$659Ii"OXp#b-*L'OF7M4,c?G6+UfcCY>
+ JLP'.@(2ddV'5RF8nS7g_8(UQno<#ER-M'iJT7ok;tsG!St+-XAf;G\=l&MN0QaX=Rh`8Lp
+ \pUj'3QUV`;c.VtPYGX$q&BcQ!5XTbC?k-XS<]rPB2p+qWqCm<)FA9Qe=^E8t2>WMh-VBjI
+ BtB"n?ukJuHK6KCNoN.k"B3,6Z*(Q1_PI-o:0W!ZU!Y_NlM[KP>@n\]ir/]X_5>2%!K_apf
+ SSl+pN57k+<%-uouck`J^[P#F#S/q:PHmTbd3#IR-rsTl!9n&b#Vkml3BGkNXrD8c8(4Me>
+ bgc;D2[H]&)-cb5%&%aM+E9$6V*5/ANYsE:::O`6A1',=m>%_:!M-/)d5Y2Xa[rhU=-$#_C
+ gBN8(($\JW"Y#]rQ'#2("#pAYSN\#Q?1,RDSDDS3*Nn(I:m-M"?%VO:)mr)pA4%qEY-q8<C
+ ml'MeG,oe\V>e at 9bDWSC+<)dYSAV-haL&)0-DE%ol1;rYo6KZJDo7BS!;/kg1MBBTFb55UY
+ OS:,`+2%\)+-XRGkL(2fWm;%";hO_PcEXiolYm`ZAg,.F9E:mH.]5GgkBGiq;H4,Lta2#<2
+ V/^g015f497im(Mp'0-TjLT7-Us%1OnLhdlb!?G<VD^OZNRhUeLZkmpAEgm`*+q"@(ZoAZa
+ r$ToJJuD4Z at O`#1_WQpul%tAHl3&WsV4rP1J#5#3VLorC;Gk+mS3'Ua(8X$RJNB2Pi.PX=r
+ TJFA0AQ%=e)G4^&8]Z"@iL0W9>+<S*[''U,"\Ikf1D(bd/IgQaH4^l$ND,g<Mu;M#MLqF3#
+ W';62#=,`jtae7*?B"mYl`Op</@bMj"`iWi7'=3>"s.(4T/=^%Nh0Ws,paEi;FDM$u]uUFE
+ PlWff"4(Hs40Cu(;9C;HK0i`bE=FW#"/Di]WhZ9=<nT1'Cl'58'5b:S3I,bN-hEMCZ!:Ir@
+ TZ0VUo_4;8(("!(eQXdZf=12<%:Lr+A314NW,_ma&jKkWirs*`Hs+PLu9h^I=p06O3p@]](
+ IJL\<%cTlo:LqOZ8T at LY+fOKfLf'Yg3KZj0/]/\0'0F#s2KYi[^6:8ag(.0qBgH,'K1r!Cp
+ N#GYBPEVupb.(?A!\^l$+@?rSD4]u_LIOXj^\ok'^%M3C#V5STp?/#J54*W7H1#SYS6(T9#
+ 9<7j,c>?;do#/(6KC3c@>@cMW'?j_kr./M,5$^YOL\h7Z$GAN/.*o<<QKeSc8gGM.1I3&ga
+ 9KodcXJ&J&AkS1r+!GpbA+PhZ\G`LS/)gc-,!if1SXPpN(lLV&n"&ZM(ih91csg']n9-^H'
+ a\DrFYL3eFr9u1.CIEI@/OWg>cUrA%alXN6DBgHq*B"Mj=m/0()j(k2!+`bF1 at gS[XdM-Qk
+ e_R1Nr[S]Q3>(UW&^F_N!A2j#QF`bR-\<;W&j)M!U.dQbSrtT$\&UWZ_?&1!i(th^Q9h]+O
+ ublU`MaI&SFFEu>UNJfqiscopi"IidDGcI`,oNC2l<F#qNks55ER*)g3X3]p5[5+aq6"p<+
+ nKI7=7iua$Ecad"W.taM9kbieFXJ&EcHW#jqGG48^cJ:3IUjMKZp5AGtt>F;A<[c_NSbWkb
+ lNL(iu8&M"/kUhO,U6 at 2Z%`?"qe0bq\<B+\it at Ht]k!iJI"[(t5re+-Z)7)YXPLA$9qW6ek
+ *7=7iuf9,f]LmcP13%`"S^t+4;K`e?lO_Kr6(@luN;J7_(,"%g<*ND+;[N[p`![lB(c:kAV
+ B.X-9]^L\JY=4o,T%"&]`lbs8c\ZUJjFWmOU7iqMF[Wu.K1.D[(8C;*r'Ua'BFgY1TtT4sa
+ Z0t$;NVV.k76k?QCnBhkTklUi[6KDdD[+aSF99%1?>hgSJ*`HiM[i9O/HP&#@C,N!9bCrB^
+ \2bYglgI9SK`l>XVcJkW+b*)ohW4%,k,R$iqpl6K.s$l%kG-*,o)]d%4Fr)0$tQpI(YiH^u
+ Fj2YI25mYb=.$&&<i`Y%iXo`Zq]TYVT!#sXB6\@=n[Z1;$q/JZt&`n5#PZ%ZNt"h!]b!GY!
+ <T`@pT%I/>&$iXVM#H4kjEcHjAm712K?7KtP$?Im4e)CQiq17F9J--tQ:Cd0M'3'7/?en#1
+ /QcclZLOJnTfoq"=o\AlMQDWZM-t\@K5?N6*>i5Y>V4XsgA=8$B;/OQP,ppZ+4q>;IeEg^-
+ \2U at Yhg.sZ32]&h^"WFM.Q&`U16sn at 4W?,:E7<C:gr\r.\cF)D5:[FX,;#0G4[IM6q\_.1N
+ Tkq^*(<,Oj':&/3`2WIpD+-.ErK99`29Qr*?Vub66Dh3NPA0L8EaQ)/e/-BKu?Nn=0cqYio
+ Yu(LkDj[5/)pU!74cXdl3#Rq'eVb%QhomZ'5SQ=08GhY=olk)J'<[Rd0!rW\)*FB?%fLC&W
+ M<+nLbMC?bm at Hoo=W?J0s*1>cGn6r+OcX%jH8Mf70k;SF[_'"&P#efJLH<ggT=,t+OBmT:;
+ ca?a`[8?NP<h>!3N(#p\:7]HC<CM:1"PrllD at js&"kst#>3WuXW[HGu04eq&F4W#5TG;b#f
+ !s27?$0&u>*5+c!N%>1`lcR2MYrQQ"r5jQ`ZigiAZ"p/c1&'doeG!cDQ4aiXu=I$IBfR04D
+ Tp:f'9NKRf4W`du9Ms%@#LkMDdNBM2IcK,ErQ&7rK",r3t-TFZ$$j1"Dh0Y2d>rpFoM8A12
+ ^@.8D`uoUm^02H4cWSD^&)_3R!q8o)'c:!(q;*pW,^Ks at DbnAB`O(OHqBc;;cBTeVt3aYm+
+ Ad";FVJt:233uut;N47:TDkT&69M8fgY);O5UU9*l?T+3H:.BYgS.dnf=1p.62K7A\4&\:8
+ ?"Hro#nq$12Dc^QD1m\Tju?<4Db\cr1XT1+1fS\(A?AO.\:%;pOiBF3N#`9P)!>3bhpL4Y^
+ \-cLOhh')N]&F_,t$5OkUPJqeA!k;rl.4b)huKoVRgLP-Mh%D<k0*kGPtEbj3!Y-s)q=9`^
+ oX-]R9P7o&U6,:UKQej0ti:\WO`-5*K8GB^1m7RLr95Fs>DScGJDb.P5dO8\pjqhfdkeH/m
+ T,Vf1J*l0n)=S;`Ti#BW+Ihql%pX0_1u91s?BO88+nXNFYZ,^B18`;&"7aU.S!AlW^sqeP)
+ \LAKVNp\oI;lkqX73Ka"7"0.*ZplPpeoBOl,41B.a\oI+(8)'Y9^GjYCDm.sgl]/(pO1-/p
+ G4a1W8'delLVF'<_>]\#Is.iH]0;nl!PEdR%d@;k,PC]ndp"bLG'A-pIf/uWrVNd*^OH(R/
+ N)"N$7cMn_uN at o1JghB:JYnI0-#&i^OK%%YZ-Gnp2Jt,2Wb"ri$7Q[N[h'-U5CG#W1o/!Wi
+ 2YLWaW%0#A*92"o~>
+Q
+0 g
+BT
+22 0 0 22 298.411426 279.754358 Tm
+/f-0-0 1 Tf
+[(Ar)21(e)]TJ
+-0.272461 -1 Td
+[(they)]TJ
+-0.536133 -1 Td
+[(equal?)]TJ
+ET
+Q q
+0 g
+2.15895 w
+0 J
+0 j
+[] 0.0 d
+4 M q 1 0 0 -1 0 790.399963 cm
+316.762 37.789 m 316.762 80.293 l S Q
+321.988 721.4 m 316.781 707.248 l 311.578 721.4 l 314.652 719.138 318.855
+ 719.15 321.988 721.4 c h
+321.988 721.4 m f*
+0.809606 w
+1 j
+q 0 1 1 0 0 790.399963 cm
+-69 321.988 m -83.152 316.781 l -69 311.578 l -71.262 314.652 -71.25 318.855
+ -69 321.988 c h
+-69 321.988 m S Q
+2.15579 w
+0 j
+q 1 0 0 -1 0 790.399963 cm
+316.762 152.66 m 316.762 194.406 l S Q
+321.98 607.271 m 316.781 593.138 l 311.586 607.271 l 314.652 605.013 318.852
+ 605.029 321.98 607.271 c h
+321.98 607.271 m f*
+0.808421 w
+1 j
+q 0 1 1 0 0 790.399963 cm
+-183.129 321.98 m -197.262 316.781 l -183.129 311.586 l -185.387 314.652
+ -185.371 318.852 -183.129 321.98 c h
+-183.129 321.98 m S Q
+2.295753 w
+0 j
+q 1 0 0 -1 0 790.399963 cm
+252.547 257.68 m 139.148 257.68 l 139.148 359.32 l S Q
+144.703 443.091 m 139.172 428.041 l 133.637 443.091 l 136.902 440.685 141.375
+ 440.701 144.703 443.091 c h
+144.703 443.091 m f*
+0.860907 w
+1 j
+q 0 1 1 0 0 790.399963 cm
+-347.309 144.703 m -362.359 139.172 l -347.309 133.637 l -349.715 136.902
+ -349.699 141.375 -347.309 144.703 c h
+-347.309 144.703 m S Q
+2.324777 w
+0 j
+q 1 0 0 -1 0 790.399963 cm
+381.137 257.691 m 495.648 257.691 l 495.648 360.906 l S Q
+501.273 441.658 m 495.668 426.416 l 490.066 441.658 l 493.375 439.22 497.902
+ 439.236 501.273 441.658 c h
+501.273 441.658 m f*
+0.871792 w
+1 j
+q 0 1 1 0 0 790.399963 cm
+-348.742 501.273 m -363.984 495.668 l -348.742 490.066 l -351.18 493.375
+ -351.164 497.902 -348.742 501.273 c h
+-348.742 501.273 m S Q
+2.290224 w
+0 j
+q 1 0 0 -1 0 790.399963 cm
+228.438 397.988 m 317.062 397.453 l 317.062 469.492 l S Q
+322.605 332.888 m 317.086 317.873 l 311.562 332.888 l 314.824 330.49 319.281
+ 330.502 322.605 332.888 c h
+322.605 332.888 m f*
+0.858834 w
+1 j
+q 0 1 1 0 0 790.399963 cm
+-457.512 322.605 m -472.527 317.086 l -457.512 311.562 l -459.91 314.824
+ -459.898 319.281 -457.512 322.605 c h
+-457.512 322.605 m S Q
+2.300242 w
+0 j
+q 1 0 0 -1 0 790.399963 cm
+379.918 533.141 m 495.336 533.141 l 495.336 633.395 l S Q
+500.902 169.041 m 495.359 153.962 l 489.812 169.041 l 493.086 166.63 497.566
+ 166.646 500.902 169.041 c h
+500.902 169.041 m f*
+0.862591 w
+1 j
+q 0 1 1 0 0 790.399963 cm
+-621.359 500.902 m -636.438 495.359 l -621.359 489.812 l -623.77 493.086
+ -623.754 497.566 -621.359 500.902 c h
+-621.359 500.902 m S Q
+2.29295 w
+0 j
+q 1 0 0 -1 0 790.399963 cm
+252.285 532.551 m 138.273 532.551 l 138.273 633.395 l S Q
+143.824 168.998 m 138.297 153.966 l 132.77 168.998 l 136.031 166.595 140.496
+ 166.611 143.824 168.998 c h
+143.824 168.998 m f*
+0.859856 w
+1 j
+q 0 1 1 0 0 790.399963 cm
+-621.402 143.824 m -636.434 138.297 l -621.402 132.77 l -623.805 136.031
+ -623.789 140.496 -621.402 143.824 c h
+-621.402 143.824 m S Q
+2.335361 w
+0 j
+q 1 0 0 -1 0 790.399963 cm
+258.828 674.629 m 370.828 674.629 l S Q
+2.348876 w
+q 1 0 0 -1 0 790.399963 cm
+316.828 674.629 m 316.828 749.066 l S Q
+322.512 53.619 m 316.852 38.22 l 311.188 53.619 l 314.531 51.162 319.105
+ 51.173 322.512 53.619 c h
+322.512 53.619 m f*
+0.880828 w
+1 j
+q 0 1 1 0 0 790.399963 cm
+-736.781 322.512 m -752.18 316.852 l -736.781 311.187 l -739.238 314.531
+ -739.227 319.105 -736.781 322.512 c h
+-736.781 322.512 m S Q
+2.4 w
+0 j
+q 1 0 0 -1 0 790.399963 cm
+495.113 422.059 m 495.113 451.77 l 332.828 451.199 l 332.828 451.199 317.516
+ 429.449 301.457 451.18 c 138.828 451.484 l 138.543 532.629 l S Q
+1 0.890196 0.815686 rg
+187.742 549.427 m 212.887 549.427 l 221.75 549.427 228.887 542.291 228.887
+ 533.427 c 228.887 524.564 221.75 517.427 212.887 517.427 c 187.742 517.427
+ l 178.879 517.427 171.742 524.564 171.742 533.427 c 171.742 542.291 178.879
+ 549.427 187.742 549.427 c h
+187.742 549.427 m f
+0 g
+BT
+22 0 0 22 182.028894 526.571399 Tm
+/f-0-0 1 Tf
+(Y)Tj
+ET
+0.8 w
+q 1 0 0 -1 0 790.399963 cm
+181.98 247.797 m 184.309 247.797 l 188.762 254.391 l 193.184 247.797 l 
+195.512 247.797 l 189.84 256.188 l 189.84 263.828 l 187.652 263.828 l 187.652
+ 256.188 l h
+181.98 247.797 m S Q
+BT
+22 0 0 22 192.556238 526.571399 Tm
+/f-0-0 1 Tf
+(e)Tj
+ET
+q 1 0 0 -1 0 790.399963 cm
+204.914 257.312 m 204.914 258.281 l 195.836 258.281 l 195.918 259.648 196.324
+ 260.691 197.055 261.406 c 197.793 262.117 198.82 262.469 200.133 262.469
+ c 200.891 262.469 201.625 262.375 202.336 262.188 c 203.043 262.004 203.75
+ 261.719 204.461 261.344 c 204.461 263.219 l 203.75 263.523 203.02 263.754
+ 202.273 263.906 c 201.531 264.059 200.777 264.141 200.008 264.141 c 198.09
+ 264.141 196.566 263.586 195.445 262.469 c 194.328 261.348 193.773 259.836
+ 193.773 257.938 c 193.773 255.961 194.305 254.391 195.367 253.234 c 196.426
+ 252.082 197.859 251.5 199.664 251.5 c 201.285 251.5 202.57 252.023 203.508
+ 253.062 c 204.441 254.105 204.914 255.523 204.914 257.312 c h
+202.945 256.734 m 202.922 255.652 202.613 254.793 202.023 254.156 c 201.438
+ 253.512 200.66 253.188 199.695 253.188 c 198.59 253.188 197.703 253.504
+ 197.039 254.125 c 196.371 254.742 195.988 255.617 195.898 256.75 c h
+202.945 256.734 m S Q
+BT
+22 0 0 22 206.091394 526.571399 Tm
+/f-0-0 1 Tf
+(s)Tj
+ET
+q 1 0 0 -1 0 790.399963 cm
+215.84 252.156 m 215.84 254.016 l 215.277 253.738 214.691 253.523 214.09
+ 253.375 c 213.484 253.23 212.863 253.156 212.23 253.156 c 211.238 253.156
+ 210.5 253.309 210.012 253.609 c 209.52 253.914 209.277 254.367 209.277 
+254.969 c 209.277 255.43 209.453 255.789 209.809 256.047 c 210.16 256.309
+ 210.863 256.559 211.918 256.797 c 212.605 256.938 l 214 257.242 214.996
+ 257.668 215.59 258.219 c 216.18 258.762 216.48 259.527 216.48 260.516 c
+ 216.48 261.633 216.035 262.52 215.152 263.172 c 214.266 263.82 213.051 
+264.141 211.512 264.141 c 210.863 264.141 210.191 264.074 209.496 263.953
+ c 208.797 263.828 208.055 263.641 207.277 263.391 c 207.277 261.344 l 208.004
+ 261.73 208.723 262.02 209.434 262.203 c 210.148 262.391 210.855 262.484
+ 211.543 262.484 c 212.477 262.484 213.199 262.328 213.699 262.016 c 214.195
+ 261.695 214.449 261.242 214.449 260.656 c 214.449 260.129 214.266 259.719
+ 213.902 259.438 c 213.535 259.148 212.742 258.867 211.527 258.594 c 210.84
+ 258.438 l 209.609 258.18 208.723 257.781 208.184 257.25 c 207.641 256.723
+ 207.371 255.984 207.371 255.047 c 207.371 253.926 207.77 253.055 208.574
+ 252.438 c 209.375 251.816 210.512 251.5 211.98 251.5 c 212.719 251.5 213.406
+ 251.559 214.043 251.672 c 214.688 251.777 215.285 251.941 215.84 252.156
+ c h
+215.84 252.156 m S Q
+1 0.890196 0.815686 rg
+186.602 274.685 m 211.742 274.685 l 220.605 274.685 227.742 267.548 227.742
+ 258.685 c 227.742 249.822 220.605 242.685 211.742 242.685 c 186.602 242.685
+ l 177.734 242.685 170.602 249.822 170.602 258.685 c 170.602 267.548 177.734
+ 274.685 186.602 274.685 c h
+186.602 274.685 m f
+0 g
+BT
+22 0 0 22 180.886035 251.828577 Tm
+/f-0-0 1 Tf
+(Y)Tj
+ET
+q 1 0 0 -1 0 790.399963 cm
+180.84 522.539 m 183.168 522.539 l 187.621 529.133 l 192.043 522.539 l 
+194.371 522.539 l 188.699 530.93 l 188.699 538.57 l 186.512 538.57 l 186.512
+ 530.93 l h
+180.84 522.539 m S Q
+BT
+22 0 0 22 191.413379 251.828577 Tm
+/f-0-0 1 Tf
+(e)Tj
+ET
+q 1 0 0 -1 0 790.399963 cm
+203.773 532.055 m 203.773 533.023 l 194.695 533.023 l 194.777 534.391 195.184
+ 535.434 195.914 536.148 c 196.652 536.859 197.68 537.211 198.992 537.211
+ c 199.75 537.211 200.484 537.117 201.195 536.93 c 201.902 536.746 202.609
+ 536.461 203.32 536.086 c 203.32 537.961 l 202.609 538.266 201.879 538.496
+ 201.133 538.648 c 200.391 538.801 199.637 538.883 198.867 538.883 c 196.949
+ 538.883 195.426 538.328 194.305 537.211 c 193.188 536.09 192.633 534.578
+ 192.633 532.68 c 192.633 530.703 193.164 529.133 194.227 527.977 c 195.285
+ 526.824 196.719 526.242 198.523 526.242 c 200.145 526.242 201.43 526.766
+ 202.367 527.805 c 203.301 528.848 203.773 530.266 203.773 532.055 c h
+201.805 531.477 m 201.781 530.395 201.473 529.535 200.883 528.898 c 200.297
+ 528.254 199.52 527.93 198.555 527.93 c 197.449 527.93 196.562 528.246 195.898
+ 528.867 c 195.23 529.484 194.848 530.359 194.758 531.492 c h
+201.805 531.477 m S Q
+BT
+22 0 0 22 204.948535 251.828577 Tm
+/f-0-0 1 Tf
+(s)Tj
+ET
+q 1 0 0 -1 0 790.399963 cm
+214.699 526.898 m 214.699 528.758 l 214.137 528.48 213.551 528.266 212.949
+ 528.117 c 212.344 527.973 211.723 527.898 211.09 527.898 c 210.098 527.898
+ 209.359 528.051 208.871 528.352 c 208.379 528.656 208.137 529.109 208.137
+ 529.711 c 208.137 530.172 208.312 530.531 208.668 530.789 c 209.02 531.051
+ 209.723 531.301 210.777 531.539 c 211.465 531.68 l 212.859 531.984 213.855
+ 532.41 214.449 532.961 c 215.039 533.504 215.34 534.27 215.34 535.258 c
+ 215.34 536.375 214.895 537.262 214.012 537.914 c 213.125 538.562 211.91
+ 538.883 210.371 538.883 c 209.723 538.883 209.051 538.816 208.355 538.695
+ c 207.656 538.57 206.914 538.383 206.137 538.133 c 206.137 536.086 l 206.863
+ 536.473 207.582 536.762 208.293 536.945 c 209.008 537.133 209.715 537.227
+ 210.402 537.227 c 211.336 537.227 212.059 537.07 212.559 536.758 c 213.055
+ 536.438 213.309 535.984 213.309 535.398 c 213.309 534.871 213.125 534.461
+ 212.762 534.18 c 212.395 533.891 211.602 533.609 210.387 533.336 c 209.699
+ 533.18 l 208.469 532.922 207.582 532.523 207.043 531.992 c 206.5 531.465
+ 206.23 530.727 206.23 529.789 c 206.23 528.668 206.629 527.797 207.434 
+527.18 c 208.234 526.559 209.371 526.242 210.84 526.242 c 211.578 526.242
+ 212.266 526.301 212.902 526.414 c 213.547 526.52 214.145 526.684 214.699
+ 526.898 c h
+214.699 526.898 m S Q
+1 0.890196 0.815686 rg
+422.027 275.142 m 447.172 275.142 l 456.035 275.142 463.172 268.005 463.172
+ 259.142 c 463.172 250.279 456.035 243.142 447.172 243.142 c 422.027 243.142
+ l 413.164 243.142 406.027 250.279 406.027 259.142 c 406.027 268.005 413.164
+ 275.142 422.027 275.142 c h
+422.027 275.142 m f
+0 g
+BT
+22 0 0 22 419.743164 251.142834 Tm
+/f-0-0 1 Tf
+(N)Tj
+ET
+q 1 0 0 -1 0 790.399963 cm
+421.898 523.227 m 424.82 523.227 l 431.93 536.633 l 431.93 523.227 l 434.039
+ 523.227 l 434.039 539.258 l 431.117 539.258 l 424.008 525.836 l 424.008
+ 539.258 l 421.898 539.258 l h
+421.898 523.227 m S Q
+BT
+22 0 0 22 436.200195 251.142834 Tm
+/f-0-0 1 Tf
+(o)Tj
+ET
+q 1 0 0 -1 0 790.399963 cm
+442.934 528.617 m 441.871 528.617 441.031 529.031 440.418 529.852 c 439.801
+ 530.676 439.496 531.812 439.496 533.258 c 439.496 534.695 439.801 535.832
+ 440.418 536.664 c 441.031 537.488 441.871 537.898 442.934 537.898 c 443.984
+ 537.898 444.816 537.484 445.434 536.648 c 446.047 535.816 446.355 534.688
+ 446.355 533.258 c 446.355 531.832 446.047 530.703 445.434 529.867 c 444.816
+ 529.035 443.984 528.617 442.934 528.617 c h
+442.934 526.93 m 444.648 526.93 446 527.496 446.98 528.617 c 447.957 529.734
+ 448.449 531.281 448.449 533.258 c 448.449 535.227 447.957 536.777 446.98
+ 537.898 c 446 539.016 444.648 539.57 442.934 539.57 c 441.203 539.57 439.848
+ 539.016 438.871 537.898 c 437.902 536.777 437.418 535.227 437.418 533.258
+ c 437.418 531.281 437.902 529.734 438.871 528.617 c 439.848 527.496 441.203
+ 526.93 442.934 526.93 c h
+442.934 526.93 m S Q
+1 0.890196 0.815686 rg
+420.887 549.427 m 446.027 549.427 l 454.895 549.427 462.027 542.294 462.027
+ 533.427 c 462.027 524.564 454.895 517.427 446.027 517.427 c 420.887 517.427
+ l 412.023 517.427 404.887 524.564 404.887 533.427 c 404.887 542.294 412.023
+ 549.427 420.887 549.427 c h
+420.887 549.427 m f
+0 g
+BT
+22 0 0 22 418.600293 525.428577 Tm
+/f-0-0 1 Tf
+(N)Tj
+ET
+q 1 0 0 -1 0 790.399963 cm
+420.758 248.941 m 423.68 248.941 l 430.789 262.348 l 430.789 248.941 l 
+432.898 248.941 l 432.898 264.973 l 429.977 264.973 l 422.867 251.551 l 
+422.867 264.973 l 420.758 264.973 l h
+420.758 248.941 m S Q
+BT
+22 0 0 22 435.057324 525.428577 Tm
+/f-0-0 1 Tf
+(o)Tj
+ET
+q 1 0 0 -1 0 790.399963 cm
+441.793 254.332 m 440.73 254.332 439.891 254.746 439.277 255.566 c 438.66
+ 256.391 438.355 257.527 438.355 258.973 c 438.355 260.41 438.66 261.547
+ 439.277 262.379 c 439.891 263.203 440.73 263.613 441.793 263.613 c 442.844
+ 263.613 443.676 263.199 444.293 262.363 c 444.906 261.531 445.215 260.402
+ 445.215 258.973 c 445.215 257.547 444.906 256.418 444.293 255.582 c 443.676
+ 254.75 442.844 254.332 441.793 254.332 c h
+441.793 252.645 m 443.508 252.645 444.859 253.211 445.84 254.332 c 446.816
+ 255.449 447.309 256.996 447.309 258.973 c 447.309 260.941 446.816 262.492
+ 445.84 263.613 c 444.859 264.73 443.508 265.285 441.793 265.285 c 440.062
+ 265.285 438.707 264.73 437.73 263.613 c 436.762 262.492 436.277 260.941
+ 436.277 258.973 c 436.277 256.996 436.762 255.449 437.73 254.332 c 438.707
+ 253.211 440.062 252.645 441.793 252.645 c h
+441.793 252.645 m S Q
+Q Q
+showpage
+%%Trailer
+end restore
+%%EOF
diff --git a/mgltex/Recompilation_decision.pdf b/mgltex/Recompilation_decision.pdf
new file mode 100644
index 0000000..a6a33bf
Binary files /dev/null and b/mgltex/Recompilation_decision.pdf differ
diff --git a/mgltex/Recompilation_decision.svg b/mgltex/Recompilation_decision.svg
new file mode 100644
index 0000000..79163b9
--- /dev/null
+++ b/mgltex/Recompilation_decision.svg
@@ -0,0 +1,1711 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   inkscape:version="0.91 r"
+   version="1.1"
+   id="svg2"
+   viewBox="0 0 788.07224 987.99994"
+   height="278.83554mm"
+   width="222.4115mm"
+   sodipodi:docname="Recompilation_decision.svg">
+  <defs
+     id="defs4">
+    <marker
+       inkscape:isstock="true"
+       style="overflow:visible"
+       id="marker5654"
+       refX="0"
+       refY="0"
+       orient="auto"
+       inkscape:stockid="Arrow2Mend">
+      <path
+         inkscape:connector-curvature="0"
+         transform="scale(-0.6,-0.6)"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+         id="path5656" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Mend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker5452"
+       style="overflow:visible"
+       inkscape:isstock="true"
+       inkscape:collect="always">
+      <path
+         id="path5454"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="scale(-0.6,-0.6)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:isstock="true"
+       style="overflow:visible"
+       id="marker5256"
+       refX="0"
+       refY="0"
+       orient="auto"
+       inkscape:stockid="Arrow2Mend"
+       inkscape:collect="always">
+      <path
+         inkscape:connector-curvature="0"
+         transform="scale(-0.6,-0.6)"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+         id="path5258" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Mend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker5066"
+       style="overflow:visible"
+       inkscape:isstock="true"
+       inkscape:collect="always">
+      <path
+         id="path5068"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="scale(-0.6,-0.6)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:isstock="true"
+       style="overflow:visible"
+       id="marker4882"
+       refX="0"
+       refY="0"
+       orient="auto"
+       inkscape:stockid="Arrow2Mend"
+       inkscape:collect="always">
+      <path
+         inkscape:connector-curvature="0"
+         transform="scale(-0.6,-0.6)"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+         id="path4884" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Mend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker4704"
+       style="overflow:visible"
+       inkscape:isstock="true"
+       inkscape:collect="always">
+      <path
+         id="path4706"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="scale(-0.6,-0.6)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:isstock="true"
+       style="overflow:visible"
+       id="marker4532"
+       refX="0"
+       refY="0"
+       orient="auto"
+       inkscape:stockid="Arrow2Mend"
+       inkscape:collect="always">
+      <path
+         inkscape:connector-curvature="0"
+         transform="scale(-0.6,-0.6)"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+         id="path4534" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Mend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker5662"
+       style="overflow:visible"
+       inkscape:isstock="true"
+       inkscape:collect="always">
+      <path
+         id="path5664"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="scale(-0.6,-0.6)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <inkscape:path-effect
+       effect="bend_path"
+       id="path-effect4543"
+       is_visible="true"
+       bendpath="m 118.00024,456.39849 222,0"
+       prop_scale="1"
+       scale_y_rel="false"
+       vertical="false" />
+    <inkscape:path-effect
+       effect="sketch"
+       id="path-effect4541"
+       is_visible="true"
+       nbiter_approxstrokes="5"
+       strokelength="100"
+       strokelength_rdm="0.3;1"
+       strokeoverlap="0.3"
+       strokeoverlap_rdm="0.3;1"
+       ends_tolerance="0.1;1"
+       parallel_offset="5;1"
+       tremble_size="5;1"
+       tremble_frequency="1"
+       nbtangents="5"
+       tgt_places_rdmness="1;1"
+       tgtscale="10"
+       tgtlength="100"
+       tgtlength_rdm="0.3;1" />
+    <inkscape:path-effect
+       effect="envelope"
+       id="path-effect4539"
+       is_visible="true"
+       yy="true"
+       xx="true"
+       bendpath1="m 225.41095,441.11923 114.58929,0"
+       bendpath2="m 340.00024,441.11923 0,101.24298"
+       bendpath3="m 225.41095,542.36221 114.58929,0"
+       bendpath4="m 225.41095,441.11923 0,101.24298" />
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="-6.0542683 : 531.67714 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="718.04023 : 477.85825 : 1"
+       inkscape:persp3d-origin="345.99297 : 302.46455 : 1"
+       id="perspective8810" />
+    <marker
+       inkscape:stockid="TriangleOutS"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleOutS"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path4367"
+         d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+         transform="scale(0.2,0.2)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="StopS"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="StopS"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path4394"
+         d="M 0,5.65 0,-5.65"
+         style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+         transform="scale(0.2,0.2)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker7593"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path7595"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+         transform="matrix(0.8,0,0,0.8,10,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker7373"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path7375"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+         transform="matrix(0.8,0,0,0.8,10,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker7159"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path7161"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+         transform="matrix(0.8,0,0,0.8,10,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker6951"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path6953"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+         transform="matrix(0.8,0,0,0.8,10,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker6743"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path6745"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+         transform="matrix(0.8,0,0,0.8,10,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker6541"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path6543"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+         transform="matrix(0.8,0,0,0.8,10,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker6167"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path6169"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+         transform="matrix(0.8,0,0,0.8,10,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:isstock="true"
+       style="overflow:visible"
+       id="marker6007"
+       refX="0"
+       refY="0"
+       orient="auto"
+       inkscape:stockid="Arrow2Mend">
+      <path
+         transform="scale(-0.6,-0.6)"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+         id="path6009"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lstart"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path4219"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+         transform="matrix(0.8,0,0,0.8,10,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:isstock="true"
+       style="overflow:visible"
+       id="marker5593"
+       refX="0"
+       refY="0"
+       orient="auto"
+       inkscape:stockid="Arrow2Mend">
+      <path
+         transform="scale(-0.6,-0.6)"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+         id="path5595"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:isstock="true"
+       style="overflow:visible"
+       id="marker5451"
+       refX="0"
+       refY="0"
+       orient="auto"
+       inkscape:stockid="Arrow2Mend">
+      <path
+         transform="scale(-0.6,-0.6)"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+         id="path5453"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:isstock="true"
+       style="overflow:visible"
+       id="marker5315"
+       refX="0"
+       refY="0"
+       orient="auto"
+       inkscape:stockid="Arrow2Mend">
+      <path
+         transform="scale(-0.6,-0.6)"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+         id="path5317"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:isstock="true"
+       style="overflow:visible"
+       id="marker5197"
+       refX="0"
+       refY="0"
+       orient="auto"
+       inkscape:stockid="Arrow2Mend">
+      <path
+         transform="scale(-0.6,-0.6)"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+         id="path5199"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Sstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow2Sstart"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path4249"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(0.3,0,0,0.3,-0.69,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Send"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow2Send"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path4252"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(-0.3,0,0,-0.3,0.69,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Mend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker4979"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path4981"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="scale(-0.6,-0.6)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="TriangleOutL"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="TriangleOutL"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path4361"
+         d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+         transform="scale(0.8,0.8)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow2Lend"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path4240"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Lstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow2Lstart"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path4237"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(1.1,0,0,1.1,1.1,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lend"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path4222"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+         transform="matrix(-0.8,0,0,-0.8,-10,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Mend"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path13789"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+         transform="matrix(-0.4,0,0,-0.4,-4,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <symbol
+       id="Terminal">
+      <title
+         id="title7859">Terminal/Interrupt</title>
+      <desc
+         id="desc7861">A terminal point in a flowchart: start, stop, halt, etc.</desc>
+      <path
+         d="m 35,95 a 20,20 0 0 1 0,-40 l 80,0 a 20,20 0 0 1 0,40 z"
+         style="stroke-width:2"
+         id="path7863"
+         inkscape:connector-curvature="0" />
+    </symbol>
+    <symbol
+       id="AuxillaryOp">
+      <title
+         id="title7838">Auxiliary Operation</title>
+      <desc
+         id="desc7840">Offline operation.</desc>
+      <rect
+         x="35"
+         y="35"
+         width="80"
+         height="80"
+         style="stroke-width:2"
+         id="rect7842" />
+    </symbol>
+    <symbol
+       id="Decision">
+      <title
+         id="title7815">Decision</title>
+      <desc
+         id="desc7817">A decision or switching type operation.</desc>
+      <path
+         d="M 15,75 75,35 135,75 75,115 Z"
+         style="stroke-width:2"
+         id="path7819"
+         inkscape:connector-curvature="0" />
+    </symbol>
+    <symbol
+       id="InputOutput">
+      <title
+         id="title7780">Input/Output</title>
+      <desc
+         id="desc7782">General input/output functions.</desc>
+      <path
+         d="m 35,35 100,0 -20,80 -100,0 z"
+         style="stroke-width:2"
+         id="path7784"
+         inkscape:connector-curvature="0" />
+    </symbol>
+    <symbol
+       id="Buffer_Small">
+      <title
+         id="title7212">Buffer Small</title>
+      <path
+         d="m 37.711573,40 25,10 -25,10 z"
+         id="path7214"
+         inkscape:connector-curvature="0" />
+    </symbol>
+    <filter
+       inkscape:menu-tooltip="Pressed metal with a rolled edge"
+       inkscape:menu="Bevels"
+       inkscape:label="Pressed Steel"
+       style="color-interpolation-filters:sRGB"
+       id="filter5206">
+      <feGaussianBlur
+         result="result1"
+         stdDeviation="3"
+         id="feGaussianBlur5208" />
+      <feBlend
+         in2="result1"
+         result="result5"
+         mode="multiply"
+         in="result1"
+         id="feBlend5210" />
+      <feGaussianBlur
+         in="result5"
+         result="result6"
+         stdDeviation="1"
+         id="feGaussianBlur5212" />
+      <feComposite
+         result="result8"
+         in2="result5"
+         in="result6"
+         operator="xor"
+         id="feComposite5214" />
+      <feComposite
+         in="result6"
+         result="fbSourceGraphic"
+         operator="xor"
+         in2="result8"
+         id="feComposite5216" />
+      <feSpecularLighting
+         in="fbSourceGraphic"
+         result="result1"
+         lighting-color="#ffffff"
+         surfaceScale="2"
+         specularConstant="2.20000005"
+         specularExponent="55"
+         id="feSpecularLighting5218">
+        <fePointLight
+           x="-5000"
+           y="-10000"
+           z="20000"
+           id="fePointLight5220" />
+      </feSpecularLighting>
+      <feComposite
+         in2="fbSourceGraphic"
+         in="result1"
+         result="result2"
+         operator="in"
+         id="feComposite5222" />
+      <feComposite
+         in="fbSourceGraphic"
+         result="result4"
+         operator="arithmetic"
+         k2="2"
+         k3="1"
+         in2="result2"
+         id="feComposite5224"
+         k1="0"
+         k4="0" />
+      <feComposite
+         in2="result4"
+         in="result4"
+         operator="in"
+         result="result91"
+         id="feComposite5226" />
+      <feBlend
+         mode="darken"
+         in2="result91"
+         id="feBlend5228" />
+    </filter>
+    <filter
+       inkscape:menu-tooltip="Pressed metal with a rolled edge"
+       inkscape:menu="Bevels"
+       inkscape:label="Pressed Steel"
+       style="color-interpolation-filters:sRGB"
+       id="filter5230">
+      <feGaussianBlur
+         result="result1"
+         stdDeviation="3"
+         id="feGaussianBlur5232" />
+      <feBlend
+         in2="result1"
+         result="result5"
+         mode="multiply"
+         in="result1"
+         id="feBlend5234" />
+      <feGaussianBlur
+         in="result5"
+         result="result6"
+         stdDeviation="1"
+         id="feGaussianBlur5236" />
+      <feComposite
+         result="result8"
+         in2="result5"
+         in="result6"
+         operator="xor"
+         id="feComposite5238" />
+      <feComposite
+         in="result6"
+         result="fbSourceGraphic"
+         operator="xor"
+         in2="result8"
+         id="feComposite5240" />
+      <feSpecularLighting
+         in="fbSourceGraphic"
+         result="result1"
+         lighting-color="#ffffff"
+         surfaceScale="2"
+         specularConstant="2.20000005"
+         specularExponent="55"
+         id="feSpecularLighting5242">
+        <fePointLight
+           x="-5000"
+           y="-10000"
+           z="20000"
+           id="fePointLight5244" />
+      </feSpecularLighting>
+      <feComposite
+         in2="fbSourceGraphic"
+         in="result1"
+         result="result2"
+         operator="in"
+         id="feComposite5246" />
+      <feComposite
+         in="fbSourceGraphic"
+         result="result4"
+         operator="arithmetic"
+         k2="2"
+         k3="1"
+         in2="result2"
+         id="feComposite5248"
+         k1="0"
+         k4="0" />
+      <feComposite
+         in2="result4"
+         in="result4"
+         operator="in"
+         result="result91"
+         id="feComposite5250" />
+      <feBlend
+         mode="darken"
+         in2="result91"
+         id="feBlend5252" />
+    </filter>
+    <filter
+       inkscape:menu-tooltip="Pressed metal with a rolled edge"
+       inkscape:menu="Bevels"
+       inkscape:label="Pressed Steel"
+       style="color-interpolation-filters:sRGB"
+       id="filter5254">
+      <feGaussianBlur
+         result="result1"
+         stdDeviation="3"
+         id="feGaussianBlur5256" />
+      <feBlend
+         in2="result1"
+         result="result5"
+         mode="multiply"
+         in="result1"
+         id="feBlend5258" />
+      <feGaussianBlur
+         in="result5"
+         result="result6"
+         stdDeviation="1"
+         id="feGaussianBlur5260" />
+      <feComposite
+         result="result8"
+         in2="result5"
+         in="result6"
+         operator="xor"
+         id="feComposite5262" />
+      <feComposite
+         in="result6"
+         result="fbSourceGraphic"
+         operator="xor"
+         in2="result8"
+         id="feComposite5264" />
+      <feSpecularLighting
+         in="fbSourceGraphic"
+         result="result1"
+         lighting-color="#ffffff"
+         surfaceScale="2"
+         specularConstant="2.20000005"
+         specularExponent="55"
+         id="feSpecularLighting5266">
+        <fePointLight
+           x="-5000"
+           y="-10000"
+           z="20000"
+           id="fePointLight5268" />
+      </feSpecularLighting>
+      <feComposite
+         in2="fbSourceGraphic"
+         in="result1"
+         result="result2"
+         operator="in"
+         id="feComposite5270" />
+      <feComposite
+         in="fbSourceGraphic"
+         result="result4"
+         operator="arithmetic"
+         k2="2"
+         k3="1"
+         in2="result2"
+         id="feComposite5272"
+         k1="0"
+         k4="0" />
+      <feComposite
+         in2="result4"
+         in="result4"
+         operator="in"
+         result="result91"
+         id="feComposite5274" />
+      <feBlend
+         mode="darken"
+         in2="result91"
+         id="feBlend5276" />
+    </filter>
+    <filter
+       inkscape:menu-tooltip="Pressed metal with a rolled edge"
+       inkscape:menu="Bevels"
+       inkscape:label="Pressed Steel"
+       style="color-interpolation-filters:sRGB"
+       id="filter5278">
+      <feGaussianBlur
+         result="result1"
+         stdDeviation="3"
+         id="feGaussianBlur5280" />
+      <feBlend
+         in2="result1"
+         result="result5"
+         mode="multiply"
+         in="result1"
+         id="feBlend5282" />
+      <feGaussianBlur
+         in="result5"
+         result="result6"
+         stdDeviation="1"
+         id="feGaussianBlur5284" />
+      <feComposite
+         result="result8"
+         in2="result5"
+         in="result6"
+         operator="xor"
+         id="feComposite5286" />
+      <feComposite
+         in="result6"
+         result="fbSourceGraphic"
+         operator="xor"
+         in2="result8"
+         id="feComposite5288" />
+      <feSpecularLighting
+         in="fbSourceGraphic"
+         result="result1"
+         lighting-color="#ffffff"
+         surfaceScale="2"
+         specularConstant="2.20000005"
+         specularExponent="55"
+         id="feSpecularLighting5290">
+        <fePointLight
+           x="-5000"
+           y="-10000"
+           z="20000"
+           id="fePointLight5292" />
+      </feSpecularLighting>
+      <feComposite
+         in2="fbSourceGraphic"
+         in="result1"
+         result="result2"
+         operator="in"
+         id="feComposite5294" />
+      <feComposite
+         in="fbSourceGraphic"
+         result="result4"
+         operator="arithmetic"
+         k2="2"
+         k3="1"
+         in2="result2"
+         id="feComposite5296"
+         k1="0"
+         k4="0" />
+      <feComposite
+         in2="result4"
+         in="result4"
+         operator="in"
+         result="result91"
+         id="feComposite5298" />
+      <feBlend
+         mode="darken"
+         in2="result91"
+         id="feBlend5300" />
+    </filter>
+    <filter
+       inkscape:menu-tooltip="Pressed metal with a rolled edge"
+       inkscape:menu="Bevels"
+       inkscape:label="Pressed Steel"
+       style="color-interpolation-filters:sRGB"
+       id="filter5302">
+      <feGaussianBlur
+         result="result1"
+         stdDeviation="3"
+         id="feGaussianBlur5304" />
+      <feBlend
+         in2="result1"
+         result="result5"
+         mode="multiply"
+         in="result1"
+         id="feBlend5306" />
+      <feGaussianBlur
+         in="result5"
+         result="result6"
+         stdDeviation="1"
+         id="feGaussianBlur5308" />
+      <feComposite
+         result="result8"
+         in2="result5"
+         in="result6"
+         operator="xor"
+         id="feComposite5310" />
+      <feComposite
+         in="result6"
+         result="fbSourceGraphic"
+         operator="xor"
+         in2="result8"
+         id="feComposite5312" />
+      <feSpecularLighting
+         in="fbSourceGraphic"
+         result="result1"
+         lighting-color="#ffffff"
+         surfaceScale="2"
+         specularConstant="2.20000005"
+         specularExponent="55"
+         id="feSpecularLighting5314">
+        <fePointLight
+           x="-5000"
+           y="-10000"
+           z="20000"
+           id="fePointLight5316" />
+      </feSpecularLighting>
+      <feComposite
+         in2="fbSourceGraphic"
+         in="result1"
+         result="result2"
+         operator="in"
+         id="feComposite5318" />
+      <feComposite
+         in="fbSourceGraphic"
+         result="result4"
+         operator="arithmetic"
+         k2="2"
+         k3="1"
+         in2="result2"
+         id="feComposite5320"
+         k1="0"
+         k4="0" />
+      <feComposite
+         in2="result4"
+         in="result4"
+         operator="in"
+         result="result91"
+         id="feComposite5322" />
+      <feBlend
+         mode="darken"
+         in2="result91"
+         id="feBlend5324" />
+    </filter>
+    <filter
+       inkscape:menu-tooltip="Pressed metal with a rolled edge"
+       inkscape:menu="Bevels"
+       inkscape:label="Pressed Steel"
+       style="color-interpolation-filters:sRGB"
+       id="filter5326">
+      <feGaussianBlur
+         result="result1"
+         stdDeviation="3"
+         id="feGaussianBlur5328" />
+      <feBlend
+         in2="result1"
+         result="result5"
+         mode="multiply"
+         in="result1"
+         id="feBlend5330" />
+      <feGaussianBlur
+         in="result5"
+         result="result6"
+         stdDeviation="1"
+         id="feGaussianBlur5332" />
+      <feComposite
+         result="result8"
+         in2="result5"
+         in="result6"
+         operator="xor"
+         id="feComposite5334" />
+      <feComposite
+         in="result6"
+         result="fbSourceGraphic"
+         operator="xor"
+         in2="result8"
+         id="feComposite5336" />
+      <feSpecularLighting
+         in="fbSourceGraphic"
+         result="result1"
+         lighting-color="#ffffff"
+         surfaceScale="2"
+         specularConstant="2.20000005"
+         specularExponent="55"
+         id="feSpecularLighting5338">
+        <fePointLight
+           x="-5000"
+           y="-10000"
+           z="20000"
+           id="fePointLight5340" />
+      </feSpecularLighting>
+      <feComposite
+         in2="fbSourceGraphic"
+         in="result1"
+         result="result2"
+         operator="in"
+         id="feComposite5342" />
+      <feComposite
+         in="fbSourceGraphic"
+         result="result4"
+         operator="arithmetic"
+         k2="2"
+         k3="1"
+         in2="result2"
+         id="feComposite5344"
+         k1="0"
+         k4="0" />
+      <feComposite
+         in2="result4"
+         in="result4"
+         operator="in"
+         result="result91"
+         id="feComposite5346" />
+      <feBlend
+         mode="darken"
+         in2="result91"
+         id="feBlend5348" />
+    </filter>
+    <filter
+       inkscape:menu-tooltip="Pressed metal with a rolled edge"
+       inkscape:menu="Bevels"
+       inkscape:label="Pressed Steel"
+       style="color-interpolation-filters:sRGB"
+       id="filter5350">
+      <feGaussianBlur
+         result="result1"
+         stdDeviation="3"
+         id="feGaussianBlur5352" />
+      <feBlend
+         in2="result1"
+         result="result5"
+         mode="multiply"
+         in="result1"
+         id="feBlend5354" />
+      <feGaussianBlur
+         in="result5"
+         result="result6"
+         stdDeviation="1"
+         id="feGaussianBlur5356" />
+      <feComposite
+         result="result8"
+         in2="result5"
+         in="result6"
+         operator="xor"
+         id="feComposite5358" />
+      <feComposite
+         in="result6"
+         result="fbSourceGraphic"
+         operator="xor"
+         in2="result8"
+         id="feComposite5360" />
+      <feSpecularLighting
+         in="fbSourceGraphic"
+         result="result1"
+         lighting-color="#ffffff"
+         surfaceScale="2"
+         specularConstant="2.20000005"
+         specularExponent="55"
+         id="feSpecularLighting5362">
+        <fePointLight
+           x="-5000"
+           y="-10000"
+           z="20000"
+           id="fePointLight5364" />
+      </feSpecularLighting>
+      <feComposite
+         in2="fbSourceGraphic"
+         in="result1"
+         result="result2"
+         operator="in"
+         id="feComposite5366" />
+      <feComposite
+         in="fbSourceGraphic"
+         result="result4"
+         operator="arithmetic"
+         k2="2"
+         k3="1"
+         in2="result2"
+         id="feComposite5368"
+         k1="0"
+         k4="0" />
+      <feComposite
+         in2="result4"
+         in="result4"
+         operator="in"
+         result="result91"
+         id="feComposite5370" />
+      <feBlend
+         mode="darken"
+         in2="result91"
+         id="feBlend5372" />
+    </filter>
+    <filter
+       inkscape:menu-tooltip="Pressed metal with a rolled edge"
+       inkscape:menu="Bevels"
+       inkscape:label="Pressed Steel"
+       style="color-interpolation-filters:sRGB"
+       id="filter5374">
+      <feGaussianBlur
+         result="result1"
+         stdDeviation="3"
+         id="feGaussianBlur5376" />
+      <feBlend
+         in2="result1"
+         result="result5"
+         mode="multiply"
+         in="result1"
+         id="feBlend5378" />
+      <feGaussianBlur
+         in="result5"
+         result="result6"
+         stdDeviation="1"
+         id="feGaussianBlur5380" />
+      <feComposite
+         result="result8"
+         in2="result5"
+         in="result6"
+         operator="xor"
+         id="feComposite5382" />
+      <feComposite
+         in="result6"
+         result="fbSourceGraphic"
+         operator="xor"
+         in2="result8"
+         id="feComposite5384" />
+      <feSpecularLighting
+         in="fbSourceGraphic"
+         result="result1"
+         lighting-color="#ffffff"
+         surfaceScale="2"
+         specularConstant="2.20000005"
+         specularExponent="55"
+         id="feSpecularLighting5386">
+        <fePointLight
+           x="-5000"
+           y="-10000"
+           z="20000"
+           id="fePointLight5388" />
+      </feSpecularLighting>
+      <feComposite
+         in2="fbSourceGraphic"
+         in="result1"
+         result="result2"
+         operator="in"
+         id="feComposite5390" />
+      <feComposite
+         in="fbSourceGraphic"
+         result="result4"
+         operator="arithmetic"
+         k2="2"
+         k3="1"
+         in2="result2"
+         id="feComposite5392"
+         k1="0"
+         k4="0" />
+      <feComposite
+         in2="result4"
+         in="result4"
+         operator="in"
+         result="result91"
+         id="feComposite5394" />
+      <feBlend
+         mode="darken"
+         in2="result91"
+         id="feBlend5396" />
+    </filter>
+    <filter
+       inkscape:menu-tooltip="Pressed metal with a rolled edge"
+       inkscape:menu="Bevels"
+       inkscape:label="Pressed Steel"
+       style="color-interpolation-filters:sRGB"
+       id="filter5398">
+      <feGaussianBlur
+         result="result1"
+         stdDeviation="3"
+         id="feGaussianBlur5400" />
+      <feBlend
+         in2="result1"
+         result="result5"
+         mode="multiply"
+         in="result1"
+         id="feBlend5402" />
+      <feGaussianBlur
+         in="result5"
+         result="result6"
+         stdDeviation="1"
+         id="feGaussianBlur5404" />
+      <feComposite
+         result="result8"
+         in2="result5"
+         in="result6"
+         operator="xor"
+         id="feComposite5406" />
+      <feComposite
+         in="result6"
+         result="fbSourceGraphic"
+         operator="xor"
+         in2="result8"
+         id="feComposite5408" />
+      <feSpecularLighting
+         in="fbSourceGraphic"
+         result="result1"
+         lighting-color="#ffffff"
+         surfaceScale="2"
+         specularConstant="2.20000005"
+         specularExponent="55"
+         id="feSpecularLighting5410">
+        <fePointLight
+           x="-5000"
+           y="-10000"
+           z="20000"
+           id="fePointLight5412" />
+      </feSpecularLighting>
+      <feComposite
+         in2="fbSourceGraphic"
+         in="result1"
+         result="result2"
+         operator="in"
+         id="feComposite5414" />
+      <feComposite
+         in="fbSourceGraphic"
+         result="result4"
+         operator="arithmetic"
+         k2="2"
+         k3="1"
+         in2="result2"
+         id="feComposite5416"
+         k1="0"
+         k4="0" />
+      <feComposite
+         in2="result4"
+         in="result4"
+         operator="in"
+         result="result91"
+         id="feComposite5418" />
+      <feBlend
+         mode="darken"
+         in2="result91"
+         id="feBlend5420" />
+    </filter>
+  </defs>
+  <sodipodi:namedview
+     inkscape:window-maximized="1"
+     inkscape:window-y="24"
+     inkscape:window-x="65"
+     inkscape:window-height="876"
+     inkscape:window-width="1535"
+     inkscape:snap-grids="false"
+     showguides="true"
+     inkscape:snap-bbox="false"
+     showgrid="true"
+     inkscape:current-layer="svg2"
+     inkscape:document-units="px"
+     inkscape:cy="482.82902"
+     inkscape:cx="440.18293"
+     inkscape:zoom="0.70000001"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     borderopacity="1.0"
+     bordercolor="#666666"
+     pagecolor="#ffffff"
+     id="base"
+     borderlayer="false"
+     inkscape:snap-to-guides="false"
+     inkscape:snap-intersection-paths="false"
+     inkscape:snap-page="false"
+     inkscape:snap-perpendicular="true"
+     inkscape:object-paths="false"
+     inkscape:object-nodes="false"
+     inkscape:snap-object-midpoints="false"
+     inkscape:snap-midpoints="true"
+     inkscape:snap-center="true"
+     inkscape:snap-global="false"
+     inkscape:connector-spacing="26"
+     inkscape:snap-others="true"
+     inkscape:snap-nodes="false"
+     inkscape:snap-bbox-midpoints="false"
+     inkscape:bbox-paths="false"
+     inkscape:bbox-nodes="false"
+     inkscape:snap-bbox-edge-midpoints="false"
+     inkscape:snap-text-baseline="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0">
+    <inkscape:grid
+       type="xygrid"
+       id="grid15208"
+       spacingx="20"
+       spacingy="20"
+       dotted="false"
+       empspacing="0"
+       originx="84.535615"
+       originy="-34.500034" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(56.035869,-48.362179)" />
+  <g
+     id="g7122">
+    <rect
+       ry="19.999998"
+       y="3.9999998"
+       x="346.03613"
+       height="39.999996"
+       width="100"
+       id="rect15298"
+       style="fill:#ff9b58;fill-opacity:1;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter5398)" />
+    <text
+       sodipodi:linespacing="100%"
+       id="text15304"
+       y="33.285709"
+       x="395.46545"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:27.5px;line-height:100%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       xml:space="preserve"><tspan
+         y="33.285709"
+         x="395.46545"
+         id="tspan15306"
+         sodipodi:role="line">Start</tspan></text>
+  </g>
+  <g
+     id="g7127">
+    <rect
+       ry="3.7605369e-06"
+       y="110.82932"
+       x="251.006"
+       height="74.345917"
+       width="290.06018"
+       id="rect15308"
+       style="fill:#ff9b58;fill-opacity:1;stroke:#000000;stroke-width:2.93979216;stroke-linecap:butt;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter5374)" />
+    <text
+       sodipodi:linespacing="100%"
+       id="text15310"
+       y="142.28799"
+       x="397.49304"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:27.5px;line-height:100%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       xml:space="preserve"><tspan
+         y="142.28799"
+         x="397.49304"
+         id="tspan15312"
+         sodipodi:role="line">Find</tspan><tspan
+         id="tspan15314"
+         y="169.78799"
+         x="397.49304"
+         sodipodi:role="line">\MGL@@@<script></tspan></text>
+  </g>
+  <g
+     id="g7133">
+    <rect
+       transform="matrix(0.73605839,-0.67691805,0.73605839,0.67691805,27.536121,2.4999998)"
+       ry="0"
+       y="434.159"
+       x="-37.940403"
+       height="104.421"
+       width="104.42103"
+       id="rect15316"
+       style="fill:#ff9b58;fill-opacity:1;stroke:#000000;stroke-width:2.61052561;stroke-linecap:butt;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter5350)" />
+    <text
+       sodipodi:linespacing="100%"
+       id="text15372"
+       y="309.45212"
+       x="396.24426"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:27.5px;line-height:100%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       xml:space="preserve"><tspan
+         y="309.45212"
+         x="396.24426"
+         id="tspan15374"
+         sodipodi:role="line">Is it</tspan><tspan
+         id="tspan15376"
+         y="336.95212"
+         x="396.24426"
+         sodipodi:role="line">defined?</tspan></text>
+  </g>
+  <g
+     id="g7149">
+    <rect
+       ry="3.5678115e-06"
+       y="458.73218"
+       x="66.625397"
+       height="70.535728"
+       width="214.82143"
+       id="rect15308-5"
+       style="fill:#ff9b58;fill-opacity:1;stroke:#000000;stroke-width:2.46426511;stroke-linecap:butt;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter5326)" />
+    <text
+       sodipodi:linespacing="100%"
+       id="text15310-7"
+       y="487.595"
+       x="173.32182"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:27.5px;line-height:100%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       xml:space="preserve"><tspan
+         y="487.595"
+         x="173.32182"
+         id="tspan15402"
+         sodipodi:role="line">Compare</tspan><tspan
+         y="515.09497"
+         x="173.32182"
+         id="tspan15404"
+         sodipodi:role="line">script vs. code</tspan></text>
+  </g>
+  <rect
+     style="fill:#ff9b58;fill-opacity:1;stroke:#000000;stroke-width:2.6016953;stroke-linecap:butt;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter5302)"
+     id="rect15308-5-1"
+     width="261.11255"
+     height="64.684021"
+     x="483.47986"
+     y="461.65802"
+     ry="3.2718219e-06" />
+  <g
+     id="g7155">
+    <text
+       sodipodi:linespacing="100%"
+       id="text15310-7-8"
+       y="487.8367"
+       x="615.10748"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:27.5px;line-height:100%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       xml:space="preserve"><tspan
+         y="487.8367"
+         x="615.10748"
+         id="tspan15430"
+         sodipodi:role="line">Rewrite/recompile</tspan><tspan
+         y="515.33667"
+         x="615.10748"
+         id="tspan15432"
+         sodipodi:role="line">script</tspan></text>
+  </g>
+  <g
+     id="g7177">
+    <rect
+       ry="3.7605369e-06"
+       y="802.82477"
+       x="469.00604"
+       height="74.345917"
+       width="290.06018"
+       id="rect15308-58"
+       style="fill:#ff9b58;fill-opacity:1;stroke:#000000;stroke-width:2.93979216;stroke-linecap:butt;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter5230)" />
+    <text
+       sodipodi:linespacing="100%"
+       id="text15310-2"
+       y="833.83441"
+       x="615.46466"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:27.5px;line-height:100%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       xml:space="preserve"><tspan
+         y="833.83441"
+         x="615.46466"
+         id="tspan15538"
+         sodipodi:role="line">Undefine</tspan><tspan
+         y="861.33441"
+         x="615.46466"
+         id="tspan15540"
+         sodipodi:role="line">\MGL@@@<script></tspan></text>
+  </g>
+  <g
+     id="g7183">
+    <rect
+       ry="3.7605369e-06"
+       y="802.82477"
+       x="29.006018"
+       height="74.345917"
+       width="290.06018"
+       id="rect15308-7"
+       style="fill:#ff9b58;fill-opacity:1;stroke:#000000;stroke-width:2.93979216;stroke-linecap:butt;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter5254)" />
+    <text
+       sodipodi:linespacing="100%"
+       id="text15310-4"
+       y="833.83441"
+       x="175.46468"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:27.5px;line-height:100%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       xml:space="preserve"><tspan
+         y="833.83441"
+         x="175.46468"
+         id="tspan15534"
+         sodipodi:role="line">Define</tspan><tspan
+         y="861.33441"
+         x="175.46468"
+         id="tspan15536"
+         sodipodi:role="line">\MGL@@@<script></tspan></text>
+  </g>
+  <g
+     id="g7189">
+    <rect
+       ry="19.999998"
+       y="944"
+       x="346.03613"
+       height="39.999996"
+       width="100"
+       id="rect15298-0"
+       style="fill:#ff9b58;fill-opacity:1;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter5206)" />
+    <text
+       sodipodi:linespacing="100%"
+       id="text15304-3"
+       y="973.28571"
+       x="395.93542"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:27.5px;line-height:100%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       xml:space="preserve"><tspan
+         y="973.28571"
+         x="395.93542"
+         id="tspan15563"
+         sodipodi:role="line">End</tspan></text>
+  </g>
+  <g
+     id="g7160">
+    <rect
+       transform="matrix(0.73605839,-0.67691805,0.73605839,0.67691805,27.536121,2.4999998)"
+       ry="0"
+       y="688.14459"
+       x="-291.92599"
+       height="104.421"
+       width="104.42103"
+       id="rect15316-5"
+       style="fill:#ff9b58;fill-opacity:1;stroke:#000000;stroke-width:2.61052561;stroke-linecap:butt;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter5278)" />
+    <text
+       sodipodi:linespacing="100%"
+       id="text15372-1"
+       y="638.30701"
+       x="396.24426"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:27.5px;line-height:100%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       xml:space="preserve"><tspan
+         y="638.30701"
+         x="396.24426"
+         id="tspan4665"
+         sodipodi:role="line">Are</tspan><tspan
+         y="665.80701"
+         x="396.24426"
+         id="tspan4667"
+         sodipodi:role="line">they</tspan><tspan
+         y="693.30701"
+         x="396.24426"
+         id="tspan4669"
+         sodipodi:role="line">equal?</tspan></text>
+  </g>
+  <path
+     style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.69868755;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker5662)"
+     d="m 395.9522,47.234559 0,53.132841"
+     id="path9635"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="cc" />
+  <path
+     style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.69473767;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker5654)"
+     d="m 395.9522,190.82724 0,52.17876"
+     id="path9668"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="cc" />
+  <path
+     style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.86969066;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker4704)"
+     d="m 315.68408,322.10132 -141.74819,0 0,127.04843"
+     id="path9880"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="ccc" />
+  <path
+     style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.90597177;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker4532)"
+     d="m 476.42192,322.11395 143.13726,0 0,129.01695"
+     id="path9880-8"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="ccc" />
+  <path
+     style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.86277986;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker4882)"
+     d="m 285.54764,497.48577 110.78038,-0.67102 0,90.05069"
+     id="path11097"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="ccc" />
+  <path
+     style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.87530303;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker5066)"
+     d="m 474.89723,666.42636 144.27202,0 0,125.31464"
+     id="path9880-87"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="ccc" />
+  <path
+     style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.86618733;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker5256)"
+     d="m 315.35785,665.6901 -142.51657,0 0,126.05511"
+     id="path9880-4"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="ccc" />
+  <path
+     style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.91920161;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+     d="m 323.53587,843.28574 140,0"
+     id="path12272"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.93609476;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker5452)"
+     d="m 396.03587,843.28574 0,93.04832"
+     id="path12293"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:"
+     d="m 618.89301,527.57146 0,37.14285 -202.85714,-0.71428 c 0,0 -19.14012,-27.19021 -39.21292,-0.0237 l -203.28708,0.38084 -0.35715,101.42857"
+     id="path12941"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="cccccc" />
+  <g
+     id="g7144">
+    <rect
+       ry="20"
+       y="301.21429"
+       x="214.67897"
+       height="40"
+       width="71.428574"
+       id="rect5520"
+       style="fill:#ffe3d0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <text
+       sodipodi:linespacing="100%"
+       id="text5522"
+       y="329.78571"
+       x="227.53612"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:27.5px;line-height:100%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;"
+       xml:space="preserve"><tspan
+         y="329.78571"
+         x="227.53612"
+         id="tspan5524"
+         sodipodi:role="line">Yes</tspan></text>
+  </g>
+  <g
+     id="g7172">
+    <rect
+       ry="20"
+       y="644.64282"
+       x="213.2504"
+       height="40"
+       width="71.428574"
+       id="rect5520-4"
+       style="fill:#ffe3d0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <text
+       sodipodi:linespacing="100%"
+       id="text5522-9"
+       y="673.21423"
+       x="226.10754"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:27.5px;line-height:100%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;"
+       xml:space="preserve"><tspan
+         y="673.21423"
+         x="226.10754"
+         id="tspan5524-4"
+         sodipodi:role="line">Yes</tspan></text>
+  </g>
+  <g
+     id="g7167">
+    <rect
+       ry="20"
+       y="644.07141"
+       x="507.5361"
+       height="40"
+       width="71.428574"
+       id="rect5520-7"
+       style="fill:#ffe3d0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <text
+       sodipodi:linespacing="100%"
+       id="text5522-6"
+       y="674.07141"
+       x="524.67896"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:27.5px;line-height:100%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;"
+       xml:space="preserve"><tspan
+         y="674.07141"
+         x="524.67896"
+         id="tspan5586"
+         sodipodi:role="line">No</tspan></text>
+  </g>
+  <g
+     id="g7139">
+    <rect
+       ry="20"
+       y="301.21426"
+       x="506.10754"
+       height="40"
+       width="71.428574"
+       id="rect5520-7-3"
+       style="fill:#ffe3d0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <text
+       sodipodi:linespacing="100%"
+       id="text5522-6-9"
+       y="331.21423"
+       x="523.25037"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:27.5px;line-height:100%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;"
+       xml:space="preserve"><tspan
+         y="331.21423"
+         x="523.25037"
+         id="tspan5586-2"
+         sodipodi:role="line">No</tspan></text>
+  </g>
+</svg>
diff --git a/mgltex/mgltex.dtx b/mgltex/mgltex.dtx
new file mode 100644
index 0000000..d50fa82
--- /dev/null
+++ b/mgltex/mgltex.dtx
@@ -0,0 +1,3093 @@
+% \iffalse meta-comment
+%
+% Copyright (C) 2014--2016 by Diego Sejas Viscarra <dsejas.mathematics at gmail.com>
+% Copyright (C) 2014--2016 by Alexey Balakin <mathgl.abalakin at gmail.com>
+%
+% This program is free software: you can redistribute it and/or modify it
+% under the terms of the GNU General Public License as published by the
+% Free Software Foundation, either version 3 of the License, or (at your
+% option) any later version.
+%
+% This program is distributed in the hope that it will be useful, but
+% WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+% Public License for more details.
+% 
+% You should have received a copy of the GNU General Public License along
+% with this program. If not, see <http://www.gnu.org/licenses/>.
+%
+% \fi
+%
+% \iffalse
+%
+%<package>
+%<package>\NeedsTeXFormat{LaTeX2e}
+%<package>\ProvidesPackage{mgltex}[2016/04/26 v4.2 Embed MGL scripts into LaTeX documents]
+%<package>
+%
+%<*driver>
+\documentclass[10pt]{ltxdoc}
+\usepackage{color}
+\usepackage{mgltex}
+\DeclareRobustCommand\mglTeX{mgl\kern-0.04em\TeX}% Otherwise, incompatibility with \CharacterTable
+\IfFileExists{hyperref.sty}{%
+  \usepackage[hidelinks]{hyperref}%
+}{}
+\EnableCrossrefs
+\CodelineIndex
+\RecordChanges
+\widowpenalty=10000
+\clubpenalty=10000
+\begin{document}
+  \DocInput{mgltex.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \CheckSum{0}
+%
+%
+% \CharacterTable
+%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%   Digits        \0\1\2\3\4\5\6\7\8\9
+%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%   Dollar        \$     Percent       \%     Ampersand     \&
+%   Acute accent  \'     Left paren    \(     Right paren   \)
+%   Asterisk      \*     Plus          \+     Comma         \,
+%   Minus         \-     Point         \.     Solidus       \/
+%   Colon         \:     Semicolon     \;     Less than     \<
+%   Equals        \=     Greater than  \>     Question mark \?
+%   Commercial at \@     Left bracket  \[     Backslash     \\
+%   Right bracket \]     Circumflex    \^     Underscore    \_
+%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%   Right brace   \}     Tilde         \~}
+%
+% \bgroup%
+%   \makeatletter%
+%   \gdef\MGL at set@pseudo at verb@env{%
+%     \if at minipage\else\vskip\parskip\fi%
+%     \setlength{\labelsep}{1em}%
+%     \@beginparpenalty\predisplaypenalty%
+%     \leftskip\@totalleftmargin\rightskip\z@%
+%     \parindent\z@\parfillskip\@flushglue\parskip\z@%
+%     \itemsep\z@%
+%     \@@par%
+%     \def\par{%
+%       \if at tempswa%
+%         \leavevmode\null\@@par\penalty\interlinepenalty%
+%       \else%
+%         \@tempswatrue%
+%         \ifhmode\@@par\penalty\interlinepenalty\fi%
+%       \fi%
+%     }%
+%     \ttfamily%
+%     \frenchspacing%
+%   }%
+%   \makeatother
+% \egroup
+%
+%	\def\doccommand#1{\texttt{\textbackslash#1}}
+%
+% \changes{\textbf{v1.0 ------------}}{2014/09/27}{Initial version}
+%
+%
+% \changes{\textbf{v2.0 ------------}}{2014/11/23}{Possible bugfix by adding \doccommand{expandafter} to commands to ignore/write lines of MGL code}
+% \changes{\textbf{v2.0 ------------}}{2014/11/23}{Add environment \texttt{mglsignature} that adds a comment to every MGL script}
+% \changes{\textbf{v2.0 ------------}}{2014/11/23}{Eliminate line ignoring commands to create more elegant scripts, due to the a new command that adds comments to the scripts}
+% \changes{\textbf{v2.0 ------------}}{2014/11/23}{Move the MGL \emph{stop} command from the \texttt{\textbackslash{}AtEndDocument} command to the \doccommand{mgl at func} buffer}
+%
+%
+% \changes{\textbf{v3.0 ------------}}{2015/03/29}{Add detection of changes in MGL scripts to speed up compilation time (only changed scripts are recompiled)}
+% \changes{\textbf{v3.0 ------------}}{2015/03/29}{Add command \doccommand{mgldir}, \doccommand{mglscriptsdir}, \doccommand{mglgraphicsdir} and \doccommand{mglbackupsdir} to specify a main directory for \textsf{\mglTeX} and directories for the creation of scripts, graphics and backups}
+% \changes{\textbf{v3.0 ------------}}{2015/03/29}{Add the \doccommand{mglquality} command to specify a default quality}
+% \changes{\textbf{v3.0 ------------}}{2015/03/29}{Add the \doccommand{mglwidth} and \doccommand{mglheight} commands to specify the default size of the images produced}
+% \changes{\textbf{v3.0 ------------}}{2015/03/29}{Add the \doccommand{mglsettings} command to configure behavior of the package}
+% \changes{\textbf{v3.0 ------------}}{2015/03/29}{Improve environment \texttt{mglsignature} by adding the possibility of using \LaTeX{} commands inside it}
+%
+%
+% \changes{\textbf{v4.0 ------------}}{2015/08/17}{Complete rewrite of \textsf{\mglTeX}}
+% \changes{\textbf{v4.0 ------------}}{2015/08/17}{\textsf{\mglTeX} now depends of the \textsf{verbatim} package}
+% \changes{\textbf{v4.0 ------------}}{2015/08/17}{All environments write their contents \emph{verbatim}}
+% \changes{\textbf{v4.0 ------------}}{2015/08/17}{Add package options \texttt{0q}, \ldots, \texttt{8q} to specify quality}
+% \changes{\textbf{v4.0 ------------}}{2015/08/17}{Add the \doccommand{mglpaths} command to add directories to the search paths for MGL scripts}
+% \changes{\textbf{v4.0 ------------}}{2015/08/17}{Add the \doccommand{mglname} command to force clousure of the current main script, its compilation, and the opening of a new main script}
+% \changes{\textbf{v4.0 ------------}}{2015/08/17}{Add the option \texttt{label} to the \texttt{mgl} environment in order to override the automatic naming of the script and corresponding image}
+% \changes{\textbf{v4.0 ------------}}{2015/08/17}{Add the option \texttt{label} to the \texttt{mglverbatim} environment to name the verbatim code}
+% \changes{\textbf{v4.0 ------------}}{2015/08/17}{Add the option \texttt{separator} to the command \doccommand{mglplot} to brake the code into different physical text lines}
+% \changes{\textbf{v4.0 ------------}}{2015/08/17}{Add the option \texttt{path} to the commands \doccommand{mglgraphics} and \doccommand{mglinclude} to force a path to search MGL scripts}
+% \changes{\textbf{v4.0 ------------}}{2015/08/17}{Verbatim-like environments and \doccommand{mglinclude} command are more visually elegant now}
+% \changes{\textbf{v4.0 ------------}}{2015/08/17}{Numbering in verbatim-like environments is optional now}
+% \changes{\textbf{v4.0 ------------}}{2015/08/17}{Add the command \doccommand{listofmglscripts} to create a list of all MGL scripts included verbatim in the document}
+% \changes{\textbf{v4.0 ------------}}{2015/08/17}{Add the command \doccommand{mglTeXwVer} that prints the name of the package with its version in a coherent manner, and separated by an unbreakable space}
+% \changes{\textbf{v4.0 ------------}}{2015/08/17}{Verbatim-like environments and the \doccommand{mglinclude} command have starred versions wich prevent the command \doccommand{listofmglscripts} to list them}
+% \changes{\textbf{v4.0 ------------}}{2015/08/17}{Remove \texttt{mglsignature} environment for being considered useless, and to avoid interference with the detection of changes in MGL scripts, to speed up script writing and to make the package less resource-consuming}
+% \changes{\textbf{v4.0 ------------}}{2015/08/17}{Remove the \doccommand{mglwidth} and \doccommand{mglheight} commands for being considered useless}
+% \changes{\textbf{v4.0 ------------}}{2015/08/17}{Many improvements, including, but not limited to, speed up, increased coherence and cleanness of the code, less resource consumption}
+% \changes{\textbf{v4.0 ------------}}{2015/08/17}{Many bugfixes}
+%
+%
+% \changes{\textbf{v4.1 ------------}}{2016/01/28}{Add the command \doccommand{mglimgext} to specify locally the extension to save the generated graphics}
+% \changes{\textbf{v4.1 ------------}}{2016/01/28}{Add the command \doccommand{mglswitch}, which replaces \doccommand{mgltexon} and \doccommand{mgltexoff}}
+% \changes{\textbf{v4.1 ------------}}{2016/01/28}{Rename the commands \doccommand{mgltexon} as \doccommand{MGL at switch@on} and \doccommand{mgltexoff} as \doccommand{MGL at switch@off} in order to avoid the user from unpurposely overwriting them}
+% \changes{\textbf{v4.1 ------------}}{2016/01/28}{The command \doccommand{mglcomments} has been reimplemented to accept one mandatory argument: \doccommand{mglcomments\{on\}} replaces the old \doccommand{mglcomments}, while \doccommand{mglcomments\{off\}} replaces the old \doccommand{mglnocomments}}
+% \changes{\textbf{v4.1 ------------}}{2016/01/28}{Remove the command \doccommand{mglnocomments} (rendered useless by the new implementation of \doccommand{mglcomments})}
+% \changes{\textbf{v4.1 ------------}}{2016/01/28}{Remove the command \doccommand{mglTeXwVer} (rendered useless by the implementation of the starred version of \doccommand{mglTeX})}
+% \changes{\textbf{v4.1 ------------}}{2016/01/28}{Restore the command \doccommand{mglsettings}, which was unintentionally deleted in version~4.0}
+% \changes{\textbf{v4.1 ------------}}{2016/01/28}{Expand the key-val list family for the command \doccommand{mglsettings}}
+% \changes{\textbf{v4.1 ------------}}{2016/01/28}{Reimplement the \doccommand{@MGL at comments@} switch}
+% \changes{\textbf{v4.1 ------------}}{2016/01/28}{A starred version of the command \doccommand{mglTeX} has been implemented, which prints the version of the package besides its name}
+%
+%
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{New package options \texttt{gray}, \texttt{color} to activate/deactivate gray-scale mode for graphics}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{New package options \texttt{0v}, \texttt{1v}, \texttt{2v} to select variant of arguments in MGL scripts}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{New package option \texttt{9q} for setting quality to \texttt{9} (for testing purposes of the author)}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{New commands: \doccommand{mglgray} (to activate/deactivate) gray-scale mode locally, and \doccommand{mglvariant} (to set variant of arguments in MGL scripts locally)}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{Rename environment \texttt{mglcommon} to \texttt{mglsetupscript} (\texttt{mglcommon} is still available, but deprecated)}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{Rename command \doccommand{mglcommonscriptname} to \texttt{mglsetupscriptname}}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{Rename command \doccommand{MGL at graph@ext} to \doccommand{MGL at imgext}}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{Rename family \texttt{MGL at keys} as \texttt{MGL at gr@keys} for consistency}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{Reorganize and update documentation}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{\mglTeX{} now depends on the \texttt{ifpdf} package}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{The MGL code line \texttt{setsize~600~400} is now automatically written to the main script in order for the scaling options and commands to work}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{Remove the \doccommand{MGL at setkeys} command, since it isn't needed as first thought}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{Some minor bugfixes}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{Change definition of \doccommand{mglcommentname} from \emph{MGL comment} to \emph{\mglTeX{} comment}}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{Rename \doccommand{MGL at document@scripts} to \doccommand{MGL at doc@scripts}}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{Rename \doccommand{MGL at script@name} tp \doccommand{MGL at script}}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{Introduce the concept of \emph{global}, \emph{local} and \emph{private} settings in the documentation}
+%
+% \GetFileInfo{mgltex.sty}
+%
+% \DoNotIndex{\def,\bgroup,\egroup,\newcommand,\newenvironment,\\,\@onlypreamble,\@undefined,\@vobeyspaces,\list}
+% \DoNotIndex{\if,\else,\fi,\begingroup,\endgroup,\end,\edef,\xdef,\gdef,\scapechar,\active,\arabic,\catcode,\bfseries}
+% \DoNotIndex{\@flushglue,\@for,\@ifnextchar,\@makeother,\{,\},\ ,\AtBeginDocument,\AtEndDocument,\centering}
+% \DoNotIndex{\closein,\closeout,\csname,\endcsname,\CurrentOption,\DeclareGraphicsExtensions,\define at key,\DeclareOption}
+% \DoNotIndex{\detokenize,\do,\dospecials,\endlinechar,\endlist,\escapechar,\ExecuteOptions,\expandafter,\footnotesize}
+% \DoNotIndex{\framebox,\Huge,\ifeof,\IfFileExists,\ifx,\immediate,\include,\includegraphics,\item,\itemsep}
+% \DoNotIndex{\itshape,\jobname,\labelsep,\leftskip,\let,\long,\mbox,\newcounter,\newread,\newtoks,\newwrite,\noexpand}
+% \DoNotIndex{\obeyspaces,\openin,\openout,\PackageError,\PackageWarning,\parfillskip,\parindent,\parskip}
+% \DoNotIndex{\PassOptionsToPackage,\ProcessOptions,\read,\relax,\RequirePackage,\rightskip,\setcounter,\setkeys,\setlength}
+% \DoNotIndex{\space,\stepcounter,\string,\TeX,\the,\vbox,\verbatim at font,\write,\z@,\z at skip,\newif,\PackageInfo,\today}
+% \DoNotIndex{\obeylines,\or,\ifcase,\small,\vskip,\section,\refstepcounter,\protect,\pretolerance,\penalty,\ttfamily}
+% \DoNotIndex{\@@par,\@@,\@M,\@addtofilelist,\@auxout,\@bsphack,\@dottedtocline,\@empty,\@esphack,\@fornoop,\@fortmp}
+% \DoNotIndex{\@gobble,\@ifundefined,\@mkboth,\@namedef,\@nil,\@nnil,\@noitemerr,\@plus,\@pnumwidth,\@secpenalty}
+% \DoNotIndex{\@startsection,\@starttoc,\@tempdima,\@tempswatrue,\@totalleftmargin,\@unknownoptionerror,\@xobeysp}
+% \DoNotIndex{\^,\addcontentsline,\addpenalty,\addvspace,\advance,\begin,\c at tocdepth,\center,\chapter,\cleaders}
+% \DoNotIndex{\endcenter,\everypar,\fbox,\fboxrule,\frenchspacing,\g at addto@macro,\global,\hb at xt@,\hbadness,\hfil,\hfill}
+% \DoNotIndex{\hrule,\hskip,\hss,\if at minipage,\if at tempswa,\ifhmode,\ifnum,\interlinepenalty,\itemindent,\kern,\l at chapter}
+% \DoNotIndex{\l at section,\large,\leavevmode,\MakeUppercase,\newdimen,\nobreak,\nopagebreak,\normalfont,\null,\numberline}
+% \DoNotIndex{\p@,\par,\unpenalty,\usecounter,\@ifstar,\^,\iffalse,\iftrue,\ifpdf}
+%
+% \title{The \textsf{\mglTeX} package\thanks{This document corresponds to \textsf{\mglTeX}~\fileversion, dated \filedate.}}
+% \author{Diego Sejas Viscarra\\\texttt{dsejas.mathematics at gmail.com}}
+%
+% \maketitle
+%
+% \begin{abstract}
+% \noindent MathGL is a fast and efficient library by Alexey Balakin for the creation of high-quality publication-ready scientific graphics. Although it defines interfaces for many programming languages, it also implements its own scripting language, called \emph{MGL}, which can be used independently. With the package \textsf{\mglTeX}, MGL scripts can be embedded within any \LaTeX{} document, and the corresponding images are automatically created and included.
+%
+% This manual documents the usage of the commands and environments of~\textsf{\mglTeX}.
+% \end{abstract}
+%
+% \tableofcontents
+%
+% \section{Introduction}
+% \noindent MathGL is a fast and efficient library by Alexey Balakin for the creation of high-quality publication-ready scientific graphics. It implements more than $50$ different types of graphics for 1d, 2d and 3d large sets of data. It supports exporting images to bitmap formats (PNG, JPEG, BMP, etc.), or vector formats (EPS, \TeX, SVG, etc.), or 3d image formats (STL, OBJ, XYZ, etc.), and even its own native 3d format, MGLD. MathGL also defines its own vector font specification forma [...]
+%
+% MathGL has interfaces for a wide variety of programming languages, such as C/C++, Fortran, Python, Octave, Pascal, Forth, and many others, but it also defines its own scripting language, called \emph{MGL}, which can be used to generate graphics independently of any programming language. The \textsf{\mglTeX} package adds support to embed MGL code inside \LaTeX{} documents, which is automatically extracted and executed, and the resulting images are included in the document.
+%
+% Besides the obvious advantage of having available all the useful features of MathGL, \textsf{\mglTeX} facilitates the maintenance of your document, since both code for text and code for graphics are contained in a single file.
+%
+% \subsection{Conventions and notations}
+% \noindent For what's left of this manual, the symbols ``$\langle$'' and ``$\rangle$'' will enclose the description of an object that should be placed in that location; this is called a \emph{meta-variable}. For example, $\meta{text}$ is a meta-variable that indicates that in that location should be placed any form of text.
+%
+% In order to save space and time, some special conventions should be applied to meta-variables:
+% \begin{enumerate}
+%   \item Any meta-variable that contain the word \emph{directory} indicates the name of a directory, in the form of an absolute or relative path, ending with the slash (``/'') character.
+%   \item Any meta-variable that contain the word \emph{subdirectory} indicates a relative path ending with the slash (``/'') character.
+%   \item \meta{$x_1\vert x_2\vert\ldots\vert x_n$} indicates that any of the values $x_1$, $x_2$, \ldots, $x_n$ can be placed there. A special case is \meta{$x_1\vert x_2\vert\ldots$}, where no upper limit is set.
+%   \item The possible values of a meta-variable could also be indicated by a property. For example \meta{$x:x>0$} indicates that any positive value can be used in that location.
+%   \item A meta-variable of the form \meta{list of something} or \meta{something list} indicate a comma-separated list of values of type $\meta{something}$; if only one value is used, no comma is needed.
+% \item A meta-variable with underscores (``|_|'') in its description indicate that spaces should not be used in that location.
+% \item \meta{key-val list} refers to a list of \meta{key}=\meta{value} pairs of options, where \meta{key} is a keyword name for an option and \meta{value} is a value assigned to it.
+% \end{enumerate}
+%
+% As is conventional for \LaTeX{} packages, the environments and commands defined by \textsf{\mglTeX} accept optional commands inside brackets ("|[|" and "|]|"), and mandatory arguments inside curly braces ("|{|" and "|}|").
+%
+% While reading the following, it must be noted that most of \textsf{\mglTeX} settings have three modes: global, local and private. A setting is \emph{global} if it applies to the whole document, it is \emph{local} if it applies to the document from one point onwards, and it is \emph{private} if it applies only to a particular MGL script. Global settings are set thorugh package options or with the command |\mglsettings| (explained later), local settings have associated commands (subsecti [...]
+%
+% \section{Usage}
+% \noindent The simplest way to load \textsf{\mglTeX} to a \LaTeX{} document is to write the command
+% \begin{center}
+%   |\usepackage{mgltex}|
+% \end{center}
+% in the preamble. Alternatively, one can pass a number of options to the package by means of the syntax
+% \begin{center}
+% |\usepackage|\oarg{options list}|{mgltex}|,  
+% \end{center}
+% where \meta{options list} can contain one or more of the following options:
+% \begin{itemize}
+%   \item \textbf{draft:} The generated images won't be included in the document. This option is useful when fast compilation of the document is needed.
+%   \item \textbf{final:} Overrides the |draft| option.
+%   \item \textbf{on:} To rewrite, recompile and include the changed MGL scripts and/or corresponding graphics.
+%   \item \textbf{off:} To avoid creation, compilation and/or inclusion of the MGL scripts and corresponding images.
+%   \item \textbf{comments:} To allow the contents of the |mglcomment| environments to be shown in the \LaTeX{} document.
+%   \item \textbf{nocomments:} To avoid showing the contents of the |mglcomment| environments in the \LaTeX{} document.
+%   \item \textbf{gray:} To create the MGL graphics in gray-scale mode.
+%   \item \textbf{color:} To create the MGL graphics in color mode.
+%   \item \textbf{1x, \ldots, 9x:} To specify the scale for the creation of graphics (|1x| is normal scaling, |2x| is twice as bigger, etc).
+%   \item \textbf{0q, \ldots, 9q:} To specify the quality for the creation of graphics. An info message indicating the characteristics of the chosen quality is printed in the .log file according to the following table:
+% \begin{center}
+%   \DeleteShortVerb{\|}
+%   \begin{tabular}{|c|l|}
+%     \hline
+%     Quality & Description\\
+%     \hline
+%     \hline
+%     $0$ & No face drawing (fastest)\\
+%     \hline
+%     $1$ & No color interpolation (fast)\\
+%     \hline
+%     $2$ & High quality (normal)\\
+%     \hline
+%     $3$ & High quality with 3d primitives (not implemented yet)\\
+%     \hline
+%     $4$ & No face drawing, direct bitmap drawing (low memory usage)\\
+%     \hline
+%     $5$ & No color interpolation, direct bitmap drawing (low memory usage)\\
+%     \hline
+%     $6$ & High quality, direct bitmap drawing (low memory usage)\\
+%     \hline
+%     $7$ & High quality with 3d primitives, direct bitmap drawing\\
+%     & (not implemented yet)\\
+%     \hline
+%     $8$ & Draw dots instead of primitives (extremely fast)\\
+%     \hline
+%     $9$ & No drawing (for testing purposes)\\
+%     \hline
+%   \end{tabular}
+%   \MakeShortVerb{\|}
+% \end{center}
+%   \item \textbf{0v, 1v, 2v:} To set the default variant of arguments for the MGL commands.
+%   \item \textbf{png, jpg, jpeg:} To export images to a bitmap format.
+%   \item \textbf{eps, epsz:} To export to uncompressed/compressed vectorial EPS format.
+%   \item \textbf{bps, bpsz:} To export to uncompressed/compressed bitmap EPS format.
+%   \item \textbf{pdf:} To export to 3D PDF format.
+%   \item \textbf{tex:} To export to \LaTeX{}/\emph{tikz} document.
+% \end{itemize}
+% If two or more mutually exclusive options are specified, only the last one will be used by \textsf{\mglTeX}. For example, if one specifies the options |0q|, |3q| and |8q|---in that order---, then the quality will be set to $8$.
+%
+% Observe the |off| option is similar to the |draft| option, with the exception that |draft| deactivates inclusion of graphics for the \textsf{\mglTeX} and \textsf{graphicx} packages simultaneously, while the |off| option only deactivates \textsf{\mglTeX} functionalities (creation and/or inclusion of scripts and graphics), not affecting \textsf{graphicx}. This could be useful to recognize which images are created with MGL, and which are only included. Another possible use for this option [...]
+%
+% There are two ways to compile a document with \textsf{\mglTeX}: The first way is to run
+% \begin{center}
+%   |latex --shell-escape |\meta{document}|.tex|
+% \end{center}
+% three times, since the first run will detect changes in the scripts; the second run will extract the MGL code, execute it and include some of the resulting graphics, while the third run will include the remaining graphics. The second way is to run
+% \begin{center}
+%   |latex |\meta{document}|.tex|
+% \end{center}
+% twice to detect changes in MGL code and to extract it, then compile the generated scripts with the program |mglconv| (part of MathGL bundle), and execute |latex |\meta{document}|.tex| once more to include the graphics.\footnote{If no changes were made to scripts intended to create graphics, only one \LaTeX{} run is needed.} (More on the recompilation-decision mechanism of \textsf{\mglTeX} can be found in subsection~\ref{subsection: recompilation decision}.)
+%
+% \subsection{Warning for the user}\label{subsection: warning}
+% Before we continue the description of the package, it must be pointed out that \textsf{\mglTeX} assummes that the command |\end{|\meta{MGL environment}|}|, that ends the corresponding \meta{MGL environment}, occupies its own physical line of \LaTeX{} code. So the correct forms of use of environments are the following:
+% \begin{quote}
+%|\begin{|\meta{MGL environment}|}|\\
+%\meta{contents of the environment}\\
+%|\end{|\meta{environment}|}|
+% \end{quote}
+% and
+% \begin{quote}
+%|\begin{|\meta{MGL environment}|}|\meta{contents of the environment}\\
+%|\end{|\meta{environment}|}|
+% \end{quote}
+% The following form will cause problems:
+% \begin{quote}
+%|\begin{|\meta{MGL environment}|}|\meta{contents of the environment}|\end{|\meta{MGL environment}|}|
+% \end{quote}
+%
+% \textsf{\mglTeX} depends on the \textsf{verbatim} package to define its environments. One of the characteristics of \textsf{verbatim} is that it transcripts everything contained between the begining and the end of an environment, including spaces before an |\end{|\meta{MGL environment}|}| command. This should not be a problem, except for the fact that \textsf{\mglTeX} has a mechanism to detect changes in MGL scripts in order to recompile them (see subsection \ref{subsection: recompilat [...]
+%
+% It should also be pointed out that the default behavior of the |verbatim| package makes the following form to ignore the \meta{text} after the |\end|\meta{MGL environment}, issuing a warning.
+% \begin{quote}
+%|\begin{|\meta{MGL environment}|}|\\
+%\meta{contents of the environment}\\
+%|\end{|\meta{MGL environment}|}|\meta{text}
+% \end{quote}
+%
+% \subsection{Environments for MGL code embedding}
+% \DescribeEnv{mgl}\noindent The main environment defined by \textsf{\mglTeX} is |mgl|. It extracts its contents to a main script, called \meta{main\_script\_name}.mgl, where \meta{main\_script\_name} stands for a name specified by the user with the |\mglname| command (explained later), or the name of the \LaTeX{} document being executed otherwise; this script is compiled, and the corresponding image is included.
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\begin{mgl}|\oarg{key-val list}\\[0.5em]
+%       \hss\meta{MGL code}\hss\\[0.5em]
+%     |\end{mgl}|\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+% Here, \meta{key-val list} can have the following optional arguments:
+% \begin{itemize}
+%   \item \textbf{bb, bbllx, bblly, bburx, bbury, natwidth, natheight, hiresbb, viewport, trim, angle, origin, width, height, totalheight, keepaspectratio, scale, clip, draft, type, ext, read, command:} These are the same options of the |\includegraphics| command from the \textsf{graphicx} package.
+%   \item \textbf{gray:} Can be used to activate (|gray=on| or |gray=1|) or deactivate (|gray=off| or |gray=0|) gray-scale mode privately (only for the current graphic).
+%   \item \textbf{mglscale:} Any positive value for this option is used to physically scale the resulting image file, i.g., |mglscale=2| will create an image file twice as bigger.
+%   \item \textbf{quality:} Sets the quality of the current graphic. Valid values are integers between |0| and |9|.
+%   \item \textbf{variant:} Sets the variant of argument for the commands in the current script.
+%   \item \textbf{imgext:} Can be used to set the extension for the current image.
+%   \item \textbf{label:} Can be used to indicate a name for the corresponding graphic (otherwise, an automatic naming will be applied)
+% \end{itemize}
+%
+% \DescribeEnv{mgladdon} This environment adds its contents to the document's main script, but it doesn't produce any image. It doesn't require any kind of arguments. It is useful to add ``complementary code'', like instructions to load dynamic libraries, set default size for the graphics, etc.
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\begin{mgladdon}|\\[0.5em]
+%       \hss\meta{MGL code}\hss\\[0.5em]
+%     |\end{mgladdon}|\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+%
+% \DescribeEnv{mglfunc} Is used to define MGL functions within the document's main script. It takes one mandatory argument, which is the name of the function, plus one optional argument, which specifies the number of arguments of the function (the default is $0$). The environment needs to contain only the body of the function, since the lines ``func \meta{function\_name} \meta{number of arguments}'' and ``return'' are appended automatically at the beginning and the end, respectively. The [...]
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\begin{mglfunc}|\oarg{number of arguments}\marg{function\_name}\\[0.5em]
+%       \hss\meta{MGL function body}\hss\\[0.5em]
+%     |\end{mglfunc}|\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+%
+% \DescribeEnv{mglcode} It has the same function as the |mgl| environment, but the corresponding code is written to a separate script, whose name is specified as mandatory argument. It accepts the following optional arguments:
+% \begin{itemize}
+%   \item \textbf{bb, bbllx, bblly, bburx, bbury, natwidth, natheight, hiresbb, viewport, trim, angle, origin, width, height, totalheight, keepaspectratio, scale, clip, draft, type, ext, read, command:} These are the same options of the |\includegraphics| command from the \textsf{graphicx} package.
+%   \item \textbf{gray:} Can be used to activate (|gray=on| or |gray=1|) or deactivate (|gray=off| or |gray=0|) gray-scale mode privately (only for the current graphic).
+%   \item \textbf{mglscale:} Any positive value for this option is used to physically scale the resulting image file, i.g., |mglscale=2| will create an image file twice as bigger.
+%   \item \textbf{quality:} Sets the quality of the current graphic. Valid values are integers between |0| and |9|.
+%   \item \textbf{variant:} Sets the variant of argument for the commands in the current script.
+%   \item \textbf{imgext:} Can be used to set the extension for the current image.
+% \end{itemize}
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\begin{mglcode}|\oarg{key-val list}\marg{script\_name}\\[0.5em]
+%       \hss\meta{MGL code}\hss\\[0.5em]
+%     |\end{mglcode}|\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+%
+% \DescribeEnv{mglscript} The code within |mglscript| is written to a script whose name is specified as mandatory argument, but no image is produced. It is useful for creation of MGL scripts which can be later post-processed by another package, like \textsf{listings} or \textsf{pygments}.
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\begin{mglscript}|\marg{script\_name}\\[0.5em]
+%       \hss\meta{MGL code}\hss\\[0.5em]
+%     |\end{mglscript}|\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+%
+% \DescribeEnv{mglsetupscript} This is used to create a common ``setup'' script to define constants, parameters, etc. that will be available to the others.
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\begin{mglsetupscript}|\\[0.5em]
+%       \hss\meta{MGL code}\hss\\[0.5em]
+%     |\end{mglsetupscript}|\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+% If called more than once, it will overwrite the setup code. Also note that it should be used only to define constants, parameters and things like that, but not graphical objects like axis or grids, because the |mgl| environment clears every graphical object before creating the image.\footnote{This problem occurs only with the \texttt{mgl} environment, so you could use \texttt{mglcommon} to create many graphics with the same axis, grid, etc., with environments like \texttt{mglcode}, but [...]
+%
+% For example, one could write
+% \begin{quote}
+%   |\begin{mglsetupscript}|\\
+%   |define gravity 9.81 # [m/s^2]|\\
+%   |\end{mglsetupscript}|
+% \end{quote}
+% to make the constant \emph{gravity} available to every script.
+%
+% \DescribeEnv{mglcommon} This is a synomyn for the |mglsetupscript| environment. It is and will always be kept in \textsf{\mglTeX} for backwards compatibility with older versions of the package, but its use is \emph{deprecated}.
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\begin{mglcommon}|\\[0.5em]
+%       \hss\meta{MGL code}\hss\\[0.5em]
+%     |\end{mglcommon}|\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+%
+% \subsection{Fast creation of graphics}
+% \noindent\textsf{\mglTeX} defines a convenient way to work with many graphics that have exactly the same settings (same rotation angles, same type of grid, same lighting, etc.): instead of writing repetitive code every time it's needed, it can be stored inside a |mglsetup| environment, and then can be used when needed with the |\mglplot| command.
+%
+% \DescribeEnv{mglsetup} This environment is defined as a special case of the |mglfunc| environment. It accepts one mandatory argument, which is a keyword (name) associated to the corresponding block of code (MGL function body).
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\begin{mglsetup}|\marg{key\_word}\\[0.5em]
+%       \hss\meta{MGL code}\hss\\[0.5em]
+%     |\end{mglsetup}|\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+%
+% \DescribeMacro{\mglplot} This command is used for fast generation of graphics with default settings, and can be used in parallel with the |mglsetup| environment. It accepts one mandatory argument which consists of MGL instructions, separated by the symbol ``:'', and can span through various text lines. It accepts the following optional arguments:
+% \begin{itemize}
+%   \item \textbf{bb, bbllx, bblly, bburx, bbury, natwidth, natheight, hiresbb, viewport, trim, angle, origin, width, height, totalheight, keepaspectratio, scale, clip, draft, type, ext, read, command:} These are the same options of the |\includegraphics| command from the \textsf{graphicx} package.
+%   \item \textbf{gray:} Can be used to activate (|gray=on| or |gray=1|) or deactivate (|gray=off| or |gray=0|) gray-scale mode privately (only for the current graphic).
+%   \item \textbf{mglscale:} Any positive value for this option is used to physically scale the resulting image file, e.g., |mglscale=2| will create an image file twice as bigger.
+%   \item \textbf{quality:} Sets the quality of the current graphic. Valid values are integers between |0| and |9|.
+%   \item \textbf{variant:} Sets the variant of argument for the commands in the current script.
+%   \item \textbf{imgext:} Can be used to set the extension for the current image.
+%   \item \textbf{label:} Can be used to indicate a name for the corresponding graphic (otherwise, an automatic naming will be applied)
+%   \item \textbf{setup:} Specifies a keyword associated to a |mglsetup| block, which will be executed before the code in the mandatory argument.
+%   \item \textbf{separator:} Specifies a text symbol that will break the code in the mandatory argument into a new physical line in the main script every time is encountered.
+% \end{itemize}
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\mglplot|\oarg{key-val list}\marg{MGL code}\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+%
+% \subsection{Verbatim-like environments}
+% \noindent The main purpose of these environments is to typeset their contents to the \LaTeX{} document, elegantly separated from the rest of the text. They have two versions: an unstarred version which can be listed later with the |\listofmglscripts| command (explained later), and a starred version which won't be listed.
+%
+% Although these environments are intended to mimic the behavior of the |verbatim| environment from \LaTeX{}, there is an important difference, namely, long lines will be broken when the page margin is reached. This intended behavior is set because a language like MGL can easily have very long lines of code, like textual formulas, vectors input as lists of values, etc. Of course, no hyphenation will be performed, but the code will be indented in the second, third, etc. continuation lines [...]
+%
+% \DescribeEnv{mglblock}\DescribeEnv{mglblock*} Besides typesetting its contents to the document, |mglblock| creates a script whose name is specified as mandatory argument. It accepts one optional argument:
+% \begin{itemize}
+%   \item \textbf{lineno:} Used to activate (|lineno=true| or simply |lineno|) or deactivate (|lineno=false|) line numbering inside the environment.
+% \end{itemize}
+% By default, each line of code is numbered.
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\begin{mglblock}|\oarg{key-val list}\marg{script\_name}\\[0.5em]
+%       \hss\meta{MGL code}\hss\\[0.5em]
+%     |\end{mglblock}|\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\begin{mglblock*}|\oarg{key-val list}\marg{script\_name}\\[0.5em]
+%       \hss\meta{MGL code}\hss\\[0.5em]
+%     |\end{mglblock*}|\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+% The ouput looks like this:
+% \begin{quote}
+%   \makeatletter
+%   \MGL at set@script at name{example_script}%
+%   \refstepcounter{MGL at verb@no}%
+%   \addcontentsline{lms}{MGL at script}{\protect\numberline{\theMGL at verb@no.}{\ttfamily\protect\detokenize{\MGL at script.mgl}}}%
+%   \setcounter{MGL at line@no}{0}%
+%   \list{\mgllinenostyle\arabic{MGL at line@no}.}{}%
+%   \MGL at set@pseudo at verb@env
+%   \fboxrule=\mgllinethickness%
+%   \item[\MGL at line@sep]\fbox{\bfseries\ttfamily\expandafter\detokenize\expandafter{\MGL at script.mgl}}\hskip\labelsep\MGL at line@sep\par\par%
+%   \stepcounter{MGL at line@no}%
+%   \item new x 50 40 '0.8*sin(pi*x)*sin(pi*(y+1)/2)'
+%   \stepcounter{MGL at line@no}%
+%   \item new y 50 40 '0.8*cos(pi*x)*sin(pi*(y+1)/2)'
+%   \stepcounter{MGL at line@no}%
+%   \item new z 50 40 '0.8*cos(pi*(y+1)/2)'
+%   \stepcounter{MGL at line@no}%
+%   \item title 'Parametric surface' : rotate 50 60 : box
+%   \stepcounter{MGL at line@no}%
+%   \item surf x y z 'BbwrR'
+%   \item[\MGL at line@sep]\hskip-\labelsep\MGL at line@sep%
+%   \endlist%
+% \end{quote}
+%
+% \DescribeEnv{mglverbatim}\DescribeEnv{mglverbatim*} This environment only typesets its contents to the \LaTeX{} document without creating any script. It accepts two optional arguments
+% \begin{itemize}
+%   \item \textbf{lineno:} Used to activate (|lineno=true| or simply |lineno|) or deactivate (|lineno=false|) line numbering inside the environment.
+%   \item \textbf{label:} Used to specify a name associated to the corresponding code.
+% \end{itemize}
+% The default behavior is to number each line of code.
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\begin{mglverbatim}|\oarg{key-val list}\\[0.5em]
+%       \hss\meta{MGL code}\hss\\[0.5em]
+%     |\end{mglverbatim}|\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\begin{mglverbatim*}|\oarg{key-val list}\\[0.5em]
+%       \hss\meta{MGL code}\hss\\[0.5em]
+%     |\end{mglverbatim*}|\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+% The output looks like this without |label|:
+% \begin{quote}
+%   \makeatletter
+%   \setcounter{MGL at line@no}{0}%
+%   \list{\mgllinenostyle\arabic{MGL at line@no}.}{}%
+%   \MGL at set@pseudo at verb@env
+%   \fboxrule=\mgllinethickness%
+%   \MGL at set@script at name{\mglverbatimname}%
+%   \item[\MGL at line@sep]\hskip-\labelsep\MGL at line@sep%
+%   \refstepcounter{MGL at verb@no}%
+%   \addcontentsline{lms}{MGL at script}{\protect\numberline{\theMGL at verb@no.}{\ttfamily\protect\detokenize{\MGL at script}}}%
+%   \stepcounter{MGL at line@no}%
+%   \item new x 50 40 '0.8*sin(pi*x)*sin(pi*(y+1)/2)'
+%   \stepcounter{MGL at line@no}%
+%   \item new y 50 40 '0.8*cos(pi*x)*sin(pi*(y+1)/2)'
+%   \stepcounter{MGL at line@no}%
+%   \item new z 50 40 '0.8*cos(pi*(y+1)/2)'
+%   \stepcounter{MGL at line@no}%
+%   \item title 'Parametric surface' : rotate 50 60 : box
+%   \stepcounter{MGL at line@no}%
+%   \item surf x y z 'BbwrR'
+%   \item[\MGL at line@sep]\hskip-\labelsep\MGL at line@sep%
+%   \endlist%
+% \end{quote}
+% \noindent If a |label| is specified, the output will look exactly as that of the |mglblock| environment.
+%
+% \DescribeEnv{mglcomment} This environment is used to embed comments. The comment won't be visible in the case of the user passing the option |nocomments| to the package, but it will be typeset \emph{verbatim} to the document if the user passes the option |comments|.
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\begin{mglcomment}|\\[0.5em]
+%       \hss\meta{Comment}\hss\\[0.5em]
+%     |\end{mglcomment}|\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+% If the user requests visible comments, this will result in the appearance of something like the following in the \LaTeX{} document:
+% \begin{quote}
+%   \makeatletter
+%   \list{}{}%
+%   \MGL at set@pseudo at verb@env
+%   \item\hskip-\labelsep<\MGL at dash@sep\mglcommentname\MGL at dash@sep>%
+%   \item This is a mglTeX comment
+%   \item\hskip-\labelsep<\MGL at dash@sep\mglcommentname\MGL at dash@sep>%
+%   \endlist%
+% \end{quote}
+%
+% \subsection{Working with external scripts}
+% \noindent \textsf{\mglTeX} provides convenient ways to deal with external scripts (scripts that exist in their own files, independently of the \LaTeX{} document, like scripts sent by a colleague or created before the actual writing of the \LaTeX{} document, etc). It must be noted, however, that the package works on the suposition that these scripts are in their final version, so no change detection is performed on them. If a external script is changed, the corresponding graphic must be [...]
+%
+% \DescribeMacro{\mglgraphics} This command takes the name of an external MGL script as mandatory argument, which will be automatically executed, and the resulting image will be included. The same optional arguments accepted by this command are:
+% \begin{itemize}
+%   \item \textbf{bb, bbllx, bblly, bburx, bbury, natwidth, natheight, hiresbb, viewport, trim, angle, origin, width, height, totalheight, keepaspectratio, clip, draft, type, ext, read, command:} These are the same options of the |\includegraphics| command from the \textsf{graphicx} package.
+%   \item \textbf{gray:} Can be used to activate (|gray=on| or |gray=1|) or deactivate (|gray=off| or |gray=0|) gray-scale mode privately (only for the current graphic).
+%   \item \textbf{mglscale:} Any positive value for this option is used to physically scale the resulting image file, i.g., |mglscale=2| will create an image file twice as bigger.
+%   \item \textbf{quality:} Sets the quality of the current graphic. Valid values are integers between |0| and |9|.
+%   \item \textbf{variant:} Sets the variant of argument for the commands in the current script.
+%   \item \textbf{imgext:} Can be used to set the extension for the current image.
+%   \item \textbf{path:} Can be used to specify the location of the script.
+% \end{itemize}
+%
+% \DescribeMacro{\mglinclude}\DescribeMacro{\mglinclude*} This command is the equivalent of the |mglverbatim| environment for external scripts. It takes one mandatory argument, which is the name of a MGL script, which will be automatically transcript \emph{verbatim} on the \LaTeX{} document. It accepts the following optional arguments:
+% \begin{itemize}
+%   \item \textbf{lineno:} Used to activate (|lineno=true| or simply |lineno|) or deactivate (|lineno=false|) line numbering inside the environment.
+%   \item \textbf{path:} Can be used to specify the location of the script.
+% \end{itemize}
+% The unstarred version of this command will be listed if |\listofmglscripts| is used (explained later), while the starred version won't.
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\mglinclude|\oarg{key-val list}\marg{script\_name}\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\mglinclude*|\marg{script\_name}\oarg{key-val list}\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+%
+% \subsection{Additional commands}
+% \DescribeMacro{\listofmglscripts}\noindent Opens a new section or chapter---depending on the \LaTeX{} class used---, where all the scripts that have been transcript in the document with the unstarred versions of the |mglblock| and |mglverbatim| environments, and the |\mglinclude| command, are listed. In case a |mglverbatim| is used, but no |label| is specified, the default name to display is specified by the |\mglverbatimname| macro (explained later), otherwise, the corresponding label [...]
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\listofmglscripts|\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+% The output is like this:
+% \begin{center}
+%   \begin{minipage}{0.9\textwidth}
+%     \listofmglscripts
+%   \end{minipage}
+% \end{center}
+%
+% \DescribeMacro{\mglTeX}\DescribeMacro{\mglTeX*} This command just pretty-prints the name of the package, i.e., the logo:
+% \begin{center}
+%   \Huge\mglTeX
+% \end{center}
+% The starred version will also print the version in a coherent manner.
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\mglTeX|\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\mglTeX*|\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+%
+% In an environment where the typesetting of the logo is impossible (a text editor, for instance), it can (and should) be replaced by ``mglTeX''.
+%
+% \subsection{Local settings commands}\label{local setts}
+% \noindent These commands are intended to be equivalent to the package options, but with a local-only effect, meaning that the new settings are applied from the point these commands are used onward.
+%
+% \DescribeMacro{\mglswitch} This command is equivalent to the package options |on| and |off|, depending on the argument passed.
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\mglswitch{|\meta{off\,$\vert$on\,$\vert$0\,$\vert$1}|}|\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+%
+% Observe that |\mglswitch{on}| and |\mglswitch{off}| can be used to save time when writing a document, wrapping a section with them, avoiding recompilation of the corresponding scripts.
+%
+% \DescribeMacro{\mglcomments} This command is equivalent to the package options |comments| and |nocomments|, depending on the argument passed.
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\mglcomments{|\meta{off\,$\vert$on\,$\vert$0\,$\vert$1}|}|\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+%
+% \DescribeMacro{\mglgray} It is equivalent to the package options |gray| and |color|, depending on the argument passed.
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\mglgray{|\meta{off\,$\vert$on\,$\vert$0\,$\vert$1}|}|\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+%
+% \DescribeMacro{\mglscale} Can be used to specify the default scaling for the creation of MGL graphics (1 is normal scaling, 2 is twice as bigger, etc.).
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\mglscale|\marg{$x:x>0$}\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+%
+% \DescribeMacro{\mglquality} The default quality for the creation of MGL graphics can be specified locally with this command. An info message will be printed in the |.log| file indicating the characteristics of the chosen value, according to the following table:
+% \begin{center}
+%   \DeleteShortVerb{\|}
+%   \begin{tabular}{|c|l|}
+%     \hline
+%     Quality & Description\\
+%     \hline
+%     \hline
+%     $0$ & No face drawing (fastest)\\
+%     \hline
+%     $1$ & No color interpolation (fast)\\
+%     \hline
+%     $2$ & High quality (normal)\\
+%     \hline
+%     $3$ & High quality with 3d primitives (not implemented yet)\\
+%     \hline
+%     $4$ & No face drawing, direct bitmap drawing (low memory usage)\\
+%     \hline
+%     $5$ & No color interpolation, direct bitmap drawing (low memory usage)\\
+%     \hline
+%     $6$ & High quality, direct bitmap drawing (low memory usage)\\
+%     \hline
+%     $7$ & High quality with 3d primitives, direct bitmap drawing\\
+%     & (not implemented yet)\\
+%     \hline
+%     $8$ & Draw dots instead of primitives (extremely fast)\\
+%     \hline
+%     $9$ & No drawing (for testing purposes)\\
+%     \hline
+%   \end{tabular}
+%   \MakeShortVerb{\|}
+% \end{center}
+% If a non available quality is chosen, it will be changed to $2$ (the default), and a warning message will be issued for the user.
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\mglquality|\marg{0\,$\vert$1\,$\vert$\ldots\,$\vert$9}\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+%
+% \DescribeMacro{\mglvariant} It is useful to set the default variant of arguments for MGL commands.
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\mglvariant|\marg{0\,$\vert$1\,$\vert$\ldots}\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+%
+% \DescribeMacro{\mglimgext} Can be used to specify the extension to save graphics.
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\mglimgext|\marg{image extension}\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+%
+% \DescribeMacro{\mglname}\noindent If used in the preamble of the document this commands just sets the name of the. If used after the |\begin{document}| command, it will force the closure of the current main script, create the corresponding graphics, and start a new main script with the specified name.
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\mglname|\marg{main\_script\_name}\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+%
+% The use of this command is encouraged when writing large documents, like books or thesis, to create a main script per document block (section, chapter, part, etc.). Since the |mgl| environment and the |\mglplot| command use an internal counter to automatically name scripts, unless the |label| option is used; if a new script is added this way to the document, it will alter the original numbering, causing \textsf{\mglTeX} to recompile the scripts from that point on (for more details, rea [...]
+%
+% \subsection{Advanced settings commands}
+% \noindent Although \textsf{\mglTeX} is completely functional without any further set up, there are some parameters of its behavior that could be useful to modify. The following commands must be used in the preamble of the document only, since the first MGL script is created at the moment of the |\begin{document}| command, and otherwise they could create weird errors during compilation; trying to use them somewhere else will produce an error. 
+%
+% \DescribeMacro{\mgldir} This command can be used to specify the main working directory for \textsf{\mglTeX}. Inside it, the scripts, backup files and graphics will be created, or can be separated inside subdirectories. This is useful, for example, to avoid many scripts and graphics from polluting the directory where the \LaTeX{} document is.
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\mgldir|\marg{main\_directory}\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+%
+% \DescribeMacro{\mglscriptsdir} It specifies the subdirectory inside \mglTeX's \meta{main\_directory} where the MGL scripts will be created.
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\mglscriptsdir|\marg{scripts\_subdirectory}\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+%
+% \DescribeMacro{\mglgraphicsdir} It specifies the subdirectory inside \mglTeX's \meta{main\_directory} where the MGL graphics will be created, including the ones from external scripts (not embedded inside the \LaTeX{} document).
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\mglgraphicsdir|\marg{graphics\_subdirectory}\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+%
+% \DescribeMacro{\mglbackupsdir} It specifies the subdirectory inside \mglTeX's \meta{main\_directory} where backups for the MGL scripts will be created.
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\mglbackupsdir|\marg{backups\_subdirectory}\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+%
+% The above commands can be used in various combinations. For example, if none of them is used, the scripts, graphics and backups will be created inside the same path where the \LaTeX{} document is being compiled; if only |\mgldir| is used, they will be created inside \meta{main\_directory}; if only |\mgldir| and |\mglscriptsdir| are used, the scripts will be created inside \meta{main\_directory}\meta{scripts\_subdirectory}, while the graphics and backups will be inside \meta{main\_direc [...]
+%
+% \DescribeMacro{\mglpaths} In case of having external MGL scripts, it is not recommended to place them inside the same location as where the embedded scripts are extracted, since they could be accidentally overwritten or deleted by the user; they should be separated in a folder which can be specified in the form of an absolute or relative path using this command.
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\mglpaths|\marg{directory list}\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+% This command can be used many times or can be used to specify many paths at once. In the case of using it many times, each call will add the new directory or directories to the list of searching paths.
+%
+% \DescribeMacro{\mglsettings} This command has been added for the confort of the user, since it handles all of the basic and advanced settings of \textsf{\mglTeX}, as an alternative to some package options and commands. It takes one mandatory argument which should be a list of \meta{key}=\meta{value} pairs, according to the following table:
+% \begin{center}
+%   \DeleteShortVerb{\|}
+%   \begin{tabular}{|l|l|l|}
+%     \hline
+%     \textbf{Key} & \textbf{Value} & \textbf{Description}\\
+%     \hline
+%     \hline
+%     dir & \meta{main\_directory} & The main working directory\\
+%     \hline
+%     scriptsdir & \meta{scripts\_subdirectory} & The subdirectory for scripts creation\\
+%     \hline
+%     graphicsdir & \meta{graphics\_subdirectory} & The subdirectory for graphics creation\\
+%     \hline
+%     backupsdir & \meta{backups\_subdirectory} & The subdirectory for backups creation\\
+%     \hline
+%     paths & \meta{directory list} & Paths to external scripts\\
+%     \hline
+%     switch & \meta{off\,$\vert$on\,$\vert$0\,$\vert$1} & Turn off/on \mglTeX\\
+%     \hline
+%     comments & \meta{off\,$\vert$on\,$\vert$0\,$\vert$1} & Turn off/on comments\\
+%     \hline
+%     gray & \meta{off\,$\vert$on\,$\vert$0\,$\vert$1} & Turn off/on gray-scale mode\\
+%     \hline
+%     mglscale & \meta{$x:x>0$} & Scale for creation of graphics\\
+%     \hline
+%     quality & \meta{0\,$\vert$1\,$\vert$\ldots\,$\vert$9} & Quality for creation of graphics\\
+%     \hline
+%     variant & \meta{0\,$\vert$1\,$\vert$\ldots} & Variant of arguments for MGL commands\\
+%     \hline
+%     imgext & \meta{image extension} & Extension for creation of graphics\\
+%     \hline
+%   \end{tabular}
+%   \MakeShortVerb{\|}
+% \end{center}
+% \begin{center}
+%   \begin{tabular}{l}
+%     \hline\\[-0.75em]
+%     |\mglsettings|\marg{key-val list}\\[0.25em]
+%     \hline
+%   \end{tabular}
+% \end{center}
+%
+% \subsection{User-definable macros}
+% \noindent There are macros that the user is allowed to modify in order to customize some aspects of the behavior of \textsf{\mglTeX}. For example, if writing in spanish, french or russian, the user would like to modify the name of the common script, the words typeset in the separator lines of mglTeX comments, the name of the list of MGL scripts, etc.
+%
+% \DescribeMacro{\mglsetupscriptname} It is the name for the common setup script that takes the contents of the |mglseuptscipt| or |mglcommon| environments. The default name is defined by
+% \begin{quote}
+%   |\def\mglsetupscriptname{MGL_setup_script}|
+% \end{quote}
+%
+% \DescribeMacro{\mglcommentname} This macro expands to the words typeset before and after a \textsf{\mglTeX} comment, in the middle of the separator lines. The default words are set by
+% \begin{quote}
+%   |\def\mglcommentname{\mglTeX{} comment}|
+% \end{quote}
+%
+% \DescribeMacro{\listofmglscriptsname} This is the name of the section/chapter created by the command |\listofmglscripts|. The default is set by
+% \begin{quote}
+%   |\def\listofmglscriptsname{List of MGL scripts}|
+% \end{quote}
+%
+% \DescribeMacro{\mglverbatimname} This is the default name to be printed in the list of MGL scripts for scripts created with the unstarred version of |mglverbatim|, for which a |label| hasn't been specified. The default is
+% \begin{quote}
+%   |\def\mglverbatimname{(Unnamed MGL script)}|
+% \end{quote}
+%
+% \DescribeMacro{\mgllinenostyle} Indicates the style for typeseting the line numbers inside the |mglblock| and |mglverbatim| environments, and the |\mglinclude| command. The default is
+% \begin{quote}
+%   |\def\mgllinenostyle{\footnotesize}|
+% \end{quote}
+%
+% \DescribeMacro{\mgldashwidth} The dashes of the separator lines for the |mglcomment| environment are contained inside boxes whose width is specified by this macro. For practical purposes, this dimension can be used to increase/decrease the space between the dashes. The default is
+% \begin{quote}
+%   |\mgldashwidth=0.75em|
+% \end{quote}
+% It is recommended to use font-dependent units for this dimension, like |em|, just in case the font is changed later, so it adapts to the new metric.\footnote{A rule of thumb is to use \texttt{em} units for horizontal dimensions, and \texttt{ex} units for vertical dimensions.}
+%
+% \DescribeMacro{\mgllinethickness} It is the thickness of the separator lines for the |mglblock| and |mglverbatim| environments, and the |\mglinclude| command. The default is
+% \begin{quote}
+%   |\mgllinethickness=0.25ex|
+% \end{quote}
+% It is also recommended to use font-dependent units for this dimension, like |ex|.
+%
+% \DescribeMacro{\mglbreakindent} \textsf{\mglTeX} allows line breaking inside verbatim-like environments and commands. When a line of code is broken, |\mglbreakindent| is the indentation of the second, third, etc. continuation lines. The default is
+% \begin{quote}
+%   |\mglbreakindent=1em|
+% \end{quote}
+% Once more, font-dependent units are encourage.
+%
+% \section{Behavior of \textsf{\mglTeX}}
+% \noindent \textsf{\mglTeX} has many convenient features designed for the comfort of the user, and to reduce the possibility of unintentional malfunction.
+% \subsection{Creation and inclusion of MGL scripts and graphics}
+% \noindent All environments and commands for MGL code embedding check for multiple scripts with the same name. This detection is performed in order to avoid unintentionally overwriting scripts, or creating confusion with different verbatim chunks of code with the same name. If such multiple naming is found a warning will be issued. However, external scripts are supposed to be responsibility of the user, so no detection of multiple naming will be performed on them.
+%
+% When \textsf{\mglTeX} is unable to find a graphic that is supposed to include, instead of producing an error, it will warn the user about it, and will display a box in the corresponding position of the document like the one shown in figure~\ref{fig: MGL image not found box}.
+% \begin{figure}[!ht]
+%   \centering
+%   \fbox{%
+%     \centering%
+%     \bfseries\Huge%
+%     \begin{tabular}{c}MGL\\image\\not\\found\end{tabular}%
+%   }
+%   \caption{This box is shown by \textsf{\mglTeX} instead of a graphic that should be included, but can't be found.}\label{fig: MGL image not found box}
+% \end{figure}
+% Notice that the first time or even the second time \LaTeX{} is executed, many of these boxes will appear in the document, because the first run detects changes on scripts, while the second run creates the graphics, but not all of them are included, until \LaTeX{} is run for the third time.
+%
+% Likewise, when a script isn't found, a warning will be issued for the user, and, if that script was meant to be included in the document by a |\mglinclude| command, the box shown in figure~\ref{fig: MGL script not found box} will be displayed instead.
+% \begin{figure}[!ht]
+%   \centering
+%   \fbox{%
+%     \centering%
+%     \bfseries\Huge%
+%     \begin{tabular}{c}MGL\\script\\not\\found\end{tabular}%
+%   }
+%    \caption{This box is shown by \textsf{\mglTeX} instead of a script that should be included, but can't be found.}\label{fig: MGL script not found box}
+% \end{figure}
+%
+% When \textsf{\mglTeX} is |off| no MGL graphics will be generated nor will be included, but instead, a box like the one of figure~\ref{fig: mglTeX is off box} will be shown.
+% \begin{figure}[!ht]
+%   \centering
+%   \fbox{%
+%     \centering%
+%     \bfseries\Huge%
+%     \begin{tabular}{c}\mglTeX\\is off;\\no image\\included\end{tabular}%
+%   }
+%   \caption{This box is shown instead of an image when \textsf{\mglTeX} is \texttt{off}.}\label{fig: mglTeX is off box}
+% \end{figure}
+%
+% \subsection{Recompilation-decision algorithm}\label{subsection: recompilation decision}
+% \noindent \textsf{\mglTeX} has the builtin capacity of detecting changes in MGL scripts, so that a script is recompiled only when it has changed, not every time \LaTeX{} is executed. This saves a lot of time, since most of the compilation time of a document is spent on the creation (and conversion to another format, if necessary) of the graphics.
+%
+% This is how the recompilation-decision is performed: When \textsf{\mglTeX} finds an environment or command meant to create a script/graphic, it checks if the command |\MGL@@@|\meta{script} is defined, where \meta{script} is the name of the script. If the command is undefined, this means the script has changed, so the corresponding code is transcript to the file \meta{script}.mgl, and the command |\MGL@@@|\meta{script} is defined. If the command is already defined, this means the script [...]
+%
+% \begin{figure}[ht!]
+%   \centering
+%   \includegraphics[scale=0.35]{Recompilation_decision}
+%   \caption{The algorithm used by \textsf{\mglTeX} to decide which scripts recereate/recompile.}\label{fig: recompilation decision}
+% \end{figure}
+%
+% The recompilation-decision mechanism can be fooled, however. The |mgl| environment and |\mglplot| command have the ability to automatically name scripts by means of the use of an internal counter, unless the |label| option is specified. Suppose the user wants to add a new |mgl| environment or |\mglplot| command exactly after the $(n-1)$th script, so the $n$th script will be the newly added, while the old $n$th will be the new $(n+1)$th, and so on, altering the original numbering. This  [...]
+%
+% There are two ways to avoid this problem: The first one is to use the |label| option on the newly arrived; the second is to wrap a complete block of the document with the |\mglswitch{off}| and |\mglswitch{on}| commands, avoiding recompilation and saving time. This last option will avoid the inclusion of the MGL graphics, so it is only recommended in case of the wrapped scripts being in their final version (not needing further modification), so there is no need of updating the correspon [...]
+%
+% There are situations when recompilation of a script has to be forced. For example, if the default quality has changed, but the script hasn't, \textsf{\mglTeX} won't recreate the corresponding graphic by its own initiative, because it won't detect any changes in the code. In order to force recompilation, the image of the corresponding script can be deleted: \textsf{\mglTeX} will detect this abscence in the next \LaTeX{} run and recompile.
+%
+% \section{Acknowledgements}
+% \noindent \textsf{\mglTeX} was born as a small personal project. It has grown and mature under the constant suggestions and requests from Prof. Alexey Balakin.
+%
+% \section{Redistributing and modifying}
+% \noindent The \emph{source code} of \textsf{\mglTeX} (.sty, .dtx, and .ins files) can be redistributed and/or modified under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. The \emph{documentation} of \textsf{\mglTeX} (.dvi, .ps, .pdf and other files) is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 
+%
+% \StopEventually{\PrintChanges\PrintIndex}
+%
+% \section{Implementation}
+% \noindent This section documents the complete code of \textsf{\mglTeX}. It's main purpose is to facilitate the understanding and maintanance of the package's code. For the following, we use ``|@|'' in the name of macros the user should not modify; the prefix ``|MGL|'' is used to simulate a namespace, so the macros from \textsf{\mglTeX} won't interfere with the ones from other packages.
+%
+% \subsection{Initialization}\label{Init}
+% \noindent We first define some macros that will serve different purposes on different parts of the package.
+% \begin{macro}{\MGL at off}\begin{macro}{\MGL at on}\begin{macro}{\MGL at zero}\begin{macro}{\MGL at one}
+% These are used in the command |\MGL at test@switch| (explained later) to determine whether the user has passed one of the options |off|, |on|, |0| or |1| to a command.
+%    \begin{macrocode}
+\def\MGL at off{off}
+\def\MGL at on{on}
+\def\MGL at zero{0}
+\def\MGL at one{1}
+%    \end{macrocode}
+% \end{macro}\end{macro}\end{macro}\end{macro}
+% \begin{macro}{\MGL at test@switch}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{New command to verify and validate switching arguments}
+% It is called by a command to test whether the user has passed the option |off|, |on|, |0| (equivalent to |off|) or |1| (equivalent to |on|); if the option is correct, it is replaced by its equivalent, otherwise, a warning is issued. It takes two arguments: the first one is the option to test, the second one is the name of the command calling this macro.
+%    \begin{macrocode}
+\def\MGL at test@switch#1#2{%
+  \def\MGL at temp@a{#1}%
+  \ifx\MGL at temp@a\MGL at on%
+  \else\ifx\MGL at temp@a\MGL at off%
+  \else\ifx\MGL at temp@a\MGL at one%
+    \def\MGL at temp@a{on}%
+  \else\ifx\MGL at temp@a\MGL at zero%
+    \def\MGL at temp@a{off}%
+  \else%
+    \PackageWarning{mgltex}{%
+      Unrecognizable option "#1" passed to command \protect#2%
+    }%
+  \fi\fi\fi\fi%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\MGL at TeX@ext}
+% Is used in the command |\MGL at includegraphics| (explained later) to determine whether the user has chosen to save graphics in \LaTeX/Tikz format.
+%    \begin{macrocode}
+\def\MGL at TeX@ext{.tex}
+%    \end{macrocode}
+% \end{macro}
+%
+% The macros |\MGL at switch@on| and |\MGL at switch@off| are called when the package options |on| and |off| are passed, respectively, or when the commands |\mglswitch{on}| and |\mglswitch{off}| are used, respectively.
+% \begin{macro}{\MGL at switch@on}
+% (Re)defines the commands to open, read, write and close scripts, and the command that includes MGL graphics.
+%    \begin{macrocode}
+
+\def\MGL at switch@on{%
+%    \end{macrocode}
+% \begin{macro}{\MGL at openout}
+% Opens a script for writing. It takes two arguments, the first being an output stream number, allocate by |\newwrite| (\TeX{} command), and the second being the path to the script.
+%    \begin{macrocode}
+  \def\MGL at openout##1##2{%
+    \immediate\openout##1="##2"%
+  }%
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\MGL at openin}
+% Opens a script for reading. It takes two arguments, the first being an input stream number, allocate by |\newread| (\TeX{} command), and the second being the path to the script.
+%    \begin{macrocode}
+  \def\MGL at openin##1##2{%
+    \immediate\openin##1="##2"%
+  }%
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\MGL at write}
+% Writes to a script opened with |\MGL at openout|. Its first argument is the output stream number of the script, and the second is the text to write.
+%    \begin{macrocode}
+  \def\MGL at write##1##2{%
+    \immediate\write##1{##2}%
+  }%
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\MGL at read}
+% Reads one line from a script opened with |\MGL at openin|. Its first argument is the input stream number of the script, and the second is a variable where the read text will be stored. The variable is first initialized as empty; if the end of the script has been reached, then there is nothing to read, so it remains empty; otherwise, one line is read and stored in the variable, locally supressing any end line character (|\endlinechar=-1|).
+%    \begin{macrocode}
+  \def\MGL at read##1##2{%
+    \def##2{}%
+    \ifeof##1\else%
+      \bgroup%
+      \endlinechar=-1%
+      \immediate\global\read##1 to ##2%
+      \egroup%
+    \fi%
+  }%
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\MGL at closeout}
+% Closes a script opened with |\MGL at openout|, whose stream number is passed as argument.
+%    \begin{macrocode}
+  \def\MGL at closeout##1{%
+    \immediate\closeout##1%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\MGL at closein}
+% Closes a script opened with |\MGL at openin|, whose stream number is passed as argument.
+%    \begin{macrocode}
+  \def\MGL at closein##1{%
+    \immediate\closein##1%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\MGL at includegraphics}
+% This is a quite sophisticated command. It is in charge of including the graphics created by \textsf{\mglTeX}.
+%    \begin{macrocode}
+  \def\MGL at includegraphics{%
+%    \end{macrocode}
+% First checks if the image exists. Note the |\MGL at dir| and |\MGL at graphics@dir| macros are set by the user with the |\mgldir| and |\mglgraphicsdir| commands, respectively, while |\MGL at script| stores the name of the script ---and thus the image--- executed, and |\MGL at imgext| is the extension chosen by the user to save the graphics.
+%    \begin{macrocode}
+    \IfFileExists{\MGL at dir\MGL at graphics@dir\MGL at script\MGL at imgext}{%
+%    \end{macrocode}
+% If the chosen extension is |.tex|, a \LaTeX/Tikz file has been created, which has to be simply included in the document; it will be automatically compiled by \LaTeX{}. (Observe we use the |\MGL at TeX@ext| macro defined above.)
+%    \begin{macrocode}
+      \ifx\MGL at imgext\MGL at TeX@ext%
+        \include{\MGL at dir\MGL at graphics@dir\MGL at script\MGL at imgext}%
+%    \end{macrocode}
+% If the chosen extension is not |.tex|, a normal visual image has been created, so the |\includegraphics| command is invoked to deal with it. The options for this command (like |scale|, |angle|, etc.) are stored in the |\MGL at graph@keys| macro, which is defined by every environment or command that creates and compiles MGL scripts, according to the optional arguments the user has passed.
+%    \begin{macrocode}
+      \else%
+        \expandafter\includegraphics\expandafter[\MGL at graph@keys]{%
+          \MGL at dir\MGL at graphics@dir\MGL at script%
+        }%
+      \fi%
+    }{%
+%    \end{macrocode}
+% If the requested image doesn't exist, the issue a warning message for the user, and print a warning framed box (``\textbf{MGL image not found}'') in the place the image should occupy.
+%    \begin{macrocode}
+      \PackageWarning{mgltex}{MGL image "\MGL at script" not found}%
+      \fbox{%
+        \centering%
+        \bfseries\Huge%
+        \begin{tabular}{c}MGL\\image\\not\\found\end{tabular}%
+      }%
+    }%
+  }%
+%    \end{macrocode}
+% \end{macro}
+% And here ends the |\MGL at switch@on| command.
+%    \begin{macrocode}
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\MGL at switch@off}
+% (Re)defines the same commands as |\MGL at switch@on| in such a way they accept the same arguments, but do nothing. The exception is |\MGL at includegraphics| which, instead of doing nothing, prints a warning framed box (``\textbf{\mglTeX{} is off; no image included}'').
+%    \begin{macrocode}
+\def\MGL at switch@off{%
+  \PackageWarning{mgltex}{mglTeX is off}%
+  \def\MGL at openout##1##2{}%
+  \def\MGL at openin##1##2{}%
+  \def\MGL at write##1##2{}%
+  \def\MGL at read##1##2{}%
+  \def\MGL at closeout##1{}
+  \def\MGL at closein##1{}
+  \def\MGL at includegraphics{%
+    \fbox{%
+      \centering%
+      \bfseries\Huge%
+      \begin{tabular}{c}\mglTeX\\is off;\\no image\\included\end{tabular}%
+    }%
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@MGL at comments@off}\begin{macro}{\@MGL at comments@on}
+% We will need a boolean switch to activate/deactivate comments later.
+%    \begin{macrocode}
+
+\def\@MGL at comments@off{\let\if at MGL@comments@\iffalse}
+\def\@MGL at comments@on{\let\if at MGL@comments@\iftrue}
+%    \end{macrocode}
+% \end{macro}\end{macro}
+%
+% \begin{macro}{\MGL at gray}\begin{macro}{\MGL at gray@off}\begin{macro}{\MGL at gray@on}
+% The commands |\MGL at gray@off| and |\MGL at gray@on| simply set the value of |\MGL at gray| to $0$ and $1$, respectively; this value will be used later through the |-g| command line option from |mglconv|.
+%    \begin{macrocode}
+
+\def\MGL at gray@off{\def\MGL at gray{0}}
+\def\MGL at gray@on{\def\MGL at gray{1}}
+%    \end{macrocode}
+% \end{macro}\end{macro}\end{macro}
+% \begin{macro}{\mglgray}
+% Depending on the option passed by the user, it calls |\@MGL at gray@on| or |\@MGL at gray@off|.
+%    \begin{macrocode}
+\def\mglgray#1{%
+  \MGL at test@switch{#1}{\mglgray}%
+  \csname @MGL at gray@\MGL at temp@a\endcsname%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\mglscale}\begin{macro}{\MGL at scale}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{Now accepts any positive value}
+% |\mglscale| sets the value of the |\MGL at scale| macro, which is used later to specify the default scaling for graphics. It only accepts positive values, otherwise it issues a warning and restarts the scaling to $1$. In order to be able to check the validity of the value passed by the user, we first set the |\MGL at scale| macro to that value and test it with the |\ifdim| conditional.\footnote{We can't use \doccommand{ifnum} here because it only accepts integer values.} Since this condition [...]
+%    \begin{macrocode}
+
+\def\mglscale#1{
+  \ifdim#1\p@>\z@%
+    \def\MGL at scale{#1}%
+  \else%
+    \PackageWarning{mgltex}{%
+      Scaling value of #1\space not allowed; using default (1)%
+    }%
+    \def\MGL at scale{1}%
+  \fi%
+}
+%    \end{macrocode}
+% \end{macro}\end{macro}
+%
+% \begin{macro}{\mglquality}\begin{macro}{\MGL at quality}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{\texttt{9} is accepted as quality value now}
+% |\mglquality| sets the value of the |\MGL at quality| macro, which is used later to specify the default quality for graphics. It only accepts integer values from $0$ to $8$ (the only ones defined by |MathGL|), otherwise it issues a warning and restarts to $2$ (the default for |MathGL|). In order to be able to check the validity of the value passed by the user, we first set the |\MGL at quality| macro to that value and test it with the |\ifcase| conditional; if the value is valid, we print an [...]
+%    \begin{macrocode}
+
+\def\mglquality#1{%
+  \def\MGL at quality{#1}%
+  \ifcase\MGL at quality%
+    \PackageInfo{mgltex}{%
+      Quality 0: No face drawing (fastest)%
+    }%
+  \or%
+    \PackageInfo{mgltex}{%
+      Quality 1: No color interpolation (fast)%
+    }%
+  \or%
+    \PackageInfo{mgltex}{%
+      Quality 2: High quality (normal)%
+    }%
+  \or%
+    \PackageInfo{mgltex}{%
+      Quality 3: High quality with 3d primitives (not implemented yet)%
+    }%
+  \or%
+    \PackageInfo{mgltex}{%
+      Quality 4: No face drawing, direct bitmap drawing
+      (low memory usage)%
+    }%
+  \or%
+    \PackageInfo{mgltex}{%
+      Quality 5: No color interpolation, direct bitmap drawing
+      (low memory usage)%
+    }%
+  \or%
+    \PackageInfo{mgltex}{%
+      Quality 6: High quality, direct bitmap drawing (low memory usage)%
+    }%
+  \or%
+    \PackageInfo{mgltex}{%
+      Quality 7: High quality with 3d primitives, direct bitmap drawing %
+      (not implemented yet)%
+    }%
+  \or%
+    \PackageInfo{mgltex}{%
+      Quality 8: Draw dots instead of primitives (extremely fast)%
+    }%
+  \or%
+    \PackageInfo{mgltex}{%
+      Quality 9: No drawing (for testing purposes)%
+    }%
+  \else%
+    \PackageWarning{mgltex}{%
+      Quality #1 not available; using default (2)%
+    }%
+    \def\MGL at quality{2}%
+  \fi%
+}
+%    \end{macrocode}
+% \end{macro}\end{macro}
+%
+% \begin{macro}{\mglvariant}\begin{macro}{\MGL at variant}
+% |\mglvariant| sets the value of the |\MGL at variant| macro, which is passed later to |mglconv| thorugh its |-v| command line option. It only accepts non-negative integer, otherwise it issues a warning and restarts to $0$ (the default for |MathGL|). In order to be able to check the validity of the value passed by the user, we use the |\ifnum| conditional; if the value is invalid we issue a warning and overwrite |\MGL at variant| to $0$.
+%    \begin{macrocode}
+
+\def\mglvariant#1{%
+  \def\MGL at variant{#1}%
+  \ifnum\MGL at variant<0%
+    \PackageWarning{mgltex}{%
+      Variant #1 not allowed; using default (0)%
+    }%
+    \def\MGL at variant{0}%
+  \fi%
+}
+%    \end{macrocode}
+% \end{macro}\end{macro}
+%
+% Now we declare the options |final| and |draft|, which are simply passed to the \textsf{graphicx} package.
+%    \begin{macrocode}
+
+\DeclareOption{draft}{%
+  \PassOptionsToPackage{\CurrentOption}{graphicx}%
+}
+\DeclareOption{final}{%
+  \PassOptionsToPackage{\CurrentOption}{graphicx}%
+}
+%    \end{macrocode}
+%
+% The rest of the package options just call an adequate command or set an adequate value for a macro.
+%    \begin{macrocode}
+
+\DeclareOption{on}{\MGL at switch@on}
+\DeclareOption{off}{\MGL at switch@off}
+
+\DeclareOption{nocomments}{\@MGL at comments@off}
+\DeclareOption{comments}{\@MGL at comments@on}
+
+\DeclareOption{gray}{\MGL at gray@on}
+\DeclareOption{color}{\MGL at gray@off}
+
+\DeclareOption{1x}{\def\MGL at scale{1}}
+\DeclareOption{2x}{\def\MGL at scale{2}}
+\DeclareOption{3x}{\def\MGL at scale{3}}
+\DeclareOption{4x}{\def\MGL at scale{4}}
+\DeclareOption{5x}{\def\MGL at scale{5}}
+\DeclareOption{6x}{\def\MGL at scale{6}}
+\DeclareOption{7x}{\def\MGL at scale{7}}
+\DeclareOption{8x}{\def\MGL at scale{8}}
+\DeclareOption{9x}{\def\MGL at scale{9}}
+
+\DeclareOption{0q}{\def\MGL at quality{0}}
+\DeclareOption{1q}{\def\MGL at quality{1}}
+\DeclareOption{2q}{\def\MGL at quality{2}}
+\DeclareOption{3q}{\def\MGL at quality{3}}
+\DeclareOption{4q}{\def\MGL at quality{4}}
+\DeclareOption{5q}{\def\MGL at quality{5}}
+\DeclareOption{6q}{\def\MGL at quality{6}}
+\DeclareOption{7q}{\def\MGL at quality{7}}
+\DeclareOption{8q}{\def\MGL at quality{8}}
+\DeclareOption{9q}{\def\MGL at quality{9}}
+
+\DeclareOption{0v}{\def\MGL at variant{0}}
+\DeclareOption{1v}{\def\MGL at variant{1}}
+\DeclareOption{2v}{\def\MGL at variant{2}}
+%    \end{macrocode}
+%
+% \begin{macro}{\MGL at imgext}
+% The following options set the default graphics extension, which is stored in the |\MGL at imgext| macro for later use.
+%    \begin{macrocode}
+
+\DeclareOption{eps}{\def\MGL at imgext{.eps}}
+\DeclareOption{epsz}{\def\MGL at imgext{.epsz}}
+\DeclareOption{epsgz}{\def\MGL at imgext{.eps.gz}}
+\DeclareOption{bps}{\def\MGL at imgext{.bps}}
+\DeclareOption{bpsz}{\def\MGL at imgext{.bpsz}}
+\DeclareOption{bpsgz}{\def\MGL at imgext{.bps.gz}}
+\DeclareOption{pdf}{\def\MGL at imgext{.pdf}}
+\DeclareOption{png}{\def\MGL at imgext{.png}}
+\DeclareOption{jpg}{\def\MGL at imgext{.jpg}}
+\DeclareOption{jpeg}{\def\MGL at imgext{.jpeg}}
+\DeclareOption{gif}{\def\MGL at imgext{.gif}}
+\DeclareOption{tex}{\def\MGL at imgext{.tex}}
+%    \end{macrocode}
+% \end{macro}
+%
+% Any other option passed by the user is invalid, so an error message is issued.
+%    \begin{macrocode}
+
+\DeclareOption*{\@unknownoptionerror}
+%    \end{macrocode}
+%
+% We now declare the default package options, and, finally, process the options the user specifies in the order they are introduced.
+%    \begin{macrocode}
+
+\ExecuteOptions{final,on,nocomments,color,1x,2q,0v,eps}
+\ProcessOptions*
+%    \end{macrocode}
+%
+% \begin{macro}{\MGL at dir}
+% This is the \textsf{\mglTeX} main working directory. By default, it is defined to empty, so it points to the path of the \LaTeX{} document.
+%    \begin{macrocode}
+
+\def\MGL at dir{}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\MGL at scripts@dir}
+% The subdirectory inside |\MGL at dir| where all MGL scripts will be created.
+%    \begin{macrocode}
+\def\MGL at scripts@dir{}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\MGL at graphics@dir}
+% The subdirectory inside |\MGL at dir| where all MGL graphics will be created.
+%    \begin{macrocode}
+\def\MGL at graphics@dir{}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\MGL at backups@dir}
+% The subdirectory inside |\MGL at dir| where all backups of scripts will be created.
+%    \begin{macrocode}
+\def\MGL at backups@dir{}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\MGL at paths}
+% This is a list of paths where extracted and external scripts will be searched for by the |\mglgraphics| and |\mglinclude| commands. Since extracted scripts are created inside |\MGL at dir\MGL at scripts@dir| and |\MGL at dir\MGL at backups@dir|, this directories are included.
+%    \begin{macrocode}
+\def\MGL at paths{\MGL at dir\MGL at scripts@dir,\MGL at dir\MGL at backups@dir}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\MGL at main@script at name}
+% \noindent This macro stores the name of the of the document's main script. It is initialized to the name of the \LaTeX{} document.
+%    \begin{macrocode}
+
+\edef\MGL at main@script at name{\jobname}
+%    \end{macrocode}
+% \end{macro}
+%
+% We set some additional staff that will be used later.
+% \begin{macro}{\MGL at main@stream}
+% The output stream for the document's main script.
+%    \begin{macrocode}
+
+\newwrite\MGL at main@stream
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\MGL at out@stream}
+% The output stream for scripts other than the main one.
+%    \begin{macrocode}
+\newwrite\MGL at out@stream
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\MGL at in@stream}
+% The input stream for scripts other than the main one.
+%    \begin{macrocode}
+\newread\MGL at in@stream
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{MGL at script@no}
+% The internal counter used by environments like |mgl| and commands like |\mglplot| to automatically name scripts.
+%    \begin{macrocode}
+\newcounter{MGL at script@no}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{MGL at line@no}
+% The counter used for verbatim-like environments and commands to numerate the lines of code.
+%    \begin{macrocode}
+\newcounter{MGL at line@no}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{MGL at verb@no}
+% The counter used to numerate verbatim-written scripts with the |\listofmglscripts| command.
+%    \begin{macrocode}
+\newcounter{MGL at verb@no}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@MGL at list@script@}
+% The boolean switch used to determine whether to add a verbatim-written script to the \emph{list of MGL scripts}.
+%    \begin{macrocode}
+\newif\if at MGL@list at script@
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\l at MGL@script}
+% The style for the leaders associating script name and page number in the \emph{list of MGL scripts}.
+%    \begin{macrocode}
+\def\l at MGL@script{\@dottedtocline{1}{0em}{1.5em}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \textsf{\mglTeX} requires the \textsf{keyval} package to define \meta{key}=\meta{value} options for the environments and commands; the \textsf{graphicx} package apports the facilities for inclusion of graphics; the \textsf{ifpdf} package is used to determine whether the user is compiling to |pdf| or not when indicating the default graphics extensionsthe \textsf{verbatim} package is used as engine for the environments.
+%    \begin{macrocode}
+
+\RequirePackage{keyval}
+\RequirePackage{graphicx}
+\RequirePackage{ifpdf}
+\RequirePackage{verbatim}
+%    \end{macrocode}
+%
+% The supported graphic extensions are declared. These extensions depend on whether we are compiling to |pdf| or not, so the |\ifpdf| conditional from the homonym package is used.
+%    \begin{macrocode}
+\ifpdf%
+  \DeclareGraphicsExtensions{%
+    .pdf,.png,.jpg,.jpeg,.gif%
+  }%
+\else%
+  \DeclareGraphicsExtensions{%
+    .eps,.epsz,.eps.gz,.bps,.bpsz,.bps.gz%
+  }%
+\fi%
+%    \end{macrocode}
+% Finally, the |\verbatim at finish| command from the \textsf{verbatim} package is disabled to avoid it from writing a blank line at the end of every script (see subsection~\ref{subsection: warning}).
+%    \begin{macrocode}
+\let\verbatim at finish\relax
+%    \end{macrocode}
+%
+% \subsection{Anatomy of environments and commands}\label{subsection: anatomy}
+% \noindent Many of the environments and commands defined by \textsf{\mglTeX} are based on the same pieces of code. So, in order to avoid repetition of commands, we use the concept of \emph{anatomy of environments and commands}, which is basically the idea of taking repetitive pieces of code and enclose them into macros which can later be used.
+%
+% \begin{macro}{\MGL at setkeys}
+% This command receives two arguments: a family of \meta{key}=\meta{value} pairs, like |MGL at keys|, and a list of such pairs. It first cleans the |\MGL at graph@keys| macro, and the process the list of pairs.
+%    \begin{macrocode}
+
+\def\MGL at setkeys#1#2{%
+  \def\MGL at graph@keys{}%
+  \setkeys{#1}{#2}%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\MGL at graph@keys}
+% The main family of \meta{key}=\meta{value} pairs is defined. These pairs are common to every environment or command that produces graphics. Most of the \meta{key}'s are redefinitions of the optional arguments for the |\includegraphics| commands, so they are stored inside the |\MGL at graph@keys| macro, which is later passed to that command as optional argument by |\MGL at includegraphics|.
+%    \begin{macrocode}
+
+\define at key{MGL at gr@keys}{bb}{%
+  \g at addto@macro\MGL at graph@keys{bb=#1,}%
+}
+\define at key{MGL at gr@keys}{bbllx}{%
+  \g at addto@macro\MGL at graph@keys{bbllx=#1,}%
+}
+\define at key{MGL at gr@keys}{bblly}{%
+  \g at addto@macro\MGL at graph@keys{bblly=#1,}%
+}
+\define at key{MGL at gr@keys}{bburx}{%
+  \g at addto@macro\MGL at graph@keys{bburx=#1,}%
+}
+\define at key{MGL at gr@keys}{bbury}{%
+  \g at addto@macro\MGL at graph@keys{bbury=#1,}%
+}
+\define at key{MGL at gr@keys}{natwidth}{%
+  \g at addto@macro\MGL at graph@keys{natwidth=#1,}%
+}
+\define at key{MGL at gr@keys}{natheight}{%
+  \g at addto@macro\MGL at graph@keys{natheight=#1,}%
+}
+\define at key{MGL at gr@keys}{hiresbb}{%
+  \g at addto@macro\MGL at graph@keys{hiresbb=#1,}%
+}
+\define at key{MGL at gr@keys}{viewport}{%
+  \g at addto@macro\MGL at graph@keys{viewport=#1,}%
+}
+\define at key{MGL at gr@keys}{trim}{%
+  \g at addto@macro\MGL at graph@keys{trim=#1,}%
+}
+\define at key{MGL at gr@keys}{angle}{%
+  \g at addto@macro\MGL at graph@keys{angle=#1,}%
+}
+\define at key{MGL at gr@keys}{origin}{%
+  \g at addto@macro\MGL at graph@keys{origin=#1,}%
+}
+\define at key{MGL at gr@keys}{width}{%
+  \g at addto@macro\MGL at graph@keys{width=#1,}%
+}
+\define at key{MGL at gr@keys}{height}{%
+  \g at addto@macro\MGL at graph@keys{height=#1,}%
+}
+\define at key{MGL at gr@keys}{totalheight}{%
+  \g at addto@macro\MGL at graph@keys{totalheight=#1,}%
+}
+\define at key{MGL at gr@keys}{keepaspectratio}[true]{%
+  \g at addto@macro\MGL at graph@keys{keepaspectratio=#1,}%
+}
+\define at key{MGL at gr@keys}{scale}{%
+  \g at addto@macro\MGL at graph@keys{scale=#1,}%
+}
+\define at key{MGL at gr@keys}{clip}[true]{%
+  \g at addto@macro\MGL at graph@keys{clip=#1,}%
+}
+\define at key{MGL at gr@keys}{draft}[true]{%
+  \g at addto@macro\MGL at graph@keys{draft=#1,}%
+}
+\define at key{MGL at gr@keys}{type}{%
+  \g at addto@macro\MGL at graph@keys{type=#1,}%
+}
+\define at key{MGL at gr@keys}{ext}{%
+  \g at addto@macro\MGL at graph@keys{ext=#1,}%
+}
+\define at key{MGL at gr@keys}{read}{%
+  \g at addto@macro\MGL at graph@keys{read=#1,}%
+}
+\define at key{MGL at gr@keys}{command}{%
+  \g at addto@macro\MGL at graph@keys{command=#1,}%
+}
+%    \end{macrocode}
+% \end{macro}
+% The following four \meta{key}=\meta{value} pairs call the adequate \textsf{\mglTeX} command.
+%    \begin{macrocode}
+\define at key{MGL at gr@keys}{gray}[0]{\mglgray{#1}}
+\define at key{MGL at gr@keys}{mglscale}{\mglscale{#1}}
+\define at key{MGL at gr@keys}{quality}{\mglquality{#1}}
+\define at key{MGL at gr@keys}{variant}{\mglvariant{#1}}
+%    \end{macrocode}
+% \begin{macro}{\MGL at imgext}
+% |\MGL at imgext| stores the default extension for the creation of the graphics.
+%    \begin{macrocode}
+\define at key{MGL at gr@keys}{imgext}{\def\MGL at imgext{.#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@MGL at lineno@}
+% The only \meta{key}=\meta{value} pair needed for verbatim-like environments and commands is the one for the |lineno| option, which sets the value of the |\@MGL at lineno@| boolean macro.
+%    \begin{macrocode}
+
+\newif\if at MGL@lineno@
+\define at key{MGL at verb@keys}{lineno}[true]{\csname @MGL at lineno@#1\endcsname}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\MGL at codes}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{Bugfix: category code for tabulators is changed too}
+% This macro changes the category codes of all special characters (like |\|, |$|, etc.) to $12$ (other), so they don't have any special meaning and can be processed as normal text. The exception is the new line character (|^^M|), which is kept active for compatibility with the \textsf{verbatim} package.
+%    \begin{macrocode}
+
+\def\MGL at codes{%
+  \let\do\@makeother\dospecials%
+  \catcode`\^^I=12%
+  \catcode`\^^M\active%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\MGL at doc@scripts}
+% A macro to store the names of the scripts created or compiled in the document.
+%    \begin{macrocode}
+
+\def\MGL at doc@scripts{}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\MGL at set@script at name}\begin{macro}{\MGL at script}
+% |\MGL at set@script at name| receives the name of a script without extension as argument, defines |\MGL at script| as that name, and checks if it has already been created or compiled, by comparing it with the names already stored in |\MGL at doc@scripts|; if it's there already, warns the user. Finally, adds the name of the script to |\MGL at doc@scripts|.
+%    \begin{macrocode}
+\def\MGL at set@script at name#1{%
+  \edef\MGL at script{#1}%
+  \@for\MGL at temp@a:=\MGL at doc@scripts\do{%
+    \ifx\MGL at temp@a\MGL at script%
+      \PackageWarning{mgltex}{Multiple MGL scripts named "\MGL at script.mgl"}%
+    \fi%
+  }%
+  \g at addto@macro\MGL at doc@scripts{\MGL at script,}%
+}
+%    \end{macrocode}
+% \end{macro}\end{macro}
+%
+% \begin{macro}{\MGL at unchanged}
+% This command defines the ``switch'' |\MGL@@@|\meta{script}, where \meta{script} is passed as argument, which indicates the script \meta{script}|.mgl| has not changed. This command has to be written to the |.aux| file to be preserved from compilation to compilation.
+%    \begin{macrocode}
+
+\def\MGL at unchanged#1{%
+  \global\@namedef{MGL@@@#1}{}%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\MGL at process@script}
+% It checks whether the ``switch'' |\MGL@@@\MGL at script| is undefined, in which case executes its first argument. If the switch is defined, it checks if the corresponding image has been created; if so, it executes its second argument; otherwise, the first one.
+%    \begin{macrocode}
+
+\def\MGL at process@script#1#2{%
+  \@ifundefined{MGL@@@\MGL at script}{%
+    #1%
+  }{%
+    \IfFileExists{\MGL at dir\MGL at graphics@dir\MGL at script\MGL at imgext}{%
+      #2%
+    }{%
+      #1%
+    }%
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\MGL at def@for at loop}\begin{macro}{\MGL at for}
+% |\MGL at def@for at loop| defines the command |\MGL at for| which is similar to the |\@for| command from the \LaTeX{} kernel, with the only exception that, instead of iterating over comma-separated lists, it can iterate over lists of items with any kind of separator, which is passed as argument of |\MGL at def@for at loop|. The body of this command is copied from the definition code of |\@for|, extracted from \emph{The \LaTeXe{} Sources} document, replacing the ``|,|'' by ``|#1|''. Note that |\MGL at fo [...]
+%    \begin{macrocode}
+
+\def\MGL at def@for at loop#1{%
+  \long\def\MGL at for##1:=##2\do##3{%
+    \expandafter\def\expandafter\@fortmp\expandafter{##2}%
+    \ifx\@fortmp\@empty\else%
+      \expandafter\MGL at forloop##2#1\@nil#1\@nil\@@##1{##3}%
+    \fi%
+  }%
+  \long\def\MGL at forloop##1#1##2#1##3\@@##4##5{%
+    \def##4{##1}%
+    \ifx##4\@nnil\else%
+      ##5\def##4{##2}%
+      \ifx##4\@nnil\else%
+        ##5\MGL at iforloop##3\@@##4{##5}%
+      \fi%
+    \fi%
+  }%
+  \long\def\MGL at iforloop##1#1##2\@@##3##4{%
+    \def##3{##1}%
+    \ifx##3\@nnil%
+      \expandafter\@fornoop%
+    \else%
+      ##4\relax\expandafter\MGL at iforloop%
+    \fi%
+    ##2\@@##3{##4}%
+  }%
+}
+%    \end{macrocode}
+% The default |\MGL at for| loop iterates over |^^J|-separated lists, i.e, \meta{new line}-character-lists.
+%    \begin{macrocode}
+\MGL at def@for at loop{^^J}
+%    \end{macrocode}
+% \end{macro}\end{macro}
+%
+% \begin{macro}{\MGL at compare@code}
+% |\MGL at compare@code| is in charge of comparing the user's MGL code, embedded within \textsf{\mglTeX} environments, with its corresponding extracted script. For that purpose, the |\verbatim at processline| and |\verbatim at finish| commands from the \textsf{verbatim} package are redefined.
+%    \begin{macrocode}
+
+\def\MGL at compare@code#1{%
+%    \end{macrocode}
+% \begin{macro}{\MGL at next}
+% This macro is called at the end of environments that use the |\MGL at compare@code| macro, and performs the ending actions of the comparision process, which are closing the |\MGL at in@stream| and writing the |\MGL at unchanged{\MGL at script}| to the |.aux| file. If during the comparison process a difference in the code is found, |\MGL at next| is redefined to only close the |\MGL at in@stream|.
+%    \begin{macrocode}
+  \def\MGL at next{%
+    \MGL at closein\MGL at in@stream%
+    \MGL at write\@auxout{\string\MGL at unchanged{\MGL at script}}%
+  }%
+%    \end{macrocode}
+% \end{macro}
+% The |\verbatim at processline| command is redefined to read from the input stream to a temporary variable (|\MGL at temp@a|), and compare it with one line of code in the \LaTeX{} document, which is stored in another temporary variable (|\MGL at temp@b|). In case they are not equal, the |\MGL at next| macro is redefined to only close the input stream, and |\verbatim at processline| is redefine again to do nothing (a little speed-up).
+%    \begin{macrocode}
+  \def\verbatim at processline{%
+    \MGL at read\MGL at in@stream{\MGL at temp@a}%
+    \edef\MGL at temp@b{\the\verbatim at line}%
+    \ifx\MGL at temp@a\MGL at temp@b\else%
+      \def\MGL at next{\MGL at closein\MGL at in@stream}%
+      \def\verbatim at processline{}%
+    \fi%
+  }%
+%    \end{macrocode}
+% The |\verbatim at finish| macro, which is called at the end of the environment, is also redefined to perform one last read of the input stream, and then check if the end of file has been reached; if it hasn't, then, despite the end of the environment has been reached ---thus the end of code---, there is still code inside the script, so there are differences between them, and |\MGL at next| has to be redefined to do nothing but close the input stream.
+%    \begin{macrocode}
+  \def\verbatim at finish{%
+    \MGL at read\MGL at in@stream{\MGL at temp@a}%
+    \ifeof\MGL at in@stream\else%
+      \def\MGL at next{\MGL at closein\MGL at in@stream}%
+    \fi%
+  }%
+%    \end{macrocode}
+% Finally, the input stream is opened, and the comparison is started by calling |\verbatim at start|.
+%    \begin{macrocode}
+  \MGL at openin\MGL at in@stream{#1}%
+  \verbatim at start%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\MGL at write@funcs}
+% This macro is used only by the |mglfunc| environment. Its only purpose is to store the commands to insert MGL functions in the main script, and is called at the end of the document or when the |\mglname| command is used. For now, we only ask it to write the |stop| command\footnote{Note the |stop| command is unnecesary in newer versions of the MGL language, but it is kept in \textsf{\mglTeX} for compatibility and for elegance.} that separates the section of scripts from the section of f [...]
+%    \begin{macrocode}
+
+\def\MGL at write@funcs{\MGL at write\MGL at main@stream{stop^^J}}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\MGL at func}
+% This is the command that writes the MGL functions. It is intended to be stored inside |\MGL at write@funcs|. It opens the backup file of the MGL function whose name is passed as argument (and has been created by a |mglfunc| environment), and then calls |\MGL@@func| to transcript from that file, line by line, to the main script.
+%    \begin{macrocode}
+\def\MGL at func#1{%
+  \MGL at openin\MGL at in@stream{\MGL at dir\MGL at backups@dir#1.mgl}%
+  \MGL@@func%
+}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\MGL@@func}
+% This command transcripts only one line from backup file of a MGL function to the main script. It calls itself recursively until the end of the backup.
+%    \begin{macrocode}
+\def\MGL@@func{%
+%    \end{macrocode}
+% It first reads from the input stream to the |\MGL at temp@a| temporary variable.
+%    \begin{macrocode}
+  \MGL at read\MGL at in@stream{\MGL at temp@a}%
+%    \end{macrocode}
+% If the end of the file has been reached, the stream is closed.
+%    \begin{macrocode}
+  \ifeof\MGL at in@stream%
+    \MGL at closein\MGL at in@stream%
+%    \end{macrocode}
+% If the end of file hasn't been reached, |\MGL at temp@a| is written to the main script, and |\MGL@@func| is called recursively.
+%    \begin{macrocode}
+  \else%
+    \MGL at write\MGL at main@stream{\MGL at temp@a}%
+    \expandafter\MGL@@func%
+  \fi%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\MGL at set@verbatim at code}
+% This command sets the parameters for verbatim-like environments and commands.
+%    \begin{macrocode}
+
+\def\MGL at set@verbatim at code{%
+%    \end{macrocode}
+% The following is standard stuff for verbatim-like environments and commands.
+%    \begin{macrocode}
+  \if at minipage\else\vskip\parskip\fi%
+  \leftskip\@totalleftmargin\rightskip\z at skip%
+  \parindent\z@\parfillskip\@flushglue\parskip\z@%
+  \@@par%
+  \def\par{%
+    \if at tempswa%
+      \leavevmode\null\@@par\penalty\interlinepenalty%
+    \else%
+      \@tempswatrue%
+      \ifhmode\@@par\penalty\interlinepenalty\fi%
+    \fi%
+  }%
+  \obeylines%
+  \let\do\@makeother\dospecials%
+  \verbatim at font%
+  \frenchspacing%
+  \everypar\expandafter{\the\everypar\unpenalty}%
+%    \end{macrocode}
+% If there are no lines of MGL code, instead of issuing an error, we display a package warning.
+%    \begin{macrocode}
+  \def\@noitemerr{\PackageWarning{mglTeX}{Empty MGL script}}%
+%    \end{macrocode}
+% The space between the end of the label box and the text of the first item (|\labelsep|) is set to |1em|, while the separation between items (|\itemsep|) is set to zero.
+%    \begin{macrocode}
+  \labelsep1em%
+  \itemsep\z@%
+%    \end{macrocode}
+% Since we want the lines of code to be broken between words, but verbatim spaces are unbreakable, we trick \LaTeX{} by inserting a breakable spaces (|\space|) instead.
+%    \begin{macrocode}
+  \def\@xobeysp{\space}\@vobeyspaces%
+%    \end{macrocode}
+% However, \LaTeX{} still resists breaking lines as much as possible in order to preserve the shape of paragraphs, so we tell it it's OK not to do so by setting the badness tolerance before hyphenation (|\pretolerance|) and the badness above which bad hboxes will be shown (|\hbadness|) to the maximum value of $10000$ (|\@M|).
+%    \begin{macrocode}
+  \pretolerance\@M%
+  \hbadness\@M%
+%    \end{macrocode}
+% In order to achieve the desired indentation of broken lines, we use the following trick: We increase the |\leftskip| parameter by the amount specified by |\mglbreakindent|, so that lines will be indented; but then we decrease the |\itemindent| parameter by the same amount so the first line won't be indented.
+%    \begin{macrocode}
+  \advance\leftskip\mglbreakindent%
+  \itemindent-\mglbreakindent%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\MGL at line@sep}
+% This is the separator displayed at the beginning and ending of the |mglblock| and |mglverbatim| environments, to distinguish the MGL code from the normal text. Its definition is similar to the one of the |\dotfill| command, which can be found in \emph{The \LaTeXe{} Sources} document, but |\nopagebreak| commands have been added to avoid unaesthetic page breaking before and after the separators.
+%    \begin{macrocode}
+
+\def\MGL at line@sep{%
+  \nopagebreak%
+  \leavevmode\cleaders\hrule height\mgllinethickness\hfill\kern\z@%
+  \nopagebreak%
+}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\MGL at dash@sep}
+% This is the separator displayed at the beginning and ending of the |mglcomments| environment, when it is allowed to be displayed.
+%    \begin{macrocode}
+\def\MGL at dash@sep{%
+  \nopagebreak%
+  \leavevmode\cleaders\hb at xt@\mgldashwidth{\hss-\hss}\hfill\kern\z@%
+  \nopagebreak%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Environments for MGL code embedding}
+% \noindent For the following, we agree that if a macro is required by an environment, and it hasn't been already defined, it will be defined between the commands that start and end such environment; also the command's name will have the environment's name as prefix.
+%
+% \begin{environment}{mgl}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{New environment options: \texttt{gray}, \texttt{mglscale}, \texttt{quality}, \texttt{variant}}
+% This environment has to transcript its contents to the document's main script, and create a backup of the code simultaneously; the backup is used to detect changes in following compilations.
+% \begin{macro}{\mgl}
+% The command that starts the |mgl| environment. It is called by the |\begin{mgl}| command.
+%    \begin{macrocode}
+
+\newcommand\mgl[1][]{%
+%    \end{macrocode}
+% We define an additional \meta{key}=\meta{value} pair in the main family of pairs, corresponding to the |label| option for this environment. This definition is local because we don't want to be valid outside the environment.
+%    \begin{macrocode}
+  \define at key{MGL at gr@keys}{label}{\def\MGL at script{##1}}%
+%    \end{macrocode}
+% The list of comma-separated options is processed.
+%    \begin{macrocode}
+  \MGL at setkeys{MGL at gr@keys}{#1}%
+%    \end{macrocode}
+% If the user hasn't used the |label| option, the automatic naming mechanism is called. Note that |\MGL at main@script at name| is set using the |\mglname| command.
+%    \begin{macrocode}
+  \@ifundefined{MGL at script}{%
+    \stepcounter{MGL at script@no}%
+    \edef\MGL at script{\MGL at main@script at name-MGL-\arabic{MGL at script@no}}%
+  }{}%
+%    \end{macrocode}
+% We use the |\MGL at set@script at name| to test whether the given name has already been used.
+%    \begin{macrocode}
+  \MGL at set@script at name{\MGL at script}%
+%    \end{macrocode}
+% |\MGL at codes| is used to change the codes of special characters.
+%    \begin{macrocode}
+  \MGL at codes%
+%    \end{macrocode}
+% |\MGL at process@script| is used to test whether the code has changed or not the last time \LaTeX{} has been executed. If it has changed, we call the |\MGL at write@script| command to (re)write the code; otherwise, the code is scanned again by asking |\MGL at compare@code| to perform a comparison on the backup file, in order to determine whether the code has changed now.
+%    \begin{macrocode}
+  \MGL at process@script{%
+    \MGL at write@script%
+  }{%
+    \MGL at compare@code{\MGL at dir\MGL at backups@dir\MGL at script.mgl}%
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\MGL at write@script}
+% (Re)writes the contents of the |mgl| environment.
+%    \begin{macrocode}
+\def\MGL at write@script{%
+%    \end{macrocode}
+% \begin{macro}{\MGL at next}
+% It contains the actions to perform immediately after the end of |\MGL at write@script|. They are close the output stream; write in the main script the commands to save the image, and to reset the initial values for all MGL parameters and clear the image; finally, write |\MGL at unchanged{\MGL at script}| in the |.aux| file.
+%    \begin{macrocode}
+  \def\MGL at next{%
+    \MGL at closeout\MGL at out@stream%
+    \MGL at write\MGL at main@stream{%
+      write '\MGL at dir\MGL at graphics@dir\MGL at script\MGL at imgext'^^J%
+      ^^Jreset^^J%
+    }%
+    \MGL at write\@auxout{\string\MGL at unchanged{\MGL at script}}%
+  }%
+%    \end{macrocode}
+% \end{macro}
+% Now we redefine the |\verbatim at processline| macro to write |\the\verbatim at line| to the main script and to the backup file.
+%    \begin{macrocode}
+  \def\verbatim at processline{%
+    \MGL at write\MGL at main@stream{\the\verbatim at line}%
+    \MGL at write\MGL at out@stream{\the\verbatim at line}%
+  }%
+%    \end{macrocode}
+% Before writing the MGL code of the environment, we set the default gray/color mode, mglscale, quality and variant.
+%    \begin{macrocode}
+  \MGL at write\MGL at main@stream{%
+    gray \MGL at gray^^J%
+    setsizescl \MGL at scale^^J%
+    quality \MGL at quality^^J%
+    variant \MGL at variant%
+  }%
+%    \end{macrocode}
+% We open the backup file in the output stream.
+%    \begin{macrocode}
+  \MGL at openout\MGL at out@stream{\MGL at dir\MGL at backups@dir\MGL at script.mgl}%
+%    \end{macrocode}
+% The transcription process starts by calling the |\verbatim at start| command.
+%    \begin{macrocode}
+  \verbatim at start%
+}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\endmgl}
+% The command that ends the |mgl| evironment. It is called by the |\end{mgl}| command. It simply calls |\MGL at next| to execute the final actions, and |\MGL at includegraphics| to insert the corresponding image. Note that |\MGL at next| performs different actions depending on whether |\MGL at process@script| calls |\MGL at write@script| or |\MGL at compare@code|, both of which define |\MGL at next| differently.
+%    \begin{macrocode}
+\def\endmgl{%
+  \MGL at next%
+  \MGL at includegraphics%
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{environment}
+%
+% \begin{environment}{mgladdon}
+% This environment only writes its contents to the document's main script, so no backup is created, nor compilation or inclusion of graphics.
+% \begin{macro}{\mgladdon}
+% Since this environment doesn't produce any output in the \LaTeX{} document, we start a \emph{space hack} by calling |\@bsphack|. We set the appropiate category codes with |\MGL at codes|; the |\verbatim at processline| is redefined to transcript |\the\verbatim at line| to the main script; finally, the |\verbatim at start| command starts the transcription process.
+%    \begin{macrocode}
+
+\def\mgladdon{%
+  \@bsphack%
+  \MGL at codes%
+  \def\verbatim at processline{%
+    \MGL at write\MGL at main@stream{\the\verbatim at line}%
+  }%
+  \verbatim at start%
+}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\endmgladdon}
+% The environment ends by closing the \emph{space hack} with |\@esphack|.
+%    \begin{macrocode}
+\def\endmgladdon{\@esphack}
+%    \end{macrocode}
+% \end{macro}
+% \end{environment}
+%
+% \begin{environment}{mglfunc}
+% This environment is used to define MGL functions inside the document's main script. Instead of writing directly to the main script, which would cause the MGL parser to end the execution of that script, it writes to a backup file which is later transcript before closing the main script.
+% \begin{macro}{\mglfunc}
+% It starts the |mglfunc| environment.
+%    \begin{macrocode}
+
+\newcommand\mglfunc[2][0]{%
+%    \end{macrocode}
+% Once again, since this command doesn't produce any output in the \LaTeX{} document, we use a \emph{space hack}.
+%    \begin{macrocode}
+  \@bsphack%
+%    \end{macrocode}
+% Although MGL functions and normal scripts are diferent in nature, in the sense that the first don't produce graphics by themselves, we have to check whether the function is being named as another script, because otherwise we run the risk of overwriting a backup file or confusing the parser.
+%    \begin{macrocode}
+  \MGL at set@script at name{#2}%
+%    \end{macrocode}
+% The instruction to transcript from the backup file to the main stream is stored in |\MGL at write@funcs| (see subsection \ref{subsection: anatomy}).
+%    \begin{macrocode}
+  \g at addto@macro\MGL at write@funcs{\MGL at func{#2}}%
+%    \end{macrocode}
+% The codes for special characters are set.
+%    \begin{macrocode}
+  \MGL at codes%
+%    \end{macrocode}
+% The |\verbatim at processline| command is redefined to write |\the\verbatim at line| to the backup file.
+%    \begin{macrocode}
+  \def\verbatim at processline{\MGL at write\MGL at out@stream{\the\verbatim at line}}%
+%    \end{macrocode}
+% The backup file is opened for writing.
+%    \begin{macrocode}
+  \MGL at openout\MGL at out@stream{\MGL at dir\MGL at backups@dir\MGL at script.mgl}%
+%    \end{macrocode}
+% The head of the function is written.
+%    \begin{macrocode}
+  \MGL at write\MGL at out@stream{func '\MGL at script' #1}%
+%    \end{macrocode}
+% The writing process is started.
+%    \begin{macrocode}
+  \verbatim at start%
+}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\endmglfunc}
+% It ends the |mglfunc| environment.
+%    \begin{macrocode}
+\def\endmglfunc{%
+%    \end{macrocode}
+% The end of the function is written.
+%    \begin{macrocode}
+  \MGL at write\MGL at out@stream{return^^J}%
+%    \end{macrocode}
+% The output stream is closed.
+%    \begin{macrocode}
+  \MGL at closeout\MGL at out@stream%
+%    \end{macrocode}
+% The \emph{space hack} is terminated.
+%    \begin{macrocode}
+  \@esphack%
+}%
+%    \end{macrocode}
+% \end{macro}
+% \end{environment}
+%
+% \begin{environment}{mglcode}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{New environment options: \texttt{gray}, \texttt{mglscale}, \texttt{quality}, \texttt{variant}}
+% This environment also checks for changes on the code, but, since it writes to its own script, there is no need to create a backup file (the check is performed using the script itself).
+% \begin{macro}{\mglcode}
+% It starts the |mglcode| environment. Its anatomy is similar to that of the |\mgl| command.
+%    \begin{macrocode}
+
+\newcommand\mglcode[2][]{%
+  \MGL at setkeys{MGL at gr@keys}{#1}%
+  \MGL at set@script at name{#2}%
+  \MGL at codes%
+  \MGL at process@script{%
+    \mglcode at write@script%
+  }{%
+    \MGL at compare@code{\MGL at dir\MGL at scripts@dir\MGL at script.mgl}%
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\mglcode at write@script}
+% This command takes care of creating the script for the |mglcode| environment.
+%    \begin{macrocode}
+\def\mglcode at write@script{%
+%    \end{macrocode}
+% \begin{macro}{\MGL at next}
+% It performs the actions immediately following the end of |\mglcode at write@script|.
+%    \begin{macrocode}
+  \def\MGL at next{%
+%    \end{macrocode}
+% The output stream is closed.
+%    \begin{macrocode}
+    \MGL at closeout\MGL at out@stream%
+%    \end{macrocode}
+% The |\MGL at unchanged{\MGL at script}| command is written to the |.aux| file.
+%    \begin{macrocode}
+    \MGL at write\@auxout{\string\MGL at unchanged{\MGL at script}}%
+%    \end{macrocode}
+% The script compilation instruction is written to the terminal.
+%    \begin{macrocode}
+    \MGL at write{18}{%
+      mglconv -q \MGL at quality\space -g \MGL at gray\space%
+      -S \MGL at scale\space -v \MGL at variant\space%
+      -s "\MGL at dir\MGL at scripts@dir\mglsetupscriptname.mgl"\space%
+      -o "\MGL at dir\MGL at graphics@dir\MGL at script\MGL at imgext"\space%
+      "\MGL at dir\MGL at scripts@dir\MGL at script.mgl"%
+    }%
+  }%
+%    \end{macrocode}
+% \end{macro}
+% The |\verbatim at processline| command is redefined so it writes |\the\verbatim at line| to the output stream.
+%    \begin{macrocode}
+  \def\verbatim at processline{\MGL at write\MGL at out@stream{\the\verbatim at line}}%
+%    \end{macrocode}
+% The script is opened for writing in the output stream.
+%    \begin{macrocode}
+  \MGL at openout\MGL at out@stream{\MGL at dir\MGL at scripts@dir\MGL at script.mgl}%
+%    \end{macrocode}
+% The writing process is started by calling the |\verbatim at start| command.
+%    \begin{macrocode}
+  \verbatim at start%
+}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\endmglcode}
+% It ends the |mglcode| environment. |\MGL at next| is called to perform the final actions and |\MGL at includegraphics| is called to insert the corresponding image. Once more, |\MGL at next| has different meanings depending on whether |\MGL at process@script| branches to |\MGL at compare@code| or |\mglcode at write@script|.
+%    \begin{macrocode}
+\def\endmglcode{%
+  \MGL at next%
+  \MGL at includegraphics%
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{environment}
+% \begin{environment}{mglscript}
+% The only function of this environment is to write its contents to a script; no image is created. It has been considered that scanning the code looking for changes is as much operation-expensive as simply writing the code, so it has been decided that this environment (over)writes the script everytime it's executed, without performing any check.
+% \begin{macro}{\mglscript}
+% Starts the environment. Its anatomy is similar to the previous environments. Since no output is written to the \LaTeX{} document, a \emph{space hack} is used.
+%    \begin{macrocode}
+
+\def\mglscript#1{%
+  \@bsphack%
+  \MGL at set@script at name{#1}%
+  \MGL at codes%
+  \def\verbatim at processline{\MGL at write\MGL at out@stream{\the\verbatim at line}}%
+  \MGL at openout\MGL at out@stream{\MGL at dir\MGL at scripts@dir\MGL at script.mgl}%
+  \verbatim at start%
+}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\endmglscript}
+% It ends the |mglscript| environment. The \emph{space hack} ends here, too.
+%    \begin{macrocode}
+\def\endmglscript{%
+  \MGL at closeout\MGL at out@stream%
+  \@esphack%
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{environment}
+%
+% \begin{environment}{mglsetupscript}\begin{environment}{mglcommon}
+% This environment doesn't require any backup file nor any scanning for changes. Although the user sets the name of the script by redifining |\mglsetupscriptname|, it is necessary to perform a check of the name, just in case a name has been inadvertedly repeated.
+% \begin{macro}{\mglsetupscript}
+% Starts the |mglsetupscript| environment.
+%    \begin{macrocode}
+
+\def\mglsetupscript{%
+  \@bsphack%
+  \MGL at set@script at name{\mglsetupscriptname}%
+  \MGL at codes%
+  \def\verbatim at processline{\MGL at write\MGL at out@stream{\the\verbatim at line}}%
+  \MGL at openout\MGL at out@stream{\MGL at dir\MGL at scripts@dir\MGL at script.mgl}%
+  \verbatim at start%
+}
+%    \end{macrocode}
+% It is declared to be an only-preamble command, so it can't be used after the |\begin{document}| instruction.
+%    \begin{macrocode}
+\@onlypreamble\mglsetupscript
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\mglcommon}
+% This macro is defined to be a synonym for |\mglcommon| (to keep backwards compatibility).
+%    \begin{macrocode}
+\let\mglcommon\mglsetupscript
+\@onlypreamble\mglcommon
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\endmglsetupscript}
+% It ends the |mglsetupscript| environment.
+%    \begin{macrocode}
+\def\endmglsetupscript{%
+  \MGL at closeout\MGL at out@stream%
+  \@esphack%
+}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\endmglcommon}
+% It is defined to be a synonym for |\endmglsetupscript|.
+%    \begin{macrocode}
+\let\endmglcommon\endmglsetupscript
+%    \end{macrocode}
+% \end{macro}
+% \end{environment}\end{environment}
+%
+% \subsection{Fast creation of graphics}
+% \begin{environment}{mglsetup}
+% This environment is meant to contain code that is executed just before the instruction of a |\mglplot| command, producing always the same ouput. Instead of writing a new chunk of code for that purpose, |mglsetup| is defined as a special case of the |mglfunc| environment, with the exception that the MGL function obtained this way doesn't accept any argument ---thus producing always the same output.
+% \begin{macro}{\mglsetup}
+% It is defined as an alias for |\mglfunc|, but only the name of the MGL function is passed to it, forcing the assumption that its number of arguments is zero.
+%    \begin{macrocode}
+
+\def\mglsetup#1{\mglfunc{#1}}%
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\endmglsetup}
+% Likewise, it is defined as an alias for |\endmglfunc|.
+%    \begin{macrocode}
+\let\endmglsetup\endmglfunc
+%    \end{macrocode}
+% \end{macro}
+% \end{environment}
+%
+% \begin{macro}{\mglplot}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{Added \doccommand{bgroup} and \doccommand{egroup} in order to keep changes private}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{New command options: \texttt{gray}, \texttt{mglscale}, \texttt{quality}, \texttt{variant}}
+% Although the function of this command is quite simple and straightforward, it requires many lines of code and some tricks in order to reach the desired functionality.
+%    \begin{macrocode}
+
+\newcommand\mglplot[2][]{%
+%    \end{macrocode}
+% Since this is a command, we need to explicitly create a local group so that all changes keep private to the command.\footnote{In contrast, environments keep changes private by default.}
+%    \begin{macrocode}
+  \bgroup%
+%    \end{macrocode}
+% We add some \meta{key}=\meta{value} pairs locally. The |label| key works exactly as the one of the |mgl| environment.
+%    \begin{macrocode}
+  \define at key{MGL at gr@keys}{label}{\edef\MGL at script{##1}}%
+%    \end{macrocode}
+% The |setup| key defines the variable |\MGL at mglplot@setup| which is later used to call a setup function for the corresponding image.
+%    \begin{macrocode}
+  \define at key{MGL at gr@keys}{setup}{\def\MGL at mglplot@setup{##1}}%
+%    \end{macrocode}
+% The |separator| key uses the |\MGL at def@for at loop| to define |\MGL at for| so that it iterates over lists separated by the indicated separator symbol.
+%    \begin{macrocode}
+  \define at key{MGL at gr@keys}{separator}{\MGL at def@for at loop{##1}}%
+%    \end{macrocode}
+% Now, we process the keys passed by the user.
+%    \begin{macrocode}
+  \MGL at setkeys{MGL at gr@keys}{#1}%
+%    \end{macrocode}
+% If the user hasn't specified a name using the |label| option, then a name is autogenerated following the same naming mechanism of the |mgl| environment.
+%    \begin{macrocode}
+  \@ifundefined{MGL at script}{%
+    \stepcounter{MGL at script@no}
+    \edef\MGL at script{\MGL at main@script at name-MGL-\arabic{MGL at script@no}}
+  }{}%
+%    \end{macrocode}
+% The name of the script is checked.
+%    \begin{macrocode}
+  \MGL at set@script at name{\MGL at script}%
+%    \end{macrocode}
+% If the user hasn't specified a setup, then the only code that has to be written is the non-optional argument of |\mglplot|; it is stored in the temporary variable |\MGL at temp@a|.
+%    \begin{macrocode}
+  \@ifundefined{MGL at mglplot@setup}{%
+    \edef\MGL at temp@a{#2}%
+  }{%
+%    \end{macrocode}
+% If the user has specified a setup, we store the code to call the setup and the code passed by the user in the temporary variable |\MGL at temp@a|.
+%    \begin{macrocode}
+    \edef\MGL at temp@a{call '\MGL at mglplot@setup'^^J#2}%
+  }
+%    \end{macrocode}
+% If the code has changed the last time \LaTeX{} has been run, we call |\mglplot at write@script| to (re)write and (re)compile the script; otherwise, we call |\mglplot at compare@code| to check if it has changed this time.
+%    \begin{macrocode}
+  \MGL at process@script{%
+    \mglplot at write@script%
+  }{%
+    \mglplot at compare@code%
+  }%
+%    \end{macrocode}
+% The corresponding image is included in the document.
+%    \begin{macrocode}
+  \MGL at includegraphics%
+%    \end{macrocode}
+% Finally, the local group is closed.
+%    \begin{macrocode}
+  \egroup%
+}
+%    \end{macrocode}
+% \begin{macro}{\mglplot at write@script}
+% This command takes the code stored in the |\MGL at temp@a| variable by the |\mglplot| command and writes it to the document's main script and to a backup file, so changes in the code can be detected.
+%    \begin{macrocode}
+\def\mglplot at write@script{%
+%    \end{macrocode}
+% The default quality is written to the main script.
+%    \begin{macrocode}
+  \MGL at write\MGL at main@stream{%
+    gray \MGL at gray^^J%
+    setsizescl \MGL at scale^^J%
+    quality \MGL at quality^^J%
+    variant \MGL at variant%
+  }%
+%    \end{macrocode}
+% The backup file is opened to write in the output stream.
+%    \begin{macrocode}
+  \MGL at openout\MGL at out@stream{\MGL at dir\MGL at backups@dir\MGL at script.mgl}%
+%    \end{macrocode}
+% Now we use the |\MGL at for| command to iterate over |\MGL at temp@a|. It takes a piece of code up to the separator symbol indicated by the user, and stores it in the temporary variable |\MGL at temp@b|, which is then written to the main script and backup file.
+%    \begin{macrocode}
+  \MGL at for\MGL at temp@b:=\MGL at temp@a\do{%
+    \MGL at write\MGL at main@stream{\MGL at temp@b}%
+    \MGL at write\MGL at out@stream{\MGL at temp@b}%
+  }%
+%    \end{macrocode}
+% The output stream is closed.
+%    \begin{macrocode}
+  \MGL at closeout\MGL at out@stream%
+%    \end{macrocode}
+% The instructions to save the image and reset the MGL parameters are written to the main script.
+%    \begin{macrocode}
+  \MGL at write\MGL at main@stream{%
+    write '\MGL at dir\MGL at graphics@dir\MGL at script\MGL at imgext'^^J%
+    ^^Jreset^^J%
+  }%
+%    \end{macrocode}
+% Finally, |\MGL at unchanged{\MGL at script}| is written to the |.aux| file.
+%    \begin{macrocode}
+  \MGL at write\@auxout{\string\MGL at unchanged{\MGL at script}}%
+}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\mglplot at compare@code}
+% This macro is in charge of comparing the code from a |\mglplot| command to detect changes.
+%    \begin{macrocode}
+\def\mglplot at compare@code{%
+%    \end{macrocode}
+% The action that will finish this command is, for now, to write |\MGL at unchanged{\MGL at script}| in the |.aux| file; it is stored in the |\MGL at next| variable. If no changes in the code are found, this will remain as the last action; otherwise, it will be overwritten to do nothing.
+%    \begin{macrocode}
+  \def\MGL at next{\MGL at write\@auxout{\string\MGL at unchanged{\MGL at script}}}%
+%    \end{macrocode}
+% The backup file is opened for reading in the input stream.
+%    \begin{macrocode}
+  \MGL at openin\MGL at in@stream{\MGL at dir\MGL at backups@dir\MGL at script.mgl}%
+%    \end{macrocode}
+% Once again, the |\MGL at for| command is used to iterate over the |\MGL at temp@a| variable defined by |\mglplot|. Pieces of code are taken up to the appearance of the separator symbol indicated by the user. In every iteration, the corresponding piece of code is stored in the |\MGL at temp@b| variable, one line of code is read from the input stream to the variable |\MGL at temp@c|, and these two are compared; if they are different, we redefined |\MGL at next| to do nothing.
+%    \begin{macrocode}
+  \MGL at for\MGL at temp@b:=\MGL at temp@a\do{%
+    \MGL at read\MGL at in@stream{\MGL at temp@c}%
+    \ifx\MGL at temp@b\MGL at temp@c\else%
+      \let\MGL at next\relax%
+    \fi%
+  }%
+%    \end{macrocode}
+% The input stream is closed.
+%    \begin{macrocode}
+  \MGL at closein\MGL at in@stream%
+%    \end{macrocode}
+% |\MGL at next| is executed.
+%    \begin{macrocode}
+  \MGL at next%
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Verbatim-like environments}
+% \begin{environment}{mglblock}
+% \begin{environment}{mglblock*}
+% The main body of these environments is the same; the only difference is that the unstarred version creates an entry in the |\listofmglscripts|, while the starred version doesn't.
+% \begin{macro}{\mglblock}
+% This command defines the switch |\@MGL at list@script@| as true, so a |\listofmglscripts| entry for the code is created, then calls the main body of the environment (|\mglblock@|).
+%    \begin{macrocode}
+
+\def\mglblock{\@MGL at list@script at true\mglblock@}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\mglblock*}
+% This command defines the switch |\@MGL at list@script@| as false, so no |\listofmglscripts| entry is created, then calls the main body of the environment (|\mglblock@|).
+%    \begin{macrocode}
+\@namedef{mglblock*}{\@MGL at list@script at false\mglblock@}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\mglblock@}
+% This macro contains the real functionality of the |mglblock| and |mglblock*| environments. It is the common code they both have.
+%    \begin{macrocode}
+\newcommand\mglblock@[2][]{%
+%    \end{macrocode}
+% First, the switch |\@MGL at lineno@| is set to true, so the lines of code will be numbered by default.
+%    \begin{macrocode}
+  \@MGL at lineno@true%
+%    \end{macrocode}
+% Now we process the decision of the user of keeping the line numbering or not.
+%    \begin{macrocode}
+  \setkeys{MGL at verb@keys}{#1}%
+%    \end{macrocode}
+% The name of the script is checked for repetition.
+%    \begin{macrocode}
+  \MGL at set@script at name{#2}%
+%    \end{macrocode}
+% If the switch |\@MGL at list@script@| is true, we increase the counter for verbatim code (|MGL at verb@no|), and add a contents line to the |.lms| file, using the style set by |\l at MGL@script|. In order to be able to use special characters in the name of the script, we use the |\detokenize| primitive.
+%    \begin{macrocode}
+  \if at MGL@list at script@%
+    \refstepcounter{MGL at verb@no}%
+    \addcontentsline{lms}{MGL at script}{%
+      \protect\numberline{\theMGL at verb@no.}%
+      {\ttfamily\protect\detokenize{\MGL at script.mgl}}%
+    }%
+  \fi%
+%    \end{macrocode}
+% If the switch |\@MGL at lineno@| is true, we create a list such that each item will be labeled or numbered by the |MGL at lineno| counter. The style for the label is set by |\mgllinenostyle|.
+%    \begin{macrocode}
+  \if at MGL@lineno@%
+    \list{\mgllinenostyle\arabic{MGL at line@no}.}{\usecounter{MGL at line@no}}%
+%    \end{macrocode}
+% Otherwise, we create a list without labeling for the items.
+%    \begin{macrocode}
+  \else%
+    \list{}{}%
+  \fi%
+%    \end{macrocode}
+% The parameters for the environment are set.
+%    \begin{macrocode}
+  \MGL at set@verbatim at code%
+%    \end{macrocode}
+% The thickness of the box that will contain the name of the script has to be the same as the thickness for the separation line at the begining of the verbatim code.
+%    \begin{macrocode}
+  \fboxrule=\mgllinethickness%
+%    \end{macrocode}
+% The separator to indicate the begining of the verbatim code is positioned; we use the |\MGL at line@sep| command to draw it.
+%    \begin{macrocode}
+  \item[\MGL at line@sep]\fbox{%
+    \bfseries\ttfamily\expandafter\detokenize\expandafter{\MGL at script.mgl}%
+  }\hskip\labelsep\MGL at line@sep\par\par%
+%    \end{macrocode}
+% The |\verbatim at processline| is redefined to put |\the\verbatim at line| in an item of the list, and to to also write it to the script file.
+%    \begin{macrocode}
+  \def\verbatim at processline{%
+    \item\the\verbatim at line%
+    \MGL at write\MGL at out@stream{\the\verbatim at line}%
+  }%
+%    \end{macrocode}
+% The script file is opened for writing.
+%    \begin{macrocode}
+  \MGL at openout\MGL at out@stream{\MGL at dir\MGL at scripts@dir\MGL at script.mgl}%
+%    \end{macrocode}
+% The writing process starts.
+%    \begin{macrocode}
+  \verbatim at start%
+}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\endmglblock}
+% To finish the environment's work, the script file is closed, the separator indicating the end of the verbatim code is placed, and the list is ended.
+%    \begin{macrocode}
+\def\endmglblock{%
+  \MGL at closeout\MGL at out@stream%
+  \item[\MGL at line@sep]\hskip-\labelsep\MGL at line@sep%
+  \endlist%
+}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\endmglblock*}
+% It is defined as an alias for |\endmglblock|.
+%    \begin{macrocode}
+\expandafter\let\csname endmglblock*\endcsname\endmglblock
+%    \end{macrocode}
+% \end{macro}
+% \end{environment}
+% \end{environment}
+%
+% \begin{environment}{mglverbatim}
+% \begin{environment}{mglverbatim*}
+% These two environments have the same main body. They difference in that the unstarred version creates an entry for the |\listofmglscripts|, while the starred version doesn't. We will apply a similar approach to the used for the |mglblock| and |mglblock*| environments.
+% \begin{macro}{\mglverbatim}
+% Similar in function to |\mglblock|.
+%    \begin{macrocode}
+
+\def\mglverbatim{\@MGL at list@script at true\mglverbatim@}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\mglverbatim}
+% Similar in function to |\mglblock*|.
+%    \begin{macrocode}
+\@namedef{mglverbatim*}{\@MGL at list@script at false\mglverbatim@}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\mglverbatim@}
+% The main body of these environments; it's similar to |\mglblock@|. To explain each line of this command would be repetitive, so we explain only the different parts.
+%    \begin{macrocode}
+\newcommand\mglverbatim@[1][]{%
+  \@MGL at lineno@true%
+  \define at key{MGL at verb@keys}{label}{\edef\MGL at script{##1}}%
+  \setkeys{MGL at verb@keys}{#1}%
+  \if at MGL@lineno@%
+    \list{\mgllinenostyle\arabic{MGL at line@no}.}{\usecounter{MGL at line@no}}%
+  \else%
+    \list{}{}%
+  \fi%
+  \MGL at set@verbatim at code%
+  \fboxrule=\mgllinethickness%
+%    \end{macrocode}
+% The separator that indicates the begining of the verbatim code is different depending on whether the user has specified a name associated to the code or not. If no name has been indicated, i.e., |\MGL at script| is undefined, the separator is just a line; otherwise, i.e., |\MGL at script| is defined, the separator is similar to the one of the |mglblock| environment.
+%    \begin{macrocode}
+  \@ifundefined{MGL at script}{%
+    \edef\MGL at script{\mglverbatimname}%
+    \item[\MGL at line@sep]\hskip-\labelsep\MGL at line@sep%
+  }{%
+    \item[\MGL at line@sep]\fbox{%
+      \bfseries\ttfamily\expandafter\detokenize\expandafter{\MGL at script.mgl}%
+    }\hskip\labelsep\MGL at line@sep\par\par%
+  }%
+%    \end{macrocode}
+% Note that, if the user requests an entry in the |\listofmglscripts|, the contents line is added to the same |.lms| file. So here start the similitudes again.
+%    \begin{macrocode}
+  \if at MGL@list at script@%
+    \refstepcounter{MGL at verb@no}%
+    \addcontentsline{lms}{MGL at script}{%
+      \protect\numberline{\theMGL at verb@no.}%
+      {\ttfamily\protect\detokenize{\MGL at script}}%
+    }%
+  \fi%
+  \def\verbatim at processline{%
+    \item\the\verbatim at line%
+  }%
+  \verbatim at start%
+}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\endmglverbatim}
+% This command could be defined as an alias for |\endmglblock|, for they execute the same instructions. But, for the sake of congruence, we rewrite the code.
+%    \begin{macrocode}
+\def\endmglverbatim{%
+  \MGL at closeout\MGL at out@stream%
+  \item[\MGL at line@sep]\hskip-\labelsep\MGL at line@sep%
+  \endlist%
+}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\endmglverbatim*}
+% It is an alias for |\endmglverbatim|.
+%    \begin{macrocode}
+\expandafter\let\csname endmglverbatim*\endcsname\endmglverbatim
+%    \end{macrocode}
+% \end{macro}
+% \end{environment}
+% \end{environment}
+%
+% \begin{environment}{mglcomment}
+% This environment has two different behaviors: When comments are allowed by the user, it behaves similarly to the |mglverbatim| environment; if comments are not allowed, it behaves as the |comment| environment from the \textsf{verbatim} package. So it is natural that we borrow code from them and adapt it to the corresponding situation.
+% \begin{macro}{\mglcomment}
+% The switch |\@MGL at comments@| governs the behavior of this command.
+%    \begin{macrocode}
+
+\def\mglcomment{%
+%    \end{macrocode}
+% If the switch is true, i.e., the user requests displaying of comments, we start a list without labels, and set the parameters for verbatim text.
+%    \begin{macrocode}
+  \if at MGL@comments@%
+    \list{}{}%
+    \MGL at set@verbatim at code%
+%    \end{macrocode}
+% The separator indicating the begining of the comment is similar to the one used by the |mglblock| and |mglverbatim| environments; the differences are that, instead of using a solid line, we use a dashed line (|\MGL at dash@sep|), and instead of displaying the name of a script, we display |\mglcommentname|.
+%    \begin{macrocode}
+    \item\hskip-\labelsep<\MGL at dash@sep\mglcommentname\MGL at dash@sep>%
+%    \end{macrocode}
+% The two following lines redefine the |\verbatim at processline| command to display the comment text line by line as items of the list, and start the process of writing the text.
+%    \begin{macrocode}
+    \def\verbatim at processline{\item\the\verbatim at line}%
+    \verbatim at start%
+%    \end{macrocode}
+% If the switch is false, i.e., the user requests no to display comments, we start a \emph{space hack}, since no text output will be produced. Then, the category codes are changed with |\MGL at codes|, and the macros |\verbatim at startline|, |\verbatim at addtoline|, |\verbatim at processline| and |\verbatim at finish| are disabled, as done in the |comment| environment of the \textsf{verbatim} package. Finally, we call the |\verbatim@| command to start reading the text in the environment.
+%    \begin{macrocode}
+  \else%
+    \@bsphack%
+    \MGL at codes%
+    \let\verbatim at startline\relax%
+    \let\verbatim at addtoline\@gobble%
+    \let\verbatim at processline\relax%
+    \let\verbatim at finish\relax%
+    \verbatim@%
+  \fi%
+}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\endmglcomment}
+% The |\@MGL at comments@| switch also governs the behavior of this command. If it's true, then the separator that ends the comment ---which is the same as the one that starts it--- is displayed, and the list is ended; otherwise, simply the \emph{space hack} is ended.
+%    \begin{macrocode}
+\def\endmglcomment{%
+  \if at MGL@comments@%
+    \item\hskip-\labelsep<\MGL at dash@sep\mglcommentname\MGL at dash@sep>%
+    \endlist%
+  \else%
+    \@esphack%
+  \fi%
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{environment}
+%
+% \subsection{Commands for external scripts}
+% \noindent Since external scripts exist independently of the \LaTeX{} document, there is no need of environments to process them, just commands. Remember these commands work on the suposition that the scripts don't change.
+%
+% \begin{macro}{\mglgraphics}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{New command options: \texttt{gray}, \texttt{mglscale}, \texttt{quality}, \texttt{variant}}
+% This command compiles the external script and includes it in the document. Although that process is simple, the code to execute it is relatively large due to the possibility of the user specifying an optional path, so many parameters have to be checked.
+%    \begin{macrocode}
+
+\newcommand\mglgraphics[2][]{%
+%    \end{macrocode}
+% In order to keep all definitions and changes local, we start a local group inside which all \LaTeX{} code will be contained.
+%    \begin{macrocode}
+  \bgroup%
+%    \end{macrocode}
+% We add the option |path| for the user to be able to specify the location of the script, which is stored in the variable |\MGL at force@path|.
+%    \begin{macrocode}
+  \define at key{MGL at gr@keys}{path}{\def\MGL at forced@path{##1}}%
+%    \end{macrocode}
+% The optional arguments are processed.
+%    \begin{macrocode}
+  \MGL at setkeys{MGL at gr@keys}{#1}%
+%    \end{macrocode}
+% The name of the script is set, though it is not check for multiple naming. This is necessary, since |\MGL at includegraphics| uses this macro.
+%    \begin{macrocode}
+  \edef\MGL at script{#2}%
+%    \end{macrocode}
+% If the corresponding image exists, then this script has been compiled in a previous \LaTeX{} run, so nothing is done, but the inclusion of the image.
+%    \begin{macrocode}
+  \IfFileExists{\MGL at dir\MGL at graphics@dir\MGL at script\MGL at imgext}{}{%
+%    \end{macrocode}
+% If the image doesn't exist, we check if the user has specified a custom location.
+%    \begin{macrocode}
+    \@ifundefined{MGL at forced@path}{%
+%    \end{macrocode}
+% If no custom location has been used, we iterate over the list of search paths (|\MGL at paths|): If we find the requested script, then we store its location in |\MGL at temp@b|.
+%    \begin{macrocode}
+      \@for\MGL at temp@a:=\MGL at paths\do{%
+        \IfFileExists{\MGL at temp@a\MGL at script.mgl}{%
+          \edef\MGL at temp@b{\MGL at temp@a}%
+        }{}%
+      }%
+    }{%
+%    \end{macrocode}
+% If the user has specified a path for the script, we check if the script actually exists. If it does, we store its location inside |\MGL at temp@b|.
+%    \begin{macrocode}
+      \IfFileExists{\MGL at forced@path\MGL at script.mgl}{%
+        \edef\MGL at temp@b{\MGL at forced@path}%
+      }{}%
+    }%
+%    \end{macrocode}
+% If |\MGL at temp@b| is not defined, the script has not been found, so a warning is issued.
+%    \begin{macrocode}
+    \@ifundefined{MGL at temp@b}{%
+      \PackageWarning{mgltex}{%
+        MGL script "\MGL at script.mgl" not found%
+      }%
+    }{%
+%    \end{macrocode}
+% If |\MGL at temp@b| is defined, the script has been found, so we compile it.
+%    \begin{macrocode}
+      \MGL at write{18}{%
+        mglconv -q \MGL at quality\space -g \MGL at gray\space%
+        -S \MGL at scale\space -v \MGL at variant\space%
+        -s "\MGL at dir\MGL at scripts@dir\mglsetupscriptname.mgl"\space%
+        -o "\MGL at dir\MGL at graphics@dir\MGL at script\MGL at imgext"\space%
+        "\MGL at temp@b\MGL at script.mgl"%
+      }%
+    }%
+  }%
+%    \end{macrocode}
+% The image is included.
+%    \begin{macrocode}
+  \MGL at includegraphics%
+%    \end{macrocode}
+% The local group ends here.
+%    \begin{macrocode}
+  \egroup%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\mglinclude}\begin{macro}{\mglinclude*}
+% The purpose of these commands is to transcript the MGL code from a script. Once again, this is a straightforward functionality, but the code is quite large, so it has been separated in various macros.
+%
+% The unstarred version defines the |\@MGL at list@script@| switch to be true, so the script is listed with the |\listofmglscripts| command, and then it calls the main body of code (|\mglinclude@|), just like the |mglblock| environment does. The starred version defines the switch as false and calls the main body, too.
+%    \begin{macrocode}
+
+\def\mglinclude{\@MGL at list@script at true\mglinclude@}
+\@namedef{mglinclude*}{\@MGL at list@script at false\mglinclude@}
+%    \end{macrocode}
+% \begin{macro}{\mglinclude@}
+%    \begin{macrocode}
+\newcommand\mglinclude@[2][]{%
+%    \end{macrocode}
+% We start a local group to keep definitions and changes local.
+%    \begin{macrocode}
+  \bgroup%
+%    \end{macrocode}
+% The default behavior is to number lines of MGL code, so the switch |\@MGL at lineno@| is set to true.
+%    \begin{macrocode}
+  \@MGL at lineno@true%
+%    \end{macrocode}
+% We add the option |path| for the user to be able to specify the location of the script, which is stored in |\MGL at forced@path|.
+%    \begin{macrocode}
+  \define at key{MGL at verb@keys}{path}{\def\MGL at forced@path{##1}}%
+%    \end{macrocode}
+% The options are processed.
+%    \begin{macrocode}
+  \setkeys{MGL at verb@keys}{#1}%
+%    \end{macrocode}
+% We don't need to check if there are multiple scripts with the same name, so we namually set |\MGL at script|, instead of using |\MGL at set@script at name|.
+%    \begin{macrocode}
+  \edef\MGL at script{#2}%
+%    \end{macrocode}
+% We check if the user has specified a custom location for the script.
+%    \begin{macrocode}
+  \@ifundefined{MGL at forced@path}{%
+%    \end{macrocode}
+% If no custom location has been used, we iterate over the list |\MGL at paths| to find the script.
+%    \begin{macrocode}
+    \@for\MGL at temp@b:=\MGL at paths\do{%
+%    \end{macrocode}
+% If the script exists, we store its location in |\MGL at temp@a|%
+%    \begin{macrocode}
+      \IfFileExists{\MGL at temp@b\MGL at script.mgl}{%
+        \edef\MGL at temp@a{\MGL at temp@b}%
+      }{}%
+    }%
+  }{%
+%    \end{macrocode}
+% If the user specified the location of the script, we check if it exists, in which case we store its location in |\MGL at temp@a|.
+%    \begin{macrocode}
+    \IfFileExists{\MGL at script.mgl}{%
+      \edef\MGL at temp@a{\MGL at forced@path}%
+    }{}%
+  }%
+%    \end{macrocode}
+% If |\MGL at temp@a| is not defined, the script has not been found, so we issue a warning, and display a box in the document with the words \emph{MGL script not found}.
+%    \begin{macrocode}
+  \@ifundefined{MGL at temp@a}{%
+    \PackageWarning{mgltex}{%
+      MGL script "\MGL at forced@path\MGL at script.mgl" not found%
+    }%
+    \center%
+      \fbox{%
+        \centering%
+        \bfseries\Huge%
+        \begin{tabular}{c}MGL\\script\\not\\found\end{tabular}%
+      }%
+    \endcenter%
+  }{%
+%    \end{macrocode}
+% If |\MGL at temp@a| is defined, the script has been found, so we call |\mglinclude@@| to set up the inclusion of the script.
+%    \begin{macrocode}
+    \mglinclude@@%
+  }%
+  \egroup%
+}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\mglinclude@@}
+% This macro sets the parameters for the inclusion of the script, and calls the command in charge of the transcription.
+%    \begin{macrocode}
+\def\mglinclude@@{%
+%    \end{macrocode}
+% We first add the script to the \LaTeX{} list of included files.
+%    \begin{macrocode}
+  \@addtofilelist{\MGL at script.mgl}%
+%    \end{macrocode}
+% If the user has used the unstarred version of |\mglinclude|, we add a contents line to the |.lms| file.
+%    \begin{macrocode}
+  \if at MGL@list at script@%
+    \refstepcounter{MGL at verb@no}%
+    \addcontentsline{lms}{MGL at script}{%
+      \protect\numberline{\theMGL at verb@no.}%
+      {\ttfamily\protect\detokenize{\MGL at script.mgl}}%
+    }%
+  \fi%
+%    \end{macrocode}
+% We start a |\list| in which each line of code will be an item. If the lines have to be numbered, we use the |MGL at line@no| counter.
+%    \begin{macrocode}
+  \if at MGL@lineno@%
+    \list{\mgllinenostyle\arabic{MGL at line@no}.}{\usecounter{MGL at line@no}}%
+  \else%
+    \list{}{}%
+  \fi%
+%    \end{macrocode}
+% We set the parameters for a verbatim code.
+%    \begin{macrocode}
+  \MGL at set@verbatim at code%
+%    \end{macrocode}
+% The heading of the environment is set. It is similar to that of the |mglblock| environment.
+%    \begin{macrocode}
+  \fboxrule=\mgllinethickness%
+  \item[\MGL at line@sep]\fbox{%
+    \bfseries\ttfamily\expandafter\detokenize\expandafter{\MGL at script.mgl}%
+  }\hskip\labelsep\MGL at line@sep\par\par%
+%    \end{macrocode}
+% We redefine the |\verbatim at processline| macro from the \textsf{verbatim} package to put |\the\verbatim at line| on an item.
+%    \begin{macrocode}
+  \def\verbatim at processline{%
+    \item\the\verbatim at line%
+  }%
+%    \end{macrocode}
+% The script is opened for reading.
+%    \begin{macrocode}
+  \immediate\openin\MGL at in@stream="\MGL at temp@a\MGL at script.mgl"%
+%    \end{macrocode}
+% We call |\mglinclude@@@| to start the transcription.
+%    \begin{macrocode}
+  \mglinclude@@@%
+}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\mglinclude@@@}
+% This command transcripts the MGL code of the script and closes the list started in |\mglinclude@@|, adding the corresponding separation line to separate the code from normal text.
+%    \begin{macrocode}
+\def\mglinclude@@@{%
+%    \end{macrocode}
+% Since the transcription has to be done even when \textsf{\mglTeX} is off, instead of using the |\MGL at read| command ---which is inactive when the package is off---, we use the usual commands from \LaTeX{} to read from the file.
+%    \begin{macrocode}
+  \immediate\read\MGL at in@stream to \MGL at temp@b%
+%    \end{macrocode}
+% If the end of file has been reached, we close the input stream, add the separation line, and end the |\list|.
+%    \begin{macrocode}
+  \ifeof\MGL at in@stream%
+    \immediate\closein\MGL at in@stream%
+    \item[\MGL at line@sep]\hskip-\labelsep\MGL at line@sep%
+    \endlist%
+%    \end{macrocode}
+% Otherwise, we use |\verbatim at startline| to clean the |\verbatim at line| buffer, then we add the just read line to the buffer, and call |\verbatim at processline| to include it as an item of the list. Finally, we recursively call |\mglinclude@@@| to read the next line.
+%    \begin{macrocode}
+  \else%
+    \verbatim at startline%
+    \expandafter\verbatim at addtoline\expandafter{\MGL at temp@b}%
+    \verbatim at processline%
+    \expandafter\mglinclude@@@%
+  \fi%
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}\end{macro}
+%
+% \subsection{Additional commands}
+% \begin{macro}{\listofmglscripts}
+% \noindent This command creates the \emph{list of MGL scripts} section. It has to be defined differently depending on whether the used document class defines the |\l at chapter| command or it only the |\l at section| command, which set the style for making a table of contents entry for the |\chapter| command and the |\section| command, respectively. If none of them are defined, we define our own style based on the latter.
+%    \begin{macrocode}
+
+\ifx\l at chapter\@undefined%
+%    \end{macrocode}
+% If |\l at chapter| is not defined, we check if |\l at section| is.
+%    \begin{macrocode}
+  \ifx\l at section\@undefined%
+%    \end{macrocode}
+% If |\l at section| is not defined, we set the |\lisofmglscripts| command to perform exactly as the |\section*{\listofmglscriptsname}| would do in the usual \textsf{book} and \textsf{article} \LaTeX{} classes, except that the type of section is |MGL at list|.
+%    \begin{macrocode}
+    \def\listofmglscripts{%
+      \@startsection{MGL at list}%
+      {1}{0em}{-3.5ex plus -1ex minus -0.2ex}%
+      {2.5ex plus 0.2ex}%
+      {\centering\normalfont\bfseries\large}*%
+      {\listofmglscriptsname}%
+%    \end{macrocode}
+% We use the |\@mkboth| command to set the page marks according to the current page style.
+%    \begin{macrocode}
+      \@mkboth{%
+        \MakeUppercase\listofmglscriptsname%
+      }{%
+        \MakeUppercase\listofmglscriptsname%
+      }%
+%    \end{macrocode}
+% The \emph{list of MGL scripts} is created by reading the document's |.lms| file.
+%    \begin{macrocode}
+      \@starttoc{lms}%
+    }%
+%    \end{macrocode}
+% The |\l at MGL@list| style has the same code as the |\l at section| style.
+%    \begin{macrocode}
+    \newcommand*\l at MGL@list[2]{%
+      \ifnum \c at tocdepth >\z@
+        \addpenalty\@secpenalty
+        \addvspace{1.0em \@plus\p@}%
+        \setlength\@tempdima{1.5em}%
+        \begingroup
+          \parindent \z@ \rightskip \@pnumwidth
+          \parfillskip -\@pnumwidth
+          \leavevmode \bfseries
+          \advance\leftskip\@tempdima
+          \hskip -\leftskip
+          #1\nobreak\hfil \nobreak\hb at xt@\@pnumwidth{\hss #2}\par
+        \endgroup
+      \fi%
+    }%
+  \else%
+%    \end{macrocode}
+% If the |\l at section| style is defined, the \emph{list of MGL scripts} is just an unumbered section.
+%    \begin{macrocode}
+    \def\listofmglscripts{%
+      \section*{\listofmglscriptsname}%
+      \@mkboth{%
+        \MakeUppercase\listofmglscriptsname%
+      }{%
+        \MakeUppercase\listofmglscriptsname%
+      }%
+      \@starttoc{lms}%
+    }%
+  \fi%
+\else%
+%    \end{macrocode}
+% If the |\l at chapter| style is defined, the \emph{list of MGL scripts} is just an unumbered chapter.
+%    \begin{macrocode}
+  \def\listofmglscripts{%
+    \chapter*{\listofmglscriptsname}%
+    \@mkboth{%
+      \MakeUppercase\listofmglscriptsname%
+    }{%
+      \MakeUppercase\listofmglscriptsname%
+    }%
+    \@starttoc{lms}%
+  }%
+\fi%
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\mglTeX}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{Add a small negative space in the logo, between the ``mgl'' and ``\TeX''}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{Declared now as robust command}
+% This macro pretty-prints the name of the package. It has a starred version, which also prints the version.
+%    \begin{macrocode}
+
+\DeclareRobustCommand\mglTeX{%
+  mgl\TeX\@ifstar{~v4.2}{}%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Local settings commands}
+% \begin{macro}{\mglswitch}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{Now accepts arguments \texttt{0} (equivalent to \texttt{off}) and \texttt{1} (equivalent to \texttt{on}), besides the usual  \texttt{off} and \texttt{on}}
+% \noindent This command turns |on| and |off| the package according to its argument; it is just a call to the commands |\MGL at switch@on| or |\MGL at switch@off|.
+%    \begin{macrocode}
+\def\mglswitch#1{%
+  \MGL at test@switch{#1}{\mglswitch}%
+  \csname MGL at switch@\MGL at temp@a\endcsname%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\mglcomments}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{Now accepts arguments \texttt{0} (equivalent to \texttt{off}) and \texttt{1} (equivalent to \texttt{on}), besides the usual  \texttt{off} and \texttt{on}}
+% Depending on the option passed by the user, it calls |\@MGL at comments@on| or |\@MGL at comments@off|.
+%    \begin{macrocode}
+\def\mglcomments#1{%
+  \MGL at test@switch{#1}{\mglcomments}%
+  \csname @MGL at comments@\MGL at temp@a\endcsname%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\mglquality}
+% See under the title \emph{Initialization}, subsection \ref{Init}.
+% \end{macro}
+%
+% \begin{macro}{\mglscale}
+% See under the title \emph{Initialization}, subsection \ref{Init}.
+% \end{macro}
+%
+% \begin{macro}{\mglvariant}
+% See under the title \emph{Initialization}, subsection \ref{Init}.
+% \end{macro}
+%
+% \begin{macro}{\mglimgext}
+% This command changes the value of |\MGL at imgext|.
+%    \begin{macrocode}
+\def\mglimgext#1{\def\MGL at imgext{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\mglname}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{Now writes the MGL code line \texttt{setsize~600~400} to the main script}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{The MGL code line \texttt{setsize~600~400} is now written to the main script}
+% \noindent The purpose of this command is to force the closure of the current main script, compile the corresponding figures, and open a new main script. At first, it is defined to only change the value of |\MGL at main@script at name| because the main script is not opened until the call of |\begin{document}|; but at that point, it is redefined to perform the described actions.
+%    \begin{macrocode}
+\def\mglname#1{\edef\MGL at main@script at name{#1}}
+%    \end{macrocode}
+% Here is the redefinition of |\mglname| after the |\begin{document}| command.
+%    \begin{macrocode}
+\AtBeginDocument{%
+  \def\mglname#1{%
+%    \end{macrocode}
+% We start a space hack, ince this function has no real effect on the document.
+%    \begin{macrocode}
+    \@bsphack%
+%    \end{macrocode}
+% The MGL functions created throughout the document are written.
+%    \begin{macrocode}
+    \MGL at write@funcs%
+%    \end{macrocode}
+% We force the closure of the main script. We use |\immediate\closeout| instead of |\MGL at closeout| in case \textsf{\mglTeX} is off.
+%    \begin{macrocode}
+    \immediate\closeout{\MGL at main@stream}%
+%    \end{macrocode}
+% The closed script is compiled.
+%    \begin{macrocode}
+    \MGL at write{18}{%
+      mglconv -q \MGL at quality\space -g \MGL at gray\space%
+      -S \MGL at scale\space -v \MGL at variant\space%
+      -s "\MGL at dir\MGL at scripts@dir\mglsetupscriptname.mgl"\space%
+      -n "\MGL at dir\MGL at scripts@dir\MGL at main@script at name.mgl"%
+    }%
+%    \end{macrocode}
+% The name of the new main script is updated, and it is check for overwriting, using |\MGL at set@script at name| inside a local group, since this command defines |\MGL at script|, which we need undefined in some parts of the code of the package.
+%    \begin{macrocode}
+    \edef\MGL at main@script at name{#1}%
+    \bgroup\MGL at set@script at name{\MGL at main@script at name}\egroup%
+    \MGL at openout\MGL at main@stream{%
+      \MGL at dir\MGL at scripts@dir\MGL at main@script at name.mgl%
+    }%
+%    \end{macrocode}
+% We set the default size for the graphics that the main script will generate; without this line the |setsizescl| commands written automatically by \textsf{\mglTeX} wouldn't work.
+%    \begin{macrocode}
+    \MGL at write\MGL at main@script at name{setsize 600 400}
+%    \end{macrocode}
+% The space hack is ended.
+%    \begin{macrocode}
+    \@esphack%
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Advanced settings commands}
+% \begin{macro}{\mgldir}
+% \noindent This command is the interface for the user to change the value of |\MGL at dir|. It is an only-preamble macro, since using it elsewhere would cause faulty behavior.
+%    \begin{macrocode}
+
+\def\mgldir#1{\def\MGL at dir{#1}}\@onlypreamble\mgldir
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\mglscriptsdir}
+% This command modifies the value of |\MGL at scripts@dir|. It is also an only-preamble macro.
+%    \begin{macrocode}
+\def\mglscriptsdir#1{\def\MGL at scripts@dir{#1}}\@onlypreamble\mglscriptsdir
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\mglgraphicsdir}
+% Modifies the value of |\MGL at graphics@dir|. It is an only-preamble macro.
+%    \begin{macrocode}
+\def\mglgraphicsdir#1{\def\MGL at graphics@dir{#1}}\@onlypreamble\mglgraphicsdir
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\mglbackupsdir}
+% Modifies the value of |\MGL at backups@dir|. It is an only-preamble macro.
+%    \begin{macrocode}
+\def\mglbackupsdir#1{\def\MGL at backups@dir{#1}}\@onlypreamble\mglbackupsdir
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\mglpaths}
+% This command adds a list of search paths for scripts to the existing one (|\MGL at paths|).
+%    \begin{macrocode}
+\def\mglpaths#1{\g at addto@macro\MGL at paths{,#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\mglsettings}
+%  \changes{\textbf{v4.2 ------------}}{2016/05/14}{Now calls the \doccommand{mglswitch} and \doccommand{mglcomments} commands for the \texttt{switch} and \texttt{comments} options, respectively}
+% \changes{\textbf{v4.2 ------------}}{2016/05/14}{Added options \texttt{gray} and \texttt{variant}}
+% First, we define a \meta{key}=\meta{value} family, |MGL at sett@keys|, for this command.
+%    \begin{macrocode}
+\define at key{MGL at sett@keys}{dir}{\def\MGL at dir{#1}}
+\define at key{MGL at sett@keys}{scriptsdir}{\def\MGL at scripts@dir{#1}}
+\define at key{MGL at sett@keys}{graphicsdir}{\def\MGL at graphics@dir{#1}}
+\define at key{MGL at sett@keys}{backupsdir}{\def\MGL at backups@dir{#1}}
+\define at key{MGL at sett@keys}{paths}{\g at addto@macro\MGL at paths{,#1}}
+\define at key{MGL at sett@keys}{switch}{\mglswitch{#1}}
+\define at key{MGL at sett@keys}{comments}{\mglcomments{#1}}
+\define at key{MGL at sett@keys}{gray}{\mglgray{#1}}
+\define at key{MGL at sett@keys}{mglscale}{\mglscale{#1}}
+\define at key{MGL at sett@keys}{quality}{\mglquality{#1}}
+\define at key{MGL at sett@keys}{variant}{\mglvariant{#1}}
+\define at key{MGL at sett@keys}{imgext}{\def\MGL at imgext{.#1}}
+%    \end{macrocode}
+% The command receives and executes the \meta{key}=\meta{value} pairs for |MGL at sett@keys|. This is an only-preamble command.
+%    \begin{macrocode}
+\def\mglsettings#1{\setkeys{MGL at sett@keys}{#1}}
+\@onlypreamble\mglsettings
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{User-definable macros}
+% \begin{macro}{\mglsetupscriptname}\begin{macro}{\mglcommentname}\begin{macro}{\listofmglscriptsname}\begin{macro}{\mglverbatimname}\begin{macro}{\mgllinenostyle}\begin{macro}{\mgldashwidth}\begin{macro}{\mgllinethickness}\begin{macro}{\mglbreakindent}
+% The user is allowed to modifu these commands, so no |@| symbol is used on them.
+%    \begin{macrocode}
+
+\def\mglsetupscriptname{MGL_setup_script}
+\def\mglcommentname{\mglTeX{} comment}
+\def\listofmglscriptsname{List of MGL scripts}
+\def\mglverbatimname{(Unnamed MGL verbatim script)}
+\def\mgllinenostyle{\footnotesize}
+\newdimen\mgldashwidth\mgldashwidth=0.75em
+\newdimen\mgllinethickness\mgllinethickness=0.25ex
+\newdimen\mglbreakindent\mglbreakindent=1em
+%    \end{macrocode}
+% \end{macro}\end{macro}\end{macro}\end{macro}\end{macro}\end{macro}\end{macro}\end{macro}
+%
+% \subsection{Final adjustments}
+% To finish the code of \textsf{\mglTeX}, we set the behavior of the package at the call of the |\begin{document}| and |\end{document}| commands.
+%
+% We tell \LaTeX{} to check the name of the document's main script for overwriting. We do this by calling |\MGL at set@script at name| inside a local group, because it defines |\MGL at script|, which we need undefined in certain parts of the code. Then the script is opened. We use |\immediate\openout| instead of |\MGL at openout| for this purpose, since, otherwise, we run the risk of the main script not being created when needed, if the user turns off \textsf{\mglTeX} before the |\begin{document}| c [...]
+%    \begin{macrocode}
+
+\AtBeginDocument{%
+  \bgroup\MGL at set@script at name{\MGL at main@script at name}\egroup%
+  \immediate\openout\MGL at main@stream=%
+  \MGL at dir\MGL at scripts@dir\MGL at main@script at name.mgl%
+  \MGL at write\MGL at main@stream{setsize 600 400}%
+}
+%    \end{macrocode}
+%
+% We also set the actions for the call of |\end{document}|
+%    \begin{macrocode}
+
+\AtEndDocument{%
+%    \end{macrocode}
+% |\MGL at write@funcs| will simply write the MGL functions throughout the \LaTeX{} document.
+%    \begin{macrocode}
+  \MGL at write@funcs%
+%    \end{macrocode}
+% The main script is closed. We use the |\immediate\closeout| construction instead of |\MGL at closeout|, since the script must be closed even when \textsf{\mglTeX} is off.
+%    \begin{macrocode}
+  \immediate\closeout\MGL at main@stream%
+%    \end{macrocode}
+% The main script is compiled.
+%    \begin{macrocode}
+  \MGL at write{18}{%
+    mglconv -q \MGL at quality\space -g \MGL at gray\space%
+    -S \MGL at scale\space -v \MGL at variant\space%
+    -s "\MGL at dir\MGL at scripts@dir\mglsetupscriptname.mgl"\space%
+    -n "\MGL at dir\MGL at scripts@dir\MGL at main@script at name.mgl"%
+  }%
+}
+%    \end{macrocode}
+%
+% \Finale
\ No newline at end of file
diff --git a/mgltex/mgltex.ins b/mgltex/mgltex.ins
new file mode 100644
index 0000000..49d18ee
--- /dev/null
+++ b/mgltex/mgltex.ins
@@ -0,0 +1,63 @@
+%%
+%% Copyright (C) 2014--2016 by Diego Sejas Viscarra <dsejas.mathematics at gmail.com>
+%% Copyright (C) 2014--2016 by Alexey Balakin <mathgl.abalakin at gmail.com>
+%%
+%% This program is free software: you can redistribute it and/or modify it
+%% under the terms of the GNU General Public License as published by the
+%% Free Software Foundation, either version 3 of the License, or (at your
+%% option) any later version.
+%%
+%% This program is distributed in the hope that it will be useful, but
+%% WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+%% Public License for more details.
+%%
+%% You should have received a copy of the GNU General Public License along
+%% with this program.  If not, see <http://www.gnu.org/licenses/>.
+%%
+
+\input docstrip.tex
+\keepsilent
+
+\usedir{tex/latex/mgltex}
+
+\preamble
+
+This is a generated file.
+
+Copyright (C) 2014--2016 by Diego Sejas Viscarra <dsejas.mathematics at gmail.com>
+Copyright (C) 2014--2016 by Alexey Balakin <mathgl.abalakin at gmail.com>
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation, either version 3 of the License, or (at your
+option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+\endpreamble
+
+\generate{\file{mgltex.sty}{\from{mgltex.dtx}{package}}}
+
+\obeyspaces
+\Msg{**********************************************************}
+\Msg{*                                                        *}
+\Msg{* To finish the installation you have to move the        *}
+\Msg{* following file into a directory searched by TeX:       *}
+\Msg{*                                                        *}
+\Msg{*          mgltex.sty                                    *}
+\Msg{*                                                        *}
+\Msg{* To produce the documentation run the file mgltex.dtx   *}
+\Msg{* through LaTeX.                                         *}
+\Msg{*                                                        *}
+\Msg{* Happy TeXing!                                          *}
+\Msg{*                                                        *}
+\Msg{**********************************************************}
+
+\endbatchfile
diff --git a/mgltex/mgltex.pdf b/mgltex/mgltex.pdf
new file mode 100644
index 0000000..58c5dd6
Binary files /dev/null and b/mgltex/mgltex.pdf differ
diff --git a/mgltex/sample.tex b/mgltex/sample.tex
new file mode 100644
index 0000000..91447c8
--- /dev/null
+++ b/mgltex/sample.tex
@@ -0,0 +1,276 @@
+\documentclass{article}
+
+\usepackage[png,comments]{mgltex}
+\usepackage{hyperref}
+
+\title{\mglTeX*{} usage sample}
+\author{Diego Sejas Viscarra \and Alexey Balakin}
+\date{\today}
+
+\mglsettings{
+	dir=MGL/,
+	scriptsdir=scripts/,
+	graphicsdir=graphics/,
+	backupsdir=backups/
+}
+
+\begin{mglsetupscript}
+	define gravity 9.81 # [m/s^2]
+\end{mglsetupscript}
+
+\begin{document}
+	
+	\maketitle
+	
+	\begin{abstract}
+		\noindent \mglTeX{} is a \LaTeX{} package that allows the creation of graphics directly from MGL scripts of the MathGL library (by Alexey Balakin) inside documents. The MGL code is extracted, executed (if shell escape is activated), and the resulting graphics are automatically included.
+		
+		This document is intended as a sample of the capabilities of \mglTeX{}, as well as a brief introduction to the package, for those who want to start right away to use it, without diving into the a little bit more technical documentation.
+	\end{abstract}
+	
+	\section{Basics on environments}
+	\begin{description}
+		\item[mgl] The easiest way to embed MGL code is the \verb|mgl| environment. It extracts its contents to a main script associated to the document.\footnote{Generally, the main script has the same name as the document being compiled. In order to rename it or create a new one, the \texttt{\textbackslash mglname} command can be used.} If shell escape is activated, \LaTeX{} will take care of calling \verb|mglconv| (the MathGL compiler) with the appropriate settings, and the resulting image  [...]
+		
+		For example, you could write:
+		\begin{verbatim}
+			\begin{figure}[!ht]
+			  \centering
+			  \begin{mgl}[width=0.85\textwidth,height=6cm]
+			    call 'prepare1d'
+			    subplot 2 1 0 '<_' : title 'Standard data plot'
+			    box : axis : grid 'xy' ';k'
+			    plot y ’rGb’
+			    
+			    subplot 2 1 1 '<_' : title 'Region plot'
+				  ranges -1 1 -1 1 : origin 0 0
+				  new y1 200 'x^3-x' : new y2 200 'x'
+				  axis : grid 'xy' 'W'
+				  region y1 y2 'ry'
+				  plot y1 '2k' : plot y2 '2k'
+				  text -0.75 -0.35 '\i{A}_1' 'k' : text 0.75 0.25 '\i{A}_2' 'k'
+			  \end{mgl}
+			  \caption{A simple plot create by \mglTeX's \texttt{mgl} environment}
+			\end{figure}
+		\end{verbatim}
+		This will produce the following image:
+		\begin{figure}[!ht]
+			\centering
+			\begin{mgl}[width=0.85\textwidth,height=5.5cm]
+				call 'prepare1d'
+				subplot 2 1 0 '<_' : title 'Standard data plot'
+				box : axis : grid 'xy' ';k'
+				plot y '2'
+				
+				subplot 2 1 1 '<_' : title 'Region plot'
+				ranges -1 1 -1 1 : origin 0 0
+				new y1 200 'x^3-x' : new y2 200 'x'
+				axis 'AKDTVISO' : grid 'xy' ';W'
+				region y1 y2 'ry'
+				plot y1 '2k' : plot y2 '2k'
+				text -0.75 -0.35 '\i{A}_1' 'k' -2 : text 0.75 0.25 '\i{A}_2' 'k' -2
+			\end{mgl}
+			\caption{A simple plot create by \mglTeX's \texttt{mgl} environment}
+		\end{figure}
+		
+		Two important aspects of \mglTeX{} can be noted from this example: First, the \verb|mgl| environment accepts the same optional argument as the \verb|\includegraphics| command from the \verb|graphicx| package. Actually, it also accepts other optional arguments, called \verb|gray| (to activate/deactivate gray-scale mode), \verb|mglscale| (to set the factor for scaling the image file), \verb|quality| (to set the quality of the image), \verb|variant| (to chose the variant of the arguments  [...]
+		
+		The second aspect to be noted about the example is that this script calls a MGL function, \verb|prepare1d|, which hasn't been defined yet. \mglTeX{} provides the \verb|mglfunc| environment for this purpose (see below).
+		
+		\item[mglfunc] This environment can be used in any part of the \LaTeX{} document; \mglTeX{} takes care of placing the corresponding code at the end of the main script, as has to be done in the MGL language.
+		
+		For example, the function \verb|prepare1d| that is called in the script above is defined like this
+		\begin{verbatim}
+		  \begin{mglfunc}{prepare1d}
+		    new y 50 3
+		    modify y '0.7*sin(2*pi*x)+0.5*cos(3*pi*x)+0.2*sin(pi*x)'
+		    modify y 'sin(2*pi*x)' 1
+		    modify y 'cos(2*pi*x)' 2
+		  \end{mglfunc}
+		\end{verbatim}
+		\begin{mglfunc}{prepare1d}
+			new y 50 3
+			modify y '0.7*sin(2*pi*x)+0.5*cos(3*pi*x)+0.2*sin(pi*x)'
+			modify y 'sin(2*pi*x)' 1
+			modify y 'cos(2*pi*x)' 2
+		\end{mglfunc}
+		As you can see, only the body of the function has to be written. The number of arguments of the function can be passed to \verb|mglfunc| as optional argument, like in the code \verb|\begin{mglfunc}[3]{func_with_three_args}|.
+		
+		\item[mgladdon] This environment just adds its contents to the main script, without producing any image. It is useful to load dynamic libraries, define constants, etc.
+		
+		\item[mglcode] The \verb|mglcode| environment is similar to \verb|mgl|, but it creates its own script, whose name is passed as mandatory argument. The same optional arguments are accepted, except \verb|label| (for obvious reasons).
+		\begin{verbatim}
+			\begin{figure}[!ht]
+			  \begin{mglcode}[scale=0.5]{vectorial_flow}
+			    new a 20 30 'sin(pi*x)*sin(pi*y)+cos(2*pi*x*y)'
+			    new b 20 30 'cos(pi*x)*cos(pi*y)+cos(2*pi*x*y)'
+			    
+			    subplot 1 1 0 '' : title 'Flow of vector field' : box
+			    flow a b 'v'; value 20
+			  \end{mglcode}
+			\end{figure}
+		\end{verbatim}
+		\begin{figure}[!ht]
+			\centering
+			\begin{mglcode}[scale=0.5]{vectorial_flow}
+				new a 20 30 'sin(pi*x)*sin(pi*y)+cos(2*pi*x*y)'
+				new b 20 30 'cos(pi*x)*cos(pi*y)+cos(2*pi*x*y)'
+				
+				subplot 1 1 0 '' : title 'Flow of a vector field' : box
+				flow a b '2v'; value 10
+			\end{mglcode}
+		\end{figure}
+		
+		\item[mglscript] This environment just creates a script, whose name is specified as mandatory argument. It is useful, for example, to create MGL scripts which can later be post-processed by another package, like \verb|listings| or \verb|pygments|.
+		
+		For example, the following won't produce any image, just a script:
+		\begin{verbatim}
+			\begin{mglscript}{Gaston_surface}
+			  subplot 1 1 0 '' : title 'Gaston\'s surface'
+			  ranges -13 13 -40 40
+			  new a 200 200 '-x+(2*0.84*cosh(0.4*x)*sinh(0.4*x))/' \
+			    '(0.4*((sqrt(0.84)*cosh(0.4*x))^2+(0.4*sin(sqrt(0.84)*y))))+' \
+			    '0.5*sin(pi/2*x)'
+			  new b 200 200 '(2*sqrt(0.84)*cosh(0.45*x)*(-(sqrt(0.84)*sin(y)*' \
+			    'cos(sqrt(0.84)*y))+cos(y)*sin(sqrt(0.84)*y)))/' \
+			    '(0.4*((sqrt(0.84)*cosh(0.4*x))^2+2*(0.4*sin(sqrt(0.84)*x))^2))'
+			  new c 200 200 '(2*sqrt(0.84)*cosh(0.45*x)*(-(sqrt(0.84)*cos(y)*' \
+			    'cos(sqrt(0.84)*y))-sin(y)*sin(sqrt(0.84)*y)))/' \
+			    '(0.4*((sqrt(0.84)*cosh(0.4*x))^2+2*(0.4*sin(sqrt(0.84)*x))^2))'
+			  rotate 60 60
+			  light on
+			  xrange c : yrange b : zrange a : crange c
+			  surf c b a '#'; meshnum 100
+			\end{mglscript}
+		\end{verbatim}
+		\begin{mglscript}{Gaston_surface}
+			subplot 1 1 0 ''
+			ranges -13 13 -40 40
+			new a 200 200 '-x+(2*0.84*cosh(0.4*x)*sinh(0.4*x))/(0.4*((sqrt(0.84)*cosh(0.4*x))^2+(0.4*sin(sqrt(0.84)*y))))+0.5*sin(pi/2*x)'
+			new b 200 200 '(2*sqrt(0.84)*cosh(0.45*x)*(-(sqrt(0.84)*sin(y)*cos(sqrt(0.84)*y))+cos(y)*sin(sqrt(0.84)*y)))/(0.4*((sqrt(0.84)*cosh(0.4*x))^2+2*(0.4*sin(sqrt(0.84)*x))^2))'
+			new c 200 200 '(2*sqrt(0.84)*cosh(0.45*x)*(-(sqrt(0.84)*cos(y)*cos(sqrt(0.84)*y))-sin(y)*sin(sqrt(0.84)*y)))/(0.4*((sqrt(0.84)*cosh(0.4*x))^2+2*(0.4*sin(sqrt(0.84)*x))^2))'
+			rotate 60 60
+			light on
+			xrange c : yrange b : zrange a : crange c
+			surf c b a '#'; meshnum 100
+			title 'Gaston surface'
+		\end{mglscript}
+		
+		\item[mglblock] It writes its contents verbatim to a file, specified as mandatory argument, and to the \LaTeX{} document.
+		
+		For example:
+		\begin{verbatim}
+			\begin{mglblock}{fractal}
+				list A [0,0,0,.16,0,0,.01] [.85,.04,-.04,.85,0,1.6,.85] [.2,-.26,.23,.22,0,1.6,.07] [-.15,.28,.26,.24,0,.44,.07]
+				ifs2d f A 100000
+				subplot 2 1 0 '<_' : title 'A fractal fern'
+				ranges f(0) f(1) : axis
+				plot f(0) f(1) 'G#o '; size 0.05
+				
+				subplot 2 1 1 '<_' : title 'Bifurcation plot'
+				ranges 0 4 0 1 : axis
+				bifurcation 0.005 'x*y*(1-y)' 'R'
+			\end{mglblock}
+		\end{verbatim}
+\begin{mglblock}{fractal}
+list A [0,0,0,.16,0,0,.01] [.85,.04,-.04,.85,0,1.6,.85] [.2,-.26,.23,.22,0,1.6,.07] [-.15,.28,.26,.24,0,.44,.07]
+ifs2d f A 100000
+subplot 2 1 0 '<_' : title 'A fractal fern'
+ranges f(0) f(1) : axis
+plot f(0) f(1) 'G#o '; size 0.05
+
+subplot 2 1 1 '<_' : title 'Bifurcation plot'
+ranges 0 4 0 1 : axis
+bifurcation 0.005 'x*y*(1-y)' 'R'
+\end{mglblock}
+		As you can see, although this is a verbatim-like environment, very long lines of code are split to fit the paragraph. Each line of code is numbered, this can be disabled with the \verb|lineno| option, like \verb|\begin{mglblock}[lineno=false]{fractal}|.
+		
+		\item[mglverbatim] This is like \verb|mglblock| environment, but it doesn't produce any script, just typesets the code to the \LaTeX{} document. It accepts the \verb|lineno| option, plus the \verb|label| option, in case you want to associate a name to the code.
+		
+		\item[mglcomment] This environment is used to embed comments in the document. You can control whether the contents of this environment are displayed or not, using the \verb|comments| and \verb|nocomments| package options, or the \verb|\mglcomments{on}| and \verb|mglcomments{off}| commands.
+		
+		An example of this would be:
+		\begin{verbatim}
+			\begin{mglcomments}
+				This comment will be shown because we used the "comments" package option for mglTeX
+			\end{mglcomments}
+		\end{verbatim}
+\begin{mglcomment}
+This comment will be shown because we used the "comments" package option for mglTeX
+\end{mglcomment}
+		Once again, long lines are broke down to fit the paragraph.
+	\end{description}
+	
+	\section{Basics on commands}
+	\begin{description}
+		\item[\textbackslash mglgraphics] This command takes the name of an external MGL script, compiles it, and includes the resulting image. It accespt the same optional arguments as the \verb|mgl| environment, except for \verb|label|, plus a \verb|path| option, which can be used to specify the location of the script. This is useful when you have a script outside of the \LaTeX{} document (sent by a colleague for example), but you don't want to transcript it to your document.
+		
+		For example, in order to display the image of the script we created with \verb|mglscript| environment, we write:
+		\begin{verbatim}
+			\begin{figure}[!ht]
+			  \centering
+			  \mglgraphics[height=9cm,width=9cm]{Gaston_surface}
+			  \caption{Gaston's surface}
+			\end{figure}
+		\end{verbatim}
+		\begin{figure}[!ht]
+			\centering
+			\mglgraphics[height=9cm,width=9cm]{Gaston_surface}
+			\caption{Gaston's surface: Three-dimensional parametric surface}
+		\end{figure}
+		
+		We could also could compile the script we created with the \verb|mglblock| environment:
+		\begin{verbatim}
+			\begin{figure}[!ht]
+			  \centering
+			  \mglgraphics[height=7cm,width=10cm]{fractal}
+			  \caption{Examples of fractal behavior}
+			\end{figure}
+		\end{verbatim}
+		\begin{figure}[!ht]
+			\centering
+			\mglgraphics[height=7cm,width=10cm]{fractal}
+			\caption{Examples of fractal behavior}
+		\end{figure}
+		
+		\item[\textbackslash mglinclude] This is equivalent to the \verb|mglblock| environment, but works for external scripts.
+		
+		\item[\textbackslash mglplot] This command allows the fast creation of plots. It takes one mandatory argument, which is a block of MGL code to produce the plot. Accepts the same optional arguments as the \verb|mgl| environment, plus an additional one, \verb|setup|, that can be used to specify a block of code to append, defined inside a \verb|mglsetup| environment (see the example below).
+		
+		The \verb|mglsetup| environment can be used if many plots will have the same settings (background color, etc.). Instead of writing the same code over and over again, it can be introduced in that environment, and used with the \verb|\mglplot| command.
+		
+		An example of use of the \verb|mglsetup| environment and the \verb|\mglplot| command would be:
+		\begin{verbatim}
+			\begin{mglsetup}{3d}
+			  clf 'W'
+			  rotate 50 60
+			  light on
+			  box : axis : grid 'xyz' ';k'
+			\end{mglsetup}
+			\begin{figure}[!ht]
+			  \centering
+			  \mglplot[setup=3d,scale=0.5]{fsurf 'cos(4*pi*hypot(x,y))*exp(-abs(x+y))'}
+			\end{figure}
+			\begin{figure}[!ht]
+			  \centering
+			  \mglplot[setup=3d,scale=0.5]{fsurf 'sin(pi*(x+y))'}
+			\end{figure}
+		\end{verbatim}
+		\begin{mglsetup}{3d}
+			clf 'W'
+			rotate 50 60
+			light on : light 0 0 1 0 'w' 0.25
+			box : axis : grid 'xyz' ';k'
+		\end{mglsetup}
+		\begin{figure}[!ht]
+			\centering
+			\mglplot[setup=3d,scale=0.5]{fsurf 'cos(4*pi*hypot(x,y))*exp(-abs(x+y))'}
+		\end{figure}
+		\begin{figure}[!ht]
+			\centering
+			\mglplot[setup=3d,scale=0.5]{fsurf 'sin(pi*(x+y))'}
+		\end{figure}
+	\end{description}
+	
+	There are more environments and commands defined by \mglTeX{}. The ones presented here are the most basic. More on this topic can be found in the documentation.
+\end{document}
\ No newline at end of file
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..00089c1
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,61 @@
+set(mgl_src
+	addon.cpp axis.cpp base_cf.cpp base.cpp canvas_cf.cpp canvas.cpp cont.cpp crust.cpp
+	complex.cpp complex_ex.cpp complex_io.cpp fft.cpp data_gr.cpp
+	data.cpp data_io.cpp data_ex.cpp data_png.cpp
+	export_2d.cpp export_3d.cpp eval.cpp evalp.cpp export.cpp
+	fit.cpp font.cpp obj.cpp other.cpp parser.cpp pde.cpp pixel.cpp pixel_gen.cpp
+	plot.cpp prim.cpp surf.cpp vect.cpp volume.cpp evalc.cpp
+	s_hull/s_hull_pro.cpp window.cpp fractal.cpp
+	exec_dat.cpp exec_gr.cpp exec_set.cpp exec_prm.cpp
+)
+
+set(mgl_hdr
+	../include/mgl2/base_cf.h	../include/mgl2/fit.h		../include/mgl2/plot.h
+	../include/mgl2/base.h		../include/mgl2/prim.h		../include/mgl2/canvas_cf.h
+	../include/mgl2/font.h		../include/mgl2/canvas.h	../include/mgl2/surf.h
+	../include/mgl2/mgl_cf.h	../include/mgl2/type.h		${MathGL2_BINARY_DIR}/include/mgl2/config.h
+${MathGL2_BINARY_DIR}/include/mgl2/dllexport.h	cont.hpp
+	../include/mgl2/cont.h		../include/mgl2/mgl.h		../include/mgl2/vect.h
+	../include/mgl2/data.h		../include/mgl2/volume.h	../include/mgl2/data_cf.h
+	../include/mgl2/define.h	../include/mgl2/other.h		../include/mgl2/eval.h
+	../include/mgl2/parser.h	../include/mgl2/addon.h		../include/mgl2/evalc.h
+	s_hull/s_hull_pro.h			../include/mgl2/wnd.h		../include/mgl2/canvas_wnd.h
+	../include/mgl2/thread.h	../include/mgl2/abstract.h	../include/mgl2/pde.h
+#	tex_table.cc	 def_font.cc
+)
+
+if(MGL_HAVE_GSL2)
+	add_definitions(-DMGL_HAVE_GSL2)
+endif(MGL_HAVE_GSL2)
+
+if(MGL_HAVE_PNG)
+	set(prc_src prc/PRCbitStream.cc prc/PRCdouble.cc prc/oPRCFile.cc prc/writePRC.cc prc.cpp )
+	set(prc_hdr prc/PRC.h prc/PRCbitStream.h prc/PRCdouble.h prc/oPRCFile.h prc/writePRC.h )
+
+	set(mgl_src ${mgl_src} ${prc_src} )
+	set(mgl_hdr ${mgl_hdr} ${prc_hdr} )
+	include_directories(prc)
+endif(MGL_HAVE_PNG)
+
+if(MGL_HAVE_OPENGL)
+	set(mgl_src ${mgl_src} opengl.cpp )
+	set(mgl_hdr ${mgl_hdr} ../include/mgl2/opengl.h )
+endif(MGL_HAVE_OPENGL)
+
+include(GenerateExportHeader)
+mgl_add_lib(mgl ${mgl_src} ${mgl_hdr})
+generate_export_header(mgl EXPORT_FILE_NAME ../include/mgl2/dllexport.h)
+
+target_link_libraries(mgl ${MGL_DEP_LIBS})
+target_link_libraries(mgl-static ${MGL_DEP_LIBS})
+
+mgl_po_src(${mgl_src} ${mgl_hdr})
+
+if(MGL_HAVE_MPI)
+	mgl_add_lib(mpi mpi.cpp ../include/mgl2/mpi.h)
+	target_link_libraries(mgl-mpi ${MPI_LIBRARIES} )
+	target_link_libraries(mgl-mpi-static ${MPI_LIBRARIES} )
+	target_include_directories(mgl-mpi SYSTEM PUBLIC ${MPI_CXX_INCLUDE_PATH})
+endif(MGL_HAVE_MPI)
+
+install(FILES ${MathGL2_BINARY_DIR}/include/mgl2/dllexport.h DESTINATION ${MGL_INCLUDE_PATH})
diff --git a/src/addon.cpp b/src/addon.cpp
new file mode 100644
index 0000000..da84360
--- /dev/null
+++ b/src/addon.cpp
@@ -0,0 +1,261 @@
+/***************************************************************************
+ * addon.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <stdarg.h>
+#ifdef WIN32
+#include <direct.h>
+#else
+#include <unistd.h>
+#endif
+#include <string.h>
+#include "mgl2/addon.h"
+#include "mgl2/data.h"
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_strcls(char *str)
+{
+	size_t len = strlen(str),i,n;
+	char *tmp = new char[len+1];	memset(tmp,0,len);
+	for(i=0;i<len;i++)
+	{
+		if(i<len-1 && str[i]==' ' && str[i+1]==' ')
+			continue;
+		tmp[i] = str[i];
+	}
+	len = strlen(tmp);
+	for(n=0;n<len;n++)		if(tmp[n]!=' ')	break;
+	for(i=len-1;i>0;i--)	if(tmp[i]!=' ')	break;
+	tmp[i+1]=0;	strcpy(str,&(tmp[n]));
+	delete []tmp;
+}
+//-----------------------------------------------------------------------------
+long MGL_EXPORT mgl_strpos(const char *str,char *fnd)
+{
+	const char *p=strstr(str,fnd);
+	return p?p-str:-1L;
+}
+//-----------------------------------------------------------------------------
+long MGL_EXPORT mgl_chrpos(const char *str,char ch)
+{
+	const char *p=str?strchr(str,ch):0;
+	return p?p-str:-1L;
+}
+//-----------------------------------------------------------------------------
+MGL_EXPORT char *mgl_fgetstr(FILE *fp)
+{
+	const long size=10240;	// NOTE: this set maximal length of string to be read
+	static char s[size];
+	do
+	{
+		if(!fgets(s,size,fp))	break;
+		mgl_strtrim(s);
+		//		strlwr(s);
+	} while(!feof(fp) && (s[0]==0 || s[0]=='%' || s[0]=='#'));
+	for(long i=0;s[i];i++)	if(s[i]=='#')	{	s[i]=0;	break;	}
+	mgl_strtrim(s);
+	return s;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_fgetpar(FILE *fp, const char *str, ...)
+{
+	if(!str || !str[0])	return;
+	const size_t len=strlen(str);
+	char *s, *t;
+	va_list lst;
+	va_start(lst,str);
+	t = mgl_fgetstr(fp);
+	for(size_t i=0;i<len;i++)
+	{
+		if(str[i]=='%')
+		{
+			if(str[i+1]=='s')	{	s = va_arg(lst, char*);	strcpy(s, t);	}
+			if(strchr("efg",str[i+1]))	{	double *v = va_arg(lst, double*);	*v = atof(t);	}
+			if(strchr("ld",str[i+1]))	{	long *n = va_arg(lst, long*); 	*n = atol(t);	}
+			i++;
+		}
+		if(str[i]==':')
+		{
+			for(;*t && *t!=':';t++);
+			if(*t==':')	t++;
+		}
+		if(str[i]<=' ')	t = mgl_fgetstr(fp);
+	}
+}
+//-----------------------------------------------------------------------------
+int MGL_EXPORT_CONST mgl_istrue(char ch)
+{	return (ch=='1' || ch=='t' || ch=='+' || ch=='v');	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_test(const char *str, ...)
+{
+	char buf[256];
+	va_list lst;
+	va_start(lst,str);
+	vsnprintf(buf,256,str,lst);	buf[255]=0;
+	va_end(lst);
+	printf(_("TEST: %s\n"),buf);
+	fflush(stdout);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_info(const char *str, ...)
+{
+	char buf[256];
+	va_list lst;
+	va_start(lst,str);
+	vsnprintf(buf,256,str,lst);	buf[255]=0;
+	va_end(lst);
+	printf("%s",buf);
+	FILE *fp = fopen("info.txt","at");
+	fprintf(fp,"%s",buf);
+	fclose(fp);
+}
+//-----------------------------------------------------------------------------
+MGL_EXPORT FILE *mgl_next_data(const char *fname,int p)
+{
+	char *s;
+	int len;
+	static int pos=0;
+	static char path[256];
+
+	if(p>0)	pos = p;
+	if(fname==NULL)	return NULL;
+	if(pos==0)	{	if(!getcwd(path,256))	return 0;	}	// remember ini dyrectory
+	else		{	if(chdir(path)==-1)		return 0;	}
+
+	// read the initial (common) data
+	FILE *fp=fopen(fname,"rt");
+	if(fp==NULL)	return NULL;
+	fseek(fp,0,SEEK_END);
+	len = ftell(fp);
+	if(pos>=len)		 // no more data
+	{	fclose(fp);	return NULL;	}
+	fseek(fp,pos,SEEK_SET);
+	//printf("pos 1 = %d\t",pos);
+	do
+	{
+		s = mgl_fgetstr(fp);
+		fflush(stdout);
+		if(s[0]=='$' || s[1]=='$' || s[3]=='$')
+		{	fclose(fp);	return NULL;	}
+	} while(!feof(fp) && (s[0]!='-' || s[1]!='-' || s[3]!='-'));
+	if(feof(fp))	// no more data
+	{	fclose(fp);	return NULL;	}
+	return fp;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_difr_grid(dual *a,int n,int step,dual q,int Border,dual *tmp,int kk)
+{	mgl_difr_grid_old(a,n,step,q,Border,tmp,tmp+n,kk);	}
+void MGL_EXPORT mgl_difr_grid_old(dual *a,int n,int step,dual q,int Border,dual *b, dual *d,int kk)
+{
+	const dual adt = dual(0.,1.)*q;
+	if(step==1)	memcpy(b,a,n*sizeof(dual));
+	else	for(long i=0;i<n;i++)	b[i] = a[i*step];
+	for(long k=kk;k>0;k--)	// 3 iterations
+	{
+		for(long i=1;i<n-1;i++)
+			d[i] = a[i*step] + adt*(b[i-1]+b[i+1]-mreal(2)*b[i])/mreal(k);
+		memcpy(b,d,n*sizeof(dual));
+		switch(Border)
+		{
+			default:
+			case 0:		// zero at border
+				b[0] = 0;	b[n-1] = 0;		break;
+			case 1:		// constant at border
+				b[0] = b[1];	b[n-1] = b[n-2];	break;
+			case 2:		// linear at border
+				b[0] = mreal(2)*b[1]-b[2];
+				b[n-1] = mreal(2)*b[n-2]-b[n-3];
+				break;
+			case 3:		// square at border
+				b[0] = b[3]+mreal(3)*(b[1]-b[2]);
+				b[n-1] = b[n-4]+mreal(3)*(b[n-2]-b[n-3]);
+				break;
+			case -1:		// exponent at border
+			case 4:
+				b[0] = norm(b[2])<norm(b[1]) ? b[1] : b[1]*b[1]/b[2];
+				b[n-1] = norm(b[n-3])<norm(b[n-2]) ? b[n-2] : b[n-2]*b[n-2]/b[n-3];
+				break;
+			case -2:		// gaussian at border
+			case 5:
+				b[0] = norm(b[2])<norm(b[1]) ? b[3] : pow(b[1]/b[2],3)*b[3];
+				b[n-1] = norm(b[n-3])<norm(b[n-2]) ? b[n-4] : pow(b[n-2]/b[n-3],3)*b[n-4];
+				break;
+		}
+	}
+	if(step==1)	memcpy(a,b,n*sizeof(dual));
+	else	for(long i=0;i<n;i++)	a[i*step] = b[i];
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_difr_axial(dual *a,int n,int step,dual q,int Border,dual *tmp,int kk, double di)
+{	mgl_difr_axial_old(a,n,step,q,Border,tmp,tmp+n,kk,di);	}
+void MGL_EXPORT mgl_difr_axial_old(dual *a,int n,int step,dual q,int Border,dual *b,dual *d,int kk, double di)
+{
+	int ii = di<0 ? -int(floor(di)) : 0;
+	mreal ff= di==floor(di) ? 4. : 2.;
+	const dual adt = dual(0.,1.)*q;
+	if(step==1)	memcpy(b,a,n*sizeof(dual));
+	else	for(long i=0;i<n;i++)	b[i] = a[i*step];
+	for(long k=kk;k>0;k--)	// kk iterations
+	{
+		d[ii] = a[ii] + adt*(b[ii+1]-b[ii])*(ff/k);
+		for(long i=ii+1;i<n-1;i++)
+		{
+			mreal dd = i+di;
+			dd = 1./(sqrt(dd*dd+1.)+dd);	// corrections for "axiality"
+			mreal gg = 1+dd*dd;
+			d[i] = a[i*step] + adt*( b[i-1]*((gg-dd)/k) - b[i]*(2*gg/k) + b[i+1]*((gg+dd)/k) );
+		}
+		memcpy(b,d,n*sizeof(dual));
+		switch(Border)
+		{
+			case 0:		// zero at border
+				b[n-1] = 0;		break;
+			case 1:		// constant at border
+				b[n-1] = b[n-2];	break;
+			case 2:		// linear at border
+				b[n-1] = -b[n-3] + mreal(2)*b[n-2];
+				break;
+			case 3:		// square at border
+				b[n-1] = b[n-4] + mreal(3)*(b[n-2]-b[n-3]);
+				break;
+			case -1:		// exponent at border
+				b[n-1] = norm(b[n-3])<norm(b[n-2]) ? b[n-2] : b[n-2]*b[n-2]/b[n-3];
+				break;
+			case -2:		// gaussian at border
+				b[n-1] = norm(b[n-3])<norm(b[n-2]) ? b[n-4] : pow(b[n-2]/b[n-3],3)*b[n-4];
+				break;
+		}
+	}
+	if(step==1)	memcpy(a,b,n*sizeof(dual));
+	else	for(long i=0;i<n;i++)	a[i*step] = b[i];
+}
+//-----------------------------------------------------------------------------
+double MGL_EXPORT mgl_gauss_rnd()
+{
+	double v1,v2;
+	v1 = mgl_rnd();
+	v2 = mgl_rnd();
+	return v1!=0 ? sqrt(-2.*log(v1))*cos(2*M_PI*v2) : 0;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_fft_freq(double *freq, long nn)
+{
+	freq[0] = 0;
+	for(long i=1;i<=nn/2;i++)
+	{	freq[i] = i; freq[nn-i] = -i;	}
+}
+//-----------------------------------------------------------------------------
diff --git a/src/axis.cpp b/src/axis.cpp
new file mode 100644
index 0000000..42c5338
--- /dev/null
+++ b/src/axis.cpp
@@ -0,0 +1,1127 @@
+/***************************************************************************
+ * axis.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <time.h>
+#include <ctype.h>
+#include "mgl2/data.h"
+#include "mgl2/canvas.h"
+#include "mgl2/prim.h"
+#include "mgl2/eval.h"
+std::wstring MGL_EXPORT mgl_ftoa(double v, const char *fmt);
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT inline struct tm *mgl_localtime (const time_t *clock, tm *result, bool use_utc)
+{	if (!clock || !result) return NULL;
+	const tm *res = use_utc?gmtime(clock):localtime(clock);
+	memcpy(result,res,sizeof(tm));	return result;	}
+//-----------------------------------------------------------------------------
+long MGL_EXPORT mgl_have_color(const char *stl)
+{
+	return mgl_get_num_color(stl,0);
+// 	long j=0;
+// 	if(stl)	for(long i=0;stl[i];i++)
+// 	{
+// 		if(strchr(MGL_COLORS,stl[i]))	j++;
+// 		if(stl[i]=='{' && stl[i+1]=='x')	j++;
+// 	}
+// 	return j;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_wcstrim(wchar_t *str)
+{
+	if(!str || *str==0)	return;
+	size_t n=mgl_wcslen(str), k, i;
+	for(k=0;k<n;k++)	if(str[k]>' ')	break;
+	for(i=n;i>k;i--)	if(str[i-1]>' ')	break;
+	for(size_t j=0;j<i-k;j++)	str[j]=str[j+k];
+	str[i-k]=0;
+}
+//-----------------------------------------------------------------------------
+//		Ticks setup
+//-----------------------------------------------------------------------------
+void mglCanvas::SetAxisStl(const char *stl, const char *tck, const char *sub)
+{
+	if(!stl || !(*stl))	strncpy(AxisStl,"k",32);
+	else 				strncpy(AxisStl,stl,32);
+	if(!tck || !(*tck))	strncpy(TickStl,AxisStl,32);
+	else 				strncpy(TickStl,tck,32);
+	if(!sub || !(*sub))	strncpy(SubTStl,TickStl,32);
+	else 				strncpy(SubTStl,sub,32);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::SetTickLen(mreal tlen, mreal stt)
+{	TickLen = tlen?tlen:0.02;	st_t=stt>0?stt:1;	}
+//-----------------------------------------------------------------------------
+void mglCanvas::SetTicks(char dir, mreal d, int ns, mreal org, const wchar_t *lbl)
+{
+	if(!strchr("xyzca",dir))	return;
+	mglAxis &aa = (dir=='x' ? ax : (dir=='y' ? ay : (dir=='z' ? az : ac)));
+
+	if(aa.f==1)	aa.t.clear();
+	aa.d=d;	aa.f=0;	aa.ns=ns;	aa.o=org;
+	aa.txt.clear();
+	if(!lbl || *lbl==0)	aa.fact.clear();
+	else	aa.fact = lbl;
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::AddTick(char dir, double v, const wchar_t *lbl)
+{
+	if(!strchr("xyzca",dir))	return;
+	mglAxis &aa = (dir=='x' ? ax : (dir=='y' ? ay : (dir=='z' ? az : ac)));
+	bool ff = (dir=='x' ? fx : (dir=='y' ? fy : (dir=='z' ? fz : fa)));
+
+	UpdateAxis();	AdjustTicks(aa,ff);
+	if(!v || !lbl || !lbl[0])	{	aa.f = 0;	return;	}
+	aa.f = 2;	aa.ns=0;	aa.ds=0;
+	aa.AddLabel(lbl,v);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::AddTick(char dir, double v, const char *lbl)
+{	MGL_TO_WCS(lbl,AddTick(dir,v,wcs));	}
+//-----------------------------------------------------------------------------
+void mglCanvas::SetTicksVal(char dir, HCDT v, const wchar_t *lbl, bool add)
+{
+	if(!strchr("xyzca",dir))	return;
+	mglAxis &aa = (dir=='x' ? ax : (dir=='y' ? ay : (dir=='z' ? az : ac)));
+	bool ff = (dir=='x' ? fx : (dir=='y' ? fy : (dir=='z' ? fz : fa)));
+
+	if(add)	{	UpdateAxis();	AdjustTicks(aa,ff);	}
+	else	aa.txt.clear();
+	if(!v || !lbl || !lbl[0])	{	aa.f = 0;	return;	}
+	aa.f = 2;	aa.ns=0;	aa.ds=0;
+	long i=0,l=0,n=v->GetNx();
+	for(long j=0;i<n && lbl[j];j++)
+	{
+		if(lbl[j]=='\n')
+		{
+			aa.AddLabel(std::wstring(lbl+l,j-l),v->v(i));
+			i++;	l=j+1;
+		}
+		if(j>1 && lbl[j]=='n' && lbl[j-1]=='\\')
+		{
+			aa.AddLabel(std::wstring(lbl+l,j-l-1),v->v(i));
+			i++;	l=j+1;
+		}
+	}
+	if(i<n && lbl[l])	aa.AddLabel(lbl+l,v->v(i));
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::SetTicksVal(char dir, HCDT v, const char *lbl, bool add)
+{	MGL_TO_WCS(lbl,SetTicksVal(dir,v,wcs,add));	}
+//-----------------------------------------------------------------------------
+void mglCanvas::SetTicksVal(char dir, const wchar_t *lbl, bool add)
+{
+	long i=0,len=mgl_wcslen(lbl);
+	for(long j=1;j<len;j++)
+		if(lbl[j]=='\n' || (lbl[j]=='n' && lbl[j-1]=='\\'))	i++;
+	if(i>63)	i=63;
+	mglData val(i+1);	val.Fill(Min.x,Max.x);
+	SetTicksVal(dir, &val, lbl, add);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::SetTicksVal(char dir, const char *lbl, bool add)
+{
+	long i=0,len=strlen(lbl);
+	for(long j=1;j<len;j++)
+		if(lbl[j]=='\n' || (lbl[j]=='n' && lbl[j-1]=='\\'))	i++;
+	if(i>63)	i=63;
+	mglData val(i+1);	val.Fill(Min.x,Max.x);
+	SetTicksVal(dir, &val, lbl, add);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::SetTicksVal(char dir, HCDT v, const wchar_t **lbl, bool add)
+{
+	if(!strchr("xyzca",dir))	return;
+	mglAxis &aa = (dir=='x' ? ax : (dir=='y' ? ay : (dir=='z' ? az : ac)));
+	bool ff = (dir=='x' ? fx : (dir=='y' ? fy : (dir=='z' ? fz : fa)));
+
+	if(add)	{	UpdateAxis();	AdjustTicks(aa,ff);	}
+	else	aa.txt.clear();
+	if(!v || !lbl)	{	aa.f = 0;	return;	}
+	aa.f = 2;	aa.ns=0;	aa.ds=0;
+	long n=v->GetNx();
+	for(long i=0;i<n;i++)	aa.AddLabel(lbl[i],v->v(i));
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::SetTicksVal(char dir, HCDT v, const char **lbl, bool add)
+{
+	if(!strchr("xyzca",dir))	return;
+	mglAxis &aa = (dir=='x' ? ax : (dir=='y' ? ay : (dir=='z' ? az : ac)));
+	bool ff = (dir=='x' ? fx : (dir=='y' ? fy : (dir=='z' ? fz : fa)));
+
+	aa.txt.clear();
+	if(add)	{	UpdateAxis();	AdjustTicks(aa,ff);	}
+	if(!v || !lbl)	{	aa.f = 0;	return;	}
+	aa.f = 2;	aa.ns=0;	aa.ds=0;
+	for(long i=0;i<v->GetNx();i++)	MGL_TO_WCS(lbl[i],aa.AddLabel(wcs,v->v(i)));
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::SetTickTempl(char dir, const wchar_t *t)
+{
+	if(!strchr("xyzca",dir))	return;
+	mglAxis &aa = (dir=='x' ? ax : (dir=='y' ? ay : (dir=='z' ? az : ac)));
+
+	if(aa.f==1)	aa.f = 0;	// remove time ticks
+	if(!t || !t[0])	aa.t.clear();	else aa.t=t;
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::SetTickTempl(char dir, const char *t)
+{
+	if(!strchr("xyzca",dir))	return;
+	mglAxis &aa = (dir=='x' ? ax : (dir=='y' ? ay : (dir=='z' ? az : ac)));
+
+	if(aa.f==1)	aa.f = 0;	// remove time ticks
+	if(!t || !t[0])	aa.t.clear();
+	else	MGL_TO_WCS(t,aa.t=wcs);
+}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT double mgl_adj_val(double v,mreal *ds=0)
+{
+	double n = floor(log10(v)), s;
+	v = floor(v*pow(10.,-n));	n = pow(10.,n);
+
+	if(v==1)	{	v = n/5;	s=n/10;	}
+	else if(v<4){	v = n/2;	s=n/10;	}
+	else if(v<7){	v = n;		s=n/5;	}
+	else		{	v = 2*n;	s=n/2;	}
+	if(ds)	*ds=s;
+	return v;
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::SetTickTime(char dir, mreal d, const char *t)
+{
+	if(!strchr("xyzca",dir))	return;
+	mglAxis &aa = (dir=='x' ? ax : (dir=='y' ? ay : (dir=='z' ? az : ac)));
+	UpdateAxis();
+
+	time_t tt;	tm t1,t2;
+	tt=(time_t)aa.v1;	mgl_localtime(&tt, &t1, get(MGL_USE_GMTIME));
+	tt=(time_t)aa.v2;	mgl_localtime(&tt, &t2, get(MGL_USE_GMTIME));
+	if(aa.v1<aa.v2)	// adjust periodic values
+	{
+		if(abs(t1.tm_year-t2.tm_year)==1)	t2.tm_yday += 365;
+		if(abs(t1.tm_yday-t2.tm_yday)==1)	t2.tm_hour += 24;
+		if(abs(t1.tm_hour-t2.tm_hour)==1)	t2.tm_min += 60;
+		if(abs(t1.tm_min-t2.tm_min)==1)		t2.tm_sec += 60;
+	}
+	else
+	{
+		if(abs(t1.tm_year-t2.tm_year)==1)	t1.tm_yday += 365;
+		if(abs(t1.tm_yday-t2.tm_yday)==1)	t1.tm_hour += 24;
+		if(abs(t1.tm_hour-t2.tm_hour)==1)	t1.tm_min += 60;
+		if(abs(t1.tm_min-t2.tm_min)==1)		t1.tm_sec += 60;
+	}
+	if(!t || !t[0])		// adjust template
+	{
+		t = abs(t1.tm_yday-t2.tm_yday)>1 ? "%x" : "%X";
+		if(abs(t1.tm_year-t2.tm_year)>3)	t = "%Y";
+	}
+	mreal ds=0;
+	if(d==0)	// try to select optimal step
+	{
+		if(abs(t1.tm_year-t2.tm_year)>1)	// number of second in year NOTE: improve it
+		{	d = 365.25*24*3600*mgl_adj_val(abs(t1.tm_year-t2.tm_year),&ds);
+			ds *= 365.25*24*3600;	}
+		// NOTE here should be months ... but it is too unregular ... so omit it now
+// 		else if(t1.tm_mon!=t2.tm_mon)	d = 30*24*3600;	// number of second in month
+		else if(abs(t1.tm_yday-t2.tm_yday)>=14)	// number of second in week 
+		{	d = mgl_adj_val(abs(t1.tm_yday-t2.tm_yday)/7,&ds);
+			ds = ((ds<1)?1./7:ds)*7*24*3600;	d = ((d>=1)?d:1)*7*24*3600;	}
+		else if(abs(t1.tm_yday-t2.tm_yday)>1)	// localtime("%x") cannot print time < 1 day
+		{	d = 24*3600.*mgl_adj_val(abs(t1.tm_yday-t2.tm_yday),&ds);
+			ds *= 24*3600;	if(d<24*3600)	{	d=24*3600;	ds=d/2;}	}
+		else if(abs(t1.tm_hour-t2.tm_hour)>1)
+		{	d = 3600.*mgl_adj_val(abs(t1.tm_hour-t2.tm_hour),&ds);	ds *=3600;	}
+		else if(abs(t1.tm_min-t2.tm_min)>1)
+		{	d = 60*mgl_adj_val(abs(t1.tm_min-t2.tm_min),&ds);	ds *=60;	}
+		else if(abs(t1.tm_sec-t2.tm_sec)>1)	// localtime("%X") cannot print time < 1 sec
+		{	d = mgl_adj_val(abs(t1.tm_sec-t2.tm_sec),&ds);
+			if(d<1)	{	d=1;	ds=0.5;}	}
+		else	// adjust msec. NOTE: this is not supported by localtime() !!!
+			d = mgl_adj_val(fabs(aa.v2-aa.v1),&ds);
+	}
+
+	aa.ds = ds;	aa.dv = d;	aa.f = 1;	aa.txt.clear();
+	MGL_TO_WCS(t,aa.t=wcs);
+
+	if(strchr("xyztuvw",aa.ch))
+		aa.org.Set(GetOrgX(aa.ch,aa.inv), GetOrgY(aa.ch,aa.inv), GetOrgZ(aa.ch,aa.inv));
+	if(aa.ch=='x')	aa.v0 = aa.org.x;
+	if(aa.ch=='y')	aa.v0 = aa.org.y;
+	if(aa.ch=='z')	aa.v0 = aa.org.z;
+
+	mreal v, v0 = mgl_isnan(aa.o) ? aa.v0 : aa.o, v1;
+	if(aa.v2>aa.v1)
+	{	v1 = aa.v2;		v0 = v0 - aa.dv*floor((v0-aa.v1)/aa.dv+1e-3);	}
+	else
+	{	v1 = aa.v1;		v0 = v0 - aa.dv*floor((v0-aa.v2)/aa.dv+1e-3);	}
+	if(v0+aa.dv!=v0 && v1+aa.dv!=v1)	for(v=v0;v<=v1;v+=aa.dv)
+	{
+		wchar_t buf[64];
+		tt = (time_t)v;	tm tp;		mgl_localtime(&tt, &tp, get(MGL_USE_GMTIME));
+		wcsftime(buf,64,aa.t.c_str(),&tp);	aa.AddLabel(buf,v);
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::AdjustTicks(const char *dir, bool force, std::string stl)
+{
+	if(force)	SetTuneTicks(3);
+	UpdateAxis();
+	if(strchr(dir,'x') || strchr(dir,'X'))	// NOTE dir have to be non-NULL here !!!
+	{	if(force)	ax.d=0;	ax.stl=stl;	AdjustTicks(ax,fx!=0);	}
+	if(strchr(dir,'y') || strchr(dir,'Y'))
+	{	if(force)	ay.d=0;	ay.stl=stl;	AdjustTicks(ay,fy!=0);	}
+	if(strchr(dir,'z') || strchr(dir,'Z'))
+	{	if(force)	az.d=0;	az.stl=stl;	AdjustTicks(az,fz!=0);	}
+	if(strchr(dir,'a') || strchr(dir,'c'))
+	{	if(force)	ac.d=0;	ac.stl=stl;	AdjustTicks(ac,fa!=0);	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::AdjustTicks(mglAxis &aa, bool ff)
+{
+	double d = fabs(aa.v2-aa.v1);
+	if(aa.f>0)	return;
+	if(ff && mgl_islog(aa.v1,aa.v2))
+	{	aa.dv = 0;	aa.ds=0;	}
+	else if(aa.d>0)
+	{	aa.dv = aa.d;	aa.ds = aa.d/(abs(aa.ns)+1);	}
+	else if(aa.d>-1.5)	// like =0 or =-1
+	{	aa.dv = mgl_adj_val(d,&aa.ds);	aa.o=0;	}
+	else
+	{
+		d /= -aa.d;
+		long n = lrint(floor(log10(d)));
+		aa.dv = pow(10.,n)*mgl_int(d*pow(10.,-n));
+		aa.o=0;	aa.ds = pow(10.,n);
+	}
+	LabelTicks(aa);
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgl_tick_ext(mreal a, mreal b, wchar_t s[32], mreal &v)
+{
+	int kind = 0;
+	if(fabs(a-b)<=0.01*fabs(a))
+	{
+		kind = 1;
+		v = fabs(a-b);
+		if(v>1000.f)
+		{
+			int k=int(log10(v)-0.01);
+			kind=3;		v=mgl_ipow(10.,k);
+			mglprintf(s, 32, L" (@{\\times{}10^{%d}})", k);
+		}
+		else if(v<0.02f)
+		{
+			int k=int(log10(v)-0.01)-1;
+			kind=3;		v=mgl_ipow(10.,k);
+			mglprintf(s, 32, L" (@{\\times{}10^{%d}})", k);
+		}
+	}
+	else
+	{
+		v = fabs(b)>fabs(a)?fabs(b):fabs(a);
+		if(v>=1000.f)
+		{
+			kind = 2;
+			int k=int(log10(v)-0.01);
+			v=mgl_ipow(10.,k);
+			mglprintf(s, 32, L" \\times 10^{%d}", k);
+		}
+		else if(v<=1e-3f)
+		{
+			kind = 2;
+			int k=int(log10(v)-0.01)-1;
+			v=mgl_ipow(10.,k);
+			mglprintf(s, 32, L" \\times 10^{%d}", k);
+		}
+	}
+	return kind;
+}
+//-----------------------------------------------------------------------------
+std::wstring MGL_NO_EXPORT mgl_format(mreal v1, mreal v2, bool zero)
+{
+	v1=fabs(v1);	v2=fabs(v2);	if(v1>v2)	v2=v1;
+	wchar_t str[5]=L"%.3g";
+	int prec=int(2-log10(v2));	if(prec<0)	prec=0;
+	if(v2<=0.001 || v2>=10000)
+	{	str[2] = '2';	str[3]='e';	}
+	else if(zero)
+	{	str[2] = '0'+prec;	str[3]='f';	}
+	return str;
+}
+//-----------------------------------------------------------------------------
+std::wstring MGL_NO_EXPORT mgl_tick_text(mreal z, mreal z0, mreal d, mreal v, int kind, const std::wstring &fact, mreal step, const char *stl)
+{
+	std::wstring str;
+	bool ff = step>0 && !fact.empty();// && mgl_wcslen(str)+fact.length()<62;
+	if(ff)	z/=step;
+	mreal u = fabs(z)<d ? 0:z;
+	if((kind&1) && z>z0)	u = fabs(z-z0)<d ? 0:(z-z0);
+	if(kind==2 || (kind==3 && z>z0))	u /= v;
+	str = mgl_ftoa(u,stl?stl:"");
+	if((kind&1) && z>z0)	str = L"@{(+"+str+L")}";
+//	if(kind&1)	fmt = z>z0?L"@{(+"+fmt+L")}":L"%g";
+//	mglprintf(str,64,fmt.c_str(), u);
+	if(ff)
+	{
+		if(str==L"-1" || str==L"+1" || str==L"\u22121")	str = str[0] + fact;
+		else if(str==L"1")	str = fact;
+		else if(str!=L"0")	str += fact;
+	}
+	return str;
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::LabelTicks(mglAxis &aa)
+{
+	if(strchr("xyztuvw",aa.ch))
+		aa.org.Set(GetOrgX(aa.ch,aa.inv), GetOrgY(aa.ch,aa.inv), GetOrgZ(aa.ch,aa.inv));
+	if(aa.ch=='x')	aa.v0 = aa.org.x;
+	if(aa.ch=='y')	aa.v0 = aa.org.y;
+	if(aa.ch=='z')	aa.v0 = aa.org.z;
+
+	wchar_t buf[64]=L"";
+	mreal v,v0,v1,w=0;
+	int d,ds;
+	if(aa.f)	return;
+	aa.txt.clear();
+	bool minus = mglchr(aa.stl.c_str(),'-') && !mglchr(aa.stl.c_str(),'+');
+	if(aa.dv==0 && aa.v1>0)	// positive log-scale
+	{
+		v0 = exp(M_LN10*floor(0.1+log10(aa.v1)));
+		ds = int(floor(0.1+log10(aa.v2/v0))/7)+1;
+		for(v=v0;v<=aa.v2*MGL_EPSILON;v*=10)	if(v*MGL_EPSILON>=aa.v1)
+		{
+			d = int(floor(0.1+log10(v)));
+			if(d==0)	wcscpy(buf,L"1");
+			else if(d==1)	wcscpy(buf,L"10");
+			else if(d>0)	mglprintf(buf,64,L"10^{%d}",d);
+			else	mglprintf(buf,64,minus?L"10^{-%d}":L"10^{\u2212%d}",-d);
+			if(d%ds!=0)	*buf=0;	//	remove too often log ticks
+			aa.AddLabel(buf,v);
+		}
+	}
+	else if(aa.dv==0 && aa.v2<0)	// negative log-scale
+	{
+		v0 = -exp(M_LN10*floor(0.1+log10(-aa.v2)));
+		ds = int(floor(0.1+log10(aa.v1/v0))/7)+1;
+		for(v=v0;v>=aa.v1*MGL_EPSILON;v*=10)	if(v*MGL_EPSILON<=aa.v2)
+		{
+			d = int(floor(0.1+log10(-v)));
+			if(d==0)	wcscpy(buf,minus?L"-1":L"\u22121");
+			else if(d==1)	wcscpy(buf,minus?L"-10":L"\u221210");
+			else if(d>0)	mglprintf(buf,64,minus?L"-10^{%d}":L"\u221210^{%d}",d);
+			else	mglprintf(buf,64,minus?L"-10^{-%d}":L"\u221210^{\u2212%d}",-d);
+			if(d%ds!=0)	*buf=0;	//	remove too often log ticks
+			aa.AddLabel(buf,v);
+		}
+	}
+	else if(aa.dv)	// ticks drawing
+	{
+		int kind=0;
+		wchar_t s[32]=L"";
+		if(aa.t.empty() && TuneTicks && !strchr(aa.stl.c_str(),'!'))
+			kind = mgl_tick_ext(aa.v2, aa.v1, s, w);
+		if(((TuneTicks&1)==0 && kind==2) || ((TuneTicks&2)==0 && kind!=2))
+			kind=0;
+
+		v0 = mgl_isnan(aa.o) ? aa.v0 : aa.o;
+		if(mgl_isnan(v0))	v0=0;
+		if(aa.v2>aa.v1)
+		{	v1 = aa.v2;		v0 = v0 - aa.dv*floor((v0-aa.v1)/aa.dv+1e-3);	}
+		else
+		{	v1 = aa.v1;		v0 = v0 - aa.dv*floor((v0-aa.v2)/aa.dv+1e-3);	}
+
+		if(v0+aa.dv!=v0 && v1+aa.dv!=v1)
+		{
+			if(aa.t.empty())	for(v=v0;v<=v1;v+=aa.dv)
+				aa.AddLabel(mgl_tick_text(v,v0,aa.dv/100,w,kind,aa.fact,aa.d,aa.stl.c_str()),v);
+			else	for(v=v0;v<=v1;v+=aa.dv)
+			{
+				if(aa.t[0]!='&')	mglprintf(buf, 64, aa.t.c_str(), fabs(v)<aa.dv/100 ? 0 : v);
+				else	mglprintf(buf, 64, aa.t.c_str()+1, mgl_int(fabs(v)<aa.dv/100 ? 0 : v));
+				mgl_wcstrim(buf);	aa.AddLabel(buf,v);
+			}
+		}
+		if(kind&2)	aa.AddLabel(s,FactorPos*(aa.v2-aa.v1)+aa.v1);
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Axis(const char *dir, const char *stl, const char *opt)
+{
+	bool text = !(mglchr(dir,'_') || mglchr(dir,'~'));
+	bool inv = mglchr(dir,'^');
+	bool ret = get(MGL_ENABLE_RTEXT);
+	if(mglchr(dir,'U'))	clr(MGL_ENABLE_RTEXT);
+
+	std::string Tstl;
+	for(const char *s="+E0123456789-fF!";*s;s++)	if(mglchr(dir,*s))	Tstl += *s;
+
+	const char *ar = "AKDTVISO";
+	char arr=0;
+	for(size_t i=0;i<strlen(ar);i++)
+		if(strchr(dir,ar[i]))	{	arr=ar[i];	break;	}
+	if(!mglchrs(dir,"xXyYzZ"))	dir="xyz";
+
+	mreal angl = SaveState(opt);
+	AdjustTicks(dir,mglchr(stl,'a'),Tstl);
+	LoadState();
+
+	ax.pos = strchr(dir,'X') ? 'T':'t';
+	ay.pos = strchr(dir,'Y') ? 'T':'t';
+	az.pos = strchr(dir,'Z') ? 'T':'t';
+	ax.inv = ay.inv = az.inv = false;
+
+	if(strchr(dir,'X') || strchr(dir,'x'))
+	{	ax.inv = inv;	DrawAxis(ax, text, arr, stl, angl);	}
+	if(strchr(dir,'Z') || strchr(dir,'z'))
+	{	az.inv = inv;	DrawAxis(az, text, arr, stl, angl);	}
+	if((TernAxis&3))
+	{
+		mglAxis ty(ay);		ty.pos='t';	ty.ch='T';
+		ty.dir.Set(-1,1);		ty.org.Set(1,0,ay.org.z);
+		DrawAxis(ty, text, arr, stl, angl);	ty.ch='t';
+		ty.dir.Set(0,-1);		ty.org.Set(0,1,ay.org.z);
+		DrawAxis(ty, text, arr, stl, angl);
+	}
+	else if(strchr(dir,'Y') || strchr(dir,'y'))
+	{	ay.inv = inv;	DrawAxis(ay, text, arr, stl, angl);	}
+	set(ret, MGL_ENABLE_RTEXT);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::DrawAxis(mglAxis &aa, bool text, char arr,const char *stl,mreal angl)
+{
+	aa.angl = angl;
+	if(strchr("xyz",aa.ch))
+		aa.org.Set(GetOrgX(aa.ch,aa.inv), GetOrgY(aa.ch,aa.inv), GetOrgZ(aa.ch,aa.inv));
+	if(aa.ch=='x')	aa.v0 = aa.org.x;
+	if(aa.ch=='y')	aa.v0 = aa.org.y;
+	if(aa.ch=='z')	aa.v0 = aa.org.z;
+
+	mglPoint d(aa.dir), o(aa.org), q(NAN);	// "transverse" org
+	if(strchr("xyz",aa.ch))	o -= d*(o*d);
+	mglPoint av=(Min+Max)/2, dv,da,db, p;
+	dv.Set(mgl_sign(av.x-o.x), mgl_sign(av.y-o.y), mgl_sign(av.z-o.z));
+	da = aa.a*(dv*aa.a);	db = aa.b*(dv*aa.b);
+
+	long k1,k2;
+	bool have_color=mgl_have_color(stl);
+	bool dif_color = !have_color && aa.dv==0 && strcmp(TickStl,SubTStl);
+	SetPenPal(have_color ? stl:AxisStl);
+	static int cgid=1;	StartGroup("Axis",cgid++);
+
+	p = o + d*aa.v1;	k1 = AddPnt(&B, p,CDef,q,-1,3);
+	for(long i=1;i<31;i++)	// axis itself
+	{
+		p = o + d*(aa.v1+(aa.v2-aa.v1)*i/30.);
+		k2 = k1;	k1 = AddPnt(&B, p,CDef,q,-1,3);
+		line_plot(k2,k1);
+	}
+	if(arr)
+	{
+		p = o + d*(aa.v1+(aa.v2-aa.v1)*1.05);
+		k2 = k1;	k1 = AddPnt(&B, p,CDef,q,-1,3);
+		line_plot(k1,k2);	arrow_plot(k1,k2,arr);
+	}
+
+	k2 = aa.txt.size();
+	mreal v, u, v0 = mgl_isnan(aa.o) ? aa.v0 : aa.o;
+	if(*TickStl && !have_color)	SetPenPal(TickStl);
+	if(k2>0)	for(long i=0;i<k2;i++)
+	{
+		v = aa.txt[i].val;	u = fabs(v);
+		if((v-aa.v2)*(v-aa.v1)<=0)	tick_draw(o+d*v, da, db, 0);
+		if(dif_color)	SetPenPal(SubTStl);
+		if(aa.dv==0 && aa.v2>aa.v1 && fabs(u-exp(M_LN10*floor(0.1+log10(u))))<0.01*u)
+			for(long j=2;j<10 && v*j<aa.v2;j++)	tick_draw(o+d*(v*j),da,db,1);
+		if(aa.dv==0 && aa.v2<aa.v1 && fabs(u-exp(M_LN10*floor(0.1+log10(u))))<0.01*u)
+			for(long j=2;j<10 && v*j<aa.v1;j++)	tick_draw(o+d*(v*j),da,db,1);
+		if(dif_color)	SetPenPal(TickStl);
+	}
+	if(aa.ds>0 && !get(MGL_NOSUBTICKS) && (fabs(aa.v1)>1e-150 || fabs(aa.v2)>1e-150))
+	{
+		if(aa.v2>aa.v1)	v0 = v0 - aa.ds*floor((v0-aa.v1)/aa.ds+1e-3);
+		else			v0 = v0 - aa.ds*floor((v0-aa.v2)/aa.ds+1e-3);
+		if(v0+aa.ds!=v0 && aa.v2+aa.ds!=aa.v2)
+		{
+			if(*SubTStl && !have_color)	SetPenPal(SubTStl);
+			for(v=v0;(v-aa.v2)*(v-aa.v1)<=0;v+=aa.ds)
+				tick_draw(o+d*v,da,db,1);
+		}
+	}
+	if(!have_color)	SetPenPal(AxisStl);
+	if(text)	DrawLabels(aa);
+	EndGroup();
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::DrawLabels(mglAxis &aa, bool inv, const mglMatrix *M)
+{
+	if(M==0)	M=&B;
+	if(strchr("xyz",aa.ch))
+		aa.org.Set(GetOrgX(aa.ch,aa.inv), GetOrgY(aa.ch,aa.inv), GetOrgZ(aa.ch,aa.inv));
+	if(aa.ch=='x')	aa.v0 = aa.org.x;
+	if(aa.ch=='y')	aa.v0 = aa.org.y;
+	if(aa.ch=='z')	aa.v0 = aa.org.z;
+
+	mglPoint d(aa.dir), o(aa.org), q(NAN);	// "transverse" org
+	if(strchr("xyz",aa.ch))	o -= d*(o*d);
+	mglPoint s=(Min+Max)/2, dv(mgl_sign(s.x-o.x), mgl_sign(s.y-o.y), mgl_sign(s.z-o.z));
+	mglPoint a = aa.a*(dv*aa.a) + aa.b*(dv*aa.b);
+	if(aa.ch=='c')	a = aa.a;
+
+	long n = aa.txt.size();
+	mreal *w=new mreal[n], wsp = 2*TextWidth(" ",FontDef,-1);
+	long *kk=new long[n];
+	for(long i=0;i<n;i++)	// fill base label properties
+	{
+		w[i] = TextWidth(aa.txt[i].text.c_str(),FontDef,-1);
+		kk[i] = AddPnt(M, o+d*aa.txt[i].val,-1,d,0,7);
+	}
+	mreal c=INFINITY, l=0, h = TextHeight(FontDef,-1);	// find sizes
+	for(long i=0;i<n-1;i++)
+	{
+		// exclude factors
+		if(aa.ch!='c' && (aa.txt[i].val<aa.v1 || aa.txt[i+1].val<aa.v1 || aa.txt[i].val>aa.v2 || aa.txt[i+1].val>aa.v2))
+			continue;
+		if(kk[i]<0 || kk[i+1]<0)	continue;
+		mreal v = (GetPntP(kk[i+1])-GetPntP(kk[i])).norm();	// distance between ticks
+		mreal vv = (w[i]+w[i+1])/2-wsp;	// length of labels
+		if(v>0 && l < vv/v)	l = vv/v;
+		if(c>v)	c = v;
+	}
+	h /= c;
+
+	mreal tet=0;
+	if(mgl_isnum(aa.angl))	tet = aa.angl*M_PI/180;	// manual rotation
+	else if(get(MGL_ENABLE_RTEXT) && get(MGL_TICKS_ROTATE) && l>1)	// try rotate first
+	{
+		mreal t1 = 1.1*h<1 ? asin(1.1*h) : M_PI/2;
+		mreal r2 = l*l+h*h;
+		mreal t2 = r2*1.21>1 ? asin((l*sqrt(r2-1/1.21)+h/1.1)/r2):M_PI/2;
+		tet = t1<t2 ? t1:t2;
+	}
+	mreal sn = sin(tet), cs=cos(tet);
+	if(sn)
+	{
+		mreal l1=h/fabs(sn), l2=fabs(l*cs+h*sn);
+		l = l2>l1?l1:l2;
+	}
+	char *align=new char[n], *up=new char[n];
+	for(long i=0;i<n;i++)	if(kk[i]>=0)	// select proper align
+	{
+		mglPoint p(a),r(o+d*aa.txt[i].val);
+		ScalePoint(M, r, p, false);
+		mglPnt &pp = Pnt[kk[i]];
+		mreal ux=pp.u*cs + pp.v*sn, uy=pp.v*cs - pp.u*sn;
+		bool Nrot = !get(MGL_ENABLE_RTEXT) || !get(MGL_TICKS_ROTATE);
+		bool Vcnt = ux==0 && uy!=0 && Nrot;
+		bool algn = tet!=0;		// TODO add proper align for arbitrary tet!
+		if(ux*ux+uy*uy!=0 && Nrot)	{	ux=1;	uy=0;	algn=true;	}
+		if(ux<0 || (ux==0 && uy<0))	{	ux=-ux;	uy=-uy;	pp.w=-pp.w;	}
+		pp.u = ux;	pp.v = uy;
+		mreal pu = p.x*ux+p.y*uy, pv = p.y*ux-p.x*uy; /*, su = ps.x*ux+ps.y*uy;*/
+		if(Vcnt)	up[i]='V';
+		else if(aa.ch!='c')	up[i] = ((pv>0) ^ inv) ? 'T':'t';
+		else		up[i]=(aa.ns==0 || aa.ns==3)?'t':'T';
+		int t=0;
+		if(algn)
+		{
+			if(aa.ch!='c')	t= (pu==0)?0:(pu<0? -1:1);
+			else	t=inv?-1:1;
+		}
+		char val[3]={'L','C','R'};	align[i] = val[t+1];
+	}
+	long k = get(MGL_TICKS_SKIP) ? 1+l : 1;
+
+	for(long i=0;i<n;i++)	if(kk[i]>=0)
+	{
+		mreal v = aa.txt[i].val;
+		if(get(MGL_NO_ORIGIN) && v==aa.v0)	continue;
+		if(v>aa.v1 && v<aa.v2 && i%k!=0)	continue;
+		char pos[4]={up[i],':',align[i],0};
+		text_plot(kk[i], aa.txt[i].text.c_str(), pos, -1, aa.sh+0.1,CDef);
+	}
+	delete []w;	delete []kk;	delete []align;	delete []up;
+}
+//-----------------------------------------------------------------------------
+char mglCanvas::GetLabelPos(mreal c, long kk, mglAxis &aa)
+{
+	if(strchr("xyz",aa.ch))
+		aa.org.Set(GetOrgX(aa.ch,aa.inv), GetOrgY(aa.ch,aa.inv), GetOrgZ(aa.ch,aa.inv));
+	mglPoint d = aa.dir, o = aa.org;	// "transverse" org
+	if(strchr("xyz",aa.ch))	o -= d*(o*d);
+	mglPoint p,q, s=(Min+Max)/2, nn;
+	s = s - d*(s*d);
+
+	int ts = 1;
+	if(aa.ch=='c')	ts=(aa.ns==0 || aa.ns==3)?1:-1;
+	if(aa.ch=='T')	ts=-1;
+
+	p = o+d*c;	nn = s-o;	ScalePoint(&B,p,nn);
+	mglPnt &qq = Pnt[kk];
+
+	if(aa.ch=='c')	qq.u = qq.v = NAN;
+	if(!get(MGL_DISABLE_SCALE))	ts = mgl_sign(qq.v*nn.x-qq.u*nn.y);
+	if(aa.ch=='T')	ts *= -1;
+	if(aa.pos=='T')	ts *= -1;
+	return ts>0 ? 't':'T';
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::tick_draw(mglPoint o, mglPoint d1, mglPoint d2, int f)
+{
+	if(TickLen==0)	return;
+	// try to exclude ticks out of axis range
+	if(f && ((o.x-Min.x)*(o.x-Max.x)>0 || (o.y-Min.y)*(o.y-Max.y)>0 || (o.z-Min.z)*(o.z-Max.z)>0))
+		return;
+	mreal v = font_factor*TickLen/sqrt(1.f+f*st_t);
+	mglPoint p=o;
+
+	ScalePoint(&B,o, d1, false);	d1.Normalize();
+	ScalePoint(&B,p, d2, false);	d2.Normalize();
+	long k2 = AddPnt(&B, p, CDef, mglPoint(NAN), 0, 0);
+	long k1 = AddPnt(&B, p+d1*v, CDef, mglPoint(NAN), 0, 0);
+	long k3 = AddPnt(&B, p+d2*v, CDef, mglPoint(NAN), 0, 0);
+	line_plot(k1,k2);	line_plot(k2,k3);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Grid(const char *dir, const char *pen, const char *opt)
+{
+	SaveState(opt);
+	bool at_tick=mglchr(dir,'!');
+	if(!mglchrs(dir,"xyz"))	dir="xyz";
+	AdjustTicks(dir,false);
+	SetPenPal(pen);
+
+	static int cgid=1;	StartGroup("AxisGrid",cgid++);
+	if(strchr(dir,'x'))	DrawGrid(ax,at_tick);
+	if(strchr(dir,'y'))	DrawGrid(ay,at_tick);
+	if(strchr(dir,'z'))	DrawGrid(az,at_tick);
+	EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_drw_grid(HMGL gr, double val, const mglPoint &d, const mglPoint &oa, const mglPoint &ob, const mglPoint &da1, const mglPoint &db1, const mglPoint &da2, const mglPoint &db2)
+{
+	gr->Reserve(62);
+	mglPoint q,p;
+	q = oa+d*val;	p = q+da1;	// lines along 'a'
+	long k1 = gr->AddPnt(p), k2;
+	for(long j=1;j<31;j++)
+	{
+		mreal v = j/30.;
+		p = q+da1*(1-v)+da2*v;
+		k2 = k1;	k1 = gr->AddPnt(p);
+		gr->line_plot(k2,k1);
+	}
+	q = ob+d*val;	p = q+db1;	// lines along 'b'
+	k1 = gr->AddPnt(p);
+	for(long j=1;j<31;j++)
+	{
+		mreal v = j/30.;
+		p = q+db1*(1-v)+db2*v;
+		k2 = k1;	k1 = gr->AddPnt(p);
+		gr->line_plot(k2,k1);
+	}
+}
+void mglCanvas::DrawGrid(mglAxis &aa, bool at_tick)
+{
+	mglPoint pp[8]={Min,Min,Min,Min,Max,Max,Max,Max},nan(NAN), oo[8], org=Min;
+	pp[1].x=Max.x;	pp[2].y=Max.y;	pp[3].z=Max.z;
+	pp[4].x=Min.x;	pp[5].y=Min.y;	pp[6].z=Min.z;
+	mreal zm=INFINITY;
+	memcpy(oo,pp,8*sizeof(mglPoint));
+	for(int i=0;i<8;i++)	// find deepest point
+	{
+		ScalePoint(&B,pp[i],nan,false);
+		if(pp[i].z<zm)	{	zm=pp[i].z;	org=oo[i];	}
+	}
+	if(mgl_isnum(Org.x)) 	org.x = Org.x;
+	if(mgl_isnum(Org.y)) 	org.y = Org.y;
+	if(mgl_isnum(Org.z)) 	org.z = Org.z;
+	mglPoint d=aa.dir, da1,da2,db1,db2,oa,ob, p,q;
+	da1 = aa.a*(aa.a*Min);	da2 = aa.a*(aa.a*Max);
+	db1 = aa.b*(aa.b*Min);	db2 = aa.b*(aa.b*Max);
+	oa  = aa.b*(aa.b*org);	ob  = aa.a*(aa.a*org);
+
+	if(at_tick && aa.ds>0 && !get(MGL_NOSUBTICKS))
+	{
+		mreal v0 = mgl_isnan(aa.o) ? aa.v0 : aa.o;
+		if(aa.v2>aa.v1)	v0 = v0 - aa.ds*floor((v0-aa.v1)/aa.ds+1e-3);
+		else			v0 = v0 - aa.ds*floor((v0-aa.v2)/aa.ds+1e-3);
+		fflush(stdout);		// somehow this help to bypass bug in GCC 32bit
+		if(v0+aa.ds!=v0 && aa.v2+aa.ds!=aa.v2)
+			for(mreal v=v0;(v-aa.v2)*(v-aa.v1)<=0;v+=aa.ds)
+				mgl_drw_grid(this, v, d, oa, ob, da1, db1, da2, db2);
+	}
+	if(aa.dv)	at_tick = false;
+	long n=aa.txt.size();
+	if(n>0)	for(long i=0;i<n;i++)
+	{
+		mreal v = aa.txt[i].val;
+		mgl_drw_grid(this, v, d, oa, ob, da1, db1, da2, db2);
+		if(at_tick)
+		{
+			mreal u = fabs(v);
+			if(aa.v2>aa.v1 && fabs(u-exp(M_LN10*floor(0.1+log10(u))))<0.01*u)
+				for(long j=2;j<10 && v*j<aa.v2;j++)
+					mgl_drw_grid(this, v*j, d, oa, ob, da1, db1, da2, db2);
+			if(aa.v2<aa.v1 && fabs(u-exp(M_LN10*floor(0.1+log10(u))))<0.01*u)
+				for(long j=2;j<10 && v*j<aa.v1;j++)
+					mgl_drw_grid(this, v*j, d, oa, ob, da1, db1, da2, db2);
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Label(char dir, const char *str, mreal pos, const char *opt)
+{
+	MGL_TO_WCS(str,Labelw(dir, wcs, pos, opt));
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Labelw(char dir, const wchar_t *text, mreal pos, const char *opt)
+{
+	mreal shift =  SaveState(opt), t=0;	if(mgl_isnan(shift))	shift=0;
+	mglPoint p,q;
+	mglAxis *aa=0;
+
+	mglAxis ty(ay);
+
+	if(dir=='x')
+	{
+		AdjustTicks(ax,fx!=0);	aa = &ax;
+		if(ax.dv)	t = (Min.x+Max.x+pos*(Max.x-Min.x))/2;
+		else	t = Min.x*pow(Max.x/Min.x, (pos+1)/2);
+		p.Set(t, GetOrgY(ax.ch,ax.inv), GetOrgZ(ax.ch,ax.inv));
+		q.Set(1,0,0);	shift += ax.sh;
+	}
+	if(dir=='y' && !(TernAxis&3))
+	{
+		AdjustTicks(ay,fy!=0);	aa = &ay;
+		if(ay.dv)	t = (Min.y+Max.y+pos*(Max.y-Min.y))/2;
+		else	t = Min.y*pow(Max.y/Min.y, (pos+1)/2);
+		p.Set(GetOrgX(ay.ch,ay.inv), t, GetOrgZ(ay.ch,ay.inv));
+		q.Set(0,1,0);	shift += ay.sh;
+		if(TernAxis&3)
+		{
+			q.Set(-1,1,0);	pos=-pos;
+		}
+	}
+	if(dir=='y' && (TernAxis&3))
+	{
+		ty.ch='T';	ty.dir.Set(-1,1);	ty.org.Set(1,0,ay.org.z);
+		AdjustTicks(ty,fy!=0);	aa = &ty;
+		if(ty.dv)	t = (Min.y+Max.y+pos*(Max.y-Min.y))/2;
+		else	t = Min.y*pow(Max.y/Min.y, (pos+1)/2);
+		p.Set(GetOrgX(ty.ch,ty.inv), t, GetOrgZ(ty.ch,ty.inv));
+		q.Set(0,1,0);	shift += ty.sh;
+		if(TernAxis&3)
+		{
+			q.Set(-1,1,0);	pos=-pos;
+		}
+	}
+	if(dir=='t' && (TernAxis&3))
+	{
+		ty.ch='t';	ty.dir.Set(0,-1);	ty.org.Set(0,1,ay.org.z);
+		AdjustTicks(ty,fy!=0);	pos = -pos;	aa = &ty;
+		if(ty.dv)	t = (Min.y+Max.y+pos*(Max.y-Min.y))/2;
+		else	t = Min.y*pow(Max.y/Min.y, (pos+1)/2);
+		p.Set(GetOrgX(ty.ch,ty.inv), t, GetOrgZ(ty.ch,ty.inv));
+		q.Set(0,1,0);	shift += ty.sh;
+	}
+	if(dir=='z')
+	{
+		AdjustTicks(az,fz!=0);	aa = &az;
+		if(az.dv)	t = (Min.z+Max.z+pos*(Max.z-Min.z))/2;
+		else	t = Min.z*pow(Max.z/Min.z, (pos+1)/2);
+		p.Set(GetOrgX(az.ch,az.inv), GetOrgY(az.ch,az.inv), t);
+		q.Set(0,0,1);	shift += az.sh;
+	}
+	if(aa)
+	{
+		char font[64],ff[3]=":C";	memset(font,0,64);
+		if(pos<-0.2)	ff[1]='L';
+		if(pos>0.2)	ff[1]='R';
+		strncpy(font,FontDef,32);	strcat(font,ff);
+		long kk = AddPnt(&B, p,-1,q,0,7);	ff[1]=0;
+		if(kk>=0)
+		{
+			mglPnt &pp = Pnt[kk];
+			if(pp.u<0 || (pp.u==0 && pp.v<0))
+			{	pp.u=-pp.u;	pp.v=-pp.v;	pp.w=-pp.w;	}
+			ff[0] = GetLabelPos(t, kk, *aa);	strcat(font,ff);
+			text_plot(kk,text,font,-1.4,(ff[0]=='T'?0.3:0.35)+shift);
+		}
+	}
+	LoadState();
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Box(const char *col, bool ticks)
+{
+	mglPoint o = Org;
+	mreal tl=TickLen;
+	if(!ticks)	TickLen=0;
+	set(MGL_NOSUBTICKS);	Org = Min;
+	static int cgid=1;	StartGroup("Box",cgid++);
+	Axis("xyz_",col);
+	if(TernAxis&1)
+	{
+		Org.x=Max.x;	Org.y=Min.y;	Org.z=Max.z;
+		DrawAxis(ax, false, 0,col);	DrawAxis(az, false, 0,col);
+		Org.x=Min.x;	Org.y=Max.y;	Org.z=Max.z;
+		DrawAxis(az, false, 0,col);
+
+		mglAxis ty(ay);				ty.ch='T';
+		ty.dir.Set(-1,1);	ty.org.Set(1,0,Max.z);
+		DrawAxis(ty, false, 0,col);	ty.ch='t';
+		ty.dir.Set(0,-1);	ty.org.Set(0,1,Max.z);
+		DrawAxis(ty, false, 0,col);
+	}
+	else if(TernAxis&2)
+	{
+		mglAxis ty(az);
+		ty.ch='T';	ty.a.Set(1,0);	ty.b.Set(-1,1);
+		ty.dir.Set(-1,0,1);	ty.org.Set(1,0,0);
+		DrawAxis(ty, false, 0,col);
+		ty.ch='t';	ty.a.Set(0,1);	ty.b.Set(-1,1);
+		ty.dir.Set(0,-1,1);	ty.org.Set(0,1,0);
+		DrawAxis(ty, false, 0,col);
+	}
+	else
+	{
+		Org.z=Max.z;	Axis("xy_",col);
+		Org = Max;		Axis("xyz_",col);
+		Org.z=Min.z;	Axis("xy_",col);
+		Org.x=Min.x;	DrawAxis(az,0,0,col);
+		Org.x=Max.x;	Org.y=Min.y;	DrawAxis(az,0,0,col);
+		if(mglchr(col,'@'))
+		{
+			// edge points
+			mglPoint p[8]={Min,Min,Min,Min,Max,Max,Max,Max},nan(NAN),oo[8];
+			p[1].x=Max.x;	p[2].y=Max.y;	p[3].z=Max.z;
+			p[4].x=Min.x;	p[5].y=Min.y;	p[6].z=Min.z;
+			mreal zm=INFINITY;	int im=0;
+			memcpy(oo,p,8*sizeof(mglPoint));
+			for(int i=0;i<8;i++)	// find deepest point
+			{
+				ScalePoint(&B,p[i],nan,false);
+				if(p[i].z<zm)	{	zm=p[i].z;	im=i;	}
+			}
+			// now draw faces
+			char color[10]="{y9}";
+			for(int i=0;col[i];i++)
+			{
+				if(col[i]=='{' && col[i+1]=='x')
+				{	memcpy(color,col+i,9);	color[9]=0;	break;	}
+				if(strchr(MGL_COLORS,col[i]))
+				{
+					if(i>1 && col[i-1]=='{')	{	color[1]=col[i];	color[2]=col[i+1];	break;	}
+					else	{	color[0]=col[i];	color[1]=0;	break;	}
+				}
+			}
+			long *pos = new long[3*31*31];
+			SetPenPal(color);
+			mreal dx = (Max.x-Min.x)/30, dy = (Max.y-Min.y)/30, dz = (Max.z-Min.z)/30;
+			for(long i=0;i<31;i++)	for(long j=0;j<31;j++)
+			{
+				long i0=3*(i+31*j);
+				pos[i0]   = AddPnt(mglPoint(oo[im].x,Min.y+dy*i,Min.z+dz*j));
+				pos[i0+1] = AddPnt(mglPoint(Min.x+dx*i,oo[im].y,Min.z+dz*j));
+				pos[i0+2] = AddPnt(mglPoint(Min.x+dx*i,Min.y+dy*j,oo[im].z));
+			}
+			for(long i=0;i<30;i++)	for(long j=0;j<30;j++)
+			{
+				long i0=3*(i+31*j);
+				quad_plot(pos[i0],pos[i0+3],pos[i0+93],pos[i0+96]);
+				quad_plot(pos[i0+1],pos[i0+4],pos[i0+94],pos[i0+97]);
+				quad_plot(pos[i0+2],pos[i0+5],pos[i0+95],pos[i0+98]);
+			}
+			delete []pos;
+// 			mgl_facex(this, oo[im].x, Min.y, Min.z, Max.y-Min.y, Max.z-Min.z, color,0,0);
+// 			mgl_facey(this, Min.x, oo[im].y, Min.z, Max.x-Min.x, Max.z-Min.z, color,0,0);
+// 			mgl_facez(this, Min.x, Min.y, oo[im].z, Max.x-Min.x, Max.y-Min.y, color,0,0);
+		}
+	}
+	EndGroup();
+	clr(MGL_NOSUBTICKS);	Org=o;	TickLen=tl;
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Colorbar(const char *sch)
+{
+	bool in = mglchr(sch,'I');
+	mreal sx = (fabs(B.b[0])+fabs(B.b[1])+fabs(B.b[2]))/B.pf/B1.b[0], x=1;
+	mreal sy = (fabs(B.b[3])+fabs(B.b[4])+fabs(B.b[5]))/B.pf/B1.b[4], y=0;
+	if(mglchr(sch,'>'))	{	x=in?(1+sx)/2:1;	y=0;	}
+	if(mglchr(sch,'<'))	{	x=in?(1-sx)/2:0;	y=0;	}
+	if(mglchr(sch,'^'))	{	x=0;	y=in?(1+sy)/2:1;	}
+	if(mglchr(sch,'_'))	{	x=0;	y=in?(1-sy)/2:0;	}
+	Colorbar(sch, x, y, 1, 1);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Colorbar(const char *sch, mreal x, mreal y, mreal w, mreal h)
+{
+	bool in = mglchr(sch,'I');
+	bool text = !mglchr(sch,'~');
+	int where = 0;		// ‘0’ - right, ‘1’ - left, ‘2’ - above, ‘3’ - under
+	if(mglchr(sch,'>'))	where = in?1:0;
+	if(mglchr(sch,'<'))	where = in?0:1;
+	if(mglchr(sch,'^'))	where = in?3:2;
+	if(mglchr(sch,'_'))	where = in?2:3;
+	if(mglchr(sch,'A'))	{	Push();	Identity();	}
+
+	ac.stl.clear();
+	for(const char *s="+E0123456789-fF!";*s;s++)	if(mglchr(sch,*s))	ac.stl += *s;
+	AdjustTicks("c",mglchr(sch,'a'),ac.stl.c_str());
+
+	long n=256, s = AddTexture(sch);
+	mglData v(n);
+	if(ac.d || Min.c*Max.c<=0)	v.Fill(Min.c,Max.c);
+	else if(Max.c>Min.c && Min.c>0)
+	{	v.Fill(log(Min.c), log(Max.c));		v.Modify("exp(u)");		}
+	else if(Min.c<Max.c && Max.c<0)
+	{	v.Fill(log(-Min.c), log(-Max.c));	v.Modify("-exp(u)");	}
+	mreal *c=new mreal[n];
+	for(long i=0;i<n;i++)	c[i] = GetC(s,v.a[i]);
+	colorbar(&v, c, where, x, y, w, h, text);
+	delete []c;
+	if(mglchr(sch,'A'))	Pop();
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Colorbar(HCDT v, const char *sch)
+{
+	bool in = mglchr(sch,'I');
+	mreal sx = (fabs(B.b[0])+fabs(B.b[1])+fabs(B.b[2]))/B.pf/B1.b[0], x=1;
+	mreal sy = (fabs(B.b[3])+fabs(B.b[4])+fabs(B.b[5]))/B.pf/B1.b[4], y=0;
+	if(mglchr(sch,'>'))	{	x=in?(1+sx)/2:1;	y=0;	}
+	if(mglchr(sch,'<'))	{	x=in?(1-sx)/2:0;	y=0;	}
+	if(mglchr(sch,'^'))	{	x=0;	y=in?(1+sy)/2:1;	}
+	if(mglchr(sch,'_'))	{	x=0;	y=in?(1-sy)/2:0;	}
+	Colorbar(v, sch, x, y, 1, 1);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Colorbar(HCDT v, const char *sch, mreal x, mreal y, mreal w, mreal h)
+{
+	bool in = mglchr(sch,'I');
+	bool text = !mglchr(sch,'~');
+	int where = 0;
+	if(mglchr(sch,'>'))	where = in?1:0;
+	if(mglchr(sch,'<'))	where = in?0:1;
+	if(mglchr(sch,'^'))	where = in?3:2;
+	if(mglchr(sch,'_'))	where = in?2:3;
+	if(mglchr(sch,'A'))	{	Push();	Identity();	}
+
+	ac.stl.clear();
+	for(const char *s="+E0123456789-fF!";*s;s++)	if(mglchr(sch,*s))	ac.stl += *s;
+	AdjustTicks("c",mglchr(sch,'a'),ac.stl.c_str());
+
+	mreal *c=new mreal[v->GetNx()];
+	if(!mgl_have_color(sch))	sch = MGL_DEF_PAL;
+	long s = AddTexture(sch);
+	int nc = GetNumPal(s*256);
+	mreal dc = nc>1 ? 1/(MGL_EPSILON*(nc-1)):0;
+	for(long i=0;i<v->GetNx();i++)	c[i] = s+i*dc;
+	colorbar(v, c, where, x, y, w, h, text);
+	delete []c;
+	if(mglchr(sch,'A'))	Pop();
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::colorbar(HCDT vv, const mreal *c, int where, mreal x, mreal y, mreal w, mreal h, bool text)
+{
+	static int cgid=1;	StartGroup("Colorbar",cgid++);
+	long n=vv->GetNx();
+	mreal s3=B.pf,ss=1/s3;		// NOTE: colorbar was wider ss=0.9;
+	mglPoint p1,p2;
+	mglMatrix M=B1;	M.pf=s3;	M.norot=true;
+
+	set(MGL_DISABLE_SCALE);		// NOTE this make colorbar non-thread-safe!!!
+	x = s3*(2*x-1);	y = s3*(2*y-1);	w *= s3;	h *= s3;
+	mask = MGL_SOLID_MASK;
+	for(long i=0;i<n-1;i++)
+	{
+		mreal d = GetA(vv->v(i))*2-1;
+		p1 = p2 = mglPoint((ss*d+1)*w+x, (ss*d+1)*h+y, s3);
+		switch(where)
+		{
+			case 1:	p1.x = x;	p2.x = x+0.1*w;	break;
+			case 2:	p1.y = y-0.1*h;	p2.y = y;	break;
+			case 3:	p1.y = y;	p2.y = y+0.1*h;	break;
+			default:p1.x = x-0.1*w;	p2.x = x;	break;
+		}
+		long n1 = AddPnt(&M, p1,c[i]), n2 = AddPnt(&M, p2,c[i]);
+		d = GetA(vv->v(i+1))*2-1;
+		p1 = p2 = mglPoint((ss*d+1)*w+x, (ss*d+1)*h+y, s3);
+		switch(where)
+		{
+			case 1:	p1.x = x;	p2.x = x+0.1*w;	break;
+			case 2:	p1.y = y-0.1*h;	p2.y = y;	break;
+			case 3:	p1.y = y;	p2.y = y+0.1*h;	break;
+			default:p1.x = x-0.1*w;	p2.x = x;	break;
+		}
+		quad_plot(n1,n2, AddPnt(&M, p1,c[i]), AddPnt(&M, p2,c[i]));
+	}
+	if(n<64)
+	{
+		ac.txt.clear();
+		if(ac.t.empty())
+			for(long i=0;i<n;i++)
+			{
+				mreal d = vv->v(i);
+				ac.AddLabel(mgl_ftoa(d,ac.stl.c_str()),d);
+			}
+		else
+		{
+			wchar_t buf[64];
+			for(long i=0;i<n;i++)
+			{
+				mreal d = vv->v(i);
+				mglprintf(buf,64,ac.t.c_str(),d);
+				ac.AddLabel(buf,d);
+			}
+		}
+	}
+	else	{	UpdateAxis();	AdjustTicks(ac,fa!=0);	}
+	// hint for using standard label drawing function
+	SetPenPal(TickStl);
+	for(size_t i=0;i<ac.txt.size();i++)
+	{
+		mreal d = fa?fa->Calc(0,0,0,ac.txt[i].val):ac.txt[i].val;
+		ac.txt[i].val = d = 2*(d-FMin.c)/(FMax.c-FMin.c)-1;
+		if(fabs(d)>1)	continue;	// this is factor
+//		mreal d = ac.txt[i].val = GetA(ac.txt[i].val)*2-1;
+		p1 = p2 = mglPoint((ss*d+1)*w+x, (ss*d+1)*h+y, s3);
+		switch(where)
+		{
+			case 1:	p1.x = x;	p2.x = x+0.1*w;	break;
+			case 2:	p1.y = y-0.1*h;	p2.y = y;	break;
+			case 3:	p1.y = y;	p2.y = y+0.1*h;	break;
+			default:p1.x = x-0.1*w;	p2.x = x;	break;
+		}
+		line_plot(AddPnt(&M, p1), AddPnt(&M, p2));
+	}
+	ac.dir.Set(ss*w,ss*h,0);	ac.a.Set(0,0,0);
+	ac.org.Set(w+x,h+y,s3+1);	ac.b.Set(0,0,0);
+	switch(where)
+	{
+		case 1:	ac.dir.x = 0;	ac.a.x= 1;	ac.org.x = x+0.1*w-(get(MGL_ENABLE_RTEXT)?0:0.06);	break;
+		case 2:	ac.dir.y = 0;	ac.a.y=-1;	ac.org.y = y-0.1*h;	break;
+		case 3:	ac.dir.y = 0;	ac.a.y= 1;	ac.org.y = y+0.1*h;	break;
+		default:ac.dir.x = 0;	ac.a.x=-1;	ac.org.x = x-0.1*w;	break;
+	}
+	SetPenPal(AxisStl);
+	bool inv = where!=3 && where!=0;
+	ac.ns = where;	ac.angl=NAN;	// NOTE ns isn't used for colorbar
+	if(text)	DrawLabels(ac,inv,&M);
+	clr(MGL_DISABLE_SCALE);	EndGroup();
+}
+//-----------------------------------------------------------------------------
diff --git a/src/base.cpp b/src/base.cpp
new file mode 100644
index 0000000..8170fe3
--- /dev/null
+++ b/src/base.cpp
@@ -0,0 +1,1598 @@
+/***************************************************************************
+ * base.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include "mgl2/font.h"
+#include "mgl2/base.h"
+#include "mgl2/eval.h"
+#if MGL_HAVE_OMP
+#include <omp.h>
+#endif
+
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_mutex_unlock(void *mutex)
+{
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_unlock((pthread_mutex_t *)mutex);
+#elif MGL_HAVE_OMP
+	omp_unset_lock((omp_lock_t *)mutex);
+#endif
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_mutex_lock(void *mutex)
+{
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_lock((pthread_mutex_t *)mutex);
+#elif MGL_HAVE_OMP
+	omp_set_lock((omp_lock_t *)mutex);
+#endif
+}
+//-----------------------------------------------------------------------------
+char *mgl_strdup(const char *s)
+{
+	char *r = (char *)malloc((strlen(s)+1)*sizeof(char));
+	if(r)	memcpy(r,s,(strlen(s)+1)*sizeof(char));
+	return r;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_create_cpp_font(HMGL gr, const wchar_t *how)
+{
+	unsigned long l=mgl_wcslen(how), i, n=0, m;
+	wchar_t ch=*how;
+	const mglFont *f = gr->GetFont();
+	std::vector<wchar_t> s;	s.push_back(ch);
+	for(i=1;i<l;i++)
+		if(how[i]==',')	continue;
+		else if(how[i]=='-' && i+1<l)
+			for(ch++;ch<how[i+1];ch++)	s.push_back(ch);
+		else	s.push_back(ch=how[i]);
+	for(i=l=n=0;i<s.size();i++)
+	{
+		ch = f->Internal(s[i]);
+		if(ch>=0)	{	l += 2*f->GetNl(0,ch);	n += 6*f->GetNt(0,ch);	}
+	}
+	printf("const unsigned long mgl_numg=%lu, mgl_cur=%lu;\n",(unsigned long)s.size(),l+n);
+	printf("const float mgl_fact=%g;\n",f->GetFact(0)/mgl_fgen);
+	printf("long mgl_gen_fnt[%lu][6] = {\n", (unsigned long)s.size());
+	for(i=m=0;i<s.size();i++)	// first write symbols descriptions
+	{
+		ch = f->Internal(s[i]);
+		if(ch<0)	continue;
+		int m1 = f->GetNl(0,ch), m2 = f->GetNt(0,ch);
+		printf("\t{0x%x,%d,%d,%lu,%d,%lu},\n",unsigned(s[i]),f->GetWidth(0,ch),m1,m,m2,m+2*m1);
+		m += 2*m1+6*m2;
+	}
+	if(m!=l+n)	printf("#error \"%lu !=%lu + %lu\"",m,l,n);
+	printf("};\nshort mgl_buf_fnt[%lu] = {\n",m);
+	for(i=0;i<s.size();i++)		// now write data itself
+	{
+		ch = f->Internal(s[i]);
+		if(ch<0)	continue;
+		unsigned m1 = f->GetNl(0,ch), m2 = f->GetNt(0,ch);
+		const short *ln = f->GetLn(0,ch), *tr = f->GetTr(0,ch);
+		for(l=0;l<2*m1;l++)	printf("%d,",ln[l]);
+		printf("\n");
+		for(l=0;l<6*m2;l++)	printf("%d,",tr[l]);
+		printf("\n");
+	}
+	printf("};\n");
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_strtrim(char *str)
+{
+	if(!str || *str==0)	return;
+	size_t n=strlen(str), k, i;
+	for(k=0;k<n;k++)	if(str[k]>' ')	break;
+	for(i=n;i>k;i--)	if(str[i-1]>' ')	break;
+	memmove(str, str+k, (i-k));
+	str[i-k]=0;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_strlwr(char *str)
+{
+	size_t l=strlen(str);
+	for(size_t k=0;k<l;k++)
+		str[k] = (str[k]>='A' && str[k]<='Z') ? str[k]+'a'-'A' : str[k];
+}
+//-----------------------------------------------------------------------------
+mglBase::mglBase()
+{
+	Flag=0;	saved=false;	PrmInd=NULL;
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_init(&mutexPnt,0);
+	pthread_mutex_init(&mutexTxt,0);
+	pthread_mutex_init(&mutexSub,0);
+	pthread_mutex_init(&mutexLeg,0);
+	pthread_mutex_init(&mutexPrm,0);
+	pthread_mutex_init(&mutexPtx,0);
+	pthread_mutex_init(&mutexStk,0);
+	pthread_mutex_init(&mutexGrp,0);
+	pthread_mutex_init(&mutexGlf,0);
+	pthread_mutex_init(&mutexAct,0);
+	pthread_mutex_init(&mutexDrw,0);
+	pthread_mutex_init(&mutexClf,0);
+	Pnt.set_mutex(&mutexClf);
+	Prm.set_mutex(&mutexClf);
+//	Txt.set_mutex(&mutexClf);
+#endif
+#if MGL_HAVE_OMP
+	lockClf = new omp_lock_t;
+	omp_init_lock((omp_lock_t*)lockClf);
+	Pnt.set_mutex(lockClf);
+	Prm.set_mutex(lockClf);
+//	Txt.set_mutex(&lockClf);
+#else
+	lockClf = NULL;
+#endif
+	fnt=0;	*FontDef=0;	fx=fy=fz=fa=fc=0;
+	AMin.Set(0,0,0,0);	AMax.Set(1,1,1,1);
+
+	InUse = 1;	SetQuality();	FaceNum = 0;
+	// Always create default palette txt[0] and default scheme txt[1]
+	mglTexture t1(MGL_DEF_PAL,-1), t2(MGL_DEF_SCH,1);
+	Txt.reserve(3);
+	MGL_PUSH(Txt,t1,mutexTxt);
+	MGL_PUSH(Txt,t2,mutexTxt);
+
+	strcpy(last_style,"__1 {dFFFF}k\0");
+	MinS.Set(-1,-1,-1);	MaxS.Set(1,1,1);
+	fnt = new mglFont;	fnt->gr = this;	PrevState=size_opt=NAN;
+}
+//-----------------------------------------------------------------------------
+mglBase::~mglBase()
+{
+	ClearEq();	ClearPrmInd();	delete fnt;
+	Pnt.set_mutex(0);	Prm.set_mutex(0);	//Txt.set_mutex(0);
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_destroy(&mutexPnt);
+	pthread_mutex_destroy(&mutexTxt);
+	pthread_mutex_destroy(&mutexSub);
+	pthread_mutex_destroy(&mutexLeg);
+	pthread_mutex_destroy(&mutexPrm);
+	pthread_mutex_destroy(&mutexPtx);
+	pthread_mutex_destroy(&mutexStk);
+	pthread_mutex_destroy(&mutexGrp);
+	pthread_mutex_destroy(&mutexGlf);
+	pthread_mutex_destroy(&mutexAct);
+	pthread_mutex_destroy(&mutexDrw);
+	pthread_mutex_destroy(&mutexClf);
+#endif
+#if MGL_HAVE_OMP
+	omp_destroy_lock((omp_lock_t*)lockClf);
+	delete ((omp_lock_t*)lockClf);
+#endif
+}
+//-----------------------------------------------------------------------------
+void mglBase::RestoreFont()	{	fnt->Restore();	}
+void mglBase::LoadFont(const char *name, const char *path)
+{	if(name && *name)	fnt->Load(name,path);	else	fnt->Restore();	}
+void mglBase::CopyFont(mglBase *gr)	{	fnt->Copy(gr->GetFont());	}
+//-----------------------------------------------------------------------------
+mreal mglBase::TextWidth(const char *text, const char *font, mreal size) const
+{	return (size<0?-size*FontSize:size)*font_factor*fnt->Width(text,(font&&*font)?font:FontDef)/20.16;	}
+mreal mglBase::TextWidth(const wchar_t *text, const char *font, mreal size) const
+{	return (size<0?-size*FontSize:size)*font_factor*fnt->Width(text,(font&&*font)?font:FontDef)/20.16;	}
+mreal mglBase::TextHeight(const char *font, mreal size) const
+{	return (size<0?-size*FontSize:size)*font_factor*fnt->Height(font?font:FontDef)/20.16; }
+void mglBase::AddActive(long k,int n)
+{
+	if(k<0 || (size_t)k>=Pnt.size())	return;
+	mglActivePos p;
+	const mglPnt &q=Pnt[k];
+	int h=GetHeight();
+	p.x = int(q.x);	p.y = h>1?h-1-int(q.y):int(q.y);
+	p.id = ObjId;	p.n = n;
+#pragma omp critical(act)
+	MGL_PUSH(Act,p,mutexAct);
+}
+//-----------------------------------------------------------------------------
+mreal mglBase::GetRatio() const	{	return 1;	}
+int mglBase::GetWidth()  const	{	return 1;	}
+int mglBase::GetHeight() const	{	return 1;	}
+//-----------------------------------------------------------------------------
+void mglBase::StartGroup(const char *name, int id)
+{
+	LightScale(&B);
+	char buf[128];
+	snprintf(buf,128,"%s_%d",name,id);	buf[127]=0;
+	StartAutoGroup(buf);
+}
+//-----------------------------------------------------------------------------
+const char *mglWarn[mglWarnEnd] = {_("data dimension(s) is incompatible"),	//mglWarnDim
+								_("data dimension(s) is too small"),		//mglWarnLow
+								_("minimal data value is negative"),		//mglWarnNeg
+								_("no file or wrong data dimensions"),		//mglWarnFile
+								_("not enough memory"), 					//mglWarnMem
+								_("data values are zero"),					//mglWarnZero
+								_("no legend entries"),					//mglWarnLeg
+								_("slice value is out of range"),			//mglWarnSlc
+								_("number of contours is zero or negative"),//mglWarnCnt
+								_("couldn't open file"),					//mglWarnOpen
+								_("light: ID is out of range"),			//mglWarnLId
+								_("size(s) is zero or negative"),			//mglWarnSize
+								_("format is not supported for that build"),//mglWarnFmt
+								_("axis ranges are incompatible"),			//mglWarnTern
+								_("pointer is NULL"),						//mglWarnNull
+								_("not enough space for plot"),			//mglWarnSpc
+								_("There is wrong argument(s) in script"),	//mglScrArg
+								_("There is wrong command(s) in script"),	//mglScrCmd
+								_("There is too long string(s) in script"),	//mglScrLong
+								_("There is unbalanced ' in script"),		//mglScrStr
+								_("There is changing temporary data in script")};	//mglScrTemp
+//-----------------------------------------------------------------------------
+extern bool mglPrintWarn;
+void mglBase::SetWarn(int code, const char *who)
+{
+	std::string warn;
+	WarnCode = code>0 ? code:0;
+	if(code>0 && code<mglWarnEnd)
+	{
+		if(who && *who)	warn = std::string(who)+": ";
+		warn = warn+mglWarn[code-1];
+	}
+	else if(!code)	Mess="";
+	else if(who && *who)	warn = who;
+	if(mglPrintWarn && !warn.empty())	fprintf(stderr,_("MathGL message - %s\n"),warn.c_str());
+	if(code && !warn.empty())	Mess = Mess+(code==-2?"":"\n")+warn;
+	LoadState();
+}
+//-----------------------------------------------------------------------------
+//		Add glyph to the buffer
+//-----------------------------------------------------------------------------
+void mglGlyph::Create(long Nt, long Nl)
+{
+//	if(Nt<0 || Nl<0)	return;
+	nt=Nt;	nl=Nl;
+#pragma omp critical(glf_create)
+	{
+		if(trig)	delete []trig;
+		trig = nt>0?new short[6*nt]:0;
+		if(line)	delete []line;
+		line = nl>0?new short[2*nl]:0;
+	}
+}
+//-----------------------------------------------------------------------------
+bool mglGlyph::operator==(const mglGlyph &g) const
+{
+	if(nl!=g.nl || nt!=g.nt)	return false;
+	if(trig && memcmp(trig,g.trig,6*nt*sizeof(short)))	return false;
+	if(line && memcmp(line,g.line,2*nl*sizeof(short)))	return false;
+	return true;
+}
+//-----------------------------------------------------------------------------
+long mglBase::AddGlyph(int s, long j)
+{
+	// first create glyph for current typeface
+	s = s&3;
+	mglGlyph g(fnt->GetNt(s,j), fnt->GetNl(s,j));
+	memcpy(g.trig, fnt->GetTr(s,j), 6*g.nt*sizeof(short));
+	memcpy(g.line, fnt->GetLn(s,j), 2*g.nl*sizeof(short));
+	// now let find the similar glyph
+	for(size_t i=0;i<Glf.size();i++)
+		if(g!=Glf[i])	continue;	else	return i;
+	// if no one then let add it
+	long k;
+#pragma omp critical(glf)
+	{k=Glf.size();	MGL_PUSH(Glf,g,mutexGlf);}	return k;
+}
+//-----------------------------------------------------------------------------
+long mglBase::AddGlyph(unsigned char id)
+{
+	size_t j=0;
+	for(size_t i=0;i<UserGlf.size();i++)
+		if(UserGlf[i].nt==-id)	j=i+1;
+	if(j==0)	return -1;
+	const mglGlyph &g=UserGlf[j-1];
+	// let find the similar glyph
+	for(size_t i=0;i<Glf.size();i++)
+		if(g!=Glf[i])	continue;	else	return i;
+	// if no one then let add it
+	long k;
+#pragma omp critical(glf)
+	{k=Glf.size();	MGL_PUSH(Glf,g,mutexGlf);}	return k;
+}
+//-----------------------------------------------------------------------------
+void mglBase::DefineGlyph(HCDT x, HCDT y, unsigned char id)
+{
+	long n = x->GetNx();
+	if(y->GetNx()!=n || n<2)	return;
+	mglGlyph g(-id,n);
+	mreal x1=1e10,x2=-1e10,y1=1e10,y2=-1e10;
+	for(long i=0;i<n;i++)
+	{
+		mreal xx = x->v(i), yy = y->v(i);
+		x1=x1>xx?xx:x1;	x2=x2<xx?xx:x2;
+		y1=y1>yy?yy:y1;	y2=y2<yy?yy:y2;
+	}
+	mreal scale = 1;
+	if(fabs(x1)<10 && fabs(x2)<10 && fabs(y1)<10 && fabs(y2)<10)
+		scale=1000;
+	for(long i=0;i<n;i++)
+	{
+		short sx = short(x->v(i)*scale), sy = short(y->v(i)*scale);
+		g.line[2*i] = sx;	g.line[2*i+1] = sy;
+	}
+	UserGlf.push_back(g);
+}
+//-----------------------------------------------------------------------------
+//		Add points to the buffer
+//-----------------------------------------------------------------------------
+void inline mgl_put_inbox(mreal a1, mreal a2, mreal &a)
+{
+	if(a1<a2)	{	if(a<a1)	a=a1;	if(a>a2)	a=a2;	}
+	else		{	if(a<a2)	a=a2;	if(a>a1)	a=a1;	}
+}
+void MGL_NO_EXPORT mgl_coor_box(HMGL gr, mglPoint &p)
+{
+	mgl_put_inbox(gr->Min.x, gr->Max.x, p.x);
+	mgl_put_inbox(gr->Min.y, gr->Max.y, p.y);
+	mgl_put_inbox(gr->Min.z, gr->Max.z, p.z);
+}
+long mglBase::AddPnt(const mglMatrix *mat, mglPoint p, mreal c, mglPoint n, mreal a, int scl)
+{
+	// scl=0 -- no scaling
+	// scl&1 -- usual scaling
+	// scl&2 -- disable NAN at scaling
+	// scl&4 -- disable NAN for normales if no light
+	// scl&8 -- bypass palette for enabling alpha
+	// scl&16 -- put points inside axis range
+	if(mgl_isnan(c) || mgl_isnan(a))	return -1;
+	bool norefr = mgl_isnan(n.x) && mgl_isnan(n.y) && !mgl_isnan(n.z);
+	if(scl>0)
+	{
+		if(scl&16)	mgl_coor_box(this, p);
+		ScalePoint(mat,p,n,!(scl&2));
+	}
+	if(mgl_isnan(p.x))	return -1;
+	a = (a>=0 && a<=1) ? a : AlphaDef;
+	c = (c>=0) ? c:CDef;
+
+	mglPnt q;
+	if(get(MGL_REDUCEACC))
+	{
+		q.x=q.xx=int(p.x*10)*0.1;	q.y=q.yy=int(p.y*10)*0.1;	q.z=q.zz=int(p.z*10)*0.1;
+		q.c=int(c*100)*0.01;	q.t=q.ta=int(a*100)*0.01;
+		q.u=mgl_isnum(n.x)?int(n.x*100)*0.01:NAN;
+		q.v=mgl_isnum(n.y)?int(n.y*100)*0.01:NAN;
+		q.w=mgl_isnum(n.z)?int(n.z*100)*0.01:NAN;
+	}
+	else
+	{
+		q.x=q.xx=p.x;	q.y=q.yy=p.y;	q.z=q.zz=p.z;
+		q.c=c;	q.t=q.ta=a;	q.u=n.x;	q.v=n.y;	q.w=n.z;
+	}
+	long ci=long(c);
+	if(ci<0 || ci>=(long)Txt.size())	ci=0;	// NOTE never should be here!!!
+	const mglTexture &txt=Txt[ci];
+	txt.GetC(c,a,q);	// RGBA color
+	if(get(MGL_GRAY_MODE))
+	{
+		float h = 0.3*q.r + 0.59*q.g + 0.11*q.b;
+		q.r = q.g = q.b = h;
+	}
+
+	// add gap for texture coordinates for compatibility with OpenGL
+	const mreal gap = 0./MGL_TEXTURE_COLOURS;
+	q.c = ci+(q.c-ci)*(1-2*gap)+gap;
+	q.t = q.t*(1-2*gap)+gap;
+	q.ta = q.t;
+
+	if(scl&8 && scl>0)	q.a=a;	// bypass palette for enabling alpha in Error()
+	if(!get(MGL_ENABLE_ALPHA))	{	q.a=1;	if(txt.Smooth!=2)	q.ta=1-gap;	}
+	if(norefr)	q.v=0;
+	if(!get(MGL_ENABLE_LIGHT) && !(scl&4))	q.u=q.v=NAN;
+	q.sub=mat->norot?-1*(short)Sub.size():Sub.size()-1;
+	long k;
+#pragma omp critical(pnt)
+	{k=Pnt.size();	MGL_PUSH(Pnt,q,mutexPnt);}	return k;
+}
+//-----------------------------------------------------------------------------
+long mglBase::CopyNtoC(long from, mreal c)
+{
+	if(from<0)	return -1;
+	mglPnt p=Pnt[from];
+	if(mgl_isnum(c))	{	p.c=c;	p.t=1;	Txt[long(c)].GetC(c,0,p);	p.a=1;	}
+	long k;
+#pragma omp critical(pnt)
+	{k=Pnt.size();	MGL_PUSH(Pnt,p,mutexPnt);}	return k;
+}
+//-----------------------------------------------------------------------------
+long mglBase::CopyProj(long from, mglPoint p, mglPoint n, short sub)
+{
+	if(from<0)	return -1;
+	mglPnt q=Pnt[from];	q.sub = sub;
+	q.x=q.xx=p.x;	q.y=q.yy=p.y;	q.z=q.zz=p.z;
+	q.u = n.x;		q.v = n.y;		q.w = n.z;
+	long k;
+#pragma omp critical(pnt)
+	{k=Pnt.size();	MGL_PUSH(Pnt,q,mutexPnt);}	return k;
+}
+//-----------------------------------------------------------------------------
+void mglBase::Reserve(long n)
+{
+	if(TernAxis&12)	n*=4;
+#pragma omp critical(pnt)
+	Pnt.reserve(n);
+#pragma omp critical(prm)
+	Prm.reserve(n);
+}
+//-----------------------------------------------------------------------------
+//		Boundaries and scaling
+//-----------------------------------------------------------------------------
+bool mglBase::RecalcCRange()
+{
+	bool wrong=false;
+	if(!fa)
+	{	FMin.c = Min.c;	FMax.c = Max.c;	}
+	else
+	{
+		FMin.c = INFINITY;	FMax.c = -INFINITY;
+		int n=30;
+		for(int i=0;i<=n;i++)
+		{
+			mreal a = fa->Calc(0,0,0,Min.c+i*(Max.c-Min.c)/n);
+			if(mgl_isbad(a))	wrong=true;
+			if(a<FMin.c)	FMin.c=a;
+			if(a>FMax.c)	FMax.c=a;
+		}
+	}
+	return wrong;
+}
+//-----------------------------------------------------------------------------
+void mglBase::RecalcBorder()
+{
+	ZMin = 1.;
+	bool wrong=false;
+	if(!fx && !fy && !fz)
+	{	FMin = Min;	FMax = Max;	}
+	else
+	{
+		FMin.Set( INFINITY, INFINITY, INFINITY);
+		FMax.Set(-INFINITY,-INFINITY,-INFINITY);
+		int n=30;
+		for(int i=0;i<=n;i++)	for(int j=0;j<=n;j++)	// x range
+		{
+			if(SetFBord(Min.x, Min.y+i*(Max.y-Min.y)/n, Min.z+j*(Max.z-Min.z)/n))	wrong=true;
+			if(SetFBord(Max.x, Min.y+i*(Max.y-Min.y)/n, Min.z+j*(Max.z-Min.z)/n))	wrong=true;
+		}
+		for(int i=0;i<=n;i++)	for(int j=0;j<=n;j++)	// y range
+		{
+			if(SetFBord(Min.x+i*(Max.x-Min.x)/n, Min.y, Min.z+j*(Max.z-Min.z)/n))	wrong=true;
+			if(SetFBord(Min.x+i*(Max.x-Min.x)/n, Max.y, Min.z+j*(Max.z-Min.z)/n))	wrong=true;
+		}
+		for(int i=0;i<=n;i++)	for(int j=0;j<=n;j++)	// x range
+		{
+			if(SetFBord(Min.x+i*(Max.x-Min.x)/n, Min.y+j*(Max.y-Min.y)/n, Min.z))	wrong=true;
+			if(SetFBord(Min.x+i*(Max.x-Min.x)/n, Min.y+j*(Max.y-Min.y)/n, Max.z))	wrong=true;
+		}
+		if(!fx)	{	FMin.x = Min.x;	FMax.x = Max.x;	}
+		else	{	mreal d=0.01*(FMax.x-FMin.x);	FMin.x-=d;	FMax.x+=d;	}
+		if(!fy)	{	FMin.y = Min.y;	FMax.y = Max.y;	}
+		else	{	mreal d=0.01*(FMax.y-FMin.y);	FMin.y-=d;	FMax.y+=d;	}
+		if(!fz)	{	FMin.z = Min.z;	FMax.z = Max.z;	}
+		else	{	mreal d=0.01*(FMax.z-FMin.z);	FMin.z-=d;	FMax.z+=d;	}
+	}
+	if(RecalcCRange())	wrong=true;
+	if(wrong)	SetWarn(mglWarnTern, "Curved coordinates");
+}
+//-----------------------------------------------------------------------------
+bool mglBase::SetFBord(mreal x,mreal y,mreal z)
+{
+	bool wrong=false;
+	if(fx)
+	{
+		mreal v = fx->Calc(x,y,z);
+		if(mgl_isbad(v))	wrong = true;
+		if(FMax.x < v)	FMax.x = v;
+		if(FMin.x > v)	FMin.x = v;
+	}
+	if(fy)
+	{
+		mreal v = fy->Calc(x,y,z);
+		if(mgl_isbad(v))	wrong = true;
+		if(FMax.y < v)	FMax.y = v;
+		if(FMin.y > v)	FMin.y = v;
+	}
+	if(fz)
+	{
+		mreal v = fz->Calc(x,y,z);
+		if(mgl_isbad(v))	wrong = true;
+		if(FMax.z < v)	FMax.z = v;
+		if(FMin.z > v)	FMin.z = v;
+	}
+	return wrong;
+}
+//-----------------------------------------------------------------------------
+bool mglBase::ScalePoint(const mglMatrix *, mglPoint &p, mglPoint &n, bool use_nan) const
+{
+	mreal &x=p.x, &y=p.y, &z=p.z;
+	if(mgl_isnan(x) || mgl_isnan(y) || mgl_isnan(z))	{	x=NAN;	return false;	}
+	mreal x1,y1,z1,x2,y2,z2;
+	x1 = x>0?x*MGL_EPSILON:x/MGL_EPSILON;	x2 = x<0?x*MGL_EPSILON:x/MGL_EPSILON;
+	y1 = y>0?y*MGL_EPSILON:y/MGL_EPSILON;	y2 = y<0?y*MGL_EPSILON:y/MGL_EPSILON;
+	z1 = z>0?z*MGL_EPSILON:z/MGL_EPSILON;	z2 = z<0?z*MGL_EPSILON:z/MGL_EPSILON;
+	bool res = true;
+	if(x2>CutMin.x && x1<CutMax.x && y2>CutMin.y && y1<CutMax.y &&
+		z2>CutMin.z && z1<CutMax.z)	res = false;
+	if(fc && fc->Calc(x,y,z)!=0)	res = false;
+
+	if(get(MGL_ENABLE_CUT) || !use_nan)
+	{
+//		if(x1<Min.x || x2>Max.x || y1<Min.y || y2>Max.y || z1<Min.z || z2>Max.z)	res = false;
+		if((x1-Min.x)*(x1-Max.x)>0 && (x2-Min.x)*(x2-Max.x)>0)	res = false;
+		if((y1-Min.y)*(y1-Max.y)>0 && (y2-Min.y)*(y2-Max.y)>0)	res = false;
+		if((z1-Min.z)*(z1-Max.z)>0 && (z2-Min.z)*(z2-Max.z)>0)	res = false;
+	}
+	else
+	{
+		if(Min.x<Max.x)
+		{
+			if(x1<Min.x)	{x=Min.x;	n.Set(1,0,0);}
+			if(x2>Max.x)	{x=Max.x;	n.Set(1,0,0);}
+		}
+		else
+		{
+			if(x1<Max.x)	{x=Max.x;	n.Set(1,0,0);}
+			if(x2>Min.x)	{x=Min.x;	n.Set(1,0,0);}
+		}
+		if(Min.y<Max.y)
+		{
+			if(y1<Min.y)	{y=Min.y;	n.Set(0,1,0);}
+			if(y2>Max.y)	{y=Max.y;	n.Set(0,1,0);}
+		}
+		else
+		{
+			if(y1<Max.y)	{y=Max.y;	n.Set(0,1,0);}
+			if(y2>Min.y)	{y=Min.y;	n.Set(0,1,0);}
+		}
+		if(Min.z<Max.z)
+		{
+			if(z1<Min.z)	{z=Min.z;	n.Set(0,0,1);}
+			if(z2>Max.z)	{z=Max.z;	n.Set(0,0,1);}
+		}
+		else
+		{
+			if(z1<Max.z)	{z=Max.z;	n.Set(0,0,1);}
+			if(z2>Min.z)	{z=Min.z;	n.Set(0,0,1);}
+		}
+	}
+
+	x1=x;	y1=y;	z1=z;
+	mreal xx=1,xy=0,xz=0,yx=0,yy=1,yz=0,zx=0,zy=0,zz=1;
+	if(fx)	{	x1 = fx->Calc(x,y,z);	xx = fx->CalcD('x',x,y,z);	xy = fx->CalcD('y',x,y,z);	xz = fx->CalcD('z',x,y,z);	}
+	if(fy)	{	y1 = fy->Calc(x,y,z);	yx = fy->CalcD('x',x,y,z);	yy = fy->CalcD('y',x,y,z);	yz = fy->CalcD('z',x,y,z);	}
+	if(fz)	{	z1 = fz->Calc(x,y,z);	zx = fz->CalcD('x',x,y,z);	zy = fz->CalcD('y',x,y,z);	zz = fz->CalcD('z',x,y,z);	}
+	if(mgl_isnan(x1) || mgl_isnan(y1) || mgl_isnan(z1))	{	x=NAN;	return false;	}
+
+	mreal d;
+	d = 1/(FMax.x - FMin.x);	x = (2*x1 - FMin.x - FMax.x)*d;	xx /= d;	xy /= d;	xz /= d;
+	d = 1/(FMax.y - FMin.y);	y = (2*y1 - FMin.y - FMax.y)*d;	yx /= d;	yy /= d;	yz /= d;
+	d = 1/(FMax.z - FMin.z);	z = (2*z1 - FMin.z - FMax.z)*d;	zx /= d;	zy /= d;	zz /= d;
+	mreal nx=n.x, ny=n.y, nz=n.z;
+	n.x = nx*xx+ny*xy+nz*xz;
+	n.y = nx*yx+ny*yy+nz*yz;
+	n.z = nx*zx+ny*zy+nz*zz;
+	if((TernAxis&3)==1)	// usual ternary axis
+	{
+		if(x+y>0)
+		{
+			if(get(MGL_ENABLE_CUT))	res = false;
+			else	y = -x;
+		}
+		x += (y+1)/2;	n.x += n.y/2;
+	}
+	else if((TernAxis&3)==2)	// quaternary axis
+	{
+		if(x+y+z>-1)
+		{
+			if(get(MGL_ENABLE_CUT))	res = false;
+			else	z = -1-y-x;
+		}
+		x += 1+(y+z)/2;		y += (z+1)/3;
+		n.x += (n.y+n.z)/2;	n.y += n.z/3;
+	}
+	if(fabs(x)>MGL_FEPSILON || fabs(y)>MGL_FEPSILON || fabs(z)>MGL_FEPSILON)	res = false;
+
+	if(!res && use_nan)	x = NAN;	// extra sign that point shouldn't be plotted
+	return res;
+}
+//-----------------------------------------------------------------------------
+//		Ranges
+//-----------------------------------------------------------------------------
+void mglScaleAxis(mreal &v1, mreal &v2, mreal &v0, mreal x1, mreal x2)
+{
+	if(!mgl_isrange(x1,x2) || !mgl_isrange(v1,v2))	return;
+	mreal dv,d0;	x2-=1;
+	if(v1*v2>0 && (v2/v1>=100 || v2/v1<=0.01))	// log scale
+	{
+		dv=log(v2/v1);	d0 = log(v0/v1)/log(v2/v1);
+		v1*=exp(dv*x1);	v2*=exp(dv*x2);	v0=v1*exp(d0*log(v2/v1));
+	}
+	else
+	{
+		dv=v2-v1;	d0=(v0-v1)/(v2-v1);
+		v1+=dv*x1;	v2+=dv*x2;	v0=v1+d0*(v2-v1);
+	}
+}
+//-----------------------------------------------------------------------------
+void mglBase::SetOrigin(mreal x0, mreal y0, mreal z0, mreal c0)
+{
+	Org.Set(x0,y0,z0,c0);
+	if((TernAxis&3)==0)
+	{
+		Min = OMin;	Max = OMax;
+		mglScaleAxis(Min.x, Max.x, Org.x, AMin.x, AMax.x);
+		mglScaleAxis(Min.y, Max.y, Org.y, AMin.y, AMax.y);
+		mglScaleAxis(Min.z, Max.z, Org.z, AMin.z, AMax.z);
+		mglScaleAxis(Min.c, Max.c, Org.c, AMin.c, AMax.c);
+	}
+}
+//-----------------------------------------------------------------------------
+void mglBase::SetRanges(mglPoint m1, mglPoint m2)
+{
+	if(mgl_isrange(m1.x, m2.x))	{	Min.x=m1.x;	Max.x=m2.x;	}
+	if(mgl_isrange(m1.y, m2.y))	{	Min.y=m1.y;	Max.y=m2.y;	}
+	if(mgl_isrange(m1.z, m2.z))	{	Min.z=m1.z;	Max.z=m2.z;	}
+	if(mgl_isrange(m1.c, m2.c))	{	Min.c=m1.c;	Max.c=m2.c;	}
+	else	{	Min.c=Min.z;Max.c=Max.z;}
+
+	if(Org.x<Min.x && mgl_isnum(Org.x))	Org.x = Min.x;
+	if(Org.x>Max.x && mgl_isnum(Org.x))	Org.x = Max.x;
+	if(Org.y<Min.y && mgl_isnum(Org.y))	Org.y = Min.y;
+	if(Org.y>Max.y && mgl_isnum(Org.y))	Org.y = Max.y;
+	if(Org.z<Min.z && mgl_isnum(Org.z))	Org.z = Min.z;
+	if(Org.z>Max.z && mgl_isnum(Org.z))	Org.z = Max.z;
+
+	if((TernAxis&3)==0)
+	{
+		OMax = Max;	OMin = Min;
+		mglScaleAxis(Min.x, Max.x, Org.x, AMin.x, AMax.x);
+		mglScaleAxis(Min.y, Max.y, Org.y, AMin.y, AMax.y);
+		mglScaleAxis(Min.z, Max.z, Org.z, AMin.z, AMax.z);
+		mglScaleAxis(Min.c, Max.c, Org.c, AMin.c, AMax.c);
+	}
+
+	CutMin.Set(0,0,0);	CutMax.Set(0,0,0);
+	RecalcBorder();
+}
+//-----------------------------------------------------------------------------
+void mglBase::CRange(HCDT a,bool add, mreal fact)
+{
+	mreal v1=a->Minimal(), v2=a->Maximal(), dv;
+	dv=(v2-v1)*fact;	v1 -= dv;	v2 += dv;
+	CRange(v1,v2,add);
+}
+void mglBase::CRange(mreal v1,mreal v2,bool add)
+{
+	if(!mgl_isrange(v1,v2) && !add)	return;
+	if(!add)
+	{
+		if(mgl_isnum(v1))	Min.c = v1;
+		if(mgl_isnum(v2))	Max.c = v2;
+	}
+	else if(Min.c<Max.c)
+	{
+		if(Min.c>v1)	Min.c=v1;
+		if(Max.c<v2)	Max.c=v2;
+	}
+	else
+	{
+		mreal dv = Min.c;
+		Min.c = v1<Max.c ? v1:Max.c;
+		Max.c = v2>dv ? v2:dv;
+	}
+	if(Org.c<Min.c && mgl_isnum(Org.c))	Org.c = Min.c;
+	if(Org.c>Max.c && mgl_isnum(Org.c))	Org.c = Max.c;
+	if((TernAxis&3)==0)
+	{
+		OMax.c = Max.c;	OMin.c = Min.c;
+		mglScaleAxis(Min.c, Max.c, Org.c, AMin.c, AMax.c);
+	}
+	RecalcCRange();
+}
+//-----------------------------------------------------------------------------
+void mglBase::XRange(HCDT a,bool add,mreal fact)
+{
+	mreal v1=a->Minimal(), v2=a->Maximal(), dv;
+	dv=(v2-v1)*fact;	v1 -= dv;	v2 += dv;
+	XRange(v1,v2,add);
+}
+void mglBase::XRange(mreal v1,mreal v2,bool add)
+{
+	if(!mgl_isrange(v1,v2) && !add)	return;
+	if(!add)
+	{
+		if(mgl_isnum(v1))	Min.x = v1;
+		if(mgl_isnum(v2))	Max.x = v2;
+	}
+	else if(Min.x<Max.x)
+	{
+		if(Min.x>v1)	Min.x=v1;
+		if(Max.x<v2)	Max.x=v2;
+	}
+	else
+	{
+		mreal dv = Min.x;
+		Min.x = v1<Max.x ? v1:Max.x;
+		Max.x = v2>dv ? v2:dv;
+	}
+	if(Org.x<Min.x && mgl_isnum(Org.x))	Org.x = Min.x;
+	if(Org.x>Max.x && mgl_isnum(Org.x))	Org.x = Max.x;
+	if((TernAxis&3)==0)
+	{
+		OMax.x = Max.x;	OMin.x = Min.x;
+		mglScaleAxis(Min.x, Max.x, Org.x, AMin.x, AMax.x);
+	}
+	RecalcBorder();
+}
+//-----------------------------------------------------------------------------
+void mglBase::YRange(HCDT a,bool add,mreal fact)
+{
+	mreal v1=a->Minimal(), v2=a->Maximal(), dv;
+	dv=(v2-v1)*fact;	v1 -= dv;	v2 += dv;
+	YRange(v1,v2,add);
+}
+void mglBase::YRange(mreal v1,mreal v2,bool add)
+{
+	if(!mgl_isrange(v1,v2) && !add)	return;
+	if(!add)
+	{
+		if(mgl_isnum(v1))	Min.y = v1;
+		if(mgl_isnum(v2))	Max.y = v2;
+	}
+	else if(Min.y<Max.y)
+	{
+		if(Min.y>v1)	Min.y=v1;
+		if(Max.y<v2)	Max.y=v2;
+	}
+	else
+	{
+		mreal dv = Min.y;
+		Min.y = v1<Max.y ? v1:Max.y;
+		Max.y = v2>dv ? v2:dv;
+	}
+	if(Org.y<Min.y && mgl_isnum(Org.y))	Org.y = Min.y;
+	if(Org.y>Max.y && mgl_isnum(Org.y))	Org.y = Max.y;
+	if((TernAxis&3)==0)
+	{
+		OMax.y = Max.y;	OMin.y = Min.y;
+		mglScaleAxis(Min.y, Max.y, Org.y, AMin.y, AMax.y);
+
+	}
+	RecalcBorder();
+}
+//-----------------------------------------------------------------------------
+void mglBase::ZRange(HCDT a,bool add,mreal fact)
+{
+	mreal v1=a->Minimal(), v2=a->Maximal(), dv;
+	dv=(v2-v1)*fact;	v1 -= dv;	v2 += dv;
+	ZRange(v1,v2,add);
+}
+void mglBase::ZRange(mreal v1,mreal v2,bool add)
+{
+	if(!mgl_isrange(v1,v2) && !add)	return;
+	if(!add)
+	{
+		if(mgl_isnum(v1))	Min.z = v1;
+		if(mgl_isnum(v2))	Max.z = v2;
+	}
+	else if(Min.z<Max.z)
+	{
+		if(Min.z>v1)	Min.z=v1;
+		if(Max.z<v2)	Max.z=v2;
+	}
+	else
+	{
+		mreal dv = Min.z;
+		Min.z = v1<Max.z ? v1:Max.z;
+		Max.z = v2>dv ? v2:dv;
+	}
+	if(Org.z<Min.z && mgl_isnum(Org.z))	Org.z = Min.z;
+	if(Org.z>Max.z && mgl_isnum(Org.z))	Org.z = Max.z;
+	if((TernAxis&3)==0)
+	{
+		OMax.z = Max.z;	OMin.z = Min.z;
+		mglScaleAxis(Min.z, Max.z, Org.z, AMin.z, AMax.z);
+	}
+	RecalcBorder();
+}
+//-----------------------------------------------------------------------------
+void mglBase::SetAutoRanges(mreal x1, mreal x2, mreal y1, mreal y2, mreal z1, mreal z2, mreal c1, mreal c2)
+{
+	if(mgl_isrange(x1,x2))	{	Min.x = x1;	Max.x = x2;	}
+	if(mgl_isrange(y1,y2))	{	Min.y = y1;	Max.y = y2;	}
+	if(mgl_isrange(z1,z2))	{	Min.z = z1;	Max.z = z2;	}
+	if(mgl_isrange(c1,c2))	{	Min.c = c1;	Max.c = c2;	}
+}
+//-----------------------------------------------------------------------------
+void mglBase::Ternary(int t)
+{
+	static mglPoint x1(-1,-1,-1),x2(1,1,1),o(NAN,NAN,NAN);
+	static bool c = true;
+	TernAxis = t;
+	if(t&3)
+	{
+		if(c)	{	x1 = Min;	x2 = Max;	o = Org;	}
+		SetRanges(mglPoint(0,0,0),mglPoint(1,1,(t&3)==1?0:1));
+		Org.Set(0,0,(t&3)==1?NAN:0);	c = false;
+	}
+	else if(!c)	{	SetRanges(x1,x2);	Org=o;	c=true;	}
+}
+//-----------------------------------------------------------------------------
+//		Transformation functions
+//-----------------------------------------------------------------------------
+void mglBase::SetFunc(const char *EqX,const char *EqY,const char *EqZ,const char *EqA)
+{
+	if(fa)	delete fa;
+	if(fx)	delete fx;
+	if(fy)	delete fy;
+	if(fz)	delete fz;
+	if(EqX && *EqX && (EqX[0]!='x' || EqX[1]!=0))
+		fx = new mglFormula(EqX);
+	else	fx = 0;
+	if(EqY && *EqY && (EqY[0]!='y' || EqY[1]!=0))
+		fy = new mglFormula(EqY);
+	else	fy = 0;
+	if(EqZ && *EqZ && (EqZ[0]!='z' || EqZ[1]!=0))
+		fz = new mglFormula(EqZ);
+	else	fz = 0;
+	if(EqA && *EqA && ((EqA[0]!='c' && EqA[0]!='a') || EqA[1]!=0))
+		fa = new mglFormula(EqA);
+	else	fa = 0;
+	RecalcBorder();
+}
+//-----------------------------------------------------------------------------
+void mglBase::CutOff(const char *EqC)
+{
+#pragma omp critical(eq)
+	{
+		if(fc)	delete fc;
+		fc = (EqC && EqC[0])?new mglFormula(EqC):0;
+	}
+}
+//-----------------------------------------------------------------------------
+void mglBase::SetCoor(int how)
+{
+	switch(how)
+	{
+	case mglCartesian:	SetFunc(0,0);	break;
+	case mglPolar:
+		SetFunc("x*cos(y)","x*sin(y)");	break;
+	case mglSpherical:
+		SetFunc("x*sin(y)*cos(z)","x*sin(y)*sin(z)","x*cos(y)");	break;
+	case mglParabolic:
+		SetFunc("x*y","(x*x-y*y)/2");	break;
+	case mglParaboloidal:
+		SetFunc("(x*x-y*y)*cos(z)/2","(x*x-y*y)*sin(z)/2","x*y");	break;
+	case mglOblate:
+		SetFunc("cosh(x)*cos(y)*cos(z)","cosh(x)*cos(y)*sin(z)","sinh(x)*sin(y)");	break;
+//		SetFunc("x*y*cos(z)","x*y*sin(z)","(x*x-1)*(1-y*y)");	break;
+	case mglProlate:
+		SetFunc("sinh(x)*sin(y)*cos(z)","sinh(x)*sin(y)*sin(z)","cosh(x)*cos(y)");	break;
+	case mglElliptic:
+		SetFunc("cosh(x)*cos(y)","sinh(x)*sin(y)");	break;
+	case mglToroidal:
+		SetFunc("sinh(x)*cos(z)/(cosh(x)-cos(y))","sinh(x)*sin(z)/(cosh(x)-cos(y))",
+			"sin(y)/(cosh(x)-cos(y))");	break;
+	case mglBispherical:
+		SetFunc("sin(y)*cos(z)/(cosh(x)-cos(y))","sin(y)*sin(z)/(cosh(x)-cos(y))",
+			"sinh(x)/(cosh(x)-cos(y))");	break;
+	case mglBipolar:
+		SetFunc("sinh(x)/(cosh(x)-cos(y))","sin(y)/(cosh(x)-cos(y))");	break;
+	case mglLogLog:	SetFunc("lg(x)","lg(y)");	break;
+	case mglLogX:	SetFunc("lg(x)","");	break;
+	case mglLogY:	SetFunc("","lg(y)");	break;
+	default:	SetFunc(0,0);	break;
+	}
+}
+//-----------------------------------------------------------------------------
+void mglBase::ClearEq()
+{
+#pragma omp critical(eq)
+	{
+		if(fx)	delete fx;
+		if(fy)	delete fy;
+		if(fz)	delete fz;
+		if(fa)	delete fa;
+		if(fc)	delete fc;
+		fx = fy = fz = fc = fa = 0;
+	}
+	RecalcBorder();
+}
+//-----------------------------------------------------------------------------
+//		Colors ids
+//-----------------------------------------------------------------------------
+MGL_EXPORT mglColorID mglColorIds[31] = {{'k', mglColor(0,0,0)},
+	{'r', mglColor(1,0,0)},		{'R', mglColor(0.5,0,0)},
+	{'g', mglColor(0,1,0)},		{'G', mglColor(0,0.5,0)},
+	{'b', mglColor(0,0,1)},		{'B', mglColor(0,0,0.5)},
+	{'w', mglColor(1,1,1)},		{'W', mglColor(0.7,0.7,0.7)},
+	{'c', mglColor(0,1,1)},		{'C', mglColor(0,0.5,0.5)},
+	{'m', mglColor(1,0,1)},		{'M', mglColor(0.5,0,0.5)},
+	{'y', mglColor(1,1,0)},		{'Y', mglColor(0.5,0.5,0)},
+	{'h', mglColor(0.5,0.5,0.5)},	{'H', mglColor(0.3,0.3,0.3)},
+	{'l', mglColor(0,1,0.5)},	{'L', mglColor(0,0.5,0.25)},
+	{'e', mglColor(0.5,1,0)},	{'E', mglColor(0.25,0.5,0)},
+	{'n', mglColor(0,0.5,1)},	{'N', mglColor(0,0.25,0.5)},
+	{'u', mglColor(0.5,0,1)},	{'U', mglColor(0.25,0,0.5)},
+	{'q', mglColor(1,0.5,0)},	{'Q', mglColor(0.5,0.25,0)},
+	{'p', mglColor(1,0,0.5)},	{'P', mglColor(0.5,0,0.25)},
+	{' ', mglColor(-1,-1,-1)},	{0, mglColor(-1,-1,-1)}	// the last one MUST have id=0
+};
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_chrrgb(char p, float c[3])
+{
+	c[0]=c[1]=c[2]=-1;
+	for(long i=0; mglColorIds[i].id; i++)
+		if(mglColorIds[i].id==p)
+		{
+			c[0]=mglColorIds[i].col.r;
+			c[1]=mglColorIds[i].col.g;
+			c[2]=mglColorIds[i].col.b;
+			break;
+		}
+}
+//-----------------------------------------------------------------------------
+size_t MGL_EXPORT mgl_get_num_color(const char *s, int smooth)
+{
+	if(!s || !s[0])	return 0;
+	size_t l=strlen(s), n=0;	long j=0;
+	for(size_t i=0;i<l;i++)		// find number of colors
+	{
+		if(smooth>=0 && s[i]==':' && j<1)	break;
+		if(s[i]=='{' && strchr(MGL_COLORS"x",s[i+1]) && j<1)	n++;
+		if(s[i]=='[' || s[i]=='{')	j++;
+		if(s[i]==']' || s[i]=='}')	j--;
+		if(strchr(MGL_COLORS,s[i]) && j<1)	n++;
+//		if(smooth && s[i]==':')	break;	// NOTE: should use []
+	}
+	return n;
+}
+//-----------------------------------------------------------------------------
+void mglTexture::Set(const char *s, int smooth, mreal alpha)
+{
+	// NOTE: New syntax -- colors are CCCCC or {CNCNCCCN}; options inside []
+	if(!s || !s[0])	return;
+	strncpy(Sch,s,259);	Smooth=smooth;	Alpha=alpha;
+
+	long l=strlen(s);
+	bool map = smooth==2 || mglchr(s,'%'), sm = smooth>=0 && !strchr(s,'|');	// Use mapping, smoothed colors
+	n = mgl_get_num_color(s,smooth);
+	if(!n)
+	{
+		if(strchr(s,'|') && !smooth)	// sharp colors
+		{	n=l=6;	s=MGL_DEF_SCH;	sm = false;	}
+		else if(smooth==0)		// none colors but color scheme
+		{	n=l=6;	s=MGL_DEF_SCH;	}
+	}
+	if(n<=0)	return;
+	bool man=sm;
+	mglColor *c = new mglColor[2*n];		// Colors itself
+	mreal *val = new mreal[n];
+	for(long i=0, m=0, j=n=0;i<l;i++)	// fill colors
+	{
+		if(smooth>=0 && s[i]==':' && j<1)	break;
+		if(s[i]=='[')	j++;
+		if(s[i]==']')	j--;
+		if(s[i]=='{')	m++;
+		if(s[i]=='}')	m--;
+		if(strchr(MGL_COLORS,s[i]) && j<1 && (m==0 || s[i-1]=='{'))	// {CN,val} format, where val in [0,1]
+		{
+			if(m>0 && s[i+1]>'0' && s[i+1]<='9')// ext color
+			{	c[2*n].Set(s[i],(s[i+1]-'0')/5.f);	i++;	}
+			else	c[2*n].Set(s[i]);	// usual color
+			val[n]=-1;	c[2*n].a = -1;	n++;
+		}
+		if(s[i]=='x' && i>0 && s[i-1]=='{' && j<1)	// {xRRGGBB,val} format, where val in [0,1]
+		{
+			uint32_t id = strtoul(s+1+i,0,16);
+			if(memchr(s+i+1,'}',8) || memchr(s+i+1,',',8))	c[2*n].a = -1;
+			else	{	c[2*n].a = (id%256)/255.;	id /= 256;	}
+			c[2*n].b = (id%256)/255.;	id /= 256;
+			c[2*n].g = (id%256)/255.;	id /= 256;
+			c[2*n].r = (id%256)/255.;
+			while(strchr("0123456789abcdefABCDEFx",s[i]))	i++;
+			val[n]=-1;	n++;	i--;
+		}
+		if(s[i]==',' && m>0 && j<1 && n>0)
+			val[n-1] = atof(s+i+1);
+		// NOTE: User can change alpha if it placed like {AN}
+		if(s[i]=='A' && j<1 && m>0 && s[i+1]>'0' && s[i+1]<='9')
+		{	man=false;	alpha = 0.1*(s[i+1]-'0');	i++;	}
+	}
+	for(long i=0;i<n;i++)	// default texture
+	{
+		if(c[2*i].a<0)	c[2*i].a=alpha;
+		c[2*i+1]=c[2*i];
+		if(man)	c[2*i].a=0;
+	}
+	if(map && sm && n>1)		// map texture
+	{
+		if(n==2)
+		{	c[1]=c[2];	c[2]=c[0];	c[0]=BC;	c[3]=c[1]+c[2];	}
+		else if(n==3)
+		{	c[1]=c[2];	c[2]=c[0];	c[0]=BC;	c[3]=c[4];	n=2;}
+		else
+		{	c[1]=c[4];	c[3]=c[6];	n=2;	}
+		c[0].a = c[1].a = c[2].a = c[3].a = alpha;
+		val[0]=val[1]=-1;
+	}
+	// TODO if(!sm && n==1)	then try to find color in palette ???
+
+	// fill missed values  of val[]
+	float  v1=0,v2=1;
+	std::vector <long>  def;
+	val[0]=0;	val[n-1]=1;	// boundary have to be [0,1]
+	for(long i=0;i<n;i++) if(val[i]>0 && val[i]<1) 	def.push_back(i);
+	def.push_back(n-1);
+	long i1=0;
+	for(size_t j=0;j<def.size();j++)	for(long i=i1+1;i<def[j];i++)
+	{
+		i1 = j>0?def[j-1]:0;	long i2 = def[j];
+		v1 = val[i1];	v2 = val[i2];
+		v2 = i2-i1>1?(v2-v1)/(i2-i1):0;
+		val[i]=v1+v2*(i-i1);
+	}
+	// fill texture itself
+	mreal v=sm?(n-1)/255.:n/256.;
+	if(!sm)	for(long i=0;i<256;i++)
+	{
+		long j = 2*long(v*i);	//u-=j;
+		col[2*i] = c[j];	col[2*i+1] = c[j+1];
+	}
+	else	for(long i=i1=0;i<256;i++)
+	{
+		mreal u = v*i;	long j = long(u);	//u-=j;
+		if(j<n-1)	// advanced scheme using val
+		{
+			for(;i1<n-1 && i>=255*val[i1];i1++);
+			v2 = i1<n?1/(val[i1]-val[i1-1]):0;
+			j=i1-1;	u=(i/255.-val[j])*v2;
+			col[2*i] = c[2*j]*(1-u)+c[2*j+2]*u;
+			col[2*i+1]=c[2*j+1]*(1-u)+c[2*j+3]*u;
+		}
+		else
+		{	col[2*i] = c[2*n-2];col[2*i+1] = c[2*n-1];	}
+	}
+	delete []c;	delete []val;
+}
+//-----------------------------------------------------------------------------
+mglColor mglTexture::GetC(mreal u,mreal v) const
+{
+	u -= long(u);
+	long i=long(255*u);	u = u*255-i;
+	const mglColor *s=col+2*i;
+	return (s[0]*(1-u)+s[2]*u)*(1-v) + (s[1]*(1-u)+s[3]*u)*v;
+}
+//-----------------------------------------------------------------------------
+void mglTexture::GetC(mreal u,mreal v,mglPnt &p) const
+{
+	u -= long(u);
+	long i=long(255*u);	u = u*255-i;
+	const mglColor &s0=col[2*i], &s1=col[2*i+1], &s2=col[2*i+2], &s3=col[2*i+3];
+	p.r = (s0.r*(1-u)+s2.r*u)*(1-v) + (s1.r*(1-u)+s3.r*u)*v;
+	p.g = (s0.g*(1-u)+s2.g*u)*(1-v) + (s1.g*(1-u)+s3.g*u)*v;
+	p.b = (s0.b*(1-u)+s2.b*u)*(1-v) + (s1.b*(1-u)+s3.b*u)*v;
+	p.a = (s0.a*(1-u)+s2.a*u)*(1-v) + (s1.a*(1-u)+s3.a*u)*v;
+//	p.a = (s0.a*(1-u)+s2.a*u)*v + (s1.a*(1-u)+s3.a*u)*(1-v);	// for alpha use inverted
+}
+//-----------------------------------------------------------------------------
+long mglBase::AddTexture(const char *cols, int smooth)
+{
+	if(smooth>=0)	SetMask(cols);
+	mglTexture t(cols,smooth,smooth==2?AlphaDef:1);
+	if(t.n==0)	return smooth<0 ? 0:1;
+	if(smooth<0)	CurrPal=0;
+	// check if already exist
+	for(size_t i=0;i<Txt.size();i++)
+		if(!t.IsSame(Txt[i]))	continue;	else	return i;
+	// create new one
+	long k;
+#pragma omp critical(txt)
+	{k=Txt.size();	MGL_PUSH(Txt,t,mutexTxt);}	return k;
+}
+//-----------------------------------------------------------------------------
+mreal mglBase::AddTexture(mglColor c)
+{
+	if(!c.Valid())	return -1;
+	// first lets try an existed one
+	for(size_t i=0;i<Txt.size();i++)	for(int j=0;j<255;j++)
+		if(c==Txt[i].col[2*j])
+			return i+j/255.;
+	// add new texture
+	mglTexture t;
+	for(long i=0;i<MGL_TEXTURE_COLOURS;i++)	t.col[i]=c;
+	long k;
+#pragma omp critical(txt)
+	{k=Txt.size();	MGL_PUSH(Txt,t,mutexTxt);}	return k;
+}
+//-----------------------------------------------------------------------------
+//		Coloring and palette
+//-----------------------------------------------------------------------------
+mreal mglBase::NextColor(long &id)
+{
+	long i=labs(id)/256, n=Txt[i].n, p=labs(id)&0xff;
+	if(id>=0)	{	p=(p+1)%n;	id = 256*i+p;	}
+	CDef = i + (n>0 ? (p+0.5)/n : 0);	CurrPal++;
+	sprintf(last_style+11,"{&%g}",CDef);
+	if(!leg_str.empty())
+	{	AddLegend(leg_str.c_str(),last_style);	leg_str.clear();	}
+	return CDef;
+}
+//-----------------------------------------------------------------------------
+mreal mglBase::NextColor(long id, long sh)
+{
+	long i=labs(id)/256, n=Txt[i].n, p=labs(id)&0xff;
+	if(id>=0)	p=(p+sh)%n;
+	mreal cc = i + (n>0 ? (p+0.5)/n : 0);
+	sprintf(last_style+11,"{&%g}",cc);
+	return cc;
+}
+//-----------------------------------------------------------------------------
+MGL_EXPORT const char *mglchrs(const char *str, const char *chr)
+{
+	if(!str || !str[0] || !chr || !chr[0])	return NULL;
+	size_t l=strlen(chr);
+	for(size_t i=0;i<l;i++)
+	{
+		const char *res = mglchr(str,chr[i]);
+		if(res)	return res;
+	}
+	return NULL;
+}
+//-----------------------------------------------------------------------------
+MGL_EXPORT const char *mglchr(const char *str, char ch)
+{
+	if(!str || !str[0])	return NULL;
+	size_t l=strlen(str),k=0;
+	for(size_t i=0;i<l;i++)
+	{
+		char c = str[i];
+		if(c=='{')	k++;
+		if(c=='}')	k--;
+		if(c==ch && k==0)	return str+i;
+	}
+	return NULL;
+}
+//-----------------------------------------------------------------------------
+char mglBase::SetPenPal(const char *p, long *Id, bool pal)
+{
+	char mk=0;
+	PDef = 0xffff;	// reset to solid line
+	strcpy(last_style,"__1 {dFFFF}k\0");
+
+	const char *s;
+	Arrow1 = Arrow2 = 0;	PenWidth = 1;
+	if(p && *p)
+	{
+//		const char *col = "wkrgbcymhRGBCYMHWlenuqpLENUQP";
+		unsigned val[8] = {0x0000, 0xffff, 0x00ff, 0x0f0f, 0x1111, 0x087f, 0x2727, 0x3333};
+		const char *stl = " -|;:ji=";
+		const char *mrk = "*o+xsd.^v<>";
+		const char *MRK = "YOPXSDCTVLR";
+		const char *wdh = "123456789";
+		const char *arr = "AKDTVISOX_";
+		long m=0;
+		size_t l=strlen(p);
+		for(size_t i=0;i<l;i++)
+		{
+			if(p[i]=='{')	m++;
+			if(p[i]=='}')	m--;
+			if(m>0 && p[i]=='d')	PDef = strtol(p+i+1,0,16);
+			if(m>0)	continue;
+			s = mglchr(stl,p[i]);
+			if(s)
+			{	PDef = val[s-stl];	sprintf(last_style+6,"%04x",PDef);	last_style[10]='}';	}
+			else if(mglchr(mrk,p[i]))
+			{	mk = p[i];	last_style[3] = mk;	}
+			else if(mglchr(wdh,p[i]))
+			{	PenWidth = p[i]-'0';	last_style[2] = p[i];	}
+			else if(mglchr(arr,p[i]))
+			{
+				if(!Arrow2)	Arrow2 = p[i];
+				else	Arrow1 = p[i];
+			}
+		}
+		if(!Arrow1)	Arrow1='_';
+		if(!Arrow2)	Arrow2='_';
+		if(mglchr(p,'#'))
+		{
+			s = mglchr(mrk,mk);
+			if(s)
+			{	mk = MRK[s-mrk];	last_style[3] = mk;	}
+		}
+		if((s=strstr(p,"{&"))!=0)
+		{	mk = last_style[3] = p[3];	strcpy(last_style+11,s);	}
+		else if(mk && mglchr(p,'&'))
+		{	mk += 128;	last_style[3] = mk;	}
+		last_style[0] = Arrow1;	last_style[1] = Arrow2;
+	}
+	if(pal)
+	{
+		if(p && (s=strstr(p,"{&"))!=0)
+		{
+			CDef = atof(s+2);
+//			if(Id)	*Id=long(tt)*256+(n+CurrPal-1)%n;
+		}
+		else
+		{
+			long tt, n;
+			tt = AddTexture(p?p:MGL_DEF_PAL,-1);	n=Txt[tt].n;
+			CDef = tt+((n+CurrPal-1)%n+0.5)/n;
+			if(Id)	*Id=long(tt)*256+(n+CurrPal-1)%n;
+			sprintf(last_style+11,"{&%g}",CDef);
+		}
+	}
+	if(Arrow1=='_')	Arrow1=0;
+	if(Arrow2=='_')	Arrow2=0;
+	return mk;
+}
+//-----------------------------------------------------------------------------
+// keep this for restore default mask
+MGL_EXPORT uint64_t mgl_mask_def[16]={0x000000FF00000000,	0x080808FF08080808,	0x0000FF00FF000000,	0x0000007700000000,
+							0x0000182424180000,	0x0000183C3C180000,	0x00003C24243C0000,	0x00003C3C3C3C0000,
+							0x0000060990600000,	0x0060584658600000,	0x00061A621A060000,	0x0000005F00000000,
+							0x0008142214080000,	0x00081C3E1C080000,	0x8142241818244281,	0x0000001824420000};
+MGL_EXPORT uint64_t mgl_mask_val[16]={0x000000FF00000000,	0x080808FF08080808,	0x0000FF00FF000000,	0x0000007700000000,
+							0x0000182424180000,	0x0000183C3C180000,	0x00003C24243C0000,	0x00003C3C3C3C0000,
+							0x0000060990600000,	0x0060584658600000,	0x00061A621A060000,	0x0000005F00000000,
+							0x0008142214080000,	0x00081C3E1C080000,	0x8142241818244281,	0x0000001824420000};
+void mglBase::SetMask(const char *p)
+{
+	mask = MGL_SOLID_MASK;	// reset to solid face
+	PenWidth = 1;	MaskAn=DefMaskAn;
+	if(p && *p)
+	{
+		const char *msk = MGL_MASK_ID, *s;
+		const char *wdh = "123456789";
+		long m=0, l=strlen(p);
+		for(long i=0;i<l;i++)
+		{
+			if(p[i]=='{')	m++;
+			if(p[i]=='}')	m--;
+			if(m>0 && p[i]=='s')	mask = strtoull(p+i+1,0,16);
+			if(m>0)	continue;
+			if(p[i]==':')	break;
+			s = mglchr(msk, p[i]);
+			if(s)	mask = mgl_mask_val[s-msk];
+			else if(mglchr(wdh,p[i]))	PenWidth = p[i]-'0';
+			else if(p[i]=='I')	MaskAn=90;
+			else if(p[i]=='/')	MaskAn=315;	// =360-45
+			else if(p[i]=='\\')	MaskAn=45;
+		}
+		// use line if rotation only specified
+		if(mask==MGL_SOLID_MASK && MaskAn!=0)	mask = mgl_mask_val[0];
+	}
+}
+//-----------------------------------------------------------------------------
+mreal mglBase::GetA(mreal a) const
+{
+	if(fa)	a = fa->Calc(0,0,0,a);
+	a = (a-FMin.c)/(FMax.c-FMin.c);
+	a = (a<1?(a>0?a:0):1)/MGL_FEPSILON;	// for texture a must be <1 always!!!
+	return a;
+}
+//-----------------------------------------------------------------------------
+mglPoint GetX(HCDT x, int i, int j, int k)
+{
+	k = k<x->GetNz() ? k : 0;
+	if(x->GetNy()>1)
+		return mglPoint(x->v(i,j,k),x->dvx(i,j,k),x->dvy(i,j,k));
+	else
+		return mglPoint(x->v(i),x->dvx(i),0);
+}
+//-----------------------------------------------------------------------------
+mglPoint GetY(HCDT y, int i, int j, int k)
+{
+	k = k<y->GetNz() ? k : 0;
+	if(y->GetNy()>1)
+		return mglPoint(y->v(i,j,k),y->dvx(i,j,k),y->dvy(i,j,k));
+	else
+		return mglPoint(y->v(j),0,y->dvx(j));
+}
+//-----------------------------------------------------------------------------
+mglPoint GetZ(HCDT z, int i, int j, int k)
+{
+	if(z->GetNy()>1)
+		return mglPoint(z->v(i,j,k),z->dvx(i,j,k),z->dvy(i,j,k));
+	else
+		return mglPoint(z->v(k),0,0);
+}
+//-----------------------------------------------------------------------------
+void mglBase::vect_plot(long p1, long p2, mreal s)
+{
+	if(p1<0 || p2<0)	return;
+	const mglPnt &q1=Pnt[p1], &q2=Pnt[p2];
+	mglPnt s1=q2,s2=q2;
+	s = s<=0 ? 0.1 : s*0.1;
+	s1.x=s1.xx = q2.x - 3*s*(q2.x-q1.x) + s*(q2.y-q1.y);
+	s2.x=s2.xx = q2.x - 3*s*(q2.x-q1.x) - s*(q2.y-q1.y);
+	s1.y=s1.yy = q2.y - 3*s*(q2.y-q1.y) - s*(q2.x-q1.x);
+	s2.y=s2.yy = q2.y - 3*s*(q2.y-q1.y) + s*(q2.x-q1.x);
+	s1.z=s1.zz=s2.z=s2.zz = q2.z - 3*s*(q2.z-q1.z);
+	long n1,n2;
+#pragma omp critical(pnt)
+	{
+		n1=Pnt.size();	MGL_PUSH(Pnt,s1,mutexPnt);
+		n2=Pnt.size();	MGL_PUSH(Pnt,s2,mutexPnt);
+	}
+	line_plot(p1,p2);	line_plot(n1,p2);	line_plot(p2,n2);
+}
+//-----------------------------------------------------------------------------
+int MGL_LOCAL_PURE mglFindArg(const char *str)
+{
+	long l=0,k=0,len=strlen(str);
+	for(long i=0;i<len;i++)
+	{
+		if(str[i]=='\'') l++;
+		if(str[i]=='{') k++;
+		if(str[i]=='}') k--;
+		if(l%2==0 && k==0)
+		{
+			if(str[i]=='#' || str[i]==';')	return -i;
+			if(str[i]<=' ')	return i;
+		}
+	}
+	return 0;
+}
+//-----------------------------------------------------------------------------
+void mglBase::SetAmbient(mreal bright)
+{	AmbBr=bright;	size_t n=Sub.size();	if(n>0)	Sub[n-1].AmbBr=bright;	}
+void mglBase::SetDiffuse(mreal bright)
+{	DifBr=bright;	size_t n=Sub.size();	if(n>0)	Sub[n-1].DifBr=bright;	}
+//-----------------------------------------------------------------------------
+mreal mglBase::SaveState(const char *opt)
+{
+	if(saved)	return PrevState;
+	if(!opt || !opt[0])	return NAN;
+	MSS=MarkSize;	ASS=ArrowSize;
+	FSS=FontSize;	ADS=AlphaDef;
+	MNS=MeshNum;	CSS=Flag;	LSS=AmbBr;
+	MinS=Min;		MaxS=Max;	saved=true;
+	// parse option
+	char *qi=mgl_strdup(opt),*q=qi, *s;
+	mgl_strtrim(q);
+	// NOTE: not consider '#' inside legend entry !!!
+	s=strchr(q,'#');	if(s)	*s=0;
+	mreal res=NAN;
+	while(q && *q)
+	{
+		s=q;	q=strchr(s,';');
+		if(q)	{	*q=0;	q++;	}
+		mgl_strtrim(s);		char *a=s;
+		long n=mglFindArg(s);	if(n>0)	{	s[n]=0;		s=s+n+1;	}
+		mgl_strtrim(a);		char *b=s;
+		n=mglFindArg(s);	if(n>0)	{	s[n]=0;		s=s+n+1;	}
+		mgl_strtrim(b);
+
+		mreal ff=atof(b),ss;
+		size_opt = NAN;
+		if(!strcmp(b,"on"))	ff=1;
+		if(!strcmp(a+1,"range"))
+		{
+			n=mglFindArg(s);	char *c=s;
+			if(n>0)	{	s[n]=0;	s=s+n+1;	}
+			mgl_strtrim(c);		ss = atof(c);
+			if(a[0]=='x')		{	Min.x=ff;	Max.x=ss;	}
+			else if(a[0]=='y')	{	Min.y=ff;	Max.y=ss;	}
+			else if(a[0]=='z')	{	Min.z=ff;	Max.z=ss;	}
+//			else if(a[0]=='c')	{	Min.c=ff;	Max.c=ss;	}	// Bad idea since there is formula for coloring
+		}
+		else if(!strcmp(a,"cut"))		SetCut(ff!=0);
+		else if(!strcmp(a,"meshnum"))	SetMeshNum(ff);
+		else if(!strcmp(a,"alpha"))		{Alpha(true);	SetAlphaDef(ff);}
+		else if(!strcmp(a,"light"))		Light(ff!=0);
+		else if(!strcmp(a,"ambient"))	SetAmbient(ff);
+		else if(!strcmp(a,"diffuse"))	SetDifLight(ff);
+		else if(!strcmp(a,"size"))
+		{	SetMarkSize(ff);	SetFontSize(ff);	SetArrowSize(ff);	size_opt=ff;	}
+		else if(!strcmp(a,"num") || !strcmp(a,"number") || !strcmp(a,"value"))	res=ff;
+		else if(!strcmp(a,"legend"))
+		{	if(*b=='\'')	{	b++;	b[strlen(b)-1]=0;	}	leg_str = b;	}
+	}
+	free(qi);	PrevState=res;	return res;
+}
+//-----------------------------------------------------------------------------
+void mglBase::LoadState()
+{
+	if(!saved)	return;
+	MarkSize=MSS;	ArrowSize=ASS;
+	FontSize=FSS;	AlphaDef=ADS;
+	MeshNum=MNS;	Flag=CSS;	AmbBr=LSS;
+	Min=MinS;		Max=MaxS;	saved=false;
+}
+//-----------------------------------------------------------------------------
+void mglBase::AddLegend(const wchar_t *text,const char *style)
+{
+	if(text)
+#pragma omp critical(leg)
+		MGL_PUSH(Leg,mglText(text,style),mutexLeg);
+}
+//-----------------------------------------------------------------------------
+void mglBase::AddLegend(const char *str,const char *style)
+{
+	MGL_TO_WCS(str,AddLegend(wcs, style));
+}
+//-----------------------------------------------------------------------------
+bool MGL_EXPORT mgl_check_dim2(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, const char *name, bool less)
+{
+//	if(!gr || !x || !y || !z)	return true;		// if data is absent then should be segfault!!!
+	long n=z->GetNx(),m=z->GetNy();
+	if(n<2 || m<2)	{	gr->SetWarn(mglWarnLow,name);	return true;	}
+	if(a && z->GetNN()!=a->GetNN())
+	{	gr->SetWarn(mglWarnDim,name);	return true;	}
+	if(less)
+	{
+		if(x->GetNx()<n)
+		{	gr->SetWarn(mglWarnDim,name);	return true;	}
+		if(y->GetNx()<m && (x->GetNy()<m || y->GetNx()<n || y->GetNy()<m))
+		{	gr->SetWarn(mglWarnDim,name);	return true;	}
+	}
+	else
+	{
+		if(x->GetNx()!=n)
+		{	gr->SetWarn(mglWarnDim,name);	return true;	}
+		if(y->GetNx()!=m && (x->GetNy()!=m || y->GetNx()!=n || y->GetNy()!=m))
+		{	gr->SetWarn(mglWarnDim,name);	return true;	}
+	}
+	return false;
+}
+//-----------------------------------------------------------------------------
+bool MGL_EXPORT mgl_check_dim0(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT r, const char *name, bool less)
+{
+//	if(!gr || !x || !y)	return true;		// if data is absent then should be segfault!!!
+	long n=y->GetNx();
+	if(less)
+	{
+		if(x->GetNx()<n)		{	gr->SetWarn(mglWarnDim,name);	return true;	}
+		if(z && z->GetNx()<n)	{	gr->SetWarn(mglWarnDim,name);	return true;	}
+		if(r && r->GetNx()<n)	{	gr->SetWarn(mglWarnDim,name);	return true;	}
+	}
+	else
+	{
+		if(x->GetNx()!=n)		{	gr->SetWarn(mglWarnDim,name);	return true;	}
+		if(z && z->GetNx()!=n)	{	gr->SetWarn(mglWarnDim,name);	return true;	}
+		if(r && r->GetNx()!=n)	{	gr->SetWarn(mglWarnDim,name);	return true;	}
+	}
+	return false;
+}
+//-----------------------------------------------------------------------------
+bool MGL_EXPORT mgl_check_dim1(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT r, const char *name, bool less)
+{
+//	if(!gr || !x || !y)	return true;		// if data is absent then should be segfault!!!
+	long n=y->GetNx();
+	if(n<2)	{	gr->SetWarn(mglWarnLow,name);	return true;	}
+	if(less)
+	{
+		if(x->GetNx()<n)		{	gr->SetWarn(mglWarnDim,name);	return true;	}
+		if(z && z->GetNx()<n)	{	gr->SetWarn(mglWarnDim,name);	return true;	}
+		if(r && r->GetNx()<n)	{	gr->SetWarn(mglWarnDim,name);	return true;	}
+	}
+	else
+	{
+		if(x->GetNx()!=n)		{	gr->SetWarn(mglWarnDim,name);	return true;	}
+		if(z && z->GetNx()!=n)	{	gr->SetWarn(mglWarnDim,name);	return true;	}
+		if(r && r->GetNx()!=n)	{	gr->SetWarn(mglWarnDim,name);	return true;	}
+	}
+	return false;
+}
+//-----------------------------------------------------------------------------
+bool MGL_EXPORT mgl_check_dim3(HMGL gr, bool both, HCDT x, HCDT y, HCDT z, HCDT a, HCDT b, const char *name)
+{
+// 	if(!gr || !x || !y || !z || !a)	return true;		// if data is absent then should be segfault!!!
+	long n=a->GetNx(),m=a->GetNy(),l=a->GetNz();
+	if(n<2 || m<2 || l<2)
+	{	gr->SetWarn(mglWarnLow,name);	return true;	}
+	if(!both && (x->GetNx()!=n || y->GetNx()!=m || z->GetNx()!=l))
+	{	gr->SetWarn(mglWarnDim,name);	return true;	}
+	if(b && b->GetNN()!=n*m*l)
+	{	gr->SetWarn(mglWarnDim,name);	return true;	}
+	return false;
+}
+//-----------------------------------------------------------------------------
+bool MGL_EXPORT mgl_check_trig(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, HCDT a, const char *name, int d)
+{
+// 	if(!gr || !x || !y || !z || !a || !nums)	return true;		// if data is absent then should be segfault!!!
+	long n = x->GetNN(), m = nums->GetNy();
+	if(nums->GetNx()<d)	{	gr->SetWarn(mglWarnLow,name);	return true;	}
+	if(y->GetNN()!=n || z->GetNN()!=n)	{	gr->SetWarn(mglWarnDim,name);	return true;	}
+	if(a->GetNN()!=m && a->GetNN()!=n)	{	gr->SetWarn(mglWarnDim,name);	return true;	}
+	return false;
+}
+//-----------------------------------------------------------------------------
+bool MGL_EXPORT mgl_isnboth(HCDT x, HCDT y, HCDT z, HCDT a)
+{
+	long n=a->GetNN();
+	return x->GetNN()!=n || y->GetNN()!=n || z->GetNN()!=n;
+}
+//-----------------------------------------------------------------------------
+bool MGL_EXPORT mgl_isboth(HCDT x, HCDT y, HCDT z, HCDT a)
+{
+	long n=a->GetNN();
+	return x->GetNN()==n && y->GetNN()==n && z->GetNN()==n;
+}
+//-----------------------------------------------------------------------------
+bool MGL_EXPORT mgl_check_vec3(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT ax, HCDT ay, HCDT az, const char *name)
+{
+// 	if(!gr || !x || !y || !z || !ax || !ay || !az)	return true;		// if data is absent then should be segfault!!!
+	long n=ax->GetNx(),m=ax->GetNy(),l=ax->GetNz(), nn=n*m*l;
+	if(nn!=ay->GetNN() || nn!=az->GetNN())
+	{	gr->SetWarn(mglWarnDim,name);	return true;	}
+	if(n<2 || m<2 || l<2)	{	gr->SetWarn(mglWarnLow,name);	return true;	}
+	bool both = x->GetNN()==nn && y->GetNN()==nn && z->GetNN()==nn;
+	if(!(both || (x->GetNx()==n && y->GetNx()==m && z->GetNx()==l)))
+	{	gr->SetWarn(mglWarnDim,name);	return true;	}
+	return false;
+}
+//-----------------------------------------------------------------------------
+void mglBase::SetFontDef(const char *font) {	strncpy(FontDef, font, 31);	}
+//-----------------------------------------------------------------------------
+void mglBase::ClearUnused()
+{
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_lock(&mutexPnt);	pthread_mutex_lock(&mutexPrm);
+#endif
+#pragma omp critical
+	{
+		size_t l=Prm.size();
+		// find points which are actually used
+		long *used = new long[Pnt.size()];	memset(used,0,Pnt.size()*sizeof(long));
+		for(size_t i=0;i<l;i++)
+		{
+			const mglPrim &p=Prm[i];
+			if(p.n1<0)	continue;
+			used[p.n1] = 1;
+			switch(p.type)
+			{
+			case 1:	case 4:	if(p.n2>=0)	used[p.n2] = 1;
+				break;
+			case 2:	if(p.n2>=0 && p.n3>=0)	used[p.n2] = used[p.n3] = 1;
+				break;
+			case 3:	if(p.n2>=0 && p.n3>=0 && p.n4>=0)
+					used[p.n2] = used[p.n3] = used[p.n4] = 1;
+				break;
+			}
+		}
+		// now add proper indexes
+		l=Pnt.size();
+		mglStack<mglPnt> pnt;	pnt.reserve(l);
+		for(size_t i=0;i<l;i++)	if(used[i])
+		{	pnt.push_back(Pnt[i]);	used[i]=pnt.size()-1;	}
+		Pnt = pnt;	pnt.clear();
+		// now replace point id
+		l=Prm.size();
+		for(size_t i=0;i<l;i++)
+		{
+			mglPrim &p=Prm[i];	p.n1=used[p.n1];
+			if(p.type==1 || p.type==4)	p.n2=used[p.n2];
+			if(p.type==2)	{	p.n2=used[p.n2];	p.n3=used[p.n3];	}
+			if(p.type==3)	{	p.n2=used[p.n2];	p.n3=used[p.n3];	p.n4=used[p.n4];	}
+		}
+		delete []used;
+	}
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_unlock(&mutexPnt);	pthread_mutex_unlock(&mutexPrm);
+#endif
+}
+//-----------------------------------------------------------------------------
+void mglBase::ClearPrmInd()
+{
+#pragma omp critical(prmind)
+	{	if(PrmInd)	delete []PrmInd;	PrmInd=NULL;	}
+}
+//-----------------------------------------------------------------------------
diff --git a/src/base_cf.cpp b/src/base_cf.cpp
new file mode 100644
index 0000000..3aeb60e
--- /dev/null
+++ b/src/base_cf.cpp
@@ -0,0 +1,318 @@
+/***************************************************************************
+ * base.cpp is part of Math gric Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include "mgl2/font.h"
+#include "mgl2/base_cf.h"
+#include "mgl2/base.h"
+//-----------------------------------------------------------------------------
+//
+//		C interfaces
+//
+//-----------------------------------------------------------------------------
+bool mglPrintWarn = true;
+void MGL_EXPORT mgl_suppress_warn(int on)	{	mglPrintWarn = !on;	}
+void MGL_EXPORT mgl_suppress_warn_(int *on)	{	mgl_suppress_warn(*on);	}
+void MGL_EXPORT mgl_set_quality(HMGL gr, int qual)	{	gr->SetQuality(qual);	}
+void MGL_EXPORT mgl_set_quality_(uintptr_t *gr, int *qual)	{	_GR_->SetQuality(*qual);	}
+int MGL_EXPORT mgl_get_quality(HMGL gr)	{	return gr->GetQuality();	}
+int MGL_EXPORT mgl_get_quality_(uintptr_t *gr)	{	return _GR_->GetQuality();	}
+int MGL_EXPORT mgl_is_frames(HMGL gr)
+{	return gr->get(MGL_VECT_FRAME) && !(gr->GetQuality()&MGL_DRAW_LMEM);	}
+void MGL_EXPORT mgl_set_draw_reg(HMGL gr, long nx, long ny, long m)	{	gr->SetDrawReg(nx,ny,m);	}
+void MGL_EXPORT mgl_set_draw_reg_(uintptr_t *gr, int *nx, int *ny, int *m)	{	_GR_->SetDrawReg(*nx,*ny,*m);	}
+//-----------------------------------------------------------------------------
+int MGL_EXPORT mgl_get_flag(HMGL gr, uint32_t flag)	{	return gr->get(flag);	}
+int MGL_EXPORT mgl_get_flag_(uintptr_t *gr, unsigned long *flag)	{	return _GR_->get(*flag);	}
+void MGL_EXPORT mgl_set_flag(HMGL gr, int val, uint32_t flag)		{	gr->set(val,flag);	}
+void MGL_EXPORT mgl_set_flag_(uintptr_t *gr, int *val, unsigned long *flag)	{	_GR_->set(*val,*flag);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_color(char id, double r, double g, double b)
+{
+	for(long i=0;mglColorIds[i].id;i++)
+		if(mglColorIds[i].id==id)	mglColorIds[i].col = mglColor(r,g,b);
+}
+void MGL_EXPORT mgl_set_color_(char *id, mreal *r, mreal *g, mreal *b, int)	{	mgl_set_color(*id,*r,*g,*b);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_def_sch(HMGL gr, const char *sch)	{	gr->SetDefScheme(sch);	}
+void MGL_EXPORT mgl_set_def_sch_(uintptr_t *gr, const char *sch,int l)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	mgl_set_def_sch(_GR_, s);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_plotid(HMGL gr, const char *id)	{	gr->PlotId = id;	}
+void MGL_EXPORT mgl_set_plotid_(uintptr_t *gr, const char *id,int l)
+{	char *s=new char[l+1];	memcpy(s,id,l);	s[l]=0;
+	_GR_->PlotId = s;	delete []s;	}
+MGL_EXPORT const char *mgl_get_plotid(HMGL gr)	{	return gr->PlotId.c_str();	}
+int MGL_EXPORT mgl_get_plotid_(uintptr_t *gr, char *out, int len)
+{
+	const char *res = mgl_get_plotid(_GR_);
+	if(out)	strncpy(out,res,len);
+	return strlen(res);
+}
+//-----------------------------------------------------------------------------
+MGL_EXPORT const char *mgl_get_mess(HMGL gr)	{	return gr->Mess.c_str();	}
+int MGL_EXPORT mgl_get_mess_(uintptr_t *gr, char *out, int len)
+{
+	const char *res = mgl_get_mess(_GR_);
+	if(out)	strncpy(out,res,len);
+	return strlen(res);
+}
+int MGL_EXPORT mgl_get_warn(HMGL gr)	{	return gr->GetWarn();	}
+void MGL_EXPORT mgl_set_warn(HMGL gr, int code, const char *txt)
+{	gr->SetWarn(code,txt);	}
+extern bool mglPrintWarn;
+void MGL_EXPORT mgl_set_global_warn(const char *txt)
+{
+	if(txt && *txt)
+	{
+		mglGlobalMess += txt;	mglGlobalMess += '\n';
+		if(mglPrintWarn)	fprintf(stderr,_("Global message - %s\n"),txt);
+	}
+}
+void MGL_EXPORT mgl_set_global_warn_(const char *txt, int l)
+{	char *s=new char[l+1];	memcpy(s,txt,l);	s[l]=0;	mgl_set_global_warn(s);	delete []s;	}
+MGL_EXPORT const char *mgl_get_global_warn()	{	return mglGlobalMess.c_str();	}
+int MGL_EXPORT mgl_get_global_warn_(char *out, int len)
+{
+	const char *res = mgl_get_global_warn();
+	if(out)	strncpy(out,res,len);
+	return strlen(res);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_origin(HMGL gr, double x0, double y0, double z0)
+{	gr->SetOrigin(x0,y0,z0);	}
+void MGL_EXPORT mgl_set_palette(HMGL gr, const char *colors)
+{	gr->SetPalette(colors);	}
+void MGL_EXPORT mgl_set_meshnum(HMGL gr, int num)	{	gr->SetMeshNum(num);	}
+void MGL_EXPORT mgl_set_facenum(HMGL gr, int num)	{	gr->FaceNum=num;		}
+void MGL_EXPORT mgl_set_alpha_default(HMGL gr, double alpha)	{	gr->SetAlphaDef(alpha);	}
+void MGL_EXPORT mgl_set_light_dif(HMGL gr, int enable)		{	gr->SetDifLight(enable);	}
+void MGL_EXPORT mgl_clear_unused(HMGL gr)	{	gr->ClearUnused();	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_rdc_acc(HMGL gr, int reduce)	{	gr->SetReduceAcc(reduce);	}
+void MGL_EXPORT mgl_highlight(HMGL gr, int id)			{	gr->Highlight(id);	}
+void MGL_EXPORT mgl_set_cut(HMGL gr, int cut)	{	gr->SetCut(cut);	}
+void MGL_EXPORT mgl_set_cut_box(HMGL gr, double x1,double y1,double z1,double x2,double y2,double z2)
+{	gr->SetCutBox(x1,y1,z1,x2,y2,z2);	}
+void MGL_EXPORT mgl_set_cutoff(HMGL gr, const char *EqC)	{	gr->CutOff(EqC);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_ternary(HMGL gr, int enable)			{	gr->Ternary(enable);	}
+void MGL_EXPORT mgl_set_range_val(HMGL gr, char dir, double v1,double v2)
+{
+	if(dir=='c' || dir=='a')	gr->CRange(v1,v2);
+	else if(dir=='x')	gr->XRange(v1,v2);
+	else if(dir=='y')	gr->YRange(v1,v2);
+	else if(dir=='z')	gr->ZRange(v1,v2);
+}
+void MGL_EXPORT mgl_add_range_val(HMGL gr, char dir, double v1,double v2)
+{
+	if(dir=='c' || dir=='a')	gr->CRange(v1,v2,true);
+	else if(dir=='x')	gr->XRange(v1,v2,true);
+	else if(dir=='y')	gr->YRange(v1,v2,true);
+	else if(dir=='z')	gr->ZRange(v1,v2,true);
+}
+void MGL_EXPORT mgl_set_range_dat(HMGL gr, char dir, HCDT a, int add)
+{
+	if(dir=='c' || dir=='a')	gr->CRange(a,add);
+	else if(dir=='x')	gr->XRange(a,add);
+	else if(dir=='y')	gr->YRange(a,add);
+	else if(dir=='z')	gr->ZRange(a,add);
+}
+void MGL_EXPORT mgl_set_ranges(HMGL gr, double x1, double x2, double y1, double y2, double z1, double z2)
+{	gr->SetRanges(x1,x2,y1,y2,z1,z2);	}
+void MGL_EXPORT mgl_set_auto_ranges(HMGL gr, double x1, double x2, double y1, double y2, double z1, double z2, double c1, double c2)
+{	gr->SetAutoRanges(x1,x2,y1,y2,z1,z2,c1,c2);	}
+void MGL_EXPORT mgl_set_func(HMGL gr, const char *EqX,const char *EqY,const char *EqZ,const char *EqA)
+{	gr->SetFunc(EqX,EqY,EqZ,EqA);	}
+void MGL_EXPORT mgl_set_coor(HMGL gr, int how)	{	gr->SetCoor(how);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_bar_width(HMGL gr, double width)	{	gr->SetBarWidth(width);	}
+//-----------------------------------------------------------------------------
+//
+//		Fortran interfaces
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_rdc_acc_(uintptr_t *gr, int *reduce)
+{	_GR_->SetReduceAcc(*reduce);	}
+void MGL_EXPORT mgl_highlight_(uintptr_t *gr, int *id)	{	_GR_->Highlight(*id);	}
+void MGL_EXPORT mgl_set_origin_(uintptr_t *gr, mreal *x0, mreal *y0, mreal *z0)
+{	_GR_->SetOrigin(*x0,*y0,*z0);	}
+int MGL_EXPORT mgl_get_warn_(uintptr_t *gr)	{	return _GR_->GetWarn();	}
+void MGL_EXPORT mgl_set_warn_(uintptr_t *gr, int *code, const char *txt, int l)
+{	char *s=new char[l+1];	memcpy(s,txt,l);	s[l]=0;
+	_GR_->SetWarn(*code, s);	delete []s;	}
+void MGL_EXPORT mgl_set_palette_(uintptr_t *gr, const char *colors, int l)
+{	char *s=new char[l+1];	memcpy(s,colors,l);	s[l]=0;
+	_GR_->SetPalette(s);	delete []s;	}
+void MGL_EXPORT mgl_set_meshnum_(uintptr_t *gr, int *num)	{	_GR_->SetMeshNum(*num);	}
+void MGL_EXPORT mgl_set_facenum_(uintptr_t *gr, int *num)	{	_GR_->FaceNum=*num;		}
+void MGL_EXPORT mgl_set_alpha_default_(uintptr_t *gr, mreal *alpha)	{	_GR_->SetAlphaDef(*alpha);	}
+void MGL_EXPORT mgl_set_light_dif_(uintptr_t *gr, int *enable)			{	_GR_->SetDifLight(*enable);	}
+void MGL_EXPORT mgl_clear_unused_(uintptr_t *gr)	{	_GR_->ClearUnused();	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_cut_box_(uintptr_t *gr, mreal *x1, mreal *y1, mreal *z1, mreal *x2, mreal *y2, mreal *z2)
+{	_GR_->SetCutBox(*x1,*y1,*z1,*x2,*y2,*z2);	}
+void MGL_EXPORT mgl_set_cut_(uintptr_t *gr, int *cut)	{	_GR_->SetCut(*cut);	}
+void MGL_EXPORT mgl_set_cutoff_(uintptr_t *gr, const char *EqC, int l)
+{	char *s=new char[l+1];	memcpy(s,EqC,l);	s[l]=0;
+	_GR_->CutOff(s);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_ternary_(uintptr_t *gr, int *enable)	{	_GR_->Ternary(*enable);	}
+void MGL_EXPORT mgl_set_range_val_(uintptr_t *gr, const char *dir, mreal *v1, mreal *v2,int)
+{	mgl_set_range_val(_GR_,*dir,*v1,*v2);	}
+void MGL_EXPORT mgl_add_range_val_(uintptr_t *gr, const char *dir, mreal *v1, mreal *v2,int)
+{	mgl_add_range_val(_GR_,*dir,*v1,*v2);	}
+void MGL_EXPORT mgl_set_range_dat_(uintptr_t *gr, const char *dir, uintptr_t *a, int *add,int)
+{	mgl_set_range_dat(_GR_,*dir,_DA_(a),*add);	}
+void MGL_EXPORT mgl_set_ranges_(uintptr_t *gr, mreal *x1, mreal *x2, mreal *y1, mreal *y2, mreal *z1, mreal *z2)
+{	_GR_->SetRanges(*x1,*x2,*y1,*y2,*z1,*z2);	}
+void MGL_EXPORT mgl_set_auto_ranges_(uintptr_t *gr, mreal *x1, mreal *x2, mreal *y1, mreal *y2, mreal *z1, mreal *z2, mreal *c1, mreal *c2)
+{	_GR_->SetAutoRanges(*x1,*x2,*y1,*y2,*z1,*z2,*c1,*c2);	}
+void MGL_EXPORT mgl_set_func_(uintptr_t *gr, const char *EqX,const char *EqY,const char *EqZ,const char *EqA,int lx,int ly,int lz,int la)
+{
+	char *sx=new char[lx+1];	memcpy(sx,EqX,lx);	sx[lx]=0;
+	char *sy=new char[ly+1];	memcpy(sy,EqY,ly);	sy[ly]=0;
+	char *sz=new char[lz+1];	memcpy(sz,EqZ,lz);	sz[lz]=0;
+	char *sa=new char[la+1];	memcpy(sa,EqA,la);	sa[la]=0;
+	_GR_->SetFunc(sx,sy,sz,sa);
+	delete []sx;	delete []sy;	delete []sz;	delete []sa;
+}
+void MGL_EXPORT mgl_set_coor_(uintptr_t *gr, int *how)
+{	_GR_->SetCoor(*how);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_tick_rotate(HMGL gr, int enable){	gr->SetTickRotate(enable);	}
+void MGL_EXPORT mgl_set_tick_skip(HMGL gr, int enable)	{	gr->SetTickSkip(enable);	}
+void MGL_EXPORT mgl_set_tick_rotate_(uintptr_t *gr,int *enable){	_GR_->SetTickRotate(*enable);	}
+void MGL_EXPORT mgl_set_tick_skip_(uintptr_t *gr, int *enable)	{	_GR_->SetTickSkip(*enable);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_rotated_text(HMGL gr, int enable)	{	gr->SetRotatedText(enable);	}
+void MGL_EXPORT mgl_set_mark_size(HMGL gr, double size)		{	gr->SetMarkSize(size);	}
+void MGL_EXPORT mgl_set_arrow_size(HMGL gr, double size)	{	gr->SetArrowSize(size);	}
+void MGL_EXPORT mgl_set_font_size(HMGL gr, double size)		{	gr->SetFontSize(size);	}
+void MGL_EXPORT mgl_set_font_def(HMGL gr, const char *fnt)	{	gr->SetFontDef(fnt);	}
+void MGL_EXPORT mgl_load_font(HMGL gr, const char *name, const char *path)
+{	gr->LoadFont(name,path);	}
+void MGL_EXPORT mgl_copy_font(HMGL gr, HMGL gr_from)	{	gr->CopyFont(gr_from);	}
+void MGL_EXPORT mgl_restore_font(HMGL gr)	{	gr->RestoreFont();	}
+void MGL_EXPORT mgl_define_symbol(HMGL gr, char id, HCDT x, HCDT y)	{	gr->DefineGlyph(x,y,id);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_bar_width_(uintptr_t *gr, mreal *width)	{	_GR_->SetBarWidth(*width);	}
+void MGL_EXPORT mgl_set_rotated_text_(uintptr_t *gr, int *rotated)	{	_GR_->SetRotatedText(*rotated);	}
+void MGL_EXPORT mgl_set_mark_size_(uintptr_t *gr, mreal *size)		{	_GR_->SetMarkSize(*size);	}
+void MGL_EXPORT mgl_set_arrow_size_(uintptr_t *gr, mreal *size)	{	_GR_->SetArrowSize(*size);	}
+void MGL_EXPORT mgl_set_font_size_(uintptr_t *gr, mreal *size)		{	_GR_->SetFontSize(*size);	}
+void MGL_EXPORT mgl_set_font_def_(uintptr_t *gr, const char *name, int l)
+{	char *s=new char[l+1];		memcpy(s,name,l);	s[l]=0;
+	_GR_->SetFontDef(s);	delete []s;	}
+void MGL_EXPORT mgl_load_font_(uintptr_t *gr, char *name, char *path, int l,int n)
+{	char *s=new char[l+1];		memcpy(s,name,l);	s[l]=0;
+	char *d=new char[n+1];		memcpy(d,path,n);	d[n]=0;
+	_GR_->LoadFont(s,d);	delete []s;		delete []d;	}
+void MGL_EXPORT mgl_copy_font_(uintptr_t *gr, uintptr_t *gr_from)
+{	_GR_->CopyFont((mglBase *)(*gr_from));	}
+void MGL_EXPORT mgl_restore_font_(uintptr_t *gr)	{	_GR_->RestoreFont();	}
+void MGL_EXPORT mgl_define_symbol_(uintptr_t *gr, char *id, uintptr_t *x, uintptr_t *y, int)
+{	_GR_->DefineGlyph(_DA_(x),_DA_(y),id?*id:0);	}
+//-----------------------------------------------------------------------------
+extern mglFont mglDefFont;
+void MGL_EXPORT mgl_def_font(const char *name, const char *path)
+{	mglDefFont.Load(name,path);	}
+void MGL_EXPORT mgl_def_font_(const char *name, const char *path,int l,int n)
+{	char *s=new char[l+1];		memcpy(s,name,l);	s[l]=0;
+	char *d=new char[n+1];		memcpy(d,path,n);	d[n]=0;
+	mglDefFont.Load(name,path);	delete []s;		delete []d;	}
+//-----------------------------------------------------------------------------
+int MGL_EXPORT mgl_check_version(const char *ver)
+{	double v=0;	int r = sscanf(ver,"2.%lg",&v);
+	return r<1 || v>MGL_VER2;	}
+int MGL_EXPORT mgl_check_version_(const char *ver, int l)
+{	char *s=new char[l+1];		memcpy(s,ver,l);	s[l]=0;
+	int r=mgl_check_version(s);	delete []s;	return r;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_start_group(HMGL gr, const char *s)	{	gr->StartAutoGroup(s);	}
+void MGL_EXPORT mgl_end_group(HMGL gr)	{	gr->EndGroup();	}
+void MGL_EXPORT mgl_start_group_(uintptr_t *gr, const char *name,int l)
+{	char *s=new char[l+1];		memcpy(s,name,l);	s[l]=0;
+	_GR_->StartAutoGroup(s);	delete []s;	}
+void MGL_EXPORT mgl_end_group_(uintptr_t *gr)	{	_GR_->EndGroup();	}
+//-----------------------------------------------------------------------------
+#include <stdarg.h>
+bool mglTestMode=false;
+void MGL_EXPORT mgl_test_txt(const char *str, ...)
+{
+	if(mglTestMode)
+	{
+		char buf[256];
+		va_list lst;
+		va_start(lst,str);
+		vsnprintf(buf,256,str,lst);	buf[255]=0;
+		va_end(lst);
+		printf(_("TEST: %s\n"),buf);
+		fflush(stdout);
+	}
+}
+void MGL_EXPORT mgl_set_test_mode(int enable)	{	mglTestMode=enable;	}
+//---------------------------------------------------------------------------
+long MGL_EXPORT mgl_use_graph(HMGL gr, int inc)
+{	if(!gr)	return 0;	gr->InUse+=inc;	return gr->InUse;	}
+long MGL_EXPORT mgl_use_graph_(uintptr_t *gr, int *inc)
+{	return mgl_use_graph(_GR_,*inc);	}
+//---------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_ambbr(HMGL gr, double i)		{	gr->SetAmbient(i);	}
+void MGL_EXPORT mgl_set_ambbr_(uintptr_t *gr, mreal *i){	_GR_->SetAmbient(*i);	}
+//---------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_difbr(HMGL gr, double i)		{	gr->SetDiffuse(i);	}
+void MGL_EXPORT mgl_set_difbr_(uintptr_t *gr, mreal *i){	_GR_->SetDiffuse(*i);	}
+//---------------------------------------------------------------------------
+void MGL_EXPORT mgl_zoom_axis(HMGL gr, double x1,double y1,double z1,double c1,double x2,double y2,double z2,double c2)
+{	gr->ZoomAxis(mglPoint(x1,y1,z1,c1), mglPoint(x2,y2,z2,c2));	}
+void MGL_EXPORT mgl_zoom_axis_(uintptr_t *gr, mreal *x1, mreal *y1, mreal *z1, mreal *c1, mreal *x2, mreal *y2, mreal *z2, mreal *c2)
+{	_GR_->ZoomAxis(mglPoint(*x1,*y1,*z1,*c1), mglPoint(*x2,*y2,*z2,*c2));	}
+//---------------------------------------------------------------------------
+extern uint64_t mgl_mask_def[16];
+void MGL_EXPORT mgl_set_mask(char id, const char *mask)
+{
+	const char *msk = MGL_MASK_ID, *s = mglchr(msk, id);
+	if(s)
+	{
+		uint64_t val = (mask && *mask) ? strtoull(mask,NULL,16) : mgl_mask_def[s-msk];
+		mgl_mask_val[s-msk] = val;
+	}
+}
+void MGL_EXPORT mgl_set_mask_(const char *id, const char *mask,int,int l)
+{	char *s=new char[l+1];	memcpy(s,mask,l);	s[l]=0;	mgl_set_mask(*id,s);	delete []s;	}
+//---------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_mask_val(char id, uint64_t mask)
+{
+	const char *msk = MGL_MASK_ID, *s = mglchr(msk, id);
+	if(s)	mgl_mask_val[s-msk]=mask;
+}
+void MGL_EXPORT mgl_set_mask_val_(const char *id, uint64_t *mask,int)
+{	mgl_set_mask_val(*id,*mask);	}
+//---------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_mask_angle(HMGL gr, int angle)	{	gr->SetMaskAngle(angle);	}
+void MGL_EXPORT mgl_set_mask_angle_(uintptr_t *gr, int *angle)	{	_GR_->SetMaskAngle(*angle);	}
+//---------------------------------------------------------------------------
+void MGL_EXPORT mgl_ask_stop(HMGL gr, int stop)		{	gr->AskStop(stop);	}
+void MGL_EXPORT mgl_ask_stop_(uintptr_t *gr, int *stop){	_GR_->AskStop(*stop);	}
+int MGL_EXPORT mgl_need_stop(HMGL gr)			{	return gr->NeedStop();	}
+int MGL_EXPORT mgl_need_stop_(uintptr_t *gr)	{	return _GR_->NeedStop();}
+void MGL_EXPORT mgl_set_event_func(HMGL gr, void (*func)(void *), void *par)
+{	gr->SetEventFunc(func,par);	}
+//---------------------------------------------------------------------------
diff --git a/src/canvas.cpp b/src/canvas.cpp
new file mode 100644
index 0000000..12a1bb0
--- /dev/null
+++ b/src/canvas.cpp
@@ -0,0 +1,1208 @@
+/***************************************************************************
+ * canvas.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <limits.h>
+#include "mgl2/font.h"
+#include "mgl2/canvas.h"
+//-----------------------------------------------------------------------------
+MGL_EXPORT std::string mglGlobalMess;	///< Buffer for receiving global messages
+//-----------------------------------------------------------------------------
+mglCanvas::mglCanvas(int w, int h) : mglBase()
+{
+	clr(MGL_DISABLE_SCALE);
+	set(MGL_VECT_FRAME);	// NOTE: require a lot of memory!
+	Z=0;	C=G=G4=GB=0;	OI=0;	gif=0;
+	CurFrameId=0;	Delay=0.5;
+	Width=Height=Depth=0;	ObjId=-1;
+	fscl=ftet=0;		PlotId = _("frame");
+	pnt_col = 0;
+
+	ac.ch='c';
+	ax.dir.Set(1,0,0);	ax.a.Set(0,1,0);	ax.b.Set(0,0,1);	ax.ch='x';
+	ay.dir.Set(0,1,0);	ay.a.Set(1,0,0);	ay.b.Set(0,0,1);	ay.ch='y';
+	az.dir.Set(0,0,1);	az.a.Set(0,1,0);	az.b.Set(1,0,0);	az.ch='z';
+
+	SetSize(w,h);	SetQuality(MGL_DRAW_NORM);	DefaultPlotParam();
+}
+//-----------------------------------------------------------------------------
+mglCanvas::~mglCanvas()
+{
+	if(G)	{	delete []G;	delete []C;	delete []Z;	delete []G4;delete []GB;delete []OI;	}
+	if(pnt_col)	delete []pnt_col;
+}
+//-----------------------------------------------------------------------------
+long mglCanvas::PushDrwDat()
+{
+	mglDrawDat d;
+	d.Pnt=Pnt;	d.Prm=Prm;	d.Sub=Sub;	d.Glf=Glf;	d.Ptx=Ptx;	d.Txt=Txt;
+#pragma omp critical(drw)
+	MGL_PUSH(DrwDat,d,mutexDrw);
+	return DrwDat.size();
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::ResetFrames()	{	CurFrameId=0;	DrwDat.clear();	}
+//-----------------------------------------------------------------------------
+void mglCanvas::SetFrame(long i)
+{
+	if(get(MGL_VECT_FRAME) && i>=0 && i<long(DrwDat.size()))
+	{
+		Finish();	CurFrameId--;
+		mglDrawDat d;
+		d.Pnt=Pnt;	d.Prm=Prm;	d.Sub=Sub;	d.Glf=Glf;	d.Ptx=Ptx;	d.Txt=Txt;
+#if MGL_HAVE_PTHREAD
+		pthread_mutex_lock(&mutexDrw);
+		DrwDat[i] = d;
+		pthread_mutex_unlock(&mutexDrw);
+#else
+#pragma omp critical(drw)
+		DrwDat[i] = d;
+#endif
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::GetFrame(long k)
+{
+	if(k<0 || (size_t)k>=DrwDat.size())	return;
+	ClearFrame();
+	const mglDrawDat &d=DrwDat[k];
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_lock(&mutexPnt);
+	pthread_mutex_lock(&mutexPrm);
+	pthread_mutex_lock(&mutexSub);
+	pthread_mutex_lock(&mutexGlf);
+	pthread_mutex_lock(&mutexPtx);
+	pthread_mutex_lock(&mutexTxt);
+#endif
+#pragma omp critical
+	{	Pnt=d.Pnt;	Prm=d.Prm;	Sub=d.Sub;	Glf=d.Glf;	Ptx=d.Ptx;	Txt=d.Txt;	ClearPrmInd();	}
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_unlock(&mutexTxt);
+	pthread_mutex_unlock(&mutexPtx);
+	pthread_mutex_unlock(&mutexGlf);
+	pthread_mutex_unlock(&mutexSub);
+	pthread_mutex_unlock(&mutexPrm);
+	pthread_mutex_unlock(&mutexPnt);
+#endif
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::ClearFrame()
+{
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_lock(&mutexPnt);
+	pthread_mutex_lock(&mutexPrm);
+	pthread_mutex_lock(&mutexGlf);
+	pthread_mutex_lock(&mutexPtx);
+	pthread_mutex_lock(&mutexTxt);
+	pthread_mutex_lock(&mutexSub);
+	pthread_mutex_lock(&mutexLeg);
+	pthread_mutex_lock(&mutexGrp);
+	pthread_mutex_lock(&mutexAct);
+#endif
+
+#pragma omp critical
+	{
+		StartAutoGroup(NULL);
+		Leg.clear();	Grp.clear();	Act.clear();	Glf.clear();
+		Pnt.clear();	Prm.clear();	Ptx.clear();	ClearPrmInd();
+		Txt.clear();	Txt.reserve(3);
+//		mglBlock inpl = Sub[0];	Sub.clear();	Sub.push_back(inpl);	// NOTE at least one inplot should present!!!
+		mglTexture t1(MGL_DEF_PAL,-1), t2(MGL_DEF_SCH,1);
+		Txt.push_back(t1);	Txt.push_back(t2);	// No extra lock is required
+	}
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_unlock(&mutexAct);
+	pthread_mutex_unlock(&mutexGrp);
+	pthread_mutex_unlock(&mutexLeg);
+	pthread_mutex_unlock(&mutexSub);
+	pthread_mutex_unlock(&mutexTxt);
+	pthread_mutex_unlock(&mutexPtx);
+	pthread_mutex_unlock(&mutexGlf);
+	pthread_mutex_unlock(&mutexPrm);
+	pthread_mutex_unlock(&mutexPnt);
+#endif
+	ClfZB(true);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::ShowFrame(long k)
+{
+	if(k<0 || (size_t)k>=DrwDat.size())	return;
+	ClfZB();
+	size_t npnt=Pnt.size(), nglf=Glf.size(), nptx=Ptx.size(), ntxt=Txt.size(), nsub=Sub.size();
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_lock(&mutexPnt);
+	pthread_mutex_lock(&mutexPrm);
+	pthread_mutex_lock(&mutexSub);
+	pthread_mutex_lock(&mutexGlf);
+	pthread_mutex_lock(&mutexPtx);
+	pthread_mutex_lock(&mutexTxt);
+#endif
+#pragma omp critical
+	{
+		const mglDrawDat &d=DrwDat[k];
+		Glf.resize(d.Glf.size());	for(size_t i=0;i<d.Glf.size();i++)	Glf.push_back(d.Glf[i]);
+		Ptx.resize(d.Ptx.size());	for(size_t i=0;i<d.Ptx.size();i++)	Ptx.push_back(d.Ptx[i]);
+		Sub.resize(d.Sub.size());	for(size_t i=0;i<d.Sub.size();i++)	Sub.push_back(d.Sub[i]);
+		Txt.reserve(d.Pnt.size());	for(size_t i=0;i<d.Txt.size();i++)	Txt.push_back(d.Txt[i]);
+		Pnt.reserve(d.Pnt.size());	ClearPrmInd();
+		for(size_t i=0;i<d.Pnt.size();i++)
+		{
+			mglPnt p = d.Pnt[i]; 	p.c += ntxt;
+			if(p.sub>=0)	p.sub += nsub;
+			else	p.sub -= nsub;
+			Pnt.push_back(p);
+		}
+		Prm.reserve(d.Prm.size());
+		for(size_t i=0;i<d.Prm.size();i++)
+		{
+			mglPrim p = d.Prm[i];
+			p.n1 += npnt;
+
+			switch(p.type)
+			{
+			case 1:	p.n2 += npnt;	break;
+			case 2:	p.n2 += npnt;	p.n3 += npnt;	break;
+			case 3:	p.n2 += npnt;	p.n3 += npnt;	p.n4 += npnt;	break;
+			case 4: p.n4 += nglf;	break;
+			case 5:	p.n2 += npnt;	break;
+			case 6: p.n3 += nptx;	break;
+			}
+			Prm.push_back(p);
+		}
+	}
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_unlock(&mutexPnt);
+	pthread_mutex_unlock(&mutexPrm);
+	pthread_mutex_unlock(&mutexSub);
+	pthread_mutex_unlock(&mutexGlf);
+	pthread_mutex_unlock(&mutexPtx);
+	pthread_mutex_unlock(&mutexTxt);
+#endif
+}
+//-----------------------------------------------------------------------------
+const unsigned char *mglCanvas::GetBits()	{	Finish();	return G;	}
+//-----------------------------------------------------------------------------
+mreal mglCanvas::GetRatio() const	{	return inW/inH;	}
+//-----------------------------------------------------------------------------
+void mglCanvas::add_prim(mglPrim &a)
+{
+	if(a.n1>=0)
+	{
+		a.z = Pnt[a.n1].z;	// this is a bit less accurate but simpler for transformation
+		a.id = ObjId;
+#pragma omp critical(prm)
+		MGL_PUSH(Prm,a,mutexPrm);
+		ClearPrmInd();	clr(MGL_FINISHED);
+	}
+}
+//-----------------------------------------------------------------------------
+extern uint64_t mgl_mask_def[16];
+void mglCanvas::DefaultPlotParam()
+{
+/* NOTE: following variables and mutex will not be changed by DefaultPlotParam()
+long InUse;			///< Smart pointer (number of users)
+mglFont *fnt;		///< Class for printing vector text
+int Quality;		///< Quality of plot (0x0-pure, 0x1-fast; 0x2-fine; 0x4 - low memory)
+int Width;			///< Width of the image
+int Height;			///< Height of the image
+int Depth;			///< Depth of the image
+int CurFrameId;		///< Number of automaticle created frames
+GifFileType *gif;*/
+	SetDrawReg(1,1,0);		Perspective(0);	SetPenDelta(1);	SetBBox();
+	memcpy(mgl_mask_val, mgl_mask_def, 16*sizeof(uint64_t));	// should be > 16*8
+	ax.Clear();	ay.Clear();	az.Clear();	ac.Clear();
+	mgl_clear_fft();		DefMaskAn=0;	ResetMask();
+	SetTickRotate(true);	SetTickSkip(true);
+	SetWarn(mglWarnNone,"");	mglGlobalMess = "";
+	ObjId = -1;	HighId = INT_MIN;
+	SetFunc(0,0);	CutOff(0);	Ternary(0);
+	Stop=false;	event_cb = NULL;	event_par=NULL;
+	SetRanges(mglPoint(-1,-1,-1,-1), mglPoint(1,1,1,1));
+	SetOrigin(NAN,NAN,NAN,NAN);
+	SetBarWidth(0.7);	SetMarkSize(1);	SetArrowSize(1);
+	SetAlphaDef(0.5);		FontDef[0]=0;
+	SetTranspType(0);		SetMeshNum(0);	// NOTE: default MeshNum=0
+	SetRotatedText(true);	CurrPal = 0;
+	SetLegendMarks();		SetFontSize(4);
+	SetTuneTicks(3);		SetAmbient();	SetDiffuse();
+	clr(MGL_DISABLE_SCALE);
+	clr(MGL_USE_GMTIME);	clr(MGL_NOSUBTICKS);
+	SetDifLight(false);		SetReduceAcc(false);
+	SetDefScheme(MGL_DEF_SCH);	SetPalette(MGL_DEF_PAL);
+	SetPenPal("k-1");		Alpha(false);
+	stack.clear();	Restore();	DefColor('k');
+	SetPlotFactor(0);	Sub.clear();
+	InPlot(0,1,0,1,false);
+	SetTickLen(0);	SetCut(true);
+	AdjustTicks("xyzc",true);	Clf('w');
+
+	for(int i=0;i<10;i++)	{	AddLight(i, mglPoint(0,0,1));	Light(i,false);	}
+	Light(0,true);	Light(false);	SetDifLight(true);
+}
+//-----------------------------------------------------------------------------
+//	Optimal axis position
+//-----------------------------------------------------------------------------
+mreal mglCanvas::FindOptOrg(char dir, int ind) const
+{
+	static mglPoint px, py, pz;
+	static mglMatrix bb;
+	mglPoint nn[8]={mglPoint(0,0,0), mglPoint(0,0,1), mglPoint(0,1,0,0), mglPoint(0,1,1),
+					mglPoint(1,0,0), mglPoint(1,0,1), mglPoint(1,1,0), mglPoint(1,1,1)}, pp[8];
+	memcpy(pp, nn, 8*sizeof(mglPoint));
+	// do nothing if transformation matrix is the same
+	if(B!=bb)
+	{
+		bb = B;
+		for(long i=0;i<8;i++)	PostScale(&B,pp[i]);
+		// find point with minimal y
+		long j=0;
+		for(long i=1;i<8;i++)	if(pp[i].y<pp[j].y)	j=i;
+		pp[0]=pp[j];
+		// first select 3 closest points
+		pp[1].x=1-nn[j].x;	pp[1].y=nn[j].y;	pp[1].z=nn[j].z;	PostScale(&B,pp[1]);	pp[1]-=pp[0];
+		pp[2].x=nn[j].x;	pp[2].y=1-nn[j].y;	pp[2].z=nn[j].z;	PostScale(&B,pp[2]);	pp[2]-=pp[0];
+		pp[3].x=nn[j].x;	pp[3].y=nn[j].y;	pp[3].z=1-nn[j].z;	PostScale(&B,pp[3]);	pp[3]-=pp[0];
+		// find cosine of axis projection
+		mreal tx=fabs(pp[1].x/pp[1].y), ty=fabs(pp[2].x/pp[2].y), tz=fabs(pp[3].x/pp[3].y);
+		px=py=pz=nn[j];
+		if(tz==0 && (ty==0 || tx==0))	// (x- & z-) or (y- & z-) axis are vertical
+		{	if(pp[1].x>pp[2].x)	pz.y=1-pz.y;	else	pz.x=1-pz.x;	}
+		else if(tx==0 && ty==0)	// x- && y-axis is vertical
+		{
+			py.x=1-py.x;
+			if(pp[1].x>pp[3].x)
+			{	px.z=1-px.z;	py.z=1-py.z;	}
+		}
+		else if(tz<tx && tz<ty)	// z-axis is vertical
+		{	if(pp[1].x>pp[2].x)	pz.y=1-pz.y;	else	pz.x=1-pz.x;	}
+		else if(ty<tx && ty<tz)	// y-axis is vertical
+		{	if(pp[1].x>pp[3].x)	py.z=1-py.z;	else	py.x=1-py.x;	}
+		else if(tx<ty && tx<tz)	// x-axis is vertical
+		{	if(pp[3].x>pp[2].x)	px.y=1-px.y;	else	px.z=1-px.z;	}
+	}
+	// return to normal variables
+	mglPoint rx = Min+(Max-Min)/px;
+	mglPoint ry = Min+(Max-Min)/py;
+	mglPoint rz = Min+(Max-Min)/pz;
+	mreal res = rx.val(ind);
+	if(dir=='y')	res = ry.val(ind);
+	if(dir=='z')	res = rz.val(ind);
+	return res;
+}
+//-----------------------------------------------------------------------------
+mreal mglCanvas::GetOrgX(char dir, bool inv) const
+{
+	mreal res = Org.x;
+	if(mgl_isnan(res))
+	{
+		if(strchr("xyz",dir))	res = FindOptOrg(dir,0);
+		else if(dir=='t')		res = Min.x;
+		else res = B.b[6]>0 ? Max.x:Min.x;
+		if(inv)	res = Min.x+Max.x-res;
+	}
+	return res;
+}
+//-----------------------------------------------------------------------------
+mreal mglCanvas::GetOrgY(char dir, bool inv) const
+{
+	mreal res = Org.y;
+	if(mgl_isnan(res))
+	{
+		if(strchr("xyz",dir))	res = FindOptOrg(dir,1);
+		else if(dir=='t')	res = Min.y;
+		else res = B.b[7]>0 ? Max.y:Min.y;
+		if(inv)	res = Min.y+Max.y-res;
+	}
+	return res;
+}
+//-----------------------------------------------------------------------------
+mreal mglCanvas::GetOrgZ(char dir, bool inv) const
+{
+	mreal res = Org.z;
+	if(mgl_isnan(res))
+	{
+		if(strchr("xyz",dir))	res = FindOptOrg(dir,2);
+		else if(dir=='t')	res = Min.z;
+		else res = B.b[8]>0 ? Max.z:Min.z;
+		if(inv)	res = Min.z+Max.z-res;
+	}
+	return res;
+}
+//-----------------------------------------------------------------------------
+//	Put primitives
+//-----------------------------------------------------------------------------
+#define MGL_MARK_PLOT	if(Quality&MGL_DRAW_LMEM)	\
+						{	mglDrawReg d;	d.set(this,dr_x,dr_y,dr_p);	d.PenWidth=pw;	\
+							d.PDef = PDef;	d.pPos = pPos;	mark_draw(Pnt[p],type,size,&d);	}\
+						else{	mglPrim a;	a.w = pw;	a.s = size;	\
+							a.n1 = p;	a.n4 = type;	a.angl=0;	add_prim(a);	}
+void mglCanvas::mark_plot(long p, char type, mreal size)
+{
+	if(p<0 || mgl_isnan(Pnt[p].x) || mgl_isnan(size))	return;
+	if(type>128 || type<0)
+	{	smbl_plot(p,type-128,20*MarkSize*(size?fabs(size):1));	return;	}
+	long pp=p;
+	mreal pw = 0.15/sqrt(font_factor);
+	size = size?fabs(size):1;
+	size *= MarkSize*0.35*font_factor;
+	if(type=='.')	size = fabs(PenWidth)*sqrt(font_factor/400);
+	if(TernAxis&12) for(int i=0;i<4;i++)
+	{	p = ProjScale(i, pp);	MGL_MARK_PLOT	}
+	else	{	MGL_MARK_PLOT	}
+}
+//-----------------------------------------------------------------------------
+#define MGL_LINE_PLOT	if(Quality&MGL_DRAW_LMEM)	\
+						{	mglDrawReg d;	d.set(this,dr_x,dr_y,dr_p);	d.PenWidth=pw;	\
+							d.PDef = PDef;	d.pPos = pPos;	line_draw(Pnt[p1],Pnt[p2],&d);	}\
+						else	{	mglPrim a(1);	a.n3=PDef;	a.s = pPos;	\
+							a.n1 = p1;	a.n2 = p2;	a.w = pw;	a.angl=0;	add_prim(a);	}
+void mglCanvas::line_plot(long p1, long p2)
+{
+	if(PDef==0)	return;
+	if(p1<0 || p2<0 || mgl_isnan(Pnt[p1].x) || mgl_isnan(Pnt[p2].x) || SamePnt(p1,p2))	return;
+	if(p1>p2)	{	long kk=p1;	p1=p2;	p2=kk;	}	// rearrange start/end for proper dashing
+	long pp1=p1,pp2=p2;
+	mreal pw = fabs(PenWidth)*sqrt(font_factor/400);
+	if(TernAxis&12) for(int i=0;i<4;i++)
+	{	p1 = ProjScale(i, pp1);	p2 = ProjScale(i, pp2);
+		MGL_LINE_PLOT	}
+	else	{	MGL_LINE_PLOT	}
+	mreal d = hypot(Pnt[p1].x-Pnt[p2].x, Pnt[p1].y-Pnt[p2].y);
+	pPos = fmod(pPos+d/pw/1.5, 16);
+}
+//-----------------------------------------------------------------------------
+#define MGL_TRIG_PLOT	if(Quality&MGL_DRAW_LMEM)	\
+						{	mglDrawReg d;	d.set(this,dr_x,dr_y,dr_p);	d.PenWidth=pw;	\
+							trig_draw(Pnt[p1],Pnt[p2],Pnt[p3],true,&d);	}\
+						else{	mglPrim a(2);	a.n1 = p1;	a.n2 = p2;	a.n3 = p3;	\
+							a.m=mask;	a.angl=MaskAn;	a.w = pw;	add_prim(a);}
+void mglCanvas::trig_plot(long p1, long p2, long p3)
+{
+	if(p1<0 || p2<0 || p3<0 || mgl_isnan(Pnt[p1].x) || mgl_isnan(Pnt[p2].x) || mgl_isnan(Pnt[p3].x))	return;
+	if(SamePnt(p1,p2) || SamePnt(p1,p3))	return;
+	long pp1=p1,pp2=p2,pp3=p3;
+	mreal pw = fabs(PenWidth)*sqrt(font_factor/400);
+	if(TernAxis&12) for(int i=0;i<4;i++)
+	{	p1 = ProjScale(i, pp1);	p2 = ProjScale(i, pp2);
+		p3 = ProjScale(i, pp3);	MGL_TRIG_PLOT	}
+	else	{	MGL_TRIG_PLOT	}
+}
+//-----------------------------------------------------------------------------
+#define MGL_QUAD_PLOT	if(Quality&MGL_DRAW_LMEM)	\
+						{	mglDrawReg d;	d.set(this,dr_x,dr_y,dr_p);	d.PenWidth=pw;	\
+							quad_draw(Pnt[p1],Pnt[p2],Pnt[p3],Pnt[p4],&d);	}\
+						else{	mglPrim a(3);	a.n1 = p1;	a.n2 = p2;	a.n3 = p3;	a.n4 = p4;	\
+							a.m=mask;	a.angl=MaskAn;	a.w = pw;	add_prim(a);	}
+void mglCanvas::quad_plot(long p1, long p2, long p3, long p4)
+{
+	if(p1<0 || mgl_isnan(Pnt[p1].x) || SamePnt(p1,p2))	{	trig_plot(p4,p2,p3);	return;	}
+	if(p2<0 || mgl_isnan(Pnt[p2].x) || SamePnt(p2,p4))	{	trig_plot(p1,p4,p3);	return;	}
+	if(p3<0 || mgl_isnan(Pnt[p3].x) || SamePnt(p1,p3))	{	trig_plot(p1,p2,p4);	return;	}
+	if(p4<0 || mgl_isnan(Pnt[p4].x) || SamePnt(p3,p4))	{	trig_plot(p1,p2,p3);	return;	}
+	long pp1=p1,pp2=p2,pp3=p3,pp4=p4;
+	mreal pw = fabs(PenWidth)*sqrt(font_factor/400);
+	if(TernAxis&12) for(int i=0;i<4;i++)
+	{	p1 = ProjScale(i, pp1);	p2 = ProjScale(i, pp2);
+		p3 = ProjScale(i, pp3);	p4 = ProjScale(i, pp4);
+		MGL_QUAD_PLOT	}
+	else	{	MGL_QUAD_PLOT	}
+}
+//-----------------------------------------------------------------------------
+mreal mglCanvas::text_plot(long p,const wchar_t *text,const char *font,mreal size,mreal sh,mreal col,bool rot)
+{
+	if(p<0 || mgl_isnan(Pnt[p].x) || !text || *text==0)	return 0;
+	if(size<0)	size *= -FontSize;
+	if(!font)	font="";
+
+	if(TernAxis&4)	// text at projections
+	{
+		mreal res;
+		TernAxis = TernAxis&(~4);
+		for(int i=0;i<4;i++)
+			res = text_plot(ProjScale(i,p,true),text,font,size/2,sh,col,rot);
+		TernAxis = TernAxis|4;
+		return res;
+	}
+	else if(TernAxis&8)	// text at projections
+	{
+		mreal res;
+		TernAxis = TernAxis&(~8);
+//		for(int i=0;i<4;i++)
+			res = text_plot(ProjScale(3,p,true),text,font,size/2,sh,col,rot);
+		TernAxis = TernAxis|8;
+		return res;
+	}
+
+
+	mglPnt q=Pnt[p];
+	mreal ll = q.u*q.u+q.v*q.v;
+	bool inv=false;
+//	if(rot && (q.u<0 || (q.u==0 && q.v<0)))		// NOTE this is 1st part of rotation changes (see also GetGlyphPhi())
+//	{	q.u=-q.u;	q.v=-q.v;	q.w=-q.w;	inv=true;	}
+
+	mreal fsize=size/6.5*font_factor, h = fnt->Height(font)*fsize, w, shift = -(sh+0.02)*h;
+	// text drawing itself
+
+#if MGL_HAVE_PTHREAD
+pthread_mutex_lock(&mutexPtx);
+#endif
+#pragma omp critical(ptx)
+	{
+		Bt = B;	Bt.norot=(q.sub<0);	// NOTE check this later for mglInPlot
+		inv = inv ^ (strchr(font,'T')!=0);
+		if(strchr(font,'V'))	shift = 0.1*h;
+		else
+		{
+			if(inv)	shift = 0.2*h-shift;
+			shift += 0.015*h;	// Correction for glyph rotation around proper point
+		}
+
+		int align;
+		mreal col1=col, col2=col;
+		if(mglGetStyle(font,0,&align))
+		{
+			col1 = AddTexture(font);
+			col2 = col1+1/MGL_FEPSILON;
+		}
+		else if(col<0)
+			col1 = col2 = AddTexture(char(0.5-col));
+		align = align&3;
+
+		Bt.x = q.x;	Bt.y = q.y - shift;	Bt.z = q.z;
+		if(ll>0)
+		{
+			Bt.x += shift*q.v/sqrt(ll);	Bt.y += shift*(1-q.u/sqrt(ll));
+			if(q.u==0 && !get(MGL_ENABLE_RTEXT))	Bt.y -= 0.1*h;
+		}
+		fscl = fsize;	forg = p;
+
+		if(mgl_isnan(ll) || !get(MGL_ENABLE_RTEXT))	ftet = 0;
+		else if(ll)	ftet = -180*atan2(q.v,q.u)/M_PI;
+		else 	ftet = NAN;
+
+		if(!(Quality&MGL_DRAW_LMEM))	// add text itself
+		{
+			mglColor mc = Txt[long(col1)].GetC(col1);
+			mglPrim a(6);	a.n1 = p;
+			a.n2 = int(255*mc.r) + 256*(int(255*mc.g) + 256*int(255*mc.b));
+			a.n3 = Ptx.size();	Ptx.push_back(mglText(text,font));
+			a.s = size;	a.w = shift;	a.p=ftet;
+			add_prim(a);
+		}
+
+		q.c=col1;	q.t=0;	Txt[long(col1)].GetC(col1,0,q);
+		q.u = q.v = NAN;	q.a=q.t=q.ta=1;
+		memset(Bt.b,0,9*sizeof(mreal));
+		Bt.b[0] = Bt.b[4] = Bt.b[8] = fscl;
+		mreal opf = Bt.pf;
+		Bt.RotateN(ftet,0,0,1);	Bt.pf = Bt.norot?1.55:opf;
+		if(strchr(font,'@'))	// draw box around text
+		{
+			long k1,k2,k3,k4;	mglPnt pt;	mglPoint pp;
+			w = fnt->Width(text,font);	h = fnt->Height(font);
+			mreal d=-w*align/2.-h*0.2;	w+=h*0.4;
+			pt = q;	pp.Set(d,-h*0.4);		PostScale(&Bt,pp);
+			pt.x=pt.xx=pp.x;	pt.y=pt.yy=pp.y;
+#pragma omp critical(pnt)
+			{k1=Pnt.size();	MGL_PUSH(Pnt,pt,mutexPnt);}
+			pt = q;	pp.Set(w+d,-h*0.4);		PostScale(&Bt,pp);
+			pt.x=pt.xx=pp.x;	pt.y=pt.yy=pp.y;
+#pragma omp critical(pnt)
+			{k2=Pnt.size();	MGL_PUSH(Pnt,pt,mutexPnt);}
+			pt = q;	pp.Set(d,h*1.2);			PostScale(&Bt,pp);
+			pt.x=pt.xx=pp.x;	pt.y=pt.yy=pp.y;
+#pragma omp critical(pnt)
+			{k3=Pnt.size();	MGL_PUSH(Pnt,pt,mutexPnt);}
+			pt = q;	pp.Set(w+d,h*1.2);		PostScale(&Bt,pp);
+			pt.x=pt.xx=pp.x;	pt.y=pt.yy=pp.y;
+#pragma omp critical(pnt)
+			{k4=Pnt.size();	MGL_PUSH(Pnt,pt,mutexPnt);}
+			PDef = 0xffff;	// reset to solid line
+			line_plot(k1,k2);	line_plot(k1,k3);
+			line_plot(k4,k2);	line_plot(k4,k3);
+			mreal bl = AddTexture('w');
+			k1 = CopyNtoC(k1,bl);	k2 = CopyNtoC(k2,bl);
+			k3 = CopyNtoC(k3,bl);	k4 = CopyNtoC(k4,bl);
+			quad_plot(k1,k2,k3,k4);
+		}
+		const char *ffont = font;
+		while(*ffont && *ffont!=':')	ffont++;
+		fsize *= fnt->Puts(text,ffont,col1,col2)/2;
+	}
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_unlock(&mutexPtx);
+#endif
+	return fsize;
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Glyph(mreal x, mreal y, mreal f, int s, long j, mreal col)
+{
+	mglPrim a(4);	// NOTE: no projection since text_plot() did it
+	a.s = fscl/Bt.pf;
+	a.w = get(MGL_ENABLE_RTEXT)?ftet:1e5;
+	a.p = f/fnt->GetFact(s&3);
+	mreal cc = col<0 ? AddTexture(char(0.5-col)):col;
+	if(cc<0)	cc = CDef;
+	a.n1 = AddPnt(&Bt, mglPoint(Bt.x,Bt.y,Bt.z), cc, mglPoint(x,y,NAN), -1, -1);
+	a.n2 = forg; 	a.n3 = s;	a.n4 = AddGlyph(s,j);
+	if(a.n1<0)	return;
+
+	if(Quality&MGL_DRAW_LMEM)
+	{
+		mglDrawReg d;	d.set(this,dr_x,dr_y,dr_p);
+		d.PDef = s;		d.pPos = a.s;	d.PenWidth=a.w;
+		glyph_draw(a,&d);
+	}
+	else	add_prim(a);
+}
+//-----------------------------------------------------------------------------
+#define MGL_GLYPH_PLOT	if(Quality&MGL_DRAW_LMEM)	glyph_draw(a,&d);\
+						else	add_prim(a);
+void mglCanvas::smbl_plot(long p1, char id, double size)
+{
+	if(p1<0)	return;
+	mglPnt q=Pnt[p1];
+	mreal ftet=NAN, ll = q.u*q.u+q.v*q.v;
+	if(mgl_isnan(ll) || !get(MGL_ENABLE_RTEXT))	ftet = 0;
+	else if(ll)	ftet = -180*atan2(q.v,q.u)/M_PI;
+	long pk;	q.u=q.v=0;	q.w=NAN;
+#pragma omp critical(pnt)
+	{pk=Pnt.size();	MGL_PUSH(Pnt,q,mutexPnt);}
+
+	mglPrim a(4);
+	a.s = fabs(size)/6.5*font_factor/B.pf;
+	a.w = get(MGL_ENABLE_RTEXT)?ftet:1e5;
+	a.p = 1./(mgl_fact*mgl_fgen);
+	a.n1 = pk;	a.n2 = p1; 	a.n3 = size<0?4:0;	a.n4 = AddGlyph(id);
+	if(a.n4<0)	return;	// no symbol is defined by user
+	mglDrawReg d;	d.set(this,dr_x,dr_y,dr_p);
+	d.PDef = size<0?4:0;	d.pPos = a.s;	d.PenWidth=a.w;
+	if(TernAxis&12) for(int i=0;i<4;i++)
+	{	a.n1 = ProjScale(i, pk);	MGL_GLYPH_PLOT	}
+	else	{	MGL_GLYPH_PLOT	}
+}
+//-----------------------------------------------------------------------------
+//	Plot positioning functions
+//-----------------------------------------------------------------------------
+void mglCanvas::InPlot(mreal x1,mreal x2,mreal y1,mreal y2, const char *st)
+{
+	if(Width<=0 || Height<=0 || Depth<=0)	return;
+	if(!st)		{	InPlot(x1,x2,y1,y2,false);	return;	}
+	inW = Width*(x2-x1);	inH = Height*(y2-y1);
+	inX=Width*x1;	inY=Height*y1;	ZMin=1;
+
+	if(strchr(st,'T'))	{	y1*=0.9;	y2*=0.9;	}	// general title
+	bool r = !(strchr(st,'r') || strchr(st,'R') || strchr(st,'>') || strchr(st,'g'));
+	bool l = !(strchr(st,'l') || strchr(st,'L') || strchr(st,'<') || strchr(st,'g'));
+	bool u = !(strchr(st,'u') || strchr(st,'U') || strchr(st,'_') || strchr(st,'g'));
+	bool a = !(strchr(st,'a') || strchr(st,'A') || strchr(st,'^') || strchr(st,'g') || strchr(st,'t'));
+	// let use simplified scheme -- i.e. no differences between axis, colorbar and/or title
+	mreal xs=(x1+x2)/2, ys=(y1+y2)/2, f1 = 1.3, f2 = 1.1;
+	if(strchr(st,'#'))	f1=f2=1.55;
+	if(r && l)	{	x2=xs+(x2-xs)*f1;	x1=xs+(x1-xs)*f1;	}
+	else if(r)	{	x2=xs+(x2-xs)*f1;	x1=xs+(x1-xs)*f2;	}
+	else if(l)	{	x2=xs+(x2-xs)*f2;	x1=xs+(x1-xs)*f1;	}
+	if(a && u)	{	y2=ys+(y2-ys)*f1;	y1=ys+(y1-ys)*f1;	}
+	else if(a)	{	y2=ys+(y2-ys)*f1;	y1=ys+(y1-ys)*f2;	}
+	else if(u)	{	y2=ys+(y2-ys)*f2;	y1=ys+(y1-ys)*f1;	}
+
+	B.clear();
+	if(get(MGL_AUTO_FACTOR)) B.pf = 1.55;	// Automatically change plot factor !!!
+	B.x = (x1+x2)/2*Width;
+	B.y = (y1+y2)/2*Height;
+	B.b[0] = Width*(x2-x1);	B.b[4] = Height*(y2-y1);
+	B.b[8] = sqrt(B.b[0]*B.b[4]);
+	B.z = (1.f-B.b[8]/(2*Depth))*Depth;
+	B1=B;	font_factor = B.b[0] < B.b[4] ? B.b[0] : B.b[4];
+
+	mglBlock p;	p.AmbBr = AmbBr;	p.DifBr = DifBr;	p.B = B;
+	for(int i=0;i<10;i++)	p.light[i] = light[i];
+	p.id = ObjId;	p.n1=x1*Width;	p.n2=x2*Width;	p.n3=y1*Height;	p.n4=y2*Height;
+#pragma omp critical(sub)
+	MGL_PUSH(Sub,p,mutexSub);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::InPlot(mglMatrix &M,mreal x1,mreal x2,mreal y1,mreal y2, bool rel)
+{
+	if(Width<=0 || Height<=0 || Depth<=0)	return;
+	M.clear();
+	if(get(MGL_AUTO_FACTOR)) M.pf = 1.55;	// Automatically change plot factor !!!
+	if(rel)
+	{
+		M.x = B1.x + (x1+x2-1)/2*B1.b[0]/1.55;
+		M.y = B1.y + (y1+y2-1)/2*B1.b[4]/1.55;
+		M.b[0] = B1.b[0]*(x2-x1);	M.b[4] = B1.b[4]*(y2-y1);
+		M.b[8] = sqrt(M.b[0]*M.b[4]);
+		M.z = B1.z + (1.f-M.b[8]/(2*Depth))*B1.b[8];
+	}
+	else
+	{
+		M.x = (x1+x2)/2*Width;
+		M.y = (y1+y2)/2*Height;
+		M.b[0] = Width*(x2-x1);	M.b[4] = Height*(y2-y1);
+		M.b[8] = sqrt(M.b[0]*M.b[4]);
+		M.z = (1.f-M.b[8]/(2*Depth))*Depth;
+		B1=M;
+	}
+	inW=M.b[0];	inH=M.b[4];	ZMin=1;
+	inX=Width*x1;	inY=Height*y1;
+	font_factor = M.b[0] < M.b[4] ? M.b[0] : M.b[4];
+
+	mglBlock p;	p.AmbBr = AmbBr;	p.DifBr = DifBr;	p.B = M;
+	for(int i=0;i<10;i++)	p.light[i] = light[i];
+	p.id = ObjId;	p.n1=x1*Width;	p.n2=x2*Width;	p.n3=y1*Height;	p.n4=y2*Height;
+#pragma omp critical(sub)
+	MGL_PUSH(Sub,p,mutexSub);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::StickPlot(int num, int id, mreal tet, mreal phi)
+{
+	mreal dx,dy,wx,wy,x1,y1,f1,f2;
+	mglPoint p1(-1,0,0), p2(1,0,0);
+	// first iteration
+	InPlot(0,1,0,1,true);	Rotate(tet, phi);
+	PostScale(GetB(),p1);	PostScale(GetB(),p2);	f1 = B.pf;
+	dx=(p2.x-p1.x)*1.55/B1.b[0];	dy=(p2.y-p1.y)*1.55/B1.b[4];
+	wx=1/(1+(num-1)*fabs(dx));		wy=1/(1+(num-1)*fabs(dy));
+	x1=dx>0?dx*id:dx*(id-num+1);	y1=dy>0?dy*id:dy*(id-num+1);
+	InPlot(x1*wx,(x1+1)*wx,y1*wy,(y1+1)*wy,true);	Rotate(tet,phi);
+	f2 = B.pf;	dx*=f1/f2;	dy*=f1/f2;	// add correction due to PlotFactor
+	wx=1/(1+(num-1)*fabs(dx));		wy=1/(1+(num-1)*fabs(dy));
+	x1=dx>0?dx*id:dx*(id-num+1);	y1=dy>0?dy*id:dy*(id-num+1);
+	InPlot(x1*wx,(x1+1)*wx,y1*wy,(y1+1)*wy,true);	Rotate(tet,phi);
+	f1=f2;	f2 = B.pf;	dx*=f1/f2;	dy*=f1/f2;	// add correction due to PlotFactor
+	wx=1/(1+(num-1)*fabs(dx));		wy=1/(1+(num-1)*fabs(dy));
+	x1=dx>0?dx*id:dx*(id-num+1);	y1=dy>0?dy*id:dy*(id-num+1);
+	InPlot(x1*wx,(x1+1)*wx,y1*wy,(y1+1)*wy,true);	Rotate(tet,phi);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Rotate(mreal tetz,mreal tetx,mreal tety)
+{
+	B.Rotate(tetz,tetx,tety);
+	if(get(MGL_AUTO_FACTOR))
+	{
+		mreal w=(fabs(B.b[3])+fabs(B.b[4])+fabs(B.b[5]))/B1.b[4];
+		mreal h=(fabs(B.b[0])+fabs(B.b[1])+fabs(B.b[2]))/B1.b[0];
+		B.pf = 1.55+0.6147*(w<h ? (h-1):(w-1));
+	}
+	size_t n = Sub.size();	if(n>0)	Sub[n-1].B = B;
+}
+//-----------------------------------------------------------------------------
+void mglMatrix::Rotate(mreal tetz,mreal tetx,mreal tety)
+{
+//	RotateN(TetX,1.,0.,0.);
+//	RotateN(TetY,0.,1.,0.);
+//	RotateN(TetZ,0.,0.,1.);
+	mreal R[9], O[9];
+	mreal cx=cos(tetx*M_PI/180), sx=-sin(tetx*M_PI/180), cy=cos(tety*M_PI/180), sy=-sin(tety*M_PI/180), cz=cos(tetz*M_PI/180), sz=-sin(tetz*M_PI/180);
+	R[0] = cx*cy;			R[1] = -cy*sx;			R[2] = sy;
+	R[3] = cx*sy*sz+cz*sx;	R[4] = cx*cz-sx*sy*sz;	R[5] =-cy*sz;
+	R[6] = sx*sz-cx*cz*sy;	R[7] = cx*sz+cz*sx*sy;	R[8] = cy*cz;
+	memcpy(O,b,9*sizeof(mreal));
+	b[0] = R[0]*O[0] + R[3]*O[1] + R[6]*O[2];
+	b[1] = R[1]*O[0] + R[4]*O[1] + R[7]*O[2];
+	b[2] = R[2]*O[0] + R[5]*O[1] + R[8]*O[2];
+	b[3] = R[0]*O[3] + R[3]*O[4] + R[6]*O[5];
+	b[4] = R[1]*O[3] + R[4]*O[4] + R[7]*O[5];
+	b[5] = R[2]*O[3] + R[5]*O[4] + R[8]*O[5];
+	b[6] = R[0]*O[6] + R[3]*O[7] + R[6]*O[8];
+	b[7] = R[1]*O[6] + R[4]*O[7] + R[7]*O[8];
+	b[8] = R[2]*O[6] + R[5]*O[7] + R[8]*O[8];
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::RotateN(mreal Tet,mreal x,mreal y,mreal z)
+{
+	B.RotateN(Tet,x,y,z);
+	if(get(MGL_AUTO_FACTOR))
+	{
+		mreal w=(fabs(B.b[3])+fabs(B.b[4])+fabs(B.b[5]))/B1.b[4];
+		mreal h=(fabs(B.b[0])+fabs(B.b[1])+fabs(B.b[2]))/B1.b[0];
+		B.pf = 1.55+0.6147*(w<h ? (h-1):(w-1));
+	}
+	size_t n = Sub.size();	if(n>0)	Sub[n-1].B = B;
+}
+//-----------------------------------------------------------------------------
+void mglMatrix::RotateN(mreal Tet,mreal vx,mreal vy,mreal vz)
+{
+	mreal R[9],T[9],c=cos(Tet*M_PI/180),s=-sin(Tet*M_PI/180),r=1-c,n=sqrt(vx*vx+vy*vy+vz*vz);
+	vx/=n;	vy/=n;	vz/=n;
+	T[0] = vx*vx*r+c;		T[1] = vx*vy*r-vz*s;	T[2] = vx*vz*r+vy*s;
+	T[3] = vx*vy*r+vz*s;	T[4] = vy*vy*r+c;		T[5] = vy*vz*r-vx*s;
+	T[6] = vx*vz*r-vy*s;	T[7] = vy*vz*r+vx*s;	T[8] = vz*vz*r+c;
+	memcpy(R,b,9*sizeof(mreal));
+	b[0] = T[0]*R[0] + T[3]*R[1] + T[6]*R[2];
+	b[1] = T[1]*R[0] + T[4]*R[1] + T[7]*R[2];
+	b[2] = T[2]*R[0] + T[5]*R[1] + T[8]*R[2];
+	b[3] = T[0]*R[3] + T[3]*R[4] + T[6]*R[5];
+	b[4] = T[1]*R[3] + T[4]*R[4] + T[7]*R[5];
+	b[5] = T[2]*R[3] + T[5]*R[4] + T[8]*R[5];
+	b[6] = T[0]*R[6] + T[3]*R[7] + T[6]*R[8];
+	b[7] = T[1]*R[6] + T[4]*R[7] + T[7]*R[8];
+	b[8] = T[2]*R[6] + T[5]*R[7] + T[8]*R[8];
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::View(mreal tetx,mreal tetz,mreal tety)
+{	Bp.Rotate(-tetz,-tetx,-tety);	}
+//-----------------------------------------------------------------------------
+void mglCanvas::Zoom(mreal x1, mreal y1, mreal x2, mreal y2)
+{
+	Bp.pf=0;	Bp.clear();		ClfZB();
+	if(x1==x2 || y1==y2)	{	x1=y1=0;	x2=y2=1;	}
+	x1=2*x1-1;	x2=2*x2-1;	y1=2*y1-1;	y2=2*y2-1;
+	Bp.b[0]=2/fabs(x2-x1);	Bp.b[4]=2/fabs(y2-y1);
+	Bp.x=(x1+x2)/fabs(x2-x1);Bp.y=(y1+y2)/fabs(y2-y1);
+}
+//-----------------------------------------------------------------------------
+int mglCanvas::GetSplId(long x,long y) const
+{
+	long id=-1;
+	for(long i=Sub.size()-1;i>=0;i--)
+	{
+		const mglBlock &p = Sub[i];
+		if(p.n1<=x && p.n2>=x && p.n3<=y && p.n4>=y)
+		{	id=p.id;	break;	}
+	}
+	return id;
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Aspect(mreal Ax,mreal Ay,mreal Az)
+{
+	if(mgl_isnan(Ax))
+	{
+		mreal dy = (Max.y-Min.y), dx = (Max.x-Min.x), dz = (Max.z-Min.z);
+		if(mgl_islog(Min.x,Max.x) && fx)	dx = log10(Max.x/Min.x);
+		if(mgl_islog(Min.y,Max.y) && fy)	dy = log10(Max.y/Min.y);
+		if(mgl_islog(Min.z,Max.z) && fz)	dz = log10(Max.z/Min.z);
+		mreal gy=exp(M_LN10*floor(0.5+log10(fabs(dy/dx))));
+		mreal gz=exp(M_LN10*floor(0.5+log10(fabs(dz/dx))));
+		if(Ay>0)	gy*=Ay;
+		if(Az>0)	gz*=Az;
+		Ax = inH*dx;	Ay = inW*dy*gy;	Az = sqrt(inW*inH)*dz*gz;
+	}
+	mreal a = fabs(Ax) > fabs(Ay) ? fabs(Ax) : fabs(Ay);
+	a = a > fabs(Az) ? a : fabs(Az);
+	if(a==0)	{	SetWarn(mglWarnZero,"Aspect");	return;	}
+	Ax/=a;	Ay/=a;	Az/=a;
+	B.b[0] *= Ax;	B.b[3] *= Ax;	B.b[6] *= Ax;
+	B.b[1] *= Ay;	B.b[4] *= Ay;	B.b[7] *= Ay;
+	B.b[2] *= Az;	B.b[5] *= Az;	B.b[8] *= Az;
+	size_t n = Sub.size();	if(n>0)	Sub[n-1].B = B;
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Shear(mreal Sx,mreal Sy)
+{
+	mreal R[6], Fx=1+fabs(Sx)*inH/inW, Fy=1+fabs(Sy)*inW/inH;
+	memcpy(R,B.b,6*sizeof(mreal));
+	B.b[0] = (R[0]+Sx*R[3])/Fx;	B.b[1] = (R[1]+Sx*R[4])/Fx;	B.b[2] = (R[2]+Sx*R[5])/Fx;
+	B.b[3] = (R[3]+Sy*R[0])/Fy;	B.b[4] = (R[4]+Sy*R[1])/Fy;	B.b[5] = (R[5]+Sy*R[2])/Fy;
+	size_t n = Sub.size();	if(n>0)	Sub[n-1].B = B;
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::ShearPlot(int num, int id, mreal sx, mreal sy, mreal xd, mreal yd)
+{
+	InPlot(0,1,0,1,true);
+	if(!(fabs(xd)<=1 && fabs(yd)<=1))	{	xd=1;	yd=0;	}
+	mreal wx,wy,dx,dy,wf,hf,x1,y1;
+	int ix=sy>=0?id:num-id-1, iy=sx>=0?id:num-id-1;
+	for(int i=0;i<3;i++)	// iterations to solve cubic equation
+	{
+		wx = fabs(sx)*inH/inW;	dx = xd + yd*wx;	wf = 1+wx+(num-1)*fabs(dx);
+		wy = fabs(sy)*inW/inH;	dy = yd + xd*wy;	hf = 1+wy+(num-1)*fabs(dy);
+		x1=(dx>=0?ix:(ix-num+1))*dx;
+		y1=(dy>=0?iy:(iy-num+1))*dy;
+		InPlot(x1/wf,(x1+1+wx)/wf,y1/hf,(y1+1+wy)/hf,true);
+	}
+	Shear(sx,sy);
+}
+//-----------------------------------------------------------------------------
+//	Lighting and transparency
+//-----------------------------------------------------------------------------
+void mglCanvas::Fog(mreal d, mreal dz)	{	FogDist=d;	FogDz = dz;	}
+//-----------------------------------------------------------------------------
+void mglCanvas::Light(int n, bool enable)
+{
+	if(n<0 || n>9)	{	SetWarn(mglWarnLId,"Light");	return;	}
+	light[n].n = enable;
+	size_t m=Sub.size();	if(m>0)	Sub[m-1].light[n].n = enable;
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::AddLight(int n, mglPoint r, mglPoint d, char col, mreal br, mreal ap)
+{
+	if(n<0 || n>9)	{	SetWarn(mglWarnLId,"AddLight");	return;	}
+	light[n].n = true;	light[n].a = ap>0?ap*ap:3;
+	light[n].b = br;	light[n].r = r;
+	light[n].d = d;		light[n].c.Set(col);
+	size_t m=Sub.size();	if(m>0)	Sub[m-1].light[n] = light[n];
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::arrow_plot(long n1, long n2, char st)
+{
+	if(n1<0 || n2<0 || !strchr("AVKSDTIOX",st))	return;
+	float ll = PenWidth*ArrowSize*0.35*font_factor;
+	uint64_t m=mask;	int ma=MaskAn;
+	ResetMask();
+	if((Quality&3)==3)
+		arrow_plot_3d(n1, n2, st, ll);
+	else
+		arrow_draw(n1, n2, st, ll);
+	mask=m;	MaskAn=ma;
+}
+//-----------------------------------------------------------------------------
+std::wstring MGL_EXPORT mgl_ftoa(double v, const char *fmt)
+{
+	char se[70], sf[70], ff[8]="%.3f", ee[8]="%.3e";
+	int dig=3;
+	for(const char *s="0123456789";*s;s++)	if(mglchr(fmt,*s))	dig = *s-'0';
+	if(mglchr(fmt,'E'))	ee[3] = 'E';
+	bool plus = mglchr(fmt,'+');
+	bool tex = mglchr(fmt,'F');
+	int fdig = int(log10(v));	fdig = fdig>0?(fdig<dig?dig-fdig:0):dig;
+	ff[2] = fdig+'0';	ee[2] = dig+'0';
+	snprintf(se,64,ee,v);	snprintf(sf,64,ff,v);
+	se[63] = sf[63] = 0;
+	long le=strlen(se), lf=strlen(sf), i;
+
+	// clear fix format
+	for(i=lf-1;i>=lf-fdig && sf[i]=='0';i--)	sf[i]=0;
+	if(sf[i]=='.')	sf[i]=0;
+	lf = strlen(sf);
+	// parse -nan numbers
+	if(!strcmp(sf,"-nan"))	memcpy(sf,"nan",4);
+
+
+	// clear exp format
+	int st = se[0]=='-'?1:0;
+	if(strcmp(sf,"nan"))
+	{
+		if(plus || se[3+st+dig]=='-')	// first remove zeros after 'e'
+		{
+			for(i=(dig>0?4:3)+st+dig;i<le && se[i]=='0';i++);
+			memmove(se+(dig>0?4:3)+st+dig,se+i,le-i+1);
+		}
+		else
+		{
+			for(i=(dig>0?3:2)+st+dig;i<le && (se[i]=='0' || se[i]=='+');i++);
+			memmove(se+(dig>0?3:2)+st+dig,se+i,le-i+1);
+		}
+	}
+	le=strlen(se);
+	// don't allow '+' at the end
+	if(le>0 && se[le-1]=='+')	se[--le]=0;
+	// remove single 'e'
+	if(le>0 && (se[le-1]=='e' || se[le-1]=='E'))	se[--le]=0;
+	for(i=1+st+dig;i>st && se[i]=='0';i--);	// remove final '0'
+	if(se[i]=='.')	i--;
+	memmove(se+i+1,se+2+st+dig,le-dig);	le=strlen(se);
+	// add '+' sign if required
+	if(plus && !strchr("-0niNI",se[0]))
+	{	memmove(se+1,se,le+1);	se[0]='+';
+		memmove(sf+1,sf,lf+1);	sf[0]='+';	}
+	if((lf>le && !mglchr(fmt,'f')) || !strcmp(sf,"0") || !strcmp(sf,"-0"))	strcpy(sf,se);
+	lf = strlen(sf);
+	std::wstring res;	res.reserve(lf+8);
+
+	if(mglchr(fmt,'-') && !(plus||tex))		// replace '-' by "\minus"
+		for(i=0;i<lf;i++)	res += sf[i];
+	else
+		for(i=0;i<lf;i++)	res += sf[i]!='-'?wchar_t(sf[i]):0x2212;
+	if(tex)	// TeX notation: 'e' -> "\cdot 10^{...}"
+	{
+		if(res[0]=='1' && (res[1]=='e' || res[1]=='E'))
+		{	res.replace(0,2,L"10^{");	res += L'}';	}
+		else if(wcschr(L"+-\u2212",res[0]) && res[1]=='1' && (res[2]=='e' || res[2]=='E'))
+ 		{	res.replace(1,2,L"10^{");	res += L'}';	}
+		else
+		{
+			size_t p;
+			for(p=1;p<res.length();p++)	if(res[p]==L'e' || res[p]==L'E')	break;
+			if(p<res.length())
+			{	res.replace(p,1,L"⋅10^{");	res += L'}';	}
+		}
+	}
+	return res;
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Legend(const std::vector<mglText> &leg, mreal x, mreal y, const char *font, const char *opt)
+{
+	long n=leg.size();
+	mreal iw, ih;
+	if(n<1)	{	SetWarn(mglWarnLeg,"Legend");	return;	}
+	mreal ll = SaveState(opt);	if(mgl_isnan(ll))	ll=0.1;
+	if(saved)	MarkSize=MSS;	// restore back size of marks
+	static int cgid=1;	StartGroup("Legend",cgid++);
+	if(ll<=0 || mgl_isnan(ll))	ll=0.1;
+	ll *=font_factor;
+	mreal size = 0.8*FontSize;
+	// setup font and parse absolute coordinates
+	if(!font)	font="#";
+	char *pA, *ff = new char[strlen(font)+3];
+	const char *fmt = strchr(font,':');
+	strcpy(ff,fmt?fmt:"");	strcat(ff,":L");	Push();
+	if((pA=strchr(ff,'A')))
+	{	*pA = ' ';	InPlot(0,1,0,1,false);	iw=B1.b[0];	ih=B1.b[4];	}
+	else if(mglchr(font,'A'))
+	{	InPlot(0,1,0,1,false);	iw=B1.b[0];	ih=B1.b[4];	}
+	else	{	iw=B1.b[0]/B1.pf;	ih=B1.b[4]/B1.pf;	}
+	// find sizes
+	mreal h=TextHeight(font,size);
+	mreal dx = 0.03*iw, dy = 0.03*ih, w=0, t, sp=TextWidth(" ",font,size);
+	for(long i=0;i<n;i++)		// find text length
+	{
+		t = TextWidth(leg[i].text.c_str(),font,size)+sp;
+		if(leg[i].stl.empty())	t -= ll;
+		w = w>t ? w:t;
+	}
+	w += ll+0.01*iw;	// add space for lines
+	long j = long((ih*0.95)/h);	if(j<1)	j=1;
+	long ncol = 1+(n-1)/j, nrow = (n+ncol-1)/ncol;
+	if(strchr(font,'-'))	// horizontal legend
+	{
+		j = long((iw*0.95)/w);	if(j<1)	j=1;
+		nrow = 1+(n-1)/j;
+		ncol = (n+nrow-1)/nrow;
+	}
+	if(mglchr(font,'^'))	// use "external" positioning
+	{
+		x = x>=0.5 ? x*iw : x*iw-w*ncol-2*dx;
+		y = y>=0.5 ? y*ih : y*ih-h*nrow-2*dy;
+	}
+	else
+	{
+		x *= iw-w*ncol-2*dx;
+		y *= ih-h*nrow-2*dy;
+	}
+	x += B.x-iw/2+dx;	y += B.y-ih/2+dy;
+	// draw it
+	mglPoint p,q(NAN,NAN,NAN);
+
+	mreal cc = AddTexture(font);
+	mreal c1,c2;	//=AddTexture(char(k1?k1:'w')), c2=AddTexture(char(k2?k2:'k'));
+	if(cc<2 || Txt[long(cc+0.5)].n==0)
+	{	c1 = AddTexture('w');	cc = c2 = AddTexture('k');	}
+	else switch(Txt[long(cc+0.5)].n)
+	{
+	case 1:	c1 = AddTexture('w');	c2 = AddTexture('k');	break;
+	case 2:	c1 = cc;	cc+=1/MGL_FEPSILON;	c2 = AddTexture('k');	break;
+	default:	c1 = cc;	c2 = cc+0.5;	cc += 1/MGL_FEPSILON;	break;
+	}
+	if((Flag&3)==2)	{	mreal tt=c1;	c2=c1;	c1=tt;	}
+
+	mglMatrix M=B;	M.norot=true;
+	if(strchr(font,'#'))	// draw bounding box
+	{
+		SetPenPal("k-");
+		long k1=AddPnt(&M,mglPoint(x,y,Depth/1.01),c1,q,1,0);
+		long k2=AddPnt(&M,mglPoint(x+w*ncol,y,Depth/1.01),c1,q,1,0);
+		long k3=AddPnt(&M,mglPoint(x,y+h*nrow,Depth/1.01),c1,q,1,0);
+		long k4=AddPnt(&M,mglPoint(x+w*ncol,y+h*nrow,Depth/1.01),c1,q,1,0);
+		quad_plot(k1,k2,k3,k4);
+		k1=CopyNtoC(k1,c2);	k2=CopyNtoC(k2,c2);
+		k3=CopyNtoC(k3,c2);	k4=CopyNtoC(k4,c2);
+		line_plot(k1,k2);	line_plot(k2,k4);
+		line_plot(k4,k3);	line_plot(k3,k1);
+	}
+	for(long i=0;i<n;i++)	// draw lines and legend
+	{
+		long iy=nrow-(i%nrow)-1,ix=i/nrow;
+		char m=SetPenPal(leg[i].stl.c_str());
+		long k1=AddPnt(&M,mglPoint(x+ix*w+0.1*ll,y+iy*h+0.45*h,Depth),CDef,q,-1,0);
+		long k2=AddPnt(&M,mglPoint(x+ix*w+0.9*ll,y+iy*h+0.45*h,Depth),CDef,q,-1,0);	pPos=0;
+		if(!leg[i].stl.empty())	line_plot(k1,k2);
+		if(m)	for(j=0;j<LegendMarks;j++)
+		{
+			p.Set(x+ix*w+0.1f*ll + (j+1)*0.8f*ll/(1.+LegendMarks),y+iy*h+0.45*h,Depth);
+			mark_plot(AddPnt(&M,p,CDef,q,-1,0),m);
+		}
+		p.Set(x+ix*w+((!leg[i].stl.empty())?ll:0.01*iw), y+iy*h+0.15*h, Depth);
+		text_plot(AddPnt(&M,p,-1,q,-1,0), leg[i].text.c_str(), ff, size,0,cc);
+	}
+	Pop();	EndGroup();	delete []ff;
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Table(mreal x, mreal y, HCDT val, const wchar_t *text, const char *frm, const char *opt)
+{
+//	if(x>=1) 	{	SetWarn(mglWarnSpc,"Table");	return;	}
+	long i,j,m=val->GetNy(),n=val->GetNx();
+//	mreal pos=SaveState(opt);
+	mreal vw = SaveState(opt);
+	static int cgid=1;	StartGroup("Table",cgid++);
+	bool grid = mglchr(frm,'#'), eqd = mglchr(frm,'='), lim = mglchr(frm,'|');
+	if(mgl_isnan(vw))	vw=1;	else 	lim = true;
+	if(!text)	text=L"";
+	x=x<0?0:x; 	y=y<0?0:y; 	y=y>1?1:y;
+//	if(vw>1-x)	vw=1-x;
+
+	char fmt[8]="3",ss[2]=" ";
+	for(const char *s="0123456789";*s;s++)	if(mglchr(frm,*s))	fmt[0]=*s;
+	for(const char *s="f+E-F";*s;s++)	if(mglchr(frm,*s))
+	{	ss[0] = *s;	strcat(fmt,ss);	}
+	std::vector<std::wstring> str;
+	for(i=0;i<n;i++)		// prepare list of strings first
+	{
+		std::wstring buf;
+		for(j=0;j+1<m;j++)
+			buf += mgl_ftoa(val->v(i,j),fmt)+L'\n';
+		buf += mgl_ftoa(val->v(i,m-1),fmt);
+		str.push_back(buf);
+	}
+
+	mreal sp=2*TextWidth(" ",frm,-1), w=*text ? sp+TextWidth(text,frm,-1):0, w1=0, ww, h;
+	for(i=0;i<n;i++)		// find width for given font size
+	{
+		ww = TextWidth(str[i].c_str(),frm,-1)+sp;
+		w1 = w1<ww?ww:w1;
+		if(!eqd)	w += ww;
+	}
+	if(eqd)	w += n*w1;
+	// reduce font size if table have to be inside inplot
+	mreal fsize=FontSize;
+	if(lim && w>vw*inW)
+	{	h=vw*inW/w;	SetFontSize(-h); 	w*=h; 	w1*=h;	sp*=h;	}
+	h = TextHeight(frm,-1);	// now we can determine text height
+
+	x = x*(inW-w)+B.x-inW/2;
+	y = y*(inH-h*m)+B.y-inH/2;
+
+	mglPoint p,q(NAN,NAN);
+	mreal xx,yy;
+	if(grid)	// draw bounding box
+	{
+		SetPenPal("k-");
+		long k1,k2;
+		k1=AddPnt(&B,mglPoint(x,y,Depth),-1,q,-1,0);
+		k2=AddPnt(&B,mglPoint(x,y+m*h,Depth),-1,q,-1,0);
+		line_plot(k1,k2);
+		ww = *text ? TextWidth(text,frm,-1)+sp:0;
+		k1=AddPnt(&B,mglPoint(x+ww,y,Depth),-1,q,-1,0);
+		k2=AddPnt(&B,mglPoint(x+ww,y+m*h,Depth),-1,q,-1,0);
+		line_plot(k1,k2);
+		for(i=0,xx=x+ww,yy=y;i<n;i++)
+		{
+			xx += eqd ? w1:(TextWidth(str[i].c_str(),frm,-1)+sp);
+			k1=AddPnt(&B,mglPoint(xx,yy,Depth),-1,q,-1,0);
+			k2=AddPnt(&B,mglPoint(xx,yy+m*h,Depth),-1,q,-1,0);
+			line_plot(k1,k2);
+		}
+		for(i=0,xx=x,yy=y;i<=m;i++)
+		{
+			k1=AddPnt(&B,mglPoint(xx,yy,Depth),-1,q,-1,0);
+			k2=AddPnt(&B,mglPoint(xx+w,yy,Depth),-1,q,-1,0);
+			line_plot(k1,k2);	yy += h;
+		}
+	}
+	int align;	mglGetStyle(frm, 0, &align);
+	if(*text)
+	{
+		ww = TextWidth(text,frm,-1)+sp;
+		long k1=AddPnt(&B,mglPoint(x+ww*align/2.,y+h*(m-0.9),Depth),-1,q,-1,0);
+		text_plot(k1,text,frm);
+	}
+	else 	ww = 0;
+	for(i=0,xx=x+ww,yy=y+h*(m-0.9);i<n;i++)	// draw lines and legend
+	{
+		ww = eqd ? w1:(TextWidth(str[i].c_str(),frm,-1)+sp);
+		long k1=AddPnt(&B,mglPoint(xx+ww*align/2.,yy,Depth),-1,q,-1,0);
+		text_plot(k1,str[i].c_str(),frm);	xx += ww;
+	}
+	FontSize = fsize;	EndGroup();
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Title(const char *title,const char *stl,mreal size)
+{
+	if(!title)	title="";
+	MGL_TO_WCS(title,Title(wcs, stl,size));
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Title(const wchar_t *title,const char *stl,mreal size)
+{
+	mreal s = size>0 ? size/FontSize:-size, h=TextHeight(stl,size)*s/2;
+	if(h>=inH)	{	SetWarn(mglWarnSpc,"Title");	return;	}
+	static int cgid=1;	StartGroup("Title",cgid++);
+	int align;
+	bool box=mglchr(stl,'#'), col = mglGetStyle(stl,0,&align);
+	align = align&3;
+	mreal y=inY+inH-h;
+	mglPoint p(inX + inW*align/2.,y,3*Depth),q(NAN,NAN,NAN);
+	mglMatrix M=B;	M.norot=true;
+	if(title)	text_plot(AddPnt(&M,p,-1,q,-1,0),title,stl,size);
+	if(box)	//	draw boungind box
+	{
+		mreal c1=AddTexture('w'), c2=col?AddTexture(stl):AddTexture('k');
+		if((Flag&3)==2 && !col)	{	mreal cc=c1;	c2=c1;	c1=cc;	}
+		else if((Flag&3)==2)	c1=AddTexture('k');
+		long k1,k2,k3,k4;
+		k1=AddPnt(&M,mglPoint(inX,y-h*0.4,3*Depth),c1,q,-1,0);
+		k2=AddPnt(&M,mglPoint(inX+inW,y-h*0.4,3*Depth),c1,q,-1,0);
+		k3=AddPnt(&M,mglPoint(inX,y+h,3*Depth),c1,q,-1,0);
+		k4=AddPnt(&M,mglPoint(inX+inW,y+h,3*Depth),c1,q,-1,0);
+		quad_plot(k1,k2,k3,k4);
+		k1=CopyNtoC(k1,c2);	k2=CopyNtoC(k2,c2);
+		k3=CopyNtoC(k3,c2);	k4=CopyNtoC(k4,c2);
+		line_plot(k1,k2);	line_plot(k2,k4);
+		line_plot(k4,k3);	line_plot(k3,k1);
+	}
+	B1.y -= h/2;	B1.b[4] -= h;	B=B1;
+	inH-=h;	font_factor = B.b[0] < B.b[4] ? B.b[0] : B.b[4];
+	EndGroup();
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::StartAutoGroup (const char *lbl)
+{
+	static int id=1;
+	if(lbl==NULL)	{	id=1;	grp_counter=0;	return;	}
+	grp_counter++;
+	if(grp_counter>1)	return;	// do nothing in "subgroups"
+	if(ObjId<0)	{	ObjId = -id;	id++;	}
+	size_t len = Grp.size();
+	if(ObjId>=0 && len>0 && ObjId!=Grp[len-1].Id)
+#pragma omp critical(grp)
+	{	MGL_PUSH(Grp,mglGroup(lbl,ObjId),mutexGrp);}
+	else if(ObjId<0)
+#pragma omp critical(grp)
+	{	MGL_PUSH(Grp,mglGroup(lbl,ObjId),mutexGrp);}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::EndGroup()
+{
+	LoadState();
+	if(Quality&MGL_DRAW_LMEM)
+	{
+		Pnt.clear();	Prm.clear();	Ptx.clear();	ClearPrmInd();
+		Glf.clear();	Act.clear(); 	Grp.clear();
+	}
+	if(grp_counter>0)	grp_counter--;
+}
+//-----------------------------------------------------------------------------
+int mglCanvas::IsActive(int xs, int ys,int &n)
+{
+	long i, h = (Width>Height ? Height:Width)/100;
+	for(i=0;i<(long)Act.size();i++)
+	{
+		const mglActivePos &p=Act[i];
+		if(abs(xs-p.x)<=h && abs(ys-p.y)<=h)
+		{	n=p.n;	return p.id;		}
+	}
+	n=-1;	return GetObjId(xs,ys);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Push()
+{
+#pragma omp critical(stk)
+	{MGL_PUSH(stack,B,mutexStk);}
+}
+//-----------------------------------------------------------------------------
diff --git a/src/canvas_cf.cpp b/src/canvas_cf.cpp
new file mode 100644
index 0000000..cc851c1
--- /dev/null
+++ b/src/canvas_cf.cpp
@@ -0,0 +1,518 @@
+/***************************************************************************
+ * canvas_cf.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include "mgl2/canvas.h"
+#include "mgl2/canvas_cf.h"
+#include "mgl2/eval.h"
+#include "mgl2/evalc.h"
+//-----------------------------------------------------------------------------
+#undef _GR_
+#define _GR_	((mglCanvas *)(*gr))
+//-----------------------------------------------------------------------------
+MGL_EXPORT const unsigned char *mgl_get_rgb(HMGL gr)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	return g?g->GetBits():0;	}
+MGL_EXPORT const unsigned char *mgl_get_rgba(HMGL gr)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	return g?g->GetRGBA():0;	}
+MGL_EXPORT const unsigned char* mgl_get_background(HMGL gr)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	return g?g->GetBackground():0;	}
+int MGL_EXPORT mgl_get_width(HMGL gr)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	return g?g->GetWidth():0;	}
+int MGL_EXPORT mgl_get_height(HMGL gr)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	return g?g->GetHeight():0;	}
+void MGL_EXPORT mgl_calc_xyz(HMGL gr, int xs, int ys, mreal *x, mreal *y, mreal *z)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);
+	mglPoint p = g?g->CalcXYZ(xs,ys):mglPoint(NAN,NAN,NAN);
+	*x = p.x;	*y = p.y;	*z = p.z;	}
+void MGL_EXPORT mgl_calc_scr(HMGL gr, double x, double y, double z, int *xs, int *ys)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->CalcScr(mglPoint(x,y,z),xs,ys);	}
+void MGL_EXPORT mgl_set_obj_id(HMGL gr, int id)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->SetObjId(id);	}
+int MGL_EXPORT mgl_get_obj_id(HMGL gr, int x, int y)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	return g?g->GetObjId(x,y):-1;	}
+int MGL_EXPORT mgl_get_spl_id(HMGL gr, int x, int y)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	return g?g->GetSplId(x,y):-1;	}
+//-----------------------------------------------------------------------------
+long MGL_EXPORT mgl_is_active(HMGL gr, int xs, int ys, int d)
+{
+	if(d<=0) 	d=1;
+	for(size_t i=0;i<gr->Act.size();i++)
+	{
+		const mglActivePos &p = gr->Act[i];
+		if(abs(xs-p.x)<d && abs(ys-p.y)<d)	return i;
+	}
+	return -1;
+}
+long MGL_EXPORT mgl_is_active_(uintptr_t *gr, int *xs, int *ys, int *d)
+{	return mgl_is_active(_GR_, *xs, *ys, *d);	}
+//-----------------------------------------------------------------------------
+int MGL_EXPORT mgl_new_frame(HMGL gr)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	return g?g->NewFrame():-1;	}
+void MGL_EXPORT mgl_end_frame(HMGL gr)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->EndFrame();	}
+int MGL_EXPORT mgl_get_num_frame(HMGL gr)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	return g?g->GetNumFrame():0;	}
+void MGL_EXPORT mgl_reset_frames(HMGL gr)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->ResetFrames();	}
+void MGL_EXPORT mgl_get_frame(HMGL gr, int i)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->GetFrame(i);	}
+void MGL_EXPORT mgl_set_frame(HMGL gr, int i)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->SetFrame(i);	}
+void MGL_EXPORT mgl_show_frame(HMGL gr, int i)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->ShowFrame(i);	}
+void MGL_EXPORT mgl_del_frame(HMGL gr, int i)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->DelFrame(i);	}
+void MGL_EXPORT mgl_clear_frame(HMGL gr)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->ClearFrame();	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_transp_type(HMGL gr, int type)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->SetTranspType(type);	}
+void MGL_EXPORT mgl_set_alpha(HMGL gr, int enable)	{	gr->Alpha(enable);	}
+void MGL_EXPORT mgl_set_gray(HMGL gr, int enable)	{	gr->set(enable, MGL_GRAY_MODE);	}
+void MGL_EXPORT mgl_set_fog(HMGL gr, double d, double dz)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Fog(d,dz);	}
+void MGL_EXPORT mgl_set_light(HMGL gr, int enable)	{	gr->Light(enable);	}
+void MGL_EXPORT mgl_set_attach_light(HMGL gr, int enable)	{	gr->AttachLight(enable);	}
+void MGL_EXPORT mgl_set_light_n(HMGL gr, int n, int enable)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Light(n, enable);	}
+void MGL_EXPORT mgl_add_light_ext(HMGL gr, int n, double x, double y, double z, char c, double br, double ap)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->AddLight(n,mglPoint(x,y,z),c,br,ap);	}
+void MGL_EXPORT mgl_add_light_loc(HMGL gr, int n, double x, double y, double z, double dx, double dy, double dz, char c, double br, double ap)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->AddLight(n,mglPoint(x,y,z),mglPoint(dx,dy,dz),c,br,ap);	}
+void MGL_EXPORT mgl_add_light(HMGL gr, int n, double x, double y, double z)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->AddLight(n,mglPoint(x,y,z));	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_mat_push(HMGL gr)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Push();	}
+void MGL_EXPORT mgl_mat_pop(HMGL gr)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Pop();	}
+void MGL_EXPORT mgl_clf(HMGL gr)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Clf();	}
+void MGL_EXPORT mgl_clf_chr(HMGL gr, char ch)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Clf(mglColor(ch));	}
+void MGL_EXPORT mgl_clf_rgb(HMGL gr, double r, double g, double b)
+{	mglCanvas *gg = dynamic_cast<mglCanvas *>(gr);	if(gg)	gg->Clf(mglColor(r,g,b));	}
+void MGL_EXPORT mgl_clf_str(HMGL gr, const char *col)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Clf(col);	}
+void MGL_EXPORT mgl_load_background(HMGL gr, const char *fn, double alpha)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->LoadBackground(fn,alpha);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_subplot_d(HMGL gr, int nx,int ny,int m,const char *style,double dx,double dy)
+{
+	double x1,x2,y1,y2;
+	int mx = m%nx, my = m/nx;
+	if(gr->get(MGL_AUTO_FACTOR))	{	dx /= 1.55;	dy /= 1.55;	}
+	else	{	dx /= 2;	dy /= 2;	}
+	x1 = (mx+dx)/nx;		x2 = (mx+1+dx)/nx;
+	y2 = 1.f-(my+dy)/ny;	y1 = 1.f-(my+1+dy)/ny;
+	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);
+	if(g)	g->InPlot(x1,x2,y1,y2,style);
+}
+void MGL_EXPORT mgl_subplot(HMGL gr, int nx,int ny,int m,const char *style)
+{	mgl_subplot_d(gr,nx,ny,m,style,0,0);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_multiplot_d(HMGL gr, int nx,int ny,int m,int dx,int dy,const char *style,double sx,double sy)
+{
+	double x1,x2,y1,y2;
+	int mx = m%nx, my = m/nx;
+	if(gr->get(MGL_AUTO_FACTOR))	{	sx /= 1.55;	sy /= 1.55;	}
+	else	{	sx /= 2;	sy /= 2;	}
+	dx = (dx<1 || dx+mx>nx) ? 1 : dx;
+	dy = (dy<1 || dy+my>ny) ? 1 : dy;
+	x1 = double(mx+sx)/nx;		x2 = double(mx+dx+sx)/nx;
+	y2 = 1-double(my+sy)/ny;	y1 = 1-double(my+dy+sy)/ny;
+	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->InPlot(x1,x2,y1,y2,style);
+}
+void MGL_EXPORT mgl_multiplot(HMGL gr, int nx,int ny,int m,int dx,int dy,const char *style)
+{	mgl_multiplot_d(gr,nx,ny,m,dx,dy,style,0,0);	}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_inplot(HMGL gr, double x1,double x2,double y1,double y2)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->InPlot(x1,x2,y1,y2,false);	}
+void MGL_EXPORT mgl_relplot(HMGL gr, double x1,double x2,double y1,double y2)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->InPlot(x1,x2,y1,y2,true);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_columnplot(HMGL gr, int num, int i, double dd)
+{
+	double w = 1./num;
+	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);
+	if(g)	g->InPlot(0,1,1-w*(i+1-dd/2),1-(i+dd/2)*w,true);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_gridplot(HMGL gr, int nx, int ny, int i, double dd)
+{
+	int ix=i%nx, iy=i/nx;
+	double wx = 1./nx, wy = 1./ny;
+	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);
+	if(g)	g->InPlot((ix+dd/2)*wx,wx*(ix+1-dd/2),1-wy*(iy+1-dd/2),1-(iy+dd/2)*wy,true);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_stickplot(HMGL gr, int num, int i, double tet, double phi)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->StickPlot(num, i, tet, phi);	}
+void MGL_EXPORT mgl_shearplot(HMGL gr, int num, int i, double sx, double sy, double xd, double yd)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->ShearPlot(num, i, sx, sy, xd, yd);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_aspect(HMGL gr, double Ax,double Ay,double Az)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Aspect(Ax,Ay,Az);	}
+void MGL_EXPORT mgl_shear(HMGL gr, double Sx,double Sy)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Shear(Sx,Sy);	}
+void MGL_EXPORT mgl_rotate(HMGL gr, double TetX,double TetZ,double TetY)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Rotate(TetX,TetZ,TetY);	}
+void MGL_EXPORT mgl_view(HMGL gr, double TetX,double TetZ,double TetY)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->View(TetX,TetZ,TetY);	}
+void MGL_EXPORT mgl_zoom(HMGL gr, double x1, double y1, double x2, double y2)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Zoom(x1,y1,x2,y2);	}
+void MGL_EXPORT mgl_rotate_vector(HMGL gr, double Tet,double x,double y,double z)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->RotateN(Tet,x,y,z);	}
+void MGL_EXPORT mgl_perspective(HMGL gr, double val)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Perspective(val);	}
+void MGL_EXPORT mgl_ask_perspective(HMGL gr, double val)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Perspective(val,false);	}
+void MGL_EXPORT mgl_title(HMGL gr, const char *title, const char *stl, double size)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Title(title,stl,size);	}
+void MGL_EXPORT mgl_titlew(HMGL gr, const wchar_t *title, const char *stl, double size)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Title(title,stl,size);	}
+//-----------------------------------------------------------------------------
+int MGL_EXPORT mgl_new_frame_(uintptr_t *gr)	{	return _GR_->NewFrame();	}
+void MGL_EXPORT mgl_end_frame_(uintptr_t *gr)	{	_GR_->EndFrame();	}
+int MGL_EXPORT mgl_get_num_frame_(uintptr_t *gr)	{	return _GR_->GetNumFrame();	}
+void MGL_EXPORT mgl_reset_frames_(uintptr_t *gr)	{	_GR_->ResetFrames();	}
+void MGL_EXPORT mgl_get_frame_(uintptr_t *gr, int *i)	{	_GR_->GetFrame(*i);	}
+void MGL_EXPORT mgl_set_frame_(uintptr_t *gr, int *i)	{	_GR_->SetFrame(*i);	}
+void MGL_EXPORT mgl_show_frame_(uintptr_t *gr, int *i)	{	_GR_->ShowFrame(*i);}
+void MGL_EXPORT mgl_del_frame_(uintptr_t *gr, int *i)	{	_GR_->DelFrame(*i);	}
+void MGL_EXPORT mgl_clear_frame_(uintptr_t *gr)			{	_GR_->ClearFrame();	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_transp_type_(uintptr_t *gr, int *type)		{	_GR_->SetTranspType(*type);	}
+void MGL_EXPORT mgl_set_alpha_(uintptr_t *gr, int *enable)			{	_GR_->Alpha(*enable);	}
+void MGL_EXPORT mgl_set_gray_(uintptr_t *gr, int *enable)			{	_GR_->set(*enable, MGL_GRAY_MODE);	}
+void MGL_EXPORT mgl_set_fog_(uintptr_t *gr, mreal *d, mreal *dz)	{	_GR_->Fog(*d, *dz);		}
+void MGL_EXPORT mgl_set_light_(uintptr_t *gr, int *enable)			{	_GR_->Light(*enable);	}
+void MGL_EXPORT mgl_set_attach_light_(uintptr_t *gr, int *enable)	{	_GR_->AttachLight(*enable);	}
+void MGL_EXPORT mgl_set_light_n_(uintptr_t *gr, int *n, int *enable)
+{	_GR_->Light(*n, *enable);	}
+void MGL_EXPORT mgl_add_light_(uintptr_t *gr, int *n, mreal *x, mreal *y, mreal *z)
+{	_GR_->AddLight(*n,mglPoint(*x,*y,*z));	}
+void MGL_EXPORT mgl_add_light_ext_(uintptr_t *gr, int *n, mreal *x, mreal *y, mreal *z, char *c, mreal *br, mreal *ap, int)
+{	_GR_->AddLight(*n,mglPoint(*x,*y,*z),*c,*br,*ap);	}
+void MGL_EXPORT mgl_add_light_loc_(uintptr_t *gr, int *n, mreal *x, mreal *y, mreal *z, mreal *dx, mreal *dy, mreal *dz, char *c, mreal *br, mreal *ap, int)
+{	_GR_->AddLight(*n,mglPoint(*x,*y,*z),mglPoint(*dx,*dy,*dz),*c,*br,*ap);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_mat_push_(uintptr_t *gr)	{	_GR_->Push();	}
+void MGL_EXPORT mgl_mat_pop_(uintptr_t *gr)	{	_GR_->Pop();	}
+void MGL_EXPORT mgl_clf_(uintptr_t *gr)		{	_GR_->Clf();	}
+void MGL_EXPORT mgl_clf_chr_(uintptr_t *gr, const char *ch, int)
+{	_GR_->Clf(mglColor(*ch));	}
+void MGL_EXPORT mgl_clf_rgb_(uintptr_t *gr, mreal *r, mreal *g, mreal *b)
+{	_GR_->Clf(mglColor(*r,*g,*b));	}
+void MGL_EXPORT mgl_clf_str_(uintptr_t *gr, const char *col, int l)
+{	char *s=new char[l+1];	memcpy(s,col,l);	s[l]=0;
+	mgl_clf_str(_GR_,s);	delete []s;	}
+void MGL_EXPORT mgl_load_background_(uintptr_t *gr, const char *fn, mreal *a, int l)
+{	char *s=new char[l+1];	memcpy(s,fn,l);	s[l]=0;
+	mgl_load_background(_GR_,s,*a);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_subplot_d_(uintptr_t *gr, int *nx,int *ny,int *m,const char *st, mreal *dx, mreal *dy,int l)
+{	char *s=new char[l+1];	memcpy(s,st,l);	s[l]=0;
+	mgl_subplot_d(_GR_,*nx,*ny,*m,s,*dx,*dy);	delete []s;	}
+void MGL_EXPORT mgl_subplot_(uintptr_t *gr, int *nx,int *ny,int *m,const char *st,int l)
+{	char *s=new char[l+1];	memcpy(s,st,l);	s[l]=0;
+	mgl_subplot(_GR_,*nx,*ny,*m,s);	delete []s;	}
+void MGL_EXPORT mgl_multiplot_(uintptr_t *gr, int *nx,int *ny,int *m,int *dx,int *dy,const char *st,int l)
+{	char *s=new char[l+1];	memcpy(s,st,l);	s[l]=0;
+	mgl_multiplot(_GR_,*nx,*ny,*m,*dx,*dy,s);	delete []s;	}
+void MGL_EXPORT mgl_multiplot_d_(uintptr_t *gr, int *nx,int *ny,int *m,int *dx,int *dy,const char *st, mreal *sx, mreal *sy,int l)
+{	char *s=new char[l+1];	memcpy(s,st,l);	s[l]=0;
+	mgl_multiplot_d(_GR_,*nx,*ny,*m,*dx,*dy,s, *sx, *sy);	delete []s;	}
+void MGL_EXPORT mgl_inplot_(uintptr_t *gr, mreal *x1, mreal *x2, mreal *y1, mreal *y2)
+{	_GR_->InPlot(*x1,*x2,*y1,*y2,false);	}
+void MGL_EXPORT mgl_relplot_(uintptr_t *gr, mreal *x1, mreal *x2, mreal *y1, mreal *y2)
+{	_GR_->InPlot(*x1,*x2,*y1,*y2,true);	}
+void MGL_EXPORT mgl_columnplot_(uintptr_t *gr, int *num, int *i, mreal *d)
+{	mgl_columnplot(_GR_,*num,*i,*d);	}
+void MGL_EXPORT mgl_gridplot_(uintptr_t *gr, int *nx, int *ny, int *i, mreal *d)
+{	mgl_gridplot(_GR_,*nx,*ny,*i,*d);	}
+void MGL_EXPORT mgl_stickplot_(uintptr_t *gr, int *num, int *i, mreal *tet, mreal *phi)
+{	_GR_->StickPlot(*num, *i, *tet, *phi);	}
+void MGL_EXPORT mgl_shearplot_(uintptr_t *gr, int *num, int *i, mreal *sy, mreal *sx, mreal *xd, mreal *yd)
+{	_GR_->ShearPlot(*num,*i,*sx,*sy,*xd,*yd);	}
+
+void MGL_EXPORT mgl_title_(uintptr_t *gr, const char *title, const char *stl, mreal *size, int l,int m)
+{	char *t=new char[l+1];	memcpy(t,title,l);	t[l]=0;
+	char *s=new char[m+1];	memcpy(s,stl,m);	s[m]=0;
+	_GR_->Title(t,s,*size);	delete []s;	delete []t;	}
+void MGL_EXPORT mgl_aspect_(uintptr_t *gr, mreal *Ax, mreal *Ay, mreal *Az)
+{	_GR_->Aspect(*Ax,*Ay,*Az);	}
+void MGL_EXPORT mgl_shear_(uintptr_t *gr, mreal *Sx, mreal *Sy)
+{	_GR_->Shear(*Sx,*Sy);	}
+void MGL_EXPORT mgl_rotate_(uintptr_t *gr, mreal *TetX, mreal *TetZ, mreal *TetY)
+{	_GR_->Rotate(*TetX,*TetZ,*TetY);	}
+void MGL_EXPORT mgl_view_(uintptr_t *gr, mreal *TetX, mreal *TetZ, mreal *TetY)
+{	_GR_->View(*TetX,*TetZ,*TetY);	}
+void MGL_EXPORT mgl_zoom_(uintptr_t *gr, mreal *x1, mreal *y1, mreal *x2, mreal *y2)
+{	_GR_->Zoom(*x1,*y1,*x2,*y2);	}
+void MGL_EXPORT mgl_rotate_vector_(uintptr_t *gr, mreal *Tet, mreal *x, mreal *y, mreal *z)
+{	_GR_->RotateN(*Tet,*x,*y,*z);	}
+void MGL_EXPORT mgl_perspective_(uintptr_t *gr, mreal *val)
+{	_GR_->Perspective(*val);	}
+void MGL_EXPORT mgl_ask_perspective_(uintptr_t *gr, mreal *val)
+{	mgl_ask_perspective(_GR_,*val);	}
+//-----------------------------------------------------------------------------
+MGL_EXPORT const unsigned char *mgl_get_rgb_(uintptr_t *gr)	{	return gr ? _GR_->GetBits():0;	}
+MGL_EXPORT const unsigned char *mgl_get_rgba_(uintptr_t *gr){	return gr ? _GR_->GetRGBA():0;	}
+MGL_EXPORT const unsigned char* mgl_get_background_(uintptr_t* gr)	{	return gr ? _GR_->GetBackground():0;	}
+int MGL_EXPORT mgl_get_width_(uintptr_t *gr)	{	return gr ? _GR_->GetWidth():0;	}
+int MGL_EXPORT mgl_get_height_(uintptr_t *gr)	{	return gr ? _GR_->GetHeight():0;}
+void MGL_EXPORT mgl_calc_xyz_(uintptr_t *gr, int *xs, int *ys, mreal *x, mreal *y, mreal *z)
+{	mglPoint p = _GR_->CalcXYZ(*xs,*ys);	*x = p.x;	*y = p.y;	*z = p.z;	}
+void MGL_EXPORT mgl_calc_scr_(uintptr_t *gr, mreal *x, mreal *y, mreal *z, int *xs, int *ys)
+{	_GR_->CalcScr(mglPoint(*x,*y,*z),xs,ys);	}
+void MGL_EXPORT mgl_set_obj_id_(uintptr_t *gr, int *id)		{	_GR_->SetObjId(*id);	}
+int MGL_EXPORT mgl_get_obj_id_(uintptr_t *gr, int *x, int *y)	{	return _GR_->GetObjId(*x,*y);	}
+int MGL_EXPORT mgl_get_spl_id_(uintptr_t *gr, int *x, int *y)	{	return _GR_->GetSplId(*x,*y);	}
+//-----------------------------------------------------------------------------
+double mgl_size_scl = 1;
+HMGL MGL_EXPORT mgl_create_graph(int width, int height)
+{	return new mglCanvas(width,height);	}
+void MGL_EXPORT mgl_delete_graph(HMGL gr)	{	if(gr)	delete gr;	}
+void MGL_EXPORT mgl_set_size_scl(double scl){	if(scl>0)	mgl_size_scl = scl;	}
+void MGL_EXPORT mgl_set_size(HMGL gr, int width, int height)
+{
+	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);
+	width = int(mgl_size_scl*width);	height = int(mgl_size_scl*height);
+	if(g)	g->SetSize(width, height);
+}
+void MGL_EXPORT mgl_scale_size(HMGL gr, int width, int height)
+{
+	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);
+	width = int(mgl_size_scl*width);	height = int(mgl_size_scl*height);
+	if(g)	g->SetSize(width, height, false);
+}
+void MGL_EXPORT mgl_set_def_param(HMGL gr)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->DefaultPlotParam();	}
+void MGL_EXPORT mgl_combine_gr(HMGL gr, HMGL in)
+{	const mglCanvas *gg = dynamic_cast<const mglCanvas *>(in);
+	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g && gg)	g->Combine(gg);	}
+void MGL_EXPORT mgl_set_bbox(HMGL gr, int x1, int y1, int x2, int y2)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->SetBBox(x1,y1,x2,y2);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_tick_len(HMGL gr, double len, double stt)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->SetTickLen(len,stt);	}
+void MGL_EXPORT mgl_set_axis_stl(HMGL gr, const char *stl, const char *tck, const char *sub)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->SetAxisStl(stl,tck,sub);	}
+void MGL_EXPORT mgl_tune_ticks(HMGL gr, int tune, double pos)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->SetTuneTicks(tune,pos);	}
+void MGL_EXPORT mgl_adjust_ticks(HMGL gr, const char *dir)
+{	mgl_adjust_ticks_ext(gr,dir,"");	}
+void MGL_EXPORT mgl_adjust_ticks_ext(HMGL gr, const char *dir, const char *stl)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->AdjustTicks(dir,true,stl);	}
+void MGL_EXPORT mgl_set_ticks(HMGL gr, char dir, double d, int ns, double org)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->SetTicks(dir,d,ns,org);	}
+void MGL_EXPORT mgl_set_ticks_factw(HMGL gr, char dir, double d, int ns, double org, const wchar_t *fact)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->SetTicks(dir,d,ns,org,fact);	}
+void MGL_EXPORT mgl_set_ticks_fact(HMGL gr, char dir, double d, int ns, double org, const char *fact)
+{	MGL_TO_WCS(fact,mgl_set_ticks_factw(gr,dir,d,ns,org,wcs));	}
+void MGL_EXPORT mgl_set_ticks_str(HMGL gr, char dir, const char *lbl, int add)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->SetTicksVal(dir,lbl,add);	}
+void MGL_EXPORT mgl_set_ticks_wcs(HMGL gr, char dir, const wchar_t *lbl, int add)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->SetTicksVal(dir,lbl,add);	}
+void MGL_EXPORT mgl_set_ticks_val(HMGL gr, char dir, HCDT val, const char *lbl, int add)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->SetTicksVal(dir,val,lbl,add);	}
+void MGL_EXPORT mgl_set_ticks_valw(HMGL gr, char dir, HCDT val, const wchar_t *lbl, int add)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->SetTicksVal(dir,val,lbl,add);	}
+void MGL_EXPORT mgl_add_tick(HMGL gr, char dir, double val, const char *lbl)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->AddTick(dir,val,lbl);	}
+void MGL_EXPORT mgl_add_tickw(HMGL gr, char dir, double val, const wchar_t *lbl)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->AddTick(dir,val,lbl);	}
+void MGL_EXPORT mgl_set_tick_templ(HMGL gr, char dir, const char *templ)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->SetTickTempl(dir,templ);	}
+void MGL_EXPORT mgl_set_tick_templw(HMGL gr, char dir, const wchar_t *templ)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->SetTickTempl(dir,templ);	}
+void MGL_EXPORT mgl_set_ticks_time(HMGL gr, char dir, double d, const char *t)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->SetTickTime(dir,d,t);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_box(HMGL gr)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Box();	}
+void MGL_EXPORT mgl_box_str(HMGL gr, const char *col, int ticks)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Box(col,ticks);	}
+void MGL_EXPORT mgl_axis(HMGL gr, const char *dir, const char *stl, const char *opt)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Axis(dir,stl,opt);	}
+void MGL_EXPORT mgl_axis_grid(HMGL gr, const char *dir,const char *pen, const char *opt)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Grid(dir,pen,opt);	}
+void MGL_EXPORT mgl_label(HMGL gr, char dir, const char *text, double pos, const char *opt)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Label(dir,text,pos,opt);	}
+void MGL_EXPORT mgl_labelw(HMGL gr, char dir, const wchar_t *text, double pos, const char *opt)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Labelw(dir,text,pos,opt);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_colorbar(HMGL gr, const char *sch)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Colorbar(sch);	}
+void MGL_EXPORT mgl_colorbar_ext(HMGL gr, const char *sch, double x, double y, double w, double h)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Colorbar(sch,x,y,w,h);	}
+void MGL_EXPORT mgl_colorbar_val(HMGL gr, HCDT dat, const char *sch)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Colorbar(dat,sch);	}
+void MGL_EXPORT mgl_colorbar_val_ext(HMGL gr, HCDT dat, const char *sch,double x, double y, double w, double h)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Colorbar(dat,sch,x,y,w,h);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_add_legend(HMGL gr, const char *text,const char *style)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->AddLegend(text,style);	}
+void MGL_EXPORT mgl_add_legendw(HMGL gr, const wchar_t *text,const char *style)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->AddLegend(text,style);	}
+void MGL_EXPORT mgl_clear_legend(HMGL gr)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->ClearLegend();	}
+void MGL_EXPORT mgl_legend_pos(HMGL gr, double x, double y, const char *font, const char *opt)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Legend(x,y,font,opt);	}
+void MGL_EXPORT mgl_legend(HMGL gr, int where, const char *font, const char *opt)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Legend(where,font,opt);	}
+void MGL_EXPORT mgl_set_legend_marks(HMGL gr, int num)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->SetLegendMarks(num);	}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_create_graph_(int *width, int *height)
+{	return uintptr_t(new mglCanvas(*width,*height));	}
+void MGL_EXPORT mgl_delete_graph_(uintptr_t *gr)	{	delete _GR_;	}
+void MGL_EXPORT mgl_set_size_scl_(double *scl)	{	mgl_set_size_scl(*scl);	}
+void MGL_EXPORT mgl_set_size_(uintptr_t *gr, int *width, int *height)
+{	mgl_set_size(_GR_,*width,*height);	}
+void MGL_EXPORT mgl_scale_size_(uintptr_t *gr, int *width, int *height)
+{	mgl_scale_size(_GR_,*width,*height);	}
+void MGL_EXPORT mgl_set_def_param_(uintptr_t *gr)	{	_GR_->DefaultPlotParam();	}
+void MGL_EXPORT mgl_combine_gr_(uintptr_t *gr, uintptr_t *in)
+{	_GR_->Combine((mglCanvas *)in);	}
+void MGL_EXPORT mgl_set_bbox_(uintptr_t *gr, int *x1, int *y1, int *x2, int *y2)
+{	_GR_->SetBBox(*x1,*y1,*x2,*y2);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_ticks_fact_(uintptr_t *gr, char *dir, double *d, int *ns, double *org, const char *fact,int,int l)
+{	char *s=new char[l+1];	memcpy(s,fact,l);	s[l]=0;
+	mgl_set_ticks_fact(_GR_,*dir,*d,*ns,*org,s);	delete []s;	}
+void MGL_EXPORT mgl_set_tick_len_(uintptr_t *gr, mreal *len, mreal *stt)
+{	_GR_->SetTickLen(*len, *stt);	}
+void MGL_EXPORT mgl_set_axis_stl_(uintptr_t *gr, const char *stl, const char *tck, const char *sub, int l,int m,int n)
+{	char *a=new char[l+1];	memcpy(a,stl,l);	a[l]=0;
+	char *t=new char[m+1];	memcpy(t,tck,m);	t[m]=0;
+	char *s=new char[n+1];	memcpy(s,sub,n);	s[n]=0;
+	_GR_->SetAxisStl(a,t,s);	delete []a;	delete []s;	delete []t;	}
+void MGL_EXPORT mgl_adjust_ticks_(uintptr_t *gr, const char *dir, int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	_GR_->AdjustTicks(s,true);	delete []s;	}
+void MGL_EXPORT mgl_adjust_ticks_(uintptr_t *gr, const char *dir, const char *stl, int l, int m)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	char *f=new char[m+1];	memcpy(f,stl,m);	f[m]=0;
+	_GR_->AdjustTicks(s,true,f);	delete []s;	delete []f;	}
+void MGL_EXPORT mgl_set_ticks_(uintptr_t *gr, char *dir, mreal *d, int *ns, mreal *org, int)
+{	_GR_->SetTicks(*dir, *d, *ns, *org);	}
+void MGL_EXPORT mgl_set_ticks_str_(uintptr_t *gr, const char *dir, const char *lbl, int *add,int,int l)
+{	char *s=new char[l+1];	memcpy(s,lbl,l);	s[l]=0;
+	_GR_->SetTicksVal(*dir,s,*add);	delete []s;	}
+void MGL_EXPORT mgl_set_ticks_val_(uintptr_t *gr, const char *dir, uintptr_t *val, const char *lbl, int *add,int,int l)
+{	char *s=new char[l+1];	memcpy(s,lbl,l);	s[l]=0;
+	_GR_->SetTicksVal(*dir,_DA_(val),s,*add);	delete []s;	}
+void MGL_EXPORT mgl_add_tick_(uintptr_t *gr, const char *dir, mreal *val, const char *lbl, int,int l)
+{	char *s=new char[l+1];	memcpy(s,lbl,l);	s[l]=0;
+	mgl_add_tick(_GR_,*dir,*val,s);	delete []s;	}
+void MGL_EXPORT mgl_tune_ticks_(uintptr_t *gr, int *tune, mreal *fact_pos)
+{	_GR_->SetTuneTicks(*tune, *fact_pos);	}
+void MGL_EXPORT mgl_set_tick_templ_(uintptr_t *gr, const char *dir, const char *templ,int,int l)
+{	char *s=new char[l+1];	memcpy(s,templ,l);	s[l]=0;
+	_GR_->SetTickTempl(*dir,s);	delete []s;	}
+void MGL_EXPORT mgl_set_ticks_time_(uintptr_t *gr, const char *dir, mreal *d, const char *t,int,int l)
+{	char *s=new char[l+1];	memcpy(s,t,l);	s[l]=0;
+	_GR_->SetTickTime(*dir,*d,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_box_(uintptr_t *gr)	{	_GR_->Box();	}
+void MGL_EXPORT mgl_box_str_(uintptr_t *gr, const char *col, int *ticks, int l)
+{	char *s=new char[l+1];	memcpy(s,col,l);	s[l]=0;
+	_GR_->Box(s,*ticks);	delete []s;	}
+void MGL_EXPORT mgl_axis_(uintptr_t *gr, const char *dir, const char *stl, const char *opt,int l,int n,int m)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	char *p=new char[n+1];	memcpy(p,stl,l);	p[n]=0;
+	char *o=new char[m+1];	memcpy(o,opt,m);	o[m]=0;
+	_GR_->Axis(s,p,o);	delete []s;	delete []p;	delete []o;	}
+void MGL_EXPORT mgl_axis_grid_(uintptr_t *gr, const char *dir,const char *pen, const char *opt,int l,int n,int m)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	char *p=new char[n+1];	memcpy(p,pen,n);	p[n]=0;
+	char *o=new char[m+1];	memcpy(o,opt,m);	o[m]=0;
+	_GR_->Grid(s,p,o);	delete []s;	delete []p;	delete []o;	}
+void MGL_EXPORT mgl_label_(uintptr_t *gr, const char *dir, const char *text, mreal *pos, const char *opt,int,int l,int m)
+{	char *s=new char[l+1];	memcpy(s,text,l);	s[l]=0;
+	char *o=new char[m+1];	memcpy(o,opt,m);	o[m]=0;
+	_GR_->Label(*dir, s, *pos, o);	delete []s;	delete []o;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_colorbar_(uintptr_t *gr, const char *sch,int l)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	_GR_->Colorbar(s);	delete []s;	}
+void MGL_EXPORT mgl_colorbar_ext_(uintptr_t *gr, const char *sch, mreal *x, mreal *y, mreal *w, mreal *h, int l)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	_GR_->Colorbar(s,*x,*y,*w,*h);	delete []s;	}
+void MGL_EXPORT mgl_colorbar_val_(uintptr_t *gr, uintptr_t *dat, const char *sch,int l)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	_GR_->Colorbar(_DA_(dat), s);	delete []s;	}
+void MGL_EXPORT mgl_colorbar_val_ext_(uintptr_t *gr, uintptr_t *dat, const char *sch, mreal *x, mreal *y, mreal *w, mreal *h, int l)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	_GR_->Colorbar(_DA_(dat),s,*x,*y,*w,*h);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_add_legend_(uintptr_t *gr, const char *text,const char *style,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,text,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,style,n);	f[n]=0;
+	_GR_->AddLegend(s,f);	delete []s;	delete []f;	}
+void MGL_EXPORT mgl_clear_legend_(uintptr_t *gr)	{	if(gr)	_GR_->ClearLegend();	}
+void MGL_EXPORT mgl_legend_pos_(uintptr_t *gr, mreal *x, mreal *y, const char *font, const char *opt,int l,int m)
+{	char *s=new char[l+1];	memcpy(s,font,l);	s[l]=0;
+	char *o=new char[m+1];	memcpy(o,opt,m);	o[m]=0;
+	_GR_->Legend(*x, *y, s, o);	delete []s;	delete []o;	}
+void MGL_EXPORT mgl_legend_(uintptr_t *gr, int *where, const char *font, const char *opt,int l,int m)
+{	char *s=new char[l+1];	memcpy(s,font,l);	s[l]=0;
+	char *o=new char[m+1];	memcpy(o,opt,m);	o[m]=0;
+	_GR_->Legend(*where, s, o);	delete []s;	delete []o;	}
+void MGL_EXPORT mgl_set_legend_marks_(uintptr_t *gr, int *num)
+{	_GR_->SetLegendMarks(*num);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_wnd_set_delay(HMGL gr, double dt)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->SetDelay(dt);	}
+double MGL_EXPORT mgl_wnd_get_delay(HMGL gr)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	return g?g->GetDelay():0;	}
+void MGL_EXPORT mgl_wnd_set_delay_(uintptr_t *gr, mreal *dt)	{	_GR_->SetDelay(*dt);	}
+double MGL_EXPORT mgl_wnd_get_delay_(uintptr_t *gr)	{	return _GR_->GetDelay();	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_plotfactor(HMGL gr, double val)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->SetPlotFactor(val);	}
+void MGL_EXPORT mgl_set_plotfactor_(uintptr_t *gr, mreal *val)
+{	_GR_->SetPlotFactor(*val);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_set_tick_shift(HMGL gr, double sx, double sy, double sz, double sc)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->SetTickShift(mglPoint(sx,sy,sz,sc));	}
+void MGL_EXPORT mgl_set_tick_shift_(uintptr_t *gr, mreal *sx, mreal *sy, mreal *sz, mreal *sc)
+{	_GR_->SetTickShift(mglPoint(*sx,*sy,*sz,*sc));	}
+//-----------------------------------------------------------------------------
+#if !MGL_HAVE_PNG
+void MGL_EXPORT mgl_write_prc(HMGL gr, const char *fname,const char *descr, int make_pdf)
+{	mgl_set_global_warn(_("PNG support was disabled. Please, enable it and rebuild MathGL."));	}
+void MGL_EXPORT mgl_write_prc_(uintptr_t *graph, const char *fname,const char *descr, int *make_pdf,int lf,int ld)
+{	mgl_set_global_warn(_("PNG support was disabled. Please, enable it and rebuild MathGL."));	}
+#endif
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_finish(HMGL gr)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Finish();	}
+void MGL_EXPORT mgl_finish_(uintptr_t *gr)	{	_GR_->Finish();	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_rasterize(HMGL gr)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->Rasterize();	}
+void MGL_EXPORT mgl_rasterize_(uintptr_t *gr)	{	_GR_->Rasterize();	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_pen_delta(HMGL gr, double d)
+{	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(g)	g->SetPenDelta(d);	}
+void MGL_EXPORT mgl_pen_delta_(uintptr_t *gr, double *d)	{	_GR_->SetPenDelta(*d);	}
+//-----------------------------------------------------------------------------
diff --git a/src/complex.cpp b/src/complex.cpp
new file mode 100644
index 0000000..e95f615
--- /dev/null
+++ b/src/complex.cpp
@@ -0,0 +1,1536 @@
+/***************************************************************************
+ * complex.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include "mgl2/datac.h"
+#include "mgl2/evalc.h"
+#include "mgl2/thread.h"
+
+#include "interp.hpp"
+#define mgl2 	mreal(2)
+#define mgl3 	mreal(3)
+#define mgl4 	mreal(4)
+
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mglStartThreadC(void *(*func)(void *), void (*post)(mglThreadC *,dual *), long n,
+					dual *a, const dual *b, const dual *c, const long *p,
+					const void *v, const dual *d, const dual *e, const char *s)
+{
+	if(!func)	return;
+#if MGL_HAVE_PTHREAD
+	if(mglNumThr<1)	mgl_set_num_thr(0);
+	if(mglNumThr>1)
+	{
+		pthread_t *tmp=new pthread_t[mglNumThr];
+		mglThreadC *par=new mglThreadC[mglNumThr];
+		for(long i=0;i<mglNumThr;i++)	// put parameters into the structure
+		{	par[i].n=n;	par[i].a=a;	par[i].b=b;	par[i].c=c;	par[i].d=d;
+			par[i].p=p;	par[i].v=v;	par[i].s=s;	par[i].e=e;	par[i].id=i;	}
+		for(long i=0;i<mglNumThr;i++)	pthread_create(tmp+i, 0, func, par+i);
+		for(long i=0;i<mglNumThr;i++)	pthread_join(tmp[i], 0);
+		if(post)	post(par,a);
+		delete []tmp;	delete []par;
+	}
+	else
+#endif
+	{
+		mglNumThr = 1;
+		mglThreadC par;
+		par.n=n;	par.a=a;	par.b=b;	par.c=c;	par.d=d;
+		par.p=p;	par.v=v;	par.s=s;	par.e=e;	par.id=0;
+		func(&par);
+		if(post)	post(&par,a);
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mglStartThreadV(void *(*func)(void *), long n, dual *a, const void *b,
+					const void *c, const long *p, const void *v, const mreal *d)
+{
+	if(!func)	return;
+#if MGL_HAVE_PTHREAD
+	if(mglNumThr<1)	mgl_set_num_thr(0);
+	if(mglNumThr>1)
+	{
+		pthread_t *tmp=new pthread_t[mglNumThr];
+		mglThreadV *par=new mglThreadV[mglNumThr];
+		for(long i=0;i<mglNumThr;i++)	// put parameters into the structure
+		{	par[i].n=n;	par[i].a=0;	par[i].b=b;	par[i].c=c;	par[i].d=d;
+			par[i].p=p;	par[i].v=v;	par[i].id=i;par[i].aa=a;	}
+		for(long i=0;i<mglNumThr;i++)	pthread_create(tmp+i, 0, func, par+i);
+		for(long i=0;i<mglNumThr;i++)	pthread_join(tmp[i], 0);
+		delete []tmp;	delete []par;
+	}
+	else
+#endif
+	{
+		mglNumThr = 1;
+		mglThreadV par;
+		par.n=n;	par.a=0;	par.b=b;	par.c=c;	par.d=d;
+		par.p=p;	par.v=v;	par.id=0;	par.aa=a;
+		func(&par);
+	}
+}
+//-----------------------------------------------------------------------------
+mdual MGL_EXPORT_CONST mgl_expi(dual a)
+{
+	dual r = exp(dual(0,1)*dual(a));
+	return r.real()+r.imag()*mgl_I;
+}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_csmth_x(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nx=t->p[0], kind=t->p[2];
+	dual *b=t->a;
+	const dual *a=t->b;
+	if(kind>0)
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			long j = i%nx;
+			if(j-kind<0)	j = i+kind-j;
+			else if(j+kind>nx-1)	j = i+nx-1-j-kind;
+			else	j=i;
+			for(long k=-kind;k<=kind;k++)	b[i] += a[j+k]/mreal(2*kind+1);
+		}
+	else
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			long j = i%nx;
+			if(j>1 && j<nx-2)	b[i] = (mreal(12)*a[i-2] - mreal(3)*a[i-1] + mreal(17)*a[i] - mreal(3)*a[i+1] + mreal(12)*a[i+2])/mreal(35);
+			else if(j==1 || j==nx-2)	b[i] = (a[i-1] + a[i] + a[i+1])/mreal(3);
+			else	b[i] = a[i];
+		}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_csmth_y(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nx=t->p[0],ny=t->p[1], kind=t->p[2];
+	dual *b=t->a;
+	const dual *a=t->b;
+	if(kind>0)
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			long j = (i/nx)%ny;
+			if(j-kind<0)	j = i+(kind-j)*nx;
+			else if(j+kind>ny-1)	j = i+(ny-1-j-kind)*nx;
+			else	j=i;
+			for(long k=-kind;k<=kind;k++)	b[i] += a[j+k*nx]/mreal(2*kind+1);
+		}
+	else
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			long j = (i/nx)%ny;
+			if(j>1 && j<ny-2)	b[i] = (mreal(12)*a[i-2*nx] - mreal(3)*a[i-nx] + mreal(17)*a[i] - mreal(3)*a[i+nx] + mreal(12)*a[i+2*nx])/mreal(35);
+			else if(j==1 || j==ny-2)	b[i] = (a[i-nx] + a[i] + a[i+nx])/mreal(3);
+			else	b[i] = a[i];
+		}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_csmth_z(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nn=t->p[0]*t->p[1], nz=t->n/nn, kind=t->p[2];
+	dual *b=t->a;
+	const dual *a=t->b;
+	if(kind>0)
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			long j = i/nn;
+			if(j-kind<0)	j = i+(kind-j)*nn;
+			else if(j+kind>nz-1)	j = i+(nz-1-j-kind)*nn;
+			else	j=i;
+			for(long k=-kind;k<=kind;k++)	b[i] += a[j+k*nn]/mreal(2*kind+1);
+		}
+	else
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			long j = i/nn;
+			if(j>1 && j<nz-2)	b[i] = (mreal(12)*a[i-2*nn] - mreal(3)*a[i-nn] + mreal(17)*a[i] - mreal(3)*a[i+nn] + mreal(12)*a[i+2*nn])/mreal(35);
+			else if(j==1 || j==nz-2)	b[i] = (a[i-nn] + a[i] + a[i+nn])/mreal(3);
+			else	b[i] = a[i];
+		}
+	return 0;
+}
+void MGL_EXPORT mgl_datac_smooth(HADT d, const char *dirs, mreal )
+{
+	long Type = -1;
+	if(!dirs || *dirs==0)	dirs = "xyz";
+	if(strchr(dirs,'0'))	return;
+	if(strchr(dirs,'d'))
+	{
+		if(strchr(dirs,'1'))	Type = 1;
+		if(strchr(dirs,'2'))	Type = 2;
+		if(strchr(dirs,'3'))	Type = 3;
+		if(strchr(dirs,'4'))	Type = 4;
+		if(strchr(dirs,'5'))	Type = 5;
+		if(strchr(dirs,'6'))	Type = 6;
+		if(strchr(dirs,'7'))	Type = 7;
+		if(strchr(dirs,'8'))	Type = 8;
+		if(strchr(dirs,'9'))	Type = 9;
+	}
+	else
+	{
+		if(strchr(dirs,'1'))	return;
+		if(strchr(dirs,'3'))	Type = 1;
+		if(strchr(dirs,'5'))	Type = 2;
+	}
+	long nx=d->nx,ny=d->ny,nz=d->nz;
+//	if(Type == SMOOTH_NONE)	return;
+	long p[3]={nx,ny,Type};
+	dual *b = new dual[nx*ny*nz];
+	// ����������� �� x
+	memset(b,0,nx*ny*nz*sizeof(dual));
+	if(nx>4 && strchr(dirs,'x'))
+	{
+		mglStartThreadC(mgl_csmth_x,0,nx*ny*nz,b,d->a,0,p);
+		memcpy(d->a,b,nx*ny*nz*sizeof(dual));
+		memset(b,0,nx*ny*nz*sizeof(dual));
+	}
+	if(ny>4 && strchr(dirs,'y'))
+	{
+		mglStartThreadC(mgl_csmth_y,0,nx*ny*nz,b,d->a,0,p);
+		memcpy(d->a,b,nx*ny*nz*sizeof(dual));
+		memset(b,0,nx*ny*nz*sizeof(dual));
+	}
+	if(nz>4 && strchr(dirs,'z'))
+	{
+		mglStartThreadC(mgl_csmth_z,0,nx*ny*nz,b,d->a,0,p);
+		memcpy(d->a,b,nx*ny*nz*sizeof(dual));
+	}
+	delete []b;
+}
+void MGL_EXPORT mgl_datac_smooth_(uintptr_t *d, const char *dir, mreal *delta,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_datac_smooth(_DC_,s,*delta);		delete []s;	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_ccsum_z(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nz=t->p[2], nn=t->n;
+	dual *b=t->a;
+	const dual *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		b[i] = a[i];
+		for(long j=1;j<nz;j++)	b[i+j*nn] = b[i+j*nn-nn] + a[i+j*nn];
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_ccsum_y(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nx=t->p[0], ny=t->p[1], nn=t->n;
+	dual *b=t->a;
+	const dual *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = (i%nx)+nx*ny*(i/nx);		b[k] = a[k];
+		for(long j=1;j<ny;j++)	b[k+j*nx] = b[k+j*nx-nx] + a[k+nx*j];
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_ccsum_x(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nx=t->p[0], nn=t->n;
+	dual *b=t->a;
+	const dual *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = i*nx;			b[k] = a[k];
+		for(long j=1;j<nx;j++)	b[j+k] = b[j+k-1] + a[j+k];
+	}
+	return 0;
+}
+void MGL_EXPORT mgl_datac_cumsum(HADT d, const char *dir)
+{
+	if(!dir || *dir==0)	return;
+	long nx=d->nx,ny=d->ny,nz=d->nz,nn=nx*ny*nz;
+	long p[3]={nx,ny,nz};
+	dual *b = new dual[nn];
+	memcpy(b,d->a,nn*sizeof(dual));
+	if(strchr(dir,'z') && nz>1)
+	{
+		mglStartThreadC(mgl_ccsum_z,0,nx*ny,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(dual));
+	}
+	if(strchr(dir,'y') && ny>1)
+	{
+		mglStartThreadC(mgl_ccsum_y,0,nx*nz,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(dual));
+	}
+	if(strchr(dir,'x') && nx>1)
+	{
+		mglStartThreadC(mgl_ccsum_x,0,nz*ny,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(dual));
+	}
+	delete []b;
+}
+void MGL_EXPORT mgl_datac_cumsum_(uintptr_t *d, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_datac_cumsum(_DC_,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_cint_z(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nz=t->p[2], nn=t->n;
+	dual *b=t->a, dd=0.5/nz;
+	const dual *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		b[i] = 0;
+		for(long j=1;j<nz;j++)	b[i+j*nn] = b[i+j*nn-nn] + (a[i+nn*j]+a[i+j*nn-nn])*dd;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_cint_y(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nx=t->p[0], ny=t->p[1], nn=t->n;
+	dual *b=t->a, dd=0.5/ny;
+	const dual *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = (i%nx)+nx*ny*(i/nx);	b[k] = 0;
+		for(long j=1;j<ny;j++)	b[k+j*nx] = b[k+j*nx-nx] + (a[k+j*nx]+a[k+j*nx-nx])*dd;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_cint_x(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nx=t->p[0], nn=t->n;
+	dual *b=t->a, dd=0.5/nx;
+	const dual *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = i*nx;			b[k] = 0;
+		for(long j=1;j<nx;j++)	b[j+k] = b[j+k-1] + (a[j+k]+a[j+k-1])*dd;
+	}
+	return 0;
+}
+void MGL_EXPORT mgl_datac_integral(HADT d, const char *dir)
+{
+	if(!dir || *dir==0)	return;
+	long nx=d->nx,ny=d->ny,nz=d->nz,nn=nx*ny*nz;
+	long p[3]={nx,ny,nz};
+	dual *b = new dual[nn];
+	memcpy(b,d->a,nn*sizeof(dual));
+	if(strchr(dir,'z') && nz>1)
+	{
+		mglStartThreadC(mgl_cint_z,0,nx*ny,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(dual));
+	}
+	if(strchr(dir,'y') && ny>1)
+	{
+		mglStartThreadC(mgl_cint_y,0,nx*nz,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(dual));
+	}
+	if(strchr(dir,'x') && nx>1)
+	{
+		mglStartThreadC(mgl_cint_x,0,nz*ny,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(dual));
+	}
+	delete []b;
+}
+void MGL_EXPORT mgl_datac_integral_(uintptr_t *d, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_datac_integral(_DC_,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_cdif_z(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nz=t->p[2], nn=t->n;
+	dual *b=t->a, dd=0.5*nz;
+	const dual *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		b[i] = -(mgl3*a[i]-mgl4*a[i+nn]+a[i+2*nn])*dd;
+		b[i+(nz-1)*nn] = (mgl3*a[i+(nz-1)*nn]-mgl4*a[i+(nz-2)*nn]+a[i+(nz-3)*nn])*dd;
+		for(long j=1;j<nz-1;j++)		b[i+j*nn] = (a[i+j*nn+nn]-a[i+j*nn-nn])*dd;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_cdif_y(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nx=t->p[0], ny=t->p[1], nn=t->n;
+	dual *b=t->a, dd=0.5*ny;
+	const dual *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = (i%nx)+nx*ny*(i/nx);
+		b[k] = -(mgl3*a[k]-mgl4*a[k+nx]+a[k+2*nx])*dd;
+		b[k+(ny-1)*nx] = (mgl3*a[k+(ny-1)*nx]-mgl4*a[k+(ny-2)*nx]+a[k+(ny-3)*nx])*dd;
+		for(long j=1;j<ny-1;j++)	b[k+j*nx] = (a[k+j*nx+nx]-a[k+j*nx-nx])*dd;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_cdif_x(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nx=t->p[0], nn=t->n;
+	dual *b=t->a, dd=0.5*nx;
+	const dual *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = i*nx;
+		b[k] = -(mgl3*a[k]-mgl4*a[k+1]+a[k+2])*dd;
+		b[k+nx-1] = (mgl3*a[k+nx-1]-mgl4*a[k+nx-2]+a[k+nx-3])*dd;
+		for(long j=1;j<nx-1;j++)	b[j+k] = (a[j+k+1]-a[j+k-1])*dd;
+	}
+	return 0;
+}
+void MGL_EXPORT mgl_datac_diff(HADT d, const char *dir)
+{
+	if(!dir || *dir==0)	return;
+	long nx=d->nx,ny=d->ny,nz=d->nz,nn=nx*ny*nz;
+	long p[3]={nx,ny,nz};
+	dual *b = new dual[nn];
+	if(strchr(dir,'z') && nz>1)
+	{
+		mglStartThreadC(mgl_cdif_z,0,nx*ny,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(dual));
+	}
+	if(strchr(dir,'y') && ny>1)
+	{
+		mglStartThreadC(mgl_cdif_y,0,nx*nz,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(dual));
+	}
+	if(strchr(dir,'x') && nx>1)
+	{
+		mglStartThreadC(mgl_cdif_x,0,nz*ny,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(dual));
+	}
+	delete []b;
+}
+void MGL_EXPORT mgl_datac_diff_(uintptr_t *d, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_datac_diff(_DC_,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_cdif2_z(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nz=t->p[2], nn=t->n;
+	dual *b=t->a, dd=0.5*nz*nz;
+	const dual *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		b[i] = b[i+(nz-1)*nn] = 0;
+		for(long j=1;j<nz-1;j++)		b[i+j*nn] = (a[i+j*nn+nn]+a[i+j*nn-nn]-mgl2*a[i+j*nn])*dd;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_cdif2_y(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nx=t->p[0], ny=t->p[1], nn=t->n;
+	dual *b=t->a, dd=0.5*ny*ny;
+	const dual *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = (i%nx)+nx*ny*(i/nx);	b[k] = b[k+(ny-1)*nx] = 0;
+		for(long j=1;j<ny-1;j++)	b[k+j*nx] = (a[k+j*nx+nx]+a[k+j*nx-nx]-mgl2*a[k+j*nx])*dd;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_cdif2_x(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nx=t->p[0], nn=t->n;
+	dual *b=t->a, dd=0.5*nx*nx;
+	const dual *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = i*nx;			b[k] = b[k+nx-1] = 0;
+		for(long j=1;j<nx-1;j++)	b[j+k] = (a[j+k+1]+a[j+k-1]-mgl2*a[j+k])*dd;
+	}
+	return 0;
+}
+void MGL_EXPORT mgl_datac_diff2(HADT d, const char *dir)
+{
+	if(!dir || *dir==0)	return;
+	long nx=d->nx,ny=d->ny,nz=d->nz,nn=nx*ny*nz;
+	long p[3]={nx,ny,nz};
+	dual *b = new dual[nn];
+	if(strchr(dir,'z') && nz>1)
+	{
+		mglStartThreadC(mgl_cdif2_z,0,nx*ny,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(dual));
+	}
+	if(strchr(dir,'y') && ny>1)
+	{
+		mglStartThreadC(mgl_cdif2_y,0,nx*nz,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(dual));
+	}
+	if(strchr(dir,'x') && nx>1)
+	{
+		mglStartThreadC(mgl_cdif2_x,0,nz*ny,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(dual));
+	}
+	delete []b;
+}
+void MGL_EXPORT mgl_datac_diff2_(uintptr_t *d, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_datac_diff2(_DC_,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_swap(HADT d, const char *dir)
+{
+	if(!dir || *dir==0)	return;
+	if(strchr(dir,'z') && d->nz>1)	mgl_datac_roll(d,'z',d->nz/2);
+	if(strchr(dir,'y') && d->ny>1)	mgl_datac_roll(d,'y',d->ny/2);
+	if(strchr(dir,'x') && d->nx>1)	mgl_datac_roll(d,'x',d->nx/2);
+}
+void MGL_EXPORT mgl_datac_swap_(uintptr_t *d, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_datac_swap(_DC_,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_roll(HADT dd, char dir, long num)
+{
+	long nx=dd->nx,ny=dd->ny,nz=dd->nz, d;
+	dual *b,*a=dd->a;
+	if(dir=='z' && nz>1)
+	{
+		d = num>0 ? num%nz : (num+nz*(1-num/nz))%nz;
+		if(d==0)	return;		// nothing to do
+		b = new dual[nx*ny*nz];
+		memcpy(b,a+nx*ny*d,nx*ny*(nz-d)*sizeof(dual));
+		memcpy(b+nx*ny*(nz-d),a,nx*ny*d*sizeof(dual));
+		memcpy(a,b,nx*ny*nz*sizeof(dual));	delete []b;
+	}
+	if(dir=='y' && ny>1)
+	{
+		d = num>0 ? num%ny : (num+ny*(1-num/ny))%ny;
+		if(d==0)	return;		// nothing to do
+		b = new dual[nx*ny*nz];
+		memcpy(b,a+nx*d,(nx*ny*nz-nx*d)*sizeof(dual));
+#pragma omp parallel for
+		for(long i=0;i<nz;i++)
+			memcpy(b+nx*(ny-d)+nx*ny*i,a+nx*ny*i,nx*d*sizeof(dual));
+		memcpy(a,b,nx*ny*nz*sizeof(dual));	delete []b;
+	}
+	if(dir=='x' && nx>1)
+	{
+		d = num>0 ? num%nx : (num+nx*(1-num/nx))%nx;
+		if(d==0)	return;		// nothing to do
+		b = new dual[nx*ny*nz];
+		memcpy(b,a+d,(nx*ny*nz-d)*sizeof(dual));
+#pragma omp parallel for
+		for(long i=0;i<nz*ny;i++)
+			memcpy(b+nx-d+nx*i,a+nx*i,d*sizeof(dual));
+		memcpy(a,b,nx*ny*nz*sizeof(dual));	delete []b;
+	}
+}
+void MGL_EXPORT mgl_datac_roll_(uintptr_t *d, const char *dir, int *num, int)
+{	mgl_datac_roll(_DC_,*dir,*num);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_mirror(HADT d, const char *dir)
+{
+	if(!dir || *dir==0)	return;
+	long nx=d->nx,ny=d->ny,nz=d->nz;
+	dual *a=d->a;
+	if(strchr(dir,'z') && nz>1)
+	{
+#pragma omp parallel for collapse(2)
+		for(long i=0;i<nx*ny;i++)	for(long j=0;j<nz/2;j++)
+		{
+			long i0 = i+j*nx*ny, j0 = i+(nz-1-j)*nx*ny;
+			dual b = a[i0];	a[i0] = a[j0];	a[j0] = b;
+		}
+	}
+	if(strchr(dir,'y') && ny>1)
+	{
+#pragma omp parallel for collapse(2)
+		for(long i=0;i<nx*nz;i++)	for(long j=0;j<ny/2;j++)
+		{
+			long j0 = (i%nx)+nx*(ny*(i/nx)+j), i0 = j0+(ny-1-2*j)*nx;
+			dual b = a[j0];	a[j0] = a[i0];	a[i0] = b;
+		}
+	}
+	if(strchr(dir,'x') && nx>1)
+	{
+#pragma omp parallel for collapse(2)
+		for(long j=0;j<ny*nz;j++)	for(long i=0;i<nx/2;i++)
+		{
+			long i0 = nx-1-i+j*nx, j0 = i+j*nx;
+			dual b = a[j0];	a[j0] = a[i0];	a[i0] = b;
+		}
+	}
+}
+void MGL_EXPORT mgl_datac_mirror_(uintptr_t *d, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_datac_mirror(_DC_,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+dual MGL_EXPORT mglSpline3Cs(const dual *a, long nx, long ny, long nz, mreal x, mreal y, mreal z)
+{	return mglSpline3st<dual>(a,nx,ny,nz,x,y,z);	}
+//-----------------------------------------------------------------------------
+dual MGL_EXPORT mglSpline3C(const dual *a, long nx, long ny, long nz, mreal x, mreal y, mreal z,dual *dx, dual *dy, dual *dz)
+{	return mglSpline3t<dual>(a,nx,ny,nz,x,y,z,dx,dy,dz);	}
+//-----------------------------------------------------------------------------
+dual MGL_EXPORT mglLinearC(const dual *a, long nx, long ny, long nz, mreal x, mreal y, mreal z)
+{	return mglLineart<dual>(a,nx,ny,nz,x,y,z);	}
+//-----------------------------------------------------------------------------
+mdual MGL_EXPORT mgl_datac_spline(HCDT d, mreal x,mreal y,mreal z)
+{
+	const mglDataC *dd=dynamic_cast<const mglDataC *>(d);
+	dual r = dd ? mglSpline3st<dual>(dd->a,dd->nx,dd->ny,dd->nz,x,y,z) : d->value(x,y,z);
+	return r.real()+r.imag()*mgl_I;
+}
+//-----------------------------------------------------------------------------
+mdual MGL_EXPORT mgl_datac_spline_ext(HCDT d, mreal x,mreal y,mreal z, dual *dx,dual *dy,dual *dz)
+{
+	const mglDataC *dd=dynamic_cast<const mglDataC *>(d);
+	if(!dd)
+	{
+		mreal rx=0,ry=0,rz=0,res;
+		res=d->valueD(x,y,z,&rx,&ry,&rz);
+		if(dx)	*dx=rx;
+		if(dy)	*dy=ry;
+		if(dz)	*dz=rz;
+		return res;
+	}
+	dual r = mglSpline3t<dual>(dd->a,dd->nx,dd->ny,dd->nz,x,y,z,dx,dy,dz);
+	return r.real()+r.imag()*mgl_I;
+}
+//-----------------------------------------------------------------------------
+mdual MGL_EXPORT mgl_datac_spline_(uintptr_t *d, mreal *x,mreal *y,mreal *z)
+{	return mgl_datac_spline(_DA_(d),*x,*y,*z);	}
+mdual MGL_EXPORT mgl_datac_spline_ext_(uintptr_t *d, mreal *x,mreal *y,mreal *z, dual *dx,dual *dy,dual *dz)
+{	return mgl_datac_spline_ext(_DA_(d),*x,*y,*z,dx,dy,dz);	}
+//-----------------------------------------------------------------------------
+mdual MGL_EXPORT mgl_datac_linear_ext(HCDT d, mreal x,mreal y,mreal z, dual *dx,dual *dy,dual *dz)
+{
+	long kx=long(x), ky=long(y), kz=long(z);
+	dual b0,b1;
+	const mglDataC *dd=dynamic_cast<const mglDataC *>(d);
+	if(!dd)
+	{
+		mreal rx=0,ry=0,rz=0,res;
+		res=mgl_data_linear_ext(d,x,y,z,&rx,&ry,&rz);
+		if(dx)	*dx=rx;
+		if(dy)	*dy=ry;
+		if(dz)	*dz=rz;
+		return res;
+	}
+
+	long nx=dd->nx, ny=dd->ny, nz=dd->nz, dn=ny>1?nx:0;
+	kx = kx>=0 ? kx:0;	kx = kx<nx-1 ? kx:nx-2;
+	ky = ky>=0 ? ky:0;	ky = ky<ny-1 ? ky:ny-2;
+	kz = kz>=0 ? kz:0;	kz = kz<nz-1 ? kz:nz-2;
+	x -= kx;	y -= ky;	z -= kz;
+	const dual *aa = dd->a, *bb;
+	if(kz>=0)
+	{
+		aa=dd->a+kx+nx*(ky+ny*kz);	bb = aa+nx*ny;
+		b0 = aa[0]*(1-x-y+x*y) + x*(1-y)*aa[1] + y*(1-x)*aa[dn] + x*y*aa[1+dn];
+		b1 = bb[0]*(1-x-y+x*y) + x*(1-y)*bb[1] + y*(1-x)*bb[dn] + x*y*bb[1+dn];
+	}
+	else
+	{
+		z=0;
+		if(ky>=0)
+		{
+			aa=dd->a+kx+nx*ky;
+			b0 = b1 = aa[0]*(1-x-y+x*y) + x*(1-y)*aa[1] + y*(1-x)*aa[dn] + x*y*aa[1+dn];
+		}
+		else if(kx>=0)
+		{
+			aa=dd->a+kx;	b0 = b1 = aa[0]*(1-x) + x*aa[1];
+		}
+		else	b0 = b1 = dd->a[0];
+	}
+	if(dx)	*dx = kx>=0?aa[1]-aa[0]:0;
+	if(dy)	*dy = ky>=0?aa[dn]-aa[0]:0;
+	if(dz)	*dz = b1-b0;
+	dual r = b0 + z*(b1-b0);
+	return r.real()+r.imag()*mgl_I;
+}
+mdual MGL_EXPORT mgl_datac_linear(HCDT d, mreal x,mreal y,mreal z)
+{	return mgl_datac_linear_ext(d, x,y,z, 0,0,0);	}
+//-----------------------------------------------------------------------------
+mdual MGL_EXPORT mgl_datac_linear_(uintptr_t *d, mreal *x,mreal *y,mreal *z)
+{	return mgl_datac_linear(_DA_(d),*x,*y,*z);	}
+mdual MGL_EXPORT mgl_datac_linear_ext_(uintptr_t *d, mreal *x,mreal *y,mreal *z, dual *dx,dual *dy,dual *dz)
+{	return mgl_datac_linear_ext(_DA_(d),*x,*y,*z,dx,dy,dz);	}
+//-----------------------------------------------------------------------------
+long MGL_NO_EXPORT mgl_powers(long N, const char *how);
+void MGL_EXPORT mgl_datac_crop_opt(HADT d, const char *how)
+{
+	const char *h = "235";
+	if(mglchr(how,'2') || mglchr(how,'3') || mglchr(how,'5'))	h = how;
+	if(mglchr(how,'x'))	mgl_datac_crop(d, 0, mgl_powers(d->nx, h), 'x');
+	if(mglchr(how,'y'))	mgl_datac_crop(d, 0, mgl_powers(d->ny, h), 'y');
+	if(mglchr(how,'z'))	mgl_datac_crop(d, 0, mgl_powers(d->nz, h), 'z');
+}
+void MGL_EXPORT mgl_datac_crop_opt_(uintptr_t *d, const char *how, int l)
+{	char *s=new char[l+1];	memcpy(s,how,l);	s[l]=0;
+	mgl_datac_crop_opt(_DC_,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_crop(HADT d, long n1, long n2, char dir)
+{
+	long nx=d->nx,ny=d->ny,nz=d->nz, nn;
+	dual *b;
+	if(n1<0)	n1=0;
+	switch(dir)
+	{
+	case 'x':
+		if(n1>=nx)	break;
+		n2 = n2>0 ? n2 : nx+n2;
+		if(n2<0 || n2>=nx || n2<n1)	n2 = nx;
+		nn = n2-n1;	b = new dual[nn*ny*nz];
+#pragma omp parallel for
+		for(long i=0;i<ny*nz;i++)
+			memcpy(b+nn*i,d->a+nx*i+n1,nn*sizeof(dual));
+		d->nx = nn;	if(!d->link)	delete []d->a;
+		d->a = b;	d->link=false;	d->NewId();
+		break;
+	case 'y':
+		if(n1>=ny)	break;
+		n2 = n2>0 ? n2 : ny+n2;
+		if(n2<0 || n2>=ny || n2<n1)	n2 = ny;
+		nn = n2-n1;	b = new dual[nn*nx*nz];
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	for(long j=0;j<nz;j++)
+			memcpy(b+nx*(i+nn*j),d->a+nx*(n1+i+ny*j),nx*sizeof(dual));
+		d->ny = nn;	if(!d->link)	delete []d->a;
+		d->a = b;	d->link=false;
+		break;
+	case 'z':
+		if(n1>=nz)	break;
+		n2 = n2>0 ? n2 : nz+n2;
+		if(n2<0 || n2>=nz || n2<n1)	n2 = nz;
+		nn = n2-n1;	b = new dual[nn*nx*ny];
+		memcpy(b,d->a+nx*ny*n1,nn*nx*ny*sizeof(dual));
+		d->nz = nn;	if(!d->link)	delete []d->a;
+		d->a = b;	d->link=false;
+		break;
+	}
+}
+void MGL_EXPORT mgl_datac_crop_(uintptr_t *d, int *n1, int *n2, const char *dir,int)
+{	mgl_datac_crop(_DC_,*n1,*n2,*dir);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_insert(HADT d, char dir, long at, long num)
+{
+	if(num<1)	return;
+	at = at<0 ? 0:at;
+	long nx=d->nx, ny=d->ny, nz=d->nz, nn;
+	mglDataC b;
+	if(dir=='x')
+	{
+		if(at>nx)	at=nx;
+		nn=nx+num;	b.Create(nn,ny,nz);
+#pragma omp parallel for
+		for(long k=0;k<ny*nz;k++)
+		{
+			if(at>0)	memcpy(b.a+nn*k, d->a+nx*k,at*sizeof(dual));
+			if(at<nx)	memcpy(b.a+at+num+nn*k, d->a+at+nx*k,(nx-at)*sizeof(dual));
+			for(long i=0;i<num;i++)	b.a[nn*k+at+i]=d->a[nx*k+at];	// copy values
+		}
+		d->Set(b);	nx+=num;
+	}
+	if(dir=='y')
+	{
+		if(at>ny)	at=ny;
+		nn=num+ny;	b.Create(nx,nn,nz);
+#pragma omp parallel for
+		for(long k=0;k<nz;k++)
+		{
+			if(at>0)	memcpy(b.a+nx*nn*k, d->a+nx*ny*k,at*nx*sizeof(dual));
+			if(at<ny)	memcpy(b.a+nx*(at+num+nn*k), d->a+nx*(at+ny*k),(ny-at)*nx*sizeof(dual));
+			for(long i=0;i<num;i++)	memcpy(b.a+nx*(nn*k+at+i),d->a+nx*(ny*k+at),nx*sizeof(dual));
+		}
+		d->Set(b);	ny+=num;
+	}
+	if(dir=='z')
+	{
+		if(at>nz)	at=nz;
+		b.Create(nx,ny,nz+num);
+		if(at>0)	memcpy(b.a, d->a,at*nx*ny*sizeof(dual));
+		if(at<nz)	memcpy(b.a+nx*ny*(at+num), d->a+nx*ny*at,(nz-at)*nx*ny*sizeof(dual));
+#pragma omp parallel for
+		for(long i=0;i<num;i++)	memcpy(b.a+nx*ny*(at+i),d->a+nx*ny*at,nx*ny*sizeof(dual));
+		d->Set(b);
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_delete(HADT d, char dir, long at, long num)
+{
+	if(num<1 || at<0)	return;
+	mglDataC b;
+	long nx=d->nx, ny=d->ny, nz=d->nz, nn;
+	if(dir=='x')
+	{
+		if(at+num>=nx)	return;
+		nn=nx-num;	b.Create(nn,ny,nz);
+#pragma omp parallel for
+		for(long k=0;k<ny*nz;k++)
+		{
+			if(at>0)	memcpy(b.a+nn*k, d->a+nx*k,at*sizeof(dual));
+			memcpy(b.a+at+nn*k, d->a+at+num+nx*k,(nx-at-num)*sizeof(dual));
+		}
+		d->Set(b);	nx-=num;
+	}
+	if(dir=='y')
+	{
+		if(at+num>=ny)	return;
+		nn=ny-num;	b.Create(nx,nn,nz);
+#pragma omp parallel for
+		for(long k=0;k<nz;k++)
+		{
+			if(at>0)	memcpy(b.a+nx*nn*k, d->a+nx*ny*k,at*nx*sizeof(dual));
+			memcpy(b.a+nx*(at+nn*k), d->a+nx*(at+num+ny*k),(ny-at-num)*nx*sizeof(dual));
+		}
+		d->Set(b);	ny-=num;
+	}
+	if(dir=='z')
+	{
+		if(at+num>=nz)	return;
+		b.Create(nx,ny,nz-num);
+		if(at>0)	memcpy(b.a, d->a,at*nx*ny*sizeof(dual));
+		memcpy(b.a+nx*ny*at, d->a+nx*ny*(at+num),(nz-at-num)*nx*ny*sizeof(dual));
+		d->Set(b);
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_insert_(uintptr_t *d, const char *dir, int *at, int *num, int)
+{	mgl_datac_insert(_DC_,*dir,*at,*num);	}
+void MGL_EXPORT mgl_datac_delete_(uintptr_t *d, const char *dir, int *at, int *num, int)
+{	mgl_datac_delete(_DC_,*dir,*at,*num);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_set_value(HADT dat, dual v, long i, long j, long k)
+{
+	if(i>=0 && i<dat->nx && j>=0 && j<dat->ny && k>=0 && k<dat->nz)
+		dat->a[i+dat->nx*(j+dat->ny*k)]=v;
+}
+void MGL_EXPORT mgl_datac_set_value_(uintptr_t *d, dual *v, int *i, int *j, int *k)
+{	mgl_datac_set_value(_DC_,*v,*i,*j,*k);	}
+//-----------------------------------------------------------------------------
+mdual MGL_EXPORT mgl_datac_get_value(HCDT dat, long i, long j, long k)
+{
+	long nx=dat->GetNx(), ny=dat->GetNy(), i0=i+nx*(j+ny*k);
+	if(i<0 || i>=nx || j<0 || j>=ny || k<0 || k>=dat->GetNz())
+		return NAN;
+	const mglDataC *d = dynamic_cast<const mglDataC*>(dat);
+	dual r = d ? d->a[i0] : dual(dat->vthr(i0),0);
+	return r.real()+r.imag()*mgl_I;
+}
+mdual MGL_EXPORT mgl_datac_get_value_(uintptr_t *d, int *i, int *j, int *k)
+{	return mgl_datac_get_value(_DA_(d),*i,*j,*k);	}
+//-----------------------------------------------------------------------------
+MGL_EXPORT dual *mgl_datac_data(HADT dat)	{	return dat->a;	}
+//-----------------------------------------------------------------------------
+MGL_EXPORT dual *mgl_datac_value(HADT dat, long i,long j,long k)
+{	long ii=i*dat->nx*(j+dat->ny*k);
+	return	ii>=0 && ii<dat->GetNN() ? dat->a+ii : 0;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_join(HADT d, HCDT v)
+{
+	long nx=d->nx, ny=d->ny, nz=d->nz, k=nx*ny*nz;
+	const mglDataC *mv = dynamic_cast<const mglDataC *>(v);
+	long vx=v->GetNx(), vy=v->GetNy(), vz=v->GetNz(), m = vx*vy*vz;
+
+	if(nx==vx && ny==vy && ny>1)	d->nz += vz;
+	else
+	{
+		ny *= nz;	vy *= vz;
+		if(nx==vx && nx>1)
+		{	d->nz = 1;	d->ny = ny+vy;	}
+		else
+		{	d->ny = d->nz = 1;	d->nx = k+m;	}
+	}
+	dual *b = new dual[k+m];
+	memcpy(b,d->a,k*sizeof(dual));
+	if(mv)	memcpy(b+k,mv->a,m*sizeof(dual));
+	else
+#pragma omp parallel for
+		for(long i=0;i<m;i++)	b[k+i] = v->vthr(i);
+	if(!d->link)	delete []d->a;
+	d->a = b;	d->link=false;	d->NewId();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_join_(uintptr_t *d, uintptr_t *val)
+{	mgl_datac_join(_DC_,_DA_(val));	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_put_val(HADT d, dual val, long xx, long yy, long zz)
+{
+	long nx=d->nx, ny=d->ny, nz=d->nz;
+	if(xx>=nx || yy>=ny || zz>=nz)	return;
+	dual *a=d->a;
+	if(xx>=0 && yy>=0 && zz>=0)	a[xx+nx*(yy+zz*ny)] = val;
+	else if(xx<0 && yy<0 && zz<0)
+#pragma omp parallel for
+		for(long i=0;i<nx*ny*nz;i++)	a[i] = val;
+	else if(xx<0 && yy<0)
+#pragma omp parallel for
+		for(long i=0;i<nx*ny;i++)	a[i+zz*nx*ny] = val;
+	else if(yy<0 && zz<0)
+#pragma omp parallel for
+		for(long i=0;i<nz*ny;i++)	a[xx+i*nx] = val;
+	else if(xx<0 && zz<0)
+#pragma omp parallel for collapse(2)
+		for(long i=0;i<nx;i++)	for(long j=0;j<nz;j++)	a[i+nx*(yy+j*ny)] = val;
+	else if(xx<0)
+#pragma omp parallel for
+		for(long i=0;i<nx;i++)	a[i+nx*(yy+zz*ny)] = val;
+	else if(yy<0)
+#pragma omp parallel for
+		for(long i=0;i<ny;i++)	a[xx+nx*(i+zz*ny)] = val;
+	else //if(zz<0)
+#pragma omp parallel for
+		for(long i=0;i<nz;i++)	a[xx+nx*(yy+i*ny)] = val;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_put_dat(HADT d, HCDT v, long xx, long yy, long zz)
+{
+	long nx=d->nx, ny=d->ny, nz=d->nz;
+	if(xx>=nx || yy>=ny || zz>=nz)	return;
+	const mglDataC *mv = dynamic_cast<const mglDataC *>(v);
+	dual *a=d->a, vv=v->v(0);
+	const dual *b = mv?mv->a:0;
+	long vx=v->GetNx(), vy=v->GetNy(), vz=v->GetNz();
+	if(xx<0 && yy<0 && zz<0)	// whole array
+	{
+		if(vx>=nx && vy>=ny && vz>=nz)
+#pragma omp parallel for
+			for(long ii=0;ii<nx*ny*nz;ii++)
+			{	long i=ii%nx, j=(ii/nx)%ny, k=ii/(nx*ny);
+				a[ii] = b?b[i+vx*(j+k*vy)]:v->v(i,j,k);	}
+		else if(vx>=nx && vy>=ny)
+#pragma omp parallel for
+			for(long ii=0;ii<nx*ny*nz;ii++)
+			{	long i=ii%nx, j=(ii/nx)%ny;
+				a[ii] = b?b[i+vx*j]:v->v(i,j);	}
+		else if(vx>=nx)
+#pragma omp parallel for
+			for(long ii=0;ii<nx*ny*nz;ii++)
+			{	long i=ii%nx;	a[ii] = b?b[i]:v->v(i);	}
+		else
+#pragma omp parallel for
+			for(long ii=0;ii<nx*ny*nz;ii++)	a[ii] = vv;
+	}
+	else if(xx<0 && yy<0)	// 2d
+	{
+		zz*=nx*ny;
+		if(vx>=nx && vy>=ny)
+#pragma omp parallel for
+			for(long ii=0;ii<nx*ny;ii++)
+			{	long i=ii%nx, j=ii/nx;
+				a[ii+zz] = b?b[i+vx*j]:v->v(i,j);	}
+		else if(vx>=nx)
+#pragma omp parallel for
+			for(long ii=0;ii<nx*ny;ii++)
+			{	long i=ii%nx;	a[ii+zz] = b?b[i]:v->v(i);	}
+		else
+#pragma omp parallel for
+			for(long ii=0;ii<nx*ny;ii++) 	a[ii+zz] = vv;
+	}
+	else if(yy<0 && zz<0)	// 2d
+	{
+		if(vx>=ny && vy>=nz)
+#pragma omp parallel for
+			for(long ii=0;ii<ny*nz;ii++)
+			{	long i=ii%ny, j=ii/ny;
+				a[ii*nx+xx] = b?b[i+vx*j]:v->v(i,j);	}
+		else if(vx>=ny)
+#pragma omp parallel for
+			for(long ii=0;ii<ny*nz;ii++)
+			{	long i=ii%ny;	a[ii*nx+xx] = b?b[i]:v->v(i);	}
+		else
+#pragma omp parallel for
+			for(long ii=0;ii<ny*nz;ii++) 	a[ii*nx+xx] = vv;
+	}
+	else if(xx<0 && zz<0)	// 2d
+	{
+		yy *= nx;	zz = nx*ny;
+		if(vx>=nx && vy>=nz)
+#pragma omp parallel for
+			for(long ii=0;ii<nx*nz;ii++)
+			{	long i=ii%nx, j=ii/nx;
+				a[i+yy+j*zz] = b?b[i+vx*j]:v->v(i,j);	}
+		else if(vx>=nx)
+#pragma omp parallel for
+			for(long ii=0;ii<nx*nz;ii++)
+			{	long i=ii%nx, j=ii/nx;
+				a[i+yy+j*zz] = b?b[i]:v->v(i);	}
+		else
+#pragma omp parallel for
+			for(long ii=0;ii<nx*nz;ii++)
+			{	long i=ii%nx, j=ii/nx;
+				a[i+yy+j*zz] = vv;	}
+	}
+	else if(xx<0)
+	{
+		xx = nx*(yy+zz*ny);
+		if(vx>=nx)
+#pragma omp parallel for
+			for(long i=0;i<nx;i++)	a[i+xx] = b?b[i]:v->v(i);
+		else
+#pragma omp parallel for
+			for(long i=0;i<nx;i++)	a[i+xx] = vv;
+	}
+	else if(yy<0)
+	{
+		xx += zz*nx*ny;
+		if(vx>=ny)
+#pragma omp parallel for
+			for(long i=0;i<ny;i++)	a[xx+nx*i] = b?b[i]:v->v(i);
+		else
+#pragma omp parallel for
+			for(long i=0;i<ny;i++)	a[xx+nx*i] = vv;
+	}
+	else if(zz<0)
+	{
+		xx += nx*yy;	yy = nx*ny;
+		if(vx>=nz)
+#pragma omp parallel for
+			for(long i=0;i<nz;i++)	a[xx+yy*i] = b?b[i]:v->v(i);
+		else
+#pragma omp parallel for
+			for(long i=0;i<nz;i++)	a[xx+yy*i] = vv;
+	}
+	else	a[xx+nx*(yy+ny*zz)] = vv;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_put_val_(uintptr_t *d, dual *val, int *i, int *j, int *k)
+{	mgl_datac_put_val(_DC_,*val, *i,*j,*k);	}
+void MGL_EXPORT mgl_datac_put_dat_(uintptr_t *d, uintptr_t *val, int *i, int *j, int *k)
+{	mgl_datac_put_dat(_DC_,_DA_(val), *i,*j,*k);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_difr_grid(dual *a,int n,int step,dual q,int Border,dual *tmp,int kk);
+void MGL_EXPORT mgl_difr_axial(dual *a,int n,int step,dual q,int Border,dual *tmp,int kk, double di);
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_difr(void *par)
+{
+#if !defined(_MSC_VER)	// MSVC produce internal compiler error on this code
+	mglThreadC *t=(mglThreadC *)par;
+	long n=t->p[0], st=t->p[1], bord=t->p[3], nn=t->n;
+	dual *b=t->a, q = *(t->b);
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel
+#endif
+	{
+		dual *tmp = new dual[2*n];
+		if(t->p[2])
+#if !MGL_HAVE_PTHREAD
+#pragma omp for
+#endif
+			for(long i=t->id;i<nn;i+=mglNumThr)
+				mgl_difr_axial(b + ((i%st)+n*(i/st)), n,st, q, bord,tmp,3,0);
+		else
+#if !MGL_HAVE_PTHREAD
+#pragma omp for
+#endif
+			for(long i=t->id;i<nn;i+=mglNumThr)
+				mgl_difr_grid(b + ((i%st)+n*(i/st)), n,st, q, bord,tmp,3);
+		delete []tmp;
+	}
+#endif
+	return 0;
+}
+void MGL_EXPORT mgl_datac_diffr(HADT d, const char *how, mreal q)
+{
+	if(!how || *how==0)	return;
+	long nx=d->nx,ny=d->ny,nz=d->nz;
+	long p[4]={0,0,0,0};
+	dual qq=q;
+	if(mglchr(how,'e'))	p[3]=-1;
+	if(mglchr(how,'g'))	p[3]=-2;
+	if(mglchr(how,'1'))	p[3]=1;
+	if(mglchr(how,'2'))	p[3]=2;
+	if(mglchr(how,'3'))	p[3]=3;
+	bool axial = mglchr(how,'r')||mglchr(how,'a');
+	if(mglchr(how,'z') && nz>1)
+	{
+		p[0]=nz;	p[1]=nx*ny;	p[2]=0;
+		mglStartThreadC(mgl_difr,0,nx*ny,d->a,&qq,0,p);
+	}
+	if(mglchr(how,'y') && ny>1 && !axial)
+	{
+		p[0]=ny;	p[1]=nx;	p[2]=0;
+		mglStartThreadC(mgl_difr,0,nx*nz,d->a,&qq,0,p);
+	}
+	if(mglchr(how,'x') && nx>1 && !axial)
+	{
+		p[0]=nx;	p[1]=1;	p[2]=0;
+		mglStartThreadC(mgl_difr,0,ny*nz,d->a,&qq,0,p);
+	}
+	if(axial && nx>1)
+	{
+		p[0]=nx;	p[1]=1;	p[2]=1;
+		mglStartThreadC(mgl_difr,0,ny*nz,0,&qq,0,p);
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_diffr_(uintptr_t *d, const char *how, double q,int l)
+{	char *s=new char[l+1];	memcpy(s,how,l);	s[l]=0;
+	mgl_datac_diffr(_DC_,s,q);	delete []s;	}
+//-----------------------------------------------------------------------------
+HADT MGL_EXPORT mgl_gsplinec_init(HCDT x, HCDT v)
+{
+	long n = v->GetNx();
+	if(!x || x->GetNx()!=n)	return 0;
+	mglDataC *res = new mglDataC(5*(n-1));
+	mreal *xx=0;
+	dual *vv=0;
+	const mglData *dx = dynamic_cast<const mglData *>(x);
+	if(!dx)
+	{
+		xx = new mreal[n];
+		for(long i=0;i<n;i++)	xx[i] = x->v(i);
+	}
+	const mglDataC *dv = dynamic_cast<const mglDataC *>(v);
+	if(!dv)
+	{
+		vv = new dual[n];
+		for(long i=0;i<n;i++)	vv[i] = v->v(i);
+	}
+	mgl_gspline_init(n,dx?dx->a:xx,dv?dv->a:vv,res->a);
+	if(xx)	delete []xx;
+	if(vv)	delete []vv;
+	return res;
+}
+uintptr_t MGL_EXPORT mgl_gsplinec_init_(uintptr_t *x, uintptr_t *v)
+{	return uintptr_t(mgl_gspline_init(_DA_(x),_DA_(v)));	}
+//-----------------------------------------------------------------------------
+mdual MGL_EXPORT mgl_gsplinec(HCDT c, mreal dx, dual *d1, dual *d2)
+{
+	long i=0, n = c->GetNx();
+	if(n%5)	return NAN;	// not the table of coefficients
+	while(dx>c->v(5*i) && i<n-1)	{	dx-=c->v(5*i);	i++;	}
+	dual res;
+	const mglDataC *d = dynamic_cast<const mglDataC *>(c);
+	if(c)
+	{
+		const dual *a = d->a+5*i;
+		if(d1)	*d1 = a[2]+dx*(mreal(2)*a[3]+(3*dx)*a[4]);
+		if(d2)	*d2 = mreal(2)*a[3]+(6*dx)*a[4];
+		res = a[1]+dx*(a[2]+dx*(a[3]+dx*a[4]));
+	}
+	else
+	{
+		if(d1)	*d1 = c->v(5*i+2)+dx*(2*c->v(5*i+3)+3*dx*c->v(5*i+4));
+		if(d2)	*d2 = 2*c->v(5*i+3)+6*dx*c->v(5*i+4);
+		res = c->v(5*i+1)+dx*(c->v(5*i+2)+dx*(c->v(5*i+3)+dx*c->v(5*i+4)));
+	}
+	return res.real()+res.imag()*mgl_I;
+}
+mdual MGL_EXPORT mgl_gsplinec_(uintptr_t *c, mreal *dx, dual *d1, dual *d2)
+{	return mgl_gsplinec(_DA_(c),*dx,d1,d2);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_refill_gs(HADT dat, HCDT xdat, HCDT vdat, mreal x1, mreal x2, long sl)
+{
+	HADT coef = mgl_gsplinec_init(xdat, vdat);
+	if(!coef)	return;	// incompatible dimensions
+	const long nx = dat->nx, nn=dat->ny*dat->nz;
+	mreal x0 = x1-xdat->v(0), dx = (x2-x1)/(nx-1);
+#pragma omp parallel for
+	for(long i=0;i<nx;i++)
+	{
+		dual d = mgl_gsplinec(coef,x0+dx*i,0,0);
+		if(sl<0)	for(long j=0;j<nn;j++)	dat->a[i+j*nx] = d;
+		else	dat->a[i+sl*nx] = d;
+	}
+	mgl_delete_datac(coef);
+}
+//-----------------------------------------------------------------------------
+mreal MGL_NO_EXPORT mgl_index_1(mreal v, HCDT dat);
+void MGL_EXPORT mgl_datac_refill_x(HADT dat, HCDT xdat, HCDT vdat, mreal x1, mreal x2, long sl)
+{
+	long nx=dat->nx,mx=vdat->GetNx(),nn=dat->ny*dat->nz;
+	if(mx!=xdat->GetNx())	return;	// incompatible dimensions
+	mreal dx = (x2-x1)/(nx-1);
+#pragma omp parallel for
+	for(long i=0;i<nx;i++)
+	{
+		mreal u = mgl_index_1(x1+dx*i,xdat);
+		dual d = mgl_datac_spline(vdat,u,0,0);
+		if(sl<0)	for(long j=0;j<nn;j++)	dat->a[i+j*nx] = d;
+		else	dat->a[i+sl*nx] = d;
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_refill_xy(HADT dat, HCDT xdat, HCDT ydat, HCDT vdat, mreal x1, mreal x2, mreal y1, mreal y2, long sl)
+{
+	long nx=dat->nx,ny=dat->ny,nz=dat->nz,mx=vdat->GetNx(),my=vdat->GetNy(),nn=nx*ny;
+	bool both=(xdat->GetNN()==vdat->GetNN() && ydat->GetNN()==vdat->GetNN());
+	if(!both && (xdat->GetNx()!=mx || ydat->GetNx()!=my))	return;	// incompatible dimensions
+	mreal dx = (x2-x1)/(nx-1), dy = (y2-y1)/(ny-1);
+	if(both)
+	{
+#pragma omp parallel for
+		for(long i=0;i<nn*nz;i++)	dat->a[i]=NAN;
+#pragma omp parallel for collapse(2)
+		for(long j=0;j<my-1;j++)	for(long i=0;i<mx-1;i++)
+		{
+			long i0 = i+mx*j;
+			mreal vx0 = (xdat->vthr(i0)-x1)/dx, vy0 = (ydat->vthr(i0)-y1)/dy;
+			mreal vx1 = (xdat->vthr(i0+1)-x1)/dx, vy1 = (ydat->vthr(i0+1)-y1)/dy;
+			mreal vx2 = (xdat->vthr(i0+mx)-x1)/dx, vy2 = (ydat->vthr(i0+mx)-y1)/dy;
+			mreal vx3 = (xdat->vthr(i0+mx+1)-x1)/dx, vy3 = (ydat->vthr(i0+mx+1)-y1)/dy;
+			long xx1 = long(mgl_min( mgl_min(vx0,vx1), mgl_min(vx2,vx3) ));	// bounding box
+			long yy1 = long(mgl_min( mgl_min(vy0,vy1), mgl_min(vy2,vy3) ));
+			long xx2 = long(mgl_max( mgl_max(vx0,vx1), mgl_max(vx2,vx3) ));
+			long yy2 = long(mgl_max( mgl_max(vy0,vy1), mgl_max(vy2,vy3) ));
+			xx1=mgl_max(xx1,0);	xx2=mgl_min(xx2,nx-1);
+			yy1=mgl_max(yy1,0);	yy2=mgl_min(yy2,ny-1);
+			if(xx1>xx2 || yy1>yy2)	continue;
+
+			mreal d1x = vx1-vx0, d1y = vy1-vy0;
+			mreal d2x = vx2-vx0, d2y = vy2-vy0;
+			mreal d3x = vx3+vx0-vx1-vx2, d3y = vy3+vy0-vy1-vy2;
+			mreal dd = d1x*d2y-d1y*d2x;
+			mreal dsx =-4*(d2y*d3x - d2x*d3y)*d1y;
+			mreal dsy = 4*(d2y*d3x - d2x*d3y)*d1x;
+
+			for(long jj=yy1;jj<=yy2;jj++)	for(long ii=xx1;ii<=xx2;ii++)
+			{
+				mreal xx = (ii-vx0), yy = (jj-vy0);
+				mreal s = dsx*xx + dsy*yy + (dd+d3y*xx-d3x*yy)*(dd+d3y*xx-d3x*yy);
+				if(s>=0)
+				{
+					s = sqrt(s);
+					mreal qu = d3x*yy - d3y*xx + dd + s;
+					mreal qv = d3y*xx - d3x*yy + dd + s;
+					mreal u = 2.f*(d2y*xx - d2x*yy)/qu;
+					mreal v = 2.f*(d1x*yy - d1y*xx)/qv;
+					if(u*(1.f-u)<0.f || v*(1.f-v)<0.f)	// first root bad
+					{
+						qu = d3x*yy - d3y*xx + dd - s;
+						qv = d3y*xx - d3x*yy + dd - s;
+						u = 2.f*(d2y*xx - d2x*yy)/qu;
+						v = 2.f*(d1x*yy - d1y*xx)/qv;
+						if(u*(1.f-u)<0.f || v*(1.f-v)<0.f)	continue;	// second root bad
+					}
+					i0 = ii+nx*jj;	s = vdat->value(i+u,j+v,0);
+					if(sl<0)	for(long k=0;k<nz;k++)	dat->a[i0+k*nn] = s;
+					else	dat->a[i0+sl*nn] = s;
+				}
+			}
+		}
+	}
+	else
+	{
+		mglData u(nx), v(ny);
+#pragma omp parallel for
+		for(long i=0;i<nx;i++)	u.a[i] = mgl_index_1(x1+dx*i,xdat);
+#pragma omp parallel for
+		for(long i=0;i<ny;i++)	v.a[i] = mgl_index_1(y1+dy*i,ydat);
+#pragma omp parallel for collapse(2)
+		for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+		{
+			dual d = mgl_datac_spline(vdat,u.a[i],v.a[j],0);
+			long i0=i+nx*j;
+			if(sl<0)	for(long k=0;k<nz;k++)	dat->a[i0+k*nn] = d;
+			else	dat->a[i0+sl*nn] = d;
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_refill_xyz(HADT dat, HCDT xdat, HCDT ydat, HCDT zdat, HCDT vdat, mreal x1, mreal x2, mreal y1, mreal y2, mreal z1, mreal z2)
+{
+	long nx=dat->nx,ny=dat->ny,nz=dat->nz,mx=vdat->GetNx(),my=vdat->GetNy(),mz=vdat->GetNz();
+	bool both=(xdat->GetNN()==vdat->GetNN() && ydat->GetNN()==vdat->GetNN() && zdat->GetNN()==vdat->GetNN());
+	if(!both && (xdat->GetNx()!=mx || ydat->GetNx()!=my || zdat->GetNx()!=mz))	return;	// incompatible dimensions
+	const mreal acx=1e-6*fabs(x2-x1), acy=1e-6*fabs(y2-y1), acz=1e-6*fabs(z2-z1);
+	if(both)
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<nz;k++)	for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+		{
+			mreal xx = x1+(x2-x1)*i/(nx-1.),dxx,dxy,dxz,vx,dx=0,dd;
+			mreal yy = y1+(y2-y1)*j/(ny-1.),dyx,dyy,dyz,vy,dy=0;
+			mreal zz = z1+(z2-z1)*k/(nz-1.),dzx,dzy,dzz,vz,dz=0;
+			vx = xdat->valueD(dx,dy,dz,&dxx,&dxy,&dxz);
+			vy = ydat->valueD(dx,dy,dz,&dyx,&dyy,&dyz);
+			vz = zdat->valueD(dx,dy,dz,&dzx,&dzy,&dzz);
+			long count=0;
+			do	// use Newton method to find root
+			{
+				if(count>50)	{	dx=NAN;	break;	}	count++;
+				dd = -dxx*dyy*dzz+dxy*dyx*dzz+dxx*dyz*dzy-dxz*dyx*dzy-dxy*dyz*dzx+dxz*dyy*dzx;
+				dx += ((dyz*dzy-dyy*dzz)*(xx-vx)+(dxy*dzz-dxz*dzy)*(yy-vy)+(dxz*dyy-dxy*dyz)*(zz-vz))/dd;
+				dy += ((dyx*dzz-dyz*dzx)*(xx-vx)+(dxz*dzx-dxx*dzz)*(yy-vy)+(dxx*dyz-dxz*dyx)*(zz-vz))/dd;
+				dz += ((dyy*dzx-dyx*dzy)*(xx-vx)+(dxx*dzy-dxy*dzx)*(yy-vy)+(dxy*dyx-dxx*dyy)*(zz-vz))/dd;
+				vx = xdat->valueD(dx,dy,dz,&dxx,&dxy,&dxz);
+				vy = ydat->valueD(dx,dy,dz,&dyx,&dyy,&dyz);
+				vz = zdat->valueD(dx,dy,dz,&dzx,&dzy,&dzz);
+			}	while(fabs(xx-vx)>acx && fabs(yy-vy)>acy && fabs(zz-vz)>acz);	// this valid for linear interpolation
+			dat->a[i+nx*(j+ny*k)] = mgl_isnan(dx)?NAN:vdat->value(dx,dy,dz);
+		}
+	else
+	{
+		mglData u(nx), v(ny), w(nz);
+		mreal dx = (x2-x1)/(nx-1), dy = (y2-y1)/(ny-1), dz = (z2-z1)/(nz-1);
+#pragma omp parallel for
+		for(long i=0;i<nx;i++)	u.a[i] = mgl_index_1(x1+dx*i,xdat);
+#pragma omp parallel for
+		for(long i=0;i<ny;i++)	v.a[i] = mgl_index_1(y1+dy*i,ydat);
+#pragma omp parallel for
+		for(long i=0;i<nz;i++)	w.a[i] = mgl_index_1(z1+dz*i,zdat);
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<nz;k++)	for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+			dat->a[i+nx*(j+ny*k)] = mgl_datac_spline(vdat,u.a[i],v.a[j],w.a[k]);
+	}
+}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_diffc_3(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nx=t->p[0], ny=t->p[1], nz=t->p[2], nn=t->n, n2=nx*ny;
+	dual *b=t->a,au,av,aw;
+	HCDT x=(HCDT)(t->c),y=(HCDT)(t->d),z=(HCDT)(t->e);
+	const dual *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for private(au,av,aw)
+#endif
+	for(long i0=t->id;i0<nn;i0+=mglNumThr)
+	{
+		long i=i0%nx, j=((i0/nx)%ny), k=i0/(nx*ny);
+		mreal xu,xv,xw,yu,yv,yw,zu,zv,zw;
+		if(i==0)
+		{
+			au = mreal(3)*a[i0]-mreal(4)*a[i0+1]+a[i0+2];
+			xu = 3*x->vthr(i0)-4*x->vthr(i0+1)+x->vthr(i0+2);
+			yu = 3*y->vthr(i0)-4*y->vthr(i0+1)+y->vthr(i0+2);
+			zu = 3*z->vthr(i0)-4*z->vthr(i0+1)+z->vthr(i0+2);
+		}
+		else if(i==nx-1)
+		{
+			au = mreal(3)*a[i0]-mreal(4)*a[i0-1]+a[i0-2];
+			xu = 3*x->vthr(i0)-4*x->vthr(i0-1)+x->vthr(i0-2);
+			yu = 3*y->vthr(i0)-4*y->vthr(i0-1)+y->vthr(i0-2);
+			zu = 3*z->vthr(i0)-4*z->vthr(i0-1)+z->vthr(i0-2);
+		}
+		else
+		{
+			au = a[i0+1]-a[i0-1];
+			xu = x->vthr(i0+1)-x->vthr(i0-1);
+			yu = y->vthr(i0+1)-y->vthr(i0-1);
+			zu = z->vthr(i0+1)-z->vthr(i0-1);
+		}
+		if(j==0)
+		{
+			av = mreal(3)*a[i0]-mreal(4)*a[i0+nx]+a[i0+2*nx];
+			xv = 3*x->vthr(i0)-4*x->vthr(i0+nx)+x->vthr(i0+2*nx);
+			yv = 3*y->vthr(i0)-4*y->vthr(i0+nx)+y->vthr(i0+2*nx);
+			zv = 3*z->vthr(i0)-4*z->vthr(i0+nx)+z->vthr(i0+2*nx);
+		}
+		else if(j==ny-1)
+		{
+			av = mreal(3)*a[i0]-mreal(4)*a[i0-nx]+a[i0+(ny-3)*nx];
+			xv = 3*x->vthr(i0)-4*x->vthr(i0-nx)+x->vthr(i0-2*nx);
+			yv = 3*y->vthr(i0)-4*y->vthr(i0-nx)+y->vthr(i0-2*nx);
+			zv = 3*z->vthr(i0)-4*z->vthr(i0-nx)+z->vthr(i0-2*nx);
+		}
+		else
+		{
+			av = a[i0+nx]-a[i0-nx];
+			xv = x->vthr(i0+nx)-x->vthr(i0-nx);
+			yv = y->vthr(i0+nx)-y->vthr(i0-nx);
+			zv = z->vthr(i0+nx)-z->vthr(i0-nx);
+		}
+		if(k==0)
+		{
+			aw = mreal(3)*a[i0]-mreal(4)*a[i0+n2]+a[i0+2*n2];
+			xw = 3*x->vthr(i0)-4*x->vthr(i0+n2)+x->vthr(i0+2*n2);
+			yw = 3*y->vthr(i0)-4*y->vthr(i0+n2)+y->vthr(i0+2*n2);
+			zw = 3*z->vthr(i0)-4*z->vthr(i0+n2)+z->vthr(i0+2*n2);
+		}
+		else if(k==nz-1)
+		{
+			aw = mreal(3)*a[i0]-mreal(4)*a[i0-n2]+a[i0-2*n2];
+			xw = 3*x->vthr(i0)-4*x->vthr(i0-n2)+x->vthr(i0-2*n2);
+			yw = 3*y->vthr(i0)-4*y->vthr(i0-n2)+y->vthr(i0-2*n2);
+			zw = 3*z->vthr(i0)-4*z->vthr(i0-n2)+z->vthr(i0-2*n2);
+		}
+		else
+		{
+			aw = a[i0+n2]-a[i0-n2];
+			xw = x->vthr(i0+n2)-x->vthr(i0-n2);
+			yw = y->vthr(i0+n2)-y->vthr(i0-n2);
+			zw = z->vthr(i0+n2)-z->vthr(i0-n2);
+		}
+		b[i0] = (au*yv*zw-av*yu*zw-au*yw*zv+aw*yu*zv+av*yw*zu-aw*yv*zu) / (xu*yv*zw-xv*yu*zw-xu*yw*zv+xw*yu*zv+xv*yw*zu-xw*yv*zu);
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_diffc_2(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nx=t->p[0], ny=t->p[1], nn=t->n, same=t->p[2];
+	dual *b=t->a,au,av;
+	HCDT x=(HCDT)(t->c),y=(HCDT)(t->d);
+	const dual *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for private(au,av)
+#endif
+	for(long i0=t->id;i0<nn;i0+=mglNumThr)
+	{
+		long i=i0%nx, j=((i0/nx)%ny), i1 = same ? i0 : i0%(nx*ny);
+		mreal xu,xv,yu,yv;
+		if(i==0)
+		{
+			au = mreal(3)*a[i0]-mreal(4)*a[i0+1]+a[i0+2];
+			xu = 3*x->vthr(i1)-4*x->vthr(i1+1)+x->vthr(i1+2);
+			yu = 3*y->vthr(i1)-4*y->vthr(i1+1)+y->vthr(i1+2);
+		}
+		else if(i==nx-1)
+		{
+			au = mreal(3)*a[i0]-mreal(4)*a[i0-1]+a[i0-2];
+			xu = 3*x->vthr(i1)-4*x->vthr(i1-1)+x->vthr(i1-2);
+			yu = 3*y->vthr(i1)-4*y->vthr(i1-1)+y->vthr(i1-2);
+		}
+		else
+		{
+			au = a[i0+1]-a[i0-1];
+			xu = x->vthr(i1+1)-x->vthr(i1-1);
+			yu = y->vthr(i1+1)-y->vthr(i1-1);
+		}
+		if(j==0)
+		{
+			av = mreal(3)*a[i0]-mreal(4)*a[i0+nx]+a[i0+2*nx];
+			xv = 3*x->vthr(i1)-4*x->vthr(i1+nx)+x->vthr(i1+2*nx);
+			yv = 3*y->vthr(i1)-4*y->vthr(i1+nx)+y->vthr(i1+2*nx);
+		}
+		else if(j==ny-1)
+		{
+			av = mreal(3)*a[i0]-mreal(4)*a[i0-nx]+a[i0-2*nx];
+			xv = 3*x->vthr(i1)-4*x->vthr(i1-nx)+x->vthr(i1-2*nx);
+			yv = 3*y->vthr(i1)-4*y->vthr(i1-nx)+y->vthr(i1-2*nx);
+		}
+		else
+		{
+			av = a[i0+nx]-a[i0-nx];
+			xv = x->vthr(i1+nx)-x->vthr(i1-nx);
+			yv = y->vthr(i1+nx)-y->vthr(i1-nx);
+		}
+		b[i0] = (av*yu-au*yv)/(xv*yu-xu*yv);
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_diffc_1(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nx=t->p[0], nn=t->n, same=t->p[1];
+	dual *b=t->a,au;
+	HCDT x=(HCDT)(t->c);
+	const dual *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for private(au)
+#endif
+	for(long i0=t->id;i0<nn;i0+=mglNumThr)
+	{
+		long i=i0%nx, i1 = same ? i0 : i;
+		mreal xu;
+		if(i==0)
+		{
+			au = mreal(3)*a[i0]-mreal(4)*a[i0+1]+a[i0+2];
+			xu = 3*x->vthr(i1)-4*x->vthr(i1+1)+x->vthr(i1+2);
+		}
+		else if(i==nx-1)
+		{
+			au = mreal(3)*a[i0]-mreal(4)*a[i0-1]+a[i0-2];
+			xu = 3*x->vthr(i1)-4*x->vthr(i1-1)+x->vthr(i1-2);
+		}
+		else
+		{
+			au = a[i0+1]-a[i0-1];
+			xu = x->vthr(i1+1)-x->vthr(i1-1);
+		}
+		b[i0] = au/xu;
+	}
+	return 0;
+}
+void MGL_EXPORT mgl_datac_diff_par(HADT d, HCDT x, HCDT y, HCDT z)
+{
+	long nx=d->GetNx(),ny=d->GetNy(),nz=d->GetNz(), nn=nx*ny*nz;
+	if(nx<2 || ny<2)	return;
+	dual *b = new dual[nn];	memset(b,0,nn*sizeof(dual));
+	long p[3]={nx,ny,nz};
+
+	if(x&&y&&z && x->GetNN()==nn && y->GetNN()==nn && z->GetNN()==nn)
+		mglStartThreadC(mgl_diffc_3,0,nn,b,d->a,(const dual *)x,p,0,(const dual *)y,(const dual *)z);
+	else if(x&&y && x->GetNx()*x->GetNy()==nx*ny && y->GetNx()*y->GetNy()==nx*ny)
+	{
+		p[2]=(x->GetNz()==nz && y->GetNz()==nz);
+		mglStartThreadC(mgl_diffc_2,0,nn,b,d->a,(const dual *)x,p,0,(const dual *)y);
+	}
+	else if(x && x->GetNx()==nx)
+	{
+		p[1]=(x->GetNy()*x->GetNz()==ny*nz);
+		mglStartThreadC(mgl_diffc_1,0,nn,b,d->a,(const dual *)x,p,0,0);
+	}
+	memcpy(d->a,b,nn*sizeof(dual));	delete []b;
+}
+void MGL_EXPORT mgl_datac_diff_par_(uintptr_t *d, uintptr_t *v1, uintptr_t *v2, uintptr_t *v3)
+{	mgl_datac_diff_par(_DC_,_DA_(v1),_DA_(v2),_DA_(v3));	}
+//-----------------------------------------------------------------------------
diff --git a/src/complex_ex.cpp b/src/complex_ex.cpp
new file mode 100644
index 0000000..7f889c1
--- /dev/null
+++ b/src/complex_ex.cpp
@@ -0,0 +1,706 @@
+/***************************************************************************
+ * data_new.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <ctype.h>
+#include "mgl2/datac.h"
+#include "mgl2/evalc.h"
+#include "mgl2/thread.h"
+#include "interp.hpp"
+HADT MGL_NO_EXPORT mglFormulaCalcC(const char *str, const std::vector<mglDataA*> &head);
+//-----------------------------------------------------------------------------
+HADT MGL_EXPORT mgl_datac_trace(HCDT d)
+{
+	long nx=d->GetNx(),ny=d->GetNy(),nz=d->GetNz();
+	const mglDataC *dc = dynamic_cast<const mglDataC *>(d);
+	mglDataC *r=new mglDataC(nx);
+	if(dc)
+	{
+		if(ny>=nx && nz>=nx)
+#pragma omp parallel for
+			for(long i=0;i<nx;i++)	r->a[i] = dc->a[i+nx*(i+ny*i)];
+		else if(ny>=nx)
+#pragma omp parallel for
+			for(long i=0;i<nx;i++)	r->a[i] = dc->a[i+nx*i];
+		else
+#pragma omp parallel for
+			for(long i=0;i<nx;i++)	r->a[i] = dc->a[i];
+	}
+	else if(ny>=nx && nz>=nx)
+#pragma omp parallel for
+		for(long i=0;i<nx;i++)	r->a[i] = d->v(i,i,i);
+	else if(ny>=nx)
+#pragma omp parallel for
+		for(long i=0;i<nx;i++)	r->a[i] = d->v(i,i);
+	else
+#pragma omp parallel for
+		for(long i=0;i<nx;i++)	r->a[i] = d->v(i);
+	return r;
+}
+uintptr_t MGL_EXPORT mgl_datac_trace_(uintptr_t *d)
+{	return uintptr_t(mgl_datac_trace(_DC_));	}
+//-----------------------------------------------------------------------------
+HADT MGL_EXPORT mgl_datac_subdata_ext(HCDT d, HCDT xx, HCDT yy, HCDT zz)
+{
+	if(!xx || !yy || !zz)
+	{
+		mglData tmp;	tmp.a[0]=-1;
+		return mgl_datac_subdata_ext(d,xx?xx:&tmp,yy?yy:&tmp,zz?zz:&tmp);
+	}
+
+	long n=0,m=0,l=0,j,k;
+	bool ix=false, iy=false, iz=false;
+	if(xx->GetNz()>1)	// 3d data
+	{
+		n = xx->GetNx();	m = xx->GetNy();	l = xx->GetNz();
+		j = yy->GetNN();	if(j>1 && j!=n*m*l)	return 0;	// wrong sizes
+		k = zz->GetNN();	if(k>1 && k!=n*m*l)	return 0;	// wrong sizes
+		ix = true;	iy = j>1;	iz = k>1;
+	}
+	else if(yy->GetNz()>1)
+	{
+		n = yy->GetNx();	m = yy->GetNy();	l = yy->GetNz();
+		j = xx->GetNN();	if(j>1 && j!=n*m*l)	return 0;	// wrong sizes
+		k = zz->GetNN();	if(k>1 && k!=n*m*l)	return 0;	// wrong sizes
+		iy = true;	ix = j>1;	iz = k>1;
+	}
+	else if(zz->GetNz()>1)
+	{
+		n = zz->GetNx();	m = zz->GetNy();	l = zz->GetNz();
+		j = yy->GetNN();	if(j>1 && j!=n*m*l)	return 0;	// wrong sizes
+		k = xx->GetNN();	if(k>1 && k!=n*m*l)	return 0;	// wrong sizes
+		iz = true;	iy = j>1;	ix = k>1;
+	}
+	else if(xx->GetNy()>1)	// 2d data
+	{
+		n = xx->GetNx();	m = xx->GetNy();	l = 1;
+		j = yy->GetNx()*yy->GetNy();	if(j>1 && j!=n*m)	return 0;	// wrong sizes
+		k = zz->GetNx()*zz->GetNy();	if(k>1 && k!=n*m)	return 0;	// wrong sizes
+		ix = true;	iy = j>1;	iz = k>1;
+	}
+	else if(yy->GetNy()>1)
+	{
+		n = yy->GetNx();	m = yy->GetNy();	l = 1;
+		j = xx->GetNx()*xx->GetNy();	if(j>1 && j!=n*m)	return 0;	// wrong sizes
+		k = zz->GetNx()*zz->GetNy();	if(k>1 && k!=n*m)	return 0;	// wrong sizes
+		iy = true;	ix = j>1;	iz = k>1;
+	}
+	else if(zz->GetNy()>1)
+	{
+		n = zz->GetNx();	m = zz->GetNy();	l = 1;
+		j = yy->GetNx()*yy->GetNy();	if(j>1 && j!=n*m)	return 0;	// wrong sizes
+		k = xx->GetNx()*xx->GetNy();	if(k>1 && k!=n*m)	return 0;	// wrong sizes
+		iz = true;	iy = j>1;	ix = k>1;
+	}
+	long nx=d->GetNx(),ny=d->GetNy(),nz=d->GetNz();
+	long vx=long(xx->v(0)), vy=long(yy->v(0)), vz=long(zz->v(0));
+	const mglDataC *dd = dynamic_cast<const mglDataC *>(d);
+	mglDataC *r;
+	if(n*m*l>1)	// this is 2d or 3d data
+	{
+		mglDataV tx(n,m,l),ty(n,m,l),tz(n,m,l);
+		if(!ix)	{	xx = &tx;	if(vx>=0)	tx.Fill(vx);	else tx.All();	}
+		if(!iy)	{	yy = &ty;	if(vy>=0)	ty.Fill(vy);	else ty.All();	}
+		if(!iz)	{	zz = &tz;	if(vz>=0)	tz.Fill(vz);	else tz.All();	}
+		r=new mglDataC(n,m,l);
+		if(dd)
+#pragma omp parallel for
+			for(long i0=0;i0<n*m*l;i0++)
+			{
+				long x=long(0.5+xx->vthr(i0)), y=long(0.5+yy->vthr(i0)), z=long(0.5+zz->vthr(i0));
+				r->a[i0] = (x>=0 && x<nx && y>=0 && y<ny && z>=0 && z<nz)?dd->a[x+nx*(y+ny*z)]:NAN;
+			}
+		else
+#pragma omp parallel for
+			for(long i0=0;i0<n*m*l;i0++)
+			{
+				long x=long(0.5+xx->vthr(i0)), y=long(0.5+yy->vthr(i0)), z=long(0.5+zz->vthr(i0));
+				r->a[i0] = (x>=0 && x<nx && y>=0 && y<ny && z>=0 && z<nz)?d->v(x,y,z):NAN;
+			}
+	}
+	else	// this is 1d data -> try as normal SubData()
+	{
+		mglDataV tx(nx),ty(ny),tz(nz);	tx.Fill(0,nx-1);	ty.Fill(0,ny-1);	tz.Fill(0,nz-1);
+		if(xx->GetNx()>1 || vx>=0)	n=xx->GetNx();	else	{	n=nx;	xx = &tx;	}
+		if(yy->GetNx()>1 || vy>=0)	m=yy->GetNx();	else	{	m=ny;	yy = &ty;	}
+		if(zz->GetNx()>1 || vz>=0)	l=zz->GetNx();	else	{	l=nz;	zz = &tz;	}
+		r=new mglDataC(n,m,l);
+		if(dd)
+#pragma omp parallel for collapse(3)
+			for(long k=0;k<l;k++)	for(long j=0;j<m;j++)	for(long i=0;i<n;i++)
+			{
+				long x=long(0.5+xx->v(i)), y=long(0.5+yy->v(j)), z=long(0.5+zz->v(k));
+				r->a[i+n*(j+m*k)] = (x>=0 && x<nx && y>=0 && y<ny && z>=0 && z<nz)?dd->a[x+nx*(y+ny*z)]:NAN;
+			}
+		else
+#pragma omp parallel for collapse(3)
+			for(long k=0;k<l;k++)	for(long j=0;j<m;j++)	for(long i=0;i<n;i++)
+			{
+				long x=long(0.5+xx->v(i)), y=long(0.5+yy->v(j)), z=long(0.5+zz->v(k));
+				r->a[i+n*(j+m*k)] = (x>=0 && x<nx && y>=0 && y<ny && z>=0 && z<nz)?d->v(x,y,z):NAN;
+			}
+		if(m==1)	{	r->ny=r->nz;	r->nz=1;	}// "squeeze" dimensions
+		if(n==1)	{	r->nx=r->ny;	r->ny=r->nz;	r->nz=1;	r->NewId();}
+	}
+	return r;
+}
+//-----------------------------------------------------------------------------
+HADT MGL_EXPORT mgl_datac_subdata(HCDT d, long xx,long yy,long zz)
+{
+	long nx=d->GetNx(),ny=d->GetNy(),nz=d->GetNz(), n=1,m=1,l=1;
+	int dx=0,dy=0,dz=0;
+	if(xx<0)	{	xx=0;	dx=1;	n=nx;	}
+	if(yy<0)	{	yy=0;	dy=1;	m=ny;	}
+	if(zz<0)	{	zz=0;	dz=1;	l=nz;	}
+	const mglDataC *dd = dynamic_cast<const mglDataC *>(d);
+	mglDataC *r=new mglDataC(n,m,l);
+	if(xx>=nx || yy>=ny || zz>=nz)
+#pragma omp parallel for
+		for(long i=0;i<n*m*l;i++)	r->a[i] = NAN;
+	else if(dd)
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<l;k++)	for(long j=0;j<m;j++)	for(long i=0;i<n;i++)
+			r->a[i+n*(j+m*k)] = dd->a[xx+dx*i + nx*(yy+dy*j + ny*(zz+dz*k))];
+	else
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<l;k++)	for(long j=0;j<m;j++)	for(long i=0;i<n;i++)
+			r->a[i+n*(j+m*k)] = d->v(xx+dx*i, yy+dy*j, zz+dz*k);
+	if(m==1)	{	r->ny=r->nz;	r->nz=1;	}// "squeeze" dimensions
+	if(n==1)	{	r->nx=r->ny;	r->ny=r->nz;	r->nz=1;	r->NewId();}
+	return r;
+}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_datac_subdata_(uintptr_t *d, int *xx,int *yy,int *zz)
+{	return uintptr_t(mgl_datac_subdata(_DC_,*xx,*yy,*zz));	}
+uintptr_t MGL_EXPORT mgl_datac_subdata_ext_(uintptr_t *d, uintptr_t *xx, uintptr_t *yy, uintptr_t *zz)
+{	return uintptr_t(mgl_datac_subdata_ext(_DC_,_DA_(xx),_DA_(yy),_DA_(zz)));	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_cresize(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nx=t->p[0]+0.1, ny=t->p[1]+0.1;
+	long n1=t->p[3]+0.1,n2=t->p[4]+0.1,n3=t->p[5]+0.1;
+	dual *b=t->a;
+	const dual *a=t->b;
+	const mreal *c=(const mreal *)t->v;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i0=t->id;i0<t->n;i0+=mglNumThr)
+	{
+		mreal i=(i0%nx), j=((i0/nx)%ny), k=(i0/(nx*ny));
+		b[i0] = mglSpline3Cs(a,n1,n2,n3, c[0]+i*c[1], c[2]+j*c[3], c[4]+k*c[5]);
+	}
+	return 0;
+}
+HADT MGL_EXPORT mgl_datac_resize_box(HCDT dat, long mx,long my,long mz, mreal x1,mreal x2, mreal y1,mreal y2, mreal z1,mreal z2)
+{	// NOTE: only for mglDataC
+	const mglDataC *d=dynamic_cast<const mglDataC *>(dat);
+	if(!d)	return 0;
+	long nx = d->nx-1, ny = d->ny-1, nz = d->nz-1;
+	mx = mx<1 ? nx+1:mx;	my = my<1 ? ny+1:my;	mz = mz<1 ? nz+1:mz;
+	mglDataC *r=new mglDataC(mx,my,mz);
+
+	mreal par[6]={nx*x1,0,ny*y1,0,nz*z1,0};
+	long nn[6]={mx,my,mz,nx+1,ny+1,nz+1};
+	if(mx>1)	par[1] = nx*(x2-x1)/(mx-1);
+	if(my>1)	par[3] = ny*(y2-y1)/(my-1);
+	if(mz>1)	par[5] = nz*(z2-z1)/(mz-1);
+	mglStartThreadC(mgl_cresize,0,mx*my*mz,r->a,d->a,0,nn,par);
+	return r;
+}
+HADT MGL_EXPORT mgl_datac_resize(HCDT d, long mx,long my,long mz)
+{	return mgl_datac_resize_box(d, mx,my,mz,0,1,0,1,0,1);	}
+uintptr_t MGL_EXPORT mgl_datac_resize_(uintptr_t *d, int *mx,int *my,int *mz)
+{	return uintptr_t(mgl_datac_resize(_DC_,*mx,*my,*mz));	}
+uintptr_t MGL_EXPORT mgl_datac_resize_box_(uintptr_t *d, int *mx,int *my,int *mz, mreal *x1,mreal *x2, mreal *y1,mreal *y2, mreal *z1,mreal *z2)
+{	return uintptr_t(mgl_datac_resize_box(_DC_,*mx,*my,*mz,*x1,*x2,*y1,*y2,*z1,*z2));	}
+//-----------------------------------------------------------------------------
+HADT MGL_EXPORT mgl_datac_combine(HCDT d1, HCDT d2)
+{
+	long n1=d1->GetNy(),n2=d2->GetNx(),nx=d1->GetNx();
+	if(d1->GetNz()>1 || (n1>1 && d2->GetNy()>1) || d2->GetNz()>1)	return 0;	// wrong dimensions
+	mglDataC *r=new mglDataC;
+	bool dim2=true;
+	if(n1==1)	{	n1=n2;	n2=d2->GetNy();	dim2 = false;	}
+	r->Create(nx,n1,n2);
+	if(dim2)	n1*=nx;	else	{	n2*=n1;	n1=nx;	}
+
+	const mglDataC *c1=dynamic_cast<const mglDataC *>(d1);
+	const mglDataC *c2=dynamic_cast<const mglDataC *>(d2);
+	if(c1 && c2)
+#pragma omp parallel for collapse(2)
+		for(long j=0;j<n2;j++)	for(long i=0;i<n1;i++)
+			r->a[i+n1*j] = c1->a[i]*c2->a[j];
+	else if(c1)
+#pragma omp parallel for collapse(2)
+		for(long j=0;j<n2;j++)	for(long i=0;i<n1;i++)
+			r->a[i+n1*j] = c1->a[i]*d2->vthr(j);
+	else if(c2)
+#pragma omp parallel for collapse(2)
+		for(long j=0;j<n2;j++)	for(long i=0;i<n1;i++)
+			r->a[i+n1*j] = d1->vthr(i)*c2->a[j];
+	else
+#pragma omp parallel for collapse(2)
+		for(long j=0;j<n2;j++)	for(long i=0;i<n1;i++)
+			r->a[i+n1*j] = d1->vthr(i)*d2->vthr(j);
+	return r;
+}
+uintptr_t MGL_EXPORT mgl_datac_combine_(uintptr_t *a, uintptr_t *b)
+{	return uintptr_t(mgl_datac_combine(_DA_(a),_DA_(b)));	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_sumc_z(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nz=t->p[2], nn=t->n;
+	dual *b=t->a;
+	const dual *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		b[i]=0;
+		for(long j=0;j<nz;j++)	b[i] += a[i+nn*j];
+		b[i] /= nz;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_sumc_y(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nx=t->p[0], ny=t->p[1], nn=t->n;
+	dual *b=t->a;
+	const dual *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = (i%nx)+nx*ny*(i/nx);	b[i]=0;
+		for(long j=0;j<ny;j++)	b[i] += a[k+nx*j];
+		b[i] /= ny;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_sumc_x(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nx=t->p[0], nn=t->n;
+	dual *b=t->a;
+	const dual *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = i*nx;	b[i]=0;
+		for(long j=0;j<nx;j++)	b[i] += a[j+k];
+		b[i] /= nx;
+	}
+	return 0;
+}
+HADT MGL_EXPORT mgl_datac_sum(HCDT dat, const char *dir)
+{
+	if(!dir || *dir==0)	return 0;
+	long nx=dat->GetNx(),ny=dat->GetNy(),nz=dat->GetNz();
+	long p[3]={nx,ny,nz};
+	dual *b = new dual[nx*ny*nz];
+	dual *c = new dual[nx*ny*nz];
+
+	const mglDataC *d=dynamic_cast<const mglDataC *>(dat);
+	if(d)	memcpy(c,d->a,nx*ny*nz*sizeof(dual));
+	else
+#pragma omp parallel for
+		for(long i=0;i<nx*ny*nz;i++)	c[i]=dat->vthr(i);
+
+	if(strchr(dir,'z') && nz>1)
+	{
+		mglStartThreadC(mgl_sumc_z,0,nx*ny,b,c,0,p);
+		memcpy(c,b,nx*ny*sizeof(dual));	p[2] = 1;
+	}
+	if(strchr(dir,'y') && ny>1)
+	{
+		mglStartThreadC(mgl_sumc_y,0,nx*p[2],b,c,0,p);
+		memcpy(c,b,nx*p[2]*sizeof(dual));	p[1] = p[2];	p[2] = 1;
+	}
+	if(strchr(dir,'x') && nx>1)
+	{
+		mglStartThreadC(mgl_sumc_x,0,p[1]*p[2],b,c,0,p);
+		p[0] = p[1];	p[1] = p[2];	p[2] = 1;
+		memcpy(c,b,p[0]*p[1]*sizeof(dual));
+	}
+	mglDataC *r=new mglDataC(p[0],p[1],p[2]);
+	memcpy(r->a,c,p[0]*p[1]*p[2]*sizeof(dual));
+	delete []b;	delete []c;	return r;
+}
+uintptr_t MGL_EXPORT mgl_datac_sum_(uintptr_t *d, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	uintptr_t r=uintptr_t(mgl_datac_sum(_DC_,s));	delete []s;	return r;	}
+//-----------------------------------------------------------------------------
+HADT MGL_EXPORT mgl_datac_momentum(HCDT dat, char dir, const char *how)
+{
+	if(!how || !(*how) || !strchr("xyz",dir))	return 0;
+	long nx=dat->GetNx(),ny=dat->GetNy(),nz=dat->GetNz();
+	mglDataV x(nx,ny,nz, 0,1,'x');	x.s=L"x";
+	mglDataV y(nx,ny,nz, 0,1,'y');	y.s=L"y";
+	mglDataV z(nx,ny,nz, 0,1,'z');	z.s=L"z";
+	mglDataC u(dat);	u.s=L"u";	// NOTE slow !!!
+	std::vector<mglDataA*> list;
+	list.push_back(&x);	list.push_back(&y);	list.push_back(&z);	list.push_back(&u);
+	HADT res=mglFormulaCalcC(how,list), b=0;
+
+	if(dir=='x')
+	{
+		b=new mglDataC(nx);
+#pragma omp parallel for
+		for(long i=0;i<nx;i++)
+		{
+			dual i1=0,i0=0;
+			for(long j=0;j<ny*nz;j++)
+			{
+				dual u=dat->vthr(i+nx*j);
+				i0 += u;	i1 += u*res->a[i+nx*j];
+			}
+			b->a[i] = i0!=mreal(0) ? i1/i0 : 0;
+		}
+	}
+	if(dir=='y')
+	{
+		b=new mglDataC(ny);
+#pragma omp parallel for
+		for(long i=0;i<ny;i++)
+		{
+			dual i1=0,i0=0;
+			for(long k=0;k<nz;k++)	for(long j=0;j<nx;j++)
+			{
+				dual u=dat->v(j,i,k);
+				i0 += u;	i1 += u*res->a[j+nx*(i+ny*k)];
+			}
+			b->a[i] = i0!=mreal(0) ? i1/i0 : 0;
+		}
+	}
+	if(dir=='z')
+	{
+		long nn=nx*ny;
+		b=new mglDataC(nz);
+#pragma omp parallel for
+		for(long i=0;i<nz;i++)
+		{
+			dual i1=0,i0=0;
+			for(long j=0;j<nn;j++)
+			{
+				dual u=dat->vthr(j+nn*i);
+				i0 += u;	i1 += u*res->a[j+nn*i];
+			}
+			b->a[i] = i0!=mreal(0) ? i1/i0 : 0;
+		}
+	}
+	mgl_delete_datac(res);	return b;
+}
+uintptr_t MGL_EXPORT mgl_datac_momentum_(uintptr_t *d, char *dir, const char *how, int,int l)
+{	char *s=new char[l+1];	memcpy(s,how,l);	s[l]=0;
+	uintptr_t r=uintptr_t(mgl_datac_momentum(_DC_,*dir, s));	delete []s;	return r;	}
+//-----------------------------------------------------------------------------
+HADT MGL_EXPORT mgl_datac_evaluate(HCDT dat, HCDT idat, HCDT jdat, HCDT kdat, int norm)
+{
+	if(!idat || (jdat && jdat->GetNN()!=idat->GetNN()) || (kdat && kdat->GetNN()!=idat->GetNN()))	return 0;
+	const mglData *dd=dynamic_cast<const mglData *>(dat);
+	const mglDataC *dc=dynamic_cast<const mglDataC *>(dat);
+	long nx=dat->GetNx(), ny=dat->GetNy(), nz=dat->GetNz();
+	mglDataC *r=new mglDataC(idat->GetNx(),idat->GetNy(),idat->GetNz());
+	mreal dx = nx-1, dy = ny-1, dz = nz-1;
+	if(!norm)	dx=dy=dz=1;
+	if(dd)
+#pragma omp parallel for
+		for(long i=0;i<idat->GetNN();i++)
+		{
+			mreal x=dx*idat->vthr(i), y=jdat?dy*jdat->vthr(i):0, z=kdat?dz*kdat->vthr(i):0;
+			r->a[i] = mgl_isnum(x*y*z)?mglSpline3st<mreal>(dd->a,nx,ny,nz, x,y,z):NAN;
+		}
+	else if(dc)
+#pragma omp parallel for
+		for(long i=0;i<idat->GetNN();i++)
+		{
+			mreal x=dx*idat->vthr(i), y=jdat?dy*jdat->vthr(i):0, z=kdat?dz*kdat->vthr(i):0;
+			r->a[i] = mgl_isnum(x*y*z)?mglSpline3st<dual>(dc->a,nx,ny,nz, x,y,z):NAN;
+		}
+	else
+#pragma omp parallel for
+		for(long i=0;i<idat->GetNN();i++)
+		{
+			mreal x=dx*idat->vthr(i), y=jdat?dy*jdat->vthr(i):0, z=kdat?dz*kdat->vthr(i):0;
+			r->a[i] = mgl_isnum(x*y*z)?dat->linear(x,y,z):NAN;;
+		}
+	return r;
+}
+uintptr_t MGL_EXPORT mgl_datac_evaluate_(uintptr_t *d, uintptr_t *idat, uintptr_t *jdat, uintptr_t *kdat, int *norm)
+{	return uintptr_t(mgl_datac_evaluate(_DC_,_DA_(idat),_DA_(jdat),_DA_(kdat),*norm));	}
+//-----------------------------------------------------------------------------
+HADT MGL_EXPORT mgl_datac_column(HCDT dat, const char *eq)
+{
+	const mglData *dd=dynamic_cast<const mglData *>(dat);
+	std::vector<mglDataA*> list;
+	if(dd && dd->id.length()>0)	for(size_t i=0;i<dd->id.length();i++)
+	{
+		mglDataT *col = new mglDataT(*dat);
+		col->SetInd(i,dd->id[i]);
+		list.push_back(col);
+	}
+	const mglDataC *dc=dynamic_cast<const mglDataC *>(dat);
+	if(dc && dc->id.length()>0)	for(size_t i=0;i<dc->id.length();i++)
+	{
+		mglDataT *col = new mglDataT(*dat);
+		col->SetInd(i,dc->id[i]);
+		list.push_back(col);
+	}
+	if(list.size()==0)	return 0;	// no named columns
+	mglDataV *t = new mglDataV(dat->GetNy(),dat->GetNz());
+	t->s=L"#$mgl";	list.push_back(t);
+	HADT r = mglFormulaCalcC(eq,list);
+	for(size_t i=0;i<list.size();i++)	delete list[i];
+	return r;
+}
+uintptr_t MGL_EXPORT mgl_datac_column_(uintptr_t *d, const char *eq,int l)
+{	char *s=new char[l+1];	memcpy(s,eq,l);	s[l]=0;
+	uintptr_t r = uintptr_t(mgl_datac_column(_DC_,s));
+	delete []s;	return r;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_mul_dat(HADT d, HCDT a)
+{
+	long nx=d->nx, ny=d->ny, nz=d->nz;
+	long mx=a->GetNx(), my=a->GetNy(), mz=a->GetNz();
+	const mglDataC *c = dynamic_cast<const mglDataC*>(a);
+
+	if(mz*my*mx==1)
+	{
+		dual v=c?c->a[0]:a->v(0);
+#pragma omp parallel for
+		for(long i=0;i<nx*ny*nz;i++)	d->a[i] += v;
+	}
+	else
+	{
+		long n=0, m=0;
+		if(nz*ny*nx==mz*my*mx)	{	n=nx*ny*nz;	m=1;	}
+		else if(ny*nx==my*mx)	{	n=nx*ny;	m=nz;	}
+		else if(nx==mx)			{	n=nx;	m=ny*nz;	}
+		if(c)
+#pragma omp parallel for collapse(2)
+			for(long k=0;k<m;k++)	for(long i=0;i<n;i++)	d->a[i+n*k] *= c->a[i];
+		else
+#pragma omp parallel for collapse(2)
+			for(long k=0;k<m;k++)	for(long i=0;i<n;i++)	d->a[i+n*k] *= a->vthr(i);
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_mul_num(HADT d, dual a)
+{
+	long n=d->GetNN();
+#pragma omp parallel for
+	for(long i=0;i<n;i++)	d->a[i] *= a;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_div_dat(HADT d, HCDT a)
+{
+	long nx=d->nx, ny=d->ny, nz=d->nz;
+	long mx=a->GetNx(), my=a->GetNy(), mz=a->GetNz();
+	const mglDataC *c = dynamic_cast<const mglDataC*>(a);
+
+	if(mz*my*mx==1)
+	{
+		dual v=c?c->a[0]:a->v(0);
+#pragma omp parallel for
+		for(long i=0;i<nx*ny*nz;i++)	d->a[i] /= v;
+	}
+	else
+	{
+		long n=0, m=0;
+		if(nz*ny*nx==mz*my*mx)	{	n=nx*ny*nz;	m=1;	}
+		else if(ny*nx==my*mx)	{	n=nx*ny;	m=nz;	}
+		else if(nx==mx)			{	n=nx;	m=ny*nz;	}
+		if(c)
+#pragma omp parallel for collapse(2)
+			for(long k=0;k<m;k++)	for(long i=0;i<n;i++)	d->a[i+n*k] /= c->a[i];
+		else
+#pragma omp parallel for collapse(2)
+			for(long k=0;k<m;k++)	for(long i=0;i<n;i++)	d->a[i+n*k] /= a->vthr(i);
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_div_num(HADT d, dual a)
+{
+	long n=d->GetNN();
+#pragma omp parallel for
+	for(long i=0;i<n;i++)	d->a[i] /= a;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_add_dat(HADT d, HCDT a)
+{
+	long nx=d->nx, ny=d->ny, nz=d->nz;
+	long mx=a->GetNx(), my=a->GetNy(), mz=a->GetNz();
+	const mglDataC *c = dynamic_cast<const mglDataC*>(a);
+
+	if(mz*my*mx==1)
+	{
+		dual v=c?c->a[0]:a->v(0);
+#pragma omp parallel for
+		for(long i=0;i<nx*ny*nz;i++)	d->a[i] += v;
+	}
+	else
+	{
+		long n=0, m=0;
+		if(nz*ny*nx==mz*my*mx)	{	n=nx*ny*nz;	m=1;	}
+		else if(ny*nx==my*mx)	{	n=nx*ny;	m=nz;	}
+		else if(nx==mx)			{	n=nx;	m=ny*nz;	}
+		if(c)
+#pragma omp parallel for collapse(2)
+			for(long k=0;k<m;k++)	for(long i=0;i<n;i++)	d->a[i+n*k] += c->a[i];
+		else
+#pragma omp parallel for collapse(2)
+			for(long k=0;k<m;k++)	for(long i=0;i<n;i++)	d->a[i+n*k] += a->vthr(i);
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_add_num(HADT d, dual a)
+{
+	long n=d->GetNN();
+#pragma omp parallel for
+	for(long i=0;i<n;i++)	d->a[i] += a;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_sub_dat(HADT d, HCDT a)
+{
+	long nx=d->nx, ny=d->ny, nz=d->nz;
+	long mx=a->GetNx(), my=a->GetNy(), mz=a->GetNz();
+	const mglDataC *c = dynamic_cast<const mglDataC*>(a);
+
+	if(mz*my*mx==1)
+	{
+		dual v=c?c->a[0]:a->v(0);
+#pragma omp parallel for
+		for(long i=0;i<nx*ny*nz;i++)	d->a[i] -= v;
+	}
+	else
+	{
+		long n=0, m=0;
+		if(nz*ny*nx==mz*my*mx)	{	n=nx*ny*nz;	m=1;	}
+		else if(ny*nx==my*mx)	{	n=nx*ny;	m=nz;	}
+		else if(nx==mx)			{	n=nx;	m=ny*nz;	}
+		if(c)
+#pragma omp parallel for collapse(2)
+			for(long k=0;k<m;k++)	for(long i=0;i<n;i++)	d->a[i+n*k] -= c->a[i];
+		else
+#pragma omp parallel for collapse(2)
+			for(long k=0;k<m;k++)	for(long i=0;i<n;i++)	d->a[i+n*k] -= a->vthr(i);
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_sub_num(HADT d, dual a)
+{
+	long n=d->GetNN();
+#pragma omp parallel for
+	for(long i=0;i<n;i++)	d->a[i] -= a;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_mul_dat_(uintptr_t *d, uintptr_t *b)	{	mgl_datac_mul_dat(_DC_, _DA_(b));	}
+void MGL_EXPORT mgl_datac_div_dat_(uintptr_t *d, uintptr_t *b)	{	mgl_datac_div_dat(_DC_, _DA_(b));	}
+void MGL_EXPORT mgl_datac_add_dat_(uintptr_t *d, uintptr_t *b)	{	mgl_datac_add_dat(_DC_, _DA_(b));	}
+void MGL_EXPORT mgl_datac_sub_dat_(uintptr_t *d, uintptr_t *b)	{	mgl_datac_sub_dat(_DC_, _DA_(b));	}
+void MGL_EXPORT mgl_datac_mul_num_(uintptr_t *d, dual *b)		{	mgl_datac_mul_num(_DC_, *b);	}
+void MGL_EXPORT mgl_datac_div_num_(uintptr_t *d, dual *b)		{	mgl_datac_div_num(_DC_, *b);	}
+void MGL_EXPORT mgl_datac_add_num_(uintptr_t *d, dual *b)		{	mgl_datac_add_num(_DC_, *b);	}
+void MGL_EXPORT mgl_datac_sub_num_(uintptr_t *d, dual *b)		{	mgl_datac_sub_num(_DC_, *b);	}
+//-----------------------------------------------------------------------------
+HADT MGL_EXPORT mgl_datac_section(HCDT dat, HCDT ids, char dir, mreal val)
+{
+	long di = 1, n = dat->GetNx();
+	if(dir=='y')	{	di = dat->GetNx();	n = dat->GetNy();	}
+	if(dir=='z')	{	di = dat->GetNx()*dat->GetNy();	n = dat->GetNz();	}
+	// first collect position of key values
+	std::vector<long> pos;	pos.push_back(0);
+	if(mgl_isnan(val))	for(long i=1;i<n;i++)
+	{
+		if(mgl_isnan(dat->vthr(i*di)))	pos.push_back(i);
+	}
+	else	for(long i=0;i<n;i++)
+	{
+		if(dat->vthr(i*di)==val)	pos.push_back(i);
+	}
+	pos.push_back(n);	// add last point (size of data)
+	// now collect required position from section and its lengths
+	std::vector<long> ls, ps;
+	long np = pos.size()-1, nl=0;
+	if(np<1)	return NULL;	// nothing to do
+	for(long i=0;i<ids->GetNN();i++)
+	{
+		long j = mgl_int(ids->vthr(i)+0.5);	j = j<0?np+j:j;
+		if(j>=0 && j<np)
+		{	long l = pos[j+1]-pos[j];	nl += l;
+			ls.push_back(l);	ps.push_back(pos[j]);	}
+	}
+	if(nl==0)	return NULL;
+	mglDataC *r=0;
+	size_t ns = ps.size();
+	if(dir=='y')
+	{
+		long nx=dat->GetNx(), nz=dat->GetNz(), sh=0;
+		r = new mglDataC(nx,nl,nz);
+		for(size_t s=0;s<ns;s++)
+		{
+			long pp = ps[s];
+#pragma omp parallel for collapse(3)
+			for(long k=0;k<nz;k++)	for(long j=0;j<ls[s];j++)	for(long i=0;i<nx;i++)
+				r->a[i+nx*(sh+j+nl*k)] = dat->vc(i,pp+j,k);
+			sh += ls[s];
+		}
+	}
+	else if(dir=='x')
+	{
+		long ny=dat->GetNy(), nz=dat->GetNz(), sh=0;
+		r = new mglDataC(nl,ny,nz);
+		for(size_t s=0;s<ns;s++)
+		{
+			long pp = ps[s];
+#pragma omp parallel for collapse(3)
+			for(long k=0;k<nz;k++)	for(long j=0;j<ny;j++)	for(long i=0;i<ls[s];i++)
+				r->a[sh+i+nl*(j+ny*k)] = dat->vc(pp+i,j,k);
+			sh += ls[s];
+		}
+	}
+	else if(dir=='z')
+	{
+		long nx=dat->GetNx(), ny=dat->GetNy(), sh=0;
+		r = new mglDataC(nx,ny,nl);
+		for(size_t s=0;s<ns;s++)
+		{
+			long pp = ps[s];
+#pragma omp parallel for collapse(3)
+			for(long k=0;k<ls[s];k++)	for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+				r->a[i+nx*(j+ny*(sh+k))] = dat->vc(i,j,pp+k);
+			sh += ls[s];
+		}
+	}
+	return r;
+}
+HADT MGL_EXPORT mgl_datac_section_val(HCDT dat, long id, char dir, mreal val)
+{	mglData v;	v.a[0]=id;	return mgl_datac_section(dat,&v,dir,val);	}
+uintptr_t MGL_EXPORT mgl_datac_section_(uintptr_t *d, uintptr_t *ids, const char *dir, mreal *val,int)
+{	return uintptr_t(mgl_datac_section(_DT_,_DA_(ids),dir[0],*val));	}
+uintptr_t MGL_EXPORT mgl_datac_section_val_(uintptr_t *d, int *id, const char *dir, mreal *val,int)
+{	return uintptr_t(mgl_datac_section_val(_DT_,*id,dir[0],*val));	}
+//-----------------------------------------------------------------------------
diff --git a/src/complex_io.cpp b/src/complex_io.cpp
new file mode 100644
index 0000000..792633e
--- /dev/null
+++ b/src/complex_io.cpp
@@ -0,0 +1,946 @@
+/***************************************************************************
+ * data_io.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <ctype.h>
+
+#ifndef WIN32
+#include <glob.h>
+#endif
+
+#include "mgl2/datac.h"
+#include "mgl2/evalc.h"
+#include "mgl2/thread.h"
+
+#if MGL_HAVE_HDF5
+#define H5_USE_16_API
+#include <hdf5.h>
+#endif
+
+inline bool isn(char ch)	{return ch=='\n';}
+MGL_NO_EXPORT char *mgl_read_gz(gzFile fp);
+HADT MGL_NO_EXPORT mglFormulaCalcC(const char *str, const std::vector<mglDataA*> &head);
+//-----------------------------------------------------------------------------
+HADT MGL_EXPORT mgl_create_datac()	{	return new mglDataC;	}
+HADT MGL_EXPORT mgl_create_datac_size(long nx, long ny, long nz){	return new mglDataC(nx,ny,nz);	}
+HADT MGL_EXPORT mgl_create_datac_file(const char *fname)		{	return new mglDataC(fname);	}
+void MGL_EXPORT mgl_delete_datac(HADT d)	{	if(d)	delete d;	}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_create_datac_()
+{	return uintptr_t(new mglDataC());	}
+uintptr_t MGL_EXPORT mgl_create_datac_size_(int *nx, int *ny, int *nz)
+{	return uintptr_t(new mglDataC(*nx,*ny,*nz));	}
+uintptr_t MGL_EXPORT mgl_create_datac_file_(const char *fname,int l)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	uintptr_t r = uintptr_t(new mglDataC(s));	delete []s;	return r;	}
+void MGL_EXPORT mgl_delete_datac_(uintptr_t *d)
+{	if(_DC_)	delete _DC_;	}
+//-----------------------------------------------------------------------------
+mdual MGL_EXPORT mgl_atoc(const char *s, int adv)
+{
+	double re=0,im=0;	size_t ll=strlen(s);
+	while(s[ll]<=' ')	ll--;
+	if(adv && *s=='(')		sscanf(s,"(%lg,%lg)",&re,&im);
+	else if(*s=='i')		{	re=0;	im=atof(s+1);	}
+	else if(adv && *s=='[')	sscanf(s,"[%lg,%lg]",&re,&im);
+	else if(adv && *s=='{')	sscanf(s,"{%lg,%lg}",&re,&im);
+	else if(s[ll]=='i')
+	{
+		double a,b;	//s[ll] = 0;
+		int s1=sscanf(s,"%lg+%lg",&re,&im);
+		int s2=sscanf(s,"%lg-%lg",&a,&b);
+		if(s1<2)
+		{
+			if(s2==2)	{	re=a;	im=-b;	}
+			else	{	im=atof(s);	re=0;	}
+		}
+	}
+	else
+	{
+		double a,b;
+		int s1=sscanf(s,"%lg+i%lg",&re,&im);
+		int s2=sscanf(s,"%lg-i%lg",&a,&b);
+		if(s1<2)
+		{
+			if(s2==2)	{	re=a;	im=-b;	}
+			else	{	re=atof(s);	im=0;	}
+		}
+	}
+	return re+im*mgl_I;
+}
+//-----------------------------------------------------------------------------
+void mglFromStr(HADT d,char *buf,long NX,long NY,long NZ)	// TODO: add multithreading read
+{
+	if(NX<1 || NY <1 || NZ<1)	return;
+	mgl_datac_create(d, NX,NY,NZ);
+	const std::string loc = setlocale(LC_NUMERIC, "C");
+	std::vector<char *> lines;
+	std::vector<std::vector<dual> > numbs;
+	lines.push_back(buf);
+	for(char *s=buf; *s; s++)	if(isn(*s))
+	{	lines.push_back(s+1);	*s = 0;	s++;	}
+	numbs.resize(lines.size());
+	long nl = long(lines.size());
+//#pragma omp parallel for
+	for(long k=0;k<nl;k++)
+	{
+		char *b = lines[k];
+		long nb = strlen(b);
+		for(long j=0;j<nb;j++)
+		{
+			while(j<nb && b[j]<=' ')	j++;	// skip first spaces
+			if(j>=nb)	break;
+			if(b[j]=='#')
+			{
+				if(j<nb-1 && b[j+1]=='#')	for(long i=j+2;i<nb;i++)
+					if(b[i]>='a' && b[i]<='z')	d->id.push_back(b[i]);
+				break;
+			}
+			char *s=b+j;
+			long sk=0;
+			while(j<nb && b[j]>' ' && ((b[j]!=',' && b[j]!=' ') || sk!=0) && b[j]!=';')
+			{
+				if(strchr("[{(",b[j]))	sk++;
+				if(strchr("]})",b[j]))	sk--;
+				j++;
+			}
+			b[j]=0;
+			numbs[k].push_back(mgl_atoc(s,true));
+		}
+	}
+	long i=0, n=NX*NY*NZ;
+	for(long k=0;k<nl && i<n;k++)
+	{
+		std::vector<dual> &vals = numbs[k];
+		long c = vals.size();
+		if(c>n-i)	c = n-i;
+		memcpy(d->a+i,&(vals[0]),c*sizeof(dual));
+		i += c;
+	}
+	setlocale(LC_NUMERIC, loc.c_str());
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_set(HADT d, HCDT a)
+{
+	if(!a)	return;
+	const mglDataC *dd = dynamic_cast<const mglDataC *>(a);	// faster for mglData
+	mgl_datac_create(d, a->GetNx(), a->GetNy(), a->GetNz());
+	if(dd)	// this one should be much faster
+		memcpy(d->a, dd->a, d->nx*d->ny*d->nz*sizeof(dual));
+	else	// very inefficient!!!
+	{
+		for(long k=0;k<d->nz;k++)	for(long j=0;j<d->ny;j++)	for(long i=0;i<d->nx;i++)
+			d->a[i+d->nx*(j+d->ny*k)] = a->v(i,j,k);
+	}
+}
+void MGL_EXPORT mgl_datac_set_(uintptr_t *d, uintptr_t *a)	{	mgl_datac_set(_DC_,_DA_(a));	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_set_values(HADT d, const char *v,long NX,long NY,long NZ)
+{
+	if(NX<1 || NY <1 || NZ<1)	return;
+	long n=strlen(v)+1;
+	char *buf = new char[n];
+	memcpy(buf,v,n);
+	mglFromStr(d,buf,NX,NY,NZ);
+	delete []buf;
+}
+void MGL_EXPORT mgl_datac_set_values_(uintptr_t *d, const char *val, int *nx, int *ny, int *nz, int l)
+{	char *s=new char[l+1];	memcpy(s,val,l);	s[l]=0;
+	mgl_datac_set_values(_DC_,s,*nx,*ny,*nz);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_set_vector(HADT d, gsl_vector *v)
+{
+#if MGL_HAVE_GSL
+	if(!v || v->size<1)	return;
+	mgl_datac_create(d, v->size,1,1);
+	for(long i=0;i<d->nx;i++)	d->a[i] = v->data[i*v->stride];
+#endif
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_set_matrix(HADT d, gsl_matrix *m)
+{
+#if MGL_HAVE_GSL
+	if(!m || m->size1<1 || m->size2<1)	return;
+	mgl_datac_create(d, m->size1,m->size2,1);
+	for(long j=0;j<d->ny;j++)	for(long i=0;i<d->nx;i++)
+		d->a[i+j*d->nx] = m->data[i * m->tda + j];
+#endif
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_set_float(HADT d, const float *A,long NX,long NY,long NZ)
+{
+	if(NX<=0 || NY<=0 || NZ<=0)	return;
+	mgl_datac_create(d, NX,NY,NZ);	if(!A)	return;
+#pragma omp parallel for
+	for(long i=0;i<NX*NY*NZ;i++)	d->a[i] = A[i];
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_set_double(HADT d, const double *A,long NX,long NY,long NZ)
+{
+	if(NX<=0 || NY<=0 || NZ<=0)	return;
+	mgl_datac_create(d, NX,NY,NZ);	if(!A)	return;
+#pragma omp parallel for
+	for(long i=0;i<NX*NY*NZ;i++)	d->a[i] = A[i];
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_set_complex(HADT d, const dual *A,long NX,long NY,long NZ)
+{
+	if(NX<=0 || NY<=0 || NZ<=0)	return;
+	mgl_datac_create(d, NX,NY,NZ);	if(!A)	return;
+	memcpy(d->a,A,NX*NY*NZ*sizeof(float));
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_set_float_(uintptr_t *d, const float *A,int *NX,int *NY,int *NZ)
+{	mgl_datac_set_float(_DC_,A,*NX,*NY,*NZ);	}
+void MGL_EXPORT mgl_datac_set_double_(uintptr_t *d, const double *A,int *NX,int *NY,int *NZ)
+{	mgl_datac_set_double(_DC_,A,*NX,*NY,*NZ);	}
+void MGL_EXPORT mgl_datac_set_complex_(uintptr_t *d, const dual *A,int *NX,int *NY,int *NZ)
+{	mgl_datac_set_complex(_DC_,A,*NX,*NY,*NZ);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_rearrange(HADT d, long mx,long my,long mz)
+{
+	if(mx<1)	return;	// wrong mx
+	if(my<1)	{	my = d->nx*d->ny*d->nz/mx;	mz = 1;	}
+	else if(mz<1)	mz = (d->nx*d->ny*d->nz)/(mx*my);
+	long m = mx*my*mz;
+	if(m==0 || m>d->nx*d->ny*d->nz)	return;	// too high desired dimensions
+	d->nx = mx;	d->ny = my;	d->nz = mz;	d->NewId();
+}
+void MGL_EXPORT mgl_datac_rearrange_(uintptr_t *d, int *mx, int *my, int *mz)
+{	mgl_datac_rearrange(_DC_,*mx,*my,*mz);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_set_id(HADT d, const char *ids)	{	d->id = ids;	}
+void MGL_EXPORT mgl_datac_set_id_(uintptr_t *d, const char *eq,int l)
+{	char *s=new char[l+1];	memcpy(s,eq,l);	s[l]=0;
+	mgl_datac_set_id(_DC_, s);	delete []s;	}
+//-----------------------------------------------------------------------------
+std::string MGL_EXPORT mgl_datac_to_string(HCDT d, long ns)
+{
+	std::string out;
+	const mglDataC *dd = dynamic_cast<const mglDataC*>(d);
+	if(!dd)	{	return	mgl_data_to_string(d,ns);	}
+	long nx=dd->nx, ny=dd->ny, nz=dd->nz;
+	const std::string loc = setlocale(LC_NUMERIC, "C");
+	if(ns<0 || (ns>=nz && nz>1))	for(long k=0;k<nz;k++)
+	{	// save whole data
+		const mglDataC *dc = dynamic_cast<const mglDataC *>(d);
+		if(dc && !dc->id.empty())	out += "## "+dc->id+'\n';
+		for(long i=0;i<ny;i++)
+		{
+			for(long j=0;j<nx-1;j++)
+				out+=mgl_str_num(dd->a[j+nx*(i+ny*k)])+'\t';
+			out+=mgl_str_num(dd->a[nx-1+nx*(i+ny*k)])+'\n';
+		}
+		out += "\n";
+	}
+	else
+	{	// save selected slice
+		if(nz>1)	for(long i=0;i<ny;i++)
+		{
+			for(long j=0;j<nx-1;j++)
+				out+=mgl_str_num(dd->a[j+nx*(i+ny*ns)])+'\t';
+			out+=mgl_str_num(dd->a[nx-1+nx*(i+ny*ns)])+'\n';
+		}
+		else if(ns<ny)	for(long j=0;j<nx;j++)
+			out+=mgl_str_num(dd->a[j+nx*ns])+'\t';
+	}
+	setlocale(LC_NUMERIC, loc.c_str());
+	return out;
+}
+void MGL_EXPORT mgl_datac_save(HCDT d, const char *fname,long ns)
+{
+	FILE *fp = fopen(fname,"w");
+	if(fp)	{	fprintf(fp,"%s",mgl_datac_to_string(d,ns).c_str());	fclose(fp);	}
+}
+void MGL_EXPORT mgl_datac_save_(uintptr_t *d, const char *fname,int *ns,int l)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	mgl_datac_save(_DC_,s,*ns);		delete []s;	}
+//-----------------------------------------------------------------------------
+int MGL_EXPORT mgl_datac_read(HADT d, const char *fname)
+{
+	long l=1,m=1,k=1,sk=0;
+	long nb,i;
+	gzFile fp = gzopen(fname,"r");
+	if(!fp)
+	{
+		if(!d->a)	mgl_datac_create(d, 1,1,1);
+		return	0;
+	}
+	char *buf = mgl_read_gz(fp);
+	nb = strlen(buf);	gzclose(fp);
+
+	bool first=false;	// space is not allowed delimiter for file with complex numbers
+	for(i=nb-1;i>=0;i--)	if(buf[i]>' ')	break;
+	buf[i+1]=0;	nb = i+1;		// remove tailing spaces
+	for(i=0;i<nb-1 && !isn(buf[i]);i++)	// determine nx
+	{
+		while(buf[i]=='#')	{	while(!isn(buf[i]) && i<nb)	i++;	}
+		char ch = buf[i];
+		if(ch>' ' && !first)	first=true;
+		if(strchr("[{(",ch))	sk++;
+		if(strchr("]})",ch))	sk--;
+		if(first && buf[i+1]>' ' && (ch=='\t' || ch==';' || ((ch==' '||ch==',') && sk==0) ))	k++;
+	}
+	first = false;
+	for(i=0;i<nb-1;i++)					// determine ny
+	{
+		char ch = buf[i];
+		if(ch=='#')	while(!isn(buf[i]) && i<nb)	i++;
+		if(isn(ch))
+		{
+			while(buf[i+1]=='\t') i++;
+			if(isn(buf[i+1]))	{first=true;	break;	}
+			m++;
+		}
+		if(ch=='\f')	break;
+	}
+	if(first)	for(i=0;i<nb-1;i++)		// determine nz
+	{
+		char ch = buf[i];
+		if(ch=='#')	while(!isn(buf[i]) && i<nb)	i++;
+//		if(ch=='#')	com = true;	// comment
+		if(isn(ch))
+		{
+//			if(com)	{	com=false;	continue;	}
+			while(buf[i+1]=='\t') i++;
+			if(isn(buf[i+1]))	l++;
+		}
+	}
+	else	for(i=0;i<nb-1;i++)	if(buf[i]=='\f')	l++;
+	mglFromStr(d,buf,k,m,l);
+	free(buf);	return 1;
+}
+int MGL_EXPORT mgl_datac_read_(uintptr_t *d, const char *fname,int l)
+{	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
+	int r = mgl_datac_read(_DC_, s);	delete []s;		return r;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_create(HADT d,long mx,long my,long mz)
+{
+	d->nx = mx>0 ? mx:1;	d->ny = my>0 ? my:1;	d->nz = mz>0 ? mz:1;
+	if(d->a && !d->link)	delete [](d->a);
+	d->a = new dual[d->nx*d->ny*d->nz];
+	d->id.clear();	d->link=false;
+	memset(d->a,0,d->nx*d->ny*d->nz*sizeof(dual));
+}
+void MGL_EXPORT mgl_datac_create_(uintptr_t *d, int *nx,int *ny,int *nz)
+{	mgl_datac_create(_DC_,*nx,*ny,*nz);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_link(HADT d, dual *A, long mx,long my,long mz)
+{
+	if(!A)	return;
+	if(!d->link && d->a)	delete [](d->a);
+	d->nx = mx>0 ? mx:1;	d->ny = my>0 ? my:1;	d->nz = mz>0 ? mz:1;
+	d->link=true;	d->a=A;	d->NewId();
+}
+void MGL_EXPORT mgl_datac_link_(uintptr_t *d, dual *A, int *nx,int *ny,int *nz)
+{	mgl_datac_link(_DC_,A,*nx,*ny,*nz);	}
+//-----------------------------------------------------------------------------
+int MGL_EXPORT mgl_datac_read_dim(HADT d, const char *fname,long mx,long my,long mz)
+{
+	if(mx<=0 || my<=0 || mz<=0)	return 0;
+	gzFile fp = gzopen(fname,"r");
+	if(!fp)	return 0;
+	char *buf = mgl_read_gz(fp);
+	gzclose(fp);
+	mglFromStr(d,buf,mx,my,mz);
+	free(buf);	return 1;
+}
+int MGL_EXPORT mgl_datac_read_dim_(uintptr_t *d, const char *fname,int *mx,int *my,int *mz,int l)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	int r = mgl_datac_read_dim(_DC_,s,*mx,*my,*mz);	delete []s;	return r;	}
+//-----------------------------------------------------------------------------
+int MGL_EXPORT mgl_datac_read_mat(HADT d, const char *fname, long dim)
+{
+	if(dim<=0 || dim>3)	return 0;
+	gzFile fp = gzopen(fname,"r");
+	if(!fp)	return 0;
+	long nx=1, ny=1, nz=1;
+	char *buf = mgl_read_gz(fp);
+	long nb = strlen(buf);	gzclose(fp);
+
+	long j=0;
+	if(buf[j]=='#')	while(!isn(buf[j]))	j++;	// skip comment
+	while(j<nb && buf[j]<=' ')	j++;
+	if(dim==1)
+	{
+		sscanf(buf+j,"%ld",&nx);
+		while(j<nb && buf[j]!='\n')	j++;
+		j++;
+//		while(buf[j]>' ')	j++;
+	}
+	else if(dim==2)
+	{
+		sscanf(buf+j,"%ld%ld",&nx,&ny);
+		while(j<nb && buf[j]!='\n')	j++;
+		j++;
+		char *b=buf+j;
+		long l=0;
+		for(long i=0;b[i];i++)
+		{
+			while(b[i]=='#')	{	while(!isn(b[i]) && b[i])	i++;	}
+			if(b[i]=='\n')	l++;
+		}
+		if(l==nx*ny || l==nx*ny+1)	// try to read 3d data (i.e. columns of matrix nx*ny)
+		{
+			nz=ny;	ny=nx;	nx=1;	l=0;
+			bool first = false;
+			for(long i=0;b[i] && !isn(b[i]);i++)	// determine nx
+			{
+				while(b[i]=='#')	{	while(!isn(b[i]) && b[i])	i++;	}
+				char ch = b[i];
+				if(ch>' ' && !first)	first=true;
+				if(first && (ch=='\t' || ch==';') && b[i+1]!='\t') nx++;
+			}
+		}
+	}
+	else if(dim==3)
+	{
+		sscanf(buf+j,"%ld%ld%ld",&nx,&ny,&nz);
+		while(j<nb && buf[j]!='\n')	j++;
+		j++;
+	}
+	mglFromStr(d,buf+j,nx,ny,nz);
+	free(buf);	return 1;
+}
+int MGL_EXPORT mgl_datac_read_mat_(uintptr_t *d, const char *fname,int *dim,int l)
+{	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
+	int r = mgl_datac_read_mat(_DC_,s,*dim);	delete []s;	return r;	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_cfill_x(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	long nx=t->p[0],ny=t->p[1];
+	dual *b=t->a, x1=t->b[0], dx=t->b[1];
+	char dir = t->s[0];
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i0=t->id;i0<t->n;i0+=mglNumThr)
+	{
+		if(dir=='x') b[i0] = x1+dx*mreal(i0%nx);
+		else if(dir=='y') b[i0] = x1+dx*mreal((i0/nx)%ny);
+		else if(dir=='z') b[i0] = x1+dx*mreal(i0/(nx*ny));
+	}
+	return 0;
+}
+void MGL_EXPORT mgl_datac_fill(HADT d, dual x1,dual x2,char dir)
+{
+	if(mgl_isnan(x2))	x2=x1;
+	if(dir<'x' || dir>'z')	dir='x';
+	long par[2]={d->nx,d->ny};
+	dual b[2]={x1,x2-x1};
+	if(dir=='x')	b[1] *= d->nx>1 ? 1./(d->nx-1):0;
+	if(dir=='y')	b[1] *= d->ny>1 ? 1./(d->ny-1):0;
+	if(dir=='z')	b[1] *= d->nz>1 ? 1./(d->nz-1):0;
+	mglStartThreadC(mgl_cfill_x,0,d->nx*d->ny*d->nz,d->a,b,0,par,0,0,0,&dir);
+}
+void MGL_EXPORT mgl_datac_fill_(uintptr_t *d, dual *x1,dual *x2,const char *dir,int)
+{	mgl_datac_fill(_DC_,*x1,*x2,*dir);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_squeeze(HADT d, long rx,long ry,long rz,long smooth)
+{
+	long kx,ky,kz, nx=d->nx, ny=d->ny, nz=d->nz;
+	dual *b;
+
+	// simple checking
+	if(rx>=nx)	rx=nx-1;
+	if(rx<1)	rx=1;
+	if(ry>=ny)	ry=ny-1;
+	if(ry<1)	ry=1;
+	if(rz>=nz)	rz=nz-1;
+	if(rz<1)	rz=1;
+	// new sizes
+	kx = 1+(nx-1)/rx;	ky = 1+(ny-1)/ry;	kz = 1+(nz-1)/rz;
+	b = new dual[kx*ky*kz];
+	if(!smooth)
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<kz;k++)	for(long j=0;j<ky;j++)	for(long i=0;i<kx;i++)
+			b[i+kx*(j+ky*k)] = d->a[i*rx+nx*(j*ry+ny*rz*k)];
+	else
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<kz;k++)	for(long j=0;j<ky;j++)	for(long i=0;i<kx;i++)
+		{
+			long dx,dy,dz,i1,j1,k1;
+			dx = (i+1)*rx<=nx ? rx : nx-i*rx;
+			dy = (j+1)*ry<=ny ? ry : ny-j*ry;
+			dz = (k+1)*rz<=nz ? rz : nz-k*rz;
+			dual s = 0;
+			for(k1=k*rz;k1<k*rz+dz;k1++)	for(j1=j*ry;j1<j*ry+dz;j1++)	for(i1=i*rx;i1<i*rx+dx;i1++)
+				s += d->a[i1+nx*(j1+ny*k1)];
+			b[i+kx*(j+ky*k)] = s/mreal(dx*dy*dz);
+		}
+	if(!d->link)	delete [](d->a);
+	d->a=b;	d->nx = kx;  d->ny = ky;  d->nz = kz;	d->NewId();	d->link=false;
+}
+void MGL_EXPORT mgl_datac_squeeze_(uintptr_t *d, int *rx,int *ry,int *rz,int *smooth)
+{	mgl_datac_squeeze(_DC_,*rx,*ry,*rz,*smooth);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_extend(HADT d, long n1, long n2)
+{
+	long nx=d->nx, ny=d->ny, nz=d->nz;
+	if(nz>2 || n1==0)	return;
+	long mx, my, mz;
+	dual *b=0;
+	if(n1>0) // extend to higher dimension(s)
+	{
+		n2 = n2>0 ? n2:1;
+		mx = nx;	my = ny>1?ny:n1;	mz = ny>1 ? n1 : n2;
+		b = new dual[mx*my*mz];
+		if(ny>1)
+#pragma omp parallel for
+			for(long i=0;i<n1;i++)	memcpy(b+i*nx*ny, d->a, nx*ny*sizeof(dual));
+		else
+#pragma omp parallel for
+			for(long i=0;i<n1*n2;i++)	memcpy(b+i*nx, d->a, nx*sizeof(dual));
+	}
+	else
+	{
+		mx = -n1;	my = n2<0 ? -n2 : nx;	mz = n2<0 ? nx : ny;
+		if(n2>0 && ny==1)	mz = n2;
+		b = new dual[mx*my*mz];
+		dual v;
+		if(n2<0)
+#pragma omp parallel for collapse(2)
+			for(long j=0;j<nx;j++)	for(long i=0;i<mx*my;i++)
+				b[i+mx*my*j] = d->a[j];
+		else
+#pragma omp parallel for collapse(2)
+			for(long j=0;j<nx*ny;j++)	for(long i=0;i<mx;i++)
+				b[i+mx*j] = d->a[j];
+		if(n2>0 && ny==1)
+#pragma omp parallel for
+			for(long i=0;i<n2;i++)	memcpy(b+i*mx*my, d->a, mx*my*sizeof(dual));
+	}
+	if(!d->link)	delete [](d->a);
+	d->a=b;	d->nx=mx;	d->ny=my;	d->nz=mz;
+	d->NewId();		d->link=false;
+}
+void MGL_EXPORT mgl_datac_extend_(uintptr_t *d, int *n1, int *n2)
+{	mgl_datac_extend(_DC_,*n1,*n2);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_transpose(HADT d, const char *dim)
+{
+	long nx=d->nx, ny=d->ny, nz=d->nz, n;
+	dual *b=new dual[nx*ny*nz], *a=d->a;
+	if(!strcmp(dim,"xyz"))	memcpy(b,a,nx*ny*nz*sizeof(dual));
+	else if(!strcmp(dim,"xzy") || !strcmp(dim,"zy"))
+	{
+#pragma omp parallel for collapse(3)
+		for(long j=0;j<ny;j++)	for(long k=0;k<nz;k++)	for(long i=0;i<nx;i++)
+			b[i+nx*(k+nz*j)] = a[i+nx*(j+ny*k)];
+		n=nz;	nz=ny;	ny=n;
+	}
+	else if(!strcmp(dim,"yxz") || !strcmp(dim,"yx"))
+	{
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<nz;k++)	for(long i=0;i<nx;i++)	for(long j=0;j<ny;j++)
+			b[j+ny*(i+nx*k)] = a[i+nx*(j+ny*k)];
+		n=nx;	nx=ny;	ny=n;
+	}
+	else if(!strcmp(dim,"yzx"))
+	{
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<nz;k++)	for(long i=0;i<nx;i++)	for(long j=0;j<ny;j++)
+			b[j+ny*(k+nz*i)] = a[i+nx*(j+ny*k)];
+		n=nx;	nx=ny;	ny=nz;	nz=n;
+	}
+	else if(!strcmp(dim,"zxy"))
+	{
+#pragma omp parallel for collapse(3)
+		for(long i=0;i<nx;i++)	for(long j=0;j<ny;j++)	for(long k=0;k<nz;k++)
+			b[k+nz*(i+nx*j)] = a[i+nx*(j+ny*k)];
+		n=nx;	nx=nz;	nz=ny;	ny=n;
+	}
+	else if(!strcmp(dim,"zyx") || !strcmp(dim,"zx"))
+	{
+#pragma omp parallel for collapse(3)
+		for(long i=0;i<nx;i++)	for(long j=0;j<ny;j++)	for(long k=0;k<nz;k++)
+			b[k+nz*(j+ny*i)] = a[i+nx*(j+ny*k)];
+		n=nz;	nz=nx;	nx=n;
+	}
+	memcpy(a,b,nx*ny*nz*sizeof(dual));	delete []b;
+	n=d->nx;	d->nx=nx;	d->ny=ny;	d->nz=nz;
+	if(nx!=n)	d->NewId();
+}
+void MGL_EXPORT mgl_datac_transpose_(uintptr_t *d, const char *dim,int l)
+{	char *s=new char[l+1];	memcpy(s,dim,l);	s[l]=0;
+	mgl_datac_transpose(_DC_,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_cmodify(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	const mglFormulaC *f = (const mglFormulaC *)(t->v);
+	long nx=t->p[0],ny=t->p[1],nz=t->p[2];
+	dual *b=t->a;
+	mreal dx,dy,dz;
+	const dual *v=t->b, *w=t->c;
+	dx=nx>1?1/(nx-1.):0;	dy=ny>1?1/(ny-1.):0;	dz=nz>1?1/(nz-1.):0;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i0=t->id;i0<t->n;i0+=mglNumThr)
+	{
+		long i=i0%nx, j=((i0/nx)%ny), k=i0/(nx*ny);
+		b[i0] = f->Calc(i*dx, j*dy, k*dz, b[i0], v?v[i0]:dual(0,0), w?w[i0]:dual(0,0));
+	}
+	return 0;
+}
+void MGL_EXPORT mgl_datac_modify(HADT d, const char *eq,long dim)
+{
+	long nx=d->nx, ny=d->ny, nz=d->nz, par[3]={nx,ny,nz};
+	if(dim<=0)	mgl_datac_modify_vw(d,eq,0,0);	// fastest variant for whole array
+	mglFormulaC f(eq);
+	if(nz>1)	// 3D array
+	{
+		par[2] -= dim;	if(par[2]<0)	par[2]=0;
+		mglStartThreadC(mgl_cmodify,0,nx*ny*par[2],d->a+nx*ny*dim,0,0,par,&f);
+	}
+	else		// 2D or 1D array
+	{
+		par[1] -= dim;	if(par[1]<0)	par[1]=0;
+		mglStartThreadC(mgl_cmodify,0,nx*par[1],d->a+nx*dim,0,0,par,&f);
+	}
+}
+void MGL_EXPORT mgl_datac_modify_(uintptr_t *d, const char *eq,int *dim,int l)
+{	char *s=new char[l+1];	memcpy(s,eq,l);	s[l]=0;
+	mgl_datac_modify(_DC_,s,*dim);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_modify_vw(HADT d, const char *eq,HCDT vdat,HCDT wdat)
+{
+	std::wstring s = d->s;	d->s = L"u";
+	mglDataV x(d->nx,d->ny,d->nz, 0,1,'x');	x.s=L"x";
+	mglDataV y(d->nx,d->ny,d->nz, 0,1,'y');	y.s=L"y";
+	mglDataV z(d->nx,d->ny,d->nz, 0,1,'z');	z.s=L"z";
+	mglDataV i(d->nx,d->ny,d->nz, 0,d->nx-1,'x');	i.s=L"i";
+	mglDataV j(d->nx,d->ny,d->nz, 0,d->ny-1,'y');	j.s=L"j";
+	mglDataV k(d->nx,d->ny,d->nz, 0,d->nz-1,'z');	k.s=L"k";
+	mglDataV r(d->nx,d->ny,d->nz);	r.s=L"#$mgl";
+	mglData v(vdat), w(wdat);	v.s = L"v";	w.s = L"w";
+	std::vector<mglDataA*> list;
+	list.push_back(&x);	list.push_back(&y);	list.push_back(&z);	list.push_back(d);
+	list.push_back(&v);	list.push_back(&w);	list.push_back(&r);
+	list.push_back(&i);	list.push_back(&j);	list.push_back(&k);
+	d->Move(mglFormulaCalcC(eq,list));	d->s = s;
+}
+void MGL_EXPORT mgl_datac_modify_vw_(uintptr_t *d, const char *eq, uintptr_t *v, uintptr_t *w,int l)
+{	char *s=new char[l+1];	memcpy(s,eq,l);	s[l]=0;
+	mgl_datac_modify_vw(_DC_,s,_DA_(v),_DA_(w));	delete []s;	}
+//-----------------------------------------------------------------------------
+bool MGL_NO_EXPORT mgl_add_file(long &kx,long &ky, long &kz, dual *&b, mglDataC *d,bool as_slice)
+{
+	if(as_slice && d->nz==1)
+	{
+		if(kx==d->nx && d->ny==1)
+		{
+			b = (dual *)realloc(b,kx*(ky+1)*sizeof(dual));
+			memcpy(b+kx*ky,d->a,kx*sizeof(dual));		ky++;
+		}
+		else if(kx==d->nx && ky==d->ny)
+		{
+			b = (dual *)realloc(b,kx*ky*(kz+1)*sizeof(dual));
+			memcpy(b+kx*ky*kz,d->a,kx*ky*sizeof(dual));	kz++;
+		}
+		else	return false;
+	}
+	else
+	{
+		if(d->ny*d->nz==1 && ky*kz==1)
+		{
+			b = (dual *)realloc(b,(kx+d->nx)*sizeof(dual));
+			memcpy(b+kx,d->a,d->nx*sizeof(dual));	kx+=d->nx;
+		}
+		else if(kx==d->nx && kz==1 && d->nz==1)
+		{
+			b = (dual *)realloc(b,kx*(ky+d->ny)*sizeof(dual));
+			memcpy(b+kx*ky,d->a,kx*d->ny*sizeof(dual));	ky+=d->ny;
+		}
+		else if(kx==d->nx && ky==d->ny)
+		{
+			b = (dual *)realloc(b,kx*kx*(kz+d->nz)*sizeof(dual));
+			memcpy(b+kx*ky*kz,d->a,kx*ky*d->nz*sizeof(dual));	kz+=d->nz;
+		}
+		else	return false;
+	}
+	return true;
+}
+//-----------------------------------------------------------------------------
+int MGL_EXPORT mgl_datac_read_range(HADT dat, const char *templ, double from, double to, double step, int as_slice)
+{
+	mglDataC d;
+	double t = from;
+	dual *b;
+	long kx,ky,kz,n=strlen(templ)+20;
+	char *fname = new char[n];
+
+	//read first file
+	do{	snprintf(fname,n,templ,t);	fname[n-1]=0;	t+= step;	} while(!mgl_datac_read(&d,fname) && t<=to);
+
+	if(t>to)	{	delete []fname;	return 0;	}
+	kx = d.nx;	ky = d.ny;	kz = d.nz;
+	b = (dual *)malloc(kx*ky*kz*sizeof(dual));
+	memcpy(b,d.a,kx*ky*kz*sizeof(dual));
+
+	// read other files
+	for(;t<=to;t+=step)
+	{
+		snprintf(fname,n,templ,t);	fname[n-1]=0;
+		if(mgl_datac_read(&d,fname))
+			if(!mgl_add_file(kx,ky,kz,b,&d,as_slice))
+			{	delete []fname;	free(b);	return 0;	}
+	}
+	dat->Set(b,kx,ky,kz);
+	delete []fname;	free(b);
+	return 1;
+}
+int MGL_EXPORT mgl_datac_read_range_(uintptr_t *d, const char *fname, mreal *from, mreal *to, mreal *step, int *as_slice,int l)
+{	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
+	int r = mgl_datac_read_range(_DC_,s,*from,*to,*step,*as_slice);	delete []s;	return r;	}
+//-----------------------------------------------------------------------------
+int MGL_EXPORT mgl_datac_read_all(HADT dat, const char *templ, int as_slice)
+{
+#ifndef WIN32
+	mglDataC d;
+	glob_t res;
+	size_t i;
+	dual *b;
+	long kx,ky,kz;
+	glob (templ, GLOB_TILDE, NULL, &res);
+
+	//read first file
+	for(i=0;i<res.gl_pathc;i++)
+		if(mgl_datac_read(&d,res.gl_pathv[i]))	break;
+
+	if(i>=res.gl_pathc)	{	globfree (&res);	return 0;	}
+	kx = d.nx;	ky = d.ny;	kz = d.nz;
+	b = (dual *)malloc(kx*ky*kz*sizeof(dual));
+	memcpy(b,d.a,kx*ky*kz*sizeof(dual));
+
+	for(;i<res.gl_pathc;i++)
+	{
+		if(mgl_datac_read(&d,res.gl_pathv[i]))
+			if(!mgl_add_file(kx,ky,kz,b,&d,as_slice))
+			{	globfree (&res);	free(b);	return 0;	}
+	}
+	dat->Set(b,kx,ky,kz);
+
+	globfree (&res);	free(b);
+	return 1;
+#else
+	return 0;
+#endif
+}
+int MGL_EXPORT mgl_datac_read_all_(uintptr_t *d, const char *fname, int *as_slice,int l)
+{	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
+	int r = mgl_datac_read_all(_DC_,s,*as_slice);	delete []s;	return r;	}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_datac_real(HCDT d)
+{
+	long nx=d->GetNx(),ny=d->GetNy(),nz=d->GetNz();
+	mglData *r=new mglData(nx,ny,nz);
+	const mglDataC *dd = dynamic_cast<const mglDataC*>(d);
+	if(dd)
+#pragma omp parallel for
+		for(long i=0;i<nx*ny*nz;i++)	r->a[i] = real(dd->a[i]);
+	else		r->Set(d);
+	return r;
+}
+uintptr_t MGL_EXPORT mgl_datac_real_(uintptr_t *d)
+{	return uintptr_t(mgl_datac_real(_DC_));	}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_datac_imag(HCDT d)
+{
+	long nx=d->GetNx(),ny=d->GetNy(),nz=d->GetNz();
+	mglData *r=new mglData(nx,ny,nz);
+	const mglDataC *dd = dynamic_cast<const mglDataC*>(d);
+	if(dd)
+#pragma omp parallel for
+		for(long i=0;i<nx*ny*nz;i++)	r->a[i] = imag(dd->a[i]);
+	return r;
+}
+uintptr_t MGL_EXPORT mgl_datac_imag_(uintptr_t *d)
+{	return uintptr_t(mgl_datac_imag(_DC_));	}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_datac_norm(HCDT d)
+{
+	long nx=d->GetNx(),ny=d->GetNy(),nz=d->GetNz();
+	mglData *r=new mglData(nx,ny,nz);
+	const mglDataC *dd = dynamic_cast<const mglDataC*>(d);
+	if(dd)
+#pragma omp parallel for
+		for(long i=0;i<nx*ny*nz;i++)	r->a[i] = norm(dd->a[i]);
+	else
+#pragma omp parallel for
+		for(long i=0;i<nx*ny*nz;i++)	r->a[i] = mgl_ipow(d->vthr(i),2);
+	return r;
+}
+uintptr_t MGL_EXPORT mgl_datac_norm_(uintptr_t *d)
+{	return uintptr_t(mgl_datac_norm(_DC_));	}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_datac_abs(HCDT d)
+{
+	long nx=d->GetNx(),ny=d->GetNy(),nz=d->GetNz();
+	mglData *r=new mglData(nx,ny,nz);
+	const mglDataC *dd = dynamic_cast<const mglDataC*>(d);
+	if(dd)
+#pragma omp parallel for
+		for(long i=0;i<nx*ny*nz;i++)	r->a[i] = abs(dd->a[i]);
+	else
+#pragma omp parallel for
+		for(long i=0;i<nx*ny*nz;i++)	r->a[i] = fabs(d->vthr(i));
+	return r;
+}
+uintptr_t MGL_EXPORT mgl_datac_abs_(uintptr_t *d)
+{	return uintptr_t(mgl_datac_abs(_DC_));	}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_datac_arg(HCDT d)
+{
+	long nx=d->GetNx(),ny=d->GetNy(),nz=d->GetNz();
+	mglData *r=new mglData(nx,ny,nz);
+	const mglDataC *dd = dynamic_cast<const mglDataC*>(d);
+	if(dd)
+#pragma omp parallel for
+		for(long i=0;i<nx*ny*nz;i++)	r->a[i] = arg(dd->a[i]);
+	return r;
+}
+uintptr_t MGL_EXPORT mgl_datac_arg_(uintptr_t *d)
+{	return uintptr_t(mgl_datac_arg(_DC_));	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_set_ri(HADT d, HCDT re, HCDT im)
+{
+	long nx=d->GetNx(),ny=d->GetNy(),nz=d->GetNz();
+	d->Create(nx,ny,nz);
+#pragma omp parallel for
+	for(long i=0;i<nx*ny*nz;i++)	d->a[i] = dual(re->vthr(i),im->vthr(i));
+}
+void MGL_EXPORT mgl_datac_set_ri_(uintptr_t *d, uintptr_t *re, uintptr_t *im)
+{	mgl_datac_set_ri(_DC_,_DA_(re),_DA_(im));	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_set_ap(HADT d, HCDT a, HCDT p)
+{
+	long nx=d->GetNx(),ny=d->GetNy(),nz=d->GetNz();
+	d->Create(nx,ny,nz);
+#pragma omp parallel for
+	for(long i=0;i<nx*ny*nz;i++)
+	{
+		mreal aa=a->vthr(i), pp=p->vthr(i);
+		d->a[i] = dual(aa*cos(pp), aa*sin(pp));
+	}
+}
+void MGL_EXPORT mgl_datac_set_ap_(uintptr_t *d, uintptr_t *a, uintptr_t *p)
+{	mgl_datac_set_ap(_DC_,_DA_(a),_DA_(p));	}
+//-----------------------------------------------------------------------------
+#if MGL_HAVE_HDF5
+void MGL_EXPORT mgl_datac_save_hdf(HCDT dat,const char *fname,const char *data,int rewrite)
+{
+	const mglDataC *d = dynamic_cast<const mglDataC *>(dat);
+	if(!d)	{	mgl_data_save_hdf(dat,fname,data,rewrite);	return;	}
+	hid_t hf,hd,hs;
+	hsize_t dims[4];
+	long rank = 3, res;
+	H5Eset_auto(0,0);
+	res=H5Fis_hdf5(fname);
+	if(res>0 && !rewrite)	hf = H5Fopen(fname, H5F_ACC_RDWR, H5P_DEFAULT);
+	else	hf = H5Fcreate(fname, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+	if(hf<0)	return;
+	if(d->nz==1 && d->ny == 1)	{	rank=2;	dims[0]=d->nx;	dims[1]=2;	}
+	else if(d->nz==1)	{	rank=3;	dims[0]=d->ny;	dims[1]=d->nx;	dims[2]=2;	}
+	else	{	rank=4;	dims[0]=d->nz;	dims[1]=d->ny;	dims[2]=d->nx;	dims[3]=2;	}
+	hs = H5Screate_simple(rank, dims, 0);
+#if MGL_USE_DOUBLE
+	hid_t mem_type_id = H5T_NATIVE_DOUBLE;
+#else
+	hid_t mem_type_id = H5T_NATIVE_FLOAT;
+#endif
+	hd = H5Dcreate(hf, data, mem_type_id, hs, H5P_DEFAULT);
+	H5Dwrite(hd, mem_type_id, hs, hs, H5P_DEFAULT, d->a);
+	H5Dclose(hd);	H5Sclose(hs);	H5Fclose(hf);
+}
+//-----------------------------------------------------------------------------
+int MGL_EXPORT mgl_datac_read_hdf(HADT d,const char *fname,const char *data)
+{
+	hid_t hf,hd,hs;
+	hsize_t dims[4];
+	long rank, res = H5Fis_hdf5(fname);
+	if(res<=0)	return 0;
+	hf = H5Fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT);
+	if(hf<0)	return 0;
+	hd = H5Dopen(hf,data);
+	if(hd<0)	return 0;
+	hs = H5Dget_space(hd);
+	rank = H5Sget_simple_extent_ndims(hs);
+	if(rank>0 && rank<=4)
+	{
+		H5Sget_simple_extent_dims(hs,dims,0);
+		if(dims[rank-1]==2)
+		{
+			if(rank==1)			{	dims[2]=dims[0]=dims[1]=1;	}
+			else if(rank==2)	{	dims[2]=dims[0];	dims[0]=dims[1]=1;	}
+			else if(rank==3)	{	dims[2]=dims[1];	dims[1]=dims[0];	dims[0]=1;	}
+			mgl_datac_create(d,dims[2],dims[1],dims[0]);
+#if MGL_USE_DOUBLE
+			H5Dread(hd, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, d->a);
+#else
+			H5Dread(hd, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, d->a);
+#endif
+		}
+		else if(rank<=3)
+		{
+			if(rank==1)			{	dims[2]=dims[0];	dims[0]=dims[1]=1;	}
+			else if(rank==2)	{	dims[2]=dims[1];	dims[1]=dims[0];	dims[0]=1;	}
+			mgl_datac_create(d,dims[2],dims[1],dims[0]);
+			long nn = dims[2]*dims[1]*dims[0];
+			mreal *a = new mreal[nn];
+#if MGL_USE_DOUBLE
+			H5Dread(hd, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, a);
+#else
+			H5Dread(hd, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, a);
+#endif
+			for(long i=0;i<nn;i++)	d->a[i] = a[i];
+			delete []a;
+		}
+	}
+	H5Sclose(hs);	H5Dclose(hd);	H5Fclose(hf);	return 1;
+}
+//-----------------------------------------------------------------------------
+#else
+void MGL_EXPORT mgl_datac_save_hdf(HCDT ,const char *,const char *,int )
+{	mgl_set_global_warn(_("HDF5 support was disabled. Please, enable it and rebuild MathGL."));	}
+int MGL_EXPORT mgl_datac_read_hdf(HADT ,const char *,const char *)
+{	mgl_set_global_warn(_("HDF5 support was disabled. Please, enable it and rebuild MathGL."));	return 0;}
+#endif
+//-----------------------------------------------------------------------------
+int MGL_EXPORT mgl_datac_read_hdf_(uintptr_t *d, const char *fname, const char *data,int l,int n)
+{	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
+	char *t=new char[n+1];		memcpy(t,data,n);	t[n]=0;
+	int r = mgl_datac_read_hdf(_DC_,s,t);	delete []s;	delete []t;	return r;	}
+void MGL_EXPORT mgl_datac_save_hdf_(uintptr_t *d, const char *fname, const char *data, int *rewrite,int l,int n)
+{	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
+	char *t=new char[n+1];		memcpy(t,data,n);	t[n]=0;
+	mgl_datac_save_hdf(_DC_,s,t,*rewrite);	delete []s;	delete []t;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_limit(HADT d, mreal v)
+{
+	long n = d->GetNN();
+	dual *a = d->a;
+	#pragma omp parallel for
+	for(long i=0;i<n;i++)
+	{	mreal b = abs(a[i]);	if(b>v)	a[i] *= v/b;	}
+}
+void MGL_EXPORT mgl_datac_limit_(uintptr_t *d, mreal *v)
+{	mgl_datac_limit(_DC_, *v);	}
+//-----------------------------------------------------------------------------
diff --git a/src/cont.cpp b/src/cont.cpp
new file mode 100644
index 0000000..49e8122
--- /dev/null
+++ b/src/cont.cpp
@@ -0,0 +1,1653 @@
+/***************************************************************************
+ * cont.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+// NOTE: Borland before 2007 (i.e. < 0x0600) use <algorithm.h>, after 0x0630 it use <algorithm>.
+// I don't find information about 2009, 2010 versions (i.e. 0x0610 and 0x0620).
+// May be condition below can be rewritten as (__CODEGEARC__ >=  0x0600)
+#if !defined(__BORLANDC__) || (__CODEGEARC__ >=  0x0630)
+#include <algorithm>
+#else
+#include <algorithm.h>
+#endif
+#include <list>
+
+#include "mgl2/surf.h"
+#include "mgl2/cont.h"
+#include "mgl2/data.h"
+#include "mgl2/eval.h"
+#include "mgl2/font.h"
+#include "mgl2/base.h"
+//-----------------------------------------------------------------------------
+//
+//	Text printing along a curve
+//
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_string_curve(mglBase *gr,long f,long ,const long *ff,const long *nn,const wchar_t *text, const char *font, mreal size)
+{
+	if(f<0 || nn[f]<0)	return;	// do nothing since there is no curve
+	if(!font)	font="";
+	int pos = strchr(font,'T') ? 1:-1, align;
+	bool cc=mglGetStyle(font,0,&align);		align = align&3;
+	mreal h=gr->TextHeight(font,size)/2;
+	wchar_t L[2]=L"a";
+
+	if(align==1)	// TODO divide curve by 2
+	{}
+
+	std::vector<mglPoint> qa, qb;	// curves above and below original
+	if(ff[f]<0)	for(long i=nn[f];i>=0 && i!=f;i=nn[i])	// find first real point
+		if(ff[i]>=0)	{	f=i;	break;	}
+	if(ff[f]<0)	return;
+	mreal c=cc?gr->AddTexture(font) : gr->GetClrC(ff[f]);
+	mglPoint p=gr->GetPntP(ff[f]), q=p, s;
+	for(long i=nn[f];i>=0 && i!=f;i=nn[i])	// find second real point
+		if(ff[i]>=0)	{	s=gr->GetPntP(ff[i]);	break;	}
+	mglPoint l=!(s-q), t=l;
+	qa.push_back(q+l*h);	qb.push_back(q-l*h);
+	for(long i=nn[f];i>=0 && i!=f;i=nn[i])	// construct curves
+	{
+		p=q;	q=s;	l=t;
+		if(nn[i]>=0 && ff[nn[i]]>=0)	{	s=gr->GetPntP(ff[nn[i]]);	t=!(s-q);	}
+		mreal tet = t.x*l.y-t.y*l.x;
+		mreal tt = 1+fabs(t.x*l.x+t.y*l.y);
+		if(tet>0)
+		{	qa.push_back(q+l*h);	qa.push_back(q+t*h);	qb.push_back(q-(l+t)*(h/tt));	}
+		else if(tet<0)
+		{	qb.push_back(q-l*h);	qb.push_back(q-t*h);	qa.push_back(q+(l+t)*(h/tt));	}
+		else
+		{	qa.push_back(q+l*h);	qb.push_back(q-l*h);	}
+	}
+	if(pos>0)	qa=qb;
+	// adjust text direction
+	bool rev = align==2;
+	const char *ffont=mglchr(font,':');
+	char *fnt = new char[strlen(font)+5];
+	if(ffont) strcpy(fnt,ffont);	else *fnt=0;
+	if(qa[0].x>qa[1].x)
+	{
+		if(align==0){	strcat(fnt,":R");	align=2;	}
+		else if(align==1)	rev = true;
+		else		{	strcat(fnt,":L");	align=0;	}
+	}
+	if(mglchr(font,'T'))	strcat(fnt,":T");
+	if(rev)	reverse(qa.begin(),qa.end());
+	long len = mgl_wcslen(text);
+	mreal *wdt=new mreal[len+1];
+	for(long j=0;j<len;j++)	{	L[0]=text[j];	wdt[j]=1.2*gr->TextWidth(L,font,size);	}
+	wdt[len]=0;
+
+	// place glyphs points
+	mglPoint *pt=new mglPoint[len+1];
+	pt[0] = qa[0];
+	long i=0, k, m = qa.size();
+	mreal t1,t2, tt=0;
+	for(long j=0;j<len;j++)
+	{
+		mreal w = align==1 ? wdt[j] : (wdt[j]+wdt[j+1])/2;	p = pt[j];
+		for(k=i+1;k<m;k++)	if((p-qa[k]).norm()>w)	break;
+		if(k>i+1 && k<m)	tt=-1;
+		i = k<m ? k-1 : m-2;		// check if end of curve
+		q = qa[i];	s = qa[i+1];	// points of line segment
+		mreal a = (q-s)*(q-s), b = (q-p)*(q-s), d = (q-p)*(q-p)-w*w;
+		w = sqrt(b*b-a*d);		// NOTE: b*b>a*d should be here!
+		if(b*b>1e3*a*d)	{	t1 = d/(b+w);	t2 = d/(b-w);	}	// keep precision
+		else			{	t1 = (b-w)/a;	t2 = (b+w)/a;	}
+		if(t1<0 || t1<tt)	t1=t2;	// t1<t2 should be here!
+		tt=t1;	pt[j+1] = q+(s-q)*tt;
+	}
+	if(rev)	pos=-pos;
+	mreal dc = (cc && len>1)?1/MGL_FEPSILON/(len-1):0;
+	for(long j=0;j<len;j++)	// draw text
+	{
+		L[0] = text[align!=2?j:len-1-j];	s = pt[j+1]-pt[j];	l = !s;
+		gr->text_plot(gr->AddPnt(pt[j]+(pos*h)*l,c+dc*i,align!=2?s:-s,-1,-1),L,fnt,size,0.05,c+dc*j);
+	}
+	delete []wdt;	delete []pt;	delete []fnt;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_textw_xyz(HMGL gr, HCDT x, HCDT y, HCDT z,const wchar_t *text, const char *font, const char *opt)
+{
+	long n=y->GetNx();
+	if(mgl_check_dim1(gr,x,y,z,0,"Text"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("TextC",cgid++);
+
+	long *nn = new long[n], *ff = new long[n];
+	for(long i=0;i<n;i++)
+		ff[i] = gr->AddPnt(mglPoint(x->v(i),y->v(i),z->v(i)),-1);
+	for(long i=1;i<n;i++)	nn[i-1] = i;
+	nn[n-1]=-1;
+	mgl_string_curve(gr,0,n,ff,nn,text,font,-1);
+	gr->EndGroup();
+	delete []ff;	delete []nn;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_textw_xy(HMGL gr, HCDT x, HCDT y, const wchar_t *text, const char *font, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV z(y->GetNx());	z.Fill(gr->AdjustZMin());
+	mgl_textw_xyz(gr,x,y,&z,text,font,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_textw_y(HMGL gr, HCDT y, const wchar_t *text, const char *font, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(y->GetNx()), z(y->GetNx());
+	x.Fill(gr->Min.x,gr->Max.x);	z.Fill(gr->AdjustZMin());
+	mgl_textw_xyz(gr,&x,y,&z,text,font,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_text_xyz(HMGL gr, HCDT x, HCDT y, HCDT z,const char *text, const char *font, const char *opt)
+{
+	MGL_TO_WCS(text,mgl_textw_xyz(gr,x,y,z, wcs, font, opt));
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_text_xy(HMGL gr, HCDT x, HCDT y, const char *text, const char *font, const char *opt)
+{
+	mglDataV z(y->GetNx());	z.Fill(gr->AdjustZMin());
+	mgl_text_xyz(gr,x,y,&z,text,font,opt);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_text_y(HMGL gr, HCDT y, const char *text, const char *font, const char *opt)
+{
+	mglDataV x(y->GetNx()), z(y->GetNx());
+	x.Fill(gr->Min.x,gr->Max.x);	z.Fill(gr->AdjustZMin());
+	mgl_text_xyz(gr,&x,y,&z,text,font,opt);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_text_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z,const char *text,const char *font, const char *opt,int l,int n,int lo)
+{	char *s=new char[l+1];	memcpy(s,text,l);	s[l]=0;
+char *f=new char[n+1];	memcpy(f,font,n);	f[n]=0;
+char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+mgl_text_xyz(_GR_, _DA_(x),_DA_(y), _DA_(z), s, f, o);
+delete []o;	delete []s;	delete []f;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_text_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, const char *text, const char *font, const char *opt, int l,int n,int lo)
+{	char *s=new char[l+1];	memcpy(s,text,l);	s[l]=0;
+char *f=new char[n+1];	memcpy(f,font,n);	f[n]=0;
+char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+mgl_text_xy(_GR_, _DA_(x),_DA_(y),s,f,o);
+delete []o;	delete []s;	delete []f;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_text_y_(uintptr_t *gr, uintptr_t *y, const char *text, const char *font, const char *opt, int l,int n,int lo)
+{	char *s=new char[l+1];	memcpy(s,text,l);	s[l]=0;
+char *f=new char[n+1];	memcpy(f,font,n);	f[n]=0;
+char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+mgl_text_y(_GR_, _DA_(y),s,f,o);	delete []o;	delete []s;	delete []f;	}
+//-----------------------------------------------------------------------------
+//
+//	Cont series
+//
+//-----------------------------------------------------------------------------
+#include "cont.hpp"
+//-----------------------------------------------------------------------------
+std::vector<mglSegment> MGL_EXPORT mgl_get_lines(mreal val, HCDT a, HCDT x, HCDT y, HCDT z, long ak)
+{
+	long n=a->GetNx(), m=a->GetNy();
+	std::vector<mglSegment> lines;
+	// first add all possible lines
+	for(long j=0;j<m-1;j++)	for(long i=0;i<n-1;i++)
+	{
+		mreal v1=a->v(i,j,ak),v2=a->v(i+1,j,ak),v3=a->v(i,j+1,ak),v4=a->v(i+1,j+1,ak);
+		mreal dl=mgl_d(val,v1,v3),dr=mgl_d(val,v2,v4),dp=mgl_d(val,v1,v2),dn=mgl_d(val,v3,v4);
+		bool added=false;
+		if(v1>val || v4>val)
+		{
+			mglSegment line;
+			if(line.set(0,dl,dn,1,i,j,ak,x,y,z))	{	lines.push_back(line);	added=true;	}
+			if(line.set(1,dr,dp,0,i,j,ak,x,y,z))	{	lines.push_back(line);	added=true;	}
+		}
+		else
+		{
+			mglSegment line;
+			if(line.set(0,dl,dp,0,i,j,ak,x,y,z))	{	lines.push_back(line);	added=true;	}
+			if(line.set(1,dr,dn,1,i,j,ak,x,y,z))	{	lines.push_back(line);	added=true;	}
+		}
+		if(!added)	// try to add any other variants
+		{
+			mglSegment line;
+			if(line.set(0,dl,1,dr,i,j,ak,x,y,z))		lines.push_back(line);
+			else if(line.set(dp,0,dn,1,i,j,ak,x,y,z))	lines.push_back(line);
+			else if(line.set(0,dl,dn,1,i,j,ak,x,y,z))	lines.push_back(line);
+			else if(line.set(1,dr,dp,0,i,j,ak,x,y,z))	lines.push_back(line);
+			else if(line.set(0,dl,dp,0,i,j,ak,x,y,z))	lines.push_back(line);
+			else if(line.set(1,dr,dn,1,i,j,ak,x,y,z))	lines.push_back(line);
+		}
+	}
+	return lines;
+}
+//-----------------------------------------------------------------------------
+std::vector<mglSegment> MGL_EXPORT mgl_get_curvs(HMGL gr, std::vector<mglSegment> lines)
+{
+	long n = lines.size(), m = n;
+	const long nsl=(n>0 && n*n>100)?sqrt(double(n)):10;
+	mreal dxsl = nsl/((gr->Max.x-gr->Min.x)*MGL_FEPSILON), x0 = gr->Min.x;
+	mreal dysl = nsl/((gr->Max.y-gr->Min.y)*MGL_FEPSILON), y0 = gr->Min.y;
+	std::vector<long> *xsl, *ysl;
+	xsl = new std::vector<long>[nsl+1];
+	ysl = new std::vector<long>[nsl+1];
+	for(long i=0;i<n;i++)	// group lines by position of its x-coor
+	{
+		long i1 = (lines[i].p1.x-x0)*dxsl, i2 = (lines[i].p2.x-x0)*dxsl;
+		if(i1<0)	i1=0;
+		if(i1>nsl)	i1=nsl;
+		if(i2<0)	i2=0;
+		if(i2>nsl)	i2=nsl;
+		if(i1==i2 && i1*(i1-nsl)<=0)	xsl[i1].push_back(i);
+		else
+		{
+			if(i1*(i1-nsl)<=0)	xsl[i1].push_back(i);
+			if(i2*(i2-nsl)<=0)	xsl[i2].push_back(i);
+		}
+		i1 = (lines[i].p1.y-y0)*dysl;
+		i2 = (lines[i].p2.y-y0)*dysl;
+		if(i1<0)	i1=0;
+		if(i1>nsl)	i1=nsl;
+		if(i2<0)	i2=0;
+		if(i2>nsl)	i2=nsl;
+		if(i1==i2 && i1*(i1-nsl)<=0)	ysl[i1].push_back(i);
+		else
+		{
+			if(i1*(i1-nsl)<=0)	ysl[i1].push_back(i);
+			if(i2*(i2-nsl)<=0)	ysl[i2].push_back(i);
+		}
+	}
+	size_t xm=0,ym=0;
+	for(long i=0;i<=nsl;i++)
+	{
+		if(xm<xsl[i].size())	xm=xsl[i].size();
+		if(ym<ysl[i].size())	ym=ysl[i].size();
+	}
+	std::vector<mglSegment> curvs;
+	char *used = new char[n];	memset(used,0,n);
+	// create curves from lines
+	while(m>0)	// NOTE! This algorithm can be *very* slow!!!
+	{
+		mglSegment curv;
+		bool added = false;
+		for(long i=0;i<n;i++)	if(!used[i])	// find any first line segment
+		{
+			curv.before(lines[i].p1);
+			curv.after(lines[i].p2);
+			used[i]=1;	m--;
+			added=true;	break;
+		}
+		while(added && m>0)
+		{
+			added = false;
+			long i1, i2;
+			if(xm<=ym)
+			{	i1 = (curv.p1.x-x0)*dxsl;	i2 = (curv.p2.x-x0)*dxsl;	}
+			else
+			{	i1 = (curv.p1.y-y0)*dysl;	i2 = (curv.p2.y-y0)*dysl;	}
+			if(i1<0)	i1=0;
+			if(i1>nsl)	i1=nsl;
+			if(i2<0)	i2=0;
+			if(i2>nsl)	i2=nsl;
+			const std::vector<long> &isl1=(xm<=ym)?xsl[i1]:ysl[i1];
+			for(size_t i=0;i<isl1.size();i++)	// first find continuation of first point
+			{
+				long ii = isl1[i];
+				const mglSegment &l=lines[ii];
+				if(used[ii])	continue;
+				if(l.p1==curv.p1)		{	curv.before(l.p2);	used[ii]=1;	m--;	added=true;	break;	}
+				else if(l.p2==curv.p1)	{	curv.before(l.p1);	used[ii]=1;	m--;	added=true;	break;	}
+			}
+			const std::vector<long> &isl2=(xm<=ym)?xsl[i2]:ysl[i2];
+			if(m>0)	for(size_t i=0;i<isl2.size();i++)	// now the same for second point
+			{
+				long ii = isl2[i];
+				const mglSegment &l=lines[ii];
+				if(used[ii])	continue;
+				if(l.p1==curv.p2)		{	curv.after(l.p2);	used[ii]=1;	m--;	added=true;	break;	}
+				else if(l.p2==curv.p2)	{	curv.after(l.p1);	used[ii]=1;	m--;	added=true;	break;	}
+			}
+		}
+		curvs.push_back(curv);
+	}
+	delete []used;	delete []xsl;	delete []ysl;
+	return curvs;
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_draw_curvs(HMGL gr, mreal val, mreal c, int text, const std::vector<mglSegment> &curvs)
+{
+	long pc=0;
+	for(size_t i=0;i<curvs.size();i++)	pc += curvs[i].pp.size();
+	gr->Reserve(pc);
+	// fill arguments for other functions
+	long *ff = new long[pc], *nn = new long[pc], m=0;
+	for(size_t i=0;i<curvs.size();i++)
+	{
+		const std::list<mglPoint> &pp=curvs[i].pp;
+		for(std::list<mglPoint>::const_iterator it=pp.begin(); it != pp.end(); ++it)
+		{
+			ff[m] = gr->AddPnt(*it, c);
+			nn[m] = m+1;	m++;
+		}
+		nn[m-1]=-1;
+	}
+	if(text && pc>1)
+	{
+		wchar_t wcs[64];
+		mglprintf(wcs,64,L"%4.3g",val);
+		mreal del = 2*gr->TextWidth(wcs,"",-0.5);
+		// find width and height of drawing area
+		mreal ar=gr->GetRatio(), w=gr->FontFactor(), h;
+		if(del<w/5)	del = w/5;
+		if(ar<1) h=w/ar;	else {	h=w;	w*=ar;	}
+		long m=long(2*w/del)+1, n=long(2*h/del)+1;
+		long *oo=new long[n*m];
+		mreal *rr=new mreal[n*m];
+		for(long i=0;i<n*m;i++)	{	oo[i]=-1;	rr[i]=del*del/4;	}
+		for(long k=0;k<pc;k++)	// print label several times if possible
+		{
+			if(nn[k]<0)	continue;
+			mglPoint t = gr->GetPntP(ff[k]);
+			long i = long(t.x/del);	t.x -= i*del;
+			long j = long(t.y/del);	t.y -= j*del;
+			if(i<0 || i>=m || j<0 || j>=n)	continue;	// never should be here!
+			mreal xx = t.x*t.x+t.y*t.y;	i += m*j;
+			if(rr[i]>xx)	{	rr[i]=xx;	oo[i]=k;	}
+		}
+		for(long i=0;i<n*m;i++)	if(oo[i]>=0)
+			mgl_string_curve(gr,oo[i],pc,ff,nn,wcs,text==1?"t:C":"T:C",-0.5);
+		delete []oo;	delete []rr;
+	}
+	for(long i=0;i<pc;i++)	if(nn[i]>=0)	gr->line_plot(ff[i], ff[nn[i]]);
+	delete []nn;	delete []ff;
+}
+//-----------------------------------------------------------------------------
+// NOTE! All data MUST have the same size! Only first slice is used!
+void MGL_EXPORT mgl_cont_gen(HMGL gr, mreal val, HCDT a, HCDT x, HCDT y, HCDT z, mreal c, int text,long ak)
+{
+	long n=a->GetNx(), m=a->GetNy();
+	if(n<2 || m<2 || x->GetNx()*x->GetNy()!=n*m || y->GetNx()*y->GetNy()!=n*m || z->GetNx()*z->GetNy()!=n*m)
+	{	gr->SetWarn(mglWarnDim,"ContGen");	return;	}
+
+	mgl_draw_curvs(gr,val,c,text,mgl_get_curvs(gr,mgl_get_lines(val,a,x,y,z,ak)));
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont_gen(HMGL gr, double val, HCDT a, HCDT x, HCDT y, HCDT z, const char *sch)
+{
+	int text=0;
+	if(mglchr(sch,'t'))	text=1;
+	if(mglchr(sch,'T'))	text=2;
+	gr->SetPenPal(sch);
+	mgl_cont_gen(gr,val,a,x,y,z,gr->CDef,text,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont_xy_val(HMGL gr, HCDT v, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{
+	long n=z->GetNx(),m=z->GetNy();
+	if(mgl_check_dim2(gr,x,y,z,0,"Cont"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Cont",cgid++);
+
+	int text=0;
+	if(mglchr(sch,'t'))	text=1;
+	if(mglchr(sch,'T'))	text=2;
+	bool fixed=(mglchr(sch,'_')) || (gr->Min.z==gr->Max.z);
+	long s=gr->AddTexture(sch);
+	gr->SetPenPal(sch);
+
+	mglData xx, yy;
+	if(x->GetNx()*x->GetNy()!=m*n || y->GetNx()*y->GetNy()!=m*n)	// make
+	{
+		xx.Create(n, m);		yy.Create(n, m);
+		for(long i=0;i<n;i++)	xx.a[i]=x->v(i);
+		for(long j=1;j<m;j++)	memcpy(xx.a+n*j,xx.a,n*sizeof(mreal));
+		for(long j=0;j<m;j++)
+		{	mreal t=y->v(j);	for(long i=0;i<n;i++)	yy.a[i+n*j]=t;	}
+		x = &xx;	y = &yy;
+	}
+	// x, y -- have the same size z
+#pragma omp parallel for collapse(2)
+	for(long i=0;i<v->GetNx();i++)	for(long j=0;j<z->GetNz();j++)
+	{
+		if(gr->NeedStop())	continue;
+		mreal v0 = v->v(i), z0 = fixed ? gr->Min.z : v0;
+		if(z->GetNz()>1)
+			z0 = gr->Min.z+(gr->Max.z-gr->Min.z)*mreal(j)/(z->GetNz()-1);
+		mglDataV zz(n, m);	zz.Fill(z0,z0);
+		mgl_cont_gen(gr,v0,z,x,y,&zz,gr->GetC(s,v0),text,j);
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont_val(HMGL gr, HCDT v, HCDT z, const char *sch, const char *opt)
+{
+	long n = z->GetNx(), m = z->GetNy();
+	if(m<2 || n<2)	{	gr->SetWarn(mglWarnLow,"Cont");	return;	}
+	gr->SaveState(opt);
+	mglDataV x(n, m), y(n, m);
+	x.Fill(gr->Min.x,gr->Max.x,'x');
+	y.Fill(gr->Min.y,gr->Max.y,'y');
+	mgl_cont_xy_val(gr,v,&x,&y,z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont_xy(HMGL gr, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long Num = mgl_isnan(r)?7:long(r+0.5);
+	if(Num<1)	{	gr->SetWarn(mglWarnCnt,"Cont");	return;	}
+	mglData v(Num);
+	for(long i=0;i<Num;i++)	v.a[i] = gr->Min.c + (gr->Max.c-gr->Min.c)*mreal(i+1)/(Num+1);
+	mgl_cont_xy_val(gr,&v,x,y,z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont(HMGL gr, HCDT z, const char *sch, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long Num = mgl_isnan(r)?7:long(r+0.5);
+	if(Num<1)	{	gr->SetWarn(mglWarnCnt,"Cont");	return;	}
+	mglData v(Num);
+	for(long i=0;i<Num;i++)	v.a[i] = gr->Min.c + (gr->Max.c-gr->Min.c)*mreal(i+1)/(Num+1);
+	mgl_cont_val(gr,&v,z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont_xy_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *x, uintptr_t *y, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+mgl_cont_xy_val(_GR_, _DA_(v), _DA_(x), _DA_(y), _DA_(a), s, o);
+delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+mgl_cont_val(_GR_, _DA_(v), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+mgl_cont_xy(_GR_, _DA_(x), _DA_(y), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont_(uintptr_t *gr, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+mgl_cont(_GR_, _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	ContF series
+//
+//-----------------------------------------------------------------------------
+long MGL_NO_EXPORT mgl_add_pnt(HMGL gr, mreal d, HCDT x, HCDT y, HCDT z, long i1, long j1, long i2, long j2, mreal c, bool edge)
+{
+	long res=-1;
+	if(edge || (d>0 && d<1))
+	{
+		mglPoint p(x->v(i1,j1)*(1-d)+x->v(i2,j2)*d,
+					y->v(i1,j1)*(1-d)+y->v(i2,j2)*d,
+					z->v(i1,j1)*(1-d)+z->v(i2,j2)*d);
+		mglPoint u(x->dvx(i1,j1)*(1-d)+x->dvx(i2,j2)*d,
+					y->dvx(i1,j1)*(1-d)+y->dvx(i2,j2)*d,
+					z->dvx(i1,j1)*(1-d)+z->dvx(i2,j2)*d);
+		mglPoint v(x->dvy(i1,j1)*(1-d)+x->dvy(i2,j2)*d,
+					y->dvy(i1,j1)*(1-d)+y->dvy(i2,j2)*d,
+					z->dvy(i1,j1)*(1-d)+z->dvy(i2,j2)*d);
+		res = gr->AddPnt(p,c,u^v);
+	}
+	return res;
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_add_range(HMGL gr, HCDT a, HCDT x, HCDT y, HCDT z, long i1, long j1, long di, long dj, mreal c, long &u1, long &u2, long ak, mreal v1, mreal v2)
+{
+	long i2=i1+di, j2=j1+dj;
+	mreal f1 = a->v(i1,j1,ak),	f2 = a->v(i2,j2,ak), d1, d2;
+	d1 = mgl_d(v1,f1,f2);
+	u1 = mgl_add_pnt(gr,d1,x,y,z,i1,j1,i2,j2,c,false);
+	d2 = mgl_d(v2,f1,f2);
+	u2 = mgl_add_pnt(gr,d2,x,y,z,i1,j1,i2,j2,c,false);
+	if(d1>d2)	{	j2=u1;	u1=u2;	u2=j2;	}
+	if(u1<0)	{	u1=u2;	u2=-1;	}
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_add_edges(HMGL gr, HCDT a, HCDT x, HCDT y, HCDT z, long i1, long j1, long di, long dj, mreal c, long &u1, long &u2, long ak, mreal v1, mreal v2)
+{
+	long i2=i1+di, j2=j1+dj;
+	u1 = u2 = -1;
+	mreal f1 = a->v(i1,j1,ak),	f2 = a->v(i2,j2,ak);
+	if(f1<=v2 && f1>=v1)	u1 = mgl_add_pnt(gr,0,x,y,z,i1,j1,i2,j2,c,true);
+	if(f2<=v2 && f2>=v1)	u2 = mgl_add_pnt(gr,1,x,y,z,i1,j1,i2,j2,c,true);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf_gen(HMGL gr, mreal v1, mreal v2, HCDT a, HCDT x, HCDT y, HCDT z, mreal c, long ak)
+{
+	long n=a->GetNx(), m=a->GetNy();
+	if(n<2 || m<2 || x->GetNx()*x->GetNy()!=n*m || y->GetNx()*y->GetNy()!=n*m || z->GetNx()*z->GetNy()!=n*m)
+	{	gr->SetWarn(mglWarnDim,"ContFGen");	return;	}
+
+	gr->Reserve(8*n*m);
+	long *kk = new long[4*n], l1,l2, r1,r2, t1,t2, u1,u2, b1,b2, d1,d2, p[8],num;
+	memset(kk,-1,2*n*sizeof(long));
+	for(long i=0;i<n-1;i++)	// add intersection points for first line
+	{
+		mgl_add_range(gr,a,x,y,z, i,0,1,0, c,u1,u2, ak,v1,v2);
+		kk[4*i]=u1;		kk[4*i+1]=u2;
+		mgl_add_edges(gr,a,x,y,z, i,0,1,0, c,d1,d2, ak,v1,v2);
+		kk[4*i+2]=d1;		kk[4*i+3]=d2;
+	}
+	for(long j=1;j<m;j++)	// add intersection points
+	{
+		mgl_add_range(gr,a,x,y,z, 0,j-1,0,1, c,r1,r2, ak,v1,v2);
+		for(long i=0;i<n-1;i++)
+		{
+			l1 = r1;		l2 = r2;	num=0;
+			t1 = kk[4*i];	t2 = kk[4*i+1];
+			b1 = kk[4*i+2];	b2 = kk[4*i+3];
+			// right edge
+			mgl_add_range(gr,a,x,y,z, i+1,j-1,0,1, c,r1,r2, ak,v1,v2);
+			// top edge
+			mgl_add_range(gr,a,x,y,z, i,j,1,0, c,u1,u2, ak,v1,v2);
+			kk[4*i]=u1;		kk[4*i+1]=u2;
+			mgl_add_edges(gr,a,x,y,z, i,j,1,0, c,d1,d2, ak,v1,v2);
+			kk[4*i+2]=d1;	kk[4*i+3]=d2;
+			// collect points
+			if(b1>=0)	p[num++] = b1;
+			if(t1>=0)	p[num++] = t1;
+			if(t2>=0)	p[num++] = t2;
+			if(b2>=0)	p[num++] = b2;
+			if(r1>=0)	p[num++] = r1;
+			if(r2>=0)	p[num++] = r2;
+			if(d2>=0)	p[num++] = d2;
+			if(u2>=0)	p[num++] = u2;
+			if(u1>=0)	p[num++] = u1;
+			if(d1>=0)	p[num++] = d1;
+			if(l2>=0)	p[num++] = l2;
+			if(l1>=0)	p[num++] = l1;
+
+			//	d1	u1	u2	d2
+			//	l2			r2
+			//	l1			r1
+			//	b1	t1	t2	b2
+
+			// draw it
+			bool b1d2 = a->v(i+1,j,ak)>v2 && a->v(i,j-1,ak)>v2;
+			bool b2d1 = a->v(i,j,ak)>v2 && a->v(i+1,j-1,ak)>v2;
+//			mreal vv = a->linearD(i+0.5,j-0.5,ak,0,0,0);
+//			vv = (vv-v1)*(vv-v2);
+			if(num<3)	continue;
+			if(num==4)	gr->quad_plot(p[0],p[1],p[3],p[2]);
+			else if(num==3)	gr->trig_plot(p[0],p[1],p[2]);
+			else if(num==5)
+			{
+				gr->quad_plot(p[0],p[1],p[3],p[2]);
+				gr->trig_plot(p[0],p[3],p[4]);
+			}
+			else if(num==6)
+			{
+				if(b1>=0 && b2>=0)
+				{
+					gr->quad_plot(b1,b2,l1,r1);
+					gr->quad_plot(l1,r1,u1,u2);
+				}
+				else if(d1>=0 && d2>=0)
+				{
+					gr->quad_plot(d1,d2,l1,r1);
+					gr->quad_plot(l1,r1,t1,t2);
+				}
+				else if(b1>=0 && d2>=0)
+				{
+					if(b2d1)
+					{	gr->trig_plot(b1,t1,l1);	gr->trig_plot(r1,u1,d2);	}
+					else
+					{	gr->quad_plot(b1,t1,l1,r1);	gr->quad_plot(l1,r1,u1,d2);	}
+				}
+				else if(d1>=0 && b2>=0)
+				{
+					if(b1d2)
+					{	gr->trig_plot(t1,b2,r1);	gr->trig_plot(l1,d1,u1);	}
+					else
+					{	gr->quad_plot(t1,b2,l1,r1);	gr->quad_plot(l1,r1,d1,u1);	}
+				}
+				else if(b1>=0 && d1>=0)
+				{
+					gr->quad_plot(b1,d1,t1,u1);
+					gr->quad_plot(t1,u1,r1,r2);
+				}
+				else if(d2>=0 && b2>=0)
+				{
+					gr->quad_plot(d2,b2,u1,t1);
+					gr->quad_plot(t1,u1,l1,l2);
+				}
+			}
+			else if(num==7)
+			{
+				if(b1>=0)
+				{
+					gr->trig_plot(b1,l1,t1);	gr->quad_plot(r1,r2,u1,u2);
+					if(!b2d1)	gr->quad_plot(l1,t1,u1,r1);
+				}
+				else if(b2>=0)
+				{
+					gr->trig_plot(b2,r1,t1);	gr->quad_plot(l1,l2,u2,u1);
+					if(!b1d2)	gr->quad_plot(r1,t1,u2,l1);
+				}
+				else if(d2>=0)
+				{
+					gr->trig_plot(d2,r1,u1);	gr->quad_plot(l1,l2,t1,t2);
+					if(!b2d1)	gr->quad_plot(r1,u1,t2,l2);
+				}
+				else if(d1>=0)
+				{
+					gr->trig_plot(d1,l1,u1);	gr->quad_plot(r1,r2,t2,t1);
+					if(!b1d2)	gr->quad_plot(l1,u1,t1,r2);
+				}
+			}
+			else if(num==8)
+			{
+				if(b2d1)
+				{	if(l2<0)	{	l2=l1;	l1=b1;	}
+					if(r2<0)	r2=d2;
+					if(t2<0)	{	t2=t1;	t1=b1;	}
+					if(u2<0)	u2=d2;
+					gr->quad_plot(r1,r2,u1,u2);	gr->quad_plot(l1,l2,t1,t2);	}
+				else
+				{	if(l2<0)	l2=d1;
+					if(r2<0)	{	r2=r1;	r1=b2;	}
+					if(t2<0)	t2=b2;
+					if(u2<0)	{	u2=u1;	u1=d1;	}
+					gr->quad_plot(r1,r2,t2,t1);	gr->quad_plot(l1,l2,u2,u1);	}
+			}
+		}
+	}
+	delete []kk;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf_gen(HMGL gr, double v1, double v2, HCDT a, HCDT x, HCDT y, HCDT z, const char *c)
+{
+	gr->SetPenPal(c);
+	mgl_contf_gen(gr,v1,v2,a,x,y,z,gr->CDef,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf_xy_val(HMGL gr, HCDT v, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{
+	long n=z->GetNx(),m=z->GetNy();
+	if(mgl_check_dim2(gr,x,y,z,0,"ContF"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("ContF",cgid++);
+	long s=gr->AddTexture(sch);
+
+	bool fixed=(mglchr(sch,'_')) || (gr->Min.z==gr->Max.z);
+	mglData xx, yy;
+	if(x->GetNx()*x->GetNy()!=m*n || y->GetNx()*y->GetNy()!=m*n)	// make
+	{
+		xx.Create(n, m);		yy.Create(n, m);
+		for(long i=0;i<n;i++)	xx.a[i]=x->v(i);
+		for(long j=1;j<m;j++)	memcpy(xx.a+n*j,xx.a,n*sizeof(mreal));
+		for(long j=0;j<m;j++)
+		{	mreal t=y->v(j);	for(long i=0;i<n;i++)	yy.a[i+n*j]=t;	}
+		x = &xx;	y = &yy;
+	}
+	// x, y -- have the same size z
+#pragma omp parallel for collapse(2)
+	for(long i=0;i<v->GetNx()-1;i++)	for(long j=0;j<z->GetNz();j++)
+	{
+		if(gr->NeedStop())	continue;
+		mreal v0 = v->v(i), z0 = fixed ? gr->Min.z : v0;
+		if(z->GetNz()>1)
+			z0 = gr->Min.z+(gr->Max.z-gr->Min.z)*mreal(j)/(z->GetNz()-1);
+		mglDataV zz(n, m);	zz.Fill(z0,z0);
+		mgl_contf_gen(gr,v0,v->v(i+1),z,x,y,&zz,gr->GetC(s,v0),j);
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf_val(HMGL gr, HCDT v, HCDT z, const char *sch, const char *opt)
+{
+	long n = z->GetNx(), m = z->GetNy();
+	if(n<2 || m<2)	{	gr->SetWarn(mglWarnLow,"Cont");	return;	}
+	gr->SaveState(opt);
+	mglDataV x(n, m), y(n, m);
+	x.Fill(gr->Min.x,gr->Max.x,'x');
+	y.Fill(gr->Min.y,gr->Max.y,'y');
+	mgl_contf_xy_val(gr,v,&x,&y,z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf_xy(HMGL gr, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long Num = mgl_isnan(r)?7:long(r+0.5);
+	if(Num<1)	{	gr->SetWarn(mglWarnCnt,"Cont");	return;	}
+	mglDataV v(Num+2);	v.Fill(gr->Min.c, gr->Max.c);
+	mgl_contf_xy_val(gr,&v,x,y,z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf(HMGL gr, HCDT z, const char *sch, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long Num = mgl_isnan(r)?7:long(r+0.5);
+	if(Num<1)	{	gr->SetWarn(mglWarnCnt,"Cont");	return;	}
+	mglDataV v(Num+2);	v.Fill(gr->Min.c, gr->Max.c);
+	mgl_contf_val(gr,&v,z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf_xy_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *x, uintptr_t *y, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_contf_xy_val(_GR_, _DA_(v), _DA_(x), _DA_(y), _DA_(a), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_contf_val(_GR_, _DA_(v), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_contf_xy(_GR_, _DA_(x), _DA_(y), _DA_(a), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf_(uintptr_t *gr, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_contf(_GR_, _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	ContP series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contp_val(HMGL gr, HCDT v, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt)
+{
+	long n=z->GetNx(),m=z->GetNy();
+	if(mgl_check_dim2(gr,x,y,z,a,"Cont"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Cont",cgid++);
+
+	int text=0;
+	if(mglchr(sch,'t'))	text=1;
+	if(mglchr(sch,'T'))	text=2;
+	bool fill = mglchr(sch,'f');
+	long s=gr->AddTexture(sch);
+	gr->SetPenPal(sch);
+
+	mglData xx, yy;
+	if(x->GetNx()*x->GetNy()!=m*n || y->GetNx()*y->GetNy()!=m*n)	// make
+	{
+		xx.Create(n, m);		yy.Create(n, m);
+		for(long i=0;i<n;i++)	xx.a[i]=x->v(i);
+		for(long j=1;j<m;j++)	memcpy(xx.a+n*j,xx.a,n*sizeof(mreal));
+		for(long j=0;j<m;j++)
+		{	mreal t=y->v(j);	for(long i=0;i<n;i++)	yy.a[i+n*j]=t;	}
+		x = &xx;	y = &yy;
+	}
+	// x, y -- have the same size z
+#pragma omp parallel for collapse(2)
+	for(long i=0;i<v->GetNx();i++)	for(long j=0;j<a->GetNz();j++)
+	{
+		if(gr->NeedStop())	continue;
+		if(fill)
+			mgl_contf_gen(gr,v->v(i),v->v(i+1),a,x,y,z,gr->GetC(s,v->v(i)),j);
+		else
+			mgl_cont_gen(gr,v->v(i),a,x,y,z,gr->GetC(s,v->v(i)),text,j);
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contp(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long Num = mgl_isnan(r)?7:long(r+0.5);
+	if(Num<1)	{	gr->SetWarn(mglWarnCnt,"Cont");	return;	}
+	mglData v(Num);
+	for(long i=0;i<Num;i++)	v.a[i] = gr->Min.c + (gr->Max.c-gr->Min.c)*mreal(i+1)/(Num+1);
+	mgl_contp_val(gr,&v,x,y,z,a,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contp_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_contp_val(_GR_, _DA_(v), _DA_(x), _DA_(y), _DA_(z), _DA_(a), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contp_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_contp(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(a), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	ContD series
+//
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgl_get_ncol(const char *sch, char *res)
+{
+	long j=0;
+	if(sch)	for(long i=0;sch[i]&&sch[i]!=':';i++)	if(strchr(MGL_COLORS,sch[i]))
+	{	if(res)	res[j]=sch[i];	j++;	}
+	return j?j:strlen(MGL_DEF_PAL);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contd_xy_val(HMGL gr, HCDT v, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{
+	long j=0,n=z->GetNx(),m=z->GetNy();
+	if(mgl_check_dim2(gr,x,y,z,0,"ContD"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("ContD",cgid++);
+
+	bool fixed=(mglchr(sch,'_')) || (gr->Min.z==gr->Max.z);
+	if(sch)	for(long i=0;sch[i];i++)	if(strchr(MGL_COLORS,sch[i]))	j++;
+	if(j==0)	sch = MGL_DEF_PAL;
+	long s = gr->AddTexture(sch,1);
+	int nc = gr->GetNumPal(s*256);
+	mglData xx, yy;
+	if(x->GetNx()*x->GetNy()!=m*n || y->GetNx()*y->GetNy()!=m*n)	// make
+	{
+		xx.Create(n, m);		yy.Create(n, m);
+		for(long i=0;i<n;i++)	xx.a[i]=x->v(i);
+		for(long j=1;j<m;j++)	memcpy(xx.a+n*j,xx.a,n*sizeof(mreal));
+		for(long j=0;j<m;j++)
+		{	mreal t=y->v(j);	for(long i=0;i<n;i++)	yy.a[i+n*j]=t;	}
+		x = &xx;	y = &yy;
+	}
+	// x, y -- have the same size z
+	mreal dc = nc>1 ? 1/(MGL_FEPSILON*(nc-1)) : 0;
+#pragma omp parallel for collapse(2)
+	for(long i=0;i<v->GetNx()-1;i++)	for(long j=0;j<z->GetNz();j++)
+	{
+		if(gr->NeedStop())	continue;
+		mreal v0 = v->v(i), z0 = fixed ? gr->Min.z : v0;
+		if(z->GetNz()>1)
+			z0 = gr->Min.z+(gr->Max.z-gr->Min.z)*mreal(j)/(z->GetNz()-1);
+		mglDataV zz(n, m);	zz.Fill(z0,z0);
+		mgl_contf_gen(gr,v0,v->v(i+1),z,x,y,&zz,s+(i%nc)*dc,j);
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contd_val(HMGL gr, HCDT v, HCDT z, const char *sch, const char *opt)
+{
+	long n = z->GetNx(), m = z->GetNy();
+	if(n<2 || m<2)	{	gr->SetWarn(mglWarnLow,"ContD");	return;	}
+	gr->SaveState(opt);
+	mglDataV x(n, m), y(n, m);
+	x.Fill(gr->Min.x,gr->Max.x,'x');
+	y.Fill(gr->Min.y,gr->Max.y,'y');
+	mgl_contd_xy_val(gr,v,&x,&y,z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contd_xy(HMGL gr, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV v(mgl_get_ncol(sch,0)+1);
+	v.Fill(gr->Min.c, gr->Max.c);
+	mgl_contd_xy_val(gr,&v,x,y,z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contd(HMGL gr, HCDT z, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV v(mgl_get_ncol(sch,0)+1);
+	v.Fill(gr->Min.c, gr->Max.c);
+	mgl_contd_val(gr,&v,z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contd_xy_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *x, uintptr_t *y, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_contd_xy_val(_GR_, _DA_(v), _DA_(x), _DA_(y), _DA_(a), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contd_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_contd_val(_GR_, _DA_(v), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contd_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_contd_xy(_GR_, _DA_(x), _DA_(y), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contd_(uintptr_t *gr, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_contd(_GR_, _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	ContV series
+//
+//-----------------------------------------------------------------------------
+// NOTE! All data MUST have the same size! Only first slice is used!
+void MGL_EXPORT mgl_contv_gen(HMGL gr, mreal val, mreal dval, HCDT a, HCDT x, HCDT y, HCDT z, mreal c, long ak)
+{
+	long n=a->GetNx(), m=a->GetNy();
+	if(n<2 || m<2 || x->GetNx()*x->GetNy()!=n*m || y->GetNx()*y->GetNy()!=n*m || z->GetNx()*z->GetNy()!=n*m)
+	{	gr->SetWarn(mglWarnDim,"ContGen");	return;	}
+
+	const std::vector<mglSegment> curvs = mgl_get_curvs(gr,mgl_get_lines(val,a,x,y,z,ak));
+	for(size_t i=0;i<curvs.size();i++)
+	{
+		const std::list<mglPoint> &pp=curvs[i].pp;
+		long f2=-1,g2=-1;
+		for(std::list<mglPoint>::const_iterator it=pp.begin(); it != pp.end(); ++it)
+		{
+			mglPoint p=*it,q(p.y,-p.x);
+			long f1 = f2;	f2 = gr->AddPnt(p,c,q);	p.z+=dval;
+			long g1 = g2;	g2 = gr->AddPnt(p,c,q);
+			gr->quad_plot(f1,g1,f2,g2);
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contv_xy_val(HMGL gr, HCDT v, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{
+	long n=z->GetNx(),m=z->GetNy();
+	if(mgl_check_dim2(gr,x,y,z,0,"ContV"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("ContV",cgid++);
+	bool fixed=(mglchr(sch,'_')) || (gr->Min.z==gr->Max.z);
+	long s=gr->AddTexture(sch);
+	gr->SetPenPal(sch);
+
+	mglData xx, yy;
+	if(x->GetNx()*x->GetNy()!=m*n || y->GetNx()*y->GetNy()!=m*n)	// make
+	{
+		xx.Create(n, m);		yy.Create(n, m);
+		for(long i=0;i<n;i++)	xx.a[i]=x->v(i);
+		for(long j=1;j<m;j++)	memcpy(xx.a+n*j,xx.a,n*sizeof(mreal));
+		for(long j=0;j<m;j++)
+		{	mreal t=y->v(j);	for(long i=0;i<n;i++)	yy.a[i+n*j]=t;	}
+		x = &xx;	y = &yy;
+	}
+	// x, y -- have the same size z
+#pragma omp parallel for collapse(2)
+	for(long i=0;i<v->GetNx();i++)	for(long j=0;j<z->GetNz();j++)
+	{
+		if(gr->NeedStop())	continue;
+		mreal v0 = v->v(i), z0 = fixed ? gr->Min.z : v0;
+		if(z->GetNz()>1)	z0 = gr->Min.z+(gr->Max.z-gr->Min.z)*mreal(j)/(z->GetNz()-1);
+		mglDataV zz(n, m);	zz.Fill(z0,z0);
+		mreal dv = (gr->Max.c-gr->Min.c)/8;
+		if(i>0)	dv = v->v(i-1)-v->v(i);
+		else if(i<v->GetNx()-1)	dv = v->v(i)-v->v(i+1);
+		if(fixed)	dv=-dv;
+		mgl_contv_gen(gr,v0,dv,z,x,y,&zz,gr->GetC(s,v0),j);
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contv_val(HMGL gr, HCDT v, HCDT z, const char *sch, const char *opt)
+{
+	long n = z->GetNx(), m = z->GetNy();
+	if(n<2 || m<2)	{	gr->SetWarn(mglWarnLow,"Cont");	return;	}
+	gr->SaveState(opt);
+	mglDataV x(n, m), y(n, m);
+	x.Fill(gr->Min.x,gr->Max.x,'x');
+	y.Fill(gr->Min.y,gr->Max.y,'y');
+	mgl_contv_xy_val(gr,v,&x,&y,z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contv_xy(HMGL gr, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long Num = mgl_isnan(r)?7:long(r+0.5);
+	if(Num<1)	{	gr->SetWarn(mglWarnCnt,"Cont");	return;	}
+	mglData v(Num);
+	for(long i=0;i<Num;i++)	v.a[i] = gr->Min.c + (gr->Max.c-gr->Min.c)*mreal(i+1)/(Num+1);
+	mgl_contv_xy_val(gr,&v,x,y,z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contv(HMGL gr, HCDT z, const char *sch, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long Num = mgl_isnan(r)?7:long(r+0.5);
+	if(Num<1)	{	gr->SetWarn(mglWarnCnt,"Cont");	return;	}
+	mglData v(Num);
+	for(long i=0;i<Num;i++)	v.a[i] = gr->Min.c + (gr->Max.c-gr->Min.c)*mreal(i+1)/(Num+1);
+	mgl_contv_val(gr,&v,z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contv_xy_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *x, uintptr_t *y, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_contv_xy_val(_GR_, _DA_(v), _DA_(x), _DA_(y), _DA_(a), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contv_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_contv_val(_GR_, _DA_(v), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contv_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_contv_xy(_GR_, _DA_(x), _DA_(y), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contv_(uintptr_t *gr, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_contv(_GR_, _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Cont3 series
+//
+//-----------------------------------------------------------------------------
+struct _mgl_slice	{	mglData x,y,z,a;	};
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_get_slice(_mgl_slice &s, HCDT x, HCDT y, HCDT z, HCDT a, char dir, mreal d, bool both)
+{
+	long n=a->GetNx(),m=a->GetNy(),l=a->GetNz(), nx=1,ny=1,p;
+
+	if(dir=='x')	{	nx = m;	ny = l;	if(d<0)	d = n/2.;	}
+	if(dir=='y')	{	nx = n;	ny = l;	if(d<0)	d = m/2.;	}
+	if(dir=='z')	{	nx = n;	ny = m;	if(d<0)	d = l/2.;	}
+	s.x.Create(nx,ny);	s.y.Create(nx,ny);
+	s.z.Create(nx,ny);	s.a.Create(nx,ny);
+	p = long(d);	d -= p;
+	if(dir=='x' && p>=n-1)	{	d+=p-n+2;	p=n-2;	}
+	if(dir=='y' && p>=m-1)	{	d+=p-m+2.;	p=m-2;	}
+	if(dir=='z' && p>=l-1)	{	d+=p-l+2;	p=l-2;	}
+	mreal v;
+
+	if(both)
+	{
+		if(dir=='x')
+#pragma omp parallel for collapse(2)
+			for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+			{
+				long i0 = i+nx*j;
+				s.x.a[i0] = x->v(p,i,j)*(1-d) + x->v(p+1,i,j)*d;
+				s.y.a[i0] = y->v(p,i,j)*(1-d) + y->v(p+1,i,j)*d;
+				s.z.a[i0] = z->v(p,i,j)*(1-d) + z->v(p+1,i,j)*d;
+				s.a.a[i0] = a->v(p,i,j)*(1-d) + a->v(p+1,i,j)*d;
+			}
+		if(dir=='y')
+#pragma omp parallel for collapse(2)
+			for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+			{
+				long i0 = i+nx*j;
+				s.x.a[i0] = x->v(i,p,j)*(1-d) + x->v(i,p+1,j)*d;
+				s.y.a[i0] = y->v(i,p,j)*(1-d) + y->v(i,p+1,j)*d;
+				s.z.a[i0] = z->v(i,p,j)*(1-d) + z->v(i,p+1,j)*d;
+				s.a.a[i0] = a->v(i,p,j)*(1-d) + a->v(i,p+1,j)*d;
+			}
+		if(dir=='z')
+#pragma omp parallel for collapse(2)
+			for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+			{
+				long i0 = i+nx*j;
+				s.x.a[i0] = x->v(i,j,p)*(1-d) + x->v(i,j,p+1)*d;
+				s.y.a[i0] = y->v(i,j,p)*(1-d) + y->v(i,j,p+1)*d;
+				s.z.a[i0] = z->v(i,j,p)*(1-d) + z->v(i,j,p+1)*d;
+				s.a.a[i0] = a->v(i,j,p)*(1-d) + a->v(i,j,p+1)*d;
+			}
+	}
+	else	// x, y, z -- vectors
+	{
+		if(dir=='x')
+		{
+			v = x->v(p)*(1-d)+x->v(p+1)*d;
+#pragma omp parallel for collapse(2)
+			for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+			{
+				long i0 = i+nx*j;	s.x.a[i0] = v;
+				s.y.a[i0] = y->v(i);	s.z.a[i0] = z->v(j);
+				s.a.a[i0] = a->v(p,i,j)*(1-d) + a->v(p+1,i,j)*d;
+			}
+		}
+		if(dir=='y')
+		{
+			v = y->v(p)*(1-d)+y->v(p+1)*d;
+#pragma omp parallel for collapse(2)
+			for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+			{
+				long i0 = i+nx*j;	s.y.a[i0] = v;
+				s.x.a[i0] = x->v(i);	s.z.a[i0] = z->v(j);
+				s.a.a[i0] = a->v(i,p,j)*(1-d) + a->v(i,p+1,j)*d;
+			}
+		}
+		if(dir=='z')
+		{
+			v = z->v(p)*(1-d)+z->v(p+1)*d;
+#pragma omp parallel for collapse(2)
+			for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+			{
+				long i0 = i+nx*j;	s.z.a[i0] = v;
+				s.x.a[i0] = x->v(i);	s.y.a[i0] = y->v(j);
+				s.a.a[i0] = a->v(i,j,p)*(1-d) + a->v(i,j,p+1)*d;
+			}
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont3_xyz_val(HMGL gr, HCDT v, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, double sVal, const char *opt)
+{
+	bool both = mgl_isboth(x,y,z,a);
+	if(mgl_check_dim3(gr,both,x,y,z,a,0,"Cont3"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Cont3",cgid++);
+	char dir='y';
+	if(mglchr(sch,'x'))	dir='x';
+	if(mglchr(sch,'z'))	dir='z';
+
+	int text=0;
+	if(mglchr(sch,'t'))	text=1;
+	if(mglchr(sch,'T'))	text=2;
+	long ss=gr->AddTexture(sch);
+	gr->SetPenPal(sch);
+
+	_mgl_slice s;
+	mgl_get_slice(s,x,y,z,a,dir,sVal,both);
+#pragma omp parallel for
+	for(long i=0;i<v->GetNx();i++)
+	{
+		mreal v0 = v->v(i);
+		mgl_cont_gen(gr,v0,&s.a,&s.x,&s.y,&s.z,gr->GetC(ss,v0),text,0);
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont3_val(HMGL gr, HCDT v, HCDT a, const char *sch, double sVal, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(a->GetNx()), y(a->GetNy()),z(a->GetNz());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	z.Fill(gr->Min.z,gr->Max.z);
+	mgl_cont3_xyz_val(gr,v,&x,&y,&z,a,sch,sVal,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont3_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, double sVal, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long Num = mgl_isnan(r)?7:long(r+0.5);
+	if(Num<1)	{	gr->SetWarn(mglWarnCnt,"Cont3");	return;	}
+	mglData v(Num);
+	for(long i=0;i<Num;i++)	v.a[i] = gr->Min.c + (gr->Max.c-gr->Min.c)*mreal(i+1)/(Num+1);
+	mgl_cont3_xyz_val(gr,&v,x,y,z,a,sch,sVal,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont3(HMGL gr, HCDT a, const char *sch, double sVal, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long Num = mgl_isnan(r)?7:long(r+0.5);
+	if(Num<1)	{	gr->SetWarn(mglWarnCnt,"Cont3");	return;	}
+	mglData v(Num);
+	for(long i=0;i<Num;i++)	v.a[i] = gr->Min.c + (gr->Max.c-gr->Min.c)*mreal(i+1)/(Num+1);
+	mgl_cont3_val(gr,&v,a,sch,sVal,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont3_xyz_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_cont3_xyz_val(_GR_, _DA_(v), _DA_(x), _DA_(y), _DA_(z), _DA_(a), s, *sVal, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont3_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_cont3_val(_GR_, _DA_(v), _DA_(a), s, *sVal, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont3_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_cont3_xyz(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(a), s, *sVal, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont3_(uintptr_t *gr, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_cont3(_GR_, _DA_(a), s, *sVal, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Dens3 series
+//
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_surf_gen(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT c, HCDT a, const char *sch);
+void MGL_EXPORT mgl_dens3_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, double sVal, const char *opt)
+{
+	bool both = mgl_isboth(x,y,z,a);
+	if(mgl_check_dim3(gr,both,x,y,z,a,0,"Dens3"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Dens3",cgid++);
+	char dir='y';
+	if(mglchr(sch,'x'))	dir='x';
+	if(mglchr(sch,'z'))	dir='z';
+
+	_mgl_slice s;
+	mgl_get_slice(s,x,y,z,a,dir,sVal,both);
+	mgl_surf_gen(gr, &s.x,&s.y,&s.z,&s.a, 0, sch);
+//	mgl_surfc_xy(gr,&s.x,&s.y,&s.z,&s.a,sch,0);
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dens3(HMGL gr, HCDT a, const char *sch, double sVal, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(a->GetNx()), y(a->GetNy()),z(a->GetNz());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	z.Fill(gr->Min.z,gr->Max.z);
+	mgl_dens3_xyz(gr,&x,&y,&z,a,sch,sVal,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dens3_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+mgl_dens3_xyz(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(a), s, *sVal, o);
+delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dens3_(uintptr_t *gr, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+mgl_dens3(_GR_, _DA_(a), s, *sVal, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Grid3 series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_grid3_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, double sVal, const char *opt)
+{
+	bool both = mgl_isboth(x,y,z,a);
+	if(mgl_check_dim3(gr,both,x,y,z,a,0,"Grid3"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Grid3",cgid++);
+	char dir='y';
+	if(mglchr(sch,'x'))	dir='x';
+	if(mglchr(sch,'z'))	dir='z';
+
+	_mgl_slice s;
+	mgl_get_slice(s,x,y,z,a,dir,sVal,both);
+	mgl_mesh_xy(gr,&s.x,&s.y,&s.z,sch,0);
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_grid3(HMGL gr, HCDT a, const char *sch, double sVal, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(a->GetNx()), y(a->GetNy()), z(a->GetNz());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	z.Fill(gr->Min.z,gr->Max.z);
+	mgl_grid3_xyz(gr,&x,&y,&z,a,sch,sVal,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_grid3_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+mgl_grid3_xyz(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(a), s, *sVal, o);
+delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_grid3_(uintptr_t *gr, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+mgl_grid3(_GR_, _DA_(a), s, *sVal, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	ContF3 series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf3_xyz_val(HMGL gr, HCDT v, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, double sVal, const char *opt)
+{
+	bool both = mgl_isboth(x,y,z,a);
+	if(mgl_check_dim3(gr,both,x,y,z,a,0,"ContF3"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("ContF3",cgid++);
+	char dir='y';
+	if(mglchr(sch,'x'))	dir='x';
+	if(mglchr(sch,'z'))	dir='z';
+
+	long ss=gr->AddTexture(sch);
+	_mgl_slice s;
+	mgl_get_slice(s,x,y,z,a,dir,sVal,both);
+#pragma omp parallel for
+	for(long i=0;i<v->GetNx()-1;i++)
+	{
+		mreal v0 = v->v(i);
+		mgl_contf_gen(gr,v0,v->v(i+1),&s.a,&s.x,&s.y,&s.z,gr->GetC(ss,v0),0);
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf3_val(HMGL gr, HCDT v, HCDT a, const char *sch, double sVal, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(a->GetNx()), y(a->GetNy()),z(a->GetNz());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	z.Fill(gr->Min.z,gr->Max.z);
+	mgl_contf3_xyz_val(gr,v,&x,&y,&z,a,sch,sVal,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf3_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, double sVal, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long Num = mgl_isnan(r)?7:long(r+0.5);
+	if(Num<1)	{	gr->SetWarn(mglWarnCnt,"ContF3");	return;	}
+	mglDataV v(Num+2);	v.Fill(gr->Min.c, gr->Max.c);
+	mgl_contf3_xyz_val(gr,&v,x,y,z,a,sch,sVal,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf3(HMGL gr, HCDT a, const char *sch, double sVal, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long Num = mgl_isnan(r)?7:long(r+0.5);
+	if(Num<1)	{	gr->SetWarn(mglWarnCnt,"ContF3");	return;	}
+	mglDataV v(Num+2);	v.Fill(gr->Min.c, gr->Max.c);
+	mgl_contf3_val(gr,&v,a,sch,sVal,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf3_xyz_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+mgl_contf3_xyz_val(_GR_, _DA_(v), _DA_(x), _DA_(y), _DA_(z), _DA_(a), s, *sVal, o);
+delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf3_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+mgl_contf3_val(_GR_, _DA_(v), _DA_(a), s, *sVal, o);
+delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf3_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+mgl_contf3_xyz(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(a), s, *sVal, o);
+delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf3_(uintptr_t *gr, uintptr_t *a, const char *sch, mreal *sVal, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+mgl_contf3(_GR_, _DA_(a), s, *sVal, o);
+delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Axial series
+//
+//-----------------------------------------------------------------------------
+long MGL_LOCAL_PURE mgl_find_prev(long i, long pc, long *nn)
+{
+	for(long k=0;k<pc;k++)	if(nn[k]==i)	return k;
+	return -1;
+}
+void MGL_NO_EXPORT mgl_axial_plot(mglBase *gr,long pc, mglPoint *ff, long *nn,char dir,mreal cc,int wire)
+{
+	mglPoint a(0,0,1),b,c,p,q1,q2;
+	if(dir=='x')	a.Set(1,0,0);
+	if(dir=='y')	a.Set(0,1,0);
+	b = !a;	c = a^b;
+
+	long p1,p2,p3,p4;
+	gr->Reserve(pc*82);
+	for(long i=0;i<pc;i++)
+	{
+		if(nn[i]<0)	continue;
+		long k = mgl_find_prev(i,pc,nn);
+		q1 = k<0 ? ff[nn[i]]-ff[i]  : (ff[nn[i]]-ff[k])*0.5;
+		q2 = nn[nn[i]]<0 ? ff[nn[i]]-ff[i]  : (ff[nn[nn[i]]]-ff[i])*0.5;
+
+		p = a*ff[i].y + c*ff[i].x;
+		p1 = wire ? gr->AddPnt(p,cc) : gr->AddPnt(p,cc,(a*q1.y + c*q1.x)^b);
+		p = a*ff[nn[i]].y + c*ff[nn[i]].x;
+		p2 = wire ? gr->AddPnt(p,cc) : gr->AddPnt(p,cc,(a*q2.y + c*q2.x)^b);
+		if(wire==1)	gr->line_plot(p1,p2);
+		else if(wire)	{	gr->mark_plot(p1,'.');	gr->mark_plot(p2,'.');	}
+
+		for(long j=1;j<41;j++)
+		{
+			p3 = p1;	p4 = p2;
+			float co = mgl_cos[(j*18)%360], si = mgl_cos[(270+j*18)%360];
+//			fi = j*M_PI/20;		si = sin(fi);	co = cos(fi);
+			p = a*ff[i].y + b*(si*ff[i].x) +  c*(co*ff[i].x);
+			p1 = wire ?	gr->AddPnt(p,cc) : gr->AddPnt(p,cc,(a*q1.y + b*(si*q1.x) +  c*(co*q1.x))^(b*co-c*si));
+			p = a*ff[nn[i]].y + b*(si*ff[nn[i]].x) +  c*(co*ff[nn[i]].x);
+			p2 = wire ?	gr->AddPnt(p,cc) : gr->AddPnt(p,cc,(a*q2.y + b*(si*q2.x) +  c*(co*q2.x))^(b*co-c*si));
+			if(wire==1)
+			{	gr->line_plot(p1,p2);	gr->line_plot(p1,p3);
+			gr->line_plot(p4,p2);	gr->line_plot(p4,p3);	}
+			else if(wire)	{	gr->mark_plot(p1,'.');	gr->mark_plot(p2,'.');	}
+			else	gr->quad_plot(p3,p4,p1,p2);
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+// NOTE! All data MUST have the same size! Only first slice is used!
+void MGL_EXPORT mgl_axial_gen(HMGL gr, mreal val, HCDT a, HCDT x, HCDT y, mreal c, char dir,long ak,int wire)
+{
+	long n=a->GetNx(), m=a->GetNy();
+	if(n<2 || m<2 || x->GetNx()*x->GetNy()!=n*m || y->GetNx()*y->GetNy()!=n*m)
+	{	gr->SetWarn(mglWarnDim,"ContGen");	return;	}
+
+	mglPoint *kk = new mglPoint[2*n*m],*pp = new mglPoint[2*n*m],p;
+	long pc=0;
+	// Usually number of points is much smaller. So, there is no reservation.
+	//	gr->Reserve(2*n*m);
+
+	// add intersection point of isoline and X or Y axis
+	const mglData *mx = dynamic_cast<const mglData *>(x);
+	const mglData *my = dynamic_cast<const mglData *>(y);
+	const mglData *ma = dynamic_cast<const mglData *>(a);
+	if(mx&&my&&ma)	for(long j=0;j<m;j++)	for(long i=0;i<n;i++)
+	{
+		long i0 = i+n*j;
+		mreal d = (i<n-1)?mgl_d(val,ma->a[i0+n*m*ak],ma->a[i0+1+n*m*ak]):-1;
+		if(d>=0 && d<1)
+		{
+			pp[pc].Set(mx->a[i0]*(1-d)+mx->a[i0+1]*d, my->a[i0]*(1-d)+my->a[i0+1]*d);
+			kk[pc].Set(i+d,j);	pc++;
+		}
+		d = (j<m-1)?mgl_d(val,ma->a[i0+n*m*ak],ma->a[i0+n*m*ak+n]):-1;
+		if(d>=0 && d<1)
+		{
+			pp[pc].Set(mx->a[i0]*(1-d)+mx->a[i0+n]*d, my->a[i0]*(1-d)+my->a[i0+n]*d);
+			kk[pc].Set(i,j+d);	pc++;
+		}
+	}
+	else	for(long j=0;j<m;j++)	for(long i=0;i<n;i++)
+	{
+		mreal va=a->v(i,j,ak),vx=x->v(i,j),vy=y->v(i,j);
+		mreal d = (i<n-1)?mgl_d(val,va,a->v(i+1,j,ak)):-1;
+		if(d>=0 && d<1)
+		{
+			pp[pc].Set(vx*(1-d)+x->v(i+1,j)*d, vy*(1-d)+y->v(i+1,j)*d);
+			kk[pc].Set(i+d,j);	pc++;
+		}
+		d = (j<m-1)?mgl_d(val,va,a->v(i,j+1,ak)):-1;
+		if(d>=0 && d<1)
+		{
+			pp[pc].Set(vx*(1-d)+x->v(i,j+1)*d, vy*(1-d)+y->v(i,j+1)*d);
+			kk[pc].Set(i,j+d);	pc++;
+		}
+	}
+	// deallocate arrays and finish if no point
+	if(pc==0)	{	delete []kk;	delete []pp;	return;	}
+	// allocate arrays for curve
+	long *nn = new long[pc], *ff = new long[pc];
+	for(long i=0;i<pc;i++)	nn[i] = ff[i] = -1;
+	// connect points to line
+	long j=-1;	// current point
+	do{
+		if(j>=0)
+		{
+			mreal kx = kk[j].x, ky = kk[j].y;	long i = -1;
+			long i11 = long(kx+1e-5), i12 = long(kx-1e-5);
+			long j11 = long(ky+1e-5), j12 = long(ky-1e-5);
+			for(long k=0;k<pc;k++)	// find closest point in grid
+			{
+				if(k==j || k==ff[j] || ff[k]!=-1)	continue;	// point is marked
+				long i21 = long(kk[k].x+1e-5), i22 = long(kk[k].x-1e-5);
+				long j21 = long(kk[k].y+1e-5), j22 = long(kk[k].y-1e-5);
+				// check if in the same cell
+				bool cond = (i11==i21 || i11==i22 || i12==i21 || i12==i22) &&
+				(j11==j21 || j11==j22 || j12==j21 || j12==j22);
+				if(cond){	i=k;	break;	}
+			}
+			if(i<0)	j = -1;	// no free close points
+			else			// mark the point
+			{	nn[j] = i;	ff[i] = j;	j = nn[i]<0 ? i : -1;	}
+		}
+		if(j<0)
+		{
+			for(long k=0;k<pc;k++)	if(nn[k]==-1)	// first check edges
+			{
+				if(kk[k].x==0 || fabs(kk[k].x-n+1)<1e-5 || kk[k].y==0 || fabs(kk[k].y-m+1)<1e-5)
+				{	nn[k]=-2;	j = k;	break;	}
+			}
+			if(j<0)	for(long k=0;k<pc;k++)	if(nn[k]==-1)	// or any points inside
+			{	j = k;	nn[k]=-2;	break;	}
+		}
+	}while(j>=0);
+	mgl_axial_plot(gr,pc,pp,nn,dir,c,wire);
+	delete []kk;	delete []nn;	delete []ff;	delete []pp;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_axial_xy_val(HMGL gr, HCDT v, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{
+	long n=z->GetNx(),m=z->GetNy();
+	if(mgl_check_dim2(gr,x,y,z,0,"Axial"))	return;
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Axial",cgid++);
+	long s=gr->AddTexture(sch);
+	char dir='y';
+	if(mglchr(sch,'x'))	dir = 'x';
+	if(mglchr(sch,'z'))	dir = 'z';
+
+	mglData xx, yy;
+	if(x->GetNx()*x->GetNy()!=m*n || y->GetNx()*y->GetNy()!=m*n)	// make
+	{
+		xx.Create(n, m);		yy.Create(n, m);
+		for(long i=0;i<n;i++)	xx.a[i]=x->v(i);
+		for(long j=1;j<m;j++)	memcpy(xx.a+n*j,xx.a,n*sizeof(mreal));
+		for(long j=0;j<m;j++)
+		{	mreal t=y->v(j);	for(long i=0;i<n;i++)	yy.a[i+n*j]=t;	}
+		x = &xx;	y = &yy;
+	}
+	// x, y -- have the same size z
+	int wire = mglchr(sch,'#')?1:0;
+	if(mglchr(sch,'.'))	wire = 2;
+#pragma omp parallel for collapse(2)
+	for(long i=0;i<v->GetNx();i++)	for(long j=0;j<z->GetNz();j++)
+	{
+		if(gr->NeedStop())	continue;
+		mreal v0 = v->v(i);
+		mgl_axial_gen(gr,v0,z,x,y,gr->GetC(s,v0),dir,j,wire);
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_axial_val(HMGL gr, HCDT v, HCDT a, const char *sch, const char *opt)
+{
+	long n=a->GetNx(), m=a->GetNy();
+	if(n<2 || m<2)	{	gr->SetWarn(mglWarnLow,"Axial");	return;	}
+	gr->SaveState(opt);
+	mglDataV x(n, m), y(n, m);
+	if(gr->Max.x*gr->Min.x>=0)	x.Fill(gr->Min.x,gr->Max.x,'x');
+	else	x.Fill(0,gr->Max.x,'x');
+	y.Fill(gr->Min.y,gr->Max.y,'y');
+	mgl_axial_xy_val(gr,v,&x,&y,a,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_axial_xy(HMGL gr, HCDT x, HCDT y, HCDT a, const char *sch, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long Num = mgl_isnan(r)?3:long(r+0.5);
+	if(Num<1)	{	gr->SetWarn(mglWarnCnt,"Axial");	return;	}
+	mglData v(Num);
+	for(long i=0;i<Num;i++)	v.a[i] = gr->Min.c + (gr->Max.c-gr->Min.c)*mreal(i+1)/(Num+1);
+	mgl_axial_xy_val(gr,&v,x,y,a,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_axial(HMGL gr, HCDT a, const char *sch, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long Num = mgl_isnan(r)?3:long(r+0.5);
+	if(Num<1)	{	gr->SetWarn(mglWarnCnt,"Axial");	return;	}
+	mglData v(Num);
+	for(long i=0;i<Num;i++)	v.a[i] = gr->Min.c + (gr->Max.c-gr->Min.c)*mreal(i+1)/(Num+1);
+	mgl_axial_val(gr,&v,a,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_axial_xy_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *x, uintptr_t *y, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+mgl_axial_xy_val(_GR_, _DA_(v), _DA_(x), _DA_(y), _DA_(a), s, o);
+delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_axial_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+mgl_axial_val(_GR_, _DA_(v), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_axial_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+mgl_axial_xy(_GR_, _DA_(x), _DA_(y), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_axial_(uintptr_t *gr, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+mgl_axial(_GR_, _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//		Torus series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_torus(HMGL gr, HCDT r, HCDT z, const char *sch, const char *opt)
+{
+	long i,j,n=r->GetNx();
+	if(n*r->GetNy()!=z->GetNx()*z->GetNy())	{	gr->SetWarn(mglWarnDim,"Torus");	return;	}
+	if(n<2)		{	gr->SetWarn(mglWarnLow,"Torus");	return;	}
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Torus",cgid++);
+
+	mglPoint *pp = new mglPoint[n];
+	long *nn = new long[n];
+	long ss=gr->AddTexture(sch);
+	char dir='y';
+	if(mglchr(sch,'x'))	dir = 'x';
+	if(mglchr(sch,'z'))	dir = 'z';
+
+	mreal c = gr->GetC(ss,gr->Min.c);
+	const mglData *mr = dynamic_cast<const mglData *>(r);
+	const mglData *mz = dynamic_cast<const mglData *>(z);
+	int wire = mglchr(sch,'#')?1:0;
+	if(mglchr(sch,'.'))	wire = 2;
+	for(j=0;j<r->GetNy();j++)
+	{
+		if(mr&&mz)	for(i=0;i<n;i++)
+		{
+			nn[i] = i<n-1 ? i+1 : -1;
+			pp[i].Set(mr->a[i+n*j], mz->a[i+n*j]);
+		}
+		else	for(i=0;i<n;i++)
+		{
+			nn[i] = i<n-1 ? i+1 : -1;
+			pp[i].Set(r->v(i,j), z->v(i,j));
+		}
+		mgl_axial_plot(gr,n,pp,nn,dir,c,wire);
+	}
+	gr->EndGroup();
+	delete []nn;	delete []pp;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_torus_(uintptr_t *gr, uintptr_t *r, uintptr_t *z, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+mgl_torus(_GR_, _DA_(r), _DA_(z), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
diff --git a/src/cont.hpp b/src/cont.hpp
new file mode 100644
index 0000000..6562988
--- /dev/null
+++ b/src/cont.hpp
@@ -0,0 +1,42 @@
+/***************************************************************************
+ * cont.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2014 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+//-----------------------------------------------------------------------------
+struct mglSegment
+{
+	mglPoint p1,p2;	// edges
+	std::list<mglPoint> pp;
+	bool set(mreal u1,mreal v1,mreal u2,mreal v2,long i,long j,long k,HCDT x, HCDT y, HCDT z)
+	{
+		bool res=(v1>=0 && v1<=MGL_FEPSILON && u1>=0 && u1<=MGL_FEPSILON && v2>=0 && v2<=MGL_FEPSILON && u2>=0 && u2<=MGL_FEPSILON);
+		if(v1==v2 && u1==u2)	res=false;	// NOTE: shouldn't be here never
+		if(res)
+		{
+			p1.Set(mgl_data_linear(x,i+u1,j+v1,k), mgl_data_linear(y,i+u1,j+v1,k), mgl_data_linear(z,i+u1,j+v1,k));
+			p2.Set(mgl_data_linear(x,i+u2,j+v2,k), mgl_data_linear(y,i+u2,j+v2,k), mgl_data_linear(z,i+u2,j+v2,k));
+		}
+		return res;
+	}
+	void before(const mglPoint &p)	{	p1 = p;	pp.push_front(p);	}
+	void after(const mglPoint &p)	{	p2 = p;	pp.push_back(p);	}
+};
+//-----------------------------------------------------------------------------
+std::vector<mglSegment> MGL_EXPORT mgl_get_curvs(HMGL gr, std::vector<mglSegment> lines);
+void MGL_NO_EXPORT mgl_draw_curvs(HMGL gr, mreal val, mreal c, int text, const std::vector<mglSegment> &curvs);
+//-----------------------------------------------------------------------------
diff --git a/src/crust.cpp b/src/crust.cpp
new file mode 100644
index 0000000..c3377fc
--- /dev/null
+++ b/src/crust.cpp
@@ -0,0 +1,775 @@
+/***************************************************************************
+ * crust.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <float.h>
+#include <math.h>
+#include <list>
+#include <limits>
+#include "mgl2/other.h"
+#include "mgl2/data.h"
+#include "mgl2/thread.h"
+#include "mgl2/base.h"
+//-----------------------------------------------------------------------------
+//
+//	TriPlot series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_triplot_xyzc(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt)
+{
+	long n = x->GetNN(), m = nums->GetNy();
+	if(mgl_check_trig(gr,nums,x,y,z,a,"TriPlot"))	return;
+
+	long ss=gr->AddTexture(sch);
+	gr->SaveState(opt);	gr->SetPenPal("-");
+	static int cgid=1;	gr->StartGroup("TriPlot",cgid++);
+
+	bool wire = mglchr(sch,'#');
+	long nc = a->GetNN();
+	if(nc!=n && nc>=m)	// colors per triangle
+	{
+		mglPoint p1,p2,p3,q;
+		gr->Reserve(m*3);
+		for(long i=0;i<m;i++)	if(nums->v(0,i)>=0 && nums->v(1,i)>=0 && nums->v(2,i)>=0)
+		{
+			long k1 = long(nums->v(0,i)+0.5);
+			p1.Set(x->v(k1), y->v(k1), z->v(k1));
+			long k2 = long(nums->v(1,i)+0.5);
+			p2.Set(x->v(k2), y->v(k2), z->v(k2));
+			long k3 = long(nums->v(2,i)+0.5);
+			p3.Set(x->v(k3), y->v(k3), z->v(k3));
+			q = wire ? mglPoint(NAN,NAN) : (p2-p1) ^ (p3-p1);
+			k1 = gr->AddPnt(p1,gr->GetC(ss,a->v(k1)),q);
+			k2 = gr->AddPnt(p2,gr->GetC(ss,a->v(k2)),q);
+			k3 = gr->AddPnt(p3,gr->GetC(ss,a->v(k3)),q);
+			gr->trig_plot(k1,k2,k3);
+		}
+	}
+	else if(nc>=n)		// colors per point
+	{
+		gr->Reserve(n);
+		long *kk = new long[n];
+		mglPoint *pp = new mglPoint[n];
+		for(long i=0;i<m;i++)	if(nums->v(0,i)>=0 && nums->v(1,i)>=0 && nums->v(2,i)>=0)	// add averaged normales
+		{
+			long k1 = long(nums->v(0,i)+0.5);
+			long k2 = long(nums->v(1,i)+0.5);
+			long k3 = long(nums->v(2,i)+0.5);
+			if(!wire)
+			{
+				mglPoint q(mglPoint(x->v(k2)-x->v(k1), y->v(k2)-y->v(k1), z->v(k2)-z->v(k1)) ^
+					mglPoint(x->v(k3)-x->v(k1), y->v(k3)-y->v(k1), z->v(k3)-z->v(k1)));
+				q.Normalize();
+				// try be sure that in the same direction ...
+				if(q.z<0)	q *= -1;
+				pp[k1] += q;	pp[k2] += q;	pp[k3] += q;
+			}
+			else	pp[k1]=pp[k2]=pp[k3]=mglPoint(NAN,NAN);
+		}
+		for(long i=0;i<n;i++)	// add points
+			kk[i] = gr->AddPnt(mglPoint(x->v(i), y->v(i), z->v(i)), gr->GetC(ss,a->v(i)), pp[i]);
+		for(long i=0;i<m;i++)	if(nums->v(0,i)>=0 && nums->v(1,i)>=0 && nums->v(2,i)>=0)	// draw triangles
+		{
+			long k1 = long(nums->v(0,i)+0.5);
+			long k2 = long(nums->v(1,i)+0.5);
+			long k3 = long(nums->v(2,i)+0.5);
+			if(wire)
+			{
+				gr->line_plot(kk[k1],kk[k2]);	gr->line_plot(kk[k1],kk[k3]);
+				gr->line_plot(kk[k3],kk[k2]);
+			}
+			else	gr->trig_plot(kk[k1],kk[k2],kk[k3]);
+		}
+		delete []kk;	delete []pp;
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_triplot_xyz(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{	mgl_triplot_xyzc(gr,nums,x,y,z,z,sch,opt);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_triplot_xy(HMGL gr, HCDT nums, HCDT x, HCDT y, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglData z(x->GetNN());
+	mreal zm = gr->AdjustZMin();	z.Fill(zm,zm);
+	mgl_triplot_xyzc(gr,nums,x,y,&z,&z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_triplot_xyzc_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_triplot_xyzc(_GR_, _DA_(nums), _DA_(x), _DA_(y), _DA_(z), _DA_(c), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_triplot_xyz_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_triplot_xyz(_GR_, _DA_(nums), _DA_(x), _DA_(y), _DA_(z), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_triplot_xy_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_triplot_xy(_GR_, _DA_(nums), _DA_(x), _DA_(y), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	QuadPlot series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_quadplot_xyzc(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt)
+{
+	long n = x->GetNN(), m = nums->GetNy();
+	if(mgl_check_trig(gr,nums,x,y,z,a,"QuadPlot",4))	return;
+
+	long ss=gr->AddTexture(sch);
+	gr->SaveState(opt);	gr->SetPenPal("-");
+	static int cgid=1;	gr->StartGroup("QuadPlot",cgid++);
+	mglPoint p1,p2,p3,p4;
+
+	long nc = a->GetNN();
+	bool wire = mglchr(sch,'#');
+	if(nc!=n && nc>=m)	// colors per triangle
+	{
+		gr->Reserve(m*4);
+		for(long i=0;i<m;i++)	if(nums->v(0,i)>=0 && nums->v(1,i)>=0 && nums->v(2,i)>=0 && nums->v(3,i)>=0)
+		{
+			long k1 = long(nums->v(0,i)+0.5);
+			p1.Set(x->v(k1), y->v(k1), z->v(k1));
+			long k2 = long(nums->v(1,i)+0.5);
+			p2.Set(x->v(k2), y->v(k2), z->v(k2));
+			long k3 = long(nums->v(2,i)+0.5);
+			p3.Set(x->v(k3), y->v(k3), z->v(k3));
+			long k4 = long(nums->v(3,i)+0.5);
+			p4.Set(x->v(k4), y->v(k4), z->v(k4));
+			mglPoint q = wire ? mglPoint(NAN,NAN):(p2-p1) ^ (p3-p1);
+			k1 = gr->AddPnt(p1,gr->GetC(ss,a->v(k1)),q);
+			k2 = gr->AddPnt(p2,gr->GetC(ss,a->v(k2)),q);
+			k3 = gr->AddPnt(p3,gr->GetC(ss,a->v(k3)),q);
+			k4 = gr->AddPnt(p4,gr->GetC(ss,a->v(k4)),q);
+			gr->quad_plot(k1,k2,k3,k4);
+		}
+	}
+	else if(nc>=n)		// colors per point
+	{
+		gr->Reserve(n);
+		long *kk = new long[n];
+		mglPoint *pp = new mglPoint[n];
+		for(long i=0;i<m;i++)	if(nums->v(0,i)>=0 && nums->v(1,i)>=0 && nums->v(2,i)>=0 && nums->v(3,i)>=0)
+		{	// add averaged normales
+			long k1 = long(nums->v(0,i)+0.5);
+			p1.Set(x->v(k1), y->v(k1), z->v(k1));
+			long k2 = long(nums->v(1,i)+0.5);
+			p2.Set(x->v(k2), y->v(k2), z->v(k2));
+			long k3 = long(nums->v(2,i)+0.5);
+			p3.Set(x->v(k3), y->v(k3), z->v(k3));
+			long k4 = long(nums->v(3,i)+0.5);
+			p4.Set(x->v(k4), y->v(k4), z->v(k4));
+
+			if(wire)	pp[k1]=pp[k2]=pp[k3]=pp[k4]=mglPoint(NAN,NAN);
+			else
+			{
+				mglPoint q1 = (p2-p1) ^ (p3-p1);	if(q1.z<0) q1*=-1;
+				mglPoint q2 = (p2-p4) ^ (p3-p4);	if(q2.z<0) q2*=-1;
+				mglPoint q3 = (p1-p2) ^ (p4-p2);	if(q3.z<0) q3*=-1;
+				mglPoint q4 = (p1-p4) ^ (p4-p3);	if(q4.z<0) q4*=-1;
+				pp[k1] += q1;	pp[k2] += q2;	pp[k3] += q3;	pp[k4] += q4;
+			}
+		}
+		for(long i=0;i<n;i++)	// add points
+			kk[i] = gr->AddPnt(mglPoint(x->v(i), y->v(i), z->v(i)),gr->GetC(ss,a->v(i)), pp[i]);
+		for(long i=0;i<m;i++)	if(nums->v(0,i)>=0 && nums->v(1,i)>=0 && nums->v(2,i)>=0 && nums->v(3,i)>=0)
+		{	// draw quads
+			long k1 = long(nums->v(0,i)+0.5);
+			long k2 = long(nums->v(1,i)+0.5);
+			long k3 = long(nums->v(2,i)+0.5);
+			long k4 = long(nums->v(3,i)+0.5);
+			if(wire)
+			{
+				gr->line_plot(kk[k1],kk[k2]);	gr->line_plot(kk[k1],kk[k3]);
+				gr->line_plot(kk[k4],kk[k2]);	gr->line_plot(kk[k4],kk[k3]);
+			}
+			else	gr->quad_plot(kk[k1],kk[k2],kk[k3],kk[k4]);
+		}
+		delete []kk;	delete []pp;
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_quadplot_xyz(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{	mgl_quadplot_xyzc(gr,nums,x,y,z,z,sch,opt);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_quadplot_xy(HMGL gr, HCDT nums, HCDT x, HCDT y, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglData z(x->GetNN());	z.Fill(gr->Min.z,gr->Min.z);
+	mgl_quadplot_xyzc(gr,nums,x,y,&z,&z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_quadplot_xyzc_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_quadplot_xyzc(_GR_, _DA_(nums), _DA_(x), _DA_(y), _DA_(z), _DA_(c), s, o);
+	delete []o;	delete []s;}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_quadplot_xyz_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_quadplot_xyzc(_GR_, _DA_(nums), _DA_(x), _DA_(y), _DA_(z), _DA_(z), s, o);
+	delete []o;	delete []s;}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_quadplot_xy_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_quadplot_xy(_GR_, _DA_(nums), _DA_(x), _DA_(y), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	TriCont series
+//
+//-----------------------------------------------------------------------------
+#include "cont.hpp"
+//-----------------------------------------------------------------------------
+std::vector<mglSegment> MGL_NO_EXPORT mgl_tri_lines(mreal val, HCDT nums, HCDT a, HCDT x, HCDT y, HCDT z)
+{
+	long n = x->GetNN(), m = nums->GetNy();
+	std::vector<mglSegment> lines;
+	for(long i=0;i<m;i++)
+	{
+		long k1 = long(nums->v(0,i)+0.5), k2 = long(nums->v(1,i)+0.5), k3 = long(nums->v(2,i)+0.5);
+		if(k1<0 || k1>=n || k2<0 || k2>=n || k3<0 || k3>=n)	continue;
+		mreal v1 = a->v(k1), v2 = a->v(k2), v3 = a->v(k3);
+		mreal d1 = mgl_d(val,v1,v2), d2 = mgl_d(val,v1,v3), d3 = mgl_d(val,v2,v3);
+		mglSegment line;
+		if(d1>=0 && d1<=1 && d2>=0 && d2<=1)
+		{
+			line.p1.Set(x->v(k1)*(1-d1)+x->v(k2)*d1, y->v(k1)*(1-d1)+y->v(k2)*d1, z->v(k1)*(1-d1)+z->v(k2)*d1);
+			line.p2.Set(x->v(k1)*(1-d2)+x->v(k3)*d2, y->v(k1)*(1-d2)+y->v(k3)*d2, z->v(k1)*(1-d2)+z->v(k3)*d2);
+		}
+		else if(d1>=0 && d1<=1 && d3>=0 && d3<=1)
+		{
+			line.p1.Set(x->v(k1)*(1-d1)+x->v(k2)*d1, y->v(k1)*(1-d1)+y->v(k2)*d1, z->v(k1)*(1-d1)+z->v(k2)*d1);
+			line.p2.Set(x->v(k2)*(1-d3)+x->v(k3)*d3, y->v(k2)*(1-d3)+y->v(k3)*d3, z->v(k2)*(1-d3)+z->v(k3)*d3);
+		}
+		else if(d3>=0 && d3<=1 && d2>=0 && d2<=1)
+		{
+			line.p1.Set(x->v(k1)*(1-d2)+x->v(k3)*d2, y->v(k1)*(1-d2)+y->v(k3)*d2, z->v(k1)*(1-d2)+z->v(k3)*d2);
+			line.p2.Set(x->v(k2)*(1-d3)+x->v(k3)*d3, y->v(k2)*(1-d3)+y->v(k3)*d3, z->v(k2)*(1-d3)+z->v(k3)*d3);
+		}
+		if(line.p1!=line.p2)	lines.push_back(line);
+	}
+	return lines;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tricont_xyzcv(HMGL gr, HCDT v, HCDT nums, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt)
+{
+	mglDataV zz(x->GetNN());
+	if(!z)	z = &zz;
+	if(mgl_check_trig(gr,nums,x,y,z,a,"TriCont"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("TriCont",cgid++);
+	int text=0;
+	if(mglchr(sch,'t'))	text=1;
+	if(mglchr(sch,'T'))	text=2;
+	bool fixed=(mglchr(sch,'_')) || (gr->Min.z==gr->Max.z);
+	long s=gr->AddTexture(sch);
+	gr->SetPenPal(sch);
+
+	for(long k=0;k<v->GetNx();k++)
+	{
+		mreal v0 = v->v(k);		zz.Fill(fixed ? gr->Min.z : v0);
+		mgl_draw_curvs(gr,v0,gr->GetC(s,v0),text,mgl_get_curvs(gr,mgl_tri_lines(v0,nums,a,x,y,fixed?&zz:z)));
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tricont_xyzc(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long n = (mgl_isnan(r) || r<=0) ? 7:long(r+0.5);
+	mglData v(n);
+	for(long i=0;i<n;i++)	v.a[i] = gr->Min.c + (gr->Max.c-gr->Min.c)*mreal(i+1)/(n+1);
+	mgl_tricont_xyzcv(gr,&v,nums,x,y,z,a,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tricont_xyc(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{	mgl_tricont_xyzc(gr,nums,x,y,0,z,sch,opt);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tricont_xycv(HMGL gr, HCDT v, HCDT nums, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{	mgl_tricont_xyzcv(gr,v,nums,x,y,0,z,sch,opt);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tricont_xyzcv_(uintptr_t *gr, uintptr_t *v, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tricont_xyzcv(_GR_, _DA_(v), _DA_(nums), _DA_(x), _DA_(y), _DA_(z), _DA_(c), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tricont_xycv_(uintptr_t *gr, uintptr_t *v, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tricont_xycv(_GR_, _DA_(v), _DA_(nums), _DA_(x), _DA_(y), _DA_(z), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tricont_xyzc_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt, int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tricont_xyzc(_GR_, _DA_(nums), _DA_(x), _DA_(y), _DA_(z), _DA_(c), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tricont_xyc_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt, int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tricont_xyc(_GR_, _DA_(nums), _DA_(x), _DA_(y), _DA_(z), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	TriContV series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tricontv_xyzcv(HMGL gr, HCDT v, HCDT nums, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt)
+{
+	mglDataV zz(x->GetNN());
+	if(!z)	z = &zz;
+	if(mgl_check_trig(gr,nums,x,y,z,a,"TriContV"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("TriContV",cgid++);
+	bool fixed=(mglchr(sch,'_')) || (gr->Min.z==gr->Max.z);
+	long s=gr->AddTexture(sch);
+	gr->SetPenPal(sch);
+
+	for(long k=0;k<v->GetNx();k++)
+	{
+		mreal v0 = v->v(k);		zz.Fill(fixed ? gr->Min.z : v0);
+		mreal dv = (gr->Max.c-gr->Min.c)/8, c = gr->GetC(s,v0);
+		if(k>0)	dv = v->v(k-1)-v->v(k);
+		else if(k<v->GetNx()-1)	dv = v->v(k)-v->v(k+1);
+		if(fixed)	dv=-dv;
+
+		const std::vector<mglSegment> curvs = mgl_get_curvs(gr,mgl_tri_lines(v0,nums,a,x,y,fixed?&zz:z));
+		for(size_t i=0;i<curvs.size();i++)
+		{
+			const std::list<mglPoint> &pp=curvs[i].pp;
+			long f2=-1,g2=-1;
+			for(std::list<mglPoint>::const_iterator it=pp.begin(); it != pp.end(); ++it)
+			{
+				mglPoint p=*it,q(p.y,-p.x);
+				long f1 = f2;	f2 = gr->AddPnt(p,c,q);	p.z+=dv;
+				long g1 = g2;	g2 = gr->AddPnt(p,c,q);
+				gr->quad_plot(f1,g1,f2,g2);
+			}
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tricontv_xyzc(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long n = (mgl_isnan(r) || r<=0) ? 7:long(r+0.5);
+	mglData v(n);
+	for(long i=0;i<n;i++)	v.a[i] = gr->Min.c + (gr->Max.c-gr->Min.c)*mreal(i+1)/(n+1);
+	mgl_tricontv_xyzcv(gr,&v,nums,x,y,z,a,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tricontv_xyc(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{	mgl_tricontv_xyzc(gr,nums,x,y,0,z,sch,opt);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tricontv_xycv(HMGL gr, HCDT v, HCDT nums, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{	mgl_tricontv_xyzcv(gr,v,nums,x,y,0,z,sch,opt);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tricontv_xyzcv_(uintptr_t *gr, uintptr_t *v, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tricontv_xyzcv(_GR_, _DA_(v), _DA_(nums), _DA_(x), _DA_(y), _DA_(z), _DA_(c), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tricontv_xycv_(uintptr_t *gr, uintptr_t *v, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tricontv_xycv(_GR_, _DA_(v), _DA_(nums), _DA_(x), _DA_(y), _DA_(z), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tricontv_xyzc_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt, int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tricontv_xyzc(_GR_, _DA_(nums), _DA_(x), _DA_(y), _DA_(z), _DA_(c), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tricontv_xyc_(uintptr_t *gr, uintptr_t *nums, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt, int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tricontv_xyc(_GR_, _DA_(nums), _DA_(x), _DA_(y), _DA_(z), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Dots series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dots_ca(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT c, HCDT a, const char *sch, const char *opt)
+{
+	long n = x->GetNN(), d, k=1;
+	if(x->GetNz()>1) 	k=3;		else if(x->GetNy()>1)	k=2;
+
+	if(y->GetNN()!=n || z->GetNN()!=n || c->GetNN()!=n || (a && a->GetNN()!=n))
+	{	gr->SetWarn(mglWarnDim,"Dots");	return;	}
+	gr->SaveState(opt);
+
+	d = gr->MeshNum>0 ? mgl_ipow(gr->MeshNum+1,k) : n;
+	d = n>d ? n/d:1;
+
+	static int cgid=1;	gr->StartGroup("Dots",cgid++);
+	char mk=gr->SetPenPal(sch);
+	long ss=gr->AddTexture(sch);
+	if(mk==0)	mk='.';
+	gr->Reserve(n);
+
+	for(long i=0;i<n;i+=d)
+	{
+		mglPoint p(x->vthr(i),y->vthr(i),z->vthr(i));
+		long pp = gr->AddPnt(p,gr->GetC(ss,c->vthr(i)),mglPoint(NAN),a?gr->GetA(a->vthr(i)):-1);
+		gr->mark_plot(pp, mk);
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dots_a(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt)
+{	mgl_dots_ca(gr, x, y, z, z, a, sch, opt);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dots(HMGL gr, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{	mgl_dots_ca(gr, x, y, z, z, NULL, sch, opt);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dots_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_dots(_GR_, _DA_(x),_DA_(y),_DA_(z),s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dots_a_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_dots_a(_GR_, _DA_(x),_DA_(y),_DA_(z),_DA_(a),s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dots_ca_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_dots_ca(_GR_, _DA_(x),_DA_(y),_DA_(z),_DA_(c),_DA_(a),s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	mglTriangulation
+//
+//-----------------------------------------------------------------------------
+long MGL_NO_EXPORT mgl_crust(long n,mglPoint *pp,long **nn,mreal ff);
+HMDT MGL_EXPORT mgl_triangulation_3d(HCDT x, HCDT y, HCDT z)
+{
+	mglData *nums=0;
+	long n = x->GetNN(), m;
+	if(y->GetNN()!=n || z->GetNN()!=n)	return nums;
+	mglPoint *pp = new mglPoint[n];
+	long *nn=0;
+	for(long i=0;i<n;i++)	pp[i].Set(x->v(i), y->v(i), z->v(i));
+	m = mgl_crust(n,pp,&nn,0);
+
+	if(m>0)
+	{
+		nums=new mglData(3,m);
+		for(long i=0;i<3*m;i++)	nums->a[i]=nn[i];
+	}
+	delete []pp;	free(nn);	return nums;
+}
+//-----------------------------------------------------------------------------
+#include "s_hull/s_hull_pro.h"
+HMDT MGL_EXPORT mgl_triangulation_2d(HCDT x, HCDT y)
+{
+	mglData *nums=0;
+	long n = x->GetNN();
+	if(y->GetNN()!=n)	return nums;
+	// use s-hull here
+	std::vector<Shx> pts;
+	Shx pt;
+
+	double x1=mglInf, x2=-mglInf, y1=mglInf, y2=-mglInf;
+	for(long i=0;i<n;i++)
+	{
+		mreal xx=x->vthr(i), yy = y->vthr(i);
+		if(xx<x1)	x1=xx;
+		if(xx>x2)	x2=xx;
+		if(yy<y1)	y1=yy;
+		if(yy>y2)	y2=yy;
+	}
+	const double dx=x2-x1, dy=y2-y1;
+	if(dx==0 || dy==0)	return nums;
+	for(long i=0;i<n;i++)	// Filter NaNs and Infs
+	{
+		pt.r = (x->vthr(i)-x1)/dx;	pt.c = (y->vthr(i)-y1)/dy;
+		if(mgl_isbad(pt.r) || mgl_isbad(pt.c))	continue;
+		pt.id = i;    pts.push_back(pt);
+	}
+
+	std::vector<Triad> triads;
+	static const double float_eps = std::numeric_limits<float>::epsilon();
+	Dupex grid_step(float_eps, float_eps);
+	const size_t original_size = pts.size();
+
+	if(pts.size() >= 3u && 0. < grid_step.r && 0. < grid_step.c) {
+		std::vector<long> out;
+		de_duplicate(pts, out, grid_step);
+
+		if (pts.size() >= 3u && s_hull_pro(pts, triads) < 0) {
+			// Error occured. It may be caused by degenerated dataset. Well, let's try to increment rounding grid step.
+			// Why 4? Why not. There are no particular reasons for this.
+			grid_step.r *= 4.;
+			grid_step.c *= 4.;
+
+			out.clear();
+			triads.clear();
+
+			de_duplicate(pts, out, grid_step);
+
+			if (pts.size() >= 3u && s_hull_pro(pts, triads) < 0) {
+				// Last try. Let's assume uniform points distribution and use range / sqrt(pts.size()) * 2 as epsilon.
+				// It removes a 3/4 of points in optimal case but in the worst case it merges all points to the one.
+				const double density = 1. + floor(0.5 + std::sqrt(static_cast<double>(pts.size())));
+				grid_step.r = grid_step.c = 2/density;
+
+				out.clear();
+				de_duplicate(pts, out, grid_step);
+
+				triads.clear();
+				s_hull_pro(pts, triads);
+			}
+		}
+	}
+
+	if (triads.empty()) {
+		mgl_set_global_warn(_("Cannot triangulate this set!"));
+	} else if(original_size > pts.size()) {
+		mgl_set_global_warn(_("There are duplicated or indistinguishably adjacent points for triangulation."));
+	}
+
+	long m = triads.size();
+	nums=new mglData(3,m);
+	for(long i=0;i<m;i++)
+	{
+		nums->a[3*i]   = triads[i].a;
+		nums->a[3*i+1] = triads[i].b;
+		nums->a[3*i+2] = triads[i].c;
+	}
+	return nums;
+}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_triangulation_3d_(uintptr_t *x, uintptr_t *y, uintptr_t *z)
+{	return uintptr_t(mgl_triangulation_3d(_DA_(x),_DA_(y),_DA_(z)));	}
+uintptr_t MGL_EXPORT mgl_triangulation_2d_(uintptr_t *x, uintptr_t *y)
+{	return uintptr_t(mgl_triangulation_2d(_DA_(x),_DA_(y)));	}
+//-----------------------------------------------------------------------------
+//
+//	DataGrid
+//
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_grid_t(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0],ny=t->p[1];
+	mreal *b=t->a;
+	const mreal *x=t->b, *y=t->c, *d=t->d;
+	HCDT zdat = (HCDT) t->v;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i0=t->id;i0<t->n;i0+=mglNumThr)	if(d[3*i0]>=0 && d[3*i0+1]>=0 && d[3*i0+2]>=0)
+	{
+		long k1 = long(d[3*i0]+0.5), k2 = long(d[3*i0+1]+0.5), k3 = long(d[3*i0+2]+0.5);
+		mreal dxu,dxv,dyu,dyv;
+		mreal z1=zdat->vthr(k1), z2=zdat->vthr(k2), z3=zdat->vthr(k3);
+		mglPoint d1(x[k2]-x[k1],y[k2]-y[k1],z2-z1), d2(x[k3]-x[k1],y[k3]-y[k1],z3-z1), p;
+
+		dxu = d2.x*d1.y - d1.x*d2.y;
+		if(fabs(dxu)<1e-5) continue; // points lies on the same line
+		dyv =-d1.x/dxu; dxv = d1.y/dxu;
+		dyu = d2.x/dxu; dxu =-d2.y/dxu;
+
+		long x1,y1,x2,y2;
+		x1 = long(mgl_min(mgl_min(x[k1],x[k2]),x[k3])); // bounding box
+		y1 = long(mgl_min(mgl_min(y[k1],y[k2]),y[k3]));
+		x2 = long(mgl_max(mgl_max(x[k1],x[k2]),x[k3]));
+		y2 = long(mgl_max(mgl_max(y[k1],y[k2]),y[k3]));
+		x1 = x1>0 ? x1:0; x2 = x2<nx ? x2:nx-1;
+		y1 = y1>0 ? y1:0; y2 = y2<ny ? y2:ny-1;
+		if((x1>x2) | (y1>y2)) continue;
+
+		mreal x0 = x[k1], y0 = y[k1];
+		for(long i=x1;i<=x2;i++) for(long j=y1;j<=y2;j++)
+		{
+			mreal xx = (i-x0), yy = (j-y0);
+			mreal u = dxu*xx+dyu*yy, v = dxv*xx+dyv*yy;
+			if((u<0) | (v<0) | (u+v>1)) continue;
+			b[i+nx*j] = z1 + d1.z*u + d2.z*v;
+		}
+	}
+	return 0;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_grid_xy(HMDT d, HCDT xdat, HCDT ydat, HCDT zdat, mreal x1, mreal x2, mreal y1, mreal y2)
+{ // NOTE: only for mglData
+	const mglData *x = dynamic_cast<const mglData *>(xdat);
+	const mglData *y = dynamic_cast<const mglData *>(ydat);
+	long n=xdat->GetNN();
+	if((n<3) || (ydat->GetNN()!=n) || (zdat->GetNN()!=n))	return;
+
+	mglData *nums = mgl_triangulation_2d(xdat,ydat);
+	if(nums->nx<3)	{	delete nums;	return;	}
+	long nn = nums->ny, par[3]={d->nx,d->ny,d->nz};
+	mreal xx[4]={x1,(d->nx-1)/(x2-x1), y1,(d->ny-1)/(y2-y1)};
+
+	mreal *xc=new mreal[n], *yc=new mreal[n];
+	if(x && y)
+#pragma omp parallel for
+		for(long i=0;i<n;i++)
+		{	xc[i]=xx[1]*(x->a[i]-xx[0]);	yc[i]=xx[3]*(y->a[i]-xx[2]);	}
+	else
+#pragma omp parallel for
+		for(long i=0;i<n;i++)
+		{	xc[i]=xx[1]*(xdat->vthr(i)-xx[0]);	yc[i]=xx[3]*(ydat->vthr(i)-xx[2]);	}
+	long tmp = d->nx*d->ny*d->nz;
+#pragma omp parallel for
+	for(long i=0;i<tmp;i++) d->a[i] = NAN;
+
+	mglStartThread(mgl_grid_t,0,nn,d->a,xc,yc,par,zdat,nums->a);
+	delete nums;	delete []xc;	delete []yc;
+}
+void MGL_EXPORT mgl_data_grid_xy_(uintptr_t *d, uintptr_t *x, uintptr_t *y, uintptr_t *z, mreal *x1, mreal *x2, mreal *y1, mreal *y2)
+{	mgl_data_grid_xy(_DT_,_DA_(x),_DA_(y),_DA_(z),*x1,*x2,*y1,*y2);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_grid(HMGL gr, HMDT d, HCDT xdat, HCDT ydat, HCDT zdat, const char *opt)
+{
+	gr->SaveState(opt);
+	mgl_data_grid_xy(d,xdat,ydat,zdat,gr->Min.x,gr->Max.x,gr->Min.y,gr->Max.y);
+	gr->LoadState();
+}
+void MGL_EXPORT mgl_data_grid_(uintptr_t *gr, uintptr_t *d, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *opt,int lo)
+{	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_data_grid(_GR_,_DT_,_DA_(x),_DA_(y),_DA_(z),o);	delete []o;	}
+//-----------------------------------------------------------------------------
+//
+//	Crust series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_crust(HMGL gr, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{
+	if(y->GetNN()!=x->GetNN() || z->GetNN()!=x->GetNN())
+	{	gr->SetWarn(mglWarnDim,"Crust");	return;	}
+	HMDT nums = mgl_triangulation_3d(x, y, z);
+	mgl_triplot_xyzc(gr,nums,x,y,z,z,sch,opt);
+	mgl_delete_data(nums);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_crust_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_crust(_GR_, _DA_(x),_DA_(y),_DA_(z),s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+long MGL_NO_EXPORT mgl_insert_trig(long i1,long i2,long i3,long **n)
+{
+	static long Cur=0,Max=0;
+	if(i1<0 || i2<0 || i3<0)	return Cur;
+	if(*n==0)
+	{
+		Max = 1024;		Cur = 0;
+		*n = (long *)malloc(Max*3*sizeof(long));
+		memset(*n,0,Max*3*sizeof(long));
+	}
+	if(Cur>=Max)
+	{
+		Max += 1024;
+		*n = (long *)realloc(*n,Max*3*sizeof(long));
+		memset(*n+3*(Max-1024),0,3*1024*sizeof(long));
+	}
+	long *nn;
+	if(i1>i3)	{	long k1=i1;	i1=i3;	i3=k1;	}	// simple sorting
+	if(i1>i2)	{	long k1=i1;	i1=i2;	i2=k1;	}
+	if(i2>i3)	{	long k1=i2;	i2=i3;	i3=k1;	}
+	for(long i=0;i<Cur;i++)	// check if it is unique
+	{
+		nn = *n + 3*i;
+		if(nn[0]==i1 && nn[1]==i2 && nn[2]==i3)	return Cur;
+	}
+	nn = *n + 3*Cur;
+	nn[0]=i1;	nn[1]=i2;	nn[2]=i3;
+	Cur++;	return Cur;
+}
+//-----------------------------------------------------------------------------
+long MGL_NO_EXPORT mgl_get_next(long k1,long n,long *,long *set,mglPoint *qq)
+{
+	long i,j=-1;
+	mreal r,rm=FLT_MAX;
+	for(i=0;i<n;i++)
+	{
+		if(i==k1 || set[i]>0)	continue;
+		r = mgl_anorm(qq[i]-qq[k1]);
+		if(r<rm)	{	rm=r;	j=i;	}
+	}
+	return j;
+}
+//-----------------------------------------------------------------------------
+long MGL_NO_EXPORT mgl_crust(long n,mglPoint *pp,long **nn,mreal ff)
+{	// TODO: update to normal algorithm
+	mreal rs=0;
+	if(ff<=0)	ff=2;
+	for(long i=0;i<n;i++)
+	{
+		mreal rm = FLT_MAX;
+		for(long j=0;j<n;j++)
+		{
+			if(i==j)	continue;
+			mreal r = mgl_anorm(pp[i]-pp[j]);
+			if(rm>r)	rm = r;
+		}
+		rs += sqrt(rm);
+	}
+	rs *= ff/n;	rs = rs*rs;		// "average" distance
+	const int nnum=100;
+	long *ind, *set;	// indexes of "close" points, flag that it was added and its number
+	mglPoint *qq;	// normalized point coordinates
+	ind = new long[nnum];	set = new long[nnum];	qq = new mglPoint[nnum];
+	long k1,k2,k3,m=0;
+	for(long i=0;i<n;i++)	// now the triangles will be found
+	{
+		memset(set,0,nnum*sizeof(long));
+		long ii=0;
+		for(long j=0;j<n;j++)	// find close vertexes
+		{
+			mreal r = mgl_anorm(pp[i]-pp[j]);
+			if(r<=rs && j!=i)	{	ind[ii] = j;	ii++;	if(ii==99)	break;}
+		}
+		if(ii<3)	continue;	// nothing to do
+		for(long j=0;j<ii;j++)
+		{
+			k1 = j;	k2 = ind[j];	k3 = i;
+			qq[k1] = pp[k2] - pp[k3];
+			qq[k1] /= qq[k1].norm();
+		}
+		k1 = 0;
+		while((k2=mgl_get_next(k1,ii,ind,set,qq))>0)
+		{
+			set[k1]=1;
+			mgl_insert_trig(i,ind[k1],ind[k2],nn);
+			k1 = k2;
+		}
+		m = mgl_insert_trig(i,ind[k1],ind[0],nn);
+	}
+	delete []set;	delete []ind;	delete []qq;	return m;
+}
+//-----------------------------------------------------------------------------
diff --git a/src/data.cpp b/src/data.cpp
new file mode 100644
index 0000000..b49a5fc
--- /dev/null
+++ b/src/data.cpp
@@ -0,0 +1,2457 @@
+/***************************************************************************
+ * data.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <time.h>
+#include "mgl2/data.h"
+#include "mgl2/datac.h"
+#include "mgl2/eval.h"
+#include "mgl2/thread.h"
+#include "interp.hpp"
+
+MGL_EXPORT int mglNumThr=0;
+//-----------------------------------------------------------------------------
+#if MGL_HAVE_PTHREAD
+#ifdef WIN32
+#include <windows.h>
+#include <process.h>
+#elif defined(__APPLE__) || defined (__FreeBSD__)
+#include <sys/sysctl.h>
+#elif defined(unix) || defined(__unix) || defined(__unix__)
+#include <sys/sysinfo.h>
+#endif
+void MGL_EXPORT mgl_set_num_thr(int n)
+{
+#ifdef WIN32
+	SYSTEM_INFO systemInfo;
+	GetSystemInfo(&systemInfo);
+	mglNumThr = n>0 ? n : systemInfo.dwNumberOfProcessors;
+#elif defined (__APPLE__) || defined(__FreeBSD__)
+	int numProcessors = 1;
+	size_t size = sizeof(numProcessors);
+	sysctlbyname("hw.ncpu", &numProcessors, &size, NULL, 0);
+	mglNumThr = n>0 ? n : numProcessors;
+#else
+	mglNumThr = n>0 ? n : get_nprocs_conf();
+#endif
+}
+#else
+void MGL_EXPORT mgl_set_num_thr(int)	{	mglNumThr = 1;	}
+#endif
+void MGL_EXPORT mgl_set_num_thr_(int *n)	{	mgl_set_num_thr(*n);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mglStartThread(void *(*func)(void *), void (*post)(mglThreadD *,mreal *), long n,
+					mreal *a, const mreal *b, const mreal *c, const long *p,
+					const void *v, const mreal *d, const mreal *e, const char *s)
+{
+	if(!func)	return;
+#if MGL_HAVE_PTHREAD
+	if(mglNumThr<1)	mgl_set_num_thr(0);
+	if(mglNumThr>1)
+	{
+		pthread_t *tmp=new pthread_t[mglNumThr];
+		mglThreadD *par=new mglThreadD[mglNumThr];
+		for(long i=0;i<mglNumThr;i++)	// put parameters into the structure
+		{	par[i].n=n;	par[i].a=a;	par[i].b=b;	par[i].c=c;	par[i].d=d;
+			par[i].p=p;	par[i].v=v;	par[i].s=s;	par[i].e=e;	par[i].id=i;	}
+		for(long i=0;i<mglNumThr;i++)	pthread_create(tmp+i, 0, func, par+i);
+		for(long i=0;i<mglNumThr;i++)	pthread_join(tmp[i], 0);
+		if(post)	post(par,a);
+		delete []tmp;	delete []par;
+	}
+	else
+#endif
+	{
+		mglNumThr = 1;
+		mglThreadD par;
+		par.n=n;	par.a=a;	par.b=b;	par.c=c;	par.d=d;
+		par.p=p;	par.v=v;	par.s=s;	par.e=e;	par.id=0;
+		func(&par);
+		if(post)	post(&par,a);
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mglStartThreadV(void *(*func)(void *), long n, mreal *a, const void *b,
+					 const void *c, const long *p, const void *v, const mreal *d)
+{
+	if(!func)	return;
+#if MGL_HAVE_PTHREAD
+	if(mglNumThr<1)	mgl_set_num_thr(0);
+	if(mglNumThr>1)
+	{
+		pthread_t *tmp=new pthread_t[mglNumThr];
+		mglThreadV *par=new mglThreadV[mglNumThr];
+		for(long i=0;i<mglNumThr;i++)	// put parameters into the structure
+		{	par[i].n=n;	par[i].a=a;	par[i].b=b;	par[i].c=c;	par[i].d=d;
+			par[i].p=p;	par[i].v=v;	par[i].id=i;par[i].aa=0;	}
+		for(long i=0;i<mglNumThr;i++)	pthread_create(tmp+i, 0, func, par+i);
+		for(long i=0;i<mglNumThr;i++)	pthread_join(tmp[i], 0);
+		delete []tmp;	delete []par;
+	}
+	else
+#endif
+	{
+		mglNumThr = 1;
+		mglThreadV par;
+		par.n=n;	par.a=a;	par.b=b;	par.c=c;	par.d=d;
+		par.p=p;	par.v=v;	par.id=0;	par.aa=0;
+		func(&par);
+	}
+}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mglSpline3s(const mreal *a, long nx, long ny, long nz, mreal x, mreal y, mreal z)
+{	return mglSpline3st<mreal>(a,nx,ny,nz,x,y,z);	}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mglSpline3(const mreal *a, long nx, long ny, long nz, mreal x, mreal y, mreal z,mreal *dx, mreal *dy, mreal *dz)
+{	return mglSpline3t<mreal>(a,nx,ny,nz,x,y,z,dx,dy,dz);	}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mglLinear(const mreal *a, long nx, long ny, long nz, mreal x, mreal y, mreal z)
+{	return mglLineart<mreal>(a,nx,ny,nz,x,y,z);	}
+//-----------------------------------------------------------------------------
+double MGL_EXPORT_CONST mgl_ipow(double x,int n)
+{
+	double t;
+	if(n==2)	return x*x;
+	if(n==1)	return x;
+	if(n<0)		return 1./mgl_ipow(x,-n);
+	if(n==0)	return 1;
+	t = mgl_ipow(x,n/2);	t = t*t;
+	if(n%2==1)	t *= x;
+	return t;
+}
+double MGL_EXPORT mgl_ipow_(mreal *x,int *n)	{	return mgl_ipow(*x,*n);	}
+//-----------------------------------------------------------------------------
+double mgl_get_time(const char *time, const char *fmt)
+{
+#if !defined(WIN32)
+	tm t;
+	strptime(time,fmt,&t);
+	return timegm(&t);
+#else
+	return NAN;
+#endif
+}
+double mgl_get_time_(const char *time, const char *fmt,int l,int m)
+{	char *s=new char[l+1];	memcpy(s,time,l);	s[l]=0;
+	char *f=new char[m+1];	memcpy(f,fmt,m); 	f[m]=0;
+	double t=mgl_get_time(s,f);	delete []s;	delete []f;	return t;	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_smth_x(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0], kind=t->p[2];
+	mreal *b=t->a, delta=t->c[0];
+	const mreal *a=t->b;
+	if(kind>0)
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			long j = i%nx;
+			if(j-kind<0)	j = i+kind-j;
+			else if(j+kind>nx-1)	j = i+nx-1-j-kind;
+			else	j=i;
+			for(long k=-kind;k<=kind;k++)	b[i] += a[j+k]/(2*kind+1);
+		}
+	else
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			long j = i%nx;
+			if(j>1 && j<nx-2)	b[i] = (12*a[i-2] - 3*a[i-1] + 17*a[i] - 3*a[i+1] + 12*a[i+2])/35.;
+			else if(j==1 || j==nx-2)	b[i] = (a[i-1] + a[i] + a[i+1])/3.;
+			else	b[i] = a[i];
+		}
+	if(delta>0)
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			double ab = fabs(a[i]-b[i]);
+			if(ab>delta)	b[i] = a[i]+(delta/ab)*(b[i]-a[i]);
+		}
+		return 0;
+}
+MGL_NO_EXPORT void *mgl_smth_y(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0],ny=t->p[1], kind=t->p[2];
+	mreal *b=t->a, delta=t->c[0];
+	const mreal *a=t->b;
+	if(kind>0)
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			long j = (i/nx)%ny;
+			if(j-kind<0)	j = i+(kind-j)*nx;
+			else if(j+kind>ny-1)	j = i+(ny-1-j-kind)*nx;
+			else	j=i;
+			for(long k=-kind;k<=kind;k++)	b[i] += a[j+k*nx]/(2*kind+1);
+		}
+	else
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			long j = (i/nx)%ny;
+			if(j>1 && j<ny-2)	b[i] = (12*a[i-2*nx] - 3*a[i-nx] + 17*a[i] - 3*a[i+nx] + 12*a[i+2*nx])/35.;
+			else if(j==1 || j==ny-2)	b[i] = (a[i-nx] + a[i] + a[i+nx])/3.;
+			else	b[i] = a[i];
+		}
+	if(delta>0)
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			double ab = fabs(a[i]-b[i]);
+			if(ab>delta)	b[i] = a[i]+(delta/ab)*(b[i]-a[i]);
+		}
+		return 0;
+}
+MGL_NO_EXPORT void *mgl_smth_z(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nn=t->p[0]*t->p[1], nz=t->n/nn, kind=t->p[2];
+	mreal *b=t->a, delta=t->c[0];
+	const mreal *a=t->b;
+	if(kind>1)
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			long j = i/nn;
+			if(j-kind<0)	j = i+(kind-j)*nn;
+			else if(j+kind>nz-1)	j = i+(nz-1-j-kind)*nn;
+			else	j=i;
+			for(long k=-kind;k<=kind;k++)	b[i] += a[j+k*nn]/(2*kind+1);
+		}
+	else
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			long j = i/nn;
+			if(j>1 && j<nz-2)	b[i] = (12*a[i-2*nn] - 3*a[i-nn] + 17*a[i] - 3*a[i+nn] + 12*a[i+2*nn])/35.;
+			else if(j==1 || j==nz-2)	b[i] = (a[i-nn] + a[i] + a[i+nn])/3.;
+			else	b[i] = a[i];
+		}
+	if(delta>0)
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			double ab = fabs(a[i]-b[i]);
+			if(ab>delta)	b[i] = a[i]+(delta/ab)*(b[i]-a[i]);
+		}
+	return 0;
+}
+void MGL_EXPORT mgl_data_smooth(HMDT d, const char *dirs, mreal delta)
+{
+	long Type = -1;
+	if(!dirs || *dirs==0)	dirs = "xyz";
+	if(strchr(dirs,'0'))	return;
+	if(strchr(dirs,'d'))
+	{
+		if(strchr(dirs,'1'))	Type = 1;
+		if(strchr(dirs,'2'))	Type = 2;
+		if(strchr(dirs,'3'))	Type = 3;
+		if(strchr(dirs,'4'))	Type = 4;
+		if(strchr(dirs,'5'))	Type = 5;
+		if(strchr(dirs,'6'))	Type = 6;
+		if(strchr(dirs,'7'))	Type = 7;
+		if(strchr(dirs,'8'))	Type = 8;
+		if(strchr(dirs,'9'))	Type = 9;
+	}
+	else
+	{
+		if(strchr(dirs,'1'))	return;
+		if(strchr(dirs,'3'))	Type = 1;
+		if(strchr(dirs,'5'))	Type = 2;
+	}
+	long nx=d->nx,ny=d->ny,nz=d->nz;
+//	if(Type == SMOOTH_NONE)	return;
+	long p[3]={nx,ny,Type};
+	mreal *b = new mreal[nx*ny*nz],dd=delta;
+	// ����������� �� x
+	memset(b,0,nx*ny*nz*sizeof(mreal));
+	if(nx>4 && strchr(dirs,'x'))
+	{
+		mglStartThread(mgl_smth_x,0,nx*ny*nz,b,d->a,&dd,p);
+		memcpy(d->a,b,nx*ny*nz*sizeof(mreal));
+		memset(b,0,nx*ny*nz*sizeof(mreal));
+	}
+	if(ny>4 && strchr(dirs,'y'))
+	{
+		mglStartThread(mgl_smth_y,0,nx*ny*nz,b,d->a,&dd,p);
+		memcpy(d->a,b,nx*ny*nz*sizeof(mreal));
+		memset(b,0,nx*ny*nz*sizeof(mreal));
+	}
+	if(nz>4 && strchr(dirs,'z'))
+	{
+		mglStartThread(mgl_smth_z,0,nx*ny*nz,b,d->a,&dd,p);
+		memcpy(d->a,b,nx*ny*nz*sizeof(mreal));
+	}
+	delete []b;
+}
+void MGL_EXPORT mgl_data_smooth_(uintptr_t *d, const char *dir, mreal *delta,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_data_smooth(_DT_,s,*delta);		delete []s;	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_csum_z(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nz=t->p[2], nn=t->n;
+	mreal *b=t->a;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		b[i] = a[i];
+		for(long j=1;j<nz;j++)	b[i+j*nn] = b[i+j*nn-nn] + a[i+j*nn];
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_csum_y(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0], ny=t->p[1], nn=t->n;
+	mreal *b=t->a;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = (i%nx)+nx*ny*(i/nx);		b[k] = a[k];
+		for(long j=1;j<ny;j++)	b[k+j*nx] = b[k+j*nx-nx] + a[k+nx*j];
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_csum_x(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0], nn=t->n;
+	mreal *b=t->a;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = i*nx;			b[k] = a[k];
+		for(long j=1;j<nx;j++)	b[j+k] = b[j+k-1] + a[j+k];
+	}
+	return 0;
+}
+void MGL_EXPORT mgl_data_cumsum(HMDT d, const char *dir)
+{
+	if(!dir || *dir==0)	return;
+	long nx=d->nx,ny=d->ny,nz=d->nz,nn=nx*ny*nz;
+	long p[3]={nx,ny,nz};
+	mreal *b = new mreal[nn];
+	memcpy(b,d->a,nn*sizeof(mreal));
+	if(strchr(dir,'z') && nz>1)
+	{
+		mglStartThread(mgl_csum_z,0,nx*ny,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(mreal));
+	}
+	if(strchr(dir,'y') && ny>1)
+	{
+		mglStartThread(mgl_csum_y,0,nx*nz,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(mreal));
+	}
+	if(strchr(dir,'x') && nx>1)
+	{
+		mglStartThread(mgl_csum_x,0,nz*ny,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(mreal));
+	}
+	delete []b;
+}
+void MGL_EXPORT mgl_data_cumsum_(uintptr_t *d, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_data_cumsum(_DT_,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_int_z(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nz=t->p[2], nn=t->n;
+	mreal *b=t->a, dd=0.5/nz;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		b[i] = 0;
+		for(long j=1;j<nz;j++)	b[i+j*nn] = b[i+j*nn-nn] + (a[i+nn*j]+a[i+j*nn-nn])*dd;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_int_y(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0], ny=t->p[1], nn=t->n;
+	mreal *b=t->a, dd=0.5/ny;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = (i%nx)+nx*ny*(i/nx);	b[k] = 0;
+		for(long j=1;j<ny;j++)	b[k+j*nx] = b[k+j*nx-nx] + (a[k+j*nx]+a[k+j*nx-nx])*dd;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_int_x(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0], nn=t->n;
+	mreal *b=t->a, dd=0.5/nx;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = i*nx;			b[k] = 0;
+		for(long j=1;j<nx;j++)	b[j+k] = b[j+k-1] + (a[j+k]+a[j+k-1])*dd;
+	}
+	return 0;
+}
+void MGL_EXPORT mgl_data_integral(HMDT d, const char *dir)
+{
+	if(!dir || *dir==0)	return;
+	long nx=d->nx,ny=d->ny,nz=d->nz,nn=nx*ny*nz;
+	long p[3]={nx,ny,nz};
+	mreal *b = new mreal[nn];
+	memcpy(b,d->a,nn*sizeof(mreal));
+	if(strchr(dir,'z') && nz>1)
+	{
+		mglStartThread(mgl_int_z,0,nx*ny,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(mreal));
+	}
+	if(strchr(dir,'y') && ny>1)
+	{
+		mglStartThread(mgl_int_y,0,nx*nz,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(mreal));
+	}
+	if(strchr(dir,'x') && nx>1)
+	{
+		mglStartThread(mgl_int_x,0,nz*ny,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(mreal));
+	}
+	delete []b;
+}
+void MGL_EXPORT mgl_data_integral_(uintptr_t *d, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_data_integral(_DT_,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_dif_z(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nz=t->p[2], nn=t->n;
+	mreal *b=t->a, dd=0.5*nz;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		b[i] = -(3*a[i]-4*a[i+nn]+a[i+2*nn])*dd;
+		b[i+(nz-1)*nn] = (3*a[i+(nz-1)*nn]-4*a[i+(nz-2)*nn]+a[i+(nz-3)*nn])*dd;
+		for(long j=1;j<nz-1;j++)		b[i+j*nn] = (a[i+j*nn+nn]-a[i+j*nn-nn])*dd;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_dif_y(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0], ny=t->p[1], nn=t->n;
+	mreal *b=t->a, dd=0.5*ny;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = (i%nx)+nx*ny*(i/nx);
+		b[k] = -(3*a[k]-4*a[k+nx]+a[k+2*nx])*dd;
+		b[k+(ny-1)*nx] = (3*a[k+(ny-1)*nx]-4*a[k+(ny-2)*nx]+a[k+(ny-3)*nx])*dd;
+		for(long j=1;j<ny-1;j++)	b[k+j*nx] = (a[k+j*nx+nx]-a[k+j*nx-nx])*dd;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_dif_x(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0], nn=t->n;
+	mreal *b=t->a, dd=0.5*nx;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = i*nx;
+		b[k] = -(3*a[k]-4*a[k+1]+a[k+2])*dd;
+		b[k+nx-1] = (3*a[k+nx-1]-4*a[k+nx-2]+a[k+nx-3])*dd;
+		for(long j=1;j<nx-1;j++)	b[j+k] = (a[j+k+1]-a[j+k-1])*dd;
+	}
+	return 0;
+}
+void MGL_EXPORT mgl_data_diff(HMDT d, const char *dir)
+{
+	if(!dir || *dir==0)	return;
+	long nx=d->nx,ny=d->ny,nz=d->nz,nn=nx*ny*nz;
+	long p[3]={nx,ny,nz};
+	mreal *b = new mreal[nn];
+	if(strchr(dir,'z') && nz>1)
+	{
+		mglStartThread(mgl_dif_z,0,nx*ny,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(mreal));
+	}
+	if(strchr(dir,'y') && ny>1)
+	{
+		mglStartThread(mgl_dif_y,0,nx*nz,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(mreal));
+	}
+	if(strchr(dir,'x') && nx>1)
+	{
+		mglStartThread(mgl_dif_x,0,nz*ny,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(mreal));
+	}
+	delete []b;
+}
+void MGL_EXPORT mgl_data_diff_(uintptr_t *d, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_data_diff(_DT_,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_dif2_z(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nz=t->p[2], nn=t->n;
+	mreal *b=t->a, dd=0.5*nz*nz;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		b[i] = b[i+(nz-1)*nn] = 0;
+		for(long j=1;j<nz-1;j++)		b[i+j*nn] = (a[i+j*nn+nn]+a[i+j*nn-nn]-2*a[i+j*nn])*dd;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_dif2_y(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0], ny=t->p[1], nn=t->n;
+	mreal *b=t->a, dd=0.5*ny*ny;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = (i%nx)+nx*ny*(i/nx);	b[k] = b[k+(ny-1)*nx] = 0;
+		for(long j=1;j<ny-1;j++)	b[k+j*nx] = (a[k+j*nx+nx]+a[k+j*nx-nx]-2*a[k+j*nx])*dd;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_dif2_x(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0], nn=t->n;
+	mreal *b=t->a, dd=0.5*nx*nx;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = i*nx;			b[k] = b[k+nx-1] = 0;
+		for(long j=1;j<nx-1;j++)	b[j+k] = (a[j+k+1]+a[j+k-1]-2*a[j+k])*dd;
+	}
+	return 0;
+}
+void MGL_EXPORT mgl_data_diff2(HMDT d, const char *dir)
+{
+	if(!dir || *dir==0)	return;
+	long nx=d->nx,ny=d->ny,nz=d->nz,nn=nx*ny*nz;
+	long p[3]={nx,ny,nz};
+	mreal *b = new mreal[nn];
+	if(strchr(dir,'z') && nz>1)
+	{
+		mglStartThread(mgl_dif2_z,0,nx*ny,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(mreal));
+	}
+	if(strchr(dir,'y') && ny>1)
+	{
+		mglStartThread(mgl_dif2_y,0,nx*nz,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(mreal));
+	}
+	if(strchr(dir,'x') && nx>1)
+	{
+		mglStartThread(mgl_dif2_x,0,nz*ny,b,d->a,0,p);
+		memcpy(d->a,b,nn*sizeof(mreal));
+	}
+	delete []b;
+}
+void MGL_EXPORT mgl_data_diff2_(uintptr_t *d, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_data_diff2(_DT_,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_swap(HMDT d, const char *dir)
+{
+	if(!dir || *dir==0)	return;
+	if(strchr(dir,'z') && d->nz>1)	mgl_data_roll(d,'z',d->nz/2);
+	if(strchr(dir,'y') && d->ny>1)	mgl_data_roll(d,'y',d->ny/2);
+	if(strchr(dir,'x') && d->nx>1)	mgl_data_roll(d,'x',d->nx/2);
+}
+void MGL_EXPORT mgl_data_swap_(uintptr_t *d, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_data_swap(_DT_,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_roll(HMDT dd, char dir, long num)
+{
+	long nx=dd->nx,ny=dd->ny,nz=dd->nz, d;
+	mreal *b,*a=dd->a;
+	if(dir=='z' && nz>1)
+	{
+		d = num>0 ? num%nz : (num+nz*(1-num/nz))%nz;
+		if(d==0)	return;		// nothing to do
+		b = new mreal[nx*ny*nz];
+		memcpy(b,a+nx*ny*d,nx*ny*(nz-d)*sizeof(mreal));
+		memcpy(b+nx*ny*(nz-d),a,nx*ny*d*sizeof(mreal));
+		memcpy(a,b,nx*ny*nz*sizeof(mreal));	delete []b;
+	}
+	if(dir=='y' && ny>1)
+	{
+		d = num>0 ? num%ny : (num+ny*(1-num/ny))%ny;
+		if(d==0)	return;		// nothing to do
+		b = new mreal[nx*ny*nz];
+		memcpy(b,a+nx*d,(nx*ny*nz-nx*d)*sizeof(mreal));
+#pragma omp parallel for
+		for(long i=0;i<nz;i++)
+			memcpy(b+nx*(ny-d)+nx*ny*i,a+nx*ny*i,nx*d*sizeof(mreal));
+		memcpy(a,b,nx*ny*nz*sizeof(mreal));	delete []b;
+	}
+	if(dir=='x' && nx>1)
+	{
+		d = num>0 ? num%nx : (num+nx*(1-num/nx))%nx;
+		if(d==0)	return;		// nothing to do
+		b = new mreal[nx*ny*nz];
+		memcpy(b,a+d,(nx*ny*nz-d)*sizeof(mreal));
+#pragma omp parallel for
+		for(long i=0;i<nz*ny;i++)
+			memcpy(b+nx-d+nx*i,a+nx*i,d*sizeof(mreal));
+		memcpy(a,b,nx*ny*nz*sizeof(mreal));	delete []b;
+	}
+}
+void MGL_EXPORT mgl_data_roll_(uintptr_t *d, const char *dir, int *num, int)
+{	mgl_data_roll(_DT_,*dir,*num);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_mirror(HMDT d, const char *dir)
+{
+	if(!dir || *dir==0)	return;
+	long nx=d->nx,ny=d->ny,nz=d->nz;
+	mreal *a=d->a;
+	if(strchr(dir,'z') && nz>1)
+	{
+#pragma omp parallel for collapse(2)
+		for(long j=0;j<nz/2;j++)	for(long i=0;i<nx*ny;i++)
+		{
+			long i0 = i+j*nx*ny, j0 = i+(nz-1-j)*nx*ny;
+			mreal b = a[i0];	a[i0] = a[j0];	a[j0] = b;
+		}
+	}
+	if(strchr(dir,'y') && ny>1)
+	{
+#pragma omp parallel for
+		for(long i=0;i<nx*nz;i++)
+		{
+			long j0 = (i%nx)+nx*ny*(i/nx);
+			for(long j=0;j<ny/2;j++)
+			{
+				long i0 = j0+(ny-1-j)*nx;
+				mreal b = a[j0+j*nx];	a[j0+j*nx] = a[i0];	a[i0] = b;
+			}
+		}
+	}
+	if(strchr(dir,'x') && nx>1)
+	{
+#pragma omp parallel for
+		for(long j=0;j<ny*nz;j++)
+		{
+			long j0 = j*nx;
+			for(long i=0;i<nx/2;i++)
+			{
+				long i0 = nx-1-i+j0;
+				mreal b = a[i+j0];	a[i+j0] = a[i0];	a[i0] = b;
+			}
+		}
+	}
+}
+void MGL_EXPORT mgl_data_mirror_(uintptr_t *d, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_data_mirror(_DT_,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_clean(HMDT d, long id)
+{
+	if(id<0 || id+1>d->nx)	return;
+	long i,j,n=d->nx,m=d->ny;
+	mreal *b = new mreal[m*n], *a=d->a;
+	for(i=j=0;i+1<m;i++)
+	{
+		if(a[id+n*i]!=a[id+n*i+n])	// this can be saved
+		{
+#pragma omp parallel for
+			for(long k=0;k<n;k++)	b[k+n*j]=a[k+n*i];
+			j++;
+		}
+	}
+	// always save last row
+	i=n*(m-1);
+#pragma omp parallel for
+	for(long k=0;k<n;k++)	b[k+n*j]=a[k+i];
+	j++;
+	memcpy(a,b,n*j*sizeof(mreal));	d->ny = j;
+	delete []b;
+}
+void MGL_EXPORT mgl_data_clean_(uintptr_t *d, int *id)	{	mgl_data_clean(_DT_,*id);	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_solve_x(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	HCDT d=(HCDT)t->v;
+	long nx=t->p[0], ny=t->p[1], nz=t->p[2], n1=t->p[3]?nx-1:1, nn=t->n;
+	const mreal *a=t->b, *ii=t->c;
+	mreal *b=t->a,val=t->d[0],da = 1e-5*(val?fabs(val):1);
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long l=t->id;l<nn;l+=mglNumThr)
+	{
+		long j=l%ny, k=l/ny;	b[l] = NAN;
+		if(ii && ii[l]!=ii[l])	continue;
+		long i0 = ii?(ii[l]*n1+1):0;
+		if(i0>nx-2)	continue;
+		if(a)	for(long i=i0+1;i<nx;i++)
+		{
+			mreal y1=a[i-1+nx*l], y2=a[i+nx*l];
+			if((y1-val)*(y2-val)<=0)
+			{
+				mreal x = i-1 + (val-y1)/(y2-y1), dx;
+				mreal v0=mglSpline3(a,nx,ny,nz,x,j,k, &dx,0,0), v=v0;
+				unsigned kk=0;
+				while(fabs(v-val)>da || dx==0)
+				{
+					x += (val-v)/dx;		kk++;
+					v = mglSpline3(a,nx,ny,nz,x,j,k, &dx,0,0);
+					if(kk>=10)
+					{
+						b[l] = x = fabs(v-val)<fabs(v0-val) ? x:i-1 + (val-y1)/(y2-y1);
+						break;
+					}
+				}
+				b[l] = x;	break;
+			}
+		}
+		else 	for(long i=i0+1;i<nx;i++)
+		{
+			mreal y1=d->v(i-1,j,k), y2=d->v(i,j,k);
+			if((y1-val)*(y2-val)<=0)
+			{	b[l] = i-1 + (val-y1)/(y2-y1);	break;	}
+		}
+		b[l] /= n1;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_solve_y(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	HCDT d=(HCDT)t->v;
+	long nx=t->p[0], ny=t->p[1], nz=t->p[2], n1=t->p[3]?ny-1:1, nn=t->n;
+	const mreal *a=t->b, *ii=t->c;
+	mreal *b=t->a,val=t->d[0],da = 1e-5*(val?fabs(val):1);
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long l=t->id;l<nn;l+=mglNumThr)
+	{
+		long j=l%nx, k=l/nx;	b[l] = NAN;
+		if(ii && ii[l]!=ii[l])	continue;
+		long i0 = ii?(ii[l]*n1+1):0;
+		if(i0>ny-2)	continue;
+		if(a)	for(long i=i0+1;i<ny;i++)
+		{
+			mreal y1=a[j+nx*(i-1+ny*k)], y2=a[j+nx*(i+ny*k)];
+			if((y1-val)*(y2-val)<=0)
+			{
+				mreal x = i-1 + (val-y1)/(y2-y1), dy;
+				mreal v0=mglSpline3(a,nx,ny,nz,j,x,k, 0,&dy,0), v=v0;
+				unsigned kk=0;
+				while(fabs(v-val)>da || dy==0)
+				{
+					x += (val-v)/dy;		kk++;
+					v = mglSpline3(a,nx,ny,nz,j,x,k, 0,&dy,0);
+					if(kk>=10)
+					{
+						b[l] = x = fabs(v-val)<fabs(v0-val) ? x:i-1 + (val-y1)/(y2-y1);
+						break;
+					}
+				}
+				b[l] = x;	break;
+			}
+		}
+		else 	for(long i=i0+1;i<ny;i++)
+		{
+			mreal y1=d->v(j,i-1,k), y2=d->v(j,i,k);
+			if((y1-val)*(y2-val)<=0)
+			{	b[l] = i-1 + (val-y1)/(y2-y1);	break;	}
+		}
+		b[l] /= n1;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_solve_z(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	HCDT d=(HCDT)t->v;
+	long nx=t->p[0], ny=t->p[1], nz=t->p[2], n1=t->p[3]?nz-1:1, nn=t->n;
+	const mreal *a=t->b, *ii=t->c;
+	mreal *b=t->a,val=t->d[0],da = 1e-5*(val?fabs(val):1);
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long l=t->id;l<nn;l+=mglNumThr)
+	{
+		long j=l%nx, k=l/nx;	b[l] = NAN;
+		if(ii && ii[l]!=ii[l])	continue;
+		long i0 = ii?(ii[l]*n1+1):0;
+		if(i0>nz-2)	continue;
+		if(a)	for(long i=i0+1;i<nz;i++)
+		{
+			mreal y1=a[nn*i-nn+l], y2=a[nn*i+l];
+			if((y1-val)*(y2-val)<=0)
+			{
+				mreal x = i-1 + (val-y1)/(y2-y1), dz;
+				mreal v0=mglSpline3(a,nx,ny,nz,j,k,x, 0,0,&dz), v=v0;
+				unsigned kk=0;
+				while(fabs(v-val)>da || dz==0)
+				{
+					x += (val-v)/dz;		kk++;
+					v = mglSpline3(a,nx,ny,nz,j,k,x, 0,0,&dz);
+					if(kk>=10)
+					{
+						b[l] = x = fabs(v-val)<fabs(v0-val) ? x:i-1 + (val-y1)/(y2-y1);
+						break;
+					}
+				}
+				b[l] = x;	break;
+			}
+		}
+		else 	for(long i=i0+1;i<nz;i++)
+		{
+			mreal y1=d->v(j,k,i-1), y2=d->v(j,k,i);
+			if((y1-val)*(y2-val)<=0)
+			{	b[l] = i-1 + (val-y1)/(y2-y1);	break;	}
+		}
+		b[l] /= n1;
+	}
+	return 0;
+}
+HMDT MGL_EXPORT mgl_data_solve(HCDT dat, mreal val, char dir, HCDT i0, int norm)
+{
+	const mglData *i = dynamic_cast<const mglData *>(i0);
+	const mglData *d = dynamic_cast<const mglData *>(dat);
+	long p[4]={dat->GetNx(), dat->GetNy(), dat->GetNz(), norm};
+	const mreal *ii=0;
+	mglData *r=new mglData, id0;
+	if(i0 && !i)	{	id0.Set(i0);	i=&id0;	}	// <-- slow but should work
+	if(dir=='x' && p[0]>1)
+	{
+		r->Create(p[1],p[2]);
+		ii = (i && i->nx*i->ny==p[1]*p[2])?i->a:0;
+		mglStartThread(mgl_solve_x,0,p[1]*p[2],r->a,d?d->a:0,ii,p,dat,&val);
+	}
+	if(dir=='y' && p[1]>1)
+	{
+		r->Create(p[0],p[2]);
+		ii = (i && i->nx*i->ny==p[0]*p[2])?i->a:0;
+		mglStartThread(mgl_solve_y,0,p[0]*p[2],r->a,d?d->a:0,ii,p,dat,&val);
+	}
+	if(dir=='z' && p[2]>1)
+	{
+		r->Create(p[0],p[1]);
+		ii = (i && i->nx*i->ny==p[0]*p[1])?i->a:0;
+		mglStartThread(mgl_solve_z,0,p[0]*p[1],r->a,d?d->a:0,ii,p,dat,&val);
+	}
+	return r;
+}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_data_solve_1d(HCDT d, mreal val, int spl, long i0)
+{
+	mreal x=0, y1, y2, a, a0, dx=0, da = 1e-5*(val?fabs(val):1);
+	long nx = d->GetNx();
+	if(i0<0 || i0>=nx)	i0=0;
+	if(val==d->v(i0+1))	return i0+1;
+	const mglData *dd=dynamic_cast<const mglData *>(d);
+	const mglDataC *dc=dynamic_cast<const mglDataC *>(d);
+	if(dd)	for(long i=i0+1;i<nx;i++)
+	{
+		y1=dd->a[i-1];	y2=dd->a[i];
+		if((y1-val)*(y2-val)<=0)
+		{
+			x = i-1 + (val-y1)/(y2-y1);
+			a0 = a = mglSpline1t<mreal>(dd->a,nx,x,&dx);
+			if(spl)	for(unsigned k=0;fabs(a-val)>da || dx==0;)
+			{
+				x += (val-a)/dx;		k++;
+				a = mglSpline1t<mreal>(dd->a,nx,x,&dx);
+				if(k>=10)
+					return fabs(a-val)<fabs(a0-val) ? x:i-1 + (val-y1)/(y2-y1);
+			}
+			return x;
+		}
+	}
+	else if(dc)	for(long i=i0+1;i<nx;i++)
+	{
+		y1=abs(dc->a[i-1]);	y2=abs(dc->a[i]);
+		if((y1-val)*(y2-val)<=0)
+		{
+			x = i-1 + (val-y1)/(y2-y1);
+			dual cx, ca = mglSpline1t<dual>(dc->a,nx,x,&cx);
+			a0 = a = abs(ca);	dx = a?(cx.real()*ca.real()+cx.imag()*ca.imag())/a:0;
+			if(spl)	for(unsigned k=0;fabs(a-val)>da || dx==0;)
+			{
+				x += (val-a)/dx;		k++;
+				ca = mglSpline1t<dual>(dc->a,nx,x,&cx);
+				a = abs(ca);	dx = a?(cx.real()*ca.real()+cx.imag()*ca.imag())/a:0;
+				if(k>=10)
+					return fabs(a-val)<fabs(a0-val) ? x:i-1 + (val-y1)/(y2-y1);
+			}
+			return x;
+		}
+	}
+	else 	for(long i=i0+1;i<nx;i++)
+	{
+		y1=d->v(i-1);	y2=d->v(i);
+		if((y1-val)*(y2-val)<=0)
+			return i-1 + (val-y1)/(y2-y1);
+	}
+	return NAN;
+}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_data_linear_ext(HCDT d, mreal x,mreal y,mreal z, mreal *dx,mreal *dy,mreal *dz)
+{
+	if(!d)	return NAN;
+	long kx=long(x), ky=long(y), kz=long(z);
+	mreal b0,b1;
+	const mglData *dd=dynamic_cast<const mglData *>(d);
+	if(dd)
+	{
+		long nx=dd->nx, ny=dd->ny, nz=dd->nz, dn=ny>1?nx:0;
+		kx = kx>=0 ? kx:0;	kx = kx<nx-1 ? kx:nx-2;
+		ky = ky>=0 ? ky:0;	ky = ky<ny-1 ? ky:ny-2;
+		kz = kz>=0 ? kz:0;	kz = kz<nz-1 ? kz:nz-2;
+		x -= kx;	y -= ky;	z -= kz;
+		const mreal *aa = dd->a, *bb;
+		if(kz>=0)
+		{
+			aa=dd->a+kx+nx*(ky+ny*kz);	bb = aa+nx*ny;
+			b0 = aa[0]*(1-x-y+x*y) + x*(1-y)*aa[1] + y*(1-x)*aa[dn] + x*y*aa[1+dn];
+			b1 = bb[0]*(1-x-y+x*y) + x*(1-y)*bb[1] + y*(1-x)*bb[dn] + x*y*bb[1+dn];
+		}
+		else
+		{
+			z=0;
+			if(ky>=0)
+			{
+				aa=dd->a+kx+nx*ky;
+				b0 = b1 = aa[0]*(1-x-y+x*y) + x*(1-y)*aa[1] + y*(1-x)*aa[dn] + x*y*aa[1+dn];
+			}
+			else if(kx>=0)
+			{
+				aa=dd->a+kx;	b0 = b1 = aa[0]*(1-x) + x*aa[1];
+			}
+			else	b0 = b1 = dd->a[0];
+		}
+		if(dx)	*dx = kx>=0?aa[1]-aa[0]:0;
+		if(dy)	*dy = ky>=0?aa[dn]-aa[0]:0;
+		if(dz)	*dz = b1-b0;
+	}
+	else
+	{
+		long nx=d->GetNx(), ny=d->GetNy(), nz=d->GetNz();
+		kx = kx>=0 ? kx:0;	kx = kx<nx-1 ? kx:nx-2;
+		ky = ky>=0 ? ky:0;	ky = ky<ny-1 ? ky:ny-2;
+		kz = kz>=0 ? kz:0;	kz = kz<nz-1 ? kz:nz-2;
+		x -= kx;	y -= ky;	z -= kz;
+		mreal a0 = 0, a1 = 0, a2 = 0;
+		if(kz>=0)
+		{
+			a0 = d->v(kx,ky,kz);	a1 = d->v(kx+1,ky,kz);	a2 = d->v(kx,ky+1,kz);
+			b0 = a0*(1-x-y+x*y) + x*(1-y)*a1 + y*(1-x)*a2 + x*y*d->v(kx+1,ky+1,kz);;
+			b1 = d->v(kx,ky,kz+1)*(1-x-y+x*y) + x*(1-y)*d->v(kx+1,ky,kz+1) + y*(1-x)*d->v(kx,ky+1,kz+1) + x*y*d->v(kx+1,ky+1,kz+1);
+		}
+		else
+		{
+			z=0;
+			if(ky>=0)
+			{
+				a0 = d->v(kx,ky);	a1 = d->v(kx+1,ky);	a2 = d->v(kx,ky+1);
+				b0 = b1 = a0*(1-x-y+x*y) + x*(1-y)*a1 + y*(1-x)*a2 + x*y*d->v(kx+1,ky+1);
+			}
+			else if(kx>=0)
+			{
+				a2=a0 = d->v(kx);	a1 = d->v(kx+1);	b0 = b1 = a0*(1-x) + x*a1;
+			}
+			else	b0 = b1 = d->v(0);
+		}
+		if(dx)	*dx = a1-a0;
+		if(dy)	*dy = a2-a0;
+		if(dz)	*dz = b1-b0;
+	}
+	return b0 + z*(b1-b0);
+}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_data_linear(HCDT d, mreal x,mreal y,mreal z)
+{	return mgl_data_linear_ext(d, x,y,z, 0,0,0);	}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_data_spline(HCDT d, mreal x,mreal y,mreal z)
+{
+	if(mgl_isbad(x) || mgl_isbad(y) || mgl_isbad(z))	return NAN;
+	return d->value(x,y,z);
+}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_data_spline_ext(HCDT d, mreal x,mreal y,mreal z, mreal *dx,mreal *dy,mreal *dz)
+{
+	if(mgl_isbad(x) || mgl_isbad(y) || mgl_isbad(z))	return NAN;
+	return d->valueD(x,y,z,dx,dy,dz);
+}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_data_spline_(uintptr_t *d, mreal *x,mreal *y,mreal *z)
+{	return mgl_data_spline(_DA_(d),*x,*y,*z);	}
+mreal MGL_EXPORT mgl_data_linear_(uintptr_t *d, mreal *x,mreal *y,mreal *z)
+{	return mgl_data_linear(_DA_(d),*x,*y,*z);	}
+mreal MGL_EXPORT mgl_data_spline_ext_(uintptr_t *d, mreal *x,mreal *y,mreal *z, mreal *dx,mreal *dy,mreal *dz)
+{	return mgl_data_spline_ext(_DA_(d),*x,*y,*z,dx,dy,dz);	}
+mreal MGL_EXPORT mgl_data_linear_ext_(uintptr_t *d, mreal *x,mreal *y,mreal *z, mreal *dx,mreal *dy,mreal *dz)
+{	return mgl_data_linear_ext(_DA_(d),*x,*y,*z,dx,dy,dz);	}
+mreal MGL_EXPORT mgl_data_solve_1d_(uintptr_t *d, mreal *val, int *spl, int *i0)
+{	return mgl_data_solve_1d(_DA_(d),*val, *spl, *i0);	}
+uintptr_t MGL_EXPORT mgl_data_solve_(uintptr_t *d, mreal *val, const char *dir, uintptr_t *i0, int *norm,int)
+{	return uintptr_t(mgl_data_solve(_DA_(d),*val, *dir, _DA_(i0), *norm));	}
+//-----------------------------------------------------------------------------
+long MGL_NO_EXPORT int_pow(long x, long n)
+{
+	if(n==2)	return x*x;
+	if(n==1)	return x;
+	if(n==0)	return 1;
+	if(n<0)		return 0;
+	long t = int_pow(x,n/2);	t = t*t;
+	if(n%2==1)	t *= x;
+	return t;
+}
+long MGL_NO_EXPORT mgl_powers(long N, const char *how)
+{
+	bool k2 = mglchr(how,'2'), k3 = mglchr(how,'3'), k5 = mglchr(how,'5');
+	const double lN=log(N), l2=log(2), l3=log(3), l5=log(5);
+	if(k2 && k3 && k5)
+	{
+		double dm=lN;	long im=0, jm=0, km=0;
+		for(long i=0;i<=lN/l2;i++)	for(long j=0;j<=(lN-i*l2)/l3;j++)	for(long k=0;k<=(lN-i*l2-j*l3)/l5;k++)
+		{
+			double d = lN-i*l2-j*l3-k*l5;
+			if(d>0 && d<dm)	{	im=i;	jm=j;	km=k;	dm=d;	}
+		}
+		return int_pow(2,im)*int_pow(3,jm)*int_pow(5,km);
+	}
+	else if(k2 && !k3 && !k5)	return int_pow(2,lN/l2);
+	else if(k3 && !k2 && !k5)	return int_pow(3,lN/l3);
+	else if(k5 && !k3 && !k2)	return int_pow(5,lN/l5);
+	else if(k2 && k3 && !k5)
+	{
+		double dm=lN;	long im=0, jm=0;
+		for(long i=0;i<=lN/l2;i++)	for(long j=0;j<=(lN-i*l2)/l3;j++)
+		{
+			double d = lN-i*l2-j*l3;
+			if(d>0 && d<dm)	{	im=i;	jm=j;	dm=d;	}
+		}
+		return int_pow(2,im)*int_pow(3,jm);
+	}
+	else if(k2 && k5 && !k3)
+	{
+		double dm=lN;	long im=0, jm=0;
+		for(long i=0;i<=lN/l2;i++)	for(long j=0;j<=(lN-i*l2)/l5;j++)
+		{
+			double d = lN-i*l2-j*l5;
+			if(d>0 && d<dm)	{	im=i;	jm=j;	dm=d;	}
+		}
+		return int_pow(2,im)*int_pow(5,jm);
+	}
+	else if(k5 && k3 && !k2)
+	{
+		double dm=lN;	long im=0, jm=0;
+		for(long i=0;i<=lN/l5;i++)	for(long j=0;j<=(lN-i*l5)/l3;j++)
+		{
+			double d = lN-i*l5-j*l3;
+			if(d>0 && d<dm)	{	im=i;	jm=j;	dm=d;	}
+		}
+		return int_pow(5,im)*int_pow(3,jm);
+	}
+	return 0;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_crop_opt(HMDT d, const char *how)
+{
+	const char *h = "235";
+	if(mglchr(how,'2') || mglchr(how,'3') || mglchr(how,'5'))	h = how;
+	if(mglchr(how,'x'))	mgl_data_crop(d, 0, mgl_powers(d->nx, h), 'x');
+	if(mglchr(how,'y'))	mgl_data_crop(d, 0, mgl_powers(d->ny, h), 'y');
+	if(mglchr(how,'z'))	mgl_data_crop(d, 0, mgl_powers(d->nz, h), 'z');
+}
+void MGL_EXPORT mgl_data_crop_opt_(uintptr_t *d, const char *how, int l)
+{	char *s=new char[l+1];	memcpy(s,how,l);	s[l]=0;
+	mgl_data_crop_opt(_DT_,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_crop(HMDT d, long n1, long n2, char dir)
+{
+	long nx=d->nx,ny=d->ny,nz=d->nz, nn;
+	mreal *b;
+	if(n1<0)	n1=0;
+	switch(dir)
+	{
+	case 'x':
+		if(n1>=nx)	break;
+		n2 = n2>0 ? n2 : nx+n2;
+		if(n2<0 || n2>=nx || n2<n1)	n2 = nx;
+		nn = n2-n1;	b = new mreal[nn*ny*nz];
+#pragma omp parallel for
+		for(long i=0;i<ny*nz;i++)
+			memcpy(b+nn*i,d->a+nx*i+n1,nn*sizeof(mreal));
+		d->nx = nn;	if(!d->link)	delete []d->a;
+		d->a = b;	d->link=false;	d->NewId();
+		break;
+	case 'y':
+		if(n1>=ny)	break;
+		n2 = n2>0 ? n2 : ny+n2;
+		if(n2<0 || n2>=ny || n2<n1)	n2 = ny;
+		nn = n2-n1;	b = new mreal[nn*nx*nz];
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	for(long j=0;j<nz;j++)
+			memcpy(b+nx*(i+nn*j),d->a+nx*(n1+i+ny*j),nx*sizeof(mreal));
+		d->ny = nn;	if(!d->link)	delete []d->a;
+		d->a = b;	d->link=false;
+		break;
+	case 'z':
+		if(n1>=nz)	break;
+		n2 = n2>0 ? n2 : nz+n2;
+		if(n2<0 || n2>=nz || n2<n1)	n2 = nz;
+		nn = n2-n1;	b = new mreal[nn*nx*ny];
+		memcpy(b,d->a+nx*ny*n1,nn*nx*ny*sizeof(mreal));
+		d->nz = nn;	if(!d->link)	delete []d->a;
+		d->a = b;	d->link=false;
+		break;
+	}
+}
+void MGL_EXPORT mgl_data_crop_(uintptr_t *d, int *n1, int *n2, const char *dir,int)
+{	mgl_data_crop(_DT_,*n1,*n2,*dir);	}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_data_last(HCDT d, const char *cond, long *i, long *j, long *k)
+{
+	long nx=d->GetNx(),ny=d->GetNy(),nz=d->GetNz();
+	if(!cond)	cond = "u";
+	mglFormula eq(cond);
+	if(*i<0 || *i>=nx)	*i=nx;
+	if(*j<0 || *j>=ny)	*j=ny-1;
+	if(*k<0 || *k>=nz)	*k=nz-1;
+	long i0 = *i+nx*(*j+ny*(*k))-1;
+	mreal x,y,z,dx=nx>1?1/(nx-1.):0,dy=ny>1?1/(ny-1.):0,dz=nz>1?1/(nz-1.):0;
+	for(;i0>=0;i0--)
+	{
+		x = dx*(i0%nx);		y = dy*((i0/nx)%ny);	z = dz*(i0/(nx*ny));
+		if(eq.Calc(x,y,z,d->vthr(i0)))	break;
+	}
+	*i = i0%nx;	*j = (i0/nx)%ny;	*k = i0/(nx*ny);
+	return i0>=0 ? d->vthr(i0) : NAN;	// NOTE: Return NAN if false
+}
+mreal MGL_EXPORT mgl_data_last_(uintptr_t *d, const char *cond, int *i, int *j, int *k, int l)
+{	long ii=*i,jj=*j,kk=*k;	char *s=new char[l+1];	memcpy(s,cond,l);	s[l]=0;
+	mreal res = mgl_data_last(_DT_,s,&ii,&jj,&kk);	*i=ii;	*j=jj;	*k=kk;
+	delete []s;		return res;	}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_data_first(HCDT d, const char *cond, long *i, long *j, long *k)
+{
+	long nx=d->GetNx(),ny=d->GetNy(),nz=d->GetNz();
+	if(!cond)	cond = "u";
+	mglFormula eq(cond);
+	if(*i<0 || *i>=nx)	*i=nx;
+	if(*j<0 || *j>=ny)	*j=ny-1;
+	if(*k<0 || *k>=nz)	*k=nz-1;
+	long i0 = *i+nx*(*j+ny*(*k))-1;
+	mreal x,y,z,dx=nx>1?1/(nx-1.):0,dy=ny>1?1/(ny-1.):0,dz=nz>1?1/(nz-1.):0;
+	for(;i0<nx*ny*nz;i0--)
+	{
+		x = dx*(i0%nx);		y = dy*((i0/nx)%ny);	z = dz*(i0/(nx*ny));
+		if(eq.Calc(x,y,z,d->vthr(i0)))	break;
+	}
+	*i = i0%nx;	*j = (i0/nx)%ny;	*k = i0/(nx*ny);
+	return i0<nx*ny*nz ? d->vthr(i0) : NAN;	// NOTE: Return NAN if false
+}
+mreal MGL_EXPORT mgl_data_first_(uintptr_t *d, const char *cond, int *i, int *j, int *k, int l)
+{	long ii=*i,jj=*j,kk=*k;	char *s=new char[l+1];	memcpy(s,cond,l);	s[l]=0;
+	mreal res = mgl_data_first(_DT_,s,&ii,&jj,&kk);	*i=ii;	*j=jj;	*k=kk;
+	delete []s;		return res;	}
+//-----------------------------------------------------------------------------
+long MGL_EXPORT mgl_data_find(HCDT d, const char *cond, char dir, long i, long j, long k)
+{
+	long nx=d->GetNx(),ny=d->GetNy(),nz=d->GetNz();
+	long m=-1;
+	if(!cond)	cond = "u";
+	mglFormula eq(cond);
+	mreal x=i/(nx-1.),y=j/(ny-1.),z=k/(nz-1.);
+	if(dir=='x' && nx>1)	for(m=i;m<nx;m++)
+		if(eq.Calc(m/(nx-1.),y,z,d->v(m,j,k)))	break;
+	if(dir=='y' && ny>1)	for(m=j;m<ny;m++)
+		if(eq.Calc(x,m/(ny-1.),z,d->v(i,m,k)))	break;
+	if(dir=='z' && nz>1)	for(m=k;m<nz;m++)
+		if(eq.Calc(x,y,m/(nz-1.),d->v(i,j,m)))	break;
+	return m;
+}
+int MGL_EXPORT mgl_data_find_(uintptr_t *d, const char *cond, char *dir, int *i, int *j, int *k, int l, int)
+{	char *s=new char[l+1];	memcpy(s,cond,l);	s[l]=0;
+	int res = mgl_data_find(_DT_,s,*dir,*i,*j,*k);	delete []s;	return res;	}
+//-----------------------------------------------------------------------------
+int MGL_EXPORT mgl_data_find_any(HCDT d, const char *cond)
+{
+	long nx=d->GetNx(),ny=d->GetNy(),nz=d->GetNz();
+	bool cc = false;
+	if(!cond || *cond==0)	cond = "u";
+	mglFormula eq(cond);
+#pragma omp parallel for collapse(3)
+	for(long k=0;k<nz;k++)	for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+	{
+		if(cc)	continue;
+		if(eq.Calc(i/(nx-1.),j/(ny-1.),k/(nz-1.),d->v(i,j,k)))	cc = true;
+	}
+	return cc;
+}
+int MGL_EXPORT mgl_data_find_any_(uintptr_t *d, const char *cond, int l)
+{	char *s=new char[l+1];	memcpy(s,cond,l);	s[l]=0;
+	int res = mgl_data_find_any(_DT_,s);	delete []s;	return res;	}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_data_momentum_val(HCDT dd, char dir, mreal *x, mreal *w, mreal *s, mreal *k)
+{
+	long nx=dd->GetNx(),ny=dd->GetNy(),nz=dd->GetNz();
+	mreal i0=0,i1=0,i2=0,i3=0,i4=0;
+	switch(dir)
+	{
+	case 'x':
+#pragma omp parallel for reduction(+:i0,i1,i2,i3,i4)
+		for(long i=0;i<nx*ny*nz;i++)
+		{
+			mreal d = i%nx, t = d*d, v = dd->vthr(i);
+			i0+= v;	i1+= v*d;	i2+= v*t;
+			i3+= v*d*t;		i4+= v*t*t;
+		}
+		break;
+	case 'y':
+#pragma omp parallel for reduction(+:i0,i1,i2,i3,i4)
+		for(long i=0;i<nx*ny*nz;i++)
+		{
+			mreal d = (i/nx)%ny, t = d*d, v = dd->vthr(i);
+			i0+= v;	i1+= v*d;	i2+= v*t;
+			i3+= v*d*t;		i4+= v*t*t;
+		}
+		break;
+	case 'z':
+#pragma omp parallel for reduction(+:i0,i1,i2,i3,i4)
+		for(long i=0;i<nx*ny*nz;i++)
+		{
+			mreal d = i/(nx*ny), t = d*d, v = dd->vthr(i);
+			i0+= v;	i1+= v*d;	i2+= v*t;
+			i3+= v*d*t;		i4+= v*t*t;
+		}
+		break;
+	default:	// "self-dispersion"
+		i0 = nx*ny*nz;
+#pragma omp parallel for reduction(+:i1,i2,i3,i4)
+		for(long i=0;i<nx*ny*nz;i++)
+		{
+			mreal v = dd->vthr(i), t = v*v;
+			i1+= v;			i2+= t;
+			i3+= v*t;		i4+= t*t;
+		}
+	}
+	if(i0==0)	return 0;
+	mreal d=i1/i0;
+	if(x)	*x=d;
+	if(w)	*w=i2>d*d*i0 ? sqrt(i2/i0-d*d) : 0;
+	if(s)	*s=i3/i0;
+	if(k)	*k=i4/(i0*3);
+	return i0;
+}
+mreal MGL_EXPORT mgl_data_momentum_val_(uintptr_t *d, char *dir, mreal *m, mreal *w, mreal *s, mreal *k,int)
+{	mreal mm=0,ww=0,ss=0,kk=0,aa=0;
+	aa = mgl_data_momentum_val(_DT_,*dir,&mm,&ww,&ss,&kk);
+	*m=mm;	*w=ww;	*s=ss;	*k=kk;	return aa;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_norm_slice(HMDT d, mreal v1,mreal v2,char dir,long keep_en,long sym)
+{
+	long nx=d->nx, ny=d->ny, nz=d->nz;
+	mreal *a=d->a;
+	mglData b(*d);
+	mreal e0=1, e, m1, m2, aa;
+	if(sym)	{	v2 = -v1>v2 ? -v1:v2;	v1 = -v2;	}
+	if(dir=='z' && nz>1)
+	{
+//#pragma omp parallel for private(m1,m2,aa,e,e0)	// TODO add omp comparison here
+		for(long k=0;k<nz;k++)
+		{
+			m1 = INFINITY;	m2 = -INFINITY;	e=0;
+			for(long i=0;i<nx*ny;i++)
+			{
+				aa = a[i+nx*ny*k];
+				m1 = m1<aa ? m1 : aa;
+				m2 = m2>aa ? m2 : aa;
+				e += aa*aa;
+			}
+			if(m1==m2)	m2+=1;
+			if(sym)	{	m2 = -m1>m2 ? -m1:m2;	m1 = -m2;	}
+			if(keep_en && k)	e = e0>0?sqrt(e/e0):1;
+			else	{	e0 = e;	e=1;	}
+			for(long i=0;i<nx*ny;i++)
+				b.a[i+nx*ny*k] = (v1 + (v2-v1)*(a[i+nx*ny*k]-m1)/(m2-m1))*e;
+		}
+	}
+	else if(dir=='y' && ny>1)
+	{
+//#pragma omp parallel for private(m1,m2,aa,e,e0)	// TODO add omp comparison here
+		for(long j=0;j<ny;j++)
+		{
+			m1 = INFINITY;	m2 = -INFINITY;	e=0;
+			for(long k=0;k<nz;k++)	for(long i=0;i<nx;i++)
+			{
+				aa = a[i+nx*(j+ny*k)];
+				m1 = m1<aa ? m1 : aa;
+				m2 = m2>aa ? m2 : aa;
+				e += aa*aa;
+			}
+			if(m1==m2)	m2+=1;
+			if(sym)	{	m2 = -m1>m2 ? -m1:m2;	m1 = -m2;	}
+			if(keep_en && j)	e = e0>0?sqrt(e/e0):1;
+			else	{	e0 = e;	e=1;	}
+#pragma omp parallel for collapse(2)
+			for(long k=0;k<nz;k++)	for(long i=0;i<nx;i++)
+				b.a[i+nx*(j+ny*k)] = (v1 + (v2-v1)*(a[i+nx*(j+ny*k)]-m1)/(m2-m1))*e;
+		}
+	}
+	else if(dir=='x' && nx>1)
+	{
+//#pragma omp parallel for private(m1,m2,aa,e,e0)	// TODO add omp comparison here
+		for(long i=0;i<nx;i++)
+		{
+			m1 = INFINITY;	m2 = -INFINITY;	e=0;
+			for(long k=0;k<ny*nz;k++)
+			{
+				aa = a[i+nx*k];
+				m1 = m1<aa ? m1 : aa;
+				m2 = m2>aa ? m2 : aa;
+				e += aa*aa;
+			}
+			if(m1==m2)	m2+=1;
+			if(sym)	{	m2 = -m1>m2 ? -m1:m2;	m1 = -m2;	}
+			if(keep_en && i)	e = e0>0?sqrt(e/e0):1;
+			else	{	e0 = e;	e=1;	}
+#pragma omp parallel for
+			for(long k=0;k<ny*nz;k++)
+				b.a[i+nx*k] = (v1 + (v2-v1)*(a[i+nx*k]-m1)/(m2-m1))*e;
+		}
+	}
+	memcpy(d->a, b.a, nx*ny*nz*sizeof(mreal));
+}
+void MGL_EXPORT mgl_data_norm_slice_(uintptr_t *d, mreal *v1,mreal *v2,char *dir,int *keep_en,int *sym,int )
+{	mgl_data_norm_slice(_DT_,*v1,*v2,*dir,*keep_en,*sym);	}
+//-----------------------------------------------------------------------------
+MGL_EXPORT const char *mgl_data_info(HCDT d)	// NOTE: Not thread safe function!
+{
+	static char buf[512];
+	char s[128];	buf[0]=0;
+	snprintf(s,128,"nx = %ld\tny = %ld\tnz = %ld\n",d->GetNx(),d->GetNy(),d->GetNz());
+	s[127]=0;	strcat(buf,s);
+
+	long i=0,j=0,k=0;
+	mreal A=0,Wa=0,X=0,Y=0,Z=0,Wx=0,Wy=0,Wz=0, b;
+	b = mgl_data_max_int(d,&i,&j,&k);
+	snprintf(s,128,_("Maximum is %g\t at x = %ld\ty = %ld\tz = %ld\n"), b,i,j,k);
+	s[127]=0;	strcat(buf,s);
+	b = mgl_data_min_int(d,&i,&j,&k);
+	snprintf(s,128,_("Minimum is %g\t at x = %ld\ty = %ld\tz = %ld\n"), b,i,j,k);
+	s[127]=0;	strcat(buf,s);
+
+	mgl_data_momentum_val(d,'a',&A,&Wa,0,0);	mgl_data_momentum_val(d,'x',&X,&Wx,0,0);
+	mgl_data_momentum_val(d,'y',&Y,&Wy,0,0);	mgl_data_momentum_val(d,'z',&Z,&Wz,0,0);
+	snprintf(s,128,_("Averages are:\n<a> = %g\t<x> = %g\t<y> = %g\t<z> = %g\n"), A,X,Y,Z);
+	s[127]=0;	strcat(buf,s);
+	snprintf(s,128,_("Widths are:\nWa = %g\tWx = %g\tWy = %g\tWz = %g\n"), Wa,Wx,Wy,Wz);
+	s[127]=0;	strcat(buf,s);
+	return buf;
+}
+int MGL_EXPORT mgl_data_info_(uintptr_t *d, char *out, int len)
+{
+	const char *res = mgl_data_info(_DA_(d));
+	if(out)	strncpy(out,res,len);
+	return strlen(res);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_insert(HMDT d, char dir, long at, long num)
+{
+	if(num<1)	return;
+	at = at<0 ? 0:at;
+	long nn, nx=d->nx, ny=d->ny, nz=d->nz, nxy=nx*ny;
+	mglData b;
+	if(dir=='x')
+	{
+		if(at>nx)	at=nx;
+		nn=nx+num;	b.Create(nn,ny,nz);
+#pragma omp parallel for
+		for(long k=0;k<ny*nz;k++)
+		{
+			if(at>0)	memcpy(b.a+nn*k, d->a+nx*k,at*sizeof(mreal));
+			if(at<nx)	memcpy(b.a+at+num+nn*k, d->a+at+nx*k,(nx-at)*sizeof(mreal));
+			if(at<nx)	for(long i=0;i<num;i++)	b.a[nn*k+at+i]=d->a[nx*k+at];	// copy values
+			else		for(long i=0;i<num;i++)	b.a[nn*k+at+i]=d->a[nx*k+nx-1];	// copy values
+		}
+		d->Set(b);	nx+=num;
+	}
+	if(dir=='y')
+	{
+		if(at>ny)	at=ny;
+		nn=num+ny;	b.Create(nx,nn,nz);
+#pragma omp parallel for
+		for(long k=0;k<nz;k++)
+		{
+			if(at>0)	memcpy(b.a+nx*nn*k, d->a+nxy*k,at*nx*sizeof(mreal));
+			if(at<ny)	memcpy(b.a+nx*(at+num+nn*k), d->a+nx*(at+ny*k),(ny-at)*nx*sizeof(mreal));
+			if(at<ny)	for(long i=0;i<num;i++)
+				memcpy(b.a+nx*(nn*k+at+i),d->a+nx*(ny*k+at),nx*sizeof(mreal));
+			else	for(long i=0;i<num;i++)
+				memcpy(b.a+nx*(nn*k+at+i),d->a+nx*(ny*k+ny-1),nx*sizeof(mreal));
+		}
+		d->Set(b);	ny+=num;
+	}
+	if(dir=='z')
+	{
+		if(at>nz)	at=nz;
+		b.Create(nx,ny,nz+num);
+		if(at>0)	memcpy(b.a, d->a,at*nxy*sizeof(mreal));
+		if(at<nz)	memcpy(b.a+nxy*(at+num), d->a+nxy*at,(nz-at)*nxy*sizeof(mreal));
+		if(at<nz)
+#pragma omp parallel for
+			for(long i=0;i<num;i++)	memcpy(b.a+nxy*(at+i),d->a+nxy*at,nxy*sizeof(mreal));
+		else
+#pragma omp parallel for
+			for(long i=0;i<num;i++)	memcpy(b.a+nxy*(at+i),d->a+nxy*(nz-1),nxy*sizeof(mreal));
+		d->Set(b);
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_delete(HMDT d, char dir, long at, long num)
+{
+	if(num<1 || at<0)	return;
+	mglData b;
+	long nx=d->nx, ny=d->ny, nz=d->nz, nn;
+	if(dir=='x')
+	{
+		if(at+num>=nx)	return;
+		nn=nx-num;	b.Create(nn,ny,nz);
+#pragma omp parallel for
+		for(long k=0;k<ny*nz;k++)
+		{
+			if(at>0)	memcpy(b.a+nn*k, d->a+nx*k,at*sizeof(mreal));
+			memcpy(b.a+at+nn*k, d->a+at+num+nx*k,(nx-at-num)*sizeof(mreal));
+		}
+		d->Set(b);	nx-=num;
+	}
+	if(dir=='y')
+	{
+		if(at+num>=ny)	return;
+		nn=ny-num;	b.Create(nx,nn,nz);
+#pragma omp parallel for
+		for(long k=0;k<nz;k++)
+		{
+			if(at>0)	memcpy(b.a+nx*nn*k, d->a+nx*ny*k,at*nx*sizeof(mreal));
+			memcpy(b.a+nx*(at+nn*k), d->a+nx*(at+num+ny*k),(ny-at-num)*nx*sizeof(mreal));
+		}
+		d->Set(b);	ny-=num;
+	}
+	if(dir=='z')
+	{
+		if(at+num>=nz)	return;
+		b.Create(nx,ny,nz-num);
+		if(at>0)	memcpy(b.a, d->a,at*nx*ny*sizeof(mreal));
+		memcpy(b.a+nx*ny*at, d->a+nx*ny*(at+num),(nz-at-num)*nx*ny*sizeof(mreal));
+		d->Set(b);
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_insert_(uintptr_t *d, const char *dir, int *at, int *num, int)
+{	mgl_data_insert(_DT_,*dir,*at,*num);	}
+void MGL_EXPORT mgl_data_delete_(uintptr_t *d, const char *dir, int *at, int *num, int)
+{	mgl_data_delete(_DT_,*dir,*at,*num);	}
+//-----------------------------------------------------------------------------
+#define omod(x,y)	(y)*((x)>0?int((x)/(y)+0.5):int((x)/(y)-0.5))
+void MGL_NO_EXPORT mgl_omod(mreal *a, mreal da, int nx, int n)
+{
+	bool qq=true;
+	for(long i=1;i<nx;i++)
+	{
+		long ii = i*n;
+		if(mgl_isnan(a[ii-n]))	{	qq=true;	continue;	}
+		if(qq)
+		{
+			a[ii] += omod(a[ii-n]-a[ii], da);
+			qq=false;
+		}
+		else
+		{
+			mreal q = 2*a[ii-n]-a[ii-2*n];
+			a[ii] += omod(q-a[ii], da);
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_sew_z(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nz=t->p[2], nn=t->n;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)	mgl_omod(t->a+i, t->b[0], nz, nn);
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_sew_y(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0], ny=t->p[1], nn=t->n;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)	mgl_omod(t->a+(i%nx)+nx*ny*(i/nx), t->b[0], ny, nx);
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_sew_x(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0], nn=t->n;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)	mgl_omod(t->a+i*nx, t->b[0], nx, 1);
+	return 0;
+}
+void MGL_EXPORT mgl_data_sew(HMDT d, const char *dirs, mreal delta)
+{
+	if(!dirs || *dirs==0)	return;
+	long nx=d->nx, ny=d->ny, nz=d->nz;
+	long p[3]={nx,ny,nz};
+	mreal da = delta;
+	if(strchr(dirs,'x') && nx>1)	mglStartThread(mgl_sew_x,0,nz*ny,d->a,&da,0,p);
+	if(strchr(dirs,'y') && ny>1)	mglStartThread(mgl_sew_y,0,nz*nx,d->a,&da,0,p);
+	if(strchr(dirs,'z') && nz>1)	mglStartThread(mgl_sew_z,0,nx*ny,d->a,&da,0,p);
+}
+void MGL_EXPORT mgl_data_sew_(uintptr_t *d, const char *dirs, mreal *da, int l)
+{	char *s=new char[l+1];	memcpy(s,dirs,l);	s[l]=0;
+	mgl_data_sew(_DT_,s,*da);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_put_val(HMDT d, mreal val, long xx, long yy, long zz)
+{
+	long nx=d->nx, ny=d->ny, nz=d->nz;
+	if(xx>=nx || yy>=ny || zz>=nz)	return;
+	mreal *a=d->a;
+	if(xx>=0 && yy>=0 && zz>=0)	a[xx+nx*(yy+zz*ny)] = val;
+	else if(xx<0 && yy<0 && zz<0)
+#pragma omp parallel for
+		for(long i=0;i<nx*ny*nz;i++)	a[i] = val;
+	else if(xx<0 && yy<0)
+#pragma omp parallel for
+		for(long i=0;i<nx*ny;i++)	a[i+zz*nx*ny] = val;
+	else if(yy<0 && zz<0)
+#pragma omp parallel for
+		for(long i=0;i<nz*ny;i++)	a[xx+i*nx] = val;
+	else if(xx<0 && zz<0)
+#pragma omp parallel for collapse(2)
+		for(long i=0;i<nx;i++)	for(long j=0;j<nz;j++)	a[i+nx*(yy+j*ny)] = val;
+	else if(xx<0)
+#pragma omp parallel for
+		for(long i=0;i<nx;i++)	a[i+nx*(yy+zz*ny)] = val;
+	else if(yy<0)
+#pragma omp parallel for
+		for(long i=0;i<ny;i++)	a[xx+nx*(i+zz*ny)] = val;
+	else //if(zz<0)
+#pragma omp parallel for
+		for(long i=0;i<nz;i++)	a[xx+nx*(yy+i*ny)] = val;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_put_dat(HMDT d, HCDT v, long xx, long yy, long zz)
+{
+	long nx=d->nx, ny=d->ny, nz=d->nz;
+	if(xx>=nx || yy>=ny || zz>=nz)	return;
+	const mglData *mv = dynamic_cast<const mglData *>(v);
+	mreal *a=d->a, vv=v->v(0);
+	const mreal *b = mv?mv->a:0;
+	long vx=v->GetNx(), vy=v->GetNy(), vz=v->GetNz();
+	if(xx<0 && yy<0 && zz<0)	// whole array
+	{
+		if(vx>=nx && vy>=ny && vz>=nz)
+#pragma omp parallel for
+			for(long ii=0;ii<nx*ny*nz;ii++)
+			{	long i=ii%nx, j=(ii/nx)%ny, k=ii/(nx*ny);
+				a[ii] = b?b[i+vx*(j+k*vy)]:v->v(i,j,k);	}
+		else if(vx>=nx && vy>=ny)
+#pragma omp parallel for
+			for(long ii=0;ii<nx*ny*nz;ii++)
+			{	long i=ii%nx, j=(ii/nx)%ny;
+				a[ii] = b?b[i+vx*j]:v->v(i,j);	}
+		else if(vx>=nx)
+#pragma omp parallel for
+			for(long ii=0;ii<nx*ny*nz;ii++)
+			{	long i=ii%nx;	a[ii] = b?b[i]:v->v(i);	}
+		else
+#pragma omp parallel for
+			for(long ii=0;ii<nx*ny*nz;ii++)	a[ii] = vv;
+	}
+	else if(xx<0 && yy<0)	// 2d
+	{
+		zz*=nx*ny;
+		if(vx>=nx && vy>=ny)
+#pragma omp parallel for
+			for(long ii=0;ii<nx*ny;ii++)
+			{	long i=ii%nx, j=ii/nx;
+				a[ii+zz] = b?b[i+vx*j]:v->v(i,j);	}
+		else if(vx>=nx)
+#pragma omp parallel for
+			for(long ii=0;ii<nx*ny;ii++)
+			{	long i=ii%nx;	a[ii+zz] = b?b[i]:v->v(i);	}
+		else
+#pragma omp parallel for
+			for(long ii=0;ii<nx*ny;ii++) 	a[ii+zz] = vv;
+	}
+	else if(yy<0 && zz<0)	// 2d
+	{
+		if(vx>=ny && vy>=nz)
+#pragma omp parallel for
+			for(long ii=0;ii<ny*nz;ii++)
+			{	long i=ii%ny, j=ii/ny;
+				a[ii*nx+xx] = b?b[i+vx*j]:v->v(i,j);	}
+		else if(vx>=ny)
+#pragma omp parallel for
+			for(long ii=0;ii<ny*nz;ii++)
+			{	long i=ii%ny;	a[ii*nx+xx] = b?b[i]:v->v(i);	}
+		else
+#pragma omp parallel for
+			for(long ii=0;ii<ny*nz;ii++) 	a[ii*nx+xx] = vv;
+	}
+	else if(xx<0 && zz<0)	// 2d
+	{
+		yy *= nx;	zz = nx*ny;
+		if(vx>=nx && vy>=nz)
+#pragma omp parallel for
+			for(long ii=0;ii<nx*nz;ii++)
+			{	long i=ii%nx, j=ii/nx;
+				a[i+yy+j*zz] = b?b[i+vx*j]:v->v(i,j);	}
+		else if(vx>=nx)
+#pragma omp parallel for
+			for(long ii=0;ii<nx*nz;ii++)
+			{	long i=ii%nx, j=ii/nx;
+				a[i+yy+j*zz] = b?b[i]:v->v(i);	}
+		else
+#pragma omp parallel for
+			for(long ii=0;ii<nx*nz;ii++)
+			{	long i=ii%nx, j=ii/nx;
+				a[i+yy+j*zz] = vv;	}
+	}
+	else if(xx<0)
+	{
+		xx = nx*(yy+zz*ny);
+		if(vx>=nx)
+#pragma omp parallel for
+			for(long i=0;i<nx;i++)	a[i+xx] = b?b[i]:v->v(i);
+		else
+#pragma omp parallel for
+			for(long i=0;i<nx;i++)	a[i+xx] = vv;
+	}
+	else if(yy<0)
+	{
+		xx += zz*nx*ny;
+		if(vx>=ny)
+#pragma omp parallel for
+			for(long i=0;i<ny;i++)	a[xx+nx*i] = b?b[i]:v->v(i);
+		else
+#pragma omp parallel for
+			for(long i=0;i<ny;i++)	a[xx+nx*i] = vv;
+	}
+	else if(zz<0)
+	{
+		xx += nx*yy;	yy = nx*ny;
+		if(vx>=nz)
+#pragma omp parallel for
+			for(long i=0;i<nz;i++)	a[xx+yy*i] = b?b[i]:v->v(i);
+		else
+#pragma omp parallel for
+			for(long i=0;i<nz;i++)	a[xx+yy*i] = vv;
+	}
+	else	a[xx+nx*(yy+ny*zz)] = vv;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_put_val_(uintptr_t *d, mreal *val, int *i, int *j, int *k)
+{	mgl_data_put_val(_DT_,*val, *i,*j,*k);	}
+void MGL_EXPORT mgl_data_put_dat_(uintptr_t *d, uintptr_t *val, int *i, int *j, int *k)
+{	mgl_data_put_dat(_DT_,_DA_(val), *i,*j,*k);	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_diff_3(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0], ny=t->p[1], nz=t->p[2], nn=t->n, n2=nx*ny;
+	mreal *b=t->a,au,av,aw,xu,xv,xw,yu,yv,yw,zu,zv,zw;
+	HCDT x=(HCDT)(t->c),y=(HCDT)(t->d),z=(HCDT)(t->e);
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for private(au,av,aw,xu,xv,xw,yu,yv,yw,zu,zv,zw)
+#endif
+	for(long i0=t->id;i0<nn;i0+=mglNumThr)
+	{
+		long i=i0%nx, j=((i0/nx)%ny), k=i0/(nx*ny);
+		if(i==0)
+		{
+			au = 3*a[i0]-4*a[i0+1]+a[i0+2];
+			xu = 3*x->vthr(i0)-4*x->vthr(i0+1)+x->vthr(i0+2);
+			yu = 3*y->vthr(i0)-4*y->vthr(i0+1)+y->vthr(i0+2);
+			zu = 3*z->vthr(i0)-4*z->vthr(i0+1)+z->vthr(i0+2);
+		}
+		else if(i==nx-1)
+		{
+			au = 3*a[i0]-4*a[i0-1]+a[i0-2];
+			xu = 3*x->vthr(i0)-4*x->vthr(i0-1)+x->vthr(i0-2);
+			yu = 3*y->vthr(i0)-4*y->vthr(i0-1)+y->vthr(i0-2);
+			zu = 3*z->vthr(i0)-4*z->vthr(i0-1)+z->vthr(i0-2);
+		}
+		else
+		{
+			au = a[i0+1]-a[i0-1];
+			xu = x->vthr(i0+1)-x->vthr(i0-1);
+			yu = y->vthr(i0+1)-y->vthr(i0-1);
+			zu = z->vthr(i0+1)-z->vthr(i0-1);
+		}
+		if(j==0)
+		{
+			av = 3*a[i0]-4*a[i0+nx]+a[i0+2*nx];
+			xv = 3*x->vthr(i0)-4*x->vthr(i0+nx)+x->vthr(i0+2*nx);
+			yv = 3*y->vthr(i0)-4*y->vthr(i0+nx)+y->vthr(i0+2*nx);
+			zv = 3*z->vthr(i0)-4*z->vthr(i0+nx)+z->vthr(i0+2*nx);
+		}
+		else if(j==ny-1)
+		{
+			av = 3*a[i0]-4*a[i0-nx]+a[i0+(ny-3)*nx];
+			xv = 3*x->vthr(i0)-4*x->vthr(i0-nx)+x->vthr(i0-2*nx);
+			yv = 3*y->vthr(i0)-4*y->vthr(i0-nx)+y->vthr(i0-2*nx);
+			zv = 3*z->vthr(i0)-4*z->vthr(i0-nx)+z->vthr(i0-2*nx);
+		}
+		else
+		{
+			av = a[i0+nx]-a[i0-nx];
+			xv = x->vthr(i0+nx)-x->vthr(i0-nx);
+			yv = y->vthr(i0+nx)-y->vthr(i0-nx);
+			zv = z->vthr(i0+nx)-z->vthr(i0-nx);
+		}
+		if(k==0)
+		{
+			aw = 3*a[i0]-4*a[i0+n2]+a[i0+2*n2];
+			xw = 3*x->vthr(i0)-4*x->vthr(i0+n2)+x->vthr(i0+2*n2);
+			yw = 3*y->vthr(i0)-4*y->vthr(i0+n2)+y->vthr(i0+2*n2);
+			zw = 3*z->vthr(i0)-4*z->vthr(i0+n2)+z->vthr(i0+2*n2);
+		}
+		else if(k==nz-1)
+		{
+			aw = 3*a[i0]-4*a[i0-n2]+a[i0-2*n2];
+			xw = 3*x->vthr(i0)-4*x->vthr(i0-n2)+x->vthr(i0-2*n2);
+			yw = 3*y->vthr(i0)-4*y->vthr(i0-n2)+y->vthr(i0-2*n2);
+			zw = 3*z->vthr(i0)-4*z->vthr(i0-n2)+z->vthr(i0-2*n2);
+		}
+		else
+		{
+			aw = a[i0+n2]-a[i0-n2];
+			xw = x->vthr(i0+n2)-x->vthr(i0-n2);
+			yw = y->vthr(i0+n2)-y->vthr(i0-n2);
+			zw = z->vthr(i0+n2)-z->vthr(i0-n2);
+		}
+		b[i0] = (au*yv*zw-av*yu*zw-au*yw*zv+aw*yu*zv+av*yw*zu-aw*yv*zu) / (xu*yv*zw-xv*yu*zw-xu*yw*zv+xw*yu*zv+xv*yw*zu-xw*yv*zu);
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_diff_2(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0], ny=t->p[1], nn=t->n, same=t->p[2];
+	mreal *b=t->a,au,av,xu,xv,yu,yv;
+	HCDT x=(HCDT)(t->c),y=(HCDT)(t->d);
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for private(au,av,xu,xv,yu,yv)
+#endif
+	for(long i0=t->id;i0<nn;i0+=mglNumThr)
+	{
+		long i=i0%nx, j=((i0/nx)%ny), i1 = same ? i0 : i0%(nx*ny);
+		if(i==0)
+		{
+			au = 3*a[i0]-4*a[i0+1]+a[i0+2];
+			xu = 3*x->vthr(i1)-4*x->vthr(i1+1)+x->vthr(i1+2);
+			yu = 3*y->vthr(i1)-4*y->vthr(i1+1)+y->vthr(i1+2);
+		}
+		else if(i==nx-1)
+		{
+			au = 3*a[i0]-4*a[i0-1]+a[i0-2];
+			xu = 3*x->vthr(i1)-4*x->vthr(i1-1)+x->vthr(i1-2);
+			yu = 3*y->vthr(i1)-4*y->vthr(i1-1)+y->vthr(i1-2);
+		}
+		else
+		{
+			au = a[i0+1]-a[i0-1];
+			xu = x->vthr(i1+1)-x->vthr(i1-1);
+			yu = y->vthr(i1+1)-y->vthr(i1-1);
+		}
+		if(j==0)
+		{
+			av = 3*a[i0]-4*a[i0+nx]+a[i0+2*nx];
+			xv = 3*x->vthr(i1)-4*x->vthr(i1+nx)+x->vthr(i1+2*nx);
+			yv = 3*y->vthr(i1)-4*y->vthr(i1+nx)+y->vthr(i1+2*nx);
+		}
+		else if(j==ny-1)
+		{
+			av = 3*a[i0]-4*a[i0-nx]+a[i0-2*nx];
+			xv = 3*x->vthr(i1)-4*x->vthr(i1-nx)+x->vthr(i1-2*nx);
+			yv = 3*y->vthr(i1)-4*y->vthr(i1-nx)+y->vthr(i1-2*nx);
+		}
+		else
+		{
+			av = a[i0+nx]-a[i0-nx];
+			xv = x->vthr(i1+nx)-x->vthr(i1-nx);
+			yv = y->vthr(i1+nx)-y->vthr(i1-nx);
+		}
+		b[i0] = (av*yu-au*yv)/(xv*yu-xu*yv);
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_diff_1(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0], nn=t->n, same=t->p[1];
+	mreal *b=t->a,au,xu;
+	HCDT x=(HCDT)(t->c);
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for private(au,xu)
+#endif
+	for(long i0=t->id;i0<nn;i0+=mglNumThr)
+	{
+		long i=i0%nx, i1 = same ? i0 : i;
+		if(i==0)
+		{
+			au = 3*a[i0]-4*a[i0+1]+a[i0+2];
+			xu = 3*x->vthr(i1)-4*x->vthr(i1+1)+x->vthr(i1+2);
+		}
+		else if(i==nx-1)
+		{
+			au = 3*a[i0]-4*a[i0-1]+a[i0-2];
+			xu = 3*x->vthr(i1)-4*x->vthr(i1-1)+x->vthr(i1-2);
+		}
+		else
+		{
+			au = a[i0+1]-a[i0-1];
+			xu = x->vthr(i1+1)-x->vthr(i1-1);
+		}
+		b[i0] = au/xu;
+	}
+	return 0;
+}
+void MGL_EXPORT mgl_data_diff_par(HMDT d, HCDT x, HCDT y, HCDT z)
+{
+	long nx=d->GetNx(),ny=d->GetNy(),nz=d->GetNz(), nn=nx*ny*nz;
+	if(nx<2 || ny<2)	return;
+	mreal *b = new mreal[nn];	memset(b,0,nn*sizeof(mreal));
+	long p[3]={nx,ny,nz};
+
+	if(x&&y&&z && x->GetNN()==nn && y->GetNN()==nn && z->GetNN()==nn)
+		mglStartThread(mgl_diff_3,0,nn,b,d->a,(const mreal *)x,p,0,(const mreal *)y,(const mreal *)z);
+	else if(x&&y && x->GetNx()*x->GetNy()==nx*ny && y->GetNx()*y->GetNy()==nx*ny)
+	{
+		p[2]=(x->GetNz()==nz && y->GetNz()==nz);
+		mglStartThread(mgl_diff_2,0,nn,b,d->a,(const mreal *)x,p,0,(const mreal *)y);
+	}
+	else if(x && x->GetNx()==nx)
+	{
+		p[1]=(x->GetNy()*x->GetNz()==ny*nz);
+		mglStartThread(mgl_diff_1,0,nn,b,d->a,(const mreal *)x,p,0,0);
+	}
+	memcpy(d->a,b,nn*sizeof(mreal));	delete []b;
+}
+void MGL_EXPORT mgl_data_diff_par_(uintptr_t *d, uintptr_t *v1, uintptr_t *v2, uintptr_t *v3)
+{	mgl_data_diff_par(_DT_,_DA_(v1),_DA_(v2),_DA_(v3));	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_set_value(HMDT dat, mreal v, long i, long j, long k)
+{	if(i>=0 && i<dat->nx && j>=0 && j<dat->ny && k>=0 && k<dat->nz)	dat->a[i+dat->nx*(j+dat->ny*k)]=v;	}
+void MGL_EXPORT mgl_data_set_value_(uintptr_t *d, mreal *v, int *i, int *j, int *k)
+{	mgl_data_set_value(_DT_,*v,*i,*j,*k);	}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_data_get_value(HCDT dat, long i, long j, long k)
+{	long nx = dat->GetNx(), ny = dat->GetNy();
+	return (i>=0 && i<nx && j>=0 && j<ny && k>=0 && k<dat->GetNz()) ? dat->vthr(i+nx*(j+ny*k)):NAN;	}
+mreal MGL_EXPORT mgl_data_get_value_(uintptr_t *d, int *i, int *j, int *k)
+{	return mgl_data_get_value(_DA_(d),*i,*j,*k);	}
+//-----------------------------------------------------------------------------
+MGL_EXPORT mreal *mgl_data_data(HMDT dat)	{	return dat->a;	}
+//-----------------------------------------------------------------------------
+MGL_EXPORT mreal *mgl_data_value(HMDT dat, long i,long j,long k)
+{	long ii=i*dat->nx*(j+dat->ny*k);
+	return	ii>=0 && ii<dat->GetNN() ? dat->a+ii : 0;	}
+//-----------------------------------------------------------------------------
+long MGL_EXPORT mgl_data_get_nx(HCDT dat)	{	return dat->GetNx();	}
+long MGL_EXPORT mgl_data_get_ny(HCDT dat)	{	return dat->GetNy();	}
+long MGL_EXPORT mgl_data_get_nz(HCDT dat)	{	return dat->GetNz();	}
+long MGL_EXPORT mgl_data_get_nx_(uintptr_t *d)	{	return _DA_(d)->GetNx();	}
+long MGL_EXPORT mgl_data_get_ny_(uintptr_t *d)	{	return _DA_(d)->GetNy();	}
+long MGL_EXPORT mgl_data_get_nz_(uintptr_t *d)	{	return _DA_(d)->GetNz();	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_join(HMDT d, HCDT v)
+{
+	if(!d || !v)	return;
+	long nx=d->nx, ny=d->ny, nz=d->nz, k=nx*ny*nz;
+	const mglData *mv = dynamic_cast<const mglData *>(v);
+	long vx=v->GetNx(), vy=v->GetNy(), vz=v->GetNz(), m = vx*vy*vz;
+
+	if(nx==vx && ny==vy && ny>1)	d->nz += vz;
+	else
+	{
+		ny *= nz;	vy *= vz;
+		if(nx==vx && nx>1)
+		{	d->nz = 1;	d->ny = ny+vy;	}
+		else
+		{	d->ny = d->nz = 1;	d->nx = k+m;	}
+	}
+	mreal *b = new mreal[k+m];
+	memcpy(b,d->a,k*sizeof(mreal));
+	if(mv)	memcpy(b+k,mv->a,m*sizeof(mreal));
+	else
+#pragma omp parallel for
+		for(long i=0;i<m;i++)	b[k+i] = v->vthr(i);
+	if(!d->link)	delete []d->a;
+	d->a = b;	d->link=false;	d->NewId();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_join_(uintptr_t *d, uintptr_t *val)
+{	mgl_data_join(_DT_,_DA_(val));	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_refill_gs(HMDT dat, HCDT xdat, HCDT vdat, mreal x1, mreal x2, long sl)
+{
+	HMDT coef = mgl_gspline_init(xdat, vdat);
+	if(!coef)	return;	// incompatible dimensions
+	const long nx = dat->nx, nn=dat->ny*dat->nz;
+	mreal x0 = x1-xdat->v(0), dx = (x2-x1)/(nx-1);
+#pragma omp parallel for
+	for(long i=0;i<nx;i++)
+	{
+		mreal d = mgl_gspline(coef,x0+dx*i,0,0);
+		if(sl<0)	for(long j=0;j<nn;j++)	dat->a[i+j*nx] = d;
+		else	dat->a[i+sl*nx] = d;
+	}
+	mgl_delete_data(coef);
+}
+//-----------------------------------------------------------------------------
+mreal MGL_NO_EXPORT mgl_index_1(mreal v, HCDT dat)
+{
+	long mx=dat->GetNx();
+	mreal d,d1=0,d2=mx-1,v1,v2;
+	v1 = dat->value(d1,0,0);
+	v2 = dat->value(d2,0,0);
+	long count=0;
+
+	const mreal eps = MGL_EPSILON-1.;
+	if(fabs(v-v1)<eps)	return d1;
+	if(fabs(v-v2)<eps)	return d2;
+	if((v1-v)*(v2-v)>0)	return NAN;
+	do
+	{
+		d = count<10?(d2-d1)*(v-v1)/(v2-v1)+d1:(d1+d2)/2;	count++;
+		mreal val = dat->value(d,0,0);
+//		if(fabs(val-v)<acx)	break;
+		if(val==v || d2-d<eps)	break;
+		if((v1-v)*(val-v)<0)	{	v2=val;	d2=d;	}	else	{	v1=val;	d1=d;	}
+	} while(fabs(d2-d1)>1e-5);
+	return d;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_refill_x(HMDT dat, HCDT xdat, HCDT vdat, mreal x1, mreal x2, long sl)
+{
+	long nx=dat->nx,mx=vdat->GetNx(),nn=dat->ny*dat->nz;
+	if(mx!=xdat->GetNx())	return;	// incompatible dimensions
+	mreal dx = (x2-x1)/(nx-1);
+#pragma omp parallel for
+	for(long i=0;i<nx;i++)
+	{
+		mreal u = mgl_index_1(x1+dx*i,xdat);
+		mreal d = vdat->value(u,0,0);
+		if(sl<0)	for(long j=0;j<nn;j++)	dat->a[i+j*nx] = d;
+		else	dat->a[i+sl*nx] = d;
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_refill_xy(HMDT dat, HCDT xdat, HCDT ydat, HCDT vdat, mreal x1, mreal x2, mreal y1, mreal y2, long sl)
+{
+	long nx=dat->nx,ny=dat->ny,nz=dat->nz,mx=vdat->GetNx(),my=vdat->GetNy(),nn=nx*ny;
+	bool both=(xdat->GetNN()==vdat->GetNN() && ydat->GetNN()==vdat->GetNN());
+	if(!both && (xdat->GetNx()!=mx || ydat->GetNx()!=my))	return;	// incompatible dimensions
+	mreal dx = (x2-x1)/(nx-1), dy = (y2-y1)/(ny-1);
+	if(both)
+	{
+#pragma omp parallel for
+		for(long i=0;i<nn*nz;i++)	dat->a[i]=NAN;
+#pragma omp parallel for collapse(2)
+		for(long j=0;j<my-1;j++)	for(long i=0;i<mx-1;i++)
+		{
+			long i0 = i+mx*j;
+			mreal vx0 = (xdat->vthr(i0)-x1)/dx, vy0 = (ydat->vthr(i0)-y1)/dy;
+			mreal vx1 = (xdat->vthr(i0+1)-x1)/dx, vy1 = (ydat->vthr(i0+1)-y1)/dy;
+			mreal vx2 = (xdat->vthr(i0+mx)-x1)/dx, vy2 = (ydat->vthr(i0+mx)-y1)/dy;
+			mreal vx3 = (xdat->vthr(i0+mx+1)-x1)/dx, vy3 = (ydat->vthr(i0+mx+1)-y1)/dy;
+			long xx1 = long(mgl_min( mgl_min(vx0,vx1), mgl_min(vx2,vx3) ));	// bounding box
+			long yy1 = long(mgl_min( mgl_min(vy0,vy1), mgl_min(vy2,vy3) ));
+			long xx2 = long(mgl_max( mgl_max(vx0,vx1), mgl_max(vx2,vx3) ));
+			long yy2 = long(mgl_max( mgl_max(vy0,vy1), mgl_max(vy2,vy3) ));
+			xx1=mgl_max(xx1,0);	xx2=mgl_min(xx2,nx-1);
+			yy1=mgl_max(yy1,0);	yy2=mgl_min(yy2,ny-1);
+			if(xx1>xx2 || yy1>yy2)	continue;
+
+			mreal d1x = vx1-vx0, d1y = vy1-vy0;
+			mreal d2x = vx2-vx0, d2y = vy2-vy0;
+			mreal d3x = vx3+vx0-vx1-vx2, d3y = vy3+vy0-vy1-vy2;
+			mreal dd = d1x*d2y-d1y*d2x;
+			mreal dsx =-4*(d2y*d3x - d2x*d3y)*d1y;
+			mreal dsy = 4*(d2y*d3x - d2x*d3y)*d1x;
+
+			for(long jj=yy1;jj<=yy2;jj++)	for(long ii=xx1;ii<=xx2;ii++)
+			{
+				mreal xx = (ii-vx0), yy = (jj-vy0);
+				mreal s = dsx*xx + dsy*yy + (dd+d3y*xx-d3x*yy)*(dd+d3y*xx-d3x*yy);
+				if(s>=0)
+				{
+					s = sqrt(s);
+					mreal qu = d3x*yy - d3y*xx + dd + s;
+					mreal qv = d3y*xx - d3x*yy + dd + s;
+					mreal u = 2.f*(d2y*xx - d2x*yy)/qu;
+					mreal v = 2.f*(d1x*yy - d1y*xx)/qv;
+					if(u*(1.f-u)<0.f || v*(1.f-v)<0.f)	// first root bad
+					{
+						qu = d3x*yy - d3y*xx + dd - s;
+						qv = d3y*xx - d3x*yy + dd - s;
+						u = 2.f*(d2y*xx - d2x*yy)/qu;
+						v = 2.f*(d1x*yy - d1y*xx)/qv;
+						if(u*(1.f-u)<0.f || v*(1.f-v)<0.f)	continue;	// second root bad
+					}
+					i0 = ii+nx*jj;	s = vdat->value(i+u,j+v,0);
+					if(sl<0)	for(long k=0;k<nz;k++)	dat->a[i0+k*nn] = s;
+					else	dat->a[i0+sl*nn] = s;
+				}
+			}
+		}
+	}
+	else
+	{
+		mglData u(nx), v(ny);
+#pragma omp parallel for
+		for(long i=0;i<nx;i++)	u.a[i] = mgl_index_1(x1+dx*i,xdat);
+#pragma omp parallel for
+		for(long i=0;i<ny;i++)	v.a[i] = mgl_index_1(y1+dy*i,ydat);
+#pragma omp parallel for collapse(2)
+		for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+		{
+			mreal d = vdat->value(u.a[i],v.a[j],0);
+			long i0=i+nx*j;
+			if(sl<0)	for(long k=0;k<nz;k++)	dat->a[i0+k*nn] = d;
+			else	dat->a[i0+sl*nn] = d;
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_refill_xyz(HMDT dat, HCDT xdat, HCDT ydat, HCDT zdat, HCDT vdat, mreal x1, mreal x2, mreal y1, mreal y2, mreal z1, mreal z2)
+{
+	long nx=dat->nx,ny=dat->ny,nz=dat->nz,mx=vdat->GetNx(),my=vdat->GetNy(),mz=vdat->GetNz();
+	bool both=(xdat->GetNN()==vdat->GetNN() && ydat->GetNN()==vdat->GetNN() && zdat->GetNN()==vdat->GetNN());
+	if(!both && (xdat->GetNx()!=mx || ydat->GetNx()!=my || zdat->GetNx()!=mz))	return;	// incompatible dimensions
+	const mreal acx=1e-6*fabs(x2-x1), acy=1e-6*fabs(y2-y1), acz=1e-6*fabs(z2-z1);
+	if(both)
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<nz;k++)	for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+		{
+			mreal xx = x1+(x2-x1)*i/(nx-1.),dxx,dxy,dxz,vx,dx=0,dd;
+			mreal yy = y1+(y2-y1)*j/(ny-1.),dyx,dyy,dyz,vy,dy=0;
+			mreal zz = z1+(z2-z1)*k/(nz-1.),dzx,dzy,dzz,vz,dz=0;
+			vx = xdat->valueD(dx,dy,dz,&dxx,&dxy,&dxz);
+			vy = ydat->valueD(dx,dy,dz,&dyx,&dyy,&dyz);
+			vz = zdat->valueD(dx,dy,dz,&dzx,&dzy,&dzz);
+			long count=0;
+			do	// use Newton method to find root
+			{
+				if(count>50)	{	dx=NAN;	break;	}	count++;
+				dd = -dxx*dyy*dzz+dxy*dyx*dzz+dxx*dyz*dzy-dxz*dyx*dzy-dxy*dyz*dzx+dxz*dyy*dzx;
+				dx += ((dyz*dzy-dyy*dzz)*(xx-vx)+(dxy*dzz-dxz*dzy)*(yy-vy)+(dxz*dyy-dxy*dyz)*(zz-vz))/dd;
+				dy += ((dyx*dzz-dyz*dzx)*(xx-vx)+(dxz*dzx-dxx*dzz)*(yy-vy)+(dxx*dyz-dxz*dyx)*(zz-vz))/dd;
+				dz += ((dyy*dzx-dyx*dzy)*(xx-vx)+(dxx*dzy-dxy*dzx)*(yy-vy)+(dxy*dyx-dxx*dyy)*(zz-vz))/dd;
+				vx = xdat->valueD(dx,dy,dz,&dxx,&dxy,&dxz);
+				vy = ydat->valueD(dx,dy,dz,&dyx,&dyy,&dyz);
+				vz = zdat->valueD(dx,dy,dz,&dzx,&dzy,&dzz);
+			}	while(fabs(xx-vx)>acx && fabs(yy-vy)>acy && fabs(zz-vz)>acz);	// this valid for linear interpolation
+			dat->a[i+nx*(j+ny*k)] = mgl_isnan(dx)?NAN:vdat->value(dx,dy,dz);
+		}
+	else
+	{
+		mglData u(nx), v(ny), w(nz);
+		mreal dx = (x2-x1)/(nx-1), dy = (y2-y1)/(ny-1), dz = (z2-z1)/(nz-1);
+#pragma omp parallel for
+		for(long i=0;i<nx;i++)	u.a[i] = mgl_index_1(x1+dx*i,xdat);
+#pragma omp parallel for
+		for(long i=0;i<ny;i++)	v.a[i] = mgl_index_1(y1+dy*i,ydat);
+#pragma omp parallel for
+		for(long i=0;i<nz;i++)	w.a[i] = mgl_index_1(z1+dz*i,zdat);
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<nz;k++)	for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+			dat->a[i+nx*(j+ny*k)] = vdat->value(u.a[i],v.a[j],w.a[k]);
+	}
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_data_evaluate(HCDT dat, HCDT idat, HCDT jdat, HCDT kdat, int norm)
+{
+	if(!idat || (jdat && jdat->GetNN()!=idat->GetNN()) || (kdat && kdat->GetNN()!=idat->GetNN()))	return 0;
+	const mglData *dd=dynamic_cast<const mglData *>(dat);
+	long nx=dat->GetNx(), ny=dat->GetNy(), nz=dat->GetNz();
+	mglData *r=new mglData(idat->GetNx(),idat->GetNy(),idat->GetNz());
+	mreal dx = nx-1, dy = ny-1, dz = nz-1;
+	if(!norm)	dx=dy=dz=1;
+	if(dd)
+#pragma omp parallel for
+		for(long i=0;i<idat->GetNN();i++)
+		{
+			mreal x=dx*idat->vthr(i), y=jdat?dy*jdat->vthr(i):0, z=kdat?dz*kdat->vthr(i):0;
+			r->a[i] = mgl_isnum(x*y*z)?mglSpline3st<mreal>(dd->a,nx,ny,nz, x,y,z):NAN;
+		}
+	else
+#pragma omp parallel for
+		for(long i=0;i<idat->GetNN();i++)
+		{
+			mreal x=dx*idat->vthr(i), y=jdat?dy*jdat->vthr(i):0, z=kdat?dz*kdat->vthr(i):0;
+			r->a[i] = mgl_isnum(x*y*z)?dat->linear(x,y,z):NAN;;
+		}
+	return r;
+}
+uintptr_t MGL_EXPORT mgl_data_evaluate_(uintptr_t *d, uintptr_t *idat, uintptr_t *jdat, uintptr_t *kdat, int *norm)
+{	return uintptr_t(mgl_data_evaluate(_DT_,_DA_(idat),_DA_(jdat),_DA_(kdat),*norm));	}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_gspline_init(HCDT x, HCDT v)
+{
+	long n = v->GetNx();
+	if(!x || x->GetNx()!=n)	return 0;
+	mglData *res = new mglData(5*(n-1));
+	mreal *xx=0, *vv=0;
+	const mglData *dx = dynamic_cast<const mglData *>(x);
+	if(!dx)
+	{
+		xx = new mreal[n];
+		for(long i=0;i<n;i++)	xx[i] = x->v(i);
+	}
+	const mglData *dv = dynamic_cast<const mglData *>(v);
+	if(!dv)
+	{
+		vv = new mreal[n];
+		for(long i=0;i<n;i++)	vv[i] = v->v(i);
+	}
+	mgl_gspline_init(n,dx?dx->a:xx,dv?dv->a:vv,res->a);
+	if(xx)	delete []xx;
+	if(vv)	delete []vv;
+	return res;
+}
+uintptr_t MGL_EXPORT mgl_gspline_init_(uintptr_t *x, uintptr_t *v)
+{	return uintptr_t(mgl_gspline_init(_DA_(x),_DA_(v)));	}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_gspline(HCDT c, mreal dx, mreal *d1, mreal *d2)
+{
+	long i=0, n = c->GetNx();
+	if(n%5 || dx<0)	return NAN;	// not the table of coefficients
+	while(dx>c->v(5*i))
+	{
+		dx-=c->v(5*i);	i++;
+		if(5*i>=n)	return NAN;
+	}
+	if(d1)	*d1 = c->v(5*i+2)+dx*(2*c->v(5*i+3)+3*dx*c->v(5*i+4));
+	if(d2)	*d2 = 2*c->v(5*i+3)+6*dx*c->v(5*i+4);
+	return c->v(5*i+1)+dx*(c->v(5*i+2)+dx*(c->v(5*i+3)+dx*c->v(5*i+4)));
+}
+mreal MGL_EXPORT mgl_gspline_(uintptr_t *c, mreal *dx, mreal *d1, mreal *d2)
+{	return mgl_gspline(_DA_(c),*dx,d1,d2);	}
+//-----------------------------------------------------------------------------
+struct pnt	{	mreal x,y;	pnt(mreal X, mreal Y):x(X),y(Y){}	};
+mreal MGL_NO_EXPORT mgl_find_pnt(std::vector<mreal> &mpos, mreal est, mreal dj)
+{
+	mreal mv = dj, val=NAN;
+	size_t n = mpos.size(), kk=0;
+	for(size_t k=0;k<n;k++)
+	{
+		mreal de = mpos[k]-est;
+		if(fabs(de)<fabs(mv))	{	mv=de;	val=de+est;	kk=k;	}
+	}
+	if(mgl_isnum(val))	mpos.erase(mpos.begin()+kk);
+	return val;
+}
+HMDT MGL_EXPORT mgl_data_detect(HCDT d, mreal lvl, mreal dj, mreal di, mreal min_len)
+{
+	long nx=d->GetNx(), ny=d->GetNy();
+	std::vector<mreal> *max_pos = new std::vector<mreal>[nx];
+	if(di<=0)	di=dj;
+	for(long i=0;i<nx;i++)	// first collect maximums for each i
+	{
+		for(long j=1;j<ny-1;j++)
+		{
+			mreal v = d->v(i,j), v1 = d->v(i,j-1), v2 = d->v(i,j+1);
+			if(v>lvl && v1<v && v>=v2)	// NOTE only one edge is required
+//			if(v>lvl && ((v1<=v && v>v2) || (v1<v && v>=v2)))	// NOTE only edges are required
+			{
+				bool c1=false, c2=false;
+				for(long j1=j-1;j1>=0;j1--)
+				{
+					mreal vv = d->v(i,j1);
+					if(vv>v)	break;
+					if(vv<v/2)	{	c1=true;	break;	}
+				}
+				for(long j2=j+1;j2<ny;j2++)
+				{
+					mreal vv = d->v(i,j2);
+					if(vv>v)	break;
+					if(vv<v/2)	{	c2=true;	break;	}
+				}
+				if(c1 && c2)	max_pos[i].push_back(j + (v2-v1)/(2*v-v2-v1)/2);
+			}
+		}
+	}
+	std::vector<pnt> curv;
+	for(long ii=0;ii<nx-1;ii++)	// now join points into curves
+	{
+		while(max_pos[ii].size())	// try to start curve
+		{
+			mreal vv = max_pos[ii].back();
+			max_pos[ii].pop_back();
+			pnt p1(ii,vv), p2(ii-1,vv);
+			size_t ini = curv.size();
+			curv.push_back(p1);
+			for(long i=ii+1;i<nx;i++)	// join points to selected curve
+			{
+				bool none=true;
+				for(long k=0;k<di && i+k<nx;k++)	// try next points
+				{
+					mreal val = mgl_find_pnt(max_pos[i+k],p1.y,dj);
+					if(mgl_isnum(val))	// first try closest point (for noise data)
+					{	p2=p1;	p1=pnt(i+k,val);	curv.push_back(p1);
+						none=false;	i+=k;	break;	}
+					else	// next try linear approximation
+					{
+						mreal est = p1.y + (k+1)*(p1.y-p2.y)/(p1.x-p2.x);
+						val = mgl_find_pnt(max_pos[i+k],est,dj);
+						if(mgl_isnum(val))
+						{	p2=p1;	p1=pnt(i+k,val);	curv.push_back(p1);
+							none=false;	i+=k;	break;	}
+					}
+				}
+				if(none)	// break curve
+				{	curv.push_back(pnt(NAN,NAN));	break;	}
+			}
+			if(mgl_isnum(curv.back().x))	curv.push_back(pnt(NAN,NAN));
+			if(curv[curv.size()-2].x-curv[ini].x<min_len)
+				curv.erase(curv.begin()+ini,curv.end());
+		}
+	}
+	size_t nn = curv.size();
+	HMDT res = new mglData(2,nn);
+	for(size_t k=0;k<nn;k++)
+	{	res->a[2*k] = curv[k].x;	res->a[2*k+1] = curv[k].y;	}
+	delete []max_pos;	return res;
+}
+uintptr_t MGL_EXPORT mgl_data_detect_(uintptr_t *d, mreal *lvl, mreal *dj, mreal *di, mreal *min_len)
+{	return uintptr_t(mgl_data_detect(_DT_,*lvl,*dj, *di, *min_len));	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_dilate(HMDT d, mreal val, long step)
+{
+	long nx = d->GetNx(), ny=d->GetNy(), nz=d->GetNz();
+	if(step<1 || nx<2) return;
+	long *dist = new long[nx*ny*nz], nn = nx*ny;
+	bool done=false;
+	if(nz>1 && ny>1)
+	{
+		done = true;
+		for(long k=0;k<nz;k++)	for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+		{
+			long i0 = i+nx*(j+ny*k);
+			if(d->vthr(i0)>=val)	dist[i0]=0;
+			else
+			{
+				dist[i0] = nx+ny;
+				if(i>0 && dist[i0-1]+1<dist[i0])	dist[i0]=dist[i0-1]+1;
+				if(j>0 && dist[i0-nx]+1<dist[i0])	dist[i0]=dist[i0-nx]+1;
+				if(k>0 && dist[i0-nn]+1<dist[i0])	dist[i0]=dist[i0-nn]+1;
+			}
+		}
+		for(long k=nz-1;k>=0;k--)	for(long j=ny-1;j>=0;j--)	for(long i=nx-1;i>=0;i--)
+		{
+			long i0 = i+nx*(j+ny*k);
+			if(i<nx-1 && dist[i0+1]+1<dist[i0])		dist[i0]=dist[i0+1]+1;
+			if(j<ny-1 && dist[i0+nx]+1<dist[i0])	dist[i0]=dist[i0+nx]+1;
+			if(k<nz-1 && dist[i0+nn]+1<dist[i0])	dist[i0]=dist[i0+nn]+1;
+		}
+	}
+	else if(ny>1)
+	{
+		done = true;
+		for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+		{
+			long i0 = i+nx*j;
+			if(d->vthr(i0)>=val)	dist[i0]=0;
+			else
+			{
+				dist[i0] = nx+ny;
+				if(i>0 && dist[i0-1]+1<dist[i0])	dist[i0]=dist[i0-1]+1;
+				if(j>0 && dist[i0-nx]+1<dist[i0])	dist[i0]=dist[i0-nx]+1;
+			}
+		}
+		for(long j=ny-1;j>=0;j--)	for(long i=nx-1;i>=0;i--)
+		{
+			long i0 = i+nx*j;
+			if(i<nx-1 && dist[i0+1]+1<dist[i0])		dist[i0]=dist[i0+1]+1;
+			if(j<ny-1 && dist[i0+nx]+1<dist[i0])	dist[i0]=dist[i0+nx]+1;
+		}
+	}
+	else
+	{
+		done = true;
+		for(long i=0;i<nx;i++)
+			if(d->v(i)>=val)	dist[i]=0;
+			else
+			{
+				dist[i] = nx;
+				if(i>0 && dist[i-1]+1<dist[i])	dist[i]=dist[i-1]+1;
+			}
+		for(long i=nx-2;i>=0;i--)
+			if(dist[i+1]+1<dist[i])	dist[i]=dist[i+1]+1;
+	}
+	if(done)	for(long i=0;i<nx*ny*nz;i++)	d->a[i] = dist[i]<=step?1:0;
+	delete []dist;
+}
+void MGL_EXPORT mgl_data_dilate_(uintptr_t *d, mreal *val, int *step)
+{	mgl_data_dilate(_DT_,*val,*step);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_erode(HMDT d, mreal val, long step)
+{
+	long nx = d->GetNx(), ny=d->GetNy(), nz=d->GetNz();
+	if(step<1 || nx<2) return;
+	long *dist = new long[nx*ny*nz], nn = nx*ny;
+	bool done=false;
+	if(nz>1 && ny>1)
+	{
+		done = true;
+		for(long k=0;k<nz;k++)	for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+		{
+			long i0 = i+nx*(j+ny*k);
+			if(d->vthr(i0)<val)	dist[i0]=0;
+			else
+			{
+				dist[i0] = nx+ny;
+				if(i>0 && dist[i0-1]+1<dist[i0])	dist[i0]=dist[i0-1]+1;
+				if(j>0 && dist[i0-nx]+1<dist[i0])	dist[i0]=dist[i0-nx]+1;
+				if(k>0 && dist[i0-nn]+1<dist[i0])	dist[i0]=dist[i0-nn]+1;
+			}
+		}
+		for(long k=nz-1;k>=0;k--)	for(long j=ny-1;j>=0;j--)	for(long i=nx-1;i>=0;i--)
+		{
+			long i0 = i+nx*(j+ny*k);
+			if(i<nx-1 && dist[i0+1]+1<dist[i0])		dist[i0]=dist[i0+1]+1;
+			if(j<ny-1 && dist[i0+nx]+1<dist[i0])	dist[i0]=dist[i0+nx]+1;
+			if(k<nz-1 && dist[i0+nn]+1<dist[i0])	dist[i0]=dist[i0+nn]+1;
+		}
+	}
+	else if(ny>1)
+	{
+		done = true;
+		for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+		{
+			long i0 = i+nx*j;
+			if(d->vthr(i0)<val)	dist[i0]=0;
+			else
+			{
+				dist[i0] = nx+ny;
+				if(i>0 && dist[i0-1]+1<dist[i0])	dist[i0]=dist[i0-1]+1;
+				if(j>0 && dist[i0-nx]+1<dist[i0])	dist[i0]=dist[i0-nx]+1;
+			}
+		}
+		for(long j=ny-1;j>=0;j--)	for(long i=nx-1;i>=0;i--)
+		{
+			long i0 = i+nx*j;
+			if(i<nx-1 && dist[i0+1]+1<dist[i0])		dist[i0]=dist[i0+1]+1;
+			if(j<ny-1 && dist[i0+nx]+1<dist[i0])	dist[i0]=dist[i0+nx]+1;
+		}
+	}
+	else
+	{
+		done = true;
+		for(long i=0;i<nx;i++)
+			if(d->v(i)<val)	dist[i]=0;
+			else
+			{
+				dist[i] = nx;
+				if(i>0 && dist[i-1]+1<dist[i])	dist[i]=dist[i-1]+1;
+			}
+		for(long i=nx-2;i>=0;i--)
+			if(dist[i+1]+1<dist[i])	dist[i]=dist[i+1]+1;
+	}
+	if(done)	for(long i=0;i<nx*ny*nz;i++)	d->a[i] = dist[i]>step?1:0;
+	delete []dist;
+}
+void MGL_EXPORT mgl_data_erode_(uintptr_t *d, mreal *val, int *step)
+{	mgl_data_erode(_DT_,*val,*step);	}
+//-----------------------------------------------------------------------------
diff --git a/src/data_ex.cpp b/src/data_ex.cpp
new file mode 100644
index 0000000..9bdf09b
--- /dev/null
+++ b/src/data_ex.cpp
@@ -0,0 +1,1072 @@
+/***************************************************************************
+ * data_new.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <ctype.h>
+#include "mgl2/data.h"
+#include "mgl2/eval.h"
+#include "mgl2/thread.h"
+HMDT MGL_NO_EXPORT mglFormulaCalc(const char *str, const std::vector<mglDataA*> &head);
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_data_trace(HCDT d)
+{
+	long nx=d->GetNx(),ny=d->GetNy(),nz=d->GetNz();
+	mglData *r=new mglData(nx);
+	if(ny>=nx && nz>=nx)
+#pragma omp parallel for
+		for(long i=0;i<nx;i++)	r->a[i] = d->v(i,i,i);
+	else if(ny>=nx)
+#pragma omp parallel for
+		for(long i=0;i<nx;i++)	r->a[i] = d->v(i,i);
+	else
+#pragma omp parallel for
+		for(long i=0;i<nx;i++)	r->a[i] = d->v(i);
+	return r;
+}
+uintptr_t MGL_EXPORT mgl_data_trace_(uintptr_t *d)
+{	return uintptr_t(mgl_data_trace(_DT_));	}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_data_subdata_ext(HCDT d, HCDT xx, HCDT yy, HCDT zz)
+{
+	if(!xx || !yy || !zz)
+	{
+		mglData tmp;	tmp.a[0]=-1;
+		return mgl_data_subdata_ext(d,xx?xx:&tmp,yy?yy:&tmp,zz?zz:&tmp);
+	}
+
+	long n=0,m=0,l=0,j,k;
+	bool ix=false, iy=false, iz=false;
+	if(xx->GetNz()>1)	// 3d data
+	{
+		n = xx->GetNx();	m = xx->GetNy();	l = xx->GetNz();
+		j = yy->GetNN();	if(j>1 && j!=n*m*l)	return 0;	// wrong sizes
+		k = zz->GetNN();	if(k>1 && k!=n*m*l)	return 0;	// wrong sizes
+		ix = true;	iy = j>1;	iz = k>1;
+	}
+	else if(yy->GetNz()>1)
+	{
+		n = yy->GetNx();	m = yy->GetNy();	l = yy->GetNz();
+		j = xx->GetNN();	if(j>1 && j!=n*m*l)	return 0;	// wrong sizes
+		k = zz->GetNN();	if(k>1 && k!=n*m*l)	return 0;	// wrong sizes
+		iy = true;	ix = j>1;	iz = k>1;
+	}
+	else if(zz->GetNz()>1)
+	{
+		n = zz->GetNx();	m = zz->GetNy();	l = zz->GetNz();
+		j = yy->GetNN();	if(j>1 && j!=n*m*l)	return 0;	// wrong sizes
+		k = xx->GetNN();	if(k>1 && k!=n*m*l)	return 0;	// wrong sizes
+		iz = true;	iy = j>1;	ix = k>1;
+	}
+	else if(xx->GetNy()>1)	// 2d data
+	{
+		n = xx->GetNx();	m = xx->GetNy();	l = 1;
+		j = yy->GetNx()*yy->GetNy();	if(j>1 && j!=n*m)	return 0;	// wrong sizes
+		k = zz->GetNx()*zz->GetNy();	if(k>1 && k!=n*m)	return 0;	// wrong sizes
+		ix = true;	iy = j>1;	iz = k>1;
+	}
+	else if(yy->GetNy()>1)
+	{
+		n = yy->GetNx();	m = yy->GetNy();	l = 1;
+		j = xx->GetNx()*xx->GetNy();	if(j>1 && j!=n*m)	return 0;	// wrong sizes
+		k = zz->GetNx()*zz->GetNy();	if(k>1 && k!=n*m)	return 0;	// wrong sizes
+		iy = true;	ix = j>1;	iz = k>1;
+	}
+	else if(zz->GetNy()>1)
+	{
+		n = zz->GetNx();	m = zz->GetNy();	l = 1;
+		j = yy->GetNx()*yy->GetNy();	if(j>1 && j!=n*m)	return 0;	// wrong sizes
+		k = xx->GetNx()*xx->GetNy();	if(k>1 && k!=n*m)	return 0;	// wrong sizes
+		iz = true;	iy = j>1;	ix = k>1;
+	}
+	long nx=d->GetNx(),ny=d->GetNy(),nz=d->GetNz();
+	long vx=long(xx->v(0)), vy=long(yy->v(0)), vz=long(zz->v(0));
+	mglData *r;
+	if(n*m*l>1)	// this is 2d or 3d data
+	{
+		mglDataV tx(n,m,l),ty(n,m,l),tz(n,m,l);
+		if(!ix)	{	xx = &tx;	if(vx>=0)	tx.Fill(vx);	else tx.All();	}
+		if(!iy)	{	yy = &ty;	if(vy>=0)	ty.Fill(vy);	else ty.All();	}
+		if(!iz)	{	zz = &tz;	if(vz>=0)	tz.Fill(vz);	else tz.All();	}
+		r=new mglData(n,m,l);
+#pragma omp parallel for
+		for(long i0=0;i0<n*m*l;i0++)
+		{
+			long x=long(0.5+xx->vthr(i0)), y=long(0.5+yy->vthr(i0)), z=long(0.5+zz->vthr(i0));
+			r->a[i0] = (x>=0 && x<nx && y>=0 && y<ny && z>=0 && z<nz)?d->v(x,y,z):NAN;
+		}
+	}
+	else	// this is 1d data -> try as normal SubData()
+	{
+		mglDataV tx(nx),ty(ny),tz(nz);	tx.All();	ty.All();	tz.All();
+		if(xx->GetNx()>1 || vx>=0)	n=xx->GetNx();	else	{	n=nx;	xx = &tx;	}
+		if(yy->GetNx()>1 || vy>=0)	m=yy->GetNx();	else	{	m=ny;	yy = &ty;	}
+		if(zz->GetNx()>1 || vz>=0)	l=zz->GetNx();	else	{	l=nz;	zz = &tz;	}
+		r=new mglData(n,m,l);
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<l;k++)	for(long j=0;j<m;j++)	for(long i=0;i<n;i++)
+		{
+			long x=long(0.5+xx->v(i)), y=long(0.5+yy->v(j)), z=long(0.5+zz->v(k));
+			r->a[i+n*(j+m*k)] = (x>=0 && x<nx && y>=0 && y<ny && z>=0 && z<nz)?d->v(x,y,z):NAN;
+		}
+		if(m==1)	{	r->ny=r->nz;	r->nz=1;	}// "squeeze" dimensions
+		if(n==1)	{	r->nx=r->ny;	r->ny=r->nz;	r->nz=1;	r->NewId();}
+	}
+	return r;
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_data_subdata(HCDT d, long xx,long yy,long zz)
+{
+	long nx=d->GetNx(),ny=d->GetNy(),nz=d->GetNz(), n=1,m=1,l=1;
+	int dx=0,dy=0,dz=0;
+	if(xx<0)	{	xx=0;	dx=1;	n=nx;	}
+	if(yy<0)	{	yy=0;	dy=1;	m=ny;	}
+	if(zz<0)	{	zz=0;	dz=1;	l=nz;	}
+	mglData *r=new mglData(n,m,l);
+	if(xx<nx && yy<ny && zz<nz)
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<l;k++)	for(long j=0;j<m;j++)	for(long i=0;i<n;i++)
+			r->a[i+n*(j+m*k)] = d->v(xx+dx*i, yy+dy*j, zz+dz*k);
+	else
+#pragma omp parallel for
+		for(long i=0;i<n*m*l;i++)	r->a[i] = NAN;
+	if(m==1)	{	r->ny=r->nz;	r->nz=1;	}// "squeeze" dimensions
+	if(n==1)	{	r->nx=r->ny;	r->ny=r->nz;	r->nz=1;	r->NewId();}
+	return r;
+}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_data_subdata_(uintptr_t *d, int *xx,int *yy,int *zz)
+{	return uintptr_t(mgl_data_subdata(_DT_,*xx,*yy,*zz));	}
+uintptr_t MGL_EXPORT mgl_data_subdata_ext_(uintptr_t *d, uintptr_t *xx, uintptr_t *yy, uintptr_t *zz)
+{	return uintptr_t(mgl_data_subdata_ext(_DT_,_DA_(xx),_DA_(yy),_DA_(zz)));	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_resize(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0]+0.1, ny=t->p[1]+0.1;
+	mreal *b=t->a;
+	const mreal *c=t->c;
+	HCDT dat = (HCDT)(t->v);
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i0=t->id;i0<t->n;i0+=mglNumThr)
+	{
+		long i=i0%nx, j=((i0/nx)%ny), k=i0/(nx*ny);
+		b[i0] = dat->value(c[0]+i*c[1], c[2]+j*c[3], c[4]+k*c[5]);
+	}
+	return 0;
+}
+HMDT MGL_EXPORT mgl_data_resize_box(HCDT dat, long mx,long my,long mz, mreal x1,mreal x2, mreal y1,mreal y2, mreal z1,mreal z2)
+{
+	long nx = dat->GetNx(), ny = dat->GetNy(), nz = dat->GetNz();
+	mx = mx<1 ? nx:mx;	my = my<1 ? ny:my;	mz = mz<1 ? nz:mz;
+	mglData *r=new mglData(mx,my,mz);
+
+	mreal par[6]={nx*x1,0,ny*y1,0,nz*z1,0};
+	long nn[6]={mx,my,mz,nx,ny,nz};
+	if(mx>1)	par[1] = (nx-1)*(x2-x1)/(mx-1);
+	if(my>1)	par[3] = (ny-1)*(y2-y1)/(my-1);
+	if(mz>1)	par[5] = (nz-1)*(z2-z1)/(mz-1);
+	mglStartThread(mgl_resize,0,mx*my*mz,r->a,0,par,nn,dat);
+	return r;
+}
+HMDT MGL_EXPORT mgl_data_resize(HCDT d, long mx,long my,long mz)
+{	return mgl_data_resize_box(d, mx,my,mz,0,1,0,1,0,1);	}
+uintptr_t MGL_EXPORT mgl_data_resize_(uintptr_t *d, int *mx,int *my,int *mz)
+{	return uintptr_t(mgl_data_resize(_DT_,*mx,*my,*mz));	}
+uintptr_t MGL_EXPORT mgl_data_resize_box_(uintptr_t *d, int *mx,int *my,int *mz, mreal *x1,mreal *x2, mreal *y1,mreal *y2, mreal *z1,mreal *z2)
+{	return uintptr_t(mgl_data_resize_box(_DT_,*mx,*my,*mz,*x1,*x2,*y1,*y2,*z1,*z2));	}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_data_combine(HCDT d1, HCDT d2)
+{
+	long n1=d1->GetNy(),n2=d2->GetNx(),nx=d1->GetNx();
+	if(d1->GetNz()>1 || (n1>1 && d2->GetNy()>1) || d2->GetNz()>1)	return 0;	// wrong dimensions
+	mglData *r=new mglData;
+	bool dim2=true;
+	if(n1==1)	{	n1=n2;	n2=d2->GetNy();	dim2 = false;	}
+	r->Create(nx,n1,n2);
+	if(dim2)	n1*=nx;	else	{	n2*=n1;	n1=nx;	}
+#pragma omp parallel for collapse(2)
+	for(long j=0;j<n2;j++)	for(long i=0;i<n1;i++)
+		r->a[i+n1*j] = d1->vthr(i)*d2->vthr(j);
+	return r;
+}
+uintptr_t MGL_EXPORT mgl_data_combine_(uintptr_t *a, uintptr_t *b)
+{	return uintptr_t(mgl_data_combine(_DA_(a),_DA_(b)));	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_sum_z(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nz=t->p[2], nn=t->n;
+	mreal *b=t->a;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		b[i]=0;
+		for(long j=0;j<nz;j++)	b[i] += a[i+nn*j];
+		b[i] /= nz;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_sum_y(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0], ny=t->p[1], nn=t->n;
+	mreal *b=t->a;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = (i%nx)+nx*ny*(i/nx);	b[i]=0;
+		for(long j=0;j<ny;j++)	b[i] += a[k+nx*j];
+		b[i] /= ny;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_sum_x(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0], nn=t->n;
+	mreal *b=t->a;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = i*nx;	b[i]=0;
+		for(long j=0;j<nx;j++)	b[i] += a[j+k];
+		b[i] /= nx;
+	}
+	return 0;
+}
+HMDT MGL_EXPORT mgl_data_sum(HCDT dat, const char *dir)
+{
+	if(!dir || *dir==0)	return 0;
+	long nx=dat->GetNx(),ny=dat->GetNy(),nz=dat->GetNz();
+	long p[3]={nx,ny,nz};
+	mreal *b = new mreal[nx*ny*nz];
+	mreal *c = new mreal[nx*ny*nz];
+
+	const mglData *d=dynamic_cast<const mglData *>(dat);
+	if(d)	memcpy(c,d->a,nx*ny*nz*sizeof(mreal));
+	else
+#pragma omp parallel for
+		for(long i=0;i<nx*ny*nz;i++)	c[i]=dat->vthr(i);
+
+	if(strchr(dir,'z') && nz>1)
+	{
+		mglStartThread(mgl_sum_z,0,nx*ny,b,c,0,p);
+		memcpy(c,b,nx*ny*sizeof(mreal));	p[2] = 1;
+	}
+	if(strchr(dir,'y') && ny>1)
+	{
+		mglStartThread(mgl_sum_y,0,nx*p[2],b,c,0,p);
+		memcpy(c,b,nx*p[2]*sizeof(mreal));	p[1] = p[2];	p[2] = 1;
+	}
+	if(strchr(dir,'x') && nx>1)
+	{
+		mglStartThread(mgl_sum_x,0,p[1]*p[2],b,c,0,p);
+		p[0] = p[1];	p[1] = p[2];	p[2] = 1;
+		memcpy(c,b,p[0]*p[1]*sizeof(mreal));
+	}
+	mglData *r=new mglData(p[0],p[1],p[2]);
+	memcpy(r->a,c,p[0]*p[1]*p[2]*sizeof(mreal));
+	delete []b;	delete []c;	return r;
+}
+uintptr_t MGL_EXPORT mgl_data_sum_(uintptr_t *d, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	uintptr_t r=uintptr_t(mgl_data_sum(_DT_,s));	delete []s;	return r;	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_max_z(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nz=t->p[2], nn=t->n;
+	mreal *b=t->a;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		b[i]=a[i];
+		for(long j=1;j<nz;j++)	if(b[i]<a[i+nn*j]) b[i] = a[i+nn*j];
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_max_y(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0], ny=t->p[1], nn=t->n;
+	mreal *b=t->a;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = (i%nx)+nx*ny*(i/nx);	b[i]=a[k];
+		for(long j=1;j<ny;j++)	if(b[i]<a[k+nx*j])	b[i]=a[k+nx*j];
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_max_x(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0], nn=t->n;
+	mreal *b=t->a;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = i*nx;	b[i]=a[k];
+		for(long j=1;j<nx;j++)	if(b[i]<a[j+k])	b[i]=a[j+k];
+	}
+	return 0;
+}
+HMDT MGL_EXPORT mgl_data_max_dir(HCDT dat, const char *dir)
+{
+	if(!dir || *dir==0)	return 0;
+	long nx=dat->GetNx(),ny=dat->GetNy(),nz=dat->GetNz();
+	long p[3]={nx,ny,nz};
+	mreal *b = new mreal[nx*ny*nz];
+	mreal *c = new mreal[nx*ny*nz];
+
+	const mglData *d=dynamic_cast<const mglData *>(dat);
+	if(d)	memcpy(c,d->a,nx*ny*nz*sizeof(mreal));
+	else
+#pragma omp parallel for
+		for(long i=0;i<nx*ny*nz;i++)	c[i]=dat->vthr(i);
+
+	if(strchr(dir,'z') && nz>1)
+	{
+		mglStartThread(mgl_max_z,0,nx*ny,b,c,0,p);
+		memcpy(c,b,nx*ny*sizeof(mreal));	p[2] = 1;
+	}
+	if(strchr(dir,'y') && ny>1)
+	{
+		mglStartThread(mgl_max_y,0,nx*p[2],b,c,0,p);
+		memcpy(c,b,nx*p[2]*sizeof(mreal));	p[1] = p[2];	p[2] = 1;
+	}
+	if(strchr(dir,'x') && nx>1)
+	{
+		mglStartThread(mgl_max_x,0,p[1]*p[2],b,c,0,p);
+		p[0] = p[1];	p[1] = p[2];	p[2] = 1;
+		memcpy(c,b,p[0]*p[1]*sizeof(mreal));
+	}
+	mglData *r=new mglData(p[0],p[1],p[2]);
+	memcpy(r->a,c,p[0]*p[1]*p[2]*sizeof(mreal));
+	delete []b;	delete []c;	return r;
+}
+uintptr_t MGL_EXPORT mgl_data_max_dir_(uintptr_t *d, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	uintptr_t r=uintptr_t(mgl_data_max_dir(_DT_,s));	delete []s;	return r;	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_min_z(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nz=t->p[2], nn=t->n;
+	mreal *b=t->a;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		b[i]=a[i];
+		for(long j=1;j<nz;j++)	if(b[i]>a[i+nn*j]) b[i] = a[i+nn*j];
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_min_y(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0], ny=t->p[1], nn=t->n;
+	mreal *b=t->a;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = (i%nx)+nx*ny*(i/nx);	b[i]=a[k];
+		for(long j=1;j<ny;j++)	if(b[i]>a[k+nx*j])	b[i]=a[k+nx*j];
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_min_x(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0], nn=t->n;
+	mreal *b=t->a;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = i*nx;	b[i]=a[k];
+		for(long j=1;j<nx;j++)	if(b[i]>a[j+k])	b[i]=a[j+k];
+	}
+	return 0;
+}
+HMDT MGL_EXPORT mgl_data_min_dir(HCDT dat, const char *dir)
+{
+	if(!dir || *dir==0)	return 0;
+	long nx=dat->GetNx(),ny=dat->GetNy(),nz=dat->GetNz();
+	long p[3]={nx,ny,nz};
+	mreal *b = new mreal[nx*ny*nz];
+	mreal *c = new mreal[nx*ny*nz];
+
+	const mglData *d=dynamic_cast<const mglData *>(dat);
+	if(d)	memcpy(c,d->a,nx*ny*nz*sizeof(mreal));
+	else
+#pragma omp parallel for
+		for(long i=0;i<nx*ny*nz;i++)	c[i]=dat->vthr(i);
+
+	if(strchr(dir,'z') && nz>1)
+	{
+		mglStartThread(mgl_min_z,0,nx*ny,b,c,0,p);
+		memcpy(c,b,nx*ny*sizeof(mreal));	p[2] = 1;
+	}
+	if(strchr(dir,'y') && ny>1)
+	{
+		mglStartThread(mgl_min_y,0,nx*p[2],b,c,0,p);
+		memcpy(c,b,nx*p[2]*sizeof(mreal));	p[1] = p[2];	p[2] = 1;
+	}
+	if(strchr(dir,'x') && nx>1)
+	{
+		mglStartThread(mgl_min_x,0,p[1]*p[2],b,c,0,p);
+		p[0] = p[1];	p[1] = p[2];	p[2] = 1;
+		memcpy(c,b,p[0]*p[1]*sizeof(mreal));
+	}
+	mglData *r=new mglData(p[0],p[1],p[2]);
+	memcpy(r->a,c,p[0]*p[1]*p[2]*sizeof(mreal));
+	delete []b;	delete []c;	return r;
+}
+uintptr_t MGL_EXPORT mgl_data_min_dir_(uintptr_t *d, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	uintptr_t r=uintptr_t(mgl_data_min_dir(_DT_,s));	delete []s;	return r;	}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_data_momentum(HCDT dat, char dir, const char *how)
+{
+	if(!how || !(*how) || !strchr("xyz",dir))	return 0;
+	long nx=dat->GetNx(),ny=dat->GetNy(),nz=dat->GetNz();
+	mglDataV x(nx,ny,nz, 0,1,'x');	x.s=L"x";
+	mglDataV y(nx,ny,nz, 0,1,'y');	y.s=L"y";
+	mglDataV z(nx,ny,nz, 0,1,'z');	z.s=L"z";
+	mglData u(dat);	u.s=L"u";	// NOTE slow !!!
+	std::vector<mglDataA*> list;
+	list.push_back(&x);	list.push_back(&y);	list.push_back(&z);	list.push_back(&u);
+	HMDT res=mglFormulaCalc(how,list), b=0;
+
+	if(dir=='x')
+	{
+		b=new mglData(nx);
+#pragma omp parallel for
+		for(long i=0;i<nx;i++)
+		{
+			mreal i1=0,i0=0;
+			for(long j=0;j<ny*nz;j++)
+			{
+				mreal u=dat->vthr(i+nx*j);
+				i0 += u;	i1 += u*res->a[i+nx*j];
+			}
+			b->a[i] = i0>0 ? i1/i0 : 0;
+		}
+	}
+	if(dir=='y')
+	{
+		b=new mglData(ny);
+#pragma omp parallel for
+		for(long i=0;i<ny;i++)
+		{
+			mreal i1=0,i0=0;
+			for(long k=0;k<nz;k++)	for(long j=0;j<nx;j++)
+			{
+				mreal u=dat->v(j,i,k);
+				i0 += u;	i1 += u*res->a[j+nx*(i+ny*k)];
+			}
+			b->a[i] = i0>0 ? i1/i0 : 0;
+		}
+	}
+	if(dir=='z')
+	{
+		long nn=nx*ny;
+		b=new mglData(nz);
+#pragma omp parallel for
+		for(long i=0;i<nz;i++)
+		{
+			mreal i1=0,i0=0;
+			for(long j=0;j<nn;j++)
+			{
+				mreal u=dat->vthr(j+nn*i);
+				i0 += u;	i1 += u*res->a[j+nn*i];
+			}
+			b->a[i] = i0>0 ? i1/i0 : 0;
+		}
+	}
+	mgl_delete_data(res);	return b;
+}
+uintptr_t MGL_EXPORT mgl_data_momentum_(uintptr_t *d, char *dir, const char *how, int,int l)
+{	char *s=new char[l+1];	memcpy(s,how,l);	s[l]=0;
+	uintptr_t r=uintptr_t(mgl_data_momentum(_DT_,*dir, s));	delete []s;	return r;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_mul_dat(HMDT d, HCDT a)
+{
+	long nx=d->nx, ny=d->ny, nz=d->nz;
+	long mx=a->GetNx(), my=a->GetNy(), mz=a->GetNz();
+	if(mz==1 && my==1 && mx==1)
+	{
+		mreal v=a->v(0);
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<nz;k++)	for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+			d->a[i+nx*(j+ny*k)] *= v;
+	}
+	else
+	{
+		long n=0, m=0;
+		if(nz*ny*nx==mz*my*mx)	{	n=nx*ny*nz;	m=1;	}
+		else if(ny*nx==my*mx)	{	n=nx*ny;	m=nz;	}
+		else if(nx==mx)			{	n=nx;	m=ny*nz;	}
+#pragma omp parallel for collapse(2)
+		for(long k=0;k<m;k++)	for(long i=0;i<n;i++)	d->a[i+n*k] *= a->vthr(i);
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_mul_num(HMDT d, mreal a)
+{
+	long n=d->GetNN();
+#pragma omp parallel for
+	for(long i=0;i<n;i++)	d->a[i] *= a;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_div_dat(HMDT d, HCDT a)
+{
+	long nx=d->nx, ny=d->ny, nz=d->nz;
+	long mx=a->GetNx(), my=a->GetNy(), mz=a->GetNz();
+	if(mz==1 && my==1 && mx==1)
+	{
+		mreal v=a->v(0);
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<nz;k++)	for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+			d->a[i+nx*(j+ny*k)] /= v;
+	}
+	else
+	{
+		long n=0, m=0;
+		if(nz*ny*nx==mz*my*mx)	{	n=nx*ny*nz;	m=1;	}
+		else if(ny*nx==my*mx)	{	n=nx*ny;	m=nz;	}
+		else if(nx==mx)			{	n=nx;	m=ny*nz;	}
+#pragma omp parallel for collapse(2)
+		for(long k=0;k<m;k++)	for(long i=0;i<n;i++)	d->a[i+n*k] /= a->vthr(i);
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_div_num(HMDT d, mreal a)
+{
+	long n=d->GetNN();
+#pragma omp parallel for
+	for(long i=0;i<n;i++)	d->a[i] /= a;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_add_dat(HMDT d, HCDT a)
+{
+	long nx=d->nx, ny=d->ny, nz=d->nz;
+	long mx=a->GetNx(), my=a->GetNy(), mz=a->GetNz();
+	if(mz==1 && my==1 && mx==1)
+	{
+		mreal v=a->v(0);
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<nz;k++)	for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+			d->a[i+nx*(j+ny*k)] += v;
+	}
+	else
+	{
+		long n=0, m=0;
+		if(nz*ny*nx==mz*my*mx)	{	n=nx*ny*nz;	m=1;	}
+		else if(ny*nx==my*mx)	{	n=nx*ny;	m=nz;	}
+		else if(nx==mx)			{	n=nx;	m=ny*nz;	}
+#pragma omp parallel for collapse(2)
+		for(long k=0;k<m;k++)	for(long i=0;i<n;i++)	d->a[i+n*k] += a->vthr(i);
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_add_num(HMDT d, mreal a)
+{
+	long n=d->GetNN();
+#pragma omp parallel for
+	for(long i=0;i<n;i++)	d->a[i] += a;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_sub_dat(HMDT d, HCDT a)
+{
+	long nx=d->nx, ny=d->ny, nz=d->nz;
+	long mx=a->GetNx(), my=a->GetNy(), mz=a->GetNz();
+	if(mz==1 && my==1 && mx==1)
+	{
+		mreal v=a->v(0);
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<nz;k++)	for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+			d->a[i+nx*(j+ny*k)] -= v;
+	}
+	else
+	{
+		long n=0, m=0;
+		if(nz*ny*nx==mz*my*mx)	{	n=nx*ny*nz;	m=1;	}
+		else if(ny*nx==my*mx)	{	n=nx*ny;	m=nz;	}
+		else if(nx==mx)			{	n=nx;	m=ny*nz;	}
+#pragma omp parallel for collapse(2)
+		for(long k=0;k<m;k++)	for(long i=0;i<n;i++)	d->a[i+n*k] -= a->vthr(i);
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_sub_num(HMDT d, mreal a)
+{
+	long n=d->GetNN();
+#pragma omp parallel for
+	for(long i=0;i<n;i++)	d->a[i] -= a;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_mul_dat_(uintptr_t *d, uintptr_t *b)	{	mgl_data_mul_dat(_DT_, _DA_(b));	}
+void MGL_EXPORT mgl_data_div_dat_(uintptr_t *d, uintptr_t *b)	{	mgl_data_div_dat(_DT_, _DA_(b));	}
+void MGL_EXPORT mgl_data_add_dat_(uintptr_t *d, uintptr_t *b)	{	mgl_data_add_dat(_DT_, _DA_(b));	}
+void MGL_EXPORT mgl_data_sub_dat_(uintptr_t *d, uintptr_t *b)	{	mgl_data_sub_dat(_DT_, _DA_(b));	}
+void MGL_EXPORT mgl_data_mul_num_(uintptr_t *d, mreal *b)		{	mgl_data_mul_num(_DT_, *b);	}
+void MGL_EXPORT mgl_data_div_num_(uintptr_t *d, mreal *b)		{	mgl_data_div_num(_DT_, *b);	}
+void MGL_EXPORT mgl_data_add_num_(uintptr_t *d, mreal *b)		{	mgl_data_add_num(_DT_, *b);	}
+void MGL_EXPORT mgl_data_sub_num_(uintptr_t *d, mreal *b)		{	mgl_data_sub_num(_DT_, *b);	}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_hist_p(mglThreadD *t,mreal *a)
+{
+	long n=t[0].p[0];
+	memset(a,0,n*sizeof(mreal));
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=0;i<mglNumThr;i++)
+	{
+		mreal *b = t[i].a;
+		for(long j=0;j<n;j++)	a[j] += b[j];
+		delete []b;
+	}
+}
+MGL_NO_EXPORT void *mgl_hist_1(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nn=t->n, n = t->p[0];
+	mreal *b=new mreal[n];
+	memset(b,0,n*sizeof(mreal));
+	HCDT a = (HCDT)(t->b), c = (HCDT)(t->c);
+	const mreal *v=(const mreal *)t->v;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = long(n*(a->vthr(i)-v[0])/(v[1]-v[0]));
+		if(k>=0 && k<n)
+#if !MGL_HAVE_PTHREAD
+#pragma omp critical(hist)
+#endif
+			b[k] += c ? c->vthr(i):1.;
+	}
+	t->a = b;	return 0;
+}
+MGL_NO_EXPORT void *mgl_hist_2(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nn=t->n, n = t->p[0];
+	long ns=t->p[1], nx=t->p[2], ny=t->p[3];
+	mreal *b=new mreal[n], d=1./ns;
+	memset(b,0,n*sizeof(mreal));
+	HCDT a = (HCDT)(t->b), c = (HCDT)(t->c);
+	const mreal *v=(const mreal *)t->v;
+	bool sp = n>0;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		mreal x = d*(i%(nx*ns)), y = d*((i/(nx*ns))%(ny*ns)), z = d*(i/(nx*ny*ns*ns));
+		mreal f = sp ? a->value(x,y,z) : a->linear(x,y,z), w=1;
+		if(c)	w = sp ? c->value(x,y,z) : c->linear(x,y,z);
+		if(mgl_isnan(f) || mgl_isnan(w))	continue;
+		long k = long(n*(f-v[0])/(v[1]-v[0]));
+		if(k>=0 && k<n)
+#if !MGL_HAVE_PTHREAD
+#pragma omp critical(hist)
+#endif
+			b[k] += w * d*d*d;
+	}
+	t->a = b;	return 0;
+}
+HMDT MGL_EXPORT mgl_data_hist(HCDT dat, long n, mreal v1, mreal v2, long nsub)
+{
+	if(n<2 || v1==v2)	return 0;
+	mglData *b=new mglData(n);
+	mreal v[2]={v1,v2};
+	long nx=dat->GetNx(), ny=dat->GetNy(), nz=dat->GetNz();
+	long ns=labs(nsub)+1, p[5]={n,ns,nx,ny,nz};
+	if(nsub==0)	mglStartThread(mgl_hist_1,mgl_hist_p, nx*ny*nz, b->a,(const mreal *)dat,0,p,v);
+	else	mglStartThread(mgl_hist_2,mgl_hist_p, nx*ny*nz*ns*ns*ns, b->a,(const mreal *)dat,0,p,v);
+	return b;
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_data_hist_w(HCDT dat, HCDT weight, long n, mreal v1, mreal v2, long nsub)
+{
+	if(n<2 || v1==v2)	return 0;
+	mglData *b=new mglData(n);
+	mreal v[2]={v1,v2};
+
+	long nx=dat->GetNx(), ny=dat->GetNy(), nz=dat->GetNz();
+	long ns=labs(nsub)+1, p[5]={n,ns,nx,ny,nz};
+	if(nsub==0)	mglStartThread(mgl_hist_1,mgl_hist_p, nx*ny*nz, b->a,(const mreal *)dat,(const mreal *)weight,p,v);
+	else	mglStartThread(mgl_hist_2,mgl_hist_p, nx*ny*nz*ns*ns*ns, b->a,(const mreal *)dat,(const mreal *)weight,p,v);
+	return b;
+}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_data_hist_(uintptr_t *d, int *n, mreal *v1, mreal *v2, int *nsub)
+{	return uintptr_t(mgl_data_hist(_DT_,*n,*v1,*v2,*nsub));	}
+uintptr_t MGL_EXPORT mgl_data_hist_w_(uintptr_t *d, uintptr_t *w, int *n, mreal *v1, mreal *v2, int *nsub)
+{	return uintptr_t(mgl_data_hist_w(_DT_,_DA_(w),*n,*v1,*v2,*nsub));	}
+//-----------------------------------------------------------------------------
+long MGL_NO_EXPORT mgl_idx_var;
+int MGL_LOCAL_PURE mgl_cmd_idx(const void *a, const void *b)
+{
+	mreal *aa = (mreal *)a, *bb = (mreal *)b;
+	return (aa[mgl_idx_var]>bb[mgl_idx_var] ? 1:(aa[mgl_idx_var]<bb[mgl_idx_var]?-1:0) );
+}
+void MGL_EXPORT mgl_data_sort(HMDT dat, long idx, long idy)
+{
+	mglData *d = dynamic_cast<mglData *>(dat);
+	if(!d || idx>=d->nx || idx<0)	return;
+	bool single = (d->nz==1 || idy<0);
+	if(idy<0 || idy>d->ny)	idy=0;
+	mgl_idx_var = idx+d->nx*idy;	// NOTE: not thread safe!!!
+	if(single)	qsort(d->a, d->ny*d->nz, d->nx*sizeof(mreal), mgl_cmd_idx);
+	else		qsort(d->a, d->nz, d->ny*d->nx*sizeof(mreal), mgl_cmd_idx);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_sort_(uintptr_t *d, int *idx, int *idy)
+{	mgl_data_sort(_DT_,*idx,*idy);	}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_find_root(mreal (*func)(mreal x, void *par), mreal x0, void *par)
+{
+	mreal x1=x0+1e-2*(x0?x0:1), f0=func(x0,par), f1=func(x1,par), x, f;
+	if(fabs(f0)<1e-7)	return x0;
+	if(fabs(f1)<1e-7)	return x1;
+	if(f0==f1)	return NAN;
+	for(long i=0;i<20;i++)
+	{
+		x = x1-f1*(x1-x0)/(f1-f0);	f = func(x,par);
+		if(fabs(f)<1e-7)	return x;
+/*		if(fabs(f-f1)>0.5*mgl_min(fabs(f),fabs(f1)))	// TODO switch to bisection if slow
+		{
+			x = (x1+x0)/2;	f = func(x,par);
+			if(fabs(f)<1e-7)	return x;
+		}*/
+		x0=x1;	f0=f1;	x1=x;	f1=f;	// new points
+	}
+	return NAN;	// no roots found
+}
+//-----------------------------------------------------------------------------
+struct MGL_NO_EXPORT mglFuncV	{	mglFormula *eq;	char var;	};
+mreal MGL_NO_EXPORT mgl_funcv(mreal v, void *par)
+{
+	mglFuncV *f = (mglFuncV *)par;
+	mreal var[MGL_VS];	memset(var,0,MGL_VS*sizeof(mreal));
+	var[f->var-'a'] = v;
+	return f->eq->Calc(var);
+}
+HMDT MGL_EXPORT mgl_data_roots(const char *func, HCDT ini, char var)
+{
+	if(!ini)	return 0;
+	mglData *res = new mglData(ini);
+
+	mglFormula eq(func);
+	mglFuncV f;	f.eq = &eq;	f.var = var;
+	long n = res->nx*res->ny*res->nz;
+#pragma omp parallel for
+	for(long i=0;i<n;i++)
+		res->a[i] = mgl_find_root(mgl_funcv,res->a[i],&f);
+	return res;
+}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_find_root_txt(const char *func, mreal ini, char var)
+{
+	mglFormula eq(func);
+	mglFuncV f;	f.eq = &eq;	f.var = var;
+	return mgl_find_root(mgl_funcv,ini,&f);
+}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_data_roots_(const char *func, uintptr_t *ini, const char *var,int l,int)
+{	char *s=new char[l+1];	memcpy(s,func,l);	s[l]=0;
+	uintptr_t r = uintptr_t(mgl_data_roots(s,_DA_(ini),*var));
+	delete []s;	return r;	}
+mreal MGL_EXPORT mgl_find_root_txt_(const char *func, mreal *ini, const char *var,int l,int)
+{	char *s=new char[l+1];	memcpy(s,func,l);	s[l]=0;
+	mreal r = mgl_find_root_txt(s,*ini,*var);
+	delete []s;	return r;	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_pulse_z(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nz=t->p[2], nn=t->n;
+	mreal *b=t->a;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long j0=0;	mreal m=a[i];
+		for(long j=1;j<nz;j++)	// get maximum
+		{	long i0=i+nn*j;
+			if(m<a[i0])	{	m=a[i0];	j0=j;	}
+		}
+		if(j0>0 && j0<nz-1)
+		{
+			long i0=i+nn*j0;
+			mreal A = (a[i0-nn]-2*a[i0]+a[i0+nn])/2;
+			mreal B = (a[i0+nn]-a[i0-nn])/2;
+			mreal C = a[i0] - B*B/(4*A);
+			b[i]=C;	b[i+nn]=j0-B/(2*A);	b[i+2*nn]=sqrt(fabs(C/A));	C /= 2;
+			mreal j1=NAN,j2=NAN;
+			for(long j=j0;j<nz-1;j++)
+			{	long i0 = i+nn*j;
+				if((a[i0]-C)*(a[i0+nn]-C)<0)	j2 = j + (a[i0]-C)/(a[i0]-a[i0+nn]);
+			}
+			for(long j=j0;j>0;j--)
+			{	long i0=i+nn*j;
+				if((a[i0]-C)*(a[i0-nn]-C)<0)	j1 = j - (a[i0]-C)/(a[i0]-a[i0-nn]);
+			}
+			b[i+3*nn]=j2-j1;	b[i+4*nn]=0;
+			if(j2>j1)	for(long j = j1;j<=j2;j++)	b[i+4*nn] += a[i+nn*j];
+		}
+		else	// maximum at the edges
+		{	b[i]=m;	b[i+nn]=j0;	b[i+2*nn]=b[i+3*nn]=b[i+4*nn]=NAN;	}
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_pulse_y(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0], ny=t->p[1], nn=t->n;
+	mreal *b=t->a;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = (i%nx)+nx*ny*(i/nx), j0=0;	mreal m=a[k];
+		long ki = (i%nx)+5*nx*(i/nx);
+		for(long j=1;j<ny;j++)	// get maximum
+		{	long i0=k+nx*j;
+			if(m<a[i0])	{	m=a[i0];	j0=j;	}
+		}
+		if(j0>0 && j0<ny-1)
+		{
+			long i0=k+nx*j0;
+			mreal A = (a[i0-nx]-2*a[i0]+a[i0+nx])/2;
+			mreal B = (a[i0+nx]-a[i0-nx])/2;
+			mreal C = a[i0] - B*B/(4*A);
+			b[ki]=C;	b[ki+nx]=j0-B/(2*A);	b[ki+2*nx]=sqrt(fabs(C/A));	C /= 2;
+			mreal j1=NAN,j2=NAN;
+			for(long j=j0;j<ny-1;j++)
+			{	long i0 = k+nx*j;
+				if((a[i0]-C)*(a[i0+nx]-C)<0)	j2 = j + (a[i0]-C)/(a[i0]-a[i0+nx]);
+			}
+			for(long j=j0;j>0;j--)
+			{	long i0=k+nx*j;
+				if((a[i0]-C)*(a[i0-nx]-C)<0)	j1 = j - (a[i0]-C)/(a[i0]-a[i0-nx]);
+			}
+			b[ki+3*nx]=j2-j1;	b[ki+4*nx]=0;
+			if(j2>j1)	for(long j = j1;j<=j2;j++)	b[ki+4*nx] += a[k+nx*j];
+		}
+		else	// maximum at the edges
+		{	b[ki]=m;	b[ki+nx]=j0;	b[ki+2*nx]=b[ki+3*nx]=b[ki+4*nx]=NAN;	}
+	}
+	return 0;
+}
+MGL_NO_EXPORT void *mgl_pulse_x(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	long nx=t->p[0], nn=t->n;
+	mreal *b=t->a;
+	const mreal *a=t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nn;i+=mglNumThr)
+	{
+		long k = i*nx, j0=0;	mreal m=a[k];
+		for(long j=1;j<nx;j++)	// get maximum
+		{	long i0=j+k;
+			if(m<a[i0])	{	m=a[i0];	j0=j;	}
+		}
+		if(j0>0 && j0<nx-1)
+		{
+			long i0=j0+k;
+			mreal A = (a[i0-1]-2*a[i0]+a[i0+1])/2;
+			mreal B = (a[i0+1]-a[i0-1])/2;
+			mreal C = a[i0] - B*B/(4*A);
+			b[5*i]=C;	b[5*i+1]=j0-B/(2*A);	b[5*i+2]=sqrt(fabs(C/A));	C /= 2;
+			mreal j1=NAN,j2=NAN;
+			for(long j=j0;j<nx-1;j++)
+			{	long i0 = j+k;
+				if((a[i0]-C)*(a[i0+1]-C)<0)	j2 = j + (a[i0]-C)/(a[i0]-a[i0+1]);
+			}
+			for(long j=j0;j>0;j--)
+			{	long i0=j+k;
+				if((a[i0]-C)*(a[i0-1]-C)<0)	j1 = j - (a[i0]-C)/(a[i0]-a[i0-1]);
+			}
+			b[5*i+3]=j2-j1;	b[5*i+4]=0;
+			if(j2>j1)	for(long j = j1;j<=j2;j++)	b[5*i+4] += a[j+k];
+		}
+		else	// maximum at the edges
+		{	b[5*i]=m;	b[5*i+1]=j0;	b[5*i+2]=b[5*i+3]=b[5*i+4]=NAN;	}
+	}
+	return 0;
+}
+HMDT MGL_EXPORT mgl_data_pulse(HCDT dat, char dir)
+{
+//	if(!dir || *dir==0)	return 0;
+	long nx=dat->GetNx(),ny=dat->GetNy(),nz=dat->GetNz();
+	long p[3]={nx,ny,nz};
+	mreal *c = new mreal[nx*ny*nz], *b=0;
+
+	const mglData *d=dynamic_cast<const mglData *>(dat);
+	if(d)	memcpy(c,d->a,nx*ny*nz*sizeof(mreal));
+	else
+#pragma omp parallel for
+		for(long i=0;i<nx*ny*nz;i++)	c[i]=dat->vthr(i);
+
+	if(dir=='z' && nz>1)
+	{
+		b = new mreal[nx*ny*5];
+		mglStartThread(mgl_pulse_z,0,nx*ny,b,c,0,p);	p[2] = 5;
+	}
+	else if(dir=='y' && ny>1)
+	{
+		b = new mreal[5*nx*nz];
+		mglStartThread(mgl_pulse_y,0,nx*p[2],b,c,0,p);	p[1] = 5;
+	}
+	else if(dir=='x' && nx>1)
+	{
+		b = new mreal[5*ny*nz];
+		mglStartThread(mgl_pulse_x,0,p[1]*p[2],b,c,0,p);	p[0] = 5;
+	}
+	mglData *r=0;
+	if(b)
+	{
+		r=new mglData(p[0],p[1],p[2]);
+		memcpy(r->a,b,p[0]*p[1]*p[2]*sizeof(mreal));
+		delete []b;
+	}
+	delete []c;	return r;
+}
+uintptr_t MGL_EXPORT mgl_data_pulse_(uintptr_t *d, const char *dir,int)
+{	return uintptr_t(mgl_data_pulse(_DT_,dir[0]));	}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_data_section(HCDT dat, HCDT ids, char dir, mreal val)
+{
+	long di = 1, n = dat->GetNx();
+	if(dir=='y')	{	di = dat->GetNx();	n = dat->GetNy();	}
+	if(dir=='z')	{	di = dat->GetNx()*dat->GetNy();	n = dat->GetNz();	}
+	// first collect position of key values
+	std::vector<long> pos;	pos.push_back(0);
+	if(mgl_isnan(val))	for(long i=1;i<n;i++)
+	{
+		if(mgl_isnan(dat->vthr(i*di)))	pos.push_back(i);
+	}
+	else	for(long i=0;i<n;i++)
+	{
+		if(dat->vthr(i*di)==val)	pos.push_back(i);
+	}
+	pos.push_back(n);	// add last point (size of data)
+	// now collect required position from section and its lengths
+	std::vector<long> ls, ps;
+	long np = pos.size()-1, nl=0;
+	if(np<1)	return NULL;	// nothing to do
+	for(long i=0;i<ids->GetNN();i++)
+	{
+		long j = mgl_int(ids->vthr(i)+0.5);	j = j<0?np+j:j;
+		if(j>=0 && j<np)
+		{	long l = pos[j+1]-pos[j];	nl += l;
+			ls.push_back(l);	ps.push_back(pos[j]);	}
+	}
+	if(nl==0)	return NULL;
+	mglData *r=0;
+	size_t ns = ps.size();
+	if(dir=='y')
+	{
+		long nx=dat->GetNx(), nz=dat->GetNz(), sh=0;
+		r = new mglData(nx,nl,nz);
+		for(size_t s=0;s<ns;s++)
+		{
+			long pp = ps[s];
+#pragma omp parallel for collapse(3)
+			for(long k=0;k<nz;k++)	for(long j=0;j<ls[s];j++)	for(long i=0;i<nx;i++)
+				r->a[i+nx*(sh+j+nl*k)] = dat->v(i,pp+j,k);
+			sh += ls[s];
+		}
+	}
+	else if(dir=='x')
+	{
+		long ny=dat->GetNy(), nz=dat->GetNz(), sh=0;
+		r = new mglData(nl,ny,nz);
+		for(size_t s=0;s<ns;s++)
+		{
+			long pp = ps[s];
+#pragma omp parallel for collapse(3)
+			for(long k=0;k<nz;k++)	for(long j=0;j<ny;j++)	for(long i=0;i<ls[s];i++)
+				r->a[sh+i+nl*(j+ny*k)] = dat->v(pp+i,j,k);
+			sh += ls[s];
+		}
+	}
+	else if(dir=='z')
+	{
+		long nx=dat->GetNx(), ny=dat->GetNy(), sh=0;
+		r = new mglData(nx,ny,nl);
+		for(size_t s=0;s<ns;s++)
+		{
+			long pp = ps[s];
+#pragma omp parallel for collapse(3)
+			for(long k=0;k<ls[s];k++)	for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+				r->a[i+nx*(j+ny*(sh+k))] = dat->v(i,j,pp+k);
+			sh += ls[s];
+		}
+	}
+	return r;
+}
+HMDT MGL_EXPORT mgl_data_section_val(HCDT dat, long id, char dir, mreal val)
+{	mglData v;	v.a[0]=id;	return mgl_data_section(dat,&v,dir,val);	}
+uintptr_t MGL_EXPORT mgl_data_section_(uintptr_t *d, uintptr_t *ids, const char *dir, mreal *val,int)
+{	return uintptr_t(mgl_data_section(_DT_,_DA_(ids),dir[0],*val));	}
+uintptr_t MGL_EXPORT mgl_data_section_val_(uintptr_t *d, int *id, const char *dir, mreal *val,int)
+{	return uintptr_t(mgl_data_section_val(_DT_,*id,dir[0],*val));	}
+//-----------------------------------------------------------------------------
diff --git a/src/data_gr.cpp b/src/data_gr.cpp
new file mode 100644
index 0000000..4fbc2f4
--- /dev/null
+++ b/src/data_gr.cpp
@@ -0,0 +1,131 @@
+/***************************************************************************
+ * data_gr.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <ctype.h>
+
+#ifndef WIN32
+#include <glob.h>
+#endif
+
+#include "mgl2/datac.h"
+#include "mgl2/evalc.h"
+#include "mgl2/thread.h"
+#include "mgl2/base.h"
+//-----------------------------------------------------------------------------
+HMDT MGL_NO_EXPORT mglFormulaCalc(const char *str, const std::vector<mglDataA*> &head);
+HADT MGL_NO_EXPORT mglFormulaCalcC(const char *str, const std::vector<mglDataA*> &head);
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_refill_gr(HMGL gr, HMDT dat, HCDT xdat, HCDT ydat, HCDT zdat, HCDT vdat, long sl, const char *opt)
+{
+	if(!vdat)	return;
+	gr->SaveState(opt);
+	if(!ydat && !zdat)	mgl_data_refill_x(dat,xdat,vdat,gr->Min.x,gr->Max.x,sl);
+//	else if(!xdat && !zdat)	mgl_data_refill_x(dat,ydat,vdat,gr->Min.y,gr->Max.y,sl);
+//	else if(!xdat && !ydat)	mgl_data_refill_x(dat,zdat,vdat,gr->Min.z,gr->Max.z,sl);
+	else if(!zdat)	mgl_data_refill_xy(dat,xdat,ydat,vdat,gr->Min.x,gr->Max.x,gr->Min.y,gr->Max.y,sl);
+//	else if(!ydat)	mgl_data_refill_xy(dat,xdat,zdat,vdat,gr->Min.x,gr->Max.x,gr->Min.z,gr->Max.z,sl);
+//	else if(!xdat)	mgl_data_refill_xy(dat,ydat,zdat,vdat,gr->Min.y,gr->Max.y,gr->Min.z,gr->Max.z,sl);
+	else	mgl_data_refill_xyz(dat,xdat,ydat,zdat,vdat,gr->Min.x,gr->Max.x,gr->Min.y,gr->Max.y,gr->Min.z,gr->Max.z);
+	gr->LoadState();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_refill_gr(HMGL gr, HADT dat, HCDT xdat, HCDT ydat, HCDT zdat, HCDT vdat, long sl, const char *opt)
+{
+	if(!vdat)	return;
+	gr->SaveState(opt);
+	if(!ydat && !zdat)	mgl_datac_refill_x(dat,xdat,vdat,gr->Min.x,gr->Max.x,sl);
+//	else if(!xdat && !zdat)	mgl_datac_refill_x(dat,ydat,vdat,gr->Min.y,gr->Max.y,sl);
+//	else if(!xdat && !ydat)	mgl_datac_refill_x(dat,zdat,vdat,gr->Min.z,gr->Max.z,sl);
+	else if(!zdat)	mgl_datac_refill_xy(dat,xdat,ydat,vdat,gr->Min.x,gr->Max.x,gr->Min.y,gr->Max.y,sl);
+//	else if(!ydat)	mgl_datac_refill_xy(dat,xdat,zdat,vdat,gr->Min.x,gr->Max.x,gr->Min.z,gr->Max.z,sl);
+//	else if(!xdat)	mgl_datac_refill_xy(dat,ydat,zdat,vdat,gr->Min.y,gr->Max.y,gr->Min.z,gr->Max.z,sl);
+	else	mgl_datac_refill_xyz(dat,xdat,ydat,zdat,vdat,gr->Min.x,gr->Max.x,gr->Min.y,gr->Max.y,gr->Min.z,gr->Max.z);
+	gr->LoadState();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_refill_x_(uintptr_t *d, uintptr_t *xdat, uintptr_t *vdat, mreal *x1, mreal *x2, long *sl)
+{	mgl_data_refill_x(_DT_,_DA_(xdat),_DA_(vdat),*x1,*x2,*sl);	}
+void MGL_EXPORT mgl_data_refill_xy_(uintptr_t *d, uintptr_t *xdat, uintptr_t *ydat, uintptr_t *vdat, mreal *x1, mreal *x2, mreal *y1, mreal *y2, long *sl)
+{	mgl_data_refill_xy(_DT_,_DA_(xdat),_DA_(ydat),_DA_(vdat),*x1,*x2,*y1,*y2,*sl);	}
+void MGL_EXPORT mgl_data_refill_xyz_(uintptr_t *d, uintptr_t *xdat, uintptr_t *ydat, uintptr_t *zdat, uintptr_t *vdat, mreal *x1, mreal *x2, mreal *y1, mreal *y2, mreal *z1, mreal *z2)
+{	mgl_data_refill_xyz(_DT_,_DA_(xdat),_DA_(ydat),_DA_(zdat),_DA_(vdat),*x1,*x2,*y1,*y2,*z1,*z2);	}
+void MGL_EXPORT mgl_data_refill_gr_(uintptr_t *gr, uintptr_t *d, uintptr_t *xdat, uintptr_t *ydat, uintptr_t *zdat, uintptr_t *vdat, long *sl, const char *opt,int l)
+{	char *s=new char[l+1];	memcpy(s,opt,l);	s[l]=0;
+	mgl_data_refill_gr(_GR_,_DT_,_DA_(xdat),_DA_(ydat),_DA_(zdat),_DA_(vdat),*sl,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_refill_x_(uintptr_t *d, uintptr_t *xdat, uintptr_t *vdat, mreal *x1, mreal *x2, long *sl)
+{	mgl_datac_refill_x(_DC_,_DA_(xdat),_DA_(vdat),*x1,*x2,*sl);	}
+void MGL_EXPORT mgl_datac_refill_xy_(uintptr_t *d, uintptr_t *xdat, uintptr_t *ydat, uintptr_t *vdat, mreal *x1, mreal *x2, mreal *y1, mreal *y2, long *sl)
+{	mgl_datac_refill_xy(_DC_,_DA_(xdat),_DA_(ydat),_DA_(vdat),*x1,*x2,*y1,*y2,*sl);	}
+void MGL_EXPORT mgl_datac_refill_xyz_(uintptr_t *d, uintptr_t *xdat, uintptr_t *ydat, uintptr_t *zdat, uintptr_t *vdat, mreal *x1, mreal *x2, mreal *y1, mreal *y2, mreal *z1, mreal *z2)
+{	mgl_datac_refill_xyz(_DC_,_DA_(xdat),_DA_(ydat),_DA_(zdat),_DA_(vdat),*x1,*x2,*y1,*y2,*z1,*z2);	}
+void MGL_EXPORT mgl_datac_refill_gr_(uintptr_t *gr, uintptr_t *d, uintptr_t *xdat, uintptr_t *ydat, uintptr_t *zdat, uintptr_t *vdat, long *sl, const char *opt,int l)
+{	char *s=new char[l+1];	memcpy(s,opt,l);	s[l]=0;
+	mgl_datac_refill_gr(_GR_,_DC_,_DA_(xdat),_DA_(ydat),_DA_(zdat),_DA_(vdat),*sl,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_fill_eq(HMGL gr, HMDT d, const char *eq, HCDT vdat, HCDT wdat, const char *opt)
+{
+	if(vdat && vdat->GetNN()!=d->GetNN())	return;	// incompatible dimensions
+	if(wdat && wdat->GetNN()!=d->GetNN())	return;
+	gr->SaveState(opt);
+	std::wstring s = d->s;	d->s = L"u";
+	mglDataV x(d->nx,d->ny,d->nz, gr->Min.x,gr->Max.x,'x');	x.s=L"x";
+	mglDataV y(d->nx,d->ny,d->nz, gr->Min.y,gr->Max.y,'y');	y.s=L"y";
+	mglDataV z(d->nx,d->ny,d->nz, gr->Min.z,gr->Max.z,'z');	z.s=L"z";
+	mglDataV i(d->nx,d->ny,d->nz, 0,d->nx-1,'x');	i.s=L"i";
+	mglDataV j(d->nx,d->ny,d->nz, 0,d->ny-1,'y');	j.s=L"j";
+	mglDataV k(d->nx,d->ny,d->nz, 0,d->nz-1,'z');	k.s=L"k";
+	mglDataV r(d->nx,d->ny,d->nz);	r.s=L"#$mgl";
+	mglData v(vdat), w(wdat);	v.s = L"v";	w.s = L"w";
+	std::vector<mglDataA*> list;
+	list.push_back(&x);	list.push_back(&y);	list.push_back(&z);	list.push_back(&r);
+	list.push_back(d);	list.push_back(&v);	list.push_back(&w);
+	list.push_back(&i);	list.push_back(&j);	list.push_back(&k);
+	d->Move(mglFormulaCalc(eq,list));	d->s = s;	gr->LoadState();
+}
+void MGL_EXPORT mgl_data_fill_eq_(uintptr_t *gr, uintptr_t *d, const char *eq, uintptr_t *v, uintptr_t *w, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,eq,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_data_fill_eq(_GR_,_DT_,s,_DA_(v),_DA_(w),o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_fill_eq(HMGL gr, HADT d, const char *eq, HCDT vdat, HCDT wdat, const char *opt)
+{
+	if(vdat && vdat->GetNN()!=d->GetNN())	return;	// incompatible dimensions
+	if(wdat && wdat->GetNN()!=d->GetNN())	return;
+	gr->SaveState(opt);
+	std::wstring s = d->s;	d->s = L"u";
+	mglDataV x(d->nx,d->ny,d->nz, gr->Min.x,gr->Max.x,'x');	x.s=L"x";
+	mglDataV y(d->nx,d->ny,d->nz, gr->Min.y,gr->Max.y,'y');	y.s=L"y";
+	mglDataV z(d->nx,d->ny,d->nz, gr->Min.z,gr->Max.z,'z');	z.s=L"z";
+	mglDataV i(d->nx,d->ny,d->nz, 0,d->nx-1,'x');	i.s=L"i";
+	mglDataV j(d->nx,d->ny,d->nz, 0,d->ny-1,'y');	j.s=L"j";
+	mglDataV k(d->nx,d->ny,d->nz, 0,d->nz-1,'z');	k.s=L"k";
+	mglDataV r(d->nx,d->ny,d->nz);	r.s=L"#$mgl";
+	mglData v(vdat), w(wdat);	v.s = L"v";	w.s = L"w";
+	std::vector<mglDataA*> list;
+	list.push_back(&x);	list.push_back(&y);	list.push_back(&z);	list.push_back(&r);
+	list.push_back(d);	list.push_back(&v);	list.push_back(&w);
+	list.push_back(&i);	list.push_back(&j);	list.push_back(&k);
+	d->Move(mglFormulaCalcC(eq,list));	d->s = s;	gr->LoadState();
+}
+void MGL_EXPORT mgl_datac_fill_eq_(uintptr_t *gr, uintptr_t *d, const char *eq, uintptr_t *v, uintptr_t *w, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,eq,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_datac_fill_eq(_GR_,_DC_,s,_DA_(v),_DA_(w),o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
diff --git a/src/data_io.cpp b/src/data_io.cpp
new file mode 100644
index 0000000..9633eb7
--- /dev/null
+++ b/src/data_io.cpp
@@ -0,0 +1,1408 @@
+/***************************************************************************
+ * data_io.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <ctype.h>
+
+#ifndef WIN32
+#include <glob.h>
+#endif
+
+#include "mgl2/data.h"
+#include "mgl2/datac.h"
+#include "mgl2/eval.h"
+#include "mgl2/thread.h"
+
+#if MGL_HAVE_HDF5
+//#define H5_NO_DEPRECATED_SYMBOLS
+#define H5_USE_16_API
+#include <hdf5.h>
+#endif
+#if MGL_HAVE_HDF4
+#define intf hdf4_intf
+#include <hdf/mfhdf.h>
+#undef intf
+#endif
+
+inline bool isn(char ch)	{return ch=='\n';}
+HMDT MGL_NO_EXPORT mglFormulaCalc(const char *str, const std::vector<mglDataA*> &head);
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_create_data()	{	return new mglData;	}
+HMDT MGL_EXPORT mgl_create_data_size(long nx, long ny, long nz){	return new mglData(nx,ny,nz);	}
+HMDT MGL_EXPORT mgl_create_data_file(const char *fname)		{	return new mglData(fname);	}
+void MGL_EXPORT mgl_delete_data(HMDT d)	{	if(d)	delete d;	}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_create_data_()
+{	return uintptr_t(new mglData());	}
+uintptr_t MGL_EXPORT mgl_create_data_size_(int *nx, int *ny, int *nz)
+{	return uintptr_t(new mglData(*nx,*ny,*nz));	}
+uintptr_t MGL_EXPORT mgl_create_data_file_(const char *fname,int l)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	uintptr_t r = uintptr_t(new mglData(s));	delete []s;	return r;	}
+void MGL_EXPORT mgl_delete_data_(uintptr_t *d)
+{	if(_DT_)	delete _DT_;	}
+//-----------------------------------------------------------------------------
+void mglFromStr(HMDT d,char *buf,long NX,long NY,long NZ)
+{
+	if(NX<1 || NY <1 || NZ<1)	return;
+	mgl_data_create(d, NX,NY,NZ);
+	const std::string loc = setlocale(LC_NUMERIC, "C");
+	std::vector<char *> lines;
+	std::vector<std::vector<mreal> > numbs;
+	lines.push_back(buf);
+	for(char *s=buf; *s; s++)	if(isn(*s))
+	{	lines.push_back(s+1);	*s = 0;	s++;	}
+	numbs.resize(lines.size());
+	long nl = long(lines.size());
+#pragma omp parallel for
+	for(long k=0;k<nl;k++)
+	{
+		char *b = lines[k];
+		long nb = strlen(b);
+		for(long j=0;j<nb;j++)
+		{
+			while(j<nb && b[j]<=' ')	j++;	// skip first spaces
+			if(j>=nb)	break;
+			if(b[j]=='#')
+			{
+				if(j<nb-1 && b[j+1]=='#')	for(long i=j+2;i<nb;i++)
+					if(b[i]>='a' && b[i]<='z')	d->id.push_back(b[i]);
+				break;
+			}
+			const char *s=b+j;
+			while(j<nb && b[j]>' ' && b[j]!=',' && b[j]!=';')	j++;
+			b[j]=0;
+			numbs[k].push_back(strstr(s,"NAN")?NAN:atof(s));
+		}
+	}
+	long i=0, n=NX*NY*NZ;
+	for(long k=0;k<nl && i<n;k++)
+	{
+		const std::vector<mreal> &vals = numbs[k];
+		long c = vals.size();
+		if(c>n-i)	c = n-i;
+		memcpy(d->a+i,&(vals[0]),c*sizeof(mreal));
+		i += c;
+	}
+	setlocale(LC_NUMERIC, loc.c_str());
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_set(HMDT d, HCDT a)
+{
+	if(!a)	return;
+//	d->temp = a->temp;	d->s = a->s;	d->func = a->func;	d->o = a->o;
+
+	mgl_data_create(d, a->GetNx(), a->GetNy(), a->GetNz());
+	const mglData *dd = dynamic_cast<const mglData *>(a);	// faster for mglData
+	if(dd)	// this one should be much faster
+		memcpy(d->a, dd->a, d->nx*d->ny*d->nz*sizeof(mreal));
+	else	// very inefficient!!!
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<d->nz;k++)	for(long j=0;j<d->ny;j++)	for(long i=0;i<d->nx;i++)
+			d->a[i+d->nx*(j+d->ny*k)] = a->v(i,j,k);
+}
+void MGL_EXPORT mgl_data_set_(uintptr_t *d, uintptr_t *a)	{	mgl_data_set(_DT_,_DA_(a));	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_set_values(HMDT d, const char *v,long NX,long NY,long NZ)
+{
+	if(NX<1 || NY <1 || NZ<1)	return;
+	long n=strlen(v)+1;
+	char *buf = new char[n];
+	memcpy(buf,v,n);
+	mglFromStr(d,buf,NX,NY,NZ);
+	delete []buf;
+}
+void MGL_EXPORT mgl_data_set_values_(uintptr_t *d, const char *val, int *nx, int *ny, int *nz, int l)
+{	char *s=new char[l+1];	memcpy(s,val,l);	s[l]=0;
+	mgl_data_set_values(_DT_,s,*nx,*ny,*nz);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_set_vector(HMDT d, gsl_vector *v)
+{
+#if MGL_HAVE_GSL
+	if(!v || v->size<1)	return;
+	mgl_data_create(d, v->size,1,1);
+#pragma omp parallel for
+	for(long i=0;i<d->nx;i++)	d->a[i] = v->data[i*v->stride];
+#endif
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_set_matrix(HMDT d, gsl_matrix *m)
+{
+#if MGL_HAVE_GSL
+	if(!m || m->size1<1 || m->size2<1)	return;
+	mgl_data_create(d, m->size1,m->size2,1);
+#pragma omp parallel for collapse(2)
+	for(long j=0;j<d->ny;j++)	for(long i=0;i<d->nx;i++)
+		d->a[i+j*d->nx] = m->data[i * m->tda + j];
+#endif
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_set_float(HMDT d, const float *A,long NX,long NY,long NZ)
+{
+	if(NX<=0 || NY<=0 || NZ<=0)	return;
+	mgl_data_create(d, NX,NY,NZ);	if(!A)	return;
+#if MGL_USE_DOUBLE
+#pragma omp parallel for
+	for(long i=0;i<NX*NY*NZ;i++)	d->a[i] = A[i];
+#else
+	memcpy(d->a,A,NX*NY*NZ*sizeof(float));
+#endif
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_set_double(HMDT d, const double *A,long NX,long NY,long NZ)
+{
+	if(NX<=0 || NY<=0 || NZ<=0)	return;
+	mgl_data_create(d, NX,NY,NZ);	if(!A)	return;
+#if MGL_USE_DOUBLE
+	memcpy(d->a,A,NX*NY*NZ*sizeof(double));
+#else
+#pragma omp parallel for
+	for(long i=0;i<NX*NY*NZ;i++)	d->a[i] = A[i];
+#endif
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_set_float2(HMDT d, float const * const *A,long N1,long N2)
+{
+	if(N1<=0 || N2<=0)	return;
+	mgl_data_create(d, N2,N1,1);	if(!A)	return;
+#if MGL_USE_DOUBLE
+#pragma omp parallel for collapse(2)
+	for(long i=0;i<N1;i++)	for(long j=0;j<N2;j++)	d->a[j+i*N2] = A[i][j];
+#else
+#pragma omp parallel for
+	for(long i=0;i<N1;i++)	memcpy(d->a+i*N2,A[i],N2*sizeof(float));
+#endif
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_set_double2(HMDT d, double const *const *A,long N1,long N2)
+{
+	if(N1<=0 || N2<=0)	return;
+	mgl_data_create(d, N2,N1,1);	if(!A)	return;
+#if MGL_USE_DOUBLE
+#pragma omp parallel for
+	for(long i=0;i<N1;i++)	memcpy(d->a+i*N2,A[i],N2*sizeof(double));
+#else
+#pragma omp parallel for collapse(2)
+	for(long i=0;i<N1;i++)	for(long j=0;j<N2;j++)	d->a[j+i*N2] = A[i][j];
+#endif
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_set_float3(HMDT d, float const * const * const *A,long N1,long N2,long N3)
+{
+	if(N1<=0 || N2<=0 || N3<=0)	return;
+	mgl_data_create(d, N3,N2,N1);	if(!A)	return;
+#if MGL_USE_DOUBLE
+#pragma omp parallel for collapse(3)
+	for(long i=0;i<N1;i++)	for(long j=0;j<N2;j++)	for(long k=0;k<N3;k++)
+		d->a[k+N3*(j+i*N2)] = A[i][j][k];
+#else
+#pragma omp parallel for collapse(2)
+	for(long i=0;i<N1;i++)	for(long j=0;j<N2;j++)
+		memcpy(d->a+N3*(j+i*N2),A[i][j],N3*sizeof(float));
+#endif
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_set_double3(HMDT d, double const * const * const *A,long N1,long N2,long N3)
+{
+	if(N1<=0 || N2<=0 || N3<=0)	return;
+	mgl_data_create(d, N3,N2,N1);	if(!A)	return;
+#if MGL_USE_DOUBLE
+#pragma omp parallel for collapse(2)
+	for(long i=0;i<N1;i++)	for(long j=0;j<N2;j++)
+		memcpy(d->a+N3*(j+i*N2),A[i][j],N3*sizeof(double));
+#else
+#pragma omp parallel for collapse(3)
+	for(long i=0;i<N1;i++)	for(long j=0;j<N2;j++)	for(long k=0;k<N3;k++)
+		d->a[k+N3*(j+i*N2)] = A[i][j][k];
+#endif
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_set_float1_(uintptr_t *d, const float *A,int *NX)
+{	mgl_data_set_float(_DT_,A,*NX,1,1);	}
+void MGL_EXPORT mgl_data_set_double1_(uintptr_t *d, const double *A,int *NX)
+{	mgl_data_set_double(_DT_,A,*NX,1,1);	}
+void MGL_EXPORT mgl_data_set_float_(uintptr_t *d, const float *A,int *NX,int *NY,int *NZ)
+{	mgl_data_set_float(_DT_,A,*NX,*NY,*NZ);	}
+void MGL_EXPORT mgl_data_set_double_(uintptr_t *d, const double *A,int *NX,int *NY,int *NZ)
+{	mgl_data_set_double(_DT_,A,*NX,*NY,*NZ);	}
+void MGL_EXPORT mgl_data_set_float2_(uintptr_t *d, const float *A,int *N1,int *N2)
+{	mgl_data_set_float(_DT_,A,*N1,*N2,1);	}
+void MGL_EXPORT mgl_data_set_double2_(uintptr_t *d, const double *A,int *N1,int *N2)
+{	mgl_data_set_double(_DT_,A,*N1,*N2,1);	}
+void MGL_EXPORT mgl_data_set_float3_(uintptr_t *d, const float *A,int *N1,int *N2,int *N3)
+{	mgl_data_set_float(_DT_,A,*N1,*N2,*N3);	}
+void MGL_EXPORT mgl_data_set_double3_(uintptr_t *d, const double *A,int *N1,int *N2,int *N3)
+{	mgl_data_set_double(_DT_,A,*N1,*N2,*N3);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_rearrange(HMDT d, long mx,long my,long mz)
+{
+	if(mx<1)	return;	// wrong mx
+	if(my<1)	{	my = d->nx*d->ny*d->nz/mx;	mz = 1;	}
+	else if(mz<1)	mz = (d->nx*d->ny*d->nz)/(mx*my);
+	long m = mx*my*mz;
+	if(m==0 || m>d->nx*d->ny*d->nz)	return;	// too high desired dimensions
+	d->nx = mx;	d->ny = my;	d->nz = mz;	d->NewId();
+}
+void MGL_EXPORT mgl_data_rearrange_(uintptr_t *d, int *mx, int *my, int *mz)
+{	mgl_data_rearrange(_DT_,*mx,*my,*mz);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_set_id(HMDT d, const char *ids)	{	d->id = ids;	}
+void MGL_EXPORT mgl_data_set_id_(uintptr_t *d, const char *eq,int l)
+{	char *s=new char[l+1];	memcpy(s,eq,l);	s[l]=0;
+	mgl_data_set_id(_DT_, s);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_set_name_w(mglDataA *dat, const wchar_t *name)
+{	dat->s = name;	}
+void MGL_EXPORT mgl_data_set_name(mglDataA *dat, const char *name)
+{	MGL_TO_WCS(name,dat->s = wcs);	}
+void MGL_EXPORT mgl_data_set_name_(uintptr_t *d, const char *name,int l)
+{	char *s=new char[l+1];	memcpy(s,name,l);	s[l]=0;
+	mgl_data_set_name(_DT_,s);		delete []s;	}
+void MGL_EXPORT mgl_data_set_func(mglDataA *dat, void (*func)(void *), void *par)
+{	dat->func = func;	dat->o = par;	}
+//-----------------------------------------------------------------------------
+/// Get section separated by symbol ch. This is analog of QString::section().
+std::vector<std::string> MGL_EXPORT mgl_str_args(const std::string &str, char ch)
+{
+	std::vector<size_t> pos;	pos.push_back(0);
+	for(size_t p=0; p != std::string::npos;)
+	{	p=str.find(ch,p+1);	pos.push_back(p?p+1:0);	}
+	std::vector<std::string> res;
+	for(size_t i=0;i<pos.size()-1;i++)
+		res.push_back(str.substr(pos[i],pos[i+1]-pos[i]-1));
+	return res;
+}
+//-----------------------------------------------------------------------------
+/// Get section separated by symbol ch. This is analog of QString::section().
+std::string MGL_EXPORT mgl_str_arg(const std::string &str, char ch, int n1, int n2)
+{
+	std::vector<size_t> pos;	pos.push_back(0);
+	for(size_t p=0; p != std::string::npos;)
+	{	p=str.find(ch,p+1);	pos.push_back(p?p+1:0);	}
+	std::string res;
+	if(n2<0)	n2=n1;
+	if(n1<0 || n1>=pos.size()-1 || n2<n1)	return res;
+	if(n2>=pos.size())	n2=pos.size()-1;
+	res = str.substr(pos[n1],pos[n2+1]-pos[n1]-1);
+	if(res.size()==1 && res[0]==ch)	res.clear();
+	return res;
+}
+//-----------------------------------------------------------------------------
+/// Get string from number.
+std::string MGL_EXPORT mgl_str_num(double val)
+{	char buf[32];	snprintf(buf,32,"%g",val);	return std::string(buf);	}
+std::string MGL_EXPORT mgl_str_num(dual val)
+{
+	char buf[64];
+	double re = real(val), im = imag(val);
+	if(re==0 && im>0)	snprintf(buf,64,"i%g",im);
+	else if(re && im<0)	snprintf(buf,64,"-i%g",-im);
+	else if(im>0)	snprintf(buf,64,"%g+i%g",re,im);
+	else if(im<0)	snprintf(buf,64,"%g-i%g",re,-im);
+	else	snprintf(buf,64,"%g",re);
+	return std::string(buf);
+}
+//-----------------------------------------------------------------------------
+std::string MGL_EXPORT mgl_data_to_string(HCDT d, long ns)
+{
+	long nx=d->GetNx(), ny=d->GetNy(), nz=d->GetNz();
+	const std::string loc = setlocale(LC_NUMERIC, "C");
+	std::string out;
+	if(ns<0 || (ns>=nz && nz>1))	for(long k=0;k<nz;k++)
+	{	// save whole data
+		const mglData *dr = dynamic_cast<const mglData *>(d);
+		if(dr && !dr->id.empty())	out += "## "+dr->id+'\n';
+		for(long i=0;i<ny;i++)
+		{
+			for(long j=0;j<nx-1;j++)	out += mgl_str_num(d->v(j,i,k))+'\t';
+			out += mgl_str_num(d->v(nx-1,i,k))+'\n';
+		}
+		out += "\n";
+	}
+	else
+	{	// save selected slice
+		if(nz>1)	for(long i=0;i<ny;i++)
+		{
+			for(long j=0;j<nx-1;j++)	out += mgl_str_num(d->v(j,i,ns))+'\t';
+			out += mgl_str_num(d->v(nx-1,i,ns))+'\n';
+		}
+		else if(ns<ny)	for(long j=0;j<nx;j++)	out += mgl_str_num(d->v(j,ns))+'\t';
+	}
+	setlocale(LC_NUMERIC, loc.c_str());
+	return out;
+}
+void MGL_EXPORT mgl_data_save(HCDT d, const char *fname,long ns)
+{
+	FILE *fp = fopen(fname,"w");
+	if(fp)	{	fprintf(fp,"%s",mgl_data_to_string(d,ns).c_str());	fclose(fp);	}
+}
+void MGL_EXPORT mgl_data_save_(uintptr_t *d, const char *fname,int *ns,int l)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	mgl_data_save(_DT_,s,*ns);		delete []s;	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT char *mgl_read_gz(gzFile fp)
+{
+	long size=1024,n=0,m;
+	char *buf=(char*)malloc(size);
+	while((m=gzread(fp,buf+size*n,size))>0)
+	{
+		if(m<size)	{	buf[size*n+m]=0;	break;	}
+		n++;		buf=(char*)realloc(buf,size*(n+1));
+		memset(buf+size*n,0,size);
+	}
+	return buf;
+}
+//-----------------------------------------------------------------------------
+int MGL_EXPORT mgl_data_read(HMDT d, const char *fname)
+{
+	long l=1,m=1,k=1,i;
+	gzFile fp = gzopen(fname,"r");
+	if(!fp)
+	{
+		if(!d->a)	mgl_data_create(d, 1,1,1);
+		return	0;
+	}
+	char *buf = mgl_read_gz(fp);
+	long nb = strlen(buf);	gzclose(fp);
+
+	bool first=false;
+	for(i=nb-1;i>=0;i--)	if(buf[i]>' ')	break;
+	buf[i+1]=0;	nb = i+1;		// remove tailing spaces
+	for(i=0;i<nb-1 && !isn(buf[i]);i++)	// determine nx
+	{
+		while(buf[i]=='#')	{	while(!isn(buf[i]) && i<nb)	i++;	}
+		char ch = buf[i];
+		if(ch>' ' && !first)	first=true;
+		if(first && (ch==' ' || ch=='\t' || ch==',' || ch==';') && buf[i+1]>' ') k++;
+	}
+	first = false;
+	for(i=0;i<nb-1;i++)					// determine ny
+	{
+		char ch = buf[i];
+		if(ch=='#')	while(!isn(buf[i]) && i<nb)	i++;
+		if(isn(ch))
+		{
+			while(buf[i+1]==' ' || buf[i+1]=='\t') i++;
+			if(isn(buf[i+1]))	{first=true;	break;	}
+			m++;
+		}
+		if(ch=='\f')	break;
+	}
+	if(first)	for(i=0;i<nb-1;i++)		// determine nz
+	{
+		char ch = buf[i];
+		if(ch=='#')	while(!isn(buf[i]) && i<nb)	i++;
+		if(isn(ch))
+		{
+			while(buf[i+1]==' ' || buf[i+1]=='\t') i++;
+			if(isn(buf[i+1]))	l++;
+		}
+	}
+	else	for(i=0;i<nb-1;i++)	if(buf[i]=='\f')	l++;
+	mglFromStr(d,buf,k,m,l);
+	free(buf);	return 1;
+}
+int MGL_EXPORT mgl_data_read_(uintptr_t *d, const char *fname,int l)
+{	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
+	int r = mgl_data_read(_DT_, s);	delete []s;		return r;	}
+//-----------------------------------------------------------------------------
+int MGL_EXPORT mgl_data_scan_file(HMDT d,const char *fname, const char *templ)
+{
+	// first scan for all "%g"
+	char *buf=new char[strlen(templ)+1],*s=buf;
+	strcpy(buf,templ);
+	std::vector<std::string> strs;
+	for(size_t i=0;buf[i];i++)
+	{
+		if(buf[i]=='%' && buf[i+1]=='%')	i++;
+		else if(buf[i]=='%' && buf[i+1]=='g')
+		{	buf[i]=0;	strs.push_back(s);	s = buf+i+2;	}
+	}
+	delete []buf;
+	if(strs.size()<1)	return 0;
+	// read proper lines from file
+	std::vector<const char *> bufs;
+	gzFile fp = gzopen(fname,"r");
+	if(!fp)
+	{
+		if(!d->a)	mgl_data_create(d, 1,1,1);
+		return	0;
+	}
+	s = mgl_read_gz(fp);	gzclose(fp);
+	size_t len = strs[0].length();
+	const char *s0 = strs[0].c_str();
+	if(!strncmp(s, s0, len))	bufs.push_back(s);
+	for(long i=0;s[i];i++)	if(s[i]=='\n')
+	{
+		while(s[i+1]=='\n')	i++;
+		s[i]=0;	i++;
+		if(!strncmp(s+i, s0, len))	bufs.push_back(s+i);
+		if(!s[i])	break;
+	}
+	// parse lines and collect data
+	size_t nx=strs.size(), ny=bufs.size();
+	if(ny<1)
+	{
+		if(!d->a)	mgl_data_create(d, 1,1,1);
+		return	0;
+	}
+	d->Create(nx,ny);
+	for(size_t j=0;j<ny;j++)
+	{
+		const char *c = bufs[j];
+		for(size_t i=0;i<nx;i++)
+		{
+			const char *p = strstr(c,strs[i].c_str());
+			if(!p)	break;
+			p += strs[i].length();	c=p;
+			d->a[i+nx*j] = atof(p);
+		}
+	}
+	free(s);	return 1;
+}
+int MGL_EXPORT mgl_data_scan_file_(uintptr_t *d,const char *fname, const char *templ,int l,int m)
+{	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
+	char *t=new char[m+1];		memcpy(t,templ,m);	t[m]=0;
+	int r = mgl_data_scan_file(_DT_, s,t);	delete []s;	delete []t;	return r;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_create(HMDT d,long mx,long my,long mz)
+{
+	d->nx = mx>0 ? mx:1;	d->ny = my>0 ? my:1;	d->nz = mz>0 ? mz:1;
+	if(d->a && !d->link)	delete [](d->a);
+	d->a = new mreal[d->nx*d->ny*d->nz];
+	d->id.clear();	d->link=false;
+	memset(d->a,0,d->nx*d->ny*d->nz*sizeof(mreal));
+}
+void MGL_EXPORT mgl_data_create_(uintptr_t *d, int *nx,int *ny,int *nz)
+{	mgl_data_create(_DT_,*nx,*ny,*nz);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_link(HMDT d, mreal *A, long mx,long my,long mz)
+{
+	if(!A)	return;
+	if(!d->link && d->a)	delete [](d->a);
+	d->nx = mx>0 ? mx:1;	d->ny = my>0 ? my:1;	d->nz = mz>0 ? mz:1;
+	d->link=true;	d->a=A;	d->NewId();
+}
+void MGL_EXPORT mgl_data_link_(uintptr_t *d, mreal *A, int *nx,int *ny,int *nz)
+{	mgl_data_link(_DT_,A,*nx,*ny,*nz);	}
+//-----------------------------------------------------------------------------
+int MGL_EXPORT mgl_data_read_dim(HMDT d, const char *fname,long mx,long my,long mz)
+{
+	if(mx<=0 || my<=0 || mz<=0)	return 0;
+	gzFile fp = gzopen(fname,"r");
+	if(!fp)	return 0;
+	char *buf = mgl_read_gz(fp);
+	gzclose(fp);
+	mglFromStr(d,buf,mx,my,mz);
+	free(buf);	return 1;
+}
+int MGL_EXPORT mgl_data_read_dim_(uintptr_t *d, const char *fname,int *mx,int *my,int *mz,int l)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	int r = mgl_data_read_dim(_DT_,s,*mx,*my,*mz);	delete []s;	return r;	}
+//-----------------------------------------------------------------------------
+int MGL_EXPORT mgl_data_read_mat(HMDT d, const char *fname, long dim)
+{
+	if(dim<=0 || dim>3)	return 0;
+	gzFile fp = gzopen(fname,"r");
+	if(!fp)	return 0;
+	long nx=1, ny=1, nz=1;
+	char *buf = mgl_read_gz(fp);
+	long nb = strlen(buf);	gzclose(fp);
+
+	long j=0;
+	if(buf[j]=='#')	while(!isn(buf[j]))	j++;	// skip comment
+	while(j<nb && buf[j]<=' ')	j++;
+	if(dim==1)
+	{
+		sscanf(buf+j,"%ld",&nx);
+		while(j<nb && buf[j]!='\n')	j++;
+		j++;
+//		while(buf[j]>' ')	j++;
+	}
+	else if(dim==2)
+	{
+		sscanf(buf+j,"%ld%ld",&nx,&ny);
+		while(j<nb && buf[j]!='\n')	j++;
+		j++;
+		char *b=buf+j;
+		long l=0;
+		for(long i=0;b[i];i++)
+		{
+			while(b[i]=='#')	{	while(!isn(b[i]) && b[i])	i++;	}
+			if(b[i]=='\n')	l++;
+		}
+		if(l==nx*ny || l==nx*ny+1)	// try to read 3d data (i.e. columns of matrix nx*ny)
+		{
+			nz=ny;	ny=nx;	nx=1;	l=0;
+			bool first = false;
+			for(long i=0;b[i] && !isn(b[i]);i++)	// determine nx
+			{
+				while(b[i]=='#')	{	while(!isn(b[i]) && b[i])	i++;	}
+				char ch = b[i];
+				if(ch>' ' && !first)	first=true;
+				if(first && (ch==' ' || ch=='\t' || ch==',' || ch==';') && b[i+1]>' ') nx++;
+			}
+		}
+	}
+	else if(dim==3)
+	{
+		sscanf(buf+j,"%ld%ld%ld",&nx,&ny,&nz);
+		while(j<nb && buf[j]!='\n')	j++;
+		j++;
+/*		while(buf[j]>' ' && j<nb)	j++;
+		while(buf[j]<=' ' && j<nb)	j++;
+		while(buf[j]>' ' && j<nb)	j++;
+		while(buf[j]<=' ' && j<nb)	j++;
+		while(buf[j]>' ' && j<nb)	j++;*/
+	}
+	mglFromStr(d,buf+j,nx,ny,nz);
+	free(buf);	return 1;
+}
+int MGL_EXPORT mgl_data_read_mat_(uintptr_t *d, const char *fname,int *dim,int l)
+{	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
+	int r = mgl_data_read_mat(_DT_,s,*dim);	delete []s;	return r;	}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_data_max(HCDT d)
+{
+	mreal m1=-INFINITY;
+	long nn=d->GetNN();
+#pragma omp parallel
+	{
+		mreal m=-INFINITY;
+#pragma omp for nowait
+		for(long i=0;i<nn;i++)
+		{	mreal v = d->vthr(i);	m = m<v ? v:m;	}
+#pragma omp critical(max_dat)
+		{	m1 = m1>m ? m1:m;	}
+	}
+	return m1;
+}
+mreal MGL_EXPORT mgl_data_max_(uintptr_t *d)	{	return mgl_data_max(_DT_);	}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_data_min(HCDT d)
+{
+	mreal m1=INFINITY;
+	long nn=d->GetNN();
+#pragma omp parallel
+	{
+		mreal m=INFINITY;
+#pragma omp for nowait
+		for(long i=0;i<nn;i++)
+		{	mreal v = d->vthr(i);	m = m>v ? v:m;	}
+#pragma omp critical(min_dat)
+		{	m1 = m1<m ? m1:m;	}
+	}
+	return m1;
+}
+mreal MGL_EXPORT mgl_data_min_(uintptr_t *d)	{	return mgl_data_min(_DT_);	}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_data_neg_max(HCDT d)
+{
+	mreal m1=0;
+	long nn=d->GetNN();
+#pragma omp parallel
+	{
+		mreal m=0;
+#pragma omp for nowait
+		for(long i=0;i<nn;i++)
+		{	mreal v = d->vthr(i);	m = m<v && v<0 ? v:m;	}
+#pragma omp critical(nmax_dat)
+		{	m1 = m1>m ? m1:m;	}
+	}
+	return m1;
+}
+mreal MGL_EXPORT mgl_data_neg_max_(uintptr_t *d)	{	return mgl_data_neg_max(_DT_);	}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_data_pos_min(HCDT d)
+{
+	mreal m1=INFINITY;
+	long nn=d->GetNN();
+#pragma omp parallel
+	{
+		mreal m=INFINITY;
+#pragma omp for nowait
+		for(long i=0;i<nn;i++)
+		{	mreal v = d->vthr(i);	m = m>v && v>0 ? v:m;	}
+#pragma omp critical(pmin_dat)
+		{	m1 = m1<m ? m1:m;	}
+	}
+	return m1;
+}
+mreal MGL_EXPORT mgl_data_pos_min_(uintptr_t *d)	{	return mgl_data_pos_min(_DT_);	}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_data_max_int(HCDT d, long *i, long *j, long *k)
+{
+	mreal m1=-INFINITY;
+	long nx=d->GetNx(), ny=d->GetNy(), nn=d->GetNN();
+#pragma omp parallel
+	{
+		mreal m=-INFINITY;
+		long im=-1,jm=-1,km=-1;
+#pragma omp for nowait
+		for(long ii=0;ii<nn;ii++)
+		{
+			mreal v = d->vthr(ii);
+			if(m < v)
+			{	m=v;	im=ii%nx;	jm=(ii/nx)%ny;	km=ii/(nx*ny);   }
+		}
+#pragma omp critical(max_int)
+		if(m1 < m)	{	m1=m;	*i=im;	*j=jm;	*k=km;   }
+	}
+	return m1;
+}
+mreal MGL_EXPORT mgl_data_max_int_(uintptr_t *d, int *i, int *j, int *k)
+{	long ii,jj,kk;	mreal res=mgl_data_max_int(_DT_,&ii,&jj,&kk);
+	*i=ii;	*j=jj;	*k=kk;	return res;	}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_data_min_int(HCDT d, long *i, long *j, long *k)
+{
+	mreal m1=INFINITY;
+	long nx=d->GetNx(), ny=d->GetNy(), nn=d->GetNN();
+#pragma omp parallel
+	{
+		mreal m=INFINITY;
+		long im=-1,jm=-1,km=-1;
+#pragma omp for nowait
+		for(long ii=0;ii<nn;ii++)
+		{
+			mreal v = d->vthr(ii);
+			if(m > v)
+			{	m=v;	im=ii%nx;	jm=(ii/nx)%ny;	km=ii/(nx*ny);   }
+		}
+#pragma omp critical(min_int)
+		if(m1 > m)	{	m1=m;	*i=im;	*j=jm;	*k=km;   }
+	}
+	return m1;
+}
+mreal MGL_EXPORT mgl_data_min_int_(uintptr_t *d, int *i, int *j, int *k)
+{	long ii,jj,kk;	mreal res=mgl_data_min_int(_DT_,&ii,&jj,&kk);
+	*i=ii;	*j=jj;	*k=kk;	return res;	}
+//-----------------------------------------------------------------------------
+long MGL_EXPORT mgl_data_max_first(HCDT d, char dir, long from, long *p1, long *p2)
+{
+	long n=d->GetNx(), n1=d->GetNy(), n2=d->GetNz(), d1=n, d2=n*n1, dd=1;
+	if(dir=='y')	{	n=n1;	n1=dd=d1;	d1=1;	}
+	if(dir=='z')	{	n=n2;	n2=n1;	n1=d1;	d1=1;	dd=d2;	d2=n2;	}
+	bool find=false;
+	if(from>=0)
+	{
+		for(long i=from+1;i<n-1;i++)
+		{
+#pragma omp parallel for collapse(2)
+			for(long i1=0;i1<n1;i1++)	for(long i2=0;i2<n2;i2++)
+			{
+				long ii=i*dd+i1*d1+i2*d2;
+				if(d->vthr(ii)>=d->vthr(ii+dd) && d->vthr(ii)>=d->vthr(ii-dd))
+				{	find=true;	if(p1)	*p1=i1;	if(p2)	*p2=i2;	}
+			}
+			if(find)	return i;
+		}
+	}
+	else
+	{
+		for(long i=n+from-1;i>0;i--)
+		{
+			for(long i1=0;i1<n1;i1++)	for(long i2=0;i2<n2;i2++)
+			{
+				long ii=i*dd+i1*d1+i2*d2;
+				if(d->vthr(ii)>=d->vthr(ii+dd) && d->vthr(ii)>=d->vthr(ii-dd))
+				{	find=true;	if(p1)	*p1=i1;	if(p2)	*p2=i2;	}
+			}
+			if(find)	return i;
+		}
+	}
+	return -1;
+}
+long MGL_EXPORT mgl_data_max_first_(uintptr_t *d, const char *dir, long *from, long *p1, long *p2,int)
+{	return mgl_data_max_first(_DT_,*dir,*from,p1,p2);	}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_data_max_real(HCDT d, mreal *x, mreal *y, mreal *z)
+{
+	long im=-1,jm=-1,km=-1;
+	long nx=d->GetNx(), ny=d->GetNy(), nz=d->GetNz();
+	mreal m=mgl_data_max_int(d,&im,&jm,&km), v, v1, v2;
+	*x=im;	*y=jm;	*z=km;
+
+	v = d->v(im,jm,km);
+	if(nx>2)
+	{
+		if(im==0)	im=1;
+		if(im==nx-1)im=nx-2;
+		v1 = d->v(im+1,jm,km);	v2 = d->v(im-1,jm,km);
+		*x = (v1+v2-2*v)==0 ? im : im+(v1-v2)/(v1+v2-2*v)/2;
+	}
+	if(ny>2)
+	{
+		if(jm==0)	jm=1;
+		if(jm==ny-1)jm=ny-2;
+		v1 = d->v(im,jm+1,km);	v2 = d->v(im,jm-1,km);
+		*y = (v1+v2-2*v)==0 ? jm : jm+(v1-v2)/(v1+v2-2*v)/2;
+	}
+	if(nz>2)
+	{
+		if(km==0)	km=1;
+		if(km==nz-1)km=nz-2;
+		v1 = d->v(im,jm,km+1);	v2 = d->v(im,jm,km-1);
+		*z = (v1+v2-2*v)==0 ? km : km+(v1-v2)/(v1+v2-2*v)/2;
+	}
+	return m;
+}
+mreal MGL_EXPORT mgl_data_max_real_(uintptr_t *d, mreal *x, mreal *y, mreal *z)
+{	return mgl_data_max_real(_DT_,x,y,z);	}
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_data_min_real(HCDT d, mreal *x, mreal *y, mreal *z)
+{
+	long im=-1,jm=-1,km=-1;
+	long nx=d->GetNx(), ny=d->GetNy(), nz=d->GetNz();
+	mreal m=mgl_data_min_int(d,&im,&jm,&km), v, v1, v2;
+	*x=im;	*y=jm;	*z=km;
+
+	v = d->v(im,jm,km);
+	if(nx>2)
+	{
+		if(im==0)	im=1;
+		if(im==nx-1)im=nx-2;
+		v1 = d->v(im+1,jm,km);	v2 = d->v(im-1,jm,km);
+		*x = (v1+v2-2*v)==0 ? im : im+(v1-v2)/(v1+v2-2*v)/2;
+	}
+	if(ny>2)
+	{
+		if(jm==0)	jm=1;
+		if(jm==ny-1)jm=ny-2;
+		v1 = d->v(im,jm+1,km);	v2 = d->v(im,jm-1,km);
+		*y = (v1+v2-2*v)==0 ? jm : jm+(v1-v2)/(v1+v2-2*v)/2;
+	}
+	if(nz>2)
+	{
+		if(km==0)	km=1;
+		if(km==nz-1)km=nz-2;
+		v1 = d->v(im,jm,km+1);	v2 = d->v(im,jm,km-1);
+		*z = (v1+v2-2*v)==0 ? km : km+(v1-v2)/(v1+v2-2*v)/2;
+	}
+	return m;
+}
+mreal MGL_EXPORT mgl_data_min_real_(uintptr_t *d, mreal *x, mreal *y, mreal *z)
+{	return mgl_data_min_real(_DT_,x,y,z);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_fill(HMDT d, mreal x1,mreal x2,char dir)
+{
+	if(mgl_isnan(x2))	x2=x1;
+	if(dir<'x' || dir>'z')	dir='x';
+	long nx=d->nx,ny=d->ny,nz=d->nz;
+	if(dir=='x')
+	{
+		mreal dx = d->nx>1 ? (x2-x1)/(d->nx-1):0;
+#pragma omp parallel for collapse(2)
+		for(long j=0;j<ny*nz;j++)	for(long i=1;i<nx;i++)	d->a[i+nx*j] = x1+dx*i;
+#pragma omp parallel for
+		for(long j=0;j<ny*nz;j++)	d->a[nx*j] = x1;
+	}
+	if(dir=='y')
+	{
+		mreal dx = d->ny>1 ? (x2-x1)/(d->ny-1):0;
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<nz;k++)	for(long j=1;j<ny;j++)	for(long i=0;i<nx;i++)	d->a[i+nx*(j+ny*k)] = x1+dx*j;
+#pragma omp parallel for collapse(2)
+		for(long j=0;j<nz;j++)	for(long i=0;i<nx;i++)	d->a[i+nx*ny*j] = x1;
+	}
+	if(dir=='z')
+	{
+		mreal dx = d->nz>1 ? (x2-x1)/(d->nz-1):0;
+#pragma omp parallel for collapse(2)
+		for(long j=1;j<nz;j++)	for(long i=0;i<nx*ny;i++)	d->a[i+nx*ny*j] = x1+dx*j;
+#pragma omp parallel for
+		for(long j=0;j<nx*ny;j++)	d->a[j] = x1;
+	}
+}
+void MGL_EXPORT mgl_data_fill_(uintptr_t *d, mreal *x1,mreal *x2,const char *dir,int)
+{	mgl_data_fill(_DT_,*x1,*x2,*dir);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_norm(HMDT d, mreal v1,mreal v2,int sym,long dim)
+{
+	long s,nn=d->nx*d->ny*d->nz;
+	mreal a1=INFINITY,a2=-INFINITY,v,*a=d->a;
+	s = dim*d->ny*(d->nz>1 ? d->nx : 1);
+	for(long i=s;i<nn;i++)	// determines borders of existing data
+	{	a1 = a1>a[i] ? a[i]:a1;	a2 = a2<a[i] ? a[i]:a2;	}
+	if(a1==a2)  {  if(a1!=0)	a1=0.;  else a2=1;  }
+	if(v1>v2)	{	v=v1;	v1=v2;	v2=v;	}	// swap if uncorrect
+	if(sym)				// use symmetric
+	{
+		v2 = -v1>v2 ? -v1:v2;	v1 = -v2;
+		a2 = -a1>a2 ? -a1:a2;	a1 = -a2;
+	}
+	v2 = (v2-v1)/(a2-a1);	v1 = v1-a1*v2;
+#pragma omp parallel for
+	for(long i=s;i<nn;i++)	a[i] = v1 + v2*a[i];
+}
+void MGL_EXPORT mgl_data_norm_(uintptr_t *d, mreal *v1,mreal *v2,int *sym,int *dim)
+{	mgl_data_norm(_DT_,*v1,*v2,*sym,*dim);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_squeeze(HMDT d, long rx,long ry,long rz,long smooth)
+{
+	long kx,ky,kz, nx=d->nx, ny=d->ny, nz=d->nz;
+	mreal *b;
+
+	// simple checking
+	if(rx>=nx)	rx=nx-1;
+	if(rx<1)	rx=1;
+	if(ry>=ny)	ry=ny-1;
+	if(ry<1)	ry=1;
+	if(rz>=nz)	rz=nz-1;
+	if(rz<1)	rz=1;
+	// new sizes
+	kx = 1+(nx-1)/rx;	ky = 1+(ny-1)/ry;	kz = 1+(nz-1)/rz;
+	b = new mreal[kx*ky*kz];
+	if(!smooth)
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<kz;k++)	for(long j=0;j<ky;j++)	for(long i=0;i<kx;i++)
+			b[i+kx*(j+ky*k)] = d->a[i*rx+nx*(j*ry+ny*rz*k)];
+	else
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<kz;k++)	for(long j=0;j<ky;j++)	for(long i=0;i<kx;i++)
+		{
+			long dx,dy,dz,i1,j1,k1;
+			dx = (i+1)*rx<=nx ? rx : nx-i*rx;
+			dy = (j+1)*ry<=ny ? ry : ny-j*ry;
+			dz = (k+1)*rz<=nz ? rz : nz-k*rz;
+			mreal s = 0;
+			for(k1=k*rz;k1<k*rz+dz;k1++)	for(j1=j*ry;j1<j*ry+dz;j1++)	for(i1=i*rx;i1<i*rx+dx;i1++)
+				s += d->a[i1+nx*(j1+ny*k1)];
+			b[i+kx*(j+ky*k)] = s/(dx*dy*dz);
+		}
+	if(!d->link)	delete [](d->a);
+	d->a=b;	d->nx = kx;  d->ny = ky;  d->nz = kz;	d->NewId();	d->link=false;
+}
+void MGL_EXPORT mgl_data_squeeze_(uintptr_t *d, int *rx,int *ry,int *rz,int *smooth)
+{	mgl_data_squeeze(_DT_,*rx,*ry,*rz,*smooth);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_extend(HMDT d, long n1, long n2)
+{
+	long nx=d->nx, ny=d->ny, nz=d->nz;
+	if(nz>2 || n1==0)	return;
+	long mx, my, mz;
+	mreal *b=0;
+	if(n1>0) // extend to higher dimension(s)
+	{
+		n2 = n2>0 ? n2:1;
+		mx = nx;	my = ny>1?ny:n1;	mz = ny>1 ? n1 : n2;
+		b = new mreal[mx*my*mz];
+		if(ny>1)
+#pragma omp parallel for
+			for(long i=0;i<n1;i++)	memcpy(b+i*nx*ny, d->a, nx*ny*sizeof(mreal));
+		else
+#pragma omp parallel for
+			for(long i=0;i<n1*n2;i++)	memcpy(b+i*nx, d->a, nx*sizeof(mreal));
+	}
+	else
+	{
+		mx = -n1;	my = n2<0 ? -n2 : nx;	mz = n2<0 ? nx : ny;
+		if(n2>0 && ny==1)	mz = n2;
+		b = new mreal[mx*my*mz];
+		if(n2<0)
+#pragma omp parallel for collapse(2)
+			for(long j=0;j<nx;j++)	for(long i=0;i<mx*my;i++)
+				b[i+mx*my*j] = d->a[j];
+		else
+#pragma omp parallel for collapse(2)
+			for(long j=0;j<nx*ny;j++)	for(long i=0;i<mx;i++)
+				b[i+mx*j] = d->a[j];
+		if(n2>0 && ny==1)
+#pragma omp parallel for
+			for(long i=0;i<n2;i++)
+				memcpy(b+i*mx*my, d->a, mx*my*sizeof(mreal));
+	}
+	if(!d->link)	delete [](d->a);
+	d->a=b;	d->nx=mx;	d->ny=my;	d->nz=mz;
+	d->NewId();		d->link=false;
+}
+void MGL_EXPORT mgl_data_extend_(uintptr_t *d, int *n1, int *n2)
+{	mgl_data_extend(_DT_,*n1,*n2);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_transpose(HMDT d, const char *dim)
+{
+	long nx=d->nx, ny=d->ny, nz=d->nz, n;
+	mreal *b=new mreal[nx*ny*nz], *a=d->a;
+	if(!strcmp(dim,"xyz"))	memcpy(b,a,nx*ny*nz*sizeof(mreal));
+	else if(!strcmp(dim,"xzy") || !strcmp(dim,"zy"))
+	{
+#pragma omp parallel for collapse(3)
+		for(long j=0;j<ny;j++)	for(long k=0;k<nz;k++)	for(long i=0;i<nx;i++)
+			b[i+nx*(k+nz*j)] = a[i+nx*(j+ny*k)];
+		n=nz;	nz=ny;	ny=n;
+	}
+	else if(!strcmp(dim,"yxz") || !strcmp(dim,"yx"))
+	{
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<nz;k++)	for(long i=0;i<nx;i++)	for(long j=0;j<ny;j++)
+			b[j+ny*(i+nx*k)] = a[i+nx*(j+ny*k)];
+		n=nx;	nx=ny;	ny=n;
+	}
+	else if(!strcmp(dim,"yzx"))
+	{
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<nz;k++)	for(long i=0;i<nx;i++)	for(long j=0;j<ny;j++)
+			b[j+ny*(k+nz*i)] = a[i+nx*(j+ny*k)];
+		n=nx;	nx=ny;	ny=nz;	nz=n;
+	}
+	else if(!strcmp(dim,"zxy"))
+	{
+#pragma omp parallel for collapse(3)
+		for(long i=0;i<nx;i++)	for(long j=0;j<ny;j++)	for(long k=0;k<nz;k++)
+			b[k+nz*(i+nx*j)] = a[i+nx*(j+ny*k)];
+		n=nx;	nx=nz;	nz=ny;	ny=n;
+	}
+	else if(!strcmp(dim,"zyx") || !strcmp(dim,"zx"))
+	{
+#pragma omp parallel for collapse(3)
+		for(long i=0;i<nx;i++)	for(long j=0;j<ny;j++)	for(long k=0;k<nz;k++)
+			b[k+nz*(j+ny*i)] = a[i+nx*(j+ny*k)];
+		n=nz;	nz=nx;	nx=n;
+	}
+	memcpy(a,b,nx*ny*nz*sizeof(mreal));	delete []b;
+	n=d->nx;	d->nx=nx;	d->ny=ny;	d->nz=nz;
+	if(nx!=n)	d->NewId();
+}
+void MGL_EXPORT mgl_data_transpose_(uintptr_t *d, const char *dim,int l)
+{	char *s=new char[l+1];	memcpy(s,dim,l);	s[l]=0;
+	mgl_data_transpose(_DT_,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_modify(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	const mglFormula *f = (const mglFormula *)(t->v);
+	long nx=t->p[0],ny=t->p[1],nz=t->p[2];
+	mreal *b=t->a, dx,dy,dz;
+	const mreal *v=t->b, *w=t->c;
+	dx=nx>1?1/(nx-1.):0;	dy=ny>1?1/(ny-1.):0;	dz=nz>1?1/(nz-1.):0;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i0=t->id;i0<t->n;i0+=mglNumThr)
+	{
+		long i=i0%nx, j=((i0/nx)%ny), k=i0/(nx*ny);
+		b[i0] = f->Calc(i*dx, j*dy, k*dz, b[i0], v?v[i0]:0, w?w[i0]:0);
+	}
+	return 0;
+}
+void MGL_EXPORT mgl_data_modify(HMDT d, const char *eq,long dim)
+{
+	long nx=d->nx, ny=d->ny, nz=d->nz, par[3]={nx,ny,nz};
+	if(dim<=0)	mgl_data_modify_vw(d,eq,0,0);	// fastes variant for whole array
+	else if(nz>1)	// 3D array
+	{
+		mglFormula f(eq);
+		par[2] -= dim;	if(par[2]<0)	par[2]=0;
+		mglStartThread(mgl_modify,0,nx*ny*par[2],d->a+nx*ny*dim,0,0,par,&f);
+	}
+	else		// 2D or 1D array
+	{
+		mglFormula f(eq);
+		par[1] -= dim;	if(par[1]<0)	par[1]=0;
+		mglStartThread(mgl_modify,0,nx*par[1],d->a+nx*dim,0,0,par,&f);
+	}
+}
+void MGL_EXPORT mgl_data_modify_(uintptr_t *d, const char *eq,int *dim,int l)
+{	char *s=new char[l+1];	memcpy(s,eq,l);	s[l]=0;
+	mgl_data_modify(_DT_,s,*dim);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_modify_vw(HMDT d, const char *eq,HCDT vdat,HCDT wdat)
+{
+	std::wstring s = d->s;	d->s = L"u";
+	mglDataV x(d->nx,d->ny,d->nz, 0,1,'x');	x.s=L"x";
+	mglDataV y(d->nx,d->ny,d->nz, 0,1,'y');	y.s=L"y";
+	mglDataV z(d->nx,d->ny,d->nz, 0,1,'z');	z.s=L"z";
+	mglDataV i(d->nx,d->ny,d->nz, 0,d->nx-1,'x');	i.s=L"i";
+	mglDataV j(d->nx,d->ny,d->nz, 0,d->ny-1,'y');	j.s=L"j";
+	mglDataV k(d->nx,d->ny,d->nz, 0,d->nz-1,'z');	k.s=L"k";
+	mglDataV r(d->nx,d->ny,d->nz);	r.s=L"#$mgl";
+	mglData v(vdat), w(wdat);	v.s = L"v";	w.s = L"w";
+	std::vector<mglDataA*> list;
+	list.push_back(&x);	list.push_back(&y);	list.push_back(&z);	list.push_back(d);
+	list.push_back(&v);	list.push_back(&w);	list.push_back(&r);
+	list.push_back(&i);	list.push_back(&j);	list.push_back(&k);
+	d->Move(mglFormulaCalc(eq,list));	d->s = s;
+}
+void MGL_EXPORT mgl_data_modify_vw_(uintptr_t *d, const char *eq, uintptr_t *v, uintptr_t *w,int l)
+{	char *s=new char[l+1];	memcpy(s,eq,l);	s[l]=0;
+	mgl_data_modify_vw(_DT_,s,_DA_(v),_DA_(w));	delete []s;	}
+//-----------------------------------------------------------------------------
+#if MGL_HAVE_HDF4
+int MGL_EXPORT mgl_data_read_hdf4(HMDT d,const char *fname,const char *data)
+{
+	int32 sd = SDstart(fname,DFACC_READ), nn, i;
+	if(sd==-1)	return 0;	// is not a HDF4 file
+	char name[64];
+	SDfileinfo(sd,&nn,&i);
+	for(i=0;i<nn;i++)
+	{
+		int32 sds, rank, dims[32], type, attr, in[2]={0,0};
+		sds = SDselect(sd,i);
+		SDgetinfo(sds,name,&rank,dims,&type,&attr);
+		if(!strcmp(name,data))	// as I understand there are possible many datas with the same name
+		{
+			if(rank==1)			{	dims[2]=dims[0];	dims[0]=dims[1]=1;	}
+			else if(rank==2)	{	dims[2]=dims[1];	dims[1]=dims[0];	dims[0]=1;	}
+//			else if(rank>3)		continue;
+			long mm=dims[0]*dims[1]*dims[2];
+			if(type==DFNT_FLOAT32)
+			{
+				float *b = new float[mm];
+				SDreaddata(sds,in,0,dims,b);
+				mgl_data_set_float(d,b,dims[2],dims[1],dims[0]);
+				delete []b;
+			}
+			if(type==DFNT_FLOAT64)
+			{
+				double *b = new double[mm];
+				SDreaddata(sds,in,0,dims,b);
+				mgl_data_set_double(d,b,dims[2],dims[1],dims[0]);
+				delete []b;
+			}
+		}
+		SDendaccess(sds);
+	}
+	SDend(sd);
+	return 1;
+}
+#else
+int MGL_EXPORT mgl_data_read_hdf4(HMDT ,const char *,const char *)
+{	mgl_set_global_warn(_("HDF4 support was disabled. Please, enable it and rebuild MathGL."));	return 0;	}
+#endif
+//-----------------------------------------------------------------------------
+#if MGL_HAVE_HDF5
+void MGL_EXPORT mgl_data_save_hdf(HCDT dat,const char *fname,const char *data,int rewrite)
+{
+	const mglData *d = dynamic_cast<const mglData *>(dat);	// NOTE: slow for non-mglData
+	if(!d)	{	mglData d(dat);	mgl_data_save_hdf(&d,fname,data,rewrite);	return;	}
+	hid_t hf,hd,hs;
+	hsize_t dims[3];
+	long rank = 3, res;
+	H5Eset_auto(0,0);
+	res=H5Fis_hdf5(fname);
+	if(res>0 && !rewrite)	hf = H5Fopen(fname, H5F_ACC_RDWR, H5P_DEFAULT);
+	else	hf = H5Fcreate(fname, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+	if(hf<0)	return;
+	if(d->nz==1 && d->ny == 1)	{	rank=1;	dims[0]=d->nx;	}
+	else if(d->nz==1)	{	rank=2;	dims[0]=d->ny;	dims[1]=d->nx;	}
+	else	{	rank=3;	dims[0]=d->nz;	dims[1]=d->ny;	dims[2]=d->nx;	}
+	hs = H5Screate_simple(rank, dims, 0);
+#if MGL_USE_DOUBLE
+	hid_t mem_type_id = H5T_NATIVE_DOUBLE;
+#else
+	hid_t mem_type_id = H5T_NATIVE_FLOAT;
+#endif
+	hd = H5Dcreate(hf, data, mem_type_id, hs, H5P_DEFAULT);
+	H5Dwrite(hd, mem_type_id, hs, hs, H5P_DEFAULT, d->a);
+	H5Dclose(hd);	H5Sclose(hs);	H5Fclose(hf);
+}
+//-----------------------------------------------------------------------------
+int MGL_EXPORT mgl_data_read_hdf(HMDT d,const char *fname,const char *data)
+{
+	hid_t hf,hd,hs;
+	long rank, res = H5Fis_hdf5(fname);
+	if(res<=0)	return mgl_data_read_hdf4(d,fname,data);
+	hf = H5Fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT);
+	if(hf<0)	return 0;
+	hd = H5Dopen(hf,data);
+	if(hd<0)	return 0;
+	hs = H5Dget_space(hd);
+	rank = H5Sget_simple_extent_ndims(hs);
+	if(rank>0 && rank<=3)
+	{
+		hsize_t dims[3];
+		H5Sget_simple_extent_dims(hs,dims,0);
+		if(rank==1)			{	dims[2]=dims[0];	dims[0]=dims[1]=1;	}
+		else if(rank==2)	{	dims[2]=dims[1];	dims[1]=dims[0];	dims[0]=1;	}
+//		else if(rank>3)		continue;
+		mgl_data_create(d,dims[2],dims[1],dims[0]);
+#if MGL_USE_DOUBLE
+		H5Dread(hd, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, d->a);
+#else
+		H5Dread(hd, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, d->a);
+#endif
+	}
+	H5Sclose(hs);	H5Dclose(hd);	H5Fclose(hf);	return 1;
+}
+//-----------------------------------------------------------------------------
+MGL_EXPORT const char * const * mgl_datas_hdf_str(const char *fname)
+{
+	static std::vector<std::string> names;
+	static const char **res=0;
+	hid_t hf,hg,hd,ht;
+	hf = H5Fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT);	names.clear();
+	if(!hf)	return 0;
+	hg = H5Gopen(hf,"/");
+	hsize_t num;
+	char name[256];
+	H5Gget_num_objs(hg, &num);	// replace by H5G_info_t t; H5Gget_info(hg,&t); num=t.nlinks;
+	for(hsize_t i=0;i<num;i++)
+	{
+		if(H5Gget_objtype_by_idx(hg, i)!=H5G_DATASET)	continue;
+		H5Gget_objname_by_idx(hg, i, name, 256);	// replace by H5Lget_name_by_idx(hg,".",i,0,0,name,256,0) ?!
+		hd = H5Dopen(hf,name);
+		ht = H5Dget_type(hd);
+		if(H5Tget_class(ht)==H5T_FLOAT || H5Tget_class(ht)==H5T_INTEGER)	names.push_back(name);
+		H5Dclose(hd);	H5Tclose(ht);
+	}
+	H5Gclose(hg);	H5Fclose(hf);	names.push_back("");
+	if(res)	delete []res;
+	size_t nn = names.size();
+	res = new const char*[nn+1];
+	for(size_t i=0;i<nn;i++)	res[i]=names[i].c_str();
+	res[nn]=NULL;	return res;
+}
+
+long MGL_EXPORT mgl_datas_hdf(const char *fname, char *buf, long size)
+{
+	const char * const *res = mgl_datas_hdf_str(fname);
+	if(!res)	return 0;
+	long n=0, len=1;
+	while(res[n][0])	{	len += strlen(res[n])+1;	n++;	}
+	if(len>size)	return -long(len);
+	strcpy(buf,res[0]);
+	for(long i=1;i<n;i++)	{	strcat(buf,"\t");	strcat(buf,res[i]);	}
+	return n;
+}
+#else
+void MGL_EXPORT mgl_data_save_hdf(HCDT ,const char *,const char *,int )
+{	mgl_set_global_warn(_("HDF5 support was disabled. Please, enable it and rebuild MathGL."));	}
+MGL_EXPORT const char * const * mgl_datas_hdf_str(const char *fname)
+{	mgl_set_global_warn(_("HDF5 support was disabled. Please, enable it and rebuild MathGL."));	return 0;}
+long MGL_EXPORT mgl_datas_hdf(const char *, char *, long )
+{	mgl_set_global_warn(_("HDF5 support was disabled. Please, enable it and rebuild MathGL."));	return 0;}
+int MGL_EXPORT mgl_data_read_hdf(HMDT ,const char *,const char *)
+{	mgl_set_global_warn(_("HDF5 support was disabled. Please, enable it and rebuild MathGL."));	return 0;}
+#endif
+//-----------------------------------------------------------------------------
+int MGL_EXPORT mgl_data_read_hdf_(uintptr_t *d, const char *fname, const char *data,int l,int n)
+{	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
+	char *t=new char[n+1];		memcpy(t,data,n);	t[n]=0;
+	int r = mgl_data_read_hdf(_DT_,s,t);	delete []s;	delete []t;	return r;	}
+void MGL_EXPORT mgl_data_save_hdf_(uintptr_t *d, const char *fname, const char *data, int *rewrite,int l,int n)
+{	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
+	char *t=new char[n+1];		memcpy(t,data,n);	t[n]=0;
+	mgl_data_save_hdf(_DT_,s,t,*rewrite);	delete []s;	delete []t;	}
+long MGL_EXPORT mgl_datas_hdf_(const char *fname, char *buf, int l, int size)
+{	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
+	int r = mgl_datas_hdf(s,buf,size);	delete []s;	return r;	}
+//-----------------------------------------------------------------------------
+bool MGL_EXPORT mgl_add_file(long &kx,long &ky, long &kz, mreal *&b, mglData *d,bool as_slice)
+{
+	if(as_slice && d->nz==1)
+	{
+		if(kx==d->nx && d->ny==1)
+		{
+			b = (mreal *)realloc(b,kx*(ky+1)*sizeof(mreal));
+			memcpy(b+kx*ky,d->a,kx*sizeof(mreal));		ky++;
+		}
+		else if(kx==d->nx && ky==d->ny)
+		{
+			b = (mreal *)realloc(b,kx*ky*(kz+1)*sizeof(mreal));
+			memcpy(b+kx*ky*kz,d->a,kx*ky*sizeof(mreal));	kz++;
+		}
+		else	return false;
+	}
+	else
+	{
+		if(d->ny*d->nz==1 && ky*kz==1)
+		{
+			b = (mreal *)realloc(b,(kx+d->nx)*sizeof(mreal));
+			memcpy(b+kx,d->a,d->nx*sizeof(mreal));	kx+=d->nx;
+		}
+		else if(kx==d->nx && kz==1 && d->nz==1)
+		{
+			b = (mreal *)realloc(b,kx*(ky+d->ny)*sizeof(mreal));
+			memcpy(b+kx*ky,d->a,kx*d->ny*sizeof(mreal));	ky+=d->ny;
+		}
+		else if(kx==d->nx && ky==d->ny)
+		{
+			b = (mreal *)realloc(b,kx*kx*(kz+d->nz)*sizeof(mreal));
+			memcpy(b+kx*ky*kz,d->a,kx*ky*d->nz*sizeof(mreal));	kz+=d->nz;
+		}
+		else	return false;
+	}
+	return true;
+}
+//-----------------------------------------------------------------------------
+int MGL_EXPORT mgl_data_read_range(HMDT dat, const char *templ, double from, double to, double step, int as_slice)
+{
+	mglData d;
+	mreal t = from, *b;
+	long kx,ky,kz,n=strlen(templ)+20;
+	char *fname = new char[n];
+
+	//read first file
+	do{	snprintf(fname,n,templ,t);	fname[n-1]=0;	t+= step;	} while(!mgl_data_read(&d,fname) && t<=to);
+
+	if(t>to)	{	delete []fname;	return 0;	}
+	kx = d.nx;	ky = d.ny;	kz = d.nz;
+	b = (mreal *)malloc(kx*ky*kz*sizeof(mreal));
+	memcpy(b,d.a,kx*ky*kz*sizeof(mreal));
+
+	// read other files
+	for(;t<=to;t+=step)
+	{
+		snprintf(fname,n,templ,t);	fname[n-1]=0;
+		if(mgl_data_read(&d,fname))
+			if(!mgl_add_file(kx,ky,kz,b,&d,as_slice))
+			{	delete []fname;	free(b);	return 0;	}
+	}
+	dat->Set(b,kx,ky,kz);
+	delete []fname;	free(b);
+	return 1;
+}
+int MGL_EXPORT mgl_data_read_range_(uintptr_t *d, const char *fname, mreal *from, mreal *to, mreal *step, int *as_slice,int l)
+{	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
+	int r = mgl_data_read_range(_DT_,s,*from,*to,*step,*as_slice);	delete []s;	return r;	}
+//-----------------------------------------------------------------------------
+int MGL_EXPORT mgl_data_read_all(HMDT dat, const char *templ, int as_slice)
+{
+#ifndef WIN32
+	mglData d;
+	glob_t res;
+	size_t i;
+	mreal *b;
+	long kx,ky,kz;
+	glob (templ, GLOB_TILDE, NULL, &res);
+
+	//read first file
+	for(i=0;i<res.gl_pathc;i++)
+		if(mgl_data_read(&d,res.gl_pathv[i]))	break;
+
+	if(i>=res.gl_pathc)
+	{	globfree (&res);	return 0;	}
+	kx = d.nx;	ky = d.ny;	kz = d.nz;
+	b = (mreal *)malloc(kx*ky*kz*sizeof(mreal));
+	memcpy(b,d.a,kx*ky*kz*sizeof(mreal));
+
+	for(;i<res.gl_pathc;i++)
+	{
+		if(mgl_data_read(&d,res.gl_pathv[i]))
+			if(!mgl_add_file(kx,ky,kz,b,&d,as_slice))
+			{	globfree (&res);	free(b);	return 0;	}
+	}
+	dat->Set(b,kx,ky,kz);
+
+	globfree (&res);	free(b);
+	return 1;
+#else
+	return 0;
+#endif
+}
+int MGL_EXPORT mgl_data_read_all_(uintptr_t *d, const char *fname, int *as_slice,int l)
+{	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
+	int r = mgl_data_read_all(_DT_,s,*as_slice);	delete []s;	return r;	}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_data_column(HCDT dat, const char *eq)
+{
+	const mglData *dd=dynamic_cast<const mglData *>(dat);
+	std::vector<mglDataA*> list;
+	if(dd && dd->id.length()>0)	for(size_t i=0;i<dd->id.length();i++)
+	{
+		mglDataT *col = new mglDataT(*dat);
+		col->SetInd(i,dd->id[i]);
+		list.push_back(col);
+	}
+	const mglDataC *dc=dynamic_cast<const mglDataC *>(dat);
+	if(dc && dc->id.length()>0)	for(size_t i=0;i<dc->id.length();i++)
+	{
+		mglDataT *col = new mglDataT(*dat);
+		col->SetInd(i,dc->id[i]);
+		list.push_back(col);
+	}
+	if(list.size()==0)	return 0;	// no named columns
+	mglDataV *t = new mglDataV(dat->GetNy(),dat->GetNz());
+	t->s=L"#$mgl";	list.push_back(t);
+	HMDT r = mglFormulaCalc(eq,list);
+	for(size_t i=0;i<list.size();i++)	delete list[i];
+	return r;
+}
+uintptr_t MGL_EXPORT mgl_data_column_(uintptr_t *d, const char *eq,int l)
+{	char *s=new char[l+1];	memcpy(s,eq,l);	s[l]=0;
+	uintptr_t r = uintptr_t(mgl_data_column(_DT_,s));
+	delete []s;	return r;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_limit(HMDT d, mreal v)
+{
+	long n = d->GetNN();
+	mreal *a = d->a;
+	#pragma omp parallel for
+	for(long i=0;i<n;i++)
+	{	mreal b = fabs(a[i]);	if(b>v)	a[i] *= v/b;	}
+}
+void MGL_EXPORT mgl_data_limit_(uintptr_t *d, mreal *v)
+{	mgl_data_limit(_DT_, *v);	}
+//-----------------------------------------------------------------------------
+/// Read binary data and swap big-endian to little-endian if swap=true
+size_t MGL_EXPORT mgl_fread(FILE *fp, void *vals, size_t size, size_t num, int swap)
+{
+	char *ptr = (char*)vals;
+	size_t r = fread(ptr,size,num,fp);
+	if(r && swap)
+	{
+		char buf[8], ch;
+		if(size==4)	for(size_t i=0;i<r;i++)
+		{
+			memcpy(buf,ptr+i*size,size);
+			ch=buf[0];	buf[0]=buf[3];	buf[3]=ch;
+			ch=buf[1];	buf[1]=buf[2];	buf[1]=ch;
+		}
+		else if(size==2)	for(size_t i=0;i<r;i++)
+		{
+			memcpy(buf,ptr+i*size,size);
+			ch=buf[0];	buf[0]=buf[1];	buf[1]=ch;
+		}
+		else if(size==8)	for(size_t i=0;i<r;i++)
+		{
+			memcpy(buf,ptr+i*size,size);
+			ch=buf[0];	buf[0]=buf[7];	buf[7]=ch;
+			ch=buf[1];	buf[1]=buf[6];	buf[6]=ch;
+			ch=buf[2];	buf[2]=buf[5];	buf[5]=ch;
+			ch=buf[3];	buf[3]=buf[4];	buf[4]=ch;
+		}
+	}
+	return r;
+}
+//-----------------------------------------------------------------------------
+/// Read data array from Tektronix WFM file
+/** Parse Tektronix TDS5000/B, TDS6000/B/C, TDS/CSA7000/B, MSO70000/C, DSA70000/B/C DPO70000/B/C DPO7000/ MSO/DPO5000. */
+int MGL_EXPORT mgl_data_read_wfm(HMDT d,const char *fname, long num, long step/*=1*/, long start/*=0*/)
+{
+	if(step<1)	step=1;
+	if(start<0)	start=0;
+	FILE *fp = fopen(fname,"rb");
+	if(!fp)	return 0;	// couldn't open file
+	unsigned short byte_order;
+	fread(&byte_order,2,1,fp);
+	bool byteorder;	// TODO
+}
+int MGL_EXPORT mgl_data_read_wfm_(uintptr_t *d, const char *fname, long *num, long *step, long *start,int l)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	int r = mgl_data_read_wfm(_DT_,s,*num,*step,*start);
+	delete []s;	return r;	}
+/// Read data array from Matlab MAT file (parse versions 4 and 5)
+int MGL_EXPORT mgl_data_read_matlab(HMDT d,const char *fname,const char *data)
+{
+	// TODO
+}
+int MGL_EXPORT mgl_data_read_matlab_(uintptr_t *d, const char *fname, const char *data,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *t=new char[n+1];	memcpy(t,data,n);	t[n]=0;
+	int r = mgl_data_read_matlab(_DT_,s,t);	delete []s;	delete []t;	return r;	}
+//-----------------------------------------------------------------------------
diff --git a/src/data_png.cpp b/src/data_png.cpp
new file mode 100644
index 0000000..8ab03f1
--- /dev/null
+++ b/src/data_png.cpp
@@ -0,0 +1,247 @@
+/***************************************************************************
+ * data_png.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include "mgl2/data.h"
+#if MGL_HAVE_PNG
+#include <png.h>
+#endif
+#if MGL_HAVE_JPEG
+#include <jpeglib.h>
+#endif
+//-----------------------------------------------------------------------------
+size_t MGL_LOCAL_PURE mgl_col_dif(unsigned char *c1,unsigned char *c2,bool sum)
+{
+	size_t res,d1=labs(long(c1[0])-long(c2[0])),
+		d2=labs(long(c1[1])-long(c2[1])),d3=labs(long(c1[2])-long(c2[2]));
+	if(sum)	res = d1+d2+d3;
+	else	res = mgl_max(d1,mgl_max(d2,d3));
+	return res;
+}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT unsigned char *mgl_create_scheme(const char *scheme,long &num)
+{
+	unsigned char *c=0,*cc=new unsigned char[3*strlen(scheme)+3],*c1,*c2;
+	size_t nc=1,np=0,l=strlen(scheme);
+	mglColor col;
+	for(size_t i=0;i<l;i++)
+	{
+		col.Set(scheme[i]);
+		if(col.Valid())
+		{	cc[3*np]=255*col.r;	cc[3*np+1]=255*col.g;	cc[3*np+2]=255*col.b;	np++;	}
+	}
+	if(np<2)	{	num=0;	delete []cc;	return 0;	}
+	for(size_t i=0;i<np-1;i++)	nc+=mgl_col_dif(cc+3*i,cc+3*i+3,false);
+	c = new unsigned char[3*nc+3];
+	size_t pos=0;
+	for(size_t i=0;i<np-1;i++)
+	{
+		size_t dd=mgl_col_dif(cc+3*i,cc+3*i+3,false);
+		for(size_t j=0;j<dd;j++)
+		{
+			c1 = c+3*(pos+j);	c2 = cc+3*i;
+			c1[0] = c2[0]+(c2[3]-c2[0])*j/dd;
+			c1[1] = c2[1]+(c2[4]-c2[1])*j/dd;
+			c1[2] = c2[2]+(c2[5]-c2[2])*j/dd;
+		}
+		pos += dd;
+	}
+	memcpy(c+3*nc-3,cc+3*np-3,3);
+	delete []cc;
+	num=nc;
+	return c;
+}
+//-----------------------------------------------------------------------------
+bool MGL_NO_EXPORT mgl_read_image(unsigned char **g, int &w, int &h, const char *fname)
+{
+	const char *ext = fname+strlen(fname)-1;	// rindex(fname,'.');
+	while(*ext!='.' && ext!=fname)	ext--;
+	if(!strcmp(ext,".png"))
+	{
+#if MGL_HAVE_PNG
+		FILE *fp = fopen(fname, "rb");
+		if(!fp)	return false;
+		png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
+		if (!png_ptr)	{	fclose(fp);	return false;	}
+		png_infop info_ptr = png_create_info_struct(png_ptr);
+		if (!info_ptr)
+		{	png_destroy_read_struct(&png_ptr,0,0);	fclose(fp);	return false;	}
+		png_infop end_info = png_create_info_struct(png_ptr);
+		if (!end_info)
+		{	png_destroy_read_struct(&png_ptr,&info_ptr,0);	fclose(fp);	return false;	}
+
+		png_init_io(png_ptr, fp);
+		png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_PACKING|PNG_TRANSFORM_STRIP_16|PNG_TRANSFORM_EXPAND,0);
+		unsigned char **rows = png_get_rows(png_ptr, info_ptr);
+
+		long wi=png_get_image_width(png_ptr, info_ptr);
+		long hi=png_get_image_height(png_ptr, info_ptr);
+		int type = png_get_color_type(png_ptr, info_ptr);
+		if(*g)
+		{
+			if(wi>w)	wi = w;
+			if(hi>h)	hi = h;
+		}
+		else	{	w = wi;	h = hi;	*g = new unsigned char[4*w*h];	}
+		if(type==PNG_COLOR_TYPE_RGB_ALPHA)
+#pragma omp parallel for
+			for(long i=0;i<hi;i++)	memcpy(*g+4*w*i,rows[i],4*wi);
+		else if(type==PNG_COLOR_TYPE_RGB)
+#pragma omp parallel for collapse(2)
+			for(long i=0;i<hi;i++)	for(long j=0;j<wi;j++)
+				memcpy(*g+4*(w*i+j),rows[i]+3*j,3);
+		else if(type==PNG_COLOR_TYPE_GRAY)
+#pragma omp parallel for collapse(2)
+			for(long i=0;i<hi;i++)	for(long j=0;j<wi;j++)
+				(*g)[4*(w*i+j)] = (*g)[4*(w*i+j)+1] = (*g)[4*(w*i+j)+2] = rows[i][j];
+		else if(type==PNG_COLOR_TYPE_GRAY_ALPHA)
+#pragma omp parallel for collapse(2)
+			for(long i=0;i<hi;i++)	for(long j=0;j<wi;j++)
+			{
+				(*g)[4*(w*i+j)] = (*g)[4*(w*i+j)+1] = (*g)[4*(w*i+j)+2] = rows[i][2*j];
+				(*g)[4*(w*i+j)+3] = rows[i][2*j+1];
+			}
+		png_destroy_read_struct(&png_ptr, &info_ptr,&end_info);
+		fclose(fp);
+#else
+		mgl_set_global_warn(_("PNG support was disabled. Please, enable it and rebuild MathGL."));
+#endif
+	}
+	else if(!strcmp(ext,".jpg") || !strcmp(ext,".jpeg"))
+	{
+#if MGL_HAVE_JPEG
+		FILE *fp = fopen(fname, "rb");
+		if(!fp)	return false;
+
+		jpeg_decompress_struct info;
+		jpeg_error_mgr err;
+		info.err = jpeg_std_error(&err);
+		jpeg_create_decompress(&info);
+
+		jpeg_stdio_src(&info, fp);
+		jpeg_read_header(&info, TRUE);	// read jpeg file header
+		jpeg_start_decompress(&info);	// decompress the file
+
+		long wi = info.output_width;	//set width and height
+		long hi = info.output_height;
+		int channels = info.num_components;	// == 4 for RGBA else for RGB
+		unsigned char *buf = new unsigned char[(channels==4?4:3)*wi];
+		if(*g)
+		{
+			if(hi>h)	hi = h;
+			if(wi>w)	wi = w;
+		}
+		else	{	w = wi;	h = hi;	*g = new unsigned char[4*w*h];	}
+		for(long i=0;i<hi;i++)
+		{
+			jpeg_read_scanlines(&info, &buf, 1);
+			if(channels==4)
+				memcpy(*g+4*i*w,buf,4*wi);
+			else
+#pragma omp parallel for
+				for(long j=0;j<wi;j++)
+					memcpy(*g+4*i*w+4*j,buf+3*j,3);
+		}
+		delete []buf;
+#else
+		mgl_set_global_warn(_("JPEG support was disabled. Please, enable it and rebuild MathGL."));
+#endif
+	}
+	return true;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_import(HMDT d, const char *fname, const char *scheme,mreal v1,mreal v2)
+{
+	if(v1>=v2)	return;
+	unsigned char *g = 0;
+	int w=0, h=0;
+	if(!mgl_read_image(&g,w,h,fname))	return;
+	long num=0;
+	unsigned char *c = mgl_create_scheme(scheme,num);
+	if(num>1)
+	{
+		d->Create(w,h,1);
+#pragma omp parallel for collapse(2)
+		for(long i=0;i<h;i++)	for(long j=0;j<w;j++)
+		{
+			size_t pos=0,mval=256;
+			for(long k=0;k<num;k++)
+			{
+				size_t val = mgl_col_dif(c+3*k,g+4*w*(d->ny-i-1)+4*j,true);
+				if(val==0)	{	pos=k;	break;	}
+				if(val<mval)	{	pos=k;	mval=val;	}
+			}
+			d->a[j+d->nx*i] = v1 + pos*(v2-v1)/num;
+		}
+	}
+	delete []g;
+	delete []c;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgl_png_save(const char *fname, int w, int h, unsigned char **p);
+int MGL_NO_EXPORT mgl_bmp_save(const char *fname, int w, int h, unsigned char **p);
+int MGL_NO_EXPORT mgl_tga_save(const char *fname, int w, int h, unsigned char **p);
+int MGL_NO_EXPORT mgl_jpeg_save(const char *fname, int w, int h, unsigned char **p);
+int MGL_NO_EXPORT mgl_bps_save(const char *fname, int w, int h, unsigned char **p);
+void MGL_EXPORT mgl_data_export(HCDT dd, const char *fname, const char *scheme,mreal v1,mreal v2,long ns)
+{
+	long nx=dd->GetNx(), ny=dd->GetNy(), nz=dd->GetNz();
+	if(v1>v2)	return;
+	if(ns<0 || ns>=nz)	ns=0;
+	if(v1==v2)
+	{
+		v1 = INFINITY;	v2=-INFINITY;
+		for(long i=0;i<nx*ny*nz;i++)
+		{	mreal vv = dd->vthr(i);	if(vv<v1)	v1=vv;	if(vv>v2)	v2=vv;	}
+	}
+	if(v1==v2)	return;
+	long num=0;
+	unsigned char *c = mgl_create_scheme(scheme,num);
+	if(num<2)	{	delete []c;		return;		}
+
+	unsigned char **p = new unsigned char*[ny];
+	unsigned char *d = new unsigned char[3*nx*ny];
+	#pragma omp parallel for
+	for(long i=0;i<ny;i++)	p[i] = d+3*nx*(ny-1-i);
+	#pragma omp parallel for collapse(2)
+	for(long i=0;i<ny;i++)	for(long j=0;j<nx;j++)
+	{
+		long k = long(num*(dd->v(j,i,ns)-v1)/(v2-v1));
+		if(k<0)		k=0;
+		if(k>=num) k=num-1;
+		memcpy(d+3*(j+i*nx),c+3*k,3);
+	}
+	delete []c;
+
+	int len=strlen(fname);
+	if(!strcmp(fname+len-4,".jpg") || !strcmp(fname+len-5,".jpeg"))	mgl_jpeg_save(fname, nx,ny,p);
+	if(!strcmp(fname+len-4,".bmp")) 	mgl_bmp_save(fname, nx,ny,p);
+	if(!strcmp(fname+len-4,".png")) 	mgl_png_save(fname, nx,ny,p);
+	if(!strcmp(fname+len-4,".eps") || !strcmp(fname+len-4,".bps")) 	mgl_bps_save(fname, nx,ny,p);
+	delete []p;	delete []d;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_export_(uintptr_t *d, const char *fname, const char *scheme,mreal *v1,mreal *v2,int *ns,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,scheme,n);	f[n]=0;
+	mgl_data_export(_DT_,s,f,*v1,*v2,*ns);	delete []s;		delete []f;	}
+void MGL_EXPORT mgl_data_import_(uintptr_t *d, const char *fname, const char *scheme,mreal *v1,mreal *v2,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,scheme,n);	f[n]=0;
+	mgl_data_import(_DT_,s,f,*v1,*v2);	delete []s;		delete []f;	}
+//-----------------------------------------------------------------------------
diff --git a/src/def_font.cc b/src/def_font.cc
new file mode 100644
index 0000000..b13632c
--- /dev/null
+++ b/src/def_font.cc
@@ -0,0 +1,1236 @@
+const unsigned long mgl_numg=411, mgl_cur=194872;
+const float mgl_fact=35.7143;
+long mgl_gen_fnt[411][6] = {
+	{0x21,166,41,0,39,82},
+	{0x22,204,43,316,38,402},
+	{0x23,250,33,630,32,696},
+	{0x24,250,81,888,80,1050},
+	{0x25,373,130,1530,129,1790},
+	{0x26,388,128,2564,127,2820},
+	{0x27,89,20,3582,19,3622},
+	{0x28,166,22,3736,20,3780},
+	{0x29,166,22,3900,21,3944},
+	{0x2a,250,154,4070,169,4378},
+	{0x2b,342,12,5392,8,5416},
+	{0x2c,125,34,5464,34,5532},
+	{0x2d,166,4,5736,2,5744},
+	{0x2e,125,21,5756,18,5798},
+	{0x2f,138,4,5906,2,5914},
+	{0x30,250,43,5926,41,6012},
+	{0x31,250,28,6258,27,6314},
+	{0x32,250,43,6476,41,6562},
+	{0x33,250,91,6808,90,6990},
+	{0x34,250,15,7530,12,7560},
+	{0x35,250,72,7632,77,7776},
+	{0x36,250,68,8238,66,8374},
+	{0x37,250,13,8770,11,8796},
+	{0x38,250,85,8862,83,9032},
+	{0x39,250,68,9530,67,9666},
+	{0x3a,138,43,10068,36,10154},
+	{0x3b,138,57,10370,52,10484},
+	{0x3c,342,7,10796,5,10810},
+	{0x3d,342,9,10840,4,10858},
+	{0x3e,342,7,10882,5,10896},
+	{0x3f,222,77,10926,73,11080},
+	{0x40,460,136,11518,136,11790},
+	{0x41,361,47,12606,50,12700},
+	{0x42,333,90,13000,90,13180},
+	{0x43,333,72,13720,72,13864},
+	{0x44,361,67,14296,68,14430},
+	{0x45,305,57,14838,54,14952},
+	{0x46,277,51,15276,47,15378},
+	{0x47,361,88,15660,86,15836},
+	{0x48,361,60,16352,56,16472},
+	{0x49,166,27,16808,26,16862},
+	{0x4a,186,45,17018,43,17108},
+	{0x4b,361,70,17366,69,17506},
+	{0x4c,305,37,17920,39,17994},
+	{0x4d,444,49,18228,47,18326},
+	{0x4e,361,47,18608,50,18702},
+	{0x4f,361,63,19002,60,19128},
+	{0x50,278,66,19488,69,19620},
+	{0x51,361,85,20034,83,20204},
+	{0x52,333,69,20702,69,20840},
+	{0x53,277,91,21254,94,21436},
+	{0x54,305,32,22000,30,22064},
+	{0x55,361,68,22244,68,22380},
+	{0x56,361,42,22788,41,22872},
+	{0x57,472,72,23118,75,23262},
+	{0x58,361,82,23712,80,23876},
+	{0x59,361,55,24356,54,24466},
+	{0x5a,305,32,24790,30,24854},
+	{0x5b,166,18,25034,16,25070},
+	{0x5c,138,4,25166,2,25174},
+	{0x5d,166,17,25186,16,25220},
+	{0x5e,234,7,25316,5,25330},
+	{0x5f,250,4,25360,2,25368},
+	{0x60,166,17,25380,16,25414},
+	{0x61,222,112,25510,115,25734},
+	{0x62,250,70,26424,71,26564},
+	{0x63,222,62,26990,60,27114},
+	{0x64,250,72,27474,79,27618},
+	{0x65,222,53,28092,53,28198},
+	{0x66,166,57,28516,53,28630},
+	{0x67,250,139,28948,149,29226},
+	{0x68,250,60,30120,67,30240},
+	{0x69,138,45,30642,44,30732},
+	{0x6a,138,71,30996,71,31138},
+	{0x6b,250,69,31564,72,31702},
+	{0x6c,138,30,32134,30,32194},
+	{0x6d,388,102,32374,108,32578},
+	{0x6e,250,66,33226,67,33358},
+	{0x6f,250,53,33760,50,33866},
+	{0x70,250,68,34166,72,34302},
+	{0x71,250,64,34734,68,34862},
+	{0x72,166,61,35270,61,35392},
+	{0x73,194,79,35758,86,35916},
+	{0x74,138,47,36432,49,36526},
+	{0x75,250,54,36820,56,36928},
+	{0x76,250,54,37264,53,37372},
+	{0x77,361,72,37690,81,37834},
+	{0x78,250,83,38320,89,38486},
+	{0x79,250,74,39020,79,39168},
+	{0x7a,222,27,39642,25,39696},
+	{0x7b,239,55,39846,54,39956},
+	{0x7c,99,4,40280,2,40288},
+	{0x7d,239,55,40300,55,40410},
+	{0x7e,270,41,40740,40,40822},
+	{0xa1,165,41,41062,39,41144},
+	{0xa2,250,81,41378,84,41540},
+	{0xa3,250,135,42044,148,42314},
+	{0xa4,250,73,43202,72,43348},
+	{0xa5,250,71,43780,69,43922},
+	{0xa6,99,9,44336,4,44354},
+	{0xa7,250,152,44378,156,44682},
+	{0xa8,166,43,45618,36,45704},
+	{0xa9,380,92,45920,87,46104},
+	{0xaa,137,95,46626,103,46816},
+	{0xab,250,69,47434,73,47572},
+	{0xac,300,6,48010,4,48022},
+	{0xad,166,4,48046,2,48054},
+	{0xae,380,106,48066,106,48278},
+	{0xaf,166,4,48914,2,48922},
+	{0xb0,199,43,48934,41,49020},
+	{0xb1,342,17,49266,10,49300},
+	{0xb2,150,41,49360,41,49442},
+	{0xb3,150,74,49688,75,49836},
+	{0xb4,166,16,50286,16,50318},
+	{0xb5,250,68,50414,67,50550},
+	{0xb6,295,48,50952,47,51048},
+	{0xb7,125,21,51330,18,51372},
+	{0xb8,166,40,51480,43,51560},
+	{0xb9,150,23,51818,26,51864},
+	{0xba,155,46,52020,45,52112},
+	{0xbb,250,73,52382,72,52528},
+	{0xbc,375,43,52960,40,53046},
+	{0xbd,375,74,53286,69,53434},
+	{0xbe,375,95,53848,89,54038},
+	{0xbf,222,86,54572,82,54744},
+	{0xc0,361,65,55236,66,55366},
+	{0xc1,361,65,55762,66,55892},
+	{0xc2,361,55,56288,55,56398},
+	{0xc3,361,89,56728,92,56906},
+	{0xc4,361,91,57458,86,57640},
+	{0xc5,361,91,58156,90,58338},
+	{0xc6,444,86,58878,85,59050},
+	{0xc7,333,108,59560,116,59776},
+	{0xc8,305,74,60472,70,60620},
+	{0xc9,305,74,61040,70,61188},
+	{0xca,305,65,61608,59,61738},
+	{0xcb,305,101,62092,90,62294},
+	{0xcc,166,45,62834,42,62924},
+	{0xcd,166,45,63176,42,63266},
+	{0xce,166,36,63518,31,63590},
+	{0xcf,166,72,63776,62,63920},
+	{0xd0,361,70,64292,69,64432},
+	{0xd1,361,88,64846,92,65022},
+	{0xd2,361,80,65574,76,65734},
+	{0xd3,361,81,66190,76,66352},
+	{0xd4,361,71,66808,65,66950},
+	{0xd5,361,104,67340,102,67548},
+	{0xd6,361,107,68160,96,68374},
+	{0xd7,319,12,68950,10,68974},
+	{0xd8,361,78,69034,80,69190},
+	{0xd9,361,87,69670,84,69844},
+	{0xda,361,87,70348,84,70522},
+	{0xdb,361,76,71026,73,71178},
+	{0xdc,361,112,71616,104,71840},
+	{0xdd,361,73,72464,70,72610},
+	{0xde,277,70,73030,75,73170},
+	{0xdf,250,98,73620,98,73816},
+	{0xe0,222,130,74404,131,74664},
+	{0xe1,222,129,75450,131,75708},
+	{0xe2,222,120,76494,120,76734},
+	{0xe3,222,155,77454,157,77764},
+	{0xe4,222,156,78706,151,79018},
+	{0xe5,222,156,79924,155,80236},
+	{0xe6,333,127,81166,132,81420},
+	{0xe7,222,97,82212,99,82406},
+	{0xe8,222,71,83000,69,83142},
+	{0xe9,222,72,83556,69,83700},
+	{0xea,222,61,84114,58,84236},
+	{0xeb,222,97,84584,89,84778},
+	{0xec,138,40,85312,42,85392},
+	{0xed,138,41,85644,42,85726},
+	{0xee,138,33,85978,31,86044},
+	{0xef,138,70,86230,62,86370},
+	{0xf0,250,74,86742,72,86890},
+	{0xf1,250,109,87322,109,87540},
+	{0xf2,250,71,88194,66,88336},
+	{0xf3,250,71,88732,66,88874},
+	{0xf4,250,61,89270,55,89392},
+	{0xf5,250,94,89722,92,89910},
+	{0xf6,250,97,90462,86,90656},
+	{0xf7,281,48,91172,38,91268},
+	{0xf8,250,73,91496,76,91642},
+	{0xf9,250,73,92098,72,92244},
+	{0xfa,250,73,92676,72,92822},
+	{0xfb,250,62,93254,61,93378},
+	{0xfc,250,98,93744,92,93940},
+	{0xfd,250,92,94492,95,94676},
+	{0xfe,250,71,95246,72,95388},
+	{0xff,250,118,95820,115,96056},
+	{0x300,0,15,96746,16,96776},
+	{0x301,0,16,96872,16,96904},
+	{0x302,0,7,97000,5,97014},
+	{0x303,0,40,97044,40,97124},
+	{0x304,0,4,97364,2,97372},
+	{0x305,0,4,97384,2,97392},
+	{0x306,0,22,97404,20,97448},
+	{0x307,0,21,97568,18,97610},
+	{0x308,0,43,97718,36,97804},
+	{0x309,0,44,98020,43,98108},
+	{0x30a,0,43,98366,40,98452},
+	{0x30b,0,36,98692,32,98764},
+	{0x30c,0,7,98956,5,98970},
+	{0x30d,0,4,99000,2,99008},
+	{0x30e,0,9,99020,4,99038},
+	{0x30f,0,36,99062,32,99134},
+	{0x391,361,45,99326,46,99416},
+	{0x392,333,71,99692,70,99834},
+	{0x393,293,35,100254,33,100324},
+	{0x394,361,8,100522,7,100538},
+	{0x395,305,56,100580,52,100692},
+	{0x396,305,32,101004,30,101068},
+	{0x397,361,60,101248,56,101368},
+	{0x398,361,105,101704,104,101914},
+	{0x399,166,27,102538,26,102592},
+	{0x39a,365,70,102748,69,102888},
+	{0x39b,351,41,103302,40,103384},
+	{0x39c,444,49,103624,47,103722},
+	{0x39d,361,47,104004,50,104098},
+	{0x39e,321,62,104398,54,104522},
+	{0x39f,361,63,104846,60,104972},
+	{0x3a0,361,52,105332,52,105436},
+	{0x3a1,278,66,105748,69,105880},
+	{0x3a3,311,24,106294,22,106342},
+	{0x3a4,305,32,106474,30,106538},
+	{0x3a5,361,55,106718,56,106828},
+	{0x3a6,381,76,107164,77,107316},
+	{0x3a7,361,82,107778,80,107942},
+	{0x3a8,372,81,108422,81,108584},
+	{0x3a9,372,62,109070,60,109194},
+	{0x3aa,166,71,109554,62,109696},
+	{0x3ab,361,99,110068,92,110266},
+	{0x3ac,271,84,110818,80,110986},
+	{0x3ad,219,111,111466,110,111688},
+	{0x3ae,256,71,112348,72,112490},
+	{0x3af,137,52,112922,54,113026},
+	{0x3b0,262,119,113350,110,113588},
+	{0x3b1,271,66,114248,64,114380},
+	{0x3b2,247,96,114764,99,114956},
+	{0x3b3,237,47,115550,48,115644},
+	{0x3b4,250,83,115932,80,116098},
+	{0x3b5,219,94,116578,94,116766},
+	{0x3b6,220,100,117330,101,117530},
+	{0x3b7,256,55,118136,56,118246},
+	{0x3b8,247,57,118582,56,118696},
+	{0x3b9,137,34,119032,38,119100},
+	{0x3ba,250,64,119328,66,119456},
+	{0x3bb,248,48,119852,47,119948},
+	{0x3bc,263,64,120230,63,120358},
+	{0x3bd,227,33,120736,35,120802},
+	{0x3be,220,137,121012,139,121286},
+	{0x3bf,252,43,122120,41,122206},
+	{0x3c0,250,67,122452,69,122586},
+	{0x3c1,247,55,123000,53,123110},
+	{0x3c2,220,79,123428,79,123586},
+	{0x3c3,273,45,124060,43,124150},
+	{0x3c4,238,46,124408,44,124500},
+	{0x3c5,262,58,124764,58,124880},
+	{0x3c6,311,73,125228,72,125374},
+	{0x3c7,250,52,125806,51,125910},
+	{0x3c8,347,54,126216,55,126324},
+	{0x3c9,312,91,126654,90,126836},
+	{0x3d1,276,96,127376,99,127568},
+	{0x3d5,311,63,128162,64,128288},
+	{0x3d6,381,95,128672,96,128862},
+	{0x3f0,275,77,129438,76,129592},
+	{0x3f1,250,63,130048,62,130174},
+	{0x3f5,219,51,130546,50,130648},
+	{0x410,356,47,130948,50,131042},
+	{0x411,305,63,131342,60,131468},
+	{0x412,325,92,131828,90,132012},
+	{0x413,285,38,132552,38,132628},
+	{0x414,332,71,132856,73,132998},
+	{0x415,314,56,133436,54,133548},
+	{0x416,510,145,133872,143,134162},
+	{0x417,287,90,135020,89,135200},
+	{0x418,361,58,135734,55,135850},
+	{0x419,361,107,136180,104,136394},
+	{0x41a,344,100,137018,99,137218},
+	{0x41b,341,64,137812,64,137940},
+	{0x41c,446,48,138324,47,138420},
+	{0x41d,362,60,138702,56,138822},
+	{0x41e,364,63,139158,60,139284},
+	{0x41f,362,52,139644,52,139748},
+	{0x420,285,65,140060,69,140190},
+	{0x421,338,71,140604,72,140746},
+	{0x422,309,32,141178,30,141242},
+	{0x423,355,75,141422,78,141572},
+	{0x424,384,76,142040,77,142192},
+	{0x425,358,82,142654,80,142818},
+	{0x426,357,59,143298,63,143416},
+	{0x427,328,64,143794,63,143922},
+	{0x428,497,71,144300,78,144442},
+	{0x429,497,81,144910,89,145072},
+	{0x42a,368,53,145606,50,145712},
+	{0x42b,441,80,146012,75,146172},
+	{0x42c,305,51,146622,48,146724},
+	{0x42d,325,76,147012,76,147164},
+	{0x42e,450,93,147620,89,147806},
+	{0x42f,318,64,148340,64,148468},
+	{0x430,224,113,148852,114,149078},
+	{0x431,253,79,149762,78,149920},
+	{0x432,237,84,150388,84,150556},
+	{0x433,196,34,151060,32,151128},
+	{0x434,231,59,151320,64,151438},
+	{0x435,233,49,151822,48,151920},
+	{0x436,360,144,152208,148,152496},
+	{0x437,194,85,153384,88,153554},
+	{0x438,262,56,154082,55,154194},
+	{0x439,262,106,154524,103,154736},
+	{0x43a,251,85,155354,87,155524},
+	{0x43b,249,63,156046,64,156172},
+	{0x43c,308,48,156556,48,156652},
+	{0x43d,262,58,156940,56,157056},
+	{0x43e,256,53,157392,50,157498},
+	{0x43f,262,52,157798,52,157902},
+	{0x440,249,71,158214,72,158356},
+	{0x441,228,63,158788,60,158914},
+	{0x442,217,40,159274,38,159354},
+	{0x443,245,69,159582,73,159720},
+	{0x444,338,134,160158,136,160426},
+	{0x445,244,77,161242,81,161396},
+	{0x446,262,57,161882,59,161996},
+	{0x447,256,62,162350,63,162474},
+	{0x448,383,76,162852,78,163004},
+	{0x449,383,82,163472,85,163636},
+	{0x44a,269,56,164146,54,164258},
+	{0x44b,334,77,164582,75,164736},
+	{0x44c,228,49,165186,48,165284},
+	{0x44d,222,54,165572,55,165680},
+	{0x44e,368,81,166010,79,166172},
+	{0x44f,235,59,166646,59,166764},
+	{0x210f,289,94,167118,101,167306},
+	{0x2111,381,130,167912,125,168172},
+	{0x2113,383,82,168922,83,169086},
+	{0x211c,436,132,169584,135,169848},
+	{0x2190,463,40,170658,44,170738},
+	{0x2191,255,39,171002,44,171080},
+	{0x2192,463,41,171344,44,171426},
+	{0x2193,255,38,171690,44,171766},
+	{0x2194,463,75,172030,86,172180},
+	{0x2195,255,74,172696,86,172844},
+	{0x2196,463,50,173360,66,173460},
+	{0x2197,463,50,173856,65,173956},
+	{0x2198,463,45,174346,63,174436},
+	{0x2199,463,49,174814,64,174912},
+	{0x2200,280,12,175296,11,175320},
+	{0x2201,231,48,175386,47,175482},
+	{0x2202,235,70,175764,72,175904},
+	{0x2203,280,12,176336,10,176360},
+	{0x2204,280,30,176420,30,176480},
+	{0x2205,381,70,176660,70,176800},
+	{0x2206,365,8,177220,7,177236},
+	{0x2207,365,8,177278,7,177294},
+	{0x2208,342,29,177336,27,177394},
+	{0x2209,342,52,177556,56,177660},
+	{0x220a,242,29,177996,27,178054},
+	{0x220b,342,30,178216,27,178276},
+	{0x220c,342,56,178438,55,178550},
+	{0x220d,242,29,178880,28,178938},
+	{0x220e,272,4,179106,2,179114},
+	{0x220f,500,49,179126,47,179224},
+	{0x2210,500,49,179506,47,179604},
+	{0x2211,457,22,179886,20,179930},
+	{0x2212,342,4,180050,2,180058},
+	{0x2213,342,17,180070,10,180104},
+	{0x2214,342,34,180164,26,180232},
+	{0x2215,261,4,180388,2,180396},
+	{0x2216,213,4,180408,2,180416},
+	{0x2217,261,135,180428,133,180698},
+	{0x2218,175,43,181496,40,181582},
+	{0x2219,175,21,181822,18,181864},
+	{0x221a,463,19,181972,18,182010},
+	{0x221b,463,93,182118,93,182304},
+	{0x221c,463,35,182862,30,182932},
+	{0x221d,342,65,183112,65,183242},
+	{0x221e,463,85,183632,85,183802},
+	{0x221f,342,6,184312,4,184324},
+	{0x2220,342,6,184348,4,184360},
+	{0x2221,342,33,184384,42,184450},
+	{0x2222,342,48,184702,52,184798},
+	{0x2223,132,4,185110,2,185118},
+	{0x2224,202,12,185130,8,185154},
+	{0x2225,261,9,185202,4,185220},
+	{0x2226,304,20,185244,14,185284},
+	{0x2227,310,7,185368,5,185382},
+	{0x2228,310,7,185412,5,185426},
+	{0x2229,310,26,185456,25,185508},
+	{0x222a,310,26,185658,24,185710},
+	{0x222b,229,67,185854,70,185988},
+	{0x222c,350,137,186408,140,186682},
+	{0x222d,471,205,187522,210,187932},
+	{0x222e,249,117,189192,126,189426},
+	{0x222f,370,209,190182,232,190600},
+	{0x2260,342,20,191992,18,192032},
+	{0x2261,342,14,192140,6,192168},
+	{0x2262,342,28,192204,26,192260},
+	{0x2263,342,19,192416,8,192454},
+	{0x2264,342,12,192502,7,192526},
+	{0x2265,342,12,192568,7,192592},
+	{0x2266,342,17,192634,9,192668},
+	{0x2267,342,17,192722,9,192756},
+	{0x2268,342,28,192810,23,192866},
+	{0x2269,342,28,193004,23,193060},
+	{0x226a,466,15,193198,10,193228},
+	{0x226b,466,15,193288,10,193318},
+	{0x226c,233,80,193378,84,193538},
+	{0x226d,342,55,194042,60,194152},
+	{0x226e,342,20,194512,19,194552},
+	{0x226f,342,20,194666,19,194706},
+	{0x27c2,346,8,194820,6,194836},
+};
+short mgl_buf_fnt[194872] = {
+88,88,94,88,117,278,117,282,118,286,118,297,117,311,113,322,108,331,101,336,92,338,81,336,74,331,69,323,66,312,65,300,65,289,66,284,66,278,16383,16383,118,21,116,30,113,37,107,43,100,47,92,49,83,47,76,43,70,37,66,30,65,22,66,13,70,6,75,0,82,-2,91,-3,100,-2,107,0,113,6,116,13,118,21,
+107,43,107,0,113,37,113,37,107,0,113,6,113,37,113,6,116,30,116,30,113,6,116,13,116,30,116,13,118,21,65,22,66,13,66,30,66,30,66,13,70,6,66,30,70,6,70,37,70,37,70,6,75,0,70,37,75,0,76,43,76,43,75,0,82,-2,76,43,82,-2,83,47,83,47,82,-2,91,-3,83,47,91,-3,92,49,92,49,91,-3,100,-2,92,49,100,-2,100,47,100,47,100,-2,107,0,100,47,107,0,107,43,118,297,117,311,117,278,118,297,117,278,117,282,118,297,117,282,118,286,118,297,118,286,118,290,118,297,118,290,118,294,117,278,117,311,113,322,117,278,113,3 [...]
+150,215,154,243,158,268,162,289,165,306,166,318,165,324,162,330,157,334,151,337,145,338,138,337,132,334,127,330,124,324,123,316,124,307,126,291,129,270,134,244,139,215,16383,16383,65,215,70,243,75,268,78,289,80,306,81,318,80,324,77,330,73,334,67,337,60,338,53,337,47,334,42,330,40,324,39,316,39,307,42,291,45,270,50,244,55,215,
+123,316,124,307,124,324,124,324,124,307,126,291,124,324,126,291,127,330,127,330,126,291,129,270,127,330,129,270,132,334,132,334,129,270,134,244,132,334,134,244,138,337,138,337,134,244,139,215,138,337,139,215,145,338,145,338,139,215,150,215,145,338,150,215,151,337,151,337,150,215,154,243,151,337,154,243,157,334,157,334,154,243,158,268,157,334,158,268,162,330,162,330,158,268,162,289,162,330,162,289,165,324,165,324,162,289,165,306,165,324,165,306,166,318,39,316,39,307,40,324,40,324,39,307,4 [...]
+248,203,248,230,200,230,214,331,185,331,171,230,104,230,119,331,90,331,75,230,17,230,17,203,71,203,60,136,3,136,3,108,56,108,40,0,69,0,85,108,152,108,137,0,166,0,181,108,235,108,235,136,185,136,195,203,16383,16383,166,203,156,136,89,136,100,203,
+90,331,75,230,85,108,85,108,75,230,71,203,85,108,71,203,69,0,69,0,71,203,60,136,69,0,60,136,56,108,56,108,60,136,3,136,56,108,3,136,3,108,17,230,17,203,71,203,17,230,71,203,75,230,90,331,85,108,89,136,90,331,89,136,100,203,90,331,100,203,104,230,90,331,104,230,119,331,185,331,171,230,181,108,181,108,171,230,166,203,181,108,166,203,166,0,166,0,166,203,156,136,166,0,156,136,152,108,152,108,156,136,89,136,152,108,89,136,85,108,104,230,100,203,166,203,104,230,166,203,171,230,200,230,214,331, [...]
+132,319,154,314,172,304,186,291,197,273,205,250,213,250,213,305,202,314,189,321,173,326,155,330,132,332,132,363,115,363,115,332,88,328,64,319,44,304,31,283,26,257,29,234,38,214,54,196,79,177,115,155,115,14,90,17,69,27,52,42,38,63,30,90,22,90,22,26,38,16,54,9,71,4,91,1,115,0,115,-43,132,-43,132,0,164,6,191,17,211,32,224,54,229,85,228,96,227,105,225,115,222,123,219,130,210,141,199,152,185,164,163,178,132,195,16383,16383,115,204,93,219,79,232,69,243,64,254,63,266,65,281,71,293,81,304,96,313 [...]
+132,319,154,314,155,330,155,330,154,314,172,304,155,330,172,304,173,326,173,326,172,304,186,291,173,326,186,291,189,321,189,321,186,291,197,273,189,321,197,273,202,314,202,314,197,273,205,250,202,314,205,250,213,305,213,305,205,250,213,250,228,96,227,105,229,85,229,85,227,105,225,115,229,85,225,115,224,54,224,54,225,115,222,123,224,54,222,123,219,130,211,32,224,54,219,130,211,32,219,130,210,141,211,32,210,141,199,152,211,32,199,152,191,17,191,17,199,152,189,74,191,17,189,74,187,55,191,17 [...]
+343,107,341,127,335,143,325,155,312,163,295,165,267,159,241,143,220,120,206,91,200,60,203,38,212,18,225,4,242,-5,261,-8,286,-2,309,14,327,39,339,71,343,107,16383,16383,331,108,328,77,318,48,303,25,285,10,265,4,255,6,248,10,242,18,238,27,237,38,239,59,244,82,252,103,263,123,276,140,280,144,284,147,290,149,295,151,300,151,311,149,319,143,326,134,330,122,331,108,16383,16383,310,353,289,353,265,331,248,317,235,309,221,305,194,305,185,307,176,311,167,317,157,324,150,330,144,334,138,336,133,33 [...]
+326,134,330,122,335,143,335,143,330,122,331,108,339,71,331,108,328,77,339,71,328,77,327,39,327,39,328,77,318,48,327,39,318,48,309,14,309,14,318,48,303,25,309,14,303,25,286,-2,286,-2,303,25,285,10,286,-2,285,10,265,4,265,4,255,6,261,-8,261,-8,255,6,248,10,261,-8,248,10,242,18,242,-5,261,-8,242,18,242,-5,242,18,238,27,242,-5,238,27,237,38,242,-5,237,38,225,4,244,82,252,103,267,159,267,159,252,103,263,123,267,159,263,123,276,140,276,140,280,144,295,165,295,165,280,144,284,147,295,165,284,14 [...]
+368,55,359,45,350,38,342,33,332,30,321,29,304,31,288,36,274,46,259,58,246,75,260,96,273,115,284,134,296,152,309,173,316,184,323,192,332,198,342,201,355,203,355,213,248,213,248,203,261,201,270,197,276,193,279,187,280,179,278,165,273,150,264,133,251,113,234,89,218,107,205,126,192,146,180,167,168,192,199,207,221,222,235,238,243,256,246,276,242,298,233,315,218,328,199,335,177,338,153,335,132,325,116,309,105,288,101,263,101,250,103,237,106,223,111,207,118,189,99,177,72,158,50,138,34,116,24,92 [...]
+153,335,132,325,142,294,142,294,132,325,141,281,142,141,141,281,132,325,142,141,132,325,126,171,118,189,103,155,126,171,118,189,126,171,132,325,118,189,132,325,116,309,118,189,116,309,111,207,99,177,72,158,75,124,99,177,75,124,86,140,99,177,86,140,103,155,99,177,103,155,118,189,72,158,50,138,53,5,72,158,53,5,67,87,72,158,67,87,69,106,72,158,69,106,75,124,79,45,70,64,77,-3,77,-3,70,64,67,87,53,5,50,138,36,20,36,20,50,138,34,116,36,20,34,116,25,42,25,42,34,116,24,92,25,42,24,92,21,69,101,2 [...]
+50,215,56,244,60,269,64,290,66,306,66,324,63,330,59,334,53,337,46,338,39,337,33,334,28,330,25,324,24,317,25,306,27,289,31,268,35,243,40,215,
+24,317,25,306,25,324,25,324,25,306,27,289,25,324,27,289,28,330,28,330,27,289,31,268,28,330,31,268,33,334,33,334,31,268,35,243,33,334,35,243,39,337,39,337,35,243,40,215,39,337,40,215,46,338,46,338,40,215,50,215,46,338,50,215,53,337,53,337,50,215,56,244,53,337,56,244,59,334,59,334,56,244,60,269,59,334,60,269,63,330,63,330,60,269,64,290,63,330,64,290,66,324,66,324,64,290,66,306,66,324,66,306,66,318,
+152,-79,116,-44,92,-8,77,31,69,76,67,127,69,180,77,223,92,261,116,295,152,330,147,338,104,307,69,270,44,227,29,179,24,126,29,75,44,27,69,-17,103,-56,146,-88,
+24,126,29,75,29,179,29,179,29,75,44,27,29,179,44,27,44,227,44,227,44,27,69,-17,44,227,69,-17,67,127,67,127,69,270,44,227,116,295,152,330,147,338,116,295,147,338,104,307,116,295,104,307,92,261,67,127,69,180,69,270,69,270,69,180,77,223,69,270,77,223,104,307,104,307,77,223,92,261,116,-44,92,-8,103,-56,116,-44,103,-56,146,-88,116,-44,146,-88,152,-79,77,31,69,76,69,-17,77,31,69,-17,103,-56,77,31,103,-56,92,-8,67,127,69,-17,69,76,
+15,330,51,295,76,259,90,219,97,174,99,122,97,69,90,26,75,-11,51,-45,15,-79,19,-88,62,-56,97,-19,122,23,137,71,142,123,137,174,121,222,96,267,63,306,21,338,
+97,174,99,122,99,122,122,23,99,122,97,69,122,23,97,69,97,-19,97,-19,97,69,90,26,97,-19,90,26,75,-11,97,174,99,122,121,222,121,222,99,122,122,23,121,222,122,23,137,174,137,174,122,23,137,71,137,174,137,71,142,123,96,267,63,306,76,259,96,267,76,259,90,219,96,267,90,219,97,174,96,267,97,174,121,222,51,295,76,259,63,306,51,295,63,306,21,338,51,295,21,338,15,330,15,-79,19,-88,51,-45,51,-45,19,-88,62,-56,51,-45,62,-56,75,-11,75,-11,62,-56,97,-19,
+134,235,147,243,158,248,178,254,190,256,200,258,207,261,212,265,215,270,216,277,215,284,213,289,209,293,204,295,198,296,190,294,183,288,174,281,166,272,159,264,154,259,144,251,130,243,130,262,131,270,133,278,135,287,140,302,142,307,143,312,144,316,144,320,143,326,140,331,136,335,131,337,126,338,120,337,115,335,111,331,109,326,108,321,108,317,110,307,111,301,113,295,115,285,118,276,121,249,121,243,110,249,101,255,93,262,85,270,76,280,70,286,65,290,60,293,56,295,51,296,46,295,41,292,38,288 [...]
+69,254,69,254,78,252,69,254,78,252,70,286,69,254,70,286,65,290,69,254,65,290,60,293,69,254,60,293,56,295,69,254,56,295,56,257,51,296,46,295,46,261,51,296,46,261,56,257,51,296,56,257,56,295,36,283,36,270,38,288,38,288,36,270,40,265,38,288,40,265,41,292,41,292,40,265,46,261,41,292,46,261,46,295,81,196,86,201,88,221,88,221,86,201,89,204,88,221,89,204,97,224,97,224,89,204,92,207,97,224,92,207,94,210,94,210,97,212,97,224,97,224,97,212,106,229,78,218,65,215,69,183,78,218,69,183,74,188,78,218,7 [...]
+318,110,318,143,188,143,188,273,155,273,155,143,24,143,24,110,155,110,155,-20,188,-20,188,110,
+188,273,155,273,188,-20,188,-20,155,273,155,143,188,-20,155,143,155,110,155,110,155,143,24,143,155,110,24,143,24,110,188,110,318,110,188,143,188,143,318,110,318,143,188,-20,155,110,155,-20,
+41,-69,60,-58,76,-44,88,-27,95,-10,98,7,96,22,90,34,81,43,70,49,57,51,47,49,39,46,33,40,29,32,27,22,29,13,32,6,38,1,46,-1,56,-2,60,-2,63,-1,66,-1,68,0,73,0,75,-1,78,-4,78,-6,76,-16,71,-27,63,-38,51,-49,36,-60,
+63,-1,66,-1,70,49,70,49,66,-1,68,0,70,49,68,0,71,0,71,0,73,0,81,43,81,43,73,0,75,-1,81,43,75,-1,77,-3,27,22,29,13,29,32,29,32,29,13,32,6,29,32,32,6,33,40,33,40,32,6,38,1,33,40,38,1,39,46,39,46,38,1,46,-1,39,46,46,-1,47,49,47,49,46,-1,56,-2,47,49,56,-2,57,51,57,51,56,-2,60,-2,57,51,60,-2,70,49,70,49,60,-2,63,-1,98,7,96,22,95,-10,95,-10,96,22,90,34,95,-10,90,34,88,-27,88,-27,90,34,81,43,88,-27,81,43,78,-6,78,-6,76,-16,88,-27,88,-27,76,-16,76,-44,81,43,77,-3,78,-4,81,43,78,-4,78,-6,81,43,70 [...]
+142,97,142,128,20,128,20,97,
+142,97,142,128,20,128,142,97,20,128,20,97,
+90,22,89,30,85,38,79,44,71,49,63,50,54,49,46,45,40,39,37,31,35,22,37,13,40,6,46,0,54,-3,63,-5,71,-3,79,0,85,6,89,13,90,22,
+35,22,37,13,37,31,37,31,37,13,40,6,37,31,40,6,40,39,40,39,40,6,46,0,40,39,46,0,46,45,46,45,46,0,54,-3,46,45,54,-3,54,49,54,49,54,-3,62,-5,54,49,62,-5,63,50,63,50,62,-5,71,-3,63,50,71,-3,71,49,71,49,71,-3,79,0,71,49,79,0,79,44,79,44,79,0,85,6,79,44,85,6,85,38,85,38,85,6,89,13,85,38,89,13,89,30,89,30,89,13,90,22,
+143,338,110,338,-3,-6,30,-6,
+143,338,110,338,-3,-6,143,338,-3,-6,30,-6,
+238,165,232,222,218,270,194,307,164,330,127,338,84,329,52,304,29,266,16,220,12,168,16,118,27,71,48,31,80,3,125,-6,168,2,200,29,222,67,234,114,238,165,16383,16383,190,162,187,108,179,65,166,33,148,13,125,6,102,13,84,33,71,65,63,109,60,165,63,220,71,265,84,298,101,318,124,325,148,318,166,298,179,265,187,219,190,162,
+101,318,124,325,124,325,127,338,124,325,148,318,127,338,148,318,164,330,164,330,148,318,166,298,164,330,166,298,194,307,194,307,166,298,179,265,194,307,179,265,187,219,166,33,168,2,179,65,179,65,168,2,200,29,179,65,200,29,187,108,187,108,200,29,190,162,194,307,190,162,200,29,194,307,200,29,218,270,218,270,200,29,222,67,218,270,222,67,232,222,232,222,222,67,234,114,232,222,234,114,238,165,125,6,125,-6,148,13,148,13,125,-6,168,2,148,13,168,2,166,33,71,265,84,298,84,329,84,329,84,298,101,31 [...]
+197,0,197,7,178,8,164,12,155,18,151,27,150,38,150,336,145,338,55,292,55,286,69,291,74,293,84,295,88,296,92,296,97,295,101,293,104,288,106,281,107,272,107,47,105,33,100,22,92,14,78,10,59,7,59,0,
+100,22,92,14,197,0,197,0,92,14,78,10,197,0,78,10,59,7,79,294,84,295,145,338,145,338,84,295,88,296,145,338,88,296,92,296,92,296,97,295,145,338,145,338,97,295,101,293,145,338,101,293,104,288,164,12,155,18,107,47,107,47,155,18,151,27,107,47,151,27,107,272,106,281,107,272,145,338,106,281,145,338,104,288,145,338,55,292,69,291,145,338,69,291,74,293,145,338,74,293,79,294,150,38,150,336,145,338,150,38,145,338,107,272,150,38,107,272,151,27,197,0,197,7,178,8,197,0,178,8,164,12,197,0,164,12,105,33, [...]
+237,69,230,71,221,57,212,48,203,42,193,39,182,38,65,38,147,126,171,153,189,179,202,203,209,226,211,250,207,278,195,302,176,321,150,334,119,338,86,333,59,320,39,299,24,271,15,238,26,236,38,262,50,280,63,292,79,299,99,301,123,298,142,289,156,275,165,255,169,230,166,205,159,181,146,155,128,129,103,100,15,6,15,0,210,0,
+26,236,38,262,39,299,39,299,38,262,50,280,39,299,50,280,59,320,59,320,50,280,63,292,59,320,63,292,86,333,86,333,63,292,79,299,86,333,79,299,99,301,99,301,123,298,119,338,119,338,123,298,150,334,24,271,15,238,26,236,24,271,26,236,39,299,166,205,171,153,169,230,169,230,171,153,176,321,176,321,171,153,189,179,176,321,189,179,195,302,195,302,189,179,202,203,195,302,202,203,207,278,207,278,202,203,209,226,207,278,209,226,211,250,176,321,150,334,156,275,176,321,156,275,165,255,176,321,165,255, [...]
+31,255,43,275,57,290,71,300,87,306,105,308,123,306,138,300,149,290,157,275,159,257,157,240,152,224,143,211,132,199,118,190,112,186,105,183,96,179,87,176,76,172,76,165,92,165,104,164,113,163,121,162,127,160,146,152,161,141,171,127,178,109,180,88,176,63,167,42,153,26,135,15,114,11,106,11,99,13,90,15,82,20,71,26,64,31,57,35,51,38,41,40,34,39,29,36,25,32,22,27,21,22,23,12,30,4,41,-1,57,-5,76,-6,103,-4,130,0,154,9,175,22,193,40,200,52,207,65,211,79,214,94,215,109,214,125,212,139,207,152,201,1 [...]
+22,257,31,255,33,284,33,284,31,255,43,275,33,284,43,275,48,306,48,306,43,275,57,290,48,306,57,290,68,323,68,323,57,290,71,300,68,323,71,300,92,334,92,334,71,300,87,306,92,334,87,306,105,308,105,308,123,306,121,338,121,338,123,306,146,335,123,306,138,300,146,335,146,335,138,300,149,290,146,335,149,290,168,326,168,326,149,290,157,275,168,326,157,275,159,257,159,257,157,240,170,213,170,213,157,240,152,200,170,213,183,226,184,311,184,311,183,226,192,241,184,311,192,241,195,292,195,292,192,24 [...]
+237,84,237,116,185,116,185,338,163,338,6,116,6,84,146,84,146,0,185,0,185,84,16383,16383,146,116,26,116,146,287,
+6,84,146,84,6,116,6,116,146,84,26,116,6,116,26,116,163,338,163,338,26,116,146,287,163,338,146,287,185,0,185,0,146,287,146,116,185,0,146,116,146,84,146,84,146,116,26,116,163,338,185,0,185,338,185,116,185,84,237,84,185,116,237,84,237,116,185,0,146,84,146,0,
+219,340,214,344,210,339,206,335,202,333,197,331,87,331,32,213,32,208,34,206,38,206,65,204,89,199,110,191,129,182,145,171,156,159,166,146,172,131,177,114,178,96,174,71,164,48,149,29,131,16,110,12,104,12,98,14,90,17,83,21,75,27,66,34,58,39,51,41,45,43,38,43,30,42,24,40,19,36,17,31,16,24,19,13,27,5,40,-1,58,-5,79,-6,99,-5,117,-2,134,1,149,8,164,17,182,33,196,51,206,71,211,95,213,122,213,137,211,150,207,162,202,174,195,185,178,205,159,220,137,232,108,241,70,249,90,291,188,291,192,292,198,294 [...]
+211,95,213,122,213,137,211,95,213,137,211,150,211,95,211,150,207,162,211,95,207,162,206,71,178,205,178,96,182,33,178,205,182,33,195,185,195,185,182,33,196,51,195,185,196,51,202,174,202,174,196,51,206,71,202,174,206,71,207,162,149,8,164,17,164,48,164,48,164,17,182,33,164,48,182,33,174,71,174,71,182,33,178,96,110,12,117,-2,131,16,131,16,117,-2,134,1,131,16,134,1,149,29,149,29,134,1,149,8,149,29,149,8,164,48,202,333,197,331,198,294,202,333,198,294,200,296,202,333,200,296,201,298,202,333,201 [...]
+223,342,185,337,152,329,123,317,97,300,71,277,52,254,37,229,26,201,19,171,17,140,18,118,21,98,26,78,33,60,41,44,53,26,68,12,86,1,106,-4,129,-6,148,-5,166,0,182,7,196,17,209,30,218,43,225,57,230,73,233,91,234,109,230,145,217,174,198,196,172,209,140,214,127,213,115,211,103,207,90,201,76,191,89,234,111,270,142,300,180,321,224,334,16383,16383,189,94,187,65,180,41,169,23,154,11,134,7,109,13,89,30,75,56,66,91,64,133,67,157,76,173,89,184,105,189,122,191,146,187,165,175,179,156,187,128,189,94,
+140,214,127,213,146,187,146,187,127,213,122,191,105,189,122,191,115,211,105,189,115,211,103,207,64,133,67,157,71,277,71,277,67,157,76,173,71,277,76,173,76,191,76,191,76,173,89,184,76,191,89,184,90,201,90,201,89,184,105,189,90,201,105,189,103,207,127,213,115,211,122,191,187,65,180,41,182,7,182,7,180,41,169,23,182,7,169,23,166,0,166,0,169,23,154,11,166,0,154,11,148,-5,148,-5,154,11,134,7,148,-5,134,7,129,-6,129,-6,134,7,109,13,129,-6,109,13,106,-4,106,-4,109,13,89,30,106,-4,89,30,86,1,86,1 [...]
+224,323,224,331,40,331,10,257,19,253,30,270,40,282,51,289,62,293,78,294,185,294,86,-3,118,-3,
+118,-3,224,323,185,294,185,294,224,323,224,331,185,294,224,331,78,294,62,293,78,294,224,331,62,293,224,331,40,331,40,331,10,257,19,253,40,331,19,253,30,270,40,331,30,270,40,282,40,331,40,282,51,289,40,331,51,289,62,293,118,-3,185,294,86,-3,
+223,78,220,100,213,121,199,141,177,162,145,185,171,200,190,215,203,229,210,246,212,267,208,289,197,309,179,324,156,334,128,338,97,335,70,324,49,308,36,287,31,260,33,242,38,225,49,208,67,189,93,166,66,145,47,127,35,111,30,94,28,75,32,48,45,25,66,8,92,-2,124,-6,157,-2,185,8,205,26,218,49,223,78,16383,16383,177,267,176,249,171,234,162,220,149,207,131,195,107,210,90,225,77,240,70,257,68,275,71,292,78,305,89,316,104,322,123,324,142,322,157,314,168,302,175,286,177,267,16383,16383,136,136,154,1 [...]
+167,109,177,162,154,122,154,122,177,162,145,185,154,122,145,185,136,136,136,136,145,185,149,207,136,136,149,207,131,195,131,195,107,210,136,136,136,136,107,210,106,156,90,142,106,156,93,166,66,8,69,54,66,79,66,79,67,97,66,145,66,145,67,97,71,113,66,145,71,113,93,166,93,166,71,113,79,128,93,166,79,128,90,142,30,94,32,48,35,111,35,111,32,48,45,25,35,111,45,25,47,127,47,127,45,25,66,8,47,127,66,8,66,145,66,145,66,8,66,79,107,210,90,225,93,166,107,210,93,166,106,156,90,225,77,240,93,166,93,1 [...]
+30,-10,65,-4,95,3,121,13,145,28,170,49,191,72,208,100,220,130,227,163,229,197,228,221,224,244,217,265,209,284,198,300,185,313,171,324,155,332,138,337,119,338,85,332,57,316,35,291,20,258,15,220,19,186,31,158,50,137,75,123,105,118,122,119,138,122,153,128,167,136,180,147,164,101,140,63,109,33,71,12,28,0,16383,16383,181,177,177,163,167,153,153,146,137,141,123,140,102,144,85,157,72,177,64,204,61,237,62,253,64,269,68,284,73,297,79,307,84,313,91,318,98,321,106,323,115,324,139,319,157,304,170,27 [...]
+62,253,64,269,57,316,57,316,64,269,68,284,57,316,68,284,85,332,85,332,68,284,73,297,85,332,73,297,79,307,79,307,84,313,85,332,85,332,84,313,91,318,85,332,91,318,119,338,119,338,91,318,98,321,119,338,98,321,106,323,119,338,106,323,115,324,115,324,139,319,119,338,119,338,139,319,138,337,123,140,105,118,122,119,123,140,122,119,138,122,123,140,102,144,105,118,85,157,72,177,75,123,85,157,75,123,105,118,85,157,105,118,102,144,61,237,62,253,57,316,61,237,57,316,50,137,61,237,50,137,64,204,64,20 [...]
+96,201,95,210,91,218,85,224,77,228,69,229,60,228,52,224,46,218,42,211,41,201,42,193,46,185,52,179,60,176,69,174,77,176,85,179,91,185,95,193,96,201,16383,16383,96,22,95,31,91,38,85,45,77,49,69,50,60,49,52,45,46,39,42,31,41,22,42,13,46,6,52,0,60,-3,69,-5,77,-3,85,0,91,6,95,13,96,22,
+42,211,42,193,46,218,46,218,42,193,46,185,46,218,46,185,52,224,52,224,46,185,52,179,52,224,52,179,60,228,60,228,52,179,60,176,60,228,60,176,69,229,69,229,60,176,69,174,69,229,69,174,77,228,77,228,69,174,77,176,77,228,77,176,85,224,85,224,77,176,85,179,85,224,85,179,91,218,91,218,85,179,91,185,91,218,91,185,95,210,95,210,91,185,95,193,95,210,95,193,96,201,42,31,42,13,46,39,46,39,42,13,46,6,46,39,46,6,52,45,52,45,46,6,52,0,52,45,52,0,60,49,60,49,52,0,60,-3,60,49,60,-3,69,50,69,50,60,-3,69, [...]
+95,201,94,210,90,218,84,224,77,228,68,229,59,228,51,224,45,218,42,211,40,201,42,193,46,185,52,179,59,176,68,174,77,176,84,179,90,185,94,193,95,201,16383,16383,54,-69,73,-58,88,-44,100,-28,107,-11,109,7,107,22,102,34,93,43,82,49,70,51,60,49,52,46,46,40,42,32,40,23,41,14,45,7,51,2,59,-1,69,-2,72,-2,75,-1,78,-1,81,0,85,0,87,-2,89,-3,90,-5,90,-7,88,-17,83,-28,75,-38,63,-49,49,-60,
+42,211,42,193,45,218,45,218,42,193,46,185,45,218,46,185,51,224,51,224,46,185,52,179,51,224,52,179,59,228,59,228,52,179,59,176,59,228,59,176,68,229,68,229,59,176,68,174,68,229,68,174,77,228,77,228,68,174,77,176,77,228,77,176,84,224,84,224,77,176,84,179,84,224,84,179,90,218,90,218,84,179,90,185,90,218,90,185,94,210,94,210,90,185,94,193,94,210,94,193,95,201,75,-1,78,-1,82,49,82,49,78,-1,81,0,82,49,81,0,83,0,83,0,85,0,93,43,93,43,85,0,87,-2,93,43,87,-2,89,-3,40,23,41,14,42,32,42,32,41,14,45, [...]
+310,-11,310,20,94,127,310,234,310,267,28,129,28,124,
+94,127,310,234,310,267,94,127,310,267,28,129,94,127,28,129,310,-11,94,127,310,-11,310,20,310,-11,28,129,28,124,
+319,160,319,193,24,193,24,160,16383,16383,319,60,319,93,24,93,24,60,
+24,193,24,160,319,160,24,193,319,160,319,193,24,93,24,60,319,60,24,93,319,60,319,93,
+310,124,310,129,28,267,28,234,244,127,28,20,28,-11,
+310,124,310,129,28,267,310,124,28,267,28,234,310,124,28,234,244,127,310,124,244,127,28,20,310,124,28,20,28,-11,
+122,82,126,101,131,118,137,133,145,147,155,161,176,187,191,208,201,226,206,242,207,259,202,286,189,308,169,324,144,335,116,338,89,335,66,325,49,310,38,290,34,267,35,255,38,246,44,239,50,235,58,233,65,234,71,237,75,242,78,248,79,255,77,264,72,270,66,276,62,283,60,292,62,301,69,310,80,317,92,321,107,323,124,320,139,312,151,300,159,283,161,264,160,246,156,227,150,209,136,171,126,147,120,127,116,109,114,95,113,82,16383,16383,145,22,144,30,140,38,134,44,127,48,119,49,110,48,103,44,97,38,93,31 [...]
+60,292,60,292,60,292,60,292,66,325,49,310,60,292,49,310,50,235,60,292,50,235,58,233,144,335,116,338,124,320,124,320,116,338,107,323,92,321,107,323,116,338,92,321,116,338,89,335,60,292,62,301,66,325,66,325,62,301,69,310,66,325,69,310,89,335,89,335,69,310,80,317,89,335,80,317,92,321,34,267,35,255,38,290,38,290,35,255,38,246,38,290,38,246,49,310,49,310,38,246,44,239,49,310,44,239,50,235,62,283,65,234,66,276,66,276,65,234,71,237,66,276,71,237,72,270,72,270,71,237,75,242,72,270,75,242,77,264, [...]
+344,36,323,27,303,20,283,16,263,13,243,12,196,19,156,40,126,71,107,112,100,161,101,184,105,206,112,227,120,247,131,265,148,285,167,301,189,313,214,320,241,323,286,316,326,296,357,267,377,229,384,186,381,157,372,130,358,108,341,94,321,88,314,89,308,92,304,96,301,103,300,112,300,115,301,117,301,120,334,247,300,247,295,228,294,228,289,238,284,245,276,250,268,253,257,254,242,252,229,248,216,241,204,231,194,219,183,203,174,185,167,167,162,147,161,128,163,109,169,93,179,82,191,75,204,72,219,74 [...]
+156,40,126,71,132,24,132,24,126,71,107,112,132,24,107,112,93,61,93,61,107,112,100,161,105,282,100,161,101,184,105,282,101,184,105,206,105,206,112,227,128,304,128,304,112,227,120,247,128,304,120,247,131,265,131,265,148,285,148,316,148,316,148,285,167,301,148,316,167,301,169,326,169,326,167,301,189,313,169,326,189,313,191,333,191,333,189,313,214,320,191,333,214,320,215,337,215,337,214,320,241,323,215,337,241,323,241,338,241,338,241,323,293,331,93,61,100,161,105,282,93,61,105,282,86,257,93, [...]
+353,0,353,9,340,12,330,17,321,26,314,38,306,55,184,337,174,337,70,93,55,58,44,34,33,20,22,13,7,9,7,0,107,0,107,9,94,10,84,12,77,16,73,22,72,30,72,34,73,38,74,43,76,51,99,108,230,108,251,61,257,45,259,38,260,31,261,26,260,23,259,21,258,18,256,16,250,12,242,10,235,10,226,9,226,0,16383,16383,224,128,108,128,166,266,
+55,58,73,22,72,30,72,30,72,34,70,93,70,93,72,34,73,38,70,93,73,38,74,43,174,337,76,51,99,108,174,337,99,108,108,128,108,128,99,108,230,108,108,128,230,108,224,128,224,128,230,108,306,55,224,128,306,55,184,337,246,11,242,10,353,0,353,0,242,10,235,10,353,0,235,10,226,9,259,21,258,18,353,0,353,0,258,18,256,16,353,0,256,16,253,14,253,14,250,12,353,0,353,0,250,12,246,11,261,26,353,0,330,17,261,26,330,17,321,26,261,26,321,26,314,38,261,26,314,38,306,55,261,26,306,55,260,31,306,55,230,108,251,6 [...]
+211,175,225,178,236,182,245,185,259,195,266,203,272,213,276,224,279,235,280,248,274,277,258,300,232,317,195,327,148,331,8,331,8,321,29,320,43,316,51,308,55,295,56,275,56,56,55,37,51,24,42,16,29,11,8,9,8,0,177,0,217,4,250,15,275,34,291,58,296,89,295,102,292,115,287,126,281,137,272,147,263,154,254,160,242,166,229,170,211,174,16383,16383,108,183,108,303,109,307,112,310,115,312,119,313,140,313,172,309,197,301,214,287,225,268,228,245,225,223,217,205,202,193,181,186,153,183,16383,16383,108,163 [...]
+51,24,42,16,177,0,177,0,42,16,29,11,177,0,29,11,8,9,55,295,56,275,112,310,55,295,112,310,148,331,148,331,112,310,115,312,148,331,115,312,119,313,148,331,119,313,140,313,148,331,140,313,172,309,207,30,194,24,217,4,217,4,194,24,179,20,217,4,179,20,177,0,177,0,179,20,161,19,177,0,161,19,138,18,138,18,126,19,177,0,177,0,126,19,118,21,177,0,118,21,55,37,55,37,118,21,56,56,258,300,232,317,236,182,236,182,232,317,228,245,236,182,228,245,225,223,236,182,225,223,225,178,225,178,225,223,217,205,22 [...]
+307,65,285,47,265,32,244,23,222,17,197,15,177,17,157,21,139,28,123,38,108,51,95,68,85,88,78,112,73,140,72,171,77,219,93,260,117,291,151,311,192,318,211,316,228,311,244,304,259,293,272,280,279,272,285,263,290,252,295,240,299,224,310,224,305,338,296,338,293,332,290,328,285,324,280,322,275,321,269,322,262,324,254,326,240,330,228,333,204,337,192,338,180,338,153,336,127,330,102,320,80,305,59,286,44,266,31,243,22,218,16,191,14,162,16,133,22,106,32,80,45,57,62,37,81,22,103,9,127,0,153,-4,180,-6 [...]
+62,37,73,140,72,171,72,171,80,305,62,37,62,37,80,305,59,286,62,37,59,286,45,57,45,57,59,286,44,266,45,57,44,266,32,80,32,80,44,266,31,243,32,80,31,243,22,106,22,106,31,243,22,218,22,106,22,218,16,133,16,133,22,218,16,191,16,133,16,191,14,162,78,112,81,22,85,88,85,88,81,22,103,9,85,88,103,9,95,68,95,68,103,9,108,51,123,38,108,51,127,0,123,38,127,0,139,28,139,28,127,0,153,-4,139,28,153,-4,157,21,157,21,153,-4,180,-6,157,21,180,-6,177,17,177,17,180,-6,197,15,222,17,197,15,214,-4,222,17,214, [...]
+8,331,8,321,27,320,40,316,47,308,51,295,52,275,52,57,51,38,48,25,40,16,27,12,8,9,8,0,148,0,178,1,206,6,231,12,254,21,275,32,299,51,318,75,331,102,340,133,343,167,341,196,334,223,324,247,310,267,293,286,270,302,244,314,214,323,180,329,143,331,16383,16383,103,291,104,300,107,306,112,310,119,312,129,313,157,311,182,308,203,301,222,291,241,278,257,260,271,241,280,219,286,193,288,164,286,132,280,104,270,81,255,61,236,45,218,34,200,27,179,22,155,19,127,18,117,19,110,22,106,26,104,33,103,42,
+48,25,40,16,148,0,148,0,40,16,27,12,148,0,27,12,8,9,52,57,51,38,110,22,110,22,51,38,148,0,110,22,148,0,117,19,117,19,148,0,127,18,155,19,127,18,148,0,155,19,148,0,178,1,104,300,107,306,52,275,52,275,107,306,112,310,52,275,112,310,143,331,143,331,112,310,119,312,143,331,119,312,129,313,129,313,119,312,129,312,129,313,129,312,157,311,129,313,157,311,143,331,143,331,157,311,180,329,206,6,231,12,218,34,218,34,231,12,236,45,255,61,236,45,254,21,255,61,254,21,275,32,155,19,178,1,179,22,179,22, [...]
+299,84,285,84,271,57,255,38,234,26,206,20,169,18,151,18,132,19,117,21,108,25,102,31,100,42,100,164,176,164,198,162,213,158,222,150,229,136,233,115,244,115,244,232,233,232,229,212,222,198,213,190,198,185,176,184,100,184,100,294,101,302,103,307,106,310,111,312,184,312,213,311,234,306,247,297,255,282,261,259,273,259,271,331,6,331,6,321,25,320,38,315,45,307,49,294,50,275,50,57,49,37,45,24,38,16,25,12,6,9,6,0,276,0,
+45,24,38,16,276,0,276,0,38,16,25,12,276,0,25,12,6,9,49,294,50,275,106,310,49,294,106,310,45,307,45,307,106,310,111,312,45,307,111,312,271,331,271,331,111,312,118,312,45,24,117,21,49,37,49,37,117,21,108,25,49,37,108,25,50,57,50,57,108,25,102,31,50,57,102,31,50,275,50,275,102,31,100,42,50,275,100,42,100,294,100,184,100,164,176,164,100,184,176,164,176,184,198,185,176,184,198,162,198,185,198,162,213,190,213,190,198,162,213,158,213,190,213,158,222,198,222,198,213,158,222,150,222,198,222,150,2 [...]
+273,259,271,331,6,331,6,321,25,319,38,315,45,307,49,294,50,276,50,61,49,40,45,25,37,16,25,12,6,9,6,0,146,0,146,9,127,12,113,16,105,24,102,37,100,56,100,164,171,164,193,162,209,158,219,150,225,136,228,115,239,115,239,232,228,232,225,212,218,198,208,190,193,185,171,184,100,184,100,292,101,300,102,306,105,310,110,311,118,312,184,312,214,311,234,306,247,297,255,282,261,259,
+38,315,45,307,271,331,271,331,45,307,110,311,271,331,110,311,118,312,271,331,118,312,184,312,271,331,184,312,214,311,50,276,102,37,100,56,100,184,100,164,171,164,100,184,171,164,171,184,193,185,171,184,193,162,193,185,193,162,208,190,208,190,193,162,209,158,208,190,209,158,218,198,218,198,209,158,219,150,218,198,219,150,225,212,225,212,219,150,225,136,225,212,225,136,228,232,228,232,225,136,228,115,228,232,228,115,239,115,271,331,214,311,234,306,271,331,234,306,247,297,271,331,247,297,25 [...]
+354,177,227,177,227,168,246,166,259,162,267,154,270,142,271,122,271,44,268,34,259,25,244,19,226,14,204,13,161,19,124,39,97,69,79,111,73,162,75,191,79,219,86,244,97,266,112,283,125,295,140,305,157,312,175,317,195,318,211,317,227,314,242,308,256,300,268,291,276,282,283,273,290,262,296,249,304,233,315,233,311,338,300,338,298,333,294,328,289,325,283,322,277,321,274,322,270,322,266,323,261,325,256,326,243,331,230,334,218,336,204,338,189,338,161,336,135,331,111,322,89,310,70,295,51,275,36,251, [...]
+16,164,18,135,19,195,19,195,18,135,23,110,19,195,23,110,25,225,25,225,23,110,31,86,25,225,31,86,36,251,36,251,31,86,42,65,36,251,42,65,51,275,51,275,42,65,57,46,51,275,57,46,70,295,70,295,57,46,73,162,157,312,161,336,140,305,140,305,161,336,135,331,140,305,135,331,125,295,125,295,135,331,112,283,97,266,112,283,111,322,97,266,111,322,89,310,89,310,70,295,75,191,89,310,75,191,79,219,89,310,79,219,86,244,89,310,86,244,97,266,193,-6,204,13,162,-4,162,-4,204,13,161,19,162,-4,161,19,133,2,133, [...]
+352,0,352,9,333,12,320,17,312,25,308,37,307,55,307,274,308,293,312,307,320,315,333,319,352,321,352,331,211,331,211,321,231,319,244,315,251,307,255,294,256,274,256,180,104,180,104,274,106,294,110,307,118,315,130,319,149,321,149,331,9,331,9,321,28,319,41,315,49,307,53,294,54,274,54,61,53,39,49,25,42,16,29,12,9,9,9,0,148,0,148,9,129,12,117,17,109,25,105,38,104,56,104,157,256,157,256,62,255,41,252,26,244,17,232,12,212,9,212,0,
+49,25,42,16,148,0,148,0,42,16,29,12,148,0,29,12,9,9,149,331,9,331,28,319,149,331,28,319,41,315,149,331,41,315,49,307,149,331,49,307,53,294,149,331,53,294,118,315,149,331,118,315,130,319,149,331,130,319,149,321,54,274,105,38,104,56,104,180,104,157,256,157,104,180,256,157,256,180,256,180,256,157,312,25,256,180,312,25,308,37,54,274,104,56,104,274,54,274,104,274,106,294,54,274,106,294,110,307,54,274,110,307,118,315,54,274,118,315,53,294,252,26,244,17,352,0,352,0,244,17,232,12,352,0,232,12,21 [...]
+157,0,157,9,137,11,122,16,114,24,109,37,108,56,108,276,109,295,113,308,122,316,136,320,157,321,157,331,9,331,9,321,30,320,44,316,53,308,57,295,57,56,56,36,52,23,44,15,30,11,9,9,9,0,
+52,23,44,15,157,0,157,0,44,15,30,11,157,0,30,11,9,9,157,331,9,331,30,320,157,331,30,320,44,316,157,331,44,316,53,308,157,331,53,308,57,295,157,331,57,295,122,316,157,331,122,316,136,320,157,331,136,320,157,321,122,16,114,24,57,56,57,56,114,24,109,37,57,56,109,37,57,276,57,276,109,37,108,56,57,276,108,56,108,276,57,276,108,276,109,295,57,276,109,295,113,308,57,276,113,308,122,316,57,276,122,316,57,295,157,0,157,9,137,11,157,0,137,11,122,16,157,0,122,16,56,36,157,0,56,36,52,23,157,0,9,9,9, [...]
+177,331,33,331,33,321,54,319,67,315,75,308,79,295,80,275,80,47,79,34,78,24,75,17,69,13,61,12,56,13,53,16,51,21,48,27,46,34,42,41,38,47,33,52,28,54,22,55,14,54,7,50,2,44,-1,37,-2,29,0,16,6,6,17,0,31,-5,47,-6,76,-2,100,8,117,28,128,56,131,93,131,275,132,294,136,307,143,315,157,319,177,321,
+78,24,75,17,76,-2,76,-2,75,17,69,13,76,-2,69,13,61,12,61,12,56,13,76,-2,76,-2,56,13,47,-6,157,319,177,321,177,331,157,319,177,331,143,315,143,315,177,331,79,295,143,315,79,295,80,275,100,8,80,275,80,47,100,8,80,47,79,34,131,275,132,294,117,28,131,275,117,28,128,56,131,275,128,56,131,93,132,294,136,307,80,275,132,294,80,275,100,8,132,294,100,8,117,28,177,331,33,331,54,319,177,331,54,319,67,315,177,331,67,315,75,308,177,331,75,308,79,295,78,24,76,-2,100,8,78,24,100,8,79,34,47,-6,56,13,53,1 [...]
+362,0,362,9,349,11,336,16,322,25,305,41,283,64,166,192,259,281,278,298,292,309,305,316,320,320,338,321,338,331,208,331,208,321,220,321,229,320,235,318,238,315,240,311,241,305,239,298,234,289,226,280,202,256,113,174,113,293,117,307,124,315,137,319,158,321,158,331,17,331,17,321,37,319,50,315,57,306,61,293,62,275,62,63,61,40,57,26,50,17,36,12,17,9,17,0,157,0,157,9,139,12,126,16,118,23,114,36,113,55,113,148,126,158,176,107,198,84,217,63,232,46,241,32,244,22,244,18,241,15,237,12,231,11,224,10 [...]
+158,321,158,321,137,319,137,319,158,321,158,331,137,319,158,331,124,315,124,315,158,331,61,293,124,315,61,293,62,275,114,36,62,275,62,63,114,36,62,63,118,23,118,23,62,63,126,16,62,275,114,36,113,55,113,174,113,148,126,158,113,174,126,158,202,256,202,256,126,158,166,192,202,256,166,192,259,281,62,275,113,55,113,274,62,275,113,274,113,293,62,275,113,293,117,307,62,275,117,307,124,315,158,331,17,331,37,319,158,331,37,319,50,315,158,331,50,315,57,306,158,331,57,306,61,293,234,289,226,280,259 [...]
+299,87,286,87,277,69,273,62,265,50,254,39,239,30,223,24,203,21,180,20,127,20,114,22,106,26,102,32,100,42,100,274,101,294,105,307,113,315,127,319,147,321,147,331,6,331,6,321,26,319,38,314,46,306,49,292,50,273,50,57,49,38,45,25,37,16,25,12,6,9,6,0,275,0,
+147,321,147,321,127,319,127,319,147,321,147,331,127,319,147,331,113,315,113,315,147,331,49,292,113,315,49,292,50,273,102,32,50,273,50,57,102,32,50,57,106,26,106,26,50,57,49,38,106,26,49,38,114,22,114,22,49,38,45,25,114,22,45,25,127,20,127,20,45,25,275,0,127,20,275,0,146,20,146,20,275,0,180,20,100,42,100,274,50,273,50,273,100,274,101,294,50,273,101,294,105,307,147,331,6,331,26,319,147,331,26,319,38,314,147,331,38,314,46,306,147,331,46,306,49,292,277,69,273,62,275,0,275,0,273,62,269,56,275 [...]
+432,0,432,9,413,12,401,17,393,25,389,38,388,56,388,275,389,294,393,307,401,316,413,320,431,321,431,331,332,331,222,80,106,331,7,331,7,321,28,319,42,315,50,307,54,294,55,275,55,75,54,47,49,29,41,18,27,12,6,9,6,0,123,0,123,9,103,12,90,18,82,29,78,48,76,75,76,275,203,0,209,0,337,286,337,61,336,40,333,26,325,17,312,12,292,9,292,0,
+49,29,41,18,123,0,123,0,41,18,27,12,123,0,27,12,6,9,333,26,325,17,432,0,432,0,325,17,312,12,432,0,312,12,292,9,413,320,431,321,431,331,413,320,431,331,401,316,401,316,431,331,337,286,401,316,337,286,393,307,393,307,337,286,389,294,401,17,393,25,337,61,337,61,393,25,389,38,337,61,389,38,337,286,337,286,389,38,388,56,337,286,388,56,388,275,203,0,209,0,222,80,222,80,209,0,337,286,222,80,337,286,332,331,332,331,337,286,431,331,106,331,7,331,28,319,106,331,28,319,42,315,106,331,42,315,50,307, [...]
+353,331,235,331,235,321,247,320,256,319,263,317,275,309,278,303,281,295,283,285,284,274,284,89,91,331,6,331,6,321,19,321,29,318,37,313,46,306,55,295,55,75,54,48,49,30,41,19,27,13,6,9,6,0,123,0,123,9,103,13,90,20,82,31,78,49,76,75,76,269,297,-5,306,-5,306,274,308,289,311,299,315,307,320,313,324,315,329,318,335,319,343,320,353,321,
+49,30,41,19,123,0,123,0,41,19,27,13,123,0,27,13,6,9,256,319,263,317,353,331,353,331,263,317,269,313,353,331,269,313,275,309,275,309,278,303,353,331,353,331,278,303,281,295,353,331,281,295,324,315,324,315,281,295,320,313,324,315,320,313,320,312,320,312,320,313,315,307,315,307,320,313,284,274,315,307,284,274,284,259,297,-5,284,259,284,89,297,-5,284,89,91,331,353,331,324,315,329,318,353,331,329,318,335,319,353,331,335,319,343,320,353,331,343,320,353,321,306,-5,306,253,297,-5,297,-5,306,253, [...]
+344,166,336,222,314,269,280,306,235,330,180,338,126,330,81,307,46,271,24,224,17,167,24,109,46,61,81,24,126,1,180,-6,234,1,279,24,314,60,336,108,344,166,16383,16383,287,169,285,134,280,103,272,76,260,53,246,35,235,26,223,19,209,15,196,12,181,11,167,12,154,15,142,19,130,25,119,33,103,52,90,75,81,102,76,132,74,166,76,194,80,222,87,247,97,269,108,286,121,298,134,308,149,314,164,318,180,320,194,319,207,316,219,311,231,305,242,296,257,279,270,257,279,231,285,201,287,169,
+149,314,180,338,134,308,134,308,180,338,126,330,134,308,126,330,121,298,121,298,126,330,108,286,97,269,108,286,126,330,97,269,126,330,81,307,81,102,81,24,90,75,90,75,81,24,126,1,90,75,126,1,103,52,103,52,126,1,119,33,130,25,119,33,126,1,130,25,126,1,180,-6,207,316,235,330,194,319,194,319,235,330,180,320,164,318,180,320,180,338,164,318,180,338,149,314,81,307,46,271,46,61,81,307,46,61,74,166,81,307,74,166,76,194,81,307,76,194,80,222,81,307,80,222,87,247,81,307,87,247,97,269,81,102,76,132,8 [...]
+8,331,8,321,27,319,39,315,46,307,49,294,50,276,50,39,47,25,40,16,27,12,8,9,8,0,148,0,148,9,128,12,114,16,106,24,102,37,101,56,101,146,109,145,115,145,122,144,136,144,164,145,188,147,208,153,225,161,243,175,253,185,260,197,266,210,270,225,271,240,270,254,267,268,262,280,255,291,246,300,231,310,213,319,191,325,166,329,137,331,16383,16383,101,295,101,302,103,307,106,310,111,312,118,313,155,310,182,302,202,288,213,266,217,238,213,213,202,192,185,177,162,167,132,164,120,164,114,165,108,165,101,166,
+111,312,118,312,118,313,137,331,118,313,155,310,137,331,155,310,166,329,166,329,155,310,182,302,166,329,182,302,191,325,191,325,182,302,202,288,191,325,202,288,213,319,213,319,202,288,213,266,213,319,213,266,231,310,231,310,213,266,217,238,231,310,217,238,225,161,225,161,213,213,208,153,208,153,213,213,202,192,208,153,202,192,188,147,188,147,202,192,185,177,188,147,185,177,164,145,164,145,185,177,162,167,164,145,162,167,136,144,136,144,162,167,132,164,136,144,132,164,128,144,128,144,132, [...]
+350,-88,350,-78,318,-74,288,-65,261,-51,236,-30,213,-2,232,1,248,6,263,12,277,21,290,32,309,54,324,77,335,104,342,133,344,166,336,224,314,272,279,308,234,330,180,338,127,330,82,308,47,272,25,224,17,166,18,140,23,115,31,92,42,70,55,50,67,36,79,25,94,16,111,7,132,0,153,-25,177,-48,206,-66,241,-78,282,-85,326,-88,16383,16383,287,169,285,139,281,111,275,85,266,64,255,47,243,35,230,25,215,18,198,13,180,11,163,13,146,18,129,26,115,37,103,50,93,68,85,89,79,113,75,139,74,167,76,196,80,222,87,247 [...]
+79,113,79,25,85,89,85,89,79,25,94,16,85,89,94,16,93,68,93,68,94,16,103,50,115,37,103,50,111,7,115,37,111,7,132,0,79,113,75,139,79,25,79,25,75,139,74,167,67,36,74,167,76,196,67,36,76,196,55,50,55,50,76,196,82,308,55,50,82,308,47,272,147,314,180,338,133,307,133,307,180,338,127,330,133,307,127,330,119,297,119,297,127,330,107,285,96,268,107,285,127,330,96,268,127,330,82,308,129,26,132,0,146,18,146,18,132,0,153,-25,146,18,153,-25,163,13,163,13,153,-25,177,-48,163,13,177,-48,180,11,180,11,177, [...]
+330,0,330,9,318,11,308,13,299,17,291,24,283,33,183,160,216,168,242,180,260,197,270,217,273,242,272,255,270,268,265,281,258,292,249,301,234,311,217,319,196,326,172,330,145,331,8,331,8,321,28,319,40,315,47,307,50,294,51,276,51,62,50,40,47,25,39,16,27,12,8,9,8,0,147,0,147,9,127,12,114,16,107,24,103,37,102,56,102,153,130,154,249,0,16383,16383,102,291,103,300,106,306,111,310,118,312,127,313,161,310,186,302,205,289,215,270,219,246,218,231,214,218,208,206,200,196,190,189,177,182,163,177,147,174 [...]
+118,312,127,312,127,313,145,331,127,313,161,310,145,331,161,310,172,330,172,330,161,310,186,302,172,330,186,302,196,326,196,326,186,302,205,289,196,326,205,289,217,319,217,319,205,289,215,270,217,319,215,270,219,246,214,218,208,206,216,168,216,168,208,206,200,196,216,168,200,196,190,189,190,189,177,182,183,160,183,160,177,182,163,177,183,160,163,177,249,0,249,0,163,177,147,174,249,0,147,174,130,154,130,154,147,174,128,172,130,154,128,172,102,171,265,281,258,292,260,197,260,197,258,292,24 [...]
+234,232,224,338,213,338,211,332,209,327,206,324,202,322,197,321,194,321,190,322,185,323,175,327,164,331,154,334,134,338,123,338,95,334,71,323,52,305,40,281,36,251,38,232,44,214,56,196,73,180,97,165,116,154,135,142,152,130,168,118,180,107,185,100,189,93,192,85,194,77,195,67,192,49,184,33,172,21,155,14,136,11,109,15,85,25,65,42,47,67,32,99,22,99,36,-6,47,-6,48,0,50,4,53,7,57,9,61,10,64,10,79,7,84,4,96,0,107,-2,131,-6,143,-6,176,-2,204,10,226,29,240,55,246,86,243,108,233,128,218,148,196,166 [...]
+50,4,53,7,65,42,65,42,53,7,57,9,65,42,57,9,61,10,61,10,64,10,65,42,65,42,64,10,69,9,65,42,69,9,85,25,85,25,69,9,74,8,85,25,74,8,79,7,95,234,83,251,97,165,97,165,83,251,79,270,73,180,79,270,71,323,73,180,71,323,56,196,56,196,71,323,52,305,56,196,52,305,44,214,44,214,52,305,40,281,44,214,40,281,38,232,38,232,40,281,36,251,81,286,88,299,95,334,95,334,88,299,98,309,95,334,98,309,123,338,123,338,98,309,112,315,123,338,112,315,129,318,129,318,146,316,134,338,134,338,146,316,144,336,81,286,95,3 [...]
+296,246,293,331,12,331,8,246,21,246,27,274,37,292,50,303,70,309,97,310,127,310,127,61,126,39,123,25,115,16,101,12,80,9,80,0,226,0,226,9,205,11,192,16,183,23,179,36,178,55,178,310,208,310,235,309,254,303,268,292,277,274,285,246,
+293,331,12,331,70,309,293,331,70,309,97,310,293,331,97,310,127,310,293,331,127,310,178,310,293,331,178,310,208,310,293,331,208,310,235,309,293,331,235,309,254,303,293,331,254,303,268,292,293,331,268,292,277,274,293,331,277,274,285,246,293,331,285,246,296,246,192,16,183,23,127,61,127,61,183,23,179,36,127,61,179,36,127,310,127,310,179,36,178,55,127,310,178,55,178,310,12,331,8,246,21,246,12,331,21,246,27,274,12,331,27,274,37,292,12,331,37,292,50,303,12,331,50,303,70,309,226,0,226,9,205,11,2 [...]
+353,331,237,331,237,321,257,319,270,312,279,301,282,283,283,257,283,103,282,85,279,70,273,57,265,45,254,34,241,26,225,20,208,16,189,15,173,16,158,19,146,24,135,30,125,37,115,50,109,63,105,79,104,97,103,118,103,275,104,293,108,306,115,314,128,319,148,321,148,331,7,331,7,321,27,319,40,315,47,308,51,297,52,280,52,124,53,95,58,69,66,48,78,30,93,16,106,8,121,1,138,-3,157,-5,177,-6,204,-5,227,0,247,6,264,17,278,30,290,45,297,62,302,81,305,104,305,258,306,282,310,300,318,311,331,318,353,321,
+105,79,106,8,109,63,109,63,106,8,121,1,109,63,121,1,115,50,115,50,121,1,125,37,135,30,125,37,138,-3,135,30,138,-3,146,24,146,24,138,-3,157,-5,146,24,157,-5,158,19,158,19,157,-5,177,-6,158,19,177,-6,173,16,173,16,177,-6,189,15,208,16,189,15,204,-5,208,16,204,-5,227,0,103,118,103,275,93,16,103,118,93,16,104,97,104,97,93,16,106,8,104,97,106,8,105,79,125,37,121,1,138,-3,283,103,282,85,290,45,290,45,282,85,279,70,290,45,279,70,278,30,278,30,279,70,273,57,278,30,273,57,265,45,265,45,254,34,264 [...]
+349,331,247,331,247,321,258,321,268,319,276,316,281,310,282,301,282,295,281,289,279,282,276,274,273,265,200,80,123,252,116,269,110,283,106,292,104,300,104,305,105,310,107,314,112,317,118,319,127,320,141,321,141,331,8,331,8,321,21,320,31,316,41,307,50,291,62,267,184,-5,191,-5,302,276,311,295,319,308,328,316,338,320,349,321,
+62,267,184,-5,62,267,62,267,184,-5,104,300,62,267,104,300,104,305,104,305,105,310,62,267,62,267,105,310,107,314,62,267,107,314,50,291,141,331,8,331,21,320,141,331,21,320,31,316,141,331,31,316,41,307,141,331,41,307,50,291,141,331,50,291,112,317,141,331,112,317,118,319,141,331,118,319,127,320,141,331,127,320,141,321,281,289,279,282,302,276,302,276,279,282,276,274,302,276,276,274,273,265,273,265,200,80,302,276,302,276,200,80,191,-5,349,331,247,331,258,321,349,331,258,321,268,319,349,331,268 [...]
+466,331,368,331,368,321,381,320,391,318,397,314,401,308,402,301,402,294,401,287,399,280,397,271,394,262,331,93,259,275,255,289,253,295,252,300,251,304,253,310,257,315,265,318,276,320,290,321,290,331,157,331,157,321,171,320,182,317,191,309,199,295,208,273,222,236,170,94,98,282,96,288,95,293,93,298,93,311,96,316,102,319,111,321,124,321,124,331,2,331,2,321,16,320,27,314,36,303,45,286,55,262,73,210,92,157,132,49,151,-5,158,-5,235,206,251,165,267,123,299,37,315,-5,323,-5,344,61,361,111,377,15 [...]
+16,320,27,314,124,331,124,331,27,314,36,303,124,331,36,303,96,316,96,316,36,303,45,286,96,316,45,286,55,262,55,262,73,210,93,311,93,311,73,210,93,306,93,302,93,306,92,157,93,302,92,157,112,103,111,321,124,321,124,331,111,321,124,331,102,319,102,319,124,331,96,316,93,306,73,210,92,157,96,316,55,262,93,311,2,331,2,321,16,320,2,331,16,320,124,331,251,165,267,123,251,304,251,304,253,310,222,236,222,236,253,310,208,273,199,295,208,273,257,315,199,295,257,315,290,331,290,331,257,315,265,318,29 [...]
+352,0,352,9,338,12,327,16,317,22,307,32,296,46,200,184,272,272,289,292,303,305,316,314,331,319,348,321,348,331,229,331,229,321,243,320,253,319,259,316,262,311,263,305,263,301,260,296,257,290,251,282,243,272,188,202,166,234,151,255,139,272,131,286,126,297,124,306,125,312,128,316,133,319,139,320,147,321,161,321,161,331,11,331,11,321,29,319,44,312,59,299,78,276,103,242,156,164,78,66,58,42,43,26,31,17,19,12,5,9,5,0,121,0,121,9,106,11,95,13,88,17,84,21,83,26,84,31,87,38,92,46,100,57,109,70,16 [...]
+31,17,121,0,43,26,43,26,121,0,88,17,43,26,88,17,58,42,58,42,88,17,84,21,58,42,84,21,83,26,83,26,84,31,78,66,78,66,84,31,87,38,78,66,87,38,156,164,156,164,87,38,92,46,156,164,92,46,100,57,103,242,156,164,126,297,103,242,126,297,124,306,124,306,125,312,103,242,156,164,100,57,109,70,109,70,169,145,156,164,156,164,169,145,166,234,156,164,166,234,151,255,78,66,58,42,83,26,103,242,125,312,78,276,78,276,125,312,128,316,78,276,128,316,59,299,59,299,128,316,133,319,59,299,133,319,161,331,161,331, [...]
+352,331,243,331,243,321,256,321,266,319,272,316,275,312,276,306,276,302,274,294,272,290,270,285,197,174,124,285,121,289,118,294,116,299,115,304,115,308,116,312,119,316,123,318,130,320,138,321,151,321,151,331,11,331,11,321,24,319,37,313,50,299,68,277,92,243,157,147,157,61,156,39,152,25,144,16,129,12,107,9,107,0,260,0,260,9,239,11,224,15,215,23,210,36,209,55,209,151,282,266,297,288,310,303,322,313,336,319,352,321,
+121,289,118,294,157,147,157,147,118,294,116,299,157,147,116,299,92,243,92,243,116,299,115,304,92,243,115,304,115,308,115,308,116,312,92,243,151,331,11,331,24,319,151,331,24,319,37,313,151,331,37,313,50,299,151,331,50,299,123,318,151,331,123,318,130,320,151,331,130,320,138,321,151,331,138,321,151,321,123,318,50,299,119,316,119,316,50,299,68,277,119,316,68,277,116,312,116,312,68,277,92,243,209,55,209,151,197,174,209,55,197,174,210,36,210,36,197,174,157,147,210,36,157,147,215,23,215,23,157, [...]
+299,88,287,88,282,72,278,59,273,49,266,40,257,33,249,28,240,24,228,21,215,20,199,19,73,19,289,324,289,331,26,331,16,246,29,246,32,260,35,271,38,279,43,287,50,295,58,301,68,306,81,309,97,311,117,312,224,312,5,7,5,0,286,0,
+35,271,38,279,26,331,26,331,38,279,43,287,26,331,43,287,50,295,50,295,58,301,26,331,26,331,58,301,68,306,26,331,68,306,81,309,73,19,289,324,224,312,224,312,289,324,289,331,224,312,289,331,117,312,97,311,117,312,289,331,97,311,289,331,26,331,26,331,16,246,29,246,26,331,29,246,32,260,26,331,32,260,35,271,224,312,5,7,73,19,73,19,5,7,286,0,73,19,286,0,199,19,199,19,286,0,215,20,278,59,273,49,286,0,286,0,273,49,266,40,286,0,266,40,257,33,257,33,249,28,286,0,286,0,249,28,240,24,286,0,240,24,22 [...]
+150,-77,150,-64,108,-64,99,-63,92,-61,86,-56,83,-48,82,-38,82,295,83,304,86,311,92,315,99,318,108,319,150,319,150,331,44,331,44,-77,
+86,311,92,315,44,331,44,331,92,315,99,318,44,331,99,318,150,331,150,331,99,318,108,319,82,-38,82,295,44,331,82,-38,44,331,44,-77,82,-38,44,-77,83,-48,83,304,86,311,44,331,83,304,44,331,82,295,150,-64,108,-64,150,-77,150,-77,108,-64,99,-63,150,-77,99,-63,44,-77,44,-77,99,-63,92,-61,44,-77,92,-61,86,-56,83,-48,44,-77,86,-56,150,331,108,319,150,319,
+143,-6,29,338,-3,338,109,-6,
+143,-6,29,338,-3,338,143,-6,-3,338,109,-6,
+123,-77,123,331,17,331,17,319,59,319,69,318,76,314,81,309,83,301,84,291,84,-50,81,-56,77,-61,70,-63,61,-64,17,-64,17,-77,
+123,-77,123,331,84,291,123,-77,84,291,84,-41,123,-77,84,-41,84,-50,123,-77,84,-50,81,-56,123,-77,81,-56,77,-61,123,-77,77,-61,70,-63,123,-77,70,-63,61,-64,123,-77,61,-64,17,-64,123,-77,17,-64,17,-77,76,314,81,309,123,331,123,331,81,309,83,301,123,331,83,301,84,291,123,331,17,331,59,319,123,331,59,319,69,318,123,331,69,318,76,314,59,319,17,331,17,319,
+223,148,132,331,103,331,12,148,46,148,118,293,189,148,
+12,148,46,148,103,331,103,331,46,148,118,293,103,331,118,293,132,331,132,331,118,293,189,148,132,331,189,148,223,148,
+250,-62,250,-36,0,-36,0,-62,
+250,-62,250,-36,0,-36,250,-62,0,-36,0,-62,
+121,253,49,328,44,332,40,335,35,337,27,339,21,338,16,336,12,333,10,329,9,323,10,318,12,314,15,309,19,305,24,301,101,253,
+101,253,121,253,49,328,101,253,49,328,44,332,101,253,44,332,40,335,101,253,40,335,35,337,101,253,35,337,31,338,101,253,31,338,27,339,101,253,27,339,24,301,9,323,10,318,10,329,10,329,10,318,12,314,10,329,12,314,12,333,12,333,12,314,15,309,12,333,15,309,16,336,16,336,15,309,19,305,16,336,19,305,21,338,21,338,19,305,24,301,21,338,24,301,27,339,
+221,33,216,29,208,25,200,23,195,25,190,28,187,35,185,44,184,56,184,168,183,181,180,191,176,199,170,208,162,215,152,222,140,226,127,229,111,230,98,229,85,227,73,224,63,220,54,215,44,208,37,200,32,192,29,183,28,175,29,167,33,161,37,156,43,153,50,152,57,153,63,156,68,161,71,167,73,172,72,178,72,182,71,185,70,189,70,194,71,201,76,208,83,213,93,217,104,218,117,216,128,211,136,202,142,190,143,173,143,146,114,135,92,126,75,118,63,112,54,105,42,97,33,87,25,75,20,62,18,47,21,29,28,14,39,4,54,-2,7 [...]
+37,156,43,153,44,208,44,208,43,153,50,152,44,208,50,152,54,215,54,215,50,152,57,153,54,215,57,153,63,220,63,220,57,153,63,156,63,220,63,156,73,224,73,224,63,156,70,194,71,167,70,194,68,161,111,230,104,218,117,216,111,230,117,216,127,229,127,229,117,216,128,211,127,229,128,211,140,226,140,226,128,211,136,202,140,226,136,202,142,190,76,208,83,213,85,227,85,227,83,213,93,217,85,227,93,217,98,229,98,229,93,217,104,218,98,229,104,218,111,230,73,224,70,194,71,201,73,224,71,201,76,208,73,224,76 [...]
+76,340,74,342,62,338,51,334,41,331,29,328,17,324,2,320,2,311,5,311,6,312,10,312,21,311,28,309,32,304,34,296,35,283,35,28,39,18,52,9,71,2,93,-2,117,-4,155,1,187,18,212,44,228,78,234,120,230,155,218,185,199,209,174,224,144,230,126,228,110,223,96,214,85,202,76,188,16383,16383,76,159,79,171,86,182,97,191,111,197,126,199,137,198,146,195,155,190,164,183,171,175,177,163,183,149,186,133,189,116,190,99,189,82,187,67,183,54,178,42,171,32,164,25,156,19,147,15,136,12,125,11,110,12,97,16,86,21,79,28,76,37,
+5,311,6,312,17,324,17,324,6,312,8,312,17,324,8,312,10,312,10,312,21,311,17,324,17,324,21,311,29,328,97,16,86,21,93,-2,93,-2,86,21,79,28,93,-2,79,28,71,2,71,2,79,28,76,37,71,2,76,37,74,342,74,342,76,37,76,188,74,342,76,188,76,340,62,338,51,334,52,9,52,9,51,334,41,331,52,9,41,331,39,18,39,18,41,331,35,283,39,18,35,283,35,28,3,311,5,311,17,324,3,311,17,324,2,320,3,311,2,320,2,311,156,19,147,15,155,1,155,1,147,15,136,12,155,1,136,12,125,11,125,11,110,12,117,-4,117,-4,110,12,97,16,117,-4,97,1 [...]
+199,78,185,60,172,46,159,38,144,33,128,31,103,36,81,49,65,69,54,96,51,128,54,157,63,181,78,200,96,211,119,215,128,215,136,212,141,208,145,201,148,191,151,180,154,172,159,166,163,161,169,158,175,157,183,158,189,161,195,166,198,172,199,179,195,195,184,209,167,220,146,227,122,230,108,229,94,226,80,221,67,213,55,204,40,189,28,172,19,152,14,130,12,106,17,70,30,39,50,15,76,0,108,-4,120,-3,132,-1,144,3,155,9,165,16,174,24,181,32,189,43,197,57,206,74,
+81,49,65,69,76,0,76,0,65,69,54,96,76,0,54,96,50,15,50,15,54,96,51,128,55,204,51,128,54,157,55,204,54,157,63,181,128,31,108,-4,120,-3,128,31,120,-3,132,-1,128,31,103,36,108,-4,81,49,76,0,108,-4,81,49,108,-4,103,36,136,212,141,208,146,227,146,227,141,208,145,201,146,227,145,201,148,191,148,191,151,180,167,220,167,220,151,180,154,172,167,220,154,172,159,166,122,230,119,215,128,215,122,230,128,215,146,227,146,227,128,215,136,212,195,195,184,209,189,161,195,195,189,161,195,166,195,195,195,166 [...]
+246,21,246,29,239,29,237,28,234,28,225,29,218,32,215,37,213,45,212,57,212,340,209,342,195,337,169,329,154,324,136,320,136,311,138,312,147,312,156,311,163,309,167,304,170,297,170,209,159,217,149,223,139,227,129,229,118,230,85,223,56,206,34,178,19,143,13,103,18,67,30,37,49,14,75,0,106,-4,122,-3,136,0,148,7,160,16,170,28,170,-2,172,-4,16383,16383,170,51,170,49,169,46,165,40,162,37,157,31,150,27,143,24,135,22,126,21,102,26,83,39,69,60,60,88,56,123,59,154,67,180,80,199,98,212,119,216,135,213, [...]
+170,209,159,217,160,195,160,195,159,217,149,223,160,195,149,223,149,206,149,206,149,223,139,227,149,206,139,227,135,213,135,213,139,227,129,229,135,213,129,229,119,216,67,180,80,199,85,223,85,223,80,199,98,212,85,223,98,212,118,230,118,230,98,212,119,216,118,230,119,216,129,229,13,103,18,67,19,143,19,143,18,67,30,37,19,143,30,37,34,178,34,178,30,37,49,14,34,178,49,14,56,206,56,206,49,14,56,123,56,206,56,123,59,154,56,206,59,154,67,180,56,206,67,180,85,223,126,21,106,-4,122,-3,126,21,122, [...]
+204,82,190,62,176,48,162,37,146,31,127,30,114,31,101,34,90,39,80,47,71,57,62,71,56,85,52,100,50,118,49,138,203,138,201,153,198,166,195,177,185,195,175,207,163,217,149,224,133,228,116,230,81,224,52,207,31,182,17,148,12,108,17,70,29,39,49,15,75,0,108,-4,136,-1,160,9,181,26,198,49,212,79,16383,16383,50,155,55,175,63,191,74,203,87,210,103,212,120,210,133,203,141,192,147,176,151,155,
+52,100,50,118,49,15,49,15,50,118,49,138,49,15,49,138,31,182,49,15,31,182,29,39,29,39,31,182,17,148,29,39,17,148,17,70,17,70,17,148,12,108,133,228,116,230,120,210,120,210,116,230,103,212,87,210,103,212,116,230,87,210,116,230,81,224,190,62,176,48,181,26,181,26,176,48,162,37,181,26,162,37,160,9,160,9,162,37,146,31,160,9,146,31,136,-1,136,-1,146,31,127,30,203,138,201,153,198,166,203,138,198,166,195,177,203,138,195,177,190,186,203,138,190,186,185,195,203,138,185,195,175,207,203,138,175,207,16 [...]
+11,225,11,209,51,209,51,52,50,34,47,21,40,13,28,9,10,7,10,0,140,0,140,7,119,9,106,13,98,21,95,33,94,52,94,209,155,209,155,225,94,225,94,283,95,299,98,311,104,320,111,326,122,328,128,327,133,325,138,321,143,316,148,308,153,301,157,296,161,293,166,291,171,290,177,291,183,294,188,298,190,304,191,310,189,321,182,329,171,336,156,340,140,342,121,340,105,335,90,328,78,318,69,305,62,292,57,279,54,264,52,247,51,225,
+57,279,54,264,95,33,95,33,54,264,52,247,95,33,52,247,51,209,51,209,52,247,51,225,51,209,51,225,11,225,78,318,95,33,94,52,94,225,94,209,155,209,94,225,155,209,155,225,133,325,140,342,128,327,128,327,140,342,122,328,111,326,122,328,121,340,111,326,121,340,105,335,94,283,95,299,90,328,90,328,95,299,98,311,90,328,98,311,105,335,105,335,98,311,104,320,105,335,104,320,111,326,90,328,78,318,94,52,90,328,94,52,94,283,189,321,182,329,183,294,189,321,183,294,188,298,189,321,188,298,190,304,189,321 [...]
+235,194,235,214,185,214,180,215,175,217,169,219,158,223,134,229,126,230,118,230,91,226,68,214,51,197,39,174,35,148,36,131,41,116,50,103,63,92,81,81,77,77,72,73,60,61,51,53,44,46,40,39,37,33,36,27,37,21,40,16,44,11,52,6,63,1,44,-13,30,-26,21,-37,16,-48,14,-59,18,-75,31,-88,49,-98,73,-105,100,-108,122,-106,144,-102,165,-96,184,-87,200,-76,211,-66,220,-56,226,-46,229,-35,230,-24,228,-6,220,7,207,18,190,26,170,29,105,32,91,33,80,35,72,38,68,41,66,46,68,52,73,60,80,67,88,73,97,77,106,76,111,7 [...]
+85,118,81,81,88,73,88,73,81,81,80,67,80,67,81,81,77,77,80,67,77,77,73,60,73,60,77,77,72,73,73,60,72,73,68,52,68,52,72,73,68,69,68,52,68,69,66,46,66,46,64,65,63,-13,63,-13,64,65,63,1,116,75,127,87,111,75,111,75,127,87,110,91,111,75,110,91,106,76,106,76,110,91,97,77,88,73,97,77,96,102,88,73,96,102,85,118,118,230,113,216,122,215,118,230,122,215,126,230,126,230,122,215,130,212,126,230,130,212,134,229,134,229,130,212,137,207,134,229,137,207,142,227,142,227,137,207,144,201,142,227,144,201,150, [...]
+243,0,243,7,230,10,221,15,216,22,214,34,214,151,211,179,204,201,191,217,174,227,152,230,135,228,120,224,106,216,92,204,79,188,79,340,76,342,66,338,46,332,34,328,18,324,5,320,5,311,6,312,11,312,22,311,29,309,34,305,36,297,36,33,33,22,28,15,19,10,4,7,4,0,113,0,113,7,98,10,88,14,82,22,79,34,79,171,90,184,101,193,112,199,123,202,134,203,148,201,158,195,165,184,170,169,171,150,171,34,168,22,162,14,152,10,137,7,137,0,
+33,22,28,15,113,0,113,0,28,15,19,10,113,0,19,10,4,7,7,312,9,312,18,324,18,324,9,312,10,312,18,324,10,312,11,312,11,312,22,311,18,324,18,324,22,311,34,328,18,324,5,320,6,312,18,324,6,312,7,312,88,14,82,22,36,51,36,51,82,22,79,34,36,51,79,34,36,286,36,297,36,286,46,332,36,297,46,332,34,328,34,328,22,311,29,309,34,328,29,309,34,305,34,328,34,305,36,297,79,188,79,340,76,342,79,188,76,342,79,51,79,51,76,342,66,338,79,51,66,338,79,34,79,34,66,338,56,335,79,34,56,335,46,332,135,228,134,203,148, [...]
+90,316,89,324,85,331,80,337,73,340,65,342,56,340,49,336,44,331,40,324,39,316,40,308,44,301,49,295,56,292,64,291,73,292,80,295,85,301,89,308,90,316,16383,16383,127,0,127,7,110,9,99,14,93,21,90,34,89,52,89,228,88,230,10,203,10,195,20,197,31,197,38,196,42,193,45,187,47,178,47,33,43,20,37,13,25,9,8,7,8,0,
+39,316,40,308,40,324,40,324,40,308,44,301,40,324,44,301,44,331,44,331,44,301,49,295,44,331,49,295,49,336,49,336,49,295,56,292,49,336,56,292,56,340,56,340,56,292,64,291,56,340,64,291,65,342,65,342,64,291,73,292,65,342,73,292,73,340,73,340,73,292,80,295,73,340,80,295,80,337,80,337,80,295,85,301,80,337,85,301,85,331,85,331,85,301,89,308,85,331,89,308,89,324,89,324,89,308,90,316,43,20,37,13,127,0,127,0,37,13,25,9,127,0,25,9,8,7,20,197,24,197,88,230,88,230,24,197,28,197,88,230,28,197,31,197,3 [...]
+97,316,96,324,92,331,86,337,79,340,71,342,63,340,56,336,51,331,47,324,46,316,47,308,51,301,56,295,63,292,71,291,79,292,87,295,92,301,96,308,97,316,16383,16383,97,228,94,230,77,224,62,218,48,213,33,208,16,203,16,195,18,195,23,196,27,197,39,197,45,196,49,193,52,187,54,178,55,167,55,-21,54,-41,54,-56,52,-67,50,-76,47,-82,45,-85,39,-89,35,-91,26,-91,18,-87,14,-83,4,-71,0,-66,-4,-63,-9,-61,-14,-61,-20,-62,-26,-65,-30,-69,-33,-74,-34,-80,-32,-90,-26,-97,-16,-103,-3,-107,12,-108,42,-103,65,-90, [...]
+86,337,87,295,92,331,92,331,87,295,92,301,92,331,92,301,96,324,96,324,92,301,96,308,96,324,96,308,97,316,46,316,47,308,47,324,47,324,47,308,51,301,47,324,51,301,51,331,51,331,51,301,56,295,51,331,56,295,56,336,56,336,56,295,63,292,56,336,63,292,63,340,63,340,63,292,71,291,63,340,71,291,71,342,71,342,71,291,79,292,71,342,79,292,79,340,79,340,79,292,87,295,79,340,87,295,86,337,18,195,23,196,33,208,18,195,33,208,16,203,18,195,16,203,16,195,42,-87,39,-89,42,-103,42,-103,39,-89,35,-91,42,-103 [...]
+252,0,252,7,240,9,228,13,217,20,206,30,194,44,118,141,132,155,164,183,188,201,206,212,222,217,240,218,240,225,138,225,138,218,148,218,155,217,160,215,162,212,163,209,161,203,155,195,151,191,83,131,83,340,81,342,70,338,48,332,35,328,18,324,3,320,3,311,7,312,17,312,20,313,28,312,34,309,38,303,40,294,41,282,41,41,40,28,38,20,32,14,21,11,3,7,3,0,121,0,121,7,110,8,100,9,92,12,87,17,84,24,83,33,83,126,158,26,160,24,162,21,163,19,163,17,164,15,163,13,162,10,153,7,143,7,143,0,
+38,20,32,14,121,0,121,0,32,14,21,11,121,0,21,11,3,7,10,312,14,312,18,324,18,324,14,312,17,312,18,324,17,312,20,313,20,313,28,312,35,328,35,328,28,312,34,309,35,328,34,309,38,303,7,312,10,312,18,324,7,312,18,324,3,320,7,312,3,320,3,311,194,44,118,141,158,26,158,26,118,141,83,131,158,26,83,131,83,126,84,24,83,33,48,332,84,24,48,332,41,282,41,282,48,332,40,294,48,332,35,328,38,303,48,332,38,303,40,294,35,328,18,324,20,313,83,33,83,340,81,342,83,33,81,342,70,338,83,33,70,338,59,335,83,33,59, [...]
+128,0,128,7,112,9,101,13,95,20,92,29,91,44,91,339,89,342,74,337,59,333,45,329,28,324,9,320,9,311,14,312,25,312,28,313,36,311,42,308,46,302,48,293,49,281,49,46,48,32,45,21,38,14,27,10,11,7,11,0,
+45,21,38,14,128,0,128,0,38,14,27,10,128,0,27,10,11,7,18,312,22,312,28,324,28,324,22,312,25,312,28,324,25,312,28,313,28,313,36,311,28,324,28,324,36,311,45,329,28,324,9,320,14,312,28,324,14,312,18,312,36,311,42,308,45,329,45,329,42,308,46,302,45,329,46,302,59,333,59,333,46,302,48,293,59,333,48,293,49,281,92,29,49,281,49,46,92,29,49,46,95,20,95,20,49,46,101,13,91,44,91,339,89,342,91,44,89,342,74,337,91,44,74,337,59,333,91,44,59,333,92,29,128,0,128,7,112,9,128,0,112,9,101,13,128,0,101,13,48, [...]
+387,0,387,7,374,8,366,10,360,13,356,19,354,27,353,39,353,140,351,172,344,197,333,215,317,226,295,230,278,228,262,224,246,215,230,204,214,188,207,203,199,215,188,223,176,228,161,230,147,229,133,226,119,220,103,208,84,191,83,191,83,228,79,230,51,220,25,212,9,208,9,199,13,200,16,200,19,201,26,201,32,200,37,196,41,190,42,181,43,168,43,44,42,29,39,19,32,12,22,9,8,7,8,0,119,0,119,7,105,8,96,11,89,16,86,24,85,35,85,175,99,189,109,195,121,200,133,203,145,204,156,202,165,195,172,183,176,168,177,1 [...]
+16,200,19,201,25,212,25,212,19,201,22,201,25,212,22,201,26,201,26,201,32,200,38,216,38,216,32,200,37,196,38,216,37,196,41,190,25,212,9,208,13,200,25,212,13,200,16,200,38,216,41,190,51,220,51,220,41,190,42,181,51,220,42,181,43,168,86,24,43,168,43,44,86,24,43,44,89,16,89,16,43,44,96,11,38,216,25,212,26,201,83,228,79,230,83,191,83,191,79,230,85,35,83,191,85,35,84,191,84,191,85,35,85,174,84,191,85,174,85,175,173,18,167,12,255,0,255,0,167,12,157,9,255,0,157,9,143,7,161,230,147,229,156,202,156 [...]
+243,0,243,7,230,9,221,13,216,19,213,29,212,42,212,153,210,180,202,201,190,217,174,227,153,230,139,229,125,224,111,216,96,205,81,190,80,190,80,228,76,230,50,220,37,216,23,212,8,208,8,199,10,200,13,200,16,201,22,201,30,200,35,197,38,191,40,181,40,47,39,32,37,21,31,14,22,9,9,7,9,0,114,0,114,7,101,9,92,13,86,18,83,26,82,36,82,174,95,186,105,194,115,199,124,202,133,203,147,201,157,195,164,185,169,171,170,152,170,52,169,35,166,23,161,15,152,10,139,7,138,0,
+37,21,31,14,114,0,114,0,31,14,22,9,114,0,22,9,9,7,13,200,16,201,23,212,23,212,16,201,19,201,23,212,19,201,22,201,22,201,30,200,23,212,23,212,30,200,37,216,23,212,8,208,10,200,23,212,10,200,13,200,30,200,35,197,37,216,37,216,35,197,38,191,37,216,38,191,50,220,50,220,38,191,40,181,50,220,40,181,40,169,83,26,40,169,40,47,83,26,40,47,86,18,86,18,40,47,92,13,80,228,76,230,80,190,80,190,76,230,82,36,80,190,82,36,81,190,81,190,82,36,82,174,81,190,82,174,96,205,96,205,82,174,95,186,96,205,95,186 [...]
+235,116,230,154,215,186,191,210,162,225,127,230,90,225,58,209,35,185,20,153,15,114,20,75,35,42,58,17,88,1,123,-4,160,1,191,17,215,43,230,76,235,116,16383,16383,190,102,187,70,180,44,168,25,151,13,131,9,120,10,110,13,101,18,93,25,86,34,76,51,69,70,64,91,61,113,60,137,62,164,70,186,82,202,98,212,118,216,130,215,140,211,149,206,158,199,165,191,174,177,181,161,186,142,189,122,190,102,
+64,91,58,17,69,70,69,70,58,17,88,1,69,70,88,1,76,51,76,51,88,1,86,34,93,25,86,34,88,1,93,25,88,1,123,-4,162,225,127,230,130,215,130,215,127,230,118,216,98,212,118,216,127,230,98,212,127,230,90,225,187,70,180,44,191,17,191,17,180,44,168,25,191,17,168,25,160,1,160,1,168,25,151,13,160,1,151,13,131,9,131,9,120,10,123,-4,123,-4,120,10,110,13,123,-4,110,13,101,18,140,211,149,206,162,225,162,225,149,206,158,199,162,225,158,199,165,191,165,191,174,177,191,210,191,210,174,177,181,161,191,210,181, [...]
+79,229,76,230,62,224,20,209,4,204,4,196,7,197,17,197,26,196,31,194,35,189,37,180,37,-78,34,-87,27,-93,17,-97,2,-99,2,-107,123,-107,123,-98,104,-97,92,-94,84,-88,80,-77,79,-61,79,17,90,8,99,2,108,-1,118,-3,130,-4,164,1,193,19,215,47,230,82,235,123,231,158,219,188,202,210,179,225,151,230,135,228,120,224,106,216,93,205,79,190,16383,16383,79,167,82,176,91,185,103,193,116,198,131,200,151,195,168,183,181,163,189,136,192,103,189,73,181,47,168,28,152,15,132,11,117,13,103,18,91,26,82,35,79,44,
+34,-87,27,-93,123,-107,123,-107,27,-93,17,-97,123,-107,17,-97,2,-99,9,197,12,197,20,209,20,209,12,197,14,197,20,209,14,197,17,197,17,197,26,196,20,209,20,209,26,196,34,214,20,209,4,204,7,197,20,209,7,197,9,197,82,35,79,44,90,8,90,8,79,44,79,17,80,-77,79,-61,48,219,80,-77,48,219,37,169,37,169,48,219,37,180,26,196,31,194,34,214,34,214,31,194,35,189,34,214,35,189,48,219,48,219,35,189,37,180,79,190,79,229,76,230,79,190,76,230,79,-61,79,190,79,-61,79,167,79,190,79,167,82,176,79,190,82,176,93, [...]
+244,-107,244,-99,231,-97,222,-93,216,-88,213,-80,213,228,207,228,180,213,167,220,155,224,144,228,122,230,87,224,57,206,33,179,18,144,12,103,16,67,27,38,44,15,66,0,92,-4,109,-2,126,1,142,8,157,19,171,32,171,-61,169,-75,165,-86,157,-93,144,-97,126,-99,126,-107,16383,16383,171,64,170,57,170,52,168,47,167,44,165,41,149,31,140,28,130,26,112,26,96,30,89,34,83,39,74,50,66,64,60,81,56,100,55,121,58,153,67,179,81,199,100,211,124,215,141,214,154,208,163,198,169,184,171,166,
+112,26,104,28,109,-2,109,-2,104,28,96,30,109,-2,96,30,92,-4,92,-4,96,30,89,34,92,-4,89,34,83,39,83,39,74,50,92,-4,92,-4,74,50,66,64,92,-4,66,64,66,0,66,0,66,64,60,81,66,0,60,81,56,100,109,-2,126,1,112,26,112,26,126,1,121,26,130,26,121,26,126,1,130,26,126,1,142,8,133,229,124,215,141,214,133,229,141,214,144,228,144,228,141,214,154,208,144,228,154,208,155,224,155,224,154,208,163,198,155,224,163,198,167,220,167,220,163,198,169,184,167,220,169,184,180,213,180,213,169,184,171,166,180,213,171,1 [...]
+80,229,78,230,62,224,48,219,35,214,20,209,3,203,3,195,7,196,11,196,14,197,21,197,28,196,32,193,36,187,37,179,38,167,38,42,37,29,35,21,29,15,18,11,2,7,2,0,123,0,123,7,105,9,93,13,85,20,81,30,80,45,80,157,82,168,88,179,97,189,106,196,115,199,119,197,122,196,125,194,128,191,133,187,137,184,141,182,144,181,148,181,155,182,160,185,164,190,167,196,167,204,166,213,163,220,157,225,149,229,140,230,128,228,117,224,106,215,94,202,80,183,
+11,196,14,197,20,209,20,209,14,197,18,197,20,209,18,197,21,197,21,197,28,196,35,214,35,214,28,196,32,193,35,214,32,193,36,187,20,209,3,203,7,196,20,209,7,196,11,196,80,183,80,229,78,230,80,183,78,230,80,45,80,45,78,230,62,224,80,45,62,224,81,30,81,30,62,224,48,219,81,30,48,219,38,167,38,167,48,219,37,179,48,219,35,214,36,187,48,219,36,187,37,179,35,214,20,209,21,197,122,196,128,228,119,197,119,197,128,228,117,224,119,197,117,224,117,198,117,198,117,224,115,199,106,196,115,199,117,224,106 [...]
+78,151,71,156,64,163,60,170,57,178,56,185,58,197,63,207,71,214,82,217,94,219,110,217,123,210,134,198,143,181,151,157,158,157,156,225,150,225,145,220,140,220,137,221,134,221,131,223,122,226,115,228,109,229,94,229,72,227,53,219,38,207,29,190,26,168,28,153,35,138,47,123,63,109,85,95,113,80,129,68,134,60,138,52,139,43,137,31,132,21,123,13,112,8,98,6,79,9,63,17,51,31,41,50,34,76,26,76,26,-1,32,-1,34,0,36,2,39,3,41,4,48,4,52,3,56,3,61,1,68,0,75,-2,82,-3,90,-4,104,-4,126,-1,145,7,160,21,170,38, [...]
+36,2,39,3,41,50,41,50,39,3,41,4,41,50,41,4,45,4,45,4,48,4,51,31,51,31,48,4,52,3,51,31,52,3,63,17,63,17,52,3,56,3,63,17,56,3,61,1,36,2,41,50,34,0,34,0,41,50,34,76,34,0,34,76,32,-1,32,-1,34,76,26,76,32,-1,26,76,26,-1,72,227,53,219,58,197,58,197,53,219,56,185,63,109,56,185,53,219,63,109,53,219,47,123,47,123,53,219,38,207,47,123,38,207,35,138,35,138,38,207,29,190,35,138,29,190,28,153,28,153,29,190,26,168,102,229,94,229,110,217,110,217,94,229,94,219,82,217,94,219,94,229,82,217,94,229,72,227,1 [...]
+133,39,127,32,121,27,115,24,109,22,103,21,93,23,86,28,81,36,78,49,77,66,77,209,127,209,127,225,77,225,77,286,76,287,76,289,75,289,74,290,72,287,69,284,65,278,64,276,53,260,42,247,32,236,23,228,15,222,12,220,8,216,7,214,7,210,8,210,8,209,35,209,35,59,37,36,42,18,51,5,64,-1,79,-4,93,-3,106,1,118,8,129,19,140,33,
+42,247,32,236,35,209,35,209,32,236,23,228,35,209,23,228,15,222,53,260,42,247,42,18,53,260,42,18,51,5,53,260,51,5,64,-1,53,260,64,-1,64,276,37,36,42,18,42,247,37,36,42,247,35,209,37,36,35,209,35,59,7,210,8,210,8,216,8,216,8,210,8,209,8,216,8,209,10,218,10,218,8,209,35,209,10,218,35,209,12,220,12,220,35,209,15,222,7,214,7,213,7,212,7,214,7,212,7,211,7,214,7,211,7,210,7,214,7,210,8,216,69,284,79,-4,77,66,77,225,77,209,127,209,77,225,127,209,127,225,77,66,77,283,77,286,77,66,77,286,76,287,77 [...]
+240,25,237,25,225,26,217,29,212,34,209,42,209,225,129,225,129,217,145,215,155,212,162,206,165,197,166,184,166,59,164,53,162,48,159,43,147,34,139,29,130,26,121,25,113,24,102,26,92,31,84,40,79,51,78,64,78,225,4,225,4,218,17,216,26,213,32,207,35,197,36,185,36,59,38,38,46,20,58,6,75,-1,97,-4,109,-3,123,0,138,8,153,21,168,38,169,38,169,-2,171,-3,186,1,199,6,225,14,240,18,
+78,225,4,225,17,216,78,225,17,216,26,213,78,225,26,213,32,207,78,225,32,207,35,197,78,225,35,197,36,185,78,225,36,185,38,38,78,225,38,38,46,20,78,225,46,20,58,6,78,225,58,6,75,-1,78,225,75,-1,78,64,164,53,162,48,168,38,168,38,162,48,159,43,168,38,159,43,155,40,155,40,147,34,153,21,153,21,147,34,139,29,153,21,139,29,138,8,138,8,139,29,130,26,138,8,130,26,123,0,123,0,130,26,121,25,123,0,121,25,113,24,113,24,102,26,109,-3,109,-3,102,26,97,-4,97,-4,102,26,92,31,97,-4,92,31,84,40,97,-4,84,40, [...]
+238,225,169,225,169,218,178,216,184,214,189,211,192,207,193,201,192,198,192,195,191,192,191,189,190,186,140,57,89,185,87,190,86,194,85,197,84,201,84,204,85,209,88,212,92,215,99,216,108,218,108,225,9,225,9,218,19,216,27,212,35,202,44,186,55,160,115,17,116,14,118,10,118,8,119,6,121,1,123,-1,125,-4,126,-6,128,-6,130,-5,132,-3,135,1,138,8,142,18,206,179,213,195,219,206,224,213,231,216,238,218,
+87,190,86,194,115,17,115,17,86,194,85,197,115,17,85,197,55,160,55,160,85,197,84,201,55,160,84,201,84,204,84,204,85,209,55,160,108,225,9,225,19,216,108,225,19,216,27,212,108,225,27,212,35,202,108,225,35,202,44,186,108,225,44,186,88,212,108,225,88,212,92,215,108,225,92,215,99,216,108,225,99,216,108,218,85,209,88,212,44,186,85,209,44,186,55,160,140,57,89,185,115,17,140,57,115,17,116,14,140,57,116,14,117,12,140,57,117,12,118,10,140,57,118,10,118,8,140,57,118,8,119,6,140,57,119,6,121,1,140,57 [...]
+347,225,286,225,286,218,294,215,301,213,305,210,307,207,307,197,306,191,302,177,299,169,254,58,209,178,206,185,204,195,204,205,207,210,212,213,221,215,233,218,233,225,131,225,131,218,141,216,148,212,155,206,160,196,166,183,175,155,130,55,80,186,79,189,79,192,78,195,78,206,81,211,85,214,91,216,100,218,100,225,11,225,11,218,17,216,22,214,26,208,31,199,37,186,104,15,108,7,111,0,113,-3,116,-5,118,-6,121,-3,123,0,126,5,130,12,186,132,232,15,235,5,238,0,241,-6,246,-6,250,0,253,7,257,17,326,190 [...]
+22,214,26,208,100,225,100,225,26,208,31,199,100,225,31,199,37,186,37,186,104,15,78,195,78,195,104,15,79,192,37,186,78,198,78,201,78,201,78,206,37,186,37,186,78,206,81,211,37,186,81,211,85,214,100,225,37,186,85,214,100,225,85,214,91,216,100,225,91,216,100,218,17,216,22,214,100,225,17,216,100,225,11,225,17,216,11,225,11,218,186,132,204,200,204,205,186,132,204,205,175,155,175,155,204,205,166,183,160,196,166,183,207,210,160,196,207,210,212,213,233,225,131,225,141,216,233,225,141,216,148,212, [...]
+239,0,239,7,230,8,222,12,215,18,207,26,199,37,134,136,176,195,182,203,190,209,198,214,207,216,217,218,217,225,137,225,137,218,145,217,151,215,155,213,157,210,157,202,154,197,150,191,145,184,136,169,133,165,130,160,124,152,123,154,121,156,119,160,117,162,109,174,103,185,98,194,95,201,94,206,95,210,97,213,101,216,107,217,116,218,116,225,12,225,12,218,17,218,25,217,32,214,39,208,47,200,55,187,55,188,102,116,45,33,37,22,31,15,24,11,17,9,8,7,8,0,81,0,81,7,73,8,68,9,64,11,62,13,61,17,61,19,62, [...]
+31,15,24,11,81,0,81,0,24,11,17,9,81,0,17,9,8,7,32,214,39,208,116,225,116,225,39,208,47,200,116,225,47,200,55,188,55,187,55,188,102,116,55,187,102,116,94,206,94,206,95,210,55,187,55,187,95,210,97,213,55,187,97,213,116,225,116,225,97,213,101,216,116,225,101,216,107,217,31,15,81,0,37,22,37,22,81,0,64,11,37,22,64,11,45,33,45,33,64,11,62,13,45,33,62,13,61,17,61,17,61,19,45,33,45,33,61,19,62,22,45,33,62,22,102,116,102,116,62,22,64,26,102,116,64,26,67,31,102,116,67,31,71,37,71,37,110,99,102,116 [...]
+238,225,171,225,171,218,179,217,186,216,190,213,193,210,194,205,194,202,193,201,193,198,192,196,143,59,88,184,82,196,81,201,81,204,82,209,85,212,90,215,98,217,109,218,109,225,7,225,7,218,14,217,21,214,26,211,30,206,33,200,99,60,105,47,111,35,116,24,121,9,119,2,116,-8,112,-21,106,-34,100,-44,96,-51,85,-62,80,-65,75,-66,71,-66,69,-65,66,-64,62,-63,63,-63,57,-60,52,-58,42,-56,36,-56,30,-57,24,-60,19,-65,16,-72,15,-79,17,-88,21,-96,28,-102,38,-106,50,-108,71,-105,90,-94,106,-76,122,-49,137,- [...]
+90,-57,85,-62,90,-94,90,-94,85,-62,80,-65,90,-94,80,-65,75,-66,75,-66,73,-66,90,-94,90,-94,73,-66,71,-105,90,-57,106,-76,96,-51,96,-51,106,-76,100,-44,106,-34,100,-44,106,-76,106,-34,106,-76,122,-49,143,59,88,184,99,60,143,59,99,60,105,47,143,59,105,47,111,35,143,59,111,35,116,24,143,59,116,24,119,15,143,59,119,15,121,9,143,59,121,9,122,-49,143,59,122,-49,137,-11,143,59,137,-11,213,192,143,59,213,192,192,196,122,-49,121,9,119,2,99,60,88,184,86,188,99,60,86,188,84,192,99,60,84,192,82,196, [...]
+209,68,200,70,197,57,195,47,193,40,190,34,186,28,181,24,173,20,163,17,149,16,133,15,67,15,201,218,201,225,28,225,26,166,36,166,39,184,44,197,51,205,63,209,79,210,147,210,13,7,13,0,201,0,
+67,15,201,218,147,210,147,210,201,218,201,225,147,210,201,225,79,210,63,209,79,210,201,225,63,209,201,225,28,225,28,225,26,166,36,166,28,225,36,166,39,184,28,225,39,184,44,197,28,225,44,197,51,205,28,225,51,205,63,209,147,210,13,7,67,15,67,15,13,7,201,0,67,15,201,0,133,15,133,15,201,0,149,16,195,47,193,40,201,0,201,0,193,40,190,34,201,0,190,34,186,28,186,28,181,24,201,0,201,0,181,24,173,20,201,0,173,20,163,17,201,0,209,68,200,70,201,0,200,70,197,57,201,0,197,57,195,47,201,0,13,7,13,0,149 [...]
+175,-84,157,-78,144,-69,136,-58,131,-42,129,-22,129,60,128,82,124,98,115,110,102,118,83,124,102,131,115,140,124,151,128,167,129,189,129,273,131,293,136,308,144,320,157,328,175,334,175,340,157,339,144,338,132,336,114,328,107,321,100,312,96,300,94,287,93,271,93,181,91,163,87,149,80,139,67,131,50,125,67,118,80,110,87,100,91,86,93,68,93,-20,94,-35,96,-49,101,-61,107,-70,114,-77,123,-82,132,-85,143,-87,157,-89,175,-89,
+107,-70,114,-77,115,110,115,110,114,-77,123,-82,115,110,123,-82,124,98,124,98,123,-82,132,-85,124,98,132,-85,129,-22,129,-22,129,60,128,82,129,-22,128,82,124,98,157,-89,175,-89,175,-84,157,-89,175,-84,157,-78,157,-89,157,-78,144,-69,157,-89,144,-69,143,-87,136,-58,131,-42,132,-85,136,-58,132,-85,143,-87,136,-58,143,-87,144,-69,102,118,83,124,87,100,102,118,87,100,91,86,102,118,91,86,93,68,102,118,93,68,94,-35,102,118,94,-35,96,-49,102,118,96,-49,101,-61,102,118,101,-61,107,-70,102,118,10 [...]
+66,-6,66,338,33,338,33,-6,
+66,-6,66,338,33,338,66,-6,33,338,33,-6,
+147,270,146,286,144,300,139,312,133,321,126,328,108,336,97,338,83,339,65,340,65,334,83,328,96,320,104,308,109,293,110,273,110,189,112,167,116,151,125,139,138,131,157,125,138,118,125,110,116,98,112,82,110,60,110,-22,109,-42,104,-58,96,-69,83,-78,65,-84,65,-89,83,-89,96,-87,108,-85,117,-82,126,-77,133,-71,139,-61,144,-50,146,-36,147,-20,147,68,149,86,153,100,160,111,172,118,190,125,172,131,160,139,153,149,149,163,147,181,
+110,273,112,167,110,273,110,273,112,167,117,332,110,273,117,332,109,293,109,293,117,332,108,336,109,293,108,336,104,308,104,308,108,336,97,338,104,308,97,338,96,320,96,320,97,338,83,339,96,320,83,339,83,328,83,328,83,339,65,340,83,328,65,340,65,334,147,181,147,270,146,286,147,181,146,286,144,300,147,181,144,300,139,312,147,181,139,312,138,131,147,181,138,131,149,163,172,118,190,125,172,131,172,118,172,131,160,111,160,111,172,131,160,139,160,111,160,139,157,125,157,125,160,139,153,149,157 [...]
+233,162,227,151,219,141,211,133,201,128,189,126,179,127,157,135,148,140,141,143,124,150,111,155,100,158,92,160,83,160,69,159,56,154,43,146,31,134,20,117,38,92,44,104,51,114,60,122,70,126,80,128,92,127,103,125,114,122,122,119,128,116,143,107,155,101,166,97,176,95,189,94,202,95,214,100,226,108,238,120,251,137,
+92,160,83,160,92,127,92,127,83,160,80,128,70,126,80,128,83,160,70,126,83,160,69,159,141,143,128,116,143,107,141,143,143,107,148,140,148,140,143,107,155,101,148,140,155,101,157,135,157,135,155,101,166,97,157,135,166,97,168,131,168,131,166,97,176,95,168,131,176,95,179,127,179,127,176,95,189,94,179,127,189,94,189,126,189,126,189,94,202,95,189,126,202,95,201,128,92,160,92,127,100,158,100,158,92,127,103,125,100,158,103,125,111,155,111,155,103,125,114,122,111,155,114,122,124,150,124,150,114,12 [...]
+101,209,100,217,96,224,90,229,83,233,75,234,66,233,59,229,53,224,49,217,48,209,49,200,53,192,58,186,66,182,74,181,83,182,90,186,96,192,100,200,101,209,16383,16383,78,141,71,141,49,-49,49,-53,48,-57,48,-69,49,-82,52,-93,58,-101,65,-106,75,-108,84,-106,91,-100,96,-92,100,-81,101,-68,101,-57,100,-53,100,-49,
+48,209,49,200,49,217,49,217,49,200,53,192,49,217,53,192,53,224,53,224,53,192,58,186,53,224,58,186,59,229,59,229,58,186,66,182,59,229,66,182,66,233,66,233,66,182,74,181,66,233,74,181,75,234,75,234,74,181,83,182,75,234,83,182,83,233,83,233,83,182,90,186,83,233,90,186,90,229,90,229,90,186,96,192,90,229,96,192,96,224,96,224,96,192,100,200,96,224,100,200,100,217,100,217,100,200,101,209,100,-49,78,141,84,-106,100,-49,84,-106,91,-100,100,-49,91,-100,96,-92,100,-49,96,-92,100,-81,100,-49,100,-81 [...]
+218,82,203,62,189,48,175,39,160,33,144,32,138,32,133,33,127,34,121,36,114,38,165,184,170,173,176,166,181,161,187,158,194,157,201,158,207,161,211,166,214,173,215,180,214,190,209,200,202,208,191,216,178,222,201,290,184,290,162,228,155,229,150,229,145,230,137,230,101,224,71,207,47,181,32,148,26,109,27,94,30,79,34,64,40,50,47,38,53,30,59,24,66,18,74,12,84,6,59,-68,76,-68,100,0,107,-1,119,-3,140,-3,151,0,161,3,171,8,180,15,190,24,198,33,206,45,214,59,224,78,16383,16383,99,49,86,63,76,77,70,92 [...]
+156,210,99,49,100,0,100,0,99,49,86,63,100,0,86,63,84,6,84,6,86,63,76,77,84,6,76,77,74,12,74,12,76,77,70,92,74,12,70,92,66,110,53,30,59,24,65,130,65,130,66,18,66,110,66,110,66,18,74,12,113,-2,119,-3,114,38,114,38,119,-3,121,36,121,36,119,-3,124,-3,121,36,124,-3,127,34,127,34,124,-3,129,-3,127,34,129,-3,133,33,133,33,129,-3,140,-3,133,33,140,-3,138,32,138,32,140,-3,144,32,160,33,144,32,151,0,160,33,151,0,161,3,114,38,165,184,156,210,156,210,162,228,155,229,156,210,155,229,151,212,151,212,1 [...]
+172,164,172,186,109,186,107,205,106,220,105,233,104,245,104,256,106,280,112,299,122,313,135,322,151,325,161,324,169,321,175,315,178,308,180,299,180,285,182,275,186,269,191,266,199,265,207,266,214,270,219,276,223,283,224,291,221,306,212,319,198,329,180,336,159,338,126,333,99,317,79,293,66,261,61,221,62,214,62,208,64,194,65,186,12,186,12,164,65,164,68,147,71,127,73,109,75,93,76,81,76,69,75,67,75,63,69,64,64,64,60,65,51,65,36,63,24,58,14,50,8,40,6,27,8,16,12,8,19,1,28,-2,40,-3,50,-2,59,0,68 [...]
+59,18,55,14,59,0,59,0,55,14,50,12,59,0,50,12,50,-2,50,-2,50,12,46,10,50,-2,46,10,40,-3,40,-3,46,10,40,10,69,64,64,64,65,43,65,43,64,64,60,65,65,43,60,65,59,45,59,45,60,65,56,65,59,45,56,65,52,46,52,46,56,65,51,65,52,46,51,65,44,47,20,35,23,40,24,58,24,58,23,40,28,44,24,58,28,44,36,63,36,63,28,44,35,46,36,63,35,46,44,47,20,22,19,28,19,1,19,1,19,28,14,50,14,50,19,28,24,58,24,58,19,28,20,35,71,35,70,33,78,14,78,14,70,33,68,29,78,14,68,29,68,6,68,6,68,29,66,26,68,6,66,26,64,22,64,22,59,18,68 [...]
+261,20,213,68,221,81,226,93,230,105,232,118,233,132,232,146,230,158,226,170,221,182,213,194,261,243,237,267,188,219,176,226,165,232,153,235,140,238,112,238,99,236,87,232,75,226,62,219,14,267,-10,243,38,194,30,182,24,170,20,158,18,145,17,131,18,117,20,105,24,92,30,80,38,68,-10,20,14,-4,62,44,74,36,87,31,99,27,112,24,126,23,139,24,152,27,164,31,176,37,188,44,237,-4,16383,16383,199,132,195,108,185,86,169,70,149,59,126,55,102,59,82,70,66,86,55,107,51,132,55,155,66,176,81,192,101,203,124,206, [...]
+99,27,112,24,102,59,102,59,112,24,126,55,149,59,126,55,126,23,149,59,126,23,139,24,62,219,14,267,38,194,62,219,38,194,38,68,62,219,38,68,51,132,62,219,51,132,55,155,62,219,55,155,66,176,62,219,66,176,75,226,66,86,55,107,62,44,62,44,55,107,51,132,140,238,126,238,148,203,148,203,126,238,124,206,101,203,124,206,112,238,101,203,112,238,99,236,87,232,75,226,81,192,87,232,81,192,101,203,87,232,101,203,99,236,261,20,213,68,237,-4,237,-4,213,68,195,108,237,-4,195,108,188,44,188,44,195,108,185,86 [...]
+256,331,158,331,158,321,174,321,181,319,186,315,190,311,191,306,191,303,190,299,188,294,187,289,184,284,128,174,69,285,67,289,65,294,64,299,63,303,63,307,64,313,67,317,73,319,83,321,95,321,95,331,-25,331,-25,321,-13,319,-3,314,7,304,18,287,32,262,80,176,8,176,8,156,92,156,95,149,95,111,8,111,8,91,95,91,95,60,94,39,91,25,84,16,72,11,55,9,55,0,177,0,177,9,161,11,150,16,142,24,138,37,137,55,137,91,224,91,224,111,137,111,137,149,141,156,224,156,224,176,151,176,197,268,207,286,218,300,229,310 [...]
+32,262,80,176,32,262,32,262,80,176,63,303,32,262,63,303,63,307,63,307,64,313,32,262,91,25,84,16,177,0,177,0,84,16,72,11,177,0,72,11,55,9,95,331,-25,331,-13,319,95,331,-13,319,-3,314,95,331,-3,314,7,304,95,331,7,304,67,317,95,331,67,317,73,319,95,331,73,319,83,321,95,331,83,321,95,321,18,287,32,262,64,313,18,287,64,313,67,317,18,287,67,317,7,304,184,284,128,174,137,149,184,284,137,149,141,156,184,284,141,156,151,176,184,284,151,176,197,268,184,284,197,268,187,289,256,331,158,331,166,321,2 [...]
+66,200,66,338,33,338,33,200,16383,16383,66,-6,66,131,33,131,33,-6,
+33,338,33,200,66,200,33,338,66,200,66,338,33,131,33,-6,66,-6,33,131,66,-6,66,131,
+100,257,94,262,86,276,84,284,83,292,85,304,91,314,100,321,111,326,126,328,135,327,144,324,150,321,155,316,156,311,156,310,155,309,154,307,152,306,144,298,142,293,140,289,140,284,141,277,144,271,149,266,155,263,163,262,172,263,179,267,184,272,188,280,189,289,185,305,177,318,163,329,145,336,124,338,101,335,82,327,68,314,58,297,55,277,57,262,61,248,70,235,84,220,105,202,99,202,97,203,92,203,74,200,58,191,46,179,38,162,35,143,38,121,48,100,64,79,88,57,121,32,137,20,150,8,159,-2,164,-13,165,- [...]
+101,335,82,327,85,304,85,304,82,327,83,292,84,220,83,292,82,327,84,220,82,327,70,235,70,235,82,327,68,314,70,235,68,314,61,248,61,248,68,314,58,297,61,248,58,297,57,262,57,262,58,297,55,277,69,133,88,57,75,124,75,124,88,57,84,114,101,99,84,114,88,57,101,99,88,57,121,32,95,191,94,203,92,203,95,191,92,203,84,190,95,191,97,203,94,203,63,169,68,178,74,200,74,200,68,178,75,185,74,200,75,185,92,203,92,203,75,185,84,190,74,200,58,191,63,169,63,169,58,191,61,158,64,79,61,158,58,191,64,79,58,191, [...]
+158,286,157,294,153,301,148,306,141,310,133,311,125,310,118,306,113,301,110,294,108,286,109,278,113,272,118,266,125,263,132,262,140,263,148,266,153,272,157,278,158,286,16383,16383,59,286,57,294,54,301,48,306,41,310,33,311,26,310,19,306,14,301,10,294,9,286,10,278,14,272,19,266,25,263,33,262,41,263,48,266,54,272,57,278,59,286,
+108,286,109,278,110,294,110,294,109,278,113,272,110,294,113,272,113,301,113,301,113,272,118,266,113,301,118,266,118,306,118,306,118,266,125,263,118,306,125,263,125,310,125,310,125,263,132,262,125,310,132,262,133,311,133,311,132,262,140,263,133,311,140,263,141,310,141,310,140,263,148,266,141,310,148,266,148,306,148,306,148,266,153,272,148,306,153,272,153,301,153,301,153,272,157,278,153,301,157,278,157,294,157,294,157,278,158,286,9,286,10,278,10,294,10,294,10,278,14,272,10,294,14,272,14,30 [...]
+273,124,266,124,257,108,247,95,236,87,223,82,208,80,183,84,162,95,147,113,137,138,133,169,137,197,146,221,161,240,180,252,205,256,221,254,234,249,245,240,253,227,257,211,266,211,266,247,265,249,264,250,263,252,261,254,259,255,249,259,238,262,216,266,205,266,169,262,138,248,115,227,100,199,95,165,99,133,112,107,132,87,158,75,191,70,210,71,230,74,247,78,260,82,265,86,16383,16383,361,165,352,220,329,267,292,305,246,329,193,338,137,329,89,305,52,268,28,220,19,165,28,110,52,63,89,26,136,1,190 [...]
+162,95,147,113,158,75,158,75,147,113,137,138,158,75,137,138,132,87,132,87,137,138,133,169,138,248,133,169,137,197,138,248,137,197,146,221,216,266,205,266,221,254,221,254,205,266,205,256,180,252,205,256,205,266,180,252,205,266,169,262,263,252,261,254,266,211,266,211,261,254,259,255,266,211,259,255,257,211,257,211,259,255,253,227,169,262,138,248,146,221,169,262,146,221,161,240,169,262,161,240,180,252,115,227,100,199,112,107,115,227,112,107,132,87,115,227,132,87,133,169,115,227,133,169,138, [...]
+135,221,129,217,127,216,124,215,118,215,116,217,115,220,115,225,114,233,114,290,112,307,106,321,96,330,81,336,62,338,44,337,29,332,18,325,10,316,8,305,9,300,11,295,14,292,19,290,24,289,29,290,37,294,39,298,40,301,40,303,39,304,39,307,38,309,38,313,39,316,43,319,48,322,54,324,60,324,67,323,72,321,76,316,78,310,79,303,79,288,56,279,40,273,29,268,20,263,13,257,9,253,6,248,4,243,2,231,4,220,9,210,16,203,26,199,37,197,46,198,55,200,64,205,73,211,83,219,85,210,88,204,93,200,98,198,105,197,112, [...]
+38,309,38,310,39,298,39,298,38,310,38,311,39,298,38,311,37,294,37,294,38,311,38,313,44,337,38,313,39,316,44,337,39,316,43,319,39,305,39,307,39,298,39,305,39,298,40,301,40,301,40,302,40,303,40,301,40,303,39,304,40,301,39,304,39,305,46,198,55,200,46,222,46,222,55,200,52,220,56,221,52,220,55,200,56,221,55,200,64,205,81,336,62,338,67,323,67,323,62,338,60,324,54,324,60,324,62,338,54,324,62,338,48,322,48,322,62,338,44,337,48,322,44,337,43,319,78,233,77,230,83,219,83,219,77,230,76,228,83,219,76 [...]
+117,113,157,77,172,64,203,33,216,21,222,17,224,17,225,18,227,19,228,20,228,22,227,26,224,31,219,39,212,49,203,60,196,70,188,80,180,91,171,102,161,113,203,166,212,178,219,187,224,194,227,199,228,203,228,205,227,207,225,208,223,208,216,204,204,193,172,163,157,150,16383,16383,21,113,61,77,76,64,107,33,120,21,126,17,128,17,129,18,131,19,132,20,132,22,131,26,128,31,123,39,116,49,107,60,100,70,92,80,65,113,107,166,116,178,123,187,128,194,131,199,132,203,132,205,131,207,129,208,127,208,120,204, [...]
+203,60,196,70,203,60,203,60,196,70,203,33,203,60,203,33,212,49,212,49,203,33,216,21,212,49,216,21,219,39,219,39,216,21,222,17,219,39,222,17,224,31,224,31,222,17,224,17,224,31,224,17,225,18,227,26,224,31,225,18,227,26,225,18,227,19,227,26,227,19,228,20,227,26,228,20,228,22,171,102,172,64,180,91,180,91,172,64,188,48,180,91,188,48,188,80,188,80,188,48,203,33,188,80,203,33,196,70,161,113,172,163,157,150,161,113,157,150,157,77,161,113,157,77,172,64,161,113,172,64,171,102,228,205,227,207,227,1 [...]
+276,57,276,196,24,196,24,164,243,164,243,57,
+243,164,243,57,276,57,243,164,276,57,276,196,243,164,276,196,24,196,243,164,24,196,24,164,
+142,97,142,128,20,128,20,97,
+142,97,142,128,20,128,142,97,20,128,20,97,
+283,76,283,80,276,86,268,94,252,112,244,123,216,162,230,168,241,177,249,188,254,199,256,211,253,228,246,241,233,251,217,258,196,260,110,260,110,252,122,251,128,248,132,244,134,237,134,98,132,91,129,87,121,85,110,84,109,76,190,76,190,84,178,85,171,87,168,92,166,100,166,157,190,157,199,143,206,133,210,127,213,121,216,116,224,101,232,90,239,82,246,77,252,76,16383,16383,166,166,166,251,185,251,199,248,210,243,217,234,221,222,222,209,221,196,216,184,209,175,199,168,187,166,188,166,16383,16383 [...]
+222,209,222,209,222,209,222,209,230,168,233,251,233,251,230,168,241,177,233,251,241,177,246,241,246,241,241,177,249,188,246,241,249,188,253,228,253,228,249,188,254,199,253,228,254,199,256,211,221,222,222,209,233,251,221,222,233,251,217,258,221,222,217,258,217,234,166,251,185,251,196,260,196,260,185,251,199,248,196,260,199,248,217,258,217,258,199,248,210,243,217,258,210,243,217,234,134,226,168,92,166,100,134,226,166,100,166,111,166,166,166,157,190,157,166,166,190,157,187,166,187,166,190,1 [...]
+161,273,161,300,6,300,6,273,
+161,273,161,300,6,300,161,273,6,300,6,273,
+171,267,168,289,158,309,143,324,123,334,101,338,78,335,58,325,42,309,32,290,28,267,32,244,42,224,57,209,77,198,100,195,123,198,142,209,158,224,168,244,171,267,16383,16383,152,267,149,250,142,235,130,223,116,215,100,212,84,215,69,223,58,234,51,249,48,267,51,284,58,298,69,310,83,318,99,321,115,318,130,310,141,299,149,284,152,267,
+83,318,99,321,99,321,101,338,99,321,115,318,101,338,115,318,123,334,123,334,115,318,130,310,123,334,130,310,143,324,143,324,130,310,141,299,143,324,141,299,149,284,171,267,168,289,168,244,168,244,168,289,158,309,168,244,158,309,158,224,158,224,158,309,152,267,158,224,152,267,149,250,158,224,149,250,142,209,142,209,149,250,142,235,142,209,142,235,130,223,158,309,143,324,149,284,158,309,149,284,152,267,142,209,130,223,123,198,123,198,130,223,116,215,123,198,116,215,100,195,100,195,116,215, [...]
+319,121,319,154,188,154,188,251,155,251,155,154,24,154,24,121,155,121,155,17,188,17,188,121,16383,16383,319,-43,319,-10,24,-10,24,-43,
+188,251,155,251,188,17,188,17,155,251,155,154,188,17,155,154,155,121,155,121,155,154,24,154,155,121,24,154,24,121,188,121,319,121,188,154,24,-10,24,-43,319,-43,24,-10,319,-43,319,-10,188,154,319,121,319,154,188,17,155,121,155,17,
+148,177,139,181,134,175,124,169,110,167,54,167,95,208,112,226,125,241,133,255,137,269,138,283,136,301,127,316,114,328,97,335,75,338,53,336,35,329,21,317,10,301,1,278,13,271,20,284,28,295,37,302,46,307,57,308,68,306,78,301,86,292,91,282,93,270,91,260,86,247,78,233,67,217,54,201,3,147,3,135,128,135,
+54,201,3,147,54,167,54,201,54,167,95,208,54,201,95,208,67,217,13,271,20,284,21,317,21,317,20,284,28,295,21,317,28,295,35,329,35,329,28,295,37,302,35,329,37,302,53,336,53,336,37,302,46,307,53,336,46,307,57,308,57,308,68,306,75,338,75,338,68,306,78,301,75,338,78,301,97,335,97,335,78,301,86,292,97,335,86,292,91,282,10,301,1,278,13,271,10,301,13,271,21,317,91,260,95,208,93,270,93,270,95,208,97,335,97,335,95,208,112,226,97,335,112,226,114,328,114,328,112,226,125,241,114,328,125,241,127,316,12 [...]
+102,256,114,263,123,271,129,279,131,288,132,296,130,310,122,321,110,330,95,336,78,338,61,336,46,331,33,322,22,309,11,291,23,281,31,293,39,301,47,306,56,309,66,310,76,309,83,306,89,301,93,295,94,286,92,276,87,267,78,259,65,252,46,244,46,230,52,231,59,231,60,232,76,230,88,225,97,216,103,205,105,190,103,179,99,169,92,162,82,157,71,155,66,155,61,156,57,158,52,161,40,169,32,173,28,174,25,175,19,174,14,172,10,169,8,165,7,159,9,150,15,142,25,136,37,132,52,131,83,134,109,144,129,159,141,177,146, [...]
+66,155,61,156,83,134,83,134,61,156,57,158,83,134,57,158,52,131,52,131,57,158,52,161,52,131,52,161,46,165,56,231,59,231,65,252,65,252,59,231,60,232,60,232,76,230,65,252,65,252,76,230,78,259,65,252,46,244,52,231,65,252,52,231,56,231,23,281,31,293,33,322,33,322,31,293,39,301,33,322,39,301,46,331,46,331,39,301,47,306,46,331,47,306,61,336,61,336,47,306,56,309,61,336,56,309,66,310,66,310,76,309,78,338,78,338,76,309,83,306,78,338,83,306,95,336,95,336,83,306,89,301,95,336,89,301,93,295,22,309,11 [...]
+46,253,66,253,143,302,149,306,153,310,156,314,158,318,158,329,155,333,152,336,147,338,141,339,133,337,129,335,125,332,120,328,
+141,339,143,302,147,338,147,338,143,302,149,306,147,338,149,306,152,336,152,336,149,306,153,310,152,336,153,310,155,333,155,333,153,310,156,314,155,333,156,314,158,329,158,329,156,314,158,318,158,329,158,318,158,323,143,302,141,339,137,338,143,302,137,338,133,337,143,302,133,337,129,335,143,302,129,335,125,332,143,302,125,332,120,328,143,302,120,328,66,253,66,253,120,328,46,253,
+215,225,171,225,171,57,164,46,155,38,144,31,131,27,116,26,102,28,90,34,81,45,76,59,74,78,74,225,30,225,30,27,29,14,26,-5,22,-28,19,-51,18,-69,19,-82,22,-93,26,-101,32,-106,40,-108,48,-106,55,-102,60,-94,63,-83,64,-69,62,-51,58,-29,52,-6,48,14,46,32,55,18,66,8,77,1,91,-3,107,-4,123,-2,137,2,150,11,162,24,172,40,174,40,176,24,182,11,191,2,201,-2,211,-4,222,-3,231,0,239,4,247,12,256,23,256,28,249,22,244,18,239,15,235,14,230,13,224,15,220,19,217,26,215,36,215,48,
+46,32,46,32,46,32,46,32,74,225,30,225,46,32,30,225,32,-106,46,32,32,-106,40,-108,46,32,40,-108,48,-106,76,59,74,78,77,1,77,1,74,78,66,8,66,8,74,78,74,225,66,8,74,225,55,18,55,18,74,225,46,32,30,225,30,27,32,-106,32,-106,30,27,29,14,32,-106,29,14,26,-101,26,-101,29,14,26,-5,26,-101,26,-5,22,-28,18,-69,19,-82,19,-51,19,-51,19,-82,22,-93,19,-51,22,-93,22,-28,22,-28,22,-93,26,-101,171,225,171,57,172,40,172,40,171,57,164,46,172,40,164,46,162,24,162,24,164,46,155,38,162,24,155,38,150,11,150,11 [...]
+266,-76,266,-65,247,-62,234,-58,227,-50,223,-38,222,-20,222,271,223,290,227,304,234,313,247,318,266,321,266,331,134,331,95,327,66,316,46,297,34,270,30,235,34,199,46,172,66,154,93,142,127,137,127,-14,126,-35,123,-49,115,-58,102,-63,83,-65,83,-76,160,-76,160,320,189,320,189,-76,16383,16383,127,147,105,153,88,164,77,182,70,206,68,237,70,266,75,289,86,305,103,315,127,320,
+123,-49,115,-58,160,-76,160,-76,115,-58,102,-63,160,-76,102,-63,83,-65,134,331,95,327,103,315,134,331,103,315,127,320,134,331,127,320,127,137,134,331,127,137,160,-76,134,331,160,-76,160,320,134,331,160,320,266,331,127,320,127,147,127,137,105,153,88,164,93,142,93,142,88,164,77,182,93,142,77,182,66,154,66,154,77,182,70,206,66,154,70,206,68,237,68,237,70,266,66,316,66,316,70,266,75,289,66,316,75,289,95,327,95,327,75,289,86,305,95,327,86,305,103,315,66,316,46,297,46,172,66,316,46,172,66,154, [...]
+90,127,89,135,85,143,79,149,71,154,63,155,54,154,46,150,40,144,37,136,35,127,37,118,40,111,46,105,54,101,63,99,71,101,79,105,85,111,89,118,90,127,
+35,127,37,118,37,136,37,136,37,118,40,111,37,136,40,111,40,144,40,144,40,111,46,105,40,144,46,105,46,150,46,150,46,105,54,101,46,150,54,101,54,154,54,154,54,101,62,99,54,154,62,99,63,155,63,155,62,99,71,101,63,155,71,101,71,154,71,154,71,101,79,105,71,154,79,105,79,149,79,149,79,105,85,111,79,149,85,111,85,143,85,143,85,111,89,118,85,143,89,118,89,135,89,135,89,118,90,127,
+87,0,70,0,49,-49,52,-51,55,-50,57,-50,60,-49,66,-49,76,-50,84,-52,89,-55,92,-60,93,-67,92,-74,88,-81,83,-85,75,-88,65,-89,59,-89,47,-87,40,-86,33,-83,26,-98,35,-102,51,-106,59,-106,68,-107,89,-105,107,-99,120,-91,128,-79,131,-64,129,-52,123,-43,114,-36,102,-32,88,-30,80,-30,77,-31,75,-31,
+59,-106,68,-107,59,-89,59,-89,68,-107,65,-89,75,-88,65,-89,68,-107,75,-88,68,-107,89,-105,57,-50,60,-49,70,0,70,0,60,-49,63,-49,70,0,63,-49,66,-49,66,-49,76,-50,70,0,70,0,76,-50,75,-31,70,0,75,-31,87,0,70,0,49,-49,52,-51,70,0,52,-51,55,-50,70,0,55,-50,57,-50,131,-64,129,-52,128,-79,128,-79,129,-52,123,-43,128,-79,123,-43,120,-91,120,-91,123,-43,114,-36,120,-91,114,-36,107,-99,107,-99,114,-36,102,-32,107,-99,102,-32,93,-67,93,-67,102,-32,92,-60,89,-55,92,-60,102,-32,89,-55,102,-32,88,-30, [...]
+124,135,124,147,113,148,105,150,99,154,96,159,95,166,95,336,89,338,30,310,30,299,36,302,41,304,45,305,52,305,54,301,55,297,55,157,52,153,47,150,40,148,28,147,28,135,
+52,153,47,150,124,135,124,135,47,150,40,148,124,135,40,148,28,147,41,304,45,305,89,338,89,338,45,305,48,305,89,338,48,305,50,305,50,305,52,305,89,338,89,338,52,305,53,303,89,338,53,303,54,301,113,148,105,150,124,135,124,135,105,150,99,154,124,135,99,154,55,164,55,164,99,154,96,159,55,164,96,159,55,291,55,297,55,291,89,338,55,297,89,338,54,301,36,302,41,304,89,338,36,302,89,338,30,310,36,302,30,310,30,299,95,166,95,336,89,338,95,166,89,338,55,291,95,166,55,291,96,159,55,157,52,153,124,135 [...]
+152,271,148,293,139,312,123,326,103,335,79,338,54,335,33,325,17,310,6,291,3,267,6,244,16,225,32,210,52,200,75,197,100,201,121,211,138,227,148,247,152,271,16383,16383,116,258,114,242,110,230,102,221,93,216,80,214,73,214,66,216,56,224,52,230,44,250,42,261,40,273,40,285,41,297,46,307,53,315,63,320,74,321,88,318,99,310,108,297,114,279,116,258,
+44,250,52,200,48,240,48,240,52,200,52,230,56,224,52,230,52,200,56,224,52,200,75,197,42,261,40,273,33,325,42,261,33,325,32,210,42,261,32,210,52,200,42,261,52,200,44,250,33,325,40,285,41,297,33,325,41,297,54,335,54,335,41,297,46,307,54,335,46,307,53,315,3,267,6,244,6,291,6,291,6,244,16,225,6,291,16,225,17,310,17,310,16,225,32,210,17,310,32,210,33,325,103,335,79,338,88,318,88,318,79,338,74,321,63,320,74,321,79,338,63,320,79,338,54,335,114,242,110,230,121,211,121,211,110,230,102,221,121,211, [...]
+229,111,189,147,174,161,143,192,130,204,124,208,122,208,121,207,119,206,118,204,118,203,119,199,122,193,127,185,134,176,143,165,150,155,158,145,167,134,176,122,185,111,143,58,134,47,127,38,122,31,119,25,118,22,118,19,119,18,121,17,123,17,130,21,142,32,158,46,174,61,189,75,16383,16383,132,111,92,147,62,177,46,192,34,204,27,208,26,208,24,207,23,206,22,204,22,203,23,199,26,193,31,185,38,176,46,165,53,155,61,145,70,134,79,122,89,111,46,58,38,47,31,38,26,31,23,25,22,22,22,19,23,18,25,17,27,17 [...]
+92,75,132,111,92,147,92,75,92,147,89,111,92,75,89,111,77,61,53,155,61,145,62,177,62,177,61,145,70,134,62,177,70,134,78,161,78,161,70,134,79,122,78,161,79,122,92,147,92,147,79,122,89,111,53,155,62,177,46,165,46,165,62,177,46,192,46,165,46,192,38,176,38,176,46,192,34,204,38,176,34,204,31,185,31,185,34,204,27,208,31,185,27,208,26,193,26,193,27,208,26,208,26,193,26,208,24,207,23,206,22,204,23,199,23,206,23,199,26,193,23,206,26,193,24,207,189,75,229,111,189,147,189,75,189,147,185,111,189,75,1 [...]
+357,45,357,74,329,74,329,203,305,203,204,70,204,45,294,45,294,0,329,0,329,45,16383,16383,294,74,227,74,294,163,16383,16383,316,338,293,338,66,-6,91,-6,16383,16383,112,135,112,147,100,148,92,150,87,154,84,159,83,166,83,336,76,338,22,310,22,299,29,302,34,304,38,305,45,305,47,301,47,157,44,153,40,150,32,148,21,147,21,135,
+204,45,294,45,204,70,204,70,294,45,227,74,204,70,227,74,305,203,305,203,227,74,294,163,305,203,294,163,329,0,329,0,294,163,294,74,329,0,294,74,294,45,294,45,294,74,227,74,305,203,329,0,329,203,329,74,329,45,357,45,329,74,357,45,357,74,293,338,66,-6,91,-6,293,338,91,-6,316,338,44,153,40,150,112,135,112,135,40,150,32,148,112,135,32,148,21,147,34,304,38,305,76,338,76,338,38,305,41,305,76,338,41,305,43,305,43,305,45,305,76,338,76,338,45,305,46,303,76,338,46,303,47,301,100,148,92,150,112,135, [...]
+371,42,362,46,357,40,352,36,346,34,340,33,333,32,276,32,318,73,335,91,347,106,355,120,360,134,361,148,358,166,350,181,337,193,320,200,298,203,275,201,257,194,243,182,232,165,223,143,235,136,243,149,251,159,259,167,269,171,280,173,291,171,301,166,308,158,313,147,315,135,313,125,308,112,301,98,290,82,276,66,225,12,225,0,351,0,16383,16383,297,338,275,338,48,-6,73,-6,16383,16383,108,135,108,147,97,148,89,150,84,154,81,159,80,166,80,336,73,338,19,310,19,299,26,302,31,304,35,305,42,305,44,301, [...]
+308,112,301,98,318,73,318,73,301,98,290,82,318,73,290,82,276,66,276,66,225,12,276,32,276,32,225,12,351,0,276,32,351,0,333,32,340,33,333,32,351,0,340,33,351,0,346,34,346,34,351,0,352,36,235,136,243,149,243,182,243,182,243,149,251,159,243,182,251,159,257,194,257,194,251,159,259,167,257,194,259,167,275,201,275,201,259,167,269,171,275,201,269,171,280,173,280,173,291,171,298,203,298,203,291,171,301,166,298,203,301,166,320,200,320,200,301,166,308,158,320,200,308,158,313,147,232,165,223,143,235 [...]
+359,45,359,74,331,74,331,203,308,203,206,70,206,45,296,45,296,0,331,0,331,45,16383,16383,296,74,229,74,296,163,16383,16383,319,338,296,338,69,-6,94,-6,16383,16383,102,256,114,263,123,271,129,279,131,288,132,296,130,310,122,321,110,330,95,336,78,338,61,336,46,331,33,322,22,309,11,291,23,281,31,293,39,301,47,306,56,309,66,310,76,309,83,306,89,301,93,295,94,286,92,276,87,267,78,259,65,252,46,244,46,230,52,231,59,231,60,232,76,230,88,225,97,216,103,205,105,190,103,179,99,169,92,162,82,157,71 [...]
+206,45,296,45,206,70,206,70,296,45,229,74,206,70,229,74,308,203,308,203,229,74,296,163,308,203,296,163,331,0,331,0,296,163,296,74,331,0,296,74,296,45,296,45,296,74,229,74,308,203,331,0,331,203,331,74,331,45,359,45,331,74,359,45,359,74,296,338,69,-6,94,-6,296,338,94,-6,319,338,66,155,61,156,83,134,83,134,61,156,57,158,83,134,57,158,52,131,52,131,57,158,52,161,52,131,52,161,46,165,56,231,59,231,65,252,65,252,59,231,60,232,60,232,76,230,65,252,65,252,76,230,78,259,65,252,46,244,52,231,65,25 [...]
+130,208,129,216,125,223,119,229,112,232,103,233,95,232,87,229,82,223,78,217,77,208,78,199,82,192,87,186,95,182,103,180,112,182,119,186,125,192,129,199,130,208,16383,16383,100,147,96,128,91,112,85,97,77,84,68,70,46,42,31,20,22,2,17,-13,15,-30,16,-42,18,-52,22,-62,27,-71,33,-79,45,-89,58,-97,74,-103,90,-107,107,-108,133,-104,155,-94,173,-79,184,-59,188,-35,187,-24,184,-16,179,-10,173,-6,164,-5,157,-5,151,-8,147,-12,144,-18,143,-25,145,-33,147,-37,150,-42,154,-46,160,-54,161,-57,162,-59,162 [...]
+103,180,112,182,112,232,112,232,112,182,119,186,112,232,119,186,119,229,119,229,119,186,125,192,119,229,125,192,125,223,125,223,125,192,129,199,125,223,129,199,129,216,129,216,129,199,130,208,78,217,78,199,82,223,82,223,78,199,82,192,82,223,82,192,87,229,87,229,82,192,87,186,87,229,87,186,95,232,95,232,87,186,95,182,95,232,95,182,103,233,103,233,95,182,103,180,103,233,103,180,112,232,72,27,79,44,77,84,72,27,77,84,68,70,68,70,46,42,62,-19,62,-19,46,42,61,-34,64,-52,61,-34,58,-97,64,-52,58 [...]
+225,378,153,453,148,457,144,460,140,462,132,464,125,463,120,461,117,458,114,454,113,448,114,443,116,439,119,434,123,430,128,426,205,378,16383,16383,353,0,353,9,340,12,330,17,321,26,314,38,306,55,184,337,174,337,70,93,55,58,44,34,33,20,22,13,7,9,7,0,107,0,107,9,94,10,84,12,77,16,73,22,72,30,72,34,73,38,74,43,76,51,99,108,230,108,251,61,257,45,259,38,260,31,261,26,260,23,259,21,258,18,256,16,250,12,242,10,235,10,226,9,226,0,16383,16383,224,128,108,128,166,266,
+205,378,225,378,153,453,205,378,153,453,148,457,205,378,148,457,144,460,205,378,144,460,140,462,205,378,140,462,136,463,205,378,136,463,132,464,205,378,132,464,128,426,113,448,114,443,114,454,114,454,114,443,116,439,114,454,116,439,117,458,117,458,116,439,119,434,117,458,119,434,120,461,120,461,119,434,123,430,120,461,123,430,125,463,125,463,123,430,128,426,125,463,128,426,132,464,55,58,73,22,72,30,72,30,72,34,70,93,70,93,72,34,73,38,70,93,73,38,74,43,174,337,76,51,99,108,174,337,99,108, [...]
+138,378,158,378,235,427,245,435,248,439,249,443,250,448,249,454,247,458,243,461,239,463,233,464,228,463,224,462,221,460,216,457,211,453,16383,16383,353,0,353,9,340,12,330,17,321,26,314,38,306,55,184,337,174,337,70,93,55,58,44,34,33,20,22,13,7,9,7,0,107,0,107,9,94,10,84,12,77,16,73,22,72,30,72,34,73,38,74,43,76,51,99,108,230,108,251,61,257,45,259,38,260,31,261,26,260,23,259,21,258,18,256,16,250,12,242,10,235,10,226,9,226,0,16383,16383,224,128,108,128,166,266,
+233,464,235,427,239,463,239,463,235,427,240,431,239,463,240,431,243,461,243,461,240,431,245,435,243,461,245,435,247,458,247,458,245,435,248,439,247,458,248,439,249,454,249,454,248,439,249,443,249,454,249,443,250,448,235,427,233,464,228,463,235,427,228,463,224,462,235,427,224,462,221,460,235,427,221,460,216,457,235,427,216,457,211,453,235,427,211,453,158,378,55,58,73,22,72,30,72,30,72,34,70,93,70,93,72,34,73,38,70,93,73,38,74,43,174,337,76,51,99,108,174,337,99,108,108,128,108,128,99,108,2 [...]
+257,378,194,462,163,462,101,378,118,378,179,430,239,378,16383,16383,353,0,353,9,340,12,330,17,321,26,314,38,306,55,184,337,174,337,70,93,55,58,44,34,33,20,22,13,7,9,7,0,107,0,107,9,94,10,84,12,77,16,73,22,72,30,72,34,73,38,74,43,76,51,99,108,230,108,251,61,257,45,259,38,260,31,261,26,260,23,259,21,258,18,256,16,250,12,242,10,235,10,226,9,226,0,16383,16383,224,128,108,128,166,266,
+101,378,118,378,163,462,163,462,118,378,179,430,163,462,179,430,194,462,194,462,179,430,239,378,194,462,239,378,257,378,55,58,73,22,72,30,72,30,72,34,70,93,70,93,72,34,73,38,70,93,73,38,74,43,174,337,76,51,99,108,174,337,99,108,108,128,108,128,99,108,230,108,108,128,230,108,224,128,224,128,230,108,306,55,224,128,306,55,184,337,246,11,242,10,353,0,353,0,242,10,235,10,353,0,235,10,226,9,259,21,258,18,353,0,353,0,258,18,256,16,353,0,256,16,253,14,253,14,250,12,353,0,353,0,250,12,246,11,261, [...]
+248,444,243,434,238,427,233,422,227,420,221,419,216,419,211,420,206,422,200,424,195,426,182,432,175,436,161,440,154,441,147,441,133,439,121,433,111,423,103,409,97,391,112,391,115,399,120,406,125,410,131,413,137,414,141,414,149,412,157,408,169,403,180,398,189,394,196,392,202,391,209,391,224,393,237,399,247,409,255,424,262,444,16383,16383,353,0,353,9,340,12,330,17,321,26,314,38,306,55,184,337,174,337,70,93,55,58,44,34,33,20,22,13,7,9,7,0,107,0,107,9,94,10,84,12,77,16,73,22,72,30,72,34,73,3 [...]
+115,399,120,406,121,433,121,433,120,406,125,410,121,433,125,410,133,439,133,439,125,410,131,413,133,439,131,413,137,414,137,414,141,414,147,441,147,441,141,414,145,413,147,441,145,413,149,412,112,391,115,399,121,433,112,391,121,433,111,423,112,391,111,423,103,409,112,391,103,409,97,391,147,441,149,412,154,441,154,441,149,412,153,410,154,441,153,410,157,408,157,408,169,403,161,440,161,440,169,403,168,438,147,441,133,439,137,414,161,440,154,441,157,408,168,438,169,403,175,436,175,436,169,4 [...]
+254,411,253,419,249,426,244,431,237,435,229,436,221,435,214,431,209,426,206,419,204,411,205,403,209,397,214,391,221,388,228,387,236,388,244,391,249,397,253,403,254,411,16383,16383,155,411,153,419,150,426,144,431,137,435,129,436,122,435,115,431,110,426,106,419,105,411,106,403,110,397,115,391,121,388,129,387,137,388,144,391,150,397,153,403,155,411,16383,16383,353,0,353,9,340,12,330,17,321,26,314,38,306,55,184,337,174,337,70,93,55,58,44,34,33,20,22,13,7,9,7,0,107,0,107,9,94,10,84,12,77,16,7 [...]
+204,411,205,403,206,419,206,419,205,403,209,397,206,419,209,397,209,426,209,426,209,397,214,391,209,426,214,391,214,431,214,431,214,391,221,388,214,431,221,388,221,435,221,435,221,388,228,387,221,435,228,387,229,436,229,436,228,387,236,388,229,436,236,388,237,435,237,435,236,388,244,391,237,435,244,391,244,431,244,431,244,391,249,397,244,431,249,397,249,426,249,426,249,397,253,403,249,426,253,403,253,419,253,419,253,403,254,411,105,411,106,403,106,419,106,419,106,403,110,397,106,419,110, [...]
+229,430,227,446,220,460,209,471,196,478,180,480,164,478,151,471,140,460,133,447,130,431,132,415,139,401,150,391,163,384,179,381,195,384,209,391,220,401,227,415,229,430,16383,16383,213,431,211,420,206,411,199,404,190,400,179,398,169,400,160,404,153,411,148,420,147,431,148,441,153,450,160,457,169,462,179,464,190,462,199,457,206,450,211,441,213,431,16383,16383,353,0,353,9,340,12,330,17,321,26,314,38,306,55,184,337,174,337,70,93,55,58,44,34,33,20,22,13,7,9,7,0,107,0,107,9,94,10,84,12,77,16,7 [...]
+211,420,206,411,209,391,209,391,206,411,199,404,209,391,199,404,195,384,195,384,199,404,190,400,195,384,190,400,179,381,179,381,190,400,179,398,180,480,179,464,190,462,180,480,190,462,196,478,196,478,190,462,199,457,196,478,199,457,209,471,209,471,199,457,206,450,209,471,206,450,211,441,229,430,227,446,227,415,227,415,227,446,220,460,227,415,220,460,220,401,220,401,220,460,213,431,211,441,213,431,220,460,211,441,220,460,209,471,211,420,209,391,220,401,211,420,220,401,213,431,153,450,160, [...]
+431,84,420,84,404,56,389,37,372,26,349,20,320,19,268,19,257,22,252,26,249,34,248,47,248,165,319,165,337,163,350,158,360,149,366,135,370,114,381,114,381,232,370,232,367,211,359,197,346,189,326,184,300,183,248,183,248,295,249,301,251,306,253,310,257,312,262,313,305,313,341,312,367,308,382,299,392,283,397,261,408,261,408,331,126,331,126,321,143,320,155,318,164,315,169,310,171,305,171,302,170,300,168,294,166,291,44,49,36,33,28,23,21,16,11,12,0,9,0,0,99,0,99,9,87,11,77,13,70,16,66,20,65,24,66 [...]
+87,11,77,13,99,0,99,0,77,13,70,16,99,0,70,16,36,33,36,33,70,16,66,20,36,33,66,20,44,49,44,49,66,20,65,24,71,48,80,68,166,291,166,291,80,68,93,95,166,291,93,95,111,130,111,130,199,130,120,150,120,150,199,130,199,150,195,27,189,18,410,0,410,0,189,18,179,13,410,0,179,13,164,11,166,291,111,130,120,150,166,291,120,150,199,309,166,291,199,309,168,294,262,313,408,331,199,309,199,309,408,331,169,310,199,309,169,310,171,305,171,305,171,302,199,309,199,309,171,302,170,300,199,309,170,300,169,297,3 [...]
+307,65,285,47,264,32,242,23,220,17,196,15,175,17,155,21,137,29,120,40,105,54,93,72,84,94,77,118,73,145,72,173,77,222,93,262,118,292,151,311,191,318,221,313,249,300,272,280,289,255,299,225,310,225,305,338,295,338,293,332,285,324,280,322,275,321,271,322,268,322,263,323,259,325,254,326,240,330,225,334,210,336,196,338,181,338,160,337,140,333,120,327,101,319,84,308,59,287,40,262,25,233,17,200,14,165,16,135,21,107,30,82,43,60,58,41,73,27,90,15,109,6,129,0,151,-4,132,-49,136,-51,139,-50,141,-50 [...]
+84,94,77,118,90,15,90,15,77,118,73,145,90,15,73,145,73,27,73,27,73,145,72,173,59,287,72,173,84,308,158,-31,175,17,155,21,158,-31,155,21,151,-4,151,-4,155,21,137,29,151,-4,137,29,129,0,129,0,137,29,120,40,129,0,120,40,109,6,109,6,120,40,105,54,142,-106,151,-107,143,-89,143,-89,151,-107,149,-89,158,-88,149,-89,151,-107,158,-88,151,-107,173,-105,141,-50,144,-49,151,-4,151,-4,144,-49,147,-49,151,-4,147,-49,150,-49,150,-49,160,-50,151,-4,151,-4,132,-49,136,-51,151,-4,136,-51,139,-50,151,-4,13 [...]
+201,378,128,453,124,457,119,460,115,462,107,464,101,463,96,461,92,458,90,454,89,448,89,443,91,439,94,434,104,426,181,378,16383,16383,299,84,285,84,271,57,255,38,234,26,206,20,169,18,151,18,132,19,117,21,108,25,102,31,100,42,100,164,176,164,198,162,213,158,222,150,229,136,233,115,244,115,244,232,233,232,229,212,222,198,213,190,198,185,176,184,100,184,100,294,101,302,103,307,106,310,111,312,184,312,213,311,234,306,247,297,255,282,261,259,273,259,271,331,6,331,6,321,25,320,38,315,45,307,49, [...]
+181,378,201,378,128,453,181,378,128,453,124,457,181,378,124,457,119,460,181,378,119,460,115,462,181,378,115,462,111,463,181,378,111,463,107,464,181,378,107,464,104,426,89,448,89,443,90,454,90,454,89,443,91,439,90,454,91,439,92,458,92,458,91,439,94,434,92,458,94,434,96,461,96,461,94,434,99,430,96,461,99,430,101,463,101,463,99,430,104,426,101,463,104,426,107,464,45,24,38,16,276,0,276,0,38,16,25,12,276,0,25,12,6,9,49,294,50,275,106,310,49,294,106,310,45,307,45,307,106,310,111,312,45,307,111 [...]
+123,378,142,378,219,427,225,431,229,435,232,439,234,443,234,454,231,458,228,461,223,463,217,464,209,462,205,460,201,457,196,453,16383,16383,299,84,285,84,271,57,255,38,234,26,206,20,169,18,151,18,132,19,117,21,108,25,102,31,100,42,100,164,176,164,198,162,213,158,222,150,229,136,233,115,244,115,244,232,233,232,229,212,222,198,213,190,198,185,176,184,100,184,100,294,101,302,103,307,106,310,111,312,184,312,213,311,234,306,247,297,255,282,261,259,273,259,271,331,6,331,6,321,25,320,38,315,45, [...]
+217,464,219,427,223,463,223,463,219,427,225,431,223,463,225,431,228,461,228,461,225,431,229,435,228,461,229,435,231,458,231,458,229,435,232,439,231,458,232,439,234,454,234,454,232,439,234,443,234,454,234,443,234,448,219,427,217,464,213,463,219,427,213,463,209,462,219,427,209,462,205,460,219,427,205,460,201,457,219,427,201,457,196,453,219,427,196,453,142,378,45,24,38,16,276,0,276,0,38,16,25,12,276,0,25,12,6,9,49,294,50,275,106,310,49,294,106,310,45,307,45,307,106,310,111,312,45,307,111,31 [...]
+242,378,179,462,148,462,86,378,103,378,164,430,224,378,16383,16383,299,84,285,84,271,57,255,38,234,26,206,20,169,18,151,18,132,19,117,21,108,25,102,31,100,42,100,164,176,164,198,162,213,158,222,150,229,136,233,115,244,115,244,232,233,232,229,212,222,198,213,190,198,185,176,184,100,184,100,294,101,302,103,307,106,310,111,312,184,312,213,311,234,306,247,297,255,282,261,259,273,259,271,331,6,331,6,321,25,320,38,315,45,307,49,294,50,275,50,57,49,37,45,24,38,16,25,12,6,9,6,0,276,0,
+86,378,103,378,148,462,148,462,103,378,164,430,148,462,164,430,179,462,179,462,164,430,224,378,179,462,224,378,242,378,45,24,38,16,276,0,276,0,38,16,25,12,276,0,25,12,6,9,49,294,50,275,106,310,49,294,106,310,45,307,45,307,106,310,111,312,45,307,111,312,271,331,271,331,111,312,118,312,45,24,117,21,49,37,49,37,117,21,108,25,49,37,108,25,50,57,50,57,108,25,102,31,50,57,102,31,50,275,50,275,102,31,100,42,50,275,100,42,100,294,100,184,100,164,176,164,100,184,176,164,176,184,198,185,176,184,19 [...]
+238,411,236,419,233,426,227,431,220,435,213,436,205,435,198,431,193,426,189,419,188,411,189,403,193,397,198,391,204,388,212,387,220,388,227,391,233,397,236,403,238,411,16383,16383,138,411,137,419,133,426,128,431,121,435,113,436,105,435,98,431,93,426,90,419,89,411,90,403,93,397,98,391,105,388,113,387,121,388,128,391,133,397,137,403,138,411,16383,16383,299,84,285,84,271,57,255,38,234,26,206,20,169,18,151,18,132,19,117,21,108,25,102,31,100,42,100,164,176,164,198,162,213,158,222,150,229,136, [...]
+113,436,113,387,121,435,121,435,113,387,121,388,121,435,121,388,128,431,128,431,121,388,128,391,128,431,128,391,133,426,133,426,128,391,133,397,133,426,133,397,137,419,137,419,133,397,137,403,137,419,137,403,138,411,89,411,90,403,90,419,90,419,90,403,93,397,90,419,93,397,93,426,93,426,93,397,98,391,93,426,98,391,98,431,98,431,98,391,105,388,98,431,105,388,105,435,105,435,105,388,113,387,105,435,113,387,113,436,45,24,38,16,276,0,276,0,38,16,25,12,276,0,25,12,6,9,49,294,50,275,106,310,49,2 [...]
+134,378,62,453,57,457,53,460,49,462,41,464,35,463,29,461,26,458,23,454,22,448,23,443,25,439,28,434,32,430,37,426,114,378,16383,16383,157,0,157,9,137,11,122,16,114,24,109,37,108,56,108,276,109,295,113,308,122,316,136,320,157,321,157,331,9,331,9,321,30,320,44,316,53,308,57,295,57,56,56,36,52,23,44,15,30,11,9,9,9,0,
+114,378,134,378,62,453,114,378,62,453,57,457,114,378,57,457,53,460,114,378,53,460,49,462,114,378,49,462,45,463,114,378,45,463,41,464,114,378,41,464,37,426,22,448,23,443,23,454,23,454,23,443,25,439,23,454,25,439,26,458,26,458,25,439,28,434,26,458,28,434,29,461,29,461,28,434,32,430,29,461,32,430,35,463,35,463,32,430,37,426,35,463,37,426,41,464,52,23,44,15,157,0,157,0,44,15,30,11,157,0,30,11,9,9,157,331,9,331,30,320,157,331,30,320,44,316,157,331,44,316,53,308,157,331,53,308,57,295,157,331,5 [...]
+32,378,52,378,129,427,139,435,142,439,143,443,144,448,143,454,141,458,137,461,133,463,127,464,122,463,118,462,115,460,110,457,105,453,16383,16383,157,0,157,9,137,11,122,16,114,24,109,37,108,56,108,276,109,295,113,308,122,316,136,320,157,321,157,331,9,331,9,321,30,320,44,316,53,308,57,295,57,56,56,36,52,23,44,15,30,11,9,9,9,0,
+127,464,129,427,133,463,133,463,129,427,134,431,133,463,134,431,137,461,137,461,134,431,139,435,137,461,139,435,141,458,141,458,139,435,142,439,141,458,142,439,143,454,143,454,142,439,143,443,143,454,143,443,144,448,129,427,127,464,122,463,129,427,122,463,118,462,129,427,118,462,115,460,129,427,115,460,110,457,129,427,110,457,105,453,129,427,105,453,52,378,52,23,44,15,157,0,157,0,44,15,30,11,157,0,30,11,9,9,157,331,9,331,30,320,157,331,30,320,44,316,157,331,44,316,53,308,157,331,53,308,5 [...]
+161,378,98,462,67,462,5,378,22,378,83,430,143,378,16383,16383,153,0,153,9,133,11,119,16,110,24,106,37,104,56,104,276,105,295,110,308,118,316,132,320,153,321,153,331,5,331,5,321,26,320,40,316,49,308,53,295,54,276,54,56,53,36,49,23,40,15,26,11,5,9,5,0,
+5,378,22,378,67,462,67,462,22,378,83,430,67,462,83,430,98,462,98,462,83,430,143,378,98,462,143,378,161,378,49,23,40,15,153,0,153,0,40,15,26,11,153,0,26,11,5,9,153,331,5,331,26,320,153,331,26,320,40,316,153,331,40,316,49,308,153,331,49,308,53,295,153,331,53,295,118,316,153,331,118,316,132,320,153,331,132,320,153,321,119,16,110,24,54,56,54,56,110,24,106,37,54,56,106,37,54,276,54,276,106,37,104,56,54,276,104,56,104,276,54,276,104,276,105,295,54,276,105,295,110,308,54,276,110,308,118,316,54, [...]
+157,411,156,419,153,426,147,431,140,435,132,436,125,435,118,431,113,426,109,419,108,411,109,403,113,397,118,391,124,388,132,387,140,388,147,391,153,397,156,403,157,411,16383,16383,58,411,57,419,53,426,48,431,41,435,33,436,25,435,18,431,13,426,10,419,8,411,10,403,13,397,18,391,25,388,32,387,40,388,47,391,53,397,57,403,58,411,16383,16383,157,0,157,9,136,11,122,16,114,24,109,37,108,56,108,276,109,295,113,308,122,316,136,320,157,321,157,331,8,331,8,321,30,320,44,316,52,308,56,295,57,276,57,5 [...]
+8,411,10,403,10,419,10,419,10,403,13,397,10,419,13,397,13,426,13,426,13,397,18,391,13,426,18,391,18,431,18,431,18,391,25,388,18,431,25,388,25,435,25,435,25,388,32,387,25,435,32,387,33,436,33,436,32,387,40,388,33,436,40,388,41,435,41,435,40,388,47,391,41,435,47,391,48,431,48,431,47,391,53,397,48,431,53,397,53,426,53,426,53,397,57,403,53,426,57,403,57,419,57,419,57,403,58,411,52,23,44,15,157,0,157,0,44,15,29,11,157,0,29,11,8,9,157,331,8,331,30,320,157,331,30,320,44,316,157,331,44,316,52,30 [...]
+8,331,8,321,28,319,40,315,48,307,51,295,52,276,52,180,11,180,11,157,52,157,52,55,51,36,47,24,40,16,27,12,8,9,8,0,150,0,183,2,213,7,242,16,267,27,287,41,307,60,322,83,333,109,340,137,343,167,334,224,308,269,267,303,212,324,143,331,16383,16383,103,157,176,157,176,180,103,180,103,293,104,301,106,307,111,310,117,312,127,313,152,312,175,309,194,304,212,297,227,289,249,271,266,249,278,224,285,195,288,164,285,130,278,101,266,76,249,55,227,39,211,31,194,26,175,22,153,19,128,18,118,19,111,21,106, [...]
+47,24,40,16,150,0,150,0,40,16,27,12,150,0,27,12,8,9,40,315,48,307,143,331,143,331,48,307,51,295,143,331,51,295,52,276,104,31,52,276,52,180,104,31,52,180,52,157,52,157,52,180,11,180,52,157,11,180,11,157,104,301,106,307,52,276,52,276,106,307,111,310,52,276,111,310,143,331,143,331,111,310,117,312,143,331,117,312,127,313,127,313,117,312,127,312,127,313,127,312,152,312,127,313,152,312,143,331,143,331,152,312,212,324,175,22,183,2,194,26,194,26,183,2,213,7,194,26,213,7,211,31,211,31,213,7,227,3 [...]
+244,444,240,434,235,427,230,422,224,420,218,419,213,419,208,420,203,422,191,426,180,432,172,436,158,440,151,441,145,441,130,439,118,433,108,423,100,409,94,391,108,391,112,399,116,406,122,410,128,413,134,414,138,414,146,412,150,410,155,408,177,398,185,394,193,392,200,391,206,391,221,393,234,399,244,409,252,424,259,444,16383,16383,353,331,235,331,235,321,247,320,256,319,263,317,275,309,278,303,281,295,283,285,284,274,284,89,91,331,6,331,6,321,19,321,29,318,37,313,46,306,55,295,55,75,54,48, [...]
+112,399,116,406,118,433,118,433,116,406,122,410,118,433,122,410,130,439,130,439,122,410,128,413,130,439,128,413,134,414,134,414,138,414,145,441,145,441,138,414,142,413,145,441,142,413,146,412,108,391,112,399,118,433,108,391,118,433,108,423,108,391,108,423,100,409,108,391,100,409,94,391,145,441,146,412,151,441,151,441,146,412,150,410,151,441,150,410,155,408,155,408,166,403,158,440,158,440,166,403,165,438,145,441,130,439,134,414,158,440,151,441,155,408,165,438,166,403,172,436,172,436,166,4 [...]
+225,378,152,453,148,457,143,460,139,462,131,464,125,463,120,461,116,458,114,454,113,448,113,443,115,439,118,434,128,426,205,378,16383,16383,344,166,336,222,314,269,280,306,235,330,180,338,126,330,81,307,46,271,24,224,17,167,24,109,46,61,81,24,126,1,180,-6,234,1,279,24,314,60,336,108,344,166,16383,16383,287,169,285,134,280,103,272,76,260,53,246,35,235,26,223,19,209,15,196,12,181,11,167,12,154,15,142,19,130,25,119,33,103,52,90,75,81,102,76,132,74,166,76,194,80,222,87,247,97,269,108,286,121 [...]
+205,378,225,378,152,453,205,378,152,453,148,457,205,378,148,457,143,460,205,378,143,460,139,462,205,378,139,462,135,463,205,378,135,463,131,464,205,378,131,464,128,426,113,448,113,443,114,454,114,454,113,443,115,439,114,454,115,439,116,458,116,458,115,439,118,434,116,458,118,434,120,461,120,461,118,434,123,430,120,461,123,430,125,463,125,463,123,430,128,426,125,463,128,426,131,464,149,314,180,338,134,308,134,308,180,338,126,330,134,308,126,330,121,298,121,298,126,330,108,286,97,269,108,2 [...]
+129,378,150,378,227,427,232,431,236,435,239,439,241,443,242,448,241,454,239,458,235,461,230,463,224,464,216,462,212,460,208,457,203,453,16383,16383,344,166,336,222,314,269,280,306,235,330,180,338,126,330,81,307,46,271,24,224,17,167,24,109,46,61,81,24,126,1,180,-6,234,1,279,24,314,60,336,108,344,166,16383,16383,287,169,285,134,280,103,272,76,260,53,246,35,235,26,223,19,209,15,196,12,181,11,167,12,154,15,142,19,130,25,119,33,103,52,90,75,81,102,76,132,74,166,76,194,80,222,87,247,97,269,108 [...]
+149,314,180,338,134,308,134,308,180,338,126,330,134,308,126,330,121,298,121,298,126,330,108,286,97,269,108,286,126,330,97,269,126,330,81,307,81,102,81,24,90,75,90,75,81,24,126,1,90,75,126,1,103,52,103,52,126,1,119,33,130,25,119,33,126,1,130,25,126,1,180,-6,207,316,235,330,194,319,194,319,235,330,180,320,164,318,180,320,180,338,164,318,180,338,149,314,81,307,46,271,46,61,81,307,46,61,74,166,81,307,74,166,76,194,81,307,76,194,80,222,81,307,80,222,87,247,81,307,87,247,97,269,81,102,76,132,8 [...]
+255,378,193,462,161,462,99,378,117,378,177,430,238,378,16383,16383,344,166,336,222,314,269,280,306,235,330,180,338,126,330,81,307,46,271,24,224,17,167,24,109,46,61,81,24,126,1,180,-6,234,1,279,24,314,60,336,108,344,166,16383,16383,287,169,285,134,280,103,272,76,260,53,246,35,235,26,223,19,209,15,196,12,181,11,167,12,154,15,142,19,130,25,119,33,103,52,90,75,81,102,76,132,74,166,76,194,80,222,87,247,97,269,108,286,121,298,134,308,149,314,164,318,180,320,194,319,207,316,219,311,231,305,242, [...]
+99,378,117,378,161,462,161,462,117,378,177,430,161,462,177,430,193,462,193,462,177,430,238,378,193,462,238,378,255,378,149,314,180,338,134,308,134,308,180,338,126,330,134,308,126,330,121,298,121,298,126,330,108,286,97,269,108,286,126,330,97,269,126,330,81,307,81,102,81,24,90,75,90,75,81,24,126,1,90,75,126,1,103,52,103,52,126,1,119,33,130,25,119,33,126,1,130,25,126,1,180,-6,207,316,235,330,194,319,194,319,235,330,180,320,164,318,180,320,180,338,164,318,180,338,149,314,81,307,46,271,46,61, [...]
+244,444,240,434,235,427,230,422,224,420,218,419,213,419,208,420,203,422,191,426,180,432,172,436,158,440,151,441,145,441,130,439,118,433,108,423,100,409,94,391,108,391,112,399,116,406,122,410,128,413,134,414,138,414,146,412,150,410,155,408,177,398,185,394,193,392,200,391,206,391,221,393,234,399,244,409,252,424,259,444,16383,16383,344,166,336,222,314,269,280,306,235,330,180,338,126,330,81,307,46,271,24,224,17,167,24,109,46,61,81,24,126,1,180,-6,234,1,279,24,314,60,336,108,344,166,16383,163 [...]
+112,399,116,406,118,433,118,433,116,406,122,410,118,433,122,410,130,439,130,439,122,410,128,413,130,439,128,413,134,414,134,414,138,414,145,441,145,441,138,414,142,413,145,441,142,413,146,412,108,391,112,399,118,433,108,391,118,433,108,423,108,391,108,423,100,409,108,391,100,409,94,391,145,441,146,412,151,441,151,441,146,412,150,410,151,441,150,410,155,408,155,408,166,403,158,440,158,440,166,403,165,438,145,441,130,439,134,414,158,440,151,441,155,408,165,438,166,403,172,436,172,436,166,4 [...]
+252,411,250,419,247,426,241,431,234,435,227,436,219,435,212,431,207,426,203,419,202,411,203,403,207,397,212,391,218,388,226,387,234,388,241,391,247,397,250,403,252,411,16383,16383,152,411,151,419,147,426,142,431,135,435,127,436,119,435,113,431,107,426,104,419,103,411,104,403,107,397,112,391,119,388,127,387,135,388,142,391,147,397,151,403,152,411,16383,16383,344,166,336,222,314,269,280,306,235,330,180,338,126,330,81,307,46,271,24,224,17,167,24,109,46,61,81,24,126,1,180,-6,234,1,279,24,314 [...]
+103,411,104,403,104,419,104,419,104,403,107,397,104,419,107,397,107,426,107,426,107,397,112,391,107,426,112,391,113,431,113,431,112,391,119,388,113,431,119,388,119,435,119,435,119,388,127,387,119,435,127,387,127,436,127,436,127,387,135,388,127,436,135,388,135,435,135,435,135,388,142,391,135,435,142,391,142,431,142,431,142,391,147,397,142,431,147,397,147,426,147,426,147,397,151,403,147,426,151,403,151,419,151,419,151,403,152,411,149,314,180,338,134,308,134,308,180,338,126,330,134,308,126, [...]
+299,11,184,126,299,242,276,265,160,150,45,265,22,242,137,126,22,11,45,-11,160,103,276,-11,
+184,126,299,242,276,265,184,126,276,265,160,150,184,126,160,150,276,-11,184,126,276,-11,299,11,22,11,45,-11,137,126,137,126,45,-11,160,103,137,126,160,103,160,150,160,150,160,103,276,-11,45,265,22,242,137,126,45,265,137,126,160,150,
+329,367,305,367,268,314,250,323,233,330,217,335,200,337,181,338,127,330,81,307,47,270,25,222,17,165,18,147,20,129,24,111,30,94,36,79,48,59,55,50,75,30,28,-39,52,-39,92,18,110,8,127,1,143,-3,161,-5,180,-6,234,1,279,24,314,61,336,109,344,166,343,184,340,203,336,220,331,237,325,252,319,263,313,272,305,281,296,291,285,302,16383,16383,97,61,88,80,82,99,77,119,75,141,74,165,79,218,93,261,115,293,144,313,180,320,196,319,211,315,225,309,238,300,251,287,16383,16383,263,270,272,251,279,232,284,212 [...]
+48,59,55,50,81,307,81,307,55,50,64,41,81,307,64,41,74,165,74,165,75,30,75,141,75,141,75,30,77,119,282,113,268,70,279,24,279,24,268,70,246,38,279,24,246,38,234,1,234,1,246,38,217,18,234,1,217,18,180,11,180,11,164,12,180,-6,180,-6,164,12,161,-5,88,80,92,18,97,61,97,61,92,18,110,8,97,61,110,8,109,44,109,44,110,8,122,32,122,32,110,8,127,1,122,32,127,1,135,22,135,22,127,1,143,-3,135,22,143,-3,149,16,149,16,143,-3,161,-5,149,16,161,-5,164,12,92,18,88,80,82,99,92,18,82,99,77,119,92,18,77,119,75 [...]
+227,378,154,453,149,457,145,460,141,462,137,463,132,464,126,463,121,461,118,458,115,454,114,448,115,443,117,439,120,434,124,430,129,426,206,378,16383,16383,353,331,237,331,237,321,257,319,270,312,279,301,282,283,283,257,283,103,282,85,279,70,273,57,265,45,254,34,241,26,225,20,208,16,189,15,173,16,158,19,146,24,135,30,125,37,115,50,109,63,105,79,104,97,103,118,103,275,104,293,108,306,115,314,128,319,148,321,148,331,7,331,7,321,27,319,40,315,47,308,51,297,52,280,52,124,53,95,58,69,66,48,78 [...]
+206,378,227,378,154,453,206,378,154,453,149,457,206,378,149,457,145,460,206,378,145,460,141,462,206,378,141,462,137,463,206,378,137,463,132,464,206,378,132,464,129,426,114,448,115,443,115,454,115,454,115,443,117,439,115,454,117,439,118,458,118,458,117,439,120,434,118,458,120,434,121,461,121,461,120,434,124,430,121,461,124,430,126,463,126,463,124,430,129,426,126,463,129,426,132,464,105,79,106,8,109,63,109,63,106,8,121,1,109,63,121,1,115,50,115,50,121,1,125,37,135,30,125,37,138,-3,135,30,1 [...]
+132,378,152,378,229,427,234,431,238,435,241,439,243,443,244,448,243,454,241,458,237,461,233,463,227,464,222,463,218,462,214,460,210,457,205,453,16383,16383,353,331,237,331,237,321,257,319,270,312,279,301,282,283,283,257,283,103,282,85,279,70,273,57,265,45,254,34,241,26,225,20,208,16,189,15,173,16,158,19,146,24,135,30,125,37,115,50,109,63,105,79,104,97,103,118,103,275,104,293,108,306,115,314,128,319,148,321,148,331,7,331,7,321,27,319,40,315,47,308,51,297,52,280,52,124,53,95,58,69,66,48,78 [...]
+105,79,106,8,109,63,109,63,106,8,121,1,109,63,121,1,115,50,115,50,121,1,125,37,135,30,125,37,138,-3,135,30,138,-3,146,24,146,24,138,-3,157,-5,146,24,157,-5,158,19,158,19,157,-5,177,-6,158,19,177,-6,173,16,173,16,177,-6,189,15,208,16,189,15,204,-5,208,16,204,-5,227,0,103,118,103,275,93,16,103,118,93,16,104,97,104,97,93,16,106,8,104,97,106,8,105,79,125,37,121,1,138,-3,227,464,229,427,233,463,233,463,229,427,234,431,233,463,234,431,237,461,237,461,234,431,238,435,237,461,238,435,241,458,241 [...]
+256,378,193,462,162,462,100,378,117,378,177,430,238,378,16383,16383,353,331,237,331,237,321,257,319,270,312,279,301,282,283,283,257,283,103,282,85,279,70,273,57,265,45,254,34,241,26,225,20,208,16,189,15,173,16,158,19,146,24,135,30,125,37,115,50,109,63,105,79,104,97,103,118,103,275,104,293,108,306,115,314,128,319,148,321,148,331,7,331,7,321,27,319,40,315,47,308,51,297,52,280,52,124,53,95,58,69,66,48,78,30,93,16,106,8,121,1,138,-3,157,-5,177,-6,204,-5,227,0,247,6,264,17,278,30,290,45,297,6 [...]
+100,378,117,378,162,462,162,462,117,378,177,430,162,462,177,430,193,462,193,462,177,430,238,378,193,462,238,378,256,378,105,79,106,8,109,63,109,63,106,8,121,1,109,63,121,1,115,50,115,50,121,1,125,37,135,30,125,37,138,-3,135,30,138,-3,146,24,146,24,138,-3,157,-5,146,24,157,-5,158,19,158,19,157,-5,177,-6,158,19,177,-6,173,16,173,16,177,-6,189,15,208,16,189,15,204,-5,208,16,204,-5,227,0,103,118,103,275,93,16,103,118,93,16,104,97,104,97,93,16,106,8,104,97,106,8,105,79,125,37,121,1,138,-3,283 [...]
+252,411,250,419,247,426,241,431,234,435,227,436,219,435,212,431,207,426,203,419,202,411,203,403,207,397,212,391,218,388,226,387,234,388,241,391,247,397,250,403,252,411,16383,16383,152,411,151,419,147,426,142,431,135,435,127,436,119,435,113,431,107,426,104,419,103,411,104,403,107,397,112,391,119,388,127,387,135,388,142,391,147,397,151,403,152,411,16383,16383,353,331,237,331,237,321,257,319,270,312,279,301,282,283,283,257,283,103,282,85,279,70,273,57,265,45,254,34,241,26,225,20,208,16,189, [...]
+202,411,203,403,203,419,203,419,203,403,207,397,203,419,207,397,207,426,207,426,207,397,212,391,207,426,212,391,212,431,212,431,212,391,218,388,212,431,218,388,219,435,219,435,218,388,226,387,219,435,226,387,227,436,227,436,226,387,234,388,227,436,234,388,234,435,234,435,234,388,241,391,234,435,241,391,241,431,241,431,241,391,247,397,241,431,247,397,247,426,247,426,247,397,250,403,247,426,250,403,250,419,250,419,250,403,252,411,103,411,104,403,104,419,104,419,104,403,107,397,104,419,107, [...]
+133,378,153,378,230,427,240,435,243,439,244,443,245,448,244,454,242,458,238,461,234,463,228,464,223,463,219,462,216,460,211,457,206,453,16383,16383,352,331,243,331,243,321,256,321,266,319,272,316,275,312,276,306,276,302,274,294,272,290,270,285,197,174,124,285,121,289,118,294,116,299,115,304,115,308,116,312,119,316,123,318,130,320,138,321,151,321,151,331,11,331,11,321,24,319,37,313,50,299,68,277,92,243,157,147,157,61,156,39,152,25,144,16,129,12,107,9,107,0,260,0,260,9,239,11,224,15,215,23 [...]
+121,289,118,294,157,147,157,147,118,294,116,299,157,147,116,299,92,243,92,243,116,299,115,304,92,243,115,304,115,308,115,308,116,312,92,243,151,331,11,331,24,319,151,331,24,319,37,313,151,331,37,313,50,299,151,331,50,299,123,318,151,331,123,318,130,320,151,331,130,320,138,321,151,331,138,321,151,321,123,318,50,299,119,316,119,316,50,299,68,277,119,316,68,277,116,312,116,312,68,277,92,243,209,55,209,151,197,174,209,55,197,174,210,36,210,36,197,174,157,147,210,36,157,147,215,23,215,23,157, [...]
+101,266,101,268,100,269,100,271,101,292,105,306,113,314,127,319,147,321,147,331,8,331,8,321,27,319,39,314,46,307,49,294,50,276,50,60,49,39,46,25,39,17,27,12,8,9,8,0,148,0,148,9,128,11,114,16,106,23,102,36,101,55,101,80,109,80,115,79,136,79,158,80,177,82,194,85,210,90,223,96,239,107,253,121,263,138,269,156,271,175,265,206,248,231,221,250,185,262,141,266,16383,16383,101,230,101,237,103,242,106,245,110,247,117,247,154,244,182,236,201,221,213,200,217,172,213,146,202,126,185,111,161,102,129,9 [...]
+50,276,102,36,50,276,50,276,102,36,101,55,50,276,101,55,100,271,100,271,101,292,50,276,50,276,101,292,105,306,50,276,105,306,113,314,147,331,8,331,27,319,147,331,27,319,39,314,147,331,39,314,46,307,147,331,46,307,49,294,147,331,49,294,113,314,147,331,113,314,127,319,147,331,127,319,147,321,50,276,113,314,49,294,101,237,103,242,101,266,101,266,103,242,106,245,101,266,106,245,141,266,141,266,106,245,110,247,141,266,110,247,117,247,117,247,154,244,141,266,141,266,154,244,185,262,201,221,213 [...]
+36,42,36,28,33,19,28,13,19,9,6,7,6,0,79,0,79,275,81,293,86,308,95,319,107,326,122,328,137,325,150,316,159,302,165,282,167,258,165,237,159,220,150,207,137,199,119,195,114,194,110,193,107,191,105,189,105,184,107,182,110,180,115,179,121,179,145,173,163,161,176,140,184,111,187,75,186,61,185,48,182,36,179,26,175,19,172,15,164,11,160,10,155,10,150,11,146,12,143,15,142,19,141,25,140,36,138,42,135,48,130,52,125,55,118,56,111,55,105,51,100,46,97,40,96,32,98,20,105,10,115,2,129,-2,145,-3,173,0,198 [...]
+33,19,28,13,79,0,79,0,28,13,19,9,79,0,19,9,6,7,158,185,142,189,145,173,145,173,142,189,137,199,145,173,137,199,121,179,121,179,137,199,119,195,121,179,119,195,115,179,115,179,119,195,114,194,115,179,114,194,110,180,110,180,114,194,110,193,110,180,110,193,107,182,107,182,110,193,107,191,107,182,107,191,105,184,105,184,107,191,105,189,105,184,105,189,105,187,81,293,86,308,93,337,93,337,86,308,95,319,93,337,95,319,126,342,126,342,95,319,107,326,126,342,107,326,122,328,122,328,137,325,126,34 [...]
+158,253,86,328,81,332,77,335,73,337,65,339,59,338,53,336,50,333,47,329,46,323,47,318,49,314,52,309,56,305,61,301,138,253,16383,16383,221,33,216,29,208,25,200,23,195,25,190,28,187,35,185,44,184,56,184,168,183,181,180,191,176,199,170,208,162,215,152,222,140,226,127,229,111,230,98,229,85,227,73,224,63,220,54,215,44,208,37,200,32,192,29,183,28,175,29,167,33,161,37,156,43,153,50,152,57,153,63,156,68,161,71,167,73,172,72,178,72,182,71,185,70,189,70,194,71,201,76,208,83,213,93,217,104,218,117,2 [...]
+138,253,158,253,86,328,138,253,86,328,81,332,138,253,81,332,77,335,138,253,77,335,73,337,138,253,73,337,69,338,138,253,69,338,65,339,138,253,65,339,61,301,46,323,47,318,47,329,47,329,47,318,49,314,47,329,49,314,50,333,50,333,49,314,52,309,50,333,52,309,53,336,53,336,52,309,56,305,53,336,56,305,59,338,59,338,56,305,61,301,59,338,61,301,65,339,37,156,43,153,44,208,44,208,43,153,50,152,44,208,50,152,54,215,54,215,50,152,57,153,54,215,57,153,63,220,63,220,57,153,63,156,63,220,63,156,73,224,7 [...]
+60,253,79,253,156,302,162,306,166,310,169,314,171,318,171,329,168,333,165,336,160,338,154,339,146,337,142,335,138,332,133,328,16383,16383,221,33,216,29,208,25,200,23,195,25,190,28,187,35,185,44,184,56,184,168,183,181,180,191,176,199,170,208,162,215,152,222,140,226,127,229,111,230,98,229,85,227,73,224,63,220,54,215,44,208,37,200,32,192,29,183,28,175,29,167,33,161,37,156,43,153,50,152,57,153,63,156,68,161,71,167,73,172,72,178,72,182,71,185,70,189,70,194,71,201,76,208,83,213,93,217,104,218, [...]
+37,156,43,153,44,208,44,208,43,153,50,152,44,208,50,152,54,215,54,215,50,152,57,153,54,215,57,153,63,220,63,220,57,153,63,156,63,220,63,156,73,224,73,224,63,156,70,194,71,167,70,194,68,161,111,230,104,218,117,216,111,230,117,216,127,229,127,229,117,216,128,211,127,229,128,211,140,226,140,226,128,211,136,202,140,226,136,202,142,190,76,208,83,213,85,227,85,227,83,213,93,217,85,227,93,217,98,229,98,229,93,217,104,218,98,229,104,218,111,230,73,224,70,194,71,201,73,224,71,201,76,208,73,224,76 [...]
+190,253,128,337,97,337,35,253,52,253,113,305,174,253,16383,16383,221,33,216,29,208,25,200,23,195,25,190,28,187,35,185,44,184,56,184,168,183,181,180,191,176,199,170,208,162,215,152,222,140,226,127,229,111,230,98,229,85,227,73,224,63,220,54,215,44,208,37,200,32,192,29,183,28,175,29,167,33,161,37,156,43,153,50,152,57,153,63,156,68,161,71,167,73,172,72,178,72,182,71,185,70,189,70,194,71,201,76,208,83,213,93,217,104,218,117,216,128,211,136,202,142,190,143,173,143,146,114,135,92,126,75,118,63, [...]
+35,253,52,253,97,337,97,337,52,253,113,305,97,337,113,305,128,337,128,337,113,305,174,253,128,337,174,253,190,253,37,156,43,153,44,208,44,208,43,153,50,152,44,208,50,152,54,215,54,215,50,152,57,153,54,215,57,153,63,220,63,220,57,153,63,156,63,220,63,156,73,224,73,224,63,156,70,194,71,167,70,194,68,161,111,230,104,218,117,216,111,230,117,216,127,229,127,229,117,216,128,211,127,229,128,211,140,226,140,226,128,211,136,202,140,226,136,202,142,190,76,208,83,213,85,227,85,227,83,213,93,217,85, [...]
+180,319,175,309,170,302,165,297,160,295,153,294,149,294,144,295,138,297,133,299,127,301,115,307,108,311,94,315,87,316,80,316,66,314,54,308,43,298,35,284,30,266,44,266,48,274,52,281,57,285,63,288,70,289,73,289,81,287,86,285,90,283,102,278,112,273,121,269,128,267,135,266,142,266,157,268,169,274,180,284,188,299,195,319,16383,16383,221,33,216,29,208,25,200,23,195,25,190,28,187,35,185,44,184,56,184,168,183,181,180,191,176,199,170,208,162,215,152,222,140,226,127,229,111,230,98,229,85,227,73,22 [...]
+48,274,52,281,54,308,54,308,52,281,57,285,54,308,57,285,66,314,66,314,57,285,63,288,66,314,63,288,70,289,70,289,73,289,80,316,80,316,73,289,77,288,80,316,77,288,81,287,44,266,48,274,54,308,44,266,54,308,43,298,44,266,43,298,35,284,44,266,35,284,30,266,37,156,43,153,44,208,44,208,43,153,50,152,44,208,50,152,54,215,54,215,50,152,57,153,54,215,57,153,63,220,63,220,57,153,63,156,63,220,63,156,73,224,73,224,63,156,70,194,71,167,70,194,68,161,80,316,81,287,87,316,87,316,81,287,86,285,87,316,86 [...]
+186,286,185,294,182,301,176,306,169,310,161,311,154,310,147,306,142,301,138,294,137,286,138,278,142,272,147,266,153,263,161,262,169,263,176,266,182,272,185,278,186,286,16383,16383,87,286,86,294,82,301,77,306,70,310,62,311,54,310,48,306,42,301,39,294,37,286,39,278,42,272,47,266,54,263,61,262,69,263,76,266,82,272,86,278,87,286,16383,16383,221,33,216,29,208,25,200,23,195,25,190,28,187,35,185,44,184,56,184,168,183,181,180,191,176,199,170,208,162,215,152,222,140,226,127,229,111,230,98,229,85, [...]
+161,311,161,262,169,310,169,310,161,262,169,263,169,310,169,263,176,306,176,306,169,263,176,266,176,306,176,266,182,301,182,301,176,266,182,272,182,301,182,272,185,294,185,294,182,272,185,278,185,294,185,278,186,286,137,286,138,278,138,294,138,294,138,278,142,272,138,294,142,272,142,301,142,301,142,272,147,266,142,301,147,266,147,306,147,306,147,266,153,263,147,306,153,263,154,310,154,310,153,263,161,262,154,310,161,262,161,311,184,56,184,152,184,168,184,56,184,168,183,181,184,56,183,181 [...]
+162,306,159,322,152,336,142,347,128,354,113,357,97,354,83,347,72,336,65,323,63,307,65,291,72,277,83,267,96,260,112,257,128,260,141,267,152,277,159,291,162,306,16383,16383,145,307,143,296,139,287,132,280,122,276,112,274,101,276,92,280,85,287,81,296,79,307,81,317,86,326,93,333,102,338,112,339,122,338,131,333,139,326,143,317,145,307,16383,16383,221,33,216,29,208,25,200,23,195,25,190,28,187,35,185,44,184,56,184,168,183,181,180,191,176,199,170,208,162,215,152,222,140,226,127,229,111,230,98,22 [...]
+143,296,139,287,141,267,141,267,139,287,132,280,141,267,132,280,128,260,128,260,132,280,122,276,128,260,122,276,112,257,112,257,122,276,112,274,63,307,65,291,65,323,65,323,65,291,72,277,65,323,72,277,72,336,72,336,72,277,83,267,72,336,83,267,79,307,79,307,83,347,72,336,37,156,43,153,44,208,44,208,43,153,50,152,44,208,50,152,54,215,54,215,50,152,57,153,54,215,57,153,63,220,63,220,57,153,63,156,63,220,63,156,73,224,73,224,63,156,70,194,71,167,70,194,68,161,111,230,104,218,117,216,111,230,1 [...]
+310,77,296,58,283,44,269,35,254,30,238,28,226,30,215,33,205,38,197,45,190,54,185,65,181,78,179,93,178,112,177,138,308,138,302,173,292,199,277,216,255,227,228,230,215,229,203,227,192,222,181,216,169,206,157,216,147,222,136,227,123,229,109,230,84,227,62,220,45,208,34,193,30,176,31,168,34,161,38,156,44,153,52,152,59,153,66,156,70,161,73,167,74,175,74,185,73,188,73,196,74,203,79,208,86,213,96,216,107,217,119,215,127,210,133,202,136,189,137,172,137,141,73,123,48,112,32,99,24,84,20,68,19,50,22 [...]
+73,196,73,196,73,196,73,196,74,203,62,220,73,196,62,220,66,156,73,196,66,156,70,161,143,38,134,31,134,17,134,17,134,31,121,25,134,17,121,25,119,7,119,7,121,25,108,21,119,7,108,21,105,1,105,1,108,21,95,19,105,1,95,19,91,-1,91,-1,95,19,83,21,91,-1,83,21,77,-2,77,-2,83,21,74,28,77,-2,74,28,67,37,63,63,58,0,64,49,64,49,58,0,77,-2,64,49,77,-2,67,37,74,203,79,208,84,227,84,227,79,208,86,213,84,227,86,213,109,230,109,230,86,213,96,216,109,230,96,216,107,217,107,217,119,215,109,230,109,230,119,2 [...]
+199,78,185,60,172,46,159,38,144,33,128,31,103,36,81,49,65,69,54,96,51,128,54,157,63,181,78,200,96,211,119,215,128,215,136,212,141,208,145,201,148,191,151,180,154,172,159,166,163,161,169,158,175,157,183,158,189,161,195,166,198,172,199,179,195,195,184,209,167,220,146,227,122,230,108,229,94,226,80,220,67,213,55,204,40,189,28,172,19,152,14,130,12,106,16,72,27,43,45,20,68,4,96,-3,77,-49,80,-51,83,-50,85,-50,88,-49,94,-49,104,-50,112,-52,117,-55,120,-60,121,-67,120,-74,116,-81,111,-85,103,-88, [...]
+81,49,65,69,68,4,68,4,65,69,54,96,68,4,54,96,45,20,45,20,54,96,51,128,55,204,51,128,54,157,55,204,54,157,63,181,87,-106,96,-107,88,-89,88,-89,96,-107,94,-89,103,-88,94,-89,96,-107,103,-88,96,-107,117,-105,96,-3,94,-49,104,-50,96,-3,104,-50,103,-31,96,-3,103,-31,103,36,103,36,103,-31,113,-4,96,-3,77,-49,80,-51,96,-3,80,-51,83,-50,96,-3,83,-50,85,-50,96,-3,85,-50,88,-49,96,-3,88,-49,91,-49,96,-3,91,-49,94,-49,185,60,172,46,174,24,174,24,172,46,159,38,174,24,159,38,156,9,156,9,159,38,144,33 [...]
+155,253,83,328,78,332,74,335,69,337,61,339,55,338,50,336,46,333,44,329,43,323,44,318,46,314,49,309,53,305,58,301,135,253,16383,16383,204,82,190,62,176,48,162,37,146,31,127,30,114,31,101,34,90,39,80,47,71,57,62,71,56,85,52,100,50,118,49,138,203,138,201,153,198,166,195,177,185,195,175,207,163,217,149,224,133,228,116,230,81,224,52,207,31,182,17,148,12,108,17,70,29,39,49,15,75,0,108,-4,136,-1,160,9,181,26,198,49,212,79,16383,16383,50,155,55,175,63,191,74,203,87,210,103,212,120,210,133,203,14 [...]
+56,85,75,0,62,71,62,71,75,0,71,57,80,47,71,57,75,0,80,47,75,0,108,-4,52,100,50,118,49,15,52,100,49,15,75,0,52,100,75,0,56,85,12,108,17,70,17,148,17,148,17,70,29,39,17,148,29,39,31,182,31,182,29,39,49,15,31,182,49,15,49,138,49,138,49,15,50,118,135,253,155,253,83,328,135,253,83,328,78,332,135,253,78,332,74,335,135,253,74,335,69,337,135,253,69,337,65,338,135,253,65,338,61,339,135,253,61,339,58,301,43,323,44,318,44,329,44,329,44,318,46,314,44,329,46,314,46,333,46,333,46,314,49,309,46,333,49, [...]
+58,253,78,253,155,302,161,306,165,310,168,314,170,318,170,323,169,329,167,333,163,336,158,338,152,339,148,338,145,337,141,335,137,332,132,328,16383,16383,204,82,190,62,176,48,162,37,146,31,127,30,114,31,101,34,90,39,80,47,71,57,62,71,56,85,52,100,50,118,49,138,203,138,201,153,198,166,195,177,185,195,175,207,163,217,149,224,133,228,116,230,81,224,52,207,31,182,17,148,12,108,17,70,29,39,49,15,75,0,108,-4,136,-1,160,9,181,26,198,49,212,79,16383,16383,50,155,55,175,63,191,74,203,87,210,103,2 [...]
+203,138,201,153,198,166,203,138,198,166,195,177,203,138,195,177,190,186,203,138,190,186,185,195,203,138,185,195,175,207,203,138,175,207,163,217,203,138,163,217,151,155,203,138,151,155,50,155,203,138,50,155,49,138,141,192,147,176,149,224,149,224,147,176,151,155,149,224,151,155,163,217,152,339,155,302,158,338,158,338,155,302,161,306,158,338,161,306,163,336,163,336,161,306,165,310,163,336,165,310,167,333,167,333,165,310,168,314,167,333,168,314,169,329,169,329,168,314,170,318,169,329,170,318 [...]
+190,253,127,337,97,337,35,253,51,253,112,305,173,253,16383,16383,204,82,190,62,176,48,162,37,146,31,127,30,114,31,101,34,90,39,80,47,71,57,62,71,56,85,52,100,50,118,49,138,203,138,201,153,198,166,195,177,185,195,175,207,163,217,149,224,133,228,116,230,81,224,52,207,31,182,17,148,12,108,17,70,29,39,49,15,75,0,108,-4,136,-1,160,9,181,26,198,49,212,79,16383,16383,50,155,55,175,63,191,74,203,87,210,103,212,120,210,133,203,141,192,147,176,151,155,
+35,253,51,253,97,337,97,337,51,253,112,305,97,337,112,305,127,337,127,337,112,305,173,253,127,337,173,253,190,253,52,100,50,118,49,15,49,15,50,118,49,138,49,15,49,138,31,182,49,15,31,182,29,39,29,39,31,182,17,148,29,39,17,148,17,70,17,70,17,148,12,108,133,228,116,230,120,210,120,210,116,230,103,212,87,210,103,212,116,230,87,210,116,230,81,224,190,62,176,48,181,26,181,26,176,48,162,37,181,26,162,37,160,9,160,9,162,37,146,31,160,9,146,31,136,-1,136,-1,146,31,127,30,203,138,201,153,198,166, [...]
+186,286,185,294,181,301,176,306,169,310,161,311,153,310,147,306,141,301,138,294,137,286,138,278,141,272,146,266,153,263,161,262,169,263,176,266,181,272,185,278,186,286,16383,16383,86,286,85,294,82,301,76,306,69,310,61,311,54,310,47,306,42,301,38,294,37,286,38,278,41,272,47,266,53,263,61,262,69,263,76,266,81,272,85,278,86,286,16383,16383,204,82,190,62,176,48,162,37,146,31,127,30,114,31,101,34,90,39,80,47,71,57,62,71,56,85,52,100,50,118,49,138,203,138,201,153,198,166,195,177,185,195,175,20 [...]
+203,138,201,153,198,166,203,138,198,166,195,177,203,138,195,177,190,186,203,138,190,186,185,195,203,138,185,195,175,207,203,138,175,207,163,217,203,138,163,217,151,155,203,138,151,155,50,155,203,138,50,155,49,138,141,192,147,176,149,224,149,224,147,176,151,155,149,224,151,155,163,217,137,286,138,278,138,294,138,294,138,278,141,272,138,294,141,272,141,301,141,301,141,272,146,266,141,301,146,266,147,306,147,306,146,266,153,263,147,306,153,263,153,310,153,310,153,263,161,262,153,310,161,262 [...]
+115,253,42,328,38,332,33,335,29,337,21,339,15,338,10,336,6,333,4,329,3,323,3,318,5,314,8,309,18,301,95,253,16383,16383,122,0,122,7,105,9,94,14,88,21,85,34,84,52,84,228,82,230,5,203,5,195,15,197,26,197,33,196,37,193,40,187,42,178,42,33,38,20,32,13,20,9,3,7,3,0,
+95,253,115,253,42,328,95,253,42,328,38,332,95,253,38,332,33,335,95,253,33,335,29,337,95,253,29,337,25,338,95,253,25,338,21,339,95,253,21,339,18,301,3,323,3,318,4,329,4,329,3,318,5,314,4,329,5,314,6,333,6,333,5,314,8,309,6,333,8,309,10,336,10,336,8,309,13,305,10,336,13,305,15,338,15,338,13,305,18,301,15,338,18,301,21,339,38,20,32,13,122,0,122,0,32,13,20,9,122,0,20,9,3,7,15,197,19,197,82,230,82,230,19,197,23,197,82,230,23,197,26,197,26,197,33,196,82,230,82,230,33,196,37,193,82,230,37,193,4 [...]
+25,253,45,253,122,302,127,306,131,310,134,314,136,318,137,323,136,329,134,333,130,336,125,338,119,339,111,337,107,335,103,332,98,328,16383,16383,127,0,127,7,110,9,99,14,93,21,90,34,89,52,89,228,87,230,10,203,10,195,20,197,31,197,38,196,42,193,45,187,47,178,47,33,43,20,37,13,25,9,8,7,8,0,
+119,339,122,302,125,338,125,338,122,302,127,306,125,338,127,306,130,336,130,336,127,306,131,310,130,336,131,310,134,333,134,333,131,310,134,314,134,333,134,314,136,329,136,329,134,314,136,318,136,329,136,318,137,323,122,302,119,339,115,338,122,302,115,338,111,337,122,302,111,337,107,335,122,302,107,335,103,332,122,302,103,332,98,328,122,302,98,328,45,253,43,20,37,13,127,0,127,0,37,13,25,9,127,0,25,9,8,7,20,197,24,197,87,230,87,230,24,197,28,197,87,230,28,197,31,197,31,197,38,196,87,230,8 [...]
+147,253,84,337,54,337,-7,253,8,253,69,305,130,253,16383,16383,110,0,110,7,93,9,83,14,77,21,74,34,73,52,73,228,70,230,-6,203,-6,195,0,196,3,197,15,197,21,196,26,193,29,187,31,178,31,52,30,33,27,20,21,13,9,9,-7,7,-7,0,
+-7,253,8,253,54,337,54,337,8,253,69,305,54,337,69,305,84,337,84,337,69,305,130,253,84,337,130,253,147,253,27,20,21,13,110,0,110,0,21,13,9,9,110,0,9,9,-7,7,3,197,8,197,70,230,70,230,8,197,11,197,70,230,11,197,15,197,15,197,21,196,70,230,70,230,21,196,26,193,70,230,26,193,29,187,31,166,31,52,77,21,31,166,77,21,74,34,31,166,74,34,73,52,31,166,73,52,70,230,31,166,70,230,31,178,0,196,3,197,70,230,0,196,70,230,-6,203,0,196,-6,203,-6,195,73,52,73,228,70,230,110,0,110,7,93,9,110,0,93,9,83,14,110 [...]
+144,286,143,294,139,301,133,306,127,310,119,311,111,310,104,306,99,301,96,294,94,286,96,278,99,272,104,266,111,263,118,262,126,263,133,266,139,272,143,278,144,286,16383,16383,45,286,43,294,40,301,34,306,27,310,20,311,12,310,5,306,0,301,-3,294,-4,286,-3,278,0,272,5,266,11,263,19,262,27,263,34,266,40,272,43,278,45,286,16383,16383,113,0,113,7,97,9,86,14,80,21,77,34,76,52,76,228,74,230,-2,203,-2,195,2,196,7,197,18,197,25,196,29,193,32,187,34,178,35,166,35,52,34,33,31,20,24,13,12,9,-4,7,-4,0,
+31,20,113,0,34,33,34,33,113,0,86,14,34,33,86,14,35,52,35,52,86,14,80,21,35,52,80,21,35,166,35,166,80,21,77,34,35,166,77,34,76,52,74,230,-2,203,2,196,74,230,2,196,7,197,74,230,7,197,11,197,74,230,11,197,15,197,74,230,15,197,18,197,74,230,18,197,25,196,74,230,25,196,29,193,74,230,29,193,32,187,74,230,32,187,34,178,74,230,34,178,35,166,74,230,35,166,76,52,74,230,76,52,76,228,94,286,96,278,96,294,96,294,96,278,99,272,96,294,99,272,99,301,99,301,99,272,104,266,99,301,104,266,104,306,104,306,1 [...]
+212,328,195,343,148,318,135,326,122,332,107,337,90,340,71,342,50,329,66,326,80,323,93,318,105,311,118,302,57,270,74,255,135,287,151,272,163,256,172,239,179,220,184,200,170,212,159,221,148,226,136,229,123,230,89,224,59,208,35,182,20,148,15,108,20,70,35,38,58,15,88,0,123,-4,145,-2,165,3,182,13,196,26,209,44,218,60,225,79,231,99,234,120,235,142,233,179,225,215,211,248,192,278,166,304,16383,16383,190,101,187,69,179,44,167,25,151,13,132,9,104,18,83,41,70,73,62,108,60,141,62,165,70,185,83,201, [...]
+136,229,123,230,142,211,142,211,123,230,118,216,99,212,118,216,123,230,99,212,123,230,89,224,122,332,118,302,135,287,122,332,135,287,135,326,135,326,135,287,151,272,135,326,151,272,148,318,148,318,151,272,166,304,148,318,166,304,195,343,195,343,166,304,212,328,107,337,90,340,93,318,107,337,93,318,105,311,107,337,105,311,118,302,107,337,118,302,122,332,50,329,66,326,71,342,71,342,66,326,80,323,71,342,80,323,90,340,90,340,80,323,93,318,187,69,179,44,182,13,182,13,179,44,167,25,182,13,167,2 [...]
+196,319,191,309,186,302,181,297,176,295,170,294,165,294,160,295,154,297,149,299,143,301,131,307,124,311,110,315,103,316,96,316,82,314,70,308,59,298,51,284,46,266,60,266,64,274,68,281,73,285,79,288,85,289,89,289,97,287,102,285,106,283,118,278,128,273,137,269,144,267,151,266,158,266,173,268,185,274,195,284,203,299,210,319,16383,16383,243,0,243,7,230,9,221,13,216,19,213,29,212,42,212,153,210,180,202,201,190,217,174,227,153,230,139,229,125,224,111,216,96,205,81,190,80,190,80,228,76,230,50,22 [...]
+37,21,31,14,114,0,114,0,31,14,22,9,114,0,22,9,9,7,13,200,16,201,23,212,23,212,16,201,19,201,23,212,19,201,22,201,22,201,30,200,23,212,23,212,30,200,37,216,23,212,8,208,10,200,23,212,10,200,13,200,30,200,35,197,37,216,37,216,35,197,38,191,37,216,38,191,50,220,50,220,38,191,40,181,50,220,40,181,40,169,83,26,40,169,40,47,83,26,40,47,86,18,86,18,40,47,92,13,80,228,76,230,80,190,80,190,76,230,82,36,80,190,82,36,81,190,81,190,82,36,82,174,81,190,82,174,96,205,96,205,82,174,95,186,96,205,95,186 [...]
+166,253,94,328,89,332,84,335,80,337,72,339,66,338,61,336,57,333,55,329,54,323,55,318,57,314,60,309,64,305,69,301,146,253,16383,16383,235,116,230,154,215,186,191,210,162,225,127,230,90,225,58,209,35,185,20,153,15,114,20,75,35,42,58,17,88,1,123,-4,160,1,191,17,215,43,230,76,235,116,16383,16383,190,102,187,70,180,44,168,25,151,13,131,9,120,10,110,13,101,18,93,25,86,34,76,51,69,70,64,91,61,113,60,137,62,164,70,186,82,202,98,212,118,216,130,215,140,211,149,206,158,199,165,191,174,177,181,161, [...]
+146,253,166,253,94,328,146,253,94,328,89,332,146,253,89,332,84,335,146,253,84,335,80,337,146,253,80,337,76,338,146,253,76,338,72,339,146,253,72,339,69,301,54,323,55,318,55,329,55,329,55,318,57,314,55,329,57,314,57,333,57,333,57,314,60,309,57,333,60,309,61,336,61,336,60,309,64,305,61,336,64,305,66,338,66,338,64,305,69,301,66,338,69,301,72,339,64,91,58,17,69,70,69,70,58,17,88,1,69,70,88,1,76,51,76,51,88,1,86,34,93,25,86,34,88,1,93,25,88,1,123,-4,162,225,127,230,130,215,130,215,127,230,118, [...]
+77,253,97,253,174,302,180,306,184,310,187,314,189,318,189,323,188,329,186,333,182,336,177,338,171,339,163,337,160,335,156,332,151,328,16383,16383,235,116,230,154,215,186,191,210,162,225,127,230,90,225,58,209,35,185,20,153,15,114,20,75,35,42,58,17,88,1,123,-4,160,1,191,17,215,43,230,76,235,116,16383,16383,190,102,187,70,180,44,168,25,151,13,131,9,120,10,110,13,101,18,93,25,86,34,76,51,69,70,64,91,61,113,60,137,62,164,70,186,82,202,98,212,118,216,130,215,140,211,149,206,158,199,165,191,174 [...]
+171,339,174,302,177,338,177,338,174,302,180,306,177,338,180,306,182,336,182,336,180,306,184,310,182,336,184,310,186,333,186,333,184,310,187,314,186,333,187,314,188,329,188,329,187,314,189,318,188,329,189,318,189,323,174,302,171,339,167,338,174,302,167,338,163,337,174,302,163,337,160,335,174,302,160,335,156,332,174,302,156,332,151,328,174,302,151,328,97,253,64,91,58,17,69,70,69,70,58,17,88,1,69,70,88,1,76,51,76,51,88,1,86,34,93,25,86,34,88,1,93,25,88,1,123,-4,162,225,127,230,130,215,130,2 [...]
+200,253,138,337,107,337,45,253,62,253,123,305,184,253,16383,16383,235,116,230,154,215,186,191,210,162,225,127,230,90,225,58,209,35,185,20,153,15,114,20,75,35,42,58,17,88,1,123,-4,160,1,191,17,215,43,230,76,235,116,16383,16383,190,102,187,70,180,44,168,25,151,13,131,9,120,10,110,13,101,18,93,25,86,34,76,51,69,70,64,91,61,113,60,137,62,164,70,186,82,202,98,212,118,216,130,215,140,211,149,206,158,199,165,191,174,177,181,161,186,142,189,122,190,102,
+45,253,62,253,107,337,107,337,62,253,123,305,107,337,123,305,138,337,138,337,123,305,184,253,138,337,184,253,200,253,64,91,58,17,69,70,69,70,58,17,88,1,69,70,88,1,76,51,76,51,88,1,86,34,93,25,86,34,88,1,93,25,88,1,123,-4,162,225,127,230,130,215,130,215,127,230,118,216,98,212,118,216,127,230,98,212,127,230,90,225,187,70,180,44,191,17,191,17,180,44,168,25,191,17,168,25,160,1,160,1,168,25,151,13,160,1,151,13,131,9,131,9,120,10,123,-4,123,-4,120,10,110,13,123,-4,110,13,101,18,140,211,149,206 [...]
+190,319,185,309,181,302,176,297,170,295,164,294,159,294,154,295,149,297,137,301,126,307,118,311,104,315,97,316,90,316,76,314,64,308,54,298,46,284,40,266,55,266,58,274,63,281,68,285,73,288,80,289,84,289,92,287,100,283,112,278,123,273,131,269,139,267,145,266,152,266,168,268,180,274,190,284,198,299,205,319,16383,16383,235,116,230,154,215,186,191,210,162,225,127,230,90,225,58,209,35,185,20,153,15,114,20,75,35,42,58,17,88,1,123,-4,160,1,191,17,215,43,230,76,235,116,16383,16383,190,102,187,70, [...]
+58,274,63,281,64,308,64,308,63,281,68,285,64,308,68,285,76,314,76,314,68,285,73,288,76,314,73,288,80,289,80,289,84,289,90,316,90,316,84,289,88,288,90,316,88,288,92,287,55,266,58,274,64,308,55,266,64,308,54,298,55,266,54,298,46,284,55,266,46,284,40,266,90,316,92,287,97,316,97,316,92,287,96,285,97,316,96,285,100,283,100,283,112,278,104,315,104,315,112,278,111,313,90,316,76,314,80,289,104,315,97,316,100,283,111,313,112,278,118,311,118,311,112,278,123,273,118,311,123,273,126,307,126,307,123, [...]
+197,286,196,294,192,301,186,306,180,310,172,311,164,310,157,306,152,301,149,294,147,286,149,278,152,272,157,266,164,263,171,262,179,263,186,266,192,272,196,278,197,286,16383,16383,98,286,96,294,93,301,87,306,80,310,73,311,65,310,58,306,53,301,49,294,48,286,49,278,53,272,58,266,64,263,72,262,80,263,87,266,93,272,96,278,98,286,16383,16383,235,116,230,154,215,186,191,210,162,225,127,230,90,225,58,209,35,185,20,153,15,114,20,75,35,42,58,17,88,1,123,-4,160,1,191,17,215,43,230,76,235,116,16383 [...]
+48,286,49,278,49,294,49,294,49,278,53,272,49,294,53,272,53,301,53,301,53,272,58,266,53,301,58,266,58,306,58,306,58,266,64,263,58,306,64,263,65,310,65,310,64,263,72,262,65,310,72,262,73,311,73,311,72,262,80,263,73,311,80,263,80,310,80,310,80,263,87,266,80,310,87,266,87,306,87,306,87,266,93,272,87,306,93,272,93,301,93,301,93,272,96,278,93,301,96,278,96,294,96,294,96,278,98,286,64,91,58,17,69,70,69,70,58,17,88,1,69,70,88,1,76,51,76,51,88,1,86,34,93,25,86,34,88,1,93,25,88,1,123,-4,162,225,12 [...]
+169,229,168,238,164,246,158,252,150,256,142,258,133,256,125,252,119,246,115,239,113,230,115,221,119,214,125,208,132,204,141,203,150,204,158,208,164,214,168,221,169,229,16383,16383,267,110,267,143,15,143,15,110,16383,16383,169,22,168,31,164,38,158,45,150,49,142,50,133,49,125,45,119,39,115,31,113,22,115,14,119,6,125,0,132,-3,141,-4,150,-3,158,0,164,6,168,13,169,22,
+113,230,115,221,115,239,115,239,115,221,119,214,115,239,119,214,119,246,119,246,119,214,125,208,119,246,125,208,125,252,125,252,125,208,132,204,125,252,132,204,133,256,133,256,132,204,141,203,133,256,141,203,142,258,142,258,141,203,150,204,142,258,150,204,150,256,150,256,150,204,158,208,150,256,158,208,158,252,158,252,158,208,164,214,158,252,164,214,164,246,164,246,164,214,168,221,164,246,168,221,168,238,168,238,168,221,169,229,15,143,15,110,267,110,15,143,267,110,267,143,113,22,115,14,1 [...]
+219,276,199,276,171,221,161,224,152,227,143,229,134,230,124,230,88,224,58,208,35,184,20,152,15,113,15,100,17,87,20,74,30,50,35,42,40,36,46,29,53,22,63,14,26,-55,45,-55,77,6,87,1,105,-3,114,-4,123,-4,159,1,190,18,214,44,229,78,235,117,233,141,227,162,218,181,204,198,186,213,16383,16383,79,46,72,63,66,81,63,99,60,118,60,138,62,164,70,186,82,202,99,212,118,216,127,215,135,213,143,210,151,205,158,198,16383,16383,170,183,178,167,183,152,187,136,189,120,190,102,187,69,180,44,168,25,151,13,131, [...]
+63,14,63,14,45,-55,63,14,45,-55,77,6,63,14,77,6,63,99,63,14,63,99,60,118,63,14,60,118,60,138,63,14,60,138,58,208,63,14,58,208,53,22,58,208,35,184,35,42,58,208,35,42,40,36,58,208,40,36,46,29,58,208,46,29,53,22,35,184,20,152,20,74,35,184,20,74,25,62,35,184,25,62,30,50,35,184,30,50,35,42,20,152,15,113,15,100,20,152,15,100,17,87,20,152,17,87,20,74,124,230,118,216,127,215,124,230,127,215,134,230,134,230,127,215,135,213,134,230,135,213,143,229,143,229,135,213,143,210,143,229,143,210,152,227,15 [...]
+170,253,97,328,92,332,88,335,84,337,80,338,75,339,69,338,64,336,61,333,58,329,57,323,58,318,60,314,63,309,67,305,73,301,150,253,16383,16383,240,25,237,25,225,26,217,29,212,34,209,42,209,225,129,225,129,217,145,215,155,212,162,206,165,197,166,184,166,59,164,53,162,48,159,43,147,34,139,29,130,26,121,25,113,24,102,26,92,31,84,40,79,51,78,64,78,225,4,225,4,218,17,216,26,213,32,207,35,197,36,185,36,59,38,38,46,20,58,6,75,-1,97,-4,109,-3,123,0,138,8,153,21,168,38,169,38,169,-2,171,-3,186,1,199 [...]
+150,253,170,253,97,328,150,253,97,328,92,332,150,253,92,332,88,335,150,253,88,335,84,337,150,253,84,337,80,338,150,253,80,338,75,339,150,253,75,339,73,301,57,323,58,318,58,329,58,329,58,318,60,314,58,329,60,314,61,333,61,333,60,314,63,309,61,333,63,309,64,336,64,336,63,309,67,305,64,336,67,305,69,338,69,338,67,305,73,301,69,338,73,301,75,339,78,225,4,225,17,216,78,225,17,216,26,213,78,225,26,213,32,207,78,225,32,207,35,197,78,225,35,197,36,185,78,225,36,185,38,38,78,225,38,38,46,20,78,22 [...]
+78,253,98,253,175,302,181,306,185,310,188,314,189,318,190,323,189,329,187,333,183,336,179,338,172,339,168,338,165,337,161,335,156,332,151,328,16383,16383,240,25,237,25,225,26,217,29,212,34,209,42,209,225,129,225,129,217,145,215,155,212,162,206,165,197,166,184,166,59,164,53,162,48,159,43,147,34,139,29,130,26,121,25,113,24,102,26,92,31,84,40,79,51,78,64,78,225,4,225,4,218,17,216,26,213,32,207,35,197,36,185,36,59,38,38,46,20,58,6,75,-1,97,-4,109,-3,123,0,138,8,153,21,168,38,169,38,169,-2,17 [...]
+209,225,129,225,145,215,209,225,145,215,155,212,209,225,155,212,162,206,209,225,162,206,165,197,209,225,165,197,166,184,209,225,166,184,168,38,209,225,168,38,169,38,209,225,169,38,171,-3,209,225,171,-3,186,1,209,225,186,1,199,6,209,225,199,6,209,54,166,184,166,69,168,38,237,25,225,26,225,14,237,25,225,14,240,18,237,25,240,18,240,25,209,54,199,6,209,42,209,42,199,6,212,10,209,42,212,10,212,34,212,34,212,10,225,14,212,34,225,14,217,29,217,29,225,14,225,26,172,339,175,302,179,338,179,338,17 [...]
+200,253,138,337,107,337,45,253,62,253,123,305,184,253,16383,16383,240,25,237,25,225,26,217,29,212,34,209,42,209,225,129,225,129,217,145,215,155,212,162,206,165,197,166,184,166,59,164,53,162,48,159,43,147,34,139,29,130,26,121,25,113,24,102,26,92,31,84,40,79,51,78,64,78,225,4,225,4,218,17,216,26,213,32,207,35,197,36,185,36,59,38,38,46,20,58,6,75,-1,97,-4,109,-3,123,0,138,8,153,21,168,38,169,38,169,-2,171,-3,186,1,199,6,225,14,240,18,
+209,225,129,225,145,215,209,225,145,215,155,212,209,225,155,212,162,206,209,225,162,206,165,197,209,225,165,197,166,184,209,225,166,184,168,38,209,225,168,38,169,38,209,225,169,38,171,-3,209,225,171,-3,186,1,209,225,186,1,199,6,209,225,199,6,209,54,166,184,166,69,168,38,237,25,225,26,225,14,237,25,225,14,240,18,237,25,240,18,240,25,209,54,199,6,209,42,209,42,199,6,212,10,209,42,212,10,212,34,212,34,212,10,225,14,212,34,225,14,217,29,217,29,225,14,225,26,45,253,62,253,107,337,107,337,62,2 [...]
+196,286,195,294,192,301,186,306,179,310,171,311,164,310,157,306,152,301,148,294,147,286,148,278,151,272,157,266,163,263,171,262,179,263,186,266,192,272,195,278,196,286,16383,16383,97,286,96,294,92,301,87,306,80,310,72,311,64,310,58,306,52,301,49,294,47,286,49,278,52,272,57,266,64,263,71,262,79,263,86,266,92,272,96,278,97,286,16383,16383,240,25,237,25,225,26,217,29,212,34,209,42,209,225,129,225,129,217,145,215,155,212,162,206,165,197,166,184,166,59,164,53,162,48,159,43,147,34,139,29,130,2 [...]
+209,225,129,225,145,215,209,225,145,215,155,212,209,225,155,212,162,206,209,225,162,206,165,197,209,225,165,197,166,184,209,225,166,184,168,38,209,225,168,38,169,38,209,225,169,38,171,-3,209,225,171,-3,186,1,209,225,186,1,199,6,209,225,199,6,209,54,166,184,166,69,168,38,237,25,225,26,225,14,237,25,225,14,240,18,237,25,240,18,240,25,209,54,199,6,209,42,209,42,199,6,212,10,209,42,212,10,212,34,212,34,212,10,225,14,212,34,225,14,217,29,217,29,225,14,225,26,147,286,148,278,148,294,148,294,14 [...]
+71,253,92,253,169,302,174,306,178,310,181,314,183,318,184,323,183,329,181,333,177,336,172,338,166,339,158,337,154,335,150,332,145,328,16383,16383,238,225,171,225,171,218,179,217,186,216,190,213,193,210,194,205,194,202,193,201,193,198,192,196,143,59,88,184,82,196,81,201,81,204,82,209,85,212,90,215,98,217,109,218,109,225,7,225,7,218,14,217,21,214,26,211,30,206,33,200,99,60,105,47,111,35,116,24,121,9,119,2,116,-8,112,-21,106,-34,100,-44,96,-51,85,-62,80,-65,75,-66,71,-66,69,-65,66,-64,62,-6 [...]
+166,339,169,302,172,338,172,338,169,302,174,306,172,338,174,306,177,336,177,336,174,306,178,310,177,336,178,310,181,333,181,333,178,310,181,314,181,333,181,314,183,329,183,329,181,314,183,318,183,329,183,318,184,323,169,302,166,339,162,338,169,302,162,338,158,337,169,302,158,337,154,335,169,302,154,335,150,332,169,302,150,332,145,328,169,302,145,328,92,253,90,-57,85,-62,90,-94,90,-94,85,-62,80,-65,90,-94,80,-65,75,-66,75,-66,73,-66,90,-94,90,-94,73,-66,71,-105,90,-57,106,-76,96,-51,96,-5 [...]
+79,339,76,342,63,337,51,333,38,329,23,325,4,320,4,311,8,311,9,312,13,312,23,311,30,308,35,303,37,295,37,-76,34,-86,27,-92,17,-96,2,-98,2,-107,123,-107,123,-98,104,-97,91,-93,84,-87,80,-75,79,-59,79,17,90,8,99,2,108,-1,118,-3,130,-4,164,1,193,19,215,47,230,82,235,123,231,160,221,190,204,212,180,225,151,230,135,229,120,224,106,216,92,205,79,190,16383,16383,79,166,83,175,91,184,103,192,117,198,131,200,152,196,170,185,182,166,189,140,192,107,189,75,181,49,169,29,152,16,131,11,117,13,103,19,9 [...]
+34,-86,27,-92,123,-107,123,-107,27,-92,17,-96,123,-107,17,-96,2,-98,8,311,9,312,23,325,23,325,9,312,11,312,23,325,11,312,13,312,13,312,23,311,23,325,23,325,23,311,38,329,23,325,4,320,6,311,23,325,6,311,8,311,30,308,35,303,38,329,38,329,35,303,37,295,38,329,37,295,37,284,80,-75,37,284,37,-63,80,-75,37,-63,84,-87,84,-87,37,-63,91,-93,79,190,79,339,76,342,79,190,76,342,79,-59,79,190,79,-59,79,166,79,190,79,166,92,205,235,123,231,160,230,82,230,82,231,160,221,190,230,82,221,190,215,47,215,47 [...]
+198,286,197,294,193,301,188,306,181,310,173,311,165,310,159,306,153,301,150,294,148,286,150,278,153,272,158,266,165,263,172,262,180,263,187,266,193,272,197,278,198,286,16383,16383,99,286,97,294,94,301,88,306,81,310,74,311,66,310,59,306,54,301,50,294,49,286,50,278,54,272,59,266,65,263,73,262,81,263,88,266,94,272,97,278,99,286,16383,16383,238,225,171,225,171,218,179,217,186,216,190,213,193,210,194,205,194,202,193,201,193,198,192,196,143,59,88,184,82,196,81,201,81,204,82,209,85,212,90,215,9 [...]
+148,286,150,278,150,294,150,294,150,278,153,272,150,294,153,272,153,301,153,301,153,272,158,266,153,301,158,266,159,306,159,306,158,266,165,263,159,306,165,263,165,310,165,310,165,263,172,262,165,310,172,262,173,311,173,311,172,262,180,263,173,311,180,263,181,310,181,310,180,263,187,266,181,310,187,266,188,306,188,306,187,266,193,272,188,306,193,272,193,301,193,301,193,272,197,278,193,301,197,278,197,294,197,294,197,278,198,286,49,286,50,278,50,294,50,294,50,278,54,272,50,294,54,272,54,3 [...]
+166,253,94,328,89,332,85,335,81,337,73,339,66,338,61,336,58,333,55,329,55,318,57,314,60,309,70,301,147,253,
+147,253,166,253,94,328,147,253,94,328,89,332,147,253,89,332,85,335,147,253,85,335,81,337,147,253,81,337,77,338,147,253,77,338,73,339,147,253,73,339,70,301,55,323,55,318,55,329,55,329,55,318,57,314,55,329,57,314,58,333,58,333,57,314,60,309,58,333,60,309,61,336,61,336,60,309,65,305,61,336,65,305,66,338,66,338,65,305,70,301,66,338,70,301,73,339,
+55,253,75,253,151,301,157,305,161,309,164,314,166,318,166,329,163,333,160,336,155,338,148,339,140,337,136,335,132,332,127,328,
+148,339,151,301,155,338,155,338,151,301,157,305,155,338,157,305,160,336,160,336,157,305,161,309,160,336,161,309,163,333,163,333,161,309,164,314,163,333,164,314,166,329,166,329,164,314,166,318,166,329,166,318,166,323,151,301,148,339,144,338,151,301,144,338,140,337,151,301,140,337,136,335,151,301,136,335,132,332,151,301,132,332,127,328,151,301,127,328,75,253,127,328,55,253,75,253,
+203,253,140,337,109,337,47,253,64,253,124,305,185,253,
+47,253,64,253,109,337,109,337,64,253,124,305,109,337,124,305,140,337,140,337,124,305,185,253,140,337,185,253,203,253,
+193,319,188,309,183,302,178,297,173,294,161,294,155,295,148,298,139,302,128,307,121,311,107,315,100,316,93,316,79,314,67,308,56,298,48,284,42,266,57,266,61,274,65,281,70,285,76,288,83,289,88,289,92,288,98,286,105,282,114,278,125,273,134,269,141,267,148,266,155,266,170,268,182,274,192,284,201,299,208,319,
+61,274,65,281,67,308,67,308,65,281,70,285,67,308,70,285,79,314,79,314,70,285,76,288,79,314,76,288,83,289,83,289,88,289,93,316,93,316,88,289,92,288,93,316,92,288,98,286,57,266,61,274,67,308,57,266,67,308,56,298,57,266,56,298,48,284,57,266,48,284,42,266,155,266,170,268,161,294,161,294,170,268,166,294,173,294,166,294,170,268,173,294,170,268,182,274,193,319,188,309,192,284,193,319,192,284,201,299,193,319,201,299,208,319,183,302,178,297,182,274,183,302,182,274,192,284,183,302,192,284,188,309, [...]
+203,273,203,300,47,300,47,273,
+203,273,203,300,47,300,203,273,47,300,47,273,
+250,385,250,410,0,410,0,385,
+250,385,250,410,0,410,250,385,0,410,0,385,
+180,332,171,313,162,300,151,290,139,285,124,283,107,285,93,291,82,301,73,315,68,332,54,332,56,305,64,283,78,267,98,257,123,253,145,256,164,266,178,281,188,303,194,332,
+107,285,93,291,98,257,98,257,93,291,82,301,98,257,82,301,78,267,78,267,82,301,73,315,78,267,73,315,68,332,171,313,162,300,164,266,164,266,162,300,151,290,164,266,151,290,145,256,145,256,151,290,139,285,145,256,139,285,124,283,124,283,107,285,123,253,123,253,107,285,98,257,68,332,54,332,56,305,68,332,56,305,64,283,68,332,64,283,78,267,180,332,171,313,178,281,180,332,178,281,188,303,180,332,188,303,194,332,124,283,123,253,145,256,171,313,164,266,178,281,
+150,286,148,294,145,301,140,306,133,310,124,311,116,310,109,306,104,301,101,294,100,286,101,278,105,272,110,266,117,263,124,262,132,263,139,266,145,271,148,278,150,286,
+124,262,132,263,133,310,133,310,132,263,139,266,133,310,139,266,140,306,140,306,139,266,145,271,140,306,145,271,145,301,145,301,145,271,148,278,145,301,148,278,148,294,148,294,148,278,150,286,101,294,101,278,104,301,104,301,101,278,105,272,104,301,105,272,109,306,109,306,105,272,110,266,109,306,110,266,116,310,116,310,110,266,117,263,116,310,117,263,124,311,124,311,117,263,124,262,124,311,124,262,133,310,101,278,101,294,100,286,
+200,286,198,294,195,301,189,306,182,310,175,311,167,310,160,306,155,301,151,294,150,286,151,278,155,272,160,266,166,263,174,262,182,263,189,266,195,272,198,278,200,286,16383,16383,100,286,99,294,95,301,90,306,83,310,75,311,67,310,60,306,55,301,51,294,50,286,51,278,55,272,60,266,67,263,75,262,83,263,90,266,95,272,99,278,100,286,
+75,311,75,262,83,310,83,310,75,262,83,263,83,310,83,263,90,306,90,306,83,263,90,266,90,306,90,266,95,301,95,301,90,266,95,272,95,301,95,272,99,294,99,294,95,272,99,278,99,294,99,278,100,286,50,286,51,278,51,294,51,294,51,278,55,272,51,294,55,272,55,301,55,301,55,272,60,266,55,301,60,266,60,306,60,306,60,266,67,263,60,306,67,263,67,310,67,310,67,263,75,262,67,310,75,262,75,311,150,286,151,278,151,294,151,294,151,278,155,272,151,294,155,272,155,301,155,301,155,272,160,266,155,301,160,266,1 [...]
+109,291,109,246,126,246,127,263,131,263,147,266,160,274,171,287,178,303,181,321,179,337,175,352,165,364,150,373,129,376,122,375,116,374,109,372,104,370,99,367,94,363,91,359,88,354,86,346,87,342,89,338,92,335,96,333,100,332,109,335,113,343,116,353,121,361,131,364,139,362,146,356,150,347,153,336,153,325,152,314,146,304,138,297,128,292,116,291,
+131,364,129,376,122,375,131,364,122,375,121,361,131,364,150,373,129,376,121,361,122,375,116,353,116,353,122,375,116,374,116,353,116,374,113,343,113,343,116,374,109,372,113,343,109,372,109,335,109,335,109,372,104,370,109,335,104,370,100,332,100,332,104,370,99,367,100,332,99,367,96,333,96,333,99,367,94,363,96,333,94,363,92,335,92,335,94,363,91,359,92,335,91,359,89,338,89,338,91,359,88,354,89,338,88,354,87,342,87,342,88,354,87,350,87,342,87,350,86,346,181,321,179,337,178,303,178,303,179,337 [...]
+175,305,173,321,165,335,155,346,141,353,126,355,110,353,96,346,85,335,78,322,75,306,78,290,85,276,95,266,109,259,124,256,140,259,154,266,165,276,173,290,175,305,16383,16383,158,306,156,295,152,286,144,279,135,275,124,273,114,275,106,279,99,286,94,295,93,306,94,316,99,325,106,332,115,337,124,339,135,337,144,332,151,325,156,316,158,306,
+156,295,152,286,154,266,154,266,152,286,144,279,154,266,144,279,140,259,140,259,144,279,135,275,140,259,135,275,124,256,124,256,135,275,124,273,126,355,124,339,135,337,126,355,135,337,141,353,141,353,135,337,144,332,141,353,144,332,155,346,155,346,144,332,151,325,155,346,151,325,156,316,175,305,173,321,173,290,173,290,173,321,165,335,173,290,165,335,165,276,165,276,165,335,158,306,156,316,158,306,165,335,156,316,165,335,155,346,156,295,154,266,165,276,156,295,165,276,158,306,99,325,106,3 [...]
+118,253,137,253,214,301,220,305,224,310,227,314,229,324,228,329,226,333,222,336,218,338,212,339,208,339,204,338,200,336,196,333,190,328,16383,16383,40,253,60,253,137,301,142,305,146,310,149,314,151,319,151,324,150,329,148,333,144,336,140,338,134,339,130,339,126,338,123,336,118,333,113,328,
+212,339,214,301,218,338,218,338,214,301,220,305,218,338,220,305,222,336,222,336,220,305,224,310,222,336,224,310,226,333,226,333,224,310,227,314,226,333,227,314,228,329,228,329,227,314,228,319,228,329,228,319,229,324,214,301,212,339,208,339,214,301,208,339,204,338,214,301,204,338,200,336,214,301,200,336,196,333,214,301,196,333,190,328,214,301,190,328,137,253,134,339,137,301,140,338,140,338,137,301,142,305,140,338,142,305,144,336,144,336,142,305,146,310,144,336,146,310,148,333,148,333,146, [...]
+203,337,185,337,125,286,65,337,47,337,109,253,141,253,
+203,337,185,337,141,253,141,253,185,337,125,286,141,253,125,286,109,253,109,253,125,286,65,337,109,253,65,337,47,337,
+142,250,142,350,115,350,115,250,
+142,250,142,350,115,350,142,250,115,350,115,250,
+174,250,174,350,146,350,146,250,16383,16383,104,250,104,350,77,350,77,250,
+146,350,146,250,174,250,146,350,174,250,174,350,77,350,77,250,104,250,77,350,104,250,104,350,
+229,253,156,328,151,333,146,336,142,338,138,339,134,339,129,338,124,336,121,333,119,329,118,324,118,319,120,314,123,310,127,305,132,301,209,253,16383,16383,151,253,78,328,73,333,68,336,64,338,60,339,56,339,51,338,46,336,43,333,40,329,40,319,42,314,44,310,49,305,54,301,131,253,
+209,253,229,253,156,328,209,253,156,328,151,333,209,253,151,333,146,336,209,253,146,336,142,338,209,253,142,338,138,339,209,253,138,339,134,339,209,253,134,339,132,301,118,324,118,319,119,329,119,329,118,319,120,314,119,329,120,314,121,333,121,333,120,314,123,310,121,333,123,310,124,336,124,336,123,310,127,305,124,336,127,305,129,338,129,338,127,305,132,301,129,338,132,301,134,339,131,253,151,253,78,328,131,253,78,328,73,333,131,253,73,333,68,336,131,253,68,336,64,338,131,253,64,338,60,3 [...]
+353,0,353,9,340,12,330,17,321,26,314,38,306,55,184,337,174,337,70,93,55,58,44,34,33,20,22,13,7,9,7,0,107,0,107,9,94,10,84,12,77,16,73,22,72,30,72,34,73,38,74,43,76,51,99,108,230,108,251,61,257,45,259,38,260,31,261,26,260,22,258,18,256,15,252,13,248,12,226,9,226,0,16383,16383,224,128,108,128,166,266,
+55,58,73,22,72,30,72,30,72,34,70,93,70,93,72,34,73,38,70,93,73,38,74,43,174,337,76,51,99,108,174,337,99,108,108,128,108,128,99,108,230,108,108,128,230,108,224,128,224,128,230,108,306,55,224,128,306,55,184,337,258,18,256,15,353,0,353,0,256,15,252,13,353,0,252,13,248,12,261,26,353,0,330,17,261,26,330,17,321,26,261,26,321,26,314,38,261,26,314,38,306,55,261,26,306,55,260,31,306,55,230,108,251,61,306,55,251,61,254,53,306,55,254,53,257,45,306,55,257,45,259,38,306,55,259,38,260,31,174,337,108,1 [...]
+211,175,235,181,254,191,268,205,277,224,280,248,274,277,258,300,232,317,195,327,148,331,8,331,8,321,29,320,43,316,51,308,55,295,56,275,56,56,55,37,51,24,42,16,29,11,8,9,8,0,177,0,217,4,250,15,275,34,291,58,296,89,292,116,281,138,263,155,239,167,211,174,16383,16383,108,183,108,303,109,307,112,310,115,312,119,313,162,310,192,302,213,289,225,270,228,245,225,223,214,205,197,193,172,186,139,183,16383,16383,108,163,140,163,171,161,198,155,220,142,234,121,239,89,234,59,220,39,198,26,170,20,138, [...]
+51,24,42,16,177,0,177,0,42,16,29,11,177,0,29,11,8,9,55,295,56,275,112,310,55,295,112,310,148,331,148,331,112,310,115,312,148,331,115,312,119,313,119,313,162,310,148,331,148,331,162,310,195,327,239,89,234,59,250,15,250,15,234,59,220,39,250,15,220,39,217,4,217,4,220,39,198,26,217,4,198,26,177,0,177,0,198,26,170,20,177,0,170,20,138,18,138,18,126,19,177,0,177,0,126,19,118,21,177,0,118,21,55,37,55,37,118,21,56,56,213,289,225,270,232,317,232,317,225,270,228,245,235,181,228,245,225,223,195,327, [...]
+289,247,286,331,6,331,6,321,25,319,38,315,45,307,49,294,50,276,50,62,49,40,45,25,37,16,25,12,6,9,6,0,146,0,146,9,126,11,113,16,105,24,101,37,100,56,100,292,101,300,103,306,106,310,111,311,118,312,206,312,232,310,251,303,264,291,272,273,276,247,
+38,315,45,307,286,331,286,331,45,307,111,311,286,331,111,311,118,312,286,331,118,312,206,312,286,331,206,312,232,310,286,331,232,310,251,303,286,331,251,303,264,291,286,331,264,291,272,273,286,331,272,273,276,247,286,331,276,247,289,247,100,56,100,292,50,276,50,276,100,292,101,300,50,276,101,300,103,306,50,276,103,306,106,310,50,276,106,310,49,294,50,276,101,37,100,56,111,311,45,307,49,294,111,311,49,294,106,310,25,319,38,315,286,331,25,319,286,331,6,331,25,319,6,331,6,321,146,0,146,9,12 [...]
+338,0,184,337,174,337,24,0,16383,16383,262,46,68,46,166,266,
+174,337,24,0,68,46,68,46,24,0,338,0,68,46,338,0,262,46,262,46,338,0,184,337,262,46,184,337,174,337,174,337,68,46,166,266,174,337,166,266,262,46,
+299,84,285,84,271,57,254,38,230,26,197,20,151,18,132,19,117,21,108,25,102,31,100,42,100,164,176,164,198,162,213,158,222,150,229,136,233,115,244,115,244,232,233,232,229,212,222,198,213,190,198,185,176,184,100,184,100,294,101,302,103,307,106,310,111,312,118,312,179,311,219,306,243,297,255,282,261,259,273,259,271,331,6,331,6,321,25,320,38,315,45,307,49,294,50,275,50,57,49,37,45,24,38,16,25,12,6,9,6,0,276,0,
+45,24,38,16,276,0,276,0,38,16,25,12,276,0,25,12,6,9,38,315,45,307,271,331,271,331,45,307,111,312,271,331,111,312,118,312,118,312,179,311,271,331,271,331,179,311,219,306,271,331,219,306,243,297,271,331,243,297,255,282,271,331,255,282,261,259,271,331,261,259,273,259,45,24,117,21,49,37,49,37,117,21,108,25,49,37,108,25,50,57,50,57,108,25,102,31,50,57,102,31,50,275,50,275,102,31,100,42,50,275,100,42,100,294,100,184,100,164,176,164,100,184,176,164,176,184,198,185,176,184,198,162,198,185,198,16 [...]
+299,88,287,88,282,72,278,59,273,49,266,40,257,33,249,28,240,24,228,21,215,20,199,19,73,19,289,324,289,331,26,331,16,246,29,246,32,260,35,271,38,279,43,287,50,295,58,301,68,306,81,309,97,311,117,312,224,312,5,7,5,0,286,0,
+35,271,38,279,26,331,26,331,38,279,43,287,26,331,43,287,50,295,50,295,58,301,26,331,26,331,58,301,68,306,26,331,68,306,81,309,73,19,289,324,224,312,224,312,289,324,289,331,224,312,289,331,117,312,97,311,117,312,289,331,97,311,289,331,26,331,26,331,16,246,29,246,26,331,29,246,32,260,26,331,32,260,35,271,224,312,5,7,73,19,73,19,5,7,286,0,73,19,286,0,199,19,199,19,286,0,215,20,278,59,273,49,286,0,286,0,273,49,266,40,286,0,266,40,257,33,257,33,249,28,286,0,286,0,249,28,240,24,286,0,240,24,22 [...]
+352,0,352,9,333,12,320,17,312,25,308,37,307,55,307,274,308,293,312,307,320,315,333,319,352,321,352,331,211,331,211,321,231,319,244,315,251,307,255,294,256,274,256,180,104,180,104,274,106,294,110,307,118,315,130,319,149,321,149,331,9,331,9,321,28,319,41,315,49,307,53,294,54,274,54,61,53,39,49,25,42,16,29,12,9,9,9,0,148,0,148,9,129,12,117,17,109,25,105,38,104,56,104,157,256,157,256,62,255,41,252,26,244,17,232,12,212,9,212,0,
+49,25,42,16,148,0,148,0,42,16,29,12,148,0,29,12,9,9,149,331,9,331,28,319,149,331,28,319,41,315,149,331,41,315,49,307,149,331,49,307,53,294,149,331,53,294,118,315,149,331,118,315,130,319,149,331,130,319,149,321,54,274,105,38,104,56,104,180,104,157,256,157,104,180,256,157,256,180,256,180,256,157,312,25,256,180,312,25,308,37,54,274,104,56,104,274,54,274,104,274,106,294,54,274,106,294,110,307,54,274,110,307,118,315,54,274,118,315,53,294,252,26,244,17,352,0,352,0,244,17,232,12,352,0,232,12,21 [...]
+251,118,249,129,247,142,245,170,245,189,246,197,247,204,251,220,238,220,235,211,231,203,226,197,218,193,209,191,156,191,146,192,139,196,133,201,129,209,124,220,112,220,114,210,116,197,117,184,117,172,118,161,118,153,115,126,113,118,125,118,129,129,134,138,139,144,146,148,156,149,209,149,219,148,226,144,231,137,235,128,238,118,16383,16383,344,166,336,222,314,269,280,306,235,330,180,338,126,330,81,307,46,271,24,224,17,167,24,109,46,61,81,24,126,1,180,-6,234,1,279,24,314,60,336,108,344,166, [...]
+207,316,219,311,235,330,235,330,219,311,231,305,235,330,231,305,242,296,242,296,257,279,280,306,280,306,257,279,270,257,280,306,270,257,279,231,134,308,149,314,180,338,180,338,149,314,164,318,180,338,164,318,180,320,180,320,194,319,235,330,235,330,194,319,207,316,235,330,180,338,180,320,247,142,246,156,238,220,238,220,246,156,245,170,238,220,245,170,245,180,245,180,245,189,238,220,238,220,245,189,246,197,238,220,246,197,247,204,249,212,251,220,238,220,249,212,238,220,247,204,280,103,272, [...]
+157,0,157,9,137,11,122,16,114,24,109,37,108,56,108,276,109,295,113,308,122,316,136,320,157,321,157,331,9,331,9,321,30,320,44,316,53,308,57,295,57,56,56,36,52,23,44,15,30,11,9,9,9,0,
+52,23,44,15,157,0,157,0,44,15,30,11,157,0,30,11,9,9,157,331,9,331,30,320,157,331,30,320,44,316,157,331,44,316,53,308,157,331,53,308,57,295,157,331,57,295,122,316,157,331,122,316,136,320,157,331,136,320,157,321,122,16,114,24,57,56,57,56,114,24,109,37,57,56,109,37,57,276,57,276,109,37,108,56,57,276,108,56,108,276,57,276,108,276,109,295,57,276,109,295,113,308,57,276,113,308,122,316,57,276,122,316,57,295,157,0,157,9,137,11,157,0,137,11,122,16,157,0,122,16,56,36,157,0,56,36,52,23,157,0,9,9,9, [...]
+362,0,362,9,349,11,336,16,322,25,305,41,283,64,166,192,259,281,278,298,292,309,305,316,320,320,338,321,338,331,208,331,208,321,220,321,229,320,235,318,238,315,240,311,241,305,239,298,234,289,226,280,202,256,113,174,113,293,117,307,124,315,137,319,158,321,158,331,17,331,17,321,37,319,50,315,57,306,61,293,62,275,62,63,61,40,57,26,50,17,36,12,17,9,17,0,157,0,157,9,139,12,126,16,118,23,114,36,113,55,113,148,126,158,176,107,198,84,217,63,232,46,241,32,244,22,244,18,241,15,237,12,231,11,224,10 [...]
+158,321,158,321,137,319,137,319,158,321,158,331,137,319,158,331,124,315,124,315,158,331,61,293,124,315,61,293,62,275,114,36,62,275,62,63,114,36,62,63,118,23,118,23,62,63,126,16,62,275,114,36,113,55,113,174,113,148,126,158,113,174,126,158,202,256,202,256,126,158,166,192,202,256,166,192,259,281,62,275,113,55,113,274,62,275,113,274,113,293,62,275,113,293,117,307,62,275,117,307,124,315,158,331,17,331,37,319,158,331,37,319,50,315,158,331,50,315,57,306,158,331,57,306,61,293,234,289,226,280,259 [...]
+344,0,344,9,330,12,320,17,311,26,304,38,296,55,179,337,169,337,70,93,56,58,44,34,34,20,22,13,7,9,7,0,107,0,107,9,94,10,84,12,77,16,73,22,72,30,72,34,73,38,74,43,76,51,160,267,161,267,241,61,244,51,247,44,249,37,250,31,251,26,249,18,244,13,236,11,227,10,216,9,216,0,
+56,58,73,22,72,30,72,30,72,34,70,93,70,93,72,34,73,38,70,93,73,38,74,43,161,267,169,337,160,267,160,267,169,337,76,51,75,47,76,51,169,337,75,47,169,337,70,93,251,26,344,0,320,17,251,26,320,17,311,26,251,26,311,26,304,38,251,26,304,38,296,55,251,26,296,55,250,31,296,55,179,337,241,61,296,55,241,61,244,51,296,55,244,51,247,44,296,55,247,44,249,37,296,55,249,37,250,31,169,337,161,267,241,61,169,337,241,61,179,337,70,93,56,58,72,30,330,12,320,17,344,0,330,12,344,0,344,9,249,18,244,13,344,0,2 [...]
+432,0,432,9,413,12,401,17,393,25,389,38,388,56,388,275,389,294,393,307,401,316,413,320,431,321,431,331,332,331,222,80,106,331,7,331,7,321,28,319,42,315,50,307,54,294,55,275,55,75,54,47,49,29,41,18,27,12,6,9,6,0,123,0,123,9,103,12,90,18,82,29,78,48,76,75,76,275,203,0,209,0,337,286,337,61,336,40,333,26,325,17,312,12,292,9,292,0,
+49,29,41,18,123,0,123,0,41,18,27,12,123,0,27,12,6,9,333,26,325,17,432,0,432,0,325,17,312,12,432,0,312,12,292,9,413,320,431,321,431,331,413,320,431,331,401,316,401,316,431,331,337,286,401,316,337,286,393,307,393,307,337,286,389,294,401,17,393,25,337,61,337,61,393,25,389,38,337,61,389,38,337,286,337,286,389,38,388,56,337,286,388,56,388,275,203,0,209,0,222,80,222,80,209,0,337,286,222,80,337,286,332,331,332,331,337,286,431,331,106,331,7,331,28,319,106,331,28,319,42,315,106,331,42,315,50,307, [...]
+353,331,235,331,235,321,247,320,256,319,263,317,275,309,278,303,281,295,283,285,284,274,284,89,91,331,6,331,6,321,19,321,29,318,37,313,46,306,55,295,55,75,54,48,49,30,41,19,27,13,6,9,6,0,123,0,123,9,103,13,90,20,82,31,78,49,76,75,76,269,297,-5,306,-5,306,274,308,289,311,299,315,307,320,313,324,315,329,318,335,319,343,320,353,321,
+49,30,41,19,123,0,123,0,41,19,27,13,123,0,27,13,6,9,256,319,263,317,353,331,353,331,263,317,269,313,353,331,269,313,275,309,275,309,278,303,353,331,353,331,278,303,281,295,353,331,281,295,324,315,324,315,281,295,320,313,324,315,320,313,320,312,320,312,320,313,315,307,315,307,320,313,284,274,315,307,284,274,284,259,297,-5,284,259,284,89,297,-5,284,89,91,331,353,331,324,315,329,318,353,331,329,318,335,319,353,331,335,319,343,320,353,331,343,320,353,321,306,-5,306,253,297,-5,297,-5,306,253, [...]
+295,247,295,331,26,331,26,246,39,246,43,263,48,276,55,284,66,289,79,290,242,290,256,289,266,284,274,276,279,263,282,247,16383,16383,252,109,252,225,240,225,239,211,235,200,229,193,219,189,207,188,114,188,102,189,93,193,87,200,83,211,81,225,70,225,70,109,81,109,84,122,87,132,93,140,101,146,113,147,205,147,218,146,227,141,234,133,239,123,240,109,16383,16383,307,0,307,85,295,85,293,70,287,57,278,49,265,44,248,42,70,42,56,44,44,49,35,57,29,69,27,85,15,85,15,0,
+295,331,26,331,66,289,295,331,66,289,79,290,295,331,79,290,242,290,295,331,242,290,256,289,295,331,256,289,266,284,295,331,266,284,274,276,295,331,274,276,279,263,295,331,279,263,282,247,295,331,282,247,295,247,26,331,26,246,39,246,26,331,39,246,43,263,26,331,43,263,48,276,26,331,48,276,55,284,26,331,55,284,66,289,219,189,207,188,218,146,218,146,207,188,205,147,205,147,207,188,114,188,205,147,114,188,113,147,101,146,113,147,102,189,101,146,102,189,93,193,83,211,84,122,87,200,87,200,84,12 [...]
+344,166,336,222,314,269,280,306,235,330,180,338,126,330,81,307,46,271,24,224,17,167,24,109,46,61,81,24,126,1,180,-6,234,1,279,24,314,60,336,108,344,166,16383,16383,287,169,285,134,280,103,272,76,260,53,246,35,235,26,223,19,209,15,196,12,181,11,167,12,154,15,142,19,130,25,119,33,103,52,90,75,81,102,76,132,74,166,76,194,80,222,87,247,97,269,108,286,121,298,134,308,149,314,164,318,180,320,194,319,207,316,219,311,231,305,242,296,257,279,270,257,279,231,285,201,287,169,
+149,314,180,338,134,308,134,308,180,338,126,330,134,308,126,330,121,298,121,298,126,330,108,286,97,269,108,286,126,330,97,269,126,330,81,307,81,102,81,24,90,75,90,75,81,24,126,1,90,75,126,1,103,52,103,52,126,1,119,33,130,25,119,33,126,1,130,25,126,1,180,-6,207,316,235,330,194,319,194,319,235,330,180,320,164,318,180,320,180,338,164,318,180,338,149,314,81,307,46,271,46,61,81,307,46,61,74,166,81,307,74,166,76,194,81,307,76,194,80,222,81,307,80,222,87,247,81,307,87,247,97,269,81,102,76,132,8 [...]
+352,0,352,9,333,12,320,17,312,25,308,37,307,55,307,274,308,293,312,307,320,315,333,319,352,321,352,331,9,331,9,321,28,319,41,315,49,307,53,294,54,274,54,61,53,39,49,25,42,16,29,12,9,9,9,0,148,0,148,9,129,12,117,17,109,25,105,38,104,56,104,296,105,303,107,307,111,310,116,312,238,312,245,311,251,310,254,306,256,301,256,62,255,41,252,26,244,17,232,12,212,9,212,0,
+49,25,42,16,148,0,148,0,42,16,29,12,148,0,29,12,9,9,53,294,54,274,111,310,53,294,111,310,49,307,49,307,111,310,116,312,49,307,116,312,352,331,352,331,116,312,123,312,252,26,244,17,352,0,352,0,244,17,232,12,352,0,232,12,212,9,352,331,123,312,238,312,352,331,238,312,245,311,352,331,245,311,251,310,352,331,251,310,254,306,352,331,254,306,256,301,352,331,256,301,256,294,352,331,256,294,320,315,352,331,320,315,333,319,352,331,333,319,352,321,307,55,307,274,256,294,256,294,307,274,308,293,256, [...]
+8,331,8,321,27,319,39,315,46,307,49,294,50,276,50,39,47,25,40,16,27,12,8,9,8,0,148,0,148,9,128,12,114,16,106,24,102,37,101,56,101,146,109,145,115,145,122,144,136,144,164,145,188,147,208,153,225,161,243,175,253,185,260,197,266,210,270,225,271,240,270,254,267,268,262,280,255,291,246,300,231,310,213,319,191,325,166,329,137,331,16383,16383,101,295,101,302,103,307,106,310,111,312,118,313,155,310,182,302,202,288,213,266,217,238,213,213,202,192,185,177,162,167,132,164,120,164,114,165,108,165,101,166,
+111,312,118,312,118,313,137,331,118,313,155,310,137,331,155,310,166,329,166,329,155,310,182,302,166,329,182,302,191,325,191,325,182,302,202,288,191,325,202,288,213,319,213,319,202,288,213,266,213,319,213,266,231,310,231,310,213,266,217,238,231,310,217,238,225,161,225,161,213,213,208,153,208,153,213,213,202,192,208,153,202,192,188,147,188,147,202,192,185,177,188,147,185,177,164,145,164,145,185,177,162,167,164,145,162,167,136,144,136,144,162,167,132,164,136,144,132,164,128,144,128,144,132, [...]
+300,102,289,102,283,82,275,66,264,56,249,49,229,47,74,47,193,184,86,312,190,312,214,310,234,305,248,294,259,276,266,251,278,251,278,331,15,331,15,324,148,162,15,7,15,0,286,0,
+278,331,15,331,86,312,278,331,86,312,190,312,278,331,190,312,214,310,278,331,214,310,234,305,278,331,234,305,248,294,278,331,248,294,259,276,278,331,259,276,266,251,278,331,266,251,278,251,148,162,15,7,74,47,148,162,74,47,193,184,148,162,193,184,86,312,148,162,86,312,15,331,148,162,15,331,15,324,275,66,264,56,286,0,286,0,264,56,249,49,286,0,249,49,229,47,286,0,300,102,289,102,286,0,289,102,283,82,286,0,283,82,275,66,286,0,229,47,74,47,286,0,74,47,15,7,286,0,15,7,15,0,
+296,246,293,331,12,331,8,246,21,246,28,274,37,292,50,303,70,309,97,310,127,310,127,61,126,39,123,25,115,16,101,12,80,9,80,0,226,0,226,9,205,11,192,16,183,23,179,36,178,55,178,310,208,310,235,309,254,303,268,292,277,274,284,246,
+293,331,12,331,70,309,293,331,70,309,97,310,293,331,97,310,127,310,293,331,127,310,178,310,293,331,178,310,208,310,293,331,208,310,235,309,293,331,235,309,254,303,293,331,254,303,268,292,293,331,268,292,277,274,293,331,277,274,284,246,293,331,284,246,296,246,192,16,183,23,127,61,127,61,183,23,179,36,127,61,179,36,127,310,127,310,179,36,178,55,127,310,178,55,178,310,12,331,8,246,21,246,12,331,21,246,28,274,12,331,28,274,37,292,12,331,37,292,50,303,12,331,50,303,70,309,226,0,226,9,205,11,2 [...]
+352,329,345,332,338,334,332,335,320,335,289,330,259,315,232,290,211,258,198,218,196,218,186,260,169,293,146,318,117,332,81,337,67,336,53,332,39,327,26,319,15,311,18,303,25,305,33,308,41,310,49,311,55,312,84,306,109,289,130,257,146,211,157,147,157,61,156,39,153,25,144,16,130,12,107,9,107,0,260,0,260,9,239,11,224,15,215,23,210,36,209,55,209,152,215,204,233,251,261,288,296,313,335,322,342,322,348,320,352,320,
+18,303,25,305,26,319,26,319,25,305,33,308,26,319,33,308,39,327,39,327,33,308,41,310,39,327,41,310,53,332,53,332,41,310,49,311,53,332,49,311,55,312,55,312,84,306,67,336,67,336,84,306,81,337,67,336,53,332,55,312,198,218,196,218,210,36,198,218,210,36,209,55,198,218,209,55,209,152,198,218,209,152,211,258,332,335,326,335,335,322,335,322,326,335,320,335,335,322,320,335,296,313,296,313,320,335,289,330,296,313,289,330,261,288,261,288,289,330,259,315,261,288,259,315,233,251,233,251,259,315,232,29 [...]
+216,290,217,301,221,310,230,316,245,320,267,321,267,331,114,331,114,321,136,320,151,317,160,311,164,302,165,290,165,280,122,276,82,263,49,241,26,209,17,165,23,128,39,97,67,72,106,57,156,51,165,51,165,42,163,29,157,20,146,14,132,10,114,9,114,0,267,0,267,9,248,11,234,15,224,20,218,29,216,43,216,51,228,51,264,56,300,69,332,91,355,123,364,165,355,209,332,241,298,263,258,276,216,280,16383,16383,215,262,250,256,276,240,295,216,306,188,310,159,304,128,290,103,268,85,243,74,215,70,16383,16383,16 [...]
+267,321,267,321,245,320,245,320,267,321,267,331,245,320,267,331,230,316,230,316,267,331,164,302,230,316,164,302,165,290,166,262,165,290,165,280,166,262,165,280,135,256,135,256,165,280,122,276,135,256,122,276,109,240,109,240,122,276,89,216,216,43,215,70,166,262,166,262,215,70,215,262,166,262,215,262,216,290,216,290,215,262,216,280,166,262,216,290,217,301,166,262,217,301,221,310,166,262,218,29,216,43,165,290,166,262,221,310,165,290,221,310,230,316,267,331,114,331,136,320,267,331,136,320,15 [...]
+352,0,352,9,338,12,327,16,317,22,307,32,296,46,200,184,272,272,289,292,303,305,316,314,331,319,348,321,348,331,229,331,229,321,243,320,253,319,259,316,262,311,263,305,263,301,260,296,257,290,251,282,243,272,188,202,166,234,151,255,139,272,131,286,126,297,124,306,125,312,128,316,133,319,139,320,147,321,161,321,161,331,11,331,11,321,29,319,44,312,59,299,78,276,103,242,156,164,78,66,58,42,43,26,31,17,19,12,5,9,5,0,121,0,121,9,106,11,95,13,88,17,84,21,83,26,84,31,87,38,92,46,100,57,109,70,16 [...]
+31,17,121,0,43,26,43,26,121,0,88,17,43,26,88,17,58,42,58,42,88,17,84,21,58,42,84,21,83,26,83,26,84,31,78,66,78,66,84,31,87,38,78,66,87,38,156,164,156,164,87,38,92,46,156,164,92,46,100,57,103,242,156,164,126,297,103,242,126,297,124,306,124,306,125,312,103,242,156,164,100,57,109,70,109,70,169,145,156,164,156,164,169,145,166,234,156,164,166,234,151,255,78,66,58,42,83,26,103,242,125,312,78,276,78,276,125,312,128,316,78,276,128,316,59,299,59,299,128,316,133,319,59,299,133,319,161,331,161,331, [...]
+362,345,332,341,310,328,295,309,287,284,285,254,283,226,278,198,267,175,248,159,218,153,212,153,212,281,214,299,221,311,232,318,246,321,263,321,263,331,110,331,110,321,128,321,142,317,152,310,159,299,161,281,161,153,156,153,125,159,106,175,95,198,90,226,89,254,86,284,78,309,64,328,42,341,11,345,11,335,21,330,28,320,32,308,34,295,35,283,34,274,34,265,33,256,33,247,32,238,39,199,59,170,87,150,122,139,161,135,161,62,160,40,156,25,147,16,132,12,110,9,110,0,263,0,263,9,244,11,229,14,220,22,21 [...]
+263,321,263,321,246,321,246,321,263,321,263,331,246,321,263,331,232,318,232,318,263,331,159,299,232,318,159,299,161,281,161,135,161,281,161,153,161,135,161,153,156,153,161,135,220,22,214,35,161,135,214,35,212,55,212,153,212,135,251,139,212,153,251,139,218,153,218,153,251,139,248,159,212,55,212,281,161,135,161,135,212,281,214,299,161,135,214,299,161,281,161,281,214,299,221,311,161,281,221,311,232,318,263,331,110,331,128,321,263,331,128,321,142,317,263,331,142,317,152,310,263,331,152,310,1 [...]
+358,0,358,84,345,84,343,71,339,61,333,53,325,49,314,47,237,47,238,66,275,80,305,100,327,126,341,159,345,199,338,242,318,280,285,310,241,331,186,338,130,330,86,309,53,277,33,239,26,199,31,159,44,126,65,100,95,80,132,66,133,47,58,47,46,48,38,52,32,59,28,70,27,85,15,85,15,0,158,0,153,80,129,93,110,114,96,140,87,170,84,200,88,235,100,268,120,295,149,313,186,320,222,314,250,298,271,273,284,239,289,200,285,168,276,138,261,112,242,92,218,80,214,0,
+58,47,46,48,158,0,158,0,46,48,38,52,158,0,38,52,15,0,15,0,38,52,32,59,15,0,32,59,15,85,15,85,32,59,28,70,15,85,28,70,27,85,26,199,31,159,33,239,33,239,31,159,44,126,33,239,44,126,53,277,53,277,44,126,65,100,53,277,65,100,86,309,86,309,65,100,84,200,95,80,84,200,65,100,186,338,149,313,186,320,186,320,222,314,241,331,241,331,222,314,250,298,241,331,250,298,285,310,285,310,250,298,271,273,285,310,271,273,284,239,289,200,305,100,318,280,318,280,305,100,327,126,318,280,327,126,338,242,338,242 [...]
+158,411,157,419,153,426,148,432,141,435,133,436,125,435,118,432,113,426,110,420,108,412,109,404,113,397,118,392,125,388,132,387,140,388,148,392,153,397,157,404,158,411,16383,16383,59,411,57,419,54,426,48,432,41,435,33,436,26,435,19,432,14,426,10,420,9,412,10,404,14,397,19,392,25,388,33,387,41,388,48,392,54,397,57,404,59,411,16383,16383,157,0,157,9,137,11,122,16,114,24,109,37,108,56,108,276,109,295,113,308,122,316,136,320,157,321,157,331,9,331,9,321,30,320,44,316,53,308,57,295,57,56,56,36 [...]
+9,412,10,404,10,420,10,420,10,404,14,397,10,420,14,397,14,426,14,426,14,397,19,392,14,426,19,392,19,432,19,432,19,392,25,388,19,432,25,388,26,435,26,435,25,388,33,387,26,435,33,387,33,436,33,436,33,387,41,388,33,436,41,388,41,435,41,435,41,388,48,392,41,435,48,392,48,432,48,432,48,392,54,397,48,432,54,397,54,426,54,426,54,397,57,404,54,426,57,404,57,419,57,419,57,404,59,411,52,23,44,15,157,0,157,0,44,15,30,11,157,0,30,11,9,9,157,331,9,331,30,320,157,331,30,320,44,316,157,331,44,316,53,30 [...]
+257,411,256,419,252,426,247,432,240,435,233,436,225,435,218,432,213,426,209,420,208,412,209,404,213,397,218,392,225,388,232,387,240,388,247,392,252,397,256,404,257,411,16383,16383,158,411,157,419,153,426,148,432,141,435,133,436,125,435,118,432,113,426,110,420,108,412,109,404,113,397,118,392,125,388,132,387,140,388,148,392,153,397,157,404,158,411,16383,16383,352,329,345,332,338,334,332,335,320,335,289,330,259,315,232,290,211,258,198,218,196,218,186,260,169,293,146,318,117,332,81,337,67,33 [...]
+18,303,25,305,26,319,26,319,25,305,33,308,26,319,33,308,39,327,39,327,33,308,41,310,39,327,41,310,53,332,53,332,41,310,49,311,53,332,49,311,55,312,55,312,84,306,67,336,67,336,84,306,81,337,67,336,53,332,55,312,198,218,196,218,210,36,198,218,210,36,209,55,198,218,209,55,209,152,198,218,209,152,211,258,260,0,260,9,239,11,260,0,239,11,224,15,260,0,224,15,156,39,260,0,156,39,153,25,260,0,153,25,144,16,260,0,144,16,130,12,260,0,130,12,107,9,260,0,107,9,107,0,169,293,157,147,210,36,169,293,210 [...]
+108,253,126,253,158,294,163,299,167,304,169,309,171,313,172,316,171,322,168,326,165,329,157,331,151,330,147,329,143,327,140,324,138,320,16383,16383,257,65,255,50,252,39,248,32,245,27,241,26,232,31,223,43,216,60,210,78,206,94,261,225,212,225,190,157,182,178,171,198,156,215,137,226,113,230,79,224,52,207,31,181,19,148,15,112,19,73,32,41,52,16,78,1,108,-4,129,-1,147,5,162,17,174,32,185,50,190,32,196,17,204,5,213,-1,225,-4,239,0,250,8,258,24,263,43,265,65,16383,16383,166,104,162,84,155,59,145 [...]
+63,167,70,189,79,224,79,224,70,189,81,204,79,224,81,204,113,230,113,230,81,204,95,213,113,230,95,213,110,216,110,216,129,208,113,230,113,230,129,208,137,226,157,331,158,294,161,330,161,330,158,294,163,299,161,330,163,299,165,329,165,329,163,299,167,304,165,329,167,304,168,326,168,326,167,304,169,309,168,326,169,309,171,322,171,322,169,309,171,313,171,322,171,313,172,316,158,294,157,331,151,330,158,294,151,330,147,329,158,294,147,329,143,327,158,294,143,327,140,324,158,294,140,324,138,320 [...]
+76,253,94,253,127,294,135,304,138,309,139,313,140,316,139,322,137,326,133,329,125,331,119,330,115,329,111,327,108,324,106,320,16383,16383,196,73,182,54,166,39,149,29,131,22,110,20,95,22,80,27,69,36,60,49,57,65,61,81,70,94,83,102,97,107,111,108,117,108,125,106,128,106,133,105,142,106,148,108,153,111,156,115,157,118,156,122,154,124,150,127,145,128,138,129,131,128,121,126,115,125,108,124,92,127,80,133,72,142,67,154,65,167,67,182,74,195,83,206,96,213,112,215,127,215,140,212,148,208,154,203,1 [...]
+37,13,65,0,47,113,47,113,65,0,57,65,63,118,57,65,61,81,63,118,61,81,70,94,72,142,67,154,70,94,70,94,67,154,65,167,63,118,65,167,60,217,63,118,60,217,49,123,49,123,60,217,40,202,49,123,40,202,39,131,39,131,40,202,31,141,142,228,121,230,127,215,127,215,121,230,112,215,96,213,112,215,121,230,96,213,121,230,87,226,125,331,127,294,129,330,129,330,127,294,131,299,129,330,131,299,133,329,133,329,131,299,135,304,133,329,135,304,137,326,137,326,135,304,138,309,137,326,138,309,139,322,139,322,138, [...]
+84,253,101,253,134,294,142,304,145,309,147,313,147,316,146,322,144,326,140,329,132,331,122,329,119,327,116,324,113,320,16383,16383,226,-107,223,-101,221,-94,219,-86,218,-76,218,160,216,182,208,202,196,217,180,226,159,230,145,229,131,224,117,216,102,205,87,190,86,190,84,205,81,215,76,223,68,226,56,228,44,225,33,216,22,203,13,188,5,172,12,170,15,176,25,188,30,193,36,194,39,193,41,190,44,184,45,173,46,156,46,0,88,0,88,174,100,185,111,194,120,199,130,202,140,203,153,201,163,195,170,185,174,1 [...]
+15,176,20,182,22,203,22,203,20,182,25,188,22,203,25,188,33,216,33,216,25,188,30,193,33,216,30,193,36,194,36,194,39,193,44,225,44,225,39,193,41,190,44,225,41,190,44,184,13,188,5,172,12,170,13,188,12,170,15,176,13,188,15,176,22,203,87,190,86,190,88,0,87,190,88,0,88,174,87,190,88,174,102,205,88,174,100,185,102,205,102,205,100,185,111,194,102,205,111,194,117,216,117,216,111,194,120,199,117,216,120,199,131,224,131,224,120,199,130,202,131,224,130,202,140,203,140,203,153,201,145,229,145,229,153 [...]
+40,253,57,253,90,294,98,304,101,309,103,313,103,316,102,322,100,326,96,329,93,330,89,331,83,330,78,329,75,327,72,324,70,320,16383,16383,126,54,120,43,115,36,110,31,105,29,99,28,95,29,91,33,90,36,89,40,89,228,88,230,72,224,57,219,41,214,26,208,10,204,10,195,15,196,37,196,42,193,45,188,47,181,47,39,48,26,51,14,57,4,65,-2,77,-4,92,-1,105,7,116,20,126,35,133,50,
+89,331,90,294,93,330,93,330,90,294,94,299,93,330,94,299,96,329,96,329,94,299,98,304,96,329,98,304,100,326,100,326,98,304,101,309,100,326,101,309,102,322,102,322,101,309,103,313,102,322,103,313,103,316,90,294,89,331,83,330,90,294,83,330,78,329,90,294,78,329,75,327,90,294,75,327,72,324,90,294,72,324,70,320,90,294,70,320,57,253,45,188,57,219,42,193,42,193,57,219,41,214,42,193,41,214,37,196,37,196,41,214,31,196,28,196,31,196,41,214,28,196,41,214,26,208,57,4,65,-2,72,224,72,224,65,-2,77,-4,72 [...]
+202,278,201,286,197,293,192,298,185,302,177,303,169,302,163,298,157,293,154,286,152,278,154,271,157,264,163,258,169,255,177,253,185,255,192,258,197,264,201,271,202,278,16383,16383,100,253,118,253,151,294,159,304,162,309,163,313,164,316,163,322,161,326,157,329,149,331,143,330,139,329,135,327,132,324,130,320,16383,16383,103,278,101,286,98,293,92,298,85,302,78,303,70,302,63,298,58,293,54,286,53,278,54,271,58,264,63,258,70,255,78,253,85,255,92,258,98,264,101,271,103,278,16383,16383,127,230,1 [...]
+18,176,23,182,26,203,26,203,23,182,28,188,26,203,28,188,36,216,36,216,28,188,33,193,36,216,33,193,39,194,39,194,43,192,47,225,47,225,43,192,46,187,47,225,46,187,48,180,16,188,8,172,15,170,16,188,15,170,18,176,16,188,18,176,26,203,49,99,51,66,49,159,49,170,49,159,60,228,49,170,60,228,48,180,48,180,60,228,47,225,54,286,54,271,58,293,58,293,54,271,58,264,58,293,58,264,63,298,63,298,58,264,63,258,63,298,63,258,70,302,70,302,63,258,70,255,70,302,70,255,78,303,78,303,70,255,78,253,78,303,78,25 [...]
+257,65,255,50,252,39,248,32,245,27,241,26,232,31,223,43,216,60,210,78,206,94,261,225,212,225,190,157,182,178,171,198,156,215,137,226,113,230,79,224,52,207,31,181,19,148,15,112,19,73,32,41,52,16,78,1,108,-4,129,-1,147,5,162,17,174,32,185,50,190,32,196,17,204,5,213,-1,225,-4,239,0,250,8,258,24,263,43,265,65,16383,16383,166,104,162,84,155,59,145,35,131,16,113,9,90,19,75,43,66,76,61,109,60,137,63,167,70,189,81,204,95,213,110,216,129,208,144,187,154,159,161,130,166,104,
+63,167,70,189,79,224,79,224,70,189,81,204,79,224,81,204,113,230,113,230,81,204,95,213,113,230,95,213,110,216,110,216,129,208,113,230,113,230,129,208,137,226,144,187,154,159,156,215,156,215,154,159,161,130,156,215,161,130,171,198,171,198,161,130,166,104,171,198,166,104,174,32,171,198,174,32,182,178,182,178,174,32,185,50,182,178,185,50,190,157,190,157,185,50,190,32,190,157,190,32,212,225,212,225,190,32,196,17,212,225,196,17,206,94,206,94,196,17,204,5,206,94,204,5,213,-1,137,226,129,208,144 [...]
+172,200,181,204,190,209,196,215,202,222,206,229,209,236,211,244,213,251,213,257,214,264,209,289,197,311,179,327,157,338,133,342,102,337,76,322,54,293,41,249,36,186,36,-67,34,-85,30,-101,27,-107,70,-107,72,-102,74,-95,76,-87,78,-67,78,16,88,7,98,1,108,-2,119,-3,131,-4,164,2,192,19,214,46,228,78,233,114,231,137,223,158,211,176,194,190,173,199,16383,16383,78,243,78,250,79,276,85,297,95,314,108,324,124,328,144,322,158,309,167,290,172,268,173,247,172,235,170,225,166,215,160,209,152,206,147,20 [...]
+108,324,124,328,124,328,133,342,124,328,144,322,133,342,144,322,157,338,157,338,144,322,158,309,157,338,158,309,179,327,179,327,158,309,167,290,179,327,167,290,172,268,172,200,181,204,172,235,172,200,172,235,170,225,172,200,170,225,169,178,172,200,169,178,179,162,172,200,179,162,173,199,233,114,231,137,228,78,228,78,231,137,223,158,228,78,223,158,214,46,214,46,223,158,211,176,214,46,211,176,194,190,192,19,214,46,194,190,192,19,194,190,190,101,192,19,190,101,187,72,192,19,187,72,179,47,19 [...]
+222,225,172,225,120,49,115,84,108,130,97,177,78,214,49,228,32,224,20,212,12,195,7,173,5,150,12,150,16,166,21,178,28,187,35,192,41,194,66,179,84,143,96,96,103,50,107,18,103,9,100,0,96,-7,90,-25,84,-47,82,-57,81,-66,81,-74,82,-85,85,-94,90,-101,96,-106,105,-108,118,-105,127,-98,133,-87,135,-73,136,-58,136,-45,135,-32,133,-19,131,-8,129,0,
+35,192,41,194,41,194,49,228,41,194,66,179,49,228,66,179,78,214,78,214,66,179,84,143,78,214,84,143,97,177,97,177,84,143,96,96,97,177,96,96,103,50,120,49,115,84,118,-105,118,-105,115,84,108,130,118,-105,108,130,107,18,107,18,108,130,103,50,103,50,108,130,97,177,118,-105,127,-98,120,49,120,49,127,-98,129,0,120,49,129,0,172,225,172,225,129,0,222,225,107,18,103,9,105,-108,107,18,105,-108,118,-105,100,0,96,-7,96,-106,100,0,96,-106,105,-108,100,0,105,-108,103,9,96,-7,93,-16,96,-106,96,-106,93,- [...]
+110,213,77,203,50,187,31,164,19,137,15,108,20,74,34,44,56,18,86,1,123,-4,161,1,192,17,215,43,230,76,235,116,232,141,225,164,213,184,197,202,176,217,145,233,114,248,87,261,68,274,61,290,64,302,72,310,83,316,95,319,106,320,137,316,154,307,165,296,176,286,191,282,198,284,203,288,206,293,208,299,209,304,203,318,188,328,168,336,145,340,124,342,102,340,81,334,61,324,47,309,42,289,45,269,54,251,68,237,87,224,110,213,16383,16383,190,104,187,71,180,45,168,25,151,13,130,9,121,10,111,13,101,19,93,2 [...]
+42,289,45,269,47,309,47,309,45,269,54,251,47,309,54,251,61,324,61,324,54,251,61,290,68,237,61,290,54,251,64,302,72,310,81,334,81,334,72,310,83,316,81,334,83,316,102,340,102,340,83,316,95,319,102,340,95,319,106,320,106,320,137,316,124,342,124,342,137,316,145,340,61,324,61,290,64,302,61,324,64,302,81,334,198,284,203,288,203,318,203,318,203,288,206,293,203,318,206,293,209,304,209,304,206,293,208,299,154,307,165,296,168,336,168,336,165,296,176,286,168,336,176,286,188,328,188,328,176,286,191, [...]
+196,73,182,54,166,39,149,29,131,22,110,20,95,22,80,27,69,36,60,49,57,65,61,81,70,94,83,102,97,107,111,108,117,108,125,106,128,106,133,105,142,106,148,108,153,111,156,115,157,118,156,122,154,124,150,127,145,128,138,129,131,128,121,126,115,125,108,124,92,127,80,133,72,142,67,154,65,167,67,182,74,195,83,206,96,213,112,215,127,215,140,212,148,208,154,203,156,195,155,193,155,190,154,187,154,183,153,179,155,171,158,166,163,161,168,158,175,157,182,158,188,161,194,165,198,171,199,179,194,199,181 [...]
+37,13,65,0,47,113,47,113,65,0,57,65,63,118,57,65,61,81,63,118,61,81,70,94,72,142,67,154,70,94,70,94,67,154,65,167,63,118,65,167,60,217,63,118,60,217,49,123,49,123,60,217,40,202,49,123,40,202,39,131,39,131,40,202,31,141,142,228,121,230,127,215,127,215,121,230,112,215,96,213,112,215,121,230,96,213,121,230,87,226,194,199,181,214,182,158,194,199,182,158,188,161,194,199,188,161,194,165,194,199,194,165,198,171,194,199,198,171,199,179,158,166,163,161,163,223,163,223,163,161,168,158,163,223,168, [...]
+76,342,59,335,45,327,35,318,29,308,27,296,30,283,38,272,48,265,60,260,71,259,72,257,52,225,36,196,25,166,19,135,17,100,21,58,33,28,49,9,71,-1,95,-4,105,-4,117,-2,128,-1,137,0,143,0,158,-1,170,-5,180,-12,186,-22,188,-34,186,-47,180,-58,170,-67,159,-72,147,-74,140,-72,134,-69,128,-64,123,-61,117,-59,110,-60,104,-63,99,-68,97,-73,96,-80,98,-90,103,-98,111,-103,121,-107,132,-108,151,-104,170,-93,187,-76,199,-55,204,-29,201,-3,192,16,177,30,156,38,128,41,117,41,113,40,103,40,78,44,61,55,49,72 [...]
+43,93,41,117,41,117,36,196,41,117,44,151,36,196,44,151,52,225,52,225,44,151,53,184,52,225,53,184,72,257,72,257,53,184,65,213,72,257,65,213,80,238,48,265,50,298,45,327,48,265,45,327,38,272,38,272,45,327,35,318,38,272,35,318,30,283,30,283,35,318,29,308,30,283,29,308,27,296,51,305,55,312,59,335,59,335,55,312,61,320,59,335,61,320,76,342,76,342,61,320,70,328,76,342,70,328,81,334,51,305,59,335,45,327,51,305,45,327,50,298,108,302,94,287,94,257,94,257,94,287,84,273,94,257,84,273,80,238,80,238,84 [...]
+226,-107,223,-101,221,-94,219,-86,218,-76,218,160,216,182,208,202,196,217,180,226,159,230,145,229,131,224,117,216,102,205,87,190,86,190,84,205,81,215,76,223,68,226,56,228,44,225,33,216,22,203,13,188,5,172,12,170,15,176,25,188,30,193,36,194,39,193,41,190,44,184,45,173,46,156,46,0,88,0,88,174,100,185,111,194,120,199,130,202,140,203,153,201,163,195,170,185,174,172,176,154,176,-79,177,-89,179,-97,181,-103,184,-107,
+15,176,20,182,22,203,22,203,20,182,25,188,22,203,25,188,33,216,33,216,25,188,30,193,33,216,30,193,36,194,36,194,39,193,44,225,44,225,39,193,41,190,44,225,41,190,44,184,13,188,5,172,12,170,13,188,12,170,15,176,13,188,15,176,22,203,87,190,86,190,88,0,87,190,88,0,88,174,87,190,88,174,102,205,88,174,100,185,102,205,102,205,100,185,111,194,102,205,111,194,117,216,117,216,111,194,120,199,117,216,120,199,131,224,131,224,120,199,130,202,131,224,130,202,140,203,140,203,153,201,145,229,145,229,153 [...]
+234,166,233,198,230,228,226,254,220,277,211,296,199,313,185,325,169,334,150,340,126,342,87,333,55,310,32,273,18,226,13,170,14,144,15,120,18,100,23,81,28,64,40,41,55,21,74,7,96,-1,122,-4,161,3,192,27,215,63,229,110,234,166,16383,16383,59,177,59,193,62,247,70,285,83,310,99,324,119,328,150,318,171,292,182,256,188,216,189,177,16383,16383,189,158,187,109,180,67,168,36,151,16,128,9,98,18,78,42,67,77,61,118,59,161,189,161,
+150,340,126,342,150,318,150,318,126,342,119,328,99,324,119,328,126,342,99,324,126,342,87,333,230,228,226,254,229,110,230,228,229,110,234,166,230,228,234,166,233,198,220,277,211,296,215,63,220,277,215,63,229,110,220,277,229,110,226,254,23,81,28,64,32,273,32,273,28,64,40,41,32,273,40,41,55,310,55,310,40,41,55,21,55,310,55,21,59,193,59,193,55,21,59,161,59,193,59,161,59,177,59,177,59,161,189,177,189,177,59,161,189,161,189,177,189,161,192,27,189,177,192,27,199,313,199,313,192,27,215,63,199,31 [...]
+126,54,120,43,115,36,110,31,105,29,99,28,95,29,91,33,90,36,89,40,89,228,88,230,72,224,57,219,41,214,26,208,10,204,10,195,15,196,37,196,42,193,45,188,47,181,47,39,48,26,51,14,57,4,65,-2,77,-4,92,-1,105,7,116,20,126,35,133,50,
+45,188,57,219,42,193,42,193,57,219,41,214,42,193,41,214,37,196,37,196,41,214,31,196,28,196,31,196,41,214,28,196,41,214,26,208,57,4,65,-2,72,224,72,224,65,-2,77,-4,72,224,77,-4,88,230,88,230,77,-4,89,40,88,230,89,40,89,228,91,33,92,-1,93,31,93,31,92,-1,105,7,93,31,105,7,95,29,95,29,105,7,99,28,105,29,99,28,105,7,105,29,105,7,116,20,133,50,126,54,126,35,126,35,126,54,120,43,126,35,120,43,116,20,116,20,120,43,115,36,116,20,115,36,110,31,92,-1,91,33,90,36,92,-1,90,36,89,40,92,-1,89,40,77,-4, [...]
+252,0,252,7,239,10,228,13,219,19,209,27,199,39,113,140,131,158,147,172,161,181,174,185,188,187,194,186,201,185,207,183,213,182,220,181,227,182,233,185,239,189,243,196,245,206,244,214,240,220,234,225,226,229,215,230,202,228,184,222,160,205,127,176,83,129,83,229,81,230,70,226,48,220,35,216,18,212,3,208,3,200,10,200,14,201,20,201,28,200,34,197,38,192,40,183,41,171,41,0,83,0,83,113,148,34,151,30,155,24,156,22,156,20,155,15,153,12,149,9,144,8,137,7,133,7,133,0,
+10,200,14,201,18,212,18,212,14,201,17,201,18,212,17,201,20,201,20,201,28,200,35,216,35,216,28,200,34,197,35,216,34,197,38,192,7,200,10,200,18,212,7,200,18,212,3,208,7,200,3,208,3,200,35,216,38,192,48,220,48,220,38,192,40,183,48,220,40,183,41,171,83,0,41,171,41,0,35,216,18,212,20,201,83,129,83,229,81,230,83,129,81,230,83,0,83,129,83,0,83,113,83,129,83,113,127,176,131,158,147,172,160,205,160,205,147,172,161,181,160,205,161,181,184,222,184,222,161,181,174,185,184,222,174,185,188,187,188,187 [...]
+238,69,235,53,229,42,222,35,215,31,209,30,200,32,193,38,186,47,181,58,176,71,121,266,113,292,104,313,95,329,83,338,68,342,51,337,39,325,32,308,28,288,26,268,34,268,38,284,43,295,49,302,56,305,64,306,74,304,83,296,92,283,100,267,107,248,113,225,6,0,56,0,128,177,164,45,169,29,176,15,184,4,193,-2,204,-5,219,-1,230,8,239,24,244,45,246,69,
+56,305,64,306,64,306,68,342,64,306,74,304,68,342,74,304,83,338,83,338,74,304,83,296,83,338,83,296,95,329,95,329,83,296,92,283,95,329,92,283,100,267,113,292,107,248,113,225,113,292,113,225,121,266,121,266,113,225,128,177,121,266,128,177,176,71,176,71,128,177,164,45,176,71,164,45,169,29,104,313,95,329,100,267,104,313,100,267,107,248,104,313,107,248,113,292,176,71,169,29,176,15,176,71,176,15,184,4,113,225,6,0,56,0,113,225,56,0,128,177,200,32,193,38,193,-2,193,-2,193,38,186,47,193,-2,186,47, [...]
+251,53,244,42,239,35,234,31,230,29,224,28,221,29,218,31,216,36,215,45,214,56,214,225,172,225,172,59,171,53,169,48,166,44,161,40,153,33,144,29,136,26,128,24,121,24,108,26,96,32,87,41,80,53,78,69,78,225,36,225,36,-65,35,-75,34,-84,32,-93,30,-101,27,-107,69,-107,71,-102,73,-94,75,-85,76,-75,76,9,78,9,81,4,87,0,93,-2,101,-4,109,-4,119,-3,131,0,144,7,158,19,171,36,172,36,173,23,177,12,182,3,191,-2,203,-4,217,-1,230,7,241,20,250,35,258,50,
+78,225,36,225,69,-107,78,225,69,-107,71,-102,78,225,71,-102,73,-94,78,225,73,-94,75,-85,78,225,75,-85,76,-75,78,225,76,-75,76,9,78,225,76,9,78,9,69,-107,36,225,36,-65,69,-107,36,-65,35,-75,69,-107,35,-75,34,-84,69,-107,34,-84,32,-93,69,-107,32,-93,30,-101,69,-107,30,-101,27,-107,87,0,93,-2,96,32,96,32,93,-2,101,-4,96,32,101,-4,108,26,108,26,101,-4,109,-4,108,26,109,-4,121,24,121,24,109,-4,119,-3,121,24,119,-3,131,0,171,53,169,48,171,36,171,36,169,48,166,44,171,36,166,44,161,40,161,40,153 [...]
+212,230,206,188,189,141,163,97,129,63,90,45,89,45,89,228,88,230,72,224,57,219,41,214,26,208,10,204,10,195,15,196,31,196,37,195,42,192,45,188,47,181,47,-6,59,-6,100,7,134,28,163,55,186,84,203,116,212,141,217,166,220,189,221,211,222,230,
+45,188,57,219,42,192,42,192,57,219,41,214,42,192,41,214,37,195,37,195,41,214,31,196,28,196,31,196,41,214,28,196,41,214,26,208,89,228,88,230,89,45,89,45,88,230,72,224,89,45,72,224,59,-6,59,-6,72,224,57,219,59,-6,57,219,47,172,47,172,57,219,47,181,26,208,10,204,15,196,26,208,15,196,20,196,26,208,20,196,25,196,26,208,25,196,28,196,186,84,189,141,163,55,163,55,189,141,163,97,163,55,163,97,134,28,134,28,163,97,129,63,134,28,129,63,100,7,100,7,129,63,90,45,189,141,203,116,206,188,206,188,203,1 [...]
+89,342,71,335,57,328,48,319,43,309,41,297,42,286,47,278,53,272,61,268,69,266,63,259,58,251,54,242,52,233,51,224,52,215,55,206,59,198,65,190,73,184,54,168,39,150,27,129,20,106,17,81,20,53,29,29,44,11,67,0,98,-4,107,-4,117,-2,128,-1,137,0,143,0,158,-1,170,-5,180,-12,186,-22,188,-34,186,-47,180,-59,170,-67,159,-72,147,-74,140,-72,134,-69,128,-64,123,-61,117,-59,110,-60,104,-63,99,-68,97,-73,96,-80,98,-90,103,-98,111,-103,121,-107,132,-108,151,-104,170,-93,187,-76,199,-53,204,-26,201,-3,192, [...]
+51,59,43,75,44,11,44,11,43,75,40,98,39,150,40,98,43,118,39,150,43,118,54,168,54,168,43,118,50,136,54,168,50,136,62,152,61,268,63,305,57,328,61,268,57,328,53,272,53,272,57,328,48,319,53,272,48,319,47,278,47,278,48,319,43,309,47,278,43,309,42,286,42,286,43,309,41,297,64,310,66,316,71,335,71,335,66,316,72,322,71,335,72,322,89,342,89,342,72,322,80,328,89,342,80,328,93,334,64,310,71,335,57,328,64,310,57,328,63,305,73,235,76,283,71,225,71,225,70,286,69,266,69,266,70,286,66,291,69,266,66,291,64 [...]
+237,114,232,151,218,183,197,208,167,224,129,230,91,223,60,203,37,174,22,139,17,101,23,67,38,38,62,15,92,0,126,-4,161,2,191,20,215,47,231,79,237,114,16383,16383,192,95,190,74,183,52,172,31,156,17,134,11,107,19,87,38,73,65,65,95,62,122,64,145,70,169,80,191,97,207,119,214,148,205,168,184,182,155,190,124,192,95,
+97,207,119,214,119,214,129,230,119,214,148,205,129,230,148,205,167,224,167,224,148,205,168,184,167,224,168,184,197,208,197,208,168,184,182,155,197,208,182,155,190,124,190,74,183,52,191,20,191,20,183,52,172,31,191,20,172,31,161,2,161,2,172,31,156,17,161,2,156,17,134,11,134,11,107,19,126,-4,126,-4,107,19,92,0,107,19,87,38,92,0,92,0,87,38,73,65,92,0,73,65,62,15,62,15,73,65,65,95,62,15,65,95,62,122,80,191,91,223,70,169,70,169,91,223,60,203,70,169,60,203,64,145,64,145,60,203,62,122,62,15,62,1 [...]
+233,69,229,55,223,45,216,40,209,37,203,36,194,38,188,41,184,47,180,54,178,61,177,69,176,78,175,88,175,109,176,127,176,144,178,160,179,173,180,183,239,183,239,225,97,225,68,222,46,214,29,200,16,180,4,155,12,155,23,167,35,176,47,180,62,183,78,183,72,119,64,77,54,54,42,42,30,36,26,35,20,31,18,25,20,15,23,6,30,0,39,-5,52,-6,77,9,91,48,98,99,100,148,100,183,147,183,145,160,143,136,139,82,139,56,141,37,147,20,156,7,169,-1,185,-4,205,0,220,12,232,29,239,49,241,69,
+72,119,64,77,77,9,77,9,64,77,54,54,77,9,54,54,52,-6,52,-6,54,54,42,42,52,-6,42,42,39,-5,39,-5,42,42,30,36,39,-5,30,36,30,0,30,0,30,36,26,35,30,0,26,35,23,6,23,6,26,35,23,33,23,6,23,33,20,31,20,15,23,6,20,31,20,15,20,31,19,28,20,15,19,28,18,25,97,225,68,222,78,183,78,183,91,48,97,225,97,225,91,48,98,99,97,225,98,99,100,183,100,183,98,99,100,148,180,183,239,183,239,225,180,183,239,225,147,183,147,183,239,225,100,183,176,78,175,88,169,-1,169,-1,175,88,175,99,169,-1,175,99,175,109,175,109,17 [...]
+36,-65,35,-75,34,-84,32,-93,30,-101,27,-107,70,-107,72,-102,74,-95,76,-85,77,-75,78,-64,78,15,88,7,98,1,108,-2,118,-4,130,-4,164,1,192,19,214,47,228,82,233,123,228,158,214,188,191,210,163,225,129,230,101,225,75,210,54,182,41,138,36,76,16383,16383,78,137,79,163,85,185,94,202,107,212,123,216,145,211,163,197,177,175,186,144,190,106,187,75,179,49,166,29,150,16,129,11,115,13,101,18,89,26,81,35,78,44,
+107,212,123,216,123,216,129,230,123,216,145,211,129,230,145,211,163,225,163,225,145,211,163,197,163,225,163,197,191,210,191,210,163,197,177,175,191,210,177,175,186,144,191,210,190,106,192,19,191,210,192,19,214,188,214,188,192,19,214,47,214,188,214,47,228,158,228,158,214,47,228,82,228,158,228,82,233,123,192,19,190,106,187,75,192,19,187,75,179,49,192,19,179,49,166,29,192,19,166,29,164,1,129,11,130,-4,150,16,150,16,130,-4,164,1,150,16,164,1,166,29,130,-4,129,11,118,-4,118,-4,129,11,115,13,1 [...]
+216,176,213,191,205,206,190,218,169,227,142,230,107,223,73,202,45,171,25,130,17,83,21,45,33,20,50,5,71,-2,95,-4,105,-4,117,-2,128,-1,137,0,143,0,158,-1,170,-5,180,-12,186,-22,188,-34,186,-47,180,-58,170,-67,159,-72,147,-74,140,-72,134,-69,128,-64,123,-61,117,-59,110,-60,104,-63,99,-68,97,-73,96,-80,98,-90,103,-98,111,-103,121,-107,132,-108,151,-104,170,-93,187,-76,199,-55,204,-29,201,-3,192,16,177,30,156,38,128,41,119,41,115,40,103,40,78,45,60,54,48,68,42,85,41,105,45,135,58,158,76,174,9 [...]
+60,54,48,68,50,5,50,5,48,68,42,85,50,5,42,85,33,20,33,20,42,85,41,105,45,171,41,105,45,135,45,171,45,135,73,202,73,202,45,135,58,158,73,202,58,158,76,174,73,202,76,174,107,223,107,223,76,174,97,183,107,223,97,183,118,186,118,186,141,182,142,230,142,230,141,182,158,174,142,230,158,174,169,227,169,227,158,174,170,163,169,227,170,163,190,218,190,218,170,163,181,155,190,218,181,155,192,151,17,83,21,45,25,130,25,130,21,45,33,20,25,130,33,20,45,171,45,171,33,20,41,105,177,30,156,38,158,-1,158, [...]
+259,183,259,225,119,225,87,220,58,207,35,184,20,151,15,108,20,73,35,42,58,18,87,1,119,-4,156,1,187,16,212,38,228,65,233,94,229,121,218,138,203,152,186,165,171,183,16383,16383,189,85,186,63,180,42,168,25,152,13,131,9,110,15,90,30,75,54,64,84,60,117,65,145,78,164,97,176,118,182,137,183,153,172,167,155,178,134,186,110,189,85,
+186,63,180,42,187,16,187,16,180,42,168,25,187,16,168,25,156,1,156,1,168,25,152,13,156,1,152,13,131,9,131,9,110,15,119,-4,119,-4,110,15,90,30,119,-4,90,30,87,1,87,1,90,30,75,54,87,1,75,54,64,84,58,207,60,117,65,145,58,207,65,145,87,220,87,220,65,145,78,164,87,220,78,164,97,176,58,18,87,1,64,84,58,18,64,84,60,117,58,18,60,117,58,207,58,18,58,207,35,184,58,18,35,184,35,42,20,151,15,108,20,73,20,151,20,73,35,42,20,151,35,42,35,184,153,172,167,155,171,183,171,183,167,155,178,134,171,183,259,2 [...]
+221,183,221,225,81,225,55,219,34,204,18,183,7,160,2,138,9,138,16,153,25,166,37,175,50,181,66,183,107,183,102,164,96,142,92,119,88,95,87,71,89,49,94,28,103,11,118,0,138,-4,157,0,172,10,183,27,191,48,193,71,185,71,182,59,176,49,169,42,161,38,151,36,141,39,133,47,128,59,125,74,124,91,125,113,128,135,131,155,134,172,136,183,
+9,138,16,153,18,183,18,183,16,153,25,166,18,183,25,166,34,204,34,204,25,166,37,175,34,204,37,175,55,219,55,219,37,175,50,181,55,219,50,181,66,183,81,225,66,183,107,183,81,225,107,183,221,225,221,225,107,183,136,183,221,225,136,183,221,183,7,160,2,138,9,138,7,160,9,138,18,183,118,0,125,74,124,91,124,91,125,113,118,0,118,0,125,113,107,183,118,0,107,183,103,11,103,11,107,183,102,164,103,11,102,164,96,142,128,135,131,155,107,183,107,183,131,155,134,172,107,183,134,172,136,183,138,-4,157,0,14 [...]
+127,230,127,220,139,218,149,214,159,209,168,201,177,191,186,176,193,159,198,141,201,122,202,104,200,75,193,49,182,28,165,14,142,9,121,14,106,28,97,47,92,68,91,87,91,193,90,205,86,215,80,222,71,226,60,228,47,225,36,216,26,203,16,188,8,172,15,170,18,176,28,188,33,193,39,194,43,192,46,187,48,180,49,170,49,99,51,66,60,38,76,15,102,0,139,-4,174,1,204,18,227,43,242,75,247,113,241,155,226,188,202,211,173,225,141,230,
+18,176,23,182,26,203,26,203,23,182,28,188,26,203,28,188,36,216,36,216,28,188,33,193,36,216,33,193,39,194,39,194,43,192,47,225,47,225,43,192,46,187,47,225,46,187,48,180,16,188,8,172,15,170,16,188,15,170,18,176,16,188,18,176,26,203,49,99,51,66,49,159,49,170,49,159,60,228,49,170,60,228,48,180,48,180,60,228,47,225,91,87,91,193,90,205,91,87,90,205,86,215,91,87,86,215,80,222,91,87,80,222,92,68,141,230,127,230,139,218,141,230,139,218,149,214,141,230,149,214,173,225,200,75,193,49,204,18,204,18,1 [...]
+134,9,124,10,114,13,104,18,94,25,86,34,76,52,68,72,63,94,61,116,60,137,63,166,73,189,88,206,109,216,134,221,134,228,132,229,129,229,126,230,121,230,84,224,54,207,33,181,19,150,15,114,19,78,33,46,55,20,85,3,123,-3,134,-4,134,-107,176,-107,176,-4,220,1,254,18,277,43,292,75,296,111,291,151,278,184,258,209,233,224,207,230,195,229,184,226,175,221,167,215,160,208,148,187,141,162,137,134,135,105,134,76,16383,16383,176,9,176,129,177,155,178,179,182,198,189,211,201,216,218,209,232,190,243,164,249 [...]
+61,116,60,137,60,137,55,20,60,137,54,207,55,20,54,207,33,46,33,46,54,207,33,181,33,46,33,181,19,78,19,78,33,181,19,150,19,78,19,150,15,114,63,94,55,20,68,72,68,72,55,20,85,3,68,72,85,3,76,52,76,52,85,3,86,34,94,25,86,34,85,3,94,25,85,3,123,-3,61,116,60,137,55,20,61,116,55,20,63,94,135,105,134,76,176,-107,176,-107,134,76,134,9,176,-107,134,9,134,-4,134,-4,134,9,124,10,134,-4,124,10,123,-3,123,-3,124,10,114,13,123,-3,114,13,104,18,134,221,134,228,132,229,134,221,132,229,129,229,134,221,129 [...]
+243,225,194,225,123,93,113,139,103,177,92,206,79,224,63,230,49,227,38,217,31,202,27,182,26,156,34,156,37,171,41,182,46,190,51,194,56,195,67,192,77,183,85,168,93,147,101,119,110,78,6,-104,55,-104,126,26,136,-34,141,-57,148,-78,157,-94,168,-105,182,-109,198,-104,209,-90,216,-71,219,-52,220,-34,213,-34,210,-49,206,-61,201,-68,195,-72,187,-74,188,-74,177,-71,168,-63,160,-48,153,-27,147,1,138,41,
+79,224,63,230,67,192,67,192,63,230,56,195,51,194,56,195,63,230,51,194,63,230,49,227,194,225,123,93,126,26,126,26,123,93,113,139,126,26,113,139,110,78,110,78,113,139,103,177,110,78,103,177,101,119,67,192,77,183,79,224,79,224,77,183,85,168,79,224,85,168,92,206,92,206,85,168,93,147,92,206,93,147,103,177,103,177,93,147,101,119,138,41,243,225,194,225,138,41,194,225,126,26,138,41,126,26,136,-34,138,41,136,-34,141,-57,138,41,141,-57,147,1,110,78,6,-104,55,-104,110,78,55,-104,126,26,210,-49,206, [...]
+342,228,332,230,316,230,290,224,273,209,262,187,256,162,254,136,253,103,249,69,239,39,223,17,197,9,197,225,155,225,155,9,129,17,112,39,103,69,99,104,98,137,96,163,90,188,78,210,61,224,36,230,31,230,25,229,14,229,10,228,10,220,30,210,42,190,49,164,52,137,52,114,55,72,65,39,84,15,114,0,155,-4,155,-107,197,-107,197,-4,236,0,265,16,285,41,296,74,300,114,300,137,303,164,310,190,322,211,342,221,
+239,39,223,17,236,0,236,0,223,17,197,9,197,-107,197,9,155,-4,197,225,155,225,155,-4,197,225,155,-4,197,9,155,225,155,9,155,-4,155,-4,155,9,129,17,155,-4,129,17,114,0,114,0,129,17,112,39,114,0,112,39,103,69,99,104,98,137,96,163,99,104,96,163,90,188,99,104,90,188,84,15,99,104,84,15,103,69,52,114,55,72,61,224,61,224,55,72,65,39,61,224,65,39,78,210,78,210,65,39,84,15,78,210,84,15,90,188,42,190,49,164,61,224,61,224,49,164,52,137,61,224,52,137,52,114,61,224,36,230,42,190,42,190,36,230,31,230,4 [...]
+180,223,206,218,226,203,240,179,249,146,252,104,252,76,248,51,242,29,229,14,210,9,200,12,190,20,181,33,174,51,170,73,173,85,177,105,178,115,179,127,177,145,174,158,169,168,163,173,156,175,149,173,143,168,138,159,135,145,133,126,134,114,135,103,137,94,139,84,142,73,138,51,132,33,123,20,113,12,100,9,82,15,71,31,64,54,61,81,60,109,63,149,73,180,88,204,108,218,132,223,132,230,94,225,62,211,37,186,20,151,15,104,15,84,18,66,23,50,30,35,39,23,49,13,59,5,70,0,81,-3,93,-4,109,-2,123,3,136,12,147, [...]
+71,31,64,54,70,0,70,0,64,54,61,81,70,0,61,81,59,5,59,5,61,81,60,109,62,211,60,109,63,149,62,211,63,149,73,180,108,218,132,223,132,230,108,218,132,230,94,225,108,218,94,225,88,204,94,225,62,211,73,180,94,225,73,180,88,204,23,50,30,35,37,186,37,186,30,35,39,23,37,186,39,23,62,211,62,211,39,23,49,13,62,211,49,13,60,109,60,109,49,13,59,5,20,151,15,104,15,84,20,151,15,84,18,66,20,151,18,66,23,50,20,151,23,50,37,186,81,-3,93,-4,82,15,82,15,93,-4,100,9,113,12,100,9,109,-2,113,12,109,-2,123,3,71 [...]
+272,145,263,146,255,146,246,147,238,148,230,150,229,176,225,203,220,230,212,257,201,281,191,300,179,316,163,329,144,338,121,342,100,339,80,331,63,316,50,294,46,264,53,226,74,194,104,168,142,149,185,137,186,133,186,116,185,85,180,56,171,32,157,15,137,9,115,14,101,28,91,46,87,66,85,84,85,110,84,131,81,145,76,154,67,159,55,160,43,158,31,151,20,140,9,125,0,105,7,100,15,114,20,123,25,128,29,131,33,132,37,131,39,128,42,123,43,115,44,104,44,93,46,61,55,34,72,13,97,0,133,-4,172,3,200,26,217,58,2 [...]
+20,123,25,128,31,151,31,151,25,128,29,131,31,151,29,131,33,132,33,132,37,131,43,158,43,158,37,131,39,128,43,158,39,128,42,123,0,105,7,100,9,125,9,125,7,100,15,114,9,125,15,114,20,140,20,140,15,114,20,123,20,140,20,123,31,151,44,104,46,61,55,160,55,160,46,61,55,34,55,160,55,34,67,159,67,159,55,34,72,13,67,159,72,13,76,154,76,154,72,13,87,66,76,154,87,66,85,84,85,84,85,110,84,131,85,84,84,131,81,145,85,84,81,145,76,154,121,342,119,323,135,320,121,342,135,320,144,338,144,338,135,320,149,310 [...]
+176,342,134,342,134,230,126,230,86,224,55,206,32,180,19,149,15,114,19,79,33,47,55,20,85,2,123,-4,134,-4,134,-107,176,-107,176,-4,223,2,257,21,280,48,292,81,296,116,294,143,286,168,272,190,254,208,230,222,221,225,211,228,189,230,176,230,16383,16383,176,9,176,216,203,210,225,193,240,168,249,137,252,102,249,73,243,48,231,27,214,14,191,9,16383,16383,135,9,125,10,114,13,104,18,95,25,86,34,77,51,69,70,64,91,61,113,60,137,62,164,70,186,82,202,99,212,120,216,135,216,
+296,116,294,143,292,81,292,81,294,143,286,168,292,81,286,168,280,48,280,48,286,168,272,190,280,48,272,190,257,21,257,21,272,190,254,208,257,21,254,208,252,102,221,225,225,193,230,222,230,222,225,193,240,168,230,222,240,168,254,208,254,208,240,168,249,137,254,208,249,137,252,102,211,228,200,229,203,210,211,228,203,210,225,193,211,228,225,193,221,225,200,229,189,230,203,210,203,210,189,230,176,230,203,210,176,230,176,216,176,216,176,230,176,342,176,216,176,342,135,216,135,216,176,342,134,3 [...]
+363,183,363,225,77,225,53,219,33,204,18,183,8,160,3,137,11,137,18,152,27,164,36,174,48,181,61,183,84,183,76,169,69,153,64,137,61,120,60,103,64,64,76,34,92,12,112,0,134,-4,153,-2,169,3,182,12,193,26,201,43,210,25,221,12,233,2,247,-2,261,-4,286,0,309,12,327,33,339,63,343,102,342,119,340,136,336,153,329,169,320,183,16383,16383,279,183,285,171,291,155,295,138,297,120,298,103,297,76,293,51,286,29,275,15,258,9,246,12,236,20,226,33,219,51,215,74,218,82,220,90,222,99,224,115,223,126,221,138,217, [...]
+11,137,18,152,18,183,18,183,18,152,27,164,18,183,27,164,33,204,33,204,27,164,36,174,33,204,36,174,53,219,53,219,36,174,48,181,53,219,48,181,61,183,77,225,61,183,84,183,77,225,84,183,363,225,363,225,84,183,125,183,363,225,125,183,279,183,8,160,3,137,11,137,8,160,11,137,18,183,108,137,112,153,84,183,84,183,112,153,118,169,84,183,118,169,125,183,108,52,112,0,115,30,115,30,112,0,134,-4,115,30,134,-4,126,15,126,15,134,-4,143,9,156,12,143,9,153,-2,156,12,153,-2,169,3,105,99,92,12,106,76,106,76 [...]
+257,225,206,225,111,104,110,104,112,114,114,125,115,138,117,150,117,160,115,183,108,202,97,217,82,226,64,230,53,229,43,225,35,219,29,210,27,198,28,193,31,188,35,184,40,181,46,180,54,181,60,184,63,188,67,191,71,192,81,190,89,184,95,174,99,162,100,148,99,136,98,121,96,107,94,94,91,85,21,0,73,0,170,121,171,121,168,111,166,100,164,88,163,76,162,65,164,46,170,27,180,11,194,0,214,-4,225,-3,236,0,244,5,250,14,252,26,251,32,248,37,244,41,239,43,233,44,225,43,219,40,213,34,209,33,199,35,191,40,18 [...]
+95,174,97,217,89,184,89,184,97,217,82,226,89,184,82,226,81,190,81,190,82,226,71,192,67,191,71,192,82,226,67,191,82,226,64,230,206,225,111,104,170,121,170,121,111,104,94,94,170,121,94,94,91,85,91,85,21,0,73,0,112,114,114,125,115,183,115,183,114,125,115,138,115,183,115,138,117,160,117,160,115,138,117,150,110,104,112,114,115,183,110,104,115,183,108,202,110,104,108,202,100,148,110,104,100,148,99,136,110,104,99,136,98,121,110,104,98,121,96,107,110,104,96,107,94,94,110,104,94,94,111,104,191,40 [...]
+213,-107,214,-103,216,-93,217,-89,217,-86,202,-54,166,-40,119,-30,75,-8,44,40,45,40,55,24,69,11,86,2,106,-2,131,-4,166,1,195,18,217,44,230,75,235,110,230,150,217,183,195,208,166,224,129,230,83,221,50,197,29,163,18,126,15,89,15,69,16,49,18,29,22,10,28,-6,65,-50,110,-71,154,-79,189,-88,205,-107,16383,16383,190,108,188,82,183,55,173,32,157,15,133,9,105,17,85,37,70,66,62,101,60,137,63,166,71,188,83,203,100,213,120,216,141,210,160,195,175,171,186,142,190,108,
+28,-6,65,-50,44,40,44,40,65,-50,75,-8,75,-8,65,-50,110,-71,75,-8,110,-71,119,-30,119,-30,110,-71,154,-79,119,-30,154,-79,166,-40,166,-40,154,-79,189,-88,166,-40,189,-88,202,-54,202,-54,189,-88,205,-107,202,-54,205,-107,217,-86,217,-86,205,-107,213,-107,217,-86,213,-107,214,-103,55,24,69,11,60,137,60,137,63,166,50,197,50,197,63,166,71,188,50,197,71,188,83,221,83,221,71,188,83,203,83,221,83,203,129,230,129,230,83,203,100,213,129,230,100,213,120,216,120,216,141,210,129,230,129,230,141,210,1 [...]
+196,56,183,41,169,29,155,22,139,17,123,16,100,21,82,35,68,56,60,82,57,112,155,112,155,127,57,127,61,151,69,175,82,196,99,210,119,215,142,212,158,203,169,191,177,177,183,162,191,162,184,230,176,230,174,224,173,222,171,220,167,220,160,221,152,223,144,226,133,229,118,230,82,223,53,205,31,178,17,145,12,108,17,74,30,44,50,18,78,1,112,-4,136,-1,157,5,176,17,191,33,204,52,
+155,112,155,127,57,112,57,112,57,127,53,205,53,205,57,127,61,151,53,205,61,151,82,223,82,223,61,151,69,175,82,223,69,175,82,196,68,56,78,1,82,35,82,35,78,1,112,-4,82,35,112,-4,100,21,100,21,112,-4,123,16,139,17,123,16,136,-1,139,17,136,-1,157,5,60,82,57,112,50,18,60,82,50,18,78,1,60,82,78,1,68,56,12,108,17,74,17,145,17,145,17,74,30,44,17,145,30,44,31,178,31,178,30,44,50,18,31,178,50,18,53,205,53,205,50,18,57,112,158,203,169,191,160,221,160,221,169,191,167,220,171,220,167,220,169,191,171, [...]
+350,0,350,9,337,12,327,17,319,26,311,38,304,55,180,337,171,337,68,93,52,58,41,34,31,20,19,13,4,9,4,0,104,0,104,9,91,10,81,12,74,16,70,22,69,30,69,34,70,38,71,43,72,47,74,51,97,108,228,108,248,61,254,45,256,38,257,31,257,23,256,21,255,18,251,14,247,12,239,10,232,10,223,9,223,0,16383,16383,220,128,105,128,162,266,
+52,58,70,22,69,30,69,30,69,34,68,93,68,93,69,34,70,38,68,93,70,38,71,43,243,11,239,10,350,0,350,0,239,10,232,10,350,0,232,10,223,9,72,47,74,51,171,337,171,337,74,51,97,108,171,337,97,108,105,128,105,128,97,108,228,108,105,128,228,108,220,128,220,128,228,108,304,55,220,128,304,55,180,337,256,21,255,18,350,0,350,0,255,18,253,16,350,0,253,16,251,14,251,14,247,12,350,0,350,0,247,12,243,11,257,26,350,0,327,17,257,26,327,17,319,26,257,26,319,26,311,38,257,26,311,38,304,55,257,26,304,55,257,31, [...]
+108,183,108,294,109,301,111,306,114,310,119,311,126,312,188,312,202,311,217,307,230,300,242,287,251,267,252,263,253,258,255,254,256,250,256,247,268,247,266,331,9,331,9,321,30,320,44,315,52,308,56,295,57,275,57,56,56,37,52,24,43,16,29,11,9,9,9,0,169,0,209,4,242,16,267,35,283,60,289,91,280,132,256,159,223,174,185,181,146,183,16383,16383,108,163,138,163,166,161,191,154,212,141,226,120,231,89,226,59,212,39,190,27,162,21,131,19,120,20,113,22,110,26,108,33,108,41,
+52,24,43,16,169,0,169,0,43,16,29,11,169,0,29,11,9,9,44,315,52,308,266,331,266,331,52,308,119,311,266,331,119,311,126,312,266,331,126,312,188,312,266,331,188,312,202,311,217,307,230,300,266,331,266,331,230,300,242,287,266,331,242,287,251,267,251,267,252,263,266,331,266,331,252,263,253,258,266,331,253,258,255,254,266,331,255,254,256,250,266,331,256,250,256,247,266,331,256,247,268,247,57,275,108,33,108,41,108,183,108,163,138,163,108,183,138,163,146,183,146,183,138,163,166,161,146,183,166,16 [...]
+212,180,226,183,237,187,245,190,253,195,260,200,267,208,273,218,277,229,280,240,281,252,275,281,259,303,233,318,196,328,150,331,9,331,9,321,30,320,44,316,52,308,56,295,57,275,57,56,56,37,52,24,43,16,30,11,9,9,9,0,178,0,218,4,251,17,276,37,292,63,297,94,296,107,293,120,289,131,282,142,273,151,264,159,255,165,244,171,230,175,212,179,16383,16383,108,188,108,296,109,302,110,307,113,310,116,311,121,312,141,312,173,310,198,302,215,290,226,273,229,250,226,228,217,210,203,198,182,191,155,188,163 [...]
+52,24,43,16,178,0,178,0,43,16,30,11,178,0,30,11,9,9,56,295,57,275,113,310,56,295,113,310,150,331,150,331,113,310,116,311,150,331,116,311,121,312,150,331,121,312,141,312,150,331,141,312,173,310,208,31,195,25,218,4,218,4,195,25,180,21,218,4,180,21,178,0,178,0,180,21,162,19,178,0,162,19,140,19,140,19,127,20,178,0,178,0,127,20,119,22,178,0,119,22,56,37,56,37,119,22,57,56,259,303,233,318,237,187,237,187,233,318,229,250,237,187,229,250,226,228,237,187,226,228,226,183,226,183,226,228,217,210,22 [...]
+272,242,270,331,9,331,9,321,28,320,41,315,48,307,52,294,53,275,53,57,52,37,48,24,41,16,28,12,9,9,9,0,150,0,150,9,130,12,117,16,109,24,105,37,104,56,104,302,106,307,109,310,114,312,192,312,206,311,221,307,234,300,246,286,255,267,256,262,258,256,259,250,260,245,260,242,
+48,24,41,16,150,0,150,0,41,16,28,12,150,0,28,12,9,9,52,294,53,275,109,310,52,294,109,310,48,307,48,307,109,310,114,312,48,307,114,312,270,331,270,331,114,312,122,312,221,307,234,300,270,331,270,331,234,300,246,286,270,331,246,286,255,267,255,267,256,262,270,331,270,331,256,262,258,256,270,331,258,256,259,250,270,331,259,250,260,245,270,331,260,245,260,242,270,331,260,242,272,242,270,331,122,312,192,312,270,331,192,312,206,311,270,331,206,311,221,307,117,16,109,24,53,57,53,57,109,24,105,3 [...]
+323,-75,323,9,303,11,291,17,283,27,279,40,278,57,278,274,280,293,283,307,291,315,304,319,323,321,323,331,47,331,47,321,62,320,75,316,83,308,88,295,90,275,87,172,79,97,65,46,45,18,17,9,7,9,7,-75,19,-75,19,-72,20,-67,21,-60,23,-54,24,-49,32,-29,43,-15,56,-5,71,0,259,0,274,-5,287,-15,298,-29,306,-49,307,-54,308,-60,309,-67,310,-72,311,-75,16383,16383,228,41,227,33,225,27,222,22,217,20,209,19,76,19,91,48,101,88,108,141,112,209,113,294,113,303,115,308,119,311,124,312,210,312,217,311,222,310,2 [...]
+20,-67,21,-60,17,9,17,9,21,-60,23,-54,17,9,23,-54,24,-49,24,-49,32,-29,45,18,45,18,32,-29,43,-15,45,18,43,-15,56,-5,62,320,75,316,323,331,323,331,75,316,124,312,323,331,124,312,131,312,323,331,131,312,210,312,323,331,210,312,217,311,87,172,91,48,90,275,90,275,91,48,113,303,113,303,91,48,113,294,71,0,87,0,76,19,71,0,76,19,79,97,79,97,76,19,91,48,79,97,91,48,87,172,65,46,45,18,56,-5,65,46,56,-5,71,0,65,46,71,0,79,97,45,18,17,9,24,-49,17,9,7,9,19,-75,17,9,19,-75,19,-72,17,9,19,-72,20,-67,32 [...]
+304,84,290,84,276,57,260,38,239,27,211,21,174,19,137,19,122,21,113,25,107,32,105,42,105,164,181,164,203,162,218,158,227,150,234,136,238,115,249,115,249,232,238,232,234,211,227,198,218,189,203,185,181,184,105,184,105,294,106,302,108,307,111,310,116,312,189,312,218,311,239,306,252,297,261,282,266,259,278,259,276,331,11,331,11,321,30,320,43,315,50,307,54,294,55,275,55,57,54,37,50,24,43,16,30,12,11,9,11,0,281,0,
+50,24,43,16,281,0,281,0,43,16,30,12,281,0,30,12,11,9,54,294,55,275,111,310,54,294,111,310,50,307,50,307,111,310,116,312,50,307,116,312,276,331,276,331,116,312,123,312,50,24,122,21,54,37,54,37,122,21,113,25,54,37,113,25,55,57,55,57,113,25,107,32,55,57,107,32,55,275,55,275,107,32,105,42,55,275,105,42,105,294,105,184,105,164,181,164,105,184,181,164,181,184,203,185,181,184,203,162,203,185,203,162,218,189,218,189,203,162,218,158,218,189,218,158,227,198,227,198,218,158,227,150,227,198,227,150, [...]
+507,0,507,9,476,18,453,32,435,52,417,79,394,113,382,130,370,144,359,155,345,164,330,172,329,173,342,181,354,193,364,209,373,228,382,251,388,266,394,280,401,293,410,301,419,305,425,302,430,295,435,286,443,279,457,276,466,278,473,283,478,289,481,297,482,305,480,315,475,324,467,331,456,336,442,338,419,335,401,325,388,309,376,290,367,267,356,239,345,216,331,197,310,185,280,181,280,293,283,307,291,315,304,319,325,321,325,331,186,331,186,321,206,320,220,315,227,307,230,294,231,275,231,181,203, [...]
+75,52,57,32,99,0,99,0,57,32,35,18,99,0,35,18,4,9,75,286,80,295,91,335,91,335,80,295,85,302,91,335,85,302,91,305,91,305,100,301,109,325,109,325,100,301,109,293,109,325,109,293,115,280,44,278,53,276,54,336,54,336,53,276,67,279,54,336,67,279,68,338,68,338,67,279,75,286,68,338,75,286,91,335,28,305,29,297,30,315,30,315,29,297,32,289,30,315,32,289,35,324,35,324,32,289,37,283,35,324,37,283,43,331,43,331,37,283,44,278,43,331,44,278,54,336,115,280,122,266,123,309,123,309,122,266,128,251,123,309,1 [...]
+177,175,201,180,222,192,240,208,251,229,256,253,252,281,239,304,217,322,185,334,142,338,131,338,121,337,111,335,100,333,89,330,83,328,67,324,60,322,54,321,49,322,44,324,40,328,37,332,35,338,25,338,23,220,35,220,43,253,56,280,76,301,101,314,131,319,156,316,176,308,191,294,201,277,204,257,204,245,201,232,196,219,188,207,175,196,165,191,155,187,143,185,127,183,104,183,104,163,128,163,146,161,160,158,172,153,184,146,194,138,202,129,209,118,213,105,215,91,211,64,201,43,183,28,159,18,128,15,10 [...]
+40,328,43,253,44,324,44,324,43,253,56,280,44,324,56,280,49,322,49,322,56,280,54,321,60,322,54,321,56,280,60,322,56,280,76,301,201,232,196,219,201,180,201,180,196,219,188,207,201,180,188,207,177,175,177,175,188,207,175,196,177,175,175,196,177,174,177,174,175,196,172,153,172,153,175,196,165,191,172,153,165,191,160,158,160,158,165,191,155,187,160,158,155,187,146,161,146,161,155,187,143,185,146,161,143,185,128,163,128,163,143,185,127,183,128,163,127,183,104,183,23,65,32,35,44,47,44,47,32,35, [...]
+352,0,352,9,333,12,320,17,312,25,309,37,307,55,307,274,309,293,312,307,320,315,333,319,352,321,352,331,212,331,212,321,230,319,242,315,251,309,255,299,257,285,105,82,105,274,106,294,110,307,118,315,131,319,150,321,150,331,9,331,9,321,29,319,42,315,50,307,53,294,54,274,54,61,53,39,50,25,42,16,29,12,9,9,9,0,149,0,148,9,131,11,118,16,110,23,106,33,105,48,257,252,257,62,256,41,252,26,245,17,232,12,213,9,213,0,
+50,25,42,16,149,0,149,0,42,16,29,12,149,0,29,12,9,9,257,285,105,82,105,48,105,48,105,274,54,274,54,274,105,274,106,294,54,274,106,294,110,307,150,331,9,331,29,319,150,331,29,319,42,315,150,331,42,315,50,307,150,331,50,307,53,294,150,331,53,294,118,315,150,331,118,315,131,319,150,331,131,319,150,321,54,274,110,307,118,315,54,274,118,315,53,294,252,26,245,17,352,0,352,0,245,17,232,12,352,0,232,12,213,9,242,315,251,309,352,331,352,331,251,309,255,299,352,331,255,299,257,285,257,285,257,252, [...]
+248,424,246,436,242,445,235,452,227,456,219,458,211,456,208,453,206,450,205,445,207,438,213,434,225,430,227,425,226,418,221,413,212,408,199,406,180,405,162,406,149,408,140,413,135,418,134,425,136,430,148,434,154,438,156,445,156,450,154,453,151,456,148,457,144,458,135,456,127,452,120,445,115,436,113,424,117,408,129,395,145,386,163,380,180,378,198,380,216,385,232,395,243,407,248,424,16383,16383,352,0,352,9,333,12,320,17,312,25,309,37,307,55,307,274,309,293,312,307,320,315,333,319,352,321,3 [...]
+149,408,140,413,145,386,145,386,140,413,135,418,145,386,135,418,129,395,129,395,135,418,134,425,135,456,134,425,136,430,135,456,136,430,144,458,144,458,136,430,142,432,144,458,142,432,148,434,148,457,148,434,151,456,151,456,148,434,154,438,151,456,154,438,154,453,154,453,154,438,156,445,154,453,156,445,156,450,129,395,134,425,135,456,129,395,135,456,127,452,129,395,127,452,120,445,129,395,120,445,117,408,115,436,113,424,117,408,115,436,117,408,120,445,149,408,163,380,162,406,162,406,163, [...]
+343,0,343,9,321,13,312,17,302,23,292,30,282,40,271,54,259,71,246,92,230,114,218,131,206,145,193,155,180,164,164,171,164,172,178,181,190,193,201,208,211,227,220,251,225,266,232,281,239,294,247,303,257,306,263,303,267,296,272,287,281,280,294,277,303,279,310,284,315,291,318,299,319,306,317,317,313,325,305,332,295,337,281,338,257,335,239,325,224,309,213,290,204,267,196,245,187,226,176,209,162,195,142,185,137,183,131,182,124,181,106,181,106,274,107,293,110,307,117,315,130,319,151,321,151,331, [...]
+151,0,151,9,132,12,151,0,132,12,119,16,151,0,119,16,54,42,151,0,54,42,51,27,151,0,51,27,43,17,151,0,43,17,29,12,151,0,29,12,9,9,151,0,9,9,9,0,55,275,107,36,106,55,106,181,106,161,113,161,55,275,106,55,106,181,106,181,113,161,116,181,116,181,113,161,119,160,116,181,119,160,124,181,124,181,119,160,125,158,124,181,125,158,131,182,131,182,125,158,130,156,131,182,130,156,134,154,134,154,140,149,137,183,137,183,140,149,142,185,162,195,142,185,149,140,162,195,149,140,160,126,55,65,54,42,119,16, [...]
+332,0,332,9,313,12,300,17,292,25,288,37,287,55,287,274,288,293,292,307,300,315,313,319,332,321,332,331,65,331,65,321,80,320,93,316,101,308,107,295,108,275,108,112,105,78,100,47,89,26,73,17,65,21,54,43,46,53,32,57,25,56,18,53,11,48,6,40,4,30,7,14,14,4,25,-2,39,-5,55,-6,92,2,114,27,126,60,130,97,131,131,131,292,132,300,133,305,136,309,141,311,148,312,219,312,226,311,231,309,234,305,236,300,237,292,237,63,236,41,232,26,225,17,212,12,193,9,193,0,
+108,112,105,78,114,27,114,27,105,78,100,47,114,27,100,47,92,2,92,2,100,47,89,26,92,2,89,26,73,17,73,17,65,21,92,2,92,2,65,21,55,-6,107,295,108,275,136,309,107,295,136,309,101,308,101,308,136,309,141,311,101,308,141,311,332,331,332,331,141,311,148,312,232,26,225,17,332,0,332,0,225,17,212,12,332,0,212,12,193,9,332,331,148,312,219,312,332,331,219,312,226,311,332,331,226,311,231,309,332,331,231,309,234,305,332,331,234,305,236,300,332,331,236,300,237,292,332,331,237,292,300,315,332,331,300,31 [...]
+435,0,435,9,417,12,404,17,397,25,393,38,392,56,392,275,393,294,397,307,404,316,417,320,435,321,435,331,335,331,225,80,109,331,11,331,11,321,31,319,45,315,53,307,57,294,58,275,58,75,57,47,53,29,44,18,30,12,9,9,9,0,127,0,127,9,107,12,94,18,85,29,81,48,80,75,80,275,206,0,213,0,340,286,340,40,336,26,328,17,315,12,296,9,296,0,
+53,29,44,18,127,0,127,0,44,18,30,12,127,0,30,12,9,9,336,26,328,17,435,0,435,0,328,17,315,12,435,0,315,12,296,9,417,320,435,321,435,331,417,320,435,331,404,316,404,316,435,331,340,286,404,316,340,286,397,307,397,307,340,286,393,294,404,17,397,25,340,61,340,61,397,25,393,38,340,61,393,38,340,286,340,286,393,38,392,56,340,286,392,56,392,275,206,0,213,0,225,80,225,80,213,0,340,286,225,80,340,286,335,331,335,331,340,286,435,331,109,331,11,331,31,319,109,331,31,319,45,315,109,331,45,315,53,307 [...]
+352,0,352,9,333,12,320,17,312,25,309,37,307,55,307,274,309,293,312,307,320,315,333,319,352,321,352,331,213,331,213,321,232,319,245,315,252,307,256,294,257,274,257,180,105,180,105,274,106,294,110,307,118,315,130,319,149,321,149,331,9,331,9,321,29,319,42,315,50,307,53,294,54,274,54,61,53,39,50,25,42,16,29,12,9,9,9,0,149,0,149,9,130,12,118,17,110,25,106,38,105,56,105,157,257,157,257,62,256,41,252,26,245,17,232,12,213,9,213,0,
+50,25,42,16,149,0,149,0,42,16,29,12,149,0,29,12,9,9,149,331,9,331,29,319,149,331,29,319,42,315,149,331,42,315,50,307,149,331,50,307,53,294,149,331,53,294,118,315,149,331,118,315,130,319,149,331,130,319,149,321,54,274,106,38,105,56,105,180,105,157,257,157,105,180,257,157,257,180,257,180,257,157,312,25,257,180,312,25,309,37,54,274,105,56,105,274,54,274,105,274,106,294,54,274,106,294,110,307,54,274,110,307,118,315,54,274,118,315,53,294,252,26,245,17,352,0,352,0,245,17,232,12,352,0,232,12,21 [...]
+345,166,337,222,316,269,281,306,236,330,181,338,127,330,82,307,47,271,26,224,18,167,26,109,47,61,82,24,127,1,181,-6,235,1,280,24,315,60,337,108,345,166,16383,16383,288,169,286,134,281,103,273,76,261,53,247,35,235,26,223,19,210,15,197,12,182,11,168,12,155,15,143,19,131,25,120,33,103,52,91,75,82,102,77,132,75,166,76,194,81,222,88,247,98,269,109,286,122,298,135,308,150,314,165,318,181,320,194,319,207,316,220,311,231,305,243,296,258,279,271,257,280,231,286,201,288,169,
+150,314,181,338,135,308,135,308,181,338,127,330,135,308,127,330,122,298,122,298,127,330,109,286,98,269,109,286,127,330,98,269,127,330,82,307,82,102,82,24,91,75,91,75,82,24,127,1,91,75,127,1,103,52,103,52,127,1,120,33,131,25,120,33,127,1,131,25,127,1,181,-6,236,330,181,338,194,319,194,319,181,338,181,320,165,318,181,320,181,338,165,318,181,338,150,314,223,19,210,15,235,1,235,1,210,15,197,12,235,1,197,12,182,11,182,11,168,12,181,-6,181,-6,168,12,155,15,181,-6,155,15,143,19,207,316,220,311, [...]
+353,0,353,9,333,12,321,17,313,25,309,37,308,55,308,274,309,293,313,307,321,315,334,319,353,321,353,331,9,331,9,321,29,319,42,315,50,307,53,294,54,274,54,61,53,39,50,25,42,16,29,12,9,9,9,0,149,0,149,9,130,12,118,17,110,25,106,38,105,56,105,300,107,306,111,309,116,311,124,312,238,312,246,311,251,309,255,306,257,300,257,62,256,41,253,26,246,17,233,12,213,9,213,0,
+50,25,42,16,149,0,149,0,42,16,29,12,149,0,29,12,9,9,42,315,50,307,353,331,353,331,50,307,116,311,353,331,116,311,124,312,353,331,124,312,238,312,353,331,238,312,246,311,253,26,246,17,353,0,353,0,246,17,233,12,353,0,233,12,213,9,353,331,246,311,251,309,353,331,251,309,255,306,353,331,255,306,257,300,353,331,257,300,257,292,353,331,257,292,321,315,353,331,321,315,334,319,353,331,334,319,353,321,308,55,308,274,257,292,257,292,308,274,309,293,257,292,309,293,313,307,321,17,313,25,257,62,257, [...]
+9,331,9,321,28,319,40,315,47,307,51,294,51,39,48,25,41,16,29,12,9,9,9,0,150,0,150,9,129,12,115,16,107,24,104,37,103,56,103,146,110,145,115,145,120,144,132,144,161,145,184,147,204,153,221,161,239,175,249,185,257,197,263,210,266,225,267,240,266,254,263,268,258,280,252,291,243,300,227,310,209,319,187,325,162,329,134,331,16383,16383,103,294,103,301,105,306,108,310,113,311,120,312,156,309,182,302,200,287,210,266,213,238,210,213,199,192,182,177,158,167,128,164,118,164,113,165,109,165,103,166,
+113,311,120,312,120,312,134,331,120,312,156,309,134,331,156,309,162,329,162,329,156,309,182,302,162,329,182,302,187,325,187,325,182,302,200,287,187,325,200,287,209,319,209,319,200,287,210,266,209,319,210,266,227,310,227,310,210,266,213,238,227,310,213,238,221,161,221,161,210,213,204,153,204,153,210,213,199,192,204,153,199,192,184,147,184,147,199,192,182,177,184,147,182,177,161,145,161,145,182,177,158,167,161,145,158,167,132,144,132,144,158,167,128,164,132,144,128,164,125,144,125,144,128, [...]
+311,65,289,47,269,32,248,23,226,17,201,15,180,17,161,21,143,28,126,38,112,51,99,68,89,88,82,112,77,140,76,171,81,219,96,260,121,291,154,311,196,318,215,316,232,311,248,304,263,293,276,280,283,272,289,263,294,252,299,240,302,224,314,224,310,338,300,338,297,332,289,324,284,322,278,321,273,322,266,324,258,326,244,330,232,333,208,337,196,338,185,338,157,336,131,330,106,320,83,305,63,286,47,266,35,243,26,218,20,191,18,162,20,133,26,106,36,80,49,57,66,37,85,22,107,9,131,0,157,-4,184,-6,218,-4, [...]
+66,37,77,140,76,171,76,171,83,305,66,37,66,37,83,305,63,286,66,37,63,286,49,57,49,57,63,286,47,266,49,57,47,266,36,80,36,80,47,266,35,243,36,80,35,243,26,106,26,106,35,243,26,218,26,106,26,218,20,133,20,133,26,218,20,191,20,133,20,191,18,162,82,112,85,22,89,88,89,88,85,22,107,9,89,88,107,9,99,68,99,68,107,9,112,51,126,38,112,51,131,0,126,38,131,0,143,28,143,28,131,0,157,-4,143,28,157,-4,161,21,161,21,157,-4,184,-6,161,21,184,-6,180,17,180,17,184,-6,201,15,226,17,201,15,218,-4,226,17,218, [...]
+296,246,292,331,18,331,15,246,27,246,33,274,42,292,54,303,73,309,100,310,130,310,130,61,129,39,125,25,117,16,104,12,83,9,83,0,229,0,229,9,208,11,194,16,186,23,182,36,181,55,181,310,210,310,237,309,256,303,269,292,277,274,284,246,
+292,331,18,331,73,309,292,331,73,309,100,310,292,331,100,310,130,310,292,331,130,310,181,310,292,331,181,310,210,310,292,331,210,310,237,309,292,331,237,309,256,303,292,331,256,303,269,292,292,331,269,292,277,274,292,331,277,274,284,246,292,331,284,246,296,246,194,16,186,23,130,61,130,61,186,23,182,36,130,61,182,36,130,310,130,310,182,36,181,55,130,310,181,55,181,310,18,331,15,246,27,246,18,331,27,246,33,274,18,331,33,274,42,292,18,331,42,292,54,303,18,331,54,303,73,309,229,0,229,9,208,1 [...]
+347,331,243,331,243,322,254,320,263,316,269,312,273,306,274,299,273,292,271,284,268,273,263,260,257,245,204,118,132,245,123,262,110,288,107,297,106,303,107,309,112,314,119,318,129,321,142,322,142,331,7,331,7,322,15,320,27,316,37,310,42,305,46,300,51,294,61,278,181,67,172,53,163,41,154,33,146,28,138,27,136,27,133,28,131,29,127,30,124,32,118,35,108,39,104,40,99,41,92,40,85,37,80,32,77,26,76,20,78,10,84,3,93,-2,104,-5,117,-6,132,-4,147,0,161,9,175,22,188,40,194,51,202,65,210,81,219,100,228, [...]
+21,318,27,316,142,331,142,331,27,316,32,313,142,331,32,313,37,310,37,310,42,305,142,331,142,331,42,305,46,300,142,331,46,300,51,294,61,278,181,67,107,297,61,278,107,297,106,303,106,303,107,309,61,278,61,278,107,309,112,314,61,278,112,314,56,286,142,331,51,294,56,286,142,331,56,286,112,314,142,331,112,314,119,318,142,331,119,318,129,321,142,331,129,321,142,322,15,320,21,318,142,331,15,320,142,331,7,331,15,320,7,331,7,322,133,28,131,29,132,-4,132,-4,131,29,127,30,132,-4,127,30,124,32,124,3 [...]
+218,290,219,301,223,310,232,316,247,320,269,321,269,331,116,331,116,321,138,320,152,317,161,311,165,302,166,290,166,280,124,276,84,263,50,241,27,209,19,165,24,128,41,97,69,72,107,57,158,51,166,51,166,37,164,27,158,19,148,14,134,10,116,9,116,0,269,0,269,9,248,11,233,14,224,19,219,27,218,38,218,51,230,51,265,56,302,69,334,91,357,123,366,165,357,209,333,241,300,263,260,276,218,280,16383,16383,217,262,251,256,278,240,296,216,307,188,311,159,305,128,291,103,270,85,244,74,217,70,16383,16383,16 [...]
+269,321,269,321,247,320,247,320,269,321,269,331,247,320,269,331,232,316,232,316,269,331,166,290,232,316,166,290,223,310,223,310,166,290,167,262,219,27,167,262,167,70,219,27,167,70,224,19,224,19,167,70,166,51,224,19,166,51,166,37,218,38,217,70,167,262,167,262,217,70,217,262,167,262,217,262,218,290,218,290,217,262,218,280,219,301,223,310,167,262,219,301,167,262,218,290,166,290,269,331,165,302,269,331,116,331,138,320,269,331,138,320,152,317,269,331,152,317,161,311,269,331,161,311,165,302,91 [...]
+352,0,352,9,337,12,326,16,316,22,306,32,296,46,200,184,272,272,289,292,303,305,316,314,330,319,348,321,348,331,229,331,229,321,243,320,253,319,259,316,262,311,263,305,262,301,260,296,256,290,250,282,243,272,187,202,165,234,151,255,139,272,130,286,125,297,123,306,124,312,127,316,132,319,139,320,147,320,161,321,161,331,11,331,11,321,28,319,43,312,58,299,77,276,102,242,155,164,77,66,57,42,42,26,30,17,18,12,4,9,4,0,121,0,121,9,105,11,95,13,88,17,84,21,83,26,84,31,87,38,92,46,99,57,109,70,169 [...]
+30,17,121,0,42,26,42,26,121,0,88,17,42,26,88,17,57,42,57,42,88,17,84,21,57,42,84,21,83,26,83,26,84,31,77,66,77,66,84,31,87,38,77,66,87,38,155,164,155,164,87,38,92,46,155,164,92,46,99,57,102,242,155,164,125,297,102,242,125,297,123,306,123,306,124,312,102,242,155,164,99,57,109,70,109,70,169,145,155,164,155,164,169,145,165,234,155,164,165,234,151,255,77,66,57,42,83,26,161,331,11,331,28,319,161,331,28,319,43,312,161,331,43,312,58,299,161,331,58,299,132,319,161,331,132,319,139,320,161,331,139 [...]
+348,-75,348,9,329,12,316,16,308,24,305,37,304,57,304,292,308,306,316,315,329,319,348,321,348,331,209,331,209,321,228,319,240,315,248,306,251,293,252,275,252,28,250,23,247,21,242,19,115,19,110,21,107,23,105,28,105,269,106,290,109,305,117,314,129,319,149,321,149,331,9,331,9,321,28,319,41,314,49,306,53,294,54,276,54,57,53,37,49,24,41,16,28,12,9,9,9,0,284,0,299,-5,312,-15,323,-29,331,-49,332,-54,333,-60,335,-67,335,-72,336,-75,
+49,24,41,16,268,0,268,0,41,16,28,12,268,0,28,12,9,9,149,331,9,331,28,319,149,331,28,319,41,314,149,331,41,314,49,306,149,331,49,306,53,294,149,331,53,294,117,314,149,331,117,314,129,319,149,331,129,319,149,321,110,21,107,23,54,57,54,57,107,23,105,28,54,57,105,28,54,276,54,276,105,28,105,34,54,276,105,34,105,269,54,276,105,269,106,290,54,276,106,290,109,305,54,276,109,305,117,314,54,276,117,314,53,294,329,319,348,321,348,331,329,319,348,331,316,315,316,315,348,331,251,293,316,315,251,293, [...]
+320,0,320,9,301,12,288,16,280,24,276,37,275,57,275,269,276,291,280,306,288,315,301,319,320,321,320,331,186,331,186,321,204,319,214,316,221,309,223,299,224,283,224,174,216,170,204,166,190,161,173,158,155,156,132,158,116,165,105,176,99,193,97,216,97,273,98,294,101,307,109,315,121,319,139,321,139,331,2,331,2,321,21,319,34,315,41,307,45,293,46,273,46,211,50,178,62,155,80,142,104,136,133,134,157,136,178,140,197,145,212,152,224,157,224,57,223,37,219,24,211,16,199,12,180,9,180,0,
+139,321,139,321,121,319,121,319,139,321,139,331,121,319,139,331,109,315,109,315,139,331,45,293,109,315,45,293,46,273,50,178,46,273,46,211,132,158,116,165,133,134,133,134,116,165,105,176,133,134,105,176,104,136,104,136,105,176,99,193,104,136,99,193,80,142,80,142,99,193,97,216,80,142,97,216,97,273,46,273,50,178,101,307,101,307,50,178,62,155,101,307,62,155,98,294,98,294,62,155,80,142,98,294,80,142,97,273,139,331,2,331,21,319,139,331,21,319,34,315,139,331,34,315,41,307,139,331,41,307,45,293, [...]
+483,0,483,9,463,12,450,16,443,24,439,37,438,57,438,270,439,292,443,306,450,315,463,319,483,321,483,331,343,331,344,321,362,319,375,315,383,306,386,293,387,275,387,28,385,23,382,21,377,19,282,19,277,21,274,23,272,27,272,269,273,290,276,305,283,314,296,319,315,321,315,331,183,331,183,321,200,319,210,314,217,306,220,294,220,28,218,23,215,21,210,19,120,19,115,21,112,23,110,28,110,269,111,291,114,306,120,315,131,320,147,321,147,331,15,331,15,321,34,319,46,314,54,306,58,294,59,276,59,57,58,37, [...]
+59,57,58,37,115,21,115,21,58,37,54,24,115,21,54,24,120,19,120,19,54,24,46,16,120,19,46,16,483,0,483,0,46,16,33,12,483,0,33,12,15,9,147,331,15,331,34,319,147,331,34,319,46,314,147,331,46,314,54,306,147,331,54,306,58,294,147,331,58,294,120,315,147,331,120,315,131,320,147,331,131,320,147,321,115,21,112,23,59,57,59,57,112,23,110,28,59,57,110,28,59,276,59,276,110,28,110,34,59,276,110,34,110,269,59,276,110,269,111,291,59,276,111,291,114,306,59,276,114,306,120,315,59,276,120,315,58,294,296,319, [...]
+483,-75,483,9,463,12,450,16,443,24,439,37,438,57,438,270,439,292,443,306,450,315,463,319,483,321,483,331,343,331,344,321,362,319,375,315,383,306,386,293,387,275,387,28,385,23,382,21,377,19,282,19,277,21,274,23,272,27,272,269,273,290,276,305,283,314,296,319,315,321,315,331,183,331,183,321,200,319,210,314,217,306,220,294,220,28,218,23,215,21,210,19,120,19,115,21,112,23,110,28,110,269,111,291,114,306,120,315,131,320,147,321,147,331,15,331,15,321,34,319,46,314,54,306,58,294,59,276,59,57,58,3 [...]
+59,57,58,37,115,21,115,21,58,37,54,24,115,21,54,24,120,19,120,19,54,24,46,16,120,19,46,16,402,0,402,0,46,16,33,12,402,0,33,12,15,9,147,331,15,331,34,319,147,331,34,319,46,314,147,331,46,314,54,306,147,331,54,306,58,294,147,331,58,294,120,315,147,331,120,315,131,320,147,331,131,320,147,321,115,21,112,23,59,57,59,57,112,23,110,28,59,57,110,28,59,276,59,276,110,28,110,34,59,276,110,34,110,269,59,276,110,269,111,291,59,276,111,291,114,306,59,276,114,306,120,315,59,276,120,315,58,294,296,319, [...]
+171,183,171,274,172,293,177,307,186,315,200,319,219,321,219,331,10,331,7,246,18,246,25,274,33,293,45,304,63,309,90,310,120,310,120,56,119,37,114,24,106,16,92,11,72,9,72,0,231,0,271,4,305,15,330,34,346,59,352,91,345,126,327,153,299,170,262,180,219,183,16383,16383,171,163,204,163,231,161,256,154,276,141,289,120,294,89,289,59,275,39,253,27,226,21,195,19,185,20,178,22,174,26,171,33,171,41,
+114,24,106,16,231,0,231,0,106,16,92,11,231,0,92,11,72,9,177,307,186,315,120,310,120,310,186,315,219,331,120,310,219,331,90,310,63,309,90,310,219,331,63,309,219,331,10,331,200,319,219,321,219,331,200,319,219,331,186,315,120,310,171,33,171,41,171,183,171,163,204,163,171,183,204,163,219,183,219,183,204,163,231,161,219,183,231,161,262,180,262,180,231,161,256,154,262,180,256,154,276,141,120,310,171,41,171,274,120,310,171,274,172,293,120,310,172,293,177,307,10,331,7,246,18,246,10,331,18,246,25 [...]
+432,0,432,9,414,12,401,17,393,25,389,38,388,57,388,274,389,294,393,307,401,315,414,319,432,321,432,331,292,331,292,321,312,319,325,315,332,307,336,294,337,274,337,61,336,39,333,25,325,16,312,12,292,9,292,0,16383,16383,108,183,108,274,110,293,115,307,123,315,137,319,156,321,156,331,9,331,9,321,30,320,44,316,52,308,56,295,57,275,57,56,56,37,52,24,43,16,30,11,9,9,9,0,170,0,210,4,244,15,268,34,284,59,290,91,283,126,265,153,238,170,201,180,158,183,16383,16383,108,163,142,163,170,161,194,154,2 [...]
+432,321,432,321,414,319,414,319,432,321,432,331,414,319,432,331,401,315,401,315,432,331,336,294,401,315,336,294,337,274,389,38,337,274,337,61,389,38,337,61,393,25,393,25,337,61,401,17,388,57,388,274,337,274,337,274,388,274,389,294,337,274,389,294,393,307,432,331,292,331,312,319,432,331,312,319,325,315,432,331,325,315,332,307,432,331,332,307,336,294,432,0,432,9,414,12,432,0,414,12,401,17,432,0,401,17,336,39,432,0,336,39,333,25,432,0,333,25,325,16,432,0,325,16,312,12,432,0,312,12,292,9,432 [...]
+108,183,108,274,110,293,115,307,123,315,137,319,156,321,156,331,9,331,9,321,30,320,44,316,52,308,56,295,57,275,57,56,56,37,52,24,43,16,30,11,9,9,9,0,170,0,210,4,243,15,268,34,284,59,289,91,283,126,265,153,237,170,201,180,158,183,16383,16383,108,163,142,163,170,161,194,154,214,141,227,120,232,89,227,59,213,39,193,27,166,21,134,19,123,20,115,22,111,26,109,33,108,41,
+52,24,43,16,170,0,170,0,43,16,30,11,170,0,30,11,9,9,156,331,9,331,30,320,156,331,30,320,44,316,156,331,44,316,52,308,156,331,52,308,56,295,156,331,56,295,123,315,156,331,123,315,137,319,156,331,137,319,156,321,57,275,109,33,108,41,108,183,108,163,142,163,108,183,142,163,158,183,158,183,142,163,170,161,158,183,170,161,201,180,201,180,170,161,194,154,201,180,194,154,214,141,57,275,108,41,108,274,57,275,108,274,110,293,57,275,110,293,115,307,57,275,115,307,123,315,57,275,123,315,56,295,57,5 [...]
+26,338,23,224,36,224,39,239,42,252,46,263,51,272,57,280,71,293,85,304,101,311,118,316,136,318,173,312,203,293,226,265,241,228,248,184,103,184,103,161,248,161,248,142,246,124,242,108,237,92,231,78,218,57,201,39,181,26,158,18,131,15,107,17,86,23,65,32,45,46,25,65,15,55,33,33,55,16,80,3,109,-4,141,-6,168,-4,194,0,218,9,240,22,258,37,275,57,288,79,298,104,304,131,306,160,305,188,299,215,290,240,278,263,263,284,244,304,222,319,198,330,173,336,147,338,136,338,124,337,113,336,101,333,90,330,83, [...]
+36,338,36,338,38,332,38,332,36,338,39,239,38,332,39,239,41,328,41,328,39,239,42,252,41,328,42,252,45,324,45,324,42,252,46,263,45,324,46,263,50,322,50,322,46,263,51,272,50,322,51,272,55,321,55,321,51,272,57,280,55,321,57,280,61,322,36,224,39,239,36,338,36,224,36,338,26,338,36,224,26,338,23,224,75,326,68,324,71,293,71,293,68,324,61,322,71,293,61,322,57,280,90,330,83,328,85,304,90,330,85,304,101,311,90,330,101,311,101,333,75,326,71,293,85,304,75,326,85,304,83,328,248,142,246,124,258,37,258, [...]
+105,180,105,274,106,294,110,307,118,315,130,319,149,321,149,331,9,331,9,321,29,319,42,315,50,307,53,294,54,274,54,61,53,39,50,25,42,16,29,12,9,9,9,0,149,0,149,9,130,12,118,17,110,25,106,38,105,56,105,157,149,157,157,102,177,57,207,22,245,0,291,-6,337,1,376,24,405,60,425,108,431,166,425,222,406,269,377,306,338,330,291,338,245,331,207,310,178,276,158,232,149,180,16383,16383,377,169,376,134,373,103,367,76,359,53,347,35,337,26,327,19,315,15,303,12,291,11,279,12,268,15,257,19,247,25,237,33,22 [...]
+50,25,42,16,149,0,149,0,42,16,29,12,149,0,29,12,9,9,149,331,9,331,29,319,149,331,29,319,42,315,149,331,42,315,50,307,149,331,50,307,53,294,149,331,53,294,118,315,149,331,118,315,130,319,149,331,130,319,149,321,158,232,149,180,149,157,149,157,149,180,105,180,149,157,105,180,105,157,106,38,105,56,54,274,106,38,54,274,54,61,54,274,105,56,105,274,54,274,105,274,106,294,54,274,106,294,110,307,54,274,110,307,118,315,54,274,118,315,53,294,149,0,149,9,130,12,149,0,130,12,118,17,149,0,118,17,53,3 [...]
+309,0,309,9,290,12,277,16,270,25,267,39,267,276,268,294,271,307,278,315,290,319,309,321,309,331,180,331,136,329,98,321,69,306,49,282,42,246,47,216,60,193,81,176,108,164,141,157,49,35,41,26,31,19,22,14,12,11,2,9,2,0,83,0,198,155,216,155,216,56,215,37,211,24,203,16,189,12,169,9,169,0,16383,16383,216,174,186,174,156,177,131,186,113,200,101,219,97,244,99,261,103,276,111,288,121,298,133,305,143,308,153,310,164,311,177,312,190,312,200,311,207,309,212,304,215,296,216,286,
+31,19,22,14,83,0,83,0,22,14,12,11,83,0,12,11,2,9,99,261,103,276,98,321,98,321,103,276,111,288,98,321,111,288,136,329,136,329,111,288,121,298,136,329,121,298,133,305,133,305,143,308,136,329,136,329,143,308,180,331,101,219,97,244,108,164,108,164,97,244,81,176,81,176,97,244,98,321,98,321,97,244,99,261,42,246,47,216,49,282,49,282,47,216,60,193,49,282,60,193,69,306,69,306,60,193,81,176,69,306,81,176,98,321,141,157,83,0,198,155,141,157,198,155,156,177,141,157,156,177,131,186,141,157,131,186,11 [...]
+223,33,218,29,210,25,206,24,201,23,196,25,192,28,189,35,187,44,186,56,186,152,185,168,184,181,181,191,176,199,170,208,162,215,152,222,140,226,127,229,111,230,98,229,85,227,73,224,63,220,54,215,44,208,37,200,32,192,29,183,28,175,29,167,33,161,37,156,43,153,50,152,57,153,63,156,68,161,71,167,73,172,72,178,72,182,71,185,70,189,70,194,71,201,76,207,83,212,93,215,104,217,117,215,129,210,138,202,144,190,146,173,146,146,116,135,93,126,76,118,63,112,54,105,42,97,33,87,25,75,20,62,18,47,21,29,28, [...]
+37,156,43,153,44,208,44,208,43,153,50,152,44,208,50,152,54,215,54,215,50,152,57,153,54,215,57,153,63,220,63,220,57,153,63,156,63,220,63,156,73,224,73,224,63,156,70,194,71,167,70,194,68,161,111,230,104,217,117,215,111,230,117,215,127,229,127,229,117,215,129,210,127,229,129,210,140,226,140,226,129,210,138,202,140,226,138,202,144,190,76,207,83,212,85,227,85,227,83,212,93,215,85,227,93,215,98,229,98,229,93,215,104,217,98,229,104,217,111,230,73,224,70,194,71,201,73,224,71,201,76,207,73,224,76 [...]
+42,174,47,203,59,230,77,253,100,270,129,278,142,279,169,279,182,280,194,283,210,293,220,306,226,320,229,333,230,343,220,343,217,332,212,325,205,320,195,318,183,317,150,317,94,304,57,269,34,223,23,172,20,127,24,87,36,52,57,22,87,2,127,-4,164,1,195,17,219,43,234,76,239,116,233,154,218,186,195,210,166,225,131,230,111,228,92,223,74,213,57,196,43,173,16383,16383,194,102,192,70,184,44,172,25,155,13,135,9,125,10,115,13,106,18,98,25,91,34,81,51,74,70,69,91,66,113,65,137,67,164,75,186,87,202,102, [...]
+169,279,183,317,156,279,156,279,183,317,150,317,156,279,150,317,142,279,142,279,150,317,129,278,100,270,129,278,150,317,100,270,150,317,94,304,229,333,230,343,226,320,226,320,230,343,220,343,226,320,220,343,220,306,220,306,220,343,217,332,220,306,217,332,212,325,210,293,220,306,212,325,210,293,212,325,205,320,210,293,205,320,195,318,210,293,195,318,194,283,169,279,182,280,183,317,183,317,182,280,194,283,183,317,194,283,195,318,42,174,47,203,57,269,57,269,47,203,59,230,57,269,59,230,94,30 [...]
+153,118,169,121,183,128,194,137,202,151,205,168,201,188,191,204,174,215,149,222,118,225,12,225,12,218,26,216,35,214,40,209,42,200,43,187,43,39,42,25,40,16,35,11,26,8,12,7,12,0,149,0,161,2,171,4,181,8,190,12,200,19,208,28,214,39,218,51,219,63,215,82,206,96,191,107,174,114,153,118,16383,16383,85,195,86,202,88,207,92,209,97,211,103,211,127,209,145,203,156,194,162,182,164,166,161,151,154,139,143,130,128,125,110,123,99,124,92,125,87,128,85,132,85,139,16383,16383,85,97,85,102,87,105,91,108,98, [...]
+40,16,35,11,137,0,137,0,35,11,26,8,137,0,26,8,12,7,86,202,88,207,43,187,43,187,88,207,92,209,43,187,92,209,118,225,118,225,92,209,97,211,118,225,97,211,103,211,103,211,127,209,118,225,118,225,127,209,149,222,159,98,170,84,174,114,174,114,170,84,174,62,174,114,174,62,174,63,174,63,174,62,181,8,181,8,174,62,171,4,171,4,174,62,170,42,171,4,170,42,161,2,161,2,170,42,160,28,161,2,160,28,149,0,149,0,160,28,146,19,149,0,146,19,137,0,137,0,146,19,127,15,137,0,127,15,106,14,106,14,98,15,137,0,137 [...]
+194,155,191,225,8,225,8,218,22,217,31,215,36,211,39,204,40,194,40,40,39,25,36,16,30,11,21,9,8,7,8,0,113,0,113,7,100,9,91,13,85,18,82,26,81,36,81,194,82,200,83,205,86,208,91,209,98,210,130,208,154,201,170,190,180,175,185,155,
+36,211,39,204,191,225,191,225,39,204,91,209,191,225,91,209,98,210,98,210,130,208,191,225,191,225,130,208,154,201,191,225,154,201,170,190,191,225,170,190,180,175,191,225,180,175,185,155,191,225,185,155,194,155,81,36,81,194,40,194,40,194,81,194,82,200,40,194,82,200,83,205,40,194,83,205,86,208,40,194,86,208,91,209,40,194,91,209,39,204,40,194,82,26,81,36,191,225,8,225,22,217,191,225,22,217,31,215,191,225,31,215,36,211,113,0,113,7,100,9,113,0,100,9,91,13,113,0,91,13,40,40,113,0,40,40,39,25,11 [...]
+219,225,21,225,21,218,34,216,44,212,51,206,55,197,56,183,56,99,55,66,51,40,42,22,28,11,7,7,7,-68,16,-68,26,-37,37,-17,47,-5,58,0,172,0,182,-5,191,-17,200,-37,210,-68,219,-68,219,7,206,9,197,11,192,16,189,25,189,198,192,207,198,213,206,216,219,218,16383,16383,147,41,146,30,143,23,139,18,133,15,126,14,58,14,64,28,68,43,71,59,73,75,73,190,74,199,76,205,80,209,85,210,92,211,135,211,141,209,145,205,146,199,147,190,
+34,216,44,212,219,225,219,225,44,212,85,210,219,225,85,210,92,211,219,225,92,211,127,211,219,225,127,211,135,211,126,14,58,14,68,0,126,14,68,0,161,0,126,14,161,0,133,15,147,190,161,0,189,198,189,198,161,0,172,0,189,198,172,0,189,183,189,183,172,0,182,-5,189,183,182,-5,189,41,189,41,182,-5,191,-17,189,41,191,-17,189,25,161,0,147,190,147,41,161,0,147,41,146,30,161,0,146,30,143,23,161,0,143,23,139,18,161,0,139,18,133,15,219,225,135,211,141,209,219,225,141,209,145,205,219,225,145,205,146,199 [...]
+210,82,196,63,182,48,167,39,150,33,132,31,102,37,80,53,66,77,58,106,55,137,209,137,208,152,205,165,202,176,197,186,192,195,181,207,169,217,156,224,140,228,123,230,88,224,59,207,37,182,24,148,19,108,23,70,35,39,55,15,81,0,114,-4,142,-1,167,9,188,26,205,49,219,79,16383,16383,56,151,61,172,69,190,80,203,93,211,109,214,126,211,139,203,148,191,154,173,158,151,
+80,53,66,77,81,0,81,0,66,77,58,106,81,0,58,106,55,15,55,15,58,106,55,137,56,151,55,137,209,137,56,151,209,137,158,151,158,151,209,137,169,217,140,228,123,230,126,211,126,211,123,230,109,214,93,211,109,214,123,230,93,211,123,230,88,224,156,224,140,228,148,191,156,224,148,191,154,173,156,224,154,173,158,151,156,224,158,151,169,217,140,228,126,211,139,203,140,228,139,203,148,191,56,151,61,172,59,207,59,207,61,172,69,190,59,207,69,190,88,224,88,224,69,190,80,203,88,224,80,203,93,211,37,182,2 [...]
+353,0,353,7,347,8,341,10,331,14,327,17,323,21,317,28,311,37,304,47,298,58,286,79,275,94,264,105,253,113,240,120,240,121,258,137,269,156,278,172,286,185,297,190,301,189,306,187,318,183,324,182,332,183,338,186,343,191,346,197,347,204,346,211,342,218,336,223,327,227,316,228,306,227,297,224,289,218,282,211,275,201,267,187,259,171,251,156,242,143,233,135,228,132,222,130,215,128,208,127,200,127,200,190,201,199,204,207,210,212,219,216,232,218,232,225,128,225,128,218,140,216,149,214,154,209,158, [...]
+25,12,19,10,73,0,73,0,19,10,14,8,73,0,14,8,7,7,50,36,44,28,73,0,73,0,44,28,38,21,73,0,38,21,33,17,33,17,29,14,73,0,73,0,29,14,25,12,95,107,85,95,124,83,124,83,85,95,74,79,124,83,74,79,73,0,73,0,74,79,62,57,73,0,62,57,56,46,56,46,62,57,63,57,67,223,65,190,74,185,67,223,74,185,75,216,75,216,74,185,80,172,75,216,80,172,82,207,82,207,80,172,87,155,82,207,87,155,88,196,88,196,87,155,100,137,88,196,100,137,94,184,94,184,100,137,101,170,50,185,55,187,56,227,56,227,55,187,60,189,56,227,60,189,67 [...]
+114,121,130,126,146,134,158,146,167,160,170,177,168,188,164,198,158,207,149,215,139,221,121,227,111,229,99,230,80,230,75,229,69,228,64,226,57,224,49,222,46,220,42,219,35,219,29,223,27,226,26,230,20,230,16,150,25,150,30,172,38,190,50,204,65,213,85,216,98,214,110,209,119,200,125,188,127,172,126,163,123,155,118,147,112,140,104,135,97,132,89,129,81,128,72,127,60,127,60,113,86,111,106,106,120,96,129,82,132,62,130,47,124,34,114,23,99,15,79,13,65,14,52,18,40,24,28,33,14,46,7,39,19,23,32,11,46,2 [...]
+26,230,20,230,25,150,26,230,25,150,30,172,26,230,30,172,27,226,49,222,46,220,50,204,50,204,46,220,42,219,50,204,42,219,39,219,39,219,35,219,38,190,38,190,35,219,32,221,38,190,32,221,30,172,30,172,32,221,29,223,30,172,29,223,27,226,64,-2,85,-4,65,14,65,14,85,-4,79,13,99,15,79,13,85,-4,99,15,85,-4,99,-3,85,216,80,230,75,229,85,216,75,229,69,228,85,216,69,228,65,213,85,216,86,230,80,230,65,213,69,228,64,226,65,213,64,226,57,224,65,213,57,224,53,223,65,213,53,223,50,204,39,219,38,190,50,204, [...]
+251,225,147,225,147,218,160,216,169,213,174,207,177,200,178,189,84,60,84,189,85,199,88,207,93,212,102,216,116,218,116,225,12,225,12,218,25,216,33,212,39,206,42,197,42,25,39,16,33,11,25,9,12,7,12,0,116,0,116,7,102,9,93,13,88,18,85,26,84,36,178,165,178,37,177,26,174,18,169,12,160,9,147,7,147,0,251,0,251,7,238,9,229,12,224,17,221,26,220,40,220,183,221,198,223,207,229,213,238,216,251,218,
+39,16,33,11,116,0,116,0,33,11,25,9,116,0,25,9,12,7,178,189,84,60,84,36,84,36,84,189,42,183,42,183,84,189,85,199,42,183,85,199,88,207,116,225,12,225,25,216,116,225,25,216,33,212,116,225,33,212,39,206,116,225,39,206,42,197,116,225,42,197,93,212,116,225,93,212,102,216,116,225,102,216,116,218,42,183,88,207,93,212,42,183,93,212,42,197,174,18,169,12,251,0,251,0,169,12,160,9,251,0,160,9,147,7,169,213,174,207,251,225,251,225,174,207,177,200,251,225,177,200,178,189,178,189,178,165,221,26,221,26,1 [...]
+201,319,199,330,195,340,188,347,180,351,171,352,167,352,161,348,159,344,158,339,160,332,166,329,172,327,178,324,180,319,179,313,174,307,166,303,152,300,133,299,115,300,102,303,93,307,88,313,87,319,89,324,95,327,101,329,107,332,109,339,108,344,107,348,101,352,97,352,88,351,80,347,73,340,68,330,66,319,70,302,82,289,98,280,116,275,133,273,151,275,169,280,185,289,196,302,201,319,16383,16383,251,225,147,225,147,218,160,216,169,213,174,207,177,200,178,189,84,60,84,189,85,199,88,207,93,212,102, [...]
+102,303,93,307,98,280,98,280,93,307,88,313,98,280,88,313,82,289,82,289,88,313,87,319,88,351,87,319,89,324,88,351,89,324,97,352,97,352,89,324,95,327,97,352,95,327,101,329,101,352,101,329,104,350,104,350,101,329,107,332,104,350,107,332,107,348,107,348,107,332,109,339,107,348,109,339,108,344,82,289,87,319,88,351,82,289,88,351,80,347,82,289,80,347,73,340,82,289,73,340,70,302,68,330,66,319,70,302,68,330,70,302,73,340,102,303,116,275,115,300,115,300,116,275,133,299,152,300,133,299,133,273,152, [...]
+248,0,248,7,241,8,235,10,225,14,221,17,217,21,211,28,205,37,198,47,192,58,180,79,168,94,156,105,144,113,131,120,131,121,148,137,160,156,168,172,176,185,188,190,192,189,202,185,208,183,214,182,222,183,228,186,233,191,237,197,238,204,236,211,233,218,226,223,218,227,207,228,196,227,185,223,176,216,168,207,161,196,140,154,132,143,124,135,118,132,112,130,105,128,98,127,91,127,91,190,92,199,95,207,100,212,109,216,122,218,122,225,18,225,18,218,31,216,39,214,45,209,48,201,49,189,49,25,46,18,42,1 [...]
+46,18,42,13,128,0,128,0,42,13,36,10,128,0,36,10,26,8,26,8,12,7,128,0,128,0,12,7,12,0,128,0,128,7,117,8,128,0,117,8,107,9,128,0,107,9,99,12,128,0,99,12,49,33,128,0,49,33,49,25,128,0,49,25,46,18,91,33,91,127,49,189,91,33,49,189,92,24,49,33,99,12,94,17,49,33,94,17,92,24,49,33,92,24,49,189,91,113,99,111,91,127,91,127,91,190,49,189,49,189,91,190,92,199,49,189,92,199,95,207,122,225,18,225,31,216,122,225,31,216,39,214,122,225,39,214,45,209,122,225,45,209,48,201,122,225,48,201,49,189,122,225,49, [...]
+238,225,45,225,45,218,57,216,66,212,71,206,74,197,75,183,75,99,74,77,73,53,69,33,62,18,50,12,46,15,42,22,38,30,32,36,23,39,18,38,13,36,8,33,5,27,4,20,6,10,10,3,18,-1,28,-3,39,-4,64,2,79,18,88,41,91,66,92,89,92,198,94,204,98,208,103,210,110,211,154,211,159,209,163,205,165,199,165,37,164,26,161,18,156,12,147,9,134,7,134,0,238,0,238,7,225,9,216,12,211,17,208,26,207,40,207,183,208,198,211,207,216,213,225,216,238,218,
+74,77,73,53,79,18,79,18,73,53,69,33,79,18,69,33,64,2,64,2,69,33,62,18,64,2,62,18,50,12,50,12,46,15,64,2,64,2,46,15,39,-4,57,216,66,212,238,225,238,225,66,212,103,210,238,225,103,210,110,211,238,225,110,211,145,211,238,225,145,211,154,211,161,18,156,12,238,0,238,0,156,12,147,9,238,0,147,9,134,7,238,225,154,211,159,209,238,225,159,209,163,205,238,225,163,205,165,199,238,225,165,199,165,190,238,225,165,190,216,213,238,225,216,213,225,216,238,225,225,216,238,218,207,40,207,183,165,190,165,19 [...]
+297,225,229,225,157,62,79,225,12,225,12,218,25,216,33,212,39,206,42,197,42,25,39,16,33,11,25,9,12,7,12,0,92,0,92,7,78,9,69,12,63,18,60,26,59,36,59,172,60,172,143,0,147,0,224,174,224,37,223,26,220,18,214,12,204,9,190,7,190,0,296,0,296,7,284,9,275,12,270,17,267,26,266,40,266,183,267,198,270,207,275,213,284,216,297,218,
+39,16,33,11,92,0,92,0,33,11,25,9,92,0,25,9,12,7,220,18,214,12,296,0,296,0,214,12,204,9,296,0,204,9,190,7,229,225,157,62,224,174,229,225,224,174,267,26,229,225,267,26,266,40,229,225,266,40,266,183,229,225,266,183,267,198,229,225,267,198,270,207,229,225,270,207,275,213,229,225,275,213,297,225,59,172,60,172,79,225,79,225,60,172,143,0,79,225,143,0,157,62,157,62,143,0,147,0,157,62,147,0,224,174,92,7,78,9,92,0,92,0,78,9,69,12,92,0,69,12,42,25,42,25,69,12,63,18,42,25,63,18,42,40,42,40,63,18,60, [...]
+251,225,147,225,147,218,160,216,169,213,174,207,177,200,178,189,178,124,84,124,84,189,85,199,88,207,93,212,102,216,116,218,116,225,12,225,12,218,25,216,33,212,39,206,42,197,42,25,39,16,33,11,25,9,12,7,12,0,116,0,116,7,102,9,93,13,88,18,85,26,84,36,84,108,178,108,178,37,177,26,174,18,169,12,160,9,147,7,147,0,251,0,251,7,238,9,229,12,224,17,221,26,220,40,220,183,221,198,223,207,229,213,238,216,251,218,
+39,16,33,11,116,0,116,0,33,11,25,9,116,0,25,9,12,7,116,225,12,225,25,216,116,225,25,216,33,212,116,225,33,212,39,206,116,225,39,206,42,197,116,225,42,197,93,212,116,225,93,212,102,216,116,225,102,216,116,218,42,183,85,26,84,36,84,124,84,108,178,108,84,124,178,108,178,124,178,124,178,108,224,17,178,124,224,17,221,26,42,183,84,36,84,189,42,183,84,189,85,199,42,183,85,199,88,207,42,183,88,207,93,212,42,183,93,212,42,197,174,18,169,12,251,0,251,0,169,12,160,9,251,0,160,9,147,7,251,225,147,22 [...]
+238,116,232,154,217,186,194,210,165,225,130,230,92,225,61,209,38,185,23,153,17,114,23,75,38,42,61,17,91,1,126,-4,163,1,194,17,218,43,233,76,238,116,16383,16383,193,102,190,70,183,44,171,25,154,13,134,9,123,10,114,13,104,18,96,25,89,34,79,51,72,70,66,91,63,113,63,137,65,164,73,186,85,202,101,212,121,216,132,215,143,211,152,206,161,199,168,191,177,177,184,161,189,142,192,122,193,102,
+66,91,61,17,72,70,72,70,61,17,91,1,72,70,91,1,79,51,79,51,91,1,89,34,96,25,89,34,91,1,96,25,91,1,126,-4,165,225,130,230,132,215,132,215,130,230,121,216,101,212,121,216,130,230,101,212,130,230,92,225,190,70,183,44,194,17,194,17,183,44,171,25,194,17,171,25,163,1,163,1,171,25,154,13,163,1,154,13,134,9,134,9,123,10,126,-4,126,-4,123,10,114,13,126,-4,114,13,104,18,143,211,152,206,165,225,165,225,152,206,161,199,165,225,161,199,168,191,168,191,177,177,194,210,194,210,177,177,184,161,194,210,18 [...]
+251,225,12,225,12,218,25,217,33,214,39,209,42,200,42,26,39,17,33,12,25,9,12,7,12,0,116,0,116,7,102,9,93,13,88,18,85,26,84,36,84,186,85,196,88,203,92,208,98,210,105,211,156,211,163,210,169,208,174,203,177,196,178,186,178,37,177,26,175,18,170,12,161,9,148,7,148,0,251,0,251,7,238,9,229,11,224,16,221,24,220,37,220,184,221,199,224,209,230,214,238,217,251,218,
+39,17,33,12,116,0,116,0,33,12,25,9,116,0,25,9,12,7,156,211,251,225,105,211,98,210,105,211,39,209,98,210,39,209,42,200,175,18,170,12,251,0,251,0,170,12,161,9,251,0,161,9,148,7,238,217,251,218,251,225,238,217,251,225,230,214,230,214,251,225,177,196,230,214,177,196,178,186,221,24,178,186,178,37,221,24,178,37,224,16,224,16,178,37,229,11,220,37,220,184,178,186,178,186,220,184,221,199,178,186,221,199,224,209,251,225,156,211,163,210,251,225,163,210,169,208,251,225,169,208,174,203,251,225,174,20 [...]
+76,229,73,230,58,224,44,219,31,214,17,209,1,204,1,196,4,197,13,197,22,196,28,194,32,189,34,180,34,-65,33,-79,30,-88,24,-94,14,-98,0,-100,0,-107,120,-107,120,-100,101,-99,88,-95,81,-89,77,-78,76,-62,76,17,86,8,96,2,107,-1,117,-3,129,-4,163,1,191,19,213,47,227,82,232,123,228,158,216,188,198,210,175,225,148,230,132,228,117,224,103,216,89,205,76,190,16383,16383,76,167,79,176,87,185,99,193,113,198,127,200,148,195,165,183,178,163,186,136,189,103,186,73,178,47,165,27,148,14,128,10,113,12,99,18, [...]
+30,-88,24,-94,120,-107,120,-107,24,-94,14,-98,120,-107,14,-98,0,-100,6,197,8,197,17,209,17,209,8,197,11,197,17,209,11,197,13,197,13,197,22,196,17,209,17,209,22,196,31,214,17,209,1,204,4,197,17,209,4,197,6,197,79,35,76,44,86,8,86,8,76,44,76,17,77,-78,76,-62,44,219,77,-78,44,219,34,169,34,169,44,219,34,180,22,196,28,194,31,214,31,214,28,194,32,189,31,214,32,189,44,219,44,219,32,189,34,180,76,190,76,229,73,230,76,190,73,230,76,-62,76,190,76,-62,76,167,76,190,76,167,79,176,76,190,79,176,89,2 [...]
+207,78,193,60,180,46,167,38,153,33,137,31,111,36,89,49,73,69,63,96,59,128,62,157,71,182,86,200,105,212,127,216,137,215,144,212,149,208,153,201,156,191,160,180,163,172,167,166,171,161,177,158,184,157,191,158,197,161,202,166,206,172,207,179,203,195,192,209,175,220,154,227,130,230,116,229,102,226,88,221,75,213,62,204,63,204,48,189,36,172,28,152,22,130,21,106,25,70,38,39,58,15,84,0,116,-4,128,-3,140,-1,152,3,163,9,173,16,182,24,189,32,197,43,205,57,214,74,
+89,49,73,69,84,0,84,0,73,69,63,96,84,0,63,96,58,15,58,15,63,96,59,128,63,204,59,128,62,157,63,204,62,157,71,182,137,31,116,-4,128,-3,137,31,128,-3,140,-1,137,31,111,36,116,-4,89,49,84,0,116,-4,89,49,116,-4,111,36,203,195,192,209,197,161,203,195,197,161,202,166,203,195,202,166,206,172,203,195,206,172,207,179,192,209,175,220,177,158,192,209,177,158,184,157,192,209,184,157,191,158,192,209,191,158,197,161,175,220,154,227,156,191,175,220,156,191,160,180,175,220,160,180,163,172,175,220,163,172 [...]
+213,155,210,225,7,225,4,155,12,155,17,175,24,191,35,202,50,209,70,211,77,211,82,209,85,207,87,202,88,195,88,40,87,25,84,16,78,11,69,9,56,7,56,0,161,0,161,7,148,9,139,13,133,18,130,26,129,36,129,195,130,201,131,206,134,209,139,210,146,211,166,209,182,202,192,191,200,175,204,155,
+84,16,78,11,161,0,161,0,78,11,69,9,161,0,69,9,56,7,24,191,35,202,7,225,7,225,35,202,50,209,7,225,50,209,70,211,70,211,77,211,210,225,210,225,77,211,82,209,210,225,82,209,85,207,85,207,87,202,210,225,210,225,87,202,139,210,210,225,139,210,146,211,146,211,166,209,210,225,210,225,166,209,182,202,210,225,182,202,192,191,210,225,192,191,200,175,210,225,200,175,204,155,210,225,204,155,213,155,129,36,129,195,88,195,88,195,129,195,130,201,88,195,130,201,131,206,88,195,131,206,134,209,88,195,134, [...]
+242,225,175,225,175,218,184,217,190,216,195,213,198,210,199,205,199,201,198,198,198,195,197,193,145,55,84,184,83,188,79,196,78,201,78,204,79,209,82,212,87,215,95,217,107,218,107,225,4,225,4,218,11,217,23,211,27,206,31,200,99,59,105,47,111,34,116,22,120,13,122,6,119,-5,111,-24,100,-44,88,-60,75,-66,70,-66,64,-64,60,-63,55,-60,49,-58,39,-56,33,-56,27,-57,21,-60,16,-65,13,-72,12,-79,14,-88,18,-96,26,-102,35,-106,47,-108,68,-105,86,-94,102,-76,118,-48,134,-11,217,192,221,202,225,208,230,213, [...]
+67,-65,68,-105,70,-66,70,-66,68,-105,86,-94,70,-66,86,-94,73,-66,73,-66,86,-94,75,-66,88,-60,75,-66,86,-94,88,-60,86,-94,102,-76,31,200,78,201,78,204,78,204,79,209,31,200,31,200,79,209,82,212,31,200,82,212,107,225,107,225,82,212,87,215,107,225,87,215,95,217,95,217,107,218,107,225,107,225,4,225,11,217,107,225,11,217,17,214,107,225,17,214,23,211,107,225,23,211,27,206,107,225,27,206,31,200,122,6,134,-11,145,55,145,55,134,-11,217,192,145,55,217,192,197,193,197,193,217,192,198,195,242,225,175 [...]
+190,330,186,331,172,325,146,315,132,310,117,305,117,297,119,298,129,298,138,297,144,295,147,290,149,281,150,270,150,204,144,212,136,219,127,225,116,229,104,230,76,225,53,209,36,185,25,153,22,113,23,89,27,66,32,46,41,29,51,15,60,8,69,2,79,-1,91,-3,103,-4,115,-3,126,0,136,6,144,13,150,22,150,-65,149,-79,146,-88,140,-94,129,-98,114,-100,114,-107,233,-107,233,-100,214,-99,202,-95,194,-89,191,-78,190,-62,190,22,195,13,203,6,213,0,224,-3,236,-4,249,-3,260,-1,270,2,279,8,287,15,298,29,306,46,31 [...]
+69,2,79,-1,72,51,72,51,79,-1,76,38,81,29,76,38,79,-1,81,29,79,-1,91,-3,150,177,150,47,150,22,150,22,150,47,147,38,150,22,147,38,144,13,144,13,147,38,141,28,144,13,141,28,136,6,136,6,141,28,132,19,136,6,132,19,126,0,126,0,132,19,120,13,126,0,120,13,115,-3,115,-3,120,13,105,10,105,10,99,11,103,-4,103,-4,99,11,92,15,103,-4,92,15,91,-3,91,-3,92,15,86,21,91,-3,86,21,81,29,150,270,150,204,150,22,150,22,150,204,150,177,150,177,150,204,147,187,147,187,150,204,144,212,147,187,144,212,141,197,141, [...]
+238,0,238,7,229,8,221,12,213,18,205,26,197,37,133,136,175,195,181,203,188,209,197,214,215,218,215,225,136,225,136,218,144,217,150,215,154,213,156,210,156,201,154,195,150,187,145,178,138,169,124,149,116,162,108,174,101,185,97,194,94,201,93,206,93,210,96,213,100,216,106,217,114,218,114,225,11,225,11,218,15,218,23,217,31,214,38,208,45,200,54,187,54,188,100,115,45,32,37,22,30,15,23,11,16,9,7,7,7,0,79,0,79,7,72,8,66,9,62,11,60,13,60,19,61,23,63,27,65,33,69,39,108,100,155,28,156,27,156,25,157, [...]
+30,15,23,11,79,0,79,0,23,11,16,9,79,0,16,9,7,7,31,214,38,208,114,225,114,225,38,208,45,200,114,225,45,200,54,188,54,188,45,200,54,187,54,187,100,115,93,206,93,206,93,210,54,187,54,187,93,210,96,213,54,187,96,213,114,225,114,225,96,213,100,216,114,225,100,216,106,217,30,15,79,0,37,22,37,22,79,0,62,11,37,22,62,11,45,32,45,32,62,11,60,13,45,32,60,13,60,17,60,17,60,19,45,32,45,32,60,19,61,23,45,32,61,23,63,27,106,217,114,218,114,225,114,225,11,225,15,218,114,225,15,218,23,217,114,225,23,217, [...]
+251,225,146,225,146,218,159,216,168,212,174,207,177,199,178,189,178,39,177,29,174,22,170,17,164,15,157,14,104,14,97,15,92,17,88,22,85,29,84,39,84,188,85,199,88,207,94,213,103,216,116,218,116,225,12,225,12,218,25,216,33,214,39,209,42,201,42,26,39,16,33,11,24,8,12,7,12,0,199,0,210,-3,221,-14,232,-34,243,-68,251,-68,251,7,238,8,229,11,224,16,221,25,220,40,220,186,221,199,223,208,229,213,238,216,251,218,
+39,16,33,11,187,0,187,0,33,11,24,8,187,0,24,8,12,7,116,225,12,225,25,216,116,225,25,216,33,214,116,225,33,214,39,209,116,225,39,209,42,201,116,225,42,201,42,188,116,225,42,188,94,213,116,225,94,213,103,216,116,225,103,216,116,218,92,17,88,22,42,41,42,41,88,22,85,29,42,41,85,29,42,188,42,188,85,29,84,39,42,188,84,39,84,188,42,188,84,188,85,199,42,188,85,199,88,207,42,188,88,207,94,213,251,225,146,225,159,216,251,225,159,216,168,212,251,225,168,212,174,207,251,225,174,207,177,199,251,225,1 [...]
+244,225,139,225,139,218,152,216,161,212,167,207,170,200,171,190,171,118,166,116,158,113,148,110,136,108,123,107,106,108,94,112,87,120,83,131,81,147,81,186,82,199,86,208,91,213,100,216,113,218,113,225,9,225,9,218,22,216,30,213,36,209,39,200,40,186,40,144,43,121,52,105,66,97,85,93,107,92,124,93,139,96,152,100,162,104,171,108,171,27,168,18,162,13,153,9,141,7,141,0,244,0,244,7,231,9,223,12,217,17,215,25,214,39,214,199,217,208,223,213,231,216,244,218,
+113,218,113,218,100,216,100,216,113,218,113,225,100,216,113,225,91,213,91,213,113,225,40,186,91,213,40,186,86,208,86,208,40,186,43,121,86,208,43,121,82,199,82,199,43,121,52,105,82,199,52,105,66,97,87,120,83,131,85,93,85,93,83,131,81,147,81,147,81,186,66,97,66,97,81,186,82,199,30,213,36,209,113,225,113,225,36,209,39,200,113,225,39,200,40,186,22,216,30,213,113,225,22,216,113,225,9,225,22,216,9,225,9,218,244,7,231,9,244,0,244,0,231,9,223,12,244,0,223,12,171,39,171,39,223,12,217,17,171,39,21 [...]
+373,225,270,225,270,218,282,216,291,213,296,207,299,200,300,189,300,39,299,29,297,22,293,17,287,15,278,14,235,14,228,15,221,17,217,22,214,29,213,39,213,189,214,199,218,207,224,213,232,216,243,218,243,225,141,225,141,218,152,216,160,213,166,207,170,199,171,189,171,39,170,29,168,22,164,17,158,15,150,14,107,14,99,15,93,17,88,22,85,29,84,39,84,189,85,199,88,207,93,212,102,216,114,218,114,225,12,225,12,218,25,216,33,212,39,206,42,197,42,25,39,16,33,11,25,9,12,7,12,0,372,0,372,7,360,8,351,11,3 [...]
+39,16,33,11,372,0,372,0,33,11,25,9,372,0,25,9,12,7,114,225,12,225,25,216,114,225,25,216,33,212,114,225,33,212,39,206,114,225,39,206,42,197,114,225,42,197,42,183,114,225,42,183,93,212,114,225,93,212,102,216,114,225,102,216,114,218,93,17,88,22,42,40,42,40,88,22,85,29,42,40,85,29,42,183,42,183,85,29,84,39,42,183,84,39,84,189,42,183,84,189,85,199,42,183,85,199,88,207,42,183,88,207,93,212,93,17,42,25,99,15,99,15,42,25,39,16,99,15,39,16,107,14,107,14,39,16,372,0,107,14,372,0,150,14,150,14,372, [...]
+373,225,270,225,270,218,282,216,291,213,296,207,299,200,300,189,300,39,299,29,297,22,293,17,287,15,278,14,235,14,228,15,221,17,217,22,214,29,213,39,213,189,214,199,218,207,224,212,232,216,243,218,243,225,141,225,141,218,142,218,152,216,160,212,166,207,170,199,171,189,171,39,170,29,168,22,164,17,158,15,150,14,107,14,99,15,93,17,88,22,85,29,84,39,84,189,85,199,87,207,93,212,101,216,114,218,114,225,12,225,12,218,25,216,33,212,39,206,42,197,42,25,39,16,33,11,25,9,12,7,12,0,325,0,335,-5,345,- [...]
+39,16,33,11,315,0,315,0,33,11,25,9,315,0,25,9,12,7,114,225,12,225,25,216,114,225,25,216,33,212,114,225,33,212,39,206,114,225,39,206,42,197,114,225,42,197,42,183,114,225,42,183,93,212,114,225,93,212,101,216,114,225,101,216,114,218,93,17,88,22,42,40,42,40,88,22,85,29,42,40,85,29,42,183,42,183,85,29,84,39,42,183,84,39,84,189,42,183,84,189,85,199,42,183,85,199,87,207,42,183,87,207,93,212,93,17,42,25,99,15,99,15,42,25,39,16,99,15,39,16,107,14,107,14,39,16,315,0,107,14,315,0,150,14,150,14,315, [...]
+126,126,126,199,129,207,134,212,143,216,156,218,156,225,8,225,4,161,12,161,18,181,25,195,35,205,46,209,61,211,68,211,74,209,79,207,83,202,84,195,84,40,83,25,80,16,75,11,66,9,52,7,52,0,169,0,196,3,220,10,238,23,249,40,253,62,249,86,235,105,215,117,188,124,158,126,16383,16383,126,112,148,112,167,111,183,107,196,98,205,84,208,64,205,43,196,29,182,20,164,15,142,14,135,14,130,16,127,19,126,23,126,30,
+80,16,75,11,169,0,169,0,75,11,66,9,169,0,66,9,52,7,74,209,156,225,68,211,68,211,156,225,61,211,46,209,61,211,156,225,46,209,156,225,8,225,156,225,74,209,79,207,156,225,79,207,83,202,156,225,83,202,84,195,156,225,84,195,134,212,156,225,134,212,143,216,156,225,143,216,156,218,84,195,126,23,126,30,126,126,126,112,148,112,126,126,148,112,158,126,158,126,148,112,167,111,158,126,167,111,188,124,188,124,167,111,183,107,188,124,183,107,196,98,84,195,126,30,126,189,84,195,126,189,126,199,84,195,1 [...]
+323,0,323,8,310,10,301,13,295,18,293,26,292,36,292,199,295,207,300,212,309,216,323,218,323,225,219,225,219,218,232,216,241,212,246,206,249,197,250,183,250,40,249,25,246,16,241,11,232,9,219,7,219,0,16383,16383,84,126,84,189,85,199,88,207,93,212,102,216,116,218,116,225,12,225,12,218,25,216,33,212,39,206,42,197,42,25,39,16,33,11,25,9,12,7,12,0,127,0,155,3,179,10,197,23,209,40,213,62,208,86,194,105,174,117,148,124,118,126,16383,16383,84,112,107,112,126,111,142,107,155,98,164,84,167,64,164,43 [...]
+323,218,323,218,309,216,309,216,323,218,323,225,309,216,323,225,300,212,300,212,323,225,249,197,300,212,249,197,250,183,293,26,250,183,250,40,293,26,250,40,295,18,295,18,250,40,301,13,292,36,292,189,250,183,250,183,292,189,292,199,250,183,292,199,295,207,323,225,219,225,232,216,323,225,232,216,241,212,323,225,241,212,246,206,323,225,246,206,249,197,323,0,323,8,310,10,323,0,310,10,301,13,323,0,301,13,250,40,323,0,250,40,249,25,323,0,249,25,246,16,323,0,246,16,241,11,323,0,241,11,232,9,323 [...]
+84,126,84,189,85,199,88,207,93,212,102,216,116,218,116,225,12,225,12,218,25,216,33,212,39,206,42,197,42,25,39,16,33,11,25,9,12,7,12,0,127,0,155,3,179,10,197,23,209,40,213,62,208,86,194,105,174,117,148,124,118,126,16383,16383,84,112,107,112,126,111,142,107,155,98,164,84,167,64,164,43,155,29,141,20,123,15,102,14,94,14,89,16,86,19,85,23,84,30,
+39,16,33,11,127,0,127,0,33,11,25,9,127,0,25,9,12,7,116,225,12,225,25,216,116,225,25,216,33,212,116,225,33,212,39,206,116,225,39,206,42,197,116,225,42,197,93,212,116,225,93,212,102,216,116,225,102,216,116,218,42,183,85,23,84,30,84,126,84,112,107,112,84,126,107,112,118,126,118,126,107,112,126,111,118,126,126,111,148,124,148,124,126,111,142,107,148,124,142,107,155,98,42,183,84,30,84,189,42,183,84,189,85,199,42,183,85,199,88,207,42,183,88,207,93,212,42,183,93,212,42,197,164,43,155,29,155,3,1 [...]
+30,228,23,157,32,157,38,173,46,189,58,203,75,212,99,216,122,212,140,200,154,182,162,157,165,128,75,128,75,112,165,112,160,87,150,64,135,47,114,35,88,31,71,33,56,37,42,46,28,59,15,78,7,74,18,53,32,32,49,14,72,0,101,-4,136,1,165,16,187,41,200,73,205,110,201,147,189,179,169,206,140,223,102,230,92,230,84,229,63,222,59,220,56,218,52,217,48,217,44,218,42,219,40,221,38,224,37,228,
+59,220,56,218,58,203,58,203,56,218,52,217,58,203,52,217,48,217,48,217,44,218,46,189,46,189,44,218,42,219,46,189,42,219,40,221,30,228,32,157,37,228,37,228,32,157,38,173,37,228,38,173,38,224,38,224,38,173,46,189,38,224,46,189,40,221,15,78,18,53,28,59,28,59,18,53,32,32,28,59,32,32,42,46,42,46,32,32,49,14,42,46,49,14,56,37,56,37,49,14,72,0,56,37,72,0,71,33,71,33,72,0,88,31,114,35,88,31,101,-4,114,35,101,-4,136,1,99,216,92,230,84,229,99,216,84,229,78,227,99,216,78,227,75,212,99,216,102,230,92 [...]
+84,124,84,189,85,199,88,207,93,212,102,216,116,218,116,225,12,225,12,218,25,216,33,212,39,206,42,197,42,25,39,16,33,11,25,9,12,7,12,0,116,0,116,7,102,9,93,13,88,18,85,26,84,36,84,108,131,108,138,70,153,39,176,16,205,0,239,-4,276,1,308,17,331,43,346,76,352,116,346,154,331,186,308,210,278,225,243,230,207,225,177,211,154,189,138,160,131,124,16383,16383,306,102,304,70,296,44,284,25,268,13,248,9,237,10,227,13,218,18,210,25,203,34,193,51,185,70,180,91,177,113,176,137,179,164,186,186,199,202,21 [...]
+39,16,33,11,116,0,116,0,33,11,25,9,116,0,25,9,12,7,116,225,12,225,25,216,116,225,25,216,33,212,116,225,33,212,39,206,116,225,39,206,42,197,116,225,42,197,93,212,116,225,93,212,102,216,116,225,102,216,116,218,138,160,131,124,131,108,131,108,131,124,84,124,131,108,84,124,84,108,85,26,84,36,42,183,85,26,42,183,42,40,42,183,84,36,84,189,42,183,84,189,85,199,42,183,85,199,88,207,42,183,88,207,93,212,42,183,93,212,42,197,116,0,116,7,102,9,116,0,102,9,93,13,116,0,93,13,42,40,116,0,42,40,42,25,1 [...]
+224,225,121,225,91,224,65,219,45,210,31,193,26,167,30,148,40,131,55,118,74,109,97,104,37,31,32,25,26,19,19,14,11,9,2,7,2,0,64,0,142,103,151,103,151,25,148,16,143,11,135,8,123,7,123,0,224,0,224,8,211,10,202,13,197,18,194,26,193,40,193,183,194,198,197,207,202,213,211,216,224,218,16383,16383,151,117,131,117,111,119,94,125,82,135,74,148,71,165,75,185,85,198,99,206,117,210,136,211,142,211,147,209,149,206,151,202,151,195,
+26,19,19,14,64,0,64,0,19,14,11,9,64,0,11,9,2,7,97,104,64,0,142,103,97,104,142,103,111,119,97,104,111,119,94,125,97,104,94,125,82,135,97,104,82,135,74,148,97,104,74,148,74,109,85,198,91,224,75,185,75,185,91,224,65,219,75,185,65,219,71,165,71,165,74,109,74,148,26,167,30,148,31,193,31,193,30,148,40,131,31,193,40,131,45,210,45,210,40,131,55,118,45,210,55,118,65,219,65,219,55,118,74,109,65,219,74,109,71,165,148,16,143,11,224,0,224,0,143,11,135,8,224,0,135,8,123,7,147,209,224,225,142,211,142,2 [...]
+266,59,253,44,242,34,234,29,228,26,222,25,216,28,216,31,215,33,216,38,217,44,218,49,220,55,221,61,247,151,249,159,252,180,252,186,250,202,245,214,236,223,224,228,208,230,189,227,169,216,147,196,123,165,99,123,98,123,133,252,205,278,211,300,139,273,146,296,148,306,151,315,153,324,156,332,158,340,155,342,143,337,131,333,116,329,98,325,76,320,76,312,85,312,92,311,99,309,103,306,104,301,104,293,103,290,103,286,93,257,45,239,40,218,87,234,23,0,65,0,78,41,88,72,98,97,109,117,121,137,137,159,15 [...]
+99,123,98,123,99,123,99,123,98,123,109,117,99,123,109,117,123,165,123,165,109,117,121,137,104,296,104,293,133,252,133,252,104,293,103,290,133,252,103,290,103,286,103,286,93,257,98,123,98,123,93,257,98,97,98,123,98,97,109,117,203,199,208,230,198,202,198,202,208,230,190,203,180,200,190,203,189,227,180,200,189,227,169,216,123,165,137,159,147,196,147,196,137,159,152,177,147,196,152,177,169,216,169,216,152,177,167,191,169,216,167,191,180,200,204,150,185,78,190,-3,204,150,190,-3,199,-4,204,150 [...]
+344,337,341,331,335,324,327,316,316,310,302,308,271,312,246,322,222,334,193,344,154,348,118,342,88,327,65,305,51,278,46,248,49,224,60,204,77,189,100,179,128,176,136,176,144,177,151,179,159,182,167,186,163,197,157,195,150,193,144,191,137,190,131,190,116,192,102,198,90,208,82,222,79,241,83,262,93,278,106,289,122,295,138,297,168,293,193,283,216,272,242,262,273,258,303,263,325,276,340,294,349,314,355,334,16383,16383,352,209,344,217,335,225,325,231,312,235,295,237,275,234,257,225,241,212,231, [...]
+102,198,90,208,100,179,100,179,90,208,82,222,100,179,82,222,77,189,77,189,82,222,79,241,88,327,79,241,83,262,88,327,83,262,93,278,154,348,138,297,168,293,154,348,168,293,193,344,193,344,168,293,193,283,193,344,193,283,222,334,222,334,193,283,216,272,222,334,216,272,242,262,222,334,242,262,246,322,246,322,242,262,273,258,246,322,273,258,271,312,271,312,273,258,302,308,316,310,302,308,303,263,316,310,303,263,325,276,355,334,344,337,349,314,349,314,344,337,341,331,349,314,341,331,340,294,34 [...]
+177,262,198,294,219,325,240,354,261,380,281,403,291,412,302,421,313,428,324,432,335,434,343,433,350,430,355,426,357,420,358,413,350,375,325,339,287,307,237,280,178,262,16383,16383,51,258,62,251,73,246,85,242,97,240,109,239,104,230,98,221,83,194,66,162,51,131,41,101,34,74,32,50,35,30,43,13,56,2,72,-4,89,-6,114,-2,140,11,169,35,201,68,239,112,226,123,191,83,161,52,135,30,113,17,94,13,85,14,78,18,73,24,71,32,70,41,77,74,94,114,117,158,142,201,165,239,232,256,290,286,337,325,367,368,378,411, [...]
+142,201,165,239,166,318,166,318,165,239,177,262,177,262,165,239,178,262,237,280,178,262,232,256,237,280,232,256,290,286,313,428,336,455,302,421,302,421,336,455,299,445,302,421,299,445,291,412,291,412,299,445,281,403,261,380,281,403,299,445,261,380,299,445,257,415,351,454,336,455,343,433,343,433,336,455,335,434,324,432,335,434,336,455,324,432,336,455,313,428,355,426,357,420,363,448,363,448,357,420,358,413,367,368,358,413,350,375,367,368,350,375,337,325,337,325,350,375,325,339,337,325,325, [...]
+406,57,402,52,396,46,384,36,379,35,361,47,353,78,347,119,335,159,309,190,309,191,331,203,348,218,361,236,368,256,371,277,367,300,355,321,335,337,308,348,272,352,206,304,193,317,178,329,160,339,140,345,118,348,89,344,63,335,43,319,30,297,25,270,31,247,45,229,62,214,76,197,82,175,79,163,73,153,64,144,54,138,45,134,49,123,74,132,97,145,115,161,128,180,132,200,126,227,112,245,95,259,81,275,75,299,76,308,80,318,87,325,97,330,108,332,133,322,149,297,157,265,161,231,162,203,162,165,160,123,156, [...]
+82,175,79,163,82,175,82,175,79,163,97,145,82,175,97,145,95,259,82,175,95,259,81,275,82,175,81,275,76,197,76,197,81,275,75,299,63,335,75,299,76,308,63,335,76,308,89,344,89,344,76,308,80,318,89,344,80,318,87,325,118,348,108,332,133,322,118,348,133,322,140,345,140,345,133,322,149,297,140,345,149,297,160,339,160,339,149,297,157,265,160,339,157,265,161,231,162,165,160,123,173,53,173,53,160,123,156,84,173,53,156,84,149,19,149,19,156,84,149,56,149,19,149,56,137,45,137,45,129,47,149,19,149,19,12 [...]
+429,110,429,143,125,143,121,145,119,147,117,150,117,155,119,161,123,167,132,176,141,186,149,195,165,215,155,224,134,202,112,180,89,160,63,143,36,129,36,124,63,110,89,93,112,73,134,51,154,29,164,39,157,49,149,59,140,68,132,78,123,86,120,89,118,92,116,96,116,99,117,102,119,105,122,107,126,109,129,110,
+121,145,119,147,119,105,119,105,119,147,117,150,119,105,117,150,117,102,117,102,117,150,117,153,116,99,112,180,112,73,112,73,112,180,89,160,112,73,89,160,89,93,89,93,89,160,63,143,89,93,63,143,63,110,63,110,63,143,36,129,63,110,36,129,36,124,155,224,134,202,141,186,155,224,141,186,149,195,155,224,149,195,157,205,155,224,157,205,165,215,134,202,112,180,118,158,134,202,118,158,119,161,134,202,119,161,121,164,134,202,121,164,123,167,134,202,123,167,132,176,134,202,132,176,141,186,117,155,11 [...]
+225,212,203,232,181,254,162,278,144,303,130,331,125,331,111,303,94,278,74,254,52,233,30,213,40,203,49,210,69,226,79,235,88,243,90,246,93,248,97,250,100,251,103,250,109,244,111,238,111,-77,144,-77,144,237,145,242,146,246,148,248,151,250,157,250,159,249,168,243,177,234,187,226,197,217,206,209,216,202,
+90,246,93,248,94,278,94,278,93,248,95,249,94,278,95,249,111,303,111,303,95,249,97,250,111,303,97,250,100,251,100,251,103,250,111,303,111,303,103,250,106,247,111,303,106,247,109,244,110,241,111,238,111,303,111,303,111,238,125,331,125,331,111,238,144,-77,125,331,144,-77,130,331,130,331,144,-77,144,237,130,331,144,237,144,303,144,303,144,237,145,242,144,303,145,242,146,246,88,243,90,246,94,278,88,243,94,278,79,235,79,235,94,278,74,254,79,235,74,254,69,226,69,226,74,254,59,218,52,233,30,213, [...]
+428,129,400,143,375,160,352,180,330,201,310,224,300,214,314,194,323,185,332,175,340,166,343,164,345,161,347,159,347,157,348,154,347,151,341,145,338,144,334,143,35,143,35,110,334,110,339,109,343,108,345,106,347,103,347,97,346,95,340,86,331,77,322,67,314,58,306,48,299,38,309,28,330,51,351,72,375,92,400,110,428,124,
+347,97,351,72,347,100,347,100,351,72,348,154,348,154,351,72,352,180,352,180,351,72,375,92,352,180,375,92,375,160,375,160,375,92,400,110,375,160,400,110,400,143,400,143,400,110,428,124,400,143,428,124,428,129,352,180,330,201,332,175,352,180,332,175,340,166,352,180,340,166,343,164,352,180,343,164,345,161,352,180,345,161,347,159,352,180,347,159,347,157,352,180,347,157,348,154,300,214,307,204,310,224,310,224,307,204,314,194,310,224,314,194,330,201,330,201,314,194,323,185,330,201,323,185,332, [...]
+216,50,206,43,186,27,168,9,165,7,163,5,160,3,158,3,156,2,153,3,147,9,145,12,145,331,112,331,112,16,111,11,110,8,105,3,99,3,96,4,90,8,88,10,78,19,69,28,49,44,40,51,30,41,53,20,74,-1,94,-24,111,-49,126,-77,131,-77,145,-49,162,-24,182,-1,203,20,225,41,
+110,8,107,5,111,-49,111,-49,107,5,105,3,111,-49,105,3,102,3,102,3,99,3,111,-49,111,-49,99,3,96,4,111,-49,96,4,94,-24,94,-24,96,4,93,6,94,-24,93,6,90,8,150,6,147,9,162,-24,162,-24,147,9,145,12,162,-24,145,12,145,-49,145,-49,145,12,145,16,145,16,145,331,131,-77,131,-77,145,331,126,-77,145,331,112,331,126,-77,126,-77,112,331,112,16,126,-77,112,16,111,-49,111,-49,112,16,111,11,111,-49,111,11,110,8,163,5,160,3,162,-24,162,-24,160,3,158,3,162,-24,158,3,156,2,156,2,153,3,162,-24,162,-24,153,3,1 [...]
+444,129,417,143,391,160,368,180,346,201,325,224,315,214,322,204,330,194,339,185,348,175,359,164,361,161,363,157,363,154,362,151,360,148,357,145,354,144,350,143,108,143,104,145,102,147,100,150,100,155,101,158,107,167,116,176,125,186,133,195,141,205,148,215,138,224,96,180,72,160,47,143,19,129,19,124,47,110,72,93,95,73,117,51,137,29,147,39,133,59,124,68,115,78,104,89,102,92,100,94,100,96,99,99,100,102,103,105,109,109,113,110,350,110,355,109,358,108,361,106,363,100,362,97,362,95,356,86,347,7 [...]
+104,145,102,147,103,105,103,105,102,147,100,150,103,105,100,150,100,102,100,102,100,150,100,153,99,99,96,180,95,73,95,73,96,180,72,160,95,73,72,160,72,93,72,93,72,160,47,143,72,93,47,143,47,110,47,110,47,143,19,129,47,110,19,129,19,124,138,224,117,202,125,186,138,224,125,186,133,195,138,224,133,195,141,205,138,224,141,205,148,215,117,202,96,180,101,158,117,202,101,158,103,161,117,202,103,161,105,164,117,202,105,164,107,167,117,202,107,167,116,176,117,202,116,176,125,186,100,155,101,158,9 [...]
+225,246,203,266,182,288,162,312,145,337,131,365,126,365,112,337,94,312,74,288,53,267,31,247,40,237,50,244,70,260,79,269,88,277,93,282,96,283,100,285,104,284,107,281,111,275,112,272,112,-16,111,-21,110,-25,107,-28,105,-29,102,-30,93,-27,90,-25,88,-22,78,-13,69,-5,59,2,49,10,40,17,30,7,53,-12,74,-34,94,-58,111,-83,126,-111,131,-111,145,-83,162,-58,181,-34,203,-12,225,7,215,17,206,10,196,2,186,-5,163,-28,160,-29,158,-30,156,-30,153,-29,150,-27,147,-24,145,-20,145,276,147,280,149,282,152,284 [...]
+69,-5,74,-34,78,-13,78,-13,74,-34,94,-58,78,-13,94,-58,88,-22,88,-22,94,-58,90,-25,91,280,93,282,94,312,94,312,93,282,96,283,94,312,96,283,112,337,112,337,96,283,98,284,112,337,98,284,100,285,100,285,104,284,112,337,112,337,104,284,107,281,112,337,107,281,109,278,110,-25,107,-28,111,-83,111,-83,107,-28,105,-29,111,-83,105,-29,102,-30,102,-30,99,-29,111,-83,111,-83,99,-29,96,-28,111,-83,96,-28,94,-58,94,-58,96,-28,93,-27,94,-58,93,-27,90,-25,109,278,111,275,112,337,112,337,111,275,112,272 [...]
+428,-54,118,271,115,274,111,280,110,282,110,285,111,287,111,288,112,290,113,291,115,292,117,294,121,295,124,296,153,296,166,297,178,298,190,300,190,315,182,314,173,313,125,313,103,315,81,318,60,324,39,331,35,328,43,306,48,285,51,263,53,241,54,219,53,210,53,193,52,184,51,176,65,176,68,188,70,214,70,243,72,249,73,251,76,254,77,254,78,255,83,255,85,254,88,254,92,252,404,-77,
+48,285,51,263,60,324,60,324,51,263,53,241,60,324,53,241,54,219,54,219,53,210,65,176,65,176,53,210,53,201,65,176,53,201,53,193,60,324,39,331,43,306,60,324,43,306,48,285,77,254,78,255,81,318,81,318,78,255,79,255,81,318,79,255,80,255,80,255,83,255,81,318,81,318,83,255,103,315,81,318,60,324,71,246,81,318,71,246,72,249,81,318,72,249,73,251,81,318,73,251,75,253,81,318,75,253,76,254,81,318,76,254,77,254,65,176,68,188,70,243,70,243,68,188,69,201,70,243,69,201,70,239,70,239,69,201,70,214,70,239,7 [...]
+425,331,403,324,382,318,360,315,338,313,289,313,281,314,272,315,272,300,284,298,297,297,309,296,339,296,342,295,346,294,348,292,350,291,351,290,352,288,353,287,353,282,352,280,348,274,345,271,35,-54,59,-77,372,252,373,253,375,254,377,254,380,255,385,255,387,254,388,254,388,253,390,251,391,249,392,246,392,226,393,214,395,188,397,176,411,176,411,185,410,193,410,241,412,263,415,285,421,307,428,328,
+272,315,272,315,281,314,281,314,272,315,284,298,281,314,284,298,289,313,289,313,284,298,297,297,289,313,297,297,298,313,298,313,297,297,309,296,298,313,309,296,307,313,307,313,309,296,315,313,338,313,315,313,322,296,338,313,322,296,335,296,375,254,377,254,382,318,382,318,377,254,380,255,382,318,380,255,382,255,382,255,384,255,403,324,403,324,384,255,385,255,403,324,385,255,387,254,353,285,353,284,360,315,360,315,353,284,372,252,360,315,372,252,382,318,382,318,372,252,373,253,382,318,373, [...]
+428,-74,421,-53,415,-31,412,-9,410,12,410,60,411,68,411,76,397,77,395,65,392,26,392,7,391,4,390,2,387,-1,380,-1,377,0,373,0,372,2,59,331,35,307,345,-17,348,-20,352,-26,353,-28,353,-33,352,-34,351,-36,350,-36,346,-40,342,-41,335,-41,322,-42,309,-42,297,-43,284,-45,272,-46,272,-60,281,-60,289,-59,338,-59,360,-61,382,-65,403,-70,425,-77,
+335,-41,322,-42,338,-59,338,-59,322,-42,315,-59,307,-59,315,-59,309,-42,307,-59,309,-42,298,-59,298,-59,309,-42,297,-43,298,-59,297,-43,289,-59,289,-59,297,-43,284,-45,289,-59,284,-45,281,-60,281,-60,284,-45,272,-46,281,-60,272,-46,272,-60,322,-42,309,-42,315,-59,353,-33,352,-34,360,-61,360,-61,352,-34,351,-36,360,-61,351,-36,350,-36,372,2,59,331,345,-17,372,2,345,-17,348,-20,372,2,348,-20,350,-23,372,2,350,-23,352,-26,372,2,352,-26,353,-28,372,2,353,-28,353,-30,372,2,353,-30,360,-61,372 [...]
+428,307,404,331,92,2,90,0,88,0,85,-1,77,-1,76,0,75,0,73,2,72,4,70,10,70,39,68,65,65,77,51,76,53,60,53,43,54,35,53,12,51,-9,48,-31,43,-53,35,-74,39,-77,60,-70,81,-65,103,-61,125,-59,173,-59,182,-60,190,-60,190,-46,178,-45,166,-43,153,-42,140,-42,127,-41,121,-41,117,-40,113,-36,112,-36,111,-34,111,-33,110,-32,110,-28,111,-26,115,-20,118,-17,
+78,-1,81,-65,79,-1,79,-1,81,-65,80,-1,83,-1,80,-1,81,-65,83,-1,81,-65,103,-61,111,-34,111,-33,103,-61,103,-61,111,-33,110,-32,103,-61,110,-32,110,-30,110,-30,110,-28,103,-61,103,-61,110,-28,92,2,103,-61,92,2,90,0,115,-20,118,-17,404,331,115,-20,404,331,92,2,404,331,118,-17,428,307,92,2,110,-28,111,-26,92,2,111,-26,113,-23,92,2,113,-23,115,-20,103,-61,90,0,88,0,103,-61,88,0,85,-1,103,-61,85,-1,83,-1,147,-59,140,-42,127,-41,147,-59,127,-41,125,-59,147,-59,153,-42,140,-42,156,-59,165,-59,16 [...]
+279,331,243,331,206,232,74,232,36,331,1,331,123,0,156,0,16383,16383,195,201,140,51,84,201,
+156,0,279,331,195,201,195,201,279,331,206,232,195,201,206,232,84,201,84,201,206,232,74,232,84,201,74,232,123,0,123,0,74,232,36,331,123,0,36,331,1,331,140,51,84,201,123,0,140,51,123,0,156,0,140,51,156,0,195,201,206,232,279,331,243,331,
+202,110,169,110,169,65,165,48,155,37,141,30,128,27,117,26,107,26,92,29,78,36,67,47,63,65,63,308,67,326,78,337,92,344,105,346,116,347,126,347,140,344,154,338,165,326,169,307,169,262,202,262,202,305,196,339,180,360,158,373,136,379,117,380,97,379,74,373,52,361,36,339,30,306,30,65,36,32,51,11,72,0,94,-5,114,-6,134,-5,157,0,179,10,196,30,202,61,
+105,346,116,347,116,347,117,380,116,347,126,347,117,380,126,347,136,379,136,379,126,347,140,344,136,379,140,344,158,373,158,373,140,344,154,338,158,373,154,338,165,326,202,305,196,339,202,262,202,262,196,339,180,360,202,262,180,360,169,307,169,307,180,360,165,326,78,337,92,344,97,379,97,379,92,344,105,346,97,379,105,346,117,380,117,380,105,346,116,347,74,373,52,361,63,308,74,373,63,308,67,326,74,373,67,326,78,337,74,373,78,337,97,379,30,306,30,65,36,32,30,306,36,32,36,339,36,339,36,32,51 [...]
+98,313,112,317,119,318,127,319,134,319,161,314,179,300,191,279,198,255,200,228,200,221,199,214,199,207,198,200,196,194,189,203,180,210,169,214,159,217,148,218,107,210,72,188,44,156,26,117,20,75,22,51,30,29,43,11,62,0,88,-5,148,9,190,47,217,98,231,154,235,204,232,250,220,287,202,313,175,329,142,334,131,334,121,333,101,327,93,323,16383,16383,184,160,182,140,180,131,178,121,176,110,166,80,152,53,135,30,116,15,94,9,78,13,68,21,63,33,61,46,60,59,65,100,79,139,99,172,124,194,153,203,161,201,16 [...]
+127,319,134,319,134,319,142,334,134,319,161,314,142,334,161,314,175,329,175,329,161,314,179,300,175,329,179,300,202,313,202,313,179,300,191,279,202,313,191,279,198,255,112,317,119,318,121,333,121,333,119,318,127,319,121,333,127,319,131,334,131,334,127,319,134,319,131,334,134,319,142,334,93,323,98,313,101,327,101,327,98,313,105,315,101,327,105,315,111,330,111,330,105,315,112,317,111,330,112,317,121,333,152,53,135,30,148,9,148,9,135,30,116,15,148,9,116,15,94,9,94,9,78,13,88,-5,88,-5,78,13, [...]
+243,0,243,331,36,331,36,298,210,298,210,182,42,182,42,149,210,149,210,33,36,33,36,0,
+42,182,210,149,210,182,210,182,210,149,243,0,210,182,243,0,210,298,210,298,243,0,243,331,210,298,243,331,36,331,243,0,210,149,210,33,243,0,210,33,36,33,243,0,36,33,36,0,210,298,36,331,36,298,210,149,42,182,42,149,
+243,0,243,331,199,331,219,387,190,387,170,331,36,331,36,298,159,298,119,182,42,182,42,149,108,149,68,33,36,33,36,0,56,0,36,-60,65,-60,85,0,16383,16383,210,182,148,182,188,298,210,298,16383,16383,210,33,97,33,137,149,210,149,
+36,331,159,298,170,331,170,331,159,298,188,298,170,331,188,298,190,387,190,387,188,298,199,331,190,387,199,331,219,387,159,298,137,149,148,182,148,182,137,149,210,149,148,182,210,149,210,182,210,182,210,149,243,0,210,182,243,0,210,298,210,298,243,0,243,331,210,298,243,331,199,331,159,298,119,182,137,149,137,149,119,182,108,149,137,149,108,149,97,33,97,33,108,149,85,0,97,33,85,0,243,0,68,33,36,33,56,0,68,33,56,0,65,-60,68,33,65,-60,85,0,68,33,85,0,108,149,210,33,97,33,243,0,210,33,243,0,2 [...]
+353,291,318,291,289,258,272,270,253,279,233,285,212,290,190,291,138,283,93,259,57,223,34,178,25,126,27,100,33,75,43,51,56,30,72,11,28,-39,63,-39,92,-6,110,-17,129,-26,148,-33,169,-37,190,-39,242,-30,288,-6,324,28,348,74,356,126,354,152,348,176,338,200,325,221,309,241,16383,16383,287,217,300,201,310,184,317,166,322,147,323,127,316,85,297,48,269,19,232,0,190,-6,174,-5,158,-2,142,2,127,9,113,18,16383,16383,94,36,81,51,71,68,64,86,60,106,58,127,65,168,84,205,112,233,148,252,190,258,208,257,2 [...]
+323,127,316,85,324,28,324,28,316,85,297,48,324,28,297,48,288,-6,288,-6,297,48,269,19,288,-6,269,19,242,-30,242,-30,269,19,232,0,242,-30,232,0,190,-39,190,-39,232,0,190,-6,127,9,129,-26,142,2,142,2,129,-26,148,-33,142,2,148,-33,158,-2,158,-2,148,-33,169,-37,158,-2,169,-37,174,-5,174,-5,169,-37,190,-39,174,-5,190,-39,190,-6,127,9,113,18,129,-26,267,233,113,18,287,217,267,233,287,217,272,270,129,-26,113,18,110,-17,110,-17,113,18,94,36,110,-17,94,36,92,-6,92,-6,94,36,81,51,92,-6,81,51,72,11, [...]
+333,0,185,337,175,337,31,0,16383,16383,272,21,63,21,167,267,
+175,337,31,0,63,21,63,21,31,0,333,0,63,21,333,0,272,21,272,21,333,0,185,337,272,21,185,337,175,337,175,337,63,21,167,267,175,337,167,267,272,21,
+334,331,31,331,180,-5,190,-5,16383,16383,302,310,197,64,93,310,
+334,331,31,331,93,310,334,331,93,310,302,310,334,331,302,310,197,64,334,331,197,64,190,-5,180,-5,190,-5,197,64,180,-5,197,64,93,310,180,-5,93,310,31,331,
+313,-12,313,20,167,20,137,24,111,37,89,57,73,82,64,109,313,109,313,142,65,142,74,170,90,195,112,215,138,228,167,233,313,233,313,266,166,266,121,258,84,238,55,207,37,169,30,126,37,83,55,45,84,14,122,-5,167,-12,
+55,45,84,14,64,109,64,109,65,142,55,45,55,45,65,142,55,207,55,45,55,207,37,83,37,83,55,207,37,169,37,83,37,169,30,126,65,142,64,109,313,109,65,142,313,109,313,142,90,195,112,215,121,258,121,258,112,215,138,228,121,258,138,228,166,266,166,266,138,228,167,233,166,266,167,233,313,266,313,266,167,233,313,233,84,238,55,207,65,142,84,238,65,142,74,170,84,238,74,170,90,195,84,238,90,195,121,258,167,-12,313,-12,313,20,167,-12,313,20,167,20,167,-12,167,20,137,24,167,-12,137,24,122,-5,137,24,111,3 [...]
+313,-12,313,20,154,20,148,22,142,23,136,25,179,109,313,109,313,142,195,142,239,233,313,233,313,266,256,266,289,331,257,331,225,266,166,266,121,258,84,238,55,207,37,169,30,126,33,97,42,70,55,45,73,24,96,7,54,-78,84,-78,121,-5,130,-7,139,-10,157,-12,167,-12,16383,16383,209,233,164,142,65,142,74,170,90,195,112,215,138,228,167,233,16383,16383,147,109,112,37,98,49,86,62,76,77,69,93,64,109,
+96,7,96,7,84,-78,96,7,84,-78,121,-5,96,7,121,-5,98,49,96,7,98,49,86,62,96,7,86,62,76,77,96,7,76,77,73,24,55,45,73,24,64,109,64,109,73,24,69,93,69,93,73,24,76,77,161,20,154,20,157,-12,157,-12,154,20,148,22,157,-12,148,22,148,-11,148,-11,148,22,142,23,148,-11,142,23,139,-10,139,-10,142,23,136,25,139,-10,136,25,130,-7,147,109,112,37,121,-5,147,109,121,-5,130,-7,147,109,130,-7,136,25,147,109,136,25,179,109,147,109,179,109,164,142,147,109,164,142,65,142,147,109,65,142,64,109,167,-12,313,-12,3 [...]
+211,22,211,55,138,55,116,57,97,64,83,75,72,90,65,109,211,109,211,142,65,142,72,162,82,177,97,188,115,194,137,196,211,196,211,229,137,229,102,224,73,210,51,188,37,159,32,126,37,93,51,65,73,42,102,28,137,22,
+83,75,72,90,73,42,73,42,72,90,65,109,73,42,65,109,51,188,73,42,51,188,51,65,51,65,51,188,37,159,51,65,37,159,37,93,37,93,37,159,32,126,82,177,97,188,102,224,102,224,97,188,115,194,102,224,115,194,137,229,137,229,115,194,137,196,51,188,65,109,65,142,65,142,65,109,211,142,211,142,65,109,211,109,211,229,137,229,137,196,211,229,137,196,211,196,73,210,51,188,65,142,73,210,65,142,72,162,73,210,72,162,82,177,73,210,82,177,102,224,97,64,102,28,116,57,116,57,102,28,137,22,116,57,137,22,138,55,138 [...]
+30,266,30,233,175,233,205,228,231,215,253,195,269,170,278,142,30,142,30,109,278,109,269,82,253,57,232,37,205,24,175,20,30,20,30,-12,175,-12,220,-5,258,14,287,45,306,83,312,126,313,126,306,169,288,207,259,238,222,258,177,266,
+269,82,253,57,258,14,258,14,253,57,232,37,258,14,232,37,220,-5,220,-5,232,37,205,24,220,-5,205,24,175,20,177,266,30,266,175,233,177,266,175,233,205,228,177,266,205,228,222,258,312,126,306,169,306,83,306,83,306,169,288,207,306,83,288,207,287,45,287,45,288,207,278,109,287,45,278,109,269,82,231,215,253,195,259,238,259,238,253,195,269,170,259,238,269,170,288,207,288,207,269,170,278,142,288,207,278,142,278,109,222,258,205,228,231,215,222,258,231,215,259,238,175,-12,220,-5,175,20,175,-12,175,2 [...]
+289,331,257,331,222,258,213,261,204,263,196,264,186,265,177,266,30,266,30,233,175,233,182,232,188,232,194,231,200,229,206,228,164,142,30,142,30,109,147,109,103,20,30,20,30,-12,86,-12,54,-78,84,-78,117,-12,175,-12,220,-5,258,14,287,45,306,83,312,126,313,126,310,155,301,183,287,208,269,229,247,247,16383,16383,195,142,230,214,244,203,256,190,266,175,273,159,278,142,16383,16383,278,109,269,82,253,57,232,37,205,24,175,20,133,20,179,109,
+86,-12,54,-78,84,-78,86,-12,84,-78,117,-12,86,-12,117,-12,103,20,86,-12,103,20,30,20,86,-12,30,20,30,-12,147,109,103,20,117,-12,147,109,117,-12,133,20,147,109,133,20,179,109,147,109,179,109,164,142,147,109,164,142,30,142,147,109,30,142,30,109,269,82,253,57,258,14,258,14,253,57,232,37,258,14,232,37,220,-5,220,-5,232,37,205,24,220,-5,205,24,175,20,195,142,230,214,206,228,206,228,213,261,204,263,206,228,204,263,200,229,200,229,204,263,196,264,200,229,196,264,194,231,194,231,196,264,188,232, [...]
+32,229,32,196,105,196,128,194,146,188,161,177,171,162,177,142,32,142,32,109,177,109,171,90,161,75,146,64,127,57,105,55,32,55,32,22,107,22,141,28,170,42,192,65,206,93,211,126,206,159,192,188,170,210,140,224,105,229,
+105,229,32,229,105,229,105,229,32,229,105,196,105,229,105,196,140,224,140,224,105,196,128,194,140,224,128,194,146,188,192,188,177,142,192,65,192,65,177,142,177,109,192,65,177,109,171,90,32,142,32,109,177,109,32,142,177,109,177,142,146,188,161,177,170,210,170,210,161,177,171,162,170,210,171,162,192,188,192,188,171,162,177,142,206,159,192,188,192,65,206,159,192,65,206,93,206,159,206,93,211,126,170,42,192,65,171,90,170,42,171,90,161,75,170,42,161,75,146,64,170,42,146,64,141,28,127,57,105,55 [...]
+243,0,243,320,30,320,30,0,
+243,0,243,320,30,320,243,0,30,320,30,0,
+474,-128,474,-115,465,-115,447,-112,433,-104,424,-92,418,-74,416,-51,416,307,418,330,423,347,434,359,451,366,474,368,474,382,26,382,26,368,35,368,52,366,66,360,76,349,83,331,85,305,85,-60,83,-80,77,-95,67,-106,54,-112,36,-115,26,-115,26,-128,210,-128,210,-115,195,-115,177,-112,165,-104,157,-91,152,-72,151,-48,151,349,350,349,350,-48,349,-69,344,-88,337,-102,324,-111,306,-115,290,-115,290,-128,
+77,-95,67,-106,210,-128,210,-128,67,-106,54,-112,210,-128,54,-112,36,-115,344,-88,337,-102,474,-128,474,-128,337,-102,324,-111,474,-128,324,-111,306,-115,474,382,26,382,35,368,474,382,35,368,52,366,474,382,52,366,66,360,474,382,66,360,76,349,474,382,76,349,151,349,474,382,151,349,350,349,474,382,350,349,434,359,474,382,434,359,451,366,474,382,451,366,474,368,433,-104,424,-92,350,-48,350,-48,424,-92,418,-74,350,-48,418,-74,350,349,350,349,418,-74,416,-51,350,349,416,-51,416,307,350,349,41 [...]
+474,-128,474,-115,451,-112,434,-106,423,-94,418,-77,416,-54,416,304,418,327,424,345,433,358,447,365,465,368,474,368,474,382,290,382,290,368,306,368,324,364,337,355,344,341,349,322,350,300,350,-96,151,-96,151,300,152,325,157,344,165,357,177,365,195,368,210,368,210,382,26,382,26,368,36,368,54,366,67,359,77,348,83,333,85,313,85,-53,83,-78,76,-96,66,-107,52,-113,35,-115,26,-115,26,-128,
+76,-96,66,-107,474,-128,474,-128,66,-107,52,-113,474,-128,52,-113,35,-115,77,348,83,333,210,382,210,382,83,333,177,365,210,382,177,365,195,368,210,382,195,368,210,368,85,313,85,-53,151,-96,85,313,151,-96,151,300,85,313,151,300,152,325,85,313,152,325,157,344,85,313,157,344,165,357,85,313,165,357,177,365,85,313,177,365,83,333,210,382,26,382,36,368,210,382,36,368,54,366,210,382,54,366,67,359,210,382,67,359,77,348,434,-106,423,-94,350,-96,350,-96,423,-94,418,-77,350,-96,418,-77,350,300,349,3 [...]
+428,20,413,20,405,-7,394,-30,379,-48,357,-59,328,-63,121,-63,289,153,144,349,304,349,339,346,364,336,381,318,392,292,400,256,415,256,415,382,41,382,225,126,29,-128,401,-128,
+415,382,41,382,144,349,415,382,144,349,304,349,415,382,304,349,339,346,415,382,339,346,364,336,415,382,364,336,381,318,415,382,381,318,392,292,415,382,392,292,400,256,415,382,400,256,415,256,225,126,29,-128,121,-63,225,126,121,-63,289,153,225,126,289,153,144,349,225,126,144,349,41,382,394,-30,379,-48,401,-128,401,-128,379,-48,357,-59,401,-128,357,-59,328,-63,405,-7,394,-30,401,-128,405,-7,401,-128,428,20,405,-7,428,20,413,20,121,-63,29,-128,401,-128,121,-63,401,-128,328,-63,
+310,110,310,143,32,143,32,110,
+310,110,310,143,32,143,310,110,32,143,32,110,
+319,218,319,251,24,251,24,218,16383,16383,319,54,319,86,188,86,188,191,155,191,155,86,24,86,24,54,155,54,155,-43,188,-43,188,54,
+24,251,24,218,319,218,24,251,319,218,319,251,188,191,155,191,188,-43,188,-43,155,191,155,86,188,-43,155,86,155,54,155,54,155,86,24,86,155,54,24,86,24,54,188,54,319,54,188,86,188,86,319,54,319,86,188,-43,155,54,155,-43,
+203,339,201,349,196,358,189,365,180,369,171,371,161,369,153,365,146,358,141,350,139,339,140,328,145,319,151,313,160,308,171,307,181,309,190,313,197,320,201,329,203,339,16383,16383,318,110,318,143,188,143,188,273,155,273,155,143,24,143,24,110,155,110,155,-20,188,-20,188,110,
+171,371,171,307,180,369,180,369,171,307,181,309,180,369,181,309,189,365,189,365,181,309,190,313,189,365,190,313,196,358,196,358,190,313,197,320,196,358,197,320,201,349,201,349,197,320,201,329,201,349,201,329,203,339,139,339,140,328,141,350,141,350,140,328,145,319,141,350,145,319,146,358,146,358,145,319,151,313,146,358,151,313,153,365,153,365,151,313,160,308,153,365,160,308,161,369,161,369,160,308,171,307,161,369,171,307,171,371,188,273,155,273,188,-20,188,-20,155,273,155,143,188,-20,155, [...]
+239,355,203,355,23,-110,59,-110,
+239,355,203,355,23,-110,239,355,23,-110,59,-110,
+201,46,44,205,12,205,171,46,
+201,46,44,205,12,205,201,46,12,205,171,46,
+228,169,227,175,225,181,221,185,216,189,210,190,208,190,206,189,204,189,202,188,200,186,191,180,182,170,170,158,156,145,137,133,138,153,142,172,146,190,150,204,151,215,150,222,147,227,143,231,138,234,132,235,127,234,121,231,117,227,114,222,113,215,114,204,118,189,122,172,126,153,127,132,111,143,96,155,72,179,62,186,63,186,60,188,58,189,56,189,54,190,51,190,45,189,40,185,37,181,34,175,33,169,34,165,35,162,37,159,40,156,44,153,55,149,70,144,87,139,105,133,122,125,105,117,88,111,71,106,56,1 [...]
+146,63,142,80,143,21,143,21,142,80,138,98,143,21,138,98,138,18,138,18,138,98,137,118,137,133,138,234,132,17,132,17,138,234,132,235,132,17,132,235,127,118,127,118,132,235,127,132,127,118,127,132,122,125,122,125,127,132,111,143,138,153,142,172,143,231,143,231,142,172,146,190,143,231,146,190,147,227,147,227,146,190,150,204,147,227,150,204,150,222,150,222,150,204,151,215,138,234,137,133,138,153,138,234,138,153,143,231,127,118,126,98,127,18,127,118,127,18,132,17,113,37,114,31,114,49,114,49,11 [...]
+155,126,152,147,142,166,128,180,110,190,89,194,67,190,48,181,33,167,24,148,20,127,23,105,33,86,47,72,66,62,88,59,109,62,128,72,142,86,152,105,155,126,16383,16383,122,126,120,115,116,105,108,98,99,93,88,92,77,93,67,98,60,106,55,115,53,127,55,138,59,147,67,154,77,159,89,161,99,159,108,154,116,147,120,137,122,126,
+60,106,66,62,67,98,67,98,66,62,88,59,67,98,88,59,77,93,77,93,88,59,88,92,99,93,88,92,88,59,99,93,88,59,109,62,55,138,59,147,67,190,67,190,59,147,67,154,67,190,67,154,89,194,89,194,67,154,77,159,89,194,77,159,89,161,89,161,99,159,110,190,110,190,99,159,108,154,110,190,108,154,116,147,20,127,23,105,24,148,24,148,23,105,33,86,24,148,33,86,33,167,33,167,33,86,47,72,33,167,47,72,48,181,48,181,47,72,53,127,55,138,67,190,48,181,55,138,48,181,53,127,155,126,152,147,152,105,152,105,152,147,142,16 [...]
+155,126,152,147,142,166,128,180,110,190,89,194,67,190,48,181,33,167,24,148,20,127,23,105,33,86,47,72,66,62,88,59,109,62,128,72,142,86,152,105,155,126,
+20,127,23,105,24,148,24,148,23,105,33,86,24,148,33,86,33,167,33,167,33,86,47,72,33,167,47,72,48,181,48,181,47,72,66,62,48,181,66,62,67,190,67,190,66,62,88,59,67,190,88,59,89,194,89,194,88,59,109,62,89,194,109,62,110,190,110,190,109,62,128,72,110,190,128,72,128,180,128,180,128,72,142,86,128,180,142,86,142,166,142,166,142,86,152,105,142,166,152,105,152,147,152,147,152,105,155,126,
+482,487,454,487,248,-45,246,-45,143,222,134,222,56,160,62,150,69,155,83,163,89,165,94,165,102,164,108,161,114,155,120,147,126,136,227,-128,243,-128,
+76,159,83,163,134,222,134,222,83,163,89,165,134,222,89,165,94,165,94,165,102,164,134,222,134,222,102,164,108,161,134,222,108,161,114,155,143,222,134,222,227,-128,227,-128,134,222,126,136,120,147,126,136,134,222,120,147,134,222,114,155,134,222,56,160,62,150,134,222,62,150,69,155,134,222,69,155,76,159,143,222,227,-128,246,-45,246,-45,227,-128,243,-128,246,-45,243,-128,248,-45,248,-45,243,-128,482,487,248,-45,482,487,454,487,
+149,381,156,391,162,399,169,404,177,407,185,408,195,407,202,404,208,399,212,392,213,382,211,369,204,359,195,351,183,345,171,340,171,335,184,335,189,334,193,333,196,333,206,328,213,323,219,315,222,306,223,296,222,284,217,274,210,266,201,261,190,259,186,260,182,260,178,262,173,264,168,267,164,270,161,272,152,275,146,273,144,271,142,268,142,265,143,260,146,255,152,251,160,249,171,248,193,250,214,257,231,269,242,286,247,307,245,320,240,331,233,340,223,347,210,352,218,358,224,365,229,373,232, [...]
+158,273,160,249,161,272,161,272,160,249,171,248,161,272,171,248,164,270,164,270,171,248,168,267,173,264,168,267,171,248,173,264,171,248,193,250,149,381,156,391,156,407,156,407,156,391,162,399,156,407,162,399,166,416,166,416,162,399,169,404,166,416,169,404,178,421,178,421,169,404,177,407,178,421,177,407,185,408,185,408,195,407,193,423,193,423,195,407,206,421,149,396,143,382,149,381,149,396,149,381,156,407,184,335,189,334,195,351,195,351,189,334,193,333,195,351,193,333,196,333,196,333,206, [...]
+252,291,252,312,225,312,225,421,210,421,131,312,131,291,201,291,201,249,225,249,225,291,16383,16383,201,312,142,312,201,395,16383,16383,482,487,454,487,248,-45,246,-45,143,222,134,222,56,160,62,150,69,155,83,163,89,165,94,165,102,164,108,161,114,155,120,147,126,136,227,-128,243,-128,
+131,291,201,291,131,312,131,312,201,291,142,312,131,312,142,312,210,421,210,421,142,312,201,395,210,421,201,395,225,249,225,249,201,395,201,312,225,249,201,312,201,291,201,291,201,312,142,312,210,421,225,249,225,421,225,312,225,291,252,291,225,312,252,291,252,312,76,159,83,163,134,222,134,222,83,163,89,165,134,222,89,165,94,165,94,165,102,164,134,222,134,222,102,164,108,161,134,222,108,161,114,155,143,222,134,222,227,-128,227,-128,134,222,126,136,120,147,126,136,134,222,120,147,134,222,1 [...]
+321,42,304,45,287,54,270,70,253,92,235,121,235,123,245,137,258,150,275,162,296,170,321,173,321,215,294,211,272,201,254,185,239,165,225,142,199,174,177,195,156,207,137,213,116,215,95,212,70,201,46,180,28,147,21,100,26,63,39,35,59,15,83,4,108,0,135,3,159,12,180,27,198,47,213,73,232,47,250,27,271,12,294,3,321,0,16383,16383,202,90,193,78,180,66,164,54,144,45,120,42,96,47,76,59,62,78,53,101,50,126,53,144,60,161,71,174,85,182,100,185,121,181,140,169,160,150,181,124,202,92,
+213,73,232,47,213,73,213,73,232,47,225,142,213,73,225,142,202,92,202,92,199,174,181,124,181,124,199,174,177,195,181,124,177,195,160,150,160,150,177,195,156,207,160,150,156,207,140,169,140,169,156,207,137,213,140,169,137,213,121,181,121,181,137,213,116,215,121,181,116,215,100,185,53,144,60,161,70,201,70,201,60,161,71,174,70,201,71,174,95,212,95,212,71,174,85,182,95,212,85,182,100,185,21,100,26,63,28,147,28,147,26,63,39,35,28,147,39,35,46,180,46,180,39,35,59,15,46,180,59,15,50,126,50,126,5 [...]
+427,111,422,148,408,177,387,198,363,210,336,215,309,211,287,201,269,185,253,165,239,142,213,174,191,195,171,207,151,213,131,215,110,212,84,201,60,180,42,147,35,100,40,63,54,35,73,15,97,4,123,0,150,3,174,12,195,27,213,47,228,73,246,47,264,27,284,12,305,3,328,0,363,7,390,25,410,51,423,81,427,111,16383,16383,249,123,259,136,270,149,285,161,304,170,328,173,352,169,371,157,385,138,394,115,397,89,394,70,387,54,377,41,363,33,347,30,327,33,308,45,290,63,270,89,249,121,16383,16383,217,90,207,78,1 [...]
+228,73,246,47,228,73,228,73,246,47,239,142,228,73,239,142,217,92,217,92,213,174,195,124,195,124,213,174,191,195,195,124,191,195,175,150,175,150,191,195,171,207,175,150,171,207,155,169,155,169,171,207,151,213,155,169,151,213,135,181,135,181,151,213,131,215,135,181,131,215,115,185,67,144,74,161,84,201,84,201,74,161,85,174,84,201,85,174,110,212,110,212,85,174,99,182,110,212,99,182,115,185,35,100,40,63,42,147,42,147,40,63,54,35,42,147,54,35,60,180,60,180,54,35,73,15,60,180,73,15,65,126,65,12 [...]
+317,0,317,33,58,33,58,292,25,292,25,0,
+58,33,58,292,25,292,58,33,25,292,25,0,58,33,25,0,317,0,58,33,317,0,317,33,
+321,0,321,33,91,33,310,252,285,273,12,0,
+91,33,310,252,285,273,91,33,285,273,12,0,91,33,12,0,321,0,91,33,321,0,321,33,
+321,0,321,33,271,33,265,61,257,88,247,113,233,138,218,160,310,252,284,273,196,185,186,195,174,205,169,209,148,182,168,166,172,161,11,0,239,0,239,-18,238,-24,238,-30,270,-35,272,-21,272,0,16383,16383,90,33,194,137,207,118,217,98,226,77,233,56,237,33,
+90,33,194,137,172,161,172,161,174,205,169,209,172,161,169,209,168,166,168,166,169,209,163,170,169,209,148,182,153,178,169,209,153,178,158,174,169,209,158,174,163,170,194,137,207,118,196,185,196,185,207,118,218,160,196,185,218,160,284,273,284,273,218,160,310,252,207,118,217,98,218,160,218,160,217,98,226,77,218,160,226,77,233,138,233,138,226,77,233,56,233,138,233,56,237,33,194,137,196,185,191,190,194,137,191,190,186,195,194,137,186,195,180,200,194,137,180,200,174,205,194,137,174,205,172,16 [...]
+326,40,281,59,284,72,286,86,288,99,290,127,289,140,288,154,286,168,280,196,326,216,314,246,269,228,266,234,263,241,257,253,253,259,225,243,228,237,231,232,233,226,236,220,238,215,28,127,239,40,237,34,234,29,232,23,229,17,225,12,254,-5,258,1,261,8,265,14,268,21,270,27,314,9,16383,16383,114,127,249,184,252,172,254,161,255,149,257,127,256,115,254,93,252,82,249,71,
+256,115,258,1,257,127,257,127,258,1,260,247,260,247,258,1,261,8,260,247,261,8,263,241,263,241,261,8,265,14,263,241,265,14,266,234,266,234,265,14,268,21,266,234,268,21,269,228,269,228,268,21,270,27,269,228,270,27,280,196,280,196,270,27,281,59,280,196,281,59,283,182,283,182,281,59,284,72,283,182,284,72,286,168,286,168,284,72,286,86,286,168,286,86,288,154,288,154,286,86,288,99,288,154,288,99,289,140,289,140,288,99,289,113,289,140,289,113,290,127,314,9,326,40,281,59,314,9,281,59,270,27,314,2 [...]
+83,-93,83,345,50,345,50,-93,
+83,-93,83,345,50,345,83,-93,50,345,50,-93,
+190,152,179,178,118,147,118,345,84,345,84,130,12,93,23,66,84,98,84,-93,118,-93,118,114,
+84,130,12,93,23,66,84,130,23,66,84,98,84,130,84,98,118,-93,84,130,118,-93,84,345,84,345,118,-93,118,345,118,147,118,114,190,152,118,147,190,152,179,178,118,-93,84,98,84,-93,
+197,-93,197,345,164,345,164,-93,16383,16383,98,-93,98,345,65,345,65,-93,
+164,345,164,-93,197,-93,164,345,197,-93,197,345,65,345,65,-93,98,-93,65,345,98,-93,98,345,
+293,181,281,207,219,175,219,345,185,345,185,158,119,125,119,345,86,345,86,108,12,70,23,44,86,75,86,-93,119,-93,119,93,185,126,185,-93,219,-93,219,143,
+86,108,12,70,23,44,86,108,23,44,86,75,86,108,86,75,119,-93,86,108,119,-93,86,345,219,345,185,345,219,-93,219,-93,185,345,185,158,219,-93,185,158,185,126,185,126,185,158,119,125,185,126,119,125,119,93,119,-93,119,345,86,345,219,143,293,181,219,175,219,175,293,181,281,207,219,-93,185,126,185,-93,119,-93,86,75,86,-93,
+295,-14,157,268,152,268,16,-14,47,-14,155,201,262,-14,
+16,-14,47,-14,152,268,152,268,47,-14,155,201,152,268,155,201,157,268,157,268,155,201,262,-14,157,268,262,-14,295,-14,
+295,268,263,268,156,52,48,268,16,268,153,-14,158,-14,
+295,268,263,268,158,-14,158,-14,263,268,156,52,158,-14,156,52,153,-14,153,-14,156,52,48,268,153,-14,48,268,16,268,
+286,-15,286,132,280,177,261,215,233,243,197,261,155,268,113,262,77,244,49,216,30,178,24,134,24,-15,57,-15,57,132,62,165,76,193,97,215,124,230,155,235,186,230,212,215,234,193,248,165,253,132,253,-15,
+253,132,253,132,248,165,248,165,253,132,261,215,248,165,261,215,234,193,234,193,261,215,233,243,234,193,233,243,212,215,212,215,233,243,197,261,212,215,197,261,186,230,186,230,197,261,155,235,124,230,155,235,155,268,124,230,155,268,113,262,62,165,76,193,77,244,77,244,76,193,97,215,77,244,97,215,113,262,113,262,97,215,124,230,49,216,30,178,57,-15,49,216,57,-15,57,132,49,216,57,132,62,165,49,216,62,165,77,244,24,134,24,-15,57,-15,24,134,57,-15,30,178,197,261,155,268,155,235,286,-15,286,132 [...]
+286,268,253,268,253,120,248,87,234,59,212,37,186,23,155,17,124,23,97,37,76,60,62,88,57,121,57,268,24,268,24,118,30,74,49,37,77,9,113,-8,155,-15,197,-8,233,9,261,38,280,75,286,120,
+253,120,248,87,261,38,261,38,248,87,234,59,261,38,234,59,233,9,233,9,234,59,212,37,233,9,212,37,197,-8,197,-8,212,37,186,23,197,-8,186,23,155,-15,155,-15,186,23,155,17,286,268,253,268,261,38,286,268,261,38,280,75,286,268,280,75,286,120,76,60,77,9,97,37,97,37,77,9,113,-8,97,37,113,-8,124,23,124,23,113,-8,155,-15,124,23,155,-15,155,17,62,88,57,121,49,37,62,88,49,37,77,9,62,88,77,9,76,60,57,268,24,268,30,74,57,268,30,74,49,37,57,268,49,37,57,121,30,74,24,268,24,118,253,120,261,38,253,268,
+102,-61,94,-89,86,-112,77,-129,67,-140,54,-144,52,-143,50,-143,49,-142,49,-137,52,-135,54,-132,57,-127,57,-116,54,-112,51,-109,46,-108,42,-107,34,-109,27,-113,21,-119,18,-127,16,-136,18,-143,22,-150,28,-155,37,-158,49,-159,78,-153,102,-135,119,-111,131,-84,140,-58,231,308,239,337,247,362,257,380,268,393,281,397,283,397,285,396,287,394,287,392,286,390,284,387,281,384,279,379,278,372,279,368,281,364,289,360,294,360,302,361,309,366,315,372,318,380,320,390,318,396,314,402,307,407,298,411,287 [...]
+49,-140,49,-137,51,-109,51,-109,49,-137,52,-135,51,-109,52,-135,54,-112,54,-112,52,-135,54,-132,54,-112,54,-132,57,-116,57,-116,54,-132,57,-127,57,-116,57,-127,57,-120,18,-127,18,-143,21,-119,21,-119,18,-143,22,-150,21,-119,22,-150,27,-113,27,-113,22,-150,28,-155,27,-113,28,-155,34,-109,34,-109,28,-155,37,-158,34,-109,37,-158,42,-107,42,-107,37,-158,49,-159,42,-107,49,-159,46,-108,46,-108,49,-159,49,-140,86,-112,77,-129,78,-153,78,-153,77,-129,67,-140,78,-153,67,-140,54,-144,54,-144,52,- [...]
+223,-61,215,-89,207,-112,198,-129,188,-140,175,-144,173,-143,172,-143,170,-142,170,-140,171,-137,173,-135,175,-132,178,-127,179,-120,178,-116,175,-112,172,-109,168,-108,163,-107,155,-109,148,-113,142,-119,139,-127,137,-136,138,-143,141,-150,146,-155,154,-158,165,-159,195,-153,219,-135,238,-111,252,-84,261,-58,352,308,360,337,368,362,378,380,389,393,402,397,404,397,406,396,408,394,408,392,407,390,405,387,402,384,400,379,399,372,400,368,402,364,410,360,415,360,423,361,430,366,435,372,439,3 [...]
+49,-137,51,-109,49,-140,49,-140,46,-108,44,-159,44,-159,46,-108,42,-107,44,-159,42,-107,34,-109,51,-109,52,-135,54,-112,54,-112,52,-135,54,-132,54,-112,54,-132,57,-116,57,-116,54,-132,57,-127,57,-116,57,-127,57,-120,94,-89,86,-112,98,-135,98,-135,86,-112,77,-129,98,-135,77,-129,74,-153,74,-153,77,-129,67,-140,74,-153,67,-140,54,-144,54,-144,52,-143,74,-153,74,-153,52,-143,50,-143,74,-153,50,-143,44,-159,44,-159,50,-143,49,-142,44,-159,49,-142,49,-141,171,-137,172,-109,170,-140,170,-140,1 [...]
+344,-61,336,-89,328,-112,319,-129,309,-140,296,-144,294,-143,293,-143,291,-141,291,-140,292,-137,297,-132,299,-127,300,-120,299,-116,296,-112,293,-109,288,-108,284,-107,276,-109,269,-113,263,-119,259,-127,258,-136,259,-143,262,-150,267,-155,275,-158,286,-159,316,-153,341,-135,359,-111,373,-84,382,-58,473,308,481,337,489,362,499,380,510,393,523,397,525,397,527,396,529,394,529,392,528,390,526,387,523,384,521,379,520,372,521,368,523,364,531,360,536,360,544,361,551,366,556,372,560,380,561,39 [...]
+49,-137,51,-109,49,-140,49,-140,46,-108,44,-159,44,-159,46,-108,42,-107,44,-159,42,-107,34,-109,51,-109,52,-135,54,-112,54,-112,52,-135,54,-132,54,-112,54,-132,57,-116,57,-116,54,-132,57,-127,57,-116,57,-127,57,-120,94,-89,86,-112,98,-135,98,-135,86,-112,77,-129,98,-135,77,-129,74,-153,74,-153,77,-129,67,-140,74,-153,67,-140,54,-144,54,-144,52,-143,74,-153,74,-153,52,-143,50,-143,74,-153,50,-143,44,-159,44,-159,50,-143,49,-142,44,-159,49,-142,49,-141,170,-137,171,-109,169,-140,169,-140,1 [...]
+176,238,167,238,131,232,101,216,76,192,60,161,55,126,58,99,67,74,81,53,100,35,123,22,102,-61,94,-89,86,-112,77,-129,67,-140,54,-144,52,-143,50,-143,49,-142,49,-137,52,-135,54,-132,57,-127,57,-116,54,-112,51,-109,46,-108,42,-107,34,-109,27,-113,21,-119,18,-127,16,-136,18,-143,22,-150,28,-155,37,-158,49,-159,78,-153,102,-135,119,-111,131,-84,140,-58,157,13,167,13,202,19,233,35,258,59,274,90,280,126,276,152,267,177,253,199,234,216,211,229,231,308,239,337,247,362,257,381,268,393,281,397,283, [...]
+49,-140,49,-137,51,-109,51,-109,49,-137,52,-135,51,-109,52,-135,54,-112,54,-112,52,-135,54,-132,54,-112,54,-132,57,-116,57,-116,54,-132,57,-127,57,-116,57,-127,57,-120,18,-127,18,-143,21,-119,21,-119,18,-143,22,-150,21,-119,22,-150,27,-113,27,-113,22,-150,28,-155,27,-113,28,-155,34,-109,34,-109,28,-155,37,-158,34,-109,37,-158,42,-107,42,-107,37,-158,49,-159,42,-107,49,-159,46,-108,46,-108,49,-159,49,-140,86,-112,77,-129,78,-153,78,-153,77,-129,67,-140,78,-153,67,-140,54,-144,54,-144,52,- [...]
+296,231,284,234,271,236,258,237,244,238,214,238,231,308,239,337,247,362,257,380,268,393,281,397,283,397,285,396,287,394,287,392,286,390,284,387,281,384,279,379,278,372,279,368,281,364,289,360,294,360,302,361,309,366,315,372,318,380,320,390,319,396,316,402,310,407,302,411,292,412,260,404,234,385,215,358,201,330,193,303,175,233,135,222,101,204,76,182,61,155,55,126,58,104,67,84,82,65,102,48,126,35,102,-61,94,-89,86,-112,77,-129,67,-140,54,-144,52,-143,50,-143,49,-142,49,-137,52,-135,54,-132 [...]
+49,-137,51,-109,49,-140,49,-140,46,-108,44,-159,44,-159,46,-108,42,-107,44,-159,42,-107,34,-109,51,-109,52,-135,54,-112,54,-112,52,-135,54,-132,54,-112,54,-132,57,-116,57,-116,54,-132,57,-127,57,-116,57,-127,57,-120,94,-89,86,-112,99,-135,99,-135,86,-112,77,-129,99,-135,77,-129,74,-153,74,-153,77,-129,67,-140,74,-153,67,-140,54,-144,54,-144,52,-143,74,-153,74,-153,52,-143,50,-143,74,-153,50,-143,44,-159,44,-159,50,-143,49,-142,44,-159,49,-142,49,-141,96,78,102,48,111,65,111,65,102,48,126 [...]
+319,60,319,93,170,93,200,160,319,160,319,193,214,193,274,331,247,331,187,193,24,193,24,160,172,160,143,93,24,93,24,60,128,60,69,-77,95,-77,156,60,
+128,60,69,-77,95,-77,128,60,95,-77,156,60,128,60,156,60,143,93,128,60,143,93,24,93,128,60,24,93,24,60,172,160,143,93,156,60,172,160,156,60,170,93,172,160,170,93,200,160,172,160,200,160,187,193,172,160,187,193,24,193,172,160,24,193,24,160,214,193,274,331,247,331,214,193,247,331,200,160,214,193,200,160,319,160,214,193,319,160,319,193,170,93,156,60,319,60,170,93,319,60,319,93,187,193,200,160,247,331,
+319,206,319,239,24,239,24,206,16383,16383,319,110,319,143,24,143,24,110,16383,16383,319,14,319,47,24,47,24,14,
+24,239,24,206,319,206,24,239,319,206,319,239,24,143,24,110,319,110,24,143,319,110,319,143,24,47,24,14,319,14,24,47,319,14,319,47,
+319,14,319,47,150,47,177,110,319,110,319,143,192,143,219,206,319,206,319,239,233,239,274,331,247,331,207,239,24,239,24,206,193,206,165,143,24,143,24,110,151,110,123,47,24,47,24,14,108,14,69,-77,95,-77,136,14,
+108,14,69,-77,95,-77,108,14,95,-77,136,14,108,14,136,14,123,47,108,14,123,47,24,47,108,14,24,47,24,14,151,110,123,47,136,14,151,110,136,14,150,47,151,110,150,47,177,110,151,110,177,110,165,143,151,110,165,143,24,143,151,110,24,143,24,110,193,206,165,143,177,110,193,206,177,110,192,143,193,206,192,143,219,206,193,206,219,206,207,239,193,206,207,239,24,239,193,206,24,239,24,206,233,239,274,331,247,331,233,239,247,331,219,206,233,239,219,206,319,206,233,239,319,206,319,239,192,143,177,110,3 [...]
+319,239,319,272,24,272,24,239,16383,16383,319,153,319,186,24,186,24,153,16383,16383,319,67,319,100,24,100,24,67,16383,16383,319,-18,319,14,24,14,24,-18,
+24,272,24,239,319,239,24,272,319,239,319,272,24,186,24,153,319,153,24,186,319,153,319,186,24,100,24,67,319,67,24,100,319,67,319,100,24,14,24,-18,319,-18,24,14,319,-18,319,14,
+315,26,315,57,99,165,315,272,315,305,32,167,32,162,16383,16383,315,-50,315,-17,32,-17,32,-50,
+99,165,315,272,315,305,99,165,315,305,32,167,99,165,32,167,315,26,99,165,315,26,315,57,32,-17,32,-50,315,-50,32,-17,315,-50,315,-17,315,26,32,167,32,162,
+315,162,315,167,32,305,32,272,248,165,32,57,32,26,16383,16383,315,-50,315,-17,32,-17,32,-50,
+248,165,32,57,315,162,248,165,315,162,315,167,248,165,315,167,32,305,248,165,32,305,32,272,32,-17,32,-50,315,-50,32,-17,315,-50,315,-17,315,162,32,57,32,26,
+311,80,311,112,95,219,311,326,311,359,28,222,28,217,16383,16383,311,-5,311,27,28,27,28,-5,16383,16383,311,-104,311,-72,28,-72,28,-104,
+95,219,311,326,311,359,95,219,311,359,28,222,95,219,28,222,311,80,95,219,311,80,311,112,28,27,28,-5,311,-5,28,27,311,-5,311,27,28,-72,28,-104,311,-104,28,-72,311,-104,311,-72,311,80,28,222,28,217,
+311,217,311,222,28,359,28,326,244,219,28,112,28,80,16383,16383,311,-5,311,27,28,27,28,-5,16383,16383,311,-104,311,-72,28,-72,28,-104,
+244,219,28,112,311,217,244,219,311,217,311,222,244,219,311,222,28,359,244,219,28,359,28,326,28,27,28,-5,311,-5,28,27,311,-5,311,27,28,-72,28,-104,311,-104,28,-72,311,-104,311,-72,311,217,28,112,28,80,
+310,94,310,126,94,233,310,340,310,373,28,235,28,230,16383,16383,310,-91,310,-58,158,-58,200,8,310,8,310,41,221,41,245,79,215,79,191,41,28,41,28,8,171,8,128,-58,28,-58,28,-91,108,-91,84,-129,114,-129,138,-91,
+94,233,310,340,310,373,94,233,310,373,28,235,94,233,28,235,310,94,94,233,310,94,310,126,28,41,171,8,191,41,191,41,171,8,200,8,191,41,200,8,215,79,215,79,200,8,221,41,215,79,221,41,245,79,221,41,200,8,310,8,221,41,310,8,310,41,108,-91,114,-129,128,-58,128,-58,114,-129,138,-91,128,-58,138,-91,171,8,171,8,138,-91,158,-58,171,8,158,-58,200,8,28,-58,28,-91,108,-91,28,-58,108,-91,128,-58,158,-58,138,-91,310,-91,158,-58,310,-91,310,-58,114,-129,108,-91,84,-129,171,8,28,41,28,8,310,94,28,235,28,230,
+310,230,310,235,28,373,28,340,244,233,28,126,28,94,16383,16383,310,-91,310,-58,165,-58,207,8,310,8,310,41,228,41,252,79,222,79,198,41,28,41,28,8,177,8,135,-58,28,-58,28,-91,114,-91,91,-129,121,-129,145,-91,
+244,233,28,126,310,230,244,233,310,230,310,235,244,233,310,235,28,373,244,233,28,373,28,340,28,41,177,8,198,41,198,41,177,8,207,8,198,41,207,8,222,79,222,79,207,8,228,41,222,79,228,41,252,79,228,41,207,8,310,8,228,41,310,8,310,41,114,-91,121,-129,135,-58,135,-58,121,-129,145,-91,135,-58,145,-91,177,8,177,8,145,-91,165,-58,177,8,165,-58,207,8,28,-58,28,-91,114,-91,28,-58,114,-91,135,-58,165,-58,145,-91,310,-91,165,-58,310,-91,310,-58,121,-129,114,-91,91,-129,177,8,28,41,28,8,310,230,28,12 [...]
+454,-12,454,18,238,127,454,233,454,266,171,129,171,124,16383,16383,295,-12,295,18,79,127,295,233,295,266,12,129,12,124,
+238,127,454,233,454,266,238,127,454,266,171,129,238,127,171,129,454,-12,238,127,454,-12,454,18,79,127,295,233,295,266,79,127,295,266,12,129,79,127,12,129,295,-12,79,127,295,-12,295,18,295,-12,12,129,12,124,454,-12,171,129,171,124,
+454,124,454,129,171,266,171,233,387,127,171,18,171,-12,16383,16383,295,124,295,129,12,266,12,233,228,127,12,18,12,-12,
+387,127,171,18,454,124,387,127,454,124,454,129,387,127,454,129,171,266,387,127,171,266,171,233,228,127,12,18,295,124,228,127,295,124,295,129,228,127,295,129,12,266,228,127,12,266,12,233,295,124,12,18,12,-12,454,124,171,18,171,-12,
+190,-102,179,-89,167,-74,154,-59,130,-25,149,4,165,35,176,66,183,97,185,127,183,156,176,187,164,218,149,248,130,278,142,296,154,312,167,328,179,342,190,355,190,365,174,353,158,340,143,326,130,312,117,296,103,312,89,326,74,340,59,353,42,365,42,357,66,329,78,313,91,296,103,278,84,249,68,218,57,187,50,156,47,127,50,97,57,66,68,35,84,4,103,-25,91,-42,78,-58,66,-74,42,-102,42,-111,59,-99,89,-73,117,-43,143,-73,158,-86,174,-99,190,-111,16383,16383,152,127,151,98,146,70,138,45,128,20,116,-2,104 [...]
+130,278,142,296,143,326,143,326,142,296,154,312,143,326,154,312,158,340,158,340,154,312,167,328,158,340,167,328,174,353,174,353,167,328,179,342,174,353,179,342,190,365,190,365,179,342,190,355,117,296,103,312,105,233,117,296,105,233,117,256,117,256,128,233,130,312,130,312,128,233,130,278,130,312,130,278,143,326,116,-2,117,-43,128,20,128,20,117,-43,130,-58,128,20,130,-58,130,-25,130,-25,130,-58,143,-73,130,-25,138,45,128,20,183,97,183,156,176,66,176,66,183,156,176,187,176,66,176,187,165,35 [...]
+319,22,300,49,273,71,242,87,207,96,174,100,198,155,227,162,255,173,281,188,303,208,319,232,319,249,302,230,283,215,261,204,237,195,213,190,254,286,228,286,184,186,171,186,138,188,105,195,75,206,47,224,24,249,24,232,43,204,69,182,101,166,135,156,170,153,146,98,116,92,88,81,61,65,40,46,24,22,24,4,40,22,60,38,82,49,106,58,131,64,89,-32,116,-32,159,66,161,67,171,67,204,65,237,58,268,46,295,28,319,4,
+40,22,60,38,61,65,61,65,60,38,82,49,61,65,82,49,88,81,88,81,82,49,106,58,88,81,106,58,116,92,116,92,106,58,131,64,146,98,131,64,159,66,146,98,159,66,170,153,170,153,159,66,161,67,170,153,161,67,164,67,40,22,61,65,40,46,40,22,40,46,24,22,40,22,24,22,24,4,135,156,170,153,138,188,138,188,170,153,171,186,173,186,171,186,171,67,173,186,171,67,174,100,174,100,171,67,204,65,174,100,204,65,207,96,207,96,204,65,237,58,207,96,237,58,242,87,242,87,237,58,268,46,242,87,268,46,273,71,273,71,268,46,29 [...]
+310,-12,310,18,171,88,214,185,310,233,310,266,232,228,277,331,250,331,198,211,28,128,28,123,137,71,71,-77,99,-77,158,60,16383,16383,179,168,148,99,94,126,
+198,211,28,128,94,126,94,126,28,128,137,71,94,126,137,71,148,99,148,99,137,71,158,60,148,99,158,60,179,168,179,168,158,60,171,88,179,168,171,88,214,185,94,126,179,168,198,211,198,211,179,168,214,185,198,211,214,185,250,331,250,331,214,185,232,228,250,331,232,228,277,331,137,71,71,-77,99,-77,137,71,99,-77,158,60,232,228,214,185,310,233,232,228,310,233,310,266,171,88,158,60,310,-12,171,88,310,-12,310,18,137,71,28,128,28,123,
+310,123,310,128,203,181,268,331,241,331,180,192,28,266,28,233,168,164,126,68,28,18,28,-12,108,26,63,-77,89,-77,142,42,16383,16383,244,126,161,84,190,153,
+108,26,63,-77,89,-77,108,26,89,-77,142,42,108,26,142,42,126,68,108,26,126,68,28,18,108,26,28,18,28,-12,168,164,126,68,142,42,168,164,142,42,161,84,168,164,161,84,190,153,168,164,190,153,180,192,168,164,180,192,28,266,168,164,28,266,28,233,203,181,268,331,241,331,203,181,241,331,190,153,203,181,190,153,244,126,203,181,244,126,310,128,310,123,310,128,244,126,310,123,244,126,161,84,310,123,161,84,142,42,180,192,190,153,241,331,
+320,0,320,33,190,33,190,331,157,331,157,33,26,33,26,0,
+190,331,157,331,190,33,190,33,157,331,157,33,190,33,157,33,320,0,320,0,157,33,26,33,320,0,26,33,26,0,190,33,320,0,320,33,
+};
diff --git a/src/eval.cpp b/src/eval.cpp
new file mode 100644
index 0000000..23db683
--- /dev/null
+++ b/src/eval.cpp
@@ -0,0 +1,753 @@
+/***************************************************************************
+ * eval.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <time.h>
+#include <ctype.h>
+
+#include "mgl2/data_cf.h"
+#include "mgl2/eval.h"
+
+#if MGL_HAVE_GSL
+#include <gsl/gsl_sf.h>
+#include <gsl/gsl_rng.h>
+#include <gsl/gsl_errno.h>
+#include <sys/stat.h>
+#endif
+//-----------------------------------------------------------------------------
+//	constants for expression parsing
+enum{
+EQ_NUM=0,	// a variable substitution
+EQ_RND,		// random number
+EQ_A,		// numeric constant
+// normal functions of 2 arguments
+EQ_LT,		// comparison x<y			!!! MUST BE FIRST 2-PLACE FUNCTION
+EQ_GT,		// comparison x>y
+EQ_EQ,		// comparison x=y
+EQ_OR,		// comparison x|y
+EQ_AND,		// comparison x&y
+EQ_ADD,		// addition x+y
+EQ_SUB,		// substraction x-y
+EQ_MUL,		// multiplication x*y
+EQ_DIV,		// division x/y
+EQ_IPOW,		// power x^n for integer n
+EQ_POW,		// power x^y
+EQ_MOD,		// x modulo y
+EQ_LOG,		// logarithm of x on base a, log_a(x) = ln(x)/ln(a)
+EQ_ARG,		// argument of complex number arg(x,y) = atan2(x,y)
+EQ_HYPOT,	// sqrt(x^2+y^2)=hypot(x,y)
+EQ_MAX,		// maximum of x and y
+EQ_MIN,		// minimum of x and y
+// special functions of 2 arguments
+EQ_BESJ,		// regular cylindrical Bessel function of fractional order
+EQ_BESY,		// irregular cylindrical Bessel function of fractional order
+EQ_BESI,		// regular modified Bessel function of fractional order
+EQ_BESK,		// irregular modified Bessel function of fractional order
+EQ_ELE,		// elliptic integral E(\phi,k) = \int_0^\phi dt   \sqrt((1 - k^2 \sin^2(t)))
+EQ_ELF,		// elliptic integral F(\phi,k) = \int_0^\phi dt 1/\sqrt((1 - k^2 \sin^2(t)))
+EQ_LP,		// Legendre polynomial P_l(x), (|x|<=1, l>=0)
+EQ_BETA,	// beta function B(x,y) = Gamma(x)*Gamma(y)/Gamma(x+y)
+EQ_GAMMA_INC,	// incomplete gamma function Gamma(a,x) = \int_x^\infty dt t^{a-1} \exp(-t) for x>=0.
+// normal functions of 1 argument
+EQ_SIN,		// sine function \sin(x).			!!! MUST BE FIRST 1-PLACE FUNCTION
+EQ_COS,		// cosine function \cos(x).
+EQ_TAN,		// tangent function \tan(x).
+EQ_ASIN,		// inverse sine function \sin(x).
+EQ_ACOS,		// inverse cosine function \sin(x).
+EQ_ATAN,		// inverse tangent function \tan(x).
+EQ_SINH,		// hyperbolic sine function \sin(x).
+EQ_COSH,		// hyperbolic cosine function \sin(x).
+EQ_TANH,		// hyperbolic tangent function \tan(x).
+EQ_ASINH,	// inverse hyperbolic sine function \sin(x).
+EQ_ACOSH,	// inverse hyperbolic cosine function \sin(x).
+EQ_ATANH,	// inverse hyperbolic tangent function \tan(x).
+EQ_SQRT,		// square root function \sqrt(x)
+EQ_EXP,		// exponential function \exp(x)
+EQ_LN,		// logarithm of x, ln(x)
+EQ_LG,		// decimal logarithm of x, lg(x) = ln(x)/ln(10)
+EQ_SIGN,	// sign of number
+EQ_STEP,		// step function
+EQ_INT,		// integer part [x]
+EQ_ABS,		// absolute value of x
+// special functions of 1 argument
+EQ_LI2,		// dilogarithm for a real argument Li2(x) = - \Re \int_0^x ds \log(1-s)/s.
+EQ_ELLE,		// complete elliptic integral is denoted by E(k) = E(\pi/2, k).
+EQ_ELLK,		// complete elliptic integral is denoted by K(k) = F(\pi/2, k).
+EQ_AI,		// Airy function Ai(x)
+EQ_BI,		// Airy function Bi(x)
+EQ_ERF,		// error function erf(x) = (2/\sqrt(\pi)) \int_0^x dt \exp(-t^2).
+EQ_EI3,		// exponential integral Ei_3(x) = \int_0^x dt \exp(-t^3) for x >= 0.
+EQ_EI,		// exponential integral Ei(x),  Ei(x) := - PV(\int_{-x}^\infty dt \exp(-t)/t), where PV denotes the principal value of the integral.
+EQ_E1,		// exponential integral E_1(x), E_1(x) := Re \int_1^\infty dt \exp(-xt)/t.
+EQ_E2,		// exponential integral E_2(x), E_2(x) := Re \int_1^\infty dt \exp(-xt)/t^2.
+EQ_SI,		// Sine integral Si(x) = \int_0^x dt \sin(t)/t.
+EQ_CI,		// Cosine integral Ci(x) = \int_0^x dt \cos(t)/t.
+EQ_GAMMA,	// Gamma function \Gamma(x) = \int_0^\infty dt  t^{x-1} \exp(-t)
+EQ_PSI,		// digamma function \psi(x) = \Gamma'(x)/\Gamma(x) for general x, x \ne 0.
+EQ_W0,		// principal branch of the Lambert W function, W_0(x). Functions W(x), are defined to be solutions of the equation W\exp(W) = x.
+EQ_W1,		// secondary real-valued branch of the Lambert W function, W_{-1}(x). Functions W(x), are defined to be solutions of the equation W\exp(W) = x.
+EQ_SINC,		// compute \sinc(x) = \sin(\pi x) / (\pi x) for any value of x.
+EQ_ZETA,		// Riemann zeta function \zeta(s) = \sum_{k=1}^\infty k^{-s}for arbitrary s, s \ne 1.
+EQ_ETA,		// eta function \eta(s) = (1-2^{1-s}) \zeta(s) for arbitrary s.
+EQ_AID,		// Derivative of Airy function Ai(x)
+EQ_BID,		// Derivative of Airy function Bi(x)
+EQ_Z,		// Dawson function \exp(-x^2) \int_0^x dt \exp(t^2)
+// Jacoby functions of 2 arguments
+EQ_SN,		// Jacobian elliptic function sn(u|m)	// !!! MUST BE FIRST NON 1-PLACE FUNCTION
+EQ_SC,		// Jacobian elliptic function sn(u|m)/cn(u|m)
+EQ_SD,		// Jacobian elliptic function sn(u|m)/dn(u|m)
+EQ_NS,		// Jacobian elliptic function 1/sn(u|m)
+EQ_NC,		// Jacobian elliptic function 1/cn(u|m)
+EQ_ND,		// Jacobian elliptic function 1/dn(u|m)
+EQ_CN,		// Jacobian elliptic function cn(u|m)
+EQ_CS,		// Jacobian elliptic function cn(u|m)/sn(u|m)
+EQ_CD,		// Jacobian elliptic function cn(u|m)/dn(u|m)
+EQ_DN,		// Jacobian elliptic function dn(u|m)
+EQ_DS,		// Jacobian elliptic function dn(u|m)/sn(u|m)
+EQ_DC,		// Jacobian elliptic function dn(u|m)/cn(u|m)
+			// MUST BE LAST ELLIPTIC FUNCTION
+// not-ready
+EQ_EN,
+EQ_CL		// Clausen function
+};
+//-----------------------------------------------------------------------------
+#ifndef M_PI
+#define M_PI       3.14159265358979323846
+#endif
+//-----------------------------------------------------------------------------
+int mglFormula::Error=0;
+bool MGL_LOCAL_PURE mglCheck(char *str,int n);
+int MGL_LOCAL_PURE mglFindInText(const char *str, const char *lst);
+//-----------------------------------------------------------------------------
+#if MGL_HAVE_GSL
+MGL_NO_EXPORT gsl_rng *mgl_rng=0;	// NOTE: should be deleted by gsl_rng_free() but I don't know where :(
+#endif
+void MGL_EXPORT mgl_srnd(long seed)
+{
+#if MGL_HAVE_GSL
+	if(mgl_rng==0)
+	{
+		gsl_rng_env_setup();
+		mgl_rng = gsl_rng_alloc(gsl_rng_default);
+	}
+	gsl_rng_set(mgl_rng, seed);
+#else
+	srand(seed);
+#endif
+}
+void MGL_EXPORT mgl_srnd_(int *seed)	{	mgl_srnd(*seed);	}
+//-----------------------------------------------------------------------------
+double MGL_EXPORT_CONST mgl_hypot(double x, double y)	{	return hypot(x,y);	}
+//-----------------------------------------------------------------------------
+#if MGL_HAVE_PTHREAD
+extern pthread_mutex_t mutexRnd;
+#endif
+double MGL_EXPORT mgl_rnd()
+{
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_lock(&mutexRnd);
+#endif
+	double res;
+#pragma omp critical(rnd)
+	{
+#if MGL_HAVE_GSL
+		if(mgl_rng==0)
+		{
+			gsl_rng_env_setup();
+			mgl_rng = gsl_rng_alloc(gsl_rng_default);
+			gsl_rng_set(mgl_rng, time(0));
+		}
+		res = gsl_rng_uniform(mgl_rng);
+//		gsl_rng_free(r);
+#else
+		res = rand()/(RAND_MAX-1.);
+#endif
+	}
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_unlock(&mutexRnd);
+#endif
+	return res;
+}
+double MGL_EXPORT mgl_rnd_()	{	return mgl_rnd();	}
+//-----------------------------------------------------------------------------
+mglFormula::~mglFormula()
+{
+	if(Left) delete Left;
+	if(Right) delete Right;
+}
+//-----------------------------------------------------------------------------
+// Formula constructor (automatically parse and "compile" formula)
+mglFormula::mglFormula(const char *string)
+{
+#if MGL_HAVE_GSL
+	gsl_set_error_handler_off();
+#endif
+	Error=0;
+	Left=Right=0;
+	Res=0; Kod=0;
+	if(!string)	{	Kod = EQ_NUM;	Res = 0;	return;	}
+	char *str = new char[strlen(string)+1];
+	strcpy(str,string);
+	long n,len;
+	mgl_strtrim(str);
+	mgl_strlwr(str);
+	len=strlen(str);
+	if(str[0]==0) {	delete []str;	return;	}
+	if(str[0]=='(' && mglCheck(str+1,len-2))	// remove braces
+	{
+		memmove(str,str+1,len);
+		len-=2;	str[len]=0;
+	}
+	len=strlen(str);
+	n=mglFindInText(str,"&|");				// lowest priority -- logical
+	if(n>=0)
+	{
+		if(str[n]=='|') Kod=EQ_OR;	else Kod=EQ_AND;
+		str[n]=0;
+		Left=new mglFormula(str);
+		Right=new mglFormula(str+n+1);
+		delete []str;	return;
+	}
+	n=mglFindInText(str,"<>=");				// low priority -- conditions
+	if(n>=0)
+	{
+		if(str[n]=='<') Kod=EQ_LT;
+		else if(str[n]=='>') Kod=EQ_GT;
+		else Kod=EQ_EQ;
+		str[n]=0;
+		Left=new mglFormula(str);
+		Right=new mglFormula(str+n+1);
+		delete []str;	return;
+	}
+	n=mglFindInText(str,"+-");				// normal priority -- additions
+	if(n>=0 && (n<2 || str[n-1]!='e' || (str[n-2]!='.' && !isdigit(str[n-2]))))
+	{
+		if(str[n]=='+') Kod=EQ_ADD; else Kod=EQ_SUB;
+		str[n]=0;
+		Left=new mglFormula(str);
+		Right=new mglFormula(str+n+1);
+		delete []str;	return;
+	}
+	n=mglFindInText(str,"*/");				// high priority -- multiplications
+	if(n>=0)
+	{
+		if(str[n]=='*') Kod=EQ_MUL; else Kod=EQ_DIV;
+		str[n]=0;
+		Left=new mglFormula(str);
+		Right=new mglFormula(str+n+1);
+		delete []str;	return;
+	}
+	n=mglFindInText(str,"^");				// highest priority -- power
+	if(n>=0)
+	{
+		Kod=EQ_IPOW;		str[n]=0;
+		Left=new mglFormula(str);
+		Right=new mglFormula(str+n+1);
+		delete []str;	return;
+	}
+
+	for(n=0;n<len;n++)	if(str[n]=='(')	break;
+	if(n>=len)								// this is number or variable
+	{
+		Kod = EQ_NUM;
+//		Left = Right = 0;
+		if(str[1]==0 && str[0]>='a' && str[0]<='z')	// available variables
+		{	Kod=EQ_A;	Res = str[0]-'a';	}
+		else if(!strcmp(str,"rnd")) Kod=EQ_RND;
+		else if(!strcmp(str,"pi")) Res=M_PI;
+		else if(!strcmp(str,"inf")) Res=INFINITY;
+		else Res=atof(str);				// this is number
+	}
+	else
+	{
+		char name[128];
+		strncpy(name,str,128);	name[127]=name[n]=0;
+		memmove(str,str+n+1,len-n);
+		len=strlen(str);		str[--len]=0;
+		if(!strncmp(name,"jacobi_",7))
+			memmove(name,name+7,(strlen(name+7)+1)*sizeof(char));
+		if(name[0]=='a')
+		{
+			if(!strcmp(name+1,"sin"))		Kod=EQ_ASIN;
+			else if(!strcmp(name+1,"cos"))	Kod=EQ_ACOS;
+			else if(!strcmp(name+1,"tan"))	Kod=EQ_ATAN;
+			else if(!strcmp(name+1,"sinh"))	Kod=EQ_ASINH;
+			else if(!strcmp(name+1,"cosh"))	Kod=EQ_ACOSH;
+			else if(!strcmp(name+1,"tanh"))	Kod=EQ_ATANH;
+			else if(!strcmp(name+1,"rg"))	Kod=EQ_ARG;
+			else if(!strcmp(name+1,"bs"))	Kod=EQ_ABS;
+			else if(!strcmp(name+1,"i"))	Kod=EQ_AI;
+			else if(!strcmp(name+1,"iry_ai"))	Kod=EQ_AI;
+			else if(!strcmp(name+1,"iry_bi"))	Kod=EQ_BI;
+			else if(!strcmp(name+1,"iry_dai"))	Kod=EQ_AID;
+			else if(!strcmp(name+1,"iry_dbi"))	Kod=EQ_BID;
+		}
+		else if(name[0]=='b')
+		{
+			if(!strcmp(name+1,"i"))		Kod=EQ_BI;
+			else if(!strcmp(name+1,"essel_j"))	Kod=EQ_BESJ;
+			else if(!strcmp(name+1,"essel_i"))	Kod=EQ_BESI;
+			else if(!strcmp(name+1,"essel_k"))	Kod=EQ_BESK;
+			else if(!strcmp(name+1,"essel_y"))	Kod=EQ_BESY;
+			else if(!strcmp(name+1,"eta"))	Kod=EQ_BETA;
+		}
+		else if(name[0]=='c')
+		{
+			if(!strcmp(name+1,"os"))		Kod=EQ_COS;
+			else if(!strcmp(name+1,"osh"))	Kod=EQ_COSH;
+			else if(!strcmp(name+1,"h"))	Kod=EQ_COSH;
+			else if(!strcmp(name+1,"i"))	Kod=EQ_CI;
+			else if(!strcmp(name+1,"n"))	Kod=EQ_CN;
+			else if(!strcmp(name+1,"s"))	Kod=EQ_CS;
+			else if(!strcmp(name+1,"d"))	Kod=EQ_CD;
+			else if(!strcmp(name+1,"l"))	Kod=EQ_CL;
+		}
+		else if(name[0]=='d')
+		{
+			if(!strcmp(name+1,"n"))			Kod=EQ_DN;
+			else if(!strcmp(name+1,"s"))	Kod=EQ_DS;
+			else if(!strcmp(name+1,"c"))	Kod=EQ_DC;
+			else if(!strcmp(name+1,"ilog"))	Kod=EQ_LI2;
+		}
+		else if(name[0]=='e')
+		{
+			if(!strcmp(name+1,"xp"))		Kod=EQ_EXP;
+			else if(!strcmp(name+1,"rf"))	Kod=EQ_ERF;
+			else if(!strcmp(name+1,"n"))	Kod=EQ_EN;
+			else if(!strcmp(name+1,"e"))	Kod=EQ_ELLE;
+			else if(!strcmp(name+1,"k"))	Kod=EQ_ELLK;
+			else if(name[0]==0)				Kod=EQ_ELE;
+			else if(!strcmp(name+1,"i"))	Kod=EQ_EI;
+			else if(!strcmp(name+1,"1"))	Kod=EQ_E1;
+			else if(!strcmp(name+1,"2"))	Kod=EQ_E2;
+			else if(!strcmp(name+1,"ta"))	Kod=EQ_ETA;
+			else if(!strcmp(name+1,"i3"))	Kod=EQ_EI3;
+			else if(!strcmp(name+1,"lliptic_e"))	Kod=EQ_ELE;
+			else if(!strcmp(name+1,"lliptic_f"))	Kod=EQ_ELF;
+			else if(!strcmp(name+1,"lliptic_ec"))	Kod=EQ_ELLE;
+			else if(!strcmp(name+1,"lliptic_kc"))	Kod=EQ_ELLK;
+		}
+		else if(name[0]=='l')
+		{
+			if(!strcmp(name+1,"og"))		Kod=EQ_LOG;
+			else if(!strcmp(name+1,"g"))	Kod=EQ_LG;
+			else if(!strcmp(name+1,"n"))	Kod=EQ_LN;
+			else if(!strcmp(name+1,"i2"))	Kod=EQ_LI2;
+			else if(!strcmp(name+1,"egendre"))	Kod=EQ_LP;
+		}
+		else if(name[0]=='s')
+		{
+			if(!strcmp(name+1,"qrt"))		Kod=EQ_SQRT;
+			else if(!strcmp(name+1,"in"))	Kod=EQ_SIN;
+			else if(!strcmp(name+1,"tep"))	Kod=EQ_STEP;
+			else if(!strcmp(name+1,"ign"))	Kod=EQ_SIGN;
+			else if(!strcmp(name+1,"inh"))	Kod=EQ_SINH;
+			else if(!strcmp(name+1,"h"))	Kod=EQ_SINH;
+			else if(!strcmp(name+1,"i"))	Kod=EQ_SI;
+			else if(!strcmp(name+1,"n"))	Kod=EQ_SN;
+			else if(!strcmp(name+1,"c"))	Kod=EQ_SC;
+			else if(!strcmp(name+1,"d"))	Kod=EQ_SD;
+			else if(!strcmp(name+1,"inc"))	Kod=EQ_SINC;
+		}
+		else if(name[0]=='t')
+		{
+			if(!strcmp(name+1,"g"))			Kod=EQ_TAN;
+			else if(!strcmp(name+1,"an"))	Kod=EQ_TAN;
+			else if(!strcmp(name+1,"anh"))	Kod=EQ_TANH;
+			else if(!strcmp(name+1,"h"))	Kod=EQ_TANH;
+		}
+		else if(name[0]=='m')
+		{
+			if(!strcmp(name+1,"od"))		Kod=EQ_MOD;
+			else if(!strcmp(name+1,"ax"))	Kod=EQ_MAX;
+			else if(!strcmp(name+1,"in"))	Kod=EQ_MIN;
+		}
+		else if(!strcmp(name,"hypot"))	Kod=EQ_HYPOT;
+		else if(!strcmp(name,"pow"))	Kod=EQ_POW;
+		else if(!strcmp(name,"i"))		Kod=EQ_BESI;
+		else if(!strcmp(name,"int"))	Kod=EQ_INT;
+		else if(!strcmp(name,"j"))		Kod=EQ_BESJ;
+		else if(!strcmp(name,"k"))		Kod=EQ_BESK;
+		else if(!strcmp(name,"y"))		Kod=EQ_BESY;
+		else if(!strcmp(name,"f"))		Kod=EQ_ELF;
+		else if(!strcmp(name,"gamma"))	Kod=EQ_GAMMA;
+		else if(!strcmp(name,"gamma_inc"))	Kod=EQ_GAMMA_INC;
+		else if(!strcmp(name,"ns"))		Kod=EQ_NS;
+		else if(!strcmp(name,"nc"))		Kod=EQ_NC;
+		else if(!strcmp(name,"nd"))		Kod=EQ_ND;
+		else if(!strcmp(name,"w0"))		Kod=EQ_W0;
+		else if(!strcmp(name,"w1"))		Kod=EQ_W1;
+		else if(!strcmp(name,"psi"))	Kod=EQ_PSI;
+		else if(!strcmp(name,"zeta"))	Kod=EQ_ZETA;
+		else if(!strcmp(name,"z"))		Kod=EQ_Z;
+		else {	delete []str;	return;	}	// unknown function
+		n=mglFindInText(str,",");
+		if(n>=0)
+		{
+			str[n]=0;
+			Left=new mglFormula(str);
+			Right=new mglFormula(str+n+1);
+		}
+		else	Left=new mglFormula(str);
+	}
+	delete []str;
+}
+//-----------------------------------------------------------------------------
+// evaluate formula for 'x'='r', 'y'='n'='v', 't'='z', 'u'='a' variables
+mreal mglFormula::Calc(mreal x,mreal y,mreal t,mreal u) const
+{
+	Error=0;
+	mreal a1[MGL_VS];	memset(a1,0,MGL_VS*sizeof(mreal));
+	a1['a'-'a'] = a1['c'-'a'] = a1['u'-'a'] = u;
+	a1['x'-'a'] = a1['r'-'a'] = x;
+	a1['y'-'a'] = a1['n'-'a'] = a1['v'-'a'] = y;
+	a1['z'-'a'] = a1['t'-'a'] = t;
+	return CalcIn(a1);
+}
+//-----------------------------------------------------------------------------
+// evaluate formula for 'x'='r', 'y'='n', 't'='z', 'u'='a', 'v'='b', 'w'='c' variables
+mreal mglFormula::Calc(mreal x,mreal y,mreal t,mreal u,mreal v,mreal w) const
+{
+	Error=0;
+	mreal a1[MGL_VS];	memset(a1,0,MGL_VS*sizeof(mreal));
+	a1['c'-'a'] = a1['w'-'a'] = w;
+	a1['b'-'a'] = a1['v'-'a'] = v;
+	a1['a'-'a'] = a1['u'-'a'] = u;
+	a1['x'-'a'] = a1['r'-'a'] = x;
+	a1['y'-'a'] = a1['n'-'a'] = y;
+	a1['z'-'a'] = a1['t'-'a'] = t;
+	return CalcIn(a1);
+}
+//-----------------------------------------------------------------------------
+// evaluate formula for arbitrary set of variables
+mreal mglFormula::Calc(const mreal var[MGL_VS]) const
+{
+	Error=0;
+	return CalcIn(var);
+}
+//-----------------------------------------------------------------------------
+// evaluate formula for 'x'='r', 'y'='n'='v', 't'='z', 'u'='a' variables
+mreal mglFormula::CalcD(char diff,mreal x,mreal y,mreal t,mreal u) const
+{
+	Error=0;
+	mreal a1[MGL_VS];	memset(a1,0,MGL_VS*sizeof(mreal));
+	a1['a'-'a'] = a1['c'-'a'] = a1['u'-'a'] = u;
+	a1['x'-'a'] = a1['r'-'a'] = x;
+	a1['y'-'a'] = a1['n'-'a'] = a1['v'-'a'] = y;
+	a1['z'-'a'] = a1['t'-'a'] = t;
+	return CalcDIn(diff-'a', a1);
+}
+//-----------------------------------------------------------------------------
+// evaluate formula for 'x'='r', 'y'='n', 't'='z', 'u'='a', 'v'='b', 'w'='c' variables
+mreal mglFormula::CalcD(char diff,mreal x,mreal y,mreal t,mreal u,mreal v,mreal w) const
+{
+	Error=0;
+	mreal a1[MGL_VS];	memset(a1,0,MGL_VS*sizeof(mreal));
+	a1['c'-'a'] = a1['w'-'a'] = w;
+	a1['b'-'a'] = a1['v'-'a'] = v;
+	a1['a'-'a'] = a1['u'-'a'] = u;
+	a1['x'-'a'] = a1['r'-'a'] = x;
+	a1['y'-'a'] = a1['n'-'a'] = y;
+	a1['z'-'a'] = a1['t'-'a'] = t;
+	return CalcDIn(diff-'a', a1);
+}
+//-----------------------------------------------------------------------------
+// evaluate derivate of formula respect to 'diff' variable for arbitrary set of other variables
+mreal mglFormula::CalcD(const mreal var[MGL_VS], char diff) const
+{
+	Error=0;
+	return CalcDIn(diff-'a', var);
+}
+//-----------------------------------------------------------------------------
+double MGL_LOCAL_CONST cand(double a,double b)	{return a&&b?1:0;}
+double MGL_LOCAL_CONST cor(double a,double b)	{return a||b?1:0;}
+double MGL_LOCAL_CONST ceq(double a,double b)	{return a==b?1:0;}
+double MGL_LOCAL_CONST clt(double a,double b)	{return a<b?1:0;}
+double MGL_LOCAL_CONST cgt(double a,double b)	{return a>b?1:0;}
+double MGL_LOCAL_CONST add(double a,double b)	{return a+b;}
+double MGL_LOCAL_CONST sub(double a,double b)	{return a-b;}
+double MGL_LOCAL_CONST mul(double a,double b)	{return a&&b?a*b:0;}
+double MGL_LOCAL_CONST del(double a,double b)	{return b?a/b:NAN;}
+double MGL_LOCAL_CONST ipw(double a,double b)	{return fabs(b-int(b))<1e-5 ? mgl_ipow(a,int(b)) : pow(a,b);}
+double MGL_LOCAL_CONST llg(double a,double b)	{return log(a)/log(b);}
+#if MGL_HAVE_GSL
+double MGL_LOCAL_CONST gslEllE(double a,double b)	{return gsl_sf_ellint_E(a,b,GSL_PREC_SINGLE);}
+double MGL_LOCAL_CONST gslEllF(double a,double b)	{return gsl_sf_ellint_F(a,b,GSL_PREC_SINGLE);}
+double MGL_LOCAL_CONST gslLegP(double a,double b)	{return gsl_sf_legendre_Pl(int(a),b);}
+double MGL_LOCAL_CONST gslEllEc(double a)	{return gsl_sf_ellint_Ecomp(a,GSL_PREC_SINGLE);}
+double MGL_LOCAL_CONST gslEllFc(double a)	{return gsl_sf_ellint_Kcomp(a,GSL_PREC_SINGLE);}
+double MGL_LOCAL_CONST gslAi(double a)	{return gsl_sf_airy_Ai(a,GSL_PREC_SINGLE);}
+double MGL_LOCAL_CONST gslBi(double a)	{return gsl_sf_airy_Bi(a,GSL_PREC_SINGLE);}
+double MGL_LOCAL_CONST gslAi_d(double a)	{return gsl_sf_airy_Ai_deriv(a,GSL_PREC_SINGLE);}
+double MGL_LOCAL_CONST gslBi_d(double a)	{return gsl_sf_airy_Bi_deriv(a,GSL_PREC_SINGLE);}
+#endif
+double MGL_LOCAL_CONST sgn(double a)	{return a<0 ? -1:(a>0?1:0);}
+double MGL_LOCAL_CONST stp(double a)	{return a>0 ? 1:0;}
+double MGL_LOCAL_CONST arg(double a,double b)	{	return atan2(b,a);	}
+double MGL_LOCAL_CONST mgz1(double)			{return NAN;}	// NOTE I think NAN value is more correct here than 0
+double MGL_LOCAL_CONST mgz2(double,double)	{return NAN;}	// NOTE I think NAN value is more correct here than 0
+double MGL_LOCAL_CONST mgl_asinh(double x)	{	return log(x+sqrt(x*x+1.));	}
+double MGL_LOCAL_CONST mgl_acosh(double x)	{	return x>1 ? log(x+sqrt(x*x-1.)) : NAN;	}
+double MGL_LOCAL_CONST mgl_atanh(double x)	{	return fabs(x)<1 ? log((1.+x)/(1.-x))/2 : NAN;	}
+double MGL_LOCAL_CONST mgl_fmin(double a,double b)	{	return a > b ? b : a;	}
+double MGL_LOCAL_CONST mgl_fmax(double a,double b)	{	return a > b ? a : b;	}
+//-----------------------------------------------------------------------------
+typedef double (*func_1)(double);
+typedef double (*func_2)(double, double);
+//-----------------------------------------------------------------------------
+static const mreal z2[EQ_SIN-EQ_LT] = {3,3,3,3,0,3,3,0,0,0,0,0,NAN,3,3,3,3
+#if MGL_HAVE_GSL
+	,3,NAN, 3,NAN, 0,0,3,1,3
+#else
+	,0,0,0,0,0,0,0,0,0
+#endif
+};
+static const func_2 f2[EQ_SIN-EQ_LT] = {clt,cgt,ceq,cor,cand,add,sub,mul,del,ipw,pow,fmod,llg,arg,hypot,mgl_fmax,mgl_fmin
+#if MGL_HAVE_GSL
+	,gsl_sf_bessel_Jnu,gsl_sf_bessel_Ynu,
+	gsl_sf_bessel_Inu,gsl_sf_bessel_Knu,
+	gslEllE,gslEllF,gslLegP,gsl_sf_beta,gsl_sf_gamma_inc
+#else
+	,mgz2,mgz2,mgz2,mgz2,mgz2,mgz2,mgz2,mgz2,mgz2
+#endif
+};
+static const func_1 f1[EQ_SN-EQ_SIN] = {sin,cos,tan,asin,acos,atan,sinh,cosh,tanh,
+			mgl_asinh,mgl_acosh,mgl_atanh,sqrt,exp,log,log10,sgn,stp,floor,fabs
+#if MGL_HAVE_GSL
+	,gsl_sf_dilog,gslEllEc,gslEllFc,gslAi,gslBi,gsl_sf_erf,
+	gsl_sf_expint_3,gsl_sf_expint_Ei,gsl_sf_expint_E1,gsl_sf_expint_E2,
+	gsl_sf_Si,gsl_sf_Ci,gsl_sf_gamma,gsl_sf_psi,gsl_sf_lambert_W0,
+	gsl_sf_lambert_Wm1,gsl_sf_sinc,gsl_sf_zeta,gsl_sf_eta,gslAi_d,gslBi_d,
+	gsl_sf_dawson
+#else
+	,mgz1,mgz1,mgz1,mgz1,mgz1,mgz1,mgz1,mgz1,mgz1,mgz1,mgz1,
+	mgz1,mgz1,mgz1,mgz1,mgz1,mgz1,mgz1,mgz1,mgz1,mgz1,mgz1
+#endif
+};
+//-----------------------------------------------------------------------------
+// evaluation of embedded (included) expressions
+mreal mglFormula::CalcIn(const mreal *a1) const
+{
+	if(Kod<EQ_LT)
+	{
+		if(Kod==EQ_RND)	return mgl_rnd();
+		else	return (Kod==EQ_A) ? a1[int(Res)] : Res;
+	}
+	double a = Left->CalcIn(a1);
+	if(mgl_isfin(a))
+	{
+		if(Kod<EQ_SIN)
+		{
+			// try to bypass calc b if a==0
+			if(a==0 && z2[Kod-EQ_LT]!=3)	return z2[Kod-EQ_LT];
+			double b = Right->CalcIn(a1);
+			b = mgl_isfin(b) ? f2[Kod-EQ_LT](a,b):NAN;
+			return mgl_isfin(b) ? b : NAN;
+		}
+		else if(Kod<EQ_SN)
+		{	a = f1[Kod-EQ_SIN](a);	return mgl_isfin(a)?a:NAN;	}
+#if MGL_HAVE_GSL
+		else if(Kod<=EQ_DC)
+		{
+			double sn=0,cn=0,dn=0,b = Right->CalcIn(a1);
+			if(mgl_isbad(b))	return NAN;
+			gsl_sf_elljac_e(a,b, &sn, &cn, &dn);
+			switch(Kod)
+			{
+			case EQ_SN:		return sn;
+			case EQ_SC:		return sn/cn;
+			case EQ_SD:		return sn/dn;
+			case EQ_CN:		return cn;
+			case EQ_CS:		return cn/sn;
+			case EQ_CD:		return cn/dn;
+			case EQ_DN:		return dn;
+			case EQ_DS:		return dn/sn;
+			case EQ_DC:		return dn/cn;
+			case EQ_NS:		return 1./sn;
+			case EQ_NC:		return 1./cn;
+			case EQ_ND:		return 1./dn;
+			}
+		}
+#endif
+	}
+	return NAN;
+}
+//-----------------------------------------------------------------------------
+double MGL_LOCAL_CONST mgzz(double,double)	{return 0;}
+double MGL_LOCAL_CONST mgp(double ,double )	{return 1;}
+double MGL_LOCAL_CONST mgm(double ,double )	{return -1;}
+double MGL_LOCAL_CONST mul1(double ,double b)	{return b;}
+double MGL_LOCAL_CONST mul2(double a,double )	{return a;}
+double MGL_LOCAL_CONST div1(double ,double b)	{return b?1/b:NAN;}
+double MGL_LOCAL_CONST div2(double a,double b)	{return b?-a/(b*b):NAN;}
+double MGL_LOCAL_CONST ipw1(double a,double b)	{return b*(fabs(b-int(b))<1e-5 ? mgl_ipow(a,int(b-1)) : pow(a,b-1));}
+double MGL_LOCAL_CONST pow1(double a,double b)	{return b*pow(a,b-1);}
+double MGL_LOCAL_CONST pow2(double a,double b)	{return log(a)*pow(a,b);}
+double MGL_LOCAL_CONST llg1(double a,double b)	{return 1/(a*log(b));}
+double MGL_LOCAL_CONST llg2(double a,double b)	{return -log(a)/(b*log(b)*log(b));}
+double MGL_LOCAL_CONST cos_d(double a)	{return -sin(a);}
+double MGL_LOCAL_CONST tan_d(double a)	{return 1./(cos(a)*cos(a));}
+double MGL_LOCAL_CONST asin_d(double a)	{return 1./sqrt(1.-a*a);}
+double MGL_LOCAL_CONST acos_d(double a)	{return -1./sqrt(1.-a*a);}
+double MGL_LOCAL_CONST atan_d(double a)	{return 1./(1.+a*a);}
+double MGL_LOCAL_CONST tanh_d(double a)	{return 1./(cosh(a)*cosh(a));}
+double MGL_LOCAL_CONST atanh_d(double a){return 1./(1.-a*a);}
+double MGL_LOCAL_CONST asinh_d(double a){return 1./sqrt(1.+a*a);}
+double MGL_LOCAL_CONST acosh_d(double a){return 1./sqrt(a*a-1.);}
+double MGL_LOCAL_CONST sqrt_d(double a)	{return 0.5/sqrt(a);}
+double MGL_LOCAL_CONST log10_d(double a){return M_LN10/a;}
+double MGL_LOCAL_CONST log_d(double a)	{return 1./a;}
+double MGL_LOCAL_CONST erf_d(double a)	{return 2*exp(-a*a)/sqrt(M_PI);}
+double MGL_LOCAL_CONST dilog_d(double a){return log(a)/(1.-a);}
+double MGL_LOCAL_CONST ei_d(double a)	{return exp(a)/a;}
+double MGL_LOCAL_CONST si_d(double a)	{return a?sin(a)/a:1;}
+double MGL_LOCAL_CONST ci_d(double a)	{return cos(a)/a;}
+double MGL_LOCAL_CONST exp3_d(double a)	{return exp(-a*a*a);}
+double MGL_LOCAL_CONST e1_d(double a)	{return exp(-a)/a;}
+double MGL_LOCAL_CONST sinc_d(double a)	{return a ? (cos(M_PI*a)/a-sin(M_PI*a)/(M_PI*a*a)) : 0;}
+#if MGL_HAVE_GSL
+double MGL_LOCAL_CONST e2_d(double a)	{return -gsl_sf_expint_E1(a);}
+double MGL_LOCAL_CONST gslJnuD(double a,double b)	{return 0.5*(gsl_sf_bessel_Jnu(a-1,b)-gsl_sf_bessel_Jnu(a+1,b));}
+double MGL_LOCAL_CONST gslYnuD(double a,double b)	{return 0.5*(gsl_sf_bessel_Ynu(a-1,b)-gsl_sf_bessel_Ynu(a+1,b));}
+double MGL_LOCAL_CONST gslKnuD(double a,double b)	{return -(a*gsl_sf_bessel_Knu(a,b)/b +gsl_sf_bessel_Knu(a-1,b));}
+double MGL_LOCAL_CONST gslInuD(double a,double b)	{return -(a*gsl_sf_bessel_Inu(a,b)/b -gsl_sf_bessel_Inu(a-1,b));}
+double MGL_LOCAL_CONST gslEllE1(double a,double b)	{return sqrt(1.-sin(a)*sin(a)*b);}
+double MGL_LOCAL_CONST gslEllE2(double a,double b)	{return (gsl_sf_ellint_E(a,b,GSL_PREC_SINGLE) - gsl_sf_ellint_F(a,b,GSL_PREC_SINGLE))/(2.*b);}
+double MGL_LOCAL_CONST gslEllF1(double a,double b)	{return 1./sqrt(1.-sin(a)*sin(a)*b);}
+double MGL_LOCAL_CONST gslEllF2(double a,double b)	{return (gsl_sf_ellint_E(a,b,GSL_PREC_SINGLE) - gsl_sf_ellint_F(a,b,GSL_PREC_SINGLE)*(1.-b))/(2*b*(1.-b)) - sin(2.*a)/(sqrt(1.-sin(a)*sin(a)*b)*2.*(1.-b));}
+double MGL_LOCAL_CONST gslE_d(double a)	{return (gsl_sf_ellint_Ecomp(a,GSL_PREC_SINGLE) - gsl_sf_ellint_Kcomp(a,GSL_PREC_SINGLE))/(2.*a);}
+double MGL_LOCAL_CONST gslK_d(double a)	{return (gsl_sf_ellint_Ecomp(a,GSL_PREC_SINGLE) - (1.-a)*gsl_sf_ellint_Kcomp(a,GSL_PREC_SINGLE))/(2.*a*(1.-a));}
+double MGL_LOCAL_CONST gamma_d(double a)	{return gsl_sf_psi(a)*gsl_sf_gamma(a);}
+#endif
+double MGL_LOCAL_CONST ginc_d(double a, double x)	{return -exp(-x)*pow(x,a-1);}
+//-----------------------------------------------------------------------------
+static const func_2 f21[EQ_SIN-EQ_LT] = {mgzz,mgzz,mgzz, mgzz,mgzz,mgp, mgp,mul1,div1, ipw1,pow1,mgp,llg1, mgz2,mgzz,mgzz
+#if MGL_HAVE_GSL
+	,mgz2,mgz2,mgz2, mgz2,gslEllE1,gslEllF1, mgz2,mgz2,mgz2
+#else
+	,mgz2,mgz2,mgz2,mgz2,mgz2,mgz2,mgz2,mgz2,mgz2
+#endif
+};
+static const func_2 f22[EQ_SIN-EQ_LT] = {mgzz,mgzz,mgzz,mgzz,mgzz,mgp,mgm,mul2,div2,pow2,pow2,mgz2,llg2, mgz2,mgzz,mgzz
+#if MGL_HAVE_GSL
+	,gslJnuD,gslYnuD,gslInuD,gslKnuD,gslEllE2,gslEllF2,mgz2/*gslLegP*/,mgz2,ginc_d
+#else
+	,mgz2,mgz2,mgz2,mgz2,mgz2,mgz2,mgz2,mgz2,mgz2
+#endif
+};
+static const func_1 f11[EQ_SN-EQ_SIN] = {cos,cos_d,tan_d,asin_d,acos_d,atan_d,cosh,sinh,tanh_d,
+	asinh_d,acosh_d,atanh_d,sqrt_d,exp,log_d,log10_d,mgz1,mgz1,mgz1,sgn
+#if MGL_HAVE_GSL
+	,dilog_d,gslE_d,gslK_d,gslAi_d,gslBi_d,erf_d,exp3_d,ei_d,e1_d,e2_d,
+	si_d,ci_d,gamma_d,gsl_sf_psi_1,mgz1,mgz1,sinc_d,mgz1,mgz1,mgz1,mgz1,mgz1
+#else
+	,mgz1,mgz1,mgz1,mgz1,mgz1,mgz1,mgz1,mgz1,mgz1,mgz1,mgz1,
+	mgz1,mgz1,mgz1,mgz1,mgz1,mgz1,mgz1,mgz1,mgz1,mgz1,mgz1
+#endif
+};
+//-----------------------------------------------------------------------------
+// evaluation of derivative of embedded (included) expressions
+mreal mglFormula::CalcDIn(int id, const mreal *a1) const
+{
+	if(Kod<EQ_LT)	return (Kod==EQ_A && id==(int)Res)?1:0;
+
+	double a = Left->CalcIn(a1), d = Left->CalcDIn(id,a1);
+	if(mgl_isfin(a) && mgl_isfin(d))
+	{
+		if(Kod<EQ_SIN)
+		{
+			double b = Right->CalcIn(a1), c = Right->CalcDIn(id,a1);
+			b = mgl_isfin(b) ? (d?f21[Kod-EQ_LT](a,b)*d:0) + (c?f22[Kod-EQ_LT](a,b)*c:0) : NAN;
+			return mgl_isfin(b) ? b : NAN;
+		}
+		else if(Kod<EQ_SN)
+		{	a = (d?f11[Kod-EQ_SIN](a)*d:0);	return mgl_isfin(a)?a:NAN;	}
+#if MGL_HAVE_GSL
+		else if(Kod<=EQ_DC)
+		{
+			double sn=0,cn=0,dn=0,b = Right->CalcIn(a1);
+			if(mgl_isbad(b))	return NAN;
+			gsl_sf_elljac_e(a,b, &sn, &cn, &dn);
+			switch(Kod)	// At this moment parse only differentiation or argument NOT mu !!!
+			{
+			case EQ_SN:		return cn*dn*d;
+			case EQ_SC:		return dn*d/(cn*cn);
+			case EQ_SD:		return cn*d/(dn*dn);
+			case EQ_CN:		return -dn*sn*d;
+			case EQ_CS:		return dn*d/(sn*sn);
+			case EQ_CD:		return (b-1)*d*sn/(dn*dn);
+			case EQ_DN:		return -b*d*cn*sn;
+			case EQ_DS:		return -cn*d/(sn*sn);
+			case EQ_DC:		return (1-b)*sn*d/(cn*cn);
+			case EQ_NS:		return -cn*dn*d/(sn*sn);
+			case EQ_NC:		return dn*sn*d/(cn*cn);
+			case EQ_ND:		return b*cn*sn*d/(dn*dn);
+			}
+		}
+#endif
+	}
+	return NAN;
+}
+//-----------------------------------------------------------------------------
+// Check braces correctness
+bool MGL_LOCAL_PURE mglCheck(char *str,int n)
+{
+	long s = 0;
+	for(long i=0;i<n;i++)
+	{
+		if(str[i]=='(')	s++;
+		if(str[i]==')') s--;
+		if(s<0)	return false;
+	}
+	return (s==0) ? true : false;
+}
+//-----------------------------------------------------------------------------
+// Try to find one of symbols lst in the string str
+int MGL_LOCAL_PURE mglFindInText(const char *str, const char *lst)
+{
+	long l=0,r=0,len=strlen(str);
+	for(long i=len-1;i>=0;i--)
+	{
+		if(str[i]=='(') l++;
+		if(str[i]==')') r++;
+		if(l==r && strchr(lst,str[i]))	return i;
+	}
+	return -1;
+}
+//-----------------------------------------------------------------------------
+HMEX MGL_EXPORT mgl_create_expr(const char *expr)	{	return new mglFormula(expr);	}
+void MGL_EXPORT mgl_delete_expr(HMEX ex)	{	if(ex)	delete ex;	}
+double MGL_EXPORT mgl_expr_eval(HMEX ex, double x, double y,double z)
+{	return ex->Calc(x,y,z);	}
+double MGL_EXPORT mgl_expr_eval_v(HMEX ex, mreal *var)
+{	return ex->Calc(var);	}
+double MGL_EXPORT mgl_expr_diff(HMEX ex, char dir, double x, double y,double z)
+{	return ex->CalcD(dir,x,y,z);	}
+double MGL_EXPORT mgl_expr_diff_v(HMEX ex, char dir, mreal *var)
+{	return ex->CalcD(var, dir);		}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_create_expr_(const char *expr, int l)
+{	char *s=new char[l+1];	memcpy(s,expr,l);	s[l]=0;
+	uintptr_t res = uintptr_t(mgl_create_expr(s));
+	delete []s;	return res;	}
+void MGL_EXPORT mgl_delete_expr_(uintptr_t *ex)	{	mgl_delete_expr((HMEX)ex);	}
+double MGL_EXPORT mgl_expr_eval_(uintptr_t *ex, mreal *x, mreal *y, mreal *z)
+{	return mgl_expr_eval((HMEX) ex, *x,*y,*z);		}
+double MGL_EXPORT mgl_expr_diff_(uintptr_t *ex, const char *dir, mreal *x, mreal *y, mreal *z, int)
+{	return mgl_expr_diff((HMEX) ex, *dir,*x,*y,*z);	}
+//-----------------------------------------------------------------------------
diff --git a/src/evalc.cpp b/src/evalc.cpp
new file mode 100644
index 0000000..4347f88
--- /dev/null
+++ b/src/evalc.cpp
@@ -0,0 +1,331 @@
+/***************************************************************************
+ * evalc.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <time.h>
+#include "mgl2/datac_cf.h"
+#include "mgl2/evalc.h"
+#if MGL_HAVE_GSL
+#include <gsl/gsl_sf.h>
+#endif
+//-----------------------------------------------------------------------------
+//	constants for expression parsing
+enum{
+EQ_NUM=0,	// a variable substitution
+EQ_RND,		// random number
+EQ_A,		// numeric constant
+// normal functions of 2 arguments
+EQ_LT,		// comparison x<y			!!! MUST BE FIRST 2-PLACE FUNCTION
+EQ_GT,		// comparison x>y
+EQ_EQ,		// comparison x=y
+EQ_ADD,		// addition x+y
+EQ_SUB,		// substraction x-y
+EQ_MUL,		// multiplication x*y
+EQ_DIV,		// division x/y
+EQ_IPOW,	// power x^n for integer n
+EQ_POW,		// power x^y
+EQ_LOG,		// logarithm of x on base a, log_a(x) = ln(x)/ln(a)
+EQ_CMPLX,	// return a+i*b
+EQ_HYPOT,	// return sqrt(a*a+b*b)
+// normal functions of 1 argument
+EQ_SIN,		// sine function \sin(x).			!!! MUST BE FIRST 1-PLACE FUNCTION
+EQ_COS,		// cosine function \cos(x).
+EQ_TAN,		// tangent function \tan(x).
+EQ_ASIN,	// inverse sine function \asin(x).
+EQ_ACOS,	// inverse cosine function \acos(x).
+EQ_ATAN,	// inverse tangent function \atan(x).
+EQ_SINH,	// hyperbolic sine function \sinh(x).
+EQ_COSH,	// hyperbolic cosine function \cosh(x).
+EQ_TANH,	// hyperbolic tangent function \tanh(x).
+EQ_ASINH,	// inverse hyperbolic sine function \asinh(x).
+EQ_ACOSH,	// inverse hyperbolic cosine function \acosh(x).
+EQ_ATANH,	// inverse hyperbolic tangent function \atanh(x).
+EQ_SQRT,	// square root function \sqrt(x)
+EQ_EXP,		// exponential function \exp(x)
+EQ_EXPI,	// exponential function \exp(i*x)
+EQ_LN,		// logarithm of x, ln(x)
+EQ_LG,		// decimal logarithm of x, lg(x) = ln(x)/ln(10)
+EQ_ABS,		// absolute value
+EQ_ARG,		// argument (or phase) of complex number
+EQ_CONJ,	// complex conjugate
+EQ_REAL,	// real part
+EQ_IMAG,	// imaginary part
+EQ_NORM,	// square of absolute value |u|^2
+EQ_LAST		// id of last entry
+};
+//-----------------------------------------------------------------------------
+int mglFormulaC::Error=0;
+bool MGL_LOCAL_PURE mglCheck(char *str,int n);
+int MGL_LOCAL_PURE mglFindInText(const char *str, const char *lst);
+//-----------------------------------------------------------------------------
+mglFormulaC::~mglFormulaC()
+{
+	if(Left) delete Left;
+	if(Right) delete Right;
+}
+//-----------------------------------------------------------------------------
+// Formula constructor (automatically parse and "compile" formula)
+mglFormulaC::mglFormulaC(const char *string)
+{
+	Error=0;
+	Left=Right=0;
+	Res=0; Kod=0;
+	if(!string)	{	Kod = EQ_NUM;	Res = 0;	return;	}
+	char *str = new char[strlen(string)+1];
+	strcpy(str,string);
+	long n,len;
+	mgl_strtrim(str);
+	mgl_strlwr(str);
+	len=strlen(str);
+	if(str[0]==0) {	delete []str;	return;	}
+	if(str[0]=='(' && mglCheck(&(str[1]),len-2))	// remove braces
+	{
+		memmove(str,str+1,len);
+		len-=2;	str[len]=0;
+	}
+	len=strlen(str);
+	n=mglFindInText(str,"<>=");				// low priority -- conditions
+	if(n>=0)
+	{
+		if(str[n]=='<') Kod=EQ_LT;
+		else if(str[n]=='>') Kod=EQ_GT;
+		else Kod=EQ_EQ;
+		str[n]=0;
+		Left=new mglFormulaC(str);
+		Right=new mglFormulaC(str+n+1);
+		delete []str;	return;
+	}
+	n=mglFindInText(str,"+-");				// normal priority -- additions
+	if(n>=0 && (n<2 || str[n-1]!='e' || (str[n-2]!='.' && !isdigit(str[n-2]))))
+	{
+		if(str[n]=='+') Kod=EQ_ADD; else Kod=EQ_SUB;
+		str[n]=0;
+		Left=new mglFormulaC(str);
+		Right=new mglFormulaC(str+n+1);
+		delete []str;	return;
+	}
+	n=mglFindInText(str,"*/");				// high priority -- multiplications
+	if(n>=0)
+	{
+		if(str[n]=='*') Kod=EQ_MUL; else Kod=EQ_DIV;
+		str[n]=0;
+		Left=new mglFormulaC(str);
+		Right=new mglFormulaC(str+n+1);
+		delete []str;	return;
+	}
+	n=mglFindInText(str,"^");				// highest priority -- power
+	if(n>=0)
+	{
+		Kod=EQ_IPOW;		str[n]=0;
+		Left=new mglFormulaC(str);
+		Right=new mglFormulaC(str+n+1);
+		delete []str;	return;
+	}
+
+	for(n=0;n<len;n++)	if(str[n]=='(')	break;
+	if(n>=len)								// this is number or variable
+	{
+		Kod = EQ_NUM;
+//		Left = Right = 0;
+		if(str[1]==0 && str[0]>='a' && str[0]<='z')	// available variables
+		{	Kod=EQ_A;	Res = str[0]-'a';	}
+		else if(!strcmp(str,"rnd")) Kod=EQ_RND;
+		else if(!strcmp(str,"pi")) Res=M_PI;
+		else if(!strcmp(str,"inf")) Res=INFINITY;
+		else if(str[0]=='i')	Res = dual(0,str[1]>' '?atof(str+1):1);
+		else Res=atof(str);					// this is number
+	}
+	else
+	{
+		char name[128];
+		strncpy(name,str,128);	name[127]=name[n]=0;
+		memmove(str,str+n+1,len-n);
+		len=strlen(str);		str[--len]=0;
+		if(!strcmp(name,"sin")) Kod=EQ_SIN;
+		else if(!strcmp(name,"cos")) Kod=EQ_COS;
+		else if(!strcmp(name,"tg")) Kod=EQ_TAN;
+		else if(!strcmp(name,"tan")) Kod=EQ_TAN;
+		else if(!strcmp(name,"asin")) Kod=EQ_ASIN;
+		else if(!strcmp(name,"acos")) Kod=EQ_ACOS;
+		else if(!strcmp(name,"atan")) Kod=EQ_ATAN;
+		else if(!strcmp(name,"sinh")) Kod=EQ_SINH;
+		else if(!strcmp(name,"cosh")) Kod=EQ_COSH;
+		else if(!strcmp(name,"tanh")) Kod=EQ_TANH;
+		else if(!strcmp(name,"sh")) Kod=EQ_SINH;
+		else if(!strcmp(name,"ch")) Kod=EQ_COSH;
+		else if(!strcmp(name,"th")) Kod=EQ_TANH;
+		else if(!strcmp(name,"sqrt")) Kod=EQ_SQRT;
+		else if(!strcmp(name,"log")) Kod=EQ_LOG;
+		else if(!strcmp(name,"pow")) Kod=EQ_POW;
+		else if(!strcmp(name,"exp")) Kod=EQ_EXP;
+		else if(!strcmp(name,"lg")) Kod=EQ_LG;
+		else if(!strcmp(name,"ln")) Kod=EQ_LN;
+		else if(!strcmp(name,"abs")) Kod=EQ_ABS;
+		else if(!strcmp(name,"arg")) Kod=EQ_ARG;
+		else if(!strcmp(name,"conj")) Kod=EQ_CONJ;
+		else if(!strcmp(name,"real")) Kod=EQ_REAL;
+		else if(!strcmp(name,"imag")) Kod=EQ_IMAG;
+		else if(!strcmp(name,"norm")) Kod=EQ_NORM;
+		else if(!strcmp(name,"cmplx")) Kod=EQ_CMPLX;
+		else if(!strcmp(name,"hypot")) Kod=EQ_HYPOT;
+		else {	delete []str;	return;	}	// unknown function
+		n=mglFindInText(str,",");
+		if(n>=0)
+		{
+			str[n]=0;
+			Left=new mglFormulaC(str);
+			Right=new mglFormulaC(str+n+1);
+		}
+		else
+			Left=new mglFormulaC(str);
+	}
+	delete []str;
+}
+//-----------------------------------------------------------------------------
+// evaluate formula for 'x'='r', 'y'='n'='v', 't'='z', 'u'='a' variables
+dual mglFormulaC::Calc(dual x,dual y,dual t,dual u) const
+{
+	Error=0;
+	dual a1[MGL_VS];	memset(a1,0,MGL_VS*sizeof(dual));
+	a1['a'-'a'] = a1['u'-'a'] = u;
+	a1['x'-'a'] = a1['r'-'a'] = x;
+	a1['y'-'a'] = a1['n'-'a'] = a1['v'-'a'] = y;
+	a1['z'-'a'] = a1['t'-'a'] = t;
+	a1['i'-'a'] = dual(0,1);
+	return CalcIn(a1);
+}
+//-----------------------------------------------------------------------------
+// evaluate formula for 'x'='r', 'y'='n', 't'='z', 'u'='a', 'v'='b', 'w'='c' variables
+dual mglFormulaC::Calc(dual x,dual y,dual t,dual u,dual v,dual w) const
+{
+	Error=0;
+	dual a1[MGL_VS];	memset(a1,0,MGL_VS*sizeof(dual));
+	a1['c'-'a'] = a1['w'-'a'] = w;
+	a1['b'-'a'] = a1['v'-'a'] = v;
+	a1['a'-'a'] = a1['u'-'a'] = u;
+	a1['x'-'a'] = a1['r'-'a'] = x;
+	a1['y'-'a'] = a1['n'-'a'] = y;
+	a1['z'-'a'] = a1['t'-'a'] = t;
+	a1['i'-'a'] = dual(0,1);
+	return CalcIn(a1);
+}
+//-----------------------------------------------------------------------------
+// evaluate formula for arbitrary set of variables
+dual mglFormulaC::Calc(const dual var[MGL_VS]) const
+{
+	Error=0;
+	return CalcIn(var);
+}
+//-----------------------------------------------------------------------------
+dual MGL_LOCAL_CONST ceqc(dual a,dual b)	{return a==b?1:0;}
+dual MGL_LOCAL_CONST cltc(dual a,dual b)	{return real(a-b)<0?1:0;}
+dual MGL_LOCAL_CONST cgtc(dual a,dual b)	{return real(a-b)>0?1:0;}
+dual MGL_LOCAL_CONST addc(dual a,dual b)	{return a+b;}
+dual MGL_LOCAL_CONST subc(dual a,dual b)	{return a-b;}
+dual MGL_LOCAL_CONST mulc(dual a,dual b)	{return a*b;}
+dual MGL_LOCAL_CONST divc(dual a,dual b)	{return a/b;}
+dual MGL_LOCAL_CONST ipwc(dual a,dual b)	{return mgl_ipowc(a,int(b.real()));}
+dual MGL_LOCAL_CONST powc(dual a,dual b)	{return exp(b*log(a));	}
+dual MGL_LOCAL_CONST llgc(dual a,dual b)	{return log(a)/log(b);	}
+dual MGL_LOCAL_CONST cmplxc(dual a,dual b)	{return a+dual(0,1)*b;	}
+dual MGL_LOCAL_CONST expi(dual a)	{	return exp(dual(0,1)*a);	}
+dual MGL_LOCAL_CONST expi(double a)	{	return dual(cos(a),sin(a));	}
+//-----------------------------------------------------------------------------
+dual MGL_NO_EXPORT ic = dual(0,1);
+dual MGL_LOCAL_CONST hypotc(dual x, dual y)	{	return sqrt(x*x+y*y);	}
+dual MGL_LOCAL_CONST asinhc(dual x)	{	return log(x+sqrt(x*x+mreal(1)));	}
+dual MGL_LOCAL_CONST acoshc(dual x)	{	return log(x+sqrt(x*x-mreal(1)));	}
+dual MGL_LOCAL_CONST atanhc(dual x)	{	return log((mreal(1)+x)/(mreal(1)-x))/mreal(2);	}
+dual MGL_LOCAL_CONST conjc(dual x)	{	return dual(real(x),-imag(x));	}
+dual MGL_LOCAL_CONST sinc(dual x)	{	return sin(x);	}
+dual MGL_LOCAL_CONST cosc(dual x)	{	return cos(x);	}
+dual MGL_LOCAL_CONST tanc(dual x)	{	return tan(x);	}
+dual MGL_LOCAL_CONST sinhc(dual x)	{	return sinh(x);	}
+dual MGL_LOCAL_CONST coshc(dual x)	{	return cosh(x);	}
+dual MGL_LOCAL_CONST tanhc(dual x)	{	return tanh(x);	}
+dual MGL_LOCAL_CONST asinc(dual x)	{	return log(ic*x+sqrt(mreal(1)-x*x))/ic;	}
+dual MGL_LOCAL_CONST acosc(dual x)	{	return log(x+sqrt(x*x-mreal(1)))/ic;	}
+dual MGL_LOCAL_CONST atanc(dual x)	{	return log((ic-x)/(ic+x))/(mreal(2)*ic);	}
+dual MGL_LOCAL_CONST expc(dual x)	{	return exp(x);	}
+dual MGL_LOCAL_CONST sqrtc(dual x)	{	return sqrt(x);	}
+dual MGL_LOCAL_CONST logc(dual x)	{	return log(x);	}
+dual MGL_LOCAL_CONST absc(dual x)	{	return abs(x);	}
+dual MGL_LOCAL_CONST argc(dual x)	{	return arg(x);	}
+dual MGL_LOCAL_CONST lgc(dual x)	{	return log10(x);}
+dual MGL_LOCAL_CONST realc(dual x)	{	return real(x);	}
+dual MGL_LOCAL_CONST imagc(dual x)	{	return imag(x);	}
+dual MGL_LOCAL_CONST normc(dual x)	{	return norm(x);	}
+//-----------------------------------------------------------------------------
+typedef dual (*func_1)(dual);
+typedef dual (*func_2)(dual, dual);
+static const func_2 f2[EQ_SIN-EQ_LT] = {cltc,cgtc,ceqc,addc,subc,mulc,divc,ipwc,powc,llgc,cmplxc,hypotc};
+static const func_1 f1[EQ_LAST-EQ_SIN] = {sinc,cosc,tanc,asinc,acosc,atanc,sinhc,coshc,tanhc,
+					asinhc,acoshc,atanhc,sqrtc,expc,expi,logc,lgc,absc,argc,conjc,realc,imagc,normc};
+// evaluation of embedded (included) expressions
+dual mglFormulaC::CalcIn(const dual *a1) const
+{
+//	if(Error)	return 0;
+	if(Kod==EQ_A)	return a1[(int)Res.real()];
+	if(Kod==EQ_RND)	return mgl_rnd();
+	if(Kod==EQ_NUM) return Res;
+
+	dual a = Left->CalcIn(a1);
+	if(mgl_isfin(a))
+	{
+		if(Kod<EQ_SIN)
+		{
+			dual b = Right->CalcIn(a1);
+			b = mgl_isfin(b)?f2[Kod-EQ_LT](a,b):NAN;
+			return mgl_isfin(b)?b:NAN;
+		}
+		else
+		{	a = f1[Kod-EQ_SIN](a);	return mgl_isfin(a)?a:NAN;	}
+	}
+	return NAN;
+}
+//-----------------------------------------------------------------------------
+mdual MGL_EXPORT_CONST mgl_ipowc(dual x,int n)
+{
+	dual t;
+	if(n==2)	t = x*x;
+	else if(n==1)	t = x;
+	else if(n<0)	t = mreal(1)/mgl_ipowc(x,-n);
+	else if(n==0)	t = mreal(1);
+	else
+	{
+		t = mgl_ipowc(x,n/2);	t = t*t;
+		if(n%2==1)	t *= x;
+	}
+	return t.real()+t.imag()*mgl_I;
+}
+mdual MGL_EXPORT mgl_ipowc_(dual *x,int *n)	{	return mgl_ipowc(*x,*n);	}
+//-----------------------------------------------------------------------------
+HAEX MGL_EXPORT mgl_create_cexpr(const char *expr)	{	return new mglFormulaC(expr);	}
+uintptr_t MGL_EXPORT mgl_create_cexpr_(const char *expr, int l)
+{	char *s=new char[l+1];	memcpy(s,expr,l);	s[l]=0;
+	uintptr_t res = uintptr_t(mgl_create_cexpr(s));
+	delete []s;	return res;	}
+void MGL_EXPORT mgl_delete_cexpr(HAEX ex)	{	if(ex)	delete ex;	}
+void MGL_EXPORT mgl_delete_cexpr_(uintptr_t *ex)	{	mgl_delete_cexpr((HAEX)ex);	}
+mdual MGL_EXPORT mgl_cexpr_eval(HAEX ex, dual x, dual y,dual z)
+{	dual r = ex->Calc(x,y,z);	return r.real()+r.imag()*mgl_I;	}
+mdual MGL_EXPORT mgl_cexpr_eval_(uintptr_t *ex, dual *x, dual *y, dual *z)
+{	return mgl_cexpr_eval((HAEX) ex, *x,*y,*z);		}
+mdual MGL_EXPORT mgl_cexpr_eval_v(HAEX ex, dual *var)
+{	dual r = ex->Calc(var);	return r.real()+r.imag()*mgl_I;	}
+//-----------------------------------------------------------------------------
diff --git a/src/evalp.cpp b/src/evalp.cpp
new file mode 100644
index 0000000..4783d2d
--- /dev/null
+++ b/src/evalp.cpp
@@ -0,0 +1,1067 @@
+/***************************************************************************
+ * evalp.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <time.h>
+#include <ctype.h>
+#include <wchar.h>
+#include "mgl2/base.h"
+#include "mgl2/parser.h"
+#if MGL_HAVE_GSL
+#include <gsl/gsl_sf.h>
+#include <gsl/gsl_errno.h>
+#endif
+//-----------------------------------------------------------------------------
+std::wstring mgl_trim_ws(const std::wstring &str);
+HMDT MGL_NO_EXPORT mglFormulaCalc(std::wstring string, mglParser *arg, const std::vector<mglDataA*> &head);
+HADT MGL_NO_EXPORT mglFormulaCalcC(std::wstring string, mglParser *arg, const std::vector<mglDataA*> &head);
+//-----------------------------------------------------------------------------
+HMDT MGL_NO_EXPORT mglFormulaCalc(const char *str, const std::vector<mglDataA*> &head)
+{
+	std::wstring s;
+	for(long i=0;str[i];i++)	s.push_back(str[i]);
+	return mglFormulaCalc(s,0,head);
+}
+//-----------------------------------------------------------------------------
+HADT MGL_NO_EXPORT mglFormulaCalcC(const char *str, const std::vector<mglDataA*> &head)
+{
+	std::wstring s;
+	for(long i=0;str[i];i++)	s.push_back(str[i]);
+	return mglFormulaCalcC(s,0,head);
+}
+//-----------------------------------------------------------------------------
+HMDT mglApplyFunc(std::wstring str, mglParser *arg, const std::vector<mglDataA*> &head, double (*func)(double))
+{
+	HMDT d = mglFormulaCalc(str, arg, head);
+	long n = d->GetNN();	mreal *dd=d->a;
+#pragma omp parallel for
+	for(long i=0;i<n;i++)	dd[i] = func(dd[i]);
+	return d;
+}
+//-----------------------------------------------------------------------------
+#if MGL_HAVE_GSL
+HMDT mglApplyFuncGSL(std::wstring str, mglParser *arg, const std::vector<mglDataA*> &head, double (*func)(double, gsl_mode_t))
+{
+	HMDT d = mglFormulaCalc(str, arg, head);
+	long n = d->GetNN();	mreal *dd=d->a;
+#pragma omp parallel for
+	for(long i=0;i<n;i++)	dd[i] = func(dd[i],GSL_PREC_SINGLE);
+	return d;
+}
+#endif
+//-----------------------------------------------------------------------------
+HMDT mglApplyOper(std::wstring a1, std::wstring a2, mglParser *arg, const std::vector<mglDataA*> &head, double (*func)(double,double))
+{
+	HMDT a = mglFormulaCalc(a1,arg,head), b = mglFormulaCalc(a2,arg,head), r,d;
+	long na = a->GetNN(), nb = b->GetNN(), nn;
+	if(na!=1)	{	r=a;	d=b;	nn=na;	}
+	else		{	r=b;	d=a;	nn=nb;	}
+	mreal va=a->a[0], vb=b->a[0], *aa=a->a, *bb=b->a, *cc=r->a;
+	if(na==nb)
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	cc[i] = func(aa[i], bb[i]);
+	else if(na==1)
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	cc[i] = func(va, bb[i]);
+	else
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	cc[i] = func(aa[i], vb);
+	mgl_delete_data(d);	return r;
+}
+//-----------------------------------------------------------------------------
+HMDT mglApplyOperAdd(std::wstring a1, std::wstring a2, mglParser *arg, const std::vector<mglDataA*> &head)
+{
+	HMDT a = mglFormulaCalc(a1,arg,head), b = mglFormulaCalc(a2,arg,head), r,d;
+	long na = a->GetNN(), nb = b->GetNN(), nn;
+	if(na!=1)	{	r=a;	d=b;	nn=na;	}
+	else		{	r=b;	d=a;	nn=nb;	}
+	mreal *aa=r->a, *bb=d->a, v=bb[0];
+	if(na==nb)
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	aa[i] += bb[i];
+	else
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	aa[i] += v;
+	mgl_delete_data(d);	return r;
+}
+//-----------------------------------------------------------------------------
+HMDT mglApplyOperSub(std::wstring a1, std::wstring a2, mglParser *arg, const std::vector<mglDataA*> &head)
+{
+	HMDT a = mglFormulaCalc(a1,arg,head), b = mglFormulaCalc(a2,arg,head), r,d;
+	long na = a->GetNN(), nb = b->GetNN(), nn;
+	if(na!=1)	{	r=a;	d=b;	nn=na;	}
+	else		{	r=b;	d=a;	nn=nb;	}
+	mreal va=a->a[0], vb=b->a[0], *aa=a->a, *bb=b->a, *cc=r->a;
+	if(na==nb)
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	cc[i] = aa[i]-bb[i];
+	else if(na==1)
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	cc[i] = va-bb[i];
+	else
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	cc[i] = aa[i]-vb;
+	mgl_delete_data(d);	return r;
+}
+//-----------------------------------------------------------------------------
+HMDT mglApplyOperMul(std::wstring a1, std::wstring a2, mglParser *arg, const std::vector<mglDataA*> &head)
+{
+	HMDT a = mglFormulaCalc(a1,arg,head), b = mglFormulaCalc(a2,arg,head), r,d;
+	long na = a->GetNN(), nb = b->GetNN(), nn;
+	if(na!=1)	{	r=a;	d=b;	nn=na;	}
+	else		{	r=b;	d=a;	nn=nb;	}
+	mreal *aa=r->a, *bb=d->a, v=bb[0];
+	if(na==nb)
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	aa[i] *= bb[i];
+	else
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	aa[i] *= v;
+	mgl_delete_data(d);	return r;
+}
+//-----------------------------------------------------------------------------
+HMDT mglApplyOperDiv(std::wstring a1, std::wstring a2, mglParser *arg, const std::vector<mglDataA*> &head)
+{
+	HMDT a = mglFormulaCalc(a1,arg,head), b = mglFormulaCalc(a2,arg,head), r,d;
+	long na = a->GetNN(), nb = b->GetNN(), nn;
+	if(na!=1)	{	r=a;	d=b;	nn=na;	}
+	else		{	r=b;	d=a;	nn=nb;	}
+	mreal va=a->a[0], vb=b->a[0], *aa=a->a, *bb=b->a, *cc=r->a;
+	if(na==nb)
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	cc[i] = bb[i]!=0?aa[i]/bb[i]:NAN;
+	else if(na==1)
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	cc[i] = bb[i]!=0?va/bb[i]:NAN;
+	else if(vb!=0)
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	cc[i] = aa[i]/vb;
+	else
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	cc[i] = NAN;
+	mgl_delete_data(d);	return r;
+}
+//-----------------------------------------------------------------------------
+HADT mglApplyFuncC(std::wstring str, mglParser *arg, const std::vector<mglDataA*> &head, dual (*func)(dual))
+{
+	HADT d = mglFormulaCalcC(str, arg, head);
+	long n = d->GetNN();	dual *dd=d->a;
+#pragma omp parallel for
+	for(long i=0;i<n;i++)	dd[i] = func(dd[i]);
+	return d;
+}
+//-----------------------------------------------------------------------------
+HADT mglApplyOperC(std::wstring a1, std::wstring a2, mglParser *arg, const std::vector<mglDataA*> &head, dual (*func)(dual,dual))
+{
+	HADT a = mglFormulaCalcC(a1,arg,head), b = mglFormulaCalcC(a2,arg,head), r,d;
+	long na = a->GetNN(), nb = b->GetNN(), nn;
+	if(na!=1)	{	r=a;	d=b;	nn=na;	}
+	else		{	r=b;	d=a;	nn=nb;	}
+	dual va=a->a[0], vb=b->a[0], *aa=a->a, *bb=b->a, *cc=r->a;
+	if(na==nb)
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	cc[i] = func(aa[i], bb[i]);
+	else if(na==1)
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	cc[i] = func(va, bb[i]);
+	else
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	cc[i] = func(aa[i], vb);
+	mgl_delete_datac(d);	return r;
+}
+//-----------------------------------------------------------------------------
+HADT mglApplyOperAddC(std::wstring a1, std::wstring a2, mglParser *arg, const std::vector<mglDataA*> &head)
+{
+	HADT a = mglFormulaCalcC(a1,arg,head), b = mglFormulaCalcC(a2,arg,head), r,d;
+	long na = a->GetNN(), nb = b->GetNN(), nn;
+	if(na!=1)	{	r=a;	d=b;	nn=na;	}
+	else		{	r=b;	d=a;	nn=nb;	}
+	dual *aa=r->a, *bb=d->a, v=bb[0];
+	if(na==nb)
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	aa[i] += bb[i];
+	else
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	aa[i] += v;
+	mgl_delete_datac(d);	return r;
+}
+//-----------------------------------------------------------------------------
+HADT mglApplyOperSubC(std::wstring a1, std::wstring a2, mglParser *arg, const std::vector<mglDataA*> &head)
+{
+	HADT a = mglFormulaCalcC(a1,arg,head), b = mglFormulaCalcC(a2,arg,head), r,d;
+	long na = a->GetNN(), nb = b->GetNN(), nn;
+	if(na!=1)	{	r=a;	d=b;	nn=na;	}
+	else		{	r=b;	d=a;	nn=nb;	}
+	dual va=a->a[0], vb=b->a[0], *aa=a->a, *bb=b->a, *cc=r->a;
+	if(na==nb)
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	cc[i] = aa[i]-bb[i];
+	else if(na==1)
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	cc[i] = va-bb[i];
+	else
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	cc[i] = aa[i]-vb;
+	mgl_delete_datac(d);	return r;
+}
+//-----------------------------------------------------------------------------
+HADT mglApplyOperMulC(std::wstring a1, std::wstring a2, mglParser *arg, const std::vector<mglDataA*> &head)
+{
+	HADT a = mglFormulaCalcC(a1,arg,head), b = mglFormulaCalcC(a2,arg,head), r,d;
+	long na = a->GetNN(), nb = b->GetNN(), nn;
+	if(na!=1)	{	r=a;	d=b;	nn=na;	}
+	else		{	r=b;	d=a;	nn=nb;	}
+	dual *aa=r->a, *bb=d->a, v=bb[0];
+	if(na==nb)
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	aa[i] *= bb[i];
+	else
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	aa[i] *= v;
+	mgl_delete_datac(d);	return r;
+}
+//-----------------------------------------------------------------------------
+HADT mglApplyOperDivC(std::wstring a1, std::wstring a2, mglParser *arg, const std::vector<mglDataA*> &head)
+{
+	HADT a = mglFormulaCalcC(a1,arg,head), b = mglFormulaCalcC(a2,arg,head), r,d;
+	long na = a->GetNN(), nb = b->GetNN(), nn;
+	if(na!=1)	{	r=a;	d=b;	nn=na;	}
+	else		{	r=b;	d=a;	nn=nb;	}
+	dual va=a->a[0], vb=b->a[0], *aa=a->a, *bb=b->a, *cc=r->a;
+	if(na==nb)
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	cc[i] = bb[i]!=mreal(0)?aa[i]/bb[i]:NAN;
+	else if(na==1)
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	cc[i] = bb[i]!=mreal(0)?va/bb[i]:NAN;
+	else if(vb!=mreal(0))
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	cc[i] = aa[i]/vb;
+	else
+#pragma omp parallel for
+		for(long i=0;i<nn;i++)	cc[i] = NAN;
+	mgl_delete_datac(d);	return r;
+}
+//-----------------------------------------------------------------------------
+bool mglCheck(std::wstring str)
+{
+	long s = 0,i,n=str.length();
+	for(i=0;i<n;i++)
+	{
+		if(str[i]=='(')	s++;
+		if(str[i]==')') s--;
+		if(s<0)	return false;
+	}
+	return (s==0) ? true : false;
+}
+//-----------------------------------------------------------------------------
+long mglFindInText(const std::wstring &str,const char *lst)
+{
+	long l=0,r=0;
+	for(long i=str.length()-1;i>=0;i--)
+	{
+		if(str[i]=='(') l++;
+		if(str[i]==')') r++;
+		if(l==r && strchr(lst,str[i]))	return i;
+	}
+	return -1;
+}
+//-----------------------------------------------------------------------------
+double MGL_LOCAL_CONST cand(double a,double b);//	{return a&&b?1:0;}
+double MGL_LOCAL_CONST cor(double a,double b);//	{return a||b?1:0;}
+double MGL_LOCAL_CONST ceq(double a,double b);//	{return a==b?1:0;}
+double MGL_LOCAL_CONST clt(double a,double b);//	{return a<b?1:0;}
+double MGL_LOCAL_CONST cgt(double a,double b);//	{return a>b?1:0;}
+double MGL_LOCAL_CONST stp(double a);//	{return a>0?1:0;}
+double MGL_LOCAL_CONST sgn(double a);//	{return a>0?1:(a<0?-1:0);}
+double MGL_LOCAL_CONST ipw(double a,double b);//	{return mgl_ipow(a,int(b));}
+double MGL_LOCAL_CONST llg(double a,double b);//	{return log(a)/log(b);}
+//double MGL_LOCAL_CONST asinh(double x);//	{	return log(x+sqrt(x*x+1));	}
+//double MGL_LOCAL_CONST acosh(double x);//	{	return x>1 ? log(x+sqrt(x*x-1)) : NAN;	}
+//double MGL_LOCAL_CONST atanh(double x);//	{	return fabs(x)<1 ? log((1+x)/(1-x))/2 : NAN;	}
+double MGL_LOCAL_CONST gslEllE(double a,double b);//	{return gsl_sf_ellint_E(a,b,GSL_PREC_SINGLE);}
+double MGL_LOCAL_CONST gslEllF(double a,double b);//	{return gsl_sf_ellint_F(a,b,GSL_PREC_SINGLE);}
+double MGL_LOCAL_CONST gslLegP(double a,double b);//	{return gsl_sf_legendre_Pl(int(a),b);}
+double MGL_LOCAL_CONST mgl_asinh(double x);
+double MGL_LOCAL_CONST mgl_acosh(double x);
+double MGL_LOCAL_CONST mgl_atanh(double x);
+double MGL_LOCAL_CONST mgl_fmin(double a,double b);
+double MGL_LOCAL_CONST mgl_fmax(double a,double b);
+//-----------------------------------------------------------------------------
+// It seems that standard wcstombs() have a bug. So, I replace by my own.
+void MGL_EXPORT mgl_wcstombs(char *dst, const wchar_t *src, int size)
+{
+	int j;
+	for(j=0;j<size-1 && src[j]!=0;j++)
+		dst[j] = src[j]<0x7f ? src[j] : ' ';
+	dst[j] = 0;
+}
+//-----------------------------------------------------------------------------
+MGL_LOCAL_PURE const mglDataA *FindVar(const std::vector<mglDataA*> &head, const std::wstring &name)
+{
+	for(size_t i=0;i<head.size();i++)
+		if(head[i] && head[i]->s==name)	return head[i];
+	return 0;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_wcslwr(wchar_t *str)
+{
+	size_t l=mgl_wcslen(str);
+	for(size_t k=0;k<l;k++)
+		str[k] = (str[k]>='A' && str[k]<='Z') ? str[k]+'a'-'A' : str[k];
+}
+//-----------------------------------------------------------------------------
+mreal mgl_gettime(const std::wstring &s)
+{
+	mreal t=NAN;
+	tm a;	memset(&a,0,sizeof(tm));
+	if(swscanf(s.c_str(),L"%u-%u-%u_%u.%u.%d", &a.tm_hour,&a.tm_min,&a.tm_sec, &a.tm_mday,&a.tm_mon,&a.tm_year)==6)
+	{	a.tm_year-=1900;	a.tm_mon -= 1;
+		if(a.tm_hour<24 && a.tm_min<60 && a.tm_sec<60 && a.tm_mday>0 && a.tm_mday<32 && a.tm_mon<12)
+			t = mktime(&a);
+	}
+	else if(swscanf(s.c_str(),L"%d.%d.%d", &a.tm_mday,&a.tm_mon,&a.tm_year)==3)
+	{	a.tm_year-=1900;	a.tm_mon -= 1;
+		if(a.tm_mday>0 && a.tm_mday<32 && a.tm_mon<12)
+			t = mktime(&a);
+	}
+	else if(swscanf(s.c_str(),L"%d-%d-%d", &a.tm_hour,&a.tm_min,&a.tm_sec)==3)
+	{	a.tm_mday=1;	a.tm_mon=0;	a.tm_year=70;
+		if(a.tm_hour<24 && a.tm_min<60 && a.tm_sec<60)
+			t = mktime(&a);
+	}
+	return t;
+}
+//-----------------------------------------------------------------------------
+/// Parse string and substitute the script argument
+// All numbers are presented as mglData(1). Do boundary checking.
+// NOTE: In any case where number is required the mglData::a[0] is used.
+// String flag is binary 0x1 -> 'x', 0x2 -> 'y', 0x4 -> 'z'
+HMDT MGL_NO_EXPORT mglFormulaCalc(std::wstring str, mglParser *arg, const std::vector<mglDataA*> &head)
+{
+#if MGL_HAVE_GSL
+	gsl_set_error_handler_off();
+#endif
+	if(str.empty())	return new mglData;	// nothing to parse
+	str = mgl_trim_ws(str);
+	mreal tval = mgl_gettime(str);
+	if(mgl_isnum(tval))
+	{	mglData *r=new mglData;	r->a[0] = tval;	return r;	}
+
+	long n,len=str.length();
+	if(str[0]=='(' && mglCheck(str.substr(1,len-2)))	// remove braces
+	{	str = str.substr(1,len-2);	len-=2;	}
+	if(str[0]=='[')	// this is manual subdata
+	{
+		long i, j, br=0,k;
+		bool ar=true,mt=false;
+		HMDT res=0;
+		for(i=1,j=1;i<len-1;i++)
+		{
+			if(str[i]=='[')	br++;
+			if(str[i]==']' && br>0)	br--;
+			if(str[i]==',' && !br)
+			{
+				HMDT a1=mglFormulaCalc(str.substr(j,i-j), arg, head);
+				if(j==1)
+				{	res = a1;	ar = (a1->nx==1);	mt = (a1->nx>1 && a1->ny==1);	}
+				else
+				{
+					if(ar)		// res 1d array
+					{	k = res->nx;	res->Insert('x',k);	mgl_data_put_dat(res,a1,k,-1,-1);	}
+					else if(mt)	// res 2d array
+					{	k = res->ny;	res->Insert('y',k);	mgl_data_put_dat(res,a1,-1,k,-1);	}
+					else		// res 3d array
+					{	k = res->nz;	res->Insert('z',k);	mgl_data_put_dat(res,a1,-1,-1,k);	}
+					mgl_delete_data(a1);
+				}
+				j=i+1;
+			}
+		}
+		HMDT a1=mglFormulaCalc(str.substr(j,i-j), arg, head);
+		if(j==1)
+		{	res = a1;	ar = (a1->nx==1);	mt = (a1->nx>1 && a1->ny==1);	}
+		else
+		{
+			if(ar)		// res 1d array
+			{	k = res->nx;	res->Insert('x',k);	mgl_data_put_dat(res,a1,k,-1,-1);	}
+			else if(mt)	// res 2d array
+			{	k = res->ny;	res->Insert('y',k);	mgl_data_put_dat(res,a1,-1,k,-1);	}
+			else		// res 3d array
+			{	k = res->nz;	res->Insert('z',k);	mgl_data_put_dat(res,a1,-1,-1,k);	}
+			mgl_delete_data(a1);
+		}
+		return res;
+	}
+
+	n=mglFindInText(str,"&|");	// lowest priority -- logical
+	if(n>=0)
+		return mglApplyOper(str.substr(0,n),str.substr(n+1),arg, head, str[n]=='|'?cor:cand);
+	n=mglFindInText(str,"<>=");	// low priority -- conditions
+	if(n>=0)
+		return mglApplyOper(str.substr(0,n),str.substr(n+1),arg, head, str[n]=='<'?clt:(str[n]=='>'?cgt:ceq));
+	n=mglFindInText(str,"+-");	// normal priority -- additions
+	if(n>=0 && (n<2 || str[n-1]!='e' || (str[n-2]!='.' && !isdigit(str[n-2])) ))
+		return str[n]=='+'? mglApplyOperAdd(str.substr(0,n),str.substr(n+1),arg, head) : mglApplyOperSub(str.substr(0,n),str.substr(n+1),arg, head);
+	n=mglFindInText(str,"*/");	// high priority -- multiplications
+	if(n>=0)
+		return str[n]=='*'? mglApplyOperMul(str.substr(0,n),str.substr(n+1),arg, head) : mglApplyOperDiv(str.substr(0,n),str.substr(n+1),arg, head);
+	n=mglFindInText(str,"@");	// high priority -- combine
+	if(n>=0)
+	{
+		HMDT a1 = mglFormulaCalc(str.substr(0,n),arg, head);
+		HMDT a2 = mglFormulaCalc(str.substr(n+1),arg, head);
+		HMDT res = mgl_data_combine(a1,a2);
+		mgl_delete_data(a1);	mgl_delete_data(a2);
+		return res;
+	}
+	n=mglFindInText(str,"^");	// highest priority -- power
+	if(n>=0)	return mglApplyOper(str.substr(0,n),str.substr(n+1),arg, head, ipw);
+	n=mglFindInText(str,":");	// highest priority -- array
+	if(n>=0 && str.compare(L":"))
+	{
+		HMDT a1=mglFormulaCalc(str.substr(0,n), arg, head);
+		HMDT a2=mglFormulaCalc(str.substr(n+1), arg, head);
+		HMDT res = new mglData(abs(int(a2->a[0]+0.5)-int(a1->a[0]+0.5))+1);
+		res->Fill(a1->a[0], a2->a[0]);
+		mgl_delete_data(a1);	mgl_delete_data(a2);
+		return res;
+	}
+	n=mglFindInText(str,".");				// highest priority -- suffixes
+	wchar_t c0 = str[n+1];
+	if(n>=0  && c0>='a' && c0!='e')
+	{
+		mreal x,y,z,k,v=NAN;
+		HMDT d = mglFormulaCalc(str.substr(0,n), arg, head);
+		long ns[3] = {d->nx, d->ny, d->nz};
+		const std::wstring &p=str.substr(n+1);
+		wchar_t ch = p[1];
+		if(c0=='a')
+		{
+			if(ch==0)	v = d->a[0];
+			else
+			{
+				d->Momentum(ch,x,y);
+				if(ch=='a')	v = x;
+				else if(ch>='x' && ch<='z')	v = x/ns[ch-'x'];
+			}
+		}
+		else if(c0=='n')
+		{
+			if(ch>='x' && ch<='z')	v = ns[p[1]-'x'];
+			else if(!p.compare(L"nmax"))	{	v=d->MaximalNeg();	}
+			else if(!p.compare(L"nmin"))	{	v=d->Minimal();	v = v<0?v:0;	}
+		}
+		else if(c0=='k')
+		{
+			d->Momentum(ch,x,y,z,k);
+			if(ch=='a')	v = k;
+			else if(ch>='x' && ch<='z')	v = k/ns[ch-'x'];
+		}
+		else if(c0=='w')
+		{
+			d->Momentum(ch,x,y);
+			if(ch=='a')	v = y;
+			else if(ch>='x' && ch<='z')	v = y/ns[ch-'x'];
+		}
+		else if(c0=='m')
+		{
+			if(ch=='a' && p[2]=='x')	v = d->Maximal();
+			else if(ch=='i' && p[2]=='n')	v = d->Minimal();
+			else if(ch=='x' && p[2]=='f')	v = d->Maximal('x',0)/mreal(ns[0]);
+			else if(ch=='x' && p[2]=='l')	v = d->Maximal('x',-1)/mreal(ns[0]);
+			else if(ch=='x')	{	d->Maximal(x,y,z);	v = x/ns[0];	}
+			else if(ch=='y' && p[2]=='f')	v = d->Maximal('y',0)/mreal(ns[1]);
+			else if(ch=='y' && p[2]=='l')	v = d->Maximal('y',-1)/mreal(ns[1]);
+			else if(ch=='y')	{	d->Maximal(x,y,z);	v = y/ns[1];	}
+			else if(ch=='z' && p[2]=='f')	v = d->Maximal('z',0)/mreal(ns[2]);
+			else if(ch=='z' && p[2]=='l')	v = d->Maximal('z',-1)/mreal(ns[2]);
+			else if(ch=='z')	{	d->Maximal(x,y,z);	v = z/ns[2];	}
+		}
+		else if(c0=='s')
+		{
+			if(ch=='u' && p[2]=='m')	v = d->Momentum('x',x,y);
+			else if(ch=='a')
+			{	d->Momentum(ch,x,y,z,k);	v = z;	}
+			else if(ch>='x' && ch<='z')
+			{	d->Momentum(ch,x,y,z,k);	v = z/ns[ch-'x'];	}
+		}
+		else if(!p.compare(L"fst"))	{	long i=-1,j=-1,l=-1;	v = d->Find(0,i,j,l);	}
+		else if(!p.compare(L"lst"))	{	long i=-1,j=-1,l=-1;	v = d->Last(0,i,j,l);	}
+		else if(!p.compare(L"pmax"))	{	v=d->Maximal();	v = v>0?v:0;	}
+		else if(!p.compare(L"pmin"))	{	v=d->MinimalPos();	}
+		delete d;
+		// if this is valid suffix when finish parsing (it can be mreal number)
+		if(mgl_isfin(v))
+		{	HMDT res = new mglData;	res->a[0]=v;	return res;	}
+	}
+	for(n=0;n<len;n++)	if(str[n]=='(')	break;
+	if(n>=len)		// this is number or variable
+	{
+		HCDT v = (str!=L"#$mgl")?FindVar(head, str):0;
+		if(v)	return new mglData(v);
+		const mglNum *f = arg?arg->FindNum(str.c_str()):0;
+		if(f)	{	HMDT res = new mglData;	res->a[0] = f->d;	return res;	}
+		else if(!str.compare(L"rnd"))
+		{
+			v=FindVar(head, L"#$mgl");
+			HMDT res = v?new mglData(v->GetNx(),v->GetNy(),v->GetNz()) : new mglData;
+			for(long i=0;i<res->GetNN();i++)	res->a[i] = mgl_rnd();
+			return res;
+		}
+		else
+		{
+			HMDT res = new mglData;
+			wchar_t ch = str[0];
+			if(ch<':') res->a[0] = wcstod(str.c_str(),0);	// this is number
+			else if(!str.compare(L"pi"))	res->a[0] = M_PI;
+			else if(ch==':')	res->a[0] = -1;
+			else if(!str.compare(L"nan"))	res->a[0] = NAN;
+			else if(!str.compare(L"inf"))	res->a[0] = INFINITY;
+			return res;
+		}
+	}
+	else
+	{
+		std::wstring nm = str.substr(0,n);
+		str = str.substr(n+1,len-n-2);	len -= n+2;
+		HCDT v = FindVar(head, nm);
+//		mglVar *v = arg->FindVar(nm.c_str());
+		if(!v && !nm.compare(0,7,L"jacobi_"))	nm = nm.substr(7);
+		n = mglFindInText(str,",");
+		if(v)	// subdata
+		{
+			if(str[0]=='\'' && str[len-1]=='\'')	// this is column call
+			{
+				char *buf = new char[len];
+				mgl_wcstombs(buf, str.substr(1).c_str(), len-1);	buf[len-1]=0;
+				HMDT res = mgl_data_column(v,buf);
+				delete []buf;	return res;
+			}
+			else
+			{
+				HMDT a1=0, a2=0, a3=0;
+				if(n>0)
+				{
+					long m=mglFindInText(str.substr(0,n),",");
+					if(m>0)
+					{
+						str[m]=0;
+						a1 = mglFormulaCalc(str.substr(0,m), arg, head);
+						a2 = mglFormulaCalc(str.substr(m+1,n-m-1), arg, head);
+						a3 = mglFormulaCalc(str.substr(n+1), arg, head);
+					}
+					else
+					{
+						a1 = mglFormulaCalc(str.substr(0,n), arg, head);
+						a2 = mglFormulaCalc(str.substr(n+1), arg, head);
+					}
+				}
+				else	a1 = mglFormulaCalc(str, arg, head);
+				HMDT res = mgl_data_subdata_ext(v,a1,a2,a3);
+				mgl_delete_data(a1);	mgl_delete_data(a2);
+				mgl_delete_data(a3);	return res;
+			}
+		}
+		else if(nm[0]=='a')	// function
+		{
+			if(!nm.compare(L"asin"))		return mglApplyFunc(str, arg, head, asin);
+			else if(!nm.compare(L"acos"))	return mglApplyFunc(str, arg, head, acos);
+			else if(!nm.compare(L"atan"))	return mglApplyFunc(str, arg, head, atan);
+			else if(!nm.compare(L"asinh"))	return mglApplyFunc(str, arg, head, mgl_asinh);
+			else if(!nm.compare(L"acosh"))	return mglApplyFunc(str, arg, head, mgl_acosh);
+			else if(!nm.compare(L"atanh"))	return mglApplyFunc(str, arg, head, mgl_atanh);
+			else if(!nm.compare(L"arg"))
+			{
+				if(n>0)	return mglApplyOper(str.substr(n+1),str.substr(0,n),arg, head, atan2);
+				else
+				{
+					HADT a1 = mglFormulaCalcC(str, arg, head);
+					HMDT res = mgl_datac_arg(a1);
+					mgl_delete_datac(a1);	return res;
+				}
+			}
+			else if(!nm.compare(L"abs"))
+			{
+				if(n>0)	return mglApplyOper(str.substr(n+1),str.substr(0,n),arg, head, hypot);
+				else
+				{
+					HADT a1 = mglFormulaCalcC(str, arg, head);
+					HMDT res = mgl_datac_abs(a1);
+					mgl_delete_datac(a1);	return res;
+				}
+			}
+#if MGL_HAVE_GSL
+			else if(!nm.compare(L"ai") || !nm.compare(L"airy_ai"))
+				return mglApplyFuncGSL(str, arg, head, gsl_sf_airy_Ai);
+			else if(!nm.compare(L"airy_dai"))
+				return mglApplyFuncGSL(str, arg, head, gsl_sf_airy_Ai_deriv);
+			else if(!nm.compare(L"airy_bi"))
+				return mglApplyFuncGSL(str, arg, head, gsl_sf_airy_Bi);
+			else if(!nm.compare(L"airy_dbi"))
+				return mglApplyFuncGSL(str, arg, head, gsl_sf_airy_Bi_deriv);
+		}
+		else if(nm[0]=='b')
+		{
+			if(!nm.compare(L"beta") && n>0)
+				return mglApplyOper(str.substr(0,n),str.substr(n+1),arg, head, gsl_sf_beta);
+			else if(!nm.compare(L"bi"))
+				return mglApplyFuncGSL(str, arg, head, gsl_sf_airy_Bi);
+			else if(!nm.compare(L"bessel_i") && n>0)
+				return mglApplyOper(str.substr(0,n),str.substr(n+1),arg, head, gsl_sf_bessel_Inu);
+			else if(!nm.compare(L"bessel_j") && n>0)
+				return mglApplyOper(str.substr(0,n),str.substr(n+1),arg, head, gsl_sf_bessel_Jnu);
+			else if(!nm.compare(L"bessel_k") && n>0)
+				return mglApplyOper(str.substr(0,n),str.substr(n+1),arg, head, gsl_sf_bessel_Knu);
+			else if(!nm.compare(L"bessel_y") && n>0)
+				return mglApplyOper(str.substr(0,n),str.substr(n+1),arg, head, gsl_sf_bessel_Ynu);
+#endif
+		}
+		else if(nm[0]=='c')
+		{
+			if(!nm.compare(L"cos"))	return mglApplyFunc(str, arg, head, cos);
+			else if(!nm.compare(L"cosh") || !nm.compare(L"ch"))	return mglApplyFunc(str, arg, head, cosh);
+			else if(!nm.compare(L"conj"))
+			{
+				HADT a1 = mglFormulaCalcC(str, arg, head);
+				HMDT res = mgl_datac_real(a1);
+				mgl_delete_datac(a1);	return res;
+			}
+#if MGL_HAVE_GSL
+			else if(!nm.compare(L"ci"))	return mglApplyFunc(str, arg, head, gsl_sf_Ci);
+#endif
+		}
+		else if(nm[0]=='e')
+		{
+			if(!nm.compare(L"exp"))	return mglApplyFunc(str, arg, head, exp);
+#if MGL_HAVE_GSL
+			else if(!nm.compare(L"erf"))	return mglApplyFunc(str, arg, head, gsl_sf_erf);
+			else if(!nm.compare(L"ee") || !nm.compare(L"elliptic_ec"))
+				return mglApplyFuncGSL(str, arg, head, gsl_sf_ellint_Ecomp);
+			else if(!nm.compare(L"ek") || !nm.compare(L"elliptic_kc"))
+				return mglApplyFuncGSL(str, arg, head, gsl_sf_ellint_Kcomp);
+			else if((!nm.compare(L"e") || !nm.compare(L"elliptic_e")) && n>0)
+				return mglApplyOper(str.substr(0,n),str.substr(n+1),arg, head, gslEllE);
+			else if(!nm.compare(L"elliptic_f"))
+				return mglApplyOper(str.substr(0,n),str.substr(n+1),arg, head, gslEllF);
+
+			else if(!nm.compare(L"ei"))	return mglApplyFunc(str, arg, head, gsl_sf_expint_Ei);
+			else if(!nm.compare(L"e1"))	return mglApplyFunc(str, arg, head, gsl_sf_expint_E1);
+			else if(!nm.compare(L"e2"))	return mglApplyFunc(str, arg, head, gsl_sf_expint_E2);
+			else if(!nm.compare(L"eta"))	return mglApplyFunc(str, arg, head, gsl_sf_eta);
+			else if(!nm.compare(L"ei3"))	return mglApplyFunc(str, arg, head, gsl_sf_expint_3);
+#endif
+		}
+		else if(nm[0]=='l')
+		{
+			if(!nm.compare(L"log") && n>0)
+				return mglApplyOper(str.substr(0,n),str.substr(n+1),arg, head, llg);
+			else if(!nm.compare(L"lg"))	return mglApplyFunc(str, arg, head, log10);
+			else if(!nm.compare(L"ln"))	return mglApplyFunc(str, arg, head, log);
+#if MGL_HAVE_GSL
+			else if(!nm.compare(L"li2"))	return mglApplyFunc(str, arg, head, gsl_sf_dilog);
+			else if(!nm.compare(L"legendre") && n>0)
+				return mglApplyOper(str.substr(0,n),str.substr(n+1),arg, head, gslLegP);
+#endif
+		}
+		else if(nm[0]=='s')
+		{
+			if(!nm.compare(L"sqrt"))	return mglApplyFunc(str, arg, head, sqrt);
+			else if(!nm.compare(L"sin"))	return mglApplyFunc(str, arg, head, sin);
+			else if(!nm.compare(L"step"))	return mglApplyFunc(str, arg, head, stp);
+			else if(!nm.compare(L"sign"))	return mglApplyFunc(str, arg, head, sgn);
+			else if(!nm.compare(L"sinh") || !nm.compare(L"sh"))	return mglApplyFunc(str, arg, head, sinh);
+#if MGL_HAVE_GSL
+			else if(!nm.compare(L"si"))		return mglApplyFunc(str, arg, head, gsl_sf_Si);
+			else if(!nm.compare(L"sinc"))	return mglApplyFunc(str, arg, head, gsl_sf_sinc);
+#endif
+		}
+		else if(nm[0]=='t')
+		{
+			if(!nm.compare(L"tg") || !nm.compare(L"tan"))
+				return mglApplyFunc(str, arg, head, tan);
+			else if(!nm.compare(L"tanh") || !nm.compare(L"th"))
+				return mglApplyFunc(str, arg, head, tanh);
+		}
+		else if(!nm.compare(L"pow") && n>0)
+			return mglApplyOper(str.substr(0,n),str.substr(n+1),arg, head, pow);
+		else if(nm[0]=='m')
+		{
+			if(!nm.compare(L"mod") && n>0)
+				return mglApplyOper(str.substr(0,n),str.substr(n+1),arg, head, fmod);
+			else if(!nm.compare(L"min") && n>0)
+				return mglApplyOper(str.substr(0,n),str.substr(n+1),arg, head, mgl_fmin);
+			else if(!nm.compare(L"max") && n>0)
+				return mglApplyOper(str.substr(0,n),str.substr(n+1),arg, head, mgl_fmax);
+		}
+		else if(!nm.compare(L"int"))	return mglApplyFunc(str, arg, head, floor);
+		else if(!nm.compare(L"random"))
+		{	HMDT res=mglFormulaCalc(str, arg, head);	mreal *a = res->a;
+			for(long i=0;i<res->GetNN();i++)	a[i] = mgl_rnd();
+			return res;	}
+		else if(!nm.compare(L"real"))
+		{
+			HADT a1 = mglFormulaCalcC(str, arg, head);
+			HMDT res = mgl_datac_real(a1);
+			mgl_delete_datac(a1);	return res;
+		}
+		else if(!nm.compare(L"imag"))
+		{
+			HADT a1 = mglFormulaCalcC(str, arg, head);
+			HMDT res = mgl_datac_imag(a1);
+			mgl_delete_datac(a1);	return res;
+		}
+		else if(!nm.compare(L"norm"))
+		{
+			HADT a1 = mglFormulaCalcC(str, arg, head);
+			HMDT res = mgl_datac_norm(a1);
+			mgl_delete_datac(a1);	return res;
+		}
+#if MGL_HAVE_GSL
+		else if(!nm.compare(L"i") && n>0)
+			return mglApplyOper(str.substr(0,n),str.substr(n+1),arg, head, gsl_sf_bessel_Inu);
+		else if(!nm.compare(L"j") && n>0)
+			return mglApplyOper(str.substr(0,n),str.substr(n+1),arg, head, gsl_sf_bessel_Jnu);
+		else if(!nm.compare(L"k") && n>0)
+			return mglApplyOper(str.substr(0,n),str.substr(n+1),arg, head, gsl_sf_bessel_Knu);
+		else if(!nm.compare(L"y") && n>0)
+			return mglApplyOper(str.substr(0,n),str.substr(n+1),arg, head, gsl_sf_bessel_Ynu);
+		else if(!nm.compare(L"f") && n>0)
+			return mglApplyOper(str.substr(0,n),str.substr(n+1),arg, head, gslEllF);
+		else if(!nm.compare(L"hypot") && n>0)
+			return mglApplyOper(str.substr(n+1),str.substr(0,n),arg, head, hypot);
+		else if(!nm.compare(L"gamma"))	return mglApplyFunc(str, arg, head, gsl_sf_gamma);
+		else if(!nm.compare(L"gamma_inc") && n>0)
+			return mglApplyOper(str.substr(0,n),str.substr(n+1),arg, head, gsl_sf_gamma_inc);
+		else if(!nm.compare(L"w0"))	return mglApplyFunc(str, arg, head, gsl_sf_lambert_W0);
+		else if(!nm.compare(L"w1"))	return mglApplyFunc(str, arg, head, gsl_sf_lambert_Wm1);
+		else if(!nm.compare(L"psi"))	return mglApplyFunc(str, arg, head, gsl_sf_psi);
+		else if(!nm.compare(L"zeta"))	return mglApplyFunc(str, arg, head, gsl_sf_zeta);
+		else if(!nm.compare(L"z"))	return mglApplyFunc(str, arg, head, gsl_sf_dawson);
+#endif
+	}
+	HMDT res = new mglData;	res->a[0]=NAN;	return res;
+}
+//-----------------------------------------------------------------------------
+dual MGL_LOCAL_CONST ceqc(dual a,dual b);	//{return a==b?1:0;}
+dual MGL_LOCAL_CONST cltc(dual a,dual b);	//{return real(a-b)<0?1:0;}
+dual MGL_LOCAL_CONST cgtc(dual a,dual b);	//{return real(a-b)>0?1:0;}
+dual MGL_LOCAL_CONST ipwc(dual a,dual b);	//{return mgl_ipowc(a,int(b.real()));}
+dual MGL_LOCAL_CONST powc(dual a,dual b);	//{return exp(b*log(a));	}
+dual MGL_LOCAL_CONST llgc(dual a,dual b);	//{return log(a)/log(b);	}
+dual MGL_LOCAL_CONST cmplxc(dual a,dual b);	//{return a+dual(0,1)*b;	}
+dual MGL_LOCAL_CONST expi(dual a);	//{	return exp(dual(0,1)*a);	}
+dual MGL_LOCAL_CONST expi(double a);	//{	return dual(cos(a),sin(a));	}
+//-----------------------------------------------------------------------------
+dual MGL_LOCAL_CONST hypotc(dual x, dual y);	//{	return sqrt(x*x+y*y);	}
+dual MGL_LOCAL_CONST asinhc(dual x);	//{	return log(x+sqrt(x*x+mreal(1)));	}
+dual MGL_LOCAL_CONST acoshc(dual x);	//{	return log(x+sqrt(x*x-mreal(1)));	}
+dual MGL_LOCAL_CONST atanhc(dual x);	//{	return log((mreal(1)+x)/(mreal(1)-x))/mreal(2);	}
+dual MGL_LOCAL_CONST conjc(dual x);	//{	return dual(real(x),-imag(x));	}
+dual MGL_LOCAL_CONST sinc(dual x);	//{	return sin(x);	}
+dual MGL_LOCAL_CONST cosc(dual x);	//{	return cos(x);	}
+dual MGL_LOCAL_CONST tanc(dual x);	//{	return tan(x);	}
+dual MGL_LOCAL_CONST sinhc(dual x);	//{	return sinh(x);	}
+dual MGL_LOCAL_CONST coshc(dual x);	//{	return cosh(x);	}
+dual MGL_LOCAL_CONST tanhc(dual x);	//{	return tanh(x);	}
+dual MGL_LOCAL_CONST asinc(dual x);	//{	return log(ic*x+sqrt(mreal(1)-x*x))/ic;	}
+dual MGL_LOCAL_CONST acosc(dual x);	//{	return log(x+sqrt(x*x-mreal(1)))/ic;	}
+dual MGL_LOCAL_CONST atanc(dual x);	//{	return log((ic-x)/(ic+x))/(mreal(2)*ic);	}
+dual MGL_LOCAL_CONST expc(dual x);	//{	return exp(x);	}
+dual MGL_LOCAL_CONST sqrtc(dual x);	//{	return sqrt(x);	}
+dual MGL_LOCAL_CONST logc(dual x);	//{	return log(x);	}
+dual MGL_LOCAL_CONST absc(dual x);	//{	return abs(x);	}
+dual MGL_LOCAL_CONST argc(dual x);	//{	return arg(x);	}
+dual MGL_LOCAL_CONST lgc(dual x);	//{	return log10(x);}
+dual MGL_LOCAL_CONST realc(dual x);	//{	return real(x);	}
+dual MGL_LOCAL_CONST imagc(dual x);	//{	return imag(x);	}
+dual MGL_LOCAL_CONST normc(dual x);	//{	return norm(x);	}
+//-----------------------------------------------------------------------------
+/// Parse string and substitute the script argument
+// All numbers are presented as mglData(1). Do boundary checking.
+// NOTE: In any case where number is required the mglData::a[0] is used.
+// String flag is binary 0x1 -> 'x', 0x2 -> 'y', 0x4 -> 'z'
+HADT MGL_NO_EXPORT mglFormulaCalcC(std::wstring str, mglParser *arg, const std::vector<mglDataA*> &head)
+{
+#if MGL_HAVE_GSL
+	gsl_set_error_handler_off();
+#endif
+	if(str.empty())	return new mglDataC;	// nothing to parse
+	str = mgl_trim_ws(str);
+	mreal tval = mgl_gettime(str);
+	if(mgl_isnum(tval))
+	{	mglDataC *r=new mglDataC;	r->a[0] = tval;	return r;	}
+	
+	long n,len=str.length();
+	if(str[0]=='(' && mglCheck(str.substr(1,len-2)))	// remove braces
+	{	str = str.substr(1,len-2);	len-=2;	}
+	if(str[0]=='[')	// this is manual subdata
+	{
+		long i, j, br=0,k;
+		bool ar=true,mt=false;
+		HADT res=0;
+		for(i=1,j=1;i<len-1;i++)
+		{
+			if(str[i]=='[')	br++;
+			if(str[i]==']' && br>0)	br--;
+			if(str[i]==',' && !br)
+			{
+				HADT a1=mglFormulaCalcC(str.substr(j,i-j), arg, head);
+				if(j==1)
+				{	res = a1;	ar = (a1->nx==1);	mt = (a1->nx>1 && a1->ny==1);	}
+				else
+				{
+					if(ar)		// res 1d array
+					{	k = res->nx;	res->Insert('x',k);	mgl_datac_put_dat(res,a1,k,-1,-1);	}
+					else if(mt)	// res 2d array
+					{	k = res->ny;	res->Insert('y',k);	mgl_datac_put_dat(res,a1,-1,k,-1);	}
+					else		// res 3d array
+					{	k = res->nz;	res->Insert('z',k);	mgl_datac_put_dat(res,a1,-1,-1,k);	}
+				}
+				mgl_delete_datac(a1);	j=i+1;
+			}
+		}
+		HADT a1=mglFormulaCalcC(str.substr(j,i-j), arg, head);
+		if(j==1)
+		{	res = a1;	ar = (a1->nx==1);	mt = (a1->nx>1 && a1->ny==1);	}
+		else
+		{
+			if(ar)		// res 1d array
+			{	k = res->nx;	res->Insert('x',k);	mgl_datac_put_dat(res,a1,k,-1,-1);	}
+			else if(mt)	// res 2d array
+			{	k = res->ny;	res->Insert('y',k);	mgl_datac_put_dat(res,a1,-1,k,-1);	}
+			else		// res 3d array
+			{	k = res->nz;	res->Insert('z',k);	mgl_datac_put_dat(res,a1,-1,-1,k);	}
+		}
+		mgl_delete_datac(a1);	return res;
+	}
+
+	n=mglFindInText(str,"<>=");	// low priority -- conditions
+	if(n>=0)
+		return mglApplyOperC(str.substr(0,n),str.substr(n+1),arg, head, str[n]=='<'?cltc:(str[n]=='>'?cgtc:ceqc));
+	n=mglFindInText(str,"+-");	// normal priority -- additions
+	if(n>=0 && (n<2 || str[n-1]!='e' || (str[n-2]!='.' && !isdigit(str[n-2]))))
+		return str[n]=='+'? mglApplyOperAddC(str.substr(0,n),str.substr(n+1),arg, head) : mglApplyOperSubC(str.substr(0,n),str.substr(n+1),arg, head);
+	n=mglFindInText(str,"*/");	// high priority -- multiplications
+	if(n>=0)
+		return str[n]=='*'? mglApplyOperMulC(str.substr(0,n),str.substr(n+1),arg, head) : mglApplyOperDivC(str.substr(0,n),str.substr(n+1),arg, head);
+	n=mglFindInText(str,"@");	// high priority -- combine
+	if(n>=0)
+	{
+		HADT a1 = mglFormulaCalcC(str.substr(0,n),arg, head);
+		HADT a2 = mglFormulaCalcC(str.substr(n+1),arg, head);
+		HADT res = mgl_datac_combine(a1,a2);
+		mgl_delete_datac(a1);	mgl_delete_datac(a2);
+		return res;
+	}
+	n=mglFindInText(str,"^");				// highest priority -- power
+	if(n>=0)
+		return mglApplyOperC(str.substr(0,n),str.substr(n+1),arg, head, ipwc);
+	n=mglFindInText(str,":");				// highest priority -- array
+	if(n>=0 && str.compare(L":"))
+	{
+		HMDT a1=mglFormulaCalc(str.substr(0,n), arg, head);
+		HMDT a2=mglFormulaCalc(str.substr(n+1), arg, head);
+		HADT res = new mglDataC(abs(int(a2->a[0]+0.5)-int(a1->a[0]+0.5))+1);
+		res->Fill(a1->a[0], a2->a[0]);
+		mgl_delete_data(a1);	mgl_delete_data(a2);
+		return res;
+	}
+	n=mglFindInText(str,".");				// highest priority -- suffixes
+	wchar_t c0 = str[n+1];
+	if(n>=0  && c0>='a' && c0!='e')
+	{
+		dual v=NAN;
+		HADT d = mglFormulaCalcC(str.substr(0,n), arg, head);
+		long ns[3] = {d->nx, d->ny, d->nz};
+		const std::wstring &p=str.substr(n+1);
+		wchar_t ch = p[1];
+		if(c0=='a')
+		{
+			if(ch==0)	v = d->a[0];
+			else
+			{
+				mreal x,y;
+				d->Momentum(ch,x,y);
+				if(ch=='a')	v = x;
+				else if(ch>='x' && ch<='z')	v = x/ns[ch-'x'];
+			}
+		}
+		else if(c0=='n' && ch>='x' && ch<='z')	v = ns[ch-'x'];
+		else if(c0=='k')
+		{
+			mreal x,y,z,k;
+			d->Momentum(ch,x,y,z,k);
+			if(ch=='a')	v = k;
+			else if(ch>='x' && ch<='z')	v = k/ns[ch-'x'];
+		}
+		else if(c0=='w')
+		{
+			mreal x,y;
+			d->Momentum(ch,x,y);
+			if(ch=='a')	v = y;
+			else if(ch>='x' && ch<='z')	v = y/ns[ch-'x'];
+		}
+		else if(c0=='m')
+		{
+			mreal x,y,z;
+			if(ch=='a' && p[2]=='x')	v = d->Maximal();
+			else if(ch=='i' && p[2]=='n')	v = d->Minimal();
+			else if(ch=='x')	{	d->Maximal(x,y,z);	v = x/ns[0];	}
+			else if(ch=='y')	{	d->Maximal(x,y,z);	v = y/ns[1];	}
+			else if(ch=='z')	{	d->Maximal(x,y,z);	v = z/ns[2];	}
+		}
+		else if(c0=='s')
+		{
+			mreal x,y,z,k;
+			if(ch=='u' && p[2]=='m')	v = d->Momentum('x',x,y);
+			else if(ch=='a')
+			{	d->Momentum(ch,x,y,z,k);	v = z;	}
+			else if(ch>='x' && ch<='z')
+			{	d->Momentum(ch,x,y,z,k);	v = z/ns[ch-'x'];	}
+		}
+		else if(!p.compare(L"fst"))	{	long i=-1,j=-1,l=-1;	v = d->Find(0,i,j,l);	}
+		else if(!p.compare(L"lst"))	{	long i=-1,j=-1,l=-1;	v = d->Last(0,i,j,l);	}
+		delete d;
+		// if this is valid suffix when finish parsing (it can be mreal number)
+		if(mgl_isfin(v))
+		{	HADT res = new mglDataC;	res->a[0]=v;	return res;	}
+	}
+	for(n=0;n<len;n++)	if(str[n]=='(')	break;
+	if(n>=len)		// this is number or variable
+	{
+		HCDT v = (str!=L"#$mgl")?FindVar(head, str):0;
+		if(v)	return new mglDataC(v);
+		const mglNum *f = arg?arg->FindNum(str.c_str()):0;
+		if(f)	{	HADT res = new mglDataC;	res->a[0] = f->c;	return res;	}
+		else if(!str.compare(L"rnd"))
+		{
+			v=FindVar(head, L"#$mgl");
+			HADT res = v?new mglDataC(v->GetNx(),v->GetNy(),v->GetNz()) : new mglDataC;
+			for(long i=0;i<res->GetNN();i++)
+				res->a[i] = dual(mgl_rnd(), mgl_rnd());
+			return res;
+		}
+		else
+		{
+			HADT res = new mglDataC;
+			wchar_t ch = str[0];
+			if(ch<':')	// this is real number
+				res->a[0] = (str[str.length()-1]=='i') ? dual(0,wcstod(str.c_str(),0)) :  mreal(wcstod(str.c_str(),0));
+			else if(ch=='i')	// this is imaginary number
+				res->a[0] = dual(0,str[1]>' '?wcstod(str.c_str()+1,0):1);
+			else if(!str.compare(L"pi"))	res->a[0] = M_PI;
+			else if(ch==':')	res->a[0] = -1;
+			else if(!str.compare(L"nan"))	res->a[0] = NAN;
+			else if(!str.compare(L"inf"))	res->a[0] = INFINITY;
+			return res;
+		}
+	}
+	else
+	{
+		std::wstring nm = str.substr(0,n);
+		str = str.substr(n+1,len-n-2);	len -= n+2;
+		HCDT v = FindVar(head, nm);
+//		mglVar *v = arg->FindVar(nm.c_str());
+		if(!v && !nm.compare(0,7,L"jacobi_"))	nm = nm.substr(7);
+		n = mglFindInText(str,",");
+		if(v)	// subdata
+		{
+			if(str[0]=='\'' && str[len-1]=='\'')	// this is column call
+			{
+				char *buf = new char[len];
+				mgl_wcstombs(buf, str.substr(1).c_str(), len-1);	buf[len-1]=0;
+				HADT res = mgl_datac_column(v,buf);
+				delete []buf;	return res;
+			}
+			else
+			{
+				HMDT a1=0, a2=0, a3=0;
+				if(n>0)
+				{
+					long m=mglFindInText(str.substr(0,n),",");
+					if(m>0)
+					{
+						str[m]=0;
+						a1 = mglFormulaCalc(str.substr(0,m), arg, head);
+						a2 = mglFormulaCalc(str.substr(m+1,n-m-1), arg, head);
+						a3 = mglFormulaCalc(str.substr(n+1), arg, head);
+					}
+					else
+					{
+						a1 = mglFormulaCalc(str.substr(0,n), arg, head);
+						a2 = mglFormulaCalc(str.substr(n+1), arg, head);
+					}
+				}
+				else	a1 = mglFormulaCalc(str, arg, head);
+				HADT res = mgl_datac_subdata_ext(v,a1,a2,a3);
+				mgl_delete_data(a1);	mgl_delete_data(a2);
+				mgl_delete_data(a3);	return res;
+			}
+		}
+		else if(nm[0]=='a')	// function
+		{
+			if(!nm.compare(L"asin"))	return mglApplyFuncC(str, arg, head, asinc);
+			else if(!nm.compare(L"acos"))	return mglApplyFuncC(str, arg, head, acosc);
+			else if(!nm.compare(L"atan"))	return mglApplyFuncC(str, arg, head, atanc);
+			else if(!nm.compare(L"asinh"))	return mglApplyFuncC(str, arg, head, asinhc);
+			else if(!nm.compare(L"acosh"))	return mglApplyFuncC(str, arg, head, acoshc);
+			else if(!nm.compare(L"atanh"))	return mglApplyFuncC(str, arg, head, atanhc);
+			else if(!nm.compare(L"arg"))	return mglApplyFuncC(str, arg, head, argc);
+			else if(!nm.compare(L"abs"))	return mglApplyFuncC(str, arg, head, absc);
+		}
+		else if(nm[0]=='c')
+		{
+			if(!nm.compare(L"cos"))	return mglApplyFuncC(str, arg, head, cosc);
+			else if(!nm.compare(L"cosh") || !nm.compare(L"ch"))	return mglApplyFuncC(str, arg, head, coshc);
+			else if(!nm.compare(L"conj"))	return mglApplyFuncC(str, arg, head, conjc);
+			else if(!nm.compare(L"cmplx") && n>0)
+				return mglApplyOperC(str.substr(0,n),str.substr(n+1),arg, head, cmplxc);
+		}
+		else if(!nm.compare(L"exp"))	return mglApplyFuncC(str, arg, head, expc);
+		else if(nm[0]=='l')
+		{
+			if(!nm.compare(L"log") || !nm.compare(L"ln"))	return mglApplyFuncC(str, arg, head, logc);
+			else if(!nm.compare(L"lg"))	return mglApplyFuncC(str, arg, head, lgc);
+		}
+		else if(nm[0]=='s')
+		{
+			if(!nm.compare(L"sqrt"))	return mglApplyFuncC(str, arg, head, sqrtc);
+			else if(!nm.compare(L"sin"))	return mglApplyFuncC(str, arg, head, sinc);
+			else if(!nm.compare(L"sinh") || !nm.compare(L"sh"))	return mglApplyFuncC(str, arg, head, sinhc);
+		}
+		else if(nm[0]=='t')
+		{
+			if(!nm.compare(L"tg") || !nm.compare(L"tan"))	return mglApplyFuncC(str, arg, head, tanc);
+			else if(!nm.compare(L"tanh") || !nm.compare(L"th"))	return mglApplyFuncC(str, arg, head, tanhc);
+		}
+		else if(!nm.compare(L"pow") && n>0)
+			return mglApplyOperC(str.substr(0,n),str.substr(n+1),arg, head, powc);
+		else if(!nm.compare(L"random"))
+		{	HADT res=mglFormulaCalcC(str, arg, head);	dual *a = res->a;
+			for(long i=0;i<res->GetNN();i++)	a[i] = dual(mgl_rnd(), mgl_rnd());
+			return res;	}
+		else if(!nm.compare(L"hypot"))
+			return mglApplyOperC(str.substr(0,n),str.substr(n+1),arg, head, hypotc);
+		else if(!nm.compare(L"real"))	return mglApplyFuncC(str, arg, head, realc);
+		else if(!nm.compare(L"imag"))	return mglApplyFuncC(str, arg, head, imagc);
+		else if(!nm.compare(L"norm"))	return mglApplyFuncC(str, arg, head, normc);
+	}
+	HADT res = new mglDataC;	res->a[0]=NAN;	return res;
+}
+//-----------------------------------------------------------------------------
diff --git a/src/exec_dat.cpp b/src/exec_dat.cpp
new file mode 100644
index 0000000..53ee2da
--- /dev/null
+++ b/src/exec_dat.cpp
@@ -0,0 +1,1617 @@
+/***************************************************************************
+ * exec_dat.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifdef WIN32
+#include <io.h>
+#include <direct.h>
+#else
+#include <unistd.h>
+#endif
+
+#include "mgl2/base.h"
+#include "mgl2/parser.h"
+#pragma GCC diagnostic ignored "-Wmisleading-indentation"
+wchar_t *mgl_str_copy(const char *s);
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_addto(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"dd"))		*d += *(a[1].d);
+	else if(d && !strcmp(k,"dn"))	*d += a[1].v;
+	else if(c && !strcmp(k,"dd"))	*c += *(a[1].d);
+	else if(c && !strcmp(k,"dn"))	*c += a[1].c;
+	else	res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_apde(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	if(k[1]=='d' && a[1].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d), *f = dynamic_cast<mglData *>(a[1].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && f)
+	{
+		mglDataC r;
+		if(!strcmp(k,"ddsdd"))
+			r = gr->APDEc(a[2].s.c_str(), *(a[3].d), *(a[4].d), 0.1,100,opt);
+		else if(!strcmp(k,"ddsddn"))
+			r = gr->APDEc(a[2].s.c_str(), *(a[3].d), *(a[4].d), a[5].v,100,opt);
+		else if(!strcmp(k,"ddsddnn"))
+			r = gr->APDEc(a[2].s.c_str(), *(a[3].d), *(a[4].d), a[5].v,a[6].v,opt);
+		else res = 1;
+		if(res==0)	{	*d = r.Abs();	*f = r.Arg();	}
+	}
+	else if(d)
+	{
+		if(!strcmp(k,"dsdd"))
+			*d = gr->APDE(a[1].s.c_str(), *(a[2].d), *(a[3].d), 0.1,100,opt);
+		else if(!strcmp(k,"dsddn"))
+			*d = gr->APDE(a[1].s.c_str(), *(a[2].d), *(a[3].d), a[4].v,100,opt);
+		else if(!strcmp(k,"dsddnn"))
+			*d = gr->APDE(a[1].s.c_str(), *(a[2].d), *(a[3].d), a[4].v,a[5].v,opt);
+		else res = 1;
+	}
+	else if(c)
+	{
+		if(!strcmp(k,"dsdd"))
+			*c = gr->APDEc(a[1].s.c_str(), *(a[2].d), *(a[3].d), 0.1,100,opt);
+		else if(!strcmp(k,"dsddn"))
+			*c = gr->APDEc(a[1].s.c_str(), *(a[2].d), *(a[3].d), a[4].v,100,opt);
+		else if(!strcmp(k,"dsddnn"))
+			*c = gr->APDEc(a[1].s.c_str(), *(a[2].d), *(a[3].d), a[4].v,a[5].v,opt);
+		else res = 1;
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_clean(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(d && !strcmp(k,"dn"))	d->Clean(mgl_int(a[1].v));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_column(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"dds"))	*d = mglData(true,mgl_data_column(a[1].d,a[2].s.c_str()));
+	else if(c && !strcmp(k,"dds"))	*c = mglDataC(true,mgl_datac_column(a[1].d,a[2].s.c_str()));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_combine(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"ddd"))	*d = mglData(true,mgl_data_combine(a[1].d, a[2].d));
+	else if(c && !strcmp(k,"ddd"))	*c = mglDataC(true,mgl_datac_combine(a[1].d, a[2].d));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_copy(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(c && !strcmp(k,"dd"))	c->Set(a[1].d);
+	else if(!d)	return 1;
+	else if(!strcmp(k,"dd"))	d->Set(a[1].d);
+	else if(!strcmp(k,"dds"))
+	{	d->Set(a[1].d);	gr->Fill(*d, a[2].s.c_str());	}
+	else if(!strcmp(k,"ddd"))
+	{
+		mglData *D = dynamic_cast<mglData *>(a[1].d);
+		mglDataC *C = dynamic_cast<mglDataC *>(a[2].d);
+		if(D && C)	{	d->Set(C->Real());	D->Set(C->Imag());	}
+		else	res = 1;
+	}
+	else if(!strcmp(k,"dn"))	*d = a[1].v;
+	else if(!strcmp(k,"ds") && gr->pr)
+		d->Set(mgl_parser_find_var(gr->pr, a[1].s.c_str()));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_correl(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"dds"))	*d = mglData(true,mgl_data_correl(a[1].d, a[1].d, a[2].s.c_str()));
+	else if(d && !strcmp(k,"ddds"))	*d = mglData(true,mgl_data_correl(a[1].d, a[2].d, a[3].s.c_str()));
+	else if(c && !strcmp(k,"dds"))	*c = mglDataC(true,mgl_datac_correl(a[1].d, a[1].d, a[2].s.c_str()));
+	else if(c && !strcmp(k,"ddds"))	*c = mglDataC(true,mgl_datac_correl(a[1].d, a[2].d, a[3].s.c_str()));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_cosfft(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"ds"))	d->CosFFT(a[1].s.c_str());
+	else if(c && !strcmp(k,"ds"))	d->CosFFT(a[1].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_crop(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"dnns"))	d->Crop(mgl_int(a[1].v),mgl_int(a[2].v),a[3].s.c_str()[0]);
+	else if(d && !strcmp(k,"ds"))	d->Crop(a[1].s.c_str());
+	else if(c && !strcmp(k,"dnns"))	c->Crop(mgl_int(a[1].v),mgl_int(a[2].v),a[3].s.c_str()[0]);
+	else if(c && !strcmp(k,"ds"))	c->Crop(a[1].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_cumsum(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"ds"))	d->CumSum(a[1].s.c_str());
+	else if(c && !strcmp(k,"ds"))	c->CumSum(a[1].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_datagrid(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(!strcmp(k,"dddd") && d)	gr->DataGrid(*d, *(a[1].d), *(a[2].d), *(a[3].d),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_datas(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"s"))
+	{
+		char *buf=new char[1024];
+		long n=mgl_datas_hdf(a[0].s.c_str(),buf,1024);
+		if(n<0)
+		{
+			delete []buf;	buf=new char[-n];
+			mgl_datas_hdf(a[0].s.c_str(),buf,-n);
+		}
+		gr->SetWarn(-1,buf);
+		delete []buf;
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_delete(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if((!strcmp(k,"d") || !strcmp(k,"s")) && gr->pr)
+		mgl_parser_del_var(gr->pr, a[0].s.c_str());
+	else if(d && !strcmp(k,"ds"))	d->Delete(a[1].s.c_str()[0]);
+	else if(d && !strcmp(k,"dsn"))	d->Delete(a[1].s.c_str()[0], mgl_int(a[2].v));
+	else if(d && !strcmp(k,"dsnn"))	d->Delete(a[1].s.c_str()[0], mgl_int(a[2].v), mgl_int(a[3].v));
+	else if(c && !strcmp(k,"ds"))	c->Delete(a[1].s.c_str()[0]);
+	else if(c && !strcmp(k,"dsn"))	c->Delete(a[1].s.c_str()[0], mgl_int(a[2].v));
+	else if(c && !strcmp(k,"dsnn"))	c->Delete(a[1].s.c_str()[0], mgl_int(a[2].v), mgl_int(a[3].v));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_detect(mglGraph *, long, mglArg *a, const char *k, const char *)
+{
+	mglData *r = dynamic_cast<mglData*>(a[0].d);
+	int res = 0;
+	if(r && !strcmp(k, "ddnn"))	r->Set(mglDetect(*(a[1].d), a[2].v, a[3].v));
+	else if(r && !strcmp(k, "ddnnn"))	r->Set(mglDetect(*(a[1].d), a[2].v, a[3].v, a[4].v));
+	else if(r && !strcmp(k, "ddnnnn"))	r->Set(mglDetect(*(a[1].d), a[2].v, a[3].v, a[4].v, a[5].v));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_diff(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"ds"))	d->Diff(a[1].s.c_str());
+	else if(d && !strcmp(k,"ddd"))	d->Diff(*(a[1].d), *(a[2].d));
+	else if(d && !strcmp(k,"dddd"))	d->Diff(*(a[1].d), *(a[2].d), *(a[3].d));
+	else if(c && !strcmp(k,"ds"))	c->Diff(a[1].s.c_str());
+//	else if(c && !strcmp(k,"ddd"))	c->Diff(*(a[1].d), *(a[2].d));	// TODO Add later
+//	else if(c && !strcmp(k,"dddd"))	c->Diff(*(a[1].d), *(a[2].d), *(a[3].d));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_diff2(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"ds"))	d->Diff2(a[1].s.c_str());
+	else if(c && !strcmp(k,"ds"))	c->Diff2(a[1].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_diffract(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(c && !strcmp(k,"dsn"))	c->Diffraction(a[1].s.c_str(), a[2].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_dilate(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(d && !strcmp(k,"d"))	d->Dilate();
+	else if(d && !strcmp(k,"dn"))	d->Dilate(a[1].v);
+	else if(d && !strcmp(k,"dnn"))	d->Dilate(a[1].v, a[2].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_divto(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"dd"))		*d /= *(a[1].d);
+	else if(d && !strcmp(k,"dn"))	*d /= a[1].v;
+	else if(c && !strcmp(k,"dd"))	*c /= *(a[1].d);
+	else if(c && !strcmp(k,"dn"))	*c /= a[1].c;
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_echo(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->SetWarn(-1,a[0].d->Get().c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_envelop(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"d"))	d->Envelop();
+	else if(d && !strcmp(k,"ds"))	d->Envelop(a[1].s.c_str()[0]);
+	else if(c && !strcmp(k,"d"))	c->Envelop();
+	else if(c && !strcmp(k,"ds"))	c->Envelop(a[1].s.c_str()[0]);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_erode(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(d && !strcmp(k,"d"))	d->Erode();
+	else if(d && !strcmp(k,"dn"))	d->Erode(a[1].v);
+	else if(d && !strcmp(k,"dnn"))	d->Erode(a[1].v, a[2].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_evaluate(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && k[0]=='d' && k[1]=='d' && k[2]=='d')
+	{
+		if(k[3]==0)	*d = mglData(true,mgl_data_evaluate(a[1].d,a[2].d,0,0,true));
+		else if(!strcmp(k+3,"n"))	*d = mglData(true,mgl_data_evaluate(a[1].d,a[2].d,0,0, a[3].v!=0));
+		else if(!strcmp(k+3,"d"))	*d = mglData(true,mgl_data_evaluate(a[1].d,a[2].d,a[3].d,0,true));
+		else if(!strcmp(k+3,"dn"))	*d = mglData(true,mgl_data_evaluate(a[1].d,a[2].d,a[3].d,0, a[4].v!=0));
+		else if(!strcmp(k+3,"dd"))	*d = mglData(true,mgl_data_evaluate(a[1].d,a[2].d,a[3].d,a[4].d,true));
+		else if(!strcmp(k+3,"ddn"))	*d = mglData(true,mgl_data_evaluate(a[1].d,a[2].d,a[3].d,a[4].d, a[5].v!=0));
+		else res = 1;
+	}
+	else if(c && k[0]=='d' && k[1]=='d' && k[2]=='d')
+	{
+		if(k[3]==0)	*c = mglDataC(true,mgl_datac_evaluate(a[1].d,a[2].d,0,0,true));
+		else if(!strcmp(k+3,"n"))	*c = mglDataC(true,mgl_datac_evaluate(a[1].d,a[2].d,0,0, a[3].v!=0));
+		else if(!strcmp(k+3,"d"))	*c = mglDataC(true,mgl_datac_evaluate(a[1].d,a[2].d,a[3].d,0,true));
+		else if(!strcmp(k+3,"dn"))	*c = mglDataC(true,mgl_datac_evaluate(a[1].d,a[2].d,a[3].d,0, a[4].v!=0));
+		else if(!strcmp(k+3,"dd"))	*c = mglDataC(true,mgl_datac_evaluate(a[1].d,a[2].d,a[3].d,a[4].d,true));
+		else if(!strcmp(k+3,"ddn"))	*c = mglDataC(true,mgl_datac_evaluate(a[1].d,a[2].d,a[3].d,a[4].d, a[5].v!=0));
+		else res = 1;
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_export(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"dss"))	a[0].d->Export(a[1].s.c_str(), a[2].s.c_str());
+	else if(!strcmp(k,"dssnn"))	a[0].d->Export(a[1].s.c_str(), a[2].s.c_str(), a[3].v,a[4].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_extend(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"dn"))	d->Extend(mgl_int(a[1].v));
+	else if(d && !strcmp(k,"dnn"))	d->Extend(mgl_int(a[1].v),mgl_int(a[2].v));
+	else if(c && !strcmp(k,"dn"))	c->Extend(mgl_int(a[1].v));
+	else if(c && !strcmp(k,"dnn"))	c->Extend(mgl_int(a[1].v),mgl_int(a[2].v));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_fill(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && k[0]=='d')
+	{
+		if(!strcmp(k,"dnn"))	d->Fill(a[1].v,a[2].v);
+		else if(!strcmp(k,"dnns"))	d->Fill(a[1].v,a[2].v,a[3].s.c_str()[0]);
+		else if(!strcmp(k,"ds"))	gr->Fill(*d,a[1].s.c_str(),opt);
+		else if(!strcmp(k,"dsd"))	gr->Fill(*d,a[1].s.c_str(), *(a[2].d),opt);
+		else if(!strcmp(k,"dsdd"))	gr->Fill(*d,a[1].s.c_str(), *(a[2].d), *(a[3].d),opt);
+		else res = 1;
+	}
+	else if(c && k[0]=='d')
+	{
+		if(!strcmp(k,"dnn"))	c->Fill(a[1].v,a[2].v);
+		else if(!strcmp(k,"dnns"))	c->Fill(a[1].v,a[2].v,a[3].s.c_str()[0]);
+		else if(!strcmp(k,"ds"))	gr->Fill(*c,a[1].s.c_str(),opt);
+		else if(!strcmp(k,"dsd"))	gr->Fill(*c,a[1].s.c_str(), *(a[2].d),opt);
+		else if(!strcmp(k,"dsdd"))	gr->Fill(*c,a[1].s.c_str(), *(a[2].d), *(a[3].d),opt);
+		else res = 1;
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_fillsample(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(d && !strcmp(k,"ds"))	d->FillSample(a[1].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_fit(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(!d)	return 1;
+	if(!strcmp(k,"dddddssd"))
+	{
+		mglData *i = dynamic_cast<mglData *>(a[7].d);
+		if(i)	*d = gr->Fit(*(a[1].d), *(a[2].d), *(a[3].d), *(a[4].d), a[5].s.c_str(), a[6].s.c_str(), *i,opt);
+		else	res = 1;
+	}
+	else if(!strcmp(k,"dddddss"))
+		*d = gr->Fit(*(a[1].d), *(a[2].d), *(a[3].d), *(a[4].d), a[5].s.c_str(), a[6].s.c_str(),opt);
+	else if(!strcmp(k,"ddddssd"))
+	{
+		mglData *i = dynamic_cast<mglData *>(a[6].d);
+		if(i)	*d = gr->Fit(*(a[1].d), *(a[2].d), *(a[3].d), a[4].s.c_str(), a[5].s.c_str(), *i,opt);
+		else	res = 1;
+	}
+	else if(!strcmp(k,"ddddss"))
+		*d = gr->Fit(*(a[1].d), *(a[2].d), *(a[3].d), a[4].s.c_str(), a[5].s.c_str(),opt);
+	else if(!strcmp(k,"dddssd"))
+	{
+		mglData *i = dynamic_cast<mglData *>(a[5].d);
+		if(i)	*d = gr->Fit(*(a[1].d), *(a[2].d), a[3].s.c_str(), a[4].s.c_str(), *i,opt);
+		else	res = 1;
+	}
+	else if(!strcmp(k,"dddss"))
+		*d = gr->Fit(*(a[1].d), *(a[2].d), a[3].s.c_str(), a[4].s.c_str(),opt);
+	else if(!strcmp(k,"ddssd"))
+	{
+		mglData *i = dynamic_cast<mglData *>(a[4].d);
+		if(i)	*d = gr->Fit(*(a[1].d), a[2].s.c_str(), a[3].s.c_str(), *i,opt);
+		else	res = 1;
+	}
+	else if(!strcmp(k,"ddss"))
+		*d = gr->Fit(*(a[1].d), a[2].s.c_str(), a[3].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_fits(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(!d)	return 1;
+	if(!strcmp(k,"ddddddssd"))
+	{
+		mglData *i = dynamic_cast<mglData *>(a[8].d);
+		if(i)	*d = gr->FitS(*(a[1].d), *(a[2].d), *(a[3].d), *(a[4].d), *(a[5].d), a[6].s.c_str(), a[7].s.c_str(), *i,opt);
+		else	res = 1;
+	}
+	else if(!strcmp(k,"ddddddss"))
+		*d = gr->FitS(*(a[1].d), *(a[2].d), *(a[3].d), *(a[4].d), *(a[5].d), a[6].s.c_str(), a[7].s.c_str(),opt);
+	else if(!strcmp(k,"dddddssd"))
+	{
+		mglData *i = dynamic_cast<mglData *>(a[7].d);
+		if(i)	*d = gr->FitS(*(a[1].d), *(a[2].d), *(a[3].d), *(a[4].d), a[5].s.c_str(), a[6].s.c_str(), *i,opt);
+		else	res = 1;
+	}
+	else if(!strcmp(k,"dddddss"))
+		*d = gr->FitS(*(a[1].d), *(a[2].d), *(a[3].d), *(a[4].d), a[5].s.c_str(), a[6].s.c_str(),opt);
+	else if(!strcmp(k,"ddddssd"))
+	{
+		mglData *i = dynamic_cast<mglData *>(a[6].d);
+		if(i)	*d = gr->FitS(*(a[1].d), *(a[2].d), *(a[3].d), a[4].s.c_str(), a[5].s.c_str(), *i,opt);
+		else	res = 1;
+	}
+	else if(!strcmp(k,"ddddss"))
+		*d = gr->FitS(*(a[1].d), *(a[2].d), *(a[3].d), a[4].s.c_str(), a[5].s.c_str(),opt);
+	else if(!strcmp(k,"dddssd"))
+	{
+		mglData *i = dynamic_cast<mglData *>(a[5].d);
+		if(i)	*d = gr->FitS(*(a[1].d), *(a[2].d), a[3].s.c_str(), a[4].s.c_str(), *i,opt);
+		else	res = 1;
+	}
+	else if(!strcmp(k,"dddss"))
+		*d = gr->FitS(*(a[1].d), *(a[2].d), a[3].s.c_str(), a[4].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_fourier(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *re = dynamic_cast<mglData *>(a[0].d), *im = dynamic_cast<mglData *>(a[1].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(!strcmp(k,"dds") && re && im)	mglFourier(*re,*im,a[2].s.c_str());
+	else if(!strcmp(k,"ds") && c)		c->FFT(a[1].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_gspline(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"ddd"))	d->RefillGS(*(a[1].d),*(a[2].d),gr->Self()->Min.x,gr->Self()->Max.x,-1);
+	else if(d && !strcmp(k,"dddn"))	d->RefillGS(*(a[1].d),*(a[2].d),gr->Self()->Min.x,gr->Self()->Max.x,mgl_int(a[3].v));
+	else if(c && !strcmp(k,"ddd"))	c->RefillGS(*(a[1].d),*(a[2].d),gr->Self()->Min.x,gr->Self()->Max.x,-1);
+	else if(c && !strcmp(k,"dddn"))	c->RefillGS(*(a[1].d),*(a[2].d),gr->Self()->Min.x,gr->Self()->Max.x,mgl_int(a[3].v));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_hankel(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"ds"))		d->Hankel(a[1].s.c_str());
+	else if(c && !strcmp(k,"ds"))	c->Hankel(a[1].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_hist(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(!d)	return 1;
+	if(!strcmp(k,"ddd"))		*d = gr->Hist(*(a[1].d), *(a[2].d),opt);
+	else if(!strcmp(k,"dddd"))	*d = gr->Hist(*(a[1].d), *(a[2].d), *(a[3].d),opt);
+	else if(!strcmp(k,"ddddd"))	*d = gr->Hist(*(a[1].d), *(a[2].d), *(a[3].d), *(a[4].d),opt);
+	else if(!strcmp(k,"ddnnn"))	*d = mglData(true,mgl_data_hist(a[1].d,int(a[2].v+0.5), a[3].v, a[4].v, 0));
+	else if(!strcmp(k,"ddnnnn"))	*d = mglData(true,mgl_data_hist(a[1].d,mgl_int(a[2].v), a[3].v, a[4].v, mgl_int(a[5].v)));
+	else if(!strcmp(k,"dddnnn"))	*d = mglData(true,mgl_data_hist_w(a[1].d,a[2].d, mgl_int(a[3].v), a[4].v, a[5].v, 0));
+	else if(!strcmp(k,"dddnnnn"))	*d = mglData(true,mgl_data_hist_w(a[1].d,a[2].d, mgl_int(a[3].v), a[4].v, a[5].v, mgl_int(a[6].v)));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_idset(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"ds"))	d->SetColumnId(a[1].s.c_str());
+	else if(c && !strcmp(k,"ds"))	c->SetColumnId(a[1].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_import(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(!d)	return 1;
+	if(!strcmp(k,"dss"))	d->Import(a[1].s.c_str(), a[2].s.c_str());
+	else if(!strcmp(k,"dssnn"))	d->Import(a[1].s.c_str(), a[2].s.c_str(), a[3].v,a[4].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_info(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->SetWarn(-1,a[0].d->PrintInfo());
+	else if(!strcmp(k,"s"))	gr->SetWarn(-1,a[0].s.c_str());
+	else if(!strcmp(k,"n"))	gr->SetWarn(-1,("value = "+mgl_str_num(a[0].v)).c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_insert(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"ds"))	d->Insert(a[1].s.c_str()[0]);
+	else if(d && !strcmp(k,"dsn"))	d->Insert(a[1].s.c_str()[0], mgl_int(a[2].v));
+	else if(d && !strcmp(k,"dsnn"))	d->Insert(a[1].s.c_str()[0], mgl_int(a[2].v), mgl_int(a[3].v));
+	else if(c && !strcmp(k,"ds"))	c->Insert(a[1].s.c_str()[0]);
+	else if(c && !strcmp(k,"dsn"))	c->Insert(a[1].s.c_str()[0], mgl_int(a[2].v));
+	else if(c && !strcmp(k,"dsnn"))	c->Insert(a[1].s.c_str()[0], mgl_int(a[2].v), mgl_int(a[3].v));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_integrate(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"ds"))	d->Integral(a[1].s.c_str());
+	else if(c && !strcmp(k,"ds"))	c->Integral(a[1].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_jacobian(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(!d)	return 1;
+	if(!strcmp(k,"ddd"))	*d = mglJacobian(*(a[1].d), *(a[2].d));
+	else if(!strcmp(k,"dddd"))	*d = mglJacobian(*(a[1].d), *(a[2].d), *(a[3].d));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_join(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if((!d && !c) || k[1]!='d')	res = 1;
+	else if(d)	for(long i=1;k[i]=='d';i++)	d->Join(*(a[i].d));
+	else if(c)	for(long i=1;k[i]=='d';i++)	c->Join(*(a[i].d));
+	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_limit(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"dn"))		d->Limit(a[1].v);
+	else if(c && !strcmp(k,"dn"))	c->Limit(a[1].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_max(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(d && !strcmp(k,"dds"))	*d = mglData(true,mgl_data_max_dir(a[1].d,a[2].s.c_str()));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_min(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(d && !strcmp(k,"dds"))	*d = mglData(true,mgl_data_min_dir(a[1].d,a[2].s.c_str()));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_mirror(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"ds"))		d->Mirror(a[1].s.c_str());
+	else if(c && !strcmp(k,"ds"))	c->Mirror(a[1].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_modify(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"ds"))	d->Modify(a[1].s.c_str());
+	else if(d && !strcmp(k,"dsn"))	d->Modify(a[1].s.c_str(), mgl_int(a[2].v));
+	else if(d && !strcmp(k,"dsd"))	d->Modify(a[1].s.c_str(),*(a[2].d));
+	else if(d && !strcmp(k,"dsdd"))	d->Modify(a[1].s.c_str(),*(a[2].d),*(a[3].d));
+	else if(c && !strcmp(k,"ds"))	c->Modify(a[1].s.c_str());
+	else if(c && !strcmp(k,"dsn"))	c->Modify(a[1].s.c_str(), mgl_int(a[2].v));
+	else if(c && !strcmp(k,"dsd"))	c->Modify(a[1].s.c_str(),*(a[2].d));
+	else if(c && !strcmp(k,"dsdd"))	c->Modify(a[1].s.c_str(),*(a[2].d),*(a[3].d));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_momentum(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"dds"))	*d = mglData(true,mgl_data_momentum(a[1].d,'z', a[2].s.c_str()));
+	else if(d && !strcmp(k,"ddss"))	*d = mglData(true,mgl_data_momentum(a[1].d,a[3].s.c_str()[0], a[2].s.c_str()));
+	else if(c && !strcmp(k,"dds"))	*c = mglDataC(true,mgl_datac_momentum(a[1].d,'z', a[2].s.c_str()));
+	else if(c && !strcmp(k,"ddss"))	*c = mglDataC(true,mgl_datac_momentum(a[1].d,a[3].s.c_str()[0], a[2].s.c_str()));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_multo(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"dd"))		*d *= *(a[1].d);
+	else if(d && !strcmp(k,"dn"))	*d *= a[1].v;
+	else if(c && !strcmp(k,"dd"))	*c *= *(a[1].d);
+	else if(c && !strcmp(k,"dn"))	*c *= a[1].c;
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_new(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"dn"))	d->Create(mgl_int(a[1].v));
+	else if(d && !strcmp(k,"dns"))
+	{	d->Create(mgl_int(a[1].v));	d->Fill(gr->Self(),a[2].s.c_str(),opt);	}
+	else if(d && !strcmp(k,"dnn"))	d->Create(mgl_int(a[1].v),mgl_int(a[2].v));
+	else if(d && !strcmp(k,"dnns"))
+	{	d->Create(mgl_int(a[1].v),mgl_int(a[2].v));	d->Fill(gr->Self(),a[3].s.c_str(),opt);	}
+	else if(d && !strcmp(k,"dnnn"))	d->Create(mgl_int(a[1].v),mgl_int(a[2].v),mgl_int(a[3].v));
+	else if(d && !strcmp(k,"dnnns"))
+	{	d->Create(mgl_int(a[1].v),mgl_int(a[2].v),mgl_int(a[3].v));	d->Fill(gr->Self(),a[4].s.c_str(),opt);	}
+	else if(c && !strcmp(k,"dn"))	c->Create(mgl_int(a[1].v));
+	else if(c && !strcmp(k,"dns"))
+	{	c->Create(mgl_int(a[1].v));	c->Fill(gr->Self(),a[2].s.c_str(),opt);	}
+	else if(c && !strcmp(k,"dnn"))	c->Create(mgl_int(a[1].v),mgl_int(a[2].v));
+	else if(c && !strcmp(k,"dnns"))
+	{	c->Create(mgl_int(a[1].v),mgl_int(a[2].v));	c->Fill(gr->Self(),a[3].s.c_str(),opt);	}
+	else if(c && !strcmp(k,"dnnn"))	c->Create(mgl_int(a[1].v),mgl_int(a[2].v),mgl_int(a[3].v));
+	else if(c && !strcmp(k,"dnnns"))
+	{	c->Create(mgl_int(a[1].v),mgl_int(a[2].v),mgl_int(a[3].v));	c->Fill(gr->Self(),a[4].s.c_str(),opt);	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_norm(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(!d)	return 1;
+	if(!strcmp(k,"dnn"))	d->Norm(a[1].v,a[2].v);
+	else if(!strcmp(k,"dnnn"))	d->Norm(a[1].v,a[2].v,a[3].v!=0);
+	else if(!strcmp(k,"dnnnn"))	d->Norm(a[1].v,a[2].v,a[3].v!=0,mgl_int(a[4].v));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_normsl(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(!d)	return 1;
+	if(!strcmp(k,"dnn"))	d->NormSl(a[1].v, a[2].v);
+	else if(!strcmp(k,"dnns"))	d->NormSl(a[1].v, a[2].v, a[3].s.c_str()[0]);
+	else if(!strcmp(k,"dnnsn"))	d->NormSl(a[1].v, a[2].v, a[3].s.c_str()[0],a[4].v);
+	else if(!strcmp(k,"dnnsnn"))d->NormSl(a[1].v, a[2].v, a[3].s.c_str()[0],a[4].v,a[5].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_ode(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d)
+	{
+		if(!strcmp(k,"dssd"))
+			*d = mglODE(a[1].s.c_str(), a[2].s.c_str(), *(a[3].d));
+		else if(!strcmp(k,"dssdnn"))
+			*d = mglODE(a[1].s.c_str(), a[2].s.c_str(), *(a[3].d), a[4].v, a[5].v);
+	}
+	else if(c)
+	{
+		if(!strcmp(k,"dssd"))
+			*c = mglODEc(a[1].s.c_str(), a[2].s.c_str(), *(a[3].d));
+		else if(!strcmp(k,"dssdnn"))
+			*c = mglODEc(a[1].s.c_str(), a[2].s.c_str(), *(a[3].d), a[4].v, a[5].v);
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_openhdf(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"s") && gr->pr)	mgl_parser_openhdf(gr->pr, a[0].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_pde(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	if(k[1]=='d' && a[1].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d), *f = dynamic_cast<mglData *>(a[1].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && f)
+	{
+		mglDataC r;
+		if(!strcmp(k,"ddsdd"))
+			r = gr->PDEc(a[2].s.c_str(), *(a[3].d), *(a[4].d), 0.1,100,opt);
+		else if(!strcmp(k,"ddsddn"))
+			r = gr->PDEc(a[2].s.c_str(), *(a[3].d), *(a[4].d), a[5].v,100,opt);
+		else if(!strcmp(k,"ddsddnn"))
+			r = gr->PDEc(a[2].s.c_str(), *(a[3].d), *(a[4].d), a[5].v,a[6].v,opt);
+		else res = 1;
+		if(res==0)	{	*d = r.Abs();	*f = r.Arg();	}
+	}
+	else if(d)
+	{
+		if(!strcmp(k,"dsdd"))
+			*d = gr->PDE(a[1].s.c_str(), *(a[2].d), *(a[3].d), 0.1,100,opt);
+		else if(!strcmp(k,"dsddn"))
+			*d = gr->PDE(a[1].s.c_str(), *(a[2].d), *(a[3].d), a[4].v,100,opt);
+		else if(!strcmp(k,"dsddnn"))
+			*d = gr->PDE(a[1].s.c_str(), *(a[2].d), *(a[3].d), a[4].v,a[5].v,opt);
+		else res = 1;
+	}
+	else if(c)
+	{
+		if(!strcmp(k,"dsdd"))
+			*c = gr->PDEc(a[1].s.c_str(), *(a[2].d), *(a[3].d), 0.1,100,opt);
+		else if(!strcmp(k,"dsddn"))
+			*c = gr->PDEc(a[1].s.c_str(), *(a[2].d), *(a[3].d), a[4].v,100,opt);
+		else if(!strcmp(k,"dsddnn"))
+			*c = gr->PDEc(a[1].s.c_str(), *(a[2].d), *(a[3].d), a[4].v,a[5].v,opt);
+		else res = 1;
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_print(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	printf("%s\n",a[0].d->PrintInfo());
+	else if(!strcmp(k,"s"))	printf("%s\n",a[0].s.c_str());
+	else if(!strcmp(k,"n"))	printf("value = %g\n",a[0].v);
+	else res = 1;	fflush(stdout);	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_pulse(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(d && !strcmp(k,"dds"))	*d = mglData(true,mgl_data_pulse(a[1].d,a[2].s[0]));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_put(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d)
+	{
+		if(!strcmp(k,"dn"))	d->Put(a[1].v);
+		else if(!strcmp(k,"dnn"))	d->Put(a[1].v, mgl_int(a[2].v));
+		else if(!strcmp(k,"dnnn"))	d->Put(a[1].v, mgl_int(a[2].v),mgl_int(a[3].v));
+		else if(!strcmp(k,"dnnnn"))	d->Put(a[1].v, mgl_int(a[2].v),mgl_int(a[3].v),mgl_int(a[4].v));
+		else if(!strcmp(k,"dd"))	d->Put(*(a[1].d));
+		else if(!strcmp(k,"ddn"))	d->Put(*(a[1].d), mgl_int(a[2].v));
+		else if(!strcmp(k,"ddnn"))	d->Put(*(a[1].d), mgl_int(a[2].v),mgl_int(a[3].v));
+		else if(!strcmp(k,"ddnnn"))	d->Put(*(a[1].d), mgl_int(a[2].v),mgl_int(a[3].v),mgl_int(a[4].v));
+		else res = 1;
+	}
+	else if(c)
+	{
+		if(!strcmp(k,"dn"))	c->Put(a[1].c);
+		else if(!strcmp(k,"dnn"))	c->Put(a[1].c, mgl_int(a[2].v));
+		else if(!strcmp(k,"dnnn"))	c->Put(a[1].c, mgl_int(a[2].v),mgl_int(a[3].v));
+		else if(!strcmp(k,"dnnnn"))	c->Put(a[1].c, mgl_int(a[2].v),mgl_int(a[3].v),mgl_int(a[4].v));
+		else if(!strcmp(k,"dd"))	c->Put(*(a[1].d));
+		else if(!strcmp(k,"ddn"))	c->Put(*(a[1].d), mgl_int(a[2].v));
+		else if(!strcmp(k,"ddnn"))	c->Put(*(a[1].d), mgl_int(a[2].v),mgl_int(a[3].v));
+		else if(!strcmp(k,"ddnnn"))	c->Put(*(a[1].d), mgl_int(a[2].v),mgl_int(a[3].v),mgl_int(a[4].v));
+		else res = 1;
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_putsfit(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;	gr->Self()->SaveState(opt);
+	if(!strcmp(k,"nn"))		gr->PutsFit(mglPoint(a[0].v,a[1].v));
+	else if(!strcmp(k,"nns"))	gr->PutsFit(mglPoint(a[0].v,a[1].v), a[2].s.c_str());
+	else if(!strcmp(k,"nnss"))	gr->PutsFit(mglPoint(a[0].v,a[1].v), a[2].s.c_str(),a[3].s.c_str());
+	else if(!strcmp(k,"nnssn"))	gr->PutsFit(mglPoint(a[0].v,a[1].v), a[2].s.c_str(),a[3].s.c_str(),a[4].v);
+	else if(!strcmp(k,"nnn"))	gr->PutsFit(mglPoint(a[0].v,a[1].v,a[2].v));
+	else if(!strcmp(k,"nnns"))	gr->PutsFit(mglPoint(a[0].v,a[1].v,a[2].v), a[3].s.c_str());
+	else if(!strcmp(k,"nnnss"))	gr->PutsFit(mglPoint(a[0].v,a[1].v,a[2].v), a[3].s.c_str(),a[4].s.c_str());
+	else if(!strcmp(k,"nnnssn"))gr->PutsFit(mglPoint(a[0].v,a[1].v,a[2].v), a[3].s.c_str(),a[4].s.c_str(),a[5].v);
+	else res = 1;	gr->Self()->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_qo2d(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	if(k[1]=='d' && a[1].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d), *f = dynamic_cast<mglData *>(a[1].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && f)
+	{
+		mglDataC r;
+		if(!strcmp(k,"ddsddd"))
+			r = mglDataC(true, mgl_qo2d_solve_c(a[2].s.c_str(), a[3].d, a[4].d, a[5].d, 1,100, 0,0));
+		else if(!strcmp(k,"ddsdddn"))
+			r = mglDataC(true, mgl_qo2d_solve_c(a[2].s.c_str(), a[3].d, a[4].d, a[5].d, a[6].v,100, 0,0));
+		else if(!strcmp(k,"ddsdddnn"))
+			r = mglDataC(true, mgl_qo2d_solve_c(a[2].s.c_str(), a[3].d, a[4].d, a[5].d, a[6].v,a[7].v, 0,0));
+		else if(!strcmp(k,"ddsdddnndd"))
+			r = mglDataC(true, mgl_qo2d_solve_c(a[2].s.c_str(), a[3].d, a[4].d, a[5].d, a[6].v,a[7].v, dynamic_cast<mglData *>(a[8].d),dynamic_cast<mglData *>(a[9].d)));
+		else res = 1;
+		if(res==0)	{	*d = r.Abs();	*f = r.Arg();	}
+	}
+	else if(d)
+	{
+		if(!strcmp(k,"dsddd"))
+			*d = mglData(true, mgl_qo2d_solve(a[1].s.c_str(), a[2].d, a[3].d, a[4].d, 1,100, 0,0));
+		else if(!strcmp(k,"dsdddn"))
+			*d = mglData(true, mgl_qo2d_solve(a[1].s.c_str(), a[2].d, a[3].d, a[4].d, a[5].v,100, 0,0));
+		else if(!strcmp(k,"dsdddnn"))
+			*d = mglData(true, mgl_qo2d_solve(a[1].s.c_str(), a[2].d, a[3].d, a[4].d, a[5].v,a[6].v, 0,0));
+		else if(!strcmp(k,"dsdddnndd"))
+			*d = mglData(true, mgl_qo2d_solve(a[1].s.c_str(), a[2].d, a[3].d, a[4].d, a[5].v,a[6].v, dynamic_cast<mglData *>(a[7].d),dynamic_cast<mglData *>(a[8].d)));
+		else res = 1;
+	}
+	else if(c)
+	{
+		if(!strcmp(k,"dsddd"))
+			*c = mglDataC(true, mgl_qo2d_solve_c(a[1].s.c_str(), a[2].d, a[3].d, a[4].d, 1,100, 0,0));
+		else if(!strcmp(k,"dsdddn"))
+			*c = mglDataC(true, mgl_qo2d_solve_c(a[1].s.c_str(), a[2].d, a[3].d, a[4].d, a[5].v,100, 0,0));
+		else if(!strcmp(k,"dsdddnn"))
+			*c = mglDataC(true, mgl_qo2d_solve_c(a[1].s.c_str(), a[2].d, a[3].d, a[4].d, a[5].v,a[6].v, 0,0));
+		else if(!strcmp(k,"dsdddnndd"))
+			*c = mglDataC(true, mgl_qo2d_solve_c(a[1].s.c_str(), a[2].d, a[3].d, a[4].d, a[5].v,a[6].v, dynamic_cast<mglData *>(a[7].d),dynamic_cast<mglData *>(a[8].d)));
+		else res = 1;
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_qo3d(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	if(k[1]=='d' && a[1].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d), *f = dynamic_cast<mglData *>(a[1].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && f)
+	{
+		mglDataC r;
+		if(!strcmp(k,"ddsddd"))
+			r = mglDataC(true, mgl_qo3d_solve_c(a[2].s.c_str(), a[3].d, a[4].d, a[5].d, 1,100, 0,0,0));
+		else if(!strcmp(k,"ddsdddn"))
+			r = mglDataC(true, mgl_qo3d_solve_c(a[2].s.c_str(), a[3].d, a[4].d, a[5].d, a[6].v,100, 0,0,0));
+		else if(!strcmp(k,"ddsdddnn"))
+			r = mglDataC(true, mgl_qo3d_solve_c(a[2].s.c_str(), a[3].d, a[4].d, a[5].d, a[6].v,a[7].v, 0,0,0));
+		else if(!strcmp(k,"ddsdddnnddd"))
+			r = mglDataC(true, mgl_qo3d_solve_c(a[2].s.c_str(), a[3].d, a[4].d, a[5].d, a[6].v,a[7].v, dynamic_cast<mglData *>(a[8].d),dynamic_cast<mglData *>(a[9].d),dynamic_cast<mglData *>(a[10].d)));
+		else res = 1;
+		if(res==0)	{	*d = r.Abs();	*f = r.Arg();	}
+	}
+	else if(d)
+	{
+		if(!strcmp(k,"dsddd"))
+			*d = mglData(true, mgl_qo3d_solve(a[1].s.c_str(), a[2].d, a[3].d, a[4].d, 1,100, 0,0,0));
+		else if(!strcmp(k,"dsdddn"))
+			*d = mglData(true, mgl_qo3d_solve(a[1].s.c_str(), a[2].d, a[3].d, a[4].d, a[5].v,100, 0,0,0));
+		else if(!strcmp(k,"dsdddnn"))
+			*d = mglData(true, mgl_qo3d_solve(a[1].s.c_str(), a[2].d, a[3].d, a[4].d, a[5].v,a[6].v, 0,0,0));
+		else if(!strcmp(k,"dsdddnnddd"))
+			*d = mglData(true, mgl_qo3d_solve(a[1].s.c_str(), a[2].d, a[3].d, a[4].d, a[5].v,a[6].v, dynamic_cast<mglData *>(a[7].d),dynamic_cast<mglData *>(a[8].d),dynamic_cast<mglData *>(a[9].d)));
+		else res = 1;
+	}
+	else if(c)
+	{
+		if(!strcmp(k,"dsddd"))
+			*c = mglDataC(true, mgl_qo3d_solve_c(a[1].s.c_str(), a[2].d, a[3].d, a[4].d, 1,100, 0,0,0));
+		else if(!strcmp(k,"dsdddn"))
+			*c = mglDataC(true, mgl_qo3d_solve_c(a[1].s.c_str(), a[2].d, a[3].d, a[4].d, a[5].v,100, 0,0,0));
+		else if(!strcmp(k,"dsdddnn"))
+			*c = mglDataC(true, mgl_qo3d_solve_c(a[1].s.c_str(), a[2].d, a[3].d, a[4].d, a[5].v,a[6].v, 0,0,0));
+		else if(!strcmp(k,"dsdddnnddd"))
+			*c = mglDataC(true, mgl_qo3d_solve_c(a[1].s.c_str(), a[2].d, a[3].d, a[4].d, a[5].v,a[6].v, dynamic_cast<mglData *>(a[7].d),dynamic_cast<mglData *>(a[8].d),dynamic_cast<mglData *>(a[9].d)));
+		else res = 1;
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_ray(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(!d)	return 1;
+	if(!strcmp(k,"dsnnnn"))
+		*d = mglRay(a[1].s.c_str(), mglPoint(a[2].v, a[3].v), mglPoint(a[4].v, a[5].v));
+	else if(!strcmp(k,"dsnnnnnn"))
+		*d = mglRay(a[1].s.c_str(), mglPoint(a[2].v, a[3].v, a[4].v), mglPoint(a[5].v, a[6].v, a[7].v));
+	else if(!strcmp(k,"dsnnnnnnn"))
+		*d = mglRay(a[1].s.c_str(), mglPoint(a[2].v, a[3].v, a[4].v), mglPoint(a[5].v, a[6].v, a[7].v), a[8].v);
+	else if(!strcmp(k,"dsnnnnnnnn"))
+		*d = mglRay(a[1].s.c_str(), mglPoint(a[2].v, a[3].v, a[4].v), mglPoint(a[5].v, a[6].v, a[7].v), a[8].v,a[9].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_read(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	bool rr=true;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	if(k[1]=='d' && a[1].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglData *f = dynamic_cast<mglData *>(a[1].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(c)
+	{
+		if(!strcmp(k,"ds"))			rr=c->Read(a[1].s.c_str());
+		else if(!strcmp(k,"dsn"))	rr=c->Read(a[1].s.c_str(), mgl_int(a[2].v));
+		else if(!strcmp(k,"dsnn"))	rr=c->Read(a[1].s.c_str(), mgl_int(a[2].v),mgl_int(a[3].v));
+		else if(!strcmp(k,"dsnnn"))	rr=c->Read(a[1].s.c_str(), mgl_int(a[2].v),mgl_int(a[3].v),mgl_int(a[4].v));
+		else res = 1;
+	}
+	else if(d && f && k[0]=='d' && k[1]=='d' && k[2]=='s')
+	{
+		mglDataC r;
+		if(k[3]==0)	rr=r.Read(a[2].s.c_str());
+		else if(!strcmp(k+3,"n"))	rr=r.Read(a[2].s.c_str(), mgl_int(a[3].v));
+		else if(!strcmp(k+3,"nn"))	rr=r.Read(a[2].s.c_str(), mgl_int(a[3].v),mgl_int(a[4].v));
+		else if(!strcmp(k+3,"nnn"))	rr=r.Read(a[2].s.c_str(), mgl_int(a[3].v),mgl_int(a[4].v),mgl_int(a[5].v));
+		else res = 1;
+		if(res==0)	{	*d = r.Real();	*f = r.Imag();	}
+	}
+	else if(d)
+	{
+		if(!strcmp(k,"ds"))	rr=d->Read(a[1].s.c_str());
+		else if(!strcmp(k,"dsn"))	rr=d->Read(a[1].s.c_str(), mgl_int(a[2].v));
+		else if(!strcmp(k,"dsnn"))	rr=d->Read(a[1].s.c_str(), mgl_int(a[2].v),mgl_int(a[3].v));
+		else if(!strcmp(k,"dsnnn"))	rr=d->Read(a[1].s.c_str(), mgl_int(a[2].v),mgl_int(a[3].v),mgl_int(a[4].v));
+		else res = 1;
+	}
+	else res = 1;
+	if(!rr)	gr->SetWarn(mglWarnFile,"Read");
+	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_readall(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	bool rr=true;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"ds"))	rr=d->ReadAll(a[1].s.c_str());
+	else if(d && !strcmp(k,"dsn"))		rr=d->ReadAll(a[1].s.c_str(), a[2].v);
+	else if(d && !strcmp(k,"dsnn"))		rr=d->ReadRange(a[1].s.c_str(), a[2].v, a[3].v);
+	else if(d && !strcmp(k,"dsnnn"))	rr=d->ReadRange(a[1].s.c_str(), a[2].v, a[3].v, a[4].v);
+	else if(d && !strcmp(k,"dsnnnn"))	rr=d->ReadRange(a[1].s.c_str(), a[2].v, a[3].v, a[4].v, a[5].v);
+	else if(c && !strcmp(k,"ds"))		rr=c->ReadAll(a[1].s.c_str());
+	else if(c && !strcmp(k,"dsn"))		rr=c->ReadAll(a[1].s.c_str(), a[2].v);
+	else if(c && !strcmp(k,"dsnn"))		rr=c->ReadRange(a[1].s.c_str(), a[2].v, a[3].v);
+	else if(c && !strcmp(k,"dsnnn"))	rr=c->ReadRange(a[1].s.c_str(), a[2].v, a[3].v, a[4].v);
+	else if(c && !strcmp(k,"dsnnnn"))	rr=c->ReadRange(a[1].s.c_str(), a[2].v, a[3].v, a[4].v, a[5].v);
+	else res = 1;
+	if(!rr)	gr->SetWarn(mglWarnFile,"ReadAll");
+	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_readhdf(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"dss"))	d->ReadHDF(a[1].s.c_str(), a[2].s.c_str());
+	else if(c && !strcmp(k,"dss"))	c->ReadHDF(a[1].s.c_str(), a[2].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_readmat(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	bool rr=true;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"ds"))		rr=d->ReadMat(a[1].s.c_str());
+	else if(d && !strcmp(k,"dsn"))	rr=d->ReadMat(a[1].s.c_str(), mgl_int(a[2].v));
+	else if(c && !strcmp(k,"ds"))	rr=c->ReadMat(a[1].s.c_str());
+	else if(c && !strcmp(k,"dsn"))	rr=c->ReadMat(a[1].s.c_str(), mgl_int(a[2].v));
+	else res = 1;
+	if(!rr)	gr->SetWarn(mglWarnFile,"ReadMat");
+	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_rearrange(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"dn"))	d->Rearrange(mgl_int(a[1].v));
+	else if(d && !strcmp(k,"dnn"))	d->Rearrange(mgl_int(a[1].v), mgl_int(a[2].v));
+	else if(d && !strcmp(k,"dnnn"))	d->Rearrange(mgl_int(a[1].v), mgl_int(a[2].v), mgl_int(a[3].v));
+	else if(c && !strcmp(k,"dn"))	c->Rearrange(mgl_int(a[1].v));
+	else if(c && !strcmp(k,"dnn"))	c->Rearrange(mgl_int(a[1].v), mgl_int(a[2].v));
+	else if(c && !strcmp(k,"dnnn"))	c->Rearrange(mgl_int(a[1].v), mgl_int(a[2].v), mgl_int(a[3].v));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_refill(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && k[0]=='d' && k[1]=='d' && k[2]=='d')
+	{
+		if(k[3]==0)	gr->Refill(*d,*(a[1].d),*(a[2].d),-1,opt);
+		else if(!strcmp(k+3,"n"))	gr->Refill(*d,*(a[1].d),*(a[2].d),mgl_int(a[3].v),opt);
+		else if(!strcmp(k+3,"d"))	gr->Refill(*d,*(a[1].d),*(a[2].d),*(a[3].d),-1,opt);
+		else if(!strcmp(k+3,"dn"))	gr->Refill(*d,*(a[1].d),*(a[2].d),*(a[3].d),mgl_int(a[4].v),opt);
+		else if(!strcmp(k+3,"dd"))	gr->Refill(*d,*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),opt);
+		else res = 1;
+	}
+	else if(c && k[0]=='d' && k[1]=='d' && k[2]=='d')
+	{
+		if(k[3]==0)	gr->Refill(*c,*(a[1].d),*(a[2].d),-1,opt);
+		else if(!strcmp(k+3,"n"))	gr->Refill(*c,*(a[1].d),*(a[2].d),mgl_int(a[3].v),opt);
+		else if(!strcmp(k+3,"d"))	gr->Refill(*c,*(a[1].d),*(a[2].d),*(a[3].d),-1,opt);
+		else if(!strcmp(k+3,"dn"))	gr->Refill(*c,*(a[1].d),*(a[2].d),*(a[3].d),mgl_int(a[4].v),opt);
+		else if(!strcmp(k+3,"dd"))	gr->Refill(*c,*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),opt);
+		else res = 1;
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_resize(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"ddn"))	*d = mglData(true,mgl_data_resize_box(a[1].d, mgl_int(a[2].v),0,0, 0,1, 0,1, 0,1));
+	else if(d && !strcmp(k,"ddnn"))	*d = mglData(true,mgl_data_resize_box(a[1].d, mgl_int(a[2].v),mgl_int(a[3].v),0, 0,1, 0,1, 0,1));
+	else if(d && !strcmp(k,"ddnnn"))*d = mglData(true,mgl_data_resize_box(a[1].d, mgl_int(a[2].v),mgl_int(a[3].v),mgl_int(a[4].v), 0,1, 0,1, 0,1));
+	else if(c && !strcmp(k,"ddn"))	*c = mglDataC(true,mgl_datac_resize_box(a[1].d, mgl_int(a[2].v),0,0, 0,1, 0,1, 0,1));
+	else if(c && !strcmp(k,"ddnn"))	*c = mglDataC(true,mgl_datac_resize_box(a[1].d, mgl_int(a[2].v),mgl_int(a[3].v),0, 0,1, 0,1, 0,1));
+	else if(c && !strcmp(k,"ddnnn"))*c = mglDataC(true,mgl_datac_resize_box(a[1].d, mgl_int(a[2].v),mgl_int(a[3].v),mgl_int(a[4].v), 0,1, 0,1, 0,1));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_rkstep(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"ss") && gr->pr)
+		mgl_rk_step_w(gr->pr, a[0].w.c_str(), a[1].w.c_str(), 1);
+	else if(!strcmp(k,"ssn") && gr->pr)
+		mgl_rk_step_w(gr->pr, a[0].w.c_str(), a[1].w.c_str(), a[2].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_roll(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"dsn"))	d->Roll(a[1].s.c_str()[0], mgl_int(a[2].v));
+	else if(c && !strcmp(k,"dsn"))	c->Roll(a[1].s.c_str()[0], mgl_int(a[2].v));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_roots(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(!d)	return 1;
+	if(!strcmp(k,"dsds"))	*d = mglData(true,mgl_data_roots(a[1].s.c_str(), a[2].d, a[3].s[0]));
+	else if(!strcmp(k,"dsns"))	d->a[0] = mgl_find_root_txt(a[1].s.c_str(), a[2].v, a[3].s[0]);
+	else if(!strcmp(k,"dsd"))	*d = mglData(true,mgl_data_roots(a[1].s.c_str(), a[2].d, 'x'));
+	else if(!strcmp(k,"dsn"))	d->a[0] = mgl_find_root_txt(a[1].s.c_str(), a[2].v, 'x');
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_save(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"ds"))	a[0].d->Save(a[1].s.c_str());
+	else if(!strcmp(k,"ss"))
+	{
+		FILE *fp = fopen(a[1].s.c_str(),"a");
+		size_t pos;	std::string s=a[0].s;
+		while((pos=s.find("\\n"))!=std::string::npos)
+		{	s[pos]=' ';	s[pos+1]='\n';	}
+		while((pos=s.find("\b\b"))!=std::string::npos)	s.erase(pos,2);
+		fprintf(fp,"%s\n",s.c_str());	fclose(fp);
+	}
+	else if(!strcmp(k,"sss"))
+	{
+		FILE *fp = fopen(a[1].s.c_str(),a[2].s.c_str());
+		size_t pos;	std::string s=a[0].s;
+		while((pos=s.find("\\n"))!=std::string::npos)
+		{	s[pos]=' ';	s[pos+1]='\n';	}
+		while((pos=s.find("\b\b"))!=std::string::npos)	s.erase(pos,2);
+		fprintf(fp,"%s\n",s.c_str());	fclose(fp);
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_savehdf(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"dss"))	a[0].d->SaveHDF(a[1].s.c_str(), a[2].s.c_str());
+	else if(!strcmp(k,"dssn"))	a[0].d->SaveHDF(a[1].s.c_str(), a[2].s.c_str(),mgl_int(a[3].v));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_scanfile(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"dss"))
+	{
+		mglData *d = dynamic_cast<mglData *>(a[0].d);
+		if(!d)	return 1;
+		d->ScanFile(a[1].s.c_str(), a[2].s.c_str());
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_section(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d)
+	{
+		if(!strcmp(k,"dddsn"))
+			*d = mglData(true,mgl_data_section(a[1].d, a[2].d, a[3].s[0], a[4].v));
+		else if(!strcmp(k,"ddds"))
+			*d = mglData(true,mgl_data_section(a[1].d, a[2].d, a[3].s[0], NAN));
+		else if(!strcmp(k,"ddd"))
+			*d = mglData(true,mgl_data_section(a[1].d, a[2].d, 'y', NAN));
+		else if(!strcmp(k,"ddnsn"))
+			*d = mglData(true,mgl_data_section_val(a[1].d, mgl_int(a[2].v), a[3].s[0], a[4].v));
+		else if(!strcmp(k,"ddns"))
+			*d = mglData(true,mgl_data_section_val(a[1].d, mgl_int(a[2].v), a[3].s[0], NAN));
+		else if(!strcmp(k,"ddn"))
+			*d = mglData(true,mgl_data_section_val(a[1].d, mgl_int(a[2].v), 'y', NAN));
+		else res = 1;
+	}
+	else if(c)
+	{
+		if(!strcmp(k,"dddsn"))
+			*d = mglDataC(true,mgl_datac_section(a[1].d, a[2].d, a[3].s[0], a[4].v));
+		else if(!strcmp(k,"ddds"))
+			*d = mglDataC(true,mgl_datac_section(a[1].d, a[2].d, a[3].s[0], NAN));
+		else if(!strcmp(k,"ddd"))
+			*d = mglDataC(true,mgl_datac_section(a[1].d, a[2].d, 'y', NAN));
+		else if(!strcmp(k,"ddnsn"))
+			*d = mglDataC(true,mgl_datac_section_val(a[1].d, mgl_int(a[2].v), a[3].s[0], a[4].v));
+		else if(!strcmp(k,"ddns"))
+			*d = mglDataC(true,mgl_datac_section_val(a[1].d, mgl_int(a[2].v), a[3].s[0], NAN));
+		else if(!strcmp(k,"ddn"))
+			*d = mglDataC(true,mgl_datac_section_val(a[1].d, mgl_int(a[2].v), 'y', NAN));
+		else res = 1;
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_sew(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(!d)	return 1;
+	if(!strcmp(k,"d"))	d->Sew();
+	else if(!strcmp(k,"ds"))	d->Sew(a[1].s.c_str());
+	else if(!strcmp(k,"dsn"))	d->Sew(a[1].s.c_str(), a[2].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_sinfft(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"ds"))	d->SinFFT(a[1].s.c_str());
+	else if(d && !strcmp(k,"ds"))	c->SinFFT(a[1].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_smooth(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"d"))	d->Smooth();
+	else if(d && !strcmp(k,"ds"))	d->Smooth(a[1].s.c_str());
+	else if(c && !strcmp(k,"d"))	c->Smooth();
+	else if(c && !strcmp(k,"ds"))	c->Smooth(a[1].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_solve(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(!d)	return 1;
+	if(!strcmp(k,"ddns"))	*d = mglData(true,mgl_data_solve(a[1].d, a[2].v, a[3].s[0], 0, true));
+	else if(!strcmp(k,"ddnsn"))	*d = mglData(true,mgl_data_solve(a[1].d, a[2].v, a[3].s[0], 0, a[4].v!=0));
+	else if(!strcmp(k,"ddnsd"))	*d = mglData(true,mgl_data_solve(a[1].d, a[2].v, a[3].s[0], a[4].d, true));
+	else if(!strcmp(k,"ddnsdn"))*d = mglData(true,mgl_data_solve(a[1].d, a[2].v, a[3].s[0], a[4].d, a[5].v!=0));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_sort(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(d && !strcmp(k,"dn"))	d->Sort(a[1].v, -1);
+	else if(d && !strcmp(k,"dnn"))	d->Sort(a[1].v, a[2].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_squeeze(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"dn"))	d->Squeeze(mgl_int(a[1].v));
+	else if(d && !strcmp(k,"dnn"))	d->Squeeze(mgl_int(a[1].v), mgl_int(a[2].v));
+	else if(d && !strcmp(k,"dnnn"))	d->Squeeze(mgl_int(a[1].v), mgl_int(a[2].v),mgl_int(a[3].v));
+	else if(d && !strcmp(k,"dnnnn"))d->Squeeze(mgl_int(a[1].v), mgl_int(a[2].v),mgl_int(a[3].v), a[4].v);
+	else if(c && !strcmp(k,"dn"))	c->Squeeze(mgl_int(a[1].v));
+	else if(c && !strcmp(k,"dnn"))	c->Squeeze(mgl_int(a[1].v), mgl_int(a[2].v));
+	else if(c && !strcmp(k,"dnnn"))	c->Squeeze(mgl_int(a[1].v), mgl_int(a[2].v),mgl_int(a[3].v));
+	else if(c && !strcmp(k,"dnnnn"))c->Squeeze(mgl_int(a[1].v), mgl_int(a[2].v),mgl_int(a[3].v), a[4].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_stfad(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(!d)	return 1;
+	if(!strcmp(k,"dddn"))		*d = mglSTFA(*(a[1].d),*(a[2].d), mgl_int(a[3].v));
+	else if(!strcmp(k,"dddns"))	*d = mglSTFA(*(a[1].d),*(a[2].d), mgl_int(a[3].v), a[4].s.c_str()[0]);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_subdata(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d)
+	{
+		if(!strcmp(k,"ddn"))		*d = mglData(true,mgl_data_subdata(a[1].d, mgl_int(a[2].v), -1, -1));
+		else if(!strcmp(k,"ddnn"))	*d = mglData(true,mgl_data_subdata(a[1].d, mgl_int(a[2].v), mgl_int(a[3].v), -1));
+		else if(!strcmp(k,"ddnnn"))	*d = mglData(true,mgl_data_subdata(a[1].d, mgl_int(a[2].v), mgl_int(a[3].v), mgl_int(a[4].v)));
+		else if(!strcmp(k,"ddd"))	*d = mglData(true,mgl_data_subdata_ext(a[1].d, a[2].d, 0, 0));
+		else if(!strcmp(k,"dddd"))	*d = mglData(true,mgl_data_subdata_ext(a[1].d, a[2].d, a[3].d, 0));
+		else if(!strcmp(k,"ddddd"))	*d = mglData(true,mgl_data_subdata_ext(a[1].d, a[2].d, a[3].d, a[4].d));
+		else res = 1;
+	}
+	else if(c)
+	{
+		if(!strcmp(k,"ddn"))		*c = mglDataC(true,mgl_datac_subdata(a[1].d, mgl_int(a[2].v), -1, -1));
+		else if(!strcmp(k,"ddnn"))	*c = mglDataC(true,mgl_datac_subdata(a[1].d, mgl_int(a[2].v), mgl_int(a[3].v), -1));
+		else if(!strcmp(k,"ddnnn"))	*c = mglDataC(true,mgl_datac_subdata(a[1].d, mgl_int(a[2].v), mgl_int(a[3].v), mgl_int(a[4].v)));
+		else if(!strcmp(k,"ddd"))	*c = mglDataC(true,mgl_datac_subdata_ext(a[1].d, a[2].d, 0, 0));
+		else if(!strcmp(k,"dddd"))	*c = mglDataC(true,mgl_datac_subdata_ext(a[1].d, a[2].d, a[3].d, 0));
+		else if(!strcmp(k,"ddddd"))	*c = mglDataC(true,mgl_datac_subdata_ext(a[1].d, a[2].d, a[3].d, a[4].d));
+		else res = 1;
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_subto(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"dd"))		*d -= *(a[1].d);
+	else if(d && !strcmp(k,"dn"))	*d -= a[1].v;
+	else if(c && !strcmp(k,"dd"))	*c -= *(a[1].d);
+	else if(c && !strcmp(k,"dn"))	*c -= a[1].c;
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_sum(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"dds"))	*d = mglData(true,mgl_data_sum(a[1].d,a[2].s.c_str()));
+	else if(c && !strcmp(k,"dds"))	*c = mglDataC(true,mgl_datac_sum(a[1].d,a[2].s.c_str()));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_swap(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"ds"))	d->Swap(a[1].s.c_str());
+	else if(c && !strcmp(k,"ds"))	c->Swap(a[1].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_trace(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"dd"))	*d = mglData(true,mgl_data_trace(a[1].d));
+	else if(c && !strcmp(k,"dd"))	*c = mglDataC(true,mgl_datac_trace(a[1].d));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_transform(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(!strcmp(k,"dsdd") && d)	*d = mglTransform(*(a[2].d),*(a[3].d),a[1].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_transforma(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(!strcmp(k,"dsdd") && d)	*d = mglTransformA(*(a[2].d),*(a[3].d),a[1].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_transpose(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(d && !strcmp(k,"d"))	d->Transpose();
+	else if(d && !strcmp(k,"ds"))	d->Transpose(a[1].s.c_str());
+	else if(c && !strcmp(k,"d"))	c->Transpose();
+	else if(c && !strcmp(k,"ds"))	c->Transpose(a[1].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_triangulate(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	if(!d)	return 1;
+	if(!strcmp(k,"ddd"))		*d = mglTriangulation(*(a[1].d), *(a[2].d));
+	else if(!strcmp(k,"dddd"))	*d = mglTriangulation(*(a[1].d), *(a[2].d), *(a[3].d));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_tridmat(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(c && !strcmp(k,"ddddds"))
+		*c = mglTridMatC(*(a[1].d), *(a[2].d), *(a[3].d), *(a[4].d), a[5].s.c_str());
+	else if(d && !strcmp(k,"ddddds"))
+		*d = mglTridMat(*(a[1].d), *(a[2].d), *(a[3].d), *(a[4].d), a[5].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_var(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);	// TODO use mglDataV here?!
+	if(!d)	return 1;
+	if(!strcmp(k,"dnn"))
+	{	d->Create(mgl_int(a[1].v));	d->Fill(a[2].v, NAN);	}
+	else if(!strcmp(k,"dnnn"))
+	{	d->Create(mgl_int(a[1].v));	d->Fill(a[2].v, a[3].v);	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_wavelet(mglGraph *, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]=='d' && a[0].d->temp)	return 5;
+	mglData *d = dynamic_cast<mglData *>(a[0].d);
+	mglDataC *c = dynamic_cast<mglDataC *>(a[0].d);
+	if(!strcmp(k,"dsn") && d)	d->Wavelet(a[1].s.c_str(), mgl_int(a[2].v));
+	else if(!strcmp(k,"dsn") && c)	c->Wavelet(a[1].s.c_str(), mgl_int(a[2].v));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+mglCommand mgls_dat_cmd[] = {
+	{"addto",_("Add data or number"),"addto Var Dat|Var num", mgls_addto ,3},
+	{"apde",_("Solve PDE using advanced method (X-Y only)"),"apde Res 'ham' IniRe IniIm [dz k0]", mgls_apde ,4},
+	{"clean",_("Remove duplicate rows"),"clean Dat id", mgls_clean ,3},
+	{"column",_("Get data column filled by formula on column ids"),"column Res Dat 'eq'", mgls_column ,4},
+	{"combine",_("Direct multiplication of arrays"), "combine Res Adat Bdat", mgls_combine ,4},
+	{"copy",_("Copy data from another variable"),"copy Dat1 Dat2 ['eq']|ReDat ImDat Cdat|Dat val|Dat 'name'", mgls_copy ,4},
+	{"correl",_("Find correlation between data arrays"), "correl Res Adat Bdat 'dir'|Res Adat 'dir'", mgls_correl ,4},
+	{"cosfft",_("Cos-Fourier transform at some direction"),"cosfft Dat 'dir'", mgls_cosfft ,16},
+	{"crop",_("Crop edge of data"),"crop Dat n1 n2 'dir'|Dat 'how'", mgls_crop ,16},
+	{"cumsum",_("Cumulative summation along direction(s)"),"cumsum Dat 'dir'", mgls_cumsum ,16},
+	{"datagrid",_("Fill data by triangulated values"),"datagrid Var Xdat Ydat Zdat", mgls_datagrid ,3},
+	{"datas",_("Print list of data names in HDF file"),"datas 'fname'", mgls_datas ,3},
+	{"delete",_("Delete data or slice of data"),"delete Dat|'Dat'|Dat 'dir' [pos=0 num=1]", mgls_delete ,3},
+	{"detect",_("Detect curves for maximums of data array"), "detect Res Dat lvl dj [di min_len]", mgls_detect, 4},
+	{"diff",_("Numerically differentiate data"),"diff Var 'dir'|Var Dir Const1 [Const2]", mgls_diff ,16},
+	{"diff2",_("Numerically double differentiate data"),"diff2 Var 'dir'", mgls_diff2 ,16},
+	{"diffract",_("Step for pulse diffraction"),"diffract Res 'how' q", mgls_diffract ,16},
+	{"dilate",_("Dilate data larger val"),"dilate Dat [val step]", mgls_dilate ,3},
+	{"divto",_("Divide by data or number"),"divto Var Dat|Var num", mgls_divto ,3},
+	{"echo",_("Print content of the data"),"echo Dat", mgls_echo ,3},
+	{"envelop",_("Find envelop for the data"),"envelop Dat ['dir']", mgls_envelop ,16},
+	{"erode",_("Erode data larger val"),"erode Dat [val step]", mgls_erode ,3},
+	{"evaluate",_("Evaluate (interpolate) values of array Dat at points i=idat,j=jdat,k=kdat"),"evaluate Res Dat Idat [norm]|Res Dat Idat Jdat [norm]|Res Dat Idat Jdat Kdat [norm]", mgls_evaluate ,4},
+	{"export",_("Export data to PNG file"),"export Dat 'fname' 'sch' [v1 v2]", mgls_export ,3},
+	{"extend",_("Extend data array"),"extend Dat dim1 [dim2]", mgls_extend ,3},
+	{"fill",_("Fill data linearly in range [v1, v2]"),"fill Var v1 v2 ['dir']|Var 'eq' [Vdat Wdat]", mgls_fill ,3},
+	{"fillsample",_("Fill x-,k-samples for transforms"),"fillsample Var 'how'", mgls_fillsample ,3},
+	{"fit",_("Fit data to formula"),"fit Res A 'eq' 'var' [Ini]|Res X A 'eq' 'var' [Ini]|Res X Y A 'eq' 'var' [Ini]|Res X Y Z A 'eq' 'var' [Ini]", mgls_fit ,4},
+	{"fits",_("Fit data to formula"),"fits Res A S 'eq' 'var' [Ini]|Res X A S 'eq' 'var' [Ini]|Res X Y A S 'eq' 'var' [Ini]|Res X Y Z A S 'eq' 'var' [Ini]", mgls_fits ,4},
+	{"fourier",_("In-place Fourier transform"),"fourier ReDat ImDat 'dir'|Cmplx 'dir'", mgls_fourier , 16},
+	{"gspline",_("Fill data by global spline of Vdat"),"gspline Dat Xdat Vdat [sl]", mgls_gspline ,3},
+	{"hankel",_("Hankel transform at some direction"),"hankel Dat 'dir'", mgls_hankel ,16},
+	{"hist",_("Create histogram (distribution) of data values"),"hist Res Dat num v1 v2 [nsub]|Res Dat Wdat num v1 v2 [nsub]|Res Xdat Dat|Res Xdat Ydat Dat|Res Xdat Ydat Zdat Dat", mgls_hist ,4},
+	{"idset",_("Set column id for data"),"idset Dat 'ids'", mgls_idset ,3},
+	{"import",_("Import data from PNG file"),"import Dat 'fname' 'scheme' [v1 v2]", mgls_import ,4},
+	{"info",_("Print message or information about the data"),"info Dat|'message'|const", mgls_info ,3},
+	{"insert",_("Insert slice of data"),"insert Dat 'dir' [pos=0 num=1]", mgls_insert ,3},
+	{"integrate",_("Integrate data along direction(s)"),"integrate Dat 'dir'", mgls_integrate ,16},
+	{"jacobian",_("Get Jacobian"),"jacobian Res Xdat Ydat [Zdat]", mgls_jacobian ,4},
+	{"join",_("Join data arrays"),"join Dat Add1 ...", mgls_join ,3},
+	{"limit",_("Limit data to be inside [-v,v]"),"limit Dat v", mgls_limit ,16},
+	{"max",_("Find maximal value over direction"),"max Res Dat 'dir'", mgls_max ,4},
+	{"min",_("Find minimal value over direction"),"min Res Dat 'dir'", mgls_min ,4},
+	{"mirror",_("Mirror data at some direction"),"mirror Dat 'dir'", mgls_mirror ,16},
+	{"modify",_("Modify data values by formula"),"modify Dat 'eq' [num]|Dat 'eq' Vdat [Wdat]", mgls_modify ,3},
+	{"momentum",_("Get momentum along direction"),"momentum Res Dat 'how' ['dir']", mgls_momentum ,4},
+	{"multo",_("Multiply by data or number"),"multo Var Dat|Var num", mgls_multo ,3},
+	{"new",_("Create new data"),"new Dat nx ['eq']|Dat nx ny ['eq']|Dat nx ny nz ['eq']", mgls_new ,4},
+	{"norm",_("Normalize data"),"norm Dat v1 v2 [sym dim]", mgls_norm ,16},
+	{"normsl",_("Normalize data slice by slice"),"normsl Dat v1 v2 ['dir' keep sym] ", mgls_normsl ,16},
+	{"ode",_("Solve ODE"),"ode Res 'df' 'var' Ini [dt tmax]", mgls_ode ,4},
+	{"openhdf",_("Open all data arrays from HDF file"),"openhdf 'fname'", mgls_openhdf ,3},
+	{"pde",_("Solve PDE"),"pde Res 'ham' IniRe IniIm [dz k0]", mgls_pde ,4},
+	{"print",_("Immediately print the message"),"print 'message'|Dat|const", mgls_print ,3},
+	{"pulse",_("Get pulse properties"),"pulse Res Dat 'dir'", mgls_pulse ,4},
+	{"put",_("Put value (numeric or array) to given data element"),"put Dat val [i j k]|Dat Val [i j k]", mgls_put ,3},
+	{"putsfit",_("Print fitted formula"),"putsfit x y ['pre' 'font' size]|x y z ['pre' 'font' size]", mgls_putsfit ,15},
+	{"qo2d",_("Solve PDE in accompanied coordinates for 2d case"),"qo2d Res 'ham' IniRe IniIm Ray [r k0 Xout Yout]", mgls_qo2d ,4},
+	{"qo3d",_("Solve PDE in accompanied coordinates for 3d case"),"qo3d Res 'ham' IniRe IniIm Ray [r k0 Xout Yout Zout]", mgls_qo3d ,4},
+	{"ray",_("Solve Hamiltonian ODE (find GO ray or trajectory)"),"ray Res 'ham' x0 y0 z0 px0 py0 pz0 [dt=0.1 tmax=10]", mgls_ray ,4},
+	{"read",_("Read data from file"),"read Dat 'file' [nx ny nz]|ReDat ImDat 'file' [nx ny nz]", mgls_read ,4},
+	{"readall",_("Read and join data from several files"),"readall Dat 'templ' [slice]|Dat 'templ' from to [step slice]", mgls_readall ,4},
+	{"readhdf",_("Read data with name 'id' from HDF file"),"readhdf Dat 'file' 'id'", mgls_readhdf ,4},
+	{"readmat",_("Read data from file with sizes specified in first row"),"readmat Dat 'file' [dim]", mgls_readmat ,4},
+	{"rearrange",_("Rearrange data dimensions"),"rearrange Dat mx [my mz]", mgls_rearrange ,3},
+	{"refill",_("Fill data by interpolation of Vdat"),"refill Dat Xdat Vdat [sl]|Dat Xdat Ydat Vdat [sl]|Dat Xdat Ydat Zdat Vdat", mgls_refill ,3},
+	{"resize",_("Resize data array"),"resize Res Dat mx [my mz]", mgls_resize ,4},
+	{"rkstep",_("Perform Runge-Kutta step"),"rkstep 'Diff1;Diff2;...' 'Var1;Var2;...' [dt]", mgls_rkstep, 6},
+	{"roll",_("Roll data along direction(s)"),"roll Dat 'dir' num", mgls_roll ,16},
+	{"roots",_("Find roots using data as initial values"), "roots Res 'func' Ini ['var']|Res 'func' ini ['var']", mgls_roots ,4},
+	{"save",_("Save data to file"),"save Dat 'file'|'str' 'file' ['how']", mgls_save ,3},
+	{"savehdf",_("Save data to HDF5 file"),"savehdf Dat 'file' 'id' [rewrite]", mgls_savehdf ,3},
+	{"scanfile",_("Get formated data from file"),"scanfile Dat 'fname 'templ'", mgls_scanfile ,4},
+	{"section",_("Extract sub-array between values"),"section Res Dat id ['dir' val]|Res Dat Ids ['dir' val]", mgls_section ,4},
+	{"sew",_("Remove jump into the data, like phase jumps"),"sew Dat ['dir' da]", mgls_sew ,16},
+	{"sinfft",_("Sin-Fourier transform at some direction"),"sinfft Dat 'dir'", mgls_sinfft ,16},
+	{"smooth",_("Smooth data"),"smooth Dat ['how']", mgls_smooth ,16},
+	{"solve",_("Find root Dat[i,j,k]=val (inverse evaluate)"),"solve Res Dat val 'dir' [Idat norm]", mgls_solve ,4},
+	{"sort",_("Sort data by values in column"),"sort Dat idx [idy]", mgls_sort ,3},
+	{"squeeze",_("Squeeze data"),"squeeze Dat kx [ky kz smooth]", mgls_squeeze ,3},
+	{"stfad",_("Do STFA transform"),"stfad Res Real Imag dn ['dir']", mgls_stfad ,4},
+	{"subdata",_("Extract sub-array"),"subdata Res Dat ix [iy iz]|Res Dat Xdat [Ydat Zdat]", mgls_subdata ,4},
+	{"subto",_("Subtract data or number"),"subto Var Dat|Var num", mgls_subto ,3},
+	{"sum",_("Find summation over direction"),"sum Res Dat 'dir'", mgls_sum ,4},
+	{"swap",_("Swap data (useful after Fourier transform)"),"swap Dat 'dir'", mgls_swap ,16},
+	{"trace",_("Get trace of array"),"trace Res Dat", mgls_trace ,4},
+	{"transform",_("Do integral transform of data"),"transform Res 'how' Rdat Idat", mgls_transform ,4},
+	{"transforma",_("Do integral transform of data"),"transforma Res 'how' Adat Pdat", mgls_transforma ,4},
+	{"transpose",_("Transpose data array"),"transpose Dat ['dir']", mgls_transpose ,16},
+	{"triangulate",_("Find triangles of randomly placed points"),"triangulate Res Xdat Ydat|Res Xdat Ydat Zdat", mgls_triangulate ,4},
+	{"tridmat",_("Solve tridiagonal matrix"),"tridmat Res A B C D 'how'", mgls_tridmat ,4},
+	{"var",_("Create new 1D data and fill it in range"),"var Dat nx x1 [x2]", mgls_var ,4},
+	{"wavelet",_("Wavelet transform at some direction"),"wavelet Dat 'dir' k", mgls_wavelet ,16},
+{"","","",NULL,0}};
+//-----------------------------------------------------------------------------
diff --git a/src/exec_gr.cpp b/src/exec_gr.cpp
new file mode 100644
index 0000000..2d200e9
--- /dev/null
+++ b/src/exec_gr.cpp
@@ -0,0 +1,1106 @@
+/***************************************************************************
+ * exec_1d.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifdef WIN32
+#include <io.h>
+#include <direct.h>
+#else
+#include <unistd.h>
+#endif
+
+#include "mgl2/base.h"
+#include "mgl2/parser.h"
+#pragma GCC diagnostic ignored "-Wmisleading-indentation"
+wchar_t *mgl_str_copy(const char *s);
+//-----------------------------------------------------------------------------
+//	1D
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_area(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Area(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->Area(*(a[0].d),a[1].s.c_str(),opt);
+	else if(!strcmp(k,"dd"))	gr->Area(*(a[0].d),*(a[1].d),"",opt);
+	else if(!strcmp(k,"dds"))	gr->Area(*(a[0].d),*(a[1].d),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->Area(*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"ddds"))	gr->Area(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_axial(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Axial(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->Axial(*(a[0].d),a[1].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->Axial(*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"ddds"))	gr->Axial(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_bars(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Bars(*(a[0].d), "",opt);
+	else if(!strcmp(k,"ds"))	gr->Bars(*(a[0].d), a[1].s.c_str(),opt);
+	else if(!strcmp(k,"dd"))	gr->Bars(*(a[0].d), *(a[1].d), "",opt);
+	else if(!strcmp(k,"dds"))	gr->Bars(*(a[0].d), *(a[1].d), a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ddd")) 	gr->Bars(*(a[0].d), *(a[1].d), *(a[2].d), "",opt);
+	else if(!strcmp(k,"ddds"))	gr->Bars(*(a[0].d), *(a[1].d), *(a[2].d), a[3].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_barh(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Barh(*(a[0].d), "",opt);
+	else if(!strcmp(k,"ds"))	gr->Barh(*(a[0].d), a[1].s.c_str(),opt);
+	else if(!strcmp(k,"dd"))	gr->Barh(*(a[0].d), *(a[1].d), "",opt);
+	else if(!strcmp(k,"dds"))	gr->Barh(*(a[0].d), *(a[1].d), a[2].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_bifurcation(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"nd"))	gr->Bifurcation(a[0].v,*(a[1].d),"",opt);
+	else if(!strcmp(k,"nds"))	gr->Bifurcation(a[0].v,*(a[1].d),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ns"))	gr->Bifurcation(a[0].v,a[1].s.c_str(),"",opt);
+	else if(!strcmp(k,"nss"))	gr->Bifurcation(a[0].v,a[1].s.c_str(),a[2].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_boxplot(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->BoxPlot(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->BoxPlot(*(a[0].d),a[1].s.c_str(),opt);
+	else if(!strcmp(k,"dd"))	gr->BoxPlot(*(a[0].d),*(a[1].d),"",opt);
+	else if(!strcmp(k,"dds"))	gr->BoxPlot(*(a[0].d),*(a[1].d),a[2].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_candle(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Candle(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->Candle(*(a[0].d),a[1].s.c_str(),opt);
+	else if(!strcmp(k,"dd"))	gr->Candle(*(a[0].d),*(a[1].d),"",opt);
+	else if(!strcmp(k,"dds"))	gr->Candle(*(a[0].d),*(a[1].d),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->Candle(*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"ddds"))	gr->Candle(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),opt);
+	else if(!strcmp(k,"dddd"))	gr->Candle(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),"",opt);
+	else if(!strcmp(k,"dddds"))	gr->Candle(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),opt);
+	else if(!strcmp(k,"ddddd"))	gr->Candle(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),"",opt);
+	else if(!strcmp(k,"ddddds"))gr->Candle(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),a[5].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_chart(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Chart(*(a[0].d), "",opt);
+	else if(!strcmp(k,"ds"))	gr->Chart(*(a[0].d), a[1].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_cones(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Cones(*(a[0].d), "",opt);
+	else if(!strcmp(k,"ds"))	gr->Cones(*(a[0].d), a[1].s.c_str(),opt);
+	else if(!strcmp(k,"dd"))	gr->Cones(*(a[0].d), *(a[1].d), "",opt);
+	else if(!strcmp(k,"dds"))	gr->Cones(*(a[0].d), *(a[1].d), a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ddd")) 	gr->Cones(*(a[0].d), *(a[1].d), *(a[2].d), "",opt);
+	else if(!strcmp(k,"ddds"))	gr->Cones(*(a[0].d), *(a[1].d), *(a[2].d), a[3].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_error(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"dd"))	gr->Error(*(a[0].d),*(a[1].d), "",opt);
+	else if(!strcmp(k,"dds"))	gr->Error(*(a[0].d),*(a[1].d), a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->Error(*(a[0].d),*(a[1].d),*(a[2].d), "",opt);
+	else if(!strcmp(k,"ddds"))	gr->Error(*(a[0].d),*(a[1].d),*(a[2].d), a[3].s.c_str(),opt);
+	else if(!strcmp(k,"dddd"))	gr->Error(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d), "",opt);
+	else if(!strcmp(k,"dddds"))	gr->Error(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d), a[4].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_iris(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"ds"))	gr->Iris(*(a[0].d),a[1].w.c_str(),"",opt);
+	else if(!strcmp(k,"dss"))	gr->Iris(*(a[0].d),a[1].w.c_str(),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"dds"))	gr->Iris(*(a[0].d),*(a[1].d),a[2].w.c_str(),"",opt);
+	else if(!strcmp(k,"ddss"))	gr->Iris(*(a[0].d),*(a[1].d),a[2].w.c_str(),a[3].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_label(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"ds"))	gr->Label(*(a[0].d), a[1].w.c_str(), "",opt);
+	else if(!strcmp(k,"dss"))	gr->Label(*(a[0].d), a[1].w.c_str(), a[2].s.c_str(),opt);
+	else if(!strcmp(k,"dds"))	gr->Label(*(a[0].d), *(a[1].d), a[2].w.c_str(), "",opt);
+	else if(!strcmp(k,"ddss"))	gr->Label(*(a[0].d), *(a[1].d), a[2].w.c_str(), a[3].s.c_str(),opt);
+	else if(!strcmp(k,"ddds"))	gr->Label(*(a[0].d), *(a[1].d), *(a[2].d), a[3].w.c_str(), "",opt);
+	else if(!strcmp(k,"dddss"))	gr->Label(*(a[0].d), *(a[1].d), *(a[2].d), a[3].w.c_str(), a[4].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_lamerey(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"nd"))	gr->Lamerey(a[0].v,*(a[1].d),"",opt);
+	else if(!strcmp(k,"nds"))	gr->Lamerey(a[0].v,*(a[1].d),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ns"))	gr->Lamerey(a[0].v,a[1].s.c_str(),"",opt);
+	else if(!strcmp(k,"nss"))	gr->Lamerey(a[0].v,a[1].s.c_str(),a[2].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_mark(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"dd"))	gr->Mark(*(a[0].d), *(a[1].d), "",opt);
+	else if(!strcmp(k,"dds"))	gr->Mark(*(a[0].d), *(a[1].d), a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ddd")) 	gr->Mark(*(a[0].d), *(a[1].d), *(a[2].d), "",opt);
+	else if(!strcmp(k,"ddds"))	gr->Mark(*(a[0].d), *(a[1].d), *(a[2].d), a[3].s.c_str(),opt);
+	else if(!strcmp(k,"dddd")) 	gr->Mark(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d), "",opt);
+	else if(!strcmp(k,"dddds"))	gr->Mark(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d), a[4].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_ohlc(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"dddd"))	gr->OHLC(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d), "",opt);
+	else if(!strcmp(k,"dddds"))	gr->OHLC(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d), a[4].s.c_str(),opt);
+	else if(!strcmp(k,"ddddd"))	gr->OHLC(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d), "",opt);
+	else if(!strcmp(k,"ddddds"))	gr->OHLC(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d), a[5].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_plot(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Plot(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->Plot(*(a[0].d),a[1].s.c_str(),opt);
+	else if(!strcmp(k,"dd"))	gr->Plot(*(a[0].d),*(a[1].d),"",opt);
+	else if(!strcmp(k,"dds"))	gr->Plot(*(a[0].d),*(a[1].d),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->Plot(*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"ddds"))	gr->Plot(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_radar(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Radar(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->Radar(*(a[0].d),a[1].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_region(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"dd"))		gr->Region(*(a[0].d),*(a[1].d),"",opt);
+	else if(!strcmp(k,"dds"))	gr->Region(*(a[0].d),*(a[1].d),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->Region(*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"ddds"))	gr->Region(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),opt);
+	else if(!strcmp(k,"dddd"))	gr->Region(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),"",opt);
+	else if(!strcmp(k,"dddds"))	gr->Region(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),opt);
+	else if(!strcmp(k,"dddddd"))	gr->Region(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d),"",opt);
+	else if(!strcmp(k,"dddddds"))	gr->Region(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d),a[6].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_stem(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Stem(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->Stem(*(a[0].d),a[1].s.c_str(),opt);
+	else if(!strcmp(k,"dd"))	gr->Stem(*(a[0].d),*(a[1].d),"",opt);
+	else if(!strcmp(k,"dds"))	gr->Stem(*(a[0].d),*(a[1].d),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->Stem(*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"ddds"))	gr->Stem(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_step(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Step(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->Step(*(a[0].d),a[1].s.c_str(),opt);
+	else if(!strcmp(k,"dd"))	gr->Step(*(a[0].d),*(a[1].d),"",opt);
+	else if(!strcmp(k,"dds"))	gr->Step(*(a[0].d),*(a[1].d),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->Step(*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"ddds"))	gr->Step(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_table(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Table(*(a[0].d), L"", "#|",opt);
+	else if(!strcmp(k,"ds"))	gr->Table(*(a[0].d), a[1].w.c_str(), "#|",opt);
+	else if(!strcmp(k,"dss"))	gr->Table(*(a[0].d), a[1].w.c_str(), a[2].s.c_str(),opt);
+	else if(!strcmp(k,"nnd"))	gr->Table(a[0].v, a[1].v, *(a[2].d), L"", "#|",opt);
+	else if(!strcmp(k,"nnds"))	gr->Table(a[0].v, a[1].v, *(a[2].d), a[3].w.c_str(), "#|",opt);
+	else if(!strcmp(k,"nndss"))	gr->Table(a[0].v, a[1].v, *(a[2].d), a[3].w.c_str(), a[4].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_tape(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Tape(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->Tape(*(a[0].d),a[1].s.c_str(),opt);
+	else if(!strcmp(k,"dd"))	gr->Tape(*(a[0].d),*(a[1].d),"",opt);
+	else if(!strcmp(k,"dds"))	gr->Tape(*(a[0].d),*(a[1].d),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->Tape(*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"ddds"))	gr->Tape(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_tens(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"dd"))	gr->Tens(*(a[0].d),*(a[1].d), "",opt);
+	else if(!strcmp(k,"dds"))	gr->Tens(*(a[0].d),*(a[1].d), a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->Tens(*(a[0].d),*(a[1].d),*(a[2].d), "",opt);
+	else if(!strcmp(k,"ddds"))	gr->Tens(*(a[0].d),*(a[1].d),*(a[2].d), a[3].s.c_str(),opt);
+	else if(!strcmp(k,"dddd")) 	gr->Tens(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d), "",opt);
+	else if(!strcmp(k,"dddds"))	gr->Tens(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d), a[4].s.c_str(),opt);
+	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_textmark(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"ds"))	gr->TextMark(*(a[0].d),a[1].w.c_str(),"",opt);
+	else if(!strcmp(k,"dss"))	gr->TextMark(*(a[0].d),a[1].w.c_str(),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"dds"))	gr->TextMark(*(a[0].d),*(a[1].d),a[2].w.c_str(),"",opt);
+	else if(!strcmp(k,"ddss"))	gr->TextMark(*(a[0].d),*(a[1].d),a[2].w.c_str(),a[3].s.c_str(),opt);
+	else if(!strcmp(k,"ddds"))	gr->TextMark(*(a[0].d),*(a[1].d),*(a[2].d),a[3].w.c_str(),"",opt);
+	else if(!strcmp(k,"dddss"))	gr->TextMark(*(a[0].d),*(a[1].d),*(a[2].d),a[3].w.c_str(),a[4].s.c_str(),opt);
+	else if(!strcmp(k,"dddds"))	gr->TextMark(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].w.c_str(),"",opt);
+	else if(!strcmp(k,"ddddss"))gr->TextMark(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].w.c_str(),a[5].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_torus(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"dd"))	gr->Torus(*(a[0].d),*(a[1].d),"",opt);
+	else if(!strcmp(k,"dds"))	gr->Torus(*(a[0].d),*(a[1].d),a[2].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_tube(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"dn"))
+		gr->Tube(*(a[0].d),a[1].v,"",opt);
+	else if(!strcmp(k,"dns"))
+		gr->Tube(*(a[0].d),a[1].v,a[2].s.c_str(),opt);
+	else if(!strcmp(k,"dd"))
+		gr->Tube(*(a[0].d),*(a[1].d),"",opt);
+	else if(!strcmp(k,"dds"))
+		gr->Tube(*(a[0].d),*(a[1].d),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ddn"))
+		gr->Tube(*(a[0].d),*(a[1].d),a[2].v,"",opt);
+	else if(!strcmp(k,"ddns"))
+		gr->Tube(*(a[0].d),*(a[1].d),a[2].v,a[3].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))
+		gr->Tube(*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"ddds"))
+		gr->Tube(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),opt);
+	else if(!strcmp(k,"dddn"))
+		gr->Tube(*(a[0].d),*(a[1].d),*(a[2].d),a[3].v,"",opt);
+	else if(!strcmp(k,"dddns"))
+		gr->Tube(*(a[0].d),*(a[1].d),*(a[2].d),a[3].v,a[4].s.c_str(),opt);
+	else if(!strcmp(k,"dddd"))
+		gr->Tube(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),"",opt);
+	else if(!strcmp(k,"dddds"))
+		gr->Tube(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+//	2D
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_belt(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Belt(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->Belt(*(a[0].d),a[1].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->Belt(*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"ddds"))	gr->Belt(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_boxs(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Boxs(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->Boxs(*(a[0].d),a[1].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->Boxs(*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"ddds"))	gr->Boxs(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_cont(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Cont(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->Cont(*(a[0].d),a[1].s.c_str(),opt);
+	else if(!strcmp(k,"dd"))	gr->Cont(*(a[0].d), *(a[1].d), "",opt);
+	else if(!strcmp(k,"dds"))	gr->Cont(*(a[0].d), *(a[1].d), a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->Cont(*(a[0].d), *(a[1].d), *(a[2].d), "",opt);
+	else if(!strcmp(k,"ddds"))	gr->Cont(*(a[0].d), *(a[1].d), *(a[2].d), a[3].s.c_str(),opt);
+	else if(!strcmp(k,"dddd"))	gr->Cont(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), "",opt);
+	else if(!strcmp(k,"dddds"))	gr->Cont(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), a[4].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_contd(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->ContD(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->ContD(*(a[0].d),a[1].s.c_str(),opt);
+	else if(!strcmp(k,"dd"))	gr->ContD(*(a[0].d), *(a[1].d), "",opt);
+	else if(!strcmp(k,"dds"))	gr->ContD(*(a[0].d), *(a[1].d), a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->ContD(*(a[0].d), *(a[1].d), *(a[2].d), "",opt);
+	else if(!strcmp(k,"ddds"))	gr->ContD(*(a[0].d), *(a[1].d), *(a[2].d), a[3].s.c_str(),opt);
+	else if(!strcmp(k,"dddd"))	gr->ContD(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), "",opt);
+	else if(!strcmp(k,"dddds"))	gr->ContD(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), a[4].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_contf(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->ContF(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->ContF(*(a[0].d),a[1].s.c_str(),opt);
+	else if(!strcmp(k,"dd"))	gr->ContF(*(a[0].d), *(a[1].d), "",opt);
+	else if(!strcmp(k,"dds"))	gr->ContF(*(a[0].d), *(a[1].d), a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->ContF(*(a[0].d), *(a[1].d), *(a[2].d), "",opt);
+	else if(!strcmp(k,"ddds"))	gr->ContF(*(a[0].d), *(a[1].d), *(a[2].d), a[3].s.c_str(),opt);
+	else if(!strcmp(k,"dddd"))	gr->ContF(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), "",opt);
+	else if(!strcmp(k,"dddds"))	gr->ContF(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), a[4].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_contp(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"dddd"))	gr->ContP(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), "",opt);
+	else if(!strcmp(k,"dddds"))	gr->ContP(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), a[4].s.c_str(),opt);
+	else if(!strcmp(k,"ddddd"))	gr->ContP(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), *(a[4].d), "",opt);
+	else if(!strcmp(k,"ddddds"))	gr->ContP(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), *(a[4].d), a[5].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_contv(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->ContV(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->ContV(*(a[0].d),a[1].s.c_str(),opt);
+	else if(!strcmp(k,"dd"))	gr->ContV(*(a[0].d), *(a[1].d), "",opt);
+	else if(!strcmp(k,"dds"))	gr->ContV(*(a[0].d), *(a[1].d), a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->ContV(*(a[0].d), *(a[1].d), *(a[2].d), "",opt);
+	else if(!strcmp(k,"ddds"))	gr->ContV(*(a[0].d), *(a[1].d), *(a[2].d), a[3].s.c_str(),opt);
+	else if(!strcmp(k,"dddd"))	gr->ContV(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), "",opt);
+	else if(!strcmp(k,"dddds"))	gr->ContV(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), a[4].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_dens(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Dens(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->Dens(*(a[0].d),a[1].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->Dens(*(a[0].d), *(a[1].d), *(a[2].d), "",opt);
+	else if(!strcmp(k,"ddds"))	gr->Dens(*(a[0].d), *(a[1].d), *(a[2].d), a[3].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_fall(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Fall(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->Fall(*(a[0].d),a[1].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->Fall(*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"ddds"))	gr->Fall(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_grid2(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Grid(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->Grid(*(a[0].d),a[1].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->Grid(*(a[0].d), *(a[1].d), *(a[2].d), "",opt);
+	else if(!strcmp(k,"ddds"))	gr->Grid(*(a[0].d), *(a[1].d), *(a[2].d), a[3].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_map(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"dd"))	gr->Map(*(a[0].d),*(a[1].d),"",opt);
+	else if(!strcmp(k,"dds"))	gr->Map(*(a[0].d),*(a[1].d),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"dddd"))	gr->Map(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),"",opt);
+	else if(!strcmp(k,"dddds"))	gr->Map(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_mesh(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Mesh(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->Mesh(*(a[0].d),a[1].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->Mesh(*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"ddds"))	gr->Mesh(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_pmap(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"dd"))	gr->Pmap(*(a[0].d), *(a[1].d), "",opt);
+	else if(!strcmp(k,"dds"))	gr->Pmap(*(a[0].d), *(a[1].d), a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ddd")) 	gr->Pmap(*(a[0].d), *(a[1].d), *(a[2].d), "",opt);
+	else if(!strcmp(k,"ddds"))	gr->Pmap(*(a[0].d), *(a[1].d), *(a[2].d), a[3].s.c_str(),opt);
+	else if(!strcmp(k,"dddd")) 	gr->Pmap(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d), "",opt);
+	else if(!strcmp(k,"dddds"))	gr->Pmap(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d), a[4].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_stfa(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"ddn"))
+		gr->STFA(*(a[0].d),*(a[1].d), mgl_int(a[2].v), "",opt);
+	else if(!strcmp(k,"ddns"))
+		gr->STFA(*(a[0].d),*(a[1].d), mgl_int(a[2].v), a[3].s.c_str(),opt);
+	else if(!strcmp(k,"ddddn"))
+		gr->STFA(*(a[0].d),*(a[1].d), *(a[2].d),*(a[3].d), mgl_int(a[4].v), "",opt);
+	else if(!strcmp(k,"ddddns"))
+		gr->STFA(*(a[0].d),*(a[1].d), *(a[2].d),*(a[3].d), mgl_int(a[4].v), a[5].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_surf(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Surf(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->Surf(*(a[0].d),a[1].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->Surf(*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"ddds"))	gr->Surf(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_surfc(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"dd"))	gr->SurfC(*(a[0].d),*(a[1].d),"",opt);
+	else if(!strcmp(k,"dds"))	gr->SurfC(*(a[0].d),*(a[1].d),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"dddd"))	gr->SurfC(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),"",opt);
+	else if(!strcmp(k,"dddds"))	gr->SurfC(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_surfa(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"dd"))	gr->SurfA(*(a[0].d),*(a[1].d),"",opt);
+	else if(!strcmp(k,"dds"))	gr->SurfA(*(a[0].d),*(a[1].d),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"dddd"))	gr->SurfA(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),"",opt);
+	else if(!strcmp(k,"dddds"))	gr->SurfA(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_surfca(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"ddd"))	gr->SurfCA(*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"ddds"))	gr->SurfCA(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),opt);
+	else if(!strcmp(k,"ddddd"))	gr->SurfCA(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),"",opt);
+	else if(!strcmp(k,"ddddds"))gr->SurfCA(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),a[5].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_tile(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Tile(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->Tile(*(a[0].d),a[1].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->Tile(*(a[0].d), *(a[1].d), *(a[2].d), "",opt);
+	else if(!strcmp(k,"ddds"))	gr->Tile(*(a[0].d), *(a[1].d), *(a[2].d), a[3].s.c_str(),opt);
+	else if(!strcmp(k,"dddd"))	gr->Tile(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), "",opt);
+	else if(!strcmp(k,"dddds"))	gr->Tile(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), a[4].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_tiles(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"dd"))	gr->TileS(*(a[0].d),*(a[1].d),"",opt);
+	else if(!strcmp(k,"dds"))	gr->TileS(*(a[0].d),*(a[1].d),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"dddd"))	gr->TileS(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),"",opt);
+	else if(!strcmp(k,"dddds"))	gr->TileS(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),opt);
+	else if(!strcmp(k,"ddddd"))	gr->TileS(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),"",opt);
+	else if(!strcmp(k,"ddddds"))	gr->TileS(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),a[5].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_triplot(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"ddd"))	gr->TriPlot(*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"ddds"))	gr->TriPlot(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),opt);
+	else if(!strcmp(k,"dddd"))	gr->TriPlot(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),"",opt);
+	else if(!strcmp(k,"dddds"))	gr->TriPlot(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),opt);
+	else if(!strcmp(k,"ddddd"))	gr->TriPlot(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),"",opt);
+	else if(!strcmp(k,"ddddds"))gr->TriPlot(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),a[5].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_quadplot(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"ddd"))	gr->QuadPlot(*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"ddds"))	gr->QuadPlot(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),opt);
+	else if(!strcmp(k,"dddd"))	gr->QuadPlot(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),"",opt);
+	else if(!strcmp(k,"dddds"))	gr->QuadPlot(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),opt);
+	else if(!strcmp(k,"ddddd"))	gr->QuadPlot(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),"",opt);
+	else if(!strcmp(k,"ddddds"))gr->QuadPlot(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),a[5].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_tricont(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"dddd"))
+		gr->TriCont(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),"",opt);
+	else if(!strcmp(k,"dddds"))
+		gr->TriCont(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),opt);
+	else if(!strcmp(k,"ddddd"))
+		gr->TriContV(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),"",opt);
+	else if(!strcmp(k,"ddddds"))
+		gr->TriContV(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),a[5].s.c_str(),opt);
+	else if(!strcmp(k,"dddddd"))
+		gr->TriCont(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d),"",opt);
+	else if(!strcmp(k,"dddddds"))
+		gr->TriCont(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d),a[6].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_tricontv(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"dddd"))
+		gr->TriContVt(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),"",opt);
+	else if(!strcmp(k,"dddds"))
+		gr->TriContVt(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),opt);
+	else if(!strcmp(k,"ddddd"))
+		gr->TriContVt(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),"",opt);
+	else if(!strcmp(k,"ddddds"))
+		gr->TriContVt(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),a[5].s.c_str(),opt);
+	else if(!strcmp(k,"dddddd"))
+		gr->TriContVt(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d),"",opt);
+	else if(!strcmp(k,"dddddds"))
+		gr->TriContVt(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d),a[6].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+//	3D
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_beam(mglGraph *gr, long , mglArg *a, const char *k, const char *)	// NOTE beam can be made obsolete ???
+{
+	int res=0;
+	if(!strcmp(k,"ddddn"))
+		gr->Beam(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].v,"",0, 3);
+	else if(!strcmp(k,"ddddns"))
+		gr->Beam(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].v,a[5].s.c_str(),0, 3);
+	else if(!strcmp(k,"ddddnsn"))
+		gr->Beam(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].v,a[5].s.c_str(),mgl_int(a[6].v), 3);
+	else if(!strcmp(k,"ddddnsnn"))
+		gr->Beam(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].v,a[5].s.c_str(),mgl_int(a[6].v), mgl_int(a[7].v));
+	else if(!strcmp(k,"nddddn"))
+		gr->Beam(a[0].v,*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),a[5].v,"",0);
+	else if(!strcmp(k,"nddddns"))
+		gr->Beam(a[0].v,*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),a[5].v,a[6].s.c_str(),0);
+	else if(!strcmp(k,"nddddnsn"))
+		gr->Beam(a[0].v,*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),a[5].v,a[6].s.c_str(),mgl_int(a[7].v));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_cloud(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Cloud(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->Cloud(*(a[0].d),a[1].s.c_str(),opt);
+	else if(!strcmp(k,"dddd"))	gr->Cloud(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),"",opt);
+	else if(!strcmp(k,"dddds"))	gr->Cloud(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_cont3(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Cont3(*(a[0].d), "", -1,opt);
+	else if(!strcmp(k,"ds"))	gr->Cont3(*(a[0].d), a[1].s.c_str(), -1,opt);
+	else if(!strcmp(k,"dsn"))	gr->Cont3(*(a[0].d), a[1].s.c_str(), mgl_int(a[2].v),opt);
+	else if(!strcmp(k,"dd"))	gr->Cont3(*(a[0].d), *(a[1].d), "", -1,opt);
+	else if(!strcmp(k,"dds"))	gr->Cont3(*(a[0].d), *(a[1].d), a[2].s.c_str(),-1,opt);
+	else if(!strcmp(k,"ddsn"))	gr->Cont3(*(a[0].d), *(a[1].d), a[2].s.c_str(),mgl_int(a[3].v),opt);
+	else if(!strcmp(k,"dddd"))	gr->Cont3(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), "", -1,opt);
+	else if(!strcmp(k,"dddds"))	gr->Cont3(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), a[4].s.c_str(),-1,opt);
+	else if(!strcmp(k,"ddddsn"))	gr->Cont3(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), a[4].s.c_str(),mgl_int(a[5].v),opt);
+	else if(!strcmp(k,"ddddd"))	gr->Cont3(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), *(a[4].d), "", -1,opt);
+	else if(!strcmp(k,"ddddds"))	gr->Cont3(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), *(a[4].d), a[5].s.c_str(),-1,opt);
+	else if(!strcmp(k,"dddddsn"))gr->Cont3(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), *(a[4].d), a[5].s.c_str(),mgl_int(a[6].v),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_contf3(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->ContF3(*(a[0].d), "", -1,opt);
+	else if(!strcmp(k,"ds"))	gr->ContF3(*(a[0].d), a[1].s.c_str(), -1,opt);
+	else if(!strcmp(k,"dsn"))	gr->ContF3(*(a[0].d), a[1].s.c_str(), mgl_int(a[2].v),opt);
+	else if(!strcmp(k,"dd"))	gr->ContF3(*(a[0].d), *(a[1].d), "", -1,opt);
+	else if(!strcmp(k,"dds"))	gr->ContF3(*(a[0].d), *(a[1].d), a[2].s.c_str(),-1,opt);
+	else if(!strcmp(k,"ddsn"))	gr->ContF3(*(a[0].d), *(a[1].d), a[2].s.c_str(),mgl_int(a[3].v),opt);
+	else if(!strcmp(k,"dddd"))	gr->ContF3(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), "", -1,opt);
+	else if(!strcmp(k,"dddds"))	gr->ContF3(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), a[4].s.c_str(),-1,opt);
+	else if(!strcmp(k,"ddddsn"))	gr->ContF3(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), a[4].s.c_str(),mgl_int(a[5].v),opt);
+	else if(!strcmp(k,"ddddd"))	gr->ContF3(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), *(a[4].d), "", -1,opt);
+	else if(!strcmp(k,"ddddds"))	gr->ContF3(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), *(a[4].d), a[5].s.c_str(),-1,opt);
+	else if(!strcmp(k,"dddddsn"))gr->ContF3(*(a[0].d), *(a[1].d), *(a[2].d), *(a[3].d), *(a[4].d), a[5].s.c_str(),mgl_int(a[6].v),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_contx(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->ContX(*(a[0].d),"",NAN,opt);
+	else if(!strcmp(k,"ds"))	gr->ContX(*(a[0].d),a[1].s.c_str(),NAN,opt);
+	else if(!strcmp(k,"dsn"))	gr->ContX(*(a[0].d),a[1].s.c_str(),a[2].v,opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_contfx(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->ContFX(*(a[0].d),"",NAN,opt);
+	else if(!strcmp(k,"ds"))	gr->ContFX(*(a[0].d),a[1].s.c_str(),NAN,opt);
+	else if(!strcmp(k,"dsn"))	gr->ContFX(*(a[0].d),a[1].s.c_str(),a[2].v,opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_conty(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->ContY(*(a[0].d),"",NAN,opt);
+	else if(!strcmp(k,"ds"))	gr->ContY(*(a[0].d),a[1].s.c_str(),NAN,opt);
+	else if(!strcmp(k,"dsn"))	gr->ContY(*(a[0].d),a[1].s.c_str(),a[2].v,opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_contfy(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->ContFY(*(a[0].d),"",NAN,opt);
+	else if(!strcmp(k,"ds"))	gr->ContFY(*(a[0].d),a[1].s.c_str(),NAN,opt);
+	else if(!strcmp(k,"dsn"))	gr->ContFY(*(a[0].d),a[1].s.c_str(),a[2].v,opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_contz(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->ContZ(*(a[0].d),"",NAN,opt);
+	else if(!strcmp(k,"ds"))	gr->ContZ(*(a[0].d),a[1].s.c_str(),NAN,opt);
+	else if(!strcmp(k,"dsn"))	gr->ContZ(*(a[0].d),a[1].s.c_str(),a[2].v,opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_contfz(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->ContFZ(*(a[0].d),"",NAN,opt);
+	else if(!strcmp(k,"ds"))	gr->ContFZ(*(a[0].d),a[1].s.c_str(),NAN,opt);
+	else if(!strcmp(k,"dsn"))	gr->ContFZ(*(a[0].d),a[1].s.c_str(),a[2].v,opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_crust(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"ddd"))	gr->Crust(*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"ddds"))	gr->Crust(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_dens3(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Dens3(*(a[0].d),"",-1,opt);
+	else if(!strcmp(k,"ds"))	gr->Dens3(*(a[0].d),a[1].s.c_str(),-1,opt);
+	else if(!strcmp(k,"dsn"))	gr->Dens3(*(a[0].d),a[1].s.c_str(),mgl_int(a[2].v),opt);
+	else if(!strcmp(k,"dddd"))	gr->Dens3(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),"", -1,opt);
+	else if(!strcmp(k,"dddds"))	gr->Dens3(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),-1,opt);
+	else if(!strcmp(k,"ddddsn"))	gr->Dens3(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),mgl_int(a[5].v),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_densx(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->DensX(*(a[0].d),"",NAN,opt);
+	else if(!strcmp(k,"ds"))	gr->DensX(*(a[0].d),a[1].s.c_str(),NAN,opt);
+	else if(!strcmp(k,"dsn"))	gr->DensX(*(a[0].d),a[1].s.c_str(),a[2].v,opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_densy(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->DensY(*(a[0].d),"",NAN,opt);
+	else if(!strcmp(k,"ds"))	gr->DensY(*(a[0].d),a[1].s.c_str(),NAN,opt);
+	else if(!strcmp(k,"dsn"))	gr->DensY(*(a[0].d),a[1].s.c_str(),a[2].v,opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_densz(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->DensZ(*(a[0].d),"",NAN,opt);
+	else if(!strcmp(k,"ds"))	gr->DensZ(*(a[0].d),a[1].s.c_str(),NAN,opt);
+	else if(!strcmp(k,"dsn"))	gr->DensZ(*(a[0].d),a[1].s.c_str(),a[2].v,opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_dots(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"ddd"))	gr->Dots(*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"ddds"))	gr->Dots(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),opt);
+	else if(!strcmp(k,"dddd"))	gr->Dots(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),"",opt);
+	else if(!strcmp(k,"dddds"))	gr->Dots(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),opt);
+	else if(!strcmp(k,"ddddd"))	gr->Dots(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),"",opt);
+	else if(!strcmp(k,"ddddds"))gr->Dots(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),a[5].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_grid3(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Grid3(*(a[0].d),"",-1,opt);
+	else if(!strcmp(k,"ds"))	gr->Grid3(*(a[0].d),a[1].s.c_str(),-1,opt);
+	else if(!strcmp(k,"dsn"))	gr->Grid3(*(a[0].d),a[1].s.c_str(),mgl_int(a[2].v),opt);
+	else if(!strcmp(k,"dddd"))	gr->Grid3(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),"",-1,opt);
+	else if(!strcmp(k,"dddds"))	gr->Grid3(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),-1,opt);
+	else if(!strcmp(k,"ddddsn"))gr->Grid3(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),mgl_int(a[5].v),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_surf3(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Surf3(*(a[0].d),"",opt);
+	else if(!strcmp(k,"ds"))	gr->Surf3(*(a[0].d),a[1].s.c_str(),opt);
+	else if(!strcmp(k,"dn"))	gr->Surf3(a[1].v,*(a[0].d),"",opt);
+	else if(!strcmp(k,"dns"))	gr->Surf3(a[1].v,*(a[0].d),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"dddd"))	gr->Surf3(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d), "",opt);
+	else if(!strcmp(k,"dddds"))	gr->Surf3(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d), a[4].s.c_str(),opt);
+	else if(!strcmp(k,"ddddn"))	gr->Surf3(a[4].v,*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),"",opt);
+	else if(!strcmp(k,"ddddns"))gr->Surf3(a[4].v,*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[5].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_surf3c(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"dd"))	gr->Surf3C(*(a[0].d),*(a[1].d),"",opt);
+	else if(!strcmp(k,"dds"))	gr->Surf3C(*(a[0].d),*(a[1].d),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ddn"))	gr->Surf3C(a[2].v,*(a[0].d),*(a[1].d),"",opt);
+	else if(!strcmp(k,"ddns"))	gr->Surf3C(a[2].v,*(a[0].d),*(a[1].d),a[3].s.c_str(),opt);
+	else if(!strcmp(k,"ddddd"))
+		gr->Surf3C(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d), "",opt);
+	else if(!strcmp(k,"ddddds"))
+		gr->Surf3C(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d), a[5].s.c_str(),opt);
+	else if(!strcmp(k,"dddddn"))
+		gr->Surf3C(a[5].v,*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),"",opt);
+	else if(!strcmp(k,"dddddns"))
+		gr->Surf3C(a[5].v,*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),a[6].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_surf3a(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"dd"))	gr->Surf3A(*(a[0].d),*(a[1].d),"",opt);
+	else if(!strcmp(k,"dds"))	gr->Surf3A(*(a[0].d),*(a[1].d),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ddn"))	gr->Surf3A(a[2].v,*(a[0].d),*(a[1].d),"",opt);
+	else if(!strcmp(k,"ddns"))	gr->Surf3A(a[2].v,*(a[0].d),*(a[1].d),a[3].s.c_str(),opt);
+	else if(!strcmp(k,"ddddd"))
+		gr->Surf3A(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d), "",opt);
+	else if(!strcmp(k,"ddddds"))
+		gr->Surf3A(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d), a[5].s.c_str(),opt);
+	else if(!strcmp(k,"dddddn"))
+		gr->Surf3A(a[5].v,*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),"",opt);
+	else if(!strcmp(k,"dddddns"))
+		gr->Surf3A(a[5].v,*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),a[6].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_surf3ca(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"ddd"))	gr->Surf3CA(*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"ddds"))	gr->Surf3CA(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),opt);
+	else if(!strcmp(k,"dddn"))	gr->Surf3CA(a[4].v,*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"dddns"))	gr->Surf3CA(a[4].v,*(a[0].d),*(a[1].d),*(a[2].d),a[4].s.c_str(),opt);
+	else if(!strcmp(k,"dddddd"))
+		gr->Surf3CA(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d), "",opt);
+	else if(!strcmp(k,"dddddds"))
+		gr->Surf3CA(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d), a[6].s.c_str(),opt);
+	else if(!strcmp(k,"ddddddn"))
+		gr->Surf3CA(a[6].v,*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d),"",opt);
+	else if(!strcmp(k,"ddddddns"))
+		gr->Surf3CA(a[6].v,*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d),a[7].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+//	Vect
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_dew(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"dd"))	gr->Dew(*(a[0].d),*(a[1].d),"",opt);
+	else if(!strcmp(k,"dds"))	gr->Dew(*(a[0].d),*(a[1].d),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"dddd"))	gr->Dew(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),"",opt);
+	else if(!strcmp(k,"dddds"))	gr->Dew(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_flow(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"dd"))	gr->Flow(*(a[0].d),*(a[1].d),"",opt);
+	else if(!strcmp(k,"dds"))	gr->Flow(*(a[0].d),*(a[1].d),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->Flow(*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"ddds"))	gr->Flow(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),opt);
+	else if(!strcmp(k,"dddd"))	gr->Flow(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),"",opt);
+	else if(!strcmp(k,"dddds"))	gr->Flow(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),opt);
+	else if(!strcmp(k,"dddddd"))
+		gr->Flow(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d),"",opt);
+	else if(!strcmp(k,"dddddds"))
+		gr->Flow(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d),a[6].s.c_str(),opt);
+	else if(!strcmp(k,"nndd"))
+		gr->FlowP(mglPoint(a[0].v,a[1].v,NAN), *(a[2].d),*(a[3].d),"",opt);
+	else if(!strcmp(k,"nndds"))
+		gr->FlowP(mglPoint(a[0].v,a[1].v,NAN), *(a[2].d),*(a[3].d),a[4].s.c_str(),opt);
+	else if(!strcmp(k,"nndddd"))
+		gr->FlowP(mglPoint(a[0].v,a[1].v,NAN), *(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d),"",opt);
+	else if(!strcmp(k,"nndddds"))
+		gr->FlowP(mglPoint(a[0].v,a[1].v,NAN), *(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d),a[6].s.c_str(),opt);
+	else if(!strcmp(k,"nnnddd"))
+		gr->FlowP(mglPoint(a[0].v,a[1].v,a[2].v), *(a[3].d),*(a[4].d),*(a[5].d),"",opt);
+	else if(!strcmp(k,"nnnddds"))
+		gr->FlowP(mglPoint(a[0].v,a[1].v,a[2].v), *(a[3].d),*(a[4].d),*(a[5].d),a[6].s.c_str(),opt);
+	else if(!strcmp(k,"nnndddddd"))
+		gr->FlowP(mglPoint(a[0].v,a[1].v,a[2].v), *(a[3].d),*(a[4].d),*(a[5].d),*(a[6].d),*(a[7].d),*(a[8].d),"",opt);
+	else if(!strcmp(k,"nnndddddds"))
+		gr->FlowP(mglPoint(a[0].v,a[1].v,a[2].v), *(a[3].d),*(a[4].d),*(a[5].d),*(a[6].d),*(a[7].d),*(a[8].d),a[9].s.c_str(),opt);
+	else res = 1;
+	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_grad(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->Grad(*(a[0].d), "",opt);
+	else if(!strcmp(k,"ds"))	gr->Grad(*(a[0].d), a[1].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->Grad(*(a[0].d),*(a[1].d),*(a[2].d), "",opt);
+	else if(!strcmp(k,"ddds"))	gr->Grad(*(a[0].d),*(a[1].d),*(a[2].d), a[3].s.c_str(),opt);
+	else if(!strcmp(k,"dddd"))	gr->Grad(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d), "",opt);
+	else if(!strcmp(k,"dddds"))	gr->Grad(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d), a[4].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_pipe(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"dd"))	gr->Pipe(*(a[0].d),*(a[1].d),"",0.05,opt);
+	else if(!strcmp(k,"dds"))	gr->Pipe(*(a[0].d),*(a[1].d),a[2].s.c_str(),0.05,opt);
+	else if(!strcmp(k,"ddsn"))	gr->Pipe(*(a[0].d),*(a[1].d),a[2].s.c_str(),a[3].v,opt);
+	else if(!strcmp(k,"dddd"))
+		gr->Pipe(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),"",0.05,opt);
+	else if(!strcmp(k,"dddds"))
+		gr->Pipe(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),0.05,opt);
+	else if(!strcmp(k,"ddddsn"))
+		gr->Pipe(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),a[5].v,opt);
+	else if(!strcmp(k,"ddd"))
+		gr->Pipe(*(a[0].d),*(a[1].d),*(a[2].d),"",0.05,opt);
+	else if(!strcmp(k,"ddds"))
+		gr->Pipe(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),0.05,opt);
+	else if(!strcmp(k,"dddsn"))
+		gr->Pipe(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),a[4].v,opt);
+	else if(!strcmp(k,"dddddd"))
+		gr->Pipe(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d),"",0.05,opt);
+	else if(!strcmp(k,"dddddds"))
+		gr->Pipe(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d),a[6].s.c_str(),0.05,opt);
+	else if(!strcmp(k,"ddddddsn"))
+		gr->Pipe(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d),a[6].s.c_str(),a[7].v,opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_traj(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"dddd"))
+		gr->Traj(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),"",opt);
+	else if(!strcmp(k,"dddds"))
+		gr->Traj(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),opt);
+	else if(!strcmp(k,"dddddd"))
+		gr->Traj(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d),"",opt);
+	else if(!strcmp(k,"dddddds"))
+		gr->Traj(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d),a[6].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_vect(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"dd"))	gr->Vect(*(a[0].d),*(a[1].d),"",opt);
+	else if(!strcmp(k,"dds"))	gr->Vect(*(a[0].d),*(a[1].d),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"ddd"))	gr->Vect(*(a[0].d),*(a[1].d),*(a[2].d),"",opt);
+	else if(!strcmp(k,"ddds"))	gr->Vect(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),opt);
+	else if(!strcmp(k,"dddd"))	gr->Vect(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),"",opt);
+	else if(!strcmp(k,"dddds"))	gr->Vect(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),a[4].s.c_str(),opt);
+	else if(!strcmp(k,"dddddd"))	gr->Vect(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d),"",opt);
+	else if(!strcmp(k,"dddddds"))	gr->Vect(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d),a[6].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_vect3(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"ddd"))
+		gr->Vect3(*(a[0].d),*(a[1].d),*(a[2].d),"",-1,opt);
+	else if(!strcmp(k,"ddds"))
+		gr->Vect3(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),-1,opt);
+	else if(!strcmp(k,"dddsn"))
+		gr->Vect3(*(a[0].d),*(a[1].d),*(a[2].d),a[3].s.c_str(),a[4].v,opt);
+	else if(!strcmp(k,"dddddd"))
+		gr->Vect3(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d),"",-1,opt);
+	else if(!strcmp(k,"dddddds"))
+		gr->Vect3(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d),a[6].s.c_str(),-1,opt);
+	else if(!strcmp(k,"ddddddsn"))
+		gr->Vect3(*(a[0].d),*(a[1].d),*(a[2].d),*(a[3].d),*(a[4].d),*(a[5].d),a[6].s.c_str(),a[7].v,opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+mglCommand mgls_grf_cmd[] = {
+	{"area",_("Draw area plot for 1D data"),"area Ydat ['fmt']|Xdat Ydat ['fmt']|Xdat Ydat Zdat ['fmt']", mgls_area ,7},
+	{"axial",_("Draw surfaces of contour lines rotation"),"axial Zdat ['fmt' num]|Xdat Ydat Zdat ['fmt' num]", mgls_axial ,8},
+	{"barh",_("Draw horizontal bars for 1D data"), "barh Ydat ['fmt' above]|Xdat Ydat ['fmt' above]", mgls_barh ,7},
+	{"bars",_("Draw bars for 1D data"),"bars Ydat ['fmt' above]|Xdat Ydat ['fmt' above]|Xdat Ydat Zdat ['fmt' above]", mgls_bars ,7},
+	{"beam",_("Draw quasi-optical beam"),"beam Ray G1 G2 Adat r ['sch' flag num]|val Ray G1 G2 Adat r ['sch' flag num]", mgls_beam ,9},
+	{"belt",_("Draw belts"),"belt Zdat ['fmt']|Xdat Ydat Zdat ['fmt']", mgls_belt ,8},
+	{"bifurcation",_("Draw Bifurcation diagram"),"bifurcation dx Func ['fmt']|dx 'func' ['fmt']", mgls_bifurcation,13},
+	{"boxplot",_("Draw boxplot for 2D data"),"boxplot Ydat ['fmt']|Xdat Ydat ['fmt']", mgls_boxplot ,7},
+	{"boxs",_("Draw boxes"),"boxs Zdat ['fmt']|Xdat Ydat Zdat ['fmt']", mgls_boxs ,8},
+	{"candle",_("Draw candlestick chart"),"candle candle Vdat1 ['fmt']|Vdat1 Vdat2 ['fmt']|Vdat1 Ydat1 Ydat2 ['fmt']||Vdat1 Vdat2 Ydat1 Ydat2 ['fmt']|Xdat Vdat1 Vdat2 Ydat1 Ydat2 ['fmt']", mgls_candle ,7},
+	{"chart",_("Draw chart"),"chart Dat ['fmt']", mgls_chart ,7},
+	{"cloud",_("Draw cloud"),"cloud Adat ['fmt']|Xdat Ydat Zdat Adat ['fmt']", mgls_cloud ,9},
+	{"cones",_("Draw cones for 1D data"),"cones Ydat ['fmt' above]|Xdat Ydat ['fmt' above]|Xdat Ydat Zdat ['fmt' above]", mgls_cones ,7},
+	{"cont",_("Draw contour lines"),"cont Zdat ['fmt' num zpos]|Vdat Zdat ['fmt' zpos]|Xdat Ydat Zdat ['fmt' num zpos]|Vdat Xdat Ydat Zdat ['fmt' zpos]", mgls_cont ,8},
+	{"cont3",_("Draw contour lines for 3D data"),"cont3 Adat 'dir' [val 'fmt' num]|Vdat Adat 'dir' [val 'fmt']|Xdat Ydat Zdat Adat 'dir' [val 'fmt' num]|Vdat Xdat Ydat Zdar Adat 'dir' [val 'fmt']", mgls_cont3 ,9},
+	{"contd",_("Draw solid contours with manual colors"),"contd Zdat ['fmt' num zpos]|Vdat Zdat ['fmt' zpos]|Xdat Ydat Zdat ['fmt' num zpos]|Vdat Xdat Ydat Zdat ['fmt' zpos]", mgls_contd ,8},
+	{"contf",_("Draw solid contours"),"contf Zdat ['fmt' num zpos]|Vdat Zdat ['fmt' zpos]|Xdat Ydat Zdat ['fmt' num zpos]|Vdat Xdat Ydat Zdat ['fmt' zpos]", mgls_contf ,8},
+	{"contf3",_("Draw solid contour lines for 3D data"),"contf3 Adat 'dir' [val 'fmt' num]|Vdat Adat 'dir' [val 'fmt']|Xdat Ydat Zdat Adat 'dir' [val 'fmt' num]|Vdat Xdat Ydat Zdar Adat 'dir' [val 'fmt']", mgls_contf3 ,9},
+	{"contfx",_("Draw solid contour lines at x-slice (or x-plane)"),"contfx Dat ['fmt' pos num]", mgls_contfx ,0},
+	{"contfy",_("Draw solid contour lines at y-slice (or y-plane)"),"contfy Dat ['fmt' pos num]", mgls_contfy ,0},
+	{"contfz",_("Draw solid contour lines at z-slice (or z-plane)"),"contfz Dat ['fmt' pos num]", mgls_contfz ,0},
+	{"contp",_("Draw contour lines on parametric surface"),"contp Xdat Ydat Zdat Adat ['fmt' num zpos]|Vdat Xdat Ydat Zdat Adat ['fmt' zpos]", mgls_contp ,8},
+	{"contv",_("Draw contour tubes"),"contv Zdat ['fmt' num zpos]|Vdat Zdat ['fmt' zpos]|Xdat Ydat Zdat ['fmt' num zpos]|Vdat Xdat Ydat Zdat ['fmt' zpos]", mgls_contv ,0},
+	{"contx",_("Draw contour lines at x-slice (or x-plane)"),"contx Dat ['fmt' pos num]", mgls_contx ,0},
+	{"conty",_("Draw contour lines at y-slice (or y-plane)"),"conty Dat ['fmt' pos num]", mgls_conty ,0},
+	{"contz",_("Draw contour lines at z-slice (or z-plane)"),"contz Dat ['fmt' pos num]", mgls_contz ,0},
+	{"crust",_("Draw reconstructed surface for arbitrary data points"),"crust Xdat Ydat Zdat ['fmt']", mgls_crust ,0},
+	{"dens",_("Draw density plot"),"dens Zdat ['fmt' zpos]|Xdat Ydat Zdat ['fmt' zpos]", mgls_dens ,8},
+	{"dens3",_("Draw density plot at slices of 3D data"),"dens3 Adat 'dir' [pos 'fmt']|Xdat Ydat Zdat Adat 'dir' [pos 'fmt']", mgls_dens3 ,9},
+	{"densx",_("Draw density plot at x-slice (or x-plane)"),"densx Dat ['fmt' pos]", mgls_densx ,0},
+	{"densy",_("Draw density plot at y-slice (or y-plane)"),"densy Dat ['fmt' pos]", mgls_densy ,0},
+	{"densz",_("Draw density plot at z-slice (or z-plane)"),"densz Dat ['fmt' pos]", mgls_densz ,0},
+	{"dew",_("Draw dew plot"),"dew Udat Vdat ['fmt']|Xdat Ydat Udat Vdat ['fmt']", mgls_dew ,11},
+	{"dots",_("Draw dots for arbitrary data points"),"dots Xdat Ydat Zdat ['fmt']|Xdat Ydat Zdat Adat ['fmt']|Xdat Ydat Zdat Cdat Adat ['fmt']", mgls_dots ,9},
+	{"error",_("Draw error boxes"),"error Ydat Yerr ['fmt']|Xdat Ydat Yerr ['fmt']|Xdat Ydat Xerr Yerr ['fmt']", mgls_error ,7},
+	{"fall",_("Draw waterfalls"),"fall Zdat ['fmt']|Xdat Ydat Zdat ['fmt']", mgls_fall ,8},
+	{"flow",_("Draw flow threads for vector field"),"flow Udat Vdat ['fmt' num]|Xdat Ydat Udat Vdat ['fmt' num]|Udat Vdat Wdat ['fmt' num]|Xdat Ydat Zdat Udat Vdat ['fmt' num]|\
+	x0 y0 Udat Vdat ['fmt']|x0 y0 Xdat Ydat Udat Vdat ['fmt']|x0 y0 z0 Udat Vdat Wdat ['fmt']|x0 y0 z0 Xdat Ydat Zdat Udat Vdat Wdat ['fmt']", mgls_flow ,11},
+	{"grad",_("Draw gradient lines for scalar field"),"grad Phi ['fmt' num]|Xdat Ydat Phi ['fmt' num]|Xdat Ydat Zdat Phi ['fmt' num]", mgls_grad ,8},
+	{"grid2",_("Draw grid for data array(s)"),"grid Zdat ['fmt']|Xdat Ydat Zdat ['fmt']", mgls_grid2 ,8},
+	{"grid3",_("Draw grid at slices of 3D data"),"grid3 Adat 'dir' [pos 'fmt']|Xdat Ydat Zdat Adat 'dir' [pos 'fmt']", mgls_grid3 ,9},
+	{"iris",_("Draw Iris plots"),"iris Dats 'ids' ['fmt']|Dats Ranges 'ids' ['fmt']", mgls_iris,13},
+	{"label",_("Draw label at arbitrary position"),"label Ydat 'txt' ['fmt'='']|Xdat Ydat 'txt' ['fmt'='']|Xdat Ydat Zdat 'txt' ['fmt'='']", mgls_label ,7},
+	{"lamerey",_("Draw Lamerey diagram"),"lamerey x0 Func ['fmt']|x0 'func' ['fmt']", mgls_lamerey ,13},
+	{"map",_("Draw mapping plot"),"map Udat Vdat ['fmt']|Xdat Ydat Udat Vdat ['fmt']", mgls_map ,10},
+	{"mark",_("Draw mark plot for 1D data"),"mark Ydat Rdat ['fmt']|Xdat Ydat Rdat ['fmt']|Xdat Ydat Zdat Rdat ['fmt']", mgls_mark ,7},
+	{"mesh",_("Draw mesh surface"),"mesh Zdat ['fmt']|Xdat Ydat Zdat ['fmt']", mgls_mesh ,8},
+	{"ohlc",_("Draw Open-High-Low-Close (OHLC) diagram"),"ohlc Odat Hdat Ldat Cdat ['fmt']|Xdat Odat Hdat Ldat Cdat ['fmt']", mgls_ohlc ,7},
+	{"pipe",_("Draw flow pipes for vector field"),"pipe Udat Vdat ['fmt' rad num]|Xdat Ydat Udat Vdat ['fmt' rad num]|Udat Vdat Wdat ['fmt' rad num]|Xdat Ydat Zdat Udat Vdat Wdat ['fmt' rad num]", mgls_pipe ,11},
+	{"plot",_("Draw usual plot for 1D data"),"plot Ydat ['fmt']|Xdat Ydat ['fmt']|Xdat Ydat Zdat ['fmt']", mgls_plot ,7},
+	{"pmap",_("Draw Poincare map"),"pmap Ydat Rdat ['fmt']|Xdat Ydat Rdat ['fmt']|Xdat Ydat Zdat Rdat ['fmt']", mgls_pmap ,7},
+	{"quadplot",_("Draw surface of quadrangles"),"quadplot Idat Xdat Ydat ['fmt']|Idat Xdat Ydat Zdat ['fmt']|Idat Xdat Ydat Zdat Cdat ['fmt'] ", mgls_quadplot ,0},
+	{"radar",_("Draw radar chart"),"radar Rdat ['fmt']", mgls_radar ,7},
+	{"region",_("Draw filled region (ribbon) between 2 curves"),"region Ydat1 Ydat2 ['fmt']|Xdat Ydat1 Ydat2 ['fmt']||Xdat1 Ydat1 Xdat2 Ydat2 ['fmt']|Xdat1 Ydat1 Zdat1 Xdat2 Ydat2 Zdat2 ['fmt']", mgls_region ,7},
+	{"stem",_("Draw stem plot for 1D data"),"stem Ydat ['fmt']|Xdat Ydat ['fmt']|Xdat Ydat Zdat ['fmt']", mgls_stem ,7},
+	{"step",_("Draw step plot for 1D data"),"step Ydat ['fmt']|Xdat Ydat ['fmt']|Xdat Ydat Zdat ['fmt']", mgls_step ,7},
+	{"stfa",_("Draw STFA diagram"),"stfa Udat Vdat dn ['fmt']|Xdat Ydat Udat Vdat dn ['fmt']", mgls_stfa ,10},
+	{"surf",_("Draw solid surface"),"surf Zdat ['fmt']|Xdat Ydat Zdat ['fmt']", mgls_surf ,8},
+	{"surf3",_("Draw isosurface for 3D data"),"surf3 Adat ['fmt' num]|Xdat Ydat Zdat Adat ['fmt' num]|Adat val ['fmt']|Xdat Ydat Zdat Adat val ['fmt']", mgls_surf3 ,9},
+	{"surf3a",_("Draw isosurface for 3D data transpared by other data"),"surf3a Adat Cdat ['fmt' num]|Xdat Ydat Zdat Adat Cdat ['fmt' num]|Adat Cdat val ['fmt']|Xdat Ydat Zdat Adat Cdat val ['fmt']", mgls_surf3a ,10},
+	{"surf3c",_("Draw isosurface for 3D data colored by other data"),"surf3c Adat Cdat ['fmt' num]|Xdat Ydat Zdat Adat Cdat ['fmt' num]|Adat Cdat val ['fmt']|Xdat Ydat Zdat Adat Cdat val ['fmt']", mgls_surf3c ,10},
+	{"surf3ca",_("Draw isosurface for 3D data colored and transpared by other data"),"surf3c Adat Cdat Bdat ['fmt' num]|Xdat Ydat Zdat Adat Cdat Bdat ['fmt' num]|Adat Cdat Bdat val ['fmt']|Xdat Ydat Zdat Adat Cdat Bdat val ['fmt']", mgls_surf3ca ,10},
+	{"surfa",_("Draw solid surface transpared by other data"),"surfa Zdat Cdat ['fmt']|Xdat Ydat Zdat Cdat ['fmt']", mgls_surfa ,10},
+	{"surfc",_("Draw solid surface colored by other data"),"surfc Zdat Cdat ['fmt']|Xdat Ydat Zdat Cdat ['fmt']", mgls_surfc ,10},
+	{"surfca",_("Draw solid surface colored and transpared by other data"),"surfca Zdat Cdat Adat ['fmt']|Xdat Ydat Zdat Cdat Adat ['fmt']", mgls_surfca ,10},
+	{"table",_("Draw table with data values"),"table Dat ['txt' 'fmt']|x y Dat ['txt' 'fmt']", mgls_table ,7},
+	{"tape",_("Draw binormales for 1D data"),"tape Ydat ['fmt']|Xdat Ydat ['fmt']|Xdat Ydat Zdat ['fmt']", mgls_tape ,7},
+	{"tens",_("Draw tension plot for 1D data"),"tens Ydat Cdat ['fmt']|Xdat Ydat Cdat ['fmt']|Xdat Ydat Zdat Cdat ['fmt']", mgls_tens ,7},
+	{"textmark",_("Draw TeX mark at point position"),"textmark Ydat Rdat 'text' ['fmt']|Xdat Ydat Rdat 'text' ['fmt']|Xdat Ydat Zdat Rdat 'text' ['fmt']", mgls_textmark ,7},
+	{"tile",_("Draw horizontal tiles"),"tile Zdat ['fmt']|Xdat Ydat Zdat ['fmt']|Xdat Ydat Zdat Cdat ['fmt']", mgls_tile ,8},
+	{"tiles",_("Draw horizontal tiles with variable size"),"tiles Zdat Rdat ['fmt']|Xdat Ydat Zdat Rdat ['fmt']|Xdat Ydat Zdat Rdat Cdat ['fmt']", mgls_tiles ,10},
+	{"torus",_("Draw surface of curve rotation"),"torus Rdat ['fmt']|Zdat Rdat ['fmt']", mgls_torus ,7},
+	{"traj",_("Draw vectors along a curve"),"traj Xdat Ydat Udat Vdat ['fmt' len]|Xdat Ydat Zdat Udat Vdat Wdat ['fmt' len]", mgls_traj ,11},
+	{"tricont",_("Draw contour lines for surface of triangles"),"tricont Idat Xdat Ydat Cdat ['fmt']|Idat Xdat Ydat Zdat Cdat ['fmt']|Vdat Idat Xdat Ydat Cdat ['fmt']|Vdat Idat Xdat Ydat Zdat Cdat ['fmt']", mgls_tricont ,0},
+	{"tricontv",_("Draw contour tubes for surface of triangles"),"tricontv Idat Xdat Ydat Cdat ['fmt']|Idat Xdat Ydat Zdat Cdat ['fmt']|Vdat Idat Xdat Ydat Cdat ['fmt']|Vdat Idat Xdat Ydat Zdat Cdat ['fmt']", mgls_tricontv ,0},
+	{"triplot",_("Draw surface of triangles"),"triplot Idat Xdat Ydat ['fmt']|Idat Xdat Ydat Zdat ['fmt']|Idat Xdat Ydat Zdat Cdat ['fmt'] ", mgls_triplot ,0},
+	{"tube",_("Draw curve by tube"),"tube Ydat Rdat ['fmt']|Ydat rval ['fmt']|Xdat Ydat Rdat ['fmt']|Xdat Ydat rval ['fmt']|Xdat Ydat Zdat Rdat ['fmt']|Xdat Ydat Zdat rval ['fmt']", mgls_tube ,7},
+	{"vect",_("Draw vector field"),"vect Udat Vdat ['fmt']|Xdat Ydat Udat Vdat ['fmt']|Udat Vdat Wdat ['fmt']|Xdat Ydat Zdat Udat Vdat Wdat ['fmt']", mgls_vect ,11},
+	{"vect3",_("Draw vector field at slices of 3D data"),"vect Udat Vdat Wdat ['fmt' sval]|Xdat Ydat Zdat Udat Vdat Wdat ['fmt' sval]", mgls_vect3 ,11},
+{"","","",NULL,0}};
+//-----------------------------------------------------------------------------
diff --git a/src/exec_prm.cpp b/src/exec_prm.cpp
new file mode 100644
index 0000000..b6a5da4
--- /dev/null
+++ b/src/exec_prm.cpp
@@ -0,0 +1,617 @@
+/***************************************************************************
+ * exec_2d.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifdef WIN32
+#include <io.h>
+#include <direct.h>
+#else
+#include <unistd.h>
+#endif
+
+#include "mgl2/base.h"
+#include "mgl2/parser.h"
+#pragma GCC diagnostic ignored "-Wmisleading-indentation"
+wchar_t *mgl_str_copy(const char *s);
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_arc(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;	gr->Self()->SaveState(opt);
+	if(!strcmp(k,"nnnnn"))
+		gr->Arc(mglPoint(a[0].v,a[1].v,NAN), mglPoint(a[2].v,a[3].v,NAN), a[4].v);
+	else if(!strcmp(k,"nnnnns"))
+		gr->Arc(mglPoint(a[0].v,a[1].v,NAN), mglPoint(a[2].v,a[3].v,NAN), a[4].v, a[5].s.c_str());
+	else if(!strcmp(k,"nnnnnn"))
+		gr->Arc(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v), a[5].v);
+	else if(!strcmp(k,"nnnnnns"))
+		gr->Arc(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v), a[5].v, a[6].s.c_str());
+	else if(!strcmp(k,"nnnnnnnnnn"))
+		gr->Arc(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v, a[5].v), mglPoint(a[6].v,a[7].v, a[8].v), a[9].v);
+	else if(!strcmp(k,"nnnnnnnnnns"))
+		gr->Arc(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v, a[5].v), mglPoint(a[6].v,a[7].v, a[8].v), a[9].v, a[10].s.c_str());
+	else res = 1;	gr->Self()->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_axis(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(k[0]==0)	gr->Axis("xyz","",opt);
+	else if(!strcmp(k,"s"))		gr->Axis(a[0].s.c_str(), "",opt);
+	else if(!strcmp(k,"ss"))	gr->Axis(a[0].s.c_str(), a[1].s.c_str(),opt);
+	else if(!strcmp(k,"sss"))	gr->SetFunc(a[0].s.c_str(),a[1].s.c_str(),a[2].s.c_str(),"");
+	else if(!strcmp(k,"ssss"))	gr->SetFunc(a[0].s.c_str(),a[1].s.c_str(),a[2].s.c_str(),a[3].s.c_str());
+	else if(!strcmp(k,"n"))		gr->SetCoor(mgl_int(a[0].v));
+	else if(!strcmp(k,"nnnn"))	gr->SetRanges(a[0].v,a[2].v, a[1].v,a[3].v);
+	else if(!strcmp(k,"nnnnnn"))gr->SetRanges(a[0].v,a[3].v, a[1].v,a[4].v, a[2].v,a[5].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_background(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"s"))	gr->LoadBackground(a[0].s.c_str());
+	else if(!strcmp(k,"sn"))	gr->LoadBackground(a[0].s.c_str(),a[1].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_ball(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;	gr->Self()->SaveState(opt);
+	if(!strcmp(k,"nn"))	gr->Mark(mglPoint(a[0].v,a[1].v,NAN),"r.");
+	else if(!strcmp(k,"nns"))	gr->Mark(mglPoint(a[0].v,a[1].v,NAN),a[2].s.c_str());
+	else if(!strcmp(k,"nnn"))	gr->Mark(mglPoint(a[0].v,a[1].v,a[2].v),"r.");
+	else if(!strcmp(k,"nnns"))	gr->Mark(mglPoint(a[0].v,a[1].v,a[2].v),a[3].s.c_str());
+	else res = 1;	gr->Self()->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_box(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;	gr->Self()->SaveState(opt);
+	if(k[0]==0)	gr->Box();
+	else if(!strcmp(k,"s"))		gr->Box(a[0].s.c_str());
+	else if(!strcmp(k,"sn"))	gr->Box(a[0].s.c_str(), a[1].v);
+	else res = 1;	gr->Self()->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_circle(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;	gr->Self()->SaveState(opt);
+	if(!strcmp(k,"nnn"))	gr->Circle(mglPoint(a[0].v,a[1].v, NAN), a[2].v);
+	else if(!strcmp(k,"nnns"))	gr->Circle(mglPoint(a[0].v,a[1].v, NAN), a[2].v, a[3].s.c_str());
+	else if(!strcmp(k,"nnnn"))	gr->Circle(mglPoint(a[0].v,a[1].v,a[2].v), a[3].v);
+	else if(!strcmp(k,"nnnns"))	gr->Circle(mglPoint(a[0].v,a[1].v,a[2].v), a[3].v, a[4].s.c_str());
+	else res = 1;	gr->Self()->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_colorbar(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;	gr->Self()->SaveState(opt);
+	if(k[0]==0)	gr->Colorbar();
+	else if(!strcmp(k,"s"))		gr->Colorbar(a[0].s.c_str());
+	else if(!strcmp(k,"d"))		gr->Colorbar(*(a[0].d));
+	else if(!strcmp(k,"ds"))	gr->Colorbar(*(a[0].d), a[1].s.c_str());
+	else if(!strcmp(k,"snn"))	gr->Colorbar(a[0].s.c_str(), a[1].v, a[2].v);
+	else if(!strcmp(k,"snnn"))	gr->Colorbar(a[0].s.c_str(), a[1].v, a[2].v, a[3].v,1);
+	else if(!strcmp(k,"snnnn"))	gr->Colorbar(a[0].s.c_str(), a[1].v, a[2].v, a[3].v,a[4].v);
+	else if(!strcmp(k,"dsnn"))	gr->Colorbar(*(a[0].d), a[1].s.c_str(), a[2].v, a[3].v);
+	else if(!strcmp(k,"dsnnn"))	gr->Colorbar(*(a[0].d), a[1].s.c_str(), a[2].v, a[3].v, a[4].v,1);
+	else if(!strcmp(k,"dsnnnn"))
+		gr->Colorbar(*(a[0].d), a[1].s.c_str(), a[2].v, a[3].v, a[4].v,a[5].v);
+	else res = 1;	gr->Self()->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_cone(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;	gr->Self()->SaveState(opt);
+	if(!strcmp(k,"nnnnnnn"))	gr->Cone(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v), a[6].v);
+	else if(!strcmp(k,"nnnnnnns"))	gr->Cone(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v), a[6].v,-1, a[7].s.c_str());
+	else if(!strcmp(k,"nnnnnnnn"))	gr->Cone(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v), a[6].v, a[7].v);
+	else if(!strcmp(k,"nnnnnnnns"))	gr->Cone(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v), a[6].v, a[7].v, a[8].s.c_str());
+	else res = 1;	gr->Self()->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_curve(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"nnnnnnnn"))
+		gr->Curve(mglPoint(a[0].v,a[1].v,NAN),
+			mglPoint(a[2].v,a[3].v),
+			mglPoint(a[4].v,a[5].v,NAN),
+			mglPoint(a[6].v,a[7].v));
+	else if(!strcmp(k,"nnnnnnnns"))
+		gr->Curve(mglPoint(a[0].v,a[1].v,NAN),
+			mglPoint(a[2].v,a[3].v),
+			mglPoint(a[4].v,a[5].v,NAN),
+			mglPoint(a[6].v,a[7].v), a[8].s.c_str());
+	else if(!strcmp(k,"nnnnnnnnnnnn"))
+		gr->Curve(mglPoint(a[0].v,a[1].v,a[2].v),
+			mglPoint(a[3].v,a[4].v,a[5].v),
+			mglPoint(a[6].v,a[7].v,a[8].v),
+			mglPoint(a[9].v,a[10].v,a[11].v));
+	else if(!strcmp(k,"nnnnnnnnnnnns"))
+		gr->Curve(mglPoint(a[0].v,a[1].v,a[2].v),
+			mglPoint(a[3].v,a[4].v,a[5].v),
+			mglPoint(a[6].v,a[7].v,a[8].v),
+			mglPoint(a[9].v,a[10].v,a[11].v), a[12].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_drop(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;	gr->Self()->SaveState(opt);
+	if(!strcmp(k,"nnnnn"))
+		gr->Drop(mglPoint(a[0].v,a[1].v), mglPoint(a[2].v,a[3].v), a[4].v);
+	else if(!strcmp(k,"nnnnns"))
+		gr->Drop(mglPoint(a[0].v,a[1].v), mglPoint(a[2].v,a[3].v), a[4].v, a[5].s.c_str());
+	else if(!strcmp(k,"nnnnnsn"))
+		gr->Drop(mglPoint(a[0].v,a[1].v), mglPoint(a[2].v,a[3].v), a[4].v, a[5].s.c_str(), a[6].v);
+	else if(!strcmp(k,"nnnnnsnn"))
+		gr->Drop(mglPoint(a[0].v,a[1].v), mglPoint(a[2].v,a[3].v), a[4].v, a[5].s.c_str(), a[6].v, a[7].v);
+	else if(!strcmp(k,"nnnnnnn"))
+		gr->Drop(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v), a[6].v);
+	else if(!strcmp(k,"nnnnnnns"))
+		gr->Drop(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v), a[6].v, a[7].s.c_str());
+	else if(!strcmp(k,"nnnnnnnsn"))
+		gr->Drop(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v), a[6].v, a[7].s.c_str(), a[8].v);
+	else if(!strcmp(k,"nnnnnnnsnn"))
+		gr->Drop(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v), a[6].v, a[7].s.c_str(), a[8].v, a[9].v);
+	else res = 1;	gr->Self()->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_ellipse(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;	gr->Self()->SaveState(opt);
+	if(!strcmp(k,"nnnnn"))
+		gr->Ellipse(mglPoint(a[0].v,a[1].v,NAN), mglPoint(a[2].v,a[3].v,NAN), a[4].v);
+	else if(!strcmp(k,"nnnnns"))
+		gr->Ellipse(mglPoint(a[0].v,a[1].v,NAN), mglPoint(a[2].v,a[3].v,NAN), a[4].v, a[5].s.c_str());
+	else if(!strcmp(k,"nnnnnnn"))
+		gr->Ellipse(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v), a[6].v);
+	else if(!strcmp(k,"nnnnnnns"))
+		gr->Ellipse(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v), a[6].v, a[7].s.c_str());
+	else res = 1;	gr->Self()->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_errbox(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;	gr->Self()->SaveState(opt);
+	if(!strcmp(k,"nnnn"))
+		gr->Error(mglPoint(a[0].v,a[1].v,NAN), mglPoint(a[2].v,a[3].v,NAN));
+	else if(!strcmp(k,"nnnns"))
+		gr->Error(mglPoint(a[0].v,a[1].v,NAN), mglPoint(a[2].v,a[3].v,NAN), a[4].s.c_str());
+	else if(!strcmp(k,"nnnnnn"))
+		gr->Error(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v));
+	else if(!strcmp(k,"nnnnnns"))
+		gr->Error(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v), a[6].s.c_str());
+	else res = 1;	gr->Self()->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_face(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;	gr->Self()->SaveState(opt);
+	if(!strcmp(k,"nnnnnnnn"))
+		gr->Face(mglPoint(a[0].v,a[1].v,NAN), mglPoint(a[2].v,a[3].v,NAN),
+				mglPoint(a[4].v,a[5].v,NAN), mglPoint(a[6].v,a[7].v,NAN));
+	else if(!strcmp(k,"nnnnnnnns"))
+		gr->Face(mglPoint(a[0].v,a[1].v,NAN), mglPoint(a[2].v,a[3].v,NAN),
+				mglPoint(a[4].v,a[5].v,NAN), mglPoint(a[6].v,a[7].v,NAN), a[8].s.c_str());
+	else if(!strcmp(k,"nnnnnnnnnnnn"))
+		gr->Face(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v),
+				mglPoint(a[6].v,a[7].v,a[8].v), mglPoint(a[9].v,a[10].v,a[11].v));
+	else if(!strcmp(k,"nnnnnnnnnnnns"))
+		gr->Face(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v),
+				mglPoint(a[6].v,a[7].v,a[8].v), mglPoint(a[9].v,a[10].v,a[11].v), a[12].s.c_str());
+	else res = 1;	gr->Self()->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_facex(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;	gr->Self()->SaveState(opt);
+	if(!strcmp(k,"nnnnn"))	gr->FaceX(mglPoint(a[0].v, a[1].v, a[2].v), a[3].v, a[4].v);
+	else if(!strcmp(k,"nnnnns"))	gr->FaceX(mglPoint(a[0].v, a[1].v, a[2].v), a[3].v, a[4].v, a[5].s.c_str());
+	else if(!strcmp(k,"nnnnnsnn"))	gr->FaceX(mglPoint(a[0].v, a[1].v, a[2].v), a[3].v, a[4].v, a[5].s.c_str(),a[6].v,a[7].v);
+	else res = 1;	gr->Self()->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_facey(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;	gr->Self()->SaveState(opt);
+	if(!strcmp(k,"nnnnn"))	gr->FaceY(mglPoint(a[0].v, a[1].v, a[2].v), a[3].v, a[4].v);
+	else if(!strcmp(k,"nnnnns"))	gr->FaceY(mglPoint(a[0].v, a[1].v, a[2].v), a[3].v, a[4].v, a[5].s.c_str());
+	else if(!strcmp(k,"nnnnnsnn"))	gr->FaceY(mglPoint(a[0].v, a[1].v, a[2].v), a[3].v, a[4].v, a[5].s.c_str(),a[6].v,a[7].v);
+	else res = 1;	gr->Self()->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_facez(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;	gr->Self()->SaveState(opt);
+	if(!strcmp(k,"nnnnn"))	gr->FaceZ(mglPoint(a[0].v, a[1].v, a[2].v), a[3].v, a[4].v);
+	else if(!strcmp(k,"nnnnns"))	gr->FaceZ(mglPoint(a[0].v, a[1].v, a[2].v), a[3].v, a[4].v, a[5].s.c_str());
+	else if(!strcmp(k,"nnnnnsnn"))	gr->FaceZ(mglPoint(a[0].v, a[1].v, a[2].v), a[3].v, a[4].v, a[5].s.c_str(),a[6].v,a[7].v);
+	else res = 1;	gr->Self()->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_fgets(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;	gr->Self()->SaveState(opt);
+	char *buf;	buf = new char[4096];
+	FILE *fp;
+	if(!strncmp(k,"nns",3))
+	{
+		int i, n = (k[3]=='n'?mgl_int(a[3].v):0);
+		fp = fopen(a[2].s.c_str(),"rt");
+		if(!fp)
+		{
+			gr->SetWarn(mglWarnOpen,a[2].s.c_str());
+			delete []buf;	return res;
+}
+		for(i=0;i<n;i++)	if(!fgets(buf,4096,fp))	continue;
+		memset(buf,0,4096);
+		if(!fgets(buf,4096,fp))
+		{
+			gr->SetWarn(mglWarnOpen,(a[2].s+" - line "+mgl_str_num(n)).c_str());
+			fclose(fp);	delete []buf;	return res;
+		}
+		fclose(fp);
+		gr->Puts(mglPoint(a[0].v,a[1].v,NAN),buf, (k[4]=='s')?a[4].s.c_str():"", k[5]=='n'?a[5].v:-1);
+	}
+	else if(!strncmp(k,"nnns",4))
+	{
+		int i, n = (k[4]=='n'?mgl_int(a[4].v):0);
+		fp = fopen(a[3].s.c_str(),"rt");
+		if(!fp)
+		{
+			gr->SetWarn(mglWarnOpen,a[3].s.c_str());
+			delete []buf;	return res;
+		}
+		for(i=0;i<n;i++)	if(!fgets(buf,4096,fp))	continue;
+		memset(buf,0,4096);
+		if(!fgets(buf,4096,fp))
+		{
+			gr->SetWarn(mglWarnOpen,(a[3].s+" - line "+mgl_str_num(n)).c_str());
+			fclose(fp);	delete []buf;	return res;
+		}
+		fclose(fp);
+		gr->Puts(mglPoint(a[0].v,a[1].v,a[2].v),buf, (k[5]=='s')?a[5].s.c_str():"", k[6]=='n'?a[6].v:-1);
+	}
+	else res = 1;	gr->Self()->LoadState();	delete []buf;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_flame2d(mglGraph *, long, mglArg *a, const char *k, const char *)
+{
+	mglData *fx = dynamic_cast<mglData*>(a[0].d);
+	mglData *fy = dynamic_cast<mglData*>(a[1].d);
+	if(!fx)	return 1;
+	int res = 0;
+	if (!strcmp(k, "dddn"))	fx->Set(mglFlame2d(*(a[1].d), *(a[2].d), mgl_int(a[3].v)));
+	else if (!strcmp(k, "ddddn") && fy)
+	{
+		mglData f(mglFlame2d(*(a[2].d), *(a[3].d), mgl_int(a[4].v)));
+		fx->Set(f.SubData(0));	fy->Set(f.SubData(1));
+	}
+	else if (!strcmp(k, "dddnn"))	fx->Set(mglFlame2d(*(a[1].d), *(a[2].d), mgl_int(a[3].v), mgl_int(a[4].v)));
+	else if (!strcmp(k, "ddddnn") && fy)
+	{
+		mglData f(mglFlame2d(*(a[2].d), *(a[3].d), mgl_int(a[4].v), mgl_int(a[5].v)));
+		fx->Set(f.SubData(0));	fy->Set(f.SubData(1));
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_fplot(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"s"))	gr->FPlot(a[0].s.c_str(), "",opt);
+	else if(!strcmp(k,"ss"))	gr->FPlot(a[0].s.c_str(), a[1].s.c_str(),opt);
+	else if(!strcmp(k,"sss"))	gr->FPlot(a[0].s.c_str(), a[1].s.c_str(), a[2].s.c_str(), "",opt);
+	else if(!strcmp(k,"ssss"))	gr->FPlot(a[0].s.c_str(), a[1].s.c_str(), a[2].s.c_str(), a[3].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_fsurf(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"s"))	gr->FSurf(a[0].s.c_str(), "",opt);
+	else if(!strcmp(k,"ss"))	gr->FSurf(a[0].s.c_str(), a[1].s.c_str(),opt);
+	else if(!strcmp(k,"sss"))	gr->FSurf(a[0].s.c_str(), a[1].s.c_str(), a[2].s.c_str(), "",opt);
+	else if(!strcmp(k,"ssss"))	gr->FSurf(a[0].s.c_str(), a[1].s.c_str(), a[2].s.c_str(), a[3].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_grid(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(k[0]==0)	gr->Grid("xyzt", "B",opt);
+	else if(!strcmp(k,"s"))	gr->Grid(a[0].s.c_str(), "B",opt);
+	else if(!strcmp(k,"ss"))gr->Grid(a[0].s.c_str(), a[1].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_ifs2d(mglGraph *, long, mglArg *a, const char *k, const char *)
+{
+	mglData *fx = dynamic_cast<mglData*>(a[0].d);
+	mglData *fy = dynamic_cast<mglData*>(a[1].d);
+	if(!fx)	return 1;
+	int res = 0;
+	if (!strcmp(k, "ddn"))	fx->Set(mglIFS2d(*(a[1].d), mgl_int(a[2].v)));
+	else if (!strcmp(k, "dddn") && fy)
+	{
+		mglData f(mglIFS2d(*(a[2].d), mgl_int(a[3].v)));
+		fx->Set(f.SubData(0));	fy->Set(f.SubData(1));
+	}
+	else if (!strcmp(k, "ddnn"))	fx->Set(mglIFS2d(*(a[1].d), mgl_int(a[2].v), mgl_int(a[3].v)));
+	else if (!strcmp(k, "dddnn") && fy)
+	{
+		mglData f(mglIFS2d(*(a[2].d), mgl_int(a[3].v), mgl_int(a[4].v)));
+		fx->Set(f.SubData(0));	fy->Set(f.SubData(1));
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_ifs3d(mglGraph *, long, mglArg *a, const char *k, const char *)
+{
+	mglData *f = dynamic_cast<mglData*>(a[0].d);
+	if(!f)	return 1;
+	int res = 0;
+	if (!strcmp(k, "ddn"))	f->Set(mglIFS3d(*(a[1].d), mgl_int(a[2].v)));
+	else if (!strcmp(k, "ddnn"))	f->Set(mglIFS3d(*(a[1].d), mgl_int(a[2].v), mgl_int(a[3].v)));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_ifsfile(mglGraph *, long, mglArg *a, const char *k, const char *)
+{
+	mglData *f = dynamic_cast<mglData*>(a[0].d);
+	if(!f)	return 1;
+	int res = 0;
+	if (!strcmp(k, "dssn"))	f->Set(mglIFSfile(a[1].s.c_str(), a[2].s.c_str(), mgl_int(a[3].v)));
+	else if (!strcmp(k, "dssnn"))	f->Set(mglIFSfile(a[1].s.c_str(), a[2].s.c_str(), mgl_int(a[3].v), mgl_int(a[4].v)));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_legend(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(k[0]==0)	gr->Legend(3, "#", opt);
+	else if(!strcmp(k,"n"))	gr->Legend(mgl_int(a[0].v), "#", opt);
+	else if(!strcmp(k,"ns"))	gr->Legend(mgl_int(a[0].v), a[1].s.c_str(), opt);
+	else if(!strcmp(k,"nn"))	gr->Legend(a[0].v, a[1].v, "#", opt);
+	else if(!strcmp(k,"nns"))	gr->Legend(a[0].v, a[1].v, a[2].s.c_str(), opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_line(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;	gr->Self()->SaveState(opt);
+	if(!strcmp(k,"nnnn"))
+		gr->Line(mglPoint(a[0].v,a[1].v,NAN), mglPoint(a[2].v,a[3].v,NAN));
+	else if(!strcmp(k,"nnnns"))
+		gr->Line(mglPoint(a[0].v,a[1].v,NAN), mglPoint(a[2].v,a[3].v,NAN), a[4].s.c_str());
+	else if(!strcmp(k,"nnnnnn"))
+		gr->Line(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v));
+	else if(!strcmp(k,"nnnnnns"))
+		gr->Line(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v), a[6].s.c_str());
+	else res = 1;	gr->Self()->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_logo(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"s"))	gr->Logo(a[0].s.c_str(),false,opt);
+	else if(!strcmp(k,"sn"))	gr->Logo(a[0].s.c_str(),mgl_int(a[1].v),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_polygon(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;	gr->Self()->SaveState(opt);
+	if(!strcmp(k,"nnnnn"))
+		gr->Polygon(mglPoint(a[0].v,a[1].v,NAN), mglPoint(a[2].v,a[3].v,NAN), mgl_int(a[4].v));
+	else if(!strcmp(k,"nnnnns"))
+		gr->Polygon(mglPoint(a[0].v,a[1].v,NAN), mglPoint(a[2].v,a[3].v,NAN), mgl_int(a[4].v), a[5].s.c_str());
+	else if(!strcmp(k,"nnnnnnn"))
+		gr->Polygon(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v), mgl_int(a[6].v));
+	else if(!strcmp(k,"nnnnnnns"))
+		gr->Polygon(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v), mgl_int(a[6].v), a[7].s.c_str());
+	else res = 1;	gr->Self()->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_rect(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;	gr->Self()->SaveState(opt);
+	if(!strcmp(k,"nnnn"))
+		gr->Face(mglPoint(a[0].v,a[1].v,NAN), mglPoint(a[0].v,a[3].v,NAN),
+				 mglPoint(a[2].v,a[1].v,NAN), mglPoint(a[2].v,a[3].v,NAN));
+	else if(!strcmp(k,"nnnns"))
+		gr->Face(mglPoint(a[0].v,a[1].v,NAN), mglPoint(a[0].v,a[3].v,NAN),
+					mglPoint(a[2].v,a[1].v,NAN), mglPoint(a[2].v,a[3].v,NAN),a[4].s.c_str());
+	else if(!strncmp(k,"nnnnnn",6))
+	{
+		if(a[0].v==a[3].v)	gr->Face(mglPoint(a[0].v,a[1].v,a[2].v),
+			mglPoint(a[0].v,a[4].v,a[2].v),
+			mglPoint(a[3].v,a[1].v,a[5].v),
+			mglPoint(a[3].v,a[4].v,a[5].v),
+			k[6]=='s' ? a[6].s.c_str() : 0);
+		else	gr->Face(mglPoint(a[0].v,a[1].v,a[2].v),
+			mglPoint(a[0].v,a[4].v,a[5].v),
+			mglPoint(a[3].v,a[1].v,a[2].v),
+			mglPoint(a[3].v,a[4].v,a[5].v),
+			k[6]=='s' ? a[6].s.c_str() : 0);
+	}
+	else res = 1;	gr->Self()->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_rhomb(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;	gr->Self()->SaveState(opt);
+	if(!strcmp(k,"nnnnn"))
+		gr->Rhomb(mglPoint(a[0].v,a[1].v,NAN), mglPoint(a[2].v,a[3].v,NAN), a[4].v);
+	else if(!strcmp(k,"nnnnns"))
+		gr->Rhomb(mglPoint(a[0].v,a[1].v,NAN), mglPoint(a[2].v,a[3].v,NAN), a[4].v, a[5].s.c_str());
+	else if(!strcmp(k,"nnnnnnn"))
+		gr->Rhomb(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v), a[6].v);
+	else if(!strcmp(k,"nnnnnnns"))
+		gr->Rhomb(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v), a[6].v, a[7].s.c_str());
+	else res = 1;	gr->Self()->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_sphere(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;	gr->Self()->SaveState(opt);
+	if(!strcmp(k,"nnn"))	gr->Sphere(mglPoint(a[0].v,a[1].v), a[2].v);
+	else if(!strcmp(k,"nnns"))	gr->Sphere(mglPoint(a[0].v,a[1].v), a[2].v, a[3].s.c_str());
+	else if(!strcmp(k,"nnnn"))	gr->Sphere(mglPoint(a[0].v,a[1].v,a[2].v), a[3].v);
+	else if(!strcmp(k,"nnnns"))	gr->Sphere(mglPoint(a[0].v,a[1].v,a[2].v), a[3].v, a[4].s.c_str());
+	else res = 1;	gr->Self()->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_symbol(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)		// NOTE don't use options -- Puts can be part of group
+{
+	int res=0;
+	if(k[0]=='n')
+	{
+		gr->Self()->SaveState(opt);
+		if(!strcmp(k,"nns"))	gr->Symbol(mglPoint(a[0].v,a[1].v,NAN),a[2].s[0]);
+		else if(!strcmp(k,"nnss"))	gr->Symbol(mglPoint(a[0].v,a[1].v,NAN),a[2].s[0], a[3].s.c_str());
+		else if(!strcmp(k,"nnssn"))	gr->Symbol(mglPoint(a[0].v,a[1].v,NAN),a[2].s[0], a[3].s.c_str(),a[4].v);
+		else if(!strcmp(k,"nnns"))	gr->Symbol(mglPoint(a[0].v,a[1].v,a[2].v),a[3].s[0]);
+		else if(!strcmp(k,"nnnss"))	gr->Symbol(mglPoint(a[0].v,a[1].v,a[2].v),a[3].s[0], a[4].s.c_str());
+		else if(!strcmp(k,"nnnssn"))gr->Symbol(mglPoint(a[0].v,a[1].v,a[2].v),a[3].s[0], a[4].s.c_str(),a[5].v);
+		else if(!strcmp(k,"nnnns"))		gr->Symbol(mglPoint(a[0].v,a[1].v,NAN), mglPoint(a[2].v,a[3].v), a[4].s[0]);
+		else if(!strcmp(k,"nnnnss"))	gr->Symbol(mglPoint(a[0].v,a[1].v,NAN), mglPoint(a[2].v,a[3].v), a[4].s[0], a[5].s.c_str());
+		else if(!strcmp(k,"nnnnssn"))	gr->Symbol(mglPoint(a[0].v,a[1].v,NAN), mglPoint(a[2].v,a[3].v), a[4].s[0], a[5].s.c_str(),a[6].v);
+		else if(!strcmp(k,"nnnnnns"))	gr->Symbol(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v), a[6].s[0]);
+		else if(!strcmp(k,"nnnnnnss"))	gr->Symbol(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v), a[6].s[0], a[7].s.c_str());
+		else if(!strcmp(k,"nnnnnnssn"))	gr->Symbol(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v), a[6].s[0], a[7].s.c_str(),a[8].v);
+		else	res=1;
+		gr->Self()->LoadState();
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_text(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)		// NOTE don't use options -- Puts can be part of group
+{
+	int res=0;
+	if(k[0]=='n')
+	{
+		gr->Self()->SaveState(opt);
+		if(!strcmp(k,"nns"))	gr->Putsw(mglPoint(a[0].v,a[1].v,NAN),a[2].w.c_str());
+		else if(!strcmp(k,"nnss"))	gr->Putsw(mglPoint(a[0].v,a[1].v,NAN),a[2].w.c_str(), a[3].s.c_str());
+		else if(!strcmp(k,"nnssn"))	gr->Putsw(mglPoint(a[0].v,a[1].v,NAN),a[2].w.c_str(), a[3].s.c_str(),a[4].v);
+		else if(!strcmp(k,"nnns"))		gr->Putsw(mglPoint(a[0].v,a[1].v,a[2].v),a[3].w.c_str());
+		else if(!strcmp(k,"nnnss"))		gr->Putsw(mglPoint(a[0].v,a[1].v,a[2].v),a[3].w.c_str(), a[4].s.c_str());
+		else if(!strcmp(k,"nnnssn"))	gr->Putsw(mglPoint(a[0].v,a[1].v,a[2].v),a[3].w.c_str(), a[4].s.c_str(),a[5].v);
+		else if(!strcmp(k,"nnnns"))		gr->Putsw(mglPoint(a[0].v,a[1].v,NAN), mglPoint(a[2].v,a[3].v), a[4].w.c_str());
+		else if(!strcmp(k,"nnnnss"))	gr->Putsw(mglPoint(a[0].v,a[1].v,NAN), mglPoint(a[2].v,a[3].v), a[4].w.c_str(), a[5].s.c_str());
+		else if(!strcmp(k,"nnnnssn"))	gr->Putsw(mglPoint(a[0].v,a[1].v,NAN), mglPoint(a[2].v,a[3].v), a[4].w.c_str(), a[5].s.c_str(),a[6].v);
+		else if(!strcmp(k,"nnnnnns"))	gr->Putsw(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v), a[6].w.c_str());
+		else if(!strcmp(k,"nnnnnnss"))	gr->Putsw(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v), a[6].w.c_str(), a[7].s.c_str());
+		else if(!strcmp(k,"nnnnnnssn"))	gr->Putsw(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v), a[6].w.c_str(), a[7].s.c_str(),a[8].v);
+		else	res=1;
+		gr->Self()->LoadState();
+	}
+	else if(!strcmp(k,"ds"))	gr->Text(*(a[0].d),a[1].w.c_str(),"",opt);
+	else if(!strcmp(k,"dss"))	gr->Text(*(a[0].d),a[1].w.c_str(),a[2].s.c_str(),opt);
+	else if(!strcmp(k,"dds"))	gr->Text(*(a[0].d),*(a[1].d),a[2].w.c_str(),"",opt);
+	else if(!strcmp(k,"ddss"))	gr->Text(*(a[0].d),*(a[1].d),a[2].w.c_str(),a[3].s.c_str(),opt);
+	else if(!strcmp(k,"ddds"))	gr->Text(*(a[0].d),*(a[1].d),*(a[2].d),a[3].w.c_str(),"",opt);
+	else if(!strcmp(k,"dddss"))	gr->Text(*(a[0].d),*(a[1].d),*(a[2].d),a[3].w.c_str(),a[4].s.c_str(),opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_title(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;	gr->Self()->SaveState(opt);
+	if(!strcmp(k,"s"))	gr->Title(a[0].w.c_str());
+	else if(!strcmp(k,"ss"))	gr->Title(a[0].w.c_str(), a[1].s.c_str());
+	else if(!strcmp(k,"ssn"))	gr->Title(a[0].w.c_str(), a[1].s.c_str(),a[2].v);
+	else res = 1;	gr->Self()->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_tlabel(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"s"))	gr->Label('t', a[0].w.c_str(), 1, opt);
+	else if(!strcmp(k,"sn"))	gr->Label('t', a[0].w.c_str(), a[1].v, opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_xlabel(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"s"))	gr->Label('x', a[0].w.c_str(), 1, opt);
+	else if(!strcmp(k,"sn"))	gr->Label('x', a[0].w.c_str(), a[1].v, opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_ylabel(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"s"))	gr->Label('y', a[0].w.c_str(), 1, opt);
+	else if(!strcmp(k,"sn"))	gr->Label('y', a[0].w.c_str(), a[1].v, opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_zlabel(mglGraph *gr, long , mglArg *a, const char *k, const char *opt)
+{
+	int res=0;
+	if(!strcmp(k,"s"))	gr->Label('z', a[0].w.c_str(), 1, opt);
+	else if(!strcmp(k,"sn"))	gr->Label('z', a[0].w.c_str(), a[1].v, opt);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+mglCommand mgls_prm_cmd[] = {
+	{"arc",_("Draw angle arc"),"arc x0 y0 x1 y1 a ['fmt']|x0 y0 z0 x1 y1 a ['fmt']|x0 y0 z0 xr yr zr x1 y1 z1 a ['fmt']", mgls_arc ,13},
+	{"axis",_("Setup or draw axis"),"axis ['dir' 'fmt']|'fx' 'fy' 'fz' ['fc']|how", mgls_axis ,12},
+	{"background",_("Load image for background"),"background 'fname' [alpha]", mgls_background ,12},
+	{"ball",_("Draw point (ball)"),"ball posx posy ['fmt']|posx posy posz ['fmt']", mgls_ball ,13},
+	{"box",_("Draw bounding box"),"box ['fmt' ticks]", mgls_box ,12},
+	{"circle",_("Draw circle"),"circle x y r ['fmt']|x y z r ['fmt']", mgls_circle ,13},
+	{"colorbar",_("Draw colorbar"),"colorbar ['fmt']|Vdat ['fmt']|'sch' x y [w h]|Vdat 'sch' x y [w h]", mgls_colorbar ,12},
+	{"cone",_("Draw cone"),"cone x1 y1 z1 x2 y2 z2 r1 [r2 'fmt' edge]", mgls_cone ,13},
+	{"curve",_("Draw curve"),"curve x1 y1 dx1 dy1 x2 y2 dx2 dy2 ['fmt']|x1 y1 z1 dx1 dy1 dz1 x2 y2 z2 dx2 dy2 dz2 ['fmt']", mgls_curve ,13},
+	{"drop",_("Draw drop"),"drop x0 y0 dx dy r ['col' sh asp]|x0 y0 z0 dx dy dz r ['col' sh asp]", mgls_drop ,13},
+	{"ellipse",_("Draw ellipse"),"ellipse x1 y1 x2 y2 r ['fmt']|x1 y1 z1 x2 y2 z2 r ['fmt']", mgls_ellipse ,13},
+	{"errbox",_("Draw error box"),"errbox x y ex ey ['fmt']|x y z ex ey ez ['fmt']", mgls_errbox ,13},
+	{"face",_("Draw face (quadrangle)"),"face x1 y1 x2 y2 x3 y3 x4 y4 ['fmt']|x1 y1 z1 x2 y2 z2 x3 y3 z3 x4 y4 z4 ['fmt']", mgls_face ,13},
+	{"facex",_("Draw face perpendicular to x-axis"),"facex x0 y0 z0 wy wz ['fmt' d1 d2]", mgls_facex ,13},
+	{"facey",_("Draw face perpendicular to y-axis"),"facex x0 y0 z0 wx wz ['fmt' d1 d2]", mgls_facey ,13},
+	{"facez",_("Draw face perpendicular to z-axis"),"facex x0 y0 z0 wy wz ['fmt' d1 d2]", mgls_facez ,13},
+	{"fgets",_("Print string from file"),"fgets x y z 'fname' [pos 'fmt' size]|x y z 'fname' [pos 'fmt' size]", mgls_fgets ,15},
+	{"flame2d",_("Computes the flame fractal"), "flame2d F A B n [skip]|Fx Fy A B n [skip]", mgls_flame2d, 4},
+	{"fplot",_("Plot curve by formula"),"fplot 'y(x)' ['fmt']|'x(t)' 'y(t)' 'z(t)' ['fmt']", mgls_fplot ,1},
+	{"fsurf",_("Plot surface by formula"),"fsurf 'z(x,y)' ['fmt']|'x(u,v)' 'y(u,v)' 'z(u,v)' ['fmt']", mgls_fsurf ,1},
+	{"grid",_("Draw grid"),"grid ['dir' 'fmt']", mgls_grid ,12},
+	{"ifs2d",_("Computes the attractor of an IFS"), "ifs2d F A n [skip]|Fx Fy A n [skip]", mgls_ifs2d, 4},
+	{"ifs3d",_("Computes the attractor of an IFS for 3d case"), "ifs3d F A n [skip]", mgls_ifs3d, 4},
+	{"ifsfile",_("Computes the attractor of an IFS with parameters from *.ifs file"), "ifsfile F 'fname' 'name' n [skip]", mgls_ifsfile, 4},
+	{"legend",_("Draw legend"),"legend [pos 'fmt']|x y ['fmt']", mgls_legend ,15},
+	{"line",_("Draw line"),"line x1 y1 x2 y2 ['fmt']|x1 y1 z1 x2 y2 z2 ['fmt']", mgls_line ,13},
+	{"logo",_("Draw bitmap (logo) along axis range"),"logo 'fname' [smooth]", mgls_logo ,13},
+	{"polygon",_("Draw polygon"),"polygon x1 y1 x2 y2 num ['fmt']|x1 y1 z1 x2 y2 z2 num ['fmt']", mgls_polygon ,13},
+	{"rect",_("Draw rectangle"),"rect x1 y1 x2 y2 ['fmt']|x1 y1 z1 x2 y2 z2 ['fmt']", mgls_rect ,13},
+	{"rhomb",_("Draw rhombus"),"rhomb x1 y1 x2 y2 r ['fmt']|x1 y1 z1 x2 y2 z2 r ['fmt']", mgls_rhomb ,13},
+	{"sphere",_("Draw sphere"),"sphere x0 y0 r ['fmt']|x0 y0 z0 r ['fmt']", mgls_sphere ,13},
+	{"symbol",_("Draw user-defined symbol at given position and direction"),"symbol x y 'id' ['fmt' size]|x y z 'id' ['fmt' size]|x y dx dy 'id' ['fmt' size]|x y z dx dy dz 'id' ['fmt' size]", mgls_symbol ,15},
+	{"text",_("Draw text at some position or along curve"),"text x y 'txt' ['fmt' size]|x y z 'txt' ['fmt' size]|x y dx dy 'txt' ['fmt' size]|x y z dx dy dz 'txt' ['fmt' size]|Ydat 'txt' ['font']|Xdat Ydat 'txt' ['font']|Xdat Ydat Zdat 'txt' ['font']", mgls_text ,15},
+	{"title",_("Add title for current subplot/inplot"),"title 'txt' ['fmt' size]", mgls_title ,5},
+	{"tlabel",_("Draw label for t-axis"),"tlabel 'txt' [pos]", mgls_tlabel ,12},
+	{"xlabel",_("Draw label for x-axis"),"xlabel 'txt' [pos]", mgls_xlabel ,12},
+	{"ylabel",_("Draw label for y-axis"),"ylabel 'txt' [pos]", mgls_ylabel,12},
+	{"zlabel",_("Draw label for z-axis"),"zlabel 'txt' [pos]", mgls_zlabel,12},
+{"","","",NULL,0}};
+//-----------------------------------------------------------------------------
diff --git a/src/exec_set.cpp b/src/exec_set.cpp
new file mode 100644
index 0000000..eeea1bd
--- /dev/null
+++ b/src/exec_set.cpp
@@ -0,0 +1,762 @@
+/***************************************************************************
+ * exec_set.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#ifdef WIN32
+#include <io.h>
+#include <direct.h>
+#else
+#include <unistd.h>
+#endif
+
+#include "mgl2/base.h"
+#include "mgl2/parser.h"
+#pragma GCC diagnostic ignored "-Wmisleading-indentation"
+wchar_t *mgl_str_copy(const char *s);
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_addlegend(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"ss"))	gr->AddLegend(a[0].w.c_str(),a[1].s.c_str());
+	else	res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_addsymbol(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"sdd"))	gr->DefineSymbol(a[0].s[0],*(a[1].d),*(a[2].d));
+	else	res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_adjust(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]==0)	gr->Adjust();
+	else if(!strcmp(k,"s"))	gr->Adjust(a[0].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_alpha(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]==0)	gr->Alpha(true);
+	else if(!strcmp(k,"n"))	gr->Alpha(a[0].v!=0);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_alphadef(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->SetAlphaDef(a[0].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_ambient(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->SetAmbient(a[0].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_arrowsize(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->SetArrowSize(a[0].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_aspect(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"nn"))	gr->Aspect(a[0].v, a[1].v, 1);
+	else if(!strcmp(k,"nnn"))	gr->Aspect(a[0].v, a[1].v, a[2].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_attachlight(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->AttachLight(a[0].v!=0);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_axisstl(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]==0)	gr->SetAxisStl();
+	else if(!strcmp(k,"s"))	gr->SetAxisStl(a[0].s.c_str());
+	else if(!strcmp(k,"ss"))	gr->SetAxisStl(a[0].s.c_str(), a[1].s.c_str());
+	else if(!strcmp(k,"sss"))	gr->SetAxisStl(a[0].s.c_str(), a[1].s.c_str(), a[2].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_barwidth(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->SetBarWidth(a[0].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_bbox(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"nn") && a[1].v>=0 && a[0].v>=0)
+		gr->SetBBox(mgl_int(a[0].v), mgl_int(a[1].v));
+	else if(!strcmp(k,"nnnn"))
+		gr->SetBBox(mgl_int(a[0].v), mgl_int(a[1].v), mgl_int(a[2].v), mgl_int(a[3].v));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_chdir(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"s"))
+	{	if(chdir(a[0].s.c_str()))	gr->SetWarn(mglWarnFile,"chdir");	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_clearlegend(mglGraph *gr, long , mglArg *, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]==0)	gr->ClearLegend();
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_clf(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]==0)	gr->Clf();
+	else if(!strcmp(k,"s"))	gr->Clf(a[0].s.c_str());
+	else if(!strcmp(k,"nnn"))	gr->Clf(a[0].v,a[1].v,a[2].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_columnplot(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"nn"))	gr->ColumnPlot(mgl_int(a[0].v), mgl_int(a[1].v));
+	else if(!strcmp(k,"nnn"))	gr->ColumnPlot(mgl_int(a[0].v), mgl_int(a[1].v), a[2].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_crange(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->SetRange('c',*(a[0].d));
+	else if(!strcmp(k,"dn"))	gr->SetRange('c',*(a[0].d),a[1].v);
+	else if(!strcmp(k,"nn"))	gr->SetRange('c', a[0].v, a[1].v);
+	else if(!strcmp(k,"nnn"))
+	{
+		if(a[2].v)	gr->AddRange('c', a[0].v, a[1].v);
+		else	gr->SetRange('c', a[0].v, a[1].v);
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_ctick(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"s"))	gr->SetTickTempl('c',a[0].w.c_str());
+	else if(!strcmp(k,"n"))	gr->SetTicks('c',a[0].v,0,0);
+	else if(!strcmp(k,"ns"))	gr->SetTicks('c',a[0].v,0,0,a[1].w.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_cut(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->SetCut(a[0].v != 0);
+	else if(!strcmp(k,"nnnnnn"))
+		gr->SetCutBox(mglPoint(a[0].v,a[1].v,a[2].v), mglPoint(a[3].v,a[4].v,a[5].v));
+	else if(!strcmp(k,"s"))	gr->CutOff(a[0].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_diffuse(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->SetDiffuse(a[0].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_drawreg(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]==0)	gr->SetDrawReg();
+	else if(!strcmp(k,"nnn"))	gr->SetDrawReg(mgl_int(a[0].v), mgl_int(a[1].v), mgl_int(a[2].v));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_facenum(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->SetFaceNum(a[0].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_fog(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->Fog(a[0].v);
+	else if(!strcmp(k,"nn"))	gr->Fog(a[0].v,a[1].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_font(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"s"))	gr->SetFontDef(a[0].s.c_str());
+	else if(!strcmp(k,"sn"))
+	{	gr->SetFontDef(a[0].s.c_str());	gr->SetFontSize(a[1].v);	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_gray(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]==0)	gr->Gray(true);
+	else if(!strcmp(k,"n"))	gr->Gray(a[0].v!=0);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_gridplot(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"nnn"))	gr->GridPlot(mgl_int(a[0].v), mgl_int(a[1].v), mgl_int(a[2].v));
+	else if(!strcmp(k,"nnnn"))	gr->GridPlot(mgl_int(a[0].v), mgl_int(a[1].v), mgl_int(a[2].v), a[3].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_inplot(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"nnnn"))	gr->InPlot(a[0].v, a[1].v, a[2].v, a[3].v);
+	else if(!strcmp(k,"nnnnn"))	gr->InPlot(a[0].v, a[1].v, a[2].v, a[3].v, a[4].v!=0);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_legendmarks(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->SetLegendMarks(mgl_int(a[0].v));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_light(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]==0)	gr->Light(true);
+	else if(!strcmp(k,"n"))	gr->Light(a[0].v!=0);
+	else if(!strcmp(k,"nn"))	gr->Light(mgl_int(a[0].v),a[1].v!=0);
+	else if(!strcmp(k,"nnnn"))	gr->AddLight(mgl_int(a[0].v),mglPoint(a[1].v,a[2].v,a[3].v));
+	else if(!strcmp(k,"nnnns"))	gr->AddLight(mgl_int(a[0].v),mglPoint(a[1].v,a[2].v,a[3].v), a[4].s.c_str()[0]);
+	else if(!strcmp(k,"nnnnsn"))gr->AddLight(mgl_int(a[0].v),mglPoint(a[1].v,a[2].v,a[3].v), a[4].s.c_str()[0],a[5].v);
+	else if(!strcmp(k,"nnnnsnn"))
+		gr->AddLight(mgl_int(a[0].v), mglPoint(a[1].v,a[2].v,a[3].v), a[4].s.c_str()[0],a[5].v,a[6].v);
+	else if(!strcmp(k,"nnnnnnn"))
+		gr->AddLight(mgl_int(a[0].v), mglPoint(a[1].v,a[2].v,a[3].v), mglPoint(a[4].v,a[5].v,a[6].v));
+	else if(!strcmp(k,"nnnnnnns"))
+		gr->AddLight(mgl_int(a[0].v), mglPoint(a[1].v,a[2].v,a[3].v), mglPoint(a[4].v,a[5].v,a[6].v), a[7].s.c_str()[0]);
+	else if(!strcmp(k,"nnnnnnnsn"))
+		gr->AddLight(mgl_int(a[0].v), mglPoint(a[1].v,a[2].v,a[3].v), mglPoint(a[4].v,a[5].v,a[6].v), a[7].s.c_str()[0],a[8].v);
+	else if(!strcmp(k,"nnnnnnnsnn"))
+		gr->AddLight(mgl_int(a[0].v), mglPoint(a[1].v,a[2].v,a[3].v), mglPoint(a[4].v,a[5].v,a[6].v), a[7].s.c_str()[0],a[8].v,a[9].v);
+	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_load(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"s") && gr->pr)	mgl_parser_load(gr->pr, a[0].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_loadfont(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]==0 || (!strcmp(k,"s") && a[0].s[0]==0))	gr->RestoreFont();
+	else if(!strcmp(k,"s"))	gr->LoadFont(a[0].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_marksize(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->SetMarkSize(a[0].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_mask(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"sn"))	gr->SetMask(a[0].s[0],a[1].v);
+	else if(!strcmp(k,"ss"))	gr->SetMask(a[0].s[0],a[1].s.c_str());
+	else if(!strcmp(k,"n"))		gr->SetMaskAngle(mgl_int(a[0].v));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_meshnum(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->SetMeshNum(a[0].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_multiplot(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"nnnnn"))
+		gr->MultiPlot(mgl_int(a[0].v), mgl_int(a[1].v), mgl_int(a[2].v), mgl_int(a[3].v), mgl_int(a[4].v));
+	else if(!strcmp(k,"nnnnns"))
+		gr->MultiPlot(mgl_int(a[0].v), mgl_int(a[1].v), mgl_int(a[2].v), mgl_int(a[3].v), mgl_int(a[4].v), a[5].s.c_str());
+	else if(!strcmp(k,"nnnnnsnn"))
+		gr->MultiPlot(mgl_int(a[0].v), mgl_int(a[1].v), mgl_int(a[2].v), mgl_int(a[3].v), mgl_int(a[4].v), a[5].s.c_str(), a[6].v,a[7].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_origin(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"nn"))	gr->SetOrigin(a[0].v,a[1].v,NAN);
+	else if(!strcmp(k,"nnn"))	gr->SetOrigin(a[0].v,a[1].v,a[2].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_origintick(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->SetOriginTick(a[0].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_palette(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"s"))	gr->SetPalette(a[0].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_pendelta(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->SetPenDelta(a[0].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_perspective(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->Perspective(a[0].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_plotid(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"s"))	gr->SetPlotId(a[1].s.c_str());
+	else  res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_quality(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]==0)	gr->SetQuality();
+	else if(!strcmp(k,"n"))	gr->SetQuality(mgl_int(a[0].v));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_ranges(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"nnnn"))	gr->SetRanges(a[0].v,a[1].v, a[2].v,a[3].v);
+	else if(!strcmp(k,"nnnnnn"))gr->SetRanges(a[0].v,a[1].v,a[2].v, a[3].v,a[4].v,a[5].v);
+	else if(!strcmp(k,"dd"))	gr->SetRanges(*(a[0].d),*(a[1].d));
+	else if(!strcmp(k,"ddd"))	gr->SetRanges(*(a[0].d),*(a[1].d), *(a[2].d));
+	else if(!strcmp(k,"dddd"))	gr->SetRanges(*(a[0].d),*(a[1].d), *(a[2].d),*(a[3].d));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_rasterize(mglGraph *gr, long , mglArg *, const char *, const char *)
+{
+	gr->Rasterize();	return 0;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_reset(mglGraph *gr, long , mglArg *, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]==0)	gr->DefaultPlotParam();
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_rotate(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"nn"))	gr->Rotate(a[0].v, a[1].v, 0);
+	else if(!strcmp(k,"nnn"))	gr->Rotate(a[0].v, a[1].v, a[2].v);
+	else if(!strcmp(k,"nnnn"))	gr->RotateN(a[0].v, a[1].v, a[2].v, a[3].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_rotatetext(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->SetRotatedText(a[0].v!=0);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_setsize(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"nn") && a[1].v>1 && a[0].v>1)
+		gr->SetSize(mgl_int(a[0].v), mgl_int(a[1].v));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_setsizescl(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->SetSizeScl(a[0].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_shear(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"nn"))	gr->Shear(a[0].v, a[1].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_shearplot(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"nnnn"))	gr->ShearPlot(mgl_int(a[0].v), mgl_int(a[1].v), a[2].v, a[3].v);
+	else if(!strcmp(k,"nnnnnn"))	gr->ShearPlot(mgl_int(a[0].v), mgl_int(a[1].v), a[2].v, a[3].v, a[4].v, a[5].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_stickplot(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"nnnn"))	gr->StickPlot(mgl_int(a[0].v), mgl_int(a[1].v), a[2].v, a[3].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_subplot(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"nnn"))	gr->SubPlot(mgl_int(a[0].v), mgl_int(a[1].v), mgl_int(a[2].v));
+	else if(!strcmp(k,"nnns"))	gr->SubPlot(mgl_int(a[0].v), mgl_int(a[1].v), mgl_int(a[2].v), a[3].s.c_str());
+	else if(!strcmp(k,"nnnsnn"))	gr->SubPlot(mgl_int(a[0].v), mgl_int(a[1].v), mgl_int(a[2].v), a[3].s.c_str(), a[4].v,a[5].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_ternary(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->Ternary(int(a[0].v));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_ticklen(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->SetTickLen(a[0].v);
+	else if(!strcmp(k,"nn"))	gr->SetTickLen(a[0].v, a[1].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_tickshift(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->SetTickShift(mglPoint(a[0].v));
+	else if(!strcmp(k,"nn"))	gr->SetTickShift(mglPoint(a[0].v, a[1].v));
+	else if(!strcmp(k,"nnn"))	gr->SetTickShift(mglPoint(a[0].v, a[1].v, a[2].v));
+	else if(!strcmp(k,"nnnn"))	gr->SetTickShift(mglPoint(a[0].v, a[1].v, a[2].v, a[3].v));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_ticktime(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"s"))	gr->SetTicksTime(a[0].s[0]);
+	else if(!strcmp(k,"sn"))	gr->SetTicksTime(a[0].s[0],a[1].v);
+	else if(!strcmp(k,"sns"))	gr->SetTicksTime(a[0].s[0],a[1].v,a[2].s.c_str());
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_transptype(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->SetTranspType(a[0].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_tuneticks(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->SetTuneTicks(mgl_int(a[0].v));
+	else if(!strcmp(k,"nn"))	gr->SetTuneTicks(mgl_int(a[0].v),a[1].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_variant(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n") && gr->pr)	mgl_parser_variant(gr->pr, a[0].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_version(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	char buf[32];	sprintf(buf,"MathGL version is 2.%g",MGL_VER2);
+	if(k[0]==0)	gr->SetWarn(-1,buf);
+	else if(!strcmp(k,"s"))	res = mgl_check_version(a[0].s.c_str())?1:0;
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_view(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"nn"))		gr->View(a[0].v, a[1].v);
+	else if(!strcmp(k,"nnn"))	gr->View(a[0].v, a[1].v, a[2].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_write(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(k[0]==0)	gr->WriteFrame("", "MathGL");
+	else if(!strcmp(k,"s"))	gr->WriteFrame(a[0].s.c_str(), "MathGL");
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_xrange(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->SetRange('x',*(a[0].d));
+	else if(!strcmp(k,"dn"))	gr->SetRange('x',*(a[0].d),a[1].v);
+	else if(!strcmp(k,"nn"))	gr->SetRange('x', a[0].v, a[1].v);
+	else if(!strcmp(k,"nnn"))
+	{
+		if(a[2].v)	gr->AddRange('x', a[0].v, a[1].v);
+		else	gr->SetRange('x', a[0].v, a[1].v);
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_xtick(mglGraph *gr, long n, mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->SetTicks('x', a[0].v);
+//	else if(!strcmp(k,"ns"))	gr->SetTicks('x', a[0].v, 0, NAN, a[1].w.c_str());
+	else if(!strcmp(k,"nn"))	gr->SetTicks('x', a[0].v, mgl_int(a[1].v));
+	else if(!strcmp(k,"nns"))	gr->SetTicks('x', a[0].v, mgl_int(a[1].v), NAN, a[2].w.c_str());
+	else if(!strcmp(k,"nnn"))	gr->SetTicks('x', a[0].v, mgl_int(a[1].v), a[2].v);
+	else if(!strcmp(k,"nnns"))	gr->SetTicks('x', a[0].v, mgl_int(a[1].v), a[2].v, a[3].w.c_str());
+	else if(!strcmp(k,"s"))		gr->SetTickTempl('x',a[0].w.c_str());
+	else if(!strcmp(k,"ds"))	gr->SetTicksVal('x', *(a[0].d), a[1].w.c_str());
+	else if(!strcmp(k,"dsn"))	gr->SetTicksVal('x', *(a[0].d), a[1].w.c_str(), a[2].v);
+	else if(!strncmp(k,"ns",2))
+	{
+		std::wstring s;
+		std::vector<mreal> v;
+		for(long i=0;i<n/2;i++)
+		{
+			if(a[2*i].type==2 && a[2*i+1].type==1)
+			{	v.push_back(a[2*i].v);	s += a[2*i+1].w+L"\n";	}
+			else	break;
+		}
+		gr->SetTicksVal('x',mglDataS(v),s.c_str(),v.size()==1?true:false);
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_yrange(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->SetRange('y',*(a[0].d));
+	else if(!strcmp(k,"dn"))	gr->SetRange('y',*(a[0].d),a[1].v);
+	else if(!strcmp(k,"nn"))	gr->SetRange('y', a[0].v, a[1].v);
+	else if(!strcmp(k,"nnn"))
+	{
+		if(a[2].v)	gr->AddRange('y', a[0].v, a[1].v);
+		else	gr->SetRange('y', a[0].v, a[1].v);
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_ytick(mglGraph *gr, long n, mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->SetTicks('y', a[0].v);
+//	else if(!strcmp(k,"ns"))	gr->SetTicks('y', a[0].v, 0, NAN, a[1].w.c_str());
+	else if(!strcmp(k,"nn"))	gr->SetTicks('y', a[0].v, mgl_int(a[1].v));
+	else if(!strcmp(k,"nns"))	gr->SetTicks('y', a[0].v, mgl_int(a[1].v), NAN, a[2].w.c_str());
+	else if(!strcmp(k,"nnn"))	gr->SetTicks('y', a[0].v, mgl_int(a[1].v), a[2].v);
+	else if(!strcmp(k,"nnns"))	gr->SetTicks('y', a[0].v, mgl_int(a[1].v), a[2].v, a[3].w.c_str());
+	else if(!strcmp(k,"s"))		gr->SetTickTempl('y',a[0].w.c_str());
+	else if(!strcmp(k,"ds"))	gr->SetTicksVal('y', *(a[0].d), a[1].w.c_str());
+	else if(!strcmp(k,"dsn"))	gr->SetTicksVal('y', *(a[0].d), a[1].w.c_str(), a[2].v);
+	else if(!strncmp(k,"ns",2))
+	{
+		std::wstring s;
+		std::vector<mreal> v;
+		for(long i=0;i<n/2;i++)
+		{
+			if(a[2*i].type==2 && a[2*i+1].type==1)
+			{	v.push_back(a[2*i].v);	s += a[2*i+1].w+L"\n";	}
+			else	break;
+		}
+		gr->SetTicksVal('y',mglDataS(v),s.c_str(),v.size()==1?true:false);
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_zoom(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"nnnn"))	gr->Zoom(a[0].v, a[1].v, a[2].v, a[3].v);
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_zoomaxis(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"nn"))	gr->ZoomAxis(mglPoint(a[0].v), mglPoint(a[1].v));
+	else if(!strcmp(k,"nnnn"))	gr->ZoomAxis(mglPoint(a[0].v, a[1].v), mglPoint(a[2].v, a[3].v));
+	else if(!strcmp(k,"nnnnnn"))	gr->ZoomAxis(mglPoint(a[0].v, a[1].v, a[2].v), mglPoint(a[3].v, a[4].v, a[5].v));
+	else if(!strcmp(k,"nnnnnnnn"))	gr->ZoomAxis(mglPoint(a[0].v, a[1].v, a[2].v, a[3].v), mglPoint(a[4].v, a[5].v, a[6].v, a[7].v));
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_zrange(mglGraph *gr, long , mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"d"))	gr->SetRange('z',*(a[0].d));
+	else if(!strcmp(k,"dn"))	gr->SetRange('z',*(a[0].d),a[1].v);
+	else if(!strcmp(k,"nn"))	gr->SetRange('z', a[0].v, a[1].v);
+	else if(!strcmp(k,"nnn"))
+	{
+		if(a[2].v)	gr->AddRange('z', a[0].v, a[1].v);
+		else	gr->SetRange('z', a[0].v, a[1].v);
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgls_ztick(mglGraph *gr, long n, mglArg *a, const char *k, const char *)
+{
+	int res=0;
+	if(!strcmp(k,"n"))	gr->SetTicks('z', a[0].v);
+//	else if(!strcmp(k,"ns"))	gr->SetTicks('z', a[0].v, 0, NAN, a[1].w.c_str());
+	else if(!strcmp(k,"nn"))	gr->SetTicks('z', a[0].v, mgl_int(a[1].v));
+	else if(!strcmp(k,"nns"))	gr->SetTicks('z', a[0].v, mgl_int(a[1].v), NAN, a[2].w.c_str());
+	else if(!strcmp(k,"nnn"))	gr->SetTicks('z', a[0].v, mgl_int(a[1].v), a[2].v);
+	else if(!strcmp(k,"nnns"))	gr->SetTicks('z', a[0].v, mgl_int(a[1].v), a[2].v, a[3].w.c_str());
+	else if(!strcmp(k,"s"))		gr->SetTickTempl('z',a[0].w.c_str());
+	else if(!strcmp(k,"ds"))	gr->SetTicksVal('z', *(a[0].d), a[1].w.c_str());
+	else if(!strcmp(k,"dsn"))	gr->SetTicksVal('z', *(a[0].d), a[1].w.c_str(), a[2].v);
+	else if(!strncmp(k,"ns",2))
+	{
+		std::wstring s;
+		std::vector<mreal> v;
+		for(long i=0;i<n/2;i++)
+		{
+			if(a[2*i].type==2 && a[2*i+1].type==1)
+			{	v.push_back(a[2*i].v);	s += a[2*i+1].w+L"\n";	}
+			else	break;
+		}
+		gr->SetTicksVal('z',mglDataS(v),s.c_str(),v.size()==1?true:false);
+	}
+	else res = 1;	return res;
+}
+//-----------------------------------------------------------------------------
+mglCommand mgls_set_cmd[] = {
+	{"addlegend",_("Add legend entry"),"addlegend 'txt' 'fmt'", mgls_addlegend,15},
+	{"addsymbol",_("Add user-defined symbol"),"addsymbol 'id' Xdat Ydat", mgls_addsymbol,15},
+	{"adjust",_("Adjust ticks for best view"),"adjust ['dir']", mgls_adjust ,14},
+	{"alpha",_("Switch on/off transparency"),"alpha [val]", mgls_alpha ,2},
+	{"alphadef",_("Set default transparency"),"alphadef val", mgls_alphadef ,2},
+	{"ambient",_("Set ambient light brightness"),"ambient val", mgls_ambient ,2},
+	{"arrowsize",_("Set size of arrows"),"arrowsize val", mgls_arrowsize ,2},
+	{"aspect",_("Set aspect ration"),"aspect valx valy [valz]", mgls_aspect ,5},
+	{"attachlight",_("Attach light settings to inplot"),"attachlight val", mgls_attachlight ,2},
+	{"axisstl",_("Set axis and tick style"),"axisstl 'stl' ['tick' 'sub']", mgls_axisstl ,14},
+	{"barwidth",_("Set default bars width"),"barwidth val", mgls_barwidth ,2},
+	{"bbox",_("Set bounding box for 2d export"),"bbox x1 y1 [x2 y2]", mgls_bbox ,2},
+	{"chdir",_("Change current directory"),"chdir 'path'", mgls_chdir ,2},
+	{"clearlegend",_("Clear legend entries"),"clearlegend", mgls_clearlegend ,15},
+	{"clf",_("Clear picture"),"clf|'col'|r g b", mgls_clf ,12},
+	{"columnplot",_("Set position of plot inside cell of column"), "columnplot num ind [d]", mgls_columnplot ,5},
+	{"crange",_("Set color range"),"crange Dat [add]|c1 c2 [add]", mgls_crange ,14},
+	{"ctick",_("Set ticks for colorbar"),"ctick 'tmpl'|dc ['factor']", mgls_ctick ,14},
+	{"cut",_("Setup plot points cutting"),"cut val|x1 y1 z1 x2 y2 z2|'cond'", mgls_cut ,2},
+	{"diffuse",_("Set diffusive light brightness"),"diffuse val", mgls_diffuse ,2},
+	{"drawreg",_("Set draw region for quality&4"),"drawreg|nx ny m", mgls_drawreg ,2},
+	{"facenum",_("Set number of visible faces"),"facenum val", mgls_facenum ,2},
+	{"fog",_("Switch on/off fog"),"fog val [dz]", mgls_fog ,2},
+	{"font",_("Setup font"),"font 'fmt' [size]", mgls_font ,15},
+	{"gray",_("Switch on/off gray-scale mode"),"gray [val]", mgls_gray ,2},
+	{"gridplot",_("Set position of plot inside cell of matrix"), "gridplot nx ny ind [d]", mgls_gridplot ,5},
+	{"inplot",_("Set arbitrary position of plot in picture"),"x1 x2 y1 y2 [rel]", mgls_inplot ,5},
+	{"legendmarks",_("Set number of marks in the legend"),"legendmarks val", mgls_legendmarks ,15},
+	{"light",_("Setup light"),"light [val]|num val|num xpos ypos zpos ['fmt' br ap]|num xpos ypos zpos px py pz ['fmt' br ap]", mgls_light ,2},
+	{"load",_("Load commands from external DLL"),"load 'fname'", mgls_load, 6},
+	{"loadfont",_("Load fontfaces"),"loadfont ['face']", mgls_loadfont ,15},
+	{"marksize",_("Set size of markers"),"marksize val", mgls_marksize ,2},
+	{"mask",_("Set brush for given mask id"),"mask 'id' 'val'|'id' val|angle", mgls_mask ,2},
+	{"meshnum",_("Set number of lines in mesh/fall/vect and so on"),"meshnum val", mgls_meshnum ,2},
+	{"multiplot",_("Set position of plot block in matrix"),"multiplot m n pos dx dy 'style' [sx sy]", mgls_multiplot ,5},
+	{"origin",_("Set axis origin"),"origin x0 y0 [z0]", mgls_origin ,14},
+	{"origintick",_("Set tick labels drawing at origin"),"origintick val", mgls_origintick ,14},
+	{"palette",_("Set palette for 1D plots"),"palette 'colors'", mgls_palette ,2},
+	{"pendelta",_("Set size of semi-transparent area around line"),"pendelta val", mgls_pendelta ,2},
+	{"perspective",_("Set perspective"),"perspective val", mgls_perspective ,2},
+	{"plotid",_("Set default filename"),"plotid 'name'", mgls_plotid ,2},
+	{"quality",_("Set plot quality"),"quality [val]", mgls_quality ,2},
+	{"ranges",_("Set axis ranges"),"ranges x1 x2 y1 y2 [z1 z2]|Xdat Ydat [Zdat Cdat]", mgls_ranges ,14},
+	{"rasterize",_("Rasterize plot and save to background"),"rasterize", mgls_rasterize ,12},
+	{"reset",_("Reset settings and clear picture"),"reset", mgls_reset ,12},
+	{"rotate",_("Rotate plot"),"rotate tetz tetx [tety]|tet x y z", mgls_rotate ,5},
+	{"rotatetext",_("Set to auto rotate text or not"),"rotatetext val", mgls_rotatetext ,15},
+	{"setsize",_("Set picture size"),"setsize width height", mgls_setsize ,2},
+	{"setsizescl",_("Set scaling factor for further setsize"),"setsizescl val", mgls_setsizescl ,2},
+	{"shear",_("Shear plot"),"shear valx valy", mgls_shear ,5},
+	{"shearplot",_("Set position of plot inside cell of sheared stick"), "shearplot num ind sx sy [xd yd]", mgls_shearplot ,5},
+	{"stickplot",_("Set position of plot inside cell of rotated stick"), "stickplot num ind tet phi", mgls_stickplot ,5},
+	{"subplot",_("Set position of plot as cell of matrix"),"subplot m n pos ['style' dx dy]", mgls_subplot ,5},
+	{"ternary",_("Switch on/off to use ternary axis"),"ternary val", mgls_ternary ,14},
+	{"ticklen",_("Set tick length"),"ticklen val [stt]", mgls_ticklen ,14},
+	{"tickshift",_("Set additional tick and axis labels shift"),"tickshift dx [dy dz dc]", mgls_tickshift ,14},
+	{"ticktime",_("Set ticks in time format"),"ticktime 'dir' [dv 'tmpl']", mgls_ticktime ,14},
+	{"transptype",_("Set type transparency"),"transptype val", mgls_transptype ,2},
+	{"tuneticks",_("Set ticks tuning"),"tuneticks val [pos]", mgls_tuneticks ,14},
+	{"variant",_("Select variant of plot style(s)"),"variant var", mgls_variant, 6},
+	{"version",_("Print MathGL version or check if it is valid"),"version ['ver']", mgls_version, 2},
+	{"view",_("Change view angles - use 'rotate' for plot rotation"),"view tetz tetx [tety]", mgls_view ,5},
+	{"write",_("Write current image to graphical file"),"write ['fname']", mgls_write ,2},
+	{"xrange",_("Set range for x-axis"),"xrange Dat [add]|x1 x2 [add]", mgls_xrange ,14},
+	{"xtick",_("Set ticks for x-axis"),"xtick dx ['factor']|dx sx ['factor']|dx sx tx ['factor']|'tmpl'|Xdat 'lbl' [add]|v1 'lbl1' ...", mgls_xtick,14},
+	{"yrange",_("Set range for y-axis"),"yrange Dat [add]|y1 y2 [add]", mgls_yrange,14},
+	{"ytick",_("Set ticks for y-axis"),"ytick dy ['factor']|dy sy ['factor']|dy sy ty ['factor']|'tmpl'|Ydat 'lbl' [add]|v1 'lbl1' ...", mgls_ytick,14},
+	{"zoom",_("Zoom plot region"),"zoom x1 x2 y1 y2", mgls_zoom,5},
+	{"zoomaxis",_("Zoom axis range"),"zoomaxis x1 x2|x1 y1 x2 y2|x1 y1 z1 x2 y2 z2|x1 y1 z1 c1 x2 y2 z2 c2", mgls_zoomaxis,14},
+	{"zrange",_("Set range for z-axis"),"yrange Dat [add]|z1 z2 [add]", mgls_zrange ,14},
+	{"ztick",_("Set ticks for z-axis"),"ztick dz ['factor']|dz sz ['factor']|dz sz tz ['factor']|'tmpl'|Zdat 'lbl' [add]|v1 'lbl1' ...", mgls_ztick,14},
+{"","","",NULL,0}};
+//-----------------------------------------------------------------------------
diff --git a/src/export.cpp b/src/export.cpp
new file mode 100644
index 0000000..f18dca9
--- /dev/null
+++ b/src/export.cpp
@@ -0,0 +1,645 @@
+/***************************************************************************
+ * export.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <time.h>
+#include <stdarg.h>
+
+#if defined(WIN32) || defined(_MSC_VER) || defined(__BORLANDC__)
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
+#include "mgl2/canvas.h"
+#include "mgl2/canvas_cf.h"
+
+#if MGL_HAVE_PNG
+#include <png.h>
+#endif
+
+#if MGL_HAVE_JPEG
+extern "C" {
+#include <jpeglib.h>
+}
+#endif
+
+#if MGL_HAVE_GIF
+#include <gif_lib.h>
+#endif
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgl_pnga_save(const char *fname, int w, int h, unsigned char **p)
+{
+#if MGL_HAVE_PNG
+	bool fl = strcmp(fname,"-");
+	FILE *fp = fl ? fopen(fname, "wb") : stdout;
+	if (!fp)	return 1;
+
+	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0);
+	if (png_ptr)
+	{
+		png_infop info_ptr = png_create_info_struct(png_ptr);
+		if (info_ptr)
+		{
+			png_init_io(png_ptr, fp);
+			png_set_filter(png_ptr, 0, PNG_ALL_FILTERS);
+			png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
+			png_set_IHDR(png_ptr, info_ptr, w, h, 8,
+						PNG_COLOR_TYPE_RGB_ALPHA,
+						PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
+						PNG_FILTER_TYPE_DEFAULT);
+			png_set_rows(png_ptr, info_ptr, p);
+			png_write_png(png_ptr, info_ptr,  PNG_TRANSFORM_IDENTITY, 0);
+			png_write_end(png_ptr, info_ptr);
+		}
+		png_destroy_write_struct(&png_ptr, &info_ptr);
+	}
+	if(fl)	fclose(fp);
+	return 0;
+#else
+	mgl_set_global_warn(_("PNG support was disabled. Please, enable it and rebuild MathGL."));
+	return 1;
+#endif
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgl_png_save(const char *fname, int w, int h, unsigned char **p)
+{
+#if MGL_HAVE_PNG
+	bool fl = strcmp(fname,"-");
+	FILE *fp = fl ? fopen(fname, "wb") : stdout;
+	if (!fp)	return 1;
+
+	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0);
+	if (png_ptr)
+	{
+		png_infop info_ptr = png_create_info_struct(png_ptr);
+		if (info_ptr)
+		{
+			png_init_io(png_ptr, fp);
+			png_set_filter(png_ptr, 0, PNG_ALL_FILTERS);
+			png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
+			png_set_IHDR(png_ptr, info_ptr, w, h, 8,
+						PNG_COLOR_TYPE_RGB,
+						PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
+						PNG_FILTER_TYPE_DEFAULT);
+			png_set_rows(png_ptr, info_ptr, p);
+			png_write_png(png_ptr, info_ptr,  PNG_TRANSFORM_IDENTITY, 0);
+			png_write_end(png_ptr, info_ptr);
+		}
+		png_destroy_write_struct(&png_ptr, &info_ptr);
+	}
+	if(fl)	fclose(fp);
+	return 0;
+#else
+	mgl_set_global_warn(_("PNG support was disabled. Please, enable it and rebuild MathGL."));
+	return 1;
+#endif
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgl_bmp_save(const char *fname, int w, int h, unsigned char **p)
+{
+	bool fl = strcmp(fname,"-");
+	FILE *fp = fl ? fopen(fname, "wb") : stdout;
+	if (!fp)	return 1;
+
+	char z[4] = {0,0,0,0};
+	unsigned u = w*h*3 + 54;
+	// BITMAPFILEHEADER
+	fwrite("BM",2,1,fp);	fwrite(&u,4,1,fp);
+	fwrite(z,4,1,fp);	u=54;	fwrite(&u,4,1,fp);
+	// BITMAPINFOHEADER
+	u=40;	fwrite(&u,4,1,fp);	fwrite(&w,4,1,fp);	fwrite(&h,4,1,fp);
+	unsigned short pp=1;
+	fwrite(&pp,2,1,fp);	pp=24;	fwrite(&pp,2,1,fp);	u = w*h*3;
+	fwrite(z,4,1,fp);	fwrite(&u,4,1,fp);
+	fwrite(z,4,1,fp);	fwrite(z,4,1,fp);
+	fwrite(z,4,1,fp);	fwrite(z,4,1,fp);
+	// image
+	for(long i=h-1;i>=0;i--)	for(long j=0;j<w;j++)
+	{
+		const unsigned char *q = p[i]+3*j;
+		fwrite(q+2,1,1,fp);
+		fwrite(q+1,1,1,fp);
+		fwrite(q+0,1,1,fp);
+	}
+	if(fl)	fclose(fp);
+	return 0;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgl_tga_save(const char *fname, int w, int h, unsigned char **p)
+{
+	bool fl = strcmp(fname,"-");
+	FILE *fp = fl ? fopen(fname, "wb") : stdout;
+	if (!fp)	return 1;
+	// header
+	char head[14]={0,0,2, 0,0,0,0,0, 0,0,0,0, 32,0};
+	fwrite(head,12,1,fp);
+	fwrite(&w,2,1,fp);	fwrite(&h,2,1,fp);
+	fwrite(head+12,2,1,fp);
+	// image
+	for(long i=h-1;i>=0;i--)	for(long j=0;j<w;j++)
+	{
+		const unsigned char *q = p[i]+4*j;
+		fwrite(q+2,1,1,fp);
+		fwrite(q+1,1,1,fp);
+		fwrite(q+0,1,1,fp);
+		fwrite(q+3,1,1,fp);
+	}
+	if(fl)	fclose(fp);
+	return 0;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgl_jpeg_save(const char *fname, int w, int h, unsigned char **p)
+{
+#if MGL_HAVE_JPEG
+	struct jpeg_compress_struct cinfo;
+	struct jpeg_error_mgr jerr;
+
+	bool fl = strcmp(fname,"-");
+	FILE *fp = fl ? fopen(fname, "wb") : stdout;
+	if (!fp)	return 1;
+
+	cinfo.err = jpeg_std_error(&jerr);
+	jpeg_create_compress(&cinfo);
+	jpeg_stdio_dest(&cinfo, fp);
+	cinfo.image_width = w;
+	cinfo.image_height = h;
+	cinfo.input_components = 3;
+	cinfo.in_color_space = JCS_RGB;
+	jpeg_set_defaults(&cinfo);
+	jpeg_start_compress(&cinfo, TRUE);
+	jpeg_write_scanlines(&cinfo, p, h);
+	jpeg_finish_compress(&cinfo);
+	jpeg_destroy_compress(&cinfo);
+	if(fl)	fclose(fp);
+	return 0;
+#else
+	mgl_set_global_warn(_("JPEG support was disabled. Please, enable it and rebuild MathGL."));
+	return 1;
+#endif
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_printf(void *fp, bool gz, const char *str, ...)	// NOTE This function is not thread-safe
+{
+	static char buf[1024];
+	va_list lst;
+	va_start(lst,str);
+	vsnprintf(buf,1023,str,lst);	buf[1023]=0;
+	va_end(lst);
+	if(gz)	gzprintf((gzFile)fp, "%s", buf);
+	else	fprintf((FILE *)fp, "%s", buf);
+}
+//---------------------------------------------------------------------------
+std::string MGL_NO_EXPORT mgl_sprintf(const char *str, ...)
+{
+	char *buf=new char[1024];
+	va_list lst;
+	va_start(lst,str);
+	vsnprintf(buf,1023,str,lst);	buf[1023]=0;
+	va_end(lst);
+	std::string res = buf;	delete []buf;
+	return res;
+}
+//---------------------------------------------------------------------------
+int MGL_NO_EXPORT mgl_bps_save(const char *fname, int w, int h, unsigned char **p)
+{
+	time_t now;	time(&now);
+	bool gz = fname[strlen(fname)-1]=='z';
+
+	void *fp;
+	if(!strcmp(fname,"-"))	fp = stdout;		// allow to write in stdout
+	else
+	{
+		fp = gz ? (void*)gzopen(fname,"wt") : (void*)fopen(fname,"wt");
+		if(gz)
+		{
+			unsigned len = strlen(fname), pos=0;
+			char *buf = new char[len+4];
+			memcpy(buf,fname,len);
+			if(buf[len-3]=='.')	pos = len-2;
+			else if(buf[len-2]=='.')	pos = len-1;
+			else	{	buf[len-1]='.';	pos = len;	}
+			if(pos)	{	buf[pos]=buf[pos+1]='b';	buf[pos+2]=0;	}
+			FILE *fb = fopen(buf,"w");
+			fprintf(fb, "%%%%BoundingBox: 0 0 %d %d\n", w, h);
+			fclose(fb);	delete []buf;
+		}
+	}
+	mgl_printf(fp, gz, "%%!PS-Adobe-3.0 EPSF-3.0\n%%%%BoundingBox: 0 0 %d %d\n",w,h);
+	mgl_printf(fp, gz, "%%%%Created by MathGL library\n%%%%Title: %s\n", fname);
+	mgl_printf(fp, gz, "%%%%CreationDate: %s\n",ctime(&now));
+	mgl_printf(fp, gz, "%d %d 8 [1 0 0 1 0 0] {currentfile %d string readhexstring pop} false 3 colorimage\n",
+			w,h,w*h/40);
+	for(long j=0;j<h;j++)	for(long i=0;i<w;i++)
+	{
+		if((i+w*j)%40==0 && i+j>0)	mgl_printf(fp, gz, "\n");
+		long jj=h-1-j;
+		mgl_printf(fp, gz, "%02x%02x%02x",p[jj][3*i],p[jj][3*i+1],p[jj][3*i+2]);
+	}
+	mgl_printf(fp, gz, "\n\nshowpage\n%%%%EOF\n");
+	if(strcmp(fname,"-"))	{	if(gz)	gzclose((gzFile)fp);	else	fclose((FILE *)fp);	}
+	return 0;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgl_gif_save(const char *fname, int w, int h, unsigned char **l)
+{
+#if MGL_HAVE_GIF
+#if GIFLIB_MAJOR>=5
+	GifFileType *fg = EGifOpenFileName(fname, 0, 0);
+#else
+	GifFileType *fg = EGifOpenFileName(fname, 0);
+#endif
+	// define colormap
+	GifColorType col[256];
+	memset(col,0,256*sizeof(GifColorType));
+	for(int i=0;i<6;i++)	for(int j=0;j<6;j++)	for(int k=0;k<6;k++)
+	{
+		long m = i+6*(j+6*k);		// part 1
+		col[m].Red = 51*i;
+		col[m].Green=51*j;
+		col[m].Blue =51*k;
+	}
+	// write header
+#if GIFLIB_MAJOR>=5
+	ColorMapObject *gmap = GifMakeMapObject(256, col);
+	EGifPutScreenDesc(fg, w, h, 256,0,gmap);
+	GifFreeMapObject(gmap);
+#else
+	ColorMapObject *gmap = MakeMapObject(256, col);
+	EGifPutScreenDesc(fg, w, h, 256,0,gmap);
+	FreeMapObject(gmap);
+#endif
+	// write frame
+	EGifPutImageDesc(fg, 0, 0, w, h, 0, 0);
+	GifPixelType *line = new GifPixelType[w*h];
+	for(long m=0;m<w*h;m++)
+	{
+		long ii = 3*(m%w), k = m/w;
+		int i = (l[k][ii]+25)/51;
+		int j = (l[k][ii+1]+25)/51;
+		k = (l[k][ii+2]+25)/51;
+		line[m] = i+6*(j+6*k);
+	}
+	EGifPutLine(fg, line, w*h);
+#if GIFLIB_MAJOR>5 || (GIFLIB_MAJOR==5 && GIFLIB_MINOR>0)
+	EGifCloseFile(fg,0);
+#else
+	EGifCloseFile(fg);
+#endif
+	delete []line;	return 0;
+#else
+	mgl_set_global_warn(_("GIF support was disabled. Please, enable it and rebuild MathGL."));
+	return 1;
+#endif
+}
+//-----------------------------------------------------------------------------
+//
+//		Save animation
+//
+//-----------------------------------------------------------------------------
+void mglCanvas::StartGIF(const char *fname, int ms)
+{
+#if MGL_HAVE_GIF
+	std::string fn=fname;
+	if(fn.empty())	{	fn=PlotId+".gif";	fname = fn.c_str();	}
+#if GIFLIB_MAJOR>5 || (GIFLIB_MAJOR==5 && GIFLIB_MINOR>0)
+	if(gif)	EGifCloseFile(gif,0);
+#else
+	if(gif)	EGifCloseFile(gif);
+#endif
+#if GIFLIB_MAJOR>=5
+	gif = EGifOpenFileName(fname, 0, 0);
+	EGifSetGifVersion(gif,true);
+#else
+	EGifSetGifVersion("89a");
+	gif = EGifOpenFileName(fname, 0);
+#endif
+	// get picture sizes
+	// NOTE: you shouldn't call SetSize() after StartGIF() !!!
+	long width, height;
+	unsigned char *f=0, **l=GetRGBLines(width, height, f);
+	if(f)	free(f);
+	if(l)	free(l);
+	// define colormap
+	GifColorType col[256];
+	memset(col,0,256*sizeof(GifColorType));
+	for(int i=0;i<6;i++)	for(int j=0;j<6;j++)	for(int k=0;k<6;k++)
+	{
+		long m = i+6*(j+6*k);		// part 1
+		col[m].Red = 51*i;
+		col[m].Green=51*j;
+		col[m].Blue =51*k;
+	}
+	// write header
+#if GIFLIB_MAJOR>=5
+	ColorMapObject *gmap = GifMakeMapObject(256, col);
+	EGifPutScreenDesc(gif, width, height, 256,0,gmap);
+	GifFreeMapObject(gmap);
+#else
+	ColorMapObject *gmap = MakeMapObject(256, col);
+	EGifPutScreenDesc(gif, width, height, 256,0,gmap);
+	FreeMapObject(gmap);
+#endif
+	// put animation parameters
+	ms /= 10;
+	unsigned char ext1[11] = {0x4E, 0x45, 0x54, 0x53, 0x43, 0x41, 0x50, 0x45, 0x32, 0x2E, 0x30};
+	unsigned char ext2[9] = {0x08, (unsigned char)(ms%256), (unsigned char)(ms/256), 0xff};
+	unsigned char ext3[3] = {0x01, 0xff, 0xff};
+#if GIFLIB_MAJOR>=5
+	EGifPutExtensionLeader(gif,0xff);
+	EGifPutExtensionBlock(gif,11,ext1);
+	EGifPutExtensionBlock(gif,3,ext3);
+	EGifPutExtensionTrailer(gif);
+	EGifPutExtension(gif,0xf9,4,ext2);
+#else
+	EGifPutExtensionFirst(gif,0xff,11,ext1);
+	EGifPutExtensionLast(gif,0xff,3,ext3);
+	EGifPutExtension(gif,0xf9,4,ext2);
+#endif
+#else
+	mgl_set_global_warn(_("GIF support was disabled. Please, enable it and rebuild MathGL."));
+#endif
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::CloseGIF()
+{
+#if MGL_HAVE_GIF
+#if GIFLIB_MAJOR>5 || (GIFLIB_MAJOR==5 && GIFLIB_MINOR>0)
+	if(gif)	EGifCloseFile(gif,0);
+#else
+	if(gif)	EGifCloseFile(gif);
+#endif
+#else
+	mgl_set_global_warn(_("GIF support was disabled. Please, enable it and rebuild MathGL."));
+#endif
+	gif = 0;
+}
+//-----------------------------------------------------------------------------
+int mglCanvas::NewFrame()
+{
+	Clf();	Identity();	CurFrameId++;
+	return CurFrameId-1;
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::EndFrame()
+{
+	Finish();
+	if(get(MGL_VECT_FRAME))	PushDrwDat();
+#if MGL_HAVE_GIF
+	if(!gif)	return;
+	long width, height, n;
+	unsigned char *f=0, **l=GetRGBLines(width, height, f);
+	n = width*height;
+	if(!l)	return;
+	EGifPutImageDesc(gif, 0, 0, width, height, 0, 0);
+	GifPixelType *line = new GifPixelType[n];
+	for(long m=0;m<n;m++)
+	{
+		long ii = 3*(m%width), k = m/width;
+		int i = (l[k][ii]+25)/51;
+		int j = (l[k][ii+1]+25)/51;
+		k = (l[k][ii+2]+25)/51;
+		line[m] = i+6*(j+6*k);
+	}
+	EGifPutLine(gif, line, n);
+	delete []line;	free(l);
+	if(f)	free(f);
+#endif
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::DelFrame(long i)
+{
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_lock(&mutexDrw);
+	if(get(MGL_VECT_FRAME))	DrwDat.erase(DrwDat.begin()+i);
+	pthread_mutex_unlock(&mutexDrw);
+#else
+#pragma omp critical(drw)
+	if(get(MGL_VECT_FRAME))	DrwDat.erase(DrwDat.begin()+i);
+#endif
+	CurFrameId--;
+}
+//-----------------------------------------------------------------------------
+#undef _GR_
+#define _GR_	((mglCanvas *)(*gr))
+#define _Gr_	((mglCanvas *)(gr))
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_write_png(HMGL gr, const char *fname,const char *)
+{
+	long w,h;	unsigned char *f=0, **p=0;
+	p =_Gr_->GetRGBLines(w,h,f,true);
+	if(p)
+	{
+		std::string fn=fname;
+		if(fn.empty())	{	fn=gr->PlotId+".png";	fname = fn.c_str();	}
+		if(mgl_pnga_save(fname,w,h,p))	gr->SetWarn(mglWarnOpen,fname);
+		free(p);	if(f)	free(f);
+	}
+}
+void MGL_EXPORT mgl_write_png_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,descr,n);	f[n]=0;
+	mgl_write_png(_GR_,s,f);	delete []s;		delete []f;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_write_png_solid(HMGL gr, const char *fname,const char *)
+{
+	long w,h;	unsigned char *f=0, **p=0;
+	p =_Gr_->GetRGBLines(w,h,f);
+	if(p)
+	{
+		std::string fn=fname;
+		if(fn.empty())	{	fn=gr->PlotId+".png";	fname = fn.c_str();	}
+		if(mgl_png_save(fname,w,h,p))	gr->SetWarn(mglWarnOpen,fname);
+		free(p);	if(f)	free(f);
+	}
+}
+void MGL_EXPORT mgl_write_png_solid_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,descr,n);	f[n]=0;
+	mgl_write_png_solid(_GR_,s,f);	delete []s;		delete []f;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_write_jpg(HMGL gr, const char *fname,const char *)
+{
+	long w,h;	unsigned char *f=0, **p=0;
+	p =_Gr_->GetRGBLines(w,h,f);
+	if(p)
+	{
+		std::string fn=fname;
+		if(fn.empty())	{	fn=gr->PlotId+".jpg";	fname = fn.c_str();	}
+		if(mgl_jpeg_save(fname,w,h,p))	gr->SetWarn(mglWarnOpen,fname);
+		free(p);	if(f)	free(f);
+	}
+}
+void MGL_EXPORT mgl_write_jpg_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,descr,n);	f[n]=0;
+	mgl_write_jpg(_GR_,s,f);	delete []s;		delete []f;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_write_tga(HMGL gr, const char *fname,const char *)
+{
+	long w,h;	unsigned char *f=0, **p=0;
+	p =_Gr_->GetRGBLines(w,h,f,true);
+	if(p)
+	{
+		std::string fn=fname;
+		if(fn.empty())	{	fn=gr->PlotId+".tga";	fname = fn.c_str();	}
+		if(mgl_tga_save(fname,w,h,p))	gr->SetWarn(mglWarnOpen,fname);
+		free(p);	if(f)	free(f);
+	}
+}
+void MGL_EXPORT mgl_write_tga_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,descr,n);	f[n]=0;
+	mgl_write_tga(_GR_,s,f);	delete []s;		delete []f;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_write_bmp(HMGL gr, const char *fname,const char *)
+{
+	long w,h;	unsigned char *f=0, **p=0;
+	p =_Gr_->GetRGBLines(w,h,f);
+	if(p)
+	{
+		std::string fn=fname;
+		if(fn.empty())	{	fn=gr->PlotId+".bmp";	fname = fn.c_str();	}
+		if(mgl_bmp_save(fname,w,h,p))	gr->SetWarn(mglWarnOpen,fname);
+		free(p);	if(f)	free(f);
+	}
+}
+void MGL_EXPORT mgl_write_bmp_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,descr,n);	f[n]=0;
+	mgl_write_bmp(_GR_,s,f);	delete []s;		delete []f;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_write_bps(HMGL gr, const char *fname,const char *)
+{
+	long w,h;	unsigned char *f=0, **p=0;
+	p =_Gr_->GetRGBLines(w,h,f);
+	if(p)
+	{
+		std::string fn=fname;
+		if(fn.empty())	{	fn=gr->PlotId+".eps";	fname = fn.c_str();	}
+		if(mgl_bps_save(fname,w,h,p))	gr->SetWarn(mglWarnOpen,fname);
+		free(p);	if(f)	free(f);
+	}
+}
+void MGL_EXPORT mgl_write_bps_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,descr,n);	f[n]=0;
+	mgl_write_bps(_GR_,s,f);	delete []s;		delete []f;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_write_gif(HMGL gr, const char *fname,const char *)
+{
+	long w,h;	unsigned char *f=0, **p=0;
+	p =_Gr_->GetRGBLines(w,h,f);
+	if(p)
+	{
+		std::string fn=fname;
+		if(fn.empty())	{	fn=gr->PlotId+".gif";	fname = fn.c_str();	}
+		if(mgl_gif_save(fname,w,h,p))	gr->SetWarn(mglWarnOpen,fname);
+		free(p);	if(f)	free(f);
+	}
+}
+void MGL_EXPORT mgl_write_gif_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,descr,n);	f[n]=0;
+	mgl_write_gif(_GR_,s,f);	delete []s;		delete []f;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_start_gif(HMGL gr, const char *fname,int ms)
+{	_Gr_->StartGIF(fname,ms);	}
+void MGL_EXPORT mgl_start_gif_(uintptr_t *gr, const char *fname,int *ms,int l)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	mgl_start_gif(_GR_,s,*ms);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_close_gif(HMGL gr)			{	_Gr_->CloseGIF();	}
+void MGL_EXPORT mgl_close_gif_(uintptr_t *gr)	{	mgl_close_gif(_GR_);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_write_frame(HMGL gr, const char *fname,const char *descr)
+{
+	char buf[64];
+	if(!fname || !fname[0])
+	{	snprintf(buf,64,"%s%04d.jpg",_Gr_->PlotId.c_str(),_Gr_->GetNumFrame());	buf[63]=0;	fname = buf;	}
+	int len=strlen(fname);
+	if(!strcmp(fname+len-4,".jpg")) 	mgl_write_jpg(gr,fname,descr);
+	if(!strcmp(fname+len-5,".jpeg"))	mgl_write_jpg(gr,fname,descr);
+	if(!strcmp(fname+len-4,".prc")) 	mgl_write_prc(gr,fname,descr,1);
+	if(!strcmp(fname+len-4,".pdf")) 	mgl_write_prc(gr,fname,descr,1);
+	if(!strcmp(fname+len-4,".png")) 	mgl_write_png(gr,fname,descr);
+	if(!strcmp(fname+len-4,".eps")) 	mgl_write_eps(gr,fname,descr);
+	if(!strcmp(fname+len-5,".epsz"))	mgl_write_eps(gr,fname,descr);
+	if(!strcmp(fname+len-7,".eps.gz"))	mgl_write_eps(gr,fname,descr);
+	if(!strcmp(fname+len-4,".bps")) 	mgl_write_bps(gr,fname,descr);
+	if(!strcmp(fname+len-5,".bpsz"))	mgl_write_bps(gr,fname,descr);
+	if(!strcmp(fname+len-7,".bps.gz"))	mgl_write_bps(gr,fname,descr);
+	if(!strcmp(fname+len-4,".svg")) 	mgl_write_svg(gr,fname,descr);
+	if(!strcmp(fname+len-5,".svgz"))	mgl_write_svg(gr,fname,descr);
+	if(!strcmp(fname+len-7,".svg.gz"))	mgl_write_svg(gr,fname,descr);
+	if(!strcmp(fname+len-4,".gif")) 	mgl_write_gif(gr,fname,descr);
+	if(!strcmp(fname+len-4,".bmp")) 	mgl_write_bmp(gr,fname,descr);
+	if(!strcmp(fname+len-4,".tga")) 	mgl_write_tga(gr,fname,descr);
+	if(!strcmp(fname+len-5,".mgld"))	mgl_export_mgld(gr,fname,descr);
+	if(!strcmp(fname+len-5,".json"))	mgl_write_json(gr,fname,descr);
+	if(!strcmp(fname+len-6,".jsonz"))	mgl_write_json(gr,fname,descr);
+	if(!strcmp(fname+len-4,".obj")) 	mgl_write_obj(gr,fname,descr,1);
+	if(!strcmp(fname+len-4,".tex")) 	mgl_write_tex(gr,fname,descr);
+	if(!strcmp(fname+len-4,".xyz")) 	mgl_write_xyz(gr,fname,descr);
+	if(!strcmp(fname+len-4,".stl")) 	mgl_write_stl(gr,fname,descr);
+	if(!strcmp(fname+len-4,".off")) 	mgl_write_off(gr,fname,descr,0);
+//	if(!strcmp(fname+len-4,".x3d")) 	mgl_write_x3d(gr,fname,descr,1);
+}
+void MGL_EXPORT mgl_write_frame_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,descr,n);	f[n]=0;
+	mgl_write_frame(_GR_,s,f);	delete []s;		delete []f;}
+//-----------------------------------------------------------------------------
+#ifdef WIN32
+#include <io.h>
+#include <direct.h>
+#endif
+void MGL_EXPORT mgl_show_image(HMGL gr, const char *viewer, int keep)
+{
+	char fname[128], *cmd = new char [128];
+	snprintf(fname,128,"%s.png", tmpnam(NULL));	fname[127]=0;
+	mgl_write_png_solid(gr,fname,"MathGL ShowImage file");
+	if(!viewer || !viewer[0])
+		viewer = MGL_DEF_VIEWER;
+#ifdef WIN32
+		if(keep)
+		{
+			snprintf(cmd,128,"%s %s &", viewer,fname);	cmd[127]=0;
+			if(system(cmd)==-1)	printf(_("Error to call external viewer\n"));
+			Sleep(2000);
+			snprintf(cmd,128,"del %s", fname);
+		}
+		else	snprintf(cmd,128,"%s %s; del %s", viewer,fname,fname);
+#else
+		if(keep)
+		{
+			snprintf(cmd,128,"%s %s &", viewer,fname);	cmd[127]=0;
+			if(system(cmd)==-1)	printf(_("Error to call external viewer\n"));
+			sleep(2);
+			snprintf(cmd,128,"rm %s", fname);
+		}
+		else	snprintf(cmd,128,"%s %s; rm %s", viewer,fname,fname);
+#endif
+		cmd[127] = 0;
+		if(system(cmd)==-1)	printf(_("Error to call external viewer\n"));
+		delete []cmd;
+}
+void MGL_EXPORT mgl_show_image_(uintptr_t *gr, const char *viewer, int *keep, int l)
+{	char *s=new char[l+1];	memcpy(s,viewer,l);	s[l]=0;
+	mgl_show_image(_GR_,s,*keep);	delete []s;	}
+//-----------------------------------------------------------------------------
diff --git a/src/export_2d.cpp b/src/export_2d.cpp
new file mode 100644
index 0000000..5a5580c
--- /dev/null
+++ b/src/export_2d.cpp
@@ -0,0 +1,743 @@
+/***************************************************************************
+ * export_2d.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include "mgl2/canvas.h"
+#include "mgl2/canvas_cf.h"
+#include "mgl2/font.h"
+#include <time.h>
+#include <algorithm>
+#include <sys/stat.h>
+#undef _GR_
+#define _GR_	((mglCanvas *)(*gr))
+#define _Gr_	((mglCanvas *)(gr))
+void mgl_printf(void *fp, bool gz, const char *str, ...);
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT const char *mgl_get_dash(unsigned short d, mreal w,char dlm)
+{
+	static std::string s;
+	if(d==0xffff)	return "";
+	int f=0, p=d&1, n=p?0:1;
+	s = p ? "" : "0";
+	for(int i=0;i<16;i++)
+	{
+		int j = i;//15-i;
+		if(((d>>j)&1) == p)	f++;
+		else
+		{
+			s += mgl_str_num(f*w)+dlm;
+			p = (d>>j)&1;	f = 1;	n++;
+		}
+	}
+	s += mgl_str_num(f*w) + ((n%2) ? "" : " 0");
+	return s.c_str();
+}
+//-----------------------------------------------------------------------------
+bool MGL_LOCAL_PURE mgl_is_same(HMGL gr, long i, mreal wp,uint32_t cp, int st)
+{
+	const mglPrim &pr=_Gr_->GetPrm(i);
+	if(abs(pr.type)!=1)	return false;
+	if(pr.w>=1 && wp!=pr.w)	return false;
+	if(pr.w<1 && wp!=1)	return false;
+	if(st!=pr.n3)	return false;
+	return (cp==_Gr_->GetPrmCol(i));
+}
+//-----------------------------------------------------------------------------
+std::vector<long> MGL_NO_EXPORT put_line(HMGL gr, long i, mreal wp, uint32_t cp,int st)
+{
+	std::vector<long> ids;
+	long n1=gr->GetPrm(i).n1, n2=gr->GetPrm(i).n2;
+	if(n1>n2)	{	n1=gr->GetPrm(i).n2;	n2=gr->GetPrm(i).n1;	}
+	if(n1<0 || n2<0)	return ids;
+	const mglPnt &pp1 = gr->GetPnt(n1), &pp2 = gr->GetPnt(n2);
+	mreal x0=pp1.x, y0=pp1.y;
+	bool ok=true;
+	long j;	// first point
+	while(ok)	// try to find starting point
+	{
+		for(ok=false,j=i+1;j<gr->GetPrmNum();j++)
+		{
+			mglPrim &q = gr->GetPrm(j);
+			if(q.type>1)	break;
+			if(mgl_is_same(gr, j, wp,cp,st) && q.type==1 && q.n1>=0 && q.n2>=0)	// previous point
+			{
+				const mglPnt &p1 = gr->GetPnt(q.n1);
+				const mglPnt &p2 = gr->GetPnt(q.n2);
+				if(p2.x==x0 && p2.y==y0)
+				{
+					ok = true;	ids.push_back(q.n1);
+					x0 = p1.x;	y0 = p1.y;	q.type = -1;
+				}
+				else if(p1.x==x0 && p1.y==y0)
+				{
+					ok = true;	ids.push_back(q.n2);
+					x0 = p2.x;	y0 = p2.y;	q.type = -1;
+				}
+			}
+		}
+	}
+	std::reverse(ids.begin(),ids.end());
+	ids.push_back(n1);	ids.push_back(n2);
+	x0 = pp2.x;	y0 = pp2.y;	ok = true;
+	while(ok)	// try to find starting point
+	{
+		for(ok=false,j=i+1;j<gr->GetPrmNum();j++)
+		{
+			mglPrim &q = gr->GetPrm(j);
+			if(q.type>1)	break;
+			if(mgl_is_same(gr, j,wp,cp,st) && q.type==1 && q.n1>=0 && q.n2>=0)	// next point
+			{
+				const mglPnt &p1 = gr->GetPnt(q.n1);
+				const mglPnt &p2 = gr->GetPnt(q.n2);
+				if(p2.x==x0 && p2.y==y0)
+				{
+					ok = true;	ids.push_back(q.n1);
+					x0 = p1.x;	y0 = p1.y;	q.type = -1;
+				}
+				else if(p1.x==x0 && p1.y==y0)
+				{
+					ok = true;	ids.push_back(q.n2);
+					x0 = p2.x;	y0 = p2.y;	q.type = -1;
+				}
+			}
+		}
+	}
+	return ids;
+}
+//-----------------------------------------------------------------------------
+//put_desc(fp,"%c%c%c_%04x {", "np %d %d mt %d %d ll %d %d ll cp fill\n",
+//"np %d %d mt ", "%d %d ll ", "cp dr\n", "} def")
+void MGL_NO_EXPORT put_desc(HMGL gr, void *fp, bool gz, const char *pre, const char *ln1, const char *ln2, const char *ln3, const char *suf)
+{
+	long n=0;
+	for(long i=0;i<gr->GetPrmNum();i++)	if(gr->GetPrm(i).type==4)	n++;
+	if(n==0)	return;		// no glyphs
+	wchar_t *g = new wchar_t[n];
+	int *s = new int[n];	n=0;
+	for(long i=0;i<gr->GetPrmNum();i++)
+	{
+		const mglPrim q = gr->GetPrm(i);
+		if(q.type!=4 || (q.n3&8))	continue;	// not a glyph
+		bool is=false;
+		for(long j=0;j<n;j++)	if(g[j]==q.n4 && s[j]==(q.n3&7))	is = true;
+		if(is)	continue;		// glyph is described
+		// have to describe
+		g[n]=q.n4;	s[n]=q.n3&7;	n++;	// add to list of described
+		// "%c%c%c_%04x {"
+		mgl_printf(fp, gz, pre, q.n3&1?'b':'n', q.n3&2?'i':'n', q.n4);
+		const mglGlyph &g = gr->GetGlf(q.n4);
+		int nl=g.nl;
+		const short *ln=g.line;
+		bool np=true;
+		if(ln && nl>0)	for(long ik=0;ik<nl;ik++)
+		{
+			long ii = 2*ik;
+			if(ln[ii]==0x3fff && ln[ii+1]==0x3fff)	// line breakthrough
+			{	mgl_printf(fp, gz, "%s",ln3);	np=true;	continue;	}
+			else if(np)	mgl_printf(fp, gz, ln1,ln[ii],ln[ii+1]);
+			else		mgl_printf(fp, gz, ln2,ln[ii],ln[ii+1]);
+			np=false;
+		}
+		mgl_printf(fp, gz, "%s%s",ln3,suf);	// finish glyph description suf="} def"
+	}
+	delete []g;		delete []s;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_write_eps(HMGL gr, const char *fname,const char *descr)
+{
+	if(!fname || *fname==0)	return;
+	if(gr->GetPrmNum()<1)	return;
+	_Gr_->clr(MGL_FINISHED);	_Gr_->PreparePrim(1);
+	time_t now;	time(&now);
+
+	bool gz = fname[strlen(fname)-1]=='z';
+	void *fp;
+	if(!strcmp(fname,"-"))	fp = stdout;		// allow to write in stdout
+	else		fp = gz ? (void*)gzopen(fname,"wt") : (void*)fopen(fname,"wt");
+	if(!fp)		{	gr->SetWarn(mglWarnOpen,fname);	return;	}
+	int w = _Gr_->GetWidth(), h = _Gr_->GetHeight();
+
+	int x1=gr->BBoxX1, x2=gr->BBoxX2<0?w:gr->BBoxX2, y1=gr->BBoxY1, y2=gr->BBoxY2<0?h:gr->BBoxY2;
+	if(x1<0 || x1>=x2 || y1<0 || y1>=y2)	{	x1=y1=0;	x2=w;	y2=h;	}
+
+	if(gz)
+	{
+		unsigned len = strlen(fname), pos=0;
+		char *buf = new char[len+4];
+		memcpy(buf,fname,len);
+		if(buf[len-3]=='.')	pos = len-2;
+		else if(buf[len-2]=='.')	pos = len-1;
+		else	{	buf[len-1]='.';	pos = len;	}
+		if(pos)	{	buf[pos]=buf[pos+1]='b';	buf[pos+2]=0;	}
+		FILE *fb = fopen(buf,"w");
+		fprintf(fb, "%%%%BoundingBox: %d %d %d %d\n", x1, h-y2, x2, h-y1);
+		fclose(fb);	delete []buf;
+	}
+
+	const std::string loc = setlocale(LC_NUMERIC, "C");
+	mgl_printf(fp, gz, "%%!PS-Adobe-3.0 EPSF-3.0\n%%%%BoundingBox: %d %d %d %d\n", x1, h-y2, x2, h-y1);
+	mgl_printf(fp, gz, "%%%%Created by MathGL library\n%%%%Title: %s\n",descr ? descr : fname);
+	mgl_printf(fp, gz, "%%%%CreationDate: %s\n",ctime(&now));
+	mgl_printf(fp, gz, "/lw {setlinewidth} def\n/rgb {setrgbcolor} def\n");
+	mgl_printf(fp, gz, "/np {newpath} def\n/cp {closepath} def\n");
+	mgl_printf(fp, gz, "/ll {lineto} def\n/mt {moveto} def\n");
+	mgl_printf(fp, gz, "/rl {rlineto} def\n/rm {rmoveto} def\n/dr {stroke} def\n");
+	mgl_printf(fp, gz, "/ss {%g} def\n",0.35*gr->mark_size());
+	mgl_printf(fp, gz, "/s2 {%g} def\n",0.7*gr->mark_size());
+	mgl_printf(fp, gz, "/sm {-%g} def\n",0.35*gr->mark_size());
+	mgl_printf(fp, gz, "/m_c {ss 0.3 mul 0 360 arc} def\n");
+	mgl_printf(fp, gz, "/d0 {[] 0 setdash} def\n/sd {setdash} def\n");
+
+	bool m_p=false,m_x=false,m_d=false,m_v=false,m_t=false,
+	m_s=false,m_a=false,m_o=false,m_T=false,
+	m_V=false,m_S=false,m_D=false,m_Y=false,m_l=false,
+	m_L=false,m_r=false,m_R=false,m_X=false,m_P=false;
+	// add mark definition if present
+	for(long i=0;i<gr->GetPrmNum();i++)
+	{
+		const mglPrim q = gr->GetPrm(i);
+		if(q.type>0)	continue;
+		if(q.n4=='+')	m_p = true;
+		if(q.n4=='x')	m_x = true;
+		if(q.n4=='s')	m_s = true;
+		if(q.n4=='d')	m_d = true;
+		if(q.n4=='v')	m_v = true;
+		if(q.n4=='^')	m_t = true;
+		if(q.n4=='*')	m_a = true;
+		if(q.n4=='o' || q.n4=='O' || q.n4=='C')	m_o = true;
+		if(q.n4=='S')	m_S = true;
+		if(q.n4=='D')	m_D = true;
+		if(q.n4=='V')	m_V = true;
+		if(q.n4=='T')	m_T = true;
+		if(q.n4=='<')	m_l = true;
+		if(q.n4=='L')	m_L = true;
+		if(q.n4=='>')	m_r = true;
+		if(q.n4=='R')	m_R = true;
+		if(q.n4=='Y')	m_Y = true;
+		if(q.n4=='P')	m_P = true;
+		if(q.n4=='X')	m_X = true;
+	}
+	if(m_P)	{	m_p=true;	m_s=true;	}
+	if(m_X)	{	m_x=true;	m_s=true;	}
+	if(m_p)	mgl_printf(fp, gz, "/m_p {sm 0 rm s2 0 rl sm sm rm 0 s2 rl d0} def\n");
+	if(m_x)	mgl_printf(fp, gz, "/m_x {sm sm rm s2 s2 rl 0 sm 2 mul rm sm 2 mul s2 rl d0} def\n");
+	if(m_s)	mgl_printf(fp, gz, "/m_s {sm sm rm 0 s2 rl s2 0 rl 0 sm 2 mul rl cp d0} def\n");
+	if(m_d)	mgl_printf(fp, gz, "/m_d {sm 0 rm ss ss rl ss sm rl sm sm rl cp d0} def\n");
+	if(m_v)	mgl_printf(fp, gz, "/m_v {sm ss 2 div rm s2 0 rl sm sm 1.5 mul rl d0 cp} def\n");
+	if(m_t)	mgl_printf(fp, gz, "/m_t {sm sm 2 div rm s2 0 rl sm ss 1.5 mul rl d0 cp} def\n");
+	if(m_a)	mgl_printf(fp, gz, "/m_a {sm 0 rm s2 0 rl sm 1.6 mul sm 0.8 mul rm ss 1.2 mul ss 1.6 mul rl 0 sm 1.6 mul rm sm 1.2 mul ss 1.6 mul rl d0} def\n");
+	if(m_o)	mgl_printf(fp, gz, "/m_o {ss 0 360 d0 arc} def\n");
+	if(m_S)	mgl_printf(fp, gz, "/m_S {sm sm rm 0 s2 rl s2 0 rl 0 sm 2 mul rl cp} def\n");
+	if(m_D)	mgl_printf(fp, gz, "/m_D {sm 0 rm ss ss rl ss sm rl sm sm rl cp} def\n");
+	if(m_V)	mgl_printf(fp, gz, "/m_V {sm ss 2 div rm s2 0 rl sm sm 1.5 mul rl cp} def\n");
+	if(m_T)	mgl_printf(fp, gz, "/m_T {sm sm 2 div rm s2 0 rl sm ss 1.5 mul rl cp} def\n");
+	if(m_Y)	mgl_printf(fp, gz, "/m_Y {0 sm rm 0 ss rl sm ss rl s2 0 rm sm sm rl d0} def\n");
+	if(m_r)	mgl_printf(fp, gz, "/m_r {sm 2 div sm rm 0 s2 rl ss 1.5 mul sm rl d0 cp} def\n");
+	if(m_l)	mgl_printf(fp, gz, "/m_l {ss 2 div sm rm 0 s2 rl sm 1.5 mul sm rl d0 cp} def\n");
+	if(m_R)	mgl_printf(fp, gz, "/m_R {sm 2 div sm rm 0 s2 rl ss 1.5 mul sm rl cp} def\n");
+	if(m_L)	mgl_printf(fp, gz, "/m_L {ss 2 div sm rm 0 s2 rl sm 1.5 mul sm rl cp} def\n");
+	if(m_P)	mgl_printf(fp, gz, "/m_P {m_p 0 sm rm m_s} def\n");
+	if(m_X)	mgl_printf(fp, gz, "/m_X {m_x ss sm rm m_s} def\n");
+	//	if(m_C)	mgl_printf(fp, gz, "/m_C {m_c m_o} def\n");
+	mgl_printf(fp, gz, "1 setlinecap\n1 setlinejoin\n\n");	// manual setting round line cap
+
+	// Write background image first
+	const unsigned char *img = mgl_get_background(gr);
+	bool same = true;
+	unsigned char white[3]={255,255,255};
+#pragma omp parallel for
+	for(long i=0;i<w*h;i++)	if(memcmp(img,img+4*i,3))	same=false;
+	if(!same)
+	{
+		mgl_printf(fp, gz, "gsave\t%d %d translate\n",x1,h-y2);
+		mgl_printf(fp, gz, "%d %d 8 [1 0 0 1 0 0] {<", x2-x1,y2-y1);
+		for(long j=y2-1;j>=y1;j--)	for(long i=x1;i<x2;i++)
+		{
+			if((i+w*(h-j-1))%40==0 && i+j>0)	mgl_printf(fp, gz, "\n");
+			mgl_printf(fp, gz, "%02x%02x%02x",img[4*(i+w*j)],img[4*(i+w*j)+1],img[4*(i+w*j)+2]);
+		}
+		mgl_printf(fp, gz, "\n>} false 3 colorimage\ngrestore\n\n");
+	}
+	else if(memcmp(img,white,3))
+		mgl_printf(fp, gz, "np 0 0 mt 0 %d ll %d %d ll %d 0 ll cp %g %g %g rgb fill\n", y2-y1, x2-x1, y2-y1, x2-x1, img[0]/255., img[1]/255., img[2]/255.);
+
+	// write definition for all glyphs
+	put_desc(gr,fp,gz,"/%c%c_%04x { np\n", "\t%d %d mt ", "%d %d ll ", "cp\n", "} def\n");
+	// write primitives
+	mreal wp=-1;
+	float qs_old=gr->mark_size()/gr->FontFactor();
+	mglRGBA cp;
+	int st=0;
+	char str[256]="";
+	for(long i=0;i<gr->GetPrmNum();i++)
+	{
+		const mglPrim &q = gr->GetPrm(i);
+		if(q.type<0)	continue;	// q.n1>=0 always
+		cp.c = _Gr_->GetPrmCol(i);
+		const mglPnt p1 = gr->GetPnt(q.n1);
+		if(q.type>1)
+		{	snprintf(str,256,"%.2g %.2g %.2g rgb ", cp.r[0]/255.,cp.r[1]/255.,cp.r[2]/255.);	str[255]=0;	}
+
+		if(q.type==0)	// mark
+		{
+			mreal x0 = p1.x,y0 = p1.y;
+			snprintf(str,256,"%.2g lw %.2g %.2g %.2g rgb ", 50*q.s*q.w>1?50*q.s*q.w:1, cp.r[0]/255.,cp.r[1]/255.,cp.r[2]/255.);
+			str[255]=0;	wp=1;	// NOTE: this may renew line style if a mark inside!
+			if(q.s!=qs_old)
+			{
+				mgl_printf(fp, gz, "/ss {%g} def\n",q.s);
+				mgl_printf(fp, gz, "/s2 {%g} def\n",q.s*2);
+				mgl_printf(fp, gz, "/sm {-%g} def\n",q.s);
+				qs_old = q.s;
+			}
+			switch(q.n4)
+			{
+				case '+':	mgl_printf(fp, gz, "np %g %g mt m_p %sdr\n",x0,y0,str);	break;
+				case 'x':	mgl_printf(fp, gz, "np %g %g mt m_x %sdr\n",x0,y0,str);	break;
+				case 's':	mgl_printf(fp, gz, "np %g %g mt m_s %sdr\n",x0,y0,str);	break;
+				case 'd':	mgl_printf(fp, gz, "np %g %g mt m_d %sdr\n",x0,y0,str);	break;
+				case '*':	mgl_printf(fp, gz, "np %g %g mt m_a %sdr\n",x0,y0,str);	break;
+				case 'v':	mgl_printf(fp, gz, "np %g %g mt m_v %sdr\n",x0,y0,str);	break;
+				case '^':	mgl_printf(fp, gz, "np %g %g mt m_t %sdr\n",x0,y0,str);	break;
+				case 'S':	mgl_printf(fp, gz, "np %g %g mt m_S %sfill\n",x0,y0,str);	break;
+				case 'D':	mgl_printf(fp, gz, "np %g %g mt m_D %sfill\n",x0,y0,str);	break;
+				case 'V':	mgl_printf(fp, gz, "np %g %g mt m_V %sfill\n",x0,y0,str);	break;
+				case 'T':	mgl_printf(fp, gz, "np %g %g mt m_T %sfill\n",x0,y0,str);	break;
+				case 'o':	mgl_printf(fp, gz, "%g %g m_o %sdr\n",x0,y0,str);break;
+				case 'O':	mgl_printf(fp, gz, "%g %g m_o %sfill\n",x0,y0,str);break;
+				case 'Y':	mgl_printf(fp, gz, "np %g %g mt m_Y %sdr\n",x0,y0,str);	break;
+				case '<':	mgl_printf(fp, gz, "np %g %g mt m_l %sdr\n",x0,y0,str);	break;
+				case '>':	mgl_printf(fp, gz, "np %g %g mt m_r %sdr\n",x0,y0,str);	break;
+				case 'L':	mgl_printf(fp, gz, "np %g %g mt m_L %sfill\n",x0,y0,str);	break;
+				case 'R':	mgl_printf(fp, gz, "np %g %g mt m_R %sfill\n",x0,y0,str);	break;
+				case 'P':	mgl_printf(fp, gz, "np %g %g mt m_P %sdr\n",x0,y0,str);	break;
+				case 'X':	mgl_printf(fp, gz, "np %g %g mt m_X %sdr\n",x0,y0,str);	break;
+				case 'C':	mgl_printf(fp, gz, "%g %g m_o %g %g m_c %sdr\n",x0,y0,x0,y0,str);	break;
+				case '.':	mgl_printf(fp, gz, "%g %g m_c %sfill\n",x0,y0,str);
+			}
+		}
+		else if(q.type==3)	// quad
+		{
+			const mglPnt &p2=gr->GetPnt(q.n2), &p3=gr->GetPnt(q.n3), &p4=gr->GetPnt(q.n4);
+			if(cp.r[3])	// TODO && gr->quad_vis(p1,p2,p3,p4))
+				mgl_printf(fp, gz, "np %g %g mt %g %g ll %g %g ll %g %g ll cp %sfill\n", p1.x, p1.y, p2.x, p2.y, p4.x, p4.y, p3.x, p3.y, str);
+		}
+		else if(q.type==2)	// trig
+		{
+			const mglPnt &p2=gr->GetPnt(q.n2), &p3=gr->GetPnt(q.n3);
+			if(cp.r[3])	// TODO && gr->trig_vis(p1,p2,p3))
+				mgl_printf(fp, gz, "np %g %g mt %g %g ll %g %g ll cp %sfill\n", p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, str);
+		}
+		else if(q.type==1)	// line
+		{
+			snprintf(str,256,"%.2g lw %.2g %.2g %.2g rgb ", q.w>1 ? q.w:1., cp.r[0]/255.,cp.r[1]/255.,cp.r[2]/255.);
+			str[255]=0;	wp = q.w>1  ? q.w:1;	st = q.n3;
+			std::vector<long> ids = put_line(gr,i,wp,cp.c,st);
+			for(size_t j=0;j<ids.size();j++)
+			{
+				const mglPnt &p = gr->GetPnt(ids[j]);
+				float x0 = p.x, y0 = p.y;
+				mgl_printf(fp, gz, j==0?"np %g %g mt ":"%g %g ll ",x0,y0);
+			}
+			const char *sd = mgl_get_dash(q.n3,q.w,' ');
+			if(sd && sd[0])	mgl_printf(fp, gz, "%s [%s] %g sd dr\n",str,sd,q.w*q.s);
+			else			mgl_printf(fp, gz, "%s d0 dr\n",str);
+		}
+		else if(q.type==4)	// glyph
+		{
+			float phi = gr->GetGlyphPhi(gr->GetPnt(q.n2),q.w);
+			if(mgl_isnan(phi))	continue;
+			mreal 	ss = q.s/2, xx = p1.u, yy = p1.v, zz = q.p;
+			mgl_printf(fp, gz, "gsave\t%g %g translate %g %g scale %g rotate %s\n",
+					   p1.x, p1.y, ss, ss, -phi, str);
+			if(q.n3&8)	// this is "line"
+			{
+				mreal dy = 0.004,f=fabs(zz);
+				mgl_printf(fp, gz, "np %g %g mt %g %g ll %g %g ll %g %g ll cp ",
+						   xx,yy+dy, xx+f,yy+dy, xx+f,yy-dy, xx,yy-dy);
+			}
+			else
+				mgl_printf(fp, gz, "%.3g %.3g translate %g %g scale %c%c_%04x ",
+						   xx, yy, zz, zz, q.n3&1?'b':'n', q.n3&2?'i':'n', q.n4);
+			if(q.n3&4)	mgl_printf(fp, gz, "dr");
+			else	mgl_printf(fp, gz, "eofill");
+			mgl_printf(fp, gz, " grestore\n");
+		}
+	}
+	for(long i=0;i<gr->GetPrmNum();i++)
+	{
+		mglPrim &q = gr->GetPrm(i);
+		if(q.type==-1)	q.type = 1;
+	}
+	mgl_printf(fp, gz, "\nshowpage\n%%%%EOF\n");
+	if(strcmp(fname,"-"))	{	if(gz)	gzclose((gzFile)fp);	else	fclose((FILE *)fp);	}
+	setlocale(LC_NUMERIC, loc.c_str());
+}
+void MGL_EXPORT mgl_write_eps_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *d=new char[n+1];	memcpy(d,descr,n);	d[n]=0;
+	mgl_write_eps(_GR_,s,d);	delete []s;		delete []d;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_write_svg(HMGL gr, const char *fname,const char *descr)
+{
+	if(!fname || *fname==0)	return;
+	if(gr->GetPrmNum()<1)	return;
+	_Gr_->clr(MGL_FINISHED);	_Gr_->PreparePrim(1);
+	time_t now;	time(&now);
+
+	bool gz = fname[strlen(fname)-1]=='z';
+	long hh = _Gr_->GetHeight(), ww = _Gr_->GetWidth();
+	void *fp = stdout;		// allow to write in stdout
+	if(strcmp(fname,"-"))	fp = gz ? (void*)gzopen(fname,"wt") : (void*)fopen(fname,"wt");
+	if(!fp)		{	gr->SetWarn(mglWarnOpen,fname);	return;	}
+
+	int x1=gr->BBoxX1, x2=gr->BBoxX2<0?ww:gr->BBoxX2, y1=gr->BBoxY1, y2=gr->BBoxY2<0?hh:gr->BBoxY2;
+	if(x1<0 || x1>=x2 || y1<0 || y1>=y2)	{	x1=y1=0;	x2=ww;	y2=hh;	}
+	ww = x2-x1;	hh = y2-y1;
+
+	const std::string loc = setlocale(LC_NUMERIC, "C");
+	mgl_printf(fp, gz, "<?xml version=\"1.0\" standalone=\"no\"?>\n");
+	mgl_printf(fp, gz, "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20000303 Stylable//EN\" \"http://www.w3.org/TR/2000/03/WD-SVG-20000303/DTD/svg-20000303-stylable.dtd\">\n");
+	mgl_printf(fp, gz, "<svg width=\"%d\" height=\"%d\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", ww, hh);
+
+	mgl_printf(fp, gz, "<!--Created by MathGL library-->\n");
+	mgl_printf(fp, gz, "<!--Title: %s-->\n<!--CreationDate: %s-->\n\n",descr?descr:fname,ctime(&now));
+
+	// write definition for all glyphs
+	put_desc(gr,fp,gz,"<defs><g id=\"%c%c_%04x\"><path d=\"", "\tM %d %d ",
+			 "L %d %d ", "Z\n", "\"/></g></defs>\n");
+
+
+	// Write background image first
+	const unsigned char *img = mgl_get_background(gr);
+	bool same = true;
+	unsigned char white[3]={255,255,255};
+#pragma omp parallel for
+	for(long i=0;i<ww*hh;i++)	if(memcmp(img,img+4*i,3))	same=false;
+	if(!same)
+	{	// TODO write as <image width="100" height="100" xlink:href="data:image/png;base64,...">
+/*		mgl_printf(fp, gz, "%d %d 8 [1 0 0 1 0 0] {<", ww,hh,1+ww*hh/40);
+		for(long j=hh-1;j>=0;j--)	for(long i=0;i<ww;i++)
+		{
+			if((i+ww*(hh-j-1))%40==0 && i+j>0)	mgl_printf(fp, gz, "\n");
+			mgl_printf(fp, gz, "%02x%02x%02x",img[4*(i+ww*j)],img[4*(i+ww*j)+1],img[4*(i+ww*j)+2]);
+		}
+		mgl_printf(fp, gz, "\n>} false 3 colorimage\n\n");*/
+	}
+	else if(memcmp(img,white,3))
+	{
+		mgl_printf(fp, gz, "<g fill=\"#%02x%02x%02x\" opacity=\"%g\">\n", img[0], img[1], img[2], img[3]/255.);
+		mgl_printf(fp, gz, "<path d=\"M 0 0 L 0 %ld L %ld %ld L %ld 0 Z\"/> </g>\n", hh, ww, hh, ww);
+	}
+
+
+	// currentColor -> inherit ???
+	mgl_printf(fp, gz, "<g fill=\"none\" stroke=\"none\" stroke-width=\"0.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n");
+	// write primitives
+	mreal wp=-1;
+	int st=0;
+	mglRGBA cp;
+
+	hh += (y2+y1)/2;
+	for(long i=0;i<gr->GetPrmNum();i++)
+	{
+		const mglPrim &q = gr->GetPrm(i);
+		if(q.type<0)	continue;	// q.n1>=0 always
+		cp.c = _Gr_->GetPrmCol(i);
+		const mglPnt p1=gr->GetPnt(q.n1);
+		if(q.type==0)
+		{
+			mreal x=p1.x-x1,y=hh-p1.y,s=q.s;
+			if(!strchr("xsSoO",q.n4))	s *= 1.1;
+			wp = 1;
+			if(strchr("SDVTLR",q.n4))
+				mgl_printf(fp, gz, "<g fill=\"#%02x%02x%02x\">\n", int(cp.r[0]),int(cp.r[1]),int(cp.r[2]));
+			else
+				mgl_printf(fp, gz, "<g stroke=\"#%02x%02x%02x\"  stroke-width=\"%g\">\n", int(cp.r[0]),int(cp.r[1]),int(cp.r[2]), 50*q.s*q.w>1?50*q.s*q.w:1);
+			switch(q.n4)
+			{
+			case 'P':
+				mgl_printf(fp, gz, "<path d=\"M %g %g L %g %g M %g %g L %g %g M %g %g L %g %g L %g %g L %g %g L %g %g\"/>\n",
+							x-s,y,x+s,y,x,y-s,x,y+s, x-s,y-s,x+s,y-s,x+s,y+s,x-s,y+s,x-s,y-s);	break;
+			case '+':
+				mgl_printf(fp, gz, "<path d=\"M %g %g L %g %g M %g %g L %g %g\"/>\n", x-s,y,x+s,y,x,y-s,x,y+s);	break;
+			case 'X':
+				mgl_printf(fp, gz, "<path d=\"M %g %g L %g %g M %g %g L %g %g M %g %g L %g %g L %g %g L %g %g L %g %g\"/>\n",
+							x-s,y-s,x+s,y+s,x+s,y-s,x-s,y+s, x-s,y-s,x+s,y-s,x+s,y+s,x-s,y+s,x-s,y-s);	break;
+			case 'x':
+				mgl_printf(fp, gz, "<path d=\"M %g %g L %g %g M %g %g L %g %g\"/>\n", x-s,y-s,x+s,y+s,x+s,y-s,x-s,y+s);	break;
+			case 's':
+			case 'S':
+				mgl_printf(fp, gz, "<path d=\"M %g %g L %g %g L %g %g L %g %gZ\"/>\n", x-s,y-s,x+s,y-s,x+s,y+s,x-s,y+s);	break;
+			case 'd':
+			case 'D':
+				mgl_printf(fp, gz, "<path d=\"M %g %g L %g %g L %g %g L %g %gZ\"/>\n", x-s,y,x,y-s,x+s,y,x,y+s);	break;
+			case 'v':
+			case 'V':
+				mgl_printf(fp, gz, "<path d=\"M %g %g L %g %g L %g %gZ\"/>\n", x-s,y-s/2,x+s,y-s/2,x,y+s);	break;
+			case '^':
+			case 'T':
+				mgl_printf(fp, gz, "<path d=\"M %g %g L %g %g L %g %gZ\"/>\n", x-s,y+s/2,x+s,y+s/2,x,y-s);	break;
+			case '<':
+			case 'L':
+				mgl_printf(fp, gz, "<path d=\"M %g %g L %g %g L %g %gZ\"/>\n", x+s/2,y+s,x+s/2,y-s,x-s,y);	break;
+			case '>':
+			case 'R':
+				mgl_printf(fp, gz, "<path d=\"M %g %g L %g %g L %g %gZ\"/>\n", x-s/2,y+s,x-s/2,y-s,x+s,y);	break;
+			case 'Y':
+				mgl_printf(fp, gz, "<path d=\"M %g %g L %g %g L %g %g M %g %g L %g %g\"/>\n", x,y-s, x,y, x+s,y+s, x,y, x-s,y+s);	break;
+			case 'C':
+				mgl_printf(fp, gz, "<circle style=\"fill:#%02x%02x%02x\" cx=\"%g\" cy=\"%g\" r=\"0.15\"/>\n<circle cx=\"%g\" cy=\"%g\" r=\"%g\"/>\n",
+							int(cp.r[0]),int(cp.r[1]),int(cp.r[2]),x,y,x,y,s);	break;
+			case 'o':
+				mgl_printf(fp, gz, "<circle cx=\"%g\" cy=\"%g\" r=\"%g\"/>\n", x,y,s);	break;
+			case 'O':
+				mgl_printf(fp, gz, "<circle style=\"fill:#%02x%02x%02x\" cx=\"%g\" cy=\"%g\" r=\"%g\"/>\n",
+							int(cp.r[0]),int(cp.r[1]),int(cp.r[2]),x,y,s);	break;
+			case '*':
+				mgl_printf(fp, gz, "<path d=\"M %g %g L %g %g M %g %g L %g %g M %g %g L %g %g\"/>\n",
+							x-s,y,x+s,y,x-0.6*s,y-0.8*s,x+0.6*s,y+0.8*s,x+0.6*s,y-0.8*s,x-0.6*s,y+0.8*s);	break;
+			case '.':
+				mgl_printf(fp, gz, "<circle style=\"fill:#%02x%02x%02x\" cx=\"%g\" cy=\"%g\" r=\"0.15\"/>\n",
+							int(cp.r[0]),int(cp.r[1]),int(cp.r[2]),x,y);	break;
+			}
+			mgl_printf(fp, gz, "</g>\n");
+		}
+		else if(q.type==1)
+		{
+			mgl_printf(fp,gz,"<g stroke=\"#%02x%02x%02x\"",int(cp.r[0]),int(cp.r[1]),int(cp.r[2]));
+			if(q.n3)
+			{
+				mgl_printf(fp, gz, " stroke-dasharray=\"%s\"", mgl_get_dash(q.n3,q.w,','));
+				mgl_printf(fp, gz, " stroke-dashoffset=\"%g\"", q.s*q.w);
+			}
+			if(q.w>1)	mgl_printf(fp, gz, " stroke-width=\"%g\"", q.w);
+			wp = q.w>1  ? q.w:1;	st = q.n3;
+			std::vector<long> ids = put_line(gr,i,wp,cp.c,st);
+			for(size_t j=0;j<ids.size();j++)
+			{
+				const mglPnt &p = gr->GetPnt(ids[j]);
+				mgl_printf(fp, gz, j==0?"><path d=\" M %g %g":" L %g %g",p.x-x1,hh-p.y);
+			}
+			mgl_printf(fp, gz, "\"/> </g>\n");
+		}
+		else if(q.type==2 && cp.r[3])
+		{
+			const mglPnt &p2=gr->GetPnt(q.n2), &p3=gr->GetPnt(q.n3);
+			mgl_printf(fp, gz, "<g fill=\"#%02x%02x%02x\" opacity=\"%g\">\n", int(cp.r[0]),int(cp.r[1]),int(cp.r[2]),cp.r[3]/255.);
+			mgl_printf(fp, gz, "<path d=\"M %g %g L %g %g L %g %g Z\"/> </g>\n", p1.x-x1, hh-p1.y, p2.x-x1, hh-p2.y, p3.x-x1, hh-p3.y);
+		}
+		else if(q.type==3 && cp.r[3])
+		{
+			const mglPnt &p2=gr->GetPnt(q.n2), &p3=gr->GetPnt(q.n3), &p4=gr->GetPnt(q.n4);
+			mgl_printf(fp, gz, "<g fill=\"#%02x%02x%02x\" opacity=\"%g\">\n", int(cp.r[0]),int(cp.r[1]),int(cp.r[2]),cp.r[3]/255.);
+			mgl_printf(fp, gz, "<path d=\"M %g %g L %g %g L %g %g L %g %g Z\"/> </g>\n", p1.x-x1, hh-p1.y, p2.x-x1, hh-p2.y, p4.x-x1, hh-p4.y, p3.x-x1, hh-p3.y);
+		}
+		else if(q.type==4)
+		{
+			float phi = gr->GetGlyphPhi(gr->GetPnt(q.n2),q.w);
+			if(mgl_isnan(phi))	continue;
+			mreal ss = q.s/2, xx = p1.u, yy = p1.v, zz = q.p;
+			if(q.n3&8)	// this is "line"
+			{
+				mgl_printf(fp, gz, "<g transform=\"translate(%g,%g) scale(%.3g,%.3g) rotate(%g)\"", p1.x-x1, hh-p1.y, ss, -ss, -phi);
+				if(q.n3&4)
+					mgl_printf(fp, gz, " stroke=\"#%02x%02x%02x\">", int(cp.r[0]),int(cp.r[1]),int(cp.r[2]));
+				else
+					mgl_printf(fp, gz, " fill=\"#%02x%02x%02x\">", int(cp.r[0]),int(cp.r[1]),int(cp.r[2]));
+				mreal dy = 0.004,f=fabs(zz);
+				mgl_printf(fp, gz, "<path d=\"M %g %g L %g %g L %g %g L %g %g\"/></g>\n", xx,yy+dy, xx+f,yy+dy, xx+f,yy-dy, xx,yy-dy);
+			}
+			else
+			{
+				ss *= zz;
+				mgl_printf(fp, gz, "<g transform=\"translate(%g,%g) scale(%.3g,%.3g) rotate(%g)\"", p1.x-x1, hh-p1.y, ss, -ss, -q.w);
+				if(q.n3&4)
+					mgl_printf(fp, gz, " stroke=\"#%02x%02x%02x\">", int(cp.r[0]),int(cp.r[1]),int(cp.r[2]));
+				else
+					mgl_printf(fp, gz, " fill=\"#%02x%02x%02x\">", int(cp.r[0]),int(cp.r[1]),int(cp.r[2]));
+				mgl_printf(fp, gz, "<use x=\"%g\" y=\"%g\" xlink:href=\"#%c%c_%04x\"/></g>\n", xx/zz, yy/zz, q.n3&1?'b':'n', q.n3&2?'i':'n', q.n4);
+			}
+		}
+	}
+
+	for(long i=0;i<gr->GetPrmNum();i++)
+	{	mglPrim &q=gr->GetPrm(i);	if(q.type==-1)	q.type = 1;	}
+	mgl_printf(fp, gz, "</g></svg>");
+	if(strcmp(fname,"-"))	{	if(gz)	gzclose((gzFile)fp);	else	fclose((FILE *)fp);	}
+	setlocale(LC_NUMERIC, loc.c_str());
+}
+void MGL_EXPORT mgl_write_svg_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *d=new char[n+1];	memcpy(d,descr,n);	d[n]=0;
+	mgl_write_svg(_GR_,s,d);	delete []s;		delete []d;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_write_tex(HMGL gr, const char *fname,const char *descr)
+{
+	if(gr->GetPrmNum()<1)	return;
+	_Gr_->clr(MGL_FINISHED);	_Gr_->PreparePrim(1);
+
+	FILE *fp = fopen(fname,"w");	fwide(fp,1);
+	if(!fp)		{	gr->SetWarn(mglWarnOpen,fname);	return;	}
+	const std::string loc = setlocale(LC_NUMERIC, "C");
+	fwprintf(fp, L"%% Created by MathGL library\n%% Title: %s\n\n",descr?descr:fname);
+	// provide marks
+	fwprintf(fp, L"\\providecommand{\\mglp}[4]{\\draw[#3] (#1-#4, #2) -- (#1+#4,#2) (#1,#2-#4) -- (#1,#2+#4);}\n");
+	fwprintf(fp, L"\\providecommand{\\mglx}[4]{\\draw[#3] (#1-#4, #2-#4) -- (#1+#4,#2+#4) (#1+#4,#2-#4) -- (#1-#4,#2+#4);}\n");
+	fwprintf(fp, L"\\providecommand{\\mgls}[4]{\\draw[#3] (#1-#4, #2-#4) -- (#1+#4,#2-#4) -- (#1+#4,#2+#4) -- (#1-#4,#2+#4) -- cycle;}\n");
+	fwprintf(fp, L"\\providecommand{\\mglS}[4]{\\fill[#3] (#1-#4, #2-#4) -- (#1+#4,#2-#4) -- (#1+#4,#2+#4) -- (#1-#4,#2+#4) -- cycle;}\n");
+	fwprintf(fp, L"\\providecommand{\\mgld}[4]{\\draw[#3] (#1, #2-#4) -- (#1+#4,#2) -- (#1,#2+#4) -- (#1-#4,#2) -- cycle;}\n");
+	fwprintf(fp, L"\\providecommand{\\mglD}[4]{\\fill[#3] (#1, #2-#4) -- (#1+#4,#2) -- (#1,#2+#4) -- (#1-#4,#2) -- cycle;}\n");
+	fwprintf(fp, L"\\providecommand{\\mglv}[4]{\\draw[#3] (#1-#4, #2+#4/2) -- (#1+#4,#2+#4/2) -- (#1,#2-#4) -- cycle;}\n");
+	fwprintf(fp, L"\\providecommand{\\mglV}[4]{\\fill[#3] (#1-#4, #2+#4/2) -- (#1+#4,#2+#4/2) -- (#1,#2-#4) -- cycle;}\n");
+	fwprintf(fp, L"\\providecommand{\\mglt}[4]{\\draw[#3] (#1-#4, #2-#4/2) -- (#1+#4,#2-#4/2) -- (#1,#2+#4) -- cycle;}\n");
+	fwprintf(fp, L"\\providecommand{\\mglT}[4]{\\fill[#3] (#1-#4, #2-#4/2) -- (#1+#4,#2-#4/2) -- (#1,#2+#4) -- cycle;}\n");
+	fwprintf(fp, L"\\providecommand{\\mgll}[4]{\\draw[#3] (#1+#4/2, #2-#4) -- (#1+#4/2,#2+#4) -- (#1-#4,#2) -- cycle;}\n");
+	fwprintf(fp, L"\\providecommand{\\mglL}[4]{\\fill[#3] (#1+#4/2, #2-#4) -- (#1+#4/2,#2+#4) -- (#1-#4,#2) -- cycle;}\n");
+	fwprintf(fp, L"\\providecommand{\\mglr}[4]{\\draw[#3] (#1-#4/2, #2-#4) -- (#1-#4/2,#2+#4) -- (#1+#4,#2) -- cycle;}\n");
+	fwprintf(fp, L"\\providecommand{\\mglR}[4]{\\fill[#3] (#1-#4/2, #2-#4) -- (#1-#4/2,#2+#4) -- (#1+#4,#2) -- cycle;}\n");
+	fwprintf(fp, L"\\providecommand{\\mglR}[4]{\\draw[#3] (#1, #2-#4) -- (#1,#2) -- (#1-#4,#2+#4) (#1,#2) -- (#1+#4,#2+#4);}\n");
+	fwprintf(fp, L"\\providecommand{\\mgla}[4]{\\draw[#3] (#1-#4, #2) -- (#1+#4,#2) (#1-0.6*#4,#2-0.8*#4) -- (#1+0.6*#4,#2+0.8*#4) (#1-0.6*#4,#2+0.8*#4) -- (#1+0.6*#4,#2-0.8*#4);}\n");
+	fwprintf(fp, L"\\providecommand{\\mglY}[4]{\\draw[#3] (#1, #2-#4) -- (#1,#2) (#1-#4,#2+#4) -- (#1,#2) (#1+#4,#2+#4) -- (#1,#2);}\n");
+	fwprintf(fp, L"\\providecommand{\\mglo}[4]{\\draw[#3] (#1, #2) circle (#4);}\n");
+	fwprintf(fp, L"\\providecommand{\\mglO}[4]{\\fill[#3] (#1, #2) circle (#4);}\n");
+	fwprintf(fp, L"\\providecommand{\\mglc}[3]{\\draw[#3] (#1, #2) circle (%g);}\n\n", 4e-4*gr->mark_size());
+	fwprintf(fp, L"\\begin{tikzpicture}\n");
+
+	// write primitives first
+	mreal wp=-1;
+	int st=0;
+	mglRGBA cp;
+	char cname[128];
+
+	for(long i=0;i<gr->GetPrmNum();i++)
+	{
+		const mglPrim &q = gr->GetPrm(i);
+		if(q.type<0)	continue;	// q.n1>=0 always
+		cp.c = _Gr_->GetPrmCol(i);
+		snprintf(cname,128,"color={rgb,255:red,%d;green,%d;blue,%d}",cp.r[0],cp.r[1],cp.r[2]);	cname[127]=0;
+
+		const mglPnt p1=gr->GetPnt(q.n1);
+		mreal x=p1.x/100,y=p1.y/100,s=q.s/100;
+		if(q.type==0)
+		{
+			if(!strchr("xsSoO",q.n4))	s *= 1.1;
+			wp = 1;
+			switch(q.n4)	// NOTE: no thickness for marks in TeX
+			{
+				case 'P':
+					fwprintf(fp, L"\\mglp{%.4g}{%.4g}{%s}{%.4g} \\mgls{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s,x,y,cname,s);	break;
+				case 'X':
+					fwprintf(fp, L"\\mglx{%.4g}{%.4g}{%s}{%.4g} \\mgls{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s,x,y,cname,s);	break;
+				case 'C':
+					fwprintf(fp, L"\\mglc{%.4g}{%.4g}{%s}{%.4g} \\mglo{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s,x,y,cname,s);	break;
+				case '+':	fwprintf(fp, L"\\mglp{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s);	break;
+				case 'x':	fwprintf(fp, L"\\mglx{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s);	break;
+				case 's':	fwprintf(fp, L"\\mgls{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s);	break;
+				case 'S':	fwprintf(fp, L"\\mglS{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s);	break;
+				case 'd':	fwprintf(fp, L"\\mgld{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s);	break;
+				case 'D':	fwprintf(fp, L"\\mglD{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s);	break;
+				case '^':	fwprintf(fp, L"\\mglt{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s);	break;
+				case 'T':	fwprintf(fp, L"\\mglT{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s);	break;
+				case 'v':	fwprintf(fp, L"\\mglv{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s);	break;
+				case 'V':	fwprintf(fp, L"\\mglV{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s);	break;
+				case '<':	fwprintf(fp, L"\\mgll{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s);	break;
+				case 'L':	fwprintf(fp, L"\\mglL{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s);	break;
+				case '>':	fwprintf(fp, L"\\mglr{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s);	break;
+				case 'R':	fwprintf(fp, L"\\mglR{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s);	break;
+				case 'Y':	fwprintf(fp, L"\\mglY{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s);	break;
+				case 'o':	fwprintf(fp, L"\\mglo{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s);	break;
+				case 'O':	fwprintf(fp, L"\\mglO{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s);	break;
+				case '*':	fwprintf(fp, L"\\mgla{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s);	break;
+				default:	fwprintf(fp, L"\\mglc{%.4g}{%.4g}{%s}\n", x,y,cname);	break;
+			}
+		}
+		else if(q.type==2 && cp.r[3])
+		{
+			const mglPnt p2=gr->GetPnt(q.n2), p3=gr->GetPnt(q.n3);
+			if(cp.r[3]<255)
+				fwprintf(fp, L"\\fill[%s, fill opacity=%.4g] (%.4g,%.4g) -- (%.4g,%.4g) -- (%.4g,%.4g) -- cycle;\n", cname,cp.r[3]/255., x,y, p2.x/100,p2.y/100, p3.x/100,p3.y/100);
+			else
+				fwprintf(fp, L"\\fill[%s, fill] (%.4g,%.4g) -- (%.4g,%.4g) -- (%.4g,%.4g) -- cycle;\n", cname, x,y, p2.x/100,p2.y/100, p3.x/100,p3.y/100);
+		}
+		else if(q.type==3 && cp.r[3])
+		{
+			const mglPnt p2=gr->GetPnt(q.n2), p3=gr->GetPnt(q.n3), p4=gr->GetPnt(q.n4);
+			if(cp.r[3]<255)
+				fwprintf(fp, L"\\fill[%s, fill opacity=%.4g] (%.4g,%.4g) -- (%.4g,%.4g) -- (%.4g,%.4g) -- (%.4g,%.4g) -- cycle;\n", cname,cp.r[3]/255., x,y, p2.x/100,p2.y/100, p4.x/100,p4.y/100, p3.x/100,p3.y/100);
+			else
+				fwprintf(fp, L"\\fill[%s, fill] (%.4g,%.4g) -- (%.4g,%.4g) -- (%.4g,%.4g) -- (%.4g,%.4g) -- cycle;\n", cname, x,y, p2.x/100,p2.y/100, p4.x/100,p4.y/100, p3.x/100,p3.y/100);
+
+		}
+		else if(q.type==1)	// lines
+		{
+			//const char *dash[]={"", "8 8","4 4","1 3","7 4 1 4","3 2 1 2"};
+			const char *w[]={"semithick","thick","very thick","ultra thick"};
+			int iw=int(q.w-0.5);	if(iw>3)	iw=3;
+			if(iw<0)	fwprintf(fp,L"\\draw[%s] ",cname);
+			else		fwprintf(fp,L"\\draw[%s,%s] ",cname,w[iw]);
+			// TODO: add line dashing
+			wp = q.w>1  ? q.w:1;	st = q.n3;
+			std::vector<long> ids = put_line(gr,i,wp,cp.c,st);
+			for(size_t j=0;j<ids.size();j++)
+			{
+				const mglPnt &p = gr->GetPnt(ids[j]);
+				float x0 = p.x, y0 = p.y;
+				fwprintf(fp, j==0?L"(%.4g,%.4g)":L" -- (%.4g,%.4g)",0.01*x0,y0*0.01);
+			}
+			fwprintf(fp, L";\n");
+		}
+		else if(q.type==6 && mgl_isnum(q.p))	// text
+		{
+			const mglText &t = gr->GetPtx(q.n3);
+			mreal dy = q.w*cos(q.p*M_PI/180)/100, dx = q.w*sin(q.p*M_PI/180)/100;
+			int f,a;	mglGetStyle(t.stl.c_str(), &f, &a);
+			std::string ss=cname;
+			if((a&3)==0)	ss.append(",anchor=base west");
+			if((a&3)==1)	ss.append(",anchor=base");
+			if((a&3)==2)	ss.append(",anchor=base east");
+//			if(f&MGL_FONT_ITAL)	ss.append(",font=\\itshape");
+//			if(f&MGL_FONT_BOLD)	ss.append(",font=\\bfshape");
+			if(t.text.find('\\')!=std::string::npos || t.text.find('{')!=std::string::npos || t.text.find('_')!=std::string::npos || t.text.find('^')!=std::string::npos)
+				fwprintf(fp,L"\\draw[%s] (%.4g,%.4g) node[rotate=%.2g]{$%ls$};\n", ss.c_str(),x-dx,y-dy, -q.p, t.text.c_str());
+			else
+				fwprintf(fp,L"\\draw[%s] (%.4g,%.4g) node[rotate=%.2g]{%ls};\n", ss.c_str(),x-dx,y-dy, -q.p, t.text.c_str());
+		}
+	}
+	fwprintf(fp, L"\\end{tikzpicture}\n");
+	for(long i=0;i<gr->GetPrmNum();i++)
+	{	mglPrim &q=gr->GetPrm(i);	if(q.type==-1)	q.type = 1;	}
+	fclose(fp);
+	setlocale(LC_NUMERIC, loc.c_str());
+
+	// provide main file for viewing figure
+	fp=fopen("mglmain.tex","wt");
+	if(fp)
+	{
+		fprintf(fp, "%% this file just show figure\n");
+		fprintf(fp, "\\documentclass{article}\n\\usepackage{tikz}\n");
+		fprintf(fp, "\\usepackage[T2A]{fontenc}\n\\usepackage[utf8]{inputenc}\n");
+		fprintf(fp, "\\begin{document}\n\\input{%s}\n\\end{document}\n",fname);
+		fclose(fp);
+	}
+}
+void MGL_EXPORT mgl_write_tex_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *d=new char[n+1];	memcpy(d,descr,n);	d[n]=0;
+	mgl_write_tex(_GR_,s,d);	delete []s;		delete []d;	}
+//-----------------------------------------------------------------------------
diff --git a/src/export_3d.cpp b/src/export_3d.cpp
new file mode 100644
index 0000000..cb01fcb
--- /dev/null
+++ b/src/export_3d.cpp
@@ -0,0 +1,1327 @@
+/***************************************************************************
+ * export_3d.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <time.h>
+#include <stdarg.h>
+#include "mgl2/canvas.h"
+#include "mgl2/canvas_cf.h"
+#undef _GR_
+#define _GR_	((mglCanvas *)(*gr))
+#define _Gr_	((mglCanvas *)(gr))
+int MGL_NO_EXPORT mgl_tga_save(const char *fname, int w, int h, unsigned char **p);
+int MGL_NO_EXPORT mgl_pnga_save(const char *fname, int w, int h, unsigned char **p);
+void MGL_NO_EXPORT mgl_printf(void *fp, bool gz, const char *str, ...);
+std::string MGL_NO_EXPORT mgl_sprintf(const char *str, ...);
+//-----------------------------------------------------------------------------
+void mglTexture::GetRGBA(unsigned char *f) const
+{
+	for(long i=255;i>=0;i--)
+	{
+		mglColor c1 = col[2*i], c2 = col[2*i+1];
+		for(long j=0;j<256;j++)
+		{
+			long i0 = 4*(j+256*i);
+			mglColor c = c1 + (c2-c1)*(j/255.);
+			f[i0]   = int(255*c.r);
+			f[i0+1] = int(255*c.g);
+			f[i0+2] = int(255*c.b);
+			f[i0+3] = int(255*c.a);
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_obj_glyph_old(HMGL gr, const mglPrim &q, const mglPnt &p, FILE *fp)
+{
+	mreal f = q.p/2, dx=p.u/2, dy=p.v/2, x,y;
+	mreal c=q.s*cos(q.w*M_PI/180), s=-q.s*sin(q.w*M_PI/180);
+	if(mgl_isnan(q.s))	c=s=0;
+	double b[4] = {c,-s, s,c};
+	long i=q.n1+1;
+
+	const mglGlyph &g = gr->GetGlf(q.n4);
+	const mreal dd = 0.004;
+	if(q.n3&8)
+	{
+		fprintf(fp,"v %g %g %g\n",p.x+b[0]*dx+b[1]*(dy-dd),p.y+b[2]*dx+b[3]*(dy-dd),p.z);
+		fprintf(fp,"v %g %g %g\n",p.x+b[0]*dx+b[1]*(dy+dd),p.y+b[2]*dx+b[3]*(dy+dd),p.z);
+		fprintf(fp,"v %g %g %g\n",p.x+b[0]*(dx+f)+b[1]*(dy-dd),p.y+b[2]*dx+b[3]*(dy-dd),p.z);
+		fprintf(fp,"v %g %g %g\n",p.x+b[0]*(dx+f)+b[1]*(dy+dd),p.y+b[2]*dx+b[3]*(dy+dd),p.z);
+		if(!(q.n3&4))	// glyph_line(p,f,true, d);
+		{
+			fprintf(fp,"f -1/%ld -3/%ld -2/%ld\n",i,i,i);
+			fprintf(fp,"f -4/%ld -2/%ld -3/%ld\n",i,i,i);
+		}
+		else	// glyph_line(p,f,false, d);
+		{
+			fprintf(fp,"l -1/%ld -2/%ld\n",i,i);
+			fprintf(fp,"l -3/%ld -4/%ld\n",i,i);
+			fprintf(fp,"l -1/%ld -3/%ld\n",i,i);
+			fprintf(fp,"l -2/%ld -4/%ld\n",i,i);
+		}
+	}
+	else
+	{
+		if(!(q.n3&4))	// glyph_fill(p,f,g, d);
+		{
+			for(long ik=0;ik<g.nt;ik++)
+			{
+				x = dx+f*g.trig[6*ik];		y = dy+f*g.trig[6*ik+1];
+				fprintf(fp,"v %g %g %g\n",p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
+				x = dx+f*g.trig[6*ik+2];	y = dy+f*g.trig[6*ik+3];
+				fprintf(fp,"v %g %g %g\n",p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
+				x = dx+f*g.trig[6*ik+4];	y = dy+f*g.trig[6*ik+5];
+				fprintf(fp,"v %g %g %g\n",p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
+				fprintf(fp,"f -1/%ld -3/%ld -2/%ld\n",i,i,i);
+			}
+		}
+		else	// glyph_wire(p,f,g, d);
+		{
+			long il=0;
+			for(long ik=0;ik<g.nl;ik++)
+			{
+				x = g.line[2*ik];	y = g.line[2*ik+1];
+				if(x==0x3fff && y==0x3fff)	// line breakthrough
+				{	il = ik+1;	continue;	}
+				else if(ik==g.nl-1 || (g.line[2*ik+2]==0x3fff && g.line[2*ik+3]==0x3fff))
+				{	// enclose the circle. May be in future this block should be commented
+					x = dx+f*g.line[2*ik];		y = dy+f*g.line[2*ik+1];
+					fprintf(fp,"v %g %g %g\n",p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
+					x = dx+f*g.line[2*il];		y = dy+f*g.line[2*il+1];
+					fprintf(fp,"v %g %g %g\n",p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
+				}
+				else
+				{	// normal line
+					x = dx+f*g.line[2*ik];		y = dy+f*g.line[2*ik+1];
+					fprintf(fp,"v %g %g %g\n",p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
+					x = dx+f*g.line[2*ik+2];	y = dy+f*g.line[2*ik+3];
+					fprintf(fp,"v %g %g %g\n",p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
+				}
+				fprintf(fp,"l -1/%ld -2/%ld\n",i,i);
+			}
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+/* M.Vidassov take/move it into src/obj.cpp */
+void MGL_EXPORT mgl_obj_prim_old(HMGL gr, const mglPrim &q, const mglPnt &p, FILE *fp, mreal size)
+{
+	char type = q.n4;	mreal ss=size;
+	long i=q.n1+1, n1=q.n1+1,n2=q.n2+1,n3=q.n3+1,n4=q.n4+1;
+	switch(q.type)
+	{
+	case 0:
+		if(!strchr("xsSoO",type))	ss *= 1.1;
+		if(type=='.' || ss==0)	fprintf(fp,"p %ld\n", i);
+		else	switch(type)
+		{
+		case 'P':
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss,p.z);
+			fprintf(fp,"l -4/%ld -3/%ld\n", i,i);
+			fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
+			fprintf(fp,"l -1/%ld -4/%ld\n", i,i);
+		case '+':
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x,p.y+ss,p.z);
+			fprintf(fp,"l -4/%ld -3/%ld\n", i,i);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);	break;
+		case 'X':
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss,p.z);
+			fprintf(fp,"l -4/%ld -3/%ld\n", i,i);
+			fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
+			fprintf(fp,"l -1/%ld -4/%ld\n", i,i);
+			fprintf(fp,"l -1/%ld -3/%ld\n", i,i);
+			fprintf(fp,"l -2/%ld -4/%ld\n", i,i);	break;
+		case 'x':
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss,p.z);
+			fprintf(fp,"l -1/%ld -3/%ld\n", i,i);
+			fprintf(fp,"l -2/%ld -4/%ld\n", i,i);	break;
+		case 'S':
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss,p.z);
+			fprintf(fp,"f -4/%ld -3/%ld -2/%ld -1/%ld\n",i,i,i,i);	break;
+		case 's':
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss,p.z);
+			fprintf(fp,"l -4/%ld -3/%ld\n", i,i);
+			fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
+			fprintf(fp,"l -1/%ld -4/%ld\n", i,i);	break;
+		case 'D':
+			fprintf(fp,"v %g %g %g\n",p.x,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
+			fprintf(fp,"f -4/%ld -3/%ld -2/%ld -1/%ld\n",i,i,i,i);	break;
+		case 'd':
+			fprintf(fp,"v %g %g %g\n",p.x,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
+			fprintf(fp,"l -4/%ld -3/%ld\n", i,i);
+			fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
+			fprintf(fp,"l -1/%ld -4/%ld\n", i,i);	break;
+		case 'Y':
+			fprintf(fp,"v %g %g %g\n",p.x,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+0.8*ss,p.y+0.6*ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-0.8*ss,p.y+0.6*ss,p.z);
+			fprintf(fp,"l -3/%ld %ld/%ld\n", i,i,i);
+			fprintf(fp,"l -2/%ld %ld/%ld\n", i,i,i);
+			fprintf(fp,"l -1/%ld %ld/%ld\n", i,i,i);	break;
+		case '*':
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
+			fprintf(fp,"v %g %g %g\n",p.x+0.6*ss,p.y+0.8*ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-0.6*ss,p.y-0.8*ss,p.z);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
+			fprintf(fp,"v %g %g %g\n",p.x+0.6*ss,p.y-0.8*ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-0.6*ss,p.y+0.8*ss,p.z);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);		break;
+		case 'T':
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss/2,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss/2,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x,p.y+ss,p.z);
+			fprintf(fp,"f -3/%ld -2/%ld -1/%ld\n", i,i,i);	break;
+		case '^':
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss/2,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss/2,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x,p.y+ss,p.z);
+			fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
+			fprintf(fp,"l -1/%ld -3/%ld\n", i,i);	break;
+		case 'V':
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss/2,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss/2,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x,p.y-ss,p.z);
+			fprintf(fp,"f -3/%ld -2/%ld -1/%ld\n", i,i,i);	break;
+		case 'v':
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss/2,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss/2,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x,p.y-ss,p.z);
+			fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
+			fprintf(fp,"l -1/%ld -3/%ld\n", i,i);	break;
+		case 'L':
+			fprintf(fp,"v %g %g %g\n",p.x+ss/2,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss/2,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
+			fprintf(fp,"f -3/%ld -2/%ld -1/%ld\n", i,i,i);	break;
+		case '<':
+			fprintf(fp,"v %g %g %g\n",p.x+ss/2,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss/2,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
+			fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
+			fprintf(fp,"l -1/%ld -3/%ld\n", i,i);	break;
+		case 'R':
+			fprintf(fp,"v %g %g %g\n",p.x-ss/2,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss/2,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
+			fprintf(fp,"f -3/%ld -2/%ld -1/%ld\n", i,i,i);	break;
+		case '>':
+			fprintf(fp,"v %g %g %g\n",p.x-ss/2,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss/2,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
+			fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
+			fprintf(fp,"l -1/%ld -3/%ld\n", i,i);	break;
+		case 'O':
+			for(long j=0;j<=20;j++)
+				fprintf(fp,"v %g %g %g\n",p.x+ss*mgl_cos[(j*36)%360],p.y+ss*mgl_cos[(270+j*36)%360],p.z);
+			for(long j=0;j<20;j++)
+				fprintf(fp,"f %ld/%ld %ld/%ld %ld/%ld\n", j-21,i, j-20,i, i,i);
+			break;
+		case 'C':	fprintf(fp,"p %ld\n", i);
+		case 'o':
+			for(long j=0;j<=20;j++)
+				fprintf(fp,"v %g %g %g\n",p.x+ss*mgl_cos[(j*36)%360],p.y+ss*mgl_cos[(270+j*36)%360],p.z);
+			for(long j=0;j<20;j++)
+				fprintf(fp,"l %ld/%ld %ld/%ld\n", j-21,i, j-20,i);
+			break;
+		}
+		break;
+	case 1:	fprintf(fp,"l %ld/%ld %ld/%ld\n", n1,n1, n2,n2);	break;
+	case 2:	fprintf(fp,"f %ld/%ld %ld/%ld %ld/%ld\n", n1,n1, n2,n2, n3,n3);	break;
+	case 3:	fprintf(fp,"f %ld/%ld %ld/%ld %ld/%ld\n", n1,n1, n2,n2, n3,n3);
+		fprintf(fp,"f %ld/%ld %ld/%ld %ld/%ld\n", n2,n2, n4,n4, n3,n3);	break;
+	case 4:	mgl_obj_glyph_old(gr,q,p,fp);		break;
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_write_obj_old(HMGL gr, const char *fname,const char *descr, int use_png)
+{
+	if(gr->GetPrmNum()==0)	return;	// nothing to do
+	long m1=0,m2=0;
+	for(size_t i=0;i<gr->Grp.size();i++)	// prepare array of indirect indexing
+	{	long m = gr->Grp[i].Id;	if(m<m1) m1=m;	if(m>m2) m2=m;	}
+	long *ng = new long[m2-m1+1];
+	for(size_t i=0;i<gr->Grp.size();i++)	ng[gr->Grp[i].Id-m1] = i;
+	for(long i=0;i<gr->GetPrmNum();i++)	// collect data for groups
+	// it is rather expensive (extra 4b per primitive) but need for export to 3D
+	{
+		long m = gr->GetPrm(i,false).id-m1;
+		if(m>=0 && m<m2-m1+1)	gr->Grp[ng[m]].p.push_back(i);
+	}
+	delete []ng;
+
+	size_t len=strlen(fname),ntxt=gr->GetTxtNum();
+	FILE *fp=fopen(fname,"wt");
+	if(!fp)		{	gr->SetWarn(mglWarnOpen,fname);	return;	}
+	// vertices definition
+	const std::string loc = setlocale(LC_NUMERIC, "C");
+	fprintf(fp,"# Created by MathGL library\n# Title: %s\n",(descr && *descr) ? descr : fname);
+	for(long i=0;i<gr->GetPntNum();i++)
+	{
+		const mglPnt &pp = gr->GetPnt(i);
+		fprintf(fp,"v %g %g %g\n",pp.x,pp.y,pp.z);
+		fprintf(fp,"vt %g %g\n",1-pp.ta,pp.c/ntxt);
+//		if(mgl_isnan(pp.u))	fprintf(fp,"vn 0 0 0\n");
+//		else fprintf(fp,"vn %g %g %g\n",pp.u,pp.v,pp.w);
+	}
+	// primitive definition in groups
+	char *tname = new char[len+5];	strcpy(tname,fname);
+	tname[len-4]=0;	fprintf(fp,"# Primitives Definitions\nmtllib %s.mtl\nusemtl %s\n",tname,tname);
+	for(size_t i=0;i<gr->Grp.size();i++)
+	{
+		fprintf(fp,"g %s\n",gr->Grp[i].Lbl.c_str());
+		std::vector<long> &p = gr->Grp[i].p;
+		for(size_t j=0;j<p.size();j++)
+		{
+			const mglPrim &q=gr->GetPrm(p[j],false);
+			mgl_obj_prim_old(gr, q, gr->GetPnt(q.n1), fp, mgl_isnan(q.s)?0:q.s);
+		}
+		gr->Grp[i].p.clear();	// we don't need indexes anymore
+	}
+	// try to save "ungrouped" primitives
+	fclose(fp);
+	// prepare MTL file
+	tname[len-4]='.';	tname[len-3]='m';	tname[len-2]='t';	tname[len-1]='l';
+	fp=fopen(tname,"wt");
+	tname[len-4]=0;	fprintf(fp,"newmtl %s\n",tname);
+	fprintf(fp,"Ka 1.000 1.000 1.000\n");
+	fprintf(fp,"Kd 1.000 1.000 1.000\n");
+	fprintf(fp,"Ks 0.000 0.000 0.000\n");
+	fprintf(fp,"d 1.0\nillum 2\n");
+	if(use_png)	strcat(tname,"_txt.png");
+//	{	tname[len-4]='.';	tname[len-3]='p';	tname[len-2]='n';	tname[len-1]='g';	}
+	else		strcat(tname,"_txt.tga");
+//	{	tname[len-4]='.';	tname[len-3]='t';	tname[len-2]='g';	tname[len-1]='a';	}
+	fprintf(fp,"map_Ka %s\nmap_Kd %s\nmap_Ks %s\n",tname,tname,tname);
+	fclose(fp);
+	// prepare texture file (TGA or PNG)
+	long j=gr->GetTxtNum();
+	unsigned char *buf = new unsigned char[4*256*256*j];
+	unsigned char **pbuf= (unsigned char **)malloc(256*j*sizeof(unsigned char *));
+	for(long i=0;i<256*j;i++)	pbuf[i] = buf+4*256*i;
+	for(long i=0;i<j;i++)	gr->GetTxt(i).GetRGBA(buf+i*256*256*4);
+	if(use_png)	mgl_pnga_save(tname,256,256*j,pbuf);
+	else		mgl_tga_save(tname,256,256*j,pbuf);
+	free(pbuf);	delete []buf;	delete []tname;
+	setlocale(LC_NUMERIC, loc.c_str());
+}
+void MGL_EXPORT mgl_write_obj_old_(uintptr_t *gr, const char *fname,const char *descr, int *use_png,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *d=new char[n+1];	memcpy(d,descr,n);	d[n]=0;
+	mgl_write_obj_old(_GR_,s,d,*use_png);	delete []s;		delete []d;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_write_stl(HMGL gr, const char *fname,const char *descr)
+{
+	if(gr->GetPrmNum()==0)	return;	// nothing to do
+	FILE *fp = fopen(fname,"wt");
+	if(!fp)		{	gr->SetWarn(mglWarnOpen,fname);	return;	}
+	const std::string loc = setlocale(LC_NUMERIC, "C");
+	fprintf(fp,"solid %s\n",(descr && *descr)?descr:"mathgl");
+	mglPnt pp;
+	for(long i=0;i<gr->GetPrmNum();i++)
+	{
+		const mglPrim &q=gr->GetPrm(i,false);
+		if(q.type==2)	//	triangles
+		{
+			pp = gr->GetPnt(q.n1);
+			fprintf(fp,"facet normal %.2g %.2g %.2g\nouter loop\n",pp.u,pp.v,pp.w);
+			fprintf(fp,"vertex %g %g %g\n",pp.x,pp.y,pp.z);
+			pp = gr->GetPnt(q.n2);
+			fprintf(fp,"vertex %g %g %g\n",pp.x,pp.y,pp.z);
+			pp = gr->GetPnt(q.n3);
+			fprintf(fp,"vertex %g %g %g\n",pp.x,pp.y,pp.z);
+			fprintf(fp,"endloop\nendfacet\n");
+		}
+		if(q.type==3)	//	quadrangles
+		{
+			pp = gr->GetPnt(q.n1);
+			fprintf(fp,"facet normal %.2g %.2g %.2g\nouter loop\n",pp.u,pp.v,pp.w);
+			fprintf(fp,"vertex %g %g %g\n",pp.x,pp.y,pp.z);
+			pp = gr->GetPnt(q.n2);
+			fprintf(fp,"vertex %g %g %g\n",pp.x,pp.y,pp.z);
+			pp = gr->GetPnt(q.n3);
+			fprintf(fp,"vertex %g %g %g\n",pp.x,pp.y,pp.z);
+			fprintf(fp,"endloop\nendfacet\n");
+			pp = gr->GetPnt(q.n1);
+			fprintf(fp,"facet normal %.2g %.2g %.2g\nouter loop\n",pp.u,pp.v,pp.w);
+			pp = gr->GetPnt(q.n4);
+			fprintf(fp,"vertex %g %g %g\n",pp.x,pp.y,pp.z);
+			pp = gr->GetPnt(q.n2);
+			fprintf(fp,"vertex %g %g %g\n",pp.x,pp.y,pp.z);
+			pp = gr->GetPnt(q.n3);
+			fprintf(fp,"vertex %g %g %g\n",pp.x,pp.y,pp.z);
+			fprintf(fp,"endloop\nendfacet\n");
+		}
+	}
+	fprintf(fp,"endsolid %s",(descr && *descr)?descr:"mathgl");
+	fclose(fp);
+	setlocale(LC_NUMERIC, loc.c_str());
+}
+void MGL_EXPORT mgl_write_stl_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *d=new char[n+1];	memcpy(d,descr,n);	d[n]=0;
+	mgl_write_stl(_GR_,s,d);	delete []s;		delete []d;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_write_xyz(HMGL gr, const char *fname,const char *descr)
+{
+	if(gr->GetPrmNum()==0)	return;	// nothing to do
+
+	FILE *fp=fopen(fname,"wt"), *ff;	// vertices definition
+	if(!fp)		{	gr->SetWarn(mglWarnOpen,fname);	return;	}
+	const std::string loc = setlocale(LC_NUMERIC, "C");
+	fprintf(fp,"# Created by MathGL library\n# Title: %s\n",(descr && *descr) ? descr : fname);
+	fprintf(fp,"# List of Vertices, with (x,y,z) coordinates.\n");
+	for(long i=0;i<gr->GetPntNum();i++)
+	{
+		const mglPnt &pp = gr->GetPnt(i);
+		fprintf(fp,"%g %g %g\n",pp.x,pp.y,pp.z);
+	}
+	fclose(fp);
+
+	// primitive definition
+	size_t len=strlen(fname);
+	char *tname = new char[len+2];	strcpy(tname,fname);	tname[len+1]=tname[len]=0;
+	tname[len]='l';	fp = fopen(tname,"wt");
+	tname[len]='f';	ff = fopen(tname,"wt");
+	fprintf(fp,"# Created by MathGL library\n# Title: %s\n",(descr && *descr) ? descr : fname);
+	fprintf(fp,"# Indices of vertices to connect for lines\n");
+	fprintf(ff,"# Created by MathGL library\n# Title: %s\n",(descr && *descr) ? descr : fname);
+	fprintf(ff,"# Indices of vertices to connect for faces\n");
+	for(long i=0;i<gr->GetPrmNum();i++)
+	{
+		const mglPrim &q=gr->GetPrm(i,false);
+		if(q.type==1)	fprintf(fp,"%ld %ld\n",q.n1+1,q.n2+1);
+		if(q.type==2)	fprintf(ff,"%ld %ld %ld\n",q.n1+1,q.n2+1,q.n3+1);
+		if(q.type==3)	fprintf(ff,"%ld %ld %ld\n%ld %ld %ld\n",q.n1+1,q.n2+1,q.n3+1,q.n4+1,q.n2+1,q.n3+1);
+	}
+	fclose(fp);	fclose(ff);	delete []tname;
+	setlocale(LC_NUMERIC, loc.c_str());
+}
+void MGL_EXPORT mgl_write_xyz_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *d=new char[n+1];	memcpy(d,descr,n);	d[n]=0;
+	mgl_write_xyz(_GR_,s,d);	delete []s;		delete []d;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_write_off(HMGL gr, const char *fname,const char *descr, int colored)
+{
+	long nf=0;
+	for(long i=0;i<gr->GetPrmNum();i++)	// find number of faces
+	{
+		const mglPrim &q=gr->GetPrm(i,false);
+		if(q.type==2 || q.type==3)	nf++;
+	}
+	if(nf<=0)	return;	// nothing to do
+
+	FILE *fp=fopen(fname,"wt");
+	if(!fp)		{	gr->SetWarn(mglWarnOpen,fname);	return;	}
+	const std::string loc = setlocale(LC_NUMERIC, "C");
+	// vertices definition
+	if(colored)
+		fprintf(fp,"COFF\n# Created by MathGL library\n# Title: %s\n",(descr && *descr) ? descr : fname);
+	else
+		fprintf(fp,"OFF\n# Created by MathGL library\n# Title: %s\n",(descr && *descr) ? descr : fname);
+	fprintf(fp,"# List of Vertices, with (x,y,z,r,g,b,a) coordinates.\n");
+	fprintf(fp,"%ld %ld 0\n",gr->GetPntNum(), nf);
+	for(long i=0;i<gr->GetPntNum();i++)
+	{
+		const mglPnt &pp = gr->GetPnt(i);
+		if(colored)
+			fprintf(fp,"%g %g %g %g %g %g %g\n", pp.x, pp.y, pp.z, pp.r, pp.g, pp.b, pp.a);
+		else	fprintf(fp,"%g %g %g\n", pp.x, pp.y, pp.z);
+	}
+	for(long i=0;i<gr->GetPrmNum();i++)
+	{
+		const mglPrim &q=gr->GetPrm(i,false);
+		const mglPnt &p1=gr->GetPnt(q.n1);
+		if(colored)
+		{
+			if(q.type==2)
+				fprintf(fp,"3 %ld %ld %ld\n",q.n1,q.n2,q.n3);
+			if(q.type==3)
+				fprintf(fp,"4 %ld %ld %ld %ld\n",q.n1,q.n2,q.n4,q.n3);
+		}
+		else
+		{
+			if(q.type==2)
+			{
+				const mglPnt &p2=gr->GetPnt(q.n2), &p3=gr->GetPnt(q.n3);
+				if(p1.a>mgl_min_a || p2.a>mgl_min_a || p3.a>mgl_min_a)
+					fprintf(fp,"3 %ld %ld %ld %.2g %.2g %.2g %.2g\n",q.n1,q.n2,q.n3,
+							(p1.r+p2.r+p3.r)/3, (p1.g+p2.g+p3.g)/3, (p1.b+p2.b+p3.b)/3, (p1.a+p2.a+p3.a)/3);
+			}
+			if(q.type==3)
+			{
+				const mglPnt &p2=gr->GetPnt(q.n2), &p3=gr->GetPnt(q.n3), &p4=gr->GetPnt(q.n4);
+				if(p1.a>mgl_min_a || p2.a>mgl_min_a || p3.a>mgl_min_a || p4.a>mgl_min_a)
+					fprintf(fp,"4 %ld %ld %ld %ld %.2g %.2g %.2g %.2g\n",q.n1,q.n2,q.n4,q.n3,
+							(p1.r+p2.r+p3.r+p4.r)/4, (p1.g+p2.g+p3.g+p4.g)/4, (p1.b+p2.b+p3.b+p4.b)/4, (p1.a+p2.a+p3.a+p4.a)/4);
+			}
+		}
+	}
+	fclose(fp);
+	setlocale(LC_NUMERIC, loc.c_str());
+}
+void MGL_EXPORT mgl_write_off_(uintptr_t *gr, const char *fname,const char *descr,int *colored,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *d=new char[n+1];	memcpy(d,descr,n);	d[n]=0;
+	mgl_write_off(_GR_,s,d,*colored);	delete []s;		delete []d;	}
+//-----------------------------------------------------------------------------
+bool mglCanvas::WriteJSON(const char *fname, bool force_zlib)
+{
+	bool fl = strcmp(fname,"-");
+	bool gz = force_zlib || fname[strlen(fname)-1]=='z';
+	void *fp = fl ? (gz ? (void*)gzopen(fname,"wt") : (void*)fopen(fname,"wt")) : stdout;
+	if (!fp)	return true;
+	std::string s=GetJSON();
+	if(gz)	gzprintf((gzFile)fp, "%s", s.c_str());
+	else	fprintf((FILE *)fp, "%s", s.c_str());
+	if(fl)	{	if(gz)	gzclose((gzFile)fp);	else	fclose((FILE *)fp);	}
+	return false;
+}
+//-----------------------------------------------------------------------------
+MGL_EXPORT const char *mgl_get_json(HMGL gr)
+{
+	static std::string json;
+	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);
+	if(g)	json = g->GetJSON();
+	return json.c_str();
+}
+//-----------------------------------------------------------------------------
+std::string mglCanvas::GetJSON()
+{
+	ClearUnused();	// clear unused points
+	PreparePrim(3);
+	std::string res, buf;
+	long ll=0,l=(long)Pnt.size();
+	long factor = Width>1?10:10000;
+	const std::string loc = setlocale(LC_NUMERIC, "C");
+	res = res + mgl_sprintf("{\n\"width\":%d,\t\"height\":%d,\t\"depth\":%d,\t\"plotid\":\"%s\",\t\"npnts\":%ld,\t\"pnts\":[\n",
+			factor*Width, factor*Height, factor*Depth, PlotId.c_str(), l);
+	for(long i=0;i<l;i++)
+	{
+		const mglPnt &q=Pnt[i];
+		res += mgl_sprintf("[%ld,%ld,%ld,%d]%c\n", long(factor*q.xx), long(factor*(Height-q.yy)), long(factor*q.zz),q.sub, i+1<l?',':' ');
+	}
+
+	l = (long)Prm.size();	ll = 0;
+	for(long i=0;i<l;i++)
+	{	mglRGBA c;	c.c = GetPrmCol(i,false);	if(c.r[3])	ll++;	}
+
+	res = res + mgl_sprintf("],\t\"nprim\":%ld,\t\"prim\":[\n",ll+1);
+
+	std::vector<mglPoint> xy;	// vector for glyphs coordinates (to be separated from pnts)
+	res.reserve(60*(ll+1));
+#pragma omp parallel for private(buf)
+	for(long i=0;i<l;i++)
+	{
+		const mglPrim &p=Prm[i];	mglRGBA cp;	cp.c = GetPrmCol(i,false);
+		if(p.n1<0 || (p.type==1 && p.n2<0) || (p.type==2 && (p.n2<0 || p.n3<0)) || (p.type==3 && (p.n2<0 || p.n3<0 || p.n4<0)))
+			continue;
+		long n1=p.n1, n2=p.n2, n3=0, n4=(p.type==3||p.type==0)?p.n4:0;
+		if(p.type==2 || p.type==3)	n3 = p.n3;
+		if(p.type==4)
+		{
+			const mglPnt &q = Pnt[p.n1];
+#pragma omp critical
+			{n2 = xy.size();	xy.push_back(mglPoint(q.u,q.v,p.n2));}
+			n3 = p.n3;	n4 = p.n4;
+		}
+		if(p.type==1 && n1>n2)	{	n1=p.n2;	n2=p.n1;	}
+		long ps=p.s==p.s?long(100*factor*p.s):0, pw=p.w==p.w?long(100*p.w):0, pp=p.p==p.p?mgl_int(1e5*p.p):0;
+		if(cp.r[3]==255 || p.type==0 || p.type==1 || p.type==4 || p.type==6)
+			buf = mgl_sprintf("[%d,%ld,%ld,%ld,%ld,%d,%ld,%ld,%ld,0,\"#%02x%02x%02x\"],\n",
+				p.type, n1, n2, n3, n4, p.id, ps,pw,pp, int(cp.r[0]),int(cp.r[1]),int(cp.r[2]));
+		else if(cp.r[3])
+			buf = mgl_sprintf("[%d,%ld,%ld,%ld,%ld,%d,%ld,%ld,%ld,0,\"rgba(%d,%d,%d,%.2g)\"],\n",
+				p.type, n1, n2, n3, n4, p.id, ps,pw,pp, int(cp.r[0]),int(cp.r[1]),int(cp.r[2]),cp.r[3]/255.);
+		else	buf = "";
+#pragma omp critical
+		res += buf;
+	}
+	res += "[-1,0,0,0,0,0,0,0,0,0,\"#000000\"]\n";	// need to add this empty block
+
+	l = (long)xy.size();
+	res = res + mgl_sprintf("],\t\"ncoor\":%lu,\t\"coor\":[\n",(unsigned long)l);
+	for(long i=0;i<l;i++)
+	{
+		const mglPoint &p=xy[i];
+		const mglPnt &q=Pnt[int(0.5+p.z)];
+		long px=long(100*p.x), py=long(100*p.y);
+		if(q.u==q.u && q.v==q.v && q.w==q.w)
+			res = res + mgl_sprintf("[%ld,%ld,%ld,%ld,%ld]%c\n", px, py, long(100*q.u), long(100*q.v), long(100*q.w), i+1<l?',':' ');
+		else
+			res = res + mgl_sprintf("[%ld,%ld,1e11,1e11,1e11]%c\n", px, py, i+1<l?',':' ');
+	}
+
+	l = (long)Glf.size();
+	res = res + mgl_sprintf("],\t\"nglfs\":%lu,\t\"glfs\":[\n",(unsigned long)l);
+	for(long i=0;i<l;i++)
+	{
+		const mglGlyph &g=Glf[i];
+		res = res + mgl_sprintf("[%ld,\n\t[", g.nl);
+		for(long j=0;j<2*g.nl;j++)	res = res + mgl_sprintf("%d%c", g.line[j], j+1<2*g.nl?',':' ');
+		res = res + mgl_sprintf("]\n]%c\n", i+1<l?',':' ');
+	}
+	res = res + mgl_sprintf("]\n}\n");
+	setlocale(LC_NUMERIC, loc.c_str());
+	return res;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_write_json(HMGL gr, const char *fname,const char *)
+{	_Gr_->WriteJSON(fname);	}
+void MGL_EXPORT mgl_write_json_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,descr,n);	f[n]=0;
+	mgl_write_json(_GR_,s,f);	delete []s;		delete []f;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_write_json_z(HMGL gr, const char *fname,const char *)
+{	_Gr_->WriteJSON(fname,true);	}
+void MGL_EXPORT mgl_write_json_z_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,descr,n);	f[n]=0;
+	mgl_write_json_z(_GR_,s,f);	delete []s;		delete []f;	}
+//-----------------------------------------------------------------------------
+bool mglCanvas::ExportMGLD(const char *fname, const char *descr)
+{
+	if(Pnt.size()<1 || Prm.size()<1)	return true;
+	FILE *fp=fopen(fname,"wt");
+	if(!fp)	return true;
+	const std::string loc = setlocale(LC_NUMERIC, "C");
+	// NOTE: I'll save Ptx. So prim type=6 is useless,and no LaTeX
+	fprintf(fp,"MGLD %lu %lu %lu %lu %d %d\n# %s\n", (unsigned long)Pnt.size(), (unsigned long)Prm.size(), (unsigned long)Txt.size(), (unsigned long)Glf.size(), Width, Height, (descr && *descr) ? descr : fname);
+	fprintf(fp,"# Vertexes: x y z c t ta u v w r g b a\n");
+	for(size_t i=0;i<Pnt.size();i++)
+	{
+		const mglPnt &q=Pnt[i];
+		fprintf(fp,"%.4g\t%.4g\t%.4g\t%.4g\t%.4g\t%.4g\t%.4g\t%.4g\t%.4g\t%.4g\t%.4g\t%.4g\t%.4g\n", q.xx, q.yy, q.zz, q.c, q.t, q.ta, q.u, q.v, q.w, q.r, q.g, q.b, q.a);
+	}
+	fprintf(fp,"# Primitives: type n1 n2 n3 n4 id s w p\n");
+	for(size_t i=0;i<Prm.size();i++)
+	{
+		const mglPrim &p=Prm[i];
+		long long unsigned mask = p.m;
+		fprintf(fp,"%d\t%ld\t%ld\t%ld\t%ld\t%d\t%g\t%g\t%g\t%d\t%llu\n", p.type, p.n1, p.n2, p.n3, p.n4, p.id, p.s==p.s?p.s:0, p.w==p.w?p.w:0, p.p==p.p?p.p:0, p.angl, mask);
+	}
+	fprintf(fp,"# Textures: smooth alpha colors\n");
+	for(size_t i=0;i<Txt.size();i++)
+	{
+		const mglTexture &t=Txt[i];
+		fprintf(fp,"%d\t%.4g\t%s\n",t.Smooth,t.Alpha,t.Sch);
+	}
+	fprintf(fp,"# Glyphs: nt nl [trig] [line]\n");
+	for(size_t i=0;i<Glf.size();i++)
+	{
+		const mglGlyph &g=Glf[i];
+		fprintf(fp,"%ld\t%ld\n", g.nt, g.nl);
+		if(g.trig)
+		{
+			for(long j=0;j<6*g.nt;j++)	fprintf(fp,"%d\t",g.trig[j]);
+			fprintf(fp,"\n");
+		}
+		if(g.line)
+		{
+			for(long j=0;j<2*g.nl;j++)	fprintf(fp,"%d\t",g.line[j]);
+			fprintf(fp,"\n");
+		}
+	}
+	fclose(fp);
+	setlocale(LC_NUMERIC, loc.c_str());
+	return false;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_export_mgld(HMGL gr, const char *fname,const char *descr)
+{	_Gr_->ExportMGLD(fname, descr);	}
+void MGL_EXPORT mgl_export_mgld_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,descr,n);	f[n]=0;
+	mgl_export_mgld(_GR_,s,f);	delete []s;		delete []f;	}
+//-----------------------------------------------------------------------------
+bool mglCanvas::ImportMGLD(const char *fname, bool add)
+{
+	FILE *fp=fopen(fname,"rt");
+	if(!fp)	return true;
+	char *buf=new char[512];
+	if(!fgets(buf,512,fp))	*buf=0;
+	if(strncmp(buf,"MGLD",4))	{	delete []buf;	fclose(fp);	return true;	}
+	unsigned long n=0,m=0,l=0,k=0, npnt=0, nglf=0;
+	int w=0,h=0,d;
+	sscanf(buf+5,"%lu%lu%lu%lu%d%d",&n,&m,&l,&k,&w,&h);
+	if(w<=0 || h<=0)	{	w=Width;	h=Height;	}
+	d = long(sqrt(double(w*h)));
+	if(n==0 || m==0 || l==0)	{	delete []buf;	fclose(fp);	return true;	}
+	const std::string loc = setlocale(LC_NUMERIC, "C");
+	if(!add)	{	Clf();	Txt.clear();	}
+	else	{	ClfZB();	npnt=Pnt.size();	nglf=Glf.size();	}
+	LightScale(&B);
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_lock(&mutexGlf);
+	pthread_mutex_lock(&mutexPnt);
+	pthread_mutex_lock(&mutexPrm);
+	pthread_mutex_lock(&mutexTxt);
+#endif
+#pragma omp critical
+	{
+		Pnt.reserve(n);	Prm.reserve(m);	Txt.reserve(l);	Glf.reserve(k);
+		mglPnt p;
+		for(unsigned long i=0;i<n;i++)
+		{
+			do {	if(!fgets(buf,512,fp))	*buf=0;	mgl_strtrim(buf);	} while(*buf=='#');
+			sscanf(buf,"%g%g%g%g%g%g%g%g%g%g%g%g%g", &p.xx, &p.yy, &p.zz, &p.c, &p.t, &p.ta, &p.u, &p.v, &p.w, &p.r, &p.g, &p.b, &p.a);
+			// rescale to current image size
+			p.xx *= Width/double(w);	p.yy *= Height/double(h);	p.zz *= Depth/double(d);
+			Pnt.push_back(p);
+		}
+		mglPrim q;
+		for(unsigned long i=0;i<m;i++)
+		{
+			do {	if(!fgets(buf,512,fp))	*buf=0;	mgl_strtrim(buf);	} while(*buf=='#');
+			long long unsigned mask=MGL_SOLID_MASK;
+			sscanf(buf,"%hd%ld%ld%ld%ld%d%g%g%g%hd%llu", &q.type, &q.n1, &q.n2, &q.n3, &q.n4, &q.id, &q.s, &q.w, &q.p, &q.angl, &mask);
+			q.n1 = q.n1>=0?q.n1+npnt:-1;	q.n2 = q.n2>=0?q.n2+npnt:-1;
+			switch(q.type)
+			{
+			case 3:	q.n4 = q.n4>=0?q.n4+npnt:-1;
+			case 2:	q.n3 = q.n3>=0?q.n3+npnt:-1;	q.m = mask;	break;
+			case 4:	q.s *= (Width<Height?Width:Height)/double(w<h?w:h);
+					q.n4 = q.n4>=0?q.n4+nglf:-1;	break;
+			}
+			Prm.push_back(q);
+		}
+		mglTexture t;
+		for(unsigned long i=0;i<l;i++)
+		{
+			int sm=0;	float a;
+			do {	if(!fgets(buf,512,fp))	*buf=0;	mgl_strtrim(buf);	} while(*buf=='#');
+			size_t j,k=0;
+			for(j=0;buf[j];j++)
+			{
+				if(buf[j]<=' ' && k)	{	sm++;	k=0;	}
+				if(buf[j]>' ')	k=1;
+				if(sm==2 && k)	break;
+			}
+			sscanf(buf,"%d%g", &sm, &a);
+			t.Set(buf+j, sm, a);
+			Txt.push_back(t);
+		}
+		mglGlyph g;
+		for(unsigned long i=0;i<k;i++)
+		{
+			do {	if(!fgets(buf,512,fp))	*buf=0;	mgl_strtrim(buf);	} while(*buf=='#' || *buf==0);
+			long nt=0,nl=0;
+			sscanf(buf,"%ld%ld", &nt, &nl);	g.Create(nt,nl);
+			for(long j=0;j<6*nt;j++)	fscanf(fp,"%hd",g.trig+j);
+			for(long j=0;j<2*nl;j++)	fscanf(fp,"%hd",g.line+j);
+			Glf.push_back(g);
+		}
+	}
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_unlock(&mutexGlf);
+	pthread_mutex_unlock(&mutexPnt);
+	pthread_mutex_unlock(&mutexPrm);
+	pthread_mutex_unlock(&mutexTxt);
+#endif
+	setlocale(LC_NUMERIC, loc.c_str());
+	delete []buf;	fclose(fp);	return false;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_import_mgld(HMGL gr, const char *fname, int add)
+{	_Gr_->ImportMGLD(fname, add);	}
+void MGL_EXPORT mgl_import_mgld_(uintptr_t *gr, const char *fname, int *add, int l)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	mgl_import_mgld(_GR_,s,*add);	delete []s;	}
+//-----------------------------------------------------------------------------
+/*void MGL_EXPORT mgl_xgl_prim(const mglPrim &q, const mglPnt &p, FILE *fp, mreal size)
+{
+	char type = q.n4;	mreal ss=size*0.35;
+	long i=q.n1;
+	switch(q.type)
+	{
+	case 0:
+		if(!strchr("xsSoO",type))	ss *= 1.1;
+		if(type=='.' || ss==0)	fprintf(fp,"p %ld\n", i);
+		else	switch(type)	// TODO: save mark by PATCH
+		{
+		case 'P':
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss,p.z);
+			fprintf(fp,"l -4/%ld -3/%ld\n", i,i);
+			fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
+			fprintf(fp,"l -1/%ld -4/%ld\n", i,i);
+		case '+':
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x,p.y+ss,p.z);
+			fprintf(fp,"l -4/%ld -3/%ld\n", i,i);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);	break;
+		case 'X':
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss,p.z);
+			fprintf(fp,"l -4/%ld -3/%ld\n", i,i);
+			fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
+			fprintf(fp,"l -1/%ld -4/%ld\n", i,i);
+			fprintf(fp,"l -1/%ld -3/%ld\n", i,i);
+			fprintf(fp,"l -2/%ld -4/%ld\n", i,i);	break;
+		case 'x':
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss,p.z);
+			fprintf(fp,"l -1/%ld -3/%ld\n", i,i);
+			fprintf(fp,"l -2/%ld -4/%ld\n", i,i);	break;
+		case 'S':
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss,p.z);
+			fprintf(fp,"f -4/%ld -3/%ld -2/%ld -1/%ld\n",i,i,i,i);	break;
+		case 's':
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss,p.z);
+			fprintf(fp,"l -4/%ld -3/%ld\n", i,i);
+			fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
+			fprintf(fp,"l -1/%ld -4/%ld\n", i,i);	break;
+		case 'D':
+			fprintf(fp,"v %g %g %g\n",p.x,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
+			fprintf(fp,"f -4/%ld -3/%ld -2/%ld -1/%ld\n",i,i,i,i);	break;
+		case 'd':
+			fprintf(fp,"v %g %g %g\n",p.x,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
+			fprintf(fp,"l -4/%ld -3/%ld\n", i,i);
+			fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
+			fprintf(fp,"l -1/%ld -4/%ld\n", i,i);	break;
+		case 'Y':
+			fprintf(fp,"v %g %g %g\n",p.x,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+0.8*ss,p.y+0.6*ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-0.8*ss,p.y+0.6*ss,p.z);
+			fprintf(fp,"l -3/%ld %ld/%ld\n", i,i,i);
+			fprintf(fp,"l -2/%ld %ld/%ld\n", i,i,i);
+			fprintf(fp,"l -1/%ld %ld/%ld\n", i,i,i);	break;
+		case '*':
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
+			fprintf(fp,"v %g %g %g\n",p.x+0.6*ss,p.y+0.8*ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-0.6*ss,p.y-0.8*ss,p.z);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
+			fprintf(fp,"v %g %g %g\n",p.x+0.6*ss,p.y-0.8*ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-0.6*ss,p.y+0.8*ss,p.z);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);		break;
+		case 'T':
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss/2,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss/2,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x,p.y+ss,p.z);
+			fprintf(fp,"f -3/%ld -2/%ld -1/%ld\n", i,i,i);	break;
+		case '^':
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y-ss/2,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y-ss/2,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x,p.y+ss,p.z);
+			fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
+			fprintf(fp,"l -1/%ld -3/%ld\n", i,i);	break;
+		case 'V':
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss/2,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss/2,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x,p.y-ss,p.z);
+			fprintf(fp,"f -3/%ld -2/%ld -1/%ld\n", i,i,i);	break;
+		case 'v':
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y+ss/2,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y+ss/2,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x,p.y-ss,p.z);
+			fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
+			fprintf(fp,"l -1/%ld -3/%ld\n", i,i);	break;
+		case 'L':
+			fprintf(fp,"v %g %g %g\n",p.x+ss/2,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss/2,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
+			fprintf(fp,"f -3/%ld -2/%ld -1/%ld\n", i,i,i);	break;
+		case '<':
+			fprintf(fp,"v %g %g %g\n",p.x+ss/2,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss/2,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss,p.y,p.z);
+			fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
+			fprintf(fp,"l -1/%ld -3/%ld\n", i,i);	break;
+		case 'R':
+			fprintf(fp,"v %g %g %g\n",p.x-ss/2,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss/2,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
+			fprintf(fp,"f -3/%ld -2/%ld -1/%ld\n", i,i,i);	break;
+		case '>':
+			fprintf(fp,"v %g %g %g\n",p.x-ss/2,p.y+ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x-ss/2,p.y-ss,p.z);
+			fprintf(fp,"v %g %g %g\n",p.x+ss,p.y,p.z);
+			fprintf(fp,"l -3/%ld -2/%ld\n", i,i);
+			fprintf(fp,"l -2/%ld -1/%ld\n", i,i);
+			fprintf(fp,"l -1/%ld -3/%ld\n", i,i);	break;
+		case 'O':
+			for(long j=0;j<=20;j++)
+				fprintf(fp,"v %g %g %g\n",p.x+ss*mgl_cos[(j*36)%360],p.y+ss*mgl_cos[(270+j*36)%360],p.z);
+			for(long j=0;j<20;j++)
+				fprintf(fp,"f %ld/%ld %ld/%ld %ld/%ld\n", j-21,i, j-20,i, i,i);
+			break;
+		case 'C':	fprintf(fp,"p %ld\n", i);
+		case 'o':
+			for(long j=0;j<=20;j++)
+				fprintf(fp,"v %g %g %g\n",p.x+ss*mgl_cos[(j*36)%360],p.y+ss*mgl_cos[(270+j*36)%360],p.z);
+			for(long j=0;j<20;j++)
+				fprintf(fp,"l %ld/%ld %ld/%ld\n", j-21,i, j-20,i);
+			break;
+		}
+		break;
+	case 1:	fprintf(fp,"l %ld/%ld %ld/%ld\n", q.n1,q.n1, q.n2,q.n2);	break;
+	case 2:	fprintf(fp,"f %ld/%ld/%ld %ld/%ld/%ld %ld/%ld/%ld\n",
+		q.n1,q.n1,q.n1, q.n2,q.n2,q.n2, q.n3,q.n3,q.n3);	break;
+	case 3:	fprintf(fp,"f %ld/%ld/%ld %ld/%ld/%ld %ld/%ld/%ld %ld/%ld/%ld\n",
+		q.n1,q.n1,q.n1, q.n2,q.n2,q.n2, q.n3,q.n3,q.n3, q.n4,q.n4,q.n4);	break;
+	case 4:	break;	// TODO: add glyphs export later
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::WriteXGL(const char *fname,const char *descr)
+{
+	if(GetPrmNum()==0)	return;	// nothing to do
+	FILE *fp=fopen(fname,"wt");
+	if(!fp)	return true;
+	fprintf(fp,"<WORLD>\n<NAME>%s</NAME>\n", (descr && *descr)?descr:fname);
+	fprintf(fp,"<BACKGROUND><BACKCOLOR>%g, %g, %g</BACKCOLOR></BACKGROUND>\n", BDef[0]/255., BDef[1]/255., BDef[2]/255.);
+	fprintf(fp,"<LIGHTING>\n<AMBIENT>%g, %g, %g</AMBIENT>\n",AmbBr, AmbBr, AmbBr);
+	if(get(MGL_ENABLE_LIGHT))	for(size_t i=0;i<10;i++)
+		if(light[i].n && mgl_isnan(light[i].r.x))
+		{
+			fprintf(fp, "<DIRECTIONALLIGHT>\n<DIRECTION>%g, %g, %g</DIRECTION>\n", light[i].d.x, light[i].d.y, light[i].d.z);
+			fprintf(fp, "<SPECULAR>%g, %g, %g</SPECULAR>\n</DIRECTIONALLIGHT>\n", light[i].c.r, light[i].c.g, light[i].c.b);
+		}
+	fprintf(fp,"</LIGHTING>");
+
+	// TODO: add textures
+
+	long m1=0,m2=0,m;
+	for(size_t i=0;i<Grp.size();i++)	// prepare array of indirect indexing
+	{	m = Grp[i].Id;	if(m<m1) m1=m;	if(m>m2) m2=m;	}
+	long *ng = new long[m2-m1+1];
+	for(size_t i=0;i<Grp.size();i++)	ng[gr->Grp[i].Id-m1] = i;
+	for(size_t i=0;i<GetPrmNum();i++)	// collect data for groups
+	// it is rather expensive (extra 4b per primitive) but need for export to 3D
+	{
+		m = GetPrm(i,false).id-m1;
+		if(m>=0 && m<m2-m1+1)	Grp[ng[m]].p.push_back(i);
+	}
+	delete []ng;
+
+	std::vector<long> p;
+	mglPrim q;
+	char *pg=new char[GetPntNum()];
+	for(size_t i=0;i<Grp.size();i++)	// first write objects
+	{
+		p = Grp[i].p;	memset(pg,0,GetPntNum());
+		fprintf(fp,"<OBJECT>\n<NAME>%s</NAME>\n<MESH>\n",Grp[i].Lbl.c_str());
+		for(size_t j=0;j<p.size();j++)		// collect Pnt for this object
+		{
+			const mglPrim q=GetPrm(p[j],false);	pg[q.n1]=1;
+			if(q.type==3)	{	pg[q.n2]=1;	pg[q.n3]=1;	pg[q.n4]=1;	}
+			else if(q.type==1)	pg[q.n2]=1;
+			else if(q.type==2)	{	pg[q.n2]=1;	pg[q.n3]=1;	}
+		}
+		for(size_t j=0;j<GetPntNum();j++)	if(pg[j])	// write Pnt for this object
+		{
+			const mglPnt s=Pnt[j];
+			fprintf(fp,"<P ID=\"%u\">%g, %g, %g</P>\n",j, s.x, s.y, s.z);
+			fprintf(fp,"<N ID=\"%u\">%g, %g, %g</N>\n",j, s.x, s.y, s.z);
+		}
+		// TODO: add line styles
+		for(size_t j=0;j<p.size();j++)	// now write primitives itself
+		{
+			const mglPrim q=GetPrm(p[j],false);
+			mgl_xgl_prim(q, GetPnt(q.n1), fp, q.s*FontFactor());
+		}
+		fprintf(fp,"</MESH>\n</OBJECT>");	// finish with this object
+		Grp[i].p.clear();	// we don't need indexes anymore
+	}
+	// TODO: try to save "ungrouped" primitives
+
+	fprintf(fp,"</WORLD>");	fclose(fp);	delete []pg;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_write_xgl(HMGL gr, const char *fname,const char *descr)
+{	_Gr_->WriteXGL(fname,descr);	}
+void MGL_EXPORT mgl_write_xgl_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *d=new char[n+1];	memcpy(d,descr,n);	d[n]=0;
+	mgl_write_xgl(_GR_,s,d);	delete []s;		delete []d;	}*/
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_x3d_mdef(HMGL gr, void *fp, bool gz)
+{
+	bool m_p=false,m_x=false,m_d=false,m_v=false,m_t=false,
+	m_s=false,m_a=false,m_o=false,m_T=false,
+	m_V=false,m_S=false,m_D=false,m_Y=false,m_l=false,
+	m_L=false,m_r=false,m_R=false,m_X=false,m_P=false;
+	for(long i=0;i<gr->GetPrmNum();i++)
+	{
+		const mglPrim q = gr->GetPrm(i,false);
+		if(q.type>0)	continue;
+		if(q.n4=='+')	m_p = true;
+		if(q.n4=='x')	m_x = true;
+		if(q.n4=='s')	m_s = true;
+		if(q.n4=='d')	m_d = true;
+		if(q.n4=='v')	m_v = true;
+		if(q.n4=='^')	m_t = true;
+		if(q.n4=='*')	m_a = true;
+		if(q.n4=='o' || q.n4=='O' || q.n4=='C')	m_o = true;
+		if(q.n4=='S')	m_S = true;
+		if(q.n4=='D')	m_D = true;
+		if(q.n4=='V')	m_V = true;
+		if(q.n4=='T')	m_T = true;
+		if(q.n4=='<')	m_l = true;
+		if(q.n4=='L')	m_L = true;
+		if(q.n4=='>')	m_r = true;
+		if(q.n4=='R')	m_R = true;
+		if(q.n4=='Y')	m_Y = true;
+		if(q.n4=='P')	m_P = true;
+		if(q.n4=='X')	m_X = true;
+	}
+	if(m_P)	{	m_p=true;	m_s=true;	}
+	if(m_X)	{	m_x=true;	m_s=true;	}
+	if(m_p)	mgl_printf(fp, gz, "<ProtoDeclare name='m_p'><ProtoInterface/>\n<ProtoBody>"
+		"<LineSet vertexCount='0,1,2,3'>\n<Coordinate point='-1 0 0, 1 0 0, 0 -1 0, 0 1 0'/>"
+		"\n</LineSet></ProtoBody></ProtoDeclare>\n");
+	/*if(m_x)	mgl_printf(fp, gz, "/m_x {sm sm rm s2 s2 rl 0 sm 2 mul rm sm 2 mul s2 rl d0} def\n");	// TODO
+	 *	if(m_s)	mgl_printf(fp, gz, "/m_s {sm sm rm 0 s2 rl s2 0 rl 0 sm 2 mul rl cp d0} def\n");
+	 *	if(m_d)	mgl_printf(fp, gz, "/m_d {sm 0 rm ss ss rl ss sm rl sm sm rl cp d0} def\n");
+	 *	if(m_v)	mgl_printf(fp, gz, "/m_v {sm ss 2 div rm s2 0 rl sm sm 1.5 mul rl d0 cp} def\n");
+	 *	if(m_t)	mgl_printf(fp, gz, "/m_t {sm sm 2 div rm s2 0 rl sm ss 1.5 mul rl d0 cp} def\n");
+	 *	if(m_a)	mgl_printf(fp, gz, "/m_a {sm 0 rm s2 0 rl sm 1.6 mul sm 0.8 mul rm ss 1.2 mul ss 1.6 mul rl 0 sm 1.6 mul rm sm 1.2 mul ss 1.6 mul rl d0} def\n");
+	 *	if(m_o)	mgl_printf(fp, gz, "/m_o {ss 0 360 d0 arc} def\n");
+	 *	if(m_S)	mgl_printf(fp, gz, "/m_S {sm sm rm 0 s2 rl s2 0 rl 0 sm 2 mul rl cp} def\n");
+	 *	if(m_D)	mgl_printf(fp, gz, "/m_D {sm 0 rm ss ss rl ss sm rl sm sm rl cp} def\n");
+	 *	if(m_V)	mgl_printf(fp, gz, "/m_V {sm ss 2 div rm s2 0 rl sm sm 1.5 mul rl cp} def\n");
+	 *	if(m_T)	mgl_printf(fp, gz, "/m_T {sm sm 2 div rm s2 0 rl sm ss 1.5 mul rl cp} def\n");
+	 *	if(m_Y)	mgl_printf(fp, gz, "/m_Y {0 sm rm 0 ss rl sm ss rl s2 0 rm sm sm rl d0} def\n");
+	 *	if(m_r)	mgl_printf(fp, gz, "/m_r {sm 2 div sm rm 0 s2 rl ss 1.5 mul sm rl d0 cp} def\n");
+	 *	if(m_l)	mgl_printf(fp, gz, "/m_l {ss 2 div sm rm 0 s2 rl sm 1.5 mul sm rl d0 cp} def\n");
+	 *	if(m_R)	mgl_printf(fp, gz, "/m_R {sm 2 div sm rm 0 s2 rl ss 1.5 mul sm rl cp} def\n");
+	 *	if(m_L)	mgl_printf(fp, gz, "/m_L {ss 2 div sm rm 0 s2 rl sm 1.5 mul sm rl cp} def\n");
+	 *	if(m_P)	mgl_printf(fp, gz, "/m_P {m_p 0 sm rm m_s} def\n");
+	 *	if(m_X)	mgl_printf(fp, gz, "/m_X {m_x ss sm rm m_s} def\n");*/
+	//	if(m_C)	mgl_printf(fp, gz, "/m_C {m_c m_o} def\n");
+	mgl_printf(fp, gz, "\n");
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_x3d_prim(const mglPrim &q, const mglPnt &p, const long *pnt, void *fp,bool gz, mreal size)
+{
+	// <ProtoInstance name='EmissiveMaterial'/>
+/*		if(q.type==0)	// mark
+		{
+			mreal x0 = p1.x,y0 = p1.y;
+			sprintf(str,"1 lw %.2g %.2g %.2g rgb ", cp.r,cp.g,cp.b);
+			wp=1;
+			if(q.s!=gr->mark_size()/gr->FontFactor())
+			{
+				mgl_printf(fp, gz, "/ss {%g} def\n",q.s*0.4*gr->FontFactor());
+				mgl_printf(fp, gz, "/s2 {%g} def\n",q.s*0.8*gr->FontFactor());
+				mgl_printf(fp, gz, "/sm {-%g} def\n",q.s*0.4*gr->FontFactor());
+			}
+			switch(q.n4)
+			{
+				case '+':	mgl_printf(fp, gz, "np %g %g mt m_p %sdr\n",x0,y0,str);	break;
+				case 'x':	mgl_printf(fp, gz, "np %g %g mt m_x %sdr\n",x0,y0,str);	break;
+				case 's':	mgl_printf(fp, gz, "np %g %g mt m_s %sdr\n",x0,y0,str);	break;
+				case 'd':	mgl_printf(fp, gz, "np %g %g mt m_d %sdr\n",x0,y0,str);	break;
+				case '*':	mgl_printf(fp, gz, "np %g %g mt m_a %sdr\n",x0,y0,str);	break;
+				case 'v':	mgl_printf(fp, gz, "np %g %g mt m_v %sdr\n",x0,y0,str);	break;
+				case '^':	mgl_printf(fp, gz, "np %g %g mt m_t %sdr\n",x0,y0,str);	break;
+				case 'S':	mgl_printf(fp, gz, "np %g %g mt m_S %sfill\n",x0,y0,str);	break;
+				case 'D':	mgl_printf(fp, gz, "np %g %g mt m_D %sfill\n",x0,y0,str);	break;
+				case 'V':	mgl_printf(fp, gz, "np %g %g mt m_V %sfill\n",x0,y0,str);	break;
+				case 'T':	mgl_printf(fp, gz, "np %g %g mt m_T %sfill\n",x0,y0,str);	break;
+				case 'o':	mgl_printf(fp, gz, "%g %g m_o %sdr\n",x0,y0,str);break;
+				case 'O':	mgl_printf(fp, gz, "%g %g m_o %sfill\n",x0,y0,str);break;
+				case 'Y':	mgl_printf(fp, gz, "np %g %g mt m_Y %sdr\n",x0,y0,str);	break;
+				case '<':	mgl_printf(fp, gz, "np %g %g mt m_l %sdr\n",x0,y0,str);	break;
+				case '>':	mgl_printf(fp, gz, "np %g %g mt m_r %sdr\n",x0,y0,str);	break;
+				case 'L':	mgl_printf(fp, gz, "np %g %g mt m_L %sfill\n",x0,y0,str);	break;
+				case 'R':	mgl_printf(fp, gz, "np %g %g mt m_R %sfill\n",x0,y0,str);	break;
+				case 'P':	mgl_printf(fp, gz, "np %g %g mt m_P %sdr\n",x0,y0,str);	break;
+				case 'X':	mgl_printf(fp, gz, "np %g %g mt m_X %sdr\n",x0,y0,str);	break;
+				case 'C':	mgl_printf(fp, gz, "%g %g m_o %g %g m_c %sdr\n",x0,y0,x0,y0,str);	break;
+				default:	mgl_printf(fp, gz, "%g %g m_c %sfill\n",x0,y0,str);
+			}
+			if(q.s!=gr->mark_size()/gr->FontFactor())
+			{
+				mgl_printf(fp, gz, "/ss {%g} def\n",0.4*gr->mark_size());
+				mgl_printf(fp, gz, "/s2 {%g} def\n",0.8*gr->mark_size());
+				mgl_printf(fp, gz, "/sm {-%g} def\n",0.4*gr->mark_size());
+			}
+		}
+		else if(q.type==3)	// quad
+		{
+			const mglPnt p2=gr->GetPnt(q.n2), p3=gr->GetPnt(q.n3), p4=gr->GetPnt(q.n4);
+			mgl_printf(fp, gz, "np %g %g mt %g %g ll %g %g ll %g %g ll cp %sfill\n",
+					   p1.x, p1.y, p2.x, p2.y, p4.x, p4.y, p3.x, p3.y, str);
+		}
+		else if(q.type==2)	// trig
+		{
+			const mglPnt p2=gr->GetPnt(q.n2), p3=gr->GetPnt(q.n3);
+			mgl_printf(fp, gz, "np %g %g mt %g %g ll %g %g ll cp %sfill\n",
+					   p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, str);
+		}
+		else if(q.type==1)	// line
+		{
+			sprintf(str,"%.2g lw %.2g %.2g %.2g rgb ", q.w>1 ? q.w:1., cp.r,cp.g,cp.b);
+			wp = q.w>1  ? q.w:1;	st = q.n3;
+			put_line(gr,fp,gz,i,wp,cp,st, "np %g %g mt ", "%g %g ll ", false, 1);
+			const char *sd = mgl_get_dash(q.n3,q.w);
+			if(sd && sd[0])	mgl_printf(fp, gz, "%s [%s] %g sd dr\n",str,sd,q.w*q.s);
+			else			mgl_printf(fp, gz, "%s d0 dr\n",str);
+		}
+		else if(q.type==4)	// glyph
+		{
+			mreal 	ss = q.s/2, xx = p1.u, yy = p1.v, zz = p1.w;
+			mgl_printf(fp, gz, "gsave\t%g %g translate %g %g scale %g rotate %s\n",
+					   p1.x, p1.y, ss, ss, -q.w, str);
+			if(q.n3&8)	// this is "line"
+			{
+				mreal dy = 0.004,f=fabs(zz);
+				mgl_printf(fp, gz, "np %g %g mt %g %g ll %g %g ll %g %g ll cp ",
+						   xx,yy+dy, xx+f,yy+dy, xx+f,yy-dy, xx,yy-dy);
+			}
+			else
+				mgl_printf(fp, gz, "%.3g %.3g translate %g %g scale %c%c_%04x ",
+						   xx, yy, zz, zz, q.n3&1?'b':'n', q.n3&2?'i':'n', q.n4);
+			if(q.n3&4)	mgl_printf(fp, gz, "dr");
+			else	mgl_printf(fp, gz, "eofill");
+			mgl_printf(fp, gz, " grestore\n");
+		}*/
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_write_x3d(HMGL gr, const char *fname,const char *descr)
+{
+	if(gr->GetPrmNum()<1)	return;
+	time_t now;	time(&now);
+
+	bool gz = fname[strlen(fname)-1]=='z';
+	void *fp = gz ? (void*)gzopen(fname,"wt") : (void*)fopen(fname,"wt");
+	if(!fp)		{	gr->SetWarn(mglWarnOpen,fname);	return;	}
+	const std::string loc = setlocale(LC_NUMERIC, "C");
+	mgl_printf(fp, gz, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+	mgl_printf(fp, gz, "<!DOCTYPE X3D PUBLIC \"ISO//Web3D//DTD X3D 3.0//EN\" \"http://www.web3d.org/specifications/x3d-3.0.dtd\">\n");
+	mgl_printf(fp, gz, "<X3D profile='Immersive'>\n<head>\n<meta name='filename' content='%s'/>\n",fname);
+	mgl_printf(fp, gz, "<meta name='description' content='%s'/>\n",(descr && *descr)?descr:fname);
+	mgl_printf(fp, gz, "<meta name='created' content='%s'/>\n",ctime(&now));
+	mgl_printf(fp, gz, "<meta name='generator' content='MathGL, http://mathgl.sourceforge.net/'/>\n");
+	mgl_printf(fp, gz, "</head>\n<Scene>\n");
+
+	// 1. first we have to define proto for marks and glyphs
+	mgl_x3d_mdef(gr, fp, gz);
+
+	// here should be defined textures ... but since X3D support RGBA then omit it in this version
+
+	// 2. now find group for primitives
+	long m1=0,m2=0,m;
+	for(size_t i=0;i<gr->Grp.size();i++)	// prepare array of indirect indexing
+	{	m = gr->Grp[i].Id;	if(m<m1) m1=m;	if(m>m2) m2=m;	}
+	long *ng = new long[m2-m1+1];
+	for(size_t i=0;i<gr->Grp.size();i++)	ng[gr->Grp[i].Id-m1] = i;
+	for(long i=0;i<gr->GetPrmNum();i++)	// collect data for groups
+	// it is rather expensive (extra 4b per primitive) but need for export to 3D
+	{
+		m = gr->GetPrm(i,false).id-m1;
+		if(m>=0 && m<m2-m1+1)	gr->Grp[ng[m]].p.push_back(i);
+	}
+	delete []ng;
+
+	// primitive definition in groups
+	long npnt = gr->GetPntNum(), k;
+	long *pnt=new long[npnt];
+	mglPrim q;
+	for(size_t i=0;i<gr->Grp.size();i++)
+	{
+		mgl_printf(fp,gz,"<Group><!--%s-->\n",gr->Grp[i].Lbl.c_str());
+		std::vector<long> &p = gr->Grp[i].p;
+
+		// define coordinates, colors and so on
+		long line=-1, face=-1, other=-1;	k=0;
+		for(size_t j=0;j<p.size();j++)	// find points for this group
+		{
+			const mglPrim &q=gr->GetPrm(p[j],false);
+			if(q.type==1)	line=q.n1;	// find kind of primitives in the group
+			if(q.type==2 || q.type==3)	face =q.n1;
+			if(q.type>3 || q.type==0)	other=q.n1;
+		}
+
+		// now save lines
+		if(line>=0)
+		{
+			mglColor c=gr->GetPntC(line);
+			bool same=true;	// check if there are the same colors for all line segments
+			for(size_t j=0;j<p.size();j++)
+			{
+				const mglPrim &q=gr->GetPrm(p[j],false);
+				if(q.type==1 && c!=gr->GetPntC(q.n1))	same=false;
+			}
+			memset(pnt,-1,npnt*sizeof(long));
+			for(size_t j=0,k=0;j<p.size();j++)	// rearrange points for this group
+			{
+				const mglPrim &q=gr->GetPrm(p[j],false);
+				if(q.type!=1)	continue;
+				if(q.n1>=0 && pnt[q.n1]<0)	{	pnt[q.n1]=k;	k++;	}
+				if(q.n2>=0 && pnt[q.n2]<0)	{	pnt[q.n2]=k;	k++;	}
+			}
+			mgl_printf(fp, gz, "<Shape><Coordinate DEF='Lpnts_%ld' point='",i);
+			for(long j=0;j<gr->GetPntNum();j++)	if(pnt[j]>=0)
+			{	const mglPnt &p=gr->GetPnt(j);	mgl_printf(fp, gz, "%g %g %g, ", p.x,p.y,p.z);	}
+			mgl_printf(fp, gz, "0.0 0.0 0.0'/>");
+			mgl_printf(fp, gz, "<Color DEF='Lclrs_%ld' color='",i);
+			for(long j=0;j<gr->GetPntNum();j++)	if(pnt[j]>=0)
+			{	const mglPnt &p=gr->GetPnt(j);	mgl_printf(fp, gz, "%g %g %g, ", p.r,p.g,p.b);	}
+			mgl_printf(fp, gz, "0.0 0.0 0.0'/>");
+
+			// TODO save IndexedLineSet here + manual color is same==true
+
+			mgl_printf(fp, gz, "</Shape>");
+		}
+
+		// now save faces
+		if(face>=0)
+		{
+			mglColor c=gr->GetPntC(face);
+			bool same=true;	// check if there are the same colors for all line segments
+			for(size_t j=0;j<p.size();j++)
+			{
+				const mglPrim &q=gr->GetPrm(p[j],false);
+				if((q.type==2 || q.type==3) && c!=gr->GetPntC(q.n1))	same=false;
+			}
+			memset(pnt,-1,npnt*sizeof(long));
+			for(size_t j=0,k=0;j<p.size();j++)	// rearrange points for this group
+			{
+				const mglPrim &q=gr->GetPrm(p[j],false);
+				if(q.type!=2 && q.type!=3)	continue;
+				if(q.n1>=0 && pnt[q.n1]<0)	{	pnt[q.n1]=k;	k++;	}
+				if(q.n2>=0 && pnt[q.n2]<0)	{	pnt[q.n2]=k;	k++;	}
+				if(q.n3>=0 && pnt[q.n3]<0)	{	pnt[q.n3]=k;	k++;	}
+				if(q.type==3 && q.n4>=0 && pnt[q.n4]<0)	{	pnt[q.n4]=k;	k++;	}
+			}
+			mgl_printf(fp, gz, "<Shape><Coordinate DEF='Fpnts_%ld' point='",i);
+			for(long j=0;j<gr->GetPntNum();j++)	if(pnt[j]>=0)
+			{	const mglPnt &p=gr->GetPnt(j);	mgl_printf(fp, gz, "%g %g %g, ", p.x,p.y,p.z);	}
+			mgl_printf(fp, gz, "0.0 0.0 0.0'/>");
+			mgl_printf(fp, gz, "<Color DEF='Fclrs_%ld' color='",i);
+			for(long j=0;j<gr->GetPntNum();j++)	if(pnt[j]>=0)
+			{	const mglPnt &p=gr->GetPnt(j);	mgl_printf(fp, gz, "%g %g %g, ", p.r,p.g,p.b);	}
+			mgl_printf(fp, gz, "0.0 0.0 0.0'/>");
+
+			// TODO save IndexedLineSet here + manual color is same==true
+
+			mgl_printf(fp, gz, "</Shape>");
+		}
+
+		// now save other primitives
+		if(other>=0)
+		{
+/*			memset(pnt,-1,npnt*sizeof(long));
+			for(j=0,k=0;j<p.size();j++)	// rearrange points for this group
+			{
+				const mglPrim &q=gr->GetPrm(p[j],false);
+				if(q.type!=2 && q.type!=3)	continue;
+				if(q.n1>=0 && pnt[q.n1]<0)	{	pnt[q.n1]=k;	k++;	}
+				if(q.n2>=0 && pnt[q.n2]<0)	{	pnt[q.n2]=k;	k++;	}
+				if(q.n3>=0 && pnt[q.n3]<0)	{	pnt[q.n3]=k;	k++;	}
+				if(q.type==3 && q.n4>=0 && pnt[q.n4]<0)	{	pnt[q.n4]=k;	k++;	}
+			}
+			mgl_printf(fp, gz, "<Shape><Coordinate DEF='Fpnts_%ld' point='",i);
+			for(j=0;j<gr->GetPntNum();j++)	if(pnt[j]>=0)
+			{	const mglPnt &p=gr->GetPnt(j);	mgl_printf(fp, gz, "%g %g %g, ", p.x,p.y,p.z);	}
+			mgl_printf(fp, gz, "0.0 0.0 0.0'/>");
+			mgl_printf(fp, gz, "<Color DEF='Fclrs_%ld' color='",i);
+			for(j=0;j<gr->GetPntNum();j++)	if(pnt[j]>=0)
+			{	const mglPnt &p=gr->GetPnt(j);	mgl_printf(fp, gz, "%g %g %g, ", p.r,p.g,p.b);	}
+			mgl_printf(fp, gz, "0.0 0.0 0.0'/>");
+
+			// TODO save IndexedLineSet here + manual color is same==true
+
+			mgl_printf(fp, gz, "</Shape>");*/
+		}
+		// no normals since mathgl ones are "signless" -- x3d should calculate it by itself
+
+		for(size_t j=0;j<p.size();j++)
+		{
+			const mglPrim &q=gr->GetPrm(p[j],false);	// TODO: collect by type (quads,trig,line) and draw together???
+			mgl_x3d_prim(q, gr->GetPnt(q.n1), pnt, fp,gz, q.s*gr->FontFactor());
+		}
+		mgl_printf(fp,gz,"</Group><!--%s-->\n",gr->Grp[i].Lbl.c_str());
+		gr->Grp[i].p.clear();	// we don't need indexes anymore
+	}
+	mgl_printf(fp, gz, "</Scene>\n");
+	if(gz)	gzclose((gzFile)fp);	else	fclose((FILE *)fp);
+	setlocale(LC_NUMERIC, loc.c_str());
+	delete []pnt;
+}
+void MGL_EXPORT mgl_write_x3d_(uintptr_t *gr, const char *fname,const char *descr,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+char *d=new char[n+1];	memcpy(d,descr,n);	d[n]=0;
+mgl_write_x3d(_GR_,s,d);	delete []s;		delete []d;	}
+//-----------------------------------------------------------------------------
diff --git a/src/fft.cpp b/src/fft.cpp
new file mode 100644
index 0000000..f5d6fd1
--- /dev/null
+++ b/src/fft.cpp
@@ -0,0 +1,1316 @@
+/***************************************************************************
+ * fft.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include "mgl2/datac.h"
+#include "mgl2/data.h"
+#include "mgl2/thread.h"
+#if MGL_HAVE_GSL
+#include <gsl/gsl_fft_complex.h>
+#include <gsl/gsl_dht.h>
+#include <gsl/gsl_sf.h>
+#include <gsl/gsl_wavelet.h>
+#endif
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mglStartThreadT(void *(*func)(void *), long n, void *a, double *b, const void *v, void **w, const long *p, const void *re, const void *im)
+{
+	if(!func)	return;
+#if MGL_HAVE_PTHREAD
+	if(mglNumThr<1)	mgl_set_num_thr(0);
+	if(mglNumThr>1)
+	{
+		pthread_t *tmp=new pthread_t[mglNumThr];
+		mglThreadT *par=new mglThreadT[mglNumThr];
+		for(long i=0;i<mglNumThr;i++)	// put parameters into the structure
+		{	par[i].n=n;	par[i].a=a;	par[i].v=v;	par[i].w=w;	par[i].b=b;
+			par[i].p=p;	par[i].re=re;	par[i].im=im;	par[i].id=i;	}
+		for(long i=0;i<mglNumThr;i++)	pthread_create(tmp+i, 0, func, par+i);
+		for(long i=0;i<mglNumThr;i++)	pthread_join(tmp[i], 0);
+		delete []tmp;	delete []par;
+	}
+	else
+#endif
+	{
+		mglNumThr = 1;
+		mglThreadT par;
+		par.n=n;	par.a=a;	par.b=b;	par.v=v;	par.w=w;
+		par.p=p;	par.re=re;	par.im=im;	par.id=0;
+		func(&par);
+	}
+}
+//-----------------------------------------------------------------------------
+struct mglFFTdata
+{
+	long wnx,wny,wnz;		// sizes for FFT
+	long hnx,hny,hnz;		// sizes for Hankel
+	void *wtx,*wty,*wtz;	// tables for FFT
+	void *htx,*hty,*htz;	// tables for Hankel
+	mglFFTdata()	{	memset(this,0,sizeof(mglFFTdata));	}
+	~mglFFTdata()	{	Clear();	}
+	void Clear()
+	{
+		if(wnx)	{	wnx=0;	mgl_fft_free(wtx,0,0);	}
+		if(wny)	{	wny=0;	mgl_fft_free(wty,0,0);	}
+		if(wnz)	{	wnz=0;	mgl_fft_free(wtz,0,0);	}
+#if MGL_HAVE_GSL
+		if(hnx)	{	hnx=0;	gsl_dht_free((gsl_dht*)htx);	}
+		if(hny)	{	hny=0;	gsl_dht_free((gsl_dht*)hty);	}
+		if(hnz)	{	hnz=0;	gsl_dht_free((gsl_dht*)htz);	}
+#endif
+	}
+} mgl_fft_data;
+void MGL_EXPORT mgl_clear_fft()	{	mgl_fft_data.Clear();	}
+//-----------------------------------------------------------------------------
+MGL_EXPORT void *mgl_fft_alloc_thr(long n)
+{
+#if MGL_HAVE_GSL
+	return gsl_fft_complex_workspace_alloc(n);
+#else
+	return new double[2*n];
+#endif
+}
+//-----------------------------------------------------------------------------
+MGL_EXPORT void *mgl_fft_alloc(long n, void **space, long nthr)
+{
+	if(space && nthr>0)	for(long i=0;i<nthr;i++)	space[i] = mgl_fft_alloc_thr(n);
+#if MGL_HAVE_GSL
+	return gsl_fft_complex_wavetable_alloc(n);
+#else
+	double *c = new double[2*n*n];
+#pragma omp parallel for collapse(2)
+	for(long i=0;i<n;i++)	for(long j=0;j<n;j++)
+	{	c[2*(i+n*j)]=cos(2*M_PI*i*j/n);	c[2*(i+n*j)+1]=-sin(2*M_PI*i*j/n);	}
+	return c;
+#endif
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_fft_free_thr(void *ws)
+{
+#if MGL_HAVE_GSL
+	if(ws)	gsl_fft_complex_workspace_free((gsl_fft_complex_workspace*)ws);
+#else
+	if(ws)	delete []((double*)ws);
+#endif
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_fft_free(void *wt, void **ws, long nthr)
+{
+	if(ws && nthr>0)	for(long i=0;i<nthr;i++)	mgl_fft_free_thr(ws[i]);
+#if MGL_HAVE_GSL
+	if(wt)	gsl_fft_complex_wavetable_free((gsl_fft_complex_wavetable*)wt);
+#else
+	if(wt)	delete []((double*)wt);
+#endif
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_fft(double *x, long s, long n, const void *wt, void *ws, int inv)
+{
+#if MGL_HAVE_GSL
+	if(inv)	gsl_fft_complex_inverse(x, s, n, (const gsl_fft_complex_wavetable*)wt, (gsl_fft_complex_workspace*)ws);
+	else	gsl_fft_complex_forward(x, s, n, (const gsl_fft_complex_wavetable*)wt, (gsl_fft_complex_workspace*)ws);
+#else	// NOTE this is VERY slow!
+	const double *c = (const double *)wt;
+	double *d = (double *)ws, f = inv?1./n:1;
+	memset(d,0,2*n*sizeof(double));
+	if(inv)	for(long i=0;i<n;i++)	for(long j=0;j<n;j++)
+	{
+		long ii = 2*(i+n*j), jj = 2*j*s;
+		d[2*i] 	+= x[jj]*c[ii]+x[jj+1]*c[ii+1];
+		d[2*i+1]+= x[jj+1]*c[ii]-x[jj]*c[ii+1];
+	}
+	else	for(long i=0;i<n;i++)	for(long j=0;j<n;j++)
+	{
+		long ii = 2*(i+n*j), jj = 2*j*s;
+		d[2*i] 	+= x[jj]*c[ii]-x[jj+1]*c[ii+1];
+		d[2*i+1]+= x[jj+1]*c[ii]+x[jj]*c[ii+1];
+	}
+	for(long j=0;j<n;j++)
+	{	long jj = 2*j*s;	x[jj] = d[2*j]*f;	x[jj+1] = d[2*j+1]*f;	}
+#endif
+}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void* mgl_fftx(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	long nx=t->p[0];
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel
+#endif
+	{
+		void *w = mgl_fft_alloc_thr(nx);
+#pragma omp for nowait
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+			mgl_fft(t->b+2*nx*i, 1, nx, t->v, w, t->p[3]);
+		mgl_fft_free_thr(w);
+	}
+	return 0;
+}
+MGL_NO_EXPORT void* mgl_ffty(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	long nx=t->p[0],ny=t->p[1];
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel
+#endif
+	{
+		void *w = mgl_fft_alloc_thr(ny);
+#pragma omp for nowait
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+			mgl_fft(t->b+2*(i%nx)+2*nx*ny*(i/nx), nx, ny, t->v, w, t->p[3]);
+		mgl_fft_free_thr(w);
+	}
+	return 0;
+}
+MGL_NO_EXPORT void* mgl_fftz(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	long nx=t->p[0],ny=t->p[1],nz=t->p[2];
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel
+#endif
+	{
+		void *w = mgl_fft_alloc_thr(nz);
+#pragma omp for nowait
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+			mgl_fft(t->b+2*i, nx*ny, nz, t->v, w, t->p[3]);
+		mgl_fft_free_thr(w);
+	}
+	return 0;
+}
+void MGL_EXPORT mgl_datac_fft(HADT d, const char *dir)
+{
+	if(!dir || *dir==0)	return;
+	long nx = d->nx, ny = d->ny, nz = d->nz;
+	void *wt=0;
+	bool clear=false;
+	long par[4]={nx,ny,nz,strchr(dir,'i')!=0};
+#if MGL_USE_DOUBLE
+	double *a = (double *)(d->a);
+#else
+	double *a = new double[2*nx*ny*nz];	// manually convert to double
+#pragma omp parallel for
+	for(long i=0;i<nx*ny*nz;i++)
+	{	a[2*i] = real(d->a[i]);	a[2*i+1] = imag(d->a[i]);	}
+#endif
+	if(strchr(dir,'x') && nx>1)
+	{
+		if(mgl_fft_data.wnx==nx)	wt = mgl_fft_data.wtx;
+		else	{	clear = true;	wt = mgl_fft_alloc(nx,0,0);	}
+		mglStartThreadT(mgl_fftx,ny*nz,0,a,wt,0,par);
+		if(mgl_fft_data.wnx==0)
+		{	clear = false;	mgl_fft_data.wtx = wt;	mgl_fft_data.wnx=nx;	}
+		if(clear)	{	mgl_fft_free(wt,0,0);	clear = false;	}
+	}
+	if(strchr(dir,'y') && ny>1)
+	{
+		if(mgl_fft_data.wny==ny)	wt = mgl_fft_data.wty;
+		else	{	clear = true;	wt = mgl_fft_alloc(ny,0,0);	}
+		mglStartThreadT(mgl_ffty,nx*nz,0,a,wt,0,par);
+		if(mgl_fft_data.wny==0)
+		{	clear = false;	mgl_fft_data.wty = wt;	mgl_fft_data.wny=ny;	}
+		if(clear)	{	mgl_fft_free(wt,0,0);	clear = false;	}
+	}
+	if(strchr(dir,'z') && nz>1)
+	{
+		if(mgl_fft_data.wnz==nz)	wt = mgl_fft_data.wtz;
+		else	{	clear = true;	wt = mgl_fft_alloc(nz,0,0);	}
+		mglStartThreadT(mgl_fftz,nx*ny,0,a,wt,0,par);
+		if(mgl_fft_data.wnz==0)
+		{	clear = false;	mgl_fft_data.wtz = wt;	mgl_fft_data.wnz=nz;	}
+		if(clear)	{	mgl_fft_free(wt,0,0);	clear = false;	}
+	}
+#if !MGL_USE_DOUBLE
+#pragma omp parallel for
+	for(long i=0;i<nx*ny*nz;i++)	d->a[i] = dual(a[2*i], a[2*i+1]);
+	delete []a;
+#endif
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_fourier(HMDT re, HMDT im, const char *dir)
+{
+	if(!dir || *dir==0)	return;
+	long nx = re->nx, ny = re->ny, nz = re->nz;
+	if(nx*ny*nz != im->nx*im->ny*im->nz || dir[0]==0)	return;
+	bool clear=false;
+	void *wt=0;
+	long par[4]={nx,ny,nz,strchr(dir,'i')!=0};
+	double *a = new double[2*nx*ny*nz];
+#pragma omp parallel for
+	for(long i=0;i<nx*ny*nz;i++)
+	{	a[2*i] = re->a[i];	a[2*i+1] = im->a[i];	}
+	if(strchr(dir,'x') && nx>1)
+	{
+		if(mgl_fft_data.wnx==nx)	wt = mgl_fft_data.wtx;
+		else	{	clear = true;	wt = mgl_fft_alloc(nx,0,0);	}
+		mglStartThreadT(mgl_fftx,ny*nz,0,a,wt,0,par);
+		if(mgl_fft_data.wnx==0)
+		{	mgl_fft_data.wtx = wt;	clear = false;	mgl_fft_data.wnx=nx;	}
+		if(clear)	{	mgl_fft_free(wt,0,0);	clear = false;	}
+	}
+	if(strchr(dir,'y') && ny>1)
+	{
+		if(mgl_fft_data.wny==ny)	wt = mgl_fft_data.wty;
+		else	{	clear = true;	wt = mgl_fft_alloc(ny,0,0);	}
+		mglStartThreadT(mgl_ffty,nx*nz,0,a,wt,0,par);
+		if(mgl_fft_data.wny==0)
+		{	mgl_fft_data.wty = wt;	clear = false;	mgl_fft_data.wny=ny;	}
+		if(clear)	{	mgl_fft_free(wt,0,0);	clear = false;	}
+	}
+	if(strchr(dir,'z') && nz>1)
+	{
+		if(mgl_fft_data.wnz==nz)	wt = mgl_fft_data.wtz;
+		else	{	clear = true;	wt = mgl_fft_alloc(nz,0,0);	}
+		mglStartThreadT(mgl_fftz,nx*ny,0,a,wt,0,par);
+		if(mgl_fft_data.wnz==0)
+		{	mgl_fft_data.wtz = wt;	clear = false;	mgl_fft_data.wnz=nz;	}
+		if(clear)	{	mgl_fft_free(wt,0,0);	clear = false;	}
+	}
+#pragma omp parallel for
+	for(long i=0;i<nx*ny*nz;i++)
+	{	re->a[i] = a[2*i];	im->a[i] = a[2*i+1];	}
+	delete []a;
+}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void* mgl_envx(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	long nx=t->p[0];
+	mreal *a = (mreal*)t->a;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel
+#endif
+	{
+		double *b =	new double[2*nx];
+		void *w = mgl_fft_alloc_thr(nx);
+#pragma omp for nowait
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			for(long j=0;j<nx;j++)	{	b[2*j] = a[j+i*nx];	b[2*j+1] = 0;	}
+			mgl_fft(b, 1, nx, t->v, w, false);
+			for(long j=0;j<nx;j++)	{	b[j] *= 2.;	b[j+nx] = 0;	}
+			mgl_fft(b, 1, nx, t->v, w, true);
+			for(long j=0;j<nx;j++)	a[j+i*nx] = hypot(b[2*j], b[2*j+1]);
+		}
+		mgl_fft_free_thr(w);	delete []b;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void* mgl_envy(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	long nx=t->p[0],ny=t->p[1];
+	mreal *a = (mreal*)t->a;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel
+#endif
+	{
+		double *b =	new double[2*ny];
+		void *w = mgl_fft_alloc_thr(ny);
+#pragma omp for nowait
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			for(long j=0;j<ny;j++)	{	b[2*j] = a[(i%nx)+nx*(j+ny*(i/nx))];	b[2*j+1] = 0;	}
+			mgl_fft(b, 1, ny, t->v, t->w[t->id], false);
+			for(long j=0;j<ny;j++)	{	b[j] *= 2.;	b[j+ny] = 0;	}
+			mgl_fft(b, 1, ny, t->v, t->w[t->id], true);
+			for(long j=0;j<ny;j++)	a[(i%nx)+nx*(j+ny*(i/nx))] = hypot(b[2*j], b[2*j+1]);
+		}
+		mgl_fft_free_thr(w);	delete []b;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void* mgl_envz(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	long nx=t->p[0],ny=t->p[1],nz=t->p[2],k=nx*ny;
+	mreal *a = (mreal*)t->a;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel
+#endif
+	{
+		double *b =	new double[2*nz];
+		void *w = mgl_fft_alloc_thr(nz);
+#pragma omp for nowait
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			for(long j=0;j<nz;j++)	{	b[2*j] = a[j*k+i];	b[2*j+1] = 0;	}
+			mgl_fft(b, 1, nz, t->v, t->w[t->id], false);
+			for(long j=0;j<nz;j++)	{	b[j] *= 2.;	b[j+nz] = 0;	}
+			mgl_fft(b, 1, nz, t->v, t->w[t->id], true);
+			for(long j=0;j<nz;j++)	a[j*k+i] = hypot(b[2*j], b[2*j+1]);
+		}
+		mgl_fft_free_thr(w);	delete []b;
+	}
+	return 0;
+}
+void MGL_EXPORT mgl_data_envelop(HMDT d, char dir)
+{
+	long nx=d->nx,ny=d->ny,nz=d->nz,par[3]={nx,ny,nz};
+	bool clear=false;
+	void *wt=0;
+	if(dir=='x' && nx>1)
+	{
+		if(mgl_fft_data.wnx==nx)	wt = mgl_fft_data.wtx;
+		else	{	clear = true;	wt = mgl_fft_alloc(nx,0,0);	}
+		mglStartThreadT(mgl_envx,ny*nz,d->a,0,wt,0,par);
+		if(mgl_fft_data.wnx==0)
+		{	mgl_fft_data.wtx = wt;	clear = false;	mgl_fft_data.wnx=nx;	}
+		if(clear)	{	mgl_fft_free(wt,0,0);	clear = false;	}
+	}
+	if(dir=='y' && ny>1)
+	{
+		if( mgl_fft_data.wny==ny)	wt = mgl_fft_data.wty;
+		else	{	clear = true;	wt = mgl_fft_alloc(ny,0,0);	}
+		mglStartThreadT(mgl_envy,nx*nz,d->a,0,wt,0,par);
+		if(mgl_fft_data.wny==0)
+		{	mgl_fft_data.wty = wt;	clear = false;	mgl_fft_data.wny=ny;	}
+		if(clear)	{	mgl_fft_free(wt,0,0);	clear = false;	}
+	}
+	if(dir=='z' && nz>1)
+	{
+		if(mgl_fft_data.wnz==nz)	wt = mgl_fft_data.wtz;
+		else	{	clear = true;	wt = mgl_fft_alloc(nz,0,0);	}
+		mglStartThreadT(mgl_envz,nx*ny,d->a,0,wt,0,par);
+		if(mgl_fft_data.wnz==0)
+		{	mgl_fft_data.wtz = wt;	clear = false;	mgl_fft_data.wnz=nz;	}
+		if(clear)	{	mgl_fft_free(wt,0,0);	clear = false;	}
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_envelop(HADT c, char dir)
+{
+	mglData re(c->nx, c->ny, c->nz), im(c->nx, c->ny, c->nz);
+	long n = c->GetNN();
+#pragma omp parallel for
+	for(long i=0;i<n;i++)	{	re.a[i]=real(c->a[i]);	im.a[i]=imag(c->a[i]);	}
+	mgl_data_envelop(&re, dir);
+	mgl_data_envelop(&im, dir);
+#pragma omp parallel for
+	for(long i=0;i<n;i++)	c->a[i] = dual(re.a[i], im.a[i]);
+}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void* mgl_stfa1(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	long mx=t->p[0],mz=t->p[2],dn=t->p[3],dd=dn/2,ny=t->p[4];
+	mreal *d = (mreal*)t->a;
+	HCDT re = (HCDT)t->re, im = (HCDT)t->im;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel
+#endif
+	{
+		double *a = new double[4*dn], ff;
+		void *w = mgl_fft_alloc_thr(2*dn);
+#pragma omp for nowait
+		for(long ii=t->id;ii<t->n;ii+=mglNumThr)
+		{
+			long i = ii%mx, j = ii/mx, i0;
+			for(long k=0;k<2*dn;k++)
+			{
+				i0 = k-dd+j*dn;		ff = 1;
+				if(i0<0)	i0=0;	else if(i0>=ny)	i0=ny-1;
+				if(k<dd)
+				{	ff = 0.5*(k-dd/2.)/dd;		ff=0.5+ff*(3-ff*ff);	}
+				else if(k>=dn+dd)
+				{	ff = 0.5*(k-3.5*dd)/dd;	ff=0.5-ff*(3-ff*ff);	}
+				a[2*k] = re->v(i,i0)*ff;	a[2*k+1] = im->v(i,i0)*ff;
+			}
+			mgl_fft(a, 1, 2*dn, t->v, w, false);
+			for(long k=0;k<dd;k++)
+			{
+				i0 = i+mx*(j+mz*k);
+				d[i0+mx*mz*dd] = hypot(a[4*k],a[4*k+1])/dn;
+				d[i0] = hypot(a[4*k+2*dn],a[4*k+2*dn+1])/dn;
+			}
+		}
+		mgl_fft_free_thr(w);	delete []a;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void* mgl_stfa2(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	long mx=t->p[0],my=t->p[1],dn=t->p[3],dd=dn/2,nx=t->p[4];
+	mreal *d = (mreal*)t->a;
+	HCDT re = (HCDT)t->re, im = (HCDT)t->im;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel
+#endif
+	{
+		double *a = new double[4*dn], ff;
+		void *w = mgl_fft_alloc_thr(2*dn);
+#pragma omp for nowait
+		for(long ii=t->id;ii<t->n;ii+=mglNumThr)
+		{
+			long i = ii%my, j = ii/my, i0;
+			for(long k=0;k<2*dn;k++)
+			{
+				i0 = k-dd+i*dn;		ff = 1;
+				if(i0<0)	i0=0;	else if(i0>=nx)	i0=nx-1;
+				if(k<dd)
+				{	ff = 0.5*(k-dd/2.)/dd;	ff=0.5+ff*(3-ff*ff);	}
+				else if(k>=3*dd)
+				{	ff = 0.5*(k-3.5*dd)/dd;	ff=0.5-ff*(3-ff*ff);	}
+				a[2*k] = re->v(i0,j)*ff;	a[2*k+1] = im->v(i0,j)*ff;
+			}
+			mgl_fft(a, 1, 2*dn, t->v, w, false);
+			for(long k=0;k<dd;k++)
+			{
+				i0 = i+my*(k+mx*j);
+				d[i0+dd*my] = hypot(a[4*k],a[4*k+1])/dn;
+				d[i0] = hypot(a[4*k+2*dn],a[4*k+2*dn+1])/dn;
+			}
+		}
+		mgl_fft_free_thr(w);	delete []a;
+	}
+	return 0;
+}
+HMDT MGL_EXPORT mgl_data_stfa(HCDT re, HCDT im, long dn, char dir)
+{
+	if(dn<2)	return 0;
+	dn = 2*(dn/2);
+	long nx = re->GetNx(), ny = re->GetNy();
+	if(nx*ny!=im->GetNx()*im->GetNy())	return 0;
+	void *wt = mgl_fft_alloc(2*dn,0,0);
+	long mx,my,mz;
+	mglData *d=new mglData;
+	if(dir=='y')
+	{
+		mx = nx;	my = dn;	mz = ny/dn;
+		mgl_data_create(d, mx, mz, my);
+		long par[5]={mx,my,mz,dn,ny};
+		mglStartThreadT(mgl_stfa1,mx*mz,d->a,0,wt,0,par,re,im);
+	}
+	else
+	{
+		mx = dn;	my = nx/dn;	mz = ny;
+		mgl_data_create(d, my, mx, mz);
+		long par[5]={mx,my,mz,dn,nx};
+		mglStartThreadT(mgl_stfa2,my*mz,d->a,0,wt,0,par,re,im);
+	}
+	mgl_fft_free(wt,0,0);
+	return d;
+}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void* mgl_sinx(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	long nx=t->p[0];
+	mreal *a = (mreal*)t->a;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel
+#endif
+	{
+		double *b = new double[2*nx], f=sqrt(2./nx);
+		void *w = mgl_fft_alloc_thr(nx);
+#pragma omp for nowait
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			long k = i*nx;	memset(b,0,2*nx*sizeof(double));
+			for(long j=1;j<nx;j++)	b[2*j]=sin(M_PI*j/nx)*(a[j+k]+a[nx-j+k])+(a[j+k]-a[nx-j+k])*0.5;
+			mgl_fft(b,1,nx,t->v,w,false);
+			a[k]=0;	a[k+1]=b[0]*f/2;	// fill sinfft
+			for(long j=1;j<nx/2;j++)
+			{
+				a[k+2*j] = -b[2*j+1]*f;
+				a[k+2*j+1] = a[k+2*j-1]+b[2*j]*f;
+			}
+			if(nx%2)	a[nx-1] = -b[nx]*f;
+		}
+		mgl_fft_free_thr(w);	delete []b;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void* mgl_siny(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	long nx=t->p[0],ny=t->p[1];
+	mreal *a = (mreal*)t->a;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel
+#endif
+	{
+		double *b = new double[2*ny], f=sqrt(2./ny);
+		void *w = mgl_fft_alloc_thr(ny);
+#pragma omp for nowait
+		for(long ii=t->id;ii<t->n;ii+=mglNumThr)
+		{
+			long i = ii%nx, k = ii/nx;	memset(b,0,2*ny*sizeof(double));
+			for(long j=1;j<ny;j++)	b[2*j]=sin(M_PI*j/ny)*(a[i+nx*(ny*k+j)]+a[i+nx*(ny*k+ny-j)])+(a[i+nx*(ny*k+j)]-a[i+nx*(ny*k+ny-j)])*0.5;
+			mgl_fft(b,1,ny,t->v,w,false);
+			a[i+nx*ny*k]=0;	a[i+nx*(ny*k+1)]=b[0]*f/2;	// fill sinfft
+			for(long j=1;j<ny/2;j++)
+			{
+				a[i+nx*(ny*k+2*j)] = -b[2*j+1]*f;
+				a[i+nx*(ny*k+2*j+1)] = a[i+nx*(ny*k+2*j-1)]+b[2*j]*f;
+			}
+			if(ny%2)	a[i+nx*(ny*k+ny-1)] = -b[ny]*f;
+		}
+		mgl_fft_free_thr(w);	delete []b;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void* mgl_sinz(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	long nx=t->p[0],ny=t->p[1],nz=t->p[2],k=nx*ny;
+	mreal *a = (mreal*)t->a;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel
+#endif
+	{
+		double *b = new double[2*nz], f=sqrt(2./nz);
+		void *w = mgl_fft_alloc_thr(nz);
+#pragma omp for nowait
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			memset(b,0,2*nz*sizeof(double));
+			for(long j=1;j<nz;j++)	b[2*j]=sin(M_PI*j/nz)*(a[i+k*j]+a[i+k*(nz-j)])+(a[i+k*j]-a[i+k*(nz-j)])*0.5;
+			mgl_fft(b,1,nz,t->v,w,false);
+			a[i]=0;	a[i+k]=b[0]*f/2;	// fill sinfft
+			for(long j=1;j<nz/2;j++)
+			{
+				a[i+k*2*j] = -b[2*j+1]*f;
+				a[i+k*(2*j+1)] = a[i+k*(2*j-1)]+b[2*j]*f;
+			}
+			if(nz%2)	a[i+k*nz-k] = -b[nz]*f;
+		}
+		mgl_fft_free_thr(w);	delete []b;
+	}
+	return 0;
+}
+void MGL_EXPORT mgl_data_sinfft(HMDT d, const char *dir)	// use DST-1
+{
+	if(!dir || *dir==0)	return;
+	bool clear=false;
+	void *wt=0;
+	long nx=d->nx, ny=d->ny, nz=d->nz, par[3]={nx,ny,nz};
+	if(strchr(dir,'x') && nx>1)
+	{
+		if(mgl_fft_data.wnx==nx)	wt = mgl_fft_data.wtx;
+		else	{	clear = true;	wt = mgl_fft_alloc(nx,0,0);	}
+		mglStartThreadT(mgl_sinx,ny*nz,d->a,0,wt,0,par);
+		if(mgl_fft_data.wnx==0)
+		{	mgl_fft_data.wtx = wt;	clear = false;	mgl_fft_data.wnx=nx;	}
+		if(clear)	{	mgl_fft_free(wt,0,0);	clear = false;	}
+	}
+	if(strchr(dir,'y') && ny>1)
+	{
+		if(mgl_fft_data.wny==ny)	wt = mgl_fft_data.wty;
+		else	{	clear = true;	wt = mgl_fft_alloc(ny,0,0);	}
+		mglStartThreadT(mgl_siny,nx*nz,d->a,0,wt,0,par);
+		if(mgl_fft_data.wny==0)
+		{	mgl_fft_data.wty = wt;	clear = false;	mgl_fft_data.wny=ny;	}
+		if(clear)	{	mgl_fft_free(wt,0,0);	clear = false;	}
+	}
+	if(strchr(dir,'z') && nz>1)
+	{
+		if(mgl_fft_data.wnz==nz)	wt = mgl_fft_data.wtz;
+		else	{	clear = true;	wt = mgl_fft_alloc(nz,0,0);	}
+		mglStartThreadT(mgl_sinz,nx*ny,d->a,0,wt,0,par);
+		if(mgl_fft_data.wnz==0)
+		{	mgl_fft_data.wtz = wt;	clear = false;	mgl_fft_data.wnz=nz;	}
+		if(clear)	{	mgl_fft_free(wt,0,0);	clear = false;	}
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_sinfft(HADT c, const char *dir)
+{
+	if(!dir || *dir==0)	return;
+	mglData re(c->nx, c->ny, c->nz), im(c->nx, c->ny, c->nz);
+	long n = c->GetNN();
+#pragma omp parallel for
+	for(long i=0;i<n;i++)	{	re.a[i]=real(c->a[i]);	im.a[i]=imag(c->a[i]);	}
+	mgl_data_sinfft(&re, dir);
+	mgl_data_sinfft(&im, dir);
+#pragma omp parallel for
+	for(long i=0;i<n;i++)	c->a[i] = dual(re.a[i], im.a[i]);
+}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void* mgl_cosx(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	long nx=t->p[0],nn=nx-1;
+	mreal *a = (mreal*)t->a;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel
+#endif
+	{
+		double *b = new double[2*nx], f=sqrt(2./nn);
+		void *w = mgl_fft_alloc_thr(nn);
+#pragma omp for nowait
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			long k = i*nx;	memset(b,0,2*nx*sizeof(double));
+			for(long j=0;j<nn;j++)	b[2*j]=(a[j+k]+a[nn-j+k])*0.5-sin(M_PI*j/nn)*(a[j+k]-a[nn-j+k]);
+			mgl_fft(b,1,nn,t->v,w,false);
+			double f1=0.5*(a[k]-a[nn+k]), s=-1;
+			a[nn+k]=0.5*(a[k]+a[nn+k]*((nn%2)?-1:1));
+			for(long j=1;j<nn;j++)
+			{
+				f1 += a[j+k]*cos(M_PI*j/nn);
+				a[nn+k] += a[j+k]*s;	s = -s;
+			}
+			a[k]=b[0]*f;	a[1+k]=f1*f;	a[nn+k]*=f;	// fill cosfft
+			for(long j=1;j<nn/2;j++)
+			{
+				a[2*j+k] = b[2*j]*f;
+				a[2*j+1+k] = a[2*j-1+k]-b[2*j+1]*f;
+			}
+			if(nn%2)	a[nn-1+k] = b[nn-1]*f;
+		}
+		mgl_fft_free_thr(w);
+		delete []b;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void* mgl_cosy(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	long nx=t->p[0],ny=t->p[1],nn=ny-1;
+	mreal *a = (mreal*)t->a;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel
+#endif
+	{
+		double *b = new double[2*ny], f=sqrt(2./nn);
+		void *w = mgl_fft_alloc_thr(nn);
+#pragma omp for nowait
+		for(long ii=t->id;ii<t->n;ii+=mglNumThr)
+		{
+			long i = ii%nx, k = ii/nx;	memset(b,0,2*ny*sizeof(double));
+			for(long j=0;j<nn;j++)	b[2*j]=(a[i+nx*(ny*k+j)]+a[i+nx*(ny*k+nn-j)])*0.5-sin(M_PI*j/nn)*(a[i+nx*(ny*k+j)]-a[i+nx*(ny*k+nn-j)]);
+			mgl_fft(b,1,nn,t->v,w,false);
+			double f1=0.5*(a[i+nx*ny*k]-a[i+nx*(ny*k+nn)]), s=-1;
+			a[i+nx*(ny*k+nn)]=0.5*(a[i+nx*ny*k]+a[i+nx*(ny*k+nn)]*((nn%2)?-1:1));
+			for(long j=1;j<nn;j++)
+			{
+				f1 += a[i+nx*(ny*k+j)]*cos(M_PI*j/nn);
+				a[i+nx*(ny*k+nn)] += a[i+nx*(ny*k+j)]*s;	s = -s;
+			}
+			a[i+nx*ny*k]=b[0]*f;	a[i+nx*(ny*k+1)]=f1*f;	a[i+nx*(ny*k+nn)]*=f;	// fill cosfft
+			for(long j=1;j<nn/2;j++)
+			{
+				a[i+nx*(ny*k+2*j)] = b[2*j]*f;
+				a[i+nx*(ny*k+2*j+1)] = a[i+nx*(ny*k+2*j-1)]-b[2*j+1]*f;
+			}
+			if(nn%2)	a[i+nx*(ny*k+nn-1)] = b[nn-1]*f;
+		}
+		mgl_fft_free_thr(w);
+		delete []b;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void* mgl_cosz(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	long nx=t->p[0],ny=t->p[1],nz=t->p[2],k=nx*ny,nn=nz-1;
+	mreal *a = (mreal*)t->a;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel
+#endif
+	{
+		double *b = new double[2*nz], f=sqrt(2./nn);
+		void *w = mgl_fft_alloc_thr(nn);
+#pragma omp for nowait
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			memset(b,0,2*nz*sizeof(double));
+			for(long j=0;j<nn;j++)	b[2*j]=(a[i+k*j]+a[i+k*(nn-j)])*0.5-sin(M_PI*j/nn)*(a[i+k*j]-a[i+k*(nn-j)]);
+			mgl_fft(b,1,nn,t->v,w,false);
+			double f1=0.5*(a[i]-a[i+k*nn]), s=-1;
+			a[i+k*nn]=0.5*(a[i]+a[i+k*nn]*((nn%2)?-1:1));
+			for(long j=1;j<nn;j++)
+			{
+				f1 += a[i+k*j]*cos(M_PI*j/nn);
+				a[i+k*nn] += a[i+k*j]*s;	s = -s;
+			}
+			a[i]=b[0]*f;	a[i+k]=f1*f;	a[i+k*nn]*=f;	// fill cosfft
+			for(long j=1;j<nn/2;j++)
+			{
+				a[i+k*2*j] = b[2*j]*f;
+				a[i+k*2*j+k] = a[i+k*2*j-k]-b[2*j+1]*f;
+			}
+			if(nn%2)	a[i+k*nn-k] = b[nn-1]*f;
+		}
+		mgl_fft_free_thr(w);
+		delete []b;
+	}
+	return 0;
+}
+void MGL_EXPORT mgl_data_cosfft(HMDT d, const char *dir)
+{
+	if(!dir || *dir==0)	return;
+	bool clear=false;
+	void *wt=0;
+	long nx=d->nx, ny=d->ny, nz=d->nz, par[3]={nx,ny,nz};
+	if(strchr(dir,'x') && nx>1)
+	{
+		if(mgl_fft_data.wnx==nx-1)	wt = mgl_fft_data.wtx;
+		else	{	clear = true;	wt = mgl_fft_alloc(nx-1,0,0);	}
+		mglStartThreadT(mgl_cosx,ny*nz,d->a,0,wt,0,par);
+		if(mgl_fft_data.wnx==0)
+		{	mgl_fft_data.wtx = wt;	clear = false;	mgl_fft_data.wnx=nx-1;	}
+		if(clear)	{	mgl_fft_free(wt,0,0);	clear = false;	}
+	}
+	if(strchr(dir,'y') && ny>1)
+	{
+		if(mgl_fft_data.wny==ny-1)	wt = mgl_fft_data.wty;
+		else	{	clear = true;	wt = mgl_fft_alloc(ny-1,0,0);	}
+		mglStartThreadT(mgl_cosy,nx*nz,d->a,0,wt,0,par);
+		if(mgl_fft_data.wny==0)
+		{	mgl_fft_data.wty = wt;	clear = false;	mgl_fft_data.wny=ny-1;	}
+		if(clear)	{	mgl_fft_free(wt,0,0);	clear = false;	}
+	}
+	if(strchr(dir,'z') && nz>1)
+	{
+		if(mgl_fft_data.wnz==nz-1)	wt = mgl_fft_data.wtz;
+		else	{	clear = true;	wt = mgl_fft_alloc(nz-1,0,0);	}
+		mglStartThreadT(mgl_cosz,nx*ny,d->a,0,wt,0,par);
+		if(mgl_fft_data.wnz==0)
+		{	mgl_fft_data.wtz = wt;	clear = false;	mgl_fft_data.wnz=nz-1;	}
+		if(clear)	{	mgl_fft_free(wt,0,0);	clear = false;	}
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_cosfft(HADT c, const char *dir)
+{
+	if(!dir || *dir==0)	return;
+	mglData re(c->nx, c->ny, c->nz), im(c->nx, c->ny, c->nz);
+	long n = c->GetNN();
+#pragma omp parallel for
+	for(long i=0;i<n;i++)	{	re.a[i]=real(c->a[i]);	im.a[i]=imag(c->a[i]);	}
+	mgl_data_cosfft(&re, dir);
+	mgl_data_cosfft(&im, dir);
+#pragma omp parallel for
+	for(long i=0;i<n;i++)	c->a[i] = dual(re.a[i], im.a[i]);
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_transform_a(HCDT am, HCDT ph, const char *tr)
+{
+	long nx = am->GetNx(), ny = am->GetNy(), nz = am->GetNz();
+	if(nx*ny*nz != ph->GetNN() || !tr || tr[0]==0)	return 0;
+	mglData re(nx,ny,nz), im(nx,ny,nz);
+#pragma omp parallel for
+	for(long i=0;i<nx*ny*nz;i++)
+	{
+		mreal a=am->vthr(i), p=ph->vthr(i);
+		re.a[i] = a*cos(p);	im.a[i] = a*sin(p);
+	}
+	return mgl_transform(&re, &im, tr);
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_transform(HCDT re, HCDT im, const char *tr)
+{
+	if(!tr || *tr==0)	return 0;
+	long nx = re->GetNx(), ny = re->GetNy(), nz = re->GetNz();
+	if(nx*ny*nz != im->GetNN() || tr[0]==0)	return 0;
+	mglData rr(re),ii(im);
+	if(strchr(tr,'i') && strchr(tr,'f'))	// general case
+	{
+		if(tr[0]=='f')	mgl_data_fourier(&rr,&ii,"x");
+		if(tr[0]=='i')	mgl_data_fourier(&rr,&ii,"xi");
+		if(tr[1]=='f')	mgl_data_fourier(&rr,&ii,"y");
+		if(tr[1]=='i')	mgl_data_fourier(&rr,&ii,"yi");
+		if(tr[2]=='f')	mgl_data_fourier(&rr,&ii,"z");
+		if(tr[2]=='i')	mgl_data_fourier(&rr,&ii,"zi");
+	}
+	else if(strchr(tr,'f'))	// do Fourier only once for speeding up
+	{
+		char str[4] = "   ";
+		if(tr[0]=='f')	str[0]='x';
+		if(tr[1]=='f')	str[1]='y';
+		if(tr[2]=='f')	str[2]='z';
+		mgl_data_fourier(&rr,&ii,str);
+	}
+	else if(strchr(tr,'i'))	// do Fourier only once for speeding up
+	{
+		char str[5] = "   i";
+		if(tr[0]=='i')	str[0]='x';
+		if(tr[1]=='i')	str[1]='y';
+		if(tr[2]=='i')	str[2]='z';
+		mgl_data_fourier(&rr,&ii,str);
+	}
+	else if(strchr(tr,'s'))	// do Fourier only once for speeding up
+	{
+		if(tr[0]=='s')	{	rr.SinFFT("x");	ii.SinFFT("x");	}
+		if(tr[1]=='s')	{	rr.SinFFT("y");	ii.SinFFT("y");	}
+		if(tr[2]=='s')	{	rr.SinFFT("z");	ii.SinFFT("z");	}
+	}
+	else if(strchr(tr,'c'))	// do Fourier only once for speeding up
+	{
+		if(tr[0]=='c')	{	rr.CosFFT("x");	ii.CosFFT("x");	}
+		if(tr[1]=='c')	{	rr.CosFFT("y");	ii.CosFFT("y");	}
+		if(tr[2]=='c')	{	rr.CosFFT("z");	ii.CosFFT("z");	}
+	}
+	else if(strchr(tr,'h'))	// do Fourier only once for speeding up
+	{
+		if(tr[0]=='h')	{	rr.Hankel("x");	ii.Hankel("x");	}
+		if(tr[1]=='h')	{	rr.Hankel("y");	ii.Hankel("y");	}
+		if(tr[2]=='h')	{	rr.Hankel("z");	ii.Hankel("z");	}
+	}
+	mglData *d = new mglData(nx, ny, nz);
+#pragma omp parallel for
+	for(long i=0;i<nx*ny*nz;i++)	d->a[i] = hypot(rr.a[i],ii.a[i]);
+	return d;
+}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_transform_a_(uintptr_t *am, uintptr_t *ph, const char *tr, int l)
+{	char *s=new char[l+1];	memcpy(s,tr,l);	s[l]=0;
+	uintptr_t res = uintptr_t(mgl_transform_a(_DA_(am),_DA_(ph),s));
+	delete []s;		return res;	}
+uintptr_t MGL_EXPORT mgl_transform_(uintptr_t *re, uintptr_t *im, const char *tr, int l)
+{	char *s=new char[l+1];	memcpy(s,tr,l);	s[l]=0;
+	uintptr_t res = uintptr_t(mgl_transform(_DA_(re),_DA_(im),s));
+	delete []s;		return res;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_envelop_(uintptr_t *d, const char *dir, int)
+{	mgl_data_envelop(_DT_,*dir);	}
+void MGL_EXPORT mgl_datac_envelop_(uintptr_t *d, const char *dir, int)
+{	mgl_datac_envelop(_DC_,*dir);	}
+//-----------------------------------------------------------------------------
+#if MGL_HAVE_GSL
+MGL_NO_EXPORT void* mgl_chnkx(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	long nx=t->p[0];
+	dual *a = (dual*)t->a;
+	const gsl_dht *dht = (const gsl_dht*)t->v;
+	double mm = gsl_sf_bessel_zero_J0(nx+1);
+
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel
+#endif
+	{
+		double *b = new double[3*nx];
+#pragma omp for nowait
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			for(long j=0;j<nx;j++)	b[j] = real(a[j+nx*i]);
+			gsl_dht_apply(dht,b,b+nx);
+			for(long j=0;j<nx;j++)	b[j] = imag(a[j+nx*i]);
+			gsl_dht_apply(dht,b,b+2*nx);
+			for(long j=0;j<nx;j++)	a[j+nx*i] = dual(b[j+nx]*mm,b[j+2*nx]*mm);
+		}
+		delete []b;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void* mgl_chnky(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	long nx=t->p[0],ny=t->p[1];
+	dual *a = (dual*)t->a;
+	const gsl_dht *dht = (const gsl_dht*)t->v;
+	double mm = gsl_sf_bessel_zero_J0(ny+1);
+
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel
+#endif
+	{
+		double *b = new double[3*ny];
+#pragma omp for nowait
+		for(long ii=t->id;ii<t->n;ii+=mglNumThr)
+		{
+			long i = ii%nx, k = ii/nx;
+			for(long j=0;j<ny;j++)	b[j] = real(a[i+nx*(j+ny*k)]);
+			gsl_dht_apply(dht,b,b+ny);
+			for(long j=0;j<ny;j++)	b[j] = imag(a[i+nx*(j+ny*k)]);
+			gsl_dht_apply(dht,b,b+2*ny);
+			for(long j=0;j<ny;j++)	a[i+nx*(j+ny*k)] = dual(b[j+ny]*mm,b[j+2*ny]*mm);
+		}
+		delete []b;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void* mgl_chnkz(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	long k=t->p[0]*t->p[1],nz=t->p[2];
+	dual *a = (dual*)t->a;
+	const gsl_dht *dht = (const gsl_dht*)t->v;
+	double mm = gsl_sf_bessel_zero_J0(nz+1);
+
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel
+#endif
+	{
+		double *b = new double[3*nz];
+#pragma omp for nowait
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			for(long j=0;j<nz;j++)	b[j] = real(a[i+j*k]);
+			gsl_dht_apply(dht,b,b+nz);
+			for(long j=0;j<nz;j++)	b[j] = imag(a[i+j*k]);
+			gsl_dht_apply(dht,b,b+2*nz);
+			for(long j=0;j<nz;j++)	a[i+j*k] = dual(b[j+nz]*mm,b[j+2*nz]*mm);
+		}
+		delete []b;
+	}
+	return 0;
+}
+void MGL_EXPORT mgl_datac_hankel(HADT d, const char *dir)
+{
+	if(!dir || *dir==0)	return;
+	gsl_dht *dht=0;
+	bool clear = false;
+	long nx=d->nx, ny=d->ny, nz=d->nz;
+	long par[3]={nx,ny,nz};
+	if(strchr(dir,'x') && nx>1)
+	{
+		if(mgl_fft_data.hnx==nx)	dht = (gsl_dht *)mgl_fft_data.htx;
+		else	{	dht = gsl_dht_new(nx,0,1);	clear = true;	}
+		mglStartThreadT(mgl_chnkx,ny*nz,d->a,0,dht,0,par);
+		if(mgl_fft_data.hnx==0)
+		{	mgl_fft_data.htx = dht;	clear = false;	mgl_fft_data.hnx=nx;	}
+	}
+	if(strchr(dir,'y') && ny>1)
+	{
+		if(mgl_fft_data.hny==ny)	dht = (gsl_dht *)mgl_fft_data.hty;
+		else	{	dht = gsl_dht_new(ny,0,1);	clear = true;	}
+		mglStartThreadT(mgl_chnky,nx*nz,d->a,0,dht,0,par);
+		if(mgl_fft_data.hny==0)
+		{	mgl_fft_data.hty = dht;	clear = false;	mgl_fft_data.hny=ny;	}
+	}
+	if(strchr(dir,'z') && nz>1)
+	{
+		if(mgl_fft_data.hnz==nz)	dht = (gsl_dht *)mgl_fft_data.htz;
+		else	{	dht = gsl_dht_new(nz,0,1);	clear = true;	}
+		mglStartThreadT(mgl_chnkz,nx*ny,d->a,0,dht,0,par);
+		if(mgl_fft_data.hnz==0)
+		{	mgl_fft_data.htz = dht;	clear = false;	mgl_fft_data.hnz=nz;	}
+	}
+	if(clear)	gsl_dht_free(dht);
+}
+#else
+void MGL_EXPORT mgl_datac_hankel(HADT , const char *){}
+#endif
+void MGL_EXPORT mgl_datac_hankel_(uintptr_t *d, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_datac_hankel(_DC_,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+#if MGL_HAVE_GSL
+MGL_NO_EXPORT void* mgl_hnkx(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	long nx=t->p[0];
+	mreal *a = (mreal*)t->a;
+	const gsl_dht *dht = (const gsl_dht*)t->v;
+	double mm = gsl_sf_bessel_zero_J0(nx+1);
+
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel
+#endif
+	{
+		double *b = new double[2*nx];
+#pragma omp for nowait
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			for(long j=0;j<nx;j++)	b[j] = a[j+nx*i];
+			gsl_dht_apply(dht,b,b+nx);
+			for(long j=0;j<nx;j++)	a[j+nx*i] = b[j+nx]*mm;
+		}
+		delete []b;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void* mgl_hnky(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	long nx=t->p[0],ny=t->p[1];
+	mreal *a = (mreal*)t->a;
+	const gsl_dht *dht = (const gsl_dht*)t->v;
+	double mm = gsl_sf_bessel_zero_J0(ny+1);
+
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel
+#endif
+	{
+		double *b = new double[2*ny];
+#pragma omp for nowait
+		for(long ii=t->id;ii<t->n;ii+=mglNumThr)
+		{
+			long i = ii%nx, k = ii/nx;
+			for(long j=0;j<ny;j++)	b[j] = a[i+nx*(j+ny*k)];
+			gsl_dht_apply(dht,b,b+ny);
+			for(long j=0;j<ny;j++)a[i+nx*(j+ny*k)] = b[j+ny]*mm;
+		}
+		delete []b;
+	}
+	return 0;
+}
+MGL_NO_EXPORT void* mgl_hnkz(void *par)
+{
+	mglThreadT *t=(mglThreadT *)par;
+	long k=t->p[0]*t->p[1],nz=t->p[2];
+	mreal *a = (mreal*)t->a;
+	const gsl_dht *dht = (const gsl_dht*)t->v;
+	double mm = gsl_sf_bessel_zero_J0(nz+1);
+
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel
+#endif
+	{
+		double *b = new double[2*nz];
+#pragma omp for nowait
+		for(long i=t->id;i<t->n;i+=mglNumThr)
+		{
+			for(long j=0;j<nz;j++)	b[j] = a[i+j*k];
+			gsl_dht_apply(dht,b,b+nz);
+			for(long j=0;j<nz;j++)	a[i+j*k] = b[j+nz]*mm;
+		}
+		delete []b;
+	}
+	return 0;
+}
+void MGL_EXPORT mgl_data_hankel(HMDT d, const char *dir)
+{
+	if(!dir || *dir==0)	return;
+	bool clear = false;
+	gsl_dht *dht=0;
+	long nx=d->nx, ny=d->ny, nz=d->nz;
+	long par[3]={nx,ny,nz};
+	if(strchr(dir,'x') && nx>1)
+	{
+		if(mgl_fft_data.hnx==nx)	dht = (gsl_dht *)mgl_fft_data.htx;
+		else	{	dht = gsl_dht_new(nx,0,1);	clear = true;	}
+		mglStartThreadT(mgl_hnkx,ny*nz,d->a,0,dht,0,par);
+		if(mgl_fft_data.hnx==0)
+		{	mgl_fft_data.htx = dht;	clear = false;	mgl_fft_data.hnx=nx;	}
+	}
+	if(strchr(dir,'y') && ny>1)
+	{
+		if(mgl_fft_data.hny==ny)	dht = (gsl_dht *)mgl_fft_data.hty;
+		else	{	dht = gsl_dht_new(ny,0,1);	clear = true;	}
+		mglStartThreadT(mgl_hnky,nx*nz,d->a,0,dht,0,par);
+		if(mgl_fft_data.hny==0)
+		{	mgl_fft_data.hty = dht;	clear = false;	mgl_fft_data.hny=ny;	}
+	}
+	if(strchr(dir,'z') && nz>1)
+	{
+		if(mgl_fft_data.hnz==nz)	dht = (gsl_dht *)mgl_fft_data.htz;
+		else	{	dht = gsl_dht_new(nz,0,1);	clear = true;	}
+		mglStartThreadT(mgl_hnkz,nx*ny,d->a,0,dht,0,par);
+		if(mgl_fft_data.hnz==0)
+		{	mgl_fft_data.htz = dht;	clear = false;	mgl_fft_data.hnz=nz;	}
+	}
+	if(clear)	gsl_dht_free(dht);
+}
+#else
+void MGL_EXPORT mgl_data_hankel(HMDT , const char *){}
+#endif
+void MGL_EXPORT mgl_data_hankel_(uintptr_t *d, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_data_hankel(_DT_,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_fill_sample(HMDT d, const char *how)
+{
+	if(!how || *how==0)	return;
+	bool kk = mglchr(how,'k');
+	long n=d->nx,dn=1;
+	mreal *aa=d->a;
+	if(mglchr(how,'y'))	{	n=d->ny;	dn=d->nx;	}
+	if(mglchr(how,'z'))	{	n=d->nz;	dn=d->nx*d->ny;	}
+	if(mglchr(how,'h'))	// Hankel
+	{
+#if MGL_HAVE_GSL
+		gsl_dht *dht = gsl_dht_new(n,0,1);
+#pragma omp parallel for
+		for(long i=0;i<n;i++)
+			aa[i*dn] = kk ? gsl_dht_k_sample(dht, i) : gsl_dht_x_sample(dht, i);
+		gsl_dht_free(dht);
+#endif
+	}
+	else	// Fourier
+	{
+		if(kk)	for(long i=0;i<n;i++)	aa[i*dn] = M_PI*(i<n/2 ? i:i-n);
+		else	for(long i=0;i<n;i++)	aa[i*dn] = mreal(2*i-n)/n;
+	}
+#pragma omp parallel for
+	for(long i=0;i<d->GetNN();i++)	aa[i] = aa[((i%(n*dn))/dn)*dn];
+}
+void MGL_EXPORT mgl_data_fill_sample_(uintptr_t *d, const char *how,int l)
+{	char *s=new char[l+1];	memcpy(s,how,l);	s[l]=0;
+	mgl_data_fill_sample(_DT_,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_fft_(uintptr_t *d, const char *dir, int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_datac_fft(_DC_,s);	delete []s;	}
+void MGL_EXPORT mgl_data_fourier_(uintptr_t *re, uintptr_t *im, const char *dir, int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_data_fourier(_DM_(re),_DM_(im),s);	delete []s;	}
+uintptr_t MGL_EXPORT mgl_data_stfa_(uintptr_t *re, uintptr_t *im, int *dn, char *dir, int)
+{	return uintptr_t(mgl_data_stfa(_DA_(re),_DA_(im),*dn,*dir));	}
+void MGL_EXPORT mgl_data_cosfft_(uintptr_t *d, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_data_cosfft(_DT_,s);	delete []s;	}
+void MGL_EXPORT mgl_data_sinfft_(uintptr_t *d, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_data_sinfft(_DT_,s);	delete []s;	}
+void MGL_EXPORT mgl_datac_cosfft_(uintptr_t *d, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_datac_cosfft(_DC_,s);	delete []s;	}
+void MGL_EXPORT mgl_datac_sinfft_(uintptr_t *d, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_datac_sinfft(_DC_,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void* mgl_cor(void *par)
+{
+	mglThreadC *t=(mglThreadC *)par;
+	dual *a = t->a;
+	const dual *b = t->b;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel
+#endif
+	for(long i=t->id;i<t->n;i+=mglNumThr)	a[i] *= conj(b[i]);
+	return 0;
+}
+HADT MGL_EXPORT mgl_datac_correl(HCDT d1, HCDT d2, const char *dir)
+{
+	if(!dir || *dir==0)	return 0;
+	if(d2==NULL)	d2=d1;
+	long nx = d1->GetNx(), ny = d1->GetNy(), nz = d1->GetNz();
+	if(nx*ny*nz!=d2->GetNN())	return 0;
+	std::string dirs;
+	if(strchr(dir,'x') && nx>1)	dirs += 'x';
+	if(strchr(dir,'y') && ny>1)	dirs += 'y';
+	if(strchr(dir,'z') && nz>1)	dirs += 'z';
+	if(dirs.empty())	return 0;
+	mglDataC *a = new mglDataC(d1), *b=a;	a->FFT(dirs.c_str());
+	if(d1!=d2)
+	{	b = new mglDataC(d2);	b->FFT(dirs.c_str());	}
+//	mglStartThreadC(mgl_cor,0,nx*ny*nz,a->a,b->a);	// TODO: sth strange
+#pragma omp parallel for
+	for(long i=0;i<nx*ny*nz;i++)	a->a[i] *= conj(b->a[i]);
+	dirs += 'i';	a->FFT(dirs.c_str());
+	if(d1!=d2)	delete b;
+	return a;
+}
+uintptr_t MGL_EXPORT mgl_datac_correl_(uintptr_t *d1, uintptr_t *d2, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	uintptr_t res = uintptr_t(mgl_datac_correl(_DA_(d1),_DA_(d2),s));
+	delete []s;		return res;	}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_data_correl(HCDT d1, HCDT d2, const char *dir)
+{
+	HADT a = mgl_datac_correl(d1,d2,dir);	// NOTE: this is not so effective but straightforward way
+	if(!a)	return 0;
+	const long nx = d1->GetNx(), ny = d1->GetNy(), nz = d1->GetNz();
+	mglData *res = new mglData(nx,ny,nz);
+#pragma omp parallel for
+	for(long i=0;i<nx*ny*nz;i++)	res->a[i] = real(a->a[i]);
+	delete a;	return res;
+}
+uintptr_t MGL_EXPORT mgl_data_correl_(uintptr_t *d1, uintptr_t *d2, const char *dir,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	uintptr_t res = uintptr_t(mgl_data_correl(_DA_(d1),_DA_(d2),s));
+	delete []s;		return res;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_data_wavelet(HMDT dat, const char *how, int k)
+{
+#if MGL_HAVE_GSL
+	gsl_wavelet *w=0;
+	if(mglchr(how,'d'))	w = gsl_wavelet_alloc(gsl_wavelet_daubechies, k);
+	else if(mglchr(how,'D'))	w = gsl_wavelet_alloc(gsl_wavelet_daubechies_centered, k);
+	else if(mglchr(how,'h'))	w = gsl_wavelet_alloc(gsl_wavelet_haar, k);
+	else if(mglchr(how,'H'))	w = gsl_wavelet_alloc(gsl_wavelet_haar_centered, k);
+	else if(mglchr(how,'b'))	w = gsl_wavelet_alloc(gsl_wavelet_bspline, k);
+	else if(mglchr(how,'B'))	w = gsl_wavelet_alloc(gsl_wavelet_bspline_centered, k);
+	if(!w)	return;
+
+	double *a;
+#if MGL_USE_DOUBLE
+	a = dat->a;
+#else
+	long nn = dat->GetNN();
+	a = new double[nn];
+#pragma omp parallel for
+	for(long i=0;i<nn;i++)	a[i] = dat->a[i];
+#endif
+	if(mglchr(how,'x'))
+#pragma omp parallel
+	{
+		long n = dat->nx;
+		gsl_wavelet_workspace *work = gsl_wavelet_workspace_alloc(n);
+		if(mglchr(how,'i'))
+#pragma omp for
+			for(long i=0;i<dat->ny*dat->nz;i++)
+				gsl_wavelet_transform_inverse(w, a+i*n, 1, n, work);
+		else
+#pragma omp for
+			for(long i=0;i<dat->ny*dat->nz;i++)
+				gsl_wavelet_transform_forward(w, a+i*n, 1, n, work);
+		gsl_wavelet_workspace_free(work);
+	}
+	if(mglchr(how,'y'))
+#pragma omp parallel
+	{
+		long n = dat->ny, s = dat->nx;
+		gsl_wavelet_workspace *work = gsl_wavelet_workspace_alloc(n);
+		if(mglchr(how,'i'))
+#pragma omp for collapse(2)
+			for(long i=0;i<dat->nx;i++)	for(long j=0;j<dat->nz;j++)
+				gsl_wavelet_transform_inverse(w, a+i+n*s*j, s, n, work);
+		else
+#pragma omp for collapse(2)
+			for(long i=0;i<dat->nx;i++)	for(long j=0;j<dat->nz;j++)
+				gsl_wavelet_transform_forward(w, a+i+n*s*j, s, n, work);
+		gsl_wavelet_workspace_free(work);
+	}
+	if(mglchr(how,'z'))
+#pragma omp parallel
+	{
+		long n = dat->nz, s = dat->nx*dat->ny;
+		gsl_wavelet_workspace *work = gsl_wavelet_workspace_alloc(n);
+		if(mglchr(how,'i'))
+#pragma omp for
+			for(long i=0;i<dat->nx*dat->ny;i++)
+				gsl_wavelet_transform_inverse(w, a+i, s, n, work);
+		else
+#pragma omp for
+			for(long i=0;i<dat->nx*dat->ny;i++)
+				gsl_wavelet_transform_forward(w, a+i, s, n, work);
+		gsl_wavelet_workspace_free(work);
+	}
+#if !MGL_USE_DOUBLE
+#pragma omp parallel for
+	for(long i=0;i<nn;i++)	dat->a[i] = a[i];
+	delete []a;
+#endif
+	gsl_wavelet_free (w);
+#endif
+}
+void MGL_EXPORT mgl_data_wavelet_(uintptr_t *d, const char *dir, int *k,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_data_wavelet(_DT_,s,*k);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_datac_wavelet(HADT c, const char *how, int k)
+{
+	mglData re(c->nx, c->ny, c->nz), im(c->nx, c->ny, c->nz);
+	long n = c->GetNN();
+#pragma omp parallel for
+	for(long i=0;i<n;i++)	{	re.a[i]=real(c->a[i]);	im.a[i]=imag(c->a[i]);	}
+	mgl_data_wavelet(&re, how, k);
+	mgl_data_wavelet(&im, how, k);
+#pragma omp parallel for
+	for(long i=0;i<n;i++)	c->a[i] = dual(re.a[i], im.a[i]);
+}
+void MGL_EXPORT mgl_datac_wavelet_(uintptr_t *d, const char *dir, int *k,int l)
+{	char *s=new char[l+1];	memcpy(s,dir,l);	s[l]=0;
+	mgl_datac_wavelet(_DC_,s,*k);	delete []s;	}
+//-----------------------------------------------------------------------------
diff --git a/src/fit.cpp b/src/fit.cpp
new file mode 100644
index 0000000..852cfae
--- /dev/null
+++ b/src/fit.cpp
@@ -0,0 +1,603 @@
+/***************************************************************************
+ * fit.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <ctype.h>
+#include "mgl2/fit.h"
+#include "mgl2/prim.h"
+#include "mgl2/eval.h"
+#include "mgl2/data.h"
+#include "mgl2/base.h"
+
+#if MGL_HAVE_GSL
+#include <gsl/gsl_multifit_nlin.h>
+#include <gsl/gsl_blas.h>
+#endif
+HMDT MGL_NO_EXPORT mglFormulaCalc(const char *str, const std::vector<mglDataA*> &head);
+//-----------------------------------------------------------------------------
+int mglFitPnts=100;		///< Number of output points in fitting
+char mglFitRes[1024];	///< Last fitted formula
+mreal mglFitChi=NAN;	///< Chi value for last fitted formula
+mglData mglFitCovar;	///< Covar matrix for lat fitted formula
+//-----------------------------------------------------------------------------
+mreal MGL_EXPORT mgl_get_fit_chi()	{	return mglFitChi;	}
+mreal MGL_EXPORT mgl_get_fit_chi_()	{	return mglFitChi;	}
+//-----------------------------------------------------------------------------
+HCDT MGL_EXPORT mgl_get_fit_covar()	{	return &mglFitCovar;	}
+uintptr_t MGL_EXPORT mgl_get_fit_covar_()	{	return (uintptr_t)&mglFitCovar;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_puts_fit(HMGL gr, double x, double y, double z, const char *pre, const char *font, double size)
+{
+	long n = strlen(mglFitRes)+(pre?strlen(pre):0)+1;
+	char *buf = new char[n];
+	if(pre)	snprintf(buf,n,"%s%s",pre,mglFitRes);
+	else	strncpy(buf,mglFitRes,n);
+	buf[n-1]=0;	mgl_puts(gr,x,y,z,buf,font,size);
+	delete []buf;
+}
+void MGL_EXPORT mgl_puts_fit_(uintptr_t* gr, mreal *x, mreal *y, mreal *z, const char *prefix, const char *font, mreal *size, int l, int n)
+{
+	char *s=new char[l+1];	memcpy(s,prefix,l);	s[l]=0;
+	char *d=new char[n+1];	memcpy(d,font,n);	d[n]=0;
+	mgl_puts_fit(_GR_, *x,*y,*z, s, d, *size);
+	delete []s;		delete []d;
+}
+//-----------------------------------------------------------------------------
+/// Structure for keeping data and precompiled fitted formula
+struct mglFitData
+{
+	long n;				///< number of points
+	mglDataA *x,*y,*z;	///< x, y, z values
+	mreal *a;			///< function values
+	mreal *s;			///< value dispersions (sigma)
+	const char *eq;		///< approximation formula
+	int m;				///< number of variables
+	const char *var;	///< variables for fitting
+};
+//-----------------------------------------------------------------------------
+#if MGL_HAVE_GSL
+int	mgl_fit__f (const gsl_vector *x, void *data, gsl_vector *f)
+{
+	mglFitData *fd = (mglFitData *)data;
+	mglDataV *var = new mglDataV[fd->m];
+	std::vector<mglDataA*> list;
+	for(long i=0;i<fd->m;i++)
+	{	var[i].s=fd->var[i];	var[i].Fill(gsl_vector_get(x,i));	list.push_back(var+i);	}
+	if(fd->x)	list.push_back(fd->x);
+	if(fd->y)	list.push_back(fd->y);
+	if(fd->z)	list.push_back(fd->z);
+	HMDT res = mglFormulaCalc(fd->eq, list);
+#pragma omp parallel for
+	for(long i=0;i<fd->n;i++)
+	{
+		mreal aa = fd->a[i], ss = fd->s[i];
+		if(mgl_isnum(aa) && ss==ss && ss!=0)
+			gsl_vector_set (f, i, (res->a[i] - aa)/ss);
+		else	gsl_vector_set (f, i, 0);
+	}
+	delete []var;	mgl_delete_data(res);
+	return GSL_SUCCESS;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgl_fit__df (const gsl_vector * x, void *data, gsl_matrix * J)
+{
+	mglFitData *fd = (mglFitData *)data;
+	mglDataV *var = new mglDataV[fd->m];
+	std::vector<mglDataA*> list;
+	for(long i=0;i<fd->m;i++)
+	{	var[i].s=fd->var[i];	var[i].Fill(gsl_vector_get(x,i));	list.push_back(var+i);	}
+	if(fd->x)	list.push_back(fd->x);
+	if(fd->y)	list.push_back(fd->y);
+	if(fd->z)	list.push_back(fd->z);
+	HMDT res = mglFormulaCalc(fd->eq, list);
+	const mreal eps = 1e-5;
+	for(long j=0;j<fd->m;j++)
+	{
+		var[j].Fill(gsl_vector_get(x,j)+eps);
+		HMDT dif = mglFormulaCalc(fd->eq, list);
+		var[j].Fill(gsl_vector_get(x,j));
+#pragma omp parallel for
+		for(long i=0;i<fd->n;i++)
+		{
+			mreal aa = fd->a[i], ss = fd->s[i];
+			if(mgl_isnum(aa) && ss==ss && ss!=0)
+				gsl_matrix_set (J, i, j, (dif->a[i]-res->a[i])/(eps*ss));
+			else	gsl_matrix_set (J, i, j, 0);
+		}
+		mgl_delete_data(dif);
+	}
+	delete []var;	mgl_delete_data(res);
+	return GSL_SUCCESS;
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgl_fit__fdf (const gsl_vector * x, void *data, gsl_vector * f, gsl_matrix * J)
+{
+	mglFitData *fd = (mglFitData *)data;
+	mglDataV *var = new mglDataV[fd->m];
+	std::vector<mglDataA*> list;
+	for(long i=0;i<fd->m;i++)
+	{	var[i].s=fd->var[i];	var[i].Fill(gsl_vector_get(x,i));	list.push_back(var+i);	}
+	if(fd->x)	list.push_back(fd->x);
+	if(fd->y)	list.push_back(fd->y);
+	if(fd->z)	list.push_back(fd->z);
+	HMDT res = mglFormulaCalc(fd->eq, list);
+#pragma omp parallel for
+	for(long i=0;i<fd->n;i++)
+	{
+		mreal aa = fd->a[i], ss = fd->s[i];
+		if(mgl_isnum(aa) && ss==ss && ss!=0)
+			gsl_vector_set (f, i, (res->a[i] - aa)/ss);
+		else	gsl_vector_set (f, i, 0);
+	}
+	const mreal eps = 1e-5;
+	for(long j=0;j<fd->m;j++)
+	{
+		var[j].Fill(gsl_vector_get(x,j)+eps);
+		HMDT dif = mglFormulaCalc(fd->eq, list);
+		var[j].Fill(gsl_vector_get(x,j));
+#pragma omp parallel for
+		for(long i=0;i<fd->n;i++)
+		{
+			mreal aa = fd->a[i], ss = fd->s[i];
+			if(mgl_isnum(aa) && ss==ss && ss!=0)
+				gsl_matrix_set (J, i, j, (dif->a[i]-res->a[i])/(eps*ss));
+			else	gsl_matrix_set (J, i, j, 0);
+		}
+		mgl_delete_data(dif);
+	}
+	delete []var;	mgl_delete_data(res);
+	return GSL_SUCCESS;
+}
+#endif
+//-----------------------------------------------------------------------------
+/// GSL based fitting procedure for formula/arguments specified by string
+mreal MGL_NO_EXPORT mgl_fit_base(mglFitData &fd, mreal *ini)
+{
+#if MGL_HAVE_GSL
+	long m=fd.m,n=fd.n,iter=0;
+	if(n<1 || ini==0)	return -1;
+	// setup data
+	double *x_init = new double[fd.m];
+	for(long i=0;i<m;i++)	x_init[i] = ini[i];
+	// setup fitting
+	gsl_vector_view vx = gsl_vector_view_array(x_init, m);
+	const gsl_multifit_fdfsolver_type *T = gsl_multifit_fdfsolver_lmsder;
+	gsl_multifit_fdfsolver *s = gsl_multifit_fdfsolver_alloc(T, n, m);
+	gsl_multifit_function_fdf f;
+	f.f = mgl_fit__f;		f.df = mgl_fit__df;
+	f.fdf = mgl_fit__fdf;	f.n = n;	f.p = m;
+	f.params = &fd;
+	gsl_multifit_fdfsolver_set(s, &f, &vx.vector);
+	int status;	// start fitting
+	do
+	{
+		iter++;
+		status = gsl_multifit_fdfsolver_iterate(s);
+		if ( status )	break;
+		status = gsl_multifit_test_delta (s->dx, s->x, 1e-4, 1e-4 );
+	}
+	while ( status == GSL_CONTINUE && iter < 500 );
+
+	gsl_matrix *covar = gsl_matrix_alloc(m, m);
+#ifdef MGL_HAVE_GSL2
+	gsl_matrix *J = gsl_matrix_alloc(s->fdf->n, s->fdf->p);
+	gsl_multifit_fdfsolver_jac(s, J);
+	gsl_multifit_covar (J, 0.0, covar);
+	gsl_matrix_free (J);
+#else
+	gsl_multifit_covar(s->J, 0.0, covar);
+#endif
+	mglFitCovar.Set(covar);
+	gsl_matrix_free(covar);
+
+	mreal res = gsl_blas_dnrm2(s->f);
+	for(long i=0;i<m;i++)	ini[i] = gsl_vector_get(s->x, i);
+	// free memory
+	gsl_multifit_fdfsolver_free(s);
+	delete []x_init;
+	return res;
+#else
+	return 0.0;
+#endif
+}
+//-----------------------------------------------------------------------------
+void mglPrepareFitEq(mglBase *gr,mreal chi, const char *eq, const char *var, mreal *par)
+{
+	char buf[32]="";
+	mglFitChi = chi;
+	snprintf(mglFitRes,1024,"chi=%g",chi);	mglFitRes[1023]=0;
+	size_t i,k,len=strlen(var);
+	for(i=0;i<len;i++)
+	{
+		snprintf(buf,32,", %c=%g",var[i],par[i]);
+		buf[31]=0;	strcat(mglFitRes,buf);
+	}
+	gr->SetWarn(-1,mglFitRes);
+
+	memset(mglFitRes, 0, 1024);	//mglFitRes[0] = 0;
+	len=strlen(eq);
+	for(i=k=0;i<len;i++)
+	{
+		const char *c = strchr(var,eq[i]);
+		if(c && (i==0 || !isalnum(eq[i-1])) && (i==len-1 || !isalnum(eq[i+1])))
+		{
+			snprintf(buf,32,"%g",par[c-var]);
+			buf[31]=0;	strcat(mglFitRes+k, buf);	k+=strlen(buf);
+		}
+		else	{	mglFitRes[k] = eq[i];	k++;	}
+	}
+	mglFitRes[k]=0;
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_fit_1(HMGL gr, HCDT y, const char *eq, const char *var, HMDT ini, const char *opt)
+{
+	gr->SaveState(opt);
+	mglData x(y->GetNx());	x.Fill(gr->Min.x, gr->Max.x);
+	mglData s(y);		s.Fill(1,1);
+	return mgl_fit_xys(gr,&x,y,&s,eq,var,ini,0);
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_fit_2(HMGL gr, HCDT z, const char *eq, const char *var, HMDT ini, const char *opt)
+{
+	gr->SaveState(opt);
+	mglData x(z->GetNx());	x.Fill(gr->Min.x, gr->Max.x);
+	mglData y(z->GetNy());	y.Fill(gr->Min.y, gr->Max.y);
+	mglData s(z);		s.Fill(1,1);
+	return mgl_fit_xyzs(gr,&x,&y,z,&s,eq,var,ini,0);
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_fit_3(HMGL gr, HCDT a, const char *eq, const char *var, HMDT ini, const char *opt)
+{
+	gr->SaveState(opt);
+	mglData x(a->GetNx());	x.Fill(gr->Min.x, gr->Max.x);
+	mglData y(a->GetNy());	y.Fill(gr->Min.y, gr->Max.y);
+	mglData z(a->GetNz());	z.Fill(gr->Min.z, gr->Max.z);
+	mglData s(a);		s.Fill(1,1);
+	return mgl_fit_xyzas(gr,&x,&y,&z,a,&s,eq,var,ini,0);
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_fit_xy(HMGL gr, HCDT x, HCDT y, const char *eq, const char *var, HMDT ini, const char *opt)
+{
+	mglData s(y);	s.Fill(1,1);
+	return mgl_fit_xys(gr,x,y,&s,eq,var,ini,opt);
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_fit_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, const char *eq, const char *var, HMDT ini, const char *opt)
+{
+	mglData s(z);	s.Fill(1,1);
+	return mgl_fit_xyzs(gr,x,y,z,&s,eq,var,ini,opt);
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_fit_xyza(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, const char *eq, const char *var, HMDT ini, const char *opt)
+{
+	mglData s(a);	s.Fill(1,1);
+	return mgl_fit_xyzas(gr,x,y,z,a,&s,eq,var,ini,opt);
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_fit_ys(HMGL gr, HCDT y, HCDT s, const char *eq, const char *var, HMDT ini, const char *opt)
+{
+	gr->SaveState(opt);
+	mglData x(y->GetNx());	x.Fill(gr->Min.x, gr->Max.x);
+	return mgl_fit_xys(gr,&x,y,s,eq,var,ini,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_fill_fit(HMGL gr, mglData &fit, mglData &in, mglFitData &fd, const char *var, long nx, long ny, long nz, long k)
+{
+	mglDataV *vv = new mglDataV[fd.m];
+	std::vector<mglDataA*> list;
+	for(long i=0;i<fd.m;i++)
+	{	vv[i].s=var[i];	vv[i].Fill(in.a[i]);	list.push_back(vv+i);	}
+	mglDataV x(nx,ny,nz, gr->Min.x,gr->Max.x,'x');	x.s = L"x";	list.push_back(&x);
+	mglDataV y(nx,ny,nz, gr->Min.y,gr->Max.y,'y');	y.s = L"y";	list.push_back(&y);
+	mglDataV z(nx,ny,nz, gr->Min.z,gr->Max.z,'z');	z.s = L"z";	list.push_back(&z);
+	HMDT res = mglFormulaCalc(fd.eq, list);
+	long nn = nx*ny*nz;
+	memcpy(fit.a+k*nn,res->a,nn*sizeof(mreal));
+	delete []vv;	mgl_delete_data(res);
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_fit_xys(HMGL gr, HCDT xx, HCDT yy, HCDT ss, const char *eq, const char *var, HMDT ini, const char *opt)
+{
+	long m = yy->GetNx();
+	mreal rr = gr->SaveState(opt);
+	long nn = (mgl_isnan(rr) || rr<=0) ? mglFitPnts:long(rr+0.5);
+	if(xx->GetNx()!=m)
+	{	gr->SetWarn(mglWarnDim,"Fit[S]");	return 0;	}
+	if(m<2)
+	{	gr->SetWarn(mglWarnLow,"Fit[S]");	return 0;	}
+	if(ss->GetNN() != yy->GetNN())
+	{	gr->SetWarn(mglWarnDim,"Fit[S]");	return 0;	}
+	if(!var || *var==0)
+	{	gr->SetWarn(mglWarnNull,"Fit[S]");	return 0;	}
+
+	mglData x(xx), y(yy), s(ss);	x.s=L"x";
+	long mm = yy->GetNy()*yy->GetNz();
+#pragma omp parallel for
+	for(long i=0;i<m;i++)	if(mgl_isnan(x.a[i]))
+		for(long j=0;j<mm;j++)	y.a[i+m*j] = NAN;
+	mglFitData fd;
+	fd.n = m;	fd.x = &x;		fd.y = 0;
+	fd.z = 0;	fd.a = y.a;		fd.s = s.a;
+	fd.eq = eq;	fd.var = var;	fd.m = strlen(var);
+	mglData in(fd.m), *fit=new mglData(nn, yy->GetNy(), yy->GetNz());
+	mreal res=-1;
+	mglDataR xc(x);
+	for(long i=0;i<yy->GetNy()*yy->GetNz();i++)
+	{
+		if(ini && ini->nx>=fd.m)	in.Set(ini->a,fd.m);
+		else in.Fill(0.,0);
+		xc.SetInd(i%x.ny, L"x");
+		fd.a = y.a+i*m;		fd.x = &xc;	//x.a+(i%x.ny)*m;
+		fd.s = s.a+i*m;
+		res = mgl_fit_base(fd,in.a);
+		mgl_fill_fit(gr,*fit,in,fd,var,nn,1,1,i);
+		if(ini && ini->nx>=fd.m)	memcpy(ini->a,in.a,fd.m*sizeof(mreal));
+	}
+	mglPrepareFitEq(gr,res,eq,var,in.a);
+	gr->LoadState();	return fit;
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_fit_xyzs(HMGL gr, HCDT xx, HCDT yy, HCDT zz, HCDT ss, const char *eq, const char *var, HMDT ini, const char *opt)
+{
+	long m=zz->GetNx(),n=zz->GetNy();
+	mreal rr = gr->SaveState(opt);
+	long nn = (mgl_isnan(rr) || rr<=0) ? mglFitPnts:long(rr+0.5);
+	if(xx->GetNx()!=m)
+	{	gr->SetWarn(mglWarnDim,"Fit[S]");	return 0;	}
+	if(ss->GetNN() != zz->GetNN())
+	{	gr->SetWarn(mglWarnDim,"Fit[S]");	return 0;	}
+	if(yy->GetNx()!=n && (xx->GetNy()!=n || yy->GetNx()!=m || yy->GetNy()!=n))
+	{	gr->SetWarn(mglWarnDim,"Fit[S]");	return 0;	}
+	if(m<2|| n<2)
+	{	gr->SetWarn(mglWarnLow,"Fit[S]");	return 0;	}
+	if(!var || *var==0)
+	{	gr->SetWarn(mglWarnNull,"Fit[S]");	return 0;	}
+
+	mglData x(m, n), y(m, n), z(zz), s(ss);	x.s=L"x";	y.s=L"y";
+	long nz = zz->GetNz(), mm = n*m;
+#pragma omp parallel for collapse(2)
+	for(long i=0;i<m;i++)	for(long j=0;j<n;j++)
+	{
+		long i0 = i+m*j;
+		x.a[i0] = GetX(xx,i,j,0).x;
+		y.a[i0] = GetY(yy,i,j,0).x;
+		if(mgl_isnan(x.a[i0]) || mgl_isnan(y.a[i0]))
+			for(long k=0;k<nz;k++)	z.a[i0+mm*k] = NAN;
+	}
+	mglFitData fd;
+	fd.n = m*n;	fd.x = &x;	fd.y = &y;
+	fd.z = 0;	fd.a = z.a;	fd.s = s.a;
+	fd.eq = eq;	fd.var=var;	fd.m = strlen(var);
+
+	mglData in(fd.m), *fit=new mglData(nn, nn, zz->GetNz());
+	mreal res = -1;
+	for(long i=0;i<nz;i++)
+	{
+		if(ini && ini->nx>=fd.m)	in.Set(ini->a,fd.m);
+		else in.Fill(0.,0);
+		fd.a = z.a+i*m*n;		fd.s = s.a+i*m*n;
+		res = mgl_fit_base(fd,in.a);
+		mgl_fill_fit(gr,*fit,in,fd,var,nn,nn,1,i);
+		if(ini && ini->nx>=fd.m)	memcpy(ini->a,in.a,fd.m*sizeof(mreal));
+	}
+	mglPrepareFitEq(gr,res, eq,var,in.a);
+	gr->LoadState();	return fit;
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_fit_xyzas(HMGL gr, HCDT xx, HCDT yy, HCDT zz, HCDT aa, HCDT ss, const char *eq, const char *var, HMDT ini, const char *opt)
+{
+	long m=aa->GetNx(), n=aa->GetNy(), l=aa->GetNz(), i = n*m*l;
+	mreal rr = gr->SaveState(opt);
+	long nn = (mgl_isnan(rr) || rr<=0) ? mglFitPnts:long(rr+0.5);
+	if(m<2 || n<2 || l<2)
+	{	gr->SetWarn(mglWarnLow,"Fit[S]");	return 0;	}
+	if(ss->GetNN() != i)
+	{	gr->SetWarn(mglWarnDim,"Fit[S]");	return 0;	}
+	bool both = xx->GetNN()==i && yy->GetNN()==i && zz->GetNN()==i;
+	if(!(both || (xx->GetNx()==m && yy->GetNx()==n && zz->GetNx()==l)))
+	{	gr->SetWarn(mglWarnDim,"Fit[S]");	return 0;	}
+	if(!var || *var==0)
+	{	gr->SetWarn(mglWarnNull,"Fit[S]");	return 0;	}
+
+	mglData x(m,n,l), y(m,n,l), z(m,n,l), a(aa), s(ss);
+	x.s=L"x";	y.s=L"y";	z.s=L"z";
+#pragma omp parallel for collapse(3)
+	for(long i=0;i<m;i++)	for(long j=0;j<n;j++)	for(long k=0;k<l;k++)
+	{
+		long i0 = i+m*(j+n*k);
+		x.a[i0] = GetX(xx,i,j,k).x;
+		y.a[i0] = GetY(yy,i,j,k).x;
+		z.a[i0] = GetZ(zz,i,j,k).x;
+		if(mgl_isnan(x.a[i0]) || mgl_isnan(y.a[i0]) || mgl_isnan(z.a[i0]))	a.a[i0] = NAN;
+	}
+	mglFitData fd;
+	fd.n = m*n*l;	fd.x = &x;	fd.y = &y;
+	fd.z = &z;		fd.a = a.a;	fd.s = s.a;
+	fd.eq = eq;		fd.var=var;	fd.m = strlen(var);
+	mglData in(fd.m), *fit=new mglData(nn, nn, nn);
+	mreal res = -1;
+
+	if(ini && ini->nx>=fd.m)	in.Set(ini->a,fd.m);
+	else in.Fill(0.,0);
+	res = mgl_fit_base(fd,in.a);
+	mgl_fill_fit(gr,*fit,in,fd,var,nn,nn,nn,0);
+	if(ini && ini->nx>=fd.m)	memcpy(ini->a,in.a,fd.m*sizeof(mreal));
+
+	mglPrepareFitEq(gr,res, eq,var,in.a);
+	gr->LoadState();	return fit;
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_hist_x(HMGL gr, HCDT x, HCDT a, const char *opt)
+{
+	long nn=a->GetNN();
+	if(nn!=x->GetNN())
+	{	gr->SetWarn(mglWarnDim,"Hist");	return 0;	}
+	mreal rr = gr->SaveState(opt);
+	long n = (mgl_isnan(rr) || rr<=0) ? mglFitPnts:long(rr+0.5);
+	mglData *res = new mglData(n);
+
+	mreal vx = n/(gr->Max.x-gr->Min.x);
+	for(long i=0;i<nn;i++)
+	{
+		long j1 = long((x->vthr(i)-gr->Min.x)*vx);
+		if(j1>=0 && j1<n)	res->a[j1] += a->vthr(i);
+	}
+	gr->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_hist_xy(HMGL gr, HCDT x, HCDT y, HCDT a, const char *opt)
+{
+	long nn=a->GetNN();
+	if(nn!=x->GetNN() || nn!=y->GetNN())
+	{	gr->SetWarn(mglWarnDim,"Hist");	return 0;	}
+	mreal rr = gr->SaveState(opt);
+	long n = (mgl_isnan(rr) || rr<=0) ? mglFitPnts:long(rr+0.5);
+	mglData *res = new mglData(n, n);
+	mreal vx = n/(gr->Max.x-gr->Min.x);
+	mreal vy = n/(gr->Max.y-gr->Min.y);
+	for(long i=0;i<nn;i++)
+	{
+		long j1 = long((x->vthr(i)-gr->Min.x)*vx);
+		long j2 = long((y->vthr(i)-gr->Min.y)*vy);
+		if(j1>=0 && j1<n && j2>=0 && j2<n)	res->a[j1+n*j2] += a->vthr(i);
+	}
+	gr->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_hist_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, const char *opt)
+{
+	long nn=a->GetNN();
+	if(nn!=x->GetNN() || nn!=y->GetNN() || nn!=z->GetNN())
+	{	gr->SetWarn(mglWarnDim,"Hist");	return 0;	}
+	mreal rr = gr->SaveState(opt);
+	long n = (mgl_isnan(rr) || rr<=0) ? mglFitPnts:long(rr+0.5);
+	mglData *res = new mglData(n, n, n);
+	mreal vx = n/(gr->Max.x-gr->Min.x), vy = n/(gr->Max.y-gr->Min.y), vz = n/(gr->Max.z-gr->Min.z);
+	for(long i=0;i<nn;i++)
+	{
+		long j1 = long((x->vthr(i)-gr->Min.x)*vx);
+		long j2 = long((y->vthr(i)-gr->Min.y)*vy);
+		long j3 = long((z->vthr(i)-gr->Min.z)*vz);
+		if(j1>=0 && j1<n && j2>=0 && j2<n && j3>=0 && j3<n)
+			res->a[j1+n*(j2+n*j3)] += a->vthr(i);
+	}
+	gr->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_hist_x_(uintptr_t* gr, uintptr_t* x, uintptr_t* a, const char *opt, int lo)
+{	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	uintptr_t r = (uintptr_t)mgl_hist_x(_GR_, _DA_(x), _DA_(a), o);
+	delete []o;	return r;	}
+uintptr_t MGL_EXPORT mgl_hist_xy_(uintptr_t* gr, uintptr_t* x, uintptr_t* y, uintptr_t* a, const char *opt, int lo)
+{	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	uintptr_t r = (uintptr_t)mgl_hist_xy(_GR_, _DA_(x), _DA_(y), _DA_(a), o);
+	delete []o;	return r;	}
+uintptr_t MGL_EXPORT mgl_hist_xyz_(uintptr_t* gr, uintptr_t* x, uintptr_t* y, uintptr_t* z, uintptr_t* a, const char *opt, int lo)
+{	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	uintptr_t r = (uintptr_t)mgl_hist_xyz(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(a), o);
+	delete []o;	return r;	}
+//-----------------------------------------------------------------------------
+MGL_EXPORT const char *mgl_get_fit(HMGL )	{	return mglFitRes;	}
+int MGL_EXPORT mgl_get_fit_(uintptr_t *gr, char *out, int len)
+{
+	const char *res = mgl_get_fit(_GR_);
+	if(out)	strncpy(out,res,len);
+	return strlen(res);
+}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_fit_1_(uintptr_t* gr, uintptr_t* y, const char *eq, const char *var, uintptr_t *ini, const char *opt, int l, int n, int lo)
+{
+	char *s=new char[l+1];	memcpy(s,eq,l);		s[l]=0;
+	char *d=new char[n+1];	memcpy(d,var,n);	d[n]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	uintptr_t r = (uintptr_t)mgl_fit_1(_GR_, _DA_(y), s, d, _DM_(ini), o);
+	delete []o;	delete []s;	delete []d;	return r;
+}
+uintptr_t MGL_EXPORT mgl_fit_2_(uintptr_t* gr, uintptr_t* z, const char *eq, const char *var, uintptr_t *ini, const char *opt, int l, int n, int lo)
+{
+	char *s=new char[l+1];	memcpy(s,eq,l);		s[l]=0;
+	char *d=new char[n+1];	memcpy(d,var,n);	d[n]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	uintptr_t r = (uintptr_t)mgl_fit_2(_GR_, _DA_(z), s, d, _DM_(ini), o);
+	delete []o;	delete []s;	delete []d;	return r;
+}
+uintptr_t MGL_EXPORT mgl_fit_3_(uintptr_t* gr, uintptr_t* a, const char *eq, const char *var, uintptr_t *ini, const char *opt, int l, int n, int lo)
+{
+	char *s=new char[l+1];	memcpy(s,eq,l);		s[l]=0;
+	char *d=new char[n+1];	memcpy(d,var,n);	d[n]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	uintptr_t r = (uintptr_t)mgl_fit_3(_GR_, _DA_(a), s, d, _DM_(ini), o);
+	delete []o;	delete []s;	delete []d;	return r;
+}
+uintptr_t MGL_EXPORT mgl_fit_xy_(uintptr_t* gr, uintptr_t* x, uintptr_t* y, const char *eq, const char *var, uintptr_t *ini, const char *opt, int l, int n, int lo)
+{
+	char *s=new char[l+1];	memcpy(s,eq,l);		s[l]=0;
+	char *d=new char[n+1];	memcpy(d,var,n);	d[n]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	uintptr_t r = (uintptr_t)mgl_fit_xy(_GR_, _DA_(x), _DA_(y), s, d, _DM_(ini), o);
+	delete []o;	delete []s;	delete []d;	return r;
+}
+uintptr_t MGL_EXPORT mgl_fit_xyz_(uintptr_t* gr, uintptr_t* x, uintptr_t* y, uintptr_t* z, const char *eq, const char *var, uintptr_t *ini, const char *opt, int l, int n, int lo)
+{
+	char *s=new char[l+1];	memcpy(s,eq,l);		s[l]=0;
+	char *d=new char[n+1];	memcpy(d,var,n);	d[n]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	uintptr_t r = (uintptr_t)mgl_fit_xyz(_GR_, _DA_(x), _DA_(y), _DA_(z), s, d, _DM_(ini), o);
+	delete []o;	delete []s;	delete []d;	return r;
+}
+uintptr_t MGL_EXPORT mgl_fit_xyza_(uintptr_t* gr, uintptr_t* x, uintptr_t* y, uintptr_t* z, uintptr_t* a, const char *eq, const char *var, uintptr_t *ini, const char *opt, int l, int n, int lo)
+{
+	char *s=new char[l+1];	memcpy(s,eq,l);		s[l]=0;
+	char *d=new char[n+1];	memcpy(d,var,n);	d[n]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	uintptr_t r = (uintptr_t)mgl_fit_xyza(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(a), s, d, _DM_(ini), o);
+	delete []o;	delete []s;	delete []d;	return r;
+}
+uintptr_t MGL_EXPORT mgl_fit_ys_(uintptr_t* gr, uintptr_t* y, uintptr_t* ss, const char *eq, const char *var, uintptr_t *ini, const char *opt, int l, int n, int lo)
+{
+	char *s=new char[l+1];	memcpy(s,eq,l);		s[l]=0;
+	char *d=new char[n+1];	memcpy(d,var,n);	d[n]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	uintptr_t r = (uintptr_t)mgl_fit_ys(_GR_, _DA_(y), _DA_(ss), s, d, _DM_(ini), o);
+	delete []o;	delete []s;	delete []d;	return r;
+}
+uintptr_t MGL_EXPORT mgl_fit_xys_(uintptr_t* gr, uintptr_t* x, uintptr_t* y, uintptr_t* ss, const char *eq, const char *var, uintptr_t *ini, const char *opt, int l, int n, int lo)
+{
+	char *s=new char[l+1];	memcpy(s,eq,l);		s[l]=0;
+	char *d=new char[n+1];	memcpy(d,var,n);	d[n]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	uintptr_t r = (uintptr_t)mgl_fit_xys(_GR_, _DA_(x), _DA_(y), _DA_(ss), s, d, _DM_(ini), o);
+	delete []o;	delete []s;	delete []d;	return r;
+}
+uintptr_t MGL_EXPORT mgl_fit_xyzs_(uintptr_t* gr, uintptr_t* x, uintptr_t* y, uintptr_t* z, uintptr_t* ss, const char *eq, const char *var, uintptr_t *ini, const char *opt, int l, int n, int lo)
+{
+	char *s=new char[l+1];	memcpy(s,eq,l);		s[l]=0;
+	char *d=new char[n+1];	memcpy(d,var,n);	d[n]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	uintptr_t r = (uintptr_t)mgl_fit_xyzs(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(ss), s, d, _DM_(ini), o);
+	delete []o;	delete []s;	delete []d;	return r;
+}
+uintptr_t MGL_EXPORT mgl_fit_xyzas_(uintptr_t* gr, uintptr_t* x, uintptr_t* y, uintptr_t* z, uintptr_t* a, uintptr_t* ss, const char *eq, const char *var, uintptr_t *ini, const char *opt, int l, int n, int lo)
+{
+	char *s=new char[l+1];	memcpy(s,eq,l);		s[l]=0;
+	char *d=new char[n+1];	memcpy(d,var,n);	d[n]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	uintptr_t r = (uintptr_t)mgl_fit_xyzas(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(a), _DA_(ss), s, d, _DM_(ini), o);
+	delete []o;	delete []s;	delete []d;	return r;
+}
+//-----------------------------------------------------------------------------
diff --git a/src/font.cpp b/src/font.cpp
new file mode 100644
index 0000000..0996ded
--- /dev/null
+++ b/src/font.cpp
@@ -0,0 +1,994 @@
+/***************************************************************************
+ * font.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <locale.h>
+#include <ctype.h>
+#include <wctype.h>
+#include <unistd.h>
+
+#if !defined(__BORLANDC__) || (__CODEGEARC__ >=  0x0630)
+#include <algorithm>
+#else
+#include <algorithm.h>
+#endif
+
+#include "mgl2/base.h"
+#include "mgl2/font.h"
+#include "def_font.cc"
+#include "tex_table.cc"
+//-----------------------------------------------------------------------------
+//mglFont mglDefFont("nofont");
+mglFont mglDefFont;
+//-----------------------------------------------------------------------------
+size_t MGL_EXPORT mgl_wcslen(const wchar_t *str)
+{
+	long i=0;
+	if(str)	while(str[i])	i++;
+	return i;
+}
+//-----------------------------------------------------------------------------
+long MGL_EXPORT_PURE mgl_internal_code(unsigned s, const std::vector<mglGlyphDescr> &glyphs)
+{
+	long i1=0,i2=glyphs.size()-1;
+	wchar_t j = wchar_t(s & MGL_FONT_MASK);
+	// let suppose that id[i]<id[i+1]
+	while(i1<i2)
+	{
+		long i = (i1+i2)/2;
+		if(j<glyphs[i].id)		i2 = i;
+		else if(j>glyphs[i].id)	i1=i+1;
+		else return i;
+	}
+	return j==glyphs[i2].id ? i2 : -1;
+}
+//-----------------------------------------------------------------------------
+bool MGL_EXPORT mglGetStyle(const char *how, int *font, int *align)
+{
+	bool col=false;
+	if(align)	*align = 1;	// centering text by default
+	if(!how || *how==0)	return col;
+	// NOTE: no brightness for text color
+	for(;*how && *how!=':';how++)
+	{
+		if(strchr(MGL_COLORS,*how))		col = true;
+		if(*how=='{' && how[1]=='x')	col = true;
+	}
+	if(align)
+	{
+		*align = 1;
+		if(strchr(how,'R'))	*align = 2;
+//		if(strchr(how,'C'))	*align = 1;
+		if(strchr(how,'L'))	*align = 0;
+		if(strchr(how,'D'))	*align+= 4;
+	}
+	if(font)
+	{
+		*font = 0;
+		if(strchr(how,'b'))	*font = *font|MGL_FONT_BOLD;
+		if(strchr(how,'i'))	*font = *font|MGL_FONT_ITAL;
+		if(strchr(how,'w'))	*font = *font|MGL_FONT_WIRE;
+		if(strchr(how,'o'))	*font = *font|MGL_FONT_OLINE;
+		if(strchr(how,'u'))	*font = *font|MGL_FONT_ULINE;
+	}
+	return col;
+}
+//-----------------------------------------------------------------------------
+float mglFont::Puts(const char *str,const char *how,float c1,float c2) const
+{
+	int font=0, align=1;	float w=0;
+	mglGetStyle(how,&font,&align);
+	MGL_TO_WCS(str,w = Puts(wcs,font,align,c1,c2));
+	return w;
+}
+//-----------------------------------------------------------------------------
+float mglFont::Width(const char *str,const char *how) const
+{
+	int font=0;	float w=0;
+	mglGetStyle(how,&font);
+	MGL_TO_WCS(str,w = Width(wcs,font));
+	return w;
+}
+//-----------------------------------------------------------------------------
+float mglFont::Puts(const wchar_t *str,const char *how,float c1,float c2) const
+{
+	int font=0, align=1;
+	mglGetStyle(how,&font,&align);
+	return Puts(str, font, align,c1,c2);
+}
+//-----------------------------------------------------------------------------
+float mglFont::Width(const wchar_t *str,const char *how) const
+{
+	int font=0;
+	mglGetStyle(how,&font);
+	return Width(str, font);
+}
+//-----------------------------------------------------------------------------
+float mglFont::Puts(const wchar_t *str,int font,int align, float c1,float c2) const
+{
+	if(GetNumGlyph()==0 || !str || *str==0)	return 0;
+	float ww=0,w=0,h = (align&4) ? 500./fact[0] : 0;
+	size_t size = mgl_wcslen(str)+1,num=0;
+	if(parse)
+	{
+		unsigned *wcs = new unsigned[size], *buf=wcs;
+		memcpy(wcs,str,size*sizeof(wchar_t));
+		Convert(str, wcs);
+		for(size_t i=0;wcs[i];i++)
+		{
+			if(wcs[i]=='\n')	// parse '\n' symbol
+			{
+				wcs[i]=0;	w = Puts(buf,0,0,1.f,0x10|font,c1,c2);	// find width
+				Puts(buf,-w*(align&3)/2.f,-h - 660*num/fact[0],1.f,font,c1,c2);	// draw it really
+				buf=wcs+i+1;	num++;	if(w>ww)	ww=w;
+			}
+// 			if(wcs[i]=='\\' && wcs[i+1]=='n' && (wcs[i+2]>' ' || wcschr(L"{}[]()!@#$%^&*/-?.,_=+\\\"", wcs[i+2])))	// parse '\n' symbol
+// 			{
+// 				wcs[i]=0;	w = Puts(buf,0,0,1.f,0x10|font,c1,c2);	// find width
+// 				Puts(buf,-w*(align&3)/2.f,-h - 720.*num/fact[0],1.f,font,c1,c2);	// draw it really
+// 				buf=wcs+i+2;	num++;	if(w>ww)	ww=w;
+// 			}
+		}
+		// draw string itself
+		w = Puts(buf,0,0,1.f,0x10|font,c1,c2);	// find width
+		Puts(buf,-w*(align&3)/2.f,-h - 660*num/fact[0],1.f,font,c1,c2);	// draw it really
+		if(w>ww)	ww=w;
+		delete []wcs;
+	}
+	else
+	{
+		int s = (font/MGL_FONT_BOLD)&3;
+		h *= fact[0]/fact[s];
+		for(size_t i=0;i<size;i++)		// find width
+		{
+			long j = str[i]!=' ' ? Internal(str[i]) : Internal('!');
+			if(j==-1)	continue;
+			w+= GetWidth(s,j)/fact[s];
+		}
+		ww = w;		w *= -(align&3)/2.f;
+		if(gr)	for(size_t i=0;i<size;i++)		// draw it
+		{
+			long j=0;	//Internal('!');
+			if(str[i]!=' ')
+			{
+				j = Internal(str[i]);
+				if(j==-1)	continue;
+				gr->Glyph(w, -h, 1, (s+(font&MGL_FONT_WIRE))?4:0, j, c1+i*(c2-c1)/(size-1));
+			}
+			w+= GetWidth(s,j)/fact[s];
+		}
+	}
+	return ww;
+}
+//-----------------------------------------------------------------------------
+float mglFont::Width(const wchar_t *str,int font) const
+{
+	if(GetNumGlyph()==0 || !str || *str==0)	return 0;
+	float ww=0,w=0;
+	size_t size = mgl_wcslen(str)+1;
+	if(parse)
+	{
+		unsigned *wcs = new unsigned[size], *buf=wcs;
+		memcpy(wcs,str,size*sizeof(wchar_t));
+		Convert(str, wcs);
+		for(size_t i=0;wcs[i];i++)	if(wcs[i]=='\n')	// parse '\n' symbol
+		{
+			wcs[i]=0;	w = Puts(buf,0,0,1.,0x10|font,'k','k');	// find width
+			buf=wcs+i+1;	if(w>ww)	ww=w;
+		}
+		w = Puts(buf,0,0,1.,0x10|font,'k','k');
+		if(w<ww)	w=ww;
+		delete []wcs;
+	}
+	else
+	{
+		int s = (font/MGL_FONT_BOLD)&3;
+		for(size_t i=0;i<size;i++)
+		{
+			long j = str[i]!=' ' ? Internal(str[i]) : Internal('!');
+			if(j==-1)	continue;
+			w+= GetWidth(s,j)/fact[s];
+		}
+	}
+	return w;
+}
+//-----------------------------------------------------------------------------
+float mglFont::Height(int font) const
+{
+	if(GetNumGlyph()==0)	return 0;
+	int s = (font/MGL_FONT_BOLD)&3;
+	return 660/fact[s];
+}
+//-----------------------------------------------------------------------------
+float mglFont::Height(const char *how) const
+{
+	if(GetNumGlyph()==0)	return 0;
+	int s=0;
+	if(how)
+	{
+		if(strchr(how,'b'))	s = s|1;
+		if(strchr(how,'i'))	s = s|2;
+	}
+	return 660/fact[s];
+}
+//-----------------------------------------------------------------------------
+/// Table of acents and its UTF8 codes
+MGL_NO_EXPORT mglTeXsymb mgl_act_symb[] = {
+	{0x02c6, L"hat"}, {0x02dc, L"tilde"}, {0x02d9, L"dot"}, {0x00a8, L"ddot"}, {0x20db, L"dddot"}, {0x20dc, L"ddddot"}, {0x02ca, L"acute"}, {0x02c7, L"check"}, {0x02cb, L"grave"}, {0x20d7, L"vec"}, {0x02c9, L"bar"}, {0x02d8, L"breve"},
+	/*end*/{0, L"\0"}};
+//-----------------------------------------------------------------------------
+int MGL_LOCAL_PURE mgl_tex_symb_cmp(const void *a, const void *b)
+{
+	const mglTeXsymb *aa = (const mglTeXsymb *)a;
+	const mglTeXsymb *bb = (const mglTeXsymb *)b;
+	return wcscmp(aa->tex, bb->tex);
+}
+//-----------------------------------------------------------------------------
+// parse LaTeX commands (mostly symbols and acents, and some font-style commands)
+unsigned mglFont::Parse(const wchar_t *s) const
+{
+	unsigned res = unsigned(-2);		// Default is no symbol
+	if(!s || !s[0])	return res;
+	mglTeXsymb tst, *rts;
+	tst.tex = s;
+	rts = (mglTeXsymb *) bsearch(&tst, mgl_tex_symb, mgl_tex_num, sizeof(mglTeXsymb), mgl_tex_symb_cmp);
+	if(rts)	return rts->kod;
+
+	for(long k=0;mgl_act_symb[k].kod;k++)	// acents
+		if(!wcscmp(s,mgl_act_symb[k].tex))
+			return mgl_act_symb[k].kod | MGL_FONT_ZEROW;
+	// arbitrary UTF symbol
+	if(s[0]=='u' && s[1]=='t' && s[2]=='f')
+	{	long k = wcstoul(s+3,NULL,16);	return wchar_t(k);	}
+	// font/style changes for next symbol
+	if(!wcscmp(s,L"big"))			res = unsigned(-5);
+	else if(!wcscmp(s,L"frac"))		res = unsigned(-6);
+	else if(!wcscmp(s,L"stack"))	res = unsigned(-7);
+	else if(!wcscmp(s,L"overset"))	res = unsigned(-8);
+	else if(!wcscmp(s,L"underset"))	res = unsigned(-9);
+	else if(!wcscmp(s,L"stackr"))	res = unsigned(-10);
+	else if(!wcscmp(s,L"stackl"))	res = unsigned(-11);
+	else if(!wcscmp(s,L"sub"))		res = unsigned(-12);
+	else if(!wcscmp(s,L"sup"))		res = unsigned(-13);
+	else if(!wcscmp(s,L"textsc"))	res = unsigned(-14);	// new
+	else if(!wcscmp(s,L"dfrac"))	res = unsigned(-15);
+	else if(!wcscmp(s,L"b"))		res = MGL_FONT_BOLD;
+	else if(!wcscmp(s,L"i"))		res = MGL_FONT_ITAL;
+	else if(!wcscmp(s,L"bi"))		res = MGL_FONT_BOLD|MGL_FONT_ITAL;
+	else if(!wcscmp(s,L"r"))		res = unsigned(-1);
+	else if(!wcscmp(s,L"a"))		res = MGL_FONT_OLINE;
+	else if(!wcscmp(s,L"u"))		res = MGL_FONT_ULINE;
+	else if(!wcscmp(s,L"n"))		res = '\n';
+	else if(!wcscmp(s,L"overline"))	res = MGL_FONT_OLINE;
+	else if(!wcscmp(s,L"underline"))res = MGL_FONT_ULINE;
+	else if(!wcscmp(s,L"textbf"))	res = MGL_FONT_BOLD;
+	else if(!wcscmp(s,L"textit"))	res = MGL_FONT_ITAL;
+	else if(!wcscmp(s,L"textrm"))	res = unsigned(-1);
+	else if(!wcscmp(s,L"T2A"))		res = unsigned(-1);
+	else if(!wcscmp(s,L"w"))		res = MGL_FONT_WIRE;
+	else if(!wcscmp(s,L"wire"))		res = MGL_FONT_WIRE;
+	else if(!wcsncmp(s,L"color",5))	res = MGL_COLOR_MASK + (0xff & s[5]);
+	return res;
+}
+//-----------------------------------------------------------------------------
+void mglFont::Convert(const wchar_t *str, unsigned *res) const
+{
+	size_t j=0;
+	wchar_t s[128]=L"";		// TeX command and current char
+	for(size_t i=0;str[i];i++)
+	{
+		wchar_t ch = str[i];
+		if(ch=='\\')	// It can be TeX command
+		{
+			if(wcschr(L"{}_^\\@# ",str[i+1]))	// No, it is usual symbol
+				res[j++] = str[++i];
+			else		// Yes, it is TeX command
+			{
+				size_t i0=i+1, k;
+				for(k=0;isalnum(str[++i]) && k<127;k++)	s[k] = str[i];
+				s[k] = 0;
+				size_t r = Parse(s);
+				if(r==unsigned(-2))			// command not found, so use next symbol itself
+				{	res[j++] = str[i0];	i = i0;	}
+				else if(r)
+				{
+					res[j++] = r;
+					if(str[i]>' ')	i--;
+					if(str[i]==0)	break;
+				}
+			}
+		}
+		else if(ch=='-' && str[i+1]=='-')	{	res[j++] = 0x2212;	i++;	}
+		else if(ch=='\b'){}
+		else if(ch<=' ' && ch!='\n')	res[j++] = ' ';	// no \t at this moment :(
+		else if(ch=='_')	res[j++] = MGL_FONT_LOWER;
+		else if(ch=='^')	res[j++] = MGL_FONT_UPPER;
+		else if(ch=='@')	res[j++] = MGL_FONT_UPPER|MGL_FONT_LOWER;
+		else if(ch=='{')	res[j++] = unsigned(-3);
+		else if(ch=='}')	res[j++] = unsigned(-4);
+		else if(ch=='#' && str[i+1]>' ')
+			res[j++] = MGL_COLOR_MASK + (0xff & str[++i]);	// TODO inline colors -- stack of RGBA colors + index
+		else	res[j++] = ch;				// It is just symbol
+	}
+	res[j] = 0;
+}
+//-----------------------------------------------------------------------------
+float mglFont::get_ptr(long &i,unsigned *str, unsigned **b1, unsigned **b2,float &w1,float &w2, float f1, float f2, int st) const
+{
+	static unsigned s1[2]={0,0}, s2[2]={0,0};
+	i++;
+	if(str[i]==unsigned(-3))
+	{
+		i++;	*b1 = str+i;
+		for(long k=1;k>0 && str[i];i++)
+		{
+			if(str[i]==unsigned(-4))	k--;
+			if(str[i]==unsigned(-3))	k++;
+		}
+		str[i-1]=0;
+	}
+	else	{	s1[0] = str[i];	*b1 = s1;	i++;	}
+	if(str[i]==unsigned(-3))
+	{
+		i++;	*b2 = str+i;
+		for(long k=1;k>0 && str[i];i++)
+		{
+			if(str[i]==unsigned(-4))	k--;
+			if(str[i]==unsigned(-3))	k++;
+		}
+		str[i-1]=0;
+	}
+	else	{	s2[0] = str[i];	*b2 = s2;	i++;	}
+	i--;
+	w1 = Puts(*b1, 0, 0, f1, 0x10|st,'k','k');
+	w2 = Puts(*b2, 0, 0, f2, 0x10|st,'k','k');
+	return w1>w2 ? w1 : w2;
+}
+//-----------------------------------------------------------------------------
+void mglFont::draw_ouline(int st, float x, float y, float f, float g, float ww, float ccol) const
+{
+	if(st&MGL_FONT_OLINE)
+		gr->Glyph(x,y+499*f/g, ww*g, (st&MGL_FONT_WIRE)?12:8, 0, ccol);
+	if(st&MGL_FONT_ULINE)
+		gr->Glyph(x,y-200*f/g, ww*g, (st&MGL_FONT_WIRE)?12:8, 0, ccol);
+}
+//-----------------------------------------------------------------------------
+#define MGL_CLEAR_STYLE {st = style;	yy = y;	ff = f;	ccol=c1+dc*i;	a = (st/MGL_FONT_BOLD)&3;}
+float mglFont::Puts(const unsigned *text, float x,float y,float f,int style,float c1,float c2) const
+{
+	if(GetNumGlyph()==0)	return 0;
+	float w=0;				// string width
+	int st = style;			// current style
+	unsigned *b1, *b2;		// pointer to substring
+	unsigned *str;			// string itself
+	float yy=y, ff=f, ww, w1, w2;
+	int a = (st/MGL_FONT_BOLD)&3;
+	long i;
+	for(i=0;text[i];i++);
+	float dc=i>1?(c2-c1)/(i-1):0;
+	str = new unsigned[i+1];
+	memcpy(str,text,(i+1)*sizeof(unsigned));
+
+	float ccol = 0;
+	for(long i=0;str[i];i++)
+	{
+		ccol = ccol<0?ccol:c1+dc*i;
+		unsigned s = str[i];		ww = 0;
+		if(s==unsigned(-3))	// recursion call here
+		{
+			i++;	b1 = str+i;
+			for(long k=1;k>0 && str[i];i++)
+			{
+				if(str[i]==unsigned(-4))	k--;
+				if(str[i]==unsigned(-3))	k++;
+			}
+			str[i-1]=0;	i--;
+			ww = Puts(b1, x, yy, ff, (st&(~MGL_FONT_OLINE)&(~MGL_FONT_ULINE)), ccol,ccol);
+			if(gr && !(style&0x10))	// add under-/over- line now
+				draw_ouline(st,x,y,f,fact[a],ww,ccol);
+			MGL_CLEAR_STYLE
+		}
+		else if(s=='\n')	// newline
+		{
+			ww = get_ptr(i, str, &b1, &b2, w1, w2, ff, ff, st);
+			Puts(b1, x+(ww-w1)/2, yy, ff, (st&(~MGL_FONT_OLINE)&(~MGL_FONT_ULINE)), ccol,ccol);
+			Puts(b2, x+(ww-w2)/2, yy-660*ff/fact[a], ff, (st&(~MGL_FONT_OLINE)&(~MGL_FONT_ULINE)), ccol,ccol);
+			MGL_CLEAR_STYLE
+		}
+		else if(s==unsigned(-9))	// underset
+		{
+			ww = get_ptr(i, str, &b1, &b2, w1, w2, ff, ff/4, st);
+			Puts(b1, x+(ww-w1)/2, yy, ff, (st&(~MGL_FONT_OLINE)&(~MGL_FONT_ULINE)), ccol,ccol);
+			Puts(b2, x+(ww-w2)/2, yy-150*ff/fact[a], ff/4, (st&(~MGL_FONT_OLINE)&(~MGL_FONT_ULINE)), ccol,ccol);
+			if(gr && !(style&0x10))	// add under-/over- line now
+				draw_ouline(st,x,y,f,fact[a],ww,ccol);
+			MGL_CLEAR_STYLE
+		}
+		else if(s==unsigned(-8))	// overset
+		{
+			ww = get_ptr(i, str, &b1, &b2, w1, w2, ff, ff/4, st);
+			Puts(b1, x+(ww-w1)/2, yy, ff, (st&(~MGL_FONT_OLINE)&(~MGL_FONT_ULINE)), ccol,ccol);
+			Puts(b2, x+(ww-w2)/2, yy+375*ff/fact[a], ff/4, (st&(~MGL_FONT_OLINE)&(~MGL_FONT_ULINE)), ccol,ccol);
+			if(gr && !(style&0x10))	// add under-/over- line now
+				draw_ouline(st,x,y,f,fact[a],ww,ccol);
+			MGL_CLEAR_STYLE
+		}
+		else if(s==unsigned(-12))	// sub
+		{
+			ww = get_ptr(i, str, &b1, &b2, w1, w2, ff, ff/4, st);
+			Puts(b1, x+(ww-w1)/2, yy, ff, (st&(~MGL_FONT_OLINE)&(~MGL_FONT_ULINE)), ccol,ccol);
+			Puts(b2, x+(ww-w2)/2, yy-250*ff/fact[a], ff/4, (st&(~MGL_FONT_OLINE)&(~MGL_FONT_ULINE)), ccol,ccol);
+			if(gr && !(style&0x10))	// add under-/over- line now
+				draw_ouline(st,x,y,f,fact[a],ww,ccol);
+			MGL_CLEAR_STYLE
+		}
+		else if(s==unsigned(-13))	// sup
+		{
+			ww = get_ptr(i, str, &b1, &b2, w1, w2, ff, ff/4, st);
+			Puts(b1, x+(ww-w1)/2, yy, ff, (st&(~MGL_FONT_OLINE)&(~MGL_FONT_ULINE)), ccol,ccol);
+			Puts(b2, x+(ww-w2)/2, yy+450*ff/fact[a], ff/4, (st&(~MGL_FONT_OLINE)&(~MGL_FONT_ULINE)), ccol,ccol);
+			if(gr && !(style&0x10))	// add under-/over- line now
+				draw_ouline(st,x,y,f,fact[a],ww,ccol);
+			MGL_CLEAR_STYLE
+		}
+		else if(s==unsigned(-11))	// stackl
+		{
+			ww = get_ptr(i, str, &b1, &b2, w1, w2, ff*0.45, ff*0.45, st);
+			Puts(b1, x, yy+250*ff/fact[a], ff*0.45, (st&(~MGL_FONT_OLINE)&(~MGL_FONT_ULINE)), ccol,ccol);
+			Puts(b2, x, yy-110*ff/fact[a], ff*0.45, (st&(~MGL_FONT_OLINE)&(~MGL_FONT_ULINE)), ccol,ccol);
+			if(gr && !(style&0x10))	// add under-/over- line now
+				draw_ouline(st,x,y,f,fact[a],ww,ccol);
+			MGL_CLEAR_STYLE
+		}
+		else if(s==unsigned(-10))	// stacr
+		{
+			ww = get_ptr(i, str, &b1, &b2, w1, w2, ff*0.45, ff*0.45, st);
+			Puts(b1, x+(ww-w1), yy+250*ff/fact[a], ff*0.45, (st&(~MGL_FONT_OLINE)&(~MGL_FONT_ULINE)), ccol,ccol);
+			Puts(b2, x+(ww-w2), yy-110*ff/fact[a], ff*0.45, (st&(~MGL_FONT_OLINE)&(~MGL_FONT_ULINE)), ccol,ccol);
+			if(gr && !(style&0x10))	// add under-/over- line now
+				draw_ouline(st,x,y,f,fact[a],ww,ccol);
+			MGL_CLEAR_STYLE
+		}
+		else if(s==unsigned(-7))	// stack
+		{
+			ww = get_ptr(i, str, &b1, &b2, w1, w2, ff*0.45, ff*0.45, st);
+			Puts(b1, x+(ww-w1)/2, yy+250*ff/fact[a], ff*0.45, (st&(~MGL_FONT_OLINE)&(~MGL_FONT_ULINE)), ccol,ccol);
+			Puts(b2, x+(ww-w2)/2, yy-110*ff/fact[a], ff*0.45, (st&(~MGL_FONT_OLINE)&(~MGL_FONT_ULINE)), ccol,ccol);
+			if(gr && !(style&0x10))	// add under-/over- line now
+				draw_ouline(st,x,y,f,fact[a],ww,ccol);
+			MGL_CLEAR_STYLE
+		}
+		else if(s==unsigned(-6))	// frac
+		{
+			ww = get_ptr(i, str, &b1, &b2, w1, w2, ff*0.45, ff*0.45, st);
+			Puts(b1, x+(ww-w1)/2, yy+250*ff/fact[a], ff*0.45, (st&(~MGL_FONT_OLINE)&(~MGL_FONT_ULINE)), ccol,ccol);
+			Puts(b2, x+(ww-w2)/2, yy-60*ff/fact[a], ff*0.45, (st&(~MGL_FONT_OLINE)&(~MGL_FONT_ULINE)), ccol,ccol);
+			if(gr && !(style&0x10))	// add under-/over- line now
+			{
+				draw_ouline(st,x,y,f,fact[a],ww,ccol);
+				gr->Glyph(x,y+150*f/fact[a], ww*fact[a], (st&MGL_FONT_WIRE)?12:8, 0, ccol);
+			}
+			MGL_CLEAR_STYLE
+		}
+		else if(s==unsigned(-15))	// dfrac
+		{
+			ww = get_ptr(i, str, &b1, &b2, w1, w2, ff, ff, st);
+			Puts(b1, x+(ww-w1)/2, yy+315*ff/fact[a], ff, (st&(~MGL_FONT_OLINE)&(~MGL_FONT_ULINE)), ccol,ccol);
+			Puts(b2, x+(ww-w2)/2, yy-405*ff/fact[a], ff, (st&(~MGL_FONT_OLINE)&(~MGL_FONT_ULINE)), ccol,ccol);
+			if(gr && !(style&0x10))	// add under-/over- line now
+			{
+				draw_ouline(st,x,y,f,fact[a],ww,ccol);
+				gr->Glyph(x,y+150*f/fact[a], ww*fact[a], (st&MGL_FONT_WIRE)?12:8, 0, ccol);
+			}
+			MGL_CLEAR_STYLE
+		}
+		else if(s==unsigned(-4))	MGL_CLEAR_STYLE	// should be never here but if I miss sth ...
+		else if(s==unsigned(-14))	// script symbols
+		{
+			long k=1;
+			if(str[i+1]==unsigned(-3))	for(long j=i+2;k>0 && str[j];j++)
+			{
+				if(str[j]==unsigned(-3))	k++;
+				if(str[j]==unsigned(-4))	k--;
+				if(iswlower(str[j]))
+					str[j] = MGL_FONT_UPPER|MGL_FONT_LOWER|towupper(str[j]);
+			}
+		}
+		else if(s==unsigned(-5))	// large symbol
+			ff *= 1.5;
+		else if(s==unsigned(-1))	// set normal font
+			st = style & MGL_FONT_ROMAN;
+		else if((s&MGL_COLOR_MASK)==MGL_COLOR_MASK)	// color specification
+			ccol = -float(s & 0xff);	// TODO inline colors -- make textures
+		else
+		{
+			unsigned ss = s&MGL_FONT_MASK;
+			if(ss)	// draw symbol (glyph)
+			{
+				long j = Internal('!');
+				float dx=0;
+				if(ss>' ')
+				{
+					j = Internal(ss);
+					if(j==-1)	continue;
+					if(s & MGL_FONT_ZEROW)
+					{
+						long j=1;
+						yy += 100*ff/fact[a];
+						while(str[i+j]>=unsigned(-15))	j++;
+						unsigned sn = str[i+j];
+						if(sn<unsigned(-15) && (sn&MGL_FONT_MASK)>' ')	// specially center
+						{
+							dx = 0.75*ff*(GetWidth(a,Internal(sn&MGL_FONT_MASK))-GetWidth(a,j))/fact[a];
+							if(dx<0)	dx=0;
+						}
+					}
+					if(gr && !(style&0x10))
+					{
+						if(st & MGL_FONT_WIRE)	gr->Glyph(x+dx,yy,ff,a+4,j,ccol);
+						else					gr->Glyph(x+dx,yy,ff,a,j,ccol);
+					}
+				}
+				ww = ff*GetWidth(a,j)/fact[a];
+				if(gr && !(style&0x10))	// add under-/over- line now
+					draw_ouline(st,x,y,f,fact[a],ww,ccol);
+				if(s & MGL_FONT_ZEROW)	ww = 0;
+				MGL_CLEAR_STYLE
+			}
+			// apply new styles
+			if(s/MGL_FONT_BOLD)	st = st | (s & MGL_FONT_STYLE);
+			a = (st/MGL_FONT_BOLD)&3;
+			ss = (s/MGL_FONT_UPPER)%4;
+			if(ss)
+			{
+				if(ss==1)		{	ff *=0.6;	yy += 200*ff/fact[a];	}	// =  500*0.4
+				else if(ss==2)	{	ff *=0.6;	yy -=  80*ff/fact[a];	}	// = -500*0.16
+				else if(ss==3)	{	ff *=0.8;	yy +=  0*60*ff/fact[a];	}	// =  500*0.12
+			}
+		}
+		x += ww;	w += ww;
+	}
+	delete []str;
+	return w;
+}
+//-----------------------------------------------------------------------------
+// copy normal style as default for other styles
+void mglFont::main_copy()
+{
+#pragma omp parallel for
+	for(long i=0;i<long(glyphs.size());i++)
+	{
+		mglGlyphDescr &g = glyphs[i];
+		g.numl[1] = g.numl[2] = g.numl[3] = g.numl[0];
+		g.numt[1] = g.numt[2] = g.numt[3] = g.numt[0];
+		g.ln[1] = g.ln[2] = g.ln[3] = g.ln[0];
+		g.tr[1] = g.tr[2] = g.tr[3] = g.tr[0];
+		g.width[1] = g.width[2] = g.width[3] = g.width[0];
+	}
+}
+//-----------------------------------------------------------------------------
+bool mglFont::read_def()
+{
+	// copy default factor for other font styles;
+	fact[1] = fact[2] = fact[3] = fact[0] = mgl_fact*mgl_fgen;
+	Buf = new short[mgl_cur];	// prealocate buffer
+	memset(Buf,0,mgl_cur*sizeof(short));
+	// now allocate memory for all fonts
+	mem_alloc(mgl_numg);
+	// and load symbols itself
+#ifndef WIN32	// win32 don't initialized threads before main()
+#pragma omp parallel for
+#endif
+	for(size_t i=0;i<mgl_numg;i++)
+	{
+		mglGlyphDescr &g = glyphs[i];
+		g.id = mgl_gen_fnt[i][0];
+		g.width[0] = g.width[1] = g.width[2] = g.width[3] = mgl_gen_fnt[i][1];
+		g.numl[0] = g.numl[1] = g.numl[2] = g.numl[3] = mgl_gen_fnt[i][2];
+		g.ln[0] = g.ln[1] = g.ln[2] = g.ln[3] = mgl_gen_fnt[i][3];
+		g.numt[0] = g.numt[1] = g.numt[2] = g.numt[3] = mgl_gen_fnt[i][4];
+		g.tr[0] = g.tr[1] = g.tr[2] = g.tr[3] = mgl_gen_fnt[i][5];
+	}
+	memcpy(Buf, mgl_buf_fnt, mgl_cur*sizeof(short));
+	numb = mgl_cur;
+	return true;
+}
+//-----------------------------------------------------------------------------
+bool mglFont::read_data(const char *fname, int s, std::vector<short> &buf, std::vector<mglGlyphDescr> &extra)
+{
+	gzFile fp;
+	char str[256];
+	int n, tmpw, tmpnl, tmpnt, retVal;
+	unsigned ss, tmpi, tmppl, tmppt;
+	fp = gzopen(fname,"r");	if(!fp)	return false;	// false if no file
+	// first string is comment (not used), second string have information
+	if(!gzgets(fp,str,256) || strncmp(str,"# font",6) || !gzgets(fp,str,256))
+	{	gzclose(fp);	return false;	}
+	retVal = sscanf(str, "%d%f%u", &n, fact+s, &ss);
+	//Check sscanf read all data  (3 items)
+	if(retVal != 3)	{	gzclose(fp);	return false;	}
+
+	for(int i=0;i<n;i++)
+	{
+		gzgets(fp,str,256);
+		retVal = sscanf(str,"%u%d%d%u%d%u", &tmpi, &tmpw, &tmpnl, &tmppl, &tmpnt, &tmppt);
+		if(retVal != 6)	{	gzclose(fp);	buf.clear();	return false;	}
+		long j=Internal(unsigned(tmpi));
+		if(j>=0)	// known symbol
+		{
+			mglGlyphDescr &g = glyphs[j];	g.width[s] = tmpw;
+			g.ln[s] = -1-tmppl;		g.tr[s] = -1-tmppt;
+			g.numl[s] = tmpnl;		g.numt[s] = tmpnt;
+		}
+		else
+		{
+			mglGlyphDescr g;	g.id = tmpi;
+			g.width[0] = g.width[1] = g.width[2] = g.width[3] = tmpw;
+			g.numl[0] = g.numl[1] = g.numl[2] = g.numl[3] = tmpnl;
+			g.ln[0] = g.ln[1] = g.ln[2] = g.ln[3] = -1-tmppl;
+			g.numt[0] = g.numt[1] = g.numt[2] = g.numt[3] = tmpnt;
+			g.tr[0] = g.tr[1] = g.tr[2] = g.tr[3] = -1-tmppt;
+#pragma omp critical
+			extra.push_back(g);
+		}
+	}
+	for(unsigned i=0;i<ss;i++)
+	{
+		for(int j=0;j<256;j++)	if((str[j] = gzgetc(fp))<=' ')	break;
+		buf.push_back(atoi(str));
+	}
+	gzclose(fp);		// finish wire normal font
+	return true;
+}
+//-----------------------------------------------------------------------------
+bool mglFont::read_main(const char *fname, std::vector<short> &buf)
+{
+	gzFile fp;
+	int tmpi, tmpw, tmpnl, tmpnt;
+	unsigned s, tmppl, tmppt,numg;
+	char str[256];
+
+	fp = gzopen(fname,"r");	if(!fp)	return false;	// this font must be in any case
+	// first string is comment (not used), second string have information
+	if(!gzgets(fp,str,256) || strncmp(str,"# font",6) || !gzgets(fp,str,256))
+	{	gzclose(fp);	return false;	}
+	sscanf(str, "%u%f%u", &numg, fact, &s);
+	fact[1] = fact[2] = fact[3] = fact[0];	// copy default factor for other font styles;
+	// now allocate memory for all fonts
+	mem_alloc(numg);
+	// and load symbols itself
+	for(size_t i=0;i<numg;i++)
+	{
+		gzgets(fp,str,256);
+		sscanf(str,"%d%d%d%u%d%u", &tmpi, &tmpw, &tmpnl, &tmppl, &tmpnt, &tmppt);
+		mglGlyphDescr &g = glyphs[i];	g.id = tmpi;
+		g.width[0] = g.width[1] = g.width[2] = g.width[3] = tmpw;
+		g.numl[0] = g.numl[1] = g.numl[2] = g.numl[3] = tmpnl;
+		g.ln[0] = g.ln[1] = g.ln[2] = g.ln[3] = tmppl;
+		g.numt[0] = g.numt[1] = g.numt[2] = g.numt[3] = tmpnt;
+		g.tr[0] = g.tr[1] = g.tr[2] = g.tr[3] = tmppt;
+	}
+	for(unsigned i=0;i<s;i++)
+	{
+		for(int j=0;j<256;j++)	if((str[j] = gzgetc(fp))<=' ')	break;
+		buf.push_back(atoi(str));
+	}
+	gzclose(fp);	// finish wire normal font
+	return true;
+}
+//-----------------------------------------------------------------------------
+size_t mglFont::SaveBin(const char *fname)
+{
+	FILE *fp = fopen(fname,"wb");
+	if(!fp)	return 0;
+	size_t sum=0;
+	fwrite(&numb,sizeof(size_t),1,fp);	sum += sizeof(size_t);
+	fwrite(fact,sizeof(float),4,fp);	sum += sizeof(float)*4;
+	fwrite(Buf,sizeof(short),numb,fp);	sum += sizeof(short)*numb;
+	size_t len = glyphs.size();
+	fwrite(&len,sizeof(size_t),1,fp);	sum += sizeof(long);
+	fwrite(&(glyphs[0]),sizeof(mglGlyphDescr),len,fp);	sum += sizeof(mglGlyphDescr)*len;
+	fclose(fp);	return sum;
+}
+//-----------------------------------------------------------------------------
+bool mglFont::LoadBin(const char *base, const char *path)
+{
+	Clear();	// first clear old
+	if(!path)	path = MGL_FONT_PATH;
+	char str[256], sep='/';
+	snprintf(str,256,"%s%c%s.vfmb",path,sep,base?base:"");	str[255]=0;
+	FILE *fp = fopen(str,"rb");		if(!fp)	return false;
+	size_t s, len;
+	bool res = true;
+	s = fread(&numb,sizeof(size_t),1,fp);
+	if(s<1)	res = false;
+	s = fread(fact,sizeof(float),4,fp);
+	if(s<4)	res = false;
+	Buf = new short[numb];
+	s = fread(Buf,sizeof(short),numb,fp);
+	if(s<numb)	res = false;
+	s = fread(&len,sizeof(size_t),1,fp);
+	if(s<1)	res = false;
+	if(res)
+	{
+		glyphs.clear();	glyphs.resize(len);
+		s = fread(&(glyphs[0]),sizeof(mglGlyphDescr),len,fp);
+		if(s<len)	res = false;
+	}
+//	if(!res)	Clear();
+	fclose(fp);		return res;
+}
+//-----------------------------------------------------------------------------
+bool mglFont::Load(const char *base, const char *path)
+{
+//	base = 0;
+	char *buf=0,sep='/';
+#ifdef WIN32
+	sep='\\';
+#endif
+	char str[256];
+	std::string loc = setlocale(LC_NUMERIC,"C");
+	if(!path)	path = MGL_FONT_PATH;
+	if(base && *base)
+	{
+		buf = new char[strlen(base)+1];
+		strcpy(buf,base);
+		if(strchr(buf,sep))
+		{
+			int i;
+			for(i=strlen(buf);i>=0 && buf[i]!=sep;i--);
+			path = buf;		buf[i]=0;	base = buf+i+1;
+		}
+		if(LoadBin(base,path))
+		{	delete []buf;	return true;	}
+	}
+	Clear();	// first clear old
+
+	snprintf(str,256,"%s%c%s.vfm",path,sep,base?base:"");	str[255]=0;
+	std::vector<short> norm, bold, ital, both;
+	if(!(base && *base) || !read_main(str,norm))
+	{
+		read_def();	setlocale(LC_NUMERIC,loc.c_str());
+		if(buf)	delete []buf;
+		return true;
+	}
+	fact[1] = fact[2] = fact[3] = fact[0];
+
+	std::vector<mglGlyphDescr> ex_b,ex_i,ex_bi;
+#pragma omp parallel sections
+	{
+		//================== bold ===========================================
+#pragma omp section
+		{	char str[256];	snprintf(str,256,"%s%c%s_b.vfm",path,sep,base);	// this file may absent
+			str[255]=0;	read_data(str, 1, bold, ex_b);	}
+
+		//================== italic =========================================
+#pragma omp section
+		{	char str[256];	snprintf(str,256,"%s%c%s_i.vfm",path,sep,base);
+			str[255]=0;	read_data(str, 2, ital, ex_i);	}
+
+		//================== bold-italic ====================================
+#pragma omp section
+		{	char str[256];	snprintf(str,256,"%s%c%s_bi.vfm",path,sep,base);
+			str[255]=0;	read_data(str, 3, both, ex_bi);	}
+	}
+
+	// now collect data
+	numb = norm.size()+bold.size()+ital.size()+both.size();
+	Buf = new short[numb];
+	memcpy(Buf,&norm[0],norm.size()*sizeof(short));
+	long cur = norm.size(), len = long(bold.size());
+	if(bold.size()>0)
+		memcpy(Buf+cur,&bold[0],bold.size()*sizeof(short));
+#pragma omp parallel for
+	for(long i=0;i<long(GetNumGlyph());i++)	if(glyphs[i].ln[1]<0)
+	{	glyphs[i].ln[1] = cur-1-glyphs[i].ln[1];	glyphs[i].tr[1] = cur-1-glyphs[i].tr[1];	}
+#pragma omp parallel for
+	for(long i=0;i<long(ex_b.size());i++)	if(ex_b[i].ln[1]<0)
+	{
+		mglGlyphDescr &g = ex_b[i];
+		g.ln[0] = g.ln[1] = g.ln[2] = g.ln[3] = cur-1-g.ln[1];
+		g.tr[0] = g.tr[1] = g.tr[2] = g.tr[3] = cur-1-g.tr[1];
+	}
+	cur += len;		len = long(ital.size());
+	if(ital.size()>0)
+		memcpy(Buf+cur,&ital[0],ital.size()*sizeof(short));
+#pragma omp parallel for
+	for(long i=0;i<long(GetNumGlyph());i++)	if(glyphs[i].ln[2]<0)
+	{	glyphs[i].ln[2] = cur-1-glyphs[i].ln[2];	glyphs[i].tr[2] = cur-1-glyphs[i].tr[2];	}
+#pragma omp parallel for
+	for(long i=0;i<long(ex_i.size());i++)	if(ex_i[i].ln[2]<0)
+	{
+		mglGlyphDescr &g = ex_i[i];
+		g.ln[0] = g.ln[1] = g.ln[2] = g.ln[3] = cur-1-g.ln[2];
+		g.tr[0] = g.tr[1] = g.tr[2] = g.tr[3] = cur-1-g.tr[2];
+	}
+	cur += len;
+	if(both.size()>0)
+		memcpy(Buf+cur,&both[0],both.size()*sizeof(short));
+#pragma omp parallel for
+	for(long i=0;i<long(GetNumGlyph());i++)	if(glyphs[i].ln[3]<0)
+	{	glyphs[i].ln[3] = cur-1-glyphs[i].ln[3];	glyphs[i].tr[3] = cur-1-glyphs[i].tr[3];	}
+#pragma omp parallel for
+	for(long i=0;i<long(ex_bi.size());i++)	if(ex_bi[i].ln[3]<0)
+	{
+		mglGlyphDescr &g = ex_bi[i];
+		g.ln[0] = g.ln[1] = g.ln[2] = g.ln[3] = cur-1-g.ln[3];
+		g.tr[0] = g.tr[1] = g.tr[2] = g.tr[3] = cur-1-g.tr[3];
+	}
+	// now add missing symbols
+	if(ex_b.size()==0)	ex_b = ex_i;
+	else
+	{
+		for(size_t i=0;i<ex_i.size();i++)	// add from ex_i
+		{
+			long j = mgl_internal_code(ex_i[i].id, ex_b);
+			if(j>=0)	// known symbol
+			{
+				mglGlyphDescr &g = ex_b[j], &f = ex_i[i];
+				g.width[2] = f.width[2];
+				g.ln[2] = f.ln[2];		g.tr[2] = f.tr[2];
+				g.numl[2] = f.numl[2];	g.numt[2] = f.numt[2];
+			}
+			else	ex_b.push_back(ex_i[i]);
+		}
+		std::sort(ex_b.begin(),ex_b.end());
+	}
+	if(ex_b.size()==0)	ex_b = ex_bi;
+	else
+	{
+		for(size_t i=0;i<ex_bi.size();i++)	// add from ex_bi
+		{
+			long j = mgl_internal_code(ex_bi[i].id, ex_b);
+			if(j>=0)	// known symbol
+			{
+				mglGlyphDescr &g = ex_b[j], &f = ex_bi[i];
+				g.width[2] = f.width[3];
+				g.ln[2] = f.ln[3];		g.tr[2] = f.tr[3];
+				g.numl[2] = f.numl[3];	g.numt[2] = f.numt[3];
+			}
+			else	ex_b.push_back(ex_bi[i]);
+		}
+		std::sort(ex_b.begin(),ex_b.end());
+	}
+	if(ex_b.size()>0)
+	{
+		glyphs.reserve(ex_b.size());	// preallocate memory
+		glyphs.insert(glyphs.end(), ex_b.begin(), ex_b.end());
+		std::sort(glyphs.begin(),glyphs.end());
+	}
+
+	// Finally normalize all factors
+	fact[0] *= mgl_fgen;	fact[1] *= mgl_fgen;
+	fact[2] *= mgl_fgen;	fact[3] *= mgl_fgen;
+	setlocale(LC_NUMERIC,loc.c_str());
+	if(buf)	delete []buf;
+	return true;
+}
+//-----------------------------------------------------------------------------
+#if MGL_HAVE_PTHREAD
+pthread_mutex_t mutexRnd;
+#endif
+//-----------------------------------------------------------------------------
+float mgl_cos[360];
+void MGL_NO_EXPORT mgl_init()
+{
+	mgl_textdomain(NULL,"");
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_init(&mutexRnd,0);
+#endif
+#ifndef WIN32	// win32 don't initialized threads before main()
+#pragma omp parallel for
+#endif
+	for(long i=0;i<360;i++)	mgl_cos[i] = cos(i*M_PI/180.);
+}
+//-----------------------------------------------------------------------------
+mglFont::mglFont(const char *name, const char *path)
+{
+	parse = true;	gr=0;	Buf=0;
+//	if(this==&mglDefFont)	Load(name, path);	else	Copy(&mglDefFont);
+	if(name && *name)	Load(name, path);
+	else if(this!=&mglDefFont)	Copy(&mglDefFont);
+	else
+	{
+		mgl_init();		// NOTE: this call init function for the library.
+		Load(MGL_DEF_FONT_NAME,0);
+	}
+}
+mglFont::~mglFont()	{	if(Buf)	delete []Buf;	}
+void mglFont::Restore()	{	Copy(&mglDefFont);	}
+//-----------------------------------------------------------------------------
+void mglFont::Clear()
+{
+//#pragma omp critical(font)
+	{	if(Buf)	delete []Buf;	Buf=0;	glyphs.clear();	}
+}
+//-----------------------------------------------------------------------------
+void mglFont::Copy(mglFont *f)
+{
+	if(!f || f==this)	return;
+#pragma omp critical(font)
+	{	if(Buf)	delete []Buf;	Buf=0;	}
+	// copy scale factors
+	memcpy(fact,f->fact,4*sizeof(float));
+	// copy symbols descriptions
+	numb = f->numb;	Buf = new short[numb];	memcpy(Buf, f->Buf, numb*sizeof(short));
+	// copy symbol parameters
+	glyphs.resize(f->glyphs.size());
+	memcpy(&glyphs[0],&(f->glyphs)[0],glyphs.size()*sizeof(mglGlyphDescr));
+}
+//-----------------------------------------------------------------------------
+long MGL_EXPORT mgl_check_tex_table()
+{
+	size_t i=0;	while(mgl_tex_symb[i].tex[0])	i++;
+	long res = 0;
+	if(mgl_tex_num!=i)
+	{	printf("real=%zu, set=%zu\n",i,mgl_tex_num);	res = -1;	}
+	for(i=0;mgl_tex_symb[i].tex[0];i++)
+	{
+		mglTeXsymb tst, *rts;	tst.tex = mgl_tex_symb[i].tex;
+		rts = (mglTeXsymb *) bsearch(&tst, mgl_tex_symb, mgl_tex_num, sizeof(mglTeXsymb), mgl_tex_symb_cmp);
+		if(!rts)
+		{	printf(_("Bad '%ls' at %zu\n"),mgl_tex_symb[i].tex,i);	res = 1+i;	}
+	}
+	return res;
+}
+//---------------------------------------------------------------------------
+bool MGL_NO_EXPORT test_transl(const char *p)
+{
+#if MGL_USE_GETTEXT
+	std::string f = std::string(p) + "/ru/LC_MESSAGES/mathgl.mo";
+	FILE *fp = fopen(f.c_str(),"r");
+	if(fp)
+	{
+		bindtextdomain("mathgl", p);
+		textdomain("mathgl");
+		fclose(fp);	return true;
+	}
+#endif
+	return false;
+}
+void MGL_EXPORT mgl_textdomain(const char *argv0, const char *loc)
+{
+	static const char *argv=NULL;
+	if(!argv0)	argv0=argv;	else	argv=argv0;
+	setlocale(LC_ALL, loc);	setlocale(LC_NUMERIC, "C");
+#if MGL_USE_GETTEXT
+	if(!test_transl(MGL_INSTALL_DIR"/share/locale/"))
+		if(!test_transl("/usr/share/locale/"))
+			if(!test_transl("/usr/local/share/locale/"))
+				if(!test_transl(getcwd(NULL,0)))
+				{
+					const char *f = argv0?strrchr(argv0,'/'):NULL;
+#ifdef WIN32
+					if(!f)	f = argv0?strrchr(argv0,'\\'):NULL;
+#endif
+					if(f)
+					{
+						std::string p(argv0,f-argv0);
+						if(!test_transl(p.c_str()))
+							return;
+					}
+					else	return;
+				}
+#endif
+}
+void MGL_EXPORT mgl_textdomain_(const char *locale, int l)
+{	char *s=new char[l+1];	memcpy(s,locale,l);	s[l]=0;
+	mgl_textdomain(NULL,s);	delete []s;	}
+//---------------------------------------------------------------------------
diff --git a/src/fractal.cpp b/src/fractal.cpp
new file mode 100644
index 0000000..22e4c3e
--- /dev/null
+++ b/src/fractal.cpp
@@ -0,0 +1,860 @@
+/***************************************************************************
+ * fractal.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include "mgl2/other.h"
+#include "mgl2/data.h"
+MGL_NO_EXPORT char *mgl_read_gz(gzFile fp);
+//-----------------------------------------------------------------------------
+//
+//	IFS series
+//
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_ifs_2d_point(HCDT A, mreal& x, mreal& y, mreal amax)
+{
+	long i, n=A->GetNy();
+	mreal r = amax*mgl_rnd(), sum_prob = 0, x1;
+	for(i=0;i<n;i++)
+	{
+		sum_prob += A->v(6,i);
+		if(r<sum_prob)	break;
+	}
+	x1= A->v(0,i)*x + A->v(1,i)*y + A->v(4,i);
+	y = A->v(2,i)*x + A->v(3,i)*y + A->v(5,i);	x = x1;
+}
+HMDT MGL_EXPORT mgl_data_ifs_2d(HCDT A, long n, long skip)
+{
+	if(!A || A->GetNx()<7 || n<1)	return 0;	// incompatible dimensions
+	mreal amax=0;
+	for(long i=0; i<A->GetNy(); i++)	amax += A->v(6,i);
+	if(amax<=0)	return 0;
+
+	mglData *f = new mglData(2,n);
+	mreal x = 0, y = 0;
+	for(long i=0; i<skip; i++)	mgl_ifs_2d_point(A, x, y,amax);
+	for(long i=0; i<n; i++)
+	{
+		mgl_ifs_2d_point(A, x, y, amax);
+		f->a[2*i] = x;	f->a[2*i+1] = y;
+	}
+	return f;
+}
+uintptr_t MGL_EXPORT mgl_data_ifs_2d_(uintptr_t *d, long *n, long *skip)
+{	return uintptr_t(mgl_data_ifs_2d(_DT_,*n,*skip));	}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_ifs_3d_point(HCDT A, mreal& x, mreal& y, mreal& z, mreal amax)
+{
+	int i, n=A->GetNy();
+	mreal r = amax*mgl_rnd(), sum_prob = 0, x1, y1;
+	for (i=0; i<n; i++)
+	{
+		sum_prob += A->v(12,i);
+		if(r<sum_prob)  break;
+	}
+	x1= A->v(0,i)*x + A->v(1,i)*y + A->v(2,i)*z + A->v(9,i);
+	y1= A->v(3,i)*x + A->v(4,i)*y + A->v(5,i)*z + A->v(10,i);
+	z = A->v(6,i)*x + A->v(7,i)*y + A->v(8,i)*z + A->v(11,i);
+	x = x1;	y = y1;
+}
+HMDT MGL_EXPORT mgl_data_ifs_3d(HCDT A, long n, long skip)
+{
+	if(!A || A->GetNx()<13 || n<1)	return 0;   // incompatible dimensions
+	mreal amax = 0;
+	for(int i=0; i<A->GetNy(); i++)	amax += A->v(12,i);
+	if(amax <= 0) return 0;
+
+	mglData *f = new mglData(3,n);
+	mreal x = 0, y = 0, z = 0;
+	for(long i=0; i<skip; i++)	mgl_ifs_3d_point(A, x, y, z, amax);
+	for(long i=0; i<n; i++)
+	{
+		mgl_ifs_3d_point(A, x, y, z, amax);
+		f->a[3*i] = x;	f->a[3*i+1] = y;	f->a[3*i+2] = z;
+	}
+	return f;
+}
+uintptr_t MGL_EXPORT mgl_data_ifs_3d_(uintptr_t *d, long *n, long *skip)
+{   return uintptr_t(mgl_data_ifs_3d(_DT_,*n,*skip));   }
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_data_ifs_file(const char *fname, const char *name, long n, long skip)
+{
+	gzFile fp = gzopen(fname,"r");
+	if(!fp)	return 0;		// Couldn't open file file
+	char *buf = mgl_read_gz(fp);	gzclose(fp);
+	char *s = strstr(buf,name);
+	if(!s)	return 0;		// No data for fractal 'name' in the file
+
+	char *p = strchr(s,'{'), *e;
+	if(!p)	return 0;		// Wrong data format for fractal 'name' in the file
+	bool ext3d = false;
+	e = strstr(s,"(3D)");	if(e && e<p)	ext3d = true;
+	e = strstr(s,"(3d)");	if(e && e<p)	ext3d = true;
+	e = strchr(p,'}');
+
+	std::vector<mreal> nums;
+	for(size_t i=0;p[i] && p+i<e;i++)
+	{
+		while(p[i]<=' ')	i++;
+		if(p[i]==';' || p[i]=='#')	while(p[i] && p[i]!='\n')	i++;
+		if(strchr("0123456789.+-",p[i]))	// this is number
+		{
+			nums.push_back(atof(p+i));
+			while(p[i]>' ')	i++;
+		}
+	}
+	HMDT dat = new mglData, res;
+	if(ext3d)
+	{
+		dat->Set(&(nums[0]), 13, nums.size()/13, 1);
+		res = mgl_data_ifs_3d(dat, n, skip);
+	}
+	else
+	{
+		dat->Set(&(nums[0]), 7, nums.size()/7, 1);
+		res = mgl_data_ifs_2d(dat, n, skip);
+	}
+	delete dat;	free(buf);	return res;
+}
+uintptr_t mgl_data_ifs_file_(const char *fname, const char *name, long *n, long *skip,int l,int m)
+{	char *s=new char[l+1];		memcpy(s,fname,l);	s[l]=0;
+	char *t=new char[m+1];		memcpy(t,name,m);	t[m]=0;
+	uintptr_t r = uintptr_t(mgl_data_ifs_file(s,t,*n,*skip));
+	delete []s;	delete []t;		return r;	}
+//-----------------------------------------------------------------------------
+//
+//	Functions for flame fractal
+//
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_linear_var0(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{	xNew += par[0]*x;	yNew += par[0]*y;	}
+void MGL_NO_EXPORT mgl_sinusoidal_var1(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{	xNew += par[0]*sin(x);	yNew += par[0]*sin(y);	}
+void MGL_NO_EXPORT mgl_spherical_var2(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{	mreal c1 = par[0]/(x*x+y*y);	xNew += c1*x;	yNew += c1*y;	}
+void MGL_NO_EXPORT mgl_swirl_var3(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal r2=x*x+y*y, c1=sin(r2), c2=cos(r2);
+	xNew += par[0]*(x*c1 - y*c2);
+	yNew += par[0]*(x*c2 + y*c1);
+}
+void MGL_NO_EXPORT mgl_horseshoe_var4(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = par[0]/hypot(x,y);
+	xNew += c1*(x*x-y*y);
+	yNew += 2*c1*x*y;
+}
+void MGL_NO_EXPORT mgl_polar_var5(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	xNew += par[0]*atan2(x,y)/M_PI;
+	yNew += par[0]*(hypot(x,y)-1);
+}
+void MGL_NO_EXPORT mgl_handkerchief_var6(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal r=hypot(x,y), t=atan2(x,y), c1=par[0]*r;
+	xNew += c1*sin(t+r);	yNew += c1*cos(t-r);
+}
+void MGL_NO_EXPORT mgl_heart_var7(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal r=hypot(x,y), c1=par[0]*r, c2=atan2(x,y)*r;
+	xNew +=  c1*sin(c2);	yNew -= c1*cos(c2);
+}
+void MGL_NO_EXPORT mgl_disc_var8(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1=par[0]*atan2(x,y)/M_PI, c2=M_PI*hypot(x,y);
+	xNew += c1*sin(c2);		yNew += c1*cos(c2);
+}
+void MGL_NO_EXPORT mgl_spiral_var9(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal r=hypot(x,y), t=atan2(x,y), c1=par[0]/r;
+	xNew += c1*(cos(t)+sin(r));
+	yNew += c1*(sin(t)-cos(r));
+}
+void MGL_NO_EXPORT mgl_hyperbolic_var10(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal r=hypot(x,y), t=atan2(x,y);
+	xNew += par[0]*sin(t)/r;
+	yNew += par[0]*r*cos(t);
+}
+void MGL_NO_EXPORT mgl_diamond_var11(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal r=hypot(x,y), t=atan2(x,y);
+	xNew += par[0]*sin(t)*cos(r);
+	yNew += par[0]*cos(t)*sin(r);
+}
+void MGL_NO_EXPORT mgl_ex_var12(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal r=hypot(x,y), t=atan2(x,y), c1=par[0]*r;
+	mreal c2=mgl_ipow(sin(t+r),3), c3 = mgl_ipow(cos(t-r), 3);
+	xNew += c1*(c2 + c3);	yNew += c1*(c2 - c3);
+}
+void MGL_NO_EXPORT mgl_julia_var13(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1=par[0]*sqrt(hypot(x,y)), c2=atan2(x,y)/2, c3=(rand()%2)*M_PI;
+	xNew += c1*cos(c2+c3);	yNew += c1*sin(c2+c3);
+}
+void MGL_NO_EXPORT mgl_bent_var14(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	if(x>=0 && y>=0)
+	{	xNew += par[0]*x;	yNew += par[0]*y;	}
+	else if(x<0 && y>=0)
+	{	xNew += par[0]*2*x;	yNew += par[0]*y;	}
+	else if(x>=0 && y<0)
+	{	xNew += par[0]*x;	yNew += par[0]*y/2;	}
+	else
+	{	xNew += par[0]*2*x;	yNew += par[0]*y/2;	}
+}
+void MGL_NO_EXPORT mgl_waves_var15(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{	// NOTE: par[1]=b[i], par[2]=1/c[i]^2, par[3]=e[i], par[4]=1/f[i]^2
+	xNew += par[0]*(x + par[1]*sin(y*par[2]));
+	yNew += par[0]*(y + par[3]*sin(x*par[4]));
+}
+void MGL_NO_EXPORT mgl_fisheye_var16(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = par[0]*2/(hypot(x,y) + 1);
+	xNew += c1*y;	yNew += c1*x;
+}
+void MGL_NO_EXPORT mgl_popcorn_var17(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{	// NOTE: par[1]=c[i], par[2]=f[i]
+	xNew += par[0]*(x + par[1]*sin(tan(3*y)));
+	yNew += par[0]*(y + par[2]*sin(tan(3*x)));
+}
+void MGL_NO_EXPORT mgl_exponential_var18(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1=par[0]*exp(x-1);
+	xNew += c1*cos(M_PI*y);	yNew += c1*sin(M_PI*y);
+}
+void MGL_NO_EXPORT mgl_power_var19(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal t=atan2(x,y), c1=par[0]*pow(hypot(x,y), sin(t));
+	xNew += c1*cos(t);	yNew += c1*sin(t);
+}
+void MGL_NO_EXPORT mgl_cosine_var20(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	xNew += par[0]*cos(M_PI*x)*cosh(y);
+	yNew -= par[0]*sin(M_PI*x)*sinh(y);
+}
+void MGL_NO_EXPORT mgl_rings_var21(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{	// NOTE: par[1]=c[i]^2
+	mreal t=atan2(x,y), r=hypot(x,y), c1=par[0]*(fmod(r+par[1],2*par[1])-par[1]+r*(1-par[1])); // convert to int?
+	xNew += c1*cos(t);	yNew += c1*sin(t);
+}
+void MGL_NO_EXPORT mgl_fan_var22(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{	// NOTE: par[1]=c[i]^2, par[2]=f[i]
+	mreal t=atan2(x,y), c1=par[0]*hypot(x,y), c2;
+	c2 = fmod(t+par[2], M_PI*par[1]); // convert to int?
+	if(c2>M_PI_2*par[1])	c2 = t - M_PI_2*par[1];
+	else	c2 += t;
+	xNew += c1*cos(c2);	yNew += c1*sin(c2);
+}
+void MGL_NO_EXPORT mgl_blob_var23(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal t=atan2(x,y), c1=par[0]*hypot(x,y)*(par[2]+(par[1]-par[2])/2*(sin(par[3]*t)));
+	xNew += c1*cos(t);	yNew += c1*sin(t);
+}
+void MGL_NO_EXPORT mgl_pdj_var24(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	xNew += par[0]*(sin(par[1]*y) - cos(par[2]*x));
+	yNew += par[0]*(sin(par[3]*x) - cos(par[4]*y));
+}
+void MGL_NO_EXPORT mgl_fan2_var25(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal t=atan2(x,y), c1, c2;
+	c1 = M_PI*par[1]*par[1];
+	c2 = t + par[2] - c1*int(2*t*par[2]/c1);
+	c1 /= 2;	c2 = c2>c1?t-c1:t+c1;
+	c1 = par[0]*hypot(x,y);
+	xNew += c1*sin(c2);	yNew += c1*cos(c2);
+}
+void MGL_NO_EXPORT mgl_rings2_var26(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal r=hypot(x,y), t=atan2(x,y), c1=par[1]*par[1];
+	c1 = par[0]*(r - 2*c1*int((r+c1)/(2*c1)) + r*(1-c1));
+	xNew += c1*cos(t);	yNew += c1*sin(t);
+}
+void MGL_NO_EXPORT mgl_eyefish_var27(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = par[0]*2/(hypot(x,y)+1);
+	xNew += c1*x;		yNew += c1*y;
+}
+void MGL_NO_EXPORT mgl_bubble_var28(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = par[0]*4/(x*x+y*y+4);
+	xNew += c1*x;		yNew += c1*y;
+}
+void MGL_NO_EXPORT mgl_cylinder_var29(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{	xNew += par[0]*sin(x);	yNew += par[0]*y;	}
+void MGL_NO_EXPORT mgl_perspective_var30(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = par[0]*par[2]/(par[2]-y*sin(par[1]));
+	xNew += c1*x;	yNew += c1*y*cos(par[1]);
+}
+void MGL_NO_EXPORT mgl_noise_var31(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1=par[0]*mgl_rnd(), c2=2*M_PI*mgl_rnd();
+	xNew += c1*x*cos(c2);	yNew += c1*y*sin(c2);
+}
+void MGL_NO_EXPORT mgl_juliaN_var32(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1=int(fabs(par[1])*mgl_rnd()), c2;
+	c2 = (atan2(y,x) + 2*M_PI*c1)/par[1];
+	c1 = par[0]*pow(hypot(x,y), par[2]/par[1]);
+	xNew += c1*cos(c2);	yNew += c1*sin(c2);
+}
+void MGL_NO_EXPORT mgl_juliaScope_var33(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1=int(fabs(par[1])*mgl_rnd()), c2;
+	c2 = ((2*(rand()%2)-1)*atan2(y,x) + 2*M_PI*c1)/par[1];
+	c1 = par[0]*pow(hypot(x,y), par[2]/par[1]);
+	xNew += c1*cos(c2);	yNew += c1*sin(c2);
+}
+void MGL_NO_EXPORT mgl_blur_var34(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1=par[0]*mgl_rnd(), c2=2*M_PI*mgl_rnd();
+	xNew += c1*cos(c2);	yNew += c1*sin(c2);
+}
+void MGL_NO_EXPORT mgl_gaussian_var35(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1=par[0]*(4*mgl_rnd()-2), c2=2*M_PI*mgl_rnd();
+	xNew += c1*cos(c2);	yNew += c1*sin(c2);
+}
+void MGL_NO_EXPORT mgl_radialBlur_var36(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal r=hypot(x,y), c1=par[1]*M_PI_2, c2=par[0]*(4*mgl_rnd()-2), c3;
+	c3 = c2*cos(c1) - 1;	c2 = atan2(y,x) + c2 *sin(c1);
+	xNew += r*cos(c2) + c3*x;	yNew += r*sin(c2) + c3*y;
+}
+void MGL_NO_EXPORT mgl_pie_var37(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1=int(mgl_rnd()*par[1] + 0.5), c2;
+	c2 = par[2] + 2*M_PI/par[1]*(c1 + mgl_rnd()*par[3]);
+	c1 = par[0]*mgl_rnd();
+	xNew += c1*cos(c2);	yNew += c1*sin(c2);
+}
+void MGL_NO_EXPORT mgl_ngon_var38(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1=2*M_PI/par[2], c2;
+	c2 = atan2(y,x) - c1*floor(atan2(y,x)/c1);
+	if(c2 <= c1/2)	c2 -= c1;
+	c1 = par[0]*(par[3]*(1/cos(c2) - 1) + par[4])/pow(hypot(x,y), par[1]);
+	xNew += c1*x;	yNew += c1*y;
+}
+void MGL_NO_EXPORT mgl_curl_var39(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1=1 + par[1]*x + par[2]*(x*x - y*y);
+	mreal c2 = par[1]*y + 2*par[2]*x*y;
+	mreal c3 = par[0]/(c1*c1 + c2*c2);
+	xNew += c3*(c1*x + c2*y);	yNew += c3*(c1*x - c2*y);
+}
+void MGL_NO_EXPORT mgl_rectangles_var40(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	xNew += par[0]*((2*floor(x/par[1]) + 1)*par[1] - x);
+	yNew += par[0]*((2*floor(y/par[2]) + 1)*par[2] - y);
+}
+void MGL_NO_EXPORT mgl_arch_var41(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1=mgl_rnd()*M_PI*par[0], c2=sin(c1);
+	xNew += par[0]*c2;	yNew += par[0]*c2*c2/cos(c1);
+}
+void MGL_NO_EXPORT mgl_tangent_var42(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{	xNew += par[0]*sin(x)/cos(y);	yNew += par[0]*tan(y);	}
+void MGL_NO_EXPORT mgl_square_var43(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	xNew += par[0]*(mgl_rnd() - 0.5);
+	yNew += par[0]*(mgl_rnd() - 0.5);
+}
+void MGL_NO_EXPORT mgl_blade_var44(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1=par[0]*x, c2=mgl_rnd()*hypot(x,y)*par[0];
+	xNew += c1*(cos(c2) + sin(c2));	// TODO check use of c2
+	yNew += c1*(cos(c2) - sin(c2));
+}
+void MGL_NO_EXPORT mgl_secant_var45(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{	xNew += par[0]*x;	yNew += 1/cos(par[0]*hypot(x,y));	}
+void MGL_NO_EXPORT mgl_rays_var46(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = par[0]*par[0]*tan(mgl_rnd()*M_PI*par[0])/(x*x+y*y);
+	xNew += c1*cos(x);	yNew += c1*sin(y);
+}
+void MGL_NO_EXPORT mgl_twintrian_var47(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1=par[0]*x, c2, c3;
+	c2 = mgl_rnd()*hypot(x,y)*par[0];
+	c3 = log10(sin(c2)*sin(c2)) + cos(c2);
+	xNew += c1*c3;	yNew += c1*(c3 - M_PI*sin(c2));
+}
+void MGL_NO_EXPORT mgl_cross_var48(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = par[0]/fabs(x*x - y*y);
+	xNew += c1*x;	yNew += c1*y;
+}
+void MGL_NO_EXPORT mgl_disc2_var49(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = cos(par[2])-1, c2 = sin(par[2]), c3;
+	if(par[2]>2*M_PI)
+	{
+		c3 = 1+par[2]-2*M_PI;
+		c1 *= c3;   c2 *= c3;
+	}
+	else if(par[2]<-2*M_PI)
+	{
+		c3 = 1+par[2]+2*M_PI;
+		c1 *= c3;   c2 *= c3;
+	}
+	c3 = par[1]*M_PI*(x+y);
+	mreal a = par[0]*atan2(x,y)/M_PI;
+	xNew += a*(c1+sin(c3)); yNew += a*(c2+cos(c3));
+}
+void MGL_NO_EXPORT mgl_supershape_var50(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = par[2]/4*atan2(y,x)+M_PI_4, r = hypot(x,y);
+	c1 = pow(fabs(sin(c1)), par[5])+pow(fabs(cos(c1)), par[4]);
+	c1 = par[0]*((par[1]*mgl_rnd()+(1-par[1])*r)-par[6])*pow(c1, -1.0/par[3])/r;
+	xNew += c1*x;	yNew += c1*y;
+}
+void MGL_NO_EXPORT mgl_flower_var51(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = par[0]*(mgl_rnd()-par[2])*cos(par[1]*atan2(y,x))/hypot(x,y);
+	xNew += c1*x;	yNew += c1*y;
+}
+void MGL_NO_EXPORT mgl_conic_var52(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = x/hypot(x,y);
+	c1 = par[0]*(mgl_rnd()-par[2])*par[1]/(1+par[1]*c1)/hypot(x,y);
+	xNew += c1*x;	yNew += c1*y;
+}
+void MGL_NO_EXPORT mgl_parabola_var53(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = hypot(x,y), c2;
+	c2 = cos(c1);	c1 = sin(c1);
+	xNew += par[0]*par[1]*c1*c1 *mgl_rnd();
+	yNew += par[0]*par[2]*c2*mgl_rnd();
+}
+void MGL_NO_EXPORT mgl_bent2_var54(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = par[0]*x, c2 = par[0]*y;
+	if(x<0.0)	c1 *= par[1];
+	if(y<0.0)	c2 *= par[2];
+	xNew += c1;		yNew += c2;
+}
+void MGL_NO_EXPORT mgl_bipolar_var55(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = 0.5*atan2(2*y, x*x+y*y-1)-M_PI_2*par[1], c2, c3, c4;
+	if(c1>M_PI_2)	c1 = -M_PI_2+fmod(c1+M_PI_2, M_PI);
+	else if(y<-M_PI_2)   c1 = M_PI_2-fmod(M_PI_2-y, M_PI);
+	c2 = par[0]*M_2_PI;
+	c3 = x*x+y*y+1;	c4 = 2*x;
+	xNew += 0.25*c2*log((c3+c4)/(c3-c4));	yNew += c1*c2;
+}
+void MGL_NO_EXPORT mgl_boarders_var56(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = round(x), c2 = round(y), c3, c4;
+	c3 = x-c1;	c4 = y-c2;
+	if(mgl_rnd()>=0.75)
+	{
+		xNew += par[0]*(c1+0.5*c3);
+		yNew += par[0]*(c2+0.5*c4);
+	}
+	else
+	{
+		if(fabs(c3)>=fabs(c4))
+		{
+			if(c3>=0)
+			{
+				xNew += par[0]*(c1+0.5*c3+0.25);
+				yNew += par[0]*(c2+0.5*c4+0.25*c4/c3);
+			}
+			else
+			{
+				xNew += par[0]*(c1+0.5*c3-0.25);
+				yNew += par[0]*(c2+0.5*c4-0.25*c4/c3);
+			}
+		}
+		else
+		{
+			if(c4>=0)
+			{
+				xNew += par[0]*(c2+0.5*c4+0.25);
+				yNew += par[0]*(c1+0.5*c3+0.25*c3/c4);
+			}
+			else
+			{
+				xNew += par[0]*(c2+0.5*c4-0.25);
+				yNew += par[0]*(c1+0.5*c3-0.25*c3/c4);
+			}
+		}
+	}
+}
+void MGL_NO_EXPORT mgl_butterfly_var57(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = 4/sqrt(3*M_PI)*par[0], c2 = 2*y; // replace 4/sqrt(3*M_PI) for the result?
+	c1 *= sqrt(fabs(x*y)/(x*x+c2*c2));
+	xNew += c1*x; yNew += c1*c2;
+}
+void MGL_NO_EXPORT mgl_cell_var58(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1=floor(x/par[1]), c2=floor(y/par[1]), c3=x-c1*par[1], c4=y-c2*par[1];
+	if(c2>=0)
+	{
+		if(c1>=0)	{	c1 *= 2;	c2 *= 2;	}
+		else		{	c1=-2*c1-1;	c2 *= 2;	}
+	}
+	else
+	{
+		if(c1>=0)	{	c1 *= 2;	c2=-2*c2-1;	}
+		else		{	c1=-2*c1-1;	c2=-2*c2-1;	}
+	}
+	xNew += par[0]*(par[1]*c1+c3);
+	yNew += par[0]*(par[1]*c2+c4);
+}
+void MGL_NO_EXPORT mgl_cpow_var59(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = atan2(y, x), c2, c3, c4, c5;
+	c2 = par[1]/par[3];
+	c3 = par[2]/par[3];
+	c4 = 0.5*log(x*x+y*y);
+	c5 = c1*c2+c3*c4+2*M_PI/par[3]*floor(par[3]*mgl_rnd());
+	c1 = par[0]*exp(c2*c4-c1*c3);
+	c2 = cos(c5);
+	c3 = sin(c5);
+	xNew += c1*c2;	yNew += c1*c3;
+}
+void MGL_NO_EXPORT mgl_curve_var60(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	xNew += par[0]*(x+par[1]*exp(-(y*y)/(par[3]*par[3])));
+	yNew += par[0]*(y+par[2]*exp(-(x*x)/(par[4]*par[4])));
+}
+void MGL_NO_EXPORT mgl_edisc_var61(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = x*x+y*y+1, c2,c3,c4,c5;
+	c2 = 2*x;
+	c3 = sqrt(c1-c2);
+	c1 = sqrt(c1+c2);
+	c1 = (c1+c3)*0.5;
+	c2 = log(c1+sqrt(c1-1));
+	c3 = -acos(x/c1);
+	c1 = par[0]/11.57034632;
+	c4 = cos(c2)*cosh(c3);
+	c5 = sin(c2)*sinh(c3);
+	xNew += c1*c4;	yNew += c1*c5;
+}
+void MGL_NO_EXPORT mgl_elliptic_var62(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = x*x+y*y+1, c2, c3, c4, c5;
+	c2 = 2*x;
+	c2 = 0.5*(sqrt(c1+c2)+sqrt(c1-c2));
+	c3 = x/c2;
+	c4 = 1-c3*c3;
+	c5 = c2-1;
+	c1 = par[0]/M_PI_2;
+	if(c4<0)	c4 = 0;
+	else	c4 = sqrt(c4);
+	if(c5<0)	c5 = 0;
+	else	c5 = sqrt(c5);
+	xNew += c1*atan2(c3, c4);
+	if(y>0)	yNew += c1*log(c2+c5);
+	else	yNew -= c1*log(c2+c5);
+}
+void MGL_NO_EXPORT mgl_escher_var63(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = 0.5*(1+cos(par[1])), c2 = 0.5*sin(par[1]), c3, c4, c5;
+	c3 = 0.5*log(x*x+y*y);	c4 = atan2(y, x);
+	c5 = c1*c4+c2*c3;		c1 = par[0]*exp(c1*c3-c2*c4);
+	xNew += c1*cos(c5);	yNew += c1*sin(c5);
+}
+void MGL_NO_EXPORT mgl_foci_var64(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1=0.5*exp(x), c2=0.25/c1, c3=par[0]/(c1+c2-cos(y));	// TODO Check this!!!
+	xNew += c1*(c2-c3);	yNew += c1*sin(y);
+}
+void MGL_NO_EXPORT mgl_lazySusan_var65(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = hypot(x, y), c2;
+	if(c1<par[0])
+	{
+		c2 = atan2(y+par[5], x-par[4])+par[1]+par[3]*(par[0]-c1);
+		c1 *= par[0];
+		xNew += c1*cos(c2)+par[4];
+		yNew += c1*sin(c2)-par[5];
+	}
+	else
+	{
+		c1 = par[0]*(1+par[2]/c1);
+		xNew += c1*(x-par[4])+par[4];
+		yNew += c1*(y+par[5])-par[5];
+	}
+}
+void MGL_NO_EXPORT mgl_loonie_var66(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = x*x+y*y, c2 = par[0]*par[0];
+	if(c1<c2)
+	{
+		c1 = par[0]*sqrt(c2/c1-1);
+		xNew += c1*x;	yNew += c1*y;
+	}
+	else	xNew += par[0]*x;	yNew += par[0]*y;
+}
+void MGL_NO_EXPORT mgl_preBlur_var67(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = par[0]*(mgl_rnd()+mgl_rnd()+mgl_rnd()+mgl_rnd()-2), c2;
+	c2 = 2*mgl_rnd()*M_PI;
+	x += c1*cos(c2);	y += c1*sin(c2); // NOTE: This changes the original coordinates, not the new ones
+}
+void MGL_NO_EXPORT mgl_modulus_var68(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	if(x>par[1])	xNew += par[0]*(-par[1]+fmod(x-par[1], 2*par[1]));
+	else if(x<par[1])	xNew += par[0]*(par[1]-fmod(par[1]-x, 2*par[1]));
+	else	xNew += par[0]*x;
+	if(y>par[2])	yNew += par[0]*(-par[2]+fmod(y+par[2], 2*par[2]));
+	else if(y<par[2])	yNew += par[0]*(par[2]-fmod(par[2]-y, 2*par[2]));
+	else	yNew += par[0]*y;
+}
+void MGL_NO_EXPORT mgl_oscope_var69(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = par[3]*exp(-fabs(x)*par[4])*cos(2*M_PI*par[2]*x)+par[1];
+	if(fabs(y) <= c1)
+	{	xNew += par[0]*x;	yNew -= par[0]*y;	}
+	else
+	{	xNew += par[0]*x;	yNew += par[0]*y;	}
+}
+void MGL_NO_EXPORT mgl_polar2_var70(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal t = atan2(x, y);
+	xNew += par[0]*t*t;	yNew += par[0]*t/2*log(x*x+y*y);
+}
+void MGL_NO_EXPORT mgl_popcorn2_var71(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	xNew += par[0]*(x+par[1]*sin(tan(par[3]*y)));
+	yNew += par[0]*(y+par[2]*sin(tan(par[3]*x)));
+}
+void MGL_NO_EXPORT mgl_scry_var72(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = 1/(hypot(x, y)*(x*x+y*y+1/par[0]));
+	xNew += c1*x;	yNew += c1*y;
+}
+void MGL_NO_EXPORT mgl_separation_var73(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	if(x>0)	xNew += par[0]*(sqrt(x*x+par[1]*par[1])-x*par[2]);
+	else	xNew -= par[0]*(sqrt(x*x+par[1]*par[1])+x*par[2]);
+	if(y>0)	yNew += par[0]*(sqrt(y*y+par[3]*par[3])-y*par[4]);
+	else	yNew -= par[0]*(sqrt(y*y+par[3]*par[3])+y*par[4]);
+}
+void MGL_NO_EXPORT mgl_split_var74(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	if(cos(M_PI*x*par[1])>=0)	xNew += par[0]*y;
+	else	xNew -= par[0]*y;
+	if(cos(M_PI*y*par[2])>=0)	yNew += par[0]*x;
+	else	yNew -= par[0]*x;
+}
+void MGL_NO_EXPORT mgl_splits_var75(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	if(x>=0)	xNew+= par[0]*(x+par[1]);
+	else 	xNew += par[0]*(x-par[1]);
+	if(y>=0)	yNew += par[0]*(y+par[2]);
+	else	yNew += par[0]*(y-par[2]);
+}
+void MGL_NO_EXPORT mgl_stripes_var76(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = floor(x+0.5), c2 = x-c1;
+	xNew += par[0]*(c2*(1-par[1])+c1);
+	yNew += par[0]*(y+c2*c2*par[2]);
+}
+void MGL_NO_EXPORT mgl_wedge_var77(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = hypot(x, y), c2, c3, c4;
+	c2 = atan2(y, x)+par[4]*c1;
+	c3 = 1-0.5*M_1_PI*par[1]*par[3];
+	c4 = floor(0.5*M_1_PI*(par[2]*c2+M_PI));
+	c2 = c2*c3+c4*par[1];
+	c1 = par[0]*(c1+par[2]);
+	xNew += c1*cos(c2);	yNew += c1*sin(c2);
+}
+void MGL_NO_EXPORT mgl_wedgeJulia_var78(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = int(fabs(par[3])*mgl_rnd()), c2;
+	c1 = (atan2(y, x)+2*M_PI*c1)/par[3];
+	c2 = floor(0.5*M_1_PI*(par[2]*c1+M_PI));
+	c2 = c1*(1-0.5*M_1_PI*par[1]*par[2]+c1*par[1]);	// TODO Check this!!!
+	c1 = par[0]*pow(x*x +y*y, par[4]/(2*par[3]));
+	xNew += c1*cos(c2);	yNew += c1*sin(c2);
+}
+void MGL_NO_EXPORT mgl_wedgeSph_var79(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = 1/hypot(x, y), c2, c3, c4;
+	c2 = atan2(y, x)+par[4]*c1;
+	c3 = 1-0.5*M_1_PI*par[1]*par[2];
+	c4 = floor(0.5*M_1_PI*(par[2]*c2+M_PI));
+	c2 = c2*c3+c4*par[1];
+	c1 = par[0]*(c1+par[3]);
+	xNew += c1*cos(c2);	yNew += c1*sin(c2);
+}
+void MGL_NO_EXPORT mgl_whorl_var80(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = hypot(x, y), c2;
+	if(c1<par[0])	c2 = atan2(y, x)+par[1]/(par[0]-c1);
+	else	c2 = atan2(y, x)+par[2]/(par[0]-c1);
+	c1 *= par[0];
+	xNew += c1*cos(c2);	yNew += c1*sin(c2);
+}
+void MGL_NO_EXPORT mgl_waves2_var81(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	xNew += par[0]*(x+par[2]*sin(y*par[1]));
+	yNew += par[0]*(y+par[4]*sin(x*par[3]));
+}
+void MGL_NO_EXPORT mgl_exp_var82(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = par[0]*exp(x);
+	xNew += c1*cos(y);	yNew += c1*sin(y);
+}
+void MGL_NO_EXPORT mgl_log_var83(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	xNew += par[0]*0.5*log(x*x+y*y);	yNew += par[0]*atan2(y, x);
+}
+void MGL_NO_EXPORT mgl_sin_var84(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	xNew += par[0]*sin(x)*cosh(y);	yNew += par[0]*cos(x)*sinh(y);
+}
+void MGL_NO_EXPORT mgl_cos_var85(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	xNew += par[0]*cos(x)*cosh(y);	yNew -= par[0]*sin(x)*sinh(y);
+}
+void MGL_NO_EXPORT mgl_tan_var86(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = par[0]/(cos(2*x)+cosh(2*y));
+	xNew += c1*sin(2*x);	yNew += c1*sinh(2*y);
+}
+void MGL_NO_EXPORT mgl_sec_var87(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = 2*par[0]/(cos(2*x)+cosh(2*y));
+	xNew += c1*cos(x)*cosh(y);	yNew += c1*sin(x)*sinh(y);
+}
+void MGL_NO_EXPORT mgl_csc_var88(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = 2*par[0]/(cosh(2*y)-cos(2*x));
+	xNew += c1*sin(x)*cosh(y);	yNew -= c1*cos(x)*sinh(y);
+}
+void MGL_NO_EXPORT mgl_cot_var89(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = par[0]/(cosh(2*y)-cos(2*x));
+	xNew += c1*sin(2*x);	yNew -= c1*sinh(2*y);
+}
+void MGL_NO_EXPORT mgl_sinh_var90(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{	xNew += par[0]*sinh(x)*cos(y);	yNew += par[0]*cosh(y)*sin(y);	}
+void MGL_NO_EXPORT mgl_cosh_var91(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{	xNew += par[0]*cosh(x)*cos(y);	yNew += par[0]*sinh(x)*sin(y);	}
+void MGL_NO_EXPORT mgl_tanh_var92(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = par[0]/(cos(2*y)+cosh(2*x));
+	xNew += c1*sinh(2*x);	yNew += c1*sin(2*y);
+}
+void MGL_NO_EXPORT mgl_sech_var93(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = 2*par[0]/(cos(2*y)+cosh(2*x));
+	xNew += c1*cos(y)*cosh(x);	yNew -= c1*sin(y)*sinh(x);
+}
+void MGL_NO_EXPORT mgl_csch_var94(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = 2*par[0]/(cosh(2*x)-cos(2*y));
+	xNew += c1*sinh(x)*cos(y);	yNew -= c1*cosh(x)*sin(y);
+}
+void MGL_NO_EXPORT mgl_coth_var95(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = par[0]/(cosh(2*x)-cos(2*y));
+	xNew += c1*sinh(2*x);	yNew += c1*sin(2*y);
+}
+void MGL_NO_EXPORT mgl_auger_var96(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = sin(par[3]*y), c2 = sin(par[3]*x);
+	c1 = x+par[2]*(par[4]*c1/2+fabs(x)*c1);
+	c2 = y+par[2]*(par[4]*c2/2+fabs(y)*c2);
+	xNew += par[0]*(x+par[1]*(c1-x));	yNew += par[0]*c2;
+}
+void MGL_NO_EXPORT mgl_flux_var97(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par)
+{
+	mreal c1 = x+par[0], c2 = x-par[0], c3;
+	c3 = 0.5*(atan2(y, c2)-atan2(y, c1));
+	c1 = par[0]*(2+par[1])*sqrt(sqrt(y*y+c1*c1)/sqrt(y*y-c2*c2));
+	xNew += c1*cos(c3);	yNew += c1*sin(c3);
+}
+//-----------------------------------------------------------------------------
+typedef void (*flame_func)(mreal &xNew, mreal &yNew, mreal x, mreal y, const mreal *par);
+MGL_NO_EXPORT flame_func ffunc[mglFlame2dLAST] = {
+	mgl_linear_var0,	mgl_sinusoidal_var1,	mgl_spherical_var2,	mgl_swirl_var3,		mgl_horseshoe_var4,
+	mgl_polar_var5,		mgl_handkerchief_var6,	mgl_heart_var7,		mgl_disc_var8,		mgl_spiral_var9,
+	mgl_hyperbolic_var10,	mgl_diamond_var11,	mgl_ex_var12,		mgl_julia_var13,	mgl_bent_var14,
+	mgl_waves_var15,		mgl_fisheye_var16,	mgl_popcorn_var17,	mgl_exponential_var18,	mgl_power_var19,
+	mgl_cosine_var20,		mgl_rings_var21,	mgl_fan_var22,		mgl_blob_var23,		mgl_pdj_var24,
+	mgl_fan2_var25,			mgl_rings2_var26,	mgl_eyefish_var27,	mgl_bubble_var28,	mgl_cylinder_var29,
+	mgl_perspective_var30,	mgl_noise_var31,	mgl_juliaN_var32,	mgl_juliaScope_var33,	mgl_blur_var34,
+	mgl_gaussian_var35,	mgl_radialBlur_var36,	mgl_pie_var37,		mgl_ngon_var38,		mgl_curl_var39,
+	mgl_rectangles_var40,	mgl_arch_var41,		mgl_tangent_var42,	mgl_square_var43,	mgl_blade_var44,
+	mgl_secant_var45,		mgl_rays_var46,		mgl_twintrian_var47,mgl_cross_var48,	mgl_disc2_var49,
+	mgl_supershape_var50,	mgl_flower_var51,	mgl_conic_var52,	mgl_parabola_var53,	mgl_bent2_var54,
+	mgl_bipolar_var55,		mgl_boarders_var56,	mgl_butterfly_var57,mgl_cell_var58,		mgl_cpow_var59,
+	mgl_curve_var60,		mgl_edisc_var61,	mgl_elliptic_var62,	mgl_escher_var63,	mgl_foci_var64,
+	mgl_lazySusan_var65,	mgl_loonie_var66,	mgl_preBlur_var67,	mgl_modulus_var68,	mgl_oscope_var69,
+	mgl_polar2_var70,		mgl_popcorn2_var71,	mgl_scry_var72,		mgl_separation_var73,	mgl_split_var74,
+	mgl_splits_var75,		mgl_stripes_var76,	mgl_wedge_var77,	mgl_wedgeJulia_var78,	mgl_wedgeSph_var79,
+	mgl_whorl_var80,		mgl_waves2_var81,	mgl_exp_var82,		mgl_log_var83,		mgl_sin_var84,
+	mgl_cos_var85,			mgl_tan_var86,		mgl_sec_var87,		mgl_csc_var88,		mgl_cot_var89,
+	mgl_sinh_var90,			mgl_cosh_var91,		mgl_tanh_var92,		mgl_sech_var93,		mgl_csch_var94,
+	mgl_coth_var95,			mgl_auger_var96,	mgl_flux_var97};
+//-----------------------------------------------------------------------------
+long MGL_NO_EXPORT mgl_flame_2d_point(HCDT A, HCDT F, mreal& x, mreal& y, mreal amax)
+{
+	long i, n=A->GetNy(), m=F->GetNy(), last_func=0, l=F->GetNx();
+	l = l>6?6:l;
+	mreal r = amax*mgl_rnd(), sum_prob = 0, x1, y1;
+	for(i=0;i<n;i++)
+	{
+		sum_prob += A->v(6,i);
+		if(r<sum_prob)	break;
+	}
+	x1 = A->v(0,i)*x+A->v(1,i)*y+A->v(4,i);
+	y1 = A->v(2,i)*x+A->v(3,i)*y+A->v(5,i);
+	x = y = 0;
+	for(long j=0;j<m;j++)
+	{
+		int v=int(F->v(0,j,i)+0.5);
+		mreal par[5] = {F->v(1,j,i),0,0,0,0};
+		for(int k=2;k<l;k++)	par[k-1]=F->v(k,j,i);
+		if(v<0 || v>=mglFlame2dLAST)	{	v=0;	par[0]=1;	}
+		ffunc[v](x,y,x1,y1,par);	last_func=v;
+	}
+	return last_func;
+}
+HMDT MGL_EXPORT mgl_data_flame_2d(HCDT A, HCDT F, long n, long skip)
+{
+	if(!A || A->GetNx()<7 || n<1)	return 0;	// incompatible dimensions
+	if(!F || F->GetNx()<2 || F->GetNz()!=A->GetNy())	return 0;	// incompatible dimensions
+	mreal amax=0;
+	for(long i=0; i<A->GetNy(); i++)	amax += A->v(6,i);
+	if(amax<=0)	return 0;
+
+	mglData *f = new mglData(3,n);
+	mreal x = 0, y = 0;
+	for(long i=0; i<skip; i++)	mgl_flame_2d_point(A, F, x, y,amax);
+	for(long i=0; i<n; i++)
+	{
+		f->a[3*i+2] = mgl_flame_2d_point(A, F, x, y, amax);	// TODO color information ?!!
+		f->a[3*i] = x;	f->a[3*i+1] = y;
+	}
+	return f;
+}
+uintptr_t MGL_EXPORT mgl_data_flame_2d_(uintptr_t *d, uintptr_t *f, long *n, long *skip)
+{	return uintptr_t(mgl_data_flame_2d(_DT_,_DA_(f),*n,*skip));	}
+//-----------------------------------------------------------------------------
diff --git a/src/interp.hpp b/src/interp.hpp
new file mode 100644
index 0000000..d3ac267
--- /dev/null
+++ b/src/interp.hpp
@@ -0,0 +1,252 @@
+//-----------------------------------------------------------------------------
+template <class Treal> Treal mglLineart(const Treal *a, long nx, long ny, long nz, mreal x, mreal y, mreal z)
+{
+	if(!a || nx<1 || ny<1 || nz<1)	return 0;
+	Treal b=0,dx,dy,dz,b1,b0;
+	if(x<0 || y<0 || z<0 || x>nx-1 || y>ny-1 || z>nz-1)
+		return 0;
+	if(nz>1 && z!=floor(z))		// 3d interpolation
+	{
+		long kx=long(x), ky=long(y), kz=long(z);
+		dx = x-mreal(kx);	dy = y-mreal(ky);	dz = z-mreal(kz);
+
+		long i0 = kx+nx*(ky+ny*kz);
+		b0 = a[i0]*(mreal(1)-dx-dy+dx*dy) + dx*(mreal(1)-dy)*a[i0+1] +
+			dy*(mreal(1)-dx)*a[i0+nx] + dx*dy*a[i0+nx+1];
+		i0 = kx+nx*(ky+ny*(kz+1));
+		b1 = a[i0]*(mreal(1)-dx-dy+dx*dy) + dx*(mreal(1)-dy)*a[i0+1] +
+			dy*(mreal(1)-dx)*a[i0+nx] + dx*dy*a[i0+nx+1];
+		b = b0 + dz*(b1-b0);
+	}
+	else if(ny>1 && y!=floor(y))	// 2d interpolation
+	{
+		long kx=long(x), ky=long(y);
+		dx = x-kx;	dy=y-ky;
+		long i0 = kx+nx*ky;
+		b = a[i0]*(mreal(1)-dx-dy+dx*dy) + dx*(mreal(1)-dy)*a[i0+1] +
+			dy*(mreal(1)-dx)*a[i0+nx] + dx*dy*a[i0+nx+1];
+	}
+	else if(nx>1 && x!=floor(x))	// 1d interpolation
+	{
+		long kx = long(x);
+		b = a[kx] + (x-kx)*(a[kx+1]-a[kx]);
+	}
+	else						// no interpolation
+		b = a[long(x+nx*(y+ny*z))];
+	return b;
+}
+//-----------------------------------------------------------------------------
+template <class Treal> Treal mgl_spline3t(const Treal y[4], long n, mreal dx, Treal &dy)
+{
+	Treal d[3];
+	d[0] = -(y[2]-mreal(4)*y[1]+mreal(3)*y[0])/mreal(2);
+	d[1] = (y[2]-y[0])/mreal(2);
+	d[2] = (y[3]-y[1])/mreal(2);
+
+	Treal t0 = (y[2]+y[0])/mreal(2)-y[1];
+	Treal t1 = (y[3]+y[1])/mreal(2)-y[2];
+	Treal f0 = y[n], d0 = d[n], res = 0;
+	if(n==1)
+	{
+		Treal df = y[2]-f0, d1 = d[2];
+		Treal b3 = mreal(10)*df+t1-mreal(3)*t0-mreal(4)*d1-mreal(6)*d0;
+		Treal b4 = mreal(-15)*df-mreal(2)*t1+mreal(3)*t0+mreal(7)*d1+mreal(8)*d0;
+		Treal b5 = mreal(6)*df+t1-t0-mreal(3)*d1-mreal(3)*d0;
+		dy = d0 + dx*(mreal(2)*t0+dx*(mreal(3)*b3+dx*(mreal(4)*b4+dx*mreal(5)*b5)));
+//		d2y = mreal(2)*t0 + dx*(mreal(6)*b3+dx*(mreal(12)*b4+dx*mreal(20)*b5));	// 2nd derivative for future
+		res = f0 + dx*(d0+dx*(t0+dx*(b3+dx*(b4+dx*b5))));
+	}
+	else if(n<1)
+	{	res = f0 + dx*(d0+dx*t0);	dy = d0+dx*t0*mreal(2);	}
+	else
+	{	res = f0 + dx*(d0+dx*t1);	dy = d0+dx*t1*mreal(2);	}
+	return res;
+}
+//-----------------------------------------------------------------------------
+template <class Treal> Treal mgl_spline3st(const Treal y[4], long n, mreal dx)
+{
+	Treal d[3];
+	d[0] = -(y[2]-mreal(4)*y[1]+mreal(3)*y[0])/mreal(2);
+	d[1] = (y[2]-y[0])/mreal(2);
+	d[2] = (y[3]-y[1])/mreal(2);
+
+	Treal f0 = y[n], d0 = d[n], res;
+	Treal t0 = (y[2]+y[0])/mreal(2)-y[1];
+	Treal t1 = (y[3]+y[1])/mreal(2)-y[2];
+	if(n==1)
+	{
+		Treal df = y[2]-f0, d1 = d[2];
+		Treal b3 = mreal(10)*df+t1-mreal(3)*t0-mreal(4)*d1-mreal(6)*d0;
+		Treal b4 = mreal(-15)*df-mreal(2)*t1+mreal(3)*t0+mreal(7)*d1+mreal(8)*d0;
+		Treal b5 = mreal(6)*df+t1-t0-mreal(3)*d1-mreal(3)*d0;
+		res = f0 + dx*(d0+dx*(t0+dx*(b3+dx*(b4+dx*b5))));
+	}
+	else	res = f0 + dx*(d0+dx*(n<1?t0:t1));
+	return res;
+}
+//-----------------------------------------------------------------------------
+template <class Treal> Treal mglSpline1t(const Treal *a, long nx, mreal x, Treal *dx=0)
+{
+	Treal r,d;
+	if(nx>3)
+	{
+		long k = long(x);
+		if(k>0 && k<nx-2)	r = mgl_spline3t<Treal>(a+k-1, 1, x-k, d);
+		else if(k<1)		r = mgl_spline3t<Treal>(a, 0, x, d);
+		else	r = mgl_spline3t<Treal>(a+nx-4, 2, x+2-nx, d);
+	}
+	else if(nx<2)	{	d=0;	r = a[0];	}
+	else if(nx==2)	{	d=a[1]-a[0];	r = a[0]+(a[1]-a[0])*x;	}
+	else	// nx==3
+	{
+		Treal b1=-(a[2]-mreal(4)*a[1]+mreal(3)*a[0])/mreal(2), b2=(a[2]-mreal(2)*a[1]+a[0])/mreal(2);
+		d = b1+mreal(2)*b2*x;	r = a[0]+x*(b1+b2*x);
+	}
+	if(dx)	*dx=d;
+	return r;
+}
+//-----------------------------------------------------------------------------
+template <class Treal> Treal mglSpline1st(const Treal *a, long nx, mreal x)
+{
+	Treal r;
+	if(nx>3)
+	{
+		long k = long(x);
+		if(k>0 && k<nx-2)	r = mgl_spline3st<Treal>(a+k-1, 1, x-k);
+		else if(k<1)		r = mgl_spline3st<Treal>(a, 0, x);
+		else	r = mgl_spline3st<Treal>(a+nx-4, 2, x+2-nx);
+	}
+	else if(nx<2)	r = a[0];
+	else if(nx==2)	r = a[0]+(a[1]-a[0])*x;
+	else	// nx==3
+	{
+		Treal b1=-(a[2]-mreal(4)*a[1]+mreal(3)*a[0])/mreal(2), b2=(a[2]-mreal(2)*a[1]+a[0])/mreal(2);
+		r = a[0]+x*(b1+b2*x);
+	}
+	return r;
+}
+//-----------------------------------------------------------------------------
+template <class Treal> Treal mglSpline3t(const Treal *a, long nx, long ny, long nz, mreal x, mreal y, mreal z, Treal *dx=0, Treal *dy=0, Treal *dz=0)
+{
+//	if(!a || nx<1 || ny<1 || nz<1)	return 0;	// NOTE remove this line because this should already checked
+	Treal gx=0,gy=0,gz=0;
+	x = x>0 ?(x<nx-1 ? x:nx-1):0;
+	y = y>0 ?(y<ny-1 ? y:ny-1):0;
+	z = z>0 ?(z<nz-1 ? z:nz-1):0;
+	Treal b;
+	if(nz>1)		// 3d interpolation
+	{
+		Treal tz[4], yz[4], xz[4];
+		long kz=long(z)-1, mz, k=long(y)-1, m;
+		if(nz>3)
+		{	mz = 4;	kz = kz>=0?kz:0;
+			if(kz>nz-4)	kz = nz-4;	}
+		else	{	mz = nz;	kz=0;	}
+		if(ny>3)
+		{	m = 4;	k = k>=0?k:0;
+			if(k>ny-4)	k = ny-4;	}
+		else	{	m = ny;	k=0;	}
+		for(long j=0;j<mz;j++)
+		{
+			Treal t[4], d[4];
+			for(long i=0;i<m;i++)
+				t[i] = mglSpline1t<Treal>(a+nx*(i+k+ny*(j+kz)),nx,x,d+i);
+			tz[j] = mglSpline1t<Treal>(t,m,y-k,yz+j);
+			xz[j] = mglSpline1t<Treal>(d,m,y-k,0);
+		}
+		b = mglSpline1t<Treal>(tz,mz,z-kz,&gz);
+		gx = mglSpline1t<Treal>(xz,mz,z-kz,0);
+		gy = mglSpline1t<Treal>(yz,mz,z-kz,0);
+	}
+	else if(ny>1)	// 2d interpolation
+	{
+		Treal t[4], d[4];
+		long k = long(y)-1, m;
+		if(ny>3)
+		{	m = 4;	k = k>=0?k:0;	if(k>ny-4)	k = ny-4;	}
+		else	{	m = ny;	k=0;	}
+		for(long i=0;i<m;i++)
+			t[i] = mglSpline1t<Treal>(a+nx*(i+k),nx,x,d+i);
+		b = mglSpline1t<Treal>(t,m,y-k,&gy);
+		gx = mglSpline1t<Treal>(d,m,y-k,0);
+	}
+	else	// 1d interpolation
+		b = mglSpline1t<Treal>(a,nx,x,&gx);
+	if(dx)	*dx=gx;
+	if(dy)	*dy=gy;
+	if(dz)	*dz=gz;
+	return b;
+}
+//-----------------------------------------------------------------------------
+template <class Treal> Treal mglSpline3st(const Treal *a, long nx, long ny, long nz, mreal x, mreal y, mreal z)
+{
+//	if(!a || nx<1 || ny<1 || nz<1)	return 0;	// NOTE remove this line because this should already checked
+	x = x>0 ?(x<nx-1 ? x:nx-1):0;
+	y = y>0 ?(y<ny-1 ? y:ny-1):0;
+	z = z>0 ?(z<nz-1 ? z:nz-1):0;
+	Treal b;
+	if(nz>1)		// 3d interpolation
+	{
+		Treal tz[4], t[4];
+		long kz=long(z)-1, mz, k=long(y)-1, m;
+		if(nz>3)
+		{	mz = 4;	kz = kz>=0?kz:0;
+			if(kz>nz-4)	kz = nz-4;	}
+		else	{	mz = nz;	kz=0;	}
+		if(ny>3)
+		{	m = 4;	k = k>=0?k:0;
+			if(k>ny-4)	k = ny-4;	}
+		else	{	m = ny;	k=0;	}
+		for(long j=0;j<mz;j++)
+		{
+			for(long i=0;i<m;i++)
+				t[i] = mglSpline1st<Treal>(a+nx*(i+k+ny*(j+kz)),nx,x);
+			tz[j] = mglSpline1st<Treal>(t,m,y-k);
+		}
+		b = mglSpline1st<Treal>(tz,mz,z-kz);
+	}
+	else if(ny>1)	// 2d interpolation
+	{
+		Treal t[4];
+		long k = long(y)-1, m;
+		if(ny>3)
+		{	m = 4;	k = k>=0?k:0;
+			if(k>ny-4)	k = ny-4;	}
+		else	{	m = ny;	k=0;	}
+		for(long i=0;i<m;i++)
+			t[i] = mglSpline1st<Treal>(a+nx*(i+k),nx,x);
+		b = mglSpline1st<Treal>(t,m,y-k);
+	}
+	else	// 1d interpolation
+		b = mglSpline1st<Treal>(a,nx,x);
+	return b;
+}
+//-----------------------------------------------------------------------------
+template <class Treal> void mgl_gspline_init(long n, const mreal *x, const Treal *v, Treal *c)
+{	// c must have size 5*(n-1) !!!
+//	if(n<2)	return;	// NOTE remove this line because this should already checked
+	Treal *a = new Treal[n], *b = new Treal[n];
+	for(long i=0;i<n-1;i++)	// basic coefficients
+	{	c[5*i] = x[i+1]-x[i];	c[5*i+1] = v[i];	}
+	// progonka
+	a[0] = -0.5;	b[0] = mreal(1.5)*(v[1]-v[0])/(x[1]-x[0]);
+	for(long i=1;i<n-1;i++)
+	{
+		mreal h0 = x[i]-x[i-1], h1 = x[i+1]-x[i];
+		Treal r = mreal(1)/(2/h0+2/h1 + a[i-1]/h0);
+		a[i] = - r/h1;
+		b[i] = ((3/h0/h0)*(v[i]-v[i-1]) + (1/h1/h1)*(v[i+1]-v[i]) + a[i-1]/h0)*r;
+	}
+	b[n-1] = ( (6/(x[n-1]-x[n-2]))*(v[n-1]-v[n-2]) - mreal(2)*b[n-2] )/(mreal(4)+mreal(2)*a[n-2]);
+	for(long i=n-2;i>=0;i--)	b[i] += a[i]*b[i+1];
+	// no spline coefficients
+	for(long i=0;i<n-1;i++)
+	{
+		c[5*i+2] = b[i];
+		mreal h = 1/(x[i+1]-x[i]), h2 = h*h;
+		c[5*i+3] = (3*h2)*(v[i+1]-v[i]) - (b[i+1]+b[i]+b[i])*h;
+		c[5*i+4] = (2*h2*h)*(v[i]-v[i+1]) + (b[i+1]+b[i])*h2;
+	}
+	delete []a;	delete []b;
+}
+//-----------------------------------------------------------------------------
diff --git a/src/mpi.cpp b/src/mpi.cpp
new file mode 100644
index 0000000..c6dfb8a
--- /dev/null
+++ b/src/mpi.cpp
@@ -0,0 +1,50 @@
+#include "mgl2/mpi.h"
+#include "mgl2/canvas.h"
+#include <mpi.h>
+#define MCW		MPI_COMM_WORLD
+#define TAG_DATA_Z	0
+#define TAG_DATA_C	1
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_mpi_send(HMGL gr, int id)
+{
+	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(!g)	return;
+	g->Finish();
+	long n = g->GetWidth()*g->GetHeight();
+	MPI_Send(g->Z,3*n,MPI_FLOAT,id,TAG_DATA_Z,MCW);
+	MPI_Send(g->C,12*n,MPI_CHAR,id,TAG_DATA_C,MCW);
+	MPI_Send(g->OI,n,MPI_INT,id,TAG_DATA_C,MCW);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_mpi_recv(HMGL gr, int id)
+{
+	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(!g)	return;
+	g->Finish();
+	MPI_Status status;
+	long w = g->GetWidth(), h = g->GetHeight(), n = w*h;
+	float *zz = new float[3*n];
+	int *oi = new int[n];
+	unsigned char *cc = new unsigned char[12*n];
+	MPI_Recv(zz,3*n,MPI_FLOAT,id,TAG_DATA_Z,MCW,&status);
+	MPI_Recv(cc,12*n,MPI_CHAR,id,TAG_DATA_C,MCW,&status);
+	MPI_Recv(oi,n,MPI_INT,id,TAG_DATA_C,MCW,&status);
+	// NOTE: No need for check errors. The matter is MPI docs:
+	// "All MPI routines return an error value. Before the value is returned,
+	// the current MPI error handler is called. By default, this error handler aborts the MPI job."
+#pragma omp parallel for
+	for(long k=0;k<n;k++)
+	{	// i0=x+Width*(Height-1-y)
+		long i = k%w, j = h-1-(k/w);
+		if(g->GetQuality()&MGL_DRAW_NORM)
+		{
+			g->pnt_plot(i,j,zz[3*k+2],cc+12*k+8,oi[k]);
+			g->pnt_plot(i,j,zz[3*k+1],cc+12*k+4,oi[k]);
+		}
+		g->pnt_plot(i,j,zz[3*k],cc+12*k,oi[k]);
+	}
+	g->set(MGL_FINISHED);
+	delete []oi; 	delete []zz; 	delete []cc;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_mpi_send_(uintptr_t *gr, int *id)	{	mgl_mpi_send(_GR_, *id);	}
+void MGL_EXPORT mgl_mpi_recv_(uintptr_t *gr, int *id)	{	mgl_mpi_recv(_GR_, *id);	}
+//-----------------------------------------------------------------------------
diff --git a/src/obj.cpp b/src/obj.cpp
new file mode 100644
index 0000000..2aa1a49
--- /dev/null
+++ b/src/obj.cpp
@@ -0,0 +1,959 @@
+/***************************************************************************
+ * obj.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <time.h>
+#include "mgl2/canvas.h"
+#include "mgl2/canvas_cf.h"
+#undef _GR_
+#define _GR_	((mglCanvas *)(*gr))
+#define _Gr_	((mglCanvas *)(gr))
+int MGL_NO_EXPORT mgl_tga_save(const char *fname, int w, int h, unsigned char **p);
+int MGL_NO_EXPORT mgl_pnga_save(const char *fname, int w, int h, unsigned char **p);
+void MGL_NO_EXPORT mgl_printf(void *fp, bool gz, const char *str, ...);
+//-----------------------------------------------------------------------------
+#include <climits>
+#include <cassert>
+#include <float.h>
+#include <math.h>
+
+#include <deque>
+#include <map>
+#include <iostream>
+
+/* Size prefixes for printf/scanf for size_t and ptrdiff_t */
+#ifdef _MSC_VER
+#      define PRIuS "Iu"  /* printf size_t */
+#      define PRIdS "Id"  /* printf ptrdiff_t */
+#else
+#      define PRIuS "zu"  /* printf size_t */
+#      define PRIdS "zd"  /* printf ptrdiff_t */
+#endif
+
+//-----------------------------------------------------------------------------
+void mglTexture::GetRGBAOBJ(unsigned char *f) const
+{
+	const size_t bw = 128; //border width
+	for(size_t i=0;i<256;i++)
+	{
+		mglColor c1 = col[2*i], c2 = col[2*i+1], c;
+		for(size_t j=0;j<512;j++)
+		{
+			size_t i0 = 4*(j+512*(255-i));
+			if (j<bw)
+				c = c1;
+			else if (j>511-bw)
+				c = c2;
+			else
+				c = c1 + (c2-c1)*((j-bw)/(255.));
+			f[i0]   = int(255*c.r);
+			f[i0+1] = int(255*c.g);
+			f[i0+2] = int(255*c.b);
+			f[i0+3] = int(255*c.a);
+		}
+	}
+}
+
+//-----------------------------------------------------------------------------
+
+struct ObjUV
+{
+  ObjUV() :
+  u(0.0), v(0.0) {}
+  ObjUV(mreal U, mreal V) :
+  u(U), v(V) {}
+  mreal u;
+  mreal v;
+
+  void Set(mreal U, mreal V)
+  { u = U; v = V; }
+
+  bool operator==(const ObjUV &c) const
+  {
+    return u==c.u && v==c.v;
+  }
+  bool operator!=(const ObjUV &c) const
+  {
+    return !(u==c.u && v==c.v);
+  }
+  bool operator<(const ObjUV &c) const
+  {
+    if(u!=c.u)
+      return (u<c.u);
+    return (v<c.v);
+  }
+  friend std::ostream& operator << (std::ostream& out, const ObjUV& c)
+  {
+    out << "vt " << c.u << " " << c.v << "\n";
+    return out;
+  }
+};
+
+struct ObjUVs {
+	std::map<ObjUV,size_t> texturecoords;
+  FILE* const fp;
+  ObjUVs(FILE *f) : fp(f) {}
+
+  size_t addTextureCoords(mreal ta, mreal c, size_t ntxt)
+	{
+    const mreal gap = 1./512;
+    const mreal u = 0.25+0.5*(ta*(1-2*gap)+gap);
+    const mreal v = ((c-floor(c))*(1-2*gap) + gap + floor(c))/ntxt;
+
+    const ObjUV point(u, v);
+    std::map<ObjUV,size_t>::iterator pPoint = texturecoords.find(point);
+    if(pPoint!=texturecoords.end())
+      return pPoint->second;
+    else
+    {
+      const size_t point_index = texturecoords.size()+1;
+      texturecoords.insert(std::make_pair(point,point_index));
+      fprintf(fp,"vt %.15g %.15g\n",u,v);
+
+      return point_index;
+    }
+	}
+
+};
+
+
+class ObjXYZ
+{
+  public :
+  mreal x;
+  mreal y;
+  mreal z;
+  ObjXYZ() :
+  x(0), y(0), z(0) {}
+  ObjXYZ(mreal fx, mreal fy, mreal fz) :
+  x(fx), y(fy), z(fz) {}
+
+  void Set(mreal fx, mreal fy, mreal fz)
+  { x = fx; y = fy; z = fz; }
+  mreal Dot(const ObjXYZ & sPt) const
+  { return(x*sPt.x)+(y*sPt.y)+(z*sPt.z); }
+  mreal LengthSquared()
+  { return(x*x+y*y+z*z); }
+
+  friend ObjXYZ operator + (const ObjXYZ& a, const ObjXYZ& b)
+  { return ObjXYZ(a.x+b.x,a.y+b.y,a.z+b.z); }
+  friend ObjXYZ operator - (const ObjXYZ& a)
+  { return ObjXYZ(-a.x,-a.y,-a.z); }
+  friend ObjXYZ operator - (const ObjXYZ& a, const ObjXYZ& b)
+  { return ObjXYZ(a.x-b.x,a.y-b.y,a.z-b.z); }
+  friend ObjXYZ operator * (const ObjXYZ& a, const mreal d)
+  { return ObjXYZ(a.x*d,a.y*d,a.z*d); }
+  friend ObjXYZ operator * (const mreal d, const ObjXYZ& a)
+  { return ObjXYZ(a.x*d,a.y*d,a.z*d); }
+  friend ObjXYZ operator / (const ObjXYZ& a, const mreal d)
+  { return ObjXYZ(a.x/d,a.y/d,a.z/d); }
+  friend ObjXYZ operator * (const ObjXYZ& a, const ObjXYZ& b)
+  { return ObjXYZ((a.y*b.z)-(a.z*b.y), (a.z*b.x)-(a.x*b.z), (a.x*b.y)-(a.y*b.x)); }
+
+  mreal Length()
+  {
+    return sqrt(x*x+y*y+z*z);
+  }
+
+  bool Normalize()
+  {
+    mreal fLength=Length();
+    if(fLength < FLT_EPSILON) return false;
+    mreal factor=1.0/fLength;
+    x *= factor;
+    y *= factor;
+    z *= factor;
+    return true;
+  }
+
+  bool operator==(const ObjXYZ &v) const
+  {
+    return x==v.x && y==v.y && z==v.z;
+  }
+  bool operator!=(const ObjXYZ &v) const
+  {
+    return !(x==v.x && y==v.y && z==v.z);
+  }
+  bool operator<(const ObjXYZ &v) const
+  {
+    if(x!=v.x)
+      return (x<v.x);
+    if(y!=v.y)
+      return (y<v.y);
+    return (z<v.z);
+  }
+  friend std::ostream& operator << (std::ostream& out, const ObjXYZ& v)
+  {
+    out << "v " << v.x << " " << v.y << " " << v.z << "\n";
+    return out;
+  }
+};
+
+struct ObjXYZs {
+	std::map<ObjXYZ,size_t> vertexcoords;
+  FILE* const fp;
+  ObjXYZs(FILE *f) : fp(f) {}
+
+	size_t addVertexCoords(mreal x, mreal y, mreal z)
+	{
+		const ObjXYZ point(x,y,z);
+
+		std::map<ObjXYZ,size_t>::iterator pPoint = vertexcoords.find(point);
+		if(pPoint!=vertexcoords.end())
+			return pPoint->second;
+		else
+		{
+			const size_t point_index = vertexcoords.size()+1;
+			vertexcoords.insert(std::make_pair(point,point_index));
+      fprintf(fp,"v %.15g %.15g %.15g\n",x,y,z);
+
+			return point_index;
+		}
+	}
+
+};
+
+struct ObjTriangle {
+  size_t p1, p2, p3;
+  size_t t1, t2, t3;
+  ObjTriangle() :
+    p1(0), p2(0), p3(0), t1(0), t2(0), t3(0) {}
+  ObjTriangle(size_t P1, size_t T1, size_t P2, size_t T2, size_t P3, size_t T3) :
+    p1(P1), p2(P2), p3(P3), t1(T1), t2(T2), t3(T3) {}
+};
+
+struct ObjLine {
+  size_t p1, p2;
+  ObjLine() :
+  p1(0), p2(0) {}
+  ObjLine(size_t P1, size_t P2) :
+  p1(P1), p2(P2) {}
+};
+
+struct ObjGroup {
+  std::deque<ObjTriangle> triangles;
+  mglColor commoncolor;
+  bool samecolor;
+  std::map<size_t, std::deque<ObjLine> > lines;
+  std::map<size_t, std::deque<size_t> > points;
+  FILE* const fp;
+  ObjXYZs &vertexcoords;
+  ObjGroup(FILE *f,ObjXYZs& v) : commoncolor(NC), samecolor(true), fp(f), vertexcoords(v) {}
+
+//  const HMGL gr;
+
+//  ObjGroup(const HMGL g) : samecolor(true),	gr(g) {}
+
+  void addSegment(size_t m, size_t p1, size_t p2)
+  {
+    lines[m].push_back(ObjLine(p1,p2));
+  }
+  void addLines(size_t m, size_t n, const size_t* p)
+  {
+    for (size_t i=0; i<n-1; i++) {
+      lines[m].push_back(ObjLine(p[i],p[i+1]));
+    }
+  }
+  void addLines(size_t m, size_t n, const mreal P[][3])
+  {
+    if(n==0)	return;
+    size_t *p=new size_t[n];
+    for (size_t i=0; i<n; i++) {
+      p[i] = vertexcoords.addVertexCoords(P[i][0], P[i][1], P[i][2]);
+    }
+    for (size_t i=0; i<n-1; i++) {
+      lines[m].push_back(ObjLine(p[i],p[i+1]));
+    }
+    delete []p;
+  }
+
+  void addPoint(size_t m, size_t p)
+  {
+    points[m].push_back(p);
+  }
+  void addTriangle(size_t p1, size_t t1, size_t p2, size_t t2, size_t p3, size_t t3)
+  {
+    triangles.push_back(ObjTriangle(p1,t1,p2,t2,p3,t3));
+  }
+  void addMonoTriangle(size_t t1, size_t p1, size_t p2, size_t p3)
+  {
+    triangles.push_back(ObjTriangle(p1,t1,p2,t1,p3,t1));
+  }
+  void addColourInfo(const mglPnt& p)
+	{
+		const mglColor color(p.r,p.g,p.b,p.a);
+
+    if (samecolor) {
+      if (commoncolor == NC) {
+        commoncolor = color;
+      } else {
+        if (commoncolor != color)
+          samecolor = false;
+      }
+    }
+  }
+  void writeLines() {
+    for(std::map<size_t, std::deque<ObjLine> >::const_iterator pm = lines.begin(); pm != lines.end(); pm++)
+    {
+      fprintf(fp,"usemtl Material%" PRIuS "\n", pm->first);
+      for(std::deque<ObjLine>::const_iterator pl = pm->second.begin(); pl != pm->second.end(); pl++)
+        fprintf(fp,"l %" PRIuS " %" PRIuS "\n", pl->p1, pl->p2);
+      }
+  }
+  void writePoints() {
+    for(std::map<size_t, std::deque<size_t> >::const_iterator pm = points.begin(); pm != points.end(); pm++)
+    {
+      fprintf(fp,"usemtl Material%" PRIuS "\n", pm->first);
+      for(std::deque<size_t>::const_iterator pp = pm->second.begin(); pp != pm->second.end(); pp++)
+        fprintf(fp,"p %" PRIuS "\n", *pp);
+    }
+  }
+  void writeTriangles() {
+    for(std::deque<ObjTriangle>::const_iterator pt = triangles.begin(); pt != triangles.end(); pt++)
+      fprintf(fp,"f %" PRIuS " %" PRIuS " %" PRIuS "\n", pt->p1, pt->p2, pt->p3);
+  }
+  void writeTexturedTriangles() {
+    for(std::deque<ObjTriangle>::const_iterator pt = triangles.begin(); pt != triangles.end(); pt++)
+      fprintf(fp,"f %" PRIuS "/%" PRIuS " %" PRIuS "/%" PRIuS " %" PRIuS "/%" PRIuS "\n", pt->p1,pt->t1, pt->p2,pt->t2, pt->p3,pt->t3);
+  }
+};
+
+struct lt_mglColor
+{
+  bool operator()(const mglColor& c1, const mglColor& c2) const
+  {
+    if(c1.r!=c2.r)
+      return (c1.r<c2.r);
+    if(c1.g!=c2.g)
+      return (c1.g<c2.g);
+    if(c1.b!=c2.b)
+      return (c1.b<c2.b);
+    if(c1.a!=c2.a)
+      return (c1.a<c2.a);
+    return false;
+  }
+};
+
+typedef std::map<mglColor,size_t,lt_mglColor> colormap;
+
+
+struct ObjMaterials {
+	colormap materialmap;
+  FILE* const fp;
+  ObjMaterials(FILE *f) : fp(f) {}
+
+	size_t addColor(const mglColor& color)
+	{
+		colormap::iterator pc = materialmap.find(color);
+		if(pc!=materialmap.end())
+			return pc->second;
+		else
+		{
+			const size_t color_index = materialmap.size();
+			materialmap.insert(std::make_pair(color,color_index));
+      fprintf(fp,"newmtl Material%" PRIuS "\n", color_index);
+      fprintf(fp,"Ka 0.1 0.1 0.1\n");
+      fprintf(fp,"Kd %g %g %g\n", color.r, color.g, color.b);
+      fprintf(fp,"Ks 0.0 0.0 0.0\n");
+      fprintf(fp,"d %g\nillum 2\nNs 15.0\n",color.a);
+
+			return color_index;
+		}
+	}
+	size_t addColor(mreal r, mreal g, mreal b, mreal a)
+	{
+		const mglColor color(r,g,b,a);
+    return addColor(color);
+  }
+	size_t addColorInfo(const mglPnt& p)
+	{
+		return addColor(p.r,p.g,p.b,p.a);
+  }
+};
+
+size_t MGL_LOCAL_CONST power_of_two(size_t input)
+{
+	size_t value = 1;
+	while ( value < input )	value <<= 1;
+	return value;
+}
+
+void MGL_EXPORT mgl_write_obj(HMGL gr, const char *fname,const char *descr, int use_png)
+{
+	if(gr->GetPrmNum()==0)	return;	// nothing to do
+
+	{
+		long mmin=0,mmax=0,m;
+		for(size_t i=0;i<gr->Grp.size();i++)	// prepare array of indirect indexing
+		{	m = gr->Grp[i].Id;	if(m<mmin) mmin=m;	if(m>mmax) mmax=m;	}
+		long *ng = new long[mmax-mmin+1];
+		for(size_t i=0;i<gr->Grp.size();i++)	ng[gr->Grp[i].Id-mmin] = i;
+		for(size_t i=0;i<size_t(gr->GetPrmNum());i++)	// collect data for groups
+		// it is rather expensive (extra 4b per primitive) but need for export to 3D
+		{
+			m = gr->GetPrm(i,false).id-mmin;
+			if(m>=0 && m<mmax-mmin+1)	gr->Grp[ng[m]].p.push_back(i);
+		}
+		delete []ng;
+	}
+
+	const size_t len=strlen(fname);
+	const size_t ntxt=gr->GetTxtNum();
+	const size_t Ntxt=power_of_two(ntxt);
+	const size_t pntnum = gr->GetPntNum();
+	char *tname = new char[len+5];	strcpy(tname,fname);
+	FILE *fp=fopen(fname,"wt");
+	ObjXYZs vertexcoords(fp);
+	std::vector<size_t> vcs(pntnum); // vertex coord ids
+	ObjUVs texturecoords(fp);
+	std::vector<size_t> tcs(pntnum); // texture coord ids
+
+	// center point
+	mglPnt p0;
+	const mreal width  = dynamic_cast<mglCanvas *>(gr)->GetWidth();
+	const mreal height = dynamic_cast<mglCanvas *>(gr)->GetHeight();
+	const mreal depth  = sqrt(width*height);
+
+	p0.x = width/2.;
+	p0.y = height/2.;
+	p0.z = (1.f-sqrt(width*height)/(2*depth))*depth;
+
+	// vertices definition
+	fprintf(fp,"# Created by MathGL library\n# Title: %s\n",(descr && *descr) ? descr : fname);
+	for(size_t i=0;i<pntnum;i++)
+	{
+		const mglPnt &pp = gr->GetPnt(i);
+		vcs[i] = vertexcoords.addVertexCoords(pp.x-p0.x, pp.y-p0.y, pp.z-p0.z);
+		tcs[i] = texturecoords.addTextureCoords(pp.ta, pp.c, Ntxt);
+	}
+
+  // prepare MTL file
+	tname[len-4]='.';	tname[len-3]='m';	tname[len-2]='t';	tname[len-1]='l';
+	FILE *fpmat=fopen(tname,"wt");
+	tname[len-4]='\0';
+	fprintf(fpmat,"newmtl Material\n");
+	fprintf(fpmat,"Ka 0.0 0.0 0.0\n");
+	fprintf(fpmat,"Kd 1.0 1.0 1.0\n");
+	fprintf(fpmat,"Ks 0.0 0.0 0.0\n");
+	fprintf(fpmat,"d 1.0\nillum 2\n");
+	if(use_png)
+		fprintf(fpmat,"map_Kd %s_txt.png\n",tname);
+	else
+		fprintf(fpmat,"map_Kd %s_txt.tga\n",tname);
+	if(use_png)
+		strcat(tname,"_txt.png");
+	else
+		strcat(tname,"_txt.tga");
+	// prepare texture file (TGA or PNG)
+	const size_t txtwidth = 512;
+	unsigned char *buf = new unsigned char[4*256*txtwidth*Ntxt];
+	unsigned char **pbuf= (unsigned char **)malloc(256*Ntxt*sizeof(unsigned char *));
+	for(size_t i=0;i<256*Ntxt;i++)	pbuf[i] = buf+4*txtwidth*i;
+	for(size_t i=0;i<ntxt;i++)	gr->GetTxt(i).GetRGBAOBJ(buf+(Ntxt-1-i)*256*txtwidth*4);
+	for(size_t i=ntxt;i<Ntxt;i++)
+	{
+		unsigned char *f=buf+(Ntxt-1-i)*256*txtwidth*4;
+		const mglColor& c=BC;
+		for(size_t k=0;k<256;k++)
+		{
+		for(size_t l=0;l<txtwidth;l++)
+		{
+			*f++ = int(255*c.r);
+			*f++ = int(255*c.g);
+			*f++ = int(255*c.b);
+			*f++ = int(255*c.a);
+		}
+		}
+	}
+	if(use_png)
+		mgl_pnga_save(tname,txtwidth,256*Ntxt,pbuf);
+	else
+		mgl_tga_save(tname,txtwidth,256*Ntxt,pbuf);
+	free(pbuf);
+	delete []buf;
+
+	ObjMaterials materials(fpmat);
+
+	// primitive definition in groups
+
+	tname[len-4]='\0';
+	fprintf(fp,"# Primitives Definitions\nmtllib %s.mtl\n",tname);
+	for(size_t i=0;i<gr->Grp.size();i++)
+	{
+		std::vector<long> &p = gr->Grp[i].p;
+		ObjGroup grp(fp, vertexcoords);
+		for(size_t j=0;j<p.size();j++)
+		{
+			const mglPrim &q = gr->GetPrm(p[j],false);
+
+			long n1=q.n1,n2=q.n2,n3=q.n3,n4=q.n4;
+			switch(q.type)
+			{
+				case 0:
+				if (gr->GetPnt(q.n1).a > mgl_min_a) {
+				const mglPnt p = gr->GetPnt(q.n1) - p0;
+				const mreal size = q.s;
+				const char type = q.n4;
+				mreal ss=size;
+				const mglColor c(p.r, p.g, p.b, p.a);
+
+				if(!strchr("xsSoO",type))	ss *= 1.1;
+				if(type=='.' || ss==0)
+				{
+					const size_t m = materials.addColor(c);
+					grp.addPoint(m, vcs[n1]);
+				}
+				else
+				switch(type)
+				{
+					case 'P':
+					{
+						const size_t m = materials.addColor(c);
+						const mreal P[5][3] =
+						{
+						{ p.x-ss,p.y-ss,p.z },
+						{ p.x+ss,p.y-ss,p.z },
+						{ p.x+ss,p.y+ss,p.z },
+						{ p.x-ss,p.y+ss,p.z },
+						{ p.x-ss,p.y-ss,p.z }
+						};
+						grp.addLines(m, 5, P);
+					}
+					case '+':
+					{
+						const size_t m = materials.addColor(c);
+						const mreal P1[2][3] =
+						{
+						{ p.x-ss,p.y,p.z },
+						{ p.x+ss,p.y,p.z }
+						};
+						grp.addLines(m, 2, P1);
+						const mreal P2[2][3] =
+						{
+						{ p.x,p.y-ss,p.z },
+						{ p.x,p.y+ss,p.z }
+						};
+						grp.addLines(m, 2, P2);
+					}
+						break;
+					case 'X':
+					{
+						const size_t m = materials.addColor(c);
+						const mreal P[5][3] =
+						{
+						{ p.x-ss,p.y-ss,p.z },
+						{ p.x+ss,p.y-ss,p.z },
+						{ p.x+ss,p.y+ss,p.z },
+						{ p.x-ss,p.y+ss,p.z },
+						{ p.x-ss,p.y-ss,p.z }
+						};
+						grp.addLines(m, 5, P);
+						const mreal P1[2][3] =
+						{
+						{ p.x-ss,p.y-ss,p.z },
+						{ p.x+ss,p.y+ss,p.z }
+						};
+						grp.addLines(m, 2, P1);
+						const mreal P2[2][3] =
+						{
+						{ p.x+ss,p.y-ss,p.z },
+						{ p.x-ss,p.y+ss,p.z }
+						};
+						grp.addLines(m, 2, P2);
+					}
+						break;
+					case 'x':
+					{
+						const size_t m = materials.addColor(c);
+						const mreal P1[2][3] =
+						{
+						{ p.x-ss,p.y-ss,p.z },
+						{ p.x+ss,p.y+ss,p.z }
+						};
+						grp.addLines(m, 2, P1);
+						const mreal P2[2][3] =
+						{
+						{ p.x+ss,p.y-ss,p.z },
+						{ p.x-ss,p.y+ss,p.z }
+						};
+						grp.addLines(m, 2, P2);
+					}
+						break;
+					case 'S':
+					{
+						const size_t ti = tcs[n1]; grp.addColourInfo(p);
+
+						const size_t pi1 = vertexcoords.addVertexCoords(p.x-ss,p.y-ss,p.z);
+						const size_t pi2 = vertexcoords.addVertexCoords(p.x+ss,p.y-ss,p.z);
+						const size_t pi3 = vertexcoords.addVertexCoords(p.x-ss,p.y+ss,p.z);
+						const size_t pi4 = vertexcoords.addVertexCoords(p.x+ss,p.y+ss,p.z);
+
+						grp.addTriangle(pi1, ti, pi2, ti, pi3, ti);
+						grp.addTriangle(pi4, ti, pi3, ti, pi2, ti);
+					}
+						break;
+					case 's':
+					{
+						const size_t m = materials.addColor(c);
+						const mreal P[5][3] =
+						{
+						{ p.x-ss,p.y-ss,p.z },
+						{ p.x+ss,p.y-ss,p.z },
+						{ p.x+ss,p.y+ss,p.z },
+						{ p.x-ss,p.y+ss,p.z },
+						{ p.x-ss,p.y-ss,p.z }
+						};
+						grp.addLines(m, 5, P);
+					}
+						break;
+					case 'D':
+					{
+						const size_t ti = tcs[n1]; grp.addColourInfo(p);
+
+						const size_t pi1 = vertexcoords.addVertexCoords(p.x,p.y-ss,p.z);
+						const size_t pi2 = vertexcoords.addVertexCoords(p.x+ss,p.y,p.z);
+						const size_t pi3 = vertexcoords.addVertexCoords(p.x-ss,p.y,p.z);
+						const size_t pi4 = vertexcoords.addVertexCoords(p.x,p.y+ss,p.z);
+
+						grp.addTriangle(pi1, ti, pi2, ti, pi3, ti);
+						grp.addTriangle(pi4, ti, pi3, ti, pi2, ti);
+					}
+						break;
+					case 'd':
+					{
+						const size_t m = materials.addColor(c);
+						const mreal P[5][3] =
+						{
+						{ p.x,p.y-ss,p.z },
+						{ p.x+ss,p.y,p.z },
+						{ p.x,p.y+ss,p.z },
+						{ p.x-ss,p.y,p.z },
+						{ p.x,p.y-ss,p.z }
+						};
+						grp.addLines(m, 5, P);
+					}
+						break;
+					case 'Y':
+					{
+						const size_t m = materials.addColor(c);
+						const mreal P1[3][3] =
+						{
+						{ p.x,			 p.y-ss,		p.z },
+						{ p.x,			 p.y,			 p.z },
+						{ p.x+0.8*ss,p.y+0.6*ss,p.z }
+						};
+						grp.addLines(m, 3, P1);
+						const mreal P2[2][3] =
+						{
+						{ p.x,			 p.y,			 p.z },
+						{ p.x-0.8*ss,p.y+0.6*ss,p.z }
+						};
+						grp.addLines(m, 2, P2);
+					}
+						break;
+					case '*':
+					{
+						const size_t m = materials.addColor(c);
+						const mreal P1[2][3] =
+						{
+						{ p.x-ss,p.y,p.z },
+						{ p.x+ss,p.y,p.z }
+						};
+						grp.addLines(m, 2, P1);
+						const mreal P2[2][3] =
+						{
+						{ p.x-0.6*ss,p.y-0.8*ss,p.z },
+						{ p.x+0.6*ss,p.y+0.8*ss,p.z }
+						};
+						grp.addLines(m, 2, P2);
+						const mreal P3[2][3] =
+						{
+						{ p.x-0.6*ss,p.y+0.8*ss,p.z },
+						{ p.x+0.6*ss,p.y-0.8*ss,p.z }
+						};
+						grp.addLines(m, 2, P3);
+
+					}
+						break;
+					case 'T':
+					{
+						const size_t ti = tcs[n1]; grp.addColourInfo(p);
+
+						const size_t pi1 = vertexcoords.addVertexCoords(p.x-ss,p.y-ss/2,p.z);
+						const size_t pi2 = vertexcoords.addVertexCoords(p.x+ss,p.y-ss/2,p.z);
+						const size_t pi3 = vertexcoords.addVertexCoords(p.x,p.y+ss,p.z);
+
+						grp.addTriangle(pi1, ti, pi2, ti, pi3, ti);
+					}
+						break;
+					case '^':
+					{
+						const size_t m = materials.addColor(c);
+						const mreal P[4][3] =
+						{
+						{ p.x-ss,p.y-ss/2,p.z },
+						{ p.x+ss,p.y-ss/2,p.z },
+						{ p.x,	 p.y+ss,	p.z },
+						{ p.x-ss,p.y-ss/2,p.z }
+						};
+						grp.addLines(m, 4, P);
+					}
+						break;
+					case 'V':
+					{
+						const size_t ti = tcs[n1]; grp.addColourInfo(p);
+
+						const size_t pi1 = vertexcoords.addVertexCoords(p.x-ss,p.y+ss/2,p.z);
+						const size_t pi2 = vertexcoords.addVertexCoords(p.x,p.y-ss,p.z);
+						const size_t pi3 = vertexcoords.addVertexCoords(p.x+ss,p.y+ss/2,p.z);
+
+						grp.addTriangle(pi1, ti, pi2, ti, pi3, ti);
+					}
+						break;
+					case 'v':
+					{
+						const size_t m = materials.addColor(c);
+						const mreal P[4][3] =
+						{
+						{ p.x-ss,p.y+ss/2,p.z },
+						{ p.x+ss,p.y+ss/2,p.z },
+						{ p.x,	 p.y-ss,	p.z },
+						{ p.x-ss,p.y+ss/2,p.z }
+						};
+						grp.addLines(m, 4, P);
+					}
+						break;
+					case 'L':
+					{
+						const size_t ti = tcs[n1]; grp.addColourInfo(p);
+
+						const size_t pi1 = vertexcoords.addVertexCoords(p.x+ss/2,p.y+ss,p.z);
+						const size_t pi2 = vertexcoords.addVertexCoords(p.x-ss,	p.y,	 p.z);
+						const size_t pi3 = vertexcoords.addVertexCoords(p.x+ss/2,p.y-ss,p.z);
+
+						grp.addTriangle(pi1, ti, pi2, ti, pi3, ti);
+					}
+						break;
+					case '<':
+					{
+						const size_t m = materials.addColor(c);
+						const mreal P[4][3] =
+						{
+						{ p.x+ss/2,p.y+ss,p.z },
+						{ p.x+ss/2,p.y-ss,p.z },
+						{ p.x-ss,	p.y,	 p.z },
+						{ p.x+ss/2,p.y+ss,p.z }
+						};
+						grp.addLines(m, 4, P);
+					}
+						break;
+					case 'R':
+					{
+						const size_t ti = tcs[n1]; grp.addColourInfo(p);
+
+						const size_t pi1 = vertexcoords.addVertexCoords(p.x-ss/2,p.y+ss,p.z);
+						const size_t pi2 = vertexcoords.addVertexCoords(p.x-ss/2,p.y-ss,p.z);
+						const size_t pi3 = vertexcoords.addVertexCoords(p.x+ss,	p.y,	 p.z);
+
+						grp.addTriangle(pi1, ti, pi2, ti, pi3, ti);
+					}
+						break;
+					case '>':
+					{
+						const size_t m = materials.addColor(c);
+						const mreal P[4][3] =
+						{
+						{ p.x-ss/2,p.y+ss,p.z },
+						{ p.x-ss/2,p.y-ss,p.z },
+						{ p.x+ss,	p.y,	 p.z },
+						{ p.x-ss/2,p.y+ss,p.z }
+						};
+						grp.addLines(m, 4, P);
+					}
+						break;
+					case 'O':
+					{
+						const size_t ti = tcs[n1]; grp.addColourInfo(p);
+
+						const size_t cpi=vertexcoords.addVertexCoords(p.x, p.y, p.z);
+						size_t pnti[21];
+						for(size_t k=0;k<=20;k++)
+						pnti[k]=vertexcoords.addVertexCoords(p.x+ss*cos(k*M_PI/10),p.y+ss*sin(k*M_PI/10),p.z);
+						for(size_t k=0;k<20;k++) {
+						grp.addTriangle(pnti[k], ti, pnti[k+1], ti, cpi, ti);
+						}
+					}
+						break;
+					case 'C':
+					{
+						const size_t m = materials.addColor(c);
+						grp.addPoint(m, vcs[n1]);
+					}
+					case 'o':
+					{
+						const size_t m = materials.addColor(c);
+						mreal P[21][3];
+						for(size_t k=0;k<=20;k++) {
+						P[k][0] = p.x+ss*cos(k*M_PI/10);
+						P[k][1] = p.y+ss*sin(k*M_PI/10);
+						P[k][2] = p.z;
+						}
+						grp.addLines(m, 21, P);
+					}
+						break;
+					}
+				}
+				break;
+				case 1:
+				if (gr->GetPnt(q.n1).a > mgl_min_a || gr->GetPnt(q.n2).a > mgl_min_a) {
+				const mglPnt& p1 = gr->GetPnt(q.n1);
+				const mglPnt& p2 = gr->GetPnt(q.n2);
+				const size_t m = materials.addColor((p1.r+p2.r)/2, (p1.g+p2.g)/2, (p1.b+p2.b)/2, (p1.a+p2.a)/2);
+				grp.addSegment(m, vcs[n1], vcs[n2]);
+				}
+				break;
+				case 2:
+				if (gr->GetPnt(q.n1).a > mgl_min_a || gr->GetPnt(q.n2).a > mgl_min_a || gr->GetPnt(q.n3).a > mgl_min_a) {
+				grp.addTriangle(vcs[n1],tcs[n1], vcs[n2],tcs[n2], vcs[n3],tcs[n3]);
+				grp.addColourInfo(gr->GetPnt(n1));
+				grp.addColourInfo(gr->GetPnt(n2));
+				grp.addColourInfo(gr->GetPnt(n3));
+				}
+				break;
+				case 3:
+				if (gr->GetPnt(q.n1).a > mgl_min_a || gr->GetPnt(q.n2).a > mgl_min_a || gr->GetPnt(q.n3).a > mgl_min_a || gr->GetPnt(q.n4).a > mgl_min_a) {
+				grp.addTriangle(vcs[n1],tcs[n1], vcs[n2],tcs[n2], vcs[n3],tcs[n3]);
+				grp.addTriangle(vcs[n2],tcs[n2], vcs[n4],tcs[n4], vcs[n3],tcs[n3]);
+				grp.addColourInfo(gr->GetPnt(n1));
+				grp.addColourInfo(gr->GetPnt(n2));
+				grp.addColourInfo(gr->GetPnt(n3));
+				grp.addColourInfo(gr->GetPnt(n4));
+				}
+				break;
+				case 4:
+				{
+				const mglPnt p = gr->GetPnt(q.n1) - p0;
+
+				const mreal f = q.p/2, dx=p.u/2, dy=p.v/2;
+				const mreal c=q.s*cos(q.w*M_PI/180), s=-q.s*sin(q.w*M_PI/180);
+				const double b[4] = {c,-s, s,c};
+				long ik,il=0;
+
+				const mglGlyph &g = gr->GetGlf(q.n4);
+				const mreal dd = 0.004;
+				if(q.n3&8)
+				{
+					const size_t p_4 = vertexcoords.addVertexCoords(p.x+b[0]*dx+b[1]*(dy-dd),p.y+b[2]*dx+b[3]*(dy-dd),p.z);
+					const size_t p_3 = vertexcoords.addVertexCoords(p.x+b[0]*dx+b[1]*(dy+dd),p.y+b[2]*dx+b[3]*(dy+dd),p.z);
+					const size_t p_2 = vertexcoords.addVertexCoords(p.x+b[0]*(dx+f)+b[1]*(dy-dd),p.y+b[2]*dx+b[3]*(dy-dd),p.z);
+					const size_t p_1 = vertexcoords.addVertexCoords(p.x+b[0]*(dx+f)+b[1]*(dy+dd),p.y+b[2]*dx+b[3]*(dy+dd),p.z);
+
+					if(!(q.n3&4))	// glyph_line(p,f,true, d);
+					{
+					const size_t ti = tcs[n1]; grp.addColourInfo(p);
+					grp.addMonoTriangle(ti, p_1, p_3, p_2);
+					grp.addMonoTriangle(ti, p_4, p_2, p_3);
+					}
+					else	// glyph_line(p,f,false, d);
+					{
+					const size_t m = materials.addColor(p.r, p.g, p.b, p.a);
+					grp.addSegment(m, p_1, p_2);
+					grp.addSegment(m, p_3, p_4);
+					grp.addSegment(m, p_1, p_3);
+					grp.addSegment(m, p_2, p_4);
+					}
+				}
+				else
+				{
+					if(!(q.n3&4))	// glyph_fill(p,f,g, d);
+					{
+					for(ik=0;ik<g.nt;ik++)
+					{
+						mreal x,y;
+						x = dx+f*g.trig[6*ik];		y = dy+f*g.trig[6*ik+1];
+						const size_t p_3 = vertexcoords.addVertexCoords(p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
+						x = dx+f*g.trig[6*ik+2];	y = dy+f*g.trig[6*ik+3];
+						const size_t p_2 = vertexcoords.addVertexCoords(p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
+						x = dx+f*g.trig[6*ik+4];	y = dy+f*g.trig[6*ik+5];
+						const size_t p_1 = vertexcoords.addVertexCoords(p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
+
+						const size_t ti = tcs[n1]; grp.addColourInfo(p);
+						grp.addMonoTriangle(ti, p_1, p_3, p_2);
+					}
+					}
+					else	// glyph_wire(p,f,g, d);
+					{
+					const size_t m = materials.addColor(p.r, p.g, p.b, p.a);
+					for(ik=0;ik<g.nl;ik++)
+					{
+						mreal x,y;
+						x = g.line[2*ik];	y = g.line[2*ik+1];
+						if(x==0x3fff && y==0x3fff)	// line breakthrough
+						{	il = ik+1;	continue;	}
+						else if(ik==g.nl-1 || (g.line[2*ik+2]==0x3fff && g.line[2*ik+3]==0x3fff))
+						{	// enclose the circle. May be in future this block should be commented
+						x = dx+f*g.line[2*ik];		y = dy+f*g.line[2*ik+1];
+						const size_t p_2 = vertexcoords.addVertexCoords(p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
+						x = dx+f*g.line[2*il];		y = dy+f*g.line[2*il+1];
+						const size_t p_1 = vertexcoords.addVertexCoords(p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
+						grp.addSegment(m, p_1, p_2);
+						}
+						else
+						{	// normal line
+						x = dx+f*g.line[2*ik];		y = dy+f*g.line[2*ik+1];
+						const size_t p_2 = vertexcoords.addVertexCoords(p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
+						x = dx+f*g.line[2*ik+2];	y = dy+f*g.line[2*ik+3];
+						const size_t p_1 = vertexcoords.addVertexCoords(p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
+						grp.addSegment(m, p_1, p_2);
+						}
+
+					}
+					}
+				}
+
+				}
+				break;
+			}
+		}
+		if (!grp.triangles.empty() || !grp.lines.empty() || !grp.points.empty())
+		fprintf(fp,"g %s\n",gr->Grp[i].Lbl.c_str());
+
+		if (!grp.triangles.empty()) {
+		if (grp.samecolor) {
+			fprintf(fp,"usemtl Material%" PRIuS "\n", materials.addColor(grp.commoncolor));
+			grp.writeTriangles();
+		} else {
+			fprintf(fp,"usemtl Material\n");
+			grp.writeTexturedTriangles();
+		}
+		}
+		grp.writeLines();
+		grp.writePoints();
+
+		gr->Grp[i].p.clear();	// we don't need indexes anymore
+	}
+	fclose(fp);
+	fclose(fpmat);
+	delete []tname;
+}
+
+void MGL_EXPORT mgl_write_obj_(uintptr_t *gr, const char *fname,const char *descr, int *use_png,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]='\0';
+	char *d=new char[n+1];	memcpy(d,descr,n);	d[n]='\0';
+	mgl_write_obj(_GR_,s,d,*use_png);	delete []s;		delete []d;	}
+//-----------------------------------------------------------------------------
diff --git a/src/opengl.cpp b/src/opengl.cpp
new file mode 100644
index 0000000..538a099
--- /dev/null
+++ b/src/opengl.cpp
@@ -0,0 +1,487 @@
+#ifdef WIN32
+#include <windows.h>
+#endif
+#ifdef __APPLE__
+#include <OpenGL/gl.h>
+#else
+#include <GL/gl.h>
+#endif
+#include "mgl2/opengl.h"
+#include "mgl2/mgl_cf.h"
+#include <algorithm>
+//-----------------------------------------------------------------------------
+/// Create mglGraph object in OpenGL mode.
+HMGL MGL_EXPORT mgl_create_graph_gl()
+{	return new mglCanvasGL;	}
+/// Create mglGraph object in OpenGL mode.
+uintptr_t MGL_EXPORT mgl_create_graph_gl_()
+{	return uintptr_t(new mglCanvasGL);	}
+//-----------------------------------------------------------------------------
+mglCanvasGL::mglCanvasGL() : mglCanvas(1,1)	{	Clf();	Zoom(0,0,1,1);	}
+//-----------------------------------------------------------------------------
+mglCanvasGL::~mglCanvasGL(){}
+//-----------------------------------------------------------------------------
+void set_pen(unsigned style, mreal width, mreal pos)
+{
+	if(style==0)	return;
+	unsigned long pdef = style*0x100010001;
+	pdef >>= long(32*pos)%32;	// NOTE try to bypass OpenGL limitations
+	style = pdef & 0xffff;
+	width *= 20;
+	if(style!=0xffff)
+	{
+		glEnable(GL_LINE_STIPPLE);
+		glLineStipple(int(width+0.5),style);
+	}
+	else	glDisable(GL_LINE_STIPPLE);
+	if(width>1)	glLineWidth(width);	// NOTE bypass bug on some drivers, where width>1 must be
+	else		glLineWidth(1);
+}
+//-----------------------------------------------------------------------------
+void mglCanvasGL::Finish()
+{
+#if MGL_USE_DOUBLE
+#define MGL_GL_TYPE	GL_DOUBLE
+#else
+#define MGL_GL_TYPE	GL_FLOAT
+#endif
+
+	if(Prm.size()>0)
+	{
+		PreparePrim(0);
+/*		glVertexPointer(3, MGL_GL_TYPE, sizeof(mglPnt), &(Pnt[0].x));	// something wrong with arrays
+		glNormalPointer(MGL_GL_TYPE, sizeof(mglPnt), &(Pnt[0].u));
+		glColorPointer(4, MGL_GL_TYPE, sizeof(mglPnt), &(Pnt[0].r));
+		glEnableClientState(GL_VERTEX_ARRAY);
+		glEnableClientState(GL_NORMAL_ARRAY);
+		glEnableClientState(GL_COLOR_ARRAY);*/
+
+		int pdef=PDef;
+		mreal ss=pPos, ww=PenWidth;
+		mglPrim p;
+		for(size_t i=0;i<Prm.size();i++)
+		{
+			p=GetPrm(i);	PDef=p.n3;	pPos=p.s;	PenWidth=p.w;
+			long n1=p.n1, n2=p.n2, n3=p.n3, n4=p.n4;
+			switch(p.type)
+			{
+/*			case 0:	mark_draw(Pnt[n1],n4,p.s,0);	break;
+			case 1:	line_draw(n1,n2);	break;
+			case 2:	trig_draw(n1,n2,n3);	break;
+			case 3:	quad_draw(n1,n2,n3,n4);	break;*/
+			case 0:	mark_draw(Pnt[n1],n4,p.s,0);	break;
+			case 1:	line_draw(Pnt[n1],Pnt[n2],0);	break;
+			case 2:	trig_draw(Pnt[n1],Pnt[n2],Pnt[n3],true,0);	break;
+			case 3:	quad_draw(Pnt[n1],Pnt[n2],Pnt[n3],Pnt[n4],0);	break;
+			case 4:	glyph_draw(p,0);	break;
+			}
+		}
+		PDef=pdef;	pPos=ss;	PenWidth=ww;
+	}
+	glFinish();
+}
+//-----------------------------------------------------------------------------
+bool mglCanvasGL::Alpha(bool enable)
+{
+	if(enable)
+	{
+		set(MGL_ENABLE_ALPHA);
+		glDisable(GL_DEPTH_TEST);
+		glEnable(GL_ALPHA_TEST);
+		glEnable(GL_BLEND);
+		if((Flag&3)==1)	glBlendFunc(GL_DST_COLOR, GL_ZERO);
+		else if((Flag&3)==2) glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+		else glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	}
+	else
+	{
+		clr(MGL_ENABLE_ALPHA);
+		glEnable(GL_DEPTH_TEST);
+		glDisable(GL_ALPHA_TEST);
+		glDisable(GL_BLEND);
+	}
+	return mglCanvas::Alpha(enable);
+}
+//-----------------------------------------------------------------------------
+void mglCanvasGL::AddLight(int n,mglPoint r,mglPoint d,char cc, mreal br,mreal ap)
+{
+	mglColor c(cc);
+	float amb[4],dif[4],spc[4], pos[4];
+	bool inf = mgl_isnan(r.x);
+	if(n<0 || n>7)	{	SetWarn(mglWarnLId,"AddLight");	return;	}
+	if(c.Valid())
+	{
+		spc[0] = br*c.r;	spc[1] = br*c.g;	spc[2] = br*c.b;
+		amb[0] = AmbBr*c.r;	amb[1] = AmbBr*c.g;	amb[2] = AmbBr*c.b;
+	}
+	else
+	{
+		spc[0] = spc[1] = spc[2] = br;
+		amb[0] = amb[1] = amb[2] = AmbBr;
+	}
+	ap = 90-180*atan(fabs(ap))/M_PI;
+	dif[0] = dif[1] = dif[2] = DifBr;
+	dif[3] = amb[3] = spc[3] = 1.;
+	if(inf)
+	{	pos[0] = d.x;	pos[1] = d.y;	pos[2] = d.z;	pos[3] = 0;	}
+	else
+	{	pos[0] = r.x;	pos[1] = r.y;	pos[2] = r.z;	pos[3] = 1;	}
+
+	glShadeModel(GL_SMOOTH);
+	glLightfv(GL_LIGHT0+n, GL_AMBIENT, amb);
+	glLightfv(GL_LIGHT0+n, GL_DIFFUSE, dif);
+	glLightfv(GL_LIGHT0+n, GL_SPECULAR, spc);
+	glLightfv(GL_LIGHT0+n, GL_POSITION, pos);
+	if(!inf)
+	{
+//		float dir[4]={d.x, d.y, d.z, 0};
+//		glLightfv(GL_LIGHT0+n, GL_SPOT_DIRECTION, dir);
+//		glLightf(GL_LIGHT0+n, GL_SPOT_CUTOFF, ap);
+	}
+	glEnable(GL_LIGHT0+n);
+}
+//-----------------------------------------------------------------------------
+void mglCanvasGL::Light(int n, bool enable)
+{
+	if(enable)	glEnable(GL_LIGHT0+n);
+	else		glDisable(GL_LIGHT0+n);
+}
+//-----------------------------------------------------------------------------
+bool mglCanvasGL::Light(bool enable)
+{
+	if(enable)	{	glEnable(GL_LIGHTING);	glEnable(GL_NORMALIZE);}
+	else		{	glDisable(GL_LIGHTING);	glDisable(GL_NORMALIZE);	}
+	return mglCanvas::Light(enable);
+}
+//-----------------------------------------------------------------------------
+void mglCanvasGL::LightScale(const mglMatrix *M)
+{
+	mglCanvas::LightScale(M);
+	GLenum ll[8] = {GL_LIGHT0,GL_LIGHT1,GL_LIGHT2,GL_LIGHT3,GL_LIGHT4,
+			GL_LIGHT5,GL_LIGHT6,GL_LIGHT7};
+	float pos[4]={0,0,0,0};
+	for(int i=0;i<8;i++)	// NOTE only global light is used in OpenGL mode
+	{
+		pos[0] = light[i].p.x;
+		pos[1] = light[i].p.y;
+		pos[2] = light[i].p.z;
+		if(light[i].n)	glLightfv(ll[i], GL_POSITION, pos);
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvasGL::Zoom(mreal x1, mreal y1, mreal x2, mreal y2)
+{
+	glMatrixMode(GL_PROJECTION);//GL_PROJECTION GL_VIEWPORT GL_MODELVIEW
+	glLoadIdentity();
+	glScaled(x2-x1,y2-y1,1);
+	glTranslated((x1+x2-1)/2,(y1+y2-1)/2,0);
+}
+//-----------------------------------------------------------------------------
+void mglCanvasGL::View(mreal TetX,mreal TetY,mreal TetZ)
+{
+	glMatrixMode(GL_PROJECTION);//GL_PROJECTION GL_VIEWPORT GL_MODELVIEW
+	glRotated(TetX,1.,0.,0.);
+	glRotated(TetY,0.,1.,0.);
+	glRotated(TetZ,0.,0.,1.);
+}
+//-----------------------------------------------------------------------------
+void mglCanvasGL::Fog(mreal d, mreal)
+{
+	if(d>0)
+	{
+		float back[4]={BDef[0]/255.f,BDef[1]/255.f,BDef[2]/255.f,BDef[3]/255.f};
+		glFogf(GL_FOG_MODE,GL_EXP);
+		glFogf(GL_FOG_DENSITY,5*d);
+		glFogfv(GL_FOG_COLOR,back);
+		glEnable(GL_FOG);
+	}
+	else	glDisable(GL_FOG);
+}
+//-----------------------------------------------------------------------------
+void mglCanvasGL::Clf(mglColor Back)
+{
+	mglCanvas::Clf(Back);
+	if(Back==NC)	Back.Set(BDef[0]/255.,BDef[1]/255.,BDef[2]/255.);
+	gl_clf(Back);
+}
+//-----------------------------------------------------------------------------
+void mglCanvasGL::Clf(const char *col)
+{
+	mglCanvas::Clf(col);
+	gl_clf(mglColor(BDef[0]/255.,BDef[1]/255.,BDef[2]/255.));
+}
+//-----------------------------------------------------------------------------
+void mglCanvasGL::gl_clf(mglColor Back)
+{
+	if(Back==NC)	Back = WC;
+//	glDepthFunc(GL_LESS);
+	glDepthFunc(GL_GREATER);
+	glClearColor(Back.r,Back.g,Back.b,1.);
+	glClearDepth(-10.);
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+	glEnable(GL_COLOR_MATERIAL);
+
+	glMatrixMode(GL_MODELVIEW);//GL_MODELVIEW GL_VIEWPORT GL_PROJECTION
+	glLoadIdentity();
+	glScaled(2,2,2);
+	glTranslated(-0.5,-0.5,-0.5);
+
+//	float dif[4]={DifBr,DifBr,DifBr,1};
+//	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, dif);
+	float spc[4]={1,1,1,1};
+	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spc);
+	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, DifBr);
+}
+//-----------------------------------------------------------------------------
+/*void mglCanvasGL::EndFrame()
+{
+//	mglGraph::EndFrame();
+	glEndList();
+}
+//-----------------------------------------------------------------------------
+int mglCanvasGL::NewFrame()
+{
+	Clf();	Identity();
+	glNewList(CurFrameId,GL_COMPILE);
+	CurFrameId++;
+	return CurFrameId-1;
+}*/
+//-----------------------------------------------------------------------------
+unsigned char **mglCanvasGL::GetRGBLines(long &width, long &height, unsigned char *&f, bool alpha)
+{
+	long x, y, d = alpha ? 4:3;
+	GLint w[4];
+	glGetIntegerv(GL_VIEWPORT,w);
+	x=w[0];	y=w[1];	width=w[2];	height=w[3];
+	unsigned char **p;
+
+	p = (unsigned char **)malloc(height * sizeof(unsigned char *));
+	f = (unsigned char *) malloc(width*height * sizeof(unsigned char)*d);
+	for(long i=0;i<height;i++)	p[i] = f+d*width*(height-1-i);
+	glReadBuffer(GL_FRONT);
+	glPixelStorei(GL_PACK_ALIGNMENT, 1);
+	glReadPixels(x, y, width, height, alpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, f);
+	return p;
+}
+//-----------------------------------------------------------------------------
+void mglCanvasGL::quad_draw(long k1, long k2, long k3, long k4)
+{
+	glBegin(GL_QUADS);
+	glArrayElement(k1);	glArrayElement(k2);
+	glArrayElement(k4);	glArrayElement(k3);
+	glEnd();
+}
+//-----------------------------------------------------------------------------
+void mglCanvasGL::trig_draw(long k1, long k2, long k3)
+{
+	glBegin(GL_TRIANGLES);
+	glArrayElement(k1);	glArrayElement(k2);	glArrayElement(k3);
+	glEnd();
+}
+//-----------------------------------------------------------------------------
+void mglCanvasGL::line_draw(long k1, long k2)
+{
+	if(PDef==0)	return;
+	set_pen(PDef,PenWidth, pPos);
+	glBegin(GL_LINES);
+	glArrayElement(k1);	glArrayElement(k2);
+	glEnd();
+}
+//-----------------------------------------------------------------------------
+void mglCanvasGL::quad_draw(const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, const mglPnt &p4, const mglDrawReg *)
+{
+	glBegin(GL_QUADS);
+	glNormal3f(p1.u,p1.v,p1.w);	glColor4f(p1.r,p1.g,p1.b,p1.a);	glVertex3f(p1.x,p1.y,p1.z);
+	glNormal3f(p2.u,p2.v,p2.w);	glColor4f(p2.r,p2.g,p2.b,p2.a);	glVertex3f(p2.x,p2.y,p2.z);
+	glNormal3f(p4.u,p4.v,p4.w);	glColor4f(p4.r,p4.g,p4.b,p4.a);	glVertex3f(p4.x,p4.y,p4.z);
+	glNormal3f(p3.u,p3.v,p3.w);	glColor4f(p3.r,p3.g,p3.b,p3.a);	glVertex3f(p3.x,p3.y,p3.z);
+	glEnd();
+}
+//-----------------------------------------------------------------------------
+void mglCanvasGL::trig_draw(const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, bool, const mglDrawReg *)
+{
+	glBegin(GL_TRIANGLES);
+	glNormal3f(p1.u,p1.v,p1.w);	glColor4f(p1.r,p1.g,p1.b,p1.a);	glVertex3f(p1.x,p1.y,p1.z);
+	glNormal3f(p2.u,p2.v,p2.w);	glColor4f(p2.r,p2.g,p2.b,p2.a);	glVertex3f(p2.x,p2.y,p2.z);
+	glNormal3f(p3.u,p3.v,p3.w);	glColor4f(p3.r,p3.g,p3.b,p3.a);	glVertex3f(p3.x,p3.y,p3.z);
+	glEnd();
+}
+//-----------------------------------------------------------------------------
+void mglCanvasGL::line_draw(const mglPnt &p1, const mglPnt &p2, const mglDrawReg *)
+{
+	if(PDef==0)	return;
+	set_pen(PDef,PenWidth, pPos);
+	glBegin(GL_LINES);
+	glColor4f(p1.r,p1.g,p1.b,p1.a);	glVertex3f(p1.x,p1.y,p1.z);
+	glColor4f(p2.r,p2.g,p2.b,p2.a);	glVertex3f(p2.x,p2.y,p2.z);
+	glEnd();
+}
+//-----------------------------------------------------------------------------
+void mglCanvasGL::pnt_draw(const mglPnt &p1, const mglDrawReg *)
+{
+	glBegin(GL_POINTS);
+	glColor4f(p1.r,p1.g,p1.b,p1.a);	glVertex3f(p1.x,p1.y,p1.z);
+	glEnd();
+}
+//-----------------------------------------------------------------------------
+void mglCanvasGL::mark_draw(const mglPnt &q, char type, mreal size, mglDrawReg *d)
+{
+	mglPnt p0=q,p1=q,p2=q,p3=q;
+	mreal ss=fabs(size);
+
+	if(type=='.' || ss==0)
+	{
+		if(d)	d->PenWidth = ss?ss:sqrt(font_factor/400);
+		pnt_draw(q,d);
+	}
+	else
+	{
+		if(d)
+		{
+			d->PDef = MGL_SOLID_MASK;	d->angle = 0;
+			d->PenWidth*=fabs(50*size);
+			if(d->PenWidth<1)	d->PenWidth=1;
+		}
+		if(!strchr("xsSoO",type))	ss *= 1.1;
+		switch(type)
+		{
+		case 'P':
+			p0.x = q.x-ss;	p0.y = q.y-ss;	p1.x = q.x+ss;	p1.y = q.y-ss;
+			p2.x = q.x+ss;	p2.y = q.y+ss;	p3.x = q.x-ss;	p3.y = q.y+ss;
+			line_draw(p0,p1,d);	line_draw(p1,p2,d);
+			line_draw(p2,p3,d);	line_draw(p3,p0,d);
+		case '+':
+			p0.x = q.x-ss;	p0.y = q.y;	p1.x = q.x+ss;	p1.y = q.y;	line_draw(p0,p1,d);
+			p2.x = q.x;	p2.y = q.y-ss;	p3.x = q.x;	p3.y = q.y+ss;	line_draw(p2,p3,d);
+			break;
+		case 'X':
+			p0.x = q.x-ss;	p0.y = q.y-ss;	p1.x = q.x+ss;	p1.y = q.y-ss;
+			p2.x = q.x+ss;	p2.y = q.y+ss;	p3.x = q.x-ss;	p3.y = q.y+ss;
+			line_draw(p0,p1,d);	line_draw(p1,p2,d);
+			line_draw(p2,p3,d);	line_draw(p3,p0,d);
+		case 'x':
+			p0.x = q.x-ss;	p0.y = q.y-ss;	p1.x = q.x+ss;	p1.y = q.y+ss;	line_draw(p0,p1,d);
+			p2.x = q.x+ss;	p2.y = q.y-ss;	p3.x = q.x-ss;	p3.y = q.y+ss;	line_draw(p2,p3,d);
+			break;
+		case 'S':
+			p0.x = q.x-ss;	p0.y = q.y-ss;	p1.x = q.x-ss;	p1.y = q.y+ss;
+			p2.x= q.x+ss;	p2.y= q.y+ss;	p3.x = q.x+ss;	p3.y = q.y-ss;
+			quad_draw(p0,p1,p3,p2,d);
+		case 's':
+			p0.x = q.x-ss;	p0.y = q.y-ss;	p1.x = q.x+ss;	p1.y = q.y-ss;
+			p2.x = q.x+ss;	p2.y = q.y+ss;	p3.x = q.x-ss;	p3.y = q.y+ss;
+			line_draw(p0,p1,d);	line_draw(p1,p2,d);
+			line_draw(p2,p3,d);	line_draw(p3,p0,d);
+			break;
+		case 'D':
+			p0.x = q.x;	p0.y = q.y-ss;	p1.x = q.x+ss;	p1.y = q.y;
+			p2.x= q.x;	p2.y= q.y+ss;	p3.x = q.x-ss;	p3.y = q.y;
+			quad_draw(p0,p1,p3,p2,d);
+		case 'd':
+			p0.x = q.x;	p0.y = q.y-ss;	p1.x = q.x+ss;	p1.y = q.y;
+			p2.x = q.x;	p2.y = q.y+ss;	p3.x = q.x-ss;	p3.y = q.y;
+			line_draw(p0,p1,d);	line_draw(p1,p2,d);
+			line_draw(p2,p3,d);	line_draw(p3,p0,d);
+			break;
+		case 'Y':
+			p1.x = q.x;	p1.y = q.y-ss;	line_draw(q,p1,d);
+			p2.x = q.x-0.8*ss;	p2.y = q.y+0.6*ss;	line_draw(q,p2,d);
+			p3.x = q.x+0.8*ss;	p3.y = q.y+0.6*ss;	line_draw(q,p3,d);
+			break;
+		case '*':
+			p0.x = q.x-ss;		p0.y = q.y;
+			p1.x = q.x+ss;		p1.y = q.y;	line_draw(p0,p1,d);
+			p0.x = q.x-0.6*ss;	p0.y = q.y-0.8*ss;
+			p1.x = q.x+0.6*ss;	p1.y = q.y+0.8*ss;	line_draw(p0,p1,d);
+			p0.x = q.x-0.6*ss;	p0.y = q.y+0.8*ss;
+			p1.x = q.x+0.6*ss;	p1.y = q.y-0.8*ss;	line_draw(p0,p1,d);
+			break;
+		case 'T':
+			p0.x = q.x-ss;	p0.y = q.y-ss/2;
+			p1.x = q.x+ss;	p1.y = q.y-ss/2;
+			p2.x= q.x;		p2.y= q.y+ss;
+			trig_draw(p0,p1,p2,false,d);
+		case '^':
+			p0.x = q.x-ss;	p0.y = q.y-ss/2;
+			p1.x = q.x+ss;	p1.y = q.y-ss/2;
+			p2.x= q.x;		p2.y= q.y+ss;
+			line_draw(p0,p1,d);	line_draw(p1,p2,d);
+			line_draw(p2,p0,d);	break;
+		case 'V':
+			p0.x = q.x-ss;	p0.y = q.y+ss/2;
+			p1.x = q.x+ss;	p1.y = q.y+ss/2;
+			p2.x= q.x;		p2.y= q.y-ss;
+			trig_draw(p0,p1,p2,false,d);
+		case 'v':
+			p0.x = q.x-ss;	p0.y = q.y+ss/2;
+			p1.x = q.x+ss;	p1.y = q.y+ss/2;
+			p2.x= q.x;		p2.y= q.y-ss;
+			line_draw(p0,p1,d);	line_draw(p1,p2,d);
+			line_draw(p2,p0,d);	break;
+		case 'L':
+			p0.x = q.x+ss/2;	p0.y = q.y+ss;
+			p1.x = q.x+ss/2;	p1.y = q.y-ss;
+			p2.x= q.x-ss;		p2.y= q.y;
+			trig_draw(p0,p1,p2,false,d);
+		case '<':
+			p0.x = q.x+ss/2;	p0.y = q.y+ss;
+			p1.x = q.x+ss/2;	p1.y = q.y-ss;
+			p2.x= q.x-ss;		p2.y= q.y;
+			line_draw(p0,p1,d);	line_draw(p1,p2,d);
+			line_draw(p2,p0,d);	break;
+		case 'R':
+			p0.x = q.x-ss/2;	p0.y = q.y+ss;
+			p1.x = q.x-ss/2;	p1.y = q.y-ss;
+			p2.x= q.x+ss;		p2.y= q.y;
+			trig_draw(p0,p1,p2,false,d);
+		case '>':
+			p0.x = q.x-ss/2;	p0.y = q.y+ss;
+			p1.x = q.x-ss/2;	p1.y = q.y-ss;
+			p2.x= q.x+ss;		p2.y= q.y;
+			line_draw(p0,p1,d);	line_draw(p1,p2,d);
+			line_draw(p2,p0,d);	break;
+		case 'O':
+/*			for(long j=long(-ss);j<=long(ss);j++)	for(long i=long(-ss);i<=long(ss);i++)
+			{
+				long x=long(q.x)+i, y=long(q.y)+j;
+				if(i*i+j*j>=ss*ss || !d || x<d->x1 || x>d->x2 || y<d->y1 || y>d->y2)	continue;
+				pnt_plot(x,y,q.z+1,cs,d->ObjId);
+			}*/
+		case 'o':
+			for(long i=0;i<=20;i++)	// TODO copy from mark_pix()?!
+			{
+				p0 = p1;	p1.x = q.x+ss*cos(i*M_PI/10);	p1.y = q.y+ss*sin(i*M_PI/10);
+				if(i>0)	line_draw(p0,p1,d);
+			}
+			break;
+		case 'C':
+			pnt_draw(q,d);
+			for(long i=0;i<=20;i++)
+			{
+				p0 = p1;	p1.x = q.x+ss*cos(i*M_PI/10);	p1.y = q.y+ss*sin(i*M_PI/10);
+				if(i>0)	line_draw(p0,p1,d);
+			}
+			break;
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvasGL::glyph_fill(mreal phi, const mglPnt &pp, mreal f, const mglGlyph &g, const mglDrawReg *d)
+{
+	if(!g.trig || g.nt<=0)	return;
+	const mreal co=cos(phi*M_PI/180), si=sin(phi*M_PI/180);
+	mglPnt q0=pp, q1=pp, q2=pp;
+	q0.u=q0.v=q1.u=q1.v=q2.u=q2.v=NAN;
+	for(long ik=0;ik<g.nt;ik++)
+	{
+		long ii = 6*ik;	mreal x, y;
+		x = pp.u+g.trig[ii]*f;	y = pp.v+g.trig[ii+1]*f;
+		q0.x = pp.x+(x*co+y*si)/2;	q0.y = pp.y+(y*co-x*si)/2;	ii+=2;
+		x = pp.u+g.trig[ii]*f;	y = pp.v+g.trig[ii+1]*f;
+		q1.x = pp.x+(x*co+y*si)/2;	q1.y = pp.y+(y*co-x*si)/2;	ii+=2;
+		x = pp.u+g.trig[ii]*f;	y = pp.v+g.trig[ii+1]*f;
+		q2.x = pp.x+(x*co+y*si)/2;	q2.y = pp.y+(y*co-x*si)/2;
+		trig_draw(q0,q1,q2,false,d);
+	}
+}
+//-----------------------------------------------------------------------------
diff --git a/src/other.cpp b/src/other.cpp
new file mode 100644
index 0000000..b0c9bb4
--- /dev/null
+++ b/src/other.cpp
@@ -0,0 +1,415 @@
+/***************************************************************************
+ * other.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include "mgl2/other.h"
+#include "mgl2/surf.h"
+#include "mgl2/cont.h"
+#include "mgl2/eval.h"
+#include "mgl2/data.h"
+#include "mgl2/base.h"
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_surf_gen(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT c, HCDT a, const char *sch);
+//-----------------------------------------------------------------------------
+HCDT MGL_NO_EXPORT fill_slice_x(HMGL gr, double sv, HCDT a, mglDataV &xx, mglDataV &yy, mglDataV &zz, mglData &aa)
+{
+	long n=a->GetNx(),m=a->GetNy(),l=a->GetNz();
+	if(l>1)
+	{
+		aa.Create(m,l);	xx.Create(m,l);	yy.Create(m,l);	zz.Create(m,l);
+		mreal d = (n-1)*(sv - gr->Min.x)/(gr->Max.x - gr->Min.x);
+		long k = long(d);	d = d - k;
+		if(k>n-2)	{	k=n-2;	d=1;	}
+		if(k<0)		{	k=0;	d=0;	}
+#pragma omp parallel for collapse(2)
+		for(long j=0;j<l;j++)	for(long i=0;i<m;i++)
+			aa.a[i+m*j] = a->v(k,i,j)*(1-d) + d*a->v(k+1,i,j);
+		a = &aa;
+	}
+	else
+	{	xx.Create(n,m);	yy.Create(n,m);	zz.Create(n,m);	}
+	xx.Fill(sv, sv);
+	yy.Fill(gr->Min.y, gr->Max.y,'x');
+	zz.Fill(gr->Min.z, gr->Max.z,'y');
+	return a;
+}
+//-----------------------------------------------------------------------------
+HCDT MGL_NO_EXPORT fill_slice_y(HMGL gr, double sv, HCDT a, mglDataV &xx, mglDataV &yy, mglDataV &zz, mglData &aa)
+{
+	long n=a->GetNx(),m=a->GetNy(),l=a->GetNz();
+	if(l>1)
+	{
+		aa.Create(n,l);	xx.Create(n,l);	yy.Create(n,l);	zz.Create(n,l);
+		mreal d = (m-1)*(sv - gr->Min.y)/(gr->Max.y - gr->Min.y);
+		long k = long(d);	d = d - k;
+		if(k>m-2)	{	k=m-2;	d=1;	}
+		if(k<0)		{	k=0;	d=0;	}
+#pragma omp parallel for collapse(2)
+		for(long j=0;j<l;j++)	for(long i=0;i<n;i++)
+			aa.a[i+n*j] = a->v(i,k,j)*(1-d) + d*a->v(i,k+1,j);
+		a = &aa;
+	}
+	else
+	{	xx.Create(n,m);	yy.Create(n,m);	zz.Create(n,m);	}
+	yy.Fill(sv, sv);
+	xx.Fill(gr->Min.x, gr->Max.x,'x');
+	zz.Fill(gr->Min.z, gr->Max.z,'y');
+	return a;
+}
+//-----------------------------------------------------------------------------
+HCDT MGL_NO_EXPORT fill_slice_z(HMGL gr, double sv, HCDT a, mglDataV &xx, mglDataV &yy, mglDataV &zz, mglData &aa)
+{
+	long n=a->GetNx(),m=a->GetNy(),l=a->GetNz();
+	xx.Create(n,m);	yy.Create(n,m);	zz.Create(n,m);
+	if(l>1)
+	{
+		aa.Create(n,m);
+		mreal d = (l-1)*(sv - gr->Min.z)/(gr->Max.z - gr->Min.z);
+		long k = long(d);	d = d - k;
+		if(k>l-2)	{	k=l-2;	d=1;	}
+		if(k<0)		{	k=0;	d=0;	}
+#pragma omp parallel for collapse(2)
+		for(long j=0;j<m;j++)	for(long i=0;i<n;i++)
+			aa.a[i+n*j] = a->v(i,j,k)*(1-d) + d*a->v(i,j,k+1);
+		a = &aa;
+	}
+	zz.Fill(sv, sv);
+	yy.Fill(gr->Min.y, gr->Max.y,'y');
+	xx.Fill(gr->Min.x, gr->Max.x,'x');
+	return a;
+}
+//-----------------------------------------------------------------------------
+//
+//	DensX, DensY, DensZ series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dens_x(HMGL gr, HCDT a, const char *sch, double sv, const char *opt)
+{
+	long n=a->GetNx(),m=a->GetNy();
+	if(n<2 || m<2)	{	gr->SetWarn(mglWarnLow,"DensX");	return;	}
+	gr->SaveState(opt);
+	if(mgl_isnan(sv))	sv = gr->GetOrgX('x');
+	if(sv<gr->Min.x || sv>gr->Max.x)	{	gr->SetWarn(mglWarnSlc,"DensX");	gr->LoadState();	return;	}
+	mglDataV xx,yy,zz;	mglData aa;
+	a = fill_slice_x(gr,sv,a,xx,yy,zz,aa);
+	mgl_surf_gen(gr, &xx,&yy,&zz,a, 0, sch);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dens_y(HMGL gr, HCDT a, const char *sch, double sv, const char *opt)
+{
+	long n=a->GetNx(),m=a->GetNy();
+	if(n<2 || m<2)	{	gr->SetWarn(mglWarnLow,"DensY");	return;	}
+	gr->SaveState(opt);
+	if(mgl_isnan(sv))	sv = gr->GetOrgY('y');
+	if(sv<gr->Min.y || sv>gr->Max.y)	{	gr->SetWarn(mglWarnSlc,"DensY");	gr->LoadState();	return;	}
+	mglDataV xx,yy,zz;	mglData aa;
+	a = fill_slice_y(gr,sv,a,xx,yy,zz,aa);
+	mgl_surf_gen(gr, &xx,&yy,&zz,a, 0, sch);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dens_z(HMGL gr, HCDT a, const char *sch, double sv, const char *opt)
+{
+	long n=a->GetNx(),m=a->GetNy();
+	if(n<2 || m<2)	{	gr->SetWarn(mglWarnLow,"DensZ");	return;	}
+	gr->SaveState(opt);
+	if(mgl_isnan(sv))	sv = gr->GetOrgZ('z');
+	if(sv<gr->Min.z || sv>gr->Max.z)	{	gr->SetWarn(mglWarnSlc,"DensZ");	gr->LoadState();	return;	}
+	mglDataV xx,yy,zz;	mglData aa;
+	a = fill_slice_z(gr,sv,a,xx,yy,zz,aa);
+	mgl_surf_gen(gr, &xx,&yy,&zz,a, 0, sch);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dens_x_(uintptr_t *gr, uintptr_t *a, const char *sch, mreal *sv, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_dens_x(_GR_, _DA_(a), s, *sv, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dens_y_(uintptr_t *gr, uintptr_t *a, const char *sch, mreal *sv, const char *opt,int l,int lo)
+{
+	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_dens_y(_GR_, _DA_(a), s, *sv, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dens_z_(uintptr_t *gr, uintptr_t *a, const char *sch, mreal *sv, const char *opt,int l,int lo)
+{
+	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_dens_z(_GR_, _DA_(a), s, *sv, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	ContX, ContY, ContZ series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont_gen(HMGL gr, mreal val, HCDT a, HCDT x, HCDT y, HCDT z, mreal c, int text,long ak);
+void MGL_EXPORT mgl_cont_x_val(HMGL gr, HCDT v, HCDT a, const char *sch, double sv, const char *opt)
+{
+	long n=a->GetNx(),m=a->GetNy();
+	if(n<2 || m<2)	{	gr->SetWarn(mglWarnLow,"ContX");	return;	}
+	gr->SaveState(opt);
+	if(mgl_isnan(sv))	sv = gr->GetOrgX('x');
+	if(sv<gr->Min.x || sv>gr->Max.x)	{	gr->SetWarn(mglWarnSlc,"ContX");	gr->LoadState();	return;	}
+	static int cgid=1;	gr->StartGroup("ContX",cgid++);
+	mglDataV xx,yy,zz;	mglData aa;
+
+	int text=0;
+	if(mglchr(sch,'t'))	text=1;
+	if(mglchr(sch,'T'))	text=2;
+	long ss=gr->AddTexture(sch);
+	gr->SetPenPal(sch);
+
+	a = fill_slice_x(gr,sv,a,xx,yy,zz,aa);
+#pragma omp parallel for
+	for(long i=0;i<v->GetNx();i++)
+	{
+		mreal v0 = v->v(i);
+		mgl_cont_gen(gr,v0,a,&xx,&yy,&zz,gr->GetC(ss,v0),text,0);
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont_y_val(HMGL gr, HCDT v, HCDT a, const char *sch, double sv, const char *opt)
+{
+	long n=a->GetNx(),m=a->GetNy();
+	if(n<2 || m<2)	{	gr->SetWarn(mglWarnLow,"ContY");	return;	}
+	gr->SaveState(opt);
+	if(mgl_isnan(sv))	sv = gr->GetOrgY('y');
+	if(sv<gr->Min.y || sv>gr->Max.y)	{	gr->SetWarn(mglWarnSlc,"ContY");	gr->LoadState();	return;	}
+	static int cgid=1;	gr->StartGroup("ContY",cgid++);
+	mglDataV xx,yy,zz;	mglData aa;
+
+	int text=0;
+	if(mglchr(sch,'t'))	text=1;
+	if(mglchr(sch,'T'))	text=2;
+	long ss=gr->AddTexture(sch);
+	gr->SetPenPal(sch);
+
+	a = fill_slice_y(gr,sv,a,xx,yy,zz,aa);
+#pragma omp parallel for
+	for(long i=0;i<v->GetNx();i++)
+	{
+		mreal v0 = v->v(i);
+		mgl_cont_gen(gr,v0,a,&xx,&yy,&zz,gr->GetC(ss,v0),text,0);
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont_z_val(HMGL gr, HCDT v, HCDT a, const char *sch, double sv, const char *opt)
+{
+	long n=a->GetNx(),m=a->GetNy();
+	if(n<2 || m<2)	{	gr->SetWarn(mglWarnLow,"ContZ");	return;	}
+	gr->SaveState(opt);
+	if(mgl_isnan(sv))	sv = gr->GetOrgZ('z');
+	if(sv<gr->Min.z || sv>gr->Max.z)	{	gr->SetWarn(mglWarnSlc,"ContZ");	gr->LoadState();	return;	}
+	static int cgid=1;	gr->StartGroup("ContZ",cgid++);
+	mglDataV xx,yy,zz;	mglData aa;
+
+	int text=0;
+	if(mglchr(sch,'t'))	text=1;
+	if(mglchr(sch,'T'))	text=2;
+	long ss=gr->AddTexture(sch);
+	gr->SetPenPal(sch);
+
+	a = fill_slice_z(gr,sv,a,xx,yy,zz,aa);
+#pragma omp parallel for
+	for(long i=0;i<v->GetNx();i++)
+	{
+		mreal v0 = v->v(i);
+		mgl_cont_gen(gr,v0,a,&xx,&yy,&zz,gr->GetC(ss,v0),text,0);
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont_x(HMGL gr, HCDT a, const char *sch, double sv, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long Num = (mgl_isnan(r) || r<=0) ? 7:long(r+0.5);
+	mglData v(Num);
+	for(long i=0;i<Num;i++)	v.a[i] = gr->Min.c + (gr->Max.c-gr->Min.c)*mreal(i+1)/(Num+1);
+	mgl_cont_x_val(gr,&v,a,sch,sv,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont_y(HMGL gr, HCDT a, const char *sch, double sv, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long Num = (mgl_isnan(r) || r<=0) ? 7:long(r+0.5);
+	mglData v(Num);
+	for(long i=0;i<Num;i++)	v.a[i] = gr->Min.c + (gr->Max.c-gr->Min.c)*mreal(i+1)/(Num+1);
+	mgl_cont_y_val(gr,&v,a,sch,sv,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont_z(HMGL gr, HCDT a, const char *sch, double sv, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long Num = (mgl_isnan(r) || r<=0) ? 7:long(r+0.5);
+	mglData v(Num);
+	for(long i=0;i<Num;i++)	v.a[i] = gr->Min.c + (gr->Max.c-gr->Min.c)*mreal(i+1)/(Num+1);
+	mgl_cont_z_val(gr,&v,a,sch,sv,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont_x_(uintptr_t *gr, uintptr_t *a, const char *sch, mreal *sv, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_cont_x(_GR_, _DA_(a), s, *sv, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont_y_(uintptr_t *gr, uintptr_t *a, const char *sch, mreal *sv, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_cont_y(_GR_, _DA_(a), s, *sv, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont_z_(uintptr_t *gr, uintptr_t *a, const char *sch, mreal *sv, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_cont_z(_GR_, _DA_(a), s, *sv, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont_x_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *a, const char *sch, mreal *sv, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_cont_x_val(_GR_, _DA_(v), _DA_(a), s, *sv, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont_y_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *a, const char *sch, mreal *sv, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_cont_y_val(_GR_, _DA_(v), _DA_(a), s, *sv, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cont_z_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *a, const char *sch, mreal *sv, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_cont_z_val(_GR_, _DA_(v), _DA_(a), s, *sv, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	ContFX, ContFY, ContFZ series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf_gen(HMGL gr, mreal v1, mreal v2, HCDT a, HCDT x, HCDT y, HCDT z, mreal c, long ak);
+void MGL_EXPORT mgl_contf_x_val(HMGL gr, HCDT v, HCDT a, const char *sch, double sv, const char *opt)
+{
+	long n=a->GetNx(),m=a->GetNy();
+	if(n<2 || m<2)	{	gr->SetWarn(mglWarnLow,"ContFX");	return;	}
+	gr->SaveState(opt);
+	if(mgl_isnan(sv))	sv = gr->GetOrgX('x');
+	if(sv<gr->Min.x || sv>gr->Max.x)	{	gr->SetWarn(mglWarnSlc,"ContFX");	gr->LoadState();	return;	}
+	static int cgid=1;	gr->StartGroup("ContFX",cgid++);
+	mglDataV xx,yy,zz;	mglData aa;
+	long ss=gr->AddTexture(sch);
+
+	a = fill_slice_x(gr,sv,a,xx,yy,zz,aa);
+#pragma omp parallel for
+	for(long i=0;i<v->GetNx()-1;i++)
+	{
+		mreal v0 = v->v(i);
+		mgl_contf_gen(gr,v0,v->v(i+1),a,&xx,&yy,&zz,gr->GetC(ss,v0),0);
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf_y_val(HMGL gr, HCDT v, HCDT a, const char *sch, double sv, const char *opt)
+{
+	long n=a->GetNx(),m=a->GetNy();
+	if(n<2 || m<2)	{	gr->SetWarn(mglWarnLow,"ContFY");	return;	}
+	gr->SaveState(opt);
+	if(mgl_isnan(sv))	sv = gr->GetOrgY('y');
+	if(sv<gr->Min.y || sv>gr->Max.y)	{	gr->SetWarn(mglWarnSlc,"ContFY");	gr->LoadState();	return;	}
+	static int cgid=1;	gr->StartGroup("ContFY",cgid++);
+	mglDataV xx,yy,zz;	mglData aa;
+	long ss=gr->AddTexture(sch);
+
+	a = fill_slice_y(gr,sv,a,xx,yy,zz,aa);
+#pragma omp parallel for
+	for(long i=0;i<v->GetNx()-1;i++)
+	{
+		mreal v0 = v->v(i);
+		mgl_contf_gen(gr,v0,v->v(i+1),a,&xx,&yy,&zz,gr->GetC(ss,v0),0);
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf_z_val(HMGL gr, HCDT v, HCDT a, const char *sch, double sv, const char *opt)
+{
+	long n=a->GetNx(),m=a->GetNy();
+	if(n<2 || m<2)	{	gr->SetWarn(mglWarnLow,"ContFZ");	return;	}
+	gr->SaveState(opt);
+	if(mgl_isnan(sv))	sv = gr->GetOrgZ('z');
+	if(sv<gr->Min.z || sv>gr->Max.z)	{	gr->SetWarn(mglWarnSlc,"ContFZ");	gr->LoadState();	return;	}
+	static int cgid=1;	gr->StartGroup("ContFZ",cgid++);
+	mglDataV xx,yy,zz;	mglData aa;
+	long ss=gr->AddTexture(sch);
+
+	a = fill_slice_z(gr,sv,a,xx,yy,zz,aa);
+#pragma omp parallel for
+	for(long i=0;i<v->GetNx()-1;i++)
+	{
+		mreal v0 = v->v(i);
+		mgl_contf_gen(gr,v0,v->v(i+1),a,&xx,&yy,&zz,gr->GetC(ss,v0),0);
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf_x(HMGL gr, HCDT a, const char *sch, double sv, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long Num = (mgl_isnan(r) || r<=0) ? 7:long(r+0.5);
+	mglData v(Num);	v.Fill(gr->Min.c, gr->Max.c);
+	mgl_contf_x_val(gr,&v,a,sch,sv,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf_y(HMGL gr, HCDT a, const char *sch, double sv, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long Num = (mgl_isnan(r) || r<=0) ? 7:long(r+0.5);
+	mglData v(Num);	v.Fill(gr->Min.c, gr->Max.c);
+	mgl_contf_y_val(gr,&v,a,sch,sv,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf_z(HMGL gr, HCDT a, const char *sch, double sv, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long Num = (mgl_isnan(r) || r<=0) ? 7:long(r+0.5);
+	mglData v(Num);	v.Fill(gr->Min.c, gr->Max.c);
+	mgl_contf_z_val(gr,&v,a,sch,sv,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_contf_x_(uintptr_t *gr, uintptr_t *a, const char *sch, mreal *sv, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_contf_x(_GR_, _DA_(a), s, *sv, o);	delete []o;	delete []s;	}
+/// Draw several contour plots for data a at y = *sv
+void MGL_EXPORT mgl_contf_y_(uintptr_t *gr, uintptr_t *a, const char *sch, mreal *sv, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_contf_y(_GR_, _DA_(a), s, *sv, o);	delete []o;	delete []s;	}
+/// Draw several contour plots for data a at z = *sv
+void MGL_EXPORT mgl_contf_z_(uintptr_t *gr, uintptr_t *a, const char *sch, mreal *sv, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_contf_z(_GR_, _DA_(a), s, *sv, o);	delete []o;	delete []s;	}
+/// Draw contour plots for data a at x = *sv
+void MGL_EXPORT mgl_contf_x_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *a, const char *sch, mreal *sv, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_contf_x_val(_GR_, _DA_(v), _DA_(a), s, *sv, o);	delete []o;	delete []s;}
+/// Draw contour plots for data a at y = *sv
+void MGL_EXPORT mgl_contf_y_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *a, const char *sch, mreal *sv, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_contf_y_val(_GR_, _DA_(v), _DA_(a), s, *sv, o);	delete []o;	delete []s;}
+/// Draw contour plots for data a at z = *sv
+void MGL_EXPORT mgl_contf_z_val_(uintptr_t *gr, uintptr_t *v, uintptr_t *a, const char *sch, mreal *sv, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_contf_z_val(_GR_, _DA_(v), _DA_(a), s, *sv, o);	delete []o;	delete []s;}
+//-----------------------------------------------------------------------------
diff --git a/src/parser.cpp b/src/parser.cpp
new file mode 100644
index 0000000..d51a3e0
--- /dev/null
+++ b/src/parser.cpp
@@ -0,0 +1,1442 @@
+/***************************************************************************
+ * parse.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <ctype.h>
+#include "mgl2/parser.h"
+#include "mgl2/canvas_cf.h"
+#include "mgl2/base.h"
+//-----------------------------------------------------------------------------
+int MGL_LOCAL_PURE mgl_cmd_cmp(const void *a, const void *b)
+{
+	const mglCommand *aa = (const mglCommand *)a;
+	const mglCommand *bb = (const mglCommand *)b;
+	return strcmp(aa->name, bb->name);
+}
+//-----------------------------------------------------------------------------
+mglCommand *mglParser::BaseCmd=NULL;	///< Base table of MGL commands. It MUST be sorted by 'name'!!!
+void mglParser::FillBaseCmd()
+{
+	if(BaseCmd)	return;
+	size_t na=0, nd=0, ng=0, np=0, ns=0, nsum=0;
+	while(mgls_prg_cmd[na].name[0])	na++;
+	while(mgls_dat_cmd[nd].name[0])	nd++;
+	while(mgls_grf_cmd[ng].name[0])	ng++;
+	while(mgls_prm_cmd[np].name[0])	np++;
+	while(mgls_set_cmd[ns].name[0])	ns++;
+	BaseCmd = new mglCommand[na+nd+ng+np+ns+1];
+	memcpy(BaseCmd, 	mgls_prg_cmd, na*sizeof(mglCommand));	nsum+=na;
+	memcpy(BaseCmd+nsum,mgls_dat_cmd, nd*sizeof(mglCommand));	nsum+=nd;
+	memcpy(BaseCmd+nsum,mgls_grf_cmd, ng*sizeof(mglCommand));	nsum+=ng;
+	memcpy(BaseCmd+nsum,mgls_prm_cmd, np*sizeof(mglCommand));	nsum+=np;
+	memcpy(BaseCmd+nsum,mgls_set_cmd, (ns+1)*sizeof(mglCommand));	nsum+=ns;
+	qsort(BaseCmd, nsum, sizeof(mglCommand), mgl_cmd_cmp);
+#if DEBUG
+	long stat[17];	memset(stat,0,17*sizeof(long));
+	const char *name[17] = { _("0 - special plot"), _("1 - other plot"), _("2 - setup"), _("3 - data handle"), _("4 - data create"), _("5 - subplot"), _("6 - program flow"), _("7 - 1d plot"), _("8 - 2d plot"), _("9 - 3d plot"), _("10 - dd plot"), _("11 - vector plot"), _("12 - axis"), _("13 - primitives"), _("14 - axis setup"), _("15 - text/legend"), _("16 - data transform") };
+	for(size_t i=0;BaseCmd[i].name[0];i++)	stat[BaseCmd[i].type]+=1;
+	for(size_t i=0;i<17;i++)	printf("%s: %ld\n",name[i],stat[i]);
+	printf("\n");	fflush(stdout);
+#endif
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_NO_EXPORT mglFormulaCalc(std::wstring string, mglParser *arg, const std::vector<mglDataA*> &head);
+HADT MGL_NO_EXPORT mglFormulaCalcC(std::wstring string, mglParser *arg, const std::vector<mglDataA*> &head);
+//-----------------------------------------------------------------------------
+MGL_EXPORT void (*mgl_ask_func)(const wchar_t *, wchar_t *)=0;
+void MGL_EXPORT mgl_ask_gets(const wchar_t *quest, wchar_t *res)
+{	printf("%ls\n",quest);	if(!fgetws(res,1024,stdin))	*res=0;	}
+//-----------------------------------------------------------------------------
+mglFunc::mglFunc(long p, const wchar_t *f)
+{
+	pos = p;	func = f;
+	size_t i;
+	for(i=0;(isalnum(f[i]) || f[i]=='_');i++);
+	narg = wcstol(f+i+1,0,0);	func = func.substr(0,i);
+	if(narg<0 || narg>9)	narg=0;
+}
+//-----------------------------------------------------------------------------
+long mglParser::IsFunc(const std::wstring &name, int *na)
+{
+	for(size_t i=0;i<func.size();i++)
+	{
+		const mglFunc &f = func[i];
+		if(f.func==name)
+		{	if(na)	*na=f.narg;	return f.pos+1;	}
+	}
+	return 0;
+}
+//-----------------------------------------------------------------------------
+void mglParser::ScanFunc(const wchar_t *line)
+{
+	static long num=0;
+	if(!line)
+	{	func.clear();	num=0;	return;	}
+	num++;
+	while(*line<=' ' && *line!=0)	line++;
+	if(wcsncmp(line,L"func",4) || line[4]>' ')	return;
+	long i;
+	for(i=4;line[i]<=' ' || line[i]=='\'';i++);
+	func.push_back(mglFunc(num-1, line+i));
+}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT wchar_t *mgl_str_copy(const char *s)
+{
+	size_t i,l=strlen(s);
+	wchar_t *str = new wchar_t[l+1];
+	for(i=0;i<l;i++)	str[i] = s[i];
+	str[i] = 0;	return str;
+}
+//-----------------------------------------------------------------------------
+bool mglParser::CheckForName(const std::wstring &s)
+{
+	return !isalpha(s[0]) || s.find_first_of(L"!@#$%%^&*()-+|,.<>:")!=std::wstring::npos || s==L"rnd" || FindNum(s.c_str());
+//	return !isalpha(s[0])||s.find_first_of(L".:()")!=std::wstring::npos;
+}
+//-----------------------------------------------------------------------------
+const mglCommand *mglParser::FindCommand(const char *com) const
+{
+	if(!AllowFileIO && ( !strncmp(com,"read",4) || !strncmp(com,"save",4) || !strcmp(com,"fgets") || !strcmp(com,"import") || !strcmp(com,"export") ))
+		return 0;
+	mglCommand tst, *rts, *cmd = Cmd;
+	long i;
+	for(i=0;cmd[i].name[0];i++);	// determine the number of symbols
+	tst.name = com;
+	rts = (mglCommand *) bsearch(&tst, cmd, i, sizeof(mglCommand), mgl_cmd_cmp);
+	return rts;
+}
+//-----------------------------------------------------------------------------
+const mglCommand *mglParser::FindCommand(const wchar_t *com) const
+{
+	size_t s = 15<mgl_wcslen(com)?15:mgl_wcslen(com);
+	char cmd[16];	wcstombs(cmd,com,s+1);	cmd[s]=0;
+	return FindCommand(cmd);
+}
+//-----------------------------------------------------------------------------
+// return values : 0 -- OK, 1 -- wrong arguments, 2 -- wrong command, 3 -- unclosed string
+int mglParser::Exec(mglGraph *gr, const wchar_t *com, long n, mglArg *a, const std::wstring &/*var*/, const wchar_t *opt)
+{
+	const char *id="dsn";
+	std::string k;
+	for(long i=0;i<n;i++)
+	{
+		k += id[a[i].type];
+		size_t len = wcstombs(NULL,a[i].w.c_str(),0)+1;
+		char *buf = new char[len];	memset(buf,0,len);
+		wcstombs(buf,a[i].w.c_str(),len);
+		a[i].s = buf;	delete []buf;
+	}
+	const mglCommand *rts=FindCommand(com);
+	if(!rts || !rts->exec)	return 2;
+/*	if(rts->type == 4)
+	{
+		if(n<1 || CheckForName(var))	return 2;
+		a[0].type = 0;	a[0].d = AddVar(var.c_str());
+		a[0].w = var;	k[0] = 'd';
+	}*/
+	std::string vopt;
+	if(opt && *opt)	// TODO: parse arguments of options
+	{
+		size_t len = mgl_wcslen(opt);
+		std::vector<std::wstring> ss;
+		std::wstring s, o;
+		bool st = true, name = true;
+		for(size_t i=0;i<len+1;i++)
+		{
+			if(st && opt[i]<=' ')	continue;	// skip spaces at beginning
+			st = false;
+			if(i<len && opt[i]!=';')
+			{
+				if(name && opt[i]<=' ')	{	name = false;	o = s;	}
+				s.push_back(opt[i]);
+			}
+			else
+			{
+				size_t j = o.size(),k;
+				wchar_t buf[64];
+				if(o==L"xrange" || o==L"yrange" || o==L"zrange" || o==L"crange")	// 2 arguments
+				{
+					bool alph=false;
+					for(k=j;k<s.length();k++)
+					{
+						if(s[k]>' ')	alph=true;
+						if(alph && s[k]<=' ')	break;
+					}
+					HMDT d1 = mglFormulaCalc(s.substr(j+1,k-j),this, DataList);
+					HMDT d2 = mglFormulaCalc(s.substr(k+1),this, DataList);
+					mglprintf(buf,64,L" %g %g",d1->a[0],d2->a[0]);
+					s = o+buf;	delete d1;	delete d2;
+				}
+				else if(o!=L"legend")	// 1 argument
+				{
+					HMDT dd = mglFormulaCalc(s.substr(j+1),this, DataList);
+					mglprintf(buf,64,L" %g",dd->a[0]);
+					s = o+buf;	delete dd;
+				}
+				st = name = true;	ss.push_back(s);
+				o.clear();	s.clear();
+			}
+		}
+		for(size_t i=0;i<ss.size();i++)
+		{
+			for(size_t j=0;j<ss[i].length();j++)	vopt += ss[i][j];
+			vopt += ';';
+		}
+	}
+	int res=rts->exec(gr, n, a, k.c_str(), vopt.c_str());
+	return res;
+}
+//-----------------------------------------------------------------------------
+mglParser::mglParser(bool setsize)
+{
+	InUse = 1;	curGr = 0;	Variant = 0;
+	Skip=Stop=for_br=false;	StarObhID = 0;
+	memset(for_stack,0,40*sizeof(int));
+	memset(if_stack,0,40*sizeof(int));
+	memset(if_for,0,40*sizeof(int));
+	if_pos=for_addr=0;
+	for(long i=0;i<40;i++)	par[i]=L"";
+
+	FillBaseCmd();	Cmd = BaseCmd;
+	AllowSetSize=setsize;	AllowFileIO=true;	AllowDllCall=true;
+	Once = true;
+	fval = new mglData[40];
+	mglNum *v;
+	v = new mglNum(0);	v->s = L"off";	NumList.push_back(v);
+	v = new mglNum(1);	v->s = L"on";	NumList.push_back(v);
+	v = new mglNum(-1);	v->s = L"all";	NumList.push_back(v);
+	v = new mglNum(NAN);	v->s = L"nan";	NumList.push_back(v);
+	v = new mglNum(M_PI);	v->s = L"pi";	NumList.push_back(v);
+	v = new mglNum(INFINITY);	v->s = L"inf";	NumList.push_back(v);
+#if MGL_HAVE_LTDL
+	lt_dlinit();
+#endif
+}
+//-----------------------------------------------------------------------------
+mglParser::~mglParser()
+{
+	DeleteAll();	delete []fval;
+	for(size_t i=0;i<NumList.size();i++)	// force delete built-in variables
+		if(NumList[i])	delete NumList[i];
+	NumList.clear();
+#if MGL_HAVE_LTDL
+	lt_dlexit();
+#endif
+}
+//-----------------------------------------------------------------------------
+void mglParser::DeleteAll()
+{
+	for(size_t i=0;i<DataList.size();i++)
+		if(DataList[i])	delete DataList[i];
+	DataList.clear();
+	for(size_t i=0;i<NumList.size();i++)
+		if(NumList[i])	delete NumList[i];
+	NumList.clear();
+	mglNum *v;
+	v = new mglNum(0);	v->s = L"off";	NumList.push_back(v);
+	v = new mglNum(1);	v->s = L"on";	NumList.push_back(v);
+	v = new mglNum(-1);	v->s = L"all";	NumList.push_back(v);
+	v = new mglNum(NAN);	v->s = L"nan";	NumList.push_back(v);
+	v = new mglNum(M_PI);	v->s = L"pi";	NumList.push_back(v);
+	v = new mglNum(INFINITY);	v->s = L"inf";	NumList.push_back(v);
+	if(Cmd && Cmd!=BaseCmd)	{	delete []Cmd;	Cmd = BaseCmd;	}
+#if MGL_HAVE_LTDL
+	for(size_t i=0;i<DllOpened.size();i++)
+		lt_dlclose(DllOpened[i]);
+	DllOpened.clear();
+#endif
+}
+//-----------------------------------------------------------------------------
+void mglParser::AddParam(int n, const char *str)
+{
+	MGL_TO_WCS(str,AddParam(n,wcs));
+}
+//-----------------------------------------------------------------------------
+int mglParser::Parse(mglGraph *gr, const char *str, long pos)
+{
+	int r=0;
+	MGL_TO_WCS(str,r = Parse(gr,wcs,pos));
+	return r;
+}
+//-----------------------------------------------------------------------------
+mglDataA *mglParser::AddVar(const char *str)
+{
+	mglDataA *v=0;
+	MGL_TO_WCS(str,v = AddVar(wcs));
+	return v;
+}
+//-----------------------------------------------------------------------------
+mglDataA *mglParser::FindVar(const char *str)
+{
+	mglDataA *v=0;
+	MGL_TO_WCS(str,v = FindVar(wcs));
+	return v;
+}
+//-----------------------------------------------------------------------------
+mglNum *mglParser::AddNum(const char *str)
+{
+	mglNum *v=0;
+	MGL_TO_WCS(str,v = AddNum(wcs));
+	return v;
+}
+//-----------------------------------------------------------------------------
+mglNum *mglParser::FindNum(const char *str)
+{
+	mglNum *v=0;
+	MGL_TO_WCS(str,v = FindNum(wcs));
+	return v;
+}
+//-----------------------------------------------------------------------------
+void mglParser::AddParam(int n, const wchar_t *str)
+{
+//	if(str && n>=0 && n<40 && !wcschr(str,'$'))	par[n] = str;
+	if(str && n>=0 && n<40)	par[n] = str;
+}
+//-----------------------------------------------------------------------------
+mglDataA *mglParser::FindVar(const wchar_t *name)
+{
+	if(name[0]=='!')	name = name+1;	// ignore complex prefix
+ 	for(size_t i=0;i<DataList.size();i++)
+ 		if(DataList[i] && DataList[i]->s==name)	return DataList[i];
+	return 0;
+}
+//-----------------------------------------------------------------------------
+mglDataA *mglParser::AddVar(const wchar_t *name)
+{	// TODO add list of forbidden names (like function names)
+	mglDataA *d=FindVar(name);
+	if(name[0]=='!' && dynamic_cast<mglDataC*>(d)==0)
+	{	d = new mglDataC;	d->s=(name+1);	DataList.push_back(d);	}
+	else if(!d)
+	{	d = new mglData;	d->s = name;	DataList.push_back(d);	}
+	return d;
+}
+//-----------------------------------------------------------------------------
+mglNum *mglParser::FindNum(const wchar_t *name)
+{
+	for(size_t i=0;i<NumList.size();i++)
+		if(NumList[i] && NumList[i]->s==name)	return NumList[i];
+	return 0;
+}
+//-----------------------------------------------------------------------------
+mglNum *mglParser::AddNum(const wchar_t *name)
+{
+	mglNum *v = FindNum(name);
+	if(!v)	{	v=new mglNum;	v->s = name;	NumList.push_back(v);	}
+	return v;
+}
+//-----------------------------------------------------------------------------
+int MGL_LOCAL_PURE mglFindArg(const std::wstring &str)
+{
+	long l=0,k=0;
+	const size_t s=str.length();
+	for(size_t i=0;i<s;i++)
+	{
+		if(str[i]=='\'') l++;
+		if(str[i]=='{') k++;
+		if(str[i]=='}') k--;
+		if(l%2==0 && k==0)
+		{
+			if(str[i]=='#' || str[i]==';')	return -long(i);
+			if(str[i]<=' ')	return long(i);
+		}
+	}
+	return 0;
+}
+//-----------------------------------------------------------------------------
+// convert substrings to arguments
+void mglParser::FillArg(mglGraph *gr, int k, std::wstring *arg, mglArg *a)
+{
+	for(long n=1;n<k;n++)
+	{
+		mglDataA *v;	mglNum *f;
+		a[n-1].type = -1;
+		std::wstring str = arg[n];
+		size_t i1=0, i2=str.length(), j=0;
+		bool s=true;
+		for(size_t i=0;i<i2;i++)
+		{
+			if(str[i]=='\'')	s = !s;
+			if(s && str[i]=='?')
+			{
+				if(j<Variant)	i1=i+1;
+				else	i2=i;
+				j++;
+			}
+		}
+		str = str.substr(i1,i2-i1);
+
+		if(str.empty())	a[n-1].type = -2;
+		else if(str[0]=='|')	a[n-1].type = -1;
+		else if(str[0]=='\'')	// this is string (simplest case)
+		{
+			a[n-1].type = 1;
+			long na=1, ns=0, np=0, ll=str.length(), ii=1, op=0;
+			std::vector<std::wstring> s;
+			std::vector<int> id;	// 0 - string, 1 - cval, 2 - rval, 3 - plus, 4 - index
+			for(long i=1;i<ll;i++)
+			{
+				if(str[i]=='\'')
+				{
+					if(na%2==1)
+					{	id.push_back(0);	s.push_back(str.substr(ii,i-ii));	}
+					else if(op && i>ii)
+					{	id.push_back(op);	s.push_back(str.substr(ii,i-ii));	}
+					na++;	ii=i+1;	op=0;
+				}
+				else if(na%2==0 && ns==0 && np==0)
+				{
+					if(str[i]=='+' && str[i-1]=='\'')
+					{	op=3;	ii=i+1;	}
+					else if(str[i]==',' && str[i+1]=='!')
+					{
+						if(op && i>ii)
+						{	id.push_back(op);	s.push_back(str.substr(ii,i-ii));	}
+						op=1;	ii=i+2;
+					}
+					else if(str[i]==',')
+					{
+						if(op && i>ii)
+						{	id.push_back(op);	s.push_back(str.substr(ii,i-ii));	}
+						op=2;	ii=i+1;
+					}
+					else if(str[i]=='[' && str[i-1]=='\'')
+					{	ii=i+1;	ns++;	}
+					else if(str[i]=='(')	np++;
+				}
+				else if(na%2==0 && np==0 && str[i]==']' && ns==1)
+				{
+					id.push_back(4);	s.push_back(str.substr(ii,i-ii));
+					op=0;	ii=i+1;	ns--;
+				}
+				else if(na%2==0 && np==1 && str[i]==')' && ns==0)	np--;
+			}
+			if(op && ll>ii)
+			{	id.push_back(op);	s.push_back(str.substr(ii,ll-ii));	}
+			wchar_t buf[32];
+			for(size_t i=0;i<id.size();i++)
+			{
+				if(id[i]==0)	a[n-1].w += s[i];
+				else if(id[i]==1)
+				{
+					HADT d = mglFormulaCalcC(s[i], this, DataList);
+					mreal di = imag(d->a[0]), dr = real(d->a[0]);
+					if(di>0)	mglprintf(buf,32,L"%g+%gi",dr,di);
+					else if(di<0)	mglprintf(buf,32,L"%g-%gi",dr,-di);	// TODO use \u2212 ???
+					else	mglprintf(buf,32,L"%g",dr);
+					a[n-1].w += buf;	delete d;
+				}
+				else if(id[i]==2)
+				{
+					HMDT d = mglFormulaCalc(s[i], this, DataList);
+					mglprintf(buf,32,L"%g",d->a[0]);	a[n-1].w += buf;	delete d;
+				}
+				else if(id[i]==3)
+				{
+					HMDT d = mglFormulaCalc(s[i], this, DataList);
+					a[n-1].w[a[n-1].w.size()-1] += d->a[0];	delete d;
+				}
+				else if(id[i]==4)
+				{
+					HMDT d = mglFormulaCalc(s[i], this, DataList);
+					long v = long(d->a[0]+0.5);	delete d;
+					if(v>=0 && v<long(a[n-1].w.size()))	a[n-1].w = a[n-1].w[v];
+					else	a[n-1].w = L"";
+				}
+			}
+		}
+		else if(str[0]=='{')
+		{	// this is temp data
+			mglData *u=new mglData;
+			std::wstring s = str.substr(1,str.length()-2);
+			a[n-1].w = u->s = L"/*"+s+L"*/";
+			a[n-1].type = 0;
+			ParseDat(gr, s, *u);	a[n-1].d = u;
+			u->temp=true;	DataList.push_back(u);
+		}
+		else if((v = FindVar(str.c_str()))!=0)	// try to find normal variables (for data creation)
+		{	a[n-1].type=0;	a[n-1].d=v;	a[n-1].w=v->s;	}
+		else if((f = FindNum(str.c_str()))!=0)	// try to find normal number (for data creation)
+		{	a[n-1].type=2;	a[n-1].d=0;	a[n-1].v=f->d;	a[n-1].c=f->c;	a[n-1].w = f->s;	}
+		else if(str[0]=='!')	// complex array is asked
+		{	// parse all numbers and formulas by unified way
+			HADT d = mglFormulaCalcC(str.substr(1), this, DataList);
+			if(d->GetNN()==1)
+			{
+				if(CheckForName(str.substr(1)))
+				{	a[n-1].type = 2;	a[n-1].v = d->v(0);	a[n-1].c = d->a[0];	}
+				else
+				{	a[n-1].type = 0;	a[n-1].d = AddVar(str.c_str());	}
+				delete d;
+			}
+			else
+			{
+				a[n-1].w = L"/*"+str+L"*/";
+				d->temp=true;	DataList.push_back(d);
+				a[n-1].type = 0;	a[n-1].d = d;
+			}
+		}
+		else
+		{	// parse all numbers and formulas by unified way
+			HMDT d = mglFormulaCalc(str, this, DataList);
+			if(d->GetNN()==1)
+			{
+				if(CheckForName(str))
+				{	a[n-1].type = 2;	a[n-1].c = a[n-1].v = d->v(0);	}
+				else
+				{	a[n-1].type = 0;	a[n-1].d = AddVar(str.c_str());	}
+				delete d;
+			}
+			else
+			{
+				a[n-1].w = L"/*"+str+L"*/";
+				d->temp=true;	DataList.push_back(d);
+				a[n-1].type = 0;	a[n-1].d = d;
+			}
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+// return values: 0 - not found, 1 - OK, 2 - wrong arguments, 3 - wrong command, 4 - string too long
+int mglParser::PreExec(mglGraph *, long k, std::wstring *arg, mglArg *a)
+{
+	long n=0;
+	if(!arg[0].compare(L"list"))	// parse command "list"
+	{
+		if(k<3 || CheckForName(arg[1]))	return 2;
+		long nx=0, ny=1,j=0,i,t=0;
+		for(i=2;i<k;i++)
+		{
+			char ch = arg[i][0];
+			if(a[i-1].type==1)	return 2;
+			if(a[i-1].type==0)
+			{
+				if(t==1)	return 2;
+				t=2;	nx++;
+			}
+			if(a[i-1].type==2)
+			{
+				if(t==2)	return 2;
+				j++;	t=1;
+			}
+			if(ch=='|' && t==1)		{	nx = j>nx ? j:nx;	j=0;	ny++;	}
+		}
+		mglDataA *vv = AddVar(arg[1].c_str());
+		mglData *v = dynamic_cast<mglData*>(vv);
+		mglDataC *vc = dynamic_cast<mglDataC*>(vv);
+		if(v)
+		{
+			if(t==1)	nx = j>nx ? j:nx;
+			if(t==1)	// list of numeric values
+			{
+				v->Create(nx,ny);
+				j=t=0;
+				for(i=2;i<k;i++)
+				{
+					if(arg[i][0]=='|')	{	t++;	j=0;	}
+					else
+					{	v->a[j+nx*t] = a[i-1].v;	j++;	}
+				}
+			}
+			if(t==2)	// list of data
+			{
+				v->Set(a[1].d);
+				for(long i=2;i<k;i++)	v->Join(*(a[i].d));
+			}
+			n=1;
+		}
+		if(vc)
+		{
+			if(t==1)	nx = j>nx ? j:nx;
+			if(t==1)	// list of numeric values
+			{
+				vc->Create(nx,ny);
+				j=t=0;
+				for(i=2;i<k;i++)
+				{
+					if(arg[i][0]=='|')	{	t++;	j=0;	}
+					else
+					{	vc->a[j+nx*t] = a[i-1].c;	j++;	}
+				}
+			}
+			if(t==2)	// list of data
+			{
+				vc->Set(a[1].d);
+				for(long i=2;i<k;i++)	vc->Join(*(a[i].d));
+			}
+			n=1;
+		}
+	}
+	return n;
+}
+//-----------------------------------------------------------------------------
+void mglParser::PutArg(std::wstring &str, bool def)
+{
+	size_t pos = str.find('$',def?10:0);
+	while(pos<str.length())
+	{
+		wchar_t ch = str[pos+1];
+		if(ch>='0' && ch<='9')	str.replace(pos,2,par[ch-'0']);
+		else if(ch>='a' && ch<='z')	str.replace(pos,2,par[ch-'a'+10]);
+		else if(ch=='$')	str.replace(pos,2,L"\uffff");
+		else str.replace(pos,1,L"\uffff");
+		pos = str.find('$',def?10:0);
+	}
+	while((pos = str.find(L'\uffff'))<str.length())	str[pos]='$';
+}
+//-----------------------------------------------------------------------------
+std::wstring mgl_trim_ws(const std::wstring &str)
+{
+	size_t n=str.length(), k, i;
+	for(k=0;k<n;k++)	if(str[k]>' ')	break;
+	for(i=n;i>k;i--)	if(str[i-1]>' ')	break;
+	return str.substr(k,i-k);
+}
+//-----------------------------------------------------------------------------
+int mglParser::ParseDef(std::wstring &str)
+{
+	if(!skip() && !str.compare(0,3,L"def") && (str[6]==' ' || str[6]=='\t'))
+	{
+		int res = 1;	mreal d;
+		PutArg(str,true);
+		const std::wstring s = mgl_trim_ws(str.substr(7));
+		if(!str.compare(3,3,L"ine"))
+		{
+			int nn = s[1]<='9' ? s[1]-'0' : (s[1]>='a' ? s[1]-'a'+10:-1);
+			if(s[0]=='$' && nn>=0 && nn<='z'-'a'+10)
+			{
+				AddParam(nn, mgl_trim_ws(s.substr(2)).c_str());	return 1;
+			}
+		}
+		if(!str.compare(3,3,L"num"))
+		{
+			int nn = s[1]<='9' ? s[1]-'0' : (s[1]>='a' ? s[1]-'a'+10:-1);
+			if(s[0]=='$' && nn>=0 && nn<='z'-'a'+10)
+			{
+				res = 0;
+				HMDT dd = mglFormulaCalc(mgl_trim_ws(s.substr(2)), this, DataList);
+				d = dd->a[0];	delete dd;
+				AddParam(nn, mgl_str_num(d).c_str());
+			}
+			return res+1;
+		}
+		if(!str.compare(3,3,L"chr"))
+		{
+			int nn = s[1]<='9' ? s[1]-'0' : (s[1]>='a' ? s[1]-'a'+10:-1);
+			if(s[0]=='$' && nn>=0 && nn<='z'-'a'+10)
+			{
+				res = 0;
+				HMDT dd = mglFormulaCalc(mgl_trim_ws(s.substr(2)), this, DataList);
+				d=dd->a[0];	delete dd;
+				wchar_t buf[2]={0,0};	buf[0] = wchar_t(d);	AddParam(nn, buf);
+			}
+			return res+1;
+		}
+	}
+	if(!skip() && !str.compare(0,3,L"ask") && (str[3]==' ' || str[3]=='\t'))
+	{
+		PutArg(str,true);
+		std::wstring s = mgl_trim_ws(str.substr(4));
+		int nn = s[1]<='9' ? s[1]-'0' : (s[1]>='a' ? s[1]-'a'+10:-1);
+		if(s[0]=='$' && nn>=0 && nn<='z'-'a'+10)
+		{
+			s = mgl_trim_ws(s.substr(2));
+			if(s[0]=='\'')	s=s.substr(1,s.length()-2);
+			if(mgl_ask_func)
+			{
+				static wchar_t res[1024];
+				mgl_ask_func(s.c_str(),res);
+				if(*res)	AddParam(nn, res);
+			}
+			return mgl_ask_func?1:2;
+		}
+		else	return 2;
+	}
+	if(!skip() && !str.compare(0,3,L"for") && (str[3]==' ' || str[3]=='\t'))
+	{
+		size_t i;	for(i=4;str[i]<=' ';i++);
+		// if command have format 'for $N ...' then change it to 'for N ...'
+		if(str[i]=='$' && str[i+1]>='0' && str[i+1]<='9')	str[i] = ' ';
+		if(str[i]=='$' && str[i+1]>='a' && str[i+1]<='z')	str[i] = ' ';
+	}
+	return 0;
+}
+//-----------------------------------------------------------------------------
+// return values: 0 - OK, 1 - wrong arguments, 2 - wrong command, 3 - string too long, 4 -- unclosed string
+int mglParser::Parse(mglGraph *gr, std::wstring str, long pos)
+{
+	if(Stop || gr->NeedStop())	return 0;
+	curGr = gr->Self();	gr->pr = this;
+	str=mgl_trim_ws(str);
+	long n,k=0,m=0,mm=0,res;
+	// try parse ':' -- several commands in line
+	for(n=0;n<long(str.length());n++)
+	{
+		if(str[n]=='\'' && (n==0 || str[n-1]!='\\'))	k++;
+		if(k%2)	continue;
+		if(str[n]=='(')	m++;
+		if(str[n]==')')	m--;
+		if(str[n]=='{')	mm++;
+		if(str[n]=='}')	mm--;
+		if(str[n]=='#')	break;
+		if((str[n]==':' || str[n]=='\n') && k%2==0 && m==0 && mm==0)
+		{
+			res=Parse(gr,str.substr(0,n),pos);
+			if(!res)	res=Parse(gr,str.substr(n+1),pos);
+			return res;
+		}
+	}
+	if(k%2 || m || mm)	return 4;	// strings is not closed
+	// define parameters or start cycle
+	res = ParseDef(str);	if(res)	return res-1;
+	// parse arguments (parameters $1, ..., $9)
+	PutArg(str,false);	str=mgl_trim_ws(str);
+
+	std::wstring opt;
+	std::vector<std::wstring> arg;
+	while(!str.empty())	// parse string to substrings (by spaces)
+	{
+		n = mglFindArg(str);
+		if(n<1)	// this is option
+		{
+			if(str[-n]==';')	opt = str.substr(-n+1);
+			if(n<0)	str = str.substr(0,-n);
+			break;
+		}
+		arg.push_back(str.substr(0,n));
+		str = mgl_trim_ws(str.substr(n+1));
+	}
+	// try to find last argument
+	if(str[0]!=0 && str[0]!='#' && str[0]!=';')	arg.push_back(str);
+	k = arg.size();
+	if(k<1) n = 0;
+	else
+	{
+		// fill arguments by its values
+		mglArg *a = new mglArg[k];
+		FillArg(gr, k, &(arg[0]), a);
+		// execute first special (program-flow-control) commands
+		if(!skip() && !arg[0].compare(L"stop"))
+		{	Stop = true;	delete []a;	return 0;	}
+		if(!arg[0].compare(L"func"))
+		{	Stop = true;	delete []a;	return 0;	}
+		n = FlowExec(gr, arg[0].c_str(),k-1,a);
+		if(n)		{	delete []a;	return n-1;	}
+		if(skip())	{	delete []a;	return 0;	}
+		if(!arg[0].compare(L"define"))
+		{
+			if(k==3)
+			{
+				DeleteVar(arg[1].c_str());	// force to delete variable with the same name
+				mglNum *v=AddNum(arg[1].c_str());
+				if(arg[2][0]=='!')	// complex number is added
+				{	HADT dd = mglFormulaCalcC(arg[2].substr(1),this, DataList);
+					v->d=NAN;	v->c = dd->a[0];	delete dd;	}
+				else
+				{	HMDT dd = mglFormulaCalc(arg[2],this, DataList);
+					v->c = v->d = dd->a[0];	delete dd;	}
+			}
+			delete []a;	return k==3?0:1;
+		}
+		if(!arg[0].compare(L"call"))
+		{
+			n = 1;
+			if(a[0].type==1)
+			{
+				int na=0;
+				a[0].s.assign(a[0].w.begin(),a[0].w.end());
+				n=-IsFunc(a[0].w.c_str(),&na);
+				if(n && k!=na+2)
+				{
+					char buf[64];
+					snprintf(buf,64,_("Bad arguments for %ls: %ld instead of %d\n"), a[0].w.c_str(),k-2,na);
+					buf[63]=0;	gr->SetWarn(-1,buf);	n = 1;
+				}
+				else if(n)
+				{
+					mglFnStack fn;			fn.pos = pos;
+					for(int i=0;i<10;i++)	{	fn.par[i] = par[i];	par[i]=L"";	}
+					for(int i=1;i<k-1;i++)	AddParam(i,arg[i+1].c_str());
+					fn_stack.push_back(fn);	n--;
+				}
+				else if(AllowFileIO)	// disable external scripts if AllowFileIO=false
+				{
+					FILE *fp = fopen(a[0].s.c_str(),"rt");
+					if(fp)
+					{
+						mglParser *prs = new mglParser(AllowSetSize);
+						prs->DataList.swap(DataList);	prs->NumList.swap(NumList);	prs->Cmd=Cmd;
+						for(int i=10;i<30;i++)	prs->AddParam(i,par[i].c_str());
+						prs->Execute(gr,fp);
+						for(int i=10;i<30;i++)	AddParam(i,prs->par[i].c_str());
+						DataList.swap(prs->DataList);	NumList.swap(prs->NumList);
+						prs->Cmd=0;	delete prs;	fclose(fp);
+					}
+					else	n=1;
+				}
+			}
+			delete []a;	return n;
+		}
+		if(!arg[0].compare(L"for"))
+		{
+			if(k<2)	{	delete []a;	return 1;	}
+			n = 1;
+			char ch = arg[1][0];
+			int r = ch-'0';
+			if(ch>='a' && ch<='z')	r = 10+ch-'a';
+//			int r = int(a[0].v);
+			if(arg[1][1]==0 && (r>=0 && r<40))
+			{
+				if(a[1].type==0)
+				{
+					n=0;		fval[r] = *(a[1].d);
+					fval[r].nx *= fval[r].ny*fval[r].nz;
+				}
+				else if(a[1].type==2 && a[2].type==2 && a[2].v>a[1].v)
+				{
+					mreal step = a[3].type==2?a[3].v:1;
+					mm = int(step>0 ? (a[2].v-a[1].v)/step : 0);
+					if(mm>0)
+					{
+						n=0;	fval[r].Create(mm+1);
+						for(int ii=0;ii<mm+1;ii++)
+							fval[r].a[ii] = a[1].v + step*ii;
+					}
+				}
+				if(n==0)
+				{
+					for(int i=39;i>0;i--)
+					{	for_stack[i]=for_stack[i-1];	if_for[i]=if_for[i-1];	}
+					for_stack[0] = r+1;		fval[r].nz = pos;	if_for[0]=if_pos;
+					wchar_t buf[32];		mglprintf(buf,32,L"%g",fval[r].a[0]);
+					AddParam(r, buf);	fval[r].ny = 1;
+				}
+			}
+			delete []a;	return n;
+		}
+		// alocate new arrays and execute the command itself
+		n = PreExec(gr, k, &(arg[0]), a);
+		if(n>0)	n--;
+		else if(!arg[0].compare(L"setsize") && !AllowSetSize)	n = 2;
+		else	n = Exec(gr, arg[0].c_str(),k-1,a, k>1?arg[1]:L"", opt.c_str());
+		delete []a;
+	}
+	// delete temporary data arrays
+	for(size_t i=0;i<DataList.size();i++)	if(DataList[i] && DataList[i]->temp)
+	{	mglDataA *u=DataList[i];	DataList[i]=0;	delete u;	}
+	return n;
+}
+//-----------------------------------------------------------------------------
+// return values: 0 - OK, 1 - wrong arguments, 2 - wrong command, 3 - string too long, 4 -- unclosed string
+int mglParser::ParseDat(mglGraph *gr, std::wstring str, mglData &res)
+{
+	std::wstring arg[32];
+	str = mgl_trim_ws(str);
+	long n,k=0;
+	for(k=0;k<32;k++)	// parse string to substrings (by spaces)
+	{
+		n = mglFindArg(str);
+		if(n<1)	{	if(n<0)	str=str.substr(0,-n);	break;	}
+		arg[k] = str.substr(0,n);//	k++;
+		str = str.substr(n+1);	str = mgl_trim_ws(str);
+	}
+	// try to find last argument
+	if(!str.empty())	{	arg[k] = str;	k++;	}
+	if(k<1) n = 0;
+	else
+	{	// fill arguments by its values
+		mglArg *a = new mglArg[k+1];
+		FillArg(gr, k, arg, a+1);	a[0].type=0;	a[0].d=&res;
+		// alocate new arrays and execute the command itself
+		int i;
+		std::string kk;
+		const char *id="dsn";
+		for(i=0;i<k;i++)
+		{
+			kk += id[a[i].type];
+			a[i].s.assign(a[i].w.begin(),a[i].w.end());
+		}
+		const mglCommand *rts=FindCommand(arg[0].c_str());
+		if(!rts || rts->type!=4)	n = 2;
+		else n = rts->exec(gr, k, a, kk.c_str(), 0);
+		delete []a;
+	}
+	return n;
+}
+//-----------------------------------------------------------------------------
+int mglParser::FlowExec(mglGraph *, const std::wstring &com, long m, mglArg *a)
+{
+	int n=-1;
+	if(!ifskip() && !com.compare(L"once"))
+	{
+		if(a[0].type==2)
+		{
+			n = 0;
+			if(a[0].v)	Skip = !Once;
+			else	Skip = Once = false;
+		}
+		else n = 1;
+	}
+	else if(!Skip && !com.compare(L"if"))
+	{
+		int cond;
+		if(a[0].type==2)
+		{	n = 0;	cond = (a[0].v!=0)?3:0;	}
+		else if(a[0].type==0)
+		{
+			n = 0;	a[1].s.assign(a[1].w.begin(),a[1].w.end());
+			cond = a[0].d->FindAny((m>1 && a[1].type==1) ? a[1].s.c_str():"u")?3:0;
+		}
+		else n = 1;
+		if(n==0)
+		{	if_stack[if_pos] = cond;	if_pos = if_pos<39 ? if_pos+1 : 39;	}
+	}
+	else if(!Skip && !com.compare(L"endif"))
+	{	if_pos = if_pos>0 ? if_pos-1 : 0;	n = 0;	}
+	else if(!Skip && !com.compare(L"else"))
+	{
+		if(if_pos>0)
+		{	n=0; if_stack[if_pos-1] = (if_stack[if_pos-1]&2)?2:3;	}
+		else n = 1;
+	}
+	else if(!Skip && !com.compare(L"elseif"))
+	{
+		int cond;
+		if(if_pos<1 || m<1)	n = 1;
+		else if(if_stack[if_pos-1]&2)	{	n = 0;	cond = 2;	}
+		else if(a[0].type==2)
+		{	n = 0;	cond = (a[0].v!=0)?3:0;	}
+		else if(a[0].type==0)
+		{
+			n = 0;	a[1].s.assign(a[1].w.begin(),a[1].w.end());
+			cond = a[0].d->FindAny((m>1 && a[1].type==1) ? a[1].s.c_str():"u")?3:0;
+		}
+		else n = 1;
+		if(n==0)	if_stack[if_pos-1] = cond;
+	}
+	else if(!ifskip() && !Skip && !com.compare(L"break"))
+	{
+		if(if_pos==if_for[0])	if_pos = if_pos>0 ? if_pos-1 : 0;
+		n = for_stack[0] ? 0:1;	for_br = true;
+	}
+	else if(!skip() && !com.compare(L"return"))
+	{
+		if(fn_stack.size()<1)	return 2;
+		const mglFnStack &fn=fn_stack.back();
+		for(int i=0;i<10;i++)	par[i]=fn.par[i];
+		n = -fn.pos-1;	fn_stack.pop_back();
+	}
+	else if(!ifskip() && !Skip && !com.compare(L"next"))
+	{
+		if(if_pos==if_for[0])	if_pos = if_pos>0 ? if_pos-1 : 0;
+		int r = for_stack[0]-1;
+		n = for_stack[0] ? 0:1;
+		if(for_stack[0])
+		{
+			if(fval[r].ny<fval[r].nx && !for_br)
+			{
+				wchar_t buf[32];		mglprintf(buf,32,L"%g",fval[r].a[fval[r].ny]);
+				AddParam(r, buf);	fval[r].ny += 1;
+				n = -fval[r].nz-1;
+			}
+			else
+			{
+				for(int i=0;i<39;i++)
+				{	for_stack[i]=for_stack[i+1];	if_for[i]=if_for[i+1];	}
+				for_stack[39] = 0;	for_br=false;
+			}
+		}
+	}
+	else if(!ifskip() && !Skip && !com.compare(L"continue"))
+	{
+		if(if_pos==if_for[0])	if_pos = if_pos>0 ? if_pos-1 : 0;
+		int r = for_stack[0]-1;
+		n = for_stack[0] ? 0:1;
+		if(for_stack[0])
+		{
+			if(fval[r].ny<fval[r].nx)
+			{
+				wchar_t buf[32];		mglprintf(buf,32,L"%g",fval[r].a[fval[r].ny]);
+				AddParam(r, buf);	fval[r].ny += 1;
+				n = -fval[r].nz-1;
+			}
+			else	for_br = true;
+		}
+	}
+	return n+1;
+}
+//-----------------------------------------------------------------------------
+void mglParser::Execute(mglGraph *gr, FILE *fp, bool print)
+{
+	if(gr==0 || fp==0)	return;
+	std::wstring str;
+	wchar_t ch;
+	while(!feof(fp) && size_t(ch=fgetwc(fp))!=WEOF)	str.push_back(ch);
+	Execute(gr,str.c_str());
+	if(print)	printf("%s\n",gr->Message());
+}
+//-----------------------------------------------------------------------------
+void mglParser::Execute(mglGraph *gr, int n, const wchar_t **text)
+{
+	if(n<1 || text==0)	return;
+	long res=0;
+	char buf[64];
+	for_br=Skip=false;	if_pos=0;	ScanFunc(0);	fn_stack.clear();
+	for(long i=0;i<n;i++)	ScanFunc(text[i]);
+	for(long i=0;i<n;i++)
+	{
+		gr->SetWarn(-1, "");
+		gr->SetObjId(i+1+StarObhID);
+		long r = Parse(gr,text[i],i+1);
+		if(r<0)	{	i = -r-2;	continue;	}
+		if(r==1)		snprintf(buf,64,_("\nWrong argument(s) in line %ld"), i+1);
+		else if(r==2)	snprintf(buf,64,_("\nWrong command in line %ld"), i+1);
+		else if(r==3)	snprintf(buf,64,_("\nString too long in line %ld"), i+1);
+		else if(r==4)	snprintf(buf,64,_("\nUnbalanced ' in line %ld"), i+1);
+		else if(r==5)	snprintf(buf,64,_("\nChange temporary data in line %ld"), i+1);
+		else if(gr->GetWarn()>0)	snprintf(buf,64,_("in line %ld"), i+1);
+		else *buf=0;
+		buf[63] = 0;
+		if(*buf)	gr->SetWarn(-2,buf);
+		if(r>0 && r<5)	res=r;
+	}
+	int code[]={mglScrArg,	mglScrCmd,	mglScrLong,	mglScrStr, mglScrTemp};
+	if(res>0)	gr->SetWarn(code[res-1],_("MGL Parser"));
+}
+//-----------------------------------------------------------------------------
+void mglParser::Execute(mglGraph *gr, const wchar_t *text)
+{
+	size_t s = mgl_wcslen(text)+1, n=1;
+	wchar_t *wcs = new wchar_t[s];
+	const wchar_t **str;
+	for(size_t i=0;i<s;i++)	if(text[i]=='\n')	n++;
+	str = (const wchar_t **)malloc(n*sizeof(wchar_t *));
+	memcpy(wcs, text, s*sizeof(wchar_t));
+	str[0] = wcs;	n=1;
+	long next=0;
+	Stop = false;
+	for(size_t i=0;i<s;i++)
+	{
+		if(text[i]=='\\')	next = i;
+		else if(text[i]>' ')next = 0;
+		if(text[i]=='\n')
+		{	// if string need to be continued then I but ' ' instead of 0x0 and
+			// pointer next string to 0x0. Last one for keeping number of strings.
+			if(next)
+			{	for(size_t ii=next;ii<=i;ii++)	wcs[ii]='\b';	str[n] = wcs+s-1;	next=0;	}
+			else
+			{	wcs[i]=0;	str[n] = wcs+i+1;	}
+			n++;
+		}
+	}
+	Execute(gr, n, str);
+	delete []wcs;	free(str);
+}
+//-----------------------------------------------------------------------------
+void mglParser::Execute(mglGraph *gr, const char *text)
+{
+	MGL_TO_WCS(text, Execute(gr, wcs));
+}
+//-----------------------------------------------------------------------------
+void mglParser::DeleteVar(const char *name)
+{
+	MGL_TO_WCS(name,DeleteVar(wcs));
+}
+//-----------------------------------------------------------------------------
+void mglParser::DeleteVar(const wchar_t *name)
+{
+	for(size_t i=0;i<DataList.size();i++)	if(DataList[i] && DataList[i]->s==name)
+	{	mglDataA *u=DataList[i];	DataList[i]=0;	delete u;	}
+}
+//-----------------------------------------------------------------------------
+void mglParser::AddCommand(const mglCommand *cmd)
+{
+	// determine the number of symbols
+	size_t mp=0;	while(Cmd[mp].name[0])	mp++;
+	size_t mc=0;	while(cmd[mc].name[0])	mc++;
+	// copy all together
+	mglCommand *buf = new mglCommand[mp+mc+1];
+	memcpy(buf, cmd, mc*sizeof(mglCommand));
+	memcpy(buf+mc, Cmd, (mp+1)*sizeof(mglCommand));
+	qsort(buf, mp+mc, sizeof(mglCommand), mgl_cmd_cmp);	// sort it
+#pragma omp critical(cmd_parser)
+	{	if(Cmd && Cmd!=BaseCmd)   delete []Cmd;	Cmd = buf;	}
+}
+//-----------------------------------------------------------------------------
+HMPR MGL_EXPORT mgl_create_parser()		{	return new mglParser;	}
+void MGL_EXPORT mgl_delete_parser(HMPR p)	{	delete p;	}
+void MGL_EXPORT mgl_parser_add_param(HMPR p, int id, const char *str)			{	p->AddParam(id,str);	}
+void MGL_EXPORT mgl_parser_add_paramw(HMPR p, int id, const wchar_t *str)		{	p->AddParam(id,str);	}
+MGL_EXPORT mglDataA *mgl_parser_add_var(HMPR p, const char *name)	{	return p->AddVar(name);	}
+MGL_EXPORT mglDataA *mgl_parser_find_var(HMPR p, const char *name)	{	return p->FindVar(name);}
+void MGL_EXPORT mgl_parser_del_var(HMPR p, const char *name)	{	p->DeleteVar(name);	}
+MGL_EXPORT mglDataA *mgl_parser_add_varw(HMPR p, const wchar_t *name)	{	return p->AddVar(name);	}
+MGL_EXPORT mglDataA *mgl_parser_find_varw(HMPR p, const wchar_t *name)	{	return p->FindVar(name);}
+void MGL_EXPORT mgl_parser_del_varw(HMPR p, const wchar_t *name)	{	p->DeleteVar(name);	}
+int MGL_EXPORT mgl_parse_line(HMGL gr, HMPR p, const char *str, int pos)
+{	return p->Parse(gr, str, pos);	}
+int MGL_EXPORT mgl_parse_linew(HMGL gr, HMPR p, const wchar_t *str, int pos)
+{	return p->Parse(gr, str, pos);	}
+void MGL_EXPORT mgl_parse_text(HMGL gr, HMPR p, const char *str)
+{	p->Execute(gr, str);	}
+void MGL_EXPORT mgl_parse_textw(HMGL gr, HMPR p, const wchar_t *str)
+{	p->Execute(gr, str);	}
+void MGL_EXPORT mgl_parse_file(HMGL gr, HMPR p, FILE *fp, int print)
+{	p->Execute(gr,fp,print);	}
+void MGL_EXPORT mgl_parser_restore_once(HMPR p)	{	p->RestoreOnce();	}
+void MGL_EXPORT mgl_parser_stop(HMPR p)	{	p->Stop = true;		}
+void MGL_EXPORT mgl_parser_allow_setsize(HMPR p, int a)	{	p->AllowSetSize= a;	}
+void MGL_EXPORT mgl_parser_allow_file_io(HMPR p, int a)	{	p->AllowFileIO = a;	}
+void MGL_EXPORT mgl_parser_allow_dll_call(HMPR p, int a){	p->AllowDllCall = a;	}
+//-----------------------------------------------------------------------------
+#define _PR_	((mglParser *)(*p))
+uintptr_t MGL_EXPORT mgl_create_parser_()	{	return uintptr_t(new mglParser);	}
+void MGL_EXPORT mgl_delete_parser_(uintptr_t* p)	{	delete _PR_;	}
+void MGL_EXPORT mgl_parser_add_param_(uintptr_t* p, int *id, const char *str, int l)
+{	char *s=new char[l+1];		memcpy(s,str,l);	s[l]=0;
+	_PR_->AddParam(*id, s);		delete []s;	}
+/*===!!! NOTE !!! You must not delete obtained data arrays !!!===============*/
+uintptr_t MGL_EXPORT mgl_parser_add_var_(uintptr_t* p, const char *name, int l)
+{	char *s=new char[l+1];		memcpy(s,name,l);	s[l]=0;
+	mglDataA *v=_PR_->AddVar(s);	delete []s;	return uintptr_t(v);	}
+/*===!!! NOTE !!! You must not delete obtained data arrays !!!===============*/
+uintptr_t MGL_EXPORT mgl_parser_find_var_(uintptr_t* p, const char *name, int l)
+{	char *s=new char[l+1];		memcpy(s,name,l);	s[l]=0;
+	mglDataA *v=_PR_->FindVar(s);	delete []s;	return uintptr_t(v);	}
+void MGL_EXPORT mgl_parser_del_var_(uintptr_t* p, const char *name, int l)
+{	char *s=new char[l+1];		memcpy(s,name,l);	s[l]=0;
+	_PR_->DeleteVar(s);	delete []s;	}
+int MGL_EXPORT mgl_parse_line_(uintptr_t* gr, uintptr_t* p, const char *str, int *pos, int l)
+{	char *s=new char[l+1];		memcpy(s,str,l);	s[l]=0;
+	int r = _PR_->Parse(_GR_, s, *pos);	delete []s;	return r;	}
+void MGL_EXPORT mgl_parse_text_(uintptr_t* gr, uintptr_t* p, const char *str, int l)
+{	char *s=new char[l+1];		memcpy(s,str,l);	s[l]=0;
+	_PR_->Execute(_GR_, s);	delete []s;	}
+void MGL_EXPORT mgl_parser_restore_once_(uintptr_t* p)	{	_PR_->RestoreOnce();	}
+void MGL_EXPORT mgl_parser_allow_setsize_(uintptr_t* p, int *a)	{	_PR_->AllowSetSize= *a;	}
+void MGL_EXPORT mgl_parser_allow_file_io_(uintptr_t* p, int *a)	{	_PR_->AllowFileIO = *a;	}
+void MGL_EXPORT mgl_parser_allow_dll_call_(uintptr_t* p, int *a){	_PR_->AllowDllCall= *a;	}
+void MGL_EXPORT mgl_parser_stop_(uintptr_t* p)	{	_PR_->Stop = true;	}
+//-----------------------------------------------------------------------------
+long MGL_EXPORT mgl_use_parser(HMPR pr, int inc)
+{	pr->InUse+=inc;	return pr->InUse;	}
+long MGL_EXPORT mgl_use_parser_(uintptr_t *p, int *inc)
+{	_PR_->InUse+=*inc;	return _PR_->InUse;	}
+//---------------------------------------------------------------------------
+MGL_EXPORT mglDataA *mgl_parser_get_var(HMPR p, unsigned long id)
+{	return id<p->DataList.size()?p->DataList[id]:0;	}
+uintptr_t MGL_EXPORT mgl_parser_get_var_(uintptr_t* p, unsigned long *id)
+{	return uintptr_t(mgl_parser_get_var(_PR_,*id));	}
+long MGL_EXPORT mgl_parser_num_var(HMPR p)
+{	return p->DataList.size();	}
+long MGL_EXPORT mgl_parser_num_var_(uintptr_t* p)
+{	return mgl_parser_num_var(_PR_);	}
+long MGL_EXPORT mgl_parser_num_const(HMPR p)
+{	return p->NumList.size();	}
+long MGL_EXPORT mgl_parser_num_const_(uintptr_t* p)
+{	return mgl_parser_num_const(_PR_);	}
+MGL_EXPORT mglNum *mgl_parser_get_const(HMPR p, unsigned long id)
+{	return id<p->NumList.size()?p->NumList[id]:0;	}
+uintptr_t MGL_EXPORT mgl_parser_get_const_(uintptr_t* p, unsigned long *id)
+{	return uintptr_t(mgl_parser_get_const(_PR_,*id));	}
+//---------------------------------------------------------------------------
+int MGL_EXPORT mgl_parser_cmd_type(HMPR pr, const char *name)
+{
+	const mglCommand *cmd = pr->FindCommand(name);
+	return cmd ? cmd->type + 1 : 0;
+}
+int MGL_EXPORT mgl_parser_cmd_type_(uintptr_t* p, const char *str, int l)
+{	char *s=new char[l+1];	memcpy(s,str,l);	s[l]=0;
+	l = mgl_parser_cmd_type(_PR_, s);	delete []s;	return l;	}
+//---------------------------------------------------------------------------
+MGL_EXPORT const char *mgl_parser_cmd_desc(HMPR pr, const char *name)
+{
+	const mglCommand *cmd = pr->FindCommand(name);
+	return cmd ? cmd->desc : 0;
+}
+MGL_EXPORT const char *mgl_parser_cmd_frmt(HMPR pr, const char *name)
+{
+	const mglCommand *cmd = pr->FindCommand(name);
+	return cmd ? cmd->form : 0;
+}
+//---------------------------------------------------------------------------
+MGL_EXPORT const char *mgl_parser_cmd_name(HMPR pr, long id)
+{	return (id<mgl_parser_cmd_num(pr) && id>=0) ? pr->Cmd[id].name:"";	}
+long MGL_EXPORT mgl_parser_cmd_num(HMPR pr)
+{	long i=0;	while(pr->Cmd[i].name[0])	i++; 	return i;	}
+//---------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_parser_calc(HMPR pr, const char *formula)
+{	HMDT d=0;	MGL_TO_WCS(formula,d = mgl_parser_calcw(pr,wcs));	return d;	}
+HMDT MGL_EXPORT mgl_parser_calcw(HMPR pr, const wchar_t *formula)
+{	return mglFormulaCalc(formula,pr, pr->DataList);	}
+uintptr_t MGL_EXPORT mgl_parser_calc_(uintptr_t *p, const char *str,int l)
+{	char *s=new char[l+1];	memcpy(s,str,l);	s[l]=0;
+	uintptr_t d = (uintptr_t)mgl_parser_calc(_PR_, s);	delete []s;	return d;	}
+//---------------------------------------------------------------------------
+HADT MGL_EXPORT mgl_parser_calc_complex(HMPR pr, const char *formula)
+{	HADT d=0;	MGL_TO_WCS(formula,d = mgl_parser_calc_complexw(pr,wcs));	return d;	}
+HADT MGL_EXPORT mgl_parser_calc_complexw(HMPR pr, const wchar_t *formula)
+{	return mglFormulaCalcC(formula,pr, pr->DataList);	}
+uintptr_t MGL_EXPORT mgl_parser_calc_complex_(uintptr_t *p, const char *str,int l)
+{	char *s=new char[l+1];	memcpy(s,str,l);	s[l]=0;
+	uintptr_t d = (uintptr_t)mgl_parser_calc_complex(_PR_, s);	delete []s;	return d;	}
+//---------------------------------------------------------------------------
+void MGL_EXPORT mgl_parser_del_all(HMPR p)	{	p->DeleteAll();	}
+void MGL_EXPORT mgl_parser_del_all_(uintptr_t *p)	{	_PR_->DeleteAll();	}
+//---------------------------------------------------------------------------
+void MGL_EXPORT mgl_parser_load(HMPR pr, const char *so_name)
+{
+	if(!pr->AllowDllCall)	return;
+#if MGL_HAVE_LTDL
+	lt_dlhandle so = lt_dlopen(so_name);
+	if(!so)	return;
+	const mglCommand *cmd = (const mglCommand *)lt_dlsym(so,"mgl_cmd_extra");
+	bool exist = true;
+	if(cmd)	for(size_t i=0;cmd[i].name[0];i++)
+		if(!pr->FindCommand(cmd[i].name))	exist=false;
+	if(exist)	{	lt_dlclose(so);	return;	}	// all commands already presents
+	else	pr->DllOpened.push_back(so);
+	pr->AddCommand(cmd);
+#endif
+}
+void MGL_EXPORT mgl_parser_load_(uintptr_t *p, const char *dll_name,int l)
+{	char *s=new char[l+1];	memcpy(s,dll_name,l);	s[l]=0;
+	mgl_parser_load(_PR_, s);	delete []s;	}
+//---------------------------------------------------------------------------
+struct mglRKdat
+{
+	mglDataA *v;
+	std::wstring e;
+	bool cmplx;
+	mglDataC cin,c1,c2,c3,c4, *cc;
+	mglData  din,d1,d2,d3,d4, *dd;
+	mglRKdat(mglDataA *var, std::wstring &eq):v(var), e(eq)
+	{	cmplx = dynamic_cast<mglDataC*>(var);	cc=0;	dd=0;	}
+	void allocate()
+	{
+		if(cmplx)
+		{	cc = dynamic_cast<mglDataC*>(v);	cin.Set(v);	}
+		else
+		{	dd = dynamic_cast<mglData*>(v);		din.Set(v);	}
+	}
+};
+void MGL_EXPORT mgl_rk_step_w(HMPR pr, const wchar_t *Eqs, const wchar_t *Vars, mreal dt)
+{
+	const std::wstring eqs(Eqs);
+	const std::wstring vars(Vars);
+	std::vector<mglRKdat> rkv;
+	size_t iv=0,jv=0,ie=0,je=0;
+	while(1)
+	{
+		iv = vars.find(';',jv);	ie = eqs.find(';',je);
+		mglDataA *vv=mgl_parser_find_varw(pr,vars.substr(jv,iv-jv).c_str());
+		std::wstring eq = eqs.substr(je,ie-je).c_str();
+		if(vv)	rkv.push_back(mglRKdat(vv, eq ));
+		jv = iv+1;	je = ie+1;
+		if(iv==std::wstring::npos || ie==std::wstring::npos)	break;
+	}
+	for(size_t i=0;i<rkv.size();i++)	rkv[i].allocate();
+	mreal hh = dt/2;
+	for(size_t i=0;i<rkv.size();i++)
+	{
+		mglRKdat &rk = rkv[i];
+		if(rk.cmplx)	rk.c1.Move(mglFormulaCalcC(rk.e, pr, pr->DataList));
+		else	rk.d1.Move(mglFormulaCalc(rk.e, pr, pr->DataList));
+	}
+	for(size_t i=0;i<rkv.size();i++)
+	{
+		mglRKdat &rk = rkv[i];
+		if(rk.cc)
+		{
+			long n = rk.cc->GetNN();	dual a = hh*rk.c1.a[0];
+			if(rk.c1.GetNN()==n)
+#pragma omp parallel for
+				for(long j=0;j<n;j++)	rk.cc->a[j] = rk.cin.a[j] + hh*rk.c1.a[j];
+			else
+#pragma omp parallel for
+				for(long j=0;j<n;j++)	rk.cc->a[j] = rk.cin.a[j] + a;
+		}
+		if(rk.dd)
+		{
+			long n = rk.dd->GetNN();	mreal a = hh*rk.d1.a[0];
+			if(rk.d1.GetNN()==n)
+#pragma omp parallel for
+				for(long j=0;j<n;j++)	rk.dd->a[j] = rk.din.a[j] + hh*rk.d1.a[j];
+			else
+#pragma omp parallel for
+				for(long j=0;j<n;j++)	rk.dd->a[j] = rk.din.a[j] + a;
+		}
+	}
+
+	for(size_t i=0;i<rkv.size();i++)
+	{
+		mglRKdat &rk = rkv[i];
+		if(rk.cmplx)	rk.c2.Move(mglFormulaCalcC(rk.e, pr, pr->DataList));
+		else	rk.d2.Move(mglFormulaCalc(rk.e, pr, pr->DataList));
+	}
+	for(size_t i=0;i<rkv.size();i++)
+	{
+		mglRKdat &rk = rkv[i];
+		if(rk.cc)
+		{
+			long n = rk.cc->GetNN();	dual a = hh*rk.c2.a[0];
+			if(rk.c2.GetNN()==n)
+#pragma omp parallel for
+				for(long j=0;j<n;j++)	rk.cc->a[j] = rk.cin.a[j] + hh*rk.c2.a[j];
+			else
+#pragma omp parallel for
+				for(long j=0;j<n;j++)	rk.cc->a[j] = rk.cin.a[j] + a;
+		}
+		if(rk.dd)
+		{
+			long n = rk.dd->GetNN();	mreal a = hh*rk.d2.a[0];
+			if(rk.d2.GetNN()==n)
+#pragma omp parallel for
+				for(long j=0;j<n;j++)	rk.dd->a[j] = rk.din.a[j] + hh*rk.d2.a[j];
+			else
+#pragma omp parallel for
+				for(long j=0;j<n;j++)	rk.dd->a[j] = rk.din.a[j] + a;
+		}
+	}
+
+	for(size_t i=0;i<rkv.size();i++)
+	{
+		mglRKdat &rk = rkv[i];
+		if(rk.cmplx)	rk.c3.Move(mglFormulaCalcC(rk.e, pr, pr->DataList));
+		else	rk.d3.Move(mglFormulaCalc(rk.e, pr, pr->DataList));
+	}
+	for(size_t i=0;i<rkv.size();i++)
+	{
+		mglRKdat &rk = rkv[i];
+		if(rk.cc)
+		{
+			long n = rk.cc->GetNN();	dual a = dt*rk.c3.a[0];
+			if(rk.c3.GetNN()==n)
+#pragma omp parallel for
+				for(long j=0;j<n;j++)	rk.cc->a[j] = rk.cin.a[j] + dt*rk.c3.a[j];
+			else
+#pragma omp parallel for
+				for(long j=0;j<n;j++)	rk.cc->a[j] = rk.cin.a[j] + a;
+		}
+		if(rk.dd)
+		{
+			long n = rk.dd->GetNN();	mreal a = dt*rk.d3.a[0];
+			if(rk.d3.GetNN()==n)
+#pragma omp parallel for
+				for(long j=0;j<n;j++)	rk.dd->a[j] = rk.din.a[j] + dt*rk.d3.a[j];
+			else
+#pragma omp parallel for
+				for(long j=0;j<n;j++)	rk.dd->a[j] = rk.din.a[j] + a;
+		}
+	}
+
+	for(size_t i=0;i<rkv.size();i++)
+	{
+		mglRKdat &rk = rkv[i];
+		if(rk.cmplx)	rk.c4.Move(mglFormulaCalcC(rk.e, pr, pr->DataList));
+		else	rk.d4.Move(mglFormulaCalc(rk.e, pr, pr->DataList));
+	}
+	for(size_t i=0;i<rkv.size();i++)
+	{
+		mglRKdat &rk = rkv[i];
+		if(rk.cc)
+		{
+			long n = rk.cc->GetNN();
+			dual a = (rk.c1.a[0]+rk.c2.a[0]+mreal(2)*(rk.c3.a[0]+rk.c4.a[0]))*(dt/6);
+			if(rk.c1.GetNN()==n)
+#pragma omp parallel for
+				for(long j=0;j<n;j++)	rk.cc->a[j] = rk.cin.a[j] + (rk.c1.a[j]+rk.c2.a[j]+mreal(2)*(rk.c3.a[j]+rk.c4.a[j]))*(dt/6);
+			else
+#pragma omp parallel for
+				for(long j=0;j<n;j++)	rk.cc->a[j] = rk.cin.a[j] + a;
+		}
+		if(rk.dd)
+		{
+			long n = rk.dd->GetNN();
+			mreal a = (rk.d1.a[0]+rk.d2.a[0]+2*(rk.d3.a[0]+rk.d4.a[0]))*(dt/6);
+			if(rk.d1.GetNN()==n)
+#pragma omp parallel for
+				for(long j=0;j<n;j++)	rk.dd->a[j] = rk.din.a[j] + (rk.d1.a[j]+rk.d2.a[j]+2*(rk.d3.a[j]+rk.d4.a[j]))*(dt/6);
+			else
+#pragma omp parallel for
+				for(long j=0;j<n;j++)	rk.dd->a[j] = rk.din.a[j] + a;
+		}
+	}
+}
+void MGL_EXPORT mgl_rk_step(HMPR pr, const char *Eqs, const char *Vars, mreal dt)
+{
+	if(Eqs && *Eqs && Vars && *Vars)
+	{
+		size_t s=mbstowcs(0,Eqs,0), w=mbstowcs(0,Vars,0);
+		wchar_t *eqs=new wchar_t[s+1];	mbstowcs(eqs,Eqs ,s);	eqs[s]=0;
+		wchar_t *wcs=new wchar_t[s+1];	mbstowcs(wcs,Vars,s);	wcs[w]=0;
+		mgl_rk_step_w(pr,eqs,wcs,dt);	delete []wcs;	delete []eqs;
+	}
+}
+void MGL_EXPORT mgl_rk_step_(uintptr_t *p, const char *eqs, const char *vars, double *dt,int l,int m)
+{	char *e=new char[l+1];	memcpy(e,eqs,l);	e[l]=0;
+	char *s=new char[m+1];	memcpy(s,vars,m);	s[m]=0;
+	mgl_rk_step(_PR_,e,s,*dt);	delete []e;	delete []s;	}
+//---------------------------------------------------------------------------
+void MGL_EXPORT mgl_parser_variant(HMPR p, int var)	{	p->SetVariant(var);	}
+void MGL_EXPORT mgl_parser_variant_(uintptr_t *p, int *var)	{	mgl_parser_variant(_PR_,*var);	}
+//---------------------------------------------------------------------------
+void MGL_EXPORT mgl_parser_openhdf(HMPR p, const char *fname)
+{
+	const char * const *res = mgl_datas_hdf_str(fname);
+	if(!res)	return;
+	for(size_t n=0;res[n][0];n++)
+	{
+		mglDataA *d = p->AddVar(res[n]);
+		mglData *dr = dynamic_cast<mglData*>(d);
+		mglDataC *dc = dynamic_cast<mglDataC*>(d);
+		if(dr)	dr->ReadHDF(fname,res[n]);
+		if(dc)	dc->ReadHDF(fname,res[n]);
+	}
+}
+void MGL_EXPORT mgl_parser_openhdf_(uintptr_t *p, const char *fname,int l)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	mgl_parser_openhdf(_PR_,s);	delete []s;	}
+//---------------------------------------------------------------------------
+void MGL_EXPORT mgl_parser_start_id(HMPR pr, int id)
+{	pr->StarObhID = id;	}
+void MGL_EXPORT mgl_parser_start_id_(uintptr_t* p, int *id)
+{	mgl_parser_start_id(_PR_, *id);	}
+
+//---------------------------------------------------------------------------
+mglCommand mgls_prg_cmd[] = {
+	{"ask",_("Define parameter from user input"),"ask $N 'question'", 0, 6},
+	{"break",_("Break for-loop"),"break", 0, 6},
+	{"call",_("Execute script in external file"),"call 'name' [args]", 0, 6},
+	{"continue",_("Skip commands and iterate for-loop again"),"continue", 0, 6},
+	{"defchr",_("Define parameter as character"),"defchr $N val", 0, 6},
+	{"define",_("Define constant or parameter"),"define $N sth | Var val", 0, 6},
+	{"defnum",_("Define parameter as numerical value"),"defnum $N val", 0, 6},
+//	{"defpal",_("Define parameter as palette color"),"defpal $N val", 0, 6},
+	{"else",_("Execute if condition is false"),"else", 0, 6},
+	{"elseif",_("Conditional operator"),"elseif val|Dat ['cond']", 0, 6},
+	{"endif",_("Finish if/else block"),"endif", 0, 6},
+	{"for",_("For loop"),"for $N v1 v2 [dv] | $N Dat", 0, 6},
+	{"func",_("Start function definition and stop execution of main script"),"func 'name' [narg]", 0, 6},
+	{"if",_("Conditional operator"),"if val|Dat ['cond']", 0, 6},
+	{"list",_("Creates new variable from list of numbers or data"),"list Var v1 ...|Var D1 ...", 0, 4},
+	{"next",_("Start next for-loop iteration"),"next", 0, 6},
+	{"once",_("Start/close commands which should executed only once"),"once val", 0, 6},
+	{"return",_("Return from function"),"return", 0, 6},
+	{"stop",_("Stop execution"),"stop", 0, 6},
+{"","","",NULL,0}};
+//-----------------------------------------------------------------------------
diff --git a/src/pde.cpp b/src/pde.cpp
new file mode 100644
index 0000000..81cd9df
--- /dev/null
+++ b/src/pde.cpp
@@ -0,0 +1,1500 @@
+/***************************************************************************
+ * pde.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include "mgl2/data.h"
+#include "mgl2/datac.h"
+#include "mgl2/eval.h"
+#include "mgl2/thread.h"
+#include "mgl2/base.h"
+const double GAMMA=0.1;	///< value for damping
+HADT MGL_NO_EXPORT mglFormulaCalcC(const char *str, const std::vector<mglDataA*> &head);
+//-----------------------------------------------------------------------------
+//
+//		Advanced PDE series in 2D case
+//
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_operator_exp(long n, dual *h, dual *a, dual *f)
+{
+	memset(f,0,2*n*sizeof(dual));
+	const long i1=n/2, i2=3*n/2-1;
+#pragma omp parallel for
+	for(long j=0;j<n;j++)
+	{
+		long jp = (j+1)%n;
+		dual h1=h[n*j]*dual(0,1),		g1=(h1+h[n*jp]*dual(0,1))/mreal(2);
+		dual h2=h[n-1+n*j]*dual(0,1),	g2=(h2+h[n-1+n*jp]*dual(0,1))/mreal(2);
+		mreal k1=M_PI*2*j/n, k2 = M_PI*(2*j+1)/n;
+		for(long i=0;i<i1;i++)
+		{
+			f[2*j] += a[i]*exp(h1+dual(0,i*k1));
+			f[2*j+1] += a[i]*exp(g1+dual(0,i*k2));
+		}
+		for(long i=i1;i<i2;i++)
+		{
+			dual hh = h[i-i1+n*j];
+			f[2*j] += a[i]*exp(hh*dual(0,1)+dual(0,i*k1));
+			f[2*j+1] += a[i]*exp((hh+h[i-i1+n*jp])*dual(0,0.5)+dual(0,i*k2));
+		}
+		for(long i=i2;i<2*n;i++)
+		{
+			f[2*j] += a[i]*exp(h2+dual(0,i*k1));
+			f[2*j+1] += a[i]*exp(g2+dual(0,i*k2));
+		}
+	}
+	memset(a,0,2*n*sizeof(dual));
+#pragma omp parallel for
+	for(long i=0;i<2*n;i++)
+	{
+		long ii=i-i1;
+		if(ii<0)	ii=0;
+		if(ii>n-1)	ii=n-1;
+		double kk=M_PI*2*i/n;
+		for(long j=0;j<n;j++)
+		{
+			dual h1 = h[ii+n*j], g1 = (h1+h[ii+n*((j+1)%n)])*dual(0,0.5);
+			a[i] += f[2*j]*exp(h1*dual(0,1)-dual(0,kk*j));
+			a[i] += f[2*j+1]*exp(g1-dual(0,kk*(j+0.5)));
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_operator_lin(long n, mreal *h, dual *a, dual *f, dual *g, dual *o)
+{
+	memset(f,0,2*n*sizeof(dual));
+	memset(g,0,2*n*sizeof(dual));
+	const long i1=n/2, i2=3*n/2-1;
+#pragma omp parallel for
+	for(long j=0;j<n;j++)
+	{
+		long jp = (j+1)%n;
+		mreal h1=tanh(h[n*j]), g1=(h1+tanh(h[n*jp]))/2;
+		mreal h2=tanh(h[n-1+n*j]), g2=(h2+tanh(h[n-1+n*jp]))/2;
+		mreal k1=M_PI*2*j/n, k2 = M_PI*(2*j+1)/n;
+		for(long i=0;i<i1;i++)
+		{
+			dual e1=exp(dual(0,i*k1)), e2=exp(dual(0,i*k2));
+			f[2*j] += a[i]*h1*e1;	f[2*j+1] += a[i]*g1*e2;
+			g[2*j] += a[i]*e1;		g[2*j+1] += a[i]*e2;
+		}
+		for(long i=i1;i<i2;i++)
+		{
+			mreal hh = tanh(h[i-i1+n*j]);
+			mreal gg = (hh+tanh(h[i-i1+n*jp]))/2;
+			dual e1=exp(dual(0,i*k1)), e2=exp(dual(0,i*k2));
+			f[2*j] += a[i]*hh*e1;	f[2*j+1] += a[i]*gg*e2;
+			g[2*j] += a[i]*e1;		g[2*j+1] += a[i]*e2;
+		}
+		for(long i=i2;i<2*n;i++)
+		{
+			dual e1=exp(dual(0,i*k1)), e2=exp(dual(0,i*k2));
+			f[2*j] += a[i]*h2*e1;	f[2*j+1] += a[i]*g2*e2;
+			g[2*j] += a[i]*e1;		g[2*j+1] += a[i]*e2;
+		}
+	}
+	memset(o,0,2*n*sizeof(dual));
+#pragma omp parallel for
+	for(long i=0;i<2*n;i++)
+	{
+		long ii=i-i1;
+		if(ii<0)	ii=0;
+		if(ii>n-1)	ii=n-1;
+		double kk=M_PI*2*i/n;
+		for(long j=0;j<n;j++)
+		{
+			mreal h1 = tanh(h[ii+n*j]);
+			mreal g1 = (h1+tanh(h[ii+n*((j+1)%n)]))/2;
+			dual e1=exp(dual(0,-j*kk)), e2=exp(dual(0,-kk*(j+0.5)));
+			o[i] += f[2*j]*e1 + f[2*j+1]*e2;
+			o[i] += g[2*j]*h1*e1 + g[2*j+1]*g1*e2;
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+HADT MGL_NO_EXPORT mgl_apde_calc_ham(HMDT hs, bool old, const char *func, std::vector<mglDataA*> list, const mreal dd)
+{
+	HADT ham = mglFormulaCalcC(func, list);	mgl_datac_mul_num(ham,dd);
+	const long nx = ham->nx;
+	if(old)
+	{
+		mreal hh = ham->Imag().Minimal();
+		if(hh>0)	hh=0;
+#pragma omp parallel for
+		for(long i=0;i<nx*nx;i++)
+		{
+			hs->a[i] = sqrt(imag(ham->a[i])-hh);	// non-additive term
+			ham->a[i] = dual(real(ham->a[i]),hh);	// additive terms
+		}
+	}
+	else
+	{
+		mglData xIm(nx), pIm(nx);
+#pragma omp parallel for
+		for(long i=0;i<nx;i++)	// first find minimal values along x and p
+		{
+			dual *ax=ham->a+i, *ay=ham->a+i*nx;
+			mreal mx=imag(ax[0]), my=imag(ay[0]);
+			for(long j=1;j<nx;j++)	my = (my<imag(ay[j]))?my:imag(ay[j]);
+			for(long j=1;j<nx;j++)	mx = (mx<imag(ax[j*nx]))?mx:imag(ax[j*nx]);
+			xIm.a[i] = mx;	pIm.a[i]=my;
+		}
+		mreal mIm=xIm.a[0];	mreal *aa=xIm.a;	// global minimum
+		for(long j=1;j<nx;j++)	mIm = (mIm<aa[j])?mIm:aa[j];
+#pragma omp parallel for collapse(2)
+		for(long j=0;j<nx;j++)	for(long i=0;i<nx;i++)
+		{
+			mreal hh = xIm.a[i]+pIm.a[j]-mIm;
+			long i0=i+nx*j;
+			hs->a[i0] = sqrt(fabs(imag(ham->a[i0])-hh));	// non-additive term. NOTE: fabs() guarantee absence of negative values due to rounding error
+			ham->a[i0] = dual(real(ham->a[i0]),hh);	// additive terms
+		}
+	}
+	return ham;
+}
+//-----------------------------------------------------------------------------
+// Solve equation dx/dy = func(p,x,y,|u|)[u] where p=d/dx. There are no assumptions about form of func().
+HADT MGL_EXPORT mgl_pde_adv_c(HMGL gr, const char *func, HCDT ini_re, HCDT ini_im, mreal dt, mreal k0, const char *opt)
+{
+	mreal gamma = gr->SaveState(opt);	if(mgl_isnan(gamma))	gamma = 20;
+	const mglPoint &Min=gr->Min, &Max=gr->Max;
+	const long nx=ini_re->GetNx(), nt = long((Max.y-Min.y)/dt)+1;
+	if(nx<2 || nt<2 || Max.x==Min.x){	gr->SetWarn(mglWarnLow,"PDE");	return 0;	}	// Too small data
+	if(ini_im->GetNx() != nx)		{	gr->SetWarn(mglWarnDim,"PDE");	return 0;	}	// Wrong dimensions
+
+	mglDataC *res=new mglDataC(nx, nt);
+	mglData hIm(nx,nx);	// for advanced damping calculation
+	mglDataC u(nx);	u.s = L"u";
+	mglDataV x(nx,nx), y(nx,nx), r(nx,nx);
+	mglDataW p(nx,nx);	p.s = L"p";
+	bool old = func[0]==';';	if(old)	func=func+1;
+	x.s = L"x";	y.s = L"y";	r.s=L"#$mgl";
+	const mreal dp = 2*M_PI/(Max.x-Min.x), dd = k0*dt/2;
+	x.Fill(Min.x,Max.x,'x');	p.Freq(dp/k0,'y');
+	std::vector<mglDataA*> list;
+	list.push_back(&x);	list.push_back(&y);	list.push_back(&p);	list.push_back(&r);	list.push_back(&u);
+
+	dual *a = new dual[2*nx];	memset(a,0,2*nx*sizeof(dual));	// Add "damping" area
+	dual *f = new dual[6*nx], *g=f+2*nx, *s=f+4*nx;
+#pragma omp parallel for
+	for(long i=0;i<nx;i++)	// Initial conditions
+		a[i+nx/2] = dual(ini_re->v(i), ini_im->v(i));
+	double *dmp = new double[2*nx];	memset(dmp,0,2*nx*sizeof(double));
+#pragma omp parallel for
+	for(long i=0;i<2*nx;i++)	// dumping
+	{
+		if(i<nx/2)		dmp[i] += gamma*mgl_ipow((nx/2-i)/mreal(nx/2),2);
+		if(i>3*nx/2)	dmp[i] += gamma*mgl_ipow((i-3*nx/2-1)/mreal(nx/2),2);
+	}
+	bool have_y = mglchr(func,'y');
+	HADT ham;
+	if(!have_y)		ham = mgl_apde_calc_ham(&hIm, old, func, list, dd);
+	for(long k=0;k<nt;k++)
+	{
+		memcpy(u.a,a+nx/2,nx*sizeof(dual));
+		memcpy(res->a+k*nx,a+nx/2,nx*sizeof(dual));
+		if(have_y)
+		{	y.Fill(k*dt);	ham = mgl_apde_calc_ham(&hIm, old, func, list, dd);	}
+		mgl_operator_exp(nx,ham->a,a,f);
+		mgl_operator_lin(nx,hIm.a,a,f,g,s);
+		mgl_operator_lin(nx,hIm.a,s,f,g,s);
+#pragma omp parallel for
+		for(long i=0;i<2*nx;i++)
+			a[i] = (a[i]-s[i]/mreal(8*nx*nx))*mreal(exp(-dmp[i]*dt)/2/nx);
+		if(have_y)	delete ham;
+	}
+	delete []a;	delete []f;	delete []dmp;
+	if(!have_y)	delete ham;
+	gr->LoadState();	return res;
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_pde_adv(HMGL gr, const char *ham, HCDT ini_re, HCDT ini_im, mreal dz, mreal k0, const char *opt)
+{
+	HADT res = mgl_pde_adv_c(gr,ham,ini_re,ini_im,dz,k0,opt);
+	HMDT out = mgl_datac_abs(res);	delete res;	return out;
+}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_pde_adv_c_(uintptr_t* gr, const char *ham, uintptr_t* ini_re, uintptr_t* ini_im, mreal *dz, mreal *k0, const char *opt, int l, int lo)
+{	char *s=new char[l+1];	memcpy(s,ham,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	uintptr_t res = uintptr_t(mgl_pde_adv_c(_GR_, s, _DA_(ini_re), _DA_(ini_im), *dz, *k0, o));
+	delete []o;	delete []s;	return res;	}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_pde_adv_(uintptr_t* gr, const char *ham, uintptr_t* ini_re, uintptr_t* ini_im, mreal *dz, mreal *k0, const char *opt, int l, int lo)
+{	char *s=new char[l+1];	memcpy(s,ham,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	uintptr_t res = uintptr_t(mgl_pde_adv(_GR_, s, _DA_(ini_re), _DA_(ini_im), *dz, *k0, o));
+	delete []o;	delete []s;	return res;	}
+//-----------------------------------------------------------------------------
+/*HADT MGL_EXPORT mgl_pde_adv_3d_c(HMGL gr, const char *ham, HCDT ini_re, HCDT ini_im, mreal dz, mreal k0, const char *opt)
+{
+	mreal gamma = gr->SaveState(opt);	if(mgl_isnan(gamma))	gamma = GAMMA;
+	mglPoint Min=gr->Min, Max=gr->Max;
+	long nx=ini_re->GetNx(), ny=ini_re->GetNy(), nz = long((Max.z-Min.z)/dz)+1;
+	if(nx<2 || nz<2 || Max.x==Min.x)			// Too small data
+	{	gr->SetWarn(mglWarnLow,"PDE");	return 0;	}
+	if(ini_im->GetNx()*ini_im->GetNy() != nx*ny)// Wrong dimensions
+	{	gr->SetWarn(mglWarnDim,"PDE");	return 0;	}
+	mglDataC *res=new mglDataC(nz, nx, ny);
+
+	mglDataV x(nx,ny), y(nx,ny), z, r(nx,ny);
+	mglDataW p(nx,ny), q(nx,ny);
+	x.s = L"x";	y.s = L"y";	p.s = L"p";	q.s = L"q";	z.s = L"z";	r.s=L"#$mgl";
+	//z.Fill(f->zz);
+	mreal dx = (Max.x-Min.x)/(nx-1), dy = ny>1?(Max.y-Min.y)/(ny-1):0;
+	mreal dp = M_PI/(Max.x-Min.x), dq = M_PI/(Max.y-Min.y);
+	double dd = k0*dz;
+	x.Fill(Min.x,Max.x,'x');	p.Freq(dp/k0,'x');
+	y.Fill(Min.y,Max.y,'y');	q.Freq(dq/k0,'y');
+
+	ddual *a = new ddual[4*nx*ny];	// Add "damping" area
+	ddual *f = new ddual[4*nx*ny];	// Effective "spectrum"
+	memset(a,0,4*nx*ny*sizeof(ddual));
+	memset(f,0,4*nx*ny*sizeof(ddual));
+#pragma omp parallel for collapse(2)
+	for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)	// Initial conditions
+	{
+		long i0 = i+nx/2+2*nx*(j+ny/2);
+		a[i0] = dual(ini_re->v(i,j), ini_im->v(i,j));
+		res->a[nz*(i+nx*j)] = a[i0];
+	}
+	double *dmp = new double[4*nx*ny];
+	memset(dmp,0,4*nx*ny*sizeof(double));
+#pragma omp parallel for collapse(2)
+	for(long j=0;j<2*ny;j++)	for(long i=0;i<2*nx;i++)	// step 1
+	{
+		long i0 = i+2*nx*j;
+		if(i<nx/2)		dmp[i0] += gamma*mgl_ipow((nx/2-i)/(nx/2.),2);
+		if(i>3*nx/2)	dmp[i0] += gamma*mgl_ipow((i-3*nx/2-1)/(nx/2.),2);
+		if(j<ny/2)		dmp[i0] += gamma*mgl_ipow((ny/2-j)/(ny/2.),2);
+		if(j>3*ny/2)	dmp[i0] += gamma*mgl_ipow((j-3*ny/2-1)/(ny/2.),2);
+	}
+	ddual *Hdat = new ddual[nx*nx*ny*ny];
+	for(long k=1;k<nz;k++)
+	{
+	}
+}*/
+//-----------------------------------------------------------------------------
+//
+//		Simplified PDE series
+//
+//-----------------------------------------------------------------------------
+struct mgl_pde_ham
+{
+	ddual *a,*hxy,*hxv,*huv,*huy;
+	const char *eqs;
+	long nx,ny;
+	double xx,yy,xs,ys,dx,dy,dq,dp,zz;
+	double dd;
+};
+void MGL_NO_EXPORT mgl_pde_hprep(const mgl_pde_ham *f)
+{
+	const long nx = f->nx, ny = f->ny;
+	mglDataV x(nx,ny), y(nx,ny), z, r(nx,ny);
+	mglDataW p(nx,ny), q(nx,ny);
+	x.s = L"x";	y.s = L"y";	p.s = L"p";	q.s = L"q";	r.s=L"#$mgl";
+	z.s = L"z";	z.Fill(f->zz);
+	dual dd(0,f->dd);
+	mglData u(nx,ny);	u.s = L"u";
+#pragma omp parallel for
+	for(long i=0;i<nx*ny;i++)	u.a[i] = abs(f->a[i]);
+	std::vector<mglDataA*> list;
+	list.push_back(&x);	list.push_back(&y);	list.push_back(&z);
+	list.push_back(&p);	list.push_back(&q);	list.push_back(&u);
+
+	x.Fill(f->xx,f->xx+f->dx*(nx-1),'x');	p.Freq(0,'x');
+	y.Fill(f->yy,f->yy+f->dy*(ny-1),'y');	q.Freq(0,'y');
+	HADT res = mglFormulaCalcC(f->eqs, list);
+#pragma omp parallel for
+	for(long i=0;i<nx*ny;i++)	f->hxy[i] = res->a[i]*dd;
+	delete res;
+	if(ny>2)
+	{
+		x.Fill(f->xs);	p.Freq(f->dp,'x');
+		res = mglFormulaCalcC(f->eqs, list);
+#pragma omp parallel for
+		for(long i=0;i<nx*ny;i++)	f->huy[i] = res->a[i]*dd;
+		delete res;
+	}
+	x.Fill(f->xs);	p.Freq(f->dp,'x');
+	y.Fill(f->ys);	q.Freq(f->dq,'y');
+	res = mglFormulaCalcC(f->eqs, list);
+#pragma omp parallel for
+	for(long i=0;i<nx*ny;i++)	f->huv[i] = res->a[i]*dd;
+	delete res;
+	if(ny>2)
+	{
+		x.Fill(f->xx,f->xx+f->dx*(nx-1),'x');	p.Freq(0,'x');
+		res = mglFormulaCalcC(f->eqs, list);
+#pragma omp parallel for
+		for(long i=0;i<nx*ny;i++)	f->hxv[i] = res->a[i]*dd;
+		delete res;
+	}
+}
+//-----------------------------------------------------------------------------
+// Solve equation dx/dz = func(p,q,x,y,z,|u|)[u] where p=d/dx, q=d/dy. At this moment simplified form of ham is supported: ham = f(p,q,z) + g(x,y,z,'u'), where variable 'u'=|u| (for allowing solve nonlinear problems). You may specify imaginary part like ham = p^2 + 1i*x*(x>0).
+HADT MGL_EXPORT mgl_pde_solve_c(HMGL gr, const char *ham, HCDT ini_re, HCDT ini_im, mreal dz, mreal k0, const char *opt)
+{
+	mreal gamma = gr->SaveState(opt);	if(mgl_isnan(gamma))	gamma = GAMMA;
+	mglPoint Min=gr->Min, Max=gr->Max;
+	long nx=ini_re->GetNx(), ny=ini_re->GetNy(), nz = long((Max.z-Min.z)/dz)+1;
+	if(nx<2 || nz<2 || Max.x==Min.x)			// Too small data
+	{	gr->SetWarn(mglWarnLow,"PDE");	return 0;	}
+	if(ini_im->GetNx()*ini_im->GetNy() != nx*ny)// Wrong dimensions
+	{	gr->SetWarn(mglWarnDim,"PDE");	return 0;	}
+	mglDataC *res=new mglDataC(nz, nx, ny);
+
+	ddual *a = new ddual[4*nx*ny], hh0;	// Add "damping" area
+	ddual *hxy = new ddual[4*nx*ny], *hxv = new ddual[4*nx*ny];
+	ddual *huy = new ddual[4*nx*ny], *huv = new ddual[4*nx*ny];
+	ddual *hx = new ddual[2*nx], *hv = new ddual[2*ny];
+	ddual *hy = new ddual[2*ny], *hu = new ddual[2*nx];
+	double *dmp = new double[4*nx*ny];
+	memset(a,0,4*nx*ny*sizeof(ddual));
+	memset(dmp,0,4*nx*ny*sizeof(double));
+#pragma omp parallel for collapse(2)
+	for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)	// Initial conditions
+	{
+		long i0 = i+nx/2+2*nx*(j+ny/2);
+		a[i0] = dual(ini_re->v(i,j), ini_im->v(i,j));
+		res->a[nz*(i+nx*j)] = a[i0];
+	}
+#pragma omp parallel for collapse(2)
+	for(long j=0;j<2*ny;j++)	for(long i=0;i<2*nx;i++)	// step 1
+	{
+		long i0 = i+2*nx*j;
+		if(i<nx/2)		dmp[i0] += gamma*mgl_ipow((nx/2-i)/(nx/2.),2);
+		if(i>3*nx/2)	dmp[i0] += gamma*mgl_ipow((i-3*nx/2-1)/(nx/2.),2);
+		if(j<ny/2)		dmp[i0] += gamma*mgl_ipow((ny/2-j)/(ny/2.),2);
+		if(j>3*ny/2)	dmp[i0] += gamma*mgl_ipow((j-3*ny/2-1)/(ny/2.),2);
+	}
+	mreal dx = (Max.x-Min.x)/(nx-1), dy = ny>1?(Max.y-Min.y)/(ny-1):0;
+	mreal dp = M_PI/(Max.x-Min.x)/k0, dq = M_PI/(Max.y-Min.y)/k0;
+	mreal xs=(Min.x+Max.x)/2, ys=(Min.y+Max.y)/2;
+	double dd = k0*dz;
+
+	mgl_pde_ham tmp;tmp.eqs = ham;
+	tmp.nx = 2*nx;	tmp.ny = 2*ny;	tmp.dd = dd;	tmp.a=a;
+	tmp.hxy=hxy;	tmp.hxv=hxv;	tmp.huy=huy;	tmp.huv=huv;
+	tmp.xx = Min.x-dx*(nx/2);	tmp.xs = xs;	tmp.dx = dx;	tmp.dp = dp;
+	tmp.yy = Min.y-dy*(ny/2);	tmp.ys = ys;	tmp.dy = dy;	tmp.dq = dq;
+
+	// prepare fft. NOTE: slow procedures due to unknown nx, ny.
+	void *wtx = mgl_fft_alloc(2*nx,0,0);
+	void *wty = mgl_fft_alloc(2*ny,0,0);
+	for(long k=1;k<nz;k++)
+	{
+		if(gr->NeedStop())	break;
+		tmp.zz = Min.z+dz*k;
+		memset(hxy,0,4*nx*ny*sizeof(dual));	memset(hxv,0,4*nx*ny*sizeof(dual));
+		memset(huv,0,4*nx*ny*sizeof(dual));	memset(huy,0,4*nx*ny*sizeof(dual));
+		mgl_pde_hprep(&tmp);
+		for(long i=0;i<2*nx;i++)	{	hx[i] = hxv[i];			hu[i] = huv[i];		}
+		for(long j=0;j<2*ny;j++)	{	hy[j] = huy[2*nx*j];	hv[j] = huv[2*nx*j];}
+		// rearrange arrays
+		hh0=hu[0];
+		if(ny>1)
+#pragma omp parallel for collapse(2)
+			for(long i=0;i<2*nx;i++) for(long j=0;j<2*ny;j++)
+			{
+				long i0 = i+2*nx*j;	huv[i0] -= hh0;
+				hxv[i0] -= hx[i]+hv[j]-hh0;
+				huy[i0] -= hu[i]+hy[j]-hh0;
+			}
+		else
+#pragma omp parallel for
+			for(long i=0;i<4*nx*ny;i++)	huv[i] -= hh0;
+			// solve equation
+		if(ny>1)
+#pragma omp parallel
+		{
+			void *wsx = mgl_fft_alloc_thr(2*nx), *wsy = mgl_fft_alloc_thr(2*ny);
+#pragma omp for
+			for(long i=0;i<4*nx*ny;i++)	a[i] *= exp(hxy[i])*exp(-double(dmp[i]*dz));
+#pragma omp for
+			for(long i=0;i<2*ny;i++)	mgl_fft((double *)(a+i*2*nx), 1, 2*nx, wtx, wsx, false);
+#pragma omp for
+			for(long i=0;i<4*nx*ny;i++)	a[i] *= exp(huy[i]);
+#pragma omp for
+			for(long i=0;i<2*nx;i++)	mgl_fft((double *)(a+i), 2*nx, 2*ny, wty, wsy, false);
+#pragma omp for
+			for(long i=0;i<4*nx*ny;i++)	a[i] *= exp(huv[i]);
+#pragma omp for
+			for(long i=0;i<2*ny;i++)	mgl_fft((double *)(a+2*i*nx), 1, 2*nx, wtx, wsx, true);
+#pragma omp for
+			for(long i=0;i<4*nx*ny;i++)	a[i] *= exp(hxv[i]);
+#pragma omp for
+			for(long i=0;i<2*nx;i++)	mgl_fft((double *)(a+i), 2*nx, 2*ny, wty, wsy, true);
+			mgl_fft_free_thr(wsx);	mgl_fft_free_thr(wsy);
+		}
+		else
+#pragma omp parallel
+		{
+			void *wsx = mgl_fft_alloc_thr(2*nx);
+#pragma omp for
+			for(long i=0;i<4*nx*ny;i++)	a[i] *= exp(hxy[i])*exp(-double(dmp[i]*dz));
+#pragma omp for
+			for(long i=0;i<2*ny;i++)	mgl_fft((double *)(a+i*2*nx), 1, 2*nx, wtx, wsx, false);
+#pragma omp for
+			for(long i=0;i<4*nx*ny;i++)	a[i] *= exp(huv[i]);
+#pragma omp for
+			for(long i=0;i<2*ny;i++)	mgl_fft((double *)(a+2*i*nx), 1, 2*nx, wtx, wsx, true);
+			mgl_fft_free_thr(wsx);
+		}
+#pragma omp parallel for collapse(2)
+		for(long i=0;i<nx;i++)	for(long j=0;j<ny;j++)	// save result
+			res->a[k+nz*(i+nx*j)] = a[i+nx/2+2*nx*(j+ny/2)];
+	}
+	mgl_fft_free(wtx,0,0);	mgl_fft_free(wty,0,0);
+	delete []a;		delete []dmp;
+	delete []hxy;	delete []hxv;	delete []huy;	delete []huv;
+	delete []hx;	delete []hy;	delete []hu;	delete []hv;
+	gr->LoadState();
+	return res;
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_pde_solve(HMGL gr, const char *ham, HCDT ini_re, HCDT ini_im, mreal dz, mreal k0, const char *opt)
+{
+	HADT res = mgl_pde_solve_c(gr,ham,ini_re,ini_im,dz,k0,opt);
+	HMDT out = mgl_datac_abs(res);	delete res;	return out;
+}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_pde_solve_c_(uintptr_t* gr, const char *ham, uintptr_t* ini_re, uintptr_t* ini_im, mreal *dz, mreal *k0, const char *opt, int l, int lo)
+{	char *s=new char[l+1];	memcpy(s,ham,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	uintptr_t res = uintptr_t(mgl_pde_solve_c(_GR_, s, _DA_(ini_re), _DA_(ini_im), *dz, *k0, o));
+	delete []o;	delete []s;	return res;	}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_pde_solve_(uintptr_t* gr, const char *ham, uintptr_t* ini_re, uintptr_t* ini_im, mreal *dz, mreal *k0, const char *opt, int l, int lo)
+{	char *s=new char[l+1];	memcpy(s,ham,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	uintptr_t res = uintptr_t(mgl_pde_solve(_GR_, s, _DA_(ini_re), _DA_(ini_im), *dz, *k0, o));
+	delete []o;	delete []s;	return res;	}
+//-----------------------------------------------------------------------------
+//
+//		ODE series
+//
+//-----------------------------------------------------------------------------
+struct mglOdeTxt	{	long n;	HMEX *eq;	const char *var;	};
+void MGL_NO_EXPORT mgl_txt_func(const mreal *x, mreal *dx, void *par)
+{
+	mglOdeTxt *p=(mglOdeTxt *)par;
+	mreal vars[MGL_VS];
+	for(long i=0;i<p->n;i++)
+	{	char ch = p->var[i];	if(ch>='a' && ch<='z')	vars[ch-'a']=x[i];	}
+#pragma omp parallel for
+	for(long i=0;i<p->n;i++)
+		dx[i] = mgl_expr_eval_v(p->eq[i], vars);
+}
+HMDT MGL_EXPORT mgl_ode_solve_str(const char *func, const char *var, HCDT x0, mreal dt, mreal tmax)
+{
+	if(!var || !(*var) || !func)	return 0;
+	long len = strlen(func);
+	mglOdeTxt par;	par.var=var;
+	par.n = strlen(var);
+	par.eq = new HMEX[par.n];
+	char *buf = new char[len+1], *f=buf, *g=f;	memcpy(buf,func,len+1);
+	mreal *xx = new mreal[par.n];
+	for(long i=0;i<par.n;i++)
+	{
+		xx[i] = x0?x0->vthr(i):0;
+		for(long k=0;f[k];k++)	if(f[k]==';')
+		{ g = f+k+1;	f[k]=0;	break;	}
+		if(f==g)	g = f+strlen(f);
+		par.eq[i] = mgl_create_expr(f);
+		f = g;
+	}
+	HMDT res = mgl_ode_solve_ex(mgl_txt_func,par.n,xx,dt,tmax,&par,NULL);
+	for(long i=0;i<par.n;i++)	mgl_delete_expr(par.eq[i]);
+	delete []par.eq;	delete []buf;	delete []xx;
+	return res;
+}
+//-----------------------------------------------------------------------------
+struct mglOdeTxtC	{	long n;	HAEX *eq;	const char *var;	};
+void MGL_NO_EXPORT mgl_txt_funcC(const mreal *x, mreal *dx, void *par)
+{
+	mglOdeTxtC *p=(mglOdeTxtC *)par;
+	dual vars[MGL_VS];
+	for(long i=0;i<p->n;i++)
+	{	char ch = p->var[i];	if(ch>='a' && ch<='z')	vars[ch-'a']=dual(x[2*i],x[2*i+1]);	}
+#pragma omp parallel for
+	for(long i=0;i<p->n;i++)
+	{
+		dual r = mgl_cexpr_eval_v(p->eq[i], vars);
+		dx[2*i] = real(r);	dx[2*i+1] = imag(r);
+	}
+}
+HADT MGL_EXPORT mgl_ode_solve_str_c(const char *func, const char *var, HCDT x0, mreal dt, mreal tmax)
+{
+	if(!var || !(*var) || !func)	return 0;
+	long len = strlen(func);
+	mglOdeTxtC par;	par.var=var;
+	par.n = strlen(var);
+	par.eq = new HAEX[par.n];
+	char *buf = new char[len+1], *f=buf, *g=f;	memcpy(buf,func,len+1);
+	mreal *xx = new mreal[2*par.n];
+	const mglDataC *c = dynamic_cast<const mglDataC *>(x0);
+	for(long i=0;i<par.n;i++)
+	{
+		if(c)	{	xx[2*i]=real(c->a[i]);	xx[2*i+1]=imag(c->a[i]);	}
+		else	{	xx[2*i] = x0?x0->vthr(i):0;	xx[2*i+1]=0;	}
+		for(long k=0;f[k];k++)	if(f[k]==';')
+		{ g = f+k+1;	f[k]=0;	break;	}
+		if(f==g)	g = f+strlen(f);
+		par.eq[i] = mgl_create_cexpr(f);
+		f = g;
+	}
+	HMDT res = mgl_ode_solve_ex(mgl_txt_funcC,2*par.n,xx,dt,tmax,&par,NULL);
+	for(long i=0;i<par.n;i++)	mgl_delete_cexpr(par.eq[i]);
+	delete []par.eq;	delete []buf;	delete []xx;
+	const long nn=par.n,nt=res->ny;
+	mglDataC *out = new mglDataC(nn, nt);
+#pragma omp parallel for
+	for(long i=0;i<nt*nn;i++)	out->a[i] = dual(res->a[2*i],res->a[2*i+1]);
+	delete res;	return out;
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_ode_solve(void (*func)(const mreal *x, mreal *dx, void *par), int n, const mreal *x0, mreal dt, mreal tmax, void *par)
+{	return mgl_ode_solve_ex(func,n,x0,dt,tmax,par,0);	}
+HMDT MGL_EXPORT mgl_ode_solve_ex(void (*func)(const mreal *x, mreal *dx, void *par), int n, const mreal *x0, mreal dt, mreal tmax, void *par, void (*bord)(mreal *x, const mreal *xp, void *par))
+{
+	if(tmax<dt)	return 0;	// nothing to do
+	const long nt = int(tmax/dt+0.5)+1;
+	mglData *res=new mglData(n,nt);
+	mreal *x=new mreal[n], *k1=new mreal[n], *k2=new mreal[n], *k3=new mreal[n], *v=new mreal[n], hh=dt/2;
+	// initial conditions
+	for(long i=0;i<n;i++)	x[i] = res->a[i] = x0[i];
+	// Runge Kutta scheme of 4th order
+	for(long k=1;k<nt;k++)
+	{
+		func(x,k1,par);
+		for(long i=0;i<n;i++)	v[i] = x[i]+k1[i]*hh;
+		func(v,k2,par);
+		for(long i=0;i<n;i++)	v[i] = x[i]+k2[i]*hh;
+		func(v,k3,par);
+		for(long i=0;i<n;i++)	{	v[i] = x[i]+k3[i]*dt;	k3[i] += k2[i];	}
+		func(v,k2,par);
+		for(long i=0;i<n;i++)	x[i] += (k1[i]+k2[i]+2*k3[i])*dt/6;
+		if(bord)	bord(x,res->a+n*(k-1),par);
+		for(long i=0;i<n;i++)	res->a[i+n*k] = x[i];
+	}
+	delete []x;	delete []k1;	delete []k2;	delete []k3;	delete []v;
+	return res;
+}
+//-----------------------------------------------------------------------------
+//
+//		Common functions for quasioptical calculations
+//
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_ray3d(const mreal *in, mreal *out, void *par)
+{
+	mglFormula *eqs = (mglFormula *)par;
+	const char *v="xyzpqvt";
+	mreal var[MGL_VS];	memset(var,0,MGL_VS*sizeof(mreal));
+	for(int i=0;i<7;i++)	var[v[i]-'a'] = in[i];
+	out[0] = eqs->CalcD(var,'p');	out[3] = -eqs->CalcD(var,'x');
+	out[1] = eqs->CalcD(var,'q');	out[4] = -eqs->CalcD(var,'y');
+	out[2] = eqs->CalcD(var,'v');	out[5] = -eqs->CalcD(var,'z');
+	out[7] = eqs->CalcD(var,'i');	out[6] = 1;
+}
+// Solve GO ray equation like dr/dt = d ham/dp, dp/dt = -d ham/dr where ham = ham(x,y,z,p,q,v,t) and px=p, py=q, pz=v. The starting point (at t=0) is r0, p0. Result is array of {x,y,z,p,q,v,t}
+HMDT MGL_EXPORT mgl_ray_trace(const char *ham, mreal x0, mreal y0, mreal z0, mreal px, mreal py, mreal pz, mreal dt, mreal tmax)
+{
+	mglFormula eqs(ham);
+	mreal in[8]={x0,y0,z0,px,py,pz,0,0};
+	HMDT res = mgl_ode_solve(mgl_ray3d,8,in,dt,tmax,&eqs);
+	mgl_data_set_id(res,"xyzpqvti");
+	return res;
+}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_ray_trace_(const char *ham, mreal *x0, mreal *y0, mreal *z0, mreal *px, mreal *py, mreal *pz, mreal *dt, mreal *tmax,int l)
+{	char *s=new char[l+1];	memcpy(s,ham,l);	s[l]=0;
+	uintptr_t res = uintptr_t(mgl_ray_trace(s, *x0,*y0,*z0, *px,*py,*pz, *dt,*tmax));
+	delete []s;	return res;	}
+//-----------------------------------------------------------------------------
+struct mgl_ap
+{
+	double x0,y0,z0,x1,y1,z1,x2,y2,z2;	// vectors {l, g1, g2}
+	double t1,t2,ch,q1,q2,pt,dt,d1,d2;	// theta_{1,2}, chi, q_{1,2}, p_t, dtau, dq_{1,2}
+	mgl_ap()	{	memset(this,0,sizeof(mgl_ap));	}
+};
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_init_ra(long n, int n7, const mreal *r, mgl_ap *ra)	// prepare some intermediate data for QO (3d case)
+{
+	double tt = hypot(r[n7]-r[0], r[n7+1]-r[1]);
+	if(tt)
+	{
+		ra[0].x1 = (r[n7+1]-r[1])/tt;
+		ra[0].y1 = (r[0]-r[n7])/tt;
+		ra[0].z1 = 0;
+	}
+	else	{	ra[0].x1 = ra[0].y1 = 0;	ra[0].z1 = 1;	}
+	ra[0].x0 = r[n7] - r[0];	ra[0].y0 = r[n7+1] - r[1];	ra[0].z0 = r[n7+2] - r[2];
+	tt = sqrt(ra[0].x0*ra[0].x0 + ra[0].y0*ra[0].y0 + ra[0].z0*ra[0].z0);
+	ra[0].x0 /= tt;	ra[0].y0 /= tt;	ra[0].z0 /= tt;
+	ra[0].x2 = ra[0].y1*ra[0].z0 - ra[0].y0*ra[0].z1;	// vector g_2
+	ra[0].y2 = ra[0].z1*ra[0].x0 - ra[0].z0*ra[0].x1;
+	ra[0].z2 = ra[0].x1*ra[0].y0 - ra[0].x0*ra[0].y1;
+	for(long i=1;i<n;i++)	// NOTE: no parallel due to dependence on prev point!
+	{
+		mgl_ap *ri=ra+i, *rp=ra+i-1;
+		const mreal *rr = r+n7*i;
+		ri->dt = rr[6] - rr[6-n7];
+		ri->x0 = rr[0] - rr[-n7];	// NOTE: very rough formulas
+		ri->y0 = rr[1] - rr[1-n7];	// for corresponding with dt one
+		ri->z0 = rr[2] - rr[2-n7];	// for corresponding with dt one
+		double ch = sqrt(ri->x0*ri->x0 + ri->y0*ri->y0 + ri->z0*ri->z0);
+		ri->x0 /= ch;	ri->y0 /= ch;	ri->z0 /= ch;
+		ri->ch = ch/ri->dt;
+		ri->pt = rr[3]*ri->x0 + rr[4]*ri->y0 + rr[5]*ri->z0;
+		ri->q1 = rr[3]*ri->x1 + rr[4]*ri->y1 + rr[5]*ri->z1;
+		ri->q2 = rr[3]*ri->x2 + rr[4]*ri->y2 + rr[5]*ri->z2;
+		// NOTE previous point is used here!
+		tt = ri->x0*rp->x1 + ri->y0*rp->y1 + ri->z0*rp->z1;
+		ri->x1 = rp->x1 - tt*ri->x0;	// vector g_1
+		ri->y1 = rp->y1 - tt*ri->y0;
+		ri->z1 = rp->z1 - tt*ri->z0;
+		ri->t1 = tt/ch;
+		tt = sqrt(ri->x1*ri->x1 + ri->y1*ri->y1 + ri->z1*ri->z1);
+		ri->x1 /= tt;	ri->y1 /= tt;	ri->z1 /= tt;	// norm for reducing numeric error
+		ri->x2 = ri->y1*ri->z0 - ri->y0*ri->z1;	// vector g_2
+		ri->y2 = ri->z1*ri->x0 - ri->z0*ri->x1;
+		ri->z2 = ri->x1*ri->y0 - ri->x0*ri->y1;
+		tt = ri->x0*rp->x2 + ri->y0*rp->y2 + ri->z0*rp->z2;
+		ri->t2 = tt/ch;
+		ri->d1 = (ri->q1-rp->q1)/ch;
+		ri->d2 = (ri->q2-rp->q2)/ch;
+	}
+	memcpy(ra,ra+1,sizeof(mgl_ap));	// setup zero point
+	ra[0].pt = r[3]*ra[0].x0 + r[4]*ra[0].y0 + r[5]*ra[0].z0;
+	ra[0].q1 = r[3]*ra[0].x1 + r[4]*ra[0].y1 + r[5]*ra[0].z1;
+	ra[0].q2 = r[3]*ra[0].x2 + r[4]*ra[0].y2 + r[5]*ra[0].z2;
+}
+//-----------------------------------------------------------------------------
+//
+//		QO2d series
+//
+//-----------------------------------------------------------------------------
+struct mgl_qo2d_ham
+{
+	ddual *hx, *hu, *a, h0;
+	double *dmp, dr, dk;
+	mreal *r;
+	mgl_ap *ra;
+	ddual (*ham)(mreal u, mreal x, mreal y, mreal px, mreal py, void *par);
+	void *par;
+};
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_qo2d_hprep(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	mgl_qo2d_ham *f = (mgl_qo2d_ham *)t->v;
+	mgl_ap *ra = f->ra;
+
+	const mreal *r = f->r;
+	const long nx=t->n;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=t->id;i<nx;i+=mglNumThr)
+	{
+		// x terms
+		mreal x1 = (2*i-nx+1)*f->dr, hh = 1 - ra->t1*x1;
+		hh = sqrt(sqrt(0.041+hh*hh*hh*hh));
+		mreal tt = (ra->pt + ra->d1*x1)/hh - ra->pt;
+		f->hx[i] = f->ham(abs(f->a[i]), r[0]+ra->x1*x1, r[1]+ra->y1*x1, r[3]+ra->x0*tt, r[4]+ra->y0*tt, f->par) - f->h0/2.;
+		// u-y terms
+		x1 = f->dk/2*(i<nx/2 ? i:i-nx);
+		f->hu[i] = f->ham(0, r[0], r[1], r[3]+ra->x1*x1, r[4]+ra->y1*x1, f->par) - f->h0/2.;
+
+		if(imag(f->hx[i])>0)	f->hx[i] = f->hx[i].real();
+		if(imag(f->hu[i])>0)	f->hu[i] = f->hu[i].real();
+		// add boundary conditions for x-direction
+		f->hx[i] -= dual(0,f->dmp[i]);
+	}
+	return 0;
+}
+//-----------------------------------------------------------------------------
+HADT MGL_EXPORT mgl_qo2d_func_c(ddual (*ham)(mreal u, mreal x, mreal y, mreal px, mreal py, void *par), void *par, HCDT ini_re, HCDT ini_im, HCDT ray_dat, mreal r, mreal k0, HMDT xx, HMDT yy)
+{
+	const mglData *ray=dynamic_cast<const mglData *>(ray_dat);	// NOTE: Ray must be mglData!
+	if(!ray)	return 0;
+	const long nx=ini_re->GetNx(), nt=ray->ny, n7=ray->nx;
+	if(nx<2 || ini_im->GetNx()!=nx || nt<2)	return 0;
+	mglDataC *res=new mglDataC(nx,nt,1);
+
+	ddual *a=new ddual[2*nx], *hu=new ddual[2*nx],  *hx=new ddual[2*nx];
+	double *dmp=new double[2*nx];
+	mgl_ap *ra = new mgl_ap[nt];	mgl_init_ra(nt, n7, ray->a, ra);	// ray
+
+	mreal dr = r/(nx-1), dk = M_PI*(nx-1)/(k0*r*nx);
+	memset(dmp,0,2*nx*sizeof(double));
+	for(long i=0;i<nx/2;i++)	// prepare damping
+	{
+		mreal x1 = (nx/2-i)/(nx/2.);
+		dmp[2*nx-1-i] = dmp[i] = 30*GAMMA*x1*x1/k0;
+	}
+	for(long i=0;i<nx;i++)	a[i+nx/2] = dual(ini_re->v(i),ini_im->v(i));	// init
+	void *wsx, *wtx = mgl_fft_alloc(2*nx,&wsx,1);
+	if(xx && yy)	{	xx->Create(nx,nt);	yy->Create(nx,nt);	}
+
+	mgl_qo2d_ham tmp;	// parameters for Hamiltonian calculation
+	tmp.hx=hx;	tmp.hu=hu;	tmp.dmp=dmp;	tmp.par=par;
+	tmp.dr=dr;	tmp.dk=dk;	tmp.ham=ham;	tmp.a=a;
+	// start calculation
+	for(long k=0;k<nt;k++)
+	{
+		for(long i=0;i<nx;i++)	// "save"
+			res->a[i+k*nx]=a[i+nx/2]*sqrt(ra[0].ch/ra[k].ch);
+		if(xx && yy)	for(long i=0;i<nx;i++)	// prepare xx, yy
+		{
+			mreal x1 = (2*i-nx+1)*dr;
+			xx->a[i+k*nx] = ray->a[n7*k] + ra[k].x1*x1;	// new coordinates
+			yy->a[i+k*nx] = ray->a[n7*k+1] + ra[k].y1*x1;
+		}
+		tmp.r=ray->a+n7*k;	tmp.ra=ra+k;
+		mreal hh = ra[k].pt*(1/sqrt(sqrt(1.041))-1);	// 0.041=0.45^4 -- minimal value of h
+		tmp.h0 = ham(0, tmp.r[0], tmp.r[1], tmp.r[3]+ra[k].x0*hh, tmp.r[4]+ra[k].x0*hh, par);
+		mglStartThread(mgl_qo2d_hprep,0,2*nx,0,0,0,0,&tmp);
+		// Step for field
+		ddual dt = ddual(0, -ra[k].dt*k0);
+		for(long i=0;i<2*nx;i++)	a[i] *= exp(hx[i]*dt);
+		mgl_fft((double *)a, 1, 2*nx, wtx, wsx, false);
+		for(long i=0;i<2*nx;i++)	a[i] *= exp(hu[i]*dt);
+		mgl_fft((double *)a, 1, 2*nx, wtx, wsx, true);
+
+/*		// Calculate B1			// TODO make more general scheme later!!!
+		hh = ra[k].pt*(1/sqrt(sqrt(1.041))-1);
+		var['x'-'a'] = ray->a[n7*k];	// new coordiantes
+		var['y'-'a'] = ray->a[n7*k+1];
+		var['p'-'a'] = ray->a[n7*k+3] + ra[k].x0*hh;	// new momentums
+		var['q'-'a'] = ray->a[n7*k+4] + ra[k].y0*hh;
+		tt = h.CalcD(var,'p')*ra[k].x1 + h.CalcD(var,'q')*ra[k].y1;
+		var['x'-'a'] = ray->a[n7*k] + ra[k].x1*dr;	// new coordiantes
+		var['y'-'a'] = ray->a[n7*k+1] + ra[k].y1*dr;
+		hh = 1 - ra[k].t1*dr;	hh = sqrt(sqrt(0.041+hh*hh*hh*hh));
+		hh = (ra[k].ch*ra[k].pt + ra[k].d1*dr)/(hh*ra[k].ch) - ra[k].pt;
+		var['p'-'a'] = ray->a[n7*k+3] + ra[k].x0*hh;	// new momentums
+		var['q'-'a'] = ray->a[n7*k+4] + ra[k].y0*hh;
+		B1 = h.CalcD(var,'p')*ra[k].x1 + h.CalcD(var,'q')*ra[k].y1;
+		B1 = (B1-tt)/dr;
+		double a1=0, a2=0;
+		for(i=0;i<2*nx;i++)	a1 += norm(a[i]);
+		hx[0] = hx[2*nx-1] = 0.;
+		for(i=1;i<2*nx-1;i++)	hx[i] = (B1*ra[k].dt*(i-nx))*(a[i+1]-a[i-1]);
+		for(i=0;i<2*nx;i++)	{	a[i] += hx[i];	a2 += norm(a[i]);	}
+		a1 = sqrt(a1/a2);
+		for(i=0;i<2*nx;i++)	a[i] *= a1;*/
+	}
+	mgl_fft_free(wtx,&wsx,1);
+	delete []a;		delete []hu;	delete []hx;	delete []ra;	delete []dmp;
+	return res;
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_qo2d_func(ddual (*ham)(mreal u, mreal x, mreal y, mreal px, mreal py, void *par), void *par, HCDT ini_re, HCDT ini_im, HCDT ray_dat, mreal r, mreal k0, HMDT xx, HMDT yy)
+{
+	HADT res = mgl_qo2d_func_c(ham,par,ini_re,ini_im,ray_dat,r,k0,xx,yy);
+	HMDT out = mgl_datac_abs(res);	delete res;	return out;
+}
+//-----------------------------------------------------------------------------
+ddual MGL_NO_EXPORT mgl_ham2d(mreal u, mreal x, mreal y, mreal px, mreal py, void *par)
+{
+	mglFormula *h = (mglFormula *)par;
+	mreal var[MGL_VS];	memset(var,0,MGL_VS*sizeof(mreal));
+	var['x'-'a'] = x;	var['y'-'a'] = y;	var['u'-'a'] = u;
+	var['p'-'a'] = px;	var['q'-'a'] = py;
+	return ddual(h->Calc(var), -h->CalcD(var,'i'));
+}
+//-----------------------------------------------------------------------------
+HADT MGL_EXPORT mgl_qo2d_solve_c(const char *ham, HCDT ini_re, HCDT ini_im, HCDT ray_dat, mreal r, mreal k0, HMDT xx, HMDT yy)
+{
+	mglFormula h(ham);
+	return mgl_qo2d_func_c(mgl_ham2d, &h, ini_re, ini_im, ray_dat, r, k0, xx, yy);
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_qo2d_solve(const char *ham, HCDT ini_re, HCDT ini_im, HCDT ray_dat, mreal r, mreal k0, HMDT xx, HMDT yy)
+{
+	HADT res = mgl_qo2d_solve_c(ham,ini_re,ini_im,ray_dat,r,k0,xx,yy);
+	HMDT out = mgl_datac_abs(res);	delete res;	return out;
+}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_qo2d_solve_(const char *ham, uintptr_t* ini_re, uintptr_t* ini_im, uintptr_t* ray, mreal *r, mreal *k0, uintptr_t* xx, uintptr_t* yy, int l)
+{	char *s=new char[l+1];	memcpy(s,ham,l);	s[l]=0;
+	uintptr_t res = uintptr_t(mgl_qo2d_solve(s, _DA_(ini_re), _DA_(ini_im), _DA_(ray), *r, *k0, _DM_(xx), _DM_(yy)));
+	delete []s;	return res;	}
+//-----------------------------------------------------------------------------
+//
+//		QO3d series
+//
+//-----------------------------------------------------------------------------
+struct mgl_qo3d_ham
+{
+	ddual *hxy, *huv, *hxv, *huy, *a;
+	ddual *hx, *hy, *hu, *hv, h0;
+	double *dmp, dr, dk;
+	mreal *r;
+	mgl_ap *ra;
+	ddual (*ham)(mreal u, mreal x, mreal y, mreal z, mreal px, mreal py, mreal pz, void *par);
+	void *par;
+};
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_qo3d_hprep(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	mgl_qo3d_ham *f = (mgl_qo3d_ham *)t->v;
+	mgl_ap *ra = f->ra;
+	const mreal *r = f->r;
+	const long nx=t->n;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long ii=t->id;ii<nx*nx;ii+=mglNumThr)
+	{
+		long i = ii%nx, j = ii/nx;
+		// x-y terms
+		mreal x1 = (2*i-nx+1)*f->dr, x2 = (2*j-nx+1)*f->dr, hh = 1-ra->t1*x1-ra->t2*x2;
+		hh = sqrt(sqrt(0.041+hh*hh*hh*hh));
+		mreal tt = (ra->pt + ra->d1*x1 + ra->d2*x2)/hh - ra->pt;
+		f->hxy[ii] = f->ham(abs(f->a[i]), r[0]+ra->x1*x1+ra->x2*x2, r[1]+ra->y1*x1+ra->y2*x2, r[2]+ra->z1*x1+ra->z2*x2, r[3]+ra->x0*tt, r[4]+ra->y0*tt, r[5]+ra->z0*tt, f->par);
+		// x-v terms
+		x1 = (2*i-nx+1)*f->dr;	x2 = f->dk/2*(j<nx/2 ? j:j-nx);	hh = 1-ra->t1*x1;
+		hh = sqrt(sqrt(0.041+hh*hh*hh*hh));
+		tt = (ra->pt + ra->d1*x1)/hh - ra->pt;
+		f->hxv[ii] = f->ham(0, r[0]+ra->x1*x1, r[1]+ra->y1*x1, r[2]+ra->z1*x1, r[3]+ra->x0*tt+ra->x2*x2, r[4]+ra->y0*tt+ra->y2*x2, r[5]+ra->z0*tt+ra->z2*x2, f->par);
+		// u-y terms
+		x1 = f->dk/2*(i<nx/2 ? i:i-nx);	x2 = (2*j-nx+1)*f->dr;	hh = 1-ra->t2*x2;
+		hh = sqrt(sqrt(0.041+hh*hh*hh*hh));
+		tt = (ra->pt + ra->d2*x2)/hh - ra->pt;
+		f->huy[ii] = f->ham(0, r[0]+ra->x2*x2, r[1]+ra->y2*x2, r[2]+ra->z2*x2, r[3]+ra->x1*x1+ra->x0*tt, r[4]+ra->y1*x1+ra->y0*tt, r[5]+ra->z1*x1+ra->z0*tt, f->par);
+		// u-y terms
+		x1 = f->dk/2*(i<nx/2 ? i:i-nx);	x2 = f->dk/2*(j<nx/2 ? j:j-nx);
+		f->huv[ii] = f->ham(0, r[0], r[1], r[2], r[3]+ra->x1*x1+ra->x2*x2, r[4]+ra->y1*x1+ra->y2*x2, r[5]+ra->z1*x1+ra->z2*x2, f->par);
+	}
+	return 0;
+}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_qo3d_post(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	mgl_qo3d_ham *f = (mgl_qo3d_ham *)t->v;
+	const long nx=t->n;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long ii=t->id;ii<nx*nx;ii+=mglNumThr)
+	{
+		long i = ii%nx, j = ii/nx;
+		f->hxy[ii] -= (f->hx[i]+f->hy[j]-f->h0/2.)/2.;
+		if(imag(f->hxy[ii])>0)	f->hxy[ii] = f->hxy[ii].real();
+		f->hxv[ii] -= (f->hx[i]+f->hv[j]-f->h0/2.)/2.;
+		if(imag(f->hxv[ii])>0)	f->hxv[ii] = f->hxv[ii].real();
+		f->huy[ii] -= (f->hu[i]+f->hy[j]-f->h0/2.)/2.;
+		if(imag(f->huy[ii])>0)	f->huy[ii] = f->huy[ii].real();
+		f->huv[ii] -= (f->hu[i]+f->hv[j]-f->h0/2.)/2.;
+		if(imag(f->huv[ii])>0)	f->huv[ii] = f->huv[ii].real();
+		// add boundary conditions for x-direction
+		f->hxy[ii] -= dual(0,f->dmp[ii]);
+	}
+	return 0;
+}
+//-----------------------------------------------------------------------------
+HADT MGL_EXPORT mgl_qo3d_func_c(ddual (*ham)(mreal u, mreal x, mreal y, mreal z, mreal px, mreal py, mreal pz, void *par), void *par, HCDT ini_re, HCDT ini_im, HCDT ray_dat, mreal r, mreal k0, HMDT xx, HMDT yy, HMDT zz)
+{
+	const mglData *ray=dynamic_cast<const mglData *>(ray_dat);	// NOTE: Ray must be mglData!
+	if(!ray)	return 0;
+	const long nx=ini_re->GetNx(), nt=ray->ny, n7=ray->nx;	// NOTE: only square grids are supported now (for simplicity)
+	if(nx<2 || ini_re->GetNx()!=nx || ini_im->GetNx()*ini_im->GetNy()!=nx*nx || nt<2)	return 0;
+	mglDataC *res=new mglDataC(nx,nx,nt);
+
+	ddual *a=new ddual[4*nx*nx], *huv=new ddual[4*nx*nx],  *hxy=new ddual[4*nx*nx], *huy=new ddual[4*nx*nx],  *hxv=new ddual[4*nx*nx];
+	ddual *hu=new ddual[2*nx],  *hx=new ddual[2*nx], *hy=new ddual[2*nx],  *hv=new ddual[2*nx];
+	double *dmp=new double[4*nx*nx];
+	mgl_ap *ra = new mgl_ap[nt];
+	mgl_init_ra(nt, n7, ray->a, ra);	// prepare ray
+
+	double dr = r/(nx-1), dk = M_PI*(nx-1)/(k0*r*nx);
+	memset(dmp,0,4*nx*nx*sizeof(double));
+#pragma omp parallel for collapse(2)
+	for(long i=0;i<nx/2;i++)	for(long j=0;j<nx/2;j++)	// prepare damping
+	{
+		double x1 = (nx/2-i)/(nx/2.), x2 = (nx/2-j)/(nx/2.);
+		dmp[2*nx-1-i] = dmp[i] = 30*GAMMA*x1*x1/k0;
+		dmp[(2*nx-1-j)*2*nx] += 30*GAMMA*x2*x2/k0;
+		dmp[j*2*nx] += 30*GAMMA*x2*x2/k0;
+	}
+#pragma omp parallel for collapse(2)
+	for(long i=0;i<nx;i++)	for(long j=0;j<nx;j++)	// init
+		a[i+nx/2+2*nx*(j+nx/2)] = dual(ini_re->v(i,j),ini_im->v(i,j));
+	void *wtx = mgl_fft_alloc(2*nx,0,0);
+	if(xx && yy && zz)	{	xx->Create(nx,nx,nt);	yy->Create(nx,nx,nt);	zz->Create(nx,nx,nt);	}
+
+	mgl_qo3d_ham tmp;	// parameters for Hamiltonian calculation
+	tmp.hxy=hxy;	tmp.hx=hx;	tmp.huv=huv;	tmp.hu=hu;
+	tmp.huy=huy;	tmp.hy=hy;	tmp.hxv=hxv;	tmp.hv=hv;
+	tmp.dmp=dmp;	tmp.par=par;
+	tmp.dr=dr;	tmp.dk=dk;	tmp.ham=ham;	tmp.a=a;
+	// start calculation
+	for(long k=0;k<nt;k++)
+	{
+#pragma omp parallel for collapse(2)
+		for(long i=0;i<nx;i++)	for(long j=0;j<nx;j++)	// "save"
+			res->a[i+nx*(j+k*nx)]=a[i+nx/2+2*nx*(j+nx/2)]*sqrt(ra[0].ch/ra[k].ch);
+		if(xx && yy && zz)
+#pragma omp parallel for collapse(2)
+			for(long i=0;i<nx;i++)	for(long j=0;j<nx;j++)	// prepare xx, yy, zz
+			{
+				mreal x1 = (2*i-nx+1)*dr, x2 = (2*j-nx+1)*dr;
+				xx->a[i+nx*(j+k*nx)] = ray->a[n7*k] + ra[k].x1*x1 + ra[k].x2*x2;	// new coordinates
+				yy->a[i+nx*(j+k*nx)] = ray->a[n7*k+1] + ra[k].y1*x1 + ra[k].y2*x2;
+				zz->a[i+nx*(j+k*nx)] = ray->a[n7*k+2] + ra[k].z1*x1 + ra[k].z2*x2;
+			}
+		tmp.r=ray->a+n7*k;	tmp.ra=ra+k;
+		mglStartThread(mgl_qo3d_hprep,0,2*nx,0,0,0,0,&tmp);	tmp.h0 = huv[0];
+		for(long i=0;i<2*nx;i++)	// fill intermediate arrays
+		{
+			tmp.hx[i] = hxv[i];	tmp.hy[i] = huy[i*2*nx];
+			tmp.hv[i] = huv[i];	tmp.hu[i] = huv[i*2*nx];
+		}
+		mglStartThread(mgl_qo3d_post,0,2*nx,0,0,0,0,&tmp);
+		// Step for field
+		ddual dt = ddual(0, -ra[k].dt*k0);
+#pragma omp parallel
+		{
+			void *wsx = mgl_fft_alloc_thr(2*nx);
+#pragma omp for
+			for(long i=0;i<4*nx*nx;i++)	a[i] *= exp(hxy[i]*dt);		// x-y
+#pragma omp for
+			for(long i=0;i<2*nx;i++)	// x->u
+				mgl_fft((double *)(a+i*2*nx), 1, 2*nx, wtx, wsx, false);
+#pragma omp for
+			for(long i=0;i<4*nx*nx;i++)	a[i] *= exp(huy[i]*dt);		// u-y
+#pragma omp for
+			for(long i=0;i<2*nx;i++)	// y->v
+				mgl_fft((double *)(a+i), 2*nx, 2*nx, wtx, wsx, false);
+#pragma omp for
+			for(long i=0;i<4*nx*nx;i++)	a[i] *= exp(huv[i]*dt);		// u-v
+#pragma omp for
+			for(long i=0;i<2*nx;i++)	// u->x
+				mgl_fft((double *)(a+i*2*nx), 1, 2*nx, wtx, wsx, true);
+#pragma omp for
+			for(long i=0;i<4*nx*nx;i++)	a[i] *= exp(hxv[i]*dt);		// x-v
+#pragma omp for
+			for(long i=0;i<2*nx;i++)	// v->y
+				mgl_fft((double *)(a+i), 2*nx, 2*nx, wtx, wsx, true);
+			mgl_fft_free_thr(wsx);
+		}
+
+/*		// Calculate B1			// TODO make more general scheme later!!!
+		hh = ra[k].pt*(1/sqrt(sqrt(1.041))-1);
+		var['x'-'a'] = ray->a[n7*k];	// new coordiantes
+		var['y'-'a'] = ray->a[n7*k+1];
+		var['p'-'a'] = ray->a[n7*k+3] + ra[k].x0*hh;	// new momentums
+		var['q'-'a'] = ray->a[n7*k+4] + ra[k].y0*hh;
+		tt = h.CalcD(var,'p')*ra[k].x1 + h.CalcD(var,'q')*ra[k].y1;
+		var['x'-'a'] = ray->a[n7*k] + ra[k].x1*dr;	// new coordiantes
+		var['y'-'a'] = ray->a[n7*k+1] + ra[k].y1*dr;
+		hh = 1 - ra[k].t1*dr;	hh = sqrt(sqrt(0.041+hh*hh*hh*hh));
+		hh = (ra[k].ch*ra[k].pt + ra[k].d1*dr)/(hh*ra[k].ch) - ra[k].pt;
+		var['p'-'a'] = ray->a[n7*k+3] + ra[k].x0*hh;	// new momentums
+		var['q'-'a'] = ray->a[n7*k+4] + ra[k].y0*hh;
+		B1 = h.CalcD(var,'p')*ra[k].x1 + h.CalcD(var,'q')*ra[k].y1;
+		B1 = (B1-tt)/dr;
+		double a1=0, a2=0;
+		for(i=0;i<2*nx;i++)	a1 += norm(a[i]);
+		hx[0] = hx[2*nx-1] = 0.;
+		for(i=1;i<2*nx-1;i++)	hx[i] = (B1*ra[k].dt*(i-nx))*(a[i+1]-a[i-1]);
+		for(i=0;i<2*nx;i++)	{	a[i] += hx[i];	a2 += norm(a[i]);	}
+		a1 = sqrt(a1/a2);
+		for(i=0;i<2*nx;i++)	a[i] *= a1;*/
+	}
+	mgl_fft_free(wtx,0,0);
+	delete []a;		delete []ra;	delete []dmp;
+	delete []huv;	delete []hxy;	delete []hxv;	delete []huy;
+	delete []hu;	delete []hx;	delete []hv;	delete []hy;
+	return res;
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_qo3d_func(ddual (*ham)(mreal u, mreal x, mreal y, mreal z, mreal px, mreal py, mreal pz, void *par), void *par, HCDT ini_re, HCDT ini_im, HCDT ray_dat, mreal r, mreal k0, HMDT xx, HMDT yy, HMDT zz)
+{
+	HADT res = mgl_qo3d_func_c(ham,par,ini_re,ini_im,ray_dat,r,k0,xx,yy,zz);
+	HMDT out = mgl_datac_abs(res);	delete res;	return out;
+}
+//-----------------------------------------------------------------------------
+ddual MGL_NO_EXPORT mgl_ham3d(mreal u, mreal x, mreal y, mreal z, mreal px, mreal py, mreal pz, void *par)
+{
+	mglFormula *h = (mglFormula *)par;
+	mreal var[MGL_VS];	memset(var,0,MGL_VS*sizeof(mreal));
+	var['x'-'a'] = x;	var['y'-'a'] = y;	var['z'-'a'] = z;	var['u'-'a'] = u;
+	var['p'-'a'] = px;	var['q'-'a'] = py;	var['v'-'a'] = pz;
+	return ddual(h->Calc(var), -h->CalcD(var,'i'));
+}
+//-----------------------------------------------------------------------------
+HADT MGL_EXPORT mgl_qo3d_solve_c(const char *ham, HCDT ini_re, HCDT ini_im, HCDT ray_dat, mreal r, mreal k0, HMDT xx, HMDT yy, HMDT zz)
+{
+	mglFormula h(ham);
+	return mgl_qo3d_func_c(mgl_ham3d, &h, ini_re, ini_im, ray_dat, r, k0, xx, yy, zz);
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_qo3d_solve(const char *ham, HCDT ini_re, HCDT ini_im, HCDT ray_dat, mreal r, mreal k0, HMDT xx, HMDT yy, HMDT zz)
+{
+	HADT res = mgl_qo3d_solve_c(ham,ini_re,ini_im,ray_dat,r,k0,xx,yy,zz);
+	HMDT out = mgl_datac_abs(res);	delete res;	return out;
+}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_qo3d_solve_(const char *ham, uintptr_t* ini_re, uintptr_t* ini_im, uintptr_t* ray, mreal *r, mreal *k0, uintptr_t* xx, uintptr_t* yy, uintptr_t* zz, int l)
+{	char *s=new char[l+1];	memcpy(s,ham,l);	s[l]=0;
+	uintptr_t res = uintptr_t(mgl_qo3d_solve(s, _DA_(ini_re), _DA_(ini_im), _DA_(ray), *r, *k0, _DM_(xx), _DM_(yy), _DM_(zz)));
+	delete []s;	return res;	}
+//-----------------------------------------------------------------------------
+//
+//		mglJacobian series
+//
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_jacob2(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	const long nx=t->p[0], ny=t->p[1];
+	mreal *r=t->a;
+	const mreal *x=t->b, *y=t->c;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i0=t->id;i0<t->n;i0+=mglNumThr)
+	{
+		long i=i0%nx, j=i0/nx;
+		long ip = i<nx-1 ? 1:0, jp = j<ny-1 ? nx:0;
+		long im = i>0 ? -1:0, jm = j>0 ? -nx:0;
+		r[i0] = (x[i0+ip]-x[i0+im])*(y[i0+jp]-y[i0+jm]) -
+				(y[i0+ip]-y[i0+im])*(x[i0+jp]-x[i0+jm]);
+		r[i0] *= mreal((nx-1)*(ny-1)) / mreal((ip-im)*(jp-jm));
+	}
+	return 0;
+}
+HMDT MGL_EXPORT mgl_jacobian_2d(HCDT x, HCDT y)
+{
+	const long nx = x->GetNx(), ny=x->GetNy();
+	if(nx!=y->GetNx() || ny!=y->GetNy() || nx<2 || ny<2)	return	0;
+	mglData *r=new mglData(nx,ny,1);
+	const mglData *xx=dynamic_cast<const mglData *>(x);
+	const mglData *yy=dynamic_cast<const mglData *>(y);
+	if(xx && yy)
+	{
+		long p[2]={nx,ny};
+		mglStartThread(mgl_jacob2,0,nx*ny,r->a,xx->a,yy->a,p);
+	}
+	else	// slow variant
+	{
+#pragma omp parallel for collapse(2)
+		for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+		{
+			long im = i>0 ? i-1:i, ip = i<nx-1 ? i+1:i;
+			long jm = j>0 ? j-1:j, jp = j<ny-1 ? j+1:j;
+			r->a[i+nx*j] = (x->v(ip,j)-x->v(im,j))*(y->v(i,jp)-y->v(i,jm)) -
+						(y->v(ip,j)-y->v(im,j))*(x->v(i,jp)-x->v(i,jm));
+			r->a[i+nx*j] *= mreal((nx-1)*(ny-1)) / mreal((ip-im)*(jp-jm));
+		}
+	}
+	return r;
+}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_jacob3(void *par)
+{
+	mglThreadD *t=(mglThreadD *)par;
+	const long nx=t->p[0], ny=t->p[1], nz=t->p[2];
+	mreal *r=t->a;
+	const mreal *x=t->b, *y=t->c, *z=t->d;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i0=t->id;i0<t->n;i0+=mglNumThr)
+	{
+		long i=i0%nx, j=(i0/nx)%ny, k=i0/(nx*ny);
+		long ip = i<nx-1 ? 1:0, jp = j<ny-1 ? nx:0, kp = k<nz-1 ? nx*ny:0;
+		long im = i>0 ? -1:0, jm = j>0 ? -nx:0, km = k>0 ? -nx*ny:0;
+		r[i0] = (x[i0+ip]-x[i0+im])*(y[i0+jp]-y[i0+jm])*(z[i0+kp]-z[i0+km]) -
+				(x[i0+ip]-x[i0+im])*(y[i0+kp]-y[i0+km])*(z[i0+jp]-z[i0+jm]) -
+				(x[i0+jp]-x[i0+jm])*(y[i0+ip]-y[i0+im])*(z[i0+kp]-z[i0+km]) +
+				(x[i0+jp]-x[i0+jm])*(y[i0+kp]-y[i0+km])*(z[i0+ip]-z[i0+im]) +
+				(x[i0+kp]-x[i0+km])*(y[i0+ip]-y[i0+im])*(z[i0+jp]-z[i0+jm]) -
+				(x[i0+kp]-x[i0+km])*(y[i0+jp]-y[i0+jm])*(z[i0+ip]-z[i0+im]);
+		r[i0] *= mreal((nx-1)*(ny-1)*(nz-1)) / mreal((ip-im)*(jp-jm)*(kp-km));
+	}
+	return 0;
+}
+HMDT MGL_EXPORT mgl_jacobian_3d(HCDT x, HCDT y, HCDT z)
+{
+	const long nx = x->GetNx(), ny=x->GetNy(), nz=x->GetNz(), nn = nx*ny*nz;
+	if(nx<2 || ny<2 || nz<2)	return 0;
+	if(nn!=y->GetNN() || nn!=z->GetNN())	return 0;
+	mglData *r=new mglData(nx,ny,nz);
+	const mglData *xx=dynamic_cast<const mglData *>(x);
+	const mglData *yy=dynamic_cast<const mglData *>(y);
+	const mglData *zz=dynamic_cast<const mglData *>(z);
+	if(xx && yy && zz)
+	{
+		long p[3]={nx,ny,nz};
+		mglStartThread(mgl_jacob3,0,nx*ny*nz,r->a,xx->a,yy->a,p,0,zz->a);
+	}
+	else	// slow variant
+	{
+#pragma omp parallel for collapse(3)
+		for(long k=0;k<nz;k++)	for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+		{
+			long im = i>0 ? i-1:i, ip = i<nx-1 ? i+1:i;
+			long jm = j>0 ? j-1:j, jp = j<ny-1 ? j+1:j;
+			long km = k>0 ? k-1:k, kp = k<nz-1 ? k+1:k;
+			long i0 = i+nx*(j+ny*k);
+			r->a[i0] = (x->v(ip,j,k)-x->v(im,j,k))*(y->v(i,jp,k)-y->v(i,jm,k))*(z->v(i,j,kp)-z->v(i,j,km)) -
+					(x->v(ip,j,k)-x->v(im,j,k))*(y->v(i,j,kp)-y->v(i,j,km))*(z->v(i,jp,k)-z->v(i,jm,k)) -
+					(x->v(i,jp,k)-x->v(i,jm,k))*(y->v(ip,j,k)-y->v(im,j,k))*(z->v(i,j,kp)-z->v(i,j,km)) +
+					(x->v(i,jp,k)-x->v(i,jm,k))*(y->v(i,j,kp)-y->v(i,j,km))*(z->v(ip,j,k)-z->v(im,j,k)) +
+					(x->v(i,j,kp)-x->v(i,j,km))*(y->v(ip,j,k)-y->v(im,j,k))*(z->v(i,jp,k)-z->v(i,jm,k)) -
+					(x->v(i,j,kp)-x->v(i,j,km))*(y->v(i,jp,k)-y->v(i,jm,k))*(z->v(ip,j,k)-z->v(im,j,k));
+			r->a[i0] *= mreal((nx-1)*(ny-1)*(nz-1)) / mreal((ip-im)*(jp-jm)*(kp-km));
+		}
+
+	}
+	return r;
+}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_jacobian_2d_(uintptr_t* x, uintptr_t* y)
+{	return uintptr_t(mgl_jacobian_2d(_DA_(x), _DA_(y)));	}
+uintptr_t MGL_EXPORT mgl_jacobian_3d_(uintptr_t* x, uintptr_t* y, uintptr_t* z)
+{	return uintptr_t(mgl_jacobian_3d(_DA_(x), _DA_(y), _DA_(z)));	}
+//-----------------------------------------------------------------------------
+//
+//	Progonka
+//
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_progonka_sr(HCDT A, HCDT B, HCDT C, HCDT D, mreal *dat, long n, long id, long i0, long di, bool difr)
+{
+	mreal *aa=dat, *bb=dat+n, *uu=dat+2*n;
+	mreal b0=B->vthr(i0), c0=C->vthr(i0), d0=D->vthr(id);
+	if(difr)	d0 = (2.-b0)*d0-c0*D->vthr(id+di);
+	aa[0] = -c0/b0;	bb[0] = d0/b0;
+	for(long i=1;i<n;i++)
+	{
+		long ii=i0+di*i, dd=id+di*i, tt = id+di*((i+1)%n);
+		mreal a=A->vthr(ii), b=B->vthr(ii), c=C->vthr(ii);
+		mreal d=difr?-a*D->vthr(dd-di)+(2.-b)*D->vthr(dd)-c*D->vthr(tt):D->vthr(dd);
+		aa[i] = -c/(b+a*aa[i-1]);
+		bb[i] = (d-a*bb[i-1])/(b+a*aa[i-1]);
+	}
+	uu[n-1] = bb[n-1];
+	for(long i=n-2;i>=0;i--)	uu[i] = bb[i]+aa[i]*uu[i+1];
+}
+void MGL_NO_EXPORT mgl_progonka_pr(HCDT A, HCDT B, HCDT C, HCDT D, mreal *dat, long n, long id, long i0, long di, bool difr)
+{
+	mreal *aa=dat, *bb=dat+n, *gg=dat+2*n, *uu=dat+3*n;
+	mreal a0=A->vthr(i0), b0=B->vthr(i0), c0=C->vthr(i0), d0=D->vthr(id);
+	if(difr)	d0 = -a0*D->vthr(id+di*(n-1))+(2.-b0)*d0-c0*D->vthr(id+di);
+	aa[0] =-c0/b0;	bb[0] = d0/b0;	gg[0] =-a0/b0;
+	for(long i=1;i<n;i++)
+	{
+		long ii=i0+di*i, il=id+di*((i+1)%n), dd=id+di*i;
+		mreal a=A->vthr(ii), b=B->vthr(ii), c=C->vthr(ii);
+		mreal d=difr?-a*D->vthr(dd-di)+(2.-b)*D->vthr(dd)-c*D->vthr(il):D->vthr(dd);
+		aa[i] = -c/(b+a*aa[i-1]);
+		bb[i] = (d-a*bb[i-1])/(b+a*aa[i-1]);
+		gg[i] = -a*gg[i-1]/(b+a*aa[i-1]);
+	}
+	mreal P=bb[n-1]/(1.-gg[n-1]), Q=aa[n-1]/(1.-gg[n-1]);
+	aa[n-1] = Q;	bb[n-1] = P;
+	for(long i=n-2;i>=0;i--)
+	{
+		bb[i] += aa[i]*bb[i+1]+gg[i]*P;
+		aa[i] = aa[i]*aa[i+1]+gg[i]*Q;
+	}
+	mreal u0 = bb[0]/(1.-aa[0]);
+	for(long i=0;i<n;i++)	uu[i]=bb[i]+aa[i]*u0;
+}
+void MGL_NO_EXPORT mgl_progonka_hr(HCDT A, HCDT B, HCDT C, HCDT D, mreal *dat, long n, long id, long i0, bool difr)
+{
+	mreal *aa=dat, *bb=dat+n, *uu=dat+n*n;
+	mreal b0=B->vthr(i0), c0=C->vthr(i0), d0=D->vthr(id);
+	uu[0] = d0/b0*(difr?(2.-b0):1.);
+	b0=B->vthr(i0+n*n-1);	d0=D->vthr(id+n*n-1);
+	uu[n*n-1] = d0/b0*(difr?(2.-b0):1.);
+	long di = n-1, i1 = i0+n*(n-1), d1 = id+n*(n-1);
+	// suppose the square grid!
+	for(long j=1;j<n;j++)
+	{
+		// first bottom-left triangle
+		b0=B->vthr(i0+j);	c0=C->vthr(i0+j);	d0=D->vthr(id+j);
+		if(difr)	d0 = (2.-b0)*d0-c0*D->vthr(id+j+di);
+		aa[0] = -c0/b0;	bb[0] = d0/b0;
+		for(long i=1;i<=j;i++)
+		{
+			long ii=i0+j+di*i, dd=id+j+di*i;
+			mreal a=A->vthr(ii),b=B->vthr(ii),c=C->vthr(ii);
+			mreal d=difr?-a*D->vthr(dd-di)+(2.-b)*D->vthr(dd)-c*D->vthr(dd+di):D->vthr(dd);
+			aa[i] = -c/(b+a*aa[i-1]);
+			bb[i] = (d-a*bb[i-1])/(b+a*aa[i-1]);
+		}
+		uu[j+di*(j-1)] = bb[j];
+		for(long i=j-1;i>=0;i--)
+			uu[j+di*i] = bb[i]+aa[i]*uu[j+di*i+di];
+		// next top-right triangle
+		long j1=n-1-j;
+		b0=B->vthr(i1+j1);	c0=C->vthr(i1+j1);	d0=D->vthr(d1+j1);
+		if(difr)	d0 = (2.-b0)*d0-c0*D->vthr(d1+j1-di);
+		aa[0] = -c0/b0;	bb[0] = d0/b0;
+		for(long i=1;i<=j;i++)
+		{
+			long ii=i1+j1-di*i, dd=d1+j1-di*i;
+			mreal a=A->vthr(ii),b=B->vthr(ii),c=C->vthr(ii);
+			mreal d=difr?-a*D->vthr(dd+di)+(2.-b)*D->vthr(dd)-c*D->vthr(dd-di):D->vthr(dd);
+			aa[i] = -c/(b+a*aa[i-1]);
+			bb[i] = (d-a*bb[i-1])/(b+a*aa[i-1]);
+		}
+		uu[j1+n*(n-1)-di*(j-1)] = bb[j];
+		for(long i=j-1;i>=0;i--)
+			uu[j1+n*(n-1)-di*i] = bb[i]+aa[i]*uu[j1+n*(n-1)-di*i-di];
+	}
+}
+//-----------------------------------------------------------------------------
+HMDT MGL_EXPORT mgl_data_tridmat(HCDT A, HCDT B, HCDT C, HCDT D, const char *how)
+{
+	const long nx=D->GetNx(),ny=D->GetNy(),nz=D->GetNz();
+	const long nn=nx*ny*nz, np=nx*ny, na=A->GetNN();
+	if(B->GetNN()!=na || C->GetNN()!=na)	return 0;
+	mglData *r = new mglData(nx,ny,nz);
+	bool per = mglchr(how,'c');
+	bool difr = mglchr(how,'d');
+	if(mglchr(how,'x') && (na==nn || na==np || na==nx))
+#pragma omp parallel
+	{
+		mglData T(nx,4);	mreal *uu=T.a+(per?3:2)*nx;
+#pragma omp for collapse(2)
+		for(long k=0;k<nz;k++)	for(long j=0;j<ny;j++)
+		{
+			long i0=0, i1=nx*(j+ny*k);
+			if(na==nn)	i0=nx*(j+ny*k);	else if(na==np)	i0=nx*j;
+			if(per)	mgl_progonka_pr(A,B,C,D,T.a,nx,i1,i0,1,difr);
+			else	mgl_progonka_sr(A,B,C,D,T.a,nx,i1,i0,1,difr);
+			i0 = nx*(j+ny*k);
+			for(long i=0;i<nx;i++)	r->a[i+i0] = uu[i];
+		}
+	}
+	else if(mglchr(how,'y') && (na==nn || na==np || na==ny))
+#pragma omp parallel
+	{
+		mglData T(ny,4);	mreal *uu=T.a+(per?3:2)*ny;
+#pragma omp for collapse(2)
+		for(long k=0;k<nz;k++)	for(long i=0;i<nx;i++)
+		{
+			long i0=0, i1 = i+np*k;
+			if(na==nn)	i0=i+np*k;	else if(na==np)	i0=i;
+			if(per)	mgl_progonka_pr(A,B,C,D,T.a,ny,i1,i0,nx,difr);
+			else	mgl_progonka_sr(A,B,C,D,T.a,ny,i1,i0,nx,difr);
+			i0 = i+np*k;
+			for(long j=0;j<ny;j++)	r->a[j*nx+i0] = uu[j];
+		}
+	}
+	else if(mglchr(how,'z') && (na==nn || na==nz))
+#pragma omp parallel
+	{
+		mglData T(nz,4);	mreal *uu=T.a+(per?3:2)*nz;
+#pragma omp for collapse(2)
+		for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+		{
+			long i0 = na==nn?i+nx*j:0, i1 = i+nx*j;
+			if(per)	mgl_progonka_pr(A,B,C,D,T.a,nz,i1,i0,np,difr);
+			else	mgl_progonka_sr(A,B,C,D,T.a,nz,i1,i0,np,difr);
+			i0 = i+nx*j;
+			for(long k=0;k<nz;k++)	r->a[k*np+i0] = uu[k];
+		}
+	}
+	else if(mglchr(how,'h') && ny==nx && (na==nn || na==np) && nx>1)
+#pragma omp parallel
+	{
+		mglData T(np,2);
+#pragma omp for
+		for(long k=0;k<nz;k++)
+		{
+			mgl_progonka_hr(A,B,C,D,T.a,nx,k*np,na==nn ? k*np:0,difr);
+			memcpy(r->a+k*np, T.a+np, np*sizeof(mreal));
+		}
+	}
+	else	{	delete r;	r=0;	}
+	return r;
+}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_data_tridmat_(uintptr_t *A, uintptr_t *B, uintptr_t *C, uintptr_t *D, const char *how, int l)
+{	char *s=new char[l+1];	memcpy(s,how,l);	s[l]=0;
+	uintptr_t r = uintptr_t(mgl_data_tridmat(_DA_(A),_DA_(B),_DA_(C),_DA_(D),s));
+	delete []s;	return r;
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_progonka_sc(HCDT A, HCDT B, HCDT C, HCDT D, dual *dat, long n, long id, long i0, long di, bool difr)
+{
+	dual *aa=dat, *bb=dat+n, *uu=dat+2*n;
+	dual b0=B->vcthr(i0), c0=C->vcthr(i0), d0=D->vcthr(id);
+	if(difr)	d0 = (mreal(2)-b0)*d0-c0*D->vcthr(id+di);
+	aa[0] = -c0/b0;	bb[0] = d0/b0;
+	for(long i=1;i<n;i++)
+	{
+		long ii=i0+di*i, dd=id+di*i, tt = id+di*((i+1)%n);
+		dual a=A->vcthr(ii), b=B->vcthr(ii), c=C->vcthr(ii);
+		dual d=difr?-a*D->vcthr(dd-di)+(mreal(2)-b)*D->vcthr(dd)-c*D->vcthr(tt):D->vcthr(dd);
+		aa[i] = -c/(b+a*aa[i-1]);
+		bb[i] = (d-a*bb[i-1])/(b+a*aa[i-1]);
+	}
+	uu[n-1] = bb[n-1];
+	for(long i=n-2;i>=0;i--)	uu[i] = bb[i]+aa[i]*uu[i+1];
+}
+void MGL_NO_EXPORT mgl_progonka_pc(HCDT A, HCDT B, HCDT C, HCDT D, dual *dat, long n, long id, long i0, long di, bool difr)
+{
+	dual *aa=dat, *bb=dat+n, *gg=dat+2*n, *uu=dat+3*n;
+	dual a0=A->vcthr(i0), b0=B->vcthr(i0), c0=C->vcthr(i0), d0=D->vcthr(id);
+	if(difr)	d0 = -a0*D->vcthr(id+di*(n-1))+(mreal(2)-b0)*d0-c0*D->vcthr(id+di);
+	aa[0] =-c0/b0;	bb[0] = d0/b0;	gg[0] =-a0/b0;
+	for(long i=1;i<n;i++)
+	{
+		long ii=i0+di*i, il=id+di*((i+1)%n), dd=id+di*i;
+		dual a=A->vcthr(ii), b=B->vcthr(ii), c=C->vcthr(ii);
+		dual d=difr?-a*D->vcthr(dd-di)+(mreal(2)-b)*D->vcthr(dd)-c*D->vcthr(il):D->vcthr(dd);
+		aa[i] = -c/(b+a*aa[i-1]);
+		bb[i] = (d-a*bb[i-1])/(b+a*aa[i-1]);
+		gg[i] = -a*gg[i-1]/(b+a*aa[i-1]);
+	}
+	dual P=bb[n-1]/(mreal(1)-gg[n-1]), Q=aa[n-1]/(mreal(1)-gg[n-1]);
+	aa[n-1] = Q;	bb[n-1] = P;
+	for(long i=n-2;i>=0;i--)
+	{
+		bb[i] += aa[i]*bb[i+1]+gg[i]*P;
+		aa[i] = aa[i]*aa[i+1]+gg[i]*Q;
+	}
+	dual u0 = bb[0]/(mreal(1)-aa[0]);
+	for(long i=0;i<n;i++)	uu[i]=bb[i]+aa[i]*u0;
+}
+void MGL_NO_EXPORT mgl_progonka_hc(HCDT A, HCDT B, HCDT C, HCDT D, dual *dat, long n, long id, long i0, bool difr)
+{
+	dual *aa=dat, *bb=dat+n, *uu=dat+n*n;
+	dual b0=B->vcthr(i0), c0=C->vcthr(i0), d0=D->vcthr(id);
+	uu[0] = d0/b0*(difr?(mreal(2)-b0):mreal(1));
+	b0=B->vcthr(i0+n*n-1);	d0=D->vcthr(id+n*n-1);
+	uu[n*n-1] = d0/b0*(difr?(mreal(2)-b0):mreal(1));
+	long di = n-1, i1 = i0+n*(n-1), d1 = id+n*(n-1);
+	// suppose the square grid!
+	for(long j=1;j<n;j++)
+	{
+		// first bottom-left triangle
+		b0=B->vcthr(i0+j);	c0=C->vcthr(i0+j);	d0=D->vcthr(id+j);
+		if(difr)	d0 = (mreal(2)-b0)*d0-c0*D->vcthr(id+j+di);
+		aa[0] = -c0/b0;	bb[0] = d0/b0;
+		for(long i=1;i<=j;i++)
+		{
+			long ii=i0+j+di*i, dd=id+j+di*i;
+			dual a=A->vcthr(ii),b=B->vcthr(ii),c=C->vcthr(ii);
+			dual d=difr?-a*D->vcthr(dd-di)+(mreal(2)-b)*D->vcthr(dd)-c*D->vcthr(dd+di):D->vcthr(dd);
+			aa[i] = -c/(b+a*aa[i-1]);
+			bb[i] = (d-a*bb[i-1])/(b+a*aa[i-1]);
+		}
+		uu[j+di*(j-1)] = bb[j];
+		for(long i=j-1;i>=0;i--)
+			uu[j+di*i] = bb[i]+aa[i]*uu[j+di*i+di];
+		// next top-right triangle
+		long j1=n-1-j;
+		b0=B->vcthr(i1+j1);	c0=C->vcthr(i1+j1);	d0=D->vcthr(d1+j1);
+		if(difr)	d0 = (mreal(2)-b0)*d0-c0*D->vcthr(d1+j1-di);
+		aa[0] = -c0/b0;	bb[0] = d0/b0;
+		for(long i=1;i<=j;i++)
+		{
+			long ii=i1+j1-di*i, dd=d1+j1-di*i;
+			dual a=A->vcthr(ii),b=B->vcthr(ii),c=C->vcthr(ii);
+			dual d=difr?-a*D->vcthr(dd+di)+(mreal(2)-b)*D->vcthr(dd)-c*D->vcthr(dd-di):D->vcthr(dd);
+			aa[i] = -c/(b+a*aa[i-1]);
+			bb[i] = (d-a*bb[i-1])/(b+a*aa[i-1]);
+		}
+		uu[j1+n*(n-1)-di*(j-1)] = bb[j];
+		for(long i=j-1;i>=0;i--)
+			uu[j1+n*(n-1)-di*i] = bb[i]+aa[i]*uu[j1+n*(n-1)-di*i-di];
+	}
+}
+//-----------------------------------------------------------------------------
+HADT MGL_EXPORT mgl_datac_tridmat(HCDT A, HCDT B, HCDT C, HCDT D, const char *how)
+{
+	const long nx=D->GetNx(),ny=D->GetNy(),nz=D->GetNz();
+	const long nn=nx*ny*nz, np=nx*ny, na=A->GetNN();
+	if(B->GetNN()!=na || C->GetNN()!=na)	return 0;
+	mglDataC *r = new mglDataC(nx,ny,nz);
+	bool per = mglchr(how,'c');
+	bool difr = mglchr(how,'d');
+	if(mglchr(how,'x') && (na==nn || na==np || na==nx))
+#pragma omp parallel
+	{
+		mglDataC T(nx,4);	dual *uu=T.a+(per?3:2)*nx;
+#pragma omp for collapse(2)
+		for(long k=0;k<nz;k++)	for(long j=0;j<ny;j++)
+		{
+			long i0=0, i1=nx*(j+ny*k);
+			if(na==nn)	i0=i1;	else if(na==np)	i0=nx*j;
+			if(per)	mgl_progonka_pc(A,B,C,D,T.a,nx,i1,i0,1,difr);
+			else	mgl_progonka_sc(A,B,C,D,T.a,nx,i1,i0,1,difr);
+			for(long i=0;i<nx;i++)	r->a[i+i1] = uu[i];
+		}
+	}
+	else if(mglchr(how,'y') && (na==nn || na==np || na==ny))
+#pragma omp parallel
+	{
+		mglDataC T(ny,4);	dual *uu=T.a+(per?3:2)*ny;
+#pragma omp for collapse(2)
+		for(long k=0;k<nz;k++)	for(long i=0;i<nx;i++)
+		{
+			long i0=0, i1 = i+np*k;
+			if(na==nn)	i0=i1;	else if(na==np)	i0=i;
+			if(per)	mgl_progonka_pc(A,B,C,D,T.a,ny,i1,i0,nx,difr);
+			else	mgl_progonka_sc(A,B,C,D,T.a,ny,i1,i0,nx,difr);
+			i0 = i+np*k;
+			for(long j=0;j<ny;j++)	r->a[j*nx+i0] = uu[j];
+		}
+	}
+	else if(mglchr(how,'z') && (na==nn || na==nz))
+#pragma omp parallel
+	{
+		mglDataC T(nz,4);	dual *uu=T.a+(per?3:2)*nz;
+#pragma omp for collapse(2)
+		for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+		{
+			long i0 = na==nn?i+nx*j:0, i1 = i+nx*j;
+			if(per)	mgl_progonka_pc(A,B,C,D,T.a,nz,i1,i0,np,difr);
+			else	mgl_progonka_sc(A,B,C,D,T.a,nz,i1,i0,np,difr);
+			for(long k=0;k<nz;k++)	r->a[k*np+i1] = uu[k];
+		}
+	}
+	else if(mglchr(how,'h') && ny==nx && (na==nn || na==np) && nx>1)
+#pragma omp parallel
+	{
+		mglDataC T(np,2);
+#pragma omp for
+		for(long k=0;k<nz;k++)
+		{
+			mgl_progonka_hc(A,B,C,D,T.a,nx,k*np, na==nn ? k*np:0,difr);
+			memcpy(r->a+k*np, T.a+np, np*sizeof(dual));
+		}
+	}
+	else	{	delete r;	r=0;	}
+	return r;
+}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_datac_tridmat_(uintptr_t *A, uintptr_t *B, uintptr_t *C, uintptr_t *D, const char *how, int l)
+{	char *s=new char[l+1];	memcpy(s,how,l);	s[l]=0;
+	uintptr_t r = uintptr_t(mgl_datac_tridmat(_DA_(A),_DA_(B),_DA_(C),_DA_(D),s));
+	delete []s;	return r;
+}
+//-----------------------------------------------------------------------------
diff --git a/src/pixel.cpp b/src/pixel.cpp
new file mode 100644
index 0000000..23538b8
--- /dev/null
+++ b/src/pixel.cpp
@@ -0,0 +1,1490 @@
+/***************************************************************************
+ * pixel.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <algorithm>
+#include "mgl2/canvas.h"
+#include "mgl2/thread.h"
+#if MGL_HAVE_OMP
+#include <omp.h>
+#endif
+
+//-----------------------------------------------------------------------------
+void mglCanvas::pxl_combine(long id, long n, const void *)
+{
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=id;i<n;i+=mglNumThr)
+	{
+		unsigned char *cc = C+12*i, c[4];
+		memcpy(c,GB+4*i,4);	// memcpy(c,BDef,4);
+		combine(c,cc+8);	combine(c,cc+4);
+		combine(c,cc);		memcpy(G4+4*i,c,4);
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::pxl_memcpy(long id, long n, const void *)
+{
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=id;i<n;i+=mglNumThr)	memcpy(G4+4*i,C+12*i,4);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::pxl_backgr(long id, long n, const void *)
+{
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=id;i<n;i+=mglNumThr)
+	{	unsigned char c[4];	memcpy(c,GB+4*i,4);	combine(c,G4+4*i);	memcpy(G+3*i,c,3);	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::pxl_transform(long id, long n, const void *)
+{
+	const mreal *b = Bp.b;
+	const mreal dx = -Bp.x*Width/2, dy = -Bp.y*Height/2, dz = Depth/2.;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=id;i<n;i+=mglNumThr)
+	{
+		mglPnt &p=Pnt[i];
+		if(p.sub>=0)
+		{
+			float x = p.xx-Width/2., y = p.yy-Height/2., z = p.zz-Depth/2.;
+			p.x = b[0]*x + b[1]*y + b[2]*z + dx;
+			p.y = b[3]*x + b[4]*y + b[5]*z + dy;
+			p.z = b[6]*x + b[7]*y + b[8]*z + dz;
+			float d = get_persp(Bp.pf,p.z,Depth);
+			p.x = Width/2. + d*p.x;	p.y = Height/2. + d*p.y;
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::pxl_setz_adv(long id, long n, const void *)
+{
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=id;i<n;i+=mglNumThr)
+	{
+		mglPrim &q=Prm[i];	q.z = Pnt[q.n1].z;
+		if(q.type==3)	q.z = (q.z + Pnt[q.n2].z + Pnt[q.n3].z + Pnt[q.n4].z)/4;
+		else if(q.type==2)	q.z = (q.z + Pnt[q.n2].z + Pnt[q.n3].z)/3;
+		else if(q.type==1)	q.z = (q.z + Pnt[q.n2].z)/2;
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::pxl_pntcol(long id, long n, const void *)
+{
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=id;i<n;i+=mglNumThr)
+	{	mglRGBA c;	col2int(Pnt[i],c.r,HighId-1);	pnt_col[i]=c.c;	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::pxl_setz(long id, long n, const void *)
+{
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=id;i<n;i+=mglNumThr)
+	{	mglPrim &q=Prm[i];	q.z = Pnt[q.n1].z;	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::pxl_primdr(long id, long , const void *)
+{
+#define Q	4	// should be >= sqrt(2*num_thr) ???
+	const int nx=Q,ny=Q;	// TODO find dependence on Q for 1, 2, 4, 8 threads. Try to select optimal
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=id;i<nx*ny;i+=mglNumThr)
+	{
+		mglDrawReg d;	d.set(this,nx,ny,i);
+		if(Quality&MGL_DRAW_NORM)	for(size_t k=0;k<Prm.size();k++)
+		{
+			if(Stop)	break;
+			const mglPrim &p=GetPrm(k);	d.copy(p);
+			long n1=p.n1, n2=p.n2, n3=p.n3, n4=p.n4;
+			switch(p.type)
+			{
+				case 3:	quad_draw(Pnt[n1],Pnt[n2],Pnt[n3],Pnt[n4],&d);	break;
+				case 1:	line_draw(Pnt[n1],Pnt[n2],&d);	break;
+				case 4:	glyph_draw(p,&d);	break;
+				case 0:	mark_draw(Pnt[n1],n4,p.s,&d);	break;
+				case 2:	trig_draw(Pnt[n1],Pnt[n2],Pnt[n3],true,&d);	break;
+			}
+		}
+		else if(Quality&MGL_DRAW_FAST)	for(size_t k=0;k<Prm.size();k++)
+		{
+			if(Stop)	break;
+			const mglPrim &p=GetPrm(k);	d.copy(p);
+			long n1=p.n1, n2=p.n2, n3=p.n3, n4=p.n4;
+			switch(p.type)
+			{
+				case 3:	trig_draw(Pnt[n1],Pnt[n2],Pnt[n4],true,&d);
+						trig_draw(Pnt[n1],Pnt[n3],Pnt[n4],true,&d);	break;
+				case 1:	line_draw(Pnt[n1],Pnt[n2],&d);	break;
+				case 4:	glyph_draw(p,&d);	break;
+				case 0:	mark_draw(Pnt[n1],n4,p.s,&d);	break;
+				case 2:	trig_draw(Pnt[n1],Pnt[n2],Pnt[n3],true,&d);	break;
+			}
+		}
+		else	for(size_t k=0;k<Prm.size();k++)
+		{
+			if(Stop)	break;
+			const mglPrim &p=GetPrm(k);	d.copy(p);
+			long n1=p.n1, n2=p.n2, n3=p.n3, n4=p.n4;
+			switch(p.type)
+			{
+				case 3:	fast_draw(Pnt[n1],Pnt[n4],&d);	fast_draw(Pnt[n2],Pnt[n3],&d);	break;
+				case 1:	fast_draw(Pnt[n1],Pnt[n2],&d);	break;
+				case 4:	glyph_draw(p,&d);	break;
+				case 0:	mark_draw(Pnt[n1],n4,p.s,&d);	break;
+				case 2:	fast_draw(Pnt[n1],Pnt[n2],&d);	fast_draw(Pnt[n1],Pnt[n3],&d);
+				fast_draw(Pnt[n2],Pnt[n3],&d);	break;
+			}
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::pxl_dotsdr(long id, long n, const void *)
+{
+	const mreal *b = Bp.b;
+	const mreal dx = -Bp.x*Width/2, dy = -Bp.y*Height/2, dz = Depth/2.;
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+	for(long i=id;i<n;i+=mglNumThr)
+	{
+		unsigned char r[4]={0,0,0,255};
+		const mglPnt &p=Pnt[i];
+		if(p.sub<0)	continue;
+		float x = p.xx-Width/2., y = p.yy-Height/2., z = p.zz-Depth/2.,xx,yy,zz;
+		xx = b[0]*x + b[1]*y + b[2]*z + dx;
+		yy = b[3]*x + b[4]*y + b[5]*z + dy;
+		zz = b[6]*x + b[7]*y + b[8]*z + dz;
+		float d = get_persp(Bp.pf,zz,Depth);
+		xx = Width/2. + d*xx;	yy = Height/2. + d*yy;
+
+		r[0] = (unsigned char)(255*p.r);
+		r[1] = (unsigned char)(255*p.g);
+		r[2] = (unsigned char)(255*p.b);
+		long i0=long(xx)+Width*(Height-1-long(yy));
+		if(i0>=0 && i0<Width*Height && zz>Z[3*i0])
+		{	Z[3*i0]=z;	memcpy(C+12*i0,r,4);	OI[i0]=-1;	}
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::pxl_other(long id, long n, const void *p)
+{
+	const mglCanvas *gr = (const mglCanvas *)p;
+	if(Quality&MGL_DRAW_NORM)
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+		for(long k=id;k<n;k+=mglNumThr)
+		{
+			long i = k%Width, j = Height-1-(k/Width);
+			pnt_plot(i,j,gr->Z[3*k+2],gr->C+12*k+8,gr->OI[k]);
+			pnt_plot(i,j,gr->Z[3*k+1],gr->C+12*k+4,gr->OI[k]);
+			pnt_plot(i,j,gr->Z[3*k],gr->C+12*k,gr->OI[k]);
+		}
+	else
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for
+#endif
+		for(long k=id;k<n;k+=mglNumThr)
+		{
+			long i = k%Width, j = Height-1-(k/Width);
+			pnt_plot(i,j,gr->Z[3*k],gr->C+12*k,gr->OI[k]);
+		}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::pnt_plot(long x,long y,mreal z,const unsigned char ci[4], int obj_id)
+{
+	if(ci[3])
+	{
+		long i0=x+Width*(Height-1-y);
+		unsigned char *cc = C+12*i0, c[4];
+		memcpy(c,ci,4);
+		float *zz = Z+3*i0, zf = FogDist*(z/Depth-0.5-FogDz);
+		// try to remove double transparency near vertexes
+		if(fabs(z-zz[0])<1 && OI[i0]==obj_id && abs(cc[0]-ci[0])+abs(cc[1]-ci[1])+abs(cc[2]-ci[2])<5)
+		{	if(cc[3]<ci[3])	memcpy(cc,c,4);	return;	}
+		if(zf<0)	// add fog
+		{
+			int d = int(255.f-255.f*exp(5.f*zf));
+			unsigned char cb[4] = {BDef[0], BDef[1], BDef[2], (unsigned char)d};
+			if(d==255)	return;
+			combine(c,cb);
+		}
+		if(Quality&MGL_DRAW_NORM)
+		{
+			if(z>=zz[1])	// shift point on slice down and paste new point
+			{
+				zz[2] = zz[1];	combine(cc+8,cc+4);
+				if(z>=zz[0])
+				{	zz[1] = zz[0];	zz[0] = z;	OI[i0]=obj_id;
+					memcpy(cc+4,cc,4);	memcpy(cc,c,4);		}
+				else	{	zz[1] = z;	memcpy(cc+4,c,4);	}
+			}
+			else
+			{
+				if(z>=zz[2])	// shift point on slice down and paste new point
+				{	zz[2] = z;	combine(cc+8,c);	}
+				else		// point below the background
+				{	combine(c,cc+8);	memcpy(cc+8,c,4);	}
+			}
+		}
+		if(Quality&MGL_DRAW_FAST)
+		{
+			if(z>=zz[0])	// point upper the background
+			{	zz[0]=z;	combine(cc,c);	OI[i0]=obj_id;	}
+		}
+		else
+		{
+			if(z>=zz[0])	// point upper the background
+			{	zz[0]=z;	memcpy(cc,c,4);		OI[i0]=obj_id;	}
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+unsigned char* mglCanvas::col2int(const mglPnt &p,unsigned char *r, int obj_id) const
+{
+//	if(!r)	return r;	// NOTE r must be provided!
+	if(p.a<=0)	{	memset(r,0,4);	return r;	}
+	float b0=0,b1=0,b2=0, ar,ag,ab,dif;
+	const size_t nl = p.sub>=0?p.sub:1-p.sub;
+	const bool glob = !get(MGL_LOCAL_LIGHT);
+	ar = ag = ab = glob?AmbBr:Sub[nl].AmbBr;
+	dif = glob?DifBr:Sub[nl].DifBr;
+
+	if(mgl_isnum(p.u+p.v+p.w))
+	{
+		float d0,d1,d2,nn;
+		for(long i=0;i<10;i++)
+		{
+			const mglLight &ll=glob?light[i]:Sub[nl].light[i];
+			if(!ll.n)	continue;
+			if(mgl_isnan(ll.q.x))		// source at infinity
+			{
+				nn = 2*(p.u*ll.p.x+p.v*ll.p.y+p.w*ll.p.z) / (p.u*p.u+p.v*p.v+p.w*p.w+1e-6);
+				d0 = ll.p.x - p.u*nn;
+				d1 = ll.p.y - p.v*nn;
+				d2 = ll.p.z - p.w*nn;
+				nn = 1 + d2/sqrt(d0*d0+d1*d1+d2*d2+1e-6);
+
+				nn = exp(-ll.a*nn)*ll.b*2;
+				b0 += nn*ll.c.r;
+				b1 += nn*ll.c.g;
+				b2 += nn*ll.c.b;
+			}
+			else		// diffuse and specular light
+			{
+				d0 = ll.q.x-p.x;	// direction to light source
+				d1 = ll.q.y-p.y;
+				d2 = ll.q.z-p.z;
+				nn = 1+(d0*ll.p.x+d1*ll.p.y+d2*ll.p.z)/sqrt(d0*d0+d1*d1+d2*d2+1e-6);
+				float bb = exp(-3*ll.a*nn);	nn = bb*dif*2;
+				ar += nn*ll.c.r;
+				ag += nn*ll.c.g;
+				ab += nn*ll.c.b;
+
+				nn = 2*(p.u*d0+p.v*d1+p.w*d2) / (p.u*p.u+p.v*p.v+p.w*p.w+1e-6);
+				d0 -= p.u*nn;	d1 -= p.v*nn;	d2 -= p.w*nn;
+				nn = 1 + d2/sqrt(d0*d0+d1*d1+d2*d2+1e-6);
+
+				nn = exp(-ll.a*nn)*bb*ll.b*2;
+				b0 += nn*ll.c.r;
+				b1 += nn*ll.c.g;
+				b2 += nn*ll.c.b;
+			}
+		}
+		b0 += (ar>1 ? 1:ar)*p.r;	// diffuse light
+		b1 += (ag>1 ? 1:ag)*p.g;
+		b2 += (ab>1 ? 1:ab)*p.b;
+		b0 = b0<1 ? b0 : 1;			// normalize components
+		b1 = b1<1 ? b1 : 1;
+		b2 = b2<1 ? b2 : 1;
+	}
+	else
+	{	b0=p.r;	b1=p.g;	b2=p.b;	}
+	// try to highlight faces
+	if(obj_id==HighId)	{	b0*=0.7;	b1*=0.7;	b2*=0.7;	}
+	r[0] = (unsigned char)(255*b0);
+	r[1] = (unsigned char)(255*b1);
+	r[2] = (unsigned char)(255*b2);
+//	r[3] = get(MGL_ENABLE_ALPHA) ? (unsigned char)(255*p.a) : 255;
+	r[3] = (unsigned char)((Quality&MGL_DRAW_NORM)?255*p.a:255);
+	return r;
+}
+//-----------------------------------------------------------------------------
+/// color mixing: color c1 is under color c2 !!!
+void mglCanvas::combine(unsigned char *c1, const unsigned char *c2) const
+{
+	if(c2[3])
+	{
+		const unsigned a1=c1[3], a2=c2[3];
+		if((Flag&3)==0)
+		{
+			unsigned b1=255-a2;
+			c1[0] = (c1[0]*b1 + c2[0]*a2)/256;
+			c1[1] = (c1[1]*b1 + c2[1]*a2)/256;
+			c1[2] = (c1[2]*b1 + c2[2]*a2)/256;
+			c1[3] = (unsigned char)(a2+a1*b1/255);
+		}
+		else if((Flag&3)==1)
+		{
+			c1[0] = (unsigned char)((255-a1*(255-c1[0])/256)*(255-a2*(255-c2[0])/256)/256);
+			c1[1] = (unsigned char)((255-a1*(255-c1[1])/256)*(255-a2*(255-c2[1])/256)/256);
+			c1[2] = (unsigned char)((255-a1*(255-c1[2])/256)*(255-a2*(255-c2[2])/256)/256);
+			c1[3] = 255;
+		}
+		else if((Flag&3)==2)
+		{
+			unsigned b1,b2,b3;
+			b1 = (c1[0]*a1 + c2[0]*a2)/255;	c1[0] = b1<255 ? b1 : 255;
+			b2 = (c1[1]*a1 + c2[1]*a2)/255;	c1[1] = b2<255 ? b2 : 255;
+			b3 = (c1[2]*a1 + c2[2]*a2)/255;	c1[2] = b3<255 ? b3 : 255;
+			c1[3] = 255;
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+bool inline visible(long i, long j, const unsigned char m[8], mreal pw, int a)	// Check if pixel visible
+{
+	float c = mgl_cos[(a+360)%360], s = mgl_cos[(a+450)%360];
+//	int ii = int(0.5+(i*c+j*s)/pw)%8, jj = int(0.5+(j*c-i*s)/pw)%8;
+//	if(ii<0)	ii+=8;	if(jj<0)	jj+=8;
+	int ii = int(0.5+(i*c+j*s)/pw)&7, jj = int(0.5+(j*c-i*s)/pw)&7;
+	return m[jj] & (1L<<ii);
+}
+//-----------------------------------------------------------------------------
+/* Bilinear interpolation r(u,v) = r0 + (r1-r0)*u + (r2-r0)*v + (r3+r0-r1-r2)*u*v
+	is used (where r is one of {x,y,z,R,G,B,A}. Variables u,v are determined
+	for each point (x,y) and selected one pair which 0<u<1 and 0<v<1.*/
+void mglCanvas::quad_draw(const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, const mglPnt &p4, const mglDrawReg *d)
+{
+	if(Quality&MGL_DRAW_LMEM)
+	{
+		if(!(Quality&3))
+		{	fast_draw(p1,p4,d);	fast_draw(p2,p3,d);	return;	}
+		if(!(Quality&MGL_DRAW_NORM))
+		{	trig_draw(p1,p2,p4,true,d);	trig_draw(p1,p3,p4,true,d);	return;	}
+	}
+	unsigned char r[4];
+	long y1,x1,y2,x2;
+	mglPnt d1(p2-p1), d2(p3-p1), d3(p4+p1-p2-p3);
+
+	if(d1.x==0 && d1.y==0)	{	trig_draw(p1,p3,p4,true,d);	return;	}
+	if(d2.x==0 && d2.y==0)	{	trig_draw(p1,p2,p4,true,d);	return;	}
+
+	x1 = long(mgl_min(mgl_min(p1.x,p2.x), mgl_min(p3.x,p4.x)));	// bounding box
+	y1 = long(mgl_min(mgl_min(p1.y,p2.y), mgl_min(p3.y,p4.y)));
+	x2 = long(mgl_max(mgl_max(p1.x,p2.x), mgl_max(p3.x,p4.x)));
+	y2 = long(mgl_max(mgl_max(p1.y,p2.y), mgl_max(p3.y,p4.y)));
+	x1=mgl_max(x1,d->x1);	x2=mgl_min(x2,d->x2);
+	y1=mgl_max(y1,d->y1);	y2=mgl_min(y2,d->y2);
+//	if(x1>x2 || y1>y2)	return;
+
+	const float dd = d1.x*d2.y-d1.y*d2.x;
+	const float dsx =-4*(d2.y*d3.x - d2.x*d3.y)*d1.y;
+	const float dsy = 4*(d2.y*d3.x - d2.x*d3.y)*d1.x;
+
+	mglPoint n1(mglPoint(p2.x-p1.x,p2.y-p1.y,p2.z-p1.z)^mglPoint(p3.x-p1.x,p3.y-p1.y,p3.z-p1.z));
+	mglPoint n2(mglPoint(p2.x-p4.x,p2.y-p4.y,p2.z-p4.z)^mglPoint(p3.x-p4.x,p3.y-p4.y,p3.z-p4.z));
+	mglPoint nr((n1.x+n2.x)*0.5,(n1.y+n2.y)*0.5,(n1.z+n2.z)*0.5);
+
+	const float x0 = p1.x, y0 = p1.y;
+	const int oi = d->ObjId, ang=d->angle;
+	const mreal pw = d->PenWidth;
+	const uint64_t pd = d->PDef;
+	for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+	{
+		if(pd==MGL_SOLID_MASK || visible(i,j,d->m, pw,ang))
+		{
+			float xx = (i-x0), yy = (j-y0), s;
+			s = dsx*xx + dsy*yy + (dd+d3.y*xx-d3.x*yy)*(dd+d3.y*xx-d3.x*yy);
+			if(s>=0)
+			{
+				s = sqrt(s);
+				float qu = d3.x*yy - d3.y*xx + dd + s;
+				float qv = d3.y*xx - d3.x*yy + dd + s;
+				float u = 2.f*(d2.y*xx - d2.x*yy)/qu;
+				float v = 2.f*(d1.x*yy - d1.y*xx)/qv;
+				if(u*(1.f-u)<0.f || v*(1.f-v)<0.f)	// first root bad
+				{
+					qu = d3.x*yy - d3.y*xx + dd - s;
+					qv = d3.y*xx - d3.x*yy + dd - s;
+//					u = v = -1.f;
+					u = 2.f*(d2.y*xx - d2.x*yy)/qu;	v = 2.f*(d1.x*yy - d1.y*xx)/qv;
+					if(u*(1.f-u)<0.f || v*(1.f-v)<0.f)	continue;	// second root bad
+				}
+				mglPnt p(p1+d1*u+d2*v+d3*(u*v));
+				if(mgl_isnan(p.u) && mgl_isnum(p.v))
+				{	p.u = nr.x;	p.v = nr.y;	p.w = nr.z;	}
+				pnt_plot(i,j,p.z,col2int(p,r,oi),oi);
+			}
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+/* Linear interpolation r(u,v) = r0 + (r1-r0)*u + (r2-r0)*v is used, where r is
+	one of {x,y,z,R,G,B,A}. Variables u,v are determined for each point (x,y).
+	Point plotted is u>0 and v>0 and u+v<1.*/
+void mglCanvas::trig_draw(const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, bool anorm, const mglDrawReg *d)
+{
+	if(!(Quality&3) && anorm)
+	{	fast_draw(p1,p2,d);	fast_draw(p1,p3,d);	fast_draw(p2,p3,d);	return;	}
+	unsigned char r[4];
+	long y1,x1,y2,x2;
+	const mglPnt d1(p2-p1), d2(p3-p1);
+
+	const float tmp = d2.x*d1.y - d1.x*d2.y;
+	if(fabs(tmp)<1e-5)	return;		// points lies on the same line
+	const float dyv =-d1.x/tmp,	dxv = d1.y/tmp;
+	const float dyu = d2.x/tmp,	dxu =-d2.y/tmp;
+
+	x1 = long(mgl_min(p1.x<p2.x?p1.x:p2.x, p3.x));	// bounding box
+	y1 = long(mgl_min(p1.y<p2.y?p1.y:p2.y, p3.y));
+	x2 = long(mgl_max(p1.x>p2.x?p1.x:p2.x, p3.x));
+	y2 = long(mgl_max(p1.y>p2.y?p1.y:p2.y, p3.y));
+	x1=x1>d->x1?x1:d->x1;	x2=x2<d->x2?x2:d->x2;
+	y1=y1>d->y1?y1:d->y1;	y2=y2<d->y2?y2:d->y2;
+//	if(x1>x2 || y1>y2)	return;
+	// default normale
+	const mglPoint nr(mglPoint(p2.x-p1.x,p2.y-p1.y,p2.z-p1.z)^mglPoint(p3.x-p1.x,p3.y-p1.y,p3.z-p1.z));
+	const float x0 = p1.x, y0 = p1.y;
+	// provide additional height to be well visible on the surfaces
+	const float dz = anorm? 0 : (Width>2 ? 1 : 1e-5*Width);
+	const int oi = d->ObjId, ang=d->angle;
+	const mreal pw = d->PenWidth;
+	const uint64_t pd = d->PDef;
+	if(Quality&MGL_DRAW_NORM)	for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+	{
+		if(pd==MGL_SOLID_MASK || visible(i,j,d->m, pw,ang))
+		{
+			float xx = (i-x0), yy = (j-y0);
+			float u = dxu*xx+dyu*yy, v = dxv*xx+dyv*yy;
+			if(u<0 || v<0 || u+v>1)	continue;
+			mglPnt p(p1+d1*u+d2*v);
+			if(mgl_isnan(p.u) && mgl_isnum(p.v) && anorm)
+			{	p.u = nr.x;	p.v = nr.y;	p.w = nr.z;	}
+			pnt_plot(i,j,p.z+dz,col2int(p,r,oi),oi);
+		}
+	}
+	else
+	{
+		col2int(p1,r,oi);
+		float zz = p1.z+dz;
+		for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+		{
+			if(pd==MGL_SOLID_MASK || visible(i,j,d->m, pw,ang))
+			{
+				float xx = (i-x0), yy = (j-y0);
+				float u = dxu*xx+dyu*yy, v = dxv*xx+dyv*yy;
+				if(u<0 || v<0 || u+v>1)	continue;
+				pnt_plot(i,j,zz,r,oi);
+			}
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+inline unsigned char mgl_sline(unsigned char c,float x)
+{	x*=x/2;	return (unsigned char)(c/(1+x+x*x/5));	}
+void mglCanvas::line_draw(const mglPnt &p1, const mglPnt &p2, const mglDrawReg *dr)
+{
+	if((Quality&3)==MGL_DRAW_WIRE)	{	fast_draw(p1,p2,dr);	return;	}	// previously was <2. This may slightly slow down for Quality=1
+	unsigned char r[4];
+	long y1,x1,y2,x2;
+
+	const float dz = Width>2 ? 1 : 1e-5*Width;		// provide additional height to be well visible on the surfaces
+	const int oi = dr->ObjId;
+	const float pw=dr->PenWidth*(oi==HighId?2:1), dpw=pen_delta*(oi==HighId?2:3);
+	const mglPnt d(p2-p1);
+	bool hor = fabs(d.x)>fabs(d.y);
+
+	x1 = long(p1.x<p2.x?p1.x:p2.x);	y1 = long(p1.y<p2.y?p1.y:p2.y);	// bounding box
+	x2 = long(p1.x>p2.x?p1.x:p2.x);	y2 = long(p1.y>p2.y?p1.y:p2.y);
+	x1 -= pw+10/dpw;	x2 += pw+10/dpw;
+	y1 -= pw+10/dpw;	y2 += pw+10/dpw;
+	x1=x1>dr->x1?x1:dr->x1;	x2=x2<dr->x2?x2:dr->x2;
+	y1=y1>dr->y1?y1:dr->y1;	y2=y2<dr->y2?y2:dr->y2;
+	const float dd = hypot(d.x, d.y);
+//	if(x1>x2 || y1>y2 || dd<1e-5)	return;
+	if(dd<1e-5)	return;
+
+	const float dxv = d.y/dd, dyv =-d.x/dd;
+	const float dxu = d.x/dd, dyu = d.y/dd;
+
+	const uint64_t pd = dr->PDef;
+	const mreal pp = dr->pPos;
+	if(hor)	for(long i=x1;i<=x2;i++)
+	{
+		y1 = int(p1.y+d.y*(i-p1.x)/d.x - pw - 10/dpw);
+		y2 = int(p1.y+d.y*(i-p1.x)/d.x + pw + 10/dpw);
+		y1=y1>dr->y1?y1:dr->y1;	y2=y2<dr->y2?y2:dr->y2;
+		if(y1>y2)	continue;
+		for(long j=y1;j<=y2;j++)
+		{
+			float xx = (i-p1.x), yy = (j-p1.y);
+			float u = dxu*xx+dyu*yy, v = dxv*xx+dyv*yy;	v = v*v;
+			if(u<0)			v += u*u;
+			else if(u>dd)	v += (u-dd)*(u-dd);
+//			if(v>pw*pw)		continue;
+			if(!(pd & ((uint64_t)1<<long(fmod(pp+u/pw, 16)) ) ))	continue;
+			mglPnt p(p1+d*(u/dd));	col2int(p,r,oi);
+			r[3] = v<(pw-1)*(pw-1)/4 ? 255 : mgl_sline(255,dpw*(sqrt(v)+(1-pw)/2));
+			pnt_plot(i,j,p.z+dz,r,oi);
+		}
+	}
+	else	for(long j=y1;j<=y2;j++)
+	{
+		x1 = int(p1.x+d.x*(j-p1.y)/d.y - pw - 10/dpw);
+		x2 = int(p1.x+d.x*(j-p1.y)/d.y + pw + 10/dpw);
+		x1=x1>dr->x1?x1:dr->x1;	x2=x2<dr->x2?x2:dr->x2;
+		if(x1>x2)	continue;
+
+		for(long i=x1;i<=x2;i++)
+		{
+			float xx = (i-p1.x), yy = (j-p1.y);
+			float u = dxu*xx+dyu*yy, v = dxv*xx+dyv*yy;	v = v*v;
+			if(u<0)			v += u*u;
+			else if(u>dd)	v += (u-dd)*(u-dd);
+//			if(v>pw*pw)		continue;
+			if(!(pd & ((uint64_t)1<<long(fmod(pp+u/pw, 16)))))		continue;
+			mglPnt p(p1+d*(u/dd));	col2int(p,r,oi);
+			r[3] = v<(pw-1)*(pw-1)/4 ? 255 : mgl_sline(255,dpw*(sqrt(v)+(1-pw)/2));
+			pnt_plot(i,j,p.z+dz,r,oi);
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::pnt_fast(long x,long y,mreal z,const unsigned char ci[4], int obj_id)
+{
+	long i0=x+Width*(Height-1-y);
+	if(ci[3]!=0 && z>Z[3*i0])	// point upper the background
+	{	Z[3*i0]=z;	memcpy(C+12*i0,ci,4);	OI[i0]=obj_id;	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::fast_draw(const mglPnt &p1, const mglPnt &p2, const mglDrawReg *dr)
+{
+	if(p1.x==p2.x && p1.y==p2.y) return;
+	const mglPnt d(p2-p1);
+	const int oi = dr->ObjId;
+	unsigned char r[4];	col2int(p1,r,oi);
+	long y1,x1,y2,x2;
+
+	const bool hor = fabs(d.x)>fabs(d.y);
+
+	x1 = long(p1.x<p2.x?p1.x:p2.x);	y1 = long(p1.y<p2.y?p1.y:p2.y);	// bounding box
+	x2 = long(p1.x>p2.x?p1.x:p2.x);	y2 = long(p1.y>p2.y?p1.y:p2.y);
+	x1=x1>dr->x1?x1:dr->x1;	x2=x2<dr->x2?x2:dr->x2;
+	y1=y1>dr->y1?y1:dr->y1;	y2=y2<dr->y2?y2:dr->y2;
+	if(x1>x2 || y1>y2)	return;
+	const float dz = Width>2 ? 1 : 1e-5*Width;	// provide additional height to be well visible on the surfaces
+
+	if(hor)	for(long i=x1;i<=x2;i++)
+	{
+		long c = long(p1.y+d.y*(i-p1.x)/d.x);
+		if(c>=y1 && c<=y2)
+			pnt_fast(i, c, p1.z+d.z*(i-p1.x)/d.x+dz, r,oi);
+	}
+	else	for(long i=y1;i<=y2;i++)
+	{
+		long c = long(p1.x+d.x*(i-p1.y)/d.y);
+		if(c>=x1 && c<=x2)
+			pnt_fast(c, i, p1.z+d.z*(i-p1.y)/d.y+dz, r,oi);
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::pnt_draw(const mglPnt &p, const mglDrawReg *dr)
+{
+//	if(k<0 || !dr)	return;
+	const int oi = dr->ObjId;
+	const float pw=(oi==HighId?6:3)*dr->PenWidth,dpw=(oi==HighId?2:3)*pen_delta;
+	unsigned char cs[4], cc;
+	col2int(p,cs,oi);	cc = cs[3];
+	if(cc==0)	return;
+	const long s = long(pw+10/dpw+fabs(pw));
+	const long i1=mgl_max(-s,dr->x1-p.x),i2=mgl_min(s,dr->x2-p.x);
+	const long j1=mgl_max(-s,dr->y1-p.y),j2=mgl_min(s,dr->y2-p.y);
+	if(!(Quality&3))	for(long j=j1;j<=j2;j++)	for(long i=i1;i<=i2;i++)	// fast draw
+	{
+		float v = i*i+j*j;
+		if(v>1+(pw-1)*(pw-1)/4)	continue;
+		pnt_plot(p.x+i,p.y+j,p.z,cs,oi);
+	}
+	else	for(long j=j1;j<=j2;j++)	for(long i=i1;i<=i2;i++)
+	{
+		float v = i*i+j*j;
+		cs[3] = v<(pw-1)*(pw-1)/4 ? cc : mgl_sline(cc,dpw*(sqrt(v)+(1-pw)/2));
+		pnt_plot(p.x+i,p.y+j,p.z,cs,oi);
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::mark_draw(const mglPnt &q, char type, mreal size, mglDrawReg *d)
+{
+	const int oi = d?d->ObjId:-1;
+	unsigned char cs[4];	col2int(q,cs,oi);
+	const unsigned char ca = cs[3];// = size>0 ? 255 : 255*q.t;
+	const mreal ss=(strchr("xsSoO",type)?1:1.1)*fabs(size), dpw=(oi==HighId?2:3)*pen_delta;
+	mreal PW=1;
+
+	if(type=='.' || ss==0)
+	{
+		if(d)	PW = 3*(ss?ss:sqrt(font_factor/400));
+		if(oi==HighId)	PW *= 2;
+		const mreal pw = PW;
+		mreal dd = pw+10/dpw;
+		long x1 = long(q.x-dd), y1 = long(q.y-dd);	// bounding box
+		long x2 = long(q.x+dd), y2 = long(q.y+dd);
+		x1=x1>d->x1?x1:d->x1;	x2=x2<d->x2?x2:d->x2;
+		y1=y1>d->y1?y1:d->y1;	y2=y2<d->y2?y2:d->y2;
+		if(x1>x2 || y1>y2)	return;
+		const float V=(pw-1)*(pw-1)/4,S=(1-pw)/2;
+
+		for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+		{
+			float dx=i-q.x, dy=j-q.y, v=dx*dx+dy*dy;
+			int sum = v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+			cs[3] = ca*sum/255;
+			pnt_plot(i,j,q.z+1,cs,oi);
+		}
+	}
+	else
+	{
+		if(d)
+		{
+			d->PDef = MGL_SOLID_MASK;	d->angle = 0;
+			PW = d->PenWidth*sqrt(fabs(50*size));
+			if(PW<1)	PW=1;
+		}
+		if(oi==HighId)	PW *= 2;
+		const mreal pw = PW;
+
+		mreal dd = ss+pw+10/dpw;
+		long x1 = long(q.x-dd), y1 = long(q.y-dd);	// bounding box
+		long x2 = long(q.x+dd), y2 = long(q.y+dd);
+		x1=x1>d->x1?x1:d->x1;	x2=x2<d->x2?x2:d->x2;
+		y1=y1>d->y1?y1:d->y1;	y2=y2<d->y2?y2:d->y2;
+		if(x1>x2 || y1>y2)	return;
+		const float V=(pw-1)*(pw-1)/4,S=(1-pw)/2;
+
+		switch(type)
+		{
+		case 'P':
+			for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+			{
+				float dx=i-q.x, dy=j-q.y, v,u;
+				int sum=0;
+				u = fabs(dy)-ss;	v = (dx-ss)*(dx-ss)+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(dy)-ss;	v = (dx+ss)*(dx+ss)+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(dy)-ss;	v = dx*dx+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(dx)-ss;	v = (dy-ss)*(dy-ss)+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(dx)-ss;	v = (dy+ss)*(dy+ss)+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(dx)-ss;	v = dy*dy+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				sum = sum>255?255:sum;	cs[3] = ca*sum/255;
+				pnt_plot(i,j,q.z+1,cs,oi);
+			}
+			break;
+		case '+':
+			for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+			{
+				float dx=i-q.x, dy=j-q.y, v,u;
+				int sum=0;
+				u = fabs(dy)-ss;	v = dx*dx+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(dx)-ss;	v = dy*dy+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				sum = sum>255?255:sum;	cs[3] = ca*sum/255;
+				pnt_plot(i,j,q.z+1,cs,oi);
+			}
+			break;
+		case 'X':
+			for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+			{
+				float dx=i-q.x, dy=j-q.y, v,u;
+				int sum=0;
+				u = fabs(dy)-ss;	v = (dx-ss)*(dx-ss)+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(dy)-ss;	v = (dx+ss)*(dx+ss)+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(dx)-ss;	v = (dy-ss)*(dy-ss)+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(dx)-ss;	v = (dy+ss)*(dy+ss)+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+
+				u = fabs(dx+dy)-2*ss;	v = dx-dy;	v = v*v+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(dx-dy)-2*ss;	v = dx+dy;	v = v*v+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+
+				sum = sum>255?255:sum;	cs[3] = ca*sum/255;
+				pnt_plot(i,j,q.z+1,cs,oi);
+			}
+			break;
+		case 'x':
+			for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+			{
+				float dx=i-q.x, dy=j-q.y, v,u;
+				int sum=0;
+				u = fabs(dx+dy)-2*ss;	v = dx-dy;	v = v*v+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(dx-dy)-2*ss;	v = dx+dy;	v = v*v+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				sum = sum>255?255:sum;	cs[3] = ca*sum/255;
+				pnt_plot(i,j,q.z+1,cs,oi);
+			}
+			break;
+		case 'S':
+			for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+			{
+				float dx=i-q.x, dy=j-q.y, v,u;
+				u = fabs(dy)-ss;	if(u<0)	u=0;
+				v = fabs(dx)-ss;	if(v<0)	v=0;	v = u*u+v*v;
+				int sum = v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				cs[3] = ca*sum/255;
+				pnt_plot(i,j,q.z+1,cs,oi);
+			}
+			break;
+		case 's':
+			for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+			{
+				float dx=i-q.x, dy=j-q.y, v,u;
+				int sum=0;
+				u = fabs(dy)-ss;	v = (dx-ss)*(dx-ss)+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(dy)-ss;	v = (dx+ss)*(dx+ss)+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(dx)-ss;	v = (dy-ss)*(dy-ss)+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(dx)-ss;	v = (dy+ss)*(dy+ss)+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				sum = sum>255?255:sum;	cs[3] = ca*sum/255;
+				pnt_plot(i,j,q.z+1,cs,oi);
+			}
+			break;
+		case 'D':
+			for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+			{
+				float dx=i-q.x, dy=j-q.y, v,u;
+				u = fabs(dx-dy)-ss;	if(u<0)	u=0;
+				v = fabs(dx+dy)-ss;	if(v<0)	v=0;	v = u*u+v*v;
+				int sum = v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				cs[3] = ca*sum/255;
+				pnt_plot(i,j,q.z+1,cs,oi);
+			}
+			break;
+		case 'd':
+			for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+			{
+				float dx=i-q.x, dy=j-q.y, v,u;
+				int sum=0;
+				u = fabs(dx+dy)-ss;	v = (dx-dy-ss)*(dx-dy-ss)+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(dx+dy)-ss;	v = (dx-dy+ss)*(dx-dy+ss)+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(dx-dy)-ss;	v = (dx+dy-ss)*(dx+dy-ss)+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(dx-dy)-ss;	v = (dx+dy+ss)*(dx+dy+ss)+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				sum = sum>255?255:sum;	cs[3] = ca*sum/255;
+				pnt_plot(i,j,q.z+1,cs,oi);
+			}
+			break;
+		case 'Y':
+			for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+			{
+				float dx=i-q.x, dy=j-q.y, v,u;
+				int sum=0;
+				u = fabs(dy+ss/2)-ss/2;	v = dx*dx+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(0.87*dx+0.5*dy-ss/2)-ss/2;	v = (0.5*dx-0.87*dy)*(0.5*dx-0.87*dy)+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(-0.87*dx+0.5*dy-ss/2)-ss/2;	v = (0.5*dx+0.87*dy)*(0.5*dx+0.87*dy)+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				sum = sum>255?255:sum;	cs[3] = ca*sum/255;
+				pnt_plot(i,j,q.z+1,cs,oi);
+			}
+			break;
+		case '*':
+			for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+			{
+				float dx=i-q.x, dy=j-q.y, v,u;
+				int sum=0;
+				u = fabs(dy)-ss;	v = dx*dx+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(0.87*dx+0.5*dy)-ss;	v = (0.5*dx-0.87*dy)*(0.5*dx-0.87*dy)+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(-0.87*dx+0.5*dy)-ss;	v = (0.5*dx+0.87*dy)*(0.5*dx+0.87*dy)+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				sum = sum>255?255:sum;	cs[3] = ca*sum/255;
+				pnt_plot(i,j,q.z+1,cs,oi);
+			}
+			break;
+		case 'T':
+			for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+			{
+				float dx=i-q.x, dy=j-q.y, v,u;
+				u=dy/1.5+ss/3;	v=(dx+ss-u)/2;
+				if(u>0 && v>0 && u+v<ss)	cs[3]=ca;
+				else
+				{
+					int sum=0;
+					u = fabs(dx)-ss;	v = dy+ss/2;	v = v*v+(u<0?0:u*u);
+					sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+					u = fabs(0.55*dx+0.83*dy)-0.9*ss;	v = 0.83*dx-0.55*dy+0.55*ss;	v = v*v+(u<0?0:u*u);
+					sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+					u = fabs(0.55*dx-0.83*dy)-0.9*ss;	v = 0.83*dx+0.55*dy-0.55*ss;	v = v*v+(u<0?0:u*u);
+					sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+					sum = sum>255?255:sum;	cs[3] = ca*sum/255;
+				}
+				pnt_plot(i,j,q.z+1,cs,oi);
+			}
+			break;
+		case '^':
+			for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+			{
+				float dx=i-q.x, dy=j-q.y, v,u;
+				int sum=0;
+				u = fabs(dx)-ss;	v = dy+ss/2;	v = v*v+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(0.55*dx+0.83*dy)-0.9*ss;	v = 0.83*dx-0.55*dy+0.55*ss;	v = v*v+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(0.55*dx-0.83*dy)-0.9*ss;	v = 0.83*dx+0.55*dy-0.55*ss;	v = v*v+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				sum = sum>255?255:sum;	cs[3] = ca*sum/255;
+				pnt_plot(i,j,q.z+1,cs,oi);
+			}
+			break;
+		case 'V':
+			for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+			{
+				float dx=i-q.x, dy=j-q.y, v,u;
+				u=-dy/1.5+ss/3;	v=(dx+ss-u)/2;
+				if(u>0 && v>0 && u+v<ss)	cs[3]=ca;
+				else
+				{
+					int sum=0;
+					u = fabs(dx)-ss;	v = dy-ss/2;	v = v*v+(u<0?0:u*u);
+					sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+					u = fabs(0.55*dx+0.83*dy)-0.9*ss;	v = 0.83*dx-0.55*dy-0.55*ss;	v = v*v+(u<0?0:u*u);
+					sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+					u = fabs(0.55*dx-0.83*dy)-0.9*ss;	v = 0.83*dx+0.55*dy+0.55*ss;	v = v*v+(u<0?0:u*u);
+					sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+					sum = sum>255?255:sum;	cs[3] = ca*sum/255;
+				}
+				pnt_plot(i,j,q.z+1,cs,oi);
+			}
+			break;
+		case 'v':
+			for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+			{
+				float dx=i-q.x, dy=j-q.y, v,u;
+				int sum=0;
+				u = fabs(dx)-ss;	v = dy-ss/2;	v = v*v+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(0.55*dx+0.83*dy)-0.9*ss;	v = 0.83*dx-0.55*dy-0.55*ss;	v = v*v+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(0.55*dx-0.83*dy)-0.9*ss;	v = 0.83*dx+0.55*dy+0.55*ss;	v = v*v+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				sum = sum>255?255:sum;	cs[3] = ca*sum/255;
+				pnt_plot(i,j,q.z+1,cs,oi);
+			}
+			break;
+		case 'L':
+			for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+			{
+				float dx=i-q.x, dy=j-q.y, v,u;
+				u=-dx/1.5+ss/3;	v=(dy+ss-u)/2;
+				if(u>0 && v>0 && u+v<ss)	cs[3]=ca;
+				else
+				{
+					int sum=0;
+					u = fabs(dy)-ss;	v = dx-ss/2;	v = v*v+(u<0?0:u*u);
+					sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+					u = fabs(0.55*dy+0.83*dx)-0.9*ss;	v = 0.83*dy-0.55*dx-0.55*ss;	v = v*v+(u<0?0:u*u);
+					sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+					u = fabs(0.55*dy-0.83*dx)-0.9*ss;	v = 0.83*dy+0.55*dx+0.55*ss;	v = v*v+(u<0?0:u*u);
+					sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+					sum = sum>255?255:sum;	cs[3] = ca*sum/255;
+				}
+				pnt_plot(i,j,q.z+1,cs,oi);
+			}
+			break;
+		case '<':
+			for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+			{
+				float dx=i-q.x, dy=j-q.y, v,u;
+				int sum=0;
+				u = fabs(dy)-ss;	v = dx-ss/2;	v = v*v+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(0.55*dy+0.83*dx)-0.9*ss;	v = 0.83*dy-0.55*dx-0.55*ss;	v = v*v+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(0.55*dy-0.83*dx)-0.9*ss;	v = 0.83*dy+0.55*dx+0.55*ss;	v = v*v+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				sum = sum>255?255:sum;	cs[3] = ca*sum/255;
+				pnt_plot(i,j,q.z+1,cs,oi);
+			}
+			break;
+		case 'R':
+			for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+			{
+				float dx=i-q.x, dy=j-q.y, v,u;
+				u=dx/1.5+ss/3;	v=(dy+ss-u)/2;
+				if(u>0 && v>0 && u+v<ss)	cs[3]=ca;
+				else
+				{
+					int sum=0;
+					u = fabs(dy)-ss;	v = dx+ss/2;	v = v*v+(u<0?0:u*u);
+					sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+					u = fabs(0.55*dy+0.83*dx)-0.9*ss;	v = 0.83*dy-0.55*dx+0.55*ss;	v = v*v+(u<0?0:u*u);
+					sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+					u = fabs(0.55*dy-0.83*dx)-0.9*ss;	v = 0.83*dy+0.55*dx-0.55*ss;	v = v*v+(u<0?0:u*u);
+					sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+					sum = sum>255?255:sum;	cs[3] = ca*sum/255;
+				}
+				pnt_plot(i,j,q.z+1,cs,oi);
+			}
+			break;
+		case '>':
+			for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+			{
+				float dx=i-q.x, dy=j-q.y, v,u;
+				int sum=0;
+				u = fabs(dy)-ss;	v = dx+ss/2;	v = v*v+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(0.55*dy+0.83*dx)-0.9*ss;	v = 0.83*dy-0.55*dx+0.55*ss;	v = v*v+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				u = fabs(0.55*dy-0.83*dx)-0.9*ss;	v = 0.83*dy+0.55*dx-0.55*ss;	v = v*v+(u<0?0:u*u);
+				sum += v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				sum = sum>255?255:sum;	cs[3] = ca*sum/255;
+				pnt_plot(i,j,q.z+1,cs,oi);
+			}
+			break;
+		case 'O':
+			for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+			{
+				float dx=i-q.x, dy=j-q.y, v;
+				v = hypot(dx,dy)-ss;	v=v<0?0:v*v;
+				int sum = v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				cs[3] = ca*sum/255;
+				pnt_plot(i,j,q.z+1,cs,oi);
+			}
+			break;
+		case 'o':
+			for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+			{
+				float dx=i-q.x, dy=j-q.y, v;
+				v = hypot(dx,dy)-ss;	v=v*v;
+				int sum = v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				cs[3] = ca*sum/255;
+				pnt_plot(i,j,q.z+1,cs,oi);
+			}
+			break;
+		case 'C':
+			for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+			{
+				float dx=i-q.x, dy=j-q.y, v;
+				v = hypot(dx,dy)-ss;	v=v*v;
+				int sum = v<V ? 255 : mgl_sline(255,dpw*(sqrt(v)+S));
+				v = dx*dx+dy*dy;
+				sum += v<(2*pw-1)*(2*pw-1)/4 ? 255 : mgl_sline(255,dpw*(sqrt(v)+(1-2*pw)/2));
+				sum = sum>255?255:sum;	cs[3] = ca*sum/255;
+				pnt_plot(i,j,q.z+1,cs,oi);
+			}
+			break;
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+// scale direction for new view/zoom
+float mglCanvas::GetGlyphPhi(const mglPnt &q, float phi)
+{
+	float x,y,z,ll;
+	if(q.sub<0)
+	{	x = q.u;	y = q.v;	z = q.w;	}
+	else
+	{
+		x = Bp.b[0]*q.u + Bp.b[1]*q.v + Bp.b[2]*q.w;
+		y = Bp.b[3]*q.u + Bp.b[4]*q.v + Bp.b[5]*q.w;
+		z = Bp.b[6]*q.u + Bp.b[7]*q.v + Bp.b[8]*q.w;
+
+		float dv= get_persp(Bp.pf,q.z,Depth);
+		float c = get_pfact(Bp.pf,Depth);
+		x += (q.x-Width/2)*z*c*dv;
+		y += (q.y-Height/2)*z*c*dv;
+	}
+	ll = x*x+y*y;
+	if(ll < 1e-10)	return NAN;
+	if(ll==ll && phi<1e4)
+	{
+		phi = -atan2(y,x)*180/M_PI;
+//		if(fabs(phi)>90) 	phi+=180;	// NOTE this is 2nd part of rotation changes (see also text_plot())
+	}
+	else phi=0;
+	return phi;
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::glyph_draw(const mglPrim &P, mglDrawReg *d)
+{
+	float phi = GetGlyphPhi(Pnt[P.n2],P.w);
+	if(mgl_isnan(phi))	return;
+	if(d)	{	d->PDef = MGL_SOLID_MASK;	d->angle = 0;	d->PenWidth=(P.n3&4)?1.2:0.8;	}
+
+	mglPnt p=Pnt[P.n1];	p.a=1;
+	mreal fact = get_persp(Bp.pf,p.z,Depth);
+	mreal pf=p.sub<0?1:sqrt((Bp.b[0]*Bp.b[0]+Bp.b[1]*Bp.b[1]+Bp.b[3]*Bp.b[3]+Bp.b[4]*Bp.b[4])/2)*fact;
+	mreal size=P.s, f = P.p*pf*P.s;
+	p.u *= pf*size;	p.v *= pf*size;
+
+	const mglGlyph &g = Glf[P.n4];
+	if(P.n3&8)
+	{
+		if(!(P.n3&4))	glyph_line(phi,p,f,true, d);
+		glyph_line(phi,p,f,false, d);
+	}
+	else
+	{
+		if(!(P.n3&4))	glyph_fill(phi,p,f,g, d);
+		glyph_wire(phi,p,f,g, d);
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_addpnts(mreal x1,mreal y1,mreal x2,mreal y2, std::vector<mreal> *b)
+{
+// 	if(x1>x2)	{	mreal t=x1;	x1=x2;	x2=t;	t=y1;	y1=y2;	y2=t;	}
+	if(y1<y2)	for(int i=long(y1);i<=long(y2)+1;i++)
+	{
+ 		mreal d = (i-y1)/(y2-y1);
+ 		if(d>=0 && d<=1)	b[i].push_back(x1+d*(x2-x1));
+	}
+	else	for(int i=long(y2);i<=long(y1)+1;i++)
+	{
+// 		mreal xx1 = x1+(x2-x1)*(i-y1)/(y2-y1);
+// 		mreal xx2 = x1+(x2-x1)*(i+1-y1)/(y2-y1);
+// 		if(xx1>xx2)	{	mreal t=xx1;	xx1=xx2;	xx2=t;	}
+// 		if(xx1<x1)	xx1=x1;
+// 		if(xx2>x2)	xx2=x2;
+// 		if(i>y1 && i<y2)
+// 		{
+// 			b[i].push_back(xx1);
+// 			if(xx2>=xx1+1)	{	b[i].push_back(xx2);	b[i].push_back(xx2);	}
+// 		}
+ 		mreal d = (i-y1)/(y2-y1);
+ 		if(d>=0 && d<=1)	b[i].push_back(x1+d*(x2-x1));
+	}
+}
+void mglCanvas::glyph_fill(mreal phi, const mglPnt &pp, mreal f, const mglGlyph &g, const mglDrawReg *d)
+{
+	if(g.trig && g.nt>0)	// slow but look very nice :(
+	{
+		const mreal co=cos(phi*M_PI/180), si=sin(phi*M_PI/180);
+		mglPnt q0=pp, q1=pp, q2=pp;
+		q0.u=q0.v=q1.u=q1.v=q2.u=q2.v=NAN;
+		for(long ik=0;ik<g.nt;ik++)
+		{
+			long ii = 6*ik; mreal x, y;
+			x = pp.u+g.trig[ii]*f;	y = pp.v+g.trig[ii+1]*f;
+			q0.x = pp.x+(x*co+y*si)/2;	q0.y = pp.y+(y*co-x*si)/2;	ii+=2;
+			x = pp.u+g.trig[ii]*f;	y = pp.v+g.trig[ii+1]*f;
+			q1.x = pp.x+(x*co+y*si)/2;	q1.y = pp.y+(y*co-x*si)/2;	ii+=2;
+			x = pp.u+g.trig[ii]*f;	y = pp.v+g.trig[ii+1]*f;
+			q2.x = pp.x+(x*co+y*si)/2;	q2.y = pp.y+(y*co-x*si)/2;
+			trig_draw(q0,q1,q2,false,d);
+		}
+		return;
+	}
+	if(!g.line || g.nl<=0)	return;
+	const mreal co=cos(phi*M_PI/180), si=sin(phi*M_PI/180);
+
+	mreal x1 = 1e10, x2=-1e10, y1=1e10, y2=-1e10;
+	for(long i=0;i<g.nl;i++)	// find sizes of glyph
+	{
+		long ii=2*i;
+		if(g.line[ii]==0x3fff && g.line[ii+1]==0x3fff)	continue;
+		mreal x = pp.u + g.line[ii]*f, y = pp.v + g.line[ii+1]*f;
+		mreal xx = pp.x+(x*co+y*si)/2, yy = pp.y+(y*co-x*si)/2;
+		if(xx<x1)	x1=xx;
+		if(xx>x2)	x2=xx;
+		if(yy<y1)	y1=yy;
+		if(yy>y2)	y2=yy;
+	}
+	x1-=2;	x2+=2;	y1-=2;	y2+=2;
+	long w = long(x2-x1+1), h = long(y2-y1+1), il=0;
+	long x0=long(x1), y0=long(y1),i1=1,i2=w-2,j1=1,j2=h-2;
+	if(d)	// apply mglDrawReg
+	{
+		if(x0+i1<d->x1)	i1 = d->x1-x0;
+		if(x0+i2>d->x2)	i2 = d->x2-x0;
+		if(y0+j1<d->y1)	j1 = d->y1-y0;
+		if(y0+j2>d->y2)	j2 = d->y2-y0;
+	}
+	else
+	{
+		if(x0+i1<0)		i1 = -x0;
+		if(x0+i2>Width)	i2 = Width-x0;
+		if(y0+j1<0)		j1 = -y0;
+		if(y0+j2>Height)j2 = Height-y0;
+	}
+	if(i1>=i2 || j1>=j2)	return;
+
+	std::vector<mreal> *b = new std::vector<mreal>[h];
+	const float dz = Width>2 ? 1 : 1e-5*Width;		// provide additional height to be well visible on the surfaces
+	const int oi = d?d->ObjId:-1;
+	unsigned char r[4];	col2int(pp,r,oi);
+	for(long i=0;i<g.nl;i++)	// add bounding points
+	{
+		long ii=2*i;
+		mreal x = pp.u + g.line[ii]*f, y = pp.v + g.line[ii+1]*f;
+		mreal xx1 = pp.x+(x*co+y*si)/2-x1, yy1 = pp.y+(y*co-x*si)/2-y1, xx2, yy2;
+		if(g.line[ii]==0x3fff && g.line[ii+1]==0x3fff)	// line breakthrough
+		{	il = i+1;	continue;	}
+		else if(i==g.nl-1 || (g.line[ii+2]==0x3fff && g.line[ii+3]==0x3fff))	// enclose the circle
+		{
+			ii=2*il;	x = pp.u + g.line[ii]*f;	y = pp.v + g.line[ii+1]*f;
+			xx2 = pp.x+(x*co+y*si)/2-x1;	yy2 = pp.y+(y*co-x*si)/2-y1;
+		}
+		else	// ordinary line
+		{
+			ii+=2;	x = pp.u + g.line[ii]*f;	y = pp.v + g.line[ii+1]*f;
+			xx2 = pp.x+(x*co+y*si)/2-x1;	yy2 = pp.y+(y*co-x*si)/2-y1;
+		}
+		mgl_addpnts(xx1,yy1,xx2,yy2,b);
+		// draw boundary lines in any case ???
+		if(fabs(xx2-xx1)>fabs(yy2-yy1))	// horizontal line
+		{
+			mreal d = (yy2-yy1)/(xx2-xx1), a = yy1-d*xx1+0.5;
+			if(xx1>xx2)	{	mreal t=xx1;	xx1=xx2;	xx2=t;	}
+			for(long k=xx1;k<=xx2;k++)
+			{
+				long ii = long(k), jj = long(a+d*k);
+				if(ii>=i1 && ii<=i2 && jj>=j1 && jj<=j2)	pnt_plot(x0+ii,y0+jj,pp.z+dz,r,oi);
+			}
+		}
+		else	// vertical line
+		{
+			mreal d = (xx2-xx1)/(yy2-yy1), a = xx1-d*yy1+0.5;
+			if(yy1>yy2)	{	mreal t=yy1;	yy1=yy2;	yy2=t;	}
+			for(long k=yy1;k<=yy2;k++)
+			{
+				long jj = long(k), ii = long(a+d*k);
+				if(ii>=i1 && ii<=i2 && jj>=j1 && jj<=j2)	pnt_plot(x0+ii,y0+jj,pp.z+dz,r,oi);
+			}
+		}
+	}
+	// TODO add smoothing -- if 3 neighbors >0 => set 1; if 3 neighbors=0 => set 0 ???
+	for(long j=j1;j<=j2;j++)	// draw glyph
+	{
+		if(b[j].size()<2)	continue;
+		std::sort(b[j].begin(),b[j].end());
+		for(size_t k=0;k<b[j].size();k+=2)
+		{
+			long ii1 = long(b[j][k]+0.5), ii2=long(b[j][k+1]+0.5);
+//			if(ii1==ii2 && b[j].size()%2==1)	{	k++;	ii2=long(b[j][k+1]+0.5);	}
+			if(ii1<i1)	ii1=i1;
+			if(ii2>i2)	ii2=i2;
+			for(long i=ii1;i<=ii2;i++)	pnt_plot(x0+i,y0+j,pp.z+dz,r,oi);
+		}
+	}
+	delete []b;
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::glyph_wire(mreal phi, const mglPnt &pp, mreal f, const mglGlyph &g, const mglDrawReg *d)
+{
+	if(!g.line || g.nl<=0)	return;
+	long il=0;
+	const mreal co=cos(phi*M_PI/180), si=sin(phi*M_PI/180);
+	mglPnt q0=pp, q1=pp;	q0.u=q0.v=q1.u=q1.v=NAN;
+	mglPoint p1,p2;
+	for(long ik=0;ik<g.nl;ik++)
+	{
+		long ii = 2*ik;
+		if(g.line[ii]==0x3fff && g.line[ii+1]==0x3fff)	// line breakthrough
+		{	il = ik+1;	continue;	}
+		else if(ik==g.nl-1 || (g.line[ii+2]==0x3fff && g.line[ii+3]==0x3fff))
+		{	// enclose the circle
+			mreal x,y;
+			x = pp.u+g.line[ii]*f;	y = pp.v+g.line[ii+1]*f;
+			q0.x = pp.x+(x*co+y*si)/2;	q0.y = pp.y+(y*co-x*si)/2;	ii=2*il;
+			x = pp.u+g.line[ii]*f;	y = pp.v+g.line[ii+1]*f;
+			q1.x = pp.x+(x*co+y*si)/2;	q1.y = pp.y+(y*co-x*si)/2;
+			line_draw(q0,q1,d);
+		}
+		else
+		{	// normal line
+			mreal x,y;
+			x = pp.u+g.line[ii]*f;	y = pp.v+g.line[ii+1]*f;
+			q0.x = pp.x+(x*co+y*si)/2;	q0.y = pp.y+(y*co-x*si)/2;	ii+=2;
+			x = pp.u+g.line[ii]*f;	y = pp.v+g.line[ii+1]*f;
+			q1.x = pp.x+(x*co+y*si)/2;	q1.y = pp.y+(y*co-x*si)/2;
+			line_draw(q0,q1,d);
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::glyph_line(mreal phi, const mglPnt &pp, mreal f, bool solid, const mglDrawReg *d)
+{
+	const mreal co=cos(phi*M_PI/180), si=sin(phi*M_PI/180);
+	mglPnt q0=pp,q1=pp,q2=pp,q3=pp;
+	q0.u=q0.v=q1.u=q1.v=q2.u=q2.v=q3.u=q3.v=NAN;
+
+	mreal dy = 0.004,x,y;
+	x=pp.u;		y=pp.v-dy;	q0.x=pp.x+(x*co+y*si)/2;	q0.y=pp.y+(y*co-x*si)/2;
+	x=pp.u+f;	y=pp.v-dy;	q1.x=pp.x+(x*co+y*si)/2;	q1.y=pp.y+(y*co-x*si)/2;
+	x=pp.u;		y=pp.v+dy;	q2.x=pp.x+(x*co+y*si)/2;	q2.y=pp.y+(y*co-x*si)/2;
+	x=pp.u+f;	y=pp.v+dy;	q3.x=pp.x+(x*co+y*si)/2;	q3.y=pp.y+(y*co-x*si)/2;
+
+	if(solid)	quad_draw(q0,q1,q3,q2,d);
+	else
+	{
+		line_draw(q0,q1,d);	line_draw(q2,q1,d);
+		line_draw(q0,q3,d);	line_draw(q2,q3,d);
+	}
+}
+//-----------------------------------------------------------------------------
+long mglCanvas::setPp(mglPnt &q, const mglPoint &p)
+{
+	q.xx=q.x=p.x;	q.yy=q.y=p.y;	q.zz=q.z=p.z;
+	long k;
+#pragma omp critical(pnt)
+	{k=Pnt.size();	MGL_PUSH(Pnt,q,mutexPnt);}
+	return k;
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::arrow_draw(long n1, long n2, char st, float ll)
+{
+	const mglPnt &p1=Pnt[n1], &p2=Pnt[n2];
+	mglPnt q=p1; 	//q.u=q.v=q.w=0;
+
+	mglPoint kl(p1.x-p2.x,p1.y-p2.y,p1.z-p2.z), kt, p0(p1.x,p1.y,p1.z), p;
+	mreal d = hypot(kl.x,kl.y);
+	if(d==0)	return;
+	kl /= d;	kt = !kl;
+	kl *= ll;	kt *= ll;
+
+	Reserve(8);
+	long k1,k2,k3,k4;
+
+	switch(st)	// S,D -- cube, T -- sq.pyramid, I -- square, O -- sphere???, A,K,V -- cone???
+	{
+		case 'I':
+			k1=setPp(q,p0+kt);	k2=setPp(q,p0-kt);	line_plot(k1,k2);	break;
+		case 'D':
+			k1=setPp(q,p0+kl);	k2=setPp(q,p0-kl);	k3=setPp(q,p0+kt);	k4=setPp(q,p0-kt);
+			trig_plot(k1,k2,k3);	trig_plot(k1,k2,k4);	break;
+		case 'S':
+			k1=setPp(q,p0+kl+kt);	k2=setPp(q,p0+kl-kt);
+			k3=setPp(q,p0-kl-kt);	k4=setPp(q,p0-kl+kt);
+			quad_plot(k1,k2,k4,k3);	break;
+		case 'X':
+			k1=setPp(q,p0+kl+kt);	k2=setPp(q,p0+kl-kt);
+			k3=setPp(q,p0-kl-kt);	k4=setPp(q,p0-kl+kt);
+			line_plot(k1,k3);	line_plot(k2,k4);	break;
+		case 'T':
+			k1=setPp(q,p0-kl+kt);	k2=setPp(q,p0-kl-kt);	k3=setPp(q,p0+kl);
+			trig_plot(k1,k2,k3);	break;
+		case 'K':
+			k1=setPp(q,p0+kt);	k2=setPp(q,p0-kt);	line_plot(k1,k2);
+		case 'A':
+			k1=setPp(q,p0-2.*kl+kt);	k2=setPp(q,p0-2.*kl-kt);	k3=setPp(q,p0-1.5*kl);
+			trig_plot(n1,k3,k1);	trig_plot(n1,k3,k2);	break;
+		case 'V':
+			k1=setPp(q,p0+2.*kl+kt);	k2=setPp(q,p0+2.*kl-kt);	k3=setPp(q,p0+1.5*kl);
+			trig_plot(n1,k3,k1);	trig_plot(n1,k3,k2);	break;
+		case 'O':	// let draw icosahedron
+		{
+			const int n = 12;	k1=setPp(q,p0+kl);
+			for(int i=1;i<=n;i++)
+			{
+				mreal u = 2*i*M_PI/n;
+				k2 = k1;	k1 = setPp(q,p0+kl*cos(u)+kt*sin(u));
+				trig_plot(n1,k1,k2);
+			}
+			break;
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::arrow_plot_3d(long n1, long n2, char st, float ll)
+{
+	const mglPnt &p1=Pnt[n1], &p2=Pnt[n2];
+	mglPnt q=p1; 	//q.u=q.v=q.w=0;
+
+	mglPoint kl(p1.x-p2.x,p1.y-p2.y,p1.z-p2.z), kt, kz, p0(p1.x,p1.y,p1.z), p;
+	if(kl.norm()==0)	return;
+	kl.Normalize();	kt = !kl;	kz = kl^kt;
+	kl *= ll;	kt *= ll;	kz *= ll;
+
+	Reserve(8);
+	long k1,k2,k3,k4,k5, k6,k7,k8;
+
+	switch(st)	// S,D -- cube, T -- sq.pyramid, I -- square, O -- sphere???, A,K,V -- cone???
+	{
+		case 'I':
+			k1=setPp(q,p0+kt);	k2=setPp(q,p0+kz);
+			k3=setPp(q,p0-kt);	k4=setPp(q,p0-kz);
+			quad_plot(k1,k2,k4,k3);	break;
+		case 'D':
+			k1=setPp(q,p0+kl);	k2=setPp(q,p0-kl);	k5=k3=setPp(q,p0+kt);
+			k4=setPp(q,p0+kz);	trig_plot(k1,k3,k4);	trig_plot(k2,k3,k4);	k3=k4;
+			k4=setPp(q,p0-kt);	trig_plot(k1,k3,k4);	trig_plot(k2,k3,k4);	k3=k4;
+			k4=setPp(q,p0-kz);	trig_plot(k1,k3,k4);	trig_plot(k2,k3,k4);	k3=k4;
+			trig_plot(k1,k3,k5);	trig_plot(k2,k3,k5);	break;
+		case 'S':
+			k1=setPp(q,p0+kl+kt);	k2=setPp(q,p0+kl+kz);	k3=setPp(q,p0+kl-kt);	k4=setPp(q,p0+kl-kz);
+			k5=setPp(q,p0-kl+kt);	k6=setPp(q,p0-kl+kz);	k7=setPp(q,p0-kl-kt);	k8=setPp(q,p0-kl-kz);
+			quad_plot(k1,k2,k4,k3);	quad_plot(k1,k2,k5,k6);	quad_plot(k3,k2,k7,k6);
+			quad_plot(k1,k4,k5,k8);	quad_plot(k3,k4,k7,k8);	quad_plot(k5,k6,k8,k7);	break;
+		case 'X':
+			k1=setPp(q,p0+kl+kt);	k2=setPp(q,p0+kl+kz);	k3=setPp(q,p0+kl-kt);	k4=setPp(q,p0+kl-kz);
+			k5=setPp(q,p0-kl+kt);	k6=setPp(q,p0-kl+kz);	k7=setPp(q,p0-kl-kt);	k8=setPp(q,p0-kl-kz);
+			line_plot(k1,k7);	line_plot(k2,k8);	line_plot(k3,k5);	line_plot(k4,k6);	break;
+		case 'T':
+			k1=setPp(q,p0-kl+kt);	k2=setPp(q,p0-kl+kz);	k3=setPp(q,p0-kl-kt);
+			k4=setPp(q,p0-kl-kz);	k5=setPp(q,p0+kl);
+			trig_plot(k1,k2,k5);	trig_plot(k2,k3,k5);
+			trig_plot(k3,k4,k5);	trig_plot(k1,k4,k5);	break;
+		case 'K':
+			k1=setPp(q,p0+kt);	k2=setPp(q,p0+kz);
+			k3=setPp(q,p0-kt);	k4=setPp(q,p0-kz);	quad_plot(k1,k2,k4,k3);
+		case 'A':
+			k1=setPp(q,p0-2.*kl+kt);	k2=setPp(q,p0-2.*kl+kz);	k3=setPp(q,p0-2.*kl-kt);
+			k4=setPp(q,p0-2.*kl-kz);	k5=setPp(q,p0-1.5*kl);
+			trig_plot(n1,k5,k1);	trig_plot(n1,k5,k2);
+			trig_plot(n1,k5,k3);	trig_plot(n1,k5,k4);	break;
+		case 'V':
+			k1=setPp(q,p0+2.*kl+kt);	k2=setPp(q,p0+2.*kl+kz);	k3=setPp(q,p0+2.*kl-kt);
+			k4=setPp(q,p0+2.*kl-kz);	k5=setPp(q,p0+1.5*kl);
+			trig_plot(n1,k5,k1);	trig_plot(n1,k5,k2);
+			trig_plot(n1,k5,k3);	trig_plot(n1,k5,k4);	break;
+		case 'O':	// let draw icosahedron
+		{
+			const int n = 12, m = n/2;	Reserve(n*m);
+			long *nn=new long[2*n], n1=setPp(q,p0+kl), n2=setPp(q,p0-kl);
+			mreal u,v,rr;
+			for(long i=0;i<m;i++)	for(long j=0;j<n;j++)
+			{
+				if(i>0 && i<m-1)
+				{
+					u = i*M_PI/(m-1.);	v = 2*M_PI*j/(n-1.)-1;	rr = sin(u);
+					nn[j+n]=nn[j];	nn[j]=setPp(q,p0+kl*cos(u)+kt*rr*cos(v)+kz*rr*sin(v));
+				}
+				else if(i==0)	nn[j] = n1;
+				else if(i==m-1)	{	nn[j+n]=nn[j];	nn[j]=n2;	}
+				if(i*j>0)	quad_plot(nn[j-1], nn[j], nn[j+n-1], nn[j+n]);
+			}
+			delete []nn;	break;
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+bool mglCanvas::quad_vis(const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, const mglPnt &p4) const
+{
+	unsigned char r[4];
+	long y1,x1,y2,x2;
+	mglPnt d1(p2-p1), d2(p3-p1), d3(p4+p1-p2-p3);
+
+	if(d1.x==0 && d1.y==0)	return trig_vis(p1,p3,p4);
+	if(d2.x==0 && d2.y==0)	return trig_vis(p1,p2,p4);
+
+	x1 = long(mgl_min(mgl_min(p1.x,p2.x), mgl_min(p3.x,p4.x)));	// bounding box
+	y1 = long(mgl_min(mgl_min(p1.y,p2.y), mgl_min(p3.y,p4.y)));
+	x2 = long(mgl_max(mgl_max(p1.x,p2.x), mgl_max(p3.x,p4.x)));
+	y2 = long(mgl_max(mgl_max(p1.y,p2.y), mgl_max(p3.y,p4.y)));
+	x1=mgl_max(x1,0);	x2=mgl_min(x2,Width);
+	y1=mgl_max(y1,0);	y2=mgl_min(y2,Height);
+//	if(x1>x2 || y1>y2)	return;
+
+	const float dd = d1.x*d2.y-d1.y*d2.x;
+	const float dsx =-4*(d2.y*d3.x - d2.x*d3.y)*d1.y;
+	const float dsy = 4*(d2.y*d3.x - d2.x*d3.y)*d1.x;
+
+	const float x0 = p1.x, y0 = p1.y;
+	bool vis = false;
+	for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+	{
+		float xx = (i-x0), yy = (j-y0), s;
+		s = dsx*xx + dsy*yy + (dd+d3.y*xx-d3.x*yy)*(dd+d3.y*xx-d3.x*yy);
+		if(s>=0)
+		{
+			s = sqrt(s);
+			float qu = d3.x*yy - d3.y*xx + dd + s;
+			float qv = d3.y*xx - d3.x*yy + dd + s;
+			float u = 2.f*(d2.y*xx - d2.x*yy)/qu;
+			float v = 2.f*(d1.x*yy - d1.y*xx)/qv;
+			if(u*(1.f-u)<0.f || v*(1.f-v)<0.f)	// first root bad
+			{
+				qu = d3.x*yy - d3.y*xx + dd - s;
+				qv = d3.y*xx - d3.x*yy + dd - s;
+//					u = v = -1.f;
+				u = 2.f*(d2.y*xx - d2.x*yy)/qu;	v = 2.f*(d1.x*yy - d1.y*xx)/qv;
+				if(u*(1.f-u)<0.f || v*(1.f-v)<0.f)	continue;	// second root bad
+			}
+			float zz = p1.z+d1.z*u+d2.z*v+d3.z*(u*v);
+			if(zz>=Z[3*(i+Width*(Height-1-j))]-2)	vis=true;
+		}
+	}
+	return vis;
+}
+//-----------------------------------------------------------------------------
+bool mglCanvas::trig_vis(const mglPnt &p1, const mglPnt &p2, const mglPnt &p3) const
+{
+	unsigned char r[4];
+	long y1,x1,y2,x2;
+	const mglPnt d1(p2-p1), d2(p3-p1);
+
+	const float tmp = d2.x*d1.y - d1.x*d2.y;
+	if(fabs(tmp)<1e-5)	return false;		// points lies on the same line
+	const float dyv =-d1.x/tmp,	dxv = d1.y/tmp;
+	const float dyu = d2.x/tmp,	dxu =-d2.y/tmp;
+
+	x1 = long(mgl_min(p1.x<p2.x?p1.x:p2.x, p3.x));	// bounding box
+	y1 = long(mgl_min(p1.y<p2.y?p1.y:p2.y, p3.y));
+	x2 = long(mgl_max(p1.x>p2.x?p1.x:p2.x, p3.x));
+	y2 = long(mgl_max(p1.y>p2.y?p1.y:p2.y, p3.y));
+	x1=x1>0?x1:0;	x2=x2<Width?x2:Width;
+	y1=y1>0?y1:0;	y2=y2<Height?y2:Height;
+//	if(x1>x2 || y1>y2)	return;
+	// default normale
+	const float x0 = p1.x, y0 = p1.y;
+	bool vis=false;
+	// provide additional height to be well visible on the surfaces
+	for(long j=y1;j<=y2;j++)	for(long i=x1;i<=x2;i++)
+	{
+		float xx = (i-x0), yy = (j-y0);
+		float u = dxu*xx+dyu*yy, v = dxv*xx+dyv*yy;
+		if(u<0 || v<0 || u+v>1)	continue;
+		float zz = p1.z+d1.z*u+d2.z*v;
+		if(zz>=Z[3*(i+Width*(Height-1-j))]-2)	vis=true;
+	}
+	return vis;
+}
+//-----------------------------------------------------------------------------
diff --git a/src/pixel_gen.cpp b/src/pixel_gen.cpp
new file mode 100644
index 0000000..4adc49c
--- /dev/null
+++ b/src/pixel_gen.cpp
@@ -0,0 +1,573 @@
+/***************************************************************************
+ * pixel.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <algorithm>
+#include "mgl2/canvas.h"
+#include "mgl2/thread.h"
+#if MGL_HAVE_OMP
+#include <omp.h>
+#endif
+
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_canvas_thr(void *par)
+{	mglThreadG *t=(mglThreadG *)par;	(t->gr->*(t->f))(t->id, t->n, t->p);	return NULL;	}
+void mglStartThread(void (mglCanvas::*func)(long i, long n, const void *p), mglCanvas *gr, long n, const void *p=NULL)
+{
+	if(!func || !gr)	return;
+#if MGL_HAVE_PTHREAD
+	if(mglNumThr<1)	mgl_set_num_thr(0);
+	if(mglNumThr>1)
+	{
+		pthread_t *tmp=new pthread_t[mglNumThr];
+		mglThreadG *par=new mglThreadG[mglNumThr];
+		for(long i=0;i<mglNumThr;i++)	// put parameters into the structure
+		{	par[i].gr=gr;	par[i].f=func;	par[i].n=n;	par[i].p=p;	par[i].id=i;	}
+		for(long i=0;i<mglNumThr;i++)	pthread_create(tmp+i, 0, mgl_canvas_thr, par+i);
+		for(long i=0;i<mglNumThr;i++)	pthread_join(tmp[i], 0);
+		delete []tmp;	delete []par;
+	}
+	else
+#endif
+	{	mglNumThr = 1;	(gr->*func)(0,n,p);	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::SetSize(int w,int h,bool clf)
+{
+	if(w<=0 || h<=0)	{	SetWarn(mglWarnSize,"SetSize");	return;	}
+	if(Width==w && Height==h)
+	{
+		InPlot(0,1,0,1,false);
+		if(clf || (Quality&4))	Clf();
+		return;
+	}
+
+	const double dx = double(w)/Width;
+	const double dy = double(h)/Height;
+	const double dz = sqrt(double(w*h))/Depth;
+	Width = w;	Height = h;	Depth = long(sqrt(double(w*h)));
+	const long s = long(w)*long(h);
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_lock(&mutexClf);
+#elif MGL_HAVE_OMP
+	omp_set_lock((omp_lock_t*)lockClf);
+#endif
+	if(G)	{	delete []G;	delete []C;	delete []Z;	delete []G4;delete []GB;delete []OI;	G=0;	}
+	G = new unsigned char[s*3];
+	G4= new unsigned char[s*4];
+	GB= new unsigned char[s*4];
+	C = new unsigned char[s*12];
+	Z = new float[s*3];	// only 3 planes
+	OI= new int[s];
+#pragma omp parallel for
+	for(long i=0;i<s;i++)	memcpy(GB+4*i,BDef,4);
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_unlock(&mutexClf);
+#elif MGL_HAVE_OMP
+	omp_unset_lock((omp_lock_t*)lockClf);
+#endif
+
+	InPlot(0,1,0,1,false);
+	if(clf || (Quality&4))	Clf();
+	else	// No clearing. So, need to scale
+	{
+#if MGL_HAVE_PTHREAD
+		pthread_mutex_lock(&mutexPnt);
+		pthread_mutex_lock(&mutexClf);
+#elif MGL_HAVE_OMP
+		omp_set_lock((omp_lock_t*)lockClf);
+#endif
+		const long m = long(Prm.size());
+		double dd = dx>dy?dy:dx;
+#pragma omp parallel for	// Scale text
+		for(long i=0;i<m;i++)	if(Prm[i].type==4)
+		{
+			mglPnt &q = Pnt[Prm[i].n1];
+			Prm[i].p *=dd;
+			q.u *= dd;	q.v *= dd;
+		}
+		const long n = long(Pnt.size());
+#pragma omp parallel for	// Scale coordinates
+		for(long i=0;i<n;i++)
+		{
+			mglPnt &q = Pnt[i];
+			q.x*=dx;	q.y*=dy;	q.z*=dz;
+			q.xx*=dx;	q.yy*=dy;	q.zz*=dz;
+			if(mgl_isnum(q.w))
+			{	q.u*=dx;	q.v*=dy;	q.w*=dz;	}
+		}
+		for(size_t i=0;i<Sub.size();i++)
+		{	mglBlock &q = Sub[i];	q.n1*=dx;	q.n2*=dx;	q.n3*=dy;	q.n4*=dy;	}
+		for(size_t k=0;k<DrwDat.size();k++)	// scale frames too
+		{
+			mglStack<mglPnt>  &pnt = DrwDat[k].Pnt;
+			const long n = long(pnt.size());
+#pragma omp parallel for
+			for(long i=0;i<n;i++)
+			{
+				mglPnt &q = pnt[i];
+				q.x*=dx;	q.y*=dy;	q.z*=dz;
+				q.xx*=dx;	q.yy*=dy;	q.zz*=dz;
+				if(mgl_isnum(q.w))
+				{	q.u*=dx;	q.v*=dy;	q.w*=dz;	}
+			}
+			std::vector<mglBlock>  &sub = DrwDat[k].Sub;
+			for(size_t i=0;i<sub.size();i++)
+			{	mglBlock &q = sub[i];	q.n1*=dx;	q.n2*=dx;	q.n3*=dy;	q.n4*=dy;	}
+		}
+#if MGL_HAVE_PTHREAD
+		pthread_mutex_unlock(&mutexClf);
+		pthread_mutex_unlock(&mutexPnt);
+#elif MGL_HAVE_OMP
+		omp_unset_lock((omp_lock_t*)lockClf);
+#endif
+		ClfZB();	Finish();
+	}
+}
+//-----------------------------------------------------------------------------
+void mglDrawReg::set(mglCanvas *gr, int nx, int ny, int m)
+{
+	int mx = m%nx, my = m/nx;	ObjId = gr->ObjId;
+	PDef = gr->mask;	angle = gr->MaskAn;
+	x1 = gr->GetWidth()*mx/nx;		y1 = gr->GetHeight()-gr->GetHeight()*(my+1)/ny;
+	x2 = gr->GetWidth()*(mx+1)/nx-1;	y2 = gr->GetHeight()-gr->GetHeight()*my/ny-1;
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::PutDrawReg(mglDrawReg *d, const mglCanvas *gr)
+{
+	if(gr)
+	{
+		const int dd = d->x2 - d->x1;
+		for(long j=d->y1;j<d->y2;j++)
+		{
+			long i = d->x1+Width*(Height-1-j);
+			memcpy(OI+i,gr->OI+i,dd*sizeof(int));
+			memcpy(Z+3*i,gr->Z+3*i,3*dd*sizeof(float));
+			memcpy(C+12*i,gr->C+12*i,12*dd);
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::PostScale(const mglMatrix *M, mglPoint &p) const
+{
+	mreal f = 1./(2*M->pf),x=p.x,y=p.y,z=p.z;
+	const mreal *b=M->b;
+	p.x = M->x + f*(x*b[0] + y*b[1] + z*b[2]);
+	p.y = M->y + f*(x*b[3] + y*b[4] + z*b[5]);
+	p.z = M->z + f*(x*b[6] + y*b[7] + z*b[8]);
+}
+//-----------------------------------------------------------------------------
+bool mglCanvas::ScalePoint(const mglMatrix *M, mglPoint &p, mglPoint &n, bool use_nan) const
+{
+	bool res = get(MGL_DISABLE_SCALE) || mglBase::ScalePoint(M,p,n,use_nan);
+	PostScale(M,p);
+
+	mreal nx=n.x, ny=n.y, nz=n.z;
+	const mreal *b=M->b;
+	n.x = nx*b[0] + ny*b[1] + nz*b[2];	// simpler for rotation only
+	n.y = nx*b[3] + ny*b[4] + nz*b[5];
+	n.z = nx*b[6] + ny*b[7] + nz*b[8];
+	n.Normalize();
+	return res;
+}
+//-----------------------------------------------------------------------------
+long mglCanvas::ProjScale(int nf, long id, bool text)
+{
+	const mglPnt &pi = Pnt[id];
+	mglPoint pp(pi.x,pi.y,pi.z), nn(pi.u,pi.v,pi.w), p, n;
+	if(mgl_isnan(pp.x))	return -1;
+	const mreal w=B1.b[0]/2, h=B1.b[4]/2, d=B1.b[8]/2, xx=B1.x-w/2, yy=B1.y-h/2;
+	if(pi.sub>=0)
+	{
+		mglPoint q(RestorePnt(pp)/(2*B.pf));
+		mglPoint u(RestorePnt(nn,true));	u.Normalize();
+		if(nf==0)
+		{	p.x = xx + q.x*w;	p.y = yy + q.y*h;	p.z = B1.z + q.z*d;	n = u;	}
+		else if(nf==1)
+		{	p.x = xx + q.x*w;	p.y = yy+h + q.z*h;	p.z = B1.z - q.y*d;	n.Set(u.x,u.z,-u.y);	}
+		else if(nf==2)
+		{	p.x = xx+w + q.z*w;	p.y = yy + q.y*h;	p.z = B1.z - q.x*d;	n.Set(u.z,u.y,-u.x);	}
+		else
+		{
+			const mreal *b=B.b;	n = nn;
+			p.x = xx+w + q.x*b[0]/2 + q.y*b[1]/2 + q.z*b[2]/2;
+			p.y = yy+h + q.x*b[3]/2 + q.y*b[4]/2 + q.z*b[5]/2;
+			p.z = B.z + q.x*b[6]/2 + q.y*b[7]/2 + q.z*b[8]/2;
+		}
+	}
+	else
+	{
+		p.x = pi.x/2 + w*(nf/2);
+		p.y = pi.y/2 + h*(nf%2);
+		p.z = pi.z;	n=nn;
+	}
+	return CopyProj(id,p,text?n:nn,pi.sub);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::LightScale(const mglMatrix *M, mglLight &ls)
+{
+	ls.p=ls.d;	ls.q=ls.r;
+	ScalePoint(M,ls.q,ls.p,false);
+	ls.p /= ls.p.norm();
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::LightScale(const mglMatrix *M)
+{
+	for(long i=0;i<10;i++)	if(light[i].n)	LightScale(M,light[i]);
+	for(size_t j=0;j<Sub.size();j++)
+		for(long i=0;i<10;i++)	if(light[i].n)	LightScale(&(Sub[j].B),Sub[j].light[i]);
+}
+//-----------------------------------------------------------------------------
+// NOTE: Perspective is not fully supported now !!! Also it use LAST InPlot parameters!!!
+mglPoint mglCanvas::RestorePnt(mglPoint ps, bool norm) const
+{
+	const mreal s3 = 2*B.pf;
+	mglPoint p;
+
+	const mreal W=Width/2, H=Height/2, D=Depth/2;
+	const mreal *b=B.b,*d=Bp.b;
+	mreal cx = B.z*d[2]+B.y*d[1]+B.x*d[0]-Bp.x*W-d[0]*W+W-d[1]*H-d[2]*D;
+	const mreal c0 = b[6]*d[2]+b[3]*d[1]+b[0]*d[0];
+	const mreal c1 = b[7]*d[2]+b[4]*d[1]+b[1]*d[0];
+	const mreal c2 = b[8]*d[2]+b[5]*d[1]+b[2]*d[0];
+	mreal cy = B.z*d[5]+B.y*d[4]+B.x*d[3]-d[3]*W-Bp.y*H-d[4]*H+H-d[5]*D;
+	const mreal c3 = b[6]*d[5]+b[3]*d[4]+b[0]*d[3];
+	const mreal c4 = b[7]*d[5]+b[4]*d[4]+b[1]*d[3];
+	const mreal c5 = b[8]*d[5]+b[5]*d[4]+b[2]*d[3];
+	mreal cz = B.z*d[8]+B.y*d[7]+B.x*d[6]-d[6]*W-d[7]*H-Bp.z*D-d[8]*D+D;
+	const mreal c6 = b[6]*d[8]+b[3]*d[7]+b[0]*d[6];
+	const mreal c7 = b[7]*d[8]+b[4]*d[7]+b[1]*d[6];
+	const mreal c8 = b[8]*d[8]+b[5]*d[7]+b[2]*d[6];
+	if(norm)	cx=cy=cz=0;
+
+	if(mgl_isnum(ps.z))	// try to take into account perspective if z-value is provided
+	{
+		float dd = get_persp(Bp.pf,ps.z,Depth);
+		ps.x = Width/2 + (ps.x-Width/2)/dd;
+		ps.y = Height/2+ (ps.y-Height/2)/dd;
+	}
+	const mreal xx = ps.x-cx, yy = ps.y-cy, zz = ps.z-cz;
+	const mreal d1=c0*c4-c1*c3, d2=c1*c5-c2*c4, d3=c0*c5-c2*c3;
+
+	if(mgl_isnum(zz))	// try to use z-values
+	{
+		// put inverse matrix here: [x,y,z]=B^(-1)[xx,yy,zz]
+		mreal det = (-c0*c4*c8+c1*c3*c8+c0*c5*c7-c2*c3*c7-c1*c5*c6+c2*c4*c6)/s3;
+		p.x = (c2*c4-c1*c5)*zz+(c1*c8-c2*c7)*yy+(c5*c7-c4*c8)*xx;	p.x /= det;
+		p.y = (c0*c5-c2*c3)*zz+(c2*c6-c0*c8)*yy+(c3*c8-c5*c6)*xx;	p.y /= det;
+		p.z = (c1*c3-c0*c4)*zz+(c0*c7-c1*c6)*yy+(c4*c6-c3*c7)*xx;	p.z /= det;
+	}
+	else if(fabs(d1) > fabs(d2) && fabs(d1) > fabs(d3))	// x-y plane
+	{
+		p.z = 0;
+		p.x = s3*(c4*xx-c1*yy)/d1;
+		p.y = s3*(c0*yy-c3*xx)/d1;
+	}
+	else if(fabs(d2) > fabs(d3))	// y-z
+	{
+		p.x = 0;
+		p.y = s3*(c5*xx-c2*yy)/d2;
+		p.z = s3*(c1*yy-c4*xx)/d2;
+	}
+	else	// x-z
+	{
+		p.y = 0;
+		p.x = s3*(c5*xx-c2*yy)/d3;
+		p.z = s3*(c0*yy-c3*xx)/d3;
+	}
+	return p;
+}
+//-----------------------------------------------------------------------------
+mglPoint mglCanvas::CalcXYZ(int xs, int ys, bool real) const
+{
+	if(xs<0 || ys<0 || xs>=Width || ys>=Height)	return mglPoint(NAN,NAN,NAN);
+	mglPoint p, ps(xs,Height-ys,NAN);
+	float zz = Z[3*(xs+Width*(Height-1-ys))];
+	if(zz>-1e20f)	{	ps.z = zz;	real=false;	}
+	p = RestorePnt(ps);
+	return real ? mglPoint(NAN,NAN,NAN) : mglPoint(Min.x + (Max.x-Min.x)*(p.x+1)/2,
+				Min.y + (Max.y-Min.y)*(p.y+1)/2, Min.z + (Max.z-Min.z)*(p.z+1)/2);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::CalcScr(mglPoint p, int *xs, int *ys) const
+{
+	mglPoint n;
+	ScalePoint(GetB(),p,n);
+	if(xs)	*xs=int(p.x);
+	if(ys)	*ys=int(p.y);
+}
+//-----------------------------------------------------------------------------
+mglPoint mglCanvas::CalcScr(mglPoint p) const
+{	int x,y;	CalcScr(p,&x,&y);	return mglPoint(x,y);	}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_prm_swap(mglPrim &s1,mglPrim &s2,mglPrim *buf)
+{
+	memcpy(buf, &s1, sizeof(mglPrim));
+	memcpy(&s1, &s2, sizeof(mglPrim));
+	memcpy(&s2, buf, sizeof(mglPrim));
+}
+void MGL_NO_EXPORT sort_prm_c(const size_t l0, const size_t r0, mglStack<mglPrim> &s, mglPrim *buf)
+{
+	if(l0==r0)	return;
+	if(l0+1==r0)
+	{
+		if(s[r0].n1<s[l0].n1)	mgl_prm_swap(s[r0],s[l0],buf);
+		return;
+	}
+	bool del= (buf==0);
+	if(del)	buf = (mglPrim*)malloc(sizeof(mglPrim));
+
+	size_t l=l0, r=r0;
+	const long v = s[(l+r)/2].n1;
+
+	for(size_t i=l0;i<=r0;i++)	// first collect <0
+		if(s[i].n1<v)
+		{
+			if(i>l)	mgl_prm_swap(s[i],s[l],buf);
+			l++;
+		}
+	r=l;
+	for(size_t i=l;i<=r0;i++)	// now collect =0
+		if(s[i].n1==v)
+		{
+			if(i>r)	mgl_prm_swap(s[i],s[r],buf);
+			r++;
+		}
+
+	if(l>l0+1)	sort_prm_c(l0,l-1,s,buf);
+	if(r<r0)	sort_prm_c(r,r0,s,buf);
+	if(del)	free(buf);
+}
+//-----------------------------------------------------------------------------
+uint32_t mglCanvas::GetColor(const mglPrim &p) const
+{
+	mglRGBA res, c1,c2,c3,c4;
+	c1.c=pnt_col[p.type==1?p.n2:p.n1];
+	unsigned r=c1.r[0], g=c1.r[1], b=c1.r[2], a=c1.r[3];
+	switch(p.type)
+	{
+	case 3:
+		c2.c=pnt_col[p.n2];	c3.c=pnt_col[p.n3];	c4.c=pnt_col[p.n4];
+		res.r[0]=(r+c2.r[0]+c3.r[0]+c4.r[0])/4;
+		res.r[1]=(g+c2.r[1]+c3.r[1]+c4.r[1])/4;
+		res.r[2]=(b+c2.r[2]+c3.r[2]+c4.r[2])/4;
+		res.r[3]=(a+c2.r[3]+c3.r[3]+c4.r[3])/4;	break;
+	case 2:
+		c2.c=pnt_col[p.n2];	c3.c=pnt_col[p.n3];
+		res.r[0]=(r+c2.r[0]+c3.r[0])/3;
+		res.r[1]=(g+c2.r[1]+c3.r[1])/3;
+		res.r[2]=(b+c2.r[2]+c3.r[2])/3;
+		res.r[3]=(a+c2.r[3]+c3.r[3])/3;	break;
+	case 6:
+		res.r[0]=p.n2&0xff;	res.r[1]=(p.n2/256)&0xff;	res.r[2]=(p.n2/65536)&0xff;	res.r[3]=255;	break;
+//		res.c=p.n2;	break;
+	default:
+		res.c = c1.c;	break;
+	}
+	// add fog into resulting color
+	float zf = FogDist*(p.z/Depth-0.5-FogDz);
+	if(zf<0)	// add fog
+	{
+		unsigned char d = (unsigned char)(255*(1.-exp(5*zf)));
+		unsigned char cb[4] = {BDef[0], BDef[1], BDef[2], d};
+		if(d<255)	combine(res.r,cb);
+	}
+	return res.c;
+}
+//-----------------------------------------------------------------------------
+HMGL mgl_qsort_gr=0;
+MGL_NO_EXPORT int mgl_type_prior[8]={1,2,4,5, 0,3,0, 7};
+int mglBase::PrmCmp(size_t i, size_t j) const
+{
+	if(i>=Prm.size() || j>=Prm.size())
+		return 0;
+	const mglPrim &a = Prm[i];
+	const mglPrim &b = Prm[j];
+	if(a.z!=b.z) 	return int(100*(a.z - b.z));
+	int t1 = mgl_type_prior[a.type], t2 = mgl_type_prior[b.type];
+	if(t1!=t2)		return t2 - t1;
+	if(a.w!=b.w) 	return int(100*(b.w - a.w));
+	return a.n3 - b.n3;
+}
+int MGL_LOCAL_PURE mgl_prm_cmp(const void *i,const void *j)
+{
+	return mgl_qsort_gr->PrmCmp(*((const size_t *)i), *((const size_t *)j));
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::PreparePrim(int fast)
+{
+	if(fast!=2)
+	{
+		mglStartThread(&mglCanvas::pxl_transform,this,Pnt.size());
+		if(fast==0)	mglStartThread(&mglCanvas::pxl_setz,this,Prm.size());
+		else	mglStartThread(&mglCanvas::pxl_setz_adv,this,Prm.size());
+#pragma omp critical
+		{
+			ClearPrmInd();	mgl_qsort_gr = this;
+			size_t n = Prm.size();
+			PrmInd = new size_t[n];
+			for(size_t i=0;i<n;i++)	PrmInd[i]=i;
+			qsort(PrmInd,n,sizeof(size_t),mgl_prm_cmp);
+			clr(MGL_FINISHED);
+		}
+	}
+	if(fast>0)
+	{
+#pragma omp critical
+		{	if(pnt_col)	delete []pnt_col;	pnt_col = new uint32_t[Pnt.size()];	}
+		mglStartThread(&mglCanvas::pxl_pntcol,this,Pnt.size());
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Finish()
+{
+	static mglMatrix bp;
+	if(Quality==MGL_DRAW_NONE)	return;
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_lock(&mutexPrm);
+	pthread_mutex_lock(&mutexPnt);
+	pthread_mutex_lock(&mutexClf);
+#elif MGL_HAVE_OMP
+	omp_set_lock((omp_lock_t*)lockClf);
+#endif
+	size_t n=Width*Height;
+	if(Quality==MGL_DRAW_DOTS)
+	{
+		mglStartThread(&mglCanvas::pxl_dotsdr,this,Pnt.size());
+		mglStartThread(&mglCanvas::pxl_memcpy,this,n);
+	}
+	else
+	{
+		if((Quality&MGL_DRAW_LMEM) || (memcmp(&Bp,&bp,sizeof(mglMatrix)) && !(Quality&MGL_DRAW_LMEM) && Prm.size()>0))
+			clr(MGL_FINISHED);
+		if(!get(MGL_FINISHED))
+		{
+			if(!(Quality&MGL_DRAW_LMEM) && Prm.size()>0)
+			{
+				PreparePrim(0);	bp=Bp;
+				clr(MGL_FINISHED);
+				mglStartThread(&mglCanvas::pxl_primdr,this,Prm.size());
+			}
+			BDef[3] = (Flag&3)!=2 ? 0:255;
+			if(Quality&MGL_DRAW_NORM)	mglStartThread(&mglCanvas::pxl_combine,this,n);
+			else 			mglStartThread(&mglCanvas::pxl_memcpy,this,n);
+			BDef[3] = 255;
+		}
+	}
+	int x2 = BBoxX2<0?Width:BBoxX2, y2 = BBoxY2<0?Height:BBoxY2;
+	if(BBoxX1>=0 && BBoxX1<x2 && BBoxY1>=0 && BBoxY1<y2)
+	{
+		unsigned char ff[8]={255,255,255,255, 0,0,0,255}, *g1 = G4+BBoxX1*4-4;
+		int ww = 8*Width;
+		if(BBoxX1>0)	for(long i=0;i<Height/2-1;i++)
+			memcpy(g1+ww*i,ff,8);
+		g1 = G4+x2*4;
+		if(x2<Width)	for(long i=0;i<Height/2-1;i++)
+			memcpy(g1+ww*i,ff,8);
+		g1 = G4+(BBoxY1-1)*4*Width;
+		if(BBoxY1>0)	for(long i=0;i<Width/2-1;i++)
+			memcpy(g1+8*i,ff,8);
+		g1 = G4+y2*4*Width;
+		if(y2<Height)	for(long i=0;i<Width/2-1;i++)
+			memcpy(g1+8*i,ff,8);
+	}
+	mglStartThread(&mglCanvas::pxl_backgr,this,n);
+	if(Quality!=MGL_DRAW_DOTS)	set(MGL_FINISHED);
+
+#if MGL_HAVE_PTHREAD
+	pthread_mutex_unlock(&mutexClf);
+	pthread_mutex_unlock(&mutexPnt);
+	pthread_mutex_unlock(&mutexPrm);
+#elif MGL_HAVE_OMP
+	omp_unset_lock((omp_lock_t*)lockClf);
+#endif
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::ClfZB(bool force)
+{
+	if(!force && (Quality&MGL_DRAW_LMEM))	return;
+	long n=Width*Height;
+	memset(C,0,12*n);	memset(OI,0,n*sizeof(int));
+#pragma omp parallel for
+	for(long i=0;i<3*n;i++)	Z[i] = -1e20f;
+	clr(MGL_FINISHED);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Clf(mglColor Back)
+{
+	Fog(0);	PDef = 0xffff;	pPos = 0;
+	ClearFrame();
+	if((Flag&3)==2)	Back.Set(0,0,0,0);
+	if(Back!=NC)	FillBackground(Back);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Clf(const char *col)
+{
+	Fog(0);	PDef = 0xffff;	pPos = 0;
+	ClearFrame();
+	mglTexture txt(col,0,0);
+	FillBackground(txt.col[1]);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Rasterize()
+{
+	Finish();
+	memcpy(GB,G4,4*Width*Height);
+}
+//-----------------------------------------------------------------------------
+bool MGL_NO_EXPORT mgl_read_image(unsigned char **g, int &w, int &h, const char *fname);
+void mglCanvas::LoadBackground(const char *fname, double alpha)
+{
+	mgl_read_image(&GB,Width,Height,fname);
+	if(alpha<1 && alpha>0)
+#pragma omp parallel for
+		for(long i=0;i<Width*Height;i++)	GB[4*i+3] = (unsigned char)(GB[4*i+3]*alpha);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::FillBackground(const mglColor &cc)
+{
+	BDef[0] = (unsigned char)(255*cc.r);	BDef[1] = (unsigned char)(255*cc.g);
+	BDef[2] = (unsigned char)(255*cc.b);	BDef[3] = (unsigned char)(255*cc.a);
+#pragma omp parallel for
+	for(long i=0;i<Width*Height;i++)	memcpy(GB+4*i,BDef,4);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::Combine(const mglCanvas *gr)
+{
+	if(Width!=gr->Width || Height!=gr->Height || !gr)	return;	// wrong sizes
+	mglStartThread(&mglCanvas::pxl_other,this,Width*Height,gr);
+}
+//-----------------------------------------------------------------------------
+unsigned char **mglCanvas::GetRGBLines(long &w, long &h, unsigned char *&f, bool alpha)
+{
+	unsigned char **p;
+	Finish();
+	long c = alpha?4:3, d = c*Width;
+	unsigned char *gg = (alpha?G4:G);
+	int x2 = BBoxX2<0?Width:BBoxX2, y2 = BBoxY2<0?Height:BBoxY2;
+	if(BBoxX1>=0 && BBoxX1<x2 && BBoxY1>=0 && BBoxY1<y2)
+	{
+		gg += c*BBoxX1 + d*BBoxY1;
+		w = x2-BBoxX1;	h = y2-BBoxY1;
+	}
+	else	{	w = Width;	h = Height;	}
+	p = (unsigned char **)malloc(h * sizeof(unsigned char *));
+	for(long j=0;j<h;j++)	p[j] = gg + d*j;
+	f = 0;	return p;
+}
+//-----------------------------------------------------------------------------
diff --git a/src/pixel_pix.cpp b/src/pixel_pix.cpp
new file mode 100644
index 0000000..ce08f55
--- /dev/null
+++ b/src/pixel_pix.cpp
@@ -0,0 +1,398 @@
+/***************************************************************************
+ * pixel_bit.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <algorithm>
+#include "mgl2/canvas.h"
+#include "mgl2/thread.h"
+#if MGL_HAVE_OMP
+#include <omp.h>
+#endif
+
+//-----------------------------------------------------------------------------
+void mglCanvas::pxl_primpx(long id, long n, const void *)	// NOTE this variant is too slow ... may be later in CUDA???
+{
+	mglDrawReg d;	d.set(this,1,1,id);
+#if !MGL_HAVE_PTHREAD
+#pragma omp parallel for firstprivate(d)
+#endif
+	for(long ii=0;ii<n;ii+=mglNumThr)
+	{
+		long i=ii%Width, j=ii/Width;
+		for(size_t k=0;k<Prm.size();k++)
+		{
+			if(Stop)	break;
+			const mglPrim &p=GetPrm(k);
+			d.PDef = p.n3;	d.pPos = p.s;
+			d.ObjId = p.id;	d.PenWidth=p.w;
+			d.angle = p.angl;
+			if(p.type==2 || p.type==3) d.PDef = p.m;
+			switch(p.type)
+			{
+			case 0:	mark_pix(i,j,Pnt[p.n1],p.n4,p.s,&d);	break;
+			case 1:	line_pix(i,j,Pnt[p.n1],Pnt[p.n2],&d);	break;
+			case 2:	trig_pix(i,j,Pnt[p.n1],Pnt[p.n2],Pnt[p.n3],true,&d);	break;
+			case 3:	quad_pix(i,j,Pnt[p.n1],Pnt[p.n2],Pnt[p.n3],Pnt[p.n4],&d);	break;
+			case 4:	glyph_pix(i,j,p,&d);	break;
+			}
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::quad_pix(long i, long j, const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, const mglPnt &p4, const mglDrawReg *d)
+{
+	if(!visible(i,j,d->m, d->PenWidth,d->angle))	return;
+	mglPnt d1(p2-p1), d2(p3-p1), d3(p4+p1-p2-p3);
+	float dd = d1.x*d2.y-d1.y*d2.x;
+	float dsx =-4*(d2.y*d3.x - d2.x*d3.y)*d1.y;
+	float dsy = 4*(d2.y*d3.x - d2.x*d3.y)*d1.x;
+	float xx = (i-p1.x), yy = (j-p1.y), s;
+	s = dsx*xx + dsy*yy + (dd+d3.y*xx-d3.x*yy)*(dd+d3.y*xx-d3.x*yy);
+	if(s<0)	return;	// no solution
+	s = sqrt(s);
+	float qu = d3.x*yy - d3.y*xx + dd + s, u=-1;
+	float qv = d3.y*xx - d3.x*yy + dd + s, v=-1;
+	if(qu && qv)
+	{
+		u = 2.f*(d2.y*xx - d2.x*yy)/qu;
+		v = 2.f*(d1.x*yy - d1.y*xx)/qv;
+	}
+	if(u*(1.f-u)<0.f || v*(1.f-v)<0.f)	// first root bad
+	{
+		qu = d3.x*yy - d3.y*xx + dd - s;
+		qv = d3.y*xx - d3.x*yy + dd - s;
+		u = v = -1.f;
+		if(qu && qv)
+		{
+			u = 2.f*(d2.y*xx - d2.x*yy)/qu;
+			v = 2.f*(d1.x*yy - d1.y*xx)/qv;
+		}
+		if(u*(1.f-u)<0.f || v*(1.f-v)<0.f)	return;	// second root bad
+	}
+	mglPnt p(p1+d1*u+d2*v+d3*(u*v));
+	if(mgl_isnan(p.u) && mgl_isnum(p.v))
+	{
+		mglPoint n1(mglPoint(p2.x-p1.x,p2.y-p1.y,p2.z-p1.z)^mglPoint(p3.x-p1.x,p3.y-p1.y,p3.z-p1.z));
+		mglPoint n2(mglPoint(p2.x-p4.x,p2.y-p4.y,p2.z-p4.z)^mglPoint(p3.x-p4.x,p3.y-p4.y,p3.z-p4.z));
+		p.u = (n1.x+n2.x)*0.5;
+		p.v = (n1.y+n2.y)*0.5;
+		p.w = (n1.z+n2.z)*0.5;
+	}
+	unsigned char r[4];
+	pnt_plot(i,j,p.z,col2int(p,r,d->ObjId),d->ObjId);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::trig_pix(long i, long j, const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, bool anorm, const mglDrawReg *d)
+{
+	if(!visible(i,j,d->m, d->PenWidth,d->angle))	return;
+	mglPnt d1(p2-p1), d2(p3-p1);
+	float dd = d2.x*d1.y - d1.x*d2.y;
+	if(fabs(dd)<1e-5)	return;		// points lies on the same line
+	float dyv =-d1.x/dd, dxv = d1.y/dd, dyu = d2.x/dd, dxu =-d2.y/dd;
+	float xx = (i-p1.x), yy = (j-p1.y);
+	float u = dxu*xx+dyu*yy, v = dxv*xx+dyv*yy;
+	if(u<0 || v<0 || u+v>1)	return;
+	mglPnt p(p1+d1*u+d2*v);
+	if(mgl_isnan(p.u) && mgl_isnum(p.v) && anorm)
+	{	mglPoint nr(mglPoint(p2.x-p1.x,p2.y-p1.y,p2.z-p1.z)^mglPoint(p3.x-p1.x,p3.y-p1.y,p3.z-p1.z));
+		p.u = nr.x;	p.v = nr.y;	p.w = nr.z;	}
+	unsigned char r[4];
+	pnt_plot(i,j,p.z,col2int(p,r,d->ObjId),d->ObjId);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::line_pix(long i, long j, const mglPnt &p1, const mglPnt &p2, const mglDrawReg *dr)
+{
+	float xx = (i-p1.x), yy = (j-p1.y);
+	mglPnt d(p2-p1);
+	float dd = hypot(d.x, d.y);
+	float dxv = d.y/dd, dyv =-d.x/dd, dxu = d.x/dd, dyu = d.y/dd;
+	float u = dxu*xx+dyu*yy, v = dxv*xx+dyv*yy;	v = v*v;
+	if(u<0)			v += u*u;
+	else if(u>dd)	v += (u-dd)*(u-dd);
+	float pw=dr->PenWidth, dpw=3*pen_delta;
+	if(dr->ObjId==HighId)	{	pw *= 2;	dpw=2*pen_delta;	}
+	if(v>pw*pw || !(dr->PDef & ( (uint64_t)1<<long(fmod(dr->pPos+u/pw, 16)) ) ))	return;
+	mglPnt p(p1+d*(u/dd));
+	unsigned char r[4];
+	col2int(p,r,dr->ObjId);
+	r[3] = v<(pw-1)*(pw-1)/4 ? 255 : mgl_sline(255,dpw*(sqrt(v)+(1-pw)/2));
+	float dz = Width>2 ? 1 : 1e-5*Width;		// provide additional height to be well visible on the surfaces
+	pnt_plot(i,j,p.z+dz,r,dr->ObjId);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::pnt_pix(long i, long j, const mglPnt &p, const mglDrawReg *dr)
+{
+	float pw=3*dr->PenWidth,dpw=3*pen_delta;
+	if(dr->ObjId==HighId)	{	pw *= 2;	dpw=2*pen_delta;	}
+	unsigned char cs[4];
+	col2int(p,cs,dr->ObjId);
+	float xx = (i-p.x), yy = (j-p.y), v = xx*xx+yy*yy;
+	if(cs[3]==0 || v>(10/dpw+pw)*(10/dpw+pw))	return;
+	if(v<(pw-1)*(pw-1)/4)	cs[3] = mgl_sline(cs[3],dpw*(sqrt(v)+(1-pw)/2));
+	pnt_plot(i,j,p.z,cs,dr->ObjId);
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::mark_pix(long i, long j, const mglPnt &q, char type, mreal size, mglDrawReg *d)
+{
+	unsigned char cs[4];	col2int(q,cs,d?d->ObjId:d->ObjId);	cs[3] = size>0 ? 255 : 255*q.t;
+	mglPnt p0=q,p1=q,p2=q,p3=q;
+	mreal ss=fabs(size);
+
+	if(type=='.' || ss==0)
+	{
+		if(d)	d->PenWidth = ss?ss:sqrt(font_factor/400);
+		pnt_pix(i,j,q,d);
+	}
+	else
+	{
+		if(d)
+		{
+			d->PDef = MGL_SOLID_MASK;	d->angle = 0;
+			d->PenWidth*=fabs(50*size);
+			if(d->PenWidth<1)	d->PenWidth=1;
+		}
+		if(!strchr("xsSoO",type))	ss *= 1.1;
+		switch(type)
+		{
+		case 'P':
+			p0.x = q.x-ss;	p0.y = q.y-ss;	p1.x = q.x+ss;	p1.y = q.y-ss;
+			p2.x = q.x+ss;	p2.y = q.y+ss;	p3.x = q.x-ss;	p3.y = q.y+ss;
+			line_pix(i,j,p0,p1,d);	line_pix(i,j,p1,p2,d);
+			line_pix(i,j,p2,p3,d);	line_pix(i,j,p3,p0,d);
+		case '+':
+			p0.x = q.x-ss;	p0.y = q.y;	p1.x = q.x+ss;	p1.y = q.y;	line_pix(i,j,p0,p1,d);
+			p2.x = q.x;	p2.y = q.y-ss;	p3.x = q.x;	p3.y = q.y+ss;	line_pix(i,j,p2,p3,d);
+			break;
+		case 'X':
+			p0.x = q.x-ss;	p0.y = q.y-ss;	p1.x = q.x+ss;	p1.y = q.y-ss;
+			p2.x = q.x+ss;	p2.y = q.y+ss;	p3.x = q.x-ss;	p3.y = q.y+ss;
+			line_pix(i,j,p0,p1,d);	line_pix(i,j,p1,p2,d);
+			line_pix(i,j,p2,p3,d);	line_pix(i,j,p3,p0,d);
+		case 'x':
+			p0.x = q.x-ss;	p0.y = q.y-ss;	p1.x = q.x+ss;	p1.y = q.y+ss;	line_pix(i,j,p0,p1,d);
+			p2.x = q.x+ss;	p2.y = q.y-ss;	p3.x = q.x-ss;	p3.y = q.y+ss;	line_pix(i,j,p2,p3,d);
+			break;
+		case 'S':
+			p0.x = q.x-ss;	p0.y = q.y-ss;	p1.x = q.x-ss;	p1.y = q.y+ss;
+			p2.x= q.x+ss;	p2.y= q.y+ss;	p3.x = q.x+ss;	p3.y = q.y-ss;
+			quad_pix(i,j,p0,p1,p3,p2,d);
+		case 's':
+			p0.x = q.x-ss;	p0.y = q.y-ss;	p1.x = q.x+ss;	p1.y = q.y-ss;
+			p2.x = q.x+ss;	p2.y = q.y+ss;	p3.x = q.x-ss;	p3.y = q.y+ss;
+			line_pix(i,j,p0,p1,d);	line_pix(i,j,p1,p2,d);
+			line_pix(i,j,p2,p3,d);	line_pix(i,j,p3,p0,d);
+			break;
+		case 'D':
+			p0.x = q.x;	p0.y = q.y-ss;	p1.x = q.x+ss;	p1.y = q.y;
+			p2.x= q.x;	p2.y= q.y+ss;	p3.x = q.x-ss;	p3.y = q.y;
+			quad_pix(i,j,p0,p1,p3,p2,d);
+		case 'd':
+			p0.x = q.x;	p0.y = q.y-ss;	p1.x = q.x+ss;	p1.y = q.y;
+			p2.x = q.x;	p2.y = q.y+ss;	p3.x = q.x-ss;	p3.y = q.y;
+			line_pix(i,j,p0,p1,d);	line_pix(i,j,p1,p2,d);
+			line_pix(i,j,p2,p3,d);	line_pix(i,j,p3,p0,d);
+			break;
+		case 'Y':
+			p1.x = q.x;	p1.y = q.y-ss;	line_pix(i,j,q,p1,d);
+			p2.x = q.x-0.8*ss;	p2.y = q.y+0.6*ss;	line_pix(i,j,q,p2,d);
+			p3.x = q.x+0.8*ss;	p3.y = q.y+0.6*ss;	line_pix(i,j,q,p3,d);
+			break;
+		case '*':
+			p0.x = q.x-ss;		p0.y = q.y;
+			p1.x = q.x+ss;		p1.y = q.y;	line_pix(i,j,p0,p1,d);
+			p0.x = q.x-0.6*ss;	p0.y = q.y-0.8*ss;
+			p1.x = q.x+0.6*ss;	p1.y = q.y+0.8*ss;	line_pix(i,j,p0,p1,d);
+			p0.x = q.x-0.6*ss;	p0.y = q.y+0.8*ss;
+			p1.x = q.x+0.6*ss;	p1.y = q.y-0.8*ss;	line_pix(i,j,p0,p1,d);
+			break;
+		case 'T':
+			p0.x = q.x-ss;	p0.y = q.y-ss/2;
+			p1.x = q.x+ss;	p1.y = q.y-ss/2;
+			p2.x= q.x;		p2.y= q.y+ss;
+			trig_pix(i,j,p0,p1,p2,false,d);
+		case '^':
+			p0.x = q.x-ss;	p0.y = q.y-ss/2;
+			p1.x = q.x+ss;	p1.y = q.y-ss/2;
+			p2.x= q.x;		p2.y= q.y+ss;
+			line_pix(i,j,p0,p1,d);	line_pix(i,j,p1,p2,d);
+			line_pix(i,j,p2,p0,d);	break;
+		case 'V':
+			p0.x = q.x-ss;	p0.y = q.y+ss/2;
+			p1.x = q.x+ss;	p1.y = q.y+ss/2;
+			p2.x= q.x;		p2.y= q.y-ss;
+			trig_pix(i,j,p0,p1,p2,false,d);
+		case 'v':
+			p0.x = q.x-ss;	p0.y = q.y+ss/2;
+			p1.x = q.x+ss;	p1.y = q.y+ss/2;
+			p2.x= q.x;		p2.y= q.y-ss;
+			line_pix(i,j,p0,p1,d);	line_pix(i,j,p1,p2,d);
+			line_pix(i,j,p2,p0,d);	break;
+		case 'L':
+			p0.x = q.x+ss/2;	p0.y = q.y+ss;
+			p1.x = q.x+ss/2;	p1.y = q.y-ss;
+			p2.x= q.x-ss;		p2.y= q.y;
+			trig_pix(i,j,p0,p1,p2,false,d);
+		case '<':
+			p0.x = q.x+ss/2;	p0.y = q.y+ss;
+			p1.x = q.x+ss/2;	p1.y = q.y-ss;
+			p2.x= q.x-ss;		p2.y= q.y;
+			line_pix(i,j,p0,p1,d);	line_pix(i,j,p1,p2,d);
+			line_pix(i,j,p2,p0,d);	break;
+		case 'R':
+			p0.x = q.x-ss/2;	p0.y = q.y+ss;
+			p1.x = q.x-ss/2;	p1.y = q.y-ss;
+			p2.x= q.x+ss;		p2.y= q.y;
+			trig_pix(i,j,p0,p1,p2,false,d);
+		case '>':
+			p0.x = q.x-ss/2;	p0.y = q.y+ss;
+			p1.x = q.x-ss/2;	p1.y = q.y-ss;
+			p2.x= q.x+ss;		p2.y= q.y;
+			line_pix(i,j,p0,p1,d);	line_pix(i,j,p1,p2,d);
+			line_pix(i,j,p2,p0,d);	break;
+		case 'O':
+			{
+				float xx = (i-q.x), yy = (j-q.y);
+				float dz = Width>2 ? 1 : 1e-5*Width;		// provide additional height to be well visible on the surfaces
+				if(xx*xx+yy*yy<ss*ss)	pnt_plot(i,j,q.z+dz,cs,d->ObjId);
+			}
+		case 'o':
+			{
+				float pw=d->PenWidth;
+				float xx = (i-q.x), yy = (j-q.y), v = hypot(xx,yy);
+				v = (v-ss)*(v-ss);
+//				if(v>pw*pw)	return;
+				if(v>(pw-1)*(pw-1)/4)	cs[3] = mgl_sline(cs[3],2*(sqrt(v)+(1-pw)/2));
+				float dz = Width>2 ? 1 : 1e-5*Width;		// provide additional height to be well visible on the surfaces
+				pnt_plot(i,j,q.z+dz,cs,d->ObjId);
+			}
+			break;
+		case 'C':
+			pnt_pix(i,j,q,d);
+			{
+				float pw=d->PenWidth;
+				float xx = (i-q.x), yy = (j-q.y), v = hypot(xx,yy);
+				v = (v-ss)*(v-ss);
+//				if(v>pw*pw)	return;
+				if(v>(pw-1)*(pw-1)/4)	cs[3] = mgl_sline(cs[3],2*(sqrt(v)+(1-pw)/2));
+				float dz = Width>2 ? 1 : 1e-5*Width;		// provide additional height to be well visible on the surfaces
+				pnt_plot(i,j,q.z+dz,cs,d->ObjId);
+			}
+			break;
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::glyph_pix(long i, long j, const mglPrim &P, mglDrawReg *d)
+{
+	float phi = GetGlyphPhi(Pnt[P.n2],P.w);
+	if(mgl_isnan(phi))	return;
+
+	if(d)	{	d->PDef = MGL_SOLID_MASK;	d->angle = 0;	d->PenWidth=1;	}
+	mglPnt p=Pnt[P.n1];
+	mreal pf=sqrt((Bp.b[0]*Bp.b[0]+Bp.b[1]*Bp.b[1]+Bp.b[3]*Bp.b[3]+Bp.b[4]*Bp.b[4])/2), f = P.p*pf;
+
+	mglMatrix M;
+	M.b[0] = M.b[4] = M.b[8] = P.s;
+	M.RotateN(phi,0,0,1);
+	M.x=p.x;	M.y=p.y;	M.z=p.z;	M.pf = 1;
+	p.u *= pf;	p.v *= pf;
+
+	const mglGlyph &g = Glf[P.n4];
+	if(P.n3&8)
+	{
+		if(!(P.n3&4))	glyph_lpix(i,j,&M,p,f,true, d);
+		glyph_lpix(i,j,&M,p,f,false, d);
+	}
+	else
+	{
+		if(!(P.n3&4))	glyph_fpix(i,j,&M,p,f,g, d);
+		glyph_wpix(i,j,&M,p,f,g, d);
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::glyph_fpix(long i, long j, const mglMatrix *M, const mglPnt &pp, mreal f, const mglGlyph &g, const mglDrawReg *d)
+{
+	if(!g.trig || g.nt<=0)	return;
+	mglPnt q0=pp, q1=pp, q2=pp;
+	q0.u=q0.v=q1.u=q1.v=q2.u=q2.v=NAN;
+	for(long ik=0;ik<g.nt;ik++)
+	{
+		long ii = 6*ik;	mglPoint p;
+		p.Set(f*g.trig[ii]+pp.u,f*g.trig[ii+1]+pp.v,0);
+		PostScale(M,p);	q0.x = p.x;	q0.y = p.y;	q0.z = p.z;
+		ii+=2;	p.Set(f*g.trig[ii]+pp.u,f*g.trig[ii+1]+pp.v,0);
+		PostScale(M,p);	q1.x = p.x;	q1.y = p.y;	q1.z = p.z;
+		ii+=2;	p.Set(f*g.trig[ii]+pp.u,f*g.trig[ii+1]+pp.v,0);
+		PostScale(M,p);	q2.x = p.x;	q2.y = p.y;	q2.z = p.z;
+		trig_pix(i,j,q0,q1,q2,false,d);
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::glyph_wpix(long i, long j, const mglMatrix *M, const mglPnt &pp, mreal f, const mglGlyph &g, const mglDrawReg *d)
+{
+	if(!g.line || g.nl<=0)	return;
+	long il=0;
+	mglPnt q0=pp, q1=pp;	q0.u=q0.v=q1.u=q1.v=NAN;
+	mglPoint p1,p2;
+	for(long ik=0;ik<g.nl;ik++)
+	{
+		long ii = 2*ik;
+		if(g.line[ii]==0x3fff && g.line[ii+1]==0x3fff)	// line breakthrough
+		{	il = ik+1;	continue;	}
+		else if(ik==g.nl-1 || (g.line[ii+2]==0x3fff && g.line[ii+3]==0x3fff))
+		{	// enclose the circle. May be in future this block should be commented
+			p1.Set(f*g.line[ii]+pp.u,f*g.line[ii+1]+pp.v,0);	ii=2*il;
+			p2.Set(f*g.line[ii]+pp.u,f*g.line[ii+1]+pp.v,0);
+		}
+		else
+		{	// normal line
+			p1.Set(f*g.line[ii]+pp.u,f*g.line[ii+1]+pp.v,0);	ii+=2;
+			p2.Set(f*g.line[ii]+pp.u,f*g.line[ii+1]+pp.v,0);
+		}
+		PostScale(M,p1);	PostScale(M,p2);
+		q0.x = p1.x;	q0.y = p1.y;	q0.z = p1.z;
+		q1.x = p2.x;	q1.y = p2.y;	q1.z = p2.z;
+		line_pix(i,j,q0,q1,d);
+	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvas::glyph_lpix(long i, long j, const mglMatrix *M, const mglPnt &pp, mreal f, bool solid, const mglDrawReg *d)
+{
+	mglPnt q0=pp,q1=pp,q2=pp,q3=pp;
+	q0.u=q0.v=q1.u=q1.v=q2.u=q2.v=q3.u=q3.v=NAN;
+	mglPoint p1,p2,p3,p4;
+
+	mreal dy = 0.004;
+	p1.Set(pp.u,pp.v-dy,0);	PostScale(M,p1);
+	p2.Set(pp.u,pp.v+dy,0);	PostScale(M,p2);
+	p3.Set(fabs(f)+pp.u,pp.v+dy,0);	PostScale(M,p3);
+	p4.Set(fabs(f)+pp.u,pp.v-dy,0);	PostScale(M,p4);
+
+	q0.x = p1.x;	q0.y = p1.y;	q0.z = p1.z;
+	q1.x = p2.x;	q1.y = p2.y;	q1.z = p2.z;
+	q2.x = p3.x;	q2.y = p3.y;	q2.z = p3.z;
+	q3.x = p4.x;	q3.y = p4.y;	q3.z = p4.z;
+
+	if(solid)	quad_pix(i,j,q0,q1,q3,q2,d);
+	else
+	{
+		line_pix(i,j,q0,q1,d);	line_pix(i,j,q2,q1,d);
+		line_pix(i,j,q0,q3,d);	line_pix(i,j,q2,q3,d);
+	}
+}
+//-----------------------------------------------------------------------------
diff --git a/src/plot.cpp b/src/plot.cpp
new file mode 100644
index 0000000..37fa250
--- /dev/null
+++ b/src/plot.cpp
@@ -0,0 +1,2076 @@
+/***************************************************************************
+ * plot.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <algorithm>
+#include "mgl2/plot.h"
+#include "mgl2/eval.h"
+#include "mgl2/data.h"
+#include "mgl2/base.h"
+//-----------------------------------------------------------------------------
+//
+//	Plot by formulas series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_fplot(HMGL gr, const char *eqY, const char *pen, const char *opt)
+{
+	if(eqY==0 || eqY[0]==0)	return;		// nothing to plot
+	mreal r = gr->SaveState(opt);
+	long n = (mgl_isnan(r) || r<=0) ? 100:long(r+0.5);
+	long nm = gr->FaceNum?gr->FaceNum*n:10000, nd = gr->FaceNum?gr->FaceNum*10:1000;
+
+	mglDataS x, y;
+	x.dat.reserve(nm);	y.dat.reserve(nm);
+
+	mglFormula *eq = new mglFormula(eqY);
+	// initial data filling
+	x.clear();	y.clear();
+	if(gr->Min.x>0 && gr->Max.x>100*gr->Min.x)
+	{
+		mreal d = log(2*gr->Max.x/gr->Min.x)/(n-1);
+		for(long i=0;i<n;i++)
+		{	mreal xx = 2*gr->Max.x*exp(d*i)/(2*gr->Max.x/gr->Min.x+exp(d*i));
+			x.dat.push_back(xx);	y.dat.push_back(eq->Calc(xx));	}
+	}
+	else if(gr->Max.x<0 && gr->Min.x<100*gr->Max.x)
+	{
+		mreal d = log(2*gr->Min.x/gr->Max.x)/(n-1);
+		for(long i=0;i<n;i++)
+		{	mreal xx = 2*gr->Min.x*exp(d*i)/(2*gr->Min.x/gr->Max.x+exp(d*i));
+			x.dat.push_back(xx);	y.dat.push_back(eq->Calc(xx));	}
+	}
+	else
+	{
+		mreal d = (gr->Max.x - gr->Min.x)/(n-1.);
+		for(long i=0;i<n;i++)
+		{	mreal xx = gr->Min.x + i*d;
+			x.dat.push_back(xx);	y.dat.push_back(eq->Calc(xx));	}
+	}
+
+	bool check=true;
+	mreal ym=fabs(gr->Max.y - gr->Min.y)/nd;
+	while(check && long(x.dat.size())<nm)
+	{
+		if(gr->NeedStop())	{	delete eq;	return;	}
+		check = false;
+		for(long i=1;i<long(x.size());i++)
+		{
+			mreal xs=(x[i]+x[i-1])/2;
+			mreal ys=(y[i]+y[i-1])/2, yr=eq->Calc(xs);
+			if(fabs(yr-ys)>ym)	// bad approximation here
+			{
+				x.dat.insert(x.dat.begin()+i,xs);
+				y.dat.insert(y.dat.begin()+i,yr);
+				check = true;	i++;
+			}
+		}
+	}
+	mgl_plot_xy(gr,&x,&y,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_fplot_xyz(HMGL gr, const char *eqX, const char *eqY, const char *eqZ, const char *pen, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long n = (mgl_isnan(r) || r<=0) ? 100:long(r+0.5);
+	long nm = gr->FaceNum?gr->FaceNum*n:10000, nd = gr->FaceNum?gr->FaceNum*10:1000;
+
+	mglDataS x, y, z, t;
+	x.dat.reserve(nm);	y.dat.reserve(nm);
+	z.dat.reserve(nm);	t.dat.reserve(nm);
+	mglFormula *ex, *ey, *ez;
+	ex = new mglFormula(eqX ? eqX : "0");
+	ey = new mglFormula(eqY ? eqY : "0");
+	ez = new mglFormula(eqZ ? eqZ : "0");
+	t.clear();	x.clear();	y.clear();	z.clear();
+	for(long i=0;i<n;i++)	// initial data filling
+	{
+		mreal tt = i/(n-1.);	t.push_back(tt);
+		x.push_back(ex->Calc(0,0,t[i]));
+		y.push_back(ey->Calc(0,0,t[i]));
+		z.push_back(ez->Calc(0,0,t[i]));
+	}
+
+	bool check=true;
+	mreal xm=fabs(gr->Max.x-gr->Min.x)/nd, ym=fabs(gr->Max.y-gr->Min.y)/nd, zm=fabs(gr->Max.z-gr->Min.z)/nd;
+	while(check && long(x.dat.size())<nm)
+	{
+		if(gr->NeedStop())	{	delete ex;	delete ey;	delete ez;	return;	}
+		check = false;
+		for(long i=1;i<long(t.size());i++)
+		{
+			mreal ts=(t[i]+t[i-1])/2;
+			mreal xs=(x[i]+x[i-1])/2, xr=ex->Calc(0,0,ts);
+			mreal ys=(y[i]+y[i-1])/2, yr=ey->Calc(0,0,ts);
+			mreal zs=(z[i]+z[i-1])/2, zr=ez->Calc(0,0,ts);
+			if(fabs(xr-xs)>xm || fabs(yr-ys)>ym || fabs(zr-zs)>zm)	// bad approximation here
+			{
+				t.dat.insert(t.dat.begin()+i,ts);
+				x.dat.insert(x.dat.begin()+i,xr);
+				y.dat.insert(y.dat.begin()+i,yr);
+				z.dat.insert(z.dat.begin()+i,zr);
+				check = true;	i++;
+			}
+		}
+	}
+	delete ex;	delete ey;	delete ez;
+	mgl_plot_xyz(gr,&x,&y,&z,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_fplot_(uintptr_t *gr, const char *fy, const char *stl, const char *opt, int ly, int ls, int lo)
+{	char *s=new char[ly+1];	memcpy(s,fy,ly);	s[ly]=0;
+	char *p=new char[ls+1];	memcpy(p,stl,ls);	p[ls]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_fplot(_GR_, s, p, o);
+	delete []s;		delete []p;	delete []o;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_fplot_xyz_(uintptr_t *gr, const char *fx, const char *fy, const char *fz, const char *stl, const char *opt, int lx, int ly, int lz, int ls, int lo)
+{	char *sx=new char[lx+1];	memcpy(sx,fx,lx);	sx[lx]=0;
+	char *sy=new char[ly+1];	memcpy(sy,fy,ly);	sy[ly]=0;
+	char *sz=new char[lz+1];	memcpy(sz,fz,lz);	sz[lz]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	char *p=new char[ls+1];		memcpy(p,stl,ls);	p[ls]=0;
+	mgl_fplot_xyz(_GR_, sx, sy, sz, p, o);
+	delete []sx;	delete []sy;	delete []sz;	delete []p;	delete []o;	}
+//-----------------------------------------------------------------------------
+//
+//	Radar series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_radar(HMGL gr, HCDT a, const char *pen, const char *opt)
+{
+	long n = a->GetNx(), ny=a->GetNy();
+	if(n<2)	{	gr->SetWarn(mglWarnLow,"Radar");	return;	}
+	mglData x(n+1,ny), y(n+1,ny);
+	mreal m=a->Minimal(), r=gr->SaveState(opt);
+	if(mgl_isnan(r) || r<0)	r = m<0 ? -m:0;
+	mreal *co=new mreal[2*n];
+	for(long i=0;i<n;i++)	{	co[i]=cos(2*i*M_PI/n);	co[i+n]=sin(2*i*M_PI/n);	}
+	for(long j=0;j<ny;j++)
+	{
+		for(long i=0;i<n;i++)
+		{
+			mreal v = a->v(i,j);
+			x.a[i+(n+1)*j] = (r+v)*co[i];
+			y.a[i+(n+1)*j] = (r+v)*co[i+n];
+		}
+		x.a[n+(n+1)*j] = r+a->v(0,j);	y.a[n+(n+1)*j] = 0;
+	}
+	mgl_plot_xy(gr,&x,&y,pen,0);
+	if(mglchr(pen,'#'))	// draw "grid"
+	{
+		m = 1.1*(a->Maximal()+r);
+		x.Create(2);	y.Create(2);
+		for(long i=0;i<n;i++)
+		{
+			x.a[1]=m*co[i];		y.a[1]=m*co[i+n];
+			mgl_plot_xy(gr,&x,&y,"k",0);
+		}
+		if(r>0)
+		{
+			x.Create(101);	y.Create(101);
+			for(long i=0;i<91;i++)
+			{	x.a[i]=r*mgl_cos[(4*i)%360];	y.a[i]=r*mgl_cos[(270+4*i)%360];	}
+			mgl_plot_xy(gr,&x,&y,"k",0);
+		}
+	}
+	delete []co;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_radar_(uintptr_t *gr, uintptr_t *a, const char *pen, const char *opt, int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_radar(_GR_, _DA_(a),s,o);	delete []s;	delete []o;	}
+//-----------------------------------------------------------------------------
+//
+//	Candle series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_candle_xyv(HMGL gr, HCDT x, HCDT v1, HCDT v2, HCDT y1, HCDT y2, const char *pen, const char *opt)
+{
+	long n=v1->GetNx(),pal,nx=x->GetNx();
+	if(n<2)	{	gr->SetWarn(mglWarnLow,"Candle");	return;	}
+	if(nx<n || v2->GetNx()!=n)	{	gr->SetWarn(mglWarnDim,"Candle");	return;	}
+	bool d1=false,d2=false;
+	if(!y1)	{	y1 = new mglData(n);	d1=true;	((mglData *)y1)->Fill(NAN,NAN);	}
+	if(!y2)	{	y2 = new mglData(n);	d2=true;	((mglData *)y2)->Fill(NAN,NAN);	}
+	if(y1->GetNx()!=n || y2->GetNx()!=n)
+	{	gr->SetWarn(mglWarnDim,"Candle");	return;	}
+	static int cgid=1;	gr->StartGroup("Candle",cgid++);
+	gr->SaveState(opt);	gr->SetPenPal(pen,&pal);	gr->Reserve(8*n);
+	bool sh = mglchr(pen,'!');
+	bool wire = mglchr(pen,'#');
+
+	mreal dv=nx>n?1:0;
+	if(mglchr(pen,'<'))	dv = 1;
+	if(mglchr(pen,'^'))	dv = 0;
+	if(mglchr(pen,'>'))	dv =-1;
+	mreal zm = gr->AdjustZMin();
+	mreal c1,c2;	c2=c1=gr->NextColor(pal);
+	bool col2 = (gr->GetNumPal(pal)==2 && !sh);
+	if(col2)	c2 = gr->NextColor(pal);
+	for(long i=0;i<n;i++)
+	{
+		mreal m1=v1->v(i),	m2 = v2->v(i),	xx = x->v(i);
+		mreal d = i<nx-1 ? x->v(i+1)-xx : xx-x->v(i-1), c;
+		mreal x1 = xx + d/2*(dv-gr->BarWidth);
+		mreal x2 = x1 + gr->BarWidth*d;	xx = (x1+x2)/2;
+		if(sh)	c = gr->NextColor(pal,i);
+		else if(wire)	c = (i>0 && m2>v2->v(i-1))?c2:c1;
+		else	c = (m1>m2)?c1:c2;
+		long n1 = gr->AddPnt(mglPoint(xx,y1->v(i),zm),c);
+		long n2 = gr->AddPnt(mglPoint(xx,m1,zm),c);
+		gr->line_plot(n1,n2);
+		long n3 = gr->AddPnt(mglPoint(xx,y2->v(i),zm),c);
+		long n4 = gr->AddPnt(mglPoint(xx,m2,zm),c);
+		gr->line_plot(n3,n4);
+
+		n1 = gr->AddPnt(mglPoint(x1,m1,zm),c);
+		n2 = gr->AddPnt(mglPoint(x2,m1,zm),c);
+		n3 = gr->AddPnt(mglPoint(x1,m2,zm),c);
+		n4 = gr->AddPnt(mglPoint(x2,m2,zm),c);
+		gr->line_plot(n1,n2);	gr->line_plot(n1,n3);
+		gr->line_plot(n4,n2);	gr->line_plot(n4,n3);
+		if(m1>m2 || (col2 && !wire))	gr->quad_plot(n1,n2,n3,n4);
+	}
+	if(d1)	delete y1;
+	if(d2)	delete y2;
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_candle_yv(HMGL gr, HCDT v1, HCDT v2, HCDT y1, HCDT y2, const char *pen, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(v1->GetNx()+1);
+	x.Fill(gr->Min.x,gr->Max.x);
+	mgl_candle_xyv(gr,&x,v1,v2,y1,y2,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_candle(HMGL gr, HCDT v1, HCDT y1, HCDT y2, const char *pen, const char *opt)
+{
+	mglData v2(v1);
+	v2.Roll('x',1);	v2.a[0]=NAN;
+	mgl_candle_yv(gr,v1,&v2,y1,y2,pen,opt);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_candle_xyv_(uintptr_t *gr, uintptr_t *x, uintptr_t *v1, uintptr_t *v2, uintptr_t *y1, uintptr_t *y2, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_candle_xyv(_GR_,_DA_(x),_DA_(v1),_DA_(v2),_DA_(y1),_DA_(y2),s,o);	delete []s;	delete []o;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_candle_yv_(uintptr_t *gr, uintptr_t *v1, uintptr_t *v2, uintptr_t *y1, uintptr_t *y2, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_candle_yv(_GR_,_DA_(v1),_DA_(v2),_DA_(y1),_DA_(y2),s,o);	delete []s;	delete []o;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_candle_(uintptr_t *gr, uintptr_t *y, uintptr_t *y1, uintptr_t *y2, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_candle(_GR_,_DA_(y),_DA_(y1),_DA_(y2),s,o);
+	delete []s;	delete []o;	}
+//-----------------------------------------------------------------------------
+//
+//	Plot series
+//
+//-----------------------------------------------------------------------------
+struct mglPointA {	mglPoint p;	bool orig;	mglPointA(const mglPoint &pp, bool o) : p(pp), orig(o) {}	};
+std::vector<mglPointA> MGL_NO_EXPORT mgl_pnt_prepare(const mglPoint &p1, const mglPoint &p2, HCDT xx, HCDT yy, HCDT zz, HCDT cc)
+{
+	std::vector<mglPointA> out;
+	long n = xx->GetNx();
+	mglPoint p(xx->v(0),yy->v(0),zz->v(0),cc?cc->v(0):0);
+	if(p>p1 && p<p2)	out.push_back(mglPointA(p,true));
+	else	out.push_back(mglPointA(mglPoint(NAN),true));
+	for(long i=1;i<n;i++)
+	{
+		mglPoint q(xx->v(i),yy->v(i),zz->v(i),cc?cc->v(i):0);
+		mreal x1,x2,y1,y2,z1,z2,t;
+		x1=mgl_d(p1.x, p.x, q.x);	x2=mgl_d(p2.x, p.x, q.x);	if(x2<x1)	{	t=x1;	x1=x2;	x2=t;	}
+		y1=mgl_d(p1.y, p.y, q.y);	y2=mgl_d(p2.y, p.y, q.y);	if(y2<y1)	{	t=y1;	y1=y2;	y2=t;	}
+		z1=mgl_d(p1.z, p.z, q.z);	z2=mgl_d(p2.z, p.z, q.z);	if(z2<z1)	{	t=z1;	z1=z2;	z2=t;	}
+		mreal d1 = mgl_isnum(x1)?x1:0, d2 = mgl_isnum(x2)?x2:1;
+		if(y1>d1)	d1=y1;
+		if(y2<d2)	d2=y2;
+		if(z1>d1)	d1=z1;
+		if(z2<d2)	d2=z2;
+		if(d1>0 && d1<1)	out.push_back(mglPointA(p+d1*(q-p),false));
+		if(d2>0 && d2<1)	out.push_back(mglPointA(p+d2*(q-p),false));
+		if(d1<1 && d2>=1)	out.push_back(mglPointA(q,true));
+		else if(i==n-1)	out.push_back(mglPointA(mglPoint(NAN),true));
+		p = q;
+	}
+	return out;
+}
+std::vector<mglPointA> MGL_NO_EXPORT mgl_pnt_copy(HCDT xx, HCDT yy, HCDT zz, HCDT cc)
+{
+	std::vector<mglPointA> out;
+	long n = xx->GetNx();
+	for(long i=0;i<n;i++)
+		out.push_back(mglPointA(mglPoint(xx->v(i),yy->v(i),zz->v(i),cc?cc->v(i):0),true));
+	return out;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_mark(HMGL gr, double x, double y, double z,const char *mark);
+void MGL_EXPORT mgl_plot_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, const char *pen, const char *opt)
+{
+	static int cgid=1;
+	long n=y->GetNx(),pal;
+	if(n<2 && !mgl_check_dim0(gr,x,y,z,0,"Plot"))
+	{
+		gr->StartGroup("Plot",cgid++);
+		gr->SaveState(opt);
+
+		char mk = gr->SetPenPal(pen);
+		if(mk)
+		{
+			long k = gr->AddPnt(mglPoint(x->v(0),y->v(0),z->v(0)),gr->CDef,mglPoint(NAN),-1,3);
+			gr->mark_plot(k,mk,gr->GetPenWidth()); 	gr->AddActive(k);
+		}
+		gr->EndGroup(); return;
+	}
+	if(mgl_check_dim1(gr,x,y,z,0,"Plot"))	return;
+
+	gr->StartGroup("Plot",cgid++);
+	gr->SaveState(opt);
+	long m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();	m = z->GetNy() > m ? z->GetNy() : m;
+	char mk=gr->SetPenPal(pen,&pal);	gr->Reserve(2*n*m);
+	bool sh = mglchr(pen,'!'), orig = !mglchr(pen,'a');
+
+	int d = gr->MeshNum>0 ? gr->MeshNum+1 : n, dx = n>d?n/d:1;
+	for(long j=0;j<m;j++)
+	{
+		if(gr->NeedStop())	break;
+		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0, mz = j<z->GetNy() ? j:0;
+		gr->NextColor(pal);
+		mglDataR xx(x,mx), yy(y,my), zz(z,mz);
+		const std::vector<mglPointA> &pp = orig ? mgl_pnt_copy(&xx, &yy, &zz, 0) :
+			mgl_pnt_prepare(gr->Min, gr->Max, &xx, &yy, &zz, 0);
+		long n1=-1, n2=-1;
+		
+		for(size_t i=0;i<pp.size();i++)
+		{
+			mreal c = sh ? gr->NextColor(pal,i):gr->CDef;
+			n2 = n1;	n1 = gr->AddPnt(pp[i].p, c);
+			if(mk && i%dx==0 && n1>=0 && pp[i].orig)	gr->mark_plot(n1,mk);
+			if(n1>=0 && n2>=0)
+			{
+				gr->line_plot(n1,n2);
+				if(i==1)	gr->arrow_plot(n2,n1,gr->Arrow1);
+			}
+		}
+		if(n1>=0 && n2>=0)	gr->arrow_plot(n1,n2,gr->Arrow2);
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_plot_xy(HMGL gr, HCDT x, HCDT y, const char *pen, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV z(y->GetNx());	z.Fill(gr->AdjustZMin());
+	mgl_plot_xyz(gr,x,y,&z,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_plot(HMGL gr, HCDT y, const char *pen, const char *opt)
+{
+	long n=y->GetNx();
+	if(n<2)	{	gr->SetWarn(mglWarnLow,"Plot");	return;	}
+	gr->SaveState(opt);
+	mglDataV x(n), z(n);
+	x.Fill(gr->Min.x,gr->Max.x);	z.Fill(gr->AdjustZMin());
+	mgl_plot_xyz(gr,&x,y,&z,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_plot_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_plot_xyz(_GR_, _DA_(x),_DA_(y),_DA_(z),s,o);	delete []s;	delete []o;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_plot_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_plot_xy(_GR_, _DA_(x),_DA_(y),s,o);	delete []s;	delete []o;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_plot_(uintptr_t *gr, uintptr_t *y,	const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_plot(_GR_, _DA_(y),s,o);	delete []s;	delete []o;	}
+//-----------------------------------------------------------------------------
+//
+//	Tens series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tens_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT c, const char *pen, const char *opt)
+{
+	long m,n=y->GetNx(), pal;
+	if(mgl_check_dim1(gr,x,y,z,0,"Tens"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Tens",cgid++);
+	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();	m = z->GetNy() > m ? z->GetNy() : m;
+	char mk=gr->SetPenPal(pen, &pal);	gr->Reserve(2*n*m);
+	long ss=gr->AddTexture(pen);
+	bool orig = !mglchr(pen,'a');
+
+	int d = gr->MeshNum>0 ? gr->MeshNum+1 : n, dx = n>d?n/d:1;
+	for(long j=0;j<m;j++)
+	{
+		if(gr->NeedStop())	break;
+		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
+		long mz = j<z->GetNy() ? j:0, mc = j<c->GetNy() ? j:0;
+		mglDataR xx(x,mx), yy(y,my), zz(z,mz), cc(c,mc);
+		const std::vector<mglPointA> &pp = orig ? mgl_pnt_copy(&xx, &yy, &zz, &cc) :
+			mgl_pnt_prepare(gr->Min, gr->Max, &xx, &yy, &zz, &cc);
+		long n1=-1, n2=-1;
+		for(size_t i=0;i<pp.size();i++)
+		{
+			n2 = n1;	n1 = gr->AddPnt(pp[i].p, gr->GetC(ss,pp[i].p.c));
+			if(mk && i%dx==0 && n1>=0 && pp[i].orig)	gr->mark_plot(n1,mk);
+			if(n1>=0 && n2>=0)
+			{
+				gr->line_plot(n1,n2);
+				if(i==1)	gr->arrow_plot(n2,n1,gr->Arrow1);
+			}
+		}
+		if(n1>=0 && n2>=0)	gr->arrow_plot(n1,n2,gr->Arrow2);
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tens_xy(HMGL gr, HCDT x, HCDT y, HCDT c, const char *pen, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV z(y->GetNx());	z.Fill(gr->AdjustZMin());
+	mgl_tens_xyz(gr,x,y,&z,c,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tens(HMGL gr, HCDT y, HCDT c, const char *pen, const char *opt)
+{
+	long n=y->GetNx();
+	if(n<2)	{	gr->SetWarn(mglWarnLow,"Tens");	return;	}
+	gr->SaveState(opt);
+	mglDataV x(n), z(n);
+	x.Fill(gr->Min.x,gr->Max.x);	z.Fill(gr->AdjustZMin());
+	mgl_tens_xyz(gr,&x,y,&z,c,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tens_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tens_xyz(_GR_, _DA_(x),_DA_(y),_DA_(z),_DA_(c),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tens_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *c, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tens_xy(_GR_, _DA_(x),_DA_(y),_DA_(c),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tens_(uintptr_t *gr, uintptr_t *y, uintptr_t *c, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tens(_GR_, _DA_(y),_DA_(c),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Area series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_area_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, const char *pen, const char *opt)
+{
+	long n=y->GetNx(),m,pal;
+	if(mgl_check_dim1(gr,x,y,z,0,"Area"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Area3",cgid++);
+	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();	m = z->GetNy() > m ? z->GetNy() : m;
+	bool sh = mglchr(pen,'!'), wire = mglchr(pen,'#'), orig = !mglchr(pen,'a');
+
+	mreal z0=gr->GetOrgZ('x');
+	gr->SetPenPal(pen,&pal);	gr->Reserve(2*n*m);
+	for(long j=0;j<m;j++)
+	{
+		if(gr->NeedStop())	break;
+		mreal c1=gr->NextColor(pal), c2=c1;
+		if(gr->GetNumPal(pal)==2*m && !sh)	c2 = gr->NextColor(pal);
+		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0, mz = j<z->GetNy() ? j:0;
+
+		mglDataR xx(x,mx), yy(y,my), zz(z,mz);
+		std::vector<mglPointA> pp = orig ? mgl_pnt_copy(&xx, &yy, &zz, 0) :
+			mgl_pnt_prepare(gr->Min, gr->Max, &xx, &yy, &zz, 0);
+		size_t np = pp.size();
+		long n1=-1, n2=-1;
+		mglPoint nn(pp[0].p.y-pp[1].p.y, pp[1].p.x-pp[0].p.x);
+		for(size_t i=0;i<np;i++)
+		{
+			long n3=n1, n4=n2;
+			if(sh)	c2=c1=gr->NextColor(pal,i);
+			if(i>0 && i<np-1)	{	nn.x=(pp[i-1].p.y-pp[i+1].p.y)/2;	nn.y=(pp[i+1].p.x-pp[i-1].p.x)/2;	}
+			else if(i==np-1)	{	nn.x=pp[np-2].p.y-pp[np-1].p.y;	nn.y=pp[np-1].p.x-pp[np-2].p.x;	}
+			n1 = gr->AddPnt(pp[i].p, c1,nn,-1,27);	pp[i].p.z = z0;
+			n2 = gr->AddPnt(pp[i].p, c2,nn,-1,27);
+			if(gr->SamePnt(n1,n3) || gr->SamePnt(n2,n4))	continue;
+			if(wire)
+			{
+				gr->line_plot(n1,n2);	gr->line_plot(n3,n4);
+				gr->line_plot(n1,n3);	gr->line_plot(n4,n2);
+			}
+			else	gr->quad_plot(n1,n2,n3,n4);
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_area_xy(HMGL gr, HCDT x, HCDT y, const char *pen, const char *opt)
+{
+	long n=y->GetNx(),m=y->GetNy(),pal;
+	if(mgl_check_dim1(gr,x,y,0,0,"Area"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Curve",cgid++);
+	mreal zm = gr->AdjustZMin();
+	mreal y0=gr->GetOrgY('x');
+	mglPoint nn(0,0,1);
+	bool sh = mglchr(pen,'!'), wire = mglchr(pen,'#'), orig = !mglchr(pen,'a');
+
+	gr->SetPenPal(pen,&pal);	gr->Reserve(2*n*m);
+	for(long j=0;j<m;j++)
+	{
+		if(gr->NeedStop())	break;
+		mreal c1=gr->NextColor(pal), c2=c1;
+		if(gr->GetNumPal(pal)==2*m && !sh)	c2=gr->NextColor(pal);
+		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
+		mreal z0 = zm + (m-1-j)*(gr->Max.z-zm)/m;
+
+		mglDataR xx(x,mx), yy(y,my);	mglDataV zz(n,1,1,z0);
+		std::vector<mglPointA> pp = orig ? mgl_pnt_copy(&xx, &yy, &zz, 0) :
+			mgl_pnt_prepare(gr->Min, gr->Max, &xx, &yy, &zz, 0);
+		size_t np = pp.size();
+		long n1=-1, n2=-1;
+		for(size_t i=0;i<np;i++)
+		{
+			long n3=n1, n4=n2;
+			if(sh)	c2=c1=gr->NextColor(pal,i);
+			n1 = gr->AddPnt(pp[i].p, c1,nn,-1,27);	pp[i].p.y = y0;
+			n2 = gr->AddPnt(pp[i].p, c2,nn,-1,27);
+			if(n1<0 || n2<0)	{	n1=n2=-1;	continue;	}
+			if(gr->SamePnt(n1,n3) || gr->SamePnt(n2,n4))	continue;
+			if(wire)
+			{
+				gr->line_plot(n1,n2);	gr->line_plot(n3,n4);
+				gr->line_plot(n1,n3);	gr->line_plot(n4,n2);
+			}
+			else	gr->quad_plot(n1,n2,n3,n4);
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_area(HMGL gr, HCDT y, const char *pen, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(y->GetNx());	x.Fill(gr->Min.x,gr->Max.x);
+	mgl_area_xy(gr,&x,y,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_area_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_area_xyz(_GR_, _DA_(x),_DA_(y),_DA_(z),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_area_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_area_xy(_GR_, _DA_(x),_DA_(y),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_area_(uintptr_t *gr, uintptr_t *y, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_area(_GR_, _DA_(y),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Region series
+//
+//-----------------------------------------------------------------------------
+struct mglPointB {	mglPoint p1, p2;	bool orig;
+	mglPointB(const mglPoint &pp1, const mglPoint &pp2, bool o) : p1(pp1), p2(pp2), orig(o) {}	};
+std::vector<mglPointB> MGL_NO_EXPORT mgl_pnt_prepare(const mglPoint &a1, const mglPoint &a2, HCDT xx1, HCDT yy1, HCDT zz1, HCDT xx2, HCDT yy2, HCDT zz2)
+{
+	std::vector<mglPointB> out;
+	long n = xx1->GetNx();
+	mglPoint p1(xx1->v(0),yy1->v(0),zz1->v(0)), p2(xx2->v(0),yy2->v(0),zz2->v(0));
+	if(p1>a1 && p1<a2 && p2>a1 && p2<a2)	out.push_back(mglPointB(p1,p2,true));
+	else	out.push_back(mglPointB(mglPoint(NAN),mglPoint(NAN),true));
+	for(long i=1;i<n;i++)
+	{
+		mglPoint q1(xx1->v(i),yy1->v(i),zz1->v(i)), q2(xx2->v(i),yy2->v(i),zz2->v(i));
+		mreal x1,x2,y1,y2,z1,z2,t;
+		x1=mgl_d(a1.x, p1.x, q1.x);	x2=mgl_d(a2.x, p1.x, q1.x);	if(x2<x1)	{	t=x1;	x1=x2;	x2=t;	}
+		y1=mgl_d(a1.y, p1.y, q1.y);	y2=mgl_d(a2.y, p1.y, q1.y);	if(y2<y1)	{	t=y1;	y1=y2;	y2=t;	}
+		z1=mgl_d(a1.z, p1.z, q1.z);	z2=mgl_d(a2.z, p1.z, q1.z);	if(z2<z1)	{	t=z1;	z1=z2;	z2=t;	}
+		mreal d11 = mgl_isnum(x1)?x1:0, d12 = mgl_isnum(x2)?x2:1;
+		if(y1>d11)	d11=y1;
+		if(y2<d12)	d12=y2;
+		if(z1>d11)	d11=z1;
+		if(z2<d12)	d12=z2;
+		x1=mgl_d(a1.x, p2.x, q2.x);	x2=mgl_d(a2.x, p2.x, q2.x);	if(x2<x1)	{	t=x1;	x1=x2;	x2=t;	}
+		y1=mgl_d(a1.y, p2.y, q2.y);	y2=mgl_d(a2.y, p2.y, q2.y);	if(y2<y1)	{	t=y1;	y1=y2;	y2=t;	}
+		z1=mgl_d(a1.z, p2.z, q2.z);	z2=mgl_d(a2.z, p2.z, q2.z);	if(z2<z1)	{	t=z1;	z1=z2;	z2=t;	}
+		mreal d21 = mgl_isnum(x1)?x1:0, d22 = mgl_isnum(x2)?x2:1;
+		if(y1>d21)	d21=y1;
+		if(y2<d22)	d22=y2;
+		if(z1>d21)	d21=z1;
+		if(z2<d22)	d22=z2;
+		
+		std::vector<mreal> dd;
+		if(d11>0 && d11<1)	dd.push_back(d11);
+		if(d21>0 && d21<1)	dd.push_back(d21);
+		if(d12>0 && d12<1)	dd.push_back(d12);
+		if(d22>0 && d22<1)	dd.push_back(d22);
+		// now add all intersections to be sure
+		x1=mgl_d(0, p2.x-p1.x, q2.x-q1.x);	if(x1>0 && x1<1)	dd.push_back(x1);
+		y1=mgl_d(0, p2.y-p1.y, q2.y-q1.y);	if(y1>0 && y1<1)	dd.push_back(y1);
+		z1=mgl_d(0, p2.z-p1.z, q2.z-q1.z);	if(z1>0 && z1<1)	dd.push_back(z1);
+		std::sort(dd.begin(),dd.end());
+		for(size_t j=0;j<dd.size();j++)
+			out.push_back(mglPointB(p1+dd[j]*(q1-p1), p2+dd[j]*(q2-p2), false));
+		if((d11<1 && d12>=1) || (d21<1 && d22>=1))	out.push_back(mglPointB(q1,q2,true));
+		else if(i==n-1)	out.push_back(mglPointB(mglPoint(NAN),mglPoint(NAN),true));
+		p1 = q1;	p2 = q2;
+	}
+	return out;
+}
+std::vector<mglPointB> MGL_NO_EXPORT mgl_pnt_copy(HCDT xx1, HCDT yy1, HCDT zz1, HCDT xx2, HCDT yy2, HCDT zz2)
+{
+	std::vector<mglPointB> out;
+	long n = xx1->GetNx();
+	for(long i=0;i<n;i++)
+		out.push_back(mglPointB(mglPoint(xx1->v(i),yy1->v(i),zz1->v(i)), mglPoint(xx2->v(i),yy2->v(i),zz2->v(i)), true));
+	return out;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_region_3d(HMGL gr, HCDT x1, HCDT y1, HCDT z1, HCDT x2, HCDT y2, HCDT z2, const char *pen, const char *opt)
+{
+	long n=y1->GetNx(), m, pal;
+	if(mgl_check_dim1(gr,x1,y1,z1,0,"Region"))	return;
+	if(mgl_check_dim1(gr,x1,x2,y2,z2,"Region"))	return;
+	m = x1->GetNy() > y1->GetNy() ? x1->GetNy() : y1->GetNy();	m = z1->GetNy() > m ? z1->GetNy() : m;
+	bool zhave = z1 && z2;
+	if(x1->GetNy()!=x2->GetNy() || y1->GetNy()!=y2->GetNy())
+	{	gr->SetWarn(mglWarnDim,"Region");	return;	}
+	if(zhave && z1->GetNy()!=z2->GetNy())
+	{	gr->SetWarn(mglWarnDim,"Region");	return;	}
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Region",cgid++);
+	mreal c1,c2;
+	mglPoint nn(0,0,1);
+	mreal zm = gr->AdjustZMin();
+//	bool inside = (mglchr(pen,'i'));	// NOTE: check if 'i' is free (used here for inside flag)
+	bool sh = mglchr(pen,'!'), wire = mglchr(pen,'#'), orig = !mglchr(pen,'a');
+
+	gr->SetPenPal(pen,&pal);	gr->Reserve(2*n*m);
+	for(long j=0;j<m;j++)
+	{
+		if(gr->NeedStop())	break;
+		c2=c1=gr->NextColor(pal);
+		if(gr->GetNumPal(pal)==2*m && !sh)	c2=gr->NextColor(pal);
+		long mx = j<x1->GetNy() ? j:0, my = j<y1->GetNy() ? j:0;
+		long mz = (zhave && j<z1->GetNy()) ? j:0;
+		mreal z0 = zm + (m-1-j)*(gr->Max.z-zm)/m;
+
+		mglDataR xx1(x1,mx), yy1(y1,my), xx2(x2,mx), yy2(y2,my);
+		mglDataV zz0(n,1,1,z0);
+		std::vector<mglPointB> pp;
+		if(zhave)
+		{
+			mglDataR zz1(z1,mz), zz2(z2,mz);
+			pp = orig ? mgl_pnt_copy(&xx1, &yy1, &zz1, &xx2, &yy2, &zz2) :
+				mgl_pnt_prepare(gr->Min, gr->Max, &xx1, &yy1, &zz1, &xx2, &yy2, &zz2);
+		}
+		else
+		{
+			pp = orig ? mgl_pnt_copy(&xx1, &yy1, &zz0, &xx2, &yy2, &zz0) :
+				mgl_pnt_prepare(gr->Min, gr->Max, &xx1, &yy1, &zz0, &xx2, &yy2, &zz0);
+		}
+
+		long n1=-1, n2=-1;
+		size_t np = pp.size();
+		for(size_t i=0;i<np;i++)
+		{
+			long n3=n1, n4=n2;
+			if(sh)	c2=c1=gr->NextColor(pal,i);
+			n1 = gr->AddPnt(pp[i].p1, c1,nn,-1,27);
+			n2 = gr->AddPnt(pp[i].p2, c2,nn,-1,27);
+			if(n1<0 || n2<0)	{	n1=n2=-1;	continue;	}
+			if(gr->SamePnt(n1,n3) || gr->SamePnt(n2,n4))	continue;
+			if(wire)
+			{
+				gr->line_plot(n1,n2);	gr->line_plot(n3,n4);
+				gr->line_plot(n1,n3);	gr->line_plot(n4,n2);
+			}
+			else	gr->quad_plot(n1,n2,n3,n4);
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_region_xy(HMGL gr, HCDT x, HCDT y1, HCDT y2, const char *pen, const char *opt)
+{
+	long n=y1->GetNx(), m=y1->GetNy(), pal;
+	if(mgl_check_dim1(gr,x,y1,y2,0,"Region"))	return;
+	if(y2->GetNy()!=m)	{	gr->SetWarn(mglWarnDim,"Region");	return;	}
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Region",cgid++);
+	mreal c1,c2;
+	mglPoint nn(0,0,1);
+	mreal zm = gr->AdjustZMin();
+	bool inside = mglchr(pen,'i');	// NOTE: check if 'i' is free (used here for inside flag)
+	bool sh = mglchr(pen,'!'), wire = mglchr(pen,'#'), orig = !mglchr(pen,'a');
+
+	gr->SetPenPal(pen,&pal);	gr->Reserve(2*n*m);
+	for(long j=0;j<m;j++)
+	{
+		if(gr->NeedStop())	break;
+		c2=c1=gr->NextColor(pal);
+		if(gr->GetNumPal(pal)==2*m && !sh)	c2=gr->NextColor(pal);
+		long mx = j<x->GetNy() ? j:0;
+		mreal z0 = zm + (m-1-j)*(gr->Max.z-zm)/m;
+
+		mglDataR xx(x,mx), yy1(y1,j), yy2(y2,j);
+		mglDataV zz0(n,1,1,z0);
+		std::vector<mglPointB> pp = orig ? mgl_pnt_copy(&xx, &yy1, &zz0, &xx, &yy2, &zz0) :
+			mgl_pnt_prepare(gr->Min, gr->Max, &xx, &yy1, &zz0, &xx, &yy2, &zz0);
+
+		mreal f1=0, f2=0;
+		long n1=-1, n2=-1;
+		size_t np = pp.size();
+		for(size_t i=0;i<np;i++)
+		{
+			long n3=n1, n4=n2;
+			mreal f3=f1, f4=f2;
+			f1 = pp[i].p1.y;	f2 = pp[i].p2.y;
+			if(sh)	c2=c1=gr->NextColor(pal,i);
+			n1 = gr->AddPnt(pp[i].p1, c1,nn,-1,27);
+			n2 = gr->AddPnt(pp[i].p2, c2,nn,-1,27);
+			if(n1<0 || n2<0)	{	n1=n2=-1;	continue;	}
+			if(inside && (f2<f1 || f4<f3))	continue;
+			if(gr->SamePnt(n1,n3) || gr->SamePnt(n2,n4))	continue;
+			if(wire)
+			{
+				gr->line_plot(n1,n2);	gr->line_plot(n3,n4);
+				gr->line_plot(n1,n3);	gr->line_plot(n4,n2);
+			}
+			else	gr->quad_plot(n1,n2,n3,n4);
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_region(HMGL gr, HCDT y1, HCDT y2, const char *pen, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(y1->GetNx());	x.Fill(gr->Min.x, gr->Max.x);
+	mgl_region_xy(gr,&x,y1,y2,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_region_3d_(uintptr_t *gr, uintptr_t *x1, uintptr_t *y1, uintptr_t *z1, uintptr_t *x2, uintptr_t *y2, uintptr_t *z2, const char *pen, const char *opt, int l, int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_region_3d(_GR_, _DA_(x1),_DA_(y1),_DA_(z1),_DA_(x2),_DA_(y2),_DA_(z2),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_region_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y1, uintptr_t *y2, const char *pen, const char *opt, int l, int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_region_xy(_GR_, _DA_(x),_DA_(y1),_DA_(y2),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_region_(uintptr_t *gr, uintptr_t *y1, uintptr_t *y2, const char *pen, const char *opt, int l, int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_region(_GR_, _DA_(y1),_DA_(y2),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Step series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_step_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, const char *pen, const char *opt)
+{
+	long m,n=y->GetNx(), pal;
+	if(mgl_check_dim1(gr,x,y,z,0,"Step"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Step3",cgid++);
+	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();	m = z->GetNy() > m ? z->GetNy() : m;
+	bool sh = mglchr(pen,'!');
+
+	char mk=gr->SetPenPal(pen,&pal);	gr->Reserve(2*n*m);
+	int d = gr->MeshNum>0 ? gr->MeshNum+1 : n, dx = n>d?n/d:1;
+	for(long j=0;j<m;j++)
+	{
+		if(gr->NeedStop())	break;
+		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0, mz = j<z->GetNy() ? j:0;
+		gr->NextColor(pal);
+		long n1 = gr->AddPnt(mglPoint(x->v(0,mx), y->v(0,my), z->v(0,mz)));
+		if(mk)	gr->mark_plot(n1,mk);
+		for(long i=1;i<n;i++)
+		{
+			long n2 = n1;	// horizontal
+			mglPoint p(x->v(i,mx), y->v(i,my), z->v(i-1,mz));
+			mreal c = sh ? gr->NextColor(pal,i):gr->CDef;
+			n1 = gr->AddPnt(p,c);	gr->line_plot(n1,n2);
+			if(i==1)	gr->arrow_plot(n2,n1,gr->Arrow1);
+
+			n2 = n1;	// vertical
+			p.z = z->v(i,mz);	n1 = gr->AddPnt(p,c);
+			if(mk && i%dx==0)	gr->mark_plot(n1,mk);
+			gr->line_plot(n1,n2);
+			if(i==n-1)	gr->arrow_plot(n1,n2,gr->Arrow2);
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_step_xy(HMGL gr, HCDT x, HCDT y, const char *pen, const char *opt)
+{
+	long m,n=y->GetNx(), pal;
+	if(mgl_check_dim1(gr,x,y,0,0,"Step",true))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Step",cgid++);
+	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();
+	bool sh = mglchr(pen,'!');
+	bool same = x->GetNx()==n;
+
+	mreal zVal =gr->AdjustZMin();
+	char mk=gr->SetPenPal(pen,&pal);	gr->Reserve(2*n*m);
+	int d = gr->MeshNum>0 ? gr->MeshNum+1 : n, dx = n>d?n/d:1;
+	for(long j=0;j<m;j++)
+	{
+		if(gr->NeedStop())	break;
+		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
+		gr->NextColor(pal);
+		mreal xx = x->v(0,mx);
+		long n1 = gr->AddPnt(mglPoint(same?xx:(xx+x->v(1,mx))/2, y->v(0,my), zVal));
+		if(mk)	gr->mark_plot(n1,mk);
+		if(!same)	n1 = gr->AddPnt(mglPoint(xx, y->v(0,my), zVal));
+		for(long i=1;i<n;i++)
+		{
+			long n2 = n1;	// horizontal
+			xx = x->v(i,mx);
+			mglPoint p(xx, y->v(i-1,my), zVal);
+			mreal c = sh ? gr->NextColor(pal,i):gr->CDef;
+			n1 = gr->AddPnt(p,c);	gr->line_plot(n1,n2);
+			if(i==1)	gr->arrow_plot(n2,n1,gr->Arrow1);
+
+			n2 = n1;	// vertical
+			p.y = y->v(i,my);		n1 = gr->AddPnt(p,c);
+			gr->line_plot(n1,n2);
+			if(same && i==n-1)	gr->arrow_plot(n1,n2,gr->Arrow2);
+			long nn = n1;
+			if(!same)	nn = gr->AddPnt(mglPoint((xx+x->v(i+1,mx))/2, y->v(i,my), zVal));
+			if(mk && i%dx==0)	gr->mark_plot(nn,mk);
+		}
+		if(!same)
+		{
+			mglPoint p(x->v(n,mx), y->v(n-1,my), zVal);
+			mreal c = sh ? gr->NextColor(pal,n-1):gr->CDef;
+			long n2 = gr->AddPnt(p,c);	gr->line_plot(n1,n2);
+			gr->arrow_plot(n2,n1,gr->Arrow2);
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_step(HMGL gr, HCDT y,	const char *pen, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(y->GetNx());	x.Fill(gr->Min.x,gr->Max.x);
+	mgl_step_xy(gr,&x,y,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_step_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_step_xyz(_GR_, _DA_(x),_DA_(y),_DA_(z),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_step_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_step_xy(_GR_, _DA_(x),_DA_(y),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_step_(uintptr_t *gr, uintptr_t *y,	const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_step(_GR_, _DA_(y),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Stem series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_stem_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, const char *pen, const char *opt)
+{
+	long m,n=y->GetNx(), pal;
+	if(mgl_check_dim0(gr,x,y,z,0,"Stem"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Stem3",cgid++);
+	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();	m = z->GetNy() > m ? z->GetNy() : m;
+	bool sh = mglchr(pen,'!');
+
+	mreal z0=gr->GetOrgZ('x');
+	char mk=gr->SetPenPal(pen,&pal);	gr->Reserve(2*n*m);
+	for(long j=0;j<m;j++)
+	{
+		if(gr->NeedStop())	break;
+		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0, mz = j<z->GetNy() ? j:0;
+		gr->NextColor(pal);
+		for(long i=0;i<n;i++)
+		{
+			mreal c = sh ? gr->NextColor(pal,i):gr->CDef;
+			long n1 = gr->AddPnt(mglPoint(x->v(i,mx), y->v(i,my), z->v(i,mz)),c);
+			if(mk)	gr->mark_plot(n1,mk);
+			long n2 = gr->AddPnt(mglPoint(x->v(i,mx), y->v(i,my), z0),c);
+			gr->line_plot(n1,n2);
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_stem_xy(HMGL gr, HCDT x, HCDT y, const char *pen, const char *opt)
+{
+	long m,n=y->GetNx(), pal;
+	if(mgl_check_dim0(gr,x,y,0,0,"Stem"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Stem",cgid++);
+	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();
+	bool sh = mglchr(pen,'!');
+
+	mreal zVal = gr->AdjustZMin(), y0=gr->GetOrgY('x');
+	char mk=gr->SetPenPal(pen,&pal);	gr->Reserve(2*n*m);
+	for(long j=0;j<m;j++)
+	{
+		if(gr->NeedStop())	break;
+		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
+		gr->NextColor(pal);
+		for(long i=0;i<n;i++)
+		{
+			mreal vv = x->v(i,mx);
+			mreal c = sh ? gr->NextColor(pal,i):gr->CDef;
+			long n1 = gr->AddPnt(mglPoint(vv, y->v(i,my), zVal),c);
+			if(mk)	gr->mark_plot(n1,mk);
+			long n2 = gr->AddPnt(mglPoint(vv, y0, zVal),c);
+			gr->line_plot(n1,n2);
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_stem(HMGL gr, HCDT y,	const char *pen, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(y->GetNx());	x.Fill(gr->Min.x,gr->Max.x);
+	mgl_stem_xy(gr,&x,y,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_stem_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_stem_xyz(_GR_,_DA_(x),_DA_(y),_DA_(z),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_stem_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_stem_xy(_GR_,_DA_(x),_DA_(y),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_stem_(uintptr_t *gr, uintptr_t *y,	const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_stem(_GR_,_DA_(y),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Bars series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_bars_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, const char *pen, const char *opt)
+{
+	long m,n=z->GetNx(), pal,nx=x->GetNx(),ny=y->GetNx();
+	if(mgl_check_dim1(gr,x,z,y,0,"Bars",true))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Bars3",cgid++);
+	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();
+	m = z->GetNy() > m ? z->GetNy() : m;
+	bool sh = mglchr(pen,'!');
+
+	bool wire = mglchr(pen,'#'), fixed = mglchr(pen,'F');
+	bool above = mglchr(pen,'a'), fall = mglchr(pen,'f');
+	if(above)	fall = false;
+	mreal c1,c2;
+	mreal *dd=new mreal[n], z0,zp,dv=nx>n?1:0;
+	if(mglchr(pen,'<'))	dv = 1;
+	if(mglchr(pen,'^'))	dv = 0;
+	if(mglchr(pen,'>'))	dv = -1;
+	memset(dd,0,n*sizeof(mreal));
+
+	mreal dc=INFINITY;
+	if(fixed)	for(long j=0;j<m;j++)
+	{
+		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
+		for(long i=0;i<n-1;i++)
+		{
+			mreal cx = hypot(x->v(i+1,mx)-x->v(i,mx), y->v(i+1,my)-y->v(i,my));
+			if(cx<dc)	dc=cx;
+		}
+	}
+	if(dc==0)	fixed=false;	// NOTE: disable fixed width if it is zero
+
+	gr->SetPenPal(pen,&pal);
+	gr->Reserve(4*n*m);
+	for(long j=0;j<m;j++)
+	{
+		if(gr->NeedStop())	break;
+		c2=c1=gr->NextColor(pal);
+		if(gr->GetNumPal(pal)==2*m && !sh)	c2 = gr->NextColor(pal);
+		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0, mz = j<z->GetNy() ? j:0;
+		zp = z0 = gr->GetOrgZ('x');
+		for(long i=0;i<n;i++)
+		{
+			if(sh)	c2=c1=gr->NextColor(pal,i);
+			mreal vv = x->v(i,mx), dx = i<nx-1 ? x->v(i+1,mx)-vv : vv-x->v(i-1,mx), dy, zz;
+			vv = y->v(i,my);	dy = i<ny-1 ? y->v(i+1,my)-vv : vv-y->v(i-1,my);
+			if(fixed)
+			{	mreal ff = dc/hypot(dx,dy);	dx *= ff;	dy *= ff;	}
+			mreal x1 = vv + dx/2*(dv-gr->BarWidth), x2 = x1 + gr->BarWidth*dx;
+			mreal y1 = vv + dy/2*(dv-gr->BarWidth), y2 = y1 + gr->BarWidth*dy;
+			vv = zz = z->v(i,mz);
+			if(!above)
+			{
+				x2 = (x2-x1)/m;		x1 += j*x2;		x2 += x1;
+				y2 = (y2-y1)/m;		y1 += j*y2;		y2 += y1;
+			}
+			else
+			{	z0 = gr->GetOrgZ('x') + dd[i];	dd[i] += zz;	zz += z0;	}
+			if(fall)	{	z0 = zp;	zz += z0;	zp = zz;	}
+
+			mreal c = vv<0 ? c1 : c2;
+			mglPoint nn(-y->dvx(i,my),x->dvx(i,mx));
+			long n1 = gr->AddPnt(mglPoint(x1,y1,zz),c,nn);
+			long n2 = gr->AddPnt(mglPoint(x1,y1,z0),c,nn);
+			long n3 = gr->AddPnt(mglPoint(x2,y2,z0),c,nn);
+			long n4 = gr->AddPnt(mglPoint(x2,y2,zz),c,nn);
+			if(wire)
+			{
+				gr->line_plot(n1,n2);	gr->line_plot(n1,n4);
+				gr->line_plot(n3,n2);	gr->line_plot(n3,n4);
+			}
+			else	gr->quad_plot(n1,n2,n4,n3);
+		}
+	}
+	gr->EndGroup();	delete []dd;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_bars_xy(HMGL gr, HCDT x, HCDT y, const char *pen, const char *opt)
+{
+	long m,n=y->GetNx(),nx=x->GetNx(),pal;
+	if(mgl_check_dim1(gr,x,y,0,0,"Bars",true))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Bars",cgid++);
+	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();
+	bool sh = mglchr(pen,'!');
+
+	bool wire = mglchr(pen,'#'), fixed = mglchr(pen,'F');
+	bool above = mglchr(pen,'a'), fall = mglchr(pen,'f');
+	if(above)	fall = false;
+	mreal c1,c2;
+	mreal *dd=new mreal[n], y0,yp,dv=nx>n?1:0;
+	if(mglchr(pen,'<'))	dv = 1;
+	if(mglchr(pen,'^'))	dv = 0;
+	if(mglchr(pen,'>'))	dv = -1;
+	mreal zm = gr->AdjustZMin();
+	memset(dd,0,n*sizeof(mreal));
+
+	mreal dx=INFINITY;
+	if(fixed)
+	{
+		long nn=x->GetNy();
+		for(long i=0;i<n-1;i++)	for(long j=0;j<nn;j++)
+		{
+			mreal cx = fabs(x->v(i+1,j)-x->v(i,j));
+			if(cx<dx)	dx=cx;
+		}
+	}
+	if(dx==0)	fixed=false;	// NOTE: disable fixed width if it is zero
+
+	gr->SetPenPal(pen,&pal);
+	gr->Reserve(4*n*m);
+	for(long j=0;j<m;j++)
+	{
+		if(gr->NeedStop())	break;
+		c2=c1=gr->NextColor(pal);
+		if(gr->GetNumPal(pal)==2*m && !sh)	c2 = gr->NextColor(pal);
+		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
+		yp = y0 = gr->GetOrgY('x');
+		for(long i=0;i<n;i++)
+		{
+			if(sh)	c2=c1=gr->NextColor(pal,i);
+			mreal vv = x->v(i,mx), d = i<nx-1 ? x->v(i+1,mx)-vv : vv-x->v(i-1,mx), yy;
+			if(fixed)	d = dx;
+			mreal x1 = vv + d/2*(dv-gr->BarWidth), x2 = x1 + gr->BarWidth*d;
+			vv = yy = y->v(i,my);
+			if(!above)
+			{	x2 = (x2-x1)/m;		x1 += j*x2;		x2 += x1;	}
+			else
+			{	y0 = gr->GetOrgY('x') + dd[i];	dd[i] += yy;	yy += y0;	}
+			if(fall)	{	y0 = yp;	yy += y0;	yp = yy;	}
+
+			mreal c = vv<0 ? c1 : c2;
+			long n1 = gr->AddPnt(mglPoint(x1,yy,zm),c);
+			long n2 = gr->AddPnt(mglPoint(x1,y0,zm),c);
+			long n3 = gr->AddPnt(mglPoint(x2,y0,zm),c);
+			long n4 = gr->AddPnt(mglPoint(x2,yy,zm),c);
+			if(wire)
+			{
+				gr->line_plot(n1,n2);	gr->line_plot(n1,n4);
+				gr->line_plot(n3,n2);	gr->line_plot(n3,n4);
+			}
+			else	gr->quad_plot(n1,n2,n4,n3);
+		}
+	}
+	gr->EndGroup();	delete []dd;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_bars(HMGL gr, HCDT y, const char *pen, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(y->GetNx()+1);	x.Fill(gr->Min.x,gr->Max.x);
+	mgl_bars_xy(gr,&x,y,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_bars_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_bars_xyz(_GR_,_DA_(x),_DA_(y),_DA_(z),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_bars_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_bars_xy(_GR_,_DA_(x),_DA_(y),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_bars_(uintptr_t *gr, uintptr_t *y,	const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_bars(_GR_,_DA_(y),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//		Barh series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_barh_yx(HMGL gr, HCDT y, HCDT v, const char *pen, const char *opt)
+{
+	long m,n=v->GetNx(),ny=y->GetNx(),pal;
+	if(mgl_check_dim1(gr,y,v,0,0,"Barh",true))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Barh",cgid++);
+	m = y->GetNy() > v->GetNy() ? y->GetNy() : v->GetNy();
+	bool sh = mglchr(pen,'!');
+
+	bool wire = mglchr(pen,'#'), fixed = mglchr(pen,'F');
+	bool above = mglchr(pen,'a'), fall = mglchr(pen,'f');
+	if(above)	fall = false;
+	mreal *dd=new mreal[n], x0,xp,dv=ny>n?1:0;
+	if(mglchr(pen,'<'))	dv = 1;
+	if(mglchr(pen,'^'))	dv = 0;
+	if(mglchr(pen,'>'))	dv = -1;
+	mreal zm = gr->AdjustZMin();
+	memset(dd,0,n*sizeof(mreal));
+
+	mreal dy=INFINITY;
+	if(fixed)
+	{
+		long nn=y->GetNy();
+		for(long i=0;i<n-1;i++)	for(long j=0;j<nn;j++)
+		{
+			mreal cx = fabs(y->v(i+1,j)-y->v(i,j));
+			if(cx<dy)	dy=cx;
+		}
+	}
+	if(dy==0)	fixed=false;	// NOTE: disable fixed width if it is zero
+
+	gr->SetPenPal(pen,&pal);
+	gr->Reserve(4*n*m);
+	for(long j=0;j<m;j++)
+	{
+		if(gr->NeedStop())	break;
+		mreal c1,c2;	c2=c1=gr->NextColor(pal);
+		if(gr->GetNumPal(pal)==2*m && !sh)	c2 = gr->NextColor(pal);
+		long mx = j<v->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
+		xp = x0 = gr->GetOrgX('y');
+		for(long i=0;i<n;i++)
+		{
+			if(sh)	c2=c1=gr->NextColor(pal,i);
+			mreal vv = y->v(i,my), d = i<ny-1 ? y->v(i+1,my)-vv : vv-y->v(i-1,my), xx;
+			if(fixed)	d = dy;
+			mreal y1 = vv + d/2*(dv-gr->BarWidth), y2 = y1 + gr->BarWidth*d;
+			vv = xx = v->v(i,mx);
+			if(!above)
+			{	y2 = (y2-y1)/m;		y1 += j*y2;		y2 += y1;	}
+			else
+			{	x0 = gr->GetOrgX('y') + dd[i];	dd[i] += xx;	xx += x0;	}
+			if(fall)	{	x0 = xp;	xx += x0;	xp = xx;	}
+
+			mreal c = vv<0 ? c1 : c2;
+			long n1 = gr->AddPnt(mglPoint(xx,y1,zm),c);
+			long n2 = gr->AddPnt(mglPoint(xx,y2,zm),c);
+			long n3 = gr->AddPnt(mglPoint(x0,y2,zm),c);
+			long n4 = gr->AddPnt(mglPoint(x0,y1,zm),c);
+			if(wire)
+			{
+				gr->line_plot(n1,n2);	gr->line_plot(n1,n4);
+				gr->line_plot(n3,n2);	gr->line_plot(n3,n4);
+			}
+			else	gr->quad_plot(n1,n2,n4,n3);
+		}
+	}
+	gr->EndGroup();	delete []dd;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_barh(HMGL gr, HCDT v,	const char *pen, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV y(v->GetNx()+1);	y.Fill(gr->Min.y,gr->Max.y);
+	mgl_barh_yx(gr,&y,v,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_barh_yx_(uintptr_t *gr, uintptr_t *y, uintptr_t *v, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_barh_yx(_GR_,_DA_(y),_DA_(v),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_barh_(uintptr_t *gr, uintptr_t *v,	const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_barh(_GR_,_DA_(v),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	OHLC series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_ohlc_x(HMGL gr, HCDT x, HCDT open, HCDT high, HCDT low, HCDT close, const char *pen, const char *opt)
+{
+	long n=open->GetNx(), nx=x->GetNx(), m=open->GetNy(), mx;
+	if(nx<n || n*m!=high->GetNx()*high->GetNy() || n*m!=low->GetNx()*low->GetNy() || n*m!=close->GetNx()*close->GetNy())
+	{	gr->SetWarn(mglWarnDim,"OHLC");	return;	}
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("OHLC",cgid++);
+	mreal dv=nx>n?1:0;
+	if(mglchr(pen,'<'))	dv = 1;
+	if(mglchr(pen,'^'))	dv = 0;
+	if(mglchr(pen,'>'))	dv = -1;
+	mreal zVal = gr->AdjustZMin();
+	bool sh = mglchr(pen,'!');
+
+	long pal;
+	gr->SetPenPal(pen,&pal);	gr->Reserve(6*n*m);
+	for(long j=0;j<m;j++)
+	{
+		if(gr->NeedStop())	break;
+		mreal c1,c2;	c2=c1=gr->NextColor(pal);
+		if(gr->GetNumPal(pal)==2*m && !sh)	c2 = gr->NextColor(pal);
+		mx = j<x->GetNy() ? j:0;
+		for(long i=0;i<n;i++)
+		{
+			mreal dd,vv,x1,x2;
+			vv = x->v(i,mx);	dd = i<nx-1 ? x->v(i+1)-vv : vv-x->v(i-1);
+			x1 = vv + dd/2*(dv-gr->BarWidth);	x2 = x1 + gr->BarWidth*dd;
+			x2 = (x2-x1)/m;		x1 += j*x2;		x2 += x1;	vv = (x2+x1)/2;
+			if(sh)	c1=c2=gr->NextColor(pal,i);
+			long n1,n2;
+
+			dd = close->v(i,j);
+			mreal c = (i==0 || dd>=close->v(i-1,j)) ? c1:c2;
+			n1=gr->AddPnt(mglPoint(vv,dd,zVal),c);
+			n2=gr->AddPnt(mglPoint(x2,dd,zVal),c);
+			gr->line_plot(n1,n2);
+			dd = open->v(i,j);
+			n1=gr->AddPnt(mglPoint(x1,dd,zVal),c);
+			n2=gr->AddPnt(mglPoint(vv,dd,zVal),c);
+			gr->line_plot(n1,n2);
+			n1=gr->AddPnt(mglPoint(vv,low->v(i,j),zVal),c);
+			n2=gr->AddPnt(mglPoint(vv,high->v(i,j),zVal),c);
+			gr->line_plot(n1,n2);
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_ohlc(HMGL gr, HCDT open, HCDT high, HCDT low, HCDT close, const char *pen, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(open->GetNx()+1);	x.Fill(gr->Min.x,gr->Max.x);
+	mgl_ohlc_x(gr,&x,open,high,low,close,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_ohlc_x_(uintptr_t *gr, uintptr_t *x, uintptr_t *open, uintptr_t *high, uintptr_t *low, uintptr_t *close, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_ohlc_x(_GR_,_DA_(x),_DA_(open),_DA_(high),_DA_(low),_DA_(close),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_ohlc_(uintptr_t *gr, uintptr_t *open, uintptr_t *high, uintptr_t *low, uintptr_t *close, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_ohlc(_GR_,_DA_(open),_DA_(high),_DA_(low),_DA_(close),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	BoxPlot series
+//
+//-----------------------------------------------------------------------------
+double sgn(double a);
+int MGL_NO_EXPORT mgl_cmp_flt(const void *a, const void *b)
+{
+	const mreal *aa = (const mreal *)a;
+	const mreal *bb = (const mreal *)b;
+	return int(sgn(*aa-*bb));
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_boxplot_xy(HMGL gr, HCDT x, HCDT y, const char *pen, const char *opt)
+{
+	long n=y->GetNx(), m=y->GetNy(), nx=x->GetNx();
+	if(nx<n || nx<2 || m<2)	{	gr->SetWarn(mglWarnDim,"BoxPlot");	return;	}
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("BoxPlot",cgid++);
+	mreal *b = new mreal[5*n], x1, x2, dd, dv=nx>n?1:0;
+	if(mglchr(pen,'<'))	dv = 1;
+	if(mglchr(pen,'^'))	dv = 0;
+	if(mglchr(pen,'>'))	dv = -1;
+	mreal zVal = gr->AdjustZMin(), vv;
+	bool sh = mglchr(pen,'!');
+	mreal *d = new mreal[m];
+	for(long i=0;i<n;i++)	// find quartiles by itself
+	{
+		long mm=0,k;
+		for(long j=0;j<m;j++)
+		{
+			mreal vv = y->v(i,j);
+			if(mgl_isnum(vv))	{	d[mm]=vv;	mm++;	}
+		}
+//			if(m==0)	{	b[i]=NAN;	break;	}
+		qsort(d, mm, sizeof(mreal), mgl_cmp_flt);
+		b[i] = d[0];	b[i+4*n] = d[mm-1];		k = mm/4;
+		b[i+n] = (mm%4) ? d[k] : (d[k]+d[k-1])/2.;
+		b[i+2*n] = (mm%2) ? d[mm/2] : (d[mm/2]+d[mm/2-1])/2.;
+		b[i+3*n] = (mm%4) ? d[mm-k-1] : (d[mm-k-1]+d[mm-k])/2.;
+	}
+	delete []d;
+
+	long pal;
+	gr->SetPenPal(pen,&pal);	gr->NextColor(pal);	gr->Reserve(18*n);
+	for(long i=0;i<n;i++)
+	{
+		vv = x->v(i);
+		dd = i<nx-1 ? x->v(i+1)-vv : vv-x->v(i-1);
+		x1 = vv + dd/2*(dv-gr->BarWidth);
+		x2 = x1 + gr->BarWidth*dd;
+		mreal c = sh ? gr->NextColor(pal,i):gr->CDef;
+		long n1,n2;
+
+		n1=gr->AddPnt(mglPoint(x1,b[i],zVal),c);	// horizontal lines
+		n2=gr->AddPnt(mglPoint(x2,b[i],zVal),c);
+		gr->line_plot(n1,n2);
+		n1=gr->AddPnt(mglPoint(x1,b[i+n],zVal),c);
+		n2=gr->AddPnt(mglPoint(x2,b[i+n],zVal),c);
+		gr->line_plot(n1,n2);
+		n1=gr->AddPnt(mglPoint(x1,b[i+2*n],zVal),c);
+		n2=gr->AddPnt(mglPoint(x2,b[i+2*n],zVal),c);
+		gr->line_plot(n1,n2);
+		n1=gr->AddPnt(mglPoint(x1,b[i+3*n],zVal),c);
+		n2=gr->AddPnt(mglPoint(x2,b[i+3*n],zVal),c);
+		gr->line_plot(n1,n2);
+		n1=gr->AddPnt(mglPoint(x1,b[i+4*n],zVal),c);
+		n2=gr->AddPnt(mglPoint(x2,b[i+4*n],zVal),c);
+		gr->line_plot(n1,n2);
+
+		//vertical lines
+		n1=gr->AddPnt(mglPoint(x1,b[i+n],zVal),c);
+		n2=gr->AddPnt(mglPoint(x1,b[i+3*n],zVal),c);
+		gr->line_plot(n1,n2);
+		n1=gr->AddPnt(mglPoint(x2,b[i+n],zVal),c);
+		n2=gr->AddPnt(mglPoint(x2,b[i+3*n],zVal),c);
+		gr->line_plot(n1,n2);
+		n1=gr->AddPnt(mglPoint((x1+x2)/2,b[i],zVal),c);
+		n2=gr->AddPnt(mglPoint((x1+x2)/2,b[i+n],zVal),c);
+		gr->line_plot(n1,n2);
+		n1=gr->AddPnt(mglPoint((x1+x2)/2,b[i+3*n],zVal),c);
+		n2=gr->AddPnt(mglPoint((x1+x2)/2,b[i+4*n],zVal),c);
+		gr->line_plot(n1,n2);
+	}
+	delete []b;	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_boxplot(HMGL gr, HCDT y, const char *pen, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(y->GetNx()+1);	x.Fill(gr->Min.x,gr->Max.x);
+	mgl_boxplot_xy(gr,&x,y,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_boxplot_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_boxplot_xy(_GR_,_DA_(x),_DA_(y),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_boxplot_(uintptr_t *gr, uintptr_t *y,	const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_boxplot(_GR_,_DA_(y),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//		Error series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_error_exy(HMGL gr, HCDT x, HCDT y, HCDT ex, HCDT ey, const char *pen, const char *opt)
+{
+	long m,n=ey->GetNx(),pal;
+	if(mgl_check_dim0(gr,x,y,ey,ex,"Error"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Error",cgid++);
+	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();
+	m = ex->GetNy() > m ? ex->GetNy() : m;
+	m = ey->GetNy() > m ? ey->GetNy() : m;
+	bool sh = mglchr(pen,'!');
+
+	bool ma = mglchr(pen,'@');
+	char mk = gr->SetPenPal(pen,&pal);
+	mreal zVal=gr->AdjustZMin();
+	gr->Reserve(5*n*m);
+	if(ma && (mk==0 || !strchr("PXsSdD+xoOC",mk) ))	mk = 'S';
+	gr->ResetMask();
+	mglPoint q(NAN,NAN);
+	for(long j=0;j<m;j++)
+	{
+		if(gr->NeedStop())	break;
+		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
+		long m1 = j<ex->GetNy() ? j:0,m2 = j<ey->GetNy() ? j:0;
+		gr->NextColor(pal);
+		if(ma)
+		{
+			if(strchr("PXsS",mk))	for(long i=0;i<n;i++)	// boundary of square
+			{
+				mreal vx=x->v(i,mx), ve=ex->v(i,m1), vy=y->v(i,my), vf=ey->v(i,m2);
+				mreal c = sh ? gr->NextColor(pal,i):gr->CDef;
+				long n1 = gr->AddPnt(mglPoint(vx-ve, vy+vf, zVal),c,q,-1,27);
+				long n2 = gr->AddPnt(mglPoint(vx-ve, vy-vf, zVal),c,q,-1,27);
+				long n3 = gr->AddPnt(mglPoint(vx+ve, vy+vf, zVal),c,q,-1,27);
+				long n4 = gr->AddPnt(mglPoint(vx+ve, vy-vf, zVal),c,q,-1,27);
+				gr->line_plot(n1,n2);	gr->line_plot(n1,n3);
+				gr->line_plot(n4,n2);	gr->line_plot(n4,n3);
+			}
+			if(strchr("dD",mk))	for(long i=0;i<n;i++)	// boundary of rhomb
+			{
+				mreal vx=x->v(i,mx), ve=ex->v(i,m1), vy=y->v(i,my), vf=ey->v(i,m2);
+				mreal c = sh ? gr->NextColor(pal,i):gr->CDef;
+				long n1 = gr->AddPnt(mglPoint(vx, vy+vf, zVal),c,q,-1,27);
+				long n2 = gr->AddPnt(mglPoint(vx-ve, vy, zVal),c,q,-1,27);
+				long n3 = gr->AddPnt(mglPoint(vx, vy-vf, zVal),c,q,-1,27);
+				long n4 = gr->AddPnt(mglPoint(vx+ve, vy, zVal),c,q,-1,27);
+				gr->line_plot(n1,n2);	gr->line_plot(n2,n3);
+				gr->line_plot(n3,n4);	gr->line_plot(n4,n1);
+			}
+			if(strchr("oOC",mk))	for(long i=0;i<n;i++)	// circle
+			{
+				mreal vx=x->v(i,mx), ve=ex->v(i,m1), vy=y->v(i,my), vf=ey->v(i,m2);
+				mreal c = sh ? gr->NextColor(pal,i):gr->CDef;
+				long n1,n2,k;
+				for(k=0,n2=-1;k<=40;k++)
+				{
+					n1 = n2;
+					n2 = gr->AddPnt(mglPoint(vx+ve*mgl_cos[(18*k)%360],
+							vy+vf*mgl_cos[(270+18*k)%360], zVal),c,q,-1,27);
+					if(k>0)	gr->line_plot(n1,n2);
+				}
+			}
+			switch(mk)
+			{
+			case 'P':	case '+':
+				for(long i=0;i<n;i++)
+				{
+					mreal vx=x->v(i,mx), ve=ex->v(i,m1), vy=y->v(i,my), vf=ey->v(i,m2);
+					mreal c = sh ? gr->NextColor(pal,i):gr->CDef;
+					long n1 = gr->AddPnt(mglPoint(vx, vy+vf, zVal),c,q,-1,27);
+					long n2 = gr->AddPnt(mglPoint(vx-ve, vy, zVal),c,q,-1,27);
+					long n3 = gr->AddPnt(mglPoint(vx, vy-vf, zVal),c,q,-1,27);
+					long n4 = gr->AddPnt(mglPoint(vx+ve, vy, zVal),c,q,-1,27);
+					gr->line_plot(n1,n3);	gr->line_plot(n2,n4);
+				}	break;
+			case 'X':	case 'x':
+				for(long i=0;i<n;i++)
+				{
+					mreal vx=x->v(i,mx), ve=ex->v(i,m1), vy=y->v(i,my), vf=ey->v(i,m2);
+					mreal c = sh ? gr->NextColor(pal,i):gr->CDef;
+					long n1 = gr->AddPnt(mglPoint(vx-ve, vy+vf, zVal),c,q,-1,27);
+					long n2 = gr->AddPnt(mglPoint(vx-ve, vy-vf, zVal),c,q,-1,27);
+					long n3 = gr->AddPnt(mglPoint(vx+ve, vy+vf, zVal),c,q,-1,27);
+					long n4 = gr->AddPnt(mglPoint(vx+ve, vy-vf, zVal),c,q,-1,27);
+					gr->line_plot(n1,n4);	gr->line_plot(n2,n3);
+				}	break;
+			case 'S':
+				for(long i=0;i<n;i++)
+				{
+					mreal vx=x->v(i,mx), ve=ex->v(i,m1), vy=y->v(i,my), vf=ey->v(i,m2);
+					mreal c = sh ? gr->NextColor(pal,i):gr->CDef;
+					long n1 = gr->AddPnt(mglPoint(vx-ve, vy+vf, zVal),c,q,-1,27);
+					long n2 = gr->AddPnt(mglPoint(vx-ve, vy-vf, zVal),c,q,-1,27);
+					long n3 = gr->AddPnt(mglPoint(vx+ve, vy+vf, zVal),c,q,-1,27);
+					long n4 = gr->AddPnt(mglPoint(vx+ve, vy-vf, zVal),c,q,-1,27);
+					gr->quad_plot(n1,n2,n3,n4);
+				}	break;
+			case 'D':
+				for(long i=0;i<n;i++)
+				{
+					mreal vx=x->v(i,mx), ve=ex->v(i,m1), vy=y->v(i,my), vf=ey->v(i,m2);
+					mreal c = sh ? gr->NextColor(pal,i):gr->CDef;
+					long n1 = gr->AddPnt(mglPoint(vx, vy+vf, zVal),c,q,-1,27);
+					long n2 = gr->AddPnt(mglPoint(vx-ve, vy, zVal),c,q,-1,27);
+					long n3 = gr->AddPnt(mglPoint(vx, vy-vf, zVal),c,q,-1,27);
+					long n4 = gr->AddPnt(mglPoint(vx+ve, vy, zVal),c,q,-1,27);
+					gr->quad_plot(n1,n4,n2,n3);
+				}	break;
+			case 'O':
+				for(long i=0;i<n;i++)
+				{
+					mreal vx=x->v(i,mx), ve=ex->v(i,m1), vy=y->v(i,my), vf=ey->v(i,m2);
+					mreal c = sh ? gr->NextColor(pal,i):gr->CDef;
+					long n1, n2, n3 = gr->AddPnt(mglPoint(vx,vy,zVal),c),k;
+					for(k=0,n2=-1;k<=40;k++)
+					{
+						n1 = n2;
+						n2 = gr->AddPnt(mglPoint(vx+ve*mgl_cos[(18*k)%360],
+								vy+vf*mgl_cos[(270+18*k)%360], zVal),c,q,-1,27);
+						if(k>0)	gr->trig_plot(n1,n2,n3);
+					}
+				}	break;
+			case 'C':
+				for(long i=0;i<n;i++)
+				{
+					gr->mark_plot(gr->AddPnt(mglPoint(x->v(i,mx),y->v(i,my),zVal),-1,q,-1,3), '.');
+					if(sh)	gr->NextColor(pal);
+				}
+			}
+		}
+		else	for(long i=0;i<n;i++)
+		{
+			mreal vx=x->v(i,mx), ve=ex->v(i,m1), vy=y->v(i,my), vf=ey->v(i,m2);
+			mreal c = sh ? gr->NextColor(pal,i):gr->CDef;
+			if(mk)	gr->mark_plot(gr->AddPnt(mglPoint(vx,vy,zVal),c), mk);
+
+			long n1 = gr->AddPnt(mglPoint(vx, vy+vf, zVal),c,q,-1,27);
+			long n2 = gr->AddPnt(mglPoint(vx, vy-vf, zVal),c,q,-1,27);
+			gr->line_plot(n1,n2);	gr->arrow_plot(n1,n2,'I');	gr->arrow_plot(n2,n1,'I');
+
+			n1 = gr->AddPnt(mglPoint(vx+ve, vy, zVal),-1,q,c,27);
+			n2 = gr->AddPnt(mglPoint(vx-ve, vy, zVal),-1,q,c,27);
+			gr->line_plot(n1,n2);	gr->arrow_plot(n1,n2,'I');	gr->arrow_plot(n2,n1,'I');
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_error_xy(HMGL gr, HCDT x, HCDT y, HCDT ey, const char *pen, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV ex(y->GetNx());	ex.Fill(NAN);
+	mgl_error_exy(gr,x,y,&ex,ey,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_error(HMGL gr, HCDT y, HCDT ey, const char *pen, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(y->GetNx()), ex(y->GetNx());
+	x.Fill(gr->Min.x,gr->Max.x);	ex.Fill(NAN);
+	mgl_error_exy(gr,&x,y,&ex,ey,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_error_(uintptr_t *gr, uintptr_t *y, uintptr_t *ey, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_error(_GR_,_DA_(y),_DA_(ey),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_error_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *ey, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_error_xy(_GR_,_DA_(x),_DA_(y),_DA_(ey),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_error_exy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *ex, uintptr_t *ey, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_error_exy(_GR_,_DA_(x),_DA_(y),_DA_(ex),_DA_(ey),s,o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//		Chart series
+//
+//-----------------------------------------------------------------------------
+void face_plot(mglBase *gr, mglPoint o, mglPoint d1, mglPoint d2, mreal c, bool wire)
+{
+	const int num=10;
+	mglPoint nn=d1^d2;
+	d1 = d1/num;	d2 = d2/num;
+	long n=num+1, *id=new long[n*n];
+	gr->Reserve(n*n);
+	for(long j=0;j<n;j++)	for(long i=0;i<n;i++)
+		id[i+n*j] = gr->AddPnt(o+d1*i+d2*j,c,nn);
+	for(long j=0;j<num;j++)	for(long i=0;i<num;i++)
+	{
+		long *ii = id+i+n*j;
+		gr->quad_plot(ii[0],ii[1],ii[n],ii[n+1]);
+	}
+	if(wire)
+	{
+		gr->Reserve(4*n);	gr->SetPenPal("k-");
+		long *jj=id+n+1;
+		jj[0] = jj[1] = gr->CopyNtoC(id[0],gr->CDef);
+		jj[2] = jj[3] = gr->CopyNtoC(id[n*n-1],gr->CDef);
+		for(long i=1;i<n;i++)
+		{
+			memcpy(jj+4,jj,4*sizeof(long));
+			jj[0] = gr->CopyNtoC(id[i],gr->CDef);
+			jj[1] = gr->CopyNtoC(id[n*i],gr->CDef);
+			jj[2] = gr->CopyNtoC(id[n*n-1-i],gr->CDef);
+			jj[3] = gr->CopyNtoC(id[n*n-1-n*i],gr->CDef);
+			gr->line_plot(jj[4],jj[0]);
+			gr->line_plot(jj[5],jj[1]);
+			gr->line_plot(jj[6],jj[2]);
+			gr->line_plot(jj[7],jj[3]);
+		}
+	}
+	delete []id;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_chart(HMGL gr, HCDT a, const char *cols, const char *opt)
+{
+	if(a->Minimal()<0)	{	gr->SetWarn(mglWarnNeg,"Chart");	return;	}
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Chart",cgid++);
+	bool wire = mglchr(cols,'#');	// draw edges
+	long n=a->GetNx(),i,j=0,len=cols?long(strlen(cols)):0;
+	if(cols)	for(i=0;i<len;i++)
+		if(strchr(MGL_COLORS,cols[i]) || cols[i]==' ')	j++;
+	if(j==0)	{	cols = MGL_DEF_PAL;	len=long(strlen(cols));	}
+	mreal *c = new mreal[len+1],cc;
+	long nc=0;			// number of colors
+	for(i=0;i<len;i++)
+		if(strchr(MGL_COLORS,cols[i]) || cols[i]==' ')
+		{	c[nc]=gr->AddTexture(cols[i]);	nc++;	}
+	// NOTE: nc>0 since j>0 or MGL_DEF_PAL is not empty
+
+	mreal dy = (gr->Max.y-gr->Min.y)/a->GetNy(), dx, ss, cs, x1, y1, dz=gr->Max.z-gr->Min.z, vv;
+	mglPoint d1,d2,o;
+
+	for(j=0;j<a->GetNy();j++)
+	{
+		if(gr->NeedStop())	break;
+		y1 = gr->Min.y + dy*j;
+		for(i=0,ss=0;i<n;i++)	ss += a->v(i,j);
+		if(ss==0)	continue;
+		for(cs=0,i=0;i<n;i++)
+		{
+			vv = a->v(i,j);	dx = vv/ss;	cc = c[i%nc];
+			if(dx==0)	continue;
+			x1 = gr->Min.x + (gr->Max.x-gr->Min.x)*cs/ss;	dx *= (gr->Max.x-gr->Min.x);
+			if(cc>=0)
+			{
+				face_plot(gr,mglPoint(x1,y1,gr->Min.z),mglPoint(dx,0,0),mglPoint(0,0,dz),cc,wire);
+				face_plot(gr,mglPoint(x1,y1,gr->Min.z),mglPoint(dx,0,0),mglPoint(0,dy,0),cc,wire);
+				face_plot(gr,mglPoint(x1,y1,gr->Min.z),mglPoint(0,dy,0),mglPoint(0,0,dz),cc,wire);
+
+				face_plot(gr,mglPoint(x1+dx,y1+dy,gr->Max.z),mglPoint(-dx,0,0),mglPoint(0,0,-dz),cc,wire);
+				face_plot(gr,mglPoint(x1+dx,y1+dy,gr->Max.z),mglPoint(-dx,0,0),mglPoint(0,-dy,0),cc,wire);
+				face_plot(gr,mglPoint(x1+dx,y1+dy,gr->Max.z),mglPoint(0,-dy,0),mglPoint(0,0,-dz),cc,wire);
+			}
+			cs += vv;
+		}
+	}
+	gr->EndGroup();	delete []c;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_chart_(uintptr_t *gr, uintptr_t *a, const char *col, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,col,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_chart(_GR_, _DA_(a), s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Mark series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_mark_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT r, const char *pen, const char *opt)
+{
+	long m,n=y->GetNx(),pal;
+	if(mgl_check_dim0(gr,x,y,z,r,"Mark"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Mark",cgid++);
+	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();
+	m = z->GetNy() > m ? z->GetNy() : m;
+	char mk=gr->SetPenPal(pen,&pal);	gr->Reserve(n*m);
+	if(mk==0)	mk='.';
+	bool sh = mglchr(pen,'!');
+
+	int d = gr->MeshNum>0 ? gr->MeshNum+1 : n, dx = n>d?n/d:1;
+	for(long j=0;j<m;j++)
+	{
+		if(gr->NeedStop())	break;
+		gr->NextColor(pal);
+		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
+		long mz = j<z->GetNy() ? j:0, mr = j<r->GetNy() ? j:0;
+		for(long i=0;i<n;i+=dx)
+		{
+			mreal c = sh ? gr->NextColor(pal,i):gr->CDef;
+			gr->mark_plot(gr->AddPnt(mglPoint(x->v(i,mx),y->v(i,my),z->v(i,mz)),c), mk, fabs(r->v(i,mr)));
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_mark_xy(HMGL gr, HCDT x, HCDT y, HCDT r, const char *pen, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV z(y->GetNx());	z.Fill(gr->AdjustZMin());
+	mgl_mark_xyz(gr,x,y,&z,r,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_mark_y(HMGL gr, HCDT y, HCDT r, const char *pen, const char *opt)
+{
+	long n=y->GetNx();
+	gr->SaveState(opt);
+	mglDataV x(n), z(n);
+	x.Fill(gr->Min.x,gr->Max.x);	z.Fill(gr->AdjustZMin());
+	mgl_mark_xyz(gr,&x,y,&z,r,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_mark_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *r, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_mark_xyz(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(r),s,o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_mark_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *r, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_mark_xy(_GR_, _DA_(x), _DA_(y), _DA_(r),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_mark_y_(uintptr_t *gr, uintptr_t *y, uintptr_t *r, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_mark_y(_GR_,_DA_(y),_DA_(r),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Tube series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tube_xyzr(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT r, const char *pen, const char *opt)
+{
+	long m,n=y->GetNx(),pal;
+	if(mgl_check_dim1(gr,x,y,z,r,"Tube"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Tube",cgid++);
+	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();
+	m = z->GetNy() > m ? z->GetNy() : m;
+	m = r->GetNy() > m ? r->GetNy() : m;
+	bool sh = mglchr(pen,'!');
+	bool wire = mglchr(pen,'#');
+
+	int num=!(gr->GetQuality()&3)?13:25;
+	gr->SetPenPal(pen,&pal);
+	gr->Reserve(n*m*num);
+	mglPoint p,l,t,u,q,d;
+	long *nn=new long[2*num];
+	memset(nn,-1,2*num*sizeof(long));
+	for(long j=0;j<m;j++)
+	{
+		if(gr->NeedStop())	break;
+		gr->NextColor(pal);
+		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
+		long mz = j<z->GetNy() ? j:0, mr = j<r->GetNy() ? j:0;
+		for(long i=0;i<n;i++)
+		{
+			l.Set(x->dvx(i,mx),y->dvx(i,my),z->dvx(i,mz));
+			t = !l;		t.Normalize();	u = t^l;	u.Normalize();
+			q.Set(x->v(i,mx),y->v(i,my),z->v(i,mz));
+			mreal rr=r->v(i,mr), dr=r->dvx(i,mr);
+			mreal c = sh ? gr->NextColor(pal,i):gr->CDef;
+			for(long k=0;k<num;k++)
+			{
+				int kk = k*360/(num-1);
+				float  co = mgl_cos[(kk)%360], si = mgl_cos[(270+kk)%360];
+				p = q + t*(rr*co) + u*(rr*si);
+				d = (t*si - u*co)^(l + t*(dr*co) + u*(dr*si));
+				nn[k+num]=nn[k];	nn[k] = gr->AddPnt(p,c,wire?mglPoint(NAN,NAN):d,-1,3);
+				if(i*k>0 && !wire)	gr->quad_plot(nn[k],nn[k-1],nn[k+num],nn[k+num-1]);
+				if(i*k>0 && wire && k%4==0)	gr->line_plot(nn[k],nn[k+num]);
+				if(k>0 && wire)		gr->line_plot(nn[k],nn[k-1]);
+			}
+		}
+	}
+	delete []nn;	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tube_xyr(HMGL gr, HCDT x, HCDT y, HCDT r, const char *pen, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV z(y->GetNx());	z.Fill(gr->AdjustZMin());
+	mgl_tube_xyzr(gr,x,y,&z,r,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tube_r(HMGL gr, HCDT y, HCDT r, const char *pen, const char *opt)
+{
+	long n=y->GetNx();
+	if(n<2)	{	gr->SetWarn(mglWarnLow,"Tube");	return;	}
+	gr->SaveState(opt);
+	mglDataV x(n), z(n);
+	x.Fill(gr->Min.x,gr->Max.x);	z.Fill(gr->AdjustZMin());
+	mgl_tube_xyzr(gr,&x,y,&z,r,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tube(HMGL gr, HCDT y, double rr, const char *pen, const char *opt)
+{
+	long n=y->GetNx();
+	if(n<2)	{	gr->SetWarn(mglWarnLow,"Tube");	return;	}
+	gr->SaveState(opt);
+	mglDataV x(n), r(n), z(n);
+	x.Fill(gr->Min.x,gr->Max.x);
+	r.Fill(rr);	z.Fill(gr->AdjustZMin());
+	mgl_tube_xyzr(gr,&x,y,&z,&r,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tube_xy(HMGL gr, HCDT x, HCDT y, double rr, const char *pen, const char *opt)
+{
+	long n=y->GetNx();
+	if(n<2)	{	gr->SetWarn(mglWarnLow,"Tube");	return;	}
+	gr->SaveState(opt);
+	mglDataV r(n), z(n);
+	r.Fill(rr);	z.Fill(gr->AdjustZMin());
+	mgl_tube_xyzr(gr,x,y,&z,&r,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tube_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, double rr, const char *pen, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV r(y->GetNx());	r.Fill(rr);
+	mgl_tube_xyzr(gr,x,y,z,&r,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tube_xyzr_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *r, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tube_xyzr(_GR_,_DA_(x),_DA_(y),_DA_(z), _DA_(r),s,o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tube_xyr_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *r, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tube_xyr(_GR_,_DA_(x),_DA_(y),_DA_(r),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tube_r_(uintptr_t *gr, uintptr_t *y, uintptr_t *r, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tube_r(_GR_,_DA_(y),_DA_(r),s,o);	delete []s;	delete []o;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tube_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, mreal *r, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tube_xyz(_GR_,_DA_(x),_DA_(y),_DA_(z),*r,s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tube_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, mreal *r, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tube_xy(_GR_,_DA_(x),_DA_(y),*r,s,o);	delete []s;	delete []o;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tube_(uintptr_t *gr, uintptr_t *y, mreal *r, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tube(_GR_,_DA_(y),*r,s,o);
+	delete []s;	delete []o;	}
+//-----------------------------------------------------------------------------
+//
+//	Tape series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tape_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, const char *pen, const char *opt)
+{
+	long m,n=y->GetNx(),pal;
+	if(mgl_check_dim1(gr,x,y,z,0,"Tape"))	return;
+
+	static int cgid=1;	gr->StartGroup("Tape",cgid++);
+	mreal ll, rr = gr->SaveState(opt);
+	if(rr==0 || mgl_isnan(rr))	rr = mgl_norm(gr->Max-gr->Min)*gr->BarWidth/25;
+	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();	m = z->GetNy() > m ? z->GetNy() : m;
+	gr->SetPenPal(pen,&pal);	gr->Reserve(4*n*m);
+	mglPoint p1,p2,q1,q2,l,nn,qn(NAN,NAN);
+	long n1=-1,n2=-1,n3=-1,n4=-1, m1=-1,m2=-1,m3=-1,m4=-1;
+	bool sh = mglchr(pen,'!'), xo = mglchr(pen,'x'), zo = mglchr(pen,'z'), wire = mglchr(pen,'#');
+	if(!xo && !zo)	xo = zo = true;
+	mreal c1,c2;
+
+	for(long j=0;j<m;j++)
+	{
+		if(gr->NeedStop())	break;
+		c2=c1=gr->NextColor(pal);
+		if(gr->GetNumPal(pal)==2*m && !sh)	c2 = gr->NextColor(pal);
+		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0, mz = j<z->GetNy() ? j:0;
+		// initial values for normales
+		p2.Set(x->v(0,mx), y->v(0,my), z->v(0,mz));
+		l.Set(x->v(1,mx)-p2.x, y->v(1,my)-p2.y, z->v(1,mz)-p2.z);	l /= mgl_norm(l);
+		q1.Set(-l.y,l.x,0);	ll = mgl_norm(q1);
+		if(ll)	q1 /= ll;	else	q1.Set(0,1,0);
+		q2 = (q1^l);
+		if(p2>gr->Min && p2<gr->Max)
+		{
+			if(xo)	{	n1 = gr->AddPnt(p2,c1,q2,-1,3);	n2 = gr->AddPnt(p2+rr*q1,c1,q2,-1,3);	}
+			if(zo)	{	n3 = gr->AddPnt(p2,c2,q1,-1,3);	n4 = gr->AddPnt(p2+rr*q2,c2,q1,-1,3);	}
+		}
+		else		{	n1=n2=n3=n4=-1;	}
+		for(long i=1;i<n;i++)
+		{
+			p1 = p2;	p2.Set(x->v(i,mx), y->v(i,my), z->v(i,mz));
+			l = p2-p1;		l /= mgl_norm(l);
+			q1 -= l*(l*q1);	q1/= mgl_norm(q1);	q2 = (q1^l);
+			m1 = n1;	m2 = n2;	m3 = n3;	m4 = n4;
+			if(sh)	c2=c1=gr->NextColor(pal,i);
+			if(p2>gr->Min && p2<gr->Max)
+			{
+				if(xo)
+				{
+					n1 = gr->AddPnt(p2,c1,wire?qn:q2,-1,3);
+					n2 = gr->AddPnt(p2+rr*q1,c1,wire?qn:q2,-1,3);
+					if(wire)	gr->line_plot(m2,n2);
+					else		gr->quad_plot(n1,n2,m1,m2);
+				}
+				if(zo)
+				{
+					n3 = gr->AddPnt(p2,c2,wire?qn:q1,-1,3);
+					n4 = gr->AddPnt(p2+rr*q2,c2,wire?qn:q1,-1,3);
+					if(wire)	gr->line_plot(m4,n4);
+					else		gr->quad_plot(n3,n4,m3,m4);
+				}
+			}
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tape_xy(HMGL gr, HCDT x, HCDT y, const char *pen, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV z(y->GetNx());	z.Fill(gr->AdjustZMin());
+	mgl_tape_xyz(gr,x,y,&z,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tape(HMGL gr, HCDT y, const char *pen, const char *opt)
+{
+	long n=y->GetNx();
+	if(n<2)	{	gr->SetWarn(mglWarnLow,"Plot");	return;	}
+	gr->SaveState(opt);
+	mglDataV x(n), z(n);
+	x.Fill(gr->Min.x,gr->Max.x);	z.Fill(gr->AdjustZMin());
+	mgl_tape_xyz(gr,&x,y,&z,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tape_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tape_xyz(_GR_, _DA_(x),_DA_(y),_DA_(z),s,o);	delete []s;	delete []o;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tape_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tape_xy(_GR_, _DA_(x),_DA_(y),s,o);	delete []s;	delete []o;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tape_(uintptr_t *gr, uintptr_t *y,	const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tape(_GR_, _DA_(y),s,o);	delete []s;	delete []o;	}
+//-----------------------------------------------------------------------------
+//
+//	Pmap series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_pmap_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT r, const char *pen, const char *opt)
+{
+	long m,n=y->GetNx(),pal;
+	if(mgl_check_dim0(gr,x,y,z,r,"Mark"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Mark",cgid++);
+	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();
+	m = z->GetNy() > m ? z->GetNy() : m;
+	char mk=gr->SetPenPal(pen,&pal);	gr->Reserve(n*m);
+	if(mk==0)	mk='.';
+
+	for(long j=0;j<m;j++)
+	{
+		if(gr->NeedStop())	break;
+		gr->NextColor(pal);
+		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
+		long mz = j<z->GetNy() ? j:0, mr = j<r->GetNy() ? j:0;
+		for(long i=0;i<n-1;i++)
+		{
+			mreal r1=r->v(i,mr), r2 = r->v(i+1,mr);
+			if(r1==0)	gr->mark_plot(gr->AddPnt(mglPoint(x->v(i,mx),y->v(i,my),z->v(i,mz))), mk);
+			if(r1*r2<0)
+			{
+				mreal d = r1/(r1-r2);
+				mglPoint p(x->v(i,mx)*(1-d)+x->v(i+1,mx)*d, y->v(i,my)*(1-d)+y->v(i+1,my)*d, z->v(i,mz)*(1-d)+d*z->v(i+1,mz));
+				gr->mark_plot(gr->AddPnt(p), mk);
+			}
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_pmap_xy(HMGL gr, HCDT x, HCDT y, HCDT r, const char *pen, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV z(y->GetNx());	z.Fill(gr->AdjustZMin());
+	mgl_pmap_xyz(gr,x,y,&z,r,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_pmap(HMGL gr, HCDT y, HCDT r, const char *pen, const char *opt)
+{
+	long n=y->GetNx();
+	gr->SaveState(opt);
+	mglDataV x(n), z(n);
+	x.Fill(gr->Min.x,gr->Max.x);	z.Fill(gr->AdjustZMin());
+	mgl_pmap_xyz(gr,&x,y,&z,r,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_pmap_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *r, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_pmap_xyz(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(r),s,o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_pmap_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *r, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_pmap_xy(_GR_, _DA_(x), _DA_(y), _DA_(r),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_pmap_(uintptr_t *gr, uintptr_t *y, uintptr_t *r, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_pmap(_GR_,_DA_(y),_DA_(r),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
diff --git a/src/prc.cpp b/src/prc.cpp
new file mode 100644
index 0000000..a351912
--- /dev/null
+++ b/src/prc.cpp
@@ -0,0 +1,991 @@
+/***************************************************************************
+ * prc.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <png.h>
+#include <stdio.h>
+#include <time.h>
+#include "mgl2/canvas.h"
+#include "mgl2/canvas_cf.h"
+
+#include "prc/oPRCFile.h"
+#include <map>
+#include <utility>
+#include <string.h>
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+
+#if MGL_HAVE_PDF
+#include <setjmp.h>
+#include <hpdf.h>
+#include <hpdf_u3d.h>
+#include <hpdf_annotation.h>
+#endif // MGL_HAVE_PDF
+
+
+#undef _GR_
+#define _GR_	((mglCanvas *)(*gr))
+#define _Gr_	((mglCanvas *)(gr))
+
+//-----------------------------------------------------------------------------
+void mglTexture::GetRGBAPRC(unsigned char *f) const
+{
+	for(size_t i=0;i<256;i++)
+	{
+		mglColor c1 = col[2*i], c2 = col[2*i+1], c;
+		for(size_t j=0;j<256;j++)
+		{
+			size_t i0 = 4*(j+256*(255-i));
+			c = c1 + (c2-c1)*(j/255.);
+			f[i0]   = int(255*c.r);
+			f[i0+1] = int(255*c.g);
+			f[i0+2] = int(255*c.b);
+			f[i0+3] = int(255*c.a);
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+int MGL_NO_EXPORT mgl_tga_save(const char *fname, int w, int h, unsigned char **p);
+int MGL_NO_EXPORT mgl_pnga_save(const char *fname, int w, int h, unsigned char **p);
+void MGL_NO_EXPORT mgl_printf(void *fp, bool gz, const char *str, ...);
+//-----------------------------------------------------------------------------
+struct prctriangle {
+	uint32_t pi[3];
+	uint32_t ti[3];
+};
+//-----------------------------------------------------------------------------
+struct prctriangles {
+	prctriangles(const HMGL g) : samecolour(true), samealpha(true),
+	gr(g), ntxt(g->GetTxtNum()), vertexcolor(g->get(MGL_PREFERVC)) {}
+	std::map<PRCVector3d,uint32_t> points;
+	std::map<PRCVector2d,uint32_t> texturecoords;
+	std::map<RGBAColour,uint32_t> colours;
+	std::vector<prctriangle> triangles;
+	RGBAColour commoncolour;
+	bool samecolour;
+	float commonalpha;
+	bool samealpha;
+	const HMGL gr;
+	const size_t ntxt;
+	bool vertexcolor;
+
+
+	uint32_t addPoint(const mglPnt& p)
+	{
+		const PRCVector3d point(p.x,p.y,p.z);
+
+		std::map<PRCVector3d,uint32_t>::iterator pPoint = points.find(point);
+		if(pPoint!=points.end())
+			return pPoint->second;
+		else
+		{
+			const uint32_t point_index = (uint32_t)points.size();
+			points.insert(std::make_pair(point,point_index));
+			return point_index;
+		}
+	}
+
+	uint32_t addPoint(float x, float y, float z)
+	{
+		const PRCVector3d point(x,y,z);
+
+		std::map<PRCVector3d,uint32_t>::iterator pPoint = points.find(point);
+		if(pPoint!=points.end())
+			return pPoint->second;
+		else
+		{
+			const uint32_t point_index = (uint32_t)points.size();
+			points.insert(std::make_pair(point,point_index));
+			return point_index;
+		}
+	}
+
+	void writePoints(double (*P)[3])
+	{
+		for(std::map<PRCVector3d,uint32_t>::const_iterator pPoint = points.begin(); pPoint != points.end(); pPoint++)
+		{
+			P[pPoint->second][0] = pPoint->first.x;
+			P[pPoint->second][1] = pPoint->first.y;
+			P[pPoint->second][2] = pPoint->first.z;
+		}
+	}
+
+	void addTriangle(uint32_t ti, uint32_t pi1, uint32_t pi2, uint32_t pi3)
+	{
+		prctriangle triangle;
+		triangle.pi[0] = pi1;
+		triangle.pi[1] = pi2;
+		triangle.pi[2] = pi3;
+		triangle.ti[0] = ti;
+		triangle.ti[1] = ti;
+		triangle.ti[2] = ti;
+		triangles.push_back(triangle);
+	}
+	void addTriangle(uint32_t pi1, uint32_t ti1, uint32_t pi2, uint32_t ti2, uint32_t pi3, uint32_t ti3)
+	{
+		prctriangle triangle;
+		triangle.pi[0] = pi1;
+		triangle.pi[1] = pi2;
+		triangle.pi[2] = pi3;
+		triangle.ti[0] = ti1;
+		triangle.ti[1] = ti2;
+		triangle.ti[2] = ti3;
+		triangles.push_back(triangle);
+	}
+	uint32_t addColourInfo(const mglPnt& p)
+	{
+		const RGBAColour colour(p.r,p.g,p.b,p.a);
+
+		if (colours.empty() && texturecoords.empty()) {
+			commoncolour = colour;
+			commonalpha = p.a;
+		}
+		if (samecolour) {
+			if (commoncolour != colour)
+				samecolour = false;
+		}
+		if (samealpha) {
+			if (commonalpha != p.a)
+				samealpha = false;
+		}
+
+		if (vertexcolor) {
+			std::map<RGBAColour,uint32_t>::iterator pColour = colours.find(colour);
+			if(pColour!=colours.end())
+				return pColour->second;
+			else
+			{
+				const uint32_t colour_index = (uint32_t)colours.size();
+				colours.insert(std::make_pair(colour,colour_index));
+				return colour_index;
+			}
+		} else {
+			const mreal gap = 1./512;
+			const double u = p.ta*(1-2*gap)+gap;
+			const double v = ((p.c-floor(p.c))*(1-2*gap) + gap + floor(p.c))/ntxt;
+
+			const PRCVector2d point(u, v);
+			std::map<PRCVector2d,uint32_t>::iterator pPoint = texturecoords.find(point);
+			if(pPoint!=texturecoords.end())
+				return pPoint->second;
+			else
+			{
+				const uint32_t point_index = (uint32_t)texturecoords.size();
+				texturecoords.insert(std::make_pair(point,point_index));
+				return point_index;
+			}
+		}
+	}
+
+	void writeTextureCoords(double (*T)[2])
+	{
+		for(std::map<PRCVector2d,uint32_t>::const_iterator pPoint = texturecoords.begin(); pPoint != texturecoords.end(); pPoint++)
+		{
+			T[pPoint->second][0] = pPoint->first.x;
+			T[pPoint->second][1] = pPoint->first.y;
+		}
+	}
+
+	void writeColours(RGBAColour *C)
+	{
+		for(std::map<RGBAColour,uint32_t>::const_iterator pColour = colours.begin(); pColour != colours.end(); pColour++)
+		{
+			C[pColour->second] = pColour->first;
+		}
+	}
+};
+
+//-----------------------------------------------------------------------------
+/* structure to store PNG image bytes */
+struct png_buf
+{
+	uint8_t *data;
+	size_t size;
+};
+//-----------------------------------------------------------------------------
+void my_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+	struct png_buf* p=(struct png_buf*)png_get_io_ptr(png_ptr);
+	size_t nsize = p->size + length;
+
+	/* allocate or grow buffer */
+	if(p->data)
+		p->data = (uint8_t*)realloc(p->data, nsize);
+	else
+		p->data = (uint8_t*)malloc(nsize);
+
+	if(!p->data)
+		png_error(png_ptr, "Write Error - no mem");
+
+	/* copy new bytes to end of buffer */
+	memcpy(p->data + p->size, data, length);
+	p->size += length;
+}
+//-----------------------------------------------------------------------------
+void my_png_flush(png_structp /*png_ptr*/)
+{
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_write_prc(HMGL gr, const char *fname,const char* /*descr*/, int make_pdf)
+{
+	if(gr->GetPrmNum()==0)	return;	// nothing to do
+	{
+		long mmin=0,mmax=0,m;
+		for(size_t i=0;i<gr->Grp.size();i++)	// prepare array of indirect indexing
+		{	m = gr->Grp[i].Id;	if(m<mmin) mmin=m;	if(m>mmax) mmax=m;	}
+		long *ng = new long[mmax-mmin+1];
+		for(size_t i=0;i<gr->Grp.size();i++)	ng[gr->Grp[i].Id-mmin] = i;
+		for(size_t i=0;i<size_t(gr->GetPrmNum());i++)	// collect data for groups
+		// it is rather expensive (extra 4b per primitive) but need for export to 3D
+		{
+			m = gr->GetPrm(i,false).id-mmin;
+			if(m>=0 && m<mmax-mmin+1)	gr->Grp[ng[m]].p.push_back(i);
+		}
+		delete []ng;
+	}
+	const size_t len=strlen(fname);
+	char * const tname = new char[len+9];	strcpy(tname,fname);
+	if (strncmp(tname+len-4, ".prc", 4)!=0)
+	{
+		tname[len]='.';	tname[len+1]='p';	tname[len+2]='r';	tname[len+3]='c'; tname[len+4]='\0';
+	}
+	oPRCFile file(tname);
+	PRCoptions grpopt;
+	grpopt.tess = true;
+	grpopt.closed = gr->get(MGL_ONESIDED); // set to true to make only front side visible
+	// grpopt.no_break = true;
+	// grpopt.do_break = false;
+	grpopt.crease_angle = 80;
+
+	uint32_t materialMathGLid = m1;
+	if (gr->get(MGL_PREFERVC)) {
+		const PRCmaterial materialMathGL(
+			RGBAColour(0.1,0.1,0.1,1), // ambient
+			RGBAColour(1.0,1.0,1.0,1), // diffuse
+			RGBAColour(0.1,0.1,0.1,1), // emissive
+			RGBAColour(0.0,0.0,0.0,1), // spectral
+			1.0,0.1 // alpha, shininess
+			);
+		materialMathGLid = file.addMaterial(materialMathGL);
+	}
+	else
+	{
+		png_buf buffer;
+		buffer.data = (uint8_t*)malloc(1024);;
+		buffer.size = 0;
+		const size_t ntxt = gr->GetTxtNum();
+
+		// prepare texture file (PNG)
+		const png_uint_32 width=256, height=256*png_uint_32(ntxt);
+		png_bytep buf = new png_byte[4*width*height];
+		png_bytepp pbuf= new png_bytep[height];
+		for(size_t i=0;i<height;i++)
+			pbuf[i] = buf+4*width*i;
+		for(size_t i=0;i<ntxt;i++)
+			gr->GetTxt(i).GetRGBAPRC(buf+(ntxt-1-i)*256*width*4);
+
+		png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0);
+		png_infop info_ptr = png_create_info_struct(png_ptr);
+
+		png_set_write_fn(png_ptr, &buffer, my_png_write_data, my_png_flush);
+		png_set_filter(png_ptr, 0, PNG_ALL_FILTERS);
+		png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
+		png_set_IHDR(png_ptr, info_ptr, width, height, 8,
+				PNG_COLOR_TYPE_RGB_ALPHA,
+				PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
+				PNG_FILTER_TYPE_DEFAULT);
+		png_set_rows(png_ptr, info_ptr, pbuf);
+		png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, 0);
+		png_write_end(png_ptr, info_ptr);
+
+		png_destroy_write_struct(&png_ptr, &info_ptr);
+		delete []pbuf;	delete []buf;
+
+		PRCtexture* t = new PRCtexture();
+		t->mapping = PRC_TEXTURE_MAPPING_DIFFUSE;
+		t->components = PRC_TEXTURE_MAPPING_COMPONENTS_RGBA;
+		// Modulate for OBJ compatibilty, Replace is a better setting
+		t->function = KEPRCTextureFunction_Replace;
+		// Repeat for OBJ compatibilty, ClampToEdge is a better setting
+		t->wrapping_mode_S = KEPRCTextureWrappingMode_ClampToEdge;
+		t->wrapping_mode_T = KEPRCTextureWrappingMode_ClampToEdge;
+		t->data = buffer.data;
+		t->size	= buffer.size;
+		t->format = KEPRCPicture_PNG;
+
+		PRCmaterial m(
+									RGBAColour(0.0,0.0,0.0,1), // ambient
+									RGBAColour(1.0,1.0,1.0,1), // diffuse
+									RGBAColour(0.0,0.0,0.0,1), // emissive
+									RGBAColour(0.0,0.0,0.0,1), // spectral
+									1.0,0.1); // alpha, shininess
+
+		materialMathGLid = file.addTexturedMaterial(m,1,&t);
+		delete t;
+
+		// char * const pngname = new char[len+100];
+		// strcpy(pngname, "test_texture_");
+		// strcat(pngname,tname);
+		// const size_t tlen=strlen(pngname)-4;
+		// pngname[tlen+1]='p';	pngname[tlen+2]='n';	pngname[tlen+3]='g';
+		// FILE *fp = fopen(pngname, "wb");
+		// fwrite(buffer.data, 1, buffer.size, fp);
+		// fclose(fp);
+		// delete[] pngname;
+
+		free(buffer.data); buffer.data = NULL;
+	}
+
+	// primitive definition in groups
+
+	mglPnt p0;
+	const double width  = dynamic_cast<mglCanvas *>(gr)->GetWidth();
+	const double height = dynamic_cast<mglCanvas *>(gr)->GetHeight();
+	const double depth  = sqrt(width*height);
+
+	p0.x = width/2.;
+	p0.y = height/2.;
+	p0.z = (1.f-sqrt(width*height)/(2*depth))*depth;
+
+	for(size_t i=0;i<gr->Grp.size();i++)
+	{
+		mglGroup& grp = gr->Grp[i];
+		std::vector<long>& prm = grp.p;
+		prctriangles group(gr);
+		file.begingroup(grp.Lbl.c_str(),&grpopt);
+		for(size_t j=0;j<prm.size();j++)
+		{
+			const mglPrim &q=gr->GetPrm(prm[j],false);
+			const double w = (q.w>1)?(q.w*sqrt(gr->FontFactor()/400.)):1;
+
+			const mglPnt p = gr->GetPnt(q.n1) - p0;
+			const mreal size = q.s;
+			{
+				switch(q.type)
+				{
+					case 0:
+					if (gr->GetPnt(q.n1).a > mgl_min_a) {
+						const char type = q.n4;
+						float ss=size;
+						const RGBAColour c(p.r, p.g, p.b, p.a);
+
+						if(!strchr("xsSoO",type))	ss *= 1.1;
+						if(type=='.' || ss==0)
+						{
+							const double P[3] = {p.x, p.y, p.z};
+							file.addPoint(P, c, w);
+						}
+						else
+							switch(type)
+							{
+								case 'P':
+								{
+									const double P[5][3] =
+									{
+										{ p.x-ss,p.y-ss,p.z },
+										{ p.x+ss,p.y-ss,p.z },
+										{ p.x+ss,p.y+ss,p.z },
+										{ p.x-ss,p.y+ss,p.z },
+										{ p.x-ss,p.y-ss,p.z }
+									};
+									file.addLine(5, P, c, w);
+								}
+								case '+':
+								{
+									const double P1[2][3] =
+									{
+										{ p.x-ss,p.y,p.z },
+										{ p.x+ss,p.y,p.z }
+									};
+									file.addLine(2, P1, c, w);
+									const double P2[2][3] =
+									{
+										{ p.x,p.y-ss,p.z },
+										{ p.x,p.y+ss,p.z }
+									};
+									file.addLine(2, P2, c, w);
+								}
+								break;
+								case 'X':
+								{
+									const double P[5][3] =
+									{
+										{ p.x-ss,p.y-ss,p.z },
+										{ p.x+ss,p.y-ss,p.z },
+										{ p.x+ss,p.y+ss,p.z },
+										{ p.x-ss,p.y+ss,p.z },
+										{ p.x-ss,p.y-ss,p.z }
+									};
+									file.addLine(5, P, c, w);
+									const double P1[2][3] =
+									{
+										{ p.x-ss,p.y-ss,p.z },
+										{ p.x+ss,p.y+ss,p.z }
+									};
+									file.addLine(2, P1, c, w);
+									const double P2[2][3] =
+									{
+										{ p.x+ss,p.y-ss,p.z },
+										{ p.x-ss,p.y+ss,p.z }
+									};
+									file.addLine(2, P2, c, w);
+								}
+								break;
+								case 'x':
+								{
+									const double P1[2][3] =
+									{
+										{ p.x-ss,p.y-ss,p.z },
+										{ p.x+ss,p.y+ss,p.z }
+									};
+									file.addLine(2, P1, c, w);
+									const double P2[2][3] =
+									{
+										{ p.x+ss,p.y-ss,p.z },
+										{ p.x-ss,p.y+ss,p.z }
+									};
+									file.addLine(2, P2, c, w);
+								}
+								break;
+								case 'S':
+								{
+									const uint32_t ti = group.addColourInfo(p);
+
+									const uint32_t pi1 = group.addPoint(p.x-ss,p.y-ss,p.z);
+									const uint32_t pi2 = group.addPoint(p.x+ss,p.y-ss,p.z);
+									const uint32_t pi3 = group.addPoint(p.x-ss,p.y+ss,p.z);
+									const uint32_t pi4 = group.addPoint(p.x+ss,p.y+ss,p.z);
+
+									group.addTriangle(ti, pi1, pi2, pi3);
+									group.addTriangle(ti, pi4, pi3, pi2);
+								}
+								break;
+								case 's':
+								{
+									const double P[5][3] =
+									{
+										{ p.x-ss,p.y-ss,p.z },
+										{ p.x+ss,p.y-ss,p.z },
+										{ p.x+ss,p.y+ss,p.z },
+										{ p.x-ss,p.y+ss,p.z },
+										{ p.x-ss,p.y-ss,p.z }
+									};
+									file.addLine(5, P, c, w);
+								}
+								break;
+								case 'D':
+								{
+									const uint32_t ti = group.addColourInfo(p);
+
+									const uint32_t pi1 = group.addPoint(p.x,p.y-ss,p.z);
+									const uint32_t pi2 = group.addPoint(p.x+ss,p.y,p.z);
+									const uint32_t pi3 = group.addPoint(p.x-ss,p.y,p.z);
+									const uint32_t pi4 = group.addPoint(p.x,p.y+ss,p.z);
+
+									group.addTriangle(ti, pi1, pi2, pi3);
+									group.addTriangle(ti, pi4, pi3, pi2);
+								}
+								break;
+								case 'd':
+								{
+									const double P[5][3] =
+									{
+										{ p.x,p.y-ss,p.z },
+										{ p.x+ss,p.y,p.z },
+										{ p.x,p.y+ss,p.z },
+										{ p.x-ss,p.y,p.z },
+										{ p.x,p.y-ss,p.z }
+									};
+									file.addLine(5, P, c, w);
+								}
+								break;
+								case 'Y':
+								{
+									const double P1[3][3] =
+									{
+										{ p.x,			 p.y-ss,		p.z },
+										{ p.x,			 p.y,			 p.z },
+										{ p.x+0.8*ss,p.y+0.6*ss,p.z }
+									};
+									file.addLine(3, P1, c, w);
+									const double P2[2][3] =
+									{
+										{ p.x,			 p.y,			 p.z },
+										{ p.x-0.8*ss,p.y+0.6*ss,p.z }
+									};
+									file.addLine(2, P2, c, w);
+								}
+								break;
+								case '*':
+								{
+									const double P1[2][3] =
+									{
+										{ p.x-ss,p.y,p.z },
+										{ p.x+ss,p.y,p.z }
+									};
+									file.addLine(2, P1, c, w);
+									const double P2[2][3] =
+									{
+										{ p.x-0.6*ss,p.y-0.8*ss,p.z },
+										{ p.x+0.6*ss,p.y+0.8*ss,p.z }
+									};
+									file.addLine(2, P2, c, w);
+									const double P3[2][3] =
+									{
+										{ p.x-0.6*ss,p.y+0.8*ss,p.z },
+										{ p.x+0.6*ss,p.y-0.8*ss,p.z }
+									};
+									file.addLine(2, P3, c, w);
+
+								}
+								break;
+								case 'T':
+								{
+									const uint32_t ti = group.addColourInfo(p);
+
+									const uint32_t pi1 = group.addPoint(p.x-ss,p.y-ss/2,p.z);
+									const uint32_t pi2 = group.addPoint(p.x+ss,p.y-ss/2,p.z);
+									const uint32_t pi3 = group.addPoint(p.x,p.y+ss,p.z);
+
+									group.addTriangle(ti, pi1, pi2, pi3);
+								}
+								break;
+								case '^':
+								{
+									const double P[4][3] =
+									{
+										{ p.x-ss,p.y-ss/2,p.z },
+										{ p.x+ss,p.y-ss/2,p.z },
+										{ p.x,	 p.y+ss,	p.z },
+										{ p.x-ss,p.y-ss/2,p.z }
+									};
+									file.addLine(4, P, c, w);
+								}
+								break;
+								case 'V':
+								{
+									const uint32_t ti = group.addColourInfo(p);
+
+									const uint32_t pi1 = group.addPoint(p.x-ss,p.y+ss/2,p.z);
+									const uint32_t pi2 = group.addPoint(p.x,p.y-ss,p.z);
+									const uint32_t pi3 = group.addPoint(p.x+ss,p.y+ss/2,p.z);
+
+									group.addTriangle(ti, pi1, pi2, pi3);
+								}
+								break;
+								case 'v':
+								{
+									const double P[4][3] =
+									{
+										{ p.x-ss,p.y+ss/2,p.z },
+										{ p.x+ss,p.y+ss/2,p.z },
+										{ p.x,	 p.y-ss,	p.z },
+										{ p.x-ss,p.y+ss/2,p.z }
+									};
+									file.addLine(4, P, c, w);
+								}
+								break;
+								case 'L':
+								{
+									const uint32_t ti = group.addColourInfo(p);
+
+									const uint32_t pi1 = group.addPoint(p.x+ss/2,p.y+ss,p.z);
+									const uint32_t pi2 = group.addPoint(p.x-ss,	p.y,	 p.z);
+									const uint32_t pi3 = group.addPoint(p.x+ss/2,p.y-ss,p.z);
+
+									group.addTriangle(ti, pi1, pi2, pi3);
+								}
+								break;
+								case '<':
+								{
+									const double P[4][3] =
+									{
+										{ p.x+ss/2,p.y+ss,p.z },
+										{ p.x+ss/2,p.y-ss,p.z },
+										{ p.x-ss,	p.y,	 p.z },
+										{ p.x+ss/2,p.y+ss,p.z }
+									};
+									file.addLine(4, P, c, w);
+								}
+								break;
+								case 'R':
+								{
+									const uint32_t ti = group.addColourInfo(p);
+
+									const uint32_t pi1 = group.addPoint(p.x-ss/2,p.y+ss,p.z);
+									const uint32_t pi2 = group.addPoint(p.x-ss/2,p.y-ss,p.z);
+									const uint32_t pi3 = group.addPoint(p.x+ss,	p.y,	 p.z);
+
+									group.addTriangle(ti, pi1, pi2, pi3);
+								}
+								break;
+								case '>':
+								{
+									const double P[4][3] =
+									{
+										{ p.x-ss/2,p.y+ss,p.z },
+										{ p.x-ss/2,p.y-ss,p.z },
+										{ p.x+ss,	p.y,	 p.z },
+										{ p.x-ss/2,p.y+ss,p.z }
+									};
+									file.addLine(4, P, c, w);
+								}
+								break;
+								case 'O':
+								{
+									const uint32_t ti = group.addColourInfo(p);
+
+									const uint32_t cpi=group.addPoint(p);
+									uint32_t pnti[21];
+									for(size_t k=0;k<=20;k++)
+										pnti[k]=group.addPoint(p.x+ss*cos(k*M_PI/10),p.y+ss*sin(k*M_PI/10),p.z);
+									for(size_t k=0;k<20;k++) {
+										group.addTriangle(ti, pnti[k], pnti[k+1], cpi);
+									}
+								}
+								break;
+								case 'C':
+								{
+									const double P[3] = {p.x, p.y, p.z};
+									file.addPoint(P, c, w);
+								}
+								case 'o':
+								{
+									double P[21][3];
+									for(size_t k=0;k<=20;k++) {
+										P[k][0] = p.x+ss*cos(k*M_PI/10);
+										P[k][1] = p.y+ss*sin(k*M_PI/10);
+										P[k][2] = p.z;
+									}
+									file.addLine(21, P, c, w);
+								}
+								break;
+						}
+					}
+					break;
+
+					case 1:
+					if (gr->GetPnt(q.n1).a > mgl_min_a || gr->GetPnt(q.n2).a > mgl_min_a) {
+						const mglPnt p1 = gr->GetPnt(q.n1) - p0, p2 = gr->GetPnt(q.n2) - p0;
+
+						const uint32_t n = 2;
+						double P[2][3];
+						P[0][0] = p1.x;
+						P[0][1] = p1.y;
+						P[0][2] = p1.z;
+						P[1][0] = p2.x;
+						P[1][1] = p2.y;
+						P[1][2] = p2.z;
+						const RGBAColour colour((p1.r+p2.r)/2, (p1.g+p2.g)/2, (p1.b+p2.b)/2, (p1.a+p2.a)/2);
+						file.addLine(n, P, colour, w);
+					}
+					break;
+
+					case 2:
+					if (gr->GetPnt(q.n1).a > mgl_min_a || gr->GetPnt(q.n2).a > mgl_min_a || gr->GetPnt(q.n3).a > mgl_min_a) {
+						const mglPnt p1 = gr->GetPnt(q.n1)	- p0, p2 = gr->GetPnt(q.n2) - p0, p3 = gr->GetPnt(q.n3) - p0;
+
+						prctriangle triangle;
+						triangle.pi[0] = group.addPoint(p1);
+						triangle.pi[1] = group.addPoint(p2);
+						triangle.pi[2] = group.addPoint(p3);
+						triangle.ti[0] = group.addColourInfo(p1);
+						triangle.ti[1] = group.addColourInfo(p2);
+						triangle.ti[2] = group.addColourInfo(p3);
+						group.triangles.push_back(triangle);
+					}
+					break;
+					case 3:
+					if (gr->GetPnt(q.n1).a > mgl_min_a || gr->GetPnt(q.n2).a > mgl_min_a || gr->GetPnt(q.n3).a > mgl_min_a || gr->GetPnt(q.n4).a > mgl_min_a) {
+						const mglPnt p1 = gr->GetPnt(q.n1) - p0;
+						const uint32_t pi1 = group.addPoint(p1);
+						const uint32_t ti1 = group.addColourInfo(p1);
+
+						const mglPnt p2 = gr->GetPnt(q.n2) - p0;
+						const uint32_t pi2 = group.addPoint(p2);
+						const uint32_t ti2 = group.addColourInfo(p2);
+
+						const mglPnt p3 = gr->GetPnt(q.n3) - p0;
+						const uint32_t pi3 = group.addPoint(p3);
+						const uint32_t ti3 = group.addColourInfo(p3);
+
+						const mglPnt p4 = gr->GetPnt(q.n4) - p0;
+						const uint32_t pi4 = group.addPoint(p4);
+						const uint32_t ti4 = group.addColourInfo(p4);
+
+						prctriangle triangle1, triangle2;
+						triangle1.pi[0] = pi1;
+						triangle1.pi[1] = pi2;
+						triangle1.pi[2] = pi3;
+						triangle1.ti[0] = ti1;
+						triangle1.ti[1] = ti2;
+						triangle1.ti[2] = ti3;
+						group.triangles.push_back(triangle1);
+						triangle2.pi[0] = pi4;
+						triangle2.pi[1] = pi3;
+						triangle2.pi[2] = pi2;
+						triangle2.ti[0] = ti4;
+						triangle2.ti[1] = ti3;
+						triangle2.ti[2] = ti2;
+						group.triangles.push_back(triangle2);
+					}
+					break;
+					case 4:
+					if (gr->GetPnt(q.n1).a > mgl_min_a) {
+						const mglPnt p = gr->GetPnt(q.n1) - p0;
+
+						const mreal f = q.p/2, dx=p.u/2, dy=p.v/2;
+						const mreal c=q.s*cos(q.w*M_PI/180), s=-q.s*sin(q.w*M_PI/180);
+						const double b[4] = {c,-s, s,c};
+						long ik,il=0;
+
+						const mglGlyph &g = gr->GetGlf(q.n4);
+						const mreal dd = 0.004;
+						if(q.n3&8)
+						{
+							if(!(q.n3&4))	// glyph_line(p,f,true, d);
+							{
+								const uint32_t ti = group.addColourInfo(p);
+								const uint32_t p_4 = group.addPoint(p.x+b[0]*dx+b[1]*(dy-dd),p.y+b[2]*dx+b[3]*(dy-dd),p.z);
+								const uint32_t p_3 = group.addPoint(p.x+b[0]*dx+b[1]*(dy+dd),p.y+b[2]*dx+b[3]*(dy+dd),p.z);
+								const uint32_t p_2 = group.addPoint(p.x+b[0]*(dx+f)+b[1]*(dy-dd),p.y+b[2]*dx+b[3]*(dy-dd),p.z);
+								const uint32_t p_1 = group.addPoint(p.x+b[0]*(dx+f)+b[1]*(dy+dd),p.y+b[2]*dx+b[3]*(dy+dd),p.z);
+
+								group.addTriangle(ti, p_1, p_3, p_2);
+								group.addTriangle(ti, p_4, p_2, p_3);
+							}
+							else	// glyph_line(p,f,false, d);
+							{
+								const RGBAColour c(p.r, p.g, p.b, p.a);
+								const double p_4[3] = {p.x+b[0]*dx+b[1]*(dy-dd),p.y+b[2]*dx+b[3]*(dy-dd),p.z};
+								const double p_3[3] = {p.x+b[0]*dx+b[1]*(dy+dd),p.y+b[2]*dx+b[3]*(dy+dd),p.z};
+								const double p_2[3] = {p.x+b[0]*(dx+f)+b[1]*(dy-dd),p.y+b[2]*dx+b[3]*(dy-dd),p.z};
+								const double p_1[3] = {p.x+b[0]*(dx+f)+b[1]*(dy+dd),p.y+b[2]*dx+b[3]*(dy+dd),p.z};
+
+								file.addSegment(p_1, p_2, c, w);
+								file.addSegment(p_3, p_4, c, w);
+								file.addSegment(p_1, p_3, c, w);
+								file.addSegment(p_2, p_4, c, w);
+							}
+						}
+						else
+						{
+							if(!(q.n3&4))	// glyph_fill(p,f,g, d);
+							{
+								for(ik=0;ik<g.nt;ik++)
+								{
+									const uint32_t ti = group.addColourInfo(p);
+									mreal x,y;
+									x = dx+f*g.trig[6*ik];		y = dy+f*g.trig[6*ik+1];
+									const uint32_t p_3 = group.addPoint(p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
+									x = dx+f*g.trig[6*ik+2];	y = dy+f*g.trig[6*ik+3];
+									const uint32_t p_2 = group.addPoint(p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
+									x = dx+f*g.trig[6*ik+4];	y = dy+f*g.trig[6*ik+5];
+									const uint32_t p_1 = group.addPoint(p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z);
+
+									group.addTriangle(ti, p_1, p_3, p_2);
+								}
+							}
+							else	// glyph_wire(p,f,g, d);
+							{
+								const RGBAColour c(p.r, p.g, p.b, p.a);
+								for(ik=0;ik<g.nl;ik++)
+								{
+									mreal x,y;
+									x = g.line[2*ik];	y = g.line[2*ik+1];
+									if(x==0x3fff && y==0x3fff)	// line breakthrough
+									{	il = ik+1;	continue;	}
+									else if(ik==g.nl-1 || (g.line[2*ik+2]==0x3fff && g.line[2*ik+3]==0x3fff))
+									{	// enclose the circle. May be in future this block should be commented
+										x = dx+f*g.line[2*ik];		y = dy+f*g.line[2*ik+1];
+										const double p_2[3] = {p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z};
+										x = dx+f*g.line[2*il];		y = dy+f*g.line[2*il+1];
+										const double p_1[3] = {p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z};
+										file.addSegment(p_1, p_2, c, w);
+									}
+									else
+									{	// normal line
+										x = dx+f*g.line[2*ik];		y = dy+f*g.line[2*ik+1];
+										const double p_2[3] = {p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z};
+										x = dx+f*g.line[2*ik+2];	y = dy+f*g.line[2*ik+3];
+										const double p_1[3] = {p.x+b[0]*x+b[1]*y,p.y+b[2]*x+b[3]*y,p.z};
+										file.addSegment(p_1, p_2, c, w);
+									}
+
+								}
+							}
+						}
+
+					}
+						break;
+
+				}
+			}
+		}
+		if (!group.triangles.empty()) {
+			const uint32_t nP = (uint32_t)group.points.size();
+			double (*P)[3] = new double[nP][3];
+			group.writePoints(P);
+			const uint32_t nI = (uint32_t)group.triangles.size();
+			uint32_t (*PI)[3] = new uint32_t[nI][3];
+			for(uint32_t k = 0; k<nI; k++)
+			{
+				PI[k][0] = group.triangles[k].pi[0];
+				PI[k][1] = group.triangles[k].pi[1];
+				PI[k][2] = group.triangles[k].pi[2];
+			}
+			if (!group.samecolour) {
+				if (gr->get(MGL_PREFERVC)) {
+					const uint32_t nC = (uint32_t)group.colours.size();
+					RGBAColour *C = new RGBAColour[nC];
+					group.writeColours(C);
+					uint32_t (*CI)[3] = new uint32_t[nI][3];
+					for(uint32_t k = 0; k<nI; k++)
+					{
+						CI[k][0] = group.triangles[k].ti[0];
+						CI[k][1] = group.triangles[k].ti[1];
+						CI[k][2] = group.triangles[k].ti[2];
+					}
+					const uint32_t tess_index = file.createTriangleMesh(nP, P, nI, PI, m1, 0, NULL, NULL, 0, NULL, NULL, nC, C, CI, 0, NULL, NULL, grpopt.crease_angle);
+					uint32_t materialid = materialMathGLid;
+					if (group.samealpha) { // workaround for transparency ignored in vertex colors, may not work in OpenGL
+						const double a = group.commonalpha;
+						const PRCmaterial materialTransparent(
+							RGBAColour(0.1,0.1,0.1,a), // ambient
+							RGBAColour(1.0,1.0,1.0,a), // diffuse
+							RGBAColour(0.1,0.1,0.1,a), // emissive
+							RGBAColour(0.0,0.0,0.0,a), // spectral
+							a,0.1 // alpha, shininess
+							);
+						materialid = file.addMaterial(materialTransparent);
+					}
+					file.useMesh(tess_index, materialid);
+					delete [] CI;
+					delete [] C;
+				} else {
+					const uint32_t nT = (uint32_t)group.texturecoords.size();
+					double (*T)[2] = new double[nT][2];
+					group.writeTextureCoords(T);
+					uint32_t (*TI)[3] = new uint32_t[nI][3];
+					for(uint32_t k = 0; k<nI; k++)
+					{
+						TI[k][0] = group.triangles[k].ti[0];
+						TI[k][1] = group.triangles[k].ti[1];
+						TI[k][2] = group.triangles[k].ti[2];
+					}
+					const uint32_t tess_index = file.createTriangleMesh(nP, P, nI, PI, m1, 0, NULL, NULL, nT, T, TI, 0, NULL, NULL, 0, NULL, NULL, grpopt.crease_angle);
+					file.useMesh(tess_index, materialMathGLid);
+					delete [] TI;
+					delete [] T;
+				}
+			} else {
+				const uint32_t tess_index = file.createTriangleMesh(nP, P, nI, PI, m1, 0, NULL, NULL, 0, NULL, NULL, 0, NULL, NULL, 0, NULL, NULL, grpopt.crease_angle);
+
+				const PRCmaterial material(
+					RGBAColour(0.1,0.1,0.1,1), // ambient
+					group.commoncolour,        // diffuse
+					RGBAColour(0.1,0.1,0.1,1), // emissive
+					RGBAColour(0.0,0.0,0.0,1), // spectral
+					group.commoncolour.A,0.1); // alpha, shininess
+				file.useMesh(tess_index, file.addMaterial(material));
+			}
+			delete [] PI;
+			delete [] P;
+		}
+		file.endgroup();
+		prm.clear();	// we don't need indexes anymore
+	}
+	file.finish();
+
+	if (make_pdf) {
+#if MGL_HAVE_PDF
+//		const HPDF_REAL width  = dynamic_cast<mglCanvas *>(gr)->GetWidth();
+//		const HPDF_REAL height = dynamic_cast<mglCanvas *>(gr)->GetHeight();
+//		const HPDF_REAL depth  = sqrt(width*height);
+
+		const HPDF_Rect rect = {0, 0, HPDF_REAL(width), HPDF_REAL(height)};
+
+		HPDF_Doc	pdf;
+		HPDF_Page page;
+		HPDF_Annotation annot;
+		HPDF_U3D u3d;
+
+		HPDF_Dict view;
+		pdf = HPDF_New (NULL, NULL);
+
+		pdf->pdf_version = HPDF_VER_17;
+
+		page = HPDF_AddPage (pdf);
+
+		HPDF_Page_SetWidth (page, width);
+		HPDF_Page_SetHeight (page, height);
+
+		u3d = HPDF_LoadU3DFromFile (pdf, tname);
+
+		//	Default view
+		view = HPDF_Create3DView (u3d->mmgr, "DefaultView");
+
+		//	Position camera
+		HPDF_3DView_SetCamera (view, 0, 0, 0, 0, 0, 1, depth, 0);
+
+		//	Set ortho projection
+		HPDF_3DView_SetOrthogonalProjection (view, 1);
+
+		//	Background color
+		HPDF_3DView_SetBackgroundColor (view, 0.9, 0.9, 0.9);
+
+		//	Lighting
+		HPDF_3DView_SetLighting (view, "CAD");
+
+		//	Add views
+		HPDF_U3D_Add3DView (u3d, view);
+		HPDF_U3D_SetDefault3DView(u3d, "DefaultView");
+
+		//	Create annotation
+		annot = HPDF_Page_Create3DAnnot (page, rect, u3d );
+
+		//  Enable toolbar
+		HPDF_Dict action = (HPDF_Dict)HPDF_Dict_GetItem (annot, "3DA", HPDF_OCLASS_DICT);
+		HPDF_Dict_AddBoolean (action, "TB", HPDF_TRUE);
+
+		/* save the document to a file */
+		const size_t tlen = strlen(tname);
+		tname[tlen-2]='p';	tname[tlen-2]='d';	tname[tlen-1]='f';
+		HPDF_SaveToFile (pdf, tname);
+
+		/* clean up */
+		HPDF_Free (pdf);
+#else
+		const size_t tlen = strlen(tname);
+		tname[tlen-2]='p';	tname[tlen-2]='d';	tname[tlen-1]='f';
+		tname[tlen+0]='.';	tname[tlen+1]='t';	tname[tlen+2]='x';	tname[tlen+3]='t'; tname[tlen+4]='\0';
+		FILE *fp=fopen(tname,"wt");
+		fputs("Can not produce PDF file, MathGL compiled without PDF output support\n", fp);
+		fclose(fp);
+		mgl_set_global_warn(_("PDF support was disabled. Please, enable it and rebuild MathGL."));
+#endif // MGL_HAVE_PDF
+	}
+	delete []tname;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_write_prc_(uintptr_t *gr, const char *fname,const char *descr, int *make_pdf,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,descr,n);	f[n]=0;
+	mgl_write_prc(_GR_,s,f,*make_pdf);	delete []s;		delete []f;	}
+//-----------------------------------------------------------------------------
diff --git a/src/prc/PRC.h b/src/prc/PRC.h
new file mode 100644
index 0000000..2cfb92f
--- /dev/null
+++ b/src/prc/PRC.h
@@ -0,0 +1,516 @@
+#ifndef __PRC_H
+#define __PRC_H
+
+#ifdef _MSC_VER
+#if _MSC_VER >= 1600
+#include <stdint.h>
+#else
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed long int32_t;
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned long uint32_t;
+#endif // _MSC_VER >= 1600
+#elif defined __BORLANDC__
+#include <stdint.h>
+#else
+#include <inttypes.h>
+#endif // _MSC_VER
+
+#include<mgl2/define.h>
+
+//const uint32_t PRCVersion=7094;   // For Adobe Reader 8 or later
+const uint32_t PRCVersion=8137; // For Adobe Reader 9 or later
+
+// from Adobe's documentation
+
+#define PRC_TYPE_Unknown			( (uint32_t)-1 )
+
+#define PRC_TYPE_ROOT				0			// This type does not correspond to any entity
+
+#define PRC_TYPE_ROOT_PRCBase			( PRC_TYPE_ROOT + 1 )	// Abstract root type for any PRC entity. 
+#define PRC_TYPE_ROOT_PRCBaseWithGraphics	( PRC_TYPE_ROOT + 2 )	// Abstract root type for any PRC entity which can bear graphics. 
+
+#define PRC_TYPE_CRV				( PRC_TYPE_ROOT + 10 )	// Types for PRC geometrical curves
+#define PRC_TYPE_SURF				( PRC_TYPE_ROOT + 75 )	// Types for PRC geometrical surfaces
+#define PRC_TYPE_TOPO				( PRC_TYPE_ROOT + 140 )	// Types for PRC topology
+#define PRC_TYPE_TESS				( PRC_TYPE_ROOT + 170 )	// Types for PRC tessellation
+#define PRC_TYPE_MISC				( PRC_TYPE_ROOT + 200 )	// Types for PRC global data
+#define PRC_TYPE_RI				( PRC_TYPE_ROOT + 230 )	// Types for PRC representation items
+#define PRC_TYPE_ASM				( PRC_TYPE_ROOT + 300 )	// Types for PRC assembly
+#define PRC_TYPE_MKP				( PRC_TYPE_ROOT + 500 )	// Types for PRC markup
+#define PRC_TYPE_GRAPH				( PRC_TYPE_ROOT + 700 )	// Types for PRC graphics
+#define PRC_TYPE_MATH				( PRC_TYPE_ROOT + 900 )	// Types for PRC mathematical operators
+
+#define PRC_TYPE_CRV_Base			( PRC_TYPE_CRV + 1 )	// Abstract type for all geometric curves. 
+#define PRC_TYPE_CRV_Blend02Boundary		( PRC_TYPE_CRV + 2 )	// Boundary Curve. 
+#define PRC_TYPE_CRV_NURBS			( PRC_TYPE_CRV + 3 )	// Non Uniform BSpline curve. 
+#define PRC_TYPE_CRV_Circle			( PRC_TYPE_CRV + 4 )	// Circle. 
+#define PRC_TYPE_CRV_Composite			( PRC_TYPE_CRV + 5 )	// Array of oriented curves. 
+#define PRC_TYPE_CRV_OnSurf			( PRC_TYPE_CRV + 6 )	// Curve defined by a UV curve on a surface. 
+#define PRC_TYPE_CRV_Ellipse			( PRC_TYPE_CRV + 7 )	// Ellipse. 
+#define PRC_TYPE_CRV_Equation			( PRC_TYPE_CRV + 8 )	// curve described by specific law elements 
+#define PRC_TYPE_CRV_Helix			( PRC_TYPE_CRV + 9 )	// Helix curve. 
+#define PRC_TYPE_CRV_Hyperbola			( PRC_TYPE_CRV + 10 )	// Hyperbola. 
+#define PRC_TYPE_CRV_Intersection		( PRC_TYPE_CRV + 11 )	// Intersection between 2 surfaces. 
+#define PRC_TYPE_CRV_Line			( PRC_TYPE_CRV + 12 )	// Line. 
+#define PRC_TYPE_CRV_Offset			( PRC_TYPE_CRV + 13 )	// Offset curve. 
+#define PRC_TYPE_CRV_Parabola			( PRC_TYPE_CRV + 14 )	// Parabola. 
+#define PRC_TYPE_CRV_PolyLine			( PRC_TYPE_CRV + 15 )	// Polyedric curve. 
+#define PRC_TYPE_CRV_Transform			( PRC_TYPE_CRV + 16 )	// Transformed curve. 
+
+#define PRC_TYPE_SURF_Base			( PRC_TYPE_SURF + 1 )	// Abstract type for all geometric surfaces. 
+#define PRC_TYPE_SURF_Blend01			( PRC_TYPE_SURF + 2 )	// Blend surface. 
+#define PRC_TYPE_SURF_Blend02			( PRC_TYPE_SURF + 3 )	// Blend Surface. 
+#define PRC_TYPE_SURF_Blend03			( PRC_TYPE_SURF + 4 )	// Blend Surface. 
+#define PRC_TYPE_SURF_NURBS			( PRC_TYPE_SURF + 5 )	// Non Uniform BSpline surface. 
+#define PRC_TYPE_SURF_Cone			( PRC_TYPE_SURF + 6 )	// Cone. 
+#define PRC_TYPE_SURF_Cylinder			( PRC_TYPE_SURF + 7 )	// Cylinder. 
+#define PRC_TYPE_SURF_Cylindrical		( PRC_TYPE_SURF + 8 )	// Surface who is defined in cylindrical space. 
+#define PRC_TYPE_SURF_Offset			( PRC_TYPE_SURF + 9 )	// Offset surface. 
+#define PRC_TYPE_SURF_Pipe			( PRC_TYPE_SURF + 10 )	// Pipe. 
+#define PRC_TYPE_SURF_Plane			( PRC_TYPE_SURF + 11 )	// Plane. 
+#define PRC_TYPE_SURF_Ruled			( PRC_TYPE_SURF + 12 )	// Ruled surface. 
+#define PRC_TYPE_SURF_Sphere			( PRC_TYPE_SURF + 13 )	// Sphere. 
+#define PRC_TYPE_SURF_Revolution		( PRC_TYPE_SURF + 14 )	// Surface of revolution. 
+#define PRC_TYPE_SURF_Extrusion			( PRC_TYPE_SURF + 15 )	// Surface of extrusion. 
+#define PRC_TYPE_SURF_FromCurves		( PRC_TYPE_SURF + 16 )	// Surface from two curves. 
+#define PRC_TYPE_SURF_Torus			( PRC_TYPE_SURF + 17 )	// Torus. 
+#define PRC_TYPE_SURF_Transform			( PRC_TYPE_SURF + 18 )	// Transformed surface. 
+#define PRC_TYPE_SURF_Blend04			( PRC_TYPE_SURF + 19 )	// defined for future use. 
+
+#define PRC_TYPE_TOPO_Context			( PRC_TYPE_TOPO + 1 )	// Self-containing set of topological entities. 
+#define PRC_TYPE_TOPO_Item			( PRC_TYPE_TOPO + 2 )	// Abstract root type for any topological entity (body or single item).
+#define PRC_TYPE_TOPO_MultipleVertex		( PRC_TYPE_TOPO + 3 )	// Vertex whose position is the average of all edges' extremity positions to whom it belongs.
+#define PRC_TYPE_TOPO_UniqueVertex		( PRC_TYPE_TOPO + 4 )	// Vertex with one set of coordinates (absolute position).
+#define PRC_TYPE_TOPO_WireEdge			( PRC_TYPE_TOPO + 5 )	// Edge belonging to a wire body / single wire body.
+#define PRC_TYPE_TOPO_Edge			( PRC_TYPE_TOPO + 6 )	// Edge belonging to a brep data.
+#define PRC_TYPE_TOPO_CoEdge			( PRC_TYPE_TOPO + 7 )	// Usage of an edge in a loop.
+#define PRC_TYPE_TOPO_Loop			( PRC_TYPE_TOPO + 8 )	// Array of co edges which delimits a face.
+#define PRC_TYPE_TOPO_Face			( PRC_TYPE_TOPO + 9 )	// Topological face delimiting a shell.
+#define PRC_TYPE_TOPO_Shell			( PRC_TYPE_TOPO + 10 )	// Topological shell (open or closed).
+#define PRC_TYPE_TOPO_Connex			( PRC_TYPE_TOPO + 11 )	// Topological region delimited by one or several shells. 
+#define PRC_TYPE_TOPO_Body			( PRC_TYPE_TOPO + 12 )	// Abstract root type for any topological body.
+#define PRC_TYPE_TOPO_SingleWireBody		( PRC_TYPE_TOPO + 13 )	// Single wire body.
+#define PRC_TYPE_TOPO_BrepData			( PRC_TYPE_TOPO + 14 )	// Main entry to solid and surface topology (regular form).
+#define PRC_TYPE_TOPO_SingleWireBodyCompress	( PRC_TYPE_TOPO + 15 )	// Single wire body. (ultra compressed form).
+#define PRC_TYPE_TOPO_BrepDataCompress		( PRC_TYPE_TOPO + 16 )	// Main entry to solid and surface topology (ultra compressed form).
+#define PRC_TYPE_TOPO_WireBody			( PRC_TYPE_TOPO + 17 )	// This type is the main entry to wire topology. 
+
+#define PRC_TYPE_TESS_Base			( PRC_TYPE_TESS + 1 )	// Abstract root type for any tessellated entity. 
+#define PRC_TYPE_TESS_3D			( PRC_TYPE_TESS + 2 )	// Tessellated faceted data; regular form. 
+#define PRC_TYPE_TESS_3D_Compressed		( PRC_TYPE_TESS + 3 )	// Tessellated faceted data; highly compressed form. 
+#define PRC_TYPE_TESS_Face			( PRC_TYPE_TESS + 4 )	// Tessellated face. 
+#define PRC_TYPE_TESS_3D_Wire			( PRC_TYPE_TESS + 5 )	// Tessellated wireframe. 
+#define PRC_TYPE_TESS_Markup			( PRC_TYPE_TESS + 6 )	// Tessellated markup. 
+
+#define PRC_TYPE_MISC_Attribute			( PRC_TYPE_MISC + 1 )	// Entity attribute. 
+#define PRC_TYPE_MISC_CartesianTransformation	( PRC_TYPE_MISC + 2 )	// Cartesian transformation. 
+#define PRC_TYPE_MISC_EntityReference		( PRC_TYPE_MISC + 3 )	// Entity reference. 
+#define PRC_TYPE_MISC_MarkupLinkedItem		( PRC_TYPE_MISC + 4 )	// Link between a markup and an entity. 
+#define PRC_TYPE_MISC_ReferenceOnPRCBase	( PRC_TYPE_MISC + 5 )	// Reference pointing on a regular entity (not topological). 
+#define PRC_TYPE_MISC_ReferenceOnTopology	( PRC_TYPE_MISC + 6 )	// Reference pointing on a topological entity. 
+#define PRC_TYPE_MISC_GeneralTransformation	( PRC_TYPE_MISC + 7 )	// General transformation.
+
+#define PRC_TYPE_RI_RepresentationItem		( PRC_TYPE_RI + 1 )	// Basic abstract type for representation items. 
+#define PRC_TYPE_RI_BrepModel			( PRC_TYPE_RI + 2 )	// Basic type for surfaces and solids. 
+#define PRC_TYPE_RI_Curve			( PRC_TYPE_RI + 3 )	// Basic type for curves. 
+#define PRC_TYPE_RI_Direction			( PRC_TYPE_RI + 4 )	// Optional point + vector. 
+#define PRC_TYPE_RI_Plane			( PRC_TYPE_RI + 5 )	// Construction plane, as opposed to planar surface. 
+#define PRC_TYPE_RI_PointSet			( PRC_TYPE_RI + 6 )	// Set of points. 
+#define PRC_TYPE_RI_PolyBrepModel		( PRC_TYPE_RI + 7 )	// Basic type to polyhedral surfaces and solids. 
+#define PRC_TYPE_RI_PolyWire			( PRC_TYPE_RI + 8 )	// Polyedric wireframe entity. 
+#define PRC_TYPE_RI_Set				( PRC_TYPE_RI + 9 )	// Logical grouping of arbitrary number of representation items. 
+#define PRC_TYPE_RI_CoordinateSystem		( PRC_TYPE_RI + 10 )	// Coordinate system. 
+
+#define PRC_TYPE_ASM_ModelFile			( PRC_TYPE_ASM + 1 )	// Basic entry type for PRC. 
+#define PRC_TYPE_ASM_FileStructure		( PRC_TYPE_ASM + 2 )	// Basic structure for PRC files. 
+#define PRC_TYPE_ASM_FileStructureGlobals	( PRC_TYPE_ASM + 3 )	// Basic structure for PRC files : globals. 
+#define PRC_TYPE_ASM_FileStructureTree		( PRC_TYPE_ASM + 4 )	// Basic structure for PRC files : tree. 
+#define PRC_TYPE_ASM_FileStructureTessellation	( PRC_TYPE_ASM + 5 )	// Basic structure for PRC files : tessellation. 
+#define PRC_TYPE_ASM_FileStructureGeometry	( PRC_TYPE_ASM + 6 )	// Basic structure for PRC files : geometry. 
+#define PRC_TYPE_ASM_FileStructureExtraGeometry	( PRC_TYPE_ASM + 7 )	// Basic structure for PRC files : extra geometry data.
+#define PRC_TYPE_ASM_ProductOccurence		( PRC_TYPE_ASM + 10 )	// Basic contruct for assemblies. 
+#define PRC_TYPE_ASM_PartDefinition		( PRC_TYPE_ASM + 11 )	// Basic construct for parts. 
+#define PRC_TYPE_ASM_Filter			( PRC_TYPE_ASM + 20 )
+
+#define PRC_TYPE_MKP_View			( PRC_TYPE_MKP + 1 )	// Grouping of markup by views. 
+#define PRC_TYPE_MKP_Markup			( PRC_TYPE_MKP + 2 )	// Basic type for simple markups. 
+#define PRC_TYPE_MKP_Leader			( PRC_TYPE_MKP + 3 )	// basic type for markup leader 
+#define PRC_TYPE_MKP_AnnotationItem		( PRC_TYPE_MKP + 4 )	// Usage of a markup.
+#define PRC_TYPE_MKP_AnnotationSet		( PRC_TYPE_MKP + 5 )	// Group of annotations.
+#define PRC_TYPE_MKP_AnnotationReference	( PRC_TYPE_MKP + 6 )	// Logical grouping of annotations for reference.
+
+#define PRC_TYPE_GRAPH_Style			( PRC_TYPE_GRAPH + 1 )	// Display style. 
+#define PRC_TYPE_GRAPH_Material			( PRC_TYPE_GRAPH + 2 )	// Display material properties. 
+#define PRC_TYPE_GRAPH_Picture			( PRC_TYPE_GRAPH + 3 )	// Picture. 
+#define PRC_TYPE_GRAPH_TextureApplication	( PRC_TYPE_GRAPH + 11 )	// Texture application. 
+#define PRC_TYPE_GRAPH_TextureDefinition	( PRC_TYPE_GRAPH + 12 )	// Texture definition. 
+#define PRC_TYPE_GRAPH_TextureTransformation	( PRC_TYPE_GRAPH + 13 )	// Texture transformation. 
+#define PRC_TYPE_GRAPH_LinePattern		( PRC_TYPE_GRAPH + 21 )	// One dimensional display style. 
+#define PRC_TYPE_GRAPH_FillPattern		( PRC_TYPE_GRAPH + 22 )	// Abstract class for two-dimensional display style. 
+#define PRC_TYPE_GRAPH_DottingPattern		( PRC_TYPE_GRAPH + 23 )	// Two-dimensional filling with dots. 
+#define PRC_TYPE_GRAPH_HatchingPattern		( PRC_TYPE_GRAPH + 24 )	// Two-dimensional filling with hatches. 
+#define PRC_TYPE_GRAPH_SolidPattern		( PRC_TYPE_GRAPH + 25 )	// Two-dimensional filling with particular style (color, material, texture). 
+#define PRC_TYPE_GRAPH_VPicturePattern		( PRC_TYPE_GRAPH + 26 )	// Two-dimensional filling with vectorised picture. 
+#define PRC_TYPE_GRAPH_AmbientLight		( PRC_TYPE_GRAPH + 31 )	// Scene ambient illumination. 
+#define PRC_TYPE_GRAPH_PointLight		( PRC_TYPE_GRAPH + 32 )	// Scene point illumination. 
+#define PRC_TYPE_GRAPH_DirectionalLight		( PRC_TYPE_GRAPH + 33 )	// Scene directional illumination. 
+#define PRC_TYPE_GRAPH_SpotLight		( PRC_TYPE_GRAPH + 34 )	// Scene spot illumination. 
+#define PRC_TYPE_GRAPH_SceneDisplayParameters	( PRC_TYPE_GRAPH + 41 )	// Parameters for scene visualisation. 
+#define PRC_TYPE_GRAPH_Camera			( PRC_TYPE_GRAPH + 42 )	// 
+
+#define PRC_TYPE_MATH_FCT_1D			( PRC_TYPE_MATH + 1 )	// Basic type for one degree equation object. 
+#define PRC_TYPE_MATH_FCT_1D_Polynom		( PRC_TYPE_MATH_FCT_1D + 1 )	// Polynomial equation. 
+#define PRC_TYPE_MATH_FCT_1D_Trigonometric	( PRC_TYPE_MATH_FCT_1D + 2 )	// Cosinus based equation. 
+#define PRC_TYPE_MATH_FCT_1D_Fraction		( PRC_TYPE_MATH_FCT_1D + 3 )	// Fraction between 2 one degree equation object. 
+#define PRC_TYPE_MATH_FCT_1D_ArctanCos		( PRC_TYPE_MATH_FCT_1D + 4 )	// Specific equation. 
+#define PRC_TYPE_MATH_FCT_1D_Combination	( PRC_TYPE_MATH_FCT_1D + 5 )	// Combination of one degree equation object. 
+#define PRC_TYPE_MATH_FCT_3D			( PRC_TYPE_MATH + 10 )	// Basic type for 3rd degree equation object. 
+#define PRC_TYPE_MATH_FCT_3D_Linear		( PRC_TYPE_MATH_FCT_3D + 1 )	// Linear transformation ( with a matrix ). 
+#define PRC_TYPE_MATH_FCT_3D_NonLinear		( PRC_TYPE_MATH_FCT_3D + 2 )	// Specific transformation. 
+
+#define PRC_PRODUCT_FLAG_DEFAULT        0x0001
+#define PRC_PRODUCT_FLAG_INTERNAL       0x0002
+#define PRC_PRODUCT_FLAG_CONTAINER      0x0004
+#define PRC_PRODUCT_FLAG_CONFIG         0x0008
+#define PRC_PRODUCT_FLAG_VIEW           0x0010
+
+#define PRC_TRANSFORMATION_Identity     0x00
+#define PRC_TRANSFORMATION_Translate    0x01
+#define PRC_TRANSFORMATION_Rotate       0x02
+#define PRC_TRANSFORMATION_Mirror       0x04
+#define PRC_TRANSFORMATION_Scale        0x08
+#define PRC_TRANSFORMATION_NonUniformScale 0x10
+#define PRC_TRANSFORMATION_NonOrtho     0x20
+#define PRC_TRANSFORMATION_Homogeneous  0x40
+
+#define PRC_FACETESSDATA_Polyface                          0x0001
+#define PRC_FACETESSDATA_Triangle                          0x0002
+#define PRC_FACETESSDATA_TriangleFan                       0x0004
+#define PRC_FACETESSDATA_TriangleStripe                    0x0008
+#define PRC_FACETESSDATA_PolyfaceOneNormal                 0x0010
+#define PRC_FACETESSDATA_TriangleOneNormal                 0x0020
+#define PRC_FACETESSDATA_TriangleFanOneNormal              0x0040
+#define PRC_FACETESSDATA_TriangleStripeOneNormal           0x0080
+#define PRC_FACETESSDATA_PolyfaceTextured                  0x0100
+#define PRC_FACETESSDATA_TriangleTextured                  0x0200
+#define PRC_FACETESSDATA_TriangleFanTextured               0x0400
+#define PRC_FACETESSDATA_TriangleStripeTextured            0x0800
+#define PRC_FACETESSDATA_PolyfaceOneNormalTextured         0x1000
+#define PRC_FACETESSDATA_TriangleOneNormalTextured         0x2000
+#define PRC_FACETESSDATA_TriangleFanOneNormalTextured      0x4000
+#define PRC_FACETESSDATA_TriangleStripeOneNormalTextured   0x8000
+#define PRC_FACETESSDATA_NORMAL_Single   		0x40000000
+#define PRC_FACETESSDATA_NORMAL_Mask			0x3FFFFFFF
+#define PRC_FACETESSDATA_WIRE_IsNotDrawn		0x4000		// Indicates that the edge should not be drawn (its neighbor will be drawn).
+#define PRC_FACETESSDATA_WIRE_IsClosing			0x8000		// Indicates that this is the last edge of a loop.
+
+#define PRC_3DWIRETESSDATA_IsClosing			0x10000000 // Indicates that the first point is implicitely repeated after the last one to close the wire edge.
+#define PRC_3DWIRETESSDATA_IsContinuous			0x20000000 // Indicates that the last point of the preceding wire should be linked with the first point of the current one.
+
+#define PRC_TEXTURE_MAPPING_DIFFUSE			0x0001 // Diffuse texture mapping attribute. Default value.
+#define PRC_TEXTURE_MAPPING_BUMP			0x0002 // Bump texture mapping attribute.
+#define PRC_TEXTURE_MAPPING_OPACITY			0x0004 // Opacity texture mapping attribute.
+#define PRC_TEXTURE_MAPPING_SPHERICAL_REFLECTION	0x0008 // Spherical reflection texture mapping attribute (used for environment mapping).
+#define PRC_TEXTURE_MAPPING_CUBICAL_REFLECTION		0x0010 // Cubical reflection texture mapping attribute (used for environment mapping).
+#define PRC_TEXTURE_MAPPING_REFRACTION			0x0020 // Refraction texture mapping attribute.
+#define PRC_TEXTURE_MAPPING_SPECULAR			0x0040 // Specular texture mapping attribute.
+#define PRC_TEXTURE_MAPPING_AMBIENT			0x0080 // Ambient texture mapping attribute.
+#define PRC_TEXTURE_MAPPING_EMISSION			0x0100 // Emission texture mapping attribute.
+
+#define PRC_TEXTURE_APPLYING_MODE_NONE		0x00 // let the application choose
+#define PRC_TEXTURE_APPLYING_MODE_LIGHTING	0x01 // use lighting mode
+#define PRC_TEXTURE_APPLYING_MODE_ALPHATEST	0x02 // use alpha test
+#define PRC_TEXTURE_APPLYING_MODE_VERTEXCOLOR	0x04 // combine a texture with one-color-per-vertex mode
+
+#define PRC_TEXTURE_MAPPING_COMPONENTS_RED	0x0001 // Red texture mapping component.
+#define PRC_TEXTURE_MAPPING_COMPONENTS_GREEN	0x0002 // Green texture mapping component.
+#define PRC_TEXTURE_MAPPING_COMPONENTS_BLUE	0x0004 // Blue texture mapping component.
+#define PRC_TEXTURE_MAPPING_COMPONENTS_RGB	0x0007 // RGB texture mapping component.
+#define PRC_TEXTURE_MAPPING_COMPONENTS_ALPHA	0x0008 // Alpha texture mapping component.
+#define PRC_TEXTURE_MAPPING_COMPONENTS_RGBA	0x000F // RGBA texture mapping component.
+
+enum EPRCModellerAttributeType {
+  KEPRCModellerAttributeTypeNull = 0,
+  KEPRCModellerAttributeTypeInt = 1,
+  KEPRCModellerAttributeTypeReal = 2,
+  KEPRCModellerAttributeTypeTime = 3,
+  KEPRCModellerAttributeTypeString = 4
+};
+
+enum EPRCPictureDataFormat {
+  KEPRCPicture_PNG,
+  KEPRCPicture_JPG,
+  KEPRCPicture_BITMAP_RGB_BYTE,
+  KEPRCPicture_BITMAP_RGBA_BYTE,
+  KEPRCPicture_BITMAP_GREY_BYTE,
+  KEPRCPicture_BITMAP_GREYA_BYTE
+};
+
+enum EPRCProductLoadStatus {
+  KEPRCProductLoadStatus_Unknown = 0,
+  KEPRCProductLoadStatus_Error,
+  KEPRCProductLoadStatus_NotLoaded,
+  KEPRCProductLoadStatus_NotLoadable,
+  KEPRCProductLoadStatus_Loaded
+};
+
+enum EPRCExtendType { 
+  KEPRCExtendTypeNone = 0,      // Discontinuous position.
+  KEPRCExtendTypeExt1 = 2,      // Same as EPRCExtendTypeCInfinity.
+  KEPRCExtendTypeExt2 = 4,      // Same as EPRCExtendTypeG1R for surface, and EPRCExtendTypeG1 for curve.
+  KEPRCExtendTypeG1 = 6,        // Continuous in direction but not magnitude of first derivative.
+  KEPRCExtendTypeG1R = 8,       // Surface extended with a ruled surface that connects with G1-continuity.
+  KEPRCExtendTypeG1_G2 = 10,    // Extended by reflection, yielding a G2 continuous extension.
+  KEPRCExtendTypeCInfinity = 12 // Unlimited continuity.
+};
+
+enum EPRCKnotType {			// Knot vector type
+  KEPRCKnotTypeUniformKnots,		// Uniform knot vector.
+  KEPRCKnotTypeUnspecified,		// Unspecified knot type.
+  KEPRCKnotTypeQuasiUniformKnots,	// Quasi-uniform knot vector.
+  KEPRCKnotTypePiecewiseBezierKnots	// Extrema with multiplicities of degree +1.
+};					// Note : this value is currently unused and should be set to KEPRCKnotTypeUnspecified.
+
+
+enum EPRCBSplineSurfaceForm {
+  KEPRCBSplineSurfaceFormPlane,			// Planar surface.
+  KEPRCBSplineSurfaceFormCylindrical,		// Cylindrical surface.
+  KEPRCBSplineSurfaceFormConical,		// Conical surface.
+  KEPRCBSplineSurfaceFormSpherical,		// Spherical surface.
+  KEPRCBSplineSurfaceFormRevolution,		// Surface of revolution.
+  KEPRCBSplineSurfaceFormRuled,			// Ruled surface.
+  KEPRCBSplineSurfaceFormGeneralizedCone,	// Cone.
+  KEPRCBSplineSurfaceFormQuadric,		// Quadric surface.
+  KEPRCBSplineSurfaceFormLinearExtrusion,	// Surface of extrusion.
+  KEPRCBSplineSurfaceFormUnspecified,		// Unspecified surface.
+  KEPRCBSplineSurfaceFormPolynomial		// Polynomial surface.
+};
+
+enum EPRCBSplineCurveForm {		// NURBS curve form
+  KEPRCBSplineCurveFormUnspecified,	// Unspecified curve form.
+  KEPRCBSplineCurveFormPolyline,	// Polygon.
+  KEPRCBSplineCurveFormCircularArc,	// Circle arc.
+  KEPRCBSplineCurveFormEllipticArc,	// Elliptical arc.
+  KEPRCBSplineCurveFormParabolicArc,	// Parabolic arc.
+  KEPRCBSplineCurveFormHyperbolicArc	// Hyperbolic arc.
+};					// Note : this value is currently unused and should be set to KEPRCBSplineCurveFormUnspecified.
+
+enum EPRCTextureMappingType {			// Defines how to retrieve mapping coordinates.
+  KEPRCTextureMappingType_Unknown,		// Let the application choose.
+  KEPRCTextureMappingType_Stored,		// Use the mapping coordinates that are stored on a 3D tessellation object
+  KEPRCTextureMappingType_Parametric,		// Retrieve the UV coordinates on the surface as mapping coordinates
+  KEPRCTextureMappingType_Operator		// Use the defined Texture mapping operator to calculate mapping coordinates
+};
+
+enum EPRCTextureFunction {			// Defines how to paint a texture on the surface being rendered.
+  KEPRCTextureFunction_Unknown,			// Let the application choose.
+  KEPRCTextureFunction_Modulate,		// Combine lighting with texturing. This is the default value.
+  KEPRCTextureFunction_Replace,			// Replace the object color with texture color data.
+  KEPRCTextureFunction_Blend,			// Reserved for future use.
+  KEPRCTextureFunction_Decal			// Reserved for future use.
+};
+
+enum EPRCTextureMappingOperator {		// The operator to use when computing mapping coordinates.
+  KEPRCTextureMappingOperator_Unknown,		// Default value
+  KEPRCTextureMappingOperator_Planar,		// Reserved for future use
+  KEPRCTextureMappingOperator_Cylindrical,	// Reserved for future use
+  KEPRCTextureMappingOperator_Spherical, 	// Reserved for future use
+  KEPRCTextureMappingOperator_Cubical 		// Reserved for future use
+};
+
+enum EPRCTextureBlendParameter {		// Reserved for future use. Defines how to apply blending.
+  KEPRCTextureBlendParameter_Unknown,		// Default value.
+  KEPRCTextureBlendParameter_Zero,		// Reserved for future use.
+  KEPRCTextureBlendParameter_One,		// Reserved for future use.
+  KEPRCTextureBlendParameter_SrcColor,		// Reserved for future use.
+  KEPRCTextureBlendParameter_OneMinusSrcColor,	// Reserved for future use.
+  KEPRCTextureBlendParameter_DstColor,		// Reserved for future use.
+  KEPRCTextureBlendParameter_OneMinusDstColor,	// Reserved for future use.
+  KEPRCTextureBlendParameter_SrcAlpha,		// Reserved for future use.
+  KEPRCTextureBlendParameter_OneMinusSrcAlpha,	// Reserved for future use.
+  KEPRCTextureBlendParameter_DstAlpha,		// Reserved for future use.
+  KEPRCTextureBlendParameter_OneMinusDstAlpha,	// Reserved for future use.
+  KEPRCTextureBlendParameter_SrcAlphaSaturate	// Reserved for future use.
+};
+
+enum EPRCTextureWrappingMode {			// Defines repeating and clamping texture modes.
+  KEPRCTextureWrappingMode_Unknown,		// Let the application choose.
+  KEPRCTextureWrappingMode_Repeat,		// Display the repeated texture on the surface.
+  KEPRCTextureWrappingMode_ClampToBorder,	// Clamp the texture to the border. Display the surface color along the texture limits.
+  KEPRCTextureWrappingMode_Clamp,		// Reserved for future use.
+  KEPRCTextureWrappingMode_ClampToEdge,		// Reserved for future use.
+  KEPRCTextureWrappingMode_MirroredRepeat	// Reserved for future use.
+};
+
+enum EPRCTextureAlphaTest {			// Reserved for future use. Defines how to use a texture alpha test.
+  KEPRCTextureAlphaTest_Unknown,		// Default value.
+  KEPRCTextureAlphaTest_Never,			// Reserved for future use.
+  KEPRCTextureAlphaTest_Less,			// Reserved for future use.
+  KEPRCTextureAlphaTest_Equal,			// Reserved for future use.
+  KEPRCTextureAlphaTest_Lequal,			// Reserved for future use.
+  KEPRCTextureAlphaTest_Greater,		// Reserved for future use.
+  KEPRCTextureAlphaTest_Notequal,		// Reserved for future use.
+  KEPRCTextureAlphaTest_Gequal,			// Reserved for future use.
+  KEPRCTextureAlphaTest_Always			// Reserved for future use.
+};
+
+
+// Bit field for graphics behavior
+#define PRC_GRAPHICS_Show			0x0001 // The entity is shown.
+#define PRC_GRAPHICS_SonHeritShow		0x0002 // Shown entity son inheritance.
+#define PRC_GRAPHICS_FatherHeritShow		0x0004 // Shown entity father inheritance.
+#define PRC_GRAPHICS_SonHeritColor		0x0008 // Color/material son inheritance.
+#define PRC_GRAPHICS_FatherHeritColor		0x0010 // Color/material father inheritance.
+#define PRC_GRAPHICS_SonHeritLayer		0x0020 // Layer son inheritance.
+#define PRC_GRAPHICS_FatherHeritLayer		0x0040 // Layer father inheritance.
+#define PRC_GRAPHICS_SonHeritTransparency	0x0080 // Transparency son inheritance.
+#define PRC_GRAPHICS_FatherHeritTransparency	0x0100 // Transparency father inheritance.
+#define PRC_GRAPHICS_SonHeritLinePattern	0x0200 // Line pattern son inheritance.
+#define PRC_GRAPHICS_FatherHeritLinePattern	0x0400 // Line pattern father inheritance.
+#define PRC_GRAPHICS_SonHeritLineWidth		0x0800 // Line width son inheritance.
+#define PRC_GRAPHICS_FatherHeritLineWidth	0x1000 // Line width father inheritance.
+#define PRC_GRAPHICS_Removed			0x2000 // The entity has been removed and no longer appears in the tree.
+
+enum EPRCMarkupType {
+  KEPRCMarkupType_Unknown = 0,
+  KEPRCMarkupType_Text,
+  KEPRCMarkupType_Dimension,
+  KEPRCMarkupType_Arrow,
+  KEPRCMarkupType_Balloon,
+  KEPRCMarkupType_CircleCenter,
+  KEPRCMarkupType_Coordinate,
+  KEPRCMarkupType_Datum,
+  KEPRCMarkupType_Fastener,
+  KEPRCMarkupType_Gdt,
+  KEPRCMarkupType_Locator,
+  KEPRCMarkupType_MeasurementPoint,
+  KEPRCMarkupType_Roughness,
+  KEPRCMarkupType_Welding,
+  KEPRCMarkupType_Table,
+  KEPRCMarkupType_Other 
+};
+
+enum EPRCMarkupSubType {
+  KEPRCMarkupSubType_Unknown = 0,
+  KEPRCMarkupSubType_EnumMax,
+
+  KEPRCMarkupSubType_Datum_Ident = 1 ,
+  KEPRCMarkupSubType_Datum_EnumMax, 
+
+  KEPRCMarkupSubType_Dimension_Distance = 1,
+  KEPRCMarkupSubType_Dimension_Radius_Tangent,
+  KEPRCMarkupSubType_Dimension_Radius_Cylinder,
+  KEPRCMarkupSubType_Dimension_Radius_Edge,
+  KEPRCMarkupSubType_Dimension_Diameter,
+  KEPRCMarkupSubType_Dimension_Diameter_Tangent,
+  KEPRCMarkupSubType_Dimension_Diameter_Cylinder,
+  KEPRCMarkupSubType_Dimension_Diameter_Edge, 
+  KEPRCMarkupSubType_Dimension_Diameter_Cone,
+  KEPRCMarkupSubType_Dimension_Length,
+  KEPRCMarkupSubType_Dimension_Length_Curvilinear,
+  KEPRCMarkupSubType_Dimension_Length_Circular,
+  KEPRCMarkupSubType_Dimension_Angle,
+  KEPRCMarkupSubType_Dimension_EnumMax,
+
+  KEPRCMarkupSubType_Gdt_Fcf = 1,
+  KEPRCMarkupSubType_Gdt_EnumMax,
+
+  KEPRCMarkupSubType_Welding_Line = 1,
+  KEPRCMarkupSubType_Welding_EnumMax,
+
+  KEPRCMarkupSubType_Other_Symbol_User = 1,
+  KEPRCMarkupSubType_Other_EnumMax 
+};
+
+#define PRC_MARKUP_IsHidden		0x01	// The tessellation is hidden.
+#define PRC_MARKUP_HasFrame		0x02	// The tessellation has a frame.
+#define PRC_MARKUP_IsNotModifiable	0x04	// The tessellation is given and should not be modified.
+#define PRC_MARKUP_IsZoomable		0x08	// The tessellation has zoom capability.
+#define PRC_MARKUP_IsOnTop		0x10	// The tessellation is on top of the geometry.
+#define PRC_MARKUP_IsFlipable		0x20	// The text tessellation can be flipped to always be readable on screen. This value is currently unused.
+
+#define PRC_RENDERING_PARAMETER_SPECIAL_CULLING	0x0001 // special culling strategy to apply
+#define PRC_RENDERING_PARAMETER_FRONT_CULLING	0x0002 // apply front culling (ignored if no special culling strategy)
+#define PRC_RENDERING_PARAMETER_BACK_CULLING	0x0004 // apply back culling (ignored if no special culling strategy)
+#define PRC_RENDERING_PARAMETER_NO_LIGHT	0x0008 // if set, no light will apply on corresponding object
+
+#define PRC_MARKUP_IsMatrix		0x08000000 // Bit to denote that the current entity is a matrix.
+#define PRC_MARKUP_IsExtraData		0x04000000 // Bit to denote that the current entity is extra data (it is neither a matrix nor a polyline).
+#define PRC_MARKUP_IntegerMask		0xFFFFF    // Integer mask to retrieve sizes.
+#define PRC_MARKUP_ExtraDataType	0x3E00000  // Mask to retrieve the integer type of the entity.
+
+#define PRC_MARKUP_ExtraDataType_Pattern	(( 0<<21)|PRC_MARKUP_IsExtraData)
+#define PRC_MARKUP_ExtraDataType_Picture	(( 1<<21)|PRC_MARKUP_IsExtraData)
+#define PRC_MARKUP_ExtraDataType_Triangles	(( 2<<21)|PRC_MARKUP_IsExtraData)
+#define PRC_MARKUP_ExtraDataType_Quads		(( 3<<21)|PRC_MARKUP_IsExtraData)
+#define PRC_MARKUP_ExtraDataType_FaceViewMode	(( 6<<21)|PRC_MARKUP_IsExtraData)
+#define PRC_MARKUP_ExtraDataType_FrameDrawMode	(( 7<<21)|PRC_MARKUP_IsExtraData)
+#define PRC_MARKUP_ExtraDataType_FixedSizeMode	(( 8<<21)|PRC_MARKUP_IsExtraData)
+#define PRC_MARKUP_ExtraDataType_Symbol		(( 9<<21)|PRC_MARKUP_IsExtraData)
+#define PRC_MARKUP_ExtraDataType_Cylinder	((10<<21)|PRC_MARKUP_IsExtraData)
+#define PRC_MARKUP_ExtraDataType_Color		((11<<21)|PRC_MARKUP_IsExtraData)
+#define PRC_MARKUP_ExtraDataType_LineStipple	((12<<21)|PRC_MARKUP_IsExtraData)
+#define PRC_MARKUP_ExtraDataType_Font		((13<<21)|PRC_MARKUP_IsExtraData)
+#define PRC_MARKUP_ExtraDataType_Text		((14<<21)|PRC_MARKUP_IsExtraData)
+#define PRC_MARKUP_ExtraDataType_Points		((15<<21)|PRC_MARKUP_IsExtraData)
+#define PRC_MARKUP_ExtraDataType_Polygon	((16<<21)|PRC_MARKUP_IsExtraData)
+#define PRC_MARKUP_ExtraDataType_LineWidth	((17<<21)|PRC_MARKUP_IsExtraData)
+
+enum EPRCCharSet
+{
+  KEPRCCharsetUnknown = -1,
+  KEPRCCharsetRoman = 0,
+  KEPRCCharsetJapanese,
+  KEPRCCharsetTraditionalChinese,
+  KEPRCCharsetKorean,
+  KEPRCCharsetArabic,
+  KEPRCCharsetHebrew,
+  KEPRCCharsetGreek,
+  KEPRCCharsetCyrillic,
+  KEPRCCharsetRightLeft,
+  KEPRCCharsetDevanagari,
+  KEPRCCharsetGurmukhi,
+  KEPRCCharsetGujarati,
+  KEPRCCharsetOriya,
+  KEPRCCharsetBengali,
+  KEPRCCharsetTamil,
+  KEPRCCharsetTelugu,
+  KEPRCCharsetKannada,
+  KEPRCCharsetMalayalam,
+  KEPRCCharsetSinhalese,
+  KEPRCCharsetBurmese,
+  KEPRCCharsetKhmer,
+  KEPRCCharsetThai,
+  KEPRCCharsetLaotian,
+  KEPRCCharsetGeorgian,
+  KEPRCCharsetArmenian,
+  KEPRCCharsetSimplifiedChinese,
+  KEPRCCharsetTibetan,
+  KEPRCCharsetMongolian,
+  KEPRCCharsetGeez,
+  KEPRCCharsetEastEuropeanRoman,
+  KEPRCCharsetVietnamese,
+  KEPRCCharsetExtendedArabic
+};
+
+#define PRC_Font_Bold         0x02    /*!< Bold. */
+#define PRC_Font_Italic       0x04    /*!< Italic. */
+#define PRC_Font_Underlined   0x08    /*!< Underlined. */
+#define PRC_Font_StrikedOut   0x10    /*!< Striked-out. */
+#define PRC_Font_Overlined    0x20    /*!< Overlined. */
+#define PRC_Font_Streched     0x40    /*!< Streched. In case the font used is not the original font, it indicates that the text needs to be stretched to fit its bounding box. */
+#define PRC_Font_Wired        0x80    /*!< Wired. Indicates that the original font is a wirefame font. */
+#define PRC_Font_FixedWidth   0x100   /*!< Fixed width. Indicates that the original font is not proportional (each glyph has the same width). */
+
+#define PRC_CONTEXT_OuterLoopFirst 0x0001 // Outer loops are always first loops (specific to PRC_TYPE_TOPO_BrepData). 
+#define PRC_CONTEXT_NoClamp        0x0002 // UV curves are clamped on the surface (specific to PRC_TYPE_TOPO_BrepData). 
+#define PRC_CONTEXT_NoSplit        0x0004 // Faces are split (specific to PRC_TYPE_TOPO_BrepData). 
+
+#define PRC_BODY_BBOX_Evaluation 0x0001 // Bounding box based on geometry. 
+#define PRC_BODY_BBOX_Precise    0x0002 // Bounding box based on tessellation. 
+#define PRC_BODY_BBOX_CADData    0x0003 // Bounding box given by a CAD data file. 
+
+#endif // __PRC_H
diff --git a/src/prc/PRCbitStream.cc b/src/prc/PRCbitStream.cc
new file mode 100644
index 0000000..2781508
--- /dev/null
+++ b/src/prc/PRCbitStream.cc
@@ -0,0 +1,404 @@
+/************
+*
+*   This file is part of a tool for producing 3D content in the PRC format.
+*   Copyright (C) 2008  Orest Shardt <shardtor (at) gmail dot com>
+*
+*   This program is free software: you can redistribute it and/or modify
+*   it under the terms of the GNU Lesser General Public License as published by
+*   the Free Software Foundation, either version 3 of the License, or
+*   (at your option) any later version.
+*
+*   This program is distributed in the hope that it will be useful,
+*   but WITHOUT ANY WARRANTY; without even the implied warranty of
+*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*   GNU Lesser General Public License for more details.
+*
+*   You should have received a copy of the GNU Lesser General Public License
+*   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*
+*************/
+
+#include <iostream>
+#include <zlib.h>
+#include <stdlib.h>
+#include <string.h>
+#include <cassert>
+#include <math.h>
+#include "PRCbitStream.h"
+#include "PRCdouble.h"
+
+using std::string;
+using std::cerr;
+using std::endl;
+
+void PRCbitStream::compress()
+{
+  const int CHUNK= 1024; // is this reasonable?
+  compressedDataSize = 0;
+
+  z_stream strm;
+  strm.zalloc = Z_NULL;
+  strm.zfree = Z_NULL;
+  strm.opaque = Z_NULL;
+  if(deflateInit(&strm,Z_DEFAULT_COMPRESSION) != Z_OK)
+  {
+    cerr << "Compression initialization failed" << endl;
+    return;
+  }
+  unsigned int sizeAvailable = deflateBound(&strm,getSize());
+  uint8_t *compressedData = (uint8_t*) malloc(sizeAvailable);
+  strm.avail_in = getSize();
+  strm.next_in = (unsigned char*)data;
+  strm.next_out = (unsigned char*)compressedData;
+  strm.avail_out = sizeAvailable;
+
+  int code;
+  unsigned int chunks = 0;
+  while((code = deflate(&strm,Z_FINISH)) == Z_OK)
+  {
+    ++chunks;
+    // strm.avail_out should be 0 if we got Z_OK
+    compressedDataSize = sizeAvailable - strm.avail_out;
+    compressedData = (uint8_t*) realloc(compressedData,CHUNK*chunks);
+    strm.next_out = (Bytef*)(compressedData + compressedDataSize);
+    strm.avail_out += CHUNK;
+    sizeAvailable += CHUNK;
+  }
+  compressedDataSize = sizeAvailable-strm.avail_out;
+
+  if(code != Z_STREAM_END)
+  {
+    cerr << "Compression error" << endl;
+    deflateEnd(&strm);
+    free(compressedData);
+    return;
+  }
+
+  compressed = true;
+
+  free(data);
+  data = compressedData;
+
+  deflateEnd(&strm);
+}
+
+void PRCbitStream::write(std::ostream &out) const
+{
+  if(compressed)
+  {
+    out.write((char*)data,compressedDataSize);
+  }
+  else
+  {
+     cerr << "Attempt to write stream before compression." << endl;
+     exit(1);
+  }
+}
+
+unsigned int PRCbitStream::getSize() const
+{
+  if(compressed)
+    return compressedDataSize;
+  else
+    return byteIndex+1;
+}
+
+uint8_t* PRCbitStream::getData()
+{
+  return data;
+}
+
+PRCbitStream& PRCbitStream::operator <<(bool b)
+{
+  writeBit(b);
+  return *this;
+}
+
+PRCbitStream& PRCbitStream::operator <<(uint32_t u)
+{
+  while(u != 0)
+  {
+    writeBit(1);
+    writeByte(u & 0xFF);
+    u >>= 8;
+  }
+  writeBit(0);
+  return *this;
+}
+
+PRCbitStream& PRCbitStream::operator <<(uint8_t u)
+{
+  writeByte(u);
+  return *this;
+}
+
+PRCbitStream& PRCbitStream::operator <<(int32_t i)
+{
+  uint8_t lastByte = 0;
+  //while(!((current value is 0 and last byte was positive) OR (current value is -1 and last value was negative)))
+  while(!(((i == 0)&&((lastByte & 0x80)==0))||((i == -1)&&((lastByte & 0x80) != 0))))
+  {
+    writeBit(1);
+    lastByte = i & 0xFF;
+    writeByte(lastByte);
+    i >>= 8;
+  }
+  writeBit(0);
+  return *this;
+}
+
+PRCbitStream& PRCbitStream::operator <<(double value)
+{
+  // write a double
+  if(compressed)
+  {
+    cerr << "Cannot write to a stream that has been compressed." << endl;
+    return *this;
+  }
+  union ieee754_double *pid=(union ieee754_double *)&value;
+  int
+        i,
+        fSaveAtEnd;
+        PRCbyte
+        *pb,
+        *pbStart,
+        *pbStop,
+        *pbEnd,
+        *pbResult,
+        bSaveAtEnd = 0;
+  struct sCodageOfFrequentDoubleOrExponent
+        cofdoe,
+        *pcofdoe;
+
+  cofdoe.u2uod.Value=value;
+  pcofdoe = (struct sCodageOfFrequentDoubleOrExponent *)bsearch(
+                           &cofdoe,
+                           acofdoe,
+                           sizeof(acofdoe)/sizeof(pcofdoe[0]),
+                           sizeof(pcofdoe[0]),
+                           stCOFDOECompare);
+
+  while(pcofdoe>acofdoe && EXPONENT(pcofdoe->u2uod.Value)==EXPONENT((pcofdoe-1)->u2uod.Value))
+    pcofdoe--;
+
+  assert(pcofdoe);
+  while(pcofdoe->Type==VT_double)
+  {
+    if(fabs(value)==pcofdoe->u2uod.Value)
+      break;
+    pcofdoe++;
+  }
+
+  for(i=1<<(pcofdoe->NumberOfBits-1);i>=1;i>>=1)
+    writeBit((pcofdoe->Bits&i)!=0);
+
+  if
+  (
+    !memcmp(&value,stadwZero,sizeof(value))
+    ||      !memcmp(&value,stadwNegativeZero,sizeof(value))
+  )
+    return *this;
+
+  writeBit(pid->ieee.negative);
+
+  if(pcofdoe->Type==VT_double)
+    return *this;
+
+  if(pid->ieee.mantissa0==0 && pid->ieee.mantissa1==0)
+  {
+    writeBit(0);
+    return *this;
+  }
+
+  writeBit(1);
+
+#ifdef WORDS_BIGENDIAN
+  pb=((PRCbyte *)&value)+1;
+#else
+  pb=((PRCbyte *)&value)+6;
+#endif
+  //add_bits((*pb)&0x0f,4 STAT_V STAT_DOUBLE);
+  writeBits((*pb)&0x0F,4);
+
+  NEXTBYTE(pb);
+  pbStart=pb;
+#ifdef WORDS_BIGENDIAN
+  pbEnd=
+  pbStop= ((PRCbyte *)(&value+1))-1;
+#else
+  pbEnd=
+  pbStop= ((PRCbyte *)&value);
+#endif
+
+  if((fSaveAtEnd=(*pbStop!=*BEFOREBYTE(pbStop)))!=0)
+    bSaveAtEnd=*pbEnd;
+  PREVIOUSBYTE(pbStop);
+
+  while(*pbStop==*BEFOREBYTE(pbStop))
+    PREVIOUSBYTE(pbStop);
+
+  for(;MOREBYTE(pb,pbStop);NEXTBYTE(pb))
+  {
+    if(pb!=pbStart && (pbResult=SEARCHBYTE(BEFOREBYTE(pb),*pb,DIFFPOINTERS(pb,pbStart)))!=NULL)
+    {
+      writeBit(0);
+      writeBits(DIFFPOINTERS(pb,pbResult),3);
+    }
+    else
+    {
+      writeBit(1);
+      writeByte(*pb);
+    }
+  }
+
+  if(!MOREBYTE(BEFOREBYTE(pbEnd),pbStop))
+  {
+    if(fSaveAtEnd)
+    {
+      writeBit(0);
+      writeBits(6,3);
+      writeByte(bSaveAtEnd);
+    }
+    else
+    {
+      writeBit(0);
+      writeBits(0,3);
+    }
+  }
+  else
+  {
+    if((pbResult=SEARCHBYTE(BEFOREBYTE(pb),*pb,DIFFPOINTERS(pb,pbStart)))!=NULL)
+    {
+      writeBit(0);
+      writeBits(DIFFPOINTERS(pb,pbResult),3);
+    }
+    else
+    {
+      writeBit(1);
+      writeByte(*pb);
+    }
+  }
+
+  return *this;
+}
+
+PRCbitStream& PRCbitStream::operator <<(const char* s)
+{
+  if (s == NULL)
+  {
+    writeBit(false); // string is NULL
+    return *this;
+  }
+  string str(s);
+  *this << str;
+  return *this;
+}
+
+PRCbitStream& PRCbitStream::operator <<(const string& s)
+{
+  if(s == "")
+  {
+    writeBit(false); // string is NULL
+    return *this;
+  }
+  writeBit(true);
+  size_t l = s.length();
+  *this << static_cast<uint32_t>(l);
+  for(size_t i = 0; i < l; ++i)
+    writeByte(s[i]);
+  return *this;
+}
+
+void PRCbitStream::writeBit(bool b)
+{
+  if(compressed)
+  {
+    cerr << "Cannot write to a stream that has been compressed." << endl;
+    return;
+  }
+
+  if(b)
+  {
+    data[byteIndex] |= (0x80 >> bitIndex);
+  }
+  nextBit();
+}
+
+void PRCbitStream::writeBits(uint32_t u, uint8_t bits)
+{
+  if(bits > 32)
+    return;
+  else
+  {
+    for(uint32_t mask = (1 << (bits-1)); mask != 0; mask >>= 1)
+    {
+      writeBit((u&mask) != 0);
+    }
+  }
+}
+
+void PRCbitStream::writeByte(uint8_t u)
+{
+  if(compressed)
+  {
+    cerr << "Cannot write to a stream that has been compressed." << endl;
+    return;
+  }
+
+  if(bitIndex == 0)
+  {
+    data[byteIndex] = u;
+    nextByte();
+  }
+  else
+  {
+    data[byteIndex] |= (u >> bitIndex);
+    unsigned int obi = bitIndex;
+    nextByte();
+    data[byteIndex] |= (u << (8-obi));
+    bitIndex = obi; // bit index is not changed by writing 8 bits
+  }
+}
+
+void PRCbitStream::nextBit()
+{
+  ++bitIndex;
+  if(bitIndex == 8)
+  {
+    nextByte();
+  }
+}
+
+void PRCbitStream::nextByte()
+{
+  ++byteIndex;
+  if(byteIndex >= allocatedLength)
+    getAChunk();
+  data[byteIndex] = 0; // clear the garbage data
+  bitIndex = 0;
+}
+
+void PRCbitStream::getAChunk()
+{
+   if(allocatedLength==0)
+     data = (uint8_t*)realloc((void*)data,CHUNK_SIZE);
+   else
+     data = (uint8_t*)realloc((void*)data,2*allocatedLength);
+
+   if(data != NULL)
+   {
+     if(allocatedLength==0)
+     {
+       allocatedLength = CHUNK_SIZE;
+       *data = 0; // clear first byte
+     }
+     else
+       allocatedLength *= 2;
+   }
+   else
+   {
+     // warn about memory problem!
+     cerr << "Memory allocation error." << endl;
+     exit(1);
+   }
+}
diff --git a/src/prc/PRCbitStream.h b/src/prc/PRCbitStream.h
new file mode 100644
index 0000000..f240baf
--- /dev/null
+++ b/src/prc/PRCbitStream.h
@@ -0,0 +1,88 @@
+/************
+*
+*   This file is part of a tool for producing 3D content in the PRC format.
+*   Copyright (C) 2008  Orest Shardt <shardtor (at) gmail dot com>
+*
+*   This program is free software: you can redistribute it and/or modify
+*   it under the terms of the GNU Lesser General Public License as published by
+*   the Free Software Foundation, either version 3 of the License, or
+*   (at your option) any later version.
+*
+*   This program is distributed in the hope that it will be useful,
+*   but WITHOUT ANY WARRANTY; without even the implied warranty of
+*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*   GNU Lesser General Public License for more details.
+*
+*   You should have received a copy of the GNU Lesser General Public License
+*   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*
+*************/
+
+#ifndef __PRC_BIT_STREAM_H
+#define __PRC_BIT_STREAM_H
+
+#ifdef _MSC_VER
+#include <stdio.h>
+#if _MSC_VER >= 1600
+#include <stdint.h>
+#else
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed long int32_t;
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned long uint32_t;
+#endif // _MSC_VER >= 1600
+#elif defined __BORLANDC__
+#include <stdint.h>
+#else
+#include <inttypes.h>
+#endif // _MSC_VER
+#include <string>
+#include <iostream>
+#include <stdlib.h>
+
+#define CHUNK_SIZE (1024)
+// Is this a reasonable initial size?
+
+class PRCbitStream
+{
+  public:
+    PRCbitStream(uint8_t*& buff, unsigned int l) : byteIndex(0), bitIndex(0),
+                 allocatedLength(l), data(buff), compressed(false)
+    {
+      if(data == 0)
+      {
+        getAChunk();
+      }
+    }
+
+    unsigned int getSize() const;
+    uint8_t* getData();
+
+    PRCbitStream& operator <<(const std::string&);
+    PRCbitStream& operator <<(bool);
+    PRCbitStream& operator <<(uint32_t);
+    PRCbitStream& operator <<(uint8_t);
+    PRCbitStream& operator <<(int32_t);
+    PRCbitStream& operator <<(double);
+    PRCbitStream& operator <<(const char*);
+
+    void compress();
+    void write(std::ostream &out) const;
+  private:
+    void writeBit(bool);
+    void writeBits(uint32_t,uint8_t);
+    void writeByte(uint8_t);
+    void nextByte();
+    void nextBit();
+    void getAChunk();
+    // bitIndex is "big endian", zero based, location of next bit to write
+    unsigned int byteIndex,bitIndex;
+    unsigned int allocatedLength;
+    uint8_t*& data;
+    bool compressed;
+    uint32_t compressedDataSize;
+};
+
+#endif // __PRC_BIT_STREAM_H
diff --git a/src/prc/PRCdouble.cc b/src/prc/PRCdouble.cc
new file mode 100644
index 0000000..69d4b02
--- /dev/null
+++ b/src/prc/PRCdouble.cc
@@ -0,0 +1,2121 @@
+#include "PRCdouble.h"
+
+// from Adobe's documentation
+
+PRCdword stadwZero[2]={DOUBLEWITHTWODWORD(0x00000000,0x00000000)};
+PRCdword stadwNegativeZero[2]={DOUBLEWITHTWODWORD(0x80000000,0x00000000)};
+
+struct sCodageOfFrequentDoubleOrExponent* getcofdoe(unsigned Bits, short NumberOfBits)
+{
+  struct sCodageOfFrequentDoubleOrExponent *pcofdoe;
+  for(pcofdoe=acofdoe; pcofdoe < acofdoe+NUMBEROFELEMENTINACOFDOE; ++pcofdoe)
+  {
+    if(pcofdoe->NumberOfBits == NumberOfBits && pcofdoe->Bits == Bits)
+      return pcofdoe;
+  }
+  return NULL;
+}
+
+int stCOFDOECompare(const void* pcofdoe1,const void* pcofdoe2)
+{
+  return(EXPONENT(((const struct sCodageOfFrequentDoubleOrExponent *)pcofdoe1)->u2uod.Value)-
+      EXPONENT(((const struct sCodageOfFrequentDoubleOrExponent *)pcofdoe2)->u2uod.Value));
+}
+
+#ifdef WORDS_BIGENDIAN
+#ifndef HAVE_MEMRCHR
+void *memrchr(const void *buf,int c,size_t count)
+{
+  unsigned char
+      *pcBuffer=(unsigned char *)buf,
+                 *pcBufferEnd=pcBuffer-count;
+
+                 for(;pcBuffer>pcBufferEnd;pcBuffer--)
+                   if(*pcBuffer==c)
+                     return(pcBuffer);
+
+                 return(NULL);
+}
+#endif
+#endif
+
+sCodageOfFrequentDoubleOrExponent acofdoe[NUMBEROFELEMENTINACOFDOE] =
+{
+        {VT_double,2,0x1,{DOUBLEWITHTWODWORDINTREE(0x00000000,0x00000000)}},
+        {VT_exponent,22,0xd1d32,{DOUBLEWITHTWODWORDINTREE(0x00000000,0x00000000)}},
+        {VT_exponent,22,0xd1d33,{DOUBLEWITHTWODWORDINTREE(0x00100000,0x00000000)}},
+        {VT_exponent,22,0xf78d8,{DOUBLEWITHTWODWORDINTREE(0x00200000,0x00000000)}},
+        {VT_exponent,22,0xf78d9,{DOUBLEWITHTWODWORDINTREE(0x00300000,0x00000000)}},
+        {VT_exponent,22,0xf78da,{DOUBLEWITHTWODWORDINTREE(0x00400000,0x00000000)}},
+        {VT_exponent,22,0xf78db,{DOUBLEWITHTWODWORDINTREE(0x00500000,0x00000000)}},
+        {VT_exponent,22,0xf78dc,{DOUBLEWITHTWODWORDINTREE(0x00600000,0x00000000)}},
+        {VT_exponent,22,0xf78dd,{DOUBLEWITHTWODWORDINTREE(0x00700000,0x00000000)}},
+        {VT_exponent,22,0xf78de,{DOUBLEWITHTWODWORDINTREE(0x00800000,0x00000000)}},
+        {VT_exponent,22,0xf78df,{DOUBLEWITHTWODWORDINTREE(0x00900000,0x00000000)}},
+        {VT_exponent,22,0xf78e0,{DOUBLEWITHTWODWORDINTREE(0x00a00000,0x00000000)}},
+        {VT_exponent,22,0xf78e1,{DOUBLEWITHTWODWORDINTREE(0x00b00000,0x00000000)}},
+        {VT_exponent,22,0xf78e2,{DOUBLEWITHTWODWORDINTREE(0x00c00000,0x00000000)}},
+        {VT_exponent,22,0xf78e3,{DOUBLEWITHTWODWORDINTREE(0x00d00000,0x00000000)}},
+        {VT_exponent,22,0xf78e4,{DOUBLEWITHTWODWORDINTREE(0x00e00000,0x00000000)}},
+        {VT_exponent,22,0xf78e5,{DOUBLEWITHTWODWORDINTREE(0x00f00000,0x00000000)}},
+        {VT_exponent,22,0xf78e6,{DOUBLEWITHTWODWORDINTREE(0x01000000,0x00000000)}},
+        {VT_exponent,22,0xf78e7,{DOUBLEWITHTWODWORDINTREE(0x01100000,0x00000000)}},
+        {VT_exponent,22,0xf78e8,{DOUBLEWITHTWODWORDINTREE(0x01200000,0x00000000)}},
+        {VT_exponent,22,0xf78e9,{DOUBLEWITHTWODWORDINTREE(0x01300000,0x00000000)}},
+        {VT_exponent,22,0xf78ea,{DOUBLEWITHTWODWORDINTREE(0x01400000,0x00000000)}},
+        {VT_exponent,22,0xf78eb,{DOUBLEWITHTWODWORDINTREE(0x01500000,0x00000000)}},
+        {VT_exponent,22,0xf78ec,{DOUBLEWITHTWODWORDINTREE(0x01600000,0x00000000)}},
+        {VT_exponent,22,0xf78ed,{DOUBLEWITHTWODWORDINTREE(0x01700000,0x00000000)}},
+        {VT_exponent,22,0xf78ee,{DOUBLEWITHTWODWORDINTREE(0x01800000,0x00000000)}},
+        {VT_exponent,22,0xf78ef,{DOUBLEWITHTWODWORDINTREE(0x01900000,0x00000000)}},
+        {VT_exponent,22,0xf78f0,{DOUBLEWITHTWODWORDINTREE(0x01a00000,0x00000000)}},
+        {VT_exponent,22,0xf78f1,{DOUBLEWITHTWODWORDINTREE(0x01b00000,0x00000000)}},
+        {VT_exponent,22,0xf78f2,{DOUBLEWITHTWODWORDINTREE(0x01c00000,0x00000000)}},
+        {VT_exponent,22,0xf78f3,{DOUBLEWITHTWODWORDINTREE(0x01d00000,0x00000000)}},
+        {VT_exponent,22,0xf78f4,{DOUBLEWITHTWODWORDINTREE(0x01e00000,0x00000000)}},
+        {VT_exponent,22,0xf78f5,{DOUBLEWITHTWODWORDINTREE(0x01f00000,0x00000000)}},
+        {VT_exponent,22,0xf78f6,{DOUBLEWITHTWODWORDINTREE(0x02000000,0x00000000)}},
+        {VT_exponent,22,0xf78f7,{DOUBLEWITHTWODWORDINTREE(0x02100000,0x00000000)}},
+        {VT_exponent,22,0xf78f8,{DOUBLEWITHTWODWORDINTREE(0x02200000,0x00000000)}},
+        {VT_exponent,22,0xf78f9,{DOUBLEWITHTWODWORDINTREE(0x02300000,0x00000000)}},
+        {VT_exponent,22,0xf78fa,{DOUBLEWITHTWODWORDINTREE(0x02400000,0x00000000)}},
+        {VT_exponent,22,0xf78fb,{DOUBLEWITHTWODWORDINTREE(0x02500000,0x00000000)}},
+        {VT_exponent,22,0xf78fc,{DOUBLEWITHTWODWORDINTREE(0x02600000,0x00000000)}},
+        {VT_exponent,22,0xf78fd,{DOUBLEWITHTWODWORDINTREE(0x02700000,0x00000000)}},
+        {VT_exponent,22,0xf78fe,{DOUBLEWITHTWODWORDINTREE(0x02800000,0x00000000)}},
+        {VT_exponent,22,0xf78ff,{DOUBLEWITHTWODWORDINTREE(0x02900000,0x00000000)}},
+        {VT_exponent,22,0x3a8300,{DOUBLEWITHTWODWORDINTREE(0x02a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8301,{DOUBLEWITHTWODWORDINTREE(0x02b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8302,{DOUBLEWITHTWODWORDINTREE(0x02c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8303,{DOUBLEWITHTWODWORDINTREE(0x02d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8304,{DOUBLEWITHTWODWORDINTREE(0x02e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8305,{DOUBLEWITHTWODWORDINTREE(0x02f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8306,{DOUBLEWITHTWODWORDINTREE(0x03000000,0x00000000)}},
+        {VT_exponent,22,0x3a8307,{DOUBLEWITHTWODWORDINTREE(0x03100000,0x00000000)}},
+        {VT_exponent,22,0x3a8308,{DOUBLEWITHTWODWORDINTREE(0x03200000,0x00000000)}},
+        {VT_exponent,22,0x3a8309,{DOUBLEWITHTWODWORDINTREE(0x03300000,0x00000000)}},
+        {VT_exponent,22,0x3a830a,{DOUBLEWITHTWODWORDINTREE(0x03400000,0x00000000)}},
+        {VT_exponent,22,0x3a830b,{DOUBLEWITHTWODWORDINTREE(0x03500000,0x00000000)}},
+        {VT_exponent,22,0x3a830c,{DOUBLEWITHTWODWORDINTREE(0x03600000,0x00000000)}},
+        {VT_exponent,22,0x3a830d,{DOUBLEWITHTWODWORDINTREE(0x03700000,0x00000000)}},
+        {VT_exponent,22,0x3a830e,{DOUBLEWITHTWODWORDINTREE(0x03800000,0x00000000)}},
+        {VT_exponent,22,0x3a830f,{DOUBLEWITHTWODWORDINTREE(0x03900000,0x00000000)}},
+        {VT_exponent,22,0x3a8310,{DOUBLEWITHTWODWORDINTREE(0x03a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8311,{DOUBLEWITHTWODWORDINTREE(0x03b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8312,{DOUBLEWITHTWODWORDINTREE(0x03c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8313,{DOUBLEWITHTWODWORDINTREE(0x03d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8314,{DOUBLEWITHTWODWORDINTREE(0x03e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8315,{DOUBLEWITHTWODWORDINTREE(0x03f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8316,{DOUBLEWITHTWODWORDINTREE(0x04000000,0x00000000)}},
+        {VT_exponent,22,0x3a8317,{DOUBLEWITHTWODWORDINTREE(0x04100000,0x00000000)}},
+        {VT_exponent,22,0x3a8318,{DOUBLEWITHTWODWORDINTREE(0x04200000,0x00000000)}},
+        {VT_exponent,22,0x3a8319,{DOUBLEWITHTWODWORDINTREE(0x04300000,0x00000000)}},
+        {VT_exponent,22,0x3a831a,{DOUBLEWITHTWODWORDINTREE(0x04400000,0x00000000)}},
+        {VT_exponent,22,0x3a831b,{DOUBLEWITHTWODWORDINTREE(0x04500000,0x00000000)}},
+        {VT_exponent,22,0x3a831c,{DOUBLEWITHTWODWORDINTREE(0x04600000,0x00000000)}},
+        {VT_exponent,22,0x3a831d,{DOUBLEWITHTWODWORDINTREE(0x04700000,0x00000000)}},
+        {VT_exponent,22,0x3a831e,{DOUBLEWITHTWODWORDINTREE(0x04800000,0x00000000)}},
+        {VT_exponent,22,0x3a831f,{DOUBLEWITHTWODWORDINTREE(0x04900000,0x00000000)}},
+        {VT_exponent,22,0x3a8320,{DOUBLEWITHTWODWORDINTREE(0x04a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8321,{DOUBLEWITHTWODWORDINTREE(0x04b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8322,{DOUBLEWITHTWODWORDINTREE(0x04c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8323,{DOUBLEWITHTWODWORDINTREE(0x04d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8324,{DOUBLEWITHTWODWORDINTREE(0x04e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8325,{DOUBLEWITHTWODWORDINTREE(0x04f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8326,{DOUBLEWITHTWODWORDINTREE(0x05000000,0x00000000)}},
+        {VT_exponent,22,0x3a8327,{DOUBLEWITHTWODWORDINTREE(0x05100000,0x00000000)}},
+        {VT_exponent,22,0x3a8328,{DOUBLEWITHTWODWORDINTREE(0x05200000,0x00000000)}},
+        {VT_exponent,22,0x3a8329,{DOUBLEWITHTWODWORDINTREE(0x05300000,0x00000000)}},
+        {VT_exponent,22,0x3a832a,{DOUBLEWITHTWODWORDINTREE(0x05400000,0x00000000)}},
+        {VT_exponent,22,0x3a832b,{DOUBLEWITHTWODWORDINTREE(0x05500000,0x00000000)}},
+        {VT_exponent,22,0x3a832c,{DOUBLEWITHTWODWORDINTREE(0x05600000,0x00000000)}},
+        {VT_exponent,22,0x3a832d,{DOUBLEWITHTWODWORDINTREE(0x05700000,0x00000000)}},
+        {VT_exponent,22,0x3a832e,{DOUBLEWITHTWODWORDINTREE(0x05800000,0x00000000)}},
+        {VT_exponent,22,0x3a832f,{DOUBLEWITHTWODWORDINTREE(0x05900000,0x00000000)}},
+        {VT_exponent,22,0x3a8330,{DOUBLEWITHTWODWORDINTREE(0x05a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8331,{DOUBLEWITHTWODWORDINTREE(0x05b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8332,{DOUBLEWITHTWODWORDINTREE(0x05c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8333,{DOUBLEWITHTWODWORDINTREE(0x05d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8334,{DOUBLEWITHTWODWORDINTREE(0x05e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8335,{DOUBLEWITHTWODWORDINTREE(0x05f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8336,{DOUBLEWITHTWODWORDINTREE(0x06000000,0x00000000)}},
+        {VT_exponent,22,0x3a8337,{DOUBLEWITHTWODWORDINTREE(0x06100000,0x00000000)}},
+        {VT_exponent,22,0x3a8338,{DOUBLEWITHTWODWORDINTREE(0x06200000,0x00000000)}},
+        {VT_exponent,22,0x3a8339,{DOUBLEWITHTWODWORDINTREE(0x06300000,0x00000000)}},
+        {VT_exponent,22,0x3a833a,{DOUBLEWITHTWODWORDINTREE(0x06400000,0x00000000)}},
+        {VT_exponent,22,0x3a833b,{DOUBLEWITHTWODWORDINTREE(0x06500000,0x00000000)}},
+        {VT_exponent,22,0x3a833c,{DOUBLEWITHTWODWORDINTREE(0x06600000,0x00000000)}},
+        {VT_exponent,22,0x3a833d,{DOUBLEWITHTWODWORDINTREE(0x06700000,0x00000000)}},
+        {VT_exponent,22,0x3a833e,{DOUBLEWITHTWODWORDINTREE(0x06800000,0x00000000)}},
+        {VT_exponent,22,0x3a833f,{DOUBLEWITHTWODWORDINTREE(0x06900000,0x00000000)}},
+        {VT_exponent,22,0x3a8340,{DOUBLEWITHTWODWORDINTREE(0x06a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8341,{DOUBLEWITHTWODWORDINTREE(0x06b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8342,{DOUBLEWITHTWODWORDINTREE(0x06c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8343,{DOUBLEWITHTWODWORDINTREE(0x06d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8344,{DOUBLEWITHTWODWORDINTREE(0x06e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8345,{DOUBLEWITHTWODWORDINTREE(0x06f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8346,{DOUBLEWITHTWODWORDINTREE(0x07000000,0x00000000)}},
+        {VT_exponent,22,0x3a8347,{DOUBLEWITHTWODWORDINTREE(0x07100000,0x00000000)}},
+        {VT_exponent,22,0x3a8348,{DOUBLEWITHTWODWORDINTREE(0x07200000,0x00000000)}},
+        {VT_exponent,22,0x3a8349,{DOUBLEWITHTWODWORDINTREE(0x07300000,0x00000000)}},
+        {VT_exponent,22,0x3a834a,{DOUBLEWITHTWODWORDINTREE(0x07400000,0x00000000)}},
+        {VT_exponent,22,0x3a834b,{DOUBLEWITHTWODWORDINTREE(0x07500000,0x00000000)}},
+        {VT_exponent,22,0x3a834c,{DOUBLEWITHTWODWORDINTREE(0x07600000,0x00000000)}},
+        {VT_exponent,22,0x3a834d,{DOUBLEWITHTWODWORDINTREE(0x07700000,0x00000000)}},
+        {VT_exponent,22,0x3a834e,{DOUBLEWITHTWODWORDINTREE(0x07800000,0x00000000)}},
+        {VT_exponent,22,0x3a834f,{DOUBLEWITHTWODWORDINTREE(0x07900000,0x00000000)}},
+        {VT_exponent,22,0x3a8350,{DOUBLEWITHTWODWORDINTREE(0x07a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8351,{DOUBLEWITHTWODWORDINTREE(0x07b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8352,{DOUBLEWITHTWODWORDINTREE(0x07c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8353,{DOUBLEWITHTWODWORDINTREE(0x07d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8354,{DOUBLEWITHTWODWORDINTREE(0x07e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8355,{DOUBLEWITHTWODWORDINTREE(0x07f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8356,{DOUBLEWITHTWODWORDINTREE(0x08000000,0x00000000)}},
+        {VT_exponent,22,0x3a8357,{DOUBLEWITHTWODWORDINTREE(0x08100000,0x00000000)}},
+        {VT_exponent,22,0x3a8358,{DOUBLEWITHTWODWORDINTREE(0x08200000,0x00000000)}},
+        {VT_exponent,22,0x3a8359,{DOUBLEWITHTWODWORDINTREE(0x08300000,0x00000000)}},
+        {VT_exponent,22,0x3a835a,{DOUBLEWITHTWODWORDINTREE(0x08400000,0x00000000)}},
+        {VT_exponent,22,0x3a835b,{DOUBLEWITHTWODWORDINTREE(0x08500000,0x00000000)}},
+        {VT_exponent,22,0x3a835c,{DOUBLEWITHTWODWORDINTREE(0x08600000,0x00000000)}},
+        {VT_exponent,22,0x3a835d,{DOUBLEWITHTWODWORDINTREE(0x08700000,0x00000000)}},
+        {VT_exponent,22,0x3a835e,{DOUBLEWITHTWODWORDINTREE(0x08800000,0x00000000)}},
+        {VT_exponent,22,0x3a835f,{DOUBLEWITHTWODWORDINTREE(0x08900000,0x00000000)}},
+        {VT_exponent,22,0x3a8360,{DOUBLEWITHTWODWORDINTREE(0x08a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8361,{DOUBLEWITHTWODWORDINTREE(0x08b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8362,{DOUBLEWITHTWODWORDINTREE(0x08c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8363,{DOUBLEWITHTWODWORDINTREE(0x08d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8364,{DOUBLEWITHTWODWORDINTREE(0x08e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8365,{DOUBLEWITHTWODWORDINTREE(0x08f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8366,{DOUBLEWITHTWODWORDINTREE(0x09000000,0x00000000)}},
+        {VT_exponent,22,0x3a8367,{DOUBLEWITHTWODWORDINTREE(0x09100000,0x00000000)}},
+        {VT_exponent,22,0x3a8368,{DOUBLEWITHTWODWORDINTREE(0x09200000,0x00000000)}},
+        {VT_exponent,22,0x3a8369,{DOUBLEWITHTWODWORDINTREE(0x09300000,0x00000000)}},
+        {VT_exponent,22,0x3a836a,{DOUBLEWITHTWODWORDINTREE(0x09400000,0x00000000)}},
+        {VT_exponent,22,0x3a836b,{DOUBLEWITHTWODWORDINTREE(0x09500000,0x00000000)}},
+        {VT_exponent,22,0x3a836c,{DOUBLEWITHTWODWORDINTREE(0x09600000,0x00000000)}},
+        {VT_exponent,22,0x3a836d,{DOUBLEWITHTWODWORDINTREE(0x09700000,0x00000000)}},
+        {VT_exponent,22,0x3a836e,{DOUBLEWITHTWODWORDINTREE(0x09800000,0x00000000)}},
+        {VT_exponent,22,0x3a836f,{DOUBLEWITHTWODWORDINTREE(0x09900000,0x00000000)}},
+        {VT_exponent,22,0x3a8370,{DOUBLEWITHTWODWORDINTREE(0x09a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8371,{DOUBLEWITHTWODWORDINTREE(0x09b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8372,{DOUBLEWITHTWODWORDINTREE(0x09c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8373,{DOUBLEWITHTWODWORDINTREE(0x09d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8374,{DOUBLEWITHTWODWORDINTREE(0x09e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8375,{DOUBLEWITHTWODWORDINTREE(0x09f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8376,{DOUBLEWITHTWODWORDINTREE(0x0a000000,0x00000000)}},
+        {VT_exponent,22,0x3a8377,{DOUBLEWITHTWODWORDINTREE(0x0a100000,0x00000000)}},
+        {VT_exponent,22,0x3a8378,{DOUBLEWITHTWODWORDINTREE(0x0a200000,0x00000000)}},
+        {VT_exponent,22,0x3a8379,{DOUBLEWITHTWODWORDINTREE(0x0a300000,0x00000000)}},
+        {VT_exponent,22,0x3a837a,{DOUBLEWITHTWODWORDINTREE(0x0a400000,0x00000000)}},
+        {VT_exponent,22,0x3a837b,{DOUBLEWITHTWODWORDINTREE(0x0a500000,0x00000000)}},
+        {VT_exponent,22,0x3a837c,{DOUBLEWITHTWODWORDINTREE(0x0a600000,0x00000000)}},
+        {VT_exponent,22,0x3a837d,{DOUBLEWITHTWODWORDINTREE(0x0a700000,0x00000000)}},
+        {VT_exponent,22,0x3a837e,{DOUBLEWITHTWODWORDINTREE(0x0a800000,0x00000000)}},
+        {VT_exponent,22,0x3a837f,{DOUBLEWITHTWODWORDINTREE(0x0a900000,0x00000000)}},
+        {VT_exponent,22,0x3a8380,{DOUBLEWITHTWODWORDINTREE(0x0aa00000,0x00000000)}},
+        {VT_exponent,22,0x3a8381,{DOUBLEWITHTWODWORDINTREE(0x0ab00000,0x00000000)}},
+        {VT_exponent,22,0x3a8382,{DOUBLEWITHTWODWORDINTREE(0x0ac00000,0x00000000)}},
+        {VT_exponent,22,0x3a8383,{DOUBLEWITHTWODWORDINTREE(0x0ad00000,0x00000000)}},
+        {VT_exponent,22,0x3a8384,{DOUBLEWITHTWODWORDINTREE(0x0ae00000,0x00000000)}},
+        {VT_exponent,22,0x3a8385,{DOUBLEWITHTWODWORDINTREE(0x0af00000,0x00000000)}},
+        {VT_exponent,22,0x3a8386,{DOUBLEWITHTWODWORDINTREE(0x0b000000,0x00000000)}},
+        {VT_exponent,22,0x3a8387,{DOUBLEWITHTWODWORDINTREE(0x0b100000,0x00000000)}},
+        {VT_exponent,22,0x3a8388,{DOUBLEWITHTWODWORDINTREE(0x0b200000,0x00000000)}},
+        {VT_exponent,22,0x3a8389,{DOUBLEWITHTWODWORDINTREE(0x0b300000,0x00000000)}},
+        {VT_exponent,22,0x3a838a,{DOUBLEWITHTWODWORDINTREE(0x0b400000,0x00000000)}},
+        {VT_exponent,22,0x3a838b,{DOUBLEWITHTWODWORDINTREE(0x0b500000,0x00000000)}},
+        {VT_exponent,22,0x3a838c,{DOUBLEWITHTWODWORDINTREE(0x0b600000,0x00000000)}},
+        {VT_exponent,22,0x3a838d,{DOUBLEWITHTWODWORDINTREE(0x0b700000,0x00000000)}},
+        {VT_exponent,22,0x3a838e,{DOUBLEWITHTWODWORDINTREE(0x0b800000,0x00000000)}},
+        {VT_exponent,22,0x3a838f,{DOUBLEWITHTWODWORDINTREE(0x0b900000,0x00000000)}},
+        {VT_exponent,22,0x3a8390,{DOUBLEWITHTWODWORDINTREE(0x0ba00000,0x00000000)}},
+        {VT_exponent,22,0x3a8391,{DOUBLEWITHTWODWORDINTREE(0x0bb00000,0x00000000)}},
+        {VT_exponent,22,0x3a8392,{DOUBLEWITHTWODWORDINTREE(0x0bc00000,0x00000000)}},
+        {VT_exponent,22,0x3a8393,{DOUBLEWITHTWODWORDINTREE(0x0bd00000,0x00000000)}},
+        {VT_exponent,22,0x3a8394,{DOUBLEWITHTWODWORDINTREE(0x0be00000,0x00000000)}},
+        {VT_exponent,22,0x3a8395,{DOUBLEWITHTWODWORDINTREE(0x0bf00000,0x00000000)}},
+        {VT_exponent,22,0x3a8396,{DOUBLEWITHTWODWORDINTREE(0x0c000000,0x00000000)}},
+        {VT_exponent,22,0x3a8397,{DOUBLEWITHTWODWORDINTREE(0x0c100000,0x00000000)}},
+        {VT_exponent,22,0x3a8398,{DOUBLEWITHTWODWORDINTREE(0x0c200000,0x00000000)}},
+        {VT_exponent,22,0x3a8399,{DOUBLEWITHTWODWORDINTREE(0x0c300000,0x00000000)}},
+        {VT_exponent,22,0x3a839a,{DOUBLEWITHTWODWORDINTREE(0x0c400000,0x00000000)}},
+        {VT_exponent,22,0x3a839b,{DOUBLEWITHTWODWORDINTREE(0x0c500000,0x00000000)}},
+        {VT_exponent,22,0x3a839c,{DOUBLEWITHTWODWORDINTREE(0x0c600000,0x00000000)}},
+        {VT_exponent,22,0x3a839d,{DOUBLEWITHTWODWORDINTREE(0x0c700000,0x00000000)}},
+        {VT_exponent,22,0x3a839e,{DOUBLEWITHTWODWORDINTREE(0x0c800000,0x00000000)}},
+        {VT_exponent,22,0x3a839f,{DOUBLEWITHTWODWORDINTREE(0x0c900000,0x00000000)}},
+        {VT_exponent,22,0x3a83a0,{DOUBLEWITHTWODWORDINTREE(0x0ca00000,0x00000000)}},
+        {VT_exponent,22,0x3a83a1,{DOUBLEWITHTWODWORDINTREE(0x0cb00000,0x00000000)}},
+        {VT_exponent,22,0x3a83a2,{DOUBLEWITHTWODWORDINTREE(0x0cc00000,0x00000000)}},
+        {VT_exponent,22,0x3a83a3,{DOUBLEWITHTWODWORDINTREE(0x0cd00000,0x00000000)}},
+        {VT_exponent,22,0x3a83a4,{DOUBLEWITHTWODWORDINTREE(0x0ce00000,0x00000000)}},
+        {VT_exponent,22,0x3a83a5,{DOUBLEWITHTWODWORDINTREE(0x0cf00000,0x00000000)}},
+        {VT_exponent,22,0x3a83a6,{DOUBLEWITHTWODWORDINTREE(0x0d000000,0x00000000)}},
+        {VT_exponent,22,0x3a83a7,{DOUBLEWITHTWODWORDINTREE(0x0d100000,0x00000000)}},
+        {VT_exponent,22,0x3a83a8,{DOUBLEWITHTWODWORDINTREE(0x0d200000,0x00000000)}},
+        {VT_exponent,22,0x3a83a9,{DOUBLEWITHTWODWORDINTREE(0x0d300000,0x00000000)}},
+        {VT_exponent,22,0x3a83aa,{DOUBLEWITHTWODWORDINTREE(0x0d400000,0x00000000)}},
+        {VT_exponent,22,0x3a83ab,{DOUBLEWITHTWODWORDINTREE(0x0d500000,0x00000000)}},
+        {VT_exponent,22,0x3a83ac,{DOUBLEWITHTWODWORDINTREE(0x0d600000,0x00000000)}},
+        {VT_exponent,22,0x3a83ad,{DOUBLEWITHTWODWORDINTREE(0x0d700000,0x00000000)}},
+        {VT_exponent,22,0x3a83ae,{DOUBLEWITHTWODWORDINTREE(0x0d800000,0x00000000)}},
+        {VT_exponent,22,0x3a83af,{DOUBLEWITHTWODWORDINTREE(0x0d900000,0x00000000)}},
+        {VT_exponent,22,0x3a83b0,{DOUBLEWITHTWODWORDINTREE(0x0da00000,0x00000000)}},
+        {VT_exponent,22,0x3a83b1,{DOUBLEWITHTWODWORDINTREE(0x0db00000,0x00000000)}},
+        {VT_exponent,22,0x3a83b2,{DOUBLEWITHTWODWORDINTREE(0x0dc00000,0x00000000)}},
+        {VT_exponent,22,0x3a83b3,{DOUBLEWITHTWODWORDINTREE(0x0dd00000,0x00000000)}},
+        {VT_exponent,22,0x3a83b4,{DOUBLEWITHTWODWORDINTREE(0x0de00000,0x00000000)}},
+        {VT_exponent,22,0x3a83b5,{DOUBLEWITHTWODWORDINTREE(0x0df00000,0x00000000)}},
+        {VT_exponent,22,0x3a83b6,{DOUBLEWITHTWODWORDINTREE(0x0e000000,0x00000000)}},
+        {VT_exponent,22,0x3a83b7,{DOUBLEWITHTWODWORDINTREE(0x0e100000,0x00000000)}},
+        {VT_exponent,22,0x3a83b8,{DOUBLEWITHTWODWORDINTREE(0x0e200000,0x00000000)}},
+        {VT_exponent,22,0x3a83b9,{DOUBLEWITHTWODWORDINTREE(0x0e300000,0x00000000)}},
+        {VT_exponent,22,0x3a83ba,{DOUBLEWITHTWODWORDINTREE(0x0e400000,0x00000000)}},
+        {VT_exponent,22,0x3a83bb,{DOUBLEWITHTWODWORDINTREE(0x0e500000,0x00000000)}},
+        {VT_exponent,22,0x3a83bc,{DOUBLEWITHTWODWORDINTREE(0x0e600000,0x00000000)}},
+        {VT_exponent,22,0x3a83bd,{DOUBLEWITHTWODWORDINTREE(0x0e700000,0x00000000)}},
+        {VT_exponent,22,0x3a83be,{DOUBLEWITHTWODWORDINTREE(0x0e800000,0x00000000)}},
+        {VT_exponent,22,0x3a83bf,{DOUBLEWITHTWODWORDINTREE(0x0e900000,0x00000000)}},
+        {VT_exponent,22,0x3a83c0,{DOUBLEWITHTWODWORDINTREE(0x0ea00000,0x00000000)}},
+        {VT_exponent,22,0x3a83c1,{DOUBLEWITHTWODWORDINTREE(0x0eb00000,0x00000000)}},
+        {VT_exponent,22,0x3a83c2,{DOUBLEWITHTWODWORDINTREE(0x0ec00000,0x00000000)}},
+        {VT_exponent,22,0x3a83c3,{DOUBLEWITHTWODWORDINTREE(0x0ed00000,0x00000000)}},
+        {VT_exponent,22,0x3a83c4,{DOUBLEWITHTWODWORDINTREE(0x0ee00000,0x00000000)}},
+        {VT_exponent,22,0x3a83c5,{DOUBLEWITHTWODWORDINTREE(0x0ef00000,0x00000000)}},
+        {VT_exponent,22,0x3a83c6,{DOUBLEWITHTWODWORDINTREE(0x0f000000,0x00000000)}},
+        {VT_exponent,22,0x3a83c7,{DOUBLEWITHTWODWORDINTREE(0x0f100000,0x00000000)}},
+        {VT_exponent,22,0x3a83c8,{DOUBLEWITHTWODWORDINTREE(0x0f200000,0x00000000)}},
+        {VT_exponent,22,0x3a83c9,{DOUBLEWITHTWODWORDINTREE(0x0f300000,0x00000000)}},
+        {VT_exponent,22,0x3a83ca,{DOUBLEWITHTWODWORDINTREE(0x0f400000,0x00000000)}},
+        {VT_exponent,22,0x3a83cb,{DOUBLEWITHTWODWORDINTREE(0x0f500000,0x00000000)}},
+        {VT_exponent,22,0x3a83cc,{DOUBLEWITHTWODWORDINTREE(0x0f600000,0x00000000)}},
+        {VT_exponent,22,0x3a83cd,{DOUBLEWITHTWODWORDINTREE(0x0f700000,0x00000000)}},
+        {VT_exponent,22,0x3a83ce,{DOUBLEWITHTWODWORDINTREE(0x0f800000,0x00000000)}},
+        {VT_exponent,22,0x3a83cf,{DOUBLEWITHTWODWORDINTREE(0x0f900000,0x00000000)}},
+        {VT_exponent,22,0x3a83d0,{DOUBLEWITHTWODWORDINTREE(0x0fa00000,0x00000000)}},
+        {VT_exponent,22,0x3a83d1,{DOUBLEWITHTWODWORDINTREE(0x0fb00000,0x00000000)}},
+        {VT_exponent,22,0x3a83d2,{DOUBLEWITHTWODWORDINTREE(0x0fc00000,0x00000000)}},
+        {VT_exponent,22,0x3a83d3,{DOUBLEWITHTWODWORDINTREE(0x0fd00000,0x00000000)}},
+        {VT_exponent,22,0x3a83d4,{DOUBLEWITHTWODWORDINTREE(0x0fe00000,0x00000000)}},
+        {VT_exponent,22,0x3a83d5,{DOUBLEWITHTWODWORDINTREE(0x0ff00000,0x00000000)}},
+        {VT_exponent,22,0x3a83d6,{DOUBLEWITHTWODWORDINTREE(0x10000000,0x00000000)}},
+        {VT_exponent,22,0x3a83d7,{DOUBLEWITHTWODWORDINTREE(0x10100000,0x00000000)}},
+        {VT_exponent,22,0x3a83d8,{DOUBLEWITHTWODWORDINTREE(0x10200000,0x00000000)}},
+        {VT_exponent,22,0x3a83d9,{DOUBLEWITHTWODWORDINTREE(0x10300000,0x00000000)}},
+        {VT_exponent,22,0x3a83da,{DOUBLEWITHTWODWORDINTREE(0x10400000,0x00000000)}},
+        {VT_exponent,22,0x3a83db,{DOUBLEWITHTWODWORDINTREE(0x10500000,0x00000000)}},
+        {VT_exponent,22,0x3a83dc,{DOUBLEWITHTWODWORDINTREE(0x10600000,0x00000000)}},
+        {VT_exponent,22,0x3a83dd,{DOUBLEWITHTWODWORDINTREE(0x10700000,0x00000000)}},
+        {VT_exponent,22,0x3a83de,{DOUBLEWITHTWODWORDINTREE(0x10800000,0x00000000)}},
+        {VT_exponent,22,0x3a83df,{DOUBLEWITHTWODWORDINTREE(0x10900000,0x00000000)}},
+        {VT_exponent,22,0x3a83e0,{DOUBLEWITHTWODWORDINTREE(0x10a00000,0x00000000)}},
+        {VT_exponent,22,0x3a83e1,{DOUBLEWITHTWODWORDINTREE(0x10b00000,0x00000000)}},
+        {VT_exponent,22,0x3a83e2,{DOUBLEWITHTWODWORDINTREE(0x10c00000,0x00000000)}},
+        {VT_exponent,22,0x3a83e3,{DOUBLEWITHTWODWORDINTREE(0x10d00000,0x00000000)}},
+        {VT_exponent,22,0x3a83e4,{DOUBLEWITHTWODWORDINTREE(0x10e00000,0x00000000)}},
+        {VT_exponent,22,0x3a83e5,{DOUBLEWITHTWODWORDINTREE(0x10f00000,0x00000000)}},
+        {VT_exponent,22,0x3a83e6,{DOUBLEWITHTWODWORDINTREE(0x11000000,0x00000000)}},
+        {VT_exponent,22,0x3a83e7,{DOUBLEWITHTWODWORDINTREE(0x11100000,0x00000000)}},
+        {VT_exponent,22,0x3a83e8,{DOUBLEWITHTWODWORDINTREE(0x11200000,0x00000000)}},
+        {VT_exponent,22,0x3a83e9,{DOUBLEWITHTWODWORDINTREE(0x11300000,0x00000000)}},
+        {VT_exponent,22,0x3a83ea,{DOUBLEWITHTWODWORDINTREE(0x11400000,0x00000000)}},
+        {VT_exponent,22,0x3a83eb,{DOUBLEWITHTWODWORDINTREE(0x11500000,0x00000000)}},
+        {VT_exponent,22,0x3a83ec,{DOUBLEWITHTWODWORDINTREE(0x11600000,0x00000000)}},
+        {VT_exponent,22,0x3a83ed,{DOUBLEWITHTWODWORDINTREE(0x11700000,0x00000000)}},
+        {VT_exponent,22,0x3a83ee,{DOUBLEWITHTWODWORDINTREE(0x11800000,0x00000000)}},
+        {VT_exponent,22,0x3a83ef,{DOUBLEWITHTWODWORDINTREE(0x11900000,0x00000000)}},
+        {VT_exponent,22,0x3a83f0,{DOUBLEWITHTWODWORDINTREE(0x11a00000,0x00000000)}},
+        {VT_exponent,22,0x3a83f1,{DOUBLEWITHTWODWORDINTREE(0x11b00000,0x00000000)}},
+        {VT_exponent,22,0x3a83f2,{DOUBLEWITHTWODWORDINTREE(0x11c00000,0x00000000)}},
+        {VT_exponent,22,0x3a83f3,{DOUBLEWITHTWODWORDINTREE(0x11d00000,0x00000000)}},
+        {VT_exponent,22,0x3a83f4,{DOUBLEWITHTWODWORDINTREE(0x11e00000,0x00000000)}},
+        {VT_exponent,22,0x3a83f5,{DOUBLEWITHTWODWORDINTREE(0x11f00000,0x00000000)}},
+        {VT_exponent,22,0x3a83f6,{DOUBLEWITHTWODWORDINTREE(0x12000000,0x00000000)}},
+        {VT_exponent,22,0x3a83f7,{DOUBLEWITHTWODWORDINTREE(0x12100000,0x00000000)}},
+        {VT_exponent,22,0x3a83f8,{DOUBLEWITHTWODWORDINTREE(0x12200000,0x00000000)}},
+        {VT_exponent,22,0x3a83f9,{DOUBLEWITHTWODWORDINTREE(0x12300000,0x00000000)}},
+        {VT_exponent,22,0x3a83fa,{DOUBLEWITHTWODWORDINTREE(0x12400000,0x00000000)}},
+        {VT_exponent,22,0x3a83fb,{DOUBLEWITHTWODWORDINTREE(0x12500000,0x00000000)}},
+        {VT_exponent,22,0x3a83fc,{DOUBLEWITHTWODWORDINTREE(0x12600000,0x00000000)}},
+        {VT_exponent,22,0x3a83fd,{DOUBLEWITHTWODWORDINTREE(0x12700000,0x00000000)}},
+        {VT_exponent,22,0x3a83fe,{DOUBLEWITHTWODWORDINTREE(0x12800000,0x00000000)}},
+        {VT_exponent,22,0x3a83ff,{DOUBLEWITHTWODWORDINTREE(0x12900000,0x00000000)}},
+        {VT_exponent,22,0x3a8400,{DOUBLEWITHTWODWORDINTREE(0x12a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8401,{DOUBLEWITHTWODWORDINTREE(0x12b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8402,{DOUBLEWITHTWODWORDINTREE(0x12c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8403,{DOUBLEWITHTWODWORDINTREE(0x12d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8404,{DOUBLEWITHTWODWORDINTREE(0x12e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8405,{DOUBLEWITHTWODWORDINTREE(0x12f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8406,{DOUBLEWITHTWODWORDINTREE(0x13000000,0x00000000)}},
+        {VT_exponent,22,0x3a8407,{DOUBLEWITHTWODWORDINTREE(0x13100000,0x00000000)}},
+        {VT_exponent,22,0x3a8408,{DOUBLEWITHTWODWORDINTREE(0x13200000,0x00000000)}},
+        {VT_exponent,22,0x3a8409,{DOUBLEWITHTWODWORDINTREE(0x13300000,0x00000000)}},
+        {VT_exponent,22,0x3a840a,{DOUBLEWITHTWODWORDINTREE(0x13400000,0x00000000)}},
+        {VT_exponent,22,0x3a840b,{DOUBLEWITHTWODWORDINTREE(0x13500000,0x00000000)}},
+        {VT_exponent,22,0x3a840c,{DOUBLEWITHTWODWORDINTREE(0x13600000,0x00000000)}},
+        {VT_exponent,22,0x3a840d,{DOUBLEWITHTWODWORDINTREE(0x13700000,0x00000000)}},
+        {VT_exponent,22,0x3a840e,{DOUBLEWITHTWODWORDINTREE(0x13800000,0x00000000)}},
+        {VT_exponent,22,0x3a840f,{DOUBLEWITHTWODWORDINTREE(0x13900000,0x00000000)}},
+        {VT_exponent,22,0x3a8410,{DOUBLEWITHTWODWORDINTREE(0x13a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8411,{DOUBLEWITHTWODWORDINTREE(0x13b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8412,{DOUBLEWITHTWODWORDINTREE(0x13c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8413,{DOUBLEWITHTWODWORDINTREE(0x13d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8414,{DOUBLEWITHTWODWORDINTREE(0x13e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8415,{DOUBLEWITHTWODWORDINTREE(0x13f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8416,{DOUBLEWITHTWODWORDINTREE(0x14000000,0x00000000)}},
+        {VT_exponent,22,0x3a8417,{DOUBLEWITHTWODWORDINTREE(0x14100000,0x00000000)}},
+        {VT_exponent,22,0x3a8418,{DOUBLEWITHTWODWORDINTREE(0x14200000,0x00000000)}},
+        {VT_exponent,22,0x3a8419,{DOUBLEWITHTWODWORDINTREE(0x14300000,0x00000000)}},
+        {VT_exponent,22,0x3a841a,{DOUBLEWITHTWODWORDINTREE(0x14400000,0x00000000)}},
+        {VT_exponent,22,0x3a841b,{DOUBLEWITHTWODWORDINTREE(0x14500000,0x00000000)}},
+        {VT_exponent,22,0x3a841c,{DOUBLEWITHTWODWORDINTREE(0x14600000,0x00000000)}},
+        {VT_exponent,22,0x3a841d,{DOUBLEWITHTWODWORDINTREE(0x14700000,0x00000000)}},
+        {VT_exponent,22,0x3a841e,{DOUBLEWITHTWODWORDINTREE(0x14800000,0x00000000)}},
+        {VT_exponent,22,0x3a841f,{DOUBLEWITHTWODWORDINTREE(0x14900000,0x00000000)}},
+        {VT_exponent,22,0x3a8420,{DOUBLEWITHTWODWORDINTREE(0x14a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8421,{DOUBLEWITHTWODWORDINTREE(0x14b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8422,{DOUBLEWITHTWODWORDINTREE(0x14c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8423,{DOUBLEWITHTWODWORDINTREE(0x14d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8424,{DOUBLEWITHTWODWORDINTREE(0x14e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8425,{DOUBLEWITHTWODWORDINTREE(0x14f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8426,{DOUBLEWITHTWODWORDINTREE(0x15000000,0x00000000)}},
+        {VT_exponent,22,0x3a8427,{DOUBLEWITHTWODWORDINTREE(0x15100000,0x00000000)}},
+        {VT_exponent,22,0x3a8428,{DOUBLEWITHTWODWORDINTREE(0x15200000,0x00000000)}},
+        {VT_exponent,22,0x3a8429,{DOUBLEWITHTWODWORDINTREE(0x15300000,0x00000000)}},
+        {VT_exponent,22,0x3a842a,{DOUBLEWITHTWODWORDINTREE(0x15400000,0x00000000)}},
+        {VT_exponent,22,0x3a842b,{DOUBLEWITHTWODWORDINTREE(0x15500000,0x00000000)}},
+        {VT_exponent,22,0x3a842c,{DOUBLEWITHTWODWORDINTREE(0x15600000,0x00000000)}},
+        {VT_exponent,22,0x3a842d,{DOUBLEWITHTWODWORDINTREE(0x15700000,0x00000000)}},
+        {VT_exponent,22,0x3a842e,{DOUBLEWITHTWODWORDINTREE(0x15800000,0x00000000)}},
+        {VT_exponent,22,0x3a842f,{DOUBLEWITHTWODWORDINTREE(0x15900000,0x00000000)}},
+        {VT_exponent,22,0x3a8430,{DOUBLEWITHTWODWORDINTREE(0x15a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8431,{DOUBLEWITHTWODWORDINTREE(0x15b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8432,{DOUBLEWITHTWODWORDINTREE(0x15c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8433,{DOUBLEWITHTWODWORDINTREE(0x15d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8434,{DOUBLEWITHTWODWORDINTREE(0x15e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8435,{DOUBLEWITHTWODWORDINTREE(0x15f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8436,{DOUBLEWITHTWODWORDINTREE(0x16000000,0x00000000)}},
+        {VT_exponent,22,0x3a8437,{DOUBLEWITHTWODWORDINTREE(0x16100000,0x00000000)}},
+        {VT_exponent,22,0x3a8438,{DOUBLEWITHTWODWORDINTREE(0x16200000,0x00000000)}},
+        {VT_exponent,22,0x3a8439,{DOUBLEWITHTWODWORDINTREE(0x16300000,0x00000000)}},
+        {VT_exponent,22,0x3a843a,{DOUBLEWITHTWODWORDINTREE(0x16400000,0x00000000)}},
+        {VT_exponent,22,0x3a843b,{DOUBLEWITHTWODWORDINTREE(0x16500000,0x00000000)}},
+        {VT_exponent,22,0x3a843c,{DOUBLEWITHTWODWORDINTREE(0x16600000,0x00000000)}},
+        {VT_exponent,22,0x3a843d,{DOUBLEWITHTWODWORDINTREE(0x16700000,0x00000000)}},
+        {VT_exponent,22,0x3a843e,{DOUBLEWITHTWODWORDINTREE(0x16800000,0x00000000)}},
+        {VT_exponent,22,0x3a843f,{DOUBLEWITHTWODWORDINTREE(0x16900000,0x00000000)}},
+        {VT_exponent,22,0x3a8440,{DOUBLEWITHTWODWORDINTREE(0x16a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8441,{DOUBLEWITHTWODWORDINTREE(0x16b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8442,{DOUBLEWITHTWODWORDINTREE(0x16c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8443,{DOUBLEWITHTWODWORDINTREE(0x16d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8444,{DOUBLEWITHTWODWORDINTREE(0x16e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8445,{DOUBLEWITHTWODWORDINTREE(0x16f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8446,{DOUBLEWITHTWODWORDINTREE(0x17000000,0x00000000)}},
+        {VT_exponent,22,0x3a8447,{DOUBLEWITHTWODWORDINTREE(0x17100000,0x00000000)}},
+        {VT_exponent,22,0x3a8448,{DOUBLEWITHTWODWORDINTREE(0x17200000,0x00000000)}},
+        {VT_exponent,22,0x3a8449,{DOUBLEWITHTWODWORDINTREE(0x17300000,0x00000000)}},
+        {VT_exponent,22,0x3a844a,{DOUBLEWITHTWODWORDINTREE(0x17400000,0x00000000)}},
+        {VT_exponent,22,0x3a844b,{DOUBLEWITHTWODWORDINTREE(0x17500000,0x00000000)}},
+        {VT_exponent,22,0x3a844c,{DOUBLEWITHTWODWORDINTREE(0x17600000,0x00000000)}},
+        {VT_exponent,22,0x3a844d,{DOUBLEWITHTWODWORDINTREE(0x17700000,0x00000000)}},
+        {VT_exponent,22,0x3a844e,{DOUBLEWITHTWODWORDINTREE(0x17800000,0x00000000)}},
+        {VT_exponent,22,0x3a844f,{DOUBLEWITHTWODWORDINTREE(0x17900000,0x00000000)}},
+        {VT_exponent,22,0x3a8450,{DOUBLEWITHTWODWORDINTREE(0x17a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8451,{DOUBLEWITHTWODWORDINTREE(0x17b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8452,{DOUBLEWITHTWODWORDINTREE(0x17c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8453,{DOUBLEWITHTWODWORDINTREE(0x17d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8454,{DOUBLEWITHTWODWORDINTREE(0x17e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8455,{DOUBLEWITHTWODWORDINTREE(0x17f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8456,{DOUBLEWITHTWODWORDINTREE(0x18000000,0x00000000)}},
+        {VT_exponent,22,0x3a8457,{DOUBLEWITHTWODWORDINTREE(0x18100000,0x00000000)}},
+        {VT_exponent,22,0x3a8458,{DOUBLEWITHTWODWORDINTREE(0x18200000,0x00000000)}},
+        {VT_exponent,22,0x3a8459,{DOUBLEWITHTWODWORDINTREE(0x18300000,0x00000000)}},
+        {VT_exponent,22,0x3a845a,{DOUBLEWITHTWODWORDINTREE(0x18400000,0x00000000)}},
+        {VT_exponent,22,0x3a845b,{DOUBLEWITHTWODWORDINTREE(0x18500000,0x00000000)}},
+        {VT_exponent,22,0x3a845c,{DOUBLEWITHTWODWORDINTREE(0x18600000,0x00000000)}},
+        {VT_exponent,22,0x3a845d,{DOUBLEWITHTWODWORDINTREE(0x18700000,0x00000000)}},
+        {VT_exponent,22,0x3a845e,{DOUBLEWITHTWODWORDINTREE(0x18800000,0x00000000)}},
+        {VT_exponent,22,0x3a845f,{DOUBLEWITHTWODWORDINTREE(0x18900000,0x00000000)}},
+        {VT_exponent,22,0x3a8460,{DOUBLEWITHTWODWORDINTREE(0x18a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8461,{DOUBLEWITHTWODWORDINTREE(0x18b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8462,{DOUBLEWITHTWODWORDINTREE(0x18c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8463,{DOUBLEWITHTWODWORDINTREE(0x18d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8464,{DOUBLEWITHTWODWORDINTREE(0x18e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8465,{DOUBLEWITHTWODWORDINTREE(0x18f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8466,{DOUBLEWITHTWODWORDINTREE(0x19000000,0x00000000)}},
+        {VT_exponent,22,0x3a8467,{DOUBLEWITHTWODWORDINTREE(0x19100000,0x00000000)}},
+        {VT_exponent,22,0x3a8468,{DOUBLEWITHTWODWORDINTREE(0x19200000,0x00000000)}},
+        {VT_exponent,22,0x3a8469,{DOUBLEWITHTWODWORDINTREE(0x19300000,0x00000000)}},
+        {VT_exponent,22,0x3a846a,{DOUBLEWITHTWODWORDINTREE(0x19400000,0x00000000)}},
+        {VT_exponent,22,0x3a846b,{DOUBLEWITHTWODWORDINTREE(0x19500000,0x00000000)}},
+        {VT_exponent,22,0x3a846c,{DOUBLEWITHTWODWORDINTREE(0x19600000,0x00000000)}},
+        {VT_exponent,22,0x3a846d,{DOUBLEWITHTWODWORDINTREE(0x19700000,0x00000000)}},
+        {VT_exponent,22,0x3a846e,{DOUBLEWITHTWODWORDINTREE(0x19800000,0x00000000)}},
+        {VT_exponent,22,0x3a846f,{DOUBLEWITHTWODWORDINTREE(0x19900000,0x00000000)}},
+        {VT_exponent,22,0x3a8470,{DOUBLEWITHTWODWORDINTREE(0x19a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8471,{DOUBLEWITHTWODWORDINTREE(0x19b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8472,{DOUBLEWITHTWODWORDINTREE(0x19c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8473,{DOUBLEWITHTWODWORDINTREE(0x19d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8474,{DOUBLEWITHTWODWORDINTREE(0x19e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8475,{DOUBLEWITHTWODWORDINTREE(0x19f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8476,{DOUBLEWITHTWODWORDINTREE(0x1a000000,0x00000000)}},
+        {VT_exponent,22,0x3a8477,{DOUBLEWITHTWODWORDINTREE(0x1a100000,0x00000000)}},
+        {VT_exponent,22,0x3a8478,{DOUBLEWITHTWODWORDINTREE(0x1a200000,0x00000000)}},
+        {VT_exponent,22,0x3a8479,{DOUBLEWITHTWODWORDINTREE(0x1a300000,0x00000000)}},
+        {VT_exponent,22,0x3a847a,{DOUBLEWITHTWODWORDINTREE(0x1a400000,0x00000000)}},
+        {VT_exponent,22,0x3a847b,{DOUBLEWITHTWODWORDINTREE(0x1a500000,0x00000000)}},
+        {VT_exponent,22,0x3a847c,{DOUBLEWITHTWODWORDINTREE(0x1a600000,0x00000000)}},
+        {VT_exponent,22,0x3a847d,{DOUBLEWITHTWODWORDINTREE(0x1a700000,0x00000000)}},
+        {VT_exponent,22,0x3a847e,{DOUBLEWITHTWODWORDINTREE(0x1a800000,0x00000000)}},
+        {VT_exponent,22,0x3a847f,{DOUBLEWITHTWODWORDINTREE(0x1a900000,0x00000000)}},
+        {VT_exponent,22,0x3a8480,{DOUBLEWITHTWODWORDINTREE(0x1aa00000,0x00000000)}},
+        {VT_exponent,22,0x3a8481,{DOUBLEWITHTWODWORDINTREE(0x1ab00000,0x00000000)}},
+        {VT_exponent,22,0x3a8482,{DOUBLEWITHTWODWORDINTREE(0x1ac00000,0x00000000)}},
+        {VT_exponent,22,0x3a8483,{DOUBLEWITHTWODWORDINTREE(0x1ad00000,0x00000000)}},
+        {VT_exponent,22,0x3a8484,{DOUBLEWITHTWODWORDINTREE(0x1ae00000,0x00000000)}},
+        {VT_exponent,22,0x3a8485,{DOUBLEWITHTWODWORDINTREE(0x1af00000,0x00000000)}},
+        {VT_exponent,22,0x3a8486,{DOUBLEWITHTWODWORDINTREE(0x1b000000,0x00000000)}},
+        {VT_exponent,22,0x3a8487,{DOUBLEWITHTWODWORDINTREE(0x1b100000,0x00000000)}},
+        {VT_exponent,22,0x3a8488,{DOUBLEWITHTWODWORDINTREE(0x1b200000,0x00000000)}},
+        {VT_exponent,22,0x3a8489,{DOUBLEWITHTWODWORDINTREE(0x1b300000,0x00000000)}},
+        {VT_exponent,22,0x3a848a,{DOUBLEWITHTWODWORDINTREE(0x1b400000,0x00000000)}},
+        {VT_exponent,22,0x3a848b,{DOUBLEWITHTWODWORDINTREE(0x1b500000,0x00000000)}},
+        {VT_exponent,22,0x3a848c,{DOUBLEWITHTWODWORDINTREE(0x1b600000,0x00000000)}},
+        {VT_exponent,22,0x3a848d,{DOUBLEWITHTWODWORDINTREE(0x1b700000,0x00000000)}},
+        {VT_exponent,22,0x3a848e,{DOUBLEWITHTWODWORDINTREE(0x1b800000,0x00000000)}},
+        {VT_exponent,22,0x3a848f,{DOUBLEWITHTWODWORDINTREE(0x1b900000,0x00000000)}},
+        {VT_exponent,22,0x3a8490,{DOUBLEWITHTWODWORDINTREE(0x1ba00000,0x00000000)}},
+        {VT_exponent,22,0x3a8491,{DOUBLEWITHTWODWORDINTREE(0x1bb00000,0x00000000)}},
+        {VT_exponent,22,0x3a8492,{DOUBLEWITHTWODWORDINTREE(0x1bc00000,0x00000000)}},
+        {VT_exponent,22,0x3a8493,{DOUBLEWITHTWODWORDINTREE(0x1bd00000,0x00000000)}},
+        {VT_exponent,22,0x3a8494,{DOUBLEWITHTWODWORDINTREE(0x1be00000,0x00000000)}},
+        {VT_exponent,22,0x3a8495,{DOUBLEWITHTWODWORDINTREE(0x1bf00000,0x00000000)}},
+        {VT_exponent,22,0x3a8496,{DOUBLEWITHTWODWORDINTREE(0x1c000000,0x00000000)}},
+        {VT_exponent,22,0x3a8497,{DOUBLEWITHTWODWORDINTREE(0x1c100000,0x00000000)}},
+        {VT_exponent,22,0x3a8498,{DOUBLEWITHTWODWORDINTREE(0x1c200000,0x00000000)}},
+        {VT_exponent,22,0x3a8499,{DOUBLEWITHTWODWORDINTREE(0x1c300000,0x00000000)}},
+        {VT_exponent,22,0x3a849a,{DOUBLEWITHTWODWORDINTREE(0x1c400000,0x00000000)}},
+        {VT_exponent,22,0x3a849b,{DOUBLEWITHTWODWORDINTREE(0x1c500000,0x00000000)}},
+        {VT_exponent,22,0x3a849c,{DOUBLEWITHTWODWORDINTREE(0x1c600000,0x00000000)}},
+        {VT_exponent,22,0x3a849d,{DOUBLEWITHTWODWORDINTREE(0x1c700000,0x00000000)}},
+        {VT_exponent,22,0x3a849e,{DOUBLEWITHTWODWORDINTREE(0x1c800000,0x00000000)}},
+        {VT_exponent,22,0x3a849f,{DOUBLEWITHTWODWORDINTREE(0x1c900000,0x00000000)}},
+        {VT_exponent,22,0x3a84a0,{DOUBLEWITHTWODWORDINTREE(0x1ca00000,0x00000000)}},
+        {VT_exponent,22,0x3a84a1,{DOUBLEWITHTWODWORDINTREE(0x1cb00000,0x00000000)}},
+        {VT_exponent,22,0x3a84a2,{DOUBLEWITHTWODWORDINTREE(0x1cc00000,0x00000000)}},
+        {VT_exponent,22,0x3a84a3,{DOUBLEWITHTWODWORDINTREE(0x1cd00000,0x00000000)}},
+        {VT_exponent,22,0x3a84a4,{DOUBLEWITHTWODWORDINTREE(0x1ce00000,0x00000000)}},
+        {VT_exponent,22,0x3a84a5,{DOUBLEWITHTWODWORDINTREE(0x1cf00000,0x00000000)}},
+        {VT_exponent,22,0x3a84a6,{DOUBLEWITHTWODWORDINTREE(0x1d000000,0x00000000)}},
+        {VT_exponent,22,0x3a84a7,{DOUBLEWITHTWODWORDINTREE(0x1d100000,0x00000000)}},
+        {VT_exponent,22,0x3a84a8,{DOUBLEWITHTWODWORDINTREE(0x1d200000,0x00000000)}},
+        {VT_exponent,22,0x3a84a9,{DOUBLEWITHTWODWORDINTREE(0x1d300000,0x00000000)}},
+        {VT_exponent,22,0x3a84aa,{DOUBLEWITHTWODWORDINTREE(0x1d400000,0x00000000)}},
+        {VT_exponent,22,0x3a84ab,{DOUBLEWITHTWODWORDINTREE(0x1d500000,0x00000000)}},
+        {VT_exponent,22,0x3a84ac,{DOUBLEWITHTWODWORDINTREE(0x1d600000,0x00000000)}},
+        {VT_exponent,22,0x3a84ad,{DOUBLEWITHTWODWORDINTREE(0x1d700000,0x00000000)}},
+        {VT_exponent,22,0x3a84ae,{DOUBLEWITHTWODWORDINTREE(0x1d800000,0x00000000)}},
+        {VT_exponent,22,0x3a84af,{DOUBLEWITHTWODWORDINTREE(0x1d900000,0x00000000)}},
+        {VT_exponent,22,0x3a84b0,{DOUBLEWITHTWODWORDINTREE(0x1da00000,0x00000000)}},
+        {VT_exponent,22,0x3a84b1,{DOUBLEWITHTWODWORDINTREE(0x1db00000,0x00000000)}},
+        {VT_exponent,22,0x3a84b2,{DOUBLEWITHTWODWORDINTREE(0x1dc00000,0x00000000)}},
+        {VT_exponent,22,0x3a84b3,{DOUBLEWITHTWODWORDINTREE(0x1dd00000,0x00000000)}},
+        {VT_exponent,22,0x3a84b4,{DOUBLEWITHTWODWORDINTREE(0x1de00000,0x00000000)}},
+        {VT_exponent,22,0x3a84b5,{DOUBLEWITHTWODWORDINTREE(0x1df00000,0x00000000)}},
+        {VT_exponent,22,0x3a84b6,{DOUBLEWITHTWODWORDINTREE(0x1e000000,0x00000000)}},
+        {VT_exponent,22,0x3a84b7,{DOUBLEWITHTWODWORDINTREE(0x1e100000,0x00000000)}},
+        {VT_exponent,22,0x3a84b8,{DOUBLEWITHTWODWORDINTREE(0x1e200000,0x00000000)}},
+        {VT_exponent,22,0x3a84b9,{DOUBLEWITHTWODWORDINTREE(0x1e300000,0x00000000)}},
+        {VT_exponent,22,0x3a84ba,{DOUBLEWITHTWODWORDINTREE(0x1e400000,0x00000000)}},
+        {VT_exponent,22,0x3a84bb,{DOUBLEWITHTWODWORDINTREE(0x1e500000,0x00000000)}},
+        {VT_exponent,22,0x3a84bc,{DOUBLEWITHTWODWORDINTREE(0x1e600000,0x00000000)}},
+        {VT_exponent,22,0x3a84bd,{DOUBLEWITHTWODWORDINTREE(0x1e700000,0x00000000)}},
+        {VT_exponent,22,0x3a84be,{DOUBLEWITHTWODWORDINTREE(0x1e800000,0x00000000)}},
+        {VT_exponent,22,0x3a84bf,{DOUBLEWITHTWODWORDINTREE(0x1e900000,0x00000000)}},
+        {VT_exponent,22,0x3a84c0,{DOUBLEWITHTWODWORDINTREE(0x1ea00000,0x00000000)}},
+        {VT_exponent,22,0x3a84c1,{DOUBLEWITHTWODWORDINTREE(0x1eb00000,0x00000000)}},
+        {VT_exponent,22,0x3a84c2,{DOUBLEWITHTWODWORDINTREE(0x1ec00000,0x00000000)}},
+        {VT_exponent,22,0x3a84c3,{DOUBLEWITHTWODWORDINTREE(0x1ed00000,0x00000000)}},
+        {VT_exponent,22,0x3a84c4,{DOUBLEWITHTWODWORDINTREE(0x1ee00000,0x00000000)}},
+        {VT_exponent,22,0x3a84c5,{DOUBLEWITHTWODWORDINTREE(0x1ef00000,0x00000000)}},
+        {VT_exponent,22,0x3a84c6,{DOUBLEWITHTWODWORDINTREE(0x1f000000,0x00000000)}},
+        {VT_exponent,22,0x3a84c7,{DOUBLEWITHTWODWORDINTREE(0x1f100000,0x00000000)}},
+        {VT_exponent,22,0x3a84c8,{DOUBLEWITHTWODWORDINTREE(0x1f200000,0x00000000)}},
+        {VT_exponent,22,0x3a84c9,{DOUBLEWITHTWODWORDINTREE(0x1f300000,0x00000000)}},
+        {VT_exponent,22,0x3a84ca,{DOUBLEWITHTWODWORDINTREE(0x1f400000,0x00000000)}},
+        {VT_exponent,22,0x3a84cb,{DOUBLEWITHTWODWORDINTREE(0x1f500000,0x00000000)}},
+        {VT_exponent,22,0x3a84cc,{DOUBLEWITHTWODWORDINTREE(0x1f600000,0x00000000)}},
+        {VT_exponent,22,0x3a84cd,{DOUBLEWITHTWODWORDINTREE(0x1f700000,0x00000000)}},
+        {VT_exponent,22,0x3a84ce,{DOUBLEWITHTWODWORDINTREE(0x1f800000,0x00000000)}},
+        {VT_exponent,22,0x3a84cf,{DOUBLEWITHTWODWORDINTREE(0x1f900000,0x00000000)}},
+        {VT_exponent,22,0x3a84d0,{DOUBLEWITHTWODWORDINTREE(0x1fa00000,0x00000000)}},
+        {VT_exponent,22,0x3a84d1,{DOUBLEWITHTWODWORDINTREE(0x1fb00000,0x00000000)}},
+        {VT_exponent,22,0x3a84d2,{DOUBLEWITHTWODWORDINTREE(0x1fc00000,0x00000000)}},
+        {VT_exponent,22,0x3a84d3,{DOUBLEWITHTWODWORDINTREE(0x1fd00000,0x00000000)}},
+        {VT_exponent,22,0x3a84d4,{DOUBLEWITHTWODWORDINTREE(0x1fe00000,0x00000000)}},
+        {VT_exponent,22,0x3a84d5,{DOUBLEWITHTWODWORDINTREE(0x1ff00000,0x00000000)}},
+        {VT_exponent,22,0x3a84d6,{DOUBLEWITHTWODWORDINTREE(0x20000000,0x00000000)}},
+        {VT_exponent,22,0x3a84d7,{DOUBLEWITHTWODWORDINTREE(0x20100000,0x00000000)}},
+        {VT_exponent,22,0x3a84d8,{DOUBLEWITHTWODWORDINTREE(0x20200000,0x00000000)}},
+        {VT_exponent,22,0x3a84d9,{DOUBLEWITHTWODWORDINTREE(0x20300000,0x00000000)}},
+        {VT_exponent,22,0x3a84da,{DOUBLEWITHTWODWORDINTREE(0x20400000,0x00000000)}},
+        {VT_exponent,22,0x3a84db,{DOUBLEWITHTWODWORDINTREE(0x20500000,0x00000000)}},
+        {VT_exponent,22,0x3a84dc,{DOUBLEWITHTWODWORDINTREE(0x20600000,0x00000000)}},
+        {VT_exponent,22,0x3a84dd,{DOUBLEWITHTWODWORDINTREE(0x20700000,0x00000000)}},
+        {VT_exponent,22,0x3a84de,{DOUBLEWITHTWODWORDINTREE(0x20800000,0x00000000)}},
+        {VT_exponent,22,0x3a84df,{DOUBLEWITHTWODWORDINTREE(0x20900000,0x00000000)}},
+        {VT_exponent,22,0x3a84e0,{DOUBLEWITHTWODWORDINTREE(0x20a00000,0x00000000)}},
+        {VT_exponent,22,0x3a84e1,{DOUBLEWITHTWODWORDINTREE(0x20b00000,0x00000000)}},
+        {VT_exponent,22,0x3a84e2,{DOUBLEWITHTWODWORDINTREE(0x20c00000,0x00000000)}},
+        {VT_exponent,22,0x3a84e3,{DOUBLEWITHTWODWORDINTREE(0x20d00000,0x00000000)}},
+        {VT_exponent,22,0x3a84e4,{DOUBLEWITHTWODWORDINTREE(0x20e00000,0x00000000)}},
+        {VT_exponent,22,0x3a84e5,{DOUBLEWITHTWODWORDINTREE(0x20f00000,0x00000000)}},
+        {VT_exponent,22,0x3a84e6,{DOUBLEWITHTWODWORDINTREE(0x21000000,0x00000000)}},
+        {VT_exponent,22,0x3a84e7,{DOUBLEWITHTWODWORDINTREE(0x21100000,0x00000000)}},
+        {VT_exponent,22,0x3a84e8,{DOUBLEWITHTWODWORDINTREE(0x21200000,0x00000000)}},
+        {VT_exponent,22,0x3a84e9,{DOUBLEWITHTWODWORDINTREE(0x21300000,0x00000000)}},
+        {VT_exponent,22,0x3a84ea,{DOUBLEWITHTWODWORDINTREE(0x21400000,0x00000000)}},
+        {VT_exponent,22,0x3a84eb,{DOUBLEWITHTWODWORDINTREE(0x21500000,0x00000000)}},
+        {VT_exponent,22,0x3a84ec,{DOUBLEWITHTWODWORDINTREE(0x21600000,0x00000000)}},
+        {VT_exponent,22,0x3a84ed,{DOUBLEWITHTWODWORDINTREE(0x21700000,0x00000000)}},
+        {VT_exponent,22,0x3a84ee,{DOUBLEWITHTWODWORDINTREE(0x21800000,0x00000000)}},
+        {VT_exponent,22,0x3a84ef,{DOUBLEWITHTWODWORDINTREE(0x21900000,0x00000000)}},
+        {VT_exponent,22,0x3a84f0,{DOUBLEWITHTWODWORDINTREE(0x21a00000,0x00000000)}},
+        {VT_exponent,22,0x3a84f1,{DOUBLEWITHTWODWORDINTREE(0x21b00000,0x00000000)}},
+        {VT_exponent,22,0x3a84f2,{DOUBLEWITHTWODWORDINTREE(0x21c00000,0x00000000)}},
+        {VT_exponent,22,0x3a84f3,{DOUBLEWITHTWODWORDINTREE(0x21d00000,0x00000000)}},
+        {VT_exponent,22,0x3a84f4,{DOUBLEWITHTWODWORDINTREE(0x21e00000,0x00000000)}},
+        {VT_exponent,22,0x3a84f5,{DOUBLEWITHTWODWORDINTREE(0x21f00000,0x00000000)}},
+        {VT_exponent,22,0x3a84f6,{DOUBLEWITHTWODWORDINTREE(0x22000000,0x00000000)}},
+        {VT_exponent,22,0x3a84f7,{DOUBLEWITHTWODWORDINTREE(0x22100000,0x00000000)}},
+        {VT_exponent,22,0x3a84f8,{DOUBLEWITHTWODWORDINTREE(0x22200000,0x00000000)}},
+        {VT_exponent,22,0x3a84f9,{DOUBLEWITHTWODWORDINTREE(0x22300000,0x00000000)}},
+        {VT_exponent,22,0x3a84fa,{DOUBLEWITHTWODWORDINTREE(0x22400000,0x00000000)}},
+        {VT_exponent,22,0x3a84fb,{DOUBLEWITHTWODWORDINTREE(0x22500000,0x00000000)}},
+        {VT_exponent,22,0x3a84fc,{DOUBLEWITHTWODWORDINTREE(0x22600000,0x00000000)}},
+        {VT_exponent,22,0x3a84fd,{DOUBLEWITHTWODWORDINTREE(0x22700000,0x00000000)}},
+        {VT_exponent,22,0x3a84fe,{DOUBLEWITHTWODWORDINTREE(0x22800000,0x00000000)}},
+        {VT_exponent,22,0x3a84ff,{DOUBLEWITHTWODWORDINTREE(0x22900000,0x00000000)}},
+        {VT_exponent,22,0x3a8500,{DOUBLEWITHTWODWORDINTREE(0x22a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8501,{DOUBLEWITHTWODWORDINTREE(0x22b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8502,{DOUBLEWITHTWODWORDINTREE(0x22c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8503,{DOUBLEWITHTWODWORDINTREE(0x22d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8504,{DOUBLEWITHTWODWORDINTREE(0x22e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8505,{DOUBLEWITHTWODWORDINTREE(0x22f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8506,{DOUBLEWITHTWODWORDINTREE(0x23000000,0x00000000)}},
+        {VT_exponent,22,0x3a8507,{DOUBLEWITHTWODWORDINTREE(0x23100000,0x00000000)}},
+        {VT_exponent,22,0x3a8508,{DOUBLEWITHTWODWORDINTREE(0x23200000,0x00000000)}},
+        {VT_exponent,22,0x3a8509,{DOUBLEWITHTWODWORDINTREE(0x23300000,0x00000000)}},
+        {VT_exponent,22,0x3a850a,{DOUBLEWITHTWODWORDINTREE(0x23400000,0x00000000)}},
+        {VT_exponent,22,0x3a850b,{DOUBLEWITHTWODWORDINTREE(0x23500000,0x00000000)}},
+        {VT_exponent,22,0x3a850c,{DOUBLEWITHTWODWORDINTREE(0x23600000,0x00000000)}},
+        {VT_exponent,22,0x3a850d,{DOUBLEWITHTWODWORDINTREE(0x23700000,0x00000000)}},
+        {VT_exponent,22,0x3a850e,{DOUBLEWITHTWODWORDINTREE(0x23800000,0x00000000)}},
+        {VT_exponent,22,0x3a850f,{DOUBLEWITHTWODWORDINTREE(0x23900000,0x00000000)}},
+        {VT_exponent,22,0x3a8510,{DOUBLEWITHTWODWORDINTREE(0x23a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8511,{DOUBLEWITHTWODWORDINTREE(0x23b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8512,{DOUBLEWITHTWODWORDINTREE(0x23c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8513,{DOUBLEWITHTWODWORDINTREE(0x23d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8514,{DOUBLEWITHTWODWORDINTREE(0x23e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8515,{DOUBLEWITHTWODWORDINTREE(0x23f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8516,{DOUBLEWITHTWODWORDINTREE(0x24000000,0x00000000)}},
+        {VT_exponent,22,0x3a8517,{DOUBLEWITHTWODWORDINTREE(0x24100000,0x00000000)}},
+        {VT_exponent,22,0x3a8518,{DOUBLEWITHTWODWORDINTREE(0x24200000,0x00000000)}},
+        {VT_exponent,22,0x3a8519,{DOUBLEWITHTWODWORDINTREE(0x24300000,0x00000000)}},
+        {VT_exponent,22,0x3a851a,{DOUBLEWITHTWODWORDINTREE(0x24400000,0x00000000)}},
+        {VT_exponent,22,0x3a851b,{DOUBLEWITHTWODWORDINTREE(0x24500000,0x00000000)}},
+        {VT_exponent,22,0x3a851c,{DOUBLEWITHTWODWORDINTREE(0x24600000,0x00000000)}},
+        {VT_exponent,22,0x3a851d,{DOUBLEWITHTWODWORDINTREE(0x24700000,0x00000000)}},
+        {VT_exponent,22,0x3a851e,{DOUBLEWITHTWODWORDINTREE(0x24800000,0x00000000)}},
+        {VT_exponent,22,0x3a851f,{DOUBLEWITHTWODWORDINTREE(0x24900000,0x00000000)}},
+        {VT_exponent,22,0x3a8520,{DOUBLEWITHTWODWORDINTREE(0x24a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8521,{DOUBLEWITHTWODWORDINTREE(0x24b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8522,{DOUBLEWITHTWODWORDINTREE(0x24c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8523,{DOUBLEWITHTWODWORDINTREE(0x24d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8524,{DOUBLEWITHTWODWORDINTREE(0x24e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8525,{DOUBLEWITHTWODWORDINTREE(0x24f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8526,{DOUBLEWITHTWODWORDINTREE(0x25000000,0x00000000)}},
+        {VT_exponent,22,0x3a8527,{DOUBLEWITHTWODWORDINTREE(0x25100000,0x00000000)}},
+        {VT_exponent,22,0x3a8528,{DOUBLEWITHTWODWORDINTREE(0x25200000,0x00000000)}},
+        {VT_exponent,22,0x3a8529,{DOUBLEWITHTWODWORDINTREE(0x25300000,0x00000000)}},
+        {VT_exponent,22,0x3a852a,{DOUBLEWITHTWODWORDINTREE(0x25400000,0x00000000)}},
+        {VT_exponent,22,0x3a852b,{DOUBLEWITHTWODWORDINTREE(0x25500000,0x00000000)}},
+        {VT_exponent,22,0x3a852c,{DOUBLEWITHTWODWORDINTREE(0x25600000,0x00000000)}},
+        {VT_exponent,22,0x3a852d,{DOUBLEWITHTWODWORDINTREE(0x25700000,0x00000000)}},
+        {VT_exponent,22,0x3a852e,{DOUBLEWITHTWODWORDINTREE(0x25800000,0x00000000)}},
+        {VT_exponent,22,0x3a852f,{DOUBLEWITHTWODWORDINTREE(0x25900000,0x00000000)}},
+        {VT_exponent,22,0x3a8530,{DOUBLEWITHTWODWORDINTREE(0x25a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8531,{DOUBLEWITHTWODWORDINTREE(0x25b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8532,{DOUBLEWITHTWODWORDINTREE(0x25c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8533,{DOUBLEWITHTWODWORDINTREE(0x25d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8534,{DOUBLEWITHTWODWORDINTREE(0x25e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8535,{DOUBLEWITHTWODWORDINTREE(0x25f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8536,{DOUBLEWITHTWODWORDINTREE(0x26000000,0x00000000)}},
+        {VT_exponent,22,0x3a8537,{DOUBLEWITHTWODWORDINTREE(0x26100000,0x00000000)}},
+        {VT_exponent,22,0x3a8538,{DOUBLEWITHTWODWORDINTREE(0x26200000,0x00000000)}},
+        {VT_exponent,22,0x3a8539,{DOUBLEWITHTWODWORDINTREE(0x26300000,0x00000000)}},
+        {VT_exponent,22,0x3a853a,{DOUBLEWITHTWODWORDINTREE(0x26400000,0x00000000)}},
+        {VT_exponent,22,0x3a853b,{DOUBLEWITHTWODWORDINTREE(0x26500000,0x00000000)}},
+        {VT_exponent,22,0x3a853c,{DOUBLEWITHTWODWORDINTREE(0x26600000,0x00000000)}},
+        {VT_exponent,22,0x3a853d,{DOUBLEWITHTWODWORDINTREE(0x26700000,0x00000000)}},
+        {VT_exponent,22,0x3a853e,{DOUBLEWITHTWODWORDINTREE(0x26800000,0x00000000)}},
+        {VT_exponent,22,0x3a853f,{DOUBLEWITHTWODWORDINTREE(0x26900000,0x00000000)}},
+        {VT_exponent,22,0x3a8540,{DOUBLEWITHTWODWORDINTREE(0x26a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8541,{DOUBLEWITHTWODWORDINTREE(0x26b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8542,{DOUBLEWITHTWODWORDINTREE(0x26c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8543,{DOUBLEWITHTWODWORDINTREE(0x26d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8544,{DOUBLEWITHTWODWORDINTREE(0x26e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8545,{DOUBLEWITHTWODWORDINTREE(0x26f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8546,{DOUBLEWITHTWODWORDINTREE(0x27000000,0x00000000)}},
+        {VT_exponent,22,0x3a8547,{DOUBLEWITHTWODWORDINTREE(0x27100000,0x00000000)}},
+        {VT_exponent,22,0x3a8548,{DOUBLEWITHTWODWORDINTREE(0x27200000,0x00000000)}},
+        {VT_exponent,22,0x3a8549,{DOUBLEWITHTWODWORDINTREE(0x27300000,0x00000000)}},
+        {VT_exponent,22,0x3a854a,{DOUBLEWITHTWODWORDINTREE(0x27400000,0x00000000)}},
+        {VT_exponent,22,0x3a854b,{DOUBLEWITHTWODWORDINTREE(0x27500000,0x00000000)}},
+        {VT_exponent,22,0x3a854c,{DOUBLEWITHTWODWORDINTREE(0x27600000,0x00000000)}},
+        {VT_exponent,22,0x3a854d,{DOUBLEWITHTWODWORDINTREE(0x27700000,0x00000000)}},
+        {VT_exponent,22,0x3a854e,{DOUBLEWITHTWODWORDINTREE(0x27800000,0x00000000)}},
+        {VT_exponent,22,0x3a854f,{DOUBLEWITHTWODWORDINTREE(0x27900000,0x00000000)}},
+        {VT_exponent,22,0x3a8550,{DOUBLEWITHTWODWORDINTREE(0x27a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8551,{DOUBLEWITHTWODWORDINTREE(0x27b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8552,{DOUBLEWITHTWODWORDINTREE(0x27c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8553,{DOUBLEWITHTWODWORDINTREE(0x27d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8554,{DOUBLEWITHTWODWORDINTREE(0x27e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8555,{DOUBLEWITHTWODWORDINTREE(0x27f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8556,{DOUBLEWITHTWODWORDINTREE(0x28000000,0x00000000)}},
+        {VT_exponent,22,0x3a8557,{DOUBLEWITHTWODWORDINTREE(0x28100000,0x00000000)}},
+        {VT_exponent,22,0x3a8558,{DOUBLEWITHTWODWORDINTREE(0x28200000,0x00000000)}},
+        {VT_exponent,22,0x3a8559,{DOUBLEWITHTWODWORDINTREE(0x28300000,0x00000000)}},
+        {VT_exponent,22,0x3a855a,{DOUBLEWITHTWODWORDINTREE(0x28400000,0x00000000)}},
+        {VT_exponent,22,0x3a855b,{DOUBLEWITHTWODWORDINTREE(0x28500000,0x00000000)}},
+        {VT_exponent,22,0x3a855c,{DOUBLEWITHTWODWORDINTREE(0x28600000,0x00000000)}},
+        {VT_exponent,22,0x3a855d,{DOUBLEWITHTWODWORDINTREE(0x28700000,0x00000000)}},
+        {VT_exponent,22,0x3a855e,{DOUBLEWITHTWODWORDINTREE(0x28800000,0x00000000)}},
+        {VT_exponent,22,0x3a855f,{DOUBLEWITHTWODWORDINTREE(0x28900000,0x00000000)}},
+        {VT_exponent,22,0x3a8560,{DOUBLEWITHTWODWORDINTREE(0x28a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8561,{DOUBLEWITHTWODWORDINTREE(0x28b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8562,{DOUBLEWITHTWODWORDINTREE(0x28c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8563,{DOUBLEWITHTWODWORDINTREE(0x28d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8564,{DOUBLEWITHTWODWORDINTREE(0x28e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8565,{DOUBLEWITHTWODWORDINTREE(0x28f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8566,{DOUBLEWITHTWODWORDINTREE(0x29000000,0x00000000)}},
+        {VT_exponent,22,0x3a8567,{DOUBLEWITHTWODWORDINTREE(0x29100000,0x00000000)}},
+        {VT_exponent,22,0x3a8568,{DOUBLEWITHTWODWORDINTREE(0x29200000,0x00000000)}},
+        {VT_exponent,22,0x3a8569,{DOUBLEWITHTWODWORDINTREE(0x29300000,0x00000000)}},
+        {VT_exponent,22,0x3a856a,{DOUBLEWITHTWODWORDINTREE(0x29400000,0x00000000)}},
+        {VT_exponent,22,0x3a856b,{DOUBLEWITHTWODWORDINTREE(0x29500000,0x00000000)}},
+        {VT_exponent,22,0x3a856c,{DOUBLEWITHTWODWORDINTREE(0x29600000,0x00000000)}},
+        {VT_exponent,22,0x3a856d,{DOUBLEWITHTWODWORDINTREE(0x29700000,0x00000000)}},
+        {VT_exponent,22,0x3a856e,{DOUBLEWITHTWODWORDINTREE(0x29800000,0x00000000)}},
+        {VT_exponent,22,0x3a856f,{DOUBLEWITHTWODWORDINTREE(0x29900000,0x00000000)}},
+        {VT_exponent,22,0x3a8570,{DOUBLEWITHTWODWORDINTREE(0x29a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8571,{DOUBLEWITHTWODWORDINTREE(0x29b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8572,{DOUBLEWITHTWODWORDINTREE(0x29c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8573,{DOUBLEWITHTWODWORDINTREE(0x29d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8574,{DOUBLEWITHTWODWORDINTREE(0x29e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8575,{DOUBLEWITHTWODWORDINTREE(0x29f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8576,{DOUBLEWITHTWODWORDINTREE(0x2a000000,0x00000000)}},
+        {VT_exponent,22,0x3a8577,{DOUBLEWITHTWODWORDINTREE(0x2a100000,0x00000000)}},
+        {VT_exponent,22,0x3a8578,{DOUBLEWITHTWODWORDINTREE(0x2a200000,0x00000000)}},
+        {VT_exponent,22,0x3a8579,{DOUBLEWITHTWODWORDINTREE(0x2a300000,0x00000000)}},
+        {VT_exponent,22,0x3a857a,{DOUBLEWITHTWODWORDINTREE(0x2a400000,0x00000000)}},
+        {VT_exponent,22,0x3a857b,{DOUBLEWITHTWODWORDINTREE(0x2a500000,0x00000000)}},
+        {VT_exponent,22,0x3a857c,{DOUBLEWITHTWODWORDINTREE(0x2a600000,0x00000000)}},
+        {VT_exponent,22,0x3a857d,{DOUBLEWITHTWODWORDINTREE(0x2a700000,0x00000000)}},
+        {VT_exponent,22,0x3a857e,{DOUBLEWITHTWODWORDINTREE(0x2a800000,0x00000000)}},
+        {VT_exponent,22,0x3a857f,{DOUBLEWITHTWODWORDINTREE(0x2a900000,0x00000000)}},
+        {VT_exponent,22,0x3a8580,{DOUBLEWITHTWODWORDINTREE(0x2aa00000,0x00000000)}},
+        {VT_exponent,22,0x3a8581,{DOUBLEWITHTWODWORDINTREE(0x2ab00000,0x00000000)}},
+        {VT_exponent,22,0x3a8582,{DOUBLEWITHTWODWORDINTREE(0x2ac00000,0x00000000)}},
+        {VT_exponent,22,0x3a8583,{DOUBLEWITHTWODWORDINTREE(0x2ad00000,0x00000000)}},
+        {VT_exponent,22,0x3a8584,{DOUBLEWITHTWODWORDINTREE(0x2ae00000,0x00000000)}},
+        {VT_exponent,22,0x3a8585,{DOUBLEWITHTWODWORDINTREE(0x2af00000,0x00000000)}},
+        {VT_exponent,22,0x3a8586,{DOUBLEWITHTWODWORDINTREE(0x2b000000,0x00000000)}},
+        {VT_exponent,22,0x3a8587,{DOUBLEWITHTWODWORDINTREE(0x2b100000,0x00000000)}},
+        {VT_exponent,22,0x3a8588,{DOUBLEWITHTWODWORDINTREE(0x2b200000,0x00000000)}},
+        {VT_exponent,22,0x3a8589,{DOUBLEWITHTWODWORDINTREE(0x2b300000,0x00000000)}},
+        {VT_exponent,22,0x3a858a,{DOUBLEWITHTWODWORDINTREE(0x2b400000,0x00000000)}},
+        {VT_exponent,22,0x3a858b,{DOUBLEWITHTWODWORDINTREE(0x2b500000,0x00000000)}},
+        {VT_exponent,22,0x3a858c,{DOUBLEWITHTWODWORDINTREE(0x2b600000,0x00000000)}},
+        {VT_exponent,22,0x3a858d,{DOUBLEWITHTWODWORDINTREE(0x2b700000,0x00000000)}},
+        {VT_exponent,22,0x3a858e,{DOUBLEWITHTWODWORDINTREE(0x2b800000,0x00000000)}},
+        {VT_exponent,22,0x3a858f,{DOUBLEWITHTWODWORDINTREE(0x2b900000,0x00000000)}},
+        {VT_exponent,22,0x3a8590,{DOUBLEWITHTWODWORDINTREE(0x2ba00000,0x00000000)}},
+        {VT_exponent,22,0x3a8591,{DOUBLEWITHTWODWORDINTREE(0x2bb00000,0x00000000)}},
+        {VT_exponent,22,0x3a8592,{DOUBLEWITHTWODWORDINTREE(0x2bc00000,0x00000000)}},
+        {VT_exponent,22,0x3a8593,{DOUBLEWITHTWODWORDINTREE(0x2bd00000,0x00000000)}},
+        {VT_exponent,22,0x3a8594,{DOUBLEWITHTWODWORDINTREE(0x2be00000,0x00000000)}},
+        {VT_exponent,22,0x3a8595,{DOUBLEWITHTWODWORDINTREE(0x2bf00000,0x00000000)}},
+        {VT_exponent,22,0x3a8596,{DOUBLEWITHTWODWORDINTREE(0x2c000000,0x00000000)}},
+        {VT_exponent,22,0x3a8597,{DOUBLEWITHTWODWORDINTREE(0x2c100000,0x00000000)}},
+        {VT_exponent,22,0x3a8598,{DOUBLEWITHTWODWORDINTREE(0x2c200000,0x00000000)}},
+        {VT_exponent,22,0x3a8599,{DOUBLEWITHTWODWORDINTREE(0x2c300000,0x00000000)}},
+        {VT_exponent,22,0x3a859a,{DOUBLEWITHTWODWORDINTREE(0x2c400000,0x00000000)}},
+        {VT_exponent,22,0x3a859b,{DOUBLEWITHTWODWORDINTREE(0x2c500000,0x00000000)}},
+        {VT_exponent,22,0x3a859c,{DOUBLEWITHTWODWORDINTREE(0x2c600000,0x00000000)}},
+        {VT_exponent,22,0x3a859d,{DOUBLEWITHTWODWORDINTREE(0x2c700000,0x00000000)}},
+        {VT_exponent,22,0x3a859e,{DOUBLEWITHTWODWORDINTREE(0x2c800000,0x00000000)}},
+        {VT_exponent,22,0x3a859f,{DOUBLEWITHTWODWORDINTREE(0x2c900000,0x00000000)}},
+        {VT_exponent,22,0x3a85a0,{DOUBLEWITHTWODWORDINTREE(0x2ca00000,0x00000000)}},
+        {VT_exponent,22,0x3a85a1,{DOUBLEWITHTWODWORDINTREE(0x2cb00000,0x00000000)}},
+        {VT_exponent,22,0x3a85a2,{DOUBLEWITHTWODWORDINTREE(0x2cc00000,0x00000000)}},
+        {VT_exponent,22,0x3a85a3,{DOUBLEWITHTWODWORDINTREE(0x2cd00000,0x00000000)}},
+        {VT_exponent,22,0x3a85a4,{DOUBLEWITHTWODWORDINTREE(0x2ce00000,0x00000000)}},
+        {VT_exponent,22,0x3a85a5,{DOUBLEWITHTWODWORDINTREE(0x2cf00000,0x00000000)}},
+        {VT_exponent,22,0x3a85a6,{DOUBLEWITHTWODWORDINTREE(0x2d000000,0x00000000)}},
+        {VT_exponent,22,0x3a85a7,{DOUBLEWITHTWODWORDINTREE(0x2d100000,0x00000000)}},
+        {VT_exponent,22,0x3a85a8,{DOUBLEWITHTWODWORDINTREE(0x2d200000,0x00000000)}},
+        {VT_exponent,22,0x3a85a9,{DOUBLEWITHTWODWORDINTREE(0x2d300000,0x00000000)}},
+        {VT_exponent,22,0x3a85aa,{DOUBLEWITHTWODWORDINTREE(0x2d400000,0x00000000)}},
+        {VT_exponent,22,0x3a85ab,{DOUBLEWITHTWODWORDINTREE(0x2d500000,0x00000000)}},
+        {VT_exponent,22,0x3a85ac,{DOUBLEWITHTWODWORDINTREE(0x2d600000,0x00000000)}},
+        {VT_exponent,22,0x3a85ad,{DOUBLEWITHTWODWORDINTREE(0x2d700000,0x00000000)}},
+        {VT_exponent,22,0x3a85ae,{DOUBLEWITHTWODWORDINTREE(0x2d800000,0x00000000)}},
+        {VT_exponent,22,0x3a85af,{DOUBLEWITHTWODWORDINTREE(0x2d900000,0x00000000)}},
+        {VT_exponent,22,0x3a85b0,{DOUBLEWITHTWODWORDINTREE(0x2da00000,0x00000000)}},
+        {VT_exponent,22,0x3a85b1,{DOUBLEWITHTWODWORDINTREE(0x2db00000,0x00000000)}},
+        {VT_exponent,22,0x3a85b2,{DOUBLEWITHTWODWORDINTREE(0x2dc00000,0x00000000)}},
+        {VT_exponent,22,0x3a85b3,{DOUBLEWITHTWODWORDINTREE(0x2dd00000,0x00000000)}},
+        {VT_exponent,22,0x3a85b4,{DOUBLEWITHTWODWORDINTREE(0x2de00000,0x00000000)}},
+        {VT_exponent,22,0x3a85b5,{DOUBLEWITHTWODWORDINTREE(0x2df00000,0x00000000)}},
+        {VT_exponent,22,0x3a85b6,{DOUBLEWITHTWODWORDINTREE(0x2e000000,0x00000000)}},
+        {VT_exponent,22,0x3a85b7,{DOUBLEWITHTWODWORDINTREE(0x2e100000,0x00000000)}},
+        {VT_exponent,22,0x3a85b8,{DOUBLEWITHTWODWORDINTREE(0x2e200000,0x00000000)}},
+        {VT_exponent,22,0x3a85b9,{DOUBLEWITHTWODWORDINTREE(0x2e300000,0x00000000)}},
+        {VT_exponent,22,0x3a85ba,{DOUBLEWITHTWODWORDINTREE(0x2e400000,0x00000000)}},
+        {VT_exponent,22,0x3a85bb,{DOUBLEWITHTWODWORDINTREE(0x2e500000,0x00000000)}},
+        {VT_exponent,22,0x3a85bc,{DOUBLEWITHTWODWORDINTREE(0x2e600000,0x00000000)}},
+        {VT_exponent,22,0x3a85bd,{DOUBLEWITHTWODWORDINTREE(0x2e700000,0x00000000)}},
+        {VT_exponent,22,0x3a85be,{DOUBLEWITHTWODWORDINTREE(0x2e800000,0x00000000)}},
+        {VT_exponent,22,0x3a85bf,{DOUBLEWITHTWODWORDINTREE(0x2e900000,0x00000000)}},
+        {VT_exponent,22,0x3a85c0,{DOUBLEWITHTWODWORDINTREE(0x2ea00000,0x00000000)}},
+        {VT_exponent,22,0x3a85c1,{DOUBLEWITHTWODWORDINTREE(0x2eb00000,0x00000000)}},
+        {VT_exponent,22,0x3a85c2,{DOUBLEWITHTWODWORDINTREE(0x2ec00000,0x00000000)}},
+        {VT_exponent,22,0x3a85c3,{DOUBLEWITHTWODWORDINTREE(0x2ed00000,0x00000000)}},
+        {VT_exponent,22,0x3a85c4,{DOUBLEWITHTWODWORDINTREE(0x2ee00000,0x00000000)}},
+        {VT_exponent,22,0x3a85c5,{DOUBLEWITHTWODWORDINTREE(0x2ef00000,0x00000000)}},
+        {VT_exponent,22,0x3a85c6,{DOUBLEWITHTWODWORDINTREE(0x2f000000,0x00000000)}},
+        {VT_exponent,22,0x3a85c7,{DOUBLEWITHTWODWORDINTREE(0x2f100000,0x00000000)}},
+        {VT_exponent,22,0x3a85c8,{DOUBLEWITHTWODWORDINTREE(0x2f200000,0x00000000)}},
+        {VT_exponent,22,0x3a85c9,{DOUBLEWITHTWODWORDINTREE(0x2f300000,0x00000000)}},
+        {VT_exponent,22,0x3a85ca,{DOUBLEWITHTWODWORDINTREE(0x2f400000,0x00000000)}},
+        {VT_exponent,22,0x3a85cb,{DOUBLEWITHTWODWORDINTREE(0x2f500000,0x00000000)}},
+        {VT_exponent,22,0x3a85cc,{DOUBLEWITHTWODWORDINTREE(0x2f600000,0x00000000)}},
+        {VT_exponent,22,0x3a85cd,{DOUBLEWITHTWODWORDINTREE(0x2f700000,0x00000000)}},
+        {VT_exponent,22,0x3a85ce,{DOUBLEWITHTWODWORDINTREE(0x2f800000,0x00000000)}},
+        {VT_exponent,22,0x3a85cf,{DOUBLEWITHTWODWORDINTREE(0x2f900000,0x00000000)}},
+        {VT_exponent,22,0x3a85d0,{DOUBLEWITHTWODWORDINTREE(0x2fa00000,0x00000000)}},
+        {VT_exponent,22,0x3a85d1,{DOUBLEWITHTWODWORDINTREE(0x2fb00000,0x00000000)}},
+        {VT_exponent,22,0x3a85d2,{DOUBLEWITHTWODWORDINTREE(0x2fc00000,0x00000000)}},
+        {VT_exponent,22,0x3a85d3,{DOUBLEWITHTWODWORDINTREE(0x2fd00000,0x00000000)}},
+        {VT_exponent,22,0x3a85d4,{DOUBLEWITHTWODWORDINTREE(0x2fe00000,0x00000000)}},
+        {VT_exponent,22,0x3a85d5,{DOUBLEWITHTWODWORDINTREE(0x2ff00000,0x00000000)}},
+        {VT_exponent,22,0x3a85d6,{DOUBLEWITHTWODWORDINTREE(0x30000000,0x00000000)}},
+        {VT_exponent,22,0x3a85d7,{DOUBLEWITHTWODWORDINTREE(0x30100000,0x00000000)}},
+        {VT_exponent,22,0x3a85d8,{DOUBLEWITHTWODWORDINTREE(0x30200000,0x00000000)}},
+        {VT_exponent,22,0x3a85d9,{DOUBLEWITHTWODWORDINTREE(0x30300000,0x00000000)}},
+        {VT_exponent,22,0x3a85da,{DOUBLEWITHTWODWORDINTREE(0x30400000,0x00000000)}},
+        {VT_exponent,22,0x3a85db,{DOUBLEWITHTWODWORDINTREE(0x30500000,0x00000000)}},
+        {VT_exponent,22,0x3a85dc,{DOUBLEWITHTWODWORDINTREE(0x30600000,0x00000000)}},
+        {VT_exponent,22,0x3a85dd,{DOUBLEWITHTWODWORDINTREE(0x30700000,0x00000000)}},
+        {VT_exponent,22,0x3a85de,{DOUBLEWITHTWODWORDINTREE(0x30800000,0x00000000)}},
+        {VT_exponent,22,0x3a85df,{DOUBLEWITHTWODWORDINTREE(0x30900000,0x00000000)}},
+        {VT_exponent,22,0x3a85e0,{DOUBLEWITHTWODWORDINTREE(0x30a00000,0x00000000)}},
+        {VT_exponent,22,0x3a85e1,{DOUBLEWITHTWODWORDINTREE(0x30b00000,0x00000000)}},
+        {VT_exponent,22,0x3a85e2,{DOUBLEWITHTWODWORDINTREE(0x30c00000,0x00000000)}},
+        {VT_exponent,22,0x3a85e3,{DOUBLEWITHTWODWORDINTREE(0x30d00000,0x00000000)}},
+        {VT_exponent,22,0x3a85e4,{DOUBLEWITHTWODWORDINTREE(0x30e00000,0x00000000)}},
+        {VT_exponent,22,0x3a85e5,{DOUBLEWITHTWODWORDINTREE(0x30f00000,0x00000000)}},
+        {VT_exponent,22,0x3a85e6,{DOUBLEWITHTWODWORDINTREE(0x31000000,0x00000000)}},
+        {VT_exponent,22,0x3a85e7,{DOUBLEWITHTWODWORDINTREE(0x31100000,0x00000000)}},
+        {VT_exponent,22,0x3a85e8,{DOUBLEWITHTWODWORDINTREE(0x31200000,0x00000000)}},
+        {VT_exponent,22,0x3a85e9,{DOUBLEWITHTWODWORDINTREE(0x31300000,0x00000000)}},
+        {VT_exponent,22,0x3a85ea,{DOUBLEWITHTWODWORDINTREE(0x31400000,0x00000000)}},
+        {VT_exponent,22,0x3a85eb,{DOUBLEWITHTWODWORDINTREE(0x31500000,0x00000000)}},
+        {VT_exponent,22,0x3a85ec,{DOUBLEWITHTWODWORDINTREE(0x31600000,0x00000000)}},
+        {VT_exponent,22,0x3a85ed,{DOUBLEWITHTWODWORDINTREE(0x31700000,0x00000000)}},
+        {VT_exponent,22,0x3a85ee,{DOUBLEWITHTWODWORDINTREE(0x31800000,0x00000000)}},
+        {VT_exponent,22,0x3a85ef,{DOUBLEWITHTWODWORDINTREE(0x31900000,0x00000000)}},
+        {VT_exponent,22,0x3a85f0,{DOUBLEWITHTWODWORDINTREE(0x31a00000,0x00000000)}},
+        {VT_exponent,22,0x3a85f1,{DOUBLEWITHTWODWORDINTREE(0x31b00000,0x00000000)}},
+        {VT_exponent,22,0x3a85f2,{DOUBLEWITHTWODWORDINTREE(0x31c00000,0x00000000)}},
+        {VT_exponent,22,0x3a85f3,{DOUBLEWITHTWODWORDINTREE(0x31d00000,0x00000000)}},
+        {VT_exponent,22,0x3a85f4,{DOUBLEWITHTWODWORDINTREE(0x31e00000,0x00000000)}},
+        {VT_exponent,22,0x3a85f5,{DOUBLEWITHTWODWORDINTREE(0x31f00000,0x00000000)}},
+        {VT_exponent,22,0x3a85f6,{DOUBLEWITHTWODWORDINTREE(0x32000000,0x00000000)}},
+        {VT_exponent,22,0x3a85f7,{DOUBLEWITHTWODWORDINTREE(0x32100000,0x00000000)}},
+        {VT_exponent,22,0x3a85f8,{DOUBLEWITHTWODWORDINTREE(0x32200000,0x00000000)}},
+        {VT_exponent,22,0x3a85f9,{DOUBLEWITHTWODWORDINTREE(0x32300000,0x00000000)}},
+        {VT_exponent,22,0x3a85fa,{DOUBLEWITHTWODWORDINTREE(0x32400000,0x00000000)}},
+        {VT_exponent,22,0x3a85fb,{DOUBLEWITHTWODWORDINTREE(0x32500000,0x00000000)}},
+        {VT_exponent,22,0x3a85fc,{DOUBLEWITHTWODWORDINTREE(0x32600000,0x00000000)}},
+        {VT_exponent,22,0x3a85fd,{DOUBLEWITHTWODWORDINTREE(0x32700000,0x00000000)}},
+        {VT_exponent,22,0x3a85fe,{DOUBLEWITHTWODWORDINTREE(0x32800000,0x00000000)}},
+        {VT_exponent,22,0x3a85ff,{DOUBLEWITHTWODWORDINTREE(0x32900000,0x00000000)}},
+        {VT_exponent,22,0x3a8600,{DOUBLEWITHTWODWORDINTREE(0x32a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8601,{DOUBLEWITHTWODWORDINTREE(0x32b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8602,{DOUBLEWITHTWODWORDINTREE(0x32c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8603,{DOUBLEWITHTWODWORDINTREE(0x32d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8604,{DOUBLEWITHTWODWORDINTREE(0x32e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8605,{DOUBLEWITHTWODWORDINTREE(0x32f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8606,{DOUBLEWITHTWODWORDINTREE(0x33000000,0x00000000)}},
+        {VT_exponent,22,0x3a8607,{DOUBLEWITHTWODWORDINTREE(0x33100000,0x00000000)}},
+        {VT_exponent,22,0x3a8608,{DOUBLEWITHTWODWORDINTREE(0x33200000,0x00000000)}},
+        {VT_exponent,22,0x3a8609,{DOUBLEWITHTWODWORDINTREE(0x33300000,0x00000000)}},
+        {VT_exponent,22,0x3a860a,{DOUBLEWITHTWODWORDINTREE(0x33400000,0x00000000)}},
+        {VT_exponent,22,0x3a860b,{DOUBLEWITHTWODWORDINTREE(0x33500000,0x00000000)}},
+        {VT_exponent,22,0x3a860c,{DOUBLEWITHTWODWORDINTREE(0x33600000,0x00000000)}},
+        {VT_exponent,22,0x3a860d,{DOUBLEWITHTWODWORDINTREE(0x33700000,0x00000000)}},
+        {VT_exponent,22,0x3a860e,{DOUBLEWITHTWODWORDINTREE(0x33800000,0x00000000)}},
+        {VT_exponent,22,0x3a860f,{DOUBLEWITHTWODWORDINTREE(0x33900000,0x00000000)}},
+        {VT_exponent,22,0x3a8610,{DOUBLEWITHTWODWORDINTREE(0x33a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8611,{DOUBLEWITHTWODWORDINTREE(0x33b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8612,{DOUBLEWITHTWODWORDINTREE(0x33c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8613,{DOUBLEWITHTWODWORDINTREE(0x33d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8614,{DOUBLEWITHTWODWORDINTREE(0x33e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8615,{DOUBLEWITHTWODWORDINTREE(0x33f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8616,{DOUBLEWITHTWODWORDINTREE(0x34000000,0x00000000)}},
+        {VT_exponent,22,0x3a8617,{DOUBLEWITHTWODWORDINTREE(0x34100000,0x00000000)}},
+        {VT_exponent,22,0x3a8618,{DOUBLEWITHTWODWORDINTREE(0x34200000,0x00000000)}},
+        {VT_exponent,22,0x3a8619,{DOUBLEWITHTWODWORDINTREE(0x34300000,0x00000000)}},
+        {VT_exponent,22,0x3a861a,{DOUBLEWITHTWODWORDINTREE(0x34400000,0x00000000)}},
+        {VT_exponent,22,0x3a861b,{DOUBLEWITHTWODWORDINTREE(0x34500000,0x00000000)}},
+        {VT_exponent,22,0x3a861c,{DOUBLEWITHTWODWORDINTREE(0x34600000,0x00000000)}},
+        {VT_exponent,22,0x3a861d,{DOUBLEWITHTWODWORDINTREE(0x34700000,0x00000000)}},
+        {VT_exponent,22,0x3a861e,{DOUBLEWITHTWODWORDINTREE(0x34800000,0x00000000)}},
+        {VT_exponent,22,0x3a861f,{DOUBLEWITHTWODWORDINTREE(0x34900000,0x00000000)}},
+        {VT_exponent,22,0x3a8620,{DOUBLEWITHTWODWORDINTREE(0x34a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8621,{DOUBLEWITHTWODWORDINTREE(0x34b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8622,{DOUBLEWITHTWODWORDINTREE(0x34c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8623,{DOUBLEWITHTWODWORDINTREE(0x34d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8624,{DOUBLEWITHTWODWORDINTREE(0x34e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8625,{DOUBLEWITHTWODWORDINTREE(0x34f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8626,{DOUBLEWITHTWODWORDINTREE(0x35000000,0x00000000)}},
+        {VT_exponent,22,0x3a8627,{DOUBLEWITHTWODWORDINTREE(0x35100000,0x00000000)}},
+        {VT_exponent,22,0x3a8628,{DOUBLEWITHTWODWORDINTREE(0x35200000,0x00000000)}},
+        {VT_exponent,22,0x3a8629,{DOUBLEWITHTWODWORDINTREE(0x35300000,0x00000000)}},
+        {VT_exponent,18,0xf787,{DOUBLEWITHTWODWORDINTREE(0x35400000,0x00000000)}},
+        {VT_exponent,18,0xd1d4,{DOUBLEWITHTWODWORDINTREE(0x35500000,0x00000000)}},
+        {VT_exponent,19,0x77f9f,{DOUBLEWITHTWODWORDINTREE(0x35600000,0x00000000)}},
+        {VT_exponent,18,0x3b8fb,{DOUBLEWITHTWODWORDINTREE(0x35700000,0x00000000)}},
+        {VT_exponent,19,0x1ef1a,{DOUBLEWITHTWODWORDINTREE(0x35800000,0x00000000)}},
+        {VT_exponent,21,0x1d4315,{DOUBLEWITHTWODWORDINTREE(0x35900000,0x00000000)}},
+        {VT_exponent,16,0x3de2,{DOUBLEWITHTWODWORDINTREE(0x35a00000,0x00000000)}},
+        {VT_exponent,22,0x3a862c,{DOUBLEWITHTWODWORDINTREE(0x35b00000,0x00000000)}},
+        {VT_exponent,22,0x3a862d,{DOUBLEWITHTWODWORDINTREE(0x35c00000,0x00000000)}},
+        {VT_exponent,22,0x3a862e,{DOUBLEWITHTWODWORDINTREE(0x35d00000,0x00000000)}},
+        {VT_exponent,22,0x3a862f,{DOUBLEWITHTWODWORDINTREE(0x35e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8630,{DOUBLEWITHTWODWORDINTREE(0x35f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8631,{DOUBLEWITHTWODWORDINTREE(0x36000000,0x00000000)}},
+        {VT_exponent,22,0x3a8632,{DOUBLEWITHTWODWORDINTREE(0x36100000,0x00000000)}},
+        {VT_exponent,22,0x3a8633,{DOUBLEWITHTWODWORDINTREE(0x36200000,0x00000000)}},
+        {VT_exponent,22,0x3a8634,{DOUBLEWITHTWODWORDINTREE(0x36300000,0x00000000)}},
+        {VT_exponent,22,0x3a8635,{DOUBLEWITHTWODWORDINTREE(0x36400000,0x00000000)}},
+        {VT_exponent,22,0x3a8636,{DOUBLEWITHTWODWORDINTREE(0x36500000,0x00000000)}},
+        {VT_exponent,22,0x3a8637,{DOUBLEWITHTWODWORDINTREE(0x36600000,0x00000000)}},
+        {VT_exponent,22,0x3a8638,{DOUBLEWITHTWODWORDINTREE(0x36700000,0x00000000)}},
+        {VT_exponent,21,0x1d431d,{DOUBLEWITHTWODWORDINTREE(0x36800000,0x00000000)}},
+        {VT_exponent,22,0x3a8639,{DOUBLEWITHTWODWORDINTREE(0x36900000,0x00000000)}},
+        {VT_exponent,22,0x3a863c,{DOUBLEWITHTWODWORDINTREE(0x36a00000,0x00000000)}},
+        {VT_exponent,16,0x3de0,{DOUBLEWITHTWODWORDINTREE(0x36b00000,0x00000000)}},
+        {VT_exponent,18,0x3a95e,{DOUBLEWITHTWODWORDINTREE(0x36c00000,0x00000000)}},
+        {VT_exponent,21,0x1d431f,{DOUBLEWITHTWODWORDINTREE(0x36d00000,0x00000000)}},
+        {VT_exponent,22,0x3a863d,{DOUBLEWITHTWODWORDINTREE(0x36e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8640,{DOUBLEWITHTWODWORDINTREE(0x36f00000,0x00000000)}},
+        {VT_exponent,20,0x34749,{DOUBLEWITHTWODWORDINTREE(0x37000000,0x00000000)}},
+        {VT_exponent,20,0x3474d,{DOUBLEWITHTWODWORDINTREE(0x37100000,0x00000000)}},
+        {VT_exponent,22,0x3a8641,{DOUBLEWITHTWODWORDINTREE(0x37200000,0x00000000)}},
+        {VT_exponent,22,0x3a8642,{DOUBLEWITHTWODWORDINTREE(0x37300000,0x00000000)}},
+        {VT_exponent,22,0x3a8643,{DOUBLEWITHTWODWORDINTREE(0x37400000,0x00000000)}},
+        {VT_exponent,22,0x3a8644,{DOUBLEWITHTWODWORDINTREE(0x37500000,0x00000000)}},
+        {VT_exponent,22,0x3a8645,{DOUBLEWITHTWODWORDINTREE(0x37600000,0x00000000)}},
+        {VT_exponent,22,0x3a8646,{DOUBLEWITHTWODWORDINTREE(0x37700000,0x00000000)}},
+        {VT_exponent,22,0x3a8647,{DOUBLEWITHTWODWORDINTREE(0x37800000,0x00000000)}},
+        {VT_exponent,22,0x3a8648,{DOUBLEWITHTWODWORDINTREE(0x37900000,0x00000000)}},
+        {VT_exponent,22,0x3a8649,{DOUBLEWITHTWODWORDINTREE(0x37a00000,0x00000000)}},
+        {VT_exponent,22,0x3a864a,{DOUBLEWITHTWODWORDINTREE(0x37b00000,0x00000000)}},
+        {VT_exponent,22,0x3a864b,{DOUBLEWITHTWODWORDINTREE(0x37c00000,0x00000000)}},
+        {VT_exponent,22,0x3a864c,{DOUBLEWITHTWODWORDINTREE(0x37d00000,0x00000000)}},
+        {VT_exponent,22,0x3a864d,{DOUBLEWITHTWODWORDINTREE(0x37e00000,0x00000000)}},
+        {VT_exponent,22,0x3a864e,{DOUBLEWITHTWODWORDINTREE(0x37f00000,0x00000000)}},
+        {VT_exponent,22,0x3a864f,{DOUBLEWITHTWODWORDINTREE(0x38000000,0x00000000)}},
+        {VT_exponent,22,0x3a8650,{DOUBLEWITHTWODWORDINTREE(0x38100000,0x00000000)}},
+        {VT_exponent,22,0x3a8651,{DOUBLEWITHTWODWORDINTREE(0x38200000,0x00000000)}},
+        {VT_exponent,22,0x3a8652,{DOUBLEWITHTWODWORDINTREE(0x38300000,0x00000000)}},
+        {VT_exponent,22,0x3a8653,{DOUBLEWITHTWODWORDINTREE(0x38400000,0x00000000)}},
+        {VT_exponent,22,0x3a8654,{DOUBLEWITHTWODWORDINTREE(0x38500000,0x00000000)}},
+        {VT_exponent,22,0x3a8655,{DOUBLEWITHTWODWORDINTREE(0x38600000,0x00000000)}},
+        {VT_exponent,22,0x3a8656,{DOUBLEWITHTWODWORDINTREE(0x38700000,0x00000000)}},
+        {VT_exponent,22,0x3a8657,{DOUBLEWITHTWODWORDINTREE(0x38800000,0x00000000)}},
+        {VT_exponent,22,0x3a8658,{DOUBLEWITHTWODWORDINTREE(0x38900000,0x00000000)}},
+        {VT_exponent,22,0x3a8659,{DOUBLEWITHTWODWORDINTREE(0x38a00000,0x00000000)}},
+        {VT_exponent,22,0x3a865a,{DOUBLEWITHTWODWORDINTREE(0x38b00000,0x00000000)}},
+        {VT_exponent,22,0x3a865b,{DOUBLEWITHTWODWORDINTREE(0x38c00000,0x00000000)}},
+        {VT_exponent,22,0x3a865c,{DOUBLEWITHTWODWORDINTREE(0x38d00000,0x00000000)}},
+        {VT_exponent,22,0x3a865d,{DOUBLEWITHTWODWORDINTREE(0x38e00000,0x00000000)}},
+        {VT_exponent,21,0x1d432f,{DOUBLEWITHTWODWORDINTREE(0x38f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8660,{DOUBLEWITHTWODWORDINTREE(0x39000000,0x00000000)}},
+        {VT_exponent,22,0x3a8661,{DOUBLEWITHTWODWORDINTREE(0x39100000,0x00000000)}},
+        {VT_exponent,22,0x3a8662,{DOUBLEWITHTWODWORDINTREE(0x39200000,0x00000000)}},
+        {VT_exponent,21,0x1d4332,{DOUBLEWITHTWODWORDINTREE(0x39300000,0x00000000)}},
+        {VT_exponent,18,0xd1d5,{DOUBLEWITHTWODWORDINTREE(0x39400000,0x00000000)}},
+        {VT_exponent,18,0x3bfda,{DOUBLEWITHTWODWORDINTREE(0x39500000,0x00000000)}},
+        {VT_exponent,15,0x7528,{DOUBLEWITHTWODWORDINTREE(0x39600000,0x00000000)}},
+        {VT_exponent,15,0x7529,{DOUBLEWITHTWODWORDINTREE(0x39700000,0x00000000)}},
+        {VT_exponent,18,0x3a95f,{DOUBLEWITHTWODWORDINTREE(0x39800000,0x00000000)}},
+        {VT_exponent,17,0x1d434,{DOUBLEWITHTWODWORDINTREE(0x39900000,0x00000000)}},
+        {VT_exponent,19,0x750cd,{DOUBLEWITHTWODWORDINTREE(0x39a00000,0x00000000)}},
+        {VT_exponent,18,0x3a867,{DOUBLEWITHTWODWORDINTREE(0x39b00000,0x00000000)}},
+        {VT_exponent,19,0x771fd,{DOUBLEWITHTWODWORDINTREE(0x39c00000,0x00000000)}},
+        {VT_exponent,15,0x7764,{DOUBLEWITHTWODWORDINTREE(0x39d00000,0x00000000)}},
+        {VT_exponent,20,0xee3f9,{DOUBLEWITHTWODWORDINTREE(0x39e00000,0x00000000)}},
+        {VT_exponent,18,0x3bfdb,{DOUBLEWITHTWODWORDINTREE(0x39f00000,0x00000000)}},
+        {VT_exponent,16,0xeff7,{DOUBLEWITHTWODWORDINTREE(0x3a000000,0x00000000)}},
+        {VT_exponent,18,0xd1d6,{DOUBLEWITHTWODWORDINTREE(0x3a100000,0x00000000)}},
+        {VT_exponent,22,0x3a8663,{DOUBLEWITHTWODWORDINTREE(0x3a200000,0x00000000)}},
+        {VT_exponent,22,0x3a8666,{DOUBLEWITHTWODWORDINTREE(0x3a300000,0x00000000)}},
+        {VT_exponent,18,0x3b8fa,{DOUBLEWITHTWODWORDINTREE(0x3a400000,0x00000000)}},
+        {VT_exponent,17,0x1d435,{DOUBLEWITHTWODWORDINTREE(0x3a500000,0x00000000)}},
+        {VT_exponent,17,0x1dfe4,{DOUBLEWITHTWODWORDINTREE(0x3a600000,0x00000000)}},
+        {VT_exponent,19,0x750d8,{DOUBLEWITHTWODWORDINTREE(0x3a700000,0x00000000)}},
+        {VT_exponent,18,0x3a95b,{DOUBLEWITHTWODWORDINTREE(0x3a800000,0x00000000)}},
+        {VT_exponent,19,0x77f9e,{DOUBLEWITHTWODWORDINTREE(0x3a900000,0x00000000)}},
+        {VT_exponent,19,0x750d9,{DOUBLEWITHTWODWORDINTREE(0x3aa00000,0x00000000)}},
+        {VT_exponent,18,0xd1d7,{DOUBLEWITHTWODWORDINTREE(0x3ab00000,0x00000000)}},
+        {VT_exponent,18,0x3b8ff,{DOUBLEWITHTWODWORDINTREE(0x3ac00000,0x00000000)}},
+        {VT_exponent,17,0x1dc7c,{DOUBLEWITHTWODWORDINTREE(0x3ad00000,0x00000000)}},
+        {VT_exponent,19,0x750da,{DOUBLEWITHTWODWORDINTREE(0x3ae00000,0x00000000)}},
+        {VT_exponent,17,0x7bc2,{DOUBLEWITHTWODWORDINTREE(0x3af00000,0x00000000)}},
+        {VT_exponent,18,0x3bfca,{DOUBLEWITHTWODWORDINTREE(0x3b000000,0x00000000)}},
+        {VT_exponent,19,0x1a3a5,{DOUBLEWITHTWODWORDINTREE(0x3b100000,0x00000000)}},
+        {VT_exponent,17,0x1d4ac,{DOUBLEWITHTWODWORDINTREE(0x3b200000,0x00000000)}},
+        {VT_exponent,18,0x3a86e,{DOUBLEWITHTWODWORDINTREE(0x3b300000,0x00000000)}},
+        {VT_exponent,17,0x1d438,{DOUBLEWITHTWODWORDINTREE(0x3b400000,0x00000000)}},
+        {VT_exponent,18,0x3bfcb,{DOUBLEWITHTWODWORDINTREE(0x3b500000,0x00000000)}},
+        {VT_exponent,19,0x1a3a7,{DOUBLEWITHTWODWORDINTREE(0x3b600000,0x00000000)}},
+        {VT_exponent,17,0x1d4ae,{DOUBLEWITHTWODWORDINTREE(0x3b700000,0x00000000)}},
+        {VT_exponent,18,0x3bfce,{DOUBLEWITHTWODWORDINTREE(0x3b800000,0x00000000)}},
+        {VT_exponent,18,0xf78c,{DOUBLEWITHTWODWORDINTREE(0x3b900000,0x00000000)}},
+        {VT_exponent,17,0x1dfec,{DOUBLEWITHTWODWORDINTREE(0x3ba00000,0x00000000)}},
+        {VT_exponent,17,0x1d439,{DOUBLEWITHTWODWORDINTREE(0x3bb00000,0x00000000)}},
+        {VT_exponent,17,0x68e8,{DOUBLEWITHTWODWORDINTREE(0x3bc00000,0x00000000)}},
+        {VT_exponent,18,0xf786,{DOUBLEWITHTWODWORDINTREE(0x3bd00000,0x00000000)}},
+        {VT_exponent,15,0x771e,{DOUBLEWITHTWODWORDINTREE(0x3be00000,0x00000000)}},
+        {VT_exponent,17,0x1dfe6,{DOUBLEWITHTWODWORDINTREE(0x3bf00000,0x00000000)}},
+        {VT_exponent,15,0x77f8,{DOUBLEWITHTWODWORDINTREE(0x3c000000,0x00000000)}},
+        {VT_exponent,14,0x3bb3,{DOUBLEWITHTWODWORDINTREE(0x3c100000,0x00000000)}},
+        {VT_exponent,14,0x3b8e,{DOUBLEWITHTWODWORDINTREE(0x3c200000,0x00000000)}},
+        {VT_exponent,14,0x3a82,{DOUBLEWITHTWODWORDINTREE(0x3c300000,0x00000000)}},
+        {VT_exponent,14,0x3b96,{DOUBLEWITHTWODWORDINTREE(0x3c400000,0x00000000)}},
+        {VT_exponent,13,0x68f,{DOUBLEWITHTWODWORDINTREE(0x3c500000,0x00000000)}},
+        {VT_exponent,12,0x3d4,{DOUBLEWITHTWODWORDINTREE(0x3c600000,0x00000000)}},
+        {VT_exponent,13,0x1dca,{DOUBLEWITHTWODWORDINTREE(0x3c700000,0x00000000)}},
+        {VT_exponent,12,0x346,{DOUBLEWITHTWODWORDINTREE(0x3c800000,0x00000000)}},
+        {VT_exponent,12,0xee7,{DOUBLEWITHTWODWORDINTREE(0x3c900000,0x00000000)}},
+        {VT_exponent,12,0xeea,{DOUBLEWITHTWODWORDINTREE(0x3ca00000,0x00000000)}},
+        {VT_exponent,11,0x1ed,{DOUBLEWITHTWODWORDINTREE(0x3cb00000,0x00000000)}},
+        {VT_exponent,12,0x3df,{DOUBLEWITHTWODWORDINTREE(0x3cc00000,0x00000000)}},
+        {VT_exponent,11,0x1a2,{DOUBLEWITHTWODWORDINTREE(0x3cd00000,0x00000000)}},
+        {VT_exponent,11,0x56f,{DOUBLEWITHTWODWORDINTREE(0x3ce00000,0x00000000)}},
+        {VT_exponent,11,0xb9,{DOUBLEWITHTWODWORDINTREE(0x3cf00000,0x00000000)}},
+        {VT_exponent,13,0x7b2,{DOUBLEWITHTWODWORDINTREE(0x3d000000,0x00000000)}},
+        {VT_exponent,13,0x1dd8,{DOUBLEWITHTWODWORDINTREE(0x3d100000,0x00000000)}},
+        {VT_exponent,13,0x15ba,{DOUBLEWITHTWODWORDINTREE(0x3d200000,0x00000000)}},
+        {VT_exponent,12,0xee6,{DOUBLEWITHTWODWORDINTREE(0x3d300000,0x00000000)}},
+        {VT_exponent,13,0x15b8,{DOUBLEWITHTWODWORDINTREE(0x3d400000,0x00000000)}},
+        {VT_exponent,14,0xf79,{DOUBLEWITHTWODWORDINTREE(0x3d500000,0x00000000)}},
+        {VT_exponent,14,0x3a81,{DOUBLEWITHTWODWORDINTREE(0x3d600000,0x00000000)}},
+        {VT_exponent,14,0xd1c,{DOUBLEWITHTWODWORDINTREE(0x3d700000,0x00000000)}},
+        {VT_exponent,15,0x7765,{DOUBLEWITHTWODWORDINTREE(0x3d800000,0x00000000)}},
+        {VT_exponent,14,0xf54,{DOUBLEWITHTWODWORDINTREE(0x3d900000,0x00000000)}},
+        {VT_exponent,13,0x15b9,{DOUBLEWITHTWODWORDINTREE(0x3da00000,0x00000000)}},
+        {VT_exponent,13,0x7ab,{DOUBLEWITHTWODWORDINTREE(0x3db00000,0x00000000)}},
+        {VT_exponent,15,0x7500,{DOUBLEWITHTWODWORDINTREE(0x3dc00000,0x00000000)}},
+        {VT_exponent,15,0x1eaa,{DOUBLEWITHTWODWORDINTREE(0x3dd00000,0x00000000)}},
+        {VT_exponent,15,0x7501,{DOUBLEWITHTWODWORDINTREE(0x3de00000,0x00000000)}},
+        {VT_exponent,15,0x1eab,{DOUBLEWITHTWODWORDINTREE(0x3df00000,0x00000000)}},
+        {VT_exponent,14,0x3b97,{DOUBLEWITHTWODWORDINTREE(0x3e000000,0x00000000)}},
+        {VT_exponent,15,0x752a,{DOUBLEWITHTWODWORDINTREE(0x3e100000,0x00000000)}},
+        {VT_exponent,15,0x77fa,{DOUBLEWITHTWODWORDINTREE(0x3e200000,0x00000000)}},
+        {VT_double,10,0xf4,{DOUBLEWITHTWODWORDINTREE(0x3e35798e,0xe2308c3a)}},
+        {VT_exponent,14,0x3a93,{DOUBLEWITHTWODWORDINTREE(0x3e300000,0x00000000)}},
+        {VT_double,11,0x77c,{DOUBLEWITHTWODWORDINTREE(0x3e45798e,0xe2308c3a)}},
+        {VT_exponent,13,0x1dc6,{DOUBLEWITHTWODWORDINTREE(0x3e400000,0x00000000)}},
+        {VT_exponent,13,0x7bd,{DOUBLEWITHTWODWORDINTREE(0x3e500000,0x00000000)}},
+        {VT_exponent,13,0x1dff,{DOUBLEWITHTWODWORDINTREE(0x3e600000,0x00000000)}},
+        {VT_exponent,12,0xefe,{DOUBLEWITHTWODWORDINTREE(0x3e700000,0x00000000)}},
+        {VT_double,8,0xaf,{DOUBLEWITHTWODWORDINTREE(0x3e8ad7f2,0x9abcaf4a)}},
+        {VT_exponent,12,0xeed,{DOUBLEWITHTWODWORDINTREE(0x3e800000,0x00000000)}},
+        {VT_exponent,11,0xb8,{DOUBLEWITHTWODWORDINTREE(0x3e900000,0x00000000)}},
+        {VT_exponent,12,0x3d8,{DOUBLEWITHTWODWORDINTREE(0x3ea00000,0x00000000)}},
+        {VT_exponent,11,0x1eb,{DOUBLEWITHTWODWORDINTREE(0x3eb00000,0x00000000)}},
+        {VT_double,9,0x1d2,{DOUBLEWITHTWODWORDINTREE(0x3ec0c6f7,0xa0b5ed8e)}},
+        {VT_exponent,13,0x1d4b,{DOUBLEWITHTWODWORDINTREE(0x3ec00000,0x00000000)}},
+        {VT_exponent,13,0x7b3,{DOUBLEWITHTWODWORDINTREE(0x3ed00000,0x00000000)}},
+        {VT_exponent,10,0x5d,{DOUBLEWITHTWODWORDINTREE(0x3ee00000,0x00000000)}},
+        {VT_exponent,12,0xeeb,{DOUBLEWITHTWODWORDINTREE(0x3ef00000,0x00000000)}},
+        {VT_exponent,11,0x1ee,{DOUBLEWITHTWODWORDINTREE(0x3f000000,0x00000000)}},
+        {VT_exponent,10,0x5f,{DOUBLEWITHTWODWORDINTREE(0x3f100000,0x00000000)}},
+        {VT_exponent,10,0x2b6,{DOUBLEWITHTWODWORDINTREE(0x3f200000,0x00000000)}},
+        {VT_exponent,9,0x1de,{DOUBLEWITHTWODWORDINTREE(0x3f300000,0x00000000)}},
+        {VT_double,10,0xd0,{DOUBLEWITHTWODWORDINTREE(0x3f454c98,0x5f06f694)}},
+        {VT_double,6,0x9,{DOUBLEWITHTWODWORDINTREE(0x3f4a36e2,0xeb1c432d)}},
+        {VT_exponent,8,0xe8,{DOUBLEWITHTWODWORDINTREE(0x3f400000,0x00000000)}},
+        {VT_double,4,0xf,{DOUBLEWITHTWODWORDINTREE(0x3f50624d,0xd2f1a9fc)}},
+        {VT_exponent,8,0xae,{DOUBLEWITHTWODWORDINTREE(0x3f500000,0x00000000)}},
+        {VT_double,5,0x16,{DOUBLEWITHTWODWORDINTREE(0x3f60624d,0xd2f1a9fc)}},
+        {VT_exponent,7,0x1b,{DOUBLEWITHTWODWORDINTREE(0x3f600000,0x00000000)}},
+        {VT_exponent,7,0x76,{DOUBLEWITHTWODWORDINTREE(0x3f700000,0x00000000)}},
+        {VT_exponent,7,0xa,{DOUBLEWITHTWODWORDINTREE(0x3f800000,0x00000000)}},
+        {VT_exponent,6,0x8,{DOUBLEWITHTWODWORDINTREE(0x3f900000,0x00000000)}},
+        {VT_exponent,6,0xe,{DOUBLEWITHTWODWORDINTREE(0x3fa00000,0x00000000)}},
+        {VT_double,11,0x751,{DOUBLEWITHTWODWORDINTREE(0x3fbe69ad,0x42c3c9ee)}},
+        {VT_exponent,6,0x4,{DOUBLEWITHTWODWORDINTREE(0x3fb00000,0x00000000)}},
+        {VT_exponent,6,0xc,{DOUBLEWITHTWODWORDINTREE(0x3fc00000,0x00000000)}},
+        {VT_exponent,5,0x3,{DOUBLEWITHTWODWORDINTREE(0x3fd00000,0x00000000)}},
+        {VT_double,11,0x777,{DOUBLEWITHTWODWORDINTREE(0x3fe00000,0x00000000)}},
+        {VT_double,9,0x1d6,{DOUBLEWITHTWODWORDINTREE(0x3fefffff,0xf8000002)}},
+        {VT_exponent,4,0x8,{DOUBLEWITHTWODWORDINTREE(0x3fe00000,0x00000000)}},
+        {VT_double,4,0x0,{DOUBLEWITHTWODWORDINTREE(0x3ff00000,0x00000000)}},
+        {VT_exponent,5,0x13,{DOUBLEWITHTWODWORDINTREE(0x3ff00000,0x00000000)}},
+        {VT_exponent,5,0x1b,{DOUBLEWITHTWODWORDINTREE(0x40000000,0x00000000)}},
+        {VT_double,9,0x15a,{DOUBLEWITHTWODWORDINTREE(0x401921fb,0x54442d18)}},
+        {VT_exponent,5,0x17,{DOUBLEWITHTWODWORDINTREE(0x40100000,0x00000000)}},
+        {VT_exponent,5,0x12,{DOUBLEWITHTWODWORDINTREE(0x40200000,0x00000000)}},
+        {VT_double,11,0x774,{DOUBLEWITHTWODWORDINTREE(0x4035ee14,0x80000000)}},
+        {VT_exponent,5,0x19,{DOUBLEWITHTWODWORDINTREE(0x40300000,0x00000000)}},
+        {VT_double,9,0x1d3,{DOUBLEWITHTWODWORDINTREE(0x404ca5dc,0x1a63c1f8)}},
+        {VT_exponent,5,0x1a,{DOUBLEWITHTWODWORDINTREE(0x40400000,0x00000000)}},
+        {VT_double,11,0x77e,{DOUBLEWITHTWODWORDINTREE(0x405bb32f,0xe0000000)}},
+        {VT_double,10,0x5e,{DOUBLEWITHTWODWORDINTREE(0x405c332f,0xe0000000)}},
+        {VT_exponent,5,0x18,{DOUBLEWITHTWODWORDINTREE(0x40500000,0x00000000)}},
+        {VT_double,9,0x1d7,{DOUBLEWITHTWODWORDINTREE(0x40668000,0x00000000)}},
+        {VT_exponent,5,0x1c,{DOUBLEWITHTWODWORDINTREE(0x40600000,0x00000000)}},
+        {VT_double,9,0x1d5,{DOUBLEWITHTWODWORDINTREE(0x40768000,0x00000000)}},
+        {VT_exponent,5,0x14,{DOUBLEWITHTWODWORDINTREE(0x40700000,0x00000000)}},
+        {VT_double,11,0x77d,{DOUBLEWITHTWODWORDINTREE(0x408f4000,0x00000000)}},
+        {VT_exponent,5,0x5,{DOUBLEWITHTWODWORDINTREE(0x40800000,0x00000000)}},
+        {VT_double,10,0xd2,{DOUBLEWITHTWODWORDINTREE(0x409233ff,0xffffffff)}},
+        {VT_double,8,0x3c,{DOUBLEWITHTWODWORDINTREE(0x40923400,0x00000000)}},
+        {VT_double,11,0x753,{DOUBLEWITHTWODWORDINTREE(0x40923400,0x00000001)}},
+        {VT_double,10,0xd3,{DOUBLEWITHTWODWORDINTREE(0x4092abff,0xffffffff)}},
+        {VT_double,8,0x35,{DOUBLEWITHTWODWORDINTREE(0x4092ac00,0x00000000)}},
+        {VT_double,11,0x770,{DOUBLEWITHTWODWORDINTREE(0x4092ac00,0x00000001)}},
+        {VT_exponent,8,0x16,{DOUBLEWITHTWODWORDINTREE(0x40900000,0x00000000)}},
+        {VT_exponent,12,0xee2,{DOUBLEWITHTWODWORDINTREE(0x40a00000,0x00000000)}},
+        {VT_exponent,12,0xee4,{DOUBLEWITHTWODWORDINTREE(0x40b00000,0x00000000)}},
+        {VT_double,7,0x1f,{DOUBLEWITHTWODWORDINTREE(0x40c81c80,0x00000000)}},
+        {VT_exponent,8,0xac,{DOUBLEWITHTWODWORDINTREE(0x40c00000,0x00000000)}},
+        {VT_exponent,13,0x15bb,{DOUBLEWITHTWODWORDINTREE(0x40d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8667,{DOUBLEWITHTWODWORDINTREE(0x40e00000,0x00000000)}},
+        {VT_exponent,22,0x3a86d8,{DOUBLEWITHTWODWORDINTREE(0x40f00000,0x00000000)}},
+        {VT_exponent,22,0x3a86d9,{DOUBLEWITHTWODWORDINTREE(0x41000000,0x00000000)}},
+        {VT_exponent,22,0x3a86da,{DOUBLEWITHTWODWORDINTREE(0x41100000,0x00000000)}},
+        {VT_exponent,17,0x1dc7e,{DOUBLEWITHTWODWORDINTREE(0x41200000,0x00000000)}},
+        {VT_exponent,22,0x3a86db,{DOUBLEWITHTWODWORDINTREE(0x41300000,0x00000000)}},
+        {VT_exponent,22,0x3a86dc,{DOUBLEWITHTWODWORDINTREE(0x41400000,0x00000000)}},
+        {VT_exponent,22,0x3a86dd,{DOUBLEWITHTWODWORDINTREE(0x41500000,0x00000000)}},
+        {VT_exponent,22,0x3a86de,{DOUBLEWITHTWODWORDINTREE(0x41600000,0x00000000)}},
+        {VT_exponent,22,0x3a86df,{DOUBLEWITHTWODWORDINTREE(0x41700000,0x00000000)}},
+        {VT_exponent,22,0x3a86f0,{DOUBLEWITHTWODWORDINTREE(0x41800000,0x00000000)}},
+        {VT_exponent,22,0x3a86f1,{DOUBLEWITHTWODWORDINTREE(0x41900000,0x00000000)}},
+        {VT_exponent,22,0x3a86f2,{DOUBLEWITHTWODWORDINTREE(0x41a00000,0x00000000)}},
+        {VT_exponent,22,0x3a86f3,{DOUBLEWITHTWODWORDINTREE(0x41b00000,0x00000000)}},
+        {VT_double,6,0x2a,{DOUBLEWITHTWODWORDINTREE(0x41cdcd64,0xff800000)}},
+        {VT_exponent,22,0x3a86f4,{DOUBLEWITHTWODWORDINTREE(0x41c00000,0x00000000)}},
+        {VT_exponent,22,0x3a86f5,{DOUBLEWITHTWODWORDINTREE(0x41d00000,0x00000000)}},
+        {VT_exponent,22,0x3a86f6,{DOUBLEWITHTWODWORDINTREE(0x41e00000,0x00000000)}},
+        {VT_exponent,22,0x3a86f7,{DOUBLEWITHTWODWORDINTREE(0x41f00000,0x00000000)}},
+        {VT_exponent,22,0x3a86f8,{DOUBLEWITHTWODWORDINTREE(0x42000000,0x00000000)}},
+        {VT_exponent,22,0x3a86f9,{DOUBLEWITHTWODWORDINTREE(0x42100000,0x00000000)}},
+        {VT_exponent,22,0x3a86fa,{DOUBLEWITHTWODWORDINTREE(0x42200000,0x00000000)}},
+        {VT_exponent,22,0x3a86fb,{DOUBLEWITHTWODWORDINTREE(0x42300000,0x00000000)}},
+        {VT_exponent,22,0x3a86fc,{DOUBLEWITHTWODWORDINTREE(0x42400000,0x00000000)}},
+        {VT_exponent,22,0x3a86fd,{DOUBLEWITHTWODWORDINTREE(0x42500000,0x00000000)}},
+        {VT_exponent,22,0x3a86fe,{DOUBLEWITHTWODWORDINTREE(0x42600000,0x00000000)}},
+        {VT_exponent,22,0x3a86ff,{DOUBLEWITHTWODWORDINTREE(0x42700000,0x00000000)}},
+        {VT_exponent,22,0x3a8740,{DOUBLEWITHTWODWORDINTREE(0x42800000,0x00000000)}},
+        {VT_exponent,22,0x3a8741,{DOUBLEWITHTWODWORDINTREE(0x42900000,0x00000000)}},
+        {VT_exponent,22,0x3a8742,{DOUBLEWITHTWODWORDINTREE(0x42a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8743,{DOUBLEWITHTWODWORDINTREE(0x42b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8744,{DOUBLEWITHTWODWORDINTREE(0x42c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8745,{DOUBLEWITHTWODWORDINTREE(0x42d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8746,{DOUBLEWITHTWODWORDINTREE(0x42e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8747,{DOUBLEWITHTWODWORDINTREE(0x42f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8748,{DOUBLEWITHTWODWORDINTREE(0x43000000,0x00000000)}},
+        {VT_exponent,22,0x3a8749,{DOUBLEWITHTWODWORDINTREE(0x43100000,0x00000000)}},
+        {VT_exponent,22,0x3a874a,{DOUBLEWITHTWODWORDINTREE(0x43200000,0x00000000)}},
+        {VT_exponent,22,0x3a874b,{DOUBLEWITHTWODWORDINTREE(0x43300000,0x00000000)}},
+        {VT_exponent,22,0x3a874c,{DOUBLEWITHTWODWORDINTREE(0x43400000,0x00000000)}},
+        {VT_exponent,22,0x3a874d,{DOUBLEWITHTWODWORDINTREE(0x43500000,0x00000000)}},
+        {VT_exponent,22,0x3a874e,{DOUBLEWITHTWODWORDINTREE(0x43600000,0x00000000)}},
+        {VT_exponent,22,0x3a874f,{DOUBLEWITHTWODWORDINTREE(0x43700000,0x00000000)}},
+        {VT_exponent,22,0x3a8750,{DOUBLEWITHTWODWORDINTREE(0x43800000,0x00000000)}},
+        {VT_exponent,22,0x3a8751,{DOUBLEWITHTWODWORDINTREE(0x43900000,0x00000000)}},
+        {VT_exponent,22,0x3a8752,{DOUBLEWITHTWODWORDINTREE(0x43a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8753,{DOUBLEWITHTWODWORDINTREE(0x43b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8754,{DOUBLEWITHTWODWORDINTREE(0x43c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8755,{DOUBLEWITHTWODWORDINTREE(0x43d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8756,{DOUBLEWITHTWODWORDINTREE(0x43e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8757,{DOUBLEWITHTWODWORDINTREE(0x43f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8758,{DOUBLEWITHTWODWORDINTREE(0x44000000,0x00000000)}},
+        {VT_exponent,15,0x1a3b,{DOUBLEWITHTWODWORDINTREE(0x44100000,0x00000000)}},
+        {VT_exponent,22,0x3a8759,{DOUBLEWITHTWODWORDINTREE(0x44200000,0x00000000)}},
+        {VT_exponent,22,0x3a875a,{DOUBLEWITHTWODWORDINTREE(0x44300000,0x00000000)}},
+        {VT_exponent,22,0x3a875b,{DOUBLEWITHTWODWORDINTREE(0x44400000,0x00000000)}},
+        {VT_exponent,22,0x3a875c,{DOUBLEWITHTWODWORDINTREE(0x44500000,0x00000000)}},
+        {VT_exponent,22,0x3a875d,{DOUBLEWITHTWODWORDINTREE(0x44600000,0x00000000)}},
+        {VT_exponent,22,0x3a875e,{DOUBLEWITHTWODWORDINTREE(0x44700000,0x00000000)}},
+        {VT_exponent,22,0x3a875f,{DOUBLEWITHTWODWORDINTREE(0x44800000,0x00000000)}},
+        {VT_exponent,22,0x3a8760,{DOUBLEWITHTWODWORDINTREE(0x44900000,0x00000000)}},
+        {VT_exponent,22,0x3a8761,{DOUBLEWITHTWODWORDINTREE(0x44a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8762,{DOUBLEWITHTWODWORDINTREE(0x44b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8763,{DOUBLEWITHTWODWORDINTREE(0x44c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8764,{DOUBLEWITHTWODWORDINTREE(0x44d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8765,{DOUBLEWITHTWODWORDINTREE(0x44e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8766,{DOUBLEWITHTWODWORDINTREE(0x44f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8767,{DOUBLEWITHTWODWORDINTREE(0x45000000,0x00000000)}},
+        {VT_exponent,22,0x3a8768,{DOUBLEWITHTWODWORDINTREE(0x45100000,0x00000000)}},
+        {VT_exponent,22,0x3a8769,{DOUBLEWITHTWODWORDINTREE(0x45200000,0x00000000)}},
+        {VT_exponent,22,0x3a876a,{DOUBLEWITHTWODWORDINTREE(0x45300000,0x00000000)}},
+        {VT_exponent,22,0x3a876b,{DOUBLEWITHTWODWORDINTREE(0x45400000,0x00000000)}},
+        {VT_exponent,22,0x3a876c,{DOUBLEWITHTWODWORDINTREE(0x45500000,0x00000000)}},
+        {VT_exponent,22,0x3a876d,{DOUBLEWITHTWODWORDINTREE(0x45600000,0x00000000)}},
+        {VT_exponent,22,0x3a876e,{DOUBLEWITHTWODWORDINTREE(0x45700000,0x00000000)}},
+        {VT_exponent,22,0x3a876f,{DOUBLEWITHTWODWORDINTREE(0x45800000,0x00000000)}},
+        {VT_exponent,22,0x3a8770,{DOUBLEWITHTWODWORDINTREE(0x45900000,0x00000000)}},
+        {VT_exponent,22,0x3a8771,{DOUBLEWITHTWODWORDINTREE(0x45a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8772,{DOUBLEWITHTWODWORDINTREE(0x45b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8773,{DOUBLEWITHTWODWORDINTREE(0x45c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8774,{DOUBLEWITHTWODWORDINTREE(0x45d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8775,{DOUBLEWITHTWODWORDINTREE(0x45e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8776,{DOUBLEWITHTWODWORDINTREE(0x45f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8777,{DOUBLEWITHTWODWORDINTREE(0x46000000,0x00000000)}},
+        {VT_exponent,22,0x3a8778,{DOUBLEWITHTWODWORDINTREE(0x46100000,0x00000000)}},
+        {VT_exponent,22,0x3a8779,{DOUBLEWITHTWODWORDINTREE(0x46200000,0x00000000)}},
+        {VT_exponent,22,0x3a877a,{DOUBLEWITHTWODWORDINTREE(0x46300000,0x00000000)}},
+        {VT_exponent,22,0x3a877b,{DOUBLEWITHTWODWORDINTREE(0x46400000,0x00000000)}},
+        {VT_exponent,22,0x3a877c,{DOUBLEWITHTWODWORDINTREE(0x46500000,0x00000000)}},
+        {VT_exponent,22,0x3a877d,{DOUBLEWITHTWODWORDINTREE(0x46600000,0x00000000)}},
+        {VT_exponent,22,0x3a877e,{DOUBLEWITHTWODWORDINTREE(0x46700000,0x00000000)}},
+        {VT_exponent,22,0x3a877f,{DOUBLEWITHTWODWORDINTREE(0x46800000,0x00000000)}},
+        {VT_exponent,22,0x3a8780,{DOUBLEWITHTWODWORDINTREE(0x46900000,0x00000000)}},
+        {VT_exponent,22,0x3a8781,{DOUBLEWITHTWODWORDINTREE(0x46a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8782,{DOUBLEWITHTWODWORDINTREE(0x46b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8783,{DOUBLEWITHTWODWORDINTREE(0x46c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8784,{DOUBLEWITHTWODWORDINTREE(0x46d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8785,{DOUBLEWITHTWODWORDINTREE(0x46e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8786,{DOUBLEWITHTWODWORDINTREE(0x46f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8787,{DOUBLEWITHTWODWORDINTREE(0x47000000,0x00000000)}},
+        {VT_exponent,22,0x3a8788,{DOUBLEWITHTWODWORDINTREE(0x47100000,0x00000000)}},
+        {VT_exponent,22,0x3a8789,{DOUBLEWITHTWODWORDINTREE(0x47200000,0x00000000)}},
+        {VT_exponent,22,0x3a878a,{DOUBLEWITHTWODWORDINTREE(0x47300000,0x00000000)}},
+        {VT_exponent,22,0x3a878b,{DOUBLEWITHTWODWORDINTREE(0x47400000,0x00000000)}},
+        {VT_exponent,22,0x3a878c,{DOUBLEWITHTWODWORDINTREE(0x47500000,0x00000000)}},
+        {VT_exponent,22,0x3a878d,{DOUBLEWITHTWODWORDINTREE(0x47600000,0x00000000)}},
+        {VT_exponent,22,0x3a878e,{DOUBLEWITHTWODWORDINTREE(0x47700000,0x00000000)}},
+        {VT_exponent,22,0x3a878f,{DOUBLEWITHTWODWORDINTREE(0x47800000,0x00000000)}},
+        {VT_exponent,22,0x3a8790,{DOUBLEWITHTWODWORDINTREE(0x47900000,0x00000000)}},
+        {VT_exponent,22,0x3a8791,{DOUBLEWITHTWODWORDINTREE(0x47a00000,0x00000000)}},
+        {VT_exponent,22,0x3a8792,{DOUBLEWITHTWODWORDINTREE(0x47b00000,0x00000000)}},
+        {VT_exponent,22,0x3a8793,{DOUBLEWITHTWODWORDINTREE(0x47c00000,0x00000000)}},
+        {VT_exponent,22,0x3a8794,{DOUBLEWITHTWODWORDINTREE(0x47d00000,0x00000000)}},
+        {VT_exponent,22,0x3a8795,{DOUBLEWITHTWODWORDINTREE(0x47e00000,0x00000000)}},
+        {VT_exponent,22,0x3a8796,{DOUBLEWITHTWODWORDINTREE(0x47f00000,0x00000000)}},
+        {VT_exponent,22,0x3a8797,{DOUBLEWITHTWODWORDINTREE(0x48000000,0x00000000)}},
+        {VT_exponent,22,0x3a8798,{DOUBLEWITHTWODWORDINTREE(0x48100000,0x00000000)}},
+        {VT_exponent,22,0x3a8799,{DOUBLEWITHTWODWORDINTREE(0x48200000,0x00000000)}},
+        {VT_exponent,22,0x3a879a,{DOUBLEWITHTWODWORDINTREE(0x48300000,0x00000000)}},
+        {VT_exponent,22,0x3a879b,{DOUBLEWITHTWODWORDINTREE(0x48400000,0x00000000)}},
+        {VT_exponent,22,0x3a879c,{DOUBLEWITHTWODWORDINTREE(0x48500000,0x00000000)}},
+        {VT_exponent,22,0x3a879d,{DOUBLEWITHTWODWORDINTREE(0x48600000,0x00000000)}},
+        {VT_exponent,22,0x3a879e,{DOUBLEWITHTWODWORDINTREE(0x48700000,0x00000000)}},
+        {VT_exponent,22,0x3a879f,{DOUBLEWITHTWODWORDINTREE(0x48800000,0x00000000)}},
+        {VT_exponent,22,0x3a87a0,{DOUBLEWITHTWODWORDINTREE(0x48900000,0x00000000)}},
+        {VT_exponent,22,0x3a87a1,{DOUBLEWITHTWODWORDINTREE(0x48a00000,0x00000000)}},
+        {VT_exponent,22,0x3a87a2,{DOUBLEWITHTWODWORDINTREE(0x48b00000,0x00000000)}},
+        {VT_exponent,22,0x3a87a3,{DOUBLEWITHTWODWORDINTREE(0x48c00000,0x00000000)}},
+        {VT_exponent,22,0x3a87a4,{DOUBLEWITHTWODWORDINTREE(0x48d00000,0x00000000)}},
+        {VT_exponent,22,0x3a87a5,{DOUBLEWITHTWODWORDINTREE(0x48e00000,0x00000000)}},
+        {VT_exponent,22,0x3a87a6,{DOUBLEWITHTWODWORDINTREE(0x48f00000,0x00000000)}},
+        {VT_exponent,22,0x3a87a7,{DOUBLEWITHTWODWORDINTREE(0x49000000,0x00000000)}},
+        {VT_exponent,22,0x3a87a8,{DOUBLEWITHTWODWORDINTREE(0x49100000,0x00000000)}},
+        {VT_exponent,22,0x3a87a9,{DOUBLEWITHTWODWORDINTREE(0x49200000,0x00000000)}},
+        {VT_exponent,22,0x3a87aa,{DOUBLEWITHTWODWORDINTREE(0x49300000,0x00000000)}},
+        {VT_exponent,22,0x3a87ab,{DOUBLEWITHTWODWORDINTREE(0x49400000,0x00000000)}},
+        {VT_exponent,22,0x3a87ac,{DOUBLEWITHTWODWORDINTREE(0x49500000,0x00000000)}},
+        {VT_exponent,22,0x3a87ad,{DOUBLEWITHTWODWORDINTREE(0x49600000,0x00000000)}},
+        {VT_exponent,22,0x3a87ae,{DOUBLEWITHTWODWORDINTREE(0x49700000,0x00000000)}},
+        {VT_exponent,22,0x3a87af,{DOUBLEWITHTWODWORDINTREE(0x49800000,0x00000000)}},
+        {VT_exponent,22,0x3a87b0,{DOUBLEWITHTWODWORDINTREE(0x49900000,0x00000000)}},
+        {VT_exponent,22,0x3a87b1,{DOUBLEWITHTWODWORDINTREE(0x49a00000,0x00000000)}},
+        {VT_exponent,22,0x3a87b2,{DOUBLEWITHTWODWORDINTREE(0x49b00000,0x00000000)}},
+        {VT_exponent,22,0x3a87b3,{DOUBLEWITHTWODWORDINTREE(0x49c00000,0x00000000)}},
+        {VT_exponent,22,0x3a87b4,{DOUBLEWITHTWODWORDINTREE(0x49d00000,0x00000000)}},
+        {VT_exponent,22,0x3a87b5,{DOUBLEWITHTWODWORDINTREE(0x49e00000,0x00000000)}},
+        {VT_exponent,22,0x3a87b6,{DOUBLEWITHTWODWORDINTREE(0x49f00000,0x00000000)}},
+        {VT_exponent,22,0x3a87b7,{DOUBLEWITHTWODWORDINTREE(0x4a000000,0x00000000)}},
+        {VT_exponent,22,0x3a87b8,{DOUBLEWITHTWODWORDINTREE(0x4a100000,0x00000000)}},
+        {VT_exponent,22,0x3a87b9,{DOUBLEWITHTWODWORDINTREE(0x4a200000,0x00000000)}},
+        {VT_exponent,22,0x3a87ba,{DOUBLEWITHTWODWORDINTREE(0x4a300000,0x00000000)}},
+        {VT_exponent,22,0x3a87bb,{DOUBLEWITHTWODWORDINTREE(0x4a400000,0x00000000)}},
+        {VT_exponent,22,0x3a87bc,{DOUBLEWITHTWODWORDINTREE(0x4a500000,0x00000000)}},
+        {VT_exponent,22,0x3a87bd,{DOUBLEWITHTWODWORDINTREE(0x4a600000,0x00000000)}},
+        {VT_exponent,22,0x3a87be,{DOUBLEWITHTWODWORDINTREE(0x4a700000,0x00000000)}},
+        {VT_exponent,22,0x3a87bf,{DOUBLEWITHTWODWORDINTREE(0x4a800000,0x00000000)}},
+        {VT_exponent,22,0x3a87c0,{DOUBLEWITHTWODWORDINTREE(0x4a900000,0x00000000)}},
+        {VT_exponent,22,0x3a87c1,{DOUBLEWITHTWODWORDINTREE(0x4aa00000,0x00000000)}},
+        {VT_exponent,22,0x3a87c2,{DOUBLEWITHTWODWORDINTREE(0x4ab00000,0x00000000)}},
+        {VT_exponent,22,0x3a87c3,{DOUBLEWITHTWODWORDINTREE(0x4ac00000,0x00000000)}},
+        {VT_exponent,22,0x3a87c4,{DOUBLEWITHTWODWORDINTREE(0x4ad00000,0x00000000)}},
+        {VT_exponent,22,0x3a87c5,{DOUBLEWITHTWODWORDINTREE(0x4ae00000,0x00000000)}},
+        {VT_exponent,22,0x3a87c6,{DOUBLEWITHTWODWORDINTREE(0x4af00000,0x00000000)}},
+        {VT_exponent,22,0x3a87c7,{DOUBLEWITHTWODWORDINTREE(0x4b000000,0x00000000)}},
+        {VT_exponent,22,0x3a87c8,{DOUBLEWITHTWODWORDINTREE(0x4b100000,0x00000000)}},
+        {VT_exponent,22,0x3a87c9,{DOUBLEWITHTWODWORDINTREE(0x4b200000,0x00000000)}},
+        {VT_exponent,22,0x3a87ca,{DOUBLEWITHTWODWORDINTREE(0x4b300000,0x00000000)}},
+        {VT_exponent,22,0x3a87cb,{DOUBLEWITHTWODWORDINTREE(0x4b400000,0x00000000)}},
+        {VT_exponent,22,0x3a87cc,{DOUBLEWITHTWODWORDINTREE(0x4b500000,0x00000000)}},
+        {VT_exponent,22,0x3a87cd,{DOUBLEWITHTWODWORDINTREE(0x4b600000,0x00000000)}},
+        {VT_exponent,22,0x3a87ce,{DOUBLEWITHTWODWORDINTREE(0x4b700000,0x00000000)}},
+        {VT_exponent,22,0x3a87cf,{DOUBLEWITHTWODWORDINTREE(0x4b800000,0x00000000)}},
+        {VT_exponent,22,0x3a87d0,{DOUBLEWITHTWODWORDINTREE(0x4b900000,0x00000000)}},
+        {VT_exponent,22,0x3a87d1,{DOUBLEWITHTWODWORDINTREE(0x4ba00000,0x00000000)}},
+        {VT_exponent,22,0x3a87d2,{DOUBLEWITHTWODWORDINTREE(0x4bb00000,0x00000000)}},
+        {VT_exponent,22,0x3a87d3,{DOUBLEWITHTWODWORDINTREE(0x4bc00000,0x00000000)}},
+        {VT_exponent,22,0x3a87d4,{DOUBLEWITHTWODWORDINTREE(0x4bd00000,0x00000000)}},
+        {VT_exponent,22,0x3a87d5,{DOUBLEWITHTWODWORDINTREE(0x4be00000,0x00000000)}},
+        {VT_exponent,22,0x3a87d6,{DOUBLEWITHTWODWORDINTREE(0x4bf00000,0x00000000)}},
+        {VT_exponent,22,0x3a87d7,{DOUBLEWITHTWODWORDINTREE(0x4c000000,0x00000000)}},
+        {VT_exponent,22,0x3a87d8,{DOUBLEWITHTWODWORDINTREE(0x4c100000,0x00000000)}},
+        {VT_exponent,22,0x3a87d9,{DOUBLEWITHTWODWORDINTREE(0x4c200000,0x00000000)}},
+        {VT_exponent,22,0x3a87da,{DOUBLEWITHTWODWORDINTREE(0x4c300000,0x00000000)}},
+        {VT_exponent,22,0x3a87db,{DOUBLEWITHTWODWORDINTREE(0x4c400000,0x00000000)}},
+        {VT_exponent,22,0x3a87dc,{DOUBLEWITHTWODWORDINTREE(0x4c500000,0x00000000)}},
+        {VT_exponent,22,0x3a87dd,{DOUBLEWITHTWODWORDINTREE(0x4c600000,0x00000000)}},
+        {VT_exponent,22,0x3a87de,{DOUBLEWITHTWODWORDINTREE(0x4c700000,0x00000000)}},
+        {VT_exponent,22,0x3a87df,{DOUBLEWITHTWODWORDINTREE(0x4c800000,0x00000000)}},
+        {VT_exponent,22,0x3a87e0,{DOUBLEWITHTWODWORDINTREE(0x4c900000,0x00000000)}},
+        {VT_exponent,22,0x3a87e1,{DOUBLEWITHTWODWORDINTREE(0x4ca00000,0x00000000)}},
+        {VT_exponent,22,0x3a87e2,{DOUBLEWITHTWODWORDINTREE(0x4cb00000,0x00000000)}},
+        {VT_exponent,22,0x3a87e3,{DOUBLEWITHTWODWORDINTREE(0x4cc00000,0x00000000)}},
+        {VT_exponent,22,0x3a87e4,{DOUBLEWITHTWODWORDINTREE(0x4cd00000,0x00000000)}},
+        {VT_exponent,22,0x3a87e5,{DOUBLEWITHTWODWORDINTREE(0x4ce00000,0x00000000)}},
+        {VT_exponent,22,0x3a87e6,{DOUBLEWITHTWODWORDINTREE(0x4cf00000,0x00000000)}},
+        {VT_exponent,22,0x3a87e7,{DOUBLEWITHTWODWORDINTREE(0x4d000000,0x00000000)}},
+        {VT_exponent,22,0x3a87e8,{DOUBLEWITHTWODWORDINTREE(0x4d100000,0x00000000)}},
+        {VT_exponent,22,0x3a87e9,{DOUBLEWITHTWODWORDINTREE(0x4d200000,0x00000000)}},
+        {VT_exponent,22,0x3a87ea,{DOUBLEWITHTWODWORDINTREE(0x4d300000,0x00000000)}},
+        {VT_exponent,22,0x3a87eb,{DOUBLEWITHTWODWORDINTREE(0x4d400000,0x00000000)}},
+        {VT_exponent,22,0x3a87ec,{DOUBLEWITHTWODWORDINTREE(0x4d500000,0x00000000)}},
+        {VT_exponent,22,0x3a87ed,{DOUBLEWITHTWODWORDINTREE(0x4d600000,0x00000000)}},
+        {VT_exponent,22,0x3a87ee,{DOUBLEWITHTWODWORDINTREE(0x4d700000,0x00000000)}},
+        {VT_exponent,22,0x3a87ef,{DOUBLEWITHTWODWORDINTREE(0x4d800000,0x00000000)}},
+        {VT_exponent,22,0x3a87f0,{DOUBLEWITHTWODWORDINTREE(0x4d900000,0x00000000)}},
+        {VT_exponent,22,0x3a87f1,{DOUBLEWITHTWODWORDINTREE(0x4da00000,0x00000000)}},
+        {VT_exponent,22,0x3a87f2,{DOUBLEWITHTWODWORDINTREE(0x4db00000,0x00000000)}},
+        {VT_exponent,22,0x3a87f3,{DOUBLEWITHTWODWORDINTREE(0x4dc00000,0x00000000)}},
+        {VT_exponent,22,0x3a87f4,{DOUBLEWITHTWODWORDINTREE(0x4dd00000,0x00000000)}},
+        {VT_exponent,22,0x3a87f5,{DOUBLEWITHTWODWORDINTREE(0x4de00000,0x00000000)}},
+        {VT_exponent,22,0x3a87f6,{DOUBLEWITHTWODWORDINTREE(0x4df00000,0x00000000)}},
+        {VT_exponent,22,0x3a87f7,{DOUBLEWITHTWODWORDINTREE(0x4e000000,0x00000000)}},
+        {VT_exponent,22,0x3a87f8,{DOUBLEWITHTWODWORDINTREE(0x4e100000,0x00000000)}},
+        {VT_exponent,22,0x3a87f9,{DOUBLEWITHTWODWORDINTREE(0x4e200000,0x00000000)}},
+        {VT_exponent,22,0x3a87fa,{DOUBLEWITHTWODWORDINTREE(0x4e300000,0x00000000)}},
+        {VT_exponent,22,0x3a87fb,{DOUBLEWITHTWODWORDINTREE(0x4e400000,0x00000000)}},
+        {VT_exponent,22,0x3a87fc,{DOUBLEWITHTWODWORDINTREE(0x4e500000,0x00000000)}},
+        {VT_exponent,22,0x3a87fd,{DOUBLEWITHTWODWORDINTREE(0x4e600000,0x00000000)}},
+        {VT_exponent,22,0x3a87fe,{DOUBLEWITHTWODWORDINTREE(0x4e700000,0x00000000)}},
+        {VT_exponent,22,0x3a87ff,{DOUBLEWITHTWODWORDINTREE(0x4e800000,0x00000000)}},
+        {VT_exponent,22,0x3a9000,{DOUBLEWITHTWODWORDINTREE(0x4e900000,0x00000000)}},
+        {VT_exponent,22,0x3a9001,{DOUBLEWITHTWODWORDINTREE(0x4ea00000,0x00000000)}},
+        {VT_exponent,22,0x3a9002,{DOUBLEWITHTWODWORDINTREE(0x4eb00000,0x00000000)}},
+        {VT_exponent,22,0x3a9003,{DOUBLEWITHTWODWORDINTREE(0x4ec00000,0x00000000)}},
+        {VT_exponent,22,0x3a9004,{DOUBLEWITHTWODWORDINTREE(0x4ed00000,0x00000000)}},
+        {VT_exponent,22,0x3a9005,{DOUBLEWITHTWODWORDINTREE(0x4ee00000,0x00000000)}},
+        {VT_exponent,22,0x3a9006,{DOUBLEWITHTWODWORDINTREE(0x4ef00000,0x00000000)}},
+        {VT_exponent,22,0x3a9007,{DOUBLEWITHTWODWORDINTREE(0x4f000000,0x00000000)}},
+        {VT_exponent,22,0x3a9008,{DOUBLEWITHTWODWORDINTREE(0x4f100000,0x00000000)}},
+        {VT_exponent,22,0x3a9009,{DOUBLEWITHTWODWORDINTREE(0x4f200000,0x00000000)}},
+        {VT_exponent,22,0x3a900a,{DOUBLEWITHTWODWORDINTREE(0x4f300000,0x00000000)}},
+        {VT_exponent,22,0x3a900b,{DOUBLEWITHTWODWORDINTREE(0x4f400000,0x00000000)}},
+        {VT_exponent,22,0x3a900c,{DOUBLEWITHTWODWORDINTREE(0x4f500000,0x00000000)}},
+        {VT_exponent,22,0x3a900d,{DOUBLEWITHTWODWORDINTREE(0x4f600000,0x00000000)}},
+        {VT_exponent,22,0x3a900e,{DOUBLEWITHTWODWORDINTREE(0x4f700000,0x00000000)}},
+        {VT_exponent,22,0x3a900f,{DOUBLEWITHTWODWORDINTREE(0x4f800000,0x00000000)}},
+        {VT_exponent,22,0x3a9010,{DOUBLEWITHTWODWORDINTREE(0x4f900000,0x00000000)}},
+        {VT_exponent,22,0x3a9011,{DOUBLEWITHTWODWORDINTREE(0x4fa00000,0x00000000)}},
+        {VT_exponent,22,0x3a9012,{DOUBLEWITHTWODWORDINTREE(0x4fb00000,0x00000000)}},
+        {VT_exponent,22,0x3a9013,{DOUBLEWITHTWODWORDINTREE(0x4fc00000,0x00000000)}},
+        {VT_exponent,22,0x3a9014,{DOUBLEWITHTWODWORDINTREE(0x4fd00000,0x00000000)}},
+        {VT_exponent,22,0x3a9015,{DOUBLEWITHTWODWORDINTREE(0x4fe00000,0x00000000)}},
+        {VT_exponent,22,0x3a9016,{DOUBLEWITHTWODWORDINTREE(0x4ff00000,0x00000000)}},
+        {VT_exponent,22,0x3a9017,{DOUBLEWITHTWODWORDINTREE(0x50000000,0x00000000)}},
+        {VT_exponent,22,0x3a9018,{DOUBLEWITHTWODWORDINTREE(0x50100000,0x00000000)}},
+        {VT_exponent,22,0x3a9019,{DOUBLEWITHTWODWORDINTREE(0x50200000,0x00000000)}},
+        {VT_exponent,22,0x3a901a,{DOUBLEWITHTWODWORDINTREE(0x50300000,0x00000000)}},
+        {VT_exponent,22,0x3a901b,{DOUBLEWITHTWODWORDINTREE(0x50400000,0x00000000)}},
+        {VT_exponent,22,0x3a901c,{DOUBLEWITHTWODWORDINTREE(0x50500000,0x00000000)}},
+        {VT_exponent,22,0x3a901d,{DOUBLEWITHTWODWORDINTREE(0x50600000,0x00000000)}},
+        {VT_exponent,22,0x3a901e,{DOUBLEWITHTWODWORDINTREE(0x50700000,0x00000000)}},
+        {VT_exponent,22,0x3a901f,{DOUBLEWITHTWODWORDINTREE(0x50800000,0x00000000)}},
+        {VT_exponent,22,0x3a9020,{DOUBLEWITHTWODWORDINTREE(0x50900000,0x00000000)}},
+        {VT_exponent,22,0x3a9021,{DOUBLEWITHTWODWORDINTREE(0x50a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9022,{DOUBLEWITHTWODWORDINTREE(0x50b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9023,{DOUBLEWITHTWODWORDINTREE(0x50c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9024,{DOUBLEWITHTWODWORDINTREE(0x50d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9025,{DOUBLEWITHTWODWORDINTREE(0x50e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9026,{DOUBLEWITHTWODWORDINTREE(0x50f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9027,{DOUBLEWITHTWODWORDINTREE(0x51000000,0x00000000)}},
+        {VT_exponent,22,0x3a9028,{DOUBLEWITHTWODWORDINTREE(0x51100000,0x00000000)}},
+        {VT_exponent,22,0x3a9029,{DOUBLEWITHTWODWORDINTREE(0x51200000,0x00000000)}},
+        {VT_exponent,22,0x3a902a,{DOUBLEWITHTWODWORDINTREE(0x51300000,0x00000000)}},
+        {VT_exponent,22,0x3a902b,{DOUBLEWITHTWODWORDINTREE(0x51400000,0x00000000)}},
+        {VT_exponent,22,0x3a902c,{DOUBLEWITHTWODWORDINTREE(0x51500000,0x00000000)}},
+        {VT_exponent,22,0x3a902d,{DOUBLEWITHTWODWORDINTREE(0x51600000,0x00000000)}},
+        {VT_exponent,22,0x3a902e,{DOUBLEWITHTWODWORDINTREE(0x51700000,0x00000000)}},
+        {VT_exponent,22,0x3a902f,{DOUBLEWITHTWODWORDINTREE(0x51800000,0x00000000)}},
+        {VT_exponent,22,0x3a9030,{DOUBLEWITHTWODWORDINTREE(0x51900000,0x00000000)}},
+        {VT_exponent,22,0x3a9031,{DOUBLEWITHTWODWORDINTREE(0x51a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9032,{DOUBLEWITHTWODWORDINTREE(0x51b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9033,{DOUBLEWITHTWODWORDINTREE(0x51c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9034,{DOUBLEWITHTWODWORDINTREE(0x51d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9035,{DOUBLEWITHTWODWORDINTREE(0x51e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9036,{DOUBLEWITHTWODWORDINTREE(0x51f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9037,{DOUBLEWITHTWODWORDINTREE(0x52000000,0x00000000)}},
+        {VT_exponent,22,0x3a9038,{DOUBLEWITHTWODWORDINTREE(0x52100000,0x00000000)}},
+        {VT_exponent,22,0x3a9039,{DOUBLEWITHTWODWORDINTREE(0x52200000,0x00000000)}},
+        {VT_exponent,22,0x3a903a,{DOUBLEWITHTWODWORDINTREE(0x52300000,0x00000000)}},
+        {VT_exponent,22,0x3a903b,{DOUBLEWITHTWODWORDINTREE(0x52400000,0x00000000)}},
+        {VT_exponent,22,0x3a903c,{DOUBLEWITHTWODWORDINTREE(0x52500000,0x00000000)}},
+        {VT_exponent,22,0x3a903d,{DOUBLEWITHTWODWORDINTREE(0x52600000,0x00000000)}},
+        {VT_exponent,22,0x3a903e,{DOUBLEWITHTWODWORDINTREE(0x52700000,0x00000000)}},
+        {VT_exponent,22,0x3a903f,{DOUBLEWITHTWODWORDINTREE(0x52800000,0x00000000)}},
+        {VT_exponent,22,0x3a9040,{DOUBLEWITHTWODWORDINTREE(0x52900000,0x00000000)}},
+        {VT_exponent,22,0x3a9041,{DOUBLEWITHTWODWORDINTREE(0x52a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9042,{DOUBLEWITHTWODWORDINTREE(0x52b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9043,{DOUBLEWITHTWODWORDINTREE(0x52c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9044,{DOUBLEWITHTWODWORDINTREE(0x52d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9045,{DOUBLEWITHTWODWORDINTREE(0x52e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9046,{DOUBLEWITHTWODWORDINTREE(0x52f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9047,{DOUBLEWITHTWODWORDINTREE(0x53000000,0x00000000)}},
+        {VT_exponent,22,0x3a9048,{DOUBLEWITHTWODWORDINTREE(0x53100000,0x00000000)}},
+        {VT_exponent,22,0x3a9049,{DOUBLEWITHTWODWORDINTREE(0x53200000,0x00000000)}},
+        {VT_exponent,22,0x3a904a,{DOUBLEWITHTWODWORDINTREE(0x53300000,0x00000000)}},
+        {VT_exponent,22,0x3a904b,{DOUBLEWITHTWODWORDINTREE(0x53400000,0x00000000)}},
+        {VT_exponent,22,0x3a904c,{DOUBLEWITHTWODWORDINTREE(0x53500000,0x00000000)}},
+        {VT_exponent,22,0x3a904d,{DOUBLEWITHTWODWORDINTREE(0x53600000,0x00000000)}},
+        {VT_exponent,22,0x3a904e,{DOUBLEWITHTWODWORDINTREE(0x53700000,0x00000000)}},
+        {VT_exponent,22,0x3a904f,{DOUBLEWITHTWODWORDINTREE(0x53800000,0x00000000)}},
+        {VT_exponent,22,0x3a9050,{DOUBLEWITHTWODWORDINTREE(0x53900000,0x00000000)}},
+        {VT_exponent,22,0x3a9051,{DOUBLEWITHTWODWORDINTREE(0x53a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9052,{DOUBLEWITHTWODWORDINTREE(0x53b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9053,{DOUBLEWITHTWODWORDINTREE(0x53c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9054,{DOUBLEWITHTWODWORDINTREE(0x53d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9055,{DOUBLEWITHTWODWORDINTREE(0x53e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9056,{DOUBLEWITHTWODWORDINTREE(0x53f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9057,{DOUBLEWITHTWODWORDINTREE(0x54000000,0x00000000)}},
+        {VT_exponent,22,0x3a9058,{DOUBLEWITHTWODWORDINTREE(0x54100000,0x00000000)}},
+        {VT_exponent,22,0x3a9059,{DOUBLEWITHTWODWORDINTREE(0x54200000,0x00000000)}},
+        {VT_exponent,22,0x3a905a,{DOUBLEWITHTWODWORDINTREE(0x54300000,0x00000000)}},
+        {VT_exponent,22,0x3a905b,{DOUBLEWITHTWODWORDINTREE(0x54400000,0x00000000)}},
+        {VT_exponent,22,0x3a905c,{DOUBLEWITHTWODWORDINTREE(0x54500000,0x00000000)}},
+        {VT_exponent,22,0x3a905d,{DOUBLEWITHTWODWORDINTREE(0x54600000,0x00000000)}},
+        {VT_exponent,22,0x3a905e,{DOUBLEWITHTWODWORDINTREE(0x54700000,0x00000000)}},
+        {VT_exponent,22,0x3a905f,{DOUBLEWITHTWODWORDINTREE(0x54800000,0x00000000)}},
+        {VT_exponent,22,0x3a9060,{DOUBLEWITHTWODWORDINTREE(0x54900000,0x00000000)}},
+        {VT_exponent,22,0x3a9061,{DOUBLEWITHTWODWORDINTREE(0x54a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9062,{DOUBLEWITHTWODWORDINTREE(0x54b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9063,{DOUBLEWITHTWODWORDINTREE(0x54c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9064,{DOUBLEWITHTWODWORDINTREE(0x54d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9065,{DOUBLEWITHTWODWORDINTREE(0x54e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9066,{DOUBLEWITHTWODWORDINTREE(0x54f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9067,{DOUBLEWITHTWODWORDINTREE(0x55000000,0x00000000)}},
+        {VT_exponent,22,0x3a9068,{DOUBLEWITHTWODWORDINTREE(0x55100000,0x00000000)}},
+        {VT_exponent,22,0x3a9069,{DOUBLEWITHTWODWORDINTREE(0x55200000,0x00000000)}},
+        {VT_exponent,22,0x3a906a,{DOUBLEWITHTWODWORDINTREE(0x55300000,0x00000000)}},
+        {VT_exponent,22,0x3a906b,{DOUBLEWITHTWODWORDINTREE(0x55400000,0x00000000)}},
+        {VT_exponent,22,0x3a906c,{DOUBLEWITHTWODWORDINTREE(0x55500000,0x00000000)}},
+        {VT_exponent,22,0x3a906d,{DOUBLEWITHTWODWORDINTREE(0x55600000,0x00000000)}},
+        {VT_exponent,22,0x3a906e,{DOUBLEWITHTWODWORDINTREE(0x55700000,0x00000000)}},
+        {VT_exponent,22,0x3a906f,{DOUBLEWITHTWODWORDINTREE(0x55800000,0x00000000)}},
+        {VT_exponent,22,0x3a9070,{DOUBLEWITHTWODWORDINTREE(0x55900000,0x00000000)}},
+        {VT_exponent,22,0x3a9071,{DOUBLEWITHTWODWORDINTREE(0x55a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9072,{DOUBLEWITHTWODWORDINTREE(0x55b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9073,{DOUBLEWITHTWODWORDINTREE(0x55c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9074,{DOUBLEWITHTWODWORDINTREE(0x55d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9075,{DOUBLEWITHTWODWORDINTREE(0x55e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9076,{DOUBLEWITHTWODWORDINTREE(0x55f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9077,{DOUBLEWITHTWODWORDINTREE(0x56000000,0x00000000)}},
+        {VT_exponent,22,0x3a9078,{DOUBLEWITHTWODWORDINTREE(0x56100000,0x00000000)}},
+        {VT_exponent,22,0x3a9079,{DOUBLEWITHTWODWORDINTREE(0x56200000,0x00000000)}},
+        {VT_exponent,22,0x3a907a,{DOUBLEWITHTWODWORDINTREE(0x56300000,0x00000000)}},
+        {VT_exponent,22,0x3a907b,{DOUBLEWITHTWODWORDINTREE(0x56400000,0x00000000)}},
+        {VT_exponent,22,0x3a907c,{DOUBLEWITHTWODWORDINTREE(0x56500000,0x00000000)}},
+        {VT_exponent,22,0x3a907d,{DOUBLEWITHTWODWORDINTREE(0x56600000,0x00000000)}},
+        {VT_exponent,22,0x3a907e,{DOUBLEWITHTWODWORDINTREE(0x56700000,0x00000000)}},
+        {VT_exponent,22,0x3a907f,{DOUBLEWITHTWODWORDINTREE(0x56800000,0x00000000)}},
+        {VT_exponent,22,0x3a9080,{DOUBLEWITHTWODWORDINTREE(0x56900000,0x00000000)}},
+        {VT_exponent,22,0x3a9081,{DOUBLEWITHTWODWORDINTREE(0x56a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9082,{DOUBLEWITHTWODWORDINTREE(0x56b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9083,{DOUBLEWITHTWODWORDINTREE(0x56c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9084,{DOUBLEWITHTWODWORDINTREE(0x56d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9085,{DOUBLEWITHTWODWORDINTREE(0x56e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9086,{DOUBLEWITHTWODWORDINTREE(0x56f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9087,{DOUBLEWITHTWODWORDINTREE(0x57000000,0x00000000)}},
+        {VT_exponent,22,0x3a9088,{DOUBLEWITHTWODWORDINTREE(0x57100000,0x00000000)}},
+        {VT_exponent,22,0x3a9089,{DOUBLEWITHTWODWORDINTREE(0x57200000,0x00000000)}},
+        {VT_exponent,22,0x3a908a,{DOUBLEWITHTWODWORDINTREE(0x57300000,0x00000000)}},
+        {VT_exponent,22,0x3a908b,{DOUBLEWITHTWODWORDINTREE(0x57400000,0x00000000)}},
+        {VT_exponent,22,0x3a908c,{DOUBLEWITHTWODWORDINTREE(0x57500000,0x00000000)}},
+        {VT_exponent,22,0x3a908d,{DOUBLEWITHTWODWORDINTREE(0x57600000,0x00000000)}},
+        {VT_exponent,22,0x3a908e,{DOUBLEWITHTWODWORDINTREE(0x57700000,0x00000000)}},
+        {VT_exponent,22,0x3a908f,{DOUBLEWITHTWODWORDINTREE(0x57800000,0x00000000)}},
+        {VT_exponent,22,0x3a9090,{DOUBLEWITHTWODWORDINTREE(0x57900000,0x00000000)}},
+        {VT_exponent,22,0x3a9091,{DOUBLEWITHTWODWORDINTREE(0x57a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9092,{DOUBLEWITHTWODWORDINTREE(0x57b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9093,{DOUBLEWITHTWODWORDINTREE(0x57c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9094,{DOUBLEWITHTWODWORDINTREE(0x57d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9095,{DOUBLEWITHTWODWORDINTREE(0x57e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9096,{DOUBLEWITHTWODWORDINTREE(0x57f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9097,{DOUBLEWITHTWODWORDINTREE(0x58000000,0x00000000)}},
+        {VT_exponent,22,0x3a9098,{DOUBLEWITHTWODWORDINTREE(0x58100000,0x00000000)}},
+        {VT_exponent,22,0x3a9099,{DOUBLEWITHTWODWORDINTREE(0x58200000,0x00000000)}},
+        {VT_exponent,22,0x3a909a,{DOUBLEWITHTWODWORDINTREE(0x58300000,0x00000000)}},
+        {VT_exponent,22,0x3a909b,{DOUBLEWITHTWODWORDINTREE(0x58400000,0x00000000)}},
+        {VT_exponent,22,0x3a909c,{DOUBLEWITHTWODWORDINTREE(0x58500000,0x00000000)}},
+        {VT_exponent,22,0x3a909d,{DOUBLEWITHTWODWORDINTREE(0x58600000,0x00000000)}},
+        {VT_exponent,22,0x3a909e,{DOUBLEWITHTWODWORDINTREE(0x58700000,0x00000000)}},
+        {VT_exponent,22,0x3a909f,{DOUBLEWITHTWODWORDINTREE(0x58800000,0x00000000)}},
+        {VT_exponent,22,0x3a90a0,{DOUBLEWITHTWODWORDINTREE(0x58900000,0x00000000)}},
+        {VT_exponent,22,0x3a90a1,{DOUBLEWITHTWODWORDINTREE(0x58a00000,0x00000000)}},
+        {VT_exponent,22,0x3a90a2,{DOUBLEWITHTWODWORDINTREE(0x58b00000,0x00000000)}},
+        {VT_exponent,22,0x3a90a3,{DOUBLEWITHTWODWORDINTREE(0x58c00000,0x00000000)}},
+        {VT_exponent,22,0x3a90a4,{DOUBLEWITHTWODWORDINTREE(0x58d00000,0x00000000)}},
+        {VT_exponent,22,0x3a90a5,{DOUBLEWITHTWODWORDINTREE(0x58e00000,0x00000000)}},
+        {VT_exponent,22,0x3a90a6,{DOUBLEWITHTWODWORDINTREE(0x58f00000,0x00000000)}},
+        {VT_exponent,22,0x3a90a7,{DOUBLEWITHTWODWORDINTREE(0x59000000,0x00000000)}},
+        {VT_exponent,22,0x3a90a8,{DOUBLEWITHTWODWORDINTREE(0x59100000,0x00000000)}},
+        {VT_exponent,22,0x3a90a9,{DOUBLEWITHTWODWORDINTREE(0x59200000,0x00000000)}},
+        {VT_exponent,22,0x3a90aa,{DOUBLEWITHTWODWORDINTREE(0x59300000,0x00000000)}},
+        {VT_exponent,22,0x3a90ab,{DOUBLEWITHTWODWORDINTREE(0x59400000,0x00000000)}},
+        {VT_exponent,22,0x3a90ac,{DOUBLEWITHTWODWORDINTREE(0x59500000,0x00000000)}},
+        {VT_exponent,22,0x3a90ad,{DOUBLEWITHTWODWORDINTREE(0x59600000,0x00000000)}},
+        {VT_exponent,22,0x3a90ae,{DOUBLEWITHTWODWORDINTREE(0x59700000,0x00000000)}},
+        {VT_exponent,22,0x3a90af,{DOUBLEWITHTWODWORDINTREE(0x59800000,0x00000000)}},
+        {VT_exponent,22,0x3a90b0,{DOUBLEWITHTWODWORDINTREE(0x59900000,0x00000000)}},
+        {VT_exponent,22,0x3a90b1,{DOUBLEWITHTWODWORDINTREE(0x59a00000,0x00000000)}},
+        {VT_exponent,22,0x3a90b2,{DOUBLEWITHTWODWORDINTREE(0x59b00000,0x00000000)}},
+        {VT_exponent,22,0x3a90b3,{DOUBLEWITHTWODWORDINTREE(0x59c00000,0x00000000)}},
+        {VT_exponent,22,0x3a90b4,{DOUBLEWITHTWODWORDINTREE(0x59d00000,0x00000000)}},
+        {VT_exponent,22,0x3a90b5,{DOUBLEWITHTWODWORDINTREE(0x59e00000,0x00000000)}},
+        {VT_exponent,22,0x3a90b6,{DOUBLEWITHTWODWORDINTREE(0x59f00000,0x00000000)}},
+        {VT_exponent,22,0x3a90b7,{DOUBLEWITHTWODWORDINTREE(0x5a000000,0x00000000)}},
+        {VT_exponent,22,0x3a90b8,{DOUBLEWITHTWODWORDINTREE(0x5a100000,0x00000000)}},
+        {VT_exponent,22,0x3a90b9,{DOUBLEWITHTWODWORDINTREE(0x5a200000,0x00000000)}},
+        {VT_exponent,22,0x3a90ba,{DOUBLEWITHTWODWORDINTREE(0x5a300000,0x00000000)}},
+        {VT_exponent,22,0x3a90bb,{DOUBLEWITHTWODWORDINTREE(0x5a400000,0x00000000)}},
+        {VT_exponent,22,0x3a90bc,{DOUBLEWITHTWODWORDINTREE(0x5a500000,0x00000000)}},
+        {VT_exponent,22,0x3a90bd,{DOUBLEWITHTWODWORDINTREE(0x5a600000,0x00000000)}},
+        {VT_exponent,22,0x3a90be,{DOUBLEWITHTWODWORDINTREE(0x5a700000,0x00000000)}},
+        {VT_exponent,22,0x3a90bf,{DOUBLEWITHTWODWORDINTREE(0x5a800000,0x00000000)}},
+        {VT_exponent,22,0x3a90c0,{DOUBLEWITHTWODWORDINTREE(0x5a900000,0x00000000)}},
+        {VT_exponent,22,0x3a90c1,{DOUBLEWITHTWODWORDINTREE(0x5aa00000,0x00000000)}},
+        {VT_exponent,22,0x3a90c2,{DOUBLEWITHTWODWORDINTREE(0x5ab00000,0x00000000)}},
+        {VT_exponent,22,0x3a90c3,{DOUBLEWITHTWODWORDINTREE(0x5ac00000,0x00000000)}},
+        {VT_exponent,22,0x3a90c4,{DOUBLEWITHTWODWORDINTREE(0x5ad00000,0x00000000)}},
+        {VT_exponent,22,0x3a90c5,{DOUBLEWITHTWODWORDINTREE(0x5ae00000,0x00000000)}},
+        {VT_exponent,22,0x3a90c6,{DOUBLEWITHTWODWORDINTREE(0x5af00000,0x00000000)}},
+        {VT_exponent,22,0x3a90c7,{DOUBLEWITHTWODWORDINTREE(0x5b000000,0x00000000)}},
+        {VT_exponent,22,0x3a90c8,{DOUBLEWITHTWODWORDINTREE(0x5b100000,0x00000000)}},
+        {VT_exponent,22,0x3a90c9,{DOUBLEWITHTWODWORDINTREE(0x5b200000,0x00000000)}},
+        {VT_exponent,22,0x3a90ca,{DOUBLEWITHTWODWORDINTREE(0x5b300000,0x00000000)}},
+        {VT_exponent,22,0x3a90cb,{DOUBLEWITHTWODWORDINTREE(0x5b400000,0x00000000)}},
+        {VT_exponent,22,0x3a90cc,{DOUBLEWITHTWODWORDINTREE(0x5b500000,0x00000000)}},
+        {VT_exponent,22,0x3a90cd,{DOUBLEWITHTWODWORDINTREE(0x5b600000,0x00000000)}},
+        {VT_exponent,22,0x3a90ce,{DOUBLEWITHTWODWORDINTREE(0x5b700000,0x00000000)}},
+        {VT_exponent,22,0x3a90cf,{DOUBLEWITHTWODWORDINTREE(0x5b800000,0x00000000)}},
+        {VT_exponent,22,0x3a90d0,{DOUBLEWITHTWODWORDINTREE(0x5b900000,0x00000000)}},
+        {VT_exponent,22,0x3a90d1,{DOUBLEWITHTWODWORDINTREE(0x5ba00000,0x00000000)}},
+        {VT_exponent,22,0x3a90d2,{DOUBLEWITHTWODWORDINTREE(0x5bb00000,0x00000000)}},
+        {VT_exponent,22,0x3a90d3,{DOUBLEWITHTWODWORDINTREE(0x5bc00000,0x00000000)}},
+        {VT_exponent,22,0x3a90d4,{DOUBLEWITHTWODWORDINTREE(0x5bd00000,0x00000000)}},
+        {VT_exponent,22,0x3a90d5,{DOUBLEWITHTWODWORDINTREE(0x5be00000,0x00000000)}},
+        {VT_exponent,22,0x3a90d6,{DOUBLEWITHTWODWORDINTREE(0x5bf00000,0x00000000)}},
+        {VT_exponent,22,0x3a90d7,{DOUBLEWITHTWODWORDINTREE(0x5c000000,0x00000000)}},
+        {VT_exponent,22,0x3a90d8,{DOUBLEWITHTWODWORDINTREE(0x5c100000,0x00000000)}},
+        {VT_exponent,22,0x3a90d9,{DOUBLEWITHTWODWORDINTREE(0x5c200000,0x00000000)}},
+        {VT_exponent,22,0x3a90da,{DOUBLEWITHTWODWORDINTREE(0x5c300000,0x00000000)}},
+        {VT_exponent,22,0x3a90db,{DOUBLEWITHTWODWORDINTREE(0x5c400000,0x00000000)}},
+        {VT_exponent,22,0x3a90dc,{DOUBLEWITHTWODWORDINTREE(0x5c500000,0x00000000)}},
+        {VT_exponent,22,0x3a90dd,{DOUBLEWITHTWODWORDINTREE(0x5c600000,0x00000000)}},
+        {VT_exponent,22,0x3a90de,{DOUBLEWITHTWODWORDINTREE(0x5c700000,0x00000000)}},
+        {VT_exponent,22,0x3a90df,{DOUBLEWITHTWODWORDINTREE(0x5c800000,0x00000000)}},
+        {VT_exponent,22,0x3a90e0,{DOUBLEWITHTWODWORDINTREE(0x5c900000,0x00000000)}},
+        {VT_exponent,22,0x3a90e1,{DOUBLEWITHTWODWORDINTREE(0x5ca00000,0x00000000)}},
+        {VT_exponent,22,0x3a90e2,{DOUBLEWITHTWODWORDINTREE(0x5cb00000,0x00000000)}},
+        {VT_exponent,22,0x3a90e3,{DOUBLEWITHTWODWORDINTREE(0x5cc00000,0x00000000)}},
+        {VT_exponent,22,0x3a90e4,{DOUBLEWITHTWODWORDINTREE(0x5cd00000,0x00000000)}},
+        {VT_exponent,22,0x3a90e5,{DOUBLEWITHTWODWORDINTREE(0x5ce00000,0x00000000)}},
+        {VT_exponent,22,0x3a90e6,{DOUBLEWITHTWODWORDINTREE(0x5cf00000,0x00000000)}},
+        {VT_exponent,22,0x3a90e7,{DOUBLEWITHTWODWORDINTREE(0x5d000000,0x00000000)}},
+        {VT_exponent,22,0x3a90e8,{DOUBLEWITHTWODWORDINTREE(0x5d100000,0x00000000)}},
+        {VT_exponent,22,0x3a90e9,{DOUBLEWITHTWODWORDINTREE(0x5d200000,0x00000000)}},
+        {VT_exponent,22,0x3a90ea,{DOUBLEWITHTWODWORDINTREE(0x5d300000,0x00000000)}},
+        {VT_exponent,22,0x3a90eb,{DOUBLEWITHTWODWORDINTREE(0x5d400000,0x00000000)}},
+        {VT_exponent,22,0x3a90ec,{DOUBLEWITHTWODWORDINTREE(0x5d500000,0x00000000)}},
+        {VT_exponent,22,0x3a90ed,{DOUBLEWITHTWODWORDINTREE(0x5d600000,0x00000000)}},
+        {VT_exponent,22,0x3a90ee,{DOUBLEWITHTWODWORDINTREE(0x5d700000,0x00000000)}},
+        {VT_exponent,22,0x3a90ef,{DOUBLEWITHTWODWORDINTREE(0x5d800000,0x00000000)}},
+        {VT_exponent,22,0x3a90f0,{DOUBLEWITHTWODWORDINTREE(0x5d900000,0x00000000)}},
+        {VT_exponent,22,0x3a90f1,{DOUBLEWITHTWODWORDINTREE(0x5da00000,0x00000000)}},
+        {VT_exponent,22,0x3a90f2,{DOUBLEWITHTWODWORDINTREE(0x5db00000,0x00000000)}},
+        {VT_exponent,22,0x3a90f3,{DOUBLEWITHTWODWORDINTREE(0x5dc00000,0x00000000)}},
+        {VT_exponent,22,0x3a90f4,{DOUBLEWITHTWODWORDINTREE(0x5dd00000,0x00000000)}},
+        {VT_exponent,22,0x3a90f5,{DOUBLEWITHTWODWORDINTREE(0x5de00000,0x00000000)}},
+        {VT_exponent,22,0x3a90f6,{DOUBLEWITHTWODWORDINTREE(0x5df00000,0x00000000)}},
+        {VT_exponent,22,0x3a90f7,{DOUBLEWITHTWODWORDINTREE(0x5e000000,0x00000000)}},
+        {VT_exponent,22,0x3a90f8,{DOUBLEWITHTWODWORDINTREE(0x5e100000,0x00000000)}},
+        {VT_exponent,22,0x3a90f9,{DOUBLEWITHTWODWORDINTREE(0x5e200000,0x00000000)}},
+        {VT_exponent,22,0x3a90fa,{DOUBLEWITHTWODWORDINTREE(0x5e300000,0x00000000)}},
+        {VT_exponent,22,0x3a90fb,{DOUBLEWITHTWODWORDINTREE(0x5e400000,0x00000000)}},
+        {VT_exponent,22,0x3a90fc,{DOUBLEWITHTWODWORDINTREE(0x5e500000,0x00000000)}},
+        {VT_exponent,22,0x3a90fd,{DOUBLEWITHTWODWORDINTREE(0x5e600000,0x00000000)}},
+        {VT_exponent,22,0x3a90fe,{DOUBLEWITHTWODWORDINTREE(0x5e700000,0x00000000)}},
+        {VT_exponent,22,0x3a90ff,{DOUBLEWITHTWODWORDINTREE(0x5e800000,0x00000000)}},
+        {VT_exponent,22,0x3a9100,{DOUBLEWITHTWODWORDINTREE(0x5e900000,0x00000000)}},
+        {VT_exponent,22,0x3a9101,{DOUBLEWITHTWODWORDINTREE(0x5ea00000,0x00000000)}},
+        {VT_exponent,22,0x3a9102,{DOUBLEWITHTWODWORDINTREE(0x5eb00000,0x00000000)}},
+        {VT_exponent,22,0x3a9103,{DOUBLEWITHTWODWORDINTREE(0x5ec00000,0x00000000)}},
+        {VT_exponent,22,0x3a9104,{DOUBLEWITHTWODWORDINTREE(0x5ed00000,0x00000000)}},
+        {VT_exponent,22,0x3a9105,{DOUBLEWITHTWODWORDINTREE(0x5ee00000,0x00000000)}},
+        {VT_exponent,22,0x3a9106,{DOUBLEWITHTWODWORDINTREE(0x5ef00000,0x00000000)}},
+        {VT_exponent,22,0x3a9107,{DOUBLEWITHTWODWORDINTREE(0x5f000000,0x00000000)}},
+        {VT_exponent,22,0x3a9108,{DOUBLEWITHTWODWORDINTREE(0x5f100000,0x00000000)}},
+        {VT_exponent,22,0x3a9109,{DOUBLEWITHTWODWORDINTREE(0x5f200000,0x00000000)}},
+        {VT_exponent,22,0x3a910a,{DOUBLEWITHTWODWORDINTREE(0x5f300000,0x00000000)}},
+        {VT_exponent,22,0x3a910b,{DOUBLEWITHTWODWORDINTREE(0x5f400000,0x00000000)}},
+        {VT_exponent,22,0x3a910c,{DOUBLEWITHTWODWORDINTREE(0x5f500000,0x00000000)}},
+        {VT_exponent,22,0x3a910d,{DOUBLEWITHTWODWORDINTREE(0x5f600000,0x00000000)}},
+        {VT_exponent,22,0x3a910e,{DOUBLEWITHTWODWORDINTREE(0x5f700000,0x00000000)}},
+        {VT_exponent,22,0x3a910f,{DOUBLEWITHTWODWORDINTREE(0x5f800000,0x00000000)}},
+        {VT_exponent,22,0x3a9110,{DOUBLEWITHTWODWORDINTREE(0x5f900000,0x00000000)}},
+        {VT_exponent,22,0x3a9111,{DOUBLEWITHTWODWORDINTREE(0x5fa00000,0x00000000)}},
+        {VT_exponent,22,0x3a9112,{DOUBLEWITHTWODWORDINTREE(0x5fb00000,0x00000000)}},
+        {VT_exponent,22,0x3a9113,{DOUBLEWITHTWODWORDINTREE(0x5fc00000,0x00000000)}},
+        {VT_exponent,22,0x3a9114,{DOUBLEWITHTWODWORDINTREE(0x5fd00000,0x00000000)}},
+        {VT_exponent,22,0x3a9115,{DOUBLEWITHTWODWORDINTREE(0x5fe00000,0x00000000)}},
+        {VT_exponent,22,0x3a9116,{DOUBLEWITHTWODWORDINTREE(0x5ff00000,0x00000000)}},
+        {VT_exponent,22,0x3a9117,{DOUBLEWITHTWODWORDINTREE(0x60000000,0x00000000)}},
+        {VT_exponent,22,0x3a9118,{DOUBLEWITHTWODWORDINTREE(0x60100000,0x00000000)}},
+        {VT_exponent,22,0x3a9119,{DOUBLEWITHTWODWORDINTREE(0x60200000,0x00000000)}},
+        {VT_exponent,22,0x3a911a,{DOUBLEWITHTWODWORDINTREE(0x60300000,0x00000000)}},
+        {VT_exponent,22,0x3a911b,{DOUBLEWITHTWODWORDINTREE(0x60400000,0x00000000)}},
+        {VT_exponent,22,0x3a911c,{DOUBLEWITHTWODWORDINTREE(0x60500000,0x00000000)}},
+        {VT_exponent,22,0x3a911d,{DOUBLEWITHTWODWORDINTREE(0x60600000,0x00000000)}},
+        {VT_exponent,22,0x3a911e,{DOUBLEWITHTWODWORDINTREE(0x60700000,0x00000000)}},
+        {VT_exponent,22,0x3a911f,{DOUBLEWITHTWODWORDINTREE(0x60800000,0x00000000)}},
+        {VT_exponent,22,0x3a9120,{DOUBLEWITHTWODWORDINTREE(0x60900000,0x00000000)}},
+        {VT_exponent,22,0x3a9121,{DOUBLEWITHTWODWORDINTREE(0x60a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9122,{DOUBLEWITHTWODWORDINTREE(0x60b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9123,{DOUBLEWITHTWODWORDINTREE(0x60c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9124,{DOUBLEWITHTWODWORDINTREE(0x60d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9125,{DOUBLEWITHTWODWORDINTREE(0x60e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9126,{DOUBLEWITHTWODWORDINTREE(0x60f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9127,{DOUBLEWITHTWODWORDINTREE(0x61000000,0x00000000)}},
+        {VT_exponent,22,0x3a9128,{DOUBLEWITHTWODWORDINTREE(0x61100000,0x00000000)}},
+        {VT_exponent,22,0x3a9129,{DOUBLEWITHTWODWORDINTREE(0x61200000,0x00000000)}},
+        {VT_exponent,22,0x3a912a,{DOUBLEWITHTWODWORDINTREE(0x61300000,0x00000000)}},
+        {VT_exponent,22,0x3a912b,{DOUBLEWITHTWODWORDINTREE(0x61400000,0x00000000)}},
+        {VT_exponent,22,0x3a912c,{DOUBLEWITHTWODWORDINTREE(0x61500000,0x00000000)}},
+        {VT_exponent,22,0x3a912d,{DOUBLEWITHTWODWORDINTREE(0x61600000,0x00000000)}},
+        {VT_exponent,22,0x3a912e,{DOUBLEWITHTWODWORDINTREE(0x61700000,0x00000000)}},
+        {VT_exponent,22,0x3a912f,{DOUBLEWITHTWODWORDINTREE(0x61800000,0x00000000)}},
+        {VT_exponent,22,0x3a9130,{DOUBLEWITHTWODWORDINTREE(0x61900000,0x00000000)}},
+        {VT_exponent,22,0x3a9131,{DOUBLEWITHTWODWORDINTREE(0x61a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9132,{DOUBLEWITHTWODWORDINTREE(0x61b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9133,{DOUBLEWITHTWODWORDINTREE(0x61c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9134,{DOUBLEWITHTWODWORDINTREE(0x61d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9135,{DOUBLEWITHTWODWORDINTREE(0x61e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9136,{DOUBLEWITHTWODWORDINTREE(0x61f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9137,{DOUBLEWITHTWODWORDINTREE(0x62000000,0x00000000)}},
+        {VT_exponent,22,0x3a9138,{DOUBLEWITHTWODWORDINTREE(0x62100000,0x00000000)}},
+        {VT_exponent,22,0x3a9139,{DOUBLEWITHTWODWORDINTREE(0x62200000,0x00000000)}},
+        {VT_exponent,22,0x3a913a,{DOUBLEWITHTWODWORDINTREE(0x62300000,0x00000000)}},
+        {VT_exponent,22,0x3a913b,{DOUBLEWITHTWODWORDINTREE(0x62400000,0x00000000)}},
+        {VT_exponent,22,0x3a913c,{DOUBLEWITHTWODWORDINTREE(0x62500000,0x00000000)}},
+        {VT_exponent,22,0x3a913d,{DOUBLEWITHTWODWORDINTREE(0x62600000,0x00000000)}},
+        {VT_exponent,22,0x3a913e,{DOUBLEWITHTWODWORDINTREE(0x62700000,0x00000000)}},
+        {VT_exponent,22,0x3a913f,{DOUBLEWITHTWODWORDINTREE(0x62800000,0x00000000)}},
+        {VT_exponent,22,0x3a9140,{DOUBLEWITHTWODWORDINTREE(0x62900000,0x00000000)}},
+        {VT_exponent,22,0x3a9141,{DOUBLEWITHTWODWORDINTREE(0x62a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9142,{DOUBLEWITHTWODWORDINTREE(0x62b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9143,{DOUBLEWITHTWODWORDINTREE(0x62c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9144,{DOUBLEWITHTWODWORDINTREE(0x62d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9145,{DOUBLEWITHTWODWORDINTREE(0x62e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9146,{DOUBLEWITHTWODWORDINTREE(0x62f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9147,{DOUBLEWITHTWODWORDINTREE(0x63000000,0x00000000)}},
+        {VT_exponent,22,0x3a9148,{DOUBLEWITHTWODWORDINTREE(0x63100000,0x00000000)}},
+        {VT_exponent,22,0x3a9149,{DOUBLEWITHTWODWORDINTREE(0x63200000,0x00000000)}},
+        {VT_exponent,22,0x3a914a,{DOUBLEWITHTWODWORDINTREE(0x63300000,0x00000000)}},
+        {VT_exponent,22,0x3a914b,{DOUBLEWITHTWODWORDINTREE(0x63400000,0x00000000)}},
+        {VT_exponent,22,0x3a914c,{DOUBLEWITHTWODWORDINTREE(0x63500000,0x00000000)}},
+        {VT_exponent,22,0x3a914d,{DOUBLEWITHTWODWORDINTREE(0x63600000,0x00000000)}},
+        {VT_exponent,22,0x3a914e,{DOUBLEWITHTWODWORDINTREE(0x63700000,0x00000000)}},
+        {VT_exponent,22,0x3a914f,{DOUBLEWITHTWODWORDINTREE(0x63800000,0x00000000)}},
+        {VT_exponent,22,0x3a9150,{DOUBLEWITHTWODWORDINTREE(0x63900000,0x00000000)}},
+        {VT_exponent,22,0x3a9151,{DOUBLEWITHTWODWORDINTREE(0x63a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9152,{DOUBLEWITHTWODWORDINTREE(0x63b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9153,{DOUBLEWITHTWODWORDINTREE(0x63c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9154,{DOUBLEWITHTWODWORDINTREE(0x63d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9155,{DOUBLEWITHTWODWORDINTREE(0x63e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9156,{DOUBLEWITHTWODWORDINTREE(0x63f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9157,{DOUBLEWITHTWODWORDINTREE(0x64000000,0x00000000)}},
+        {VT_exponent,22,0x3a9158,{DOUBLEWITHTWODWORDINTREE(0x64100000,0x00000000)}},
+        {VT_exponent,22,0x3a9159,{DOUBLEWITHTWODWORDINTREE(0x64200000,0x00000000)}},
+        {VT_exponent,22,0x3a915a,{DOUBLEWITHTWODWORDINTREE(0x64300000,0x00000000)}},
+        {VT_exponent,22,0x3a915b,{DOUBLEWITHTWODWORDINTREE(0x64400000,0x00000000)}},
+        {VT_exponent,22,0x3a915c,{DOUBLEWITHTWODWORDINTREE(0x64500000,0x00000000)}},
+        {VT_exponent,22,0x3a915d,{DOUBLEWITHTWODWORDINTREE(0x64600000,0x00000000)}},
+        {VT_exponent,22,0x3a915e,{DOUBLEWITHTWODWORDINTREE(0x64700000,0x00000000)}},
+        {VT_exponent,22,0x3a915f,{DOUBLEWITHTWODWORDINTREE(0x64800000,0x00000000)}},
+        {VT_exponent,22,0x3a9160,{DOUBLEWITHTWODWORDINTREE(0x64900000,0x00000000)}},
+        {VT_exponent,22,0x3a9161,{DOUBLEWITHTWODWORDINTREE(0x64a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9162,{DOUBLEWITHTWODWORDINTREE(0x64b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9163,{DOUBLEWITHTWODWORDINTREE(0x64c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9164,{DOUBLEWITHTWODWORDINTREE(0x64d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9165,{DOUBLEWITHTWODWORDINTREE(0x64e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9166,{DOUBLEWITHTWODWORDINTREE(0x64f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9167,{DOUBLEWITHTWODWORDINTREE(0x65000000,0x00000000)}},
+        {VT_exponent,22,0x3a9168,{DOUBLEWITHTWODWORDINTREE(0x65100000,0x00000000)}},
+        {VT_exponent,22,0x3a9169,{DOUBLEWITHTWODWORDINTREE(0x65200000,0x00000000)}},
+        {VT_exponent,22,0x3a916a,{DOUBLEWITHTWODWORDINTREE(0x65300000,0x00000000)}},
+        {VT_exponent,22,0x3a916b,{DOUBLEWITHTWODWORDINTREE(0x65400000,0x00000000)}},
+        {VT_exponent,22,0x3a916c,{DOUBLEWITHTWODWORDINTREE(0x65500000,0x00000000)}},
+        {VT_exponent,22,0x3a916d,{DOUBLEWITHTWODWORDINTREE(0x65600000,0x00000000)}},
+        {VT_exponent,22,0x3a916e,{DOUBLEWITHTWODWORDINTREE(0x65700000,0x00000000)}},
+        {VT_exponent,22,0x3a916f,{DOUBLEWITHTWODWORDINTREE(0x65800000,0x00000000)}},
+        {VT_exponent,22,0x3a9170,{DOUBLEWITHTWODWORDINTREE(0x65900000,0x00000000)}},
+        {VT_exponent,22,0x3a9171,{DOUBLEWITHTWODWORDINTREE(0x65a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9172,{DOUBLEWITHTWODWORDINTREE(0x65b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9173,{DOUBLEWITHTWODWORDINTREE(0x65c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9174,{DOUBLEWITHTWODWORDINTREE(0x65d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9175,{DOUBLEWITHTWODWORDINTREE(0x65e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9176,{DOUBLEWITHTWODWORDINTREE(0x65f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9177,{DOUBLEWITHTWODWORDINTREE(0x66000000,0x00000000)}},
+        {VT_exponent,22,0x3a9178,{DOUBLEWITHTWODWORDINTREE(0x66100000,0x00000000)}},
+        {VT_exponent,22,0x3a9179,{DOUBLEWITHTWODWORDINTREE(0x66200000,0x00000000)}},
+        {VT_exponent,22,0x3a917a,{DOUBLEWITHTWODWORDINTREE(0x66300000,0x00000000)}},
+        {VT_exponent,22,0x3a917b,{DOUBLEWITHTWODWORDINTREE(0x66400000,0x00000000)}},
+        {VT_exponent,22,0x3a917c,{DOUBLEWITHTWODWORDINTREE(0x66500000,0x00000000)}},
+        {VT_exponent,22,0x3a917d,{DOUBLEWITHTWODWORDINTREE(0x66600000,0x00000000)}},
+        {VT_exponent,22,0x3a917e,{DOUBLEWITHTWODWORDINTREE(0x66700000,0x00000000)}},
+        {VT_exponent,22,0x3a917f,{DOUBLEWITHTWODWORDINTREE(0x66800000,0x00000000)}},
+        {VT_exponent,22,0x3a9180,{DOUBLEWITHTWODWORDINTREE(0x66900000,0x00000000)}},
+        {VT_exponent,22,0x3a9181,{DOUBLEWITHTWODWORDINTREE(0x66a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9182,{DOUBLEWITHTWODWORDINTREE(0x66b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9183,{DOUBLEWITHTWODWORDINTREE(0x66c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9184,{DOUBLEWITHTWODWORDINTREE(0x66d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9185,{DOUBLEWITHTWODWORDINTREE(0x66e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9186,{DOUBLEWITHTWODWORDINTREE(0x66f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9187,{DOUBLEWITHTWODWORDINTREE(0x67000000,0x00000000)}},
+        {VT_exponent,22,0x3a9188,{DOUBLEWITHTWODWORDINTREE(0x67100000,0x00000000)}},
+        {VT_exponent,22,0x3a9189,{DOUBLEWITHTWODWORDINTREE(0x67200000,0x00000000)}},
+        {VT_exponent,22,0x3a918a,{DOUBLEWITHTWODWORDINTREE(0x67300000,0x00000000)}},
+        {VT_exponent,22,0x3a918b,{DOUBLEWITHTWODWORDINTREE(0x67400000,0x00000000)}},
+        {VT_exponent,22,0x3a918c,{DOUBLEWITHTWODWORDINTREE(0x67500000,0x00000000)}},
+        {VT_exponent,22,0x3a918d,{DOUBLEWITHTWODWORDINTREE(0x67600000,0x00000000)}},
+        {VT_exponent,22,0x3a918e,{DOUBLEWITHTWODWORDINTREE(0x67700000,0x00000000)}},
+        {VT_exponent,22,0x3a918f,{DOUBLEWITHTWODWORDINTREE(0x67800000,0x00000000)}},
+        {VT_exponent,22,0x3a9190,{DOUBLEWITHTWODWORDINTREE(0x67900000,0x00000000)}},
+        {VT_exponent,22,0x3a9191,{DOUBLEWITHTWODWORDINTREE(0x67a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9192,{DOUBLEWITHTWODWORDINTREE(0x67b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9193,{DOUBLEWITHTWODWORDINTREE(0x67c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9194,{DOUBLEWITHTWODWORDINTREE(0x67d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9195,{DOUBLEWITHTWODWORDINTREE(0x67e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9196,{DOUBLEWITHTWODWORDINTREE(0x67f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9197,{DOUBLEWITHTWODWORDINTREE(0x68000000,0x00000000)}},
+        {VT_exponent,22,0x3a9198,{DOUBLEWITHTWODWORDINTREE(0x68100000,0x00000000)}},
+        {VT_exponent,22,0x3a9199,{DOUBLEWITHTWODWORDINTREE(0x68200000,0x00000000)}},
+        {VT_exponent,22,0x3a919a,{DOUBLEWITHTWODWORDINTREE(0x68300000,0x00000000)}},
+        {VT_exponent,22,0x3a919b,{DOUBLEWITHTWODWORDINTREE(0x68400000,0x00000000)}},
+        {VT_exponent,22,0x3a919c,{DOUBLEWITHTWODWORDINTREE(0x68500000,0x00000000)}},
+        {VT_exponent,22,0x3a919d,{DOUBLEWITHTWODWORDINTREE(0x68600000,0x00000000)}},
+        {VT_exponent,22,0x3a919e,{DOUBLEWITHTWODWORDINTREE(0x68700000,0x00000000)}},
+        {VT_exponent,22,0x3a919f,{DOUBLEWITHTWODWORDINTREE(0x68800000,0x00000000)}},
+        {VT_exponent,22,0x3a91a0,{DOUBLEWITHTWODWORDINTREE(0x68900000,0x00000000)}},
+        {VT_exponent,22,0x3a91a1,{DOUBLEWITHTWODWORDINTREE(0x68a00000,0x00000000)}},
+        {VT_exponent,22,0x3a91a2,{DOUBLEWITHTWODWORDINTREE(0x68b00000,0x00000000)}},
+        {VT_exponent,22,0x3a91a3,{DOUBLEWITHTWODWORDINTREE(0x68c00000,0x00000000)}},
+        {VT_exponent,22,0x3a91a4,{DOUBLEWITHTWODWORDINTREE(0x68d00000,0x00000000)}},
+        {VT_exponent,22,0x3a91a5,{DOUBLEWITHTWODWORDINTREE(0x68e00000,0x00000000)}},
+        {VT_exponent,22,0x3a91a6,{DOUBLEWITHTWODWORDINTREE(0x68f00000,0x00000000)}},
+        {VT_exponent,22,0x3a91a7,{DOUBLEWITHTWODWORDINTREE(0x69000000,0x00000000)}},
+        {VT_exponent,22,0x3a91a8,{DOUBLEWITHTWODWORDINTREE(0x69100000,0x00000000)}},
+        {VT_exponent,22,0x3a91a9,{DOUBLEWITHTWODWORDINTREE(0x69200000,0x00000000)}},
+        {VT_exponent,22,0x3a91aa,{DOUBLEWITHTWODWORDINTREE(0x69300000,0x00000000)}},
+        {VT_exponent,22,0x3a91ab,{DOUBLEWITHTWODWORDINTREE(0x69400000,0x00000000)}},
+        {VT_exponent,22,0x3a91ac,{DOUBLEWITHTWODWORDINTREE(0x69500000,0x00000000)}},
+        {VT_exponent,22,0x3a91ad,{DOUBLEWITHTWODWORDINTREE(0x69600000,0x00000000)}},
+        {VT_exponent,22,0x3a91ae,{DOUBLEWITHTWODWORDINTREE(0x69700000,0x00000000)}},
+        {VT_exponent,22,0x3a91af,{DOUBLEWITHTWODWORDINTREE(0x69800000,0x00000000)}},
+        {VT_exponent,22,0x3a91b0,{DOUBLEWITHTWODWORDINTREE(0x69900000,0x00000000)}},
+        {VT_exponent,22,0x3a91b1,{DOUBLEWITHTWODWORDINTREE(0x69a00000,0x00000000)}},
+        {VT_exponent,22,0x3a91b2,{DOUBLEWITHTWODWORDINTREE(0x69b00000,0x00000000)}},
+        {VT_exponent,22,0x3a91b3,{DOUBLEWITHTWODWORDINTREE(0x69c00000,0x00000000)}},
+        {VT_exponent,22,0x3a91b4,{DOUBLEWITHTWODWORDINTREE(0x69d00000,0x00000000)}},
+        {VT_exponent,22,0x3a91b5,{DOUBLEWITHTWODWORDINTREE(0x69e00000,0x00000000)}},
+        {VT_exponent,22,0x3a91b6,{DOUBLEWITHTWODWORDINTREE(0x69f00000,0x00000000)}},
+        {VT_exponent,22,0x3a91b7,{DOUBLEWITHTWODWORDINTREE(0x6a000000,0x00000000)}},
+        {VT_exponent,22,0x3a91b8,{DOUBLEWITHTWODWORDINTREE(0x6a100000,0x00000000)}},
+        {VT_exponent,22,0x3a91b9,{DOUBLEWITHTWODWORDINTREE(0x6a200000,0x00000000)}},
+        {VT_exponent,22,0x3a91ba,{DOUBLEWITHTWODWORDINTREE(0x6a300000,0x00000000)}},
+        {VT_exponent,22,0x3a91bb,{DOUBLEWITHTWODWORDINTREE(0x6a400000,0x00000000)}},
+        {VT_exponent,22,0x3a91bc,{DOUBLEWITHTWODWORDINTREE(0x6a500000,0x00000000)}},
+        {VT_exponent,22,0x3a91bd,{DOUBLEWITHTWODWORDINTREE(0x6a600000,0x00000000)}},
+        {VT_exponent,22,0x3a91be,{DOUBLEWITHTWODWORDINTREE(0x6a700000,0x00000000)}},
+        {VT_exponent,22,0x3a91bf,{DOUBLEWITHTWODWORDINTREE(0x6a800000,0x00000000)}},
+        {VT_exponent,22,0x3a91c0,{DOUBLEWITHTWODWORDINTREE(0x6a900000,0x00000000)}},
+        {VT_exponent,22,0x3a91c1,{DOUBLEWITHTWODWORDINTREE(0x6aa00000,0x00000000)}},
+        {VT_exponent,22,0x3a91c2,{DOUBLEWITHTWODWORDINTREE(0x6ab00000,0x00000000)}},
+        {VT_exponent,22,0x3a91c3,{DOUBLEWITHTWODWORDINTREE(0x6ac00000,0x00000000)}},
+        {VT_exponent,22,0x3a91c4,{DOUBLEWITHTWODWORDINTREE(0x6ad00000,0x00000000)}},
+        {VT_exponent,22,0x3a91c5,{DOUBLEWITHTWODWORDINTREE(0x6ae00000,0x00000000)}},
+        {VT_exponent,22,0x3a91c6,{DOUBLEWITHTWODWORDINTREE(0x6af00000,0x00000000)}},
+        {VT_exponent,22,0x3a91c7,{DOUBLEWITHTWODWORDINTREE(0x6b000000,0x00000000)}},
+        {VT_exponent,22,0x3a91c8,{DOUBLEWITHTWODWORDINTREE(0x6b100000,0x00000000)}},
+        {VT_exponent,22,0x3a91c9,{DOUBLEWITHTWODWORDINTREE(0x6b200000,0x00000000)}},
+        {VT_exponent,22,0x3a91ca,{DOUBLEWITHTWODWORDINTREE(0x6b300000,0x00000000)}},
+        {VT_exponent,22,0x3a91cb,{DOUBLEWITHTWODWORDINTREE(0x6b400000,0x00000000)}},
+        {VT_exponent,22,0x3a91cc,{DOUBLEWITHTWODWORDINTREE(0x6b500000,0x00000000)}},
+        {VT_exponent,22,0x3a91cd,{DOUBLEWITHTWODWORDINTREE(0x6b600000,0x00000000)}},
+        {VT_exponent,22,0x3a91ce,{DOUBLEWITHTWODWORDINTREE(0x6b700000,0x00000000)}},
+        {VT_exponent,22,0x3a91cf,{DOUBLEWITHTWODWORDINTREE(0x6b800000,0x00000000)}},
+        {VT_exponent,22,0x3a91d0,{DOUBLEWITHTWODWORDINTREE(0x6b900000,0x00000000)}},
+        {VT_exponent,22,0x3a91d1,{DOUBLEWITHTWODWORDINTREE(0x6ba00000,0x00000000)}},
+        {VT_exponent,22,0x3a91d2,{DOUBLEWITHTWODWORDINTREE(0x6bb00000,0x00000000)}},
+        {VT_exponent,22,0x3a91d3,{DOUBLEWITHTWODWORDINTREE(0x6bc00000,0x00000000)}},
+        {VT_exponent,22,0x3a91d4,{DOUBLEWITHTWODWORDINTREE(0x6bd00000,0x00000000)}},
+        {VT_exponent,22,0x3a91d5,{DOUBLEWITHTWODWORDINTREE(0x6be00000,0x00000000)}},
+        {VT_exponent,22,0x3a91d6,{DOUBLEWITHTWODWORDINTREE(0x6bf00000,0x00000000)}},
+        {VT_exponent,22,0x3a91d7,{DOUBLEWITHTWODWORDINTREE(0x6c000000,0x00000000)}},
+        {VT_exponent,22,0x3a91d8,{DOUBLEWITHTWODWORDINTREE(0x6c100000,0x00000000)}},
+        {VT_exponent,22,0x3a91d9,{DOUBLEWITHTWODWORDINTREE(0x6c200000,0x00000000)}},
+        {VT_exponent,22,0x3a91da,{DOUBLEWITHTWODWORDINTREE(0x6c300000,0x00000000)}},
+        {VT_exponent,22,0x3a91db,{DOUBLEWITHTWODWORDINTREE(0x6c400000,0x00000000)}},
+        {VT_exponent,22,0x3a91dc,{DOUBLEWITHTWODWORDINTREE(0x6c500000,0x00000000)}},
+        {VT_exponent,22,0x3a91dd,{DOUBLEWITHTWODWORDINTREE(0x6c600000,0x00000000)}},
+        {VT_exponent,22,0x3a91de,{DOUBLEWITHTWODWORDINTREE(0x6c700000,0x00000000)}},
+        {VT_exponent,22,0x3a91df,{DOUBLEWITHTWODWORDINTREE(0x6c800000,0x00000000)}},
+        {VT_exponent,22,0x3a91e0,{DOUBLEWITHTWODWORDINTREE(0x6c900000,0x00000000)}},
+        {VT_exponent,22,0x3a91e1,{DOUBLEWITHTWODWORDINTREE(0x6ca00000,0x00000000)}},
+        {VT_exponent,22,0x3a91e2,{DOUBLEWITHTWODWORDINTREE(0x6cb00000,0x00000000)}},
+        {VT_exponent,22,0x3a91e3,{DOUBLEWITHTWODWORDINTREE(0x6cc00000,0x00000000)}},
+        {VT_exponent,22,0x3a91e4,{DOUBLEWITHTWODWORDINTREE(0x6cd00000,0x00000000)}},
+        {VT_exponent,22,0x3a91e5,{DOUBLEWITHTWODWORDINTREE(0x6ce00000,0x00000000)}},
+        {VT_exponent,22,0x3a91e6,{DOUBLEWITHTWODWORDINTREE(0x6cf00000,0x00000000)}},
+        {VT_exponent,22,0x3a91e7,{DOUBLEWITHTWODWORDINTREE(0x6d000000,0x00000000)}},
+        {VT_exponent,22,0x3a91e8,{DOUBLEWITHTWODWORDINTREE(0x6d100000,0x00000000)}},
+        {VT_exponent,22,0x3a91e9,{DOUBLEWITHTWODWORDINTREE(0x6d200000,0x00000000)}},
+        {VT_exponent,22,0x3a91ea,{DOUBLEWITHTWODWORDINTREE(0x6d300000,0x00000000)}},
+        {VT_exponent,22,0x3a91eb,{DOUBLEWITHTWODWORDINTREE(0x6d400000,0x00000000)}},
+        {VT_exponent,22,0x3a91ec,{DOUBLEWITHTWODWORDINTREE(0x6d500000,0x00000000)}},
+        {VT_exponent,22,0x3a91ed,{DOUBLEWITHTWODWORDINTREE(0x6d600000,0x00000000)}},
+        {VT_exponent,22,0x3a91ee,{DOUBLEWITHTWODWORDINTREE(0x6d700000,0x00000000)}},
+        {VT_exponent,22,0x3a91ef,{DOUBLEWITHTWODWORDINTREE(0x6d800000,0x00000000)}},
+        {VT_exponent,22,0x3a91f0,{DOUBLEWITHTWODWORDINTREE(0x6d900000,0x00000000)}},
+        {VT_exponent,22,0x3a91f1,{DOUBLEWITHTWODWORDINTREE(0x6da00000,0x00000000)}},
+        {VT_exponent,22,0x3a91f2,{DOUBLEWITHTWODWORDINTREE(0x6db00000,0x00000000)}},
+        {VT_exponent,22,0x3a91f3,{DOUBLEWITHTWODWORDINTREE(0x6dc00000,0x00000000)}},
+        {VT_exponent,22,0x3a91f4,{DOUBLEWITHTWODWORDINTREE(0x6dd00000,0x00000000)}},
+        {VT_exponent,22,0x3a91f5,{DOUBLEWITHTWODWORDINTREE(0x6de00000,0x00000000)}},
+        {VT_exponent,22,0x3a91f6,{DOUBLEWITHTWODWORDINTREE(0x6df00000,0x00000000)}},
+        {VT_exponent,22,0x3a91f7,{DOUBLEWITHTWODWORDINTREE(0x6e000000,0x00000000)}},
+        {VT_exponent,22,0x3a91f8,{DOUBLEWITHTWODWORDINTREE(0x6e100000,0x00000000)}},
+        {VT_exponent,22,0x3a91f9,{DOUBLEWITHTWODWORDINTREE(0x6e200000,0x00000000)}},
+        {VT_exponent,22,0x3a91fa,{DOUBLEWITHTWODWORDINTREE(0x6e300000,0x00000000)}},
+        {VT_exponent,22,0x3a91fb,{DOUBLEWITHTWODWORDINTREE(0x6e400000,0x00000000)}},
+        {VT_exponent,22,0x3a91fc,{DOUBLEWITHTWODWORDINTREE(0x6e500000,0x00000000)}},
+        {VT_exponent,22,0x3a91fd,{DOUBLEWITHTWODWORDINTREE(0x6e600000,0x00000000)}},
+        {VT_exponent,22,0x3a91fe,{DOUBLEWITHTWODWORDINTREE(0x6e700000,0x00000000)}},
+        {VT_exponent,22,0x3a91ff,{DOUBLEWITHTWODWORDINTREE(0x6e800000,0x00000000)}},
+        {VT_exponent,22,0x3a9200,{DOUBLEWITHTWODWORDINTREE(0x6e900000,0x00000000)}},
+        {VT_exponent,22,0x3a9201,{DOUBLEWITHTWODWORDINTREE(0x6ea00000,0x00000000)}},
+        {VT_exponent,22,0x3a9202,{DOUBLEWITHTWODWORDINTREE(0x6eb00000,0x00000000)}},
+        {VT_exponent,22,0x3a9203,{DOUBLEWITHTWODWORDINTREE(0x6ec00000,0x00000000)}},
+        {VT_exponent,22,0x3a9204,{DOUBLEWITHTWODWORDINTREE(0x6ed00000,0x00000000)}},
+        {VT_exponent,22,0x3a9205,{DOUBLEWITHTWODWORDINTREE(0x6ee00000,0x00000000)}},
+        {VT_exponent,22,0x3a9206,{DOUBLEWITHTWODWORDINTREE(0x6ef00000,0x00000000)}},
+        {VT_exponent,22,0x3a9207,{DOUBLEWITHTWODWORDINTREE(0x6f000000,0x00000000)}},
+        {VT_exponent,22,0x3a9208,{DOUBLEWITHTWODWORDINTREE(0x6f100000,0x00000000)}},
+        {VT_exponent,22,0x3a9209,{DOUBLEWITHTWODWORDINTREE(0x6f200000,0x00000000)}},
+        {VT_exponent,22,0x3a920a,{DOUBLEWITHTWODWORDINTREE(0x6f300000,0x00000000)}},
+        {VT_exponent,22,0x3a920b,{DOUBLEWITHTWODWORDINTREE(0x6f400000,0x00000000)}},
+        {VT_exponent,22,0x3a920c,{DOUBLEWITHTWODWORDINTREE(0x6f500000,0x00000000)}},
+        {VT_exponent,22,0x3a920d,{DOUBLEWITHTWODWORDINTREE(0x6f600000,0x00000000)}},
+        {VT_exponent,22,0x3a920e,{DOUBLEWITHTWODWORDINTREE(0x6f700000,0x00000000)}},
+        {VT_exponent,22,0x3a920f,{DOUBLEWITHTWODWORDINTREE(0x6f800000,0x00000000)}},
+        {VT_exponent,22,0x3a9210,{DOUBLEWITHTWODWORDINTREE(0x6f900000,0x00000000)}},
+        {VT_exponent,22,0x3a9211,{DOUBLEWITHTWODWORDINTREE(0x6fa00000,0x00000000)}},
+        {VT_exponent,22,0x3a9212,{DOUBLEWITHTWODWORDINTREE(0x6fb00000,0x00000000)}},
+        {VT_exponent,22,0x3a9213,{DOUBLEWITHTWODWORDINTREE(0x6fc00000,0x00000000)}},
+        {VT_exponent,22,0x3a9214,{DOUBLEWITHTWODWORDINTREE(0x6fd00000,0x00000000)}},
+        {VT_exponent,22,0x3a9215,{DOUBLEWITHTWODWORDINTREE(0x6fe00000,0x00000000)}},
+        {VT_exponent,22,0x3a9216,{DOUBLEWITHTWODWORDINTREE(0x6ff00000,0x00000000)}},
+        {VT_exponent,22,0x3a9217,{DOUBLEWITHTWODWORDINTREE(0x70000000,0x00000000)}},
+        {VT_exponent,22,0x3a9218,{DOUBLEWITHTWODWORDINTREE(0x70100000,0x00000000)}},
+        {VT_exponent,22,0x3a9219,{DOUBLEWITHTWODWORDINTREE(0x70200000,0x00000000)}},
+        {VT_exponent,22,0x3a921a,{DOUBLEWITHTWODWORDINTREE(0x70300000,0x00000000)}},
+        {VT_exponent,22,0x3a921b,{DOUBLEWITHTWODWORDINTREE(0x70400000,0x00000000)}},
+        {VT_exponent,22,0x3a921c,{DOUBLEWITHTWODWORDINTREE(0x70500000,0x00000000)}},
+        {VT_exponent,22,0x3a921d,{DOUBLEWITHTWODWORDINTREE(0x70600000,0x00000000)}},
+        {VT_exponent,22,0x3a921e,{DOUBLEWITHTWODWORDINTREE(0x70700000,0x00000000)}},
+        {VT_exponent,22,0x3a921f,{DOUBLEWITHTWODWORDINTREE(0x70800000,0x00000000)}},
+        {VT_exponent,22,0x3a9220,{DOUBLEWITHTWODWORDINTREE(0x70900000,0x00000000)}},
+        {VT_exponent,22,0x3a9221,{DOUBLEWITHTWODWORDINTREE(0x70a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9222,{DOUBLEWITHTWODWORDINTREE(0x70b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9223,{DOUBLEWITHTWODWORDINTREE(0x70c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9224,{DOUBLEWITHTWODWORDINTREE(0x70d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9225,{DOUBLEWITHTWODWORDINTREE(0x70e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9226,{DOUBLEWITHTWODWORDINTREE(0x70f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9227,{DOUBLEWITHTWODWORDINTREE(0x71000000,0x00000000)}},
+        {VT_exponent,22,0x3a9228,{DOUBLEWITHTWODWORDINTREE(0x71100000,0x00000000)}},
+        {VT_exponent,22,0x3a9229,{DOUBLEWITHTWODWORDINTREE(0x71200000,0x00000000)}},
+        {VT_exponent,22,0x3a922a,{DOUBLEWITHTWODWORDINTREE(0x71300000,0x00000000)}},
+        {VT_exponent,22,0x3a922b,{DOUBLEWITHTWODWORDINTREE(0x71400000,0x00000000)}},
+        {VT_exponent,22,0x3a922c,{DOUBLEWITHTWODWORDINTREE(0x71500000,0x00000000)}},
+        {VT_exponent,22,0x3a922d,{DOUBLEWITHTWODWORDINTREE(0x71600000,0x00000000)}},
+        {VT_exponent,22,0x3a922e,{DOUBLEWITHTWODWORDINTREE(0x71700000,0x00000000)}},
+        {VT_exponent,22,0x3a922f,{DOUBLEWITHTWODWORDINTREE(0x71800000,0x00000000)}},
+        {VT_exponent,22,0x3a9230,{DOUBLEWITHTWODWORDINTREE(0x71900000,0x00000000)}},
+        {VT_exponent,22,0x3a9231,{DOUBLEWITHTWODWORDINTREE(0x71a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9232,{DOUBLEWITHTWODWORDINTREE(0x71b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9233,{DOUBLEWITHTWODWORDINTREE(0x71c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9234,{DOUBLEWITHTWODWORDINTREE(0x71d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9235,{DOUBLEWITHTWODWORDINTREE(0x71e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9236,{DOUBLEWITHTWODWORDINTREE(0x71f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9237,{DOUBLEWITHTWODWORDINTREE(0x72000000,0x00000000)}},
+        {VT_exponent,22,0x3a9238,{DOUBLEWITHTWODWORDINTREE(0x72100000,0x00000000)}},
+        {VT_exponent,22,0x3a9239,{DOUBLEWITHTWODWORDINTREE(0x72200000,0x00000000)}},
+        {VT_exponent,22,0x3a923a,{DOUBLEWITHTWODWORDINTREE(0x72300000,0x00000000)}},
+        {VT_exponent,22,0x3a923b,{DOUBLEWITHTWODWORDINTREE(0x72400000,0x00000000)}},
+        {VT_exponent,22,0x3a923c,{DOUBLEWITHTWODWORDINTREE(0x72500000,0x00000000)}},
+        {VT_exponent,22,0x3a923d,{DOUBLEWITHTWODWORDINTREE(0x72600000,0x00000000)}},
+        {VT_exponent,22,0x3a923e,{DOUBLEWITHTWODWORDINTREE(0x72700000,0x00000000)}},
+        {VT_exponent,22,0x3a923f,{DOUBLEWITHTWODWORDINTREE(0x72800000,0x00000000)}},
+        {VT_exponent,22,0x3a9240,{DOUBLEWITHTWODWORDINTREE(0x72900000,0x00000000)}},
+        {VT_exponent,22,0x3a9241,{DOUBLEWITHTWODWORDINTREE(0x72a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9242,{DOUBLEWITHTWODWORDINTREE(0x72b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9243,{DOUBLEWITHTWODWORDINTREE(0x72c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9244,{DOUBLEWITHTWODWORDINTREE(0x72d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9245,{DOUBLEWITHTWODWORDINTREE(0x72e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9246,{DOUBLEWITHTWODWORDINTREE(0x72f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9247,{DOUBLEWITHTWODWORDINTREE(0x73000000,0x00000000)}},
+        {VT_exponent,22,0x3a9248,{DOUBLEWITHTWODWORDINTREE(0x73100000,0x00000000)}},
+        {VT_exponent,22,0x3a9249,{DOUBLEWITHTWODWORDINTREE(0x73200000,0x00000000)}},
+        {VT_exponent,22,0x3a924a,{DOUBLEWITHTWODWORDINTREE(0x73300000,0x00000000)}},
+        {VT_exponent,22,0x3a924b,{DOUBLEWITHTWODWORDINTREE(0x73400000,0x00000000)}},
+        {VT_exponent,22,0x3a924c,{DOUBLEWITHTWODWORDINTREE(0x73500000,0x00000000)}},
+        {VT_exponent,22,0x3a924d,{DOUBLEWITHTWODWORDINTREE(0x73600000,0x00000000)}},
+        {VT_exponent,22,0x3a924e,{DOUBLEWITHTWODWORDINTREE(0x73700000,0x00000000)}},
+        {VT_exponent,22,0x3a924f,{DOUBLEWITHTWODWORDINTREE(0x73800000,0x00000000)}},
+        {VT_exponent,22,0x3a9250,{DOUBLEWITHTWODWORDINTREE(0x73900000,0x00000000)}},
+        {VT_exponent,22,0x3a9251,{DOUBLEWITHTWODWORDINTREE(0x73a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9252,{DOUBLEWITHTWODWORDINTREE(0x73b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9253,{DOUBLEWITHTWODWORDINTREE(0x73c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9254,{DOUBLEWITHTWODWORDINTREE(0x73d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9255,{DOUBLEWITHTWODWORDINTREE(0x73e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9256,{DOUBLEWITHTWODWORDINTREE(0x73f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9257,{DOUBLEWITHTWODWORDINTREE(0x74000000,0x00000000)}},
+        {VT_exponent,22,0x3a9258,{DOUBLEWITHTWODWORDINTREE(0x74100000,0x00000000)}},
+        {VT_exponent,22,0x3a9259,{DOUBLEWITHTWODWORDINTREE(0x74200000,0x00000000)}},
+        {VT_exponent,22,0x3a925a,{DOUBLEWITHTWODWORDINTREE(0x74300000,0x00000000)}},
+        {VT_exponent,22,0x3a925b,{DOUBLEWITHTWODWORDINTREE(0x74400000,0x00000000)}},
+        {VT_exponent,22,0x3a925c,{DOUBLEWITHTWODWORDINTREE(0x74500000,0x00000000)}},
+        {VT_exponent,22,0x3a925d,{DOUBLEWITHTWODWORDINTREE(0x74600000,0x00000000)}},
+        {VT_exponent,22,0x3a925e,{DOUBLEWITHTWODWORDINTREE(0x74700000,0x00000000)}},
+        {VT_exponent,22,0x3a925f,{DOUBLEWITHTWODWORDINTREE(0x74800000,0x00000000)}},
+        {VT_exponent,22,0x3a9260,{DOUBLEWITHTWODWORDINTREE(0x74900000,0x00000000)}},
+        {VT_exponent,22,0x3a9261,{DOUBLEWITHTWODWORDINTREE(0x74a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9262,{DOUBLEWITHTWODWORDINTREE(0x74b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9263,{DOUBLEWITHTWODWORDINTREE(0x74c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9264,{DOUBLEWITHTWODWORDINTREE(0x74d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9265,{DOUBLEWITHTWODWORDINTREE(0x74e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9266,{DOUBLEWITHTWODWORDINTREE(0x74f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9267,{DOUBLEWITHTWODWORDINTREE(0x75000000,0x00000000)}},
+        {VT_exponent,22,0x3a9268,{DOUBLEWITHTWODWORDINTREE(0x75100000,0x00000000)}},
+        {VT_exponent,22,0x3a9269,{DOUBLEWITHTWODWORDINTREE(0x75200000,0x00000000)}},
+        {VT_exponent,22,0x3a926a,{DOUBLEWITHTWODWORDINTREE(0x75300000,0x00000000)}},
+        {VT_exponent,22,0x3a926b,{DOUBLEWITHTWODWORDINTREE(0x75400000,0x00000000)}},
+        {VT_exponent,22,0x3a926c,{DOUBLEWITHTWODWORDINTREE(0x75500000,0x00000000)}},
+        {VT_exponent,22,0x3a926d,{DOUBLEWITHTWODWORDINTREE(0x75600000,0x00000000)}},
+        {VT_exponent,22,0x3a926e,{DOUBLEWITHTWODWORDINTREE(0x75700000,0x00000000)}},
+        {VT_exponent,22,0x3a926f,{DOUBLEWITHTWODWORDINTREE(0x75800000,0x00000000)}},
+        {VT_exponent,22,0x3a9270,{DOUBLEWITHTWODWORDINTREE(0x75900000,0x00000000)}},
+        {VT_exponent,22,0x3a9271,{DOUBLEWITHTWODWORDINTREE(0x75a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9272,{DOUBLEWITHTWODWORDINTREE(0x75b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9273,{DOUBLEWITHTWODWORDINTREE(0x75c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9274,{DOUBLEWITHTWODWORDINTREE(0x75d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9275,{DOUBLEWITHTWODWORDINTREE(0x75e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9276,{DOUBLEWITHTWODWORDINTREE(0x75f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9277,{DOUBLEWITHTWODWORDINTREE(0x76000000,0x00000000)}},
+        {VT_exponent,22,0x3a9278,{DOUBLEWITHTWODWORDINTREE(0x76100000,0x00000000)}},
+        {VT_exponent,22,0x3a9279,{DOUBLEWITHTWODWORDINTREE(0x76200000,0x00000000)}},
+        {VT_exponent,22,0x3a927a,{DOUBLEWITHTWODWORDINTREE(0x76300000,0x00000000)}},
+        {VT_exponent,22,0x3a927b,{DOUBLEWITHTWODWORDINTREE(0x76400000,0x00000000)}},
+        {VT_exponent,22,0x3a927c,{DOUBLEWITHTWODWORDINTREE(0x76500000,0x00000000)}},
+        {VT_exponent,22,0x3a927d,{DOUBLEWITHTWODWORDINTREE(0x76600000,0x00000000)}},
+        {VT_exponent,22,0x3a927e,{DOUBLEWITHTWODWORDINTREE(0x76700000,0x00000000)}},
+        {VT_exponent,22,0x3a927f,{DOUBLEWITHTWODWORDINTREE(0x76800000,0x00000000)}},
+        {VT_exponent,22,0x3a9280,{DOUBLEWITHTWODWORDINTREE(0x76900000,0x00000000)}},
+        {VT_exponent,22,0x3a9281,{DOUBLEWITHTWODWORDINTREE(0x76a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9282,{DOUBLEWITHTWODWORDINTREE(0x76b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9283,{DOUBLEWITHTWODWORDINTREE(0x76c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9284,{DOUBLEWITHTWODWORDINTREE(0x76d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9285,{DOUBLEWITHTWODWORDINTREE(0x76e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9286,{DOUBLEWITHTWODWORDINTREE(0x76f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9287,{DOUBLEWITHTWODWORDINTREE(0x77000000,0x00000000)}},
+        {VT_exponent,22,0x3a9288,{DOUBLEWITHTWODWORDINTREE(0x77100000,0x00000000)}},
+        {VT_exponent,22,0x3a9289,{DOUBLEWITHTWODWORDINTREE(0x77200000,0x00000000)}},
+        {VT_exponent,22,0x3a928a,{DOUBLEWITHTWODWORDINTREE(0x77300000,0x00000000)}},
+        {VT_exponent,22,0x3a928b,{DOUBLEWITHTWODWORDINTREE(0x77400000,0x00000000)}},
+        {VT_exponent,22,0x3a928c,{DOUBLEWITHTWODWORDINTREE(0x77500000,0x00000000)}},
+        {VT_exponent,22,0x3a928d,{DOUBLEWITHTWODWORDINTREE(0x77600000,0x00000000)}},
+        {VT_exponent,22,0x3a928e,{DOUBLEWITHTWODWORDINTREE(0x77700000,0x00000000)}},
+        {VT_exponent,22,0x3a928f,{DOUBLEWITHTWODWORDINTREE(0x77800000,0x00000000)}},
+        {VT_exponent,22,0x3a9290,{DOUBLEWITHTWODWORDINTREE(0x77900000,0x00000000)}},
+        {VT_exponent,22,0x3a9291,{DOUBLEWITHTWODWORDINTREE(0x77a00000,0x00000000)}},
+        {VT_exponent,22,0x3a9292,{DOUBLEWITHTWODWORDINTREE(0x77b00000,0x00000000)}},
+        {VT_exponent,22,0x3a9293,{DOUBLEWITHTWODWORDINTREE(0x77c00000,0x00000000)}},
+        {VT_exponent,22,0x3a9294,{DOUBLEWITHTWODWORDINTREE(0x77d00000,0x00000000)}},
+        {VT_exponent,22,0x3a9295,{DOUBLEWITHTWODWORDINTREE(0x77e00000,0x00000000)}},
+        {VT_exponent,22,0x3a9296,{DOUBLEWITHTWODWORDINTREE(0x77f00000,0x00000000)}},
+        {VT_exponent,22,0x3a9297,{DOUBLEWITHTWODWORDINTREE(0x78000000,0x00000000)}},
+        {VT_exponent,22,0x3a9298,{DOUBLEWITHTWODWORDINTREE(0x78100000,0x00000000)}},
+        {VT_exponent,22,0x3a9299,{DOUBLEWITHTWODWORDINTREE(0x78200000,0x00000000)}},
+        {VT_exponent,22,0x3a929a,{DOUBLEWITHTWODWORDINTREE(0x78300000,0x00000000)}},
+        {VT_exponent,22,0x3a929b,{DOUBLEWITHTWODWORDINTREE(0x78400000,0x00000000)}},
+        {VT_exponent,22,0x3a929c,{DOUBLEWITHTWODWORDINTREE(0x78500000,0x00000000)}},
+        {VT_exponent,22,0x3a929d,{DOUBLEWITHTWODWORDINTREE(0x78600000,0x00000000)}},
+        {VT_exponent,22,0x3a929e,{DOUBLEWITHTWODWORDINTREE(0x78700000,0x00000000)}},
+        {VT_exponent,22,0x3a929f,{DOUBLEWITHTWODWORDINTREE(0x78800000,0x00000000)}},
+        {VT_exponent,22,0x3a92a0,{DOUBLEWITHTWODWORDINTREE(0x78900000,0x00000000)}},
+        {VT_exponent,22,0x3a92a1,{DOUBLEWITHTWODWORDINTREE(0x78a00000,0x00000000)}},
+        {VT_exponent,22,0x3a92a2,{DOUBLEWITHTWODWORDINTREE(0x78b00000,0x00000000)}},
+        {VT_exponent,22,0x3a92a3,{DOUBLEWITHTWODWORDINTREE(0x78c00000,0x00000000)}},
+        {VT_exponent,22,0x3a92a4,{DOUBLEWITHTWODWORDINTREE(0x78d00000,0x00000000)}},
+        {VT_exponent,22,0x3a92a5,{DOUBLEWITHTWODWORDINTREE(0x78e00000,0x00000000)}},
+        {VT_exponent,22,0x3a92a6,{DOUBLEWITHTWODWORDINTREE(0x78f00000,0x00000000)}},
+        {VT_exponent,22,0x3a92a7,{DOUBLEWITHTWODWORDINTREE(0x79000000,0x00000000)}},
+        {VT_exponent,22,0x3a92a8,{DOUBLEWITHTWODWORDINTREE(0x79100000,0x00000000)}},
+        {VT_exponent,22,0x3a92a9,{DOUBLEWITHTWODWORDINTREE(0x79200000,0x00000000)}},
+        {VT_exponent,22,0x3a92aa,{DOUBLEWITHTWODWORDINTREE(0x79300000,0x00000000)}},
+        {VT_exponent,22,0x3a92ab,{DOUBLEWITHTWODWORDINTREE(0x79400000,0x00000000)}},
+        {VT_exponent,22,0x3a92ac,{DOUBLEWITHTWODWORDINTREE(0x79500000,0x00000000)}},
+        {VT_exponent,22,0x3a92ad,{DOUBLEWITHTWODWORDINTREE(0x79600000,0x00000000)}},
+        {VT_exponent,22,0x3a92ae,{DOUBLEWITHTWODWORDINTREE(0x79700000,0x00000000)}},
+        {VT_exponent,22,0x3a92af,{DOUBLEWITHTWODWORDINTREE(0x79800000,0x00000000)}},
+        {VT_exponent,22,0x3a92b0,{DOUBLEWITHTWODWORDINTREE(0x79900000,0x00000000)}},
+        {VT_exponent,22,0x3a92b1,{DOUBLEWITHTWODWORDINTREE(0x79a00000,0x00000000)}},
+        {VT_exponent,22,0x3a92b2,{DOUBLEWITHTWODWORDINTREE(0x79b00000,0x00000000)}},
+        {VT_exponent,22,0x3a92b3,{DOUBLEWITHTWODWORDINTREE(0x79c00000,0x00000000)}},
+        {VT_exponent,22,0x3a92b4,{DOUBLEWITHTWODWORDINTREE(0x79d00000,0x00000000)}},
+        {VT_exponent,22,0x3a92b5,{DOUBLEWITHTWODWORDINTREE(0x79e00000,0x00000000)}},
+        {VT_exponent,22,0x3a92b6,{DOUBLEWITHTWODWORDINTREE(0x79f00000,0x00000000)}},
+        {VT_exponent,22,0x3a92b7,{DOUBLEWITHTWODWORDINTREE(0x7a000000,0x00000000)}},
+        {VT_exponent,22,0x3a92b8,{DOUBLEWITHTWODWORDINTREE(0x7a100000,0x00000000)}},
+        {VT_exponent,22,0x3a92b9,{DOUBLEWITHTWODWORDINTREE(0x7a200000,0x00000000)}},
+        {VT_exponent,22,0x3a92ba,{DOUBLEWITHTWODWORDINTREE(0x7a300000,0x00000000)}},
+        {VT_exponent,22,0x3a92bb,{DOUBLEWITHTWODWORDINTREE(0x7a400000,0x00000000)}},
+        {VT_exponent,22,0x3a92bc,{DOUBLEWITHTWODWORDINTREE(0x7a500000,0x00000000)}},
+        {VT_exponent,22,0x3a92bd,{DOUBLEWITHTWODWORDINTREE(0x7a600000,0x00000000)}},
+        {VT_exponent,22,0x3a92be,{DOUBLEWITHTWODWORDINTREE(0x7a700000,0x00000000)}},
+        {VT_exponent,22,0x3a92bf,{DOUBLEWITHTWODWORDINTREE(0x7a800000,0x00000000)}},
+        {VT_exponent,22,0x3a92c0,{DOUBLEWITHTWODWORDINTREE(0x7a900000,0x00000000)}},
+        {VT_exponent,22,0x3a92c1,{DOUBLEWITHTWODWORDINTREE(0x7aa00000,0x00000000)}},
+        {VT_exponent,22,0x3a92c2,{DOUBLEWITHTWODWORDINTREE(0x7ab00000,0x00000000)}},
+        {VT_exponent,22,0x3a92c3,{DOUBLEWITHTWODWORDINTREE(0x7ac00000,0x00000000)}},
+        {VT_exponent,22,0x3a92c4,{DOUBLEWITHTWODWORDINTREE(0x7ad00000,0x00000000)}},
+        {VT_exponent,22,0x3a92c5,{DOUBLEWITHTWODWORDINTREE(0x7ae00000,0x00000000)}},
+        {VT_exponent,22,0x3a92c6,{DOUBLEWITHTWODWORDINTREE(0x7af00000,0x00000000)}},
+        {VT_exponent,22,0x3a92c7,{DOUBLEWITHTWODWORDINTREE(0x7b000000,0x00000000)}},
+        {VT_exponent,22,0x3a92c8,{DOUBLEWITHTWODWORDINTREE(0x7b100000,0x00000000)}},
+        {VT_exponent,22,0x3a92c9,{DOUBLEWITHTWODWORDINTREE(0x7b200000,0x00000000)}},
+        {VT_exponent,22,0x3a92ca,{DOUBLEWITHTWODWORDINTREE(0x7b300000,0x00000000)}},
+        {VT_exponent,22,0x3a92cb,{DOUBLEWITHTWODWORDINTREE(0x7b400000,0x00000000)}},
+        {VT_exponent,22,0x3a92cc,{DOUBLEWITHTWODWORDINTREE(0x7b500000,0x00000000)}},
+        {VT_exponent,22,0x3a92cd,{DOUBLEWITHTWODWORDINTREE(0x7b600000,0x00000000)}},
+        {VT_exponent,22,0x3a92ce,{DOUBLEWITHTWODWORDINTREE(0x7b700000,0x00000000)}},
+        {VT_exponent,22,0x3a92cf,{DOUBLEWITHTWODWORDINTREE(0x7b800000,0x00000000)}},
+        {VT_exponent,22,0x3a92d0,{DOUBLEWITHTWODWORDINTREE(0x7b900000,0x00000000)}},
+        {VT_exponent,22,0x3a92d1,{DOUBLEWITHTWODWORDINTREE(0x7ba00000,0x00000000)}},
+        {VT_exponent,22,0x3a92d2,{DOUBLEWITHTWODWORDINTREE(0x7bb00000,0x00000000)}},
+        {VT_exponent,22,0x3a92d3,{DOUBLEWITHTWODWORDINTREE(0x7bc00000,0x00000000)}},
+        {VT_exponent,22,0x3a92d4,{DOUBLEWITHTWODWORDINTREE(0x7bd00000,0x00000000)}},
+        {VT_exponent,22,0x3a92d5,{DOUBLEWITHTWODWORDINTREE(0x7be00000,0x00000000)}},
+        {VT_exponent,22,0x3a92d6,{DOUBLEWITHTWODWORDINTREE(0x7bf00000,0x00000000)}},
+        {VT_exponent,22,0x3a92d7,{DOUBLEWITHTWODWORDINTREE(0x7c000000,0x00000000)}},
+        {VT_exponent,22,0x3a92d8,{DOUBLEWITHTWODWORDINTREE(0x7c100000,0x00000000)}},
+        {VT_exponent,22,0x3a92d9,{DOUBLEWITHTWODWORDINTREE(0x7c200000,0x00000000)}},
+        {VT_exponent,22,0x3a92da,{DOUBLEWITHTWODWORDINTREE(0x7c300000,0x00000000)}},
+        {VT_exponent,22,0x3a92db,{DOUBLEWITHTWODWORDINTREE(0x7c400000,0x00000000)}},
+        {VT_exponent,22,0x3a92dc,{DOUBLEWITHTWODWORDINTREE(0x7c500000,0x00000000)}},
+        {VT_exponent,22,0x3a92dd,{DOUBLEWITHTWODWORDINTREE(0x7c600000,0x00000000)}},
+        {VT_exponent,22,0x3a92de,{DOUBLEWITHTWODWORDINTREE(0x7c700000,0x00000000)}},
+        {VT_exponent,22,0x3a92df,{DOUBLEWITHTWODWORDINTREE(0x7c800000,0x00000000)}},
+        {VT_exponent,22,0x3a92e0,{DOUBLEWITHTWODWORDINTREE(0x7c900000,0x00000000)}},
+        {VT_exponent,22,0x3a92e1,{DOUBLEWITHTWODWORDINTREE(0x7ca00000,0x00000000)}},
+        {VT_exponent,22,0x3a92e2,{DOUBLEWITHTWODWORDINTREE(0x7cb00000,0x00000000)}},
+        {VT_exponent,22,0x3a92e3,{DOUBLEWITHTWODWORDINTREE(0x7cc00000,0x00000000)}},
+        {VT_exponent,22,0x3a92e4,{DOUBLEWITHTWODWORDINTREE(0x7cd00000,0x00000000)}},
+        {VT_exponent,22,0x3a92e5,{DOUBLEWITHTWODWORDINTREE(0x7ce00000,0x00000000)}},
+        {VT_exponent,22,0x3a92e6,{DOUBLEWITHTWODWORDINTREE(0x7cf00000,0x00000000)}},
+        {VT_exponent,22,0x3a92e7,{DOUBLEWITHTWODWORDINTREE(0x7d000000,0x00000000)}},
+        {VT_exponent,22,0x3a92e8,{DOUBLEWITHTWODWORDINTREE(0x7d100000,0x00000000)}},
+        {VT_exponent,22,0x3a92e9,{DOUBLEWITHTWODWORDINTREE(0x7d200000,0x00000000)}},
+        {VT_exponent,22,0x3a92ea,{DOUBLEWITHTWODWORDINTREE(0x7d300000,0x00000000)}},
+        {VT_exponent,22,0x3a92eb,{DOUBLEWITHTWODWORDINTREE(0x7d400000,0x00000000)}},
+        {VT_exponent,22,0x3a92ec,{DOUBLEWITHTWODWORDINTREE(0x7d500000,0x00000000)}},
+        {VT_exponent,22,0x3a92ed,{DOUBLEWITHTWODWORDINTREE(0x7d600000,0x00000000)}},
+        {VT_exponent,22,0x3a92ee,{DOUBLEWITHTWODWORDINTREE(0x7d700000,0x00000000)}},
+        {VT_exponent,22,0x3a92ef,{DOUBLEWITHTWODWORDINTREE(0x7d800000,0x00000000)}},
+        {VT_exponent,22,0x3a92f0,{DOUBLEWITHTWODWORDINTREE(0x7d900000,0x00000000)}},
+        {VT_exponent,22,0x3a92f1,{DOUBLEWITHTWODWORDINTREE(0x7da00000,0x00000000)}},
+        {VT_exponent,22,0x3a92f2,{DOUBLEWITHTWODWORDINTREE(0x7db00000,0x00000000)}},
+        {VT_exponent,22,0x3a92f3,{DOUBLEWITHTWODWORDINTREE(0x7dc00000,0x00000000)}},
+        {VT_exponent,22,0x3a92f4,{DOUBLEWITHTWODWORDINTREE(0x7dd00000,0x00000000)}},
+        {VT_exponent,22,0x3a92f5,{DOUBLEWITHTWODWORDINTREE(0x7de00000,0x00000000)}},
+        {VT_exponent,22,0x3a92f6,{DOUBLEWITHTWODWORDINTREE(0x7df00000,0x00000000)}},
+        {VT_exponent,22,0x3a92f7,{DOUBLEWITHTWODWORDINTREE(0x7e000000,0x00000000)}},
+        {VT_exponent,22,0x3a92f8,{DOUBLEWITHTWODWORDINTREE(0x7e100000,0x00000000)}},
+        {VT_exponent,22,0x3a92f9,{DOUBLEWITHTWODWORDINTREE(0x7e200000,0x00000000)}},
+        {VT_exponent,22,0x3a92fa,{DOUBLEWITHTWODWORDINTREE(0x7e300000,0x00000000)}},
+        {VT_exponent,22,0x3a92fb,{DOUBLEWITHTWODWORDINTREE(0x7e400000,0x00000000)}},
+        {VT_exponent,22,0x3a92fc,{DOUBLEWITHTWODWORDINTREE(0x7e500000,0x00000000)}},
+        {VT_exponent,22,0x3a92fd,{DOUBLEWITHTWODWORDINTREE(0x7e600000,0x00000000)}},
+        {VT_exponent,22,0x3a92fe,{DOUBLEWITHTWODWORDINTREE(0x7e700000,0x00000000)}},
+        {VT_exponent,22,0x3a92ff,{DOUBLEWITHTWODWORDINTREE(0x7e800000,0x00000000)}},
+        {VT_exponent,22,0x3a95a0,{DOUBLEWITHTWODWORDINTREE(0x7e900000,0x00000000)}},
+        {VT_exponent,22,0x3a95a1,{DOUBLEWITHTWODWORDINTREE(0x7ea00000,0x00000000)}},
+        {VT_exponent,22,0x3a95a2,{DOUBLEWITHTWODWORDINTREE(0x7eb00000,0x00000000)}},
+        {VT_exponent,22,0x3a95a3,{DOUBLEWITHTWODWORDINTREE(0x7ec00000,0x00000000)}},
+        {VT_exponent,22,0x3a95a4,{DOUBLEWITHTWODWORDINTREE(0x7ed00000,0x00000000)}},
+        {VT_exponent,22,0x3a95a5,{DOUBLEWITHTWODWORDINTREE(0x7ee00000,0x00000000)}},
+        {VT_exponent,22,0x3a95a6,{DOUBLEWITHTWODWORDINTREE(0x7ef00000,0x00000000)}},
+        {VT_exponent,22,0x3a95a7,{DOUBLEWITHTWODWORDINTREE(0x7f000000,0x00000000)}},
+        {VT_exponent,22,0x3a95a8,{DOUBLEWITHTWODWORDINTREE(0x7f100000,0x00000000)}},
+        {VT_exponent,22,0x3a95a9,{DOUBLEWITHTWODWORDINTREE(0x7f200000,0x00000000)}},
+        {VT_exponent,22,0x3a95aa,{DOUBLEWITHTWODWORDINTREE(0x7f300000,0x00000000)}},
+        {VT_exponent,22,0x3a95ab,{DOUBLEWITHTWODWORDINTREE(0x7f400000,0x00000000)}},
+        {VT_exponent,22,0x3a95ac,{DOUBLEWITHTWODWORDINTREE(0x7f500000,0x00000000)}},
+        {VT_exponent,22,0x3a95ad,{DOUBLEWITHTWODWORDINTREE(0x7f600000,0x00000000)}},
+        {VT_exponent,22,0x3a95ae,{DOUBLEWITHTWODWORDINTREE(0x7f700000,0x00000000)}},
+        {VT_exponent,22,0x3a95af,{DOUBLEWITHTWODWORDINTREE(0x7f800000,0x00000000)}},
+        {VT_exponent,22,0x3b8fe0,{DOUBLEWITHTWODWORDINTREE(0x7f900000,0x00000000)}},
+        {VT_exponent,22,0x3b8fe1,{DOUBLEWITHTWODWORDINTREE(0x7fa00000,0x00000000)}},
+        {VT_exponent,22,0x3b8fe2,{DOUBLEWITHTWODWORDINTREE(0x7fb00000,0x00000000)}},
+        {VT_exponent,22,0x3b8fe3,{DOUBLEWITHTWODWORDINTREE(0x7fc00000,0x00000000)}},
+        {VT_exponent,21,0x68e90,{DOUBLEWITHTWODWORDINTREE(0x7fd00000,0x00000000)}},
+        {VT_exponent,21,0x68e91,{DOUBLEWITHTWODWORDINTREE(0x7fe00000,0x00000000)}},
+        {VT_exponent,21,0x68e98,{DOUBLEWITHTWODWORDINTREE(0x7ff80000,0x00000000)}},
+}; // End of acofdoe array
diff --git a/src/prc/PRCdouble.h b/src/prc/PRCdouble.h
new file mode 100644
index 0000000..4a3a79d
--- /dev/null
+++ b/src/prc/PRCdouble.h
@@ -0,0 +1,140 @@
+#ifndef __PRC_DOUBLE_H
+#define __PRC_DOUBLE_H
+
+#include <cstdlib>
+#include <cmath>
+#include <cstring>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef BYTE_ORDER
+# undef WORDS_BIG_ENDIAN
+# undef WORDS_LITTLE_ENDIAN
+# if BYTE_ORDER == BIG_ENDIAN
+#  define WORDS_BIG_ENDIAN 1
+# endif
+# if BYTE_ORDER == LITTLE_ENDIAN
+#  define WORDS_LITTLE_ENDIAN 1
+# endif
+#endif   
+
+// from Adobe's documentation
+
+union ieee754_double
+{
+ double d;
+ /* This is the IEEE 754 double-precision format. */
+ struct
+ {
+#ifdef WORDS_BIGENDIAN
+  unsigned int negative:1;
+  unsigned int exponent:11;
+  /* Together these comprise the mantissa.  */
+  unsigned int mantissa0:20;
+  unsigned int mantissa1:32;
+#else
+  /* Together these comprise the mantissa.  */
+  unsigned int mantissa1:32;
+  unsigned int mantissa0:20;
+  unsigned int exponent:11;
+  unsigned int negative:1;
+#endif
+ } ieee;
+};
+
+union ieee754_float
+{
+ float f;
+ /* This is the IEEE 754 float-precision format. */
+ struct {
+#ifdef WORDS_BIGENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:8;
+ unsigned int mantissa:23;
+#else
+ unsigned int mantissa:23;
+ unsigned int exponent:8;
+ unsigned int negative:1;
+#endif
+ } ieee;
+};
+
+enum ValueType {VT_double,VT_exponent};
+
+struct sCodageOfFrequentDoubleOrExponent
+{
+  short Type;
+  short NumberOfBits;
+  unsigned Bits;
+  union {
+    unsigned ul[2];
+    double Value;
+  } u2uod;
+};
+
+#ifdef WORDS_BIGENDIAN
+#       define DOUBLEWITHTWODWORD(upper,lower)  upper,lower
+#       define UPPERPOWER       (0)
+#       define LOWERPOWER       (!UPPERPOWER)
+
+#       define NEXTBYTE(pbd)                            ((pbd)++)
+#       define PREVIOUSBYTE(pbd)                ((pbd)--)
+#       define MOREBYTE(pbd,pbend)              ((pbd)<=(pbend))
+#       define OFFSETBYTE(pbd,offset)   ((pbd)+=offset)
+#       define BEFOREBYTE(pbd)                  ((pbd)-1)
+#       define DIFFPOINTERS(p1,p2)              ((p1)-(p2))
+#       define SEARCHBYTE(pbstart,b,nb) (unsigned char *)memrchr((pbstart),(b),(nb))
+#       define BYTEAT(pb,i)     *((pb)-(i))
+#else
+#       define DOUBLEWITHTWODWORD(upper,lower)  lower,upper
+#       define UPPERPOWER       (1)
+#       define LOWERPOWER       (!UPPERPOWER)
+
+#       define NEXTBYTE(pbd)                            ((pbd)--)
+#       define PREVIOUSBYTE(pbd)                ((pbd)++)
+#       define MOREBYTE(pbd,pbend)              ((pbd)>=(pbend))
+#       define OFFSETBYTE(pbd,offset)   ((pbd)-=offset)
+#       define BEFOREBYTE(pbd)                  ((pbd)+1)
+#       define DIFFPOINTERS(p1,p2)              ((unsigned)((p2)-(p1)))
+#       define SEARCHBYTE(pbstart,b,nb) (unsigned char *)memchr((pbstart),(b),(nb))
+#       define BYTEAT(pb,i)     *((pb)+(i))
+#endif
+
+#define MAXLENGTHFORCOMPRESSEDTYPE      ((22+1+1+4+6*(1+8))+7)/8
+
+#define NEGATIVE(d)     (((union ieee754_double *)&(d))->ieee.negative)
+#define EXPONENT(d)     (((union ieee754_double *)&(d))->ieee.exponent)
+#define MANTISSA0(d)    (((union ieee754_double *)&(d))->ieee.mantissa0)
+#define MANTISSA1(d)    (((union ieee754_double *)&(d))->ieee.mantissa1)
+
+typedef unsigned char PRCbyte;
+typedef unsigned short PRCword;
+typedef unsigned PRCdword;
+
+extern PRCdword stadwZero[2],stadwNegativeZero[2];
+
+#define NUMBEROFELEMENTINACOFDOE   (2077)
+
+#ifdef WORDS_BIGENDIAN
+#       define DOUBLEWITHTWODWORDINTREE(upper,lower)    {upper,lower} 
+#else
+#       define DOUBLEWITHTWODWORDINTREE(upper,lower)    {lower,upper}
+#endif
+extern sCodageOfFrequentDoubleOrExponent acofdoe[NUMBEROFELEMENTINACOFDOE];
+
+struct sCodageOfFrequentDoubleOrExponent* getcofdoe(unsigned,short);
+
+#define STAT_V
+#define STAT_DOUBLE
+
+int stCOFDOECompare(const void*,const void*);
+
+#ifdef WORDS_BIGENDIAN
+#ifndef HAVE_MEMRCHR
+void *memrchr(const void *,int,size_t);
+#endif
+#endif
+
+#endif // __PRC_DOUBLE_H
diff --git a/src/prc/oPRCFile.cc b/src/prc/oPRCFile.cc
new file mode 100644
index 0000000..b090f8a
--- /dev/null
+++ b/src/prc/oPRCFile.cc
@@ -0,0 +1,2461 @@
+/************
+*
+*   This file is part of a tool for producing 3D content in the PRC format.
+*   Copyright (C) 2008  Orest Shardt <shardtor (at) gmail dot com>
+*   with enhancements contributed by Michail Vidiassov.
+*
+*   This program is free software: you can redistribute it and/or modify
+*   it under the terms of the GNU Lesser General Public License as published by
+*   the Free Software Foundation, either version 3 of the License, or
+*   (at your option) any later version.
+*
+*   This program is distributed in the hope that it will be useful,
+*   but WITHOUT ANY WARRANTY; without even the implied warranty of
+*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*   GNU Lesser General Public License for more details.
+*
+*   You should have received a copy of the GNU Lesser General Public License
+*   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*
+*************/
+
+#include "oPRCFile.h"
+#include <time.h>
+#include <sstream>
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+#include <string>
+#include <zlib.h>
+#include <string.h>
+
+#define WriteUnsignedInteger( value ) out << (uint32_t)(value);
+#define WriteInteger( value ) out << (int32_t)(value);
+#define WriteDouble( value ) out << (double)(value);
+#define WriteString( value ) out << (value);
+#define WriteUncompressedUnsignedInteger( value ) writeUncompressedUnsignedInteger(out, (uint32_t)(value));
+#define WriteUncompressedBlock( value, count ) out.write((char *)(value),(count));
+#define SerializeFileStructureUncompressedUniqueId( value ) (value).serializeFileStructureUncompressedUniqueId(out);
+#define SerializeCompressedUniqueId( value ) (value).serializeCompressedUniqueId(out);
+#define SerializeContentPRCBase write(out);
+#define SerializeRgbColor( value ) (value).serializeRgbColor(out);
+#define SerializePicture( value ) (value)->serializePicture(out);
+#define SerializeTextureDefinition( value ) (value)->serializeTextureDefinition(out);
+#define SerializeMarkup( value ) (value)->serializeMarkup(out);
+#define SerializeAnnotationEntity( value ) (value)->serializeAnnotationEntity(out);
+#define SerializeFontKeysSameFont( value ) (value).serializeFontKeysSameFont(out);
+#define SerializeMaterial( value ) (value)->serializeMaterial(out);
+
+#define SerializeUserData UserData(0,0).write(out);
+#define SerializeEmptyContentPRCBase ContentPRCBase(PRC_TYPE_ROOT_PRCBase).serializeContentPRCBase(out);
+#define SerializeCategory1LineStyle( value ) (value)->serializeCategory1LineStyle(out);
+#define SerializeCoordinateSystem( value ) (value)->serializeCoordinateSystem(out);
+#define SerializeRepresentationItem( value ) (value)->serializeRepresentationItem(out);
+#define SerializePartDefinition( value ) (value)->serializePartDefinition(out);
+#define SerializeProductOccurrence( value ) (value)->serializeProductOccurrence(out);
+#define SerializeContextAndBodies( value ) (value)->serializeContextAndBodies(out);
+#define SerializeGeometrySummary( value ) (value)->serializeGeometrySummary(out);
+#define SerializeContextGraphics( value ) (value)->serializeContextGraphics(out);
+#define SerializeStartHeader serializeStartHeader(out);
+#define SerializeUncompressedFile( value ) (value)->serializeUncompressedFile(out);
+#define SerializeUncompressedFiles  serializeUncompressedFiles(out);
+
+#define SerializeModelFileData serializeModelFileData(modelFile_out); modelFile_out.compress();
+#define SerializeUnit( value ) (value).serializeUnit(out);
+
+using std::string;
+using namespace std;
+
+// Map [0,1] to [0,255]
+inline uint8_t byte(double r) 
+{
+  if(r < 0.0) r=0.0;
+  else if(r > 1.0) r=1.0;
+  int a=(int)(256.0*r);
+  if(a == 256) a=255;
+  return a;
+}
+
+void PRCFileStructure::serializeFileStructureGlobals(PRCbitStream &out)
+{
+  // even though this is technically not part of this section,
+  // it is handled here for convenience
+  const uint32_t number_of_schema = 0;
+  WriteUnsignedInteger (number_of_schema)
+
+  WriteUnsignedInteger (PRC_TYPE_ASM_FileStructureGlobals)
+
+  PRCSingleAttribute sa((int32_t)PRCVersion);
+  PRCAttribute a("__PRC_RESERVED_ATTRIBUTE_PRCInternalVersion");
+  a.addKey(sa);
+  ContentPRCBase cb(PRC_TYPE_ROOT_PRCBase);
+  cb.addAttribute(a);
+  cb.serializeContentPRCBase(out);
+  WriteUnsignedInteger (number_of_referenced_file_structures)
+  // SerializeFileStructureInternalGlobalData
+  WriteDouble (tessellation_chord_height_ratio)
+  WriteDouble (tessellation_angle_degree)
+
+  // SerializeMarkupSerializationHelper
+  WriteString (default_font_family_name)
+
+  const uint32_t number_of_fonts = font_keys_of_font.size();
+  WriteUnsignedInteger (number_of_fonts)
+  for (uint32_t i=0;i<number_of_fonts;i++)
+  {
+    SerializeFontKeysSameFont (font_keys_of_font[i])
+  }
+
+  const uint32_t number_of_colors = colors.size();
+  WriteUnsignedInteger (number_of_colors)
+  for (uint32_t i=0;i<number_of_colors;i++)
+      SerializeRgbColor (colors[i])
+
+  const uint32_t number_of_pictures = pictures.size();
+  WriteUnsignedInteger (number_of_pictures)
+  for (uint32_t i=0;i<number_of_pictures;i++)
+     SerializePicture (pictures[i])
+
+  const uint32_t number_of_texture_definitions = texture_definitions.size();
+  WriteUnsignedInteger (number_of_texture_definitions)
+  for (uint32_t i=0;i<number_of_texture_definitions;i++)
+     SerializeTextureDefinition (texture_definitions[i])
+
+  const uint32_t number_of_materials = materials.size();
+  WriteUnsignedInteger (number_of_materials)
+  for (uint32_t i=0;i<number_of_materials;i++)
+     SerializeMaterial (materials[i])
+
+  // number of line patterns hard coded for now
+  const uint32_t number_of_line_patterns = 1;
+  WriteUnsignedInteger (number_of_line_patterns)
+  PRCLinePattern().serializeLinePattern(out);
+
+  const uint32_t number_of_styles = styles.size();
+  WriteUnsignedInteger (number_of_styles)
+  for (uint32_t i=0;i<number_of_styles;i++)
+     SerializeCategory1LineStyle (styles[i])
+
+  const uint32_t number_of_fill_patterns = 0;
+  WriteUnsignedInteger (number_of_fill_patterns)
+
+  const uint32_t number_of_reference_coordinate_systems = reference_coordinate_systems.size();
+  WriteUnsignedInteger (number_of_reference_coordinate_systems)
+  for (uint32_t i=0;i<number_of_reference_coordinate_systems;i++)
+     SerializeCoordinateSystem (reference_coordinate_systems[i])
+
+  SerializeUserData
+}
+
+void PRCFileStructure::serializeFileStructureTree(PRCbitStream &out)
+{
+  WriteUnsignedInteger (PRC_TYPE_ASM_FileStructureTree)
+
+  SerializeEmptyContentPRCBase
+
+  const uint32_t number_of_part_definitions = part_definitions.size();
+  WriteUnsignedInteger (number_of_part_definitions)
+  for (uint32_t i=0;i<number_of_part_definitions;i++)
+    SerializePartDefinition (part_definitions[i])
+	
+  const uint32_t number_of_product_occurrences = product_occurrences.size();
+  WriteUnsignedInteger (number_of_product_occurrences)
+  for (uint32_t i=0;i<number_of_product_occurrences;i++)
+  {
+    product_occurrences[i]->unit_information.unit_from_CAD_file = true;
+    product_occurrences[i]->unit_information.unit = unit;
+    SerializeProductOccurrence (product_occurrences[i])
+  }
+
+  // SerializeFileStructureInternalData
+  WriteUnsignedInteger (PRC_TYPE_ASM_FileStructure)
+  SerializeEmptyContentPRCBase
+  const uint32_t next_available_index = makePRCID();
+  WriteUnsignedInteger (next_available_index)
+  const uint32_t index_product_occurence = number_of_product_occurrences;  // Asymptote (oPRCFile) specific - we write the root product last
+  WriteUnsignedInteger (index_product_occurence)
+
+  SerializeUserData
+}
+
+void PRCFileStructure::serializeFileStructureTessellation(PRCbitStream &out)
+{
+  WriteUnsignedInteger (PRC_TYPE_ASM_FileStructureTessellation)
+
+  SerializeEmptyContentPRCBase
+  const uint32_t number_of_tessellations = tessellations.size();
+  WriteUnsignedInteger (number_of_tessellations)
+  for (uint32_t i=0;i<number_of_tessellations;i++)
+    tessellations[i]->serializeBaseTessData(out);
+
+  SerializeUserData
+}
+
+void PRCFileStructure::serializeFileStructureGeometry(PRCbitStream &out)
+{
+  WriteUnsignedInteger (PRC_TYPE_ASM_FileStructureGeometry)
+
+  SerializeEmptyContentPRCBase
+  const uint32_t number_of_contexts = contexts.size();
+  WriteUnsignedInteger (number_of_contexts)
+  for (uint32_t i=0;i<number_of_contexts;i++)
+    SerializeContextAndBodies (contexts[i])
+
+  SerializeUserData
+}
+
+void PRCFileStructure::serializeFileStructureExtraGeometry(PRCbitStream &out)
+{
+  WriteUnsignedInteger (PRC_TYPE_ASM_FileStructureExtraGeometry)
+
+  SerializeEmptyContentPRCBase
+  const uint32_t number_of_contexts = contexts.size();
+  WriteUnsignedInteger (number_of_contexts)
+  for (uint32_t i=0;i<number_of_contexts;i++)
+  {
+     SerializeGeometrySummary (contexts[i])
+     SerializeContextGraphics (contexts[i])
+  }
+
+  SerializeUserData
+}
+
+void oPRCFile::serializeModelFileData(PRCbitStream &out)
+{
+  // even though this is technically not part of this section,
+  // it is handled here for convenience
+  const uint32_t number_of_schema = 0;
+  WriteUnsignedInteger (number_of_schema)
+  WriteUnsignedInteger (PRC_TYPE_ASM_ModelFile)
+
+  PRCSingleAttribute sa((int32_t)PRCVersion);
+  PRCAttribute a("__PRC_RESERVED_ATTRIBUTE_PRCInternalVersion");
+  a.addKey(sa);
+  ContentPRCBase cb(PRC_TYPE_ROOT_PRCBase,"PRC file");
+  cb.addAttribute(a);
+  cb.serializeContentPRCBase(out);
+
+  SerializeUnit (unit)
+
+  out << (uint32_t)1; // 1 product occurrence
+  //UUID
+  SerializeCompressedUniqueId( fileStructures[0]->file_structure_uuid )
+  // index+1
+  out << (uint32_t)fileStructures[0]->product_occurrences.size();
+  // active
+  out << true;
+  out << (uint32_t)0; // index in model file
+
+  SerializeUserData
+}
+
+void makeFileUUID(PRCUniqueId& UUID)
+{
+  // make a UUID
+  static uint32_t count = 0;
+  ++count;
+  // the minimum requirement on UUIDs is that all must be unique in the file
+  UUID.id0 = 0x33595341; // some constant
+  UUID.id1 = (uint32_t)time(NULL); // the time
+  UUID.id2 = count;
+  UUID.id3 = 0xa5a55a5a; // Something random, not seeded by the time, would be nice. But for now, a constant
+  // maybe add something else to make it more unique
+  // so multiple files can be combined
+  // a hash of some data perhaps?
+}
+
+void makeAppUUID(PRCUniqueId& UUID)
+{
+  UUID.id0 = UUID.id1 = UUID.id2 = UUID.id3 = 0;
+}
+
+void PRCStartHeader::serializeStartHeader(ostream &out) const
+{
+  WriteUncompressedBlock ("PRC",3)
+  WriteUncompressedUnsignedInteger (minimal_version_for_read)
+  WriteUncompressedUnsignedInteger (authoring_version)
+  SerializeFileStructureUncompressedUniqueId( file_structure_uuid );
+  SerializeFileStructureUncompressedUniqueId( application_uuid );
+}
+
+void PRCStartHeader::serializeUncompressedFiles(ostream &out) const
+{
+  const uint32_t number_of_uncompressed_files = uncompressed_files.size();
+  WriteUncompressedUnsignedInteger (number_of_uncompressed_files)
+  for (uint32_t i=0; i<number_of_uncompressed_files; i++)
+    SerializeUncompressedFile (uncompressed_files[i])
+}
+
+uint32_t PRCStartHeader::getStartHeaderSize() const
+{
+  return 3+(2+2*4)*sizeof(uint32_t);
+}
+
+uint32_t PRCStartHeader::getUncompressedFilesSize() const
+{
+  uint32_t size = 0;
+  for(PRCUncompressedFileList::const_iterator it = uncompressed_files.begin(); it != uncompressed_files.end(); it++)
+    size += (*it)->getSize();
+  return size;
+}
+
+void PRCFileStructure::write(ostream &out)
+{
+  // SerializeFileStructureHeader
+  SerializeStartHeader
+  SerializeUncompressedFiles
+  globals_out.write(out);
+  tree_out.write(out);
+  tessellations_out.write(out);
+  geometry_out.write(out);
+  extraGeometry_out.write(out);
+}
+
+#define SerializeFileStructureGlobals serializeFileStructureGlobals(globals_out); globals_out.compress(); sizes[1]=globals_out.getSize();
+#define SerializeFileStructureTree serializeFileStructureTree(tree_out); tree_out.compress(); sizes[2]=tree_out.getSize();
+#define SerializeFileStructureTessellation serializeFileStructureTessellation(tessellations_out); tessellations_out.compress(); sizes[3]=tessellations_out.getSize();
+#define SerializeFileStructureGeometry serializeFileStructureGeometry(geometry_out); geometry_out.compress(); sizes[4]=geometry_out.getSize();
+#define SerializeFileStructureExtraGeometry serializeFileStructureExtraGeometry(extraGeometry_out); extraGeometry_out.compress(); sizes[5]=extraGeometry_out.getSize();
+#define FlushSerialization resetGraphicsAndName();
+void PRCFileStructure::prepare()
+{
+  uint32_t size = 0;
+  size += getStartHeaderSize();
+  size += sizeof(uint32_t);
+  size += getUncompressedFilesSize();
+  sizes[0]=size;
+
+  SerializeFileStructureGlobals
+  FlushSerialization
+
+  SerializeFileStructureTree
+  FlushSerialization
+
+  SerializeFileStructureTessellation
+  FlushSerialization
+
+  SerializeFileStructureGeometry
+  FlushSerialization
+
+  SerializeFileStructureExtraGeometry
+  FlushSerialization
+}
+
+uint32_t PRCFileStructure::getSize()
+{
+  uint32_t size = 0;
+  for(size_t i=0; i<6; i++)
+    size += sizes[i];
+  return size;
+}
+
+
+void PRCFileStructureInformation::write(ostream &out)
+{
+  SerializeFileStructureUncompressedUniqueId( UUID );
+
+  WriteUncompressedUnsignedInteger (reserved)
+  WriteUncompressedUnsignedInteger (number_of_offsets)
+  for(uint32_t i = 0; i < number_of_offsets; ++i)
+  {
+    WriteUncompressedUnsignedInteger (offsets[i])
+  }
+}
+
+uint32_t PRCFileStructureInformation::getSize()
+{
+  return (4+2+number_of_offsets)*sizeof(uint32_t);
+}
+
+void PRCHeader::write(ostream &out)
+{
+  SerializeStartHeader
+  WriteUncompressedUnsignedInteger (number_of_file_structures)
+  for(uint32_t i = 0; i < number_of_file_structures; ++i)
+  {
+    fileStructureInformation[i].write(out);
+  }
+  WriteUncompressedUnsignedInteger (model_file_offset)
+  WriteUncompressedUnsignedInteger (file_size)
+  SerializeUncompressedFiles
+}
+
+uint32_t PRCHeader::getSize()
+{
+  uint32_t size = getStartHeaderSize() + sizeof(uint32_t);
+  for(uint32_t i = 0; i < number_of_file_structures; ++i)
+    size += fileStructureInformation[i].getSize();
+  size += 3*sizeof(uint32_t);
+  size += getUncompressedFilesSize();
+  return size;
+}
+
+void oPRCFile::doGroup(PRCgroup& group)
+{
+    const string& name = group.name;
+
+    PRCProductOccurrence*& product_occurrence        = group.product_occurrence;
+    PRCProductOccurrence*& parent_product_occurrence = group.parent_product_occurrence;
+    PRCPartDefinition*& part_definition              = group.part_definition;
+    PRCPartDefinition*& parent_part_definition       = group.parent_part_definition;
+
+    if(group.options.tess)
+    {
+      if(!group.lines.empty())
+      {
+        for(PRCtesslineMap::const_iterator wit=group.lines.begin(); wit!=group.lines.end(); wit++)
+        {
+          bool same_color = true;
+          const PRCtesslineList& lines = wit->second;
+          const PRCRgbColor &color = lines.front().color;
+          for(PRCtesslineList::const_iterator lit=lines.begin(); lit!=lines.end(); lit++)
+            if(color!=lit->color)
+            {
+              same_color = false;
+              break;
+            }
+          map<PRCVector3d,uint32_t> points;
+          PRC3DWireTess *tess = new PRC3DWireTess();
+          if(!same_color)
+          {
+            tess->is_segment_color = true;
+            tess->is_rgba = false;
+          }
+          for(PRCtesslineList::const_iterator lit=lines.begin(); lit!=lines.end(); lit++)
+          {
+            tess->wire_indexes.push_back(lit->point.size());
+            for(uint32_t i=0; i<lit->point.size(); i++)
+            {
+              map<PRCVector3d,uint32_t>::iterator pPoint = points.find(lit->point[i]);
+              if(pPoint!=points.end())
+                tess->wire_indexes.push_back(pPoint->second);
+              else
+              {
+                const uint32_t point_index = tess->coordinates.size();
+                points.insert(make_pair(lit->point[i],point_index));
+                tess->wire_indexes.push_back(point_index);
+                tess->coordinates.push_back(lit->point[i].x);
+                tess->coordinates.push_back(lit->point[i].y);
+                tess->coordinates.push_back(lit->point[i].z);
+              }
+              if(!same_color && i>0)
+              {
+                tess->rgba_vertices.push_back(byte(lit->color.red));
+                tess->rgba_vertices.push_back(byte(lit->color.green));
+                tess->rgba_vertices.push_back(byte(lit->color.blue));
+              }
+            }
+          }
+          const uint32_t tess_index = add3DWireTess(tess);
+          PRCPolyWire *polyWire = new PRCPolyWire();
+          polyWire->index_tessellation = tess_index;
+          if(same_color)
+            polyWire->index_of_line_style = addColourWidth(RGBAColour(color.red,color.green,color.blue),wit->first);
+          else
+            polyWire->index_of_line_style = addColourWidth(RGBAColour(1,1,1),wit->first);
+          part_definition->addPolyWire(polyWire);
+        }
+      }
+//    make rectangles pairs of triangles in a tesselation
+      if(!group.rectangles.empty())
+      {
+        bool same_color = true;
+        const uint32_t &style = group.rectangles.front().style;
+        for(PRCtessrectangleList::const_iterator rit=group.rectangles.begin(); rit!=group.rectangles.end(); rit++)
+          if(style!=rit->style)
+          {
+            same_color = false;
+            break;
+          }
+        map<PRCVector3d,uint32_t> points;
+        PRC3DTess *tess = new PRC3DTess();
+        tess->crease_angle = group.options.crease_angle;
+        PRCTessFace *tessFace = new PRCTessFace();
+        tessFace->used_entities_flag=PRC_FACETESSDATA_Triangle;
+        uint32_t triangles = 0;
+        for(PRCtessrectangleList::const_iterator rit=group.rectangles.begin(); rit!=group.rectangles.end(); rit++)
+        {
+          const bool degenerate = (rit->vertices[0]==rit->vertices[1]);
+          uint32_t vertex_indices[4];
+          for(size_t i = (degenerate?1:0); i < 4; ++i)
+          {
+            map<PRCVector3d,uint32_t>::const_iterator pPoint = points.find(rit->vertices[i]);
+            if(pPoint!=points.end())
+              vertex_indices[i] =  pPoint->second;
+            else
+            {
+              points.insert(make_pair(rit->vertices[i],(vertex_indices[i] = tess->coordinates.size())));
+              tess->coordinates.push_back(rit->vertices[i].x);
+              tess->coordinates.push_back(rit->vertices[i].y);
+              tess->coordinates.push_back(rit->vertices[i].z);
+            }
+          }
+          if(degenerate)
+          {
+            tess->triangulated_index.push_back(vertex_indices[1]);
+            tess->triangulated_index.push_back(vertex_indices[2]);
+            tess->triangulated_index.push_back(vertex_indices[3]);
+            triangles++;
+            if(!same_color)
+              tessFace->line_attributes.push_back(rit->style);
+          }
+          else
+          {
+            tess->triangulated_index.push_back(vertex_indices[0]);
+            tess->triangulated_index.push_back(vertex_indices[2]);
+            tess->triangulated_index.push_back(vertex_indices[3]);
+            triangles++;
+            if(!same_color)
+              tessFace->line_attributes.push_back(rit->style);
+            tess->triangulated_index.push_back(vertex_indices[3]);
+            tess->triangulated_index.push_back(vertex_indices[1]);
+            tess->triangulated_index.push_back(vertex_indices[0]);
+            triangles++;
+            if(!same_color)
+              tessFace->line_attributes.push_back(rit->style);
+          }
+        }
+        tessFace->sizes_triangulated.push_back(triangles);
+        tess->addTessFace(tessFace);
+        const uint32_t tess_index = add3DTess(tess);
+        PRCPolyBrepModel *polyBrepModel = new PRCPolyBrepModel();
+        polyBrepModel->index_tessellation = tess_index;
+        polyBrepModel->is_closed = group.options.closed;
+        if(same_color)
+          polyBrepModel->index_of_line_style = style;
+        part_definition->addPolyBrepModel(polyBrepModel);
+      }
+    }
+
+    if(!group.quads.empty())
+    {
+      map<PRCVector3d,uint32_t> points;
+      PRC3DTess *tess = new PRC3DTess();
+      tess->crease_angle = group.options.crease_angle;
+      PRCTessFace *tessFace = new PRCTessFace();
+      tessFace->used_entities_flag=PRC_FACETESSDATA_Triangle;
+      uint32_t triangles = 0;
+
+      tessFace->is_rgba = false;
+      for(PRCtessquadList::const_iterator qit=group.quads.begin(); qit!=group.quads.end(); qit++)
+      {
+        const RGBAColour* C = qit->colours;
+        if(C[0].A != 1.0 || C[1].A != 1.0 || C[2].A != 1.0 || C[3].A != 1.0)
+        {
+          tessFace->is_rgba = true;
+          break;
+        }
+      }
+      bool same_colour = true;
+      const RGBAColour& colour = group.quads.front().colours[0];
+      for(PRCtessquadList::const_iterator qit=group.quads.begin(); qit!=group.quads.end(); qit++)
+      {
+        const RGBAColour* C = qit->colours;
+        if(colour!=C[0] || colour!=C[1] || colour!=C[2] || colour!=C[3])
+        {
+          same_colour = false;
+          break;
+        }
+      }
+      
+      for(PRCtessquadList::const_iterator qit=group.quads.begin(); qit!=group.quads.end(); qit++)
+      {
+        const RGBAColour* C = qit->colours;
+        const bool degenerate = (qit->vertices[0]==qit->vertices[1]);
+        uint32_t vertex_indices[4];
+        for(size_t i = (degenerate?1:0); i < 4; ++i)
+        {
+          map<PRCVector3d,uint32_t>::const_iterator pPoint = points.find(qit->vertices[i]);
+          if(pPoint!=points.end())
+            vertex_indices[i] =  pPoint->second;
+          else
+          {
+            points.insert(make_pair(qit->vertices[i],(vertex_indices[i] = tess->coordinates.size())));
+            tess->coordinates.push_back(qit->vertices[i].x);
+            tess->coordinates.push_back(qit->vertices[i].y);
+            tess->coordinates.push_back(qit->vertices[i].z);
+          }
+        }
+        if(degenerate)
+        {
+          tess->triangulated_index.push_back(vertex_indices[1]);
+          tess->triangulated_index.push_back(vertex_indices[2]);
+          tess->triangulated_index.push_back(vertex_indices[3]);
+          triangles++;
+          if(!same_colour)
+          {
+            tessFace->rgba_vertices.push_back(byte(C[1].R));
+            tessFace->rgba_vertices.push_back(byte(C[1].G));
+            tessFace->rgba_vertices.push_back(byte(C[1].B));
+            if(tessFace->is_rgba)
+              tessFace->rgba_vertices.push_back(byte(C[1].A));
+            
+            tessFace->rgba_vertices.push_back(byte(C[2].R));
+            tessFace->rgba_vertices.push_back(byte(C[2].G));
+            tessFace->rgba_vertices.push_back(byte(C[2].B));
+            if(tessFace->is_rgba)
+              tessFace->rgba_vertices.push_back(byte(C[2].A));
+            
+            tessFace->rgba_vertices.push_back(byte(C[3].R));
+            tessFace->rgba_vertices.push_back(byte(C[3].G));
+            tessFace->rgba_vertices.push_back(byte(C[3].B));
+            if(tessFace->is_rgba)
+              tessFace->rgba_vertices.push_back(byte(C[3].A));
+          }
+        }
+        else
+        {
+          tess->triangulated_index.push_back(vertex_indices[0]);
+          tess->triangulated_index.push_back(vertex_indices[2]);
+          tess->triangulated_index.push_back(vertex_indices[3]);
+          triangles++;
+          if(!same_colour)
+          {
+            tessFace->rgba_vertices.push_back(byte(C[0].R));
+            tessFace->rgba_vertices.push_back(byte(C[0].G));
+            tessFace->rgba_vertices.push_back(byte(C[0].B));
+            if(tessFace->is_rgba)
+              tessFace->rgba_vertices.push_back(byte(C[0].A));
+            
+            tessFace->rgba_vertices.push_back(byte(C[2].R));
+            tessFace->rgba_vertices.push_back(byte(C[2].G));
+            tessFace->rgba_vertices.push_back(byte(C[2].B));
+            if(tessFace->is_rgba)
+              tessFace->rgba_vertices.push_back(byte(C[2].A));
+            
+            tessFace->rgba_vertices.push_back(byte(C[3].R));
+            tessFace->rgba_vertices.push_back(byte(C[3].G));
+            tessFace->rgba_vertices.push_back(byte(C[3].B));
+            if(tessFace->is_rgba)
+              tessFace->rgba_vertices.push_back(byte(C[3].A));
+          }
+          tess->triangulated_index.push_back(vertex_indices[3]);
+          tess->triangulated_index.push_back(vertex_indices[1]);
+          tess->triangulated_index.push_back(vertex_indices[0]);
+          triangles++;
+          if(!same_colour)
+          {
+            tessFace->rgba_vertices.push_back(byte(C[3].R));
+            tessFace->rgba_vertices.push_back(byte(C[3].G));
+            tessFace->rgba_vertices.push_back(byte(C[3].B));
+            if(tessFace->is_rgba)
+              tessFace->rgba_vertices.push_back(byte(C[3].A));
+          
+            tessFace->rgba_vertices.push_back(byte(C[1].R));
+            tessFace->rgba_vertices.push_back(byte(C[1].G));
+            tessFace->rgba_vertices.push_back(byte(C[1].B));
+            if(tessFace->is_rgba)
+              tessFace->rgba_vertices.push_back(byte(C[1].A));
+          
+            tessFace->rgba_vertices.push_back(byte(C[0].R));
+            tessFace->rgba_vertices.push_back(byte(C[0].G));
+            tessFace->rgba_vertices.push_back(byte(C[0].B));
+            if(tessFace->is_rgba)
+              tessFace->rgba_vertices.push_back(byte(C[0].A));
+          }
+        }
+      }
+      tessFace->sizes_triangulated.push_back(triangles);
+      tess->addTessFace(tessFace);
+      const uint32_t tess_index = add3DTess(tess);
+      PRCPolyBrepModel *polyBrepModel = new PRCPolyBrepModel();
+      polyBrepModel->index_tessellation = tess_index;
+      polyBrepModel->is_closed = group.options.closed;
+      if(same_colour)
+        polyBrepModel->index_of_line_style = addColour(colour);
+      part_definition->addPolyBrepModel(polyBrepModel);
+    }
+
+    if(!group.points.empty())
+    {
+      for(PRCpointsetMap::const_iterator pit=group.points.begin(); pit!=group.points.end(); pit++)
+      {
+        PRCPointSet *pointset = new PRCPointSet();
+        pointset->index_of_line_style = pit->first;
+        pointset->point = pit->second;
+        part_definition->addPointSet(pointset);
+      }
+    }
+
+    if(!group.pointsets.empty())
+    {
+      for(std::vector<PRCPointSet*>::iterator pit=group.pointsets.begin(); pit!=group.pointsets.end(); pit++)
+      {
+        part_definition->addPointSet(*pit);
+      }
+    }
+
+    if(!group.polymodels.empty())
+    {
+      for(std::vector<PRCPolyBrepModel*>::iterator pit=group.polymodels.begin(); pit!=group.polymodels.end(); pit++)
+      {
+        (*pit)->is_closed = group.options.closed;
+        part_definition->addPolyBrepModel(*pit);
+      }
+    }
+
+    if(!group.polywires.empty())
+    {
+      for(std::vector<PRCPolyWire*>::iterator pit=group.polywires.begin(); pit!=group.polywires.end(); pit++)
+      {
+        part_definition->addPolyWire(*pit);
+      }
+    }
+
+    if(!group.wires.empty())
+    {
+      PRCTopoContext *wireContext = NULL;
+      const uint32_t context_index = getTopoContext(wireContext);
+      for(PRCwireList::iterator wit=group.wires.begin(); wit!=group.wires.end(); wit++)
+      {
+        PRCWireEdge *wireEdge = new PRCWireEdge;
+        wireEdge->curve_3d = wit->curve;
+        PRCSingleWireBody *wireBody = new PRCSingleWireBody;
+        wireBody->setWireEdge(wireEdge);
+        const uint32_t wire_body_index = wireContext->addSingleWireBody(wireBody);
+        PRCWire *wire = new PRCWire();
+        wire->index_of_line_style = wit->style;
+        wire->context_id = context_index;
+        wire->body_id = wire_body_index;
+        if(wit->transform)
+            wire->index_local_coordinate_system = addTransform(wit->transform);
+        part_definition->addWire(wire);
+      }
+    }
+
+    PRCfaceList &faces = group.faces;
+    if(!faces.empty())
+    {
+      bool same_color = true;
+      const uint32_t style = faces.front().style;
+      for(PRCfaceList::const_iterator fit=faces.begin(); fit!=faces.end(); fit++)
+        if(style!=fit->style)
+        {
+          same_color = false;
+          break;
+        }
+      PRCTopoContext *context = NULL;
+      const uint32_t context_index = getTopoContext(context);
+      context->granularity = group.options.granularity;
+   // Acrobat 9 also does the following:
+   // context->tolerance = group.options.granularity;
+   // context->have_smallest_face_thickness = true;
+   // context->smallest_thickness = group.options.granularity;
+      PRCShell *shell = new PRCShell;
+
+      for(PRCfaceList::iterator fit=faces.begin(); fit!=faces.end(); fit++)
+      {
+        if(fit->transform || group.options.do_break ||
+           (fit->transparent && !group.options.no_break))
+        {
+          PRCShell *shell = new PRCShell;
+          shell->addFace(fit->face);
+          PRCConnex *connex = new PRCConnex;
+          connex->addShell(shell);
+          PRCBrepData *body = new PRCBrepData;
+          body->addConnex(connex);
+          const uint32_t body_index = context->addBrepData(body);
+
+          PRCBrepModel *brepmodel = new PRCBrepModel();
+          brepmodel->index_of_line_style = fit->style;
+          brepmodel->context_id = context_index;
+          brepmodel->body_id = body_index;
+          brepmodel->is_closed = group.options.closed;
+
+          brepmodel->index_local_coordinate_system = addTransform(fit->transform);
+
+          part_definition->addBrepModel(brepmodel);
+        }
+        else
+        {
+          if(!same_color)
+            fit->face->index_of_line_style = fit->style;
+          shell->addFace(fit->face);
+        }
+      }
+      if(shell->face.empty())
+      {
+        delete shell;
+      }
+      else
+      {
+        PRCConnex *connex = new PRCConnex;
+        connex->addShell(shell);
+        PRCBrepData *body = new PRCBrepData;
+        body->addConnex(connex);
+        const uint32_t body_index = context->addBrepData(body);
+        PRCBrepModel *brepmodel = new PRCBrepModel();
+        if(same_color)
+          brepmodel->index_of_line_style = style;
+        brepmodel->context_id = context_index;
+        brepmodel->body_id = body_index;
+        brepmodel->is_closed = group.options.closed;
+        part_definition->addBrepModel(brepmodel);
+      }
+    }
+
+    PRCcompfaceList &compfaces = group.compfaces;
+    if(!compfaces.empty())
+    {
+      bool same_color = true;
+      const uint32_t style = compfaces.front().style;
+      for(PRCcompfaceList::const_iterator fit=compfaces.begin(); fit!=compfaces.end(); fit++)
+        if(style!=fit->style)
+        {
+          same_color = false;
+          break;
+        }
+      PRCTopoContext *context = NULL;
+      const uint32_t context_index = getTopoContext(context);
+      PRCCompressedBrepData *body = new PRCCompressedBrepData;
+
+      body->serial_tolerance=group.options.compression;
+      body->brep_data_compressed_tolerance=0.1*group.options.compression;
+
+      for(PRCcompfaceList::const_iterator fit=compfaces.begin(); fit!=compfaces.end(); fit++)
+      {
+        if(group.options.do_break ||
+           (fit->transparent && !group.options.no_break))
+        {
+          PRCCompressedBrepData *body = new PRCCompressedBrepData;
+          body->face.push_back(fit->face);
+
+          body->serial_tolerance=group.options.compression;
+          body->brep_data_compressed_tolerance=2.8346456*
+            group.options.compression;
+          const uint32_t body_index = context->addCompressedBrepData(body);
+
+          PRCBrepModel *brepmodel = new PRCBrepModel();
+          brepmodel->index_of_line_style = fit->style;
+          brepmodel->context_id = context_index;
+          brepmodel->body_id = body_index;
+          brepmodel->is_closed = group.options.closed;
+
+          part_definition->addBrepModel(brepmodel);
+        }
+        else
+        {
+          if(!same_color)
+            fit->face->index_of_line_style = fit->style;
+          body->face.push_back(fit->face);
+        }
+      }
+      if(body->face.empty())
+      {
+        delete body;
+      }
+      else
+      {
+        const uint32_t body_index = context->addCompressedBrepData(body);
+        PRCBrepModel *brepmodel = new PRCBrepModel();
+        if(same_color)
+          brepmodel->index_of_line_style = style;
+        brepmodel->context_id = context_index;
+        brepmodel->body_id = body_index;
+        brepmodel->is_closed = group.options.closed;
+        part_definition->addBrepModel(brepmodel);
+      }
+    }
+
+    // Simplify and reduce to as simple entities as possible
+    // products with named representation items can not be reduced to sets, since 
+    // outside references are already set
+    bool nonamedparts = true;
+    for(PRCRepresentationItemList::const_iterator it=part_definition->representation_item.begin(); it!=part_definition->representation_item.end(); it++)
+    {
+      if (!(*it)->name.empty())
+      {
+        nonamedparts = false;
+        break;
+      }
+    }
+    lastgroupname.clear();
+    lastgroupnames.clear();
+    // First option - reduce to one element in parent
+    if (parent_part_definition && product_occurrence->index_son_occurrence.empty() &&
+        part_definition->representation_item.size() == 1 &&
+        ( name.empty() || part_definition->representation_item.front()->name.empty() ) &&
+        ( !group.transform  || part_definition->representation_item.front()->index_local_coordinate_system==m1) )
+    {
+      if(part_definition->representation_item.front()->name.empty() )
+        part_definition->representation_item.front()->name = name;
+      if(part_definition->representation_item.front()->index_local_coordinate_system==m1)
+        part_definition->representation_item.front()->index_local_coordinate_system = addTransform(group.transform);
+      lastgroupname = calculate_unique_name(part_definition->representation_item.front(), parent_product_occurrence);
+      parent_part_definition->addRepresentationItem(part_definition->representation_item.front());
+      part_definition->representation_item.clear();
+      delete product_occurrence; product_occurrence = NULL;
+      delete part_definition; part_definition = NULL;
+    }
+    // Second option - reduce to a set
+    else if (parent_part_definition && product_occurrence->index_son_occurrence.empty() &&
+      !part_definition->representation_item.empty() &&
+      !group.options.do_break && nonamedparts)
+    {
+      PRCSet *set = new PRCSet(name);
+      set->index_local_coordinate_system = addTransform(group.transform);
+      lastgroupname = calculate_unique_name(set, parent_product_occurrence);
+      for(PRCRepresentationItemList::iterator it=part_definition->representation_item.begin(); it!=part_definition->representation_item.end(); it++)
+      {
+        lastgroupnames.push_back(calculate_unique_name(*it, parent_product_occurrence));
+        set->addRepresentationItem(*it);
+      }
+      part_definition->representation_item.clear();
+      parent_part_definition->addSet(set);
+      delete product_occurrence; product_occurrence = NULL;
+      delete part_definition; part_definition = NULL;
+    }
+    // Third option - create product
+    else if ( !product_occurrence->index_son_occurrence.empty() || !part_definition->representation_item.empty())
+    {
+      // if everything is enclosed in one group - drop the root group
+      if (parent_product_occurrence == NULL && group.transform == NULL &&
+          part_definition->representation_item.empty() && product_occurrence->index_son_occurrence.size()==1) {
+        delete part_definition; part_definition = NULL;
+        delete product_occurrence; product_occurrence = NULL;
+      }
+      else
+      {
+        lastgroupname = calculate_unique_name(product_occurrence, NULL);
+        if (part_definition->representation_item.empty()) {
+          delete part_definition; part_definition = NULL;
+        }
+        else
+        {
+          for(PRCRepresentationItemList::const_iterator it=part_definition->representation_item.begin(); it!=part_definition->representation_item.end(); it++)
+            if ((*it)->name.empty())
+              lastgroupnames.push_back(calculate_unique_name(*it, product_occurrence));
+          product_occurrence->index_part = addPartDefinition(part_definition);
+        }
+        if (group.transform) {
+          product_occurrence->location = group.transform;
+          group.transform = NULL;
+        }
+        if (parent_product_occurrence) {
+          parent_product_occurrence->index_son_occurrence.push_back(addProductOccurrence(product_occurrence));
+        }
+        else {
+          addProductOccurrence(product_occurrence);
+        }
+      }
+    }
+    // Last case - absolutely nothing to do
+    else
+    {
+      delete product_occurrence; product_occurrence = NULL;
+      delete part_definition; part_definition = NULL;
+    }
+
+}
+
+std::string oPRCFile::calculate_unique_name(const ContentPRCBase *prc_entity,const ContentPRCBase *prc_occurence)
+{
+  std::stringstream ss (std::stringstream::in | std::stringstream::out);
+  uint8_t *serialization_buffer = NULL;
+  PRCbitStream serialization(serialization_buffer,0u);
+  const PRCFileStructure *pfile_structure = fileStructures[0];
+  const PRCUniqueId& uuid = pfile_structure->file_structure_uuid;
+// ConvertUniqueIdentifierToString (prc_entity)
+// SerializeCompressedUniqueId (file_structure)
+  serialization << uuid.id0 << uuid.id1 << uuid.id2 << uuid.id3;
+// WriteUnsignedInteger (type)
+  serialization << prc_entity->getType();
+// WriteUnsignedInteger (unique_identifier)
+  serialization << prc_entity->getPRCID();
+  if (prc_occurence)
+  {
+// serialization_buffer = Flush serialization (serialization) 
+  {
+    const uint32_t size_serialization = serialization.getSize();
+    while(size_serialization == serialization.getSize())
+      serialization << false;
+  }
+// ConvertUniqueIdentifierToString (prc_occurrence_unique_id)
+// SerializeCompressedUniqueId (file_structure)
+    serialization << uuid.id0 << uuid.id1 << uuid.id2 << uuid.id3;
+// WriteUnsignedInteger (type)
+    serialization << (uint32_t)PRC_TYPE_ASM_ProductOccurence;
+// WriteUnsignedInteger (unique_identifier)
+    serialization << prc_occurence->getPRCID();
+  }
+  ss << (prc_entity->name.empty()?"node":prc_entity->name.c_str()) << '.';
+  const uint32_t size_serialization = serialization.getSize();
+  for(size_t j=0; j<size_serialization; j++)
+    ss << hex << setfill('0') << setw(2) << (uint32_t)(serialization_buffer[j]);
+  free(serialization_buffer);
+
+  return ss.str();
+}
+
+bool oPRCFile::finish()
+{
+  if(groups.size()!=1) {
+    fputs("begingroup without matching endgroup",stderr);
+    exit(1);
+  }
+  doGroup(groups.top());
+
+  // write each section's bit data
+  fileStructures[0]->prepare();
+  SerializeModelFileData
+
+  // create the header
+
+  // fill out enough info so that sizes can be computed correctly
+  header.number_of_file_structures = number_of_file_structures;
+  header.fileStructureInformation = new PRCFileStructureInformation[number_of_file_structures];
+  for(uint32_t i = 0; i < number_of_file_structures; ++i)
+  {
+    header.fileStructureInformation[i].UUID = fileStructures[i]->file_structure_uuid;
+    header.fileStructureInformation[i].reserved = 0;
+    header.fileStructureInformation[i].number_of_offsets = 6;
+    header.fileStructureInformation[i].offsets = new uint32_t[6];
+  }
+
+  header.minimal_version_for_read = PRCVersion;
+  header.authoring_version = PRCVersion;
+  makeFileUUID(header.file_structure_uuid);
+  makeAppUUID(header.application_uuid);
+
+  header.file_size = getSize();
+  header.model_file_offset = header.file_size - modelFile_out.getSize();
+
+  uint32_t currentOffset = header.getSize();
+
+  for(uint32_t i = 0; i < number_of_file_structures; ++i)
+  {
+    for(size_t j=0; j<6; j++)
+    {
+      header.fileStructureInformation[i].offsets[j] = currentOffset;
+      currentOffset += fileStructures[i]->sizes[j];
+    }
+  }
+
+  // write the data
+  header.write(output);
+
+  for(uint32_t i = 0; i < number_of_file_structures; ++i)
+  {
+    fileStructures[i]->write(output);
+  }
+
+  modelFile_out.write(output);
+  output.flush();
+
+  for(uint32_t i = 0; i < number_of_file_structures; ++i)
+    delete[] header.fileStructureInformation[i].offsets;
+  delete[] header.fileStructureInformation;
+
+  return true;
+}
+
+uint32_t oPRCFile::getSize()
+{
+  uint32_t size = header.getSize();
+
+  for(uint32_t i = 0; i < number_of_file_structures; ++i)
+  {
+    size += fileStructures[i]->getSize();
+  }
+
+  size += modelFile_out.getSize();
+  return size;
+}
+
+uint32_t PRCFileStructure::addPicture(EPRCPictureDataFormat format, uint32_t size, const uint8_t *p, uint32_t width, uint32_t height, string name)
+{
+  uint8_t *data = NULL;
+  if(size==0 || p==NULL)
+  { cerr << "image not set" << endl; return m1; }
+  if(format==KEPRCPicture_PNG || format==KEPRCPicture_JPG)
+  {
+    width = 0; // width and height are ignored for JPG and PNG pictures - but let us keep things clean
+    height = 0;
+    data = new uint8_t[size];
+    memcpy(data, p, size);
+  }
+  else
+  {
+    uint32_t components=0;
+    switch(format)
+    {
+      case KEPRCPicture_BITMAP_RGB_BYTE:
+        components = 3; break;
+      case KEPRCPicture_BITMAP_RGBA_BYTE:
+        components = 4; break;
+      case KEPRCPicture_BITMAP_GREY_BYTE:
+        components = 1; break;
+      case KEPRCPicture_BITMAP_GREYA_BYTE:
+        components = 2; break;
+      default:
+      { cerr << "unknown picture format" << endl; return m1; }
+    }
+    if(width==0 || height==0)
+    { cerr << "width or height parameter not set" << endl; return m1; }
+    if (size < width*height*components)
+    { cerr << "image too small" << endl; return m1; }
+    {
+      uint32_t compressedDataSize = 0;
+      const int CHUNK= 1024; // is this reasonable?
+      
+      z_stream strm;
+      strm.zalloc = Z_NULL;
+      strm.zfree = Z_NULL;
+      strm.opaque = Z_NULL;
+      if(deflateInit(&strm,Z_DEFAULT_COMPRESSION) != Z_OK)
+      { cerr << "Compression initialization failed" << endl; return m1; }
+      unsigned int sizeAvailable = deflateBound(&strm,size);
+      uint8_t *compressedData = (uint8_t*) malloc(sizeAvailable);
+      strm.avail_in = size;
+      strm.next_in = (unsigned char*)p;
+      strm.next_out = (unsigned char*)compressedData;
+      strm.avail_out = sizeAvailable;
+      
+      int code;
+      unsigned int chunks = 0;
+      while((code = deflate(&strm,Z_FINISH)) == Z_OK)
+      {
+        ++chunks;
+        // strm.avail_out should be 0 if we got Z_OK
+        compressedDataSize = sizeAvailable - strm.avail_out;
+        compressedData = (uint8_t*) realloc(compressedData,CHUNK*chunks);
+        strm.next_out = (Bytef*)(compressedData + compressedDataSize);
+        strm.avail_out += CHUNK;
+        sizeAvailable += CHUNK;
+      }
+      compressedDataSize = sizeAvailable-strm.avail_out;
+      
+      if(code != Z_STREAM_END)
+      {
+        deflateEnd(&strm);
+        free(compressedData);
+        { cerr << "Compression error" << endl; return m1; }
+      }
+      
+      deflateEnd(&strm);
+      size = compressedDataSize;
+      data = new uint8_t[compressedDataSize];
+      memcpy(data, compressedData, compressedDataSize);
+      free(compressedData);
+    }
+  }
+  
+  uint32_t uncompressed_file_index = m1;
+  {
+    PRCUncompressedFile* uncompressed_file = new PRCUncompressedFile(size, data);
+    uncompressed_file_index = addUncompressedFileUnique(uncompressed_file);
+    delete[] data;
+  }
+  uint32_t picture_index = m1;
+  {
+    PRCPicture* picture = new PRCPicture(name);
+    picture->format = format;
+    picture->uncompressed_file_index = uncompressed_file_index;
+    picture->pixel_width = width;
+    picture->pixel_height = height;
+    picture_index = addPictureUnique(picture);
+  }
+  return picture_index;
+}
+
+uint32_t oPRCFile::addColour(const RGBAColour &colour)
+{
+  PRCcolourMap::const_iterator pColour = colourMap.find(colour);
+  if(pColour!=colourMap.end())
+    return pColour->second;
+  const uint32_t color_index = addRgbColorUnique(colour.R, colour.G, colour.B);
+  PRCStyle *style = new PRCStyle();
+  style->line_width = 1.0;
+  style->is_vpicture = false;
+  style->line_pattern_vpicture_index = 0;
+  style->is_material = false;
+  style->color_material_index = color_index;
+  style->is_transparency_defined = (colour.A < 1.0);
+  style->transparency = (uint8_t)(colour.A * 256);
+  style->additional = 0;
+  const uint32_t style_index = addStyle(style);
+  colourMap.insert(make_pair(colour,style_index));
+  return style_index;
+}
+
+uint32_t oPRCFile::addColourWidth(const RGBAColour &colour, double width)
+{
+  const RGBAColourWidth colourwidth(colour.R, colour.G, colour.B, colour.A, width);
+  PRCcolourwidthMap::const_iterator pColour = colourwidthMap.find(colourwidth);
+  if(pColour!=colourwidthMap.end())
+    return pColour->second;
+  const uint32_t color_index = addRgbColorUnique(colour.R, colour.G, colour.B);
+  PRCStyle *style = new PRCStyle();
+  style->line_width = width;
+  style->is_vpicture = false;
+  style->line_pattern_vpicture_index = 0;
+  style->is_material = false;
+  style->color_material_index = color_index;
+  style->is_transparency_defined = (colour.A < 1.0);
+  style->transparency = (uint8_t)(colour.A * 256);
+  style->additional = 0;
+  const uint32_t style_index = addStyle(style);
+  colourwidthMap.insert(make_pair(colourwidth,style_index));
+  return style_index;
+}
+
+uint32_t oPRCFile::addTransform(PRCGeneralTransformation3d*& transform)
+{
+  if(!transform)
+    return m1;
+  PRCtransformMap::const_iterator pTransform = transformMap.find(*transform);
+  if(pTransform!=transformMap.end())
+    return pTransform->second;
+  PRCCoordinateSystem *coordinateSystem = new PRCCoordinateSystem();
+  bool transform_replaced = false;
+  if(                            transform->M(0,1)==0 && transform->M(0,2)==0 &&
+      transform->M(1,0)==0 &&                            transform->M(1,2)==0 &&
+      transform->M(2,0)==0 && transform->M(2,1)==0 &&
+      transform->M(3,0)==0 && transform->M(3,1)==0 && transform->M(3,2)==0 && transform->M(3,3)==1 )
+  {
+    transform_replaced = true;
+    PRCCartesianTransformation3d *carttransform = new PRCCartesianTransformation3d;
+//  if(transform->M(0,3)==0 && transform->M(1,3)==0 && transform->M(1,3)==0 &&
+//     transform->M(0,0)==1 && transform->M(1,1)==1 && transform->M(2,2)==1 )
+//    carttransform->behaviour = PRC_TRANSFORMATION_Identity;
+    if(transform->M(0,3)!=0 || transform->M(1,3)!=0 || transform->M(2,3)!=0)
+    {
+      carttransform->behaviour |= PRC_TRANSFORMATION_Translate;
+      carttransform->origin.Set(transform->M(0,3),transform->M(1,3),transform->M(2,3));
+    }
+    if(transform->M(0,0)!=transform->M(1,1) || transform->M(0,0)!=transform->M(2,2))
+    {
+      carttransform->behaviour |= PRC_TRANSFORMATION_NonUniformScale;
+      carttransform->scale.Set(transform->M(0,0),transform->M(1,1),transform->M(2,2));
+    }
+    else
+      if(transform->M(0,0)!=1)
+      {
+        carttransform->behaviour |= PRC_TRANSFORMATION_Scale;
+        carttransform->uniform_scale=transform->M(0,0);
+      }
+    coordinateSystem->axis_set = carttransform;
+  }
+  else
+    coordinateSystem->axis_set = transform;
+
+  const uint32_t coordinate_system_index = fileStructures[0]->addCoordinateSystem(coordinateSystem);
+  transformMap.insert(make_pair(*transform,coordinate_system_index));
+  if(transform_replaced)
+    delete transform;
+  transform = NULL;
+  return coordinate_system_index;
+}
+
+uint32_t oPRCFile::addTransform(const double* t)
+{
+  if(!t)
+    return m1;
+  PRCGeneralTransformation3d* transform = new PRCGeneralTransformation3d(t);
+  return addTransform(transform);
+}
+
+uint32_t oPRCFile::addTransform(const double origin[3], const double x_axis[3], const double y_axis[3], double scale)
+{
+  PRCCartesianTransformation3d* transform = new PRCCartesianTransformation3d(origin, x_axis, y_axis, scale);
+  if(transform->behaviour==PRC_TRANSFORMATION_Identity)
+    return m1;
+  PRCCoordinateSystem *coordinateSystem = new PRCCoordinateSystem();
+  coordinateSystem->axis_set = transform;
+  const uint32_t coordinate_system_index = fileStructures[0]->addCoordinateSystem(coordinateSystem);
+  return coordinate_system_index;
+}
+
+uint32_t oPRCFile::addMaterial(const PRCmaterial& m)
+{
+  PRCmaterialMap::const_iterator pMaterial = materialMap.find(m);
+  if(pMaterial!=materialMap.end())
+    return pMaterial->second;
+
+  uint32_t material_index = m1;
+  {
+    PRCMaterialGeneric *materialGeneric = new PRCMaterialGeneric;
+    materialGeneric->ambient  = addRgbColorUnique(m.ambient.R,  m.ambient.G,  m.ambient.B);
+    materialGeneric->diffuse  = addRgbColorUnique(m.diffuse.R,  m.diffuse.G,  m.diffuse.B);
+    materialGeneric->emissive = addRgbColorUnique(m.emissive.R, m.emissive.G, m.emissive.B);
+    materialGeneric->specular = addRgbColorUnique(m.specular.R, m.specular.G, m.specular.B);
+    materialGeneric->shininess = m.shininess;
+    materialGeneric->ambient_alpha  = m.ambient.A;
+    materialGeneric->diffuse_alpha  = m.diffuse.A;
+    materialGeneric->emissive_alpha = m.emissive.A;
+    materialGeneric->specular_alpha = m.specular.A;
+    material_index = addMaterialGenericUnique(materialGeneric);
+  }
+
+  uint32_t style_index = m1;
+  {
+    PRCStyle *style = new PRCStyle;
+    style->line_width = m.width;
+    style->is_vpicture = false;
+    style->line_pattern_vpicture_index = 0;
+    style->is_material = true;
+    style->is_transparency_defined = (m.alpha < 1.0);
+    style->transparency = (uint8_t)(m.alpha * 256);
+    style->additional = 0;
+    style->color_material_index = material_index;
+    style_index = addStyleUnique(style);
+  }
+  materialMap.insert(make_pair(m,style_index));
+  return style_index;
+}
+
+uint32_t oPRCFile::addTexturedMaterial(const PRCmaterial& m, uint32_t n, const PRCtexture* const tt[])
+{
+  uint32_t material_generic_index = m1;
+  {
+    PRCMaterialGeneric *materialGeneric = new PRCMaterialGeneric;
+    materialGeneric->ambient  = addRgbColorUnique(m.ambient.R,  m.ambient.G,  m.ambient.B);
+    materialGeneric->diffuse  = addRgbColorUnique(m.diffuse.R,  m.diffuse.G,  m.diffuse.B);
+    materialGeneric->emissive = addRgbColorUnique(m.emissive.R, m.emissive.G, m.emissive.B);
+    materialGeneric->specular = addRgbColorUnique(m.specular.R, m.specular.G, m.specular.B);
+    materialGeneric->shininess = m.shininess;
+    materialGeneric->ambient_alpha  = m.ambient.A;
+    materialGeneric->diffuse_alpha  = m.diffuse.A;
+    materialGeneric->emissive_alpha = m.emissive.A;
+    materialGeneric->specular_alpha = m.specular.A;
+    material_generic_index = addMaterialGenericUnique(materialGeneric);
+  }
+
+  uint32_t color_material_index = material_generic_index;
+
+  uint32_t texture_application_index = m1;
+  for (uint32_t i=n; i>0; i--) {
+    const PRCtexture* t = tt[i-1];
+    if (t == NULL) {
+      continue;
+    }
+    const uint32_t picture_index = addPicture(t->format, t->size, t->data, t->height, t->width);
+    
+    uint32_t texture_definition_index = m1;
+    {
+      PRCTextureDefinition *textureDefinition = new PRCTextureDefinition;
+      textureDefinition->picture_index = picture_index;
+      textureDefinition->texture_mapping_attribute = t->mapping;
+      textureDefinition->texture_mapping_attribute_components = t->components;
+      textureDefinition->texture_function = t->function;
+      textureDefinition->texture_wrapping_mode_S = t->wrapping_mode_S;
+      textureDefinition->texture_wrapping_mode_T = t->wrapping_mode_T;
+      texture_definition_index = addTextureDefinitionUnique(textureDefinition);
+    }
+    {
+      PRCTextureApplication *textureApplication = new PRCTextureApplication;
+      textureApplication->material_generic_index=material_generic_index;
+      textureApplication->texture_definition_index=texture_definition_index;
+      textureApplication->next_texture_index = texture_application_index;
+      texture_application_index = addTextureApplicationUnique(textureApplication);
+    }
+    color_material_index = texture_application_index;
+  }
+
+  uint32_t style_index = m1;
+  {
+    PRCStyle *style = new PRCStyle;
+    style->line_width = 0.0;
+    style->is_vpicture = false;
+    style->line_pattern_vpicture_index = 0;
+    style->is_material = true;
+    style->is_transparency_defined = (m.alpha < 1.0);
+    style->transparency = (uint8_t)(m.alpha * 256);
+    style->additional = 0;
+    style->color_material_index = color_material_index;
+    style_index = addStyleUnique(style);
+  }
+  return style_index;
+}
+
+bool isid(const double* t)
+{
+  return(
+         t[0]==1 && t[4]==0 && t[ 8]==0 && t[12]==0 &&
+         t[1]==0 && t[5]==1 && t[ 9]==0 && t[13]==0 &&
+         t[2]==0 && t[6]==0 && t[10]==1 && t[14]==0 &&
+         t[3]==0 && t[7]==0 && t[11]==0 && t[15]==1 );
+}
+
+
+void oPRCFile::begingroup(const char *name, const PRCoptions *options,
+                          const double* t)
+{
+  const PRCgroup &parent_group = groups.top();
+  groups.push(PRCgroup());
+  PRCgroup &group = groups.top();
+  group.name=name;
+  if(options) group.options=*options;
+  if(t&&!isid(t))
+    group.transform = new PRCGeneralTransformation3d(t);
+  group.product_occurrence = new PRCProductOccurrence(name);
+  group.parent_product_occurrence = parent_group.product_occurrence;
+  group.part_definition = new PRCPartDefinition;
+  group.parent_part_definition = parent_group.part_definition;
+}
+
+void oPRCFile::endgroup()
+{
+  if(groups.size()<2) {
+    fputs("begingroup without matching endgroup",stderr);
+    exit(1);
+  }
+  
+  doGroup(groups.top());
+  groups.pop();
+
+// std::cout << lastgroupname << std::endl;
+// for(std::vector<std::string>::const_iterator it=lastgroupnames.begin(); it!=lastgroupnames.end(); it++)
+//   std::cout << " " << *it << std::endl;
+
+}
+
+PRCgroup& oPRCFile::findGroup()
+{
+  return groups.top();
+}
+
+#define ADDWIRE(curvtype)                                 \
+  PRCgroup &group = findGroup();                          \
+  group.wires.push_back(PRCwire());                       \
+  PRCwire &wire = group.wires.back();                     \
+  curvtype *curve = new curvtype;                         \
+  wire.curve = curve;                                     \
+  wire.style = addColour(c);
+
+#define ADDFACE(surftype)                                 \
+  PRCgroup &group = findGroup();                          \
+  group.faces.push_back(PRCface());                       \
+  PRCface& face = group.faces.back();                     \
+  surftype *surface = new surftype;                       \
+  face.face = new PRCFace;                                \
+  face.face->base_surface = surface;                      \
+  face.transparent = m.alpha < 1.0;                       \
+  face.style = addMaterial(m);
+
+#define ADDCOMPFACE                                       \
+  PRCgroup &group = findGroup();                          \
+  group.compfaces.push_back(PRCcompface());               \
+  PRCcompface& face = group.compfaces.back();             \
+  PRCCompressedFace *compface = new PRCCompressedFace;    \
+  face.face = compface;                                   \
+  face.transparent = m.alpha < 1.0;                       \
+  face.style = addMaterial(m);
+
+void oPRCFile::addPoint(const double P[3], const RGBAColour &c, double w)
+{
+  PRCgroup &group = findGroup();
+  group.points[addColourWidth(c,w)].push_back(PRCVector3d(P[0],P[1],P[2]));
+}
+
+void oPRCFile::addPoint(double x, double y, double z, const RGBAColour &c, double w)
+{
+  PRCgroup &group = findGroup();
+  group.points[addColourWidth(c,w)].push_back(PRCVector3d(x,y,z));
+}
+
+
+void oPRCFile::addPoints(uint32_t n, const double P[][3], const RGBAColour &c, double w)
+{
+  if(n==0 || P==NULL)
+     return;
+  PRCgroup &group = findGroup();
+  PRCPointSet *pointset = new PRCPointSet();
+  group.pointsets.push_back(pointset);
+  pointset->index_of_line_style = addColourWidth(c,w);
+  pointset->point.reserve(n);
+  for(uint32_t i=0; i<n; i++)
+    pointset->point.push_back(PRCVector3d(P[i][0],P[i][1],P[i][2]));
+}
+
+void oPRCFile::addPoints(uint32_t n, const double P[][3], uint32_t style_index)
+{
+  if(n==0 || P==NULL)
+    return;
+  PRCgroup &group = findGroup();
+  PRCPointSet *pointset = new PRCPointSet();
+  group.pointsets.push_back(pointset);
+  pointset->index_of_line_style = style_index;
+  pointset->point.reserve(n);
+  for(uint32_t i=0; i<n; i++)
+    pointset->point.push_back(PRCVector3d(P[i][0],P[i][1],P[i][2]));
+}
+
+void oPRCFile::useMesh(uint32_t tess_index, uint32_t style_index, const double origin[3], const double x_axis[3], const double y_axis[3], double scale)
+{
+  PRCgroup &group = findGroup();
+  PRCPolyBrepModel *polyBrepModel = new PRCPolyBrepModel();
+  polyBrepModel->index_local_coordinate_system = addTransform(origin, x_axis, y_axis, scale);
+  polyBrepModel->index_tessellation = tess_index;
+  polyBrepModel->is_closed = group.options.closed;
+  polyBrepModel->index_of_line_style = style_index;
+  group.polymodels.push_back(polyBrepModel);
+}
+
+void oPRCFile::useMesh(uint32_t tess_index, uint32_t style_index, const double* t)
+{
+  PRCgroup &group = findGroup();
+  PRCPolyBrepModel *polyBrepModel = new PRCPolyBrepModel();
+  polyBrepModel->index_local_coordinate_system = addTransform(t);
+  polyBrepModel->index_tessellation = tess_index;
+  polyBrepModel->is_closed = group.options.closed;
+  polyBrepModel->index_of_line_style = style_index;
+  group.polymodels.push_back(polyBrepModel);
+}
+
+void oPRCFile::useLines(uint32_t tess_index, uint32_t style_index, const double origin[3], const double x_axis[3], const double y_axis[3], double scale)
+{
+  PRCgroup &group = findGroup();
+  PRCPolyWire *polyWire = new PRCPolyWire();
+  polyWire->index_local_coordinate_system = addTransform(origin, x_axis, y_axis, scale);
+  polyWire->index_tessellation = tess_index;
+  polyWire->index_of_line_style = style_index;
+  group.polywires.push_back(polyWire);
+}
+
+void oPRCFile::useLines(uint32_t tess_index, uint32_t style_index, const double* t)
+{
+  PRCgroup &group = findGroup();
+  PRCPolyWire *polyWire = new PRCPolyWire();
+  polyWire->index_local_coordinate_system = addTransform(t);
+  polyWire->index_tessellation = tess_index;
+  polyWire->index_of_line_style = style_index;
+  group.polywires.push_back(polyWire);
+}
+
+void oPRCFile::addTriangles(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[][3], const PRCmaterial& m,
+ uint32_t nN, const double N[][3],   const uint32_t NI[][3],
+ uint32_t nT, const double T[][2],   const uint32_t TI[][3],
+ uint32_t nC, const RGBAColour C[],  const uint32_t CI[][3],
+ uint32_t nM, const PRCmaterial M[], const uint32_t MI[], double ca)
+{
+  if(nP==0 || P==NULL || nI==0 || PI==NULL)
+     return;
+  const uint32_t tess_index = createTriangleMesh(nP, P, nI, PI, m, nN, N, NI, nT, T, TI, nC, C, CI, nM, M, MI, ca);
+  useMesh(tess_index,m1);
+}
+
+uint32_t oPRCFile::createTriangleMesh(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[][3], const uint32_t style_index,
+ uint32_t nN, const double N[][3],  const uint32_t NI[][3],
+ uint32_t nT, const double T[][2],  const uint32_t TI[][3],
+ uint32_t nC, const RGBAColour C[], const uint32_t CI[][3],
+ uint32_t nS, const uint32_t S[],   const uint32_t SI[], double ca)
+{
+  if(nP==0 || P==NULL || nI==0 || PI==NULL)
+     return m1;
+
+  const bool triangle_color = (nS != 0 && S != NULL && SI != NULL);
+  const bool vertex_color   = (nC != 0 && C != NULL && CI != NULL);
+  const bool has_normals    = (nN != 0 && N != NULL && NI != NULL);
+  const bool textured       = (nT != 0 && T != NULL && TI != NULL);
+
+  PRC3DTess *tess = new PRC3DTess();
+  PRCTessFace *tessFace = new PRCTessFace();
+  tessFace->used_entities_flag = textured ? PRC_FACETESSDATA_TriangleTextured : PRC_FACETESSDATA_Triangle;
+  tessFace->number_of_texture_coordinate_indexes = textured ? 1 : 0;
+  tess->coordinates.reserve(3*nP);
+  for(uint32_t i=0; i<nP; i++)
+  {
+    tess->coordinates.push_back(P[i][0]);
+    tess->coordinates.push_back(P[i][1]);
+    tess->coordinates.push_back(P[i][2]);
+  }
+  if(has_normals)
+  {
+    tess->normal_coordinate.reserve(3*nN);
+  for(uint32_t i=0; i<nN; i++)
+  {
+    tess->normal_coordinate.push_back(N[i][0]);
+    tess->normal_coordinate.push_back(N[i][1]);
+    tess->normal_coordinate.push_back(N[i][2]);
+  }
+  }
+  else
+    tess->crease_angle = ca;
+  if(textured)
+  {
+    tess->texture_coordinate.reserve(2*nT);
+  for(uint32_t i=0; i<nT; i++)
+  {
+    tess->texture_coordinate.push_back(T[i][0]);
+    tess->texture_coordinate.push_back(T[i][1]);
+  }
+  }
+  tess->triangulated_index.reserve(3*nI+(has_normals?3:0)*nI+(textured?3:0)*nI);
+  for(uint32_t i=0; i<nI; i++)
+  {
+    if(has_normals)
+    tess->triangulated_index.push_back(3*NI[i][0]);
+    if(textured)
+    tess->triangulated_index.push_back(2*TI[i][0]);
+    tess->triangulated_index.push_back(3*PI[i][0]);
+    if(has_normals)
+    tess->triangulated_index.push_back(3*NI[i][1]);
+    if(textured)
+    tess->triangulated_index.push_back(2*TI[i][1]);
+    tess->triangulated_index.push_back(3*PI[i][1]);
+    if(has_normals)
+    tess->triangulated_index.push_back(3*NI[i][2]);
+    if(textured)
+    tess->triangulated_index.push_back(2*TI[i][2]);
+    tess->triangulated_index.push_back(3*PI[i][2]);
+  }
+  tessFace->sizes_triangulated.push_back(nI);
+  if(triangle_color)
+  {
+    tessFace->line_attributes.reserve(nI);
+    for(uint32_t i=0; i<nI; i++)
+       tessFace->line_attributes.push_back(SI[i]);
+  }
+  else if (style_index != m1 )
+  {
+      tessFace->line_attributes.push_back(style_index);
+  }
+  if(vertex_color)
+  {
+    tessFace->is_rgba=false;
+    for(uint32_t i=0; i<nI; i++)
+      if(1.0 != C[CI[i][0]].A || 1.0 != C[CI[i][1]].A || 1.0 != C[CI[i][2]].A)
+      {
+         tessFace->is_rgba=true;
+         break;
+      }
+
+    tessFace->rgba_vertices.reserve((tessFace->is_rgba?4:3)*3*nI);
+    for(uint32_t i=0; i<nI; i++)
+    {
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][0]].R));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][0]].G));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][0]].B));
+       if(tessFace->is_rgba)
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][0]].A));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][1]].R));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][1]].G));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][1]].B));
+       if(tessFace->is_rgba)
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][1]].A));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][2]].R));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][2]].G));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][2]].B));
+       if(tessFace->is_rgba)
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][2]].A));
+    }
+  }
+  tess->addTessFace(tessFace);
+  const uint32_t tess_index = add3DTess(tess);
+  return tess_index;
+}
+
+void oPRCFile::addQuads(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[][4], const PRCmaterial& m,
+ uint32_t nN, const double N[][3],   const uint32_t NI[][4],
+ uint32_t nT, const double T[][2],   const uint32_t TI[][4],
+ uint32_t nC, const RGBAColour C[],  const uint32_t CI[][4],
+ uint32_t nM, const PRCmaterial M[], const uint32_t MI[], double ca)
+{
+  if(nP==0 || P==NULL || nI==0 || PI==NULL)
+     return;
+  const uint32_t tess_index = createQuadMesh(nP, P, nI, PI, m, nN, N, NI, nT, T, TI, nC, C, CI, nM, M, MI, ca);
+  useMesh(tess_index,m1);
+}
+
+uint32_t oPRCFile::createQuadMesh(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[][4], uint32_t style_index,
+ uint32_t nN, const double N[][3],   const uint32_t NI[][4],
+ uint32_t nT, const double T[][2],   const uint32_t TI[][4],
+ uint32_t nC, const RGBAColour C[],  const uint32_t CI[][4],
+ uint32_t nS, const uint32_t S[],    const uint32_t SI[], double ca)
+{
+  if(nP==0 || P==NULL || nI==0 || PI==NULL)
+     return m1;
+
+  const bool triangle_color = (nS != 0 && S != NULL && SI != NULL);
+  const bool vertex_color   = (nC != 0 && C != NULL && CI != NULL);
+  const bool has_normals    = (nN != 0 && N != NULL && NI != NULL);
+  const bool textured       = (nT != 0 && T != NULL && TI != NULL);
+
+  PRC3DTess *tess = new PRC3DTess();
+  PRCTessFace *tessFace = new PRCTessFace();
+  tessFace->used_entities_flag = textured ? PRC_FACETESSDATA_TriangleTextured : PRC_FACETESSDATA_Triangle;
+  tessFace->number_of_texture_coordinate_indexes = textured ? 1 : 0;
+  tess->coordinates.reserve(3*nP);
+  for(uint32_t i=0; i<nP; i++)
+  {
+    tess->coordinates.push_back(P[i][0]);
+    tess->coordinates.push_back(P[i][1]);
+    tess->coordinates.push_back(P[i][2]);
+  }
+  if(has_normals)
+  {
+    tess->normal_coordinate.reserve(3*nN);
+  for(uint32_t i=0; i<nN; i++)
+  {
+    tess->normal_coordinate.push_back(N[i][0]);
+    tess->normal_coordinate.push_back(N[i][1]);
+    tess->normal_coordinate.push_back(N[i][2]);
+  }
+  }
+  else
+    tess->crease_angle = ca;
+  if(textured)
+  {
+    tess->texture_coordinate.reserve(2*nT);
+  for(uint32_t i=0; i<nT; i++)
+  {
+    tess->texture_coordinate.push_back(T[i][0]);
+    tess->texture_coordinate.push_back(T[i][1]);
+  }
+  }
+  tess->triangulated_index.reserve(2*(3*nI+(has_normals?3:0)*nI+(textured?3:0)*nI));
+  for(uint32_t i=0; i<nI; i++)
+  {
+    // first triangle
+    if(has_normals)
+    tess->triangulated_index.push_back(3*NI[i][0]);
+    if(textured)
+    tess->triangulated_index.push_back(2*TI[i][0]);
+    tess->triangulated_index.push_back(3*PI[i][0]);
+    if(has_normals)
+    tess->triangulated_index.push_back(3*NI[i][1]);
+    if(textured)
+    tess->triangulated_index.push_back(2*TI[i][1]);
+    tess->triangulated_index.push_back(3*PI[i][1]);
+    if(has_normals)
+    tess->triangulated_index.push_back(3*NI[i][3]);
+    if(textured)
+    tess->triangulated_index.push_back(2*TI[i][3]);
+    tess->triangulated_index.push_back(3*PI[i][3]);
+    // second triangle
+    if(has_normals)
+    tess->triangulated_index.push_back(3*NI[i][1]);
+    if(textured)
+    tess->triangulated_index.push_back(2*TI[i][1]);
+    tess->triangulated_index.push_back(3*PI[i][1]);
+    if(has_normals)
+    tess->triangulated_index.push_back(3*NI[i][2]);
+    if(textured)
+    tess->triangulated_index.push_back(2*TI[i][2]);
+    tess->triangulated_index.push_back(3*PI[i][2]);
+    if(has_normals)
+    tess->triangulated_index.push_back(3*NI[i][3]);
+    if(textured)
+    tess->triangulated_index.push_back(2*TI[i][3]);
+    tess->triangulated_index.push_back(3*PI[i][3]);
+  }
+  tessFace->sizes_triangulated.push_back(2*nI);
+  if(triangle_color)
+  {
+    tessFace->line_attributes.reserve(2*nI);
+    for(uint32_t i=0; i<nI; i++)
+    {
+       tessFace->line_attributes.push_back(SI[i]);
+       tessFace->line_attributes.push_back(SI[i]);
+    }
+  }
+  else
+  {
+      tessFace->line_attributes.push_back(style_index);
+  }
+  if(vertex_color)
+  {
+    tessFace->is_rgba=false;
+    for(uint32_t i=0; i<nI; i++)
+      if(1.0 != C[CI[i][0]].A || 1.0 != C[CI[i][1]].A || 1.0 != C[CI[i][2]].A)
+      {
+         tessFace->is_rgba=true;
+         break;
+      }
+
+    tessFace->rgba_vertices.reserve(2*(tessFace->is_rgba?4:3)*3*nI);
+    for(uint32_t i=0; i<nI; i++)
+    {
+       // first triangle
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][0]].R));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][0]].G));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][0]].B));
+       if(tessFace->is_rgba)
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][0]].A));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][1]].R));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][1]].G));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][1]].B));
+       if(tessFace->is_rgba)
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][1]].A));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][3]].R));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][3]].G));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][3]].B));
+       if(tessFace->is_rgba)
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][3]].A));
+       // second triangle
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][1]].R));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][1]].G));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][1]].B));
+       if(tessFace->is_rgba)
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][1]].A));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][2]].R));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][2]].G));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][2]].B));
+       if(tessFace->is_rgba)
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][2]].A));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][3]].R));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][3]].G));
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][3]].B));
+       if(tessFace->is_rgba)
+       tessFace->rgba_vertices.push_back(byte(C[CI[i][3]].A));
+    }
+  }
+  tess->addTessFace(tessFace);
+  const uint32_t tess_index = add3DTess(tess);
+  return tess_index;
+}
+
+void oPRCFile::addQuad(const double P[][3], const RGBAColour C[])
+{
+  PRCgroup &group = findGroup();
+
+  group.quads.push_back(PRCtessquad());
+  PRCtessquad &quad = group.quads.back();
+  for(size_t i = 0; i < 4; i++)
+  {
+    quad.vertices[i].x = P[i][0];
+    quad.vertices[i].y = P[i][1];
+    quad.vertices[i].z = P[i][2];
+    quad.colours[i] = C[i];
+  }
+}
+/*
+void oPRCFile::addTriangle(const double P[][3], const double T[][2], uint32_t style_index)
+{
+  PRCgroup &group = findGroup();
+
+  group.triangles.push_back(PRCtesstriangle());
+  PRCtesstriangle &triangle = group.triangles.back();
+  for(size_t i = 0; i < 3; i++)
+  {
+    triangle.vertices[i].x = P[i][0];
+    triangle.vertices[i].y = P[i][1];
+    triangle.vertices[i].z = P[i][2];
+    triangle.texcoords[i].x = T[i][0];
+    triangle.texcoords[i].y = T[i][1];
+  }
+  triangle.style = style_index;
+}
+*/
+
+void oPRCFile::addLines(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[],
+ const RGBAColour& c, double w,
+ bool segment_color, uint32_t nC, const RGBAColour C[], uint32_t nCI, const uint32_t CI[])
+{
+  if(nP==0 || P==NULL || nI==0 || PI==NULL)
+    return;
+  const uint32_t tess_index = createLines(nP, P, nI, PI, segment_color, nC, C, nCI, CI);
+  useLines(tess_index, c, w);
+}
+
+uint32_t oPRCFile::createLines(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[],
+ bool segment_color, uint32_t nC, const RGBAColour C[], uint32_t nCI, const uint32_t CI[])
+{
+  if(nP==0 || P==NULL || nI==0 || PI==NULL)
+    return m1;
+
+  const bool vertex_color  = (nC != 0 && C != NULL && CI != NULL);
+
+  PRC3DWireTess *tess = new PRC3DWireTess();
+  tess->coordinates.reserve(3*nP);
+  for(uint32_t i=0; i<nP; i++)
+  {
+    tess->coordinates.push_back(P[i][0]);
+    tess->coordinates.push_back(P[i][1]);
+    tess->coordinates.push_back(P[i][2]);
+  }
+  tess->wire_indexes.reserve(nI);
+  for(uint32_t i=0; i<nI;)
+  {
+    tess->wire_indexes.push_back(PI[i]);
+    const uint32_t ni = i+PI[i]+1;
+    for(i++; i<ni; i++)
+      tess->wire_indexes.push_back(3*PI[i]);
+  }
+  if(vertex_color)
+  {
+    tess->is_segment_color = segment_color;
+    tess->is_rgba=false;
+    for(uint32_t i=0; i<nCI; i++)
+      if(1.0 != C[CI[i]].A)
+      {
+         tess->is_rgba=true;
+         break;
+      }
+    tess->rgba_vertices.reserve((tess->is_rgba?4:3)*nCI);
+    for(uint32_t i=0; i<nCI; i++)
+    {
+       tess->rgba_vertices.push_back(byte(C[CI[i]].R));
+       tess->rgba_vertices.push_back(byte(C[CI[i]].G));
+       tess->rgba_vertices.push_back(byte(C[CI[i]].B));
+       if(tess->is_rgba)
+       tess->rgba_vertices.push_back(byte(C[CI[i]].A));
+    }
+  }
+  const uint32_t tess_index = add3DWireTess(tess);
+  return tess_index;
+}
+
+uint32_t oPRCFile::createSegments(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[][2],
+                               bool segment_color, uint32_t nC, const RGBAColour C[], const uint32_t CI[][2])
+{
+  if(nP==0 || P==NULL || nI==0 || PI==NULL)
+    return m1;
+  
+  const bool vertex_color  = (nC != 0 && C != NULL && CI != NULL);
+  
+  PRC3DWireTess *tess = new PRC3DWireTess();
+  tess->coordinates.reserve(3*nP);
+  for(uint32_t i=0; i<nP; i++)
+  {
+    tess->coordinates.push_back(P[i][0]);
+    tess->coordinates.push_back(P[i][1]);
+    tess->coordinates.push_back(P[i][2]);
+  }
+  tess->wire_indexes.reserve(3*nI);
+  for(uint32_t i=0; i<nI; i++)
+  {
+    tess->wire_indexes.push_back(2);
+    tess->wire_indexes.push_back(3*PI[i][0]);
+    tess->wire_indexes.push_back(3*PI[i][1]);
+  }
+  if(vertex_color)
+  {
+    tess->is_segment_color = segment_color;
+    tess->is_rgba=false;
+    for(uint32_t i=0; i<nI; i++)
+      if(1.0 != C[CI[i][0]].A || 1.0 != C[CI[i][1]].A)
+      {
+        tess->is_rgba=true;
+        break;
+      }
+    tess->rgba_vertices.reserve((tess->is_rgba?4:3)*(segment_color?1:2)*nI);
+    for(uint32_t i=0; i<nI; i++)
+    {
+      if (segment_color) {
+        tess->rgba_vertices.push_back(byte(0.5*C[CI[i][0]].R+0.5*C[CI[i][1]].R));
+        tess->rgba_vertices.push_back(byte(0.5*C[CI[i][0]].G+0.5*C[CI[i][1]].G));
+        tess->rgba_vertices.push_back(byte(0.5*C[CI[i][0]].B+0.5*C[CI[i][1]].B));
+        if(tess->is_rgba)
+          tess->rgba_vertices.push_back(byte(0.5*C[CI[i][0]].A+0.5*C[CI[i][1]].A));
+      } else {
+        tess->rgba_vertices.push_back(byte(C[CI[i][0]].R));
+        tess->rgba_vertices.push_back(byte(C[CI[i][0]].G));
+        tess->rgba_vertices.push_back(byte(C[CI[i][0]].B));
+        if(tess->is_rgba)
+          tess->rgba_vertices.push_back(byte(C[CI[i][0]].A));
+        tess->rgba_vertices.push_back(byte(C[CI[i][1]].R));
+        tess->rgba_vertices.push_back(byte(C[CI[i][1]].G));
+        tess->rgba_vertices.push_back(byte(C[CI[i][1]].B));
+        if(tess->is_rgba)
+          tess->rgba_vertices.push_back(byte(C[CI[i][1]].A));
+      }
+    }
+  }
+  const uint32_t tess_index = add3DWireTess(tess);
+  return tess_index;
+}
+
+void oPRCFile::addLine(uint32_t n, const double P[][3], const RGBAColour &c, double w)
+{
+  PRCgroup &group = findGroup();
+  if(group.options.tess)
+  {
+    group.lines[w].push_back(PRCtessline());
+    PRCtessline& line = group.lines[w].back();
+    line.color.red   = c.R;
+    line.color.green = c.G;
+    line.color.blue  = c.B;
+    for(uint32_t i=0; i<n; i++)
+      line.point.push_back(PRCVector3d(P[i][0],P[i][1],P[i][2]));
+  }
+  else
+  {
+    ADDWIRE(PRCPolyLine)
+    curve->point.resize(n);
+    for(uint32_t i=0; i<n; i++)
+     curve->point[i].Set(P[i][0],P[i][1],P[i][2]);
+    curve->interval.min = 0;
+    curve->interval.max = curve->point.size()-1;
+  }
+}
+
+void oPRCFile::addSegment(const double P1[3], const double P2[3], const RGBAColour &c, double w)
+{
+  PRCgroup &group = findGroup();
+  if(group.options.tess)
+  {
+    group.lines[w].push_back(PRCtessline());
+    PRCtessline& line = group.lines[w].back();
+    line.color.red   = c.R;
+    line.color.green = c.G;
+    line.color.blue  = c.B;
+    line.point.push_back(PRCVector3d(P1[0],P1[1],P1[2]));
+    line.point.push_back(PRCVector3d(P2[0],P2[1],P2[2]));
+  }
+  else
+  {
+    ADDWIRE(PRCPolyLine)
+    curve->point.resize(2);
+    curve->point[0].Set(P1[0],P1[1],P1[2]);
+    curve->point[1].Set(P2[0],P2[1],P2[2]);
+    curve->interval.min = 0;
+    curve->interval.max = curve->point.size()-1;
+  }
+}
+
+void oPRCFile::addBezierCurve(uint32_t n, const double cP[][3],
+                              const RGBAColour &c)
+{
+  ADDWIRE(PRCNURBSCurve)
+  curve->is_rational = false;
+  curve->degree = 3;
+  const size_t NUMBER_OF_POINTS = n;
+  curve->control_point.resize(NUMBER_OF_POINTS);
+  for(size_t i = 0; i < NUMBER_OF_POINTS; ++i)
+    curve->control_point[i].Set(cP[i][0],cP[i][1],cP[i][2]);
+  curve->knot.resize(3+NUMBER_OF_POINTS+1);
+  curve->knot[0] = 1;
+  for(size_t i = 1; i < 3+NUMBER_OF_POINTS; ++i)
+    curve->knot[i] = (i+2)/3; // integer division is intentional
+  curve->knot[3+NUMBER_OF_POINTS] = (3+NUMBER_OF_POINTS+1)/3;
+}
+
+void oPRCFile::addCurve(uint32_t d, uint32_t n, const double cP[][3], const double *k, const RGBAColour &c, const double w[])
+{
+  ADDWIRE(PRCNURBSCurve)
+  curve->is_rational = (w!=NULL);
+  curve->degree = d;
+  curve->control_point.resize(n);
+  for(uint32_t i = 0; i < n; i++)
+    if(w)
+      curve->control_point[i].Set(cP[i][0]*w[i],cP[i][1]*w[i],cP[i][2]*w[i],w[i]);
+    else
+      curve->control_point[i].Set(cP[i][0],cP[i][1],cP[i][2]);
+  curve->knot.resize(d+n+1);
+  for(uint32_t i = 0; i < d+n+1; i++)
+    curve->knot[i] = k[i];
+}
+
+void oPRCFile::addRectangle(const double P[][3], const PRCmaterial &m)
+{
+  PRCgroup &group = findGroup();
+  if(group.options.tess)
+  {
+    group.rectangles.push_back(PRCtessrectangle());
+    PRCtessrectangle &rectangle = group.rectangles.back();
+    rectangle.style = addMaterial(m);
+    for(size_t i = 0; i < 4; i++)
+    {
+       rectangle.vertices[i].x = P[i][0];
+       rectangle.vertices[i].y = P[i][1];
+       rectangle.vertices[i].z = P[i][2];
+    }
+  }
+  else if(group.options.compression == 0.0)
+  {
+    ADDFACE(PRCNURBSSurface)
+
+    surface->is_rational = false;
+    surface->degree_in_u = 1;
+    surface->degree_in_v = 1;
+    surface->control_point.resize(4);
+    for(size_t i = 0; i < 4; ++i)
+    {
+        surface->control_point[i].x = P[i][0];
+        surface->control_point[i].y = P[i][1];
+        surface->control_point[i].z = P[i][2];
+    }
+    surface->knot_u.resize(4);
+    surface->knot_v.resize(4);
+    surface->knot_v[0] = surface->knot_u[0] = 1;
+    surface->knot_v[1] = surface->knot_u[1] = 3;
+    surface->knot_v[2] = surface->knot_u[2] = 4;
+    surface->knot_v[3] = surface->knot_u[3] = 4;
+  }
+  else
+  {
+    ADDCOMPFACE
+
+    compface->degree = 1;
+    compface->control_point.resize(4);
+    for(size_t i = 0; i < 4; ++i)
+    {
+        compface->control_point[i].x = P[i][0];
+        compface->control_point[i].y = P[i][1];
+        compface->control_point[i].z = P[i][2];
+    }
+  }
+}
+
+void oPRCFile::addPatch(const double cP[][3], const PRCmaterial &m)
+{
+  PRCgroup &group = findGroup();
+  if(group.options.compression == 0.0)
+  {
+    ADDFACE(PRCNURBSSurface)
+
+    surface->is_rational = false;
+    surface->degree_in_u = 3;
+    surface->degree_in_v = 3;
+    surface->control_point.resize(16);
+    for(size_t i = 0; i < 16; ++i)
+    {
+        surface->control_point[i].x = cP[i][0];
+        surface->control_point[i].y = cP[i][1];
+        surface->control_point[i].z = cP[i][2];
+    }
+    surface->knot_u.resize(8);
+    surface->knot_v.resize(8);
+    surface->knot_v[0] = surface->knot_u[0] = 1;
+    surface->knot_v[1] = surface->knot_u[1] = 1;
+    surface->knot_v[2] = surface->knot_u[2] = 1;
+    surface->knot_v[3] = surface->knot_u[3] = 1;
+    surface->knot_v[4] = surface->knot_u[4] = 2;
+    surface->knot_v[5] = surface->knot_u[5] = 2;
+    surface->knot_v[6] = surface->knot_u[6] = 2;
+    surface->knot_v[7] = surface->knot_u[7] = 2;
+  }
+  else
+  {
+    ADDCOMPFACE
+
+    compface->degree = 3;
+    compface->control_point.resize(16);
+    for(size_t i = 0; i < 16; ++i)
+    {
+        compface->control_point[i].x = cP[i][0];
+        compface->control_point[i].y = cP[i][1];
+        compface->control_point[i].z = cP[i][2];
+    }
+  }
+}
+
+void oPRCFile::addSurface(uint32_t dU, uint32_t dV, uint32_t nU, uint32_t nV,
+                          const double cP[][3], const double *kU,
+                          const double *kV, const PRCmaterial &m,
+                          const double w[])
+{
+  ADDFACE(PRCNURBSSurface)
+
+  surface->is_rational = (w!=NULL);
+  surface->degree_in_u = dU;
+  surface->degree_in_v = dV;
+  surface->control_point.resize(nU*nV);
+  for(size_t i = 0; i < nU*nV; i++)
+    if(w)
+      surface->control_point[i]=PRCControlPoint(cP[i][0]*w[i],cP[i][1]*w[i],cP[i][2]*w[i],w[i]);
+    else
+      surface->control_point[i]=PRCControlPoint(cP[i][0],cP[i][1],cP[i][2]);
+  surface->knot_u.insert(surface->knot_u.end(), kU, kU+(dU+nU+1));
+  surface->knot_v.insert(surface->knot_v.end(), kV, kV+(dV+nV+1));
+}
+
+#define SETTRANSF \
+  if(t&&!isid(t))                                                             \
+    face.transform = new PRCGeneralTransformation3d(t);                       \
+  if(origin) surface->origin.Set(origin[0],origin[1],origin[2]);              \
+  if(x_axis) surface->x_axis.Set(x_axis[0],x_axis[1],x_axis[2]);              \
+  if(y_axis) surface->y_axis.Set(y_axis[0],y_axis[1],y_axis[2]);              \
+  surface->scale = scale;                                                     \
+  surface->geometry_is_2D = false;                                            \
+  if(surface->origin!=PRCVector3d(0.0,0.0,0.0))                                     \
+    surface->behaviour = surface->behaviour | PRC_TRANSFORMATION_Translate;   \
+  if(surface->x_axis!=PRCVector3d(1.0,0.0,0.0)||surface->y_axis!=PRCVector3d(0.0,1.0,0.0)) \
+    surface->behaviour = surface->behaviour | PRC_TRANSFORMATION_Rotate;      \
+  if(surface->scale!=1)                                                       \
+    surface->behaviour = surface->behaviour | PRC_TRANSFORMATION_Scale;       \
+  surface->has_transformation = (surface->behaviour != PRC_TRANSFORMATION_Identity);
+
+#define PRCFACETRANSFORM const double origin[3], const double x_axis[3], const double y_axis[3], double scale, const double* t
+
+void oPRCFile::addTube(uint32_t n, const double cP[][3], const double oP[][3], bool straight, const PRCmaterial &m, PRCFACETRANSFORM)
+{
+  ADDFACE(PRCBlend01)
+  SETTRANSF
+  if(straight)
+  {
+    PRCPolyLine *center_curve = new PRCPolyLine;
+    center_curve->point.resize(n);
+    for(uint32_t i=0; i<n; i++)
+      center_curve->point[i].Set(cP[i][0],cP[i][1],cP[i][2]);
+    center_curve->interval.min = 0;
+    center_curve->interval.max = center_curve->point.size()-1;
+    surface->center_curve = center_curve;
+
+    PRCPolyLine *origin_curve = new PRCPolyLine;
+    origin_curve->point.resize(n);
+    for(uint32_t i=0; i<n; i++)
+      origin_curve->point[i].Set(oP[i][0],oP[i][1],oP[i][2]);
+    origin_curve->interval.min = 0;
+    origin_curve->interval.max = origin_curve->point.size()-1;
+    surface->origin_curve = origin_curve;
+
+    surface->uv_domain.min.x = 0;
+    surface->uv_domain.max.x = 2*pi;
+    surface->uv_domain.min.y = 0;
+    surface->uv_domain.max.y = n-1;
+  }
+  else
+  {
+    PRCNURBSCurve *center_curve = new PRCNURBSCurve;
+    center_curve->is_rational = false;
+    center_curve->degree = 3;
+    const uint32_t CENTER_NUMBER_OF_POINTS = n;
+    center_curve->control_point.resize(CENTER_NUMBER_OF_POINTS);
+    for(uint32_t i = 0; i < CENTER_NUMBER_OF_POINTS; ++i)
+      center_curve->control_point[i].Set(cP[i][0],cP[i][1],cP[i][2]);
+    center_curve->knot.resize(3+CENTER_NUMBER_OF_POINTS+1);
+    center_curve->knot[0] = 1;
+    for(uint32_t i = 1; i < 3+CENTER_NUMBER_OF_POINTS; ++i)
+      center_curve->knot[i] = (i+2)/3; // integer division is intentional
+    center_curve->knot[3+CENTER_NUMBER_OF_POINTS] = (3+CENTER_NUMBER_OF_POINTS+1)/3;
+    surface->center_curve = center_curve;
+
+    PRCNURBSCurve *origin_curve = new PRCNURBSCurve;
+    origin_curve->is_rational = false;
+    origin_curve->degree = 3;
+    const uint32_t ORIGIN_NUMBER_OF_POINTS = n;
+    origin_curve->control_point.resize(ORIGIN_NUMBER_OF_POINTS);
+    for(uint32_t i = 0; i < ORIGIN_NUMBER_OF_POINTS; ++i)
+      origin_curve->control_point[i].Set(oP[i][0],oP[i][1],oP[i][2]);
+    origin_curve->knot.resize(3+ORIGIN_NUMBER_OF_POINTS+1);
+    origin_curve->knot[0] = 1;
+    for(size_t i = 1; i < 3+ORIGIN_NUMBER_OF_POINTS; ++i)
+      origin_curve->knot[i] = (i+2)/3; // integer division is intentional
+    origin_curve->knot[3+ORIGIN_NUMBER_OF_POINTS] = (3+ORIGIN_NUMBER_OF_POINTS+1)/3;
+    surface->origin_curve = origin_curve;
+
+    surface->uv_domain.min.x = 0;
+    surface->uv_domain.max.x = 2*pi;
+    surface->uv_domain.min.y = 1; // first knot
+    surface->uv_domain.max.y = (3+CENTER_NUMBER_OF_POINTS+1)/3; // last knot
+  }
+}
+
+void oPRCFile::addHemisphere(double radius, const PRCmaterial &m, PRCFACETRANSFORM)
+{
+  ADDFACE(PRCSphere)
+  SETTRANSF
+  surface->uv_domain.min.x = 0;
+  surface->uv_domain.max.x = 2*pi;
+  surface->uv_domain.min.y = 0;
+  surface->uv_domain.max.y = 0.5*pi;
+  surface->radius = radius;
+}
+
+void oPRCFile::addSphere(double radius, const PRCmaterial &m, PRCFACETRANSFORM)
+{
+  ADDFACE(PRCSphere)
+  SETTRANSF
+  surface->uv_domain.min.x = 0;
+  surface->uv_domain.max.x = 2*pi;
+  surface->uv_domain.min.y =-0.5*pi;
+  surface->uv_domain.max.y = 0.5*pi;
+  surface->radius = radius;
+}
+
+void oPRCFile::addDisk(double radius, const PRCmaterial &m, PRCFACETRANSFORM)
+{
+  ADDFACE(PRCRuled)
+  SETTRANSF
+  PRCCircle *first_curve = new PRCCircle;
+  first_curve->radius = radius;
+  surface->first_curve = first_curve;
+  PRCCircle *second_curve = new PRCCircle;
+  second_curve->radius = 0;
+  surface->second_curve = second_curve;
+
+  surface->uv_domain.min.x = 0;
+  surface->uv_domain.max.x = 1;
+  surface->uv_domain.min.y = 0;
+  surface->uv_domain.max.y = 2*pi;
+  surface->parameterization_on_v_coeff_a = -1;
+  surface->parameterization_on_v_coeff_b = 2*pi;
+}
+
+void oPRCFile::addCylinder(double radius, double height, const PRCmaterial &m, PRCFACETRANSFORM)
+{
+  ADDFACE(PRCCylinder)
+  SETTRANSF
+  surface->uv_domain.min.x = 0;
+  surface->uv_domain.max.x = 2*pi;
+  surface->uv_domain.min.y = (height>0)?0:height;
+  surface->uv_domain.max.y = (height>0)?height:0;
+  surface->radius = radius;
+}
+
+void oPRCFile::addCone(double radius, double height, const PRCmaterial &m, PRCFACETRANSFORM)
+{
+  ADDFACE(PRCCone)
+  SETTRANSF
+  surface->uv_domain.min.x = 0;
+  surface->uv_domain.max.x = 2*pi;
+  surface->uv_domain.min.y = (height>0)?0:height;
+  surface->uv_domain.max.y = (height>0)?height:0;
+  surface->bottom_radius = radius;
+  surface->semi_angle = -atan(radius/height);;
+}
+
+void oPRCFile::addTorus(double major_radius, double minor_radius, double angle1, double angle2, const PRCmaterial &m, PRCFACETRANSFORM)
+{
+  ADDFACE(PRCTorus)
+  SETTRANSF
+  surface->uv_domain.min.x = (angle1/180)*pi;
+  surface->uv_domain.max.x = (angle2/180)*pi;
+  surface->uv_domain.min.y = 0;
+  surface->uv_domain.max.y = 2*pi;
+  surface->major_radius = major_radius;
+  surface->minor_radius = minor_radius;
+}
+
+#undef PRCFACETRANSFORM
+#undef ADDFACE
+#undef ADDWIRE
+#undef SETTRANSF
+
+uint32_t PRCFileStructure::addRgbColor(double r, double g, double b)
+{
+  const PRCRgbColor color(r, g, b);
+  colors.push_back(color);
+  return 3*(colors.size()-1);
+}
+
+uint32_t PRCFileStructure::addRgbColorUnique(double r, double g, double b)
+{
+  const PRCRgbColor color(r, g, b);
+  uint32_t color_index = m1;
+  PRCRgbColorMap::const_iterator iRgbColor = colorMap.find(color);
+  if(iRgbColor!=colorMap.end())
+  {
+    color_index = iRgbColor->second;
+  }
+  else
+  {
+    color_index = 3*colors.size();
+    colors.push_back(color);
+    colorMap.insert(make_pair(color,color_index));
+  }
+  return color_index;
+}
+
+#define ADD_ADDUNIQ( prctype, prcmap, prclist) \
+uint32_t PRCFileStructure::add##prctype(PRC##prctype *& p##prctype)   \
+{ \
+  prclist.push_back(p##prctype); \
+  p##prctype = NULL; \
+  return prclist.size()-1; \
+} \
+ \
+uint32_t PRCFileStructure::add##prctype##Unique(PRC##prctype*& p##prctype) \
+{ \
+  uint32_t prc_index = m1; \
+  PRC##prctype##Map::const_iterator i##prctype = prcmap.find(p##prctype); \
+  if(i##prctype!=prcmap.end()) \
+  { \
+    delete p##prctype; \
+    prc_index = i##prctype->second; \
+  } \
+  else \
+  { \
+    prc_index = prclist.size(); \
+    prclist.push_back(p##prctype); \
+    prcmap.insert(make_pair(p##prctype,prc_index)); \
+  } \
+  p##prctype = NULL; \
+  return prc_index; \
+}
+
+ADD_ADDUNIQ(UncompressedFile,   uncompressedfileMap,   uncompressed_files  )
+ADD_ADDUNIQ(Picture,            pictureMap,            pictures            )
+ADD_ADDUNIQ(TextureDefinition,  texturedefinitionMap,  texture_definitions )
+ADD_ADDUNIQ(MaterialGeneric,    materialgenericMap,    materials           )
+ADD_ADDUNIQ(TextureApplication, textureapplicationMap, materials           )
+ADD_ADDUNIQ(Style,              styleMap,              styles              )
+
+#undef ADD_ADDUNIQ
+
+uint32_t PRCFileStructure::addPartDefinition(PRCPartDefinition*& pPartDefinition)
+{
+  part_definitions.push_back(pPartDefinition);
+  pPartDefinition = NULL;
+  return part_definitions.size()-1;
+}
+
+uint32_t PRCFileStructure::addProductOccurrence(PRCProductOccurrence*& pProductOccurrence)
+{
+  product_occurrences.push_back(pProductOccurrence);
+  pProductOccurrence = NULL;
+  return product_occurrences.size()-1;
+}
+
+uint32_t PRCFileStructure::addTopoContext(PRCTopoContext*& pTopoContext)
+{
+  contexts.push_back(pTopoContext);
+  pTopoContext = NULL;
+  return contexts.size()-1;
+}
+
+uint32_t PRCFileStructure::getTopoContext(PRCTopoContext*& pTopoContext)
+{
+  pTopoContext = new PRCTopoContext;
+  contexts.push_back(pTopoContext);
+  return contexts.size()-1;
+}
+
+uint32_t PRCFileStructure::add3DTess(PRC3DTess*& p3DTess)
+{
+  tessellations.push_back(p3DTess);
+  p3DTess = NULL;
+  return tessellations.size()-1;
+}
+
+uint32_t PRCFileStructure::add3DWireTess(PRC3DWireTess*& p3DWireTess)
+{
+  tessellations.push_back(p3DWireTess);
+  p3DWireTess = NULL;
+  return tessellations.size()-1;
+}
+/*
+uint32_t PRCFileStructure::addMarkupTess(PRCMarkupTess*& pMarkupTess)
+{
+  tessellations.push_back(pMarkupTess);
+  pMarkupTess = NULL;
+  return tessellations.size()-1;
+}
+
+uint32_t PRCFileStructure::addMarkup(PRCMarkup*& pMarkup)
+{
+  markups.push_back(pMarkup);
+  pMarkup = NULL;
+  return markups.size()-1;
+}
+
+uint32_t PRCFileStructure::addAnnotationItem(PRCAnnotationItem*& pAnnotationItem)
+{
+  annotation_entities.push_back(pAnnotationItem);
+  pAnnotationItem = NULL;
+  return annotation_entities.size()-1;
+}
+*/
+uint32_t PRCFileStructure::addCoordinateSystem(PRCCoordinateSystem*& pCoordinateSystem)
+{
+  reference_coordinate_systems.push_back(pCoordinateSystem);
+  pCoordinateSystem = NULL;
+  return reference_coordinate_systems.size()-1;
+}
+
+uint32_t PRCFileStructure::addCoordinateSystemUnique(PRCCoordinateSystem*& pCoordinateSystem)
+{
+  for(uint32_t i = 0; i < reference_coordinate_systems.size(); ++i)
+  {
+    if(*(reference_coordinate_systems[i])==*pCoordinateSystem) {
+      pCoordinateSystem = NULL;
+      return i;
+    }
+  }
+  reference_coordinate_systems.push_back(pCoordinateSystem);
+  pCoordinateSystem = NULL;
+  return reference_coordinate_systems.size()-1;
+}
diff --git a/src/prc/oPRCFile.h b/src/prc/oPRCFile.h
new file mode 100644
index 0000000..33f97db
--- /dev/null
+++ b/src/prc/oPRCFile.h
@@ -0,0 +1,850 @@
+/************
+*
+*   This file is part of a tool for producing 3D content in the PRC format.
+*   Copyright (C) 2008  Orest Shardt <shardtor (at) gmail dot com>
+*
+*   This program is free software: you can redistribute it and/or modify
+*   it under the terms of the GNU Lesser General Public License as published by
+*   the Free Software Foundation, either version 3 of the License, or
+*   (at your option) any later version.
+*
+*   This program is distributed in the hope that it will be useful,
+*   but WITHOUT ANY WARRANTY; without even the implied warranty of
+*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*   GNU Lesser General Public License for more details.
+*
+*   You should have received a copy of the GNU Lesser General Public License
+*   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*
+*************/
+
+#ifndef __O_PRC_FILE_H
+#define __O_PRC_FILE_H
+
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <map>
+#include <set>
+#include <list>
+#include <stack>
+#include <string>
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "PRC.h"
+#include "PRCbitStream.h"
+#include "writePRC.h"
+
+class oPRCFile;
+class PRCFileStructure;
+
+#define EQFLD(fld) fld==c.fld
+#define COMPFLD(fld) \
+if(fld != c.fld) \
+return (fld < c.fld);
+
+struct RGBAColour
+{
+  RGBAColour(double r=0.0, double g=0.0, double b=0.0, double a=1.0) :
+    R(r), G(g), B(b), A(a) {}
+  double R,G,B,A;
+
+  void Set(double r, double g, double b, double a=1.0) 
+  {
+    R = r; G = g; B = b; A = a;
+  }
+  bool operator==(const RGBAColour &c) const
+  {
+    return (EQFLD(R) && EQFLD(G) && EQFLD(B) && EQFLD(A));
+  }
+  bool operator!=(const RGBAColour &c) const
+  {
+    return !(EQFLD(R) && EQFLD(G) && EQFLD(B) && EQFLD(A));
+  }
+  bool operator<(const RGBAColour &c) const
+  {
+    COMPFLD(R)
+    COMPFLD(G)
+    COMPFLD(B)
+    COMPFLD(A)
+    return false;
+  }
+  friend RGBAColour operator * (const RGBAColour& a, const double d)
+  { return RGBAColour(a.R*d,a.G*d,a.B*d,a.A*d); }
+  friend RGBAColour operator * (const double d, const RGBAColour& a)
+  { return RGBAColour(a.R*d,a.G*d,a.B*d,a.A*d); }
+};
+typedef std::map<RGBAColour,uint32_t> PRCcolourMap;
+
+struct RGBAColourWidth
+{
+  RGBAColourWidth(double r=0.0, double g=0.0, double b=0.0, double a=1.0, double w=1.0) :
+    R(r), G(g), B(b), A(a), W(w) {}
+  double R,G,B,A,W;
+
+  bool operator==(const RGBAColourWidth &c) const
+  {
+    return (EQFLD(R) && EQFLD(G) && EQFLD(B) && EQFLD(A) && EQFLD(W));
+  }
+  bool operator!=(const RGBAColourWidth &c) const
+  {
+    return !(EQFLD(R) && EQFLD(G) && EQFLD(B) && EQFLD(A) && EQFLD(W));
+  }
+  bool operator<(const RGBAColourWidth &c) const
+  {
+    COMPFLD(R)
+    COMPFLD(G)
+    COMPFLD(B)
+    COMPFLD(A)
+    COMPFLD(W)
+    return false;
+  }
+};
+typedef std::map<RGBAColourWidth,uint32_t> PRCcolourwidthMap;
+
+struct PRCmaterial
+{
+  PRCmaterial() : alpha(1.0),shininess(1.0),width(1.0) {}
+  PRCmaterial(const RGBAColour &a, const RGBAColour &d, const RGBAColour &e,
+              const RGBAColour &s, double p, double h, double w=1.0) :
+  ambient(a), diffuse(d), emissive(e), specular(s), alpha(p), shininess(h), width(w) {}
+  
+  RGBAColour ambient,diffuse,emissive,specular;
+  double alpha,shininess,width;
+  
+  bool operator==(const PRCmaterial &c) const
+  {
+    return (EQFLD(ambient)   &&
+            EQFLD(diffuse)   &&
+            EQFLD(emissive)  &&
+            EQFLD(specular)  &&
+            EQFLD(alpha)     &&
+            EQFLD(shininess) &&
+            EQFLD(width));
+  }
+  bool operator<(const PRCmaterial &c) const
+  {
+    COMPFLD(ambient)
+    COMPFLD(diffuse)
+    COMPFLD(emissive)
+    COMPFLD(specular)
+    COMPFLD(alpha)
+    COMPFLD(shininess)
+    COMPFLD(width)
+    return false;
+  }
+};
+typedef std::map<PRCmaterial,uint32_t> PRCmaterialMap;
+
+#undef EQFLD
+#undef COMPFLD
+                 
+struct PRCtexture
+{
+  PRCtexture() : 
+  data(NULL), format(KEPRCPicture_BITMAP_RGBA_BYTE), width(0), height(0), size(0),
+  mapping(0), components(PRC_TEXTURE_MAPPING_COMPONENTS_RGBA),
+  function(KEPRCTextureFunction_Modulate),
+  wrapping_mode_S(KEPRCTextureWrappingMode_Repeat), wrapping_mode_T(KEPRCTextureWrappingMode_Repeat) {}
+  
+  const uint8_t* data;
+  EPRCPictureDataFormat format;
+  /*
+    KEPRCPicture_PNG
+    KEPRCPicture_JPG
+    KEPRCPicture_BITMAP_RGB_BYTE
+    KEPRCPicture_BITMAP_RGBA_BYTE
+    KEPRCPicture_BITMAP_GREY_BYTE
+    KEPRCPicture_BITMAP_GREYA_BYTE
+  */
+  uint32_t width;   // may be omitted for PNG and JPEG
+  uint32_t height;  // too
+  uint32_t size;
+  
+  uint32_t mapping;
+  /*
+  PRC_TEXTURE_MAPPING_DIFFUSE
+  PRC_TEXTURE_MAPPING_BUMP
+  PRC_TEXTURE_MAPPING_OPACITY 
+  PRC_TEXTURE_MAPPING_SPHERICAL_REFLECTION
+  */
+  
+  uint8_t components;
+  /*
+    PRC_TEXTURE_MAPPING_COMPONENTS_RED
+    PRC_TEXTURE_MAPPING_COMPONENTS_GREEN
+    PRC_TEXTURE_MAPPING_COMPONENTS_BLUE
+    PRC_TEXTURE_MAPPING_COMPONENTS_RGB
+    PRC_TEXTURE_MAPPING_COMPONENTS_ALPHA
+    PRC_TEXTURE_MAPPING_COMPONENTS_RGBA
+  */
+  
+  EPRCTextureFunction function;
+  /*
+   enum EPRCTextureFunction {			// Defines how to paint a texture on the surface being rendered.
+   KEPRCTextureFunction_Unknown,			// Let the application choose.
+   KEPRCTextureFunction_Modulate,		// Combine lighting with texturing. This is the default value.
+   KEPRCTextureFunction_Replace,			// Replace the object color with texture color data.
+   KEPRCTextureFunction_Blend,			// Reserved for future use.
+   KEPRCTextureFunction_Decal			// Reserved for future use.
+   };
+  */
+
+  EPRCTextureWrappingMode wrapping_mode_S;
+  EPRCTextureWrappingMode wrapping_mode_T;
+  /*
+   enum EPRCTextureWrappingMode {			// Defines repeating and clamping texture modes.
+   KEPRCTextureWrappingMode_Unknown,		// Let the application choose.
+   KEPRCTextureWrappingMode_Repeat,		// Display the repeated texture on the surface.
+   KEPRCTextureWrappingMode_ClampToBorder,	// Clamp the texture to the border. Display the surface color along the texture limits.
+   KEPRCTextureWrappingMode_Clamp,		// Reserved for future use.
+   KEPRCTextureWrappingMode_ClampToEdge,		// Reserved for future use.
+   KEPRCTextureWrappingMode_MirroredRepeat	// Reserved for future use.
+   };
+  */
+
+};
+
+/*
+struct PRCmaterial
+{
+  PRCmaterial() : alpha(1.0),shininess(1.0),
+      picture_data(NULL), picture_format(KEPRCPicture_BITMAP_RGB_BYTE), picture_width(0), picture_height(0), picture_size(0),
+      picture_replace(false), picture_repeat(false) {}
+  PRCmaterial(const RGBAColour &a, const RGBAColour &d, const RGBAColour &e,
+              const RGBAColour &s, double p, double h,
+              const uint8_t* pic=NULL, EPRCPictureDataFormat picf=KEPRCPicture_BITMAP_RGB_BYTE,
+              uint32_t picw=0, uint32_t pich=0, uint32_t pics=0, bool picreplace=false, bool picrepeat=false) :
+      ambient(a), diffuse(d), emissive(e), specular(s), alpha(p), shininess(h),
+      picture_data(pic), picture_format(picf), picture_width(picw), picture_height(pich), picture_size(pics),
+      picture_replace(picreplace), picture_repeat(picrepeat) {
+        if(picture_size==0)
+        {
+          if (picture_format==KEPRCPicture_BITMAP_RGB_BYTE)
+             picture_size = picture_width*picture_height*3;
+          if (picture_format==KEPRCPicture_BITMAP_RGBA_BYTE)
+             picture_size = picture_width*picture_height*4;
+          if (picture_format==KEPRCPicture_BITMAP_GREY_BYTE)
+             picture_size = picture_width*picture_height*1;
+          if (picture_format==KEPRCPicture_BITMAP_GREYA_BYTE)
+             picture_size = picture_width*picture_height*2;
+        }
+      }
+  RGBAColour ambient,diffuse,emissive,specular;
+  double alpha,shininess;
+  const uint8_t* picture_data;
+  EPRCPictureDataFormat picture_format;
+  uint32_t picture_width;
+  uint32_t picture_height;
+  uint32_t picture_size;
+  bool picture_replace; // replace material color with texture color? if false - just modify
+  bool picture_repeat;  // repeat texture? if false - clamp to edge
+
+  bool operator==(const PRCmaterial &m) const
+  {
+    return (ambient==m.ambient && diffuse==m.diffuse && emissive==m.emissive
+        && specular==m.specular && alpha==m.alpha && shininess==m.shininess
+        && picture_replace==m.picture_replace && picture_repeat==m.picture_repeat
+        && picture_format==m.picture_format
+        && picture_width==m.picture_width && picture_height==m.picture_height && picture_size==m.picture_size
+        && (picture_data==m.picture_data || memcmp(picture_data,m.picture_data,picture_size)==0) );
+  }
+  bool operator<(const PRCmaterial &m) const
+  {
+    if(ambient!=m.ambient)
+      return (ambient<m.ambient);
+    if(diffuse!=m.diffuse)
+      return (diffuse<m.diffuse);
+    if(emissive!=m.emissive)
+      return (emissive<m.emissive);
+    if(specular!=m.specular)
+      return (specular<m.specular);
+    if(alpha!=m.alpha)
+      return (alpha<m.alpha);
+    if(shininess!=m.shininess)
+      return (shininess<m.shininess);
+    if(picture_replace!=m.picture_replace)
+      return (picture_replace<m.picture_replace);
+    if(picture_repeat!=m.picture_repeat)
+      return (picture_repeat<m.picture_repeat);
+    if(picture_format!=m.picture_format)
+      return (picture_format<m.picture_format);
+    if(picture_width!=m.picture_width)
+      return (picture_width<m.picture_width);
+    if(picture_height!=m.picture_height)
+      return (picture_height<m.picture_height);
+    if(picture_size!=m.picture_size)
+      return (picture_size<m.picture_size);
+    if(picture_data!=m.picture_data)
+      return (memcmp(picture_data,m.picture_data,picture_size)<0);
+    return false;
+  }
+};
+typedef std::map<PRCmaterial,uint32_t> PRCmaterialMap;
+*/
+
+struct PRCtessrectangle // rectangle
+{
+  PRCVector3d vertices[4];
+  uint32_t style;
+};
+typedef std::vector<PRCtessrectangle> PRCtessrectangleList;
+
+struct PRCtessquad // rectangle
+{
+  PRCVector3d vertices[4];
+  RGBAColour  colours[4];
+};
+typedef std::vector<PRCtessquad> PRCtessquadList;
+/*
+struct PRCtesstriangle // textured triangle
+{
+  PRCtesstriangle() : 
+  style(m1) {}
+  PRCVector3d vertices[3];
+// PRCVector3d normals[3];
+// RGBAColour  colors[3];
+  PRCVector2d texcoords[3];
+  uint32_t style;
+};
+typedef std::vector<PRCtesstriangle> PRCtesstriangleList;
+*/
+struct PRCtessline // polyline
+{
+  std::vector<PRCVector3d> point;
+  PRCRgbColor color;
+};
+typedef std::list<PRCtessline> PRCtesslineList;
+typedef std::map<double, PRCtesslineList> PRCtesslineMap;
+
+struct PRCface
+{
+  PRCface() : transform(NULL), face(NULL) {}
+  uint32_t style;
+  bool transparent;
+  PRCGeneralTransformation3d*  transform;
+  PRCFace* face;
+};
+typedef std::vector <PRCface>  PRCfaceList;
+
+struct PRCcompface
+{
+  PRCcompface() : face(NULL) {}
+  uint32_t style;
+  bool transparent;
+  PRCCompressedFace* face;
+};
+typedef std::vector <PRCcompface>  PRCcompfaceList;
+
+struct PRCwire
+{
+  PRCwire() : style(m1), transform(NULL), curve(NULL) {}
+  uint32_t style;
+  PRCGeneralTransformation3d*  transform;
+  PRCCurve* curve;
+};
+typedef std::vector <PRCwire>  PRCwireList;
+
+typedef std::map <uint32_t,std::vector<PRCVector3d> >  PRCpointsetMap;
+
+class PRCoptions
+{
+public:
+  double compression;
+  double granularity;
+
+  bool closed;   // render the surface as one-sided; may yield faster rendering
+  bool tess;     // use tessellated mesh to store straight patches
+  bool do_break; //
+  bool no_break; // do not render transparent patches as one-faced nodes
+  double crease_angle; // crease angle for meshes
+
+  PRCoptions(double compression=0.0, double granularity=0.0, bool closed=false,
+             bool tess=false, bool do_break=true, bool no_break=false, double crease_angle=25.8419)
+    : compression(compression), granularity(granularity), closed(closed),
+      tess(tess), do_break(do_break), no_break(no_break), crease_angle(crease_angle) {}
+};
+
+class PRCgroup
+{
+ public:
+  PRCgroup() : 
+    product_occurrence(NULL), parent_product_occurrence(NULL), part_definition(NULL), parent_part_definition(NULL), transform(NULL) {}
+  PRCgroup(const std::string& name) : 
+    product_occurrence(NULL), parent_product_occurrence(NULL), part_definition(NULL), parent_part_definition(NULL), transform(NULL), name(name) {}
+  PRCProductOccurrence *product_occurrence, *parent_product_occurrence;
+  PRCPartDefinition *part_definition, *parent_part_definition;
+  PRCfaceList       faces;
+  PRCcompfaceList   compfaces;
+  PRCtessrectangleList  rectangles;
+// PRCtesstriangleList   triangles;
+  PRCtessquadList       quads;
+  PRCtesslineMap        lines;
+  PRCwireList           wires;
+  PRCpointsetMap        points;
+  std::vector<PRCPointSet*>      pointsets;
+  std::vector<PRCPolyBrepModel*> polymodels;
+  std::vector<PRCPolyWire*>      polywires;
+  PRCGeneralTransformation3d*  transform;
+  std::string name;
+  PRCoptions options;
+};
+
+void makeFileUUID(PRCUniqueId&);
+void makeAppUUID(PRCUniqueId&);
+
+class PRCStartHeader
+{
+  public:
+    uint32_t minimal_version_for_read; // PRCVersion
+    uint32_t authoring_version; // PRCVersion
+    PRCUniqueId file_structure_uuid;
+    PRCUniqueId application_uuid; // should be 0
+
+    PRCStartHeader() :
+      minimal_version_for_read(PRCVersion), authoring_version(PRCVersion) {}
+    void serializeStartHeader(std::ostream&) const;
+    void serializeUncompressedFiles(std::ostream&) const;
+
+    PRCUncompressedFileList uncompressed_files;
+    uint32_t getStartHeaderSize() const;
+    uint32_t getUncompressedFilesSize() const;
+};
+
+class PRCFileStructure : public PRCStartHeader
+{
+  public:
+    uint32_t number_of_referenced_file_structures;
+    double tessellation_chord_height_ratio;
+    double tessellation_angle_degree;
+    std::string default_font_family_name;
+    PRCRgbColorList colors;
+    PRCRgbColorMap colorMap;
+    PRCPictureList pictures;
+    PRCPictureMap pictureMap;
+    PRCUncompressedFileMap uncompressedfileMap;
+    PRCTextureDefinitionList texture_definitions;
+    PRCTextureDefinitionMap texturedefinitionMap;
+    PRCMaterialList materials;
+    PRCMaterialGenericMap materialgenericMap;
+    PRCTextureApplicationMap textureapplicationMap;
+    PRCStyleList styles;
+    PRCStyleMap styleMap;
+
+    PRCCoordinateSystemList reference_coordinate_systems;
+    std::vector<PRCFontKeysSameFont> font_keys_of_font;
+    PRCPartDefinitionList part_definitions;
+    PRCProductOccurrenceList product_occurrences;
+//  PRCMarkupList markups;
+//  PRCAnnotationItemList annotation_entities;
+    double unit;
+    PRCTopoContextList contexts;
+    PRCTessList tessellations;
+
+    uint32_t sizes[6];
+    uint8_t *globals_data;
+    PRCbitStream globals_out; // order matters: PRCbitStream must be initialized last
+    uint8_t *tree_data;
+    PRCbitStream tree_out;
+    uint8_t *tessellations_data;
+    PRCbitStream tessellations_out;
+    uint8_t *geometry_data;
+    PRCbitStream geometry_out;
+    uint8_t *extraGeometry_data;
+    PRCbitStream extraGeometry_out;
+
+    ~PRCFileStructure () {
+      for(PRCUncompressedFileList::iterator  it=uncompressed_files.begin();  it!=uncompressed_files.end();  ++it) delete *it;
+      for(PRCPictureList::iterator           it=pictures.begin();            it!=pictures.end();            ++it) delete *it;
+      for(PRCTextureDefinitionList::iterator it=texture_definitions.begin(); it!=texture_definitions.end(); ++it) delete *it;
+      for(PRCMaterialList::iterator          it=materials.begin();           it!=materials.end();           ++it) delete *it;
+      for(PRCStyleList::iterator             it=styles.begin();              it!=styles.end();              ++it) delete *it;
+      for(PRCTopoContextList::iterator       it=contexts.begin();            it!=contexts.end();            ++it) delete *it;
+      for(PRCTessList::iterator              it=tessellations.begin();       it!=tessellations.end();       ++it) delete *it;
+      for(PRCPartDefinitionList::iterator    it=part_definitions.begin();    it!=part_definitions.end();    ++it) delete *it;
+      for(PRCProductOccurrenceList::iterator it=product_occurrences.begin(); it!=product_occurrences.end(); ++it) delete *it;
+      for(PRCCoordinateSystemList::iterator  it=reference_coordinate_systems.begin(); it!=reference_coordinate_systems.end(); it++)
+        delete *it;
+
+      free(globals_data);
+      free(tree_data);
+      free(tessellations_data);
+      free(geometry_data);
+      free(extraGeometry_data);
+    }
+
+    PRCFileStructure() :
+      number_of_referenced_file_structures(0),
+      tessellation_chord_height_ratio(2000.0),tessellation_angle_degree(40.0),
+      default_font_family_name(""),
+      unit(1),
+      globals_data(NULL),globals_out(globals_data,0),
+      tree_data(NULL),tree_out(tree_data,0),
+      tessellations_data(NULL),tessellations_out(tessellations_data,0),
+      geometry_data(NULL),geometry_out(geometry_data,0),
+      extraGeometry_data(NULL),extraGeometry_out(extraGeometry_data,0) {}
+    void write(std::ostream&);
+    void prepare();
+    uint32_t getSize();
+    void serializeFileStructureGlobals(PRCbitStream&);
+    void serializeFileStructureTree(PRCbitStream&);
+    void serializeFileStructureTessellation(PRCbitStream&);
+    void serializeFileStructureGeometry(PRCbitStream&);
+    void serializeFileStructureExtraGeometry(PRCbitStream&);
+    uint32_t addPicture(EPRCPictureDataFormat format, uint32_t size, const uint8_t *picture, uint32_t width=0, uint32_t height=0, std::string name="");
+#define ADD_ADDUNIQ( prctype ) \
+uint32_t add##prctype( PRC##prctype*& p##prctype ); \
+uint32_t add##prctype##Unique( PRC##prctype*& p##prctype);
+  
+  ADD_ADDUNIQ( UncompressedFile   )
+  ADD_ADDUNIQ( Picture            )
+  ADD_ADDUNIQ( TextureDefinition  )
+  ADD_ADDUNIQ( TextureApplication )
+  ADD_ADDUNIQ( MaterialGeneric    )
+  ADD_ADDUNIQ( Style              ) 
+
+#undef ADD_ADDUNIQ
+
+    uint32_t addRgbColor(double r, double g, double b);
+    uint32_t addRgbColorUnique(double r, double g, double b);
+    uint32_t addPartDefinition(PRCPartDefinition*& pPartDefinition);
+    uint32_t addProductOccurrence(PRCProductOccurrence*& pProductOccurrence);
+    uint32_t addTopoContext(PRCTopoContext*& pTopoContext);
+    uint32_t getTopoContext(PRCTopoContext*& pTopoContext);
+    uint32_t add3DTess(PRC3DTess*& p3DTess);
+    uint32_t add3DWireTess(PRC3DWireTess*& p3DWireTess);
+/*
+    uint32_t addMarkupTess(PRCMarkupTess*& pMarkupTess);
+    uint32_t addMarkup(PRCMarkup*& pMarkup);
+    uint32_t addAnnotationItem(PRCAnnotationItem*& pAnnotationItem);
+ */
+    uint32_t addCoordinateSystem(PRCCoordinateSystem*& pCoordinateSystem);
+    uint32_t addCoordinateSystemUnique(PRCCoordinateSystem*& pCoordinateSystem);
+};
+
+class PRCFileStructureInformation
+{
+  public:
+    PRCUniqueId UUID;
+    uint32_t reserved; // 0
+    uint32_t number_of_offsets;
+    uint32_t *offsets;
+
+    void write(std::ostream&);
+
+    uint32_t getSize();
+};
+
+class PRCHeader : public PRCStartHeader
+{
+  public :
+    uint32_t number_of_file_structures;
+    PRCFileStructureInformation *fileStructureInformation;
+    uint32_t model_file_offset;
+    uint32_t file_size; // not documented
+
+    void write(std::ostream&);
+    uint32_t getSize();
+};
+
+typedef std::map <PRCGeneralTransformation3d,uint32_t> PRCtransformMap;
+
+class oPRCFile
+{
+  public:
+    oPRCFile(std::ostream &os, double u=1, uint32_t n=1) :
+      number_of_file_structures(n),
+      fileStructures(new PRCFileStructure*[n]),
+      unit(u),
+      modelFile_data(NULL),modelFile_out(modelFile_data,0),
+      fout(NULL),output(os)
+      {
+        for(uint32_t i = 0; i < number_of_file_structures; ++i)
+        {
+          fileStructures[i] = new PRCFileStructure();
+          fileStructures[i]->minimal_version_for_read = PRCVersion;
+          fileStructures[i]->authoring_version = PRCVersion;
+          makeFileUUID(fileStructures[i]->file_structure_uuid);
+          makeAppUUID(fileStructures[i]->application_uuid);
+          fileStructures[i]->unit = u;
+        }
+
+        groups.push(PRCgroup());
+        PRCgroup &group = groups.top();
+        group.name="root";
+        group.transform = NULL;
+        group.product_occurrence = new PRCProductOccurrence(group.name);
+        group.parent_product_occurrence = NULL;
+        group.part_definition = new PRCPartDefinition;
+        group.parent_part_definition = NULL;
+      }
+
+    oPRCFile(const std::string &name, double u=1, uint32_t n=1) :
+      number_of_file_structures(n),
+      fileStructures(new PRCFileStructure*[n]),
+      unit(u),
+      modelFile_data(NULL),modelFile_out(modelFile_data,0),
+      fout(new std::ofstream(name.c_str(),
+                             std::ios::out|std::ios::binary|std::ios::trunc)),
+      output(*fout)
+      {
+        for(uint32_t i = 0; i < number_of_file_structures; ++i)
+        {
+          fileStructures[i] = new PRCFileStructure();
+          fileStructures[i]->minimal_version_for_read = PRCVersion;
+          fileStructures[i]->authoring_version = PRCVersion;
+          makeFileUUID(fileStructures[i]->file_structure_uuid);
+          makeAppUUID(fileStructures[i]->application_uuid);
+          fileStructures[i]->unit = u;
+        }
+
+        groups.push(PRCgroup());
+        PRCgroup &group = groups.top();
+        group.name="root";
+        group.transform = NULL;
+        group.product_occurrence = new PRCProductOccurrence(group.name);
+        group.parent_product_occurrence = NULL;
+        group.part_definition = new PRCPartDefinition;
+        group.parent_part_definition = NULL;
+      }
+
+    ~oPRCFile()
+    {
+      for(uint32_t i = 0; i < number_of_file_structures; ++i)
+        delete fileStructures[i];
+      delete[] fileStructures;
+      if(fout != NULL)
+        delete fout;
+      free(modelFile_data);
+    }
+
+    void begingroup(const char *name, const PRCoptions *options=NULL,
+                    const double* t=NULL);
+    void endgroup();
+
+    std::string lastgroupname;
+    std::vector<std::string> lastgroupnames;
+    std::string calculate_unique_name(const ContentPRCBase *prc_entity,const ContentPRCBase *prc_occurence);
+    
+    bool finish();
+    uint32_t getSize();
+
+    const uint32_t number_of_file_structures;
+    PRCFileStructure **fileStructures;
+    PRCHeader header;
+    PRCUnit unit;
+    uint8_t *modelFile_data;
+    PRCbitStream modelFile_out; // order matters: PRCbitStream must be initialized last
+    PRCmaterialMap materialMap;
+    PRCcolourMap colourMap;
+    PRCcolourwidthMap colourwidthMap;
+    PRCgroup rootGroup;
+    PRCtransformMap transformMap;
+    std::stack<PRCgroup> groups;
+    PRCgroup& findGroup();
+    void doGroup(PRCgroup& group);
+    uint32_t addColour(const RGBAColour &colour);
+    uint32_t addColourWidth(const RGBAColour &colour, double width);
+    uint32_t addLineMaterial(const RGBAColour& c, double width)
+               { return addColourWidth(c,width); }
+    uint32_t addMaterial(const PRCmaterial &material);
+    uint32_t addTexturedMaterial(const PRCmaterial &material, uint32_t n=0, const PRCtexture* const* tt=NULL);
+    uint32_t addTransform(PRCGeneralTransformation3d*& transform);
+    uint32_t addTransform(const double* t);
+    uint32_t addTransform(const double origin[3], const double x_axis[3], const double y_axis[3], double scale);
+    void addPoint(const double P[3], const RGBAColour &c, double w=1.0);
+    void addPoint(double x, double y, double z, const RGBAColour &c, double w);
+    void addPoints(uint32_t n, const double P[][3], const RGBAColour &c, double w=1.0);
+    void addPoints(uint32_t n, const double P[][3], uint32_t style_index);
+    void addLines(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[],
+                      const RGBAColour& c, double w,
+                      bool segment_color, uint32_t nC, const RGBAColour C[], uint32_t nCI, const uint32_t CI[]);
+    uint32_t createLines(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[],
+                      bool segment_color, uint32_t nC, const RGBAColour C[], uint32_t nCI, const uint32_t CI[]);
+    uint32_t createSegments(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[][2],
+                            bool segment_color, uint32_t nC, const RGBAColour C[], const uint32_t CI[][2]);
+
+    void addTriangles(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[][3], const PRCmaterial& m,
+                      uint32_t nN, const double N[][3],   const uint32_t NI[][3],
+                      uint32_t nT, const double T[][2],   const uint32_t TI[][3],
+                      uint32_t nC, const RGBAColour C[],  const uint32_t CI[][3],
+                      uint32_t nM, const PRCmaterial M[], const uint32_t MI[], double ca);
+    uint32_t createTriangleMesh(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[][3], uint32_t style_index,
+                      uint32_t nN, const double N[][3],   const uint32_t NI[][3],
+                      uint32_t nT, const double T[][2],   const uint32_t TI[][3],
+                      uint32_t nC, const RGBAColour C[],  const uint32_t CI[][3],
+                      uint32_t nS, const uint32_t S[], const uint32_t SI[], double ca);
+    uint32_t createTriangleMesh(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[][3], const PRCmaterial& m,
+                      uint32_t nN, const double N[][3],   const uint32_t NI[][3],
+                      uint32_t nT, const double T[][2],   const uint32_t TI[][3],
+                      uint32_t nC, const RGBAColour C[],  const uint32_t CI[][3],
+                      uint32_t nM, const PRCmaterial M[], const uint32_t MI[], double ca)
+            {
+               const uint32_t style = addMaterial(m);
+               if(M!=NULL && nM>0)
+               {
+                 uint32_t* const styles = new uint32_t[nM];
+                 for(uint32_t i=0; i<nM; i++)
+                   styles[i]=addMaterial(M[i]);
+                 const uint32_t meshid =  createTriangleMesh(nP, P, nI, PI, style, nN, N, NI, nT, T, TI, nC, C, CI, nM, styles, MI, ca);
+                 delete[] styles;
+                 return meshid;
+               }
+               else
+                 return createTriangleMesh(nP, P, nI, PI, style, nN, N, NI, nT, T, TI, nC, C, CI, 0, NULL, NULL, ca);
+            }
+    void addQuads(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[][4], const PRCmaterial& m,
+                      uint32_t nN, const double N[][3],   const uint32_t NI[][4],
+                      uint32_t nT, const double T[][2],   const uint32_t TI[][4],
+                      uint32_t nC, const RGBAColour C[],  const uint32_t CI[][4],
+                      uint32_t nM, const PRCmaterial M[], const uint32_t MI[], double ca);
+    uint32_t createQuadMesh(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[][4], uint32_t style_index,
+                      uint32_t nN, const double N[][3],   const uint32_t NI[][4],
+                      uint32_t nT, const double T[][2],   const uint32_t TI[][4],
+                      uint32_t nC, const RGBAColour C[],  const uint32_t CI[][4],
+                      uint32_t nS, const uint32_t S[],    const uint32_t SI[], double ca);
+    uint32_t createQuadMesh(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[][4], const PRCmaterial& m,
+                      uint32_t nN, const double N[][3],   const uint32_t NI[][4],
+                      uint32_t nT, const double T[][2],   const uint32_t TI[][4],
+                      uint32_t nC, const RGBAColour C[],  const uint32_t CI[][4],
+                      uint32_t nM, const PRCmaterial M[], const uint32_t MI[], double ca)
+            {
+               const uint32_t style = addMaterial(m);
+               if(M!=NULL && nM>0)
+               {
+                 uint32_t* const styles = new uint32_t[nM];
+                 for(uint32_t i=0; i<nM; i++)
+                   styles[i]=addMaterial(M[i]);
+                 const uint32_t meshid =  createQuadMesh(nP, P, nI, PI, style, nN, N, NI, nT, T, TI, nC, C, CI, nM, styles, MI, ca);
+                 delete[] styles;
+                 return meshid;
+               }
+               else
+                 return createQuadMesh(nP, P, nI, PI, style, nN, N, NI, nT, T, TI, nC, C, CI, 0, NULL, NULL, ca);
+            }
+#define PRCTRANSFORM const double origin[3]=NULL, const double x_axis[3]=NULL, const double y_axis[3]=NULL, double scale=1, const double* t=NULL
+#define PRCCARTRANSFORM const double origin[3], const double x_axis[3], const double y_axis[3], double scale
+#define PRCGENTRANSFORM const double* t=NULL
+#define PRCNOMATERIALINDEX m1
+    void useMesh(uint32_t tess_index, uint32_t style_index,            PRCGENTRANSFORM);
+    void useMesh(uint32_t tess_index, const PRCmaterial& m,            PRCGENTRANSFORM)
+           { useMesh(tess_index,addMaterial(m),t); }
+    void useMesh(uint32_t tess_index, uint32_t style_index,            PRCCARTRANSFORM);
+    void useMesh(uint32_t tess_index, const PRCmaterial& m,            PRCCARTRANSFORM)
+           { useMesh(tess_index,addMaterial(m),origin, x_axis, y_axis, scale); }
+
+    void useLines(uint32_t tess_index, uint32_t style_index,           PRCGENTRANSFORM);
+    void useLines(uint32_t tess_index, const RGBAColour& c,  double w, PRCGENTRANSFORM)
+           { useLines(tess_index, addLineMaterial(c,w), t); }
+    void useLines(uint32_t tess_index, uint32_t style_index,           PRCCARTRANSFORM);
+    void useLines(uint32_t tess_index, const RGBAColour& c,  double w, PRCCARTRANSFORM)
+           { useLines(tess_index,addLineMaterial(c,w),origin, x_axis, y_axis, scale); }
+
+//  void addTriangle(const double P[][3], const double T[][2], uint32_t style_index);
+  
+    void addLine(uint32_t n, const double P[][3], const RGBAColour &c, double w=1.0);
+    void addSegment(const double P1[3], const double P2[3], const RGBAColour &c, double w=1.0);
+
+    void addBezierCurve(uint32_t n, const double cP[][3], const RGBAColour &c);
+    void addCurve(uint32_t d, uint32_t n, const double cP[][3], const double *k, const RGBAColour &c, const double w[]);
+    void addQuad(const double P[][3], const RGBAColour C[]);
+
+    void addRectangle(const double P[][3], const PRCmaterial &m);
+    void addPatch(const double cP[][3], const PRCmaterial &m);
+    void addSurface(uint32_t dU, uint32_t dV, uint32_t nU, uint32_t nV,
+     const double cP[][3], const double *kU, const double *kV, const PRCmaterial &m,
+     const double w[]);
+    void addTube(uint32_t n, const double cP[][3], const double oP[][3], bool straight, const PRCmaterial& m, PRCTRANSFORM);
+    void addHemisphere(double radius, const PRCmaterial& m, PRCTRANSFORM);
+    void addSphere(double radius, const PRCmaterial& m, PRCTRANSFORM);
+    void addDisk(double radius, const PRCmaterial& m, PRCTRANSFORM);
+    void addCylinder(double radius, double height, const PRCmaterial& m, PRCTRANSFORM);
+    void addCone(double radius, double height, const PRCmaterial& m, PRCTRANSFORM);
+    void addTorus(double major_radius, double minor_radius, double angle1, double angle2, const PRCmaterial& m, PRCTRANSFORM);
+#undef PRCTRANSFORM
+#undef PRCCARTRANSFORM
+#undef PRCGENTRANSFORM
+
+
+    uint32_t addPicture(EPRCPictureDataFormat format, uint32_t size, const uint8_t *picture, uint32_t width=0, uint32_t height=0,
+      std::string name="", uint32_t fileStructure=0)
+      { return fileStructures[fileStructure]->addPicture(format, size, picture, width, height, name); }
+
+#define ADD_ADDUNIQ( prctype ) \
+  uint32_t add##prctype(PRC##prctype*& p##prctype, uint32_t fileStructure=0) \
+  { return fileStructures[fileStructure]->add##prctype( p##prctype ); } \
+  uint32_t add##prctype##Unique(PRC##prctype*& p##prctype, uint32_t fileStructure=0) \
+  { return fileStructures[fileStructure]->add##prctype##Unique(p##prctype); }
+  
+  ADD_ADDUNIQ( TextureDefinition  )
+  ADD_ADDUNIQ( TextureApplication )
+  ADD_ADDUNIQ( MaterialGeneric    )
+  ADD_ADDUNIQ( Style              ) 
+#undef ADD_ADDUNIQ
+    uint32_t addRgbColor(double r, double g, double b,
+       uint32_t fileStructure=0)
+      {
+        return fileStructures[fileStructure]->addRgbColor(r, g, b);
+      }
+    uint32_t addRgbColorUnique(double r, double g, double b,
+       uint32_t fileStructure=0)
+      {
+        return fileStructures[fileStructure]->addRgbColorUnique(r, g, b);
+      }
+    uint32_t addPartDefinition(PRCPartDefinition*& pPartDefinition, uint32_t fileStructure=0)
+      {
+        return fileStructures[fileStructure]->addPartDefinition(pPartDefinition);
+      }
+    uint32_t addProductOccurrence(PRCProductOccurrence*& pProductOccurrence, uint32_t fileStructure=0)
+      {
+        return fileStructures[fileStructure]->addProductOccurrence(pProductOccurrence);
+      }
+    uint32_t addTopoContext(PRCTopoContext*& pTopoContext, uint32_t fileStructure=0)
+      {
+        return fileStructures[fileStructure]->addTopoContext(pTopoContext);
+      }
+    uint32_t getTopoContext(PRCTopoContext*& pTopoContext, uint32_t fileStructure=0)
+    {
+      return fileStructures[fileStructure]->getTopoContext(pTopoContext);
+    }
+    uint32_t add3DTess(PRC3DTess*& p3DTess, uint32_t fileStructure=0)
+      {
+        return fileStructures[fileStructure]->add3DTess(p3DTess);
+      }
+    uint32_t add3DWireTess(PRC3DWireTess*& p3DWireTess, uint32_t fileStructure=0)
+      {
+        return fileStructures[fileStructure]->add3DWireTess(p3DWireTess);
+      }
+/*
+    uint32_t addMarkupTess(PRCMarkupTess*& pMarkupTess, uint32_t fileStructure=0)
+      {
+        return fileStructures[fileStructure]->addMarkupTess(pMarkupTess);
+      }
+    uint32_t addMarkup(PRCMarkup*& pMarkup, uint32_t fileStructure=0)
+      {
+        return fileStructures[fileStructure]->addMarkup(pMarkup);
+      }
+    uint32_t addAnnotationItem(PRCAnnotationItem*& pAnnotationItem, uint32_t fileStructure=0)
+      {
+        return fileStructures[fileStructure]->addAnnotationItem(pAnnotationItem);
+      }
+ */
+    uint32_t addCoordinateSystem(PRCCoordinateSystem*& pCoordinateSystem, uint32_t fileStructure=0)
+      {
+        return fileStructures[fileStructure]->addCoordinateSystem(pCoordinateSystem);
+      }
+    uint32_t addCoordinateSystemUnique(PRCCoordinateSystem*& pCoordinateSystem, uint32_t fileStructure=0)
+      {
+        return fileStructures[fileStructure]->addCoordinateSystemUnique(pCoordinateSystem);
+      }
+  private:
+    void serializeModelFileData(PRCbitStream&);
+    std::ofstream *fout;
+    std::ostream &output;
+};
+
+#endif // __O_PRC_FILE_H
diff --git a/src/prc/writePRC.cc b/src/prc/writePRC.cc
new file mode 100644
index 0000000..098b4b7
--- /dev/null
+++ b/src/prc/writePRC.cc
@@ -0,0 +1,2097 @@
+/************
+*
+*   This file is part of a tool for producing 3D content in the PRC format.
+*   Copyright (C) 2008  Orest Shardt <shardtor (at) gmail dot com>
+*   with enhancements contributed by Michail Vidiassov.
+*
+*   This program is free software: you can redistribute it and/or modify
+*   it under the terms of the GNU Lesser General Public License as published by
+*   the Free Software Foundation, either version 3 of the License, or
+*   (at your option) any later version.
+*
+*   This program is distributed in the hope that it will be useful,
+*   but WITHOUT ANY WARRANTY; without even the implied warranty of
+*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*   GNU Lesser General Public License for more details.
+*
+*   You should have received a copy of the GNU Lesser General Public License
+*   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*
+*************/
+
+#include "writePRC.h"
+#include <climits>
+#include <cassert>
+
+// debug print includes
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <sstream>
+
+#if !defined(__GNUC__) || defined(__clang__)
+#include <vector>
+#endif
+
+#include <iterator>
+
+using namespace std;
+
+#ifndef __GNUC_PREREQ
+#define __GNUC_PREREQ(maj, min) (0)
+#endif
+
+// Count leading zeros.
+uint32_t CLZ(uint32_t a) 
+{
+#if __GNUC_PREREQ(3,4)
+  return __builtin_clz(a);
+#else
+// find the log base 2 of a 32-bit integer
+  static const int MultiplyDeBruijnBitPosition[32] = {
+    0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
+    8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
+  };
+
+  a |= a >> 1; // first round down to one less than a power of 2 
+  a |= a >> 2;
+  a |= a >> 4;
+  a |= a >> 8;
+  a |= a >> 16;
+
+  return 31-MultiplyDeBruijnBitPosition[(uint32_t)(a * 0x07C4ACDDU) >> 27];
+#endif
+}
+
+// Portable integer implementation of ceil(log2(x)).
+uint32_t Log2(uint32_t x) 
+{
+  assert(x != 0);
+  uint32_t L=31-CLZ(x);
+  return ((uint32_t) 1 << L == x) ? L : L+1;
+}
+
+#define WriteUnsignedInteger( value ) pbs << (uint32_t)(value);
+#define WriteInteger( value ) pbs << (int32_t)(value);
+#define WriteCharacter( value ) pbs << (uint8_t)(value);
+#define WriteDouble( value ) pbs << (double)(value);
+#define WriteBit( value ) pbs << (bool)(value);
+#define WriteBoolean( value ) pbs << (bool)(value);
+#define WriteString( value ) pbs << (value);
+#define SerializeContentPRCBase serializeContentPRCBase(pbs);
+#define SerializeGraphics serializeGraphics(pbs);
+#define SerializePRCBaseWithGraphics { serializeContentPRCBase(pbs); serializeGraphics(pbs); }
+#define SerializeRepresentationItemContent serializeRepresentationItemContent(pbs);
+#define SerializeRepresentationItem( value ) (value)->serializeRepresentationItem(pbs);
+#define SerializeMarkup( value ) (value).serializeMarkup(pbs);
+#define SerializeReferenceUniqueIdentifier( value ) (value).serializeReferenceUniqueIdentifier(pbs);
+#define SerializeContentBaseTessData serializeContentBaseTessData(pbs);
+#define SerializeTessFace( value ) (value)->serializeTessFace(pbs);
+#define SerializeUserData UserData(0,0).write(pbs);
+#define SerializeLineAttr( value ) pbs << (uint32_t)((value)+1);
+#define SerializeVector3d( value ) (value).serializeVector3d(pbs);
+#define SerializeVector2d( value ) (value).serializeVector2d(pbs);
+#define SerializeName( value ) writeName(pbs, (value));
+#define SerializeInterval( value )  (value).serializeInterval(pbs);
+// #define SerializeBoundingBox( value )  (value).serializeBoundingBox(pbs);
+#define SerializeDomain( value )  (value).serializeDomain(pbs);
+#define SerializeParameterization  serializeParameterization(pbs);
+#define SerializeUVParameterization  serializeUVParameterization(pbs);
+#define SerializeTransformation  serializeTransformation(pbs);
+#define SerializeBaseTopology  serializeBaseTopology(pbs);
+#define SerializeBaseGeometry  serializeBaseGeometry(pbs);
+#define SerializePtrCurve( value )    {WriteBoolean( false ); if((value)==NULL) pbs << (uint32_t)PRC_TYPE_ROOT; else (value)->serializeCurve(pbs);}
+#define SerializePtrSurface( value )  {WriteBoolean( false ); if((value)==NULL) pbs << (uint32_t)PRC_TYPE_ROOT; else (value)->serializeSurface(pbs);}
+#define SerializePtrTopology( value ) {WriteBoolean( false ); if((value)==NULL) pbs << (uint32_t)PRC_TYPE_ROOT; else (value)->serializeTopoItem(pbs);}
+#define SerializeContentCurve  serializeContentCurve(pbs);
+#define SerializeContentWireEdge  serializeContentWireEdge(pbs);
+#define SerializeContentBody  serializeContentBody(pbs);
+#define SerializeTopoContext  serializeTopoContext(pbs);
+#define SerializeContextAndBodies( value )  (value).serializeContextAndBodies(pbs);
+#define SerializeBody( value )  (value)->serializeBody(pbs);
+#define ResetCurrentGraphics resetGraphics();
+#define SerializeContentSurface  serializeContentSurface(pbs);
+#define SerializeCompressedUniqueId( value ) (value).serializeCompressedUniqueId(pbs);
+#define SerializeUnit( value ) (value).serializeUnit(pbs);
+#define SerializeBoundingBox serializeBoundingBox(pbs);
+#define SerializeAttributeEntry serializeAttributeEntry(pbs);
+#define SerializeContentSingleAttribute( value ) (value).serializeSingleAttribute(pbs);
+#define SerializeAttribute( value ) (value).serializeAttribute(pbs);
+#define SerializeAttributeData serializeAttributes(pbs);
+#define WriteUncompressedUnsignedInteger( value ) writeUncompressedUnsignedInteger(out, (uint32_t)(value));
+#define SerializeFileStructureUncompressedUniqueId( value ) (value).serializeFileStructureUncompressedUniqueId(out);
+
+void writeUncompressedUnsignedInteger(ostream &out, uint32_t data)
+{
+#ifdef WORDS_BIGENDIAN
+  out.write(((char*)&data)+3,1);
+  out.write(((char*)&data)+2,1);
+  out.write(((char*)&data)+1,1);
+  out.write(((char*)&data)+0,1);
+#else
+  out.write(((char*)&data)+0,1);
+  out.write(((char*)&data)+1,1);
+  out.write(((char*)&data)+2,1);
+  out.write(((char*)&data)+3,1);
+#endif
+}
+
+double PRCVector3d::Length()
+{
+  return sqrt(x*x+y*y+z*z);
+}
+
+bool PRCVector3d::Normalize()
+{
+ double fLength=Length();
+ if(fLength < FLT_EPSILON) return false;
+ double factor=1.0/fLength;
+ x *= factor;
+ y *= factor;
+ z *= factor;
+ return true;
+}
+
+double PRCVector2d::Length()
+{
+  return sqrt(x*x+y*y);
+}
+
+bool PRCVector2d::Normalize()
+{
+  double fLength=Length();
+  if(fLength < FLT_EPSILON) return false;
+  double factor=1.0/fLength;
+  x *= factor;
+  y *= factor;
+
+  return true;
+}
+
+void PRCVector2d::serializeVector2d(PRCbitStream &pbs)
+{
+  WriteDouble (x)
+  WriteDouble (y)
+}
+
+uint32_t makeCADID()
+{
+  static uint32_t ID = 1;
+  return ID++;
+}
+
+uint32_t makePRCID()
+{
+  static uint32_t ID = 1;
+  return ID++;
+}
+
+bool type_eligible_for_reference(uint32_t type)
+{
+  if(
+     type == PRC_TYPE_MISC_EntityReference ||
+     type == PRC_TYPE_MISC_MarkupLinkedItem ||
+     type == PRC_TYPE_RI_BrepModel ||
+     type == PRC_TYPE_RI_Curve ||
+     type == PRC_TYPE_RI_Direction ||
+     type == PRC_TYPE_RI_Plane ||
+     type == PRC_TYPE_RI_PointSet ||
+     type == PRC_TYPE_RI_PolyBrepModel ||
+     type == PRC_TYPE_RI_PolyWire ||
+     type == PRC_TYPE_RI_Set ||
+     type == PRC_TYPE_RI_CoordinateSystem ||
+     type == PRC_TYPE_ASM_ProductOccurence ||
+     type == PRC_TYPE_ASM_PartDefinition ||
+     type == PRC_TYPE_ASM_Filter ||
+     type == PRC_TYPE_MKP_View ||
+     type == PRC_TYPE_MKP_Markup ||
+     type == PRC_TYPE_MKP_Leader ||
+     type == PRC_TYPE_MKP_AnnotationItem ||
+     type == PRC_TYPE_MKP_AnnotationSet ||
+     type == PRC_TYPE_MKP_AnnotationReference ||
+     type == PRC_TYPE_GRAPH_Style ||
+     type == PRC_TYPE_GRAPH_Material ||
+     type == PRC_TYPE_GRAPH_TextureApplication ||
+     type == PRC_TYPE_GRAPH_TextureDefinition ||
+     type == PRC_TYPE_GRAPH_LinePattern ||
+     type == PRC_TYPE_GRAPH_DottingPattern ||
+     type == PRC_TYPE_GRAPH_HatchingPattern ||
+     type == PRC_TYPE_GRAPH_SolidPattern ||
+     type == PRC_TYPE_GRAPH_VPicturePattern ||
+     type == PRC_TYPE_GRAPH_AmbientLight ||
+     type == PRC_TYPE_GRAPH_PointLight ||
+     type == PRC_TYPE_GRAPH_DirectionalLight ||
+     type == PRC_TYPE_GRAPH_SpotLight ||
+     type == PRC_TYPE_GRAPH_SceneDisplayParameters ||
+     type == PRC_TYPE_GRAPH_Camera
+    )
+    return true;
+  else
+    return false;
+}
+
+void UserData::write(PRCbitStream &pbs)
+{
+  pbs << size;
+  if(size > 0) {
+    uint32_t quot=size/8;
+    uint32_t rem=size-8*quot;
+    for(uint32_t i = 0; i < quot; ++i)
+      pbs << data[i];
+    for(uint32_t j = 0; j < rem; ++j) // 0-based, big endian bit counting
+      pbs << (bool)((data[quot] & (0x80 >> j))!=0);
+  }
+}
+
+void PRCAttributeEntry::serializeAttributeEntry(PRCbitStream &pbs) const
+{
+  WriteBoolean (title_is_integer) 
+  if (title_is_integer)
+    WriteUnsignedInteger (title_integer)
+  else	
+    WriteString (title_text)
+}
+
+void PRCSingleAttribute::serializeSingleAttribute(PRCbitStream &pbs) const
+{
+  SerializeAttributeEntry
+  WriteUnsignedInteger (type)
+  switch (type)
+  {
+    case KEPRCModellerAttributeTypeInt:
+      WriteInteger (value.integer)
+      break;
+    case KEPRCModellerAttributeTypeReal:
+      WriteDouble (value.real)
+      break;
+    case KEPRCModellerAttributeTypeTime:
+      WriteUnsignedInteger (value.time)
+      break;
+    case KEPRCModellerAttributeTypeString:
+      WriteString (value_text)
+      break; 
+    default:
+      break;
+  }
+}
+
+void PRCAttribute::serializeAttribute(PRCbitStream &pbs) const
+{
+  WriteUnsignedInteger (PRC_TYPE_MISC_Attribute) 
+  
+  SerializeAttributeEntry
+  const uint32_t size_of_attribute_keys = attribute_keys.size();
+  WriteUnsignedInteger (size_of_attribute_keys) 
+  for(uint32_t i=0;i<size_of_attribute_keys;i++) 
+    SerializeContentSingleAttribute (attribute_keys[i]) 
+}
+
+void PRCAttributes::serializeAttributes(PRCbitStream &pbs) const
+{
+  if (attributes.empty()) { // shortcut for most typical case
+    const uint32_t number_of_attributes = 0;
+    WriteUnsignedInteger (number_of_attributes) 
+    return;
+  }
+  const uint32_t number_of_attributes = attributes.size();
+  WriteUnsignedInteger (number_of_attributes) 
+  for(PRCAttributeList::const_iterator it = attributes.begin(); it != attributes.end(); ++it)
+  {
+    SerializeAttribute(*it)
+  }
+}
+
+void ContentPRCBase::serializeContentPRCBase(PRCbitStream &pbs) const
+{
+  SerializeAttributeData
+
+  SerializeName (name)
+  if (type_eligible_for_reference(type))
+  {
+    WriteUnsignedInteger (CAD_identifier)
+    WriteUnsignedInteger (CAD_persistent_identifier)
+    WriteUnsignedInteger (PRC_unique_identifier)
+  }
+}
+
+
+bool IsCompressedType(uint32_t type)
+{
+  return (type == PRC_TYPE_TOPO_BrepDataCompress || type == PRC_TYPE_TOPO_SingleWireBodyCompress || type == PRC_TYPE_TESS_3D_Compressed);
+}
+
+void PRCReferenceUniqueIdentifier::serializeReferenceUniqueIdentifier(PRCbitStream &pbs)
+{
+  WriteUnsignedInteger (PRC_TYPE_MISC_ReferenceOnPRCBase)
+  WriteUnsignedInteger (type)
+  const bool reference_in_same_file_structure = true;
+  WriteBoolean (reference_in_same_file_structure)
+// if (!reference_in_same_file_structure)
+//    SerializeCompressedUniqueId (target_file_structure)
+  WriteUnsignedInteger (unique_identifier)
+}
+
+void PRCUncompressedFile::serializeUncompressedFile(ostream &out) const
+{
+  WriteUncompressedUnsignedInteger (file_contents.size())
+  std::ostream_iterator<uint8_t> out_it (out);
+  copy ( file_contents.begin(), file_contents.end(), out_it );
+}
+
+uint32_t PRCUncompressedFile::getSize() const
+{
+  return sizeof(uint32_t)+file_contents.size();
+}
+
+void PRCRgbColor::serializeRgbColor(PRCbitStream &pbs)
+{
+  WriteDouble (red)
+  WriteDouble (green)
+  WriteDouble (blue)
+}
+
+void PRCPicture::serializePicture(PRCbitStream &pbs)
+{
+  WriteUnsignedInteger (PRC_TYPE_GRAPH_Picture)
+  SerializeContentPRCBase
+  WriteInteger (format) //see Types for picture files
+  WriteUnsignedInteger (uncompressed_file_index+1)
+  WriteUnsignedInteger (pixel_width)
+  WriteUnsignedInteger (pixel_height)
+}
+
+void PRCTextureDefinition::serializeTextureDefinition(PRCbitStream &pbs)
+{
+  uint32_t i=0; // universal index for PRC standart compatibility
+  const uint8_t texture_dimension = 2;
+  const uint32_t texture_mapping_attributes = texture_mapping_attribute;
+  const uint32_t size_texture_mapping_attributes_intensities = 1;
+  const double *texture_mapping_attributes_intensities = &texture_mapping_attribute_intensity;
+  const uint32_t size_texture_mapping_attributes_components = 1;
+  const uint8_t *texture_mapping_attributes_components = &texture_mapping_attribute_components;
+  const EPRCTextureMappingType eMappingType = KEPRCTextureMappingType_Stored;
+  
+  const double red = 1.0;
+  const double green = 1.0;
+  const double blue = 1.0;
+  const double alpha = 1.0;
+  const EPRCTextureBlendParameter blend_src_rgb = KEPRCTextureBlendParameter_Unknown;
+  const EPRCTextureBlendParameter blend_dst_rgb = KEPRCTextureBlendParameter_Unknown;
+  const EPRCTextureBlendParameter blend_src_alpha = KEPRCTextureBlendParameter_Unknown;
+  const EPRCTextureBlendParameter blend_dst_alpha = KEPRCTextureBlendParameter_Unknown;
+  const EPRCTextureAlphaTest alpha_test = KEPRCTextureAlphaTest_Unknown;
+  const double alpha_test_reference = 1.0;
+  const EPRCTextureWrappingMode texture_wrapping_mode_R = KEPRCTextureWrappingMode_ClampToBorder;
+  const bool texture_transformation = false;
+
+  WriteUnsignedInteger (PRC_TYPE_GRAPH_TextureDefinition)
+
+  SerializeContentPRCBase
+
+  WriteUnsignedInteger (picture_index+1) 
+  WriteCharacter (texture_dimension) 
+
+  //   SerializeTextureMappingType
+  WriteInteger (eMappingType) // Texture mapping type
+  //  if (eMappingType == TEXTURE_MAPPING_OPERATOR)
+  //  {
+  //     WriteInteger (eMappingOperator) // Texture mapping operator
+  //     WriteInteger (transformation)
+  //     if (transformation)
+  //        SerializeCartesianTransformation3d (transformation) 
+  //  }
+
+  WriteUnsignedInteger (texture_mapping_attributes) // Texture mapping attributes 
+  WriteUnsignedInteger (size_texture_mapping_attributes_intensities)
+  for (i=0;i<size_texture_mapping_attributes_intensities;i++)
+     WriteDouble (texture_mapping_attributes_intensities[i])
+  WriteUnsignedInteger (size_texture_mapping_attributes_components)
+  for (i=0;i<size_texture_mapping_attributes_components;i++)
+     WriteCharacter (texture_mapping_attributes_components[i]) 
+
+  WriteInteger (texture_function)
+  // reserved for future use; see Texture function 
+  if (texture_function == KEPRCTextureFunction_Blend)
+  {
+     WriteDouble (red) // blend color component in the range [0.0,1.0]
+     WriteDouble (green) // blend color component in the range [0.0,1.0]
+     WriteDouble (blue) // blend color component in the range [0.0,1.0]
+     WriteDouble (alpha) // blend color component in the range [0.0,1.0]
+  }
+
+  WriteInteger (blend_src_rgb) // Texture blend parameter 
+  // reserved for future use; see Texture blend parameter 
+  if (blend_src_rgb != KEPRCTextureBlendParameter_Unknown)
+     WriteInteger (blend_dst_rgb) // Texture blend parameter 
+
+  WriteInteger (blend_src_alpha) // Texture blend parameter 
+  // reserved for future use; see Texture blend parameter 
+  if (blend_src_alpha != KEPRCTextureBlendParameter_Unknown)
+     WriteInteger (blend_dst_alpha) // Texture blend parameter 
+
+  WriteCharacter (texture_applying_mode) // Texture applying mode 
+  if (texture_applying_mode & PRC_TEXTURE_APPLYING_MODE_ALPHATEST)
+  {
+     WriteInteger (alpha_test) // Texture alpha test 
+     WriteDouble (alpha_test_reference)
+  }
+
+  WriteInteger (texture_wrapping_mode_S) // Texture wrapping mode
+  if (texture_dimension > 1)
+     WriteInteger (texture_wrapping_mode_T) // Texture wrapping mode
+  if (texture_dimension > 2 )
+     WriteInteger (texture_wrapping_mode_R) // Texture wrapping mode
+
+  WriteBit (texture_transformation)
+//  if (texture_transformation)
+//     SerializeTextureTransformation (texture_transformation)
+}
+
+void PRCMaterialGeneric::serializeMaterialGeneric(PRCbitStream &pbs)
+{
+  WriteUnsignedInteger (PRC_TYPE_GRAPH_Material)
+  SerializeContentPRCBase
+  WriteUnsignedInteger (ambient + 1)
+  WriteUnsignedInteger (diffuse + 1)
+  WriteUnsignedInteger (emissive + 1)
+  WriteUnsignedInteger (specular + 1)
+  WriteDouble (shininess)
+  WriteDouble (ambient_alpha)
+  WriteDouble (diffuse_alpha)
+  WriteDouble (emissive_alpha)
+  WriteDouble (specular_alpha)
+}
+
+void PRCTextureApplication::serializeTextureApplication(PRCbitStream &pbs) 
+{
+  WriteUnsignedInteger (PRC_TYPE_GRAPH_TextureApplication)
+  SerializeContentPRCBase
+
+  WriteUnsignedInteger (material_generic_index+1) 
+  WriteUnsignedInteger (texture_definition_index+1) 
+  WriteUnsignedInteger (next_texture_index+1) 
+  WriteUnsignedInteger (UV_coordinates_index+1)
+}
+
+void PRCLinePattern::serializeLinePattern(PRCbitStream &pbs)
+{
+  uint32_t i = 0;
+  WriteUnsignedInteger (PRC_TYPE_GRAPH_LinePattern)
+  SerializeContentPRCBase
+  
+  const uint32_t size_lengths = lengths.size();
+  WriteUnsignedInteger (size_lengths)
+  for (i=0;i<size_lengths;i++)
+    WriteDouble (lengths[i])
+  WriteDouble (phase)
+  WriteBoolean (is_real_length)
+}
+
+
+void PRCStyle::serializeCategory1LineStyle(PRCbitStream &pbs)
+{
+  const bool is_additional_1_defined = (additional!=0);
+  const uint8_t additional_1 = additional;
+  const bool is_additional_2_defined = false;
+  const uint8_t additional_2 = 0;
+  const bool is_additional_3_defined = false;
+  const uint8_t additional_3 = 0;
+  WriteUnsignedInteger (PRC_TYPE_GRAPH_Style)
+  SerializeContentPRCBase
+  WriteDouble (line_width)
+  WriteBoolean (is_vpicture)
+  WriteUnsignedInteger (line_pattern_vpicture_index + 1)
+  WriteBoolean (is_material)
+  WriteUnsignedInteger (color_material_index + 1)
+  WriteBoolean (is_transparency_defined)
+  if (is_transparency_defined)
+     WriteCharacter (transparency)
+  WriteBoolean (is_additional_1_defined)
+  if (is_additional_1_defined)
+     WriteCharacter (additional_1)
+  WriteBoolean (is_additional_2_defined)
+  if (is_additional_2_defined)
+     WriteCharacter (additional_2)
+  WriteBoolean (is_additional_3_defined)
+  if (is_additional_3_defined)
+     WriteCharacter (additional_3)
+}
+
+std::string currentName;
+
+void writeName(PRCbitStream &pbs,const std::string &name)
+{
+  pbs << (name == currentName);
+  if(name != currentName)
+  {
+    pbs << name;
+    currentName = name;
+  }
+}
+
+void resetName()
+{
+  currentName = "";
+}
+
+uint32_t current_layer_index = m1;
+uint32_t current_index_of_line_style = m1;
+uint16_t current_behaviour_bit_field = 1;
+
+void writeGraphics(PRCbitStream &pbs,uint32_t l,uint32_t i,uint16_t b,bool force)
+{
+  if(force || current_layer_index != l || current_index_of_line_style != i || current_behaviour_bit_field != b)
+  {
+    pbs << false << (uint32_t)(l+1) << (uint32_t)(i+1)
+        << (uint8_t)(b&0xFF) << (uint8_t)((b>>8)&0xFF);
+    current_layer_index = l;
+    current_index_of_line_style = i;
+    current_behaviour_bit_field = b;
+  }
+  else
+    pbs << true;
+}
+
+void writeGraphics(PRCbitStream &pbs,const PRCGraphics &graphics,bool force)
+{
+  if(force || current_layer_index != graphics.layer_index || current_index_of_line_style != graphics.index_of_line_style || current_behaviour_bit_field != graphics.behaviour_bit_field)
+  {
+    pbs << false
+        << (uint32_t)(graphics.layer_index+1)
+        << (uint32_t)(graphics.index_of_line_style+1)
+        << (uint8_t)(graphics.behaviour_bit_field&0xFF)
+        << (uint8_t)((graphics.behaviour_bit_field>>8)&0xFF);
+    current_layer_index = graphics.layer_index;
+    current_index_of_line_style = graphics.index_of_line_style;
+    current_behaviour_bit_field = graphics.behaviour_bit_field;
+  }
+  else
+    pbs << true;
+}
+
+void PRCGraphics::serializeGraphics(PRCbitStream &pbs)
+{
+  if(current_layer_index != this->layer_index || current_index_of_line_style != this->index_of_line_style || current_behaviour_bit_field != this->behaviour_bit_field)
+  {
+    pbs << false
+        << (uint32_t)(this->layer_index+1)
+        << (uint32_t)(this->index_of_line_style+1)
+        << (uint8_t)(this->behaviour_bit_field&0xFF)
+        << (uint8_t)((this->behaviour_bit_field>>8)&0xFF);
+    current_layer_index = this->layer_index;
+    current_index_of_line_style = this->index_of_line_style;
+    current_behaviour_bit_field = this->behaviour_bit_field;
+  }
+  else
+    pbs << true;
+}
+
+void PRCGraphics::serializeGraphicsForced(PRCbitStream &pbs)
+{
+  pbs << false
+      << (uint32_t)(this->layer_index+1)
+      << (uint32_t)(this->index_of_line_style+1)
+      << (uint8_t)(this->behaviour_bit_field&0xFF)
+      << (uint8_t)((this->behaviour_bit_field>>8)&0xFF);
+  current_layer_index = this->layer_index;
+  current_index_of_line_style = this->index_of_line_style;
+  current_behaviour_bit_field = this->behaviour_bit_field;
+}
+
+void resetGraphics()
+{
+  current_layer_index = m1;
+  current_index_of_line_style = m1;
+  current_behaviour_bit_field = 1;
+}
+
+void resetGraphicsAndName()
+{
+  resetGraphics(); resetName();
+}
+
+void  PRCMarkup::serializeMarkup(PRCbitStream &pbs)
+{
+  WriteUnsignedInteger (PRC_TYPE_MKP_Markup)
+  SerializeContentPRCBase 
+  SerializeGraphics
+  WriteUnsignedInteger (type) 
+  WriteUnsignedInteger (sub_type) 
+  const uint32_t number_of_linked_items = 0;
+  WriteUnsignedInteger (number_of_linked_items) 
+//  for (i=0;i<number_of_linked_items;i++) 
+//     SerializeReferenceUniqueIdentifier (linked_items[i])
+  const uint32_t number_of_leaders = 0;
+  WriteUnsignedInteger (number_of_leaders) 
+//  for (i=0;i<number_of_leaders;i++) 
+//     SerializeReferenceUniqueIdentifier (leaders[i])
+  WriteUnsignedInteger (index_tessellation + 1) 
+  SerializeUserData
+}
+
+void  PRCAnnotationItem::serializeAnnotationItem(PRCbitStream &pbs)
+{
+// group___tf_annotation_item_____serialize2.html
+// group___tf_annotation_item_____serialize_content2.html
+// group___tf_annotation_entity_____serialize_content2.html
+  WriteUnsignedInteger (PRC_TYPE_MKP_AnnotationItem)
+  SerializeContentPRCBase 
+  SerializeGraphics
+  SerializeReferenceUniqueIdentifier (markup)
+  SerializeUserData
+}
+
+void  PRCRepresentationItemContent::serializeRepresentationItemContent(PRCbitStream &pbs)
+{
+  SerializeContentPRCBase 
+  SerializeGraphics
+  WriteUnsignedInteger (index_local_coordinate_system + 1)
+  WriteUnsignedInteger (index_tessellation + 1)
+}
+
+void  PRCBrepModel::serializeBrepModel(PRCbitStream &pbs)
+{
+   WriteUnsignedInteger (PRC_TYPE_RI_BrepModel)
+
+   SerializeRepresentationItemContent 
+   WriteBit (has_brep_data)
+   if (has_brep_data)
+   {
+      WriteUnsignedInteger (context_id+1)
+      WriteUnsignedInteger (body_id+1)
+   }
+   WriteBoolean (is_closed)
+   SerializeUserData
+}
+
+void  PRCPolyBrepModel::serializePolyBrepModel(PRCbitStream &pbs)
+{
+   WriteUnsignedInteger (PRC_TYPE_RI_PolyBrepModel)
+
+   SerializeRepresentationItemContent 
+   WriteBoolean (is_closed)
+   SerializeUserData
+}
+
+void  PRCPointSet::serializePointSet(PRCbitStream &pbs)
+{
+  WriteUnsignedInteger (PRC_TYPE_RI_PointSet)
+
+  SerializeRepresentationItemContent 
+
+  const uint32_t number_of_points = point.size();
+  WriteUnsignedInteger (number_of_points)
+  for (uint32_t i=0;i<number_of_points;i++)
+  {
+     SerializeVector3d (point[i])
+  }
+  SerializeUserData
+}
+
+void  PRCSet::serializeSet(PRCbitStream &pbs)
+{
+  WriteUnsignedInteger (PRC_TYPE_RI_Set)
+
+  SerializeRepresentationItemContent 
+
+  const uint32_t number_of_elements = elements.size();
+  WriteUnsignedInteger (number_of_elements)
+  for (uint32_t i=0;i<number_of_elements;i++)
+  {
+    SerializeRepresentationItem (elements[i])
+  }
+  SerializeUserData
+}
+
+uint32_t PRCSet::addBrepModel(PRCBrepModel*& pBrepModel)
+{
+  elements.push_back(pBrepModel);
+  pBrepModel = NULL;
+  return elements.size()-1;
+}
+
+uint32_t PRCSet::addPolyBrepModel(PRCPolyBrepModel*& pPolyBrepModel)
+{
+  elements.push_back(pPolyBrepModel);
+  pPolyBrepModel = NULL;
+  return elements.size()-1;
+}
+
+uint32_t PRCSet::addPointSet(PRCPointSet*& pPointSet)
+{
+  elements.push_back(pPointSet);
+  pPointSet  = NULL;
+  return elements.size()-1;
+}
+
+uint32_t PRCSet::addSet(PRCSet*& pSet)
+{
+  elements.push_back(pSet);
+  pSet = NULL;
+  return elements.size()-1;
+}
+
+uint32_t PRCSet::addWire(PRCWire*& pWire)
+{
+  elements.push_back(pWire);
+  pWire = NULL;
+  return elements.size()-1;
+}
+
+uint32_t PRCSet::addPolyWire(PRCPolyWire*& pPolyWire)
+{
+  elements.push_back(pPolyWire);
+  pPolyWire = NULL;
+  return elements.size()-1;
+}
+
+uint32_t PRCSet::addRepresentationItem(PRCRepresentationItem*& pRepresentationItem)
+{
+  elements.push_back(pRepresentationItem);
+  pRepresentationItem = NULL;
+  return elements.size()-1;
+}
+
+void  PRCWire::serializeWire(PRCbitStream &pbs)
+{
+   WriteUnsignedInteger (PRC_TYPE_RI_Curve)
+
+   SerializeRepresentationItemContent 
+   WriteBit (has_wire_body)
+   if (has_wire_body)
+   {
+      WriteUnsignedInteger (context_id+1)
+      WriteUnsignedInteger (body_id+1)
+   }
+
+   SerializeUserData
+}
+
+void  PRCPolyWire::serializePolyWire(PRCbitStream &pbs)
+{
+  WriteUnsignedInteger (PRC_TYPE_RI_PolyWire)
+
+  SerializeRepresentationItemContent 
+  SerializeUserData
+}
+
+void  PRCGeneralTransformation3d::serializeGeneralTransformation3d(PRCbitStream &pbs) const
+{
+  WriteUnsignedInteger (PRC_TYPE_MISC_GeneralTransformation)
+  for (uint32_t i=0; i<16; i++)
+     WriteDouble(m_coef[i]); 
+}
+
+void  PRCCartesianTransformation3d::serializeCartesianTransformation3d(PRCbitStream &pbs) const
+{
+  WriteUnsignedInteger (PRC_TYPE_MISC_CartesianTransformation)
+  WriteCharacter ( behaviour )
+  if (behaviour & PRC_TRANSFORMATION_Translate)
+     SerializeVector3d ( origin )
+  if (behaviour & PRC_TRANSFORMATION_NonOrtho)
+  {
+     SerializeVector3d ( X )
+     SerializeVector3d ( Y )
+     SerializeVector3d ( Z )
+  }
+  else if (behaviour & PRC_TRANSFORMATION_Rotate)
+  {
+     SerializeVector3d ( X )
+     SerializeVector3d ( Y )
+  }
+
+  if (behaviour & PRC_TRANSFORMATION_NonUniformScale)
+  {
+        SerializeVector3d ( scale )
+  }
+  else if (behaviour & PRC_TRANSFORMATION_Scale)
+  {
+        WriteDouble ( uniform_scale )
+  }
+
+  if (behaviour & PRC_TRANSFORMATION_Homogeneous)
+  {
+     WriteDouble ( X_homogeneous_coord )
+     WriteDouble ( Y_homogeneous_coord )
+     WriteDouble ( Z_homogeneous_coord )
+     WriteDouble ( origin_homogeneous_coord )
+  }
+}
+
+void  PRCTransformation::serializeTransformation(PRCbitStream &pbs)
+{ 
+   WriteBit ( has_transformation )
+   if (has_transformation)
+   {
+      WriteCharacter ( behaviour )
+      if ( geometry_is_2D )
+      {
+         if (behaviour & PRC_TRANSFORMATION_Translate)
+            SerializeVector2d ( origin )
+         if (behaviour & PRC_TRANSFORMATION_Rotate)
+         {
+            SerializeVector2d ( x_axis )
+            SerializeVector2d ( y_axis )
+         }
+         if (behaviour & PRC_TRANSFORMATION_Scale)
+            WriteDouble ( scale )
+      }
+      else
+      {
+         if (behaviour & PRC_TRANSFORMATION_Translate)
+            SerializeVector3d ( origin )
+         if (behaviour & PRC_TRANSFORMATION_Rotate)
+         {
+            SerializeVector3d ( x_axis )
+            SerializeVector3d ( y_axis )
+         }
+         if (behaviour & PRC_TRANSFORMATION_Scale)
+            WriteDouble ( scale )
+      }
+   }
+}
+void  PRCCoordinateSystem::serializeCoordinateSystem(PRCbitStream &pbs)
+{
+  WriteUnsignedInteger (PRC_TYPE_RI_CoordinateSystem)
+
+  SerializeRepresentationItemContent 
+  axis_set->serializeTransformation3d(pbs);
+  SerializeUserData
+}
+
+void  PRCFontKeysSameFont::serializeFontKeysSameFont(PRCbitStream &pbs)
+{
+  uint32_t i=0; // universal index for PRC standart compatibility
+  WriteString (font_name)
+  WriteUnsignedInteger (char_set)
+  const uint32_t number_of_font_keys = font_keys.size();
+  WriteUnsignedInteger (number_of_font_keys)
+  for (i=0;i<number_of_font_keys;i++)
+  {
+     WriteUnsignedInteger (font_keys[i].font_size + 1)
+     WriteCharacter (font_keys[i].attributes)
+  }
+}
+
+void SerializeArrayRGBA (const std::vector<uint8_t> &rgba_vertices,const bool is_rgba, PRCbitStream &pbs)
+{
+  uint32_t i = 0;
+  uint32_t j = 0;
+// number_by_vector can be assigned a value of 3 (RGB) or 4 (RGBA).
+// number_of_vectors is equal to number_of_colors / number_by_vector.
+  const uint32_t number_by_vector=is_rgba?4:3;
+  const std::vector<uint8_t> &vector_color = rgba_vertices;
+  const uint32_t number_of_colors=vector_color.size();
+  const uint32_t number_of_vectors=number_of_colors / number_by_vector;
+  // first one 
+  for (i=0;i<number_by_vector;i++)
+     WriteCharacter (vector_color[i])
+  
+  for (i=1;i<number_of_vectors;i++)
+  {
+     bool b_same = true;
+     for (j=0;j<number_by_vector;j++)
+     {
+        if ((vector_color[i*number_by_vector+j] - vector_color[(i-1)*number_by_vector+j]) != 0)
+        {
+           b_same = false;
+           break;
+        }
+     }
+     WriteBoolean (b_same)
+     if (!b_same)
+     {
+        for (j=0;j<number_by_vector;j++)
+           WriteCharacter (vector_color[i*number_by_vector+j])
+     }
+  }
+}
+
+void  PRCTessFace::serializeTessFace(PRCbitStream &pbs)
+{
+  uint32_t i=0; // universal index for PRC standart compatibility
+  WriteUnsignedInteger (PRC_TYPE_TESS_Face)
+
+  const uint32_t size_of_line_attributes=line_attributes.size();
+  WriteUnsignedInteger (size_of_line_attributes) 
+  for (i=0;i<size_of_line_attributes;i++) 
+     SerializeLineAttr (line_attributes[i])
+
+  WriteUnsignedInteger (start_wire) 
+  const uint32_t size_of_sizes_wire=sizes_wire.size();
+  WriteUnsignedInteger (size_of_sizes_wire) 
+  for (i=0;i<size_of_sizes_wire;i++) 
+     WriteUnsignedInteger (sizes_wire[i])
+
+  WriteUnsignedInteger (used_entities_flag) 
+
+  WriteUnsignedInteger (start_triangulated) 
+  const uint32_t size_of_sizes_triangulated=sizes_triangulated.size();
+  WriteUnsignedInteger (size_of_sizes_triangulated) 
+  for (i=0;i<size_of_sizes_triangulated;i++) 
+     WriteUnsignedInteger (sizes_triangulated[i])
+
+  if(number_of_texture_coordinate_indexes==0 &&
+     used_entities_flag &
+     (
+      PRC_FACETESSDATA_PolyfaceTextured|
+      PRC_FACETESSDATA_TriangleTextured|
+      PRC_FACETESSDATA_TriangleFanTextured|
+      PRC_FACETESSDATA_TriangleStripeTextured|
+      PRC_FACETESSDATA_PolyfaceOneNormalTextured|
+      PRC_FACETESSDATA_TriangleOneNormalTextured|
+      PRC_FACETESSDATA_TriangleFanOneNormalTextured|
+      PRC_FACETESSDATA_TriangleStripeOneNormalTextured
+     ))
+    WriteUnsignedInteger (1)  // workaround for error of not setting number_of_texture_coordinate_indexes
+  else 
+    WriteUnsignedInteger (number_of_texture_coordinate_indexes)
+
+  const bool has_vertex_colors = !rgba_vertices.empty();
+  WriteBoolean (has_vertex_colors)
+  if (has_vertex_colors)
+  {
+     WriteBoolean (is_rgba)
+     const bool b_optimised=false;
+     WriteBoolean (b_optimised)
+     if (!b_optimised)
+     {
+       SerializeArrayRGBA (rgba_vertices, is_rgba, pbs);
+     }
+     else
+     {
+     // not described
+     }
+  }
+  if (size_of_line_attributes) 
+     WriteUnsignedInteger (behaviour)
+}
+
+void  PRCContentBaseTessData::serializeContentBaseTessData(PRCbitStream &pbs)
+{
+  uint32_t i=0; // universal index for PRC standart compatibility
+  WriteBoolean (is_calculated)
+  const uint32_t number_of_coordinates = coordinates.size();
+  WriteUnsignedInteger (number_of_coordinates)
+  for (i=0;i<number_of_coordinates;i++)
+     WriteDouble (coordinates[i])
+}
+
+void  PRC3DTess::serialize3DTess(PRCbitStream &pbs)
+{
+  uint32_t i=0; // universal index for PRC standart compatibility
+  WriteUnsignedInteger (PRC_TYPE_TESS_3D)
+  SerializeContentBaseTessData 
+  WriteBoolean (has_faces)
+  WriteBoolean (has_loops)
+  const bool must_recalculate_normals=normal_coordinate.empty();
+  WriteBoolean (must_recalculate_normals)
+  if (must_recalculate_normals)
+  {
+     const uint8_t normals_recalculation_flags=0;
+     // not used; should be zero
+     WriteCharacter (normals_recalculation_flags)
+     // definition similar to VRML
+     WriteDouble (crease_angle)
+  }
+  
+  const uint32_t number_of_normal_coordinates=normal_coordinate.size();
+  WriteUnsignedInteger (number_of_normal_coordinates)
+  for (i=0;i<number_of_normal_coordinates;i++)
+     WriteDouble (normal_coordinate[i])
+  
+  const uint32_t number_of_wire_indices=wire_index.size();
+  WriteUnsignedInteger (number_of_wire_indices)
+  for (i=0;i<number_of_wire_indices;i++)
+     WriteUnsignedInteger (wire_index[i])
+  
+  // note : those can be single triangles, triangle fans or stripes
+  const uint32_t number_of_triangulated_indices=triangulated_index.size();
+  WriteUnsignedInteger (number_of_triangulated_indices)
+  for (i=0;i<number_of_triangulated_indices;i++)
+     WriteUnsignedInteger (triangulated_index[i])
+  
+  const uint32_t number_of_face_tessellation=face_tessellation.size();
+  WriteUnsignedInteger (number_of_face_tessellation)
+  for (i=0;i<number_of_face_tessellation;i++)
+     SerializeTessFace (face_tessellation[i])
+  
+  const uint32_t number_of_texture_coordinates=texture_coordinate.size();
+  WriteUnsignedInteger (number_of_texture_coordinates)
+  for (i=0;i<number_of_texture_coordinates;i++)
+     WriteDouble (texture_coordinate[i])
+}
+
+void PRC3DTess::addTessFace(PRCTessFace*& pTessFace)
+{
+  face_tessellation.push_back(pTessFace);
+  pTessFace = NULL;
+}
+
+void  PRC3DWireTess::serialize3DWireTess(PRCbitStream &pbs)
+{
+// group___tf3_d_wire_tess_data_____serialize2.html
+// group___tf3_d_wire_tess_data_____serialize_content2.html
+  uint32_t i=0; // universal index for PRC standart compatibility
+  WriteUnsignedInteger (PRC_TYPE_TESS_3D_Wire)
+  SerializeContentBaseTessData 
+  const uint32_t number_of_wire_indexes=wire_indexes.size();
+  WriteUnsignedInteger (number_of_wire_indexes)
+  for (i=0;i<number_of_wire_indexes;i++)
+     WriteUnsignedInteger (wire_indexes[i])
+  
+  const bool has_vertex_colors = !rgba_vertices.empty();
+  WriteBoolean (has_vertex_colors)
+  if (has_vertex_colors)
+  {
+     WriteBoolean (is_rgba)
+     WriteBoolean (is_segment_color)
+     const bool b_optimised=false;
+     WriteBoolean (b_optimised)
+     if (!b_optimised)
+     {
+       SerializeArrayRGBA (rgba_vertices, is_rgba, pbs);
+     }
+     else
+     {
+     // not described
+     }
+  }
+}
+
+void  PRCMarkupTess::serializeMarkupTess(PRCbitStream &pbs)
+{
+// group___tf_markup_tess_data_____serialize2.html
+// group___tf_markup_tess_data_____serialize_content2.html
+  uint32_t i=0; // universal index for PRC standart compatibility
+  WriteUnsignedInteger (PRC_TYPE_TESS_Markup)
+  SerializeContentBaseTessData 
+
+  const uint32_t number_of_codes=codes.size();
+  WriteUnsignedInteger (number_of_codes)
+  for (i=0;i<number_of_codes;i++)
+     WriteUnsignedInteger (codes[i])
+  const uint32_t number_of_texts=texts.size();
+  WriteUnsignedInteger (number_of_texts)
+  for (i=0;i<number_of_texts;i++)
+     WriteString (texts[i])
+  WriteString (label) // label of tessellation
+  WriteCharacter (behaviour)
+}
+
+void writeUnit(PRCbitStream &out,bool fromCAD,double unit)
+{
+  out << fromCAD << unit;
+}
+
+void writeEmptyMarkups(PRCbitStream &out)
+{
+  out << (uint32_t)0 // # of linked items
+      << (uint32_t)0 // # of leaders
+      << (uint32_t)0 // # of markups
+      << (uint32_t)0; // # of annotation entities
+}
+
+void PRCBaseTopology::serializeBaseTopology(PRCbitStream &pbs)
+{
+   WriteBoolean (base_information)
+   if (base_information)
+   {
+      SerializeAttributeData
+      SerializeName (name)
+      WriteUnsignedInteger (identifier)
+   }
+}
+
+void PRCBaseGeometry::serializeBaseGeometry(PRCbitStream &pbs)
+{
+   WriteBoolean (base_information)
+   if (base_information)
+   {
+      SerializeAttributeData
+      SerializeName (name)
+      WriteUnsignedInteger (identifier)
+   }
+}
+
+void PRCContentBody::serializeContentBody(PRCbitStream &pbs)
+{
+   SerializeBaseTopology
+   WriteCharacter ( behavior )
+}
+
+void PRCBoundingBox::serializeBoundingBox(PRCbitStream &pbs)
+{
+   SerializeVector3d ( min )
+   SerializeVector3d ( max )
+}
+
+void PRCDomain::serializeDomain(PRCbitStream &pbs)
+{
+   SerializeVector2d ( min )
+   SerializeVector2d ( max )
+}
+
+void PRCInterval::serializeInterval(PRCbitStream &pbs)
+{
+   WriteDouble ( min )
+   WriteDouble ( max )
+}
+
+void PRCParameterization::serializeParameterization(PRCbitStream &pbs)
+{
+   SerializeInterval ( interval )
+   WriteDouble ( parameterization_coeff_a )
+   WriteDouble ( parameterization_coeff_b )
+}
+
+void PRCUVParameterization::serializeUVParameterization(PRCbitStream &pbs)
+{
+   WriteBoolean ( swap_uv )
+   SerializeDomain ( uv_domain )
+   WriteDouble ( parameterization_on_u_coeff_a )
+   WriteDouble ( parameterization_on_v_coeff_a )
+   WriteDouble ( parameterization_on_u_coeff_b )
+   WriteDouble ( parameterization_on_v_coeff_b )
+}
+
+void PRCContentSurface::serializeContentSurface(PRCbitStream &pbs)
+{
+   SerializeBaseGeometry
+   WriteUnsignedInteger ( extend_info )
+}
+
+void  PRCNURBSSurface::serializeNURBSSurface(PRCbitStream &pbs)
+{ 
+   uint32_t i=0;
+//  uint32_t i=0, j=0;
+   WriteUnsignedInteger (PRC_TYPE_SURF_NURBS) 
+
+   SerializeContentSurface 
+   WriteBoolean ( is_rational )
+   WriteUnsignedInteger ( degree_in_u )
+   WriteUnsignedInteger ( degree_in_v )
+   const uint32_t highest_index_of_knots_in_u = knot_u.size()-1;
+   const uint32_t highest_index_of_knots_in_v = knot_v.size()-1;
+   const uint32_t highest_index_of_control_point_in_u = highest_index_of_knots_in_u - degree_in_u - 1;
+   const uint32_t highest_index_of_control_point_in_v = highest_index_of_knots_in_v - degree_in_v - 1;
+   WriteUnsignedInteger ( highest_index_of_control_point_in_u )
+   WriteUnsignedInteger ( highest_index_of_control_point_in_v )
+   WriteUnsignedInteger ( highest_index_of_knots_in_u )
+   WriteUnsignedInteger ( highest_index_of_knots_in_v )
+   for (i=0; i < (highest_index_of_control_point_in_u+1)*(highest_index_of_control_point_in_v+1); i++)
+   {
+      WriteDouble ( control_point[i].x )
+      WriteDouble ( control_point[i].y )
+      WriteDouble ( control_point[i].z )
+      if (is_rational)
+         WriteDouble ( control_point[i].w )
+   }
+//  for (i=0; i<=highest_index_of_control_point_in_u; i++)
+//  {
+//     for (j=0; j<=highest_index_of_control_point_in_v; j++)
+//     {
+//        WriteDouble ( control_point[i*(highest_index_of_control_point_in_u+1)+j].x )
+//        WriteDouble ( control_point[i*(highest_index_of_control_point_in_u+1)+j].y )
+//        WriteDouble ( control_point[i*(highest_index_of_control_point_in_u+1)+j].z )
+//        if (is_rational)
+//           WriteDouble ( control_point[i*(highest_index_of_control_point_in_u+1)+j].w )
+//     }
+//  }
+   for (i=0; i<=highest_index_of_knots_in_u; i++)
+      WriteDouble ( knot_u[i] )
+   for (i=0; i<=highest_index_of_knots_in_v; i++)
+      WriteDouble ( knot_v[i] )
+   WriteUnsignedInteger ( knot_type )
+   WriteUnsignedInteger ( surface_form )
+}
+
+void writeUnsignedIntegerWithVariableBitNumber(PRCbitStream &pbs, uint32_t value, uint32_t bit_number)
+{
+   uint32_t i;
+   for(i=0; i<bit_number; i++)
+   {
+      if( value >= 1u<<(bit_number - 1 - i) )
+      {
+         WriteBoolean (true)
+      
+         value -= 1u<<(bit_number - 1 - i);
+      }
+      else
+      {
+         WriteBoolean (false)
+      }
+   }
+}
+#define WriteUnsignedIntegerWithVariableBitNumber( value, bit_number )  writeUnsignedIntegerWithVariableBitNumber( pbs, (value), (bit_number) );
+
+void writeIntegerWithVariableBitNumber(PRCbitStream &pbs, int32_t iValue, uint32_t uBitNumber)
+{ 
+  WriteBoolean(iValue<0);
+  WriteUnsignedIntegerWithVariableBitNumber(abs(iValue), uBitNumber - 1);
+}
+#define WriteIntegerWithVariableBitNumber( value, bit_number )  writeIntegerWithVariableBitNumber( pbs, (value), (bit_number) );
+
+void writeDoubleWithVariableBitNumber(PRCbitStream &pbs, double dValue,double dTolerance, unsigned uBitNumber)
+{
+// calling functions must ensure no overflow
+  int32_t iTempValue = (int32_t) ( dValue / dTolerance );
+  WriteIntegerWithVariableBitNumber(iTempValue, uBitNumber);
+}
+#define WriteDoubleWithVariableBitNumber( value, bit_number )  writeDoubleWithVariableBitNumber( pbs, (value), (bit_number) );
+
+uint32_t  GetNumberOfBitsUsedToStoreUnsignedInteger(uint32_t uValue)
+{
+  uint32_t uNbBit=2;
+  uint32_t uTemp = 2;
+  while(uValue >= uTemp)
+  {
+    uTemp*=2;
+    uNbBit++;
+  }
+  return uNbBit-1;
+}
+
+void  writeNumberOfBitsThenUnsignedInteger(PRCbitStream &pbs, uint32_t unsigned_integer)
+{
+   uint32_t number_of_bits = GetNumberOfBitsUsedToStoreUnsignedInteger( unsigned_integer );
+   WriteUnsignedIntegerWithVariableBitNumber ( number_of_bits, 5 )
+   WriteUnsignedIntegerWithVariableBitNumber ( unsigned_integer, number_of_bits )
+}
+#define WriteNumberOfBitsThenUnsignedInteger( value ) writeNumberOfBitsThenUnsignedInteger( pbs, value );
+
+uint32_t  GetNumberOfBitsUsedToStoreInteger(int32_t iValue)
+{
+   return GetNumberOfBitsUsedToStoreUnsignedInteger(abs(iValue))+1;
+}
+
+int32_t intdiv(double dValue, double dTolerance)
+{
+  double ratio=fabs(dValue)/dTolerance;
+  assert(ratio <= INT_MAX);
+  int32_t iTempValue=(int32_t) ratio;
+  if(ratio - iTempValue >= 0.5) iTempValue++;
+  if(dValue < 0) 
+    return -iTempValue;
+  else
+    return iTempValue;
+}
+
+// round dValue to nearest multiple of dTolerance
+double roundto(double dValue, double dTolerance)
+{
+    return intdiv(dValue, dTolerance) * dTolerance;
+}
+
+PRCVector3d roundto(PRCVector3d vec, double dTolerance)
+{
+    PRCVector3d res;
+    res.x = roundto(vec.x,dTolerance);
+    res.y = roundto(vec.y,dTolerance);
+    res.z = roundto(vec.z,dTolerance);
+    return    res;
+}
+
+uint32_t  GetNumberOfBitsUsedToStoreDouble(double dValue, double dTolerance )
+{
+   return GetNumberOfBitsUsedToStoreInteger(intdiv(dValue,dTolerance));
+}
+
+struct itriple
+{
+  int32_t x;
+  int32_t y;
+  int32_t z;
+};
+
+uint32_t  GetNumberOfBitsUsedToStoreTripleInteger(const itriple &iTriple)
+{
+   const uint32_t x_bits = GetNumberOfBitsUsedToStoreInteger(iTriple.x);
+   const uint32_t y_bits = GetNumberOfBitsUsedToStoreInteger(iTriple.y);
+   const uint32_t z_bits = GetNumberOfBitsUsedToStoreInteger(iTriple.z);
+   uint32_t bits = x_bits;
+   if(y_bits > bits)
+     bits = y_bits;
+   if(z_bits > bits)
+     bits = z_bits;
+   return bits;
+}
+
+itriple iroundto(PRCVector3d vec, double dTolerance)
+{
+    itriple res;
+    res.x = intdiv(vec.x, dTolerance);
+    res.y = intdiv(vec.y, dTolerance);
+    res.z = intdiv(vec.z, dTolerance);
+    return    res;
+}
+
+void  PRCCompressedFace::serializeCompressedFace(PRCbitStream &pbs, double brep_data_compressed_tolerance)
+{
+   serializeCompressedAnaNurbs( pbs, brep_data_compressed_tolerance );
+}
+#define SerializeCompressedFace( value ) (value)->serializeCompressedFace( pbs, brep_data_compressed_tolerance );
+
+void  PRCCompressedFace::serializeContentCompressedFace(PRCbitStream &pbs)
+{
+   WriteBoolean ( orientation_surface_with_shell )
+   const bool surface_is_trimmed = false;
+   WriteBoolean ( surface_is_trimmed )
+}
+
+void  PRCCompressedFace::serializeCompressedAnaNurbs(PRCbitStream &pbs, double brep_data_compressed_tolerance)
+{
+   // WriteCompressedEntityType ( PRC_HCG_AnaNurbs )
+   const bool is_a_curve = false;
+   WriteBoolean ( is_a_curve ) 
+   WriteUnsignedIntegerWithVariableBitNumber (13 , 4)
+   serializeContentCompressedFace( pbs );
+   serializeCompressedNurbs( pbs, brep_data_compressed_tolerance );
+}
+
+void  PRCCompressedFace::serializeCompressedNurbs(PRCbitStream &pbs, double brep_data_compressed_tolerance)
+{
+   const double nurbs_tolerance = 0.2*brep_data_compressed_tolerance;
+   const uint32_t degree_in_u = degree;
+   const uint32_t degree_in_v = degree;
+   
+   WriteUnsignedIntegerWithVariableBitNumber ( degree_in_u, 5)
+   WriteUnsignedIntegerWithVariableBitNumber ( degree_in_v, 5)
+
+   const uint32_t number_of_knots_in_u = 4; // 0011 or 00001111 knot vector - just 2 spans
+   WriteUnsignedIntegerWithVariableBitNumber (number_of_knots_in_u - 2, 16)
+   uint32_t number_bit = degree_in_u ? Log2( degree_in_u + 2 ) : 2;
+   WriteBoolean (false) // Multiplicity_is_already_stored - no
+   WriteUnsignedIntegerWithVariableBitNumber( degree_in_u+1,number_bit)
+   WriteBoolean (true) // Multiplicity_is_already_stored - yes
+   const uint32_t number_of_knots_in_v = 4; // 0011 or 00001111 knot vector - just 2 spans
+   WriteUnsignedIntegerWithVariableBitNumber (number_of_knots_in_v - 2, 16)
+   number_bit = degree_in_v ? Log2( degree_in_v + 2 ) : 2;
+   WriteBoolean (false) // Multiplicity_is_already_stored - no
+   WriteUnsignedIntegerWithVariableBitNumber( degree_in_v+1,number_bit)
+   WriteBoolean (true) // Multiplicity_is_already_stored - yes
+  
+   const bool is_closed_u = false; 
+   WriteBoolean ( is_closed_u )
+   const bool is_closed_v = false; 
+   WriteBoolean ( is_closed_v )
+
+   const uint32_t number_of_control_point_in_u = degree_in_u + 1;
+   const uint32_t number_of_control_point_in_v = degree_in_v + 1;
+
+#if defined( __GNUC__ ) && !defined( __clang__ ) 
+   PRCVector3d P[number_of_control_point_in_u][number_of_control_point_in_v];
+#else
+   vector<vector<PRCVector3d> > P(number_of_control_point_in_u, vector<PRCVector3d>(number_of_control_point_in_v));
+#endif
+   for(uint32_t i=0;i<number_of_control_point_in_u;i++)
+   for(uint32_t j=0;j<number_of_control_point_in_v;j++)
+      P[i][j] = control_point[i*number_of_control_point_in_v+j];
+#ifdef __GNUC__
+   itriple compressed_control_point[number_of_control_point_in_u][number_of_control_point_in_v];
+   uint32_t control_point_type[number_of_control_point_in_u][number_of_control_point_in_v];
+#else
+   vector<vector<itriple> > compressed_control_point(number_of_control_point_in_u, vector<itriple>(number_of_control_point_in_v));
+   vector<vector<uint32_t> > control_point_type(number_of_control_point_in_u, vector<uint32_t>(number_of_control_point_in_v));
+#endif
+
+   uint32_t number_of_bits_for_isomin = 1;
+   uint32_t number_of_bits_for_rest = 1;
+   
+   for(uint32_t j = 1; j < number_of_control_point_in_v; j++)
+   {
+      compressed_control_point[0][j] = iroundto(P[0][j]-P[0][j-1], nurbs_tolerance );
+      P[0][j] = P[0][j-1] + roundto(P[0][j]-P[0][j-1], nurbs_tolerance);
+      uint32_t bit_size = GetNumberOfBitsUsedToStoreTripleInteger(compressed_control_point[0][j]);
+      if (bit_size > number_of_bits_for_isomin)
+        number_of_bits_for_isomin = bit_size;
+   }
+
+   for(uint32_t i = 1; i < number_of_control_point_in_u; i++)
+   {
+      compressed_control_point[i][0] = iroundto(P[i][0]-P[i-1][0], nurbs_tolerance );
+      P[i][0] = P[i-1][0] + roundto(P[i][0]-P[i-1][0], nurbs_tolerance);
+      uint32_t bit_size = GetNumberOfBitsUsedToStoreTripleInteger(compressed_control_point[i][0]);
+      if (bit_size > number_of_bits_for_isomin)
+        number_of_bits_for_isomin = bit_size;
+   }
+
+   for(uint32_t i=1;i<number_of_control_point_in_u;i++)
+   for(uint32_t j=1;j<number_of_control_point_in_v;j++)
+   {
+     compressed_control_point[i][j].x = 0;
+     compressed_control_point[i][j].y = 0;
+     compressed_control_point[i][j].z = 0;
+     
+     PRCVector3d V = P[i-1][j] - P[i-1][j-1];
+     PRCVector3d U = P[i][j-1] - P[i-1][j-1];
+     PRCVector3d Pc = P[i][j] - (P[i-1][j-1] + U + V);
+
+     if(Pc.Length() < nurbs_tolerance)
+     {
+       control_point_type[i][j] = 0;
+       P[i][j] = P[i-1][j-1] + U + V;
+     }
+     else 
+     {
+       PRCVector3d N = U*V;
+       PRCVector3d Ue = U;
+       PRCVector3d Ne = N;
+       if( V.Length() < FLT_EPSILON || !Ue.Normalize() || !Ne.Normalize())
+       {
+          control_point_type[i][j] = 3;
+       // Pc = roundto(Pc, nurbs_tolerance); // not sure if this rounding really happens, need to experiment, docs imply but do not state
+          compressed_control_point[i][j] = iroundto(Pc, nurbs_tolerance);
+          P[i][j] = P[i-1][j-1] + U + V + roundto(Pc, nurbs_tolerance); // see above
+       }
+       else
+       {
+         PRCVector3d NUe = Ne*Ue;
+         double x = Pc.Dot(Ue);
+         double y = Pc.Dot(NUe);
+         double z = Pc.Dot(Ne);
+
+         if(x*x+y*y<nurbs_tolerance*nurbs_tolerance)
+         {
+           control_point_type[i][j] = 1;
+           compressed_control_point[i][j] = iroundto(PRCVector3d(0.0,0.0,z), nurbs_tolerance);
+           P[i][j] = P[i-1][j-1] + U + V + roundto(z, nurbs_tolerance)*Ne; // see above
+         }
+         else
+         {
+           if(fabs(z)<nurbs_tolerance/2)
+           {
+             control_point_type[i][j] = 2;
+             compressed_control_point[i][j] = iroundto(PRCVector3d(x,y,0), nurbs_tolerance);
+             P[i][j] = P[i-1][j-1] + U + V + roundto(x, nurbs_tolerance)*Ue + roundto(y, nurbs_tolerance)*NUe; // see above
+           }
+           else
+           {
+             control_point_type[i][j] = 3;
+             compressed_control_point[i][j] = iroundto(Pc, nurbs_tolerance);
+             P[i][j] = P[i-1][j-1] + U + V + roundto(Pc, nurbs_tolerance); // see above
+           }
+         }
+       }
+     }
+     uint32_t bit_size = GetNumberOfBitsUsedToStoreTripleInteger(compressed_control_point[i][j]);
+     if (bit_size > number_of_bits_for_rest)
+       number_of_bits_for_rest = bit_size;
+   }
+
+   if( number_of_bits_for_rest == 2 ) number_of_bits_for_rest--; // really I think it must be unconditional, but so it seems to be done in Adobe Acrobat (9.3)
+   WriteUnsignedIntegerWithVariableBitNumber ( number_of_bits_for_isomin, 20 )
+   WriteUnsignedIntegerWithVariableBitNumber ( number_of_bits_for_rest,   20 )
+   WriteDouble ( P[0][0].x )
+   WriteDouble ( P[0][0].y )
+   WriteDouble ( P[0][0].z )
+   
+   for(uint32_t j = 1; j < number_of_control_point_in_v; j++)
+   {
+      WriteIntegerWithVariableBitNumber(compressed_control_point[0][j].x, number_of_bits_for_isomin+1)
+      WriteIntegerWithVariableBitNumber(compressed_control_point[0][j].y, number_of_bits_for_isomin+1)
+      WriteIntegerWithVariableBitNumber(compressed_control_point[0][j].z, number_of_bits_for_isomin+1)
+   }
+   
+   for(uint32_t i = 1; i < number_of_control_point_in_u; i++)
+   {
+      WriteIntegerWithVariableBitNumber(compressed_control_point[i][0].x, number_of_bits_for_isomin+1)
+      WriteIntegerWithVariableBitNumber(compressed_control_point[i][0].y, number_of_bits_for_isomin+1)
+      WriteIntegerWithVariableBitNumber(compressed_control_point[i][0].z, number_of_bits_for_isomin+1)
+   }
+   
+   for(uint32_t i = 1; i < number_of_control_point_in_u; i++)
+   {
+      for(uint32_t j = 1; j < number_of_control_point_in_v; j++)
+      {
+         WriteUnsignedIntegerWithVariableBitNumber ( control_point_type[i][j], 2 )
+         
+         if(control_point_type[i][j] == 1)
+         {
+            WriteIntegerWithVariableBitNumber ( compressed_control_point[i][j].z, number_of_bits_for_rest+1 )
+         }
+         else if(control_point_type[i][j] == 2)
+         {
+            WriteIntegerWithVariableBitNumber ( compressed_control_point[i][j].x, number_of_bits_for_rest+1 )
+            WriteIntegerWithVariableBitNumber ( compressed_control_point[i][j].y, number_of_bits_for_rest+1 )
+         }
+         else if(control_point_type[i][j] == 3)
+         {
+            WriteIntegerWithVariableBitNumber ( compressed_control_point[i][j].x, number_of_bits_for_rest+1 )
+            WriteIntegerWithVariableBitNumber ( compressed_control_point[i][j].y, number_of_bits_for_rest+1 )
+            WriteIntegerWithVariableBitNumber ( compressed_control_point[i][j].z, number_of_bits_for_rest+1 )
+         }
+      }
+   }
+   
+   const uint32_t type_param_u = 0;
+   WriteBoolean( type_param_u == 0 )
+   const uint32_t type_param_v = 0;
+   WriteBoolean( type_param_v == 0 )
+   const bool is_rational = false;
+   WriteBoolean( is_rational )
+}
+
+void PRCCompressedBrepData::serializeCompressedShell(PRCbitStream &pbs)
+{
+   uint32_t i;
+   const uint32_t number_of_face = face.size();
+   WriteBoolean ( number_of_face == 1 )
+
+   if( number_of_face != 1 )
+      WriteNumberOfBitsThenUnsignedInteger (number_of_face)
+   
+   for( i=0; i < number_of_face; i++)
+         SerializeCompressedFace ( face[i] )
+   
+   const bool is_an_iso_face = false;
+   for( i=0; i < number_of_face; i++)
+      WriteBoolean ( is_an_iso_face )
+}
+
+void PRCCompressedBrepData::serializeCompressedBrepData(PRCbitStream &pbs)
+{
+   WriteUnsignedInteger ( PRC_TYPE_TOPO_BrepDataCompress )
+   SerializeContentBody
+   
+   WriteDouble ( brep_data_compressed_tolerance )
+   const uint32_t number_of_bits_to_store_reference = 1;
+   WriteNumberOfBitsThenUnsignedInteger ( number_of_bits_to_store_reference )
+   const uint32_t number_vertex_iso = 0;
+   WriteUnsignedIntegerWithVariableBitNumber ( number_vertex_iso, number_of_bits_to_store_reference )
+   const uint32_t number_edge_iso = 0;
+   WriteUnsignedIntegerWithVariableBitNumber ( number_edge_iso, number_of_bits_to_store_reference )
+   
+   const uint32_t number_of_shell = 1;
+   const uint32_t number_of_connex = 1;
+   WriteBoolean ( number_of_shell == 1 && number_of_connex == 1 )
+   serializeCompressedShell( pbs );
+
+   uint32_t i;
+   const uint32_t number_of_faces = face.size();
+   for(i=0; i< number_of_faces; i++)
+      face[i]->serializeBaseTopology( pbs );
+}
+
+void  PRCBlend01::serializeBlend01(PRCbitStream &pbs)
+{ 
+   WriteUnsignedInteger (PRC_TYPE_SURF_Blend01) 
+
+   SerializeContentSurface
+   SerializeTransformation
+   SerializeUVParameterization
+   SerializePtrCurve ( center_curve ) 
+   SerializePtrCurve ( origin_curve ) 
+   SerializePtrCurve ( tangent_curve ) 
+}
+
+void  PRCRuled::serializeRuled(PRCbitStream &pbs)
+{ 
+   WriteUnsignedInteger (PRC_TYPE_SURF_Ruled) 
+
+   SerializeContentSurface
+   SerializeTransformation
+   SerializeUVParameterization
+   SerializePtrCurve ( first_curve ) 
+   SerializePtrCurve ( second_curve ) 
+}
+
+void  PRCSphere::serializeSphere(PRCbitStream &pbs)
+{ 
+   WriteUnsignedInteger (PRC_TYPE_SURF_Sphere) 
+
+   SerializeContentSurface
+   SerializeTransformation
+   SerializeUVParameterization
+   WriteDouble ( radius )
+}
+
+void  PRCCone::serializeCone(PRCbitStream &pbs)
+{ 
+   WriteUnsignedInteger (PRC_TYPE_SURF_Cone) 
+
+   SerializeContentSurface
+   SerializeTransformation
+   SerializeUVParameterization
+   WriteDouble ( bottom_radius )
+   WriteDouble ( semi_angle )
+}
+
+void  PRCCylinder::serializeCylinder(PRCbitStream &pbs)
+{ 
+   WriteUnsignedInteger (PRC_TYPE_SURF_Cylinder) 
+
+   SerializeContentSurface
+   SerializeTransformation
+   SerializeUVParameterization
+   WriteDouble ( radius )
+}
+
+void  PRCTorus::serializeTorus(PRCbitStream &pbs)
+{ 
+   WriteUnsignedInteger (PRC_TYPE_SURF_Torus) 
+
+   SerializeContentSurface
+   SerializeTransformation
+   SerializeUVParameterization
+   WriteDouble ( major_radius )
+   WriteDouble ( minor_radius )
+}
+
+void PRCFace::serializeFace(PRCbitStream &pbs)
+{ 
+   uint32_t i = 0;
+   WriteUnsignedInteger (PRC_TYPE_TOPO_Face) 
+
+   SerializeBaseTopology
+   SerializePtrSurface ( base_surface )
+   WriteBit ( have_surface_trim_domain )
+   if ( have_surface_trim_domain )
+      SerializeDomain ( surface_trim_domain ) 
+   WriteBit ( have_tolerance )
+   if ( have_tolerance )
+      WriteDouble ( tolerance ) 
+   WriteUnsignedInteger ( number_of_loop )
+   WriteInteger ( outer_loop_index )
+   for (i=0;i<number_of_loop;i++)
+   {
+//    SerializePtrTopology ( loop[i] )
+   }
+}
+
+void PRCShell::serializeShell(PRCbitStream &pbs)
+{ 
+   uint32_t i = 0;
+   WriteUnsignedInteger (PRC_TYPE_TOPO_Shell) 
+
+   SerializeBaseTopology
+   WriteBoolean ( shell_is_closed )
+   uint32_t number_of_face = face.size();
+   WriteUnsignedInteger ( number_of_face ) 
+   for (i=0;i<number_of_face;i++)
+   {
+      SerializePtrTopology ( face[i] )
+      WriteCharacter ( orientation_surface_with_shell[i] )
+   }
+}
+
+void PRCShell::addFace(PRCFace*& pFace, uint8_t orientation)
+{
+  face.push_back(pFace);
+  pFace = NULL;
+  orientation_surface_with_shell.push_back(orientation);
+}
+
+void PRCConnex::serializeConnex(PRCbitStream &pbs)
+{ 
+   uint32_t i = 0;
+   WriteUnsignedInteger (PRC_TYPE_TOPO_Connex) 
+
+   SerializeBaseTopology
+   uint32_t number_of_shell = shell.size();
+   WriteUnsignedInteger ( number_of_shell ) 
+   for (i=0;i<number_of_shell;i++)
+   {
+      SerializePtrTopology ( shell[i] )
+   }
+}
+
+void PRCConnex::addShell(PRCShell*& pShell)
+{
+  shell.push_back(pShell);
+  pShell = NULL;
+}
+
+#define have_bbox( behavior ) (behavior!=0)
+void PRCBrepData::serializeBrepData(PRCbitStream &pbs)
+{
+   uint32_t i = 0;
+   WriteUnsignedInteger ( PRC_TYPE_TOPO_BrepData) 
+
+   SerializeContentBody 
+   uint32_t number_of_connex = connex.size();
+   WriteUnsignedInteger ( number_of_connex ) 
+   for ( i=0; i<number_of_connex; i++)
+   {
+      SerializePtrTopology ( connex[i] )
+   }
+   if ( have_bbox(behavior) )
+      SerializeBoundingBox
+}
+#undef have_bbox
+
+void PRCBrepData::addConnex(PRCConnex*& pConnex)
+{
+  connex.push_back(pConnex);
+  pConnex = NULL;
+}
+
+void PRCContentWireEdge::serializeContentWireEdge(PRCbitStream &pbs)
+{
+   SerializeBaseTopology
+   SerializePtrCurve ( curve_3d )
+   WriteBit ( has_curve_trim_interval )
+   if ( has_curve_trim_interval )
+      SerializeInterval ( curve_trim_interval )
+}
+
+void PRCWireEdge::serializeWireEdge(PRCbitStream &pbs)
+{
+   WriteUnsignedInteger (PRC_TYPE_TOPO_WireEdge) 
+   SerializeContentWireEdge 
+}
+
+void PRCContentCurve::serializeContentCurve(PRCbitStream &pbs)
+{
+   SerializeBaseGeometry
+   WriteUnsignedInteger ( extend_info )
+   WriteBoolean ( is_3d )
+}
+
+void  PRCNURBSCurve::serializeNURBSCurve(PRCbitStream &pbs)
+{ 
+   uint32_t i=0;
+   WriteUnsignedInteger (PRC_TYPE_CRV_NURBS) 
+
+   SerializeContentCurve 
+   WriteBoolean ( is_rational )
+   WriteUnsignedInteger ( degree )
+   uint32_t highest_index_of_control_point = control_point.size()-1;
+   uint32_t highest_index_of_knots = knot.size()-1;
+   WriteUnsignedInteger ( highest_index_of_control_point )
+   WriteUnsignedInteger ( highest_index_of_knots )
+   for (i=0; i<=highest_index_of_control_point; i++)
+   {
+      WriteDouble ( control_point[i].x )
+      WriteDouble ( control_point[i].y )
+      if (is_3d)
+         WriteDouble ( control_point[i].z )
+      if (is_rational)
+         WriteDouble ( control_point[i].w )
+   }
+   for (i=0; i<=highest_index_of_knots; i++)
+      WriteDouble ( knot[i] )
+   WriteUnsignedInteger ( knot_type )
+   WriteUnsignedInteger ( curve_form )
+}
+
+void  PRCPolyLine::serializePolyLine(PRCbitStream &pbs)
+{ 
+   uint32_t i=0;
+   WriteUnsignedInteger (PRC_TYPE_CRV_PolyLine) 
+
+   SerializeContentCurve 
+   SerializeTransformation
+   SerializeParameterization
+   uint32_t number_of_point = point.size();
+   WriteUnsignedInteger ( number_of_point ) 
+   for (i=0; i<number_of_point; i++) 
+   {
+      if (is_3d)
+         SerializeVector3d ( point[i] )
+      else
+         SerializeVector2d ( point[i] )
+   }
+}
+
+void  PRCCircle::serializeCircle(PRCbitStream &pbs)
+{ 
+   WriteUnsignedInteger (PRC_TYPE_CRV_Circle) 
+
+   SerializeContentCurve 
+   SerializeTransformation
+   SerializeParameterization
+   WriteDouble ( radius )
+}
+
+void  PRCComposite::serializeComposite(PRCbitStream &pbs)
+{ 
+   uint32_t i=0;
+   WriteUnsignedInteger (PRC_TYPE_CRV_Composite) 
+
+   SerializeContentCurve 
+   SerializeTransformation
+   SerializeParameterization
+   uint32_t number_of_curves = base_curve.size();
+   WriteUnsignedInteger ( number_of_curves ) 
+   for (i=0; i<number_of_curves; i++) 
+   {
+      SerializePtrCurve ( base_curve[i] )
+      WriteBoolean ( base_sense[i] )
+   }
+   WriteBoolean ( is_closed )
+}
+
+void PRCTopoContext::serializeTopoContext(PRCbitStream &pbs)
+{ 
+   WriteUnsignedInteger (PRC_TYPE_TOPO_Context) 
+
+   SerializeContentPRCBase
+   WriteCharacter ( behaviour )
+   WriteDouble ( granularity )
+   WriteDouble ( tolerance )
+   WriteBoolean ( have_smallest_face_thickness )
+   if ( have_smallest_face_thickness )
+      WriteDouble ( smallest_thickness )
+   WriteBoolean ( have_scale )
+   if ( have_scale )
+      WriteDouble ( scale )
+}
+
+void PRCTopoContext::serializeContextAndBodies(PRCbitStream &pbs)
+{ 
+   uint32_t i=0;
+   SerializeTopoContext 
+   uint32_t number_of_bodies = body.size();
+   WriteUnsignedInteger (number_of_bodies) 
+   for (i=0;i<number_of_bodies;i++) 
+      SerializeBody (body[i]) 
+}
+
+void PRCTopoContext::serializeGeometrySummary(PRCbitStream &pbs)
+{ 
+   uint32_t i=0;
+   uint32_t number_of_bodies = body.size();
+   WriteUnsignedInteger (number_of_bodies) 
+   for (i=0;i<number_of_bodies;i++) 
+   {
+      WriteUnsignedInteger ( body[i]->serialType() ) 
+      if ( IsCompressedType(body[i]->serialType()) )
+      {
+         WriteDouble ( body[i]->serialTolerance() ) 
+      }
+   }
+}
+
+void PRCTopoContext::serializeContextGraphics(PRCbitStream &pbs)
+{ 
+   uint32_t i=0, j=0, k=0, l=0;
+   ResetCurrentGraphics
+   uint32_t number_of_body = body.size();
+   PRCGraphicsList element;
+   bool has_graphics = false;
+   for (i=0;i<number_of_body;i++)
+   {
+        if ( body[i]->topo_item_type == PRC_TYPE_TOPO_BrepData && dynamic_cast<PRCBrepData*>(body[i]))
+        {
+                PRCBrepData *body_i = dynamic_cast<PRCBrepData*>(body[i]);
+                for (j=0;j<body_i->connex.size();j++)
+                {
+                        for(k=0;k<body_i->connex[j]->shell.size();k++)
+                        {
+                                for( l=0;l<body_i->connex[j]->shell[k]->face.size();l++)
+                                {
+                                        element.push_back( body_i->connex[j]->shell[k]->face[l] );
+                                        has_graphics = has_graphics || body_i->connex[j]->shell[k]->face[l]->has_graphics();
+                                }
+                        }
+                }
+        }
+        else if ( body[i]->topo_item_type == PRC_TYPE_TOPO_BrepDataCompress && dynamic_cast<PRCCompressedBrepData*>(body[i]))
+        {
+                PRCCompressedBrepData *body_i = dynamic_cast<PRCCompressedBrepData*>(body[i]);
+             	for( l=0;l<body_i->face.size();l++)
+             	{
+             		element.push_back( body_i->face[l] );
+             		has_graphics = has_graphics || body_i->face[l]->has_graphics();
+             	}
+        }
+   }
+   uint32_t number_of_treat_type = 0;
+   if (has_graphics && !element.empty())
+     number_of_treat_type = 1;
+   WriteUnsignedInteger (number_of_treat_type) 
+   for (i=0;i<number_of_treat_type;i++) 
+   {
+      const uint32_t element_type = PRC_TYPE_TOPO_Face;
+      WriteUnsignedInteger (element_type) 
+      const uint32_t number_of_element = element.size();
+      WriteUnsignedInteger (number_of_element) 
+      for (j=0;j<number_of_element;j++) 
+      {
+         WriteBoolean ( element[j]->has_graphics() ) 
+         if (element[j]->has_graphics()) 
+         {
+            element[j]->serializeGraphics(pbs);
+         }
+      }
+   }
+}
+
+uint32_t PRCTopoContext::addSingleWireBody(PRCSingleWireBody*& pSingleWireBody)
+{
+  body.push_back(pSingleWireBody);
+  pSingleWireBody = NULL;
+  return body.size()-1;
+}
+
+uint32_t PRCTopoContext::addBrepData(PRCBrepData*& pBrepData)
+{
+  body.push_back(pBrepData);
+  pBrepData = NULL;
+  return body.size()-1;
+}
+
+uint32_t PRCTopoContext::addCompressedBrepData(PRCCompressedBrepData*& pCompressedBrepData)
+{
+  body.push_back(pCompressedBrepData);
+  pCompressedBrepData = NULL;
+  return body.size()-1;
+}
+
+void PRCSingleWireBody::serializeSingleWireBody(PRCbitStream &pbs)
+{
+  WriteUnsignedInteger ( PRC_TYPE_TOPO_SingleWireBody) 
+
+  SerializeContentBody 
+  SerializePtrTopology ( wire_edge )
+}
+
+void PRCUniqueId::serializeCompressedUniqueId(PRCbitStream &pbs) const
+{
+   WriteUnsignedInteger (id0) 
+   WriteUnsignedInteger (id1) 
+   WriteUnsignedInteger (id2) 
+   WriteUnsignedInteger (id3) 	
+}
+
+void PRCUniqueId::serializeFileStructureUncompressedUniqueId(std::ostream& out) const
+{
+   WriteUncompressedUnsignedInteger (id0) 
+   WriteUncompressedUnsignedInteger (id1) 
+   WriteUncompressedUnsignedInteger (id2) 
+   WriteUncompressedUnsignedInteger (id3) 
+}
+
+void PRCUnit::serializeUnit(PRCbitStream &pbs)
+{
+   WriteBoolean (unit_from_CAD_file)
+   WriteDouble (unit)
+}
+
+void PRCProductOccurrence::serializeProductOccurrence(PRCbitStream &pbs)
+{
+   WriteUnsignedInteger ( PRC_TYPE_ASM_ProductOccurence ) 
+
+   SerializePRCBaseWithGraphics 
+
+// SerializeReferencesOfProductOccurrence 
+   WriteUnsignedInteger (index_part+1)
+   WriteUnsignedInteger (index_prototype+1)
+   if (index_prototype != m1)
+   {
+      WriteBoolean (prototype_in_same_file_structure)
+      if (!prototype_in_same_file_structure)
+         SerializeCompressedUniqueId (prototype_file_structure)
+   }
+   WriteUnsignedInteger(index_external_data+1)
+   if (index_external_data != m1)
+   {
+      WriteBoolean (external_data_in_same_file_structure)
+      if (!external_data_in_same_file_structure)
+         SerializeCompressedUniqueId (external_data_file_structure)
+   }
+   const uint32_t number_of_son_product_occurrences = index_son_occurrence.size();
+   WriteUnsignedInteger (number_of_son_product_occurrences)
+   for (uint32_t i=0;i<number_of_son_product_occurrences;i++)
+      WriteUnsignedInteger (index_son_occurrence[i])
+
+   WriteCharacter (product_behaviour)
+
+// SerializeProductInformation (product_information)
+   SerializeUnit (unit_information)
+   WriteCharacter (product_information_flags)
+   WriteInteger (product_load_status)
+
+   const bool has_location = location != NULL;
+   WriteBit (has_location)
+   if (has_location)
+     location->serializeTransformation3d (pbs);
+   
+   WriteUnsignedInteger (0) // number_of_references
+   
+// SerializeMarkups (markups)
+   WriteUnsignedInteger (0) // number_of_linked_items 
+   WriteUnsignedInteger (0) // number_of_leaders 
+   WriteUnsignedInteger (0) // number_of_markups 
+   WriteUnsignedInteger (0) // number_of_annotation_entities 
+
+   
+   WriteUnsignedInteger (0) // number_of_views
+   WriteBit (false) // has_entity_filter
+   WriteUnsignedInteger (0) // number_of_display_filters
+   WriteUnsignedInteger (0) // number_of_scene_display_parameters
+
+   SerializeUserData
+}
+
+uint32_t PRCPartDefinition::addBrepModel(PRCBrepModel*& pBrepModel)
+{
+  representation_item.push_back(pBrepModel);
+  pBrepModel = NULL;
+  return representation_item.size()-1;
+}
+
+uint32_t PRCPartDefinition::addPolyBrepModel(PRCPolyBrepModel*& pPolyBrepModel)
+{
+  representation_item.push_back(pPolyBrepModel);
+  pPolyBrepModel = NULL;
+  return representation_item.size()-1;
+}
+
+uint32_t PRCPartDefinition::addPointSet(PRCPointSet*& pPointSet)
+{
+  representation_item.push_back(pPointSet);
+  pPointSet = NULL;
+  return representation_item.size()-1;
+}
+
+uint32_t PRCPartDefinition::addSet(PRCSet*& pSet)
+{
+  representation_item.push_back(pSet);
+  pSet = NULL;
+  return representation_item.size()-1;
+}
+
+uint32_t PRCPartDefinition::addWire(PRCWire*& pWire)
+{
+  representation_item.push_back(pWire);
+  pWire = NULL;
+  return representation_item.size()-1;
+}
+
+uint32_t PRCPartDefinition::addPolyWire(PRCPolyWire*& pPolyWire)
+{
+  representation_item.push_back(pPolyWire);
+  pPolyWire = NULL;
+  return representation_item.size()-1;
+}
+
+uint32_t PRCPartDefinition::addRepresentationItem(PRCRepresentationItem*& pRepresentationItem)
+{
+  representation_item.push_back(pRepresentationItem);
+  pRepresentationItem = NULL;
+  return representation_item.size()-1;
+}
+
+void PRCPartDefinition::serializePartDefinition(PRCbitStream &pbs)
+{
+  WriteUnsignedInteger ( PRC_TYPE_ASM_PartDefinition ) 
+	
+  SerializePRCBaseWithGraphics
+  SerializeBoundingBox
+
+  uint32_t number_of_representation_items = representation_item.size();
+  WriteUnsignedInteger (number_of_representation_items)
+  for (uint32_t i=0;i<number_of_representation_items;i++)
+    SerializeRepresentationItem (representation_item[i])
+	
+  // SerializeMarkups (markups)
+  WriteUnsignedInteger (0) // number_of_linked_items 
+  WriteUnsignedInteger (0) // number_of_leaders 
+  WriteUnsignedInteger (0) // number_of_markups 
+  WriteUnsignedInteger (0) // number_of_annotation_entities 
+
+  WriteUnsignedInteger (0) // number_of_views
+  SerializeUserData
+}	
diff --git a/src/prc/writePRC.h b/src/prc/writePRC.h
new file mode 100644
index 0000000..59457b1
--- /dev/null
+++ b/src/prc/writePRC.h
@@ -0,0 +1,1649 @@
+/************
+*
+*   This file is part of a tool for producing 3D content in the PRC format.
+*   Copyright (C) 2008  Orest Shardt <shardtor (at) gmail dot com>
+*
+*   This program is free software: you can redistribute it and/or modify
+*   it under the terms of the GNU Lesser General Public License as published by
+*   the Free Software Foundation, either version 3 of the License, or
+*   (at your option) any later version.
+*
+*   This program is distributed in the hope that it will be useful,
+*   but WITHOUT ANY WARRANTY; without even the implied warranty of
+*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*   GNU Lesser General Public License for more details.
+*
+*   You should have received a copy of the GNU Lesser General Public License
+*   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*
+*************/
+
+#ifndef __WRITE_PRC_H
+#define __WRITE_PRC_H
+#include <string>
+#include <vector>
+#include <deque>
+#include <list>
+#include <map>
+#include <iostream>
+#include <algorithm>
+#include "PRCbitStream.h"
+#include "PRC.h"
+#include <float.h>
+#include <math.h>
+
+static const uint32_t m1=(uint32_t)-1;
+static const double pi=acos(-1.0);
+
+class PRCVector3d
+{
+public :
+ double x;
+ double y;
+ double z;
+ PRCVector3d() :
+ x(0), y(0), z(0) {}
+ PRCVector3d(double fx, double fy, double fz) :
+ x(fx), y(fy), z(fz) {}
+ PRCVector3d(const double c[], double fx=0, double fy=0, double fz=0) :
+ x(c?c[0]:fx), y(c?c[1]:fy), z(c?c[2]:fz) {}
+ PRCVector3d(const PRCVector3d& sVector3d) :
+ x(sVector3d.x), y(sVector3d.y), z(sVector3d.z) {}
+
+ void Set(double fx, double fy, double fz)
+ { x = fx; y = fy; z = fz; }
+ double Dot(const PRCVector3d & sPt) const
+ { return(x*sPt.x)+(y*sPt.y)+(z*sPt.z); }
+ double LengthSquared()
+ { return(x*x+y*y+z*z); }
+
+ friend PRCVector3d operator + (const PRCVector3d& a, const PRCVector3d& b)
+ { return PRCVector3d(a.x+b.x,a.y+b.y,a.z+b.z); }
+ friend PRCVector3d operator - (const PRCVector3d& a)
+ { return PRCVector3d(-a.x,-a.y,-a.z); }
+ friend PRCVector3d operator - (const PRCVector3d& a, const PRCVector3d& b)
+ { return PRCVector3d(a.x-b.x,a.y-b.y,a.z-b.z); }
+ friend PRCVector3d operator * (const PRCVector3d& a, const double d)
+ { return PRCVector3d(a.x*d,a.y*d,a.z*d); }
+ friend PRCVector3d operator * (const double d, const PRCVector3d& a)
+ { return PRCVector3d(a.x*d,a.y*d,a.z*d); }
+ friend PRCVector3d operator / (const PRCVector3d& a, const double d)
+ { return PRCVector3d(a.x/d,a.y/d,a.z/d); }
+ friend PRCVector3d operator * (const PRCVector3d& a, const PRCVector3d& b)
+ { return PRCVector3d((a.y*b.z)-(a.z*b.y), (a.z*b.x)-(a.x*b.z), (a.x*b.y)-(a.y*b.x)); }
+
+ void write(PRCbitStream &out) { out << x << y << z; }
+ void serializeVector3d(PRCbitStream &pbs) const { pbs << x << y << z; }
+ void serializeVector2d(PRCbitStream &pbs) const { pbs << x << y; }
+
+ double Length();
+ bool Normalize();
+
+ bool operator==(const PRCVector3d &v) const
+ {
+  return x==v.x && y==v.y && z==v.z;
+ }
+ bool operator!=(const PRCVector3d &v) const
+ {
+  return !(x==v.x && y==v.y && z==v.z);
+ }
+ bool operator<(const PRCVector3d &v) const
+ {
+   if(x!=v.x)
+     return (x<v.x);
+   if(y!=v.y)
+     return (y<v.y);
+   return (z<v.z);
+ }
+ friend std::ostream& operator << (std::ostream& out, const PRCVector3d& v)
+ {
+   out << "(" << v.x << "," << v.y << "," << v.z << ")";
+   return out;
+ }
+};
+/*
+class UUID
+{
+  public:
+    UUID(uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3) :
+      id0(u0),id1(u1),id2(u2),id3(u3) {}
+    void write(PRCbitStream &out)
+    {
+      out << id0 << id1 << id2 << id3;
+    }
+  private:
+    uint32_t id0,id1,id2,id3;
+}; */
+
+void writeUncompressedUnsignedInteger(std::ostream &out, uint32_t data);
+
+void writeUnit(PRCbitStream &,bool,double);
+
+void writeEmptyMarkups(PRCbitStream&);
+
+class UserData
+{
+  public:
+    UserData(uint32_t s = 0, uint8_t* d = 0) : size(s),data(d) {}
+    void write(PRCbitStream&);
+  private:
+    uint32_t size;
+    uint8_t* data;
+};
+
+struct PRCAttributeEntry
+{
+	PRCAttributeEntry() : title_is_integer(false) {}
+	PRCAttributeEntry(uint32_t integer) : title_is_integer(true)
+  {
+    title_integer = integer;
+  }
+	PRCAttributeEntry(const std::string &text) : title_is_integer(false)
+  {
+    title_text = text;
+  }
+  void serializeAttributeEntry(PRCbitStream&) const;
+  bool title_is_integer;
+  std::string title_text;
+  uint32_t title_integer;
+};
+
+class PRCSingleAttribute : public PRCAttributeEntry
+{
+  public:
+  PRCSingleAttribute() : type(KEPRCModellerAttributeTypeNull) {}
+	PRCSingleAttribute(int32_t integer) : PRCAttributeEntry(), type(KEPRCModellerAttributeTypeInt)
+  {
+    value.integer = integer;
+  }
+	PRCSingleAttribute(double real) : PRCAttributeEntry(), type(KEPRCModellerAttributeTypeReal)
+  {
+    value.real = real;
+  }
+  PRCSingleAttribute(uint32_t time) : PRCAttributeEntry(), type(KEPRCModellerAttributeTypeTime)
+  {
+    value.time = time;
+  }  
+	PRCSingleAttribute(const std::string &text) : PRCAttributeEntry(), type(KEPRCModellerAttributeTypeString)
+  {
+    value_text = text;}
+	PRCSingleAttribute(uint32_t title, int32_t integer) : PRCAttributeEntry(title), type(KEPRCModellerAttributeTypeInt)
+  {
+    value.integer = integer;
+  }
+	PRCSingleAttribute(uint32_t title, double real) : PRCAttributeEntry(title), type(KEPRCModellerAttributeTypeReal)
+  {
+    value.real = real;
+  }
+  PRCSingleAttribute(uint32_t title, uint32_t time) : PRCAttributeEntry(title), type(KEPRCModellerAttributeTypeTime)
+  {
+    value.time = time;
+  }  
+	PRCSingleAttribute(uint32_t title, const std::string &text) : PRCAttributeEntry(title), type(KEPRCModellerAttributeTypeString)
+  {
+    value_text = text;
+  }
+	PRCSingleAttribute(const std::string title, int32_t integer) : PRCAttributeEntry(title), type(KEPRCModellerAttributeTypeInt)
+  {
+    value.integer = integer;
+  }
+	PRCSingleAttribute(const std::string title, double real) : PRCAttributeEntry(title), type(KEPRCModellerAttributeTypeReal)
+  {
+    value.real = real;
+  }
+  PRCSingleAttribute(const std::string title, uint32_t time) : PRCAttributeEntry(title), type(KEPRCModellerAttributeTypeTime)
+  {
+    value.time = time;
+  }  
+	PRCSingleAttribute(const std::string title, const std::string &text) : PRCAttributeEntry(title), type(KEPRCModellerAttributeTypeString)
+  {
+    value_text = text;
+  }
+  void serializeSingleAttribute(PRCbitStream&) const;
+  EPRCModellerAttributeType  type;
+  union PRCSingleAttributeData
+  {
+    int32_t integer;
+    double real;
+    uint32_t time;
+  } value;
+  std::string value_text;
+};
+
+class PRCAttribute : public PRCAttributeEntry
+{
+  public:
+  PRCAttribute() : PRCAttributeEntry() {}
+	PRCAttribute(uint32_t title) : PRCAttributeEntry(title) {}
+	PRCAttribute(const std::string title) : PRCAttributeEntry(title) {}
+  void serializeAttribute(PRCbitStream &) const;
+  PRCSingleAttribute& newKey() { attribute_keys.resize(attribute_keys.size()+1); return attribute_keys.back(); }
+  void addKey(const PRCSingleAttribute &key) { attribute_keys.push_back(key); }
+  std::deque<PRCSingleAttribute> attribute_keys;
+};
+typedef std::list<PRCAttribute> PRCAttributeList;
+
+class PRCAttributes
+{
+  public:
+  void serializeAttributes(PRCbitStream&) const;
+  PRCAttribute& newAttribute() { attributes.push_front(PRCAttribute()); return attributes.front(); }
+  void addAttribute(const PRCAttribute &attribute) { attributes.push_front(attribute); }
+  PRCAttributeList attributes;
+};
+
+bool type_eligible_for_reference(uint32_t type);
+uint32_t makeCADID();
+uint32_t makePRCID();
+
+class ContentPRCBase : public PRCAttributes
+{
+  public:
+  ContentPRCBase(uint32_t t, std::string n="") :
+    type(t),name(n),CAD_identifier(0), CAD_persistent_identifier(0), PRC_unique_identifier(0)
+  {
+    if(type_eligible_for_reference(type))
+    {
+      CAD_identifier = makeCADID();
+      PRC_unique_identifier = makePRCID();
+    }
+  }
+  void serializeContentPRCBase(PRCbitStream&) const;
+  uint32_t getPRCID() const { return PRC_unique_identifier; }
+  uint32_t getType() const { return type; }
+  uint32_t type;
+  std::string name;
+  uint32_t CAD_identifier, CAD_persistent_identifier, PRC_unique_identifier;
+};
+
+class PRCReferenceUniqueIdentifier
+{
+public:
+  PRCReferenceUniqueIdentifier() :
+    type(0), unique_identifier(m1) {}
+  void serializeReferenceUniqueIdentifier(PRCbitStream&);
+  uint32_t type;
+// bool reference_in_same_file_structure;
+// PRCUniqueId target_file_structure;
+  uint32_t unique_identifier;
+};
+
+extern std::string currentName;
+void writeName(PRCbitStream&,const std::string&);
+void resetName();
+
+extern uint32_t current_layer_index;
+extern uint32_t current_index_of_line_style;
+extern uint16_t current_behaviour_bit_field;
+
+void writeGraphics(PRCbitStream&,uint32_t=m1,uint32_t=m1,uint16_t=1,bool=false);
+void resetGraphics();
+
+void resetGraphicsAndName();
+
+struct PRCVector2d
+{
+  PRCVector2d() :
+  x(0.0), y(0.0) {}
+  PRCVector2d(double X, double Y) :
+  x(X), y(Y) {}
+  void serializeVector2d(PRCbitStream&);
+  double x;
+  double y;
+  PRCVector2d(const double c[], double fx=0, double fy=0) :
+  x(c?c[0]:fx), y(c?c[1]:fy) {}
+  PRCVector2d(const PRCVector2d& sVector2d) :
+  x(sVector2d.x), y(sVector2d.y) {}
+  
+  void Set(double fx, double fy)
+  { x = fx; y = fy; }
+  double Dot(const PRCVector2d & sPt) const
+  { return(x*sPt.x)+(y*sPt.y); }
+  double LengthSquared()
+  { return(x*x+y*y); }
+  
+  friend PRCVector2d operator + (const PRCVector2d& a, const PRCVector2d& b)
+  { return PRCVector2d(a.x+b.x,a.y+b.y); }
+  friend PRCVector2d operator - (const PRCVector2d& a)
+  { return PRCVector2d(-a.x,-a.y); }
+  friend PRCVector2d operator - (const PRCVector2d& a, const PRCVector2d& b)
+  { return PRCVector2d(a.x-b.x,a.y-b.y); }
+  friend PRCVector2d operator * (const PRCVector2d& a, const double d)
+  { return PRCVector2d(a.x*d,a.y*d); }
+  friend PRCVector2d operator * (const double d, const PRCVector2d& a)
+  { return PRCVector2d(a.x*d,a.y*d); }
+  friend PRCVector2d operator / (const PRCVector2d& a, const double d)
+  { return PRCVector2d(a.x/d,a.y/d); }
+    
+  double Length();
+  bool Normalize();
+  
+  bool operator==(const PRCVector2d &v) const
+  {
+    return x==v.x && y==v.y;
+  }
+  bool operator!=(const PRCVector2d &v) const
+  {
+    return !(x==v.x && y==v.y);
+  }
+  bool operator<(const PRCVector2d &v) const
+  {
+    if(x!=v.x)
+      return (x<v.x);
+    return (y<v.y);
+  }
+  friend std::ostream& operator << (std::ostream& out, const PRCVector2d& v)
+  {
+    out << "(" << v.x << "," << v.y << ")";
+    return out;
+  }
+};
+
+#define EQFLD(fld) fld==c.fld
+#define COMPFLD(fld) \
+if(fld != c.fld) \
+  return (fld < c.fld);
+#define PRCMAP(PRCtype) \
+struct PRCtype##Cmp : public std::binary_function <const PRCtype*, const PRCtype*, bool> \
+{ bool operator()(const PRCtype* Left, const PRCtype* Right) const  { return (*Left < *Right); } }; \
+typedef std::map<PRCtype*,uint32_t,PRCtype##Cmp> PRCtype##Map;
+#define PRCLIST(PRCtype) \
+typedef std::deque <PRCtype*>  PRCtype##List;
+
+
+struct PRCRgbColor
+{
+  PRCRgbColor(double r=0.0, double g=0.0, double b=0.0) :
+  red(r), green(g), blue(b) {}
+  double red,green,blue;
+  void serializeRgbColor(PRCbitStream&);
+  
+  bool operator==(const PRCRgbColor &c) const
+  {
+    return (EQFLD(red) &&
+            EQFLD(green) &&
+            EQFLD(blue)
+            );
+  }
+  bool operator!=(const PRCRgbColor &c) const
+  {
+    return !(EQFLD(red) &&
+             EQFLD(green) &&
+             EQFLD(blue)
+             );
+  }
+  bool operator<(const PRCRgbColor &c) const
+  {
+    COMPFLD(red)
+    COMPFLD(green)
+    COMPFLD(blue)
+    return false;
+  }
+};
+typedef std::map<PRCRgbColor,uint32_t> PRCRgbColorMap;
+typedef std::deque<PRCRgbColor>  PRCRgbColorList;
+
+class PRCUncompressedFile
+{
+public:
+  PRCUncompressedFile() {}
+  PRCUncompressedFile(uint32_t fs, uint8_t *d) {
+    file_contents.assign( d, d + fs );  
+  }
+
+  std::vector<uint8_t> file_contents;
+  
+  void serializeUncompressedFile(std::ostream&) const;
+  
+  uint32_t getSize() const;
+  
+  bool operator==(const PRCUncompressedFile& c) const
+  {
+    return file_contents==c.file_contents;
+  }
+  bool operator<(const PRCUncompressedFile& c) const
+  {
+    return file_contents<c.file_contents;
+  }
+};
+PRCLIST(PRCUncompressedFile)
+PRCMAP(PRCUncompressedFile)
+
+class PRCPicture : public ContentPRCBase
+{
+public:
+  PRCPicture(std::string n="") :
+  ContentPRCBase(PRC_TYPE_GRAPH_Picture,n), format(KEPRCPicture_PNG), uncompressed_file_index(m1), pixel_width(0), pixel_height(0) {}
+  void serializePicture(PRCbitStream&);
+  EPRCPictureDataFormat format;
+  uint32_t uncompressed_file_index;
+  uint32_t pixel_width;
+  uint32_t pixel_height;
+  bool operator==(const PRCPicture& c) const
+  {
+    return (EQFLD(format) &&
+            EQFLD(uncompressed_file_index) &&
+            EQFLD(pixel_width) &&
+            EQFLD(pixel_height) &&
+            EQFLD(name)
+            );
+  }
+  bool operator<(const PRCPicture& c) const
+  {
+    COMPFLD(format)
+    COMPFLD(uncompressed_file_index)
+    COMPFLD(pixel_width)
+    COMPFLD(pixel_height)
+    COMPFLD(name)
+    return false;
+  }
+};
+PRCLIST(PRCPicture)
+PRCMAP(PRCPicture)
+
+
+class PRCTextureDefinition : public ContentPRCBase
+{
+public:
+  PRCTextureDefinition(std::string n="") :
+    ContentPRCBase(PRC_TYPE_GRAPH_TextureDefinition,n), picture_index(m1), texture_mapping_attribute(PRC_TEXTURE_MAPPING_DIFFUSE),
+    texture_mapping_attribute_intensity(1.0), texture_mapping_attribute_components(PRC_TEXTURE_MAPPING_COMPONENTS_RGBA),
+    texture_function(KEPRCTextureFunction_Modulate), texture_applying_mode(PRC_TEXTURE_APPLYING_MODE_NONE),
+    texture_wrapping_mode_S(KEPRCTextureWrappingMode_Unknown), texture_wrapping_mode_T(KEPRCTextureWrappingMode_Unknown) // ,
+    // texture_transformation(false), texture_flip_S(false), texture_flip_T(false),
+    // behaviour(PRC_TRANSFORMATION_Identity), scale(1.0,1.0), uniform_scale(1.0)
+    {}
+  void serializeTextureDefinition(PRCbitStream&);
+  uint32_t picture_index;
+  uint32_t texture_mapping_attribute;
+  double texture_mapping_attribute_intensity;
+  uint8_t texture_mapping_attribute_components;
+  EPRCTextureFunction texture_function;
+  uint8_t texture_applying_mode;
+  EPRCTextureWrappingMode texture_wrapping_mode_S;
+  EPRCTextureWrappingMode texture_wrapping_mode_T;
+  // bool texture_transformation;
+  // bool texture_flip_S;
+  // bool texture_flip_T;
+  // uint8_t behaviour;
+  // PRCVector2d origin;
+  // PRCVector2d X;
+  // PRCVector2d Y;
+  // PRCVector2d scale;
+  // double uniform_scale;
+  // double X_homegeneous_coord;
+  // double Y_homegeneous_coord;
+  // double origin_homegeneous_coord;
+  
+  bool operator==(const PRCTextureDefinition& c) const
+  {
+    return (EQFLD(picture_index) &&
+            EQFLD(texture_mapping_attribute) &&
+            EQFLD(texture_mapping_attribute_intensity) &&
+            EQFLD(texture_mapping_attribute_components) &&
+            EQFLD(texture_function) &&
+            EQFLD(texture_applying_mode) &&
+            EQFLD(texture_wrapping_mode_S) &&
+            EQFLD(texture_wrapping_mode_T) &&
+            EQFLD(name)
+            );
+  }
+  bool operator<(const PRCTextureDefinition& c) const
+  {
+    COMPFLD(picture_index)
+    COMPFLD(texture_mapping_attribute)
+    COMPFLD(texture_mapping_attribute_intensity)
+    COMPFLD(texture_mapping_attribute_components)
+    COMPFLD(texture_function)
+    COMPFLD(texture_applying_mode)
+    COMPFLD(texture_wrapping_mode_S)
+    COMPFLD(texture_wrapping_mode_T)
+    COMPFLD(name)
+    return false;
+  }
+
+};
+PRCLIST(PRCTextureDefinition)
+PRCMAP(PRCTextureDefinition)
+
+class PRCMaterial
+{
+public:
+  virtual ~PRCMaterial() {}
+  virtual void serializeMaterial(PRCbitStream&) = 0;
+};
+PRCLIST(PRCMaterial)
+
+class PRCMaterialGeneric : public ContentPRCBase, public PRCMaterial
+{
+public:
+  PRCMaterialGeneric(std::string n="") :
+    ContentPRCBase(PRC_TYPE_GRAPH_Material,n),
+    ambient(m1), diffuse(m1), emissive(m1), specular(m1), 
+    shininess(0.0),
+    ambient_alpha(1.0), diffuse_alpha(1.0), emissive_alpha(1.0), specular_alpha(1.0)
+    {}
+  void serializeMaterialGeneric(PRCbitStream&);
+  void serializeMaterial(PRCbitStream &pbs) { serializeMaterialGeneric(pbs); }
+  uint32_t ambient;
+  uint32_t diffuse;
+  uint32_t emissive;
+  uint32_t specular;
+  double shininess;
+  double ambient_alpha;
+  double diffuse_alpha;
+  double emissive_alpha;
+  double specular_alpha;
+
+  bool operator==(const PRCMaterialGeneric& c) const
+  {
+    return (EQFLD(ambient) &&
+            EQFLD(diffuse) &&
+            EQFLD(emissive) &&
+            EQFLD(specular) &&
+            EQFLD(shininess) &&
+            EQFLD(ambient_alpha) &&
+            EQFLD(diffuse_alpha) &&
+            EQFLD(emissive_alpha) &&
+            EQFLD(specular_alpha) &&
+            EQFLD(name)
+            );
+  }
+  bool operator<(const PRCMaterialGeneric& c) const
+  {
+    COMPFLD(ambient)
+    COMPFLD(diffuse)
+    COMPFLD(emissive)
+    COMPFLD(specular)
+    COMPFLD(shininess)
+    COMPFLD(ambient_alpha)
+    COMPFLD(diffuse_alpha)
+    COMPFLD(emissive_alpha)
+    COMPFLD(specular_alpha)
+    COMPFLD(name)
+    return false;
+  }
+};
+PRCMAP(PRCMaterialGeneric)
+
+class PRCTextureApplication : public ContentPRCBase, public PRCMaterial
+{
+public:
+  PRCTextureApplication(std::string n="") :
+    ContentPRCBase(PRC_TYPE_GRAPH_TextureApplication,n),
+    material_generic_index(m1), texture_definition_index(m1),
+    next_texture_index(m1), UV_coordinates_index(0)
+    {}
+  void serializeTextureApplication(PRCbitStream&);
+  void serializeMaterial(PRCbitStream &pbs) { serializeTextureApplication(pbs); }
+  uint32_t material_generic_index;
+  uint32_t texture_definition_index;
+  uint32_t next_texture_index;
+  uint32_t UV_coordinates_index;
+  
+  bool operator==(const PRCTextureApplication& c) const
+  {
+    return (EQFLD(material_generic_index) &&
+            EQFLD(texture_definition_index) &&
+            EQFLD(next_texture_index) &&
+            EQFLD(UV_coordinates_index) &&
+            EQFLD(name)
+            );
+  }
+  bool operator<(const PRCTextureApplication& c) const
+  {
+    COMPFLD(material_generic_index)
+    COMPFLD(texture_definition_index)
+    COMPFLD(next_texture_index)
+    COMPFLD(UV_coordinates_index)
+    COMPFLD(name)
+    return false;
+  }
+};
+PRCMAP(PRCTextureApplication)
+
+class PRCLinePattern : public ContentPRCBase
+{
+public:
+  PRCLinePattern(std::string n="") :
+  ContentPRCBase(PRC_TYPE_GRAPH_LinePattern,n),
+  phase(0), is_real_length(false) {}
+  void serializeLinePattern(PRCbitStream&);
+  std::vector<double> lengths;
+  double phase;
+  bool is_real_length;
+};
+typedef std::deque <PRCLinePattern*>  PRCLinePatternList;
+
+class PRCStyle : public ContentPRCBase
+{
+public:
+  PRCStyle(std::string n="") :
+    ContentPRCBase(PRC_TYPE_GRAPH_Style,n), line_width(0.0), is_vpicture(false), line_pattern_vpicture_index(m1),
+    is_material(false), color_material_index(m1), is_transparency_defined(false), transparency(255), additional(0)
+    {}
+  void serializeCategory1LineStyle(PRCbitStream&);
+  double line_width;
+  bool is_vpicture;
+  uint32_t line_pattern_vpicture_index;
+  bool is_material;
+  uint32_t color_material_index;
+  bool is_transparency_defined;
+  uint8_t transparency;
+  uint8_t additional;
+  bool operator==(const PRCStyle& c) const
+  {
+    return (EQFLD(line_width) &&
+            EQFLD(is_vpicture) &&
+            EQFLD(line_pattern_vpicture_index) &&
+            EQFLD(is_material) &&
+            EQFLD(color_material_index) &&
+            EQFLD(is_transparency_defined) &&
+            EQFLD(transparency) &&
+            EQFLD(additional) &&
+            EQFLD(name)
+            );
+  }
+  bool operator<(const PRCStyle& c) const
+  {
+    COMPFLD(line_width)
+    COMPFLD(is_vpicture)
+    COMPFLD(line_pattern_vpicture_index)
+    COMPFLD(is_material)
+    COMPFLD(color_material_index)
+    COMPFLD(is_transparency_defined)
+    COMPFLD(transparency)
+    COMPFLD(additional)
+    COMPFLD(name)
+    return false;
+  }
+
+};
+PRCLIST(PRCStyle)
+PRCMAP(PRCStyle)
+
+#undef EQFLD
+#undef COMPFLD
+#undef PRCMAP
+
+
+class PRCTessFace
+{
+public:
+  PRCTessFace() :
+  start_wire(0), used_entities_flag(0),
+  start_triangulated(0), number_of_texture_coordinate_indexes(0), 
+  is_rgba(false), behaviour(PRC_GRAPHICS_Show)
+  {}
+  void serializeTessFace(PRCbitStream&);
+  std::vector<uint32_t> line_attributes;
+  uint32_t start_wire;			// specifing bounding wire seems not to work as of Acrobat/Reader 9.2
+  std::vector<uint32_t> sizes_wire;	// specifing bounding wire seems not to work as of Acrobat/Reader 9.2
+  uint32_t used_entities_flag;
+  uint32_t start_triangulated;
+  std::vector<uint32_t> sizes_triangulated;
+  uint32_t number_of_texture_coordinate_indexes;
+  bool is_rgba;
+  std::vector<uint8_t> rgba_vertices;
+  uint32_t behaviour;
+};
+typedef std::deque <PRCTessFace*>  PRCTessFaceList;
+
+class PRCContentBaseTessData
+{
+public:
+  PRCContentBaseTessData() :
+  is_calculated(false) {}
+  void serializeContentBaseTessData(PRCbitStream&);
+  bool is_calculated;
+  std::vector<double> coordinates;
+};
+
+class PRCTess : public PRCContentBaseTessData
+{
+public:
+  virtual ~PRCTess() {}
+  virtual void serializeBaseTessData(PRCbitStream &pbs) = 0;
+};
+typedef std::deque <PRCTess*>  PRCTessList;
+
+class PRC3DTess : public PRCTess
+{
+public:
+  PRC3DTess() :
+  has_faces(false), has_loops(false),
+  crease_angle(25.8419)  // arccos(0.9), default found in Acrobat output
+  {}
+  ~PRC3DTess() { for(PRCTessFaceList::iterator it=face_tessellation.begin(); it!=face_tessellation.end(); ++it) delete *it; }
+  void serialize3DTess(PRCbitStream&);
+  void serializeBaseTessData(PRCbitStream &pbs) { serialize3DTess(pbs); }
+  void addTessFace(PRCTessFace*& pTessFace);
+
+  bool has_faces;
+  bool has_loops;
+  double crease_angle;
+  std::vector<double> normal_coordinate;
+  std::vector<uint32_t> wire_index;		// specifing bounding wire seems not to work as of Acrobat/Reader 9.2
+  std::vector<uint32_t> triangulated_index;
+  PRCTessFaceList face_tessellation;
+  std::vector<double> texture_coordinate;
+};
+
+class PRC3DWireTess : public PRCTess
+{
+public:
+  PRC3DWireTess() :
+  is_rgba(false), is_segment_color(false) {}
+  void serialize3DWireTess(PRCbitStream&);
+  void serializeBaseTessData(PRCbitStream &pbs) { serialize3DWireTess(pbs); }
+
+  bool is_rgba;
+  bool is_segment_color;
+  std::vector<uint32_t> wire_indexes;
+  std::vector<uint8_t> rgba_vertices;
+};
+
+class PRCMarkupTess : public PRCTess
+{
+public:
+  PRCMarkupTess() :
+  behaviour(0)
+  {}
+  void serializeMarkupTess(PRCbitStream&);
+  void serializeBaseTessData(PRCbitStream &pbs) { serializeMarkupTess(pbs); }
+
+  std::vector<uint32_t> codes;
+  std::vector<std::string> texts;
+  std::string label;
+  uint8_t behaviour;
+};
+
+class PRCGraphics
+{
+public:
+  PRCGraphics() : layer_index(m1), index_of_line_style(m1), behaviour_bit_field(PRC_GRAPHICS_Show) {}
+  void serializeGraphics(PRCbitStream&);
+  void serializeGraphicsForced(PRCbitStream&);
+  bool has_graphics() { return (index_of_line_style!=m1 || layer_index!=m1 || behaviour_bit_field!=PRC_GRAPHICS_Show) ; }
+  uint32_t layer_index;
+  uint32_t index_of_line_style;
+  uint16_t behaviour_bit_field;
+};
+typedef std::deque <PRCGraphics*>  PRCGraphicsList;
+
+void writeGraphics(PRCbitStream&,const PRCGraphics&,bool=false);
+
+class PRCMarkup: public PRCGraphics, public ContentPRCBase
+{
+public:
+  PRCMarkup(std::string n="") :
+    ContentPRCBase(PRC_TYPE_MKP_Markup,n),
+    type(KEPRCMarkupType_Unknown), sub_type(KEPRCMarkupSubType_Unknown), index_tessellation(m1) {}
+  void serializeMarkup(PRCbitStream&);
+  EPRCMarkupType type;
+  EPRCMarkupSubType sub_type;
+// vector<PRCReferenceUniqueIdentifier> linked_items;
+// vector<PRCReferenceUniqueIdentifier> leaders;
+  uint32_t index_tessellation;
+};
+typedef std::deque <PRCMarkup*>  PRCMarkupList;
+
+class PRCAnnotationItem: public PRCGraphics, public ContentPRCBase
+{
+public:
+  PRCAnnotationItem(std::string n="") :
+    ContentPRCBase(PRC_TYPE_MKP_AnnotationItem,n) {}
+  void serializeAnnotationItem(PRCbitStream&);
+  void serializeAnnotationEntity(PRCbitStream &pbs) { serializeAnnotationItem(pbs); }
+  PRCReferenceUniqueIdentifier markup;
+};
+typedef std::deque <PRCAnnotationItem*>  PRCAnnotationItemList;
+
+class PRCRepresentationItemContent: public PRCGraphics, public ContentPRCBase
+{
+public:
+  PRCRepresentationItemContent(uint32_t t, std::string n="") :
+    ContentPRCBase(t,n),
+    index_local_coordinate_system(m1), index_tessellation(m1) {}
+  void serializeRepresentationItemContent(PRCbitStream&);
+  uint32_t index_local_coordinate_system;
+  uint32_t index_tessellation;
+};
+
+class PRCRepresentationItem : public PRCRepresentationItemContent
+{
+public:
+  PRCRepresentationItem(uint32_t t, std::string n="") :
+    PRCRepresentationItemContent(t,n) {}
+  virtual ~PRCRepresentationItem() {}
+  virtual void serializeRepresentationItem(PRCbitStream &pbs) = 0;
+};
+typedef std::deque <PRCRepresentationItem*>  PRCRepresentationItemList;
+
+class PRCBrepModel : public PRCRepresentationItem
+{
+public:
+  PRCBrepModel(std::string n="") :
+    PRCRepresentationItem(PRC_TYPE_RI_BrepModel,n), has_brep_data(true), context_id(m1), body_id(m1), is_closed(false) {}
+  void serializeBrepModel(PRCbitStream&);
+  void serializeRepresentationItem(PRCbitStream &pbs) { serializeBrepModel(pbs); }
+  bool has_brep_data;
+  uint32_t context_id;
+  uint32_t body_id;
+  bool is_closed;
+};
+
+class PRCPolyBrepModel : public PRCRepresentationItem
+{
+public:
+  PRCPolyBrepModel(std::string n="") :
+    PRCRepresentationItem(PRC_TYPE_RI_PolyBrepModel,n), is_closed(false) {}
+  void serializePolyBrepModel(PRCbitStream&);
+  void serializeRepresentationItem(PRCbitStream &pbs) { serializePolyBrepModel(pbs); }
+  bool is_closed;
+};
+
+class PRCPointSet : public PRCRepresentationItem
+{
+public:
+  PRCPointSet(std::string n="") :
+    PRCRepresentationItem(PRC_TYPE_RI_PointSet,n) {}
+  void serializePointSet(PRCbitStream&);
+  void serializeRepresentationItem(PRCbitStream &pbs) { serializePointSet(pbs); }
+  std::vector<PRCVector3d> point;
+};
+
+class PRCWire : public PRCRepresentationItem
+{
+public:
+  PRCWire(std::string n="") :
+    PRCRepresentationItem(PRC_TYPE_RI_Curve,n), has_wire_body(true), context_id(m1), body_id(m1) {}
+  void serializeWire(PRCbitStream&);
+  void serializeRepresentationItem(PRCbitStream &pbs) { serializeWire(pbs); }
+  bool has_wire_body;
+  uint32_t context_id;
+  uint32_t body_id;
+};
+
+class PRCPolyWire : public PRCRepresentationItem
+{
+public:
+  PRCPolyWire(std::string n="") :
+    PRCRepresentationItem(PRC_TYPE_RI_PolyWire,n) {}
+  void serializePolyWire(PRCbitStream&);
+  void serializeRepresentationItem(PRCbitStream &pbs) { serializePolyWire(pbs); }
+};
+
+class PRCSet : public PRCRepresentationItem
+{
+public:
+  PRCSet(std::string n="") :
+    PRCRepresentationItem(PRC_TYPE_RI_Set,n) {}
+  ~PRCSet() { for(PRCRepresentationItemList::iterator it=elements.begin(); it!=elements.end(); ++it) delete *it; }
+  void serializeSet(PRCbitStream&);
+  void serializeRepresentationItem(PRCbitStream &pbs) { serializeSet(pbs); }
+  uint32_t addBrepModel(PRCBrepModel*& pBrepModel);
+  uint32_t addPolyBrepModel(PRCPolyBrepModel*& pPolyBrepModel);
+  uint32_t addPointSet(PRCPointSet*& pPointSet);
+  uint32_t addSet(PRCSet*& pSet);
+  uint32_t addWire(PRCWire*& pWire);
+  uint32_t addPolyWire(PRCPolyWire*& pPolyWire);
+  uint32_t addRepresentationItem(PRCRepresentationItem*& pRepresentationItem);
+  PRCRepresentationItemList elements;
+};
+
+class PRCTransformation3d
+{
+public:
+  virtual ~PRCTransformation3d() {}
+  virtual void serializeTransformation3d(PRCbitStream&) const =0;
+};
+typedef std::deque <PRCTransformation3d*> PRCTransformation3dList;
+
+class PRCGeneralTransformation3d : public PRCTransformation3d
+{
+public:
+  PRCGeneralTransformation3d()
+  {
+    setidentity();
+  }
+  PRCGeneralTransformation3d(const double t[])
+  {
+    set(t);
+  }
+  
+  void serializeGeneralTransformation3d(PRCbitStream&) const;
+  void serializeTransformation3d(PRCbitStream& pbs)  const { serializeGeneralTransformation3d(pbs); }
+  double m_coef[16];
+  bool operator==(const PRCGeneralTransformation3d &t) const
+  {
+    for (size_t i=0;i<16;i++)
+        if(m_coef[i]!=t.m_coef[i])
+         return false;
+    return true;
+  }
+  bool operator<(const PRCGeneralTransformation3d &t) const
+  {
+    for (size_t i=0;i<16;i++)
+        if(m_coef[i]!=t.m_coef[i])
+        {
+          return (m_coef[i]<t.m_coef[i]);
+        }
+    return false;
+  }
+  void set(const double t[])
+  {
+    if(t!=NULL) 
+      for (size_t i=0;i<16;i++)
+          m_coef[i]=t[i];
+    else
+      setidentity();
+  }
+  void set(const float t[])
+  {
+    if(t!=NULL) 
+      for (size_t i=0;i<16;i++)
+        m_coef[i]=t[i];
+    else
+      setidentity();
+  }
+  void setidentity()
+  {
+    m_coef[0]=1; m_coef[4]=0; m_coef[ 8]=0; m_coef[12]=0;
+    m_coef[1]=0; m_coef[5]=1; m_coef[ 9]=0; m_coef[13]=0;
+    m_coef[2]=0; m_coef[6]=0; m_coef[10]=1; m_coef[14]=0;
+    m_coef[3]=0; m_coef[7]=0; m_coef[11]=0; m_coef[15]=1;
+  }
+  bool isnotidtransform() const {
+    return(
+           m_coef[0]!=1 || m_coef[4]!=0 || m_coef[ 8]!=0 || m_coef[12]!=0 ||
+           m_coef[1]!=0 || m_coef[5]!=1 || m_coef[ 9]!=0 || m_coef[13]!=0 ||
+           m_coef[2]!=0 || m_coef[6]!=0 || m_coef[10]!=1 || m_coef[14]!=0 ||
+           m_coef[3]!=0 || m_coef[7]!=0 || m_coef[11]!=0 || m_coef[15]!=1 );
+  }
+  bool isidtransform() const {
+    return(
+           m_coef[0]==1 && m_coef[4]==0 && m_coef[ 8]==0 && m_coef[12]==0 &&
+           m_coef[1]==0 && m_coef[5]==1 && m_coef[ 9]==0 && m_coef[13]==0 &&
+           m_coef[2]==0 && m_coef[6]==0 && m_coef[10]==1 && m_coef[14]==0 &&
+           m_coef[3]==0 && m_coef[7]==0 && m_coef[11]==0 && m_coef[15]==1 );
+  }
+  double M(size_t i, size_t j) const {
+    return m_coef[i+j*4];
+  }
+};
+typedef std::deque <PRCGeneralTransformation3d> PRCGeneralTransformation3dList;
+
+class PRCCartesianTransformation3d : public PRCTransformation3d
+{
+public:
+  PRCCartesianTransformation3d() :
+    behaviour(PRC_TRANSFORMATION_Identity), origin(0.0,0.0,0.0), X(1.0,0.0,0.0), Y(0.0,1.0,0.0), Z(0.0,0.0,1.0),
+    scale(1.0,1.0,1.0), uniform_scale(1.0),
+    X_homogeneous_coord(0.0), Y_homogeneous_coord(0.0), Z_homogeneous_coord(0.0), origin_homogeneous_coord(1.0) {}
+  PRCCartesianTransformation3d(const double o[3], const double x[3], const double y[3], double sc) :
+    behaviour(PRC_TRANSFORMATION_Identity), origin(o,0.0,0.0,0.0), X(x,1.0,0.0,0.0), Y(y,0.0,1.0,0.0), Z(0.0,0.0,1.0),
+    scale(1.0,1.0,1.0), uniform_scale(sc),
+    X_homogeneous_coord(0.0), Y_homogeneous_coord(0.0), Z_homogeneous_coord(0.0), origin_homogeneous_coord(1.0)
+    {
+      if(origin!=PRCVector3d(0.0,0.0,0.0))
+        behaviour = behaviour | PRC_TRANSFORMATION_Translate;
+      if(X!=PRCVector3d(1.0,0.0,0.0) || Y!=PRCVector3d(0.0,1.0,0.0))
+        behaviour = behaviour | PRC_TRANSFORMATION_Rotate;
+      if(uniform_scale!=1)
+        behaviour = behaviour | PRC_TRANSFORMATION_Scale;
+    }
+  void serializeCartesianTransformation3d(PRCbitStream& pbs) const;
+  void serializeTransformation3d(PRCbitStream& pbs) const { serializeCartesianTransformation3d(pbs); }
+  uint8_t behaviour;
+  PRCVector3d origin;
+  PRCVector3d X;
+  PRCVector3d Y;
+  PRCVector3d Z;
+  PRCVector3d scale;
+  double uniform_scale;
+  double X_homogeneous_coord;
+  double Y_homogeneous_coord;
+  double Z_homogeneous_coord;
+  double origin_homogeneous_coord;
+  bool operator==(const PRCCartesianTransformation3d &t) const
+  {
+    return behaviour==t.behaviour && origin==t.origin && X==t.X && Y==t.Y && Z==t.Z && scale==t.scale && uniform_scale==t.uniform_scale &&
+           X_homogeneous_coord==t.X_homogeneous_coord && Y_homogeneous_coord==t.Y_homogeneous_coord &&
+           Z_homogeneous_coord==t.Z_homogeneous_coord && origin_homogeneous_coord==t.origin_homogeneous_coord;
+  }
+};
+
+class PRCTransformation
+{
+public:
+  PRCTransformation() :
+    has_transformation(false), geometry_is_2D(false), behaviour(PRC_TRANSFORMATION_Identity),
+    origin(0.0,0.0,0.0), x_axis(1.0,0.0,0.0), y_axis(0.0,1.0,0.0), scale(1) {}
+  void serializeTransformation(PRCbitStream&);
+  bool has_transformation;
+  bool geometry_is_2D;
+  uint8_t behaviour;
+  PRCVector3d origin;
+  PRCVector3d x_axis;
+  PRCVector3d y_axis;
+  double scale;
+};
+
+class PRCCoordinateSystem : public PRCRepresentationItem
+{
+public:
+  PRCCoordinateSystem(std::string n="") :
+  PRCRepresentationItem(PRC_TYPE_RI_CoordinateSystem,n), axis_set(NULL) {}
+  ~PRCCoordinateSystem() { delete axis_set; }
+  void serializeCoordinateSystem(PRCbitStream&);
+  void serializeRepresentationItem(PRCbitStream &pbs) { serializeCoordinateSystem(pbs); }
+  void setAxisSet(PRCGeneralTransformation3d*& transform) { axis_set = transform; transform = NULL; } 
+  void setAxisSet(PRCCartesianTransformation3d*& transform) { axis_set = transform; transform = NULL; } 
+  PRCTransformation3d *axis_set;
+  bool operator==(const PRCCoordinateSystem &t) const
+  {
+    if(index_local_coordinate_system!=t.index_local_coordinate_system)
+      return false;
+    PRCGeneralTransformation3d*       axis_set_general = dynamic_cast<PRCGeneralTransformation3d*>(axis_set);
+    PRCGeneralTransformation3d*     t_axis_set_general = dynamic_cast<PRCGeneralTransformation3d*>(t.axis_set);
+    PRCCartesianTransformation3d*   axis_set_cartesian = dynamic_cast<PRCCartesianTransformation3d*>(axis_set);
+    PRCCartesianTransformation3d* t_axis_set_cartesian = dynamic_cast<PRCCartesianTransformation3d*>(t.axis_set);
+    if(axis_set_general!=NULL)
+      return (t_axis_set_general!=NULL?(*axis_set_general==*t_axis_set_general):false); 
+    if(axis_set_cartesian!=NULL)
+      return (t_axis_set_cartesian!=NULL?(*axis_set_cartesian==*t_axis_set_cartesian):false); 
+    return false;
+  }
+};
+typedef std::deque <PRCCoordinateSystem*>  PRCCoordinateSystemList;
+
+struct PRCFontKey
+{
+  uint32_t font_size;
+  uint8_t  attributes;
+};
+
+class PRCFontKeysSameFont
+{
+public:
+  void serializeFontKeysSameFont(PRCbitStream&);
+  std::string font_name;
+  uint32_t char_set;
+  std::vector<PRCFontKey> font_keys;
+
+};
+
+// Topology
+class PRCBaseGeometry : public PRCAttributes
+{
+public:
+  PRCBaseGeometry() :
+    base_information(false), identifier(0) {}
+  PRCBaseGeometry(std::string n, uint32_t id = 0) :
+    base_information(true),name(n),identifier(id) {}
+  void serializeBaseGeometry(PRCbitStream&);
+  bool base_information;
+  std::string name;
+  uint32_t identifier;
+};
+
+class PRCBoundingBox
+{
+public:
+  PRCBoundingBox() : min(0.0,0.0,0.0), max(0.0,0.0,0.0) {}
+  PRCBoundingBox(const PRCVector3d &m, const PRCVector3d& M) : min(m),max(M) {}
+  void serializeBoundingBox(PRCbitStream &pbs);
+  PRCVector3d min;
+  PRCVector3d max;
+};
+
+class PRCDomain
+{
+public:
+  void serializeDomain(PRCbitStream &pbs);
+  PRCVector2d min;
+  PRCVector2d max;
+};
+
+class PRCInterval
+{
+public:
+  PRCInterval() : min(0), max(0) {}
+  PRCInterval(double m, double M) : min(m), max(M) {}
+  void serializeInterval(PRCbitStream &pbs);
+  double min;
+  double max;
+};
+
+class PRCParameterization
+{
+public:
+  PRCParameterization() : parameterization_coeff_a(1), parameterization_coeff_b(0) {}
+  PRCParameterization(double min, double max) : interval(min, max), parameterization_coeff_a(1), parameterization_coeff_b(0) {}
+  void serializeParameterization(PRCbitStream &pbs);
+  PRCInterval interval;
+  double parameterization_coeff_a;
+  double parameterization_coeff_b;
+};
+
+class PRCUVParameterization
+{
+public:
+  PRCUVParameterization() : swap_uv(false),
+    parameterization_on_u_coeff_a(1), parameterization_on_v_coeff_a(1),
+    parameterization_on_u_coeff_b(0), parameterization_on_v_coeff_b(0) {}
+  void serializeUVParameterization(PRCbitStream &pbs);
+  bool swap_uv;
+  PRCDomain uv_domain;
+  double parameterization_on_u_coeff_a;
+  double parameterization_on_v_coeff_a;
+  double parameterization_on_u_coeff_b;
+  double parameterization_on_v_coeff_b;
+};
+
+class PRCControlPoint
+{
+public:
+  PRCControlPoint() :
+   x(0), y(0), z(0), w(1) {}
+  PRCControlPoint(double X, double Y, double Z=0, double W=1) :
+   x(X), y(Y), z(Z), w(W) {}
+  PRCControlPoint(const PRCVector3d &v) :
+   x(v.x), y(v.y), z(v.z), w(1) {}
+  void Set(double fx, double fy, double fz, double fw=1)
+   { x = fx; y = fy; z = fz; w = fw; }
+  double x;
+  double y;
+  double z;
+  double w;
+};
+
+class PRCContentSurface: public PRCBaseGeometry
+{
+public:
+  PRCContentSurface() :
+    PRCBaseGeometry(), extend_info(KEPRCExtendTypeNone) {}
+  PRCContentSurface(std::string n) :
+    PRCBaseGeometry(n,makeCADID()),extend_info(KEPRCExtendTypeNone) {} 
+  void serializeContentSurface(PRCbitStream&);
+  EPRCExtendType extend_info;
+};
+
+class PRCSurface : public PRCContentSurface
+{
+public:
+  PRCSurface() :
+    PRCContentSurface() {}
+  PRCSurface(std::string n) :
+    PRCContentSurface(n) {}
+  virtual ~PRCSurface() {}
+  virtual void  serializeSurface(PRCbitStream &pbs) = 0;
+};
+
+class PRCNURBSSurface : public PRCSurface
+{
+public:
+  PRCNURBSSurface() :
+    PRCSurface(), knot_type(KEPRCKnotTypeUnspecified), surface_form(KEPRCBSplineSurfaceFormUnspecified) {}
+  PRCNURBSSurface(std::string n) :
+    PRCSurface(n), knot_type(KEPRCKnotTypeUnspecified), surface_form(KEPRCBSplineSurfaceFormUnspecified) {}
+  void  serializeNURBSSurface(PRCbitStream &pbs);
+  void  serializeSurface(PRCbitStream &pbs) { serializeNURBSSurface(pbs); }
+  bool is_rational;
+  uint32_t degree_in_u;
+  uint32_t degree_in_v;
+  std::vector<PRCControlPoint> control_point;
+  std::vector<double> knot_u;
+  std::vector<double> knot_v;
+  const EPRCKnotType knot_type;
+  const EPRCBSplineSurfaceForm surface_form;
+};
+
+class PRCContentCurve: public PRCBaseGeometry
+{
+public:
+  PRCContentCurve() :
+    PRCBaseGeometry(), extend_info(KEPRCExtendTypeNone), is_3d(true) {}
+  PRCContentCurve(std::string n) :
+    PRCBaseGeometry(n,makeCADID()),extend_info(KEPRCExtendTypeNone), is_3d(true) {} 
+  void serializeContentCurve(PRCbitStream&);
+  EPRCExtendType extend_info;
+  bool is_3d;
+};
+
+class PRCCurve : public PRCContentCurve
+{
+public:
+  PRCCurve() :
+    PRCContentCurve() {}
+  PRCCurve(std::string n) :
+    PRCContentCurve(n) {}
+  virtual ~PRCCurve() {}
+  virtual void  serializeCurve(PRCbitStream &pbs) = 0;
+};
+typedef std::deque <PRCCurve*>  PRCCurveList;
+
+class PRCNURBSCurve : public PRCCurve
+{
+public:
+  PRCNURBSCurve() :
+    PRCCurve(), knot_type(KEPRCKnotTypeUnspecified), curve_form(KEPRCBSplineCurveFormUnspecified) {}
+  PRCNURBSCurve(std::string n) :
+    PRCCurve(n), knot_type(KEPRCKnotTypeUnspecified), curve_form(KEPRCBSplineCurveFormUnspecified) {}
+  void  serializeNURBSCurve(PRCbitStream &pbs);
+  void  serializeCurve(PRCbitStream &pbs) { serializeNURBSCurve(pbs); }
+  bool is_rational;
+  uint32_t degree;
+  std::vector<PRCControlPoint> control_point;
+  std::vector<double> knot;
+  const EPRCKnotType knot_type;
+  const EPRCBSplineCurveForm curve_form;
+};
+
+class PRCPolyLine : public PRCCurve, public PRCTransformation, public PRCParameterization
+{
+public:
+  PRCPolyLine() :
+    PRCCurve() {}
+  PRCPolyLine(std::string n) :
+    PRCCurve(n) {}
+  void  serializePolyLine(PRCbitStream &pbs);
+  void  serializeCurve(PRCbitStream &pbs) { serializePolyLine(pbs); }
+  std::vector<PRCVector3d> point;
+};
+
+class PRCCircle : public PRCCurve, public PRCTransformation, public PRCParameterization
+{
+public:
+  PRCCircle() :
+    PRCCurve(), PRCParameterization(0,2*pi) {}
+  PRCCircle(std::string n) :
+    PRCCurve(n), PRCParameterization(0,2*pi) {}
+  void  serializeCircle(PRCbitStream &pbs);
+  void  serializeCurve(PRCbitStream &pbs) { serializeCircle(pbs); }
+  double radius;
+};
+
+class PRCComposite : public PRCCurve, public PRCTransformation, public PRCParameterization
+{
+public:
+  PRCComposite() :
+    PRCCurve() {}
+  PRCComposite(std::string n) :
+    PRCCurve(n) {}
+  void  serializeComposite(PRCbitStream &pbs);
+  void  serializeCurve(PRCbitStream &pbs) { serializeComposite(pbs); }
+  PRCCurveList base_curve;
+  std::vector<bool> base_sense;
+  bool is_closed;
+};
+
+class PRCBlend01 : public PRCSurface, public PRCTransformation, public PRCUVParameterization
+{
+public:
+  PRCBlend01() :
+    PRCSurface(), center_curve(NULL), origin_curve(NULL), tangent_curve(NULL) {}
+  PRCBlend01(std::string n) :
+    PRCSurface(n), center_curve(NULL), origin_curve(NULL), tangent_curve(NULL) {}
+  ~PRCBlend01() { delete center_curve; delete origin_curve; delete tangent_curve; }
+  void  serializeBlend01(PRCbitStream &pbs);
+  void  serializeSurface(PRCbitStream &pbs) { serializeBlend01(pbs); }
+// void  setCenterCurve (PRCCurve*& curve) { center_curve  = curve; curve = NULL; }
+// void  setOriginCurve (PRCCurve*& curve) { origin_curve  = curve; curve = NULL; }
+// void  setTangentCurve(PRCCurve*& curve) { tangent_curve = curve; curve = NULL; }
+  PRCCurve* center_curve;
+  PRCCurve* origin_curve;
+  PRCCurve* tangent_curve;
+};
+
+class PRCRuled : public PRCSurface, public PRCTransformation, public PRCUVParameterization
+{
+public:
+  PRCRuled() :
+    PRCSurface(), first_curve(NULL), second_curve(NULL) {}
+  PRCRuled(std::string n) :
+    PRCSurface(n) {}
+  ~PRCRuled() { delete first_curve; delete second_curve; }
+  void  serializeRuled(PRCbitStream &pbs);
+  void  serializeSurface(PRCbitStream &pbs) { serializeRuled(pbs); }
+// void  setFirstCurve(PRCCurve*&  curve) { first_curve  = curve; curve = NULL; }
+// void  setSecondCurve(PRCCurve*& curve) { second_curve = curve; curve = NULL; }
+  PRCCurve* first_curve;
+  PRCCurve* second_curve;
+};
+
+class PRCSphere : public PRCSurface, public PRCTransformation, public PRCUVParameterization
+{
+public:
+  PRCSphere() :
+    PRCSurface() {}
+  PRCSphere(std::string n) :
+    PRCSurface(n) {}
+  void  serializeSphere(PRCbitStream &pbs);
+  void  serializeSurface(PRCbitStream &pbs) { serializeSphere(pbs); }
+  double radius;
+};
+
+class PRCCone : public PRCSurface, public PRCTransformation, public PRCUVParameterization
+{
+public:
+  PRCCone() :
+    PRCSurface() {}
+  PRCCone(std::string n) :
+    PRCSurface(n) {}
+  void  serializeCone(PRCbitStream &pbs);
+  void  serializeSurface(PRCbitStream &pbs) { serializeCone(pbs); }
+  double bottom_radius;
+  double semi_angle;
+};
+
+class PRCCylinder : public PRCSurface, public PRCTransformation, public PRCUVParameterization
+{
+public:
+  PRCCylinder() :
+    PRCSurface() {}
+  PRCCylinder(std::string n) :
+    PRCSurface(n) {}
+  void  serializeCylinder(PRCbitStream &pbs);
+  void  serializeSurface(PRCbitStream &pbs) { serializeCylinder(pbs); }
+  double radius;
+};
+
+class PRCTorus : public PRCSurface, public PRCTransformation, public PRCUVParameterization
+{
+public:
+  PRCTorus() :
+    PRCSurface() {}
+  PRCTorus(std::string n) :
+    PRCSurface(n) {}
+  void  serializeTorus(PRCbitStream &pbs);
+  void  serializeSurface(PRCbitStream &pbs) { serializeTorus(pbs); }
+  double major_radius;
+  double minor_radius;
+};
+
+class PRCBaseTopology : public PRCAttributes
+{
+public:
+  PRCBaseTopology() :
+    base_information(false),identifier(0) {}
+  PRCBaseTopology(std::string n, uint32_t id = 0) :
+    base_information(true),name(n),identifier(id) {}
+  void serializeBaseTopology(PRCbitStream&);
+  bool base_information;
+  std::string name;
+  uint32_t identifier;
+};
+
+class PRCTopoItem
+{
+public:
+  virtual ~PRCTopoItem() {}
+  virtual void serializeTopoItem(PRCbitStream&)=0;
+};
+
+class PRCContentBody: public PRCBaseTopology
+{
+public:
+  PRCContentBody() :
+    PRCBaseTopology(), behavior(0) {}
+  PRCContentBody(std::string n) :
+    PRCBaseTopology(n,makeCADID()), behavior(0) {}
+  void serializeContentBody(PRCbitStream&);
+  uint8_t behavior;
+};
+
+class PRCBody : public PRCContentBody, public PRCTopoItem
+{
+public:
+  PRCBody() :
+    PRCContentBody(), topo_item_type(PRC_TYPE_ROOT) {}
+  PRCBody(uint32_t tit) :
+    PRCContentBody(), topo_item_type(tit) {}
+  PRCBody(uint32_t tit, std::string n) :
+    PRCContentBody(n), topo_item_type(tit) {}
+  virtual ~PRCBody() {}
+  virtual void serializeBody(PRCbitStream &pbs) = 0;
+  void serializeTopoItem(PRCbitStream &pbs) { serializeBody(pbs); }
+  uint32_t serialType() { return topo_item_type; }
+  virtual double serialTolerance() { return 0; }
+  const uint32_t topo_item_type;
+};
+typedef std::deque <PRCBody*>  PRCBodyList;
+
+class PRCContentWireEdge : public PRCBaseTopology
+{
+public:
+  PRCContentWireEdge() :
+    PRCBaseTopology(), curve_3d(NULL), has_curve_trim_interval(false) {}
+  PRCContentWireEdge(std::string n) :
+    PRCBaseTopology(n,makeCADID()), curve_3d(NULL), has_curve_trim_interval(false) {} 
+  ~PRCContentWireEdge() { delete curve_3d; }
+  void serializeContentWireEdge(PRCbitStream &pbs);
+// void setCurve(PRCCurve*& curve) { curve_3d = curve; curve = NULL; }
+  PRCCurve* curve_3d;
+  bool has_curve_trim_interval;
+  PRCInterval curve_trim_interval;
+};
+
+class PRCWireEdge : public PRCContentWireEdge, public PRCTopoItem
+{
+public:
+  void serializeWireEdge(PRCbitStream &pbs);
+  void serializeTopoItem(PRCbitStream &pbs) { serializeWireEdge(pbs); }
+};
+
+class PRCSingleWireBody : public PRCBody
+{
+public:
+  PRCSingleWireBody() :
+    PRCBody(PRC_TYPE_TOPO_SingleWireBody), wire_edge(NULL) {}
+  PRCSingleWireBody(std::string n) :
+    PRCBody(PRC_TYPE_TOPO_SingleWireBody, n), wire_edge(NULL) {}
+  ~PRCSingleWireBody() { delete wire_edge; }
+  void serializeSingleWireBody(PRCbitStream &pbs);
+  void serializeBody(PRCbitStream &pbs) { serializeSingleWireBody(pbs); }
+  void setWireEdge(PRCWireEdge*& wireEdge) { wire_edge = wireEdge; wireEdge = NULL; }  
+  PRCWireEdge* wire_edge;
+};
+
+class PRCFace : public PRCBaseTopology, public PRCTopoItem, public PRCGraphics
+{
+public:
+  PRCFace() :
+    PRCBaseTopology(), base_surface(NULL), have_surface_trim_domain(false), have_tolerance(false), tolerance(0), number_of_loop(0), outer_loop_index(-1) {}
+  PRCFace(std::string n) :
+    PRCBaseTopology(n,makeCADID()), base_surface(NULL), have_surface_trim_domain(false), have_tolerance(false), tolerance(0), number_of_loop(0), outer_loop_index(-1) {} 
+  ~PRCFace() { delete base_surface; }
+  void serializeFace(PRCbitStream &pbs);
+  void serializeTopoItem(PRCbitStream &pbs) { serializeFace(pbs); }
+  void setBaseSurface(PRCSurface*& surface) { base_surface = surface; surface = NULL; }
+  PRCSurface *base_surface;
+  const bool have_surface_trim_domain;
+  PRCDomain surface_trim_domain;
+  const bool have_tolerance;
+  const double tolerance;
+  const uint32_t number_of_loop;
+  const int32_t outer_loop_index;
+// PRCLoopList loop;
+};
+typedef std::deque <PRCFace*>  PRCFaceList;
+
+class PRCShell : public PRCBaseTopology, public PRCTopoItem
+{
+public:
+  PRCShell() :
+    PRCBaseTopology(), shell_is_closed(false) {}
+  PRCShell(std::string n) :
+    PRCBaseTopology(n,makeCADID()), shell_is_closed(false) {}
+  ~PRCShell() { for(PRCFaceList::iterator it=face.begin(); it!=face.end(); ++it) delete *it; }
+  void serializeShell(PRCbitStream &pbs);
+  void serializeTopoItem(PRCbitStream &pbs) { serializeShell(pbs); }
+  void addFace(PRCFace*& pFace, uint8_t orientation=2);
+  bool shell_is_closed;
+  PRCFaceList face;
+  std::vector<uint8_t> orientation_surface_with_shell;
+};
+typedef std::deque <PRCShell*>  PRCShellList;
+
+class PRCConnex : public PRCBaseTopology, public PRCTopoItem
+{
+public:
+  PRCConnex() :
+    PRCBaseTopology() {}
+  PRCConnex(std::string n) :
+    PRCBaseTopology(n,makeCADID()) {} 
+  ~PRCConnex() { for(PRCShellList::iterator it=shell.begin(); it!=shell.end(); ++it) delete *it; }
+  void serializeConnex(PRCbitStream &pbs);
+  void serializeTopoItem(PRCbitStream &pbs) { serializeConnex(pbs); }
+  void addShell(PRCShell*& pShell);
+  PRCShellList shell;
+};
+typedef std::deque <PRCConnex*>  PRCConnexList;
+
+class PRCBrepData : public PRCBody, public PRCBoundingBox
+{
+public:
+  PRCBrepData() :
+    PRCBody(PRC_TYPE_TOPO_BrepData) {}
+  PRCBrepData(std::string n) :
+    PRCBody(PRC_TYPE_TOPO_BrepData, n) {}
+  ~PRCBrepData() { for(PRCConnexList::iterator it=connex.begin(); it!=connex.end(); ++it) delete *it; }
+  void serializeBrepData(PRCbitStream &pbs);
+  void serializeBody(PRCbitStream &pbs) { serializeBrepData(pbs); }
+  void addConnex(PRCConnex*& pConnex);
+  PRCConnexList connex;
+};
+
+// For now - treat just the case of Bezier surfaces cubic 4x4 or linear 2x2
+class PRCCompressedFace : public PRCBaseTopology, public PRCGraphics
+{
+public:
+  PRCCompressedFace() :
+    PRCBaseTopology(), orientation_surface_with_shell(true), degree(0) {}
+  PRCCompressedFace(std::string n) :
+    PRCBaseTopology(n,makeCADID()), orientation_surface_with_shell(true), degree(0) {} 
+  void serializeCompressedFace(PRCbitStream &pbs, double brep_data_compressed_tolerance);
+  void serializeContentCompressedFace(PRCbitStream &pbs);
+  void serializeCompressedAnaNurbs(PRCbitStream &pbs, double brep_data_compressed_tolerance);
+  void serializeCompressedNurbs(PRCbitStream &pbs, double brep_data_compressed_tolerance);
+  bool orientation_surface_with_shell;
+  uint32_t degree;
+  std::vector<PRCVector3d> control_point;
+};
+typedef std::deque <PRCCompressedFace*>  PRCCompressedFaceList;
+
+// For now - treat just the case of one connex/one shell
+class PRCCompressedBrepData : public PRCBody
+{
+public:
+  PRCCompressedBrepData() :
+    PRCBody(PRC_TYPE_TOPO_BrepDataCompress), serial_tolerance(0), brep_data_compressed_tolerance(0) {}
+  PRCCompressedBrepData(std::string n) :
+    PRCBody(PRC_TYPE_TOPO_BrepDataCompress, n), serial_tolerance(0), brep_data_compressed_tolerance(0) {}
+  ~PRCCompressedBrepData() { for(PRCCompressedFaceList::iterator it=face.begin(); it!=face.end(); ++it) delete *it; }
+  void serializeCompressedBrepData(PRCbitStream &pbs);
+  void serializeBody(PRCbitStream &pbs) { serializeCompressedBrepData(pbs); }
+  void serializeCompressedShell(PRCbitStream &pbs);
+  double serialTolerance() { return serial_tolerance; }
+  double serial_tolerance;
+  double brep_data_compressed_tolerance;
+  PRCCompressedFaceList face;
+};
+
+class PRCTopoContext : public ContentPRCBase
+{
+public:
+  PRCTopoContext(std::string n="") :
+  ContentPRCBase(PRC_TYPE_TOPO_Context,n), behaviour(0), granularity(1), tolerance(0),
+   have_smallest_face_thickness(false), smallest_thickness(0), have_scale(false), scale(1) {}
+  ~PRCTopoContext() { for(PRCBodyList::iterator it=body.begin(); it!=body.end(); ++it) delete *it; }
+  void serializeTopoContext(PRCbitStream&);
+  void serializeContextAndBodies(PRCbitStream&);
+  void serializeGeometrySummary(PRCbitStream&);
+  void serializeContextGraphics(PRCbitStream&);
+  uint32_t addSingleWireBody(PRCSingleWireBody*& body);
+  uint32_t addBrepData(PRCBrepData*& body);
+  uint32_t addCompressedBrepData(PRCCompressedBrepData*& body);
+  uint8_t  behaviour;
+  double granularity;
+  double tolerance;
+  bool have_smallest_face_thickness;
+  double smallest_thickness;
+  bool have_scale;
+  double scale;
+  PRCBodyList body;
+};
+typedef std::deque <PRCTopoContext*>  PRCTopoContextList;
+
+class PRCUniqueId
+{
+public:
+  PRCUniqueId() : id0(0), id1(0), id2(0), id3(0)  {}
+  void serializeCompressedUniqueId(PRCbitStream&) const;
+  void serializeFileStructureUncompressedUniqueId(std::ostream& out) const;
+  uint32_t id0;
+  uint32_t id1;
+  uint32_t id2;
+  uint32_t id3;
+};
+
+class PRCUnit
+{
+public:
+  PRCUnit() : unit_from_CAD_file(false), unit(1) {}
+  PRCUnit(double u, bool ufcf=true) : unit_from_CAD_file(ufcf), unit(u) {}
+  void serializeUnit(PRCbitStream&);
+  bool unit_from_CAD_file;
+  double unit;
+};
+
+class PRCProductOccurrence: public PRCGraphics, public ContentPRCBase
+{
+public:
+  PRCProductOccurrence(std::string n="") :
+    ContentPRCBase(PRC_TYPE_ASM_ProductOccurence,n),
+    index_part(m1),
+    index_prototype(m1), prototype_in_same_file_structure(true),
+    index_external_data(m1), external_data_in_same_file_structure(true),
+    product_behaviour(0), product_information_flags(0), product_load_status(KEPRCProductLoadStatus_Loaded),
+    location(NULL) {}
+  ~PRCProductOccurrence() { delete location; }
+  void setLocation(PRCGeneralTransformation3d*& transform) { location = transform; transform = NULL; }
+  void serializeProductOccurrence(PRCbitStream&);
+  uint32_t index_part;
+  uint32_t index_prototype;
+  bool prototype_in_same_file_structure;
+  PRCUniqueId prototype_file_structure;
+  uint32_t index_external_data;
+  bool external_data_in_same_file_structure;
+  PRCUniqueId external_data_file_structure;
+  std::vector<uint32_t> index_son_occurrence;
+  uint8_t product_behaviour;
+  PRCUnit unit_information;
+  uint8_t product_information_flags;
+  EPRCProductLoadStatus product_load_status;
+  PRCGeneralTransformation3d *location;
+};
+typedef std::deque <PRCProductOccurrence*>  PRCProductOccurrenceList;
+
+class PRCPartDefinition: public PRCGraphics, public ContentPRCBase, public PRCBoundingBox
+{
+public:
+	PRCPartDefinition(std::string n="") :
+    ContentPRCBase(PRC_TYPE_ASM_PartDefinition,n) {}
+  ~PRCPartDefinition() { for(PRCRepresentationItemList::iterator it=representation_item.begin(); it!=representation_item.end(); ++it) delete *it; }
+	void serializePartDefinition(PRCbitStream&);
+	uint32_t addBrepModel(PRCBrepModel*& pBrepModel);
+	uint32_t addPolyBrepModel(PRCPolyBrepModel*& pPolyBrepModel);
+	uint32_t addPointSet(PRCPointSet*& pPointSet);
+	uint32_t addSet(PRCSet*& pSet);
+	uint32_t addWire(PRCWire*& pWire);
+	uint32_t addPolyWire(PRCPolyWire*& pPolyWire);
+	uint32_t addRepresentationItem(PRCRepresentationItem*& pRepresentationItem);
+	PRCRepresentationItemList representation_item;
+};
+typedef std::deque <PRCPartDefinition*>  PRCPartDefinitionList;
+
+#endif //__WRITE_PRC_H
diff --git a/src/prim.cpp b/src/prim.cpp
new file mode 100644
index 0000000..7706316
--- /dev/null
+++ b/src/prim.cpp
@@ -0,0 +1,1264 @@
+/***************************************************************************
+ * prim.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include "mgl2/canvas.h"
+#include "mgl2/prim.h"
+#include "mgl2/font.h"
+#include "mgl2/plot.h"
+#include "mgl2/data.h"
+std::wstring MGL_EXPORT mgl_ftoa(double v, const char *fmt);
+//-----------------------------------------------------------------------------
+//
+//	Mark & Curve series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_mark(HMGL gr, double x, double y, double z,const char *mark)
+{
+	char mk = gr->SetPenPal(mark);
+	if(!mk)	mk = '.';
+	if(mgl_isnan(z))	z=2*gr->Max.z-gr->Min.z;
+	static int cgid=1;	gr->StartGroup("MarkS",cgid++);
+	long k = gr->AddPnt(mglPoint(x,y,z),gr->CDef,mglPoint(NAN),-1,3);
+	gr->mark_plot(k,mk,gr->GetPenWidth()); 	gr->AddActive(k);
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_mark_(uintptr_t *gr, mreal *x, mreal *y, mreal *z, const char *pen,int l)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	mgl_mark(_GR_, *x,*y,*z,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_ball(HMGL gr, double x, double y, double z)
+{
+	static int cgid=1;	gr->StartGroup("Ball",cgid++);
+	if(mgl_isnan(z))	z=2*gr->Max.z-gr->Min.z;
+	long k = gr->AddPnt(mglPoint(x,y,z),gr->AddTexture('r'),mglPoint(NAN),-1,3);
+	gr->mark_plot(k,'.');	gr->AddActive(k);
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_ball_(uintptr_t *gr, mreal *x, mreal *y, mreal *z)
+{	mgl_ball(_GR_, *x,*y,*z);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_line(HMGL gr, double x1, double y1, double z1, double x2, double y2, double z2, const char *pen,int n)
+{
+	static int cgid=1;	gr->StartGroup("Line",cgid++);
+	if(mgl_isnan(z1) || mgl_isnan(z2))	z1=z2=2*gr->Max.z-gr->Min.z;
+	mglPoint p1(x1,y1,z1), p2(x2,y2,z2), p=p1,nn(NAN);
+	gr->SetPenPal(pen);
+	n = (n<2) ? 2 : n;
+
+	gr->Reserve(n);
+	long k1 = gr->AddPnt(p,gr->CDef,nn,-1,3);	gr->AddActive(k1);
+	for(long i=1;i<n;i++)
+	{
+		mreal s = i/mreal(n-1);	p = p1*(1-s)+p2*s;
+		long k2 = k1;
+		k1 = gr->AddPnt(p,gr->CDef,nn,-1,3);
+		gr->line_plot(k2,k1);
+		if(i==1)	gr->arrow_plot(k2,k1,gr->Arrow1);
+		if(i==n-1)	gr->arrow_plot(k1,k2,gr->Arrow2);
+	}
+	gr->AddActive(k1,1);	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_line_(uintptr_t *gr, mreal *x1, mreal *y1, mreal *z1, mreal *x2, mreal *y2, mreal *z2, const char *pen,int *n,int l)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	mgl_line(_GR_, *x1,*y1,*z1, *x2,*y2,*z2,s,*n);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_curve(HMGL gr, double x1, double y1, double z1, double dx1, double dy1, double dz1, double x2, double y2, double z2, double dx2, double dy2, double dz2, const char *pen,int n)
+{
+	static int cgid=1;	gr->StartGroup("Curve",cgid++);
+	if(mgl_isnan(z1) || mgl_isnan(z2))	z1=z2=2*gr->Max.z-gr->Min.z;
+	const mglPoint p1(x1,y1,z1), p2(x2,y2,z2),nn(NAN);
+	const mglPoint d1(3*dx1,3*dy1,3*dz1), d2(3*dx2,3*dy2,3*dz2);	// NOTE use d->3*d to be exact as Bezier curve
+	mglPoint a,b,p=p1;
+	a = 3*(p2-p1)-d2-2*d1;	b = d1+d2-2*(p2-p1);
+	n = (n<2) ? 2 : n;
+	gr->SetPenPal(pen);
+
+	gr->Reserve(n);
+	long k1=gr->AddPnt(p,gr->CDef,nn,-1,3);	gr->AddActive(k1);
+	for(long i=1;i<n;i++)
+	{
+		mreal s = i/(n-1.);	p = p1+s*(d1+s*(a+s*b));
+		long k2 = k1;
+		k1 = gr->AddPnt(p,gr->CDef,nn,-1,3);
+		gr->line_plot(k2,k1);
+		if(i==1)	gr->arrow_plot(k2,k1,gr->Arrow1);
+		if(i==n-1)	gr->arrow_plot(k1,k2,gr->Arrow2);
+	}
+	gr->AddActive(gr->AddPnt(p1+d1/3,gr->CDef,nn,-1,3),1);
+	gr->AddActive(gr->AddPnt(p2-d2/3,gr->CDef,nn,-1,3),3);
+	gr->AddActive(k1,2);	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_curve_(uintptr_t* gr, mreal *x1, mreal *y1, mreal *z1, mreal *dx1, mreal *dy1, mreal *dz1, mreal *x2, mreal *y2, mreal *z2, mreal *dx2, mreal *dy2, mreal *dz2, const char *pen,int *n, int l)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	mgl_curve(_GR_, *x1,*y1,*z1, *dx1,*dy1,*dz1, *x2,*y2,*z2, *dx2,*dy2,*dz2, s, *n);	delete []s;}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_error_box(HMGL gr, double x, double y, double z, double ex, double ey, double ez, const char *pen)
+{
+	static int cgid=1;	gr->StartGroup("ErBox",cgid++);
+	char mk=gr->SetPenPal(pen);
+	mglPoint p(x,y,z), q,nn(NAN);
+	gr->Reserve(7);
+	long k1,k2;
+	q = p;	q.x += ex;	k1 = gr->AddPnt(q,gr->CDef,nn,0,3);
+	q = p;	q.x -= ex;	k2 = gr->AddPnt(q,gr->CDef,nn,0,3);
+	gr->line_plot(k1,k2);	gr->arrow_plot(k1,k2,'I');	gr->arrow_plot(k2,k1,'I');
+	q = p;	q.y += ey;	k1 = gr->AddPnt(q,gr->CDef,nn,0,3);
+	q = p;	q.y -= ey;	k2 = gr->AddPnt(q,gr->CDef,nn,0,3);
+	gr->line_plot(k1,k2);	gr->arrow_plot(k1,k2,'I');	gr->arrow_plot(k2,k1,'I');
+	q = p;	q.z += ez;	k1 = gr->AddPnt(q,gr->CDef,nn,0,3);
+	q = p;	q.z -= ez;	k2 = gr->AddPnt(q,gr->CDef,nn,0,3);
+	gr->line_plot(k1,k2);	gr->arrow_plot(k1,k2,'I');	gr->arrow_plot(k2,k1,'I');
+	if(mk)	gr->mark_plot(gr->AddPnt(p,gr->CDef,nn,0,3),mk);
+	gr->AddActive(gr->AddPnt(p,gr->CDef,nn,-1,3),0);
+	gr->AddActive(gr->AddPnt(p+mglPoint(ex,ey),gr->CDef,nn,-1,3),1);
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_error_box_(uintptr_t *gr, mreal *x1, mreal *y1, mreal *z1, mreal *x2, mreal *y2, mreal *z2, const char *pen,int l)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	mgl_error_box(_GR_, *x1,*y1,*z1, *x2,*y2,*z2,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Face series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_face(HMGL gr, double x0, double y0, double z0, double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3, const char *stl)
+{
+	static int cgid=1;	gr->StartGroup("Face",cgid++);
+	long pal;
+	gr->SetPenPal(stl,&pal);
+//	mreal c1,c2,c3,c4,zz=(gr->Min.z+gr->Max.z)/2;
+	mreal c1,c2,c3,c4,zz=2*gr->Max.z-gr->Min.z;
+	c1=c2=c3=c4=gr->CDef;
+	if(mgl_isnan(z0))	z0 = zz;
+	if(mgl_isnan(z1))	z1 = zz;
+	if(mgl_isnan(z2))	z2 = zz;
+	if(mgl_isnan(z3))	z3 = zz;
+	mglPoint p1(x0,y0,z0), p2(x1,y1,z1), p3(x2,y2,z2), p4(x3,y3,z3);
+	if(gr->GetNumPal(pal)>=4)
+	{	c2=gr->NextColor(pal,1);	c3=gr->NextColor(pal,2);	c4=gr->NextColor(pal,3);	}
+	mglPoint q1,q2,q3,q4;
+	q1 = (p2-p1)^(p3-p1);	q4 = (p2-p4)^(p3-p4);
+	q2 = (p1-p2)^(p4-p2);	q3 = (p1-p3)^(p4-p3);
+	gr->Reserve(4);
+	long k1,k2,k3,k4;
+	double a = gr->get(MGL_ENABLE_ALPHA)?-1:1;
+	k1 = gr->AddPnt(p1,c1,q1,a,11);	gr->AddActive(k1,0);
+	k2 = gr->AddPnt(p2,c2,q2,a,11);	gr->AddActive(k2,1);
+	k3 = gr->AddPnt(p3,c3,q3,a,11);	gr->AddActive(k3,2);
+	k4 = gr->AddPnt(p4,c4,q4,a,11);	gr->AddActive(k4,3);
+	gr->quad_plot(k1,k2,k3,k4);
+	if(mglchr(stl,'#'))
+	{
+		gr->Reserve(4);
+		pal = gr->AddTexture('k');
+		k1=gr->CopyNtoC(k1,pal);	k2=gr->CopyNtoC(k2,pal);
+		k3=gr->CopyNtoC(k3,pal);	k4=gr->CopyNtoC(k4,pal);
+		gr->line_plot(k1,k2);		gr->line_plot(k1,k3);
+		gr->line_plot(k3,k4);		gr->line_plot(k2,k4);
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_facex(HMGL gr, double x0, double y0, double z0, double wy, double wz, const char *stl, double d1, double d2)
+{	mgl_face(gr, x0,y0,z0, x0,y0+wy,z0, x0,y0,z0+wz, x0,y0+wy+d1,z0+wz+d2, stl);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_facey(HMGL gr, double x0, double y0, double z0, double wx, double wz, const char *stl, double d1, double d2)
+{	mgl_face(gr, x0,y0,z0, x0+wx,y0,z0, x0,y0,z0+wz, x0+wx+d1,y0,z0+wz+d2, stl);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_facez(HMGL gr, double x0, double y0, double z0, double wx, double wy, const char *stl, double d1, double d2)
+{	mgl_face(gr, x0,y0,z0, x0,y0+wy,z0, x0+wx,y0,z0, x0+wx+d1,y0+wy+d2,z0, stl);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_facex_(uintptr_t* gr, mreal *x0, mreal *y0, mreal *z0, mreal *wy, mreal *wz, const char *stl, mreal *dx, mreal *dy, int l)
+{	char *s=new char[l+1];	memcpy(s,stl,l);	s[l]=0;
+	mgl_facex(_GR_, *x0,*y0,*z0,*wy,*wz,s,*dx,*dy);	delete []s;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_facey_(uintptr_t* gr, mreal *x0, mreal *y0, mreal *z0, mreal *wx, mreal *wz, const char *stl, mreal *dx, mreal *dy, int l)
+{	char *s=new char[l+1];	memcpy(s,stl,l);	s[l]=0;
+	mgl_facey(_GR_, *x0,*y0,*z0,*wx,*wz,s,*dx,*dy);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_facez_(uintptr_t* gr, mreal *x0, mreal *y0, mreal *z0, mreal *wx, mreal *wy, const char *stl, mreal *dx, mreal *dy, int l)
+{	char *s=new char[l+1];	memcpy(s,stl,l);	s[l]=0;
+	mgl_facez(_GR_, *x0,*y0,*z0,*wx,*wy,s,*dx,*dy);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_face_(uintptr_t* gr, mreal *x0, mreal *y0, mreal *z0, mreal *x1, mreal *y1, mreal *z1, mreal *x2, mreal *y2, mreal *z2, mreal *x3, mreal *y3, mreal *z3, const char *stl, int l)
+{	char *s=new char[l+1];	memcpy(s,stl,l);	s[l]=0;
+	mgl_face(_GR_, *x0,*y0,*z0, *x1,*y1,*z1, *x2,*y2,*z2, *x3,*y3,*z3, stl);	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Cone
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cone(HMGL gr, double x1, double y1, double z1, double x2, double y2, double z2, double r1, double r2, const char *stl)
+{
+	if(r2<0)	r2=r1;
+	if(r1==0 && r2==0)	return;
+
+	static int cgid=1;	gr->StartGroup("Cone",cgid++);
+	mglPoint p1(x1,y1,z1), p2(x2,y2,z2), p,q(NAN,NAN),t(NAN,NAN), d=p2-p1,a,b;
+	a=!d;	a.Normalize();		b=d^a;	b.Normalize();
+	mreal c1,c2,dr=r2-r1;
+	const char *s;
+	if((s=strstr(stl,"{&"))!=0)	c1 = c2 = atof(s+2);
+	else
+	{
+		long ss=gr->AddTexture(stl);
+		c1=gr->GetC(ss,p1.z);
+		c2=gr->GetC(ss,p2.z);
+	}
+	long *kk=new long[164],k1=-1,k2=-1;
+	bool edge = mglchr(stl,'@');
+	bool wire = mglchr(stl,'#');
+	gr->Reserve(edge?166:82);
+	if(edge && !wire)
+	{
+		k1=gr->AddPnt(p1,c1,d,-1,3);
+		k2=gr->AddPnt(p2,c2,d,-1,3);
+	}
+	long n=wire?6:18;	//wire?6:18;
+	if(mglchr(stl,'4'))	n=2;
+	else if(mglchr(stl,'6'))	n=3;
+	else if(mglchr(stl,'8'))	n=4;
+	bool refr = n>6;
+	if(refr)	t=d;
+
+	for(long i=0;i<2*n+1;i++)
+	{
+		int f = n!=4?(2*i+1)*90/n:45*i;
+		mreal co = mgl_cos[f%360], si = mgl_cos[(f+270)%360];
+		p = p1+(r1*co)*a+(r1*si)*b;
+		if(refr)	q = (si*a-co*b)^(d + (dr*co)*a + (dr*si)*b);
+		kk[i] = gr->AddPnt(p,c1,q,-1,3);
+		if(edge && !wire)	kk[i+82] = gr->AddPnt(p,c1,t,-1,3);
+		p = p2+(r2*co)*a+(r2*si)*b;
+		kk[i+2*n+1] = gr->AddPnt(p,c2,q,-1,3);
+		if(edge && !wire)	kk[i+123] = gr->AddPnt(p,c2,t,-1,3);
+	}
+	if(wire)	for(long i=0;i<2*n;i++)
+	{
+		gr->line_plot(kk[i],kk[i+1]);
+		gr->line_plot(kk[i],kk[i+2*n+1]);
+		gr->line_plot(kk[i+2*n+2],kk[i+1]);
+		gr->line_plot(kk[i+2*n+2],kk[i+2*n+1]);
+	}
+	else	for(long i=0;i<2*n;i++)
+	{
+		gr->quad_plot(kk[i],kk[i+1],kk[i+2*n+1],kk[i+2*n+2]);
+		if(edge)
+		{
+			gr->trig_plot(k1,kk[i+82],kk[i+83]);
+			gr->trig_plot(k2,kk[i+123],kk[i+124]);
+		}
+	}
+	gr->EndGroup();	delete []kk;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cone_(uintptr_t* gr, mreal *x1, mreal *y1, mreal *z1, mreal *x2, mreal *y2, mreal *z2, mreal *r1, mreal *r2, const char *stl, int l)
+{	char *s=new char[l+1];	memcpy(s,stl,l);	s[l]=0;
+	mgl_cone(_GR_, *x1,*y1,*z1, *x2,*y2,*z2,*r1,*r2,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Cones series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cones_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, const char *pen, const char *opt)
+{
+	long m,n=z->GetNx(),nx=x->GetNx(), nz=z->GetNy(), pal;
+	if(mgl_check_dim1(gr,x,z,y,0,"Cones",true))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Cones",cgid++);
+	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();	m = nz > m ? nz : m;
+
+	bool above= mglchr(pen,'a');
+	bool wire = mglchr(pen,'#');
+	bool tube = mglchr(pen,'t');
+	mreal *dd=new mreal[2*n], x1,z0,zz,d, vx,vy,vz,v0,v1,dv=nx>n?1:0;
+	if(mglchr(pen,'<'))	dv = 1;
+	if(mglchr(pen,'^'))	dv = 0;
+	if(mglchr(pen,'>'))	dv = -1;
+
+	gr->SetPenPal(pen,&pal);
+	std::string cb="@";
+	if(wire)	cb += '#';
+	if(mglchr(pen,'4'))	cb+='4';
+	else if(mglchr(pen,'6'))	cb+='6';
+	else if(mglchr(pen,'8'))	cb+='8';
+
+	memset(dd,0,2*n*sizeof(mreal));
+	z0 = gr->GetOrgZ('x');
+	for(long i=0;i<n;i++)	for(long j=0;j<m;j++)	dd[i] += z->v(i, j<nz ? j:0);
+
+	char buf[64];
+	for(long j=0;j<m;j++)
+	{
+		if(gr->NeedStop())	break;
+		sprintf(buf,"{&%g}",gr->NextColor(pal));
+		std::string c1=cb+buf, c2=c1;
+		if(gr->GetNumPal(pal)==2*m)
+		{	sprintf(buf,"{&%g}",gr->NextColor(pal));	c2 = cb+buf;	}
+		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0, mz = j<nz ? j:0;
+		for(long i=0;i<n;i++)
+		{
+			vx=x->v(i,mx);	vy=y->v(i,my);	vz=z->v(i,mz);
+			v0=y->v(i,0);	v1=i<nx-1 ? x->v(i+1,mx):x->v(i-1,mx);
+			d = i<nx-1 ? v1-vx : vx-v1;
+			x1 = vx + d/2*(dv-0.*gr->BarWidth);
+			d *= 0.7*gr->BarWidth;
+			if(above)
+			{
+				zz = j>0?dd[i+n]:z0;	dd[i+n] += vz;
+				mgl_cone(gr, x1,v0,zz, x1,v0,dd[i+n],
+						 tube?d:d*(dd[i]-zz)/(dd[i]-z0),
+						 tube?d:d*(dd[i]-dd[i+n])/(dd[i]-z0), c1.c_str());
+			}
+			else	mgl_cone(gr, x1,vy,z0, x1,vy,vz, d,tube?d:0, vz<0?c1.c_str():c2.c_str());
+		}
+	}
+	gr->EndGroup();	delete []dd;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cones_xz(HMGL gr, HCDT x, HCDT z, const char *pen, const char *opt)
+{
+	gr->SaveState(opt);
+	mglData y(z);
+	y.Fill(gr->Min.y,gr->Max.y,'y');
+	mgl_cones_xyz(gr,x,&y,z,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cones(HMGL gr, HCDT z, const char *pen, const char *opt)
+{
+	gr->SaveState(opt);
+	mglData x(z->GetNx()+1);
+	x.Fill(gr->Min.x,gr->Max.x);
+	mgl_cones_xz(gr,&x,z,pen,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cones_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_cones_xyz(_GR_,_DA_(x),_DA_(y),_DA_(z),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cones_xz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_cones_xz(_GR_,_DA_(x),_DA_(y),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cones_(uintptr_t *gr, uintptr_t *y,	const char *pen, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_cones(_GR_,_DA_(y),s,o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Polygon & Arc
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_polygon(HMGL gr, double x1, double y1, double z1, double x2, double y2, double z2, int n, const char *stl)
+{
+	if(n<3)	return;
+	long pal=0, n0,n1,n2,np,k1=-1,kp=-1;
+	static int cgid=1;	gr->StartGroup("Polygon",cgid++);
+	gr->SetPenPal(stl,&pal);
+	mreal c=gr->NextColor(pal);
+	mreal k=(gr->GetNumPal(pal)>1)?gr->NextColor(pal):gr->AddTexture('k');
+	bool fill = !mglchr(stl,'#'), box = mglchr(stl,'@') || !fill;
+	if(!fill)	k=c;
+	gr->Reserve(box?2*n+1:n+1);
+	if(mgl_isnan(z1) || mgl_isnan(z2))	z1=z2=2*gr->Max.z-gr->Min.z;
+	mglPoint p1(x1,y1,z1), p2(x2,y2,z2), d=p2-p1, u=!d, p,qq;
+	n0 = gr->AddPnt(p1,c,qq,-1,11);
+	u = (d.norm()/u.norm())*u;
+	n1 = np = gr->AddPnt(p2,c,qq,-1,11);
+	gr->AddActive(n0,0);	gr->AddActive(n1,1);
+	if(box) k1 = kp = gr->CopyNtoC(n1,k);
+	for(long i=1;i<n;i++)
+	{
+		p = p1+d*cos(2*M_PI*i/n)+u*sin(2*M_PI*i/n);
+		n2 = gr->AddPnt(p,c,qq,-1,11);
+		if(fill)	gr->trig_plot(n0,n1,n2);
+		if(box)
+		{
+			long kk = gr->CopyNtoC(n2,k);
+			gr->line_plot(k1, kk);	k1 = kk;
+		}
+		n1 = n2;
+	}
+	if(fill)	gr->trig_plot(n0,n2,np);
+	if(box)		gr->line_plot(k1, kp);
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_arc_ext(HMGL gr, double x0, double y0, double z0, double xr, double yr, double zr, double x1, double y1, double z1, double a, const char* stl)
+{
+	long pal=0, n = long(fabs(a)/9+1.5);	a *= M_PI/180;
+	static int cgid=1;	gr->StartGroup("Arc",cgid++);
+	gr->SetPenPal(stl,&pal);
+	mreal c=gr->NextColor(pal);
+	gr->Reserve(n+2);
+	if(mgl_isnan(z0) || mgl_isnan(z1))	z0=z1=2*gr->Max.z-gr->Min.z;
+	mglPoint p0(x0,y0,z0), p1(x1,y1,z1), d=p1-p0, u(mglPoint(xr,yr,zr)^d), p,qq;
+	if(u.norm()==0)	return;	// wrong vector orientation
+	u = (d.norm()/u.norm())*u;
+	gr->AddActive(gr->AddPnt(p0,gr->CDef,qq,-1,3),0);
+	long n1 = gr->AddPnt(p1,c,qq,-1,11);	gr->AddActive(n1,1);
+	for(long i=1;i<n;i++)
+	{
+		p = p0+d*cos(a*i/(n-1))+u*sin(a*i/(n-1));
+		long n2 = gr->AddPnt(p,c,qq,-1,11);
+		if(i==1)	gr->arrow_plot(n1,n2,gr->Arrow1);
+		if(i==n-1)	{	gr->arrow_plot(n2,n1,gr->Arrow2);	gr->AddActive(n2,2);	}
+		gr->line_plot(n1,n2);	n1 = n2;
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_arc(HMGL gr, double x0, double y0, double x1, double y1, double a, const char* stl)
+{	mgl_arc_ext(gr,x0,y0,NAN,0,0,1,x1,y1,NAN,a,stl);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_polygon_(uintptr_t* gr, mreal *x1, mreal *y1, mreal *z1, mreal *x2, mreal *y2, mreal *z2, int *n, const char *stl,int l)
+{	char *s=new char[l+1];	memcpy(s,stl,l);	s[l]=0;
+	mgl_polygon(_GR_,*x1,*y1,*z1,*x2,*y2,*z2,*n,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_arc_ext_(uintptr_t* gr, mreal *x0, mreal *y0, mreal *z0, mreal *x1, mreal *y1, mreal *z1, mreal *x2, mreal *y2, mreal *z2, mreal *r, const char *stl,int l)
+{	char *s=new char[l+1];	memcpy(s,stl,l);	s[l]=0;
+	mgl_arc_ext(_GR_,*x0,*y0,*z0,*x1,*y1,*z1,*x2,*y2,*z2,*r,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_arc_(uintptr_t* gr, mreal *x0, mreal *y0, mreal *x1, mreal *y1, mreal *a, const char *stl,int l)
+{	char *s=new char[l+1];	memcpy(s,stl,l);	s[l]=0;
+	mgl_arc(_GR_,*x0,*y0,*x1,*y1,*a,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Ellipse & Rhomb
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_ellipse(HMGL gr, double x1, double y1, double z1, double x2, double y2, double z2, double r, const char *stl)
+{
+	const int n = 41;
+	long pal=0,n0,n1=-1,m1=-1;
+	static int cgid=1;	gr->StartGroup("Ellipse",cgid++);
+	gr->SetPenPal(stl,&pal);
+	mreal c=gr->NextColor(pal), d;
+	mreal k=(gr->GetNumPal(pal)>1)?gr->NextColor(pal):gr->AddTexture('k');
+	bool fill = !mglchr(stl,'#'), box = mglchr(stl,'@') || !fill;
+	if(!fill)	k=c;
+
+	gr->Reserve(2*n+1);
+	if(mgl_isnan(z1) || mgl_isnan(z2))	z1=z2=2*gr->Max.z-gr->Min.z;
+	mglPoint p1(x1,y1,z1), p2(x2,y2,z2), v=p2-p1;
+	d = v.norm();
+	if(d==0)	v.Set(1);	else	v /= d;
+	mglPoint u(mglPoint(0,0,1)^v), q(u^v), p, s=(p1+p2)/2.;
+	u *= r;		v *= sqrt(d*d/4+r*r);
+	// central point first
+	n0 = gr->AddPnt(p1,c,q,-1,11);	gr->AddActive(n0);
+	gr->AddActive(gr->AddPnt(p2,c,q,-1,11),1);
+	for(long i=0;i<n;i++)
+	{
+		int t=i*360/(n-1);
+		p = s+v*mgl_cos[t%360]+u*mgl_cos[(270+t)%360];
+		long n2 = n1;	n1 = gr->AddPnt(p,c,q,-1,11);
+		if(i==n/4)	gr->AddActive(n1,2);
+		long m2 = m1;	m1 = gr->CopyNtoC(n1,k);
+		if(i>0)
+		{
+			if(fill)	gr->trig_plot(n0,n1,n2);
+			if(box)	gr->line_plot(m1,m2);
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_rhomb(HMGL gr, double x1, double y1, double z1, double x2, double y2, double z2, double r, const char *stl)
+{
+	long pal=0, n1,n2,n3,n4;
+	static int cgid=1;	gr->StartGroup("Rhomb",cgid++);
+	gr->SetPenPal(stl,&pal);
+	mreal c=gr->NextColor(pal);
+	mreal k=(gr->GetNumPal(pal)>1)?gr->NextColor(pal):gr->AddTexture('k');
+	mreal b=(gr->GetNumPal(pal)>2)?gr->NextColor(pal):c;
+	bool fill = !mglchr(stl,'#'), box = mglchr(stl,'@') || !fill;
+	if(!fill)	k=c;
+	gr->Reserve(8);
+	if(mgl_isnan(z1) || mgl_isnan(z2))	z1=z2=2*gr->Max.z-gr->Min.z;
+	mglPoint p1(x1,y1,z1), p2(x2,y2,z2), u=!(p1-p2), p, s,qq;
+	u = (r/u.norm())*u;	s = (p1+p2)/2.;
+	p = p1;		n1 = gr->AddPnt(p,c,qq,-1,11);
+	p = s+u;	n2 = gr->AddPnt(p,b==c?c:k,qq,-1,11);
+	p = p2;		n3 = gr->AddPnt(p,b,qq,-1,11);
+	p = s-u;	n4 = gr->AddPnt(p,b==c?c:k,qq,-1,11);
+	gr->AddActive(n1,0);	gr->AddActive(n2,2);	gr->AddActive(n3,1);
+	if(fill)	gr->quad_plot(n1,n2,n4,n3);
+	n1 = gr->CopyNtoC(n1,k);	n2 = gr->CopyNtoC(n2,k);
+	n3 = gr->CopyNtoC(n3,k);	n4 = gr->CopyNtoC(n4,k);
+	if(box)
+	{	gr->line_plot(n1,n2);	gr->line_plot(n2,n3);
+		gr->line_plot(n3,n4);	gr->line_plot(n4,n1);	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_ellipse_(uintptr_t* gr, mreal *x1, mreal *y1, mreal *z1, mreal *x2, mreal *y2, mreal *z2, mreal *r, const char *stl,int l)
+{	char *s=new char[l+1];	memcpy(s,stl,l);	s[l]=0;
+	mgl_ellipse(_GR_,*x1,*y1,*z1,*x2,*y2,*z2,*r,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_rhomb_(uintptr_t* gr, mreal *x1, mreal *y1, mreal *z1, mreal *x2, mreal *y2, mreal *z2, mreal *r, const char *stl,int l)
+{	char *s=new char[l+1];	memcpy(s,stl,l);	s[l]=0;
+	mgl_rhomb(_GR_,*x1,*y1,*z1,*x2,*y2,*z2,*r,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Sphere & Drop
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_sphere(HMGL gr, double x, double y, double z, double r, const char *stl)
+{	mgl_drop(gr,x,y,z,1,0,0,2*r,stl,0,1);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_sphere_(uintptr_t* gr, mreal *x, mreal *y, mreal *z, mreal *r, const char *stl,int l)
+{	char *s=new char[l+1];	memcpy(s,stl,l);	s[l]=0;
+	mgl_sphere(_GR_, *x,*y,*z,*r,s);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_drop(HMGL gr, mglPoint p, mglPoint q, double r, double c, double sh, double a)
+{
+	mglPoint p1,p2,pp,qq;
+	if(q.norm()==0)	{	q.Set(1,0,0);	sh=0;	}
+	q.Normalize();	p1 = !q;	p2 = q^p1;	r /= 2;
+
+	static int cgid=1;	gr->StartGroup("Drop",cgid++);
+	const int m=12, n=2*m+1;
+	gr->Reserve(n*m);
+	long *nn=new long[2*n],n1,n2;
+	mreal x,y,z,rr,dr;
+
+	z = r*(1+sh)*(1+sh);	n1 = gr->AddPnt(p + q*z,c,q,-1,3);
+	z = r*(1+sh)*(sh-1);	n2 = gr->AddPnt(p + q*z,c,q,-1,3);
+
+	for(long i=0;i<=m;i++)	for(long j=0;j<n;j++)	// NOTE use prev.points => not for omp
+	{
+		if(i>0 && i<m)
+		{
+			int u=i*180/m, v=180*j/m+202;
+			float co=mgl_cos[u%360], si=mgl_cos[(u+270)%360];
+			float cv=mgl_cos[v%360], sv=mgl_cos[(v+270)%360];
+			rr = r*a*si*(1.+sh*co)/(1+sh);
+			dr = r*a/(1+sh)*(co*(1.+sh*co) - sh*si*si);
+			x = rr*cv;	y = rr*sv;
+			z = r*(1+sh)*(co+sh);
+			pp = p + p1*x + p2*y + q*z;
+			qq = (p1*sv-p2*cv)^(p1*(dr*cv) + p2*(dr*sv) - q*(r*(1+sh)*si));
+			nn[j+n]=nn[j];	nn[j]=gr->AddPnt(pp,c,qq,-1,3);
+		}
+		else if(i==0)	nn[j] = n1;
+		else if(i==m)	{	nn[j+n]=nn[j];	nn[j]=n2;	}
+		if(i*j>0)	gr->quad_plot(nn[j-1], nn[j], nn[j+n-1], nn[j+n]);
+	}
+	delete []nn;	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_drop(HMGL gr, double x1, double y1, double z1, double x2, double y2, double z2, double r, const char *stl, double sh, double a)
+{
+	mreal c=gr->AddTexture((stl && stl[0]) ? stl[0]:'r');
+	mgl_drop(gr,mglPoint(x1,y1,z1), mglPoint(x2,y2,z2), r, c, sh, a);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_drop_(uintptr_t* gr, mreal *x1, mreal *y1, mreal *z1, mreal *x2, mreal *y2, mreal *z2, mreal *r, const char *stl, mreal *shift, mreal *ap, int l)
+{	char *s=new char[l+1];	memcpy(s,stl,l);	s[l]=0;
+	mgl_drop(_GR_, *x1,*y1,*z1, *x2,*y2,*z2, *r,s,*shift,*ap);	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Dew series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dew_xy(HMGL gr, HCDT x, HCDT y, HCDT ax, HCDT ay, const char *sch, const char *opt)
+{
+	long n=ax->GetNx(),m=ax->GetNy();
+	if(mgl_check_dim2(gr,x,y,ax,ay,"Dew"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("DewXY",cgid++);
+
+	long ss = gr->AddTexture(sch);
+	bool inv = mglchr(sch,'i');
+	mreal zVal = gr->Min.z, xm=0;
+	long tx=1,ty=1;
+	if(gr->MeshNum>1)	{	tx=(n-1)/(gr->MeshNum-1);	ty=(m-1)/(gr->MeshNum-1);	}
+	if(tx<1)	tx=1;
+	if(ty<1)	ty=1;
+
+	for(long k=0;k<ax->GetNz();k++)	for(long j=0;j<m;j++)	for(long i=0;i<n;i++)
+	{
+		mreal ym = sqrt(ax->v(i,j,k)*ax->v(i,j,k)+ay->v(i,j,k)*ay->v(i,j,k));
+		xm = xm>ym ? xm : ym;
+	}
+	xm = 1./MGL_FEPSILON/(xm==0 ? 1:xm);
+
+	for(long k=0;k<ax->GetNz();k++)
+	{
+		if(ax->GetNz()>1)	zVal = gr->Min.z+(gr->Max.z-gr->Min.z)*mreal(k)/(ax->GetNz()-1);
+		for(long i=0;i<n;i+=tx)	for(long j=0;j<m;j+=ty)
+		{
+			if(gr->NeedStop())	{	gr->EndGroup();	return;	}
+			mreal xx=GetX(x,i,j,k).x, yy=GetY(y,i,j,k).x, dd;
+			mreal dx = i<n-1 ? (GetX(x,i+1,j,k).x-xx) : (xx-GetX(x,i-1,j,k).x);
+			mreal dy = j<m-1 ? (GetY(y,i,j+1,k).x-yy) : (yy-GetY(y,i,j-1,k).x);
+			dx *= tx;	dy *= ty;
+
+			mglPoint q(ax->v(i,j,k),ay->v(i,j,k));	dd = q.norm();
+			if(inv)	q = -q;
+			mgl_drop(gr,mglPoint(xx, yy, zVal),q,(dx<dy?dx:dy)/2,gr->GetC(ss,dd*xm,false),dd*xm,1);
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dew_2d(HMGL gr, HCDT ax, HCDT ay, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglData x(ax->GetNx()), y(ax->GetNy());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	mgl_dew_xy(gr,&x,&y,ax,ay,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dew_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *ax, uintptr_t *ay, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_dew_xy(_GR_, _DA_(x), _DA_(y), _DA_(ax), _DA_(ay), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dew_2d_(uintptr_t *gr, uintptr_t *ax, uintptr_t *ay, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_dew_2d(_GR_, _DA_(ax), _DA_(ay), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Symbol series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_symbol(HMGL gr, double x, double y, double z, char id, const char *how, double size)
+{	mgl_symbol_dir(gr, x, y, z, NAN, NAN, 0, id, how, size);	}
+void MGL_EXPORT mgl_symbol_dir(HMGL gr, double x, double y, double z, double dx, double dy, double dz, char id, const char *how, double size)
+{
+	bool a=mglchr(how,'a'), A=mglchr(how,'A');
+//	static int cgid=1;	gr->StartGroup("Puts",cgid++);
+	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);
+	if(g && (a||A))
+	{
+		g->Push();	g->Identity(a);
+		gr->set(MGL_DISABLE_SCALE);
+		mreal s=a?1:g->GetPlotFactor();
+		x = (2*x-1)*s;	y = (2*y-1)*s;
+		dx= (2*dx-1)*s;	dy= (2*dy-1)*s;
+	}
+	if(mgl_isnan(z))	z=2*gr->Max.z-gr->Min.z;
+	mglPoint p(x,y,z), d(dx-x,dy-y,dz-z);
+	long cc = mgl_get_num_color(how,0)?gr->AddTexture(how):gr->AddTexture('k');
+	long k = gr->AddPnt(p,cc,d,-1,7);
+	gr->AddActive(k,0);
+	gr->AddActive(gr->AddPnt(mglPoint(dx,dy,dz),cc,d,-1,7),1);
+	if(g && (a||A))	{	g->Pop();	gr->clr(MGL_DISABLE_SCALE);	}
+	if(size<0)	size *= -gr->GetFontSize();
+	
+	int font=0;	mglGetStyle(how, &font, NULL);
+	if(font&MGL_FONT_WIRE)	size = -size;
+	gr->smbl_plot(k,id,size);
+//	gr->EndGroup();
+}
+void MGL_EXPORT mgl_symbol_(uintptr_t *gr, double *x, double *y, double *z, char *id, const char *how, double *size,int,int n)
+{	char *f=new char[n+1];	memcpy(f,how,n);	f[n]=0;
+	mgl_symbol(_GR_, *x, *y, *z, *id, f, *size);	delete []f;	}
+void MGL_EXPORT mgl_symbol_dir_(uintptr_t *gr, double *x, double *y, double *z, double *dx, double *dy, double *dz, char *id, const char *how, double *size,int,int n)
+{	char *f=new char[n+1];	memcpy(f,how,n);	f[n]=0;
+	mgl_symbol_dir(_GR_, *x, *y, *z, *dx, *dy, *dz, *id, f, *size);	delete []f;	}
+//-----------------------------------------------------------------------------
+//
+//	Puts series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_puts(HMGL gr, double x, double y, double z,const char *text, const char *font, double size)
+{	mgl_puts_dir(gr, x, y, z, NAN, NAN, 0, text, font, size);	}
+void MGL_EXPORT mgl_putsw(HMGL gr, double x, double y, double z,const wchar_t *text, const char *font, double size)
+{	mgl_putsw_dir(gr, x, y, z, NAN, NAN, 0, text, font, size);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_puts_dir(HMGL gr, double x, double y, double z, double dx, double dy, double dz, const char *text, const char *font, double size)
+{
+	MGL_TO_WCS(text,mgl_putsw_dir(gr, x, y, z, dx, dy, dz, wcs, font, size));
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_putsw_dir(HMGL gr, double x, double y, double z, double dx, double dy, double dz, const wchar_t *text, const char *font, double size)
+{
+	bool a=mglchr(font,'a'), A=mglchr(font,'A');
+	static int cgid=1;	gr->StartGroup("Puts",cgid++);
+	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);
+	if(g && (a||A))
+	{
+		g->Push();	g->Identity(a);
+		gr->set(MGL_DISABLE_SCALE);
+		mreal s=a?1:g->GetPlotFactor();
+		x = (2*x-1)*s;	y = (2*y-1)*s;
+		dx= (2*dx-1)*s;	dy= (2*dy-1)*s;
+	}
+	if(mgl_isnan(z))	z=2*gr->Max.z-gr->Min.z;
+	mglPoint p(x,y,z), d(dx-x,dy-y,dz-z);
+	long k = gr->AddPnt(p,-1,d,-1,7);
+	gr->AddActive(k,0);
+	gr->AddActive(gr->AddPnt(mglPoint(dx,dy,dz),-1,d,-1,7),1);
+	if(g && (a||A))	{	g->Pop();	gr->clr(MGL_DISABLE_SCALE);	}
+	gr->text_plot(k,text,font,size);
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_puts_(uintptr_t *gr, mreal *x, mreal *y, mreal *z,const char *text, const char *font, mreal *size, int l, int n)
+{	wchar_t *s=new wchar_t[l+1];	mbstowcs(s,text,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,font,n);	f[n]=0;
+	mgl_putsw_dir(_GR_, *x, *y, *z, NAN, NAN, 0, s, f, *size);
+	delete []s;	delete []f;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_puts_dir_(uintptr_t *gr, mreal *x, mreal *y, mreal *z, mreal *dx, mreal *dy, mreal *dz, const char *text, const char *font, mreal *size, int l, int n)
+{	wchar_t *s=new wchar_t[l+1];	mbstowcs(s,text,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,font,n);	f[n]=0;
+	mgl_putsw_dir(_GR_, *x, *y, *z, *dx, *dy, *dz, s, f, *size);
+	delete []s;	delete []f;	}
+//-----------------------------------------------------------------------------
+//
+//	TextMark series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_textmarkw_xyzr(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT r, const wchar_t *text, const char *fnt, const char *opt)
+{
+	long m,n=y->GetNx();
+	if(mgl_check_dim0(gr,x,y,z,r,"TextMark"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("TextMark",cgid++);
+	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();
+	m = z->GetNy() > m ? z->GetNy() : m;
+	m = r->GetNy() > m ? r->GetNy() : m;
+	gr->Reserve(n*m);
+
+	mglPoint q(NAN);
+	int d = gr->MeshNum>0 ? gr->MeshNum+1 : n, dx = n>d?n/d:1;
+	for(long j=0;j<m;j++)
+	{
+		if(gr->NeedStop())	break;
+		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
+		long mz = j<z->GetNy() ? j:0, mr = j<r->GetNy() ? j:0;
+		for(long i=0;i<n;i+=dx)
+		{
+			long k = gr->AddPnt(mglPoint(x->v(i,mx), y->v(i,my), z->v(i,mz)),-1,q);
+			gr->text_plot(k, text, fnt, -0.5*fabs(r->v(i,mr)));
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_textmarkw_xyr(HMGL gr, HCDT x, HCDT y, HCDT r, const wchar_t *text, const char *fnt, const char *opt)
+{
+	gr->SaveState(opt);
+	mglData z(y->GetNx());	z.Fill(gr->Min.z,gr->Min.z);
+	mgl_textmarkw_xyzr(gr,x,y,&z,r,text,fnt,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_textmarkw_yr(HMGL gr, HCDT y, HCDT r, const wchar_t *text, const char *fnt, const char *opt)
+{
+	long n=y->GetNx();
+	gr->SaveState(opt);
+	mglData x(n);	x.Fill(gr->Min.x,gr->Max.x);
+	mglData z(n);	z.Fill(gr->Min.z,gr->Min.z);
+	mgl_textmarkw_xyzr(gr,&x,y,&z,r,text,fnt,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_textmarkw(HMGL gr, HCDT y, const wchar_t *text, const char *fnt, const char *opt)
+{
+	long n=y->GetNx();
+	gr->SaveState(opt);
+	mglData r(n);	r.Fill(1,1);
+	mglData x(n);	x.Fill(gr->Min.x,gr->Max.x);
+	mglData z(n);	z.Fill(gr->Min.z,gr->Min.z);
+	mgl_textmarkw_xyzr(gr,&x,y,&z,&r,text,fnt,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_textmark_xyzr(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT r, const char *str, const char *fnt, const char *opt)
+{	MGL_TO_WCS(str,mgl_textmarkw_xyzr(gr, x, y, z, r, wcs, fnt, opt));	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_textmark_xyr(HMGL gr, HCDT x, HCDT y, HCDT r, const char *str, const char *fnt, const char *opt)
+{	MGL_TO_WCS(str,mgl_textmarkw_xyr(gr, x, y, r, wcs, fnt, opt));	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_textmark_yr(HMGL gr, HCDT y, HCDT r, const char *str, const char *fnt, const char *opt)
+{	MGL_TO_WCS(str,mgl_textmarkw_yr(gr, y, r, wcs, fnt, opt));	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_textmark(HMGL gr, HCDT y, const char *str, const char *fnt, const char *opt)
+{	MGL_TO_WCS(str,mgl_textmarkw(gr, y, wcs, fnt, opt));	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_textmark_xyzr_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *r, const char *text, const char *fnt, const char *opt, int l,int n,int lo)
+{	wchar_t *s=new wchar_t[l+1];	memcpy(s,text,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,fnt,n);	f[n]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_textmarkw_xyzr(_GR_, _DA_(x),_DA_(y),_DA_(z),_DA_(r),s,f, o);
+	delete []o;	delete []s;		delete []f;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_textmark_xyr_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *r, const char *text, const char *fnt, const char *opt, int l,int n,int lo)
+{	wchar_t *s=new wchar_t[l+1];	mbstowcs(s,text,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,fnt,n);	f[n]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_textmarkw_xyr(_GR_, _DA_(x),_DA_(y),_DA_(r),s,f, o);
+	delete []o;	delete []s;	delete []f;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_textmark_yr_(uintptr_t *gr, uintptr_t *y, uintptr_t *r, const char *text, const char *fnt, const char *opt, int l,int n,int lo)
+{	wchar_t *s=new wchar_t[l+1];	mbstowcs(s,text,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,fnt,n);	f[n]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_textmarkw_yr(_GR_, _DA_(y),_DA_(r),s,f, o);	delete []o;	delete []s;	delete []f;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_textmark_(uintptr_t *gr, uintptr_t *y, const char *text, const char *fnt, const char *opt, int l,int n,int lo)
+{	wchar_t *s=new wchar_t[l+1];	mbstowcs(s,text,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,fnt,n);	f[n]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_textmarkw(_GR_, _DA_(y),s,f, o);	delete []o;	delete []s;	delete []f;	}
+//-----------------------------------------------------------------------------
+//
+//	Label series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_labelw_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, const wchar_t *text, const char *fnt, const char *opt)
+{
+	long m,n=y->GetNx();
+	if(mgl_check_dim0(gr,x,y,z,0,"Label"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Label",cgid++);
+	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();	m = z->GetNy() > m ? z->GetNy() : m;
+
+	mglPoint q(NAN);
+
+	char fmt[8]="2",ss[2]=" ";
+	std::string Tstl;
+	for(const char *s="0123456789";*s;s++)	if(mglchr(fnt,*s))	fmt[0] = *s;
+	for(const char *s="f+E-F";*s;s++)	if(mglchr(fnt,*s))
+	{	ss[0] = *s;	strcat(fmt,ss);	}
+	for(long j=0;j<m;j++)
+	{
+		if(gr->NeedStop())	break;
+		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0, mz = j<z->GetNy() ? j:0;
+		for(long i=0;i<n;i++)
+		{
+			mreal xx=x->v(i,mx), yy=y->v(i,my), zz=z->v(i,mz);
+			long kk = gr->AddPnt(mglPoint(xx,yy,zz),-1,q),k,l;
+			std::wstring buf;
+			for(k=l=0;text[k];k++)
+			{
+				if(text[k]!='%' || (k>0 && text[k-1]=='\\'))
+				{	buf += text[k];	continue;	}
+				else if(text[k+1]=='%')	buf+=L"%";
+				else if(text[k+1]=='n')	{	wchar_t tmp[32];	mglprintf(tmp,32,L"%ld",i);	buf += tmp;	}
+				else if(text[k+1]=='x')	buf += mgl_ftoa(xx,fmt);
+				else if(text[k+1]=='y')	buf += mgl_ftoa(yy,fmt);
+				else if(text[k+1]=='z')	buf += mgl_ftoa(zz,fmt);
+				else {	buf+=L"%";	continue;	}
+				k++;
+			}
+			gr->text_plot(kk, buf.c_str(), fnt, -0.7, 0.05);
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_labelw_xy(HMGL gr, HCDT x, HCDT y, const wchar_t *text, const char *fnt, const char *opt)
+{
+	gr->SaveState(opt);
+	mglData z(y->GetNx());	z.Fill(gr->Min.z,gr->Min.z);
+	mgl_labelw_xyz(gr,x,y,&z,text,fnt,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_labelw_y(HMGL gr, HCDT y, const wchar_t *text, const char *fnt, const char *opt)
+{
+	long n=y->GetNx();
+	if(n<2)	{	gr->SetWarn(mglWarnLow,"TextMark");	return;	}
+	gr->SaveState(opt);
+	mglData x(n);	x.Fill(gr->Min.x,gr->Max.x);
+	mglData z(n);	z.Fill(gr->Min.z,gr->Min.z);
+	mgl_labelw_xyz(gr,&x,y,&z,text,fnt,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_label_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, const char *str, const char *fnt, const char *opt)
+{	MGL_TO_WCS(str,mgl_labelw_xyz(gr, x, y, z, wcs, fnt, opt));	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_label_xy(HMGL gr, HCDT x, HCDT y, const char *str, const char *fnt, const char *opt)
+{	MGL_TO_WCS(str,mgl_labelw_xy(gr, x, y, wcs, fnt, opt));	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_label_y(HMGL gr, HCDT y, const char *str, const char *fnt, const char *opt)
+{	MGL_TO_WCS(str,mgl_labelw_y(gr, y, wcs, fnt, opt));	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_label_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *text, const char *fnt, const char *opt, int l,int n,int lo)
+{	wchar_t *s=new wchar_t[l+1];	mbstowcs(s,text,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,fnt,n);	f[n]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_labelw_xyz(_GR_, _DA_(x),_DA_(y),_DA_(z),s,f, o);
+	delete []o;	delete []s;		delete []f;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_label_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, const char *text, const char *fnt, const char *opt, int l,int n,int lo)
+{	wchar_t *s=new wchar_t[l+1];	mbstowcs(s,text,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,fnt,n);	f[n]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_labelw_xy(_GR_, _DA_(x),_DA_(y),s,f, o);
+	delete []o;	delete []s;	delete []f;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_label_y_(uintptr_t *gr, uintptr_t *y, const char *text, const char *fnt, const char *opt, int l,int n,int lo)
+{	wchar_t *s=new wchar_t[l+1];	mbstowcs(s,text,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,fnt,n);	f[n]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_labelw_y(_GR_, _DA_(y),s,f, o);	delete []o;	delete []s;	delete []f;	}
+//-----------------------------------------------------------------------------
+//
+//	Table series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tablew(HMGL gr, double x, double y, HCDT val, const wchar_t *text, const char *fnt, const char *opt)
+{
+	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);
+	if(g)	g->Table(x,y,val,text,fnt,opt);
+}
+void MGL_EXPORT mgl_table(HMGL gr, double x, double y, HCDT val, const char *text, const char *fnt, const char *opt)
+{
+	if(!text)	mgl_tablew(gr,x,y,val,L"",fnt,opt);
+	else	MGL_TO_WCS(text,mgl_tablew(gr, x, y, val, wcs, fnt, opt));
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_table_(uintptr_t *gr, mreal *x, mreal *y, uintptr_t *val, const char *text, const char *fnt, const char *opt,int l,int n,int lo)
+{	wchar_t *s=new wchar_t[l+1];	mbstowcs(s,text,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,fnt,n);	f[n]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tablew(_GR_, *x, *y, _DA_(val),s,f, o);
+	delete []o;	delete []s;	delete []f;	}
+//-----------------------------------------------------------------------------
+//
+//	Logo series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_logo(HMGL gr, long w, long h, const unsigned char *rgba, int smooth, const char *opt)
+{
+	if(w<1 || h<1 || !rgba)	{	gr->SetWarn(mglWarnLow,"Logo");	return;	}
+	static int cgid=1;	gr->StartGroup("Logo",cgid++);
+	mreal z = gr->SaveState(opt);
+	if(mgl_isnan(z))	z = gr->Min.z;
+	mreal x1 = gr->Min.x, y1 = gr->Min.y, dx, dy;
+	if(!smooth || w<2 || h<2)
+	{
+		dx = (gr->Max.x-x1)/w;	dy = (gr->Max.y-y1)/h;
+		gr->Reserve(4*(w+1)*(h+1));
+		for(long j=0;j<h;j++)	for(long i=0;i<w;i++)
+		{
+			long i0 = 4*(i+w*(h-1-j)), k1,k2,k3,k4;
+			mglColor c(rgba[i0]/255.,rgba[i0+1]/255.,rgba[i0+2]/255.);
+			k1 = gr->AddPnt(mglPoint(x1+dx*i,y1+dy*j,z),0);	gr->SetRGBA(k1,c);
+			k2 = gr->AddPnt(mglPoint(x1+dx*(i+1),y1+dy*j,z),0);	gr->SetRGBA(k2,c);
+			k3 = gr->AddPnt(mglPoint(x1+dx*i,y1+dy*(j+1),z),0);	gr->SetRGBA(k3,c);
+			k4 = gr->AddPnt(mglPoint(x1+dx*(i+1),y1+dy*(j+1),z),0);	gr->SetRGBA(k4,c);
+			gr->quad_plot(k1,k2,k3,k4);
+		}
+	}
+	else
+	{
+		dx = (gr->Max.x-x1)/(w-1);	dy = (gr->Max.y-y1)/(h-1);
+		gr->Reserve(w*h);
+		long *pos = new long[w*h];
+		for(long j=0;j<h;j++)	for(long i=0;i<w;i++)
+		{
+			long i0 = 4*(i+w*(h-1-j)), i1 = i+w*j;
+			pos[i1] = gr->AddPnt(mglPoint(x1+dx*i,y1+dy*j,z),0);
+			gr->SetRGBA(pos[i1],mglColor(rgba[i0]/255.,rgba[i0+1]/255.,rgba[i0+2]/255.));
+		}
+		for(long j=0;j<h-1;j++)	for(long i=0;i<w-1;i++)
+		{
+			long i1 = i+w*j;
+			gr->quad_plot(pos[i1],pos[i1+1],pos[i1+w],pos[i1+1+w]);
+		}
+		delete []pos;
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+bool MGL_NO_EXPORT mgl_read_image(unsigned char **g, int &w, int &h, const char *fname);
+void MGL_EXPORT mgl_logo_file(HMGL gr, const char *fname, int smooth, const char *opt)
+{
+	unsigned char *g = 0;
+	int w=0, h=0;
+	if(!mgl_read_image(&g,w,h,fname))	return;
+	mgl_logo(gr,w,h,g,smooth,opt);
+	delete []g;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_logo_file_(uintptr_t *gr, const char *fname, int *smooth, const char *opt,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,fname,l);	s[l]=0;
+	char *f=new char[n+1];	memcpy(f,opt,n);	f[n]=0;
+	mgl_logo_file(_GR_,s,*smooth,f);	delete []s;		delete []f;	}
+//-----------------------------------------------------------------------------
+//
+//	Lamerey series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_lamerey(HMGL gr, double x0, double (*f)(double,void *), void *par, const char *stl, const char *opt)
+{
+	static int cgid=1;	gr->StartGroup("Lamerey",cgid++);
+	mreal r=gr->SaveState(opt);
+	double x=x0, dx = 1e-5*fabs(gr->Max.x-gr->Min.x);
+	long n = r>2 ? long(r+0.5):20, n1, n2;
+	gr->SetPenPal(stl);	gr->Reserve(6*n+1);
+	bool vect = mglchr(stl,'v');
+	n2 = gr->AddPnt(mglPoint(x,x,gr->Max.z));
+	if(!mglchr(stl,'~'))
+	{
+		n1 = gr->AddPnt(mglPoint(x,gr->GetOrgY('x'),gr->Max.z));
+		gr->line_plot(n1,n2);	if(vect)	gr->vect_plot(n1,n2,0.3*gr->GetArrowSize());
+	}
+	for(long i=0;i<n;i++)
+	{
+		x0 = x;		x = f(x0,par);
+		if(fabs(x-x0)<dx)	break;
+		n1=n2;	n2 = gr->AddPnt(mglPoint(x0,x,gr->Max.z));
+		gr->line_plot(n1,n2);	if(vect)	gr->vect_plot(n1,n2,0.3*gr->GetArrowSize());
+		n1=n2;	n2 = gr->AddPnt(mglPoint(x,x,gr->Max.z));
+		gr->line_plot(n1,n2);	if(vect)	gr->vect_plot(n1,n2,0.3*gr->GetArrowSize());
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+struct mglDatSpl	{	HCDT d;	double x0,dx;	double y0,dy;	};
+double MGL_NO_EXPORT func_dat(double x, void *p)
+{	mglDatSpl *s = (mglDatSpl *)p;	return s->d->value((x-s->x0)*s->dx);	}
+void MGL_EXPORT mgl_lamerey_dat(HMGL gr, double x0, HCDT f, const char *stl, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	char buf[64]="";	if(r>2)	sprintf(buf,"value %g",r);
+	mglDatSpl s;	s.d=f;	s.x0=gr->Min.x;	s.dx=f->GetNx()/(gr->Max.x-gr->Min.x);
+	mgl_lamerey(gr,x0,func_dat,&s,stl,buf);
+}
+//-----------------------------------------------------------------------------
+double MGL_NO_EXPORT func_str(double x, void *p)
+{	HMEX s = (HMEX)p;	return mgl_expr_eval(s,x,0,0);	}
+void MGL_EXPORT mgl_lamerey_str(HMGL gr, double x0, const char *f, const char *stl, const char *opt)
+{
+	HMEX eq = mgl_create_expr(f);
+	mgl_lamerey(gr,x0,func_str,eq,stl,opt);
+	mgl_delete_expr(eq);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_lamerey_dat_(uintptr_t *gr, double *x0, uintptr_t *f, const char *stl, const char *opt, int l,int n)
+{	char *s=new char[l+1];	memcpy(s,stl,l);	s[l]=0;
+	char *o=new char[n+1];	memcpy(o,opt,n);	o[n]=0;
+	mgl_lamerey_dat(_GR_,*x0,_DA_(f),s,o);	delete []s;	delete []o;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_lamerey_str_(uintptr_t *gr, double *x0, const char *func, const char *stl, const char *opt, int m,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,stl,l);	s[l]=0;
+	char *o=new char[n+1];	memcpy(o,opt,n);	o[n]=0;
+	char *f=new char[m+1];	memcpy(f,func,m);	f[m]=0;
+	mgl_lamerey_str(_GR_,*x0,f,s,o);	delete []f;	delete []s;	delete []o;	}
+//-----------------------------------------------------------------------------
+//
+//	Bifurcation series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_bifurcation(HMGL gr, double dx, double (*f)(double,double,void *), void *par, const char *stl, const char *opt)
+{
+	if((gr->Max.x-gr->Min.x)*dx<=0)	{	gr->SetWarn(mglWarnSlc,"Bifurcation");	return;	}
+	static int cgid=1;	gr->StartGroup("Bifurcation",cgid++);
+	mreal res=gr->SaveState(opt);
+	long n = res>2 ? long(res+0.5):1024, m=(gr->Max.x-gr->Min.x)/dx, m1=0,m2=0;
+	gr->SetPenPal(stl);	gr->Reserve(2*n*m);
+	double *v1=new double[n], *v2=new double[n], dd=0.1*fabs(gr->Max.y-gr->Min.y)/n;
+	double r = gr->Min.y+mgl_rnd()*(gr->Max.y-gr->Min.y), r0 = r;
+
+	bool fin=false;
+	for(long i=0;i<10*n;i++)	r = f(gr->Min.x,r,par);	// wait for loop stabilization
+	for(m1=0;m1<n;m1++)	// collect period information
+	{
+		r = f(gr->Min.x,r,par);
+		for(long j=0;j<m1;j++)	if(fabs(v1[j]-r)<dd)
+		{	fin=true;	break;	}
+		if(fin)	break;	else	v1[m1]=r;
+	}
+	for(mreal xx = gr->Min.x+dx;xx<=gr->Max.x;xx+=dx)
+	{
+		m2=m1;	memcpy(v2,v1,n*sizeof(double));	r=r0;
+		for(long i=0;i<10*n;i++)	r = f(xx,r,par);	// wait for loop stabilization
+		for(fin=false,m1=0;m1<n;m1++)	// collect period information
+		{
+			r = f(xx,r,par);
+			for(long j=0;j<m1;j++)	if(fabs(v1[j]-r)<dd)
+			{	fin=true;	break;	}
+			if(fin)	break;	else	v1[m1]=r;
+		}
+		if(m1>=m2)	for(long i=0;i<m1;i++)
+		{
+			double vv=v2[0], vi=v1[i];
+			for(long j=1;j<m2;j++)	if(fabs(v2[j]-vi)<fabs(vv-vi))	vv = v2[j];
+			gr->line_plot(gr->AddPnt(mglPoint(xx-dx,vv,gr->Max.z)), gr->AddPnt(mglPoint(xx,v1[i],gr->Max.z)));
+		}
+		else	for(long i=0;i<m1;i++)
+			gr->line_plot(gr->AddPnt(mglPoint(xx-dx,v1[i],gr->Max.z)), gr->AddPnt(mglPoint(xx,v1[i],gr->Max.z)));
+	}
+	gr->EndGroup();	delete []v1;	delete []v2;
+}
+//-----------------------------------------------------------------------------
+double MGL_NO_EXPORT bif_dat(double x, double y, void *p)
+{	mglDatSpl *s = (mglDatSpl *)p;	return s->d->value((x-s->x0)*s->dx, (y-s->y0)*s->dy);	}
+void MGL_EXPORT mgl_bifurcation_dat(HMGL gr, double dx, HCDT f, const char *stl, const char *opt)
+{
+	if(dx==0 || (gr->Max.x-gr->Min.x)*dx<0)	{	gr->SetWarn(mglWarnSlc,"Bifurcation");	return;	}
+	if(f->GetNy()<2)	{	gr->SetWarn(mglWarnLow,"Bifurcation");	return;	}
+	mreal r = gr->SaveState(opt);
+	char buf[64]="";	if(r>2)	sprintf(buf,"value %g",r);
+	mglDatSpl s;	s.d=f;
+	s.x0=gr->Min.x;	s.dx=f->GetNx()/(gr->Max.x-gr->Min.x);
+	s.y0=gr->Min.y;	s.dy=f->GetNy()/(gr->Max.y-gr->Min.y);
+	mgl_bifurcation(gr,dx,bif_dat,&s,stl,buf);
+}
+//-----------------------------------------------------------------------------
+double MGL_NO_EXPORT bif_str(double x, double y, void *p)
+{	HMEX s = (HMEX)p;	return mgl_expr_eval(s,x,y,0);	}
+void MGL_EXPORT mgl_bifurcation_str(HMGL gr, double dx, const char *f, const char *stl, const char *opt)
+{
+	HMEX eq = mgl_create_expr(f);
+	mgl_bifurcation(gr,dx,bif_str,eq,stl,opt);
+	mgl_delete_expr(eq);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_bifurcation_dat_(uintptr_t *gr, double *dx, uintptr_t *f, const char *stl, const char *opt, int l,int n)
+{	char *s=new char[l+1];	memcpy(s,stl,l);	s[l]=0;
+	char *o=new char[n+1];	memcpy(o,opt,n);	o[n]=0;
+	mgl_bifurcation_dat(_GR_,*dx,_DA_(f),s,o);	delete []s;	delete []o;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_bifurcation_str_(uintptr_t *gr, double *dx, const char *func, const char *stl, const char *opt, int m,int l,int n)
+{	char *s=new char[l+1];	memcpy(s,stl,l);	s[l]=0;
+	char *o=new char[n+1];	memcpy(o,opt,n);	o[n]=0;
+	char *f=new char[m+1];	memcpy(f,func,m);	f[m]=0;
+	mgl_bifurcation_str(_GR_,*dx,f,s,o);	delete []f;	delete []s;	delete []o;	}
+//-----------------------------------------------------------------------------
+//
+// Iris series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_irisw(HMGL gr, HCDT dats, HCDT ranges, const wchar_t *ids, const char *stl, const char *opt)
+{
+	long m=dats->GetNx(), nx=dats->GetNy(), ny=dats->GetNz();	// TODO parse several slices?
+	if(m<2 || nx<2)	{	gr->SetWarn(mglWarnLow,"Iris");	return;	}
+	if(m!=ranges->GetNy())	{	gr->SetWarn(mglWarnDim,"Iris");	return;	}
+	mglCanvas *g = dynamic_cast<mglCanvas *>(gr);	if(!g)	return;
+	mreal ofsize = gr->GetFontSize();
+	mreal res=gr->SaveState(opt), fsize = gr->GetFontSize();
+	if(mgl_isnan(res))	res=-1;
+	res /= m;
+	static int cgid=1;	gr->StartGroup("Iris",cgid++);
+	std::wstring *strs = new std::wstring[m];
+	bool label = ids && ids[0];	// disable axis drawing
+	if(label)
+	{
+		const wchar_t *s, *p=ids;
+		if(wcschr(ids,';'))	for(long i=0;i<m;i++)
+		{
+			s = wcschr(p,';');
+			if(s)	{	strs[i] = std::wstring(p,s-p);	p = s+1;	}
+			else	{	strs[i] = p;	break;	}
+		}
+// 		else	for(long i=0;i<m;i++)
+// 		{
+// 			s = wcsstr(p,L"\\t ");
+// 			if(s)	{	strs[i] = std::wstring(p,s-p);	p = s+3;	}
+// 			else	{	strs[i] = p;	break;	}
+// 		}
+	}
+	HMDT dat[m];
+	mreal dx = 1./m;
+	for(long i=0;i<m;i++)	dat[i]=mgl_data_subdata(dats,i,-1,-1);
+	for(long i=0;i<m;i++)	for(long j=0;j<m;j++)
+	{
+		g->InPlot(dx*i,dx*(i+1),dx*(m-j-1),dx*(m-j),true);
+		if(label)	g->Box();
+		gr->SetRanges(ranges->v(0,i),ranges->v(1,i),ranges->v(0,j),ranges->v(1,j));
+		gr->ResetPal();
+		gr->SetFontSize(fsize);
+		if(i==j)
+		{
+			const char *tstl = wcschr(strs[i].c_str(),'\n') || wcsstr(strs[i].c_str(),L"\\n ") ? "a":"aV";
+			mgl_putsw(gr, dx*(i+0.5), dx*(m-j-0.5),0, strs[i].c_str(), tstl, res);
+		}
+		else	mgl_plot_xy(gr,dat[i],dat[j],stl,NULL);
+	}
+	if(label)
+	{
+		for(long i=0;i<m;i+=2)
+		{
+			gr->SetRanges(ranges->v(0,i),ranges->v(1,i),ranges->v(0,m-i-1),ranges->v(1,m-i-1));
+			gr->SetFontSize(fsize);	g->InPlot(dx*i,dx*(i+1),0,dx,true);	g->Axis("x");
+			gr->SetFontSize(fsize);	g->InPlot(0,dx,dx*i,dx*(i+1),true);	g->Axis("y");
+		}
+		for(long i=1;i<m;i+=2)
+		{
+			gr->SetRanges(ranges->v(0,i),ranges->v(1,i),ranges->v(0,m-i-1),ranges->v(1,m-i-1));
+			gr->SetFontSize(fsize);	g->InPlot(dx*i,dx*(i+1),1-dx,1,true);	g->Axis("x^");
+			gr->SetFontSize(fsize);	g->InPlot(1-dx,1,dx*i,dx*(i+1),true);	g->Axis("y^");
+		}
+	}
+	delete []strs;	for(long i=0;i<m;i++)	delete dat[i];
+	g->InPlot(0,1,0,1,true);	gr->EndGroup();	gr->SetFontSize(ofsize);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_irisw_1(HMGL gr, HCDT dats, const wchar_t *ids, const char *stl, const char *opt)
+{
+	long n=dats->GetNy()*dats->GetNz(), m=dats->GetNx();
+	mglData ranges(2,m);
+	for(long i=0;i<m;i++)
+	{
+		mreal &v1=ranges.a[2*i], &v2=ranges.a[1+2*i];
+		v1=INFINITY;	v2=-INFINITY;
+		for(long j=0;j<n;j++)
+		{
+			mreal v = dats->vthr(i+m*j);
+			if(v<v1)	v1=v;
+			if(v>v2)	v2=v;
+		}
+		if(!mgl_isnum(v1))	{	v1=-1;	v2=1;	}
+		if(v1==v2)	{	v1-=1;	v2+=1;	}
+	}
+	mgl_irisw(gr,dats,&ranges,ids,stl,opt);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_iris(HMGL gr, HCDT dats, HCDT ranges, const char *ids, const char *stl, const char *opt)
+{
+	MGL_TO_WCS(ids,mgl_irisw(gr, dats, ranges, wcs, stl, opt));
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_iris_1(HMGL gr, HCDT dats, const char *ids, const char *stl, const char *opt)
+{
+	MGL_TO_WCS(ids,mgl_irisw_1(gr, dats, wcs, stl, opt));
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_iris_(uintptr_t *gr, uintptr_t *dats, uintptr_t *ranges, const char *ids, const char *stl, const char *opt,int l,int m,int n)
+{	char *i=new char[l+1];	memcpy(i,ids,l);	i[l]=0;
+	char *s=new char[m+1];	memcpy(s,stl,m);	s[m]=0;
+	char *o=new char[n+1];	memcpy(o,opt,n);	o[n]=0;
+	mgl_iris(_GR_,_DA_(dats),_DA_(ranges),i,s,o);	delete []i;	delete []s;	delete []o;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_iris_1_(uintptr_t *gr, uintptr_t *dats, const char *ids, const char *stl, const char *opt,int l,int m,int n)
+{	char *i=new char[l+1];	memcpy(i,ids,l);	i[l]=0;
+	char *s=new char[m+1];	memcpy(s,stl,m);	s[m]=0;
+	char *o=new char[n+1];	memcpy(o,opt,n);	o[n]=0;
+	mgl_iris_1(_GR_,_DA_(dats),i,s,o);	delete []i;	delete []s;	delete []o;	}
+//-----------------------------------------------------------------------------
diff --git a/src/s_hull/COPYING.txt b/src/s_hull/COPYING.txt
new file mode 100644
index 0000000..e11e9cf
--- /dev/null
+++ b/src/s_hull/COPYING.txt
@@ -0,0 +1,49 @@
+S-hull, Copyright (c) 2010
+Dr David SInclair
+Cambridge, UK
+
+email david at s-hull.org
+
+The software includes the S-hull programs.
+S-hull is copyrighted as above.
+S-hull is free software and may be obtained from www.s-hull.org.
+It may be freely copied, modified, 
+and redistributed under the following conditions:
+S-hull is free software and may be obtained from www.s-hull.org.
+It may be freely copied, modified, 
+and redistributed under the following conditions which might loosely be termed a contribtors beerware license:
+1. All copyright notices must remain intact in all files.
+2. A copy of this text file must be distributed along with any copies 
+   of S-hull that you redistribute; this includes copies that you have 
+   modified, or copies of programs or other software products that 
+   include S-hull where distributed as source.
+
+3. If you modify S-hull, you must include a notice giving the
+   name of the person performing the modification, the date of
+   modification, and the reason for such modification.
+
+4. If you are distributing a binary or compiled version of s-hull it
+	    is not necessary to include any acknowledgement or reference
+	    to s-hull.
+5. There is no warranty or other guarantee of fitness for S-hull, it is 
+   provided solely "as is".  Bug reports or fixes may be sent to 
+   bugs at s-hull.org; the authors may or may not act on them as 
+   they desire.
+6. By copying or compliing the code for S-hull you explicitly indemnify 
+the copyright holder against any liability he may incur as a result of you 
+copying the code.
+
+7. If you meet any of the contributors to the code you used from s-hull.org
+	    in a pub or a bar, and you think the source code they contributed to is worth it,
+	    you can buy them a beer.
+
+	    If your principles run against beer a bacon-double-cheeseburger would do just as nicely
+	    or you could email david at s-hull.org and arrange to make a donation of 10 of your local currancy units
+	    to support s-hull.org.
+	    
+-------------------
+
+This is permission to use s-hull-pro mathgl as long as the routines retain
+my copyright notice. I an happy for it to be included in an LGPL product and 
+I am happy for the source to be bundled with mathgl under whatever license you
+use for that.
diff --git a/src/s_hull/s_hull_pro.cpp b/src/s_hull/s_hull_pro.cpp
new file mode 100644
index 0000000..eb022b4
--- /dev/null
+++ b/src/s_hull/s_hull_pro.cpp
@@ -0,0 +1,2159 @@
+#include <iostream>
+//#include <hash_set.h>
+//#include <hash_set>
+#include <set>
+#include <vector>
+#include <fstream>
+#include <stdlib.h>
+#include <math.h>
+#include <string>
+#include <algorithm>
+
+
+#include "s_hull_pro.h"
+
+using namespace std;
+
+
+/* copyright 2012 Dr David Sinclair
+   david at s-hull.org
+
+	program to compute Delaunay triangulation of a set of points.
+
+	this code may not be published or distributed without the concent of the copyright holder.
+
+ */
+
+
+// Global replace int->long by A.Balakin 21 April 2014 -- 64bit version can handle huge data arrays
+
+
+void circle_cent2(double r1,double c1, double r2,double c2, double r3,double c3,
+				  double &r,double &c, double &ro2)
+{
+	/*
+	 *  function to return the center of a circle and its radius
+	 * degenerate case should never be passed to this routine!!!!!!!!!!!!!
+	 * but will return r0 = -1 if it is.
+	 */
+
+	double a1 = (r1+r2)/2.0;
+	double a2 = (c1+c2)/2.0;
+	double b1 = (r3+r2)/2.0;
+	double b2 = (c3+c2)/2.0;
+
+	double e2 = r1-r2;
+	double e1 = -c1+c2;
+
+	double q2 = r3-r2;
+	double q1 = -c3+c2;
+
+	r=0;
+	c=0;
+	ro2=-1;
+	if( e1*-q2 + e2*q1 == 0 ) return;
+
+	double beta = (-e2*(b1-a1) + e1*(b2-a2))/( e2*q1-e1*q2);
+
+	r = b1 + q1*beta;
+	c = b2 + q2*beta;
+
+	ro2 = (r1-r)*(r1-r) + (c1-c)*(c1-c);
+	return;
+}
+
+
+/*
+    read an ascii file of (r,c) point pairs.
+
+    the first line of the points file should contain
+    "NUMP  2 points"
+
+    if it does not have the word points in it the first line is
+    interpretted as a point pair.
+
+ */
+
+long read_Shx(std::vector<Shx> &pts, char * fname)
+{
+	char s0[513];
+	long nump =0;
+	double p1,p2;
+
+	Shx pt;
+
+	std::string line;
+	std::string points_str("points");
+
+	std::ifstream myfile;
+	myfile.open(fname);
+
+	if (myfile.is_open())
+	{
+
+		getline (myfile,line);
+		//long numc = line.length();
+
+		// check string for the string "points"
+		long n = (long) line.find( points_str);
+		if( n > 0)
+		{
+			while ( myfile.good() )
+			{
+				getline (myfile,line);
+				if( line.length() <= 512)
+				{
+					copy( line.begin(), line.end(), s0);
+					s0[line.length()] = 0;
+					long v = sscanf( s0, "%lg %lg", &p1,&p2);
+					if( v>0 ) {
+						pt.id = nump;
+						nump++;
+						pt.r = p1;
+						pt.c = p2;
+						pts.push_back(pt);
+					}
+				}
+			}
+		}
+		else    // assume all number pairs on a line are points
+		{
+			if( line.length() <= 512)
+			{
+				copy( line.begin(), line.end(), s0);
+				s0[line.length()] = 0;
+				long v = sscanf( s0, "%lg %lg", &p1,&p2);
+				if( v>0 )
+				{
+					pt.id = nump;
+					nump++;
+					pt.r = p1;
+					pt.c = p2;
+					pts.push_back(pt);
+				}
+			}
+
+			while ( myfile.good() )
+			{
+				getline (myfile,line);
+				if( line.length() <= 512)
+				{
+					copy( line.begin(), line.end(), s0);
+					s0[line.length()] = 0;
+					long v = sscanf( s0, "%lg %lg", &p1,&p2);
+					if( v>0 )
+					{
+						pt.id = nump;
+						nump++;
+						pt.r = p1;
+						pt.c = p2;
+						pts.push_back(pt);
+					}
+				}
+			}
+		}
+		myfile.close();
+	}
+
+	nump = (long) pts.size();
+
+	return(nump);
+}
+
+/*
+	write out a set of points to disk
+
+
+*/
+
+void write_Shx(std::vector<Shx> &pts, char * fname)
+{
+	std::ofstream out(fname, ios::out);
+
+	long nr = (long) pts.size();
+	out << nr << " 2 points" << endl;
+
+	for (long r = 0; r < nr; r++)
+	{
+		out << pts[r].r << ' ' << pts[r].c <<  endl;
+	}
+	out.close();
+
+	return;
+}
+
+
+
+/*
+ write out triangle ids to be compatible with matlab/octave array numbering.
+
+ */
+void write_Triads(std::vector<Triad> &ts, char * fname)
+{
+	std::ofstream out(fname, ios::out);
+
+	long nr = (long) ts.size();
+	out << nr << " 6   point-ids (1,2,3)  adjacent triangle-ids ( limbs ab  ac  bc )" << endl;
+
+	for (long r = 0; r < nr; r++)
+	{
+		out << ts[r].a+1 << ' ' << ts[r].b+1 <<' ' << ts[r].c+1 <<' '
+			<< ts[r].ab+1 <<' ' << ts[r].ac+1 <<' ' << ts[r].bc+1 << endl; //" " << ts[r].ro <<  endl;
+	}
+	out.close();
+
+	return;
+}
+
+
+
+
+
+/*  version in which the ids of the triangles associated with the sides of the hull are tracked.
+
+
+ */
+
+long s_hull_pro( std::vector<Shx> &pts, std::vector<Triad> &triads)
+{
+
+	long nump = (long) pts.size();
+
+	if( nump < 3 )
+	{
+// Commented by A.Balakin 21 April 2014 -- library shouldn't print anything
+//		cerr << "less than 3 points, aborting " << endl;
+		return(-1);
+	}
+
+
+	double r = pts[0].r;
+	double c = pts[0].c;
+	for( long k=0; k<nump; k++)
+	{
+		double dr = pts[k].r-r;
+		double dc = pts[k].c-c;
+
+		pts[k].ro = dr*dr + dc*dc;
+
+	}
+
+	sort( pts.begin(), pts.end() );
+
+
+	double r1 = pts[0].r;
+	double c1 = pts[0].c;
+
+	double r2 = pts[1].r;
+	double c2 = pts[1].c;
+	long mid = -1;
+	double romin2 =  9.0e20, ro2, R=0,C=0;	// added by A.Balakin 21 April 2014 -- uninitialised variable
+
+	long k=2;
+	while (k<nump)
+	{
+
+		circle_cent2(r1,c1,r2,c2,  pts[k].r,  pts[k].c, r,c,ro2);
+		if( ro2 < romin2 && ro2 > 0 )
+		{
+			mid = k;
+			romin2 = ro2;
+			R = r;
+			C = c;
+
+		}
+		else if( romin2 *4 < pts[k].ro )
+			k=nump;
+
+		k++;
+	}
+
+	if( mid < 0 )
+	{
+// Commented by A.Balakin 21 April 2014 -- library shouldn't print anything
+//		cerr << "linear structure, aborting " << endl;
+		return(-2);
+	}
+
+
+	Shx pt0 = pts[0];
+	Shx pt1 = pts[1];
+	Shx pt2 = pts[mid];
+
+	pts.erase(pts.begin() + mid);  // necessary for round off reasons:((((((
+	pts.erase(pts.begin() );
+	pts.erase(pts.begin() );
+
+	for( long k=0; k<nump-3; k++)
+	{
+		double dr = pts[k].r-R;
+		double dc = pts[k].c-C;
+
+		pts[k].ro = dr*dr + dc*dc;
+
+	}
+
+	sort( pts.begin(), pts.end() );
+
+	pts.insert(pts.begin(), pt2);
+	pts.insert(pts.begin(), pt1);
+	pts.insert(pts.begin(), pt0);
+
+	std::vector<long> slump;
+	slump.resize(nump);
+
+	for( long k=0; k<nump; k++)
+	{
+		if( pts[k].id < nump)
+		{
+			slump[ pts[k].id] = k;
+		}
+		else
+		{
+			long mx = pts[k].id+1;
+			while( (long) slump.size() <= mx)
+			{
+				slump.push_back(0);
+			}
+			slump[pts[k].id] = k;
+		}
+	}
+
+	std::vector<Shx> hull;
+
+
+	r = (pts[0].r + pts[1].r + pts[2].r )/(double) 3.0;
+	c = (pts[0].c + pts[1].c + pts[2].c )/(double) 3.0;
+
+	double dr0 = pts[0].r - r,  dc0 = pts[0].c - c;
+	double tr01 =  pts[1].r - pts[0].r, tc01 =  pts[1].c - pts[0].c;
+
+	double df = -tr01* dc0 + tc01*dr0;
+	if( df < 0 )    // [ 0 1 2 ]
+	{
+		pt0.tr = pt1.r-pt0.r;
+		pt0.tc = pt1.c-pt0.c;
+		pt0.trid = 0;
+		hull.push_back( pt0 );
+
+		pt1.tr = pt2.r-pt1.r;
+		pt1.tc = pt2.c-pt1.c;
+		pt1.trid = 0;
+		hull.push_back( pt1 );
+
+		pt2.tr = pt0.r-pt2.r;
+		pt2.tc = pt0.c-pt2.c;
+		pt2.trid = 0;
+		hull.push_back( pt2 );
+
+
+		Triad tri(pt0.id,pt1.id,pt2.id);
+		tri.ro = romin2;
+		tri.R = R;
+		tri.C = C;
+
+		triads.push_back(tri);
+
+	}
+	else           // [ 0 2 1 ] as anti-clockwise turning is the work of the devil....
+	{
+		pt0.tr = pt2.r-pt0.r;
+		pt0.tc = pt2.c-pt0.c;
+		pt0.trid = 0;
+		hull.push_back( pt0 );
+
+		pt2.tr = pt1.r-pt2.r;
+		pt2.tc = pt1.c-pt2.c;
+		pt2.trid = 0;
+		hull.push_back( pt2 );
+
+		pt1.tr = pt0.r-pt1.r;
+		pt1.tc = pt0.c-pt1.c;
+		pt1.trid = 0;
+		hull.push_back( pt1 );
+
+		Triad tri(pt0.id,pt2.id,pt1.id);
+		tri.ro = romin2;
+		tri.R = R;
+		tri.C = C;
+		triads.push_back(tri);
+	}
+
+	// add new points into hull (removing obscured ones from the chain)
+	// and creating triangles....
+	// that will need to be flipped.
+
+	double dr, dc, rx,cx;
+	Shx  ptx;
+	long numt=0;	// added by A.Balakin 21 April 2014 -- uninitialised variable
+
+	for( long k=3; k<nump; k++)
+	{
+		rx = pts[k].r;
+		cx = pts[k].c;
+		ptx.r = rx;
+		ptx.c = cx;
+		ptx.id = pts[k].id;
+
+		long numh = (long) hull.size()/*, numh_old = numh*/;	// commented by A.Balakin 21 April 2014 -- unused variable
+		dr = rx- hull[0].r;
+		dc = cx- hull[0].c;  // outwards pointing from hull[0] to pt.
+
+		std::vector<long> pidx, tridx;
+		long hidx;  // new hull point location within hull.....
+
+
+		double df = -dc* hull[0].tr + dr*hull[0].tc;    // visibility test vector.
+		if( df < 0 )   // starting with a visible hull facet !!!
+		{
+//			long e1 = 1, e2 = numh;	// commented by A.Balakin 21 April 2014 -- unused variable
+			hidx = 0;
+
+			// check to see if segment numh is also visible
+			df = -dc* hull[numh-1].tr + dr*hull[numh-1].tc;
+			//cerr << df << ' ' ;
+			if( df < 0 )     // visible.
+			{
+				pidx.push_back(hull[numh-1].id);
+				tridx.push_back(hull[numh-1].trid);
+
+
+				for( long h=0; h<numh-1; h++)
+				{
+					// if segment h is visible delete h
+					dr = rx- hull[h].r;
+					dc = cx- hull[h].c;
+					df = -dc* hull[h].tr + dr*hull[h].tc;
+					pidx.push_back(hull[h].id);
+					tridx.push_back(hull[h].trid);
+					if( df < 0 )
+					{
+						hull.erase(hull.begin() + h);
+						h--;
+						numh--;
+					}
+					else 	  // quit on invisibility
+					{
+						ptx.tr = hull[h].r - ptx.r;
+						ptx.tc = hull[h].c - ptx.c;
+
+						hull.insert( hull.begin() , ptx);
+						numh++;
+						break;
+					}
+				}
+				// look backwards through the hull structure.
+
+				for( long h=numh-2; h>0; h--)
+				{
+					// if segment h is visible delete h + 1
+					dr = rx- hull[h].r;
+					dc = cx- hull[h].c;
+					df = -dc* hull[h].tr + dr*hull[h].tc;
+
+					if( df < 0 )   // h is visible
+					{
+						pidx.insert(pidx.begin(), hull[h].id);
+						tridx.insert(tridx.begin(), hull[h].trid);
+						hull.erase(hull.begin() + h+1);  // erase end of chain
+
+					}
+					else
+					{
+
+						h = (long) hull.size()-1;
+						hull[h].tr = -hull[h].r + ptx.r;   // points at start of chain.
+						hull[h].tc = -hull[h].c + ptx.c;
+						break;
+					}
+				}
+
+				df = 9;
+
+			}
+			else
+			{
+				//	cerr << df << ' ' << endl;
+				hidx = 1;  // keep pt hull[0]
+				tridx.push_back(hull[0].trid);
+				pidx.push_back(hull[0].id);
+
+				for( long h=1; h<numh; h++)
+				{
+					// if segment h is visible delete h
+					dr = rx- hull[h].r;
+					dc = cx- hull[h].c;
+					df = -dc* hull[h].tr + dr*hull[h].tc;
+					pidx.push_back(hull[h].id);
+					tridx.push_back(hull[h].trid);
+					if( df < 0 )                      // visible
+					{
+						hull.erase(hull.begin() + h);
+						h--;
+						numh--;
+					}
+					else 	  // quit on invisibility
+					{
+						ptx.tr = hull[h].r - ptx.r;
+						ptx.tc = hull[h].c - ptx.c;
+
+						hull[h-1].tr = ptx.r - hull[h-1].r;
+						hull[h-1].tc = ptx.c - hull[h-1].c;
+
+						hull.insert( hull.begin()+h, ptx);
+						break;
+					}
+				}
+			}
+
+			df = 8;
+
+		}
+		else
+		{
+			long e1 = -1,  e2 = numh;
+			for( long h=1; h<numh; h++)
+			{
+				dr = rx- hull[h].r;
+				dc = cx- hull[h].c;
+				df = -dc* hull[h].tr + dr*hull[h].tc;
+				if( df < 0 )
+				{
+					if( e1 < 0 ) e1 = h;  // fist visible
+				}
+				else
+				{
+					if( e1 > 0 )  // first invisible segment.
+					{
+						e2 = h;
+						break;
+					}
+				}
+
+			}
+
+	if (e1 < 0) {
+		// Cannot find visible point - it might be caused by numerical issues on some kind of datasets
+		return (-5);
+	}
+
+			// triangle pidx starts at e1 and ends at e2 (inclusive).
+			if( e2 < numh )
+			{
+				for( long e=e1; e<=e2; e++)
+				{
+					pidx.push_back(hull[e].id);
+					tridx.push_back(hull[e].trid);
+				}
+			}
+			else
+			{
+				for( long e=e1; e<e2; e++)
+				{
+					pidx.push_back(hull[e].id);
+					tridx.push_back(hull[e].trid);   // there are only n-1 triangles from n hull pts.
+				}
+				pidx.push_back(hull[0].id);
+			}
+
+
+			// erase elements e1+1 : e2-1 inclusive.
+
+			if( e1 < e2-1)
+			{
+				hull.erase(hull.begin() + e1+1, hull.begin()+ e2);
+			}
+
+			// insert ptx at location e1+1.
+			if( e2 == numh)
+			{
+				ptx.tr = hull[0].r - ptx.r;
+				ptx.tc = hull[0].c - ptx.c;
+			}
+			else
+			{
+				ptx.tr = hull[e1+1].r - ptx.r;
+				ptx.tc = hull[e1+1].c - ptx.c;
+			}
+
+			hull[e1].tr = ptx.r - hull[e1].r;
+			hull[e1].tc = ptx.c - hull[e1].c;
+
+			hull.insert( hull.begin()+e1+1, ptx);
+			hidx = e1+1;
+
+		}
+
+
+		long a = ptx.id, T0;
+		Triad trx( a, 0,0);
+		r1 = pts[slump[a]].r;
+		c1 = pts[slump[a]].c;
+
+		long npx = (long) pidx.size()-1;
+		numt = (long) triads.size();
+		T0 = numt;
+
+		if( npx == 1)
+		{
+			trx.b = pidx[0];
+			trx.c = pidx[1];
+
+			trx.bc = tridx[0];
+			trx.ab = -1;
+			trx.ac = -1;
+
+			// index back into the triads.
+			Triad &txx = triads[tridx[0]];
+			if( ( trx.b == txx.a && trx.c == txx.b) |( trx.b == txx.b && trx.c == txx.a))
+			{
+				txx.ab = numt;
+			}
+			else if( ( trx.b == txx.a && trx.c == txx.c) |( trx.b == txx.c && trx.c == txx.a))
+			{
+				txx.ac = numt;
+			}
+			else if( ( trx.b == txx.b && trx.c == txx.c) |( trx.b == txx.c && trx.c == txx.b))
+			{
+				txx.bc = numt;
+			}
+
+
+			hull[hidx].trid = numt;
+			if( hidx > 0 )
+				hull[hidx-1].trid = numt;
+			else
+			{
+				numh = (long) hull.size();
+				hull[numh-1].trid = numt;
+			}
+			triads.push_back( trx );
+			numt++;
+		}
+
+		else
+		{
+			trx.ab = -1;
+			for(long p=0; p<npx; p++)
+			{
+				trx.b = pidx[p];
+				trx.c = pidx[p+1];
+
+
+				trx.bc = tridx[p];
+				if( p > 0 )
+					trx.ab = numt-1;
+				trx.ac = numt+1;
+
+				// index back into the triads.
+				Triad &txx = triads[tridx[p]];
+				if( ( trx.b == txx.a && trx.c == txx.b) |( trx.b == txx.b && trx.c == txx.a))
+				{
+					txx.ab = numt;
+				}
+				else if( ( trx.b == txx.a && trx.c == txx.c) |( trx.b == txx.c && trx.c == txx.a))
+				{
+					txx.ac = numt;
+				}
+				else if( ( trx.b == txx.b && trx.c == txx.c) |( trx.b == txx.c && trx.c == txx.b))
+				{
+					txx.bc = numt;
+				}
+
+				triads.push_back( trx );
+				numt++;
+			}
+			triads[numt-1].ac=-1;
+
+			hull[hidx].trid = numt-1;
+			if( hidx > 0 )
+				hull[hidx-1].trid = T0;
+			else
+			{
+				numh = (long) hull.size();
+				hull[numh-1].trid = T0;
+			}
+
+
+		}
+
+	}
+
+// Commented by A.Balakin 21 April 2014 -- library shouldn't print anything
+//	cerr << "of triangles " << triads.size() << " to be flipped. "<< endl;
+
+	//  write_Triads(triads, "tris0.mat");
+
+	std::set<long> ids;
+
+	long tf = T_flip_pro( pts, triads, slump, numt, 0, ids);
+	if( tf < 0 )
+	{
+// Commented by A.Balakin 21 April 2014 -- library shouldn't print anything
+//		cerr << "cannot triangualte this set " << endl;
+		return(-3);
+	}
+
+	//  write_Triads(triads, "tris1.mat");
+
+	long nits = (long) ids.size(), nit=1;
+	while(  nits > 0 && nit < 50)
+	{
+
+		tf = T_flip_pro_idx( pts, triads, slump, ids);
+		nits = (long) ids.size();
+		nit ++;
+		if( tf < 0 )
+		{
+// Commented by A.Balakin 21 April 2014 -- library shouldn't print anything
+//			cerr << "cannot triangualte this set " << endl;
+			return(-4);
+		}
+	}
+
+	ids.clear();
+	nits = T_flip_edge( pts, triads, slump, numt, 0, ids);
+	nit=0;
+
+	while(  nits > 0 && nit < 100) {
+
+		tf = T_flip_pro_idx( pts, triads, slump, ids);
+		nits = (long) ids.size();
+		//	cerr << "flipping cycle  " << nit << "   active triangles " << nits << endl;
+		nit ++;
+		if( tf < 0 )
+		{
+// Commented by A.Balakin 21 April 2014 -- library shouldn't print anything
+//			cerr << "cannot triangualte this set " << endl;
+			return(-4);
+		}
+	}
+	return(1);
+}
+
+
+void circle_cent4(double r1,double c1, double r2,double c2, double r3,double c3,
+				  double &r,double &c, double &ro2)
+{
+	/*
+	 *  function to return the center of a circle and its radius
+	 * degenerate case should never be passed to this routine!!!!!!!!!!!!!
+	 * but will return r0 = -1 if it is.
+	 */
+
+	double rd, cd;
+	double v1 = 2*(r2-r1), v2 = 2*(c2-c1), v3 = r2*r2 - r1*r1 + c2*c2 - c1*c1;
+	double v4 = 2*(r3-r1),
+		   v5 = 2*(c3-c1),
+		   v6 = r3*r3 - r1*r1 + c3*c3 - c1*c1,
+
+		   v7 =  v2*v4 - v1*v5;
+	if( v7 == 0 )
+	{
+		r=0;
+		c=0;
+		ro2 = -1;
+		return;
+	}
+
+	cd = (v4*v3 - v1*v6)/v7;
+	if( v1 != 0 )
+		rd = (v3 - c*v2)/v1;
+	else
+		rd = (v6 - c*v5)/v4;
+
+	ro2 = (double)  ( (rd-r1)*(rd-r1) + (cd-c1)*(cd-c1) );
+	r = (double) rd;
+	c = (double) cd;
+
+	return;
+}
+
+
+namespace {
+
+/**
+ * Rounds the value given to the nearest multiple of the epsilon given
+ */
+double coarsen(const double value, const double epsilon) {
+	const double minimal_epsilon = std::numeric_limits<double>::epsilon() * value;
+	return (epsilon < minimal_epsilon) ? value : floor(value / epsilon + 0.5) * epsilon;
+}
+
+}
+
+/* test a set of points for duplicates.
+
+   erase duplicate points, do not change point ids.
+
+*/
+
+long de_duplicate( std::vector<Shx> &pts, std::vector<long> &outx, const Dupex epsilon ) {
+	long nump = (long) pts.size();
+	std::vector<Dupex> dpx;
+	Dupex d;
+	for( long k=0; k<nump; k++) {
+		d.r = coarsen(pts[k].r, epsilon.r);
+		d.c = coarsen(pts[k].c, epsilon.c);
+		d.id = k;
+		dpx.push_back(d);
+	}
+
+	sort(dpx.begin(), dpx.end());
+
+	for( long k=0; k<nump-1; k++) {
+		if( dpx[k].r == dpx[k+1].r && dpx[k].c == dpx[k+1].c )
+		{
+// Commented by A.Balakin 21 April 2014 -- library shouldn't print anything
+//			cerr << "duplicate-point ids " << dpx[k].id << "  " << dpx[k+1].id << "   at  ("  << pts[dpx[k+1].id].r << "," << pts[dpx[k+1].id].c << ")" << endl;
+			outx.push_back( dpx[k+1].id);
+		}
+	}
+
+	if( outx.size() == 0 )
+		return(0);
+
+	sort(outx.begin(), outx.end());
+
+	long nx = (long) outx.size();
+	for( long k=nx-1; k>=0; k--) {
+		pts.erase(pts.begin()+outx[k]);
+	}
+
+	return(nx);
+}
+
+
+
+
+/*
+   flip pairs of triangles that are not valid delaunay triangles
+   the Cline-Renka test is used rather than the less stable circum
+   circle center computation test of s-hull.
+
+   or the more expensive determinant test.
+
+ */
+
+
+long T_flip_pro( std::vector<Shx> &pts, std::vector<Triad> &triads, std::vector<long> &slump, long numt, long start, std::set<long> &ids)
+{
+
+	double r3,c3;
+	long pa,pb,pc, pd, D, L1, L2, L3, L4, T2;
+
+	Triad tx, tx2;
+
+
+	for( long t=start; t<numt; t++)
+	{
+
+		Triad &tri = triads[t];
+		// test all 3 neighbours of tri
+
+		long flipped = 0;
+
+		if( tri.bc >= 0 )
+		{
+
+			pa = slump[tri.a];
+			pb = slump[tri.b];
+			pc = slump[tri.c];
+
+			T2 = tri.bc;
+			Triad &t2 = triads[T2];
+			// find relative orientation (shared limb).
+			if( t2.ab == t )
+			{
+				D = t2.c;
+				pd = slump[t2.c];
+
+				if( tri.b == t2.a)
+				{
+					L3 = t2.ac;
+					L4 = t2.bc;
+				}
+				else
+				{
+					L3 = t2.bc;
+					L4 = t2.ac;
+				}
+			}
+			else if(  t2.ac == t )
+			{
+				D = t2.b;
+				pd = slump[t2.b];
+
+				if( tri.b == t2.a)
+				{
+					L3 = t2.ab;
+					L4 = t2.bc;
+				}
+				else
+				{
+					L3 = t2.bc;
+					L4 = t2.ab;
+				}
+			}
+			else if(  t2.bc == t )
+			{
+				D = t2.a;
+				pd = slump[t2.a];
+
+				if( tri.b == t2.b)
+				{
+					L3 = t2.ab;
+					L4 = t2.ac;
+				}
+				else
+				{
+					L3 = t2.ac;
+					L4 = t2.ab;
+				}
+			}
+			else
+			{
+// Commented by A.Balakin 21 April 2014 -- library shouldn't print anything
+//				cerr << "triangle flipping error. " << t << endl;
+				return(-5);
+			}
+
+
+// Commented by A.Balakin 21 April 2014 -- unused variable
+//			if( pd < 0 || pd > 100)
+//				long dfx = 9;
+
+			r3 = pts[pd].r;
+			c3 = pts[pd].c;
+
+			long XX = Cline_Renka_test( pts[pa].r, pts[pa].c, pts[pb].r, pts[pb].c,
+									   pts[pc].r, pts[pc].c, r3, c3 );
+
+			if( XX < 0 )
+			{
+
+				L1 = tri.ab;
+				L2 = tri.ac;
+				if( L1 != L3 && L2 != L4 )   // need this check for stability.
+				{
+
+					tx.a = tri.a;
+					tx.b = tri.b;
+					tx.c = D;
+
+					tx.ab = L1;
+					tx.ac = T2;
+					tx.bc = L3;
+
+
+					// triangle 2;
+					tx2.a = tri.a;
+					tx2.b = tri.c;
+					tx2.c = D;
+
+					tx2.ab = L2;
+					tx2.ac = t;
+					tx2.bc = L4;
+
+
+					ids.insert(t);
+					ids.insert(T2);
+
+					t2 = tx2;
+					tri = tx;
+					flipped = 1;
+
+					// change knock on triangle labels.
+					if( L3 >= 0 )
+					{
+						Triad &t3 = triads[L3];
+						if( t3.ab == T2 ) t3.ab = t;
+						else if( t3.bc == T2 ) t3.bc = t;
+						else if( t3.ac == T2 ) t3.ac = t;
+					}
+
+					if(L2 >= 0 )
+					{
+						Triad &t4 = triads[L2];
+						if( t4.ab == t ) t4.ab = T2;
+						else if( t4.bc == t ) t4.bc = T2;
+						else if( t4.ac == t ) t4.ac = T2;
+					}
+				}
+			}
+		}
+
+
+		if(  flipped == 0 && tri.ab >= 0 )
+		{
+
+			pc = slump[tri.c];
+			pb = slump[tri.b];
+			pa = slump[tri.a];
+
+			T2 = tri.ab;
+			Triad &t2 = triads[T2];
+			// find relative orientation (shared limb).
+			if( t2.ab == t )
+			{
+				D = t2.c;
+				pd = slump[t2.c];
+
+				if( tri.a == t2.a)
+				{
+					L3 = t2.ac;
+					L4 = t2.bc;
+				}
+				else
+				{
+					L3 = t2.bc;
+					L4 = t2.ac;
+				}
+			}
+			else if(  t2.ac == t )
+			{
+				D = t2.b;
+				pd = slump[t2.b];
+
+				if( tri.a == t2.a)
+				{
+					L3 = t2.ab;
+					L4 = t2.bc;
+				}
+				else
+				{
+					L3 = t2.bc;
+					L4 = t2.ab;
+				}
+			}
+			else if(  t2.bc == t )
+			{
+				D = t2.a;
+				pd = slump[t2.a];
+
+				if( tri.a == t2.b)
+				{
+					L3 = t2.ab;
+					L4 = t2.ac;
+				}
+				else
+				{
+					L3 = t2.ac;
+					L4 = t2.ab;
+				}
+			}
+			else
+			{
+// Commented by A.Balakin 21 April 2014 -- library shouldn't print anything
+//				cerr << "triangle flipping error. " << t << endl;
+				return(-5);
+			}
+
+			r3 = pts[pd].r;
+			c3 = pts[pd].c;
+
+			long XX = Cline_Renka_test( pts[pc].r, pts[pc].c, pts[pb].r, pts[pb].c,
+									   pts[pa].r, pts[pa].c,r3, c3);
+
+			if( XX < 0)
+			{
+
+
+				L1 = tri.ac;
+				L2 = tri.bc;
+				if( L1 != L3 && L2 != L4 )   // need this check for stability.
+				{
+
+					tx.a = tri.c;
+					tx.b = tri.a;
+					tx.c = D;
+
+					tx.ab = L1;
+					tx.ac = T2;
+					tx.bc = L3;
+
+
+					// triangle 2;
+					tx2.a = tri.c;
+					tx2.b = tri.b;
+					tx2.c = D;
+
+					tx2.ab = L2;
+					tx2.ac = t;
+					tx2.bc = L4;
+
+
+					ids.insert(t);
+					ids.insert(T2);
+
+					t2 = tx2;
+					tri = tx;
+					flipped = 1;
+
+					// change knock on triangle labels.
+					if( L3 >= 0 )
+					{
+						Triad &t3 = triads[L3];
+						if( t3.ab == T2 ) t3.ab = t;
+						else if( t3.bc == T2 ) t3.bc = t;
+						else if( t3.ac == T2 ) t3.ac = t;
+					}
+
+					if(L2 >= 0 )
+					{
+						Triad &t4 = triads[L2];
+						if( t4.ab == t ) t4.ab = T2;
+						else if( t4.bc == t ) t4.bc = T2;
+						else if( t4.ac == t ) t4.ac = T2;
+					}
+
+				}
+
+			}
+		}
+
+
+		if( flipped == 0 && tri.ac >= 0 )
+		{
+
+			pc = slump[tri.c];
+			pb = slump[tri.b];
+			pa = slump[tri.a];
+
+			T2 = tri.ac;
+			Triad &t2 = triads[T2];
+			// find relative orientation (shared limb).
+			if( t2.ab == t )
+			{
+				D = t2.c;
+				pd = slump[t2.c];
+
+				if( tri.a == t2.a)
+				{
+					L3 = t2.ac;
+					L4 = t2.bc;
+				}
+				else
+				{
+					L3 = t2.bc;
+					L4 = t2.ac;
+				}
+			}
+			else if(  t2.ac == t )
+			{
+				D = t2.b;
+				pd = slump[t2.b];
+
+				if( tri.a == t2.a)
+				{
+					L3 = t2.ab;
+					L4 = t2.bc;
+				}
+				else
+				{
+					L3 = t2.bc;
+					L4 = t2.ab;
+				}
+			}
+			else if(  t2.bc == t )
+			{
+				D = t2.a;
+				pd = slump[t2.a];
+
+				if( tri.a == t2.b)
+				{
+					L3 = t2.ab;
+					L4 = t2.ac;
+				}
+				else
+				{
+					L3 = t2.ac;
+					L4 = t2.ab;
+				}
+			}
+			else
+			{
+// Commented by A.Balakin 21 April 2014 -- library shouldn't print anything
+//				cerr << "triangle flipping error. " << t << endl;
+				return(-5);
+			}
+
+			r3 = pts[pd].r;
+			c3 = pts[pd].c;
+
+			long XX = Cline_Renka_test( pts[pb].r, pts[pb].c, pts[pa].r, pts[pa].c,
+									   pts[pc].r, pts[pc].c,r3, c3);
+
+			if( XX < 0 )
+			{
+
+				L1 = tri.ab;   // .ac shared limb
+				L2 = tri.bc;
+				if( L1 != L3 && L2 != L4 )   // need this check for stability.
+				{
+
+					tx.a = tri.b;
+					tx.b = tri.a;
+					tx.c = D;
+
+					tx.ab = L1;
+					tx.ac = T2;
+					tx.bc = L3;
+
+
+					// triangle 2;
+					tx2.a = tri.b;
+					tx2.b = tri.c;
+					tx2.c = D;
+
+					tx2.ab = L2;
+					tx2.ac = t;
+					tx2.bc = L4;
+
+					ids.insert(t);
+					ids.insert(T2);
+
+					t2 = tx2;
+					tri = tx;
+
+					// change knock on triangle labels.
+					if( L3 >= 0 )
+					{
+						Triad &t3 = triads[L3];
+						if( t3.ab == T2 ) t3.ab = t;
+						else if( t3.bc == T2 ) t3.bc = t;
+						else if( t3.ac == T2 ) t3.ac = t;
+					}
+
+					if(L2 >= 0 )
+					{
+						Triad &t4 = triads[L2];
+						if( t4.ab == t ) t4.ab = T2;
+						else if( t4.bc == t ) t4.bc = T2;
+						else if( t4.ac == t ) t4.ac = T2;
+					}
+
+				}
+			}
+		}
+
+
+	}
+
+
+	return(1);
+}
+
+/* minimum angle cnatraint for circum circle test.
+   due to Cline & Renka
+
+   A   --	B
+
+   |	/	|
+
+   C   --	D
+
+
+ */
+
+long Cline_Renka_test(double &Ax, double &Ay,
+					 double &Bx, double &By,
+					 double &Cx, double &Cy,
+					 double &Dx, double &Dy)
+{
+
+	double v1x = Bx-Ax, v1y = By-Ay,	v2x = Cx-Ax, v2y = Cy-Ay,
+		  v3x = Bx-Dx, v3y = By-Dy,	v4x = Cx-Dx, v4y = Cy-Dy;
+	double cosA = v1x*v2x + v1y*v2y;
+	double cosD = v3x*v4x + v3y*v4y;
+
+	if( cosA < 0 && cosD < 0 ) // two obtuse angles
+		return(-1);
+
+//	double ADX = Ax-Dx, ADy = Ay-Dy;	// commented by A.Balakin 21 April 2014 -- unused variable
+
+
+	if( cosA > 0 && cosD > 0 )  // two acute angles
+		return(1);
+
+
+	double sinA = fabs(v1x*v2y - v1y*v2x);
+	double sinD = fabs(v3x*v4y - v3y*v4x);
+
+	if( cosA*sinD + sinA*cosD < 0 )
+		return(-1);
+
+	return(1);
+
+}
+
+
+
+
+// same again but with set of triangle ids to be iterated over.
+
+
+long T_flip_pro_idx( std::vector<Shx> &pts, std::vector<Triad> &triads, std::vector<long> &slump, std::set<long> &ids)
+{
+
+	double  r3,c3;
+	long pa,pb,pc, pd,  D, L1, L2, L3, L4, T2;
+
+	Triad tx, tx2;
+	std::set<long> ids2;
+	ids2.clear();
+
+	std::set<long> :: const_iterator x=ids.begin();
+	while(x != ids.end() )
+	{
+		long t = *x;
+		x++;
+
+
+		Triad &tri = triads[t];
+		// test all 3 neighbours of tri
+		long flipped = 0;
+
+
+
+		if( tri.bc >= 0 )
+		{
+
+			pa = slump[tri.a];
+			pb = slump[tri.b];
+			pc = slump[tri.c];
+
+			T2 = tri.bc;
+			Triad &t2 = triads[T2];
+			// find relative orientation (shared limb).
+			if( t2.ab == t )
+			{
+				D = t2.c;
+				pd = slump[t2.c];
+
+				if( tri.b == t2.a)
+				{
+					L3 = t2.ac;
+					L4 = t2.bc;
+				}
+				else
+				{
+					L3 = t2.bc;
+					L4 = t2.ac;
+				}
+			}
+			else if(  t2.ac == t )
+			{
+				D = t2.b;
+				pd = slump[t2.b];
+
+				if( tri.b == t2.a)
+				{
+					L3 = t2.ab;
+					L4 = t2.bc;
+				}
+				else
+				{
+					L3 = t2.bc;
+					L4 = t2.ab;
+				}
+			}
+			else if(  t2.bc == t )
+			{
+				D = t2.a;
+				pd = slump[t2.a];
+
+				if( tri.b == t2.b)
+				{
+					L3 = t2.ab;
+					L4 = t2.ac;
+				}
+				else
+				{
+					L3 = t2.ac;
+					L4 = t2.ab;
+				}
+			}
+			else
+			{
+// Commented by A.Balakin 21 April 2014 -- library shouldn't print anything
+//				cerr << "triangle flipping error. " << t << "  T2: " <<  T2<<  endl;
+				return(-6);
+			}
+
+			r3 = pts[pd].r;
+			c3 = pts[pd].c;
+
+			long XX = Cline_Renka_test( pts[pa].r, pts[pa].c, pts[pb].r, pts[pb].c,
+									   pts[pc].r, pts[pc].c,r3, c3);
+
+			if( XX < 0 )
+			{
+				L1 = tri.ab;
+				L2 = tri.ac;
+
+				if( L1 != L3 && L2 != L4 )   // need this check for stability.
+				{
+
+
+					tx.a = tri.a;
+					tx.b = tri.b;
+					tx.c = D;
+
+					tx.ab = L1;
+					tx.ac = T2;
+					tx.bc = L3;
+
+
+					// triangle 2;
+					tx2.a = tri.a;
+					tx2.b = tri.c;
+					tx2.c = D;
+
+					tx2.ab = L2;
+					tx2.ac = t;
+					tx2.bc = L4;
+
+					ids2.insert(t);
+					ids2.insert(T2);
+
+					t2 = tx2;
+					tri = tx;
+					flipped = 1;
+
+					// change knock on triangle labels.
+					if( L3 >= 0 )
+					{
+						Triad &t3 = triads[L3];
+						if( t3.ab == T2 ) t3.ab = t;
+						else if( t3.bc == T2 ) t3.bc = t;
+						else if( t3.ac == T2 ) t3.ac = t;
+					}
+
+					if(L2 >= 0 )
+					{
+						Triad &t4 = triads[L2];
+						if( t4.ab == t ) t4.ab = T2;
+						else if( t4.bc == t ) t4.bc = T2;
+						else if( t4.ac == t ) t4.ac = T2;
+					}
+
+				}
+			}
+		}
+
+
+		if( flipped == 0 && tri.ab >= 0 )
+		{
+
+			pc = slump[tri.c];
+			pb = slump[tri.b];
+			pa = slump[tri.a];
+
+			T2 = tri.ab;
+			Triad &t2 = triads[T2];
+			// find relative orientation (shared limb).
+			if( t2.ab == t )
+			{
+				D = t2.c;
+				pd = slump[t2.c];
+
+				if( tri.a == t2.a)
+				{
+					L3 = t2.ac;
+					L4 = t2.bc;
+				}
+				else
+				{
+					L3 = t2.bc;
+					L4 = t2.ac;
+				}
+			}
+			else if(  t2.ac == t )
+			{
+				D = t2.b;
+				pd = slump[t2.b];
+
+				if( tri.a == t2.a)
+				{
+					L3 = t2.ab;
+					L4 = t2.bc;
+				}
+				else
+				{
+					L3 = t2.bc;
+					L4 = t2.ab;
+				}
+			}
+			else if(  t2.bc == t )
+			{
+				D = t2.a;
+				pd = slump[t2.a];
+
+				if( tri.a == t2.b)
+				{
+					L3 = t2.ab;
+					L4 = t2.ac;
+				}
+				else
+				{
+					L3 = t2.ac;
+					L4 = t2.ab;
+				}
+			}
+			else
+			{
+// Commented by A.Balakin 21 April 2014 -- library shouldn't print anything
+//				cerr << "triangle flipping error. " << t <<  endl;
+				return(-6);
+			}
+
+			r3 = pts[pd].r;
+			c3 = pts[pd].c;
+
+			long XX = Cline_Renka_test( pts[pc].r, pts[pc].c, pts[pb].r, pts[pb].c,
+									   pts[pa].r, pts[pa].c,r3, c3);
+
+			if( XX < 0 )
+			{
+				L1 = tri.ac;
+				L2 = tri.bc;
+				if( L1 != L3 && L2 != L4 )   // need this check for stability.
+				{
+
+					tx.a = tri.c;
+					tx.b = tri.a;
+					tx.c = D;
+
+					tx.ab = L1;
+					tx.ac = T2;
+					tx.bc = L3;
+
+
+					// triangle 2;
+					tx2.a = tri.c;
+					tx2.b = tri.b;
+					tx2.c = D;
+
+					tx2.ab = L2;
+					tx2.ac = t;
+					tx2.bc = L4;
+
+
+					ids2.insert(t);
+					ids2.insert(T2);
+
+					t2 = tx2;
+					tri = tx;
+					flipped = 1;
+
+					// change knock on triangle labels.
+					if( L3 >= 0 )
+					{
+						Triad &t3 = triads[L3];
+						if( t3.ab == T2 ) t3.ab = t;
+						else if( t3.bc == T2 ) t3.bc = t;
+						else if( t3.ac == T2 ) t3.ac = t;
+					}
+
+					if(L2 >= 0 )
+					{
+						Triad &t4 = triads[L2];
+						if( t4.ab == t ) t4.ab = T2;
+						else if( t4.bc == t ) t4.bc = T2;
+						else if( t4.ac == t ) t4.ac = T2;
+					}
+
+				}
+			}
+		}
+
+
+		if( flipped == 0 && tri.ac >= 0 )
+		{
+
+			pc = slump[tri.c];
+			pb = slump[tri.b];
+			pa = slump[tri.a];
+
+			T2 = tri.ac;
+			Triad &t2 = triads[T2];
+			// find relative orientation (shared limb).
+			if( t2.ab == t )
+			{
+				D = t2.c;
+				pd = slump[t2.c];
+
+				if( tri.a == t2.a)
+				{
+					L3 = t2.ac;
+					L4 = t2.bc;
+				}
+				else
+				{
+					L3 = t2.bc;
+					L4 = t2.ac;
+				}
+			}
+			else if(  t2.ac == t )
+			{
+				D = t2.b;
+				pd = slump[t2.b];
+
+				if( tri.a == t2.a)
+				{
+					L3 = t2.ab;
+					L4 = t2.bc;
+				}
+				else
+				{
+					L3 = t2.bc;
+					L4 = t2.ab;
+				}
+			}
+			else if(  t2.bc == t )
+			{
+				D = t2.a;
+				pd = slump[t2.a];
+
+				if( tri.a == t2.b)
+				{
+					L3 = t2.ab;
+					L4 = t2.ac;
+				}
+				else
+				{
+					L3 = t2.ac;
+					L4 = t2.ab;
+				}
+			}
+			else
+			{
+// Commented by A.Balakin 21 April 2014 -- library shouldn't print anything
+//				cerr << "triangle flipping error. " << t << endl;
+				return(-6);
+			}
+
+			r3 = pts[pd].r;
+			c3 = pts[pd].c;
+
+			long XX = Cline_Renka_test( pts[pb].r, pts[pb].c, pts[pc].r, pts[pc].c,
+									   pts[pa].r, pts[pa].c,r3, c3);
+
+			if( XX < 0 )
+			{
+				L1 = tri.ab;   // .ac shared limb
+				L2 = tri.bc;
+				if( L1 != L3 && L2 != L4 )   // need this check for stability.
+				{
+					tx.a = tri.b;
+					tx.b = tri.a;
+					tx.c = D;
+
+					tx.ab = L1;
+					tx.ac = T2;
+					tx.bc = L3;
+
+					// triangle 2;
+					tx2.a = tri.b;
+					tx2.b = tri.c;
+					tx2.c = D;
+
+					tx2.ab = L2;
+					tx2.ac = t;
+					tx2.bc = L4;
+
+					ids2.insert(t);
+					ids2.insert(T2);
+
+					t2 = tx2;
+					tri = tx;
+
+					// change knock on triangle labels.
+					if( L3 >= 0 )
+					{
+						Triad &t3 = triads[L3];
+						if( t3.ab == T2 ) t3.ab = t;
+						else if( t3.bc == T2 ) t3.bc = t;
+						else if( t3.ac == T2 ) t3.ac = t;
+					}
+
+					if(L2 >= 0 )
+					{
+						Triad &t4 = triads[L2];
+						if( t4.ab == t ) t4.ab = T2;
+						else if( t4.bc == t ) t4.bc = T2;
+						else if( t4.ac == t ) t4.ac = T2;
+					}
+
+
+				}
+			}
+		}
+	}
+
+	ids.clear();
+	ids.insert(ids2.begin(), ids2.end());
+
+	return(1);
+}
+
+/* test the seed configuration to see if the center
+   of the circum circle lies inside the seed triangle.
+
+   if not issue a warning.
+*/
+
+
+long  test_center(Shx &pt0, Shx &pt1,Shx &pt2)
+{
+	double r01 = pt1.r - pt0.r;
+	double c01 = pt1.c - pt0.c;
+
+	double r02 = pt2.r - pt0.r;
+	double c02 = pt2.c - pt0.c;
+
+	double r21 = pt1.r - pt2.r;
+	double c21 = pt1.c - pt2.c;
+
+	double v = r01*r02 + c01*c02;
+	if( v < 0 ) return(-1);
+
+	v = r21*r02 + c21*c02;
+	if( v > 0 ) return(-1);
+
+	v = r01*r21 + c01*c21;
+	if( v < 0 ) return(-1);
+
+	return(1);
+}
+
+long de_duplicateX( std::vector<Shx> &pts, std::vector<long> &outx,std::vector<Shx> &pts2 )
+{
+	long nump = (long) pts.size();
+	std::vector<Dupex> dpx;
+	Dupex d;
+	for( long k=0; k<nump; k++)
+	{
+		d.r = pts[k].r;
+		d.c = pts[k].c;
+		d.id = k;
+		dpx.push_back(d);
+	}
+
+	sort(dpx.begin(), dpx.end());
+
+// Commented by A.Balakin 21 April 2014 -- library shouldn't print anything
+//	cerr << "de-duplicating ";
+	pts2.clear();
+	pts2.push_back(pts[dpx[0].id]);
+	pts2[0].id = 0;
+	long cnt = 1;
+
+	for( long k=0; k<nump-1; k++)
+	{
+		if( dpx[k].r == dpx[k+1].r && dpx[k].c == dpx[k+1].c )
+		{
+			//cerr << "duplicate-point ids " << dpx[k].id << "  " << dpx[k+1].id << "   at  ("  << pts[dpx[k+1].id].r << "," << pts[dpx[k+1].id].c << ")" << endl;
+			//cerr << dpx[k+1].id << " ";
+
+			outx.push_back( dpx[k+1].id);
+		}
+		else
+		{
+			pts[dpx[k+1].id].id = cnt;
+			pts2.push_back(pts[dpx[k+1].id]);
+			cnt++;
+		}
+	}
+
+// Commented by A.Balakin 21 April 2014 -- library shouldn't print anything
+//	cerr << "removed  " << outx.size() << endl;
+
+	return(outx.size());
+}
+
+
+
+long T_flip_edge( std::vector<Shx> &pts, std::vector<Triad> &triads, std::vector<long> &slump, long numt, long start, std::set<long> &ids)
+{
+	double r3,c3;
+	long pa,pb,pc, pd, D, L1, L2, L3, L4, T2;
+
+	Triad tx, tx2;
+
+
+	for( long t=start; t<numt; t++)
+	{
+		Triad &tri = triads[t];
+		// test all 3 neighbours of tri
+
+		long flipped = 0;
+
+		if( tri.bc >= 0  && (tri.ac < 0 || tri.ab < 0) )
+		{
+			pa = slump[tri.a];
+			pb = slump[tri.b];
+			pc = slump[tri.c];
+
+			T2 = tri.bc;
+			Triad &t2 = triads[T2];
+			// find relative orientation (shared limb).
+			if( t2.ab == t )
+			{
+				D = t2.c;
+				pd = slump[t2.c];
+
+				if( tri.b == t2.a)
+				{
+					L3 = t2.ac;
+					L4 = t2.bc;
+				}
+				else {
+					L3 = t2.bc;
+					L4 = t2.ac;
+				}
+			}
+			else if(  t2.ac == t )
+			{
+				D = t2.b;
+				pd = slump[t2.b];
+
+				if( tri.b == t2.a)
+				{
+					L3 = t2.ab;
+					L4 = t2.bc;
+				}
+				else
+				{
+					L3 = t2.bc;
+					L4 = t2.ab;
+				}
+			}
+			else if(  t2.bc == t )
+			{
+				D = t2.a;
+				pd = slump[t2.a];
+
+				if( tri.b == t2.b)
+				{
+					L3 = t2.ab;
+					L4 = t2.ac;
+				}
+				else
+				{
+					L3 = t2.ac;
+					L4 = t2.ab;
+				}
+			}
+			else
+			{
+// Commented by A.Balakin 21 April 2014 -- library shouldn't print anything
+//				cerr << "triangle flipping error. " << t << endl;
+				return(-5);
+			}
+
+
+// Commented by A.Balakin 21 April 2014 -- unused variable
+//			if( pd < 0 || pd > 100)
+//				long dfx = 9;
+
+			r3 = pts[pd].r;
+			c3 = pts[pd].c;
+
+			long XX = Cline_Renka_test( pts[pa].r, pts[pa].c, pts[pb].r, pts[pb].c,
+									   pts[pc].r, pts[pc].c, r3, c3 );
+
+			if( XX < 0 ) {
+
+				L1 = tri.ab;
+				L2 = tri.ac;
+				//	if( L1 != L3 && L2 != L4 ){  // need this check for stability.
+
+				tx.a = tri.a;
+				tx.b = tri.b;
+				tx.c = D;
+
+				tx.ab = L1;
+				tx.ac = T2;
+				tx.bc = L3;
+
+
+				// triangle 2;
+				tx2.a = tri.a;
+				tx2.b = tri.c;
+				tx2.c = D;
+
+				tx2.ab = L2;
+				tx2.ac = t;
+				tx2.bc = L4;
+
+
+				ids.insert(t);
+				ids.insert(T2);
+
+				t2 = tx2;
+				tri = tx;
+				flipped = 1;
+
+				// change knock on triangle labels.
+				if( L3 >= 0 )
+				{
+					Triad &t3 = triads[L3];
+					if( t3.ab == T2 ) t3.ab = t;
+					else if( t3.bc == T2 ) t3.bc = t;
+					else if( t3.ac == T2 ) t3.ac = t;
+				}
+
+				if(L2 >= 0 )
+				{
+					Triad &t4 = triads[L2];
+					if( t4.ab == t ) t4.ab = T2;
+					else if( t4.bc == t ) t4.bc = T2;
+					else if( t4.ac == t ) t4.ac = T2;
+				}
+				//	}
+			}
+		}
+
+
+		if(  flipped == 0 && tri.ab >= 0  && (tri.ac < 0 || tri.bc < 0))
+		{
+			pc = slump[tri.c];
+			pb = slump[tri.b];
+			pa = slump[tri.a];
+
+			T2 = tri.ab;
+			Triad &t2 = triads[T2];
+			// find relative orientation (shared limb).
+			if( t2.ab == t )
+			{
+				D = t2.c;
+				pd = slump[t2.c];
+
+				if( tri.a == t2.a)
+				{
+					L3 = t2.ac;
+					L4 = t2.bc;
+				}
+				else
+				{
+					L3 = t2.bc;
+					L4 = t2.ac;
+				}
+			}
+			else if(  t2.ac == t )
+			{
+				D = t2.b;
+				pd = slump[t2.b];
+
+				if( tri.a == t2.a)
+				{
+					L3 = t2.ab;
+					L4 = t2.bc;
+				}
+				else
+				{
+					L3 = t2.bc;
+					L4 = t2.ab;
+				}
+			}
+			else if(  t2.bc == t )
+			{
+				D = t2.a;
+				pd = slump[t2.a];
+
+				if( tri.a == t2.b)
+				{
+					L3 = t2.ab;
+					L4 = t2.ac;
+				}
+				else
+				{
+					L3 = t2.ac;
+					L4 = t2.ab;
+				}
+			}
+			else {
+// Commented by A.Balakin 21 April 2014 -- library shouldn't print anything
+//				cerr << "triangle flipping error. " << t << endl;
+				return(-5);
+			}
+
+			r3 = pts[pd].r;
+			c3 = pts[pd].c;
+
+			long XX = Cline_Renka_test( pts[pc].r, pts[pc].c, pts[pb].r, pts[pb].c,
+									   pts[pa].r, pts[pa].c,r3, c3);
+
+			if( XX < 0)
+			{
+				L1 = tri.ac;
+				L2 = tri.bc;
+				//	if( L1 != L3 && L2 != L4 ){  // need this check for stability.
+
+				tx.a = tri.c;
+				tx.b = tri.a;
+				tx.c = D;
+
+				tx.ab = L1;
+				tx.ac = T2;
+				tx.bc = L3;
+
+				// triangle 2;
+				tx2.a = tri.c;
+				tx2.b = tri.b;
+				tx2.c = D;
+
+				tx2.ab = L2;
+				tx2.ac = t;
+				tx2.bc = L4;
+
+				ids.insert(t);
+				ids.insert(T2);
+
+				t2 = tx2;
+				tri = tx;
+				flipped = 1;
+
+				// change knock on triangle labels.
+				if( L3 >= 0 )
+				{
+					Triad &t3 = triads[L3];
+					if( t3.ab == T2 ) t3.ab = t;
+					else if( t3.bc == T2 ) t3.bc = t;
+					else if( t3.ac == T2 ) t3.ac = t;
+				}
+
+				if(L2 >= 0 )
+				{
+					Triad &t4 = triads[L2];
+					if( t4.ab == t ) t4.ab = T2;
+					else if( t4.bc == t ) t4.bc = T2;
+					else if( t4.ac == t ) t4.ac = T2;
+				}
+			}
+		}
+
+
+		if( flipped == 0 && tri.ac >= 0  && (tri.bc < 0 || tri.ab < 0) )
+		{
+			pc = slump[tri.c];
+			pb = slump[tri.b];
+			pa = slump[tri.a];
+
+			T2 = tri.ac;
+			Triad &t2 = triads[T2];
+			// find relative orientation (shared limb).
+			if( t2.ab == t )
+			{
+				D = t2.c;
+				pd = slump[t2.c];
+
+				if( tri.a == t2.a)
+				{
+					L3 = t2.ac;
+					L4 = t2.bc;
+				}
+				else
+				{
+					L3 = t2.bc;
+					L4 = t2.ac;
+				}
+			}
+			else if(  t2.ac == t )
+			{
+				D = t2.b;
+				pd = slump[t2.b];
+
+				if( tri.a == t2.a)
+				{
+					L3 = t2.ab;
+					L4 = t2.bc;
+				}
+				else {
+					L3 = t2.bc;
+					L4 = t2.ab;
+				}
+			}
+			else if(  t2.bc == t )
+			{
+				D = t2.a;
+				pd = slump[t2.a];
+
+				if( tri.a == t2.b)
+				{
+					L3 = t2.ab;
+					L4 = t2.ac;
+				}
+				else
+				{
+					L3 = t2.ac;
+					L4 = t2.ab;
+				}
+			}
+			else
+			{
+// Commented by A.Balakin 21 April 2014 -- library shouldn't print anything
+//				cerr << "triangle flipping error. " << t << endl;
+				return(-5);
+			}
+
+			r3 = pts[pd].r;
+			c3 = pts[pd].c;
+
+			long XX = Cline_Renka_test( pts[pb].r, pts[pb].c, pts[pa].r, pts[pa].c,
+									   pts[pc].r, pts[pc].c,r3, c3);
+
+			if( XX < 0 )
+			{
+				L1 = tri.ab;   // .ac shared limb
+				L2 = tri.bc;
+				//	if( L1 != L3 && L2 != L4 ){  // need this check for stability.
+
+				tx.a = tri.b;
+				tx.b = tri.a;
+				tx.c = D;
+
+				tx.ab = L1;
+				tx.ac = T2;
+				tx.bc = L3;
+
+
+				// triangle 2;
+				tx2.a = tri.b;
+				tx2.b = tri.c;
+				tx2.c = D;
+
+				tx2.ab = L2;
+				tx2.ac = t;
+				tx2.bc = L4;
+
+				ids.insert(t);
+				ids.insert(T2);
+
+				t2 = tx2;
+				tri = tx;
+
+				// change knock on triangle labels.
+				if( L3 >= 0 )
+				{
+					Triad &t3 = triads[L3];
+					if( t3.ab == T2 ) t3.ab = t;
+					else if( t3.bc == T2 ) t3.bc = t;
+					else if( t3.ac == T2 ) t3.ac = t;
+				}
+
+				if(L2 >= 0 )
+				{
+					Triad &t4 = triads[L2];
+					if( t4.ab == t ) t4.ab = T2;
+					else if( t4.bc == t ) t4.bc = T2;
+					else if( t4.ac == t ) t4.ac = T2;
+				}
+			}
+		}
+	}
+	return(1);
+}
+
diff --git a/src/s_hull/s_hull_pro.h b/src/s_hull/s_hull_pro.h
new file mode 100644
index 0000000..2e632ec
--- /dev/null
+++ b/src/s_hull/s_hull_pro.h
@@ -0,0 +1,149 @@
+#ifndef _structures_h
+#define _structures_h
+
+// for FILE
+
+#include <stdlib.h>
+#include <vector>
+#include <set>
+#include <limits>
+#include <mgl2/define.h>
+
+/*
+	for use in s_hull_pro.cpp
+
+	S-hull-pro, Copyright (c) 2012
+	Dr David SInclair
+	Cambridge, UK
+
+	email david at s-hull.org
+*/
+
+// Global replace int->long by A.Balakin 21 April 2014 -- 64bit version can handle huge data arrays
+
+struct Triad
+{
+	long a,b, c;
+	long ab, bc, ac;  // adjacent edges index to neighbouring triangle.
+	double ro, R,C;
+	//std::set<long> idx;
+	Triad() {a=b=c=0;	ab=bc=ac=-1;	ro=-1;	R=C=0;}	// added by A.Balakin 21 April 2014 -- uninitialised variable
+	Triad(long x, long y) : a(x), b(y),c(0), ab(-1), bc(-1), ac(-1), ro(-1), R(0), C(0) {}
+	Triad(long x, long y, long z) : a(x), b(y), c(z),  ab(-1), bc(-1), ac(-1), ro(-1), R(0), C(0) {}
+	Triad(const Triad &p) : a(p.a), b(p.b), c(p.c), ab(p.ab), bc(p.bc), ac(p.ac), ro(p.ro), R(p.R), C(p.C) {}
+
+	Triad &operator=(const Triad &p)
+	{
+		a = p.a;
+		b = p.b;
+		c = p.c;
+
+		ab = p.ab;
+		bc = p.bc;
+		ac = p.ac;
+
+		ro = p.ro;
+		R = p.R;
+		C = p.C;
+
+		return *this;
+	}
+};
+
+
+
+/* point structure for s_hull only.
+   has to keep track of triangle ids as hull evolves.
+*/
+
+
+struct Shx
+{
+	long id, trid;
+	double r,c, tr,tc, ro;
+	Shx() {r=c=tr=tc=ro=0;	id=-1;	trid=0;}	// added by A.Balakin 21 April 2014 -- uninitialised variable
+	Shx(double a, double b) : r(a), c(b)
+	{	trid=0;	ro=tr=tc=0;	id=-1;	}			// added by A.Balakin 21 April 2014 -- uninitialised variable
+	Shx(double a, double b, double x) : r(a), c(b), ro(x)
+	{	trid=0;	tr=tc=0;	id=-1;	}			// added by A.Balakin 21 April 2014 -- uninitialised variable
+	Shx(const Shx &p) : id(p.id), trid(p.trid), r(p.r), c(p.c), tr(p.tr), tc(p.tc), ro(p.ro) {}
+
+	Shx &operator=(const Shx &p)
+	{
+		id = p.id;
+		trid = p.trid;
+		r = p.r;
+		c = p.c;
+		tr = p.tr;
+		tc = p.tc;
+		ro = p.ro;
+		return *this;
+	}
+};
+
+
+// sort into descending order (for use in corner responce ranking).
+inline bool operator<(const Shx &a, const Shx &b)
+{
+	if( a.ro == b.ro) {
+		if( a.r == b.r ) {
+			return a.c < b.c;
+		}
+		return a.r < b.r;
+	}
+	return a.ro <  b.ro;
+};
+
+
+struct Dupex
+{
+	long id;
+	double r,c;
+
+	Dupex() {	r=c=0;	id=-1;	}	// added by A.Balakin 21 April 2014 -- uninitialised variable
+	Dupex(double a, double b) : id(-1), r(a), c(b) {}
+	Dupex(double a, double b, long x) : id(x), r(a), c(b) {}
+	Dupex(const Dupex &p) : id(p.id),  r(p.r), c(p.c) {}
+
+	Dupex &operator=(const Dupex &p)
+	{
+		id = p.id;
+		r = p.r;
+		c = p.c;
+		return *this;
+	}
+};
+
+
+
+// sort into descending order (for use in corner responce ranking).
+inline bool operator<(const Dupex &a, const Dupex &b)
+{
+	if( a.r == b.r)
+		return a.c < b.c;
+	return a.r <  b.r;
+};
+
+
+
+
+
+// from s_hull.C
+long s_hull_pro( std::vector<Shx> &pts, std::vector<Triad> &triads);
+void circle_cent2(double r1,double c1, double r2,double c2, double r3,double c3,double &r,double &c, double &ro2);
+void circle_cent4(double r1,double c1, double r2,double c2, double r3,double c3,double &r,double &c, double &ro2);
+void write_Shx(std::vector<Shx> &pts, char * fname);
+void write_Triads(std::vector<Triad> &ts, char * fname);
+long Cline_Renka_test(double &Ax, double &Ay, double &Bx, double &By, double &Cx, double &Cy, double &Dx, double &Dy);
+long T_flip_pro( std::vector<Shx> &pts, std::vector<Triad> &triads, std::vector<long> &slump, long numt, long start, std::set<long> &ids);
+long T_flip_pro_idx( std::vector<Shx> &pts, std::vector<Triad> &triads, std::vector<long> &slump, std::set<long> &ids);
+
+long read_Shx(std::vector<Shx> &pts, char * fname);
+long de_duplicate( std::vector<Shx> &pts,  std::vector<long> &outx, Dupex epsilon = Dupex(std::numeric_limits<float>::epsilon(),std::numeric_limits<float>::epsilon()) );
+long de_duplicateX( std::vector<Shx> &pts, std::vector<long> &outx,std::vector<Shx> &pts2 );
+long  test_center(Shx &pt0, Shx &pt1,Shx &pt2);
+
+long T_flip_edge( std::vector<Shx> &pts, std::vector<Triad> &triads, std::vector<long> &slump, long numt, long start, std::set<long> &ids);
+
+
+#endif
diff --git a/src/surf.cpp b/src/surf.cpp
new file mode 100644
index 0000000..301fbe1
--- /dev/null
+++ b/src/surf.cpp
@@ -0,0 +1,944 @@
+/***************************************************************************
+ * surf.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include "mgl2/define.h"
+#include "mgl2/surf.h"
+#include "mgl2/data.h"
+#include "mgl2/eval.h"
+#include "mgl2/base.h"
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_mesh_plot(mglBase *gr, long *pos, long n, long m, int how)
+{
+	int d = gr->MeshNum>0 ? gr->MeshNum+1 : n*m, dx = n>d?n/d:1, dy = m>d?m/d:1;
+	// NOTE: number of lines in each direction can be reduced too
+	if(how&1)	for(long j=0;j<m;j+=dy)
+	{
+		long s=0;
+		for(long i=0;i<n-1;i++)	if(pos[n*j+i]>=0 && pos[n*j+i+1]>=0)	s++;
+		d = gr->FaceNum>0 ? gr->FaceNum+1 : n;	s = s>d?s/d:1;
+		for(long i=0;i<n-s;i+=s)
+			gr->line_plot(pos[n*j+i],pos[n*j+i+s]);
+
+	}
+	if(how&2)	for(long i=0;i<n;i+=dx)
+	{
+		long s=0;
+		for(long j=0;j<m-1;j++)	if(pos[n*j+i]>=0 && pos[n*j+i+n]>=0)	s++;
+		d = gr->FaceNum>0 ? gr->FaceNum+1 : n;	s = s>d?s/d:1;
+		for(long j=0;j<m-s;j+=s)
+			gr->line_plot(pos[n*j+i],pos[n*j+i+s*n]);
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_surf_plot(mglBase *gr, long *pos, long n, long m)
+{
+	long s=0;
+	for(long j=0;j<m-1;j++)	for(long i=0;i<n-1;i++)
+		if(pos[n*j+i]>=0 && pos[n*j+i+1]>=0 && pos[n*j+i+n]>=0 && pos[n*j+i+n+1]>=0)
+			s++;
+	long dx=1,dy=1;
+	if(gr->FaceNum && s>gr->FaceNum*gr->FaceNum)
+	{
+		int d = gr->FaceNum+1,ns=n*s/((n-1)*(m-1)),ms=m*s/((n-1)*(m-1));
+		dx = ns>d?ns/d:1;		dy = ms>d?ms/d:1;
+	}
+	for(long j=0;j<m-dy;j+=dy)	for(long i=0;i<n-dx;i+=dx)
+		gr->quad_plot(pos[n*j+i],pos[n*j+i+dx],pos[n*j+i+n*dy],pos[n*j+i+n*dy+dx]);
+}
+//-----------------------------------------------------------------------------
+//
+//	Plot by formulas series
+//
+//-----------------------------------------------------------------------------
+HMDT MGL_NO_EXPORT mglFormulaCalc(const char *str, const std::vector<mglDataA*> &head);
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_fsurf(HMGL gr, const char *eqZ, const char *sch, const char *opt)
+{	// NOTE Strong function variation analysis can be added here
+	if(eqZ==0 || eqZ[0]==0)	return;		// nothing to plot
+	mreal r = gr->SaveState(opt);
+	long n = (mgl_isnan(r) || r<=0) ? 100:long(r+0.5);
+	mglData z(n,n);
+	mglDataV x(n,n,1, gr->Min.x,gr->Max.x,'x');	x.s=L"x";
+	mglDataV y(n,n,1, gr->Min.y,gr->Max.y,'y');	y.s=L"y";
+	mglDataV t(n,n);	t.s=L"#$mgl";
+	std::vector<mglDataA*> list;
+	list.push_back(&x);	list.push_back(&y);	list.push_back(&t);
+	z.Move(mglFormulaCalc(eqZ,list));
+	mgl_surf(gr, &z, sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_fsurf_xyz(HMGL gr, const char *eqX, const char *eqY, const char *eqZ, const char *sch, const char *opt)
+{	// NOTE Strong function variation analysis can be added here
+	if(eqZ==0 || eqZ[0]==0)	return;		// nothing to plot
+	mreal r = gr->SaveState(opt);
+	long n = (mgl_isnan(r) || r<=0) ? 100:long(r+0.5);
+	mglData z(n,n), x(n,n), y(n,n);
+	mglDataV u(n,n,1, 0,1,'x');	u.s=L"u";
+	mglDataV v(n,n,1, 0,1,'y');	v.s=L"v";
+	mglDataV t(n,n);	t.s=L"#$mgl";
+	std::vector<mglDataA*> list;
+	list.push_back(&u);	list.push_back(&v);	list.push_back(&t);
+	x.Move(mglFormulaCalc(eqX,list));
+	y.Move(mglFormulaCalc(eqY,list));
+	z.Move(mglFormulaCalc(eqZ,list));
+	mgl_surf_xy(gr,&x,&y,&z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_fsurf_(uintptr_t *gr, const char *fy, const char *stl, const char *opt, int ly, int ls, int lo)
+{	char *s=new char[ly+1];	memcpy(s,fy,ly);	s[ly]=0;
+	char *p=new char[ls+1];	memcpy(p,stl,ls);	p[ls]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_fsurf(_GR_, s, p, o);	delete []o;	delete []s;	delete []p;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_fsurf_xyz_(uintptr_t *gr, const char *fx, const char *fy, const char *fz, const char *stl, const char *opt, int lx, int ly, int lz, int ls, int lo)
+{
+	char *sx=new char[lx+1];	memcpy(sx,fx,lx);	sx[lx]=0;
+	char *sy=new char[ly+1];	memcpy(sy,fy,ly);	sy[ly]=0;
+	char *sz=new char[lz+1];	memcpy(sz,fz,lz);	sz[lz]=0;
+	char *p=new char[ls+1];		memcpy(p,stl,ls);	p[ls]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_fsurf_xyz(_GR_, sx, sy, sz, p, o);	delete []o;
+	delete []sx;	delete []sy;	delete []sz;	delete []p;
+}
+//-----------------------------------------------------------------------------
+//
+//	Mesh series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_mesh_xy(HMGL gr, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{
+	long n=z->GetNx(),m=z->GetNy();
+	if(mgl_check_dim2(gr,x,y,z,0,"Mesh"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Mesh",cgid++);
+	gr->SetPenPal(sch,0,false);
+	long ss = gr->AddTexture(sch);
+	long *pos = new long[n*m];	memset(pos,-1L,n*m*sizeof(long));
+	gr->Reserve(n*m*z->GetNz());
+
+	for(long k=0;k<z->GetNz();k++)
+	{
+		if(gr->NeedStop())	break;
+		for(long j=0;j<m;j++)	for(long i=0;i<n;i++)
+		{
+			mreal zz = z->v(i,j,k);
+			pos[i+n*j] = gr->AddPnt(mglPoint(GetX(x,i,j,k).x, GetY(y,i,j,k).x, zz),gr->GetC(ss,zz));
+		}
+		mgl_mesh_plot(gr,pos,n,m,3);
+	}
+	delete []pos;	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_mesh(HMGL gr, HCDT z, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(z->GetNx()), y(z->GetNy());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	mgl_mesh_xy(gr,&x,&y,z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_mesh_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_mesh_xy(_GR_, _DA_(x), _DA_(y), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_mesh_(uintptr_t *gr, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_mesh(_GR_, _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Fall series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_fall_xy(HMGL gr, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{
+	long n=z->GetNx(),m=z->GetNy();
+	if(mgl_check_dim2(gr,x,y,z,0,"Fall"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Fall",cgid++);
+	gr->SetPenPal(sch,0,false);
+	long ss = gr->AddTexture(sch);
+	long *pos = new long[n*m];
+	gr->Reserve(n*m*z->GetNz());
+
+	for(long k=0;k<z->GetNz();k++)
+	{
+		if(gr->NeedStop())	break;
+		for(long j=0;j<m;j++)	for(long i=0;i<n;i++)
+		{
+			mreal zz = z->v(i,j,k);
+			pos[i+n*j] = gr->AddPnt(mglPoint(GetX(x,i,j,k).x, GetY(y,i,j,k).x, zz),gr->GetC(ss,zz));
+		}
+		mgl_mesh_plot(gr,pos,n,m, (mglchr(sch,'x')) ? 2:1);
+	}
+	delete []pos;	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_fall(HMGL gr, HCDT z, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(z->GetNx()), y(z->GetNy());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	mgl_fall_xy(gr,&x,&y,z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_fall_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_fall_xy(_GR_, _DA_(x), _DA_(y), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_fall_(uintptr_t *gr, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_fall(_GR_, _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Grid series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_grid_xy(HMGL gr, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{
+	long n=z->GetNx(),m=z->GetNy();
+	if(mgl_check_dim2(gr,x,y,z,0,"Grid"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Grid",cgid++);
+	mreal	zVal = gr->Min.z;
+	gr->SetPenPal(sch?sch:"k-");
+	long *pos = new long[n*m];
+	gr->Reserve(n*m*z->GetNz());
+
+	for(long k=0;k<z->GetNz();k++)
+	{
+		if(gr->NeedStop())	break;
+		if(z->GetNz()>1)	zVal = gr->Min.z+(gr->Max.z-gr->Min.z)*mreal(k)/(z->GetNz()-1);
+		for(long j=0;j<m;j++)	for(long i=0;i<n;i++)
+			pos[i+n*j] = gr->AddPnt(mglPoint(GetX(x,i,j,k).x, GetY(y,i,j,k).x, zVal),gr->CDef);
+		mgl_mesh_plot(gr,pos,n,m,3);
+	}
+	delete []pos;	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_grid(HMGL gr, HCDT z,const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(z->GetNx()), y(z->GetNy());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	mgl_grid_xy(gr,&x,&y,z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_grid_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_grid_xy(_GR_,_DA_(x), _DA_(y), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_grid_(uintptr_t *gr, uintptr_t *a,const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_grid(_GR_, _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Surf series
+//
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_surf_gen(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT c, HCDT a, const char *sch)
+{
+	long n=z->GetNx(),m=z->GetNy();
+	long ss = gr->AddTexture(sch);
+	long *pos = new long[n*m];
+	bool wire = (mglchr(sch,'#'));
+	gr->Reserve((n+1)*(m+1)*z->GetNz()*(wire?2:1));
+
+	mglPoint q,s,xx,yy;
+	for(long k=0;k<z->GetNz();k++)
+	{
+		if(gr->NeedStop())	break;
+		if(a)	for(long j=0;j<m;j++)	for(long i=0;i<n;i++)
+		{
+			xx = GetX(x,i,j,k);		yy = GetY(y,i,j,k);
+			q.Set(xx.y, yy.y, z->dvx(i,j,k));
+			s.Set(xx.z, yy.z, z->dvy(i,j,k));
+			pos[i+n*j] = gr->AddPnt(mglPoint(xx.x, yy.x, z->v(i,j,k)), gr->GetC(ss,c->v(i,j,k)), q^s, gr->GetA(a->v(i,j,k)));
+		}
+		else	for(long j=0;j<m;j++)	for(long i=0;i<n;i++)
+		{
+			xx = GetX(x,i,j,k);		yy = GetY(y,i,j,k);
+			q.Set(xx.y, yy.y, z->dvx(i,j,k));
+			s.Set(xx.z, yy.z, z->dvy(i,j,k));
+			pos[i+n*j] = gr->AddPnt(mglPoint(xx.x, yy.x, z->v(i,j,k)), gr->GetC(ss,c->v(i,j,k)), q^s);
+		}
+		if(sch && mglchr(sch,'.'))
+			for(long i=0;i<n*m;i++)	gr->mark_plot(pos[i],'.');
+		else	mgl_surf_plot(gr,pos,n,m);
+		if(wire)
+		{
+			gr->SetPenPal("k-");
+			for(long i=0;i<n*m;i++)	pos[i] = gr->CopyNtoC(pos[i],gr->CDef);
+			mgl_mesh_plot(gr,pos,n,m,3);
+		}
+	}
+	delete []pos;	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf_xy(HMGL gr, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{
+	if(mgl_check_dim2(gr,x,y,z,0,"Surf"))	return;
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Surf",cgid++);
+	mgl_surf_gen(gr, x, y, z, z, 0, sch);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf(HMGL gr, HCDT z, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(z->GetNx()), y(z->GetNy());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	mgl_surf_xy(gr,&x,&y,z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_surf_xy(_GR_, _DA_(x), _DA_(y), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf_(uintptr_t *gr, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_surf(_GR_, _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	SurfCA series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surfca_xy(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT c, HCDT a, const char *sch, const char *opt)
+{
+	if(mgl_check_dim2(gr,x,y,z,c,"SurfCA"))	return;
+	if(mgl_check_dim2(gr,x,y,z,a,"SurfCA"))	return;
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("SurfCA",cgid++);
+	mgl_surf_gen(gr, x, y, z, c, a, sch);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surfca(HMGL gr, HCDT z, HCDT c, HCDT a, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(z->GetNx()), y(z->GetNy());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	mgl_surfca_xy(gr,&x,&y,z,c,a,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surfca_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_surfca_xy(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(c), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surfca_(uintptr_t *gr, uintptr_t *z, uintptr_t *c, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_surfca(_GR_, _DA_(z), _DA_(c), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	SurfC series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surfc_xy(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT c, const char *sch, const char *opt)
+{
+	if(mgl_check_dim2(gr,x,y,z,c,"SurfC"))	return;
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("SurfC",cgid++);
+	mgl_surf_gen(gr, x, y, z, c, 0, sch);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surfc(HMGL gr, HCDT z, HCDT c, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(z->GetNx()), y(z->GetNy());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	mgl_surfc_xy(gr,&x,&y,z,c,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surfc_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_surfc_xy(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surfc_(uintptr_t *gr, uintptr_t *z, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_surfc(_GR_, _DA_(z), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	SurfA series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surfa_xy(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT c, const char *sch, const char *opt)
+{
+	if(mgl_check_dim2(gr,x,y,z,c,"SurfA"))	return;
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("SurfA",cgid++);
+	mgl_surf_gen(gr, x, y, z, z, c, sch);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surfa(HMGL gr, HCDT z, HCDT c, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(z->GetNx()), y(z->GetNy());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	mgl_surfa_xy(gr,&x,&y,z,c,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surfa_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_surfa_xy(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surfa_(uintptr_t *gr, uintptr_t *z, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_surfa(_GR_, _DA_(z), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Belt series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_belt_xy(HMGL gr, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{
+	long n=z->GetNx(),m=z->GetNy();
+	if(mgl_check_dim2(gr,x,y,z,0,"Belt"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Belt",cgid++);
+	int d = gr->MeshNum>0 ? gr->MeshNum+1 : n*m, dx = n>d?n/d:1, dy = m>d?m/d:1;
+	long ss = gr->AddTexture(sch);
+	long *pos = new long[2*(n>m?n:m)];
+	gr->Reserve(2*n*m*z->GetNz());
+	bool how = !mglchr(sch,'x');
+
+	mglPoint p1,p2,q,s,xx,yy;
+	for(long k=0;k<z->GetNz();k++)
+	{
+		if(gr->NeedStop())	break;
+		if(how)	for(long i=0;i<n-dx;i+=dx)
+		{
+			for(long j=0;j<m;j++)
+			{
+				xx = GetX(x,i,j,k);		yy = GetY(y,i,j,k);
+				p1.Set(xx.x, yy.x, z->v(i,j,k));
+				s.Set(xx.z, yy.z, z->dvy(i,j,k));
+				q.Set(xx.y, yy.y, 0);	s = q^s;
+				mreal c = gr->GetC(ss,p1.z);
+				p2.Set(GetX(x,i+dx,j,k).x,GetY(y,i+dx,j,k).x,p1.z);
+				pos[2*j] = gr->AddPnt(p1,c,s);
+				pos[2*j+1]=gr->AddPnt(p2,c,s);
+			}
+			mgl_surf_plot(gr,pos,2,m);
+		}
+		else	for(long j=0;j<m-dy;j+=dy)
+		{
+			for(long i=0;i<n;i++)	// ñîçäàåì ìàññèâ òî÷åê
+			{
+				xx = GetX(x,i,j,k);		yy = GetY(y,i,j,k);
+				p1.Set(xx.x, yy.x, z->v(i,j,k));
+				q.Set(xx.y, yy.y, z->dvx(i,j,k));
+				s.Set(xx.z, yy.z, 0);	s = q^s;
+				mreal c = gr->GetC(ss,p1.z);
+				p2.Set(GetX(x,i,j+dy,k).x,GetY(y,i,j+dy,k).x,p1.z);
+				pos[2*i] = gr->AddPnt(p1,c,s);
+				pos[2*i+1]=gr->AddPnt(p2,c,s);
+			}
+			mgl_surf_plot(gr,pos,2,n);
+		}
+	}
+	delete []pos; gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_belt(HMGL gr, HCDT z, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(z->GetNx()), y(z->GetNy());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	mgl_belt_xy(gr,&x,&y,z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_belt_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_belt_xy(_GR_, _DA_(x), _DA_(y), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_belt_(uintptr_t *gr, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_belt(_GR_, _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Dens series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dens_xy(HMGL gr, HCDT x, HCDT y, HCDT c, const char *sch, const char *opt)
+{
+	if(mgl_check_dim2(gr,x,y,c,0,"Dens"))	return;
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Dens",cgid++);
+	mreal	zVal = gr->Min.z;
+
+	mglDataV z(c->GetNx(),c->GetNy(),c->GetNz());
+	if(z.GetNz()>1)	z.Fill(gr->Min.z,gr->Max.z,'z');
+	else	z.Fill(zVal);
+	mgl_surf_gen(gr, x, y, &z, c, 0, sch);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dens(HMGL gr, HCDT c, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(c->GetNx()), y(c->GetNy());
+	x.Fill(gr->Min.x, gr->Max.x);
+	y.Fill(gr->Min.y, gr->Max.y);
+	mgl_dens_xy(gr,&x,&y,c,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dens_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_dens_xy(_GR_,_DA_(x), _DA_(y), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_dens_(uintptr_t *gr, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_dens(_GR_,_DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	STFA series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_stfa_xy(HMGL gr, HCDT x, HCDT y, HCDT re, HCDT im, int dn, const char *sch, const char *opt)
+{	mglData tmp(mglSTFA(*re,*im,dn,'x'));	mgl_dens_xy(gr,x,y,&tmp,sch,opt);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_stfa(HMGL gr, HCDT re, HCDT im, int dn, const char *sch, const char *opt)
+{	mglData tmp(mglSTFA(*re,*im,dn,'x'));	mgl_dens(gr,&tmp,sch,opt);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_stfa_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *re, uintptr_t *im, int *dn, const char *sch, const char *opt, int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_stfa_xy(_GR_,_DA_(x), _DA_(y), _DA_(re), _DA_(im), *dn, s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_stfa_(uintptr_t *gr, uintptr_t *re, uintptr_t *im, int *dn, const char *sch, const char *opt, int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_stfa(_GR_,_DA_(re), _DA_(im), *dn, s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Boxs series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_boxs_xy(HMGL gr, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{
+	long n=z->GetNx(),m=z->GetNy();
+	if(mgl_check_dim2(gr,x,y,z,0,"Boxs",true))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Boxs",cgid++);
+	long ly = y->GetNy()>=m ? y->GetNy() : y->GetNx(), lx = x->GetNx();
+	int d = gr->MeshNum>0 ? gr->MeshNum+1 : n*m, dx = n>d?n/d:1, dy = m>d?m/d:1;
+
+	long ss = gr->AddTexture(sch);
+	bool wire = mglchr(sch,'#');
+	bool full = mglchr(sch,'@');
+	gr->Reserve(8*n*m*z->GetNz());
+
+	mglPoint p1,p2,p3,p4,q,s,t(wire||full?NAN:0,0,1),xx,yy;
+	mreal zz,z1,z2,x1,y1,x2,y2,x3,y3,c,z0=gr->GetOrgZ('x');
+	long k1,k2,k3,k4,k5,k6,k7,k8;
+	for(long k=0;k<z->GetNz();k++)
+	{
+		if(gr->NeedStop())	break;
+		for(long i=0;i<n;i+=dx)	for(long j=0;j<m;j+=dy)
+		{
+			zz = z->v(i,j,k);		c  = gr->GetC(ss,zz);
+			xx = GetX(x,i,j,k);		yy = GetY(y,i,j,k);
+			x1 = i<lx-dx ? GetX(x,i+dx,j,k).x:NAN;
+			y1 = i<lx-dx ? GetY(y,i+dx,j,k).x:NAN;
+			x2 = j<ly-dy ? GetX(x,i,j+dy,k).x:NAN;
+			y2 = j<ly-dy ? GetY(y,i,j+dy,k).x:NAN;
+			x3 = i<lx-dx && j<ly-dy ? GetX(x,i+dx,j+dy,k).x:NAN;
+			y3 = i<lx-dx && j<ly-dy ? GetY(y,i+dx,j+dy,k).x:NAN;
+			z1 = i<n-dx?z->v(i+dx,j,k):NAN;
+			z2 = j<m-dy?z->v(i,j+dy,k):NAN;
+			q.Set(xx.y,yy.y,0);
+			s.Set(xx.z,yy.z,0);
+			p1.Set(xx.x,yy.x,zz);	k1 = gr->AddPnt(p1,c,t);
+			p2.Set(x1,y1,zz);		k2 = gr->AddPnt(p2,c,t);
+			p3.Set(x2,y2,zz);		k3 = gr->AddPnt(p3,c,t);
+			p4.Set(x3,y3,zz);		k4 = gr->AddPnt(p4,c,t);
+			if(wire)
+			{
+				gr->line_plot(k1,k2);	gr->line_plot(k1,k3);
+				gr->line_plot(k4,k2);	gr->line_plot(k4,k3);
+			}
+			else	gr->quad_plot(k1,k2,k3,k4);
+
+			if(full)
+			{
+				p1.Set(xx.x,yy.x,z0);	k5 = gr->AddPnt(p1,c,t);
+				p2.Set(x1,y1,z0);		k6 = gr->AddPnt(p2,c,t);
+				p3.Set(x2,y2,z0);		k7 = gr->AddPnt(p3,c,t);
+				p4.Set(x3,y3,z0);		k8 = gr->AddPnt(p4,c,t);
+				if(wire)
+				{
+					gr->line_plot(k5,k6);	gr->line_plot(k5,k7);
+					gr->line_plot(k8,k6);	gr->line_plot(k8,k7);
+					gr->line_plot(k1,k5);	gr->line_plot(k3,k7);
+					gr->line_plot(k2,k6);	gr->line_plot(k4,k8);
+				}
+				else
+				{
+					gr->quad_plot(k1,k2,k5,k6);	gr->quad_plot(k1,k3,k5,k7);
+					gr->quad_plot(k4,k2,k8,k6);	gr->quad_plot(k4,k3,k8,k7);
+					gr->quad_plot(k5,k6,k7,k8);
+				}
+			}
+			else
+			{
+				p3.Set(x1,y1,z1);		k5 = gr->AddPnt(p3,c,wire?t:q);
+				p4.Set(x3,y3,z1);		k6 = gr->AddPnt(p4,c,wire?t:q);
+				if(wire)
+				{	gr->line_plot(k2,k5);	gr->line_plot(k6,k5);	gr->line_plot(k6,k4);	}
+				else	gr->quad_plot(k2,k4,k5,k6);
+				p3.Set(x2,y2,z2);		k7 = gr->AddPnt(p3,c,wire?t:s);
+				p4.Set(x3,y3,z2);		k8 = gr->AddPnt(p4,c,wire?t:s);
+				if(wire)
+				{	gr->line_plot(k3,k7);	gr->line_plot(k4,k8);	gr->line_plot(k7,k8);	}
+				else	gr->quad_plot(k3,k4,k7,k8);
+			}
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_boxs(HMGL gr, HCDT z, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(z->GetNx()+1), y(z->GetNy()+1);
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	mgl_boxs_xy(gr,&x,&y,z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_boxs_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_boxs_xy(_GR_, _DA_(x), _DA_(y), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_boxs_(uintptr_t *gr, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_boxs(_GR_, _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Tile series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tile_xyc(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT c, const char *sch, const char *opt)
+{
+	long n=z->GetNx(),m=z->GetNy();
+	if(mgl_check_dim2(gr,x,y,z,c,"Tile",true))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Tile",cgid++);
+	long ly = x->GetNy()>=z->GetNy() ? y->GetNy() : y->GetNx(), lx = x->GetNx();
+	int d = gr->MeshNum>0 ? gr->MeshNum+1 : n*m, dx = n>d?n/d:1, dy = m>d?m/d:1;
+
+	long ss = gr->AddTexture(sch);
+	gr->Reserve(4*n*m*z->GetNz());
+	bool alongX = mglchr(sch,'x');
+	bool alongY = mglchr(mglchr(sch,':'),'y');
+
+	mglPoint s(0,0,1);
+	for(long k=0;k<z->GetNz();k++)
+	{
+		if(gr->NeedStop())	break;
+		if(alongX)	for(long j=0;j<m;j+=dx)	for(long i=0;i<n;i+=dy)
+		{
+			mreal zz = z->v(i,j,k), cc = gr->GetC(ss,c->v(i,j,k));
+			mreal xx = GetX(x,i,j,k).x, yy = GetY(y,i,j,k).x;
+			long k1 = gr->AddPnt(mglPoint(xx,yy,zz),cc,s);
+			zz = i<lx-dx ? z->v(i+dx,j,k):NAN;
+			yy = i<lx-dx ? GetY(y,i+dx,j,k).x:NAN;
+			long k2 = gr->AddPnt(mglPoint(xx,yy,zz),cc,s);
+			zz = j<ly-dy ? z->v(i,j+dy,k):NAN;
+			yy = j<ly-dy ? GetY(y,i,j+dy,k).x:NAN;
+			long k3 = gr->AddPnt(mglPoint(xx,yy,zz),cc,s);
+			zz = i<lx-dx && j<ly-dy ? z->v(i+dx,j+dy,k):NAN;
+			yy = i<lx-dx && j<ly-dy ? GetY(y,i+dx,j+dy,k).x:NAN;
+			long k4 = gr->AddPnt(mglPoint(xx,yy,zz),cc,s);
+			gr->quad_plot(k1,k2,k3,k4);
+		}
+		else if(alongY)	for(long j=0;j<m;j+=dx)	for(long i=0;i<n;i+=dy)
+		{
+			mreal zz = z->v(i,j,k), cc = gr->GetC(ss,c->v(i,j,k));
+			mreal xx = GetX(x,i,j,k).x, yy = GetY(y,i,j,k).x;
+			long k1 = gr->AddPnt(mglPoint(xx,yy,zz),cc,s);
+			xx = i<lx-dx ? GetX(x,i+dx,j,k).x:NAN;
+			zz = i<lx-dx ? z->v(i+dx,j,k):NAN;
+			long k2 = gr->AddPnt(mglPoint(xx,yy,zz),cc,s);
+			xx = j<ly-dy ? GetX(x,i,j+dy,k).x:NAN;
+			zz = j<ly-dy ? z->v(i,j+dy,k):NAN;
+			long k3 = gr->AddPnt(mglPoint(xx,yy,zz),cc,s);
+			xx = i<lx-dx && j<ly-dy ? GetX(x,i+dx,j+dy,k).x:NAN;
+			zz = i<lx-dx && j<ly-dy ? z->v(i+dx,j+dy,k):NAN;
+			long k4 = gr->AddPnt(mglPoint(xx,yy,zz),cc,s);
+			gr->quad_plot(k1,k2,k3,k4);
+		}
+		else	for(long j=0;j<m;j+=dx)	for(long i=0;i<n;i+=dy)
+		{
+			mreal zz = z->v(i,j,k), cc = gr->GetC(ss,c->v(i,j,k));
+			mreal xx = GetX(x,i,j,k).x, yy = GetY(y,i,j,k).x;
+			long k1 = gr->AddPnt(mglPoint(xx,yy,zz),cc,s);
+			xx = i<lx-dx ? GetX(x,i+dx,j,k).x:NAN;
+			yy = i<lx-dx ? GetY(y,i+dx,j,k).x:NAN;
+			long k2 = gr->AddPnt(mglPoint(xx,yy,zz),cc,s);
+			xx = j<ly-dy ? GetX(x,i,j+dy,k).x:NAN;
+			yy = j<ly-dy ? GetY(y,i,j+dy,k).x:NAN;
+			long k3 = gr->AddPnt(mglPoint(xx,yy,zz),cc,s);
+			xx = i<lx-dx && j<ly-dy ? GetX(x,i+dx,j+dy,k).x:NAN;
+			yy = i<lx-dx && j<ly-dy ? GetY(y,i+dx,j+dy,k).x:NAN;
+			long k4 = gr->AddPnt(mglPoint(xx,yy,zz),cc,s);
+			gr->quad_plot(k1,k2,k3,k4);
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tile_xy(HMGL gr, HCDT x, HCDT y, HCDT z, const char *sch, const char *opt)
+{	mgl_tile_xyc(gr,x,y,z,z,sch,opt);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tile(HMGL gr, HCDT z, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(z->GetNx()+1), y(z->GetNy()+1);
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	mgl_tile_xyc(gr,&x,&y,z,z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tile_xyc_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tile_xyc(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(c), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tile_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tile_xy(_GR_, _DA_(x), _DA_(y), _DA_(z), s, o);	delete []o;	delete []s;	}
+	//-----------------------------------------------------------------------------
+	void MGL_EXPORT mgl_tile_(uintptr_t *gr, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tile(_GR_, _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	TileS series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tiles_xyc(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT s, HCDT c, const char *sch, const char *opt)
+{
+	long n=z->GetNx(),m=z->GetNy();
+	if(mgl_check_dim2(gr,x,y,z,s,"TileS",true))	return;
+	if(mgl_check_dim2(gr,x,y,z,c,"TileS",true))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("TileS",cgid++);
+	long ly = x->GetNy()>=z->GetNy() ? y->GetNy() : y->GetNx(), lx = x->GetNx();
+	int d = gr->MeshNum>0 ? gr->MeshNum+1 : n*m, dx = n>d?n/d:1, dy = m>d?m/d:1;
+
+	long sc = gr->AddTexture(sch);
+	gr->Reserve(4*n*m*z->GetNz());
+	bool alongX = mglchr(sch,'x');
+	bool alongY = mglchr(mglchr(sch,':'),'y');
+
+	mglPoint t(0,0,1);
+	mreal x1,x2,x3,x4,y1,y2,y3,y4;
+	for(long k=0;k<z->GetNz();k++)
+	{
+		if(gr->NeedStop())	break;
+		if(alongX)	for(long j=0;j<m;j+=dx)	for(long i=0;i<n;i+=dy)
+		{
+			mreal xx = GetX(x,i,j,k).x, cc = gr->GetC(sc,c->v(i,j,k));
+			mreal ss = (1-gr->GetA(s->v(i,j,k)))/2, sm = 1-ss;
+			x1 = z->v(i,j,k);	y1 = GetY(y,i,j,k).x;
+			x2 = x3 = x4 = y2 = y3 = y4 = NAN;
+			if(i<lx-dx)	{	x2 = z->v(i+dx,j,k)-x1;	y2 = GetY(y,i+dx,j,k).x-y1;	}
+			if(j<ly-dy)	{	x4 = z->v(i,j+dy,k)-x1;	y4 = GetY(y,i,j+dy,k).x-y1;	}
+			if(i<lx-dx && j<ly-dy)
+			{	x3 = z->v(i+dx,j+dy,k)-x2-x4-x1;	y3 = GetY(y,i+dx,j+dy,k).x-y2-y4-y1;	}
+
+			long k1 = gr->AddPnt(mglPoint(xx, y1+y2*ss+y4*ss+y3*ss*ss, x1+x2*ss+x4*ss+x3*ss*ss),cc,t);
+			long k2 = gr->AddPnt(mglPoint(xx, y1+y2*sm+y4*ss+y3*ss*sm, x1+x2*sm+x4*ss+x3*ss*sm),cc,t);
+			long k3 = gr->AddPnt(mglPoint(xx, y1+y2*ss+y4*sm+y3*ss*sm, x1+x2*ss+x4*sm+x3*ss*sm),cc,t);
+			long k4 = gr->AddPnt(mglPoint(xx, y1+y2*sm+y4*sm+y3*sm*sm, x1+x2*sm+x4*sm+x3*sm*sm),cc,t);
+			gr->quad_plot(k1,k2,k3,k4);
+		}
+		else if(alongY)	for(long j=0;j<m;j+=dx)	for(long i=0;i<n;i+=dy)
+		{
+			mreal yy = GetY(y,i,j,k).x, cc = gr->GetC(sc,c->v(i,j,k));
+			mreal ss = (1-gr->GetA(s->v(i,j,k)))/2, sm = 1-ss;
+			x1 = GetX(x,i,j,k).x;	y1 = z->v(i,j,k);
+			x2 = x3 = x4 = y2 = y3 = y4 = NAN;
+			if(i<lx-dx)	{	x2 = GetX(x,i+dx,j,k).x-x1;	y2 = z->v(i+dx,j,k)-y1;	}
+			if(j<ly-dy)	{	x4 = GetX(x,i,j+dy,k).x-x1;	y4 = z->v(i,j+dy,k)-y1;	}
+			if(i<lx-dx && j<ly-dy)
+			{	x3 = GetX(x,i+dx,j+dy,k).x-x2-x4-x1;	y3 = z->v(i+dx,j+dy,k)-y2-y4-y1;	}
+
+			long k1 = gr->AddPnt(mglPoint(x1+x2*ss+x4*ss+x3*ss*ss, yy, y1+y2*ss+y4*ss+y3*ss*ss),cc,t);
+			long k2 = gr->AddPnt(mglPoint(x1+x2*sm+x4*ss+x3*ss*sm, yy, y1+y2*sm+y4*ss+y3*ss*sm),cc,t);
+			long k3 = gr->AddPnt(mglPoint(x1+x2*ss+x4*sm+x3*ss*sm, yy, y1+y2*ss+y4*sm+y3*ss*sm),cc,t);
+			long k4 = gr->AddPnt(mglPoint(x1+x2*sm+x4*sm+x3*sm*sm, yy, y1+y2*sm+y4*sm+y3*sm*sm),cc,t);
+			gr->quad_plot(k1,k2,k3,k4);
+		}
+		else	for(long j=0;j<m;j+=dx)	for(long i=0;i<n;i+=dy)
+		{
+			mreal zz = z->v(i,j,k), cc = gr->GetC(sc,c->v(i,j,k));
+			mreal ss = (1-gr->GetA(s->v(i,j,k)))/2, sm = 1-ss;
+			x1 = GetX(x,i,j,k).x;	y1 = GetY(y,i,j,k).x;
+			x2 = x3 = x4 = y2 = y3 = y4 = NAN;
+			if(i<lx-dx)	{	x2 = GetX(x,i+dx,j,k).x-x1;	y2 = GetY(y,i+dx,j,k).x-y1;	}
+			if(j<ly-dy)	{	x4 = GetX(x,i,j+dy,k).x-x1;	y4 = GetY(y,i,j+dy,k).x-y1;	}
+			if(i<lx-dx && j<ly-dy)
+			{	x3 = GetX(x,i+dx,j+dy,k).x-x2-x4-x1;	y3 = GetY(y,i+dx,j+dy,k).x-y2-y4-y1;	}
+
+			long k1 = gr->AddPnt(mglPoint(x1+x2*ss+x4*ss+x3*ss*ss, y1+y2*ss+y4*ss+y3*ss*ss, zz),cc,t);
+			long k2 = gr->AddPnt(mglPoint(x1+x2*sm+x4*ss+x3*ss*sm, y1+y2*sm+y4*ss+y3*ss*sm, zz),cc,t);
+			long k3 = gr->AddPnt(mglPoint(x1+x2*ss+x4*sm+x3*ss*sm, y1+y2*ss+y4*sm+y3*ss*sm, zz),cc,t);
+			long k4 = gr->AddPnt(mglPoint(x1+x2*sm+x4*sm+x3*sm*sm, y1+y2*sm+y4*sm+y3*sm*sm, zz),cc,t);
+			gr->quad_plot(k1,k2,k3,k4);
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tiles_xy(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT s, const char *sch, const char *opt)
+{	mgl_tiles_xyc(gr,x,y,z,s,z,sch,opt);	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tiles(HMGL gr, HCDT z, HCDT s, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(z->GetNx()+1), y(z->GetNy()+1);
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	mgl_tiles_xyc(gr,&x,&y,z,s,z,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tiles_xyc_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *r, uintptr_t *c, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tiles_xyc(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(r), _DA_(c), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_tiles_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *r, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tiles_xy(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(r), s, o);	delete []o;	delete []s;	}
+	//-----------------------------------------------------------------------------
+	void MGL_EXPORT mgl_tiles_(uintptr_t *gr, uintptr_t *a, uintptr_t *r, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_tiles(_GR_, _DA_(a), _DA_(r), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Map series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_map_xy(HMGL gr, HCDT x, HCDT y, HCDT ax, HCDT ay, const char *sch, const char *opt)
+{
+	long n=ax->GetNx(),m=ax->GetNy();
+	if(mgl_check_dim2(gr,x,y,ax,ay,"Map"))	return;
+
+	bool nboth = !(x->GetNx()==n && y->GetNx()==n && x->GetNy()==m && y->GetNy()==m);
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Map",cgid++);
+
+	long ss = gr->AddTexture(mgl_have_color(sch)?sch:"rgb",2);
+	long s = nboth ?1:n;
+
+	mglPoint t(NAN);
+	long *pos = new long[n*m];
+	gr->Reserve(n*m);
+
+#pragma omp parallel for collapse(2)
+	for(long j=0;j<m;j++)	for(long i=0;i<n;i++)
+	{
+		long s1 = i>0 ? 1:0, s2 = i<n-1 ? 1:0;
+		mreal xdx = (ax->v(i+s2,j)-ax->v(i-s1,j))/(GetX(x,i+s2,j).x-GetX(x,i-s1,j).x);
+		mreal ydx = (ay->v(i+s2,j)-ay->v(i-s1,j))/(GetX(x,i+s2,j).x-GetX(x,i-s1,j).x);
+		s1 = j>0 ? s:0;		s2 = j<m-1 ? s:0;
+		mreal xdy = (ax->v(i,j+s2)-ax->v(i,j-s1))/(GetY(y,i,j+s2).x-GetY(y,i,j-s1).x);
+		mreal ydy = (ay->v(i,j+s2)-ay->v(i,j-s1))/(GetY(y,i,j+s2).x-GetY(y,i,j-s1).x);
+		xdx = xdx*ydy - xdy*ydx;	// Jacobian
+		mreal xx,yy;
+
+		if(nboth)
+		{
+			xx = (x->v(i) - gr->Min.x)/(gr->Max.x - gr->Min.x);
+			yy = (y->v(j) - gr->Min.y)/(gr->Max.y - gr->Min.y);
+		}
+		else
+		{
+			xx = (x->v(i,j) - gr->Min.x)/(gr->Max.x - gr->Min.x);
+			yy = (y->v(i,j) - gr->Min.y)/(gr->Max.y - gr->Min.y);
+		}
+		if(xx<0)	xx=0;
+		if(xx>=1)	xx=1/MGL_FEPSILON;
+		if(yy<0)	yy=0;
+		if(yy>=1)	yy=1/MGL_FEPSILON;
+		pos[i+n*j] = gr->AddPnt(mglPoint(ax->v(i,j), ay->v(i,j), xdx),gr->GetC(ss,xx,false),t,yy);
+	}
+	if(sch && mglchr(sch,'.'))
+		for(long i=0;i<n*m;i++)	gr->mark_plot(pos[i],'.');
+	else	mgl_surf_plot(gr,pos,n,m);
+	delete []pos;	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_map(HMGL gr, HCDT ax, HCDT ay, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(ax->GetNx()), y(ax->GetNy());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	mgl_map_xy(gr,&x,&y,ax,ay,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_map_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *a, uintptr_t *b, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_map_xy(_GR_, _DA_(x), _DA_(y), _DA_(a), _DA_(b), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_map_(uintptr_t *gr, uintptr_t *a, uintptr_t *b, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_map(_GR_, _DA_(a), _DA_(b), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
diff --git a/src/tex_table.cc b/src/tex_table.cc
new file mode 100644
index 0000000..86deba2
--- /dev/null
+++ b/src/tex_table.cc
@@ -0,0 +1,1951 @@
+/***************************************************************************
+ * tex_table.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2014 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include "mgl2/font.h"
+
+/// Table of LaTeX symbols and its UTF8 codes. This array MUST BE sorted!!!
+const size_t mgl_tex_num=1924;
+const mglTeXsymb mgl_tex_symb[] = {
+	{0x23, L"#"},
+	{0x25, L"%"},
+	{0x26, L"&"},
+	{0xc5, L"AA"},
+	{0xc6, L"AE"},
+	{0x2370, L"APLboxquestion"},
+	{0x2353, L"APLboxupcaret"},
+	{0x2340, L"APLnotbackslash"},
+	{0x233f, L"APLnotslash"},
+	{0x391, L"Alpha"},
+	{0x26, L"And"},
+	{0x212b, L"Angstrom"},
+	{0x2ae7, L"Barv"},
+	{0x2102, L"BbbC"},
+	{0x213e, L"BbbGamma"},
+	{0x210d, L"BbbH"},
+	{0x2115, L"BbbN"},
+	{0x2119, L"BbbP"},
+	{0x213f, L"BbbPi"},
+	{0x211a, L"BbbQ"},
+	{0x211d, L"BbbR"},
+	{0x2124, L"BbbZ"},
+	{0x213d, L"Bbbgamma"},
+	{0x213c, L"Bbbpi"},
+	{0x2140, L"Bbbsum"},
+	{0x392, L"Beta"},
+	{0x224e, L"Bumpeq"},
+	{0x410, L"CYRA"},
+	{0x411, L"CYRB"},
+	{0x426, L"CYRC"},
+	{0x427, L"CYRCH"},
+	{0x414, L"CYRD"},
+	{0x415, L"CYRE"},
+	{0x42d, L"CYREREV"},
+	{0x42b, L"CYRERY"},
+	{0x424, L"CYRF"},
+	{0x413, L"CYRG"},
+	{0x425, L"CYRH"},
+	{0x42a, L"CYRHRDSN"},
+	{0x418, L"CYRI"},
+	{0x419, L"CYRISHRT"},
+	{0x41a, L"CYRK"},
+	{0x41b, L"CYRL"},
+	{0x41c, L"CYRM"},
+	{0x41d, L"CYRN"},
+	{0x41e, L"CYRO"},
+	{0x41f, L"CYRP"},
+	{0x420, L"CYRR"},
+	{0x421, L"CYRS"},
+	{0x42c, L"CYRSFTSN"},
+	{0x428, L"CYRSH"},
+	{0x429, L"CYRSHCH"},
+	{0x422, L"CYRT"},
+	{0x423, L"CYRU"},
+	{0x412, L"CYRV"},
+	{0x42f, L"CYRYA"},
+	{0x401, L"CYRYO"},
+	{0x42e, L"CYRYU"},
+	{0x417, L"CYRZ"},
+	{0x416, L"CYRZH"},
+	{0x22d2, L"Cap"},
+	{0x3a7, L"Chi"},
+	{0x2237, L"Colon"},
+	{0x2a74, L"Coloneq"},
+	{0x22d3, L"Cup"},
+	{0x27f1, L"DDownarrow"},
+	{0xd0, L"DH"},
+	{0x110, L"DJ"},
+	{0x2ae5, L"DashV"},
+	{0x27da, L"DashVDash"},
+	{0x2ae4, L"Dashv"},
+	{0x290b, L"Ddownarrow"},
+	{0x394, L"Delta"},
+	{0x3dc, L"Digamma"},
+	{0x2251, L"Doteq"},
+	{0x21d3, L"Downarrow"},
+	{0x395, L"Epsilon"},
+	{0x2263, L"Equiv"},
+	{0x397, L"Eta"},
+	{0x2107, L"Eulerconst"},
+	{0x203c, L"Exclam"},
+	{0x2132, L"Finv"},
+	{0x2141, L"Game"},
+	{0x393, L"Gamma"},
+	{0x2aa2, L"Gt"},
+	{0x26a5, L"Hermaphrodite"},
+	{0x2111, L"Im"},
+	{0x399, L"Iota"},
+	{0x39a, L"Kappa"},
+	{0x3de, L"Koppa"},
+	{0x141, L"L"},
+	{0x2b45, L"LLeftarrow"},
+	{0x39b, L"Lambda"},
+	{0x27ec, L"Lbrbrak"},
+	{0x21b2, L"Ldsh"},
+	{0x21d0, L"Leftarrow"},
+	{0x21d4, L"Leftrightarrow"},
+	{0x21da, L"Lleftarrow"},
+	{0x27f8, L"Longleftarrow"},
+	{0x27fa, L"Longleftrightarrow"},
+	{0x27fd, L"Longmapsfrom"},
+	{0x27fe, L"Longmapsto"},
+	{0x27f9, L"Longrightarrow"},
+	{0x2995, L"Lparengtr"},
+	{0x21b0, L"Lsh"},
+	{0x2aa1, L"Lt"},
+	{0x29da, L"Lvzigzag"},
+	{0x2906, L"Mapsfrom"},
+	{0x2907, L"Mapsto"},
+	{0x39c, L"Mu"},
+	{0x14a, L"NG"},
+	{0x21d7, L"Nearrow"},
+	{0x2aec, L"Not"},
+	{0x39d, L"Nu"},
+	{0x21d6, L"Nwarrow"},
+	{0xd8, L"O"},
+	{0x152, L"OE"},
+	{0x1a0, L"Ohorn"},
+	{0x3a9, L"Omega"},
+	{0x39f, L"Omicron"},
+	{0x2a37, L"Otimes"},
+	{0xb6, L"P"},
+	{0x3a6, L"Phi"},
+	{0x3a0, L"Pi"},
+	{0x210e, L"Planckconst"},
+	{0x2abb, L"Prec"},
+	{0x214a, L"PropertyLine"},
+	{0x3a8, L"Psi"},
+	{0x220e, L"QED"},
+	{0x2047, L"Question"},
+	{0x2b46, L"RRightarrow"},
+	{0x27ed, L"Rbrbrak"},
+	{0x21b3, L"Rdsh"},
+	{0x211c, L"Re"},
+	{0x3a1, L"Rho"},
+	{0x21d2, L"Rightarrow"},
+	{0x2996, L"Rparenless"},
+	{0x21db, L"Rrightarrow"},
+	{0x21b1, L"Rsh"},
+	{0x29db, L"Rvzigzag"},
+	{0xa7, L"S"},
+	{0x2abc, L"Sc"},
+	{0x21d8, L"Searrow"},
+	{0x3a3, L"Sigma"},
+	{0x2a4e, L"Sqcap"},
+	{0x2a4f, L"Sqcup"},
+	{0x3da, L"Stigma"},
+	{0x22d0, L"Subset"},
+	{0x22d1, L"Supset"},
+	{0x21d9, L"Swarrow"},
+	{0xde, L"TH"},
+	{0x3a4, L"Tau"},
+	{0x398, L"Theta"},
+	{0x27f0, L"UUparrow"},
+	{0x1af, L"Uhorn"},
+	{0x21d1, L"Uparrow"},
+	{0x21d5, L"Updownarrow"},
+	{0x290a, L"Uuparrow"},
+	{0x22ab, L"VDash"},
+	{0x2aeb, L"Vbar"},
+	{0x22a9, L"Vdash"},
+	{0x2a54, L"Vee"},
+	{0x2016, L"Vert"},
+	{0x22aa, L"Vvdash"},
+	{0x2980, L"Vvert"},
+	{0x2a53, L"Wedge"},
+	{0x2612, L"XBox"},
+	{0x39e, L"Xi"},
+	{0x2144, L"Yup"},
+	{0x1b5, L"Zbar"},
+	{0x396, L"Zeta"},
+	{0x5e, L"^"},
+	{0xe5, L"aa"},
+	{0x223e, L"ac"},
+	{0x23e6, L"accurrent"},
+	{0x267e, L"acidfree"},
+	{0x2940, L"acwcirclearrow"},
+	{0x27f2, L"acwgapcirclearrow"},
+	{0x2939, L"acwleftarcarrow"},
+	{0x21ba, L"acwopencirclearrow"},
+	{0x293a, L"acwoverarcarrow"},
+	{0x293b, L"acwundercurvearrow"},
+	{0x22f0, L"adots"},
+	{0xe6, L"ae"},
+	{0x2135, L"aleph"},
+	{0x3b1, L"alpha"},
+//	{0x2210, L"amalg"},
+	{0x2a3f, L"amalg"},
+	{0x299f, L"angdnr"},
+	{0x2220, L"angle"},
+	{0x299e, L"angles"},
+	{0x29a4, L"angleubar"},
+	{0x2248, L"approx"},
+	{0x224a, L"approxeq"},
+	{0x2a70, L"approxeqq"},
+	{0x224b, L"approxident"},
+	{0x2258, L"arceq"},
+	{0x2648, L"aries"},
+	{0x22a6, L"assert"},
+	{0x2217, L"ast"},
+	{0x2a6e, L"asteq"},
+	{0x2609, L"astrosun"},
+	{0x224d, L"asymp"},
+	{0x2a11, L"awint"},
+	{0x2aed, L"bNot"},
+	{0x224c, L"backcong"},
+	{0x2036, L"backdprime"},
+	{0x3f6, L"backepsilon"},
+	{0x2035, L"backprime"},
+	{0x223d, L"backsim"},
+	{0x22cd, L"backsimeq"},
+	{0x5c, L"backslash"},
+	{0x2037, L"backtrprime"},
+	{0x22ff, L"bagmember"},
+	{0x2aea, L"barV"},
+	{0x2a43, L"barcap"},
+	{0x2a42, L"barcup"},
+	{0x2961, L"bardownharpoonleft"},
+	{0x295d, L"bardownharpoonright"},
+	{0x21e4, L"barleftarrow"},
+	{0x21b9, L"barleftarrowrightarrowbar"},
+	{0x2956, L"barleftharpoondown"},
+	{0x2952, L"barleftharpoonup"},
+	{0x21b8, L"barovernorthwestarrow"},
+	{0x2920, L"barrightarrowdiamond"},
+	{0x295f, L"barrightharpoondown"},
+	{0x295b, L"barrightharpoonup"},
+	{0x2912, L"baruparrow"},
+	{0x2958, L"barupharpoonleft"},
+	{0x2954, L"barupharpoonright"},
+	{0x22bd, L"barvee"},
+	{0x22bc, L"barwedge"},
+	{0x23b6, L"bbrktbrk"},
+	{0x2550, L"bdHrule"},
+	{0x2551, L"bdVrule"},
+	{0x256c, L"bdbVbH"},
+	{0x256b, L"bdbVbh"},
+	{0x2563, L"bdbVlH"},
+	{0x2562, L"bdbVlh"},
+	{0x2560, L"bdbVrH"},
+	{0x255f, L"bdbVrh"},
+	{0x256a, L"bdbvbH"},
+	{0x253c, L"bdbvbh"},
+	{0x2561, L"bdbvlH"},
+	{0x2524, L"bdbvlh"},
+	{0x255e, L"bdbvrH"},
+	{0x251c, L"bdbvrh"},
+	{0x2566, L"bddVbH"},
+	{0x2565, L"bddVbh"},
+	{0x2557, L"bddVlH"},
+	{0x2556, L"bddVlh"},
+	{0x2554, L"bddVrH"},
+	{0x2553, L"bddVrh"},
+	{0x2564, L"bddvbH"},
+	{0x252c, L"bddvbh"},
+	{0x2555, L"bddvlH"},
+	{0x2510, L"bddvlh"},
+	{0x2552, L"bddvrH"},
+	{0x250c, L"bddvrh"},
+	{0x2500, L"bdhrule"},
+	{0x2571, L"bdnesw"},
+	{0x2572, L"bdnwse"},
+	{0x2508, L"bdquadhdash"},
+	{0x250a, L"bdquadvdash"},
+	{0x2506, L"bdtriplevdash"},
+	{0x2569, L"bduVbH"},
+	{0x2568, L"bduVbh"},
+	{0x255d, L"bduVlH"},
+	{0x255c, L"bduVlh"},
+	{0x255a, L"bduVrH"},
+	{0x2559, L"bduVrh"},
+	{0x2567, L"bduvbH"},
+	{0x2534, L"bduvbh"},
+	{0x255b, L"bduvlH"},
+	{0x2518, L"bduvlh"},
+	{0x2558, L"bduvrH"},
+	{0x2514, L"bduvrh"},
+	{0x2502, L"bdvrule"},
+	{0x2235, L"because"},
+	{0x23e3, L"benzenr"},
+	{0x3b2, L"beta"},
+	{0x2136, L"beth"},
+	{0x226c, L"between"},
+	{0x25bc, L"bigblacktriangledown"},
+	{0x25b2, L"bigblacktriangleup"},
+	{0x27d8, L"bigbot"},
+	{0x22c2, L"bigcap"},
+	{0x22c3, L"bigcup"},
+	{0x2a57, L"bigslopedvee"},
+	{0x2a58, L"bigslopedwedge"},
+	{0x2605, L"bigstar"},
+	{0x27d9, L"bigtop"},
+	{0x25bd, L"bigtriangledown"},
+	{0x25b3, L"bigtriangleup"},
+	{0x22c1, L"bigvee"},
+	{0x22c0, L"bigwedge"},
+	{0x2606, L"bigwhitestar"},
+	{0x29ed, L"blackcircledownarrow"},
+	{0x2688, L"blackcircledrightdot"},
+	{0x2791, L"blackcircledsanseight"},
+	{0x278e, L"blackcircledsansfive"},
+	{0x278d, L"blackcircledsansfour"},
+	{0x2792, L"blackcircledsansnine"},
+	{0x278a, L"blackcircledsansone"},
+	{0x2790, L"blackcircledsansseven"},
+	{0x278f, L"blackcircledsanssix"},
+	{0x2793, L"blackcircledsansten"},
+	{0x278c, L"blackcircledsansthree"},
+	{0x278b, L"blackcircledsanstwo"},
+	{0x2689, L"blackcircledtwodots"},
+	{0x25d5, L"blackcircleulquadwhite"},
+	{0x29ea, L"blackdiamonddownarrow"},
+	{0x29d7, L"blackhourglass"},
+	{0x25c8, L"blackinwhitediamond"},
+	{0x25a3, L"blackinwhitesquare"},
+	{0x25d6, L"blacklefthalfcircle"},
+	{0x25c4, L"blackpointerleft"},
+	{0x25ba, L"blackpointerright"},
+	{0x25d7, L"blackrighthalfcircle"},
+	{0x263b, L"blacksmiley"},
+	{0x25b4, L"blacktriangle"},
+	{0x25be, L"blacktriangledown"},
+	{0x25c0, L"blacktriangleleft"},
+	{0x25b6, L"blacktriangleright"},
+	{0x2b2c, L"blkhorzoval"},
+	{0x2b2e, L"blkvertoval"},
+	{0x2588, L"blockfull"},
+	{0x2592, L"blockhalfshaded"},
+	{0x258c, L"blocklefthalf"},
+	{0x2584, L"blocklowhalf"},
+	{0x2591, L"blockqtrshaded"},
+	{0x2590, L"blockrighthalf"},
+	{0x2593, L"blockthreeqtrshaded"},
+	{0x2580, L"blockuphalf"},
+	{0x22a5, L"bot"},
+	{0x25e1, L"botsemicircle"},
+	{0x22c8, L"bowtie"},
+	{0x25fb, L"box"},
+	{0x29c6, L"boxast"},
+	{0x25eb, L"boxbar"},
+	{0x29c8, L"boxbox"},
+	{0x29c5, L"boxbslash"},
+	{0x29c7, L"boxcircle"},
+	{0x29c4, L"boxdiag"},
+	{0x22a1, L"boxdot"},
+	{0x229f, L"boxminus"},
+	{0x29c9, L"boxonbox"},
+	{0x229e, L"boxplus"},
+	{0x22a0, L"boxtimes"},
+	{0x2b41, L"bsimilarleftarrow"},
+	{0x2b47, L"bsimilarrightarrow"},
+	{0x27c8, L"bsolhsub"},
+	{0x2a32, L"btimes"},
+	{0x2219, L"bullet"},
+	{0x25ce, L"bullseye"},
+	{0x224f, L"bumpeq"},
+	{0x2aae, L"bumpeqq"},
+	{0x212c, L"calB"},
+	{0x2130, L"calE"},
+	{0x2131, L"calF"},
+	{0x210b, L"calH"},
+	{0x2110, L"calI"},
+	{0x2112, L"calL"},
+	{0x2133, L"calM"},
+	{0x211b, L"calR"},
+	{0x2229, L"cap"},
+	{0x2a40, L"capdot"},
+	{0x2a44, L"capwedge"},
+	{0x2038, L"caretinsert"},
+	{0x23ce, L"carreturn"},
+	{0x21b5, L"carriagereturn"},
+	{0x293f, L"ccwundercurvearrow"},
+	{0x22c5, L"cdot"},
+	{0xb7, L"cdotp"},
+	{0x22ef, L"cdots"},
+	{0x2ba, L"cdprime"},
+	{0x2713, L"checkmark"},
+	{0x3c7, L"chi"},
+	{0x29c3, L"cirE"},
+	{0x27df, L"cirbot"},
+	{0x2218, L"circ"},
+	{0x2257, L"circeq"},
+	{0x2a10, L"circfint"},
+	{0x25d2, L"circlebottomhalfblack"},
+	{0x24b6, L"circledA"},
+	{0x24b7, L"circledB"},
+	{0x24b8, L"circledC"},
+	{0x24b9, L"circledD"},
+	{0x24ba, L"circledE"},
+	{0x24bb, L"circledF"},
+	{0x24bc, L"circledG"},
+	{0x24bd, L"circledH"},
+	{0x24be, L"circledI"},
+	{0x24bf, L"circledJ"},
+	{0x24c0, L"circledK"},
+	{0x24c1, L"circledL"},
+	{0x24c2, L"circledM"},
+	{0x24c3, L"circledN"},
+	{0x24c4, L"circledO"},
+	{0x24c5, L"circledP"},
+	{0x24c6, L"circledQ"},
+	{0x24c7, L"circledR"},
+	{0x24c8, L"circledS"},
+	{0x24c9, L"circledT"},
+	{0x24ca, L"circledU"},
+	{0x24cb, L"circledV"},
+	{0x24cc, L"circledW"},
+	{0x24cd, L"circledX"},
+	{0x24ce, L"circledY"},
+	{0x24cf, L"circledZ"},
+	{0x24d0, L"circleda"},
+	{0x229b, L"circledast"},
+	{0x24d1, L"circledb"},
+	{0x29bf, L"circledbullet"},
+	{0x24d2, L"circledc"},
+	{0x229a, L"circledcirc"},
+	{0x24d3, L"circledd"},
+	{0x229d, L"circleddash"},
+	{0x24d4, L"circlede"},
+	{0x2467, L"circledeight"},
+	{0x229c, L"circledequal"},
+	{0x24d5, L"circledf"},
+	{0x2464, L"circledfive"},
+	{0x2463, L"circledfour"},
+	{0x24d6, L"circledg"},
+	{0x24d7, L"circledh"},
+	{0x24d8, L"circledi"},
+	{0x24d9, L"circledj"},
+	{0x24da, L"circledk"},
+	{0x24db, L"circledl"},
+	{0x24dc, L"circledm"},
+	{0x24dd, L"circledn"},
+	{0x2468, L"circlednine"},
+	{0x24de, L"circledo"},
+	{0x2460, L"circledone"},
+	{0x29ec, L"circledownarrow"},
+	{0x24df, L"circledp"},
+	{0x29b7, L"circledparallel"},
+	{0x24e0, L"circledq"},
+	{0x24e1, L"circledr"},
+	{0x2686, L"circledrightdot"},
+	{0x24e2, L"circleds"},
+	{0x2787, L"circledsanseight"},
+	{0x2784, L"circledsansfive"},
+	{0x2783, L"circledsansfour"},
+	{0x2788, L"circledsansnine"},
+	{0x2780, L"circledsansone"},
+	{0x2786, L"circledsansseven"},
+	{0x2785, L"circledsanssix"},
+	{0x2789, L"circledsansten"},
+	{0x2782, L"circledsansthree"},
+	{0x2781, L"circledsanstwo"},
+	{0x2466, L"circledseven"},
+	{0x2465, L"circledsix"},
+	{0x272a, L"circledstar"},
+	{0x24e3, L"circledt"},
+	{0x2462, L"circledthree"},
+	{0x2461, L"circledtwo"},
+	{0x2687, L"circledtwodots"},
+	{0x24e4, L"circledu"},
+	{0x24e5, L"circledv"},
+	{0x29b6, L"circledvert"},
+	{0x24e6, L"circledw"},
+	{0x29be, L"circledwhitebullet"},
+	{0x24e7, L"circledx"},
+	{0x24e8, L"circledy"},
+	{0x24e9, L"circledz"},
+	{0x24ea, L"circledzero"},
+	{0x29b5, L"circlehbar"},
+	{0x25d0, L"circlelefthalfblack"},
+	{0x25f5, L"circlellquad"},
+	{0x25f6, L"circlelrquad"},
+	{0x2b30, L"circleonleftarrow"},
+	{0x21f4, L"circleonrightarrow"},
+	{0x25d1, L"circlerighthalfblack"},
+	{0x25d3, L"circletophalfblack"},
+	{0x25f4, L"circleulquad"},
+	{0x25f7, L"circleurquad"},
+	{0x25d4, L"circleurquadblack"},
+	{0x25cd, L"circlevertfill"},
+	{0x2aef, L"cirmid"},
+	{0x29c2, L"cirscir"},
+	{0x2329, L"clangle"},
+	{0x2a4d, L"closedvarcap"},
+	{0x2a4c, L"closedvarcup"},
+	{0x2a50, L"closedvarcupsmashprod"},
+	{0x2050, L"closure"},
+	{0x2318, L"cloverleaf"},
+	{0x2663, L"clubsuit"},
+	{0x3a, L"colon"},
+	{0x2236, L"colon"},
+	{0x2254, L"coloneq"},
+	{0x2a29, L"commaminus"},
+	{0x2201, L"complement"},
+	{0x27e1, L"concavediamond"},
+	{0x27e2, L"concavediamondtickleft"},
+	{0x27e3, L"concavediamondtickright"},
+	{0x2245, L"cong"},
+	{0x2a6d, L"congdot"},
+	{0x2332, L"conictaper"},
+	{0x260c, L"conjunction"},
+	{0x2210, L"coprod"},
+	{0x2b9, L"cprime"},
+	{0x232a, L"crangle"},
+	{0x2acf, L"csub"},
+	{0x2ad1, L"csube"},
+	{0x2ad0, L"csup"},
+	{0x2ad2, L"csupe"},
+	{0x221b, L"cuberoot"},
+	{0x222a, L"cup"},
+	{0x228d, L"cupdot"},
+	{0x228c, L"cupleftarrow"},
+	{0x2a45, L"cupvee"},
+	{0x22de, L"curlyeqprec"},
+	{0x22df, L"curlyeqsucc"},
+	{0x22ce, L"curlyvee"},
+	{0x22cf, L"curlywedge"},
+	{0x21b6, L"curvearrowleft"},
+	{0x293d, L"curvearrowleftplus"},
+	{0x21b7, L"curvearrowright"},
+	{0x293c, L"curvearrowrightminus"},
+	{0x2941, L"cwcirclearrow"},
+	{0x27f3, L"cwgapcirclearrow"},
+	{0x21bb, L"cwopencirclearrow"},
+	{0x2938, L"cwrightarcarrow"},
+	{0x293e, L"cwundercurvearrow"},
+	{0x232d, L"cylcty"},
+	{0x430, L"cyra"},
+	{0x431, L"cyrb"},
+	{0x446, L"cyrc"},
+	{0x447, L"cyrch"},
+	{0x434, L"cyrd"},
+	{0x435, L"cyre"},
+	{0x44d, L"cyrerev"},
+	{0x44b, L"cyrery"},
+	{0x444, L"cyrf"},
+	{0x433, L"cyrg"},
+	{0x445, L"cyrh"},
+	{0x44a, L"cyrhrdsn"},
+	{0x438, L"cyri"},
+	{0x439, L"cyrishrt"},
+	{0x43a, L"cyrk"},
+	{0x43b, L"cyrl"},
+	{0x43c, L"cyrm"},
+	{0x43d, L"cyrn"},
+	{0x43e, L"cyro"},
+	{0x43f, L"cyrp"},
+	{0x440, L"cyrr"},
+	{0x441, L"cyrs"},
+	{0x44c, L"cyrsftsn"},
+	{0x448, L"cyrsh"},
+	{0x449, L"cyrshch"},
+	{0x442, L"cyrt"},
+	{0x443, L"cyru"},
+	{0x432, L"cyrv"},
+	{0x44f, L"cyrya"},
+	{0x451, L"cyryo"},
+	{0x44e, L"cyryu"},
+	{0x437, L"cyrz"},
+	{0x436, L"cyrzh"},
+	{0x2020, L"dag"},
+	{0x2020, L"dagger"},
+	{0x2138, L"daleth"},
+	{0x2621, L"danger"},
+	{0x2ae3, L"dashV"},
+	{0x27db, L"dashVdash"},
+	{0x2239, L"dashcolon"},
+	{0x296b, L"dashleftharpoondown"},
+	{0x296d, L"dashrightharpoondown"},
+	{0x22a3, L"dashv"},
+	{0x290f, L"dbkarow"},
+	{0x2021, L"ddag"},
+	{0x2021, L"ddagger"},
+	{0x22f1, L"ddots"},
+	{0x2a77, L"ddotseq"},
+	{0xb0, L"degree"},
+	{0x3b4, L"delta"},
+	{0xf0, L"dh"},
+	{0x2300, L"diameter"},
+	{0x25c7, L"diamond"},
+	{0x2b19, L"diamondbotblack"},
+	{0x27d0, L"diamondcdot"},
+	{0x291d, L"diamondleftarrow"},
+	{0x291f, L"diamondleftarrowbar"},
+	{0x2b16, L"diamondleftblack"},
+	{0x2b17, L"diamondrightblack"},
+	{0x2662, L"diamondsuit"},
+	{0x2b18, L"diamondtopblack"},
+	{0x2680, L"dicei"},
+	{0x2681, L"diceii"},
+	{0x2682, L"diceiii"},
+	{0x2683, L"diceiv"},
+	{0x2684, L"dicev"},
+	{0x2685, L"dicevi"},
+	{0x3dd, L"digamma"},
+	{0x273d, L"dingasterisk"},
+	{0x2393, L"dircurrent"},
+	{0x22f2, L"disin"},
+	{0xf7, L"div"},
+	{0x22c7, L"divideontimes"},
+	{0x111, L"dj"},
+	{0x230d, L"dlcrop"},
+	{0x2250, L"doteq"},
+	{0x2a67, L"dotequiv"},
+	{0x2238, L"dotminus"},
+	{0x2214, L"dotplus"},
+	{0x2026, L"dots"},
+	{0x2a6a, L"dotsim"},
+	{0x223a, L"dotsminusdots"},
+	{0x25cc, L"dottedcircle"},
+	{0x2b1a, L"dottedsquare"},
+	{0x2a30, L"dottimes"},
+	{0x2a62, L"doublebarvee"},
+	{0x2a5e, L"doublebarwedge"},
+	{0x29fa, L"doubleplus"},
+	{0x2193, L"downarrow"},
+	{0x2913, L"downarrowbar"},
+	{0x2908, L"downarrowbarred"},
+	{0x21e3, L"downdasharrow"},
+	{0x21ca, L"downdownarrows"},
+	{0x297f, L"downfishtail"},
+	{0x21c3, L"downharpoonleft"},
+	{0x2959, L"downharpoonleftbar"},
+	{0x21c2, L"downharpoonright"},
+	{0x2955, L"downharpoonrightbar"},
+	{0x2965, L"downharpoonsleftright"},
+	{0x2935, L"downrightcurvedarrow"},
+	{0x29e8, L"downtriangleleftblack"},
+	{0x29e9, L"downtrianglerightblack"},
+	{0x21f5, L"downuparrows"},
+	{0x296f, L"downupharpoonsleftright"},
+	{0x21e9, L"downwhitearrow"},
+	{0x21af, L"downzigzagarrow"},
+	{0x2033, L"dprime"},
+	{0x279b, L"draftingarrow"},
+	{0x2910, L"drbkarow"},
+	{0x230c, L"drcrop"},
+	{0x29f6, L"dsol"},
+	{0x2a64, L"dsub"},
+	{0x29df, L"dualmap"},
+	{0x2641, L"earth"},
+	{0x2a98, L"egsdot"},
+	{0x266a, L"eighthnote"},
+	{0x23e7, L"elinters"},
+	{0x2113, L"ell"},
+	{0x2a97, L"elsdot"},
+	{0x2014, L"emdash"},
+	{0x2205, L"emptyset"},
+	{0x29b3, L"emptysetoarr"},
+	{0x29b4, L"emptysetoarrl"},
+	{0x29b1, L"emptysetobar"},
+	{0x29b2, L"emptysetocirc"},
+	{0x2013, L"endash"},
+	{0x2025, L"enleadertwodots"},
+	{0x2709, L"envelope"},
+	{0x29e3, L"eparsl"},
+	{0x3f5, L"epsilon"},
+	{0x2256, L"eqcirc"},
+	{0x2255, L"eqcolon"},
+	{0x225d, L"eqdef"},
+	{0x2a66, L"eqdot"},
+	{0x2a75, L"eqeq"},
+	{0x2a76, L"eqeqeq"},
+	{0x22dd, L"eqgtr"},
+	{0x22dc, L"eqless"},
+	{0x2a9a, L"eqqgtr"},
+	{0x2a99, L"eqqless"},
+	{0x2a71, L"eqqplus"},
+	{0x2a73, L"eqqsim"},
+	{0x2a9c, L"eqqslantgtr"},
+	{0x2a9b, L"eqqslantless"},
+	{0x2242, L"eqsim"},
+	{0x2a96, L"eqslantgtr"},
+	{0x2a95, L"eqslantless"},
+	{0x2b40, L"equalleftarrow"},
+	{0x22d5, L"equalparallel"},
+	{0x2971, L"equalrightarrow"},
+	{0x2261, L"equiv"},
+	{0x2a78, L"equivDD"},
+	{0x2a68, L"equivVert"},
+	{0x2a69, L"equivVvert"},
+	{0x29e5, L"eqvparsl"},
+	{0x29f3, L"errbarblackcircle"},
+	{0x29f1, L"errbarblackdiamond"},
+	{0x29ef, L"errbarblacksquare"},
+	{0x29f2, L"errbarcircle"},
+	{0x29f0, L"errbardiamond"},
+	{0x29ee, L"errbarsquare"},
+	{0x3b7, L"eta"},
+	{0x20ac, L"euro"},
+	{0x2203, L"exists"},
+	{0x2252, L"fallingdotseq"},
+	{0x29d3, L"fbowtie"},
+	{0x2a3e, L"fcmp"},
+	{0x292f, L"fdiagovnearrow"},
+	{0x292c, L"fdiagovrdiag"},
+	{0x2640, L"female"},
+	{0x2012, L"figdash"},
+	{0x2a0f, L"fint"},
+	{0x25c9, L"fisheye"},
+	{0x266d, L"flat"},
+	{0x23e5, L"fltns"},
+	{0x2200, L"forall"},
+	{0x2adc, L"forks"},
+	{0x2add, L"forksnot"},
+	{0x2ad9, L"forkv"},
+	{0x221c, L"fourthroot"},
+	{0x2999, L"fourvdots"},
+	{0x215d, L"fracfiveeighths"},
+	{0x215a, L"fracfivesixths"},
+	{0x2158, L"fracfourfifths"},
+	{0x215b, L"fraconeeighth"},
+	{0x2155, L"fraconefifth"},
+	{0x2159, L"fraconesixth"},
+	{0x2153, L"fraconethird"},
+	{0x215e, L"fracseveneights"},
+	{0x2044, L"fracslash"},
+	{0x215c, L"fracthreeeighths"},
+	{0x2157, L"fracthreefifths"},
+	{0x2156, L"fractwofifths"},
+	{0x2154, L"fractwothirds"},
+	{0x212d, L"frakC"},
+	{0x210c, L"frakH"},
+	{0x2128, L"frakZ"},
+	{0x2322, L"frown"},
+	{0x2639, L"frownie"},
+	{0x27d7, L"fullouterjoin"},
+	{0x3b3, L"gamma"},
+	{0x2265, L"ge"},
+	{0x2265, L"geq"},
+	{0x2267, L"geqq"},
+	{0x2a7e, L"geqslant"},
+	{0x2aa9, L"gescc"},
+	{0x2a80, L"gesdot"},
+	{0x2a82, L"gesdoto"},
+	{0x2a84, L"gesdotol"},
+	{0x2a94, L"gesles"},
+	{0x2190, L"gets"},
+	{0x226b, L"gg"},
+	{0x22d9, L"ggg"},
+	{0x2af8, L"gggnest"},
+	{0x2137, L"gimel"},
+	{0x2a92, L"glE"},
+	{0x2aa5, L"gla"},
+	{0x29e6, L"gleichstark"},
+	{0x2aa4, L"glj"},
+	{0x2a8a, L"gnapprox"},
+	{0x2a88, L"gneq"},
+	{0x2269, L"gneqq"},
+	{0x22e7, L"gnsim"},
+	{0x3e, L"greater"},
+	{0x2a8e, L"gsime"},
+	{0x2a90, L"gsiml"},
+	{0x2aa7, L"gtcc"},
+	{0x2a7a, L"gtcir"},
+	{0x29a0, L"gtlpar"},
+	{0x2a7c, L"gtquest"},
+	{0x2a86, L"gtrapprox"},
+	{0x2978, L"gtrarr"},
+	{0x22d7, L"gtrdot"},
+	{0x22db, L"gtreqless"},
+	{0x2a8c, L"gtreqqless"},
+	{0x2277, L"gtrless"},
+	{0x2273, L"gtrsim"},
+	{0xab, L"guillemotleft"},
+	{0xbb, L"guillemotright"},
+	{0x2039, L"guilsinglleft"},
+	{0x203a, L"guilsinglright"},
+	{0x23af, L"harrowextender"},
+	{0x2a6f, L"hatapprox"},
+	{0x210f, L"hbar"},
+	{0x2661, L"heartsuit"},
+	{0x22b9, L"hermitmatrix"},
+	{0x2394, L"hexagon"},
+	{0x2b23, L"hexagonblack"},
+	{0x306e, L"hiraganano"},
+	{0x2924, L"hknearrow"},
+	{0x2923, L"hknwarrow"},
+	{0x2925, L"hksearow"},
+	{0x2926, L"hkswarow"},
+	{0x21a9, L"hookleftarrow"},
+	{0x21aa, L"hookrightarrow"},
+	{0x2015, L"horizbar"},
+	{0x29d6, L"hourglass"},
+	{0x2302, L"house"},
+	{0x25ad, L"hrectangle"},
+	{0x25ac, L"hrectangleblack"},
+	{0x210f, L"hslash"},
+	{0x2043, L"hyphenbullet"},
+	{0x3030, L"hzigzag"},
+	{0x2a0c, L"iiiint"},
+	{0x222d, L"iiint"},
+	{0x29dc, L"iinfin"},
+	{0x222c, L"iint"},
+	{0x22b7, L"imageof"},
+	{0x2208, L"in"},
+	{0x2105, L"incare"},
+	{0x2206, L"increment"},
+	{0x221e, L"infty"},
+	{0x222b, L"int"},
+	{0x2a0e, L"intBar"},
+	{0x2a0d, L"intbar"},
+	{0x2321, L"intbottom"},
+	{0x2a19, L"intcap"},
+	{0x2231, L"intclockwise"},
+	{0x2a1a, L"intcup"},
+	{0x22ba, L"intercal"},
+	{0x2af4, L"interleave"},
+	{0x23ae, L"intextender"},
+	{0x2a17, L"intlharhk"},
+	{0x2a3c, L"intprod"},
+	{0x2a3d, L"intprodr"},
+	{0x2320, L"inttop"},
+	{0x2a18, L"intx"},
+	{0x25d8, L"inversebullet"},
+	{0x25d9, L"inversewhitecircle"},
+	{0x2310, L"invnot"},
+	{0x25db, L"invwhitelowerhalfcircle"},
+	{0x25da, L"invwhiteupperhalfcircle"},
+	{0x3b9, L"iota"},
+	{0x2e0, L"ipasupgamma"},
+	{0x2e1, L"ipasupl"},
+	{0x2e4, L"ipasuprerglotstpp"},
+	{0x2e2, L"ipasups"},
+	{0x2e3, L"ipasupx"},
+	{0x2ed, L"ipaunaspirated"},
+	{0x2ec, L"ipavoicing"},
+	{0x22f9, L"isinE"},
+	{0x22f5, L"isindot"},
+	{0x22f7, L"isinobar"},
+	{0x22f4, L"isins"},
+	{0x22f8, L"isinvb"},
+	{0x2145, L"itBbbD"},
+	{0x2146, L"itBbbd"},
+	{0x2147, L"itBbbe"},
+	{0x2148, L"itBbbi"},
+	{0x2149, L"itBbbj"},
+	{0x2643, L"jupiter"},
+	{0x3ba, L"kappa"},
+	{0x223b, L"kernelcontraction"},
+	{0x3df, L"koppa"},
+	{0x142, L"l"},
+	{0x27ea, L"lAngle"},
+	{0x2983, L"lBrace"},
+	{0x27e6, L"lBrack"},
+	{0x2985, L"lParen"},
+	{0x3bb, L"lambda"},
+	{0x19b, L"lambdabar"},
+	{0x27e8, L"langle"},
+	{0x2991, L"langledot"},
+	{0x29e0, L"laplac"},
+	{0x2bd, L"lasp"},
+	{0x2aab, L"lat"},
+	{0x2aad, L"late"},
+	{0x27c5, L"lbag"},
+	{0x2997, L"lblkbrbrak"},
+	{0x7b, L"lbrace"},
+	{0x23a9, L"lbracelend"},
+	{0x23a8, L"lbracemid"},
+	{0x23a7, L"lbraceuend"},
+	{0x5b, L"lbrack"},
+	{0x23a2, L"lbrackextender"},
+	{0x23a3, L"lbracklend"},
+	{0x298f, L"lbracklltick"},
+	{0x298b, L"lbrackubar"},
+	{0x23a1, L"lbrackuend"},
+	{0x298d, L"lbrackultick"},
+	{0x2772, L"lbrbrak"},
+	{0x2308, L"lceil"},
+	{0x29fc, L"lcurvyangle"},
+	{0x21e0, L"ldasharrhead"},
+	{0x2264, L"le"},
+	{0x219d, L"leadsto"},
+	{0x2190, L"leftarrow"},
+	{0x2b4a, L"leftarrowapprox"},
+	{0x2b42, L"leftarrowbackapprox"},
+	{0x2b4b, L"leftarrowbsimilar"},
+	{0x2977, L"leftarrowless"},
+	{0x2b32, L"leftarrowonoplus"},
+	{0x2946, L"leftarrowplus"},
+	{0x2943, L"leftarrowshortrightarrow"},
+	{0x2973, L"leftarrowsimilar"},
+	{0x297a, L"leftarrowsubset"},
+	{0x21a2, L"leftarrowtail"},
+	{0x21fd, L"leftarrowtriangle"},
+	{0x2b3e, L"leftarrowx"},
+	{0x290c, L"leftbkarrow"},
+	{0x2b3f, L"leftcurvedarrow"},
+	{0x21e0, L"leftdasharrow"},
+	{0x21e1, L"leftdasharrowhead"},
+	{0x290e, L"leftdbkarrow"},
+	{0x291b, L"leftdbltail"},
+	{0x2b38, L"leftdotarrow"},
+	{0x2936, L"leftdowncurvedarrow"},
+	{0x297c, L"leftfishtail"},
+	{0x21bd, L"leftharpoondown"},
+	{0x295e, L"leftharpoondownbar"},
+	{0x2962, L"leftharpoonsupdown"},
+	{0x21bc, L"leftharpoonup"},
+	{0x295a, L"leftharpoonupbar"},
+	{0x296a, L"leftharpoonupdash"},
+	{0x21c7, L"leftleftarrows"},
+	{0x263e, L"leftmoon"},
+	{0x27d5, L"leftouterjoin"},
+	{0x2194, L"leftrightarrow"},
+	{0x2948, L"leftrightarrowcircle"},
+	{0x21c6, L"leftrightarrows"},
+	{0x21ff, L"leftrightarrowtriangle"},
+	{0x2950, L"leftrightharpoondowndown"},
+	{0x294b, L"leftrightharpoondownup"},
+	{0x21cb, L"leftrightharpoons"},
+	{0x2967, L"leftrightharpoonsdown"},
+	{0x2966, L"leftrightharpoonsup"},
+	{0x294a, L"leftrightharpoonupdown"},
+	{0x294e, L"leftrightharpoonupup"},
+	{0x21ad, L"leftrightsquigarrow"},
+	{0x219c, L"leftsquigarrow"},
+	{0x21dc, L"leftsquigarrow"},
+	{0x2919, L"lefttail"},
+	{0x2b31, L"leftthreearrows"},
+	{0x22cb, L"leftthreetimes"},
+	{0x21e6, L"leftwhitearrow"},
+	{0x2264, L"leq"},
+	{0x2266, L"leqq"},
+	{0x2af9, L"leqqslant"},
+	{0x2afa, L"leqqslant"},
+	{0x2a7d, L"leqslant"},
+	{0x2aa8, L"lescc"},
+	{0x2a7f, L"lesdot"},
+	{0x2a81, L"lesdoto"},
+	{0x2a83, L"lesdotor"},
+	{0x2a93, L"lesges"},
+	{0x3c, L"less"},
+	{0x2a85, L"lessapprox"},
+	{0x22d6, L"lessdot"},
+	{0x22da, L"lesseqgtr"},
+	{0x2a8b, L"lesseqqgtr"},
+	{0x2276, L"lessgtr"},
+	{0x2272, L"lesssim"},
+	{0x29d1, L"lfbowtie"},
+	{0x230a, L"lfloor"},
+	{0x29d4, L"lftimes"},
+	{0x2a91, L"lgE"},
+	{0x2b24, L"lgblkcircle"},
+	{0x2b1b, L"lgblksquare"},
+	{0x25ef, L"lgwhtcircle"},
+	{0x2b1c, L"lgwhtsquare"},
+	{0x22b2, L"lhd"},
+	{0x21b4, L"linefeed"},
+	{0x226a, L"ll"},
+	{0x2989, L"llangle"},
+	{0x25df, L"llarc"},
+	{0x25e3, L"llblacktriangle"},
+	{0x231e, L"llcorner"},
+	{0x22d8, L"lll"},
+	{0x2af7, L"lllnest"},
+	{0x2987, L"llparenthesis"},
+	{0x25fa, L"lltriangle"},
+	{0x23b0, L"lmoustache"},
+	{0x2a89, L"lnapprox"},
+	{0x2a87, L"lneq"},
+	{0x2268, L"lneqq"},
+	{0x22e6, L"lnsim"},
+	{0x27de, L"longdashv"},
+	{0x27cc, L"longdivision"},
+	{0x27f5, L"longleftarrow"},
+	{0x27f7, L"longleftrightarrow"},
+	{0x2b33, L"longleftsquigarrow"},
+	{0x27fb, L"longmapsfrom"},
+	{0x27fc, L"longmapsto"},
+	{0x27f6, L"longrightarrow"},
+	{0x27ff, L"longrightsquigarrow"},
+	{0x21ab, L"looparrowleft"},
+	{0x21ac, L"looparrowright"},
+	{0x2a1c, L"lowint"},
+	{0x25ca, L"lozenge"},
+	{0x27e0, L"lozengeminus"},
+	{0x239c, L"lparenextender"},
+	{0x239d, L"lparenlend"},
+	{0x2993, L"lparenless"},
+	{0x239b, L"lparenuend"},
+	{0x2018, L"lq"},
+	{0x25de, L"lrarc"},
+	{0x25e2, L"lrblacktriangle"},
+	{0x231f, L"lrcorner"},
+	{0x25ff, L"lrtriangle"},
+	{0x29e1, L"lrtriangleeq"},
+	{0x2a8d, L"lsime"},
+	{0x2a8f, L"lsimg"},
+	{0x2acd, L"lsqhook"},
+	{0x2aa6, L"ltcc"},
+	{0x2a79, L"ltcir"},
+	{0x22c9, L"ltimes"},
+	{0x2976, L"ltlarr"},
+	{0x2a7b, L"ltquest"},
+	{0x29cf, L"ltrivb"},
+	{0x23b8, L"lvboxline"},
+	{0x29d8, L"lvzigzag"},
+	{0x2642, L"male"},
+	{0x2720, L"maltese"},
+	{0x21a7, L"mapsdown"},
+	{0x21a4, L"mapsfrom"},
+	{0x21a6, L"mapsto"},
+	{0x21a5, L"mapsup"},
+	{0x2b25, L"mdblkdiamond"},
+	{0x2b27, L"mdblklozenge"},
+	{0x26ab, L"mdblkrcl"},
+	{0x25fc, L"mdblksquare"},
+	{0x25cf, L"mdlgblkcircle"},
+	{0x25c6, L"mdlgblkdiamond"},
+	{0x29eb, L"mdlgblklozenge"},
+	{0x25a0, L"mdlgblksquare"},
+	{0x25cb, L"mdlgwhtcircle"},
+	{0x25c7, L"mdlgwhtdiamond"},
+	{0x25a1, L"mdlgwhtsquare"},
+	{0x2981, L"mdsmblkcircle"},
+	{0x25fe, L"mdsmblksquare"},
+	{0x26ac, L"mdsmwhtcircl"},
+	{0x25fd, L"mdsmwhtsquare"},
+	{0x26aa, L"mdwhtcircl"},
+	{0x2b26, L"mdwhtdiamond"},
+	{0x2b28, L"mdwhtlozenge"},
+	{0x25fb, L"mdwhtsquare"},
+	{0x29af, L"measangledltosw"},
+	{0x29ae, L"measangledrtose"},
+	{0x29ab, L"measangleldtosw"},
+	{0x29a9, L"measanglelutonw"},
+	{0x29aa, L"measanglerdtose"},
+	{0x29a8, L"measanglerutone"},
+	{0x29ad, L"measangleultonw"},
+	{0x29ac, L"measangleurtone"},
+	{0x225e, L"measeq"},
+	{0x2221, L"measuredangle"},
+	{0x299b, L"measuredangleleft"},
+	{0x22be, L"measuredrightangle"},
+	{0x2b51, L"medblackstar"},
+	{0x205f, L"medmathspace"},
+	{0x2b50, L"medwhitestar"},
+	{0x263f, L"mercury"},
+	{0x2127, L"mho"},
+	{0x2223, L"mid"},
+	{0x2a5d, L"midbarvee"},
+	{0x2a5c, L"midbarwedge"},
+	{0x2af0, L"midcir"},
+	{0x2212, L"minus"},
+	{0x2a2a, L"minusdot"},
+	{0x2a2b, L"minusfdots"},
+	{0x2a2c, L"minusrdots"},
+	{0x2adb, L"mlcp"},
+	{0x22a7, L"models"},
+	{0x2213, L"mp"},
+	{0x3bc, L"mu"},
+	{0x22b8, L"multimap"},
+	{0x27dc, L"multimapinv"},
+	{0x21df, L"nHdownarrow"},
+	{0x21de, L"nHuparrow"},
+	{0x21cd, L"nLeftarrow"},
+	{0x21ce, L"nLeftrightarrow"},
+	{0x21cf, L"nRightarrow"},
+	{0x22af, L"nVDash"},
+	{0x22ae, L"nVdash"},
+	{0x21fa, L"nVleftarrow"},
+	{0x2b3a, L"nVleftarrowtail"},
+	{0x21fc, L"nVleftrightarrow"},
+	{0x21fb, L"nVrightarrow"},
+	{0x2915, L"nVrightarrowtail"},
+	{0x2b35, L"nVtwoheadleftarrow"},
+	{0x2b3d, L"nVtwoheadleftarrowtail"},
+	{0x2901, L"nVtwoheadrightarrow"},
+	{0x2918, L"nVtwoheadrightarrowtail"},
+	{0x2207, L"nabla"},
+	{0x2249, L"napprox"},
+	{0x226d, L"nasymp"},
+	{0x266e, L"natural"},
+	{0x2247, L"ncong"},
+	{0x2260, L"ne"},
+	{0x2197, L"nearrow"},
+	{0xac, L"neg"},
+	{0x2931, L"neovnwarrow"},
+	{0x292e, L"neovsearrow"},
+	{0x2646, L"neptune"},
+	{0x2260, L"neq"},
+	{0x2262, L"nequiv"},
+	{0x2922, L"neswarrow"},
+	{0x26b2, L"neuter"},
+	{0x2204, L"nexists"},
+	{0x14b, L"ng"},
+	{0x2271, L"ngeq"},
+	{0x226f, L"ngtr"},
+	{0x2279, L"ngtrless"},
+	{0x2275, L"ngtrsim"},
+	{0x2af5, L"nhVvert"},
+	{0x2af2, L"nhpar"},
+	{0x220b, L"ni"},
+	{0x22fe, L"niobar"},
+	{0x22fc, L"nis"},
+	{0x22fa, L"nisd"},
+	{0x219a, L"nleftarrow"},
+	{0x21ae, L"nleftrightarrow"},
+	{0x2270, L"nleq"},
+	{0x226e, L"nless"},
+	{0x2278, L"nlessgtr"},
+	{0x2274, L"nlesssim"},
+	{0x2224, L"nmid"},
+	{0x220c, L"nni"},
+	{0x2011, L"nobreakhyphen"},
+	{0x2209, L"notin"},
+	{0x2226, L"nparallel"},
+	{0x2a14, L"npolint"},
+	{0x2280, L"nprec"},
+	{0x22e0, L"npreccurlyeq"},
+	{0x219b, L"nrightarrow"},
+	{0x2241, L"nsim"},
+	{0x2244, L"nsime"},
+	{0x22e2, L"nsqsubseteq"},
+	{0x22e3, L"nsqsupseteq"},
+	{0x2284, L"nsubset"},
+	{0x2288, L"nsubseteq"},
+	{0x2281, L"nsucc"},
+	{0x22e1, L"nsucccurlyeq"},
+	{0x2285, L"nsupset"},
+	{0x2289, L"nsupseteq"},
+	{0x22ea, L"ntriangleleft"},
+	{0x22ec, L"ntrianglelefteq"},
+	{0x22eb, L"ntriangleright"},
+	{0x22ed, L"ntrianglerighteq"},
+	{0x3bd, L"nu"},
+	{0x22ad, L"nvDash"},
+	{0x2902, L"nvLeftarrow"},
+	{0x2904, L"nvLeftrightarrow"},
+	{0x2903, L"nvRightarrow"},
+	{0x22ac, L"nvdash"},
+	{0x29de, L"nvinfty"},
+	{0x21f7, L"nvleftarrow"},
+	{0x2b39, L"nvleftarrowtail"},
+	{0x21f9, L"nvleftrightarrow"},
+	{0x21f8, L"nvrightarrow"},
+	{0x2914, L"nvrightarrowtail"},
+	{0x2b34, L"nvtwoheadleftarrow"},
+	{0x2b3c, L"nvtwoheadleftarrowtail"},
+	{0x2900, L"nvtwoheadrightarrow"},
+	{0x2917, L"nvtwoheadrightarrowtail"},
+	{0x2196, L"nwarrow"},
+	{0x2932, L"nwovnearrow"},
+	{0x2921, L"nwsearrow"},
+	{0xf8, L"o"},
+	{0x233d, L"obar"},
+	{0x29ba, L"obot"},
+	{0x23e0, L"obrbrak"},
+	{0x29b8, L"obslash"},
+	{0x2a38, L"odiv"},
+	{0x2299, L"odot"},
+	{0x29bc, L"odotslashdot"},
+	{0x153, L"oe"},
+	{0x29c1, L"ogreaterthan"},
+	{0x1a1, L"ohorn"},
+	{0x2230, L"oiiint"},
+	{0x222f, L"oiint"},
+	{0x222e, L"oint"},
+	{0x2233, L"ointctrclockwise"},
+	{0x29bb, L"olcross"},
+	{0x3d8, L"oldKoppa"},
+	{0x3d9, L"oldkoppa"},
+	{0x29c0, L"olessthan"},
+	{0x3c9, L"omega"},
+	{0x3bf, L"omicron"},
+	{0x2296, L"ominus"},
+	{0x29b9, L"operp"},
+	{0x2295, L"oplus"},
+	{0x2a2d, L"opluslhrim"},
+	{0x2a2e, L"oplusrhrim"},
+	{0x22b6, L"origof"},
+	{0x2298, L"oslash"},
+	{0x2297, L"otimes"},
+	{0x2a36, L"otimeshat"},
+	{0x2a34, L"otimeslhrim"},
+	{0x2a35, L"otimesrhrim"},
+	{0x23de, L"overbrace"},
+	{0x23b4, L"overbracket"},
+	{0x203e, L"overline"},
+	{0x23dc, L"overparen"},
+	{0x220b, L"owns"},
+	{0x2225, L"parallel"},
+	{0x25b1, L"parallelogram"},
+	{0x25b0, L"parallelogramblack"},
+	{0x2af3, L"parsim"},
+	{0x2202, L"partial"},
+	{0x2aa3, L"partialmeetcontraction"},
+	{0x2b20, L"pentagon"},
+	{0x2b1f, L"pentagonblack"},
+	{0x27c2, L"perp"},
+	{0x2ae1, L"perps"},
+	{0x3d5, L"phi"},
+	{0x260e, L"phone"},
+	{0x3c0, L"pi"},
+	{0x22d4, L"pitchfork"},
+	{0x2a25, L"plusdot"},
+	{0x2a72, L"pluseqq"},
+	{0x2a23, L"plushat"},
+	{0x2a26, L"plussim"},
+	{0x2a27, L"plussubtwo"},
+	{0x2a28, L"plustrif"},
+	{0x2647, L"pluto"},
+	{0xb1, L"pm"},
+	{0x2a15, L"pointnt"},
+	{0x3012, L"postalmark"},
+	{0x227a, L"prec"},
+	{0x2ab7, L"precapprox"},
+	{0x227c, L"preccurlyeq"},
+	{0x2aaf, L"preceq"},
+	{0x2ab3, L"preceqq"},
+	{0x2ab9, L"precnapprox"},
+	{0x2ab1, L"precneq"},
+	{0x2ab5, L"precneqq"},
+	{0x22e8, L"precnsim"},
+	{0x227e, L"precsim"},
+	{0x2032, L"prime"},
+	{0x220f, L"prod"},
+	{0x232e, L"profalar"},
+	{0x2312, L"profline"},
+	{0x2313, L"profsurf"},
+	{0x221d, L"propto"},
+	{0x22b0, L"prurel"},
+	{0x3c8, L"psi"},
+	{0x27d3, L"pullback"},
+	{0x27d4, L"pushout"},
+	{0x2057, L"qprime"},
+	{0x2669, L"quarternote"},
+	{0x225f, L"questeq"},
+	{0x201e, L"quotdblbase"},
+	{0x201f, L"quotdblright"},
+	{0x27, L"quote"},
+	{0x201a, L"quotsinglbase"},
+	{0x201b, L"quotsinglright"},
+	{0x27eb, L"rAngle"},
+	{0x2984, L"rBrace"},
+	{0x27e7, L"rBrack"},
+	{0x2986, L"rParen"},
+	{0x27e9, L"rangle"},
+	{0x2992, L"rangledot"},
+	{0x237c, L"rangledownzigzagarrow"},
+	{0x2bc, L"rasp"},
+	{0x27c6, L"rbag"},
+	{0x2998, L"rblkbrbrak"},
+	{0x7d, L"rbrace"},
+	{0x23ad, L"rbracelend"},
+	{0x23ac, L"rbracemid"},
+	{0x23ab, L"rbraceuend"},
+	{0x5d, L"rbrack"},
+	{0x23a5, L"rbrackextender"},
+	{0x23a6, L"rbracklend"},
+	{0x298e, L"rbracklrtick"},
+	{0x298c, L"rbrackubar"},
+	{0x23a4, L"rbrackuend"},
+	{0x2990, L"rbrackurtick"},
+	{0x2773, L"rbrbrak"},
+	{0x2309, L"rceil"},
+	{0x29fd, L"rcurvyangle"},
+	{0x292b, L"rdiagovfdiag"},
+	{0x2930, L"rdiagovsearrow"},
+	{0x2315, L"recorder"},
+	{0x29a3, L"revangle"},
+	{0x29a5, L"revangleubar"},
+	{0x29b0, L"revemptyset"},
+	{0x2aee, L"revnmid"},
+	{0x29d2, L"rfbowtie"},
+	{0x230b, L"rfloor"},
+	{0x29d5, L"rftimes"},
+	{0x22b3, L"rhd"},
+	{0x3c1, L"rho"},
+	{0x2b4c, L"righarrowbsimilar"},
+	{0x221f, L"rightangle"},
+	{0x299d, L"rightanglemdot"},
+	{0x299c, L"rightanglesqr"},
+	{0x2192, L"rightarrow"},
+	{0x2975, L"rightarrowapprox"},
+	{0x2b48, L"rightarrowbackapprox"},
+	{0x21e5, L"rightarrowbar"},
+	{0x291e, L"rightarrowdiamond"},
+	{0x2b43, L"rightarrowgtr"},
+	{0x27f4, L"rightarrowonoplus"},
+	{0x2945, L"rightarrowplus"},
+	{0x2942, L"rightarrowshortleftarrow"},
+	{0x2974, L"rightarrowsimilar"},
+	{0x2b44, L"rightarrowsupset"},
+	{0x21a3, L"rightarrowtail"},
+	{0x21fe, L"rightarrowtriangle"},
+	{0x2947, L"rightarrowx"},
+	{0x290d, L"rightbkarrow"},
+	{0x2933, L"rightcurvedarrow"},
+	{0x21e2, L"rightdasharrow"},
+	{0x291c, L"rightdbltail"},
+	{0x2911, L"rightdotarrow"},
+	{0x2937, L"rightdowncurvedarrow"},
+	{0x297d, L"rightfishtail"},
+	{0x21c1, L"rightharpoondown"},
+	{0x2957, L"rightharpoondownbar"},
+	{0x2964, L"rightharpoonsupdown"},
+	{0x21c0, L"rightharpoonup"},
+	{0x2953, L"rightharpoonupbar"},
+	{0x296c, L"rightharpoonupdash"},
+	{0x2970, L"rightimply"},
+	{0x21c4, L"rightleftarrows"},
+	{0x21cc, L"rightleftharpoons"},
+	{0x2969, L"rightleftharpoonsdown"},
+	{0x2968, L"rightleftharpoonsup"},
+	{0x263d, L"rightmoon"},
+	{0x27d6, L"rightouterjoin"},
+	{0x2b54, L"rightpentagon"},
+	{0x2b53, L"rightpentagonblack"},
+	{0x21c9, L"rightrightarrows"},
+	{0x219d, L"rightsquigarrow"},
+	{0x21dd, L"rightsquigarrow"},
+	{0x291a, L"righttail"},
+	{0x21f6, L"rightthreearrows"},
+	{0x22cc, L"rightthreetimes"},
+	{0x21e8, L"rightwhitearrow"},
+	{0x2a22, L"ringplus"},
+	{0x2253, L"risingdotseq"},
+	{0x23b1, L"rmoustache"},
+	{0x239f, L"rparenextender"},
+	{0x2994, L"rparengtr"},
+	{0x23a0, L"rparenlend"},
+	{0x239e, L"rparenuend"},
+	{0x2a12, L"rppolint"},
+	{0x2019, L"rq"},
+	{0x298a, L"rrangle"},
+	{0x2988, L"rrparenthesis"},
+	{0x29f7, L"rsolbar"},
+	{0x2ace, L"rsqhook"},
+	{0x2a65, L"rsub"},
+	{0x22ca, L"rtimes"},
+	{0x29ce, L"rtriltri"},
+	{0x29f4, L"ruledelayed"},
+	{0x23b9, L"rvboxline"},
+	{0x29d9, L"rvzigzag"},
+	{0x3e1, L"sampi"},
+	{0x2143, L"sansLmirrored"},
+	{0x2142, L"sansLturned"},
+	{0x2644, L"saturn"},
+	{0x2702, L"scissors"},
+	{0x2a13, L"scpolint"},
+	{0x212c, L"scrB"},
+	{0x2130, L"scrE"},
+	{0x2131, L"scrF"},
+	{0x210b, L"scrH"},
+	{0x2110, L"scrI"},
+	{0x2112, L"scrL"},
+	{0x2133, L"scrM"},
+	{0x211b, L"scrR"},
+	{0x212f, L"scre"},
+	{0x210a, L"scrg"},
+	{0x2134, L"scro"},
+	{0x22b1, L"scurel"},
+	{0x2198, L"searrow"},
+	{0x292d, L"seovnearrow"},
+	{0x2216, L"setminus"},
+	{0x29f5, L"setminus"},
+	{0x266f, L"sharp"},
+	{0x2adf, L"shortdowntack"},
+	{0x2190, L"shortleftarrow"},
+	{0x2ade, L"shortlefttack"},
+	{0x2192, L"shortrightarrow"},
+	{0x2944, L"shortrightarrowleftarrow"},
+	{0x2ae0, L"shortuptack"},
+	{0x29e2, L"shuffle"},
+	{0x3c3, L"sigma"},
+	{0x3c5, L"silon"},
+	{0x3d2, L"silon"},
+	{0x223c, L"sim"},
+	{0x2243, L"simeq"},
+	{0x2aa0, L"simgE"},
+	{0x2a9e, L"simgtr"},
+	{0x2b49, L"similarleftarrow"},
+	{0x2972, L"similarrightarrow"},
+	{0x2a9f, L"simlE"},
+	{0x2a9d, L"simless"},
+	{0x2a6c, L"simminussim"},
+	{0x2246, L"simneqq"},
+	{0x2a24, L"simplus"},
+	{0x2a6b, L"simrdots"},
+	{0x223f, L"sinewave"},
+	{0x2215, L"slash"},
+	{0x25c2, L"smallblacktriangleleft"},
+	{0x25b8, L"smallblacktriangleright"},
+	{0x22c4, L"smalldiamond"},
+	{0x220a, L"smallin"},
+	{0x222b, L"smallint"},
+	{0x220d, L"smallni"},
+	{0x2216, L"smallsetminus"},
+	{0x25c3, L"smalltriangleleft"},
+	{0x25b9, L"smalltriangleright"},
+	{0x2a33, L"smashtimes"},
+	{0x2b29, L"smblkdiamond"},
+	{0x2b2a, L"smblklozenge"},
+	{0x25aa, L"smblksquare"},
+	{0x29e4, L"smeparsl"},
+	{0x2323, L"smile"},
+	{0x263a, L"smiley"},
+	{0x2aaa, L"smt"},
+	{0x2aac, L"smte"},
+	{0x2b52, L"smwhitestar"},
+	{0x25e6, L"smwhtcircle"},
+	{0x2b2b, L"smwhtlozenge"},
+	{0x25ab, L"smwhtsquare"},
+	{0x2660, L"spadesuit"},
+	{0x2222, L"sphericalangle"},
+	{0x29a1, L"sphericalangleup"},
+	{0x2293, L"sqcap"},
+	{0x2294, L"sqcup"},
+	{0x2a16, L"sqint"},
+	{0x2311, L"sqlozenge"},
+	{0x800221a, L"sqrt"},
+	{0x800221b, L"sqrt3"},
+	{0x800221c, L"sqrt4"},
+	{0x23b7, L"sqrtbottom"},
+	{0x228f, L"sqsubset"},
+	{0x2291, L"sqsubseteq"},
+	{0x22e4, L"sqsubsetneq"},
+	{0x2290, L"sqsupset"},
+	{0x2292, L"sqsupseteq"},
+	{0x22e5, L"sqsupsetneq"},
+	{0x25a9, L"squarecrossfill"},
+	{0x25a9, L"squaregrayfill"},
+	{0x25a4, L"squarehfill"},
+	{0x25a6, L"squarehvfill"},
+	{0x25e7, L"squareleftblack"},
+	{0x25e8, L"squareleftblack"},
+	{0x2b15, L"squarellblack"},
+	{0x25f1, L"squarellquad"},
+	{0x25ea, L"squarelrblack"},
+	{0x25f2, L"squarelrquad"},
+	{0x25a8, L"squareneswfill"},
+	{0x25a7, L"squarenwsefill"},
+	{0x25e9, L"squareulblack"},
+	{0x25f0, L"squareulquad"},
+	{0x2b14, L"squareurblack"},
+	{0x25f3, L"squareurquad"},
+	{0x25a5, L"squarevfill"},
+	{0x25a2, L"squoval"},
+	{0xdf, L"ss"},
+	{0x22c6, L"star"},
+	{0x225b, L"stareq"},
+	{0xa3, L"sterling"},
+	{0x3db, L"stigma"},
+	{0x23e4, L"strns"},
+	{0x2ac3, L"subedot"},
+	{0x2ac1, L"submult"},
+	{0x2979, L"subrarr"},
+	{0x2282, L"subset"},
+	{0x2ac9, L"subsetapprox"},
+	{0x27c3, L"subsetcirc"},
+	{0x2abd, L"subsetdot"},
+	{0x2286, L"subseteq"},
+	{0x2ac5, L"subseteqq"},
+	{0x228a, L"subsetneq"},
+	{0x2acb, L"subsetneqq"},
+	{0x2abf, L"subsetplus"},
+	{0x2ac7, L"subsim"},
+	{0x2ad5, L"subsub"},
+	{0x2ad3, L"subsup"},
+	{0x227b, L"succ"},
+	{0x2ab8, L"succapprox"},
+	{0x227d, L"succcurlyeq"},
+	{0x2ab0, L"succeq"},
+	{0x2ab4, L"succeqq"},
+	{0x2aba, L"succnapprox"},
+	{0x2ab2, L"succneq"},
+	{0x2ab6, L"succneqq"},
+	{0x22e9, L"succnsim"},
+	{0x227f, L"succsim"},
+	{0x2211, L"sum"},
+	{0x23b3, L"sumbottom"},
+	{0x2a0b, L"sumint"},
+	{0x23b2, L"sumtop"},
+	{0x263c, L"sun"},
+	{0x2ad8, L"supdsub"},
+	{0x2ac4, L"supedot"},
+	{0x27c9, L"suphsol"},
+	{0x2ad7, L"suphsub"},
+	{0x297b, L"suplarr"},
+	{0x2ac2, L"supmult"},
+	{0x207f, L"supn"},
+	{0x2283, L"supset"},
+	{0x2aca, L"supsetapprox"},
+	{0x27c4, L"supsetcirc"},
+	{0x2abe, L"supsetdot"},
+	{0x2287, L"supseteq"},
+	{0x2ac6, L"supseteqq"},
+	{0x228b, L"supsetneq"},
+	{0x2acc, L"supsetneqq"},
+	{0x2ac0, L"supsetplus"},
+	{0x2ac8, L"supsim"},
+	{0x2ad4, L"supsub"},
+	{0x2ad6, L"supsup"},
+	{0x221a, L"surd"},
+	{0x2199, L"swarrow"},
+	{0x2afe, L"talloblong"},
+	{0x2316, L"target"},
+	{0x3c4, L"tau"},
+	{0x2649, L"taurus"},
+	{0x1d8d, L"testhookx"},
+	{0x2051, L"textAsterisks"},
+	{0x2ca, L"textacute"},
+	{0x2d6, L"textadvanced"},
+	{0x2bf, L"textain"},
+	{0xb4, L"textasciiacute"},
+	{0x5e, L"textasciicircum"},
+	{0xa8, L"textasciidieresis"},
+	{0x60, L"textasciigrave"},
+	{0xaf, L"textasciimacron"},
+	{0x7e, L"textasciitilde"},
+	{0x204e, L"textasterisklow"},
+	{0x2036, L"textbackdprime"},
+	{0x2035, L"textbackprime"},
+	{0x2037, L"textbacktrprime"},
+	{0x25f, L"textbardotlessj"},
+	{0x284, L"textbardotlessjvar"},
+	{0x2a1, L"textbarglotstop"},
+	{0x268, L"textbari"},
+	{0x19a, L"textbarl"},
+	{0x275, L"textbaro"},
+	{0x2a2, L"textbarrevglotstop"},
+	{0x289, L"textbaru"},
+	{0x26c, L"textbeltl"},
+	{0x1ba, L"textbenttailyogh"},
+	{0x2d8, L"textbreve"},
+	{0xa6, L"textbrokenbar"},
+	{0x2022, L"textbullet"},
+	{0x298, L"textbullseye"},
+	{0xa2, L"textcent"},
+	{0x2117, L"textcircledP"},
+	{0x29a, L"textcloseepsilon"},
+	{0x277, L"textcloseomega"},
+	{0x25e, L"textcloserevepsilon"},
+	{0xa9, L"textcopyright"},
+	{0x180, L"textcrb"},
+	{0x127, L"textcrh"},
+	{0x1be, L"textcrinvglotstop"},
+	{0x19b, L"textcrlambda"},
+	{0x1bb, L"textcrtwo"},
+	{0x255, L"textctc"},
+	{0x221, L"textctd"},
+	{0x286, L"textctesh"},
+	{0x29d, L"textctj"},
+	{0x234, L"textctl"},
+	{0x235, L"textctn"},
+	{0x236, L"textctt"},
+	{0x293, L"textctyogh"},
+	{0x291, L"textctz"},
+	{0xa4, L"textcurrency"},
+	{0x2a5, L"textdctzlig"},
+	{0xb0, L"textdegree"},
+	{0x2052, L"textdiscount"},
+	{0x24, L"textdollar"},
+	{0x2d9, L"textdotaccent"},
+	{0x237, L"textdotlessj"},
+	{0x2dd, L"textdoubleacute"},
+	{0x1c2, L"textdoublebarpipe"},
+	{0x1c1, L"textdoublepipe"},
+	{0x2033, L"textdprime"},
+	{0x2c5, L"textdptr"},
+	{0x2a4, L"textdyoghlig"},
+	{0x2a3, L"textdzlig"},
+	{0x25b, L"textepsilon"},
+	{0x283, L"textesh"},
+	{0x212e, L"textestimated"},
+	{0x1c3, L"textexclam"},
+	{0xa1, L"textexclamdown"},
+	{0x27e, L"textfishhookr"},
+	{0x192, L"textflorin"},
+	{0x20a3, L"textfranc"},
+	{0x263, L"textgamma"},
+	{0x294, L"textglotstop"},
+	{0x2cb, L"textgrave"},
+	{0x2d1, L"texthalflength"},
+	{0x2be, L"texthamza"},
+	{0xa727, L"texthen"},
+	{0xa727, L"textheng"},
+	{0x1d8a, L"texthooks"},
+	{0x1d8e, L"texthookz"},
+	{0x253, L"texthtb"},
+	{0x188, L"texthtc"},
+	{0x257, L"texthtd"},
+	{0x260, L"texthtg"},
+	{0x266, L"texthth"},
+	{0x267, L"texththeng"},
+	{0x199, L"texthtk"},
+	{0x1a5, L"texthtp"},
+	{0x2a0, L"texthtq"},
+	{0x29b, L"texthtscg"},
+	{0x1ad, L"texthtt"},
+	{0x195, L"texthvlig"},
+	{0x2010, L"texthyphen"},
+	{0x296, L"textinvglotstop"},
+	{0x281, L"textinvscr"},
+	{0x269, L"textiota"},
+	{0x2d0, L"textlengthmark"},
+	{0x2d3, L"textlhalfring"},
+	{0x1d81, L"textlhookd"},
+	{0x1d84, L"textlhookk"},
+	{0x1d85, L"textlhookl"},
+	{0x1ab, L"textlhookt"},
+	{0x27f, L"textlhti"},
+	{0x20a4, L"textlira"},
+	{0x27c, L"textlonglegr"},
+	{0x2ae, L"textlongy"},
+	{0x2af, L"textlongy"},
+	{0x1aa, L"textlooptoprevesh"},
+	{0x2cf, L"textlowacute"},
+	{0x2d5, L"textlowered"},
+	{0x2ce, L"textlowgrave"},
+	{0x2cd, L"textlowmacron"},
+	{0x2c2, L"textlptr"},
+	{0x271, L"textltailm"},
+	{0x272, L"textltailn"},
+	{0x26b, L"textltilde"},
+	{0x26e, L"textlyoghlig"},
+	{0x2c9, L"textmacron"},
+	{0xb5, L"textmu"},
+	{0x2116, L"textnumero"},
+	{0x2db, L"textogonek"},
+	{0x2126, L"textohm"},
+	{0xbd, L"textonehalf"},
+	{0xbc, L"textonequarter"},
+	{0xb9, L"textonesuperior"},
+	{0x254, L"textopeno"},
+	{0xaa, L"textordfeminine"},
+	{0xba, L"textordmasculine"},
+	{0x2df, L"textovercross"},
+	{0x2125, L"textoz"},
+	{0x2031, L"textpertenthousand"},
+	{0x2030, L"textperthousand"},
+	{0x20a7, L"textpesetas"},
+	{0x278, L"textphi"},
+	{0x1c0, L"textpipe"},
+	{0x2032, L"textprime"},
+	{0x2c8, L"textprimstress"},
+	{0x2057, L"textqprime"},
+	{0xbf, L"textquestiondown"},
+	{0x22, L"textquotedbl"},
+	{0x201c, L"textquotedblleft"},
+	{0x201d, L"textquotedblright"},
+	{0x2d4, L"textraised"},
+	{0x2c0, L"textraiseglotstop"},
+	{0x2c1, L"textraiserevglotstop"},
+	{0x264, L"textramshorns"},
+	{0x211e, L"textrecipe"},
+	{0x203b, L"textreferencemark"},
+	{0xae, L"textregistered"},
+	{0x2d7, L"textretracted"},
+	{0x258, L"textreve"},
+	{0x25c, L"textrevepsilon"},
+	{0x295, L"textrevglotstop"},
+	{0x2d2, L"textrhalfring"},
+	{0x25d, L"textrhookrevepsilon"},
+	{0x25a, L"textrhookschwa"},
+	{0x2de, L"textrhoticity"},
+	{0x2da, L"textringaccent"},
+	{0x2c3, L"textrptr"},
+	{0x256, L"textrtaild"},
+	{0x26d, L"textrtaill"},
+	{0x273, L"textrtailn"},
+	{0x27d, L"textrtailr"},
+	{0x282, L"textrtails"},
+	{0x288, L"textrtailt"},
+	{0x290, L"textrtailz"},
+	{0x1d00, L"textsca"},
+	{0x299, L"textscb"},
+	{0x1d07, L"textsce"},
+	{0x262, L"textscg"},
+	{0x29c, L"textsch"},
+	{0x259, L"textschwa"},
+	{0x26a, L"textsci"},
+	{0x29f, L"textscl"},
+	{0x274, L"textscn"},
+	{0x276, L"textscoelig"},
+	{0x280, L"textscr"},
+	{0x251, L"textscripta"},
+	{0x261, L"textscriptg"},
+	{0x28b, L"textscriptv"},
+	{0x1d1c, L"textscu"},
+	{0x28f, L"textscy"},
+	{0x2cc, L"textsecstress"},
+	{0x204f, L"textsemicolonreversed"},
+	{0x3a5, L"textsilon"},
+	{0x2dc, L"textsmalltilde"},
+	{0x297, L"textstretchcvar"},
+	{0x77, L"textsubw"},
+	{0x2b0, L"textsuph"},
+	{0x2b1, L"textsuphth"},
+	{0x2b6, L"textsupinvscr"},
+	{0x2b2, L"textsupj"},
+	{0x2b3, L"textsupr"},
+	{0x2b4, L"textsupturnr"},
+	{0x2b5, L"textsupturnrrtail"},
+	{0x2b7, L"textsupw"},
+	{0x2b8, L"textsupy"},
+	{0x2a7, L"texttctctlig"},
+	{0x2a8, L"texttctctlig"},
+	{0xbe, L"textthreequarters"},
+	{0xb3, L"textthreesuperior"},
+	{0x2122, L"texttrademark"},
+	{0x2034, L"texttrprime"},
+	{0x2a6, L"texttslig"},
+	{0x250, L"textturna"},
+	{0x2bb, L"textturncomma"},
+	{0x265, L"textturnh"},
+	{0x29e, L"textturnk"},
+	{0x27a, L"textturnlonglegr"},
+	{0x26f, L"textturnm"},
+	{0x270, L"textturnmrleg"},
+	{0x279, L"textturnr"},
+	{0x27b, L"textturnrrtail"},
+	{0x252, L"textturnscripta"},
+	{0x287, L"textturnt"},
+	{0x28c, L"textturnv"},
+	{0x28d, L"textturnw"},
+	{0x28e, L"textturny"},
+	{0xb2, L"texttwosuperior"},
+	{0x28a, L"textupsilon"},
+	{0x2c4, L"textuptr"},
+	{0x285, L"textvibyi"},
+	{0x2423, L"textvisiblespace"},
+	{0x292, L"textyogh"},
+	{0xfe, L"th"},
+	{0x2234, L"therefore"},
+	{0x29e7, L"thermod"},
+	{0x3b8, L"theta"},
+	{0x2248, L"thickapprox"},
+	{0x223c, L"thicksim"},
+	{0x27c0, L"threedangle"},
+	{0x2af6, L"threedotcolon"},
+	{0x2040, L"tieconcat"},
+	{0x29dd, L"tieinfty"},
+	{0xd7, L"times"},
+	{0x2a31, L"timesbar"},
+	{0x29ff, L"tminus"},
+	{0x2192, L"to"},
+	{0x2928, L"toea"},
+	{0x2927, L"tona"},
+	{0x2e5, L"tonebarextrahigh"},
+	{0x2e9, L"tonebarextralow"},
+	{0x2e6, L"tonebarhigh"},
+	{0x2e8, L"tonebarlow"},
+	{0x2e7, L"tonebarmid"},
+	{0x22a4, L"top"},
+	{0x2336, L"topbot"},
+	{0x2af1, L"topcir"},
+	{0x2ada, L"topfork"},
+	{0x25e0, L"topsemicircle"},
+	{0x2929, L"tosa"},
+	{0x292a, L"towa"},
+	{0x29fe, L"tplus"},
+	{0x23e2, L"trapezium"},
+	{0x25ec, L"trianglecdot"},
+	{0x25bf, L"triangledown"},
+	{0x26a0, L"triangleexclam"},
+	{0x25c1, L"triangleleft"},
+	{0x25ed, L"triangleleftblack"},
+	{0x22b4, L"trianglelefteq"},
+	{0x2a3a, L"triangleminus"},
+	{0x29ca, L"triangleodot"},
+	{0x2a39, L"triangleplus"},
+	{0x225c, L"triangleq"},
+	{0x25b7, L"triangleright"},
+	{0x25ee, L"trianglerightblack"},
+	{0x22b5, L"trianglerighteq"},
+	{0x29cc, L"triangles"},
+	{0x29cd, L"triangleserifs"},
+	{0x2a3b, L"triangletimes"},
+	{0x29cb, L"triangleubar"},
+	{0x29fb, L"tripleplus"},
+	{0x2034, L"trprime"},
+	{0x29a2, L"turnangle"},
+	{0x2129, L"turnediota"},
+	{0x2319, L"turnednot"},
+	{0x2a4b, L"twocaps"},
+	{0x2a4a, L"twocups"},
+	{0x21a1, L"twoheaddownarrow"},
+	{0x219e, L"twoheadleftarrow"},
+	{0x2b3b, L"twoheadleftarrowtail"},
+	{0x2b37, L"twoheadleftdbkarrow"},
+	{0x2b36, L"twoheadmapsfrom"},
+	{0x2905, L"twoheadmapsto"},
+	{0x21a0, L"twoheadrightarrow"},
+	{0x2916, L"twoheadrightarrowtail"},
+	{0x219f, L"twoheaduparrow"},
+	{0x2949, L"twoheaduparrowcircle"},
+	{0x2017, L"twolowline"},
+	{0x266b, L"twonotes"},
+	{0x2982, L"typecolon"},
+	{0x23e1, L"ubrbrak"},
+	{0x1b0, L"uhorn"},
+	{0x25dc, L"ularc"},
+	{0x25e4, L"ulblacktriangle"},
+	{0x231c, L"ulcorner"},
+	{0x230f, L"ulcrop"},
+	{0x25f8, L"ultriangle"},
+	{0x2a41, L"uminus"},
+	{0x23df, L"underbrace"},
+	{0x23b5, L"underbracket"},
+	{0x23dd, L"underparen"},
+	{0x22b4, L"unlhd"},
+	{0x22b5, L"unrhd"},
+	{0x214b, L"upand"},
+	{0x2191, L"uparrow"},
+	{0x2909, L"uparrowbarred"},
+	{0x29bd, L"uparrowoncircle"},
+	{0x21e2, L"updasharrow"},
+	{0x2195, L"updownarrow"},
+	{0x21a8, L"updownarrowbar"},
+	{0x21c5, L"updownarrows"},
+	{0x2951, L"updownharpoonleftleft"},
+	{0x294d, L"updownharpoonleftright"},
+	{0x294c, L"updownharpoonrightleft"},
+	{0x294f, L"updownharpoonrightright"},
+	{0x296e, L"updownharpoonsleftright"},
+	{0x297e, L"upfishtail"},
+	{0x21bf, L"upharpoonleft"},
+	{0x2960, L"upharpoonleftbar"},
+	{0x21be, L"upharpoonright"},
+	{0x295c, L"upharpoonrightbar"},
+	{0x2963, L"upharpoonsleftright"},
+	{0x27d2, L"upin"},
+	{0x2a1b, L"upint"},
+	{0x228e, L"uplus"},
+	{0x2934, L"uprightcurvearrow"},
+	{0x2127, L"upsilon"},
+	{0x21c8, L"upuparrows"},
+	{0x21e7, L"upwhitearrow"},
+	{0x25dd, L"urarc"},
+	{0x25e5, L"urblacktriangle"},
+	{0x231d, L"urcorner"},
+	{0x230e, L"urcrop"},
+	{0x25f9, L"urtriangle"},
+	{0x2c7, L"v"},
+	{0x2ae8, L"vBar"},
+	{0x2ae9, L"vBarv"},
+	{0x22a8, L"vDash"},
+	{0x2ae2, L"vDdash"},
+	{0x3f4, L"varTheta"},
+	{0x2ae6, L"varVdash"},
+	{0x2305, L"varbarwedge"},
+	{0x3d0, L"varbeta"},
+	{0x2667, L"varclubsuit"},
+	{0x2666, L"vardiamondsuit"},
+	{0x2306, L"vardoublebarwedge"},
+	{0x3b5, L"varepsilon"},
+	{0x2665, L"varheartsuit"},
+	{0x2b21, L"varhexagon"},
+	{0x2b22, L"varhexagonblack"},
+	{0x232c, L"varhexagonlrbonds"},
+	{0x2208, L"varin"},
+	{0x22f6, L"varisinobar"},
+	{0x22f3, L"varisins"},
+	{0x3f0, L"varkappa"},
+	{0x22bf, L"varlrtriangle"},
+	{0x220b, L"varni"},
+	{0x22fd, L"varniobar"},
+	{0x22fb, L"varnis"},
+	{0x2205, L"varnothing"},
+	{0x2232, L"varointclockwise"},
+	{0x3c6, L"varphi"},
+	{0x3d6, L"varpi"},
+	{0x221d, L"varpropto"},
+	{0x3f1, L"varrho"},
+	{0x23d0, L"varrowextender"},
+	{0x3c2, L"varsigma"},
+	{0x2664, L"varspadesuit"},
+	{0x2736, L"varstar"},
+	{0x3d1, L"vartheta"},
+	{0x25b5, L"vartriangle"},
+	{0x22b2, L"vartriangleleft"},
+	{0x22b3, L"vartriangleright"},
+	{0x2a61, L"varveebar"},
+	{0x23aa, L"vbraceextender"},
+	{0x29d0, L"vbrtri"},
+	{0x22a2, L"vdash"},
+	{0x22ee, L"vdots"},
+	{0x2a2f, L"vectimes"},
+	{0x2228, L"vee"},
+	{0x22bb, L"veebar"},
+	{0x27c7, L"veedot"},
+	{0x2a63, L"veedoublebar"},
+	{0x225a, L"veeeq"},
+	{0x2a5b, L"veemidvert"},
+	{0x2a52, L"veeodot"},
+	{0x2a56, L"veeonvee"},
+	{0x2a59, L"veeonwedge"},
+	{0x7c, L"vert"},
+	{0x2317, L"viewdata"},
+	{0x27dd, L"vlongdash"},
+	{0x25af, L"vrectangle"},
+	{0x25ae, L"vrectangleblack"},
+	{0x2b1d, L"vysmlblksquare"},
+	{0x2b1e, L"vysmlwhtsquare"},
+	{0x299a, L"vzigzag"},
+	{0x231a, L"watchicon"},
+	{0x2227, L"wedge"},
+	{0x2a5f, L"wedgebar"},
+	{0x27d1, L"wedgedot"},
+	{0x2a60, L"wedgedoublebar"},
+	{0x2a5a, L"wedgemidvert"},
+	{0x2a51, L"wedgeodot"},
+	{0x2a55, L"wedgeonwedge"},
+	{0x2259, L"wedgeq"},
+	{0x21ea, L"whitearrowupfrombar"},
+	{0x27c1, L"whiteinwhitetriangle"},
+	{0x25c5, L"whitepointerleft"},
+	{0x25bb, L"whitepointerright"},
+	{0x27e4, L"whitesquaretickleft"},
+	{0x27e5, L"whitesquaretickright"},
+	{0x2b2d, L"whthorzoval"},
+	{0x2b2f, L"whtvertoval"},
+	{0x29a6, L"wideangledown"},
+	{0x29a7, L"wideangleup"},
+	{0x2118, L"wp"},
+	{0x2240, L"wr"},
+	{0x29f9, L"xbsol"},
+	{0x3be, L"xi"},
+	{0x29f8, L"xsol"},
+	{0xa5, L"yen"},
+	{0x3b6, L"zeta"},
+	{0x2a20, L"zpipe"},
+{0, L""}};
+//-----------------------------------------------------------------------------
diff --git a/src/vect.cpp b/src/vect.cpp
new file mode 100644
index 0000000..253e140
--- /dev/null
+++ b/src/vect.cpp
@@ -0,0 +1,1515 @@
+/***************************************************************************
+ * vect.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include "mgl2/vect.h"
+#include "mgl2/eval.h"
+#include "mgl2/data.h"
+#include "mgl2/base.h"
+//-----------------------------------------------------------------------------
+//
+//	Traj series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_traj_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT ax, HCDT ay, HCDT az, const char *sch, const char *opt)
+{
+	long n=ax->GetNx(),pal;
+	if(mgl_check_dim1(gr,x,z,y,ax,"Traj"))	return;
+	if(mgl_check_dim1(gr,ax,az,ay,0,"Traj"))	return;
+
+	mreal len=gr->SaveState(opt);	if(mgl_isnan(len))	len = 0;
+	static int cgid=1;	gr->StartGroup("Traj",cgid++);
+
+	// find maximum
+	long m = x->GetNy()>y->GetNy() ? x->GetNy():y->GetNy();
+	long i = ax->GetNy()>ay->GetNy() ? ax->GetNy():ay->GetNy();
+	long j = z->GetNy()>az->GetNy() ? z->GetNy():az->GetNy();
+	if(i>m)	m=i;
+	if(j>m)	m=j;
+	gr->SetPenPal(sch,&pal);	gr->Reserve(4*n*m);
+
+	mglPoint p1,p2;
+/*	for(j=0;j<m;j++)	for(i=0;i<n;i++)	// find maximal amplitude of vector field
+	{
+		mx = j<ax->GetNy() ? j:0;	my = j<ay->GetNy() ? j:0;	mz = j<az->GetNy() ? j:0;
+		da = sqrt(ax->v(i,mx)*ax->v(i,mx)+ay->v(i,my)*ay->v(i,my)+az->v(i,mz)*az->v(i,mz));
+		xm = xm>da ? xm : da;
+	}
+	xm = 1./(xm ? sqrt(xm):1);*/
+	for(long j=0;j<m;j++) // start prepare arrows
+	{
+		if(gr->NeedStop())	break;
+		gr->NextColor(pal);
+		long nx = j<x->GetNy() ? j:0, ny = j<y->GetNy() ? j:0, nz = j<z->GetNy() ? j:0;
+		long mx = j<ax->GetNy() ? j:0,my = j<ay->GetNy() ? j:0,mz = j<az->GetNy() ? j:0;
+		for(long i=0;i<n;i++)
+		{
+			p1.Set(x->v(i,nx), y->v(i,ny), z->v(i,nz));
+			p2.Set(ax->v(i,mx),ay->v(i,my),az->v(i,mz));
+			mreal dd = p2.norm();
+			if(len==0)
+			{
+				mreal dx,dy,dz;
+				if(i<n-1)
+				{	dx=x->v(i+1,nx)-p1.x;	dy=y->v(i+1,ny)-p1.y;	dz=z->v(i+1,nz)-p1.z;	}
+				else
+				{	dx=p1.x-x->v(i-1,nx);	dy=p1.y-y->v(i-1,ny);	dz=p1.z-z->v(i-1,nz);	}
+				dd = dd ? sqrt(dx*dx+dy*dy+dz*dz)/dd : 0;
+			}
+			else dd = len;
+			gr->vect_plot(gr->AddPnt(p1), gr->AddPnt(p1+dd*p2,-1,mglPoint(NAN),-1,2),gr->GetArrowSize());
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_traj_xy(HMGL gr, HCDT x, HCDT y, HCDT ax, HCDT ay, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV z(x->GetNx()), az(x->GetNx());	z.Fill(gr->AdjustZMin());
+	mgl_traj_xyz(gr,x,y,&z,ax,ay,&az,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_traj_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *ax, uintptr_t *ay, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_traj_xy(_GR_, _DA_(x), _DA_(y), _DA_(ax), _DA_(ay), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_traj_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *ax, uintptr_t *ay, uintptr_t *az, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_traj_xyz(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(ax), _DA_(ay), _DA_(az), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Vect series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_vect_xy(HMGL gr, HCDT x, HCDT y, HCDT ax, HCDT ay, const char *sch, const char *opt)
+{
+	long n=ax->GetNx(),m=ax->GetNy(),l=ax->GetNz();
+	if(mgl_check_dim2(gr,x,y,ax,ay,"Vect"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Vect",cgid++);
+	bool dot = sch && mglchr(sch,'.');
+	bool fix = mglchr(sch,'f');
+	bool end = mglchr(sch,'>');
+	bool beg = mglchr(sch,'<');
+	bool grd = mglchr(sch,'=');
+
+	long ss = gr->AddTexture(sch);
+	gr->Reserve(4*n*m);
+	mreal	zVal = gr->Min.z;
+
+	long tx=1,ty=1;
+	if(gr->MeshNum>1)	{	tx=(n-1)/(gr->MeshNum-1);	ty=(m-1)/(gr->MeshNum-1);	}
+	if(tx<1)	tx=1;
+	if(ty<1)	ty=1;
+
+	mreal xm=0,cm=0,ca=0;
+	mreal dm=(fabs(gr->Max.c)+fabs(gr->Min.c))*1e-5;
+	// use whole array for determining maximal vectors length
+	mglPoint p1,p2,v,d;
+
+#pragma omp parallel private(p1,p2,v,d)
+	{
+		mreal xm1=0,cm1=0,xx,c1,c2;
+#pragma omp for nowait collapse(3) reduction(+:ca)
+		for(long k=0;k<l;k++)	for(long j=0;j<m;j+=ty)	for(long i=0;i<n;i+=tx)
+		{
+			d.Set(GetX(x,i,j,k).x, GetY(y,i,j,k).x);
+			v.Set(ax->v(i,j,k),ay->v(i,j,k));
+			c1 = v.norm();	xm1 = xm1<c1 ? c1:xm1;	// handle NAN values
+			p1 = i<n-1 ? mglPoint(GetX(x,i+tx,j,k).x, GetY(y,i+tx,j,k).x)-d : d-mglPoint(GetX(x,i-tx,j,k).x, GetY(y,i-tx,j,k).x);
+			c1 = fabs(v*p1);	xx = p1.norm();	c1 *= xx?1/(xx*xx):0;
+			p1 = j<m-1 ? mglPoint(GetX(x,i,j+ty,k).x, GetY(y,i,j+ty,k).x)-d : d-mglPoint(GetX(x,i,j-ty,k).x, GetY(y,i,j-ty,k).x);
+			c2 = fabs(v*p1);	xx = p1.norm();	c2 *= xx?1/(xx*xx):0;
+			c1 = c1<c2 ? c2:c1;	ca+=c1;	cm1 = cm1<c1 ? c1:cm1;
+		}
+#pragma omp critical(max_vec)
+		{cm = cm<cm1 ? cm1:cm;	xm = xm<xm1 ? xm1:xm;}
+	}
+	ca /= (n*m*l)/(tx*ty);
+	xm = xm?1./xm:0;	cm = cm?1./cm:0;
+
+	for(long k=0;k<l;k++)
+	{
+		if(gr->NeedStop())	break;
+		if(ax->GetNz()>1)	zVal = gr->Min.z+(gr->Max.z-gr->Min.z)*mreal(k)/(ax->GetNz()-1);
+		for(long j=0;j<m;j+=ty)	for(long i=0;i<n;i+=tx)
+		{
+			d.Set(GetX(x,i,j,k).x, GetY(y,i,j,k).x, zVal);
+			v.Set(ax->v(i,j,k),ay->v(i,j,k));
+			mreal dd = v.norm(), c1, c2;
+			v *= cm*(fix?(dd>dm ? 1./dd : 0) : xm);
+
+			if(end)		{	p1 = d-v;	p2 = d;	}
+			else if(beg)	{	p1 = d;	p2 = d+v;	}
+			else		{	p1=d-v/2.;	p2=d+v/2.;	}
+			if(grd)	{	c1=gr->GetC(ss,dd*xm-0.5,false);	c2=gr->GetC(ss,dd*xm,false);}
+			else	c1 = c2 = gr->GetC(ss,dd*xm,false);
+			long n1=gr->AddPnt(p1,c1),	n2=gr->AddPnt(p2,c2);
+			// allow vectors outside bounding box
+			if(n1<0 && n2>=0)	n1=gr->AddPnt(p1,c1,mglPoint(NAN),-1,2);
+			if(n2<0 && n1>=0)	n2=gr->AddPnt(p2,c2,mglPoint(NAN),-1,2);
+			if(dot)	{	gr->line_plot(n1,n2);	gr->mark_plot(n1,'.');	}
+			else	gr->vect_plot(n1,n2,gr->GetArrowSize());
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_vect_2d(HMGL gr, HCDT ax, HCDT ay, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(ax->GetNx()), y(ax->GetNy());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	mgl_vect_xy(gr,&x,&y,ax,ay,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_vect_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *ax, uintptr_t *ay, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_vect_xy(_GR_, _DA_(x), _DA_(y), _DA_(ax), _DA_(ay), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_vect_2d_(uintptr_t *gr, uintptr_t *ax, uintptr_t *ay, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_vect_2d(_GR_, _DA_(ax), _DA_(ay), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Vect3 series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_vect_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT ax, HCDT ay, HCDT az, const char *sch, const char *opt)
+{
+	long n=ax->GetNx(),m=ax->GetNy(),l=ax->GetNz();
+	if(mgl_check_vec3(gr,x,y,z,ax,ay,az,"Vect_3d"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Vect_3d",cgid++);
+	bool dot = mglchr(sch,'.');
+	bool fix = mglchr(sch,'f');
+	bool end = mglchr(sch,'>');
+	bool beg = mglchr(sch,'<');
+	bool grd = mglchr(sch,'=');
+
+	long ss = gr->AddTexture(sch);
+	gr->Reserve(2*n*m*l);
+	long tx=1,ty=1,tz=1;
+	if(gr->MeshNum>1)
+	{	tx=(n-1)/(gr->MeshNum-1);	ty=(m-1)/(gr->MeshNum-1);	tz=(l-1)/(gr->MeshNum-1);}
+	if(tx<1)	tx=1;
+	if(ty<1)	ty=1;
+	if(tz<1)	tz=1;
+
+	mreal xm=0,cm=0,ca=0;
+	mreal dm=(fabs(gr->Max.c)+fabs(gr->Min.c))*1e-5;
+	// use whole array for determining maximal vectors length
+	mglPoint p1,p2, v, d;
+
+#pragma omp parallel private(p1,p2,v,d)
+	{
+		mreal c1,c2,c3, xm1=0,cm1=0,xx;
+#pragma omp for nowait collapse(3) reduction(+:ca)
+		for(long k=0;k<l;k+=tz)	for(long i=0;i<n;i+=tx)	for(long j=0;j<m;j+=ty)
+		{
+			d.Set(GetX(x,i,j,k).x, GetY(y,i,j,k).x, GetZ(z,i,j,k).x);
+			v.Set(ax->v(i,j,k),ay->v(i,j,k),az->v(i,j,k));
+			c1 = v.norm();	xm1 = xm1<c1 ? c1:xm1;	// handle NAN values
+			p1 = i<n-1 ? mglPoint(GetX(x,i+tx,j,k).x, GetY(y,i+tx,j,k).x, GetZ(z,i+tx,j,k).x)-d : d-mglPoint(GetX(x,i-tx,j,k).x, GetY(y,i-tx,j,k).x, GetZ(z,i-tx,j,k).x);
+			c1 = fabs(v*p1);	xx = p1.norm();	c1 *= xx?1/(xx*xx):0;
+			p1 = j<m-1 ? mglPoint(GetX(x,i,j+ty,k).x, GetY(y,i,j+ty,k).x, GetZ(z,i,j+ty,k).x)-d : d-mglPoint(GetX(x,i,j-ty,k).x, GetY(y,i,j-ty,k).x, GetZ(z,i,j-ty,k).x);
+			c2 = fabs(v*p1);	xx = p1.norm();	c2 *= xx?1/(xx*xx):0;
+			p1 = k<l-1 ? mglPoint(GetX(x,i,j,k+tz).x, GetY(y,i,j,k+tz).x, GetZ(z,i,j,k+tz).x)-d : d-mglPoint(GetX(x,i,j,k-tz).x, GetY(y,i,j,k-tz).x, GetZ(z,i,j,k-tz).x);
+			c3 = fabs(v*p1);	xx = p1.norm();	c3 *= xx?1/(xx*xx):0;
+			c1 = c1<c2 ? c2:c1;	c1 = c1<c3 ? c3:c1;
+			ca+=c1;	cm1 = cm1<c1 ? c1:cm1;
+		}
+#pragma omp critical(max_vec)
+		{cm = cm<cm1 ? cm1:cm;	xm = xm<xm1 ? xm1:xm;}
+	}
+	ca /= mreal(n*m*l)/mreal(tx*ty*tz);
+	xm = xm?1./xm:0;	cm = cm?1./cm:0;
+
+	for(long k=0;k<l;k+=tz)
+	{
+		if(gr->NeedStop())	break;
+		for(long i=0;i<n;i+=tx)	for(long j=0;j<m;j+=ty)
+		{
+			d.Set(GetX(x,i,j,k).x, GetY(y,i,j,k).x, GetZ(z,i,j,k).x);
+			v.Set(ax->v(i,j,k),ay->v(i,j,k),az->v(i,j,k));
+			mreal dd = v.norm(),c1,c2;
+			v *= cm*(fix?(dd>dm ? 1./dd : 0) : xm);
+
+			if(end)		{	p1 = d-v;	p2 = d;	}
+			else if(beg)	{	p1 = d;	p2 = d+v;	}
+			else		{	p1=d-v/2.;	p2=d+v/2.;	}
+			if(grd)	{	c1=gr->GetC(ss,dd*xm-0.5,false);	c2=gr->GetC(ss,dd*xm,false);	}
+			else	c1 = c2 = gr->GetC(ss,dd*xm,false);
+			long n1=gr->AddPnt(p1,c1),	n2=gr->AddPnt(p2,c2);
+			// allow vectors outside bounding box
+			if(n1<0 && n2>=0)	n1=gr->AddPnt(p1,c1,mglPoint(NAN),-1,2);
+			if(n2<0 && n1>=0)	n2=gr->AddPnt(p2,c2,mglPoint(NAN),-1,2);
+			if(dot)	{	gr->line_plot(n1,n2);	gr->mark_plot(n1,'.');	}
+			else	gr->vect_plot(n1,n2,gr->GetArrowSize());
+		}
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_vect_3d(HMGL gr, HCDT ax, HCDT ay, HCDT az, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(ax->GetNx()), y(ax->GetNy()), z(ax->GetNz());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	z.Fill(gr->Min.z,gr->Max.z);
+	mgl_vect_xyz(gr,&x,&y,&z,ax,ay,az,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_vect_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *ax, uintptr_t *ay, uintptr_t *az, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_vect_xyz(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(ax), _DA_(ay), _DA_(az), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_vect_3d_(uintptr_t *gr, uintptr_t *ax, uintptr_t *ay, uintptr_t *az, const char *sch, const char *opt, int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_vect_3d(_GR_, _DA_(ax), _DA_(ay), _DA_(az), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Vect3 series
+//
+//-----------------------------------------------------------------------------
+struct _mgl_vec_slice	{	mglData x,y,z,ax,ay,az;	};
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_get_slice(_mgl_vec_slice &s, HCDT x, HCDT y, HCDT z, HCDT ax, HCDT ay, HCDT az, char dir, mreal d, bool both)
+{
+	long n=ax->GetNx(),m=ax->GetNy(),l=ax->GetNz(), nx=1,ny=1,p;
+
+	if(dir=='x')	{	nx = m;	ny = l;	if(d<0)	d = n/2.;	}
+	if(dir=='y')	{	nx = n;	ny = l;	if(d<0)	d = m/2.;	}
+	if(dir=='z')	{	nx = n;	ny = m;	if(d<0)	d = l/2.;	}
+	s.x.Create(nx,ny);	s.y.Create(nx,ny);	s.z.Create(nx,ny);
+	s.ax.Create(nx,ny);	s.ay.Create(nx,ny);	s.az.Create(nx,ny);
+	p = long(d);	d -= p;
+	if(dir=='x' && p>=n-1)	{	d+=p-n+2;	p=n-2;	}
+	if(dir=='y' && p>=m-1)	{	d+=p-m+2.;	p=m-2;	}
+	if(dir=='z' && p>=l-1)	{	d+=p-l+2;	p=l-2;	}
+
+	if(both)
+	{
+		if(dir=='x')
+#pragma omp parallel for collapse(2)
+			for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+			{
+				long i0 = i+nx*j;
+				s.x.a[i0] = x->v(p,i,j)*(1-d) + x->v(p+1,i,j)*d;
+				s.y.a[i0] = y->v(p,i,j)*(1-d) + y->v(p+1,i,j)*d;
+				s.z.a[i0] = z->v(p,i,j)*(1-d) + z->v(p+1,i,j)*d;
+				s.ax.a[i0] = ax->v(p,i,j)*(1-d) + ax->v(p+1,i,j)*d;
+				s.ay.a[i0] = ay->v(p,i,j)*(1-d) + ay->v(p+1,i,j)*d;
+				s.az.a[i0] = az->v(p,i,j)*(1-d) + az->v(p+1,i,j)*d;
+			}
+		if(dir=='y')
+#pragma omp parallel for collapse(2)
+			for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+			{
+				long i0 = i+nx*j;
+				s.x.a[i0] = x->v(i,p,j)*(1-d) + x->v(i,p+1,j)*d;
+				s.y.a[i0] = y->v(i,p,j)*(1-d) + y->v(i,p+1,j)*d;
+				s.z.a[i0] = z->v(i,p,j)*(1-d) + z->v(i,p+1,j)*d;
+				s.ax.a[i0] = ax->v(i,p,j)*(1-d) + ax->v(i,p+1,j)*d;
+				s.ay.a[i0] = ay->v(i,p,j)*(1-d) + ay->v(i,p+1,j)*d;
+				s.az.a[i0] = az->v(i,p,j)*(1-d) + az->v(i,p+1,j)*d;
+			}
+		if(dir=='z')
+#pragma omp parallel for collapse(2)
+			for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+			{
+				long i0 = i+nx*j;
+				s.x.a[i0] = x->v(i,j,p)*(1-d) + x->v(i,j,p+1)*d;
+				s.y.a[i0] = y->v(i,j,p)*(1-d) + y->v(i,j,p+1)*d;
+				s.z.a[i0] = z->v(i,j,p)*(1-d) + z->v(i,j,p+1)*d;
+				s.ax.a[i0] = ax->v(i,j,p)*(1-d) + ax->v(i,j,p+1)*d;
+				s.ay.a[i0] = ay->v(i,j,p)*(1-d) + ay->v(i,j,p+1)*d;
+				s.az.a[i0] = az->v(i,j,p)*(1-d) + az->v(i,j,p+1)*d;
+			}
+	}
+	else	// x, y, z -- vectors
+	{
+		if(dir=='x')
+		{
+			mreal v = x->v(p)*(1-d)+x->v(p+1)*d;
+#pragma omp parallel for collapse(2)
+			for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+			{
+				long i0 = i+nx*j;	s.x.a[i0] = v;
+				s.y.a[i0] = y->v(i);	s.z.a[i0] = z->v(j);
+				s.ax.a[i0] = ax->v(p,i,j)*(1-d) + ax->v(p+1,i,j)*d;
+				s.ay.a[i0] = ay->v(p,i,j)*(1-d) + ay->v(p+1,i,j)*d;
+				s.az.a[i0] = az->v(p,i,j)*(1-d) + az->v(p+1,i,j)*d;
+			}
+		}
+		if(dir=='y')
+		{
+			mreal v = y->v(p)*(1-d)+y->v(p+1)*d;
+#pragma omp parallel for collapse(2)
+			for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+			{
+				long i0 = i+nx*j;	s.y.a[i0] = v;
+				s.x.a[i0] = x->v(i);	s.z.a[i0] = z->v(j);
+				s.ax.a[i0] = ax->v(i,p,j)*(1-d) + ax->v(i,p+1,j)*d;
+				s.ay.a[i0] = ay->v(i,p,j)*(1-d) + ay->v(i,p+1,j)*d;
+				s.az.a[i0] = az->v(i,p,j)*(1-d) + az->v(i,p+1,j)*d;
+			}
+		}
+		if(dir=='z')
+		{
+			mreal v = z->v(p)*(1-d)+z->v(p+1)*d;
+#pragma omp parallel for collapse(2)
+			for(long j=0;j<ny;j++)	for(long i=0;i<nx;i++)
+			{
+				long i0 = i+nx*j;	s.z.a[i0] = v;
+				s.x.a[i0] = x->v(i);	s.y.a[i0] = y->v(j);
+				s.ax.a[i0] = ax->v(i,j,p)*(1-d) + ax->v(i,j,p+1)*d;
+				s.ay.a[i0] = ay->v(i,j,p)*(1-d) + ay->v(i,j,p+1)*d;
+				s.az.a[i0] = az->v(i,j,p)*(1-d) + az->v(i,j,p+1)*d;
+			}
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_vect3_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT ax, HCDT ay, HCDT az, const char *sch, double sVal, const char *opt)
+{
+	bool both = mgl_isboth(x,y,z,ax);
+	if(mgl_check_vec3(gr,x,y,z,ax,ay,az,"Vect3"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Vect3",cgid++);
+	char dir='y';
+	if(mglchr(sch,'x'))	dir='x';
+	if(mglchr(sch,'z'))	dir='z';
+
+	bool dot = mglchr(sch,'.');
+	bool fix = mglchr(sch,'f');
+	bool end = mglchr(sch,'>');
+	bool beg = mglchr(sch,'<');
+	bool grd = mglchr(sch,'=');
+	long ss = gr->AddTexture(sch);
+
+	_mgl_vec_slice s;
+	mgl_get_slice(s,x,y,z,ax,ay,az,dir,sVal,both);
+
+	long n=s.ax.nx,m=s.ax.ny, tx=1,ty=1;
+	if(gr->MeshNum>1)	{	tx=(n-1)/(gr->MeshNum-1);	ty=(m-1)/(gr->MeshNum-1);	}
+	if(tx<1)	tx=1;
+	if(ty<1)	ty=1;
+	mreal xm=0,cm=0,ca=0;
+	mreal dm=(fabs(gr->Max.c)+fabs(gr->Min.c))*1e-5;
+	// use whole array for determining maximal vectors length
+	mglPoint p1,p2, v, d=(gr->Max-gr->Min)/mglPoint(1./ax->GetNx(),1./ax->GetNy(),1./ax->GetNz());
+
+	long tn=ty*n;
+#pragma omp parallel private(p1,p2,v)
+	{
+		mreal xm1=0,cm1=0, xx,yy,zz, c1,c2;
+#pragma omp for nowait collapse(2) reduction(+:ca)
+		for(long i=0;i<n;i+=tx)	for(long j=0;j<m;j+=ty)
+		{
+			long i0 = i+n*j;
+			xx = s.x.a[i0];	yy = s.y.a[i0];	zz = s.z.a[i0];
+			p1 = i<n-1 ? mglPoint(s.x.a[i0+tx]-xx, s.y.a[i0+tx]-yy, s.z.a[i0+tx]-zz) : mglPoint(xx-s.x.a[i0-tx], yy-s.y.a[i0-tx], zz-s.z.a[i0-tx]);
+			p2 = j<m-1 ? mglPoint(s.x.a[i0+tn]-xx, s.y.a[i0+tn]-yy, s.z.a[i0+tn]-zz) : mglPoint(xx-s.x.a[i0-tn], yy-s.y.a[i0-tn], zz-s.z.a[i0-tn]);
+			v.Set(s.ax.a[i0], s.ay.a[i0], s.az.a[i0]);
+			c1 = v.norm();	xm1 = xm1<c1 ? c1:xm1;	// handle NAN values
+			yy = fabs(v*d);	xx = d.norm();	yy *= xx?1/(xx*xx):0;
+			c1 = fabs(v*p1);	xx = p1.norm();	c1 *= xx?1/(xx*xx):0;
+			c2 = fabs(v*p2);	xx = p2.norm();	c2 *= xx?1/(xx*xx):0;
+			c1 = c1<c2 ? c2:c1;	c1 = c1<yy ? yy:c1;
+			ca+=c1;	cm1 = cm1<c1 ? c1:cm1;
+		}
+#pragma omp critical(max_vec)
+		{cm = cm<cm1 ? cm1:cm;	xm = xm<xm1 ? xm1:xm;}
+	}
+	ca /= mreal(n*m)/mreal(tx*ty);
+	xm = xm?1./xm:0;	cm = cm?1./cm:0;
+
+	for(long i=0;i<n;i+=tx)	for(long j=0;j<m;j+=ty)
+	{
+		long i0 = i+n*j;
+		d.Set(s.x.a[i0], s.y.a[i0], s.z.a[i0]);
+		v.Set(s.ax.a[i0], s.ay.a[i0], s.az.a[i0]);
+		mreal dd = v.norm(),c1,c2;
+		v *= cm*(fix?(dd>dm ? 1./dd : 0) : xm);
+
+		if(end)		{	p1 = d-v;	p2 = d;	}
+		else if(beg)	{	p1 = d;	p2 = d+v;	}
+		else		{	p1=d-v/2.;	p2=d+v/2.;	}
+		if(grd)	{	c1=gr->GetC(ss,dd*xm-0.5,false);	c2=gr->GetC(ss,dd*xm,false);}
+		else	c1 = c2 = gr->GetC(ss,dd*xm,false);
+		long n1=gr->AddPnt(p1,c1),	n2=gr->AddPnt(p2,c2);
+		// allow vectors outside bounding box
+		if(n1<0 && n2>=0)	n1=gr->AddPnt(p1,c1,mglPoint(NAN),-1,2);
+		if(n2<0 && n1>=0)	n2=gr->AddPnt(p2,c2,mglPoint(NAN),-1,2);
+		if(dot)	{	gr->line_plot(n1,n2);	gr->mark_plot(n1,'.');	}
+		else	gr->vect_plot(n1,n2,gr->GetArrowSize());
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_vect3(HMGL gr, HCDT ax, HCDT ay, HCDT az, const char *sch, double sVal, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(ax->GetNx()), y(ax->GetNy()),z(ax->GetNz());	// NOTE mglDataV here is useless
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	z.Fill(gr->Min.z,gr->Max.z);
+	mgl_vect3_xyz(gr,&x,&y,&z,ax,ay,az,sch,sVal,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_vect3_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *ax, uintptr_t *ay, uintptr_t *az, const char *sch, mreal *sVal, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_vect3_xyz(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(ax), _DA_(ay), _DA_(az), s, *sVal, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_vect3_(uintptr_t *gr, uintptr_t *ax, uintptr_t *ay, uintptr_t *az, const char *sch, mreal *sVal, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_vect3(_GR_, _DA_(ax), _DA_(ay), _DA_(az), s, *sVal, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Flow 2d series
+//
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT flow(mglBase *gr, double zVal, double u, double v, HCDT x, HCDT y, HCDT ax, HCDT ay, long ss, bool vv)
+{
+	long n=100*(ax->GetNx()+ax->GetNy());
+	bool nboth = x->GetNx()*x->GetNy()!=ax->GetNx()*ax->GetNy() || y->GetNx()*y->GetNy()!=ax->GetNx()*ax->GetNy();
+
+	mglPoint *pp = new mglPoint[n], dp;
+	mglPoint dx(1/fabs(gr->Max.x-gr->Min.x),1/fabs(gr->Max.y-gr->Min.y),1/fabs(gr->Max.z-gr->Min.z));
+	mglPoint nx(ax->GetNx(),ax->GetNy());
+
+	mreal dt = 0.5/(ax->GetNx() > ax->GetNy() ? ax->GetNx() : ax->GetNy());
+	mreal e,f,g,ff[4],gg[4],h,s=2,acc=dt/20;
+	if(u<0 || v<0)	{	dt = -dt;	u = -u;	v = -v;	s *= -1;}
+	long k=0;
+	bool end = false;
+	if(nboth) do{
+		mglPoint dif;
+		pp[k].x = x->Spline1(dif,u,0,0);	f = ax->Spline1(u,v,0)/dif.x;
+		pp[k].y = y->Spline1(dif,v,0,0);	g = ay->Spline1(u,v,0)/dif.x;
+		pp[k].z = zVal;
+		if(mgl_isbad(f+g))	break;
+		else	for(long m=0;m<k-1;m+=10)	// determines encircle
+			if(mgl_anorm((pp[k]-pp[m])/dx)<acc)	end = true;
+		h = hypot(f,g);	pp[k].c = gr->GetC(ss,s*h);
+		if(end || h<1e-5)	break;	// stationary point
+		if(k==0 || mgl_anorm((pp[k]-pp[k-1])/nx)>=1)	k++;
+		// find next point by midpoint method
+		h+=1;	ff[0]=f*dt/h;	gg[0]=g*dt/h;
+		e = u+ff[0]/2;	h = v+gg[0]/2;
+		x->Spline1(dif,e,0,0);	f = ax->Spline1(e,h,0)/dif.x;
+		y->Spline1(dif,h,0,0);	g = ay->Spline1(e,h,0)/dif.x;
+		h = 1+hypot(f,g);	ff[1]=f*dt/h;	gg[1]=g*dt/h;
+		e = u+ff[1]/2;	h = v+gg[1]/2;
+		x->Spline1(dif,e,0,0);	f = ax->Spline1(e,h,0)/dif.x;
+		y->Spline1(dif,h,0,0);	g = ay->Spline1(e,h,0)/dif.x;
+		h = 1+hypot(f,g);	ff[2]=f*dt/h;	gg[2]=g*dt/h;
+		e = u+ff[2];	h = v+gg[2];
+		x->Spline1(dif,e,0,0);	f = ax->Spline1(e,h,0)/dif.x;
+		y->Spline1(dif,h,0,0);	g = ay->Spline1(e,h,0)/dif.x;
+		h = 1+hypot(f,g);	ff[3]=f*dt/h;	gg[3]=g*dt/h;
+		u += ff[0]/6+ff[1]/3+ff[2]/3+ff[3]/6;
+		v += gg[0]/6+gg[1]/3+gg[2]/3+gg[3]/6;
+		// condition of end
+		end = end || k>=n || u<0 || v<0 || u>1 || v>1;
+	} while(!end);
+	else do{
+		mglPoint dif;
+		mreal xu,xv,yu,yv,det,xx,yy;
+		pp[k].x = x->Spline1(dif,u,v,0);	xu=dif.x;	xv=dif.y;
+		pp[k].y = y->Spline1(dif,u,v,0);	yu=dif.x;	yv=dif.y;
+		xx = ax->Spline1(u,v,0);	yy = ay->Spline1(u,v,0);
+		det = xv*yu-xu*yv;	f = (yy*xv-xx*yv)/det;	g = (xx*yu-yy*xu)/det;
+		pp[k].z = zVal;
+		if(mgl_isbad(f+g))	break;
+		else	for(long m=0;m<k-1;m+=10)	// determines encircle
+			if(mgl_anorm((pp[k]-pp[m])/dx)<acc)	end = true;
+		h = hypot(f,g);	pp[k].c = gr->GetC(ss,s*h);
+		if(end || h<1e-5)	break;	// stationary point
+		if(k==0 || mgl_anorm((pp[k]-pp[k-1])/nx)>=1)	k++;
+		// find next point by midpoint method
+		h+=1;	ff[0]=f*dt/h;	gg[0]=g*dt/h;
+		e = u+ff[0]/2;	h = v+gg[0]/2;
+			x->Spline1(dif,e,h,0);	xu=dif.x;	xv=dif.y;
+			y->Spline1(dif,e,h,0);	yu=dif.x;	yv=dif.y;
+			xx = ax->Spline1(e,h,0);	yy = ay->Spline1(e,h,0);
+			det = xv*yu-xu*yv;	f = (yy*xv-xx*yv)/det;	g = (xx*yu-yy*xu)/det;
+		h = 1+hypot(f,g);	ff[1]=f*dt/h;	gg[1]=g*dt/h;
+		e = u+ff[1]/2;	h = v+gg[1]/2;
+			x->Spline1(dif,e,h,0);	xu=dif.x;	xv=dif.y;
+			y->Spline1(dif,e,h,0);	yu=dif.x;	yv=dif.y;
+			xx = ax->Spline1(e,h,0);	yy = ay->Spline1(e,h,0);
+			det = xv*yu-xu*yv;	f = (yy*xv-xx*yv)/det;	g = (xx*yu-yy*xu)/det;
+		h = 1+hypot(f,g);	ff[2]=f*dt/h;	gg[2]=g*dt/h;
+		e = u+ff[2];	h = v+gg[2];
+			x->Spline1(dif,e,h,0);	xu=dif.x;	xv=dif.y;
+			y->Spline1(dif,e,h,0);	yu=dif.x;	yv=dif.y;
+			xx = ax->Spline1(e,h,0);	yy = ay->Spline1(e,h,0);
+			det = xv*yu-xu*yv;	f = (yy*xv-xx*yv)/det;	g = (xx*yu-yy*xu)/det;
+		h = 1+hypot(f,g);	ff[3]=f*dt/h;	gg[3]=g*dt/h;
+		u += ff[0]/6+ff[1]/3+ff[2]/3+ff[3]/6;
+		v += gg[0]/6+gg[1]/3+gg[2]/3+gg[3]/6;
+		// condition of end
+		end = end || k>=n || u<0 || v<0 || u>1 || v>1;
+	} while(!end);
+	if(k>1)
+	{
+		long j,a=long(0.3*gr->GetArrowSize()/fabs(dt));
+		gr->Reserve(k);	j = gr->AddPnt(pp[0],pp[0].c);
+		for(long i=1;i<k;i++)
+		{
+			long jj=j;	j = gr->AddPnt(pp[i],pp[i].c);
+			if(vv && i%a==0)
+			{
+				if(dt<0)	gr->vect_plot(j,jj,a/3);
+				else		gr->vect_plot(jj,j,a/3);
+			}
+			else	gr->line_plot(jj,j);
+		}
+	}
+	delete []pp;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_flow_xy(HMGL gr, HCDT x, HCDT y, HCDT ax, HCDT ay, const char *sch, const char *opt)
+{
+	if(mgl_check_dim2(gr,x,y,ax,ay,"Flow"))	return;
+
+	mreal r = gr->SaveState(opt);
+	long num = mgl_isnan(r)?5:long(r+0.5);
+	static int cgid=1;	gr->StartGroup("Flow",cgid++);
+
+	long ss = gr->AddTexture(sch);
+	bool vv = mglchr(sch,'v');
+	// allocate memory
+	mreal zVal = gr->Min.z;
+	bool cnt=!mglchr(sch,'#');
+
+	std::vector<mreal> u, v;
+	if(mglchr(sch,'*'))	for(long i=0;i<num;i++)	for(long j=0;j<num;j++)
+	{
+		mreal t = (i+1.)/(num+1.), s = (j+1.)/(num+1.);
+		u.push_back(s);		v.push_back(t);
+		u.push_back(-s);	v.push_back(-t);
+	}
+	else	for(long i=0;i<num;i++)
+	{
+		mreal t = (i+1.)/(num+1.);
+		u.push_back(0);		v.push_back(t);
+		u.push_back(0);		v.push_back(-t);
+		u.push_back(1);		v.push_back(t);
+		u.push_back(-1);	v.push_back(-t);
+		u.push_back(t);		v.push_back(0);
+		u.push_back(-t);	v.push_back(0);
+		u.push_back(t);		v.push_back(1);
+		u.push_back(-t);	v.push_back(-1);
+		if(cnt)
+		{
+			u.push_back(t);		v.push_back(0.5);
+			u.push_back(-t);	v.push_back(-0.5);
+			u.push_back(0.5);	v.push_back(t);
+			u.push_back(-0.5);	v.push_back(-t);
+		}
+	}
+	for(long k=0;k<ax->GetNz();k++)
+	{
+		if(gr->NeedStop())	break;
+		if(ax->GetNz()>1)	zVal = gr->Min.z+(gr->Max.z-gr->Min.z)*mreal(k)/(ax->GetNz()-1);
+		HMDT bx=mgl_data_subdata(ax,-1,-1,k), by=mgl_data_subdata(ay,-1,-1,k);
+#pragma omp parallel for
+		for(long i=0;i<long(u.size());i++)	if(!gr->NeedStop())
+			flow(gr, zVal, u[i], v[i], x, y, bx, by,ss,vv);
+		mgl_delete_data(bx);	mgl_delete_data(by);
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_flow_2d(HMGL gr, HCDT ax, HCDT ay, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(ax->GetNx()), y(ax->GetNy());	// NOTE mglDataV here is useless
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	mgl_flow_xy(gr,&x,&y,ax,ay,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_flow_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *ax, uintptr_t *ay, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_flow_xy(_GR_, _DA_(x), _DA_(y), _DA_(ax), _DA_(ay), s, o);	delete []o;	delete []s;	}
+void MGL_EXPORT mgl_flow_2d_(uintptr_t *gr, uintptr_t *ax, uintptr_t *ay, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_flow_2d(_GR_, _DA_(ax), _DA_(ay), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_flowp_xy(HMGL gr, double x0, double y0, double z0, HCDT x, HCDT y, HCDT ax, HCDT ay, const char *sch, const char *opt)
+{
+	if(mgl_isnan(z0))	z0 = gr->Min.z;
+	mreal u,v;
+	long n=ax->GetNx(), m=ax->GetNy();
+	bool nboth = x->GetNx()*x->GetNy()!=n*m || y->GetNx()*y->GetNy()!=n*m;
+	if(mgl_check_dim2(gr,x,y,ax,ay,"FlowP"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("FlowP",cgid++);
+
+	long ss = gr->AddTexture(sch);
+	bool vv = mglchr(sch,'v');
+	// find coordinates u, v
+	mreal dm=INFINITY;
+	long i0=0,j0=0;
+	for(long i=0;i<n;i++)	for(long j=0;j<m;j++)	// first find closest
+	{
+		mreal d = nboth ? hypot(x->v(i)-x0,y->v(j)-y0) : hypot(x->v(i,j)-x0,y->v(i,j)-y0);
+		if(d<dm)	{	i0=i;	j0=j;	dm=d;	}
+	}
+	if(dm==0)	{	u = i0/mreal(n);	v = j0/mreal(m);	}	// we find it
+	else
+	{
+		mreal dxu,dxv,dyu,dyv, dx, dy;
+		if(nboth)
+		{
+			dx = x->v(i0)-x0;	dy = y->v(j0)-y0;
+			dxu= x->dvx(i0);	dyv= y->dvx(j0);
+			u = (i0+dx/dxu)/n;	v = (j0+dy/dyv)/m;
+		}
+		else
+		{
+			dx = x->v(i0,j0)-x0;	dy = y->v(i0,j0)-y0;
+			dxu= x->dvx(i0,j0);		dyu= y->dvx(i0,j0);
+			dxv= x->dvy(i0,j0);		dyv= y->dvy(i0,j0);
+			mreal d = dxv*dyu-dxu*dyv;
+			u = (i0+(dxv*dy-dx*dyv)/d)/n;
+			v = (j0-(dxu*dy-dx*dyu)/d)/m;
+		}
+	}
+	flow(gr, z0, u, v, x, y, ax, ay,ss,vv);
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_flowp_2d(HMGL gr, double x0, double y0, double z0, HCDT ax, HCDT ay, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(ax->GetNx()), y(ax->GetNy());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	mgl_flowp_xy(gr,x0,y0,z0,&x,&y,ax,ay,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_flowp_xy_(uintptr_t *gr, mreal *x0, mreal *y0, mreal *z0, uintptr_t *x, uintptr_t *y, uintptr_t *ax, uintptr_t *ay, const char *sch, const char *opt, int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_flowp_xy(_GR_, *x0,*y0,*z0, _DA_(x), _DA_(y), _DA_(ax), _DA_(ay), s, o);	delete []o;	delete []s;
+}
+void MGL_EXPORT mgl_flowp_2d_(uintptr_t *gr, mreal *x0, mreal *y0, mreal *z0, uintptr_t *ax, uintptr_t *ay, const char *sch, const char *opt, int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_flowp_2d(_GR_, *x0,*y0,*z0, _DA_(ax), _DA_(ay), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Flow 3d series
+//
+//-----------------------------------------------------------------------------
+void flow(mglBase *gr, double u, double v, double w, HCDT x, HCDT y, HCDT z, HCDT ax, HCDT ay, HCDT az,long ss,bool vv, bool xo, bool zo)
+{
+	static long n=100*(ax->GetNx()+ax->GetNy()+ax->GetNz());
+	long nn = ax->GetNN();
+	bool nboth = x->GetNN()!=nn || y->GetNN()!=nn || z->GetNN()!=nn;
+	mglPoint *pp = new mglPoint[n], dp;
+	mglPoint dx(1/fabs(gr->Max.x-gr->Min.x),1/fabs(gr->Max.y-gr->Min.y),1/fabs(gr->Max.z-gr->Min.z));
+	mglPoint nx(ax->GetNx(),ax->GetNy(),ax->GetNz());
+
+	nn = (ax->GetNx() > ax->GetNy() ? ax->GetNz() : ax->GetNy());
+	nn = (nn > ax->GetNz() ? nn : ax->GetNz());
+	mreal dt = 0.2/nn, e,f,g,ee[4],ff[4],gg[4],h,s=2,u1,v1,w1,acc=dt/20;
+	if(u<0 || v<0 || w<0)
+	{	dt = -dt;	u = -u;	v = -v;	w = -w;	s *= -1;}
+	long k=0;
+	bool end = false;
+	if(nboth) do{
+		mglPoint dif;
+		pp[k].x = x->Spline1(dif,u,0,0);	e = ax->Spline1(u,v,w)/dif.x;
+		pp[k].y = y->Spline1(dif,v,0,0);	f = ay->Spline1(u,v,w)/dif.x;
+		pp[k].z = z->Spline1(dif,w,0,0);	g = az->Spline1(u,v,w)/dif.x;
+		if(mgl_isbad(e+f+g))	end = true;
+		else	for(long m=0;m<k-1;m+=10)	// determines encircle
+			if(mgl_anorm((pp[k]-pp[m])/dx)<acc)	end = true;
+		if(end)	break;
+		h = sqrt(e*e+f*f+g*g);	pp[k].c = gr->GetC(ss,s*h);
+		if(h<1e-5)	break;	// stationary point
+		if(k==0 || mgl_anorm((pp[k]-pp[k-1])/nx)>=1)	k++;
+		// find next point by midpoint method
+		h+=1;	ee[0]=e*dt/h;	ff[0]=f*dt/h;	gg[0]=g*dt/h;
+		u1 = u+ee[0]/2;	v1 = v+ff[0]/2;	w1 = w+gg[0]/2;
+		x->Spline1(dif,u1,0,0);	e = ax->Spline1(u1,v1,w1)/dif.x;
+		y->Spline1(dif,v1,0,0);	f = ay->Spline1(u1,v1,w1)/dif.x;
+		z->Spline1(dif,w1,0,0);	g = az->Spline1(u1,v1,w1)/dif.x;
+		h = 1+sqrt(e*e+f*f+g*g);
+		ee[1]=e*dt/h;	ff[1]=f*dt/h;	gg[1]=g*dt/h;
+		u1 = u+ee[1]/2;	v1 = v+ff[1]/2;	w1 = w+gg[1]/2;
+		x->Spline1(dif,u1,0,0);	e = ax->Spline1(u1,v1,w1)/dif.x;
+		y->Spline1(dif,v1,0,0);	f = ay->Spline1(u1,v1,w1)/dif.x;
+		z->Spline1(dif,w1,0,0);	g = az->Spline1(u1,v1,w1)/dif.x;
+		h = 1+sqrt(e*e+f*f+g*g);
+		ee[2]=e*dt/h;	ff[2]=f*dt/h;	gg[2]=g*dt/h;
+		u1 = u+ee[2];	v1 = v+ff[2];	w1 = w+gg[2];
+		x->Spline1(dif,u1,0,0);	e = ax->Spline1(u1,v1,w1)/dif.x;
+		y->Spline1(dif,v1,0,0);	f = ay->Spline1(u1,v1,w1)/dif.x;
+		z->Spline1(dif,w1,0,0);	g = az->Spline1(u1,v1,w1)/dif.x;
+		h = 1+sqrt(e*e+f*f+g*g);
+		ee[3]=e*dt/h;	ff[3]=f*dt/h;	gg[3]=g*dt/h;
+		u += ee[0]/6+ee[1]/3+ee[2]/3+ee[3]/6;
+		v += ff[0]/6+ff[1]/3+ff[2]/3+ff[3]/6;
+		w += gg[0]/6+gg[1]/3+gg[2]/3+gg[3]/6;
+		// condition of end
+		end = end || k>=n || u<0 || v<0 || u>1 || v>1 || w<0 || w>1;
+	} while(!end);
+	else do{
+		mglPoint dif;
+		mreal xu,xv,xw,yu,yv,yw,zv,zu,zw,det,xx,yy,zz;
+		pp[k].x = x->Spline1(dif,u,v,w);	xu=dif.x;	xv=dif.y;	xw=dif.z;
+		pp[k].y = y->Spline1(dif,u,v,w);	yu=dif.x;	yv=dif.y;	yw=dif.z;
+		pp[k].z = z->Spline1(dif,u,v,w);	zu=dif.x;	zv=dif.y;	zw=dif.z;
+		xx = ax->Spline1(u,v,w);	yy = ay->Spline1(u,v,w);	zz = az->Spline1(u,v,w);
+		det = -xu*yv*zw+xv*yu*zw+xu*yw*zv-xw*yu*zv-xv*yw*zu+xw*yv*zu;
+		e = (-xv*yw*zz+xw*yv*zz+xv*yy*zw-xx*yv*zw-xw*yy*zv+xx*yw*zv)/det;
+		f = (xu*yw*zz-xw*yu*zz-xu*yy*zw+xx*yu*zw+xw*yy*zu-xx*yw*zu)/det;
+		g = (-xu*yv*zz+xv*yu*zz+xu*yy*zv-xx*yu*zv-xv*yy*zu+xx*yv*zu)/det;
+		if(mgl_isbad(e+f+g))	end = true;
+		else	for(long m=0;m<k-1;m+=10)	// determines encircle
+			if(mgl_anorm((pp[k]-pp[m])/dx)<acc)	end = true;
+		if(end)	break;
+		h = sqrt(e*e+f*f+g*g);	pp[k].c = gr->GetC(ss,s*h);
+		if(h<1e-5)	break;	// stationary point
+		if(k==0 || mgl_anorm((pp[k]-pp[k-1])/nx)>=1)	k++;
+		// find next point by midpoint method
+		h+=1;	ee[0]=e*dt/h;	ff[0]=f*dt/h;	gg[0]=g*dt/h;
+		u1 = u+ee[0]/2;	v1 = v+ff[0]/2;	w1 = w+gg[0]/2;
+		x->Spline1(dif,u1,v1,w1);	xu=dif.x;	xv=dif.y;	xw=dif.z;	xx = ax->Spline1(u1,v1,w1);
+		y->Spline1(dif,u1,v1,w1);	yu=dif.x;	yv=dif.y;	yw=dif.z;	yy = ay->Spline1(u1,v1,w1);
+		z->Spline1(dif,u1,v1,w1);	zu=dif.x;	zv=dif.y;	zw=dif.z;	zz = az->Spline1(u1,v1,w1);
+		det = -xu*yv*zw+xv*yu*zw+xu*yw*zv-xw*yu*zv-xv*yw*zu+xw*yv*zu;
+		e = (-xv*yw*zz+xw*yv*zz+xv*yy*zw-xx*yv*zw-xw*yy*zv+xx*yw*zv)/det;
+		f = (xu*yw*zz-xw*yu*zz-xu*yy*zw+xx*yu*zw+xw*yy*zu-xx*yw*zu)/det;
+		g = (-xu*yv*zz+xv*yu*zz+xu*yy*zv-xx*yu*zv-xv*yy*zu+xx*yv*zu)/det;
+		h = 1+sqrt(e*e+f*f+g*g);
+		ee[1]=e*dt/h;	ff[1]=f*dt/h;	gg[1]=g*dt/h;
+		u1 = u+ee[1]/2;	v1 = v+ff[1]/2;	w1 = w+gg[1]/2;
+		x->Spline1(dif,u1,v1,w1);	xu=dif.x;	xv=dif.y;	xw=dif.z;	xx = ax->Spline1(u1,v1,w1);
+		y->Spline1(dif,u1,v1,w1);	yu=dif.x;	yv=dif.y;	yw=dif.z;	yy = ay->Spline1(u1,v1,w1);
+		z->Spline1(dif,u1,v1,w1);	zu=dif.x;	zv=dif.y;	zw=dif.z;	zz = az->Spline1(u1,v1,w1);
+		det = -xu*yv*zw+xv*yu*zw+xu*yw*zv-xw*yu*zv-xv*yw*zu+xw*yv*zu;
+		e = (-xv*yw*zz+xw*yv*zz+xv*yy*zw-xx*yv*zw-xw*yy*zv+xx*yw*zv)/det;
+		f = (xu*yw*zz-xw*yu*zz-xu*yy*zw+xx*yu*zw+xw*yy*zu-xx*yw*zu)/det;
+		g = (-xu*yv*zz+xv*yu*zz+xu*yy*zv-xx*yu*zv-xv*yy*zu+xx*yv*zu)/det;
+		h = 1+sqrt(e*e+f*f+g*g);
+		ee[2]=e*dt/h;	ff[2]=f*dt/h;	gg[2]=g*dt/h;
+		u1 = u+ee[2];	v1 = v+ff[2];	w1 = w+gg[2];
+		x->Spline1(dif,u1,v1,w1);	xu=dif.x;	xv=dif.y;	xw=dif.z;	xx = ax->Spline1(u1,v1,w1);
+		y->Spline1(dif,u1,v1,w1);	yu=dif.x;	yv=dif.y;	yw=dif.z;	yy = ay->Spline1(u1,v1,w1);
+		z->Spline1(dif,u1,v1,w1);	zu=dif.x;	zv=dif.y;	zw=dif.z;	zz = az->Spline1(u1,v1,w1);
+		det = -xu*yv*zw+xv*yu*zw+xu*yw*zv-xw*yu*zv-xv*yw*zu+xw*yv*zu;
+		e = (-xv*yw*zz+xw*yv*zz+xv*yy*zw-xx*yv*zw-xw*yy*zv+xx*yw*zv)/det;
+		f = (xu*yw*zz-xw*yu*zz-xu*yy*zw+xx*yu*zw+xw*yy*zu-xx*yw*zu)/det;
+		g = (-xu*yv*zz+xv*yu*zz+xu*yy*zv-xx*yu*zv-xv*yy*zu+xx*yv*zu)/det;
+		h = 1+sqrt(e*e+f*f+g*g);
+		ee[3]=e*dt/h;	ff[3]=f*dt/h;	gg[3]=g*dt/h;
+		u += ee[0]/6+ee[1]/3+ee[2]/3+ee[3]/6;
+		v += ff[0]/6+ff[1]/3+ff[2]/3+ff[3]/6;
+		w += gg[0]/6+gg[1]/3+gg[2]/3+gg[3]/6;
+		// condition of end
+		end = end || k>=n || u<0 || v<0 || u>1 || v>1 || w<0 || w>1;
+	} while(!end);
+	if(k>1)
+	{
+		long j,a=long(gr->GetArrowSize()/fabs(dt));
+		mreal rr = mgl_anorm(gr->Max-gr->Min)*gr->BarWidth/25, ll;
+		mglPoint q1,q2,l;
+		long n1=-1,n2=-1,n3=-1,n4=-1;
+
+		gr->Reserve(4*k);	j = gr->AddPnt(pp[0],pp[0].c);
+		l = pp[1] - pp[0];	l /= mgl_anorm(l);
+		q1.Set(l.y,-l.x,0);	ll = mgl_anorm(q1);
+		if(ll)	q1 /= ll;	else	q1.Set(0,1,0);
+		q2 = q1^l;
+		if(xo)	{	n1 = gr->AddPnt(pp[0],-1,q2);	n2 = gr->AddPnt(pp[0]+rr*q1,-1,q2);	}
+		if(zo)	{	n3 = gr->AddPnt(pp[0],-1,q1);	n4 = gr->AddPnt(pp[0]+rr*q2,-1,q1);	}
+		for(long i=1;i<k;i++)
+		{
+			long jj=j;	j = gr->AddPnt(pp[i],pp[i].c);
+			if(vv && i%a==0)
+			{
+				if(dt<0)	gr->vect_plot(j,jj,a/3);
+				else		gr->vect_plot(jj,j,a/3);
+			}
+			else	gr->line_plot(jj,j);
+			l = pp[i]-pp[i-1];		l /= mgl_anorm(l);
+			q1 -= l*(l*q1);	q1/= mgl_anorm(q1);	q2 = q1^l;
+			long m1 = n1, m2 = n2, m3 = n3, m4 = n4;
+			if(xo)
+			{	n1 = gr->AddPnt(pp[i],-1,q2);	n2 = gr->AddPnt(pp[i]+rr*q1,-1,q2);	gr->quad_plot(n1,n2,m1,m2);	}
+			if(zo)
+			{	n3 = gr->AddPnt(pp[i],-1,q1);	n4 = gr->AddPnt(pp[i]+rr*q2,-1,q1);	gr->quad_plot(n3,n4,m3,m4);	}
+		}
+	}
+	delete []pp;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_flow_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT ax, HCDT ay, HCDT az, const char *sch, const char *opt)
+{
+	if(mgl_check_vec3(gr,x,y,z,ax,ay,az,"Flow3"))	return;
+
+	mreal r = gr->SaveState(opt);
+	long num = mgl_isnan(r)?3:long(r+0.5);
+	static int cgid=1;	gr->StartGroup("Flow3",cgid++);
+	bool cnt=!mglchr(sch,'#');
+	long ss = gr->AddTexture(sch);
+	bool vv = mglchr(sch,'v'), xo = mglchr(sch,'x'), zo = mglchr(sch,'z');
+
+	std::vector<mreal> u, v, w;
+	for(long i=0;i<num;i++)	for(long j=0;j<num;j++)
+	{
+		mreal t = (i+1.)/(num+1.), s = (j+1.)/(num+1.);
+		u.push_back(t);		v.push_back(s);		w.push_back(0);
+		u.push_back(-t);	v.push_back(-s);	w.push_back(0);
+		u.push_back(t);		v.push_back(s);		w.push_back(1);
+		u.push_back(-t);	v.push_back(-s);	w.push_back(-1);
+
+		u.push_back(t);		v.push_back(0);		w.push_back(s);
+		u.push_back(-t);	v.push_back(0);		w.push_back(-s);
+		u.push_back(t);		v.push_back(1);		w.push_back(s);
+		u.push_back(-t);	v.push_back(-1);	w.push_back(-s);
+
+		u.push_back(0);		v.push_back(s);		w.push_back(t);
+		u.push_back(0);		v.push_back(-s);	w.push_back(-t);
+		u.push_back(1);		v.push_back(s);		w.push_back(t);
+		u.push_back(-1);	v.push_back(-s);	w.push_back(-t);
+		if(cnt)
+		{
+			u.push_back(t);		v.push_back(s);		w.push_back(0.5);
+			u.push_back(-t);	v.push_back(-s);	w.push_back(-0.5);
+			u.push_back(t);		v.push_back(0.5);	w.push_back(s);
+			u.push_back(-t);	v.push_back(-0.5);	w.push_back(-s);
+			u.push_back(0.5);	v.push_back(s);		w.push_back(t);
+			u.push_back(-0.5);	v.push_back(-s);	w.push_back(-t);
+		}
+	}
+#pragma omp parallel for
+	for(long i=0;i<long(u.size());i++)	if(!gr->NeedStop())
+		flow(gr, u[i], v[i], w[i], x, y, z, ax, ay, az,ss,vv,xo,zo);
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_flow_3d(HMGL gr, HCDT ax, HCDT ay, HCDT az, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(ax->GetNx()), y(ax->GetNy()), z(ax->GetNz());	// NOTE mglDataV here is useless
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	z.Fill(gr->Min.z,gr->Max.z);
+	mgl_flow_xyz(gr,&x,&y,&z,ax,ay,az,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_flow_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *ax, uintptr_t *ay, uintptr_t *az, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_flow_xyz(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(ax), _DA_(ay), _DA_(az), s, o);	delete []o;	delete []s;	}
+void MGL_EXPORT mgl_flow_3d_(uintptr_t *gr, uintptr_t *ax, uintptr_t *ay, uintptr_t *az, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_flow_3d(_GR_, _DA_(ax), _DA_(ay), _DA_(az), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_flowp_xyz(HMGL gr, double x0, double y0, double z0, HCDT x, HCDT y, HCDT z, HCDT ax, HCDT ay, HCDT az, const char *sch, const char *opt)
+{
+	mglPoint p(x0,y0,z0);
+	mreal u,v,w;
+	long n=ax->GetNx(),m=ax->GetNy(),l=ax->GetNz();
+	bool nboth = !(x->GetNN()==n*m*l && y->GetNN()==n*m*l && z->GetNN()==n*m*l);
+	if(mgl_check_vec3(gr,x,y,z,ax,ay,az,"FlowP3"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("FlowP3",cgid++);
+	long ss = gr->AddTexture(sch);
+	bool vv = mglchr(sch,'v'), xo = mglchr(sch,'x'), zo = mglchr(sch,'z');
+
+	// find coordinates u, v, w
+	mreal dm=INFINITY;
+	long i0=0,j0=0,k0=0;
+	mreal dx,dy,dz;
+	for(long i=0;i<n;i++)	for(long j=0;j<m;j++)	for(long k=0;k<l;k++)	// first find closest
+	{
+		if(nboth)
+		{	dx = x->v(i)-p.x;	dy = y->v(j)-p.y;	dz = x->v(k)-p.z;	}
+		else
+		{	dx = x->v(i,j,k)-p.x;	dy = y->v(i,j,k)-p.y;	dz = x->v(i,j,k)-p.z;	}
+		mreal d = sqrt(dx*dx+dy*dy+dz*dz);
+		if(d<dm)	{	i0=i;	j0=j;	k0=k;	dm=d;	}
+	}
+	if(dm==0)	// we find it
+	{	u=i0/mreal(n);	v=j0/mreal(m);	w=k0/mreal(l);	}
+	else
+	{
+		mreal dxu,dxv,dxw,dyu,dyv,dyw,dzu,dzv,dzw;
+		if(nboth)
+		{
+			dx = x->v(i0)-p.x;	dy = y->v(j0)-p.y;	dz = z->v(k0)-p.z;
+			dxu= x->dvx(i0);	dyv= y->dvx(j0);	dzw= z->dvx(k0);
+			u = (i0+dx/dxu)/n;	v = (j0+dy/dyv)/m;	w = (k0+dz/dzw)/m;
+		}
+		else
+		{
+			dx = x->v(i0,j0,k0)-p.x;	dy = y->v(i0,j0,k0)-p.y;	dz = z->v(i0,j0,k0)-p.z;
+			dxu= x->dvx(i0,j0,k0);		dyu= y->dvx(i0,j0,k0);		dzu= z->dvx(i0,j0,k0);
+			dxv= x->dvy(i0,j0,k0);		dyv= y->dvy(i0,j0,k0);		dzv= z->dvy(i0,j0,k0);
+			dxw= x->dvz(i0,j0,k0);		dyw= y->dvz(i0,j0,k0);		dzw= z->dvz(i0,j0,k0);
+			mreal d = dxu*(dyw*dzv-dyv*dzw)+dxv*(dyu*dzw-dyw*dzu)+dxw*(dyv*dzu-dyu*dzv);
+			u = (i0+(dx*(dyw*dzv-dyv*dzw)+dxv*(dy*dzw-dyw*dz)+dxw*(dyv*dz-dy*dzv))/d)/n;
+			v = (j0-(dx*(dyw*dzu-dyu*dzw)+dxu*(dy*dzw-dyw*dz)+dxw*(dyu*dz-dy*dzu))/d)/m;
+			w = (i0+(dx*(dyv*dzu-dyu*dzv)+dxu*(dy*dzv-dyv*dz)+dxv*(dyu*dz-dy*dzu))/d)/l;
+		}
+	}
+	flow(gr, u, v, w, x, y, z, ax, ay, az,ss,vv,xo,zo);
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_flowp_3d(HMGL gr, double x0, double y0, double z0, HCDT ax, HCDT ay, HCDT az, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(ax->GetNx()), y(ax->GetNy()), z(ax->GetNz());	// NOTE mglDataV here is useless
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	z.Fill(gr->Min.z,gr->Max.z);
+	mgl_flowp_xyz(gr, x0,y0,z0, &x,&y,&z,ax,ay,az,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_flowp_xyz_(uintptr_t *gr, mreal *x0, mreal *y0, mreal *z0, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *ax, uintptr_t *ay, uintptr_t *az, const char *sch, const char *opt, int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_flowp_xyz(_GR_, *x0,*y0,*z0, _DA_(x), _DA_(y), _DA_(z), _DA_(ax), _DA_(ay), _DA_(az), s, o);
+	delete []o;	delete []s;	}
+void MGL_EXPORT mgl_flowp_3d_(uintptr_t *gr, mreal *x0, mreal *y0, mreal *z0, uintptr_t *ax, uintptr_t *ay, uintptr_t *az, const char *sch, const char *opt, int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_flowp_3d(_GR_, *x0,*y0,*z0, _DA_(ax), _DA_(ay), _DA_(az), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Grad series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_grad_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT phi, const char *sch, const char *opt)
+{
+	mglData ax(phi), ay,az,xx,yy,zz;
+	ay.Set(ax);	az.Set(ax);	xx.Set(ax);	yy.Set(ax);	zz.Set(ax);
+	long n=xx.nx, m=xx.ny, l=xx.nz, nn = n*m*l;
+	if(x->GetNN()==nn && y->GetNN()==nn && z->GetNN()==nn)
+	{	xx.Set(x);	yy.Set(y);	zz.Set(z);	}	// nothing to do
+	else if(x->GetNx()==n && y->GetNx()==m && z->GetNx()==l)
+#pragma omp parallel for collapse(3)
+		for(long i=0;i<n;i++)	for(long j=0;j<m;j++)	for(long k=0;k<l;k++)
+		{
+			long i0 = i+n*(j+m*k);
+			xx.a[i0] = x->v(i);	yy.a[i0] = y->v(j);	zz.a[i0] = z->v(k);
+		}
+	else	{	gr->SetWarn(mglWarnDim,"Grad");	return;	}
+	ax.Diff(xx,yy,zz);	ay.Diff(yy,xx,zz);	az.Diff(zz,xx,yy);
+	mgl_flow_xyz(gr,&xx,&yy,&zz,&ax,&ay,&az,sch,opt);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_grad_xy(HMGL gr, HCDT x, HCDT y, HCDT phi, const char *sch, const char *opt)
+{
+	mglData ax(phi), ay,xx,yy;
+	ay.Set(ax);	xx.Set(ax);	yy.Set(ax);
+	long n = phi->GetNx(), m=phi->GetNy(), nn=n*m;
+	if(x->GetNx()*x->GetNy()==nn && y->GetNx()*y->GetNy()==nn)	{	xx.Set(x);	yy.Set(y);	}
+	else if(x->GetNx()==n && y->GetNx()==m)
+#pragma omp parallel for collapse(2)
+		for(long i=0;i<n;i++)	for(long j=0;j<m;j++)
+		{	long i0 = i+n*j;	xx.a[i0] = x->v(i);	yy.a[i0] = y->v(j);	}
+	else	{	gr->SetWarn(mglWarnDim,"Grad");	return;	}
+	ax.Diff(xx,yy);	ay.Diff(yy,xx);
+	mgl_flow_xy(gr,&xx,&yy,&ax,&ay,sch,opt);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_grad(HMGL gr, HCDT phi, const char *sch, const char *opt)
+{
+	mglDataV x(phi->GetNx()), y(phi->GetNy()), z(phi->GetNz());
+	gr->SaveState(opt);
+	x.Fill(gr->Min.x,gr->Max.x);	y.Fill(gr->Min.y,gr->Max.y);	z.Fill(gr->Min.z,gr->Max.z);
+	if(phi->GetNz()==1)	mgl_grad_xy(gr,&x,&y,phi,sch,0);
+	else				mgl_grad_xyz(gr,&x,&y,&z,phi,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_grad_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *ph, const char *sch, const char *opt, int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_grad_xyz(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(ph), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_grad_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *ph, const char *sch, const char *opt, int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_grad_xy(_GR_, _DA_(x), _DA_(y), _DA_(ph), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_grad_(uintptr_t *gr, uintptr_t *ph, const char *sch, const char *opt, int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_grad(_GR_, _DA_(ph), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Pipe 2d series
+//
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT flowr(mglBase *gr, double zVal, double u, double v, HCDT x, HCDT y, HCDT ax, HCDT ay, double r0,long sc)
+{
+	long n=100*(ax->GetNx()+ax->GetNy());
+	bool nboth = x->GetNx()*x->GetNy()!=ax->GetNx()*ax->GetNy() || y->GetNx()*y->GetNy()!=ax->GetNx()*ax->GetNy();
+
+	mglPoint *pp = new mglPoint[n], dp;
+	mreal *cc = new mreal[n];
+	mglPoint dx(1/fabs(gr->Max.x-gr->Min.x),1/fabs(gr->Max.y-gr->Min.y),1/fabs(gr->Max.z-gr->Min.z));
+	mglPoint nx(ax->GetNx(),ax->GetNy());
+
+	mreal dt = 0.5/(ax->GetNx() > ax->GetNy() ? ax->GetNx() : ax->GetNy()),e,f,g,ff[4],gg[4],h,s=2,acc=dt/20;
+	mreal ss = 16./mgl_ipow(gr->Max.c - gr->Min.c,2);
+	if(u<0 || v<0)	{	dt = -dt;	u = -u;	v = -v;	s *= -1;}
+	long k=0;
+	bool end = false;
+	if(nboth) do{
+		mglPoint dif;
+		pp[k].x = x->Spline1(dif,u,0,0);	f = ax->Spline1(u,v,0)/dif.x;
+		pp[k].y = y->Spline1(dif,v,0,0);	g = ay->Spline1(u,v,0)/dif.x;
+		pp[k].z = zVal;
+		if(mgl_isbad(f+g))	end = true;
+		else	for(long m=0;m<k-1;m+=10)	// determines encircle
+			if(mgl_anorm((pp[k]-pp[m])/dx)<acc)	end = true;
+		if(end)	break;
+		h = hypot(f,g);	cc[k] = gr->GetC(sc,s*h);
+		pp[k].c = r0>0 ? r0*sqrt(1e-2+ss*h*h)/2 : -r0/sqrt(1e-2+ss*h*h)/5;
+		if(h<1e-5)	break;	// stationary point
+		if(k==0 || mgl_anorm((pp[k]-pp[k-1])/nx)>=1)	k++;
+		// find next point by midpoint method
+		h+=1;	ff[0]=f*dt/h;	gg[0]=g*dt/h;
+		e = u+ff[0]/2;	h = v+gg[0]/2;
+		x->Spline1(dif,e,0,0);	f = ax->Spline1(e,h,0)/dif.x;
+		y->Spline1(dif,h,0,0);	g = ay->Spline1(e,h,0)/dif.x;
+		h = 1+hypot(f,g);	ff[1]=f*dt/h;	gg[1]=g*dt/h;
+		e = u+ff[1]/2;	h = v+gg[1]/2;
+		x->Spline1(dif,e,0,0);	f = ax->Spline1(e,h,0)/dif.x;
+		y->Spline1(dif,h,0,0);	g = ay->Spline1(e,h,0)/dif.x;
+		h = 1+hypot(f,g);	ff[2]=f*dt/h;	gg[2]=g*dt/h;
+		e = u+ff[2];	h = v+gg[2];
+		x->Spline1(dif,e,0,0);	f = ax->Spline1(e,h,0)/dif.x;
+		y->Spline1(dif,h,0,0);	g = ay->Spline1(e,h,0)/dif.x;
+		h = 1+hypot(f,g);	ff[3]=f*dt/h;	gg[3]=g*dt/h;
+		u += ff[0]/6+ff[1]/3+ff[2]/3+ff[3]/6;
+		v += gg[0]/6+gg[1]/3+gg[2]/3+gg[3]/6;
+		// condition of end
+		end = end || k>=n || u<0 || v<0 || u>1 || v>1;
+	} while(!end);
+	else do{
+		mglPoint dif;
+		mreal xu,xv,yu,yv,det,xx,yy;
+			pp[k].x = x->Spline1(dif,u,v,0);	xu=dif.x;	xv=dif.y;
+			pp[k].y = y->Spline1(dif,u,v,0);	yu=dif.x;	yv=dif.y;
+			xx = ax->Spline1(u,v,0);	yy = ay->Spline1(u,v,0);
+			det = xv*yu-xu*yv;	f = (yy*xv-xx*yv)/det;	g = (xx*yu-yy*xu)/det;
+		pp[k].z = zVal;
+		if(mgl_isbad(f+g))	end = true;
+		else	for(long m=0;m<k-1;m+=10)	// determines encircle
+			if(mgl_anorm((pp[k]-pp[m])/dx)<acc)	end = true;
+		if(end)	break;
+		h = hypot(f,g);	cc[k] = gr->GetC(sc,s*h);
+		pp[k].c = r0>0 ? r0*sqrt(1e-2+ss*h*h)/2 : -r0/sqrt(1e-2+ss*h*h)/5;
+		if(h<1e-5)	break;	// stationary point
+		if(k==0 || mgl_anorm((pp[k]-pp[k-1])/nx)>=1)	k++;
+		// find next point by midpoint method
+		h+=1;	ff[0]=f*dt/h;	gg[0]=g*dt/h;
+		e = u+ff[0]/2;	h = v+gg[0]/2;
+			x->Spline1(dif,e,h,0);	xu=dif.x;	xv=dif.y;
+			y->Spline1(dif,e,h,0);	yu=dif.x;	yv=dif.y;
+			xx = ax->Spline1(e,h,0);	yy = ay->Spline1(e,h,0);
+			det = xv*yu-xu*yv;	f = (yy*xv-xx*yv)/det;	g = (xx*yu-yy*xu)/det;
+		h = 1+hypot(f,g);	ff[1]=f*dt/h;	gg[1]=g*dt/h;
+		e = u+ff[1]/2;	h = v+gg[1]/2;
+			x->Spline1(dif,e,h,0);	xu=dif.x;	xv=dif.y;
+			y->Spline1(dif,e,h,0);	yu=dif.x;	yv=dif.y;
+			xx = ax->Spline1(e,h,0);	yy = ay->Spline1(e,h,0);
+			det = xv*yu-xu*yv;	f = (yy*xv-xx*yv)/det;	g = (xx*yu-yy*xu)/det;
+		h = 1+hypot(f,g);	ff[2]=f*dt/h;	gg[2]=g*dt/h;
+		e = u+ff[2];	h = v+gg[2];
+			x->Spline1(dif,e,h,0);	xu=dif.x;	xv=dif.y;
+			y->Spline1(dif,e,h,0);	yu=dif.x;	yv=dif.y;
+			xx = ax->Spline1(e,h,0);	yy = ay->Spline1(e,h,0);
+			det = xv*yu-xu*yv;	f = (yy*xv-xx*yv)/det;	g = (xx*yu-yy*xu)/det;
+		h = 1+hypot(f,g);	ff[3]=f*dt/h;	gg[3]=g*dt/h;
+		u += ff[0]/6+ff[1]/3+ff[2]/3+ff[3]/6;
+		v += gg[0]/6+gg[1]/3+gg[2]/3+gg[3]/6;
+		// condition of end
+		end = end || k>=n || u<0 || v<0 || u>1 || v>1;
+	} while(!end);
+	if(k>1)
+	{
+		int num=!(gr->GetQuality()&3)?13:25;
+		long *id=new long[2*num];
+		mglPoint p,l=pp[1]-pp[0],t,q,d;
+		t = !l;	t.Normalize();	q = t^l;	q.Normalize();
+		mreal rr=pp[0].c,dr=l.c;
+		gr->Reserve(num*k);
+
+		for(long j=0;j<num;j++)
+		{
+			int fi=j*360/(num-1);
+			float co = mgl_cos[fi%360], si = mgl_cos[(270+fi)%360];
+			p = pp[0] + t*(rr*co) + q*(rr*si);
+			d = (t*si - q*co)^(l + t*(dr*co) + q*(dr*si));
+			id[j] = gr->AddPnt(p,cc[0],d);
+		}
+		for(long i=1;i<k;i++)
+		{
+			if(i<k-1)	l = pp[i+1]-pp[i-1];
+			else	l = pp[i]-pp[i-1];
+			t = !l;	t.Normalize();	q = t^l;	q.Normalize();
+			rr=pp[i].c;	dr=l.c;
+			memcpy(id+num,id,num*sizeof(long));
+			for(long j=0;j<num;j++)
+			{
+				int fi=j*360/(num-1);
+				float co = mgl_cos[fi%360], si = mgl_cos[(270+fi)%360];
+				p = pp[i] + t*(rr*co) + q*(rr*si);
+				d = (t*si - q*co)^(l + t*(dr*co) + q*(dr*si));
+				id[j] = gr->AddPnt(p,cc[i],d);
+				if(j>0)	gr->quad_plot(id[j-1],id[j],id[j+num-1],id[j+num]);
+			}
+		}
+		delete []id;
+	}
+	delete []pp;	delete []cc;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_pipe_xy(HMGL gr, HCDT x, HCDT y, HCDT ax, HCDT ay, const char *sch, double r0, const char *opt)
+{
+	if(mgl_check_dim2(gr,x,y,ax,ay,"Pipe"))	return;
+
+	mreal r = gr->SaveState(opt);
+	long num = mgl_isnan(r)?5:long(r+0.5);
+	static int cgid=1;	gr->StartGroup("Pipe",cgid++);
+
+	long ss = gr->AddTexture(sch);
+	// allocate memory
+	mreal zVal = gr->Min.z;
+	bool cnt=!mglchr(sch,'#');
+	if(mglchr(sch,'i'))	r0 = -fabs(r0);
+
+	std::vector<mreal> u, v;
+	if(mglchr(sch,'*'))	for(long i=0;i<num;i++)	for(long j=0;j<num;j++)
+	{
+		mreal t = (i+1.)/(num+1.), s = (j+1.)/(num+1.);
+		u.push_back(s);		v.push_back(t);
+		u.push_back(-s);		v.push_back(-t);
+	}
+	else	for(long i=0;i<num;i++)
+	{
+		mreal t = (i+1.)/(num+1.);
+		u.push_back(0);		v.push_back(t);
+		u.push_back(0);		v.push_back(-t);
+		u.push_back(1);		v.push_back(t);
+		u.push_back(-1);	v.push_back(-t);
+		u.push_back(t);		v.push_back(0);
+		u.push_back(-t);	v.push_back(0);
+		u.push_back(t);		v.push_back(1);
+		u.push_back(-t);	v.push_back(-1);
+		if(cnt)
+		{
+			u.push_back(t);		v.push_back(0.5);
+			u.push_back(-t);	v.push_back(-0.5);
+			u.push_back(0.5);	v.push_back(t);
+			u.push_back(-0.5);	v.push_back(-t);
+		}
+	}
+	for(long k=0;k<ax->GetNz();k++)
+	{
+		if(gr->NeedStop())	break;
+		if(ax->GetNz()>1)	zVal = gr->Min.z+(gr->Max.z-gr->Min.z)*mreal(k)/(ax->GetNz()-1);
+		HMDT bx=mgl_data_subdata(ax,-1,-1,k), by=mgl_data_subdata(ay,-1,-1,k);
+#pragma omp parallel for
+		for(long i=0;i<long(u.size());i++)	if(!gr->NeedStop())
+			flowr(gr, zVal, u[i], v[i], x, y, bx, by,r0,ss);
+		mgl_delete_data(bx);	mgl_delete_data(by);
+	}
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_pipe_2d(HMGL gr, HCDT ax, HCDT ay, const char *sch, double r0, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(ax->GetNx()), y(ax->GetNy());	// NOTE mglDataV here is useless
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	mgl_pipe_xy(gr,&x,&y,ax,ay,sch,r0,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_pipe_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *ax, uintptr_t *ay, const char *sch, mreal *r0, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_pipe_xy(_GR_, _DA_(x), _DA_(y), _DA_(ax), _DA_(ay), s, *r0, o);	delete []o;	delete []s;	}
+void MGL_EXPORT mgl_pipe_2d_(uintptr_t *gr, uintptr_t *ax, uintptr_t *ay, const char *sch, mreal *r0, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_pipe_2d(_GR_, _DA_(ax), _DA_(ay), s, *r0, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Pipe 3d series
+//
+//-----------------------------------------------------------------------------
+void flowr(mglBase *gr, double u, double v, double w, HCDT x, HCDT y, HCDT z, HCDT ax, HCDT ay, HCDT az, double r0,long sc)
+{
+	static long n=100*(ax->GetNx()+ax->GetNy()+ax->GetNz());
+	long nn = ax->GetNN();
+	bool nboth = x->GetNN()!=nn || y->GetNN()!=nn || z->GetNN()!=nn;
+	mglPoint *pp = new mglPoint[n], dp;
+	mreal *cc = new mreal[n];
+	mglPoint dx(1/fabs(gr->Max.x-gr->Min.x),1/fabs(gr->Max.y-gr->Min.y),1/fabs(gr->Max.z-gr->Min.z));
+	mglPoint nx(ax->GetNx(),ax->GetNy(),ax->GetNz());
+
+	nn = (ax->GetNx() > ax->GetNy() ? ax->GetNx() : ax->GetNy());
+	nn = (nn > ax->GetNz() ? nn : ax->GetNz());
+	mreal dt = 0.2/nn, e,f,g,ee[4],ff[4],gg[4],h,s=2,u1,v1,w1,acc=dt/20;
+	mreal ss = 16./mgl_ipow(gr->Max.c - gr->Min.c,2);
+
+	if(u<0 || v<0 || w<0)
+	{	dt = -dt;	u = -u;	v = -v;	w = -w;	s *= -1;}
+	long k=0;
+	bool end = false;
+	if(nboth) do{
+		mglPoint dif;
+		pp[k].x = x->Spline1(dif,u,0,0);	e = ax->Spline1(u,v,w)/dif.x;
+		pp[k].y = y->Spline1(dif,v,0,0);	f = ay->Spline1(u,v,w)/dif.x;
+		pp[k].z = z->Spline1(dif,w,0,0);	g = az->Spline1(u,v,w)/dif.x;
+		if(mgl_isbad(e+f+g))	end = true;
+		else	for(long m=0;m<k-1;m+=10)	// determines encircle
+			if(mgl_anorm((pp[k]-pp[m])/dx)<acc)	end = true;
+		if(end)	break;
+		h = sqrt(e*e+f*f+g*g);	cc[k] = gr->GetC(sc,s*h);
+		pp[k].c = r0>0 ? r0*sqrt(1e-2+ss*h*h)/2 : -r0/sqrt(1e-2+ss*h*h)/5;
+		if(h<1e-5)	break;	// stationary point
+		if(k==0 || mgl_anorm((pp[k]-pp[k-1])/nx)>=1)	k++;
+		// find next point by midpoint method
+		h+=1;	ee[0]=e*dt/h;	ff[0]=f*dt/h;	gg[0]=g*dt/h;
+		u1 = u+ee[0]/2;	v1 = v+ff[0]/2;	w1 = w+gg[0]/2;
+		x->Spline1(dif,u1,0,0);	e = ax->Spline1(u1,v1,w1)/dif.x;
+		y->Spline1(dif,v1,0,0);	f = ay->Spline1(u1,v1,w1)/dif.x;
+		z->Spline1(dif,w1,0,0);	g = az->Spline1(u1,v1,w1)/dif.x;
+		h = 1+sqrt(e*e+f*f+g*g);
+		ee[1]=e*dt/h;	ff[1]=f*dt/h;	gg[1]=g*dt/h;
+		u1 = u+ee[1]/2;	v1 = v+ff[1]/2;	w1 = w+gg[1]/2;
+		x->Spline1(dif,u1,0,0);	e = ax->Spline1(u1,v1,w1)/dif.x;
+		y->Spline1(dif,v1,0,0);	f = ay->Spline1(u1,v1,w1)/dif.x;
+		z->Spline1(dif,w1,0,0);	g = az->Spline1(u1,v1,w1)/dif.x;
+		h = 1+sqrt(e*e+f*f+g*g);
+		ee[2]=e*dt/h;	ff[2]=f*dt/h;	gg[2]=g*dt/h;
+		u1 = u+ee[2];	v1 = v+ff[2];	w1 = w+gg[2];
+		x->Spline1(dif,u1,0,0);	e = ax->Spline1(u1,v1,w1)/dif.x;
+		y->Spline1(dif,v1,0,0);	f = ay->Spline1(u1,v1,w1)/dif.x;
+		z->Spline1(dif,w1,0,0);	g = az->Spline1(u1,v1,w1)/dif.x;
+		h = 1+sqrt(e*e+f*f+g*g);
+		ee[3]=e*dt/h;	ff[3]=f*dt/h;	gg[3]=g*dt/h;
+		u += ee[0]/6+ee[1]/3+ee[2]/3+ee[3]/6;
+		v += ff[0]/6+ff[1]/3+ff[2]/3+ff[3]/6;
+		w += gg[0]/6+gg[1]/3+gg[2]/3+gg[3]/6;
+		// condition of end
+		end = end || k>=n || u<0 || v<0 || u>1 || v>1 || w<0 || w>1;
+	} while(!end);
+	else do{
+		mglPoint dif;
+		mreal xu,xv,xw,yu,yv,yw,zv,zu,zw,det,xx,yy,zz;
+		pp[k].x = x->Spline1(dif,u,v,w);	xu=dif.x;	xv=dif.y;	xw=dif.z;
+		pp[k].y = y->Spline1(dif,u,v,w);	yu=dif.x;	yv=dif.y;	yw=dif.z;
+		pp[k].z = z->Spline1(dif,u,v,w);	zu=dif.x;	zv=dif.y;	zw=dif.z;
+		xx = ax->Spline1(u,v,w);	yy = ay->Spline1(u,v,w);	zz = az->Spline1(u,v,w);
+		det = -xu*yv*zw+xv*yu*zw+xu*yw*zv-xw*yu*zv-xv*yw*zu+xw*yv*zu;
+		e = (-xv*yw*zz+xw*yv*zz+xv*yy*zw-xx*yv*zw-xw*yy*zv+xx*yw*zv)/det;
+		f = (xu*yw*zz-xw*yu*zz-xu*yy*zw+xx*yu*zw+xw*yy*zu-xx*yw*zu)/det;
+		g = (-xu*yv*zz+xv*yu*zz+xu*yy*zv-xx*yu*zv-xv*yy*zu+xx*yv*zu)/det;
+		if(mgl_isbad(e+f+g))	end = true;
+		else	for(long m=0;m<k-1;m+=10)	// determines encircle
+			if(mgl_anorm((pp[k]-pp[m])/dx)<acc)	end = true;
+		if(end)	break;
+		h = sqrt(e*e+f*f+g*g);	cc[k] = gr->GetC(sc,s*h);
+		pp[k].c = r0>0 ? r0*sqrt(1e-2+ss*h*h)/2 : -r0/sqrt(1e-2+ss*h*h)/5;
+		if(h<1e-5)	break;	// stationary point
+		if(k==0 || mgl_anorm((pp[k]-pp[k-1])/nx)>=1)	k++;
+		// find next point by midpoint method
+		h+=1;	ee[0]=e*dt/h;	ff[0]=f*dt/h;	gg[0]=g*dt/h;
+		u1 = u+ee[0]/2;	v1 = v+ff[0]/2;	w1 = w+gg[0]/2;
+		x->Spline1(dif,u1,v1,w1);	xu=dif.x;	xv=dif.y;	xw=dif.z;	xx = ax->Spline1(u1,v1,w1);
+		y->Spline1(dif,u1,v1,w1);	yu=dif.x;	yv=dif.y;	yw=dif.z;	yy = ay->Spline1(u1,v1,w1);
+		z->Spline1(dif,u1,v1,w1);	zu=dif.x;	zv=dif.y;	zw=dif.z;	zz = az->Spline1(u1,v1,w1);
+		det = -xu*yv*zw+xv*yu*zw+xu*yw*zv-xw*yu*zv-xv*yw*zu+xw*yv*zu;
+		e = (-xv*yw*zz+xw*yv*zz+xv*yy*zw-xx*yv*zw-xw*yy*zv+xx*yw*zv)/det;
+		f = (xu*yw*zz-xw*yu*zz-xu*yy*zw+xx*yu*zw+xw*yy*zu-xx*yw*zu)/det;
+		g = (-xu*yv*zz+xv*yu*zz+xu*yy*zv-xx*yu*zv-xv*yy*zu+xx*yv*zu)/det;
+		h = 1+sqrt(e*e+f*f+g*g);
+		ee[1]=e*dt/h;	ff[1]=f*dt/h;	gg[1]=g*dt/h;
+		u1 = u+ee[1]/2;	v1 = v+ff[1]/2;	w1 = w+gg[1]/2;
+		x->Spline1(dif,u1,v1,w1);	xu=dif.x;	xv=dif.y;	xw=dif.z;	xx = ax->Spline1(u1,v1,w1);
+		y->Spline1(dif,u1,v1,w1);	yu=dif.x;	yv=dif.y;	yw=dif.z;	yy = ay->Spline1(u1,v1,w1);
+		z->Spline1(dif,u1,v1,w1);	zu=dif.x;	zv=dif.y;	zw=dif.z;	zz = az->Spline1(u1,v1,w1);
+		det = -xu*yv*zw+xv*yu*zw+xu*yw*zv-xw*yu*zv-xv*yw*zu+xw*yv*zu;
+		e = (-xv*yw*zz+xw*yv*zz+xv*yy*zw-xx*yv*zw-xw*yy*zv+xx*yw*zv)/det;
+		f = (xu*yw*zz-xw*yu*zz-xu*yy*zw+xx*yu*zw+xw*yy*zu-xx*yw*zu)/det;
+		g = (-xu*yv*zz+xv*yu*zz+xu*yy*zv-xx*yu*zv-xv*yy*zu+xx*yv*zu)/det;
+		h = 1+sqrt(e*e+f*f+g*g);
+		ee[2]=e*dt/h;	ff[2]=f*dt/h;	gg[2]=g*dt/h;
+		u1 = u+ee[2];	v1 = v+ff[2];	w1 = w+gg[2];
+		x->Spline1(dif,u1,v1,w1);	xu=dif.x;	xv=dif.y;	xw=dif.z;	xx = ax->Spline1(u1,v1,w1);
+		y->Spline1(dif,u1,v1,w1);	yu=dif.x;	yv=dif.y;	yw=dif.z;	yy = ay->Spline1(u1,v1,w1);
+		z->Spline1(dif,u1,v1,w1);	zu=dif.x;	zv=dif.y;	zw=dif.z;	zz = az->Spline1(u1,v1,w1);
+		det = -xu*yv*zw+xv*yu*zw+xu*yw*zv-xw*yu*zv-xv*yw*zu+xw*yv*zu;
+		e = (-xv*yw*zz+xw*yv*zz+xv*yy*zw-xx*yv*zw-xw*yy*zv+xx*yw*zv)/det;
+		f = (xu*yw*zz-xw*yu*zz-xu*yy*zw+xx*yu*zw+xw*yy*zu-xx*yw*zu)/det;
+		g = (-xu*yv*zz+xv*yu*zz+xu*yy*zv-xx*yu*zv-xv*yy*zu+xx*yv*zu)/det;
+		h = 1+sqrt(e*e+f*f+g*g);
+		ee[3]=e*dt/h;	ff[3]=f*dt/h;	gg[3]=g*dt/h;
+		u += ee[0]/6+ee[1]/3+ee[2]/3+ee[3]/6;
+		v += ff[0]/6+ff[1]/3+ff[2]/3+ff[3]/6;
+		w += gg[0]/6+gg[1]/3+gg[2]/3+gg[3]/6;
+		// condition of end
+		end = end || k>=n || u<0 || v<0 || u>1 || v>1 || w<0 || w>1;
+	} while(!end);
+	if(k>1)
+	{
+		const int num=24;
+		long *id=new long[2*num];
+		mglPoint p,l=pp[1]-pp[0],t,q,d;
+		t = !l;	t.Normalize();	q = t^l;	q.Normalize();
+		mreal rr=pp[0].c,dr=l.c;
+		gr->Reserve(num*k);
+
+		for(long j=0;j<num;j++)
+		{
+			int fi=j*360/(num-1);
+			float co = mgl_cos[fi%360], si = mgl_cos[(270+fi)%360];
+			p = pp[0] + t*(rr*co) + q*(rr*si);
+			d = (t*si - q*co)^(l + t*(dr*co) + q*(dr*si));
+			id[j] = gr->AddPnt(p,cc[0],d);
+		}
+		for(long i=1;i<k;i++)
+		{
+			if(i<k-1)	l = pp[i+1]-pp[i-1];
+			else	l = pp[i]-pp[i-1];
+			t = !l;	t.Normalize();	q = t^l;	q.Normalize();
+			rr=pp[i].c;	dr=l.c;
+			memcpy(id+num,id,num*sizeof(long));
+			for(long j=0;j<num;j++)
+			{
+				int fi=j*360/(num-1);
+				float co = mgl_cos[fi%360], si = mgl_cos[(270+fi)%360];
+				p = pp[i] + t*(rr*co) + q*(rr*si);
+				d = (t*si - q*co)^(l + t*(dr*co) + q*(dr*si));
+				id[j] = gr->AddPnt(p,cc[i],d);
+				if(j>0)	gr->quad_plot(id[j-1],id[j],id[j+num-1],id[j+num]);
+			}
+		}
+		delete []id;
+	}
+	delete []pp;	delete []cc;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_pipe_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT ax, HCDT ay, HCDT az, const char *sch, double r0, const char *opt)
+{
+	if(mgl_check_vec3(gr,x,y,z,ax,ay,az,"Vect"))	return;
+
+	mreal r = gr->SaveState(opt);
+	long num = mgl_isnan(r)?3:long(r+0.5);
+	static int cgid=1;	gr->StartGroup("Pipe3",cgid++);
+	if(mglchr(sch,'i'))	r0 = -fabs(r0);
+
+	long ss = gr->AddTexture(sch);
+	bool cnt=!mglchr(sch,'#');
+
+	std::vector<mreal> u, v, w;
+	for(long i=0;i<num;i++)	for(long j=0;j<num;j++)
+	{
+		mreal t = (i+1.)/(num+1.), s = (j+1.)/(num+1.);
+		u.push_back(t);		v.push_back(s);		w.push_back(0);
+		u.push_back(-t);	v.push_back(-s);	w.push_back(0);
+		u.push_back(t);		v.push_back(s);		w.push_back(1);
+		u.push_back(-t);	v.push_back(-s);	w.push_back(-1);
+
+		u.push_back(t);		v.push_back(0);		w.push_back(s);
+		u.push_back(-t);	v.push_back(0);		w.push_back(-s);
+		u.push_back(t);		v.push_back(1);		w.push_back(s);
+		u.push_back(-t);	v.push_back(-1);	w.push_back(-s);
+
+		u.push_back(0);		v.push_back(s);		w.push_back(t);
+		u.push_back(0);		v.push_back(-s);	w.push_back(-t);
+		u.push_back(1);		v.push_back(s);		w.push_back(t);
+		u.push_back(-1);	v.push_back(-s);	w.push_back(-t);
+		if(cnt)
+		{
+			u.push_back(t);		v.push_back(s);		w.push_back(0.5);
+			u.push_back(-t);	v.push_back(-s);	w.push_back(-0.5);
+			u.push_back(t);		v.push_back(0.5);	w.push_back(s);
+			u.push_back(-t);	v.push_back(-0.5);	w.push_back(-s);
+			u.push_back(0.5);	v.push_back(s);		w.push_back(t);
+			u.push_back(-0.5);	v.push_back(-s);	w.push_back(-t);
+		}
+	}
+#pragma omp parallel for
+	for(long i=0;i<long(u.size());i++)	if(!gr->NeedStop())
+		flowr(gr, u[i], v[i], w[i], x, y, z, ax, ay, az,r0,ss);
+	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_pipe_3d(HMGL gr, HCDT ax, HCDT ay, HCDT az, const char *sch, double r0, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(ax->GetNx()), y(ax->GetNy()), z(ax->GetNz());	// NOTE mglDataV here is useless
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	z.Fill(gr->Min.z,gr->Max.z);
+	mgl_pipe_xyz(gr,&x,&y,&z,ax,ay,az,sch,r0,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_pipe_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *ax, uintptr_t *ay, uintptr_t *az, const char *sch, mreal *r0, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_pipe_xyz(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(ax), _DA_(ay), _DA_(az), s, *r0, o);
+	delete []o;	delete []s;	}
+void MGL_EXPORT mgl_pipe_3d_(uintptr_t *gr, uintptr_t *ax, uintptr_t *ay, uintptr_t *az, const char *sch, mreal *r0, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
+	mgl_pipe_3d(_GR_, _DA_(ax), _DA_(ay), _DA_(az), s, *r0, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
diff --git a/src/volume.cpp b/src/volume.cpp
new file mode 100644
index 0000000..00f1b53
--- /dev/null
+++ b/src/volume.cpp
@@ -0,0 +1,681 @@
+/***************************************************************************
+ * surf.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include "mgl2/define.h"
+#include "mgl2/volume.h"
+#include "mgl2/data.h"
+#include "mgl2/eval.h"
+#include "mgl2/base.h"
+//-----------------------------------------------------------------------------
+//
+//	CloudQ series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cloud_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt)
+{
+	if(!(gr->GetQuality()&3))	return;	// do nothing in fast_draw
+	long n=a->GetNx(),m=a->GetNy(),l=a->GetNz();
+	bool nboth = mgl_isnboth(x,y,z,a);
+	if(mgl_check_dim3(gr,!nboth,x,y,z,a,0,"Cloud"))	return;
+
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Cloud",cgid++);
+
+	long tx=1,ty=1,tz=1;
+	if(gr->MeshNum>1)
+	{
+		tx=(n-1)/(gr->MeshNum-1);	if(tx<1)	tx=1;
+		ty=(m-1)/(gr->MeshNum-1);	if(ty<1)	ty=1;
+		tz=(l-1)/(gr->MeshNum-1);	if(tz<1)	tz=1;
+	}
+
+	mreal	alpha = gr->AlphaDef;
+	bool inv = mglchr(sch,'i');
+	bool dot = mglchr(sch,'.');
+	alpha /= pow(n/tx*m/ty*l/tz,1./3)/20;
+	if(alpha>1)	alpha = 1;
+	long ss = gr->AddTexture(sch);
+
+	// x, y, z -- have the same size as a
+	n /= tx;	m /= ty;	l /= tz;
+	long *pos=new long[n*m*l];
+	gr->Reserve(n*m*l);
+	mglPoint q(NAN);
+	for(long k=0;k<l;k++)
+	{
+		if(gr->NeedStop())	break;
+		for(long j=0;j<m;j++)	for(long i=0;i<n;i++)
+		{
+			mglPoint p = nboth ? mglPoint(x->v(i*tx),y->v(j*ty),z->v(k*tz)) : mglPoint(x->v(i*tx,j*ty,k*tz),y->v(i*tx,j*ty,k*tz),z->v(i*tx,j*ty,k*tz));
+			mreal aa = gr->GetA(a->v(i*tx,j*ty,k*tz));
+			mreal bb = inv ? (1-aa)*(1-aa)*alpha : aa*aa*alpha;
+			pos[i+n*(j+m*k)] = gr->AddPnt(p,gr->GetC(ss,aa,false),q,bb);
+		}
+	}
+	if(dot)	for(long i=0;i<n*m*l;i++)	gr->mark_plot(pos[i],'.');
+	else	for(long k=0;k<l;k++)
+	{
+		if(gr->NeedStop())	break;
+		for(long j=0;j<m;j++)	for(long i=0;i<n;i++)
+		{
+			long i0 = i+n*(j+m*k);
+			if(i<n-1 && j<m-1)	gr->quad_plot(pos[i0],pos[i0+1],pos[i0+n],pos[i0+n+1]);
+			if(i<n-1 && k<l-1)	gr->quad_plot(pos[i0],pos[i0+1],pos[i0+n*m],pos[i0+n*m+1]);
+			if(k<l-1 && j<m-1)	gr->quad_plot(pos[i0],pos[i0+n],pos[i0+n*m],pos[i0+n+n*m]);
+		}
+	}
+	delete []pos;	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cloud(HMGL gr, HCDT a, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(a->GetNx()), y(a->GetNy()),z(a->GetNz());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	z.Fill(gr->Min.z,gr->Max.z);
+	mgl_cloud_xyz(gr,&x,&y,&z,a,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cloud_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_cloud_xyz(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_cloud_(uintptr_t *gr, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_cloud(_GR_, _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Surf3 series
+//
+//-----------------------------------------------------------------------------
+mreal MGL_NO_EXPORT mgl_get_norm(mreal x, mreal d1, mreal d2, mreal d3)
+{
+	mreal nx = d1*(1-x) + d2*x;
+	if(mgl_isbad(nx))
+	{
+		nx = d1*(1+x) - d3*x;
+		if(mgl_isbad(nx))
+		{
+			if(mgl_isfin(d1))	nx = d1;
+			if(mgl_isfin(d2))	nx = d2;
+			if(mgl_isfin(d3))	nx = d3;
+		}
+	}
+	return nx;
+}
+mglPoint MGL_NO_EXPORT mgl_normal_3d(HCDT a, mglPoint p, bool inv, long n,long m,long l)
+{
+	mreal x=p.x, y=p.y, z=p.z;
+	mreal nx=0, ny=0, nz=0;
+	long i=long(x), j=long(y), k=long(z);
+	i = i<n-1 ? i:n-2;	j = j<m-1 ? j:m-2;	k = k<l-1 ? k:l-2;
+	x-=i;	y-=j;	z-=k;
+
+	nx = mgl_get_norm(x, a->dvx(i,j,k), a->dvx(i+1,j,k), i>0?a->dvx(i-1,j,k):NAN);
+	ny = mgl_get_norm(y, a->dvy(i,j,k), a->dvy(i,j+1,k), j>0?a->dvy(i,j-1,k):NAN);
+	nz = mgl_get_norm(z, a->dvz(i,j,k), a->dvz(i,j,k+1), k>0?a->dvz(i,j,k-1):NAN);
+	return inv ? mglPoint(nx,ny,nz) : mglPoint(-nx,-ny,-nz);
+}
+//-----------------------------------------------------------------------------
+mreal MGL_NO_EXPORT mgl_normal_1d(HCDT a, mreal x, long n)
+{
+	long i=long(x);
+	i = i<n-1 ? i:n-2;	x-=i;
+	return mgl_get_norm(x, a->dvx(i), a->dvx(i+1), i>0?a->dvx(i-1):NAN);
+}
+//-----------------------------------------------------------------------------
+mglPoint MGL_NO_EXPORT mgl_find_norm(bool nboth, HCDT x, HCDT y, HCDT z, HCDT a, mglPoint u, bool inv, long n,long m,long l)
+{
+	mglPoint s = mgl_normal_3d(a,u,inv,n,m,l), t, q;
+	if(nboth)
+	{
+		q.x = s.x/mgl_normal_1d(x,u.x,n);
+		q.y = s.y/mgl_normal_1d(y,u.y,m);
+		q.z = s.z/mgl_normal_1d(z,u.z,l);
+	}
+	else
+	{
+		t = mgl_normal_3d(x,u,true,n,m,l);	q.x = (s*t)/(t*t);
+		t = mgl_normal_3d(y,u,true,n,m,l);	q.y = (s*t)/(t*t);
+		t = mgl_normal_3d(z,u,true,n,m,l);	q.z = (s*t)/(t*t);
+	}
+	return q;
+}
+//-----------------------------------------------------------------------------
+inline mreal MGL_NO_EXPORT mgl_cos_pp(const mglPoint *kk,long i0,long i1,long i2)
+{
+	mglPoint dp1 = kk[i1]-kk[i0], dp2 = kk[i2]-kk[i0];
+	mreal p1=dp1*dp1,p2=dp2*dp2,pc=dp1*dp2;
+	return p1*p2>1e-10 ? pc/sqrt(p1*p2) : NAN;
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3_plot(HMGL gr, long n,long m,long *kx1,long *kx2,long *ky1,long *ky2, long *kz, std::vector<mglPoint> kk, int wire)
+{
+	long id[12],us[12],pd[12];
+	mglPoint pp[12];
+
+#pragma omp parallel for private(id,us,pd,pp) collapse(2)
+	for(long j=0;j<m-1;j++)	for(long i=0;i<n-1;i++)
+	{
+		long i0 = i+n*j,ii,jj,k;
+		// find ID of points of Surf3 intersection with cell i0
+		memset(id,-1,12*sizeof(long));	long ni = 0;
+		if(kx1[i0]>=0)		id[ni++] = kx1[i0];
+		if(ky1[i0]>=0)		id[ni++] = ky1[i0];
+		if(kx1[i0+n]>=0)	id[ni++] = kx1[i0+n];
+		if(ky1[i0+1]>=0)	id[ni++] = ky1[i0+1];
+		if(kz[i0]>=0)		id[ni++] = kz[i0];
+		if(kz[i0+1]>=0)		id[ni++] = kz[i0+1];
+		if(kz[i0+n+1]>=0)	id[ni++] = kz[i0+n+1];
+		if(kz[i0+n]>=0)		id[ni++] = kz[i0+n];
+		if(kx2[i0]>=0)		id[ni++] = kx2[i0];
+		if(ky2[i0]>=0)		id[ni++] = ky2[i0];
+		if(kx2[i0+n]>=0)	id[ni++] = kx2[i0+n];
+		if(ky2[i0+1]>=0)	id[ni++] = ky2[i0+1];
+		if(ni<3)	continue;
+
+		for(jj=0;jj<ni;jj++)
+		{	pp[jj]=kk[id[jj]];	pd[jj]=mgl_int(pp[jj].c);	}
+		// remove points which is too close to first one
+		for(jj=1;jj<ni;)
+		{
+			mreal d = mgl_norm(pp[jj] - pp[0]);
+			if(d>1e-5)	jj++;
+			else
+			{	ni--;	for(ii=jj;ii<ni;ii++)	id[ii]=id[ii+1];	}
+		}
+		// continue if number of points <3 i.e. there is no triangle
+		if(ni<3)	continue;
+		memset(us,0,12*sizeof(long));
+		// firstly let find most outstanding point
+		mreal d0=2;
+		for(jj=1,ii=2;ii<ni;ii++)
+		{
+			mreal d = mgl_cos_pp(pp,0,ii,1);
+			if(d<d0)	{	d0=d;	jj=ii;	}
+		}
+		// copy first 2 points as base
+		long p1 = pd[0], p2 = pd[jj], p3;
+		// select the same orientation of all triangles of the surface
+		us[0] = us[jj] = 1;
+		// find all triangles
+		for(k=2;k<ni;k++)
+		{
+			// find closest point in sence cosine of angle
+			for(i0=-1,ii=1,d0=-2;ii<ni;ii++)
+			{
+				if(us[ii])	continue;
+				mreal d = mgl_cos_pp(pp,0,ii,jj);
+				if(d>d0)	{	d0=d;	i0=ii;	}
+			}
+			if(i0<0)	break;	// no more triangles. NOTE: should be never here
+			jj = i0;	us[jj]=1;	p3 = pd[jj];
+			if(wire==1)
+			{
+				gr->line_plot(p1, p2);
+				gr->line_plot(p1, p3);
+				gr->line_plot(p2, p3);
+			}
+			else if(wire==2)
+			{
+				gr->mark_plot(p1, '.');
+				gr->mark_plot(p2, '.');
+				gr->mark_plot(p3, '.');
+			}
+			else	gr->trig_plot(p1, p2, p3);
+			p2 = p3;
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_surf3ca_gen(HMGL gr, double val, HCDT x, HCDT y, HCDT z, HCDT a, HCDT c, HCDT b, const char *sch)
+{
+	long n=a->GetNx(),m=a->GetNy(),l=a->GetNz();
+	bool nboth = mgl_isnboth(x,y,z,a);
+	int wire = mglchr(sch,'#')?1:0;
+	if(mglchr(sch,'.'))	wire = 2;
+	bool inv = (mglchr(sch,'-'));
+	long ss = gr->AddTexture(sch);
+
+	long *kx1 = new long[n*m],	*kx2 = new long[n*m];
+	long *ky1 = new long[n*m],	*ky2 = new long[n*m];
+	long *kz  = new long[n*m];
+	std::vector<mglPoint> kk;
+	kk.reserve(n*m*l);
+
+	for(long k=0;k<l;k++)
+	{
+		if(gr->NeedStop())	break;
+		memcpy(kx1,kx2,n*m*sizeof(long));	memset(kx2,-1,n*m*sizeof(long));
+		memcpy(ky1,ky2,n*m*sizeof(long));	memset(ky2,-1,n*m*sizeof(long));
+		memset(kz ,-1,n*m*sizeof(long));
+		gr->Reserve(n*m);	gr->Reserve(n*m);
+		size_t kk1 = kk.size();
+		for(long j=0;j<m;j++)	for(long i=0;i<n;i++)
+		{
+			long i1 = i+n*j;
+			mreal a0 = a->v(i,j,k);
+			if(mgl_isnan(a0))	continue;
+			if(i<n-1)
+			{
+				mreal d = mgl_d(val,a0,a->v(i+1,j,k));
+				if(d>=0 && d<1)
+				{	kx2[i1] = kk.size();	kk.push_back(mglPoint(i+d,j,k));	}
+			}
+			if(j<m-1)
+			{
+				mreal d = mgl_d(val,a0,a->v(i,j+1,k));
+				if(d>=0 && d<1)
+				{	ky2[i1] = kk.size();	kk.push_back(mglPoint(i,j+d,k));	}
+			}
+			if(k>0)
+			{
+				mreal d = mgl_d(val,a->v(i,j,k-1),a0);
+				if(d>=0 && d<1)
+				{	kz[i1] = kk.size();		kk.push_back(mglPoint(i,j,k+d-1));	}
+			}
+		}
+		mreal cv=gr->GetC(ss,val);
+		if(b && c)	for(size_t i=kk1;i<kk.size();i++)
+		{
+			mglPoint &u = kk[i];
+			mreal cc = c->linear(u.x,u.y,u.z), bb = b->linear(u.x,u.y,u.z);
+			if(mgl_isnan(cc) || mgl_isnan(bb))	u.c = -1;	else
+			u.c = gr->AddPnt(nboth ? mglPoint(x->linear(u.x,0,0),y->linear(u.y,0,0),z->linear(u.z,0,0)) :
+					mglPoint(x->linear(u.x,u.y,u.z),y->linear(u.x,u.y,u.z),z->linear(u.x,u.y,u.z)),
+					gr->GetC(ss,cc), mgl_find_norm(nboth, x,y,z,a, u, inv,n,m,l), gr->GetA(bb));
+		}
+		else if(c)	for(size_t i=kk1;i<kk.size();i++)
+		{
+			mglPoint &u = kk[i];
+			mreal cc = c->linear(u.x,u.y,u.z);
+			if(mgl_isnan(cc))	u.c = -1;	else
+			u.c = gr->AddPnt(nboth ? mglPoint(x->linear(u.x,0,0),y->linear(u.y,0,0),z->linear(u.z,0,0)) :
+					mglPoint(x->linear(u.x,u.y,u.z),y->linear(u.x,u.y,u.z),z->linear(u.x,u.y,u.z)),
+					gr->GetC(ss,cc), mgl_find_norm(nboth, x,y,z,a, u, inv,n,m,l));
+		}
+		else if(b)	for(size_t i=kk1;i<kk.size();i++)
+		{
+			mglPoint &u = kk[i];
+			mreal bb = b->linear(u.x,u.y,u.z);
+			if(mgl_isnan(bb))	u.c = -1;	else
+			u.c = gr->AddPnt(nboth ? mglPoint(x->linear(u.x,0,0),y->linear(u.y,0,0),z->linear(u.z,0,0)) :
+					mglPoint(x->linear(u.x,u.y,u.z),y->linear(u.x,u.y,u.z),z->linear(u.x,u.y,u.z)),
+					cv, mgl_find_norm(nboth, x,y,z,a, u, inv,n,m,l), gr->GetA(bb));
+		}
+		else	for(size_t i=kk1;i<kk.size();i++)
+		{
+			mglPoint &u = kk[i];
+			u.c = gr->AddPnt(nboth ? mglPoint(x->linear(u.x,0,0),y->linear(u.y,0,0),z->linear(u.z,0,0)) :
+					mglPoint(x->linear(u.x,u.y,u.z),y->linear(u.x,u.y,u.z),z->linear(u.x,u.y,u.z)),
+					cv, mgl_find_norm(nboth, x,y,z,a, u, inv,n,m,l));
+		}
+
+		if(k>0)	mgl_surf3_plot(gr,n,m,kx1,kx2,ky1,ky2,kz,kk,wire);
+	}
+	delete []kx1;	delete []kx2;	delete []ky1;
+	delete []ky2;	delete []kz;	gr->EndGroup();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3_xyz_val(HMGL gr, double val, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt)
+{
+	if(mgl_check_dim3(gr,mgl_isboth(x,y,z,a),x,y,z,a,0,"Surf3"))	return;
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Surf3",cgid++);
+	mgl_surf3ca_gen(gr, val, x, y, z, a, 0, 0, sch);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3_val(HMGL gr, double val, HCDT a, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(a->GetNx()), y(a->GetNy()), z(a->GetNz());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	z.Fill(gr->Min.z,gr->Max.z);
+	mgl_surf3_xyz_val(gr,val,&x,&y,&z,a,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long num = mgl_isnan(r)?3:long(r+0.5);
+	for(long i=0;i<num;i++)
+	{
+		mreal v = gr->Max.c + (gr->Min.c-gr->Max.c)*(i+1.)/(num+1);
+		mgl_surf3_xyz_val(gr,v,x,y,z,a,sch,0);
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3(HMGL gr, HCDT a, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(a->GetNx()), y(a->GetNy()), z(a->GetNz());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	z.Fill(gr->Min.z,gr->Max.z);
+	mgl_surf3_xyz(gr,&x,&y,&z,a,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3_xyz_val_(uintptr_t *gr, mreal *Val, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_surf3_xyz_val(_GR_, *Val, _DA_(x), _DA_(y), _DA_(z), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3_val_(uintptr_t *gr, mreal *Val, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_surf3_val(_GR_, *Val, _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_surf3_xyz(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3_(uintptr_t *gr, uintptr_t *a, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_surf3(_GR_, _DA_(a), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Surf3A series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3a_xyz_val(HMGL gr, double val, HCDT x, HCDT y, HCDT z, HCDT a, HCDT b, const char *sch, const char *opt)
+{
+	if(mgl_check_dim3(gr,!mgl_isnboth(x,y,z,a),x,y,z,a,b,"Surf3A"))	return;
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Surf3A",cgid++);
+	mgl_surf3ca_gen(gr, val, x, y, z, a, 0, b, sch);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3a_val(HMGL gr, double val, HCDT a, HCDT b, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(a->GetNx()), y(a->GetNy()),z(a->GetNz());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	z.Fill(gr->Min.z,gr->Max.z);
+	mgl_surf3a_xyz_val(gr,val,&x,&y,&z,a,b,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3a_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, HCDT b, const char *sch, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long num = mgl_isnan(r)?3:long(r+0.5);
+	if(b->GetNx()==num && b->GetNy()==1 && b->GetNz()==1)
+	{
+		mreal a0=gr->AlphaDef;
+		for(long i=0;i<num;i++)
+		{
+			mreal v = gr->Max.c + (gr->Min.c-gr->Max.c)*(i+1.)/(num+1);
+			gr->AlphaDef = gr->GetA(b->v(i));
+			mgl_surf3_xyz_val(gr,v,x,y,z,a,sch,0);
+		}
+		gr->AlphaDef = a0;
+	}
+	else
+		for(long i=0;i<num;i++)
+		{
+			mreal v = gr->Max.c + (gr->Min.c-gr->Max.c)*(i+1.)/(num+1);
+			mgl_surf3a_xyz_val(gr,v,x,y,z,a,b,sch,0);
+		}
+	gr->LoadState();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3a(HMGL gr, HCDT a, HCDT b, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(a->GetNx()), y(a->GetNy()),z(a->GetNz());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	z.Fill(gr->Min.z,gr->Max.z);
+	mgl_surf3a_xyz(gr,&x,&y,&z,a,b,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3a_xyz_val_(uintptr_t *gr, mreal *Val, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, uintptr_t *b, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_surf3a_xyz_val(_GR_, *Val, _DA_(x), _DA_(y), _DA_(z), _DA_(a), _DA_(b), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3a_val_(uintptr_t *gr, mreal *Val, uintptr_t *a, uintptr_t *b, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	 mgl_surf3a_val(_GR_, *Val, _DA_(a), _DA_(b), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3a_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, uintptr_t *b, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_surf3a_xyz(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(a), _DA_(b), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3a_(uintptr_t *gr, uintptr_t *a, uintptr_t *b, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_surf3a(_GR_, _DA_(a), _DA_(b), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Surf3C series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3c_xyz_val(HMGL gr, double val, HCDT x, HCDT y, HCDT z, HCDT a, HCDT c, const char *sch, const char *opt)
+{
+	if(mgl_check_dim3(gr,!mgl_isnboth(x,y,z,a),x,y,z,a,c,"Surf3C"))	return;
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Surf3C",cgid++);
+	mgl_surf3ca_gen(gr, val, x, y, z, a, c, 0, sch);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3c_val(HMGL gr, double val, HCDT a, HCDT b, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(a->GetNx()), y(a->GetNy()),z(a->GetNz());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	z.Fill(gr->Min.z,gr->Max.z);
+	mgl_surf3c_xyz_val(gr,val,&x,&y,&z,a,b,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3c_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, HCDT b, const char *sch, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long num = mgl_isnan(r)?3:long(r+0.5);
+	for(long i=0;i<num;i++)
+	{
+		mreal v = gr->Max.c + (gr->Min.c-gr->Max.c)*(i+1.)/(num+1);
+		mgl_surf3c_xyz_val(gr,v,x,y,z,a,b,sch,0);
+	}
+	gr->LoadState();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3c(HMGL gr, HCDT a, HCDT b, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(a->GetNx()), y(a->GetNy()),z(a->GetNz());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	z.Fill(gr->Min.z,gr->Max.z);
+	mgl_surf3c_xyz(gr,&x,&y,&z,a,b,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3c_xyz_val_(uintptr_t *gr, mreal *Val, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, uintptr_t *b, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_surf3c_xyz_val(_GR_, *Val, _DA_(x), _DA_(y), _DA_(z), _DA_(a), _DA_(b), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3c_val_(uintptr_t *gr, mreal *Val, uintptr_t *a, uintptr_t *b, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	 mgl_surf3c_val(_GR_, *Val, _DA_(a), _DA_(b), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3c_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, uintptr_t *b, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_surf3c_xyz(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(a), _DA_(b), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3c_(uintptr_t *gr, uintptr_t *a, uintptr_t *b, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_surf3c(_GR_, _DA_(a), _DA_(b), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Surf3C series
+//
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3ca_xyz_val(HMGL gr, double val, HCDT x, HCDT y, HCDT z, HCDT a, HCDT c, HCDT b, const char *sch, const char *opt)
+{
+	if(mgl_check_dim3(gr,!mgl_isnboth(x,y,z,a),x,y,z,a,c,"Surf3C") || mgl_check_dim3(gr,!mgl_isnboth(x,y,z,a),x,y,z,a,b,"Surf3C"))	return;
+	gr->SaveState(opt);
+	static int cgid=1;	gr->StartGroup("Surf3C",cgid++);
+	mgl_surf3ca_gen(gr, val, x, y, z, a, c, b, sch);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3ca_val(HMGL gr, double val, HCDT a, HCDT c, HCDT b, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(a->GetNx()), y(a->GetNy()),z(a->GetNz());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	z.Fill(gr->Min.z,gr->Max.z);
+	mgl_surf3ca_xyz_val(gr,val,&x,&y,&z,a,c,b,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3ca_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT a, HCDT c, HCDT b, const char *sch, const char *opt)
+{
+	mreal r = gr->SaveState(opt);
+	long num = mgl_isnan(r)?3:long(r+0.5);
+	for(long i=0;i<num;i++)
+	{
+		mreal v = gr->Max.c + (gr->Min.c-gr->Max.c)*(i+1.)/(num+1);
+		mgl_surf3ca_xyz_val(gr,v,x,y,z,a,c,b,sch,0);
+	}
+	gr->LoadState();
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3ca(HMGL gr, HCDT a, HCDT c, HCDT b, const char *sch, const char *opt)
+{
+	gr->SaveState(opt);
+	mglDataV x(a->GetNx()), y(a->GetNy()),z(a->GetNz());
+	x.Fill(gr->Min.x,gr->Max.x);
+	y.Fill(gr->Min.y,gr->Max.y);
+	z.Fill(gr->Min.z,gr->Max.z);
+	mgl_surf3ca_xyz(gr,&x,&y,&z,a,c,b,sch,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3ca_xyz_val_(uintptr_t *gr, mreal *Val, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, uintptr_t *c, uintptr_t *b, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_surf3ca_xyz_val(_GR_, *Val, _DA_(x), _DA_(y), _DA_(z), _DA_(a), _DA_(c), _DA_(b), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3ca_val_(uintptr_t *gr, mreal *Val, uintptr_t *a, uintptr_t *c, uintptr_t *b, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	 mgl_surf3ca_val(_GR_, *Val, _DA_(a), _DA_(c), _DA_(b), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3ca_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *a, uintptr_t *c, uintptr_t *b, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_surf3ca_xyz(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(a), _DA_(c), _DA_(b), s, o);
+	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_surf3ca_(uintptr_t *gr, uintptr_t *a, uintptr_t *c, uintptr_t *b, const char *sch, const char *opt,int l,int lo)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
+	mgl_surf3ca(_GR_, _DA_(a), _DA_(c), _DA_(b), s, o);	delete []o;	delete []s;	}
+//-----------------------------------------------------------------------------
+//
+//	Beam series
+//
+//-----------------------------------------------------------------------------
+// flag & 0x1	--	accompanied coordinates
+// flag & 0x2	--	project to r*z
+// flag & 0x4	--	normalize field
+void MGL_EXPORT mgl_beam_val(HMGL gr, double val, HCDT tr, HCDT g1, HCDT g2, HCDT a, double r, const char *stl, int flag)
+{
+	long n = a->GetNz(),m=a->GetNx(),l=a->GetNy();
+	if(n<2 || m<2 || l<2)	{	gr->SetWarn(mglWarnLow,"Beam");	return;	}
+	if(a->Minimal()<0)		{	gr->SetWarn(mglWarnNeg,"Beam");	return;	}
+	if(tr->GetNx()<3 || tr->GetNy()<n || g1->GetNx()<3 || g1->GetNy()<n || g2->GetNx()<3 || g2->GetNy()<n)
+	{	gr->SetWarn(mglWarnDim,"Beam");	return;	}
+	mglData x(a),y(a),z(a),b(a);
+	mreal asum0=1;	r = fabs(r);
+	if(flag & 4)	for(long j=0;j<m*l;j++)	asum0 += a->vthr(j)*a->vthr(j);
+	if(asum0==0)	{	gr->SetWarn(mglWarnZero,"Beam");	return;	}
+#pragma omp parallel for
+	for(long i=0;i<n;i++)
+	{
+		if(gr->NeedStop())	continue;
+		if(flag & 4)
+		{
+			mreal asum=0, amax=0;
+			for(long j=0;j<m*l;j++)
+			{
+				mreal aa = a->vthr(j+m*l*i);
+				asum += aa*aa;	amax = amax>aa ? amax : aa;
+			}
+			amax = amax?sqrt(asum/asum0)/amax:0;
+			for(long j=0;j<m*l;j++)	b.a[j+m*l*i] = b.a[j+m*l*i]*amax;
+		}
+		if(flag & 1)	for(long j=0;j<m;j++)	for(long k=0;k<l;k++)
+		{
+			long i0 = j+m*(k+l*i);
+			x.a[i0] = 2*j/(m-1.)-1;
+			y.a[i0] = 2*k/(l-1.)-1;
+			z.a[i0] = gr->Max.z*i/(n-1.);
+		}
+		else	for(long j=0;j<m;j++)	for(long k=0;k<l;k++)
+		{
+			long i0 = j+m*(k+l*i);
+			x.a[i0] = tr->v(0,i) + g1->v(0,i)*(2*j/(m-1.)-1)*r + g2->v(0,i)*(2*k/(l-1.)-1)*r;
+			y.a[i0] = tr->v(1,i) + g1->v(1,i)*(2*j/(m-1.)-1)*r + g2->v(1,i)*(2*k/(l-1.)-1)*r;
+			z.a[i0] = tr->v(2,i) + g1->v(2,i)*(2*j/(m-1.)-1)*r + g2->v(2,i)*(2*k/(l-1.)-1)*r;
+		}
+		if(flag & 2)	for(long j=0;j<m;j++)	for(long k=0;k<l;k++)
+		{
+			long i0 = j+m*(k+l*i);
+			x.a[i0] = hypot(x.a[i0],y.a[i0]);
+		}
+	}
+	mgl_surf3_xyz_val(gr,val,&x,&y,&z,&b,stl,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_beam(HMGL gr, HCDT tr, HCDT g1, HCDT g2, HCDT a, double r, const char *stl, int flag, int num)
+{
+	num = num<=0 ? 1 : num;
+	for(long i=0;i<num;i++)
+	{
+		mreal v = gr->Max.c + (gr->Min.c-gr->Max.c)*(i+1.)/(num+1);
+		mgl_beam_val(gr,v,tr,g1,g2,a,r,stl,flag);
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_beam_val_(uintptr_t *gr, mreal *val, uintptr_t *tr, uintptr_t *g1, uintptr_t *g2, uintptr_t *a, mreal *r, const char *sch, int *norm,int l)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	mgl_beam_val(_GR_, *val,_DA_(tr),_DA_(g1),_DA_(g2),_DA_(a),*r,s,*norm);	delete []s;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_beam_(uintptr_t *gr, uintptr_t *tr, uintptr_t *g1, uintptr_t *g2, uintptr_t *a, mreal *r, const char *sch, int *norm, int *num,int l)
+{	char *s=new char[l+1];	memcpy(s,sch,l);	s[l]=0;
+	mgl_beam(_GR_, _DA_(tr), _DA_(g1), _DA_(g2), _DA_(a), *r,s,*norm,*num);	delete []s;	}
+//-----------------------------------------------------------------------------
diff --git a/src/window.cpp b/src/window.cpp
new file mode 100644
index 0000000..068db2a
--- /dev/null
+++ b/src/window.cpp
@@ -0,0 +1,253 @@
+/***************************************************************************
+ * window.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include "mgl2/canvas_wnd.h"
+//-----------------------------------------------------------------------------
+mglCanvasWnd::mglCanvasWnd() : mglCanvas()
+{
+	Setup();	LoadFunc=0;	FuncPar=0;	DrawFunc=0;	ClickFunc=0;
+	GG = 0;		NumFig = 0;	CurFig = -1;
+#if MGL_HAVE_PTHR_WIDGET
+	mutex=0;
+#endif
+}
+//-----------------------------------------------------------------------------
+mglCanvasWnd::~mglCanvasWnd()	{	if(GG) free(GG);	}
+//-----------------------------------------------------------------------------
+void mglCanvasWnd::SetCurFig(int c)
+{
+	CurFig=c;
+	if(get(MGL_VECT_FRAME) && c>=0 && c<(long)DrwDat.size() && DrawFunc)
+		GetFrame(c);
+}
+//-----------------------------------------------------------------------------
+void mglCanvasWnd::ResetFrames()
+{
+	if(GG)	free(GG);
+	GG = 0;	NumFig = CurFig = 0;
+	mglCanvas::ResetFrames();
+}
+//-----------------------------------------------------------------------------
+void mglCanvasWnd::SetSize(int w,int h,bool)
+{
+	if(DrawFunc)	ResetFrames();
+	mglCanvas::SetSize(w,h,false);
+//	if(Wnd)	Wnd->size(w,h);
+}
+//-----------------------------------------------------------------------------
+void mglCanvasWnd::EndFrame()
+{
+	CurFig = CurFrameId-1;
+	if(!GG)
+	{
+		GG = (unsigned char *)malloc(3*Width*Height);
+		NumFig = 1;		CurFig = 0;
+	}
+	else if(CurFig>NumFig-1)
+	{
+		GG = (unsigned char *)realloc(GG,3*(CurFig+1)*Width*Height);
+		NumFig = CurFig+1;
+	}
+	mglCanvas::EndFrame();
+	memcpy(GG + CurFig*Width*Height*3,G,3*Width*Height);
+	CurFig++;
+}
+//-----------------------------------------------------------------------------
+void mglCanvasWnd::SetFrame(long i)
+{
+	mglCanvas::SetFrame(i);
+	if(i>=0 && i<NumFig)	memcpy(GG + i*Width*Height*3,G,3*Width*Height);
+}
+//-----------------------------------------------------------------------------
+void mglCanvasWnd::DelFrame(long i)
+{
+	if(i<0 || i>=CurFrameId)	return;
+	if(CurFig>=i)	CurFig--;
+	long n = Width*Height*3;
+	if(CurFrameId-i>1)	memmove(GG+i*n, GG+i*n+n, n*(CurFrameId-i-1));
+	mglCanvas::DelFrame(i);
+}
+//-----------------------------------------------------------------------------
+void mglCanvasWnd::SetDrawFunc(int (*draw)(mglBase *gr, void *p), void *par, void (*reload)(void *p))
+{
+	if(draw)
+	{
+		ResetFrames();
+		if(get(MGL_CLF_ON_UPD))	DefaultPlotParam();
+		const std::string loc = setlocale(LC_NUMERIC, "C");
+		// use frames for quickly redrawing while adding/changing primitives
+		if(mgl_is_frames(this))	NewFrame();
+
+		int n = draw(this,par);
+		if(n<NumFig && n>=0)	NumFig = n;
+		DrawFunc = draw;		FuncPar = par;
+		LoadFunc = reload;
+
+		if(mgl_is_frames(this))	EndFrame();
+		if(n>=0)	SetCurFig(0);
+		setlocale(LC_NUMERIC, loc.c_str());
+	}
+	else	LoadFunc = 0;
+}
+//-----------------------------------------------------------------------------
+const unsigned char *mglCanvasWnd::GetBits()
+{
+	const unsigned char *g = mglCanvas::GetBits();
+	if(GG && NumFig>0 && CurFig<NumFig && CurFig>=0 && !get(MGL_VECT_FRAME))
+		g = GG + CurFig*Width*Height*3;
+	return g;
+}
+//-----------------------------------------------------------------------------
+void mglCanvasWnd::ReLoad()
+{
+	if(LoadFunc)
+	{
+		LoadFunc(FuncPar);
+		// update number of slides
+		ResetFrames();
+		const std::string loc = setlocale(LC_NUMERIC, "C");
+		// use frames for quickly redrawing while adding/changing primitives
+		if(mgl_is_frames(this))	NewFrame();
+
+		int n = DrawFunc ? DrawFunc(this,FuncPar) : 0;
+		if(n<NumFig && n>=0)	NumFig = n;
+
+		if(mgl_is_frames(this))	EndFrame();
+		setlocale(LC_NUMERIC, loc.c_str());
+		Update();
+	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_wnd_set_func(HMGL gr, int (*draw)(HMGL gr, void *p), void *par, void (*reload)(void *p))
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);	if(g)	g->SetDrawFunc(draw, par, reload);	}
+void MGL_EXPORT mgl_wnd_toggle_alpha(HMGL gr)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);	if(g)	g->ToggleAlpha();	}
+void MGL_EXPORT mgl_wnd_toggle_light(HMGL gr)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);	if(g)	g->ToggleLight();	}
+void MGL_EXPORT mgl_wnd_toggle_zoom(HMGL gr)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);	if(g)	g->ToggleZoom();	}
+void MGL_EXPORT mgl_wnd_toggle_rotate(HMGL gr)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);	if(g)	g->ToggleRotate();	}
+void MGL_EXPORT mgl_wnd_toggle_no(HMGL gr)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);	if(g)	g->ToggleNo();	}
+void MGL_EXPORT mgl_wnd_update(HMGL gr)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);	if(g)	g->Update();	}
+void MGL_EXPORT mgl_wnd_reload(HMGL gr)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);	if(g)	g->ReLoad();	}
+void MGL_EXPORT mgl_wnd_adjust(HMGL gr)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);	if(g)	g->Adjust();	}
+void MGL_EXPORT mgl_wnd_next_frame(HMGL gr)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);	if(g)	g->NextFrame();	}
+void MGL_EXPORT mgl_wnd_prev_frame(HMGL gr)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);	if(g)	g->PrevFrame();	}
+void MGL_EXPORT mgl_wnd_animation(HMGL gr)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);	if(g)	g->Animation();	}
+void MGL_EXPORT mgl_setup_window(HMGL gr, int clf_upd, int showpos)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);	if(g)	g->Setup(clf_upd, showpos);	}
+void MGL_EXPORT mgl_set_click_func(HMGL gr, void (*func)(void *p))
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);	if(g)	g->ClickFunc = func;	}
+void MGL_EXPORT mgl_get_last_mouse_pos(HMGL gr, mreal *x, mreal *y, mreal *z)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);
+	mglPoint p;	if(g)	p=g->GetMousePos();
+	*x=p.x;	*y=p.y;	*z=p.z;	}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_wnd_toggle_alpha_(uintptr_t *gr)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>((HMGL)(*gr));
+	if(g)	g->ToggleAlpha();	}
+void MGL_EXPORT mgl_wnd_toggle_light_(uintptr_t *gr)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>((HMGL)(*gr));
+	if(g)	g->ToggleLight();	}
+void MGL_EXPORT mgl_wnd_toggle_zoom_(uintptr_t *gr)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>((HMGL)(*gr));
+	if(g)	g->ToggleZoom();	}
+void MGL_EXPORT mgl_wnd_toggle_rotate_(uintptr_t *gr)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>((HMGL)(*gr));
+	if(g)	g->ToggleRotate();	}
+void MGL_EXPORT mgl_wnd_toggle_no_(uintptr_t *gr)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>((HMGL)(*gr));
+	if(g)	g->ToggleNo();	}
+void MGL_EXPORT mgl_wnd_update_(uintptr_t *gr)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>((HMGL)(*gr));
+	if(g)	g->Update();	}
+void MGL_EXPORT mgl_wnd_reload_(uintptr_t *gr)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>((HMGL)(*gr));
+	if(g)	g->ReLoad();	}
+void MGL_EXPORT mgl_wnd_adjust_(uintptr_t *gr)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>((HMGL)(*gr));
+	if(g)	g->Adjust();	}
+void MGL_EXPORT mgl_wnd_next_frame_(uintptr_t *gr)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>((HMGL)(*gr));
+	if(g)	g->NextFrame();	}
+void MGL_EXPORT mgl_wnd_prev_frame_(uintptr_t *gr)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>((HMGL)(*gr));
+	if(g)	g->PrevFrame();	}
+void MGL_EXPORT mgl_wnd_animation_(uintptr_t *gr)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>((HMGL)(*gr));
+	if(g)	g->Animation();	}
+void MGL_EXPORT mgl_setup_window_(uintptr_t *gr, int *clf_upd, int *showpos)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>((HMGL)(*gr));
+	if(g)	g->Setup(*clf_upd, *showpos);	}
+void MGL_EXPORT mgl_get_last_mouse_pos_(uintptr_t *gr, mreal *x, mreal *y, mreal *z)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>((HMGL)(*gr));
+	mglPoint p;	if(g)	p=g->GetMousePos();
+	*x=p.x;	*y=p.y;	*z=p.z;	}
+//-----------------------------------------------------------------------------
+#if MGL_HAVE_PTHR_WIDGET
+void MGL_EXPORT mgl_wnd_set_mutex(HMGL gr, pthread_mutex_t *mutex)
+{	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);
+	if(g)	g->mutex = mutex;	}
+#endif
+//-----------------------------------------------------------------------------
+//
+//	mglDraw class handling
+//
+//-----------------------------------------------------------------------------
+/*int mgl_draw_class(HMGL gr, void *p)	// so stupid way to save mglDraw class inheritance :(
+{
+	mglGraph g(gr);	mglWindow *w = (mglWindow *)p;
+	return (w && w->dr) ? w->dr->Draw(&g) : 0;
+}
+void MGL_EXPORT mgl_reload_class(void *p)	// so stupid way to save mglDraw class inheritance :(
+{	mglWindow *w = (mglWindow *)p;	if(w && w->dr)	w->dr->Reload();}
+void MGL_EXPORT mgl_click_class(void *p)	// so stupid way to save mglDraw class inheritance :(
+{	mglWindow *w = (mglWindow *)p;	if(w && w->dr)	w->dr->Click();	}*/
+int MGL_EXPORT mgl_draw_class(HMGL gr, void *p)
+{	mglGraph g(gr);	mglDraw *dr = (mglDraw *)p;	return dr?dr->Draw(&g):0;	}
+void MGL_EXPORT mgl_reload_class(void *p)
+{	mglDraw *dr = (mglDraw *)p;	if(dr)	dr->Reload();	}
+void MGL_EXPORT mgl_click_class(void *p)
+{	mglDraw *dr = (mglDraw *)p;	if(dr)	dr->Click();		}
+//-----------------------------------------------------------------------------
+typedef int (*draw_func)(mglGraph *gr);
+int MGL_EXPORT mgl_draw_graph(HMGL gr, void *p)
+{
+	mglGraph g(gr);
+	draw_func func = (draw_func)(p);
+	return func ? func(&g) : 0;
+}
+//-----------------------------------------------------------------------------
+MGL_EXPORT void *mgl_draw_calc(void *p)
+{
+#if MGL_HAVE_PTHR_WIDGET
+	mglDraw *d = (mglDraw *)p;
+	d->Calc();	d->running = false;
+#endif
+	return 0;
+}
+//-----------------------------------------------------------------------------
diff --git a/texinfo/CMakeLists.txt b/texinfo/CMakeLists.txt
new file mode 100644
index 0000000..7d6abaf
--- /dev/null
+++ b/texinfo/CMakeLists.txt
@@ -0,0 +1,219 @@
+configure_file(${MathGL2_SOURCE_DIR}/texinfo/version.texi.in ${MathGL2_BINARY_DIR}/texinfo/version.texi)
+
+set(MGL_EXTRA light pendelta)
+set(MGL_PNG alpha area aspect axial axis barh bars belt boxplot
+	box boxs candle chart cloud colorbar combined cones conta contd
+	contfa contf contf_xyz cont contv cont_xyz curvcoor cut dat_diff
+	dat_extra densa dens dens_xyz dew dots error error2 fall fit flow fonts
+	fog grad hist inplot label legend loglog map mark mesh mirror
+	molecule parser pde pipe plot primitives projection qo2d radar region schemes
+	several_light solve stem step stereo stfa style surf3a surf3c surf3ca surf3
+	surfa surfc surfca surf table tape tens ternary textmark text ticks tile tiles
+	torus traj triangulation triplot tube type0 type1 type2 vect vecta venn
+	projection5 mask correl refill ohlc ode indirect
+	pulse scanfile bifurcation lamerey pmap ifs2d ifs3d
+	flame2d detect dilate iris section apde earth )
+set(MGL_PNG_N )
+set(MGL_PNG_S )
+set(MGL_PNG_J )
+set(MGL_PNG_D )
+
+set(MGL_OUT ${CMAKE_BINARY_DIR}/texinfo)
+set(MGL_TEX ${CMAKE_SOURCE_DIR}/texinfo)
+file(MAKE_DIRECTORY ${MGL_OUT}/udav)
+file(MAKE_DIRECTORY ${MGL_OUT}/png)
+file(MAKE_DIRECTORY ${MGL_OUT}/small)
+file(MAKE_DIRECTORY ${MGL_OUT}/json)
+file(MAKE_DIRECTORY ${MGL_OUT}/pdf)
+file(COPY ${MGL_TEX}/qt.png ${MGL_TEX}/fltk.png ${MGL_TEX}/classes.png ${MGL_TEX}/emblem_sm.png ${MGL_TEX}/datadvance.png DESTINATION ${MGL_OUT})
+file(COPY ${MGL_TEX}/index.html ${MGL_TEX}/json.html ${MGL_TEX}/mathgl.js DESTINATION ${MGL_OUT})
+file(COPY ${CMAKE_SOURCE_DIR}/examples/iris.dat DESTINATION ${MGL_OUT}/png)
+file(COPY ${CMAKE_SOURCE_DIR}/examples/iris.dat DESTINATION ${MGL_OUT}/small)
+file(COPY ${CMAKE_SOURCE_DIR}/examples/iris.dat DESTINATION ${MGL_OUT}/json)
+file(COPY ${CMAKE_SOURCE_DIR}/examples/iris.dat DESTINATION ${MGL_OUT}/pdf)
+file(COPY ${CMAKE_SOURCE_DIR}/examples/Equirectangular-projection.jpg DESTINATION ${MGL_OUT}/png)
+file(COPY ${CMAKE_SOURCE_DIR}/examples/Equirectangular-projection.jpg DESTINATION ${MGL_OUT}/small)
+file(COPY ${CMAKE_SOURCE_DIR}/examples/Equirectangular-projection.jpg DESTINATION ${MGL_OUT}/json)
+file(COPY ${CMAKE_SOURCE_DIR}/examples/Equirectangular-projection.jpg DESTINATION ${MGL_OUT}/pdf)
+
+set(UDAV_IMG udav_arg.png udav_calc.png udav_cmd.png udav_data.png udav_mask.png
+	udav_gen_set.png udav_help.png udav_light.png udav_main.png udav_opt.png udav_inplot.png
+	udav_pen.png udav_prop.png udav_sch.png udav_txt.png udav_var.png)
+foreach(SAMPLE ${UDAV_IMG})
+	file(COPY ${MGL_TEX}/udav/${SAMPLE} DESTINATION ${MGL_OUT}/udav/)
+endforeach(SAMPLE)
+
+foreach(SAMPLE ${MGL_PNG})
+	set(MGL_PNG_N ${MGL_PNG_N} ${MGL_OUT}/png/${SAMPLE}.png)
+	add_custom_command(OUTPUT ${MGL_OUT}/png/${SAMPLE}.png
+		COMMAND mgl_example -kind=${SAMPLE}
+		DEPENDS mgl_example
+		WORKING_DIRECTORY ${MGL_OUT}/png )
+	set(MGL_PNG_S ${MGL_PNG_S} ${MGL_OUT}/small/${SAMPLE}-sm.png)
+	add_custom_command(OUTPUT ${MGL_OUT}/small/${SAMPLE}-sm.png
+		COMMAND mgl_example -kind=${SAMPLE} -mini
+		DEPENDS mgl_example
+		WORKING_DIRECTORY ${MGL_OUT}/small )
+
+	if(MGL_HAVE_DOC_JSON)
+		set(MGL_PNG_J ${MGL_PNG_J} ${MGL_OUT}/json/${SAMPLE}.json)
+		add_custom_command(OUTPUT ${MGL_OUT}/json/${SAMPLE}.json
+			COMMAND mgl_example -json -kind=${SAMPLE}
+			DEPENDS mgl_example
+			WORKING_DIRECTORY ${MGL_OUT}/json )
+	endif(MGL_HAVE_DOC_JSON)
+	if(MGL_HAVE_DOC_PRC)
+		set(MGL_PNG_D ${MGL_PNG_D} ${MGL_OUT}/pdf/${SAMPLE}.pdf)
+		add_custom_command(OUTPUT ${MGL_OUT}/pdf/${SAMPLE}.pdf
+			COMMAND mgl_example -pdf -kind=${SAMPLE}
+			DEPENDS mgl_example
+			WORKING_DIRECTORY ${MGL_OUT}/pdf )
+	endif(MGL_HAVE_DOC_PRC)
+endforeach(SAMPLE)
+
+foreach(SAMPLE ${MGL_EXTRA})
+	set(MGL_PNG_N ${MGL_PNG_N} ${MGL_OUT}/png/${SAMPLE}.png)
+	add_custom_command(OUTPUT ${MGL_OUT}/png/${SAMPLE}.png
+		COMMAND mgl_example -kind=${SAMPLE}
+		DEPENDS mgl_example
+		WORKING_DIRECTORY ${MGL_OUT}/png )
+	set(MGL_PNG_S ${MGL_PNG_S} ${MGL_OUT}/small/${SAMPLE}-sm.png)
+	add_custom_command(OUTPUT ${MGL_OUT}/small/${SAMPLE}-sm.png
+		COMMAND mgl_example -kind=${SAMPLE} -mini
+		DEPENDS mgl_example
+		WORKING_DIRECTORY ${MGL_OUT}/small )
+endforeach(SAMPLE)
+
+set(list_texi_files_en overview_en.texi example_en.texi ex_mgl_en.texi parse_en.texi formats_en.texi udav_en.texi symbols_en.texi core_en.texi concept_en.texi widget_en.texi data_en.texi other_en.texi appendix_en.texi fdl.texi ${MathGL2_BINARY_DIR}/texinfo/version.texi time.texi time_big.texi )
+set(list_texi_files_ru overview_ru.texi example_ru.texi ex_mgl_ru.texi parse_ru.texi formats_ru.texi udav_ru.texi symbols_ru.texi core_ru.texi concept_ru.texi widget_ru.texi data_ru.texi other_ru.texi appendix_ru.texi fdl.texi ${MathGL2_BINARY_DIR}/texinfo/version.texi time.texi time_big.texi )
+
+add_custom_command(OUTPUT ${MGL_OUT}/mathgl_en.info
+	COMMAND ${findmi} ${MGL_TEX}/mathgl_en.texi
+	DEPENDS ${list_texi_files_en} mathgl_en.texi #${MGL_PNG_N}
+	WORKING_DIRECTORY ${MGL_OUT}
+)
+add_custom_command(OUTPUT ${MGL_OUT}/mathgl_ru.info
+	COMMAND ${findmi} ${MGL_TEX}/mathgl_ru.texi
+	DEPENDS ${list_texi_files_ru} mathgl_ru.texi #${MGL_PNG_N}
+	WORKING_DIRECTORY ${MGL_OUT}
+)
+
+add_custom_command(OUTPUT ${MGL_OUT}/mathgl_en.html
+	COMMAND ${findth} ${th_opt} -I ${MGL_OUT} --no-split ${MGL_TEX}/mathgl_en.texi
+	DEPENDS ${list_texi_files_en} mathgl_en.texi ${MGL_PNG_N}
+	WORKING_DIRECTORY ${MGL_OUT}
+)
+add_custom_command(OUTPUT ${MGL_OUT}/mgl_en.html
+	COMMAND ${findth} ${th_opt} --set-customization-variable 'BODYTEXT ' -I ${MGL_OUT} --no-split ${MGL_TEX}/mgl_en.texi
+	# following line bypass FLTK bugs
+	COMMAND sed "'s/–/-/g'" -i ${MGL_OUT}/mgl_en.html
+	COMMAND sed "'s/‘/`/g'" -i ${MGL_OUT}/mgl_en.html
+	COMMAND sed "'s/’/`/g'" -i ${MGL_OUT}/mgl_en.html
+	DEPENDS ${list_texi_files_en} mgl_en.texi ${MGL_PNG_N}
+	WORKING_DIRECTORY ${MGL_OUT}
+)
+add_custom_command(OUTPUT ${MGL_OUT}/mathgl_ru.html
+	COMMAND ${findth} ${th_opt} -I=${MGL_OUT} --no-split ${MGL_TEX}/mathgl_ru.texi
+	DEPENDS ${list_texi_files_ru} mathgl_ru.texi ${MGL_PNG_N}
+	WORKING_DIRECTORY ${MGL_OUT}
+)
+add_custom_command(OUTPUT ${MGL_OUT}/mgl_ru.html
+	COMMAND ${findth} ${th_opt} --set-customization-variable 'BODYTEXT ' -I=${MGL_OUT} --no-split ${MGL_TEX}/mgl_ru.texi
+	# following line bypass FLTK bugs
+	COMMAND sed "'s/–/-/g'" -i ${MGL_OUT}/mgl_ru.html
+	COMMAND sed "'s/‘/`/g'" -i ${MGL_OUT}/mgl_ru.html
+	COMMAND sed "'s/’/`/g'" -i ${MGL_OUT}/mgl_ru.html
+	DEPENDS ${list_texi_files_ru} mgl_ru.texi ${MGL_PNG_N}
+	WORKING_DIRECTORY ${MGL_OUT}
+)
+
+add_custom_command(OUTPUT ${site_en}
+	COMMAND ${findth} ${th_opt} -I=${MGL_OUT}/png --split=node -o doc_en ${MGL_TEX}/doc_en.texi
+	DEPENDS ${list_texi_files_en} doc_en.texi ${MGL_PNG_N} web_en.texi ${MGL_PNG_S} ${MGL_PNG_J} ${MGL_PNG_D}
+	WORKING_DIRECTORY ${MGL_OUT}
+)
+add_custom_command(OUTPUT ${site_ru}
+	COMMAND ${findth} ${th_opt} -I=${MGL_OUT}/png --split=node -o doc_ru ${MGL_TEX}/doc_ru.texi
+	DEPENDS ${list_texi_files_ru} doc_ru.texi ${MGL_PNG_N} web_ru.texi ${MGL_PNG_S} ${MGL_PNG_J} ${MGL_PNG_D}
+	WORKING_DIRECTORY ${MGL_OUT}
+)
+
+add_custom_command(OUTPUT ${MGL_OUT}/mathgl_en.pdf
+	COMMAND ${findtp} ${MGL_TEX}/mathgl_en.texi
+	COMMAND ${findtp} ${MGL_TEX}/mathgl_en.texi
+	COMMAND ${findtp} ${MGL_TEX}/mathgl_en.texi
+	DEPENDS ${list_texi_files_en} mathgl_en.texi ${MGL_PNG_N}
+	WORKING_DIRECTORY ${MGL_OUT}
+)
+add_custom_command(OUTPUT ${MGL_OUT}/mgl_en.pdf
+	COMMAND ${findtp} ${MGL_TEX}/mgl_en.texi
+	COMMAND ${findtp} ${MGL_TEX}/mgl_en.texi
+	COMMAND ${findtp} ${MGL_TEX}/mgl_en.texi
+	DEPENDS ${list_texi_files_en} mgl_en.texi ${MGL_PNG_N}
+	WORKING_DIRECTORY ${MGL_OUT}
+)
+
+add_custom_command(OUTPUT ${MGL_OUT}/mathgl_ru.pdf
+	COMMAND ${findtp} ${MGL_TEX}/mathgl_ru.texi
+	COMMAND ${findtp} ${MGL_TEX}/mathgl_ru.texi
+	COMMAND ${findtp} ${MGL_TEX}/mathgl_ru.texi
+	DEPENDS ${list_texi_files_ru} mathgl_ru.texi ${MGL_PNG_N}
+	WORKING_DIRECTORY ${MGL_OUT}
+)
+add_custom_command(OUTPUT ${MGL_OUT}/mgl_ru.pdf
+	COMMAND ${findtp} ${MGL_TEX}/mgl_ru.texi
+	COMMAND ${findtp} ${MGL_TEX}/mgl_ru.texi
+	COMMAND ${findtp} ${MGL_TEX}/mgl_ru.texi
+	DEPENDS ${list_texi_files_en} mgl_ru.texi ${MGL_PNG_N}
+	WORKING_DIRECTORY ${MGL_OUT}
+)
+
+if(MGL_HAVE_DOC_INFO)
+	add_custom_target(doc_info ALL
+		DEPENDS ${MGL_OUT}/mathgl_en.info
+		DEPENDS ${MGL_OUT}/mathgl_ru.info
+	)
+# TODO: try to install all mathgl*.info* in future!!!
+	install(FILES ${MGL_OUT}/mathgl_en.info ${MGL_OUT}/mathgl_en.info-1 ${MGL_OUT}/mathgl_en.info-2 ${MGL_OUT}/mathgl_en.info-3 DESTINATION ${MGL_INFO_PATH})
+endif(MGL_HAVE_DOC_INFO)
+
+if(MGL_HAVE_DOC_HTML)
+	add_custom_target(doc_html ALL
+	DEPENDS ${MGL_OUT}/mgl_en.html
+	DEPENDS ${MGL_OUT}/mathgl_en.html
+	DEPENDS ${MGL_OUT}/mgl_ru.html
+	DEPENDS ${MGL_OUT}/mathgl_ru.html
+	)
+	install(FILES ${MGL_TEX}/qt.png ${MGL_TEX}/fltk.png ${MGL_TEX}/classes.png ${MGL_TEX}/datadvance.png DESTINATION ${MGL_DOC_PATH})
+	install(FILES ${MGL_OUT}/mathgl_en.html ${MGL_OUT}/mgl_en.html ${MGL_OUT}/mathgl_ru.html ${MGL_OUT}/mgl_ru.html DESTINATION ${MGL_DOC_PATH})
+	install(DIRECTORY ${MGL_OUT}/png DESTINATION ${MGL_DOC_PATH})
+	install(DIRECTORY ${MGL_OUT}/udav DESTINATION ${MGL_DOC_PATH})
+endif(MGL_HAVE_DOC_HTML)
+
+if(MGL_HAVE_DOC_SITE)
+	add_custom_target(doc_site ALL
+	DEPENDS ${site_en}
+	DEPENDS ${site_ru}
+	)
+endif(MGL_HAVE_DOC_SITE)
+
+if(MGL_HAVE_DOC_PDF_EN)
+	add_custom_target(doc_en ALL
+		DEPENDS ${MGL_OUT}/mgl_en.pdf
+		DEPENDS ${MGL_OUT}/mathgl_en.pdf
+	)
+	install(FILES ${MGL_OUT}/mathgl_en.pdf ${MGL_OUT}/mgl_en.pdf DESTINATION ${MGL_DOC_PATH})
+endif(MGL_HAVE_DOC_PDF_EN)
+
+if(MGL_HAVE_DOC_PDF_RU)
+	add_custom_target(doc_ru ALL
+#			DEPENDS ${MGL_OUT}/mgl_ru.pdf
+#			DEPENDS ${MGL_OUT}/mathgl_ru.pdf
+	)
+#		install(FILES ${MGL_OUT}/mathgl_ru.pdf DESTINATION ${MGL_DOC_PATH})
+endif(MGL_HAVE_DOC_PDF_RU)
+
+set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "doc_en;doc_ru;./mathgl*.*;./mgl*.*")
+
+install(FILES ${MGL_TEX}/mglconv.1 ${MGL_TEX}/mglview.1 ${MGL_TEX}/udav.1 ${MGL_TEX}/mgl.cgi.1 DESTINATION ${MGL_MAN_PATH}/man1)
+install(FILES ${MGL_TEX}/mgl.5 DESTINATION ${MGL_MAN_PATH}/man5)
diff --git a/texinfo/appendix_en.texi b/texinfo/appendix_en.texi
new file mode 100644
index 0000000..aa21d0b
--- /dev/null
+++ b/texinfo/appendix_en.texi
@@ -0,0 +1,69 @@
+ at nav{}
+
+The full list of TeX-like commands recognizable by MathGL is shown below. If command is not recognized then it will be printed as is by ommitting @samp{\} symbol. For example, @samp{\#} produce ``#'', @samp{\\} produce ``\'', @samp{\qq} produce ``qq''.
+ at c All commands are typed without @samp{\} sign.
+
+ at strong{Change case}: _, ^, @@.
+
+ at strong{Text style}: \big, \b, \textbf, \i, \textit, \bi, \r, \textrm, \a, \overline, \u, \underline, \w, \wire, #, \color[wkrgbcymhRGBCYMHWlenupqLENUPQ]
+
+ at strong{Roots}: \sqrt, \sqrt3, \sqrt4
+
+ at strong{Fractions}: \frac, \dfrac, \stack, \overset, \underset, \stackr, \stackl
+
+ at strong{Accents}: \hat, \tilde, \dot, \ddot, \dddot, \ddddot, \acute, \check, \grave, \vec, \bar, \breve
+
+ at strong{Special symbols}:
+
+\# (#), \% (%), \& (&), \^ (^).
+
+\AA (Å), \AE (Æ), \APLboxquestion (⍰), \APLboxupcaret (⍓), \APLnotbackslash (⍀), \APLnotslash (⌿), \Alpha (Α), \And (&), \Angstrom (Å), \Barv (⫧), \BbbC (ℂ), \BbbGamma (ℾ), \BbbH (ℍ), \BbbN (ℕ), \BbbP (ℙ), \BbbPi (ℿ), \BbbQ (ℚ), \BbbR (ℝ), \BbbZ (ℤ), \Bbbgamma (ℽ), \Bbbpi (ℼ), \Bbbsum (⅀), \Beta (Β), \Bumpeq (≎), \Cap (⋒), \Chi (Χ), \Colon (∷), \Coloneq (⩴), \Cup (⋓), \DDownarrow (⟱), \DH (Ð), \DJ (Đ), \DashV (⫥), \DashVDash (⟚), \Dashv (⫤), \Ddownarrow (⤋), \Delta (Δ), \Digamma (Ϝ), \Do [...]
+
+\aa (å), \ac (∾), \accurrent (⏦), \acidfree (♾), \acwcirclearrow (⥀), \acwgapcirclearrow (⟲), \acwleftarcarrow (⤹), \acwopencirclearrow (↺), \acwoverarcarrow (⤺), \acwundercurvearrow (⤻), \adots (⋰), \ae (æ), \aleph (ℵ), \alpha (α), \amalg (⨿), \angdnr (⦟), \angle (∠), \angles (⦞), \angleubar (⦤), \approx (≈), \approxeq (≊), \approxeqq (⩰), \approxident (≋), \arceq (≘), \aries (♈), \assert (⊦), \ast (∗), \asteq (⩮), \astrosun (☉), \asymp (≍), \awint (⨑).
+
+\bNot (⫭), \backcong (≌), \backdprime (‶), \backepsilon (϶), \backprime (‵), \backsim (∽), \backsimeq (⋍), \backslash (\), \backtrprime (‷), \bagmember (⋿), \barV (⫪), \barcap (⩃), \barcup (⩂), \bardownharpoonleft (⥡), \bardownharpoonright (⥝), \barleftarrow (⇤), \barleftarrowrightarrowbar (↹), \barleftharpoondown (⥖), \barleftharpoonup (⥒), \barovernorthwestarrow (↸), \barrightarrowdiamond (⤠), \barrightharpoondown (⥟), \barrightharpoonup (⥛), \baruparrow (⤒), \barupharpoonleft (⥘), \ba [...]
+
+\calB (ℬ), \calE (ℰ), \calF (ℱ), \calH (ℋ), \calM (ℳ), \calR (ℛ), \cap (∩), \capdot (⩀), \capwedge (⩄), \caretinsert (‸), \carreturn (⏎), \carriagereturn (↵), \ccwundercurvearrow (⤿), \cdot (⋅), \cdotp (·), \cdots (⋯), \cdprime (ʺ), \checkmark (✓), \chi (χ), \cirE (⧃), \cirbot (⟟), \circ (∘), \circeq (≗), \circfint (⨐), \circlebottomhalfblack (◒), \circledA (Ⓐ), \circledB (Ⓑ), \circledC (Ⓒ), \circledD (Ⓓ), \circledE (Ⓔ), \circledF (Ⓕ), \circledG (Ⓖ), \circledH (Ⓗ), \circledI (Ⓘ), \circle [...]
+
+\dag (†), \dagger (†), \daleth (ℸ), \danger (☡), \dashV (⫣), \dashVdash (⟛), \dashcolon (∹), \dashleftharpoondown (⥫), \dashrightharpoondown (⥭), \dashv (⊣), \dbkarow (⤏), \ddag (‡), \ddagger (‡), \ddots (⋱), \ddotseq (⩷), \delta (δ), \dh (ð), \diameter (⌀), \diamond (◇), \diamondbotblack (⬙), \diamondcdot (⟐), \diamondleftarrow (⤝), \diamondleftarrowbar (⤟), \diamondleftblack (⬖), \diamondrightblack (⬗), \diamondsuit (♢), \diamondtopblack (⬘), \dicei (⚀), \diceii (⚁), \diceiii (⚂), \dic [...]
+
+\earth (♁), \egsdot (⪘), \eighthnote (♪), \elinters (⏧), \ell (ℓ), \elsdot (⪗), \emdash (—), \emptyset (∅), \emptysetoarr (⦳), \emptysetoarrl (⦴), \emptysetobar (⦱), \emptysetocirc (⦲), \endash (–), \enleadertwodots (‥), \envelope (✉), \eparsl (⧣), \epsilon (ϵ), \eqcirc (≖), \eqcolon (≕), \eqdef (≝), \eqdot (⩦), \eqeq (⩵), \eqeqeq (⩶), \eqgtr (⋝), \eqless (⋜), \eqqgtr (⪚), \eqqless (⪙), \eqqplus (⩱), \eqqsim (⩳), \eqqslantgtr (⪜), \eqqslantless (⪛), \eqsim (≂), \eqslantgtr (⪖), \eqslantl [...]
+
+\fallingdotseq (≒), \fbowtie (⧓), \fcmp (⨾), \fdiagovnearrow (⤯), \fdiagovrdiag (⤬), \female (♀), \figdash (‒), \fint (⨏), \fisheye (◉), \flat (♭), \fltns (⏥), \forall (∀), \forks (⫝̸), \forksnot (⫝), \forkv (⫙), \fourthroot (∜), \fourvdots (⦙), \fracfiveeighths (⅝), \fracfivesixths (⅚), \fracfourfifths (⅘), \fraconeeighth (⅛), \fraconefifth (⅕), \fraconesixth (⅙), \fraconethird (⅓), \fracseveneights (⅞), \fracslash (⁄), \fracthreeeighths (⅜), \fracthreefifths (⅗), \fractwofifths (⅖), \fr [...]
+
+\gamma (γ), \ge (≥), \geq (≥), \geqq (≧), \geqslant (⩾), \gescc (⪩), \gesdot (⪀), \gesdoto (⪂), \gesdotol (⪄), \gesles (⪔), \gets (←), \gg (≫), \ggg (⋙), \gggnest (⫸), \gimel (ℷ), \glE (⪒), \gla (⪥), \gleichstark (⧦), \glj (⪤), \gnapprox (⪊), \gneq (⪈), \gneqq (≩), \gnsim (⋧), \greater (>), \gsime (⪎), \gsiml (⪐), \gtcc (⪧), \gtcir (⩺), \gtlpar (⦠), \gtquest (⩼), \gtrapprox (⪆), \gtrarr (⥸), \gtrdot (⋗), \gtreqless (⋛), \gtreqqless (⪌), \gtrless (≷), \gtrsim (≳), \guillemotleft («), \gui [...]
+
+\harrowextender (⎯), \hatapprox (⩯), \hbar (ℏ), \heartsuit (♡), \hermitmatrix (⊹), \hexagon (⎔), \hexagonblack (⬣), \hiraganano (の), \hknearrow (⤤), \hknwarrow (⤣), \hksearow (⤥), \hkswarow (⤦), \hookleftarrow (↩), \hookrightarrow (↪), \horizbar (―), \hourglass (⧖), \house (⌂), \hrectangle (▭), \hrectangleblack (▬), \hslash (ℏ), \hyphenbullet (⁃), \hzigzag (〰).
+
+\iiiint (⨌), \iiint (∭), \iinfin (⧜), \iint (∬), \imageof (⊷), \in (∈), \incare (℅), \increment (∆), \infty (∞), \int (∫), \intBar (⨎), \intbar (⨍), \intbottom (⌡), \intcap (⨙), \intclockwise (∱), \intcup (⨚), \intercal (⊺), \interleave (⫴), \intextender (⎮), \intlharhk (⨗), \intprod (⨼), \intprodr (⨽), \inttop (⌠), \intx (⨘), \inversebullet (◘), \inversewhitecircle (◙), \invnot (⌐), \invwhitelowerhalfcircle (◛), \invwhiteupperhalfcircle (◚), \iota (ι), \ipasupgamma (ˠ), \ipasupl (ˡ), \i [...]
+
+\jupiter (♃), \kappa (κ), \kernelcontraction (∻), \koppa (ϟ).
+
+\l (ł), \lAngle (⟪), \lBrace (⦃), \lBrack (⟦), \lParen (⦅), \lambda (λ), \lambdabar (ƛ), \langle (⟨), \langledot (⦑), \laplac (⧠), \lasp (ʽ), \lat (⪫), \late (⪭), \lbag (⟅), \lblkbrbrak (⦗), \lbrace (@{), \lbracelend (⎩), \lbracemid (⎨), \lbraceuend (⎧), \lbrack ([), \lbrackextender (⎢), \lbracklend (⎣), \lbracklltick (⦏), \lbrackubar (⦋), \lbrackuend (⎡), \lbrackultick (⦍), \lbrbrak (❲), \lceil (⌈), \lcurvyangle (⧼), \ldasharrhead (⇠), \le (≤), \leadsto (↝), \leftarrow (←), \leftarrowap [...]
+
+\male (♂), \maltese (✠), \mapsdown (↧), \mapsfrom (↤), \mapsto (↦), \mapsup (↥), \mdblkdiamond (⬥), \mdblklozenge (⬧), \mdblkrcl (⚫), \mdblksquare (◼), \mdlgblkcircle (●), \mdlgblkdiamond (◆), \mdlgblklozenge (⧫), \mdlgblksquare (■), \mdlgwhtcircle (○), \mdlgwhtdiamond (◇), \mdlgwhtsquare (□), \mdsmblkcircle (⦁), \mdsmblksquare (◾), \mdsmwhtcircl (⚬), \mdsmwhtsquare (◽), \mdwhtcircl (⚪), \mdwhtdiamond (⬦), \mdwhtlozenge (⬨), \mdwhtsquare (◻), \measangledltosw (⦯), \measangledrtose (⦮), \ [...]
+
+\nHdownarrow (⇟), \nHuparrow (⇞), \nLeftarrow (⇍), \nLeftrightarrow (⇎), \nRightarrow (⇏), \nVDash (⊯), \nVdash (⊮), \nVleftarrow (⇺), \nVleftarrowtail (⬺), \nVleftrightarrow (⇼), \nVrightarrow (⇻), \nVrightarrowtail (⤕), \nVtwoheadleftarrow (⬵), \nVtwoheadleftarrowtail (⬽), \nVtwoheadrightarrow (⤁), \nVtwoheadrightarrowtail (⤘), \nabla (∇), \napprox (≉), \nasymp (≭), \natural (♮), \ncong (≇), \ne (≠), \nearrow (↗), \neg (¬), \neovnwarrow (⤱), \neovsearrow (⤮), \neptune (♆), \neq (≠), \n [...]
+
+\o (ø), \obar (⌽), \obot (⦺), \obrbrak (⏠), \obslash (⦸), \odiv (⨸), \odot (⊙), \odotslashdot (⦼), \oe (œ), \ogreaterthan (⧁), \ohorn (ơ), \oiiint (∰), \oiint (∯), \oint (∮), \ointctrclockwise (∳), \olcross (⦻), \oldKoppa (Ϙ), \oldkoppa (ϙ), \olessthan (⧀), \omega (ω), \omicron (ο), \ominus (⊖), \operp (⦹), \oplus (⊕), \opluslhrim (⨭), \oplusrhrim (⨮), \origof (⊶), \oslash (⊘), \otimes (⊗), \otimeshat (⨶), \otimeslhrim (⨴), \otimesrhrim (⨵), \overbrace (⏞), \overbracket (⎴), \overline (‾ [...]
+
+\parallel (∥), \parallelogram (▱), \parallelogramblack (▰), \parsim (⫳), \partial (∂), \partialmeetcontraction (⪣), \pentagon (⬠), \pentagonblack (⬟), \perp (⟂), \perps (⫡), \phi (ϕ), \phone (☎), \pi (π), \pitchfork (⋔), \plusdot (⨥), \pluseqq (⩲), \plushat (⨣), \plussim (⨦), \plussubtwo (⨧), \plustrif (⨨), \pluto (♇), \pm (±), \pointnt (⨕), \postalmark (〒), \prec (≺), \precapprox (⪷), \preccurlyeq (≼), \preceq (⪯), \preceqq (⪳), \precnapprox (⪹), \precneq (⪱), \precneqq (⪵), \precnsim ( [...]
+
+\qprime (⁗), \quarternote (♩), \questeq (≟), \quotdblbase („), \quotdblright (‟), \quotsinglbase (‚), \quotsinglright (‛).
+
+\rAngle (⟫), \rBrace (⦄), \rBrack (⟧), \rParen (⦆), \rangle (⟩), \rangledot (⦒), \rangledownzigzagarrow (⍼), \rasp (ʼ), \rbag (⟆), \rblkbrbrak (⦘), \rbrace (@}), \rbracelend (⎭), \rbracemid (⎬), \rbraceuend (⎫), \rbrack (]), \rbrackextender (⎥), \rbracklend (⎦), \rbracklrtick (⦎), \rbrackubar (⦌), \rbrackuend (⎤), \rbrackurtick (⦐), \rbrbrak (❳), \rceil (⌉), \rcurvyangle (⧽), \rdiagovfdiag (⤫), \rdiagovsearrow (⤰), \recorder (⌕), \revangle (⦣), \revangleubar (⦥), \revemptyset (⦰), \revnm [...]
+
+\sampi (ϡ), \sansLmirrored (⅃), \sansLturned (⅂), \saturn (♄), \scissors (✂), \scpolint (⨓), \scrB (ℬ), \scrE (ℰ), \scrF (ℱ), \scrH (ℋ), \scrI (ℐ), \scrL (ℒ), \scrM (ℳ), \scrR (ℛ), \scre (ℯ), \scrg (ℊ), \scro (ℴ), \scurel (⊱), \searrow (↘), \seovnearrow (⤭), \setminus (∖), \setminus (⧵), \sharp (♯), \shortdowntack (⫟), \shortleftarrow (←), \shortlefttack (⫞), \shortrightarrow (→), \shortrightarrowleftarrow (⥄), \shortuptack (⫠), \shuffle (⧢), \sigma (σ), \silon (υ), \silon (ϒ), \sim (∼), [...]
+
+\talloblong (⫾), \target (⌖), \tau (τ), \taurus (♉), \testhookx (ᶍ), \textAsterisks (⁑), \textacute (ˊ), \textadvanced (˖), \textain (ʿ), \textasciiacute (´), \textasciicircum (^), \textasciidieresis (¨), \textasciigrave (`), \textasciimacron (¯), \textasciitilde (~), \textasterisklow (⁎), \textbackdprime (‶), \textbackprime (‵), \textbacktrprime (‷), \textbardotlessj (ɟ), \textbardotlessjvar (ʄ), \textbarglotstop (ʡ), \textbari (ɨ), \textbarl (ƚ), \textbaro (ɵ), \textbarrevglotstop (ʢ), [...]
+
+\ubrbrak (⏡), \uhorn (ư), \ularc (◜), \ulblacktriangle (◤), \ulcorner (⌜), \ulcrop (⌏), \ultriangle (◸), \uminus (⩁), \underbrace (⏟), \underbracket (⎵), \underparen (⏝), \unlhd (⊴), \unrhd (⊵), \upand (⅋), \uparrow (↑), \uparrowbarred (⤉), \uparrowoncircle (⦽), \updasharrow (⇢), \updownarrow (↕), \updownarrowbar (↨), \updownarrows (⇅), \updownharpoonleftleft (⥑), \updownharpoonleftright (⥍), \updownharpoonrightleft (⥌), \updownharpoonrightright (⥏), \updownharpoonsleftright (⥮), \upfish [...]
+
+\v (ˇ), \vBar (⫨), \vBarv (⫩), \vDash (⊨), \vDdash (⫢), \varTheta (ϴ), \varVdash (⫦), \varbarwedge (⌅), \varbeta (ϐ), \varclubsuit (♧), \vardiamondsuit (♦), \vardoublebarwedge (⌆), \varepsilon (ε), \varheartsuit (♥), \varhexagon (⬡), \varhexagonblack (⬢), \varhexagonlrbonds (⌬), \varin (∈), \varisinobar (⋶), \varisins (⋳), \varkappa (ϰ), \varlrtriangle (⊿), \varni (∋), \varniobar (⋽), \varnis (⋻), \varnothing (∅), \varointclockwise (∲), \varphi (φ), \varpi (ϖ), \varpropto (∝), \varrho (ϱ [...]
+
+\watchicon (⌚), \wedge (∧), \wedgebar (⩟), \wedgedot (⟑), \wedgedoublebar (⩠), \wedgemidvert (⩚), \wedgeodot (⩑), \wedgeonwedge (⩕), \wedgeq (≙), \whitearrowupfrombar (⇪), \whiteinwhitetriangle (⟁), \whitepointerleft (◅), \whitepointerright (▻), \whitesquaretickleft (⟤), \whitesquaretickright (⟥), \whthorzoval (⬭), \whtvertoval (⬯), \wideangledown (⦦), \wideangleup (⦧), \wp (℘), \wr (≀).
+
+\xbsol (⧹), \xi (ξ), \xsol (⧸), \yen (¥), \zeta (ζ), \zpipe (⨠), 
+
+IF ANYBODY WILL CHECK WHETHER ALL NAMES CORRESPOND TO RIGHT TEX SYMBOLS I SHALL APPRECIATE IT GREATLY. 
+
diff --git a/texinfo/appendix_ru.texi b/texinfo/appendix_ru.texi
new file mode 100644
index 0000000..06bf9d9
--- /dev/null
+++ b/texinfo/appendix_ru.texi
@@ -0,0 +1,67 @@
+ at nav{}
+
+Ниже приведен полный список TeX-их команд, распознаваемых MathGL. Если команда была не распознана, то она будет напечатана как есть с пропущенным символом @samp{\}. Например, @samp{\#} выдаст ``#'', @samp{\\} выдаст ``\'', @samp{\qq} выдаст ``qq''.
+
+ at strong{Положение символов}: _, ^, @@.
+
+ at strong{Стиль текста}: \big, \b, \textbf, \i, \textit, \bi, \r, \textrm, \a, \overline, \u, \underline, \w, \wire, #, \color[wkrgbcymhRGBCYMHWlenupqLENUPQ]
+
+ at strong{Корни}: \sqrt, \sqrt3, \sqrt4
+
+ at strong{Дроби}: \frac, \dfrac, \stack, \overset, \underset, \stackr, \stackl
+
+ at strong{Акценты}: \hat, \tilde, \dot, \ddot, \dddot, \ddddot, \acute, \check, \grave, \vec, \bar, \breve
+
+ at strong{Специальные символы}:
+\# (#), \% (%), \& (&), \^ (^).
+
+\AA (Å), \AE (Æ), \APLboxquestion (⍰), \APLboxupcaret (⍓), \APLnotbackslash (⍀), \APLnotslash (⌿), \Alpha (Α), \And (&), \Angstrom (Å), \Barv (⫧), \BbbC (ℂ), \BbbGamma (ℾ), \BbbH (ℍ), \BbbN (ℕ), \BbbP (ℙ), \BbbPi (ℿ), \BbbQ (ℚ), \BbbR (ℝ), \BbbZ (ℤ), \Bbbgamma (ℽ), \Bbbpi (ℼ), \Bbbsum (⅀), \Beta (Β), \Bumpeq (≎), \Cap (⋒), \Chi (Χ), \Colon (∷), \Coloneq (⩴), \Cup (⋓), \DDownarrow (⟱), \DH (Ð), \DJ (Đ), \DashV (⫥), \DashVDash (⟚), \Dashv (⫤), \Ddownarrow (⤋), \Delta (Δ), \Digamma (Ϝ), \Do [...]
+
+\aa (å), \ac (∾), \accurrent (⏦), \acidfree (♾), \acwcirclearrow (⥀), \acwgapcirclearrow (⟲), \acwleftarcarrow (⤹), \acwopencirclearrow (↺), \acwoverarcarrow (⤺), \acwundercurvearrow (⤻), \adots (⋰), \ae (æ), \aleph (ℵ), \alpha (α), \amalg (⨿), \angdnr (⦟), \angle (∠), \angles (⦞), \angleubar (⦤), \approx (≈), \approxeq (≊), \approxeqq (⩰), \approxident (≋), \arceq (≘), \aries (♈), \assert (⊦), \ast (∗), \asteq (⩮), \astrosun (☉), \asymp (≍), \awint (⨑).
+
+\bNot (⫭), \backcong (≌), \backdprime (‶), \backepsilon (϶), \backprime (‵), \backsim (∽), \backsimeq (⋍), \backslash (\), \backtrprime (‷), \bagmember (⋿), \barV (⫪), \barcap (⩃), \barcup (⩂), \bardownharpoonleft (⥡), \bardownharpoonright (⥝), \barleftarrow (⇤), \barleftarrowrightarrowbar (↹), \barleftharpoondown (⥖), \barleftharpoonup (⥒), \barovernorthwestarrow (↸), \barrightarrowdiamond (⤠), \barrightharpoondown (⥟), \barrightharpoonup (⥛), \baruparrow (⤒), \barupharpoonleft (⥘), \ba [...]
+
+\calB (ℬ), \calE (ℰ), \calF (ℱ), \calH (ℋ), \calM (ℳ), \calR (ℛ), \cap (∩), \capdot (⩀), \capwedge (⩄), \caretinsert (‸), \carreturn (⏎), \carriagereturn (↵), \ccwundercurvearrow (⤿), \cdot (⋅), \cdotp (·), \cdots (⋯), \cdprime (ʺ), \checkmark (✓), \chi (χ), \cirE (⧃), \cirbot (⟟), \circ (∘), \circeq (≗), \circfint (⨐), \circlebottomhalfblack (◒), \circledA (Ⓐ), \circledB (Ⓑ), \circledC (Ⓒ), \circledD (Ⓓ), \circledE (Ⓔ), \circledF (Ⓕ), \circledG (Ⓖ), \circledH (Ⓗ), \circledI (Ⓘ), \circle [...]
+
+\dag (†), \dagger (†), \daleth (ℸ), \danger (☡), \dashV (⫣), \dashVdash (⟛), \dashcolon (∹), \dashleftharpoondown (⥫), \dashrightharpoondown (⥭), \dashv (⊣), \dbkarow (⤏), \ddag (‡), \ddagger (‡), \ddots (⋱), \ddotseq (⩷), \delta (δ), \dh (ð), \diameter (⌀), \diamond (◇), \diamondbotblack (⬙), \diamondcdot (⟐), \diamondleftarrow (⤝), \diamondleftarrowbar (⤟), \diamondleftblack (⬖), \diamondrightblack (⬗), \diamondsuit (♢), \diamondtopblack (⬘), \dicei (⚀), \diceii (⚁), \diceiii (⚂), \dic [...]
+
+\earth (♁), \egsdot (⪘), \eighthnote (♪), \elinters (⏧), \ell (ℓ), \elsdot (⪗), \emdash (—), \emptyset (∅), \emptysetoarr (⦳), \emptysetoarrl (⦴), \emptysetobar (⦱), \emptysetocirc (⦲), \endash (–), \enleadertwodots (‥), \envelope (✉), \eparsl (⧣), \epsilon (ϵ), \eqcirc (≖), \eqcolon (≕), \eqdef (≝), \eqdot (⩦), \eqeq (⩵), \eqeqeq (⩶), \eqgtr (⋝), \eqless (⋜), \eqqgtr (⪚), \eqqless (⪙), \eqqplus (⩱), \eqqsim (⩳), \eqqslantgtr (⪜), \eqqslantless (⪛), \eqsim (≂), \eqslantgtr (⪖), \eqslantl [...]
+
+\fallingdotseq (≒), \fbowtie (⧓), \fcmp (⨾), \fdiagovnearrow (⤯), \fdiagovrdiag (⤬), \female (♀), \figdash (‒), \fint (⨏), \fisheye (◉), \flat (♭), \fltns (⏥), \forall (∀), \forks (⫝̸), \forksnot (⫝), \forkv (⫙), \fourthroot (∜), \fourvdots (⦙), \fracfiveeighths (⅝), \fracfivesixths (⅚), \fracfourfifths (⅘), \fraconeeighth (⅛), \fraconefifth (⅕), \fraconesixth (⅙), \fraconethird (⅓), \fracseveneights (⅞), \fracslash (⁄), \fracthreeeighths (⅜), \fracthreefifths (⅗), \fractwofifths (⅖), \fr [...]
+
+\gamma (γ), \ge (≥), \geq (≥), \geqq (≧), \geqslant (⩾), \gescc (⪩), \gesdot (⪀), \gesdoto (⪂), \gesdotol (⪄), \gesles (⪔), \gets (←), \gg (≫), \ggg (⋙), \gggnest (⫸), \gimel (ℷ), \glE (⪒), \gla (⪥), \gleichstark (⧦), \glj (⪤), \gnapprox (⪊), \gneq (⪈), \gneqq (≩), \gnsim (⋧), \greater (>), \gsime (⪎), \gsiml (⪐), \gtcc (⪧), \gtcir (⩺), \gtlpar (⦠), \gtquest (⩼), \gtrapprox (⪆), \gtrarr (⥸), \gtrdot (⋗), \gtreqless (⋛), \gtreqqless (⪌), \gtrless (≷), \gtrsim (≳), \guillemotleft («), \gui [...]
+
+\harrowextender (⎯), \hatapprox (⩯), \hbar (ℏ), \heartsuit (♡), \hermitmatrix (⊹), \hexagon (⎔), \hexagonblack (⬣), \hiraganano (の), \hknearrow (⤤), \hknwarrow (⤣), \hksearow (⤥), \hkswarow (⤦), \hookleftarrow (↩), \hookrightarrow (↪), \horizbar (―), \hourglass (⧖), \house (⌂), \hrectangle (▭), \hrectangleblack (▬), \hslash (ℏ), \hyphenbullet (⁃), \hzigzag (〰).
+
+\iiiint (⨌), \iiint (∭), \iinfin (⧜), \iint (∬), \imageof (⊷), \in (∈), \incare (℅), \increment (∆), \infty (∞), \int (∫), \intBar (⨎), \intbar (⨍), \intbottom (⌡), \intcap (⨙), \intclockwise (∱), \intcup (⨚), \intercal (⊺), \interleave (⫴), \intextender (⎮), \intlharhk (⨗), \intprod (⨼), \intprodr (⨽), \inttop (⌠), \intx (⨘), \inversebullet (◘), \inversewhitecircle (◙), \invnot (⌐), \invwhitelowerhalfcircle (◛), \invwhiteupperhalfcircle (◚), \iota (ι), \ipasupgamma (ˠ), \ipasupl (ˡ), \i [...]
+
+\jupiter (♃), \kappa (κ), \kernelcontraction (∻), \koppa (ϟ).
+
+\l (ł), \lAngle (⟪), \lBrace (⦃), \lBrack (⟦), \lParen (⦅), \lambda (λ), \lambdabar (ƛ), \langle (⟨), \langledot (⦑), \laplac (⧠), \lasp (ʽ), \lat (⪫), \late (⪭), \lbag (⟅), \lblkbrbrak (⦗), \lbrace (@{), \lbracelend (⎩), \lbracemid (⎨), \lbraceuend (⎧), \lbrack ([), \lbrackextender (⎢), \lbracklend (⎣), \lbracklltick (⦏), \lbrackubar (⦋), \lbrackuend (⎡), \lbrackultick (⦍), \lbrbrak (❲), \lceil (⌈), \lcurvyangle (⧼), \ldasharrhead (⇠), \le (≤), \leadsto (↝), \leftarrow (←), \leftarrowap [...]
+
+\male (♂), \maltese (✠), \mapsdown (↧), \mapsfrom (↤), \mapsto (↦), \mapsup (↥), \mdblkdiamond (⬥), \mdblklozenge (⬧), \mdblkrcl (⚫), \mdblksquare (◼), \mdlgblkcircle (●), \mdlgblkdiamond (◆), \mdlgblklozenge (⧫), \mdlgblksquare (■), \mdlgwhtcircle (○), \mdlgwhtdiamond (◇), \mdlgwhtsquare (□), \mdsmblkcircle (⦁), \mdsmblksquare (◾), \mdsmwhtcircl (⚬), \mdsmwhtsquare (◽), \mdwhtcircl (⚪), \mdwhtdiamond (⬦), \mdwhtlozenge (⬨), \mdwhtsquare (◻), \measangledltosw (⦯), \measangledrtose (⦮), \ [...]
+
+\nHdownarrow (⇟), \nHuparrow (⇞), \nLeftarrow (⇍), \nLeftrightarrow (⇎), \nRightarrow (⇏), \nVDash (⊯), \nVdash (⊮), \nVleftarrow (⇺), \nVleftarrowtail (⬺), \nVleftrightarrow (⇼), \nVrightarrow (⇻), \nVrightarrowtail (⤕), \nVtwoheadleftarrow (⬵), \nVtwoheadleftarrowtail (⬽), \nVtwoheadrightarrow (⤁), \nVtwoheadrightarrowtail (⤘), \nabla (∇), \napprox (≉), \nasymp (≭), \natural (♮), \ncong (≇), \ne (≠), \nearrow (↗), \neg (¬), \neovnwarrow (⤱), \neovsearrow (⤮), \neptune (♆), \neq (≠), \n [...]
+
+\o (ø), \obar (⌽), \obot (⦺), \obrbrak (⏠), \obslash (⦸), \odiv (⨸), \odot (⊙), \odotslashdot (⦼), \oe (œ), \ogreaterthan (⧁), \ohorn (ơ), \oiiint (∰), \oiint (∯), \oint (∮), \ointctrclockwise (∳), \olcross (⦻), \oldKoppa (Ϙ), \oldkoppa (ϙ), \olessthan (⧀), \omega (ω), \omicron (ο), \ominus (⊖), \operp (⦹), \oplus (⊕), \opluslhrim (⨭), \oplusrhrim (⨮), \origof (⊶), \oslash (⊘), \otimes (⊗), \otimeshat (⨶), \otimeslhrim (⨴), \otimesrhrim (⨵), \overbrace (⏞), \overbracket (⎴), \overline (‾ [...]
+
+\parallel (∥), \parallelogram (▱), \parallelogramblack (▰), \parsim (⫳), \partial (∂), \partialmeetcontraction (⪣), \pentagon (⬠), \pentagonblack (⬟), \perp (⟂), \perps (⫡), \phi (ϕ), \phone (☎), \pi (π), \pitchfork (⋔), \plusdot (⨥), \pluseqq (⩲), \plushat (⨣), \plussim (⨦), \plussubtwo (⨧), \plustrif (⨨), \pluto (♇), \pm (±), \pointnt (⨕), \postalmark (〒), \prec (≺), \precapprox (⪷), \preccurlyeq (≼), \preceq (⪯), \preceqq (⪳), \precnapprox (⪹), \precneq (⪱), \precneqq (⪵), \precnsim ( [...]
+
+\qprime (⁗), \quarternote (♩), \questeq (≟), \quotdblbase („), \quotdblright (‟), \quotsinglbase (‚), \quotsinglright (‛).
+
+\rAngle (⟫), \rBrace (⦄), \rBrack (⟧), \rParen (⦆), \rangle (⟩), \rangledot (⦒), \rangledownzigzagarrow (⍼), \rasp (ʼ), \rbag (⟆), \rblkbrbrak (⦘), \rbrace (@}), \rbracelend (⎭), \rbracemid (⎬), \rbraceuend (⎫), \rbrack (]), \rbrackextender (⎥), \rbracklend (⎦), \rbracklrtick (⦎), \rbrackubar (⦌), \rbrackuend (⎤), \rbrackurtick (⦐), \rbrbrak (❳), \rceil (⌉), \rcurvyangle (⧽), \rdiagovfdiag (⤫), \rdiagovsearrow (⤰), \recorder (⌕), \revangle (⦣), \revangleubar (⦥), \revemptyset (⦰), \revnm [...]
+
+\sampi (ϡ), \sansLmirrored (⅃), \sansLturned (⅂), \saturn (♄), \scissors (✂), \scpolint (⨓), \scrB (ℬ), \scrE (ℰ), \scrF (ℱ), \scrH (ℋ), \scrI (ℐ), \scrL (ℒ), \scrM (ℳ), \scrR (ℛ), \scre (ℯ), \scrg (ℊ), \scro (ℴ), \scurel (⊱), \searrow (↘), \seovnearrow (⤭), \setminus (∖), \setminus (⧵), \sharp (♯), \shortdowntack (⫟), \shortleftarrow (←), \shortlefttack (⫞), \shortrightarrow (→), \shortrightarrowleftarrow (⥄), \shortuptack (⫠), \shuffle (⧢), \sigma (σ), \silon (υ), \silon (ϒ), \sim (∼), [...]
+
+\talloblong (⫾), \target (⌖), \tau (τ), \taurus (♉), \testhookx (ᶍ), \textAsterisks (⁑), \textacute (ˊ), \textadvanced (˖), \textain (ʿ), \textasciiacute (´), \textasciicircum (^), \textasciidieresis (¨), \textasciigrave (`), \textasciimacron (¯), \textasciitilde (~), \textasterisklow (⁎), \textbackdprime (‶), \textbackprime (‵), \textbacktrprime (‷), \textbardotlessj (ɟ), \textbardotlessjvar (ʄ), \textbarglotstop (ʡ), \textbari (ɨ), \textbarl (ƚ), \textbaro (ɵ), \textbarrevglotstop (ʢ), [...]
+
+\ubrbrak (⏡), \uhorn (ư), \ularc (◜), \ulblacktriangle (◤), \ulcorner (⌜), \ulcrop (⌏), \ultriangle (◸), \uminus (⩁), \underbrace (⏟), \underbracket (⎵), \underparen (⏝), \unlhd (⊴), \unrhd (⊵), \upand (⅋), \uparrow (↑), \uparrowbarred (⤉), \uparrowoncircle (⦽), \updasharrow (⇢), \updownarrow (↕), \updownarrowbar (↨), \updownarrows (⇅), \updownharpoonleftleft (⥑), \updownharpoonleftright (⥍), \updownharpoonrightleft (⥌), \updownharpoonrightright (⥏), \updownharpoonsleftright (⥮), \upfish [...]
+
+\v (ˇ), \vBar (⫨), \vBarv (⫩), \vDash (⊨), \vDdash (⫢), \varTheta (ϴ), \varVdash (⫦), \varbarwedge (⌅), \varbeta (ϐ), \varclubsuit (♧), \vardiamondsuit (♦), \vardoublebarwedge (⌆), \varepsilon (ε), \varheartsuit (♥), \varhexagon (⬡), \varhexagonblack (⬢), \varhexagonlrbonds (⌬), \varin (∈), \varisinobar (⋶), \varisins (⋳), \varkappa (ϰ), \varlrtriangle (⊿), \varni (∋), \varniobar (⋽), \varnis (⋻), \varnothing (∅), \varointclockwise (∲), \varphi (φ), \varpi (ϖ), \varpropto (∝), \varrho (ϱ [...]
+
+\watchicon (⌚), \wedge (∧), \wedgebar (⩟), \wedgedot (⟑), \wedgedoublebar (⩠), \wedgemidvert (⩚), \wedgeodot (⩑), \wedgeonwedge (⩕), \wedgeq (≙), \whitearrowupfrombar (⇪), \whiteinwhitetriangle (⟁), \whitepointerleft (◅), \whitepointerright (▻), \whitesquaretickleft (⟤), \whitesquaretickright (⟥), \whthorzoval (⬭), \whtvertoval (⬯), \wideangledown (⦦), \wideangleup (⦧), \wp (℘), \wr (≀).
+
+\xbsol (⧹), \xi (ξ), \xsol (⧸), \yen (¥), \zeta (ζ), \zpipe (⨠), 
+
+Я БУДУ КРАЙНЕ ПРИЗНАТЕЛЕН ЕСЛИ КТО-НИБУДЬ ПРОВЕРИТ СООТВЕТСТВИЕ ВСЕХ ИМЕН ПРАВИЛЬНЫМ ТЕХ-ИМ СИМВОЛАМ. 
+
diff --git a/texinfo/classes.dia b/texinfo/classes.dia
new file mode 100644
index 0000000..80f25ac
Binary files /dev/null and b/texinfo/classes.dia differ
diff --git a/texinfo/classes.pdf b/texinfo/classes.pdf
new file mode 100644
index 0000000..dc97539
Binary files /dev/null and b/texinfo/classes.pdf differ
diff --git a/texinfo/classes.png b/texinfo/classes.png
new file mode 100644
index 0000000..fbd2ee2
Binary files /dev/null and b/texinfo/classes.png differ
diff --git a/texinfo/concept_en.texi b/texinfo/concept_en.texi
new file mode 100644
index 0000000..4a318f8
--- /dev/null
+++ b/texinfo/concept_en.texi
@@ -0,0 +1,396 @@
+ at chapter General concepts
+ at nav{}
+
+The set of MathGL features is rather rich -- just the number of basic graphics types
+is larger than 50. Also there are functions for data handling, plot setup and so on. In spite of it I tried to keep a similar style in function names and in the order of arguments. Mostly it is
+used for different drawing functions.
+
+There are six most general (base) concepts:
+ at enumerate
+ at item
+ at strong{Any picture is created in memory first.} The internal (memory) representation can be different: bitmap picture (for @code{SetQuality(MGL_DRAW_LMEM)} or @code{@ref{quality} 6}) or the list of vector primitives (default). After that the user may decide what he/she want: save to file, display on the screen, run animation, do additional editing and so on. This approach assures a high portability of the program -- the source code will produce exactly the same picture in @emph{any} OS. [...]
+ at item
+ at strong{Every plot settings (style of lines, font, color scheme) are specified by a string.} It provides convenience for user/programmer -- short string with parameters is more comprehensible than a large set of parameters. Also it provides portability -- the strings are the same in any OS so that it is not necessary to think about argument types.
+ at item
+ at strong{All functions have ``simplified'' and ``advanced'' forms.} It is done for user's convenience. One needs to specify only one data array in the ``simplified'' form in order to see the result. But one may set parametric dependence of coordinates and produce rather complex curves and surfaces in the ``advanced'' form. In both cases the order of function arguments is the same: first data arrays, second the string with style, and later string with options for additional plot tuning.
+ at item
+ at strong{All data arrays for plotting are encapsulated in mglData(A) class.} This reduces the number of errors while working with memory and provides a uniform interface for data of different types (mreal, double and so on) or for formula plotting.
+ at item
+ at strong{All plots are vector plots.} The MathGL library is intended for handling scientific data which have vector nature (lines, faces, matrices and so on). As a result, vector representation is used in all cases! In addition, the vector representation allows one to scale the plot easily -- change the canvas size by a factor of 2, and the picture will be proportionally scaled.
+ at item
+ at strong{New drawing never clears things drawn already.} This, in some sense, unexpected, idea allows to create a lot of ``combined'' graphics. For example, to make a surface with contour lines one needs to call the function for surface plotting and the function for contour lines plotting (in any order). Thus the special functions for making this ``combined'' plots (as it is done in Matlab and some other plotting systems) are superfluous.
+ at end enumerate
+
+In addition to the general concepts I want to comment on some non-trivial or less commonly used general ideas -- plot positioning, axis specification and curvilinear coordinates, styles for lines, text and color scheme.
+
+ at menu
+* Coordinate axes::
+* Color styles::
+* Line styles::
+* Color scheme::
+* Font styles::
+* Textual formulas::
+* Command options::
+* Interfaces::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Coordinate axes, Color styles, , General concepts
+ at section Coordinate axes
+ at nav{}
+
+Two axis representations are used in MathGL. The first one consists of normalizing coordinates of data points in axis range (see @ref{Axis settings}). If @code{SetCut()} is @code{true} then the outlier points are omitted, otherwise they are projected to the bounding box (see @ref{Cutting}). Also, the point will be omitted if it lies inside the box defined by @code{SetCutBox()} or if the value of formula @code{CutOff()} is nonzero for its coordinates. After that, transformation formulas d [...]
+
+The range of @emph{x, y, z}-axis can be specified by @code{SetRange()} or @ref{ranges} functions. Its origin is specified by @ref{origin} function. At this you can you can use @code{NAN} values for selecting axis origin automatically.
+
+There is 4-th axis @emph{c} (color axis or colorbar) in addition to the usual axes @emph{x, y, z}. It sets the range of values for the surface coloring. Its borders are automatically set to values of z-range during the call of @ref{ranges} function. Also, one can directly set it by call @code{SetRange('c', ...)}. Use @ref{colorbar} function for drawing the colorbar.
+
+The form (appearence) of tick labels is controlled by @code{SetTicks()} function (@pxref{Ticks}). Function @var{SetTuneTicks} switches on/off tick enhancing by factoring out acommon multiplier (for small coordinate values, like 0.001 to 0.002, or large, like from 1000 to 2000) or common component (for narrow range, like from 0.999 to 1.000). Finally, you may use functions @code{SetTickTempl()} for setting templates for tick labels (it supports TeX symbols). Also, there is a possibility t [...]
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Color styles, Line styles, Coordinate axes, General concepts
+ at section Color styles
+ at nav{}
+
+Base colors are defined by one of symbol @samp{wkrgbcymhRGBCYMHWlenupqLENUPQ}.
+ at ifhtml
+ at html
+<p>The color types are: ‘<samp>k</samp>’ – black, ‘<samp>r</samp>’ – <span style="color: rgb(255, 0, 0);">red</span>, ‘<samp>R</samp>’ – <span style="color: rgb(127, 0, 0);">dark red</span>, ‘<samp>g</samp>’ – <span style="color: rgb(0, 255, 0);">green</span>, ‘<samp>G</samp>’ – <span style="color: rgb(0, 127, 0);">dark green</span>, ‘<samp>b</samp>’ – <span style="color: rgb(0, 0, [...]
+ at end html
+ at end ifhtml
+ at ifnothtml
+The color types are: @samp{k} -- black, @samp{r} -- red, @samp{R} -- dark red, @samp{g} -- green, @samp{G} -- dark green, @samp{b} -- blue, @samp{B} -- dark blue, @samp{c} -- cyan, @samp{C} -- dark cyan, @samp{m} -- magenta, @samp{M} -- dark magenta, @samp{y} -- yellow, @samp{Y} -- dark yellow (gold), @samp{h} -- gray, @samp{H} -- dark gray, @samp{w} -- white, @samp{W} -- bright gray, @samp{l} -- green-blue, @samp{L} -- dark green-blue, @samp{e} -- green-yellow, @samp{E} -- dark green-ye [...]
+ at end ifnothtml
+
+You can also use ``bright'' colors. The ``bright'' color contain 2 symbols in brackets @samp{@{cN@}}: first one is the usual symbol for color id, the second one is a digit for its brightness. The digit can be in range @samp{1}... at samp{9}. Number @samp{5} corresponds to a normal color, @samp{1} is a very dark version of the color (practically black), and @samp{9} is a very bright version of the color (practically white). For example, the colors can be @samp{@{b2@}} @samp{@{b7@}} @samp{@{r [...]
+
+Finally, you can specify RGB or RGBA values of a color using format @samp{@{xRRGGBB@}} or @samp{@{xRRGGBBAA@}} correspondingly. For example, @samp{@{xFF9966@}} give you
+ at ifhtml
+ at html
+<span style="color: rgb(255, 153, 102);">melone</span> color.
+ at end html
+ at end ifhtml
+ at ifnothtml
+melone color.
+ at end ifnothtml
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Line styles, Color scheme, Color styles, General concepts
+ at section Line styles
+ at nav{}
+
+ at cindex Line style
+ at cindex Mark style
+ at cindex Arrows
+
+The line style is defined by the string which may contain specifications for color (@samp{wkrgbcymhRGBCYMHWlenupqLENUPQ}), dashing style (@samp{-|;:ji=} or space), width (@samp{123456789}) and marks (@samp{*o+xsd.^v<>} and @samp{#} modifier). If one of the type of information is omitted then default values used with next color from palette (see @ref{Palette and colors}). Note, that internal color counter will be nullified by any change of palette. This includes even hidden change (for ex [...]
+ at ifhtml
+ at html
+By default palette contain following colors: <span style="color: rgb(76, 76, 76);">dark gray</span> ‘<samp>H</samp>’, <span style="color: rgb(0, 0, 255);">blue</span> ‘<samp>b</samp>’, <span style="color: rgb(0, 255, 0);">green</span> ‘<samp>g</samp>’, <span style="color: rgb(255, 0, 0);">red</span> ‘<samp>r</samp>’, <span style="color: rgb(0, 255, 255);">cyan</span> ‘<samp>c</samp>’, <span style="color: rgb(255, 0, 255);">magen [...]
+
+<p>Dashing style has the following meaning: space – no line (usable for plotting only marks), ‘<samp>-</samp>’ – solid line (■■■■■■■■■■■■■■■■), ‘<samp>|</samp>’ – long dashed line (■■■■■■■■□□□□□□□□), ‘<samp>;</samp>’ – dashed line (■& [...]
+ at end html
+ at end ifhtml
+ at ifnothtml
+By default palette contain following colors: dark gray @samp{H}, blue @samp{b}, green @samp{g}, red @samp{r}, cyan @samp{c}, magenta @samp{m}, yellow @samp{y}, gray @samp{h}, blue-green @samp{l}, sky-blue @samp{n}, orange @samp{q}, yellow-green @samp{e}, blue-violet @samp{u}, purple @samp{p}.
+
+Dashing style has the following meaning: space -- no line (usable for plotting only marks), @samp{-} -- solid line (################), @samp{|} -- long dashed line (########________), @samp{;} -- dashed line (####____####____), @samp{=} -- small dashed line (##__##__##__##__), @samp{:} -- dotted line (#___#___#___#___), @samp{j} -- dash-dotted line (#######____#____), @samp{i} -- small dash-dotted line (###__#__###__#__), @samp{@{dNNNN@}} -- manual mask style (for v.2.3 and later, like @ [...]
+ at end ifnothtml
+
+Marker types are: @samp{o} -- circle, @samp{+} -- cross, @samp{x} -- skew cross, @samp{s} -- square, @samp{d} -- rhomb (or diamond), @samp{.} -- dot (point), @samp{^} -- triangle up, @samp{v} -- triangle down, @samp{<} -- triangle left, @samp{>} -- triangle right, @samp{#*} -- Y sign, @samp{#+} -- squared cross, @samp{#x} -- squared skew cross, @samp{#.} -- circled dot. If string contain symbol @samp{#} then the solid versions of markers are used.
+
+You can provide user-defined symbols (see @ref{addsymbol}) to draw it as marker by using @samp{&} style. In particular, @samp{&*}, @samp{&o}, @samp{&+}, @samp{&x}, @samp{&s}, @samp{&d}, @samp{&.}, @samp{&^}, @samp{&v}, @samp{&<}, @samp{&>} will draw user-defined symbol @samp{*o+xsd.^v<>} correspondingly; and 
+ at samp{&#o}, @samp{&#+}, @samp{&#x}, @samp{&#s}, @samp{&#d}, @samp{&#.}, @samp{&#^}, @samp{&#v}, @samp{&#<}, @samp{&#>} will draw user-defined symbols @samp{YOPXSDCTVLR} correspondingly. Note, that wired version of user-defined symbols will be drawn if you set negative marker size (see @ref{marksize} or @code{size} in @ref{Command options}).
+
+One may specify to draw a special symbol (an arrow) at the beginning and at the end of line. This is done if the specification string contains one of the following symbols: @samp{A} -- outer arrow, @samp{V} -- inner arrow, @samp{I} -- transverse hatches, @samp{K} -- arrow with hatches, @samp{T} -- triangle, @samp{S} -- square, @samp{D} -- rhombus, @samp{O} -- circle, @samp{X} -- skew cross, @samp{_} -- nothing (the default). The following rule applies: the first symbol specifies the arro [...]
+
+ at pfig{style, Color and line styles.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Color scheme, Font styles, Line styles, General concepts
+ at section Color scheme
+ at nav{}
+
+ at cindex Color scheme
+
+The color scheme is used for determining the color of surfaces, isolines, isosurfaces and so on. The color scheme is defined by the string, which may contain several characters that are color id (@pxref{Line styles}) or characters @samp{#:|}. Symbol @samp{#} switches to mesh drawing or to a wire plot. Symbol @samp{|} disables color interpolation in color scheme, which can be useful, for example, for sharp colors during matrix plotting. Symbol @samp{:} terminate the color scheme parsing.  [...]
+
+The final color is a linear interpolation of color array. The color array is constructed from the string ids (including ``bright'' colors, see @ref{Color styles}). The argument is the amplitude normalized in color range (see @ref{Axis settings}). For example, string containing 4 characters @samp{bcyr} corresponds to a colorbar from blue (lowest value) through cyan (next value) through yellow (next value) to the red (highest value). String @samp{kw} corresponds to a colorbar from black (l [...]
+
+The special 2-axis color scheme (like in @ref{map} plot) can be used if it contain symbol @samp{%}. In this case the second direction (alpha channel) is used as second coordinate for colors. At this, up to 4 colors can be specified for corners: @{c1,a1@}, @{c2,a1@}, @{c1,a2@}, @{c2,a2@}. Here color and alpha ranges are @{c1,c2@} and @{a1,a2@} correspondingly. If one specify less than 4 colors then black color is used for corner @{c1,a1@}. If only 2 colors are specified then the color of  [...]
+
+There are several useful combinations. String @samp{kw} corresponds to the simplest gray color scheme where higher values are brighter. String @samp{wk} presents the inverse gray color scheme where higher value is darker. Strings @samp{kRryw}, @samp{kGgw}, @samp{kBbcw} present the well-known @emph{hot}, @emph{summer} and @emph{winter} color schemes. Strings @samp{BbwrR} and @samp{bBkRr} allow to view bi-color figure on white or black background, where negative values are blue and positiv [...]
+
+For more precise coloring, you can change default (equidistant) position of colors in color scheme. The format is @samp{@{CN,pos@}}, @samp{@{CN,pos@}} or @samp{@{xRRGGBB,pos@}}. The position value @var{pos} should be in range [0, 1]. Note, that alternative method for fine tuning of the color scheme is using the formula for coloring (see @ref{Curved coordinates}).
+
+ at pfig{schemes, Most popular color schemes.}
+
+When coloring by @emph{coordinate} (used in @ref{map}), the final color is determined by the position of the point in 3d space and is calculated from formula c=x*c[1] + y*c[2]. Here, c[1], c[2] are the first two elements of color array; x, y are normalized to axis range coordinates of the point.
+ at c This type of coloring is useful for isosurface plot where color may show the exact position of a piece of surface.
+
+Additionally, MathGL can apply mask to face filling at bitmap rendering. The kind of mask is specified by one of symbols @samp{-+=;oOsS~<>jdD*^} in color scheme. Mask can be rotated by arbitrary angle by command @ref{mask} or by three predefined values +45, -45 and 90 degree by symbols @samp{\/I} correspondingly. Examples of predefined masks are shown on the figure below.
+
+ at pfig{mask, Example of masks for face coloring.}
+
+However, you can redefine mask for one symbol by specifying new matrix of size 8*8 as second argument for @ref{mask} command. For example, the right-down subplot on the figure above is produced by code@*
+ at ifclear UDAV
+ at code{gr->SetMask('+', "ff00182424f800");	gr->Dens(a,"3+");}@*
+or just use manual mask style (for v.2.3 and later)@*
+ at code{gr->Dens(a,"3@{s00ff00182424f800@}");}
+ at end ifclear
+ at ifset UDAV
+ at code{mask '+' 'ff00182424f800':dens a '3+'}@*
+or just use manual mask style (for v.2.3 and later)@*
+ at code{dens a '3@{s00ff00182424f800@}'}
+ at end ifset
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Font styles, Textual formulas, Color scheme, General concepts
+ at section Font styles
+ at nav{}
+
+ at cindex Font styles
+
+Text style is specified by the string which may contain: color id characters @samp{wkrgbcymhRGBCYMHW} (see @ref{Color styles}), and font style (@samp{ribwou}) and/or alignment (@samp{LRC}) specifications. At this, font style and alignment begin after the separator @samp{:}. For example, @samp{r:iCb} sets the bold (@samp{b}) italic (@samp{i}) font text aligned at the center (@samp{C}) and with red color (@samp{r}). Starting from MathGL v.2.3, you can set not single color for whole text, b [...]
+
+The font styles are: @samp{r} -- roman (or regular) font, @samp{i} -- italic style, @samp{b} -- bold style. By default roman roman font is used. The align types are: @samp{L} -- align left (default), @samp{C} -- align center, @samp{R} -- align right, @samp{T} -- align under, @samp{V} -- align center vertical. Additional font effects are: @samp{w} -- wired, @samp{o} -- over-lined, @samp{u} -- underlined.
+
+Also a parsing of the LaTeX-like syntax is provided. There are commands for the font style changing inside the string (for example, use \b for bold font): \a or \overline -- over-lined, \b or \textbf -- bold, \i or \textit -- italic, \r or \textrm -- roman (disable bold and italic attributes), \u or \underline -- underlined, \w or \wire -- wired, \big -- bigger size, @@ -- smaller size. The lower and upper indexes are specified by @samp{_} and @samp{^} symbols. At this the changed font s [...]
+ at ifhtml
+ at html
+ α symbol.
+ at end html
+ at end ifhtml
+ at ifnothtml
+ @math{\alpha} symbol.
+ at end ifnothtml
+
+The most of commands for special TeX or AMSTeX symbols, the commands for font style changing (\textrm, \textbf, \textit, \textsc, \overline, \underline), accents (\hat, \tilde, \dot, \ddot, \acute, \check, \grave, \bar, \breve) and roots (\sqrt, \sqrt3, \sqrt4) are recognized. The full list contain approximately 2000 commands. Note that first space symbol after the command is ignored, but second one is printed as normal symbol (space). For example, the following strings produce the same  [...]
+
+ at ifhtml
+ at html
+In particular, the Greek letters are recognizable special symbols: α – \alpha, β – \beta, γ – \gamma, δ – \delta, ε – \epsilon, η – \eta, ι – \iota, χ – \chi, κ – \kappa, λ – \lambda, μ – \mu, ν – \nu, o – \o, ω – \omega, ϕ – \phi, π – \pi, ψ – \psi, ρ – \rho, σ – \sigma, θ &ndash [...]
+
+<p>The small part of most common special TeX symbols are: ∠ – \angle, ⋅ – \cdot, ♣ – \clubsuit, ✓ – \checkmark, ∪ – \cup, ∩ – \cap, ♢ – \diamondsuit, ◇ – \diamond, ÷
+ – \div,
+↓ – \downarrow, † – \dag, ‡ – \ddag, ≡ – \equiv, ∃ – \exists, ⌢ – \frown, ♭ – \flat, ≥ – \ge, ≥ – \geq, ≧ – \geqq, ← – \gets, ♡ – \heartsuit, ∞ – \infty, ∫ – \int, \Int, ℑ  – \Im, ♢ – \lozenge, ⟨ – \langle, ≤ – \le, ≤ – \leq, ≦ – \leqq, ← – \leftarrow, & [...]
+ at end html
+ at end ifhtml
+ at ifnothtml
+In particular, the Greek letters are recognizable special symbols: @math{\alpha} -- \alpha, @math{\beta} -- \beta, @math{\gamma} -- \gamma, @math{\delta} -- \delta, @math{\epsilon} -- \epsilon, @math{\eta} -- \eta, @math{\iota} -- \iota, @math{\chi} -- \chi, @math{\kappa} -- \kappa, @math{\lambda} -- \lambda, @math{\mu} -- \mu, @math{\nu} -- \nu, @math{o} -- \o, @math{\omega} -- \omega, @math{\phi} -- \phi, @math{\pi} -- \pi, @math{\psi} -- \psi, @math{\rho} -- \rho, @math{\sigma} -- \si [...]
+
+The small part of most common special TeX symbols are: @math{\angle} -- \angle, @math{\aleph} -- \aleph, @math{\cdot} -- \cdot, @math{\clubsuit} -- \clubsuit, @math{\cup} -- \cup, @math{\cap} -- \cap, @math{\diamondsuit} -- \diamondsuit, @math{\diamond} -- \diamond, @math{\div} -- \div, @math{\downarrow} -- \downarrow, @math{\dag} -- \dag, @math{\ddag} -- \ddag, @math{\equiv} -- \equiv, @math{\exists} -- \exists, @math{\frown} -- \frown, @math{\flat} -- \flat, @math{\ge} -- \ge, @math{\g [...]
+ at end ifnothtml
+
+The font size can be defined explicitly (if @var{size}>0) or relatively to a base font size as |@var{size}|*@var{FontSize} (if @var{size}<0). The value @var{size}=0 specifies that the string will not be printed. The base font size is measured in internal ``MathGL'' units. Special functions @code{SetFontSizePT(), SetFontSizeCM(), SetFontSizeIN()} (see @ref{Font settings}) allow one to set it in more ``common'' variables for a given dpi value of the picture.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Textual formulas, Command options, Font styles, General concepts
+ at section Textual formulas
+ at nav{}
+
+ at cindex Textual formulas
+
+MathGL have the fast variant of textual formula evaluation
+ at ifclear UDAV
+(@pxref{Evaluate expression})
+ at end ifclear
+. There are a lot of functions and operators available. The operators are: @samp{+} -- addition, @samp{-} -- subtraction, @samp{*} -- multiplication, @samp{/} -- division, @samp{^} -- integer power. Also there are logical ``operators'': @samp{<} -- true if x<y, @samp{>} -- true if x>y, @samp{=} -- true if x=y, @samp{&} -- true if x and y both nonzero, @samp{|} -- true if x or y nonzero. These logical operators have lowest priority and return 1 if true or 0 if false.
+
+The basic functions are: @samp{sqrt(x)} -- square root of @var{x}, @samp{pow(x,y)} -- power @var{x} in @var{y}, @samp{ln(x)} -- natural logarithm of @var{x}, @samp{lg(x)} -- decimal logarithm of @var{x}, @samp{log(a,x)} -- logarithm base @var{a} of @var{x}, @samp{abs(x)} -- absolute value of @var{x}, @samp{sign(x)} -- sign of @var{x}, @samp{mod(x,y)} -- @var{x} modulo @var{y}, @samp{step(x)} -- step function, @samp{int(x)} -- integer part of @var{x}, @samp{rnd} -- random number, @samp{ra [...]
+ at ifhtml
+ at html
+π = 3.1415926…, inf=∞
+ at end html
+ at end ifhtml
+ at ifnothtml
+ at math{\pi=3.1415926..., inf=\infty}
+ at end ifnothtml
+
+Functions for complex numbers @samp{real(x)}, @samp{imag(x)}, @samp{abs(x)}, @samp{arg(x)}, @samp{conj(x)}.
+
+Trigonometric functions are: @samp{sin(x)}, @samp{cos(x)}, @samp{tan(x)} (or @samp{tg(x)}). Inverse trigonometric functions are: @samp{asin(x)}, @samp{acos(x)}, @samp{atan(x)}. Hyperbolic functions are: @samp{sinh(x)} (or @samp{sh(x)}), @samp{cosh(x)} (or @samp{ch(x)}), @samp{tanh(x)} (or @samp{th(x)}). Inverse hyperbolic functions are: @samp{asinh(x)}, @samp{acosh(x)}, @samp{atanh(x)}.
+
+ at ifhtml
+ at html
+<p>There are a set of special functions: ‘<samp>gamma(x)</samp>’ – Gamma function Γ(x) = ∫<sub>0</sub><sup>∞</sup> t<sup>x-1</sup> exp(-t) dt, ‘<samp>gamma_inc(x,y)</samp>’ – incomplete Gamma function Γ(x,y) = ∫<sub>y</sub><sup>∞</sup> t<sup>x-1</sup> exp(-t) dt, ‘<samp>psi(x)</samp>’ – digamma function ψ(x) = Γ′(x)/Γ(x) for x≠0, ‘<samp>ai(x)</samp>’ – Airy fun [...]
+
+<p>The exponent integrals are: ‘<samp>ci(x)</samp>’ – Cosine integral Ci(x) = ∫<sub>0</sub><sup>x</sup>dt cos(t)/t, ‘<samp>si(x)</samp>’ – Sine integral Si(x) = ∫<sub>0</sub><sup>x</sup>dt sin(t)/t, ‘<samp>erf(x)</samp>’ – error function erf(x) = (2/√π) ∫<sub>0</sub><sup>x</sup>dt exp(-t<sup>2</sup>) , ‘<samp>ei(x)</samp>’ – exponential integral Ei(x) = -PV(∫<sub>-x</sub><sup>∞</sup>dt  [...]
+
+<p>Bessel functions are: ‘<samp>j(nu,x)</samp>’ – regular cylindrical Bessel function of fractional order <em>nu</em>, ‘<samp>y(nu,x)</samp>’ – irregular cylindrical Bessel function of fractional order <em>nu</em>, ‘<samp>i(nu,x)</samp>’ – regular modified Bessel function of fractional order <em>nu</em>, ‘<samp>k(nu,x)</samp>’ – irregular modified Bessel function of fractional order <em>nu</em>. </p>
+
+<p>Elliptic integrals are: ‘<samp>ee(k)</samp>’ – complete elliptic integral is denoted by E(k) = E(π/2,k), ‘<samp>ek(k)</samp>’ – complete elliptic integral is denoted by K(k) = F(π/2,k), ‘<samp>e(phi,k)</samp>’ – elliptic integral E(φ,k) = ∫<sub>0</sub><sup>φ</sup>dt √(1 - k<sup>2</sup>sin<sup>2</sup>(t)), ‘<samp>f(phi,k)</samp>’ – elliptic integral F(φ,k) = ∫<sub>0</sub><sup>φ</ [...]
+ at end html
+ at end ifhtml
+ at ifnothtml
+There are a set of special functions: @samp{gamma(x)} -- Gamma function @math{\Gamma(x) = \int_0^\infty dt t^@{x-1@} exp(-t)}, @samp{gamma_inc(x,y)} -- incomplete Gamma function @math{\Gamma(x,y) = \int_y^\infty dt t^@{x-1@} exp(-t)}, @samp{psi(x)} -- digamma function @math{\psi(x) = \Gamma'(x)/\Gamma(x)} for x!=0, @samp{ai(x)} -- Airy function Ai(x), @samp{bi(x)} -- Airy function Bi(x), @samp{cl(x)} -- Clausen function, @samp{li2(x)} (or @samp{dilog(x)}) -- dilogarithm @math{Li_2(x) = - [...]
+
+The exponent integrals are: @samp{ci(x)} -- Cosine integral @math{Ci(x) = \int_0^x dt \cos(t)/t}, @samp{si(x)} -- Sine integral @math{Si(x) = \int_0^x dt \sin(t)/t}, @samp{erf(x)} -- error function @math{erf(x) = (2/\sqrt(\pi)) \int_0^x dt \exp(-t^2)}, @samp{ei(x)} -- exponential integral @math{Ei(x) := - PV(\int_@{-x@}^\infty dt \exp(-t)/t)} (where PV denotes the principal value of the integral), @samp{e1(x)} -- exponential integral @math{E_1(x) := Re \int_1^\infty dt \exp(-xt)/t} , @sa [...]
+
+Bessel functions are: @samp{j(nu,x)} -- regular cylindrical Bessel function of fractional order @var{nu}, @samp{y(nu,x)} -- irregular cylindrical Bessel function of fractional order @var{nu}, @samp{i(nu,x)} -- regular modified Bessel function of fractional order @var{nu}, @samp{k(nu,x)} -- irregular modified Bessel function of fractional order @var{nu}.
+
+Elliptic integrals are: @samp{ee(k)} -- complete elliptic integral is denoted by @math{E(k) = E(\pi/2, k)}, @samp{ek(k)} -- complete elliptic integral is denoted by @math{K(k) = F(\pi/2, k)}, @samp{e(phi,k)} -- elliptic integral @math{E(\phi,k) = \int_0^\phi dt \sqrt((1 - k^2 \sin^2(t)))}, @samp{f(phi,k)} -- elliptic integral @math{F(\phi,k) = \int_0^\phi dt 1/\sqrt((1 - k^2 \sin^2(t)))}.
+ at end ifnothtml
+
+Jacobi elliptic functions are: @samp{sn(u,m)}, @samp{cn(u,m)}, @samp{dn(u,m)}, @samp{sc(u,m)}, @samp{sd(u,m)}, @samp{ns(u,m)}, @samp{cs(u,m)}, @samp{cd(u,m)}, @samp{nc(u,m)}, @samp{ds(u,m)}, @samp{dc(u,m)}, @samp{nd(u,m)}.
+
+Note, some of these functions are unavailable if MathGL was compiled without GSL support.
+
+There is no difference between lower or upper case in formulas. If argument value lie outside the range of function definition then function returns NaN.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node  Command options, Interfaces, Textual formulas, General concepts
+ at section Command options
+ at nav{}
+
+Command options allow the easy setup of the selected plot by changing global settings only for this plot. Each option start from symbol @samp{;}. Options work so that MathGL remember the current settings, change settings as it being set in the option, execute function and return the original settings back. So, the options are most usable for plotting functions.
+
+The most useful options are @code{xrange, yrange, zrange}. They sets the boundaries for data change. This boundaries are used for automatically filled variables. So, these options allow one to change the position of some plots. For example, in command @code{Plot(y,"","xrange 0.1 0.9");} or @code{plot y; xrange 0.1 0.9} the x coordinate will be equidistantly distributed in range 0.1 ... 0.9.  @sref{Using options}
+
+The full list of options are:
+ at cindex alpha
+ at cindex alphadef
+ at deffn {MGL option} alpha @code{val}
+Sets alpha value (transparency) of the plot. The value should be in range [0, 1]. See also @ref{alphadef}.
+ at end deffn
+ at c @cindex ambient
+ at c @deffn {MGL option} ambient @code{val}
+ at c Sets brightness of ambient light for the plot. The value should be in range [0, 1]. See also @ref{ambient}.
+ at c @end deffn
+ at c @cindex diffuse
+ at c @deffn {MGL option} diffuse @code{val}
+ at c Sets brightness of diffuse light for the plot. The value should be in range [0, 1]. See also @ref{diffuse}.
+ at c @end deffn
+
+ at cindex xrange
+ at deffn {MGL option} xrange @code{val1 val2}
+Sets boundaries of x coordinate change for the plot. See also @ref{xrange}.
+ at end deffn
+ at cindex yrange
+ at deffn {MGL option} yrange @code{val1 val2}
+Sets boundaries of y coordinate change for the plot. See also @ref{yrange}.
+ at end deffn
+ at cindex zrange
+ at deffn {MGL option} zrange @code{val1 val2}
+Sets boundaries of z coordinate change for the plot. See also @ref{zrange}.
+ at end deffn
+
+ at cindex cut
+ at deffn {MGL option} cut @code{val}
+Sets whether to cut or to project the plot points lying outside the bounding box. See also @ref{cut}.
+ at end deffn
+ at cindex fontsize
+ at deffn {MGL option} size @code{val}
+Sets the size of text, marks and arrows. See also @ref{font}, @ref{marksize}, @ref{arrowsize}.
+ at end deffn
+ at cindex meshnum
+ at deffn {MGL option} meshnum @code{val}
+Work like @ref{meshnum} command.
+ at end deffn
+
+ at cindex legend
+ at deffn {MGL option} legend 'txt'
+Adds string 'txt' to internal legend accumulator. The style of described line and mark is taken from arguments of the last @ref{1D plotting} command. See also @ref{legend}.
+ at end deffn
+ at cindex value
+ at deffn {MGL option} value @code{val}
+Set the value to be used as additional numeric parameter in plotting command.
+ at end deffn
+
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Interfaces, , Command options, General concepts
+ at section Interfaces
+ at nav{}
+
+ at ifset UDAV
+You can use @code{mglParse} class for executing MGL scripts from different languages.
+ at end ifset
+
+ at ifclear UDAV
+
+The MathGL library has interfaces for a set of languages. Most of them are based on the C interface via SWIG tool. There are Python, Java, Octave, Lisp, C#, Guile, Lua, Modula 3, Ocaml, Perl, PHP, Pike, R, Ruby, and Tcl interfaces. Also there is a Fortran interface which has a similar set of functions, but slightly different types of arguments (integers instead of pointers). These functions are marked as [C function].
+
+Some of the languages listed above support classes (like C++ or Python). The name of functions for them is the same as in C++ (see @ref{MathGL core} and @ref{Data processing}) and marked like [Method on mglGraph].
+
+Finally, a special command language MGL (see @ref{MGL scripts}) was written for a faster access to plotting functions. Corresponding scripts can be executed separately (by UDAV, mglconv, mglview and so on) or from the C/C++/Python/... code (@pxref{mglParse class}).
+
+ at menu
+* C interface::
+* C++ interface::
+ at end menu
+
+ at external{}
+ at node C interface, C++ interface, , Interfaces
+ at subsection C/Fortran interface
+ at nav{}
+
+The C interface is a base for many other interfaces. It contains the pure C functions for most of the methods of MathGL classes. In distinction to C++ classes, C functions must have an argument HMGL (for graphics) and/or HMDT (for data arrays), which specifies the object for drawing or manipulating (changing). So, firstly, the user has to create this object by the function @code{mgl_create_*()} and has to delete it after the use by function @code{mgl_delete_*()}.
+
+All C functions are described in the header file @code{#include <mgl2/mgl_cf.h>} and use variables of the following types:
+ at itemize
+ at item
+ at code{HMGL} --- Pointer to class @code{mglGraph} (@pxref{MathGL core}).
+ at item
+ at code{HCDT} --- Pointer to class @code{const mglDataA} (@pxref{Data processing}) --- constant data array.
+ at item
+ at code{HMDT} --- Pointer to class @code{mglData} (@pxref{Data processing}) --- data array of real numbers.
+ at item
+ at code{HADT} --- Pointer to class @code{mglDataC} (@pxref{Data processing}) --- data array of complex numbers.
+ at item
+ at code{HMPR} --- Pointer to class @code{mglParse} (@pxref{mglParse class}) --- MGL script parsing.
+ at item
+ at code{HMEX} --- Pointer to class @code{mglExpr} (@pxref{Evaluate expression}) --- textual formulas for real numbers.
+ at item
+ at code{HMAX} --- Pointer to class @code{mglExprC} (@pxref{Evaluate expression}) --- textual formulas for complex numbers.
+ at end itemize
+These variables contain identifiers for graphics drawing objects and for the data objects.
+
+Fortran functions/subroutines have the same names as C functions. However, there is a difference. Variable of type @code{HMGL, HMDT} must be an integer with sufficient size (@code{integer*4} in the 32-bit operating system or @code{integer*8} in the 64-bit operating system). All C functions of type @code{void} are subroutines in Fortran, which are called by operator @code{call}. The exceptions are functions, which return variables of types @code{HMGL} or @code{HMDT}. These functions shoul [...]
+
+ at external{}
+ at node C++ interface, , C interface, Interfaces
+ at subsection C++/Python interface
+ at nav{}
+
+MathGL provides the interface to a set of languages via SWIG library. Some of these languages support classes. The typical example is Python -- which is named in this chapter's title. Exactly the same classes are used for high-level C++ API. Its feature is using only inline member-functions what make high-level API to be independent on compiler even for binary build.
+
+There are 3 main classes in:
+ at itemize
+ at item @code{mglGraph}
+-- provide most plotting functions (see @ref{MathGL core}).
+ at item @code{mglData}
+-- provide base data processing (see @ref{Data processing}). It have an additional feature to access data values. You can use a construct like this: @code{dat[i]=sth;} or @code{sth=dat[i]} where flat representation of data is used (i.e., @var{i} can be in range 0...nx*nx*nz-1). You can also import NumPy arrays as input arguments in Python: @code{mgl_dat = mglData(numpy_dat);}.
+ at item @code{mglParse}
+-- provide functions for parsing MGL scripts (see @ref{MGL scripts}).
+ at end itemize
+
+
+To use Python classes just execute @samp{import mathgl}. The simplest example will be:
+ at verbatim
+import mathgl
+a=mathgl.mglGraph()
+a.Box()
+a.WritePNG("test.png")
+ at end verbatim
+Alternatively you can import all classes from @code{mathgl} module and easily access MathGL classes like this:
+ at verbatim
+from mathgl import *
+a=mglGraph()
+a.Box()
+a.WritePNG("test.png")
+ at end verbatim
+This becomes useful if you create many @code{mglData} objects, for example.
+
+ at end ifclear
+
+ at external{}
diff --git a/texinfo/concept_ru.texi b/texinfo/concept_ru.texi
new file mode 100644
index 0000000..ca60790
--- /dev/null
+++ b/texinfo/concept_ru.texi
@@ -0,0 +1,393 @@
+ at chapter Основные принципы
+ at nav{}
+
+Возможности библиотеки MathGL довольно богаты -- число только основных типов графиков превышает 50 видов. Кроме того, есть функции для обработки данных, настройки вида графика и пр. и пр. Тем не менее, я старался придерживаться единого стиля в порядке аргументов функций и способе их ``настройки''. В основном все ниже сказанное относится к функциям рисования различных графиков.
+
+Всего основных концепций (базисных идей) шесть:
+ at enumerate
+ at item
+ at strong{Все рисунки создаются в памяти.} Это могут быть как растровые картинки (для @code{SetQuality(MGL_DRAW_LMEM)} или @code{@ref{quality} 6}), так и векторные списки примитивов (по умолчанию). Дальнейшая судьба рисунков определяется пользователем: можно сохранить в файл, вывести на экран, создать анимацию/кино, дополнительно отредактировать и т.д. Такой подход обеспечивает высокую переносимость библиотеки -- один и тот же программный код создаст в точности одинаковый рисунок на @emph{ [...]
+ at item
+ at strong{Все настройки графиков (стиль линий, цветовые схемы поверхностей, стиль и цвет текста) задаются строками.} Это обеспечивает: удобство для пользователя -- короткую строку легче читать и здесь тяжелее ошибиться, чем в большом списке параметров; переносимость -- строки выглядят одинаково на всех платформах и не надо заботиться о типе и числе аргументов.
+ at item
+ at strong{Все функции имеют ``упрощенный'' и ``продвинутый'' варианты.} Сделано опять из-за удобства. В ``упрощенном'' варианте для построения графика нужны только один-два массив(а) данных, которые автоматически равнораспределяются в заданном диапазоне осей координат. В ``продвинутой'' версии можно не только указать явно диапазон построения графика, но и задать его параметрически. Последнее позволяет легко строить довольно сложные кривые и поверхности. В обоих вариантах функций порядок ар [...]
+ at item
+ at strong{Все данные передаются через экземпляры класса mglData(A).} Такой подход позволяет избежать ошибок при работе с памятью и единообразно передавать данные разных типов (float, double, данные из файла, заполненных пользователем и пр.) в функции рисования.
+ at item
+ at strong{Все элементы рисунков векторные.} Изначально библиотека MathGL была ориентированна на работу с научными данными, которые по своей природе векторные (линии, грани, матрицы и т.д.). Поэтому векторность используется во всех рисунках! Причем иногда даже в ущерб производительности (например, при выводе шрифтов). Помимо всего прочего, векторность позволяет легко масштабировать рисунок -- измените размер картинки в 2 раза, и рисунок пропорционально растянется.
+ at item
+ at strong{Новые графики не удаляют уже нарисованное.} Этот, в чем-то неожиданный, подход позволяет создавать огромное количество ``комбинированных'' графиков. Например, поверхность с наложенными линиями уровня строится двумя последовательными вызовами функций рисования поверхности и линий уровня (в любом порядке). И совершенно не надо писать специальную функцию (как в Matlab и некоторых других программах) для рисования этого графика.
+ at end enumerate
+
+Кроме основных концепций я хотел бы остановиться на нескольких, как оказалось, нетривиальных моментах -- способе указания положения графика, осей координат и строковых параметров линий, поверхностей, текста.
+
+ at menu
+* Coordinate axes::
+* Color styles::
+* Line styles::
+* Color scheme::
+* Font styles::
+* Textual formulas::
+* Command options::
+* Interfaces::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Coordinate axes, Color styles, , General concepts
+ at section Оси координат
+ at nav{}
+
+Представление системы координат в MathGL состоит из двух частей. Вначале координаты нормируются в диапазон изменения осей координат (@pxref{Axis settings}). Если флаг @code{SetCut()} установлен, то точки вне интервала отбрасываются, в противном случае, они проецируются на ограничивающий параллелепипед (см. @ref{Cutting}). Кроме того, отбрасываются точки внутри границ, определенных переменными @var{CutMin}x at var{CutMax} и точки, для которых значение функции @code{CutOff}() не равно нулю. П [...]
+
+Диапазон изменения @emph{x, y, z}-координат задается функциями @code{SetRange()} или @ref{ranges}. Точка пересечения осей координат задается функцией @code{SetOrigin()}. При этом можно использовать NAN значения для автоматического выбора положения оси.
+
+Кроме привычных осей @emph{x, y, z} есть еще одна ось -- цветовая шкала -- ось @emph{c}. Она используется при окрашивании поверхностей и задает границы изменения функции при окрашивании. Ее границы автоматически устанавливаются равными диапазону z-оси при вызове @ref{ranges}. Возможно и ручное изменение границ цветового интервала посредством вызова @code{SetRange('c', ...)}. Используйте @ref{colorbar} для отображения цветовой шкалы.
+
+Вид меток по осям определяется функцией @code{SetTicks()} (@pxref{Ticks}). Функция @var{SetTuneTicks} включает/выключает выделение общего множителя (большого или малого факторов в диапазоне) для меток осей координат. Наконец, если стандартный вид меток не устраивает пользователя, то их шаблон можно задать явно (можно использовать и ТеХ символы), воспользовавшись функцией  @code{SetTickTempl()}. Кроме того, в качестве меток можно вывести произвольный текст использовав функцию @code{SetTic [...]
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Color styles, Line styles, Coordinate axes, General concepts
+ at section Цвета
+ at nav{}
+
+Base colors are defined by one of symbol @samp{wkrgbcymhRGBCYMHWlenupqLENUPQ}.
+ at ifhtml
+ at html
+<p>Символы цвета: ‘<samp>k</samp>’ – черный, ‘<samp>r</samp>’ – <span style="color: rgb(255, 0, 0);">красный</span>, ‘<samp>R</samp>’ – <span style="color: rgb(127, 0, 0);">темно красный</span>, ‘<samp>g</samp>’ – <span style="color: rgb(0, 255, 0);">зеленый</span>, ‘<samp>G</samp>’ – <span style="color: rgb(0, 127, 0);">темно зеленый</span>, ‘<samp>b</samp>’ – <span style="color:  [...]
+ at end html
+ at end ifhtml
+ at ifnothtml
+Символы цвета: @samp{k} -- черный, @samp{r} -- красный, @samp{R} -- темно красный, @samp{g} -- зеленый, @samp{G} -- темно зеленый, @samp{b} -- синий, @samp{B} -- темно синий, @samp{c} -- голубой, @samp{C} -- темно голубой, @samp{m} -- пурпурный, @samp{M} -- темно пурпурный, @samp{y} -- желтый, @samp{Y} -- темно желтый (золотой), @samp{h} -- серый, @samp{H} -- темно серый, @samp{w} -- белый, @samp{W} -- светло серый, @samp{l} -- сине-зеленый, @samp{L} -- темно сине-зеленый, @samp{e} -- же [...]
+ at end ifnothtml
+
+В цветовой схеме можно использовать тональные (``подсвеченные'') цвета. Тональный цвет задается двумя символами в фигурных скобках @samp{@{cN@}}: первый -- обычный цвет, второй -- его яркость цифрой. Цифра может быть в диапазоне @samp{1}... at samp{9}. При этом @samp{5} соответствует нормальному цвету, @samp{1} -- очень темная версия цвета (почти черный), @samp{9} -- очень светлая версия цвета (почти белый). Например, цвета могут быть @samp{@{b2@}} @samp{@{b7@}} @samp{@{r7@}} и т.д.
+
+Наконец, можно указать явно RGB или RGBA значения цвета, используя формат @samp{@{xRRGGBB@}} или @samp{@{xRRGGBBAA@}} соответственно. Например, @samp{@{xFF9966@}} даст цвет
+ at ifhtml
+ at html
+<span style="color: rgb(255, 153, 102);">дыни</span>.
+ at end html
+ at end ifhtml
+ at ifnothtml
+дыни.
+ at end ifnothtml
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Line styles, Color scheme, Color styles, General concepts
+ at section Стиль линий
+ at nav{}
+
+ at cindex Стиль линий
+ at cindex Стиль маркеров
+ at cindex Стиль стрелок
+
+Стиль линии задается строкой, которая может содержать символ цвета (@samp{wkrgbcymhRGBCYMHWlenupqLENUPQ}), тип пунктира (@samp{-|;:ji} или пробел), ширину линии (@samp{0123456789}) и тип маркера (@samp{o+xsd.^v} и модификатор @samp{#}). Если пропущен цвет или тип пунктира, то используется значение по умолчанию с последним указанным цветом или значение из палитры (для @pxref{1D plotting}).
+ at ifhtml
+ at html
+По умолчанию палитры содержит следующие цвета: <span style="color: rgb(76, 76, 76);">темно серый</span> ‘<samp>H</samp>’, <span style="color: rgb(0, 0, 255);">синий</span> ‘<samp>b</samp>’, <span style="color: rgb(0, 255, 0);">зеленый</span> ‘<samp>g</samp>’, <span style="color: rgb(255, 0, 0);">красный</span> ‘<samp>r</samp>’, <span style="color: rgb(0, 255, 255);">голубой</span> ‘<samp>c</samp>’, <span style="color: rgb(255, 0 [...]
+
+<p>Тип пунктира: пробел – нет линии (для рисования только маркеров), ‘<samp>-</samp>’ – сплошная линия (■■■■■■■■■■■■■■■■), ‘<samp>|</samp>’ – длинный пунктир (■■■■■■■■□□□□□□□□), ‘<samp>;</samp>’ – пунктир (■■■■&#9633 [...]
+ at end html
+ at end ifhtml
+ at ifnothtml
+По умолчанию палитра содержит следующие цвета: темно серый @samp{H}, синий @samp{b}, зеленый @samp{g}, красный @samp{r}, голубой @samp{c}, пурпурный @samp{m}, yellow @samp{y}, серый @samp{h}, сине-зеленый @samp{l}, небесно-синий @samp{n}, оранжевый @samp{q}, желто-зеленый @samp{e}, сине-фиолетовый @samp{u}, фиолетовый @samp{p}.
+
+Тип пунктира: пробел -- нет линии (для рисования только маркеров), @samp{-} -- сплошная линия (################), @samp{|} -- длинный пунктир (########________), @samp{;} -- пунктир (####____####____), @samp{=} -- короткий пунктир (##__##__##__##__), @samp{:} -- точки (#___#___#___#___), @samp{j} -- пунктир с точками  (#######____#____), @samp{i} -- мелкий пунктир с точками (###__#__###__#__), @samp{@{dNNNN@}} -- заданный вручную стиль (для v.2.3 и поздних, например @samp{@{df090@}} для  [...]
+ at end ifnothtml
+
+Типы маркеров: @samp{o} -- окружность, @samp{+} -- крест, @samp{x} -- косой крест, @samp{s} -- квадрат, @samp{d} - ромб, @samp{.} -- точка, @samp{^} -- треугольник вверх, @samp{v} -- треугольник вниз, @samp{<} -- треугольник влево, @samp{>} -- треугольник вправо, @samp{#*} -- знак Y, @samp{#+} -- крест в квадрате, @samp{#x} -- косой крест в квадрате, @samp{#.} -- точка в окружности. Если в строке присутствует символ @samp{#}, то используются символы с заполнением.
+
+Вы можете определить собственные символы (см. @ref{addsymbol}) для рисования маркеров при использовании стиля @samp{&}. В частности, @samp{&*}, @samp{&o}, @samp{&+}, @samp{&x}, @samp{&s}, @samp{&d}, @samp{&.}, @samp{&^}, @samp{&v}, @samp{&<}, @samp{&>} нарисует определенный пользователем символ с именем @samp{*o+xsd.^v<>} соответственно; и
+ at samp{&#o}, @samp{&#+}, @samp{&#x}, @samp{&#s}, @samp{&#d}, @samp{&#.}, @samp{&#^}, @samp{&#v}, @samp{&#<}, @samp{&#>} нарисует определенный пользователем символ с именем @samp{YOPXSDCTVLR} соответственно. Замечу, что будет нарисован только контур определенного пользователем символа если задан отрицательный размер маркера (см. @ref{marksize} или опцию @code{size} в @ref{Command options}).
+
+На конце и в начале линии можно выводить специальный символ (стрелку), если в строке указать один из символов: @samp{A} -- стрелка наружу, @samp{V} -- стрелка внутрь, @samp{I} -- поперечная черта, @samp{K} -- стрелка с чертой, @samp{T} -- треугольник, @samp{S} -- квадрат, @samp{D} -- ромб, @samp{O} -- круг, @samp{X} -- косой крест, @samp{_} -- нет стрелки (по умолчанию). При этом действует следующее правило: первый символ определяет стрелку на конце линии, второй символ -- стрелку в нача [...]
+
+ at pfig{style, Color and line styles.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Color scheme, Font styles, Line styles, General concepts
+ at section Цветовая схема
+ at nav{}
+
+ at cindex Цветовая схема
+
+Цветовая схема используется для определения цвета поверхностей, линий уровня и пр. Цветовая схема задается строкой @emph{s}, которая содержит символы цвета (@pxref{Line styles}) или символы @samp{#:|}. Символ @samp{#} переключает рисование поверхности на сетчатое (для трехмерных поверхностей) или включает рисование сетки на поверхности. Символ @samp{|} отключает интерполяцию цвета в цветовой схеме. Это может быть полезно для ``резких'' цветов, например, при рисовании матриц. Если в строк [...]
+
+При определении цвета по @emph{амплитуде} (наиболее часто используется) окончательный цвет определяется путем линейной интерполяции массива цветов. Массив цветов формируется из цветов, указанных в строке спецификации. Аргумент -- амплитуда, нормированная на диапазон изменения цвета (см. @ref{Axis settings}). Например, строка из 4 символов @samp{bcyr} соответствует изменению цвета от синего (минимальное значение) через голубой и желтый (промежуточные значения) к красному (максимальное зна [...]
+
+Специальная двуосная цветовая схема (как в графике @ref{map}) задается символом @samp{%}. В ней второе направление (прозрачность) используется как вторая координата для цвета. При этом можно указать до 4 цветов для углов: @{c1,a1@}, @{c2,a1@}, @{c1,a2@}, @{c2,a2@}. Здесь диапазоны цвета и прозрачности равны @{c1,c2@} и @{a1,a2@}. Если указано меньше 4 цветов, то черный используется для угла @{c1,a1@}. Если задано только 2 цвета, то их сумма используется для угла @{c2,a2@}.
+
+Есть несколько полезных цветовых схем. Строка @samp{kw} дает обычную серую (черно-белую) схему, когда большие значения светлее. Строка @samp{wk} представляет обратную серую схему, когда большие значения темнее. Строки @samp{kRryw}, @samp{kGgw}, @samp{kBbcw} представляют собой хорошо известные схемы @emph{hot}, @emph{summer} и @emph{winter}. Строки @samp{BbwrR} и @samp{bBkRr} позволяют рисовать двухцветные фигуры на белом или черном фоне, когда отрицательные значения показаны синим цветом [...]
+
+Для более точно раскрашивания поверхностей можно изменить равномерное (по умолчанию) положение цветов в цветовой схеме. Формат следующий: @samp{@{CN,pos@}}, @samp{@{CN,pos@}} или @samp{@{xRRGGBB,pos@}}. Здесь значение @var{pos} положения цвета должно быть в диапазоне [0, 1]. Отмечу, что альтернативным механизмом тонкой настройки цветовой схемы может служить использование формул для цветовой координаты (см. @ref{Curved coordinates}).
+
+ at pfig{schemes, Most popular color schemes.}
+
+При определении цвета по @emph{положению точки в пространстве} (используется в @ref{map}) окончательный цвет определяется по формуле c=x*c[1] + y*c[2]. Здесь c[1], c[2] -- первые три цвета в цветовом массиве; x, y -- координаты точки, нормированные в диапазон изменения осей координат.
+ at c Такой тип определения цвета полезен, например, при построении поверхностей уровня, когда цвет дает представление о положении точки в пространстве.
+
+
+Дополнительно, MathGL может наложить маску при закраске граней для создания растрового изображения. Тип маски задается одним из символов @samp{-+=;oOsS~<>jdD*^} в цветовой схеме. Маску можно повернуть на произвольный угол командой @ref{mask} или на один из улов +45, -45 или 90 градусов, используя символы @samp{\/I} соответственно. Примеры масок по умолчанию показаны на рисунке ниже.
+
+ at pfig{mask, Example of masks for face coloring.}
+
+Однако, вы можете задать собственную маску (как матрицу 8*8) для любого из этих символов, используя второй аргумент команды @ref{mask}. Например, маска на правом нижнем подрисунке получается кодом@*
+ at ifclear UDAV
+ at code{gr->SetMask('+', "ff00182424f80000");	gr->Dens(a,"3+");}@*
+или использовать явное задание маски (для v.2.3 и более поздних)@*
+ at code{gr->Dens(a,"3@{s00ff00182424f800@}");}
+ at end ifclear
+ at ifset UDAV
+ at code{mask '+' 'ff00182424f80000':dens a '3+'}@*
+или использовать явное задание маски (для v.2.3 и более поздних)@*
+ at code{dens a '3@{s00ff00182424f800@}'}
+ at end ifset
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Font styles, Textual formulas, Color scheme, General concepts
+ at section Стиль текста
+ at nav{}
+
+ at cindex Стиль текста
+
+Стиль текста задается строкой, которая может содержать цвет текста @samp{wkrgbcymhRGBCYMHW} (см. @ref{Color styles}), а также тип шрифта (@samp{ribwou}) и/или выравнивания (@samp{LRC}) после символа @samp{:}. Например, @samp{r:iCb} соответствует жирному (@samp{b}) курсиву (@samp{i}) с выравниванием по центру (@samp{C} красного цвета (@samp{r}). Начиная с MathGL версии 2.3, вы можете использовать не только один цвет для всего текста, но и задать цветовой градиент для выводимой строки (см. [...]
+
+Начертания шрифта: @samp{r} -- прямой шрифт, @samp{i} -- курсив, @samp{b} -- жирный. По умолчанию используется прямой шрифт. Типы выравнивания текста: @samp{L} -- по левому краю (по умолчанию), @samp{C} -- по центру, @samp{R} -- по правому краю, @samp{T} -- под текстом, @samp{V} -- по центру вертикально. Дополнительные эффекты шрифта: @samp{w} -- контурный, @samp{o} -- надчеркнутый, @samp{u} -- подчеркнутый.
+
+Синтаксический разбор LaTeX-их команд по умолчанию включен. Это команды смены стиля текста (например, \b для жирного текста): \a или \overline -- надчеркивание, \b или \textbf -- жирный, \i или \textit -- курсив, \r или \textrm -- прямой (отменяет стили жирного и курсива), \u или \underline -- подчеркнутый, \w или \wire -- контурный, \big -- большего размера, @@ -- меньшего размера. Нижний и верхний индексы задаются символами @samp{_} и @samp{^}. При этом изменение стиля применяется толь [...]
+ at ifhtml
+ at html
+α.
+ at end html
+ at end ifhtml
+ at ifnothtml
+ at math{\alpha}.
+ at end ifnothtml
+
+Распознаются также большинство символов TeX и AMSTeX, команды смены стиля текста (\textrm, \textbf, \textit, \textsc, \overline, \underline), акценты (\hat, \tilde, \dot, \ddot, \acute, \check, \grave, \bar, \breve) и корни (\sqrt, \sqrt3, \sqrt4). Полный список содержит около 2000 символов. Отмечу, что первый пробел (пробел, табуляция и пр.) после команды игнорируется, а все остальные пробелы печатаются обычным образом. Например, следующие строки дают одинаковый результат @math{\tilde a [...]
+
+ at ifhtml
+ at html
+В частности, распознаются греческие буквы: α – \alpha, β – \beta, γ – \gamma, δ – \delta, ε – \epsilon, η – \eta, ι – \iota, χ – \chi, κ – \kappa, λ – \lambda, μ – \mu, ν – \nu, o – \o, ω – \omega, ϕ – \phi, π – \pi, ψ – \psi, ρ – \rho, σ – \sigma, θ – \theta, τ –  [...]
+
+<p>Еще примеры наиболее общеупотребительных TeX-их символов: ∠ – \angle, ⋅ – \cdot, ♣ – \clubsuit, ✓ – \checkmark, ∪ – \cup, ∩ – \cap, ♢ – \diamondsuit, ◇ – \diamond, ÷
+ – \div,
+↓ – \downarrow, † – \dag, ‡ – \ddag, ≡ – \equiv, ∃ – \exists, ⌢ – \frown, ♭ – \flat, ≥ – \ge, ≥ – \geq, ≧ – \geqq, ← – \gets, ♡ – \heartsuit, ∞ – \infty, ∫ – \int, \Int, ℑ  – \Im, ♢ – \lozenge, ⟨ – \langle, ≤ – \le, ≤ – \leq, ≦ – \leqq, ← – \leftarrow, & [...]
+ at end html
+ at end ifhtml
+ at ifnothtml
+В частности, распознаются греческие буквы: @math{\alpha} -- \alpha, @math{\beta} -- \beta, @math{\gamma} -- \gamma, @math{\delta} -- \delta, @math{\epsilon} -- \epsilon, @math{\eta} -- \eta, @math{\iota} -- \iota, @math{\chi} -- \chi, @math{\kappa} -- \kappa, @math{\lambda} -- \lambda, @math{\mu} -- \mu, @math{\nu} -- \nu, @math{o} -- \o, @math{\omega} -- \omega, @math{\phi} -- \phi, @math{\pi} -- \pi, @math{\psi} -- \psi, @math{\rho} -- \rho, @math{\sigma} -- \sigma, @math{\theta} -- \t [...]
+
+Еще примеры наиболее общеупотребительных TeX-их символов: @math{\angle} -- \angle, @math{\aleph} -- \aleph, @math{\cdot} -- \cdot, @math{\clubsuit} -- \clubsuit, @math{\cup} -- \cup, @math{\cap} -- \cap, @math{\diamondsuit} -- \diamondsuit, @math{\diamond} -- \diamond, @math{\div} -- \div, @math{\downarrow} -- \downarrow, @math{\dag} -- \dag, @math{\ddag} -- \ddag, @math{\equiv} -- \equiv, @math{\exists} -- \exists, @math{\frown} -- \frown, @math{\flat} -- \flat, @math{\ge} -- \ge, @math [...]
+ at end ifnothtml
+
+Размер текста может быть задан явно (если @var{size}>0) или относительно базового размера шрифта для рисунка |@var{size}|*@var{FontSize} при @var{size}<0. Значение @var{size}=0 указывает, что соответствующая строка выводиться не будет. Базовый размер шрифта измеряется во внутренних единицах. Специальные функции @code{SetFontSizePT(), SetFontSizeCM(), SetFontSizeIN()} позволяют задавать его в более ``привычных'' единицах.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Textual formulas, Command options, Font styles, General concepts
+ at section Текстовые формулы
+
+ at cindex Текстовые формулы
+
+MathGL имеет быстрый парсер текстовых формул
+ at ifclear UDAV
+(@pxref{Evaluate expression})
+ at end ifclear
+, понимающий большое число функций и операций. Базовые операции: @samp{+} -- сложение, @samp{-} -- вычитание, @samp{*} -- умножение, @samp{/} -- деление, @samp{^} -- возведение в целосичленную степень. Также есть логические операции: @samp{<} -- истина если if x<y, @samp{>} -- истина если x>y, @samp{=} -- истина если x=y, @samp{&} -- истина если x и y оба не равны нулю, @samp{|} -- истина если x или y не нуль. Логические операции имеют наинизший приоритет и возвращают 1 если истина или 0 [...]
+
+Базовые функции: @samp{sqrt(x)} -- квадратный корень из @var{x}, @samp{pow(x,y)} -- @var{x} в степени @var{y}, @samp{ln(x)} -- натуральный логарифм @var{x}, @samp{lg(x)} -- десятичный логарифм @var{x}, @samp{log(a,x)} -- логарифм по основанию @var{a} от @var{x}, @samp{abs(x)} -- модуль @var{x}, @samp{sign(x)} -- знак @var{x}, @samp{mod(x,y)} -- остаток от деления @var{x} на @var{y}, @samp{step(x)} -- ступенчатая функция, @samp{int(x)} -- целая часть @var{x}, @samp{rnd} -- случайное число [...]
+ at ifhtml
+ at html
+π = 3.1415926…, inf=∞
+ at end html
+ at end ifhtml
+ at ifnothtml
+ at math{\pi=3.1415926..., inf=\infty}
+ at end ifnothtml
+
+Функции для работы с комплексными числами @samp{real(x)}, @samp{imag(x)}, @samp{abs(x)}, @samp{arg(x)}, @samp{conj(x)}.
+
+Тригонометрические функции: @samp{sin(x)}, @samp{cos(x)}, @samp{tan(x)} (или @samp{tg(x)}). Обратные тригонометрические функции: @samp{asin(x)}, @samp{acos(x)}, @samp{atan(x)}. Гиперболические функции: @samp{sinh(x)} (или @samp{sh(x)}), @samp{cosh(x)} (или @samp{ch(x)}), @samp{tanh(x)} (или @samp{th(x)}). Обратные гиперболические функции: @samp{asinh(x)}, @samp{acosh(x)}, @samp{atanh(x)}.
+
+ at ifhtml
+ at html
+<p>Специальные функции: ‘<samp>gamma(x)</samp>’ – гамма функция Γ(x) = ∫<sub>0</sub><sup>∞</sup> t<sup>x-1</sup> exp(-t) dt, ‘<samp>gamma_inc(x,y)</samp>’ – неполная гамма функция Γ(x,y) = ∫<sub>y</sub><sup>∞</sup> t<sup>x-1</sup> exp(-t) dt, ‘<samp>psi(x)</samp>’ – дигамма функция ψ(x) = Γ′(x)/Γ(x) для x≠0, ‘<samp>ai(x)</samp>’ – Эйри функция Ai(x), ‘<sa [...]
+
+<p>Экспоненциальные интегралы: ‘<samp>ci(x)</samp>’ – cos-интеграл Ci(x) = ∫<sub>0</sub><sup>x</sup>dt cos(t)/t, ‘<samp>si(x)</samp>’ – sin-интеграл Si(x) = ∫<sub>0</sub><sup>x</sup>dt sin(t)/t, ‘<samp>erf(x)</samp>’ – функция ошибки erf(x) = (2/√π) ∫<sub>0</sub><sup>x</sup>dt exp(-t<sup>2</sup>) , ‘<samp>ei(x)</samp>’ – интеграл Ei(x) = -PV(∫<sub>-x</sub><sup>∞</sup>dt exp(-t)/t) (где  [...]
+
+<p>Функции Бесселя: ‘<samp>j(nu,x)</samp>’ – функция Бесселя первого рода, ‘<samp>y(nu,x)</samp>’ – функция Бесселя второго рода, ‘<samp>i(nu,x)</samp>’ – модифицированная функция Бесселя первого рода, ‘<samp>k(nu,x)</samp>’ – модифицированная функция Бесселя второго рода. </p>
+
+<p>Эллиптические интегралы: ‘<samp>ee(k)</samp>’ – полный эллиптический интеграл E(k) = E(π/2,k), ‘<samp>ek(k)</samp>’ – полный эллиптический интеграл K(k) = F(π/2,k), ‘<samp>e(phi,k)</samp>’ – эллиптический интеграл E(φ,k) = ∫<sub>0</sub><sup>φ</sup>dt √(1 - k<sup>2</sup>sin<sup>2</sup>(t)), ‘<samp>f(phi,k)</samp>’ – эллиптический интеграл F(φ,k) = ∫<sub>0</sub><sup>φ</sup>dt 1/&r [...]
+ at end html
+ at end ifhtml
+ at ifnothtml
+Специальные функции: @samp{gamma(x)} -- гамма функция @math{\Gamma(x) = \int_0^\infty dt t^@{x-1@} \exp(-t)}, @samp{gamma_inc(x,y)} -- неполная гамма функция @math{\Gamma(x,y) = \int_y^\infty dt t^@{x-1@} exp(-t)}, @samp{psi(x)} -- дигамма функция @math{\psi(x) = \Gamma'(x)/\Gamma(x)} для x!=0, @samp{ai(x)} -- Эйри функция Ai(x), @samp{bi(x)} -- Эйри функция Bi(x), @samp{cl(x)} -- функция Клаузена, @samp{li2(x)} (или @samp{dilog(x)}) -- дилогарифм @math{Li_2(x) = - \Re \int_0^x ds \log(1 [...]
+
+Экспоненциальные интегралы: @samp{ci(x)} -- cos-интеграл @math{Ci(x) = \int_0^x dt \cos(t)/t}, @samp{si(x)} -- sin-интеграл @math{Si(x) = \int_0^x dt \sin(t)/t}, @samp{erf(x)} -- функция ошибки @math{erf(x) = (2/\sqrt(\pi)) \int_0^x dt \exp(-t^2)}, @samp{ei(x)} -- интеграл @math{Ei(x) := - PV(\int_@{-x@}^\infty dt \exp(-t)/t)} (где PV обозначает главное значение), @samp{e1(x)} -- интеграл @math{E_1(x) := Re \int_1^\infty dt \exp(-xt)/t} , @samp{e2(x)} -- интеграл @math{E_2(x) := Re \int_ [...]
+
+Функции Бесселя: @samp{j(nu,x)} -- функция Бесселя первого рода, @samp{y(nu,x)} -- функция Бесселя второго рода, @samp{i(nu,x)} -- модифицированная функция Бесселя первого рода, @samp{k(nu,x)} -- модифицированная функция Бесселя второго рода.
+
+Эллиптические интегралы: @samp{ee(k)} -- полный эллиптический интеграл @math{E(k) = E(\pi/2, k)}, @samp{ek(k)} -- полный эллиптический интеграл @math{K(k) = F(\pi/2, k)}, @samp{e(phi,k)} -- эллиптический интеграл @math{E(\phi,k) = \int_0^\phi dt \sqrt((1 - k^2 \sin^2(t)))}, @samp{f(phi,k)} -- эллиптический интеграл @math{F(\phi,k) = \int_0^\phi dt 1/\sqrt((1 - k^2 \sin^2(t)))}.
+ at end ifnothtml
+
+Функции Якоби: @samp{sn(u,m)}, @samp{cn(u,m)}, @samp{dn(u,m)}, @samp{sc(u,m)}, @samp{sd(u,m)}, @samp{ns(u,m)}, @samp{cs(u,m)}, @samp{cd(u,m)}, @samp{nc(u,m)}, @samp{ds(u,m)}, @samp{dc(u,m)}, @samp{nd(u,m)}.
+
+Некоторые из функций могут быть недоступны если не была включена поддержка GSL при компиляции библиотеки MathGL.
+
+При разборе формул нет различия между верхним и нижним регистром. Если аргумент лежит вне области определения функции, то возвращается NaN.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node  Command options, Interfaces, Textual formulas, General concepts
+ at section Опции команд
+ at nav{}
+
+Опции команд позволяют легко настроить вид отдельного графика не меняя глобальных настроек для все рисунка. Каждая опция отделяется от предыдущей символом @samp{;}. Опции работают так, что запоминают текущие настройки рисунка, применяют собственные настройки, выполняют команду и возвращают глобальные настройки обратно. Поэтому использование опций для команд обработки данных или настройки графика бесполезно.
+
+Наиболее часто используемые опции -- @code{xrange, yrange, zrange}, устанавливают границы изменения осей координат (и тем самым автоматических массивов). Например, команда @code{Plot(y,"","xrange 0.1 0.9");} или @code{plot y; xrange 0.1 0.9} построит кривую с x-координатой равно распределенной в интервале 0.1 ... 0.9, а не вдоль текущей оси x. @sref{Using options}
+
+Полный список опций:
+ at cindex alpha
+ at cindex alphadef
+ at deffn {Опция MGL} alpha @code{val}
+Задает величину прозрачности поверхности. Значение должно быть в диапазоне [0, 1]. См. также @ref{alphadef}
+ at end deffn
+ at c @cindex ambient
+ at c @deffn {Опция MGL} ambient @code{val}
+ at c Задает яркость фонового освещения. Значение должно быть в диапазоне [0, 1]. См. также @ref{ambient}
+ at c @end deffn
+ at c @cindex diffuse
+ at c @deffn {Опция MGL} diffuse @code{val}
+ at c Задает яркость диффузного освещения для поверхности. Значение должно быть в диапазоне [0, 1]. См. также @ref{diffuse}.
+ at c @end deffn
+
+ at cindex xrange
+ at deffn {Опция MGL} xrange @code{val1 val2}
+Задает границы изменения координаты x. См. также @ref{xrange}
+ at end deffn
+ at cindex yrange
+ at deffn {Опция MGL} yrange @code{val1 val2}
+Задает границы изменения координаты y. См. также @ref{yrange}
+ at end deffn
+ at cindex zrange
+ at deffn {Опция MGL} zrange @code{val1 val2}
+Задает границы изменения координаты z. См. также @ref{zrange}
+ at end deffn
+
+ at cindex cut
+ at deffn {Опция MGL} cut @code{val}
+Задает обрезание точек за пределами осей координат. См. также @ref{cut}.
+ at end deffn
+ at cindex fontsize
+ at deffn {Опция MGL} size @code{val}
+Задает размер текста, маркеров и стрелок. См. также @ref{font}, @ref{marksize}, @ref{arrowsize}.
+ at end deffn
+ at cindex meshnum
+ at deffn {Опция MGL} meshnum @code{val}
+Задает ориентировочное число линий, стрелок, ячеек и пр. См. также @ref{meshnum}
+ at end deffn
+
+ at cindex legend
+ at deffn {Опция MGL} legend 'txt'
+Добавляет строку 'txt' во внутренний массив записей легенды. Стиль линии и маркера аргумента последней вызванной команды построения @ref{1D plotting}. См. также @ref{legend}
+ at end deffn
+ at cindex value
+ at deffn {MGL option} value @code{val}
+Задает значение, которое будет использовано как дополнительный числовой параметр при построении графика.
+ at end deffn
+
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Interfaces, , Command options, General concepts
+ at section Интерфейсы
+ at nav{}
+
+ at ifset UDAV
+Вы можете использовать класс @code{mglParse} для выполнения MGL скриптов из других языков программирования.
+ at end ifset
+
+ at ifclear UDAV
+
+Библиотека MathGL имеет интерфейсы к ряду языков программирования. Большинство из них основано на С интерфейсе с использованием SWIG. Это Python, Java, Octave, Lisp, C#, Guile, Lua, Modula 3, Ocaml, Perl, PHP, Pike, R, Ruby, и Tcl интерфейсы. Также есть Fortran интерфейс, который имеет схожий набор функций, но слегка различающиеся типы аргументов (целые вместо указателей). Эти функции отмечены как [C function].
+
+Некоторые языки поддерживают классы (подобно C++ или Python). Имена функций для них такие же как в С++ (см. @ref{MathGL core} и @ref{Data processing}) и отмечены, например, так [Method on mglGraph].
+
+Наконец, специальный командный язык MGL (см. @ref{MGL scripts}) был создан для быстрого доступа к функциям рисования. Соответствующие скрипты могут быть выполнены самостоятельно (с помощью UDAV, mglconv, mglview и т.д.) или из программы на языке C/C++/Python/... (см. @ref{mglParse class}).
+
+ at menu
+* C interface::
+* C++ interface::
+ at end menu
+
+ at external{}
+ at node C interface, C++ interface, , Interfaces
+ at subsection C/Fortran интерфейс
+ at nav{}
+
+C интерфейс -- основа для многих других интерфейсов. Он содержит функции С для всех методов MathGL. В отличие от C++ классов, C функции содержат обязательный(ые) аргумент(ы) типа HMGL (для графики) и/или HCDT/HMDT/HADT (для массивов данных), который указывают на объект для рисования или изменения. Поэтому перед использованием их необходимо создать с помощью функции @code{mgl_create_*()}, и удалить после использования (или в конце программы) с помощью функции @code{mgl_delete_*()}.
+
+Все C функции описаны в заголовочном файле @code{#include <mgl2/mgl_cf.h>} и используют переменные следующих типов:
+ at itemize
+ at item
+ at code{HMGL} --- Указатель на класс @code{mglGraph} (см. @ref{MathGL core}).
+ at item
+ at code{HCDT} --- Указатель на класс @code{const mglDataA} (см. @ref{Data processing}) --- неизменяемые массивы данных.
+ at item
+ at code{HMDT} --- Указатель на класс @code{mglData} (см. @ref{Data processing}) --- массивы данных с действительными числами.
+ at item
+ at code{HADT} --- Указатель на класс @code{mglDataC} (см. @ref{Data processing}) --- массивы данных с комплексными числами.
+ at item
+ at code{HMPR} --- Указатель на класс @code{mglParse} (см. @ref{mglParse class}) --- выполнение MGL скриптов.
+ at item
+ at code{HMEX} --- Указатель на класс @code{mglExpr} (см. @ref{Evaluate expression}) --- текстовые формулы для действительных чисел.
+ at item
+ at code{HMAX} --- Указатель на класс @code{mglExprC} (см. @ref{Evaluate expression}) --- текстовые формулы для комплексных чисел.
+ at end itemize
+
+Фортрановские функции и подпрограммы имеют такие же имена как функции С. Однако есть отличие. Переменные типов @code{HMGL, HCDT, HMDT, ...} должны быть целыми с достаточной разрядностью (@code{integer*4} для 32-битной операционной системы или @code{integer*8} для 64-битной). Все C функции типа @code{void} --- подпрограммы на Фортране и должны вызываться оператором @code{call}. Прочие функции, возвращающие тип @code{HMGL} или @code{HMDT} и т.п. должны быть объявлены в Фортране как возвращ [...]
+
+ at external{}
+ at node C++ interface, , C interface, Interfaces
+ at subsection C++/Python интерфейс
+ at nav{}
+
+MathGL имеет интерфейс на основе классов (объектов с членами-функциями) с использованием библиотеки SWIG. Типичный пример -- Python, имя которого использовано в заголовке раздела. В точности те же классы используются и в C++ API. Отмечу, что С++ классы содержат только inline члены-функции, что делает С++ API независимым от компилятора даже для бинарной версии.
+
+Есть 3 основных класса:
+ at itemize
+ at item @code{mglGraph}
+-- обеспечивает вывод графики (см. @ref{MathGL core}).
+ at item @code{mglData}
+-- обеспечивает обработку данных (см. @ref{Data processing}). Класс имеет возможность прямого доступа к данным с помощью конструкции вида: @code{dat[i]=sth;} или @code{sth=dat[i]}, где используется "плоское" представление данных (т.е., @var{i} может быть в диапазоне 0...nx*nx*nz-1). Также можно импортировать массивы NumPy в Python: @code{mgl_dat = mglData(numpy_dat);}.
+ at item @code{mglParse}
+-- обеспечивает выполнение скриптов MGL (см. @ref{MGL scripts}).
+ at end itemize
+
+
+Для использования в Python достаточно выполнить @samp{import mathgl}. Простейший пример имеет вид:
+ at verbatim
+import mathgl
+a=mathgl.mglGraph()
+a.Box()
+a.WritePNG("test.png")
+ at end verbatim
+Также можно импортировать все классы из модуля @code{mathgl} и обеспечить более легкий доступ к MathGL:
+ at verbatim
+from mathgl import *
+a=mglGraph()
+a.Box()
+a.WritePNG("test.png")
+ at end verbatim
+Это становится более полезным если, например, вы создаете много объектов данных @code{mglData}.
+
+ at end ifclear
+
+ at external{}
diff --git a/texinfo/copyright.texi b/texinfo/copyright.texi
new file mode 100644
index 0000000..f76c118
--- /dev/null
+++ b/texinfo/copyright.texi
@@ -0,0 +1,11 @@
+Copyright @copyright{} 2008-2012 Alexey A. Balakin.
+
+ at quotation
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.2
+or any later version published by the Free Software Foundation;
+with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+Texts.  A copy of the license is included in the section entitled ``GNU
+Free Documentation License.''
+ at end quotation
+
diff --git a/texinfo/core_en.texi b/texinfo/core_en.texi
new file mode 100644
index 0000000..7f75ac0
--- /dev/null
+++ b/texinfo/core_en.texi
@@ -0,0 +1,3803 @@
+ at c ------------------------------------------------------------------
+ at chapter MathGL core
+ at nav{}
+ at cindex mglGraph
+
+ at ifset UDAV
+This chapter contains a lot of plotting commands for 1D, 2D and 3D data. It also encapsulates parameters for axes drawing. Moreover an arbitrary coordinate transformation can be used for each axis.  Additional information about colors, fonts, formula parsing can be found in @ref{General concepts}. The full list of symbols used by MathGL for setting up plots can be found in @ref{Symbols for styles}.
+ at end ifset
+
+ at ifclear UDAV
+The core of MathGL is @strong{mglGraph} class defined in @code{#include <mgl2/mgl.h>}. It contains a lot of plotting functions for 1D, 2D and 3D data. It also encapsulates parameters for axes drawing. Moreover an arbitrary coordinate transformation can be used for each axis. All plotting functions use data encapsulated in mglData class (see @ref{Data processing}) that allows to check sizes of used arrays easily. Also it have many functions for data handling: modify it by formulas, find m [...]
+ at end ifclear
+
+Some of MathGL features will appear only in novel versions. To test used MathGL version you can use following function.
+ at anchor{version}
+ at deftypefn {MGL command} {} version 'ver'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{bool} CheckVersion (@code{const char *}ver) static
+ at deftypefnx {C function} @code{int} mgl_check_version (@code{const char *}ver)
+ at end ifclear
+Return zero if MathGL version is appropriate for required by @var{ver}, i.e. if major version is the same and minor version is greater or equal to one in @var{ver}.
+ at end deftypefn
+
+ at menu
+* Constructor::
+* Graphics setup::
+* Axis settings::
+* Subplots and rotation::
+* Export picture::
+* Background::
+* Primitives::
+* Text printing::
+* Axis and Colorbar::
+* Legend::
+* 1D plotting::
+* 2D plotting::
+* 3D plotting::
+* Dual plotting::
+* Vector fields::
+* Other plotting::
+* Nonlinear fitting::
+* Data manipulation::
+ at c * IDTF functions::
+ at end menu
+
+ at c ##################################################################
+ at external{}
+ at node Constructor, Graphics setup, , MathGL core
+ at section Create and delete objects
+ at nav{}
+
+ at ifclear UDAV
+ at deftypefn {Constructor on @code{mglGraph}} {} mglGraph (@code{int} kind=@code{0}, @code{int} width=@code{600}, @code{int} height=@code{400})
+ at deftypefnx {Constructor on @code{mglGraph}} {} mglGraph (@code{const mglGraph &}gr)
+ at deftypefnx {Constructor on @code{mglGraph}} {} mglGraph (@code{HMGL} gr)
+ at deftypefnx {C function} @code{HMGL} mgl_create_graph (@code{int} width, @code{int} height)
+ at deftypefnx {C function} @code{HMGL} mgl_create_graph_gl ()
+Creates the instance of class mglGraph with specified sizes @var{width} and @var{height}. Parameter @var{kind} may have following values: @samp{0} -- use default plotter, @samp{1} -- use OpenGL plotter.
+ at end deftypefn
+
+ at deftypefn {Destructor on @code{mglGraph}} {} ~mglGraph ()
+ at deftypefnx {C function} @code{HMGL} mgl_delete_graph (@code{HMGL} gr)
+Deletes the instance of class mglGraph.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{HMGL} Self ()
+Returns the pointer to internal object of type @code{HMGL}.
+ at end deftypefn
+ at end ifclear
+
+ at ifset UDAV
+You don't need to create canvas object in MGL.
+ at end ifset
+
+ at c ##################################################################
+ at external{}
+ at node Graphics setup, Axis settings, Constructor, MathGL core
+ at section Graphics setup
+ at nav{}
+ at cindex MathGL setup
+
+Functions and variables in this group influences on overall graphics appearance. So all of them should be placed @emph{before} any actual plotting function calls.
+
+ at anchor{reset}
+ at deftypefn {MGL command} {} reset
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} DefaultPlotParam ()
+ at deftypefnx {C function} @code{void} mgl_set_def_param (@code{HMGL} gr)
+ at end ifclear
+Restore initial values for all of parameters and clear the image.
+ at end deftypefn
+
+ at menu
+* Transparency::
+* Lighting::
+* Fog::
+* Default sizes::
+* Cutting::
+* Font settings::
+* Palette and colors::
+* Masks::
+* Error handling::
+* Stop drawing::
+ at end menu
+
+ at c ==================================================================
+ at external{}
+ at node Transparency, Lighting, , Graphics setup
+ at subsection Transparency
+ at nav{}
+ at cindex Alpha
+ at ifclear UDAV
+ at cindex SetAlphaDef
+ at cindex SetTranspType
+ at end ifclear
+ at cindex AlphaDef
+ at cindex TranspType
+
+There are several functions and variables for setup transparency. The general function is @ref{alpha} which switch on/off the transparency for overall plot. It influence only for graphics which created after @ref{alpha} call (with one exception, OpenGL). Function @ref{alphadef} specify the default value of alpha-channel. Finally, function @ref{transptype} set the kind of transparency. @sref{Transparency and lighting}
+
+ at anchor{alpha}
+ at deftypefn {MGL command} {} alpha @code{[val=on]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Alpha (@code{bool} enable)
+ at deftypefnx {C function} @code{void} mgl_set_alpha (@code{HMGL} gr, @code{int} enable)
+ at end ifclear
+Sets the transparency on/off and returns previous value of transparency. It is recommended to call this function before any plotting command. Default value is transparency off.
+ at end deftypefn
+
+ at anchor{alphadef}
+ at deftypefn {MGL command} {} alphadef @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetAlphaDef (@code{mreal} val)
+ at deftypefnx {C function} @code{void} mgl_set_alpha_default (@code{HMGL} gr, @code{mreal} alpha)
+ at end ifclear
+Sets default value of alpha channel (transparency) for all plotting functions. Initial value is 0.5.
+ at end deftypefn
+
+ at anchor{transptype}
+ at deftypefn {MGL command} {} transptype @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetTranspType (@code{int} type)
+ at deftypefnx {C function} @code{void} mgl_set_transp_type (@code{HMGL} gr, @code{int} type)
+ at end ifclear
+Set the type of transparency. Possible values are:
+ at itemize @bullet
+ at item
+Normal transparency (@samp{0}) -- below things is less visible than upper ones. It does not look well in OpenGL mode (mglGraphGL) for several surfaces.
+ at item
+Glass-like transparency (@samp{1}) -- below and upper things are commutable and just decrease intensity of light by RGB channel.
+ at item
+Lamp-like transparency (@samp{2}) -- below and upper things are commutable and are the source of some additional light. I recommend to set @code{SetAlphaDef(0.3)} or less for lamp-like transparency.
+ at end itemize
+ at sref{Types of transparency}.
+ at end deftypefn
+
+ at c ==================================================================
+ at external{}
+ at node Lighting, Fog, Transparency, Graphics setup
+ at subsection Lighting
+ at nav{}
+
+ at ifclear UDAV
+ at cindex SetAmbient
+ at cindex AddLight
+ at end ifclear
+ at cindex Light
+ at cindex Ambient
+
+There are several functions for setup lighting. The general function is @ref{light} which switch on/off the lighting for overall plot. It influence only for graphics which created after @ref{light} call (with one exception, OpenGL). Generally MathGL support up to 10 independent light sources. But in OpenGL mode only 8 of light sources is used due to OpenGL limitations. The position, color, brightness of each light source can be set separately. By default only one light source is active.  [...]
+
+ at anchor{light}
+ at deftypefn {MGL command} {} light @code{[val=on]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{bool} Light (@code{bool} enable)
+ at deftypefnx {C function} @code{void} mgl_set_light (@code{HMGL} gr, @code{int} enable)
+ at end ifclear
+Sets the using of light on/off for overall plot. Function returns previous value of lighting. Default value is lightning off.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} light @code{num} @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Light (@code{int} n, @code{bool} enable)
+ at deftypefnx {C function} @code{void} mgl_set_light_n (@code{HMGL} gr, @code{int} n, @code{int} enable)
+ at end ifclear
+Switch on/off @var{n}-th light source separately.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} light @code{num xdir ydir zdir} ['col'='w' @code{br=0.5}]
+ at deftypefnx {MGL command} {} light @code{num xdir ydir zdir xpos ypos zpos} ['col'='w' @code{br=0.5 ap=0}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} AddLight (@code{int} n, @code{mglPoint} d, @code{char} c=@code{'w'}, @code{mreal} bright=@code{0.5}, @code{mreal} ap=@code{0})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} AddLight (@code{int} n, @code{mglPoint} r, @code{mglPoint} d, @code{char} c=@code{'w'}, @code{mreal} bright=@code{0.5}, @code{mreal} ap=@code{0})
+ at deftypefnx {C function} @code{void} mgl_add_light (@code{HMGL} gr, @code{int} n, @code{mreal} dx, @code{mreal} dy, @code{mreal} dz)
+ at deftypefnx {C function} @code{void} mgl_add_light_ext (@code{HMGL} gr, @code{int} n, @code{mreal} dx, @code{mreal} dy, @code{mreal} dz, @code{char} c, @code{mreal} bright, @code{mreal} ap)
+ at deftypefnx {C function} @code{void} mgl_add_light_loc (@code{HMGL} gr, @code{int} n, @code{mreal} rx, @code{mreal} ry, @code{mreal} rz, @code{mreal} dx, @code{mreal} dy, @code{mreal} dz, @code{char} c, @code{mreal} bright, @code{mreal} ap)
+ at end ifclear
+The function adds a light source with identification @var{n} in direction @var{d} with color @var{c} and with brightness @var{bright} (which must be in range [0,1]). If position @var{r} is specified and isn't NAN then light source is supposed to be local otherwise light source is supposed to be placed at infinity.
+ at end deftypefn
+
+ at anchor{diffuse}
+ at deftypefn {MGL command} {} diffuse @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetDiffuse (@code{mreal} bright)
+ at deftypefnx {C function} @code{void} mgl_set_difbr (@code{HMGL} gr, @code{mreal} bright)
+ at end ifclear
+Set brightness of diffusive light (only for local light sources).
+ at end deftypefn
+
+ at anchor{ambient}
+ at deftypefn {MGL command} {} ambient @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetAmbient (@code{mreal} bright=@code{0.5})
+ at deftypefnx {C function} @code{void} mgl_set_ambbr (@code{HMGL} gr, @code{mreal} bright)
+ at end ifclear
+Sets the brightness of ambient light. The value should be in range [0,1].
+ at end deftypefn
+
+ at anchor{attachlight}
+ at deftypefn {MGL command} {} attachlight @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} AttachLight (@code{bool} val)
+ at deftypefnx {C function} @code{void} mgl_set_attach_light (@code{HMGL} gr, @code{int} val)
+ at end ifclear
+Set to attach light settings to @ref{inplot}/@ref{subplot}. Note, OpenGL and some output formats don't support this feature.
+ at end deftypefn
+
+ at c ==================================================================
+ at external{}
+ at node Fog, Default sizes, Lighting, Graphics setup
+ at subsection Fog
+ at nav{}
+ at cindex Fog
+
+ at anchor{fog}
+ at deftypefn {MGL command} {} fog @code{val [dz=0.25]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Fog (@code{mreal} d, @code{mreal} dz=@code{0.25})
+ at deftypefnx {C function} @code{void} mgl_set_fog (@code{HMGL} gr, @code{mreal} d, @code{mreal} dz)
+ at end ifclear
+Function imitate a fog in the plot. Fog start from relative distance @var{dz} from view point and its density growths exponentially in depth. So that the fog influence is determined by law ~ 1-exp(- at emph{d*z}). Here @emph{z} is normalized to 1 depth of the plot. If value @var{d}=@code{0} then the fog is absent. Note, that fog was applied at stage of image creation, not at stage of drawing. @sref{Adding fog}
+ at end deftypefn
+
+ at c ==================================================================
+ at external{}
+ at node Default sizes, Cutting, Fog, Graphics setup
+ at subsection Default sizes
+ at nav{}
+ at ifclear UDAV
+ at cindex SetBarWidth
+ at cindex SetMarkSize
+ at cindex SetArrowSize
+ at cindex SetMeshNum
+ at cindex SetPlotId
+ at end ifclear
+ at cindex BarWidth
+ at cindex MarkSize
+ at cindex ArrowSize
+ at cindex MeshNum
+
+These variables control the default (initial) values for most graphics parameters including sizes of markers, arrows, line width and so on. As any other settings these ones will influence only on plots created after the settings change.
+
+ at anchor{barwidth}
+ at deftypefn {MGL command} {} barwidth @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetBarWidth ( @code{mreal} val)
+ at deftypefnx {C function} @code{void} mgl_set_bar_width (@code{HMGL} gr, @code{mreal} val)
+ at end ifclear
+Sets relative width of rectangles in @ref{bars}, @ref{barh}, @ref{boxplot}, @ref{candle}, @ref{ohlc}. Default value is @code{0.7}.
+ at end deftypefn
+
+ at anchor{marksize}
+ at deftypefn {MGL command} {} marksize @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetMarkSize (@code{mreal} val)
+ at deftypefnx {C function} @code{void} mgl_set_mark_size (@code{HMGL} gr, @code{mreal} val)
+ at end ifclear
+Sets size of marks for @ref{1D plotting}. Default value is @code{1}.
+ at end deftypefn
+
+ at anchor{arrowsize}
+ at deftypefn {MGL command} {} arrowsize @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetArrowSize (@code{mreal} val)
+ at deftypefnx {C function} @code{void} mgl_set_arrow_size (@code{HMGL} gr, @code{mreal} val)
+ at end ifclear
+Sets size of arrows for @ref{1D plotting}, lines and curves (see @ref{Primitives}). Default value is @code{1}.
+ at end deftypefn
+
+ at anchor{meshnum}
+ at anchor{MeshNum}
+ at deftypefn {MGL command} {} meshnum @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetMeshNum (@code{int} val)
+ at deftypefnx {C function} @code{void} mgl_set_meshnum (@code{HMGL} gr, @code{int} num)
+ at end ifclear
+Sets approximate number of lines in @ref{mesh}, @ref{fall}, @ref{grid2}, and also the number of hachures in @ref{vect}, @ref{dew}, and the number of cells in @ref{cloud}, and the number of markers in @ref{plot}, @ref{tens}, @ref{step}, @ref{mark}, @ref{textmark}. By default (=0) it draws all lines/hachures/cells/markers.
+ at end deftypefn
+
+ at anchor{facenum}
+ at deftypefn {MGL command} {} facenum @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetFaceNum (@code{int} val)
+ at deftypefnx {C function} @code{void} mgl_set_facenum (@code{HMGL} gr, @code{int} num)
+ at end ifclear
+Sets approximate number of visible faces. Can be used for speeding up drawing by cost of lower quality. By default (=0) it draws all of them.
+ at end deftypefn
+
+ at anchor{plotid}
+ at deftypefn {MGL command} {} plotid 'id'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetPlotId (@code{const char *}id)
+ at deftypefnx {C function} @code{void} mgl_set_plotid (@code{HMGL} gr, @code{const char *}id)
+ at end ifclear
+Sets default name @var{id} as filename for saving (in FLTK window for example).
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Method on @code{mglGraph}} @code{const char *} GetPlotId ()
+ at deftypefnx {C function only} @code{const char *} mgl_get_plotid (@code{HMGL} gr)
+ at deftypefnx {Fortran subroutine} @code{} mgl_get_plotid (@code{long} gr, @code{char *}out, @code{int} len)
+Gets default name @var{id} as filename for saving (in FLTK window for example).
+ at end deftypefn
+ at end ifclear
+
+ at anchor{pendelta}
+ at deftypefn {MGL command} {} pendelta @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetPenDelta (@code{double} val)
+ at deftypefnx {C function} @code{void} mgl_pen_delta (@code{HMGL} gr, @code{double} val)
+ at end ifclear
+Changes the blur around lines and text (default is 1). For @var{val}>1 the text and lines are more sharped. For @var{val}<1 the text and lines are more blurred.
+ at end deftypefn
+
+ at c ==================================================================
+ at external{}
+ at node Cutting, Font settings, Default sizes, Graphics setup
+ at subsection Cutting
+ at nav{}
+ at ifclear UDAV
+ at cindex SetCut
+ at cindex SetCutBox
+ at cindex CutOff
+ at end ifclear
+ at cindex Cut
+
+These variables and functions set the condition when the points are excluded (cutted) from the drawing. Note, that a point with NAN value(s) of coordinate or amplitude will be automatically excluded from the drawing. @sref{Cutting sample}
+
+ at anchor{cut}
+ at deftypefn {MGL command} {} cut @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetCut (@code{bool} val)
+ at deftypefnx {C function} @code{void} mgl_set_cut (@code{HMGL} gr, @code{int} val)
+ at end ifclear
+Flag which determines how points outside bounding box are drawn. If it is @code{true} then points are excluded from plot (it is default) otherwise the points are projected to edges of bounding box.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} cut @code{x1 y1 z1 x2 y2 z2}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetCutBox (@code{mglPoint} p1, @code{mglPoint} p1)
+ at deftypefnx {C function} @code{void} mgl_set_cut_box (@code{HMGL} gr, @code{mreal} x1, @code{mreal} y1, @code{mreal} z1, @code{mreal} x2, @code{mreal} y2, @code{mreal} z2)
+ at end ifclear
+Lower and upper edge of the box in which never points are drawn. If both edges are the same (the variables are equal) then the cutting box is empty.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} cut 'cond'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} CutOff (@code{const char *}cond)
+ at deftypefnx {C function} @code{void} mgl_set_cutoff (@code{HMGL} gr, @code{const char *}cond)
+ at end ifclear
+Sets the cutting off condition by formula @var{cond}. This condition determine will point be plotted or not. If value of formula is nonzero then point is omitted, otherwise it plotted. Set argument as @code{""} to disable cutting off condition.
+ at end deftypefn
+
+ at c ==================================================================
+ at external{}
+ at node Font settings, Palette and colors, Cutting, Graphics setup
+ at subsection Font settings
+ at nav{}
+ at ifclear UDAV
+ at cindex SetFontSize
+ at cindex SetFontDef
+ at cindex SetRotatedText
+ at cindex SetFontSizePT
+ at cindex SetFontSizeCM
+ at cindex SetFontSizeIN
+ at cindex LoadFont
+ at cindex CopyFont
+ at cindex RestoreFont
+ at end ifclear
+ at cindex Font
+ at cindex RotateText
+
+ at anchor{font}
+ at deftypefn {MGL command} {} font 'fnt' [@code{val=6}]
+Font style for text and labels (see text). Initial style is 'fnt'=':rC' give Roman font with centering. Parameter @code{val} sets the size of font for tick and axis labels. Default font size of axis labels is 1.4 times large than for tick labels. For more detail, see @ref{Font styles}.
+ at end deftypefn
+
+ at anchor{rotatetext}
+ at deftypefn {MGL command} {} rotatetext @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetRotatedText (@code{bool} val)
+ at deftypefnx {C function} @code{void} mgl_set_rotated_text (@code{HMGL} gr, @code{int} val)
+ at end ifclear
+Sets to use or not text rotation.
+ at end deftypefn
+
+ at anchor{loadfont}
+ at deftypefn {MGL command} {} loadfont ['name'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} LoadFont (@code{const char *}name, @code{const char *}path=@code{""})
+ at deftypefnx {C function} @code{void} mgl_load_font (@code{HMGL} gr, @code{const char *}name, @code{const char *}path)
+ at end ifclear
+Load font typeface from @var{path}/@var{name}. Empty name will load default font.
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Method on @code{mglGraph}} @code{void} SetFontDef (@code{const char *}fnt)
+ at deftypefnx {C function} @code{void} mgl_set_font_def (@code{HMGL} gr, @code{const char *} val)
+Sets the font specification (see @ref{Text printing}). Default is @samp{rC} -- Roman font centering.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} SetFontSize (@code{mreal} val)
+ at deftypefnx {C function} @code{void} mgl_set_font_size (@code{HMGL} gr, @code{mreal} val)
+Sets the size of font for tick and axis labels. Default font size of axis labels is 1.4 times large than for tick labels.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} SetFontSizePT (@code{mreal} cm, @code{int} dpi=@code{72})
+Set FontSize by size in pt and picture DPI (default is 16 pt for dpi=72).
+ at end deftypefn
+ at deftypefn {Method on @code{mglGraph}} @code{inline void} SetFontSizeCM (@code{mreal} cm, @code{int} dpi=@code{72})
+Set FontSize by size in centimeters and picture DPI (default is 0.56 cm = 16 pt).
+ at end deftypefn
+ at deftypefn {Method on @code{mglGraph}} @code{inline void} SetFontSizeIN (@code{mreal} cm, @code{int} dpi=@code{72})
+Set FontSize by size in inch and picture DPI (default is 0.22 in = 16 pt).
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} CopyFont (@code{mglGraph *} from)
+ at deftypefnx {C function} @code{void} mgl_copy_font (@code{HMGL} gr, @code{HMGL} gr_from)
+Copy font data from another @code{mglGraph} object.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} RestoreFont ()
+ at deftypefnx {C function} @code{void} mgl_restore_font (@code{HMGL} gr)
+Restore font data to default typeface.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} SetDefFont (@code{const char *}name, @code{const char *}path=@code{""}) static
+ at deftypefnx {C function} @code{void} mgl_def_font (@code{const char *}name, @code{const char *}path)
+Load default font typeface (for all newly created HMGL/mglGraph objects) from @var{path}/@var{name}.
+ at end deftypefn
+
+ at end ifclear
+
+ at c ==================================================================
+ at external{}
+ at node Palette and colors, Masks, Font settings, Graphics setup
+ at subsection Palette and colors
+ at nav{}
+ at ifclear UDAV
+ at cindex SetPalette
+ at end ifclear
+ at cindex Palette
+
+ at anchor{palette}
+ at deftypefn {MGL command} {} palette 'colors'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetPalette (@code{const char *}colors)
+ at deftypefnx {C function} @code{void} mgl_set_palette (@code{HMGL} gr, @code{const char *}colors)
+ at end ifclear
+Sets the palette as selected colors. Default value is @code{"Hbgrcmyhlnqeup"} that corresponds to colors: dark gray @samp{H}, blue @samp{b}, green @samp{g}, red @samp{r}, cyan @samp{c}, magenta @samp{m}, yellow @samp{y}, gray @samp{h}, blue-green @samp{l}, sky-blue @samp{n}, orange @samp{q}, yellow-green @samp{e}, blue-violet @samp{u}, purple @samp{p}. The palette is used mostly in 1D plots (see @ref{1D plotting}) for curves which styles are not specified. Internal color counter will be  [...]
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Method on @code{mglGraph}} @code{void} SetDefScheme (@code{const char *}sch)
+ at deftypefnx {C function} @code{void} mgl_set_def_sch (@code{HMGL} gr, @code{const char *}sch)
+Sets the @var{sch} as default color scheme. Default value is @code{"BbcyrR"}.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} SetColor (@code{char} id, @code{mreal} r, @code{mreal} g, @code{mreal} b) static
+ at deftypefnx {C function} @code{void} mgl_set_color (@code{char} id, @code{mreal} r, @code{mreal} g, @code{mreal} b)
+Sets RGB values for color with given @var{id}. This is global setting which influence on any later usage of symbol @var{id}.
+ at end deftypefn
+ at end ifclear
+
+
+ at anchor{gray}
+ at deftypefn {MGL command} {} gray [@code{val=on}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Gray (@code{bool} enable)
+ at deftypefnx {C function} @code{void} mgl_set_gray (@code{HMGL} gr, @code{int} enable)
+ at end ifclear
+Sets the gray-scale mode on/off.
+ at end deftypefn
+
+ at c ==================================================================
+ at external{}
+ at node Masks, Error handling, Palette and colors, Graphics setup
+ at subsection Masks
+ at nav{}
+ at cindex SetMask
+ at cindex SetMaskAngle
+
+ at anchor{mask}
+ at deftypefn {MGL command} {} mask 'id' 'hex'
+ at deftypefnx {Команда MGL} {} mask 'id' hex
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetMask (@code{char} id, @code{const char *}hex)
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetMask (@code{char} id, @code{uint64_t} hex)
+ at deftypefnx {C function} @code{void} mgl_set_mask (@code{HMGL} gr, @code{const char *}hex)
+ at deftypefnx {C function} @code{void} mgl_set_mask_val (@code{HMGL} gr, @code{uint64_t} hex)
+ at end ifclear
+Sets new bit matrix @var{hex} of size 8*8 for mask with given @var{id}. This is global setting which influence on any later usage of symbol @var{id}. The predefined masks are (see @ref{Color scheme}): @samp{-} is 000000FF00000000, @samp{+} is 080808FF08080808,	@samp{=} is 0000FF00FF000000,	@samp{;} is 0000007700000000, @samp{o} is 0000182424180000,	@samp{O} is 0000183C3C180000,	@samp{s} is 00003C24243C0000,	@samp{S} is 00003C3C3C3C0000, @samp{~} is 0000060990600000,	@samp{<} is 006058465 [...]
+ at end deftypefn
+
+ at deftypefn {MGL command} {} mask angle
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetMaskAngle (@code{int} angle)
+ at deftypefnx {C function} @code{void} mgl_set_mask_angle (@code{HMGL} gr, @code{int} angle)
+ at end ifclear
+Sets the default rotation angle (in degrees) for masks. Note, you can use symbols @samp{\}, @samp{/}, @samp{I} in color scheme for setting rotation angles as 45, -45 and 90 degrees correspondingly.
+ at end deftypefn
+
+
+ at c ==================================================================
+ at external{}
+ at node Error handling, Stop drawing, Masks, Graphics setup
+ at subsection Error handling
+ at nav{}
+ at ifset UDAV
+All warnings will be displayed automatically in special tool-window or in console.
+ at end ifset
+ at ifclear UDAV
+ at cindex Message
+ at cindex SetWarn
+ at cindex GetWarn
+
+Normally user should set it to zero by @code{SetWarn(0);} before plotting and check if @code{GetWarn()} or @code{Message()} return non zero after plotting. Only last warning will be saved. All warnings/errors produced by MathGL is not critical -- the plot just will not be drawn. By default, all warnings are printed in stderr. You can disable it by using @code{mgl_suppress_warn(true);}.
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} SetWarn (@code{int} code, @code{const char *}info=@code{""})
+ at deftypefnx {C function} @code{void} mgl_set_warn (@code{HMGL} gr, @code{int} code, @code{const char *}info)
+Set warning code. Normally you should call this function only for clearing the warning state, i.e. call @code{SetWarn(0);}. Text @var{info} will be printed as is if @var{code}<0.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{const char *}Message ()
+ at deftypefnx {C function only} @code{const char *}mgl_get_mess (@code{HMGL} gr)
+ at deftypefnx {Fortran subroutine} @code{} mgl_get_mess (@code{long} gr, @code{char *}out, @code{int} len)
+Return messages about matters why some plot are not drawn. If returned string is empty then there are no messages.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{int} GetWarn ()
+ at deftypefnx {C function} @code{int} mgl_get_warn (@code{HMGL} gr)
+Return the numerical ID of warning about the not drawn plot. Possible values are:
+ at table @code
+ at item mglWarnNone=0
+Everything OK
+ at item mglWarnDim
+Data dimension(s) is incompatible
+ at item mglWarnLow
+Data dimension(s) is too small
+ at item mglWarnNeg
+Minimal data value is negative
+ at item mglWarnFile
+No file or wrong data dimensions
+ at item mglWarnMem
+Not enough memory
+ at item mglWarnZero
+Data values are zero
+ at item mglWarnLeg
+No legend entries
+ at item mglWarnSlc
+Slice value is out of range
+ at item mglWarnCnt
+Number of contours is zero or negative
+ at item mglWarnOpen
+Couldn't open file
+ at item mglWarnLId
+Light: ID is out of range
+ at item mglWarnSize
+Setsize: size(s) is zero or negative
+ at item mglWarnFmt
+Format is not supported for that build
+ at item mglWarnTern
+Axis ranges are incompatible
+ at item mglWarnNull
+Pointer is NULL
+ at item mglWarnSpc
+Not enough space for plot
+ at item mglScrArg
+Wrong argument(s) of a command in MGL script
+ at item mglScrCmd
+Wrong command in MGL script
+ at item mglScrLong
+Too long line in MGL script
+ at item mglScrStr
+Unbalanced ' in MGL script
+ at item mglScrTemp
+Change temporary data in MGL script
+ at end table
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} SuppressWarn (@code{bool} state) static
+ at deftypefnx {C function} @code{void} mgl_suppress_warn (@code{int} state)
+Disable printing warnings to @code{stderr} if @var{state} is nonzero.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} SetGlobalWarn (@code{const char *}info) static
+ at deftypefnx {C function} @code{void} mgl_set_global_warn (@code{const char *}info)
+Set warning message @var{info} for global scope.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{const char *} GlobalWarn () static
+ at deftypefnx {C function} @code{const char *} mgl_get_global_warn ()
+Get warning message(s) for global scope.
+ at end deftypefn
+
+ at end ifclear
+
+ at c ==================================================================
+ at external{}
+ at node Stop drawing, , Error handling, Graphics setup
+ at subsection Stop drawing
+ at nav{}
+ at ifset UDAV
+You can use @ref{stop} command or press corresponding toolbutton to stop drawing and script execution.
+ at end ifset
+ at ifclear UDAV
+ at cindex Stop
+ at cindex NeedStop
+ at cindex SetEventFunc
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} Stop (@code{bool} stop=@code{true})
+ at deftypefnx {C function only} @code{void} mgl_ask_stop (@code{HMGL} gr, @code{int} stop)
+Ask to stop drawing if @var{stop} is non-zero, otherwise reset stop flag.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{bool} NeedStop ()
+ at deftypefnx {C function only} @code{void} mgl_need_stop (@code{HMGL} gr)
+Return @code{true} if drawing should be terminated. Also it process all events in GUI. User should call this function from time to time inside a long calculation to allow processing events for GUI.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{bool} SetEventFunc (@code{void (*}func at code{)(void *)}, @code{void *}par=@code{NULL})
+ at deftypefnx {C function only} @code{void} mgl_set_event_func (@code{HMGL} gr, @code{void (*}func at code{)(void *)}, @code{void *}par)
+Set callback function which will be called to process events of GUI library.
+ at end deftypefn
+
+ at end ifclear
+
+ at c ==================================================================
+ at external{}
+ at node Axis settings, Subplots and rotation, Graphics setup, MathGL core
+ at section Axis settings
+ at nav{}
+
+These large set of variables and functions control how the axis and ticks will be drawn. Note that there is 3-step transformation of data coordinates are performed. Firstly, coordinates are projected if @code{Cut=true} (see @ref{Cutting}), after it transformation formulas are applied, and finally the data was normalized in bounding box. Note, that MathGL will produce warning if axis range and transformation formulas are not compatible.
+
+ at menu
+* Ranges (bounding box)::
+* Curved coordinates::
+* Ticks::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Ranges (bounding box), Curved coordinates, , Axis settings
+ at subsection Ranges (bounding box)
+ at nav{}
+ at cindex CRange
+ at cindex XRange
+ at cindex YRange
+ at cindex ZRange
+ at cindex Ranges
+ at cindex Origin
+ at ifclear UDAV
+ at cindex SetRange
+ at cindex SetRanges
+ at cindex SetOrigin
+ at end ifclear
+
+ at anchor{xrange}
+ at anchor{yrange}
+ at anchor{zrange}
+ at anchor{crange}
+ at deftypefn {MGL command} {} xrange @code{v1 v2} [@code{add=off}]
+ at deftypefnx {MGL command} {} yrange @code{v1 v2} [@code{add=off}]
+ at deftypefnx {MGL command} {} zrange @code{v1 v2} [@code{add=off}]
+ at deftypefnx {MGL command} {} crange @code{v1 v2} [@code{add=off}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetRange (@code{char} dir, @code{mreal} v1, @code{mreal} v2)
+ at deftypefnx {Method on @code{mglGraph}} @code{void} AddRange (@code{char} dir, @code{mreal} v1, @code{mreal} v2)
+ at deftypefnx {C function} @code{void} mgl_set_range_val (@code{HMGL} gr, @code{char} dir, @code{mreal} v1, @code{mreal} v2)
+ at deftypefnx {C function} @code{void} mgl_add_range_val (@code{HMGL} gr, @code{char} dir, @code{mreal} v1, @code{mreal} v2)
+ at end ifclear
+Sets or adds the range for @samp{x}-, at samp{y}-, at samp{z}- coordinate or coloring (@samp{c}). If one of values is @code{NAN} then it is ignored. See also @ref{ranges}.
+ at end deftypefn
+
+
+ at deftypefn {MGL command} {} xrange dat [@code{add=off}]
+ at deftypefnx {MGL command} {} yrange dat [@code{add=off}]
+ at deftypefnx {MGL command} {} zrange dat [@code{add=off}]
+ at deftypefnx {MGL command} {} crange dat [@code{add=off}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetRange (@code{char} dir, @code{const mglDataA &}dat, @code{bool} add=@code{false})
+ at deftypefnx {C function} @code{void} mgl_set_range_dat (@code{HMGL} gr, @code{char} dir, @code{const HCDT} a, @code{int} add)
+ at end ifclear
+Sets the range for @samp{x}-, at samp{y}-, at samp{z}- coordinate or coloring (@samp{c}) as minimal and maximal values of data @var{dat}. Parameter @code{add=on} shows that the new range will be joined to existed one (not replace it).
+ at end deftypefn
+
+ at anchor{ranges}
+ at deftypefn {MGL command} {} ranges @code{x1 x2 y1 y2 [z1=0 z2=0]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetRanges (@code{mglPoint} p1, @code{mglPoint} p2)
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetRanges (@code{double} x1, @code{double} x2, @code{double} y1, @code{double} y2, @code{double} z1=@code{0}, @code{double} z2=@code{0})
+ at deftypefnx {C function} @code{void} mgl_set_ranges (@code{HMGL} gr, @code{double} x1, @code{double} x2, @code{double} y1, @code{double} y2, @code{double} z1, @code{double} z2)
+ at end ifclear
+Sets the ranges of coordinates. If minimal and maximal values of the coordinate are the same then they are ignored. Also it sets the range for coloring (analogous to @code{crange z1 z2}). This is default color range for 2d plots. Initial ranges are [-1, 1].
+ at end deftypefn
+
+ at deftypefn {MGL command} {} ranges @code{xx yy [zz cc=zz]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetRanges (@code{const mglDataA &}xx, @code{const mglDataA &}yy)
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetRanges (@code{const mglDataA &}xx, @code{const mglDataA &}yy, @code{const mglDataA &}zz)
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetRanges (@code{const mglDataA &}xx, @code{const mglDataA &}yy, @code{const mglDataA &}zz, @code{const mglDataA &}cc)
+ at end ifclear
+Sets the ranges of @samp{x}-, at samp{y}-, at samp{z}-, at samp{c}-coordinates and coloring as minimal and maximal values of data @var{xx}, @var{yy}, @var{zz}, @var{cc} correspondingly.
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Method on @code{mglGraph}} @code{void} SetAutoRanges (@code{mglPoint} p1, @code{mglPoint} p2)
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetAutoRanges (@code{double} x1, @code{double} x2, @code{double} y1, @code{double} y2, @code{double} z1=@code{0}, @code{double} z2=@code{0}, @code{double} c1=@code{0}, @code{double} c2=@code{0})
+ at deftypefnx {C function} @code{void} mgl_set_auto_ranges (@code{HMGL} gr, @code{double} x1, @code{double} x2, @code{double} y1, @code{double} y2, @code{double} z1, @code{double} z2, @code{double} z1, @code{double} z2)
+Sets the ranges for automatic coordinates. If minimal and maximal values of the coordinate are the same then they are ignored.
+ at end deftypefn
+ at end ifclear
+
+ at anchor{origin}
+ at deftypefn {MGL command} {} origin @code{x0 y0 [z0=nan]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetOrigin (@code{mglPoint} p0)
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetOrigin (@code{mreal} x0, @code{mreal} y0, @code{mreal} z0=@code{NAN})
+ at deftypefnx {C function} @code{void} mgl_set_origin (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0)
+ at end ifclear
+Sets center of axis cross section. If one of values is NAN then MathGL try to select optimal axis position.
+ at end deftypefn
+
+ at anchor{zoomaxis}
+ at deftypefn {MGL command} {} zoomaxis @code{x1 x2}
+ at deftypefnx {MGL command} {} zoomaxis @code{x1 y1 x2 y2}
+ at deftypefnx {MGL command} {} zoomaxis @code{x1 y1 z1 x2 y2 z2}
+ at deftypefnx {MGL command} {} zoomaxis @code{x1 y1 z1 c1 x2 y2 z2 c2}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ZoomAxis (@code{mglPoint} p1, @code{mglPoint} p2)
+ at deftypefnx {C function} @code{void} mgl_zoom_axis (@code{HMGL} gr, @code{mreal} x1, @code{mreal} y1, @code{mreal} z1, @code{mreal} c1, @code{mreal} x2, @code{mreal} y2, @code{mreal} z2, @code{mreal} c2)
+ at end ifclear
+Additionally extend axis range for any settings made by @code{SetRange} or @code{SetRanges} functions according the formula @math{min += (max-min)*p1} and @math{max += (max-min)*p1} (or @math{min *= (max/min)^p1} and @math{max *= (max/min)^p1} for log-axis range when @math{inf>max/min>100} or @math{0<max/min<0.01}). Initial ranges are [0, 1]. Attention! this settings can not be overwritten by any other functions, including @code{DefaultPlotParam()}.
+ at end deftypefn
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Curved coordinates, Ticks, Ranges (bounding box), Axis settings
+ at subsection Curved coordinates
+ at nav{}
+ at cindex Axis
+ at ifclear UDAV
+ at cindex SetFunc
+ at cindex SetCoor
+ at cindex Ternary
+ at end ifclear
+
+ at deftypefn {MGL command} {} axis 'fx' 'fy' 'fz' ['fa'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetFunc (@code{const char *}EqX, @code{const char *}EqY, @code{const char *}EqZ=@code{""}, @code{const char *}EqA=@code{""})
+ at deftypefnx {C function} @code{void} mgl_set_func (@code{HMGL} gr, @code{const char *}EqX, @code{const char *}EqY, @code{const char *}EqZ, @code{const char *}EqA)
+ at end ifclear
+Sets transformation formulas for curvilinear coordinate. Each string should contain mathematical expression for real coordinate depending on internal coordinates @samp{x}, @samp{y}, @samp{z} and @samp{a} or @samp{c} for colorbar. For example, the cylindrical coordinates are introduced as @code{SetFunc("x*cos(y)", "x*sin(y)", "z");}. For removing of formulas the corresponding parameter should be empty or @code{NULL}. Using transformation formulas will slightly slowing the program. Paramet [...]
+ at end deftypefn
+
+ at deftypefn {MGL command} {} axis @code{how}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetCoor (@code{int} how)
+ at deftypefnx {C function} @code{void} mgl_set_coor (@code{HMGL} gr, @code{int} how)
+ at end ifclear
+Sets one of the predefined transformation formulas for curvilinear coordinate. Parameter @var{how} define the coordinates:
+ at table @code
+ at item mglCartesian=0
+Cartesian coordinates (no transformation, @{x,y,z@});
+ at item mglPolar=1
+Polar coordinates: @{x*cos(y), x*sin(y), z@};
+ at item mglSpherical=2
+Sperical coordinates: @{x*sin(y)*cos(z), x*sin(y)*sin(z), x*cos(y)@};
+ at item mglParabolic=3
+Parabolic coordinates: @{x*y, (x*x-y*y)/2, z@}
+ at item mglParaboloidal=4
+Paraboloidal coordinates: @{(x*x-y*y)*cos(z)/2, (x*x-y*y)*sin(z)/2, x*y@};
+ at item mglOblate=5
+Oblate coordinates: @{cosh(x)*cos(y)*cos(z), cosh(x)*cos(y)*sin(z), sinh(x)*sin(y)@};
+ at item mglProlate=6
+Prolate coordinates: @{sinh(x)*sin(y)*cos(z), sinh(x)*sin(y)*sin(z), cosh(x)*cos(y)@};
+ at item mglElliptic=7
+Elliptic coordinates: @{cosh(x)*cos(y), sinh(x)*sin(y), z@};
+ at item mglToroidal=8
+Toroidal coordinates: @{sinh(x)*cos(z)/(cosh(x)-cos(y)), sinh(x)*sin(z)/(cosh(x)-cos(y)), sin(y)/(cosh(x)-cos(y))@};
+ at item mglBispherical=9
+Bispherical coordinates: @{sin(y)*cos(z)/(cosh(x)-cos(y)), sin(y)*sin(z)/(cosh(x)-cos(y)), sinh(x)/(cosh(x)-cos(y))@};
+ at item mglBipolar=10
+Bipolar coordinates: @{sinh(x)/(cosh(x)-cos(y)), sin(y)/(cosh(x)-cos(y)), z@};
+ at item mglLogLog=11
+Log-log coordinates: @{lg(x), lg(y), lg(z)@};
+ at item mglLogX=12
+Log-x coordinates: @{lg(x), y, z@};
+ at item mglLogY=13
+Log-y coordinates: @{x, lg(y), z@}.
+ at end table
+ at end deftypefn
+
+ at anchor{ternary}
+ at deftypefn {MGL command} {} ternary @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Ternary (@code{int} tern)
+ at deftypefnx {C function} @code{void} mgl_set_ternary (@code{HMGL} gr, @code{int} tern)
+ at end ifclear
+The function sets to draws Ternary (@var{tern}=@code{1}), Quaternary (@var{tern}=@code{2}) plot or projections (@var{tern}=@code{4,5,6}).
+
+Ternary plot is special plot for 3 dependent coordinates (components) @var{a}, @var{b}, @var{c} so that @var{a}+ at var{b}+ at var{c}=1. MathGL uses only 2 independent coordinates @var{a}=x and @var{b}=y since it is enough to plot everything. At this third coordinate z act as another parameter to produce contour lines, surfaces and so on.
+
+Correspondingly, Quaternary plot is plot for 4 dependent coordinates @var{a}, @var{b}, @var{c} and @var{d} so that @var{a}+ at var{b}+ at var{c}+ at var{d}=1. MathGL uses only 3 independent coordinates @var{a}=x, @var{b}=y and @var{d}=z since it is enough to plot everything.
+
+Projections can be obtained by adding value @code{4} to @var{tern} argument. So, that @var{tern}=@code{4} will draw projections in Cartesian coordinates, @var{tern}=@code{5} will draw projections in Ternary coordinates, @var{tern}=@code{6} will draw projections in Quaternary coordinates. If you add @code{8} instead of @code{4} then all text labels will not be printed  on projections.
+
+Use @code{Ternary(0)} for returning to usual axis. @sref{Ternary axis} @sref{Axis projection}
+ at end deftypefn
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Ticks, , Curved coordinates, Axis settings
+ at subsection Ticks
+ at nav{}
+ at cindex AxisStl
+ at cindex TickLen
+ at cindex Adjust
+ at cindex XTick
+ at cindex YTick
+ at cindex ZTick
+ at cindex CTick
+ at ifclear UDAV
+ at cindex SetAxisStl
+ at cindex SetTickLen
+ at cindex SetTicks
+ at cindex SetTicksVal
+ at cindex SetTuneTicks
+ at cindex SetTickTime
+ at cindex SetTickTempl
+ at cindex SetTickRotate
+ at cindex SetTickSkip
+ at cindex SetOriginTick
+ at cindex AddTick
+ at end ifclear
+
+ at anchor{adjust}
+ at deftypefn {MGL command} {} adjust ['dir'='xyzc']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Adjust (@code{const char *}dir=@code{"xyzc"})
+ at deftypefnx {C function} @code{void} mgl_adjust_ticks (@code{HMGL} gr, @code{const char *}dir)
+ at end ifclear
+Set the ticks step, number of sub-ticks and initial ticks position to be the most human readable for the axis along direction(s) @var{dir}. Also set @code{SetTuneTicks(true)}. Usually you don't need to call this function except the case of returning to default settings.
+ at end deftypefn
+
+ at anchor{xtick}
+ at anchor{ytick}
+ at anchor{ztick}
+ at anchor{ctick}
+ at deftypefn {MGL command} {} xtick @code{val [sub=0 org=nan 'fact'='']}
+ at deftypefnx {MGL command} {} ytick @code{val [sub=0 org=nan 'fact'='']}
+ at deftypefnx {MGL command} {} ztick @code{val [sub=0 org=nan 'fact'='']}
+ at deftypefnx {MGL command} {} ctick @code{val [sub=0 org=nan 'fact'='']}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetTicks (@code{char} dir, @code{mreal} d=@code{0}, @code{int} ns=@code{0}, @code{mreal} org=@code{NAN}, @code{const char *}fact=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetTicks (@code{char} dir, @code{mreal} d, @code{int} ns, @code{mreal} org, @code{const wchar_t *}fact)
+ at deftypefnx {C function} @code{void} mgl_set_ticks (@code{HMGL} gr, @code{char} dir, @code{mreal} d, @code{int} ns, @code{mreal} org)
+ at deftypefnx {C function} @code{void} mgl_set_ticks_fact (@code{HMGL} gr, @code{char} dir, @code{mreal} d, @code{int} ns, @code{mreal} org, @code{const char *}fact)
+ at deftypefnx {C function} @code{void} mgl_set_ticks_factw (@code{HMGL} gr, @code{char} dir, @code{mreal} d, @code{int} ns, @code{mreal} org, @code{const wchar_t *}fact)
+ at end ifclear
+Set the ticks step @var{d}, number of sub-ticks @var{ns} (used for positive @var{d}) and initial ticks position @var{org} for the axis along direction @var{dir} (use 'c' for colorbar ticks). Variable @var{d} set step for axis ticks (if positive) or it's number on the axis range (if negative). Zero value set automatic ticks. If @var{org} value is NAN then axis origin is used. Parameter @var{fact} set text which will be printed after tick label (like "\pi" for @var{d}=M_PI).
+ at end deftypefn
+
+ at deftypefn {MGL command} {} xtick @code{val1} 'lbl1' [@code{val2} 'lbl2' ...]
+ at deftypefnx {MGL command} {} ytick @code{val1} 'lbl1' [@code{val2} 'lbl2' ...]
+ at deftypefnx {MGL command} {} ztick @code{val1} 'lbl1' [@code{val2} 'lbl2' ...]
+ at deftypefnx {MGL command} {} xtick vdat 'lbls' [@code{add=off}]
+ at deftypefnx {MGL command} {} ytick vdat 'lbls' [@code{add=off}]
+ at deftypefnx {MGL command} {} ztick vdat 'lbls' [@code{add=off}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetTicksVal (@code{char} dir, @code{const char *}lbl, @code{bool} add=@code{false})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetTicksVal (@code{char} dir, @code{const wchar_t *}lbl, @code{bool} add=@code{false})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetTicksVal (@code{char} dir, @code{const mglDataA &}val, @code{const char *}lbl, @code{bool} add=@code{false})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetTicksVal (@code{char} dir, @code{const mglDataA &}val, @code{const wchar_t *}lbl, @code{bool} add=@code{false})
+ at deftypefnx {C function} @code{void} mgl_set_ticks_str (@code{HMGL} gr, @code{char} dir, @code{const char *}lbl, @code{bool} add)
+ at deftypefnx {C function} @code{void} mgl_set_ticks_wcs (@code{HMGL} gr, @code{char} dir, @code{const wchar_t *}lbl, @code{bool} add)
+ at deftypefnx {C function} @code{void} mgl_set_ticks_val (@code{HMGL} gr, @code{char} dir, @code{HCDT} val, @code{const char *}lbl, @code{bool} add)
+ at deftypefnx {C function} @code{void} mgl_set_ticks_valw (@code{HMGL} gr, @code{char} dir, @code{HCDT} val, @code{const wchar_t *}lbl, @code{bool} add)
+ at end ifclear
+Set the manual positions @var{val} and its labels @var{lbl} for ticks along axis @var{dir}. If array @var{val} is absent then values equidistantly distributed in x-axis range are used. Labels are separated by @samp{\n} symbol. If only one value is specified in MGL command then the label will be @emph{add} to the current ones. Use @code{SetTicks()} to restore automatic ticks.
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Method on @code{mglGraph}} @code{void} AddTick (@code{char} dir, @code{double} val, @code{const char *}lbl)
+ at deftypefnx {Method on @code{mglGraph}} @code{void} AddTick (@code{char} dir, @code{double} val, @code{const wchar_t *}lbl)
+ at deftypefnx {C function} @code{void} mgl_add_tick (@code{HMGL} gr, @code{char} dir, @code{double} val, @code{const char *}lbl)
+ at deftypefnx {C function} @code{void} mgl_set_tickw (@code{HMGL} gr, @code{char} dir, @code{double} val, @code{const wchar_t *}lbl)
+The same as previous but add single tick label @var{lbl} at position @var{val} to the list of existed ones.
+ at end deftypefn
+ at end ifclear
+
+ at deftypefn {MGL command} {} xtick 'templ'
+ at deftypefnx {MGL command} {} ytick 'templ'
+ at deftypefnx {MGL command} {} ztick 'templ'
+ at deftypefnx {MGL command} {} ctick 'templ'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetTickTempl (@code{char} dir, @code{const char *}templ)
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetTickTempl (@code{char} dir, @code{const wchar_t *}templ)
+ at deftypefnx {C function} @code{void} mgl_set_tick_templ (@code{HMGL} gr, @code{const char *}templ)
+ at deftypefnx {C function} @code{void} mgl_set_tick_templw (@code{HMGL} gr, @code{const wchar_t *}templ)
+ at end ifclear
+Set template @var{templ} for x-,y-,z-axis ticks or colorbar ticks. It may contain TeX symbols also. If @var{templ}=@code{""} then default template is used (in simplest case it is @samp{%.2g}). If template start with @samp{&} symbol then @code{long} integer value will be passed instead of default type @code{double}. Setting on template switch off automatic ticks tuning.
+ at end deftypefn
+
+ at anchor{ticktime}
+ at deftypefn {MGL command} {} ticktime 'dir' [@code{dv=0} 'tmpl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetTicksTime (@code{char} dir, @code{mreal} val, @code{const char *}templ)
+ at deftypefnx {C function} @code{void} mgl_set_ticks_time (@code{HMGL} gr, @code{mreal} val, @code{const char *}templ)
+ at end ifclear
+Sets time labels with step @var{val} and template @var{templ} for x-,y-,z-axis ticks or colorbar ticks. It may contain TeX symbols also. The format of template @var{templ} is the same as described in @url{http://www.manpagez.com/man/3/strftime/}. Most common variants are @samp{%X} for national representation of time, @samp{%x} for national representation of date, @samp{%Y} for year with century. If @var{val}=0 and/or @var{templ}="" then automatic tick step and/or template will be selecte [...]
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {C function} @code{double} mgl_get_time (@code{const char*}str, @code{const char *}templ)
+Gets number of seconds from 1970 year to specified date/time @var{str}. The format of string is specified by @var{templ}, which is the same as described in @url{http://www.manpagez.com/man/3/strftime/}. Most common variants are @samp{%X} for national representation of time, @samp{%x} for national representation of date, @samp{%Y} for year with century. Note, that MS Visual Studio couldn't handle date before 1970.
+ at end deftypefn
+ at end ifclear
+
+ at anchor{tuneticks}
+ at deftypefn {MGL command} {} tuneticks @code{val} [@code{pos=1.15}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetTuneTicks (@code{int} tune, @code{mreal} pos=@code{1.15})
+ at deftypefnx {C function} @code{void} mgl_tune_ticks (@code{HMGL} gr, @code{int} tune, @code{mreal} pos)
+ at end ifclear
+Switch on/off ticks enhancing by factoring common multiplier (for small, like from 0.001 to 0.002, or large, like from 1000 to 2000, coordinate values -- enabled if @var{tune}&1 is nonzero) or common component (for narrow range, like from 0.999 to 1.000 -- enabled if @var{tune}&2 is nonzero). Also set the position @var{pos} of common multiplier/component on the axis: =0 at minimal axis value, =1 at maximal axis value. Default value is 1.15.
+ at end deftypefn
+
+ at anchor{tickshift}
+ at deftypefn {MGL command} {} tickshift @code{dx [dy=0 dz=0 dc=0]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetTickShift (@code{mglPoint} d)
+ at deftypefnx {C function} @code{void} mgl_set_tick_shift (@code{HMGL} gr, @code{mreal} dx, @code{mreal} dy, @code{mreal} dz, @code{mreal} dc)
+ at end ifclear
+Set value of additional shift for ticks labels.
+ at end deftypefn
+
+ at ifclear UDAV
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} SetTickRotate (@code{bool} val)
+ at deftypefnx {C function} @code{void} mgl_set_tick_rotate (@code{HMGL} gr, @code{bool} val)
+Enable/disable ticks rotation if there are too many ticks or ticks labels are too long.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} SetTickSkip (@code{bool} val)
+ at deftypefnx {C function} @code{void} mgl_set_tick_skip (@code{HMGL} gr, @code{bool} val)
+Enable/disable ticks skipping if there are too many ticks or ticks labels are too long.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} SetTimeUTC (@code{bool} val)
+ at c @deftypefnx {C function} @code{void} mgl_set_tick_skip (@code{HMGL} gr, @code{bool} val)
+Enable/disable using UTC time for ticks labels. In C/Fortran you can use @code{mgl_set_flag(gr,val, MGL_USE_GMTIME);}.
+ at end deftypefn
+
+ at end ifclear
+
+ at anchor{origintick}
+ at deftypefn {MGL command} {} origintick @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetOriginTick (@code{bool} val=@code{true})
+ at end ifclear
+Enable/disable drawing of ticks labels at axis origin. In C/Fortran you can use @code{mgl_set_flag(gr,val, MGL_NO_ORIGIN);}.
+ at end deftypefn
+
+ at anchor{ticklen}
+ at deftypefn {MGL command} {} ticklen @code{val} [@code{stt=1}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetTickLen (@code{mreal} val, @code{mreal} stt=@code{1})
+ at deftypefnx {C function} @code{void} mgl_set_tick_len (@code{HMGL} gr, @code{mreal} val, @code{mreal} stt)
+ at end ifclear
+The relative length of axis ticks. Default value is @code{0.1}. Parameter @var{stt}>0 set relative length of subticks which is in @code{sqrt(1+stt)} times smaller.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} axisstl 'stl' ['tck'='' 'sub'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetAxisStl (@code{const char *}stl=@code{"k"}, @code{const char *}tck=@code{0}, @code{const char *}sub=@code{0})
+ at deftypefnx {C function} @code{void} mgl_set_axis_stl (@code{HMGL} gr, @code{const char *}stl, @code{const char *}tck, @code{const char *}sub)
+ at end ifclear
+The line style of axis (@var{stl}), ticks (@var{tck}) and subticks (@var{sub}). If @var{stl} is empty then default style is used (@samp{k} or @samp{w} depending on transparency type). If @var{tck} or @var{sub} is empty then axis style is used (i.e. @var{stl}).
+ at end deftypefn
+
+ at c ##################################################################
+ at external{}
+ at node Subplots and rotation, Export picture, Axis settings, MathGL core
+ at section Subplots and rotation
+ at nav{}
+ at cindex Aspect
+ at cindex Rotate
+ at cindex RotateN
+ at cindex SubPlot
+ at cindex MultiPlot
+ at cindex StickPlot
+ at cindex ColumnPlot
+ at cindex InPlot
+ at cindex Title
+ at cindex Perspective
+ at cindex View
+ at cindex Push
+ at cindex Pop
+
+These functions control how and where further plotting will be placed. There is a certain calling order of these functions for the better plot appearance. First one should be @ref{subplot}, @ref{multiplot} or @ref{inplot} for specifying the place. Second one can be @ref{title} for adding title for the subplot. After it a @ref{rotate}, @ref{shear} and @ref{aspect}. And finally any other plotting functions may be called. Alternatively you can use @ref{columnplot}, @ref{gridplot}, @ref{stic [...]
+
+ at anchor{subplot}
+ at deftypefn {MGL command} {} subplot @code{nx ny m} ['stl'='<>_^' @code{dx=0 dy=0}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SubPlot (@code{int} nx, @code{int} ny, @code{int} m, @code{const char *}stl=@code{"<>_^"}, @code{mreal} dx=@code{0}, @code{mreal} dy=@code{0})
+ at deftypefnx {C function} @code{void} mgl_subplot (@code{HMGL} gr, @code{int} nx, @code{int} ny, @code{int} m, @code{const char *}stl)
+ at deftypefnx {C function} @code{void} mgl_subplot_d (@code{HMGL} gr, @code{int} nx, @code{int} ny, @code{int} m, @code{const char *}stl, @code{mreal} dx, @code{mreal} dy)
+ at end ifclear
+Puts further plotting in a @var{m}-th cell of @var{nx}*@var{ny} grid of the whole frame area. The position of the cell can be shifted from its default position by relative size @var{dx}, @var{dy}. This function set off any aspects or rotations. So it should be used first for creating the subplot. Extra space will be reserved for axis/colorbar if @var{stl} contain:
+ at itemize @bullet
+ at item
+ at samp{L} or @samp{<} -- at left side,
+ at item
+ at samp{R} or @samp{>} -- at right side,
+ at item
+ at samp{A} or @samp{^} -- at top side,
+ at item
+ at samp{U} or @samp{_} -- at bottom side,
+ at item
+ at samp{#} -- reserve none space (use whole region for axis range) -- axis and tick labels will be invisible by default.
+ at end itemize
+From the aesthetical point of view it is not recommended to use this function with different matrices in the same frame. Note, colorbar can be invisible (be out of image borders) if you set empty style @samp{}.
+ at end deftypefn
+
+ at anchor{multiplot}
+ at deftypefn {MGL command} {} multiplot @code{nx ny m dx dy} ['style'='<>_^' sx sy]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} MultiPlot (@code{int} nx, @code{int} ny, @code{int} m, @code{int} dx, @code{int} dy, @code{const char *}stl=@code{"<>_^"})
+ at deftypefnx {C function} @code{void} mgl_multiplot (@code{HMGL} gr, @code{int} nx, @code{int} ny, @code{int} m, @code{int} dx, @code{int} dy, @code{const char *}stl)
+ at end ifclear
+Puts further plotting in a rectangle of @var{dx}*@var{dy} cells starting from @var{m}-th cell of @var{nx}*@var{ny} grid of the whole frame area. The position of the rectangular area can be shifted from its default position by relative size @var{sx}, @var{sy}. This function set off any aspects or rotations.  So it should be used first for creating subplot. Extra space will be reserved for axis/colorbar if @var{stl} contain:
+ at itemize @bullet
+ at item
+ at samp{L} or @samp{<} -- at left side,
+ at item
+ at samp{R} or @samp{>} -- at right side,
+ at item
+ at samp{A} or @samp{^} -- at top side,
+ at item
+ at samp{U} or @samp{_} -- at bottom side.
+ at samp{#} -- reserve none space (use whole region for axis range) -- axis and tick labels will be invisible by default.
+ at end itemize
+ at end deftypefn
+
+ at anchor{inplot}
+ at deftypefn {MGL command} {} inplot @code{x1 x2 y1 y2 [rel=on]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} InPlot (@code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2, @code{bool} rel=@code{true})
+ at deftypefnx {C function} @code{void} mgl_inplot (@code{HMGL} gr, @code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2)
+ at deftypefnx {C function} @code{void} mgl_relplot (@code{HMGL} gr, @code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2)
+ at end ifclear
+Puts further plotting in some region of the whole frame surface. This function allows one to create a plot in arbitrary place of the screen. The position is defined by rectangular coordinates [@var{x1}, @var{x2}]*[@var{y1}, @var{y2}]. The coordinates @var{x1}, @var{x2}, @var{y1}, @var{y2} are normalized to interval [0, 1]. If parameter @var{rel}=@code{true} then the relative position to current @ref{subplot} (or @ref{inplot} with @var{rel}=@code{false}) is used. This function set off any [...]
+ at end deftypefn
+
+ at anchor{columnplot}
+ at deftypefn {MGL command} {} columnplot @code{num ind [d=0]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ColumnPlot (@code{int} num, @code{int} ind, @code{mreal} d=@code{0})
+ at deftypefnx {C function} @code{void} mgl_columnplot (@code{HMGL} gr, @code{int} num, @code{int} ind)
+ at deftypefnx {C function} @code{void} mgl_columnplot_d (@code{HMGL} gr, @code{int} num, @code{int} ind, @code{mreal} d)
+ at end ifclear
+Puts further plotting in @var{ind}-th cell of column with @var{num} cells. The position is relative to previous @ref{subplot} (or @ref{inplot} with @var{rel}=@code{false}). Parameter @var{d} set extra gap between cells.
+ at end deftypefn
+
+ at anchor{gridplot}
+ at deftypefn {MGL command} {} gridplot @code{nx ny ind [d=0]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} GridPlot (@code{int} nx, @code{int} ny, @code{int} ind, @code{mreal} d=@code{0})
+ at deftypefnx {C function} @code{void} mgl_gridplot (@code{HMGL} gr, @code{int} nx, @code{int} ny, @code{int} ind)
+ at deftypefnx {C function} @code{void} mgl_gridplot_d (@code{HMGL} gr, @code{int} nx, @code{int} ny, @code{int} ind, @code{mreal} d)
+ at end ifclear
+Puts further plotting in @var{ind}-th cell of @var{nx}*@var{ny} grid. The position is relative to previous @ref{subplot} (or @ref{inplot} with @var{rel}=@code{false}). Parameter @var{d} set extra gap between cells.
+ at end deftypefn
+
+ at anchor{stickplot}
+ at deftypefn {MGL command} {} stickplot @code{num ind tet phi}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} StickPlot (@code{int} num, @code{int} ind, @code{mreal} tet, @code{mreal} phi)
+ at deftypefnx {C function} @code{void} mgl_stickplot (@code{HMGL} gr, @code{int} num, @code{int} ind, @code{mreal} tet, @code{mreal} phi)
+ at end ifclear
+Puts further plotting in @var{ind}-th cell of stick with @var{num} cells. At this, stick is rotated on angles @var{tet}, @var{phi}. The position is relative to previous @ref{subplot} (or @ref{inplot} with @var{rel}=@code{false}).
+ at end deftypefn
+
+ at anchor{shearplot}
+ at deftypefn {MGL command} {} shearplot @code{num ind sx sy [xd yd]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ShearPlot (@code{int} num, @code{int} ind, @code{mreal} sx, @code{mreal} sy, @code{mreal} xd=@code{1}, @code{mreal} yd=@code{0})
+ at deftypefnx {C function} @code{void} mgl_shearplot (@code{HMGL} gr, @code{int} num, @code{int} ind, @code{mreal} sx, @code{mreal} sy, @code{mreal} xd, @code{mreal} yd)
+ at end ifclear
+Puts further plotting in @var{ind}-th cell of stick with @var{num} cells. At this, cell is sheared on values @var{sx}, @var{sy}. Stick direction is specified be @var{xd} and @var{yd}. The position is relative to previous @ref{subplot} (or @ref{inplot} with @var{rel}=@code{false}).
+ at end deftypefn
+
+
+ at anchor{title}
+ at deftypefn {MGL command} {} title 'title' ['stl'='' @code{size=-2}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Title (@code{const char *}txt, @code{const char *}stl=@code{""}, @code{mreal} size=@code{-2})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Title (@code{const wchar_t *}txt, @code{const char *}stl=@code{""}, @code{mreal} size=@code{-2})
+ at deftypefnx {C function} @code{void} mgl_title (@code{HMGL} gr, @code{const char *}txt, @code{const char *}stl, @code{mreal} size)
+ at deftypefnx {C function} @code{void} mgl_titlew (@code{HMGL} gr, @code{const wchar_t *}txt, @code{const char *}stl, @code{mreal} size)
+ at end ifclear
+Add text @var{title} for current subplot/inplot. Parameter @var{stl} can contain:
+ at itemize @bullet
+ at item
+font style (see, @ref{Font styles});
+ at item
+ at samp{#} for box around the title.
+ at end itemize
+Parameter @var{size} set font size. This function set off any aspects or rotations. So it should be used just after creating subplot.
+ at end deftypefn
+
+ at anchor{rotate}
+ at deftypefn {MGL command} {} rotate @code{tetx tetz [tety=0]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Rotate (@code{mreal} TetX, @code{mreal} TetZ, @code{mreal} TetY=@code{0})
+ at deftypefnx {C function} @code{void} mgl_rotate (@code{HMGL} gr, @code{mreal} TetX, @code{mreal} TetZ, @code{mreal} TetY)
+ at end ifclear
+Rotates a further plotting relative to each axis @{x, z, y@} consecutively on angles @var{TetX}, @var{TetZ}, @var{TetY}.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} rotate @code{tet x y z}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} RotateN (@code{mreal} Tet, @code{mreal} x, @code{mreal} y, @code{mreal} z)
+ at deftypefnx {C function} @code{void} mgl_rotate_vector (@code{HMGL} gr, @code{mreal Tet}, @code{mreal x}, @code{mreal y}, @code{mreal z})
+ at end ifclear
+Rotates a further plotting around vector @{@var{x}, @var{y}, @var{z}@} on angle @var{Tet}.
+ at end deftypefn
+
+ at anchor{shear}
+ at deftypefn {MGL command} {} shear @code{sx sy}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Shear (@code{mreal} sx, @code{mreal} sy)
+ at deftypefnx {C function} @code{void} mgl_shear (@code{HMGL} gr, @code{mreal} sx, @code{mreal} sy)
+ at end ifclear
+Shears a further plotting on values @var{sx}, @var{sy}.
+ at end deftypefn
+
+ at anchor{aspect}
+ at deftypefn {MGL command} {} aspect @code{ax ay [az=1]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Aspect (@code{mreal} Ax, @code{mreal} Ay, @code{mreal} Az=@code{1})
+ at deftypefnx {C function} @code{void} mgl_aspect (@code{HMGL} gr, @code{mreal} Ax, @code{mreal} Ay, @code{mreal} Az)
+ at end ifclear
+Defines aspect ratio for the plot. The viewable axes will be related one to another as the ratio @var{Ax:Ay:Az}. For the best effect it should be used after @ref{rotate} function. If @var{Ax} is @code{NAN} then function try to select optimal aspect ratio to keep equal ranges for x-y axis. At this, @var{Ay} will specify proportionality factor, or set to use automatic one if @var{Ay}=@code{NAN}.
+ at end deftypefn
+
+ at ifclear UDAV
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} Push ()
+ at deftypefnx {C function} @code{void} mgl_mat_push (@code{HMGL} gr)
+Push transformation matrix into stack. Later you can restore its current state by Pop() function.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} Pop ()
+ at deftypefnx {C function} @code{void} mgl_mat_pop (@code{HMGL} gr)
+Pop (restore last 'pushed') transformation matrix into stack.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} SetPlotFactor (@code{mreal} val)
+ at deftypefnx {C function} @code{void} mgl_set_plotfactor (@code{HMGL} gr, @code{mreal} val)
+Sets the factor of plot size. It is not recommended to set it lower then 1.5. This is some analogue of function Zoom() but applied not to overall image but for each InPlot. Use negative value or zero to enable automatic selection.
+ at end deftypefn
+
+ at end ifclear
+
+There are 3 functions @code{View()}, @code{Zoom()} and @code{Perspective()} which transform whole image. I.e. they act as secondary transformation matrix. They were introduced for rotating/zooming the whole plot by mouse. It is not recommended to call them for picture drawing.
+
+ at anchor{perspective}
+ at deftypefn {MGL command} {} perspective @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Perspective (@code{mreal} a)
+ at deftypefnx {C function} @code{void} mgl_perspective (@code{HMGL} gr, @code{mreal} a)
+ at end ifclear
+Add (switch on) the perspective to plot. The parameter @math{a = Depth/(Depth+dz) \in [0,1)}. By default (@code{a=0}) the perspective is off.
+ at end deftypefn
+
+ at anchor{view}
+ at deftypefn {MGL command} {} view @code{tetx tetz [tety=0]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} View (@code{mreal} TetX, @code{mreal} TetZ, @code{mreal} TetY=@code{0})
+ at deftypefnx {C function} @code{void} mgl_view (@code{HMGL} gr, @code{mreal} TetX, @code{mreal} TetZ, @code{mreal} TetY)
+ at end ifclear
+Rotates a further plotting relative to each axis @{x, z, y@} consecutively on angles @var{TetX}, @var{TetZ}, @var{TetY}. Rotation is done independently on @ref{rotate}. Attention! this settings can not be overwritten by @code{DefaultPlotParam()}. Use @code{Zoom(0,0,1,1)} to return default view.
+ at end deftypefn
+
+ at anchor{zoom}
+ at deftypefn {MGL command} {} zoom @code{x1 y1 x2 y2}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph} (C++, Python)} @code{void} Zoom (@code{mreal} x1, @code{mreal} y1, @code{mreal} x2, @code{mreal} y2)
+ at deftypefnx {C function} @code{void} mgl_set_zoom (@code{HMGL} gr, @code{mreal} x1, @code{mreal} y1, @code{mreal} x2, @code{mreal} y2)
+ at end ifclear
+The function changes the scale of graphics that correspond to zoom in/out of the picture. After function call the current plot will be cleared and further the picture will contain plotting from its part [x1,x2]*[y1,y2]. Here picture coordinates @var{x1}, @var{x2}, @var{y1}, @var{y2} changes from 0 to 1. Attention! this settings can not be overwritten by any other functions, including @code{DefaultPlotParam()}. Use @code{Zoom(0,0,1,1)} to return default view.
+ at end deftypefn
+
+ at c ##################################################################
+ at external{}
+ at node Export picture, Background, Subplots and rotation, MathGL core
+ at section Export picture
+ at nav{}
+ at cindex SetSize
+
+Functions in this group save or give access to produced picture. So, usually they should be called after plotting is done.
+
+ at anchor{setsize}
+ at deftypefn {MGL command} {} setsize @code{w h}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetSize (@code{int} width, @code{int} height, @code{bool} clear=@code{true})
+ at deftypefnx {C function} @code{void} mgl_set_size (@code{HMGL} gr, @code{int} width, @code{int} height)
+ at deftypefnx {C function} @code{void} mgl_scale_size (@code{HMGL} gr, @code{int} width, @code{int} height)
+ at end ifclear
+Sets size of picture in pixels. This function @strong{should be} called before any other plotting because it completely remove picture contents if @var{clear}=@code{true}. Function just clear pixels and scale all primitives if @var{clear}=@code{false}.
+ at end deftypefn
+
+ at anchor{setsizescl}
+ at deftypefn {MGL command} {} setsizescl @code{factor}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetSizeScl (@code{double} factor)
+ at deftypefnx {C function} @code{void} mgl_set_size_scl (@code{HMGL} gr, @code{double} factor)
+ at end ifclear
+Set factor for width and height in all further calls of @ref{setsize}.
+ at end deftypefn
+
+ at anchor{quality}
+ at deftypefn {MGL command} {} quality [@code{val}=2]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetQuality (@code{int} val=@code{MGL_DRAW_NORM})
+ at deftypefnx {C function} @code{void} mgl_set_quality (@code{HMGL} gr, @code{int} val)
+ at end ifclear
+Sets quality of the plot depending on value @var{val}: @code{MGL_DRAW_WIRE=0} -- no face drawing (fastest), @code{MGL_DRAW_FAST=1} -- no color interpolation (fast), @code{MGL_DRAW_NORM=2} -- high quality (normal), @code{MGL_DRAW_HIGH=3} -- high quality with 3d primitives (arrows and marks); @code{MGL_DRAW_LMEM=0x4} -- direct bitmap drawing (low memory usage); @code{MGL_DRAW_DOTS=0x8} -- for dots drawing instead of primitives (extremely fast).
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Method on @code{mglGraph}} @code{int} GetQuality ()
+ at deftypefnx {C function} @code{int} mgl_get_quality (@code{HMGL} gr)
+Gets quality of the plot: @code{MGL_DRAW_WIRE=0} -- no face drawing (fastest), @code{MGL_DRAW_FAST=1} -- no color interpolation (fast), @code{MGL_DRAW_NORM=2} -- high quality (normal), @code{MGL_DRAW_HIGH=3} -- high quality with 3d primitives (arrows and marks); @code{MGL_DRAW_LMEM=0x4} -- direct bitmap drawing (low memory usage); @code{MGL_DRAW_DOTS=0x8} -- for dots drawing instead of primitives (extremely fast).
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} StartGroup (const char *name)
+ at deftypefnx {C function} @code{void} mgl_start_group (@code{HMGL} gr, @code{const char *}name)
+Starts group definition. Groups contain objects and other groups, they are used to select a part of a model to zoom to or to make invisible or to make semitransparent and so on.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} EndGroup ()
+ at deftypefnx {C function} @code{void} mgl_end_group (@code{HMGL} gr)
+Ends group definition.
+ at end deftypefn
+ at end ifclear
+
+ at menu
+* Export to file::
+* Frames/Animation::
+* Bitmap in memory::
+* Parallelization::
+ at end menu
+
+ at c ==================================================================
+ at external{}
+ at node Export to file, Frames/Animation, , Export picture
+ at subsection Export to file
+ at nav{}
+ at cindex Write
+ at ifclear UDAV
+ at cindex WriteFrame
+ at cindex WritePNG
+ at cindex WriteGIF
+ at c @cindex WriteIDTF
+ at cindex WriteSVG
+ at cindex WriteBMP
+ at cindex WriteEPS
+ at cindex WriteBPS
+ at cindex WriteTGA
+ at cindex WriteTEX
+ at cindex WritePRC
+ at cindex WriteOBJ
+ at cindex WriteWGL
+ at cindex WriteJPEG
+ at cindex ShowImage
+ at end ifclear
+
+These functions export current view to a graphic file. The filename @var{fname} should have appropriate extension. Parameter @var{descr} gives the short description of the picture. Just now the transparency is supported in PNG, SVG, OBJ and PRC files.
+
+ at anchor{write}
+ at deftypefn {MGL command} {} write ['fname'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} WriteFrame (@code{const char *}fname=@code{""}, @code{const char *}descr=@code{""})
+ at deftypefnx {C function} @code{void} mgl_write_frame (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+ at end ifclear
+Exports current frame to a file @var{fname} which type is determined by the extension. Parameter @var{descr} adds description to file (can be @code{""}). If @var{fname}=@code{""} then the file @samp{frame####.jpg} is used, where @samp{####} is current frame id and name @samp{frame} is defined by @ref{plotid} class property.
+ at end deftypefn
+
+ at anchor{bbox}
+ at deftypefn {MGL command} {} bbox x1 y1 [x2=@code{-1} y2=@code{-1}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetBBox (@code{int} x1=@code{0}, @code{int} y1=@code{0}, @code{int} x2=@code{-1}, @code{int} y2=@code{-1})
+ at deftypefnx {C function} @code{void} mgl_set_bbox (@code{HMGL} gr, @code{int} x1, @code{int} y1, @code{int} x2, @code{int} y2)
+ at end ifclear
+Set boundary box for export graphics into 2D file formats. If @var{x2}<0 (@var{y2}<0) then original image width (height) will be used. If @var{x1}<0 or @var{y1}<0 or @var{x1}>=@var{x2}|Width or @var{y1}>=@var{y2}|Height then cropping will be disabled.
+ at end deftypefn
+
+
+ at ifclear UDAV
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} WritePNG (@code{const char *}fname, @code{const char *}descr=@code{""}, @code{int} compr=@code{""}, @code{bool} alpha=@code{true})
+ at deftypefnx {C function} @code{void} mgl_write_png (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+ at deftypefnx {C function} @code{void} mgl_write_png_solid (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Exports current frame to PNG file. Parameter @var{fname} specifies the file name, @var{descr} adds description to file, @var{alpha} gives the transparency type. By default there are no description added and semitransparent image used. This function does nothing if HAVE_PNG isn't defined during compilation of MathGL library.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} WriteJPEG (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {C function} @code{void} mgl_write_jpg (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Exports current frame to JPEG file. Parameter @var{fname} specifies the file name, @var{descr} adds description to file. By default there is no description added. This function does nothing if HAVE_JPEG isn't defined during compilation of MathGL library.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} WriteGIF (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {C function} @code{void} mgl_write_gif (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Exports current frame to GIF file. Parameter @var{fname} specifies the file name, @var{descr} adds description to file. By default there is no description added. This function does nothing if HAVE_GIF isn't defined during compilation of MathGL library.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} WriteBMP (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {C function} @code{void} mgl_write_bmp (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Exports current frame to BMP file. Parameter @var{fname} specifies the file name, @var{descr} adds description to file. There is no compression used.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} WriteTGA (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {C function} @code{void} mgl_write_tga (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Exports current frame to TGA file. Parameter @var{fname} specifies the file name, @var{descr} adds description to file. There is no compression used.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} WriteEPS (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {C function} @code{void} mgl_write_eps (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Exports current frame to EPS file using vector representation. So it is not recommended for the export of large data plot. It is better to use bitmap format (for example PNG or JPEG). However, program has no internal limitations for size of output file. Parameter @var{fname} specifies the file name, @var{descr} adds description to file. By default there is no description added. If file name is terminated by @samp{z} (for example, @samp{fname.eps.gz}) then file will be compressed in gzip  [...]
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} WriteBPS (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {C function} @code{void} mgl_write_eps (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Exports current frame to EPS file using bitmap representation. Parameter @var{fname} specifies the file name, @var{descr} adds description to file. By default there is no description added. If file name is terminated by @samp{z} (for example, @samp{fname.eps.gz}) then file will be compressed in gzip format.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} WriteSVG (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {C function} @code{void} mgl_write_svg (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Exports current frame to SVG (Scalable Vector Graphics) file using vector representation. In difference of EPS format, SVG format support transparency that allows to correctly draw semitransparent plot (like @ref{surfa}, @ref{surf3a} or @ref{cloud}). Note, the output file may be too large for graphic of large data array (especially for surfaces). It is better to use bitmap format (for example PNG or JPEG). However, program has no internal limitations for size of output file. Parameter @v [...]
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} WriteTEX (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {C function} @code{void} mgl_write_tex (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Exports current frame to LaTeX (package Tikz/PGF) file using vector representation. Note, the output file may be too large for graphic of large data array (especially for surfaces). It is better to use bitmap format (for example PNG or JPEG). However, program has no internal limitations for size of output file. Parameter @var{fname} specifies the file name, @var{descr} adds description to file (default is file name). Note, there is no text scaling now (for example, in subplots), what may [...]
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} WritePRC (@code{const char *}fname, @code{const char *}descr=@code{""}, @code{bool} make_pdf=@code{true})
+ at deftypefnx {C function} @code{void} mgl_write_prc (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr, @code{int} make_pdf)
+Exports current frame to PRC file using vector representation (see @url{http://en.wikipedia.org/wiki/PRC_%28file_format%29}). Note, the output file may be too large for graphic of large data array (especially for surfaces). It is better to use bitmap format (for example PNG or JPEG). However, program has no internal limitations for size of output file. Parameter @var{fname} specifies the file name, @var{descr} adds description to file (default is file name). If parameter @var{make_pdf}=@ [...]
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} WriteOBJ (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {C function} @code{void} mgl_write_obj (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Exports current frame to OBJ/MTL file using vector representation (see @url{http://en.wikipedia.org/wiki/Wavefront_.obj_file, OBJ format} for details). Note, the output file may be too large for graphic of large data array (especially for surfaces). It is better to use bitmap format (for example PNG or JPEG). However, program has no internal limitations for size of output file. Parameter @var{fname} specifies the file name, @var{descr} adds description to file (default is file name).
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} WriteXYZ (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {C function} @code{void} mgl_write_xyz (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Exports current frame to XYZ/XYZL/XYZF files using vector representation (see @url{http://people.sc.fsu.edu/~jburkardt/data/xyz/xyz.html, XYZ format} for details). Note, the output file may be too large for graphic of large data array (especially for surfaces). It is better to use bitmap format (for example PNG or JPEG). However, program has no internal limitations for size of output file. Parameter @var{fname} specifies the file name, @var{descr} adds description to file (default is fil [...]
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} WriteSTL (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {C function} @code{void} mgl_write_stl (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Exports current frame to STL file using vector representation (see @url{http://en.wikipedia.org/wiki/STL_(file_format), STL format} for details). Note, the output file may be too large for graphic of large data array (especially for surfaces). It is better to use bitmap format (for example PNG or JPEG). However, program has no internal limitations for size of output file. Parameter @var{fname} specifies the file name, @var{descr} adds description to file (default is file name.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} WriteOFF (@code{const char *}fname, @code{const char *}descr=@code{""}, @code{bool} colored=@code{false})
+ at deftypefnx {C function} @code{void} mgl_write_off (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr, @code{bool} colored)
+Exports current frame to OFF file using vector representation (see @url{http://people.sc.fsu.edu/~jburkardt/data/off/off.html, OFF format} for details). Note, the output file may be too large for graphic of large data array (especially for surfaces). It is better to use bitmap format (for example PNG or JPEG). However, program has no internal limitations for size of output file. Parameter @var{fname} specifies the file name, @var{descr} adds description to file (default is file name).
+ at end deftypefn
+
+ at c @deftypefn {Method on @code{mglGraph}} @code{void} WriteX3D (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at c @deftypefnx {C function} @code{void} mgl_write_x3d (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+ at c Exports current frame to X3D file using vector representation (see @url{http://en.wikipedia.org/wiki/X3d, X3D format} for details). Note, the output file may be too large for graphic of large data array (especially for surfaces). It is better to use bitmap format (for example PNG or JPEG). However, program has no internal limitations for size of output file. Parameter @var{fname} specifies the file name, @var{descr} adds description to file (default is file name).
+ at c @end deftypefn
+
+
+ at c @deftypefn {Method on @code{mglGraph}} @code{void} WriteIDTF (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at c @deftypefnx {C function} @code{void} mgl_write_idtf (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+ at c Exports current frame to IDTF file. Later this file can be converted to U3D format. The vector representation is used. So, the output file may be too large for graphic of large data array (especially for surfaces). However, program has no internal limitations for size of output file. Parameter @var{fname} specifies the file name, @var{descr} adds description to file (default is file name).
+ at c @end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} ShowImage (@code{const char *}viewer, @code{bool} nowait=@code{false})
+ at deftypefnx {C function} @code{void} mgl_show_image (@code{const char *}viewer, @code{int} nowait)
+Displays the current picture using external program @var{viewer} for viewing. The function save the picture to temporary file and call @var{viewer} to display it. If @var{nowait}=@code{true} then the function return immediately (it will not wait while window will be closed).
+ at end deftypefn
+
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} WriteJSON (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {C function} @code{void} mgl_write_json (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Exports current frame to textual file using @ref{JSON format}. Later this file can be used for faster loading and viewing by JavaScript script. Parameter @var{fname} specifies the file name, @var{descr} adds description to file.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} ExportMGLD (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {C function} @code{void} mgl_export_mgld (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Exports points and primitives in file using @ref{MGLD format}. Later this file can be used for faster loading and viewing by @code{mglview} utility. Parameter @var{fname} specifies the file name, @var{descr} adds description to file (default is file name).
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} ImportMGLD (@code{const char *}fname, @code{bool} add=@code{false})
+ at deftypefnx {C function} @code{void} mgl_import_mgld (@code{HMGL} gr, @code{const char *}fname, @code{int} add)
+Imports points and primitives in file using @ref{MGLD format}. Later this file can be used for faster loading and viewing by @code{mglview} utility. Parameter @var{fname} specifies the file name, @var{add} sets to append or replace primitives to existed ones.
+ at end deftypefn
+
+ at end ifclear
+
+
+ at c ##################################################################
+ at external{}
+ at node Frames/Animation, Bitmap in memory, Export to file, Export picture
+ at subsection Frames/Animation
+ at nav{}
+
+ at ifset UDAV
+There are no commands for making animation in MGL. However you can use features of @code{mglconv} and @code{mglview} utilities. For example, by busing special comments @samp{##a } or @samp{##c }.
+ at end ifset
+
+ at ifclear UDAV
+ at cindex NewFrame
+ at cindex EndFrame
+ at cindex GetNumFrame
+ at cindex ResetFrames
+ at cindex StartGIF
+ at cindex CloseGIF
+
+These functions provide ability to create several pictures simultaneously. For most of cases it is useless but for widget classes (see @ref{Widget classes}) they can provide a way to show animation. Also you can write several frames into animated GIF file.
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} NewFrame ()
+ at deftypefnx {C function} @code{void} mgl_new_frame (@code{HMGL} gr)
+Creates new frame. Function returns current frame id. This is not thread safe function in OpenGL mode! Use direct list creation in multi-threading drawing. The function @code{EndFrame()} @strong{must} be call after the finishing of the frame drawing for each call of this function.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} EndFrame ()
+ at deftypefnx {C function} @code{void} mgl_end_frame (@code{HMGL} gr)
+Finishes the frame drawing.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{int} GetNumFrame ()
+ at deftypefnx {C function} @code{int} mgl_get_num_frame (@code{HMGL} gr)
+Gets the number of created frames.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} SetFrame (@code{int} i)
+ at deftypefnx {C function} @code{void} mgl_set_frame (@code{HMGL} gr, @code{int} i)
+Finishes the frame drawing and sets drawing data to frame @var{i}, which should be in range [0, @code{GetNumFrame()}-1]. This function is similar to @code{EndFrame()} but don't add frame to the GIF image.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} GetFrame (@code{int} i)
+ at deftypefnx {C function} @code{void} mgl_get_frame (@code{HMGL} gr, @code{int} i)
+Replaces drawing data by one from frame @var{i}. Function work if @code{MGL_VECT_FRAME} is set on (by default).
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} ShowFrame (@code{int} i)
+ at deftypefnx {C function} @code{void} mgl_show_frame (@code{HMGL} gr, @code{int} i)
+Appends drawing data from frame @var{i} to current one. Function work if @code{MGL_VECT_FRAME} is set on (by default).
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} DelFrame (@code{int} i)
+ at deftypefnx {C function} @code{void} mgl_del_frame (@code{HMGL} gr, @code{int} i)
+Deletes drawing data for frame @var{i} and shift all later frame indexes. Function work if @code{MGL_VECT_FRAME} is set on (by default). Do nothing in OpenGL mode.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} ResetFrames ()
+ at deftypefnx {C function} @code{void} mgl_reset_frames (@code{HMGL} gr)
+Reset frames counter (start it from zero).
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} ClearFrame (@code{int} i)
+ at deftypefnx {C function} @code{void} mgl_clear_frame (@code{HMGL} gr, @code{int} i)
+Clear list of primitives for current drawing.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} StartGIF (@code{const char *}fname, @code{int} ms=@code{100})
+ at deftypefnx {C function} @code{void} mgl_start_gif (@code{HMGL} gr, @code{const char *}fname, @code{int} ms)
+Start writing frames into animated GIF file @var{fname}. Parameter @var{ms} set the delay between frames in milliseconds. You @strong{should not} change the picture size during writing the cinema. Use @code{CloseGIF()} to finalize writing. Note, that this function is disabled in OpenGL mode.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} CloseGIF ()
+ at deftypefnx {C function} @code{void} mgl_close_gif (@code{HMGL} gr)
+Finish writing animated GIF and close connected pointers.
+ at end deftypefn
+ at end ifclear
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Bitmap in memory, Parallelization, Frames/Animation, Export picture
+ at subsection Bitmap in memory
+ at nav{}
+
+ at ifclear UDAV
+These functions return the created picture (bitmap), its width and height. You may display it by yourself in any graphical library (see also, @ref{Widget classes}) or save in file (see also, @ref{Export to file}).
+
+ at deftypefn {Method on @code{mglGraph}} @code{const unsigned char *} GetRGB ()
+ at deftypefnx {Method on @code{mglGraph}} @code{void} GetRGB (@code{char *}buf, @code{int} size)
+ at deftypefnx {Method on @code{mglGraph}} @code{void} GetBGRN (@code{char *}buf, @code{int} size)
+ at deftypefnx {C function} @code{const unsigned char *} mgl_get_rgb (@code{HMGL} gr)
+Gets RGB bitmap of the current state of the image. Format of each element of bits is: @{red, green, blue@}. Number of elements is Width*Height. Position of element @{i,j@} is [3*i + 3*Width*j] (or is [4*i + 4*Width*j] for @code{GetBGRN()}). You have to provide the proper @var{size} of the buffer, @var{buf}, i.e. the code for Python should look like
+ at verbatim
+from mathgl import *
+gr = mglGraph();
+bits='\t';
+bits=bits.expandtabs(4*gr.GetWidth()*gr.GetHeight());
+gr.GetBGRN(bits, len(bits));
+ at end verbatim
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{const unsigned char *} GetRGBA ()
+ at deftypefnx {Method on @code{mglGraph}} @code{void} GetRGBA (@code{char *}buf, @code{int} size)
+ at deftypefnx {C function} @code{const unsigned char *} mgl_get_rgba (@code{HMGL} gr)
+Gets RGBA bitmap of the current state of the image. Format of each element of bits is: @{red, green, blue, alpha@}. Number of elements is Width*Height. Position of element @{i,j@} is [4*i + 4*Width*j].
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{int} GetWidth ()
+ at deftypefnx {Method on @code{mglGraph}} @code{int} GetHeight ()
+ at deftypefnx {C function} @code{int} mgl_get_width (@code{HMGL} gr)
+ at deftypefnx {C function} @code{int} mgl_get_height (@code{HMGL} gr)
+Gets width and height of the image.
+ at end deftypefn
+
+
+ at deftypefn {Method on @code{mglGraph}} @code{mglPoint} CalcXYZ (@code{int} xs, @code{int} ys)
+ at deftypefnx {C function} @code{void} mgl_calc_xyz (@code{HMGL} gr, @code{int} xs, @code{int} ys, @code{mreal *}x, @code{mreal *}y, @code{mreal *}z)
+Calculate 3D coordinate @{x,y,z@} for screen point @{xs,ys@}. At this moment it ignore perspective and transformation formulas (curvilinear coordinates). The calculation are done for the last used InPlot (see @ref{Subplots and rotation}).
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{mglPoint} CalcScr (@code{mglPoint} p)
+ at deftypefnx {C function} @code{void} mgl_calc_scr (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{int *}xs, @code{int *}ys)
+Calculate screen point @{xs,ys@} for 3D coordinate @{x,y,z@}. The calculation are done for the last used InPlot (see @ref{Subplots and rotation}).
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} SetObjId (@code{int} id)
+ at deftypefnx {C function} @code{void} mgl_set_obj_id (@code{HMGL} gr, @code{int} id)
+Set the numeric id for object or subplot/inplot.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{int} GetObjId (@code{int} xs, @code{int} ys)
+ at deftypefnx {C function} @code{int} mgl_get_obj_id (@code{HMGL} gr, @code{int} xs, @code{int} ys)
+Get the numeric id for most upper object at pixel @{xs, ys@} of the picture.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{int} GetSplId (@code{int} xs, @code{int} ys)
+ at deftypefnx {C function} @code{int} mgl_get_spl_id (@code{HMGL} gr, @code{int} xs, @code{int} ys)
+Get the numeric id for most subplot/inplot at pixel @{xs, ys@} of the picture.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{void} Highlight (@code{int} id)
+ at deftypefnx {C function} @code{void} mgl_highlight (@code{HMGL} gr, @code{int} id)
+Highlight the object with given @var{id}.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{long} IsActive (@code{int} xs, @code{int} ys, @code{int} d=@code{1})
+ at deftypefnx {C function} @code{long} mgl_is_active (@code{HMGL} gr, @code{int} xs, @code{int} ys, @code{int} d)
+Checks if point @{@var{xs}, @var{ys}@} is close to one of active point (i.e. mglBase::Act) with accuracy @var{d} and return its index or @code{-1} if not found. Active points are special points which characterize primitives (like edges and so on). This function for advanced users only.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{long} SetDrawReg (@code{int} nx=@code{1}, @code{int} ny=@code{1}, @code{int} m=@code{0})
+ at deftypefnx {C function} @code{long} mgl_set_draw_reg (@code{HMGL} gr, @code{int} nx, @code{int} ny, @code{int} m)
+Limits drawing region by rectangular area of @var{m}-th cell of matrix with sizes @var{nx}*@var{ny} (like in @ref{subplot}). This function can be used to update only small region of the image for purposes of higher speed. This function for advanced users only.
+ at end deftypefn
+
+
+ at end ifclear
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Parallelization, , Bitmap in memory, Export picture
+ at subsection Parallelization
+ at nav{}
+
+ at ifclear UDAV
+ at cindex Combine
+ at cindex MPI_Send
+ at cindex MPI_Recv
+
+Many of things MathGL do in parallel by default (if MathGL was built with pthread). However, there is function which set the number of threads to be used.
+
+ at deftypefn {C function} @code{int} mgl_set_num_thr (@code{int} n)
+Set the number of threads to be used by MathGL. If @var{n}<1 then the number of threads is set as maximal number of processors (cores). If @var{n}=1 then single thread will be used (this is default if pthread was disabled).
+ at end deftypefn
+
+Another option is combining bitmap image (taking into account Z-ordering) from different instances of  @code{mglGraph}. This method is most appropriate for computer clusters when the data size is so large that it exceed the memory of single computer node.
+
+ at deftypefn {Method on @code{mglGraph}} @code{int} Combine (@code{const mglGraph *}g)
+ at deftypefnx {C function} @code{int} mgl_combine_gr (@code{HMGL} gr, @code{HMGL} g)
+Combine drawing from instance @var{g} with @var{gr} (or with this) taking into account Z-ordering of pixels. The width and height of both instances must be the same.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{int} MPI_Send (@code{int} id)
+ at deftypefnx {C function} @code{int} mgl_mpi_send (@code{HMGL} gr, @code{int} id)
+Send graphical information from node @var{id} using MPI. The width and height in both nodes must be the same.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{int} MPI_Recv (@code{int} id)
+ at deftypefnx {C function} @code{int} mgl_mpi_send (@code{HMGL} gr, @code{int} id)
+Receive graphical information from node @var{id} using MPI. The width and height in both nodes must be the same.
+ at end deftypefn
+ at end ifclear
+
+
+ at c ##################################################################
+ at external{}
+ at node Background, Primitives, Export picture, MathGL core
+ at section Background
+ at nav{}
+ at cindex LoadBackground
+ at cindex Clf
+ at cindex Rasterize
+
+These functions change background image.
+
+ at anchor{clf}
+ at deftypefn {MGL command} {} clf ['col']
+ at deftypefnx {MGL command} {} clf r g b
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Clf ()
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Clf (@code{const char *} col)
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Clf (@code{char} col)
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Clf (@code{mreal} r, @code{mreal} g, @code{mreal} b)
+ at deftypefnx {C function} @code{void} mgl_clf (@code{HMGL} gr)
+ at deftypefnx {C function} @code{void} mgl_clf_str (@code{HMGL} gr, @code{const char *} col)
+ at deftypefnx {C function} @code{void} mgl_clf_chr (@code{HMGL} gr, @code{char} col)
+ at deftypefnx {C function} @code{void} mgl_clf_rgb (@code{HMGL} gr, @code{mreal} r, @code{mreal} g, @code{mreal} b)
+ at end ifclear
+Clear the picture and fill background by specified color.
+ at end deftypefn
+
+ at anchor{rasterize}
+ at deftypefn {MGL command} {} rasterize
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Rasterize ()
+ at deftypefnx {C function} @code{void} mgl_rasterize (@code{HMGL} gr)
+ at end ifclear
+Force drawing the plot and use it as background. After it, function clear the list of primitives, like @ref{clf}. This function is useful if you want save part of plot as bitmap one (for example, large surfaces, isosurfaces or vector fields) and keep some parts as vector one (like annotation, curves, axis and so on).
+ at end deftypefn
+
+ at anchor{background}
+ at deftypefn {MGL command} {} background 'fname' [@code{alpha=1}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} LoadBackground (@code{const char *} fname, @code{double} alpha=@code{1})
+ at deftypefnx {C function} @code{void} mgl_load_background (@code{HMGL} gr, @code{const char *} fname, @code{double} alpha)
+ at end ifclear
+Load PNG or JPEG file @var{fname} as background for the plot. Parameter @var{alpha} manually set transparency of the background.
+ at end deftypefn
+
+
+
+ at c ##################################################################
+ at external{}
+ at node Primitives, Text printing, Background, MathGL core
+ at section Primitives
+ at nav{}
+ at cindex Ball
+ at cindex Line
+ at cindex Curve
+ at cindex Glyph
+ at cindex Face
+ at cindex FaceX
+ at cindex FaceY
+ at cindex FaceZ
+ at cindex Cone
+ at cindex Drop
+ at cindex Sphere
+
+ at ifclear UDAV
+ at cindex Mark
+ at cindex Error
+ at end ifclear
+
+These functions draw some simple objects like line, point, sphere, drop, cone and so on. @sref{Using primitives}
+
+ at anchor{ball}
+ at deftypefn {MGL command} {} ball @code{x y} ['col'='r.']
+ at deftypefnx {MGL command} {} ball @code{x y z} ['col'='r.']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Ball (@code{mglPoint} p, @code{char} col=@code{'r'})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Mark (@code{mglPoint} p, @code{const char *}mark)
+ at deftypefnx {C function} @code{void} mgl_mark (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{const char *}mark)
+ at end ifclear
+Draws a mark (point @samp{.} by default) at position @var{p}=@{@var{x}, @var{y}, @var{z}@} with color @var{col}.
+ at end deftypefn
+
+ at anchor{errbox}
+ at deftypefn {MGL command} {} errbox @code{x y ex ey} ['stl'='']
+ at deftypefnx {MGL command} {} errbox @code{x y z ex ey ez} ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Error (@code{mglPoint} p, @code{mglPoint} e, @code{char} *stl=@code{""})
+ at deftypefnx {C function} @code{void} mgl_error_box (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{mreal} ex, @code{mreal} ey, @code{mreal} ez, @code{char *}stl)
+ at end ifclear
+Draws a 3d error box at position @var{p}=@{@var{x}, @var{y}, @var{z}@} with sizes @var{e}=@{@var{ex}, @var{ey}, @var{ez}@} and style @var{stl}. Use NAN for component of @var{e} to reduce number of drawn elements.
+ at end deftypefn
+
+ at anchor{line}
+ at deftypefn {MGL command} {} line @code{x1 y1 x2 y2} ['stl'='']
+ at deftypefnx {MGL command} {} line @code{x1 y1 z1 x2 y2 z2} ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Line (@code{mglPoint} p1, @code{mglPoint} p2, @code{char *}stl=@code{"B"}, @code{int} num=@code{2})
+ at deftypefnx {C function} @code{void} mgl_line (@code{HMGL} gr, @code{mreal} x1, @code{mreal} y1, @code{mreal} z1, @code{mreal} x2, @code{mreal} y2, @code{mreal} z2, @code{char *}stl, @code{int} num)
+ at end ifclear
+Draws a geodesic line (straight line in Cartesian coordinates) from point @var{p1} to @var{p2} using line style @var{stl}. Parameter @var{num} define the ``quality'' of the line. If @var{num}=@code{2} then the stright line will be drawn in all coordinate system (independently on transformation formulas (see @ref{Curved coordinates}). Contrary, for large values (for example, =@code{100}) the geodesic line will be drawn in corresponding coordinate system (straight line in Cartesian coordin [...]
+ at end deftypefn
+
+ at anchor{curve}
+ at deftypefn {MGL command} {} curve @code{x1 y1 dx1 dy1 x2 y2 dx2 dy2} ['stl'='']
+ at deftypefnx {MGL command} {} curve @code{x1 y1 z1 dx1 dy1 dz1 x2 y2 z2 dx2 dy2 dz2} ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Curve (@code{mglPoint} p1, @code{mglPoint} d1, @code{mglPoint} p2, @code{mglPoint} d2, @code{const char *}stl=@code{"B"}, @code{int} num=@code{100})
+ at deftypefnx {C function} @code{void} mgl_curve (@code{HMGL} gr, @code{mreal} x1, @code{mreal} y1, @code{mreal} z1, @code{mreal} dx1, @code{mreal} dy1, @code{mreal} dz1, @code{mreal} x2, @code{mreal} y2, @code{mreal} z2, @code{mreal} dx2, @code{mreal} dy2, @code{mreal} dz2, @code{const char *}stl, @code{int} num)
+ at end ifclear
+Draws Bezier-like curve from point @var{p1} to @var{p2} using line style @var{stl}. At this tangent is codirected with @var{d1}, @var{d2} and proportional to its amplitude. Parameter @var{num} define the ``quality'' of the curve. If @var{num}=@code{2} then the straight line will be drawn in all coordinate system (independently on transformation formulas, see @ref{Curved coordinates}). Contrary, for large values (for example, =@code{100}) the spline like Bezier curve will be drawn in corr [...]
+ at end deftypefn
+
+ at anchor{face}
+ at deftypefn {MGL command} {} face @code{x1 y1 x2 y2 x3 y3 x4 y4} ['stl'='']
+ at deftypefnx {MGL command} {} face @code{x1 y1 z1 x2 y2 z2 x3 y3 z3 x4 y4 z4} ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Face (@code{mglPoint} p1, @code{mglPoint} p2, @code{mglPoint} p3, @code{mglPoint} p4, @code{const char *}stl=@code{"w"})
+ at deftypefnx {C function} @code{void} mgl_face (@code{HMGL} gr, @code{mreal} x1, @code{mreal} y1, @code{mreal} z1, @code{mreal} x2, @code{mreal} y2, @code{mreal} z2, @code{mreal} x3, @code{mreal} y3, @code{mreal} z3, @code{mreal} x4, @code{mreal} y4, @code{mreal} z4, @code{const char *}stl)
+ at end ifclear
+Draws the solid quadrangle (face) with vertexes @var{p1}, @var{p2}, @var{p3}, @var{p4} and with color(s) @var{stl}. At this colors can be the same for all vertexes or different if all 4 colors are specified for each vertex. Face will be drawn even if it lies out of bounding box.
+ at end deftypefn
+
+ at anchor{rect}
+ at deftypefn {MGL command} {} rect @code{x1 y1 x2 y2} ['stl'='']
+ at deftypefnx {MGL command} {} rect @code{x1 y1 z1 x2 y2 z2} ['stl'='']
+Draws the solid rectangle (face) with vertexes @{@var{x1}, @var{y1}, @var{z1}@} and @{@var{x2}, @var{y2}, @var{z2}@} with color @var{stl}. At this colors can be the same for all vertexes or separately if all 4 colors are specified for each vertex. Face will be drawn even if it lies out of bounding box.
+ at end deftypefn
+
+ at anchor{facex}
+ at anchor{facey}
+ at anchor{facez}
+ at deftypefn {MGL command} {} facex @code{x0 y0 z0 wy wz} ['stl'='' @code{d1=0 d2=0}]
+ at deftypefnx {MGL command} {} facey @code{x0 y0 z0 wx wz} ['stl'='' @code{d1=0 d2=0}]
+ at deftypefnx {MGL command} {} facez @code{x0 y0 z0 wx wy} ['stl'='' @code{d1=0 d2=0}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} FaceX (@code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{mreal} wy, @code{mreal} wz, @code{const char *}stl=@code{"w"}, @code{mreal} d1=@code{0}, @code{mreal} d2=@code{0})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} FaceY (@code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{mreal} wx, @code{mreal} wz, @code{const char *}stl=@code{"w"}, @code{mreal} d1=@code{0}, @code{mreal} d2=@code{0})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} FaceZ (@code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{mreal} wx, @code{mreal} wy, @code{const char *}stl=@code{"w"}, @code{mreal} d1=@code{0}, @code{mreal} d2=@code{0})
+ at deftypefnx {C function} @code{void} mgl_facex (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{mreal} wy, @code{mreal} wz, @code{const char *}stl, @code{mreal} d1, @code{mreal} d2)
+ at deftypefnx {C function} @code{void} mgl_facey (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{mreal} wx, @code{mreal} wz, @code{const char *}stl, @code{mreal} d1, @code{mreal} d2)
+ at deftypefnx {C function} @code{void} mgl_facez (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{mreal} wx, @code{mreal} wy, @code{const char *}stl, @code{mreal} d1, @code{mreal} d2)
+ at end ifclear
+Draws the solid rectangle (face) perpendicular to [x,y,z]-axis correspondingly at position @{@var{x0}, @var{y0}, @var{z0}@} with color @var{stl} and with widths @var{wx}, @var{wy}, @var{wz} along corresponding directions. At this colors can be the same for all vertexes or separately if all 4 colors are specified for each vertex. Parameters @var{d1}!=0, @var{d2}!=0 set additional shift of the last vertex (i.e. to draw quadrangle). Face will be drawn even if it lies out of bounding box.
+ at end deftypefn
+
+ at anchor{sphere}
+ at deftypefn {MGL command} {} sphere @code{x0 y0 r} ['col'='r']
+ at deftypefnx {MGL command} {} sphere @code{x0 y0 z0 r} ['col'='r']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Sphere (@code{mglPoint} p, @code{mreal} r, @code{const char *}stl=@code{"r"})
+ at deftypefnx {C function} @code{void} mgl_sphere (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{mreal} r, @code{const char *}stl)
+ at end ifclear
+Draw the sphere with radius @var{r} and center at point @var{p}=@{@var{x0}, @var{y0}, @var{z0}@} and color @var{stl}.
+ at end deftypefn
+
+ at anchor{drop}
+ at deftypefn {MGL command} {} drop @code{x0 y0 dx dy r} ['col'='r' @code{sh=1 asp=1}]
+ at deftypefnx {MGL command} {} drop @code{x0 y0 z0 dx dy dz r} ['col'='r' @code{sh=1 asp=1}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Drop (@code{mglPoint} p, @code{mglPoint} d, @code{mreal} r, @code{const char *}col=@code{"r"}, @code{mreal} shift=@code{1}, @code{mreal} ap=@code{1})
+ at deftypefnx {C function} @code{void} mgl_drop (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{mreal} dx, @code{mreal} dy, @code{mreal} dz, @code{mreal} r, @code{const char *}col, @code{mreal} shift, @code{mreal} ap)
+ at end ifclear
+Draw the drop with radius @var{r} at point @var{p} elongated in direction @var{d} and with color @var{col}. Parameter @var{shift} set the degree of drop oblongness: @samp{0} is sphere, @samp{1} is maximally oblongness drop. Parameter @var{ap} set relative width of the drop (this is analogue of ``ellipticity'' for the sphere).
+ at end deftypefn
+
+ at anchor{cone}
+ at deftypefn {MGL command} {} cone @code{x1 y1 z1 x2 y2 z2 r1} [@code{r2=-1} 'stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Cone (@code{mglPoint} p1, @code{mglPoint} p2, @code{mreal} r1, @code{mreal} r2=@code{-1}, @code{const char *}stl=@code{"B"})
+ at deftypefnx {C function} @code{void} mgl_cone (@code{HMGL} gr, @code{mreal} x1, @code{mreal} y1, @code{mreal} z1, @code{mreal} x2, @code{mreal} y2, @code{mreal} z2, @code{mreal} r1, @code{mreal} r2, @code{const char *}stl)
+ at end ifclear
+Draw tube (or truncated cone if @var{edge}=@code{false}) between points @var{p1}, @var{p2} with radius at the edges @var{r1}, @var{r2}. If @var{r2}<0 then it is supposed that @var{r2}=@var{r1}. The cone color is defined by string @var{stl}. Parameter @var{stl} can contain:
+ at itemize @bullet
+ at item
+ at samp{@@} for drawing edges;
+ at item
+ at samp{#} for wired cones;
+ at item
+ at samp{t} for drawing tubes/cylinder instead of cones/prisms;
+ at item
+ at samp{4}, @samp{6}, @samp{8} for drawing square, hex- or octo-prism instead of cones.
+ at end itemize
+ at end deftypefn
+
+ at anchor{circle}
+ at deftypefn {MGL command} {} circle @code{x0 y0 r} ['col'='r']
+ at deftypefnx {MGL command} {} circle @code{x0 y0 z0 r} ['col'='r']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Circle (@code{mglPoint} p, @code{mreal} r, @code{const char *}stl=@code{"r"})
+ at end ifclear
+Draw the circle with radius @var{r} and center at point @var{p}=@{@var{x0}, @var{y0}, @var{z0}@}. Parameter @var{col} may contain
+ at itemize @bullet
+ at item
+colors for filling and boundary (second one if style @samp{@@} is used, black color is used by default);
+ at item
+ at samp{#} for wire figure (boundary only);
+ at item
+ at samp{@@} for filling and boundary.
+ at end itemize
+ at end deftypefn
+
+ at anchor{ellipse}
+ at deftypefn {MGL command} {} ellipse @code{x1 y1 x2 y2 r} ['col'='r']
+ at deftypefnx {MGL command} {} ellipse @code{x1 y1 z1 x2 y2 z2 r} ['col'='r']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Ellipse (@code{mglPoint} p1, @code{mglPoint} p2, @code{mreal} r, @code{const char *}col=@code{"r"})
+ at deftypefnx {C function} @code{void} mgl_ellipse (@code{HMGL} gr, @code{mreal} x1, @code{mreal} y1, @code{mreal} z1, @code{mreal} x2, @code{mreal} y2, @code{mreal} z2, @code{mreal} r, @code{const char *}col)
+ at end ifclear
+Draw the ellipse with radius @var{r} and focal points @var{p1}, @var{p2}. Parameter @var{col} may contain
+ at itemize @bullet
+ at item
+colors for filling and boundary (second one if style @samp{@@} is used, black color is used by default);
+ at item
+ at samp{#} for wire figure (boundary only);
+ at item
+ at samp{@@} for filling and boundary.
+ at end itemize
+ at end deftypefn
+
+ at anchor{rhomb}
+ at deftypefn {MGL command} {} rhomb @code{x1 y1 x2 y2 r} ['col'='r']
+ at deftypefnx {MGL command} {} rhomb @code{x1 y1 z1 x2 y2 z2 r} ['col'='r']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Rhomb (@code{mglPoint} p1, @code{mglPoint} p2, @code{mreal} r, @code{const char *}col=@code{"r"})
+ at deftypefnx {C function} @code{void} mgl_rhomb (@code{HMGL} gr, @code{mreal} x1, @code{mreal} y1, @code{mreal} z1, @code{mreal} x2, @code{mreal} y2, @code{mreal} z2, @code{mreal} r, @code{const char *}col)
+ at end ifclear
+Draw the rhombus with width @var{r} and edge points @var{p1}, @var{p2}. Parameter @var{col} may contain
+ at itemize @bullet
+ at item
+colors for filling and boundary (second one if style @samp{@@} is used, black color is used by default);
+ at item
+ at samp{#} for wire figure (boundary only);
+ at item
+ at samp{@@} for filling and boundary.
+ at end itemize
+ at end deftypefn
+
+ at anchor{arc}
+ at deftypefn {MGL command} {} arc @code{x0 y0 x1 y1 a} ['col'='r']
+ at deftypefnx {MGL command} {} arc @code{x0 y0 z0 x1 y1 a} ['col'='r']
+ at deftypefnx {MGL command} {} arc @code{x0 y0 z0 xa ya za x1 y1 z1 a} ['col'='r']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Arc (@code{mglPoint} p0, @code{mglPoint} p1, @code{mreal} a, @code{const char *}col=@code{"r"})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Arc (@code{mglPoint} p0, @code{mglPoint} pa, @code{mglPoint} p1, @code{mreal} a, @code{const char *}col=@code{"r"})
+ at deftypefnx {C function} @code{void} mgl_arc (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} x1, @code{mreal} y1, @code{mreal} a, @code{const char *}col)
+ at deftypefnx {C function} @code{void} mgl_arc_ext (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{mreal} xa, @code{mreal} ya, @code{mreal} za, @code{mreal} x1, @code{mreal} y1, @code{mreal} z1, @code{mreal} a, @code{const char *}col)
+ at end ifclear
+Draw the arc around axis @var{pa} (default is z-axis @var{pa}=@{0,0,1@}) with center at @var{p0} and starting from point @var{p1}. Parameter @var{a} set the angle of arc in degree. Parameter @var{col} may contain color of the arc and arrow style for arc edges.
+ at end deftypefn
+
+ at anchor{polygon}
+ at deftypefn {MGL command} {} polygon @code{x0 y0 x1 y1 num} ['col'='r']
+ at deftypefnx {MGL command} {} polygon @code{x0 y0 z0 x1 y1 z1 num} ['col'='r']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Polygon (@code{mglPoint} p0, @code{mglPoint} p1, @code{int} num, @code{const char *}col=@code{"r"})
+ at deftypefnx {C function} @code{void} mgl_polygon (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{mreal} x1, @code{mreal} y1, @code{mreal} z1, @code{int} num, @code{const char *}col)
+ at end ifclear
+Draw the polygon with @var{num} edges starting from @var{p1}. The center of polygon is located in @var{p0}. Parameter @var{col} may contain
+ at itemize @bullet
+ at item
+colors for filling and boundary (second one if style @samp{@@} is used, black color is used by default);
+ at item
+ at samp{#} for wire figure (boundary only);
+ at item
+ at samp{@@} for filling and boundary.
+ at end itemize
+ at end deftypefn
+
+
+ at anchor{logo}
+ at deftypefn {MGL command} {} logo 'fname' [smooth=off]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Logo (@code{const char *}fname, @code{bool} smooth=@code{false}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Logo (@code{long} w, @code{long} h, @code{const unsigned char *}rgba, @code{bool} smooth=@code{false}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function only} @code{void} mgl_logo (@code{HMGL} gr, @code{long} w, @code{long} h, @code{const unsigned char *}rgba, @code{bool} smooth, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_logo_file (@code{HMGL} gr, @code{const char *}fname, @code{bool} smooth, @code{const char *}opt)
+ at end ifclear
+Draw bitmap (logo) along whole axis range, which can be changed by @ref{Command options}. Bitmap can be loaded from file or specified as RGBA values for pixels. Parameter @var{smooth} set to draw bitmap without or with color interpolation.
+ at end deftypefn
+
+
+ at anchor{symbol}
+ at deftypefn {MGL command} {} symbol @code{x y} 'id' ['fnt'='' @code{size=-1}]
+ at deftypefnx {MGL command} {} symbol @code{x y z} 'id' ['fnt'='' @code{size=-1}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Symbol (@code{mglPoint} p, @code{char} id, @code{const char *}fnt=@code{""}, @code{mreal} size=@code{-1})
+ at deftypefnx {C function} @code{void} mgl_symbol (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{char} id, @code{const char *}fnt, @code{mreal} size)
+ at end ifclear
+Draws user-defined symbol with name @var{id} at position @var{p} with style specifying by @var{fnt}. The size of font is set by @var{size} parameter (default is @code{-1}). The string @var{fnt} may contain color specification ended by @samp{:} symbol; styles @samp{a}, @samp{A} to draw at absolute position @{@var{x}, @var{y}@} (supposed to be in range [0,1]) of picture (for @samp{A}) or subplot/inplot (for @samp{a}); and style @samp{w} to draw wired symbol.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} symbol @code{x y dx dy} 'id' ['fnt'=':L' @code{size=-1}]
+ at deftypefnx {MGL command} {} symbol @code{x y z dx dy dz} 'id' ['fnt'=':L' @code{size=-1}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Symbol (@code{mglPoint} p, @code{mglPoint} d, @code{char} id, @code{const char *}fnt=@code{""}, @code{mreal} size=@code{-1})
+ at deftypefnx {C function} @code{void} mgl_symbol_dir (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{mreal} dx, @code{mreal} dy, @code{mreal} dz, @code{const char *}text, @code{const char *}fnt, @code{mreal} size)
+ at end ifclear
+The same as previous but symbol will be drawn rotated along direction @var{d}.
+ at end deftypefn
+
+ at anchor{addsymbol}
+ at deftypefn {MGL command} {} addsymbol 'id' xdat ydat
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} DefineSymbol (@code{char} id, @code{const mglDataA &}xdat, @code{const mglDataA &}ydat)
+ at deftypefnx {C function} @code{void} mgl_define_symbol (@code{HMGL} gr, @code{HCDT} xdat, @code{HCDT} ydat)
+ at end ifclear
+Add user-defined symbol with name @var{id} and contour @{@var{xdat}, @var{ydat}@}. You can use @code{NAN} values to set break (jump) of contour curve.
+ at end deftypefn
+
+
+ at c ##################################################################
+ at external{}
+ at node Text printing, Axis and Colorbar, Primitives, MathGL core
+ at section Text printing
+ at nav{}
+ at ifclear UDAV
+ at cindex Puts
+ at cindex Putsw
+ at end ifclear
+ at cindex Text
+ at cindex Label
+ at cindex fgets
+
+These functions draw the text. There are functions for drawing text in arbitrary place, in arbitrary direction and along arbitrary curve. MathGL can use arbitrary font-faces and parse many TeX commands (for more details see @ref{Font styles}). All these functions have 2 variant: for printing 8-bit text (@code{char *}) and for printing Unicode text (@code{wchar_t *}). In first case the conversion into the current locale is used. So sometimes you need to specify it by @code{setlocale()} fu [...]
+
+The font parameters are described by string. This string may set the text color @samp{wkrgbcymhRGBCYMHW} (see @ref{Color styles}). Starting from MathGL v.2.3, you can set color gradient for text (see @ref{Color scheme}). Also,  after delimiter symbol @samp{:}, it can contain characters of font type (@samp{rbiwou}) and/or align (@samp{LRCTV}) specification. The font types are: @samp{r} -- roman (or regular) font, @samp{i} -- italic style, @samp{b} -- bold style, @samp{w} -- wired style, @ [...]
+
+If string contains symbols @samp{aA} then text is printed at absolute position @{@var{x}, @var{y}@} (supposed to be in range [0,1]) of picture (for @samp{A}) or subplot/inplot (for @samp{a}). If string contains symbol @samp{@@} then box around text is drawn.
+
+ at sref{Text features}
+
+ at anchor{text}
+ at deftypefn {MGL command} {} text @code{x y} 'text' ['fnt'='' @code{size=-1}]
+ at deftypefnx {MGL command} {} text @code{x y z} 'text' ['fnt'='' @code{size=-1}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Puts (@code{mglPoint} p, @code{const char *}text, @code{const char *}fnt=@code{":C"}, @code{mreal} size=@code{-1})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Putsw (@code{mglPoint} p, @code{const wchar_t *}text, @code{const char *}fnt=@code{":C"}, @code{mreal} size=@code{-1})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Puts (@code{mreal} x, @code{mreal} y, @code{const char *}text, @code{const char *}fnt=@code{":AC"}, @code{mreal} size=@code{-1})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Putsw (@code{mreal} x, @code{mreal} y, @code{const wchar_t *}text, @code{const char *}fnt=@code{":AC"}, @code{mreal} size=@code{-1})
+ at deftypefnx {C function} @code{void} mgl_puts (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{const char *}text, @code{const char *}fnt, @code{mreal} size)
+ at deftypefnx {C function} @code{void} mgl_putsw (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{const wchar_t *}text, @code{const char *}fnt, @code{mreal} size)
+ at end ifclear
+Draws the string @var{text} at position @var{p} with fonts specifying by the criteria @var{fnt}. The size of font is set by @var{size} parameter (default is @code{-1}).
+ at end deftypefn
+
+ at deftypefn {MGL command} {} text @code{x y dx dy} 'text' ['fnt'=':L' @code{size=-1}]
+ at deftypefnx {MGL command} {} text @code{x y z dx dy dz} 'text' ['fnt'=':L' @code{size=-1}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Puts (@code{mglPoint} p, @code{mglPoint} d, @code{const char *}text, @code{const char *}fnt=@code{":L"}, @code{mreal} size=@code{-1})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Putsw (@code{mglPoint} p, @code{mglPoint} d, @code{const wchar_t *}text, @code{const char *}fnt=@code{":L"}, @code{mreal} size=@code{-1})
+ at deftypefnx {C function} @code{void} mgl_puts_dir (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{mreal} dx, @code{mreal} dy, @code{mreal} dz, @code{const char *}text, @code{const char *}fnt, @code{mreal} size)
+ at deftypefnx {C function} @code{void} mgl_putsw_dir (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{mreal} dx, @code{mreal} dy, @code{mreal} dz, @code{const wchar_t *}text, @code{const char *}fnt, @code{mreal} size)
+ at end ifclear
+Draws the string @var{text} at position @var{p} along direction @var{d} with specified @var{size}. Parameter @var{fnt} set text style and text position: under (@samp{T}) or above (@samp{t}) the line.
+ at end deftypefn
+
+ at anchor{fgets}
+ at deftypefn {MGL command} {} fgets @code{x y} 'fname' [@code{n=0} 'fnt'='' @code{size=-1.4}]
+ at deftypefnx {MGL command} {} fgets @code{x y z} 'fname' [@code{n=0} 'fnt'='' @code{size=-1.4}]
+Draws unrotated @var{n}-th line of file @var{fname} at position @{@var{x}, at var{y}, at var{z}@} with specified @var{size}. By default parameters from @ref{font} command are used.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} text ydat 'text' ['fnt'='']
+ at deftypefnx {MGL command} {} text xdat ydat 'text' ['fnt'='']
+ at deftypefnx {MGL command} {} text xdat ydat zdat 'text' ['fnt'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Text (@code{const mglDataA &}y, @code{const char *}text, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Text (@code{const mglDataA &}y, @code{const wchar_t *}text, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Text (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const char *}text, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Text (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const wchar_t *}text, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Text (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}text, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Text (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const wchar_t *}text, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_text_y (@code{HMGL} gr, @code{HCDT} y, @code{const char *}text, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_textw_y (@code{HMGL} gr, @code{HCDT} y, @code{const wchar_t *}text, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_text_xy (@code{HCDT} x, @code{HCDT} y, @code{const char *}text, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_textw_xy (@code{HCDT} x, @code{HCDT} y, @code{const wchar_t *}text, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_text_xyz (@code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}text, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_textw_xyz (@code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const wchar_t *}text, @code{const char *}fnt, @code{const char *}opt)
+ at end ifclear
+The function draws @var{text} along the curve between points @{@var{x}[i], @var{y}[i], @var{z}[i]@} by font style @var{fnt}. The string @var{fnt} may contain symbols @samp{t} for printing the text under the curve (default), or @samp{T} for printing the text under the curve. The sizes of 1st dimension must be equal for all arrays @code{x.nx=y.nx=z.nx}. If array @var{x} is not specified then its an automatic array is used with values equidistantly distributed in x-axis range (see @ref{Rang [...]
+ at end deftypefn
+
+ at c ##################################################################
+ at external{}
+ at node Axis and Colorbar, Legend, Text printing, MathGL core
+ at section Axis and Colorbar
+ at nav{}
+ at cindex Axis
+ at cindex Box
+ at cindex Grid
+ at cindex Colorbar
+ at cindex Label
+
+These functions draw the ``things for measuring'', like axis with ticks, colorbar with ticks, grid along axis, bounding box and labels for axis. For more information see @ref{Axis settings}.
+
+ at anchor{axis}
+ at deftypefn {MGL command} {} axis ['dir'='xyz' 'stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Axis (@code{const char *}dir=@code{"xyz"}, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_axis (@code{HMGL} gr, @code{const char *}dir, @code{const char *}stl, @code{const char *}opt)
+ at end ifclear
+Draws axes with ticks (see @ref{Axis settings}). Parameter @var{dir} may contain:
+ at itemize @bullet
+ at item @samp{xyz} for drawing axis in corresponding direction;
+ at item @samp{XYZ} for drawing axis in corresponding direction but with inverted positions of labels;
+ at item @samp{~} or @samp{_} for disabling tick labels;
+ at item @samp{U} for disabling rotation of tick labels;
+ at item @samp{^} for inverting default axis origin;
+ at item @samp{!} for disabling ticks tuning (see @ref{tuneticks});
+ at item @samp{AKDTVISO} for drawing arrow at the end of axis;
+ at item @samp{a} for forced adjusting of axis ticks;
+ at item @samp{f} for printing ticks labels in fixed format;
+ at item @samp{E} for using @samp{E} instead of @samp{e} in ticks labels;
+ at item @samp{F} for printing ticks labels in LaTeX format;
+ at item @samp{+} for printing @samp{+} for positive ticks;
+ at item @samp{-} for printing usual @samp{-} in ticks labels;
+ at item @samp{0123456789} for precision at printing ticks labels.
+ at end itemize
+Styles of ticks and axis can be overrided by using @var{stl} string. Option @code{value} set the manual rotation angle for the ticks. @sref{Axis and ticks}
+ at end deftypefn
+
+ at anchor{colorbar}
+ at deftypefn {MGL command} {} colorbar ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Colorbar (@code{const char *}sch=@code{""})
+ at deftypefnx {C function} @code{void} mgl_colorbar (@code{HMGL} gr, @code{const char *}sch)
+ at end ifclear
+Draws colorbar. Parameter @var{sch} may contain:
+ at itemize @bullet
+ at item
+color scheme (see @ref{Color scheme});
+ at item @samp{<>^_} for positioning at left, at right, at top or at bottom correspondingly;
+ at item @samp{I} for positioning near bounding (by default, is positioned at edges of subplot);
+ at item @samp{A} for using absolute coordinates;
+ at item @samp{~} for disabling tick labels.
+ at item @samp{!} for disabling ticks tuning (see @ref{tuneticks});
+ at item @samp{f} for printing ticks labels in fixed format;
+ at item @samp{E} for using @samp{E} instead of @samp{e} in ticks labels;
+ at item @samp{F} for printing ticks labels in LaTeX format;
+ at item @samp{+} for printing @samp{+} for positive ticks;
+ at item @samp{-} for printing usual @samp{-} in ticks labels;
+ at item @samp{0123456789} for precision at printing ticks labels.
+ at end itemize
+ at sref{Colorbars}
+ at end deftypefn
+
+ at deftypefn {MGL command} {} colorbar vdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Colorbar (@code{const mglDataA &}v, @code{const char *}sch=@code{""})
+ at deftypefnx {C function} @code{void} mgl_colorbar_val (@code{HMGL} gr, @code{HCDT} v, @code{const char *}sch)
+ at end ifclear
+The same as previous but with sharp colors @var{sch} (current palette if @code{sch=""}) for values @var{v}. @sref{ContD sample}
+ at end deftypefn
+
+ at deftypefn {MGL command} {} colorbar 'sch' @code{x y [w=1 h=1]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Colorbar (@code{const char *}sch, @code{mreal} x, @code{mreal} y, @code{mreal} w=@code{1}, @code{mreal} h=@code{1})
+ at deftypefnx {C function} @code{void} mgl_colorbar_ext (@code{HMGL} gr, @code{const char *}sch, @code{mreal} x, @code{mreal} y, @code{mreal} w, @code{mreal} h)
+ at end ifclear
+The same as first one but at arbitrary position of subplot @{@var{x}, @var{y}@} (supposed to be in range [0,1]). Parameters @var{w}, @var{h} set the relative width and height of the colorbar.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} colorbar vdat 'sch' @code{x y [w=1 h=1]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Colorbar (@code{const mglDataA &}v, @code{const char *}sch, @code{mreal} x, @code{mreal} y, @code{mreal} w=@code{1}, @code{mreal} h=@code{1})
+ at deftypefnx {C function} @code{void} mgl_colorbar_val_ext (@code{HMGL} gr, @code{HCDT} v, @code{const char *}sch, @code{mreal} x, @code{mreal} y, @code{mreal} w, @code{mreal} h)
+ at end ifclear
+The same as previous but with sharp colors @var{sch} (current palette if @code{sch=""}) for values @var{v}. @sref{ContD sample}
+ at end deftypefn
+
+ at anchor{grid}
+ at deftypefn {MGL command} {} grid ['dir'='xyz' 'pen'='B']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Grid (@code{const char *}dir=@code{"xyz"}, @code{const char *}pen=@code{"B"}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_axis_grid (@code{HMGL} gr, @code{const char *}dir, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Draws grid lines perpendicular to direction determined by string parameter @var{dir}. If @var{dir} contain @samp{!} then grid lines will be drawn at coordinates of subticks also. The step of grid lines is the same as tick step for @ref{axis}. The style of lines is determined by @var{pen} parameter (default value is dark blue solid line @samp{B-}).
+ at end deftypefn
+
+ at anchor{box}
+ at deftypefn {MGL command} {} box ['stl'='k' @code{ticks=on}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Box (@code{const char *}col=@code{""}, @code{bool} ticks=@code{true})
+ at deftypefnx {C function} @code{void} mgl_box (@code{HMGL} gr)
+ at deftypefnx {C function} @code{void} mgl_box_str (@code{HMGL} gr, @code{const char *}col, @code{int} ticks)
+ at end ifclear
+Draws bounding box outside the plotting volume with color @var{col}. If @var{col} contain @samp{@@} then filled faces are drawn. At this first color is used for faces (default is light yellow), last one for edges. @sref{Bounding box}
+ at end deftypefn
+
+ at anchor{xlabel}
+ at anchor{ylabel}
+ at anchor{zlabel}
+ at anchor{tlabel}
+ at deftypefn {MGL command} {} xlabel 'text' [@code{pos=1}]
+ at deftypefnx {MGL command} {} ylabel 'text' [@code{pos=1}]
+ at deftypefnx {MGL command} {} zlabel 'text' [@code{pos=1}]
+ at deftypefnx {MGL command} {} tlabel 'text' [@code{pos=1}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Label (@code{char} dir, @code{const char *}text, @code{mreal} pos=@code{1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Label (@code{char} dir, @code{const wchar_t *}text, @code{mreal} pos=@code{1}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_label (@code{HMGL} gr, @code{char} dir, @code{const char *}text, @code{mreal} pos, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_labelw (@code{HMGL} gr, @code{char} dir, @code{const wchar_t *}text, @code{mreal} pos, @code{const char *}opt)
+ at end ifclear
+Prints the label @var{text} for axis @var{dir}=@samp{x}, at samp{y}, at samp{z}, at samp{t} (here @samp{t} is ``ternary'' axis @math{t=1-x-y}). The position of label is determined by @var{pos} parameter. If @var{pos}=0 then label is printed at the center of axis. If @var{pos}>0 then label is printed at the maximum of axis. If @var{pos}<0 then label is printed at the minimum of axis. Option @code{value} set additional shifting of the label. @xref{Text printing}.
+ at end deftypefn
+
+ at c ##################################################################
+ at external{}
+ at node Legend, 1D plotting, Axis and Colorbar, MathGL core
+ at section Legend
+ at nav{}
+ at cindex Legend
+ at cindex AddLegend
+ at cindex ClearLegend
+ at cindex SetLegendBox
+ at cindex SetLegendMarks
+
+These functions draw legend to the graph (useful for @ref{1D plotting}). Legend entry is a pair of strings: one for style of the line, another one with description text (with included TeX parsing). The arrays of strings may be used directly or by accumulating first to the internal arrays (by function @ref{addlegend}) and further plotting it. The position of the legend can be selected automatic or manually (even out of bounding box). Parameters @var{fnt} and @var{size} specify the font st [...]
+ at itemize @bullet
+ at item
+font style for legend text;
+ at item
+ at samp{A} for positioning in absolute coordinates;
+ at item
+ at samp{^} for positioning outside of specified point;
+ at item
+ at samp{#} for drawing box around legend;
+ at item
+ at samp{-} for arranging legend entries horizontally;
+ at item
+colors for face (1st one), for border (2nd one) and for text (last one). If less than 3 colors are specified then the color for border is black (for 2 and less colors), and the color for face is white (for 1 or none colors).
+ at end itemize
+ at sref{Legend sample}
+
+ at anchor{legend}
+ at deftypefn {MGL command} {} legend [@code{pos=3} 'fnt'='#']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Legend (@code{int} pos=@code{0x3}, @code{const char *}fnt=@code{"#"}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_legend (@code{HMGL} gr, @code{int} pos, @code{const char *}fnt, @code{const char *}opt)
+ at end ifclear
+Draws legend of accumulated legend entries by font @var{fnt} with @var{size}. Parameter @var{pos} sets the position of the legend: @samp{0} is bottom left corner, @samp{1} is bottom right corner, @samp{2} is top left corner, @samp{3} is top right corner (is default). Option @code{value} set the space between line samples and text (default is 0.1).
+ at end deftypefn
+
+ at deftypefn {MGL command} {} legend @code{x y} ['fnt'='#']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Legend (@code{mreal} x, @code{mreal} y, @code{const char *}fnt=@code{"#"}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_legend_pos (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{const char *}fnt, @code{const char *}opt)
+ at end ifclear
+Draws legend of accumulated legend entries by font @var{fnt} with @var{size}. Position of legend is determined by parameter @var{x}, @var{y} which supposed to be normalized to interval [0,1]. Option @code{value} set the space between line samples and text (default is 0.1).
+ at end deftypefn
+
+ at anchor{addlegend}
+ at deftypefn {MGL command} {} addlegend 'text' 'stl'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} AddLegend (@code{const char *}text, @code{const char *}style)
+ at deftypefnx {Method on @code{mglGraph}} @code{void} AddLegend (@code{const wchar_t *}text, @code{const char *}style)
+ at deftypefnx {C function} @code{void} mgl_add_legend (@code{HMGL} gr, @code{const char *}text, @code{const char *}style)
+ at deftypefnx {C function} @code{void} mgl_add_legendw (@code{HMGL} gr, @code{const wchar_t *}text, @code{const char *}style)
+ at end ifclear
+Adds string @var{text} to internal legend accumulator. The style of described line and mark is specified in string @var{style} (see @ref{Line styles}).
+ at end deftypefn
+
+ at anchor{clearlegend}
+ at deftypefn {MGL command} {} clearlegend
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ClearLegend ()
+ at deftypefnx {C function} @code{void} mgl_clear_legend (@code{HMGL} gr)
+ at end ifclear
+Clears saved legend strings.
+ at end deftypefn
+
+ at anchor{legendmarks}
+ at deftypefn {MGL command} {} legendmarks @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SetLegendMarks (@code{int} num)
+ at deftypefnx {C function} @code{void} mgl_set_legend_marks (@code{HMGL} gr, @code{int} num)
+ at end ifclear
+Set the number of marks in the legend. By default 1 mark is used.
+ at end deftypefn
+
+ at c ##################################################################
+ at external{}
+ at node 1D plotting, 2D plotting, Legend, MathGL core
+ at section 1D plotting
+ at nav{}
+ at cindex Plot
+ at cindex Radar
+ at cindex Tens
+ at cindex Area
+ at cindex Region
+ at cindex Stem
+ at cindex Bars
+ at cindex Barh
+ at cindex Chart
+ at cindex Step
+ at cindex Torus
+ at cindex Tube
+ at cindex Mark
+ at cindex TextMark
+ at cindex Error
+ at cindex BoxPlot
+ at cindex Candle
+ at cindex Tape
+ at cindex Label
+ at cindex Cones
+
+These functions perform plotting of 1D data. 1D means that data depended from only 1 parameter like parametric curve @{x[i],y[i],z[i]@}, i=1...n. By default (if absent) values of @var{x}[i] are equidistantly distributed in axis range, and @var{z}[i] equal to minimal z-axis value. The plots are drawn for each row if one of the data is the matrix. By any case the sizes of 1st dimension @strong{must be equal} for all arrays @code{x.nx=y.nx=z.nx}.
+
+String @var{pen} specifies the color and style of line and marks (see @ref{Line styles}). By default (@code{pen=""}) solid line with color from palette is used (see @ref{Palette and colors}). Symbol @samp{!} set to use new color from palette for each point (not for each curve, as default). String @var{opt} contain command options (see @ref{Command options}). @sref{1D samples}
+
+ at anchor{plot}
+ at deftypefn {MGL command} {} plot ydat ['stl'='']
+ at deftypefnx {MGL command} {} plot xdat ydat ['stl'='']
+ at deftypefnx {MGL command} {} plot xdat ydat zdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Plot (@code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Plot (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Plot (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_plot (@code{HMGL} gr, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_plot_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_plot_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+These functions draw continuous lines between points @{@var{x}[i], @var{y}[i], @var{z}[i]@}. If @var{pen} contain @samp{a} then segments between points outside of axis range are drawn too. See also @ref{area}, @ref{step}, @ref{stem}, @ref{tube}, @ref{mark}, @ref{error}, @ref{belt}, @ref{tens}, @ref{tape}, @ref{meshnum}. @sref{Plot sample}
+ at end deftypefn
+
+ at anchor{radar}
+ at deftypefn {MGL command} {} radar adat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Radar (@code{const mglDataA &}a, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_radar (@code{HMGL} gr, @code{HCDT} a, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+This functions draws radar chart which is continuous lines between points located on an radial lines (like plot in Polar coordinates). Option @code{value} set the additional shift of data (i.e. the data @var{a}+ at code{value} is used instead of @var{a}). If @code{value<0} then @code{r=max(0, -min(value)}. If @var{pen} containt @samp{#} symbol then "grid" (radial lines and circle for @var{r}) is drawn. If @var{pen} contain @samp{a} then segments between points outside of axis range are draw [...]
+ at end deftypefn
+
+ at anchor{step}
+ at deftypefn {MGL command} {} step ydat ['stl'='']
+ at deftypefnx {MGL command} {} step xdat ydat ['stl'='']
+ at deftypefnx {MGL command} {} step xdat ydat zdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Step (@code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Step (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Step (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_step (@code{HMGL} gr, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_step_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_step_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+These functions draw continuous stairs for points to axis plane. If @var{x}.nx>@var{y}.nx then @var{x} set the edges of bars, rather than its central positions. See also @ref{plot}, @ref{stem}, @ref{tile}, @ref{boxs}, @ref{meshnum}. @sref{Step sample}
+ at end deftypefn
+
+ at anchor{tens}
+ at deftypefn {MGL command} {} tens ydat cdat ['stl'='']
+ at deftypefnx {MGL command} {} tens xdat ydat cdat ['stl'='']
+ at deftypefnx {MGL command} {} tens xdat ydat zdat cdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Tens (@code{const mglDataA &}y, @code{const mglDataA &}c, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Tens (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}c, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Tens (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}c, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_tens (@code{HMGL} gr, @code{HCDT} y, @code{HCDT} c, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_tens_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} c, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_tens_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} c, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+These functions draw continuous lines between points @{@var{x}[i], @var{y}[i], @var{z}[i]@} with color defined by the special array @var{c}[i] (look like tension plot). String @var{pen} specifies the color scheme (see @ref{Color scheme}) and style and/or width of line (see @ref{Line styles}). If @var{pen} contain @samp{a} then segments between points outside of axis range are drawn too. See also @ref{plot}, @ref{mesh}, @ref{fall}, @ref{meshnum}. @sref{Tens sample}
+ at end deftypefn
+
+ at anchor{tape}
+ at deftypefn {MGL command} {} tape ydat ['stl'='']
+ at deftypefnx {MGL command} {} tape xdat ydat ['stl'='']
+ at deftypefnx {MGL command} {} tape xdat ydat zdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Tape (@code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Tape (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Tape (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_tape (@code{HMGL} gr, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_tape_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_tape_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+These functions draw tapes of normals for curve between points @{@var{x}[i], @var{y}[i], @var{z}[i]@}. Initial tape(s) was selected in x-y plane (for @samp{x} in @var{pen}) and/or y-z plane (for @samp{x} in @var{pen}). The width of tape is proportional to @ref{barwidth} and can be changed by option @code{value}. See also @ref{plot}, @ref{flow}, @ref{barwidth}. @sref{Tape sample}
+ at end deftypefn
+
+ at anchor{area}
+ at deftypefn {MGL command} {} area ydat ['stl'='']
+ at deftypefnx {MGL command} {} area xdat ydat ['stl'='']
+ at deftypefnx {MGL command} {} area xdat ydat zdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Area (@code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Area (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Area (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_area (@code{HMGL} gr, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_area_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_area_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+These functions draw continuous lines between points and fills it to axis plane. Also you can use gradient filling if number of specified colors is equal to 2*number of curves. If @var{pen} contain @samp{#} then wired plot is drawn. If @var{pen} contain @samp{a} then segments between points outside of axis range are drawn too. See also @ref{plot}, @ref{bars}, @ref{stem}, @ref{region}. @sref{Area sample}
+ at end deftypefn
+
+ at anchor{region}
+ at deftypefn {MGL command} {} region ydat1 ydat2 ['stl'='']
+ at deftypefnx {MGL command} {} region xdat ydat1 ydat2 ['stl'='']
+ at deftypefnx {MGL command} {} region xdat1 ydat1 xdat2 ydat2 ['stl'='']
+ at deftypefnx {MGL command} {} region xdat1 ydat1 zdat1 xdat2 ydat2 zdat2 ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Region (@code{const mglDataA &}y1, @code{const mglDataA &}y2, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Region (@code{const mglDataA &}x, @code{const mglDataA &}y1, @code{const mglDataA &}y2, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Region (@code{const mglDataA &}x1, @code{const mglDataA &}y1, @code{const mglDataA &}x2, @code{const mglDataA &}y2, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Region (@code{const mglDataA &}x1, @code{const mglDataA &}y1, @code{const mglDataA &}z1, @code{const mglDataA &}x2, @code{const mglDataA &}y2, @code{const mglDataA &}z2, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_region (@code{HMGL} gr, @code{HCDT} y1, @code{HCDT} y2, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_region_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y1, @code{HCDT} y2, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_region_3d (@code{HMGL} gr, @code{HCDT} x1, @code{HCDT} y1, @code{HCDT} z1, @code{HCDT} x2, @code{HCDT} y2, @code{HCDT} z2, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+These functions fill area between 2 curves. Dimensions of arrays @var{y1} and @var{y2} must be equal. Also you can use gradient filling if number of specified colors is equal to 2*number of curves. If for 2D version @var{pen} contain symbol @samp{i} then only area with y1<y<y2 will be filled else the area with y2<y<y1 will be filled too. If @var{pen} contain @samp{#} then wired plot is drawn. If @var{pen} contain @samp{a} then segments between points outside of axis range are drawn too.  [...]
+ at end deftypefn
+
+ at anchor{stem}
+ at deftypefn {MGL command} {} stem ydat ['stl'='']
+ at deftypefnx {MGL command} {} stem xdat ydat ['stl'='']
+ at deftypefnx {MGL command} {} stem xdat ydat zdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Stem (@code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Stem (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Stem (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_stem (@code{HMGL} gr, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_stem_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_stem_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+These functions draw vertical lines from points to axis plane. See also @ref{area}, @ref{bars}, @ref{plot}, @ref{mark}. @sref{Stem sample}
+ at end deftypefn
+
+ at anchor{bars}
+ at deftypefn {MGL command} {} bars ydat ['stl'='']
+ at deftypefnx {MGL command} {} bars xdat ydat ['stl'='']
+ at deftypefnx {MGL command} {} bars xdat ydat zdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Bars (@code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Bars (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Bars (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_bars (@code{HMGL} gr, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_bars_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_bars_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+These functions draw vertical bars from points to axis plane. Parameter @var{pen} can contain:
+ at itemize @bullet
+ at item
+ at samp{a} for drawing lines one above another (like summation);
+ at item
+ at samp{f} for drawing waterfall chart, which show the cumulative effect of sequential positive or negative values;
+ at item
+ at samp{F} for using fixed (minimal) width for all bars;
+ at item
+ at samp{<}, @samp{^} or @samp{>} for aligning boxes left, right or centering them at its x-coordinates.
+ at end itemize
+You can give different colors for positive and negative values if number of specified colors is equal to 2*number of curves. If @var{x}.nx>@var{y}.nx then @var{x} set the edges of bars, rather than its central positions. See also @ref{barh}, @ref{cones}, @ref{area}, @ref{stem}, @ref{chart}, @ref{barwidth}. @sref{Bars sample}
+ at end deftypefn
+
+ at anchor{barh}
+ at deftypefn {MGL command} {} barh vdat ['stl'='']
+ at deftypefnx {MGL command} {} barh ydat vdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Barh (@code{const mglDataA &}v, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Barh (@code{const mglDataA &}y, @code{const mglDataA &}v, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_barh (@code{HMGL} gr, @code{HCDT} v, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_barh_xy (@code{HMGL} gr, @code{HCDT} y, @code{HCDT} v, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+These functions draw horizontal bars from points to axis plane. Parameter @var{pen} can contain:
+ at itemize @bullet
+ at item
+ at samp{a} for drawing lines one above another (like summation);
+ at item
+ at samp{f} for drawing waterfall chart, which show the cumulative effect of sequential positive or negative values;
+ at item
+ at samp{F} for using fixed (minimal) width for all bars;
+ at item
+ at samp{<}, @samp{^} or @samp{>} for aligning boxes left, right or centering them at its x-coordinates.
+ at end itemize
+You can give different colors for positive and negative values if number of specified colors is equal to 2*number of curves. If @var{x}.nx>@var{y}.nx then @var{x} set the edges of bars, rather than its central positions. See also @ref{bars}, @ref{barwidth}. @sref{Barh sample}
+ at end deftypefn
+
+ at anchor{cones}
+ at deftypefn {MGL command} {} cones ydat ['stl'='']
+ at deftypefnx {MGL command} {} cones xdat ydat ['stl'='']
+ at deftypefnx {MGL command} {} cones xdat ydat zdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Cones (@code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Cones (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Cones (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_cones (@code{HMGL} gr, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_cones_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_cones_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+These functions draw cones from points to axis plane. If string contain symbol @samp{a} then cones are drawn one above another (like summation). You can give different colors for positive and negative values if number of specified colors is equal to 2*number of curves. Parameter @var{pen} can contain:
+ at itemize @bullet
+ at item
+ at samp{@@} for drawing edges;
+ at item
+ at samp{#} for wired cones;
+ at item
+ at samp{t} for drawing tubes/cylinders instead of cones/prisms;
+ at item
+ at samp{4}, @samp{6}, @samp{8} for drawing square, hex- or octo-prism instead of cones;
+ at item
+ at samp{<}, @samp{^} or @samp{>} for aligning boxes left, right or centering them at its x-coordinates.
+ at end itemize
+See also @ref{bars}, @ref{cone}, @ref{barwidth}. @sref{Cones sample}
+ at end deftypefn
+
+
+
+ at anchor{chart}
+ at deftypefn {MGL command} {} chart adat ['col'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Chart (@code{const mglDataA &}a, @code{const char *}col=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_chart (@code{HMGL} gr, @code{HCDT} a, @code{const char *}col, @code{const char *}opt)
+ at end ifclear
+The function draws colored stripes (boxes) for data in array @var{a}. The number of stripes is equal to the number of rows in @var{a} (equal to @var{a.ny}). The color of each next stripe is cyclically changed from colors specified in string @var{col} or in palette Pal (see @ref{Palette and colors}). Spaces in colors denote transparent ``color'' (i.e. corresponding stripe(s) are not drawn). The stripe width is proportional to value of element in @var{a}. Chart is plotted only for data wit [...]
+ at end deftypefn
+
+ at anchor{boxplot}
+ at deftypefn {MGL command} {} boxplot adat ['stl'='']
+ at deftypefnx {MGL command} {} boxplot xdat adat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} BoxPlot (@code{const mglDataA &}a, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} BoxPlot (@code{const mglDataA &}x, @code{const mglDataA &}a, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_boxplot (@code{HMGL} gr, @code{HCDT} a, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_boxplot_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} a, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+These functions draw boxplot (also known as a box-and-whisker diagram) at points @var{x}[i]. This is five-number summaries of data @var{a}[i,j] (minimum, lower quartile (Q1), median (Q2), upper quartile (Q3) and maximum) along second (j-th) direction. If @var{pen} contain @samp{<}, @samp{^} or @samp{>} then boxes will be aligned left, right or centered at its x-coordinates. See also @ref{plot}, @ref{error}, @ref{bars}, @ref{barwidth}. @sref{BoxPlot sample}
+ at end deftypefn
+
+ at anchor{candle}
+ at deftypefn {MGL command} {} candle vdat1 ['stl'='']
+ at deftypefnx {MGL command} {} candle vdat1 vdat2 ['stl'='']
+ at deftypefnx {MGL command} {} candle vdat1 ydat1 ydat2 ['stl'='']
+ at deftypefnx {MGL command} {} candle vdat1 vdat2 ydat1 ydat2 ['stl'='']
+ at deftypefnx {MGL command} {} candle xdat vdat1 vdat2 ydat1 ydat2 ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Candle (@code{const mglDataA &}v1, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Candle (@code{const mglDataA &}v1, @code{const mglDataA &}v2, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Candle (@code{const mglDataA &}v1, @code{const mglDataA &}y1, @code{const mglDataA &}y2, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Candle (@code{const mglDataA &}v1, @code{const mglDataA &}v2, @code{const mglDataA &}y1, @code{const mglDataA &}y2, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Candle (@code{const mglDataA &}x, @code{const mglDataA &}v1, @code{const mglDataA &}v2, @code{const mglDataA &}y1, @code{const mglDataA &}y2, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_candle (@code{HMGL} gr, @code{HCDT} v1, @code{HCDT} y1, @code{HCDT} y2, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_candle_yv (@code{HMGL} gr, @code{HCDT} v1, @code{HCDT} v2, @code{HCDT} y1, @code{HCDT} y2, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_candle_xyv (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} v1, @code{HCDT} v2, @code{HCDT} y1, @code{HCDT} y2, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+These functions draw candlestick chart at points @var{x}[i]. This is a combination of a line-chart and a bar-chart, in that each bar represents the range of price movement over a given time interval. Wire (or white) candle correspond to price growth @var{v1}[i]<@var{v2}[i], opposite case -- solid (or dark) candle. You can give different colors for growth and decrease values if number of specified colors is equal to 2. If @var{pen} contain @samp{#} then the wire candle will be used even f [...]
+ at end deftypefn
+
+ at anchor{ohlc}
+ at deftypefn {MGL command} {} ohlc odat hdat ldat cdat ['stl'='']
+ at deftypefnx {MGL command} {} ohlc xdat odat hdat ldat cdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} OHLC (@code{const mglDataA &}o, @code{const mglDataA &}h, @code{const mglDataA &}l, @code{const mglDataA &}c, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} OHLC (@code{const mglDataA &}x, @code{const mglDataA &}o, @code{const mglDataA &}h, @code{const mglDataA &}l, @code{const mglDataA &}c, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_ohlc (@code{HMGL} gr, @code{HCDT} o, @code{HCDT} h, @code{HCDT} l, @code{HCDT} c, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_ohlc_x (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} o, @code{HCDT} h, @code{HCDT} l, @code{HCDT} c, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+These functions draw Open-High-Low-Close diagram. This diagram show vertical line for between maximal(high @var{h}) and minimal(low @var{l}) values, as well as horizontal lines before/after vertical line for initial(open @var{o})/final(close @var{c}) values of some process (usually price). You can give different colors for up and down values (when closing values higher or not as in previous point) if number of specified colors is equal to 2*number of curves. See also @ref{candle}, @ref{p [...]
+ at end deftypefn
+
+
+ at anchor{error}
+ at deftypefn {MGL command} {} error ydat yerr ['stl'='']
+ at deftypefnx {MGL command} {} error xdat ydat yerr ['stl'='']
+ at deftypefnx {MGL command} {} error xdat ydat xerr yerr ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Error (@code{const mglDataA &}y, @code{const mglDataA &}ey, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Error (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}ey, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Error (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}ex, @code{const mglDataA &}ey, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_error (@code{HMGL} gr, @code{HCDT} y, @code{HCDT} ey, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_error_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} ey, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_error_exy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} ex, @code{HCDT} ey, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+These functions draw error boxes @{@var{ex}[i], @var{ey}[i]@} at points @{@var{x}[i], @var{y}[i]@}. This can be useful, for example, in experimental points, or to show numeric error or some estimations and so on. If string @var{pen} contain symbol @samp{@@} than large semitransparent mark is used instead of error box. See also @ref{plot}, @ref{mark}. @sref{Error sample}
+ at end deftypefn
+
+ at anchor{mark}
+ at deftypefn {MGL command} {} mark ydat rdat ['stl'='']
+ at deftypefnx {MGL command} {} mark xdat ydat rdat ['stl'='']
+ at deftypefnx {MGL command} {} mark xdat ydat zdat rdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Mark (@code{const mglDataA &}y, @code{const mglDataA &}r, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Mark (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}r, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Mark (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}r, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_mark_y (@code{HMGL} gr, @code{HCDT} y, @code{HCDT} r, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_mark_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} r, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_mark_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} r, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+These functions draw marks with size @var{r}[i]*@ref{marksize} at points @{@var{x}[i], @var{y}[i], @var{z}[i]@}. If you need to draw markers of the same size then you can use @ref{plot} function with empty line style @samp{ }. For markers with size in axis range use @ref{error} with style @samp{@@}. See also @ref{plot}, @ref{textmark}, @ref{error}, @ref{stem}, @ref{meshnum}. @sref{Mark sample}
+ at end deftypefn
+
+ at anchor{textmark}
+ at deftypefn {MGL command} {} textmark ydat 'txt' ['stl'='']
+ at deftypefnx {MGL command} {} textmark ydat rdat 'txt' ['stl'='']
+ at deftypefnx {MGL command} {} textmark xdat ydat rdat 'txt' ['stl'='']
+ at deftypefnx {MGL command} {} textmark xdat ydat zdat rdat 'txt' ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} TextMark (@code{const mglDataA &}y, @code{const char *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} TextMark (@code{const mglDataA &}y, @code{const wchar_t *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} TextMark (@code{const mglDataA &}y, @code{const mglDataA &}r, @code{const char *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} TextMark (@code{const mglDataA &}y, @code{const mglDataA &}r, @code{const wchar_t *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} TextMark (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}r, @code{const char *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} TextMark (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}r, @code{const wchar_t *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} TextMark (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}r, @code{const char *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} TextMark (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}r, @code{const wchar_t *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_textmark (@code{HMGL} gr, @code{HCDT} y, @code{const char *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_textmarkw (@code{HMGL} gr, @code{HCDT} y, @code{const wchar_t *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_textmark_yr (@code{HMGL} gr, @code{HCDT} y, @code{HCDT} r, @code{const char *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_textmarkw_yr (@code{HMGL} gr, @code{HCDT} y, @code{HCDT} r, @code{const wchar_t *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_textmark_xyr (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} r, @code{const char *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_textmarkw_xyr (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} r, @code{const wchar_t *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_textmark_xyzr (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} r, @code{const char *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_textmarkw_xyzr (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} r, @code{const wchar_t *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at end ifclear
+These functions draw string @var{txt} as marks with size proportional to @var{r}[i]*@var{marksize} at points @{@var{x}[i], @var{y}[i], @var{z}[i]@}. By default (if omitted) @var{r}[i]=1. See also @ref{plot}, @ref{mark}, @ref{stem}, @ref{meshnum}. @sref{TextMark sample}
+ at end deftypefn
+
+ at anchor{label}
+ at deftypefn {MGL command} {} label ydat 'txt' ['stl'='']
+ at deftypefnx {MGL command} {} label xdat ydat 'txt' ['stl'='']
+ at deftypefnx {MGL command} {} label xdat ydat zdat 'txt' ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Label (@code{const mglDataA &}y, @code{const char *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Label (@code{const mglDataA &}y, @code{const wchar_t *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Label (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const char *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Label (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const wchar_t *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Label (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Label (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const wchar_t *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_label (@code{HMGL} gr, @code{HCDT} y, @code{const char *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_labelw (@code{HMGL} gr, @code{HCDT} y, @code{const wchar_t *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_label_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{const char *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_labelw_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{const wchar_t *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_label_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_labelw_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const wchar_t *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at end ifclear
+These functions draw string @var{txt} at points @{@var{x}[i], @var{y}[i], @var{z}[i]@}. If string @var{txt} contain @samp{%x}, @samp{%y}, @samp{%z} or @samp{%n} then it will be replaced by the value of x-,y-,z-coordinate of the point or its index. String @var{fnt} may contain:
+ at itemize
+ at item font style @ref{Font styles};
+ at item @samp{f} for fixed format of printed numbers;
+ at item @samp{E} for using @samp{E} instead of @samp{e};
+ at item @samp{F} for printing in LaTeX format;
+ at item @samp{+} for printing @samp{+} for positive numbers;
+ at item @samp{-} for printing usual @samp{-};
+ at item @samp{0123456789} for precision at printing numbers.
+ at end itemize
+See also @ref{plot}, @ref{mark}, @ref{textmark}, @ref{table}. @sref{Label sample}
+ at end deftypefn
+
+ at anchor{table}
+ at deftypefn {MGL command} {} table vdat 'txt' ['stl'='#']
+ at deftypefnx {MGL command} {} table x y vdat 'txt' ['stl'='#']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Table (@code{const mglDataA &}val, @code{const char *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Table (@code{const mglDataA &}val, @code{const wchar_t *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Table (@code{mreal} x, @code{mreal} y, @code{const mglDataA &}val, @code{const char *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Table (@code{mreal} x, @code{mreal} y, @code{const mglDataA &}val, @code{const wchar_t *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_table (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{HCDT} val, @code{const char *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_tablew (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{HCDT} val, @code{const wchar_t *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at end ifclear
+These functions draw table with values of @var{val} and captions from string @var{txt} (separated by newline symbol @samp{\n}) at points @{@var{x}, @var{y}@} (default at @{0,0@}) related to current subplot. String @var{fnt} may contain:
+ at itemize
+ at item font style @ref{Font styles};
+ at item @samp{#} for drawing cell borders;
+ at item @samp{|} for limiting table widh by subplot one (equal to option @samp{value 1});
+ at item @samp{=} for equal width of all cells;
+ at item @samp{f} for fixed format of printed numbers;
+ at item @samp{E} for using @samp{E} instead of @samp{e};
+ at item @samp{F} for printing in LaTeX format;
+ at item @samp{+} for printing @samp{+} for positive numbers;
+ at item @samp{-} for printing usual @samp{-};
+ at item @samp{0123456789} for precision at printing numbers.
+ at end itemize
+Option @code{value} set the width of the table (default is 1). See also @ref{plot}, @ref{label}. @sref{Table sample}
+ at end deftypefn
+
+ at anchor{iris}
+ at deftypefn {MGL command} {} iris dats 'ids' ['stl'='']
+ at deftypefnx {MGL command} {} iris dats rngs 'ids' ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Iris (@code{const mglDataA &}dats, @code{const char *}ids, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Iris (@code{const mglDataA &}dats, @code{const wchar_t *}ids, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Iris (@code{const mglDataA &}dats, @code{const mglDataA &}rngs, @code{const char *}ids, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Iris (@code{const mglDataA &}dats, @code{const mglDataA &}rngs, @code{const wchar_t *}ids, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_iris_1 (@code{HMGL} gr, @code{HCDT} dats, @code{const char *}ids, @code{const char *}stl, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_irisw_1 (@code{HMGL} gr, @code{HCDT} dats, @code{const wchar_t *}ids, @code{const char *}stl, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_iris (@code{HMGL} gr, @code{HCDT} dats, @code{HCDT} rngs, @code{const char *}ids, @code{const char *}stl, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_irisw (@code{HMGL} gr, @code{HCDT} dats, @code{HCDT} rngs, @code{const wchar_t *}ids, @code{const char *}stl, @code{const char *}opt)
+ at end ifclear
+Draws Iris plots for determining cross-dependences of data arrays @var{dats} (see @uref{http://en.wikipedia.org/wiki/Iris_flower_data_set}). Data @var{rngs} of size 2*@var{dats}.nx provide manual axis ranges for each column. String @var{ids} contain column names, separated by @samp{;} symbol. Option @code{value} set the text size for column names. You can add another data set to existing Iris plot by providing the same ranges @var{rngs} and empty column names @var{ids}. See also @ref{plo [...]
+ at end deftypefn
+
+ at anchor{tube}
+ at deftypefn {MGL command} {} tube ydat rdat ['stl'='']
+ at deftypefnx {MGL command} {} tube ydat @code{rval} ['stl'='']
+ at deftypefnx {MGL command} {} tube xdat ydat rdat ['stl'='']
+ at deftypefnx {MGL command} {} tube xdat ydat @code{rval} ['stl'='']
+ at deftypefnx {MGL command} {} tube xdat ydat zdat rdat ['stl'='']
+ at deftypefnx {MGL command} {} tube xdat ydat zdat @code{rval} ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Tube (@code{const mglDataA &}y, @code{const mglDataA &}r, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Tube (@code{const mglDataA &}y, @code{mreal} r, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Tube (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}r, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Tube (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{mreal} r, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Tube (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}r, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Tube (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{mreal} r, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_tube_r (@code{HMGL} gr, @code{HCDT} y, @code{HCDT} r, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_tube (@code{HMGL} gr, @code{HCDT} y, @code{mreal} r, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_tube_xyr (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} r, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_tube_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{mreal} r, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_tube_xyzr (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} r, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_tube_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{mreal} r, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+These functions draw the tube with variable radius @var{r}[i] along the curve between points @{@var{x}[i], @var{y}[i], @var{z}[i]@}. See also @ref{plot}. @sref{Tube sample}
+ at end deftypefn
+
+ at anchor{torus}
+ at deftypefn {MGL command} {} torus rdat zdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Torus (@code{const mglDataA &}r, @code{const mglDataA &}z, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_torus (@code{HMGL} gr, @code{HCDT} r, @code{HCDT} z, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+These functions draw surface which is result of curve @{@var{r}, @var{z}@} rotation around axis. If string @var{pen} contain symbols @samp{x} or @samp{z} then rotation axis will be set to specified direction (default is @samp{y}). If string @var{pen} have symbol @samp{#} then wire plot is produced. If string @var{pen} have symbol @samp{.} then plot by dots is produced. See also @ref{plot}, @ref{axial}. @sref{Torus sample}
+ at end deftypefn
+
+ at anchor{lamerey}
+ at deftypefn {MGL command} {} lamerey @code{x0} ydat ['stl'='']
+ at deftypefnx {MGL command} {} lamerey @code{x0} 'y(x)' ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Lamerey (@code{double} x0, @code{const mglDataA &}y, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Lamerey (@code{double} x0, @code{const char *}y, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_lamerey_dat (@code{HMGL} gr, @code{double} x0, @code{HCDT} y, @code{const char *}stl, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_lamerey_str (@code{HMGL} gr, @code{double} x0, @code{const char *}y, @code{const char *}stl, @code{const char *}opt)
+ at end ifclear
+These functions draw Lamerey diagram for mapping x_new = y(x_old) starting from point @var{x0}. String @var{stl} may contain line style, symbol @samp{v} for drawing arrows, symbol @samp{~} for disabling first segment. Option @code{value} set the number of segments to be drawn (default is 20). See also @ref{plot}, @ref{fplot}, @ref{bifurcation}, @ref{pmap}. @sref{Lamerey sample}
+ at end deftypefn
+
+ at anchor{bifurcation}
+ at deftypefn {MGL command} {} bifurcation @code{dx} ydat ['stl'='']
+ at deftypefnx {MGL command} {} bifurcation @code{dx} 'y(x)' ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Bifurcation (@code{double} dx, @code{const mglDataA &}y, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Bifurcation (@code{double} dx, @code{const char *}y, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_bifurcation_dat (@code{HMGL} gr, @code{double} dx, @code{HCDT} y, @code{const char *}stl, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_bifurcation_str (@code{HMGL} gr, @code{double} dx, @code{const char *}y, @code{const char *}stl, @code{const char *}opt)
+ at end ifclear
+These functions draw bifurcation diagram for mapping x_new = y(x_old). Parameter @var{dx} set the accuracy along x-direction. String @var{stl} set color. Option @code{value} set the number of stationary points (default is 1024). See also @ref{plot}, @ref{fplot}, @ref{lamerey}. @sref{Bifurcation sample}
+ at end deftypefn
+
+ at anchor{pmap}
+ at deftypefn {MGL command} {} pmap ydat sdat ['stl'='']
+ at deftypefnx {MGL command} {} pmap xdat ydat sdat ['stl'='']
+ at deftypefnx {MGL command} {} pmap xdat ydat zdat sdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Pmap (@code{const mglDataA &}y, @code{const mglDataA &}s, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Pmap (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}s, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Pmap (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}s, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_pmap (@code{HMGL} gr, @code{HMDT} y, @code{HCDT} s, @code{const char *}stl, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_pmap_xy (@code{HMGL} gr, @code{HCDT} x, @code{HMDT} y, @code{HCDT} s, @code{const char *}stl, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_pmap_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HMDT} y, @code{HCDT} z, @code{HCDT} s, @code{const char *}stl, @code{const char *}opt)
+ at end ifclear
+These functions draw Poincare map for curve @{@var{x}, @var{y}, @var{z}@} at surface @var{s}=0. Basically, it show intersections of the curve and the surface. String @var{stl} set the style of marks. See also @ref{plot}, @ref{mark}, @ref{lamerey}. @sref{Pmap sample}
+ at end deftypefn
+
+
+ at c ##################################################################
+ at external{}
+ at node 2D plotting, 3D plotting, 1D plotting, MathGL core
+ at section 2D plotting
+ at nav{}
+ at cindex Mesh
+ at cindex Fall
+ at cindex Belt
+ at cindex Surf
+ at cindex Boxs
+ at cindex Tile
+ at cindex Dens
+ at cindex Cont
+ at cindex ContF
+ at cindex ContD
+ at cindex Axial
+ at cindex Grad
+ at cindex Grid
+
+These functions perform plotting of 2D data. 2D means that data depend from 2 independent parameters like matrix @math{f(x_i,y_j), i=1...n, j=1...m}.  By default (if absent) values of @var{x}, @var{y} are equidistantly distributed in axis range. The plots are drawn for each z slice of the data. The minor dimensions of arrays @var{x}, @var{y}, @var{z} should be equal @code{x.nx=z.nx && y.nx=z.ny} or @code{x.nx=y.nx=z.nx && x.ny=y.ny=z.ny}. Arrays @var{x} and @var{y} can be vectors (not ma [...]
+
+ at anchor{surf}
+ at deftypefn {MGL command} {} surf zdat ['sch'='']
+ at deftypefnx {MGL command} {} surf xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Surf (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Surf (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_surf (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_surf_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws surface specified parametrically @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@}. If string @var{sch} have symbol @samp{#} then grid lines are drawn. If string @var{sch} have symbol @samp{.} then plot by dots is produced. See also @ref{mesh}, @ref{dens}, @ref{belt}, @ref{tile}, @ref{boxs}, @ref{surfc}, @ref{surfa}. @sref{Surf sample}
+ at end deftypefn
+
+ at anchor{mesh}
+ at deftypefn {MGL command} {} mesh zdat ['sch'='']
+ at deftypefnx {MGL command} {} mesh xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Mesh (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Mesh (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_mesh (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_mesh_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws mesh lines for surface specified parametrically @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@}. See also @ref{surf}, @ref{fall}, @ref{meshnum}, @ref{cont}, @ref{tens}. @sref{Mesh sample}
+ at end deftypefn
+
+ at anchor{fall}
+ at deftypefn {MGL command} {} fall zdat ['sch'='']
+ at deftypefnx {MGL command} {} fall xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Fall (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Fall (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_fall (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_fall_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws fall lines for surface specified parametrically @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@}. This plot can be used for plotting several curves shifted in depth one from another. If @var{sch} contain @samp{x} then lines are drawn along x-direction else (by default) lines are drawn along y-direction. See also @ref{belt}, @ref{mesh}, @ref{tens}, @ref{meshnum}. @sref{Fall sample}
+ at end deftypefn
+
+ at anchor{belt}
+ at deftypefn {MGL command} {} belt zdat ['sch'='']
+ at deftypefnx {MGL command} {} belt xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Belt (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Belt (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_belt (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_belt_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws belts for surface specified parametrically @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@}. This plot can be used as 3d generalization of @ref{plot}). If @var{sch} contain @samp{x} then belts are drawn along x-direction else (by default) belts are drawn along y-direction. See also @ref{fall}, @ref{surf}, @ref{plot}, @ref{meshnum}. @sref{Belt sample}
+ at end deftypefn
+
+ at anchor{boxs}
+ at deftypefn {MGL command} {} boxs zdat ['sch'='']
+ at deftypefnx {MGL command} {} boxs xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Boxs (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Boxs (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_boxs (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_boxs_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws vertical boxes for surface specified parametrically @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@}. Symbol @samp{@@} in @var{sch} set to draw filled boxes. See also @ref{surf}, @ref{dens}, @ref{tile}, @ref{step}. @sref{Boxs sample}
+ at end deftypefn
+
+ at anchor{tile}
+ at deftypefn {MGL command} {} tile zdat ['sch'='']
+ at deftypefnx {MGL command} {} tile xdat ydat zdat ['sch'='']
+ at deftypefnx {MGL command} {} tile xdat ydat zdat cdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Tile (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Tile (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Tile (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_tile (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_tile_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_tile_xyc (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws horizontal tiles for surface specified parametrically @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@} and color it by matrix @var{c}[i,j] (@var{c}=@var{z} if @var{c} is not provided). If string @var{sch} contain style @samp{x} or @samp{y} then tiles will be oriented perpendicular to x- or y-axis. Such plot can be used as 3d generalization of @ref{step}. See also @ref{surf}, @ref{boxs}, @ref{step}, @ref{tiles}. @sref{Tile sample}
+ at end deftypefn
+
+ at anchor{dens}
+ at deftypefn {MGL command} {} dens zdat ['sch'='']
+ at deftypefnx {MGL command} {} dens xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Dens (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""}, @code{mreal} zVal=@code{NAN})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Dens (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""}, @code{mreal} zVal=@code{NAN})
+ at deftypefnx {C function} @code{void} mgl_dens (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_dens_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws density plot for surface specified parametrically @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@} at @var{z} equal to minimal z-axis value. If string @var{sch} have symbol @samp{#} then grid lines are drawn. If string @var{sch} have symbol @samp{.} then plot by dots is produced. See also @ref{surf}, @ref{cont}, @ref{contf}, @ref{boxs}, @ref{tile}, @code{dens[xyz]}. @sref{Dens sample}
+ at end deftypefn
+
+ at anchor{cont}
+ at deftypefn {MGL command} {} cont vdat zdat ['sch'='']
+ at deftypefnx {MGL command} {} cont vdat xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Cont (@code{const mglDataA &}v, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Cont (@code{const mglDataA &}v, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_cont_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_cont_xy_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws contour lines for surface specified parametrically @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@} at @var{z}=@var{v}[k], or at @var{z} equal to minimal z-axis value if @var{sch} contain symbol @samp{_}. Contours are plotted for @var{z}[i,j]=@var{v}[k] where @var{v}[k] are values of data array @var{v}. If string @var{sch} have symbol @samp{t} or @samp{T} then contour labels @var{v}[k] will be drawn below (or above) the contours. See also @ref{dens}, @ref{contf}, @ref{cont [...]
+ at end deftypefn
+
+ at deftypefn {MGL command} {} cont zdat ['sch'='']
+ at deftypefnx {MGL command} {} cont xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Cont (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Cont (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_cont (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_cont_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The same as previous with vector @var{v} of @var{num}-th elements equidistantly distributed in color range. Here @var{num} is equal to parameter @code{value} in options @var{opt} (default is 7).
+ at end deftypefn
+
+ at anchor{contf}
+ at deftypefn {MGL command} {} contf vdat zdat ['sch'='']
+ at deftypefnx {MGL command} {} contf vdat xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContF (@code{const mglDataA &}v, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContF (@code{const mglDataA &}v, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_contf_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_contf_xy_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws solid (or filled) contour lines for surface specified parametrically @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@} at @var{z}=@var{v}[k], or at @var{z} equal to minimal z-axis value if @var{sch} contain symbol @samp{_}. Contours are plotted for @var{z}[i,j]=@var{v}[k] where @var{v}[k] are values of data array @var{v} (must be @code{v.nx>2}). See also @ref{dens}, @ref{cont}, @ref{contd}, @code{contf[xyz]}. @sref{ContF sample}
+ at end deftypefn
+
+ at deftypefn {MGL command} {} contf zdat ['sch'='']
+ at deftypefnx {MGL command} {} contf xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContF (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContF (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_contf (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_contf_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The same as previous with vector @var{v} of @var{num}-th elements equidistantly distributed in color range. Here @var{num} is equal to parameter @code{value} in options @var{opt} (default is 7).
+ at end deftypefn
+
+ at anchor{contd}
+ at deftypefn {MGL command} {} contd vdat zdat ['sch'='']
+ at deftypefnx {MGL command} {} contd vdat xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContD (@code{const mglDataA &}v, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContD (@code{const mglDataA &}v, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_contd_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_contd_xy_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws solid (or filled) contour lines for surface specified parametrically @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@} at @var{z}=@var{v}[k] (or at @var{z} equal to minimal z-axis value if @var{sch} contain symbol @samp{_}) with manual colors. Contours are plotted for @var{z}[i,j]=@var{v}[k] where @var{v}[k] are values of data array @var{v} (must be @code{v.nx>2}). String @var{sch} sets the contour colors: the color of k-th contour is determined by character @code{sch[k%str [...]
+ at end deftypefn
+
+ at deftypefn {MGL command} {} contd zdat ['sch'='']
+ at deftypefnx {MGL command} {} contd xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContD (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContD (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_contd (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_contd_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The same as previous with vector @var{v} of @var{num}-th elements equidistantly distributed in color range. Here @var{num} is equal to parameter @code{value} in options @var{opt} (default is 7).
+ at end deftypefn
+
+ at anchor{contp}
+ at deftypefn {MGL command} {} contp vdat xdat ydat zdat adat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContP (@code{const mglDataA &}v, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_contp_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws contour lines on surface specified parametrically @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@}. Contours are plotted for @var{a}[i,j]=@var{v}[k] where @var{v}[k] are values of data array @var{v}. If string @var{sch} have symbol @samp{t} or @samp{T} then contour labels @var{v}[k] will be drawn below (or above) the contours. If string @var{sch} have symbol @samp{f} then solid contours will be drawn. See also @ref{cont}, @ref{contf}, @ref{surfc}, @code{cont[xyz]}. @c TODO [...]
+ at end deftypefn
+
+ at deftypefn {MGL command} {} contp xdat ydat zdat adat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContP (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_contp (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The same as previous with vector @var{v} of @var{num}-th elements equidistantly distributed in color range. Here @var{num} is equal to parameter @code{value} in options @var{opt} (default is 7).
+ at end deftypefn
+
+
+ at anchor{contv}
+ at deftypefn {MGL command} {} contv vdat zdat ['sch'='']
+ at deftypefnx {MGL command} {} contv vdat xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContV (@code{const mglDataA &}v, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContV (@code{const mglDataA &}v, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_contv_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_contv_xy_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws vertical cylinder (tube) at contour lines for surface specified parametrically @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@} at @var{z}=@var{v}[k], or at @var{z} equal to minimal z-axis value if @var{sch} contain symbol @samp{_}. Contours are plotted for @var{z}[i,j]=@var{v}[k] where @var{v}[k] are values of data array @var{v}. See also @ref{cont}, @ref{contf}. @sref{ContV sample}
+ at end deftypefn
+
+ at deftypefn {MGL command} {} contv zdat ['sch'='']
+ at deftypefnx {MGL command} {} contv xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContV (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContV (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_contv (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_contv_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The same as previous with vector @var{v} of @var{num}-th elements equidistantly distributed in color range. Here @var{num} is equal to parameter @code{value} in options @var{opt} (default is 7).
+ at end deftypefn
+
+ at anchor{axial}
+ at deftypefn {MGL command} {} axial vdat zdat ['sch'='']
+ at deftypefnx {MGL command} {} axial vdat xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Axial (@code{const mglDataA &}v, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Axial (@code{const mglDataA &}v, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_axial_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_axial_xy_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws surface which is result of contour plot rotation for surface specified parametrically @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@}. Contours are plotted for @var{z}[i,j]=@var{v}[k] where @var{v}[k] are values of data array @var{v}. If string @var{sch} have symbol @samp{#} then wire plot is produced. If string @var{sch} have symbol @samp{.} then plot by dots is produced. If string contain symbols @samp{x} or @samp{z} then rotation axis will be set to specified direction [...]
+ at end deftypefn
+
+ at deftypefn {MGL command} {} axial zdat ['sch'='']
+ at deftypefnx {MGL command} {} axial xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Axial (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""}, @code{int} num=@code{3})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Axial (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""}, @code{int} num=@code{3})
+ at deftypefnx {C function} @code{void} mgl_axial (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_axial_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The same as previous with vector @var{v} of @var{num}-th elements equidistantly distributed in color range. Here @var{num} is equal to parameter @code{value} in options @var{opt} (default is 3).
+ at end deftypefn
+
+ at anchor{grid2}
+ at deftypefn {MGL command} {} grid2 zdat ['sch'='']
+ at deftypefnx {MGL command} {} grid2 xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Grid (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Grid (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_grid (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_grid_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws grid lines for density plot of surface specified parametrically @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@} at @var{z} equal to minimal z-axis value. See also @ref{dens}, @ref{cont}, @ref{contf}, @ref{grid3}, @ref{meshnum}.
+ at end deftypefn
+
+
+ at c ##################################################################
+ at external{}
+ at node 3D plotting, Dual plotting, 2D plotting, MathGL core
+ at section 3D plotting
+ at nav{}
+ at cindex Surf3
+ at cindex Dens3
+ at cindex Cont3
+ at cindex ContF3
+ at cindex Grid3
+ at cindex Cloud
+ at cindex Beam
+
+These functions perform plotting of 3D data. 3D means that data depend from 3 independent parameters like matrix @math{f(x_i,y_j,z_k), i=1...n, j=1...m, k=1...l}. By default (if absent) values of @var{x}, @var{y}, @var{z} are equidistantly distributed in axis range. The minor dimensions of arrays @var{x}, @var{y}, @var{z}, @var{a} should be equal @code{x.nx=a.nx && y.nx=a.ny && z.nz=a.nz} or @code{x.nx=y.nx=z.nx=a.nx && x.ny=y.ny=z.ny=a.ny && x.nz=y.nz=z.nz=a.nz}. Arrays @var{x}, @var{y} [...]
+
+ at anchor{surf3}
+ at deftypefn {MGL command} {} surf3 adat @code{val} ['sch'='']
+ at deftypefnx {MGL command} {} surf3 xdat ydat zdat adat @code{val} ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Surf3 (@code{mreal} val, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Surf3 (@code{mreal} val, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_surf3_val (@code{HMGL} gr, @code{mreal} val, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_surf3_xyz_val (@code{HMGL} gr, @code{mreal} val, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws isosurface plot for 3d array specified parametrically @var{a}[i,j,k](@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]) at @var{a}(x,y,z)=@var{val}. If string contain @samp{#} then wire plot is produced. If string @var{sch} have symbol @samp{.} then plot by dots is produced. Note, that there is possibility of incorrect plotting due to uncertainty of cross-section defining if there are two or more isosurface intersections inside one cell. See also @ref{cloud}, @ref{dens3}, [...]
+ at end deftypefn
+
+ at deftypefn {MGL command} {} surf3 adat ['sch'='']
+ at deftypefnx {MGL command} {} surf3 xdat ydat zdat adat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Surf3 (@code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Surf3 (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_surf3 (@code{HMGL} gr, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_surf3_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Draws @var{num}-th uniformly distributed in color range isosurfaces for 3d data. Here @var{num} is equal to parameter @code{value} in options @var{opt} (default is 3).
+ at end deftypefn
+
+ at anchor{cloud}
+ at deftypefn {MGL command} {} cloud adat ['sch'='']
+ at deftypefnx {MGL command} {} cloud xdat ydat zdat adat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Cloud (@code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Cloud (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_cloud (@code{HMGL} gr, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_cloud_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws cloud plot for 3d data specified parametrically @var{a}[i,j,k](@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]). This plot is a set of cubes with color and transparency proportional to value of @var{a}. The resulting plot is like cloud -- low value is transparent but higher ones are not. The number of plotting cells depend on @ref{meshnum}. If string @var{sch} contain symbol @samp{.} then lower quality plot will produced with much low memory usage. If string @var{sch} c [...]
+ at end deftypefn
+
+ at anchor{dens3}
+ at deftypefn {MGL command} {} dens3 adat ['sch'='' @code{sval=-1}]
+ at deftypefnx {MGL command} {} dens3 xdat ydat zdat adat ['sch'='' @code{sval=-1}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Dens3 (@code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Dens3 (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_dens3 (@code{HMGL} gr, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_dens3_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at end ifclear
+The function draws density plot for 3d data specified parametrically @var{a}[i,j,k](@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]). Density is plotted at slice @var{sVal} in direction @{@samp{x}, @samp{y}, @samp{z}@} if @var{sch} contain corresponding symbol (by default, @samp{y} direction is used). If string @var{stl} have symbol @samp{#} then grid lines are drawn. See also @ref{cont3}, @ref{contf3}, @ref{dens}, @ref{grid3}. @sref{Dens3 sample}
+ at end deftypefn
+
+ at anchor{cont3}
+ at deftypefn {MGL command} {} cont3 vdat adat ['sch'='' @code{sval=-1}]
+ at deftypefnx {MGL command} {} cont3 vdat xdat ydat zdat adat ['sch'='' @code{sval=-1}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Cont3 (@code{const mglDataA &}v, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Cont3 (@code{const mglDataA &}v, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_cont3_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_cont3_xyz_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at end ifclear
+The function draws contour plot for 3d data specified parametrically @var{a}[i,j,k](@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]). Contours are plotted for values specified in array @var{v} at slice @var{sVal} in direction @{@samp{x}, @samp{y}, @samp{z}@} if @var{sch} contain corresponding symbol (by default, @samp{y} direction is used). If string @var{sch} have symbol @samp{#} then grid lines are drawn. If string @var{sch} have symbol @samp{t} or @samp{T} then contour labels will be d [...]
+ at end deftypefn
+
+ at deftypefn {MGL command} {} cont3 adat ['sch'='' @code{sval=-1}]
+ at deftypefnx {MGL command} {} cont3 xdat ydat zdat adat ['sch'='' @code{sval=-1}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Cont3 (@code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Cont3 (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_cont3 (@code{HMGL} gr, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_cont3_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at end ifclear
+The same as previous with vector @var{v} of @var{num}-th elements equidistantly distributed in color range. Here @var{num} is equal to parameter @code{value} in options @var{opt} (default is 7).
+ at end deftypefn
+
+ at anchor{contf3}
+ at deftypefn {MGL command} {} contf3 vdat adat ['sch'='' @code{sval=-1}]
+ at deftypefnx {MGL command} {} contf3 vdat xdat ydat zdat adat ['sch'='' @code{sval=-1}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Contf3 (@code{const mglDataA &}v, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Contf3 (@code{const mglDataA &}v, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_contf3_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_contf3_xyz_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at end ifclear
+The function draws solid (or filled) contour plot for 3d data specified parametrically @var{a}[i,j,k](@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]). Contours are plotted for values specified in array @var{v} at slice @var{sVal} in direction @{@samp{x}, @samp{y}, @samp{z}@} if @var{sch} contain corresponding symbol (by default, @samp{y} direction is used). If string @var{sch} have symbol @samp{#} then grid lines are drawn. See also @ref{dens3}, @ref{cont3}, @ref{contf}, @ref{grid3}. @sr [...]
+ at end deftypefn
+
+ at deftypefn {MGL command} {} contf3 adat ['sch'='' @code{sval=-1}]
+ at deftypefnx {MGL command} {} contf3 xdat ydat zdat adat ['sch'='' @code{sval=-1}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Contf3 (@code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Contf3 (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_contf3 (@code{HMGL} gr, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_contf3_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at end ifclear
+The same as previous with vector @var{v} of @var{num}-th elements equidistantly distributed in color range. Here @var{num} is equal to parameter @code{value} in options @var{opt} (default is 7).
+ at end deftypefn
+
+ at anchor{grid3}
+ at deftypefn {MGL command} {} grid3 adat ['sch'='' @code{sval=-1}]
+ at deftypefnx {MGL command} {} grid3 xdat ydat zdat adat ['sch'='' @code{sval=-1}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Grid3 (@code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Grid3 (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_grid3 (@code{HMGL} gr, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_grid3_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at end ifclear
+The function draws grid for 3d data specified parametrically @var{a}[i,j,k](@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]). Grid is plotted at slice @var{sVal} in direction @{@samp{x}, @samp{y}, @samp{z}@} if @var{sch} contain corresponding symbol (by default, @samp{y} direction is used). See also @ref{cont3}, @ref{contf3}, @ref{dens3}, @ref{grid2}, @ref{meshnum}.
+ at end deftypefn
+
+ at anchor{beam}
+ at deftypefn {MGL command} {} beam tr g1 g2 adat @code{rval} ['sch'='' @code{flag=0 num=3}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Beam (@code{const mglDataA &}tr, @code{const mglDataA &}g1, @code{const mglDataA &}g2, @code{const mglDataA &}a, @code{mreal} r, @code{const char *}stl=@code{""}, @code{int} flag=@code{0}, @code{int} num=@code{3})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Beam (@code{mreal} val, @code{const mglDataA &}tr, @code{const mglDataA &}g1, @code{const mglDataA &}g2, @code{const mglDataA &}a, @code{mreal} r, @code{const char *}stl=@code{""}, @code{int} flag=@code{0})
+ at deftypefnx {C function} @code{void} mgl_beam (@code{HMGL} gr, @code{HCDT} tr, @code{HCDT} g1, @code{HCDT} g2, @code{HCDT} a, @code{mreal} r, @code{const char *}stl, @code{int} flag, @code{int} num)
+ at deftypefnx {C function} @code{void} mgl_beam_val (@code{HMGL} gr, @code{mreal} val, @code{HCDT} tr, @code{HCDT} g1, @code{HCDT} g2, @code{HCDT} a, @code{mreal} r, @code{const char *}stl, @code{int} flag)
+ at end ifclear
+Draws the isosurface for 3d array @var{a} at constant values of @var{a}=@var{val}. This is special kind of plot for @var{a} specified in accompanied coordinates along curve @var{tr} with orts @var{g1}, @var{g2} and with transverse scale @var{r}. Variable @var{flag} is bitwise: @samp{0x1} - draw in accompanied (not laboratory) coordinates; @samp{0x2} - draw projection to @math{\rho-z} plane; @samp{0x4} - draw normalized in each slice field. The x-size of data arrays @var{tr}, @var{g1}, @v [...]
+ at end deftypefn
+
+
+ at c ##################################################################
+ at external{}
+ at node Dual plotting, Vector fields, 3D plotting, MathGL core
+ at section Dual plotting
+ at nav{}
+ at cindex SurfC
+ at cindex SurfA
+ at cindex Surf3C
+ at cindex Surf3A
+ at cindex TileS
+ at cindex Map
+ at cindex STFA
+
+These plotting functions draw @emph{two matrix} simultaneously. There are 5 generally different types of data representations: surface or isosurface colored by other data (SurfC, Surf3C), surface or isosurface transpared by other data (SurfA, Surf3A), tiles with variable size (TileS), mapping diagram (Map), STFA diagram (STFA). By default (if absent) values of @var{x}, @var{y}, @var{z} are equidistantly distributed in axis range. The minor dimensions of arrays @var{x}, @var{y}, @var{z},  [...]
+
+ at anchor{surfc}
+ at deftypefn {MGL command} {} surfc zdat cdat ['sch'='']
+ at deftypefnx {MGL command} {} surfc xdat ydat zdat cdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SurfC (@code{const mglDataA &}z, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SurfC (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_surfc (@code{HMGL} gr, @code{HCDT} z, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_surfc_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws surface specified parametrically @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@} and color it by matrix @var{c}[i,j]. If string @var{sch} have symbol @samp{#} then grid lines are drawn. If string @var{sch} have symbol @samp{.} then plot by dots is produced. All dimensions of arrays @var{z} and @var{c} must be equal. Surface is plotted for each z slice of the data. See also @ref{surf}, @ref{surfa}, @ref{surfca}, @ref{surf3c}. @sref{SurfC sample}
+ at end deftypefn
+
+ at anchor{surf3c}
+ at deftypefn {MGL command} {} surf3c adat cdat @code{val} ['sch'='']
+ at deftypefnx {MGL command} {} surf3c xdat ydat zdat adat cdat @code{val} ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Surf3C (@code{mreal} val, @code{const mglDataA &}a, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Surf3C (@code{mreal} val, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_surf3c_val (@code{HMGL} gr, @code{mreal} val, @code{HCDT} a, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_surf3c_xyz_val (@code{HMGL} gr, @code{mreal} val, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws isosurface plot for 3d array specified parametrically @var{a}[i,j,k](@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]) at @var{a}(x,y,z)=@var{val}. It is mostly the same as @ref{surf3} function but the color of isosurface depends on values of array @var{c}. If string @var{sch} contain @samp{#} then wire plot is produced. If string @var{sch} have symbol @samp{.} then plot by dots is produced. See also @ref{surf3}, @ref{surfc}, @ref{surf3a}, @ref{surf3ca}. @sref{Surf3C sample}
+ at end deftypefn
+
+ at deftypefn {MGL command} {} surf3c adat cdat ['sch'='']
+ at deftypefnx {MGL command} {} surf3c xdat ydat zdat adat cdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Surf3C (@code{const mglDataA &}a, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Surf3C (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_surf3c (@code{HMGL} gr, @code{HCDT} a, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_surf3c_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Draws @var{num}-th uniformly distributed in color range isosurfaces for 3d data. Here @var{num} is equal to parameter @code{value} in options @var{opt} (default is 3).
+ at end deftypefn
+
+
+ at anchor{surfa}
+ at deftypefn {MGL command} {} surfa zdat cdat ['sch'='']
+ at deftypefnx {MGL command} {} surfa xdat ydat zdat cdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SurfA (@code{const mglDataA &}z, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SurfA (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_surfa (@code{HMGL} gr, @code{HCDT} z, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_surfa_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws surface specified parametrically @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@} and transparent it by matrix @var{c}[i,j]. If string @var{sch} have symbol @samp{#} then grid lines are drawn. If string @var{sch} have symbol @samp{.} then plot by dots is produced. All dimensions of arrays @var{z} and @var{c} must be equal. Surface is plotted for each z slice of the data. See also @ref{surf}, @ref{surfc}, @ref{surfca}, @ref{surf3a}. @sref{SurfA sample}
+ at end deftypefn
+
+ at anchor{surf3a}
+ at deftypefn {MGL command} {} surf3a adat cdat @code{val} ['sch'='']
+ at deftypefnx {MGL command} {} surf3a xdat ydat zdat adat cdat @code{val} ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Surf3A (@code{mreal} val, @code{const mglDataA &}a, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Surf3A (@code{mreal} val, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_surf3a_val (@code{HMGL} gr, @code{mreal} val, @code{HCDT} a, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_surf3a_xyz_val (@code{HMGL} gr, @code{mreal} val, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws isosurface plot for 3d array specified parametrically @var{a}[i,j,k](@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]) at @var{a}(x,y,z)=@var{val}. It is mostly the same as @ref{surf3} function but the transparency of isosurface depends on values of array @var{c}. If string @var{sch} contain @samp{#} then wire plot is produced. If string @var{sch} have symbol @samp{.} then plot by dots is produced. See also @ref{surf3}, @ref{surfc}, @ref{surf3a}, @ref{surf3ca}. @sref{Sur [...]
+ at end deftypefn
+
+ at deftypefn {MGL command} {} surf3a adat cdat ['sch'='']
+ at deftypefnx {MGL command} {} surf3a xdat ydat zdat adat cdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Surf3A (@code{const mglDataA &}a, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Surf3A (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_surf3a (@code{HMGL} gr, @code{HCDT} a, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_surf3a_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Draws @var{num}-th uniformly distributed in color range isosurfaces for 3d data. At this array @var{c} can be vector with values of transparency and @var{num}=@var{c}.nx. In opposite case @var{num} is equal to parameter @code{value} in options @var{opt} (default is 3).
+ at end deftypefn
+
+
+
+ at anchor{surfca}
+ at deftypefn {MGL command} {} surfca zdat cdat adat ['sch'='']
+ at deftypefnx {MGL command} {} surfca xdat ydat zdat cdat adat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SurfCA (@code{const mglDataA &}z, @code{const mglDataA &}c, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} SurfCA (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}c, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_surfca (@code{HMGL} gr, @code{HCDT} z, @code{HCDT} c, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_surfca_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} c, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws surface specified parametrically @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@}, color it by matrix @var{c}[i,j] and transparent it by matrix @var{a}[i,j]. If string @var{sch} have symbol @samp{#} then grid lines are drawn. If string @var{sch} have symbol @samp{.} then plot by dots is produced. All dimensions of arrays @var{z} and @var{c} must be equal. Surface is plotted for each z slice of the data. Note, you can use @ref{map}-like coloring if use @samp{%} in color sch [...]
+ at end deftypefn
+
+ at anchor{surf3ca}
+ at deftypefn {MGL command} {} surf3ca adat cdat bdat @code{val} ['sch'='']
+ at deftypefnx {MGL command} {} surf3ca xdat ydat zdat adat cdat bdat @code{val} ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Surf3CA (@code{mreal} val, @code{const mglDataA &}a, @code{const mglDataA &}c, @code{const mglDataA &}b, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Surf3CA (@code{mreal} val, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const mglDataA &}c, @code{const mglDataA &}b, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_surf3ca_val (@code{HMGL} gr, @code{mreal} val, @code{HCDT} a, @code{HCDT} c, @code{HCDT} b, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_surf3ca_xyz_val (@code{HMGL} gr, @code{mreal} val, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{HCDT} c, @code{HCDT} b, at code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws isosurface plot for 3d array specified parametrically @var{a}[i,j,k](@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]) at @var{a}(x,y,z)=@var{val}. It is mostly the same as @ref{surf3} function but the color and the transparency of isosurface depends on values of array @var{c} and @var{b} correspondingly. If string @var{sch} contain @samp{#} then wire plot is produced. If string @var{sch} have symbol @samp{.} then plot by dots is produced. Note, you can use @ref{map}-lik [...]
+ at end deftypefn
+
+ at deftypefn {MGL command} {} surf3ca adat cdat bdat ['sch'='']
+ at deftypefnx {MGL command} {} surf3ca xdat ydat zdat adat cdat bdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Surf3CA (@code{const mglDataA &}a, @code{const mglDataA &}c, @code{const mglDataA &}b, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Surf3CA (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const mglDataA &}c, @code{const mglDataA &}b, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_surf3ca (@code{HMGL} gr, @code{HCDT} a, @code{HCDT} c, @code{HCDT} b, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_surf3ca_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{HCDT} c, @code{HCDT} b, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Draws @var{num}-th uniformly distributed in color range isosurfaces for 3d data. Here parameter @var{num} is equal to parameter @code{value} in options @var{opt} (default is 3).
+ at end deftypefn
+
+ at anchor{tiles}
+ at deftypefn {MGL command} {} tiles zdat rdat ['sch'='']
+ at deftypefnx {MGL command} {} tiles xdat ydat zdat rdat ['sch'='']
+ at deftypefnx {MGL command} {} tiles xdat ydat zdat rdat cdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} TileS (@code{const mglDataA &}z, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} TileS (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}r, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} TileS (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}r, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_tiles (@code{HMGL} gr, @code{HCDT} z, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_tiles_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} r, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_tiles_xyc (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} r, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws horizontal tiles for surface specified parametrically @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@} and color it by matrix @var{c}[i,j]. It is mostly the same as @ref{tile} but the size of tiles is determined by @var{r} array. If string @var{sch} contain style @samp{x} or @samp{y} then tiles will be oriented perpendicular to x- or y-axis. This is some kind of ``transparency'' useful for exporting to EPS files. Tiles is plotted for each z slice of the data. See also @ref [...]
+ at end deftypefn
+
+ at anchor{map}
+ at deftypefn {MGL command} {} map udat vdat ['sch'='']
+ at deftypefnx {MGL command} {} map xdat ydat udat vdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Map (@code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Map (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_map (@code{HMGL} gr, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_map_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws mapping plot for matrices @{@var{ax}, @var{ay} @} which parametrically depend on coordinates @var{x}, @var{y}. The initial position of the cell (point) is marked by color. Height is proportional to Jacobian(ax,ay). This plot is like Arnold diagram ??? If string @var{sch} contain symbol @samp{.} then the color ball at matrix knots are drawn otherwise face is drawn. @sref{Mapping visualization}
+ at end deftypefn
+
+ at anchor{stfa}
+ at deftypefn {MGL command} {} stfa re im @code{dn} ['sch'='']
+ at deftypefnx {MGL command} {} stfa xdat ydat re im @code{dn} ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} STFA (@code{const mglDataA &}re, @code{const mglDataA &}im, @code{int} dn, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} STFA (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}re, @code{const mglDataA &}im, @code{int} dn, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_stfa (@code{HMGL} gr, @code{HCDT} re, @code{HCDT} im, @code{int} dn, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_stfa_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} re, @code{HCDT} im, @code{int} dn, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Draws spectrogram of complex array @var{re}+i*@var{im} for Fourier size of @var{dn} points at plane @var{z} equal to minimal z-axis value. For example in 1D case, result is density plot of data @math{res[i,j]=|\sum_d^dn exp(I*j*d)*(re[i*dn+d]+I*im[i*dn+d])|/dn} with size @{int(nx/dn), dn, ny@}. At this array @var{re}, @var{im} parametrically depend on coordinates @var{x}, @var{y}. The size of @var{re} and @var{im} must be the same. The minor dimensions of arrays @var{x}, @var{y}, @var{re [...]
+ at end deftypefn
+
+
+ at c ##################################################################
+ at external{}
+ at node Vector fields, Other plotting, Dual plotting, MathGL core
+ at section Vector fields
+ at nav{}
+ at cindex Traj
+ at cindex Vect
+ at cindex Dew
+ at cindex Flow
+ at cindex FlowP
+ at cindex Pipe
+
+These functions perform plotting of 2D and 3D vector fields. There are 5 generally different types of vector fields representations: simple vector field (Vect), vectors along the curve (Traj), vector field by dew-drops (Dew), flow threads (Flow, FlowP), flow pipes (Pipe). By default (if absent) values of @var{x}, @var{y}, @var{z} are equidistantly distributed in axis range. The minor dimensions of arrays @var{x}, @var{y}, @var{z}, @var{ax} should be equal. The size of @var{ax}, @var{ay}  [...]
+
+ at anchor{traj}
+ at deftypefn {MGL command} {} traj xdat ydat udat vdat ['sch'='']
+ at deftypefnx {MGL command} {} traj xdat ydat zdat udat vdat wdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Traj (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Traj (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const mglDataA &}az, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_traj_xyz (@code{HMGL} gr, @code{HCDT}x, @code{HCDT}y, @code{HCDT}z, @code{HCDT}ax, @code{HCDT}ay, @code{HCDT}az, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_traj_xy (@code{HMGL} gr, @code{HCDT}x, @code{HCDT}y, @code{HCDT}ax, @code{HCDT}ay, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws vectors @{@var{ax}, @var{ay}, @var{az}@} along a curve @{@var{x}, @var{y}, @var{z}@}. The length of arrows are proportional to @math{\sqrt@{ax^2+ay^2+az^2@}}. String @var{pen} specifies the color (see @ref{Line styles}). By default (@code{pen=""}) color from palette is used (see @ref{Palette and colors}). Option @code{value} set the vector length factor (if non-zero) or vector length to be proportional the distance between curve points (if @code{value=0}). The minor si [...]
+ at end deftypefn
+
+ at anchor{vect}
+ at deftypefn {MGL command} {} vect udat vdat ['sch'='']
+ at deftypefnx {MGL command} {} vect xdat ydat udat vdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Vect (@code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Vect (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_vect_2d (@code{HMGL} gr, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_vect_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws plane vector field plot for the field @{@var{ax}, @var{ay}@} depending parametrically on coordinates @var{x}, @var{y} at level @var{z} equal to minimal z-axis value. The length and color of arrows are proportional to @math{\sqrt@{ax^2+ay^2@}}. The number of arrows depend on @ref{meshnum}. The appearance of the hachures (arrows) can be changed by symbols:
+ at itemize @bullet
+ at item
+ at samp{f} for drawing arrows with fixed lengths,
+ at item
+ at samp{>}, @samp{<} for drawing arrows to or from the cell point (default is centering),
+ at item
+ at samp{.} for drawing hachures with dots instead of arrows,
+ at item
+ at samp{=} for enabling color gradient along arrows.
+ at end itemize
+See also @ref{flow}, @ref{dew}. @sref{Vect sample}
+ at end deftypefn
+
+ at deftypefn {MGL command} {} vect udat vdat wdat ['sch'='']
+ at deftypefnx {MGL command} {} vect xdat ydat zdat udat vdat wdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Vect (@code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const mglDataA &}az, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Vect (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const mglDataA &}az, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_vect_3d (@code{HMGL} gr, @code{HCDT} ax, @code{HCDT} ay, @code{HCDT} az, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_vect_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} ax, @code{HCDT} ay, @code{HCDT} az, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+This is 3D version of the first functions. Here arrays @var{ax}, @var{ay}, @var{az} must be 3-ranged tensors with equal sizes and the length and color of arrows is proportional to @math{\sqrt@{ax^2+ay^2+az^2@}}.
+ at end deftypefn
+
+ at anchor{vect3}
+ at deftypefn {MGL command} {} vect3 udat vdat wdat ['sch'='' sval]
+ at deftypefnx {MGL command} {} vect3 xdat ydat zdat udat vdat wdat ['sch'='' sval]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Vect3 (@code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const mglDataA &}az, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Vect3 (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const mglDataA &}az, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_vect3 (@code{HMGL} gr, @code{HCDT} ax, @code{HCDT} ay, @code{HCDT} az, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_vect3_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} ax, @code{HCDT} ay, @code{HCDT} az, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at end ifclear
+The function draws 3D vector field plot for the field @{@var{ax}, @var{ay}, @var{az}@} depending parametrically on coordinates @var{x}, @var{y}, @var{z}. Vector field is drawn at slice @var{sVal} in direction @{@samp{x}, @samp{y}, @samp{z}@} if @var{sch} contain corresponding symbol (by default, @samp{y} direction is used). The length and color of arrows are proportional to @math{\sqrt@{ax^2+ay^2+az^2@}}. The number of arrows depend on @ref{meshnum}. The appearance of the hachures (arrow [...]
+ at itemize @bullet
+ at item
+ at samp{f} for drawing arrows with fixed lengths,
+ at item
+ at samp{>}, @samp{<} for drawing arrows to or from the cell point (default is centering),
+ at item
+ at samp{.} for drawing hachures with dots instead of arrows,
+ at item
+ at samp{=} for enabling color gradient along arrows.
+ at end itemize
+See also @ref{vect}, @ref{flow}, @ref{dew}. @sref{Vect3 sample}
+ at end deftypefn
+
+ at anchor{dew}
+ at deftypefn {MGL command} {} dew udat vdat ['sch'='']
+ at deftypefnx {MGL command} {} dew xdat ydat udat vdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Dew (@code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Dew (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_dew (@code{HMGL} gr, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_dew_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws dew-drops for plane vector field @{@var{ax}, @var{ay}@} depending parametrically on coordinates @var{x}, @var{y} at level @var{z} equal to minimal z-axis value. Note that this is very expensive plot in memory usage and creation time! The color of drops is proportional to @math{\sqrt@{ax^2+ay^2@}}. The number of drops depend on @ref{meshnum}. See also @ref{vect}. @sref{Dew sample}
+ at end deftypefn
+
+ at anchor{flow}
+ at deftypefn {MGL command} {} flow udat vdat ['sch'='']
+ at deftypefnx {MGL command} {} flow xdat ydat udat vdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Flow (@code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Flow (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_flow_2d (@code{HMGL} gr, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_flow_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws flow threads for the plane vector field @{@var{ax}, @var{ay}@} parametrically depending on coordinates @var{x}, @var{y} at level @var{z} equal to minimal z-axis value. Number of threads is proportional to @code{value} option (default is 5). String @var{sch} may contain:
+ at itemize @bullet
+ at item
+color scheme -- up-half (warm) corresponds to normal flow (like attractor), bottom-half (cold) corresponds to inverse flow (like source);
+ at item
+ at samp{#} for starting threads from edges only;
+ at item
+ at samp{*} for starting threads from a 2D array of points inside the data;
+ at item
+ at samp{v} for drawing arrows on the threads;
+ at item
+ at samp{x}, @samp{z} for drawing tapes of normals in x-y and y-z planes correspondingly.
+ at end itemize
+See also @ref{pipe}, @ref{vect}, @ref{tape}, @ref{barwidth}. @sref{Flow sample}
+ at end deftypefn
+
+ at deftypefn {MGL command} {} flow udat vdat wdat ['sch'='']
+ at deftypefnx {MGL command} {} flow xdat ydat zdat udat vdat wdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Flow (@code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const mglDataA &}az, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Flow (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const mglDataA &}az, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_flow_3d (@code{HMGL} gr, @code{HCDT} ax, @code{HCDT} ay, @code{HCDT} az, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_flow_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} ax, @code{HCDT} ay, @code{HCDT} az, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+This is 3D version of the first functions. Here arrays @var{ax}, @var{ay}, @var{az} must be 3-ranged tensors with equal sizes and the color of line is proportional to @math{\sqrt@{ax^2+ay^2+az^2@}}.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} flow @code{x0 y0} udat vdat ['sch'='']
+ at deftypefnx {MGL command} {} flow @code{x0 y0} xdat ydat udat vdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} FlowP (@code{mglPoint} p0, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} FlowP (@code{mglPoint} p0, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_flowp_2d (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_flowp_xy (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{HCDT} x, @code{HCDT} y, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The same as first one (@ref{flow}) but draws single flow thread starting from point @var{p0}=@{@var{x0}, at var{y0}, at var{z0}@}.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} flow @code{x0 y0 z0} udat vdat wdat ['sch'='']
+ at deftypefnx {MGL command} {} flow @code{x0 y0 z0} xdat ydat zdat udat vdat wdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} FlowP (@code{mglPoint} p0, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const mglDataA &}az, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} FlowP (@code{mglPoint} p0, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const mglDataA &}az, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_flowp_3d (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{HCDT} ax, @code{HCDT} ay, @code{HCDT} az, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_flowp_xyz (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} ax, @code{HCDT} ay, @code{HCDT} az, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+This is 3D version of the previous functions.
+ at end deftypefn
+
+ at anchor{grad}
+ at deftypefn {MGL command} {} grad pdat ['sch'='']
+ at deftypefnx {MGL command} {} grad xdat ydat pdat ['sch'='']
+ at deftypefnx {MGL command} {} grad xdat ydat zdat pdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Grad (@code{const mglDataA &}phi, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Grad (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}phi, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Grad (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}phi, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_grad (@code{HMGL} gr, @code{HCDT} phi, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_grad_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} phi, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_grad_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} phi, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws gradient lines for scalar field @var{phi}[i,j] (or @var{phi}[i,j,k] in 3d case) specified parametrically @{@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]@}. Number of lines is proportional to @code{value} option (default is 5). See also @ref{dens}, @ref{cont}, @ref{flow}.
+ at end deftypefn
+
+ at anchor{pipe}
+ at deftypefn {MGL command} {} pipe udat vdat ['sch'='' @code{r0=0.05}]
+ at deftypefnx {MGL command} {} pipe xdat ydat udat vdat ['sch'='' @code{r0=0.05}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Pipe (@code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{mreal} r0=@code{0.05}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Pipe (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{mreal} r0=@code{0.05}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_pipe_2d (@code{HMGL} gr, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{mreal} r0, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_pipe_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{mreal} r0, @code{const char *}opt)
+ at end ifclear
+The function draws flow pipes for the plane vector field @{@var{ax}, @var{ay}@} parametrically depending on coordinates @var{x}, @var{y} at level @var{z} equal to minimal z-axis value. Number of pipes is proportional to @code{value} option (default is 5). If @samp{#} symbol is specified then pipes start only from edges of axis range. The color of lines is proportional to @math{\sqrt@{ax^2+ay^2@}}. Warm color corresponds to normal flow (like attractor). Cold one corresponds to inverse flo [...]
+ at end deftypefn
+
+ at deftypefn {MGL command} {} pipe udat vdat wdat ['sch'='' @code{r0=0.05}]
+ at deftypefnx {MGL command} {} pipe xdat ydat zdat udat vdat wdat ['sch'='' @code{r0=0.05}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Pipe (@code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const mglDataA &}az, @code{const char *}sch=@code{""}, @code{mreal} r0=@code{0.05}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Pipe (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const mglDataA &}az, @code{const char *}sch=@code{""}, @code{mreal} r0=@code{0.05}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_pipe_3d (@code{HMGL} gr, @code{HCDT} ax, @code{HCDT} ay, @code{HCDT} az, @code{const char *}sch, @code{mreal} r0, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_pipe_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} ax, @code{HCDT} ay, @code{HCDT} az, @code{const char *}sch, @code{mreal} r0, @code{const char *}opt)
+ at end ifclear
+This is 3D version of the first functions. Here arrays @var{ax}, @var{ay}, @var{az} must be 3-ranged tensors with equal sizes and the color of line is proportional to @math{\sqrt@{ax^2+ay^2+az^2@}}.
+ at end deftypefn
+
+
+ at c ##################################################################
+ at external{}
+ at node Other plotting, Nonlinear fitting, Vector fields, MathGL core
+ at section Other plotting
+ at nav{}
+ at cindex DensXYZ
+ at cindex ContXYZ
+ at cindex ContFXYZ
+ at cindex Dots
+ at cindex Crust
+ at cindex TriPlot
+ at cindex TriCont
+ at cindex QuadPlot
+ at cindex FPlot
+ at cindex FSurf
+
+These functions perform miscellaneous plotting. There is unstructured data points plots (Dots), surface reconstruction (Crust), surfaces on the triangular or quadrangular mesh (TriPlot, TriCont, QuadPlot), textual formula plotting (Plots by formula), data plots at edges (Dens[XYZ], Cont[XYZ], ContF[XYZ]). Each type of plotting has similar interface. There are 2 kind of versions which handle the arrays of data and coordinates or only single data array. Parameters of color scheme are speci [...]
+
+ at anchor{densz} @anchor{densy} @anchor{densx} @anchor{DensXYZ}
+ at deftypefn {MGL command} {} densx dat ['sch'='' @code{sval=nan}]
+ at deftypefnx {MGL command} {} densy dat ['sch'='' @code{sval=nan}]
+ at deftypefnx {MGL command} {} densz dat ['sch'='' @code{sval=nan}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} DensX (@code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} DensY (@code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} DensZ (@code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_dens_x (@code{HMGL} gr, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_dens_y (@code{HMGL} gr, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_dens_z (@code{HMGL} gr, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at end ifclear
+These plotting functions draw density plot in x, y, or z plain. If @var{a} is a tensor (3-dimensional data) then interpolation to a given @var{sVal} is performed. These functions are useful for creating projections of the 3D data array to the bounding box. See also @ref{ContXYZ}, @ref{ContFXYZ}, @ref{dens}, @ref{Data manipulation}. @sref{Dens projection sample}
+ at end deftypefn
+
+ at anchor{contz} @anchor{conty} @anchor{contx} @anchor{ContXYZ}
+ at deftypefn {MGL command} {} contx dat ['sch'='' @code{sval=nan}]
+ at deftypefnx {MGL command} {} conty dat ['sch'='' @code{sval=nan}]
+ at deftypefnx {MGL command} {} contz dat ['sch'='' @code{sval=nan}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContX (@code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContY (@code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContZ (@code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_cont_x (@code{HMGL} gr, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_cont_y (@code{HMGL} gr, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_cont_z (@code{HMGL} gr, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at end ifclear
+These plotting functions draw contour lines in x, y, or z plain. If @var{a} is a tensor (3-dimensional data) then interpolation to a given @var{sVal} is performed. These functions are useful for creating projections of the 3D data array to the bounding box. Option @code{value} set the number of contours. See also @ref{ContFXYZ}, @ref{DensXYZ}, @ref{cont}, @ref{Data manipulation}. @sref{Cont projection sample}
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Method on @code{mglGraph}} @code{void} ContX (@code{const mglDataA &}v, @code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContY (@code{const mglDataA &}v, @code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContZ (@code{const mglDataA &}v, @code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_cont_x_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_cont_y_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_cont_z_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+The same as previous with manual contour levels.
+ at end deftypefn
+ at end ifclear
+
+ at anchor{contfz} @anchor{contfy} @anchor{contfx} @anchor{ContFXYZ}
+ at deftypefn {MGL command} {} contfx dat ['sch'='' @code{sval=nan}]
+ at deftypefnx {MGL command} {} contfy dat ['sch'='' @code{sval=nan}]
+ at deftypefnx {MGL command} {} contfz dat ['sch'='' @code{sval=nan}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContFX (@code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContFY (@code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContFZ (@code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_contf_x (@code{HMGL} gr, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_contf_y (@code{HMGL} gr, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_contf_z (@code{HMGL} gr, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at end ifclear
+These plotting functions draw solid contours in x, y, or z plain. If @var{a} is a tensor (3-dimensional data) then interpolation to a given @var{sVal} is performed. These functions are useful for creating projections of the 3D data array to the bounding box. Option @code{value} set the number of contours. See also @ref{ContFXYZ}, @ref{DensXYZ}, @ref{cont}, @ref{Data manipulation}. @sref{ContF projection sample}
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Method on @code{mglGraph}} @code{void} ContFX (@code{const mglDataA &}v, @code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContFY (@code{const mglDataA &}v, @code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} ContFZ (@code{const mglDataA &}v, @code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_contf_x_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_contf_y_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_contf_z_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+The same as previous with manual contour levels.
+ at end deftypefn
+ at end ifclear
+
+ at anchor{fplot}
+ at deftypefn {MGL command} {} fplot 'y(x)' ['pen'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} FPlot (@code{const char *}eqY, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_fplot (@code{HMGL} gr, @code{const char *}eqY, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Draws command function @samp{y(x)} at plane @var{z} equal to minimal z-axis value, where @samp{x} variable is changed in @code{xrange}. You do not need to create the data arrays to plot it. Option @code{value} set initial number of points.  See also @ref{plot}.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} fplot 'x(t)' 'y(t)' 'z(t)' ['pen'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} FPlot (@code{const char *}eqX, @code{const char *}eqY, @code{const char *}eqZ, @code{const char *}pen, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_fplot_xyz (@code{HMGL} gr, @code{const char *}eqX, @code{const char *}eqY, @code{const char *}eqZ, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Draws command parametrical curve @{@samp{x(t)}, @samp{y(t)}, @samp{z(t)}@} where @samp{t} variable is changed in range [0, 1]. You do not need to create the data arrays to plot it. Option @code{value} set number of points. See also @ref{plot}.
+ at end deftypefn
+
+ at anchor{fsurf}
+ at deftypefn {MGL command} {} fsurf 'z(x,y)' ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} FSurf (@code{const char *}eqZ, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""});
+ at deftypefnx {C function} @code{void} mgl_fsurf (@code{HMGL} gr, @code{const char *}eqZ, @code{const char *}sch, @code{const char *}opt);
+ at end ifclear
+Draws command surface for function @samp{z(x,y)} where @samp{x}, @samp{y} variable are changed in @code{xrange, yrange}. You do not need to create the data arrays to plot it. Option @code{value} set number of points. See also @ref{surf}.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} fsurf 'x(u,v)' 'y(u,v)' 'z(u,v)' ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} FSurf (@code{const char *}eqX, @code{const char *}eqY, @code{const char *}eqZ, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_fsurf_xyz (@code{HMGL} gr, @code{const char *}eqX, @code{const char *}eqY, @code{const char *}eqZ, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Draws command parametrical surface @{@samp{x(u,v)}, @samp{y(u,v)}, @samp{z(u,v)}@} where @samp{u}, @samp{v} variable are changed in range [0, 1]. You do not need to create the data arrays to plot it. Option @code{value} set number of points. See also @ref{surf}.
+ at end deftypefn
+
+ at anchor{triplot}
+ at deftypefn {MGL command} {} triplot idat xdat ydat ['sch'='']
+ at deftypefnx {MGL command} {} triplot idat xdat ydat zdat ['sch'='']
+ at deftypefnx {MGL command} {} triplot idat xdat ydat zdat cdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} TriPlot (@code{const mglDataA &}id, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} TriPlot (@code{const mglDataA &}id, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} TriPlot (@code{const mglDataA &}id, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_triplot_xy (@code{HMGL} gr, @code{HCDT} id, @code{HCDT} x, @code{HCDT} y, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_triplot_xyz (@code{HMGL} gr, @code{HCDT} id, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_triplot_xyzc (@code{HMGL} gr, @code{HCDT} id, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws the surface of triangles. Triangle vertexes are set by indexes @var{id} of data points @{@var{x}[i], @var{y}[i], @var{z}[i]@}. String @var{sch} sets the color scheme. If string contain @samp{#} then wire plot is produced. First dimensions of @var{id} must be 3 or greater. Arrays @var{x}, @var{y}, @var{z} must have equal sizes. Parameter @var{c} set the colors of triangles (if @var{id}.ny=@var{c}.nx) or colors of vertexes (if @var{x}.nx=@var{c}.nx). See also @ref{dots}, [...]
+ at end deftypefn
+
+ at anchor{tricont}
+ at deftypefn {MGL command} {} tricont vdat idat xdat ydat zdat cdat ['sch'='']
+ at deftypefnx {MGL command} {} tricont vdat idat xdat ydat zdat ['sch'='']
+ at deftypefnx {MGL command} {} tricont idat xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} TriCont (@code{const mglDataA &}id, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} TriCont (@code{const mglDataA &}id, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} TriContV (@code{const mglDataA &}v, @code{const mglDataA &}id, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} TriContV (@code{const mglDataA &}v, @code{const mglDataA &}id, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_tricont_xyzc (@code{HMGL} gr, @code{HCDT} id, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_tricont_xyz (@code{HMGL} gr, @code{HCDT} id, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_tricont_xyzcv (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} id, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_tricont_xyzv (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} id, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws contour lines for surface of triangles at @var{z}=@var{v}[k] (or at  @var{z} equal to minimal z-axis value if @var{sch} contain symbol @samp{_}). Triangle vertexes are set by indexes @var{id} of data points @{@var{x}[i], @var{y}[i], @var{z}[i]@}. Contours are plotted for @var{z}[i,j]=@var{v}[k] where @var{v}[k] are values of data array @var{v}. If @var{v} is absent then arrays of option @code{value} elements  equidistantly distributed in color range is used. String @va [...]
+ at end deftypefn
+
+ at anchor{quadplot}
+ at deftypefn {MGL command} {} quadplot idat xdat ydat ['sch'='']
+ at deftypefnx {MGL command} {} quadplot idat xdat ydat zdat ['sch'='']
+ at deftypefnx {MGL command} {} quadplot idat xdat ydat zdat cdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} QuadPlot (@code{const mglDataA &}id, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} QuadPlot (@code{const mglDataA &}id, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} QuadPlot (@code{const mglDataA &}id, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_quadplot_xy (@code{HMGL} gr, @code{HCDT} id, @code{HCDT} x, @code{HCDT} y, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_quadplot_xyz (@code{HMGL} gr, @code{HCDT} id, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_quadplot_xyzc (@code{HMGL} gr, @code{HCDT} id, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws the surface of quadrangles. Quadrangles vertexes are set by indexes @var{id} of data points @{@var{x}[i], @var{y}[i], @var{z}[i]@}. String @var{sch} sets the color scheme. If string contain @samp{#} then wire plot is produced. First dimensions of @var{id} must be 4 or greater. Arrays @var{x}, @var{y}, @var{z} must have equal sizes. Parameter @var{c} set the colors of quadrangles (if @var{id}.ny=@var{c}.nx) or colors of vertexes (if @var{x}.nx=@var{c}.nx). See also @ref [...]
+ at end deftypefn
+
+ at anchor{dots}
+ at deftypefn {MGL command} {} dots xdat ydat zdat ['sch'='']
+ at deftypefnx {MGL command} {} dots xdat ydat zdat adat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Dots (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Dots (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Dots (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}c, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_dots (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_dots_a (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_dots_ca (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} c, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function draws the arbitrary placed points @{@var{x}[i], @var{y}[i], @var{z}[i]@}. String @var{sch} sets the color scheme and kind of marks. If arrays @var{c}, @var{a} are specified then they define colors and transparencies of dots. You can use @ref{tens} plot with style @samp{ .} to draw non-transparent dots with specified colors. Arrays @var{x}, @var{y}, @var{z}, @var{a} must have equal sizes. See also @ref{crust}, @ref{tens}, @ref{mark}, @ref{plot}. @sref{Dots sample}
+ at end deftypefn
+
+ at anchor{crust}
+ at deftypefn {MGL command} {} crust xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Crust (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_crust (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+The function reconstruct and draws the surface for arbitrary placed points @{@var{x}[i], @var{y}[i], @var{z}[i]@}. String @var{sch} sets the color scheme. If string contain @samp{#} then wire plot is produced. Arrays @var{x}, @var{y}, @var{z} must have equal sizes. See also @ref{dots}, @ref{triplot}. @c @sref{Crust sample}
+ at end deftypefn
+
+ at c ##################################################################
+ at external{}
+ at node Nonlinear fitting, Data manipulation, Other plotting, MathGL core
+ at section Nonlinear fitting
+ at nav{}
+ at cindex Fit
+ at cindex FitS
+ at cindex PutsFit
+ at cindex mglFitPnts
+ at cindex Fit2
+ at cindex Fit3
+
+These functions fit data to formula. Fitting goal is to find formula parameters for the best fit the data points, i.e. to minimize the sum @math{\sum_i (f(x_i, y_i, z_i) - a_i)^2/s_i^2}. At this, approximation function @samp{f} can depend only on one argument @samp{x} (1D case), on two arguments @samp{x,y} (2D case) and on three arguments @samp{x,y,z} (3D case). The function @samp{f} also may depend on parameters. Normally the list of fitted parameters is specified by @var{var} string (l [...]
+
+Functions Fit() and FitS() do not draw the obtained data themselves. They fill the data @var{fit} by formula @samp{f} with found coefficients and return it. At this, the @samp{x,y,z} coordinates are equidistantly distributed in the axis range. Number of points in @var{fit} is defined by option @code{value} (default is @var{mglFitPnts}=100). Note, that this functions use GSL library and do something only if MathGL was compiled with GSL support. @sref{Nonlinear fitting hints}
+
+ at anchor{fits}
+ at deftypefn {MGL command} {} fits res adat sdat 'func' 'var' [ini=0]
+ at deftypefnx {MGL command} {} fits res xdat adat sdat 'func' 'var' [ini=0]
+ at deftypefnx {MGL command} {} fits res xdat ydat adat sdat 'func' 'var' [ini=0]
+ at deftypefnx {MGL command} {} fits res xdat ydat zdat adat sdat 'func' 'var' [ini=0]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} FitS (@code{const mglDataA &}a, @code{const mglDataA &}s, @code{const char *}func, @code{const char *}var, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} FitS (@code{const mglDataA &}a, @code{const mglDataA &}s, @code{const char *}func, @code{const char *}var, @code{mglData &}ini, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} FitS (@code{const mglDataA &}x, @code{const mglDataA &}a, @code{const mglDataA &}s, @code{const char *}func, @code{const char *}var, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} FitS (@code{const mglDataA &}x, @code{const mglDataA &}a, @code{const mglDataA &}s, @code{const char *}func, @code{const char *}var, @code{mglData &}ini, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} FitS (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}a, @code{const mglDataA &}s, @code{const char *}func, @code{const char *}var, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} FitS (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}a, @code{const mglDataA &}s, @code{const char *}func, @code{const char *}var, @code{mglData &}ini, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} FitS (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const mglDataA &}s, @code{const char *}func, @code{const char *}var, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} FitS (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const mglDataA &}s, @code{const char *}func, @code{const char *}var, @code{mglData &}ini, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{HMDT} mgl_fit_ys (@code{HMGL} gr, @code{HCDT} a, @code{HCDT} s, @code{const char *}func, @code{const char *}var, @code{HMDT} ini, @code{const char *}opt)
+ at deftypefnx {C function} @code{HMDT} mgl_fit_xys (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} a, @code{HCDT} s, @code{const char *}func, @code{const char *}var, @code{HMDT} ini, @code{const char *}opt)
+ at deftypefnx {C function} @code{HMDT} mgl_fit_xyzs (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} a, @code{HCDT} s, @code{const char *}func, @code{const char *}var, @code{HMDT} ini, @code{const char *}opt)
+ at deftypefnx {C function} @code{HMDT} mgl_fit_xyzas (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{HCDT} s, @code{const char *}func, @code{const char *}var, @code{HMDT} ini, @code{const char *}opt)
+ at end ifclear
+Fit data along x-, y- and z-directions for array specified parametrically @var{a}[i,j,k](@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]) with weight factor @var{s}[i,j,k].
+ at end deftypefn
+
+ at anchor{fit}
+ at deftypefn {MGL command} {} fit res adat 'func' 'var' [ini=0]
+ at deftypefnx {MGL command} {} fit res xdat adat 'func' 'var' [ini=0]
+ at deftypefnx {MGL command} {} fit res xdat ydat adat 'func' 'var' [ini=0]
+ at deftypefnx {MGL command} {} fit res xdat ydat zdat adat 'func' 'var' [ini=0]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} Fit (@code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} Fit (@code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{mglData &}ini, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} Fit (@code{const mglDataA &}x, @code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} Fit (@code{const mglDataA &}x, @code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{mglData &}ini, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} Fit (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} Fit (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{mglData &}ini, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} Fit (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} Fit (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{mglData &}ini, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{HMDT} mgl_fit_y (@code{HMGL} gr, @code{HCDT} a, @code{const char *}func, @code{const char *}var, @code{HMDT} ini, @code{const char *}opt)
+ at deftypefnx {C function} @code{HMDT} mgl_fit_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} a, @code{const char *}func, @code{const char *}var, @code{HMDT} ini, @code{const char *}opt)
+ at deftypefnx {C function} @code{HMDT} mgl_fit_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} a, @code{const char *}func, @code{const char *}var, @code{HMDT} ini, @code{const char *}opt)
+ at deftypefnx {C function} @code{HMDT} mgl_fit_xyza (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}func, @code{const char *}var, @code{HMDT} ini, @code{const char *}opt)
+ at end ifclear
+Fit data along x-, y- and z-directions for array specified parametrically @var{a}[i,j,k](@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]) with weight factor 1.
+ at end deftypefn
+
+
+ at ifclear UDAV
+ at deftypefn {Method on @code{mglGraph}} @code{mglData} Fit2 (@code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} Fit2 (@code{mglData &}fit, @code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{mglData &}ini, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} Fit3 (@code{mglData &}fit, @code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} Fit3 (@code{mglData &}fit, @code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{mglData &}ini, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{HMDT} mgl_fit_2 (@code{HMGL} gr, @code{HCDT} a, @code{const char *}func, @code{const char *}var, @code{HMDT} ini, @code{const char *}opt)
+ at deftypefnx {C function} @code{HMDT} mgl_fit_3 (@code{HMGL} gr, @code{HCDT} a, @code{const char *}func, @code{const char *}var, @code{HMDT} ini, @code{const char *}opt)
+Fit data along all directions for 2d or 3d arrays @var{a} with @var{s}=1 and @var{x}, @var{y}, @var{z} equidistantly distributed in axis range.
+ at end deftypefn
+ at end ifclear
+
+ at anchor{putsfit}
+ at deftypefn {MGL command} {} putsfit @code{x y} ['pre'='' 'fnt'='' @code{size=-1}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} PutsFit (@code{mglPoint} p, @code{const char *}prefix=@code{""}, @code{const char *}font=@code{""}, @code{mreal} size=@code{-1})
+ at deftypefnx {C function} @code{void} mgl_puts_fit (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{const char *}prefix, @code{const char *}font, @code{mreal} size)
+ at end ifclear
+Print last fitted formula with found coefficients (as numbers) at position @var{p0}. The string @var{prefix} will be printed before formula. All other parameters are the same as in @ref{Text printing}.
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Method on @code{mglGraph}} @code{const char *}GetFit ()
+ at deftypefnx {C function only} @code{const char *} mgl_get_fit (@code{HMGL} gr)
+ at deftypefnx {Fortran subroutine} @code{} mgl_get_fit (@code{long} gr, @code{char *}out, @code{int} len)
+Get last fitted formula with found coefficients (as numbers).
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{mreal} GetFitChi ()
+ at deftypefnx {C function} @code{mreal} mgl_get_fit_chi ()
+Get \chi for last fitted formula.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglGraph}} @code{mreal} GetFitCovar ()
+ at deftypefnx {C function} @code{mreal} mgl_get_fit_covar ()
+Get covariance matrix for last fitted formula.
+ at end deftypefn
+ at end ifclear
+
+
+ at c ##################################################################
+ at external{}
+ at node Data manipulation, , Nonlinear fitting, MathGL core
+ at section Data manipulation
+ at nav{}
+ at cindex Hist
+ at cindex Fill
+ at cindex DataGrid
+
+ at deftypefn {MGL command} {} hist @sc{res} xdat adat
+ at deftypefnx {MGL command} {} hist @sc{res} xdat ydat adat
+ at deftypefnx {MGL command} {} hist @sc{res} xdat ydat zdat adat
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} Hist (@code{const mglDataA &}x, @code{const mglDataA &}a, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} Hist (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}a, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} Hist (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{HMDT} mgl_hist_x (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} a, @code{const char *}opt)
+ at deftypefnx {C function} @code{HMDT} mgl_hist_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} a, @code{const char *}opt)
+ at deftypefnx {C function} @code{HMDT} mgl_hist_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}opt)
+ at end ifclear
+These functions make distribution (histogram) of data. They do not draw the obtained data themselves. These functions can be useful if user have data defined for random points (for example, after PIC simulation) and he want to produce a plot which require regular data (defined on grid(s)). The range for grids is always selected as axis range. Arrays @var{x}, @var{y}, @var{z} define the positions (coordinates) of random points. Array @var{a} define the data value. Number of points in outp [...]
+ at end deftypefn
+
+
+ at deftypefn {MGL command} {} fill dat 'eq'
+ at deftypefnx {MGL command} {} fill dat 'eq' vdat
+ at deftypefnx {MGL command} {} fill dat 'eq' vdat wdat
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Fill (@code{mglData &}u, @code{const char *}eq, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Fill (@code{mglData &}u, @code{const char *}eq, @code{const mglDataA &}v, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglGraph}} @code{void} Fill (@code{mglData &}u, @code{const char *}eq, @code{const mglDataA &}v, @code{const mglDataA &}w, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_data_fill_eq (@code{HMGL} gr, @code{HMDT} u, @code{const char *}eq, @code{HCDT}v, @code{HCDT}w, @code{const char *}opt)
+ at end ifclear
+Fills the value of array @samp{u} according to the formula in string @var{eq}. Formula is an arbitrary expression depending  on variables @samp{x}, @samp{y}, @samp{z}, @samp{u}, @samp{v}, @samp{w}. Coordinates @samp{x}, @samp{y}, @samp{z} are supposed to be normalized in axis range. Variable @samp{u} is the original value of the array. Variables @samp{v} and @samp{w} are values of arrays @var{v}, @var{w} which can be @code{NULL} (i.e. can be omitted).
+ at end deftypefn
+
+ at deftypefn {MGL command} {} datagrid dat xdat ydat zdat
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{void} DataGrid (@code{mglData &}u, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_data_grid (@code{HMGL} gr, @code{HMDT} u, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}opt)
+ at end ifclear
+Fills the value of array @samp{u} according to the linear interpolation of triangulated surface, found for arbitrary placed points @samp{x}, @samp{y}, @samp{z}. Interpolation is done at points equidistantly distributed in axis range. NAN value is used for grid points placed outside of triangulated surface. @sref{Making regular data}
+ at end deftypefn
+
+ at deftypefn {MGL command} {} refill dat xdat vdat [sl=-1]
+ at deftypefnx {MGL command} {} refill dat xdat ydat vdat [sl=-1]
+ at deftypefnx {MGL command} {} refill dat xdat ydat zdat vdat
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Refill (@code{mglDataA &}dat, @code{const mglDataA &}x, @code{const mglDataA &}v, @code{long} sl=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglData}} @code{void} Refill (@code{mglDataA &}dat, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}v, @code{long} sl=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglData}} @code{void} Refill (@code{mglDataA &}dat, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}v, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_data_refill_gr (@code{HMGL} gr, @code{HMDT} a, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} v, @code{long} sl, @code{const char *}opt)
+ at end ifclear
+Fills by interpolated values of array @var{v} at the point @{@var{x}, @var{y}, @var{z}@}=@{@code{X[i], Y[j], Z[k]}@} (or @{@var{x}, @var{y}, @var{z}@}=@{@code{X[i,j,k], Y[i,j,k], Z[i,j,k]}@} if @var{x}, @var{y}, @var{z} are not 1d arrays), where @code{X,Y,Z} are equidistantly distributed in axis range and have the same sizes as array @var{dat}. If parameter @var{sl} is 0 or positive then changes will be applied only for slice @var{sl}.
+ at end deftypefn
+
+
+ at deftypefn {MGL command} {} pde @sc{res} 'ham' ini_re ini_im [@code{dz=0.1 k0=100}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglGraph}} @code{mglData} PDE (@code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{mreal} dz=@code{0.1}, @code{mreal} k0=@code{100}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{HMDT} mgl_pde_solve (@code{HMGL} gr, @code{const char *}ham, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{mreal} dz, @code{mreal} k0, @code{const char *}opt)
+ at end ifclear
+Solves equation du/dz = i*k0*@var{ham}(p,q,x,y,z,|u|)[u], where p=-i/k0*d/dx, q=-i/k0*d/dy are pseudo-differential operators. Parameters @var{ini_re}, @var{ini_im} specify real and imaginary part of initial field distribution. Coordinates @samp{x}, @samp{y}, @samp{z} are supposed to be normalized in axis range. Note, that really this ranges are increased by factor 3/2 for purpose of reducing reflection from boundaries. Parameter @var{dz} set the step along evolutionary coordinate z. At t [...]
+ at end deftypefn
+
+ at c ##################################################################
+ at c @external{}
+ at c @node IDTF functions, , Data manipulation, MathGL core
+ at c @section IDTF functions
+ at c @nav{}
+
+ at c These functions provide IDTF specific features. In all other cases they do nothing.
+
+ at c @ifclear UDAV
+
+ at c @deftypefn {Method on @code{mglGraph}} @code{void} VertexColor (@code{bool} enable)
+ at c Enables smooth color change.
+ at c @end deftypefn
+
+ at c @deftypefn {Method on @code{mglGraph}} @code{void} Compression (@code{bool} enable)
+ at c Gives smaller files, but quality degrades.
+ at c @end deftypefn
+
+ at c inline void DoubleSided(bool){}	// NOTE: Add later -- IDTF
+ at c inline void TextureColor(bool){}	// NOTE: Add later -- IDTF
+
+ at c @end ifclear
+
+ at external{}
diff --git a/texinfo/core_ru.texi b/texinfo/core_ru.texi
new file mode 100644
index 0000000..22775a8
--- /dev/null
+++ b/texinfo/core_ru.texi
@@ -0,0 +1,3772 @@
+ at c ------------------------------------------------------------------
+ at chapter Ядро MathGL
+ at nav{}
+ at cindex mglGraph
+
+ at ifset UDAV
+Эта глава посвящена описанию множества команд построения графиков для 1D, 2D и 3D массивов данных. Сюда включены также команды настройки графика, вывода текста и примитивов, рисования осей координат и др. Дополнительную информацию о цвете, шрифтах, стилях линий и формулах можно найти в @ref{General concepts}.
+ at end ifset
+
+ at ifclear UDAV
+Основным классом MathGL является класс @strong{mglGraph}, определённый в @code{#include <mgl2/mgl.h>}. Он включает в себя множество функций для построения графиков от 1D, 2D и 3D массивов. Он также содержит функции вывода текста и построения осей координат. Есть возможность построения в произвольной системе координат, которая  задается строковыми формулами. Все графические функции используют класс mglData (см. @ref{Data processing}) для хранения массивов данных. Это позволяет легко контр [...]
+ at end ifclear
+
+Некоторые возможности MathGL доступны только в новых версиях библиотеки. Для проверки текущей версии MathGL можно использовать следующую функцию.
+ at anchor{version}
+ at deftypefn {Команда MGL} {} version 'ver'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{bool} CheckVersion (@code{const char *}ver) static
+ at deftypefnx {Функция С} @code{int} mgl_check_version (@code{const char *}ver)
+ at end ifclear
+Возвращает нулевое значение если версия MathGL подходит для требуемой в @var{ver}, т.е. если номер основной версии совпадает и "подверсия" больше или равна указанной в @var{ver}.
+ at end deftypefn
+
+ at menu
+* Constructor::
+* Graphics setup::
+* Axis settings::
+* Subplots and rotation::
+* Export picture::
+* Background::
+* Primitives::
+* Text printing::
+* Axis and Colorbar::
+* Legend::
+* 1D plotting::
+* 2D plotting::
+* 3D plotting::
+* Dual plotting::
+* Vector fields::
+* Other plotting::
+* Nonlinear fitting::
+* Data manipulation::
+ at c * IDTF functions::
+ at end menu
+
+ at c ##################################################################
+ at external{}
+ at node Constructor, Graphics setup, , MathGL core
+ at section Создание и удаление графического объекта
+ at nav{}
+
+ at ifclear UDAV
+ at deftypefn {Конструктор класса @code{mglGraph}} {} mglGraph (@code{int} kind=@code{0}, @code{int} width=@code{600}, @code{int} height=@code{400})
+ at deftypefnx {Конструктор класса @code{mglGraph}} {} mglGraph (@code{const mglGraph &}gr)
+ at deftypefnx {Конструктор класса @code{mglGraph}} {} mglGraph (@code{HMGL} gr)
+ at deftypefnx {Функция С} @code{HMGL} mgl_create_graph (@code{int} width, @code{int} height)
+ at deftypefnx {Функция С} @code{HMGL} mgl_create_graph_gl ()
+Создает (или использует созданный) экземпляр класса, производного от @code{mglGraph} (тип @code{HMGL}) с указанными размерами @var{width} и @var{height}. Параметр @var{kind} может иметь следующие значения: @samp{0} -- использовать рисование по умолчанию, @samp{1} -- использовать рисование в OpenGL.
+ at end deftypefn
+
+ at deftypefn {Destructor on @code{mglGraph}} {} ~mglGraph ()
+ at deftypefnx {Функция С} @code{HMGL} mgl_delete_graph (@code{HMGL} gr)
+Удаляет экземпляр класса mglGraph.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{HMGL} Self ()
+Возвращает указатель на используемый объект типа @code{HMGL}.
+ at end deftypefn
+ at end ifclear
+
+ at ifset UDAV
+MGL не требует создания данного типа объектов.
+ at end ifset
+
+ at c ##################################################################
+ at external{}
+ at node Graphics setup, Axis settings, Constructor, MathGL core
+ at section Настройка графика
+ at nav{}
+ at cindex Настройка MathGL
+
+Функции и переменные в этой группе влияют на вид всего рисунка. Соответственно они должны располагаться @emph{перед} вызовом функций непосредственно рисующих графики.
+
+ at anchor{reset}
+ at deftypefn {Команда MGL} {} reset
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} DefaultPlotParam ()
+ at deftypefnx {Функция С} @code{void} mgl_set_def_param (@code{HMGL} gr)
+ at end ifclear
+Устанавливает все настройки по умолчанию и очищает рисунок.
+ at end deftypefn
+
+ at menu
+* Transparency::
+* Lighting::
+* Fog::
+* Default sizes::
+* Cutting::
+* Font settings::
+* Palette and colors::
+* Masks::
+* Error handling::
+* Stop drawing::
+ at end menu
+
+ at c ==================================================================
+ at external{}
+ at node Transparency, Lighting, , Graphics setup
+ at subsection Прозрачность
+ at nav{}
+ at cindex Alpha
+ at ifclear UDAV
+ at cindex SetAlphaDef
+ at cindex SetTranspType
+ at end ifclear
+ at cindex AlphaDef
+ at cindex TranspType
+
+Эти функции и переменные настраивают тип и степень прозрачности поверхностей. Главной является функция @ref{alpha}, которая включает/выключает прозрачность для всего графика. Функция @ref{alphadef} устанавливает величину alpha-канала по умолчанию. Наконец, функция @ref{transptype} задает тип прозрачности. @sref{Transparency and lighting}
+
+ at anchor{alpha}
+ at deftypefn {Команда MGL} {} alpha @code{[val=on]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Alpha (@code{bool} enable)
+ at deftypefnx {Функция С} @code{void} mgl_set_alpha (@code{HMGL} gr, @code{int} enable)
+ at end ifclear
+Включает/выключает прозрачность и возвращает свое предыдущее состояние. По умолчанию прозрачность выключена. Функция включает прозрачность для @emph{всего} рисунка.
+ at end deftypefn
+
+ at anchor{alphadef}
+ at deftypefn {Команда MGL} {} alphadef @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetAlphaDef (@code{mreal} val)
+ at deftypefnx {Функция С} @code{void} mgl_set_alpha_default (@code{HMGL} gr, @code{mreal} alpha)
+ at end ifclear
+Задает значение прозрачности по умолчанию для всех графиков. Значение по умолчанию 0.5.
+ at end deftypefn
+
+ at anchor{transptype}
+ at deftypefn {Команда MGL} {} transptype @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetTranspType (@code{int} type)
+ at deftypefnx {Функция С} @code{void} mgl_set_transp_type (@code{HMGL} gr, @code{int} type)
+ at end ifclear
+Задает тип прозрачности. Допустимые значения:
+ at itemize @bullet
+ at item
+Обычная прозрачность (@samp{0}) -- "закрытые" объекты видны меньше чем закрывающие. Этот режим некорректно отображается в OpenGL (mglGraphGL) для нескольких перекрывающихся поверхностей.
+ at item
+"Стеклянная" прозрачность (@samp{1}) -- закрытые и закрывающие объекты единообразно ослабляют интенсивность света (по RGB каналам).
+ at item
+"Ламповая" прозрачность (@samp{2}) -- закрытые и закрывающие объекты являются источниками дополнительного освещения (рекомендую установить @code{SetAlphaDef(0.3)} или меньше в этом случае).
+ at end itemize
+ at sref{Types of transparency}
+ at end deftypefn
+
+ at c ==================================================================
+ at external{}
+ at node Lighting, Fog, Transparency, Graphics setup
+ at subsection Освещение
+ at nav{}
+ at ifclear UDAV
+ at cindex SetAmbient
+ at cindex AddLight
+ at end ifclear
+ at cindex Light
+ at cindex Ambient
+
+Эти функции настраивают освещение графика. Главная функция @ref{light} включает/выключает освещение графиков построенных после ее вызова (в OpenGL работает сразу для всего рисунка). MathGL  поддерживает до 10 независимых источников света. Но в режиме OpenGL можно использовать только первые 8 из них. Положение, цвет, яркость каждого источника света можно задавать по отдельности. По умолчанию включен только первый (с порядковым номером @code{0}) источник света белого цвета, расположенный с [...]
+
+ at anchor{light}
+ at deftypefn {Команда MGL} {} light @code{[val=on]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{bool} Light (@code{bool} enable)
+ at deftypefnx {Функция С} @code{void} mgl_set_light (@code{HMGL} gr, @code{int} enable)
+ at end ifclear
+Включает/выключает освещение графика и возвращает предыдущее состояние. По умолчанию освещение выключено.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} light @code{num} @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Light (@code{int} n, @code{bool} enable)
+ at deftypefnx {Функция С} @code{void} mgl_set_light_n (@code{HMGL} gr, @code{int} n, @code{int} enable)
+ at end ifclear
+Включает/выключает @var{n}-ый источник света.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} light @code{num xdir ydir zdir} ['col'='w' @code{br=0.5 ap=0}]
+ at deftypefnx {Команда MGL} {} light @code{num xdir ydir zdir xpos ypos zpos} ['col'='w' @code{br=0.5}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} AddLight (@code{int} n, @code{mglPoint} d, @code{char} c=@code{'w'}, @code{mreal} bright=@code{0.5}, @code{mreal} ap=@code{0})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} AddLight (@code{int} n, @code{mglPoint} r, @code{mglPoint} d, @code{char} c=@code{'w'}, @code{mreal} bright=@code{0.5}, @code{mreal} ap=@code{0})
+ at deftypefnx {Функция С} @code{void} mgl_add_light (@code{HMGL} gr, @code{int} n, @code{mreal} dx, @code{mreal} dy, @code{mreal} dz)
+ at deftypefnx {Функция С} @code{void} mgl_add_light_ext (@code{HMGL} gr, @code{int} n, @code{mreal} dx, @code{mreal} dy, @code{mreal} dz, @code{char} c, @code{mreal} bright, @code{mreal} ap)
+ at deftypefnx {Функция С} @code{void} mgl_add_light_loc (@code{HMGL} gr, @code{int} n, @code{mreal} rx, @code{mreal} ry, @code{mreal} rz, @code{mreal} dx, @code{mreal} dy, @code{mreal} dz, @code{char} c, @code{mreal} bright, @code{mreal} ap)
+ at end ifclear
+Добавляет источник света с номером @var{n} в положение @var{p} с цветом @var{c} и яркостью @var{bright}, которая должна быть в диапазоне [0,1]. Если указано положение источника @var{r} и оно не NAN, то источник считается локальным, иначе источник полагается бесконечно удалённым (для более быстрого рисования).
+ at end deftypefn
+
+ at anchor{diffuse}
+ at deftypefn {Команда MGL} {} diffuse @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetDifLight (@code{mreal} bright)
+ at deftypefnx {Функция С} @code{void} mgl_set_difbr (@code{HMGL} gr, @code{mreal} bright)
+ at end ifclear
+Задает яркость диффузного освещения (только для локальных источников света).
+ at end deftypefn
+
+ at anchor{ambient}
+ at deftypefn {Команда MGL} {} ambient @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetAmbient (@code{mreal} bright=@code{0.5})
+ at deftypefnx {Функция С} @code{void} mgl_set_ambbr (@code{HMGL} gr, @code{mreal} bright)
+ at end ifclear
+Задает яркость рассеянного освещения. Значение должно быть в диапазоне [0,1].
+ at end deftypefn
+
+ at anchor{attachlight}
+ at deftypefn {Команда MGL} {} attachlight @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} AttachLight (@code{bool} val)
+ at deftypefnx {Функция С} @code{void} mgl_set_attach_light (@code{HMGL} gr, @code{int} val)
+ at end ifclear
+Задает привязку настроек освещения к @ref{inplot}/@ref{subplot}. Отмечу, что OpenGL и некоторые выходные форматы не поддерживают эту возможность.
+ at end deftypefn
+
+
+ at c ==================================================================
+ at external{}
+ at node Fog, Default sizes, Lighting, Graphics setup
+ at subsection Туман
+ at nav{}
+ at cindex Fog
+
+ at anchor{fog}
+ at deftypefn {Команда MGL} {} fog @code{val [dz=0.25]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Fog (@code{mreal} d, @code{mreal} dz=@code{0.25})
+ at deftypefnx {Функция С} @code{void} mgl_set_fog (@code{HMGL} gr, @code{mreal} d, @code{mreal} dz)
+ at end ifclear
+Имитирует туман на графике. Туман начинается на относительном расстоянии @var{dz} от точки обзора и его плотность растет экспоненциально вглубь по закону ~ 1-exp(- at emph{d*z}). Здесь @emph{z} -- нормализованная на 1 глубина графика. Если @var{d}=@code{0} то туман отсутствует. @sref{Adding fog}
+ at end deftypefn
+
+ at c ==================================================================
+ at external{}
+ at node Default sizes, Cutting, Fog, Graphics setup
+ at subsection Базовые размеры
+ at nav{}
+ at ifclear UDAV
+ at cindex SetBarWidth
+ at cindex SetMarkSize
+ at cindex SetArrowSize
+ at cindex SetMeshNum
+ at cindex SetPlotId
+ at end ifclear
+ at cindex BarWidth
+ at cindex MarkSize
+ at cindex ArrowSize
+ at cindex MeshNum
+
+Эти функции задают величины большинства параметров графика, включая размеры маркеров, стрелок, толщину линий и т.д. Как и любые другие настройки, они подействуют только на графики созданные после изменения настроек.
+
+ at anchor{barwidth}
+ at deftypefn {Команда MGL} {} barwidth @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetBarWidth ( @code{mreal} val)
+ at deftypefnx {Функция С} @code{void} mgl_set_bar_width (@code{HMGL} gr, @code{mreal} val)
+ at end ifclear
+Задает относительный размер прямоугольников в @ref{bars}, @ref{barh}, @ref{boxplot}, @ref{candle}. Значение по умолчанию @code{0.7}.
+ at end deftypefn
+
+ at anchor{marksize}
+ at deftypefn {Команда MGL} {} marksize @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetMarkSize (@code{mreal} val)
+ at deftypefnx {Функция С} @code{void} mgl_set_mark_size (@code{HMGL} gr, @code{mreal} val)
+ at end ifclear
+Задает размер маркеров для @ref{1D plotting}. Значение по умолчанию @code{1}.
+ at end deftypefn
+
+ at anchor{arrowsize}
+ at deftypefn {Команда MGL} {} arrowsize @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetArrowSize (@code{mreal} val)
+ at deftypefnx {Функция С} @code{void} mgl_set_arrow_size (@code{HMGL} gr, @code{mreal} val)
+ at end ifclear
+Задает размер стрелок для @ref{1D plotting}, линий и кривых (см. @ref{Primitives}). Значение по умолчанию @code{1}.
+ at end deftypefn
+
+ at anchor{meshnum}
+ at anchor{MeshNum}
+ at deftypefn {Команда MGL} {} meshnum @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetMeshNum (@code{int} val)
+ at deftypefnx {Функция С} @code{void} mgl_set_meshnum (@code{HMGL} gr, @code{int} num)
+ at end ifclear
+Задает ориентировочное число линий в @ref{mesh}, @ref{fall}, и число стрелок (штрихов) в @ref{vect}, @ref{dew}, и число ячеек в @ref{cloud}, и число маркеров в @ref{plot}, @ref{tens}, @ref{step}, @ref{mark}, @ref{textmark}. По умолчанию (=0) рисуются все линии, стрелки, ячейки и т.д.
+ at end deftypefn
+
+ at anchor{facenum}
+ at deftypefn {Команда MGL} {} facenum @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetFaceNum (@code{int} val)
+ at deftypefnx {Функция С} @code{void} mgl_set_facenum (@code{HMGL} gr, @code{int} num)
+ at end ifclear
+Задает ориентировочное число видимых граней. Может быть использована для ускорения рисования за счет более грубого рисунка. По умолчанию (=0) рисуются все грани.
+ at end deftypefn
+
+ at anchor{plotid}
+ at deftypefn {Команда MGL} {} plotid 'id'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetPlotId (@code{const char *}id)
+ at deftypefnx {Функция С} @code{void} mgl_set_plotid (@code{HMGL} gr, @code{const char *}id)
+ at end ifclear
+Задает имя графика для сохранения в файл (например, в окне FLTK).
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Метод класса @code{mglGraph}} @code{const char *} GetPlotId ()
+ at deftypefnx {Функция С} @code{const char *} mgl_get_plotid (@code{HMGL} gr)
+ at deftypefnx {Fortran процедура} @code{} mgl_get_plotid (@code{long} gr, @code{char *}out, @code{int} len)
+Возвращает имя графика для сохранения в файл (например, в окне FLTK).
+ at end deftypefn
+ at end ifclear
+
+ at anchor{pendelta}
+ at deftypefn {Команда MGL} {} pendelta @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetPenDelta (@code{double} val)
+ at deftypefnx {Функция С} @code{void} mgl_pen_delta (@code{HMGL} gr, @code{double} val)
+ at end ifclear
+Изменяет размытие около линий и текста (по умолчанию 1). Для @var{val}>1 текст и линии более резкие. Для @var{val}<1 текст и линии более размытые.
+ at end deftypefn
+
+ at c ==================================================================
+ at external{}
+ at node Cutting, Font settings, Default sizes, Graphics setup
+ at subsection Обрезание
+ at nav{}
+ at ifclear UDAV
+ at cindex SetCut
+ at cindex SetCutBox
+ at cindex CutOff
+ at end ifclear
+ at cindex Cut
+
+Эти функции задают условия когда точка будет исключена (вырезана) из рисования. Замечу, что все точки со значением(-ями) NAN по одной из координат или амплитуде автоматически исключаются из рисования. @sref{Cutting sample}
+
+ at anchor{cut}
+ at deftypefn {Команда MGL} {} cut @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetCut (@code{bool} val)
+ at deftypefnx {Функция С} @code{void} mgl_set_cut (@code{HMGL} gr, @code{int} val)
+ at end ifclear
+Задает обрезание точек за пределами осей координат. Если @code{true} то такие точки исключаются из рисования (это по умолчанию) иначе они проецируются на ограничивающий прямоугольник.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} cut @code{x1 y1 z1 x2 y2 z2}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetCutBox (@code{mglPoint} p1, @code{mglPoint} p1)
+ at deftypefnx {Функция С} @code{void} mgl_set_cut_box (@code{HMGL} gr, @code{mreal} x1, @code{mreal} y1, @code{mreal} z1, @code{mreal} x2, @code{mreal} y2, @code{mreal} z2)
+ at end ifclear
+Задает границы параллелепипеда внутри которого точки не рисуются. Если границы одинаковы (переменные равны), то параллелепипеда считается пустым.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} cut 'cond'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} CutOff (@code{const char *}cond)
+ at deftypefnx {Функция С} @code{void} mgl_set_cutoff (@code{HMGL} gr, @code{const char *}cond)
+ at end ifclear
+Задает условие обрезания по формуле @var{cond}. Это условие исключает точки из рисования если результат вычисления формулы не равен нулю. Установите аргумент @code{""} для выключения условия обрезания.
+ at end deftypefn
+
+ at c ==================================================================
+ at external{}
+ at node Font settings, Palette and colors, Cutting, Graphics setup
+ at subsection Шрифты
+ at nav{}
+ at ifclear UDAV
+ at cindex SetFontSize
+ at cindex SetFontDef
+ at cindex SetRotatedText
+ at cindex SetFontSizePT
+ at cindex SetFontSizeCM
+ at cindex SetFontSizeIN
+ at cindex LoadFont
+ at cindex CopyFont
+ at cindex RestoreFont
+ at end ifclear
+ at cindex Font
+ at cindex RotateText
+
+ at anchor{font}
+ at deftypefn {Команда MGL} {} font 'fnt' [@code{val=6}]
+Задает стиль и размер шрифта. Вначале используется @samp{:rC} -- прямой шрифт с выравниванием по центру. По умолчанию размер подписей оси координат в 1.4 раза больше. См. также см. @ref{Font styles}.
+ at end deftypefn
+
+ at anchor{rotatetext}
+ at deftypefn {Команда MGL} {} rotatetext @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetRotatedText (@code{bool} val)
+ at deftypefnx {Функция С} @code{void} mgl_set_rotated_text (@code{HMGL} gr, @code{int} val)
+ at end ifclear
+Включает/выключает вращение меток и подписей осей координат вдоль оси.
+ at end deftypefn
+
+ at anchor{loadfont}
+ at deftypefn {Команда MGL} {} loadfont ['name'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} LoadFont (@code{const char *}name, @code{const char *}path=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_load_font (@code{HMGL} gr, @code{const char *}name, @code{const char *}path)
+ at end ifclear
+Загружает начертание шрифта из файла @var{path}/@var{name}. Пустая строка загрузит шрифт по умолчанию.
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} SetFontDef (@code{const char *}fnt)
+ at deftypefnx {Функция С} @code{void} mgl_set_font_def (@code{HMGL} gr, @code{const char *} val)
+Задает стиль шрифта (см. @ref{Text printing}). По умолчанию используется @samp{rC} -- прямой шрифт с выравниванием по центру.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} SetFontSize (@code{mreal} val)
+ at deftypefnx {Функция С} @code{void} mgl_set_font_size (@code{HMGL} gr, @code{mreal} val)
+Задает базовый размер шрифта. По умолчанию размер подписей оси координат в 1.4 раза больше.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} SetFontSizePT (@code{mreal} cm, @code{int} dpi=@code{72})
+Задает размер шрифта в пунктах для заданного DPI (по умолчанию 16 pt для dpi=72).
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglGraph}} @code{inline void} SetFontSizeCM (@code{mreal} cm, @code{int} dpi=@code{72})
+Задает размер шрифта в сантиметрах для заданного DPI (по умолчанию 0.56 см = 16 pt).
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglGraph}} @code{inline void} SetFontSizeIN (@code{mreal} cm, @code{int} dpi=@code{72})
+Задает размер шрифта в дюймах для заданного DPI (по умолчанию 0.22 in = 16 pt).
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} CopyFont (@code{mglGraph *} from)
+ at deftypefnx {Функция С} @code{void} mgl_copy_font (@code{HMGL} gr, @code{HMGL} gr_from)
+Копирует начертание шрифта из другого объекта @code{mglGraph}.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} RestoreFont ()
+ at deftypefnx {Функция С} @code{void} mgl_restore_font (@code{HMGL} gr)
+Восстанавливает начертание шрифта по умолчанию.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} SetDefFont (@code{const char *}name, @code{const char *}path=@code{""}) static
+ at deftypefnx {Функция С} @code{void} mgl_def_font (@code{const char *}name, @code{const char *}path)
+Загружает начертание шрифта по умолчанию (для всех вновь создаваемых HMGL/mglGraph объектов) из файла @var{path}/@var{name}.
+ at end deftypefn
+
+ at end ifclear
+
+ at c ==================================================================
+ at external{}
+ at node Palette and colors, Masks, Font settings, Graphics setup
+ at subsection Палитра и цвета
+ at nav{}
+ at ifclear UDAV
+ at cindex SetPalette
+ at end ifclear
+ at cindex Palette
+
+ at anchor{palette}
+ at deftypefn {Команда MGL} {} palette 'colors'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetPalette (@code{const char *}colors)
+ at deftypefnx {Функция С} @code{void} mgl_set_palette (@code{HMGL} gr, @code{const char *}colors)
+ at end ifclear
+Задает палитру как последовательность цветов. Значение по умолчанию @code{"Hbgrcmyhlnqeup"}, что соответствует цветам: темно серый @samp{H}, синий @samp{b}, зелёный @samp{g}, красный @samp{r}, голубой @samp{c}, малиновый @samp{m}, жёлтый @samp{y}, серый @samp{h}, сине-зелёный  @samp{l}, небесно-голубой @samp{n}, оранжевый @samp{q}, желто-зелёный @samp{e}, сине-фиолетовый @samp{u}, фиолетовый @samp{p}. Палитра в основном используется в 1D графиках (см. @ref{1D plotting}) для кривых с неоп [...]
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} SetDefScheme (@code{const char *}sch)
+ at deftypefnx {Функция С} @code{void} mgl_set_def_sch (@code{HMGL} gr, @code{const char *}sch)
+Устанавливает @var{sch} в качестве цветовой схемы по умолчанию. Начальное значение @code{"BbcyrR"}.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} SetColor (@code{char} id, @code{mreal} r, @code{mreal} g, @code{mreal} b) static
+ at deftypefnx {Функция С} @code{void} mgl_set_color (@code{char} id, @code{mreal} r, @code{mreal} g, @code{mreal} b)
+Задает RGB значения для цвета с заданным @var{id}. Изменения действуют глобально для всех последующих использований данного @var{id}.
+ at end deftypefn
+ at end ifclear
+
+ at anchor{gray}
+ at deftypefn {Команда MGL} {} gray [@code{val=on}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Gray (@code{bool} enable)
+ at deftypefnx {Функция С} @code{void} mgl_set_gray (@code{HMGL} gr, @code{int} enable)
+ at end ifclear
+Включает/выключает вывод графика в оттенках серого.
+ at end deftypefn
+
+ at c ==================================================================
+ at external{}
+ at node Masks, Error handling, Palette and colors, Graphics setup
+ at subsection Маски
+ at nav{}
+ at cindex SetMask
+ at cindex SetMaskAngle
+
+ at anchor{mask}
+ at deftypefn {Команда MGL} {} mask 'id' 'hex'
+ at deftypefnx {Команда MGL} {} mask 'id' hex
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetMask (@code{char} id, @code{const char *}hex)
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetMask (@code{char} id, @code{uint64_t} hex)
+ at deftypefnx {Функция С} @code{void} mgl_set_mask (@code{HMGL} gr, @code{const char *}hex)
+ at deftypefnx {Функция С} @code{void} mgl_set_mask_val (@code{HMGL} gr, @code{uint64_t} hex)
+ at end ifclear
+Задает новую матрицу @var{hex} размером 8*8 для маски с заданным @var{id}. Изменения действуют глобально для всех последующих использований данного @var{id}. Значения по умолчанию (см. @ref{Color scheme}): @samp{-} -- 000000FF00000000, @samp{+} -- 080808FF08080808,	@samp{=} -- 0000FF00FF000000,	@samp{;} -- 0000007700000000, @samp{o} -- 0000182424180000,	@samp{O} -- 0000183C3C180000,	@samp{s} -- 00003C24243C0000,	@samp{S} -- 00003C3C3C3C0000, @samp{~} -- 0000060990600000,	@samp{<} -- 0060 [...]
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} mask angle
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetMaskAngle (@code{int} angle)
+ at deftypefnx {Функция С} @code{void} mgl_set_mask_angle (@code{HMGL} gr, @code{int} angle)
+ at end ifclear
+Задает угол поворота маски в градусах. Отмечу, что символы @samp{\}, @samp{/}, @samp{I} в цветовой схеме задают угол поворота в 45, -45 и 90 градусов соответственно.
+ at end deftypefn
+
+ at c ==================================================================
+ at external{}
+ at node Error handling, Stop drawing , Masks, Graphics setup
+ at subsection Обработка ошибок
+ at nav{}
+ at ifset UDAV
+Все сообщения будут выведены автоматически в специальном окне или в консоли.
+ at end ifset
+ at ifclear UDAV
+ at cindex Message
+ at cindex SetWarn
+ at cindex GetWarn
+
+Обычно вы должны сбросить признак ошибки с помощью @code{SetWarn(0);} перед построением и проверить @code{GetWarnCode()} или @code{Message()} на наличие ошибок после построения. Только последнее предупреждение сохраняется. Замечу, что все предупреждения/ошибки в MathGL не являются критичными -- в худшем из вариантов соответствующий график просто не будет построен. По умолчанию, все предупреждения выводятся в @code{stderr}. Этот вывод можно выключить вызовом @code{mgl_suppress_warn(true);}.
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} SetWarn (@code{int} code, @code{const char *}info=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_set_warn (@code{HMGL} gr, @code{int} code, @code{const char *}info)
+Задает код предупреждения. Обычно вызывается только для очистки предупреждений (@code{SetWarn(0);}) или внутри библиотеки. Текст @var{info} будет добавлен к предупреждениям как есть при @var{code}<0.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{const char *}Message ()
+ at deftypefnx {Функция С} @code{const char *}mgl_get_mess (@code{HMGL} gr)
+ at deftypefnx {Fortran процедура} @code{} mgl_get_mess (@code{long} gr, @code{char *}out, @code{int} len)
+Возвращает текст предупреждений о причине отсутствия графика. Если возвращаемая строка пустая, то сообщений нет.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{int} GetWarn ()
+ at deftypefnx {Функция С} @code{int} mgl_get_warn (@code{HMGL} gr)
+Возвращает код сообщения о причине отсутствия графика. Возможные значения:
+ at table @code
+ at item mglWarnNone=0
+Предупреждений нет
+ at item mglWarnDim
+Неправильные или несовместимые размеры данных
+ at item mglWarnLow
+Размеры данных слишком малы
+ at item mglWarnNeg
+Минимальное значение отрицательно
+ at item mglWarnFile
+Файл не найден или указаны неправильные размерности
+ at item mglWarnMem
+Не достаточно памяти
+ at item mglWarnZero
+Значение данных равно нулю
+ at item mglWarnLeg
+Нет записей в легенде
+ at item mglWarnSlc
+Индекс среза вне данных
+ at item mglWarnCnt
+Число линий уровня меньше или равно нулю
+ at item mglWarnOpen
+Не могу открыть файл
+ at item mglWarnLId
+Light: ID вне допустимых значений
+ at item mglWarnSize
+Setsize: размер(ы) равны нулю или отрицательны
+ at item mglWarnFmt
+Формат не поддерживается
+ at item mglWarnTern
+Диапазоны осей несовместимые
+ at item mglWarnNull
+Указатель равен NULL
+ at item mglWarnSpc
+Не хватает места для графика
+ at item mglScrArg
+Неправильные аргументы команды скрипта MGL
+ at item mglScrCmd
+Неправильная команда в скрипте MGL
+ at item mglScrLong
+Слишком длинная строка в скрипте MGL
+ at item mglScrStr
+Одиночная ' в скрипте MGL
+ at item mglScrTemp
+Изменяется временная переменная в MGL скрипте
+ at end table
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} SuppressWarn (@code{bool} state) static
+ at deftypefnx {Функция С} @code{void} mgl_suppress_warn (@code{int} state)
+Выключает вывод предупреждений в @code{stderr} если @var{state} не ноль.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} SetGlobalWarn (@code{const char *}info) static
+ at deftypefnx {Функция С} @code{void} mgl_set_global_warn (@code{const char *}info)
+Задает предупреждение @var{info}, не привязанное к конкретному объекту рисования.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{const char *} GlobalWarn () static
+ at deftypefnx {Функция С} @code{const char *} mgl_get_global_warn ()
+Возвращает предупреждения, не привязанные к конкретному объекту рисования.
+ at end deftypefn
+
+
+ at end ifclear
+
+ at c ==================================================================
+ at external{}
+ at node Stop drawing, , Error handling, Graphics setup
+ at subsection Остановка рисования
+ at nav{}
+ at ifset UDAV
+Вы можете использовать команду @ref{stop} или соответствующую кнопку панели инструментов для остановки рисования и выполнения скрипта.
+ at end ifset
+ at ifclear UDAV
+ at cindex Stop
+ at cindex NeedStop
+ at cindex SetEventFunc
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} Stop (@code{bool} stop=@code{true})
+ at deftypefnx {Функция С only} @code{void} mgl_ask_stop (@code{HMGL} gr, @code{int} stop)
+Просит остановить рисование если @var{stop} не ноль, иначе сбрасывает флаг остановки.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{bool} NeedStop ()
+ at deftypefnx {Функция С only} @code{void} mgl_need_stop (@code{HMGL} gr)
+Возвращает @code{true} если рисование должно быть остановлено. Также запускает обработку всех отложенных событий в GUI. Пользователь должен вызывать эту функцию время от времени внутри долгих вычислений для плавности отклика GUI.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{bool} SetEventFunc (@code{void (*}func at code{)(void *)}, @code{void *}par=@code{NULL})
+ at deftypefnx {Функция С only} @code{void} mgl_set_event_func (@code{HMGL} gr, @code{void (*}func at code{)(void *)}, @code{void *}par)
+Задает функцию, которая будет вызвана для обработки событий в GUI библиотеке.
+ at end deftypefn
+
+ at end ifclear
+
+
+ at c ==================================================================
+ at external{}
+ at node Axis settings, Subplots and rotation, Graphics setup, MathGL core
+ at section Настройки осей координат
+ at nav{}
+
+Эти функции управляет видом и масштабом осей координат. Перед построением для каждой точки выполняются 3 преобразования: сначала определяется возможность рисования точки (см. @ref{Cutting}), далее применяются формулы перехода к криволинейным координатам и наконец точка отображается. Отмечу, что MathGL выдает предупреждение если масштабы осей координат лежат вне области определения формул преобразования координат.
+
+ at menu
+* Ranges (bounding box)::
+* Curved coordinates::
+* Ticks::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Ranges (bounding box), Curved coordinates, , Axis settings
+ at subsection Масштаб осей координат
+ at nav{}
+ at cindex CRange
+ at cindex XRange
+ at cindex YRange
+ at cindex ZRange
+ at cindex Ranges
+ at cindex Origin
+ at ifclear UDAV
+ at cindex SetRange
+ at cindex SetRanges
+ at cindex SetOrigin
+ at end ifclear
+
+ at anchor{xrange}
+ at anchor{yrange}
+ at anchor{zrange}
+ at anchor{crange}
+ at deftypefn {Команда MGL} {} xrange @code{v1 v2} [@code{add=off}]
+ at deftypefnx {Команда MGL} {} yrange @code{v1 v2} [@code{add=off}]
+ at deftypefnx {Команда MGL} {} zrange @code{v1 v2} [@code{add=off}]
+ at deftypefnx {Команда MGL} {} crange @code{v1 v2} [@code{add=off}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetRange (@code{char} dir, @code{mreal} v1, @code{mreal} v2)
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} AddRange (@code{char} dir, @code{mreal} v1, @code{mreal} v2)
+ at deftypefnx {Функция С} @code{void} mgl_set_range_val (@code{HMGL} gr, @code{char} dir, @code{mreal} v1, @code{mreal} v2)
+ at deftypefnx {Функция С} @code{void} mgl_add_range_val (@code{HMGL} gr, @code{char} dir, @code{mreal} v1, @code{mreal} v2)
+ at end ifclear
+Задает диапазон изменения @samp{x}-, at samp{y}-, at samp{z}-, at samp{c}-координат. Если одно из значений равно @code{NAN}, то оно игнорируется. Параметр @code{add=on} указывает добавлять новый диапазон к существующему (не заменять его). См. также @ref{ranges}.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} xrange dat [@code{add=off}]
+ at deftypefnx {Команда MGL} {} yrange dat [@code{add=off}]
+ at deftypefnx {Команда MGL} {} zrange dat [@code{add=off}]
+ at deftypefnx {Команда MGL} {} crange dat [@code{add=off}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetRange (@code{char} dir, @code{const mglDataA &}dat, @code{bool} add=@code{false})
+ at deftypefnx {Функция С} @code{void} mgl_set_range_dat (@code{HMGL} gr, @code{char} dir, @code{const HCDT} a, @code{int} add)
+ at end ifclear
+Задает диапазон изменения @samp{x}-, at samp{y}-, at samp{z}-, at samp{c}-координат как минимальное и максимальное значение массива @var{dat}. Параметр @code{add=on} указывает добавлять новый диапазон к существующему (не заменять его).
+ at end deftypefn
+
+ at anchor{ranges}
+ at deftypefn {Команда MGL} {} ranges @code{x1 x2 y1 y2 [z1=0 z2=0]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetRanges (@code{mglPoint} p1, @code{mglPoint} p2)
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetRanges (@code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2, @code{mreal} z1=@code{0}, @code{mreal} z2=@code{0})
+ at deftypefnx {Функция С} @code{void} mgl_set_ranges (@code{HMGL} gr, @code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2, @code{mreal} z1, @code{mreal} z2)
+ at end ifclear
+Задает диапазон изменения координат. Если минимальное и максимальное значение координаты равны, то они игнорируются по данному направлению. Также устанавливает размер цветовой шкалы, аналогично команде  @code{crange z1 z2}. Начальные диапазоны равны [-1, 1].
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} ranges @code{xx yy [zz cc=zz]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetRanges (@code{const mglDataA &}xx, @code{const mglDataA &}yy)
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetRanges (@code{const mglDataA &}xx, @code{const mglDataA &}yy, @code{const mglDataA &}zz)
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetRanges (@code{const mglDataA &}xx, @code{const mglDataA &}yy, @code{const mglDataA &}zz, @code{const mglDataA &}cc)
+ at end ifclear
+Задает диапазон изменения @samp{x}-, at samp{y}-, at samp{z}-, at samp{c}-координат как минимальное и максимальное значение массивов @var{xx}, @var{yy}, @var{zz}, @var{cc} соответственно.
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} SetAutoRanges (@code{mglPoint} p1, @code{mglPoint} p2)
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetAutoRanges (@code{double} x1, @code{double} x2, @code{double} y1, @code{double} y2, @code{double} z1=@code{0}, @code{double} z2=@code{0}, @code{double} c1=@code{0}, @code{double} c2=@code{0})
+ at deftypefnx {Функция С} @code{void} mgl_set_auto_ranges (@code{HMGL} gr, @code{double} x1, @code{double} x2, @code{double} y1, @code{double} y2, @code{double} z1, @code{double} z2, @code{double} z1, @code{double} z2)
+Задает диапазон изменения координат для автоматических переменных. Если минимальное и максимальное значение координаты равны, то они игнорируются по данному направлению.
+ at end deftypefn
+ at end ifclear
+
+ at anchor{origin}
+ at deftypefn {Команда MGL} {} origin @code{x0 y0 [z0=nan]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetOrigin (@code{mglPoint} p0)
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetOrigin (@code{mreal} x0, @code{mreal} y0, @code{mreal} z0=@code{NAN})
+ at deftypefnx {Функция С} @code{void} mgl_set_origin (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0)
+ at end ifclear
+Задает центр пересечения осей координат. Если одно из значений равно NAN, то MathGL попытается выбрать оптимальное положение осей координат по этому направлению.
+ at end deftypefn
+
+ at anchor{zoomaxis}
+ at deftypefn {Команда MGL} {} zoomaxis @code{x1 x2}
+ at deftypefnx {Команда MGL} {} zoomaxis @code{x1 y1 x2 y2}
+ at deftypefnx {Команда MGL} {} zoomaxis @code{x1 y1 z1 x2 y2 z2}
+ at deftypefnx {Команда MGL} {} zoomaxis @code{x1 y1 z1 c1 x2 y2 z2 c2}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ZoomAxis (@code{mglPoint} p1, @code{mglPoint} p2)
+ at deftypefnx {Функция С} @code{void} mgl_zoom_axis (@code{HMGL} gr, @code{mreal} x1, @code{mreal} y1, @code{mreal} z1, @code{mreal} c1, @code{mreal} x2, @code{mreal} y2, @code{mreal} z2, @code{mreal} c2)
+ at end ifclear
+Дополнительно расширяет диапазон осей координат, задаваемый функциями @code{SetRange} или @code{SetRanges}, в соответствии с формулами @math{min += (max-min)*p1} и @math{max += (max-min)*p1} (или @math{min *= (max/min)^p1} и @math{max *= (max/min)^p1} для "логарифмических" диапазонов, когда @math{inf>max/min>100} или @math{0<max/min<0.01}). Начальные значения [0, 1]. Внимание! эти настройки не могут быть переписаны никакими другими функциями, включая  @code{DefaultPlotParam()}.
+ at end deftypefn
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Curved coordinates, Ticks, Ranges (bounding box), Axis settings
+ at subsection Криволинейные координаты
+ at nav{}
+ at cindex Axis
+ at ifclear UDAV
+ at cindex SetFunc
+ at cindex SetCoor
+ at cindex Ternary
+ at end ifclear
+
+ at deftypefn {Команда MGL} {} axis 'fx' 'fy' 'fz' ['fa'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetFunc (@code{const char *}EqX, @code{const char *}EqY, @code{const char *}EqZ=@code{""}, @code{const char *}EqA=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_set_func (@code{HMGL} gr, @code{const char *}EqX, @code{const char *}EqY, @code{const char *}EqZ, @code{const char *}EqA)
+ at end ifclear
+Задает формулы перехода к криволинейным координатам. Каждая строка является математическим выражением, зависящим от старых координат @samp{x}, @samp{y}, @samp{z} и @samp{a} или @samp{c} для цветовой шкалы. Например, для цилиндрических координат будет @code{SetFunc("x*cos(y)", "x*sin(y)", "z");}. Для удаления формул соответствующий параметр должен быть пустым или @code{NULL}. Использование формул преобразования слегка замедляет программу. Параметр @var{EqA} задает аналогичную формулу для  [...]
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} axis @code{how}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetCoor (@code{int} how)
+ at deftypefnx {Функция С} @code{void} mgl_set_coor (@code{HMGL} gr, @code{int} how)
+ at end ifclear
+Устанавливает одну из предопределенных систем криволинейных координат в зависимости от параметра @var{how}:
+ at table @code
+ at item mglCartesian=0
+декартова система (нет преобразования координат, @{x,y,z@});
+ at item mglPolar=1
+полярные координаты: @{x*cos(y),x*sin(y), z@};
+ at item mglSpherical=2
+сферические координаты: @{x*sin(y)*cos(z), x*sin(y)*sin(z), x*cos(y)@};
+ at item mglParabolic=3
+параболические координаты: @{x*y, (x*x-y*y)/2, z@};
+ at item mglParaboloidal=4
+Paraboloidal coordinates: @{(x*x-y*y)*cos(z)/2, (x*x-y*y)*sin(z)/2, x*y@};
+ at item mglOblate=5
+Oblate coordinates: @{cosh(x)*cos(y)*cos(z), cosh(x)*cos(y)*sin(z), sinh(x)*sin(y)@};
+ at item mglProlate=6
+Prolate coordinates: @{sinh(x)*sin(y)*cos(z), sinh(x)*sin(y)*sin(z), cosh(x)*cos(y)@};
+ at item mglElliptic=7
+эллиптические координаты: @{cosh(x)*cos(y), sinh(x)*sin(y), z@};
+ at item mglToroidal=8
+тороидальные координаты: @{sinh(x)*cos(z)/(cosh(x)-cos(y)), sinh(x)*sin(z)/(cosh(x)-cos(y)), sin(y)/(cosh(x)-cos(y))@};
+ at item mglBispherical=9
+бисферические координаты: @{sin(y)*cos(z)/(cosh(x)-cos(y)), sin(y)*sin(z)/(cosh(x)-cos(y)), sinh(x)/(cosh(x)-cos(y))@};
+ at item mglBipolar=10
+биполярные координаты: @{sinh(x)/(cosh(x)-cos(y)), sin(y)/(cosh(x)-cos(y)), z@};
+ at item mglLogLog=11
+Log-log координаты: @{lg(x), lg(y), lg(z)@};
+ at item mglLogX=12
+Log-x координаты: @{lg(x), y, z@};
+ at item mglLogY=13
+Log-y координаты: @{x, lg(y), z@}.
+ at end table
+ at end deftypefn
+
+ at anchor{ternary}
+ at deftypefn {Команда MGL} {} ternary @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Ternary (@code{int} tern)
+ at deftypefnx {Функция С} @code{void} mgl_set_ternary (@code{HMGL} gr, @code{int} tern)
+ at end ifclear
+Задает рисование треугольных (Ternary, @var{tern}=@code{1}), пирамидальных (Quaternary, @var{tern}=@code{2}) осей координат и проекций осей координат (@var{tern}=@code{4,5,6}).
+
+Ternary -- специальный тип графика для 3 зависимых координат (компонент) @var{a}, @var{b}, @var{c} таких, что @var{a}+ at var{b}+ at var{c}=1. MathGL использует только 2 независимые координаты @var{a}=x и @var{b}=y поскольку их достаточно для построения всех графиков. При этом третья координата z является независимым параметром для построения линий уровня, поверхностей и т.д.
+
+Соответственно Quaternary координаты -- 4 зависимые координаты @var{a}, @var{b}, @var{c} и @var{d}, такие что @var{a}+ at var{b}+ at var{c}+ at var{d}=1. MathGL использует только 2 независимые координаты @var{a}=x, @var{b}=y и @var{d}=z поскольку их достаточно для построения всех графиков.
+
+Проекции строятся если к переменной @var{tern} добавить число @code{4}. Так что @var{tern}=@code{4} нарисует проекции в декартовых координатах, @var{tern}=@code{5} нарисует проекции в треугольных координатах, @var{tern}=@code{6} нарисует проекции в пирамидальных координатах. Если добавить @code{8} вместо @code{4}, то текст не будет выводиться на проекциях.
+
+Используйте @code{Ternary(0)} для возвращения к привычным координатам. @sref{Ternary axis} @sref{Axis projection}
+ at end deftypefn
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Ticks, , Curved coordinates, Axis settings
+ at subsection Метки осей
+ at nav{}
+ at cindex AxisStl
+ at cindex TickLen
+ at cindex Adjust
+ at cindex XTick
+ at cindex YTick
+ at cindex ZTick
+ at cindex CTick
+ at ifclear UDAV
+ at cindex SetAxisStl
+ at cindex SetTickLen
+ at cindex SetTicks
+ at cindex SetTicksVal
+ at cindex SetTuneTicks
+ at cindex SetTickTime
+ at cindex SetTickTempl
+ at cindex SetTickRotate
+ at cindex SetTickSkip
+ at cindex SetOriginTick
+ at cindex AddTick
+ at end ifclear
+
+ at anchor{adjust}
+ at deftypefn {Команда MGL} {} adjust ['dir'='xyzc']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Adjust (@code{const char *}dir=@code{"xyzc"})
+ at deftypefnx {Функция С} @code{void} mgl_adjust_ticks (@code{HMGL} gr, @code{const char *}dir)
+ at end ifclear
+Автоматически задает шаг меток осей, число подметок и начальное положение меток для осей координат @var{dir} в виде наиболее удобном для человека. Также задает @code{SetTuneTicks(true)}. Обычно не требуется вызывать эту функцию кроме случая возвращения настроек по умолчанию.
+ at end deftypefn
+
+ at anchor{xtick}
+ at anchor{ytick}
+ at anchor{ztick}
+ at anchor{ctick}
+ at deftypefn {Команда MGL} {} xtick @code{val [sub=0 org=nan 'fact'='']}
+ at deftypefnx {Команда MGL} {} ytick @code{val [sub=0 org=nan 'fact'='']}
+ at deftypefnx {Команда MGL} {} ztick @code{val [sub=0 org=nan 'fact'='']}
+ at deftypefnx {Команда MGL} {} ctick @code{val [sub=0 org=nan 'fact'='']}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetTicks (@code{char} dir, @code{mreal} d=@code{0}, @code{int} ns=@code{0}, @code{mreal} org=@code{NAN}, @code{const char *}fact=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetTicks (@code{char} dir, @code{mreal} d=@code{0}, @code{int} ns=@code{0}, @code{mreal} org=@code{NAN}, @code{const wchar_t *}fact)
+ at deftypefnx {Функция С} @code{void} mgl_set_ticks (@code{HMGL} gr, @code{char} dir, @code{mreal} d, @code{int} ns, @code{mreal} org)
+ at deftypefnx {Функция С} @code{void} mgl_set_ticks_fact (@code{HMGL} gr, @code{char} dir, @code{mreal} d, @code{int} ns, @code{mreal} org, @code{const char *}fact)
+ at deftypefnx {Функция С} @code{void} mgl_set_ticks_factw (@code{HMGL} gr, @code{char} dir, @code{mreal} d, @code{int} ns, @code{mreal} org, @code{const wchar_t *} fact)
+ at end ifclear
+Задает шаг меток осей @var{d}, число подметок @var{ns} и начальное положение меток @var{org} для оси вдоль направления @var{dir} (используйте 'c' для меток colorbar). Переменная @var{d} задает шаг меток (если положительна) или их число на оси (если отрицательна). Нулевое значение задает автоматическую расстановку меток. Если @var{org}=@code{NAN}, то используется значение из переменной @var{Org}. Параметр @var{fact} задает текст, которые будет напечатан после метки оси (например, "\pi" дл [...]
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} xtick @code{val1} 'lbl1' [@code{val2} 'lbl2' ...]
+ at deftypefnx {Команда MGL} {} ytick @code{val1} 'lbl1' [@code{val2} 'lbl2' ...]
+ at deftypefnx {Команда MGL} {} ztick @code{val1} 'lbl1' [@code{val2} 'lbl2' ...]
+ at deftypefnx {Команда MGL} {} xtick vdat 'lbls' [@code{add=off}]
+ at deftypefnx {Команда MGL} {} ytick vdat 'lbls' [@code{add=off}]
+ at deftypefnx {Команда MGL} {} ztick vdat 'lbls' [@code{add=off}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetTicksVal (@code{char} dir, @code{const char *}lbl, @code{bool} add=@code{false})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetTicksVal (@code{char} dir, @code{const wchar_t *}lbl, @code{bool} add=@code{false})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetTicksVal (@code{char} dir, @code{const mglDataA &}val, @code{const char *}lbl, @code{bool} add=@code{false})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetTicksVal (@code{char} dir, @code{const mglDataA &}val, @code{const wchar_t *}lbl, @code{bool} add=@code{false})
+ at deftypefnx {Функция С} @code{void} mgl_set_ticks_str (@code{HMGL} gr, @code{char} dir, @code{const char *}lbl, @code{bool} add)
+ at deftypefnx {Функция С} @code{void} mgl_set_ticks_wcs (@code{HMGL} gr, @code{char} dir, @code{const wchar_t *}lbl, @code{bool} add)
+ at deftypefnx {Функция С} @code{void} mgl_set_ticks_val (@code{HMGL} gr, @code{char} dir, @code{HCDT} val, @code{const char *}lbl, @code{bool} add)
+ at deftypefnx {Функция С} @code{void} mgl_set_ticks_valw (@code{HMGL} gr, @code{char} dir, @code{HCDT} val, @code{const wchar_t *}lbl, @code{bool} add)
+ at end ifclear
+Задает явное положение @var{val} и подписи @var{lbl} для меток вдоль оси @var{dir}. Если массив @var{val} не указан, то используются значения равно распределённые в диапазоне осей координат. Метки разделяются символом @samp{\n}. Если в команде MGL задано только одно значение, то метка будет @emph{добавлена} к существующим меткам. Используйте @code{SetTicks()} для восстановления автоматических меток.
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} AddTick (@code{char} dir, @code{double} val, @code{const char *}lbl)
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} AddTick (@code{char} dir, @code{double} val, @code{const wchar_t *}lbl)
+ at deftypefnx {Функция С} @code{void} mgl_add_tick (@code{HMGL} gr, @code{char} dir, @code{double} val, @code{const char *}lbl)
+ at deftypefnx {Функция С} @code{void} mgl_set_tickw (@code{HMGL} gr, @code{char} dir, @code{double} val, @code{const wchar_t *}lbl)
+Аналогично предыдущему, но добавляет одну метку оси к списку существующих меток.
+ at end deftypefn
+ at end ifclear
+
+ at deftypefn {Команда MGL} {} xtick 'templ'
+ at deftypefnx {Команда MGL} {} ytick 'templ'
+ at deftypefnx {Команда MGL} {} ztick 'templ'
+ at deftypefnx {Команда MGL} {} ctick 'templ'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetTickTempl (@code{char} dir, @code{const char *}templ)
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetTickTempl (@code{char} dir, @code{const wchar_t *}templ)
+ at deftypefnx {Функция С} @code{void} mgl_set_tick_templ (@code{HMGL} gr, @code{const char *}templ)
+ at deftypefnx {Функция С} @code{void} mgl_set_tick_templw (@code{HMGL} gr, @code{const wchar_t *}templ)
+ at end ifclear
+Задает шаблон @var{templ} для меток вдоль x-,y-,z-оси или colorbar. Шаблон может содержать и символы TeX. Если @var{templ}=@code{""}, то используется шаблон по умолчанию (в простейшем случае @samp{%.2g}). Если шаблон начинается с символа @samp{&}, то будет использовано целое @code{long} вместо типа @code{double}. Установка шаблона выключает автоматическое улучшение вида меток.
+ at end deftypefn
+
+ at anchor{ticktime}
+ at deftypefn {Команда MGL} {} ticktime 'dir' [@code{dv=0} 'tmpl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetTicksTime (@code{char} dir, @code{mreal} val, @code{const char *}templ)
+ at deftypefnx {Функция С} @code{void} mgl_set_ticks_time (@code{HMGL} gr, @code{mreal} val, @code{const char *}templ)
+ at end ifclear
+Задает метки времени с шагом @var{val} и шаблоном @var{templ} для меток вдоль x-,y-,z-оси или colorbar. Шаблон может содержать и символы TeX. Формат шаблона @var{templ} такой же как @url{http://www.manpagez.com/man/3/strftime/}. Наиболее употребительные варианты: @samp{%X} для национального представления времени, @samp{%x} для национального представления даты, @samp{%Y} для года с цифрами столетия. Если @var{val}=0 и/или @var{templ}="", то используется автоматическая расстановка меток и/ [...]
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Функция С} @code{double} mgl_get_time (@code{const char*}str, @code{const char *}templ)
+Возвращает число секунд с 1970 года до даты/времени, указанной в строке @var{str}. Формат строки задается @var{templ}, такой же как @url{http://www.manpagez.com/man/3/strftime/}. Наиболее употребительные варианты: @samp{%X} для национального представления времени, @samp{%x} для национального представления даты, @samp{%Y} для года с цифрами столетия. Отмечу, что MS Visual Studio не может обрабатывать даты до 1970.
+ at end deftypefn
+ at end ifclear
+
+ at anchor{tuneticks}
+ at deftypefn {Команда MGL} {} tuneticks @code{val} [@code{pos=1.15}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetTuneTicks (@code{int} tune, @code{mreal} pos=@code{1.15})
+ at deftypefnx {Функция С} @code{void} mgl_tune_ticks (@code{HMGL} gr, @code{int} tune, @code{mreal} pos)
+ at end ifclear
+Включает/выключает улучшение вида меток осей путем вынесения общего множителя (для маленьких, типа 0.001...0.002, или больших, типа 1000...2000, значений координат) или общей компоненты (для узкого диапазона, типа 0.999...1.000). Также задает положение @var{pos} общего множителя на оси: =0 около минимального значения, =1 около максимального значения.
+ at end deftypefn
+
+ at anchor{tickshift}
+ at deftypefn {Команда MGL} {} tickshift @code{dx [dy=0 dz=0 dc=0]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetTickShift (@code{mglPoint} d)
+ at deftypefnx {Функция С} @code{void} mgl_set_tick_shift (@code{HMGL} gr, @code{mreal} dx, @code{mreal} dy, @code{mreal} dz, @code{mreal} dc)
+ at end ifclear
+Задает значение дополнительного сдвига меток осей координат.
+ at end deftypefn
+
+ at ifclear UDAV
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} SetTickRotate (@code{bool} val)
+ at deftypefnx {Функция С} @code{void} mgl_set_tick_rotate (@code{HMGL} gr, @code{bool} val)
+Включает/выключает поворот меток если их число или длина меток слишком велики.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} SetTickSkip (@code{bool} val)
+ at deftypefnx {Функция С} @code{void} mgl_set_tick_skip (@code{HMGL} gr, @code{bool} val)
+Включает/выключает пропуск меток если их число или длина меток слишком велики.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} SetTimeUTC (@code{bool} val)
+Разрешает/запрещает использование UTC времени в метках осей координат. В C/Fortran следует использовать @code{mgl_set_flag(gr,val, MGL_USE_GMTIME);}.
+ at end deftypefn
+
+ at end ifclear
+
+ at anchor{origintick}
+ at deftypefn {Команда MGL} {} origintick @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetOriginTick (@code{bool} val=@code{true})
+ at end ifclear
+Разрешает/запрещает рисование меток в точке пересечения осей координат. В C/Fortran следует использовать @code{mgl_set_flag(gr,val, MGL_NO_ORIGIN);}.
+ at end deftypefn
+
+ at anchor{ticklen}
+ at deftypefn {Команда MGL} {} ticklen @code{val} [@code{stt=1}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetTickLen (@code{mreal} val, @code{mreal} stt=@code{1})
+ at deftypefnx {Функция С} @code{void} mgl_set_tick_len (@code{HMGL} gr, @code{mreal} val, @code{mreal} stt)
+ at end ifclear
+Задает относительную длину меток осей координат. Значение по умолчанию @code{0.1}. Параметр @var{stt}>0 задает относительную длину подметок, которые в @code{sqrt(1+stt)} раз меньше.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} axisstl 'stl' ['tck'='' 'sub'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetAxisStl (@code{const char *}stl=@code{"k"}, @code{const char *}tck=@code{0}, @code{const char *}sub=@code{0})
+ at deftypefnx {Функция С} @code{void} mgl_set_axis_stl (@code{HMGL} gr, @code{const char *}stl, @code{const char *}tck, @code{const char *}sub)
+ at end ifclear
+Задает стиль осей (@var{stl}), меток (@var{tck}) и подметок (@var{sub}) осей координат. Если @var{stl} пустая или ноль, то используется стиль по умолчанию (@samp{k} или @samp{w} в зависимости от типа прозрачности). Если  @var{tck}, @var{sub} пустая или ноль, то используется стиль осей (т.е. @var{stl}).
+ at end deftypefn
+
+ at c ##################################################################
+ at external{}
+ at node Subplots and rotation, Export picture, Axis settings, MathGL core
+ at section Матрица преобразования
+ at nav{}
+ at cindex Aspect
+ at cindex Rotate
+ at cindex RotateN
+ at cindex SubPlot
+ at cindex MultiPlot
+ at cindex StickPlot
+ at cindex ColumnPlot
+ at cindex InPlot
+ at cindex Title
+ at cindex Perspective
+ at cindex View
+ at cindex Push
+ at cindex Pop
+
+Эти функции контролируют где и как график будет расположен. Существует определенный порядок вызова этих функций для лучшего вида графика. Вначале должны вызываться функции @ref{subplot}, @ref{multiplot} или @ref{inplot} для указания местоположения вывода. После них -- функции вращения @ref{rotate}, @ref{shear} и @ref{aspect}. И наконец любые другие функции для рисования графика. Вместо вращения графика можно вызвать функцию @ref{columnplot}, @ref{gridplot}, @ref{stickplot}, @ref{shearplo [...]
+
+ at anchor{subplot}
+ at deftypefn {Команда MGL} {} subplot @code{nx ny m} ['stl'='<>_^' @code{dx=0 dy=0}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SubPlot (@code{int} nx, @code{int} ny, @code{int} m, @code{const char *}stl=@code{"<>_^"}, @code{mreal} dx=@code{0}, @code{mreal} dy=@code{0})
+ at deftypefnx {Функция С} @code{void} mgl_subplot (@code{HMGL} gr, @code{int} nx, @code{int} ny, @code{int} m, @code{const char *}stl)
+ at deftypefnx {Функция С} @code{void} mgl_subplot_d (@code{HMGL} gr, @code{int} nx, @code{int} ny, @code{int} m, @code{const char *}stl, @code{mreal} dx, @code{mreal} dy)
+ at end ifclear
+Помещает последующий вывод в @var{m}-ую ячейку сетки размером @var{nx}*@var{ny} от всего рисунка. Функция сбрасывает матрицу трансформации (повороты и сжатие графика) и должна вызываться первой для создания "подграфика". С эстетической точки зрения не рекомендуется вызывать эту функцию с различными (или не кратными) размерами сетки. Дополнительное место для осей/colorbar резервируется только если строка @var{stl} содержит: 
+ at itemize @bullet
+ at item
+ at samp{L} или @samp{<} -- с левого края,
+ at item
+ at samp{R} или @samp{>} -- с правого края,
+ at item
+ at samp{A} или @samp{^} -- с верхнего края,
+ at item
+ at samp{U} или @samp{_} -- с нижнего края,
+ at item
+ at samp{#} -- место резервироваться не будет -- оси координат будут занимать все доступное пространство.
+ at end itemize
+Ячейка может быть дополнительно сдвинута относительно своего обычного положения на относительный размер @var{dx}, @var{dy}. Отмечу, что colorbar может находиться за пределами рисунка если выбран пустой стиль @samp{}.
+ at end deftypefn
+
+ at anchor{multiplot}
+ at deftypefn {Команда MGL} {} multiplot @code{nx ny m dx dy} ['style'='<>_^' sx sy]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} MultiPlot (@code{int} nx, @code{int} ny, @code{int} m, @code{int} dx, @code{int} dy, @code{const char *}stl=@code{"<>_^"})
+ at deftypefnx {Функция С} @code{void} mgl_multiplot (@code{HMGL} gr, @code{int} nx, @code{int} ny, @code{int} m, @code{int} dx, @code{int} dy, @code{const char *}stl)
+ at end ifclear
+Помещает последующий вывод в прямоугольник из @var{dx}*@var{dy} ячеек, начиная с @var{m}-ой ячейки, сетки размером @var{nx}*@var{ny} от всего рисунка. Функция сбрасывает матрицу трансформации (повороты и сжатие графика) и должна вызываться первой для создания "подграфика". Дополнительное место для осей/colorbar резервируется если строка @var{stl} содержит:
+ at itemize @bullet
+ at item
+ at samp{L} или @samp{<} -- с левого края,
+ at item
+ at samp{R} или @samp{>} -- с правого края,
+ at item
+ at samp{A} или @samp{^} -- с верхнего края,
+ at item
+ at samp{U} или @samp{_} -- с нижнего края,
+ at item
+ at samp{#} -- место резервироваться не будет -- оси координат будут занимать все доступное пространство.
+ at end itemize
+Область вывода может быть дополнительно сдвинута относительно своего обычного положения на относительный размер @var{sx}, @var{sy}.
+ at end deftypefn
+
+ at anchor{inplot}
+ at deftypefn {Команда MGL} {} inplot @code{x1 x2 y1 y2 [rel=on]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} InPlot (@code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2, @code{bool} rel=@code{true})
+ at deftypefnx {Функция С} @code{void} mgl_inplot (@code{HMGL} gr, @code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2)
+ at deftypefnx {Функция С} @code{void} mgl_relplot (@code{HMGL} gr, @code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2)
+ at end ifclear
+Помещает последующий вывод в прямоугольную область [@var{x1}, @var{x2}]*[@var{y1}, @var{y2}] (исходный размер [0,1]*[0,1]). Эта функция позволяет поместить график в произвольную область рисунка. Если параметр @var{rel}=@code{true}, то используется позиция относительно текущего @ref{subplot} (или @ref{inplot} с @var{rel}=@code{false}). Функция сбрасывает матрицу трансформации (повороты и сжатие графика) и должна вызываться первой для создания "подграфика".
+ at end deftypefn
+
+ at anchor{columnplot}
+ at deftypefn {Команда MGL} {} columnplot @code{num ind [d=0]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ColumnPlot (@code{int} num, @code{int} ind, @code{mreal} d=@code{0})
+ at deftypefnx {Функция С} @code{void} mgl_columnplot (@code{HMGL} gr, @code{int} num, @code{int} ind)
+ at deftypefnx {Функция С} @code{void} mgl_columnplot_d (@code{HMGL} gr, @code{int} num, @code{int} ind, @code{mreal} d)
+ at end ifclear
+Помещает последующий вывод в @var{ind}-ую строку столбца из @var{num} строк. Положение столбца выбирается относительно последнего вызова @ref{subplot} (или @ref{inplot} с @var{rel}=@code{false}). Параметр @var{d} задает дополнительный зазор между строк.
+ at end deftypefn
+
+ at anchor{gridplot}
+ at deftypefn {Команда MGL} {} gridplot @code{nx ny ind [d=0]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} GridPlot (@code{int} nx, @code{int} ny, @code{int} ind, @code{mreal} d=@code{0})
+ at deftypefnx {Функция С} @code{void} mgl_gridplot (@code{HMGL} gr, @code{int} nx, @code{int} ny, @code{int} ind)
+ at deftypefnx {Функция С} @code{void} mgl_gridplot_d (@code{HMGL} gr, @code{int} nx, @code{int} ny, @code{int} ind, @code{mreal} d)
+ at end ifclear
+Помещает последующий вывод в @var{ind}-ую ячейку таблицы @var{nx}*@var{ny}. Положение ячейки выбирается относительно последнего вызова @ref{subplot} (или @ref{inplot} с @var{rel}=@code{false}). Параметр @var{d} задает дополнительный зазор между ячеек.
+ at end deftypefn
+
+ at anchor{stickplot}
+ at deftypefn {Команда MGL} {} stickplot @code{num ind tet phi}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} StickPlot (@code{int} num, @code{int} ind, @code{mreal} tet, @code{mreal} phi)
+ at deftypefnx {Функция С} @code{void} mgl_stickplot (@code{HMGL} gr, @code{int} num, @code{int} ind, @code{mreal} tet, @code{mreal} phi)
+ at end ifclear
+Помещает последующий вывод в @var{ind}-ую ячейку "бруска" из @var{num} ячеек. При этом сам брусок повернут на углы @var{tet}, @var{phi}. Положение выбирается относительно последнего вызова  @ref{subplot} (или @ref{inplot} с @var{rel}=@code{false}).
+ at end deftypefn
+
+ at anchor{shearplot}
+ at deftypefn {Команда MGL} {} shearplot @code{num ind sx sy [xd yd]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ShearPlot (@code{int} num, @code{int} ind, @code{mreal} sx, @code{mreal} sy, @code{mreal} xd=@code{1}, @code{mreal} yd=@code{0})
+ at deftypefnx {Функция С} @code{void} mgl_shearplot (@code{HMGL} gr, @code{int} num, @code{int} ind, @code{mreal} sx, @code{mreal} sy, @code{mreal} xd, @code{mreal} yd)
+ at end ifclear
+Помещает последующий вывод в @var{ind}-ую ячейку "бруска" из @var{num} ячеек. При этом сама ячейка скошена на @var{sx}, @var{sy}. Направление бруска задается переменными @var{xd} и @var{yd}. Положение выбирается относительно последнего вызова  @ref{subplot} (или @ref{inplot} с @var{rel}=@code{false}).
+ at end deftypefn
+
+ at anchor{title}
+ at deftypefn {Команда MGL} {} title 'title' ['stl'='' @code{size=-2}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Title (@code{const char *}txt, @code{const char *}stl=@code{""}, @code{mreal} size=@code{-2})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Title (@code{const wchar_t *}txt, @code{const char *}stl=@code{""}, @code{mreal} size=@code{-2})
+ at deftypefnx {Функция С} @code{void} mgl_title (@code{HMGL} gr, @code{const char *}txt, @code{const char *}stl, @code{mreal} size)
+ at deftypefnx {Функция С} @code{void} mgl_titlew (@code{HMGL} gr, @code{const wchar_t *}txt, @code{const char *}stl, @code{mreal} size)
+ at end ifclear
+Выводит заголовок @var{title} для текущего "подграфика" шрифтом @var{stl} с размером @var{size}. Если строка @var{stl} содержит @samp{#}, то рисуется обрамляющий прямоугольник. Функция сбрасывает матрицу трансформации (повороты и сжатие графика) и должна вызываться сразу после создания "подграфика".
+ at end deftypefn
+
+ at anchor{rotate}
+ at deftypefn {Команда MGL} {} rotate @code{tetx tetz [tety=0]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Rotate (@code{mreal} TetX, @code{mreal} TetZ, @code{mreal} TetY=@code{0})
+ at deftypefnx {Функция С} @code{void} mgl_rotate (@code{HMGL} gr, @code{mreal} TetX, @code{mreal} TetZ, @code{mreal} TetY)
+ at end ifclear
+Вращает систему координат относительно осей @{x, z, y@} последовательно на углы @var{TetX}, @var{TetZ}, @var{TetY}.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} rotate @code{tet x y z}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} RotateN (@code{mreal} Tet, @code{mreal} x, @code{mreal} y, @code{mreal} z)
+ at deftypefnx {Функция С} @code{void} mgl_rotate_vector (@code{HMGL} gr, @code{mreal Tet}, @code{mreal x}, @code{mreal y}, @code{mreal z})
+ at end ifclear
+Вращает систему координат относительно вектора @{@var{x}, @var{y}, @var{z}@} на угол @var{Tet}.
+ at end deftypefn
+
+
+ at anchor{shear}
+ at deftypefn {Команда MGL} {} shear @code{sx sy}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Shear (@code{mreal} sx, @code{mreal} sy)
+ at deftypefnx {Функция С} @code{void} mgl_shear (@code{HMGL} gr, @code{mreal} sx, @code{mreal} sy)
+ at end ifclear
+Сдвигает (скашивает) систему координат на значения @var{sx}, @var{sy}.
+ at end deftypefn
+
+
+ at anchor{aspect}
+ at deftypefn {Команда MGL} {} aspect @code{ax ay [az=1]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Aspect (@code{mreal} Ax, @code{mreal} Ay, @code{mreal} Az=@code{1})
+ at deftypefnx {Функция С} @code{void} mgl_aspect (@code{HMGL} gr, @code{mreal} Ax, @code{mreal} Ay, @code{mreal} Az)
+ at end ifclear
+Устанавливает соотношение размеров осей в отношении @var{Ax:Ay:Az}. Для лучшего вида следует вызывать после функции @ref{rotate}. Если @var{Ax}=@code{NAN}, то функция выберет оптимальное соотношение размеров, чтобы шаг по осям x-y был одинаков. При этом, @var{Ay} задает фактор пропорциональности шага (обычно 1), или указывает на его автоматический выбор при @var{Ay}=@code{NAN}.
+ at end deftypefn
+
+ at ifclear UDAV
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} Push ()
+ at deftypefnx {Функция С} @code{void} mgl_mat_push (@code{HMGL} gr)
+Помещает матрицу преобразования в стек. Позднее вы можете восстановить текущее состояние с помощью функции Pop().
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} Pop ()
+ at deftypefnx {Функция С} @code{void} mgl_mat_pop (@code{HMGL} gr)
+Заменяет (восстанавливает) матрицу преобразования на последнюю помещенную в стек матрицу.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} SetPlotFactor (@code{mreal} val)
+ at deftypefnx {Функция С} @code{void} mgl_set_plotfactor (@code{HMGL} gr, @code{mreal} val)
+Задает масштаб картинки. Не рекомендуется устанавливать значения меньше 1.5. Это аналог функции Zoom(), но применяется только к конкретному подграфику. Используйте ноль для включения автоматического масштабирования.
+ at end deftypefn
+
+ at end ifclear
+
+
+Также есть 3 функции, которые управляют перспективой @code{Perspective()}, масштабированием @code{Zoom()} и вращением @code{View()} всего рисунка. Т.е. они действуют как ещё одна матрица трансформации. Они были введены для вращения/приближения графика с помощью мыши. Не рекомендуется вызывать их при рисовании графика.
+
+ at anchor{perspective}
+ at deftypefn {Команда MGL} {} perspective @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Perspective (@code{mreal} a)
+ at deftypefnx {Функция С} @code{void} mgl_perspective (@code{HMGL} gr, @code{mreal} a)
+ at end ifclear
+Добавляет (включает) перспективу для графика. Параметр @math{a = Depth/(Depth+dz) \in [0,1)}. По умолчанию (@code{a=0}) перспектива отключена.
+ at end deftypefn
+
+ at anchor{view}
+ at deftypefn {Команда MGL} {} view @code{tetx tetz [tety=0]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} View (@code{mreal} TetX, @code{mreal} TetZ, @code{mreal} TetY=@code{0})
+ at deftypefnx {Функция С} @code{void} mgl_view (@code{HMGL} gr, @code{mreal} TetX, @code{mreal} TetZ, @code{mreal} TetY)
+ at end ifclear
+Вращает систему координат относительно осей @{x, z, y@} последовательно на углы @var{TetX}, @var{TetZ}, @var{TetY}. Вращение происходит независимо от @ref{rotate}. Внимание! эти настройки не могут быть переписаны функцией  @code{DefaultPlotParam()}. Используйте @code{Zoom(0,0,1,1)} для возвращения к виду по умолчанию.
+ at end deftypefn
+
+ at anchor{zoom}
+ at deftypefn {Команда MGL} {} zoom @code{x1 y1 x2 y2}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Zoom (@code{mreal} x1, @code{mreal} y1, @code{mreal} x2, @code{mreal} y2)
+ at deftypefnx {Функция С} @code{void} mgl_set_zoom (@code{HMGL} gr, @code{mreal} x1, @code{mreal} y1, @code{mreal} x2, @code{mreal} y2)
+ at end ifclear
+Масштабирует весь рисунок. После вызова функции текущий график будет очищен и в дальнейшем рисунок будет содержать только область [x1,x2]*[y1,y2] от исходного рисунка. Координаты @var{x1}, @var{x2}, @var{y1}, @var{y2} меняются в диапазоне от 0 до 1. Внимание! эти настройки не могут быть переписаны никакими другими функциями, включая  @code{DefaultPlotParam()}. Используйте @code{Zoom(0,0,1,1)} для возвращения к виду по умолчанию.
+ at end deftypefn
+
+ at c ##################################################################
+ at external{}
+ at node Export picture, Background, Subplots and rotation, MathGL core
+ at section Экспорт рисунка
+ at nav{}
+ at cindex SetSize
+
+Функции в этой группе сохраняют или дают доступ к полученному рисунку. Поэтом обычно они должны вызываться в конце рисования.
+
+ at anchor{setsize}
+ at deftypefn {Команда MGL} {} setsize @code{w h}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetSize (@code{int} width, @code{int} height, @code{bool} clear=@code{true})
+ at deftypefnx {Функция С} @code{void} mgl_set_size (@code{HMGL} gr, @code{int} width, @code{int} height)
+ at deftypefnx {Функция С} @code{void} mgl_scale_size (@code{HMGL} gr, @code{int} width, @code{int} height)
+ at end ifclear
+Изменяет размер картинки в пикселях. Функция должна вызываться @strong{перед} любыми функциями построения потому что полностью очищает содержимое рисунка при @var{clear}=@code{true}. Функция только очищает растровый рисунок и масштабирует примитивы при @var{clear}=@code{false}.
+ at end deftypefn
+
+
+ at anchor{setsizescl}
+ at deftypefn {Команда MGL} {} setsizescl @code{factor}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetSizeScl (@code{double} factor)
+ at deftypefnx {Функция С} @code{void} mgl_set_size_scl (@code{HMGL} gr, @code{double} factor)
+ at end ifclear
+Задает множитель для высоты и ширины во всех последующих вызовах @ref{setsize}.
+ at end deftypefn
+
+
+ at anchor{quality}
+ at deftypefn {Команда MGL} {} quality [@code{val}=2]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetQuality (@code{int} val=@code{MGL_DRAW_NORM})
+ at deftypefnx {Функция С} @code{void} mgl_set_quality (@code{HMGL} gr, @code{int} val)
+ at end ifclear
+Задает качество графика в зависимости от значения @var{val}: @code{MGL_DRAW_WIRE=0} -- нет рисования граней (наиболее быстрый), @code{MGL_DRAW_FAST=1} -- нет интерполяции цвета (быстрый), @code{MGL_DRAW_NORM=2} -- высокое качество (нормальный), @code{MGL_DRAW_HIGH=3} -- высокое качество с рисованием 3d примитивов (стрелок и маркеров). Если установлен бит @code{MGL_DRAW_LMEM=0x4}, то происходит прямое рисование в растровое изображение (меньше затраты памяти). Если установлен бит @code{MGL [...]
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Метод класса @code{mglGraph}} @code{int} GetQuality ()
+ at deftypefnx {Функция С} @code{void} mgl_get_quality (@code{HMGL} gr)
+Возвращает качество графика: @code{MGL_DRAW_WIRE=0} -- нет рисования граней (наиболее быстрый), @code{MGL_DRAW_FAST=1} -- нет интерполяции цвета (быстрый), @code{MGL_DRAW_NORM=2} -- высокое качество (нормальный), @code{MGL_DRAW_HIGH=3} -- высокое качество с рисованием 3d примитивов (стрелок и маркеров). Если установлен бит @code{MGL_DRAW_LMEM=0x4}, то происходит прямое рисование в растровое изображение (меньше затраты памяти). Если установлен бит @code{MGL_DRAW_DOTS=0x8}, то рисуются точ [...]
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} StartGroup (const char *name)
+ at deftypefnx {Функция С} @code{void} mgl_start_group (@code{HMGL} gr, @code{const char *}name)
+Начинает определение группы. Группа может содержать объекты и другие группы. Они используются для выбора части модели при приближении, изменении прозрачности и т.д.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} EndGroup ()
+ at deftypefnx {Функция С} @code{void} mgl_end_group (@code{HMGL} gr)
+Завершает определение группы.
+ at end deftypefn
+ at end ifclear
+
+ at menu
+* Export to file::
+* Frames/Animation::
+* Bitmap in memory::
+* Parallelization::
+ at end menu
+
+ at c ==================================================================
+ at external{}
+ at node Export to file, Frames/Animation, , Export picture
+ at subsection Экспорт в файл
+ at nav{}
+ at cindex Write
+ at ifclear UDAV
+ at cindex WriteFrame
+ at cindex WritePNG
+ at cindex WriteGIF
+ at c @cindex WriteIDTF
+ at cindex WriteSVG
+ at cindex WriteBMP
+ at cindex WriteEPS
+ at cindex WriteBPS
+ at cindex WriteTGA
+ at cindex WriteTEX
+ at cindex WritePRC
+ at cindex WriteOBJ
+ at cindex WriteWGL
+ at cindex WriteJPEG
+ at cindex ShowImage
+ at end ifclear
+
+Эти функции экспортируют текущую картинку (кадр) в файл. Имя файла @var{fname} должно иметь соответствующее расширение. Параметр @var{descr} дает краткое описание картинки. Пока прозрачность поддерживается только для форматов PNG, SVG, OBJ и PRC.
+
+ at anchor{write}
+ at deftypefn {Команда MGL} {} write ['fname'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} WriteFrame (@code{const char *}fname=@code{""}, @code{const char *}descr=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_write_frame (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+ at end ifclear
+Экспортирует текущий кадр в файл @var{fname} с типом, определяемым по расширению. Параметр @var{descr} добавляет описание (может быть пустым). Если @var{fname} пустой, то используется имя @samp{frame####.jpg}, где @samp{####} -- текущий номер кадра и имя @samp{frame} определяется переменной @ref{plotid}.
+ at end deftypefn
+
+ at anchor{bbox}
+ at deftypefn {Команда MGL} {} bbox x1 y1 [x2=@code{-1} y2=@code{-1}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetBBox (@code{int} x1=@code{0}, @code{int} y1=@code{0}, @code{int} x2=@code{-1}, @code{int} y2=@code{-1})
+ at deftypefnx {Функция С} @code{void} mgl_set_bbox (@code{HMGL} gr, @code{int} x1, @code{int} y1, @code{int} x2, @code{int} y2)
+ at end ifclear
+Задает область изображения, которая будет сохранена в файл 2D формата. Если @var{x2}<0 (@var{y2}<0), то исходная ширина (высота) рисунка будет использована. Если @var{x1}<0 или @var{y1}<0 или @var{x1}>=@var{x2}|Width или @var{y1}>=@var{y2}|Height, то обрезания рисунка не будет.
+ at end deftypefn
+
+ at ifclear UDAV
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} WritePNG (@code{const char *}fname, @code{const char *}descr=@code{""}, @code{int} compr=@code{""}, @code{bool} alpha=@code{true})
+ at deftypefnx {Функция С} @code{void} mgl_write_png (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+ at deftypefnx {Функция С} @code{void} mgl_write_png_solid (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Экспортирует текущий кадр в PNG файл. Параметры функции следующие: @var{fname} -- имя файла, @var{descr} -- описание файла, @var{alpha} -- прозрачность фона. Если при компиляции MathGL не был определен флаг HAVE_PNG, то экспорт в файл не производится.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} WriteJPEG (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_write_jpg (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Экспортирует текущий кадр в JPEG файл. Параметры функции следующие: @var{fname} -- имя файла, @var{descr} -- описание файла. Если при компиляции MathGL не был определен флаг HAVE_JPEG, то экспорт в файл не производится.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} WriteGIF (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_write_gif (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Экспортирует текущий кадр в GIF файл. Параметры функции следующие: @var{fname} -- имя файла, @var{descr} -- описание файла. Если при компиляции MathGL не был определен флаг HAVE_GIF, то экспорт в файл не производится.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} WriteBMP (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_write_bmp (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Экспортирует текущий кадр в BMP файл. Параметры функции следующие: @var{fname} -- имя файла, @var{descr} -- описание файла.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} WriteTGA (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_write_tga (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Экспортирует текущий кадр в TGA файл. Параметры функции следующие: @var{fname} -- имя файла, @var{descr} -- описание файла.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} WriteEPS (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_write_eps (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Экспортирует текущий кадр в EPS файл, используя векторное представление графика. Вследствие чего не рекомендуется сохранять большие графики (поверхности, а особенно поверхности уровня) из-за большого размера файла. Хотя никаких внутренних ограничений на размер выходного файла нет. Для них лучше использовать растровый формат (например, PNG или JPEG). Параметры функции следующие: @var{fname} -- имя файла, @var{descr} -- описание файла. Если имя файла оканчивается на @samp{z} (например, @sa [...]
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} WriteBPS (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_write_eps (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Экспортирует текущий кадр в EPS файл, используя растровое представление графика. Параметры функции следующие: @var{fname} -- имя файла, @var{descr} -- описание файла. Если имя файла оканчивается на @samp{z} (например, @samp{fname.eps.gz}), то файл автоматически архивируется в формате gzip.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} WriteSVG (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_write_svg (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Экспортирует текущий кадр в SVG файл, используя векторное представление графика. Вследствие чего не рекомендуется сохранять большие графики (поверхности, а особенно поверхности уровня) из-за большого размера файла. Хотя никаких внутренних ограничений на размер выходного файла нет. Для них лучше использовать растровый формат (например, PNG или JPEG). Параметры функции следующие: @var{fname} -- имя файла, @var{descr} -- описание файла. Если имя файла оканчивается на @samp{z} (например, @sa [...]
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} WriteTEX (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_write_tex (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Экспортирует текущий кадр в LaTeX файл (пакет Tikz/PGF), используя векторное представление графика. Вследствие чего не рекомендуется сохранять большие графики (поверхности, а особенно поверхности уровня) из-за большого размера файла. Хотя никаких внутренних ограничений на размер выходного файла нет. Для них лучше использовать растровый формат (например, PNG или JPEG). Параметры функции следующие: @var{fname} -- имя файла, @var{descr} -- описание файла. Отмечу, что сейчас отсутствует изме [...]
+ at end deftypefn
+
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} WritePRC (@code{const char *}fname, @code{const char *}descr=@code{""}, @code{bool} make_pdf=@code{true})
+ at deftypefnx {Функция С} @code{void} mgl_write_prc (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr, @code{int} make_pdf)
+Экспортирует текущий кадр в PRC файл, используя векторное представление графика (см. @url{http://en.wikipedia.org/wiki/PRC_%28file_format%29}). Вследствие чего не рекомендуется сохранять большие графики (поверхности, а особенно поверхности уровня) из-за большого размера файла. Хотя никаких внутренних ограничений на размер выходного файла нет. Для них лучше использовать растровый формат (например, PNG или JPEG). Параметры функции следующие: @var{fname} -- имя файла, @var{descr} -- описани [...]
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} WriteOBJ (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_write_obj (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Экспортирует текущий кадр в OBJ/MTL файл, используя векторное представление графика (см. @url{http://en.wikipedia.org/wiki/Wavefront_.obj_file, OBJ формат}). Вследствие чего не рекомендуется сохранять большие графики (поверхности, а особенно поверхности уровня) из-за большого размера файла. Хотя никаких внутренних ограничений на размер выходного файла нет. Для них лучше использовать растровый формат (например, PNG или JPEG). Параметры функции следующие: @var{fname} -- имя файла, @var{des [...]
+ at end deftypefn
+
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} WriteXYZ (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_write_xyz (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Экспортирует текущий кадр в XYZ/XYZL/XYZF файлы, используя векторное представление графика (см. @url{http://people.sc.fsu.edu/~jburkardt/data/xyz/xyz.html, XYZ формат}). Вследствие чего не рекомендуется сохранять большие графики (поверхности, а особенно поверхности уровня) из-за большого размера файла. Хотя никаких внутренних ограничений на размер выходного файла нет. Для них лучше использовать растровый формат (например, PNG или JPEG). Параметры функции следующие: @var{fname} -- имя фай [...]
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} WriteSTL (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_write_stl (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Экспортирует текущий кадр в STL файл, используя векторное представление графика (см. @url{http://en.wikipedia.org/wiki/STL_(file_format), STL формат}). Вследствие чего не рекомендуется сохранять большие графики (поверхности, а особенно поверхности уровня) из-за большого размера файла. Хотя никаких внутренних ограничений на размер выходного файла нет. Для них лучше использовать растровый формат (например, PNG или JPEG). Параметры функции следующие: @var{fname} -- имя файла, @var{descr} -- [...]
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} WriteOFF (@code{const char *}fname, @code{const char *}descr=@code{""}, @code{bool} colored=@code{false})
+ at deftypefnx {Функция С} @code{void} mgl_write_off (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr, @code{bool} colored)
+Экспортирует текущий кадр в OFF файл, используя векторное представление графика (см. @url{http://people.sc.fsu.edu/~jburkardt/data/off/off.html, OFF формат}). Вследствие чего не рекомендуется сохранять большие графики (поверхности, а особенно поверхности уровня) из-за большого размера файла. Хотя никаких внутренних ограничений на размер выходного файла нет. Для них лучше использовать растровый формат (например, PNG или JPEG). Параметры функции следующие: @var{fname} -- имя файла, @var{de [...]
+ at end deftypefn
+
+ at c @deftypefn {Метод класса @code{mglGraph}} @code{void} WriteX3D (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at c @deftypefnx {Функция С} @code{void} mgl_write_x3d (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+ at c Экспортирует текущий кадр в X3D файл, используя векторное представление графика (см. @url{http://en.wikipedia.org/wiki/X3d, X3D формат}). Вследствие чего не рекомендуется сохранять большие графики (поверхности, а особенно поверхности уровня) из-за большого размера файла. Хотя никаких внутренних ограничений на размер выходного файла нет. Для них лучше использовать растровый формат (например, PNG или JPEG). Параметры функции следующие: @var{fname} -- имя файла, @var{descr} -- описание файла.
+ at c @end deftypefn
+
+
+ at c @deftypefn {Метод класса @code{mglGraph}} @code{void} WriteIDTF (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at c @deftypefnx {Функция С} @code{void} mgl_write_idtf (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+ at c Экспортирует текущий кадр в IDTF файл, используя векторное представление графика (класс mglGraphIDTF). Параметры функции следующие: @var{fname} -- имя файла, @var{descr} -- описание файла.
+ at c @end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} ShowImage (@code{const char *}viewer, @code{bool} nowait=@code{false})
+ at deftypefnx {Функция С} @code{void} mgl_show_image (@code{const char *}viewer, @code{int} nowait)
+Отображает текущий кадр используя внешнюю программу просмотра @var{viewer}. Функция сохраняет картинку во временный файл и вызывает @var{viewer} для его отображения. Если @var{nowait}=@code{true}, то функция возвращает управление немедленно -- не ждет пока окно просмотра будет закрыто.
+ at end deftypefn
+
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} WriteJSON (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_write_json (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Экспортирует точки и примитивы в текстовый файл используя @ref{JSON format}. В дальнейшем этот файл можно загрузить и просмотреть в JavaScript скрипте. Параметры функции следующие: @var{fname} -- имя файла, @var{descr} -- описание файла.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} ExportMGLD (@code{const char *}fname, @code{const char *}descr=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_export_mgld (@code{HMGL} gr, @code{const char *}fname, @code{const char *}descr)
+Экспортирует точки и примитивы в файл @ref{MGLD format}. В дальнейшем этот файл можно загрузить и просмотреть с помощью @code{mglview}. Параметры функции следующие: @var{fname} -- имя файла, @var{descr} -- описание файла.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} ImportMGLD (@code{const char *}fname, @code{bool} add=@code{false})
+ at deftypefnx {Функция С} @code{void} mgl_import_mgld (@code{HMGL} gr, @code{const char *}fname, @code{int} add)
+Импортирует точки и примитивы из файла в @ref{MGLD format}. Параметры функции следующие: @var{fname} -- имя файла, @var{add} -- флаг добавления или замены существующих точек и примитивов.
+ at end deftypefn
+
+ at end ifclear
+
+
+ at c ##################################################################
+ at external{}
+ at node Frames/Animation, Bitmap in memory, Export to file, Export picture
+ at subsection Кадры/Анимация
+ at nav{}
+
+ at ifset UDAV
+В MGL нет специальных команд для создания анимации. Однако можно воспользоваться возможностями утилит @code{mglconv} и @code{mglview}. Например, используя комментарии спеиального вида @samp{##a } или @samp{##c }.
+ at end ifset
+
+ at ifclear UDAV
+ at cindex NewFrame
+ at cindex EndFrame
+ at cindex GetNumFrame
+ at cindex ResetFrames
+ at cindex StartGIF
+ at cindex CloseGIF
+
+Эти функции позволяют создавать несколько картинок одновременно. В большинстве случаев это бесполезно, но для органов управления (см. @ref{Widget classes}) это позволяет показывать анимацию. Также можно записать несколько кадров в анимированный GIF файл.
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} NewFrame ()
+ at deftypefnx {Функция С} @code{void} mgl_new_frame (@code{HMGL} gr)
+Создает новый кадр. Функция возвращает номер текущего кадра. В режиме OpenGL функция не должны вызываться в параллельных потоках! -- используйте прямое создание списка. Функция @code{EndFrame()} @strong{должна} быть вызвана после рисования кадра для каждого вызова этой функции.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} EndFrame ()
+ at deftypefnx {Функция С} @code{void} mgl_end_frame (@code{HMGL} gr)
+Завершает рисование кадра.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{int} GetNumFrame ()
+ at deftypefnx {Функция С} @code{int} mgl_get_num_frame (@code{HMGL} gr)
+Возвращает число созданных кадров.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} GetFrame (@code{int} i)
+ at deftypefnx {Функция С} @code{void} mgl_get_frame (@code{HMGL} gr, @code{int} i)
+Завершает рисование кадра и сохраняет объекты рисования в кадр с номером @var{i}, который должен быть в диапазоне [0, @code{GetNumFrame()}-1]. Функция аналогична @code{EndFrame()}, но не добавляет кадр в GIF изображение.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} GetFrame (@code{int} i)
+ at deftypefnx {Функция С} @code{void} mgl_get_frame (@code{HMGL} gr, @code{int} i)
+Заменяет объекты рисования на объекты из кадра с номером @var{i}. Функция работает если установлен флаг @code{MGL_VECT_FRAME} (по умолчанию).
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} ShowFrame (@code{int} i)
+ at deftypefnx {Функция С} @code{void} mgl_show_frame (@code{HMGL} gr, @code{int} i)
+Добавляет объекты рисования из кадра с номером @var{i} к уже существующим. Функция работает если установлен флаг @code{MGL_VECT_FRAME} (по умолчанию).
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} DelFrame (@code{int} i)
+ at deftypefnx {Функция С} @code{void} mgl_del_frame (@code{HMGL} gr, @code{int} i)
+Удаляет объекты рисования для кадра с номером @var{i} и сдвигает нумерацию всех последующих кадров. Функция работает если установлен флаг @code{MGL_VECT_FRAME} (по умолчанию).
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} ResetFrames ()
+ at deftypefnx {Функция С} @code{void} mgl_reset_frames (@code{HMGL} gr)
+Сбрасывает счетчик кадров в 0.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} ClearFrame (@code{int} i)
+ at deftypefnx {Функция С} @code{void} mgl_clear_frame (@code{HMGL} gr, @code{int} i)
+Очищает текущий список объектов.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} StartGIF (@code{const char *}fname, @code{int} ms=@code{100})
+ at deftypefnx {Функция С} @code{void} mgl_start_gif (@code{HMGL} gr, @code{const char *}fname, @code{int} ms)
+Начинает запись кадров в анимированный GIF файл @var{fname}. Параметр @var{ms} задает задержку между кадрами в миллисекундах. Вы @strong{не должны} менять размер рисунка во время создания кино. Используйте CloseGIF() для завершения записи. Эта функция не работает в режиме OpenGL.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} CloseGIF ()
+ at deftypefnx {Функция С} @code{void} mgl_close_gif (@code{HMGL} gr)
+Завершает запись анимированного GIF файла.
+ at end deftypefn
+ at end ifclear
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Bitmap in memory, Parallelization, Frames/Animation, Export picture
+ at subsection Рисование в памяти
+ at nav{}
+
+ at ifclear UDAV
+Эти функции возвращают созданный растровый рисунок, его ширину и высоту. В дальнейшем его можно использовать в любой графической библиотеке (см. также, @ref{Widget classes}) или сохранить в файл (см. также, @ref{Export to file}).
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{const unsigned char *} GetRGB ()
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} GetRGB (@code{char *}buf, @code{int} size)
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} GetBGRN (@code{char *}buf, @code{int} size)
+ at deftypefnx {Функция С} @code{const unsigned char *} mgl_get_rgb (@code{HMGL} gr)
+Возвращает растровое изображение в формате RGB для текущего кадра. Формат каждого элемента (пикселя): @{red, green, blue@}. Число элементов Width*Height. Положение элемента @{i,j@} есть [3*i + 3*Width*j] (или [4*i + 4*Width*j] для @code{GetBGRN()}). В Python вы должны предоставить буфер @var{buf} достаточного размера @var{size}, т.е. код должен выглядеть следующим образом (для Python)
+ at verbatim
+from mathgl import *
+gr = mglGraph();
+bits='\t';
+bits=bits.expandtabs(4*gr.GetWidth()*gr.GetHeight());
+gr.GetBGRN(bits, len(bits));
+ at end verbatim
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{const unsigned char *} GetRGBA ()
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} GetRGBA (@code{char *}buf, @code{int} size)
+ at deftypefnx {Функция С} @code{const unsigned char *} mgl_get_rgba (@code{HMGL} gr)
+Возвращает растровое изображение в формате RGBA для текущего кадра. Формат каждого элемента (пикселя): @{red, green, blue, alpha@}. Число элементов Width*Height. Положение элемента @{i,j@} есть [4*i + 4*Width*j].
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{int} GetWidth ()
+ at deftypefnx {Метод класса @code{mglGraph}} @code{int} GetHeight ()
+ at deftypefnx {Функция С} @code{int} mgl_get_width (@code{HMGL} gr)
+ at deftypefnx {Функция С} @code{int} mgl_get_height (@code{HMGL} gr)
+Возвращает ширину и высоту изображения.
+ at end deftypefn
+
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{mglPoint} CalcXYZ (@code{int} xs, @code{int} ys)
+ at deftypefnx {Функция С} @code{void} mgl_calc_xyz (@code{HMGL} gr, @code{int} xs, @code{int} ys, @code{mreal *}x, @code{mreal *}y, @code{mreal *}z)
+Вычисляет 3D координаты @{x,y,z@} для экранной точки @{xs,ys@}. В данный момент игнорируется перспектива графика и формулы перехода в криволинейные координаты. Вычисления производятся для последнего использованного InPlot (см. @ref{Subplots and rotation}).
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{mglPoint} CalcScr (@code{mglPoint} p)
+ at deftypefnx {Функция С} @code{void} mgl_calc_scr (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{int *}xs, @code{int *}ys)
+Вычисляет экранные координаты @{xs,ys@} для 3D координат @{x,y,z@}. Вычисления производятся для последнего использованного InPlot (см. @ref{Subplots and rotation}).
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} SetObjId (@code{int} id)
+ at deftypefnx {Функция С} @code{void} mgl_set_obj_id (@code{HMGL} gr, @code{int} id)
+Задает числовой идентификатор для объектов или subplot/inplot.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{int} GetObjId (@code{int} xs, @code{int} ys)
+ at deftypefnx {Функция С} @code{int} mgl_get_obj_id (@code{HMGL} gr, @code{int} xs, @code{int} ys)
+Возвращает числовой идентификатор верхнего объекта в точке @{xs, ys@} рисунка.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{int} GetSplId (@code{int} xs, @code{int} ys)
+ at deftypefnx {Функция С} @code{int} mgl_get_spl_id (@code{HMGL} gr, @code{int} xs, @code{int} ys)
+Возвращает числовой идентификатор верхнего "подграфика" в точке @{xs, ys@} рисунка.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} Highlight (@code{int} id)
+ at deftypefnx {Функция С} @code{void} mgl_highlight (@code{HMGL} gr, @code{int} id)
+Выделяет объект с заданным @var{id}.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{long} IsActive (@code{int} xs, @code{int} ys, @code{int} d=@code{1})
+ at deftypefnx {Функция С} @code{long} mgl_is_active (@code{HMGL} gr, @code{int} xs, @code{int} ys, @code{int} d)
+Проверяет близка ли точка @{@var{xs}, @var{ys}@} к активной точке (т.е. mglBase::Act) с точностью @var{d} и возвращает индекс активной точки или @code{-1} если не найдено. Активные точки -- специальные точки, которые характеризуют примитивы (например, вершины). Это функция только для опытных пользователей.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{long} SetDrawReg (@code{int} nx=@code{1}, @code{int} ny=@code{1}, @code{int} m=@code{0})
+ at deftypefnx {Функция С} @code{long} mgl_set_draw_reg (@code{HMGL} gr, @code{int} nx, @code{int} ny, @code{int} m)
+Ограничивает рисование прямоугольной областью @var{m}-ой клетки матрицы размером @var{nx}*@var{ny} (аналогично @ref{subplot}). Функция может бытб использована для ускорения вывода путем уменьшения выводимых примитивов. Это функция только для опытных пользователей.
+ at end deftypefn
+
+ at end ifclear
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Parallelization, , Bitmap in memory, Export picture
+ at subsection Распараллеливание
+ at nav{}
+
+ at ifclear UDAV
+ at cindex Combine
+ at cindex MPI_Send
+ at cindex MPI_Recv
+
+Многие функции MathGL используют несколько потоков для ускорения работы (если MathGL была собрана с поддержкой pthread). При этом можно настраивать число используемых потоков.
+
+ at deftypefn {Функция С} @code{int} mgl_set_num_thr (@code{int} n)
+Задает число потоков, которое будет использовано в MathGL. При @var{n}<1 число потоков задается как максимальное число процессоров (ядер) в системе. При @var{n}=1 не используется распараллеливание.
+ at end deftypefn
+
+Другая возможность -- комбинирование изображений из разных объектов @code{mglGraph}. Эти методы наиболее подходят для компьютерных кластеров, когда данные настолько велики, что не могут поместиться в памяти отдельного компьютера.
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{int} Combine (@code{const mglGraph *}g)
+ at deftypefnx {Функция С} @code{int} mgl_combine_gr (@code{HMGL} gr, @code{HMGL} g)
+Комбинирует (добавляет) рисунок из @var{g} с @var{gr}, принимая во внимание ``высоту'' пикселей. Ширина и высота обоих рисунков должна быть одинаковы.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{int} MPI_Send (@code{int} id)
+ at deftypefnx {Функция С} @code{int} mgl_mpi_send (@code{HMGL} gr, @code{int} id)
+Посылает рисунок из компьютера (ноды) @var{id}, используя MPI. Ширина и высота обоих рисунков должна быть одинаковы.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{int} MPI_Recv (@code{int} id)
+ at deftypefnx {Функция С} @code{int} mgl_mpi_send (@code{HMGL} gr, @code{int} id)
+Принимает рисунок из компьютера (ноды) @var{id}, используя MPI. Ширина и высота обоих рисунков должна быть одинаковы.
+ at end deftypefn
+ at end ifclear
+
+
+ at c ##################################################################
+ at external{}
+ at node Background, Primitives, Export picture, MathGL core
+ at section Фоновое изображение
+ at nav{}
+ at cindex LoadBackground
+ at cindex Clf
+ at cindex Rasterize
+
+These functions change background image.
+
+ at anchor{clf}
+ at deftypefn {Команда MGL} {} clf ['col']
+ at deftypefnx {Команда MGL} {} clf r g b
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Clf ()
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Clf (@code{const char *} col)
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Clf (@code{char} col)
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Clf (@code{mreal} r, @code{mreal} g, @code{mreal} b)
+ at deftypefnx {Функция С} @code{void} mgl_clf (@code{HMGL} gr)
+ at deftypefnx {Функция С} @code{void} mgl_clf_str (@code{HMGL} gr, @code{const char *} col)
+ at deftypefnx {Функция С} @code{void} mgl_clf_chr (@code{HMGL} gr, @code{char} col)
+ at deftypefnx {Функция С} @code{void} mgl_clf_rgb (@code{HMGL} gr, @code{mreal} r, @code{mreal} g, @code{mreal} b)
+ at end ifclear
+Очищает рисунок и заполняет фон заданным цветом.
+ at end deftypefn
+
+ at anchor{rasterize}
+ at deftypefn {Команда MGL} {} rasterize
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Rasterize ()
+ at deftypefnx {Функция С} @code{void} mgl_rasterize (@code{HMGL} gr)
+ at end ifclear
+Завершает рисование графика и помещает результат в качестве фона. После этого, очищает список примитивов (как @ref{clf}). Функция полезна для сохранения части графика (например, поверхностей или векторных полей) в растровом виде, а другой части (кривых, осей и пр.) в векторном.
+ at end deftypefn
+
+ at anchor{background}
+ at deftypefn {Команда MGL} {} background 'fname' [@code{alpha=1}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} LoadBackground (@code{const char *} fname, @code{double} alpha=@code{1})
+ at deftypefnx {Функция С} @code{void} mgl_load_background (@code{HMGL} gr, @code{const char *} fname, @code{double} alpha)
+ at end ifclear
+Загружает PNG или JPEG файл @var{fname} в качестве фона для графика. Параметр @var{alpha} задает прозрачность фона вручную.
+ at end deftypefn
+
+
+ at c ##################################################################
+ at external{}
+ at node Primitives, Text printing, Export picture, MathGL core
+ at section Рисование примитивов
+ at nav{}
+ at cindex Ball
+ at cindex Line
+ at cindex Curve
+ at cindex Glyph
+ at cindex Face
+ at cindex FaceX
+ at cindex FaceY
+ at cindex FaceZ
+ at cindex Cone
+ at cindex Drop
+ at cindex Sphere
+
+ at ifclear UDAV
+ at cindex Mark
+ at cindex Error
+ at end ifclear
+
+Эти функции рисуют рисуют простые объекты типа линий, точек, сфер, капель, конусов, и т.д.
+
+ at anchor{ball}
+ at deftypefn {Команда MGL} {} ball @code{x y} ['col'='r.']
+ at deftypefnx {Команда MGL} {} ball @code{x y z} ['col'='r.']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Ball (@code{mglPoint} p, @code{char} col=@code{'r'})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Mark (@code{mglPoint} p, @code{const char *}mark)
+ at deftypefnx {Функция С} @code{void} mgl_mark (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{const char *}mark)
+ at end ifclear
+Рисует маркер (точку по умолчанию) с координатами @var{p}=@{@var{x}, @var{y}, @var{z}@} и цветом @var{col}.
+ at end deftypefn
+
+ at anchor{errbox}
+ at deftypefn {Команда MGL} {} errbox @code{x y ex ey} ['stl'='']
+ at deftypefnx {Команда MGL} {} errbox @code{x y z ex ey ez} ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Error (@code{mglPoint} p, @code{mglPoint} e, @code{char} *stl=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_error_box (@code{HMGL} gr, @code{mreal} px, @code{mreal} py, @code{mreal} pz, @code{mreal} ex, @code{mreal} ey, @code{mreal} ez, @code{char *}stl)
+ at end ifclear
+Рисует 3d error box в точке @var{p}=@{@var{x}, @var{y}, @var{z}@} размером @var{e}=@{@var{ex}, @var{ey}, @var{ez}@} и стилем @var{stl}. Используйте NAN в компонентах @var{e} для уменьшения рисуемых элементов.
+ at end deftypefn
+
+ at anchor{line}
+ at deftypefn {Команда MGL} {} line @code{x1 y1 x2 y2} ['stl'='']
+ at deftypefnx {Команда MGL} {} line @code{x1 y1 z1 x2 y2 z2} ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Line (@code{mglPoint} p1, @code{mglPoint} p2, @code{char *}stl=@code{"B"}, @code{int}num=@code{2})
+ at deftypefnx {Функция С} @code{void} mgl_line (@code{HMGL} gr, @code{mreal} x1, @code{mreal} y1, @code{mreal} z1, @code{mreal} x2, @code{mreal} y2, @code{mreal} z2, @code{char *}stl, @code{int}num)
+ at end ifclear
+Рисует геодезическую линию (декартовых координатах -- прямую) из точки @var{p1} в @var{p2} использую стиль линии @var{stl}. Параметр @var{num} определяет гладкость линии (число точек на линии). Если @var{num}=@code{2}, то рисуется прямая даже в криволинейных координатах (см. @ref{Curved coordinates}). Наоборот, для больших значений (например, =@code{100}) рисуется геодезическая линия (окружность в полярных координатах, парабола в параболических и т.д.). Линия рисуется даже если часть ее  [...]
+ at end deftypefn
+
+ at anchor{curve}
+ at deftypefn {Команда MGL} {} curve @code{x1 y1 dx1 dy1 x2 y2 dx2 dy2} ['stl'='']
+ at deftypefnx {Команда MGL} {} curve @code{x1 y1 z1 dx1 dy1 dz1 x2 y2 z2 dx2 dy2 dz2} ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Curve (@code{mglPoint} p1, @code{mglPoint} d1, @code{mglPoint} p2, @code{mglPoint} d2, @code{const char *}stl=@code{"B"}, @code{int} num=@code{100})
+ at deftypefnx {Функция С} @code{void} mgl_curve (@code{HMGL} gr, @code{mreal} x1, @code{mreal} y1, @code{mreal} z1, @code{mreal} dx1, @code{mreal} dy1, @code{mreal} dz1, @code{mreal} x2, @code{mreal} y2, @code{mreal} z2, @code{mreal} dx2, @code{mreal} dy2, @code{mreal} dz2, @code{const char *}stl, @code{int} num)
+ at end ifclear
+Рисует кривую Безье из точки @var{p1} в @var{p2} используя стиль линии @var{stl}. Касательные в точках пропорциональны @var{d1}, @var{d2}. Параметр @var{num} определяет гладкость линии (число точек на линии). Если @var{num}=@code{2}, то рисуется прямая даже в криволинейных координатах (см. @ref{Curved coordinates}). Наоборот, для больших значений (например, =@code{100}) рисуется геодезическая линия (окружность в полярных координатах, парабола в параболических и т.д.). Кривая рисуется даж [...]
+ at end deftypefn
+
+ at anchor{face}
+ at deftypefn {Команда MGL} {} face @code{x1 y1 x2 y2 x3 y3 x4 y4} ['stl'='']
+ at deftypefnx {Команда MGL} {} face @code{x1 y1 z1 x2 y2 z2 x3 y3 z3 x4 y4 z4} ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Face (@code{mglPoint} p1, @code{mglPoint} p2, @code{mglPoint} p3, @code{mglPoint} p4, @code{const char *}stl=@code{"w"})
+ at deftypefnx {Функция С} @code{void} mgl_face (@code{HMGL} gr, @code{mreal} x1, @code{mreal} y1, @code{mreal} z1, @code{mreal} x2, @code{mreal} y2, @code{mreal} z2, @code{mreal} x3, @code{mreal} y3, @code{mreal} z3, @code{mreal} x4, @code{mreal} y4, @code{mreal} z4, @code{const char *}stl)
+ at end ifclear
+Рисует заполненный четырехугольник (грань) с углами в точках @var{p1}, @var{p2}, @var{p3}, @var{p4} и цветом(-ами) @var{stl}. При этом цвет может быть один для всей грани, или различным если указаны все 4 цвета. Грань будет нарисована даже если часть ее лежит вне диапазона осей координат.
+ at end deftypefn
+
+ at anchor{rect}
+ at deftypefn {Команда MGL} {} rect @code{x1 y1 x2 y2} ['stl'='']
+ at deftypefnx {Команда MGL} {} rect @code{x1 y1 z1 x2 y2 z2} ['stl'='']
+Рисует закрашенный прямоугольник (грань) с вершинами @{@var{x1}, @var{y1}, @var{z1}@} и @{@var{x2}, @var{y2}, @var{z2}@} цветом @var{stl}. При этом цвет может быть один для всей грани, или различным для разных вершин если указаны все 4 цвета. Грань будет нарисована даже если часть ее лежит вне диапазона осей координат.
+ at end deftypefn
+
+ at anchor{facex}
+ at anchor{facey}
+ at anchor{facez}
+ at deftypefn {Команда MGL} {} facex @code{x0 y0 z0 wy wz} ['stl'='' @code{d1=0 d2=0}]
+ at deftypefnx {Команда MGL} {} facey @code{x0 y0 z0 wx wz} ['stl'='' @code{d1=0 d2=0}]
+ at deftypefnx {Команда MGL} {} facez @code{x0 y0 z0 wx wy} ['stl'='' @code{d1=0 d2=0}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} FaceX (@code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{mreal} wy, @code{mreal} wz, @code{const char *}stl=@code{"w"}, @code{mreal} d1=@code{0}, @code{mreal} d2=@code{0})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} FaceY (@code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{mreal} wx, @code{mreal} wz, @code{const char *}stl=@code{"w"}, @code{mreal} d1=@code{0}, @code{mreal} d2=@code{0})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} FaceZ (@code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{mreal} wx, @code{mreal} wy, @code{const char *}stl=@code{"w"}, @code{mreal} d1=@code{0}, @code{mreal} d2=@code{0})
+ at deftypefnx {Функция С} @code{void} mgl_facex (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{mreal} wy, @code{mreal} wz, @code{const char *}stl, @code{mreal} d1, @code{mreal} d2)
+ at deftypefnx {Функция С} @code{void} mgl_facey (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{mreal} wx, @code{mreal} wz, @code{const char *}stl, @code{mreal} d1, @code{mreal} d2)
+ at deftypefnx {Функция С} @code{void} mgl_facez (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{mreal} wx, @code{mreal} wy, @code{const char *}stl, @code{mreal} d1, @code{mreal} d2)
+ at end ifclear
+Рисует закрашенный прямоугольник (грань) перпендикулярно оси [x,y,z] в точке @{@var{x0}, @var{y0}, @var{z0}@} цветом @var{stl} и шириной @var{wx}, @var{wy}, @var{wz} вдоль соответствующего направления. При этом цвет может быть один для всей грани, или различным для разных вершин если указаны все 4 цвета. Параметры @var{d1}!=0, @var{d2}!=0 задают дополнительный сдвиг последней точки (т.е. рисуют четырехугольник). Грань будет нарисована даже если часть ее лежит вне диапазона осей координат.
+ at end deftypefn
+
+ at anchor{sphere}
+ at deftypefn {Команда MGL} {} sphere @code{x0 y0 r} ['col'='r']
+ at deftypefnx {Команда MGL} {} sphere @code{x0 y0 z0 r} ['col'='r']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Sphere (@code{mglPoint} p, @code{mreal} r, @code{const char *}stl=@code{"r"})
+ at deftypefnx {Функция С} @code{void} mgl_sphere (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{mreal} r, @code{const char *}stl)
+ at end ifclear
+Рисует сферу радиуса @var{r} с центром в точке @var{p}=@{@var{x0}, @var{y0}, @var{z0}@} цветом @var{stl}.
+ at end deftypefn
+
+ at anchor{drop}
+ at deftypefn {Команда MGL} {} drop @code{x0 y0 dx dy r} ['col'='r' @code{sh=1 asp=1}]
+ at deftypefnx {Команда MGL} {} drop @code{x0 y0 z0 dx dy dz r} ['col'='r' @code{sh=1 asp=1}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Drop (@code{mglPoint} p, @code{mglPoint} d, @code{mreal} r, @code{const char *}col=@code{"r"}, @code{mreal} shift=@code{1}, @code{mreal} ap=@code{1})
+ at deftypefnx {Функция С} @code{void} mgl_drop (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{mreal} dx, @code{mreal} dy, @code{mreal} dz, @code{mreal} r, @code{const char *}col, @code{mreal} shift, @code{mreal} ap)
+ at end ifclear
+Рисует каплю радиуса @var{r} в точке @var{p} вытянутую вдоль направления @var{d} цветом @var{col}. Параметр @var{shift} определяет степень вытянутости: @samp{0} -- сфера, @samp{1} -- классическая капля. Параметр @var{ap} определяет относительную ширину капли (аналог "эллиптичности" для сферы).
+ at end deftypefn
+
+ at anchor{cone}
+ at deftypefn {Команда MGL} {} cone @code{x1 y1 z1 x2 y2 z2 r1} [@code{r2=-1} 'stl'='' @code{edge=off}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Cone (@code{mglPoint} p1, @code{mglPoint} p2, @code{mreal} r1, @code{mreal} r2=@code{-1}, @code{const char *}stl=@code{"B"}, @code{bool} edge=@code{false})
+ at deftypefnx {Функция С} @code{void} mgl_cone (@code{HMGL} gr, @code{mreal} x1, @code{mreal} y1, @code{mreal} z1, @code{mreal} x2, @code{mreal} y2, @code{mreal} z2, @code{mreal} r1, @code{mreal} r2, @code{const char *}stl, @code{int} draw_edge)
+ at end ifclear
+Рисует трубу (или усеченный конус если @var{edge}=@code{false}) между точками @var{p1}, @var{p2} с радиусами на концах @var{r1}, @var{r2}. Если @var{r2}<0, то полагается @var{r2}=@var{r1}. Цвет конуса задается строкой @var{stl}. Параметр @var{stl} может содержать:
+ at itemize @bullet
+ at item
+ at samp{@@} для рисования торцов;
+ at item
+ at samp{#} для сетчатой фигуры;
+ at item
+ at samp{t} для рисования цилиндра вместо конуса/призмы;
+ at item
+ at samp{4}, @samp{6}, @samp{8} для рисования квадратной, шестиугольной или восьмиугольной призмы вместо конуса.
+ at end itemize
+
+ at end deftypefn
+
+ at anchor{circle}
+ at deftypefn {Команда MGL} {} circle @code{x0 y0 r} ['col'='r']
+ at deftypefnx {Команда MGL} {} circle @code{x0 y0 z0 r} ['col'='r']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Circle (@code{mglPoint} p, @code{mreal} r, @code{const char *}stl=@code{"r"})
+ at end ifclear
+Рисует круг радиуса @var{r} с центром в точке @var{p}=@{@var{x0}, @var{y0}, @var{z0}@} цветом @var{stl}. Если @var{col} содержит: @samp{#} то рисуется только граница, @samp{@@} то рисуется граница (вторым цветом из @var{col} или черными).
+ at end deftypefn
+
+ at anchor{ellipse}
+ at deftypefn {Команда MGL} {} ellipse @code{x1 y1 x2 y2 r} ['col'='r']
+ at deftypefnx {Команда MGL} {} ellipse @code{x1 y1 z1 x2 y2 z2 r} ['col'='r']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Ellipse (@code{mglPoint} p1, @code{mglPoint} p2, @code{mreal} r, @code{const char *}col=@code{"r"})
+ at deftypefnx {Функция С} @code{void} mgl_ellipse (@code{HMGL} gr, @code{mreal} x1, @code{mreal} y1, @code{mreal} z1, @code{mreal} x2, @code{mreal} y2, @code{mreal} z2, @code{mreal} r, @code{const char *}col)
+ at end ifclear
+Рисует эллипс радиуса @var{r} с фокусами в точках @var{p1}, @var{p2} цветом @var{stl}. Если @var{col} содержит: @samp{#} то рисуется только граница, @samp{@@} то рисуется граница (вторым цветом из @var{col} или черными).
+ at end deftypefn
+
+ at anchor{rhomb}
+ at deftypefn {Команда MGL} {} rhomb @code{x1 y1 x2 y2 r} ['col'='r']
+ at deftypefnx {Команда MGL} {} rhomb @code{x1 y1 z1 x2 y2 z2 r} ['col'='r']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Rhomb (@code{mglPoint} p1, @code{mglPoint} p2, @code{mreal} r, @code{const char *}col=@code{"r"})
+ at deftypefnx {Функция С} @code{void} mgl_rhomb (@code{HMGL} gr, @code{mreal} x1, @code{mreal} y1, @code{mreal} z1, @code{mreal} x2, @code{mreal} y2, @code{mreal} z2, @code{mreal} r, @code{const char *}col)
+ at end ifclear
+Рисует ромб ширины @var{r} с вершинами в точках @var{p1}, @var{p2} цветом @var{stl}. Если @var{col} содержит: @samp{#} то рисуется только граница, @samp{@@} то рисуется граница (вторым цветом из @var{col} или черными). Если @var{col} содержит 3 цвета, то используется градиентная заливка.
+ at end deftypefn
+
+ at anchor{arc}
+ at deftypefn {Команда MGL} {} arc @code{x0 y0 x1 y1 a} ['col'='r']
+ at deftypefnx {Команда MGL} {} arc @code{x0 y0 z0 x1 y1 a} ['col'='r']
+ at deftypefnx {Команда MGL} {} arc @code{x0 y0 z0 xa ya za x1 y1 z1 a} ['col'='r']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Arc (@code{mglPoint} p0, @code{mglPoint} p1, @code{mreal} a, @code{const char *}col=@code{"r"})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Arc (@code{mglPoint} p0, @code{mglPoint} pa, @code{mglPoint} p1, @code{mreal} a, @code{const char *}col=@code{"r"})
+ at deftypefnx {Функция С} @code{void} mgl_arc (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} x1, @code{mreal} y1, @code{mreal} a, @code{const char *}col)
+ at deftypefnx {Функция С} @code{void} mgl_arc_ext (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{mreal} xa, @code{mreal} ya, @code{mreal} za, @code{mreal} x1, @code{mreal} y1, @code{mreal} z1, @code{mreal} a, @code{const char *}col)
+ at end ifclear
+Рисует дугу вокруг оси @var{pa} (по умолчанию вокруг оси z @var{pa}=@{0,0,1@}) с центром в @var{p0}, начиная с точки @var{p1}. Параметр @var{a} задает угол дуги в градусах. Строка @var{col} задает цвет дуги и тип стрелок на краях.
+ at end deftypefn
+
+ at anchor{polygon}
+ at deftypefn {Команда MGL} {} polygon @code{x0 y0 x1 y1 num} ['col'='r']
+ at deftypefnx {Команда MGL} {} polygon @code{x0 y0 z0 x1 y1 z1 num} ['col'='r']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Polygon (@code{mglPoint} p0, @code{mglPoint} p1, @code{int} num, @code{const char *}col=@code{"r"})
+ at deftypefnx {Функция С} @code{void} mgl_polygon (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{mreal} x1, @code{mreal} y1, @code{mreal} z1, @code{int} num, @code{const char *}col)
+ at end ifclear
+Рисует правильный @var{num}-угольник с центром в @var{p0} с первой вершиной в @var{p1} цветом @var{col}. Если @var{col} содержит: @samp{#} то рисуется только граница, @samp{@@} то рисуется граница (вторым цветом из @var{col} или черными).
+ at c Если @var{col} содержит 3 цвета, то используется градиентная заливка.
+ at end deftypefn
+
+ at anchor{logo}
+ at deftypefn {Команда MGL} {} logo 'fname' [smooth=off]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Logo (@code{const char *}fname, @code{bool} smooth=@code{false}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Logo (@code{long} w, @code{long} h, @code{const unsigned char *}rgba, @code{bool} smooth=@code{false}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_logo (@code{HMGL} gr, @code{long} w, @code{long} h, @code{const unsigned char *}rgba, @code{bool} smooth, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_logo_file (@code{HMGL} gr, @code{const char *}fname, @code{bool} smooth, @code{const char *}opt)
+ at end ifclear
+Draw bitmap (logo) along whole axis range, which can be changed by @ref{Command options}. Bitmap can be loaded from file or specified as RGBA values for pixels. Parameter @var{smooth} set to draw bitmap without or with color interpolation.
+ at end deftypefn
+
+
+
+ at anchor{symbol}
+ at deftypefn {Команда MGL} {} symbol @code{x y} 'id' ['fnt'='' @code{size=-1}]
+ at deftypefnx {Команда MGL} {} symbol @code{x y z} 'id' ['fnt'='' @code{size=-1}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Symbol (@code{mglPoint} p, @code{char} id, @code{const char *}fnt=@code{""}, @code{mreal} size=@code{-1})
+ at deftypefnx {Функция С} @code{void} mgl_symbol (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{char} id, @code{const char *}fnt, @code{mreal} size)
+ at end ifclear
+Рисует определенный пользователем символ с именем @var{id} в точке @var{p} стилем @var{fnt}. Размер задается параметром @var{size} (по умолчанию @code{-1}). Строка @var{fnt}  может содержать цвет (до разделителя @samp{:}); стили @samp{a} или @samp{A} для вывода в абсолютной позиции (@{@var{x}, @var{y}@} полагаются в диапазоне [0,1]) относительно рисунка (для @samp{A}) или subplot/inplot (для @samp{a}); и стиль @samp{w} для рисования только контура символа.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} symbol @code{x y dx dy} 'id' ['fnt'=':L' @code{size=-1}]
+ at deftypefnx {Команда MGL} {} symbol @code{x y z dx dy dz} 'id' ['fnt'=':L' @code{size=-1}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Symbol (@code{mglPoint} p, @code{mglPoint} d, @code{char} id, @code{const char *}fnt=@code{""}, @code{mreal} size=@code{-1})
+ at deftypefnx {Функция С} @code{void} mgl_symbol_dir (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{mreal} dx, @code{mreal} dy, @code{mreal} dz, @code{const char *}text, @code{const char *}fnt, @code{mreal} size)
+ at end ifclear
+Аналогично предыдущему, но символ рисуется в повернутым в направлении @var{d}.
+ at end deftypefn
+
+ at anchor{addsymbol}
+ at deftypefn {Команда MGL} {} addsymbol 'id' xdat ydat
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} DefineSymbol (@code{char} id, @code{const mglDataA &}xdat, @code{const mglDataA &}ydat)
+ at deftypefnx {Функция С} @code{void} mgl_define_symbol (@code{HMGL} gr, @code{HCDT} xdat, @code{HCDT} ydat)
+ at end ifclear
+Добавляет определенный пользователем символ с именем @var{id} и границей @{@var{xdat}, @var{ydat}@}. Значения @code{NAN} задают разрыв (скачок) граничной кривой.
+ at end deftypefn
+
+
+ at c ##################################################################
+ at external{}
+ at node Text printing, Axis and Colorbar, Primitives, MathGL core
+ at section Вывод текста
+ at nav{}
+ at ifclear UDAV
+ at cindex Puts
+ at cindex Putsw
+ at end ifclear
+ at cindex Text
+ at cindex fgets
+
+Функции для вывода текста позволяют вывести строку текста в произвольном месте рисунка, в произвольном направлении и вдоль произвольной кривой. MathGL позволяет использовать произвольное начертание шрифта и многие ТеХ-ие команды (детальнее см. @ref{Font styles}). Все функции вывода текста имеют варианты для 8-bit строк (@code{char *}) и для Unicode строк (@code{wchar_t *}). В первом случае используется конверсия из текущей локали, т.е. иногда вам требуется явно указать локаль с помощью ф [...]
+
+Параметры шрифта задаются строкой, которая может содержать символы цвета @samp{wkrgbcymhRGBCYMHW} (см. @ref{Color styles}). Также после символа @samp{:} можно указать  символы стиля (@samp{rbiwou}) и/или выравнивания (@samp{LRCTV}). Стили шрифта: @samp{r} -- прямой, @samp{i} -- курсив, @samp{b} -- жирный, @samp{w} -- контурный, @samp{o} -- надчеркнутый, @samp{u} -- подчеркнутый. По умолчанию используется прямой шрифт. Типы выравнивания: @samp{L} -- по левому краю (по умолчанию), @samp{C} [...]
+
+Если строка содержит символы @samp{aA}, то текст выводится в абсолютных координатах (полагаются в диапазоне [0,1]). При этом используются координаты относительно рисунка (если указано @samp{A}) или относительно последнего subplot/inplot (если указано @samp{a}). Если строка содержит символ @samp{@@}, то вокруг текста рисуется прямоугольник.
+
+ at sref{Text features}
+
+ at anchor{text}
+ at deftypefn {Команда MGL} {} text @code{x y} 'text' ['fnt'='' @code{size=-1}]
+ at deftypefnx {Команда MGL} {} text @code{x y z} 'text' ['fnt'='' @code{size=-1}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Puts (@code{mglPoint} p, @code{const char *}text, @code{const char *}fnt=@code{":C"}, @code{mreal} size=@code{-1})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Putsw (@code{mglPoint} p, @code{const wchar_t *}text, @code{const char *}fnt=@code{":C"}, @code{mreal} size=@code{-1})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Puts (@code{mreal} x, @code{mreal} y, @code{const char *}text, @code{const char *}fnt=@code{":AC"}, @code{mreal} size=@code{-1})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Putsw (@code{mreal} x, @code{mreal} y, @code{const wchar_t *}text, @code{const char *}fnt=@code{":AC"}, @code{mreal} size=@code{-1})
+ at deftypefnx {Функция С} @code{void} mgl_puts (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{const char *}text, @code{const char *}fnt, @code{mreal} size)
+ at deftypefnx {Функция С} @code{void} mgl_putsw (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{const wchar_t *}text, @code{const char *}fnt, @code{mreal} size)
+ at end ifclear
+Выводит строку @var{text} от точки @var{p} шрифтом определяемым строкой @var{fnt}. Размер шрифта задается параметром @var{size} (по умолчанию @code{-1}).
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} text @code{x y dx dy} 'text' ['fnt'=':L' @code{size=-1}]
+ at deftypefnx {Команда MGL} {} text @code{x y z dx dy dz} 'text' ['fnt'=':L' @code{size=-1}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Puts (@code{mglPoint} p, @code{mglPoint} d, @code{const char *}text, @code{const char *}fnt=@code{':L'}, @code{mreal} size=@code{-1})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Putsw (@code{mglPoint} p, @code{mglPoint} d, @code{const wchar_t *}text, @code{const char *}fnt=@code{':L'}, @code{mreal} size=@code{-1})
+ at deftypefnx {Функция С} @code{void} mgl_puts_dir (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{mreal} dx, @code{mreal} dy, @code{mreal} dz, @code{const char *}text, @code{const char *}fnt, @code{mreal} size)
+ at deftypefnx {Функция С} @code{void} mgl_putsw_dir (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{mreal} dx, @code{mreal} dy, @code{mreal} dz, @code{const wchar_t *}text, @code{const char *}fnt, @code{mreal} size)
+ at end ifclear
+Выводит строку @var{text} от точки @var{p} вдоль направления @var{d}. Параметр @var{fnt} задает стиль текста и указывает выводить текст под линией (@samp{T}) или над ней (@samp{t}).
+ at end deftypefn
+
+ at anchor{fgets}
+ at deftypefn {Команда MGL} {} fgets @code{x y} 'fname' [@code{n=0} 'fnt'='' @code{size=-1.4}]
+ at deftypefnx {Команда MGL} {} fgets @code{x y z} 'fname' [@code{n=0} 'fnt'='' @code{size=-1.4}]
+Выводит @var{n}-ую строку файла @var{fname} от точки @{@var{x}, at var{y}, at var{z}@} шрифтом @var{fnt} и размером @var{size}. По умолчанию используются параметры заданные командой @ref{font}.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} text ydat 'text' ['fnt'='']
+ at deftypefnx {Команда MGL} {} text xdat ydat 'text' ['fnt'='' @code{size=-1 zval=nan}]
+ at deftypefnx {Команда MGL} {} text xdat ydat zdat 'text' ['fnt'='' @code{size=-1}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Text (@code{const mglDataA &}y, @code{const char *}text, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Text (@code{const mglDataA &}y, @code{const wchar_t *}text, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Text (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const char *}text, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Text (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const wchar_t *}text, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Text (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}text, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Text (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const wchar_t *}text, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_text_y (@code{HMGL} gr, @code{HCDT} y, @code{const char *}text, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_textw_y (@code{HMGL} gr, @code{HCDT} y, @code{const wchar_t *}text, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_text_xy (@code{HCDT} x, @code{HCDT} y, @code{const char *}text, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_textw_xy (@code{HCDT} x, @code{HCDT} y, @code{const wchar_t *}text, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_text_xyz (@code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}text, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_textw_xyz (@code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const wchar_t *}text, @code{const char *}fnt, @code{const char *}opt)
+ at end ifclear
+Выводит строку @var{text} вдоль кривой @{@var{x}[i], @var{y}[i], @var{z}[i]@} шрифтом @var{fnt}. Строка @var{fnt} может содержать символы: @samp{t} для вывода текста под кривой (по умолчанию), или @samp{T} для вывода текста под кривой. Размеры по 1-ой размерности должны быть одинаковы для всех массивов @code{x.nx=y.nx=z.nx}. Если массив @var{x} не указан, то используется "автоматический" массив со значениями в диапазоне осей координат (см. @ref{Ranges (bounding box)}). Если массив @var{z [...]
+ at end deftypefn
+
+ at c ##################################################################
+ at external{}
+ at node Axis and Colorbar, Legend, Text printing, MathGL core
+ at section Оси и Colorbar
+ at nav{}
+ at cindex Axis
+ at cindex Box
+ at cindex Grid
+ at cindex Colorbar
+ at cindex Label
+
+Эти функции рисуют объекты для "измерения" типа осей координат, цветовой таблицы (colorbar), сетку по осям, обрамляющий параллелепипед и подписи по осям координат. См. также см. @ref{Axis settings}.
+
+ at anchor{axis}
+ at deftypefn {Команда MGL} {} axis ['dir'='xyz' 'stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Axis (@code{const char *}dir=@code{"xyz"}, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_axis (@code{HMGL} gr, @code{const char *}dir, @code{const char *}stl, @code{const char *}opt)
+ at end ifclear
+Рисует оси координат и метки на них (см. @ref{Axis settings}) в направлениях @samp{xyz}, указанных строкой @var{dir}. Строка @var{dir} может содержать:
+ at itemize
+ at item @samp{xyz} для рисования соответствующих осей;
+ at item @samp{XYZ} для рисования соответствующих осей с метками с другой стороны;
+ at item @samp{~} или @samp{_} для осей без подписей;
+ at item @samp{U} для невращаемых подписей;
+ at item @samp{^} для инвертирования положения по умолчанию;
+ at item @samp{!} для отключения улучшения вида меток (см. @ref{tuneticks});
+ at item @samp{AKDTVISO} для вывода стрелки на конце оси;
+ at item @samp{a} для принудительной автоматической расстановки меток;
+ at item @samp{f} для вывода чисел в фиксированном формате;
+ at item @samp{E} для вывода @samp{E} вместо @samp{e};
+ at item @samp{F} для вывода в формате LaTeX;
+ at item @samp{+} для вывода @samp{+} для положительных чисел;
+ at item @samp{-} для вывода обычного @samp{-};
+ at item @samp{0123456789} для задания точности при выводе чисел.
+ at end itemize
+Стиль меток и оси(ей) задается строкой @var{stl}. Опция @code{value} задает угол вращения меток оси. @sref{Axis and ticks}
+ at end deftypefn
+
+ at anchor{colorbar}
+ at deftypefn {Команда MGL} {} colorbar ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Colorbar (@code{const char *}sch=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_colorbar (@code{HMGL} gr, @code{const char *}sch)
+ at end ifclear
+Рисует полосу соответствия цвета и числовых значений (colorbar) для цветовой схемы @var{sch} (используется текущая для @code{sch=""}) с краю от графика. Строка @var{sch} также может содержать:
+ at itemize
+ at item @samp{<>^_} для расположения слева, справа, сверху или снизу соответственно;
+ at item @samp{I} для расположения около осей (по умолчанию, на краях subplot);
+ at item @samp{A} для использования абсолютных координат (относительно рисунка);
+ at item @samp{~} для colorbar без подписей;
+ at item @samp{!} для отключения улучшения вида меток (см. @ref{tuneticks});
+ at item @samp{a} для принудительной автоматической расстановки меток;
+ at item @samp{f} для вывода чисел в фиксированном формате;
+ at item @samp{E} для вывода @samp{E} вместо @samp{e};
+ at item @samp{F} для вывода в формате LaTeX;
+ at item @samp{+} для вывода @samp{+} для положительных чисел;
+ at item @samp{-} для вывода обычного @samp{-};
+ at item @samp{0123456789} для задания точности при выводе чисел.
+ at end itemize
+ at sref{Colorbars}
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} colorbar vdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Colorbar (@code{const mglDataA &}v, @code{const char *}sch=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_colorbar_val (@code{HMGL} gr, @code{HCDT} v, @code{const char *}sch)
+ at end ifclear
+Аналогично предыдущему, но для цветовой схемы без сглаживания с заданными значениями @var{v}. @sref{ContD sample}
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} colorbar 'sch' @code{x y [w=1 h=1]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Colorbar (@code{const char *}sch, @code{mreal} x, @code{mreal} y, @code{mreal} w=@code{1}, @code{mreal} h=@code{1})
+ at deftypefnx {Функция С} @code{void} mgl_colorbar_ext (@code{HMGL} gr, @code{const char *}sch, @code{mreal} x, @code{mreal} y, @code{mreal} w, @code{mreal} h)
+ at end ifclear
+Аналогично первому, но в произвольном месте графика @{@var{x}, @var{y}@} (полагаются в диапазоне [0,1]). Параметры @var{w}, @var{h} задают относительную ширину и высоту colorbar.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} colorbar vdat 'sch' @code{x y [w=1 h=1]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Colorbar (@code{const mglDataA &}v, @code{const char *}sch, @code{mreal} x, @code{mreal} y, @code{mreal} w=@code{1}, @code{mreal} h=@code{1})
+ at deftypefnx {Функция С} @code{void} mgl_colorbar_val_ext (@code{HMGL} gr, @code{HCDT} v, @code{const char *}sch, @code{mreal} x, @code{mreal} y, @code{mreal} w, @code{mreal} h)
+ at end ifclear
+Аналогично предыдущему, но для цветовой схемы @var{sch} без сглаживания с заданными значениями @var{v}. @sref{ContD sample}
+ at end deftypefn
+
+ at anchor{grid}
+ at deftypefn {Команда MGL} {} grid ['dir'='xyz' 'pen'='B']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Grid (@code{const char *}dir=@code{"xyz"}, @code{const char *}pen=@code{"B"}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_axis_grid (@code{HMGL} gr, @code{const char *}dir, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Рисует линии сетки в направлениях перпендикулярным @var{dir}. Если @var{dir} содержит @samp{!}, то линии рисуются также и для координат под-меток. Шаг сетки такой же как у меток осей координат. Стиль линий задается параметром @var{pen} (по умолчанию -- сплошная темно синяя линия @samp{B-}).
+ at end deftypefn
+
+ at anchor{box}
+ at deftypefn {Команда MGL} {} box ['stl'='k' @code{ticks=on}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Box (@code{const char *}col=@code{""}, @code{bool} ticks=@code{true})
+ at deftypefnx {Функция С} @code{void} mgl_box (@code{HMGL} gr)
+ at deftypefnx {Функция С} @code{void} mgl_box_str (@code{HMGL} gr, @code{const char *}col, @code{int} ticks)
+ at end ifclear
+Рисует ограничивающий параллелепипед цветом @var{col}. Если @var{col} содержит @samp{@@}, то рисуются закрашенные задние грани. При этом первый цвет используется для граней (по умолчанию светло жёлтый), а последний для рёбер и меток.
+ at end deftypefn
+
+ at anchor{xlabel}
+ at anchor{ylabel}
+ at anchor{zlabel}
+ at anchor{tlabel}
+ at deftypefn {Команда MGL} {} xlabel 'text' [@code{pos=1}]
+ at deftypefnx {Команда MGL} {} ylabel 'text' [@code{pos=1}]
+ at deftypefnx {Команда MGL} {} zlabel 'text' [@code{pos=1}]
+ at deftypefnx {Команда MGL} {} tlabel 'text' [@code{pos=1}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Label (@code{char} dir, @code{const char *}text, @code{mreal} pos=@code{1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Label (@code{char} dir, @code{const wchar_t *}text, @code{mreal} pos=@code{1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_label (@code{HMGL} gr, @code{char} dir, @code{const char *}text, @code{mreal} pos, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_labelw (@code{HMGL} gr, @code{char} dir, @code{const wchar_t *}text, @code{mreal} pos, @code{const char *}opt)
+ at end ifclear
+Выводит подпись @var{text} для оси @var{dir}=@samp{x}, at samp{y}, at samp{z}, at samp{t} (где @samp{t} -- ``тернарная'' ось @math{t=1-x-y}). Параметр @var{pos} задает положение подписи: при @var{pos}=0 -- по центру оси, при @var{pos}>0 -- около максимальных значений, при @var{pos}<0 -- около минимальных значений. Опция @code{value} задает дополнительный сдвиг текста. @xref{Text printing}.
+ at end deftypefn
+
+ at c ##################################################################
+ at external{}
+ at node Legend, 1D plotting, Axis and Colorbar, MathGL core
+ at section Легенда
+ at nav{}
+ at cindex Legend
+ at cindex AddLegend
+ at cindex ClearLegend
+ at cindex SetLegendBox
+ at cindex SetLegendMarks
+
+Эти функции обеспечивают рисование легенды графика (полезно для @ref{1D plotting}). Запись в легенде состоит из двух строк: одна для стиля линии и маркеров, другая с текстом описания (с включенным разбором TeX-их команд). Можно использовать непосредственно массивы строк, или накопление во внутренние массивы с помощью функции AddLegend() с последующим отображением. Положение легенды можно задать автоматически или вручную. Параметры @var{fnt} и @var{size} задают стиль и размер шрифта (см.  [...]
+ at itemize @bullet
+ at item
+стиль текста для записей;
+ at item
+ at samp{A} для расположения относительно всего рисунка, а не текущего subplot;
+ at item
+ at samp{^} для размещения снаружи от указанных координат;
+ at item
+ at samp{#} для вывода прямоугольника вокруг легенды;
+ at item
+ at samp{-} для горизонтального расположения записей;
+ at item
+цвета для заливки (1-ый), для границы (2-ой) и для текста записей (3-ий). Если указано меньше трех цветов, то цвет границы черный (для 2 и менее цветов), и цвет заливки белый (для 1 и менее цвета).
+ at end itemize
+ at sref{Legend sample}
+
+ at anchor{legend}
+ at deftypefn {Команда MGL} {} legend [@code{pos=3} 'fnt'='#']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Legend (@code{int} pos=@code{0x3}, @code{const char *}fnt=@code{"#"}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_legend (@code{HMGL} gr, @code{int} pos, @code{const char *}fnt, @code{const char *}opt)
+ at end ifclear
+Рисует легенду из накопленных записей шрифтом @var{fnt}. Параметр @var{pos} задает положение легенды: @samp{0} -- в нижнем левом углу, @samp{1} -- нижнем правом углу, @samp{2} -- верхнем левом углу, @samp{3} -- верхнем правом углу (по умолчанию). Опция @code{value} задает зазор между примером линии и текстом (по умолчанию 0.1).
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} legend @code{x y} ['fnt'='#']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Legend (@code{mreal} x, @code{mreal} y, @code{const char *}fnt=@code{"#"}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_legend_pos (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{const char *}fnt, @code{const char *}opt)
+ at end ifclear
+Рисует легенду из накопленных записей шрифтом @var{fnt}. Положение легенды задается параметрами @var{x}, @var{y}, которые полагаются нормированными в диапазоне [0,1]. Опция @code{value} задает зазор между примером линии и текстом (по умолчанию 0.1).
+ at end deftypefn
+
+ at anchor{addlegend}
+ at deftypefn {Команда MGL} {} addlegend 'text' 'stl'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} AddLegend (@code{const char *}text, @code{const char *}style)
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} AddLegend (@code{const wchar_t *}text, @code{const char *}style)
+ at deftypefnx {Функция С} @code{void} mgl_add_legend (@code{HMGL} gr, @code{const char *}text, @code{const char *}style)
+ at deftypefnx {Функция С} @code{void} mgl_add_legendw (@code{HMGL} gr, @code{const wchar_t *}text, @code{const char *}style)
+ at end ifclear
+Добавляет описание @var{text} кривой со стилем @var{style} (см. @ref{Line styles}) во внутренний массив записей легенды.
+ at end deftypefn
+
+ at anchor{clearlegend}
+ at deftypefn {Команда MGL} {} clearlegend
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ClearLegend ()
+ at deftypefnx {Функция С} @code{void} mgl_clear_legend (@code{HMGL} gr)
+ at end ifclear
+Очищает внутренний массив записей легенды.
+ at end deftypefn
+
+ at anchor{legendmarks}
+ at deftypefn {Команда MGL} {} legendmarks @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SetLegendMarks (@code{int} num)
+ at deftypefnx {Функция С} @code{void} mgl_set_legend_marks (@code{HMGL} gr, @code{int} num)
+ at end ifclear
+Задает число маркеров в легенде. По умолчанию используется 1 маркер.
+ at end deftypefn
+
+ at c ##################################################################
+ at external{}
+ at node 1D plotting, 2D plotting, Legend, MathGL core
+ at section 1D графики
+ at nav{}
+ at cindex Plot
+ at cindex Radar
+ at cindex Tens
+ at cindex Area
+ at cindex Region
+ at cindex Stem
+ at cindex Bars
+ at cindex Barh
+ at cindex Chart
+ at cindex Step
+ at cindex Torus
+ at cindex Tube
+ at cindex Mark
+ at cindex TextMark
+ at cindex Error
+ at cindex BoxPlot
+ at cindex Candle
+ at cindex Tape
+ at cindex Label
+ at cindex Cones
+
+Эти функции строят графики для одномерных (1D) массивов. Одномерными считаются массивы, зависящие только от одного параметра (индекса) подобно кривой в параметрической форме @{x(i),y(i),z(i)@}, i=1...n. По умолчанию (если отсутствуют) значения @var{x}[i] равно распределены в диапазоне оси х, и @var{z}[i] равно минимальному значению оси z. Графики рисуются для каждой строки массива данных если он двумерный. Размер по 1-ой координате @strong{должен быть одинаков} для всех массивов @code{x. [...]
+
+Строка @var{pen} задает цвет и стиль линии и маркеров (см. @ref{Line styles}). По умолчанию (@code{pen=""}) рисуется сплошная линия с текущим цветом из палитры (см. @ref{Palette and colors}). Символ @samp{!} в строке задает использование нового цвета из палитры для каждой точки данных (не для всей кривой, как по умолчанию). Строка @var{opt} задает опции графика (см. @ref{Command options}). @sref{1D samples}
+
+ at anchor{plot}
+ at deftypefn {Команда MGL} {} plot ydat ['stl'='']
+ at deftypefnx {Команда MGL} {} plot xdat ydat ['stl'='']
+ at deftypefnx {Команда MGL} {} plot xdat ydat zdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Plot (@code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Plot (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Plot (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_plot (@code{HMGL} gr, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_plot_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_plot_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Функции рисуют ломанную линию по точкам @{@var{x}[i], @var{y}[i], @var{z}[i]@}. Если @var{pen} содержит @samp{a}, то рисуются и сегменты между точками вне диапазона осей координат. См. также @ref{area}, @ref{step}, @ref{stem}, @ref{tube}, @ref{mark}, @ref{error}, @ref{belt}, @ref{tens}, @ref{tape}, @ref{meshnum}. @sref{Plot sample}
+ at end deftypefn
+
+ at anchor{radar}
+ at deftypefn {Команда MGL} {} radar adat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Radar (@code{const mglDataA &}a, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_radar (@code{HMGL} gr, @code{HCDT} a, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Функции рисуют radar chart, представляющий собой ломанную с вершинами на радиальных линиях (типа ломанной в полярных координатах). Параметр @code{value} в опциях @var{opt} задает дополнительный сдвиг данных (т.е. использование @var{a}+ at code{value} вместо @var{a}). Если @var{pen} содержит @samp{#}, то рисуется "сетка" (радиальные линии). Если @var{pen} содержит @samp{a}, то рисуются и сегменты между точками вне диапазона осей координат. См. также @ref{plot}, @ref{meshnum}. @sref{Radar sample}
+ at end deftypefn
+
+ at anchor{step}
+ at deftypefn {Команда MGL} {} step ydat ['stl'='']
+ at deftypefnx {Команда MGL} {} step xdat ydat ['stl'='']
+ at deftypefnx {Команда MGL} {} step xdat ydat zdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Step (@code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Step (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Step (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_step (@code{HMGL} gr, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_step_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_step_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Функции рисуют ступеньки для точек массива. Если @var{x}.nx>@var{y}.nx, то массив @var{x} задает границы ступенек, а не их конец. См. также @ref{plot}, @ref{stem}, @ref{tile}, @ref{boxs}, @ref{meshnum}. @sref{Step sample}
+ at end deftypefn
+
+ at anchor{tens}
+ at deftypefn {Команда MGL} {} tens ydat cdat ['stl'='']
+ at deftypefnx {Команда MGL} {} tens xdat ydat cdat ['stl'='']
+ at deftypefnx {Команда MGL} {} tens xdat ydat zdat cdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Tens (@code{const mglDataA &}y, @code{const mglDataA &}c, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Tens (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}c, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Tens (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}c, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_tens (@code{HMGL} gr, @code{HCDT} y, @code{HCDT} c, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_tens_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} c, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_tens_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} c, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Функции рисуют ломанную линию по точкам с цветом, определяемым массивом @var{c} (типа графика натяжений). Строка @var{pen} задает цветовую схему (см. @ref{Color scheme}) и стиль линий и/или маркеров (см. @ref{Line styles}). Если @var{pen} содержит @samp{a}, то рисуются и сегменты между точками вне диапазона осей координат. См. также @ref{plot}, @ref{mesh}, @ref{fall}, @ref{meshnum}. @sref{Tens sample}
+ at end deftypefn
+
+ at anchor{tape}
+ at deftypefn {Команда MGL} {} tape ydat ['stl'='']
+ at deftypefnx {Команда MGL} {} tape xdat ydat ['stl'='']
+ at deftypefnx {Команда MGL} {} tape xdat ydat zdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Tape (@code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Tape (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Tape (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_tape (@code{HMGL} gr, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_tape_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_tape_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Функции рисуют ленты, которые вращаются вокруг кривой @{@var{x}[i], @var{y}[i], @var{z}[i]@} как её нормали. Начальная лента(ы) выбираются в плоскости x-y (для @samp{x} в @var{pen}) и/или y-z (для @samp{x} в @var{pen}). Ширина лент пропорциональна @ref{barwidth}, а также может быть изменена опцией @code{value}. См. также @ref{plot}, @ref{flow}, @ref{barwidth}. @sref{Tape sample}
+ at end deftypefn
+
+ at anchor{area}
+ at deftypefn {Команда MGL} {} area ydat ['stl'='']
+ at deftypefnx {Команда MGL} {} area xdat ydat ['stl'='']
+ at deftypefnx {Команда MGL} {} area xdat ydat zdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Area (@code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Area (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Area (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_area (@code{HMGL} gr, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_area_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_area_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Функции рисуют ломанную линию между точками и закрашивает её вниз до плоскости осей координат. Градиентная заливка используется если число цветов равно удвоенному число кривых. Если @var{pen} содержит @samp{#}, то рисуется только каркас. Если @var{pen} содержит @samp{a}, то рисуются и сегменты между точками вне диапазона осей координат. См. также @ref{plot}, @ref{bars}, @ref{stem}, @ref{region}. @sref{Area sample}
+ at end deftypefn
+
+ at anchor{region}
+ at deftypefn {Команда MGL} {} region ydat1 ydat2 ['stl'='']
+ at deftypefnx {Команда MGL} {} region xdat ydat1 ydat2 ['stl'='']
+ at deftypefnx {Команда MGL} {} region xdat1 ydat1 xdat2 ydat2 ['stl'='']
+ at deftypefnx {Команда MGL} {} region xdat1 ydat1 zdat1 xdat2 ydat2 zdat2 ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Region (@code{const mglDataA &}y1, @code{const mglDataA &}y2, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Region (@code{const mglDataA &}x, @code{const mglDataA &}y1, @code{const mglDataA &}y2, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Region (@code{const mglDataA &}x1, @code{const mglDataA &}y1, @code{const mglDataA &}x2, @code{const mglDataA &}y2, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Region (@code{const mglDataA &}x1, @code{const mglDataA &}y1, @code{const mglDataA &}z1, @code{const mglDataA &}x2, @code{const mglDataA &}y2, @code{const mglDataA &}z2, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_region (@code{HMGL} gr, @code{HCDT} y1, @code{HCDT} y2, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_region_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y1, @code{HCDT} y2, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_region_3d (@code{HMGL} gr, @code{HCDT} x1, @code{HCDT} y1, @code{HCDT} z1, @code{HCDT} x2, @code{HCDT} y2, @code{HCDT} z2, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Функции закрашивают область между 2 кривыми. Градиентная заливка используется если число цветов равно удвоенному число кривых. Если в 2d версии @var{pen} содержит @samp{i}, то закрашивается только область y1<y<y2, в противном случае будет закрашена и область y2<y<y1. Если @var{pen} содержит @samp{#}, то рисуется только каркас. Если @var{pen} содержит @samp{a}, то рисуются и сегменты между точками вне диапазона осей координат. См. также @ref{area}, @ref{bars}, @ref{stem}. @sref{Region sample}
+ at end deftypefn
+
+ at anchor{stem}
+ at deftypefn {Команда MGL} {} stem ydat ['stl'='']
+ at deftypefnx {Команда MGL} {} stem xdat ydat ['stl'='']
+ at deftypefnx {Команда MGL} {} stem xdat ydat zdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Stem (@code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Stem (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Stem (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_stem (@code{HMGL} gr, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_stem_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_stem_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Функции рисуют вертикальные линии из точек до плоскости осей координат. См. также @ref{area}, @ref{bars}, @ref{plot}, @ref{mark}. @sref{Stem sample}
+ at end deftypefn
+
+ at anchor{bars}
+ at deftypefn {Команда MGL} {} bars ydat ['stl'='']
+ at deftypefnx {Команда MGL} {} bars xdat ydat ['stl'='']
+ at deftypefnx {Команда MGL} {} bars xdat ydat zdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Bars (@code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Bars (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Bars (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_bars (@code{HMGL} gr, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_bars_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_bars_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Функции рисуют вертикальные полосы (прямоугольники) из точек до плоскости осей координат. Строка @var{pen} может содержать:
+ at itemize @bullet
+ at item
+ at samp{a} для вывода линий одной поверх другой (как при суммировании);
+ at item
+ at samp{f} для определения кумулятивного эффекта последовательности положительных и отрицательных значений (график типа waterfall);
+ at item
+ at samp{F} для использования одинаковой (минимальной) ширины полосок;
+ at item
+ at samp{<}, @samp{^} or @samp{>} для выравнивания полосок влево, вправо или центрирования относительно их координат.
+ at end itemize
+Можно использовать разные цвета для положительных и отрицательных значений если число указанных цветов равно удвоенному числу кривых для построения. Если @var{x}.nx>@var{y}.nx, то массив @var{x} задает границы полос, а не их центр. См. также @ref{barh}, @ref{cones}, @ref{area}, @ref{stem}, @ref{chart}, @ref{barwidth}. @sref{Bars sample}
+ at end deftypefn
+
+ at anchor{barh}
+ at deftypefn {Команда MGL} {} barh vdat ['stl'='']
+ at deftypefnx {Команда MGL} {} barh ydat vdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Barh (@code{const mglDataA &}v, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Barh (@code{const mglDataA &}y, @code{const mglDataA &}v, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_barh (@code{HMGL} gr, @code{HCDT} v, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_barh_xy (@code{HMGL} gr, @code{HCDT} y, @code{HCDT} v, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Функции рисуют горизонтальные полосы (прямоугольники) из точек до плоскости осей координат. Строка @var{pen} может содержать:
+ at itemize @bullet
+ at item
+ at samp{a} для вывода линий одной поверх другой (как при суммировании);
+ at item
+ at samp{f} для определения кумулятивного эффекта последовательности положительных и отрицательных значений (график типа waterfall);
+ at item
+ at samp{F} для использования одинаковой (минимальной) ширины полосок;
+ at item
+ at samp{<}, @samp{^} or @samp{>} для выравнивания полосок влево, вправо или центрирования относительно их координат.
+ at end itemize
+Можно использовать разные цвета для положительных и отрицательных значений если число указанных цветов равно удвоенному числу кривых для построения. Если @var{x}.nx>@var{y}.nx, то массив @var{x} задает границы полос, а не их центр. См. также @ref{bars}, @ref{barwidth}. @sref{Barh sample}
+ at end deftypefn
+
+ at anchor{cones}
+ at deftypefn {Команда MGL} {} cones ydat ['stl'='']
+ at deftypefnx {Команда MGL} {} cones xdat ydat ['stl'='']
+ at deftypefnx {Команда MGL} {} cones xdat ydat zdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Cones (@code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Cones (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Cones (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_cones (@code{HMGL} gr, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_cones_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_cones_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Функции рисуют конусы из точек до плоскости осей координат. Если строка @var{pen} содержит символ @samp{a}, то линии рисуются одна поверх другой. Можно использовать разные цвета для положительных и отрицательных значений если число указанных цветов равно удвоенному числу кривых для построения. Параметр @var{pen} может содержать:
+ at itemize @bullet
+ at item
+ at samp{@@} для рисования торцов;
+ at item
+ at samp{#} для сетчатой фигуры;
+ at item
+ at samp{t} для рисования цилиндра вместо конуса/призмы;
+ at item
+ at samp{4}, @samp{6}, @samp{8} для рисования квадратной, шестиугольной или восьмиугольной призмы вместо конуса;
+ at item
+ at samp{<}, @samp{^} или @samp{>} для выравнивания конусов влево, вправо или по центру относительно их координат.
+ at end itemize
+См. также @ref{bars}, @ref{cone}, @ref{barwidth}. @sref{Cones sample}
+ at end deftypefn
+
+
+
+ at anchor{chart}
+ at deftypefn {Команда MGL} {} chart adat ['col'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Chart (@code{const mglDataA &}a, @code{const char *}col=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_chart (@code{HMGL} gr, @code{HCDT} a, @code{const char *}col, @code{const char *}opt)
+ at end ifclear
+Рисует цветные полосы (пояса) для массива данных @var{a}. Число полос равно числу строк @var{a} (равно @var{a.ny}). Цвет полос поочерёдно меняется из цветов указанных в @var{col} или в палитре (см. @ref{Palette and colors}). Пробел в цветах соответствует прозрачному "цвету", т.е. если @var{col} содержит пробел(ы), то соответствующая полоса не рисуется. Ширина полосы пропорциональна значению элемента в @var{a}. График строится только для массивов не содержащих отрицательных значений. Если [...]
+ at end deftypefn
+
+ at anchor{boxplot}
+ at deftypefn {Команда MGL} {} boxplot adat ['stl'='']
+ at deftypefnx {Команда MGL} {} boxplot xdat adat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} BoxPlot (@code{const mglDataA &}a, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} BoxPlot (@code{const mglDataA &}x, @code{const mglDataA &}a, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_boxplot (@code{HMGL} gr, @code{HCDT} a, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_boxplot_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} a, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Функции рисуют boxplot (называемый также как box-and-whisker diagram или как "ящик с усами") в точках @var{x}[i] на плоскости @var{z} = @var{zVal} (по умолчанию @var{z} равно минимальному значению оси z). Это график, компактно изображающий распределение вероятностей @var{a}[i,j] (минимум, нижний квартиль (Q1), медиана (Q2), верхний квартиль (Q3) и максимум) вдоль второго (j-го) направления. Если @var{pen} содержит @samp{<}, @samp{^} или @samp{>}, то полоски будут выровнены влево, вправо  [...]
+ at end deftypefn
+
+ at anchor{candle}
+ at deftypefn {Команда MGL} {} candle vdat1 ['stl'='']
+ at deftypefnx {Команда MGL} {} candle vdat1 vdat2 ['stl'='']
+ at deftypefnx {Команда MGL} {} candle vdat1 ydat1 ydat2 ['stl'='']
+ at deftypefnx {Команда MGL} {} candle vdat1 vdat2 ydat1 ydat2 ['stl'='']
+ at deftypefnx {Команда MGL} {} candle xdat vdat1 vdat2 ydat1 ydat2 ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Candle (@code{const mglDataA &}v1, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Candle (@code{const mglDataA &}v1, @code{const mglDataA &}v2, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Candle (@code{const mglDataA &}v1, @code{const mglDataA &}y1, @code{const mglDataA &}y2, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Candle (@code{const mglDataA &}v1, @code{const mglDataA &}v2, @code{const mglDataA &}y1, @code{const mglDataA &}y2, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Candle (@code{const mglDataA &}x, @code{const mglDataA &}v1, @code{const mglDataA &}v2, @code{const mglDataA &}y1, @code{const mglDataA &}y2, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_candle (@code{HMGL} gr, @code{HCDT} v1, @code{HCDT} y1, @code{HCDT} y2, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_candle_yv (@code{HMGL} gr, @code{HCDT} v1, @code{HCDT} v2, @code{HCDT} y1, @code{HCDT} y2, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_candle_xyv (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} v1, @code{HCDT} v2, @code{HCDT} y1, @code{HCDT} y2, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Функции рисуют candlestick chart в точках @var{x}[i]. Этот график показывает прямоугольником ("свечой") диапазон изменения величины. Прозрачная (белая) свеча соответствует росту величины @var{v1}[i]<@var{v2}[i], чёрная -- уменьшению. "Тени" показывают минимальное @var{y1} и максимальное @var{y2} значения. Если @var{v2} отсутствует, то он определяется как @var{v2}[i]=@var{v1}[i+1]. Можно использовать разные цвета для растущих и падающих дней если число указанных цветов равно удвоенному чи [...]
+ at end deftypefn
+
+ at anchor{ohlc}
+ at deftypefn {Команда MGL} {} ohlc odat hdat ldat cdat ['stl'='']
+ at deftypefnx {Команда MGL} {} ohlc xdat odat hdat ldat cdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {MМетод класса @code{mglGraph}} @code{void} OHLC (@code{const mglDataA &}o, @code{const mglDataA &}h, @code{const mglDataA &}l, @code{const mglDataA &}c, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} OHLC (@code{const mglDataA &}x, @code{const mglDataA &}o, @code{const mglDataA &}h, @code{const mglDataA &}l, @code{const mglDataA &}c, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_ohlc (@code{HMGL} gr, @code{HCDT} o, @code{HCDT} h, @code{HCDT} l, @code{HCDT} c, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_ohlc_x (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} o, @code{HCDT} h, @code{HCDT} l, @code{HCDT} c, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Функции рисуют Open-High-Low-Close диаграмму. Этот график содержит вертикальные линии между максимальным @var{h} и минимальным @var{l} значениями, и горизонтальные линии перед/после вертикальной линии для начального @var{o} и конечного @var{c} значений процесса (обычно цены). Можно использовать разные цвета для растущих и падающих дней если число указанных цветов равно удвоенному числу кривых для построения. См. также @ref{candle}, @ref{plot}, @ref{barwidth}. @sref{OHLC sample}
+ at end deftypefn
+
+
+ at anchor{error}
+ at deftypefn {Команда MGL} {} error ydat yerr ['stl'='']
+ at deftypefnx {Команда MGL} {} error xdat ydat yerr ['stl'='']
+ at deftypefnx {Команда MGL} {} error xdat ydat xerr yerr ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Error (@code{const mglDataA &}y, @code{const mglDataA &}ey, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Error (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}ey, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Error (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}ex, @code{const mglDataA &}ey, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_error (@code{HMGL} gr, @code{HCDT} y, @code{HCDT} ey, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_error_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} ey, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_error_exy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} ex, @code{HCDT} ey, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Функции рисуют размер ошибки @{@var{ex}[i], @var{ey}[i]@} в точках @{@var{x}[i], @var{y}[i]@} на плоскости @var{z} = @var{zVal} (по умолчанию @var{z} равно минимальному значению оси z). Такой график полезен для отображения ошибки эксперимента, вычислений и пр. Если @var{pen} содержит @samp{@@}, то будут использованы большие полупрозрачные маркеры. См. также @ref{plot}, @ref{mark}. @sref{Error sample}
+ at end deftypefn
+
+ at anchor{mark}
+ at deftypefn {Команда MGL} {} mark ydat rdat ['stl'='']
+ at deftypefnx {Команда MGL} {} mark xdat ydat rdat ['stl'='']
+ at deftypefnx {Команда MGL} {} mark xdat ydat zdat rdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Mark (@code{const mglDataA &}y, @code{const mglDataA &}r, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Mark (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}r, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Mark (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}r, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_mark_y (@code{HMGL} gr, @code{HCDT} y, @code{HCDT} r, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_mark_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} r, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_mark_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} r, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Функции рисуют маркеры размером @var{r}[i]*@ref{marksize} (см. @ref{Default sizes}) в точках @{@var{x}[i], @var{y}[i], @var{z}[i]@}. Для рисования маркеров одинакового размера можно использовать функцию @ref{plot} с невидимой линией (со стилем содержащим @samp{ }). Для маркеров с размером как у координат можно использовать @ref{error} со стилем @samp{@@}. См. также @ref{plot}, @ref{textmark}, @ref{error}, @ref{stem}, @ref{meshnum}. @sref{Mark sample}
+ at end deftypefn
+
+ at anchor{textmark}
+ at deftypefn {Команда MGL} {} textmark ydat 'txt' ['stl'='']
+ at deftypefnx {Команда MGL} {} textmark ydat rdat 'txt' ['stl'='']
+ at deftypefnx {Команда MGL} {} textmark xdat ydat rdat 'txt' ['stl'='']
+ at deftypefnx {Команда MGL} {} textmark xdat ydat zdat rdat 'txt' ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} TextMark (@code{const mglDataA &}y, @code{const char *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} TextMark (@code{const mglDataA &}y, @code{const wchar_t *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} TextMark (@code{const mglDataA &}y, @code{const mglDataA &}r, @code{const char *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} TextMark (@code{const mglDataA &}y, @code{const mglDataA &}r, @code{const wchar_t *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} TextMark (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}r, @code{const char *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} TextMark (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}r, @code{const wchar_t *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} TextMark (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}r, @code{const char *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} TextMark (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}r, @code{const wchar_t *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_textmark (@code{HMGL} gr, @code{HCDT} y, @code{const char *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_textmarkw (@code{HMGL} gr, @code{HCDT} y, @code{const wchar_t *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_textmark_yr (@code{HMGL} gr, @code{HCDT} y, @code{HCDT} r, @code{const char *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_textmarkw_yr (@code{HMGL} gr, @code{HCDT} y, @code{HCDT} r, @code{const wchar_t *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_textmark_xyr (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} r, @code{const char *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_textmarkw_xyr (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} r, @code{const wchar_t *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_textmark_xyzr (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} r, @code{const char *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_textmarkw_xyzr (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} r, @code{const wchar_t *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at end ifclear
+Функции рисуют текст @var{txt} как маркер с размером пропорциональным @var{r}[i]*@var{marksize} в точках @{@var{x}[i], @var{y}[i], @var{z}[i]@}. См. также @ref{plot}, @ref{mark}, @ref{stem}, @ref{meshnum}. @sref{TextMark sample}
+ at end deftypefn
+
+ at anchor{label}
+ at deftypefn {Команда MGL} {} label ydat 'txt' ['stl'='']
+ at deftypefnx {Команда MGL} {} label xdat ydat 'txt' ['stl'='']
+ at deftypefnx {Команда MGL} {} label xdat ydat zdat 'txt' ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Label (@code{const mglDataA &}y, @code{const char *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Label (@code{const mglDataA &}y, @code{const wchar_t *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Label (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const char *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Label (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const wchar_t *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Label (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Label (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const wchar_t *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_label (@code{HMGL} gr, @code{HCDT} y, @code{const char *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_labelw (@code{HMGL} gr, @code{HCDT} y, @code{const wchar_t *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_label_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{const char *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_labelw_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{const wchar_t *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_label_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_labelw_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const wchar_t *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at end ifclear
+Функции выводят текстовую строку @var{txt} в точках @{@var{x}[i], @var{y}[i], @var{z}[i]@}. Если строка @var{txt} содержит @samp{%x}, @samp{%y}, @samp{%z} или @samp{%n}, то они будут заменены на значения соответствующих координат или на номер точки. Строка @var{fnt} может содержать:
+ at itemize
+ at item стиль текста @ref{Font styles};
+ at item @samp{f} для вывода чисел в фиксированном формате;
+ at item @samp{E} для вывода @samp{E} вместо @samp{e};
+ at item @samp{F} для вывода в формате LaTeX;
+ at item @samp{+} для вывода @samp{+} для положительных чисел;
+ at item @samp{-} для вывода обычного @samp{-};
+ at item @samp{0123456789} для задания точности при выводе чисел.
+ at end itemize
+См. также @ref{plot}, @ref{mark}, @ref{textmark}, @ref{table}. @sref{Label sample}
+ at end deftypefn
+
+ at anchor{table}
+ at deftypefn {Команда MGL} {} table vdat 'txt' ['stl'='#']
+ at deftypefnx {Команда MGL} {} table x y vdat 'txt' ['stl'='#']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Table (@code{const mglDataA &}val, @code{const char *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Table (@code{const mglDataA &}val, @code{const wchar_t *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Table (@code{mreal} x, @code{mreal} y, @code{const mglDataA &}val, @code{const char *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Table (@code{mreal} x, @code{mreal} y, @code{const mglDataA &}val, @code{const wchar_t *}txt, @code{const char *}fnt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_table (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{HCDT} val, @code{const char *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_tablew (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{HCDT} val, @code{const wchar_t *}txt, @code{const char *}fnt, @code{const char *}opt)
+ at end ifclear
+Рисует таблицу значений массива @var{val} с заголовками @var{txt} (разделенными символом новой строки @samp{\n}) в точке @{@var{x}, @var{y}@} (по умолчанию @{0,0@}) относительно текущего subplot. Строка @var{fnt} может содержать:
+ at itemize
+ at item стиль текста @ref{Font styles};
+ at item @samp{#} для рисования границ ячеек;
+ at item @samp{=} для одинаковой ширины всех ячеек;
+ at item @samp{|} для ограничения ширины таблицы шириной subplot (эквивалентно опции @samp{value 1});
+ at item @samp{f} для вывода чисел в фиксированном формате;
+ at item @samp{E} для вывода @samp{E} вместо @samp{e};
+ at item @samp{F} для вывода в формате LaTeX;
+ at item @samp{+} для вывода @samp{+} для положительных чисел;
+ at item @samp{-} для вывода обычного @samp{-};
+ at item @samp{0123456789} для задания точности при выводе чисел.
+ at end itemize
+Опция @code{value} задает ширину таблицы (по умолчанию 1). См. также @ref{plot}, @ref{label}. @sref{Table sample}
+ at end deftypefn
+
+ at anchor{iris}
+ at deftypefn {Команда MGL} {} iris dats 'ids' ['stl'='']
+ at deftypefnx {Команда MGL} {} iris dats rngs 'ids' ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Iris (@code{const mglDataA &}dats, @code{const char *}ids, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Iris (@code{const mglDataA &}dats, @code{const wchar_t *}ids, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Iris (@code{const mglDataA &}dats, @code{const mglDataA &}rngs, @code{const char *}ids, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Iris (@code{const mglDataA &}dats, @code{const mglDataA &}rngs, @code{const wchar_t *}ids, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_iris_1 (@code{HMGL} gr, @code{HCDT} dats, @code{const char *}ids, @code{const char *}stl, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_irisw_1 (@code{HMGL} gr, @code{HCDT} dats, @code{const wchar_t *}ids, @code{const char *}stl, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_iris (@code{HMGL} gr, @code{HCDT} dats, @code{HCDT} rngs, @code{const char *}ids, @code{const char *}stl, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_irisw (@code{HMGL} gr, @code{HCDT} dats, @code{HCDT} rngs, @code{const wchar_t *}ids, @code{const char *}stl, @code{const char *}opt)
+ at end ifclear
+Рисует Ирисы Фишера для определения зависимостей данных @var{dats} друг от друга (см. @uref{http://en.wikipedia.org/wiki/Iris_flower_data_set}). Массив @var{rngs} размером 2*@var{dats}.nx задает диапазон изменения осей для каждой из колонки. Строка @var{ids} содержит имена колонок данных, разделенных символом @samp{;}. Опция @code{value} задает размер текста для имен данных. На график можно добавить новый набор данных если указать тот же размер @var{rngs} и использовать пустую строку име [...]
+ at end deftypefn
+
+ at anchor{tube}
+ at deftypefn {Команда MGL} {} tube ydat rdat ['stl'='']
+ at deftypefnx {Команда MGL} {} tube ydat @code{rval} ['stl'='']
+ at deftypefnx {Команда MGL} {} tube xdat ydat rdat ['stl'='']
+ at deftypefnx {Команда MGL} {} tube xdat ydat @code{rval} ['stl'='']
+ at deftypefnx {Команда MGL} {} tube xdat ydat zdat rdat ['stl'='']
+ at deftypefnx {Команда MGL} {} tube xdat ydat zdat @code{rval} ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Tube (@code{const mglDataA &}y, @code{const mglDataA &}r, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Tube (@code{const mglDataA &}y, @code{mreal} r, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Tube (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}r, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Tube (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{mreal} r, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Tube (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}r, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Tube (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{mreal} r, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_tube_r (@code{HMGL} gr, @code{HCDT} y, @code{HCDT} r, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_tube (@code{HMGL} gr, @code{HCDT} y, @code{mreal} r, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_tube_xyr (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} r, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_tube_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{mreal} r, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_tube_xyzr (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} r, @code{const char *}pen, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_tube_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{mreal} r, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Функции рисуют трубу радиуса @var{r}[i] вдоль кривой между точками @{@var{x}[i], @var{y}[i], @var{z}[i]@}. См. также @ref{plot}. @sref{Tube sample}
+ at end deftypefn
+
+ at anchor{torus}
+ at deftypefn {Команда MGL} {} torus rdat zdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Torus (@code{const mglDataA &}r, @code{const mglDataA &}z, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_torus (@code{HMGL} gr, @code{HCDT} r, @code{HCDT} z, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Функции рисуют поверхность вращения кривой @{@var{r}, @var{z}@} относительно оси. Если строка @var{pen} содержит @samp{x} или @samp{z}, то ось вращения будет выбрана в указанном направлении (по умолчанию вдоль оси y). Если @var{sch} содержит @samp{#}, то рисуется сетчатая поверхность. Если @var{sch} содержит @samp{.}, то рисуется поверхность из точек. См. также @ref{plot}, @ref{axial}. @sref{Torus sample}
+ at end deftypefn
+
+
+
+ at anchor{lamerey}
+ at deftypefn {Команда MGL} {} lamerey @code{x0} ydat ['stl'='']
+ at deftypefnx {Команда MGL} {} lamerey @code{x0} 'y(x)' ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Lamerey (@code{double} x0, @code{const mglDataA &}y, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Lamerey (@code{double} x0, @code{const char *}y, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_lamerey_dat (@code{HMGL} gr, @code{double} x0, @code{HCDT} y, @code{const char *}stl, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_lamerey_str (@code{HMGL} gr, @code{double} x0, @code{const char *}y, @code{const char *}stl, @code{const char *}opt)
+ at end ifclear
+Функции рисуют диаграмму Ламерея для точечного отображения x_new = y(x_old) начиная с точки @var{x0}. Строка @var{stl} может содержать стиль линии, символ @samp{v} для стрелок, символ @samp{~} для исключения первого сегмента. Опция @code{value} задает число сегментов для рисования (по умолчанию 20). См. также @ref{plot}, @ref{fplot}, @ref{bifurcation}, @ref{pmap}. @sref{Lamerey sample}
+ at end deftypefn
+
+ at anchor{bifurcation}
+ at deftypefn {Команда MGL} {} bifurcation @code{dx} ydat ['stl'='']
+ at deftypefnx {Команда MGL} {} bifurcation @code{dx} 'y(x)' ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Bifurcation (@code{double} dx, @code{const mglDataA &}y, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Bifurcation (@code{double} dx, @code{const char *}y, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_bifurcation_dat (@code{HMGL} gr, @code{double} dx, @code{HCDT} y, @code{const char *}stl, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_bifurcation_str (@code{HMGL} gr, @code{double} dx, @code{const char *}y, @code{const char *}stl, @code{const char *}opt)
+ at end ifclear
+Функции рисуют бифуркационную диаграмму (диаграмму удвоения периода) для точечного отображения x_new = y(x_old). Параметр @var{dx} задает точность по оси x. Строка @var{stl} задает цвет. Опция @code{value} задает число учитываемых стационарных точек (по умолчанию 1024). См. также @ref{plot}, @ref{fplot}, @ref{lamerey}. @sref{Bifurcation sample}
+ at end deftypefn
+
+ at anchor{pmap}
+ at deftypefn {Команда MGL} {} pmap ydat sdat ['stl'='']
+ at deftypefnx {Команда MGL} {} pmap xdat ydat sdat ['stl'='']
+ at deftypefnx {Команда MGL} {} pmap xdat ydat zdat sdat ['stl'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Pmap (@code{const mglDataA &}y, @code{const mglDataA &}s, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Pmap (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}s, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Pmap (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}s, @code{const char *}stl=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_pmap (@code{HMGL} gr, @code{HMDT} y, @code{HCDT} s, @code{const char *}stl, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_pmap_xy (@code{HMGL} gr, @code{HCDT} x, @code{HMDT} y, @code{HCDT} s, @code{const char *}stl, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_pmap_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HMDT} y, @code{HCDT} z, @code{HCDT} s, @code{const char *}stl, @code{const char *}opt)
+ at end ifclear
+Функции рисуют отображение Пуанкаре для кривой @{@var{x}, @var{y}, @var{z}@} при условии @var{s}=0. Проще говоря, рисуются точки пересечения кривой и поверхности. Строка @var{stl} задает стиль маркеров. См. также @ref{plot}, @ref{mark}, @ref{lamerey}. @sref{Pmap sample}
+ at end deftypefn
+
+
+ at c ##################################################################
+ at external{}
+ at node 2D plotting, 3D plotting, 1D plotting, MathGL core
+ at section 2D графики
+ at nav{}
+ at cindex Mesh
+ at cindex Fall
+ at cindex Belt
+ at cindex Surf
+ at cindex Boxs
+ at cindex Tile
+ at cindex Dens
+ at cindex Cont
+ at cindex ContF
+ at cindex ContD
+ at cindex Axial
+ at cindex Grad
+ at cindex Grid
+
+Эти функции строят графики для двумерных (2D) массивов. Двумерными считаются массивы, зависящие только от двух параметров (индексов) подобно матрице @math{f(x_i,y_j), i=1...n, j=1...m}. По умолчанию (если отсутствуют) значения @var{x}, @var{y} равно распределены в диапазоне осей координат. Младшие размерности массивов @var{x}, @var{y}, @var{z} должны быть одинаковы @code{x.nx=z.nx && y.nx=z.ny} или @code{x.nx=y.nx=z.nx && x.ny=y.ny=z.ny}. Массивы @var{x} и @var{y} могут быть векторами (н [...]
+
+ at anchor{surf}
+ at deftypefn {Команда MGL} {} surf zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} surf xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Surf (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Surf (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_surf (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_surf_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует параметрически заданную поверхность @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@}. Если @var{sch} содержит @samp{#}, то рисуется сетка на поверхности. Если @var{sch} содержит @samp{.}, то рисуется поверхность из точек. См. также @ref{mesh}, @ref{dens}, @ref{belt}, @ref{tile}, @ref{boxs}, @ref{surfc}, @ref{surfa}. @sref{Surf sample}
+ at end deftypefn
+
+ at anchor{mesh}
+ at deftypefn {Команда MGL} {} mesh zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} mesh xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Mesh (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Mesh (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_mesh (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_mesh_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует сетчатую поверхность, заданную параметрически @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@}. См. также @ref{surf}, @ref{fall}, @ref{meshnum}, @ref{cont}, @ref{tens}. @sref{Mesh sample}
+ at end deftypefn
+
+ at anchor{fall}
+ at deftypefn {Команда MGL} {} fall zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} fall xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Fall (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Fall (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_fall (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_fall_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует водопад для параметрически заданной поверхности @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@}. График удобен для построения нескольких кривых, сдвинутых вглубь друг относительно друга. Если @var{sch} содержит @samp{x}, то линии рисуются вдоль оси x, иначе (по умолчанию) вдоль оси y. См. также @ref{belt}, @ref{mesh}, @ref{tens}, @ref{meshnum}. @sref{Fall sample}
+ at end deftypefn
+
+ at anchor{belt}
+ at deftypefn {Команда MGL} {} belt zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} belt xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Belt (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Belt (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_belt (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_belt_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует ленточки для параметрически заданной поверхности @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@}. График может использоваться как 3d обобщение графика @ref{plot}. Если @var{sch} содержит @samp{x}, то ленточки рисуются вдоль оси x, иначе (по умолчанию) вдоль оси y. См. также @ref{fall}, @ref{surf}, @ref{plot}, @ref{meshnum}. @sref{Belt sample}
+ at end deftypefn
+
+ at anchor{boxs}
+ at deftypefn {Команда MGL} {} boxs zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} boxs xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Boxs (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Boxs (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_boxs (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_boxs_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует вертикальные ящики для параметрически заданной поверхности @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@}. См. также @ref{surf}, @ref{dens}, @ref{tile}, @ref{step}. @sref{Boxs sample}
+ at end deftypefn
+
+ at anchor{tile}
+ at deftypefn {Команда MGL} {} tile zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} tile xdat ydat zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} tile xdat ydat zdat cdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Tile (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Tile (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Tile (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_tile (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_tile_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_tile_xyc (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует плитки для параметрически заданной поверхности @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@} с цветом, заданным массивом @var{c}[i,j]. Если строка @var{sch} содержит стиль @samp{x} или @samp{y}, то плитки будут ориентированы перпендикулярно x- или y-оси. График может использоваться как 3d обобщение @ref{step}. См. также @ref{surf}, @ref{boxs}, @ref{step}, @ref{tiles}. @sref{Tile sample}
+ at end deftypefn
+
+ at anchor{dens}
+ at deftypefn {Команда MGL} {} dens zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} dens xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Dens (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""}, @code{mreal} zVal=@code{NAN})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Dens (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""}, @code{mreal} zVal=@code{NAN})
+ at deftypefnx {Функция С} @code{void} mgl_dens (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_dens_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует график плотности для параметрически заданной поверхности @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@} при @var{z} равном минимальному значению оси z. Если @var{sch} содержит @samp{#}, то рисуется сетка. Если @var{sch} содержит @samp{.}, то рисуется поверхность из точек. См. также @ref{surf}, @ref{cont}, @ref{contf}, @ref{boxs}, @ref{tile}, @code{dens[xyz]}. @sref{Dens sample}
+ at end deftypefn
+
+ at anchor{cont}
+ at deftypefn {Команда MGL} {} cont vdat zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} cont vdat xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Cont (@code{const mglDataA &}v, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Cont (@code{const mglDataA &}v, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_cont__val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_cont_xy_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует линии уровня для параметрически заданной поверхности @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@} при @var{z=v}[k] или при @var{z}  равном минимальному значению оси z если @var{sch} содержит @samp{_}. Линии уровня рисуются для @var{z}[i,j]=@var{v}[k]. Если @var{sch} содержит @samp{t} или @samp{T}, то значения @var{v}[k] будут выведены вдоль контуров над (или под) кривой. См. также @ref{dens}, @ref{contf}, @ref{contd}, @ref{axial}, @code{cont[xyz]}. @sref{Cont sample}
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} cont zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} cont xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Cont (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Cont (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_cont (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_cont_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Как предыдущий с вектором @var{v} из @var{num} элементов равно распределенных в диапазоне изменения цвета. Здесь @var{num} равен значению параметра @code{value} в опциях @var{opt} (по умолчанию 7).
+ at end deftypefn
+
+ at anchor{contf}
+ at deftypefn {Команда MGL} {} contf vdat zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} contf vdat xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContF (@code{const mglDataA &}v, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContF (@code{const mglDataA &}v, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_contf_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_contf_xy_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует закрашенные линии (контуры) уровня для параметрически заданной поверхности @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@} при @var{z=v}[k] или при @var{z}  равном минимальному значению оси z если @var{sch} содержит @samp{_}. Линии уровня рисуются для @var{z}[i,j]=@var{v}[k]. См. также @ref{dens}, @ref{cont}, @ref{contd}, @code{contf[xyz]}. @sref{ContF sample}
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} contf zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} contf xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContF (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContF (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_contf (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_contf_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Как предыдущий с вектором @var{v} из @var{num} элементов равно распределенных в диапазоне изменения цвета. Здесь @var{num} равен значению параметра @code{value} в опциях @var{opt} (по умолчанию 7).
+ at end deftypefn
+
+ at anchor{contd}
+ at deftypefn {Команда MGL} {} contd vdat zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} contd vdat xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContD (@code{const mglDataA &}v, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContD (@code{const mglDataA &}v, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_contd_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_contd_xy_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует закрашенные линии (контуры) уровня для параметрически заданной поверхности @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@} при @var{z=v}[k] или при @var{z}  равном минимальному значению оси z если @var{sch} содержит @samp{_}. Линии уровня рисуются для @var{z}[i,j]=@var{v}[k]. Строка @var{sch} задает цвета контуров: цвет k-го контура определяется как k-ый цвет строки. См. также @ref{dens}, @ref{cont}, @ref{contf}. @sref{ContD sample}
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} contd zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} contd xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContD (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContD (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_contd (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_contd_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Как предыдущий с вектором @var{v} из @var{num} элементов равно распределенных в диапазоне изменения цвета. Здесь @var{num} равен значению параметра @code{value} в опциях @var{opt} (по умолчанию 7).
+ at end deftypefn
+
+
+ at anchor{contp}
+ at deftypefn {Команда MGL} {} contp vdat xdat ydat zdat adat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContP (@code{const mglDataA &}v, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_contp_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует линии уровня для параметрически заданной поверхности @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@}. Линии уровня рисуются для @var{a}[i,j]=@var{v}[k]. Если @var{sch} содержит @samp{t} или @samp{T}, то значения @var{v}[k] будут выведены вдоль контуров над (или под) кривой. Если @var{sch} содержит @samp{f}, то контуры будут закрашены. См. также @ref{cont}, @ref{contf}, @ref{surfc}, @code{cont[xyz]}. @c TODO @sref{Cont sample}
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} contp xdat ydat zdat adat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContP (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_contp (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Как предыдущий с вектором @var{v} из @var{num} элементов равно распределенных в диапазоне изменения цвета. Здесь @var{num} равен значению параметра @code{value} в опциях @var{opt} (по умолчанию 7).
+ at end deftypefn
+
+ at anchor{contv}
+ at deftypefn {Команда MGL} {} contv vdat zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} contv vdat xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContV (@code{const mglDataA &}v, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContV (@code{const mglDataA &}v, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_contv_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_contv_xy_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует вертикальные цилиндры от линий уровня для параметрически заданной поверхности @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@} при @var{z}=@var{v}[k] или при @var{z}  равном минимальному значению оси z если @var{sch} содержит @samp{_}. Линии уровня рисуются для @var{z}[i,j]=@var{v}[k]. См. также @ref{cont}, @ref{contf}. @sref{ContV sample}
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} contv zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} contv xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContV (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContV (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_contv (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_contv_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Как предыдущий с вектором @var{v} из @var{num} элементов равно распределенных в диапазоне изменения цвета. Здесь @var{num} равен значению параметра @code{value} в опциях @var{opt} (по умолчанию 7).
+ at end deftypefn
+
+ at anchor{axial}
+ at deftypefn {Команда MGL} {} axial vdat zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} axial vdat xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Axial (@code{const mglDataA &}v, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Axial (@code{const mglDataA &}v, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_axial_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_axial_xy_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует поверхность вращения линии уровня для параметрически заданной поверхности @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@}. Линии уровня рисуются для @var{z}[i,j]=@var{v}[k]. Если @var{sch} содержит @samp{#}, то рисуется сетчатая поверхность. Если @var{sch} содержит @samp{.}, то рисуется поверхность из точек. Если строка содержит символы @samp{x} или @samp{z}, то ось вращения устанавливается в указанное направление (по умолчанию вдоль @samp{y}). См. также @ref{cont}, @ref{contf}, @ref [...]
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} axial zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} axial xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Axial (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""}, @code{int} num=@code{3})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Axial (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""}, @code{int} num=@code{3})
+ at deftypefnx {Функция С} @code{void} mgl_axial (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_axial_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Как предыдущий с вектором @var{v} из @var{num} элементов равно распределенных в диапазоне изменения цвета. Здесь @var{num} равен значению параметра @code{value} в опциях @var{opt} (по умолчанию 3).
+ at end deftypefn
+
+ at anchor{grid2}
+ at deftypefn {Команда MGL} {} grid2 zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} grid2 xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Grid (@code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Grid (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_grid (@code{HMGL} gr, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_grid_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует плоскую сету для параметрически заданной поверхности @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@} при @var{z} равном минимальному значению оси z. См. также @ref{dens}, @ref{cont}, @ref{contf}, @ref{grid3}, @ref{meshnum}.
+ at end deftypefn
+
+
+ at c ##################################################################
+ at external{}
+ at node 3D plotting, Dual plotting, 2D plotting, MathGL core
+ at section 3D графики
+ at nav{}
+ at cindex Surf3
+ at cindex Dens3
+ at cindex Cont3
+ at cindex ContF3
+ at cindex Grid3
+ at cindex Cloud
+ at cindex Beam
+
+Эти функции строят графики для трехмерных (3D) массивов. Трёхмерными считаются массивы, зависящие от трёх параметров (индексов) подобно матрице @math{f(x_i,y_j,z_k), i=1...n, j=1...m, k=1...l}. По умолчанию (если отсутствуют) значения @var{x}, @var{y}, @var{z} равно распределены в диапазоне осей координат. Младшие размерности массивов @var{x}, @var{y}, @var{z} должны быть одинаковы @code{x.nx=a.nx && y.nx=a.ny && z.nz=a.nz} или @code{x.nx=y.nx=z.nx=a.nx && x.ny=y.ny=z.ny=a.ny && x.nz=y.n [...]
+
+
+ at anchor{surf3}
+ at deftypefn {Команда MGL} {} surf3 adat @code{val} ['sch'='']
+ at deftypefnx {Команда MGL} {} surf3 xdat ydat zdat adat @code{val} ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Surf3 (@code{mreal} val, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Surf3 (@code{mreal} val, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_surf3_val (@code{HMGL} gr, @code{mreal} val, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_surf3_xyz_val (@code{HMGL} gr, @code{mreal} val, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует поверхность уровня для 3d массива, заданного параметрически @var{a}[i,j,k](@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]) при @var{a}(x,y,z)=@var{val}. Если @var{sch} содержит @samp{#}, то рисуется сетчатая поверхность. Если @var{sch} содержит @samp{.}, то рисуется поверхность из точек. Замечу, что возможно некорректная отрисовка граней вследствие неопределённости построения сечения если поверхность пересекает ячейку данных 2 и более раз. См. также @ref{cloud}, @ref{dens3}, @ref{ [...]
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} surf3 adat ['sch'='']
+ at deftypefnx {Команда MGL} {} surf3 xdat ydat zdat adat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Surf3 (@code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Surf3 (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_surf3 (@code{HMGL} gr, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_surf3_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Аналогично предыдущему для @var{num} поверхностей уровня равномерно распределённых в диапазоне изменения цвета. Величина @var{num} равна значению параметра @code{value} в опциях @var{opt} (по умолчанию 3).
+ at end deftypefn
+
+ at anchor{cloud}
+ at deftypefn {Команда MGL} {} cloud adat ['sch'='']
+ at deftypefnx {Команда MGL} {} cloud xdat ydat zdat adat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Cloud (@code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Cloud (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_cloud (@code{HMGL} gr, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_cloud_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует облачный график для 3d массива, заданного параметрически @var{a}[i,j,k](@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]). График состоит из кубиков с цветом и прозрачностью пропорциональной значениям @var{a}. Результат похож на облако -- малые значения прозрачны, а большие нет. Число кубиков зависит от @ref{meshnum}. Если @var{sch} содержит @samp{.}, то будет построен график более низкого качества, но с заметно меньшим использованием памяти. Если @var{sch} содержит @samp{i}, то про [...]
+ at end deftypefn
+
+ at anchor{dens3}
+ at deftypefn {Команда MGL} {} dens3 adat ['sch'='' @code{sval=-1}]
+ at deftypefnx {Команда MGL} {} dens3 xdat ydat zdat adat ['sch'='' @code{sval=-1}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Dens3 (@code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Dens3 (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_dens3 (@code{HMGL} gr, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_dens3_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at end ifclear
+Рисует график плотности для 3d массива, заданного параметрически @var{a}[i,j,k](@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]). График рисуется на срезе @var{sVal} в направлении @{@samp{x}, @samp{y}, @samp{z}@}, указанном в строке @var{sch} (по умолчанию, в напралении @samp{y}). Если @var{sch} содержит @samp{#}, то на срезе рисуется сетка. См. также @ref{cont3}, @ref{contf3}, @ref{dens}, @ref{grid3}. @sref{Dens3 sample}
+ at end deftypefn
+
+ at anchor{cont3}
+ at deftypefn {Команда MGL} {} cont3 vdat adat ['sch'='' @code{sval=-1}]
+ at deftypefnx {Команда MGL} {} cont3 vdat xdat ydat zdat adat ['sch'='' @code{sval=-1}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Cont3 (@code{const mglDataA &}v, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Cont3 (@code{const mglDataA &}v, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_cont3_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_cont3_xyz_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at end ifclear
+Рисует линии уровня для 3d массива, заданного параметрически @var{a}[i,j,k](@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]). Линии рисуются для значений из массива @var{v} на срезе @var{sVal} в направлении @{@samp{x}, @samp{y}, @samp{z}@}, указанном в строке @var{sch} (по умолчанию, в напралении @samp{y}). Если @var{sch} содержит @samp{#}, то на срезе рисуется сетка. Если @var{sch} содержит @samp{t} или @samp{T}, то значения @var{v}[k] будут выведены вдоль контуров над (или под) кривой.  [...]
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} cont3 adat ['sch'='' @code{sval=-1}]
+ at deftypefnx {Команда MGL} {} cont3 xdat ydat zdat adat ['sch'='' @code{sval=-1}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Cont3 (@code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Cont3 (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_cont3 (@code{HMGL} gr, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_cont3_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at end ifclear
+Аналогично предыдущему для @var{num} линий уровня равномерно распределённых в диапазоне изменения цвета. Величина @var{num} равна значению параметра @code{value} в опциях @var{opt} (по умолчанию 7).
+ at end deftypefn
+
+ at anchor{contf3}
+ at deftypefn {Команда MGL} {} contf3 vdat adat ['sch'='' @code{sval=-1}]
+ at deftypefnx {Команда MGL} {} contf3 vdat xdat ydat zdat adat ['sch'='' @code{sval=-1}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Contf3 (@code{const mglDataA &}v, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Contf3 (@code{const mglDataA &}v, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_contf3_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_contf3_xyz_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at end ifclear
+Рисует закрашенные линии (контуры) уровня для 3d массива, заданного параметрически @var{a}[i,j,k](@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]). Линии рисуются для значений из массива @var{v} на срезе @var{sVal} в направлении @{@samp{x}, @samp{y}, @samp{z}@}, указанном в строке @var{sch} (по умолчанию, в напралении @samp{y}). Если @var{sch} содержит @samp{#}, то на срезе рисуется сетка. См. также @ref{dens3}, @ref{cont3}, @ref{contf}, @ref{grid3}. @sref{ContF3 sample}
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} contf3 adat ['sch'='' @code{sval=-1}]
+ at deftypefnx {Команда MGL} {} contf3 xdat ydat zdat adat ['sch'='' @code{sval=-1}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Contf3 (@code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Contf3 (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_contf3 (@code{HMGL} gr, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_contf3_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at end ifclear
+Аналогично предыдущему для @var{num} закрашенных линий (контуров) уровня равномерно распределённых в диапазоне изменения цвета. Величина @var{num} равна значению параметра @code{value} в опциях @var{opt} (по умолчанию 7).
+ at end deftypefn
+
+ at anchor{grid3}
+ at deftypefn {Команда MGL} {} grid3 adat ['sch'='' @code{sval=-1}]
+ at deftypefnx {Команда MGL} {} grid3 xdat ydat zdat adat ['sch'='' @code{sval=-1}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Grid3 (@code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Grid3 (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_grid3 (@code{HMGL} gr, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_grid3_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at end ifclear
+Рисует сетку для 3d массива, заданного параметрически @var{a}[i,j,k](@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]). График рисуется на срезе @var{sVal} в направлении @{@samp{x}, @samp{y}, @samp{z}@}, указанном в строке @var{sch} (по умолчанию, в напралении @samp{y}). См. также @ref{cont3}, @ref{contf3}, @ref{dens3}, @ref{grid2}, @ref{meshnum}.
+ at end deftypefn
+
+ at anchor{beam}
+ at deftypefn {Команда MGL} {} beam tr g1 g2 adat @code{rval} ['sch'='' @code{flag=0 num=3}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Beam (@code{const mglDataA &}tr, @code{const mglDataA &}g1, @code{const mglDataA &}g2, @code{const mglDataA &}a, @code{mreal} r, @code{const char *}stl=@code{""}, @code{int} flag=@code{0}, @code{int} num=@code{3})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Beam (@code{mreal} val, @code{const mglDataA &}tr, @code{const mglDataA &}g1, @code{const mglDataA &}g2, @code{const mglDataA &}a, @code{mreal} r, @code{const char *}stl=@code{""}, @code{int} flag=@code{0})
+ at deftypefnx {Функция С} @code{void} mgl_beam (@code{HMGL} gr, @code{HCDT} tr, @code{HCDT} g1, @code{HCDT} g2, @code{HCDT} a, @code{mreal} r, @code{const char *}stl, @code{int} flag, @code{int} num)
+ at deftypefnx {Функция С} @code{void} mgl_beam_val (@code{HMGL} gr, @code{mreal} val, @code{HCDT} tr, @code{HCDT} g1, @code{HCDT} g2, @code{HCDT} a, @code{mreal} r, @code{const char *}stl, @code{int} flag)
+ at end ifclear
+Рисует поверхность уровня для 3d массива @var{a} при постоянном значении @var{a}=@var{val}. Это специальный тип графика для @var{a} заданного в сопровождающей системе координат вдоль кривой @var{tr} с ортами @var{g1}, @var{g2} и с поперечным размером @var{r}. Переменная @var{flag} -- битовый флаг: @samp{0x1} - рисовать в сопровождающих (не лабораторных) координатах; @samp{0x2} - рисовать проекцию на плоскость @math{\rho-z}; @samp{0x4} - рисовать нормированное в каждом сечении поле. Разме [...]
+ at end deftypefn
+
+
+ at c ##################################################################
+ at external{}
+ at node Dual plotting, Vector fields, 3D plotting, MathGL core
+ at section Парные графики
+ at nav{}
+ at cindex SurfC
+ at cindex SurfA
+ at cindex Surf3C
+ at cindex Surf3A
+ at cindex TileS
+ at cindex Map
+ at cindex STFA
+
+Эти функции строят графики для двух связанных массивов. Есть несколько основных типов 3D графиков: поверхность и поверхность уровня с окраской по второму массиву (SurfC, Surf3C), поверхность и поверхность уровня с прозрачностью по второму массиву (SurfA, Surf3A), плитки переменного размера (TileS), диаграмма точечного отображения (Map), STFA диаграмма (STFA). По умолчанию (если отсутствуют) значения @var{x}, @var{y} (и @var{z} для @code{Surf3C, Surf3A}) равно распределены в диапазоне осе [...]
+
+
+ at anchor{surfc}
+ at deftypefn {Команда MGL} {} surfc zdat cdat ['sch'='']
+ at deftypefnx {Команда MGL} {} surfc xdat ydat zdat cdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SurfC (@code{const mglDataA &}z, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SurfC (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_surfc (@code{HMGL} gr, @code{HCDT} z, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_surfc_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует параметрически заданную поверхность @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@} с цветом, заданным массивом @var{c}[i,j]. Если @var{sch} содержит @samp{#}, то на поверхности рисуется сетка. Если @var{sch} содержит @samp{.}, то рисуется поверхность из точек. Размерность массивов @var{z} и @var{c} должна быть одинакова. График строится для каждого z среза данных. См. также @ref{surf}, @ref{surfa}, @ref{surf3c}. @sref{SurfC sample}
+ at end deftypefn
+
+ at anchor{surf3c}
+ at deftypefn {Команда MGL} {} surf3c adat cdat @code{val} ['sch'='']
+ at deftypefnx {Команда MGL} {} surf3c xdat ydat zdat adat cdat @code{val} ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Surf3C (@code{mreal} val, @code{const mglDataA &}a, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Surf3C (@code{mreal} val, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_surf3c_val (@code{HMGL} gr, @code{mreal} val, @code{HCDT} a, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_surf3c_xyz_val (@code{HMGL} gr, @code{mreal} val, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует поверхность уровня для 3d массива, заданного параметрически @var{a}[i,j,k](@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]) при @var{a}(x,y,z)=@var{val}. Аналогично @ref{surf3}, но цвет задается массивом @var{c}. Если @var{sch} содержит @samp{#}, то рисуется сетчатая поверхность. Если @var{sch} содержит @samp{.}, то рисуется поверхность из точек. См. также @ref{surf3}, @ref{surfc}, @ref{surf3a}. @sref{Surf3C sample}
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} surf3c adat cdat ['sch'='']
+ at deftypefnx {Команда MGL} {} surf3c xdat ydat zdat adat cdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Surf3C (@code{const mglDataA &}a, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Surf3C (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_surf3c (@code{HMGL} gr, @code{HCDT} a, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_surf3c_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Аналогично предыдущему для @var{num} поверхностей уровня равномерно распределённых в диапазоне изменения цвета. Величина @var{num} равна значению параметра @code{value} в опциях @var{opt} (по умолчанию 3).
+ at end deftypefn
+
+
+ at anchor{surfa}
+ at deftypefn {Команда MGL} {} surfa zdat cdat ['sch'='']
+ at deftypefnx {Команда MGL} {} surfa xdat ydat zdat cdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SurfA (@code{const mglDataA &}z, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SurfA (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_surfa (@code{HMGL} gr, @code{HCDT} z, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_surfa_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует параметрически заданную поверхность @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@} с прозрачностью, заданной массивом @var{c}[i,j]. Если @var{sch} содержит @samp{#}, то на поверхности рисуется сетка. Если @var{sch} содержит @samp{.}, то рисуется поверхность из точек. Размерность массивов @var{z} и @var{c} должна быть одинакова. График строится для каждого z среза данных. См. также @ref{surf}, @ref{surfc}, @ref{surf3a}. @sref{SurfA sample}
+ at end deftypefn
+
+ at anchor{surf3a}
+ at deftypefn {Команда MGL} {} surf3a adat cdat @code{val} ['sch'='']
+ at deftypefnx {Команда MGL} {} surf3a xdat ydat zdat adat cdat @code{val} ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Surf3A (@code{mreal} val, @code{const mglDataA &}a, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Surf3A (@code{mreal} val, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_surf3a_val (@code{HMGL} gr, @code{mreal} val, @code{HCDT} a, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_surf3a_xyz_val (@code{HMGL} gr, @code{mreal} val, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует поверхность уровня для 3d массива, заданного параметрически @var{a}[i,j,k](@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]) при @var{a}(x,y,z)=@var{val}. Аналогично @ref{surf3}, но прозрачность задается массивом @var{c}. Если @var{sch} содержит @samp{#}, то рисуется сетчатая поверхность. Если @var{sch} содержит @samp{.}, то рисуется поверхность из точек. См. также @ref{surf3}, @ref{surfc}, @ref{surf3a}. @sref{Surf3A sample}
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} surf3a adat cdat ['sch'='']
+ at deftypefnx {Команда MGL} {} surf3a xdat ydat zdat adat cdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Surf3A (@code{const mglDataA &}a, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Surf3A (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_surf3a (@code{HMGL} gr, @code{HCDT} a, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_surf3a_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Аналогично предыдущему для @var{num} поверхностей уровня равномерно распределённых в диапазоне изменения цвета. При этом массив @var{c} может быть вектором со значениями прозрачности и @var{num}=@var{c}.nx. В противном случае величина @var{num} равна значению параметра @code{value} в опциях @var{opt} (по умолчанию 3).
+ at end deftypefn
+
+
+
+ at anchor{surfca}
+ at deftypefn {Команда MGL} {} surfca zdat cdat adat ['sch'='']
+ at deftypefnx {Команда MGL} {} surfca xdat ydat zdat cdat adat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SurfCA (@code{const mglDataA &}z, @code{const mglDataA &}c, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} SurfCA (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}c, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_surfca (@code{HMGL} gr, @code{HCDT} z, @code{HCDT} c, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_surfca_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} c, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует параметрически заданную поверхность @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@} с цветом и прозрачностью, заданными массивами @var{c}[i,j] и @var{a}[i,j] соответственно. Если @var{sch} содержит @samp{#}, то на поверхности рисуется сетка. Если @var{sch} содержит @samp{.}, то рисуется поверхность из точек. Размерность массивов @var{z} и @var{c} должна быть одинакова. График строится для каждого z среза данных. См. также @ref{surf}, @ref{surfc}, @ref{surfa}, @ref{surf3ca}. @sref{Sur [...]
+ at end deftypefn
+
+ at anchor{surf3ca}
+ at deftypefn {Команда MGL} {} surf3ca adat cdat bdat @code{val} ['sch'='']
+ at deftypefnx {Команда MGL} {} surf3ca xdat ydat zdat adat cdat bdat @code{val} ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Surf3CA (@code{mreal} val, @code{const mglDataA &}a, @code{const mglDataA &}c, @code{const mglDataA &}b, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Surf3CA (@code{mreal} val, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const mglDataA &}c, @code{const mglDataA &}b, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_surf3ca_val (@code{HMGL} gr, @code{mreal} val, @code{HCDT} a, @code{HCDT} c, @code{HCDT} b, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_surf3ca_xyz_val (@code{HMGL} gr, @code{mreal} val, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{HCDT} c, @code{HCDT} b, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует поверхность уровня для 3d массива, заданного параметрически @var{a}[i,j,k](@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]) при @var{a}(x,y,z)=@var{val}. Аналогично @ref{surf3}, но цвет и прозрачность задается массивами @var{c} и @var{b} соответственно. Если @var{sch} содержит @samp{#}, то рисуется сетчатая поверхность. Если @var{sch} содержит @samp{.}, то рисуется поверхность из точек. См. также @ref{surf3}, @ref{surfc}, @ref{surf3a}. @sref{Surf3A sample}
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} surf3ca adat cdat ['sch'='']
+ at deftypefnx {Команда MGL} {} surf3ca xdat ydat zdat adat cdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Surf3CA (@code{const mglDataA &}a, @code{const mglDataA &}c, @code{const mglDataA &}b, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Surf3CA (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const mglDataA &}c, @code{const mglDataA &}b, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_surf3ca (@code{HMGL} gr, @code{HCDT} a, @code{HCDT} c, @code{HCDT} b, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_surf3ca_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{HCDT} c, @code{HCDT} b, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Аналогично предыдущему для @var{num} поверхностей уровня равномерно распределённых в диапазоне изменения цвета. Здесь величина @var{num} равна значению параметра @code{value} в опциях @var{opt} (по умолчанию 3).
+ at end deftypefn
+
+
+ at anchor{tiles}
+ at deftypefn {Команда MGL} {} tiles zdat rdat ['sch'='']
+ at deftypefnx {Команда MGL} {} tiles xdat ydat zdat rdat ['sch'='']
+ at deftypefnx {Команда MGL} {} tiles xdat ydat zdat rdat cdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} TileS (@code{const mglDataA &}z, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} TileS (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}r, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} TileS (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}r, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_tiles (@code{HMGL} gr, @code{HCDT} z, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_tiles_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} r, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_tiles_xyc (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} r, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует плитки для параметрически заданной поверхности @{@var{x}[i,j], @var{y}[i,j], @var{z}[i,j]@} с цветом, заданным массивом @var{c}[i,j]. Аналогично Tile(), но размер плиток задается массивов @var{r}. Если строка @var{sch} содержит стиль @samp{x} или @samp{y}, то плитки будут ориентированы перпендикулярно x- или y-оси. Это создает эффект "прозрачности" при экспорте в файлы EPS. График строится для каждого z среза данных. См. также @ref{surfa}, @ref{tile}. @sref{TileS sample}
+ at end deftypefn
+
+ at anchor{map}
+ at deftypefn {Команда MGL} {} map udat vdat ['sch'='']
+ at deftypefnx {Команда MGL} {} map xdat ydat udat vdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Map (@code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Map (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_map (@code{HMGL} gr, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_map_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует точечное отображение для матриц @{@var{ax}, @var{ay} @} параметрически зависящих от координат @var{x}, @var{y}. Исходное положение ячейки задает ее цвет. Высота пропорциональна якобиану J(ax,ay). График является аналогом диаграммы Арнольда ??? Если @var{sch} содержит @samp{.}, то цветные точки рисуются в узлах матриц (полезно для "запутанного" отображения), иначе рисуются грани. @sref{Mapping visualization}
+ at end deftypefn
+
+ at anchor{stfa}
+ at deftypefn {Команда MGL} {} stfa re im @code{dn} ['sch'='']
+ at deftypefnx {Команда MGL} {} stfa xdat ydat re im @code{dn} ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} STFA (@code{const mglDataA &}re, @code{const mglDataA &}im, @code{int} dn, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} STFA (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}re, @code{const mglDataA &}im, @code{int} dn, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_stfa (@code{HMGL} gr, @code{HCDT} re, @code{HCDT} im, @code{int} dn, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_stfa_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} re, @code{HCDT} im, @code{int} dn, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует спектрограмму комплексного массива @var{re}+i*@var{im} для Фурье размером @var{dn} точек в плоскости @var{z} равно минимальному значению оси z. Параметр @var{dn} -- любое чётное число. Например в 1D случае, результатом будет график плотности от массива @math{res[i,j]=|\sum_d^dn exp(I*j*d)*(re[i*dn+d]+I*im[i*dn+d])|/dn} размером @{int(nx/dn), dn, ny@}. Массивы @var{re}, @var{im} параметрически зависят от координат @var{x}, @var{y}. Все размеры массивов @var{re} и @var{im} должны бы [...]
+ at end deftypefn
+
+
+ at c ##################################################################
+ at external{}
+ at node Vector fields, Other plotting, Dual plotting, MathGL core
+ at section Векторные поля
+ at nav{}
+ at cindex Traj
+ at cindex Vect
+ at cindex Dew
+ at cindex Flow
+ at cindex FlowP
+ at cindex Pipe
+
+Эти функции рисуют графики для 2D и 3D векторных полей. Есть несколько типов графиков: просто векторное поле (Vect), вектора вдоль траектории (Traj), векторное поле каплями (Dew), нити тока (Flow, FlowP), трубки тока (Pipe). По умолчанию (если отсутствуют) значения @var{x}, @var{y} и @var{z} равно распределены в диапазоне осей координат. Младшие размерности массивов @var{x}, @var{y}, @var{z} и @var{ax} должны быть одинаковы. Размеры массивов @var{ax}, @var{ay} и @var{az} должны быть один [...]
+
+ at anchor{traj}
+ at deftypefn {Команда MGL} {} traj xdat ydat udat vdat ['sch'='']
+ at deftypefnx {Команда MGL} {} traj xdat ydat zdat udat vdat wdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Traj (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Traj (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const mglDataA &}az, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_traj_xyz (@code{HMGL} gr, @code{HCDT}x, @code{HCDT}y, @code{HCDT}z, @code{HCDT}ax, @code{HCDT}ay, @code{HCDT}az, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_traj_xy (@code{HMGL} gr, @code{HCDT}x, @code{HCDT}y, @code{HCDT}ax, @code{HCDT}ay, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует вектора @{@var{ax}, @var{ay}, @var{az}@} вдоль кривой @{@var{x}, @var{y}, @var{z}@}. Длина векторов пропорциональна @math{\sqrt@{ax^2+ay^2+az^2@}}. Строка @var{pen} задает цвет (см. @ref{Line styles}). По умолчанию (@code{pen=""}) используется текущий цвет из палитры (см. @ref{Palette and colors}). Опция @code{value} задает фактор длины векторов (если не нуль) или выбирать длину пропорционально расстоянию между точками кривой (если @code{value=0}). Размер по 1-му индексу должен бы [...]
+ at end deftypefn
+
+ at anchor{vect}
+ at deftypefn {Команда MGL} {} vect udat vdat ['sch'='']
+ at deftypefnx {Команда MGL} {} vect xdat ydat udat vdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Vect (@code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Vect (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_vect_2d (@code{HMGL} gr, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_vect_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует векторное поле @{@var{ax}, @var{ay}@} параметрически зависящее от координат @var{x}, @var{y} на плоскости при @var{z} равном минимальному значению оси z. Длина и цвет векторов пропорциональна @math{\sqrt@{ax^2+ay^2@}}. Число рисуемых векторов зависит от @ref{meshnum}. Вид стрелок/штрихов может быть изменён символами:
+ at itemize @bullet
+ at item
+ at samp{f} для стрелок одинаковой длины,
+ at item
+ at samp{>}, @samp{<} для стрелок начинающихся или заканчивающихся в ячейке сетки (по умолчанию центрированы),
+ at item
+ at samp{.} для рисования штрихов с точкой в начале вместо стрелок,
+ at item
+ at samp{=} для использования градиента цвета вдоль стрелок.
+ at end itemize
+См. также @ref{flow}, @ref{dew}. @sref{Vect sample}
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} vect udat vdat wdat ['sch'='']
+ at deftypefnx {Команда MGL} {} vect xdat ydat zdat udat vdat wdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Vect (@code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const mglDataA &}az, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Vect (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const mglDataA &}az, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_vect_3d (@code{HMGL} gr, @code{HCDT} ax, @code{HCDT} ay, @code{HCDT} az, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_vect_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} ax, @code{HCDT} ay, @code{HCDT} az, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Это 3d версия графика. Здесь массивы @var{ax}, @var{ay}, @var{az} должны трёхмерными тензорами и длина вектора пропорциональна @math{\sqrt@{ax^2+ay^2+az^2@}}.
+ at end deftypefn
+
+ at anchor{vect3}
+ at deftypefn {Команда MGL} {} vect3 udat vdat wdat ['sch'='' sval]
+ at deftypefnx {Команда MGL} {} vect3 xdat ydat zdat udat vdat wdat ['sch'='' sval]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Vect3 (@code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const mglDataA &}az, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Vect3 (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const mglDataA &}az, @code{const char *}sch=@code{""}, @code{mreal} sVal=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_vect3 (@code{HMGL} gr, @code{HCDT} ax, @code{HCDT} ay, @code{HCDT} az, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_vect3_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} ax, @code{HCDT} ay, @code{HCDT} az, @code{const char *}sch, @code{mreal} sVal, @code{const char *}opt)
+ at end ifclear
+Рисует 3D векторное поле @{@var{ax}, @var{ay}, @var{az}@} параметрически зависящее от координат @var{x}, @var{y}, @var{z}. График рисуется на срезе @var{sVal} в направлении @{@samp{x}, @samp{y}, @samp{z}@}, указанном в строке @var{sch} (по умолчанию, в напралении @samp{y}). Длина и цвет векторов пропорциональна @math{\sqrt@{ax^2+ay^2+az^2@}}. Число рисуемых векторов зависит от @ref{meshnum}. Вид стрелок/штрихов может быть изменён символами:
+ at itemize @bullet
+ at item
+ at samp{f} для стрелок одинаковой длины,
+ at item
+ at samp{>}, @samp{<} для стрелок начинающихся или заканчивающихся в ячейке сетки (по умолчанию центрированы),
+ at item
+ at samp{.} для рисования штрихов с точкой в начале вместо стрелок,
+ at item
+ at samp{=} для использования градиента цвета вдоль стрелок.
+ at end itemize
+См. также @ref{vect}, @ref{flow}, @ref{dew}. @sref{Vect sample}
+ at end deftypefn
+
+ at anchor{dew}
+ at deftypefn {Команда MGL} {} dew udat vdat ['sch'='']
+ at deftypefnx {Команда MGL} {} dew xdat ydat udat vdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Dew (@code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Dew (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_dew (@code{HMGL} gr, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_dew_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует капли для векторного поля @{@var{ax}, @var{ay}@}, параметрически зависящего от координат @var{x}, @var{y} при @var{z} равном минимальному значению оси z. Замечу, что график требует много памяти и процессорного времени для своего создания! Цвет капель пропорционален @math{\sqrt@{ax^2+ay^2@}}. Число капель определяется @ref{meshnum}. См. также @ref{vect}. @sref{Dew sample}
+ at end deftypefn
+
+ at anchor{flow}
+ at deftypefn {Команда MGL} {} flow udat vdat ['sch'='']
+ at deftypefnx {Команда MGL} {} flow xdat ydat udat vdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Flow (@code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Flow (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_flow_2d (@code{HMGL} gr, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_flow_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует нити тока для векторного поля @{@var{ax}, @var{ay}@}, параметрически зависящего от координат @var{x}, @var{y} на плоскости при @var{z} равном минимальному значению оси z. Число нитей пропорционально значению опции @code{value} (по умолчанию 5). Цвет нитей пропорционален @math{\sqrt@{ax^2+ay^2@}}. Строка @var{sch} может содержать
+ at itemize @bullet
+ at item
+цветовую схему -- тёплые цвета соответствуют нормальному току (типа стока), холодные цвета соответствуют обратному току (типа источника);
+ at item
+ at samp{#} для использования нитей, начинающихся только на границе;
+ at item
+ at samp{*} для использования нитей, начинающихся с двумерной сетки внутри данных;
+ at item
+ at samp{v} для рисования стрелок на нитях;
+ at item
+ at samp{x}, @samp{z} для рисования лент нормалей, начинающихся в плоскостях x-y и y-z соответственно.
+ at end itemize
+См. также @ref{pipe}, @ref{vect}, @ref{tape}, @ref{barwidth}. @sref{Flow sample}
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} flow udat vdat wdat ['sch'='']
+ at deftypefnx {Команда MGL} {} flow xdat ydat zdat udat vdat wdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Flow (@code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const mglDataA &}az, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Flow (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const mglDataA &}az, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_flow_3d (@code{HMGL} gr, @code{HCDT} ax, @code{HCDT} ay, @code{HCDT} az, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_flow_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} ax, @code{HCDT} ay, @code{HCDT} az, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Это 3d версия графика. Здесь массивы должны трёхмерными тензорами и цвет пропорционален @math{\sqrt@{ax^2+ay^2+az^2@}}.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} flow @code{x0 y0} udat vdat ['sch'='']
+ at deftypefnx {Команда MGL} {} flow @code{x0 y0} xdat ydat udat vdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} FlowP (@code{mglPoint} p0, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} FlowP (@code{mglPoint} p0, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_flowp_2d (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_flowp_xy (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{HCDT} x, @code{HCDT} y, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Аналогично @ref{flow}, но рисует одну нить из точки @var{p0}=@{@var{x0}, at var{y0}, at var{z0}@}.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} flow @code{x0 y0 z0} udat vdat wdat ['sch'='']
+ at deftypefnx {Команда MGL} {} flow @code{x0 y0 z0} xdat ydat zdat udat vdat wdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} FlowP (@code{mglPoint} p0, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const mglDataA &}az, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} FlowP (@code{mglPoint} p0, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const mglDataA &}az, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_flowp_3d (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{HCDT} ax, @code{HCDT} ay, @code{HCDT} az, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_flowp_xyz (@code{HMGL} gr, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} ax, @code{HCDT} ay, @code{HCDT} az, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Это 3d версия графика.
+ at end deftypefn
+
+ at anchor{grad}
+ at deftypefn {Команда MGL} {} grad pdat ['sch'='']
+ at deftypefnx {Команда MGL} {} grad xdat ydat pdat ['sch'='']
+ at deftypefnx {Команда MGL} {} grad xdat ydat zdat pdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Grad (@code{const mglDataA &}phi, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Grad (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}phi, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Grad (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}phi, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_grad (@code{HMGL} gr, @code{HCDT} phi, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_grad_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} phi, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_grad_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} phi, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует линии градиента скалярного поля @var{phi}[i,j] (или @var{phi}[i,j,k] в 3d случае) заданного параметрически @{@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]@}. Число линий пропорционально значению опции @code{value} (по умолчанию 5). См. также @ref{dens}, @ref{cont}, @ref{flow}.
+ at end deftypefn
+
+ at anchor{pipe}
+ at deftypefn {Команда MGL} {} pipe udat vdat ['sch'='' @code{r0=0.05}]
+ at deftypefnx {Команда MGL} {} pipe xdat ydat udat vdat ['sch'='' @code{r0=0.05}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Pipe (@code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{mreal} r0=@code{0.05}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Pipe (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const char *}sch=@code{""}, @code{mreal} r0=@code{0.05}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_pipe_2d (@code{HMGL} gr, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{mreal} r0, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_pipe_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} ax, @code{HCDT} ay, @code{const char *}sch, @code{mreal} r0, @code{const char *}opt)
+ at end ifclear
+Рисует трубки тока для векторного поля @{@var{ax}, @var{ay}@}, параметрически зависящего от координат @var{x}, @var{y} на плоскости при @var{z} равном минимальному значению оси z. Число трубок пропорционально значению опции @code{value}. Цвет и радиус трубок пропорционален @math{\sqrt@{ax^2+ay^2@}}. Тёплые цвета соответствуют нормальному току (типа стока). Холодные цвета соответствуют обратному току (типа источника). Параметр @var{r0} задает радиус трубок. При @var{r0}<0 радиус трубок об [...]
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} pipe udat vdat wdat ['sch'='' @code{r0=0.05}]
+ at deftypefnx {Команда MGL} {} pipe xdat ydat zdat udat vdat wdat ['sch'='' @code{r0=0.05}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Pipe (@code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const mglDataA &}az, @code{const char *}sch=@code{""}, @code{mreal} r0=@code{0.05}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Pipe (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}ax, @code{const mglDataA &}ay, @code{const mglDataA &}az, @code{const char *}sch=@code{""}, @code{mreal} r0=@code{0.05}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_pipe_3d (@code{HMGL} gr, @code{HCDT} ax, @code{HCDT} ay, @code{HCDT} az, @code{const char *}sch, @code{mreal} r0, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_pipe_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} ax, @code{HCDT} ay, @code{HCDT} az, @code{const char *}sch, @code{mreal} r0, @code{const char *}opt)
+ at end ifclear
+Это 3d версия графика. Здесь массивы @var{ax}, @var{ay}, @var{az} должны трёхмерными тензорами и цвет пропорционален @math{\sqrt@{ax^2+ay^2+az^2@}}.
+ at end deftypefn
+
+
+ at c ##################################################################
+ at external{}
+ at node Other plotting, Nonlinear fitting, Vector fields, MathGL core
+ at section Прочие графики
+ at nav{}
+ at cindex DensXYZ
+ at cindex ContXYZ
+ at cindex ContFXYZ
+ at cindex Dots
+ at cindex Crust
+ at cindex TriPlot
+ at cindex TriCont
+ at cindex QuadPlot
+ at cindex FPlot
+ at cindex FSurf
+
+Это функции, не относящиеся к какой-то специальной категории. Сюда входят функции построения графиков по текстовым формулам (FPlot и FSurf), рисования поверхностей из треугольников и четырёхугольников (TriPlot, TriCont, QuadPlot), произвольных точек в пространстве (Dots) и реконструкции по ним поверхности (Crust), графики плотности и линии уровня на плоскостях, перпендикулярных осям x, y или z (Dens[XYZ], Cont[XYZ], ContF[XYZ]). Каждый тип графика имеет похожий интерфейс. Есть версия для [...]
+
+ at anchor{densz} @anchor{densy} @anchor{densx} @anchor{DensXYZ}
+ at deftypefn {Команда MGL} {} densx dat ['sch'='' @code{sval=nan}]
+ at deftypefnx {Команда MGL} {} densy dat ['sch'='' @code{sval=nan}]
+ at deftypefnx {Команда MGL} {} densz dat ['sch'='' @code{sval=nan}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} DensX (@code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} DensY (@code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} DensZ (@code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_dens_x (@code{HMGL} gr, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_dens_y (@code{HMGL} gr, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_dens_z (@code{HMGL} gr, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at end ifclear
+Эти функции рисуют график плотности на x, y или z плоскостях. Если @var{a} -- 3d массив, то выполняется интерполяция к заданному срезу @var{sVal}. Функции полезны для создания проекций 3D массивов на оси координат. См. также @ref{ContXYZ}, @ref{ContFXYZ}, @ref{dens}, @ref{Data manipulation}. @sref{Dens projection sample}
+ at end deftypefn
+
+ at anchor{contz} @anchor{conty} @anchor{contx} @anchor{ContXYZ}
+ at deftypefn {Команда MGL} {} contx dat ['sch'='' @code{sval=nan}]
+ at deftypefnx {Команда MGL} {} conty dat ['sch'='' @code{sval=nan}]
+ at deftypefnx {Команда MGL} {} contz dat ['sch'='' @code{sval=nan}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContX (@code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContY (@code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContZ (@code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_cont_x (@code{HMGL} gr, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_cont_y (@code{HMGL} gr, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_cont_z (@code{HMGL} gr, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at end ifclear
+Эти функции рисуют линии уровня на x, y или z плоскостях. Если @var{a} -- 3d массив, то выполняется интерполяция к заданному срезу @var{sVal}. Опция @code{value} задает число контуров. Функции полезны для создания проекций 3D массивов на оси координат. См. также @ref{ContFXYZ}, @ref{DensXYZ}, @ref{cont}, @ref{Data manipulation}. @sref{Cont projection sample}
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} ContX (@code{const mglDataA &}v, @code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContY (@code{const mglDataA &}v, @code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContZ (@code{const mglDataA &}v, @code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_cont_x_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_cont_y_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_cont_z_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+Аналогично предыдущему с ручным заданием значений для линий уровня.
+ at end deftypefn
+ at end ifclear
+
+ at anchor{contfz} @anchor{contfy} @anchor{contfx} @anchor{ContFXYZ}
+ at deftypefn {Команда MGL} {} contfx dat ['sch'='' @code{sval=nan}]
+ at deftypefnx {Команда MGL} {} contfy dat ['sch'='' @code{sval=nan}]
+ at deftypefnx {Команда MGL} {} contfz dat ['sch'='' @code{sval=nan}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContFX (@code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContFY (@code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContFZ (@code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_contf_x (@code{HMGL} gr, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_contf_y (@code{HMGL} gr, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_contf_z (@code{HMGL} gr, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at end ifclear
+Эти функции рисуют закрашенные контуры уровня на x, y или z плоскостях. Если @var{a} -- 3d массив, то выполняется интерполяция к заданному срезу @var{sVal}. Опция @code{value} задает число контуров. Функции полезны для создания проекций 3D массивов на оси координат. См. также @ref{ContFXYZ}, @ref{DensXYZ}, @ref{cont}, @ref{Data manipulation}. @sref{ContF projection sample}
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Метод класса @code{mglGraph}} @code{void} ContFX (@code{const mglDataA &}v, @code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContFY (@code{const mglDataA &}v, @code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} ContFZ (@code{const mglDataA &}v, @code{const mglDataA &}a, @code{const char *}stl=@code{""}, @code{mreal} sVal=@code{NAN}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_contf_x_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_contf_y_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_contf_z_val (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} a, @code{const char *}stl, @code{mreal} sVal, @code{const char *}opt)
+Аналогично предыдущему с ручным заданием значений для линий уровня.
+ at end deftypefn
+ at end ifclear
+
+ at anchor{fplot}
+ at deftypefn {Команда MGL} {} fplot 'y(x)' ['pen'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} FPlot (@code{const char *}eqY, @code{const char *}pen=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_fplot (@code{HMGL} gr, @code{const char *}eqY, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Рисует функцию @samp{eqY(x)} в плоскости @var{z} равно минимальному значению оси z с координатой @samp{x} в диапазоне осей координат. Опция @code{value} задает начальное число точек. См. также @ref{plot}.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} fplot 'x(t)' 'y(t)' 'z(t)' ['pen'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} FPlot (@code{const char *}eqX, @code{const char *}eqY, @code{const char *}eqZ, @code{const char *}pen, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_fplot_xyz (@code{HMGL} gr, @code{const char *}eqX, @code{const char *}eqY, @code{const char *}eqZ, @code{const char *}pen, @code{const char *}opt)
+ at end ifclear
+Рисует параметрическую кривую @{@samp{eqX(t)}, @samp{eqY(t)}, @samp{eqZ(t)}@}, где координата @samp{t} меняется в диапазоне [0, 1]. Опция @code{value} задает начальное число точек. См. также @ref{plot}.
+ at end deftypefn
+
+ at anchor{fsurf}
+ at deftypefn {Команда MGL} {} fsurf 'z(x,y)' ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} FSurf (@code{const char *}eqZ, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""});
+ at deftypefnx {Функция С} @code{void} mgl_fsurf (@code{HMGL} gr, @code{const char *}eqZ, @code{const char *}sch, @code{const char *}opt);
+ at end ifclear
+Рисует поверхность @samp{eqY(x,y)} с координатами @samp{x}, @samp{y} в диапазоне @code{xrange, yrange}. Опция @code{value} задает число точек. См. также @ref{surf}.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} fsurf 'x(u,v)' 'y(u,v)' 'z(u,v)' ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} FSurf (@code{const char *}eqX, @code{const char *}eqY, @code{const char *}eqZ, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_fsurf_xyz (@code{HMGL} gr, @code{const char *}eqX, @code{const char *}eqY, @code{const char *}eqZ, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует параметрическую поверхность @{@samp{eqX(u,v)}, @samp{eqY(u,v)}, @samp{eqZ(u,v)}@}, где координаты @samp{u}, @samp{v} меняются в диапазоне [0, 1]. Опция @code{value} задает число точек. См. также @ref{surf}.
+ at end deftypefn
+
+ at anchor{triplot}
+ at deftypefn {Команда MGL} {} triplot idat xdat ydat ['sch'='']
+ at deftypefnx {Команда MGL} {} triplot idat xdat ydat zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} triplot idat xdat ydat zdat cdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} TriPlot (@code{const mglDataA &}id, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} TriPlot (@code{const mglDataA &}id, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} TriPlot (@code{const mglDataA &}id, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_triplot_xy (@code{HMGL} gr, @code{HCDT} id, @code{HCDT} x, @code{HCDT} y, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_triplot_xyz (@code{HMGL} gr, @code{HCDT} id, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_triplot_xyzc (@code{HMGL} gr, @code{HCDT} id, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует поверхность из треугольников. Вершины треугольников задаются индексами @var{id} в массиве точек @{@var{x}[i], @var{y}[i], @var{z}[i]@}. Строка @var{sch} задает цветовую схему. Если строка содержит @samp{#}, то рисуется сетчатая поверхность. Размер по 1-му индексу массива @var{id} должен быть 3 или больше. Массивы @var{x}, @var{y}, @var{z} должны иметь одинаковые размеры. Массив @var{c} задает цвет треугольников (если @var{id}.ny=@var{c}.nx) или цвет вершин (если @var{x}.nx=@var{c} [...]
+ at end deftypefn
+
+ at anchor{tricont}
+ at deftypefn {Команда MGL} {} tricont vdat idat xdat ydat zdat cdat ['sch'='']
+ at deftypefnx {Команда MGL} {} tricont vdat idat xdat ydat zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} tricont idat xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} TriCont (@code{const mglDataA &}id, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} TriCont (@code{const mglDataA &}id, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} TriContV (@code{const mglDataA &}v, @code{const mglDataA &}id, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} TriContV (@code{const mglDataA &}v, @code{const mglDataA &}id, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_tricont_xyzc (@code{HMGL} gr, @code{HCDT} id, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_tricont_xyz (@code{HMGL} gr, @code{HCDT} id, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_tricont_xyzcv (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} id, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_tricont_xyzv (@code{HMGL} gr, @code{HCDT} v, @code{HCDT} id, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует линии уровня поверхности из треугольников при @var{z}=@var{v}[k] (или при @var{z} равном минимальному значению оси z если @var{sch} содержит @samp{_}). Вершины треугольников задаются индексами @var{id} в массиве точек @{@var{x}[i], @var{y}[i], @var{z}[i]@}. Если аргуент @var{v} не задан, то используется массив из @var{num} элементов равно распределенных в диапазоне изменения цвета. Здесь @var{num} равен значению параметра @code{value} в опциях @var{opt} (по умолчанию 7). Строка @v [...]
+ at end deftypefn
+
+ at anchor{quadplot}
+ at deftypefn {Команда MGL} {} quadplot idat xdat ydat ['sch'='']
+ at deftypefnx {Команда MGL} {} quadplot idat xdat ydat zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} quadplot idat xdat ydat zdat cdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} QuadPlot (@code{const mglDataA &}id, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} QuadPlot (@code{const mglDataA &}id, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}c, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} QuadPlot (@code{const mglDataA &}id, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_quadplot_xy (@code{HMGL} gr, @code{HCDT} id, @code{HCDT} x, @code{HCDT} y, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_quadplot_xyz (@code{HMGL} gr, @code{HCDT} id, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_quadplot_xyzc (@code{HMGL} gr, @code{HCDT} id, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} c, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует поверхность из четырёхугольников. Вершины четырёхугольников задаются индексами @var{id} в массиве точек @{@var{x}[i], @var{y}[i], @var{z}[i]@}. Строка @var{sch} задает цветовую схему. Если строка содержит @samp{#}, то рисуется сетчатая поверхность. Размер по 1-му индексу массива @var{id} должен быть 4 или больше. Массивы @var{x}, @var{y}, @var{z} должны иметь одинаковые размеры. Массив @var{c} задает цвет четырёхугольников (если @var{id}.ny=@var{c}.nx) или цвет вершин (если @var{x [...]
+ at end deftypefn
+
+ at anchor{dots}
+ at deftypefn {Команда MGL} {} dots xdat ydat zdat ['sch'='']
+ at deftypefnx {Команда MGL} {} dots xdat ydat zdat adat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Dots (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Dots (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Dots (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}c, @code{const mglDataA &}a, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_dots (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_dots_a (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_dots_ca (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} c, @code{HCDT} a, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Рисует произвольно расположенные точки @{@var{x}[i], @var{y}[i], @var{z}[i]@}. Строка @var{sch} задает цветовую схему и тип маркеров. Если определёны массивы @var{c}, @var{a} то они задают цвет и прозрачность точек соответственно. Непрозрачные точки с заданным цветом можно нарисовать с помощью @ref{tens}, используя стиль @samp{ .}. Массивы @var{x}, @var{y}, @var{z}, @var{a} должны иметь одинаковые размеры. См. также @ref{crust}, @ref{tens}, @ref{mark}, @ref{plot}. @sref{Dots sample}
+ at end deftypefn
+
+ at anchor{crust}
+ at deftypefn {Команда MGL} {} crust xdat ydat zdat ['sch'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Crust (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}sch=@code{""}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_crust (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}sch, @code{const char *}opt)
+ at end ifclear
+Реконструирует и рисует поверхность по произвольно расположенным точкам @{@var{x}[i], @var{y}[i], @var{z}[i]@}. Опция @var{value} задает радиус ошибки (увеличите для удаления дыр). Строка @var{sch} задает цветовую схему. Если строка содержит @samp{#}, то рисуется сетчатая поверхность. Массивы @var{x}, @var{y}, @var{z} должны иметь одинаковые размеры. См. также @ref{dots}, @ref{triplot}. @c @sref{Crust sample}
+ at end deftypefn
+
+ at c ##################################################################
+ at external{}
+ at node Nonlinear fitting, Data manipulation, Other plotting, MathGL core
+ at section Nonlinear fitting
+ at nav{}
+ at cindex Fit
+ at cindex FitS
+ at cindex PutsFit
+ at cindex mglFitPnts
+ at cindex Fit2
+ at cindex Fit3
+
+Эти функции подбирают параметры функции для наилучшей аппроксимации данных, т.е. минимизируют сумму @math{\sum_i (f(x_i, y_i, z_i) - a_i)^2/s_i^2}. При этом аппроксимирующая функция @samp{f} может зависеть от одного аргумента @samp{x} (1D случай), от двух аргументов @samp{x,y} (2D случай) или от трех аргументов @samp{x,y,z} (3D случай). Функция @samp{f} также может зависеть от параметров. Список параметров задается строкой @var{var} (например, @samp{abcd}). Обычно пользователь должен пре [...]
+
+Функции Fit() и FitS() не рисуют полученные массивы. Они заполняют массив @var{fit} по формуле @samp{f} с найденными коэффициентами и возвращают @math{\chi^2} ошибку аппроксимации. При этом, координаты @samp{x,y,z} равно распределены в диапазоне осей координат. Число точек в @var{fit} определяется опцией @code{value} (по умолчанию @var{mglFitPnts}=100). Функции используют библиотеку GSL. @sref{Nonlinear fitting hints}
+
+ at anchor{fits}
+ at deftypefn {Команда MGL} {} fits res adat sdat 'func' 'var' [ini=0]
+ at deftypefnx {Команда MGL} {} fits res xdat adat sdat 'func' 'var' [ini=0]
+ at deftypefnx {Команда MGL} {} fits res xdat ydat adat sdat 'func' 'var' [ini=0]
+ at deftypefnx {Команда MGL} {} fits res xdat ydat zdat adat sdat 'func' 'var' [ini=0]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} FitS (@code{const mglDataA &}a, @code{const mglDataA &}s, @code{const char *}func, @code{const char *}var, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} FitS (@code{const mglDataA &}a, @code{const mglDataA &}s, @code{const char *}func, @code{const char *}var, @code{mglData &}ini, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} FitS (@code{const mglDataA &}x, @code{const mglDataA &}a, @code{const mglDataA &}s, @code{const char *}func, @code{const char *}var, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} FitS (@code{const mglDataA &}x, @code{const mglDataA &}a, @code{const mglDataA &}s, @code{const char *}func, @code{const char *}var, @code{mglData &}ini, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} FitS (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}a, @code{const mglDataA &}s, @code{const char *}func, @code{const char *}var, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} FitS (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}a, @code{const mglDataA &}s, @code{const char *}func, @code{const char *}var, @code{mglData &}ini, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} FitS (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const mglDataA &}s, @code{const char *}func, @code{const char *}var, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} FitS (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const mglDataA &}s, @code{const char *}func, @code{const char *}var, @code{mglData &}ini, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{HMDT} mgl_fit_ys (@code{HMGL} gr, @code{HCDT} a, @code{HCDT} s, @code{const char *}func, @code{const char *}var, @code{HMDT} ini, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{HMDT} mgl_fit_xys (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} a, @code{HCDT} s, @code{const char *}func, @code{const char *}var, @code{HMDT} ini, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{HMDT} mgl_fit_xyzs (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} a, @code{HCDT} s, @code{const char *}func, @code{const char *}var, @code{HMDT} ini, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{HMDT} mgl_fit_xyzas (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{HCDT} s, @code{const char *}func, @code{const char *}var, @code{HMDT} ini, @code{const char *}opt)
+ at end ifclear
+"Подгоняют" формулу вдоль x-, y- и z-направлений для 3d массива заданного параметрически @var{a}[i,j,k](@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]) с весовым множителем @var{s}[i,j,k].
+ at end deftypefn
+
+ at anchor{fit}
+ at deftypefn {Команда MGL} {} fit res adat 'func' 'var' [ini=0]
+ at deftypefnx {Команда MGL} {} fit res xdat adat 'func' 'var' [ini=0]
+ at deftypefnx {Команда MGL} {} fit res xdat ydat adat 'func' 'var' [ini=0]
+ at deftypefnx {Команда MGL} {} fit res xdat ydat zdat adat 'func' 'var' [ini=0]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} Fit (@code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} Fit (@code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{mglData &}ini, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} Fit (@code{const mglDataA &}x, @code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} Fit (@code{const mglDataA &}x, @code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{mglData &}ini, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} Fit (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} Fit (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{mglData &}ini, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} Fit (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} Fit (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{mglData &}ini, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{HMDT} mgl_fit_y (@code{HMGL} gr, @code{HCDT} a, @code{const char *}func, @code{const char *}var, @code{HMDT} ini, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{HMDT} mgl_fit_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} a, @code{const char *}func, @code{const char *}var, @code{HMDT} ini, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{HMDT} mgl_fit_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} a, @code{const char *}func, @code{const char *}var, @code{HMDT} ini, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{HMDT} mgl_fit_xyza (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}func, @code{const char *}var, @code{HMDT} ini, @code{const char *}opt)
+ at end ifclear
+"Подгоняют" формулу вдоль x-, y- и z-направлений для 3d массива заданного параметрически @var{a}[i,j,k](@var{x}[i,j,k], @var{y}[i,j,k], @var{z}[i,j,k]) с весовым множителем 1.
+ at end deftypefn
+
+
+ at ifclear UDAV
+ at deftypefn {Метод класса @code{mglGraph}} @code{mglData} Fit2 (@code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} Fit2 (@code{mglData &}fit, @code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{mglData &}ini, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} Fit3 (@code{mglData &}fit, @code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} Fit3 (@code{mglData &}fit, @code{const mglDataA &}a, @code{const char *}func, @code{const char *}var, @code{mglData &}ini, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{HMDT} mgl_fit_2 (@code{HMGL} gr, @code{HCDT} a, @code{const char *}func, @code{const char *}var, @code{HMDT} ini, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{HMDT} mgl_fit_3 (@code{HMGL} gr, @code{HCDT} a, @code{const char *}func, @code{const char *}var, @code{HMDT} ini, @code{const char *}opt)
+"Подгоняют" формулу вдоль всех направлений для 2d или 3d массива @var{a} с @var{s}=1 и @var{x}, @var{y}, @var{z} равно распределёнными в диапазоне осей координат.
+ at end deftypefn
+ at end ifclear
+
+ at anchor{putsfit}
+ at deftypefn {Команда MGL} {} putsfit @code{x y} ['pre'='' 'fnt'='' @code{size=-1}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} PutsFit (@code{mglPoint} p, @code{const char *}prefix=@code{""}, @code{const char *}font=@code{""}, @code{mreal} size=@code{-1})
+ at deftypefnx {Функция С} @code{void} mgl_puts_fit (@code{HMGL} gr, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{const char *}prefix, @code{const char *}font, @code{mreal} size)
+ at end ifclear
+Печатает последнюю подобранную формулу с найденными коэффициентами в точке @var{p0}. Строка @var{prefix} будет напечатана перед формулой. Все другие параметры такие же как в @ref{Text printing}.
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Метод класса @code{mglGraph}} @code{const char *}GetFit ()
+ at deftypefnx {Функция С} @code{const char *} mgl_get_fit (@code{HMGL} gr)
+ at deftypefnx {Fortran процедура} @code{} mgl_get_fit (@code{long} gr, @code{char *}out, @code{int} len)
+Возвращает последнюю подобранную формулу с найденными коэффициентами.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{mreal} GetFitChi ()
+ at deftypefnx {Функция С} @code{mreal} mgl_get_fit_chi ()
+Возвращает величину \chi для последней подобранной формулы.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglGraph}} @code{mreal} GetFitCovar ()
+ at deftypefnx {Функция С} @code{mreal} mgl_get_fit_covar ()
+Возвращает ковариационную матрицу для последней подобранной формулы.
+ at end deftypefn
+
+ at end ifclear
+
+
+ at c ##################################################################
+ at external{}
+ at node Data manipulation, , Nonlinear fitting, MathGL core
+ at section Распределение данных
+ at nav{}
+ at cindex Hist
+ at cindex Fill
+ at cindex DataGrid
+
+ at deftypefn {Команда MGL} {} hist @sc{res} xdat adat
+ at deftypefnx {Команда MGL} {} hist @sc{res} xdat ydat adat
+ at deftypefnx {Команда MGL} {} hist @sc{res} xdat ydat zdat adat
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} Hist (@code{const mglDataA &}x, @code{const mglDataA &}a, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} Hist (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}a, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} Hist (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}a, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{HMDT} mgl_hist_x (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} a, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{HMDT} mgl_hist_xy (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} a, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{HMDT} mgl_hist_xyz (@code{HMGL} gr, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} a, @code{const char *}opt)
+ at end ifclear
+Создают распределения данных. Они не рисуют данные. Функции могут быть полезны в случае когда данные пользователя определены на случайно расположенных точка (например, после PIC расчетов) и он хочет построить график, требующий регулярных данных (данных на сетках). Диапазон сеток равен диапазону осей координат. Массивы @var{x}, @var{y}, @var{z} определяют положение (координаты) точек. Массив @var{a} задает значения данных. Число точек в результате @var{res} определяется опцией @code{value [...]
+ at end deftypefn
+
+
+ at deftypefn {Команда MGL} {} fill dat 'eq'
+ at deftypefnx {Команда MGL} {} fill dat 'eq' vdat
+ at deftypefnx {Команда MGL} {} fill dat 'eq' vdat wdat
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Fill (@code{mglData &}u, @code{const char *}eq, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Fill (@code{mglData &}u, @code{const char *}eq, @code{const mglDataA &}v, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} Fill (@code{mglData &}u, @code{const char *}eq, @code{const mglDataA &}v, @code{const mglDataA &}w, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_data_fill_eq (@code{HMGL} gr, @code{HMDT} u, @code{const char *}eq, @code{HCDT}v, @code{HCDT}w, @code{const char *}opt)
+ at end ifclear
+Заполняют значения массива @samp{u} в соответствии с формулой в строке @var{eq}. Формула -- произвольное выражение, зависящее от переменных @samp{x}, @samp{y}, @samp{z}, @samp{u}, @samp{v}, @samp{w}. Координаты @samp{x}, @samp{y}, @samp{z} полагаются в диапазоне изменения осей координат. Переменная @samp{u} -- значение исходного массива. Переменные @samp{v} и @samp{w} -- значения массивов @var{v}, @var{w}, которые могут быть @code{NULL} (т.е. могут быть опущены).
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} datagrid dat xdat ydat zdat
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{void} DataGrid (@code{mglData &}u, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_data_grid (@code{HMGL} gr, @code{HMDT} u, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}opt)
+ at end ifclear
+Заполняет значения массива @samp{u} результатом линейной интерполяции по триангулированной поверхности, найденной по произвольно расположенным точкам @samp{x}, @samp{y}, @samp{z}. NAN значение используется для точек сетки вне триангулированной поверхности. @sref{Making regular data}
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} refill dat xdat vdat [sl=-1]
+ at deftypefnx {Команда MGL} {} refill dat xdat ydat vdat [sl=-1]
+ at deftypefnx {Команда MGL} {} refill dat xdat ydat zdat vdat
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Refill (@code{mglDataA &}dat, @code{const mglDataA &}x, @code{const mglDataA &}v, @code{long} sl=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Refill (@code{mglDataA &}dat, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}v, @code{long} sl=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Refill (@code{mglDataA &}dat, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}v, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_data_refill_gr (@code{HMGL} gr, @code{HMDT} a, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} v, @code{long} sl, @code{const char *}opt)
+ at end ifclear
+Заполняет значениями интерполяции массива @var{v} в точках @{@var{x}, @var{y}, @var{z}@}=@{@code{X[i], Y[j], Z[k]}@} (или @{@var{x}, @var{y}, @var{z}@}=@{@code{X[i,j,k], Y[i,j,k], Z[i,j,k]}@} если @var{x}, @var{y}, @var{z} не 1d массивы), где @code{X,Y,Z} равномерно распределены в диапазоне осей координат и имеют такой же размер как и массив @var{dat}. Если параметр @var{sl} равен 0 или положительный, то изменятся будет только @var{sl}-ый срез.
+ at end deftypefn
+
+
+
+ at deftypefn {Команда MGL} {} pde @sc{res} 'ham' ini_re ini_im [@code{dz=0.1 k0=100}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglGraph}} @code{mglData} PDE (@code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{mreal} dz=@code{0.1}, @code{mreal} k0=@code{100}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{HMDT} mgl_pde_solve (@code{HMGL} gr, @code{const char *}ham, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{mreal} dz, @code{mreal} k0, @code{const char *}opt)
+ at end ifclear
+Решает уравнение в частных производных du/dz = i*k0*@var{ham}(p,q,x,y,z,|u|)[u], где p=-i/k0*d/dx, q=-i/k0*d/dy -- псевдо-дифференциальные оперторы. Параметры @var{ini_re}, @var{ini_im} задают действительную и мнимую часть начального распределения поля. Координаты @samp{x}, @samp{y}, @samp{z} полагаются в диапазоне изменения осей координат. Отмечу, ято в действительности этот диапазон увеличен на 3/2 для уменьшения отражения от границ сетки. Параметр @var{dz} задает шаг по эволюционной к [...]
+ at end deftypefn
+
+ at c ##################################################################
+ at c @external{}
+ at c @node IDTF functions, , Data distributions, MathGL core
+ at c @section IDTF функции
+ at c @nav{}
+
+ at c Эти функции обеспечивают поддержку особых возможностей при создании IDTF. Во всех прочих случаях они не делают ничего.
+
+ at c @deftypefn {Метод класса @code{mglGraph}} @code{void} VertexColor (@code{bool} enable)
+ at c Разрешает плавное изменение цвета.
+ at c @end deftypefn
+
+ at c @deftypefn {Метод класса @code{mglGraph}} @code{void} Compression (@code{bool} enable)
+ at c Дает меньший объем файла, но с худшим качеством.
+ at c @end deftypefn
+
+ at c inline void DoubleSided(bool){}	// NOTE: Add later -- IDTF
+ at c inline void TextureColor(bool){}	// NOTE: Add later -- IDTF
+
+ at c @end ifclear
+
+ at external{}
diff --git a/texinfo/data_en.texi b/texinfo/data_en.texi
new file mode 100644
index 0000000..284e383
--- /dev/null
+++ b/texinfo/data_en.texi
@@ -0,0 +1,2104 @@
+ at c ------------------------------------------------------------------
+ at chapter Data processing
+ at nav{}
+
+ at ifset UDAV
+This chapter describe commands for allocation, resizing, loading and saving, modifying of data arrays. Also it can numerically differentiate and integrate data, interpolate, fill data by formula and so on. Class supports data with dimensions up to 3 (like function of 3 variables -- x,y,z). Data arrays are denoted by Small Caps (like @sc{dat}) if it can be (re-)created by MGL commands.
+ at end ifset
+
+ at ifclear UDAV
+This chapter describe classes @code{mglData} and @code{mglDataC} for working with data arrays of real and complex numbers. Both classes are derived from abstract class @code{mglDataA}, and can be used as arguments of any plotting functions (see @ref{MathGL core}). These classes are defined in @code{#include <mgl2/data.h>} and @code{#include <mgl2/datac.h>} correspondingly. The classes have mostly the same set of functions for easy and safe allocation, resizing, loading, saving, modifying [...]
+ at end ifclear
+
+ at menu
+* Public variables::
+* Data constructor::
+* Data resizing::
+* Data filling::
+* File I/O::
+* Make another data::
+* Data changing::
+* Interpolation::
+* Data information::
+* Operators::
+* Global functions::
+* Evaluate expression::
+* Special data classes::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Public variables, Data constructor, , Data processing
+ at section Public variables
+ at nav{}
+
+ at ifset UDAV
+MGL don't support direct access to data arrays. See section @ref{Data filling}
+ at end ifset
+
+ at ifclear UDAV
+ at deftypecv {Variable} mglData @code{mreal *} a
+ at deftypecvx {Variable} mglDataC @code{dual *} a
+Data array itself. The flat data representation is used. For example, matrix [nx x ny] is presented as flat (1d-) array with length nx*ny. The element with indexes @{i, j, k@} is a[i+nx*j+nx*ny*k] (indexes are zero based).
+ at end deftypecv
+ at deftypecv {Variable} mglData @code{long} nx
+ at deftypecvx {Variable} mglDataC @code{long} nx
+Number of points in 1st dimensions ('x' dimension).
+ at end deftypecv
+ at deftypecv {Variable} mglData @code{long} ny
+ at deftypecvx {Variable} mglDataC @code{long} ny
+Number of points in 2nd dimensions ('y' dimension).
+ at end deftypecv
+ at deftypecv {Variable} mglData @code{long} nz
+ at deftypecvx {Variable} mglDataC @code{long} nz
+Number of points in 3d dimensions ('z' dimension).
+ at end deftypecv
+ at deftypecv {Variable} mglData @code{std::string} id
+ at deftypecvx {Variable} mglDataC @code{std::string} id
+Names of column (or slice if nz>1)  -- one character per column.
+ at end deftypecv
+ at deftypecv {Variable} mglData @code{bool} link
+ at deftypecvx {Variable} mglDataC @code{bool} link
+Flag to use external data, i.e. don't delete it.
+ at end deftypecv
+
+ at deftypecv {Variable} mglDataA @code{std::wstring} s
+Name of data. It is used in parsing of MGL scripts.
+ at end deftypecv
+ at deftypecv {Variable} mglDataA @code{bool} temp
+Flag of temporary variable, which should be deleted.
+ at end deftypecv
+ at deftypecv {Variable} mglDataA @code{void (*)(void *)} func
+Pointer to callback function which will be called at destroying.
+ at end deftypecv
+ at deftypecv {Variable} mglDataA @code{void *} o
+Pointer to object for callback function.
+ at end deftypecv
+
+
+ at deftypefn {Method on @code{mglData}} @code{mreal} GetVal (@code{long} i)
+ at deftypefnx {Method on @code{mglDataC}} @code{mreal} GetVal (@code{long} i)
+ at deftypefnx {Method on @code{mglData}} @code{void} SetVal (@code{mreal} val, @code{long} i)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} SetVal (@code{mreal} val, @code{long} i)
+Gets or sets the value in by "flat" index @var{i} without border checking. Index @var{i} should be in range [0, nx*ny*nz-1].
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglDataA}} @code{long} GetNx ()
+ at deftypefnx {Method on @code{mglDataA}} @code{long} GetNy ()
+ at deftypefnx {Method on @code{mglDataA}} @code{long} GetNz ()
+ at deftypefnx {C function} @code{long} mgl_data_get_nx (@code{HCDT} dat)
+ at deftypefnx {C function} @code{long} mgl_data_get_ny (@code{HCDT} dat)
+ at deftypefnx {C function} @code{long} mgl_data_get_nz (@code{HCDT} dat)
+Gets the x-, y-, z-size of the data.
+ at end deftypefn
+
+ at deftypefn {C function} @code{mreal} mgl_data_get_value (@code{HCDT} dat, @code{int} i, @code{int} j, @code{int} k)
+ at deftypefnx {C function} @code{dual} mgl_datac_get_value (@code{HCDT} dat, @code{int} i, @code{int} j, @code{int} k)
+ at deftypefnx {C function} @code{mreal *} mgl_data_value (@code{HMDT} dat, @code{int} i, @code{int} j, @code{int} k)
+ at deftypefnx {C function} @code{dual *} mgl_datac_value (@code{HADT} dat, @code{int} i, @code{int} j, @code{int} k)
+ at deftypefnx {C function} @code{void} mgl_data_set_value (@code{HMDT} dat, @code{mreal} v, @code{int} i, @code{int} j, @code{int} k)
+ at deftypefnx {C function} @code{void} mgl_datac_set_value (@code{HADT} dat, @code{dual} v, @code{int} i, @code{int} j, @code{int} k)
+Gets or sets the value in specified cell of the data with border checking.
+ at end deftypefn
+ at deftypefn {C function} @code{const mreal *} mgl_data_data (@code{HCDT} dat)
+ at deftypefnx {C function} @code{const dual *} mgl_datac_data (@code{HCDT} dat)
+Returns pointer to internal data array.
+ at end deftypefn
+
+ at deftypefn {C function only} @code{void} mgl_data_set_func (@code{mglDataA *}dat, @code{void (*}func at code{)(void *)}, @code{void *}par)
+Set pointer to callback function which will be called at destroying.
+ at end deftypefn
+
+ at deftypefn {C function} @code{void} mgl_data_set_name (@code{mglDataA *}dat, @code{const char *}name)
+ at deftypefnx {C function} @code{void} mgl_data_set_name_w (@code{mglDataA *}dat, @code{const wchar_t *}name)
+Set name of data, which used in parsing of MGL scripts.
+ at end deftypefn
+
+ at end ifclear
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Data constructor, Data resizing, Public variables, Data processing
+ at section Data constructor
+ at nav{}
+ at cindex mglData
+
+ at ifset UDAV
+There are many functions, which can create data for output (see @ref{Data filling}, @ref{File I/O}, @ref{Make another data}, @ref{Global functions}). Here I put most useful of them.
+ at end ifset
+
+ at anchor{new}
+ at deftypefn {MGL command} {} new @sc{dat} [@code{nx=1} 'eq']
+ at deftypefnx {MGL command} {} new @sc{dat} @code{nx ny} ['eq']
+ at deftypefnx {MGL command} {} new @sc{dat} @code{nx ny nz} ['eq']
+ at ifclear UDAV
+ at deftypefnx {Constructor on @code{mglData}} {} mglData (@code{int} mx=@code{1}, @code{int} my=@code{1}, @code{int} mz=@code{1})
+ at deftypefnx {Constructor on @code{mglDataC}} {} mglDataC (@code{int} mx=@code{1}, @code{int} my=@code{1}, @code{int} mz=@code{1})
+ at deftypefnx {C function} @code{HMDT} mgl_create_data ()
+ at deftypefnx {C function} @code{HMDT} mgl_create_data_size (@code{int} mx, @code{int} my, @code{int} mz)
+ at deftypefnx {C function} @code{HADT} mgl_create_datac ()
+ at deftypefnx {C function} @code{HADT} mgl_create_datac_size (@code{int} mx, @code{int} my, @code{int} mz)
+ at end ifclear
+Default constructor. Allocates the memory for data array and initializes it by zero. If string @var{eq} is specified then data will be filled by corresponding formula as in @ref{fill}.
+ at end deftypefn
+
+ at anchor{copy}
+ at deftypefn {MGL command} {} copy @sc{dat} dat2 ['eq'='']
+ at deftypefnx {MGL command} {} copy @sc{dat} @code{val}
+ at ifclear UDAV
+ at deftypefnx {Constructor on @code{mglData}} {} mglData (@code{const mglDataA &}dat2)
+ at deftypefnx {Constructor on @code{mglData}} {} mglData (@code{const mglDataA *}dat2)
+ at deftypefnx {Constructor on @code{mglData}} {} mglData (@code{int} size, @code{const float *}dat2)
+ at deftypefnx {Constructor on @code{mglData}} {} mglData (@code{int} size, @code{int} cols, @code{const float *}dat2)
+ at deftypefnx {Constructor on @code{mglData}} {} mglData (@code{int} size, @code{const double *}dat2)
+ at deftypefnx {Constructor on @code{mglData}} {} mglData (@code{int} size, @code{int} cols, @code{const double *}dat2)
+ at deftypefnx {Constructor on @code{mglData}} {} mglData (@code{const double *}dat2, @code{int} size)
+ at deftypefnx {Constructor on @code{mglData}} {} mglData (@code{const double *}dat2, @code{int} size, @code{int} cols)
+ at deftypefnx {Constructor on @code{mglDataC}} {} mglDataC (@code{const mglDataA &}dat2)
+ at deftypefnx {Constructor on @code{mglDataC}} {} mglDataC (@code{const mglDataA *}dat2)
+ at deftypefnx {Constructor on @code{mglDataC}} {} mglDataC (@code{int} size, @code{const float *}dat2)
+ at deftypefnx {Constructor on @code{mglDataC}} {} mglDataC (@code{int} size, @code{int} cols, @code{const float *}dat2)
+ at deftypefnx {Constructor on @code{mglDataC}} {} mglDataC (@code{int} size, @code{const double *}dat2)
+ at deftypefnx {Constructor on @code{mglDataC}} {} mglDataC (@code{int} size, @code{int} cols, @code{const double *}dat2)
+ at deftypefnx {Constructor on @code{mglDataC}} {} mglDataC (@code{int} size, @code{const dual *}dat2)
+ at deftypefnx {Constructor on @code{mglDataC}} {} mglDataC (@code{int} size, @code{int} cols, @code{const dual *}dat2)
+ at end ifclear
+Copy constructor. Allocates the memory for data array and copy values from other array. At this, if parameter @var{eq} or @var{val} is specified then the data will be modified by corresponding formula similarly to @ref{fill}.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} copy @sc{redat} @sc{imdat} dat2 ['eq'='']
+Allocates the memory for data array and copy real and imaginary values from complex array @var{dat2}.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} copy 'name'
+Allocates the memory for data array and copy values from other array specified by its name, which can be "invalid" for MGL names (like one read from HDF5 files).
+ at end deftypefn
+
+
+ at deftypefn {MGL command} {} read @sc{dat} 'fname'
+ at ifclear UDAV
+ at deftypefnx {Constructor on @code{mglData}} {} mglData (@code{const char *}fname)
+ at deftypefnx {Constructor on @code{mglDataC}} {} mglDataC (@code{const char *}fname)
+ at deftypefnx {C function} @code{HMDT} mgl_create_data_file (@code{const char *}fname)
+ at deftypefnx {C function} @code{HADT} mgl_create_datac_file (@code{const char *}fname)
+ at end ifclear
+Reads data from tab-separated text file with auto determining sizes of the data.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} delete dat
+ at deftypefnx {MGL command} {} delete 'name'
+ at ifclear UDAV
+ at deftypefnx {Destructor on @code{mglData}} {} ~mglData ()
+ at deftypefnx {C function} @code{void} mgl_delete_data (@code{HMDT} dat)
+ at deftypefnx {Destructor on @code{mglDataC}} {} ~mglDataC ()
+ at deftypefnx {C function} @code{void} mgl_delete_datac (@code{HADT} dat)
+ at end ifclear
+Deletes the data array from memory.
+ at end deftypefn
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Data resizing, Data filling, Data constructor, Data processing
+ at section Data resizing
+ at nav{}
+ at cindex Create
+ at cindex Rearrange
+ at cindex Extend
+ at cindex Transpose
+ at cindex Squeeze
+ at cindex Crop
+ at cindex Insert
+ at cindex Delete
+ at cindex Sort
+ at cindex Clean
+ at cindex Join
+
+ at deftypefn {MGL command} {} new @sc{dat} [@code{nx=1 ny=1 nz=1}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Create (@code{int} mx, @code{int} my=@code{1}, @code{int} mz=@code{1})
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Create (@code{int} mx, @code{int} my=@code{1}, @code{int} mz=@code{1})
+ at deftypefnx {C function} @code{void} mgl_data_create (@code{HMDT} dat, @code{int} mx, @code{int} my, @code{int} mz)
+ at deftypefnx {C function} @code{void} mgl_datac_create (@code{HADT} dat, @code{int} mx, @code{int} my, @code{int} mz)
+ at end ifclear
+Creates or recreates the array with specified size and fills it by zero. This function does nothing if one of parameters @var{mx}, @var{my}, @var{mz} is zero or negative.
+ at end deftypefn
+
+ at anchor{rearrange}
+ at deftypefn {MGL command} {} rearrange dat @code{mx [my=0 mz=0]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Rearrange (@code{int} mx, @code{int} my=@code{0}, @code{int} mz=@code{0})
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Rearrange (@code{int} mx, @code{int} my=@code{0}, @code{int} mz=@code{0})
+ at deftypefnx {C function} @code{void} mgl_data_rearrange (@code{HMDT} dat, @code{int} mx, @code{int} my, @code{int} mz)
+ at deftypefnx {C function} @code{void} mgl_datac_rearrange (@code{HADT} dat, @code{int} mx, @code{int} my, @code{int} mz)
+ at end ifclear
+Rearrange dimensions without changing data array so that resulting sizes should  be @var{mx}*@var{my}*@var{mz} < nx*ny*nz. If some of parameter @var{my} or @var{mz} are zero then it will be selected to optimal fill of data array. For example, if @var{my}=0 then it will be change to @var{my}=nx*ny*nz/@var{mx} and @var{mz}=1.
+ at end deftypefn
+
+ at anchor{transpose}
+ at deftypefn {MGL command} {} transpose dat ['dim'='yxz']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Transpose (@code{const char *}dim=@code{"yx"})
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Transpose (@code{const char *}dim=@code{"yx"})
+ at deftypefnx {C function} @code{void} mgl_data_transpose (@code{HMDT} dat, @code{const char *}dim)
+ at deftypefnx {C function} @code{void} mgl_datac_transpose (@code{HADT} dat, @code{const char *}dim)
+ at end ifclear
+Transposes (shift order of) dimensions of the data. New order of dimensions is specified in string @var{dim}. This function can be useful also after reading of one-dimensional data.
+ at end deftypefn
+
+ at anchor{extend}
+ at deftypefn {MGL command} {} extend dat @code{n1 [n2=0]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Extend (@code{int} n1, @code{int} n2=@code{0})
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Extend (@code{int} n1, @code{int} n2=@code{0})
+ at deftypefnx {C function} @code{void} mgl_data_extend (@code{HMDT} dat, @code{int} n1, @code{int} n2)
+ at deftypefnx {C function} @code{void} mgl_datac_extend (@code{HADT} dat, @code{int} n1, @code{int} n2)
+ at end ifclear
+Increase the dimensions of the data by inserting new (|@var{n1}|+1)-th slices after (for @var{n1}>0) or before (for @var{n1}<0) of existed one. It is possible to insert 2 dimensions simultaneously for 1d data by using parameter @var{n2}. Data to new slices is copy from existed one. For example, for @var{n1}>0 new array will be
+ at iftex
+ at math{a_{ij}^{new} = a_i^{old}} where j=0... at var{n1}. Correspondingly, for @var{n1}<0 new array will be @math{a_{ij}^{new} = a_j^{old}} where i=0...|@var{n1}|.
+ at end iftex
+ at ifnottex
+a_ij^new = a_i^old where j=0... at var{n1}. Correspondingly, for @var{n1}<0 new array will be a_ij^new = a_j^old where i=0...|@var{n1}|.
+ at end ifnottex
+ at end deftypefn
+
+ at anchor{squeeze}
+ at deftypefn {MGL command} {} squeeze dat @code{rx [ry=1 rz=1 sm=off]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Squeeze (@code{int} rx, @code{int} ry=@code{1}, @code{int} rz=@code{1}, @code{bool} smooth=@code{false})
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Squeeze (@code{int} rx, @code{int} ry=@code{1}, @code{int} rz=@code{1}, @code{bool} smooth=@code{false})
+ at deftypefnx {C function} @code{void} mgl_data_squeeze (@code{HMDT} dat, @code{int} rx, @code{int} ry, @code{int} rz, @code{int} smooth)
+ at deftypefnx {C function} @code{void} mgl_datac_squeeze (@code{HADT} dat, @code{int} rx, @code{int} ry, @code{int} rz, @code{int} smooth)
+ at end ifclear
+Reduces the data size by excluding data elements which indexes are not divisible by @var{rx}, @var{ry}, @var{rz} correspondingly. Parameter @var{smooth} set to use smoothing
+ at iftex
+(i.e. @math{a_{out}[i]=\sum_{j=i,i+r}a[j]/r}) or not (i.e. @math{a_{out}[i]=a[j*r]}).
+ at end iftex
+ at ifnottex
+(i.e. out[i]=\sum_@{j=i,i+r@} a[j]/r) or not (i.e. out[i]=a[j*r]).
+ at end ifnottex
+ at end deftypefn
+
+ at anchor{crop}
+ at deftypefn {MGL command} {} crop dat @code{n1 n2} 'dir'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Crop (@code{int} n1, @code{int} n2, @code{char} dir=@code{'x'})
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Crop (@code{int} n1, @code{int} n2, @code{char} dir=@code{'x'})
+ at deftypefnx {C function} @code{void} mgl_data_crop (@code{HMDT} dat, @code{int} n1, @code{int} n2, @code{char} dir)
+ at deftypefnx {C function} @code{void} mgl_datac_crop (@code{HADT} dat, @code{int} n1, @code{int} n2, @code{char} dir)
+ at end ifclear
+Cuts off edges of the data @var{i}<@var{n1} and @var{i}>@var{n2} if @var{n2}>0 or @var{i}>@code{n[xyz]}- at var{n2} if @var{n2}<=0 along direction @var{dir}.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} crop dat 'how'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Crop (@code{const char *}how=@code{"235x"})
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Crop (@code{const char *}how=@code{"235x"})
+ at deftypefnx {C function} @code{void} mgl_data_crop_opt (@code{HMDT} dat, @code{const char *}how)
+ at deftypefnx {C function} @code{void} mgl_datac_crop_opt (@code{HADT} dat, @code{const char *}how)
+ at end ifclear
+Cuts off far edge of the data to be more optimal for fast Fourier transform. The resulting size will be the closest value of 2^n*3^m*5^l to the original one. The string @var{how} may contain: @samp{x}, @samp{y}, @samp{z} for directions, and @samp{2}, @samp{3}, @samp{5} for using corresponding bases.
+ at end deftypefn
+
+ at anchor{insert}
+ at deftypefn {MGL command} {} insert dat 'dir' @code{[pos=off num=0]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Insert (@code{char} dir, @code{int} pos=@code{0}, @code{int} num=@code{1})
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Insert (@code{char} dir, @code{int} pos=@code{0}, @code{int} num=@code{1})
+ at deftypefnx {C function} @code{void} mgl_data_insert (@code{HMDT} dat, @code{char} dir, @code{int} pos, @code{char} num)
+ at deftypefnx {C function} @code{void} mgl_datac_insert (@code{HADT} dat, @code{char} dir, @code{int} pos, @code{char} num)
+ at end ifclear
+Insert @var{num} slices along @var{dir}-direction at position @var{pos} and fill it by zeros.
+ at end deftypefn
+
+ at anchor{delete}
+ at deftypefn {MGL command} {} delete dat 'dir' @code{[pos=off num=0]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Delete (@code{char} dir, @code{int} pos=@code{0}, @code{int} num=@code{1})
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Delete (@code{char} dir, @code{int} pos=@code{0}, @code{int} num=@code{1})
+ at deftypefnx {C function} @code{void} mgl_data_delete (@code{HMDT} dat, @code{char} dir, @code{int} pos, @code{char} num)
+ at deftypefnx {C function} @code{void} mgl_datac_delete (@code{HADT} dat, @code{char} dir, @code{int} pos, @code{char} num)
+ at end ifclear
+Delete @var{num} slices along @var{dir}-direction at position @var{pos}.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} delete dat
+ at deftypefnx {MGL command} {} delete 'name'
+Deletes the whole data array.
+ at end deftypefn
+
+ at anchor{sort}
+ at deftypefn {MGL command} {} sort dat @code{idx [idy=-1]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Sort (@code{lond} idx, @code{long} idy=@code{-1})
+ at deftypefnx {C function} @code{void} mgl_data_sort (@code{HMDT} dat, @code{lond} idx, @code{long} idy)
+ at end ifclear
+Sort data rows (or slices in 3D case) by values of specified column @var{idx} (or cell @{@var{idx}, at var{idy}@} for 3D case). Note, this function is not thread safe!
+ at end deftypefn
+
+ at anchor{clean}
+ at deftypefn {MGL command} {} clean dat @code{idx}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Clean (@code{lond} idx)
+ at deftypefnx {C function} @code{void} mgl_data_clean (@code{HMDT} dat, @code{lond} idx)
+ at end ifclear
+Delete rows which values are equal to next row for given column @var{idx}.
+ at end deftypefn
+
+ at anchor{join}
+ at deftypefn {MGL command} {} join dat vdat [v2dat ...]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Join (@code{const mglDataA &}vdat)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Join (@code{const mglDataA &}vdat)
+ at deftypefnx {C function} @code{void} mgl_data_join (@code{HMDT} dat, @code{HCDT} vdat)
+ at deftypefnx {C function} @code{void} mgl_datac_join (@code{HADT} dat, @code{HCDT} vdat)
+ at end ifclear
+Join data cells from @var{vdat} to @var{dat}. At this, function increase @var{dat} sizes according following: z-size for data arrays arrays with equal x-,y-sizes; or y-size for data arrays with equal x-sizes; or x-size otherwise.
+ at end deftypefn
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Data filling, File I/O, Data resizing, Data processing
+ at section Data filling
+ at nav{}
+ at cindex Fill
+ at cindex Modify
+ at cindex Set
+ at cindex List
+ at cindex Var
+ at cindex Refill
+
+ at anchor{list}
+ at deftypefn {MGL command} {} list @sc{dat} @code{v1 ...}
+Creates new variable with name @var{dat} and fills it by numeric values of command arguments @code{v1 ...}. Command can create one-dimensional and two-dimensional arrays with arbitrary values. For creating 2d array the user should use delimiter @samp{|} which means that the following values lie in next row. Array sizes are [maximal of row sizes * number of rows]. For example, command @code{list 1 | 2 3} creates the array [1 0; 2 3]. Note, that the maximal number of arguments is 1000.
+ at end deftypefn
+ at deftypefn {MGL command} {} list @sc{dat} d1 ...
+Creates new variable with name @var{dat} and fills it by data values of arrays of command arguments @var{d1 ...}. Command can create two-dimensional or three-dimensional (if arrays in arguments are 2d arrays) arrays with arbitrary values. Minor dimensions of all arrays in arguments should be equal to dimensions of first array d1. In the opposite case the argument will be ignored. Note, that the maximal number of arguments is 1000.
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Method on @code{mglData}} @code{void} Set (@code{const float *}A, @code{int} NX, @code{int} NY=@code{1}, @code{int} NZ=@code{1})
+ at deftypefnx {Method on @code{mglData}} @code{void} Set (@code{const double *}A, @code{int} NX, @code{int} NY=@code{1}, @code{int} NZ=@code{1})
+ at deftypefnx {C function} @code{void} mgl_data_set_float (@code{HMDT} dat, @code{const mreal *}A, @code{int} NX, @code{int} NY, @code{int} NZ)
+ at deftypefnx {C function} @code{void} mgl_data_set_double (@code{HMDT} dat, @code{const double *}A, @code{int} NX, @code{int} NY, @code{int} NZ)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Set (@code{const float *}A, @code{int} NX, @code{int} NY=@code{1}, @code{int} NZ=@code{1})
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Set (@code{const double *}A, @code{int} NX, @code{int} NY=@code{1}, @code{int} NZ=@code{1})
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Set (@code{const dual *}A, @code{int} NX, @code{int} NY=@code{1}, @code{int} NZ=@code{1})
+ at deftypefnx {C function} @code{void} mgl_datac_set_float (@code{HADT} dat, @code{const mreal *}A, @code{int} NX, @code{int} NY, @code{int} NZ)
+ at deftypefnx {C function} @code{void} mgl_datac_set_double (@code{HADT} dat, @code{const double *}A, @code{int} NX, @code{int} NY, @code{int} NZ)
+ at deftypefnx {C function} @code{void} mgl_datac_set_complex (@code{HADT} dat, @code{const dual *}A, @code{int} NX, @code{int} NY, @code{int} NZ)
+Allocates memory and copies the data from the @strong{flat} @code{float*} or @code{double*} array.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglData}} @code{void} Set (@code{const float **}A, @code{int} N1, @code{int} N2)
+ at deftypefnx {Method on @code{mglData}} @code{void} Set (@code{const double **}A, @code{int} N1, @code{int} N2)
+ at deftypefnx {C function} @code{void} mgl_data_set_mreal2 (@code{HMDT} dat, @code{const mreal **}A, @code{int} N1, @code{int} N2)
+ at deftypefnx {C function} @code{void} mgl_data_set_double2 (@code{HMDT} dat, @code{const double **}A, @code{int} N1, @code{int} N2)
+Allocates memory and copies the data from the @code{float**} or @code{double**} array with dimensions @var{N1}, @var{N2}, i.e. from array defined as @code{mreal a[N1][N2];}.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglData}} @code{void} Set (@code{const float ***}A, @code{int} N1, @code{int} N2)
+ at deftypefnx {Method on @code{mglData}} @code{void} Set (@code{const double ***}A, @code{int} N1, @code{int} N2)
+ at deftypefnx {C function} @code{void} mgl_data_set_mreal3 (@code{HMDT} dat, @code{const mreal ***}A, @code{int} N1, @code{int} N2)
+ at deftypefnx {C function} @code{void} mgl_data_set_double3 (@code{HMDT} dat, @code{const double ***}A, @code{int} N1, @code{int} N2)
+Allocates memory and copies the data from the @code{float***} or @code{double***} array with dimensions @var{N1}, @var{N2}, @var{N3}, i.e. from array defined as @code{mreal a[N1][N2][N3];}.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglData}} @code{void} Set (@code{gsl_vector *}v)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Set (@code{gsl_vector *}v)
+ at deftypefnx {C function} @code{void} mgl_data_set_vector (@code{HMDT} dat, @code{gsl_vector *}v)
+ at deftypefnx {C function} @code{void} mgl_datac_set_vector (@code{HADT} dat, @code{gsl_vector *}v)
+Allocates memory and copies the data from the @code{gsl_vector *} structure.
+ at end deftypefn
+ at deftypefn {Method on @code{mglData}} @code{void} Set (@code{gsl_matrix *}m)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Set (@code{gsl_matrix *}m)
+ at deftypefnx {C function} @code{void} mgl_data_set_matrix (@code{HMDT} dat, @code{gsl_matrix *}m)
+ at deftypefnx {C function} @code{void} mgl_datac_set_matrix (@code{HADT} dat, @code{gsl_matrix *}m)
+Allocates memory and copies the data from the @code{gsl_matrix *} structure.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglData}} @code{void} Set (@code{const mglDataA &}from)
+ at deftypefnx {Method on @code{mglData}} @code{void} Set (@code{HCDT} from)
+ at deftypefnx {C function} @code{void} mgl_data_set (@code{HMDT} dat, @code{HCDT} from)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Set (@code{const mglDataA &}from)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Set (@code{HCDT} from)
+ at deftypefnx {C function} @code{void} mgl_datac_set (@code{HADT} dat, @code{HCDT} from)
+Copies the data from @code{mglData} (or @code{mglDataA}) instance @var{from}.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglDataC}} @code{void} Set (@code{const mglDataA &}re, @code{const mglDataA &}im)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Set (@code{HCDT} re, @code{HCDT} im)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} SetAmpl (@code{HCDT} ampl, @code{const mglDataA &}phase)
+ at deftypefnx {C function} @code{void} mgl_datac_set_ri (@code{HADT} dat, @code{HCDT} re, @code{HCDT} im)
+ at deftypefnx {C function} @code{void} mgl_datac_set_ap (@code{HADT} dat, @code{HCDT} ampl, @code{HCDT} phase)
+Copies the data from @code{mglData} instances for real and imaginary parts of complex data arrays.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglData}} @code{void} Set (@code{const std::vector<int> &}d)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Set (@code{const std::vector<int> &}d)
+ at deftypefnx {Method on @code{mglData}} @code{void} Set (@code{const std::vector<float> &}d)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Set (@code{const std::vector<float> &}d)
+ at deftypefnx {Method on @code{mglData}} @code{void} Set (@code{const std::vector<double> &}d)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Set (@code{const std::vector<double> &}d)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Set (@code{const std::vector<dual> &}d)
+Allocates memory and copies the data from the @code{std::vector<T>} array.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglData}} @code{void} Set (@code{const char *}str, @code{int} NX, @code{int} NY=@code{1}, @code{int} NZ=@code{1})
+ at deftypefnx {C function} @code{void} mgl_data_set_values (@code{const char *}str, @code{int} NX, @code{int} NY, @code{int} NZ)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Set (@code{const char *}str, @code{int} NX, @code{int} NY=@code{1}, @code{int} NZ=@code{1})
+ at deftypefnx {C function} @code{void} mgl_datac_set_values (@code{const char *}str, @code{int} NX, @code{int} NY, @code{int} NZ)
+Allocates memory and scanf the data from the string.
+ at end deftypefn
+
+
+ at deftypefn {Method on @code{mglData}} @code{void} SetList (@code{long} n, ...)
+Allocate memory and set data from variable argument list of @emph{double} values. Note, you need to specify decimal point @samp{.} for integer values! For example, the code @code{SetList(2,0.,1.);} is correct, but the code @code{SetList(2,0,1);} is incorrect.
+ at end deftypefn
+
+
+
+ at deftypefn {Method on @code{mglData}} @code{void} Link (@code{mglData &}from)
+ at deftypefnx {Method on @code{mglData}} @code{void} Link (@code{mreal *}A, @code{int} NX, @code{int} NY=@code{1}, @code{int} NZ=@code{1})
+ at deftypefnx {C function} @code{void} mgl_data_link (@code{HMDT} dat, @code{mreal *}A, @code{int} NX, @code{int} NY, @code{int} NZ)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Link (@code{mglDataC &}from)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Link (@code{dual *}A, @code{int} NX, @code{int} NY=@code{1}, @code{int} NZ=@code{1})
+ at deftypefnx {C function} @code{void} mgl_datac_link (@code{HADT} dat, @code{dual *}A, @code{int} NX, @code{int} NY, @code{int} NZ)
+Links external data array, i.e. don't delete this array at exit.
+ at end deftypefn
+ at end ifclear
+
+ at anchor{var}
+ at deftypefn {MGL command} {} var @sc{dat} @code{num v1 [v2=nan]}
+Creates new variable with name @var{dat} for one-dimensional array of size @var{num}. Array elements are equidistantly distributed in range [@var{v1}, @var{v2}]. If @var{v2}=@code{nan} then @var{v2=v1} is used.
+ at end deftypefn
+
+ at anchor{fill}
+ at deftypefn {MGL command} {} fill dat v1 v2 ['dir'='x']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Fill (@code{mreal} v1, @code{mreal} v2, @code{char} dir=@code{'x'})
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Fill (@code{dual} v1, @code{dual} v2, @code{char} dir=@code{'x'})
+ at deftypefnx {C function} @code{void} mgl_data_fill (@code{HMDT} dat, @code{mreal} v1, @code{mreal} v2, @code{char} dir)
+ at deftypefnx {C function} @code{void} mgl_datac_fill (@code{HADT} dat, @code{dual} v1, @code{dual} v2, @code{char} dir)
+ at end ifclear
+Equidistantly fills the data values to range [@var{v1}, @var{v2}] in direction @var{dir}=@{@samp{x}, at samp{y}, at samp{z}@}.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} fill dat 'eq' [vdat wdat]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Fill (@code{HMGL} gr, @code{const char *}eq, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglData}} @code{void} Fill (@code{HMGL} gr, @code{const char *}eq, @code{const mglDataA &}vdat, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglData}} @code{void} Fill (@code{HMGL} gr, @code{const char *}eq, @code{const mglDataA &}vdat, @code{const mglDataA &}wdat, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Fill (@code{HMGL} gr, @code{const char *}eq, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Fill (@code{HMGL} gr, @code{const char *}eq, @code{const mglDataA &}vdat, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Fill (@code{HMGL} gr, @code{const char *}eq, @code{const mglDataA &}vdat, @code{const mglDataA &}wdat, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_data_fill_eq (@code{HMGL} gr, @code{HMDT} dat, @code{const char *}eq, @code{HCDT} vdat, @code{HCDT} wdat, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_datac_fill_eq (@code{HMGL} gr, @code{HADT} dat, @code{const char *}eq, @code{HCDT} vdat, @code{HCDT} wdat, @code{const char *}opt)
+ at end ifclear
+Fills the value of array according to the formula in string @var{eq}. Formula is an arbitrary expression depending  on variables @samp{x}, @samp{y}, @samp{z}, @samp{u}, @samp{v}, @samp{w}. Coordinates @samp{x}, @samp{y}, @samp{z} are supposed to be normalized in axis range of canvas @var{gr} (in difference from @code{Modify} functions). Variable @samp{u} is the original value of the array. Variables @samp{v} and @samp{w} are values of @var{vdat}, @var{wdat} which can be @code{NULL} (i.e. [...]
+ at end deftypefn
+
+ at anchor{modify}
+ at deftypefn {MGL command} {} modify dat 'eq' [@code{dim=0}]
+ at deftypefnx {MGL command} {} modify dat 'eq' vdat [wdat]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Modify (@code{const char *}eq, @code{int} dim=@code{0})
+ at deftypefnx {Method on @code{mglData}} @code{void} Modify (@code{const char *}eq, @code{const mglDataA &}v)
+ at deftypefnx {Method on @code{mglData}} @code{void} Modify (@code{const char *}eq, @code{const mglDataA &}v, @code{const mglDataA &}w)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Modify (@code{const char *}eq, @code{int} dim=@code{0})
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Modify (@code{const char *}eq, @code{const mglDataA &}v)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Modify (@code{const char *}eq, @code{const mglDataA &}v, @code{const mglDataA &}w)
+ at deftypefnx {C function} @code{void} mgl_data_modify (@code{HMDT} dat, @code{const char *}eq, @code{int} dim)
+ at deftypefnx {C function} @code{void} mgl_data_modify_vw (@code{HMDT} dat, @code{const char *}eq, @code{HCDT} v, @code{HCDT} w)
+ at deftypefnx {C function} @code{void} mgl_datac_modify (@code{HADT} dat, @code{const char *}eq, @code{int} dim)
+ at deftypefnx {C function} @code{void} mgl_datac_modify_vw (@code{HADT} dat, @code{const char *}eq, @code{HCDT} v, @code{HCDT} w)
+ at end ifclear
+The same as previous ones but coordinates @samp{x}, @samp{y}, @samp{z} are supposed to be normalized in range [0,1]. If @var{dim}>0 is specified then modification will be fulfilled only for slices >=@var{dim}.
+ at end deftypefn
+
+ at anchor{fillsample}
+ at deftypefn {MGL command} {} fillsample dat 'how'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} FillSample (@code{const char *}how)
+ at deftypefnx {C function} @code{void} mgl_data_fill_sample (@code{HMDT} a, @code{const char *}how)
+ at end ifclear
+Fills data by 'x' or 'k' samples for Hankel ('h') or Fourier ('f') transform.
+ at end deftypefn
+
+
+ at anchor{datagrid}
+ at deftypefn {MGL command} {} datagrid dat xdat ydat zdat
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Grid (@code{HMGL} gr, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Grid (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{mglPoint} p1, @code{mglPoint} p2)
+ at deftypefnx {C function} @code{void} mgl_data_grid (@code{HMGL} gr, @code{HMDT} u, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}opt)
+ at deftypefnx {C function} @code{void} mgl_data_grid_xy (@code{HMDT} u, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2)
+ at end ifclear
+Fills the value of array according to the linear interpolation of triangulated surface assuming x-,y-coordinates equidistantly distributed in axis range (or in range [x1,x2]*[y1,y2]). Triangulated surface is found for arbitrary placed points @samp{x}, @samp{y}, @samp{z}. NAN value is used for grid points placed outside of triangulated surface. @sref{Making regular data}
+ at end deftypefn
+
+
+ at anchor{put}
+ at deftypefn {MGL command} {} put dat @code{val [i=all j=all k=all]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Put (@code{mreal} val, @code{int} i=@code{-1}, @code{int} j=@code{-1}, @code{int} k=@code{-1})
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Put (@code{dual} val, @code{int} i=@code{-1}, @code{int} j=@code{-1}, @code{int} k=@code{-1})
+ at deftypefnx {C function} @code{void} mgl_data_put_val (@code{HMDT} a, @code{mreal} val, @code{int} i, @code{int} j, @code{int} k)
+ at deftypefnx {C function} @code{void} mgl_datac_put_val (@code{HADT} a, @code{dual} val, @code{int} i, @code{int} j, @code{int} k)
+ at end ifclear
+Sets value(s) of array a[@var{i}, @var{j}, @var{k}] = @var{val}. Negative indexes @var{i}, @var{j}, @var{k}=-1 set the value @var{val} to whole range in corresponding direction(s). For example, @code{Put(val,-1,0,-1);} sets a[i,0,j]=@var{val} for i=0...(nx-1), j=0...(nz-1).
+ at end deftypefn
+
+ at deftypefn {MGL command} {} put dat vdat [@code{i=all j=all k=all}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Put (@code{const mglDataA &}v, @code{int} i=@code{-1}, @code{int} j=@code{-1}, @code{int} k=@code{-1})
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Put (@code{const mglDataA &}v, @code{int} i=@code{-1}, @code{int} j=@code{-1}, @code{int} k=@code{-1})
+ at deftypefnx {C function} @code{void} mgl_data_put_dat (@code{HMDT} a, @code{HCDT} v, @code{int} i, @code{int} j, @code{int} k)
+ at deftypefnx {C function} @code{void} mgl_datac_put_dat (@code{HADT} a, @code{HCDT} v, @code{int} i, @code{int} j, @code{int} k)
+ at end ifclear
+Copies value(s) from array @var{v} to the range of original array. Negative indexes @var{i}, @var{j}, @var{k}=-1 set the range in corresponding direction(s). At this minor dimensions of array @var{v} should be large than corresponding dimensions of this array. For example, @code{Put(v,-1,0,-1);} sets a[i,0,j]=v.ny>nz ? v[i,j] : v[i], where i=0...(nx-1), j=0...(nz-1) and condition v.nx>=nx is true.
+ at end deftypefn
+
+ at anchor{refill}
+ at deftypefn {MGL command} {} refill dat xdat vdat [sl=-1]
+ at deftypefnx {MGL command} {} refill dat xdat ydat vdat [sl=-1]
+ at deftypefnx {MGL command} {} refill dat xdat ydat zdat vdat
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Refill (@code{const mglDataA &}x, @code{const mglDataA &}v, @code{mreal} x1, @code{mreal} x2, @code{long} sl=@code{-1})
+ at deftypefnx {Method on @code{mglData}} @code{void} Refill (@code{const mglDataA &}x, @code{const mglDataA &}v, @code{mglPoint} p1, @code{mglPoint} p2, @code{long} sl=@code{-1})
+ at deftypefnx {Method on @code{mglData}} @code{void} Refill (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}v, @code{mglPoint} p1, @code{mglPoint} p2, @code{long} sl=@code{-1})
+ at deftypefnx {Method on @code{mglData}} @code{void} Refill (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}v, @code{mglPoint} p1, @code{mglPoint} p2)
+ at deftypefnx {Method on @code{mglData}} @code{void} Refill (@code{HMGL} gr, @code{const mglDataA &}x, @code{const mglDataA &}v, @code{long} sl=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglData}} @code{void} Refill (@code{HMGL} gr, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}v, @code{long} sl=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Method on @code{mglData}} @code{void} Refill (@code{HMGL} gr, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}v, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{void} mgl_data_refill_x (@code{HMDT} a, @code{HCDT} x, @code{HCDT} v, @code{mreal} x1, @code{mreal} x2, @code{long} sl)
+ at deftypefnx {C function} @code{void} mgl_data_refill_xy (@code{HMDT} a, @code{HCDT} x, @code{HCDT} y, @code{HCDT} v, @code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2, @code{long} sl)
+ at deftypefnx {C function} @code{void} mgl_data_refill_xyz (@code{HMDT} a, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} v, @code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2, @code{mreal} z1, @code{mreal} z2)
+ at deftypefnx {C function} @code{void} mgl_data_refill_gr (@code{HMGL} gr, @code{HMDT} a, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} v, @code{long} sl, @code{const char *}opt)
+ at end ifclear
+Fills by interpolated values of array @var{v} at the point @{@var{x}, @var{y}, @var{z}@}=@{@code{X[i], Y[j], Z[k]}@} (or @{@var{x}, @var{y}, @var{z}@}=@{@code{X[i,j,k], Y[i,j,k], Z[i,j,k]}@} if @var{x}, @var{y}, @var{z} are not 1d arrays), where @code{X,Y,Z} are equidistantly distributed in range [@var{x1}, at var{x2}]*[@var{y1}, at var{y2}]*[@var{z1}, at var{z2}] and have the same sizes as this array. If parameter @var{sl} is 0 or positive then changes will be applied only for slice @var{sl}.
+ at end deftypefn
+
+ at anchor{gspline}
+ at deftypefn {MGL command} {} gspline dat xdat vdat [sl=-1]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} RefillGS (@code{const mglDataA &}x, @code{const mglDataA &}v, @code{mreal} x1, @code{mreal} x2, @code{long} sl=@code{-1})
+ at deftypefnx {C function} @code{void} mgl_data_refill_gs (@code{HMDT} a, @code{HCDT} x, @code{HCDT} v, @code{mreal} x1, @code{mreal} x2, @code{long} sl)
+ at end ifclear
+Fills by global cubic spline values of array @var{v} at the point @var{x}=@code{X[i]}, where @code{X} are equidistantly distributed in range [@var{x1}, at var{x2}] and have the same sizes as this array. If parameter @var{sl} is 0 or positive then changes will be applied only for slice @var{sl}.
+ at end deftypefn
+
+ at anchor{idset}
+ at deftypefn {MGL command} {} idset dat 'ids'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} SetColumnId (@code{const char *}ids)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} SetColumnId (@code{const char *}ids)
+ at deftypefnx {C function} @code{void} mgl_data_set_id (@code{HMDT} a, @code{const char *}ids)
+ at deftypefnx {C function} @code{void} mgl_datac_set_id (@code{HADT} a, @code{const char *}ids)
+ at end ifclear
+Sets the symbol @var{ids} for data columns. The string should contain one symbol 'a'...'z' per column. These ids are used in @ref{column}.
+ at end deftypefn
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node File I/O, Make another data, Data filling, Data processing
+ at section File I/O
+ at nav{}
+ at cindex Read
+ at cindex ReadMat
+ at cindex ReadRange
+ at cindex ReadAll
+ at cindex Save
+ at cindex ReadHDF
+ at cindex SaveHDF
+ at cindex Import
+ at cindex Export
+
+ at anchor{read}
+ at deftypefn {MGL command} {} read @sc{dat} 'fname'
+ at deftypefnx {MGL command} {} read @sc{redat} @sc{imdat} 'fname'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{bool} Read (@code{const char *}fname)
+ at deftypefnx {Method on @code{mglDataC}} @code{bool} Read (@code{const char *}fname)
+ at deftypefnx {C function} @code{int} mgl_data_read (@code{HMDT} dat, @code{const char *}fname)
+ at deftypefnx {C function} @code{int} mgl_datac_read (@code{HADT} dat, @code{const char *}fname)
+ at end ifclear
+Reads data from tab-separated text file with auto determining sizes of the data. Double newline means the beginning of new z-slice.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} read @sc{dat} 'fname' @code{mx [my=1 mz=1]}
+ at deftypefnx {MGL command} {} read @sc{redat} @sc{imdat} 'fname' @code{mx [my=1 mz=1]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{bool} Read (@code{const char *}fname, @code{int} mx, @code{int} my=@code{1}, @code{int} mz=@code{1})
+ at deftypefnx {Method on @code{mglDataC}} @code{bool} Read (@code{const char *}fname, @code{int} mx, @code{int} my=@code{1}, @code{int} mz=@code{1})
+ at deftypefnx {C function} @code{int} mgl_data_read_dim (@code{HMDT} dat, @code{const char *}fname, @code{int} mx, @code{int} my, @code{int} mz)
+ at deftypefnx {C function} @code{int} mgl_datac_read_dim (@code{HADT} dat, @code{const char *}fname, @code{int} mx, @code{int} my, @code{int} mz)
+ at end ifclear
+Reads data from text file with specified data sizes. This function does nothing if one of parameters @var{mx}, @var{my} or @var{mz} is zero or negative.
+ at end deftypefn
+
+ at anchor{readmat}
+ at deftypefn {MGL command} {} readmat @sc{dat} 'fname' [@code{dim=2}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{bool} ReadMat (@code{const char *}fname, @code{int} dim=@code{2})
+ at deftypefnx {Method on @code{mglDataC}} @code{bool} ReadMat (@code{const char *}fname, @code{int} dim=@code{2})
+ at deftypefnx {C function} @code{int} mgl_data_read_mat (@code{HMDT} dat, @code{const char *}fname, @code{int} dim)
+ at deftypefnx {C function} @code{int} mgl_datac_read_mat (@code{HADT} dat, @code{const char *}fname, @code{int} dim)
+ at end ifclear
+Read data from text file with size specified at beginning of the file by first @var{dim} numbers. At this, variable @var{dim} set data dimensions.
+ at end deftypefn
+
+ at anchor{readall}
+ at deftypefn {MGL command} {} readall @sc{dat} 'templ' @code{v1 v2 [dv=1 slice=off]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} ReadRange (@code{const char *}templ, @code{mreal} from, @code{mreal} to, @code{mreal} step=@code{1}, @code{bool} as_slice=@code{false})
+ at deftypefnx {Method on @code{mglDataC}} @code{void} ReadRange (@code{const char *}templ, @code{mreal} from, @code{mreal} to, @code{mreal} step=@code{1}, @code{bool} as_slice=@code{false})
+ at deftypefnx {C function} @code{int} mgl_data_read_range (@code{HMDT} dat, @code{const char *}templ, @code{mreal} from, @code{mreal} to, @code{mreal} step, @code{int} as_slice)
+ at deftypefnx {C function} @code{int} mgl_datac_read_range (@code{HADT} dat, @code{const char *}templ, @code{mreal} from, @code{mreal} to, @code{mreal} step, @code{int} as_slice)
+ at end ifclear
+Join data arrays from several text files. The file names are determined by function call @code{sprintf(fname,templ,val);}, where @var{val} changes from @var{from} to @var{to} with step @var{step}. The data load one-by-one in the same slice if @var{as_slice}=@code{false} or as slice-by-slice if @var{as_slice}=@code{true}.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} readall @sc{dat} 'templ' @code{[slice=off]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} ReadAll (@code{const char *}templ, @code{bool} as_slice=@code{false})
+ at deftypefnx {Method on @code{mglDataC}} @code{void} ReadAll (@code{const char *}templ, @code{bool} as_slice=@code{false})
+ at deftypefnx {C function} @code{int} mgl_data_read_all (@code{HMDT} dat, @code{const char *}templ, @code{int} as_slice)
+ at deftypefnx {C function} @code{int} mgl_datac_read_all (@code{HADT} dat, @code{const char *}templ, @code{int} as_slice)
+ at end ifclear
+Join data arrays from several text files which filenames satisfied the template @var{templ} (for example, @var{templ}=@code{"t_*.dat"}). The data load one-by-one in the same slice if @var{as_slice}=@code{false} or as slice-by-slice if @var{as_slice}=@code{true}.
+ at end deftypefn
+
+ at anchor{scanfile}
+ at deftypefn {MGL command} {} scanfile @sc{dat} 'fname' 'templ'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{bool} ScanFile (@code{const char *}fname, @code{const char *}templ)
+ at deftypefnx {C function} @code{int} mgl_data_scan_file (@code{HMDT} dat, @code{const char *}fname, @code{const char *}templ)
+ at end ifclear
+Read file @var{fname} line-by-line and scan each line for numbers according the template @var{templ}. The numbers denoted as @samp{%g} in the template. @sref{Saving and scanning file}
+ at end deftypefn
+
+ at anchor{save}
+ at deftypefn {MGL command} {} save dat 'fname'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglDataA}} @code{void} Save (@code{const char *}fname, @code{int} ns=@code{-1}) @code{const}
+ at deftypefnx {C function} @code{void} mgl_data_save (@code{HCDT} dat, @code{const char *}fname, @code{int} ns)
+ at deftypefnx {C function} @code{void} mgl_datac_save (@code{HCDT} dat, @code{const char *}fname, @code{int} ns)
+ at end ifclear
+Saves the whole data array (for @var{ns}=@code{-1}) or only @var{ns}-th slice to the text file @var{fname}.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} save 'str' 'fname' ['mode'='a']
+Saves the string @var{str} to the text file @var{fname}. For parameter @var{mode}=@samp{a} will append string to the file (default); for @var{mode}=@samp{w} will overwrite the file. @sref{Saving and scanning file}
+ at end deftypefn
+
+
+ at anchor{readhdf}
+ at deftypefn {MGL command} {} readhdf @sc{dat} 'fname' 'dname'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} ReadHDF (@code{const char *}fname, @code{const char *}dname)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} ReadHDF (@code{const char *}fname, @code{const char *}dname)
+ at deftypefnx {C function} @code{void} mgl_data_read_hdf (@code{HMDT} dat, @code{const char *}fname, @code{const char *}dname)
+ at deftypefnx {C function} @code{void} mgl_datac_read_hdf (@code{HADT} dat, @code{const char *}fname, @code{const char *}dname)
+ at end ifclear
+Reads data array named @var{dname} from HDF5 or HDF4 file. This function does nothing if HDF5|HDF4 was disabled during library compilation.
+ at end deftypefn
+
+ at anchor{savehdf}
+ at deftypefn {MGL command} {} savehdf dat 'fname' 'dname' [@code{rewrite}=@code{off}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglDataA}} @code{void} SaveHDF (@code{const char *}fname, @code{const char *}dname, @code{bool} rewrite=@code{false}) @code{const}
+ at deftypefnx {C function} @code{void} mgl_data_save_hdf (@code{HCDT} dat, @code{const char *}fname, @code{const char *}dname, @code{int} rewrite)
+ at deftypefnx {C function} @code{void} mgl_datac_save_hdf (@code{HCDT} dat, @code{const char *}fname, @code{const char *}dname, @code{int} rewrite)
+ at end ifclear
+Saves data array named @var{dname} to HDF5 file. This function does nothing if HDF5 was disabled during library compilation.
+ at end deftypefn
+
+ at anchor{datas}
+ at deftypefn {MGL command} {} datas 'fname'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglDataA}} @code{int} DatasHDF (@code{const char *}fname, @code{char *}buf, @code{long} size) @code{static}
+ at deftypefnx {C function} @code{int} mgl_datas_hdf (@code{const char *}fname, @code{char *}buf, @code{long} size)
+ at end ifclear
+Put data names from HDF5 file @var{fname} into @var{buf} as '\t' separated fields. In MGL version the list of data names will be printed as message. This function does nothing if HDF5 was disabled during library compilation.
+ at end deftypefn
+
+ at anchor{openhdf}
+ at deftypefn {MGL command} {} openhdf 'fname'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglParse}} @code{void} OpenHDF (@code{const char *}fname)
+ at deftypefnx {C function} @code{void} mgl_parser_openhdf (@code{HMPR} pr, @code{const char *}fname)
+ at end ifclear
+Reads all data array from HDF5 file @var{fname} and create MGL variables with names of data names in HDF file. Complex variables will be created if data name starts with @samp{!}.
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {C function} @code{const char * const *} mgl_datas_hdf_str (@code{HMPR} pr, @code{const char *}fname)
+Put HDF data names as list of strings (last one is ""). The result is valid untill next call of the function.
+ at end deftypefn
+ at end ifclear
+
+
+ at anchor{import}
+ at deftypefn {MGL command} {} import @sc{dat} 'fname' 'sch' [@code{v1=0 v2=1}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Import (@code{const char *}fname, @code{const char *}scheme, @code{mreal} v1=@code{0}, mreal v2=@code{1})
+ at deftypefnx {C function} @code{void} mgl_data_import (@code{HMDT} dat, @code{const char *}fname, @code{const char *}scheme, @code{mreal} v1, mreal v2)
+ at end ifclear
+Reads data from bitmap file (now support only PNG format). The RGB values of bitmap pixels are transformed to mreal values in range [@var{v1}, @var{v2}] using color scheme @var{scheme} (@pxref{Color scheme}).
+ at end deftypefn
+
+ at anchor{export}
+ at deftypefn {MGL command} {} export dat 'fname' 'sch' [@code{v1=0 v2=0}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglDataA}} @code{void} Export (@code{const char *}fname, @code{const char *}scheme, @code{mreal} v1=@code{0}, mreal v2=@code{0}, @code{int} ns=@code{-1}) const
+ at deftypefnx {C function} @code{void} mgl_data_export (@code{HMDT} dat, @code{const char *}fname, @code{const char *}scheme, @code{mreal} v1, mreal v2, @code{int} ns) const
+ at end ifclear
+Saves data matrix (or @code{ns}-th slice for 3d data) to bitmap file (now support only PNG format). The data values are transformed from range [@var{v1}, @var{v2}] to RGB pixels of bitmap using color scheme @var{scheme} (@pxref{Color scheme}). If @var{v1}>=@var{v2} then the values of @var{v1}, @var{v2} are automatically determined as minimal and maximal value of the data array.
+ at end deftypefn
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Make another data, Data changing, File I/O, Data processing
+ at section Make another data
+ at nav{}
+ at cindex SubData
+ at cindex Column
+ at cindex Trace
+ at cindex Hist
+ at cindex Resize
+ at cindex Evaluate
+ at cindex Combine
+ at cindex Momentum
+ at cindex Sum
+ at cindex Min
+ at cindex Max
+ at cindex Roots
+ at cindex Correl
+ at cindex AutoCorrel
+
+
+ at anchor{subdata}
+ at deftypefn {MGL command} {} subdata @sc{res} dat @code{xx [yy=all zz=all]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{mglData} SubData (@code{mreal} xx, @code{mreal} yy=@code{-1}, @code{mreal} zz=@code{-1}) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{mglData} SubData (@code{mreal} xx, @code{mreal} yy=@code{-1}, @code{mreal} zz=@code{-1}) @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_data_subdata (@code{HCDT} dat, @code{mreal} xx, @code{mreal} yy, @code{mreal} zz)
+ at end ifclear
+Extracts sub-array data from the original data array keeping fixed positive index. For example @code{SubData(-1,2)} extracts 3d row (indexes are zero based), @code{SubData(4,-1)} extracts 5th column, @code{SubData(-1,-1,3)} extracts 4th slice and so on. If argument(s) are non-integer then linear interpolation between slices is used. In MGL version this command usually is used as inline one @code{dat(xx,yy,zz)}. Function return NULL or create empty data if data cannot be created for given [...]
+ at end deftypefn
+
+ at deftypefn {MGL command} {} subdata @sc{res} dat xdat [ydat zdat]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{mglData} SubData (@code{const mglDataA &}xx, @code{const mglDataA &}yy, @code{const mglDataA &}zz) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{mglData} SubData (@code{const mglDataA &}xx, @code{const mglDataA &}yy, @code{const mglDataA &}zz) @code{const}
+ at deftypefnx {Method on @code{mglData}} @code{mglData} SubData (@code{const mglDataA &}xx, @code{const mglDataA &}yy) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{mglData} SubData (@code{const mglDataA &}xx, @code{const mglDataA &}yy) @code{const}
+ at deftypefnx {Method on @code{mglData}} @code{mglData} SubData (@code{const mglDataA &}xx) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{mglData} SubData (@code{const mglDataA &}xx) @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_data_subdata_ext (@code{HCDT} dat, @code{HCDT} xx, @code{HCDT} yy, @code{HCDT} zz)
+ at deftypefnx {C function} @code{HADT} mgl_datac_subdata_ext (@code{HCDT} dat, @code{HCDT} xx, @code{HCDT} yy, @code{HCDT} zz)
+ at end ifclear
+Extracts sub-array data from the original data array for indexes specified by arrays @var{xx}, @var{yy}, @var{zz} (indirect access). This function work like previous one for 1D arguments or numbers, and resulting array dimensions are equal dimensions of 1D arrays for corresponding direction. For 2D and 3D arrays in arguments, the resulting array have the same dimensions as input arrays. The dimensions of all argument must be the same (or to be scalar 1*1*1) if they are 2D or 3D arrays. I [...]
+ at end deftypefn
+
+ at anchor{column}
+ at deftypefn {MGL command} {} column @sc{res} dat 'eq'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Column (@code{const char *}eq) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{mglData} Column (@code{const char *}eq) @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_data_column (@code{HCDT} dat, @code{const char *}eq)
+ at end ifclear
+Get column (or slice) of the data filled by formula @var{eq} on column ids. For example, @code{Column("n*w^2/exp(t)");}. The column ids must be defined first by @ref{idset} function or read from files. In MGL version this command usually is used as inline one @code{dat('eq')}. Function return NULL or create empty data if data cannot be created for given arguments.
+ at end deftypefn
+
+ at anchor{resize}
+ at deftypefn {MGL command} {} resize @sc{res} dat @code{mx [my=1 mz=1]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Resize (@code{int} mx, @code{int} my=@code{0}, @code{int} mz=@code{0}, @code{mreal} x1=@code{0}, @code{mreal} x2=@code{1}, @code{mreal} y1=@code{0}, @code{mreal} y2=@code{1}, @code{mreal} z1=@code{0}, @code{mreal} z2=@code{1}) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{mglData} Resize (@code{int} mx, @code{int} my=@code{0}, @code{int} mz=@code{0}, @code{mreal} x1=@code{0}, @code{mreal} x2=@code{1}, @code{mreal} y1=@code{0}, @code{mreal} y2=@code{1}, @code{mreal} z1=@code{0}, @code{mreal} z2=@code{1}) @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_data_resize (@code{HCDT} dat, @code{int} mx, @code{int} my, @code{int} mz)
+ at deftypefnx {C function} @code{HMDT} mgl_data_resize_box (@code{HCDT} dat, @code{int} mx, @code{int} my, @code{int} mz, @code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2, @code{mreal} z1, @code{mreal} z2)
+ at end ifclear
+Resizes the data to new size @var{mx}, @var{my}, @var{mz} from box (part) [@var{x1}, at var{x2}] x [@var{y1}, at var{y2}] x [@var{z1}, at var{z2}] of original array. Initially x,y,z coordinates are supposed to be in [0,1]. If one of sizes @var{mx}, @var{my} or @var{mz} is 0 then initial size is used. Function return NULL or create empty data if data cannot be created for given arguments.
+ at end deftypefn
+
+ at anchor{evaluate}
+ at deftypefn {MGL command} {} evaluate @sc{res} dat idat [@code{norm=on}]
+ at deftypefnx {MGL command} {} evaluate @sc{res} dat idat jdat [@code{norm=on}]
+ at deftypefnx {MGL command} {} evaluate @sc{res} dat idat jdat kdat [@code{norm=on}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Evaluate (@code{const mglDataA &}idat, @code{bool} norm=@code{true}) @code{const}
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Evaluate (@code{const mglDataA &}idat, @code{const mglDataA &}jdat, @code{bool} norm=@code{true}) @code{const}
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Evaluate (@code{const mglDataA &}idat, @code{const mglDataA &}jdat, @code{const mglDataA &}kdat, @code{bool} norm=@code{true}) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{mglData} Evaluate (@code{const mglDataA &}idat, @code{bool} norm=@code{true}) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{mglData} Evaluate (@code{const mglDataA &}idat, @code{const mglDataA &}jdat, @code{bool} norm=@code{true}) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{mglData} Evaluate (@code{const mglDataA &}idat, @code{const mglDataA &}jdat, @code{const mglDataA &}kdat, @code{bool} norm=@code{true}) @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_data_evaluate (@code{HCDT} dat, @code{HCDT} idat, @code{HCDT} jdat, @code{HCDT} kdat, @code{int} norm)
+ at end ifclear
+Gets array which values is result of interpolation of original array for coordinates from other arrays. All dimensions must be the same for data @var{idat}, @var{jdat}, @var{kdat}. Coordinates from @var{idat}, @var{jdat}, @var{kdat} are supposed to be normalized in range [0,1] (if @var{norm}=@code{true}) or in ranges [0,nx], [0,ny], [0,nz] correspondingly. Function return NULL or create empty data if data cannot be created for given arguments.
+ at end deftypefn
+
+ at anchor{section}
+ at deftypefn {MGL command} {} section @sc{res} dat ids ['dir'='y' @code{val=nan}]
+ at deftypefnx {MGL command} {} section @sc{res} dat @code{id} ['dir'='y' @code{val=nan}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Section (@code{const mglDataA &}ids, @code{const char *}dir=@code{'y'}, @code{mreal} val=@code{NAN}) @code{const}
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Section (@code{long} id, @code{const char *}dir=@code{'y'}, @code{mreal} val=@code{NAN}) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{mglData} Section (@code{const mglDataA &}ids, @code{const char *}dir=@code{'y'}, @code{mreal} val=@code{NAN}) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{mglData} Section (@code{long} id, @code{const char *}dir=@code{'y'}, @code{mreal} val=@code{NAN}) @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_data_section (@code{HCDT} dat, @code{HCDT} ids, @code{const char *}dir, @code{mreal} val)
+ at deftypefnx {C function} @code{HMDT} mgl_data_section_val (@code{HCDT} dat, @code{long} id, @code{const char *}dir, @code{mreal} val)
+ at deftypefnx {C function} @code{HADT} mgl_datac_section (@code{HCDT} dat, @code{HCDT} ids, @code{const char *}dir, @code{mreal} val)
+ at deftypefnx {C function} @code{HADT} mgl_datac_section_val (@code{HCDT} dat, @code{long} id, @code{const char *}dir, @code{mreal} val)
+ at end ifclear
+Gets array which is @var{id}-th section (range of slices separated by value @var{val}) of original array @var{dat}. For @var{id}<0 the reverse order is used (i.e. -1 give last section). If several @var{ids} are provided then output array will be result  of sequential joining of sections.
+ at end deftypefn
+
+
+ at anchor{solve}
+ at deftypefn {MGL command} {} solve @sc{res} dat @code{val} 'dir' [@code{norm=on}]
+ at deftypefnx {MGL command} {} solve @sc{res} dat @code{val} 'dir' idat [@code{norm=on}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Solve (@code{mreal} val, @code{char} dir, @code{bool} norm=@code{true}) @code{const}
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Solve (@code{mreal} val, @code{char} dir, @code{const mglDataA &}idat, @code{bool} norm=@code{true}) @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_data_solve (@code{HCDT} dat, @code{mreal} val, @code{char} dir, @code{HCDT} idat, @code{int} norm)
+ at end ifclear
+Gets array which values is indexes (roots) along given direction @var{dir}, where interpolated values of data @var{dat} are equal to @var{val}. Output data will have the sizes of @var{dat} in directions transverse to @var{dir}. If data @var{idat} is provided then its values are used as starting points. This allows to find several branches by consequentive calls. Indexes are supposed to be normalized in range [0,1] (if @var{norm}=@code{true}) or in ranges [0,nx], [0,ny], [0,nz] correspond [...]
+ at end deftypefn
+
+ at anchor{roots}
+ at deftypefn {MGL command} {} roots @sc{res} 'func' ini ['var'='x']
+ at deftypefnx {MGL command} {} roots @sc{res} 'func' @code{ini} ['var'='x']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Roots (@code{const char *}func, @code{char} var) @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_data_roots (@code{const char *}func, @code{HCDT} ini, @code{char} var)
+ at deftypefnx {C function} @code{mreal} mgl_find_root_txt (@code{const char *}func, @code{mreal} ini, @code{char} var)
+ at end ifclear
+Find roots of equation 'func'=0 for variable @var{var} with initial guess @var{ini}. Secant method is used for root finding. Function return NULL or create empty data if data cannot be created for given arguments.
+ at end deftypefn
+
+ at anchor{detect}
+ at deftypefn {MGL command} {} detect @sc{res} dat @code{lvl dj [di=0 minlen=0]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Detect (@code{mreal} lvl, @code{mreal} dj, @code{mreal} di=@code{0}, @code{mreal} minlen=@code{0}) @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_data_detect (@code{HCDT} dat, @code{mreal} lvl, @code{mreal} dj, @code{mreal} di, @code{mreal} minlen)
+ at end ifclear
+Get curves @{x,y@}, separated by NAN values, for local maximal values of array @var{dat} as function of x-coordinate. Noises below @var{lvl} amplitude are ignored. Parameter @var{dj} (in range [0,ny]) set the "attraction" y-distance of points to the curve. Similarly, @var{di} continue curve in x-direction through gaps smaller than @var{di} points. Curves with minimal length smaller than @var{minlen} will be ignored.
+ at end deftypefn
+
+ at anchor{hist}
+ at deftypefn {MGL command} {} hist @sc{res} dat @code{num v1 v2 [nsub=0]}
+ at deftypefnx {MGL command} {} hist @sc{res} dat wdat @code{num v1 v2 [nsub=0]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Hist (@code{int} n, @code{mreal} v1=@code{0}, @code{mreal} v2=@code{1}, @code{int} nsub=@code{0}) @code{const}
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Hist (@code{const mglDataA &}w, @code{int} n, @code{mreal} v1=@code{0}, @code{mreal} v2=@code{1}, @code{int} nsub=@code{0}) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{mglData} Hist (@code{int} n, @code{mreal} v1=@code{0}, @code{mreal} v2=@code{1}, @code{int} nsub=@code{0}) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{mglData} Hist (@code{const mglDataA &}w, @code{int} n, @code{mreal} v1=@code{0}, @code{mreal} v2=@code{1}, @code{int} nsub=@code{0}) @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_data_hist (@code{HCDT} dat, @code{int} n, @code{mreal} v1, @code{mreal} v2, @code{int} nsub)
+ at deftypefnx {C function} @code{HMDT} mgl_data_hist_w (@code{HCDT} dat, @code{HCDT} w, @code{int} n, @code{mreal} v1, @code{mreal} v2, @code{int} nsub)
+ at end ifclear
+Creates @var{n}-th points distribution of the data values in range [@var{v1}, @var{v2}]. Array @var{w} specifies weights of the data elements (by default is 1). Parameter @var{nsub} define the number of additional interpolated points (for smoothness of histogram). Function return NULL or create empty data if data cannot be created for given arguments. See also @ref{Data manipulation}
+ at end deftypefn
+
+ at anchor{momentum}
+ at deftypefn {MGL command} {} momentum @sc{res} dat 'how' ['dir'='z']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Momentum (@code{char} dir, @code{const char *}how) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{mglData} Momentum (@code{char} dir, @code{const char *}how) @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_data_momentum (@code{HCDT} dat, @code{char} dir, @code{const char *}how)
+ at end ifclear
+Gets momentum (1d-array) of the data along direction @var{dir}. String @var{how} contain kind of momentum. The momentum is defined like as
+ at iftex
+ at math{res_k = \sum_{ij} how(x_i,y_j,z_k) a_{ij}/\sum_{ij} a_{ij}}
+ at end iftex
+ at ifnottex
+res_k = \sum_ij how(x_i,y_j,z_k) a_ij/ \sum_ij a_ij
+ at end ifnottex
+if @var{dir}=@samp{z} and so on. Coordinates @samp{x}, @samp{y}, @samp{z} are data indexes normalized in range [0,1]. Function return NULL or create empty data if data cannot be created for given arguments.
+ at end deftypefn
+
+ at anchor{sum}
+ at deftypefn {MGL command} {} sum @sc{res} dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Sum (@code{const char *}dir) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{mglData} Sum (@code{const char *}dir) @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_data_sum (@code{HCDT} dat, @code{const char *}dir)
+ at end ifclear
+Gets array which is the result of summation in given direction or direction(s). Function return NULL or create empty data if data cannot be created for given arguments.
+ at end deftypefn
+
+ at anchor{max}
+ at deftypefn {MGL command} {} max @sc{res} dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Max (@code{const char *}dir) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{mglData} Max (@code{const char *}dir) @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_data_max_dir (@code{HCDT} dat, @code{const char *}dir)
+ at end ifclear
+Gets array which is the maximal data values in given direction or direction(s). Function return NULL or create empty data if data cannot be created for given arguments.
+ at end deftypefn
+
+ at anchor{min}
+ at deftypefn {MGL command} {} min @sc{res} dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Min (@code{const char *}dir) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{mglData} Min (@code{const char *}dir) @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_data_min_dir (@code{HCDT} dat, @code{const char *}dir)
+ at end ifclear
+Gets array which is the maximal data values in given direction or direction(s). Function return NULL or create empty data if data cannot be created for given arguments.
+ at end deftypefn
+
+ at anchor{combine}
+ at deftypefn {MGL command} {} combine @sc{res} adat bdat
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Combine (@code{const mglDataA &}a) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{mglData} Combine (@code{const mglDataA &}a) @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_data_combine (@code{HCDT} dat, @code{HCDT} a)
+ at end ifclear
+Returns direct multiplication of arrays (like, res[i,j] = this[i]*a[j] and so on). Function return NULL or create empty data if data cannot be created for given arguments.
+ at end deftypefn
+
+ at anchor{trace}
+ at deftypefn {MGL command} {} trace @sc{res} dat
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Trace () @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{mglData} Trace () @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_data_trace (@code{HCDT} dat)
+ at end ifclear
+Gets array of diagonal elements a[i,i] (for 2D case) or a[i,i,i] (for 3D case) where i=0...nx-1. Function return copy of itself for 1D case. Data array must have dimensions ny,nz >= nx or ny,nz = 1. Function return NULL or create empty data if data cannot be created for given arguments.
+ at end deftypefn
+
+ at anchor{correl}
+ at deftypefn {MGL command} {} correl @sc{res} adat bdat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Correl (@code{const mglDataA &}b, @code{const char *}dir) @code{const}
+ at deftypefnx {Method on @code{mglData}} @code{mglData} AutoCorrel (@code{const char *}dir) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{mglDataC} Correl (@code{const mglDataA &}b, @code{const char *}dir) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{mglDataC} AutoCorrel (@code{const char *}dir) @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_data_correl (@code{HCDT} a, @code{HCDT} b, @code{const char *}dir)
+ at deftypefnx {C function} @code{HADT} mgl_datac_correl (@code{HCDT} a, @code{HCDT} b, @code{const char *}dir)
+ at end ifclear
+Find correlation between data @var{a} (or this in C++) and @var{b} along directions @var{dir}. Fourier transform is used to find the correlation. So, you may want to use functions @ref{swap} or @ref{norm} before plotting it. Function return NULL or create empty data if data cannot be created for given arguments.
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Method on @code{mglDataC}} @code{mglData} Real () @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_datac_real (@code{HCDT} dat)
+Gets array of real parts of the data.
+ at end deftypefn
+ at deftypefn {Method on @code{mglDataC}} @code{mglData} Imag () @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_datac_imag (@code{HCDT} dat)
+Gets array of imaginary parts of the data.
+ at end deftypefn
+ at deftypefn {Method on @code{mglDataC}} @code{mglData} Abs () @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_datac_abs (@code{HCDT} dat)
+Gets array of absolute values of the data.
+ at end deftypefn
+ at deftypefn {Method on @code{mglDataC}} @code{mglData} Arg () @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_datac_arg (@code{HCDT} dat)
+Gets array of arguments of the data.
+ at end deftypefn
+ at end ifclear
+
+ at anchor{pulse}
+ at deftypefn {MGL command} {} pulse @sc{res} dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{mglData} Pulse (@code{const char *}dir) @code{const}
+ at deftypefnx {C function} @code{HMDT} mgl_data_pulse (@code{HCDT} dat, @code{const char *}dir)
+ at end ifclear
+Find pulse properties along direction @var{dir}: pulse maximum (in column 0) and its position (in column 1), pulse width near maximum (in column 3) and by half height (in column 2), energy in first pulse (in column 4). NAN values are used for widths if maximum is located near the edges. Note, that there is uncertainty for complex data. Usually one should use square of absolute value (i.e. |dat[i]|^2) for them. So, MathGL don't provide this function for complex data arrays. However, C fun [...]
+ at end deftypefn
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Data changing, Interpolation, Make another data, Data processing
+ at section Data changing
+ at nav{}
+ at cindex CumSum
+ at cindex Integral
+ at cindex Diff
+ at cindex Diff2
+ at cindex SinFFT
+ at cindex CosFFT
+ at cindex Hankel
+ at cindex Swap
+ at cindex Roll
+ at cindex Mirror
+ at cindex Sew
+ at cindex Smooth
+ at cindex Envelop
+ at cindex Norm
+ at cindex NormSl
+
+These functions change the data in some direction like differentiations, integrations and so on. The direction in which the change will applied is specified by the string parameter, which may contain @samp{x}, @samp{y} or @samp{z} characters for 1-st, 2-nd and 3-d dimension correspondingly.
+
+ at anchor{cumsum}
+ at deftypefn {MGL command} {} cumsum dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} CumSum (@code{const char *}dir)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} CumSum (@code{const char *}dir)
+ at deftypefnx {C function} @code{void} mgl_data_cumsum (@code{HMDT} dat, @code{const char *}dir)
+ at deftypefnx {C function} @code{void} mgl_datac_cumsum (@code{HADT} dat, @code{const char *}dir)
+ at end ifclear
+Cumulative summation of the data in given direction or directions.
+ at end deftypefn
+
+ at anchor{integrate}
+ at deftypefn {MGL command} {} integrate dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Integral (@code{const char *}dir)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Integral (@code{const char *}dir)
+ at deftypefnx {C function} @code{void} mgl_data_integral (@code{HMDT} dat, @code{const char *}dir)
+ at deftypefnx {C function} @code{void} mgl_datac_integral (@code{HADT} dat, @code{const char *}dir)
+ at end ifclear
+Integrates (like cumulative summation) the data in given direction or directions.
+ at end deftypefn
+
+ at anchor{diff}
+ at deftypefn {MGL command} {} diff dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Diff (@code{const char *}dir)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Diff (@code{const char *}dir)
+ at deftypefnx {C function} @code{void} mgl_data_diff (@code{HMDT} dat, @code{const char *}dir)
+ at deftypefnx {C function} @code{void} mgl_datac_diff (@code{HADT} dat, @code{const char *}dir)
+ at end ifclear
+Differentiates the data in given direction or directions.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} diff dat xdat ydat [zdat]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Diff (@code{const mglDataA &}x)
+ at deftypefnx {Method on @code{mglData}} @code{void} Diff (@code{const mglDataA &}x, @code{const mglDataA &}y)
+ at deftypefnx {Method on @code{mglData}} @code{void} Diff (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Diff (@code{const mglDataA &}x)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Diff (@code{const mglDataA &}x, @code{const mglDataA &}y)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Diff (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z)
+ at deftypefnx {C function} @code{void} mgl_data_diff_par (@code{HMDT} dat, @code{HCDT} x, @code{HCDT}y, @code{HCDT}z)
+ at deftypefnx {C function} @code{void} mgl_datac_diff_par (@code{HADT} dat, @code{HCDT} x, @code{HCDT}y, @code{HCDT}z)
+ at end ifclear
+Differentiates the data specified parametrically in direction @var{x} with @var{y}, @var{z}=constant. Parametrical differentiation uses the formula (for 2D case): @math{da/dx = (a_j*y_i-a_i*y_j)/(x_j*y_i-x_i*y_j)} where @math{a_i=da/di, a_j=da/dj} denotes usual differentiation along 1st and 2nd dimensions. The similar formula is used for 3D case. Note, that you may change the order of arguments -- for example, if you have 2D data a(i,j) which depend on coordinates @{x(i,j), y(i,j)@} then [...]
+ at end deftypefn
+
+ at anchor{diff2}
+ at deftypefn {MGL command} {} diff2 dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Diff2 (@code{const char *}dir)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Diff2 (@code{const char *}dir)
+ at deftypefnx {C function} @code{void} mgl_data_diff2 (@code{HMDT} dat, @code{const char *}dir)
+ at deftypefnx {C function} @code{void} mgl_datac_diff2 (@code{HADT} dat, @code{const char *}dir)
+ at end ifclear
+Double-differentiates (like Laplace operator) the data in given direction.
+ at end deftypefn
+
+ at anchor{sinfft}
+ at deftypefn {MGL command} {} sinfft dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} SinFFT (@code{const char *}dir)
+ at deftypefnx {C function} @code{void} mgl_data_sinfft (@code{HMDT} dat, @code{const char *}dir)
+ at end ifclear
+Do Sine transform of the data in given direction or directions. The Sine transform is @math{\sum a_j \sin(k j)} (see @uref{http://en.wikipedia.org/wiki/Discrete_sine_transform#DST-I}).
+ at end deftypefn
+
+ at anchor{cosfft}
+ at deftypefn {MGL command} {} cosfft dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} CosFFT (@code{const char *}dir)
+ at deftypefnx {C function} @code{void} mgl_data_cosfft (@code{HMDT} dat, @code{const char *}dir)
+ at end ifclear
+Do Cosine transform of the data in given direction or directions. The Cosine transform is @math{\sum a_j \cos(k j)} (see @uref{http://en.wikipedia.org/wiki/Discrete_cosine_transform#DCT-I}).
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Method on @code{mglDataC}} @code{void} FFT (@code{const char *}dir)
+ at deftypefnx {C function} @code{void} mgl_datac_fft (@code{HADT} dat, @code{const char *}dir)
+Do Fourier transform of the data in given direction or directions. If @var{dir} contain @samp{i} then inverse Fourier is used. The Fourier transform is @math{\sum a_j \exp(i k j)} (see @uref{http://en.wikipedia.org/wiki/Discrete_Fourier_transform}).
+ at end deftypefn
+ at end ifclear
+
+ at anchor{hankel}
+ at deftypefn {MGL command} {} hankel dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Hankel (@code{const char *}dir)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Hankel (@code{const char *}dir)
+ at deftypefnx {C function} @code{void} mgl_data_hankel (@code{HMDT} dat, @code{const char *}dir)
+ at deftypefnx {C function} @code{void} mgl_datac_hankel (@code{HADT} dat, @code{const char *}dir)
+ at end ifclear
+Do Hankel transform of the data in given direction or directions. The Hankel transform is @math{\sum a_j J_0(k j)} (see @uref{http://en.wikipedia.org/wiki/Hankel_transform}).
+ at end deftypefn
+
+ at anchor{wavelet}
+ at deftypefn {MGL command} {} wavelet dat 'dir' @code{k}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Wavelet (@code{const char *}dir, @code{int} k)
+ at deftypefnx {C function} @code{void} mgl_data_wavelet (@code{HMDT} dat, @code{const char *}dir, @code{int} k)
+ at end ifclear
+Apply wavelet transform of the data in given direction or directions. Parameter @var{dir} set the kind of wavelet transform:
+ at samp{d} for daubechies, @samp{D} for centered daubechies, @samp{h} for haar, @samp{H} for centered haar, @samp{b} for bspline, @samp{B} for centered bspline. If string @var{dir} contain symbol @samp{i} then inverse wavelet transform is applied. Parameter @var{k} set the size of wavelet transform.
+ at end deftypefn
+
+ at anchor{swap}
+ at deftypefn {MGL command} {} swap dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Swap (@code{const char *}dir)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Swap (@code{const char *}dir)
+ at deftypefnx {C function} @code{void} mgl_data_swap (@code{HMDT} dat, @code{const char *}dir)
+ at deftypefnx {C function} @code{void} mgl_datac_swap (@code{HADT} dat, @code{const char *}dir)
+ at end ifclear
+Swaps the left and right part of the data in given direction (useful for Fourier spectrum).
+ at end deftypefn
+
+ at anchor{roll}
+ at deftypefn {MGL command} {} roll dat 'dir' num
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Roll (@code{char} dir, @code{num})
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Roll (@code{char} dir, @code{num})
+ at deftypefnx {C function} @code{void} mgl_data_roll (@code{HMDT} dat, @code{char} dir, @code{num})
+ at deftypefnx {C function} @code{void} mgl_datac_roll (@code{HADT} dat, @code{char} dir, @code{num})
+ at end ifclear
+Rolls the data along direction @var{dir}. Resulting array will be out[i] = ini[(i+ at var{num})%nx] if @code{dir='x'}.
+ at end deftypefn
+
+ at anchor{mirror}
+ at deftypefn {MGL command} {} mirror dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Mirror (@code{const char *}dir)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Mirror (@code{const char *}dir)
+ at deftypefnx {C function} @code{void} mgl_data_mirror (@code{HMDT} dat, @code{const char *}dir)
+ at deftypefnx {C function} @code{void} mgl_datac_mirror (@code{HADT} dat, @code{const char *}dir)
+ at end ifclear
+Mirror the left-to-right part of the data in given direction. Looks like change the value index @var{i}->@var{n-i}. Note, that the similar effect in graphics you can reach by using options (@pxref{Command options}), for example, @code{surf dat; xrange 1 -1}.
+ at end deftypefn
+
+ at anchor{sew}
+ at deftypefn {MGL command} {} sew dat ['dir'='xyz' @code{da=2*pi}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Sew (@code{const char *}dir, @code{mreal} da=@code{2*M_PI})
+ at deftypefnx {C function} @code{void} mgl_data_sew (@code{HMDT} dat, @code{const char *}dir, @code{mreal} da)
+ at end ifclear
+Remove value steps (like phase jumps after inverse trigonometric functions) with period @var{da} in given direction.
+ at end deftypefn
+
+ at anchor{smooth}
+ at deftypefn {MGL command} {} smooth data ['dir'='xyz']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Smooth (@code{const char *}dir=@code{"xyz"}, @code{mreal} delta=@code{0})
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Smooth (@code{const char *}dir=@code{"xyz"}, @code{mreal} delta=@code{0})
+ at deftypefnx {C function} @code{void} mgl_data_smooth (@code{HMDT} dat, @code{const char *}dir, @code{mreal} delta)
+ at deftypefnx {C function} @code{void} mgl_datac_smooth (@code{HADT} dat, @code{const char *}dir, @code{mreal} delta)
+ at end ifclear
+Smooths the data on specified direction or directions. String @var{dirs} specifies the dimensions which will be smoothed. It may contain characters:
+ at itemize @bullet
+ at item
+ at samp{xyz} for smoothing along x-,y-,z-directions correspondingly,
+ at item
+ at samp{0} does nothing,
+ at item
+ at samp{3} for linear averaging over 3 points,
+ at item
+ at samp{5} for linear averaging over 5 points,
+ at item
+ at samp{d1}... at samp{d9} for linear averaging over (2*N+1)-th points.
+ at end itemize
+By default quadratic averaging over 5 points is used.
+ at end deftypefn
+
+ at anchor{envelop}
+ at deftypefn {MGL command} {} envelop dat ['dir'='x']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Envelop (@code{char} dir=@code{'x'})
+ at deftypefnx {C function} @code{void} mgl_data_envelop (@code{HMDT} dat, @code{char} dir)
+ at end ifclear
+Find envelop for data values along direction @var{dir}.
+ at end deftypefn
+
+ at anchor{diffract}
+ at deftypefn {MGL command} {} diffract dat 'how' @code{q}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Diffraction (@code{const char *}how, @code{mreal} q)
+ at deftypefnx {C function} @code{void} mgl_datac_diffr (@code{HADT} dat, @code{const char *}how, @code{mreal} q)
+ at end ifclear
+Calculates one step of diffraction by finite-difference method with parameter @var{q}=@math{\delta t/\delta x^2} using method with 3-d order of accuracy. Parameter @var{how} may contain:
+ at itemize @bullet
+ @item @samp{xyz} for calculations along x-,y-,z-directions correspondingly;
+ at item
+ @samp{r} for using axial symmetric Laplace operator for x-direction;
+ at item
+ @samp{0} for zero boundary conditions;
+ at item
+ @samp{1} for constant boundary conditions;
+ at item
+ @samp{2} for linear boundary conditions;
+ at item
+ @samp{3} for parabolic boundary conditions;
+ at item
+ @samp{4} for exponential boundary conditions;
+ at item
+ @samp{5} for gaussian boundary conditions.
+ at end itemize
+ at end deftypefn
+
+ at anchor{norm}
+ at deftypefn {MGL command} {} norm dat @code{v1 v2 [sym=off dim=0]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Norm (@code{mreal} v1=@code{0}, @code{mreal} v2=@code{1}, @code{bool} sym=@code{false}, @code{long} dim=@code{0})
+ at deftypefnx {C function} @code{void} mgl_data_norm (@code{HMDT} dat, @code{mreal} v1, @code{mreal} v2, @code{int} sym, @code{long} dim)
+ at end ifclear
+Normalizes the data to range [@var{v1}, at var{v2}]. If flag @var{sym}=@code{true} then symmetrical interval [-max(|v1|,|v2|), max(|v1|,|v2|)] is used. Modification will be applied only for slices >=@var{dim}.
+ at end deftypefn
+
+ at anchor{normsl}
+ at deftypefn {MGL command} {} normsl dat @code{v1 v2} ['dir'='z' @code{keep=on sym=off}]
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} NormSl (@code{mreal} v1=@code{0}, @code{mreal} v2=@code{1}, @code{char} dir=@code{'z'}, @code{bool} keep=@code{true}, @code{bool} sym=@code{false})
+ at deftypefnx {C function} @code{void} mgl_data_norm_slice (@code{HMDT} dat, @code{mreal} v1, @code{mreal} v2, @code{char} dir, @code{int} keep, @code{int} sym)
+ at end ifclear
+Normalizes data slice-by-slice along direction @var{dir} the data in slices to range [@var{v1}, at var{v2}]. If flag @var{sym}=@code{true} then symmetrical interval [-max(|v1|,|v2|), max(|v1|,|v2|)] is used. If @var{keep} is set then maximal value of k-th slice will be limited by
+ at iftex
+ at math{\sqrt{\sum a_{ij}(k)/\sum a_{ij}(0)}}.
+ at end iftex
+ at ifnottex
+ at math{\sqrt@{\sum a_ij(k)/\sum a_ij(0)@}}.
+ at end ifnottex
+ at end deftypefn
+
+ at anchor{limit}
+ at deftypefn {MGL command} {} limit dat @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Limit (@code{mreal} val)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} Limit (@code{mreal} val)
+ at deftypefnx {C function} @code{void} mgl_data_limit (@code{HMDT} dat, @code{mreal} val)
+ at deftypefnx {C function} @code{void} mgl_datac_limit (@code{HADT} dat, @code{mreal} val)
+ at end ifclear
+Limits the data values to be inside the range [- at var{val}, at var{val}], keeping the original sign of the value (phase for complex numbers). This is equivalent to operation @code{a[i] *= abs(a[i])<val?1.:val/abs(a[i]);}.
+ at end deftypefn
+
+ at anchor{dilate}
+ at deftypefn {MGL command} {} dilate dat @code{[val=1 step=1]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Dilate (@code{mreal} val=@code{1}, @code{long} step=@code{1})
+ at deftypefnx {C function} @code{void} mgl_data_dilate (@code{HMDT} dat, @code{mreal} val, @code{long} step)
+ at end ifclear
+Return dilated by @var{step} cells array of 0 or 1 for data values larger @var{val}. @c TODO @sref{Dilate and erode sample}
+ at end deftypefn
+
+ at anchor{erode}
+ at deftypefn {MGL command} {} erode dat @code{[val=1 step=1]}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} Erode (@code{mreal} val=@code{1}, @code{long} step=@code{1})
+ at deftypefnx {C function} @code{void} mgl_data_erode (@code{HMDT} dat, @code{mreal} val, @code{long} step)
+ at end ifclear
+Return eroded by @var{step} cells array of 0 or 1 for data values larger @var{val}. @c TODO @sref{Dilate and erode sample}
+ at end deftypefn
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Interpolation, Data information, Data changing, Data processing
+ at section Interpolation
+ at nav{}
+
+MGL scripts can use spline interpolation by @ref{evaluate} or @ref{refill} commands. Also you can use @ref{resize} for obtaining a data array with new sizes.
+
+ at ifclear UDAV
+
+However, there are much special faster functions in other modes (C/C++/Fortran/Python/...).
+
+ at cindex Spline
+ at deftypefn {Method on @code{mglData}} @code{mreal} Spline (@code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{dual} Spline (@code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+ at deftypefnx {C function} @code{mreal} mgl_data_spline (@code{HCDT} dat, @code{mreal} x, @code{mreal} y, @code{mreal} z)
+ at deftypefnx {C function} @code{dual} mgl_datac_spline (@code{HCDT} dat, @code{mreal} x, @code{mreal} y, @code{mreal} z)
+Interpolates data by cubic spline to the given point @var{x} in [0...nx-1], @var{y} in [0...ny-1], @var{z} in [0...nz-1].
+ at end deftypefn
+ at cindex Spline1
+ at deftypefn {Method on @code{mglData}} @code{mreal} Spline1 (@code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{dual} Spline1 (@code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+Interpolates data by cubic spline to the given point @var{x}, @var{y}, @var{z} which assumed to be normalized in range [0, 1].
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglData}} @code{mreal} Spline (@code{mglPoint} &dif, @code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+ at deftypefnx {C function} @code{mreal} mgl_data_spline_ext (@code{HCDT} dat, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{mreal *}dx, @code{mreal *}dy, @code{mreal *}dz)
+ at deftypefnx {C function} @code{dual} mgl_datac_spline_ext (@code{HCDT} dat, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{dual *}dx, @code{dual *}dy, @code{dual *}dz)
+Interpolates data by cubic spline to the given point @var{x} in [0...nx-1], @var{y} in [0...ny-1], @var{z} in [0...nz-1]. The values of derivatives at the point are saved in @var{dif}.
+ at end deftypefn
+ at cindex Spline1
+ at deftypefn {Method on @code{mglData}} @code{mreal} Spline1 (@code{mglPoint} &dif, @code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+Interpolates data by cubic spline to the given point @var{x}, @var{y}, @var{z} which assumed to be normalized in range [0, 1]. The values of derivatives at the point are saved in @var{dif}.
+ at end deftypefn
+
+ at cindex Linear
+ at deftypefn {Method on @code{mglData}} @code{mreal} Linear (@code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{dual} Linear (@code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+ at deftypefnx {C function} @code{mreal} mgl_data_linear (@code{HCDT} dat, @code{mreal} x, @code{mreal} y, @code{mreal} z)
+ at deftypefnx {C function} @code{dual} mgl_datac_linear (@code{HCDT} dat, @code{mreal} x, @code{mreal} y, @code{mreal} z)
+Interpolates data by linear function to the given point @var{x} in [0...nx-1], @var{y} in [0...ny-1], @var{z} in [0...nz-1].
+ at end deftypefn
+ at cindex Linear1
+ at deftypefn {Method on @code{mglData}} @code{mreal} Linear1 (@code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{dual} Linear1 (@code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+Interpolates data by linear function to the given point @var{x}, @var{y}, @var{z} which assumed to be normalized in range [0, 1].
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglData}} @code{mreal} Linear (@code{mglPoint} &dif, @code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{dual} Linear (@code{mglPoint} &dif, @code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+ at deftypefnx {C function} @code{mreal} mgl_data_linear_ext (@code{HCDT} dat, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{mreal *}dx, @code{mreal *}dy, @code{mreal *}dz)
+ at deftypefnx {C function} @code{dual} mgl_datac_linear_ext (@code{HCDT} dat, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{dual *}dx, @code{dual *}dy, @code{dual *}dz)
+Interpolates data by linear function to the given point @var{x} in [0...nx-1], @var{y} in [0...ny-1], @var{z} in [0...nz-1]. The values of derivatives at the point are saved in @var{dif}.
+ at end deftypefn
+ at cindex Linear1
+ at deftypefn {Method on @code{mglData}} @code{mreal} Linear1 (@code{mglPoint} &dif, @code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+ at deftypefnx {Method on @code{mglDataC}} @code{dual} Linear1 (@code{mglPoint} &dif, @code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+Interpolates data by linear function to the given point @var{x}, @var{y}, @var{z} which assumed to be normalized in range [0, 1]. The values of derivatives at the point are saved in @var{dif}.
+ at end deftypefn
+
+ at end ifclear
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Data information, Operators, Interpolation, Data processing
+ at section Data information
+ at nav{}
+
+There are a set of functions for obtaining data properties in MGL language. However most of them can be found using "suffixes". Suffix can get some numerical value of the data array (like its size, maximal or minimal value, the sum of elements and so on) as number. Later it can be used as usual number in command arguments. The suffixes start from point @samp{.} right after (without spaces) variable name or its sub-array. For example, @code{a.nx} give the x-size of data @var{a}, @code{b(1 [...]
+
+
+ at cindex PrintInfo
+ at anchor{info}
+ at deftypefn {MGL command} {} info dat
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglDataA}} @code{const char *} PrintInfo () @code{const}
+ at deftypefnx {Method on @code{mglDataA}} @code{void} PrintInfo (@code{FILE *}fp) @code{const}
+ at deftypefnx {C function only} @code{const char *} mgl_data_info (@code{HCDT} dat)
+ at deftypefnx {Fortran subroutine} @code{} mgl_data_info (@code{long} dat, @code{char *}out, @code{int} len)
+ at end ifclear
+Gets or prints to file @var{fp} or as message (in MGL) information about the data (sizes, maximum/minimum, momentums and so on).
+ at end deftypefn
+
+ at deftypefn {MGL command} {} info 'txt'
+Prints string @var{txt} as message.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} info val
+Prints value of number @var{val} as message.
+ at end deftypefn
+
+ at anchor{print}
+ at deftypefn {MGL command} {} print dat
+ at deftypefnx {MGL command} {} print 'txt'
+ at deftypefnx {MGL command} {} print val
+The same as @ref{info} but immediately print to stdout.
+ at end deftypefn
+
+ at anchor{echo}
+ at deftypefn {MGL command} {} echo dat
+Prints all values of the data array @var{dat} as message.
+ at end deftypefn
+
+
+ at cindex GetNx
+ at cindex GetNy
+ at cindex GetNz
+ at anchor{.nx} @anchor{.ny} @anchor{.nz}
+ at deftypefn {MGL suffix} {(dat)} .nx
+ at deftypefnx {MGL suffix} {(dat)} .ny
+ at deftypefnx {MGL suffix} {(dat)} .nz
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglDataA}} @code{long} GetNx ()
+ at deftypefnx {Method on @code{mglDataA}} @code{long} GetNy ()
+ at deftypefnx {Method on @code{mglDataA}} @code{long} GetNz ()
+ at deftypefnx {C function} @code{long} mgl_data_get_nx (@code{HCDT} dat)
+ at deftypefnx {C function} @code{long} mgl_data_get_ny (@code{HCDT} dat)
+ at deftypefnx {C function} @code{long} mgl_data_get_nz (@code{HCDT} dat)
+ at end ifclear
+Gets the x-, y-, z-size of the data.
+ at end deftypefn
+
+
+
+ at cindex Maximal
+ at anchor{.max}
+ at deftypefn {MGL suffix} {(dat)} .max
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglDataA}} @code{mreal} Maximal () @code{const}
+ at deftypefnx {C function} @code{mreal} mgl_data_max (@code{HCDT} dat)
+ at end ifclear
+Gets maximal value of the data.
+ at end deftypefn
+
+ at cindex Minimal
+ at anchor{.min}
+ at deftypefn {MGL suffix} {(dat)} .min
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglDataA}} @code{mreal} Minimal () @code{const}
+ at deftypefnx {C function} @code{mreal} mgl_data_min (@code{HMDT} dat) @code{const}
+ at end ifclear
+Gets minimal value of the data.
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Method on @code{mglDataA}} @code{mreal} Minimal (@code{int} &i, @code{int} &j, @code{int} &k) @code{const}
+ at deftypefnx {C function} @code{mreal} mgl_data_min_int (@code{HCDT} dat, @code{int} *i, @code{int} *j, @code{int} *k)
+Gets position of minimum to variables @var{i}, @var{j}, @var{k} and returns the minimal value.
+ at end deftypefn
+ at deftypefn {Method on @code{mglDataA}} @code{mreal} Maximal (@code{int} &i, @code{int} &j, @code{int} &k) @code{const}
+ at deftypefnx {C function} @code{mreal} mgl_data_max_int (@code{HCDT} dat, @code{int} *i, @code{int} *j, @code{int} *k)
+Gets position of maximum to variables @var{i}, @var{j}, @var{k} and returns the maximal value.
+ at end deftypefn
+ at deftypefn {Method on @code{mglDataA}} @code{mreal} Minimal (@code{mreal} &x, @code{mreal} &y, @code{mreal} &z) @code{const}
+ at deftypefnx {C function} @code{mreal} mgl_data_min_real (@code{HCDT} dat, @code{mreal} *x, @code{mreal} *y, @code{mreal} *z)
+Gets approximated (interpolated) position of minimum to variables @var{x}, @var{y}, @var{z} and returns the minimal value.
+ at end deftypefn
+ at end ifclear
+
+ at anchor{.mx} @anchor{.my} @anchor{.mz}
+ at deftypefn {MGL suffix} {(dat)} .mx
+ at deftypefnx {MGL suffix} {(dat)} .my
+ at deftypefnx {MGL suffix} {(dat)} .mz
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglDataA}} @code{mreal} Maximal (@code{mreal} &x, @code{mreal} &y, @code{mreal} &z) @code{const}
+ at deftypefnx {C function} @code{mreal} mgl_data_max_real (@code{HCDT} dat, @code{mreal} *x, @code{mreal} *y, @code{mreal} *z)
+ at end ifclear
+Gets approximated (interpolated) position of maximum to variables @var{x}, @var{y}, @var{z} and returns the maximal value.
+ at end deftypefn
+
+
+ at anchor{.mxf} @anchor{.myf} @anchor{.mzf}
+ at anchor{.mxl} @anchor{.myl} @anchor{.mzl}
+ at deftypefn {MGL suffix} {(dat)} .mxf
+ at deftypefnx {MGL suffix} {(dat)} .myf
+ at deftypefnx {MGL suffix} {(dat)} .mzf
+ at deftypefnx {MGL suffix} {(dat)} .mxl
+ at deftypefnx {MGL suffix} {(dat)} .myl
+ at deftypefnx {MGL suffix} {(dat)} .mzl
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglDataA}} @code{long} Maximal (@code{char} dir, @code{long} from) @code{const}
+ at deftypefnx {Method on @code{mglDataA}} @code{long} Maximal (@code{char} dir, @code{long} from, @code{long} &p1, @code{long} &p2) @code{const}
+ at deftypefnx {C function} @code{mreal} mgl_data_max_firstl (@code{HCDT} dat, @code{char} dir, @code{long} from, @code{long} *p1, @code{long} *p2)
+ at end ifclear
+Get first starting @var{from} give position (or last one if @var{from}<0) maximum along direction @var{dir}, and save its orthogonal coordinates in @var{p1}, @var{p2}.
+ at end deftypefn
+
+
+ at cindex Momentum
+ at anchor{.ax} @anchor{.ay} @anchor{.az} @anchor{.aa} @anchor{.sum}
+ at anchor{.wx} @anchor{.wy} @anchor{.wz} @anchor{.wa}
+ at anchor{.sx} @anchor{.sy} @anchor{.sz} @anchor{.sa}
+ at anchor{.kx} @anchor{.ky} @anchor{.kz} @anchor{.ka}
+ at deftypefn {MGL suffix} {(dat)} .sum
+ at deftypefnx {MGL suffix} {(dat)} .ax
+ at deftypefnx {MGL suffix} {(dat)} .ay
+ at deftypefnx {MGL suffix} {(dat)} .az
+ at deftypefnx {MGL suffix} {(dat)} .aa
+ at deftypefnx {MGL suffix} {(dat)} .wx
+ at deftypefnx {MGL suffix} {(dat)} .wy
+ at deftypefnx {MGL suffix} {(dat)} .wz
+ at deftypefnx {MGL suffix} {(dat)} .wa
+ at deftypefnx {MGL suffix} {(dat)} .sx
+ at deftypefnx {MGL suffix} {(dat)} .sy
+ at deftypefnx {MGL suffix} {(dat)} .sz
+ at deftypefnx {MGL suffix} {(dat)} .sa
+ at deftypefnx {MGL suffix} {(dat)} .kx
+ at deftypefnx {MGL suffix} {(dat)} .ky
+ at deftypefnx {MGL suffix} {(dat)} .kz
+ at deftypefnx {MGL suffix} {(dat)} .ka
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglDataA}} @code{mreal} Momentum (@code{char} dir, @code{mreal} &a, @code{mreal} &w) @code{const}
+ at deftypefnx {Method on @code{mglDataA}} @code{mreal} Momentum (@code{char} dir, @code{mreal} &m, @code{mreal} &w, @code{mreal} &s, @code{mreal} &k) @code{const}
+ at deftypefnx {C function} @code{mreal} mgl_data_momentum_val (@code{HCDT} dat, @code{char} dir, @code{mreal} *a, @code{mreal} *w, @code{mreal} *s, @code{mreal} *k)
+ at end ifclear
+Gets zero-momentum (energy, @math{I=\sum dat_i}) and write first momentum (median, @math{a = \sum \xi_i dat_i/I}), second momentum (width, @math{w^2 = \sum (\xi_i-a)^2 dat_i/I}), third momentum (skewness, @math{s = \sum (\xi_i-a)^3 dat_i/ I w^3}) and fourth momentum (kurtosis, @math{k = \sum (\xi_i-a)^4 dat_i / 3 I w^4}) to variables. Here @math{\xi} is corresponding coordinate if @var{dir} is @samp{'x'}, @samp{'y'} or @samp{'z'}. Otherwise median is @math{a = \sum dat_i/N}, width is @ma [...]
+ at end deftypefn
+
+ at anchor{.fst}
+ at deftypefn {MGL suffix} {(dat)} .fst
+ at ifclear UDAV
+ at cindex Find
+ at deftypefnx {Method on @code{mglDataA}} @code{mreal} Find (@code{const char *}cond, @code{int} &i, @code{int} &j, @code{int} &k) @code{const}
+ at deftypefnx {C function} @code{mreal} mgl_data_first (@code{HCDT} dat, @code{const char *}cond, @code{int} *i, @code{int} *j, @code{int} *k)
+ at end ifclear
+Find position (after specified in @var{i}, @var{j}, @var{k}) of first nonzero value of formula @var{cond}. Function return the data value at found position.
+ at end deftypefn
+
+ at anchor{.lst}
+ at deftypefn {MGL suffix} {(dat)} .lst
+ at ifclear UDAV
+ at cindex Last
+ at deftypefnx {Method on @code{mglDataA}} @code{mreal} Last (@code{const char *}cond, @code{int} &i, @code{int} &j, @code{int} &k) @code{const}
+ at deftypefnx {C function} @code{mreal} mgl_data_last (@code{HCDT} dat, @code{const char *}cond, @code{int} *i, @code{int} *j, @code{int} *k)
+ at end ifclear
+Find position (before specified in @var{i}, @var{j}, @var{k}) of last nonzero value of formula @var{cond}. Function return the data value at found position.
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Method on @code{mglDataA}} @code{int} Find (@code{const char *}cond, @code{char} dir, @code{int} i=@code{0}, @code{int} j=@code{0}, @code{int} k=@code{0}) @code{const}
+ at deftypefnx {C function} @code{mreal} mgl_data_find (@code{HCDT} dat, @code{const char *}cond, @code{int} i, @code{int} j, @code{int} k)
+Return position of first in direction @var{dir} nonzero value of formula @var{cond}. The search is started from point @{i,j,k@}.
+ at end deftypefn
+ at cindex FindAny
+ at deftypefn {Method on @code{mglDataA}} @code{bool} FindAny (@code{const char *}cond) @code{const}
+ at deftypefnx {C function} @code{mreal} mgl_data_find_any (@code{HCDT} dat, @code{const char *}cond)
+Determines if any nonzero value of formula in the data array.
+ at end deftypefn
+ at end ifclear
+
+ at anchor{.a}
+ at deftypefn {MGL suffix} {(dat)} .a
+Give first (for @code{.a}, i.e. @code{dat->a[0]}).
+ at end deftypefn
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Operators, Global functions, Data information, Data processing
+ at section Operators
+ at nav{}
+
+ at deftypefn {MGL command} {} copy @sc{dat} dat2 ['eq'='']
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} operator= (@code{const mglDataA &}d)
+ at end ifclear
+Copies data from other variable.
+ at end deftypefn
+
+ at deftypefn {MGL command} {} copy dat @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mreal}} @code{void} operator= (@code{mreal} val)
+ at end ifclear
+Set all data values equal to @var{val}.
+ at end deftypefn
+
+ at anchor{multo}
+ at deftypefn {MGL command} {} multo dat dat2
+ at deftypefnx {MGL command} {} multo dat @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} operator*= (@code{const mglDataA &}d)
+ at deftypefnx {Method on @code{mglData}} @code{void} operator*= (@code{mreal} d)
+ at deftypefnx {C function} @code{void} mgl_data_mul_dat (@code{HMDT} dat, @code{HCDT} d)
+ at deftypefnx {C function} @code{void} mgl_data_mul_num (@code{HMDT} dat, @code{mreal} d)
+ at end ifclear
+Multiplies data element by the other one or by value.
+ at end deftypefn
+
+ at anchor{divto}
+ at deftypefn {MGL command} {} divto dat dat2
+ at deftypefnx {MGL command} {} divto dat @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} operator/= (@code{const mglDataA &}d)
+ at deftypefnx {Method on @code{mglData}} @code{void} operator/= (@code{mreal} d)
+ at deftypefnx {C function} @code{void} mgl_data_div_dat (@code{HMDT} dat, @code{HCDT} d)
+ at deftypefnx {C function} @code{void} mgl_data_div_num (@code{HMDT} dat, @code{mreal} d)
+ at end ifclear
+Divides each data element by the other one or by value.
+ at end deftypefn
+
+ at anchor{addto}
+ at deftypefn {MGL command} {} addto dat dat2
+ at deftypefnx {MGL command} {} addto dat @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} operator+= (@code{const mglDataA &}d)
+ at deftypefnx {Method on @code{mglData}} @code{void} operator+= (@code{mreal} d)
+ at deftypefnx {C function} @code{void} mgl_data_add_dat (@code{HMDT} dat, @code{HCDT} d)
+ at deftypefnx {C function} @code{void} mgl_data_add_num (@code{HMDT} dat, @code{mreal} d)
+ at end ifclear
+Adds to each data element the other one or the value.
+ at end deftypefn
+
+ at anchor{subto}
+ at deftypefn {MGL command} {} subto dat dat2
+ at deftypefnx {MGL command} {} subto dat @code{val}
+ at ifclear UDAV
+ at deftypefnx {Method on @code{mglData}} @code{void} operator-= (@code{const mglDataA &}d)
+ at deftypefnx {Method on @code{mglData}} @code{void} operator-= (@code{mreal} d)
+ at deftypefnx {C function} @code{void} mgl_data_sub_dat (@code{HMDT} dat, @code{HCDT} d)
+ at deftypefnx {C function} @code{void} mgl_data_sub_num (@code{HMDT} dat, @code{mreal} d)
+ at end ifclear
+Subtracts from each data element the other one or the value.
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Library Function} mglData operator+ (@code{const mglDataA &}a, @code{const mglDataA &}b)
+ at deftypefnx {Library Function} mglData operator+ (@code{mreal} a, @code{const mglDataA &}b)
+ at deftypefnx {Library Function} mglData operator+ (@code{const mglDataA &}a, @code{mreal} b)
+Adds the other data or the number.
+ at end deftypefn
+
+ at deftypefn {Library Function} mglData operator- (@code{const mglDataA &}a, @code{const mglDataA &}b)
+ at deftypefnx {Library Function} mglData operator- (@code{mreal} a, @code{const mglDataA &}b)
+ at deftypefnx {Library Function} mglData operator- (@code{const mglDataA &}a, @code{mreal} b)
+Subtracts the other data or the number.
+ at end deftypefn
+
+ at deftypefn {Library Function} mglData operator* (@code{const mglDataA &}a, @code{const mglDataA &}b)
+ at deftypefnx {Library Function} mglData operator* (@code{mreal} a, @code{const mglDataA &}b)
+ at deftypefnx {Library Function} mglData operator* (@code{const mglDataA &}a, @code{mreal} b)
+Multiplies by the other data or the number.
+ at end deftypefn
+
+ at deftypefn {Library Function} mglData operator/ (@code{const mglDataA &}a, @code{const mglDataA &}b)
+ at deftypefnx {Library Function} mglData operator/ (@code{const mglDataA &}a, @code{mreal} b)
+Divides by the other data or the number.
+ at end deftypefn
+ at end ifclear
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Global functions, Evaluate expression, Operators, Data processing
+ at section Global functions
+ at nav{}
+
+ at ifclear UDAV
+These functions are not methods of @code{mglData} class. However it provide additional functionality to handle data. So I put it in this chapter.
+ at end ifclear
+
+ at anchor{transform}
+ at deftypefn {MGL command} {} transform @sc{dat} 'type' real imag
+ at ifclear UDAV
+ at deftypefnx {Global function} @code{mglData} mglTransform (@code{const mglDataA &}real, @code{const mglDataA &}imag, @code{const char *}type)
+ at deftypefnx {C function} @code{HMDT} mgl_transform (@code{HCDT} real, @code{HCDT} imag, @code{const char *}type)
+ at end ifclear
+Does integral transformation of complex data @var{real}, @var{imag} on specified direction. The order of transformations is specified in string @var{type}: first character for x-dimension, second one for y-dimension, third one for z-dimension. The possible character are: @samp{f} is forward Fourier transformation, @samp{i} is inverse Fourier transformation, @samp{s} is Sine transform, @samp{c} is Cosine transform, @samp{h} is Hankel transform, @samp{n} or @samp{ } is no transformation.
+ at end deftypefn
+
+ at anchor{transforma}
+ at deftypefn {MGL command} {} transforma @sc{dat} 'type' ampl phase
+ at ifclear UDAV
+ at deftypefnx {Global function} @code{mglData} mglTransformA @code{const mglDataA &}ampl, @code{const mglDataA &}phase, @code{const char *}type)
+ at deftypefnx {C function} @code{HMDT} mgl_transform_a @code{HCDT} ampl, @code{HCDT} phase, @code{const char *}type)
+ at end ifclear
+The same as previous but with specified amplitude @var{ampl} and phase @var{phase} of complex numbers.
+ at end deftypefn
+
+ at anchor{fourier}
+ at deftypefn {MGL command} {} fourier reDat imDat 'dir'
+ at deftypefnx {MGL command} {} fourier complexDat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Global function} @code{void} mglFourier @code{const mglDataA &}re, @code{const mglDataA &}im, @code{const char *}dir)
+ at deftypefnx {Method on @code{mglDataC}} @code{void} FFT (@code{const char *}dir)
+ at deftypefnx {C function} @code{void} mgl_data_fourier @code{HCDT} re, @code{HCDT} im, @code{const char *}dir)
+ at deftypefnx {C function} @code{void} mgl_datac_fft (@code{HADT} dat, @code{const char *}dir)
+ at end ifclear
+Does Fourier transform of complex data @var{re}+i*@var{im} in directions @var{dir}. Result is placed back into @var{re} and @var{im} data arrays. If @var{dir} contain @samp{i} then inverse Fourier is used.
+ at end deftypefn
+
+ at anchor{stfad}
+ at deftypefn {MGL command} {} stfad @sc{res} real imag @code{dn} ['dir'='x']
+ at ifclear UDAV
+ at deftypefnx {Global function} @code{mglData} mglSTFA (@code{const mglDataA &}real, @code{const mglDataA &}imag, @code{int} dn, @code{char} dir=@code{'x'})
+ at deftypefnx {C function} @code{HMDT} mgl_data_stfa (@code{HCDT} real, @code{HCDT} imag, @code{int} dn, @code{char} dir)
+ at end ifclear
+Short time Fourier transformation for real and imaginary parts. Output  is amplitude of partial Fourier of length @var{dn}. For example if @var{dir}=@samp{x}, result will have size @{int(nx/dn), dn, ny@} and it will contain @math{res[i,j,k]=|\sum_d^dn exp(I*j*d)*(real[i*dn+d,k]+I*imag[i*dn+d,k])|/dn}.
+ at end deftypefn
+
+ at anchor{tridmat}
+ at deftypefn {MGL command} {} tridmat @sc{res adat bdat cdat ddat} 'how'
+ at ifclear UDAV
+ at deftypefnx {Global function} @code{mglData} mglTridMat (@code{const mglDataA &}A, @code{const mglDataA &}B, @code{const mglDataA &}C, @code{const mglDataA &}D, @code{const char *}how)
+ at deftypefnx {Global function} @code{mglDataC} mglTridMatC (@code{const mglDataA &}A, @code{const mglDataA &}B, @code{const mglDataA &}C, @code{const mglDataA &}D, @code{const char *}how)
+ at deftypefnx {C function} @code{HMDT} mgl_data_tridmat (@code{HCDT} A, @code{HCDT} B, @code{HCDT} C, @code{HCDT} D, @code{const char*}how)
+ at deftypefnx {C function} @code{HADT} mgl_datac_tridmat (@code{HCDT} A, @code{HCDT} B, @code{HCDT} C, @code{HCDT} D, @code{const char*}how)
+ at end ifclear
+Get array as solution of tridiagonal system of equations @var{A}[i]*x[i-1]+ at var{B}[i]*x[i]+ at var{C}[i]*x[i+1]=@var{D}[i]. String @var{how} may contain:
+ at itemize @bullet
+ at item
+ at samp{xyz} for solving along x-,y-,z-directions correspondingly;
+ at item
+ at samp{h} for solving along hexagonal direction at x-y plain (require square matrix);
+ at item
+ at samp{c} for using periodical boundary conditions;
+ at item
+ at samp{d} for for diffraction/diffuse calculation (i.e. for using - at var{A}[i]*@var{D}[i-1]+(2- at var{B}[i])*@var{D}[i]- at var{C}[i]*@var{D}[i+1] at right part instead of @var{D}[i]).
+ at end itemize
+Data dimensions of arrays @var{A}, @var{B}, @var{C} should be equal. Also their dimensions need to be equal to all or to minor dimension(s) of array @var{D}. @sref{PDE solving hints}
+ at end deftypefn
+
+
+ at anchor{pde}
+ at deftypefn {MGL command} {} pde @sc{res} 'ham' ini_re ini_im [@code{dz=0.1 k0=100}]
+ at ifclear UDAV
+ at deftypefnx {Global function} @code{mglData} mglPDE (@code{HMGL} gr, @code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{mreal} dz=@code{0.1}, @code{mreal} k0=@code{100}, @code{const char *}opt=@code{""})
+ at deftypefnx {Global function} @code{mglDataC} mglPDEc (@code{HMGL} gr, @code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{mreal} dz=@code{0.1}, @code{mreal} k0=@code{100}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{HMDT} mgl_pde_solve (@code{HMGL} gr, @code{const char *}ham, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{mreal} dz, @code{mreal} k0, @code{const char *}opt)
+ at deftypefnx {C function} @code{HADT} mgl_pde_solve_c (@code{HMGL} gr, @code{const char *}ham, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{mreal} dz, @code{mreal} k0, @code{const char *}opt)
+ at end ifclear
+Solves equation du/dz = i*k0*@var{ham}(p,q,x,y,z,|u|)[u], where p=-i/k0*d/dx, q=-i/k0*d/dy are pseudo-differential operators. Parameters @var{ini_re}, @var{ini_im} specify real and imaginary part of initial field distribution. Parameters @var{Min}, @var{Max} set the bounding box for the solution. Note, that really this ranges are increased by factor 3/2 for purpose of reducing reflection from boundaries. Parameter @var{dz} set the step along evolutionary coordinate z. At this moment, sim [...]
+ at end deftypefn
+
+ at anchor{apde}
+ at deftypefn {MGL command} {} apde @sc{res} 'ham' ini_re ini_im [@code{dz=0.1 k0=100}]
+ at ifclear UDAV
+ at deftypefnx {Global function} @code{mglData} mglAPDE (@code{HMGL} gr, @code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{mreal} dz=@code{0.1}, @code{mreal} k0=@code{100}, @code{const char *}opt=@code{""})
+ at deftypefnx {Global function} @code{mglDataC} mglAPDEc (@code{HMGL} gr, @code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{mreal} dz=@code{0.1}, @code{mreal} k0=@code{100}, @code{const char *}opt=@code{""})
+ at deftypefnx {C function} @code{HMDT} mgl_pde_solve_adv (@code{HMGL} gr, @code{const char *}ham, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{mreal} dz, @code{mreal} k0, @code{const char *}opt)
+ at deftypefnx {C function} @code{HADT} mgl_pde_solve_adv_c (@code{HMGL} gr, @code{const char *}ham, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{mreal} dz, @code{mreal} k0, @code{const char *}opt)
+ at end ifclear
+Solves equation du/dz = i*k0*@var{ham}(p,q,x,y,z,|u|)[u], where p=-i/k0*d/dx, q=-i/k0*d/dy are pseudo-differential operators. Parameters @var{ini_re}, @var{ini_im} specify real and imaginary part of initial field distribution. Parameters @var{Min}, @var{Max} set the bounding box for the solution. Note, that really this ranges are increased by factor 3/2 for purpose of reducing reflection from boundaries. Parameter @var{dz} set the step along evolutionary coordinate z. The advanced and ra [...]
+ at end deftypefn
+
+
+ at anchor{ray}
+ at deftypefn {MGL command} {} ray @sc{res} 'ham' @code{x0 y0 z0 p0 q0 v0 [dt=0.1 tmax=10]}
+ at ifclear UDAV
+ at deftypefnx {Global function} @code{mglData} mglRay (@code{const char *}ham, @code{mglPoint} r0, @code{mglPoint} p0, @code{mreal} dt=@code{0.1}, @code{mreal} tmax=@code{10})
+ at deftypefnx {C function} @code{HMDT} mgl_ray_trace (@code{const char *}ham, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{mreal} px, @code{mreal} py, @code{mreal} pz, @code{mreal} dt, @code{mreal} tmax)
+ at end ifclear
+Solves GO ray equation like dr/dt = d @var{ham}/dp, dp/dt = -d @var{ham}/dr. This is Hamiltonian equations for particle trajectory in 3D case. Here @var{ham} is Hamiltonian which may depend on coordinates @samp{x}, @samp{y}, @samp{z}, momentums @samp{p}=px, @samp{q}=py, @samp{v}=pz and time @samp{t}: @math{ham = H(x,y,z,p,q,v,t)}. The starting point (at @code{t=0}) is defined by variables @var{r0}, @var{p0}. Parameters @var{dt} and @var{tmax} specify the integration step and maximal time [...]
+ at end deftypefn
+
+ at anchor{ode}
+ at deftypefn {MGL command} {} ode @sc{res} 'df' 'var' ini [@code{dt=0.1 tmax=10}]
+ at ifclear UDAV
+ at deftypefnx {Global function} @code{mglData} mglODE (@code{const char *}df, @code{const char *}var, @code{const mglDataA &}ini, @code{mreal} dt=@code{0.1}, @code{mreal} tmax=@code{10})
+ at deftypefnx {Global function} @code{mglDataC} mglODEc (@code{const char *}df, @code{const char *}var, @code{const mglDataA &}ini, @code{mreal} dt=@code{0.1}, @code{mreal} tmax=@code{10})
+ at deftypefnx {C function} @code{HMDT} mgl_ode_solve_str (@code{const char *}df, @code{const char *}var, @code{HCDT} ini, @code{mreal} dt, @code{mreal} tmax)
+ at deftypefnx {C function} @code{HADT} mgl_ode_solve_str_c (@code{const char *}df, @code{const char *}var, @code{HCDT} ini, @code{mreal} dt, @code{mreal} tmax)
+ at deftypefnx {C function} @code{HMDT} mgl_ode_solve (@code{void (*}df at code{)(const mreal *x, mreal *dx, void *par)}, @code{int} n, @code{const mreal *}ini, @code{mreal} dt, @code{mreal} tmax)
+ at deftypefnx {C function} @code{HMDT} mgl_ode_solve_ex (@code{void (*}df at code{)(const mreal *x, mreal *dx, void *par)}, @code{int} n, @code{const mreal *}ini, @code{mreal} dt, @code{mreal} tmax, @code{void (*}bord at code{)(mreal *x, const mreal *xprev, void *par)})
+ at end ifclear
+Solves ODE equations dx/dt = df(x). The functions @var{df} can be specified as string of ';'-separated textual formulas (argument @var{var} set the character ids of variables x[i]) or as callback function, which fill @code{dx} array for give @code{x}'s. Parameters @var{ini}, @var{dt}, @var{tmax} set initial values, time step and maximal time of the calculation. Result is data array with dimensions @{@var{n} * int(@var{tmax}/@var{dt}+1)@}.
+ at end deftypefn
+
+ at anchor{qo2d}
+ at deftypefn {MGL command} {} qo2d @sc{res} 'ham' ini_re ini_im ray [@code{r=1 k0=100} xx yy]
+ at ifclear UDAV
+ at deftypefnx {Global function} @code{mglData} mglQO2d (@code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{const mglDataA &}ray, @code{mreal} r=@code{1}, @code{mreal} k0=@code{100})
+ at deftypefnx {Global function} @code{mglData} mglQO2d (@code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{const mglDataA &}ray, @code{mglData &}xx, @code{mglData &}yy, @code{mreal} r=@code{1}, @code{mreal} k0=@code{100})
+ at deftypefnx {Global function} @code{mglDataC} mglQO2dc (@code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{const mglDataA &}ray, @code{mreal} r=@code{1}, @code{mreal} k0=@code{100})
+ at deftypefnx {Global function} @code{mglDataC} mglQO2dc (@code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{const mglDataA &}ray, @code{mglData &}xx, @code{mglData &}yy, @code{mreal} r=@code{1}, @code{mreal} k0=@code{100})
+ at deftypefnx {C function} @code{HMDT} mgl_qo2d_solve (@code{const char *}ham, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{HCDT} ray, @code{mreal} r, @code{mreal} k0, @code{HMDT} xx, @code{HMDT} yy)
+ at deftypefnx {C function} @code{HADT} mgl_qo2d_solve_c (@code{const char *}ham, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{HCDT} ray, @code{mreal} r, @code{mreal} k0, @code{HMDT} xx, @code{HMDT} yy)
+ at deftypefnx {C function} @code{HMDT} mgl_qo2d_func (@code{dual (*}ham at code{)(mreal u, mreal x, mreal y, mreal px, mreal py, void *par)}, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{HCDT} ray, @code{mreal} r, @code{mreal} k0, @code{HMDT} xx, @code{HMDT} yy)
+ at deftypefnx {C function} @code{HADT} mgl_qo2d_func_c (@code{dual (*}ham at code{)(mreal u, mreal x, mreal y, mreal px, mreal py, void *par)}, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{HCDT} ray, @code{mreal} r, @code{mreal} k0, @code{HMDT} xx, @code{HMDT} yy)
+ at end ifclear
+Solves equation du/dt = i*k0*@var{ham}(p,q,x,y,|u|)[u], where p=-i/k0*d/dx, q=-i/k0*d/dy are pseudo-differential operators (see @code{mglPDE()} for details). Parameters @var{ini_re}, @var{ini_im} specify real and imaginary part of initial field distribution. Parameters @var{ray} set the reference ray, i.e. the ray around which the accompanied coordinate system will be maked. You may use, for example, the array created by @ref{ray} function. Note, that the reference ray @strong{must be} s [...]
+ at end deftypefn
+
+
+ at anchor{qo3d}
+ at deftypefn {MGL command} {} qo3d @sc{res} 'ham' ini_re ini_im ray [@code{r=1 k0=100} xx yy zz]
+ at ifclear UDAV
+ at deftypefnx {Global function} @code{mglData} mglQO3d (@code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{const mglDataA &}ray, @code{mreal} r=@code{1}, @code{mreal} k0=@code{100})
+ at deftypefnx {Global function} @code{mglData} mglQO3d (@code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{const mglDataA &}ray, @code{mglData &}xx, @code{mglData &}yy, @code{mglData &}zz, @code{mreal} r=@code{1}, @code{mreal} k0=@code{100})
+ at deftypefnx {Global function} @code{mglDataC} mglQO3dc (@code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{const mglDataA &}ray, @code{mreal} r=@code{1}, @code{mreal} k0=@code{100})
+ at deftypefnx {Global function} @code{mglDataC} mglQO3dc (@code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{const mglDataA &}ray, @code{mglData &}xx, @code{mglData &}yy, @code{mglData &}zz, @code{mreal} r=@code{1}, @code{mreal} k0=@code{100})
+ at deftypefnx {C function} @code{HMDT} mgl_qo3d_solve (@code{const char *}ham, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{HCDT} ray, @code{mreal} r, @code{mreal} k0, @code{HMDT} xx, @code{HMDT} yy, @code{HMDT} zz)
+ at deftypefnx {C function} @code{HADT} mgl_qo3d_solve_c (@code{const char *}ham, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{HCDT} ray, @code{mreal} r, @code{mreal} k0, @code{HMDT} xx, @code{HMDT} yy, @code{HMDT} zz)
+ at deftypefnx {C function} @code{HMDT} mgl_qo3d_func (@code{dual (*}ham at code{)(mreal u, mreal x, mreal y, mreal z, mreal px, mreal py, mreal pz, void *par)}, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{HCDT} ray, @code{mreal} r, @code{mreal} k0, @code{HMDT} xx, @code{HMDT} yy, @code{HMDT} zz)
+ at deftypefnx {C function} @code{HADT} mgl_qo3d_func_c (@code{dual (*}ham at code{)(mreal u, mreal x, mreal y, mreal z, mreal px, mreal py, mreal pz, void *par)}, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{HCDT} ray, @code{mreal} r, @code{mreal} k0, @code{HMDT} xx, @code{HMDT} yy, @code{HMDT} zz)
+ at end ifclear
+Solves equation du/dt = i*k0*@var{ham}(p,q,v,x,y,z,|u|)[u], where p=-i/k0*d/dx, q=-i/k0*d/dy, v=-i/k0*d/dz are pseudo-differential operators (see @code{mglPDE()} for details). Parameters @var{ini_re}, @var{ini_im} specify real and imaginary part of initial field distribution. Parameters @var{ray} set the reference ray, i.e. the ray around which the accompanied coordinate system will be maked. You may use, for example, the array created by @ref{ray} function. Note, that the reference ray  [...]
+ at end deftypefn
+
+
+ at anchor{jacobian}
+ at deftypefn {MGL command} {} jacobian @sc{res} xdat ydat [zdat]
+ at ifclear UDAV
+ at deftypefnx {Global function} @code{mglData} mglJacobian (@code{const mglDataA &}x, @code{const mglDataA &}y)
+ at deftypefnx {Global function} @code{mglData} mglJacobian (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z)
+ at deftypefnx {C function} @code{HMDT} mgl_jacobian_2d (@code{HCDT} x, @code{HCDT} y)
+ at deftypefnx {C function} @code{HMDT} mgl_jacobian_3d (@code{HCDT} x, @code{HCDT} y, @code{HCDT} z)
+ at end ifclear
+Computes the Jacobian for transformation @{i,j,k@} to @{@var{x}, at var{y}, at var{z}@} where initial coordinates  @{i,j,k@} are data indexes normalized in range [0,1]. The Jacobian is determined by formula det||@math{dr_\alpha/d\xi_\beta}|| where @math{r}=@{@var{x}, at var{y}, at var{z}@} and @math{\xi}=@{i,j,k@}. All dimensions must be the same for all data arrays. Data must be 3D if all 3 arrays @{@var{x}, at var{y}, at var{z}@} are specified or 2D if only 2 arrays @{@var{x}, at var{y}@} are specified.
+ at end deftypefn
+
+ at anchor{triangulation}
+ at deftypefn {MGL command} {} triangulation @sc{res} xdat ydat
+ at c @deftypefn {MGL command} {} triangulation @sc{res} xdat ydat [zdat]
+ at ifclear UDAV
+ at deftypefnx {Global function} @code{mglData} mglTriangulation (@code{const mglDataA &}x, @code{const mglDataA &}y)
+ at c @deftypefnx {Global function} @code{mglData} mglTriangulation (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z)
+ at deftypefnx {C function} @code{HMDT} mgl_triangulation_2d (@code{HCDT} x, @code{HCDT} y)
+ at c @deftypefnx {C function} @code{HMDT} mgl_triangulation_3d (@code{HCDT} x, @code{HCDT} y, @code{HCDT} z)
+ at end ifclear
+Computes triangulation for arbitrary placed points with coordinates @{@var{x}, at var{y}@} (i.e. finds triangles which connect points). MathGL use @uref{http://www.s-hull.org/,s-hull} code for triangulation. The sizes of 1st dimension @strong{must be equal} for all arrays @code{x.nx=y.nx}. Resulting array can be used in @ref{triplot} or @ref{tricont} functions for visualization of reconstructed surface. @sref{Making regular data}
+ at end deftypefn
+
+ at ifclear UDAV
+
+ at deftypefn {Global function} @code{mglData} mglGSplineInit (@code{const mglDataA &}x, @code{const mglDataA &}y)
+ at deftypefnx {Global function} @code{mglDataC} mglGSplineCInit (@code{const mglDataA &}x, @code{const mglDataA &}y)
+ at deftypefnx {C function} @code{HMDT} mgl_gspline_init (@code{HCDT} x, @code{HCDT} y)
+ at deftypefnx {C function} @code{HADT} mgl_gsplinec_init (@code{HCDT} x, @code{HCDT} y)
+Prepare coefficients for global cubic spline interpolation.
+ at end deftypefn
+
+ at deftypefn {Global function} @code{mreal} mglGSpline (@code{const mglDataA &}coef, @code{mreal} dx, @code{mreal *}d1=@code{0}, @code{mreal *}d2=@code{0})
+ at deftypefnx {Global function} @code{dual} mglGSplineC (@code{const mglDataA &}coef, @code{mreal} dx, @code{dual *}d1=@code{0}, @code{dual *}d2=@code{0})
+ at deftypefnx {C function} @code{mreal} mgl_gspline (@code{HCDT} coef, @code{mreal} dx, @code{mreal *}d1, @code{mreal *}d2)
+ at deftypefnx {C function} @code{dual} mgl_gsplinec (@code{HCDT} coef, @code{mreal} dx, @code{dual *}d1, @code{dual *}d2)
+Evaluate global cubic spline (and its 1st and 2nd derivatives @var{d1}, @var{d2} if they are not @code{NULL}) using prepared coefficients @var{coef} at point @var{dx}+ at var{x0} (where @var{x0} is 1st element of data @var{x} provided to @code{mglGSpline*Init()} function).
+ at end deftypefn
+
+ at end ifclear
+
+
+ at anchor{ifs2d}
+ at deftypefn {MGL command} {} ifs2d @sc{res} dat @code{num} [@code{skip=20}]
+ at ifclear UDAV
+ at deftypefnx {Global function} @code{mglData} mglIFS2d (@code{const mglDataA &}dat, @code{long} num, @code{long} skip=@code{20})
+ at deftypefnx {C function} @code{HMDT} mgl_data_ifs_2d (@code{HCDT} dat, @code{long} num, @code{long} skip)
+ at end ifclear
+Computes @var{num} points @{x[i]=res[0,i], y[i]=res[1,i]@} for fractal using iterated function system. Matrix @var{dat} is used for generation according the formulas
+ at verbatim
+x[i+1] = dat[0,i]*x[i] + dat[1,i]*y[i] + dat[4,i];
+y[i+1] = dat[2,i]*x[i] + dat[3,i]*y[i] + dat[5,i];
+ at end verbatim
+Value @code{dat[6,i]} is used as weight factor for i-th row of matrix @var{dat}. At this first @var{skip} iterations will be omitted. Data array @var{dat} must have x-size greater or equal to 7. @sref{Fractal sample}
+ at end deftypefn
+
+ at anchor{ifs3d}
+ at deftypefn {MGL command} {} ifs3d @sc{res} dat @code{num} [@code{skip=20}]
+ at ifclear UDAV
+ at deftypefnx {Global function} @code{mglData} mglIFS3d (@code{const mglDataA &}dat, @code{long} num, @code{long} skip=@code{20})
+ at deftypefnx {C function} @code{HMDT} mgl_data_ifs_3d (@code{HCDT} dat, @code{long} num, @code{long} skip)
+ at end ifclear
+Computes @var{num} points @{x[i]=res[0,i], y[i]=res[1,i], z[i]=res[2,i]@} for fractal using iterated function system. Matrix @var{dat} is used for generation according the formulas
+ at verbatim
+x[i+1] = dat[0,i]*x[i] + dat[1,i]*y[i] + dat[2,i]*z[i] + dat[9,i];
+y[i+1] = dat[3,i]*x[i] + dat[4,i]*y[i] + dat[5,i]*z[i] + dat[10,i];
+z[i+1] = dat[6,i]*x[i] + dat[7,i]*y[i] + dat[8,i]*z[i] + dat[11,i];
+ at end verbatim
+Value @code{dat[12,i]} is used as weight factor for i-th row of matrix @var{dat}. At this first @var{skip} iterations will be omitted. Data array @var{dat} must have x-size greater or equal to 13. @sref{Fractal sample}
+ at end deftypefn
+
+ at anchor{ifsfile}
+ at deftypefn {MGL command} {} ifsfile @sc{res} 'fname' 'name' @code{num} [@code{skip=20}]
+ at ifclear UDAV
+ at deftypefnx {Global function} @code{mglData} mglIFSfile (@code{const char *}fname, @code{const char *}name, @code{long} num, @code{long} skip=@code{20})
+ at deftypefnx {C function} @code{HMDT} mgl_data_ifs_file (@code{const char *}fname, @code{const char *}name, @code{long} num, @code{long} skip)
+ at end ifclear
+Reads parameters of IFS fractal named @var{name} from file @var{fname} and computes @var{num} points for this fractal. At this first @var{skip} iterations will be omitted. See also @ref{ifs2d}, @ref{ifs3d}.
+
+IFS file may contain several records. Each record contain the name of fractal (@samp{binary} in the example below) and the body of fractal, which is enclosed in curly braces @{@}. Symbol @samp{;} start the comment. If the name of fractal contain @samp{(3D)} or @samp{(3d)} then the 3d IFS fractal is specified. The sample below contain two fractals: @samp{binary} -- usual 2d fractal, and @samp{3dfern (3D)} -- 3d fractal.
+
+ at verbatim
+ binary
+ { ; comment allowed here
+  ; and here
+  .5  .0 .0 .5 -2.563477 -0.000003 .333333   ; also comment allowed here
+  .5  .0 .0 .5  2.436544 -0.000003 .333333
+  .0 -.5 .5 .0  4.873085  7.563492 .333333
+  }
+
+ 3dfern (3D) {
+   .00  .00 0 .0 .18 .0 0  0.0 0.00 0 0.0 0 .01
+   .85  .00 0 .0 .85 .1 0 -0.1 0.85 0 1.6 0 .85
+   .20 -.20 0 .2 .20 .0 0  0.0 0.30 0 0.8 0 .07
+  -.20  .20 0 .2 .20 .0 0  0.0 0.30 0 0.8 0 .07
+  }
+ at end verbatim
+ at end deftypefn
+
+ at anchor{flame2d}
+ at deftypefn {MGL command} {} flame2d @sc{res} dat func @code{num} [@code{skip=20}]
+ at ifclear UDAV
+ at deftypefnx {Global function} @code{mglData} mglFlame2d (@code{const mglDataA &}dat, @code{const mglDataA &}func, @code{long} num, @code{long} skip=@code{20})
+ at deftypefnx {C function} @code{HMDT} mgl_data_flame_2d (@code{HCDT} dat, @code{HCDT} func, @code{long} num, @code{long} skip)
+ at end ifclear
+Computes @var{num} points @{x[i]=res[0,i], y[i]=res[1,i]@} for "flame" fractal using iterated function system. Array @var{func} define "flame" function identificator (@var{func}[0,i,j]), its weight (@var{func}[0,i,j]) and arguments (@var{func}[2 ... 5,i,j]). Matrix @var{dat} set linear transformation of coordinates before applying the function. The resulting coordinates are
+ at verbatim
+xx = dat[0,i]*x[j] + dat[1,j]*y[i] + dat[4,j];
+yy = dat[2,i]*x[j] + dat[3,j]*y[i] + dat[5,j];
+x[j+1] = sum_i @var{func}[1,i,j]*@var{func}[0,i,j]_x(xx, yy; @var{func}[2,i,j],..., at var{func}[5,i,j]);
+y[j+1] = sum_i @var{func}[1,i,j]*@var{func}[0,i,j]_y(xx, yy; @var{func}[2,i,j],..., at var{func}[5,i,j]);
+ at end verbatim
+The possible function ids are: @code{mglFlame2d_linear=0,	mglFlame2d_sinusoidal,	mglFlame2d_spherical,	mglFlame2d_swirl,		mglFlame2d_horseshoe,
+	mglFlame2d_polar,		mglFlame2d_handkerchief,mglFlame2d_heart,		mglFlame2d_disc,		mglFlame2d_spiral,
+	mglFlame2d_hyperbolic,	mglFlame2d_diamond,		mglFlame2d_ex,			mglFlame2d_julia,		mglFlame2d_bent,
+	mglFlame2d_waves,		mglFlame2d_fisheye,		mglFlame2d_popcorn,		mglFlame2d_exponential,	mglFlame2d_power,
+	mglFlame2d_cosine,		mglFlame2d_rings,		mglFlame2d_fan,			mglFlame2d_blob,		mglFlame2d_pdj,
+	mglFlame2d_fan2,		mglFlame2d_rings2,		mglFlame2d_eyefish,		mglFlame2d_bubble,		mglFlame2d_cylinder,
+	mglFlame2d_perspective,	mglFlame2d_noise,		mglFlame2d_juliaN,		mglFlame2d_juliaScope,	mglFlame2d_blur,
+	mglFlame2d_gaussian,	mglFlame2d_radialBlur,	mglFlame2d_pie,			mglFlame2d_ngon,		mglFlame2d_curl,
+	mglFlame2d_rectangles,	mglFlame2d_arch,		mglFlame2d_tangent,		mglFlame2d_square,		mglFlame2d_blade,
+	mglFlame2d_secant,		mglFlame2d_rays,		mglFlame2d_twintrian,	mglFlame2d_cross,		mglFlame2d_disc2,
+	mglFlame2d_supershape,	mglFlame2d_flower,		mglFlame2d_conic,		mglFlame2d_parabola,	mglFlame2d_bent2,
+	mglFlame2d_bipolar,		mglFlame2d_boarders,	mglFlame2d_butterfly,	mglFlame2d_cell,		mglFlame2d_cpow,
+	mglFlame2d_curve,		mglFlame2d_edisc,		mglFlame2d_elliptic,	mglFlame2d_escher,		mglFlame2d_foci,
+	mglFlame2d_lazySusan,	mglFlame2d_loonie,		mglFlame2d_preBlur,		mglFlame2d_modulus,		mglFlame2d_oscope,
+	mglFlame2d_polar2,		mglFlame2d_popcorn2,	mglFlame2d_scry,		mglFlame2d_separation,	mglFlame2d_split,
+	mglFlame2d_splits,		mglFlame2d_stripes,		mglFlame2d_wedge,		mglFlame2d_wedgeJulia,	mglFlame2d_wedgeSph,
+	mglFlame2d_whorl,		mglFlame2d_waves2,		mglFlame2d_exp,			mglFlame2d_log,			mglFlame2d_sin,
+	mglFlame2d_cos,			mglFlame2d_tan,			mglFlame2d_sec,			mglFlame2d_csc,			mglFlame2d_cot,
+	mglFlame2d_sinh,		mglFlame2d_cosh,		mglFlame2d_tanh,		mglFlame2d_sech,		mglFlame2d_csch,
+	mglFlame2d_coth,		mglFlame2d_auger,		mglFlame2d_flux.}
+Value @code{dat[6,i]} is used as weight factor for i-th row of matrix @var{dat}. At this first @var{skip} iterations will be omitted. Sizes of data arrays must be: @var{dat}.nx>=7, @var{func}.nx>=2 and @var{func}.nz=@var{dat}.ny.  @sref{Fractal sample}
+ at end deftypefn
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Evaluate expression, Special data classes, Global functions, Data processing
+ at section Evaluate expression
+ at nav{}
+
+ at ifset UDAV
+You can use arbitrary formulas of existed data arrays or constants as any argument of data processing or data plotting commands. There are only 2 limitations: formula shouldn't contain spaces (to be recognized as single argument), and formula cannot be used as argument which will be (re)created by MGL command.
+ at end ifset
+
+ at ifclear UDAV
+ at cindex mglExpr
+ at cindex mglExprC
+
+MathGL have a special classes @code{mglExpr} and @code{mglExprC} for evaluating of formula specified by the string for real and complex numbers correspondingly. These classes are defined in @code{#include <mgl2/data.h>} and @code{#include <mgl2/datac.h>} correspondingly. It is the fast variant of formula evaluation. At creation it will be recognized and compiled to tree-like internal code. At evaluation stage only fast calculations are performed. There is no difference between lower or u [...]
+
+ at deftypefn {Constructor on @code{mglExpr}} @code{} mglExpr (@code{const char *}expr)
+ at deftypefnx {Constructor on @code{mglExprC}} @code{} mglExprC (@code{const char *}expr)
+ at deftypefnx {C function} @code{HMEX} mgl_create_expr (@code{const char *}expr)
+ at deftypefnx {C function} @code{HAEX} mgl_create_cexpr (@code{const char *}expr)
+Parses the formula @var{expr} and creates formula-tree. Constructor recursively parses the formula and creates a tree-like structure containing functions and operators for fast further evaluating by @code{Calc()} or @code{CalcD()} functions.
+ at end deftypefn
+
+ at deftypefn {Destructor on @code{mglExpr}} @code{} ~mglExpr ()
+ at deftypefnx {Destructor on @code{mglExprC}} @code{} ~mglExprC ()
+ at deftypefnx {C function} @code{void} mgl_delete_expr (@code{HMEX} ex)
+ at deftypefnx {C function} @code{void} mgl_delete_cexpr (@code{HAEX} ex)
+Deletes the instance of class  mglExpr.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglExpr}} @code{mreal} Eval (@code{mreal} x, @code{mreal} y, @code{mreal} z)
+ at deftypefnx {Method on @code{mglExprC}} @code{dual} Eval (@code{dual} x, @code{dual} y, @code{dual} z)
+ at deftypefnx {C function} @code{mreal} mgl_expr_eval (@code{HMEX} ex, @code{mreal} x, @code{mreal} y, @code{mreal} z)
+ at deftypefnx {C function} @code{dual} mgl_cexpr_eval (@code{HAEX} ex, @code{dual} x, @code{dual} y, @code{dual} z)
+Evaluates the formula for @code{'x','r'}=@var{x}, @code{'y','n'}=@var{y}, @code{'z','t'}=@var{z}, @code{'a','u'}=@var{u}.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglExpr}} @code{mreal} Eval (@code{mreal} var[26])
+ at deftypefnx {Method on @code{mglExprC}} @code{dual} Eval (@code{dual} var[26])
+ at deftypefnx {C function} @code{mreal} mgl_expr_eval_v (@code{HMEX} ex, @code{mreal *}var)
+ at deftypefnx {C function} @code{dual} mgl_expr_eval_v (@code{HAEX} ex, @code{dual *}var)
+Evaluates the formula for variables in array @var{var}[0,...,'z'-'a'].
+ at end deftypefn
+
+
+ at deftypefn {Method on @code{mglExpr}} @code{mreal} Diff (@code{char} dir, @code{mreal} x, @code{mreal} y, @code{mreal} z)
+ at deftypefnx {C function} @code{mreal} mgl_expr_diff (@code{HMEX} ex, @code{char} dir, @code{mreal} x, @code{mreal} y, @code{mreal} z)
+Evaluates the formula derivation respect to @var{dir} for @code{'x','r'}=@var{x}, @code{'y','n'}=@var{y}, @code{'z','t'}=@var{z}, @code{'a','u'}=@var{u}.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglExpr}} @code{mreal} Diff (@code{char} dir, @code{mreal} var[26])
+ at deftypefnx {C function} @code{mreal} mgl_expr_diff_v (@code{HMEX} ex, @code{char} dir, @code{mreal *}var)
+Evaluates the formula derivation respect to @var{dir} for variables in array @var{var}[0,...,'z'-'a'].
+ at end deftypefn
+
+ at end ifclear
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Special data classes, , Evaluate expression, Data processing
+ at section Special data classes
+ at nav{}
+
+
+ at ifset UDAV
+MGL use these special classes automatically.
+ at end ifset
+
+ at ifclear UDAV
+This section describe special data classes @code{mglDataV}, @code{mglDataF}, @code{mglDataT} and @code{mglDataR} which sometime can noticeable speed up drawing or data handling. These classes are defined in @code{#include <mgl2/data.h>}. Note, that all plotting and data handling routines can be done using usual @code{mglData} or @code{mglDataC} classes. Also these special classes are usable in C++ code only.
+
+ at heading Class @code{mglDataV}
+represent variable with values equidistantly distributed in given range.
+ at deftypefn {Constructor on @code{mglDataV}} @code{} mglDataV (@code{const mglDataV &} d)
+Copy constructor.
+ at end deftypefn
+ at deftypefn {Constructor on @code{mglDataV}} @code{} mglDataV (@code{long} nx=@code{1}, @code{long} ny=@code{1}, @code{long} nz=@code{1}, @code{mreal} v1=@code{0}, @code{mreal} v2=@code{NaN}, @code{char} dir=@code{'x'})
+Create variable with "sizes" @var{nx}x at var{ny}x at var{nz} which changes from @var{v1} to @var{v2} (or is constant if @var{v2}=@code{NaN}) along @var{dir} direction.
+ at end deftypefn
+ at deftypefn {Method on @code{mglDataV}} @code{void} Create (@code{long} nx=@code{1}, @code{long} ny=@code{1}, @code{long} nz=@code{1})
+Set "sizes" @var{nx}x at var{ny}x at var{nz}.
+ at end deftypefn
+ at deftypefn {Method on @code{mglDataV}} @code{void} Fill (@code{mreal} x1, @code{mreal} x2=@code{NaN}, @code{char} dir=@code{'x'})
+Set ranges of the variable.
+ at end deftypefn
+ at deftypefn {Method on @code{mglDataV}} @code{void} Freq (@code{mreal} dp, @code{char} dir=@code{'x'})
+Set as frequency variable with increment @var{dp}.
+ at end deftypefn
+
+ at heading Class @code{mglDataF}
+represent function which values are evaluated (instead of access to data array as in @code{mglData}).
+ at deftypefn {Constructor on @code{mglDataF}} @code{} mglDataF (@code{const mglDataF &} d)
+Copy constructor.
+ at end deftypefn
+ at deftypefn {Constructor on @code{mglDataF}} @code{} mglDataF (@code{long} nx=@code{1}, @code{long} ny=@code{1}, @code{long} nz=@code{1})
+Create variable with "sizes" @var{nx}x at var{ny}x at var{nz} with zero function.
+ at end deftypefn
+ at deftypefn {Method on @code{mglDataF}} @code{void} Create (@code{long} nx=@code{1}, @code{long} ny=@code{1}, @code{long} nz=@code{1})
+Set "sizes" @var{nx}x at var{ny}x at var{nz}.
+ at end deftypefn
+ at deftypefn {Method on @code{mglDataF}} @code{void} SetRanges (@code{mglPoint} p1, @code{mglPoint} p2)
+Set ranges for internal x,y,z variables.
+ at end deftypefn
+ at deftypefn {Method on @code{mglDataF}} @code{void} SetFormula (@code{const char *}func)
+Set string which will be evaluated at function calls. Note this variant is about 10 times slower than @code{SetFunc}() one.
+ at end deftypefn
+ at deftypefn {Method on @code{mglDataF}} @code{void} SetFunc (@code{mreal (*}f at code{)(mreal x,mreal y,mreal z,void *p)}, @code{void *}p=@code{NULL})
+Set pointer to function which will be used for data.
+ at end deftypefn
+
+ at heading Class @code{mglDataT}
+represent named reference to column of another data array.
+ at deftypefn {Constructor on @code{mglDataT}} @code{} mglDataT (@code{const mglDataT &} d)
+Copy constructor.
+ at end deftypefn
+ at deftypefn {Constructor on @code{mglDataT}} @code{} mglDataT (@code{const mglDataA &} d, @code{long} col=@code{0})
+Create variable which reference @var{col}-th column of data @var{d}.
+ at end deftypefn
+ at deftypefn {Method on @code{mglDataT}} @code{void} SetInd (@code{long} col, @code{wchar_t} name)
+ at deftypefnx {Method on @code{mglDataT}} @code{void} SetInd (@code{long} col, @code{const wchar_t *} name)
+Set reference to another column of the same data and its name.
+ at end deftypefn
+
+ at heading Class @code{mglDataR}
+represent named reference to row of another data array.
+ at deftypefn {Constructor on @code{mglDataR}} @code{} mglDataR (@code{const mglDataR &} d)
+Copy constructor.
+ at end deftypefn
+ at deftypefn {Constructor on @code{mglDataR}} @code{} mglDataR (@code{const mglDataA &} d, @code{long} row=@code{0})
+Create variable which reference @var{row}-th row of data @var{d}.
+ at end deftypefn
+ at deftypefn {Method on @code{mglDataR}} @code{void} SetInd (@code{long} row, @code{wchar_t} name)
+ at deftypefnx {Method on @code{mglDataR}} @code{void} SetInd (@code{long} row, @code{const wchar_t *} name)
+Set reference to another row of the same data and its name.
+ at end deftypefn
+
+ at heading Class @code{mglDataW}
+represent FFT frequency as data array.
+ at deftypefn {Constructor on @code{mglDataW}} @code{} mglDataW (@code{const mglDataW &} d)
+Copy constructor.
+ at end deftypefn
+ at deftypefn {Constructor on @code{mglDataW}} @code{} mglDataW (@code{long} xx=@code{1}, @code{long} yy=@code{1}, @code{long} zz=@code{1}, @code{double} dp=@code{0}, @code{char} dir=@code{'x'})
+Set frequency sizes, direction @var{dir} and increment @var{dp}.
+ at end deftypefn
+ at deftypefn {Method on @code{mglDataR}} @code{void} Freq (@code{double} dp, @code{char} dir=@code{'x'})
+Equidistantly fill the data with step @var{dp} in direction @var{dir}.
+ at end deftypefn
+
+
+ at heading Class @code{mglDataS}
+incapsulate std::vector and present it as data array.
+ at deftypecv {Variable} mglDataS @code{std::vector<mreal>} dat
+Data array itself.
+ at end deftypecv
+ at deftypefn {Constructor on @code{mglDataS}} @code{} mglDataS (@code{const mglDataS &} d)
+Copy constructor.
+ at end deftypefn
+ at deftypefn {Constructor on @code{mglDataS}} @code{} mglDataS (@code{const std::vector<mreal> &} d)
+Create copy data from @var{d}.
+ at end deftypefn
+ at deftypefn {Constructor on @code{mglDataS}} @code{} mglDataS (@code{size_t} s)
+Allocate memory for @var{s} .
+ at end deftypefn
+ at deftypefn {Method on @code{mglDataS}} @code{void} reserve (@code{size_t} num)
+Reserve space for @var{num} elements.
+ at end deftypefn
+ at deftypefn {Method on @code{mglDataS}} @code{void} push_back (@code{double} v)
+Appends value @var{v} to the end of data.
+ at end deftypefn
+
+ at end ifclear
+
+ at external{}
diff --git a/texinfo/data_ru.texi b/texinfo/data_ru.texi
new file mode 100644
index 0000000..4cbad38
--- /dev/null
+++ b/texinfo/data_ru.texi
@@ -0,0 +1,2086 @@
+ at c ------------------------------------------------------------------
+ at chapter Обработка данных
+ at nav{}
+
+ at ifset UDAV
+В данной главе описываются команды для работы с массивами данных. Они включают команды для выделения памяти и изменения размера данных, чтения данных из файла, численного дифференцирования, интегрирования, интерполяции и пр., заполнения по текстовой формуле и т.д. Класс позволяет работать с данными размерности не более 3 (как функции от трёх переменных -- x,y,z). Массивы которые могут быть созданы командами MGL отображаются Small Caps шрифтом (например, @sc{dat}).
+ at end ifset
+
+ at ifclear UDAV
+В данной главе описываются классы @code{mglData} и @code{mglDataC} для работы с массивами действительных и комплексных данных, определённые в @code{#include <mgl2/data.h>} и @code{#include <mgl2/datac.h>} соответственно. Оба класса являются наследниками абстрактного класса @code{mglDataA}, и могут быть использованы в аргументах всех функций рисования (см. @ref{MathGL core}). Классы содержат функции для выделения памяти и изменения размера данных, чтения данных из файла, численного диффер [...]
+ at end ifclear
+
+ at menu
+* Public variables::
+* Data constructor::
+* Data resizing::
+* Data filling::
+* File I/O::
+* Make another data::
+* Data changing::
+* Interpolation::
+* Data information::
+* Operators::
+* Global functions::
+* Evaluate expression::
+* Special data classes::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Public variables, Data constructor, , Data processing
+ at section Переменные
+ at nav{}
+
+ at ifset UDAV
+MGL не поддерживает прямой доступ к элементам массива. См. раздел @ref{Data filling}
+ at end ifset
+
+ at ifclear UDAV
+ at deftypecv {Variable} mglData @code{mreal *} a
+ at deftypecvx {Variable} mglDataC @code{dual *} a
+Указатель на массив данных. Это одномерный массив. Например, матрица [nx x ny x nz] представляется одномерным массивом длиной nx*ny*nz, где элемент с индексами @{i, j, k@} находится как a[i+nx*j+nx*ny*k] (индексы отсчитываются от нуля).
+ at end deftypecv
+ at deftypecv {Variable} mglData @code{int} nx
+ at deftypecvx {Variable} mglDataC @code{long} nx
+Размер массива по 1-ой размерности ('x' размерности).
+ at end deftypecv
+ at deftypecv {Variable} mglData @code{int} ny
+ at deftypecvx {Variable} mglDataC @code{long} ny
+Размер массива по 2-ой размерности ('y' размерности).
+ at end deftypecv
+ at deftypecv {Variable} mglData @code{int} nz
+ at deftypecvx {Variable} mglDataC @code{long} nz
+Размер массива по 3-ей размерности ('z' размерности).
+ at end deftypecv
+ at deftypecv {Variable} mglData @code{std::string} id
+ at deftypecvx {Variable} mglDataC @code{std::string} id
+Имена колонки (или среза при nz>1) -- один символ на колонку.
+ at end deftypecv
+ at deftypecv {Variable} mglData @code{bool} link
+ at deftypecvx {Variable} mglDataC @code{bool} link
+Флаг использования указателя на внешние данные, включает запрет на удаление массива данных.
+ at end deftypecv
+
+ at deftypecv {Variable} mglDataA @code{std::wstring} s
+Имя массива данных, использующееся при разборе MGL скриптов.
+ at end deftypecv
+ at deftypecv {Variable} mglDataA @code{bool} temp
+Флаг временной переменной, которая может быть удалена в любой момент.
+ at end deftypecv
+ at deftypecv {Variable} mglDataA @code{void (*)(void *)} func
+Указатель на callback функцию, которая будет вызвана при удлалении данных.
+ at end deftypecv
+ at deftypecv {Variable} mglDataA @code{void *} o
+Указатель для callback функции.
+ at end deftypecv
+
+ at deftypefn {Метод класса @code{mglData}} @code{mreal} GetVal (@code{long} i)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{mreal} GetVal (@code{long} i)
+ at deftypefnx {Метод класса @code{mglData}} @code{void} SetVal (@code{mreal} val, @code{long} i)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} SetVal (@code{mreal} val, @code{long} i)
+Присваивает или возвращает значение используя "непрерывную" индексацию без проверки выхода за границы массива. Индекс @var{i} должен быть в диапазоне [0, nx*ny*nz-1].
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglDataA}} @code{long} GetNx ()
+ at deftypefnx {Метод класса @code{mglDataA}} @code{long} GetNy ()
+ at deftypefnx {Метод класса @code{mglDataA}} @code{long} GetNz ()
+ at deftypefnx {Функция С} @code{long} mgl_data_get_nx (@code{HCDT} dat)
+ at deftypefnx {Функция С} @code{long} mgl_data_get_ny (@code{HCDT} dat)
+ at deftypefnx {Функция С} @code{long} mgl_data_get_nz (@code{HCDT} dat)
+Возвращает размер данных в направлении x, y и z соответственно.
+ at end deftypefn
+
+ at deftypefn {Функция С} @code{mreal} mgl_data_get_value (@code{HCDT} dat, @code{int} i, @code{int} j, @code{int} k)
+ at deftypefnx {Функция С} @code{dual} mgl_datac_get_value (@code{HCDT} dat, @code{int} i, @code{int} j, @code{int} k)
+ at deftypefnx {Функция С} @code{mreal *} mgl_data_value (@code{HMDT} dat, @code{int} i, @code{int} j, @code{int} k)
+ at deftypefnx {Функция С} @code{dual *} mgl_datac_value (@code{HADT} dat, @code{int} i, @code{int} j, @code{int} k)
+ at deftypefnx {Функция С} @code{void} mgl_data_set_value (@code{HMDT} dat, @code{mreal} v, @code{int} i, @code{int} j, @code{int} k)
+ at deftypefnx {Функция С} @code{void} mgl_datac_set_value (@code{HADT} dat, @code{dual} v, @code{int} i, @code{int} j, @code{int} k)
+Присваивает или возвращает значение ячейки данных с проверкой выхода за пределы массива.
+ at end deftypefn
+ at deftypefn {Функция С} @code{const mreal *} mgl_data_data (@code{HCDT} dat)
+Возвращает указатель на внутренний массив данных.
+ at end deftypefn
+
+ at deftypefn {Функция С} @code{void} mgl_data_set_func (@code{mglDataA *}dat, @code{void (*}func at code{)(void *)}, @code{void *}par)
+Задает указатель на callback функцию, которая будет вызвана при удлалении данных.
+ at end deftypefn
+
+ at deftypefn {Функция С} @code{void} mgl_data_set_name (@code{mglDataA *}dat, @code{const char *}name)
+ at deftypefnx {Функция С} @code{void} mgl_data_set_name_w (@code{mglDataA *}dat, @code{const wchar_t *}name)
+Задает имя массива данных, использующееся при разборе MGL скриптов.
+ at end deftypefn
+
+ at end ifclear
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Data constructor, Data resizing, Public variables, Data processing
+ at section Создание и удаление данных
+ at nav{}
+ at cindex mglData
+
+ at ifset UDAV
+There are many functions, which can create data for output (see @ref{Data filling}, @ref{File I/O}, @ref{Make another data}, @ref{Global functions}). Here I put most useful of them.
+ at end ifset
+
+ at anchor{new}
+ at deftypefn {Команда MGL} {} new @sc{dat} [@code{nx=1} 'eq']
+ at deftypefnx {Команда MGL} {} new @sc{dat} @code{nx ny} ['eq']
+ at deftypefnx {Команда MGL} {} new @sc{dat} @code{nx ny nz} ['eq']
+ at ifclear UDAV
+ at deftypefnx {Конструктор класса @code{mglData}} {} mglData (@code{int} mx=@code{1}, @code{int} my=@code{1}, @code{int} mz=@code{1})
+ at deftypefnx {Конструктор класса @code{mglDataC}} {} mglDataC (@code{int} mx=@code{1}, @code{int} my=@code{1}, @code{int} mz=@code{1})
+ at deftypefnx {Функция С} @code{HMDT} mgl_create_data ()
+ at deftypefnx {Функция С} @code{HMDT} mgl_create_data_size (@code{int} mx, @code{int} my, @code{int} mz)
+ at end ifclear
+Выделяет память для массива данных и заполняет её нулями. Если указана формула @var{eq}, то данные заполняются также как при использовании @ref{fill}.
+ at end deftypefn
+
+ at anchor{copy}
+ at deftypefn {Команда MGL} {} copy @sc{dat} dat2 ['eq'='']
+ at deftypefnx {Команда MGL} {} copy @sc{dat} @code{val}
+ at ifclear UDAV
+ at deftypefnx {Конструктор класса @code{mglData}} {} mglData (@code{const mglData &}dat2)
+ at deftypefnx {Конструктор класса @code{mglData}} {} mglData (@code{const mglDataA *}dat2)
+ at deftypefnx {Конструктор класса @code{mglData}} {} mglData (@code{int} size, @code{const mreal *}dat2)
+ at deftypefnx {Конструктор класса @code{mglData}} {} mglData (@code{int} size, @code{int} cols, @code{const mreal *}dat2)
+ at deftypefnx {Конструктор класса @code{mglData}} {} mglData (@code{int} size, @code{const double *}dat2)
+ at deftypefnx {Конструктор класса @code{mglData}} {} mglData (@code{int} size, @code{int} cols, @code{const double *}dat2)
+ at deftypefnx {Конструктор класса @code{mglData}} {} mglData (@code{const double *}dat2, @code{int} size)
+ at deftypefnx {Конструктор класса @code{mglData}} {} mglData (@code{const double *}dat2, @code{int} size, @code{int} cols)
+ at deftypefnx {Конструктор класса @code{mglDataC}} {} mglDataC (@code{const mglDataA &}dat2)
+ at deftypefnx {Конструктор класса @code{mglDataC}} {} mglDataC (@code{const mglDataA *}dat2)
+ at deftypefnx {Конструктор класса @code{mglDataC}} {} mglDataC (@code{int} size, @code{const float *}dat2)
+ at deftypefnx {Конструктор класса @code{mglDataC}} {} mglDataC (@code{int} size, @code{int} cols, @code{const float *}dat2)
+ at deftypefnx {Конструктор класса @code{mglDataC}} {} mglDataC (@code{int} size, @code{const double *}dat2)
+ at deftypefnx {Конструктор класса @code{mglDataC}} {} mglDataC (@code{int} size, @code{int} cols, @code{const double *}dat2)
+ at deftypefnx {Конструктор класса @code{mglDataC}} {} mglDataC (@code{int} size, @code{const dual *}dat2)
+ at deftypefnx {Конструктор класса @code{mglDataC}} {} mglDataC (@code{int} size, @code{int} cols, @code{const dual *}dat2)
+ at end ifclear
+Копирует данные из другого экземпляра данных. Если указана формула @var{eq}, то данные заполняются также как при использовании @ref{fill}.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} copy @sc{redat} @sc{imdat} dat2
+Копирует действительную и мнимую часть данных из комплексного массива данных @var{dat2}.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} copy @sc{dat} 'name'
+Копирует данные из другого экземпляра данных с именем @var{name}. При этом имя @var{name} может быть некорректным с точки зрения MGL (например, взятым из HDF5 файла).
+ at end deftypefn
+
+
+
+ at deftypefn {Команда MGL} {} read @sc{dat} 'fname'
+ at ifclear UDAV
+ at deftypefnx {Конструктор класса @code{mglData}} {} mglData (@code{const char *}fname)
+ at deftypefnx {Конструктор класса @code{mglDataC}} {} mglDataC (@code{const char *}fname)
+ at deftypefnx {Функция С} @code{HMDT} mgl_create_data_file (@code{const char *}fname)
+ at deftypefnx {Функция С} @code{HADT} mgl_create_datac_file (@code{const char *}fname)
+ at end ifclear
+Читает данные из текстового файла с автоматическим определением размеров массива.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} delete dat
+ at deftypefnx {Команда MGL} {} delete 'name'
+ at ifclear UDAV
+ at deftypefnx {Destructor on @code{mglData}} {} ~mglData ()
+ at deftypefnx {Функция С} @code{void} mgl_delete_data (@code{HMDT} dat)
+ at deftypefnx {Destructor on @code{mglDataC}} {} ~mglDataC ()
+ at deftypefnx {Функция С} @code{void} mgl_delete_datac (@code{HADT} dat)
+ at end ifclear
+Удаляет массив данных из памяти.
+ at end deftypefn
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Data resizing, Data filling, Data constructor, Data processing
+ at section Изменение размеров данных
+ at nav{}
+ at cindex Create
+ at cindex Rearrange
+ at cindex Extend
+ at cindex Transpose
+ at cindex Squeeze
+ at cindex Crop
+ at cindex Insert
+ at cindex Delete
+ at cindex Sort
+ at cindex Clean
+ at cindex Join
+
+
+ at deftypefn {Команда MGL} {} new @sc{dat} [@code{nx=1 ny=1 nz=1}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Create (@code{int} mx, @code{int} my=@code{1}, @code{int} mz=@code{1})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Create (@code{int} mx, @code{int} my=@code{1}, @code{int} mz=@code{1})
+ at deftypefnx {Функция С} @code{void} mgl_data_create (@code{HMDT} dat, @code{int} mx, @code{int} my, @code{int} mz)
+ at deftypefnx {Функция С} @code{void} mgl_datac_create (@code{HADT} dat, @code{int} mx, @code{int} my, @code{int} mz)
+ at end ifclear
+Создает/пересоздает массив данных указанного размера и заполняет его нулями. Ничего не делает при @var{mx}, @var{my}, @var{mz} отрицательных или равных нулю.
+ at end deftypefn
+
+ at anchor{rearrange}
+ at deftypefn {Команда MGL} {} rearrange dat @code{mx [my=0 mz=0]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Rearrange (@code{int} mx, @code{int} my=@code{0}, @code{int} mz=@code{0})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Rearrange (@code{int} mx, @code{int} my=@code{0}, @code{int} mz=@code{0})
+ at deftypefnx {Функция С} @code{void} mgl_data_rearrange (@code{HMDT} dat, @code{int} mx, @code{int} my, @code{int} mz)
+ at deftypefnx {Функция С} @code{void} mgl_datac_rearrange (@code{HADT} dat, @code{int} mx, @code{int} my, @code{int} mz)
+ at end ifclear
+Изменяет размерность данных без изменения самого массива данных, так что результирующий массив @var{mx}*@var{my}*@var{mz} < nx*ny*nz. Если один из параметров @var{my} или @var{mz} ноль, то он будет выбран оптимальным образом. Например, если @var{my}=0, то будет @var{my}=nx*ny*nz/@var{mx} и @var{mz}=1.
+ at end deftypefn
+
+ at anchor{transpose}
+ at deftypefn {Команда MGL} {} transpose dat ['dim'='yxz']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Transpose (@code{const char *}dim=@code{"yx"})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Transpose (@code{const char *}dim=@code{"yx"})
+ at deftypefnx {Функция С} @code{void} mgl_data_transpose (@code{const char *}dim)
+ at deftypefnx {Функция С} @code{void} mgl_datac_transpose (@code{HADT} dat, @code{const char *}dim)
+ at end ifclear
+Транспонирует (меняет порядок размерностей) массив данных. Новый порядок размерностей задается строкой @var{dim}. Функция может быть полезна для транспонирования одномерных (или квазиодномерных) массивов после чтения их из файла.
+ at end deftypefn
+
+ at anchor{extend}
+ at deftypefn {Команда MGL} {} extend dat @code{n1 [n2=0]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Extend (@code{int} n1, @code{int} n2=@code{0})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Extend (@code{int} n1, @code{int} n2=@code{0})
+ at deftypefnx {Функция С} @code{void} mgl_data_extend (@code{HMDT} dat, @code{int} n1, @code{int} n2)
+ at deftypefnx {Функция С} @code{void} mgl_datac_extend (@code{HADT} dat, @code{int} n1, @code{int} n2)
+ at end ifclear
+Увеличивает размер данных путем вставки (|@var{n1}|+1) новых срезов после (для @var{n1}>0) или перед (для @var{n1}<0) существующими данными. Можно добавить сразу 2 размерности для 1d массива, используя второй параметр @var{n2}. Данные в новые срезы будут скопированы из существующих. Например, для @var{n1}>0 новый массив будет
+ at iftex
+ at math{a_{ij}^{new} = a_i^{old}} where j=0... at var{n1}. Соответственно, для @var{n1}<0 новый массив будет @math{a_{ij}^{new} = a_j^{old}}, где i=0...|@var{n1}|.
+ at end iftex
+ at ifnottex
+a_ij^new = a_i^old where j=0... at var{n1}. Соответственно, для @var{n1}<0 новый массив будет a_ij^new = a_j^old, где i=0...|@var{n1}|.
+ at end ifnottex
+ at end deftypefn
+
+ at anchor{squeeze}
+ at deftypefn {Команда MGL} {} squeeze dat @code{rx [ry=1 rz=1 sm=off]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Squeeze (@code{int} rx, @code{int} ry=@code{1}, @code{int} rz=@code{1}, @code{bool} smooth=@code{false})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Squeeze (@code{int} rx, @code{int} ry=@code{1}, @code{int} rz=@code{1}, @code{bool} smooth=@code{false})
+ at deftypefnx {Функция С} @code{void} mgl_data_squeeze (@code{HMDT} dat, @code{int} rx, @code{int} ry, @code{int} rz, @code{int} smooth)
+ at deftypefnx {Функция С} @code{void} mgl_datac_squeeze (@code{HADT} dat, @code{int} rx, @code{int} ry, @code{int} rz, @code{int} smooth)
+ at end ifclear
+Уменьшает размер данных путём удаления элементов с индексами не кратными @var{rx}, @var{ry}, @var{rz} соответственно. Параметр @var{smooth} задает использовать сглаживания
+ at iftex
+(т.е. @math{a_{out}[i]=\sum_{j=i,i+r}a[j]/r}) или нет (т.е. @math{a_{out}[i]=a[j*r]}).
+ at end iftex
+ at ifnottex
+(т.е. out[i]=\sum_@{j=i,i+r@} a[j]/r) или нет (т.е. out[i]=a[j*r]).
+ at end ifnottex
+ at end deftypefn
+
+ at anchor{crop}
+ at deftypefn {Команда MGL} {} crop dat @code{n1 n2} 'dir'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Crop (@code{int} n1, @code{int} n2, @code{char} dir=@code{'x'})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Crop (@code{int} n1, @code{int} n2, @code{char} dir=@code{'x'})
+ at deftypefnx {Функция С} @code{void} mgl_data_crop (@code{HMDT} dat, @code{int} n1, @code{int} n2, @code{char} dir)
+ at deftypefnx {Функция С} @code{void} mgl_datac_crop (@code{HADT} dat, @code{int} n1, @code{int} n2, @code{char} dir)
+ at end ifclear
+Обрезает границы данных при @var{i}<@var{n1} и @var{i}>@var{n2} (при @var{n2}>0) или @var{i}>@code{n[xyz]}- at var{n2} (при @var{n2}<=0) вдоль направления @var{dir}.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} crop dat 'how'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Crop (@code{const char *}how=@code{"235x"})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Crop (@code{const char *}how=@code{"235x"})
+ at deftypefnx {Функция Сn} @code{void} mgl_data_crop_opt (@code{HMDT} dat, @code{const char *}how)
+ at deftypefnx {Функция Сn} @code{void} mgl_datac_crop_opt (@code{HADT} dat, @code{const char *}how)
+ at end ifclear
+Обрезает дальний край данных, чтобы сделать их более оптимальным для быстрого преобразования Фурье. Размер массива будет равен наиболее близким к исходному из 2^n*3^m*5^l. Строка @var{how} может содержать: @samp{x}, @samp{y}, @samp{z} для направлений, и @samp{2}, @samp{3}, @samp{5} для использования соответствующего основания.
+ at end deftypefn
+
+ at anchor{insert}
+ at deftypefn {Команда MGL} {} insert dat 'dir' @code{[pos=off num=0]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Insert (@code{char} dir, @code{int} pos=@code{0}, @code{int} num=@code{1})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Insert (@code{char} dir, @code{int} pos=@code{0}, @code{int} num=@code{1})
+ at deftypefnx {Функция С} @code{void} mgl_data_insert (@code{HMDT} dat, @code{char} dir, @code{int} pos, @code{char} num)
+ at deftypefnx {Функция С} @code{void} mgl_datac_insert (@code{HADT} dat, @code{char} dir, @code{int} pos, @code{char} num)
+ at end ifclear
+Вставляет @var{num} срезов вдоль направления @var{dir} с позиции @var{pos} и заполняет их нулями.
+ at end deftypefn
+
+ at anchor{delete}
+ at deftypefn {Команда MGL} {} delete dat 'dir' @code{[pos=off num=0]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Delete (@code{char} dir, @code{int} pos=@code{0}, @code{int} num=@code{1})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Delete (@code{char} dir, @code{int} pos=@code{0}, @code{int} num=@code{1})
+ at deftypefnx {Функция С} @code{void} mgl_data_delete (@code{HMDT} dat, @code{char} dir, @code{int} pos, @code{char} num)
+ at deftypefnx {Функция С} @code{void} mgl_datac_delete (@code{HADT} dat, @code{char} dir, @code{int} pos, @code{char} num)
+ at end ifclear
+Удаляет @var{num} срезов вдоль направления @var{dir} с позиции @var{pos}.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} delete dat
+ at deftypefnx {Команда MGL} {} delete 'name'
+Удаляет массив данных из памяти.
+ at end deftypefn
+
+ at anchor{sort}
+ at deftypefn {Команда MGL} {} sort dat @code{idx [idy=-1]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Sort (@code{lond} idx, @code{long} idy=@code{-1})
+ at deftypefnx {Функция С} @code{void} mgl_data_sort (@code{HMDT} dat, @code{lond} idx, @code{long} idy)
+ at end ifclear
+Сортирует строки (или срезы в 3D случае) по значениям в указанной колонке @var{idx} (или ячейках @{@var{idx}, at var{idy}@} для 3D случая). Не используйте в многопоточных функциях!
+ at end deftypefn
+
+ at anchor{clean}
+ at deftypefn {Команда MGL} {} clean dat @code{idx}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Clean (@code{lond} idx)
+ at deftypefnx {Функция С} @code{void} mgl_data_clean (@code{HMDT} dat, @code{lond} idx)
+ at end ifclear
+Удаляет строки в которых значения для заданной колонки @var{idx} совпадают со значениями в следующей строке.
+ at end deftypefn
+
+
+ at anchor{join}
+ at deftypefn {Команда MGL} {} join dat vdat [v2dat ...]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Join (@code{const mglDataA &}vdat)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Join (@code{const mglDataA &}vdat)
+ at deftypefnx {Функция С} @code{void} mgl_data_join (@code{HMDT} dat, @code{HCDT} vdat)
+ at deftypefnx {Функция С} @code{void} mgl_datac_join (@code{HADT} dat, @code{HCDT} vdat)
+ at end ifclear
+Объединяет данные из массива @var{vdat} с данными массива @var{dat}. При этом, функция увеличивает размер массива @var{dat}: в z-направлении для массивов с одинаковыми размерами по x и y; в y-направлении для массивов с одинаковыми размерами по x; в x-направлении в остальных случаях.
+ at end deftypefn
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Data filling, File I/O, Data resizing, Data processing
+ at section Заполнение данных
+ at nav{}
+ at cindex Fill
+ at cindex Modify
+ at cindex Set
+ at cindex List
+ at cindex Var
+ at cindex Refill
+
+ at anchor{list}
+ at deftypefn {Команда MGL} {} list @sc{dat} @code{v1 ...}
+Создает новый массив данных @var{dat} и заполняет его числовыми значениями аргументов @code{v1 ...}. Команда может создавать одно- и двухмерные массивы с произвольными значениями. Для создания 2d массива следует использовать разделитель @samp{|}, который означает начало новой строки данных. Размер массива данных будет [maximal of row sizes * number of rows]. Например, команда @code{list 1 | 2 3} создаст массив [1 0; 2 3]. Замечу, что максимальное число аргументов равно 1000.
+ at end deftypefn
+ at deftypefn {Команда MGL} {} list @sc{dat} d1 ...
+Создает новый массив данных @var{dat} и заполняет его значениями из массивов @var{d1 ...}. Команда может создавать двух- и трёхмерные (если аргументы -- двумерные массивы) массивы. Меньшая размерность всех массивов в аргументах должна совпадать. В противном случае аргумент (массив) будет пропущен.
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Метод класса @code{mglData}} @code{void} Set (@code{const mreal *}A, @code{int} NX, @code{int} NY=@code{1}, @code{int} NZ=@code{1})
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Set (@code{const double *}A, @code{int} NX, @code{int} NY=@code{1}, @code{int} NZ=@code{1})
+ at deftypefnx {Функция С} @code{void} mgl_data_set_mreal (@code{HMDT} dat, @code{const mreal *}A, @code{int} NX, @code{int} NY, @code{int} NZ)
+ at deftypefnx {Функция С} @code{void} mgl_data_set_double (@code{HMDT} dat, @code{const double *}A, @code{int} NX, @code{int} NY, @code{int} NZ)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Set (@code{const float *}A, @code{int} NX, @code{int} NY=@code{1}, @code{int} NZ=@code{1})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Set (@code{const double *}A, @code{int} NX, @code{int} NY=@code{1}, @code{int} NZ=@code{1})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Set (@code{const dual *}A, @code{int} NX, @code{int} NY=@code{1}, @code{int} NZ=@code{1})
+ at deftypefnx {Функция С} @code{void} mgl_datac_set_float (@code{HADT} dat, @code{const mreal *}A, @code{int} NX, @code{int} NY, @code{int} NZ)
+ at deftypefnx {Функция С} @code{void} mgl_datac_set_double (@code{HADT} dat, @code{const double *}A, @code{int} NX, @code{int} NY, @code{int} NZ)
+ at deftypefnx {Функция С} @code{void} mgl_datac_set_complex (@code{HADT} dat, @code{const dual *}A, @code{int} NX, @code{int} NY, @code{int} NZ)
+Выделяет память и копирует данные из массивов типа @code{mreal*} или @code{double*}, т.е. из массивов определённых как @code{mreal a[NX*NY*NZ];}.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglData}} @code{void} Set (@code{const mreal **}A, @code{int} N1, @code{int} N2)
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Set (@code{const double **}A, @code{int} N1, @code{int} N2)
+ at deftypefnx {Функция С} @code{void} mgl_data_set_mreal2 (@code{HMDT} dat, @code{const mreal **}A, @code{int} N1, @code{int} N2)
+ at deftypefnx {Функция С} @code{void} mgl_data_set_double2 (@code{HMDT} dat, @code{const double **}A, @code{int} N1, @code{int} N2)
+Выделяет память и копирует данные из массивов типа @code{mreal**} или @code{double**} с размерностями @var{N1}, @var{N2}, т.е. из массивов определённых как @code{mreal a[N1][N2];}.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglData}} @code{void} Set (@code{const mreal ***}A, @code{int} N1, @code{int} N2)
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Set (@code{const double ***}A, @code{int} N1, @code{int} N2)
+ at deftypefnx {Функция С} @code{void} mgl_data_set_mreal3 (@code{HMDT} dat, @code{const mreal ***}A, @code{int} N1, @code{int} N2)
+ at deftypefnx {Функция С} @code{void} mgl_data_set_double3 (@code{HMDT} dat, @code{const double ***}A, @code{int} N1, @code{int} N2)
+Выделяет память и копирует данные из массивов типа @code{mreal***} или @code{double***} с размерностями @var{N1}, @var{N2}, @var{N3}, т.е. из массивов определённых как @code{mreal a[N1][N2][N3];}.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglData}} @code{void} Set (@code{gsl_vector *}v)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Set (@code{gsl_vector *}v)
+ at deftypefnx {Функция С} @code{void} mgl_data_set_vector (@code{HMDT} dat, @code{gsl_vector *}v)
+ at deftypefnx {Функция С} @code{void} mgl_datac_set_vector (@code{HADT} dat, @code{gsl_vector *}v)
+Выделяет память и копирует данные из структуры типа @code{gsl_vector *}.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglData}} @code{void} Set (@code{gsl_matrix *}m)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Set (@code{gsl_matrix *}m)
+ at deftypefnx {Функция С} @code{void} mgl_data_set_matrix (@code{HMDT} dat, @code{gsl_matrix *}m)
+ at deftypefnx {Функция С} @code{void} mgl_datac_set_matrix (@code{HADT} dat, @code{gsl_matrix *}m)
+Выделяет память и копирует данные из структуры типа @code{gsl_matrix *}.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglData}} @code{void} Set (@code{const mglDataA &}from)
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Set (@code{HCDT} from)
+ at deftypefnx {Функция С} @code{void} mgl_data_set (@code{HMDT} dat, @code{HCDT} from)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Set (@code{const mglDataA &}from)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Set (@code{HCDT} from)
+ at deftypefnx {Функция С} @code{void} mgl_datac_set (@code{HADT} dat, @code{HCDT} from)
+Выделяет память и копирует данные из другого экземпляра данных @var{from}.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglDataC}} @code{void} Set (@code{const mglDataA &}re, @code{const mglDataA &}im)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Set (@code{HCDT} re, @code{HCDT} im)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} SetAmpl (@code{HCDT} ampl, @code{const mglDataA &}phase)
+ at deftypefnx {Функция С} @code{void} mgl_datac_set_ri (@code{HADT} dat, @code{HCDT} re, @code{HCDT} im)
+ at deftypefnx {Функция С} @code{void} mgl_datac_set_ap (@code{HADT} dat, @code{HCDT} ampl, @code{HCDT} phase)
+Выделяет память и копирует данные из экземпляра данных для действительной @var{re} и мнимой @var{im} частей комплексного массива данных.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglData}} @code{void} Set (@code{const std::vector<int> &}d)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Set (@code{const std::vector<int> &}d)
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Set (@code{const std::vector<float> &}d)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Set (@code{const std::vector<float> &}d)
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Set (@code{const std::vector<double> &}d)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Set (@code{const std::vector<double> &}d)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Set (@code{const std::vector<dual> &}d)
+Выделяет память и копирует данные из массива типа @code{std::vector<T>}.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglData}} @code{void} Set (@code{const char *}str, @code{int} NX, @code{int} NY=@code{1}, @code{int} NZ=@code{1})
+ at deftypefnx {Функция С} @code{void} mgl_data_set_values (@code{const char *}str, @code{int} NX, @code{int} NY, @code{int} NZ)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Set (@code{const char *}str, @code{int} NX, @code{int} NY=@code{1}, @code{int} NZ=@code{1})
+ at deftypefnx {Функция С} @code{void} mgl_datac_set_values (@code{const char *}str, @code{int} NX, @code{int} NY, @code{int} NZ)
+Выделяет память и сканирует массив данных из строки.
+ at end deftypefn
+
+
+ at deftypefn {Метод класса @code{mglData}} @code{void} SetList (@code{long} n, ...)
+Allocate memory and set data from variable argument list of @emph{double} values. Note, you need to specify decimal point @samp{.} for integer values! For example, the code @code{SetList(2,0.,1.);} is correct, but the code @code{SetList(2,0,1);} is incorrect.
+ at end deftypefn
+
+
+ at deftypefn {Метод класса @code{mglData}} @code{void} Link (@code{mglData &}from)
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Link (@code{mreal *}A, @code{int} NX, @code{int} NY=@code{1}, @code{int} NZ=@code{1})
+ at deftypefnx {Функция С} @code{void} mgl_data_link (@code{HMDT} dat, @code{const mreal *}A, @code{int} NX, @code{int} NY, @code{int} NZ)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Link (@code{mglDataC &}from)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Link (@code{dual *}A, @code{int} NX, @code{int} NY=@code{1}, @code{int} NZ=@code{1})
+ at deftypefnx {Функция С} @code{void} mgl_datac_link (@code{HADT} dat, @code{const mreal *}A, @code{int} NX, @code{int} NY, @code{int} NZ)
+Устанавливает флаг использования внешнего массива данных, которые не будут удалены. Флаг может быть возвращён в исходное состояние и создан новый внутренний массив если использовались функции изменяющие размер данных.
+ at end deftypefn
+ at end ifclear
+
+ at anchor{var}
+ at deftypefn {Команда MGL} {} var @sc{dat} @code{num v1 [v2=nan]}
+Создает новый одномерный массив данных @var{dat} размером @var{num}, и заполняет его равномерно в диапазоне [@var{v1}, @var{v2}]. Если @var{v2}=@code{nan}, то используется @var{v2=v1}.
+ at end deftypefn
+
+ at anchor{fill}
+ at deftypefn {Команда MGL} {} fill dat v1 v2 ['dir'='x']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Fill (@code{mreal} v1, @code{mreal} v2, @code{char} dir=@code{'x'})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Fill (@code{dual} v1, @code{dual} v2, @code{char} dir=@code{'x'})
+ at deftypefnx {Функция С} @code{void} mgl_data_fill (@code{HMDT} dat, @code{mreal} v1, @code{mreal} v2, @code{char} dir)
+ at deftypefnx {Функция С} @code{void} mgl_datac_fill (@code{HADT} dat, @code{dual} v1, @code{dual} v2, @code{char} dir)
+ at end ifclear
+Заполняет значениями равно распределёнными в диапазоне [@var{x1}, @var{x2}] в направлении @var{dir}=@{@samp{x}, at samp{y}, at samp{z}@}.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} fill dat 'eq'[vdat wdat]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Fill (@code{HMGL} gr, @code{const char *}eq, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Fill (@code{HMGL} gr, @code{const char *}eq, @code{const mglDataA &}vdat, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Fill (@code{HMGL} gr, @code{const char *}eq, @code{const mglDataA &}vdat, @code{const mglDataA &}wdat, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Fill (@code{HMGL} gr, @code{const char *}eq, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Fill (@code{HMGL} gr, @code{const char *}eq, @code{const mglDataA &}vdat, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Fill (@code{HMGL} gr, @code{const char *}eq, @code{const mglDataA &}vdat, @code{const mglDataA &}wdat, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_data_fill_eq (@code{HMGL} gr, @code{HMDT} dat, @code{const char *}eq, @code{HCDT} vdat, @code{HCDT} wdat, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_datac_fill_eq (@code{HMGL} gr, @code{HADT} dat, @code{const char *}eq, @code{HCDT} vdat, @code{HCDT} wdat, @code{const char *}opt)
+ at end ifclear
+Заполняет значениями вычисленными по формуле @var{eq}. Формула представляет собой произвольное выражение, зависящее от переменных @samp{x}, @samp{y}, @samp{z}, @samp{u}, @samp{v}, @samp{w}. Координаты @samp{x}, @samp{y}, @samp{z} полагаются меняющимися в диапазоне @var{Min} x @var{Max} (в отличие от функции @code{Modify}). Переменная @samp{u} -- значения исходного массива, переменные @samp{v}, @samp{w} -- значения массивов @var{vdat}, @var{wdat}. Последние могут быть @code{NULL}, т.е. опущены.
+ at end deftypefn
+
+ at anchor{modify}
+ at deftypefn {Команда MGL} {} modify dat 'eq' [@code{dim=0}]
+ at deftypefnx {Команда MGL} {} modify dat 'eq' vdat [wdat]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Modify (@code{const char *}eq, @code{int} dim=@code{0})
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Modify (@code{const char *}eq, @code{const mglDataA &}v)
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Modify (@code{const char *}eq, @code{const mglDataA &}v, @code{const mglDataA &}w)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Modify (@code{const char *}eq, @code{int} dim=@code{0})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Modify (@code{const char *}eq, @code{const mglDataA &}v)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Modify (@code{const char *}eq, @code{const mglDataA &}v, @code{const mglDataA &}w)
+ at deftypefnx {Функция С} @code{void} mgl_data_modify (@code{HMDT} dat, @code{const char *}eq, @code{int} dim)
+ at deftypefnx {Функция С} @code{void} mgl_data_modify_vw (@code{HMDT} dat, @code{const char *}eq, @code{HCDT} v, @code{HCDT} w)
+ at deftypefnx {Функция С} @code{void} mgl_datac_modify (@code{HADT} dat, @code{const char *}eq, @code{int} dim)
+ at deftypefnx {Функция С} @code{void} mgl_datac_modify_vw (@code{HADT} dat, @code{const char *}eq, @code{HCDT} v, @code{HCDT} w)
+ at end ifclear
+Аналогично предыдущему с координатами @samp{x}, @samp{y}, @samp{z}, меняющимися в диапазоне [0,1]. Если указан @var{dim}>0, то изменяются только слои >=@var{dim}.
+ at end deftypefn
+
+ at anchor{fillsample}
+ at deftypefn {Команда MGL} {} fillsample dat 'how'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} FillSample (@code{const char *}how)
+ at deftypefnx {Функция С} @code{void} mgl_data_fill_sample (@code{HMDT} a, @code{const char *}how)
+ at end ifclear
+Заполняет массив данных 'x' или 'k' значениями для преобразований Ханкеля ('h') или Фурье ('f').
+ at end deftypefn
+
+
+ at anchor{datagrid}
+ at deftypefn {Команда MGL} {} datagrid dat xdat ydat zdat
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Grid (@code{HMGL} gr, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Grid (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{mglPoint} p1, @code{mglPoint} p2)
+ at deftypefnx {Функция С} @code{void} mgl_data_grid (@code{HMGL} gr, @code{HMDT} u, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{void} mgl_data_grid_xy (@code{HMDT} u, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2)
+ at end ifclear
+Заполняет значения массива результатом линейной интерполяции (считая координаты равнораспределенными в диапазоне осей координат или в диапазоне [x1,x2]*[y1,y2]) по триангулированной поверхности, найденной по произвольно расположенным точкам @samp{x}, @samp{y}, @samp{z}. NAN значение используется для точек сетки вне триангулированной поверхности. @sref{Making regular data}
+ at end deftypefn
+
+
+ at anchor{put}
+ at deftypefn {Команда MGL} {} put dat @code{val [i=all j=all k=all]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Put (@code{mreal} val, @code{int} i=@code{-1}, @code{int} j=@code{-1}, @code{int} k=@code{-1})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Put (@code{dual} val, @code{int} i=@code{-1}, @code{int} j=@code{-1}, @code{int} k=@code{-1})
+ at deftypefnx {Функция С} @code{void} mgl_data_put_val (@code{HMDT} a, @code{mreal} val, @code{int} i, @code{int} j, @code{int} k)
+ at deftypefnx {Функция С} @code{void} mgl_datac_put_val (@code{HADT} a, @code{dual} val, @code{int} i, @code{int} j, @code{int} k)
+ at end ifclear
+Присваивает значения (под-)массива @var{dat}[@var{i}, @var{j}, @var{k}] = @var{val}. Индексы @var{i}, @var{j}, @var{k} равные @samp{-1} задают значения @var{val} для всего диапазона соответствующего направления(ий). Например, @code{Put(val,-1,0,-1);} задает a[i,0,j]=@var{val} для i=0...(nx-1), j=0...(nz-1).
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} put dat vdat [@code{i=all j=all k=all}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Put (@code{const mglDataA &}v, @code{int} i=@code{-1}, @code{int} j=@code{-1}, @code{int} k=@code{-1})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Put (@code{const mglDataA &}v, @code{int} i=@code{-1}, @code{int} j=@code{-1}, @code{int} k=@code{-1})
+ at deftypefnx {Функция С} @code{void} mgl_data_put_dat (@code{HMDT} a, @code{HCDT} v, @code{int} i, @code{int} j, @code{int} k)
+ at deftypefnx {Функция С} @code{void} mgl_datac_put_dat (@code{HADT} a, @code{HCDT} v, @code{int} i, @code{int} j, @code{int} k)
+ at end ifclear
+Копирует значения из массива @var{v} в диапазон значений данного массива. Индексы @var{i}, @var{j}, @var{k} равные @samp{-1} задают диапазон изменения значений в соответствующих направление(ях). Младшие размерности массива @var{v} должны быть больше выбранного диапазона массива. Например, @code{Put(v,-1,0,-1);} присвоит a[i,0,j]=@var{v}.ny>nz ? @var{v}.a[i,j] : @var{v}.a[i], где i=0...(nx-1), j=0...(nz-1) и условие v.nx>=nx выполнено.
+ at end deftypefn
+
+ at anchor{refill}
+ at deftypefn {Команда MGL} {} refill dat xdat vdat [sl=-1]
+ at deftypefnx {Команда MGL} {} refill dat xdat ydat vdat [sl=-1]
+ at deftypefnx {Команда MGL} {} refill dat xdat ydat zdat vdat
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Refill (@code{const mglDataA &}x, @code{const mglDataA &}v, @code{mreal} x1, @code{mreal} x2, @code{long} sl=@code{-1})
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Refill (@code{const mglDataA &}x, @code{const mglDataA &}v, @code{mglPoint} p1, @code{mglPoint} p2, @code{long} sl=@code{-1})
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Refill (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}v, @code{mglPoint} p1, @code{mglPoint} p2, @code{long} sl=@code{-1})
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Refill (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}v, @code{mglPoint} p1, @code{mglPoint} p2)
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Refill (@code{HMGL} gr, @code{const mglDataA &}x, @code{const mglDataA &}v, @code{long} sl=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Refill (@code{HMGL} gr, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}v, @code{long} sl=@code{-1}, @code{const char *}opt=@code{""})
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Refill (@code{HMGL} gr, @code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z, @code{const mglDataA &}v, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{void} mgl_data_refill_x (@code{HMDT} a, @code{HCDT} x, @code{HCDT} v, @code{mreal} x1, @code{mreal} x2, @code{long} sl)
+ at deftypefnx {Функция С} @code{void} mgl_data_refill_xy (@code{HMDT} a, @code{HCDT} x, @code{HCDT} y, @code{HCDT} v, @code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2, @code{long} sl)
+ at deftypefnx {Функция С} @code{void} mgl_data_refill_xyz (@code{HMDT} a, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} v, @code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2, @code{mreal} z1, @code{mreal} z2)
+ at deftypefnx {Функция С} @code{void} mgl_data_refill_gr (@code{HMGL} gr, @code{HMDT} a, @code{HCDT} x, @code{HCDT} y, @code{HCDT} z, @code{HCDT} v, @code{long} sl, @code{const char *}opt)
+ at end ifclear
+Заполняет значениями интерполяции массива @var{v} в точках @{@var{x}, @var{y}, @var{z}@}=@{@code{X[i], Y[j], Z[k]}@} (или @{@var{x}, @var{y}, @var{z}@}=@{@code{X[i,j,k], Y[i,j,k], Z[i,j,k]}@} если @var{x}, @var{y}, @var{z} не 1d массивы), где @code{X,Y,Z} равномерно распределены в диапазоне [@var{x1}, at var{x2}]*[@var{y1}, at var{y2}]*[@var{z1}, at var{z2}] и имеют такой же размер как и заполняемый массив. Если параметр @var{sl} равен 0 или положительный, то изменятся будет только @var{sl}-ый срез.
+ at end deftypefn
+
+ at anchor{gspline}
+ at deftypefn {Команда MGL} {} gspline dat xdat vdat [sl=-1]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} RefillGS (@code{const mglDataA &}x, @code{const mglDataA &}v, @code{mreal} x1, @code{mreal} x2, @code{long} sl=@code{-1})
+ at deftypefnx {Функция С} @code{void} mgl_data_refill_gs (@code{HMDT} a, @code{HCDT} x, @code{HCDT} v, @code{mreal} x1, @code{mreal} x2, @code{long} sl)
+ at end ifclear
+Заполняет значениями глобального кубического сплайна для массива @var{v} в точках @var{x}=@code{X[i]}, где @code{X} равномерно распределен в диапазоне [@var{x1}, at var{x2}] и имеет такой же размер как и заполняемый массив. Если параметр @var{sl} равен 0 или положительный, то изменятся будет только @var{sl}-ый срез.
+ at end deftypefn
+
+ at anchor{idset}
+ at deftypefn {Команда MGL} {} idset dat 'ids'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} SetColumnId (@code{const char *}ids)
+ at deftypefnx {Функция С} @code{void} mgl_data_set_id (@code{const char *}ids)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} SetColumnId (@code{const char *}ids)
+ at deftypefnx {Функция С} @code{void} mgl_datac_set_id (@code{HADT} a, @code{const char *}ids)
+ at end ifclear
+Задает названия @var{ids} для колонок массива данных. Строка должна содержать один символ 'a'...'z' на колонку. Эти названия используются в функции @ref{column}.
+ at end deftypefn
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node File I/O, Make another data, Data filling, Data processing
+ at section Чтение/сохранение данных
+ at nav{}
+ at cindex Read
+ at cindex ReadMat
+ at cindex ReadRange
+ at cindex ReadAll
+ at cindex Save
+ at cindex ReadHDF
+ at cindex SaveHDF
+ at cindex Import
+ at cindex Export
+
+ at anchor{read}
+ at deftypefn {Команда MGL} {} read @sc{dat} 'fname'
+ at deftypefnx {Команда MGL} {} read @sc{redat} @sc{imdat} 'fname'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Read (@code{const char *}fname)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{bool} Read (@code{const char *}fname)
+ at deftypefnx {Функция С} @code{int} mgl_data_read (@code{HMDT} dat, @code{const char *}fname)
+ at deftypefnx {Функция С} @code{int} mgl_datac_read (@code{HADT} dat, @code{const char *}fname)
+ at end ifclear
+Читает данные из текстового файла с разделителями символом пробела/табуляции с автоматическим определением размера массива. Двойной перевод строки начинает новый срез данных (по направлению z).
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} read @sc{dat} 'fname' @code{mx [my=1 mz=1]}
+ at deftypefnx {Команда MGL} {} read @sc{redat} @sc{imdat} 'fname' @code{mx [my=1 mz=1]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Read (@code{const char *}fname, @code{int} mx, @code{int} my=@code{1}, @code{int} mz=@code{1})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{bool} Read (@code{const char *}fname, @code{int} mx, @code{int} my=@code{1}, @code{int} mz=@code{1})
+ at deftypefnx {Функция С} @code{int} mgl_data_read_dim (@code{HMDT} dat, @code{const char *}fname, @code{int} mx, @code{int} my, @code{int} mz)
+ at deftypefnx {Функция С} @code{int} mgl_datac_read_dim (@code{HADT} dat, @code{const char *}fname, @code{int} mx, @code{int} my, @code{int} mz)
+ at end ifclear
+Читает данные из текстового файла с заданными размерами. Ничего не делается если параметры @var{mx}, @var{my} или @var{mz} равны нулю или отрицательны.
+ at end deftypefn
+
+ at anchor{readmat}
+ at deftypefn {Команда MGL} {} readmat @sc{dat} 'fname' [@code{dim=2}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} ReadMat (@code{const char *}fname, @code{int} dim=@code{2})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{bool} ReadMat (@code{const char *}fname, @code{int} dim=@code{2})
+ at deftypefnx {Функция С} @code{int} mgl_data_read_mat (@code{HMDT} dat, @code{const char *}fname, @code{int} dim)
+ at deftypefnx {Функция С} @code{int} mgl_datac_read_mat (@code{HADT} dat, @code{const char *}fname, @code{int} dim)
+ at end ifclear
+Читает данные из текстового файла с размерами, указанными в первых @var{dim} числах файла. При этом переменная @var{dim} задает размерность (1d, 2d, 3d) данных.
+ at end deftypefn
+
+ at anchor{readall}
+ at deftypefn {Команда MGL} {} readall @sc{dat} 'templ' @code{v1 v2 [dv=1 slice=off]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} ReadRange (@code{const char *}templ, @code{mreal} from, @code{mreal} to, @code{mreal} step=@code{1.f}, @code{bool} as_slice=@code{false})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} ReadRange (@code{const char *}templ, @code{mreal} from, @code{mreal} to, @code{mreal} step=@code{1}, @code{bool} as_slice=@code{false})
+ at deftypefnx {Функция С} @code{int} mgl_data_read_range (@code{HMDT} dat, @code{const char *}templ, @code{mreal} from, @code{mreal} to, @code{mreal} step, @code{int} as_slice)
+ at deftypefnx {Функция С} @code{int} mgl_datac_read_range (@code{HADT} dat, @code{const char *}templ, @code{mreal} from, @code{mreal} to, @code{mreal} step, @code{int} as_slice)
+ at end ifclear
+Объединяет данные из нескольких текстовых файлов. Имена файлов определяются вызовом функции @code{sprintf(fname,templ,val);}, где @var{val} меняется от @var{from} до @var{to} с шагом @var{step}. Данные загружаются один за другим в один и тот же срез данных (при @var{as_slice}=@code{false}) или срез-за-срезом (при @var{as_slice}=@code{true}).
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} readall @sc{dat} 'templ' @code{[slice=off]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} ReadAll (@code{const char *}templ, @code{bool} as_slice=@code{false})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} ReadAll (@code{const char *}templ, @code{bool} as_slice=@code{false})
+ at deftypefnx {Функция С} @code{int} mgl_data_read_all (@code{HMDT} dat, @code{const char *}templ, @code{int} as_slice)
+ at deftypefnx {Функция С} @code{int} mgl_datac_read_all (@code{HADT} dat, @code{const char *}templ, @code{int} as_slice)
+ at end ifclear
+Объединяет данные из нескольких текстовых файлов, чьи имена удовлетворяют шаблону @var{templ} (например, @var{templ}=@code{"t_*.dat"}). Данные загружаются один за другим в один и тот же срез данных (при @var{as_slice}=@code{false}) или срез-за-срезом (при @var{as_slice}=@code{true}).
+ at end deftypefn
+
+ at anchor{scanfile}
+ at deftypefn {Команда MGL} {} scanfile @sc{dat} 'fname' 'templ'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{bool} ScanFile (@code{const char *}fname, @code{const char *}templ)
+ at deftypefnx {Функция С} @code{int} mgl_data_scan_file (@code{HMDT} dat, @code{const char *}fname, @code{const char *}templ)
+ at end ifclear
+Читает файл @var{fname} построчно и каждую строку сканирует на соответствие шаблону @var{templ}. Полученные числа (обозначаются как @samp{%g} в шаблоне) сохраняются. @sref{Saving and scanning file}
+ at end deftypefn
+
+ at anchor{save}
+ at deftypefn {Команда MGL} {} save dat 'fname'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglDataA}} @code{void} Save (@code{const char *}fname, @code{int} ns=@code{-1}) @code{const}
+ at deftypefnx {Функция С} @code{void} mgl_data_save (@code{HCDT} dat, @code{const char *}fname, @code{int} ns)
+ at deftypefnx {Функция С} @code{void} mgl_datac_save (@code{HCDT} dat, @code{const char *}fname, @code{int} ns)
+ at end ifclear
+Сохраняет весь массив данных при @var{ns}=@code{-1} или только @var{ns}-ый срез в текстовый файл.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} save 'str' 'fname' ['mode'='a']
+Сохраняет строку @var{str} в файл @var{fname}. Для параметра @var{mode}=@samp{a} происходит добавление строки (по умолчанию): для  @var{mode}=@samp{w} файл будет перезаписан. @sref{Saving and scanning file}
+ at end deftypefn
+
+ at anchor{readhdf}
+ at deftypefn {Команда MGL} {} readhdf @sc{dat} 'fname' 'dname'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} ReadHDF (@code{const char *}fname, @code{const char *}dname)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} ReadHDF (@code{const char *}fname, @code{const char *}dname)
+ at deftypefnx {Функция С} @code{void} mgl_data_read_hdf (@code{HMDT} dat, @code{const char *}fname, @code{const char *}dname)
+ at deftypefnx {Функция С} @code{void} mgl_datac_read_hdf (@code{HADT} dat, @code{const char *}fname, @code{const char *}dname)
+ at end ifclear
+Читает массив с именем @var{dname} из HDF5 или HDF4 файла @var{fname}. Функция ничего не делает если библиотека была собрана без поддержки HDF5|HDF4.
+ at end deftypefn
+
+ at anchor{savehdf}
+ at deftypefn {Команда MGL} {} savehdf dat 'fname' 'dname' [@code{rewrite}=@code{off}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglDataA}} @code{void} SaveHDF (@code{const char *}fname, @code{const char *}dname, @code{bool} rewrite=@code{false}) @code{const}
+ at deftypefnx {Функция С} @code{void} mgl_data_save_hdf (@code{HCDT} dat, @code{const char *}fname, @code{const char *}dname, @code{int} rewrite)
+ at deftypefnx {Функция С} @code{void} mgl_datac_save_hdf (@code{HCDT} dat, @code{const char *}fname, @code{const char *}dname, @code{int} rewrite)
+ at end ifclear
+Сохраняет массив под именем @var{dname} в HDF5 или HDF4 файл @var{fname}. Функция ничего не делает если библиотека была собрана без поддержки HDF5|HDF4.
+ at end deftypefn
+
+ at anchor{datas}
+ at deftypefn {Команда MGL} {} datas 'fname'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglDataA}} @code{int} DatasHDF (@code{const char *}fname, @code{char *}buf, @code{long} size) @code{static}
+ at deftypefnx {Функция С} @code{void} mgl_datas_hdf (@code{const char *}fname, @code{char *}buf, @code{long} size)
+ at end ifclear
+Помещает имена массивов данных в HDF5 файле @var{fname} в строку @var{buf} разделёнными символом табуляции '\t'. В версии MGL имена массивов будут выведены как сообщение. Функция ничего не делает если библиотека была собрана без поддержки HDF5.
+ at end deftypefn
+
+ at anchor{openhdf}
+ at deftypefn {Команда MGL} {} openhdf 'fname'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglParse}} @code{void} OpenHDF (@code{const char *}fname)
+ at deftypefnx {Функция С} @code{void} mgl_parser_openhdf (@code{HMPR} pr, @code{const char *}fname)
+ at end ifclear
+Читает все массивы данных из HDF5 файла @var{fname} и создает переменные MGL с соответствующими именами. Если имя данных начинается с @samp{!}, то будут созданы комплексные массивы.
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Функция С} @code{const char * const *} mgl_datas_hdf_str (@code{HMPR} pr, @code{const char *}fname)
+Помещает имена данных из HDF файла @var{fname} в массив строк (последняя строка ""). Массив строк будет изменен при следующем вызове функции.
+ at end deftypefn
+ at end ifclear
+
+ at anchor{import}
+ at deftypefn {Команда MGL} {} import @sc{dat} 'fname' 'sch' [@code{v1=0 v2=1}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Import (@code{const char *}fname, @code{const char *}scheme, @code{mreal} v1=@code{0}, mreal v2=@code{1})
+ at deftypefnx {Функция С} @code{void} mgl_data_import (@code{HMDT} dat, @code{const char *}fname, @code{const char *}scheme, @code{mreal} v1, mreal v2)
+ at end ifclear
+Читает данные из растрового файла. RGB значения пикселов преобразуются в число в диапазоне [@var{v1}, @var{v2}] используя цветовую схему @var{sch} (@pxref{Color scheme}).
+ at end deftypefn
+
+ at anchor{export}
+ at deftypefn {Команда MGL} {} export dat 'fname' 'sch' [@code{v1=0 v2=0}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglDataA}} @code{void} Export (@code{const char *}fname, @code{const char *}scheme, @code{mreal} v1=@code{0}, mreal v2=@code{0}, @code{int} ns=@code{-1}) const
+ at deftypefnx {Функция С} @code{void} mgl_data_export (@code{HMDT} dat, @code{const char *}fname, @code{const char *}scheme, @code{mreal} v1, mreal v2, @code{int} ns) const
+ at end ifclear
+Сохраняет данные в растровый файл. Числовые значения, нормированные в диапазон [@var{v1}, @var{v2}], преобразуются в RGB значения пикселов, используя цветовую схему @var{sch} (@pxref{Color scheme}). Если @var{v1}>=@var{v2}, то значения @var{v1}, @var{v2} определяются автоматически как минимальное и максимальное значение данных.
+ at end deftypefn
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Make another data, Data changing, File I/O, Data processing
+ at section Make another data
+ at nav{}
+ at cindex SubData
+ at cindex Column
+ at cindex Trace
+ at cindex Hist
+ at cindex Resize
+ at cindex Evaluate
+ at cindex Combine
+ at cindex Momentum
+ at cindex Sum
+ at cindex Min
+ at cindex Max
+ at cindex Roots
+ at cindex Correl
+ at cindex AutoCorrel
+
+ at anchor{subdata}
+ at deftypefn {Команда MGL} {} subdata @sc{res} dat @code{xx [yy=all zz=all]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} SubData (@code{mreal} xx, @code{mreal} yy=@code{-1}, @code{mreal} zz=@code{-1}) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{mglData} SubData (@code{mreal} xx, @code{mreal} yy=@code{-1}, @code{mreal} zz=@code{-1}) @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_subdata (@code{HCDT} dat, @code{mreal} xx, @code{mreal} yy, @code{mreal} zz)
+ at end ifclear
+Возвращает в @var{res} подмассив массива данных @var{dat} с фиксированными значениями индексов с положительными значениями. Например, @code{SubData(-1,2)} выделяет третью строку (индексы начинаются с нуля), @code{SubData(4,-1)} выделяет 5-ую колонку, @code{SubData(-1,-1,3)} выделяет 4-ый срез и т.д. В MGL скриптах обычно используется упрощенная версия @code{dat(xx,yy,zz)}. Функция возвращает NULL или пустой массив если данные не могут быть созданы при данных значениях аргументов.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} subdata @sc{res} dat xdat [ydat zdat]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} SubData (@code{const mglDataA &}xx, @code{const mglDataA &}yy, @code{const mglDataA &}zz) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{mglData} SubData (@code{const mglDataA &}xx, @code{const mglDataA &}yy, @code{const mglDataA &}zz) @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_subdata_ext (@code{HCDT} dat, @code{HCDT} xx, @code{HCDT} yy, @code{HCDT} zz)
+ at end ifclear
+Возвращает в @var{res} подмассив массива данных @var{dat} с индексами, заданными в массивах @var{xx}, @var{yy}, @var{zz} (косвенная адресация). Результат будет иметь размерность массивов с индексами. Размеры массивов @var{xx}, @var{yy}, @var{zz} с индексами должна быть одинакова, либо должны быть "скаляром" (т.е. 1*1*1). В MGL скриптах обычно используется упрощенная версия @code{dat(xx,yy,zz)}. Функция возвращает NULL или пустой массив если данные не могут быть созданы при данных значени [...]
+ at end deftypefn
+
+ at anchor{column}
+ at deftypefn {Команда MGL} {} column @sc{res} dat 'eq'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Column (@code{const char *}eq) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{mglData} Column (@code{const char *}eq) @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_column (@code{HCDT} dat, @code{const char *}eq)
+ at end ifclear
+Возвращает массив данных заполненный по формуле @var{eq}, вычисленной для именованных колонок (или срезов). Например, @code{Column("n*w^2/exp(t)");}. Имена колонок должны быть предварительно заданы функцией @ref{idset} или при чтении файлов данных. В MGL скриптах обычно используется упрощенная версия @code{dat('eq')}. Функция возвращает NULL или пустой массив если данные не могут быть созданы при данных значениях аргументов.
+ at end deftypefn
+
+ at anchor{resize}
+ at deftypefn {Команда MGL} {} resize @sc{res} dat @code{mx [my=1 mz=1]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Resize (@code{int} mx, @code{int} my=@code{0}, @code{int} mz=@code{0}, @code{mreal} x1=@code{0}, @code{mreal} x2=@code{1}, @code{mreal} y1=@code{0}, @code{mreal} y2=@code{1}, @code{mreal} z1=@code{0}, @code{mreal} z2=@code{1}) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{mglData} Resize (@code{int} mx, @code{int} my=@code{0}, @code{int} mz=@code{0}, @code{mreal} x1=@code{0}, @code{mreal} x2=@code{1}, @code{mreal} y1=@code{0}, @code{mreal} y2=@code{1}, @code{mreal} z1=@code{0}, @code{mreal} z2=@code{1}) @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_resize (@code{HCDT} dat, @code{int} mx, @code{int} my, @code{int} mz)
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_resize_box (@code{HCDT} dat, @code{int} mx, @code{int} my, @code{int} mz, @code{mreal} x1, @code{mreal} x2, @code{mreal} y1, @code{mreal} y2, @code{mreal} z1, @code{mreal} z2)
+ at end ifclear
+Возвращает массив данных размером @var{mx}, @var{my}, @var{mz} со значениями полученными интерполяцией значений из части [@var{x1}, at var{x2}] x [@var{y1}, at var{y2}] x [@var{z1}, at var{z2}] исходного массива. Величины x,y,z полагаются нормированными в диапазоне [0,1]. Если значение @var{mx}, @var{my} или @var{mz} равно 0, то исходный размер используется.  Функция возвращает NULL или пустой массив если данные не могут быть созданы при данных значениях аргументов.
+ at end deftypefn
+
+ at anchor{evaluate}
+ at deftypefn {Команда MGL} {} evaluate @sc{res} dat idat [@code{norm=on}]
+ at deftypefnx {Команда MGL} {} evaluate @sc{res} dat idat jdat [@code{norm=on}]
+ at deftypefnx {Команда MGL} {} evaluate @sc{res} dat idat jdat kdat [@code{norm=on}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Evaluate (@code{const mglDataA &}idat, @code{bool} norm=@code{true}) @code{const}
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Evaluate (@code{const mglDataA &}idat, @code{const mglDataA &}jdat, @code{bool} norm=@code{true}) @code{const}
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Evaluate (@code{const mglDataA &}idat, @code{const mglDataA &}jdat, @code{const mglDataA &}kdat, @code{bool} norm=@code{true}) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{mglData} Evaluate (@code{const mglDataA &}idat, @code{bool} norm=@code{true}) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{mglData} Evaluate (@code{const mglDataA &}idat, @code{const mglDataA &}jdat, @code{bool} norm=@code{true}) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{mglData} Evaluate (@code{const mglDataA &}idat, @code{const mglDataA &}jdat, @code{const mglDataA &}kdat, @code{bool} norm=@code{true}) @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_evaluate (@code{HCDT} dat, @code{HCDT} idat, @code{HCDT} jdat, @code{HCDT} kdat, @code{int} norm)
+ at end ifclear
+Возвращает массив данных, полученный в результате интерполяции исходного массива в точках других массивов (например, res[i,j]=dat[idat[i,j],jdat[i,j]]). Размеры массивов @var{idat}, @var{jdat}, @var{kdat} должны совпадать. Координаты в @var{idat}, @var{jdat}, @var{kdat} полагаются нормированными в диапазон [0,1] (при @var{norm}=@code{true}) или в диапазоны [0,nx], [0,ny], [0,nz] соответственно. Функция возвращает NULL или пустой массив если данные не могут быть созданы при данных значени [...]
+ at end deftypefn
+
+ at anchor{section}
+ at deftypefn {Команда MGL} {} section @sc{res} dat ids ['dir'='y' @code{val=nan}]
+ at deftypefnx {Команда MGL} {} section @sc{res} dat @code{id} ['dir'='y' @code{val=nan}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Section (@code{const mglDataA &}ids, @code{const char *}dir=@code{'y'}, @code{mreal} val=@code{NAN}) @code{const}
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Section (@code{long} id, @code{const char *}dir=@code{'y'}, @code{mreal} val=@code{NAN}) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{mglData} Section (@code{const mglDataA &}ids, @code{const char *}dir=@code{'y'}, @code{mreal} val=@code{NAN}) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{mglData} Section (@code{long} id, @code{const char *}dir=@code{'y'}, @code{mreal} val=@code{NAN}) @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_section (@code{HCDT} dat, @code{HCDT} ids, @code{const char *}dir, @code{mreal} val)
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_section_val (@code{HCDT} dat, @code{long} id, @code{const char *}dir, @code{mreal} val)
+ at deftypefnx {Функция С} @code{HADT} mgl_datac_section (@code{HCDT} dat, @code{HCDT} ids, @code{const char *}dir, @code{mreal} val)
+ at deftypefnx {Функция С} @code{HADT} mgl_datac_section_val (@code{HCDT} dat, @code{long} id, @code{const char *}dir, @code{mreal} val)
+ at end ifclear
+Возвращает массив данных, являющийся @var{id}-ой секцией (диапазоном срезов, разделенных значениями @var{val}) исходного массива @var{dat}. Для @var{id}<0 используется обратный порядок (т.e. -1 даст последнюю секцию). Если указано несколько @var{ids}, то выходной массив будет результатом последовательного объединения секций.
+ at end deftypefn
+
+ at anchor{solve}
+ at deftypefn {Команда MGL} {} solve @sc{res} dat @code{val} 'dir' [@code{norm=on}]
+ at deftypefnx {Команда MGL} {} solve @sc{res} dat @code{val} 'dir' idat [@code{norm=on}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Solve (@code{mreal} val, @code{char} dir, @code{bool} norm=@code{true}) @code{const}
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Solve (@code{mreal} val, @code{char} dir, @code{const mglDataA &}idat, @code{bool} norm=@code{true}) @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_solve (@code{HCDT} dat, @code{mreal} val, @code{char} dir, @code{HCDT} idat, @code{int} norm)
+ at end ifclear
+Возвращает массив индексов (корней) вдоль выбранного направления @var{dir} в которых значения массива @var{dat} равны @var{val}. Выходной массив будет иметь размеры массива @var{dat} в направлениях поперечных @var{dir}. Если предоставлен массив @var{idat}, то его значения используются как стартовые при поиске. Это позволяет найти несколько веток с помощью последовательного вызова функции. Индексы полагаются нормированными в диапазон [0,1] (при @var{norm}=@code{true}) или в диапазоны [0,n [...]
+ at end deftypefn
+
+ at anchor{roots}
+ at deftypefn {Команда MGL} {} roots @sc{res} 'func' ini ['var'='x']
+ at deftypefnx {Команда MGL} {} roots @sc{res} 'func' @code{ini} ['var'='x']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Roots (@code{const char *}func, @code{char} var) @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_roots (@code{const char *}func, @code{HCDT} ini, @code{char} var)
+ at deftypefnx {Функция С} @code{mreal} mgl_find_root_txt (@code{const char *}func, @code{mreal} ini, @code{char} var)
+ at end ifclear
+Возвращает массив корней уравнения 'func'=0 для переменной @var{var} с начальными положениями @var{ini}. Функция возвращает NULL или пустой массив если данные не могут быть созданы при данных значениях аргументов.
+ at end deftypefn
+
+ at anchor{detect}
+ at deftypefn {Команда MGL} {} detect @sc{res} dat @code{lvl dj [di=0 minlen=0]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Detect (@code{mreal} lvl, @code{mreal} dj, @code{mreal} di=@code{0}, @code{mreal} minlen=@code{0}) @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_detect (@code{HCDT} dat, @code{mreal} lvl, @code{mreal} dj, @code{mreal} di, @code{mreal} minlen)
+ at end ifclear
+Возвращает массив кривых @{x,y@}, разделенных NAN значениями, для локальных максимумов массива @var{dat} как функцию координаты x. Шумы амплитудой меньше @var{lvl} игнорируются. Параметр @var{dj} (в диапазоне [0,ny]) задает область "притяжения" точек в y-направлении к кривой. Аналогично, @var{di} продолжает кривые в x-направлении через разрывы длиной менее @var{di} точек. Кривые с минимальной длинной менее @var{minlen} игнорируются.
+ at end deftypefn
+
+ at anchor{hist}
+ at deftypefn {Команда MGL} {} hist @sc{res} dat @code{num v1 v2 [nsub=0]}
+ at deftypefnx {Команда MGL} {} hist @sc{res} dat wdat @code{num v1 v2 [nsub=0]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Hist (@code{int} n, @code{mreal} v1=@code{0}, @code{mreal} v2=@code{1}, @code{int} nsub=@code{0}) @code{const}
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Hist (@code{const mglDataA &}w, @code{int} n, @code{mreal} v1=@code{0}, @code{mreal} v2=@code{1}, @code{int} nsub=@code{0}) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{mglData} Hist (@code{int} n, @code{mreal} v1=@code{0}, @code{mreal} v2=@code{1}, @code{int} nsub=@code{0}) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{mglData} Hist (@code{const mglDataA &}w, @code{int} n, @code{mreal} v1=@code{0}, @code{mreal} v2=@code{1}, @code{int} nsub=@code{0}) @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_hist (@code{HCDT} dat, @code{int} n, @code{mreal} v1, @code{mreal} v2, @code{int} nsub)
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_hist_w (@code{HCDT} dat, @code{HCDT} w, @code{int} n, @code{mreal} v1, @code{mreal} v2, @code{int} nsub)
+ at end ifclear
+Возвращает распределение (гистограмму) из @var{n} точек от значений массива в диапазоне [@var{v1}, @var{v2}]. Массив @var{w} задает веса элементов (по умолчанию все веса равны 1). Параметр @var{nsub} задает число дополнительных точек интерполяции (для сглаживания получившейся гистограммы). Функция возвращает NULL или пустой массив если данные не могут быть созданы при данных значениях аргументов. См. также @ref{Data manipulation}
+ at end deftypefn
+
+ at anchor{momentum}
+ at deftypefn {Команда MGL} {} momentum @sc{res} dat 'how' ['dir'='z']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Momentum (@code{char} dir, @code{const char *}how) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{mglData} Momentum (@code{char} dir, @code{const char *}how) @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_momentum (@code{HCDT} dat, @code{char} dir, @code{const char *}how)
+ at end ifclear
+Возвращает момент (1d массив) данных вдоль направления @var{dir}. Строка @var{how} определяет тип момента. Момент определяется как
+ at iftex
+ at math{res_k = \sum_{ij} how(x_i,y_j,z_k) a_{ij}/\sum_{ij} a_{ij}}
+ at end iftex
+ at ifnottex
+res_k = \sum_ij how(x_i,y_j,z_k) a_ij/ \sum_ij a_ij
+ at end ifnottex
+если @var{dir}=@samp{z} и т.д. Координаты @samp{x}, @samp{y}, @samp{z} -- индексы массива в диапазоне [0,1]. Функция возвращает NULL или пустой массив если данные не могут быть созданы при данных значениях аргументов.
+ at end deftypefn
+
+ at anchor{sum}
+ at deftypefn {Команда MGL} {} sum @sc{res} dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Sum (@code{const char *}dir) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{mglData} Sum (@code{const char *}dir) @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_sum (@code{HCDT} dat, @code{const char *}dir)
+ at end ifclear
+Возвращает результат суммирования данных вдоль направления(ий) @var{dir}. Функция возвращает NULL или пустой массив если данные не могут быть созданы при данных значениях аргументов.
+ at end deftypefn
+
+ at anchor{max}
+ at deftypefn {Команда MGL} {} max @sc{res} dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Max (@code{const char *}dir) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{mglData} Max (@code{const char *}dir) @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_max_dir (@code{HCDT} dat, @code{const char *}dir)
+ at end ifclear
+Возвращает максимальное значение данных вдоль направления(ий) @var{dir}. Функция возвращает NULL или пустой массив если данные не могут быть созданы при данных значениях аргументов.
+ at end deftypefn
+
+ at anchor{min}
+ at deftypefn {Команда MGL} {} min @sc{res} dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Min (@code{const char *}dir) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{mglData} Min (@code{const char *}dir) @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_min_dir (@code{HCDT} dat, @code{const char *}dir)
+ at end ifclear
+Возвращает минимальное значение данных вдоль направления(ий) @var{dir}. Функция возвращает NULL или пустой массив если данные не могут быть созданы при данных значениях аргументов.
+ at end deftypefn
+
+ at anchor{combine}
+ at deftypefn {Команда MGL} {} combine @sc{res} adat bdat
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Combine (@code{const mglDataA &}a) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{mglData} Combine (@code{const mglDataA &}a) @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_combine (@code{HCDT} dat, @code{HCDT} a)
+ at end ifclear
+Возвращает прямое произведение массивов (наподобие, res[i,j] = adat[i]*bdat[j] и т.д.). Функция возвращает NULL или пустой массив если данные не могут быть созданы при данных значениях аргументов.
+ at end deftypefn
+
+ at anchor{trace}
+ at deftypefn {Команда MGL} {} trace @sc{res} dat
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Trace () @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{mglData} Trace () @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_trace (@code{HCDT} dat)
+ at end ifclear
+Возвращает массив диагональных элементов a[i,i] (для 2D данных) или a[i,i,i] (для 3D данных) где i=0...nx-1. В 1D случае возвращается сам массив данных. Размеры массива данных должен быть ny,nz >= nx или ny,nz = 1. Функция возвращает NULL или пустой массив если данные не могут быть созданы при данных значениях аргументов.
+ at end deftypefn
+
+ at anchor{correl}
+ at deftypefn {Команда MGL} {} correl @sc{res} adat bdat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Correl (@code{const mglDataA &}b, @code{const char *}dir) @code{const}
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} AutoCorrel (@code{const char *}dir) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{mglDataC} Correl (@code{const mglDataA &}b, @code{const char *}dir) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{mglDataC} AutoCorrel (@code{const char *}dir) @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_correl (@code{HCDT} a, @code{HCDT} b, @code{const char *}dir)
+ at deftypefnx {Функция С} @code{HADT} mgl_datac_correl (@code{HCDT} a, @code{HCDT} b, @code{const char *}dir)
+ at end ifclear
+Возвращает корреляцию массивов @var{a} (или this в C++) и @var{b} вдоль направлений @var{dir}. При вычислении используется преобразование Фурье. Поэтому может потребоваться вызов функций @ref{swap} и/или @ref{norm} перед построением. Функция возвращает NULL или пустой массив если данные не могут быть созданы при данных значениях аргументов.
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Метод класса @code{mglDataC}} @code{mglData} Real () @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_datac_real (@code{HCDT} dat)
+Возвращает массив действительных частей массива данных.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglDataC}} @code{mglData} Imag () @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_datac_imag (@code{HCDT} dat)
+Возвращает массив мнимых частей массива данных.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglDataC}} @code{mglData} Abs () @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_datac_abs (@code{HCDT} dat)
+Возвращает массив абсолютных значений массива данных.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglDataC}} @code{mglData} Arg () @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_datac_arg (@code{HCDT} dat)
+Возвращает массив аргументов массива данных.
+ at end deftypefn
+ at end ifclear
+
+ at anchor{pulse}
+ at deftypefn {Команда MGL} {} pulse @sc{res} dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{mglData} Pulse (@code{const char *}dir) @code{const}
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_pulse (@code{HCDT} dat, @code{const char *}dir)
+ at end ifclear
+Находит параметры импульса вдоль направления @var{dir}: максимальное значение (в колонке 0), его положение (в колонке 1), ширина по параболлической аппроксимации (в колонке 3) и по полувысоте (в колонке 2), энергию около максимума (в колонке 4). NAN значения используются для ширин если максимум расположен вблизи границ массива. Отмечу, что для комплексных массивов есть неопределенность определения параметров. Обычно следует использовать квадрат абсолютного значения амплитуды (т.е. |dat[i [...]
+ at end deftypefn
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Data changing, Interpolation, Make another data, Data processing
+ at section Изменение данных
+ at nav{}
+ at cindex CumSum
+ at cindex Integral
+ at cindex Diff
+ at cindex Diff2
+ at cindex SinFFT
+ at cindex CosFFT
+ at cindex Hankel
+ at cindex Swap
+ at cindex Roll
+ at cindex Mirror
+ at cindex Sew
+ at cindex Smooth
+ at cindex Envelop
+ at cindex Norm
+ at cindex NormSl
+
+These functions change the data in some direction like differentiations, integrations and so on. The direction in which the change will applied is specified by the string parameter, which may contain @samp{x}, @samp{y} or @samp{z} characters for 1-st, 2-nd and 3-d dimension correspondingly.
+
+ at anchor{cumsum}
+ at deftypefn {Команда MGL} {} cumsum dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} CumSum (@code{const char *}dir)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} CumSum (@code{const char *}dir)
+ at deftypefnx {Функция С} @code{void} mgl_data_cumsum (@code{HMDT} dat, @code{const char *}dir)
+ at deftypefnx {Функция С} @code{void} mgl_datac_cumsum (@code{HADT} dat, @code{const char *}dir)
+ at end ifclear
+Суммирует с накоплением в выбранном направлении(ях).
+ at end deftypefn
+
+ at anchor{integrate}
+ at deftypefn {Команда MGL} {} integrate dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Integral (@code{const char *}dir)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Integral (@code{const char *}dir)
+ at deftypefnx {Функция С} @code{void} mgl_data_integral (@code{HMDT} dat, @code{const char *}dir)
+ at deftypefnx {Функция С} @code{void} mgl_datac_integral (@code{HADT} dat, @code{const char *}dir)
+ at end ifclear
+Выполняет интегрирование (методом трапеций) в выбранном направлении(ях).
+ at end deftypefn
+
+ at anchor{diff}
+ at deftypefn {Команда MGL} {} diff dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Diff (@code{const char *}dir)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Diff (@code{const char *}dir)
+ at deftypefnx {Функция С} @code{void} mgl_data_diff (@code{HMDT} dat, @code{const char *}dir)
+ at deftypefnx {Функция С} @code{void} mgl_datac_diff (@code{HADT} dat, @code{const char *}dir)
+ at end ifclear
+Выполняет дифференцирование в выбранном направлении(ях).
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} diff dat xdat ydat [zdat]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Diff (@code{const mglDataA &}x)
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Diff (@code{const mglDataA &}x, @code{const mglDataA &}y)
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Diff (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Diff (@code{const mglDataA &}x)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Diff (@code{const mglDataA &}x, @code{const mglDataA &}y)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Diff (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z)
+ at deftypefnx {Функция С} @code{void} mgl_data_diff_par (@code{HMDT} dat, @code{HCDT} x, @code{HCDT}y, @code{HCDT}z)
+ at deftypefnx {Функция С} @code{void} mgl_datac_diff_par (@code{HADT} dat, @code{HCDT} x, @code{HCDT}y, @code{HCDT}z)
+ at end ifclear
+Выполняет дифференцирование данных, параметрически зависящих от координат, в направлении @var{x} с @var{y}, @var{z}=constant. Параметр @var{z} может быть опущен, что соответствует 2D случаю. Используются следующие формулы (2D случай): @math{da/dx = (a_j*y_i-a_i*y_j)/(x_j*y_i-x_i*y_j)}, где @math{a_i=da/di, a_j=da/dj} обозначает дифференцирование вдоль 1-ой и 2-ой размерности. Похожие формулы используются и в 3D случае. Порядок аргументов можно менять -- например, если данные a(i,j) завис [...]
+ at end deftypefn
+
+ at anchor{diff2}
+ at deftypefn {Команда MGL} {} diff2 dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Diff2 (@code{const char *}dir)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Diff2 (@code{const char *}dir)
+ at deftypefnx {Функция С} @code{void} mgl_data_diff2 (@code{HMDT} dat, @code{const char *}dir)
+ at deftypefnx {Функция С} @code{void} mgl_datac_diff2 (@code{HADT} dat, @code{const char *}dir)
+ at end ifclear
+Выполняет двойное дифференцирование (как в операторе Лапласа) в выбранном направлении(ях).
+ at end deftypefn
+
+ at anchor{sinfft}
+ at deftypefn {Команда MGL} {} sinfft dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} SinFFT (@code{const char *}dir)
+ at deftypefnx {Функция С} @code{void} mgl_data_sinfft (@code{HMDT} dat, @code{const char *}dir)
+ at end ifclear
+Выполняет синус преобразование в выбранном направлении(ях). Синус преобразование есть @math{\sum a_j \sin(k j)} (см. @uref{http://en.wikipedia.org/wiki/Discrete_sine_transform#DST-I}).
+ at end deftypefn
+
+ at anchor{cosfft}
+ at deftypefn {Команда MGL} {} cosfft dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} CosFFT (@code{const char *}dir)
+ at deftypefnx {Функция С} @code{void} mgl_data_cosfft (@code{HMDT} dat, @code{const char *}dir)
+ at end ifclear
+Выполняет косинус преобразование в выбранном направлении(ях). Синус преобразование есть @math{\sum a_j \cos(k j)} (см. @uref{http://en.wikipedia.org/wiki/Discrete_cosine_transform#DCT-I}).
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Метод класса @code{mglDataC}} @code{void} FFT (@code{const char *}dir)
+ at deftypefnx {Функция С} @code{void} mgl_datac_fft (@code{HADT} dat, @code{const char *}dir)
+Выполняет фурье преобразование в выбранном направлении(ях). Если строка @var{dir} содержит @samp{i}, то используется обратное преобразование фурье. Фурье преобразование есть @math{\sum a_j \exp(i k j)} (см. @uref{http://en.wikipedia.org/wiki/Discrete_Fourier_transform}).
+ at end deftypefn
+ at end ifclear
+
+ at anchor{hankel}
+ at deftypefn {Команда MGL} {} hankel dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Hankel (@code{const char *}dir)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Hankel (@code{const char *}dir)
+ at deftypefnx {Функция С} @code{void} mgl_data_hankel (@code{HMDT} dat, @code{const char *}dir)
+ at deftypefnx {Функция С} @code{void} mgl_datac_hankel (@code{HADT} dat, @code{const char *}dir)
+ at end ifclear
+Выполняет преобразование Ханкеля в выбранном направлении(ях). Преобразование Ханкеля есть @math{\sum a_j J_0(k j)} (см. @uref{http://en.wikipedia.org/wiki/Hankel_transform}).
+ at end deftypefn
+
+ at anchor{wavelet}
+ at deftypefn {Команда MGL} {} wavelet dat 'dir' @code{k}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Wavelet (@code{const char *}dir, @code{int} k)
+ at deftypefnx {Функция С} @code{void} mgl_data_wavelet (@code{HMDT} dat, @code{const char *}dir, @code{int} k)
+ at end ifclear
+Выполняет преобразование wavelet в выбранном направлении(ях). Параметр @var{dir} задает тип:
+ at samp{d} для daubechies, @samp{D} для центрированного daubechies, @samp{h} для haar, @samp{H} для центрированного haar, @samp{b} для bspline, @samp{B} для центрированного bspline. Если указан символ @samp{i}, то выполняется обратное преобразование. Параметр @var{k} задает размер преобразования.
+ at end deftypefn
+
+ at anchor{swap}
+ at deftypefn {Команда MGL} {} swap dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Swap (@code{const char *}dir)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Swap (@code{const char *}dir)
+ at deftypefnx {Функция С} @code{void} mgl_data_swap (@code{HMDT} dat, @code{const char *}dir)
+ at deftypefnx {Функция С} @code{void} mgl_datac_swap (@code{HADT} dat, @code{const char *}dir)
+ at end ifclear
+Меняет местами левую и правую части данных в выбранном направлении(ях). Полезно для отображения результата FFT.
+ at end deftypefn
+
+ at anchor{roll}
+ at deftypefn {Команда MGL} {} roll dat 'dir' num
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Roll (@code{char} dir, @code{num})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Roll (@code{char} dir, @code{num})
+ at deftypefnx {Функция С} @code{void} mgl_data_roll (@code{HMDT} dat, @code{char} dir, @code{num})
+ at deftypefnx {Функция С} @code{void} mgl_datac_roll (@code{HADT} dat, @code{char} dir, @code{num})
+ at end ifclear
+Сдвигает данные на @var{num} ячеек в выбранном направлении(ях). Соответствует замене индекса на @var{i}->(i+ at var{num})%nx при @code{dir='x'}.
+ at end deftypefn
+
+ at anchor{mirror}
+ at deftypefn {Команда MGL} {} mirror dat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Mirror (@code{const char *}dir)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Mirror (@code{const char *}dir)
+ at deftypefnx {Функция С} @code{void} mgl_data_mirror (@code{HMDT} dat, @code{const char *}dir)
+ at deftypefnx {Функция С} @code{void} mgl_datac_mirror (@code{HADT} dat, @code{const char *}dir)
+ at end ifclear
+Отражает данные в выбранном направлении(ях). Соответствует замене индекса на @var{i}->@var{n}- at var{i}. Отмечу, что похожего эффекта на графике можно достичь используя опции (@pxref{Command options}), например, @code{surf dat; xrange 1 -1}.
+ at end deftypefn
+
+ at anchor{sew}
+ at deftypefn {Команда MGL} {} sew dat ['dir'='xyz' @code{da=2*pi}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Sew (@code{const char *}dir, @code{mreal} da=@code{2*M_PI})
+ at deftypefnx {Функция С} @code{void} mgl_data_sew (@code{HMDT} dat, @code{const char *}dir, @code{mreal} da)
+ at end ifclear
+Удаляет скачки данных (например, скачки фазы после обратных тригонометрических функций) с периодом @var{da} в выбранном направлении(ях).
+ at end deftypefn
+
+ at anchor{smooth}
+ at deftypefn {Команда MGL} {} smooth data ['dir'='xyz']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Smooth (@code{const char *}dir=@code{"xyz"}, @code{mreal} delta=@code{0})
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Smooth (@code{const char *}dir=@code{"xyz"}, @code{mreal} delta=@code{0})
+ at deftypefnx {Функция С} @code{void} mgl_data_smooth (@code{HMDT} dat, @code{const char *}dir, @code{mreal} delta)
+ at deftypefnx {Функция С} @code{void} mgl_datac_smooth (@code{HADT} dat, @code{const char *}dir, @code{mreal} delta)
+ at end ifclear
+Сглаживает данные в выбранном направлении(ях) @var{dir}. Строка @var{dirs} задает направления вдоль которых будет производиться сглаживание. Строка @var{dir} может содержать:
+ at itemize @bullet
+ at item
+ at samp{xyz} -- сглаживание по x-,y-,z-направлениям,
+ at item
+ at samp{0} -- ничего не делает,
+ at item
+ at samp{3} -- линейное усреднение по 3 точкам,
+ at item
+ at samp{5} -- линейное усреднение по 5 точкам,
+ at item
+ at samp{d1}... at samp{d9} -- линейное усреднение по (2*N+1) точкам.
+ at end itemize
+По умолчанию используется квадратичное усреднение по 5 точкам.
+ at end deftypefn
+
+ at anchor{envelop}
+ at deftypefn {Команда MGL} {} envelop dat ['dir'='x']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Envelop (@code{char} dir=@code{'x'})
+ at deftypefnx {Функция С} @code{void} mgl_data_envelop (@code{HMDT} dat, @code{char} dir)
+ at end ifclear
+Находит огибающую данных в выбранном направлении @var{dir}.
+ at end deftypefn
+
+ at anchor{diffract}
+ at deftypefn {Команда MGL} {} diffract dat 'how' @code{q}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Diffraction (@code{const char *}how, @code{mreal} q)
+ at deftypefnx {Функция С} @code{void} mgl_datac_diffr (@code{HADT} dat, @code{const char *}how, @code{mreal} q)
+ at end ifclear
+Вычисляет один шаг диффракции в конечно-разностной схеме с параметром @var{q}=@math{\delta t/\delta x^2} используя метод третьего порядка точности. Параметр @var{how} может содержать:
+ at itemize @bullet
+ @item @samp{xyz} для расчета вдоль x-,y-,z-направления;
+ at item
+ @samp{r} для аксиально симметричного лапласиана по направлению x;
+ at item
+ @samp{0} для нулевых граничных условий;
+ at item
+ @samp{1} для постоянных граничных условий;
+ at item
+ @samp{2} для линейных граничных условий;
+ at item
+ @samp{3} для параболлических граничных условий;
+ at item
+ @samp{4} для экспоненциальных граничных условий;
+ at item
+ @samp{5} для гауссовых граничных условий.
+ at end itemize
+ at end deftypefn
+
+ at anchor{norm}
+ at deftypefn {Команда MGL} {} norm dat @code{v1 v2 [sym=off dim=0]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Norm (@code{mreal} v1=@code{0}, @code{mreal} v2=@code{1}, @code{bool} sym=@code{false}, @code{long} dim=@code{0})
+ at deftypefnx {Функция С} @code{void} mgl_data_norm (@code{HMDT} dat, @code{mreal} v1, @code{mreal} v2, @code{int} sym, @code{long} dim)
+ at end ifclear
+Нормирует данные в интервал [@var{v1}, at var{v2}]. Если @var{sym}=@code{true}, то используется симметричный интервал [-max(|v1|,|v2|), max(|v1|,|v2|)]. Изменения применяются только к срезам >=@var{dim}.
+ at end deftypefn
+
+ at anchor{normsl}
+ at deftypefn {Команда MGL} {} normsl dat @code{v1 v2} ['dir'='z' @code{keep=on sym=off}]
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} NormSl (@code{mreal} v1=@code{0}, @code{mreal} v2=@code{1}, @code{char} dir=@code{'z'}, @code{bool} keep=@code{true}, @code{bool} sym=@code{false})
+ at deftypefnx {Функция С} @code{void} mgl_data_norm_slice (@code{HMDT} dat, @code{mreal} v1, @code{mreal} v2, @code{char} dir, @code{int} keep, @code{int} sym)
+ at end ifclear
+Нормирует данные срез-за-срезом в выбранном направлении @var{dir} в интервал [@var{v1}, at var{v2}]. Если @var{sym}=@code{true}, то используется симметричный интервал [-max(|v1|,|v2|), max(|v1|,|v2|)]. Если @var{keep}=@code{true}, то максимальное значение k-го среза ограничено величиной
+ at iftex
+ at math{\sqrt{\sum a_{ij}(k)/\sum a_{ij}(0)}}.
+ at end iftex
+ at ifnottex
+ at math{\sqrt@{\sum a_ij(k)/\sum a_ij(0)@}}.
+ at end ifnottex
+ at end deftypefn
+
+ at anchor{limit}
+ at deftypefn {Команда MGL} {} limit dat @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Limit (@code{mreal} val)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} Limit (@code{mreal} val)
+ at deftypefnx {Функция С} @code{void} mgl_data_limit (@code{HMDT} dat, @code{mreal} val)
+ at deftypefnx {Функция С} @code{void} mgl_datac_limit (@code{HADT} dat, @code{mreal} val)
+ at end ifclear
+Ограничивает амплитуду данных диапазоном [- at var{val}, at var{val}]. При этом сохраняется исходный знак (фаза для комплексных чисел). Эквивалентно операции @code{a[i] *= abs(a[i])<val?1.:val/abs(a[i]);}.
+ at end deftypefn
+
+ at anchor{dilate}
+ at deftypefn {Команда MGL} {} dilate dat @code{[val=1 step=1]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Dilate (@code{mreal} val=@code{1}, @code{long} step=@code{1})
+ at deftypefnx {Функция С} @code{void} mgl_data_dilate (@code{HMDT} dat, @code{mreal} val, @code{long} step)
+ at end ifclear
+Возвращает "расширенный" на @var{step} ячеек массив из 0 и 1 для данных больших порогового значения @var{val}. @c TODO @sref{Dilate and erode sample}
+ at end deftypefn
+
+ at anchor{erode}
+ at deftypefn {Команда MGL} {} erode dat @code{[val=1 step=1]}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} Erode (@code{mreal} val=@code{1}, @code{long} step=@code{1})
+ at deftypefnx {Функция С} @code{void} mgl_data_erode (@code{HMDT} dat, @code{mreal} val, @code{long} step)
+ at end ifclear
+Возвращает "суженный" на @var{step} ячеек массив из 0 и 1 для данных больших порогового значения @var{val}. @c TODO @sref{Dilate and erode sample}
+ at end deftypefn
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Interpolation, Data information, Data changing, Data processing
+ at section Интерполяция
+ at nav{}
+
+Скрипты MGL могут использовать интерполяцию кубическими сплайнами с помощью команд @ref{evaluate} или @ref{refill}. Также можно использовать @ref{resize} для массива с новыми размерами.
+
+ at ifclear UDAV
+
+Однако, есть специальные и более быстрые функции при использовании других языков (C/C++/Fortran/Python/...).
+
+ at cindex Spline
+ at deftypefn {Метод класса @code{mglData}} @code{mreal} Spline (@code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{dual} Spline (@code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+ at deftypefnx {Функция С} @code{mreal} mgl_data_spline (@code{HCDT} dat, @code{mreal} x, @code{mreal} y, @code{mreal} z)
+ at deftypefnx {Функция С} @code{dual} mgl_datac_spline (@code{HCDT} dat, @code{mreal} x, @code{mreal} y, @code{mreal} z)
+Интерполирует данные кубическим сплайном в точке @var{x} в [0...nx-1], @var{y} в [0...ny-1], @var{z} в [0...nz-1].
+ at end deftypefn
+ at cindex Spline1
+ at deftypefn {Метод класса @code{mglData}} @code{mreal} Spline1 (@code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{dual} Spline1 (@code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+Интерполирует данные кубическим сплайном в точке @var{x}, @var{y}, @var{z}, где координаты полагаются в интервале [0, 1].
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglData}} @code{mreal} Spline (@code{mglPoint} &dif, @code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+ at deftypefnx {Функция С} @code{mreal} mgl_data_spline_ext (@code{HCDT} dat, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{mreal *}dx, @code{mreal *}dy, @code{mreal *}dz)
+ at deftypefnx {Функция С} @code{dual} mgl_datac_spline_ext (@code{HCDT} dat, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{dual *}dx, @code{dual *}dy, @code{dual *}dz)
+Интерполирует данные кубическим сплайном в точке @var{x} в [0...nx-1], @var{y} в [0...ny-1], @var{z} в [0...nz-1]. Значения производных в точке записываются в @var{dif}.
+ at end deftypefn
+ at cindex Spline1
+ at deftypefn {Метод класса @code{mglData}} @code{mreal} Spline1 (@code{mglPoint} &dif, @code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+Интерполирует данные кубическим сплайном в точке @var{x}, @var{y}, @var{z}, где координаты полагаются в интервале [0, 1]. Значения производных в точке записываются в @var{dif}.
+ at end deftypefn
+
+
+ at cindex Linear
+ at deftypefn {Метод класса @code{mglData}} @code{mreal} Linear (@code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{dual} Linear (@code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+ at deftypefnx {Функция С} @code{mreal} mgl_data_linear (@code{HCDT} dat, @code{mreal} x, @code{mreal} y, @code{mreal} z)
+ at deftypefnx {Функция С} @code{dual} mgl_datac_linear (@code{HCDT} dat, @code{mreal} x, @code{mreal} y, @code{mreal} z)
+Интерполирует данные линейной функцией в точке @var{x} в [0...nx-1], @var{y} в [0...ny-1], @var{z} в [0...nz-1].
+ at end deftypefn
+ at cindex Linear1
+ at deftypefn {Метод класса @code{mglData}} @code{mreal} Linear1 (@code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{dual} Linear1 (@code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+Интерполирует данные линейной функцией в точке @var{x}, @var{y}, @var{z}, где координаты полагаются в интервале [0, 1].
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglData}} @code{mreal} Linear (@code{mglPoint} &dif, @code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{dual} Linear (@code{mglPoint} &dif, @code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+ at deftypefnx {Функция С} @code{mreal} mgl_data_linear_ext (@code{HCDT} dat, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{mreal *}dx, @code{mreal *}dy, @code{mreal *}dz)
+ at deftypefnx {Функция С} @code{dual} mgl_datac_linear_ext (@code{HCDT} dat, @code{mreal} x, @code{mreal} y, @code{mreal} z, @code{dual *}dx, @code{dual *}dy, @code{dual *}dz)
+Интерполирует данные линейной функцией в точке @var{x}, @var{y}, @var{z}, где координаты полагаются в интервале [0, 1]. Значения производных в точке записываются в @var{dif}.
+ at end deftypefn
+ at cindex Linear1
+ at deftypefn {Метод класса @code{mglData}} @code{mreal} Linear1 (@code{mglPoint} &dif, @code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+ at deftypefnx {Метод класса @code{mglDataC}} @code{dual} Linear1 (@code{mglPoint} &dif, @code{mreal} x, @code{mreal} y=@code{0}, @code{mreal} z=@code{0}) @code{const}
+Интерполирует данные линейной функцией в точке @var{x}, @var{y}, @var{z}, где координаты полагаются в интервале [0, 1]. Значения производных в точке записываются в @var{dif}.
+ at end deftypefn
+
+ at end ifclear
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Data information, Operators, Interpolation, Data processing
+ at section Информационные функции
+ at nav{}
+
+В MathGL есть ряд функций для получения свойств массива данных. В MGL скриптах большинство из них реализовано в виде "суффиксов". Суффиксы дают числовое значение некоторой характеристики массива данных. Например, его размер, минимальное и максимальное значение, сумму элементов и т.д. Суффиксы начинаются с точки @samp{.} сразу после массива (без пробелов). Например, @code{a.nx} даст размер массива @var{a} вдоль x, @code{b(1).max} даст максимальное значение второй колонки массива @var{b},  [...]
+
+
+ at cindex PrintInfo
+ at anchor{info}
+ at deftypefn {Команда MGL} {} info dat
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglDataA}} @code{const char *} PrintInfo () @code{const}
+ at deftypefnx {Метод класса @code{mglDataA}} @code{void} PrintInfo (@code{FILE *}fp) @code{const}
+ at deftypefnx {Функция С} @code{const char *} mgl_data_info (@code{HCDT} dat)
+ at deftypefnx {Fortran процедура} @code{} mgl_data_info (@code{long} dat, @code{char *}out, @code{int} len)
+ at end ifclear
+Возвращает строку с информацией о данных (размеры, моменты и пр.) или пишет её в файл. В MGL скрипте печатает её как сообщение.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} info 'txt'
+Печатает строку @var{txt} как сообщение.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} info val
+Печатает значение числа @var{val} как сообщение.
+ at end deftypefn
+
+ at anchor{print}
+ at deftypefn {Команда MGL} {} print dat
+ at deftypefnx {Команда MGL} {} print 'txt'
+ at deftypefnx {Команда MGL} {} print val
+Аналогично @ref{info}, но сразу выводит в stdout.
+ at end deftypefn
+
+ at anchor{echo}
+ at deftypefn {Команда MGL} {} echo dat
+Печатает все значения массива @var{dat} как сообщение.
+ at end deftypefn
+
+
+ at cindex GetNx
+ at cindex GetNy
+ at cindex GetNz
+ at anchor{.nx} @anchor{.ny} @anchor{.nz}
+ at deftypefn {MGL suffix} {(dat)} .nx
+ at deftypefnx {MGL suffix} {(dat)} .ny
+ at deftypefnx {MGL suffix} {(dat)} .nz
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglDataA}} @code{long} GetNx ()
+ at deftypefnx {Метод класса @code{mglDataA}} @code{long} GetNy ()
+ at deftypefnx {Метод класса @code{mglDataA}} @code{long} GetNz ()
+ at deftypefnx {Функция С} @code{long} mgl_data_get_nx (@code{HCDT} dat)
+ at deftypefnx {Функция С} @code{long} mgl_data_get_ny (@code{HCDT} dat)
+ at deftypefnx {Функция С} @code{long} mgl_data_get_nz (@code{HCDT} dat)
+ at end ifclear
+Возвращает размер данных в направлении x, y и z соответственно.
+ at end deftypefn
+
+
+
+ at cindex Maximal
+ at anchor{.max}
+ at deftypefn {MGL suffix} {(dat)} .max
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglDataA}} @code{mreal} Maximal () @code{const}
+ at deftypefnx {Функция С} @code{mreal} mgl_data_max (@code{HCDT} dat)
+ at end ifclear
+Возвращает максимальное значение массива данных.
+ at end deftypefn
+
+ at cindex Minimal
+ at anchor{.min}
+ at deftypefn {MGL suffix} {(dat)} .min
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglDataA}} @code{mreal} Minimal () @code{const}
+ at deftypefnx {Функция С} @code{mreal} mgl_data_min (@code{HMDT} dat) @code{const}
+ at end ifclear
+Возвращает минимальное значение массива данных.
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Метод класса @code{mglDataA}} @code{mreal} Minimal (@code{int} &i, @code{int} &j, @code{int} &k) @code{const}
+ at deftypefnx {Функция С} @code{mreal} mgl_data_min_int (@code{HCDT} dat, @code{int} *i, @code{int} *j, @code{int} *k)
+Возвращает максимальное значение массива данных и сохраняет его положение в переменные @var{i}, @var{j}, @var{k}.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglDataA}} @code{mreal} Maximal (@code{int} &i, @code{int} &j, @code{int} &k) @code{const}
+ at deftypefnx {Функция С} @code{mreal} mgl_data_max_int (@code{HCDT} dat, @code{int} *i, @code{int} *j, @code{int} *k)
+Возвращает минимальное значение массива данных и сохраняет его положение в переменные @var{i}, @var{j}, @var{k}.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglDataA}} @code{mreal} Minimal (@code{mreal} &x, @code{mreal} &y, @code{mreal} &z) @code{const}
+ at deftypefnx {Функция С} @code{mreal} mgl_data_min_real (@code{HCDT} dat, @code{mreal} *x, @code{mreal} *y, @code{mreal} *z)
+Возвращает максимальное значение массива данных и его приближенное (интерполированное) положение в переменные @var{x}, @var{y}, @var{z}.
+ at end deftypefn
+ at end ifclear
+
+ at anchor{.mx} @anchor{.my} @anchor{.mz}
+ at deftypefn {MGL suffix} {(dat)} .mx
+ at deftypefnx {MGL suffix} {(dat)} .my
+ at deftypefnx {MGL suffix} {(dat)} .mz
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglDataA}} @code{mreal} Maximal (@code{mreal} &x, @code{mreal} &y, @code{mreal} &z) @code{const}
+ at deftypefnx {Функция С} @code{mreal} mgl_data_max_real (@code{HCDT} dat, @code{mreal} *x, @code{mreal} *y, @code{mreal} *z)
+ at end ifclear
+Возвращает минимальное значение массива данных и его приближенное (интерполированное) положение в переменные @var{x}, @var{y}, @var{z}.
+ at end deftypefn
+
+ at anchor{.mxf} @anchor{.myf} @anchor{.mzf}
+ at anchor{.mxl} @anchor{.myl} @anchor{.mzl}
+ at deftypefn {MGL suffix} {(dat)} .mxf
+ at deftypefnx {MGL suffix} {(dat)} .myf
+ at deftypefnx {MGL suffix} {(dat)} .mzf
+ at deftypefnx {MGL suffix} {(dat)} .mxl
+ at deftypefnx {MGL suffix} {(dat)} .myl
+ at deftypefnx {MGL suffix} {(dat)} .mzl
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglDataA}} @code{long} Maximal (@code{char} dir, @code{long} from) @code{const}
+ at deftypefnx {Метод класса @code{mglDataA}} @code{long} Maximal (@code{char} dir, @code{long} from, @code{long} &p1, @code{long} &p2) @code{const}
+ at deftypefnx {Функция С} @code{mreal} mgl_data_max_firstl (@code{HCDT} dat, @code{char} dir, @code{long} from, @code{long} *p1, @code{long} *p2)
+ at end ifclear
+Возвращает положение первого (последнего при @var{from}<0) максимума в направлении @var{dir}, начиная с позиции @var{from}. Положение остальных координат для максимума сохраняется в @var{p1}, @var{p2}.
+ at end deftypefn
+
+
+ at cindex Momentum
+ at anchor{.ax} @anchor{.ay} @anchor{.az} @anchor{.aa} @anchor{.sum}
+ at anchor{.wx} @anchor{.wy} @anchor{.wz} @anchor{.wa}
+ at anchor{.sx} @anchor{.sy} @anchor{.sz} @anchor{.sa}
+ at anchor{.kx} @anchor{.ky} @anchor{.kz} @anchor{.ka}
+ at deftypefn {MGL suffix} {(dat)} .sum
+ at deftypefnx {MGL suffix} {(dat)} .ax
+ at deftypefnx {MGL suffix} {(dat)} .ay
+ at deftypefnx {MGL suffix} {(dat)} .az
+ at deftypefnx {MGL suffix} {(dat)} .aa
+ at deftypefnx {MGL suffix} {(dat)} .wx
+ at deftypefnx {MGL suffix} {(dat)} .wy
+ at deftypefnx {MGL suffix} {(dat)} .wz
+ at deftypefnx {MGL suffix} {(dat)} .wa
+ at deftypefnx {MGL suffix} {(dat)} .sx
+ at deftypefnx {MGL suffix} {(dat)} .sy
+ at deftypefnx {MGL suffix} {(dat)} .sz
+ at deftypefnx {MGL suffix} {(dat)} .sa
+ at deftypefnx {MGL suffix} {(dat)} .kx
+ at deftypefnx {MGL suffix} {(dat)} .ky
+ at deftypefnx {MGL suffix} {(dat)} .kz
+ at deftypefnx {MGL suffix} {(dat)} .ka
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglDataA}} @code{mreal} Momentum (@code{char} dir, @code{mreal} &a, @code{mreal} &w) @code{const}
+ at deftypefnx {Метод класса @code{mglDataA}} @code{mreal} Momentum (@code{char} dir, @code{mreal} &m, @code{mreal} &w, @code{mreal} &s, @code{mreal} &k) @code{const}
+ at deftypefnx {Функция С} @code{mreal} mgl_data_momentum_val (@code{HCDT} dat, @code{char} dir, @code{mreal} *a, @code{mreal} *w, @code{mreal} *s, @code{mreal} *k)
+ at end ifclear
+Возвращает нулевой момент (энергию, @math{I=\sum a_i}) и записывает первый (среднее, @math{m = \sum \xi_i a_i/I}), второй (ширину, @math{w^2 = \sum (\xi_i-m)^2 a_i/I}), третий (асимметрия, @math{s = \sum (\xi_i-m)^3 a_i/ I w^3}) и четвёртый моменты (эксцесс, @math{k = \sum (\xi_i-m)^4 a_i / 3 I w^4})). Здесь @math{\xi} -- соответствующая координата если @var{dir} равно @samp{'x'}, @samp{'y'}, @samp{'z'}. В противном случае среднее, ширина, асимметрия, эксцесс равны @math{m = \sum a_i/N}, [...]
+ at end deftypefn
+
+ at anchor{.fst}
+ at deftypefn {MGL suffix} {(dat)} .fst
+ at ifclear UDAV
+ at cindex Find
+ at deftypefnx {Метод класса @code{mglDataA}} @code{mreal} Find (@code{const char *}cond, @code{int} &i, @code{int} &j, @code{int} &k) @code{const}
+ at deftypefnx {Функция С} @code{mreal} mgl_data_first (@code{HCDT} dat, @code{const char *}cond, @code{int} *i, @code{int} *j, @code{int} *k)
+ at end ifclear
+Находит положение (после заданного в @var{i}, @var{j}, @var{k}) первого не нулевого значения формулы @var{cond}. Функция возвращает найденное значение и записывает его положение в @var{i}, @var{j}, @var{k}.
+ at end deftypefn
+
+ at anchor{.lst}
+ at deftypefn {MGL suffix} {(dat)} .lst
+ at ifclear UDAV
+ at cindex Last
+ at deftypefnx {Метод класса @code{mglDataA}} @code{mreal} Last (@code{const char *}cond, @code{int} &i, @code{int} &j, @code{int} &k) @code{const}
+ at deftypefnx {Функция С} @code{mreal} mgl_data_last (@code{HCDT} dat, @code{const char *}cond, @code{int} *i, @code{int} *j, @code{int} *k)
+ at end ifclear
+Находит положение (перед заданного в @var{i}, @var{j}, @var{k}) последнего не нулевого значения формулы @var{cond}. Функция возвращает найденное значение и записывает его положение в @var{i}, @var{j}, @var{k}.
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Метод класса @code{mglDataA}} @code{int} Find (@code{const char *}cond, @code{char} dir, @code{int} i=@code{0}, @code{int} j=@code{0}, @code{int} k=@code{0}) @code{const}
+ at deftypefnx {Функция С} @code{mreal} mgl_data_find (@code{HCDT} dat, @code{const char *}cond, @code{int} i, @code{int} j, @code{int} k)
+Возвращает положение первого в направлении @var{dir} не нулевого значения формулы @var{cond}. Поиск начинается с точки @{i,j,k@}.
+ at end deftypefn
+ at cindex FindAny
+ at deftypefn {Метод класса @code{mglDataA}} @code{bool} FindAny (@code{const char *}cond) @code{const}
+ at deftypefnx {Функция С} @code{mreal} mgl_data_find_any (@code{HCDT} dat, @code{const char *}cond)
+Определяет есть ли хоть одно значение массива, удовлетворяющее условию @var{cond}.
+ at end deftypefn
+ at end ifclear
+
+ at anchor{.a}
+ at deftypefn {MGL suffix} {(dat)} .a
+Возвращает первое число массива (для @code{.a} это @code{dat->a[0]}).
+ at end deftypefn
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Operators, Global functions, Data information, Data processing
+ at section Операторы
+ at nav{}
+
+ at deftypefn {Команда MGL} {} copy @sc{dat} dat2 ['eq'='']
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} operator= (@code{const mglDataA &}d)
+ at end ifclear
+Копирует данные из другого экземпляра.
+ at end deftypefn
+
+ at deftypefn {Команда MGL} {} copy dat @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mreal}} @code{void} operator= (@code{mreal} val)
+ at end ifclear
+Устанавливает все значения массива равными @var{val}.
+ at end deftypefn
+
+ at anchor{multo}
+ at deftypefn {Команда MGL} {} multo dat dat2
+ at deftypefnx {Команда MGL} {} multo dat @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} operator*= (@code{const mglDataA &}d)
+ at deftypefnx {Метод класса @code{mglData}} @code{void} operator*= (@code{mreal} d)
+ at deftypefnx {Функция С} @code{void} mgl_data_mul_dat (@code{HMDT} dat, @code{HCDT} d)
+ at deftypefnx {Функция С} @code{void} mgl_data_mul_num (@code{HMDT} dat, @code{mreal} d)
+ at end ifclear
+Поэлементно умножает на массив @var{d} или на число @var{val}.
+ at end deftypefn
+
+ at anchor{divto}
+ at deftypefn {Команда MGL} {} divto dat dat2
+ at deftypefnx {Команда MGL} {} divto dat @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} operator/= (@code{const mglDataA &}d)
+ at deftypefnx {Метод класса @code{mglData}} @code{void} operator/= (@code{mreal} d)
+ at deftypefnx {Функция С} @code{void} mgl_data_div_dat (@code{HMDT} dat, @code{HCDT} d)
+ at deftypefnx {Функция С} @code{void} mgl_data_div_num (@code{HMDT} dat, @code{mreal} d)
+ at end ifclear
+Поэлементно делит на массив @var{d} или на число @var{val}.
+ at end deftypefn
+
+ at anchor{addto}
+ at deftypefn {Команда MGL} {} addto dat dat2
+ at deftypefnx {Команда MGL} {} addto dat @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} operator+= (@code{const mglDataA &}d)
+ at deftypefnx {Метод класса @code{mglData}} @code{void} operator+= (@code{mreal} d)
+ at deftypefnx {Функция С} @code{void} mgl_data_add_dat (@code{HMDT} dat, @code{HCDT} d)
+ at deftypefnx {Функция С} @code{void} mgl_data_add_num (@code{HMDT} dat, @code{mreal} d)
+ at end ifclear
+Поэлементно прибавляет @var{d} или число @var{val}.
+ at end deftypefn
+
+ at anchor{subto}
+ at deftypefn {Команда MGL} {} subto dat dat2
+ at deftypefnx {Команда MGL} {} subto dat @code{val}
+ at ifclear UDAV
+ at deftypefnx {Метод класса @code{mglData}} @code{void} operator-= (@code{const mglDataA &}d)
+ at deftypefnx {Метод класса @code{mglData}} @code{void} operator-= (@code{mreal} d)
+ at deftypefnx {Функция С} @code{void} mgl_data_sub_dat (@code{HMDT} dat, @code{HCDT} d)
+ at deftypefnx {Функция С} @code{void} mgl_data_sub_num (@code{HMDT} dat, @code{mreal} d)
+ at end ifclear
+Поэлементно вычитает @var{d} или число @var{val}.
+ at end deftypefn
+
+ at ifclear UDAV
+ at deftypefn {Library Function} mglData operator+ (@code{const mglDataA &}a, @code{const mglDataA &}b)
+ at deftypefnx {Library Function} mglData operator+ (@code{mreal} a, @code{const mglDataA &}b)
+ at deftypefnx {Library Function} mglData operator+ (@code{const mglDataA &}a, @code{mreal} b)
+Возвращает поэлементную сумму данных.
+ at end deftypefn
+
+ at deftypefn {Library Function} mglData operator- (@code{const mglDataA &}a, @code{const mglDataA &}b)
+ at deftypefnx {Library Function} mglData operator- (@code{mreal} a, @code{const mglDataA &}b)
+ at deftypefnx {Library Function} mglData operator- (@code{const mglDataA &}a, @code{mreal} b)
+Возвращает поэлементную разность данных.
+ at end deftypefn
+
+ at deftypefn {Library Function} mglData operator* (@code{const mglDataA &}a, @code{const mglDataA &}b)
+ at deftypefnx {Library Function} mglData operator* (@code{mreal} a, @code{const mglDataA &}b)
+ at deftypefnx {Library Function} mglData operator* (@code{const mglDataA &}a, @code{mreal} b)
+Возвращает поэлементное произведение данных.
+ at end deftypefn
+
+ at deftypefn {Library Function} mglData operator/ (@code{const mglDataA &}a, @code{const mglDataA &}b)
+ at deftypefnx {Library Function} mglData operator/ (@code{const mglDataA &}a, @code{mreal} b)
+Возвращает поэлементное деление данных.
+ at end deftypefn
+ at end ifclear
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Global functions, Evaluate expression, Operators, Data processing
+ at section Глобальные функции
+ at nav{}
+
+ at ifclear UDAV
+Эти функции не методы класса @code{mglData}, но они дают дополнительные возможности по обработке данных. Поэтому я поместил их в эту главу.
+ at end ifclear
+
+ at anchor{transform}
+ at deftypefn {Команда MGL} {} transform @sc{dat} 'type' real imag
+ at ifclear UDAV
+ at deftypefnx {Общая функция} @code{mglData} mglTransform (@code{const mglDataA &}real, @code{const mglDataA &}imag, @code{const char *}type)
+ at deftypefnx {Функция С} @code{HMDT} mgl_transform (@code{HCDT} real, @code{HCDT} imag, @code{const char *}type)
+ at end ifclear
+Выполняет интегральное преобразование комплексных данных @var{real}, @var{imag} в выбранном направлении и возвращает модуль результата. Порядок и тип преобразований задается строкой @var{type}: первый символ для x-направления, второй для y-направления, третий для z-направления. Возможные символы: @samp{f} -- прямое преобразование Фурье, @samp{i} -- обратное преобразование Фурье, @samp{s} -- синус преобразование, @samp{c} -- косинус преобразование, @samp{h} -- преобразование Ханкеля, @sam [...]
+ at end deftypefn
+
+ at anchor{transforma}
+ at deftypefn {Команда MGL} {} transforma @sc{dat} 'type' ampl phase
+ at ifclear UDAV
+ at deftypefnx {Общая функция} @code{mglData} mglTransformA @code{const mglDataA &}ampl, @code{const mglDataA &}phase, @code{const char *}type)
+ at deftypefnx {Функция С} @code{HMDT} mgl_transform_a @code{HCDT} ampl, @code{HCDT} phase, @code{const char *}type)
+ at end ifclear
+Аналогично предыдущему с заданными амплитудой @var{ampl} и фазой @var{phase} комплексных чисел.
+ at end deftypefn
+
+ at anchor{fourier}
+ at deftypefn {Команда MGL} {} fourier reDat imDat 'dir'
+ at deftypefnx {Команда MGL} {} fourier complexDat 'dir'
+ at ifclear UDAV
+ at deftypefnx {Общая функция} @code{void} mglFourier @code{const mglDataA &}re, @code{const mglDataA &}im, @code{const char *}dir)
+ at deftypefnx {Метод класса @code{mglDataC}} @code{void} FFT (@code{const char *}dir)
+ at deftypefnx {Функция С} @code{void} mgl_data_fourier @code{HCDT} re, @code{HCDT} im, @code{const char *}dir)
+ at deftypefnx {Функция С} @code{void} mgl_datac_fft (@code{HADT} dat, @code{const char *}dir)
+ at end ifclear
+Выполняет Фурье преобразование для комплексных данных @var{re}+i*@var{im} в направлениях @var{dir}. Результат помещается обратно в массивы @var{re} и @var{im}. Если @var{dir} содержит @samp{i}, то выполняется обратное преобразование Фурье.
+ at end deftypefn
+
+ at anchor{stfad}
+ at deftypefn {Команда MGL} {} stfad @sc{res} real imag @code{dn} ['dir'='x']
+ at ifclear UDAV
+ at deftypefnx {Общая функция} @code{mglData} mglSTFA (@code{const mglDataA &}real, @code{const mglDataA &}imag, @code{int} dn, @code{char} dir=@code{'x'})
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_stfa (@code{HCDT} real, @code{HCDT} imag, @code{int} dn, @code{char} dir)
+ at end ifclear
+Выполняет оконное преобразование Фурье длиной @var{dn} для комплексных данных @var{real}, @var{imag} и возвращает модуль результата. Например, для @var{dir}=@samp{x} результат будет иметь размер @{int(nx/dn), dn, ny@} и будет равен @math{res[i,j,k]=|\sum_d^dn exp(I*j*d)*(real[i*dn+d,k]+I*imag[i*dn+d,k])|/dn}.
+ at end deftypefn
+
+ at anchor{tridmat}
+ at deftypefn {Команда MGL} {} tridmat @sc{res adat bdat cdat ddat} 'how'
+ at ifclear UDAV
+ at deftypefnx {Общая функция} @code{mglData} mglTridMat (@code{const mglDataA &}A, @code{const mglDataA &}B, @code{const mglDataA &}C, @code{const mglDataA &}D, @code{const char *}how)
+ at deftypefnx {Общая функция} @code{mglDataC} mglTridMatC (@code{const mglDataA &}A, @code{const mglDataA &}B, @code{const mglDataA &}C, @code{const mglDataA &}D, @code{const char *}how)
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_tridmat (@code{HCDT} A, @code{HCDT} B, @code{HCDT} C, @code{HCDT} D, @code{const char*}how)
+ at deftypefnx {Функция С} @code{HADT} mgl_datac_tridmat (@code{HCDT} A, @code{HCDT} B, @code{HCDT} C, @code{HCDT} D, @code{const char*}how)
+ at end ifclear
+Возвращает решение трехдиагональной системы уравнений @var{A}[i]*x[i-1]+ at var{B}[i]*x[i]+ at var{C}[i]*x[i+1]=@var{D}[i]. Строка @var{how} может содержать:
+ at itemize @bullet
+ at item
+ at samp{xyz} для решения вдоль x-,y-,z-направлений;
+ at item
+ at samp{h} для решения вдоль диагонали на плоскости x-y (требует квадратную матрицу);
+ at item
+ at samp{c} для использования периодических граничных условий;
+ at item
+ at samp{d} для расчета диффракции/диффузии (т.е. для использования - at var{A}[i]*@var{D}[i-1]+(2- at var{B}[i])*@var{D}[i]- at var{C}[i]*@var{D}[i+1] в правой частиц вместо @var{D}[i]).
+ at end itemize
+Размеры массивов @var{A}, @var{B}, @var{C} должны быть одинаковы. Также их размерности должны совпадать со всеми или с "младшими" размерностями массива @var{D}. @sref{PDE solving hints}
+ at end deftypefn
+
+ at anchor{pde}
+ at deftypefn {Команда MGL} {} pde @sc{res} 'ham' ini_re ini_im [@code{dz=0.1 k0=100}]
+ at ifclear UDAV
+ at deftypefnx {Общая функция} @code{mglData} mglPDE (@code{HMGL} gr, @code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{mreal} dz=@code{0.1}, @code{mreal} k0=@code{100}, @code{const char *}opt=@code{""})
+ at deftypefnx {Общая функция} @code{mglDataC} mglPDEc (@code{HMGL} gr, @code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{mreal} dz=@code{0.1}, @code{mreal} k0=@code{100}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{HMDT} mgl_pde_solve (@code{HMGL} gr, @code{const char *}ham, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{mreal} dz, @code{mreal} k0, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{HADT} mgl_pde_solve_c (@code{HMGL} gr, @code{const char *}ham, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{mreal} dz, @code{mreal} k0, @code{const char *}opt)
+ at end ifclear
+Решает уравнение в частных производных du/dz = i*k0*@var{ham}(p,q,x,y,z,|u|)[u], где p=-i/k0*d/dx, q=-i/k0*d/dy -- псевдо-дифференциальные операторы. Параметры @var{ini_re}, @var{ini_im} задают начальное распределение поля. Координаты в уравнении и в решении полагаются в диапазоне осей координат. Замечу, что внутри этот диапазон увеличивается в 3/2 раза для уменьшения отражения от границ расчетного интервала. Параметр @var{dz} задает шаг по эволюционной координате z. В данный момент испо [...]
+ at end deftypefn
+
+ at anchor{apde}
+ at deftypefn {Команда MGL} {} apde @sc{res} 'ham' ini_re ini_im [@code{dz=0.1 k0=100}]
+ at ifclear UDAV
+ at deftypefnx {Общая функция} @code{mglData} mglAPDE (@code{HMGL} gr, @code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{mreal} dz=@code{0.1}, @code{mreal} k0=@code{100}, @code{const char *}opt=@code{""})
+ at deftypefnx {Общая функция} @code{mglDataC} mglAPDEc (@code{HMGL} gr, @code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{mreal} dz=@code{0.1}, @code{mreal} k0=@code{100}, @code{const char *}opt=@code{""})
+ at deftypefnx {Функция С} @code{HMDT} mgl_pde_solve_adv (@code{HMGL} gr, @code{const char *}ham, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{mreal} dz, @code{mreal} k0, @code{const char *}opt)
+ at deftypefnx {Функция С} @code{HADT} mgl_pde_solve_adv_c (@code{HMGL} gr, @code{const char *}ham, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{mreal} dz, @code{mreal} k0, @code{const char *}opt)
+ at end ifclear
+Решает уравнение в частных производных du/dz = i*k0*@var{ham}(p,q,x,y,z,|u|)[u], где p=-i/k0*d/dx, q=-i/k0*d/dy -- псевдо-дифференциальные операторы. Параметры @var{ini_re}, @var{ini_im} задают начальное распределение поля. Координаты в уравнении и в решении полагаются в диапазоне осей координат. Замечу, что внутри этот диапазон увеличивается в 3/2 раза для уменьшения отражения от границ расчетного интервала. Параметр @var{dz} задает шаг по эволюционной координате z. Используется достато [...]
+ at end deftypefn
+
+ at anchor{ray}
+ at deftypefn {Команда MGL} {} ray @sc{res} 'ham' @code{x0 y0 z0 p0 q0 v0 [dt=0.1 tmax=10]}
+ at ifclear UDAV
+ at deftypefnx {Общая функция} @code{mglData} mglRay (@code{const char *}ham, @code{mglPoint} r0, @code{mglPoint} p0, @code{mreal} dt=@code{0.1}, @code{mreal} tmax=@code{10})
+ at deftypefnx {Функция С} @code{HMDT} mgl_ray_trace (@code{const char *}ham, @code{mreal} x0, @code{mreal} y0, @code{mreal} z0, @code{mreal} px, @code{mreal} py, @code{mreal} pz, @code{mreal} dt, @code{mreal} tmax)
+ at end ifclear
+Решает систему геометрооптических уравнений d at emph{r}/dt = d @var{ham}/d at emph{p}, d at emph{p}/dt = -d @var{ham}/d at emph{r}. Это гамильтоновы уравнения для траектории частицы в 3D случае. Гамильтониан @var{ham} может зависеть от координат @samp{x}, @samp{y}, @samp{z}, импульсов @samp{p}=px, @samp{q}=py, @samp{v}=pz и времени @samp{t}: @math{ham = H(x,y,z,p,q,v,t)}. Начальная точка (при @code{t=0}) задается переменными @{@var{x0}, @var{y0}, @var{z0}, @var{p0}, @var{q0}, @var{v0}@}. Параметры  [...]
+ at end deftypefn
+
+ at anchor{ode}
+ at deftypefn {Команда MGL} {} ode @sc{res} 'df' 'var' ini [@code{dt=0.1 tmax=10}]
+ at ifclear UDAV
+ at deftypefnx {Общая функция} @code{mglData} mglODE (@code{const char *}df, @code{const char *}var, @code{const mglDataA &}ini, @code{mreal} dt=@code{0.1}, @code{mreal} tmax=@code{10})
+ at deftypefnx {Общая функция} @code{mglDataC} mglODEc (@code{const char *}df, @code{const char *}var, @code{const mglDataA &}ini, @code{mreal} dt=@code{0.1}, @code{mreal} tmax=@code{10})
+ at deftypefnx {Функция С} @code{HMDT} mgl_ode_solve_str (@code{const char *}df, @code{const char *}var, @code{HCDT} ini, @code{mreal} dt, @code{mreal} tmax)
+ at deftypefnx {Функция С} @code{HADT} mgl_ode_solve_str_c (@code{const char *}df, @code{const char *}var, @code{HCDT} ini, @code{mreal} dt, @code{mreal} tmax)
+ at deftypefnx {Функция С} @code{HMDT} mgl_ode_solve (@code{void (*}df at code{)(const mreal *x, mreal *dx, void *par)}, @code{int} n, @code{const mreal *}ini, @code{mreal} dt, @code{mreal} tmax)
+ at deftypefnx {Функция С} @code{HMDT} mgl_ode_solve_ex (@code{void (*}df at code{)(const mreal *x, mreal *dx, void *par)}, @code{int} n, @code{const mreal *}ini, @code{mreal} dt, @code{mreal} tmax, @code{void (*}bord at code{)(mreal *x, const mreal *xprev, void *par)})
+ at end ifclear
+Решает систему обыкновенных дифференциальных уравнений dx/dt = df(x). Функции @var{df} могут быть заданны строкой с разделенными ';' формулами (аргумент @var{var} задает символы для переменных x[i]) или указателем на функцию, которая заполняет @code{dx} по заданным значениям @code{x}. Параметры @var{ini}, @var{dt}, @var{tmax} задают начальные значения, шаг и максимальное время интегрирования. Результат -- массив с размером @{@var{n} * int(@var{tmax}/@var{dt}+1)@}.
+ at end deftypefn
+
+ at anchor{qo2d}
+ at deftypefn {Команда MGL} {} qo2d @sc{res} 'ham' ini_re ini_im ray [@code{r=1 k0=100} xx yy]
+ at ifclear UDAV
+ at deftypefnx {Общая функция} @code{mglData} mglQO2d (@code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{const mglDataA &}ray, @code{mreal} r=@code{1}, @code{mreal} k0=@code{100}, @code{mglData *}xx=@code{0}, @code{mglData *}yy=@code{0})
+ at deftypefnx {Общая функция} @code{mglData} mglQO2d (@code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{const mglDataA &}ray, @code{mglData &}xx, @code{mglData &}yy, @code{mreal} r=@code{1}, @code{mreal} k0=@code{100})
+ at deftypefnx {Общая функция} @code{mglDataC} mglQO2dc (@code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{const mglDataA &}ray, @code{mreal} r=@code{1}, @code{mreal} k0=@code{100})
+ at deftypefnx {Общая функция} @code{mglDataC} mglQO2dc (@code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{const mglDataA &}ray, @code{mglData &}xx, @code{mglData &}yy, @code{mreal} r=@code{1}, @code{mreal} k0=@code{100})
+ at deftypefnx {Функция С} @code{HMDT} mgl_qo2d_solve (@code{const char *}ham, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{HCDT} ray, @code{mreal} r, @code{mreal} k0, @code{HMDT} xx, @code{HMDT} yy)
+ at deftypefnx {Функция С} @code{HADT} mgl_qo2d_solve_c (@code{const char *}ham, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{HCDT} ray, @code{mreal} r, @code{mreal} k0, @code{HMDT} xx, @code{HMDT} yy)
+ at deftypefnx {Функция С} @code{HMDT} mgl_qo2d_func (@code{dual (*}ham at code{)(mreal u, mreal x, mreal y, mreal px, mreal py, void *par)}, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{HCDT} ray, @code{mreal} r, @code{mreal} k0, @code{HMDT} xx, @code{HMDT} yy)
+ at deftypefnx {Функция С} @code{HADT} mgl_qo2d_func_c (@code{dual (*}ham at code{)(mreal u, mreal x, mreal y, mreal px, mreal py, void *par)}, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{HCDT} ray, @code{mreal} r, @code{mreal} k0, @code{HMDT} xx, @code{HMDT} yy)
+ at end ifclear
+Решает уравнение в частных производных du/dt = i*k0*@var{ham}(p,q,x,y,|u|)[u] в сопровождающей системе координат, где p=-i/k0*d/dx, q=-i/k0*d/dy -- псевдо-дифференциальные операторы. Параметры @var{ini_re}, @var{ini_im} задают начальное распределение поля. Параметр @var{ray} задает опорный луч для сопровождающей системы координат. Можно использовать луч найденный с помощью @ref{ray}. Опорный луч должен быть достаточно гладкий, чтобы система координат была однозначной и для исключения оши [...]
+ at end deftypefn
+
+ at anchor{qo3d}
+ at deftypefn {Команда MGL} {} qo3d @sc{res} 'ham' ini_re ini_im ray [@code{r=1 k0=100} xx yy zz]
+ at ifclear UDAV
+ at deftypefnx {Общая функция} @code{mglData} mglQO3d (@code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{const mglDataA &}ray, @code{mreal} r=@code{1}, @code{mreal} k0=@code{100})
+ at deftypefnx {Общая функция} @code{mglData} mglQO3d (@code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{const mglDataA &}ray, @code{mglData &}xx, @code{mglData &}yy, @code{mglData &}zz, @code{mreal} r=@code{1}, @code{mreal} k0=@code{100})
+ at deftypefnx {Общая функция} @code{mglDataC} mglQO3dc (@code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{const mglDataA &}ray, @code{mreal} r=@code{1}, @code{mreal} k0=@code{100})
+ at deftypefnx {Общая функция} @code{mglDataC} mglQO3dc (@code{const char *}ham, @code{const mglDataA &}ini_re, @code{const mglDataA &}ini_im, @code{const mglDataA &}ray, @code{mglData &}xx, @code{mglData &}yy, @code{mglData &}zz, @code{mreal} r=@code{1}, @code{mreal} k0=@code{100})
+ at deftypefnx {Функция С} @code{HMDT} mgl_qo3d_solve (@code{const char *}ham, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{HCDT} ray, @code{mreal} r, @code{mreal} k0, @code{HMDT} xx, @code{HMDT} yy, @code{HMDT} zz)
+ at deftypefnx {Функция С} @code{HADT} mgl_qo3d_solve_c (@code{const char *}ham, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{HCDT} ray, @code{mreal} r, @code{mreal} k0, @code{HMDT} xx, @code{HMDT} yy, @code{HMDT} zz)
+ at deftypefnx {Функция С} @code{HMDT} mgl_qo3d_func (@code{dual (*}ham at code{)(mreal u, mreal x, mreal y, mreal z, mreal px, mreal py, mreal pz, void *par)}, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{HCDT} ray, @code{mreal} r, @code{mreal} k0, @code{HMDT} xx, @code{HMDT} yy, @code{HMDT} zz)
+ at deftypefnx {Функция С} @code{HADT} mgl_qo3d_func_c (@code{dual (*}ham at code{)(mreal u, mreal x, mreal y, mreal z, mreal px, mreal py, mreal pz, void *par)}, @code{HCDT} ini_re, @code{HCDT} ini_im, @code{HCDT} ray, @code{mreal} r, @code{mreal} k0, @code{HMDT} xx, @code{HMDT} yy, @code{HMDT} zz)
+ at end ifclear
+Решает уравнение в частных производных du/dt = i*k0*@var{ham}(p,q,v,x,y,z,|u|)[u] в сопровождающей системе координат, где p=-i/k0*d/dx, q=-i/k0*d/dy, v=-i/k0*d/dz -- псевдо-дифференциальные операторы. Параметры @var{ini_re}, @var{ini_im} задают начальное распределение поля. Параметр @var{ray} задает опорный луч для сопровождающей системы координат. Можно использовать луч найденный с помощью @ref{ray}. Опорный луч должен быть достаточно гладкий, чтобы система координат была однозначной и  [...]
+ at end deftypefn
+
+ at anchor{jacobian}
+ at deftypefn {Команда MGL} {} jacobian @sc{res} xdat ydat [zdat]
+ at ifclear UDAV
+ at deftypefnx {Общая функция} @code{mglData} mglJacobian (@code{const mglDataA &}x, @code{const mglDataA &}y)
+ at deftypefnx {Общая функция} @code{mglData} mglJacobian (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z)
+ at deftypefnx {Функция С} @code{HMDT} mgl_jacobian_2d (@code{HCDT} x, @code{HCDT} y)
+ at deftypefnx {Функция С} @code{HMDT} mgl_jacobian_3d (@code{HCDT} x, @code{HCDT} y, @code{HCDT} z)
+ at end ifclear
+Вычисляет якобиан преобразования @{i,j,k@} в @{@var{x}, at var{y}, at var{z}@}, где координаты @{i,j,k@} полагаются нормированными в интервал [0,1]. Якобиан находится по формуле det||@math{dr_\alpha/d\xi_\beta}||, где @math{r}=@{@var{x}, at var{y}, at var{z}@} и @math{\xi}=@{i,j,k@}. Все размерности всех массивов должны быть одинаковы. Данные должны быть трехмерными если указаны все 3 массива @{@var{x}, at var{y}, at var{z}@} или двумерными если только 2 массива @{@var{x}, at var{y}@}.
+ at end deftypefn
+
+ at anchor{triangulation}
+ at deftypefn {Команда MGL} {} triangulation @sc{res} xdat ydat [zdat]
+ at c @deftypefn {Команда MGL} {} triangulation @sc{res} xdat ydat [zdat]
+ at ifclear UDAV
+ at deftypefnx {Общая функция} @code{mglData} mglTriangulation (@code{const mglDataA &}x, @code{const mglDataA &}y)
+ at deftypefnx {Общая функция} @code{mglData} mglTriangulation (@code{const mglDataA &}x, @code{const mglDataA &}y, @code{const mglDataA &}z)
+ at deftypefnx {Функция С} @code{HMDT} mgl_triangulation_2d (@code{HCDT} x, @code{HCDT} y)
+ at deftypefnx {Функция С} @code{HMDT} mgl_triangulation_3d (@code{HCDT} x, @code{HCDT} y, @code{HCDT} z)
+ at end ifclear
+Выполняет триангуляцию для произвольно расположенных точек с координатами @{@var{x}, at var{y}, at var{z}@} (т.е. находит треугольники, соединяющие точки). Первая размерность всех массивов должна быть одинакова @code{x.nx=y.nx=z.nx}. Получившийся массив можно использовать в @ref{triplot} или @ref{tricont} для визуализации реконструированной поверхности. @sref{Making regular data}
+ at end deftypefn
+
+
+ at ifclear UDAV
+
+ at deftypefn {Общая функция} @code{mglData} mglGSplineInit (@code{const mglDataA &}x, @code{const mglDataA &}y)
+ at deftypefnx {Общая функция} @code{mglDataC} mglGSplineCInit (@code{const mglDataA &}x, @code{const mglDataA &}y)
+ at deftypefnx {Функция С} @code{HMDT} mgl_gspline_init (@code{HCDT} x, @code{HCDT} y)
+ at deftypefnx {Функция С} @code{HADT} mgl_gsplinec_init (@code{HCDT} x, @code{HCDT} y)
+Подготавливает коэффициенты для глобального кубического сплайна.
+ at end deftypefn
+
+ at deftypefn {Общая функция} @code{mreal} mglGSpline (@code{const mglDataA &}coef, @code{mreal} dx, @code{mreal *}d1=@code{0}, @code{mreal *}d2=@code{0})
+ at deftypefnx {Общая функция} @code{dual} mglGSplineC (@code{const mglDataA &}coef, @code{mreal} dx, @code{dual *}d1=@code{0}, @code{dual *}d2=@code{0})
+ at deftypefnx {Функция С} @code{mreal} mgl_gspline (@code{HCDT} coef, @code{mreal} dx, @code{mreal *}d1, @code{mreal *}d2)
+ at deftypefnx {Функция С} @code{dual} mgl_gsplinec (@code{HCDT} coef, @code{mreal} dx, @code{dual *}d1, @code{dual *}d2)
+Вычисляет глобальный кубический сплайн (а также 1ую и 2ую производные @var{d1}, @var{d2} если они не @code{NULL}), используя коэффициенты @var{coef} в точке @var{dx}+ at var{x0} (здесь @var{x0} -- 1ый элемент массива @var{x} в функции @code{mglGSpline*Init()}).
+ at end deftypefn
+
+ at end ifclear
+
+ at anchor{ifs2d}
+ at deftypefn {Команда MGL} {} ifs2d @sc{res} dat @code{num} [@code{skip=20}]
+ at ifclear UDAV
+ at deftypefnx {Общая функция} @code{mglData} mglIFS2d (@code{const mglDataA &}dat, @code{long} num, @code{long} skip=@code{20})
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_ifs_2d (@code{HCDT} dat, @code{long} num, @code{long} skip)
+ at end ifclear
+Находит @var{num} точек @{x[i]=res[0,i], y[i]=res[1,i]@} фрактала с использованием итерационной системы функций (IFS). Матрица @var{dat} используется для генерации в соответствии с формулами
+ at verbatim
+x[i+1] = dat[0,i]*x[i] + dat[1,i]*y[i] + dat[4,i];
+y[i+1] = dat[2,i]*x[i] + dat[3,i]*y[i] + dat[5,i];
+ at end verbatim
+Значение @code{dat[6,i]} -- весовой коэффициент для i-ой строки матрицы @var{dat}. Первые @var{skip} итераций будут опущены. Массив @var{dat} должен иметь размер по x больше или равный 7. @sref{Fractal sample}
+ at end deftypefn
+
+ at anchor{ifs3d}
+ at deftypefn {Команда MGL} {} ifs3d @sc{res} dat @code{num} [@code{skip=20}]
+ at ifclear UDAV
+ at deftypefnx {Общая функция} @code{mglData} mglIFS3d (@code{const mglDataA &}dat, @code{long} num, @code{long} skip=@code{20})
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_ifs_3d (@code{HCDT} dat, @code{long} num, @code{long} skip)
+ at end ifclear
+Находит @var{num} точек @{x[i]=res[0,i], y[i]=res[1,i], z[i]=res[2,i]@} фрактала с использованием итерационной системы функций (IFS). Матрица @var{dat} используется для генерации в соответствии с формулами
+ at verbatim
+x[i+1] = dat[0,i]*x[i] + dat[1,i]*y[i] + dat[2,i]*z[i] + dat[9,i];
+y[i+1] = dat[3,i]*x[i] + dat[4,i]*y[i] + dat[5,i]*z[i] + dat[10,i];
+z[i+1] = dat[6,i]*x[i] + dat[7,i]*y[i] + dat[8,i]*z[i] + dat[11,i];
+ at end verbatim
+Значение @code{dat[12,i]} -- весовой коэффициент для i-ой строки матрицы @var{dat}. Первые @var{skip} итераций будут опущены. Массив @var{dat} должен иметь размер по x больше или равный 13. @sref{Fractal sample}
+ at end deftypefn
+
+ at anchor{ifsfile}
+ at deftypefn {Команда MGL} {} ifsfile @sc{res} 'fname' 'name' @code{num} [@code{skip=20}]
+ at ifclear UDAV
+ at deftypefnx {Общая функция} @code{mglData} mglIFSfile (@code{const char *}fname, @code{const char *}name, @code{long} num, @code{long} skip=@code{20})
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_ifs_file (@code{const char *}fname, @code{const char *}name, @code{long} num, @code{long} skip)
+ at end ifclear
+Считывает параметры фрактала @var{name} из файла @var{fname} и находит @var{num} точек для него. Первые @var{skip} итераций будут опущены. См. также @ref{ifs2d}, @ref{ifs3d}.
+
+Файл IFS может содержать несколько записей. Каждая запись содержит имя фрактала (@samp{binary} в примере ниже) и тело в фигурных скобках @{@} с параметрами фрактала. Символ @samp{;} начинает комментарий. Если имя содержит @samp{(3D)} или @samp{(3d)}, то определен 3d IFS фрактал. Пример содержит два фрактала: @samp{binary} -- обычный 2d фрактал, и @samp{3dfern (3D)} -- 3d фрактал.
+
+ at verbatim
+ binary
+ { ; comment allowed here
+  ; and here
+  .5  .0 .0 .5 -2.563477 -0.000003 .333333   ; also comment allowed here
+  .5  .0 .0 .5  2.436544 -0.000003 .333333
+  .0 -.5 .5 .0  4.873085  7.563492 .333333
+  }
+
+ 3dfern (3D) {
+   .00  .00 0 .0 .18 .0 0  0.0 0.00 0 0.0 0 .01
+   .85  .00 0 .0 .85 .1 0 -0.1 0.85 0 1.6 0 .85
+   .20 -.20 0 .2 .20 .0 0  0.0 0.30 0 0.8 0 .07
+  -.20  .20 0 .2 .20 .0 0  0.0 0.30 0 0.8 0 .07
+  }
+ at end verbatim
+ at end deftypefn
+
+ at anchor{flame2d}
+ at deftypefn {Команда MGL} {} flame2d @sc{res} dat func @code{num} [@code{skip=20}]
+ at ifclear UDAV
+ at deftypefnx {Общая функция} @code{mglData} mglFlame2d (@code{const mglDataA &}dat, @code{const mglDataA &}func, @code{long} num, @code{long} skip=@code{20})
+ at deftypefnx {Функция С} @code{HMDT} mgl_data_flame_2d (@code{HCDT} dat, @code{HCDT} func, @code{long} num, @code{long} skip)
+ at end ifclear
+Находит @var{num} точек @{x[i]=res[0,i], y[i]=res[1,i]@} фрактала с использованием итерационной системы функций (IFS). Массив @var{func} задает идентификатор функции (@var{func}[0,i,j]), ее вес (@var{func}[0,i,j]) и аргументы (@var{func}[2 ... 5,i,j]). Матрица @var{dat} используется для преобразования координат для аргументов функции. Результирующее преобразование имеет вид:
+ at verbatim
+xx = dat[0,i]*x[j] + dat[1,j]*y[i] + dat[4,j];
+yy = dat[2,i]*x[j] + dat[3,j]*y[i] + dat[5,j];
+x[j+1] = sum_i @var{func}[1,i,j]*@var{func}[0,i,j]_x(xx, yy; @var{func}[2,i,j],..., at var{func}[5,i,j]);
+y[j+1] = sum_i @var{func}[1,i,j]*@var{func}[0,i,j]_y(xx, yy; @var{func}[2,i,j],..., at var{func}[5,i,j]);
+ at end verbatim
+Значение @code{dat[6,i]} -- весовой коэффициент для i-ой строки матрицы @var{dat}. Первые @var{skip} итераций будут опущены. Массив @var{dat} должен иметь размер по x больше или равный 7.
+Доступные идентификаторы функций: @code{mglFlame2d_linear=0,	mglFlame2d_sinusoidal,	mglFlame2d_spherical,	mglFlame2d_swirl,		mglFlame2d_horseshoe,
+	mglFlame2d_polar,		mglFlame2d_handkerchief,mglFlame2d_heart,		mglFlame2d_disc,		mglFlame2d_spiral,
+	mglFlame2d_hyperbolic,	mglFlame2d_diamond,		mglFlame2d_ex,			mglFlame2d_julia,		mglFlame2d_bent,
+	mglFlame2d_waves,		mglFlame2d_fisheye,		mglFlame2d_popcorn,		mglFlame2d_exponential,	mglFlame2d_power,
+	mglFlame2d_cosine,		mglFlame2d_rings,		mglFlame2d_fan,			mglFlame2d_blob,		mglFlame2d_pdj,
+	mglFlame2d_fan2,		mglFlame2d_rings2,		mglFlame2d_eyefish,		mglFlame2d_bubble,		mglFlame2d_cylinder,
+	mglFlame2d_perspective,	mglFlame2d_noise,		mglFlame2d_juliaN,		mglFlame2d_juliaScope,	mglFlame2d_blur,
+	mglFlame2d_gaussian,	mglFlame2d_radialBlur,	mglFlame2d_pie,			mglFlame2d_ngon,		mglFlame2d_curl,
+	mglFlame2d_rectangles,	mglFlame2d_arch,		mglFlame2d_tangent,		mglFlame2d_square,		mglFlame2d_blade,
+	mglFlame2d_secant,		mglFlame2d_rays,		mglFlame2d_twintrian,	mglFlame2d_cross,		mglFlame2d_disc2,
+	mglFlame2d_supershape,	mglFlame2d_flower,		mglFlame2d_conic,		mglFlame2d_parabola,	mglFlame2d_bent2,
+	mglFlame2d_bipolar,		mglFlame2d_boarders,	mglFlame2d_butterfly,	mglFlame2d_cell,		mglFlame2d_cpow,
+	mglFlame2d_curve,		mglFlame2d_edisc,		mglFlame2d_elliptic,	mglFlame2d_escher,		mglFlame2d_foci,
+	mglFlame2d_lazySusan,	mglFlame2d_loonie,		mglFlame2d_preBlur,		mglFlame2d_modulus,		mglFlame2d_oscope,
+	mglFlame2d_polar2,		mglFlame2d_popcorn2,	mglFlame2d_scry,		mglFlame2d_separation,	mglFlame2d_split,
+	mglFlame2d_splits,		mglFlame2d_stripes,		mglFlame2d_wedge,		mglFlame2d_wedgeJulia,	mglFlame2d_wedgeSph,
+	mglFlame2d_whorl,		mglFlame2d_waves2,		mglFlame2d_exp,			mglFlame2d_log,			mglFlame2d_sin,
+	mglFlame2d_cos,			mglFlame2d_tan,			mglFlame2d_sec,			mglFlame2d_csc,			mglFlame2d_cot,
+	mglFlame2d_sinh,		mglFlame2d_cosh,		mglFlame2d_tanh,		mglFlame2d_sech,		mglFlame2d_csch,
+	mglFlame2d_coth,		mglFlame2d_auger,		mglFlame2d_flux.}
+Значение @code{dat[6,i]} -- весовой коэффициент для i-ой строки матрицы @var{dat}. Первые @var{skip} итераций будут опущены. Размеры массивов должны удовлетворять требованиям: @var{dat}.nx>=7, @var{func}.nx>=2 и @var{func}.nz=@var{dat}.ny. @sref{Fractal sample}
+ at end deftypefn
+
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Evaluate expression, Special data classes, Global functions, Data processing
+ at section Вычисление выражений
+ at nav{}
+
+ at ifset UDAV
+В MGL скриптах в качестве аргументов команд можно использовать произвольные формулы от существующих массивов данных и констант. Есть только 2 ограничения: формула не должна содержать пробелов (чтобы распознаваться как один аргумент), формула не может быть аргументом, который может быть пересоздан при выполнении скрипта.
+ at end ifset
+
+ at ifclear UDAV
+В MathGL есть специальные классы @code{mglExpr} и @code{mglExprC} для вычисления формул заданных строкой для действительных и комплексных чисел соответственно. Классы определены в @code{#include <mgl2/data.h>} и @code{#include <mgl2/datac.h>} соответственно. При создании класса происходит разбор формулы в древовидную структуру. А при вычислении только выполняется достаточно быстрый обход по дереву. В данный момент нет различия между верхним и нижним регистром. Если аргумент какой-либо фу [...]
+
+ at deftypefn {Конструктор класса @code{mglExpr}} @code{} mglExpr (@code{const char *}expr)
+ at deftypefnx {Конструктор класса @code{mglExprC}} @code{} mglExprC (@code{const char *}expr)
+ at deftypefnx {Функция С} @code{HMEX} mgl_create_expr (@code{const char *}expr)
+ at deftypefnx {Функция С} @code{HAEX} mgl_create_cexpr (@code{const char *}expr)
+Разбирает формулу @var{expr} и создает древовидную структуру, содержащую последовательность вызова функций и операторов для последующего быстрого вычисления формулы с помощью функций @code{Calc()} и/или @code{CalcD()}.
+ at end deftypefn
+
+ at deftypefn {Destructor on @code{mglExpr}} @code{} ~mglExpr ()
+ at deftypefnx {Destructor on @code{mglExprC}} @code{} ~mglExprC ()
+ at deftypefnx {Функция С} @code{void} mgl_delete_expr (@code{HMEX} ex)
+ at deftypefnx {Функция С} @code{void} mgl_delete_cexpr (@code{HAEX} ex)
+Удаляет объект типа @code{mglExpr}.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglExpr}} @code{mreal} Eval (@code{mreal} x, @code{mreal} y, @code{mreal} z)
+ at deftypefnx {Метод класса @code{mglExprC}} @code{dual} Eval (@code{dual} x, @code{dual} y, @code{dual} z)
+ at deftypefnx {Функция С} @code{mreal} mgl_expr_eval (@code{HMEX} ex, @code{mreal} x, @code{mreal} y, @code{mreal} z)
+ at deftypefnx {Функция С} @code{dual} mgl_cexpr_eval (@code{HAEX} ex, @code{dual} x, @code{dual} y, @code{dual} z)
+Вычисляет значение формулы для @code{'x','r'}=@var{x}, @code{'y','n'}=@var{y}, @code{'z','t'}=@var{z}, @code{'a','u'}=@var{u}.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglExpr}} @code{mreal} Eval (@code{mreal} var[26])
+ at deftypefnx {Метод класса @code{mglExprC}} @code{dual} Eval (@code{dual} var[26])
+ at deftypefnx {Функция С} @code{mreal} mgl_expr_eval_v (@code{HMEX} ex, @code{mreal *}var)
+ at deftypefnx {Функция С} @code{dual} mgl_cexpr_eval_v (@code{HMEX} ex, @code{dual *}var)
+Вычисляет значение формулы для переменных в массиве @var{var}[0,...,'z'-'a'].
+ at end deftypefn
+
+
+ at deftypefn {Метод класса @code{mglExpr}} @code{mreal} Diff (@code{char} dir, @code{mreal} x, @code{mreal} y, @code{mreal} z)
+ at deftypefnx {Функция С} @code{mreal} mgl_expr_diff (@code{HMEX} ex, @code{char} dir, @code{mreal} x, @code{mreal} y, @code{mreal} z)
+Вычисляет производную от формулы по переменной @var{dir} для @code{'x','r'}=@var{x}, @code{'y','n'}=@var{y}, @code{'z','t'}=@var{z}, @code{'a','u'}=@var{u}.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglExpr}} @code{mreal} Diff (@code{char} dir, @code{mreal} var[26])
+ at deftypefnx {Функция С} @code{mreal} mgl_expr_diff_v (@code{HMEX} ex, @code{char} dir, @code{mreal *}var)
+Вычисляет производную от формулы по переменной @var{dir} для переменных в массиве @var{var}[0,...,'z'-'a'].
+ at end deftypefn
+
+ at end ifclear
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Special data classes, , Evaluate expression, Data processing
+ at section Special data classes
+ at nav{}
+
+ at ifset UDAV
+MGL использует специальные классы автоматически.
+ at end ifset
+
+ at ifclear UDAV
+Раздел описывает специальные классы данных @code{mglDataV}, @code{mglDataF}, @code{mglDataT} и @code{mglDataR}, которые могут заметно ускорить рисование и обработку данных. Классы определены в @code{#include <mgl2/data.h>}. Отмечу, что все функции рисования и обработки данных можно выполнить используя только основные классы @code{mglData} и/или @code{mglDataC}. Также специальные классы доступны только в коде на С++.
+
+ at heading Класс @code{mglDataV}
+представляет переменную со значениями равнораспределенными в заданном интервале.
+ at deftypefn {Конструктор @code{mglDataV}} @code{} mglDataV (@code{const mglDataV &} d)
+Конструктор копирования.
+ at end deftypefn
+ at deftypefn {Конструктор @code{mglDataV}} @code{} mglDataV (@code{long} nx=@code{1}, @code{long} ny=@code{1}, @code{long} nz=@code{1}, @code{mreal} v1=@code{0}, @code{mreal} v2=@code{NaN}, @code{char} dir=@code{'x'})
+Создает переменную "размером" @var{nx}x at var{ny}x at var{nz}, изменяющуюся от @var{v1} до @var{v2} (или постоянную при @var{v2}=@code{NaN}) вдоль направления @var{dir}.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglDataV}} @code{void} Create (@code{long} nx=@code{1}, @code{long} ny=@code{1}, @code{long} nz=@code{1})
+Задает "размеры" переменной @var{nx}x at var{ny}x at var{nz}.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglDataV}} @code{void} Fill (@code{mreal} x1, @code{mreal} x2=@code{NaN}, @code{char} dir=@code{'x'})
+Задает диапазон изменения переменной.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglDataV}} @code{void} Freq (@code{mreal} dp, @code{char} dir=@code{'x'})
+Задает переменную для частоты с шагом @var{dp}.
+ at end deftypefn
+
+ at heading Класс @code{mglDataF}
+представляет функцию, которая будет вызываться вместо обращения к элементам массива (как в классе @code{mglData}).
+ at deftypefn {Конструктор @code{mglDataF}} @code{} mglDataF (@code{const mglDataF &} d)
+Конструктор копирования.
+ at end deftypefn
+ at deftypefn {Конструктор @code{mglDataF}} @code{} mglDataF (@code{long} nx=@code{1}, @code{long} ny=@code{1}, @code{long} nz=@code{1})
+Создает данные "размером" @var{nx}x at var{ny}x at var{nz} с нулевой функцией.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglDataF}} @code{void} Create (@code{long} nx=@code{1}, @code{long} ny=@code{1}, @code{long} nz=@code{1})
+Задает "размеры" данных @var{nx}x at var{ny}x at var{nz}.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglDataF}} @code{void} SetRanges (@code{mglPoint} p1, @code{mglPoint} p2)
+Задает диапазоны изменения внутренних переменных x,y,z.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglDataF}} @code{void} SetFormula (@code{const char *}func)
+Задает строку, которая будет разобрана в функцию. Это вариант более чем 10 раз медленнее в сравнении с @code{SetFunc}().
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglDataF}} @code{void} SetFunc (@code{mreal (*}f at code{)(mreal x,mreal y,mreal z,void *p)}, @code{void *}p=@code{NULL})
+Задает указатель на функцию, которая будет использована вместо доступа к элементам массива.
+ at end deftypefn
+
+ at heading Класс @code{mglDataT}
+представляет именнованную ссылку на столбец в другом массиве данных.
+ at deftypefn {Конструктор @code{mglDataT}} @code{} mglDataT (@code{const mglDataT &} d)
+Конструктор копирования.
+ at end deftypefn
+ at deftypefn {Конструктор @code{mglDataT}} @code{} mglDataT (@code{const mglDataA &} d, @code{long} col=@code{0})
+Создает ссылку на @var{col}-ый столбец данных @var{d}.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglDataT}} @code{void} SetInd (@code{long} col, @code{wchar_t} name)
+ at deftypefnx {Метод класса @code{mglDataT}} @code{void} SetInd (@code{long} col, @code{const wchar_t *} name)
+Задает ссылку на другой столбец того же массива данных.
+ at end deftypefn
+
+
+ at heading Класс @code{mglDataR}
+представляет именнованную ссылку на строку в другом массиве данных.
+ at deftypefn {Конструктор @code{mglDataR}} @code{} mglDataR (@code{const mglDataR &} d)
+Конструктор копирования.
+ at end deftypefn
+ at deftypefn {Конструктор @code{mglDataR}} @code{} mglDataR (@code{const mglDataA &} d, @code{long} row=@code{0})
+Создает ссылку на @var{row}-ую строку данных @var{d}.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglDataR}} @code{void} SetInd (@code{long} row, @code{wchar_t} name)
+ at deftypefnx {Метод класса @code{mglDataR}} @code{void} SetInd (@code{long} row, @code{const wchar_t *} name)
+Задает ссылку на другой столбец того же массива данных.
+ at end deftypefn
+
+
+ at heading Class @code{mglDataW}
+представляет часоту для FFT в виде массива данных.
+ at deftypefn {Конструктор @code{mglDataW}} @code{} mglDataW (@code{const mglDataW &} d)
+Конструктор копирования.
+ at end deftypefn
+ at deftypefn {Конструктор @code{mglDataW}} @code{} mglDataW (@code{long} xx=@code{1}, @code{long} yy=@code{1}, @code{long} zz=@code{1}, @code{double} dp=@code{0}, @code{char} dir=@code{'x'})
+Задает размеры, направление @var{dir} и шаг @var{dp} для частоты.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglDataR}} @code{void} Freq (@code{double} dp, @code{char} dir=@code{'x'})
+Равномерно распределяет данные с шагом @var{dp} в направлении @var{dir}.
+ at end deftypefn
+
+
+ at heading Class @code{mglDataS}
+представляет std::vector в виде массива данных.
+ at deftypecv {Variable} mglDataS @code{std::vector<mreal>} dat
+Собственно данные.
+ at end deftypecv
+ at deftypefn {Конструктор @code{mglDataS}} @code{} mglDataS (@code{const mglDataS &} d)
+Конструктор копирования.
+ at end deftypefn
+ at deftypefn {Конструктор @code{mglDataS}} @code{} mglDataS (@code{const std::vector<mreal> &} d)
+Копирует данные из @var{d}.
+ at end deftypefn
+ at deftypefn {Конструктор @code{mglDataS}} @code{} mglDataS (@code{size_t} s)
+Выделяет память для @var{s} элементов.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglDataS}} @code{void} reserve (@code{size_t} num)
+Резервирует место для @var{num} элементов.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglDataS}} @code{void} push_back (@code{double} v)
+Добавляет значение @var{v} к концу массива данных.
+ at end deftypefn
+
+
+ at end ifclear
+
+ at external{}
diff --git a/texinfo/datadvance.png b/texinfo/datadvance.png
new file mode 100644
index 0000000..72b95be
Binary files /dev/null and b/texinfo/datadvance.png differ
diff --git a/texinfo/doc_en.texi b/texinfo/doc_en.texi
new file mode 100644
index 0000000..4cf17a0
--- /dev/null
+++ b/texinfo/doc_en.texi
@@ -0,0 +1,215 @@
+\input texinfo
+ at documentencoding UTF-8
+ at documentlanguage en
+
+ at setfilename mathgl_en.info
+ at include version.texi
+ at settitle MathGL @value{VERSION}
+ at syncodeindex pg cp
+ at comment %**end of header
+
+ at copying
+This manual is for MathGL (version @value{VERSION}), a collection of classes and routines for scientific plotting. Please report any errors in this manual to @email{mathgl.abalakin@@gmail.org}.
+
+ at include copyright.texi
+ at end copying
+
+ at dircategory MathGL documentation system
+ at direntry
+* MathGL: (mathgl). The library for scientific graphics.
+ at end direntry
+
+ at titlepage
+ at title MathGL
+ at subtitle for version @value{VERSION}
+ at author A.A. Balakin (@uref{http://mathgl.sourceforge.net/})
+ at page
+ at vskip 0pt plus 1filll
+ at insertcopying
+ at end titlepage
+
+ at contents
+
+ at node Top
+ at top MathGL
+
+This file documents the Mathematical Graphic Library (MathGL), a collection of classes and routines for scientific plotting. It corresponds to release @value{VERSION} of the library. Please report any errors in this manual to @email{mathgl.abalakin@@gmail.org}. More information about MathGL can be found at the project homepage, @uref{http://mathgl.sourceforge.net/}.
+
+ at include copyright.texi
+
+ at menu
+* Website::
+* Overview::
+* Examples::
+* General concepts::
+* MathGL core::
+* Widget classes::
+* Data processing::
+* MGL scripts::
+* UDAV::
+* Other classes::
+* Symbols and hot-keys::
+* File formats::
+* TeX-like symbols::
+* Plotting time::
+* Copying This Manual::
+* Index::
+ at end menu
+
+ at macro nav {}
+ at html
+<nav style="float:right;border:1px solid black;padding:3px;margin-left:7px">
+ at end html
+@ @ @ref{Main, Main page}@*
+@ @ @ref{News}@*
+@ @ @ref{Pictures}@*
+@ @ @ref{Download}@*
+ at comment @ @ @ref{Download}
+
+ at html
+<table style="background-color: #fff; padding: 5px;" cellspacing=0>
+<tr><td><img src="http://groups.google.com/intl/en/images/logos/groups_logo_sm.gif" height=25 width=117 alt="Google Groups"></td></tr>
+<tr><td style="padding-left: 5px;font-size: 110%"> <a target=_blank href="http://groups.google.com/group/mathgl"><b>MathGL</b></a> </td></tr>
+</table>
+
+<hr style="width: 100%; height: 1px;">
+<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
+<!-- 160x600, Vertical -->
+<ins class="adsbygoogle"
+     style="display:inline-block;width:160px;height:600px"
+     data-ad-client="ca-pub-1128070552722622"
+     data-ad-slot="2695178987"></ins>
+<script>
+(adsbygoogle = window.adsbygoogle || []).push({});
+</script>
+</nav>
+ at end html
+ at end macro
+
+ at macro external {}
+ at html
+<br><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
+<!-- Ref 728x15 -->
+<ins class="adsbygoogle"
+     style="display:inline-block;width:728px;height:15px"
+     data-ad-client="ca-pub-1128070552722622"
+     data-ad-slot="7008431385"></ins>
+<script>
+(adsbygoogle = window.adsbygoogle || []).push({});
+</script><br>
+ at comment
+<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
+<!-- 728x90, Horizontal -->
+<ins class="adsbygoogle"
+     style="display:inline-block;width:728px;height:90px"
+     data-ad-client="ca-pub-1128070552722622"
+     data-ad-slot="9958083480"></ins>
+<script>
+(adsbygoogle = window.adsbygoogle || []).push({});
+</script><br/>
+<footer>
+<!--LiveInternet counter--><script type="text/javascript"><!--
+document.write("<a href='http://www.liveinternet.ru/click' "+
+"target=_blank><img src='http://counter.yadro.ru/hit?t12.2;r"+
+escape(document.referrer)+((typeof(screen)=="undefined")?"":
+";s"+screen.width+"*"+screen.height+"*"+(screen.colorDepth?
+screen.colorDepth:screen.pixelDepth))+";u"+escape(document.URL)+
+";"+Math.random()+
+"' alt='' title='LiveInternet: number of views during 24"+
+" hours, number of visitors during 24 hours and during today' "+
+"border=0 width=88 height=31><\/a>")//--></script><!--/LiveInternet-->
+
+<a target=_blank href="http://sourceforge.net"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=152187&type=2" alt="SourceForge.net Logo" border="0" height="37" width="125"></a>
+
+<a target=_blank href="http://www.thefreecountry.com/"> <img src="http://www.thefreecountry.com/images/tfc88x31green.gif" alt="thefreecountry.com: Free Programmers' Resources, Free Webmasters' Resources, Free Security Resources, Free Software" border="0" height="31" width="88"></a>
+
+<a target=_blank href="http://sourceforge.net/donate/index.php?group_id=152187"><img src="http://images.sourceforge.net/images/project-support.jpg" width="88" height="32" border="0" alt="Support This Project" /> </a>
+</footer>
+ at end html
+ at end macro
+
+ at macro fig {fname,text}
+ at center @image{../\fname\, 11cm, , \text\, png}
+ at end macro
+ at macro pfig {fname,text}
+ at center @uref{../pdf/\fname\.pdf, @image{../png/\fname\, 11cm, , \text\, png}}
+ at c @center @image{../png/\fname\, 11cm, , \text\. See also @uref{../pdf/\fname\.pdf, 3D PDF} sample, .png}
+ at end macro
+ at macro ufig {fname,width,text}
+ at center @image{../udav/\fname\, \width\cm, , \text\, png}
+ at end macro
+ at macro sfig {plot,text}
+ at ref{\text\, @image{../small/\plot\-sm,3cm, , , png}}
+ at end macro
+
+
+ at macro sref {arg}
+ at xref{\arg\}, for sample code and picture.
+ at end macro
+
+ at node Website, Overview, , Top
+ at include web_en.texi
+
+ at node Overview, Examples, Website, Top
+ at include overview_en.texi
+
+ at node Examples, General concepts, Overview, Top
+ at include example_en.texi
+
+ at node General concepts, MathGL core, Examples, Top
+ at include concept_en.texi
+
+ at node MathGL core, Widget classes, General concepts, Top
+ at include core_en.texi
+
+ at node Widget classes, Data processing, MathGL core, Top
+ at include widget_en.texi
+
+ at node Data processing, MGL scripts, Widget classes, Top
+ at include data_en.texi
+
+ at node MGL scripts, UDAV, Data processing, Top
+ at include parse_en.texi
+
+ at node UDAV, Other classes, MGL scripts, Top
+ at include udav_en.texi
+
+ at node Other classes, Symbols and hot-keys, UDAV, Top
+ at include other_en.texi
+
+ at node Symbols and hot-keys, File formats, Other classes, Top
+ at appendix Symbols and hot-keys
+ at include symbols_en.texi
+
+ at node File formats, TeX-like symbols, Symbols and hot-keys, Top
+ at appendix File formats
+ at include formats_en.texi
+
+ at node TeX-like symbols, Plotting time, File formats, Top
+ at appendix TeX-like symbols
+ at include appendix_en.texi
+
+ at node Plotting time, Copying This Manual, TeX-like symbols, Top
+ at appendix Plotting time
+ at nav{}
+
+Table below show plotting time in seconds for all samples in file @uref{http://sourceforge.net/p/mathgl/code/HEAD/tree/mathgl-2x/examples/samples.cpp, examples/samples.cpp}. The test was done in my laptop (i5-2430M) with 64-bit Debian.
+
+Few words about the speed. Firstly, direct bitmap drawing (Quality=4,5,6) is faster than buffered one (Quality=0,1,2), but sometimes it give incorrect result (see @ref{cloud}) and don't allow to export in vector or 3d formats (like EPS, SVG, PDF ...). Secondly, lower quality is faster than high one generally, i.e. Quality=1 is faster than Quality=2, and Quality=0 is faster than Quality=1. However, if plot contain a lot of faces (like @ref{cloud}, @ref{surf3}, @ref{pipe}, @ref{dew}) then  [...]
+
+Results for image size 800*600 (default one).
+ at include time.texi
+
+Results for image size 1920*1440 (print quality)
+ at include time_big.texi
+
+ at node Copying This Manual, Index, Plotting time, Top
+ at appendix GNU Free Documentation License
+ at include fdl.texi
+
+ at node Index, , Copying This Manual, Top
+ at unnumbered Index
+
+ at printindex cp
+
+ at bye
diff --git a/texinfo/doc_ru.texi b/texinfo/doc_ru.texi
new file mode 100644
index 0000000..a1309b8
--- /dev/null
+++ b/texinfo/doc_ru.texi
@@ -0,0 +1,217 @@
+\input texinfo
+ at documentencoding UTF-8
+ at documentlanguage ru
+
+ at setfilename mathgl_en.info
+ at include version.texi
+ at settitle MathGL @value{VERSION}
+ at syncodeindex pg cp
+ at comment %**end of header
+
+ at copying
+This manual is for MathGL (version @value{VERSION}), a collection of classes and routines for scientific plotting. Please report any errors in this manual to @email{mathgl.abalakin@@gmail.org}.
+
+ at include copyright.texi
+ at end copying
+
+ at dircategory MathGL documentation system
+ at direntry
+* MathGL: (mathgl). The library for scientific graphics.
+ at end direntry
+
+ at titlepage
+ at title MathGL
+ at subtitle for version @value{VERSION}
+ at author A.A. Balakin (@uref{http://mathgl.sourceforge.net/})
+ at page
+ at vskip 0pt plus 1filll
+ at insertcopying
+ at end titlepage
+
+ at contents
+
+ at ifnottex
+ at node Top
+ at top MathGL
+
+This file documents the Mathematical Graphic Library (MathGL), a collection of classes and routines for scientific plotting. It corresponds to release @value{VERSION} of the library. Please report any errors in this manual to @email{mathgl.abalakin@@gmail.org}. More information about MathGL can be found at the project homepage, @uref{http://mathgl.sourceforge.net/}.
+
+ at include copyright.texi
+
+ at end ifnottex
+
+ at menu
+* Website::
+* Overview::
+* Examples::
+* General concepts::
+* MathGL core::
+* Widget classes::
+* Data processing::
+* MGL scripts::
+* UDAV ::
+* Other classes::
+* Symbols and hot-keys::
+* File formats::
+* TeX-like symbols::
+* Plotting time::
+* Copying This Manual::
+* Index::
+ at end menu
+
+ at macro nav {}
+ at html
+<nav style="float:right;border:1px solid black;padding:3px;margin-left:7px">
+ at end html
+@ @ @ref{Main, Main page}@*
+@ @ @ref{News}@*
+@ @ @ref{Pictures}@*
+@ @ @ref{Download}@*
+ at comment @ @ @ref{Download}
+
+ at html
+<table style="background-color: #fff; padding: 5px;" cellspacing=0>
+<tr><td><img src="http://groups.google.com/intl/en/images/logos/groups_logo_sm.gif" height=25 width=117 alt="Google Groups"></td></tr>
+<tr><td style="padding-left: 5px;font-size: 110%"> <a target=_blank href="http://groups.google.com/group/mathgl"><b>MathGL</b></a> </td></tr>
+</table>
+
+<hr style="width: 100%; height: 1px;">
+<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
+<!-- 160x600, Vertical -->
+<ins class="adsbygoogle"
+     style="display:inline-block;width:160px;height:600px"
+     data-ad-client="ca-pub-1128070552722622"
+     data-ad-slot="2695178987"></ins>
+<script>
+(adsbygoogle = window.adsbygoogle || []).push({});
+</script>
+</nav>
+ at end html
+ at end macro
+
+ at macro external {}
+ at html
+<br><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
+<!-- Ref 728x15 -->
+<ins class="adsbygoogle"
+     style="display:inline-block;width:728px;height:15px"
+     data-ad-client="ca-pub-1128070552722622"
+     data-ad-slot="7008431385"></ins>
+<script>
+(adsbygoogle = window.adsbygoogle || []).push({});
+</script><br>
+ at comment
+<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
+<!-- 728x90, Horizontal -->
+<ins class="adsbygoogle"
+     style="display:inline-block;width:728px;height:90px"
+     data-ad-client="ca-pub-1128070552722622"
+     data-ad-slot="9958083480"></ins>
+<script>
+(adsbygoogle = window.adsbygoogle || []).push({});
+</script><br/>
+<footer>
+<!--LiveInternet counter--><script type="text/javascript"><!--
+document.write("<a href='http://www.liveinternet.ru/click' "+
+"target=_blank><img src='http://counter.yadro.ru/hit?t12.2;r"+
+escape(document.referrer)+((typeof(screen)=="undefined")?"":
+";s"+screen.width+"*"+screen.height+"*"+(screen.colorDepth?
+screen.colorDepth:screen.pixelDepth))+";u"+escape(document.URL)+
+";"+Math.random()+
+"' alt='' title='LiveInternet: number of views during 24"+
+" hours, number of visitors during 24 hours and during today' "+
+"border=0 width=88 height=31><\/a>")//--></script><!--/LiveInternet-->
+
+<a target=_blank href="http://sourceforge.net"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=152187&type=2" alt="SourceForge.net Logo" border="0" height="37" width="125"></a>
+
+<a target=_blank href="http://www.thefreecountry.com/"> <img src="http://www.thefreecountry.com/images/tfc88x31green.gif" alt="thefreecountry.com: Free Programmers' Resources, Free Webmasters' Resources, Free Security Resources, Free Software" border="0" height="31" width="88"></a>
+
+<a target=_blank href="http://sourceforge.net/donate/index.php?group_id=152187"><img src="http://images.sourceforge.net/images/project-support.jpg" width="88" height="32" border="0" alt="Support This Project" /> </a>
+</footer>
+ at end html
+ at end macro
+
+ at macro fig {fname,text}
+ at center @image{../\fname\, 11cm, , \text\, png}
+ at end macro
+ at macro pfig {fname,text}
+ at uref{../pdf/\fname\.pdf, @image{../png/\fname\, 11cm, , \text\, png}}
+ at c @center @image{../png/\fname\, 11cm, , \text\ См. также пример @uref{../pdf/\fname\.pdf, 3D PDF}, .png}
+ at end macro
+ at macro ufig {fname,width,text}
+ at center @image{../udav/\fname\, \width\cm, , \text\, png}
+ at end macro
+ at macro sfig {plot,text}
+ at ref{\text\, @image{../small/\plot\-sm,3cm, , , png}}
+ at end macro
+
+ at macro sref {arg}
+См. раздел @ref{\arg\}, для примеров кода и графика.
+ at end macro
+
+ at node Website, Overview, , Top
+ at include web_ru.texi
+
+ at node Overview, Examples, Website, Top
+ at include overview_ru.texi
+
+ at node Examples, General concepts, Overview, Top
+ at include example_ru.texi
+
+ at node General concepts, MathGL core, Examples, Top
+ at include concept_ru.texi
+
+ at node MathGL core, Widget classes, General concepts, Top
+ at include core_ru.texi
+
+ at node Widget classes, Data processing, MathGL core, Top
+ at include widget_ru.texi
+
+ at node Data processing, MGL scripts, Widget classes, Top
+ at include data_ru.texi
+
+ at node MGL scripts, UDAV, Data processing, Top
+ at include parse_ru.texi
+
+ at node UDAV, Other classes, MGL scripts, Top
+ at include udav_ru.texi
+
+ at node Other classes, Symbols and hot-keys, UDAV, Top
+ at include other_ru.texi
+
+ at node Symbols and hot-keys, File formats, Other classes, Top
+ at appendix Symbols and hot-keys
+ at include symbols_ru.texi
+
+ at node File formats, TeX-like symbols, Symbols and hot-keys, Top
+ at appendix File formats
+ at include formats_ru.texi
+
+ at node TeX-like symbols, Plotting time, File formats, Top
+ at appendix Символы TeX
+ at include appendix_ru.texi
+
+ at node Plotting time, Copying This Manual, TeX-like symbols, Top
+ at appendix Время отрисовки
+ at nav{}
+
+В таблице показаны времена создания графика для всех примеров из файла @uref{http://sourceforge.net/p/mathgl/code/HEAD/tree/mathgl-2x/examples/samples.cpp, examples/samples.cpp}. Тест выполнен на моем ноутбуке (i5-2430M) с 64-bit Debian.
+
+Несколько слов о скорости. Во-первых, прямое рисование в память (Quality=4,5,6) быстрее буферизованного (Quality=0,1,2), но иногда результат некоректен (см. @ref{cloud}) и пропадает возможность экспорта в векторные и 3d форматы (например, EPS, SVG, PDF, ...). Во-вторых, обычно картинка худшего качества рисуется быстрее, т.е. Quality=1 быстрее Quality=2, и Quality=0 быстрее Quality=1. Однако, если график содержит множество граней (например @ref{cloud}, @ref{surf3}, @ref{pipe}, @ref{dew}), [...]
+
+Результаты для изображения размером 800*600 (по умолчанию).
+ at include time.texi
+
+Результаты для изображения размером 1920*1440 (для печати)
+ at include time_big.texi
+
+ at node Copying This Manual, Index, Plotting time, Top
+ at appendix GNU Free Documentation License
+ at include fdl.texi
+
+ at node Index, , Copying This Manual, Top
+ at unnumbered Index
+
+ at printindex cp
+
+ at bye
diff --git a/texinfo/emblem_sm.png b/texinfo/emblem_sm.png
new file mode 100644
index 0000000..0b8a3e5
Binary files /dev/null and b/texinfo/emblem_sm.png differ
diff --git a/texinfo/ex_mgl_en.texi b/texinfo/ex_mgl_en.texi
new file mode 100644
index 0000000..2dad786
--- /dev/null
+++ b/texinfo/ex_mgl_en.texi
@@ -0,0 +1,3249 @@
+ at c ------------------------------------------------------------------
+ at chapter MathGL examples
+ at nav{}
+
+This chapter contain information about basic and advanced MathGL, hints and samples for all types of graphics. I recommend you read first 2 sections one after another and at least look on @ref{Hints} section. Also I recommend you to look at @ref{General concepts} and @ref{FAQ}.
+
+Most of sample scripts placed below use a set of functions for preparing the data.
+ at verbatim
+func 'prepare1d'
+new y 50 3
+modify y '0.7*sin(2*pi*x)+0.5*cos(3*pi*x)+0.2*sin(pi*x)'
+modify y 'sin(2*pi*x)' 1
+modify y 'cos(2*pi*x)' 2
+new x1 50 'x'
+new x2 50 '0.05-0.03*cos(pi*x)'
+new y1 50 '0.5-0.3*cos(pi*x)'
+new y2 50 '-0.3*sin(pi*x)'
+return
+
+func 'prepare2d'
+new a 50 40 '0.6*sin(pi*(x+1))*sin(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'
+new b 50 40 '0.6*cos(pi*(x+1))*cos(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'
+return
+
+func 'prepare3d'
+new c 61 50 40 '-2*(x^2+y^2+z^4-z^2)+0.2'
+new d 61 50 40 '1-2*tanh((x+y)*(x+y))'
+return
+
+func 'prepare2v'
+new a 20 30 '0.6*sin(pi*(x+1))*sin(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'
+new b 20 30 '0.6*cos(pi*(x+1))*cos(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'
+return
+
+func 'prepare3v'
+define $1 pow(x*x+y*y+(z-0.3)*(z-0.3)+0.03,1.5)
+define $2 pow(x*x+y*y+(z+0.3)*(z+0.3)+0.03,1.5)
+new ex 10 10 10 '0.2*x/$1-0.2*x/$2'
+new ey 10 10 10 '0.2*y/$1-0.2*y/$2'
+new ez 10 10 10 '0.2*(z-0.3)/$1-0.2*(z+0.3)/$2'
+return
+ at end verbatim
+Basically, you can put this text after the script. Note, that you need to terminate main script by @ref{stop} command before defining a function.
+
+ at menu
+* Basic usage::
+* Advanced usage::
+* Data handling::
+* Data plotting::
+* 1D samples::
+* 2D samples::
+* 3D samples::
+* Vector field samples::
+* Hints::
+* FAQ::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Basic usage, Advanced usage, , Examples
+ at section Basic usage
+ at nav{}
+
+MGL script can be used by several manners. Each has positive and negative sides:
+ at itemize @bullet
+ at item
+ at emph{Using UDAV.}
+
+Positive sides are possibilities to view the plot at once and to modify it, rotate, zoom or switch on transparency or lighting by hands or by mouse. Negative side is the needness of the X-terminal. @c For more details, see @ref{UDAV}.
+
+ at item
+ at emph{Using command line tools.}
+
+Positive aspects are: batch processing of similar data set, for example, a set of resulting data files for different calculation parameters), running from the console program, including the cluster calculation), fast and automated drawing, saving pictures for further analysis, or demonstration). Negative sides are: the usage of the external program for picture viewing. Also, the data plotting is non-visual. So, you have to imagine the picture, view angles, lighting and so on) before the  [...]
+
+In this case you can use the program: @code{mglconv} or @code{mglview} for viewing.
+
+ at item
+ at emph{Using C/C++/... code.}
+
+You can easily execute MGL script within C/C++/Fortan code. This can be useful for fast data plotting, for example, in web applications, where textual string (MGL script) may contain all necessary information for plot. The basic C++ code may look as following
+ at verbatim
+const char *mgl_script; // script itself, can be of type const wchar_t*
+mglGraph gr;
+mglParse pr;
+pr.Execute(&gr, mgl_script);
+ at end verbatim
+ at end itemize
+
+The simplest script is
+ at verbatim
+box         # draw bounding box
+axis        # draw axis
+fplot 'x^3' # draw some function
+ at end verbatim
+
+Just type it in UDAV and press F5. Also you can save it in text file @samp{test.mgl} and type in the console @code{mglconv test.mgl} what produce file @samp{test.mgl.png} with resulting picture.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Advanced usage, Data handling, Basic usage, Examples
+ at section Advanced usage
+ at nav{}
+
+Now I show several non-obvious features of MGL: several subplots in a single picture, curvilinear coordinates, text printing and so on. Generally you may miss this section at first reading, but I don't recommend it.
+
+ at menu
+* Subplots::
+* Axis and ticks::
+* Curvilinear coordinates::
+* Colorbars::
+* Bounding box::
+* Ternary axis::
+* Text features::
+* Legend sample::
+* Cutting sample::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Subplots, Axis and ticks, , Advanced usage
+ at subsection Subplots
+ at nav{}
+
+Let me demonstrate possibilities of plot positioning and rotation. MathGL has a set of functions: @ref{subplot}, @ref{inplot}, @ref{title}, @ref{aspect} and @ref{rotate} and so on (see @ref{Subplots and rotation}). The order of their calling is strictly determined. First, one changes the position of plot in image area (functions @ref{subplot}, @ref{inplot} and @ref{multiplot}). Secondly, you can add the title of plot by @ref{title} function. After that one may rotate the plot (command @r [...]
+ at verbatim
+subplot 2 2 0
+box:text -1 1.1 'Just box' ':L'
+inplot 0.2 0.5 0.7 1 off
+box:text 0 1.2 'InPlot example'
+
+subplot 2 2 1:title 'Rotate only'
+rotate 50 60:box
+
+subplot 2 2 2:title 'Rotate and Aspect'
+rotate 50 60:aspect 1 1 2:box
+
+subplot 2 2 3:title 'Shear'
+box 'c':shear 0.2 0.1:box
+ at end verbatim
+Here I used function @code{Puts} for printing the text in arbitrary position of picture (see @ref{Text printing}). Text coordinates and size are connected with axes. However, text coordinates may be everywhere, including the outside the bounding box. I'll show its features later in @ref{Text features}.
+
+Note that several commands can be placed in a string if they are separated by @samp{:} symbol.
+
+ at pfig{aspect, Example of several subplots on the single picture.}
+
+More complicated sample show how to use most of positioning functions:
+ at verbatim
+subplot 3 2 0:title 'StickPlot'
+stickplot 3 0 20 30:box 'r':text 0 0 0 '0' 'r'
+stickplot 3 1 20 30:box 'g':text 0 0 0 '1' 'g'
+stickplot 3 2 20 30:box 'b':text 0 0 0 '2' 'b'
+
+subplot 3 2 3 '':title 'ColumnPlot'
+columnplot 3 0:box 'r':text 0 0 '0' 'r'
+columnplot 3 1:box 'g':text 0 0 '1' 'g'
+columnplot 3 2:box 'b':text 0 0 '2' 'b'
+
+subplot 3 2 4 '':title 'GridPlot'
+gridplot 2 2 0:box 'r':text 0 0 '0' 'r'
+gridplot 2 2 1:box 'g':text 0 0 '1' 'g'
+gridplot 2 2 2:box 'b':text 0 0 '2' 'b'
+gridplot 2 2 3:box 'm':text 0 0 '3' 'm'
+
+subplot 3 2 5 '':title 'InPlot':box
+inplot 0.4 1 0.6 1 on:box 'r'
+
+multiplot 3 2 1 2 1 '':title 'MultiPlot and ShearPlot':box
+shearplot 3 0 0.2 0.1:box 'r':text 0 0 '0' 'r'
+shearplot 3 1 0.2 0.1:box 'g':text 0 0 '1' 'g'
+shearplot 3 2 0.2 0.1:box 'b':text 0 0 '2' 'b'
+ at end verbatim
+
+ at pfig{inplot, Example for most of positioning functions.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Axis and ticks, Curvilinear coordinates, Subplots, Advanced usage
+ at subsection Axis and ticks
+ at nav{}
+
+MathGL library can draw not only the bounding box but also the axes, grids, labels and so on. The ranges of axes and their origin (the point of intersection) are determined by functions @code{SetRange()}, @code{SetRanges()}, @code{SetOrigin()} (see @ref{Ranges (bounding box)}). Ticks on axis are specified by function @code{SetTicks}, @code{SetTicksVal}, @code{SetTicksTime} (see @ref{Ticks}). But usually
+
+Command @ref{axis} draws axes. Its textual string shows in which directions the axis or axes will be drawn (by default @code{"xyz"}, function draws axes in all directions). Command @ref{grid} draws grid perpendicularly to specified directions. Example of axes and grid drawing is:
+ at verbatim
+subplot 2 2 0:title 'Axis origin, Grid'
+origin 0 0:axis:grid:fplot 'x^3'
+
+subplot 2 2 1:title '2 axis'
+ranges -1 1 -1 1:origin -1 -1:axis
+ylabel 'axis_1':fplot 'sin(pi*x)' 'r2'
+ranges 0 1 0 1:origin 1 1:axis
+ylabel 'axis_2':fplot 'cos(pi*x)'
+
+subplot 2 2 3:title 'More axis'
+origin nan nan:xrange -1 1:axis
+xlabel 'x' 0:ylabel 'y_1' 0:fplot 'x^2' 'k'
+yrange -1 1:origin -1.3 -1:axis 'y' 'r'
+ylabel '#r{y_2}' 0.2:fplot 'x^3' 'r'
+
+subplot 2 2 2:title '4 segments, inverted axis':origin 0 0:
+inplot 0.5 1 0.5 1 on:ranges 0 10 0 2:axis
+fplot 'sqrt(x/2)':xlabel 'W' 1:ylabel 'U' 1
+inplot 0 0.5 0.5 1 on:ranges 1 0 0 2:axis 'x'
+fplot 'sqrt(x)+x^3':xlabel '\tau' 1
+inplot 0.5 1 0 0.5 on:ranges 0 10 4 0:axis 'y'
+fplot 'x/4':ylabel 'L' -1
+inplot 0 0.5 0 0.5 on:ranges 1 0 4 0:fplot '4*x^2'
+ at end verbatim
+
+Note, that MathGL can draw not only single axis (which is default). But also several axis on the plot (see right plots). The idea is that the change of settings does not influence on the already drawn graphics. So, for 2-axes I setup the first axis and draw everything concerning it. Then I setup the second axis and draw things for the second axis. Generally, the similar idea allows one to draw rather complicated plot of 4 axis with different ranges (see bottom left plot).
+
+At this inverted axis can be created by 2 methods. First one is used in this sample -- just specify minimal axis value to be large than maximal one. This method work well for 2D axis, but can wrongly place labels in 3D case. Second method is more general and work in 3D case too -- just use @ref{aspect} function with negative arguments. For example, following code will produce exactly the same result for 2D case, but 2nd variant will look better in 3D.
+ at verbatim
+# variant 1
+ranges 0 10 4 0:axis
+
+# variant 2
+ranges 0 10 0 4:aspect 1 -1:axis
+ at end verbatim
+
+ at pfig{axis, Example of axis.}
+
+Another MathGL feature is fine ticks tunning. By default (if it is not changed by @code{SetTicks} function), MathGL try to adjust ticks positioning, so that they looks most human readable. At this, MathGL try to extract common factor for too large or too small axis ranges, as well as for too narrow ranges. Last one is non-common notation and can be disabled by @code{SetTuneTicks} function.
+
+Also, one can specify its own ticks with arbitrary labels by help of @code{SetTicksVal} function. Or one can set ticks in time format. In last case MathGL will try to select optimal format for labels with automatic switching between years, months/days, hours/minutes/seconds or microseconds. However, you can specify its own time representation using formats described in @url{http://www.manpagez.com/man/3/strftime/}. Most common variants are @samp{%X} for national representation of time, @ [...]
+
+The sample code, demonstrated ticks feature is
+ at verbatim
+subplot 3 3 0:title 'Usual axis'
+axis
+
+subplot 3 3 1:title 'Too big/small range'
+ranges -1000 1000 0 0.001:axis
+
+subplot 3 3 2:title 'LaTeX-like labels'
+axis 'F!'
+
+subplot 3 3 3:title 'Too narrow range'
+ranges 100 100.1 10 10.01:axis
+
+subplot 3 3 4:title 'No tuning, manual "+"'
+axis '+!'
+# for version <2.3 you can use
+#tuneticks off:axis
+
+subplot 3 3 5:title 'Template for ticks'
+xtick 'xxx:%g':ytick 'y:%g'
+axis
+
+xtick '':ytick '' # switch it off for other plots
+
+subplot 3 3 6:title 'No tuning, higher precision'
+axis '!4'
+
+subplot 3 3 7:title 'Manual ticks'
+ranges -pi pi 0 2
+xtick pi 3 '\pi'
+xtick 0.886 'x^*' on # note this will disable subticks drawing
+# or you can use
+#xtick -pi '\pi' -pi/2 '-\pi/2' 0 '0' 0.886 'x^*' pi/2 '\pi/2' pi 'pi'
+# or you can use
+#list v -pi -pi/2 0 0.886 pi/2 pi:xtick v '-\pi\n-\pi/2\n{}0\n{}x^*\n\pi/2\n\pi'
+axis:grid:fplot '2*cos(x^2)^2' 'r2'
+
+subplot 3 3 8:title 'Time ticks'
+xrange 0 3e5:ticktime 'x':axis
+ at end verbatim
+
+ at pfig{ticks, Features of axis ticks.}
+
+The last sample I want to show in this subsection is Log-axis. From MathGL's point of view, the log-axis is particular case of general curvilinear coordinates. So, we need first define new coordinates (see also @ref{Curvilinear coordinates}) by help of @code{SetFunc} or @code{SetCoor} functions. At this one should wary about proper axis range. So the code looks as following:
+ at verbatim
+subplot 2 2 0 '<_':title 'Semi-log axis'
+ranges 0.01 100 -1 1:axis 'lg(x)' '' ''
+axis:grid 'xy' 'g':fplot 'sin(1/x)'
+xlabel 'x' 0:ylabel 'y = sin 1/x' 0
+
+subplot 2 2 1 '<_':title 'Log-log axis'
+ranges 0.01 100 0.1 100:axis 'lg(x)' 'lg(y)' ''
+axis:grid '!' 'h=':grid:fplot 'sqrt(1+x^2)'
+xlabel 'x' 0:ylabel 'y = \sqrt{1+x^2}' 0
+
+subplot 2 2 2 '<_':title 'Minus-log axis'
+ranges -100 -0.01 -100 -0.1:axis '-lg(-x)' '-lg(-y)' ''
+axis:fplot '-sqrt(1+x^2)'
+xlabel 'x' 0:ylabel 'y = -\sqrt{1+x^2}' 0
+
+subplot 2 2 3 '<_':title 'Log-ticks'
+ranges 0.01 100 0 100:axis 'sqrt(x)' '' ''
+axis:fplot 'x'
+xlabel 'x' 1:ylabel 'y = x' 0
+ at end verbatim
+
+ at pfig{loglog, Features of axis ticks.}
+
+You can see that MathGL automatically switch to log-ticks as we define log-axis formula (in difference from v.1.*). Moreover, it switch to log-ticks for any formula if axis range will be large enough (see right bottom plot). Another interesting feature is that you not necessary define usual log-axis (i.e. when coordinates are positive), but you can define ``minus-log'' axis when coordinate is negative (see left bottom plot).
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Curvilinear coordinates, Colorbars, Axis and ticks, Advanced usage
+ at subsection Curvilinear coordinates
+ at nav{}
+
+As I noted in previous subsection, MathGL support curvilinear coordinates. In difference from other plotting programs and libraries, MathGL uses textual formulas for connection of the old (data) and new (output) coordinates. This allows one to plot in arbitrary coordinates. The following code plots the line @var{y}=0, @var{z}=0 in Cartesian, polar, parabolic and spiral coordinates:
+ at verbatim
+origin -1 1 -1
+subplot 2 2 0:title 'Cartesian':rotate 50 60
+fplot '2*t-1' '0.5' '0' '2r':axis:grid
+
+axis 'y*sin(pi*x)' 'y*cos(pi*x)' '':
+subplot 2 2 1:title 'Cylindrical':rotate 50 60
+fplot '2*t-1' '0.5' '0' '2r':axis:grid
+
+axis '2*y*x' 'y*y - x*x' ''
+subplot 2 2 2:title 'Parabolic':rotate 50 60
+fplot '2*t-1' '0.5' '0' '2r':axis:grid
+
+axis 'y*sin(pi*x)' 'y*cos(pi*x)' 'x+z'
+subplot 2 2 3:title 'Spiral':rotate 50 60
+fplot '2*t-1' '0.5' '0' '2r':axis:grid
+ at end verbatim
+
+ at pfig{curvcoor, Example of curvilinear coordinates}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Colorbars, Bounding box, Curvilinear coordinates, Advanced usage
+ at subsection Colorbars
+ at nav{}
+
+MathGL handle @ref{colorbar} as special kind of axis. So, most of functions for axis and ticks setup will work for colorbar too. Colorbars can be in log-scale, and generally as arbitrary function scale; common factor of colorbar labels can be separated; and so on.
+
+But of course, there are differences -- colorbars usually located out of bounding box. At this, colorbars can be at subplot boundaries (by default), or at bounding box (if symbol @samp{I} is specified). Colorbars can handle sharp colors. And they can be located at arbitrary position too. The sample code, which demonstrate colorbar features is:
+ at verbatim
+call 'prepare2d'
+new v 9 'x'
+
+subplot 2 2 0:title 'Colorbar out of box':box
+colorbar '<':colorbar '>':colorbar '_':colorbar '^'
+
+subplot 2 2 1:title 'Colorbar near box':box
+colorbar '<I':colorbar '>I':colorbar '_I':colorbar '^I'
+
+subplot 2 2 2:title 'manual colors':box:contd v a
+colorbar v '<':colorbar v '>':colorbar v '_':colorbar v '^'
+
+subplot 2 2 3:title '':text -0.5 1.55 'Color positions' ':C' -2
+
+colorbar 'bwr>' 0.25 0:text -0.9 1.2 'Default'
+colorbar 'b{w,0.3}r>' 0.5 0:text -0.1 1.2 'Manual'
+
+crange 0.01 1e3
+colorbar '>' 0.75 0:text 0.65 1.2 'Normal scale'
+colorbar '>':text 1.35 1.2 'Log scale'
+ at end verbatim
+
+ at pfig{colorbar, Example of colorbars}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Bounding box, Ternary axis, Colorbars, Advanced usage
+ at subsection Bounding box
+ at nav{}
+
+Box around the plot is rather useful thing because it allows one to: see the plot boundaries, and better estimate points position since box contain another set of ticks. MathGL provide special function for drawing such box -- @ref{box} function. By default, it draw black or white box with ticks (color depend on transparency type, see @ref{Types of transparency}). However, you can change the color of box, or add drawing of rectangles at rear faces of box. Also you can disable ticks drawin [...]
+ at verbatim
+subplot 2 2 0:title 'Box (default)':rotate 50 60:box
+
+subplot 2 2 1:title 'colored':rotate 50 60:box 'r'
+
+subplot 2 2 2:title 'with faces':rotate 50 60:box '@'
+
+subplot 2 2 3:title 'both':rotate 50 60:box '@cm'
+ at end verbatim
+
+ at pfig{box, Example of Box()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Ternary axis, Text features, Bounding box, Advanced usage
+ at subsection Ternary axis
+ at nav{}
+
+There are another unusual axis types which are supported by MathGL. These are ternary and quaternary axis. Ternary axis is special axis of 3 coordinates @var{a}, @var{b}, @var{c} which satisfy relation @var{a}+ at var{b}+ at var{c}=1. Correspondingly, quaternary axis is special axis of 4 coordinates @var{a}, @var{b}, @var{c}, @var{d} which satisfy relation @var{a}+ at var{b}+ at var{c}+ at var{d}=1.
+
+Generally speaking, only 2 of coordinates (3 for quaternary) are independent. So, MathGL just introduce some special transformation formulas which treat @var{a} as @samp{x}, @var{b} as @samp{y} (and @var{c} as @samp{z} for quaternary). As result, all plotting functions (curves, surfaces, contours and so on) work as usual, but in new axis. You should use @ref{ternary} function for switching to ternary/quaternary coordinates. The sample code is:
+ at verbatim
+ranges 0 1 0 1 0 1
+new x 50 '0.25*(1+cos(2*pi*x))'
+new y 50 '0.25*(1+sin(2*pi*x))'
+new z 50 'x'
+new a 20 30 '30*x*y*(1-x-y)^2*(x+y<1)'
+new rx 10 'rnd':copy ry (1-rx)*rnd
+light on
+
+subplot 2 2 0:title 'Ordinary axis 3D':rotate 50 60
+box:axis:grid
+plot x y z 'r2':surf a '#'
+xlabel 'B':ylabel 'C':zlabel 'Z'
+
+subplot 2 2 1:title 'Ternary axis (x+y+t=1)':ternary 1
+box:axis:grid 'xyz' 'B;'
+plot x y 'r2':plot rx ry 'q^ ':cont a:line 0.5 0 0 0.75 'g2'
+xlabel 'B':ylabel 'C':tlabel 'A'
+
+subplot 2 2 2:title 'Quaternary axis 3D':rotate 50 60:ternary 2
+box:axis:grid 'xyz' 'B;'
+plot x y z 'r2':surf a '#'
+xlabel 'B':ylabel 'C':tlabel 'A':zlabel 'D'
+
+subplot 2 2 3:title 'Ternary axis 3D':rotate 50 60:ternary 1
+box:axis:grid 'xyz' 'B;'
+plot x y z 'r2':surf a '#'
+xlabel 'B':ylabel 'C':tlabel 'A':zlabel 'Z'
+ at end verbatim
+
+ at pfig{ternary, Ternary and Quaternary axis}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Text features, Legend sample, Ternary axis, Advanced usage
+ at subsection Text features
+ at nav{}
+
+MathGL prints text by vector font. There are functions for manual specifying of text position (like @code{Puts}) and for its automatic selection (like @code{Label}, @code{Legend} and so on). MathGL prints text always in specified position even if it lies outside the bounding box. The default size of font is specified by functions @var{SetFontSize*} (see @ref{Font settings}). However, the actual size of output string depends on subplot size (depends on functions @code{SubPlot}, @code{InPl [...]
+
+Text can be printed as usual one (from left to right), along some direction (rotated text), or along a curve. Text can be printed on several lines, divided by new line symbol @samp{\n}.
+
+Example of MathGL font drawing is:
+ at verbatim
+call 'prepare1d'
+
+subplot 2 2 0 ''
+text 0 1 'Text can be in ASCII and in Unicode'
+text 0 0.6 'It can be \wire{wire}, \big{big} or #r{colored}'
+text 0 0.2 'One can change style in string: \b{bold}, \i{italic, \b{both}}'
+text 0 -0.2 'Easy to \a{overline} or \u{underline}'
+text 0 -0.6 'Easy to change indexes ^{up} _{down} @{center}'
+text 0 -1 'It parse TeX: \int \alpha \cdot \
+\sqrt3{sin(\pi x)^2 + \gamma_{i_k}} dx'
+
+subplot 2 2 1 ''
+ text 0 0.5 '\sqrt{\frac{\alpha^{\gamma^2}+\overset 1{\big\infty}}{\sqrt3{2+b}}}' '@' -2
+text 0 -0.5 'Text can be printed\n{}on several lines'
+
+subplot 2 2 2 '':box:plot y(:,0)
+text y 'This is very very long string drawn along a curve' 'k'
+text y 'Another string drawn under a curve' 'Tr'
+
+subplot 2 2 3 '':line -1 -1 1 -1 'rA':text 0 -1 1 -1 'Horizontal'
+line -1 -1 1 1 'rA':text 0 0 1 1 'At angle' '@'
+line -1 -1 -1 1 'rA':text -1 0 -1 1 'Vertical'
+ at end verbatim
+
+ at pfig{text, Example of text printing}
+
+You can change font faces by loading font files by function @ref{loadfont}. Note, that this is long-run procedure. Font faces can be downloaded from @uref{http://mathgl.sourceforge.net/download.html, MathGL website} or from @uref{http://sourceforge.net/project/showfiles.php?group_id=152187&package_id=267177, here}. The sample code is:
+ at verbatim
+define d 0.25
+loadfont 'STIX':text 0 1.1 'default font (STIX)'
+loadfont 'adventor':text 0 1.1-d 'adventor font'
+loadfont 'bonum':text 0 1.1-2*d 'bonum font'
+loadfont 'chorus':text 0 1.1-3*d 'chorus font'
+loadfont 'cursor':text 0 1.1-4*d 'cursor font'
+loadfont 'heros':text 0 1.1-5*d 'heros font'
+loadfont 'heroscn':text 0 1.1-6*d 'heroscn font'
+loadfont 'pagella':text 0 1.1-7*d 'pagella font'
+loadfont 'schola':text 0 1.1-8*d 'schola font'
+loadfont 'termes':text 0 1.1-9*d 'termes font'
+ at end verbatim
+
+ at pfig{fonts, Example of font faces}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Legend sample, Cutting sample, Text features, Advanced usage
+ at subsection Legend sample
+ at nav{}
+
+Legend is one of standard ways to show plot annotations. Basically you need to connect the plot style (line style, marker and color) with some text. In MathGL, you can do it by 2 methods: manually using @ref{addlegend} function; or use @samp{legend} option (see @ref{Command options}), which will use last plot style. In both cases, legend entries will be added into internal accumulator, which later used for legend drawing itself. @ref{clearlegend} function allow you to remove all saved le [...]
+
+There are 2 features. If plot style is empty then text will be printed without indent. If you want to plot the text with indent but without plot sample then you need to use space @samp{ } as plot style. Such style @samp{ } will draw a plot sample (line with marker(s)) which is invisible line (i.e. nothing) and print the text with indent as usual one.
+
+Command @ref{legend} draw legend on the plot. The position of the legend can be selected automatic or manually. You can change the size and style of text labels, as well as setup the plot sample. The sample code demonstrating legend features is:
+ at verbatim
+addlegend 'sin(\pi {x^2})' 'b'
+addlegend 'sin(\pi x)' 'g*'
+addlegend 'sin(\pi \sqrt{x})' 'rd'
+addlegend 'jsut text' ' '
+addlegend 'no indent for this' ''
+
+subplot 2 2 0 '':title 'Legend (default)':box
+legend
+
+text 0.75 0.65 'Absolute position' 'A'
+legend 3 'A#'
+
+subplot 2 2 2 '':title 'coloring':box
+legend 0 'r#':legend 1 'Wb#':legend 2 'ygr#'
+
+subplot 2 2 3 '':title 'manual position':box
+legend 0.5 1:text 0.5 0.55 'at x=0.5, y=1' 'a'
+legend 1 '#-':text 0.75 0.25 'Horizontal legend' 'a'
+ at end verbatim
+
+ at pfig{legend, Example of legend}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cutting sample, , Legend sample, Advanced usage
+ at subsection Cutting sample
+ at nav{}
+
+The last common thing which I want to show in this section is how one can cut off points from plot. There are 4 mechanism for that.
+ at itemize @bullet
+ at item
+You can set one of coordinate to NAN value. All points with NAN values will be omitted.
+
+ at item
+You can enable cutting at edges by @code{SetCut} function. As result all points out of bounding box will be omitted.
+
+ at item
+You can set cutting box by @code{SetCutBox} function. All points inside this box will be omitted.
+
+ at item
+You can define cutting formula by @code{SetCutOff} function. All points for which the value of formula is nonzero will be omitted. Note, that this is the slowest variant.
+ at end itemize
+
+Below I place the code which demonstrate last 3 possibilities:
+ at verbatim
+call 'prepare2d'
+call 'prepare3d'
+
+subplot 2 2 0:title 'Cut on (default)':rotate 50 60
+light on:box:surf a; zrange -1 0.5
+
+subplot 2 2 1:title 'Cut off':rotate 50 60
+box:surf a; zrange -1 0.5; cut off
+
+subplot 2 2 2:title 'Cut in box':rotate 50 60:box:alpha on
+cut 0 -1 -1 1 0 1.1:surf3 c
+cut 0 0 0 0 0 0	# restore back
+
+subplot 2 2 3:title 'Cut by formula':rotate 50 60:box
+cut '(z>(x+0.5*y-1)^2-1) & (z>(x-0.5*y-1)^2-1)':surf3 c
+ at end verbatim
+
+ at pfig{cut, Example of point cutting}
+
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Data handling, Data plotting, Advanced usage, Examples
+ at section Data handling
+ at nav{}
+
+Class @code{mglData} contains all functions for the data handling in MathGL (@pxref{Data processing}). There are several matters why I use class @code{mglData} but not a single array: it does not depend on type of data (mreal or double), sizes of data arrays are kept with data, memory working is simpler and safer.
+
+ at menu
+* Array creation::
+* Change data::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Array creation, Change data, , Data handling
+ at subsection Array creation
+ at nav{}
+
+One can put numbers into the data instance by several ways. Let us do it for square function:
+ at itemize @bullet
+ at item
+one can create array by @code{list} command
+ at verbatim
+list a 0 0.04 0.16 0.36 0.64 1
+ at end verbatim
+
+ at item
+another way is to copy from ``inline'' array
+ at verbatim
+copy a [0,0.04,0.16,0.36,0.64,1]
+ at end verbatim
+
+ at item
+next way is to fill the data by textual formula with the help of @code{modify} function
+ at verbatim
+new a 6
+modify a 'x^2'
+ at end verbatim
+
+ at item
+or one may fill the array in some interval and modify it later
+ at verbatim
+new a 6
+fill a 0 1
+modify a 'u^2'
+ at end verbatim
+
+ at item
+or fill the array using current axis range
+ at verbatim
+new a 6
+fill a '(x+1)^2/4'
+ at end verbatim
+or use single line
+ at verbatim
+new a 6 '(x+1)^2/4'
+ at end verbatim
+
+ at item
+finally it can be loaded from file
+ at verbatim
+new s 6 '(x+1)^2/4'
+save s 'sqr.dat'    # create file first
+read a 'sqr.dat'    # load it
+ at end verbatim
+
+ at item
+at this one can read only part of data
+ at verbatim
+new s 6 '(x+1)^2/4'
+save s 'sqr.dat'    # create file first
+read a 'sqr.dat' 5  # load it
+ at end verbatim
+ at end itemize
+
+Creation of 2d- and 3d-arrays is mostly the same. One can use direct data filling by @code{list} command
+ at verbatim
+list a 11 12 13 | 21 22 23 | 31 32 33
+ at end verbatim
+or by inline arrays
+ at verbatim
+copy a [[11,12,13],[21,22,23],[31,32,33]]
+ at end verbatim
+Also data can be filled by formula
+ at verbatim
+new z 30 40 'sin(pi*x)*cos(pi*y)'
+ at end verbatim
+or loaded from a file.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Change data, , Array creation, Data handling
+ at subsection Change data
+ at nav{}
+
+MathGL has functions for data processing: differentiating, integrating, smoothing and so on (for more detail, see @ref{Data processing}). Let us consider some examples. The simplest ones are integration and differentiation. The direction in which operation will be performed is specified by textual string, which may contain symbols @samp{x}, @samp{y} or @samp{z}. For example, the call of @code{diff 'x'} will differentiate data along @samp{x} direction; the call of @code{integrate 'xy'} pe [...]
+ at verbatim
+ranges 0 1 0 1 0 1:new a 30 40 'x*y'
+subplot 2 2 0:title 'a(x,y)':rotate 60 40
+surf a:box
+
+subplot 2 2 1:title 'da/dx':rotate 60 40
+diff a 'x':surf a:box
+
+subplot 2 2 2:title '\int da/dx dxdy':rotate 60 40
+integrate a 'xy':surf a:box
+
+subplot 2 2 3:title '\int {d^2}a/dxdy dx':rotate 60 40
+diff2 a 'y':surf a:box
+ at end verbatim
+
+ at pfig{dat_diff, Example of data differentiation and integration}
+
+Data smoothing (command @ref{smooth}) is more interesting and important. This function has single argument which define type of smoothing and its direction. Now 3 methods are supported: @samp{3} -- linear averaging by 3 points, @samp{5} -- linear averaging by 5 points, and default one -- quadratic averaging by 5 points.
+
+MathGL also have some amazing functions which is not so important for data processing as useful for data plotting. There are functions for finding envelope (useful for plotting rapidly oscillating data), for data sewing (useful to removing jumps on the phase), for data resizing (interpolation). Let me demonstrate it:
+ at verbatim
+subplot 2 2 0 '':title 'Envelop sample'
+new d1 1000 'exp(-8*x^2)*sin(10*pi*x)'
+axis:plot d1 'b'
+envelop d1 'x'
+plot d1 'r'
+
+subplot 2 2 1 '':title 'Smooth sample':ranges 0 1 0 1
+new y0 30 '0.4*sin(pi*x) + 0.3*cos(1.5*pi*x) - 0.4*sin(2*pi*x)+0.5*rnd'
+copy y1 y0:smooth y1 'x3':plot y1 'r';legend '"3" style'
+copy y2 y0:smooth y2 'x5':plot y2 'g';legend '"5" style'
+copy y3 y0:smooth y3 'x':plot y3 'b';legend 'default'
+plot y0 '{m7}:s';legend 'none':legend:box
+
+subplot 2 2 2:title 'Sew sample':rotate 50 60:light on:alpha on
+new d2 100 100 'mod((y^2-(1-x)^2)/2,0.1)'
+box:surf d2 'b'
+sew d2 'xy' 0.1
+surf d2 'r'
+
+subplot 2 2 3:title 'Resize sample (interpolation)'
+new x0 10 'rnd':new v0 10 'rnd'
+resize x1 x0 100:resize v1 v0 100
+plot x0 v0 'b+ ':plot x1 v1 'r-':label x0 v0 '%n'
+ at end verbatim
+
+ at pfig{dat_extra, Example of data smoothing}
+
+Finally one can create new data arrays on base of the existing one: extract slice, row or column of data (@ref{subdata}), summarize along a direction(s) (@ref{sum}), find distribution of data elements (@ref{hist}) and so on.
+
+ at anchor{Solve sample}
+Another interesting feature of MathGL is interpolation and root-finding. There are several functions for linear and cubic spline interpolation (see @ref{Interpolation}). Also there is a function @ref{evaluate} which do interpolation of data array for values of each data element of index data. It look as indirect access to the data elements.
+
+This function have inverse function @ref{solve} which find array of indexes at which data array is equal to given value (i.e. work as root finding). But @ref{solve} function have the issue -- usually multidimensional data (2d and 3d ones) have an infinite number of indexes which give some value. This is contour lines for 2d data, or isosurface(s) for 3d data. So, @ref{solve} function will return index only in given direction, assuming that other index(es) are the same as equidistant inde [...]
+
+ at verbatim
+zrange 0 1
+new x 20 30 '(x+2)/3*cos(pi*y)'
+new y 20 30 '(x+2)/3*sin(pi*y)'
+new z 20 30 'exp(-6*x^2-2*sin(pi*y)^2)'
+
+subplot 2 1 0:title 'Cartesian space':rotate 30 -40
+axis 'xyzU':box
+xlabel 'x':ylabel 'y'origin 1 1:grid 'xy'
+mesh x y z
+
+# section along 'x' direction
+solve u x 0.5 'x'
+var v u.nx 0 1
+evaluate yy y u v
+evaluate xx x u v
+evaluate zz z u v
+plot xx yy zz 'k2o'
+
+# 1st section along 'y' direction
+solve u1 x -0.5 'y'
+var v1 u1.nx 0 1
+evaluate yy y v1 u1
+evaluate xx x v1 u1
+evaluate zz z v1 u1
+plot xx yy zz 'b2^'
+
+# 2nd section along 'y' direction
+solve u2 x -0.5 'y' u1
+evaluate yy y v1 u2
+evaluate xx x v1 u2
+evaluate zz z v1 u2
+plot xx yy zz 'r2v'
+
+subplot 2 1 1:title 'Accompanied space'
+ranges 0 1 0 1:origin 0 0
+axis:box:xlabel 'i':ylabel 'j':grid2 z 'h'
+
+plot u v 'k2o':line 0.4 0.5 0.8 0.5 'kA'
+plot v1 u1 'b2^':line 0.5 0.15 0.5 0.3 'bA'
+plot v1 u2 'r2v':line 0.5 0.7 0.5 0.85 'rA'
+ at end verbatim
+
+ at pfig{solve, Example of data interpolation and root finding}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Data plotting, 1D samples, Data handling, Examples
+ at section Data plotting
+ at nav{}
+
+Let me now show how to plot the data. Next section will give much more examples for all plotting functions. Here I just show some basics. MathGL generally has 2 types of plotting functions. Simple variant requires a single data array for plotting, other data (coordinates) are considered uniformly distributed in axis range. Second variant requires data arrays for all coordinates. It allows one to plot rather complex multivalent curves and surfaces (in case of parametric dependencies). Usu [...]
+
+Note, that the call of drawing function adds something to picture but does not clear the previous plots (as it does in Matlab). Another difference from Matlab is that all setup (like transparency, lightning, axis borders and so on) must be specified @strong{before} plotting functions.
+
+Let start for plots for 1D data. Term ``1D data'' means that data depend on single index (parameter) like curve in parametric form @{x(i),y(i),z(i)@}, i=1...n. The textual argument allow you specify styles of line and marks (see @ref{Line styles}). If this parameter is empty @code{''} then solid line with color from palette is used (see @ref{Palette and colors}).
+
+Below I shall show the features of 1D plotting on base of @ref{plot} function. Let us start from sinus plot:
+ at verbatim
+new y0 50 'sin(pi*x)'
+subplot 2 2 0
+plot y0:box
+ at end verbatim
+Style of line is not specified in @ref{plot} function. So MathGL uses the solid line with first color of palette (this is blue). Next subplot shows array @var{y1} with 2 rows:
+ at verbatim
+subplot 2 2 1
+new y1 50 2
+fill y1 'cos(pi*(x+y/4))*2/(y+3)'
+plot y1:box
+ at end verbatim
+As previously I did not specify the style of lines. As a result, MathGL again uses solid line with next colors in palette (there are green and red). Now let us plot a circle on the same subplot. The circle is parametric curve @math{x=cos(\pi t), y=sin(\pi t)}. I will set the color of the circle (dark yellow, @samp{Y}) and put marks @samp{+} at point position:
+ at verbatim
+new x 50 'cos(pi*x)'
+plot x y0 'Y+'
+ at end verbatim
+Note that solid line is used because I did not specify the type of line. The same picture can be achieved by @ref{plot} and @ref{subdata} functions. Let us draw ellipse by orange dash line:
+ at verbatim
+plot y1(:,0) y1(:,1) 'q|'
+ at end verbatim
+
+Drawing in 3D space is mostly the same. Let us draw spiral with default line style. Now its color is 4-th color from palette (this is cyan):
+ at verbatim
+subplot 2 2 2:rotate 60 40
+new z 50 'x'
+plot x y0 z:box
+ at end verbatim
+Functions @ref{plot} and @ref{subdata} make 3D curve plot but for single array. Use it to put circle marks on the previous plot:
+ at verbatim
+new y2 10 3 'cos(pi*(x+y/2))'
+modify y2 '2*x-1' 2
+plot y2(:,0) y2(:,1) y2(:,2) 'bo '
+ at end verbatim
+Note that line style is empty @samp{ } here. Usage of other 1D plotting functions looks similar:
+ at verbatim
+subplot 2 2 3:rotate 60 40
+bars x y0 z 'r':box
+ at end verbatim
+
+Surfaces @ref{surf} and other 2D plots (@pxref{2D plotting}) are drown the same simpler as 1D one. The difference is that the string parameter specifies not the line style but the color scheme of the plot (see @ref{Color scheme}). Here I draw attention on 4 most interesting color schemes. There is gray scheme where color is changed from black to white (string @samp{kw}) or from white to black (string @samp{wk}). Another scheme is useful for accentuation of negative (by blue color) and po [...]
+
+Now I shall show the example of a surface drawing. At first let us switch lightning on
+ at verbatim
+light on
+ at end verbatim
+and draw the surface, considering coordinates x,y to be uniformly distributed in axis range
+ at verbatim
+new a0 50 40 '0.6*sin(pi*(x+1))*sin(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'
+subplot 2 2 0:rotate 60 40
+surf a0:box
+ at end verbatim
+Color scheme was not specified. So previous color scheme is used. In this case it is default color scheme (``jet'') for the first plot. Next example is a sphere. The sphere is parametrically specified surface:
+ at verbatim
+new x 50 40 '0.8*sin(pi*x)*cos(pi*y/2)'
+new y 50 40 '0.8*cos(pi*x)*cos(pi*y/2)'
+new z 50 40 '0.8*sin(pi*y/2)'
+subplot 2 2 1:rotate 60 40
+surf x y z 'BbwrR':box
+ at end verbatim
+I set color scheme to @code{"BbwrR"} that corresponds to red top and blue bottom of the sphere.
+
+Surfaces will be plotted for each of slice of the data if @var{nz}>1. Next example draws surfaces for data arrays with @var{nz}=3:
+ at verbatim
+new a1 50 40 3
+modify a1 '0.6*sin(2*pi*x)*sin(3*pi*y)+0.4*cos(3*pi*(x*y))'
+modify a1 '0.6*cos(2*pi*x)*cos(3*pi*y)+0.4*sin(3*pi*(x*y))' 1
+modify a1 '0.6*cos(2*pi*x)*cos(3*pi*y)+0.4*cos(3*pi*(x*y))' 2
+subplot 2 2 2:rotate 60 40
+alpha on
+surf a1:box
+ at end verbatim
+Note, that it may entail a confusion. However, if one will use density plot then the picture will look better:
+ at verbatim
+subplot 2 2 3:rotate 60 40
+dens a1:box
+ at end verbatim
+
+Drawing of other 2D plots is analogous. The only peculiarity is the usage of flag @samp{#}. By default this flag switches on the drawing of a grid on plot (@ref{grid} or @ref{mesh} for plots in plain or in volume). However, for isosurfaces (including surfaces of rotation @ref{axial}) this flag switches the  face drawing off and figure becomes wired.
+ at c ------------------------------------------------------------------
+ at external{}
+ at node 1D samples, 2D samples, Data plotting, Examples
+ at section 1D samples
+ at nav{}
+
+This section is devoted to visualization of 1D data arrays. 1D means the data which depend on single index (parameter) like curve in parametric form @{x(i),y(i),z(i)@}, i=1...n. Most of samples will use the same data for plotting. So, I put its initialization in separate function
+ at verbatim
+func 'prepare1d'
+new y 50 3
+modify y '0.7*sin(2*pi*x)+0.5*cos(3*pi*x)+0.2*sin(pi*x)'
+modify y 'sin(2*pi*x)' 1
+modify y 'cos(2*pi*x)' 2
+new x1 50 'x'
+new x2 50 '0.05-0.03*cos(pi*x)'
+new y1 50 '0.5-0.3*cos(pi*x)'
+new y2 50 '-0.3*sin(pi*x)'
+return
+ at end verbatim
+Basically, you can put this text after the script. Note, that you need to terminate main script by @ref{stop} command before defining a function.
+
+ at menu
+* Plot sample::
+* Radar sample::
+* Step sample::
+* Tens sample::
+* Area sample::
+* Region sample::
+* Stem sample::
+* Bars sample::
+* Barh sample::
+* Cones sample::
+* Chart sample::
+* BoxPlot sample::
+* Candle sample::
+* OHLC sample::
+* Error sample::
+* Mark sample::
+* TextMark sample::
+* Label sample::
+* Table sample::
+* Iris sample::
+* Tube sample::
+* Tape sample::
+* Torus sample::
+* Lamerey sample::
+* Bifurcation sample::
+* Pmap sample::
+ at end menu
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Plot sample, Radar sample, , 1D samples
+ at subsection Plot sample
+ at nav{}
+
+Command @ref{plot} is most standard way to visualize 1D data array. By default, @code{Plot} use colors from palette. However, you can specify manual color/palette, and even set to use new color for each points by using @samp{!} style. Another feature is @samp{ } style which draw only markers without line between points. The sample code is:
+ at verbatim
+call 'prepare1d'
+subplot 2 2 0 '':title 'Plot plot (default)':box
+plot y
+
+subplot 2 2 2 '':title ''!' style; 'rgb' palette':box
+plot y 'o!rgb'
+
+subplot 2 2 3 '':title 'just markers':box
+plot y ' +'
+
+new yc 30 'sin(pi*x)':new xc 30 'cos(pi*x)':new z 30 'x'
+subplot 2 2 1:title '3d variant':rotate 50 60:box
+plot xc yc z 'rs'
+ at end verbatim
+
+ at pfig{plot, Example of Plot()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Radar sample, Step sample, Plot sample, 1D samples
+ at subsection Radar sample
+ at nav{}
+
+Command @ref{radar} plot is variant of @code{Plot} one, which make plot in polar coordinates and draw radial rays in point directions. If you just need a plot in polar coordinates then I recommend to use @ref{Curvilinear coordinates} or @code{Plot} in parabolic form with @code{x=r*cos(fi); y=r*sin(fi);}. The sample code is:
+ at verbatim
+new yr 10 3 '0.4*sin(pi*(x+1.5+y/2)+0.1*rnd)'
+subplot 1 1 0 '':title 'Radar plot (with grid, "\#")'
+radar yr '#'
+ at end verbatim
+
+ at pfig{radar, Example of Radar()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Step sample, Tens sample, Radar sample, 1D samples
+ at subsection Step sample
+ at nav{}
+
+Command @ref{step} plot data as stairs. It have the same options as @code{Plot}. The sample code is:
+ at verbatim
+call 'prepare1d'
+origin 0 0 0:subplot 2 2 0 '':title 'Step plot (default)':box
+step y
+
+new yc 30 'sin(pi*x)':new xc 30 'cos(pi*x)':new z 30 'x'
+subplot 2 2 1:title '3d variant':rotate 50 60:box
+step xc yc z 'r'
+
+subplot 2 2 2 '':title '"!" style':box
+step y 's!rgb'
+ at end verbatim
+
+ at pfig{step, Example of Step()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Tens sample, Area sample, Step sample, 1D samples
+ at subsection Tens sample
+ at nav{}
+
+Command @ref{tens} is variant of @ref{plot} with smooth coloring along the curves. At this, color is determined as for surfaces (see @ref{Color scheme}). The sample code is:
+ at verbatim
+call 'prepare1d'
+subplot 2 2 0 '':title 'Tens plot (default)':box
+tens y(:,0) y(:,1)
+
+subplot 2 2 2 '':title ' style':box
+tens y(:,0) y(:,1) 'o '
+
+new yc 30 'sin(pi*x)':new xc 30 'cos(pi*x)':new z 30 'x'
+subplot 2 2 1:title '3d variant':rotate 50 60:box
+tens xc yc z z 's'
+ at end verbatim
+
+ at pfig{tens, Example of Tens()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Area sample, Region sample, Tens sample, 1D samples
+ at subsection Area sample
+ at nav{}
+
+Command @ref{area} fill the area between curve and axis plane. It support gradient filling if 2 colors per curve is specified. The sample code is:
+ at verbatim
+call 'prepare1d'
+origin 0 0 0
+subplot 2 2 0 '':title 'Area plot (default)':box
+area y
+
+subplot 2 2 1 '':title '2 colors':box
+area y 'cbgGyr'
+
+subplot 2 2 2 '':title '"!" style':box
+area y '!'
+
+new yc 30 'sin(pi*x)':new xc 30 'cos(pi*x)':new z 30 'x'
+subplot 2 2 3:title '3d variant':rotate 50 60:box
+area xc yc z 'r':area xc -yc z 'b#'
+ at end verbatim
+
+ at pfig{area, Example of Area()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Region sample, Stem sample, Area sample, 1D samples
+ at subsection Region sample
+ at nav{}
+
+Command @ref{region} fill the area between 2 curves. It support gradient filling if 2 colors per curve is specified. Also it can fill only the region y1<y<y2 if style @samp{i} is used. The sample code is:
+ at verbatim
+call 'prepare1d'
+copy y1 y(:,1):copy y2 y(:,2)
+
+subplot 2 2 0 '':title 'Region plot (default)':box
+region y1 y2:plot y1 'k2':plot y2 'k2'
+
+subplot 2 2 1 '':title '2 colors':box
+region y1 y2 'yr':plot y1 'k2':plot y2 'k2'
+
+subplot 2 2 2 '':title '"i" style':box
+region y1 y2 'ir':plot y1 'k2':plot y2 'k2'
+
+subplot 2 2 3 '^_':title '3d variant':rotate 40 60:box
+new x1 100 'sin(pi*x)':new y1 100 'cos(pi*x)':new z 100 'x'
+new x2 100 'sin(pi*x+pi/3)':new y2 100 'cos(pi*x+pi/3)'
+plot x1 y1 z 'r2':plot x2 y2 z 'b2'
+region x1 y1 z x2 y2 z 'cmy!'
+ at end verbatim
+
+ at pfig{region, Example of Region()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Stem sample, Bars sample, Region sample, 1D samples
+ at subsection Stem sample
+ at nav{}
+
+Command @ref{stem} draw vertical bars. It is most attractive if markers are drawn too. The sample code is:
+ at verbatim
+call 'prepare1d'
+origin 0 0 0:subplot 2 2 0 '':title 'Stem plot (default)':box
+stem y
+
+new yc 30 'sin(pi*x)':new xc 30 'cos(pi*x)':new z 30 'x'
+subplot 2 2 1:title '3d variant':rotate 50 60:box
+stem xc yc z 'rx'
+
+subplot 2 2 2 '':title '"!" style':box
+stem y 'o!rgb'
+ at end verbatim
+
+ at pfig{stem, Example of Stem()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Bars sample, Barh sample, Stem sample, 1D samples
+ at subsection Bars sample
+ at nav{}
+
+Command @ref{bars} draw vertical bars. It have a lot of options: bar-above-bar (@samp{a} style), fall like (@samp{f} style), 2 colors for positive and negative values, wired bars (@samp{#} style), 3D variant. The sample code is:
+ at verbatim
+new ys 10 3 '0.8*sin(pi*(x+y/4+1.25))+0.2*rnd':origin 0 0 0
+subplot 3 2 0 '':title 'Bars plot (default)':box
+bars ys
+
+subplot 3 2 1 '':title '2 colors':box
+bars ys 'cbgGyr'
+
+subplot 3 2 4 '':title '"\#" style':box
+bars ys '#'
+
+new yc 30 'sin(pi*x)':new xc 30 'cos(pi*x)':new z 30 'x'
+subplot 3 2 5:title '3d variant':rotate 50 60:box
+bars xc yc z 'r'
+
+subplot 3 2 2 '':title '"a" style':ranges -1 1 -3 3:box
+bars ys 'a'
+
+subplot 3 2 3 '':title '"f" style':box
+bars ys 'f'
+ at end verbatim
+
+ at pfig{bars, Example of Bars()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Barh sample, Cones sample, Bars sample, 1D samples
+ at subsection Barh sample
+ at nav{}
+
+Command @ref{barh} is the similar to @code{Bars} but draw horizontal bars. The sample code is:
+ at verbatim
+new ys 10 3 '0.8*sin(pi*(x+y/4+1.25))+0.2*rnd':origin 0 0 0
+subplot 2 2 0 '':title 'Barh plot (default)':box
+barh ys
+
+subplot 2 2 1 '':title '2 colors':box
+barh ys 'cbgGyr'
+
+ranges -3 3 -1 1:subplot 2 2 2 '':title '"a" style':box:barh ys 'a'
+subplot 2 2 3 '': title '"f" style':box
+barh ys 'f'
+ at end verbatim
+
+ at pfig{barh, Example of Barh()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cones sample, Chart sample, Bars sample, 1D samples
+ at subsection Cones sample
+ at nav{}
+
+Command @ref{cones} is similar to @code{Bars} but draw cones. The sample code is:
+ at verbatim
+new ys 10 3 '0.8*sin(pi*(x+y/4+1.25))+0.2*rnd'
+origin 0 0 0:light on
+subplot 3 2 0:title 'Cones plot':rotate 50 60:box
+cones ys
+
+subplot 3 2 1:title '2 colors':rotate 50 60:box
+cones ys 'cbgGyr'
+
+subplot 3 2 2:title '"\#" style':rotate 50 60:box
+cones ys '#'
+
+subplot 3 2 3:title '"a" style':rotate 50 60:zrange -2 2:box
+cones ys 'a'
+
+subplot 3 2 4:title '"t" style':rotate 50 60:box
+cones ys 't'
+
+subplot 3 2 5:title '"4" style':rotate 50 60:box
+cones ys '4'
+ at end verbatim
+
+ at pfig{cones, Example of Cones()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Chart sample, BoxPlot sample, Cones sample, 1D samples
+ at subsection Chart sample
+ at nav{}
+
+Command @ref{chart} draw colored boxes with width proportional to data values. Use @samp{ } for empty box. Plot looks most attractive in polar coordinates -- well known pie chart. The sample code is:
+ at verbatim
+new ch 7 2 'rnd+0.1':light on
+subplot 2 2 0:title 'Chart plot (default)':rotate 50 60:box
+chart ch
+
+subplot 2 2 1:title '"\#" style':rotate 50 60:box
+chart ch '#'
+
+subplot 2 2 2:title 'Pie chart; " " color':rotate 50 60:
+axis '(y+1)/2*cos(pi*x)' '(y+1)/2*sin(pi*x)' '':box
+chart ch 'bgr cmy#'
+
+subplot 2 2 3:title 'Ring chart; " " color':rotate 50 60:
+axis '(y+2)/3*cos(pi*x)' '(y+2)/3*sin(pi*x)' '':box
+chart ch 'bgr cmy#'
+ at end verbatim
+
+ at pfig{chart, Example of Chart()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node BoxPlot sample, Candle sample, Chart sample, 1D samples
+ at subsection BoxPlot sample
+ at nav{}
+
+Command @ref{boxplot} draw box-and-whisker diagram. The sample code is:
+ at verbatim
+new a 10 7 '(2*rnd-1)^3/2'
+subplot 1 1 0 '':title 'Boxplot plot':box
+boxplot a
+ at end verbatim
+
+ at pfig{boxplot, Example of BoxPlot()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Candle sample, OHLC sample, BoxPlot sample, 1D samples
+ at subsection Candle sample
+ at nav{}
+
+Command @ref{candle} draw candlestick chart. This is a combination of a line-chart and a bar-chart, in that each bar represents the range of price movement over a given time interval. The sample code is:
+ at verbatim
+new y 30 'sin(pi*x/2)^2':copy y1 y/2:copy y2 (y+1)/2
+subplot 1 1 0 '':title 'Candle plot (default)':yrange 0 1:box
+candle y y1 y2
+ at end verbatim
+
+ at pfig{candle, Example of Candle()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node OHLC sample, Error sample, Candle sample, 1D samples
+ at subsection OHLC sample
+ at nav{}
+
+Command @ref{ohlc} draw Open-High-Low-Close diagram. This diagram show vertical line for between maximal(high) and minimal(low) values, as well as horizontal lines before/after vertical line for initial(open)/final(close) values of some process. The sample code is:
+ at verbatim
+new o 10 '0.5*sin(pi*x)'
+new c 10 '0.5*sin(pi*(x+2/9))'
+new l 10 '0.3*rnd-0.8'
+new h 10 '0.3*rnd+0.5'
+subplot 1 1 0 '':title 'OHLC plot':box
+ohlc o h l c
+ at end verbatim
+
+ at pfig{ohlc, Example of OHLC()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Error sample, Mark sample, OHLC sample, 1D samples
+ at subsection Error sample
+ at nav{}
+
+Command @ref{error} draw error boxes around the points. You can draw default boxes or semi-transparent symbol (like marker, see @ref{Line styles}). Also you can set individual color for each box. The sample code is:
+ at verbatim
+call 'prepare1d'
+new y 50 '0.7*sin(pi*x-pi) + 0.5*cos(3*pi*(x+1)/2) + 0.2*sin(pi*(x+1)/2)'
+new x0 10 'x + 0.1*rnd-0.05':new ex 10 '0.1':new ey 10 '0.2'
+new y0 10 '0.7*sin(pi*x-pi) + 0.5*cos(3*pi*(x+1)/2) + 0.2*sin(pi*(x+1)/2) + 0.2*rnd-0.1'
+
+subplot 2 2 0 '':title 'Error plot (default)':box:plot y
+error x0 y0 ex ey 'k'
+
+subplot 2 2 1 '':title '"!" style; no e_x':box:plot y
+error x0 y0 ey 'o!rgb'
+
+subplot 2 2 2 '':title '"\@" style':box:plot y
+error x0 y0 ex ey '@'; alpha 0.5
+
+subplot 2 2 3:title '3d variant':rotate 50 60:axis
+for $1 0 9
+  errbox 2*rnd-1 2*rnd-1 2*rnd-1 0.2 0.2 0.2 'bo'
+next
+ at end verbatim
+
+ at pfig{error, Example of Error()}
+
+Additionally, you can use solid large "marks" instead of error boxes by selecting proper style.
+ at verbatim
+new x0 10 'rnd':new ex 10 '0.1'
+new y0 10 'rnd':new ey 10 '0.1'
+ranges 0 1 0 1
+subplot 4 3 0 '':box:error x0 y0 ex ey '#+@'
+subplot 4 3 1 '':box:error x0 y0 ex ey '#x@'
+subplot 4 3 2 '':box:error x0 y0 ex ey '#s@'; alpha 0.5
+subplot 4 3 3 '':box:error x0 y0 ex ey 's@'
+subplot 4 3 4 '':box:error x0 y0 ex ey 'd@'
+subplot 4 3 5 '':box:error x0 y0 ex ey '#d@'; alpha 0.5
+subplot 4 3 6 '':box:error x0 y0 ex ey '+@'
+subplot 4 3 7 '':box:error x0 y0 ex ey 'x@'
+subplot 4 3 8 '':box:error x0 y0 ex ey 'o@'
+subplot 4 3 9 '':box:error x0 y0 ex ey '#o@'; alpha 0.5
+subplot 4 3 10 '':box:error x0 y0 ex ey '#.@'
+subplot 4 3 11 '':box:error x0 y0 ex ey; alpha 0.5
+ at end verbatim
+
+ at pfig{error2, Example of Error() with marks}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Mark sample, TextMark sample, Error sample, 1D samples
+ at subsection Mark sample
+ at nav{}
+
+Command @ref{mark} draw markers at points. It is mostly the same as @code{Plot} but marker size can be variable. The sample code is:
+ at verbatim
+call 'prepare1d'
+subplot 1 1 0 '':title 'Mark plot (default)':box
+mark y y1 's'
+ at end verbatim
+
+ at pfig{mark, Example of Mark()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node TextMark sample, Label sample, Mark sample, 1D samples
+ at subsection TextMark sample
+ at nav{}
+
+Command @ref{textmark} like @code{Mark} but draw text instead of markers. The sample code is:
+ at verbatim
+call 'prepare1d'
+subplot 1 1 0 '':title 'TextMark plot (default)':box
+textmark y y1 '\gamma' 'r'
+ at end verbatim
+
+ at pfig{textmark, Example of TextMark()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Label sample, Table sample, TextMark sample, 1D samples
+ at subsection Label sample
+ at nav{}
+
+Command @ref{label} print text at data points. The string may contain @samp{%x}, @samp{%y}, @samp{%z} for x-, y-, z-coordinates of points, @samp{%n} for point index. The sample code is:
+ at verbatim
+new ys 10 '0.2*rnd-0.8*sin(pi*x)'
+subplot 1 1 0 '':title 'Label plot':box
+plot ys ' *':label ys 'y=%y'
+ at end verbatim
+
+ at pfig{label, Example of Label()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Table sample, Iris sample, Label sample, 1D samples
+ at subsection Table sample
+ at nav{}
+
+Command @ref{table} draw table with data values. The sample code is:
+ at verbatim
+new ys 10 3 '0.8*sin(pi*(x+y/4+1.25))+0.2*rnd'
+subplot 2 2 0:title 'Table sample':box
+table ys 'y_1\n{}y_2\n{}y_3'
+
+subplot 2 2 1:title 'no borders, colored'
+table ys 'y_1\n{}y_2\n{}y_3' 'r|'
+
+subplot 2 2 2:title 'no font decrease'
+table ys 'y_1\n{}y_2\n{}y_3' '#'
+
+subplot 2 2 3:title 'manual width and position':box
+table 0.5 0.95 ys 'y_1\n{}y_2\n{}y_3' '#';value 0.7
+ at end verbatim
+
+ at pfig{table, Example of Table()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Iris sample, Tube sample, Table sample, 1D samples
+ at subsection Iris sample
+ at nav{}
+
+Command @ref{iris} draw Iris plot for columns of data array. The sample code is:
+ at verbatim
+read a 'iris.dat'
+crop a 0 4 'x':rearrange a a.nx 50
+subplot 1 1 0 '':title 'Iris plot'
+iris a 'sepal\n length;sepal\n width;petal\n length;petal\n width' '. ';value -1.5;size -2
+ at end verbatim
+
+ at pfig{iris, Example of Iris()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Tube sample, Tape sample, Iris sample, 1D samples
+ at subsection Tube sample
+ at nav{}
+
+Command @ref{tube} draw tube with variable radius. The sample code is:
+ at verbatim
+light on:call 'prepare1d'
+new yc 50 'sin(pi*x)':new xc 50 'cos(pi*x)':new z 50 'x':divto y1 20
+
+subplot 2 2 0 '':title 'Tube plot (default)':box
+tube y 0.05
+
+subplot 2 2 1 '':title 'variable radius':box
+tube y y1
+
+subplot 2 2 2 '':title '"\#" style':box
+tube y 0.05 '#'
+
+subplot 2 2 3:title '3d variant':rotate 50 60:box
+tube xc yc z y2 'r'
+ at end verbatim
+
+ at pfig{tube, Example of Tube()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Tape sample, Torus sample, Tube sample, 1D samples
+ at subsection Tape sample
+ at nav{}
+
+Command @ref{tape} draw tapes which rotate around the curve as normal and binormal. The sample code is:
+ at verbatim
+call 'prepare1d'
+new yc 50 'sin(pi*x)':new xc 50 'cos(pi*x)':new z 50 'x'
+
+subplot 2 2 0 '':title 'Tape plot (default)':box
+tape y:plot y 'k'
+
+subplot 2 2 1:title '3d variant, 2 colors':rotate 50 60:light on:box
+plot xc yc z 'k':tape xc yc z 'rg'
+
+subplot 2 2 2:title '3d variant, x only':rotate 50 60:box
+plot xc yc z 'k':tape xc yc z 'xr':tape xc yc z 'xr#'
+
+subplot 2 2 3:title '3d variant, z only':rotate 50 60:box
+plot xc yc z 'k':tape xc yc z 'zg':tape xc yc z 'zg#'
+ at end verbatim
+
+ at pfig{tape, Example of Tape()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Torus sample, Lamerey sample, Tape sample, 1D samples
+ at subsection Torus sample
+ at nav{}
+
+Command @ref{torus} draw surface of the curve rotation. The sample code is:
+ at verbatim
+call 'prepare1d'
+subplot 2 2 0:title 'Torus plot (default)':light on:rotate 50 60:box
+torus y1 y2
+
+subplot 2 2 1:title '"x" style':light on:rotate 50 60:box
+torus y1 y2 'x'
+
+subplot 2 2 2:title '"z" style':light on:rotate 50 60:box
+torus y1 y2 'z'
+
+subplot 2 2 3:title '"\#" style':light on:rotate 50 60:box
+torus y1 y2 '#'
+ at end verbatim
+
+ at pfig{torus, Example of Torus()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Lamerey sample, Bifurcation sample, Torus sample, 1D samples
+ at subsection Lamerey sample
+ at nav{}
+
+Function @ref{lamerey} draw Lamerey diagram. The sample code is:
+ at verbatim
+subplot 1 1 0 '<_':title 'Lamerey sample'
+axis:xlabel '\i x':ylabel '\bar{\i x} = 2 \i{x}'
+fplot 'x' 'k='
+fplot '2*x' 'b'
+
+lamerey 0.00097 '2*x' 'rv~';size 2
+lamerey -0.00097 '2*x' 'rv~';size 2
+ at end verbatim
+
+ at pfig{lamerey, Example of Lamerey()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Bifurcation sample, Pmap sample, Lamerey sample, 1D samples
+ at subsection Bifurcation sample
+ at nav{}
+
+Function @ref{bifurcation} draw Bifurcation diagram for logistic map. The sample code is:
+ at verbatim
+subplot 1 1 0 '<_':title 'Bifurcation sample'
+ranges 0 4 0 1:axis
+bifurcation 0.005 'x*y*(1-y)' 'r'
+ at end verbatim
+
+ at pfig{bifurcation, Example of Bifurcation()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Pmap sample, , Bifurcation sample, 1D samples
+ at subsection Pmap sample
+ at nav{}
+
+Function @ref{pmap} draw Poincare map -- show intersections of the curve and the surface. The sample code is:
+ at verbatim
+subplot 1 1 0 '<_^':title 'Poincare map sample'
+ode r 'cos(y)+sin(z);cos(z)+sin(x);cos(x)+sin(y)' 'xyz' [0.1,0,0] 0.1 100
+rotate 40 60:copy x r(0):copy y r(1):copy z r(2)
+ranges x y z
+axis:plot x y z 'b':fsurf '0'
+xlabel '\i x' 0:ylabel '\i y' 0:zlabel '\i z'
+
+pmap x y z z 'b#o'
+ at end verbatim
+
+ at pfig{pmap, Example of Pmap()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node 2D samples, 3D samples, 1D samples, Examples
+ at section 2D samples
+ at nav{}
+
+This section is devoted to visualization of 2D data arrays. 2D means the data which depend on 2 indexes (parameters) like matrix z(i,j)=z(x(i),y(j)), i=1...n, j=1...m or in parametric form @{x(i,j),y(i,j),z(i,j)@}. Most of samples will use the same data for plotting. So, I put its initialization in separate function
+ at verbatim
+func 'prepare2d'
+new a 50 40 '0.6*sin(pi*(x+1))*sin(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'
+new b 50 40 '0.6*cos(pi*(x+1))*cos(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'
+return
+ at end verbatim
+Basically, you can put this text after the script. Note, that you need to terminate main script by @ref{stop} command before defining a function.
+
+ at menu
+* Surf sample::
+* SurfC sample::
+* SurfA sample::
+* SurfCA sample::
+* Mesh sample::
+* Fall sample::
+* Belt sample::
+* Boxs sample::
+* Tile sample::
+* TileS sample::
+* Dens sample::
+* Cont sample::
+* ContF sample::
+* ContD sample::
+* ContV sample::
+* Axial sample::
+* Grad sample::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Surf sample, SurfC sample, , 2D samples
+ at subsection Surf sample
+ at nav{}
+
+Command @ref{surf} is most standard way to visualize 2D data array. @code{Surf} use color scheme for coloring (see @ref{Color scheme}). You can use @samp{#} style for drawing black meshes on the surface. The sample code is:
+ at verbatim
+call 'prepare2d'
+subplot 2 2 0:title 'Surf plot (default)':rotate 50 60:light on:box:surf a
+
+subplot 2 2 1:title '"\#" style; meshnum 10':rotate 50 60:box
+surf a '#'; meshnum 10
+
+subplot 2 2 2:title '"." style':rotate 50 60:box
+surf a '.'
+
+new x 50 40 '0.8*sin(pi*x)*sin(pi*(y+1)/2)'
+new y 50 40 '0.8*cos(pi*x)*sin(pi*(y+1)/2)'
+new z 50 40 '0.8*cos(pi*(y+1)/2)'
+subplot 2 2 3:title 'parametric form':rotate 50 60:box
+surf x y z 'BbwrR'
+ at end verbatim
+
+ at pfig{surf, Example of Surf()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node SurfC sample, SurfA sample, Surf sample, 2D samples
+ at subsection SurfC sample
+ at nav{}
+
+Command @ref{surfc} is similar to @ref{surf} but its coloring is determined by another data. The sample code is:
+ at verbatim
+call 'prepare2d'
+title 'SurfC plot':rotate 50 60:light on:box
+surfc a b
+ at end verbatim
+
+ at pfig{surfc, Example of SurfC()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node SurfA sample, SurfCA sample, SurfC sample, 2D samples
+ at subsection SurfA sample
+ at nav{}
+
+Command @ref{surfa} is similar to @ref{surf} but its transparency is determined by another data. The sample code is:
+ at verbatim
+call 'prepare2d'
+title 'SurfA plot':rotate 50 60:light on:alpha on:box
+surfa a b
+ at end verbatim
+
+ at pfig{surfa, Example of SurfA()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node SurfCA sample, Mesh sample, SurfA sample, 2D samples
+ at subsection SurfCA sample
+ at nav{}
+
+Command @ref{surfca} is similar to @ref{surf} but its color and transparency is determined by another data. The sample code is:
+ at verbatim
+call 'prepare2d'
+title 'SurfCA plot':rotate 50 60:light on:alpha on:box
+surfa a b a
+ at end verbatim
+
+ at pfig{surfca, Example of SurfCA()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Mesh sample, Fall sample, SurfCA sample, 2D samples
+ at subsection Mesh sample
+ at nav{}
+
+Command @ref{mesh} draw wired surface. You can use @ref{meshnum} for changing number of lines to be drawn. The sample code is:
+ at verbatim
+call 'prepare2d'
+title 'Mesh plot':rotate 50 60:box
+mesh a
+ at end verbatim
+
+ at pfig{mesh, Example of Mesh()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Fall sample, Belt sample, Mesh sample, 2D samples
+ at subsection Fall sample
+ at nav{}
+
+Command @ref{fall} draw waterfall surface. You can use @ref{meshnum} for changing number of lines to be drawn. Also you can use @samp{x} style for drawing lines in other direction. The sample code is:
+ at verbatim
+call 'prepare2d'
+title 'Fall plot':rotate 50 60:box
+fall a
+ at end verbatim
+
+ at pfig{fall, Example of Fall()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Belt sample, Boxs sample, Fall sample, 2D samples
+ at subsection Belt sample
+ at nav{}
+
+Command @ref{belt} draw surface by belts. You can use @samp{x} style for drawing lines in other direction. The sample code is:
+ at verbatim
+call 'prepare2d'
+title 'Belt plot':rotate 50 60:box
+belt a
+ at end verbatim
+
+ at pfig{belt, Example of Belt()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Boxs sample, Tile sample, Fall sample, 2D samples
+ at subsection Boxs sample
+ at nav{}
+
+Command @ref{boxs} draw surface by boxes. You can use @samp{#} for drawing wire plot. The sample code is:
+ at verbatim
+call 'prepare2d'
+origin 0 0 0
+subplot 2 2 0:title 'Boxs plot (default)':rotate 40 60:light on:box
+boxs a
+
+subplot 2 2 1:title '"\@" style':rotate 50 60:box
+boxs a '@'
+
+subplot 2 2 2:title '"\#" style':rotate 50 60:box
+boxs a '#'
+
+subplot 2 2 3:title 'compare with Tile':rotate 50 60:box
+tile a
+ at end verbatim
+
+ at pfig{boxs, Example of Boxs()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Tile sample, TileS sample, Boxs sample, 2D samples
+ at subsection Tile sample
+ at nav{}
+
+Command @ref{tile} draw surface by tiles. The sample code is:
+ at verbatim
+call 'prepare2d'
+subplot 1 1 0 '':title 'Tiles plot':box
+tile a
+ at end verbatim
+
+ at pfig{tile, Example of Tile()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node TileS sample, Dens sample, Tile sample, 2D samples
+ at subsection TileS sample
+ at nav{}
+
+Command @ref{tiles} is similar to @ref{tile} but tile sizes is determined by another data. This allows one to simulate transparency of the plot. The sample code is:
+ at verbatim
+call 'prepare2d'
+subplot 1 1 0 '':title 'Tiles plot':box
+tiles a b
+ at end verbatim
+
+ at pfig{tiles, Example of TileS()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Dens sample, Cont sample, TileS sample, 2D samples
+ at subsection Dens sample
+ at nav{}
+
+Command @ref{dens} draw density plot for surface. The sample code is:
+ at verbatim
+call 'prepare2d'
+subplot 2 2 0 '':title 'Dens plot (default)':box
+dens a
+
+subplot 2 2 1:title '3d variant':rotate 50 60:box
+dens a
+
+subplot 2 2 2 '':title '"\#" style; meshnum 10':box
+dens a '#'; meshnum 10
+
+new a1 30 40 3 '0.6*sin(2*pi*x+pi*(z+1)/2)*sin(3*pi*y+pi*z) +\
+ 0.4*cos(3*pi*(x*y)+pi*(z+1)^2/2)'
+subplot 2 2 3:title 'several slices':rotate 50 60:box
+dens a1
+ at end verbatim
+
+ at pfig{dens, Example of Dens()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cont sample, ContF sample, Dens sample, 2D samples
+ at subsection Cont sample
+ at nav{}
+
+Command @ref{cont} draw contour lines for surface. You can select automatic (default) or manual levels for contours, print contour labels, draw it on the surface (default) or at plane (as @code{Dens}). The sample code is:
+ at verbatim
+call 'prepare2d'
+list v -0.5 -0.15 0 0.15 0.5
+subplot 2 2 0:title 'Cont plot (default)':rotate 50 60:box
+cont a
+
+subplot 2 2 1:title 'manual levels':rotate 50 60:box
+cont v a
+
+subplot 2 2 2:title '"\_" style':rotate 50 60:box
+cont a '_'
+
+subplot 2 2 3 '':title '"t" style':box
+cont a 't'
+ at end verbatim
+
+ at pfig{cont, Example of Cont()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ContF sample, ContD sample, Cont sample, 2D samples
+ at subsection ContF sample
+ at nav{}
+
+Command @ref{contf} draw filled contours.  You can select automatic (default) or manual levels for contours. The sample code is:
+ at verbatim
+call 'prepare2d'
+list v -0.5 -0.15 0 0.15 0.5
+subplot 2 2 0:title 'ContF plot (default)':rotate 50 60:box
+contf a
+
+subplot 2 2 1:title 'manual levels':rotate 50 60:box
+contf v a
+
+subplot 2 2 2:title '"\_" style':rotate 50 60:box
+contf a '_'
+
+new a1 30 40 3 '0.6*sin(2*pi*x+pi*(z+1)/2)*sin(3*pi*y+pi*z) +\
+ 0.4*cos(3*pi*(x*y)+pi*(z+1)^2/2)'
+subplot 2 2 3:title 'several slices':rotate 50 60:box
+contf a1
+ at end verbatim
+
+ at pfig{contf, Example of ContF()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ContD sample, ContV sample, ContF sample, 2D samples
+ at subsection ContD sample
+ at nav{}
+
+Command @ref{contd} is similar to @code{ContF} but with manual contour colors. The sample code is:
+ at verbatim
+call 'prepare2d'
+list v -0.5 -0.15 0 0.15 0.5
+subplot 2 2 0:title 'ContD plot (default)':rotate 50 60:box
+contd a
+
+subplot 2 2 1:title 'manual levels':rotate 50 60:box
+contd v a
+
+subplot 2 2 2:title '"\_" style':rotate 50 60:box
+contd a '_'
+
+new a1 30 40 3 '0.6*sin(2*pi*x+pi*(z+1)/2)*sin(3*pi*y+pi*z) +\
+ 0.4*cos(3*pi*(x*y)+pi*(z+1)^2/2)'
+subplot 2 2 3:title 'several slices':rotate 50 60:box
+contd a1
+ at end verbatim
+
+ at pfig{contd, Example of ContD()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ContV sample, Axial sample, ContD sample, 2D samples
+ at subsection ContV sample
+ at nav{}
+
+Command @ref{contv} draw vertical cylinders (belts) at contour lines. The sample code is:
+ at verbatim
+call 'prepare2d'
+list v -0.5 -0.15 0 0.15 0.5
+subplot 2 2 0:title 'ContV plot (default)':rotate 50 60:box
+contv a
+
+subplot 2 2 1:title 'manual levels':rotate 50 60:box
+contv v a
+
+subplot 2 2 2:title '"\_" style':rotate 50 60:box
+contv a '_'
+
+subplot 2 2 3:title 'ContV and ContF':rotate 50 60:light on:box
+contv a:contf a:cont a 'k'
+ at end verbatim
+
+ at pfig{contv, Example of ContV()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Axial sample, Grad sample, ContV sample, 2D samples
+ at subsection Axial sample
+ at nav{}
+
+Command @ref{axial} draw surfaces of rotation for contour lines. You can draw wire surfaces (@samp{#} style) or ones rotated in other directions (@samp{x}, @samp{z} styles). The sample code is:
+ at verbatim
+light on:alpha on:call 'prepare2d'
+subplot 2 2 0:title 'Axial plot (default)':rotate 50 60:box
+axial a
+
+subplot 2 2 1:title '"x" style;\".\" style':light on:rotate 50 60:box
+axial a 'x.'
+
+subplot 2 2 2:title '"z" style':light on:rotate 50 60:box
+axial a 'z'
+
+subplot 2 2 3:title '"\#" style':light on:rotate 50 60:box
+axial a '#'
+ at end verbatim
+
+ at pfig{axial, Example of Axial()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Grad sample, , Axial sample, 2D samples
+ at subsection Grad sample
+ at nav{}
+
+Command @ref{grad} draw gradient lines for matrix. The sample code is:
+ at verbatim
+call 'prepare2d'
+subplot 1 1 0 '':title 'Grad plot':box
+grad a:dens a '{u8}w{q8}'
+ at end verbatim
+
+ at pfig{grad, Example of Grad()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node 3D samples, Vector field samples, 2D samples, Examples
+ at section 3D samples
+ at nav{}
+
+This section is devoted to visualization of 3D data arrays. 3D means the data which depend on 3 indexes (parameters) like tensor a(i,j,k)=a(x(i),y(j),x(k)), i=1...n, j=1...m, k=1...l or in parametric form @{x(i,j,k),y(i,j,k),z(i,j,k),a(i,j,k)@}. Most of samples will use the same data for plotting. So, I put its initialization in separate function
+ at verbatim
+func 'prepare3d'
+new c 61 50 40 '-2*(x^2+y^2+z^4-z^2)+0.2'
+new d 61 50 40 '1-2*tanh((x+y)*(x+y))'
+return
+ at end verbatim
+Basically, you can put this text after the script. Note, that you need to terminate main script by @ref{stop} command before defining a function.
+
+ at menu
+* Surf3 sample::
+* Surf3C sample::
+* Surf3A sample::
+* Surf3CA sample::
+* Cloud sample::
+* Dens3 sample::
+* Cont3 sample::
+* ContF3 sample::
+* Dens projection sample::
+* Cont projection sample::
+* ContF projection sample::
+* TriPlot and QuadPlot::
+* Dots sample::
+* Fractal sample::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Surf3 sample, Surf3C sample, , 3D samples
+ at subsection Surf3 sample
+ at nav{}
+
+Command @ref{surf3} is one of most suitable (for my opinion) functions to visualize 3D data. It draw the isosurface(s) -- surface(s) of constant amplitude (3D analogue of contour lines). You can draw wired isosurfaces if specify @samp{#} style. The sample code is:
+ at verbatim
+call 'prepare3d'
+light on:alpha on
+subplot 2 2 0:title 'Surf3 plot':rotate 50 60:box
+surf3 c
+
+subplot 2 2 1:title '"\#" style':rotate 50 60:box
+surf3 c '#'
+
+subplot 2 2 2:title '"." style':rotate 50 60:box
+surf3 c '.'
+ at end verbatim
+
+ at pfig{surf3, Example of Surf3()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Surf3C sample, Surf3A sample, Surf3 sample, 3D samples
+ at subsection Surf3C sample
+ at nav{}
+
+Command @ref{surf3c} is similar to @ref{surf3} but its coloring is determined by another data. The sample code is:
+ at verbatim
+call 'prepare3d'
+title 'Surf3C plot':rotate 50 60:light on:alpha on:box
+surf3c c d
+ at end verbatim
+
+ at pfig{surf3c, Example of Surf3C()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Surf3A sample, Surf3CA sample, Surf3C sample, 3D samples
+ at subsection Surf3A sample
+ at nav{}
+
+Command @ref{surf3a} is similar to @ref{surf3} but its transparency is determined by another data. The sample code is:
+ at verbatim
+call 'prepare3d'
+title 'Surf3A plot':rotate 50 60:light on:alpha on:box
+surf3a c d
+ at end verbatim
+
+ at pfig{surf3a, Example of Surf3A()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Surf3CA sample, Cloud sample, Surf3A sample, 3D samples
+ at subsection Surf3CA sample
+ at nav{}
+
+Command @ref{surf3ca} is similar to @ref{surf3} but its color and transparency is determined by another data. The sample code is:
+ at verbatim
+call 'prepare3d'
+title 'Surf3CA plot':rotate 50 60:light on:alpha on:box
+surf3a c d c
+ at end verbatim
+
+ at pfig{surf3ca, Example of Surf3CA()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cloud sample, Dens3 sample, Surf3CA sample, 3D samples
+ at subsection Cloud sample
+ at nav{}
+
+Command @ref{cloud} draw cloud-like object which is less transparent for higher data values. Similar plot can be created using many (about 10-20) @code{Surf3A(a,a)} isosurfaces. The sample code is:
+ at verbatim
+call 'prepare3d'
+subplot 2 2 0:title 'Cloud plot':rotate 50 60:alpha on:box
+cloud c 'wyrRk'
+
+subplot 2 2 1:title '"i" style':rotate 50 60:box
+cloud c 'iwyrRk'
+
+subplot 2 2 2:title '"." style':rotate 50 60:box
+cloud c '.wyrRk'
+
+subplot 2 2 3:title 'meshnum 10':rotate 50 60:box
+cloud c 'wyrRk'; meshnum 10
+ at end verbatim
+
+ at pfig{cloud, Example of Cloud()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Dens3 sample, Cont3 sample, Cloud sample, 3D samples
+ at subsection Dens3 sample
+ at nav{}
+
+Command @ref{dens3} draw just usual density plot but at slices of 3D data. The sample code is:
+ at verbatim
+call 'prepare3d'
+title 'Dens3 sample':rotate 50 60:alpha on:alphadef 0.7
+origin 0 0 0:box:axis '_xyz'
+dens3 c 'x':dens3 c ':y':dens3 c 'z'
+ at end verbatim
+
+ at pfig{densa, Example of Dens3()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cont3 sample, ContF3 sample, Dens3 sample, 3D samples
+ at subsection Cont3 sample
+ at nav{}
+
+Command @ref{cont3} draw just usual contour lines but at slices of 3D data. The sample code is:
+ at verbatim
+call 'prepare3d'
+title 'Cont3 sample':rotate 50 60:box
+cont3 c 'x':cont3 c:cont3 c 'z'
+ at end verbatim
+
+ at pfig{conta, Example of Cont3()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ContF3 sample, Dens projection sample, Cont3 sample, 3D samples
+ at subsection ContF3 sample
+ at nav{}
+
+Command @ref{contf3} draw just usual filled contours but at slices of 3D data. The sample code is:
+ at verbatim
+call 'prepare3d'
+title 'Cont3 sample':rotate 50 60:box:light on
+contf3 c 'x':contf3 c:contf3 c 'z'
+cont3 c 'xk':cont3 c 'k':cont3 c 'zk'
+ at end verbatim
+
+ at pfig{contfa, Example of ContF3()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Dens projection sample, Cont projection sample, ContF3 sample, 3D samples
+ at subsection Dens projection sample
+ at nav{}
+
+Functions @ref{densz}, @ref{densy}, @ref{densx} draw density plot on plane perpendicular to corresponding axis. One of possible application is drawing projections of 3D field. The sample code is:
+ at verbatim
+call 'prepare3d'
+title 'Dens[XYZ] sample':rotate 50 60:box
+densx {sum c 'x'} '' -1
+densy {sum c 'y'} '' 1
+densz {sum c 'z'} '' -1
+ at end verbatim
+
+ at pfig{dens_xyz, Example of DensX() DensY() DensZ()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cont projection sample, ContF projection sample, Dens projection sample, 3D samples
+ at subsection Cont projection sample
+ at nav{}
+
+Functions @ref{contz}, @ref{conty}, @ref{contx} draw contour lines on plane perpendicular to corresponding axis. One of possible application is drawing projections of 3D field. The sample code is:
+ at verbatim
+call 'prepare3d'
+title 'Cont[XYZ] sample':rotate 50 60:box
+contx {sum c 'x'} '' -1
+conty {sum c 'y'} '' 1
+contz {sum c 'z'} '' -1
+ at end verbatim
+
+ at pfig{cont_xyz, Example of ContX() ContY() ContZ()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ContF projection sample, TriPlot and QuadPlot, Cont projection sample, 3D samples
+ at subsection ContF projection sample
+ at nav{}
+
+Functions @ref{contfz}, @ref{contfy}, @ref{contfx} draw filled contours on plane perpendicular to corresponding axis. One of possible application is drawing projections of 3D field. The sample code is:
+ at verbatim
+call 'prepare3d'
+title 'ContF[XYZ] sample':rotate 50 60:box
+contfx {sum c 'x'} '' -1
+contfy {sum c 'y'} '' 1
+contfz {sum c 'z'} '' -1
+ at end verbatim
+
+ at pfig{contf_xyz, Example of ContFX() ContFY() ContFZ()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node TriPlot and QuadPlot, Dots sample, ContF projection sample, 3D samples
+ at subsection TriPlot and QuadPlot
+ at nav{}
+
+Command @ref{triplot} and @ref{quadplot} draw set of triangles (or quadrangles for @code{QuadPlot}) for irregular data arrays. Note, that you have to provide not only vertexes, but also the indexes of triangles or quadrangles. I.e. perform triangulation by some other library. The sample code is:
+ at verbatim
+list q 0 1 2 3 | 4 5 6 7 | 0 2 4 6 | 1 3 5 7 | 0 4 1 5 | 2 6 3 7
+list xq -1 1 -1 1 -1 1 -1 1
+list yq -1 -1 1 1 -1 -1 1 1
+list zq -1 -1 -1 -1 1 1 1 1
+light on
+subplot 2 2 0:title 'QuadPlot sample':rotate 50 60
+quadplot q xq yq zq 'yr'
+quadplot q xq yq zq '#k'
+
+subplot 2 2 2:title 'QuadPlot coloring':rotate 50 60
+quadplot q xq yq zq yq 'yr'
+quadplot q xq yq zq '#k'
+
+list t 0 1 2 | 0 1 3 | 0 2 3 | 1 2 3
+list xt -1 1 0 0
+list yt -1 -1 1 0
+list zt -1 -1 -1 1
+subplot 2 2 1:title 'TriPlot sample':rotate 50 60
+triplot t xt yt zt 'b'
+triplot t xt yt zt '#k'
+
+subplot 2 2 3:title 'TriPlot coloring':rotate 50 60
+triplot t xt yt zt yt 'cb'
+triplot t xt yt zt '#k'
+tricont t xt yt zt 'B'
+ at end verbatim
+
+ at pfig{triplot, Example of TriPlot() and QuadPlot()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Dots sample, Fractal sample, TriPlot and QuadPlot, 3D samples
+ at subsection Dots sample
+ at nav{}
+
+Command @ref{dots} is another way to draw irregular points. @code{Dots} use color scheme for coloring (see @ref{Color scheme}). The sample code is:
+ at verbatim
+new t 2000 'pi*(rnd-0.5)':new f 2000 '2*pi*rnd'
+copy x 0.9*cos(t)*cos(f):copy y 0.9*cos(t)*sin(f):copy z 0.6*sin(t):copy c cos(2*t)
+subplot 2 2 0:title 'Dots sample':rotate 50 60
+box:dots x y z
+alpha on
+subplot 2 2 1:title 'add transparency':rotate 50 60
+box:dots x y z c
+subplot 2 2 2:title 'add colorings':rotate 50 60
+box:dots x y z x c
+subplot 2 2 3:title 'Only coloring':rotate 50 60
+box:tens x y z x ' .'
+ at end verbatim
+
+ at pfig{dots, Example of Dots()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Fractal sample, , Dots sample, 3D samples
+ at subsection Fractal sample
+ at nav{}
+
+Commands @ref{ifs2d} and @ref{ifs3d} generate points for fractals using iterated function system in 2d and 3d cases correspondingly. The sample codes are:
+ at verbatim
+list A [0.33,0,0,0.33,0,0,0.2] [0.33,0,0,0.33,0.67,0,0.2] [0.33,0,0,0.33,0.33,0.33,0.2]\
+       [0.33,0,0,0.33,0,0.67,0.2] [0.33,0,0,0.33,0.67,0.67,0.2]
+ifs2d fx fy A 100000
+subplot 1 1 0 '<_':title 'IFS 2d sample'
+ranges fx fy:axis
+plot fx fy 'r#o ';size 0.05
+ at end verbatim
+
+ at pfig{ifs2d, Example of IFS fractal (2d case).}
+
+ at verbatim
+list A [0,0,0,0,.18,0,0,0,0,0,0,0,.01] [.85,0,0,0,.85,.1,0,-0.1,0.85,0,1.6,0,.85]\
+        [.2,-.2,0,.2,.2,0,0,0,0.3,0,0.8,0,.07] [-.2,.2,0,.2,.2,0,0,0,0.3,0,0.8,0,.07]
+ifs3d f A 100000
+title 'IFS 3d sample':rotate 50 60
+ranges f(0) f(1) f(2):axis:box
+dots f(0) f(1) f(2) 'G#o';size 0.05
+ at end verbatim
+
+ at pfig{ifs3d, Example of IFS fractal (3d case).}
+
+
+Command @ref{flame2d} generate points for flame fractals in 2d case. The sample codes are:
+ at verbatim
+list A [0.33,0,0,0.33,0,0,0.2] [0.33,0,0,0.33,0.67,0,0.2] [0.33,0,0,0.33,0.33,0.33,0.2]\
+        [0.33,0,0,0.33,0,0.67,0.2] [0.33,0,0,0.33,0.67,0.67,0.2]
+new B 2 3 A.ny '0.3'
+put B 3 0 0 -1
+put B 3 0 1 -1
+put B 3 0 2 -1
+flame2d fx fy A B 1000000
+subplot 1 1 0 '<_':title 'Flame2d sample'
+ranges fx fy:box:axis
+plot fx fy 'r#o ';size 0.05
+ at end verbatim
+
+ at pfig{flame2d, Example of flame fractal (2d case).}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Vector field samples, Hints, 3D samples, Examples
+ at section Vector field samples
+ at nav{}
+
+Vector field visualization (especially in 3d case) is more or less complex task. MathGL provides 3 general types of plots: vector field itself (@code{Vect}), flow threads (@code{Flow}), and flow pipes with radius proportional to field amplitude (@code{Pipe}).
+
+However, the plot may look tangly -- there are too many overlapping lines. I may suggest 2 ways to solve this problem. The first one is to change @code{SetMeshNum} for decreasing the number of hachures. The second way is to use the flow thread chart @code{Flow}, or possible many flow thread from manual position (@code{FlowP}). Unfortunately, I don't know any other methods to visualize 3d vector field. If you know any, e-mail me and I shall add it to MathGL.
+
+Most of samples will use the same data for plotting. So, I put its initialization in separate function
+ at verbatim
+func 'prepare2v'
+new a 20 30 '0.6*sin(pi*(x+1))*sin(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'
+new b 20 30 '0.6*cos(pi*(x+1))*cos(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'
+return
+
+func 'prepare3v'
+define $1 pow(x*x+y*y+(z-0.3)*(z-0.3)+0.03,1.5)
+define $2 pow(x*x+y*y+(z+0.3)*(z+0.3)+0.03,1.5)
+new ex 10 10 10 '0.2*x/$1-0.2*x/$2'
+new ey 10 10 10 '0.2*y/$1-0.2*y/$2'
+new ez 10 10 10 '0.2*(z-0.3)/$1-0.2*(z+0.3)/$2'
+return
+ at end verbatim
+Basically, you can put this text after the script. Note, that you need to terminate main script by @ref{stop} command before defining a function.
+
+ at menu
+* Vect sample::
+* Vect3 sample::
+* Traj sample::
+* Flow sample::
+* Pipe sample::
+* Dew sample::
+ at end menu
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Vect sample, Vect3 sample, , Vector field samples
+ at subsection Vect sample
+ at nav{}
+
+Command @ref{vect} is most standard way to visualize vector fields -- it draw a lot of arrows or hachures for each data cell. It have a lot of options which can be seen on the figure (and in the sample code). @code{Vect} use color scheme for coloring (see @ref{Color scheme}). The sample code is:
+ at verbatim
+call 'prepare2v'
+subplot 3 2 0 '':title 'Vect plot (default)':box
+vect a b
+
+subplot 3 2 1 '':title '"." style; "=" style':box
+vect a b '.='
+
+subplot 3 2 2 '':title '"f" style':box
+vect a b 'f'
+
+subplot 3 2 3 '':title '">" style':box
+vect a b '>'
+
+subplot 3 2 4 '':title '"<" style':box
+vect a b '<'
+
+call 'prepare3v'
+subplot 3 2 5:title '3d variant':rotate 50 60:box
+vect ex ey ez
+ at end verbatim
+
+ at pfig{vect, Example of Vect()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Vect3 sample, Traj sample, Vect sample, Vector field samples
+ at subsection Vect3 sample
+ at nav{}
+
+Command @ref{vect3} draw just usual vector field plot but at slices of 3D data. The sample code is:
+ at verbatim
+origin 0 0 0:call 'prepare3v'
+subplot 2 1 0:title 'Vect3 sample':rotate 50 60
+box:axis '_xyz'
+vect3 ex ey ez 'x':vect3 ex ey ez:vect3 ex ey ez 'z'
+
+subplot 2 1 1:title '"f" style':rotate 50 60
+box:axis '_xyz'
+vect3 ex ey ez 'fx':vect3 ex ey ez 'f':vect3 ex ey ez 'fz'
+grid3 ex 'Wx':grid3 ex 'W':grid3 ex 'Wz'
+ at end verbatim
+
+ at pfig{vecta, Example of Vect3()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Traj sample, Flow sample, Vect3 sample, Vector field samples
+ at subsection Traj sample
+ at nav{}
+
+Command @ref{traj} is 1D analogue of @code{Vect}. It draw vectors from specified points. The sample code is:
+ at verbatim
+call 'prepare1d'
+subplot 1 1 0 '':title 'Traj plot':box
+plot x1 y:traj x1 y y1 y2
+ at end verbatim
+
+ at pfig{traj, Example of Traj()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Flow sample, Pipe sample, Traj sample, Vector field samples
+ at subsection Flow sample
+ at nav{}
+
+Command @ref{flow} is another standard way to visualize vector fields -- it draw lines (threads) which is tangent to local vector field direction. MathGL draw threads from edges of bounding box and from central slices. Sometimes it is not most appropriate variant -- you may want to use @code{FlowP} to specify manual position of threads. @code{Flow} use color scheme for coloring (see @ref{Color scheme}). At this warm color corresponds to normal flow (like attractor), cold one corresponds  [...]
+ at verbatim
+call 'prepare2v'
+subplot 2 2 0 '':title 'Flow plot (default)':box
+flow a b
+
+subplot 2 2 1 '':title '"v" style':box
+flow a b 'v'
+
+subplot 2 2 2 '':title 'from edges only':box
+flow a b '#'
+
+call 'prepare3v'
+subplot 2 2 3:title '3d variant':rotate 50 60:box
+flow ex ey ez
+ at end verbatim
+
+ at pfig{flow, Example of Flow()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Pipe sample, Dew sample, Flow sample, Vector field samples
+ at subsection Pipe sample
+ at nav{}
+
+Command @ref{pipe} is similar to @ref{flow} but draw pipes (tubes) which radius is proportional to the amplitude of vector field. @code{Pipe} use color scheme for coloring (see @ref{Color scheme}). At this warm color corresponds to normal flow (like attractor), cold one corresponds to inverse flow (like source). The sample code is:
+ at verbatim
+call 'prepare2v'
+subplot 2 2 0 '':title 'Pipe plot (default)':light on:box
+pipe a b
+
+subplot 2 2 1 '':title '"i" style':box
+pipe a b 'i'
+
+subplot 2 2 2 '':title 'from edges only':box
+pipe a b '#'
+
+call 'prepare3v'
+subplot 2 2 3:title '3d variant':rotate 50 60:box
+pipe ex ey ez '' 0.1
+ at end verbatim
+
+ at pfig{pipe, Example of Pipe()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Dew sample, , Pipe sample, Vector field samples
+ at subsection Dew sample
+ at nav{}
+
+Command @ref{dew} is similar to @code{Vect} but use drops instead of arrows. The sample code is:
+ at verbatim
+call 'prepare2v'
+subplot 1 1 0 '':title 'Dew plot':light on:box
+dew a b
+ at end verbatim
+
+ at pfig{dew, Example of Dew()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Hints, FAQ, Vector field samples, Examples
+ at section Hints
+ at nav{}
+
+In this section I've included some small hints and advices for the improving of the quality of plots and for the demonstration of some non-trivial features of MathGL library. In contrast to previous examples I showed mostly the idea but not the whole drawing function.
+
+ at menu
+* ``Compound'' graphics::
+* Transparency and lighting::
+* Types of transparency::
+* Axis projection::
+* Adding fog::
+* Lighting sample::
+* Using primitives::
+* STFA sample::
+* Mapping visualization::
+* Data interpolation::
+* Making regular data::
+* Making histogram::
+* Nonlinear fitting hints::
+* PDE solving hints::
+* Drawing phase plain::
+* Pulse properties::
+* Using MGL parser::
+* Using options::
+* ``Templates''::
+* Stereo image::
+* Reduce memory usage::
+* Saving and scanning file::
+* Mixing bitmap and vector output::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ``Compound'' graphics, Transparency and lighting, , Hints
+ at subsection ``Compound'' graphics
+ at nav{}
+
+As I noted above, MathGL functions (except the special one, like Clf()) do  not erase the previous plotting but just add the new one. It allows one to draw ``compound'' plots easily. For example, popular Matlab command @code{surfc} can be emulated in MathGL by 2 calls:
+ at verbatim
+  Surf(a);
+  Cont(a, "_");     // draw contours at bottom
+ at end verbatim
+Here @var{a} is 2-dimensional data for the plotting, @code{-1} is the value of z-coordinate at which the contour should be plotted (at the bottom in this example). Analogously, one can draw density plot instead of contour lines and so on.
+
+Another nice plot is contour lines plotted directly on the surface:
+ at verbatim
+  Light(true);       // switch on light for the surface
+  Surf(a, "BbcyrR"); // select 'jet' colormap for the surface
+  Cont(a, "y");      // and yellow color for contours
+ at end verbatim
+The possible difficulties arise in black&white case, when the color of the surface can be close to the color of a contour line. In that case I may suggest the following code:
+ at verbatim
+  Light(true);   // switch on light for the surface
+  Surf(a, "kw"); // select 'gray' colormap for the surface
+  CAxis(-1,0);   // first draw for darker surface colors
+  Cont(a, "w");  // white contours
+  CAxis(0,1);    // now draw for brighter surface colors
+  Cont(a, "k");  // black contours
+  CAxis(-1,1);   // return color range to original state
+ at end verbatim
+The idea is to divide the color range on 2 parts (dark and bright) and to select the contrasting color for contour lines for each of part.
+
+Similarly, one can plot flow thread over density plot of vector field amplitude (this is another amusing plot from Matlab) and so on. The list of compound graphics can be prolonged but I hope that the general idea is clear.
+
+Just for illustration I put here following sample code:
+ at verbatim
+call 'prepare2v'
+call 'prepare3d'
+new v 10:fill v -0.5 1:copy d sqrt(a^2+b^2)
+subplot 2 2 0:title 'Surf + Cont':rotate 50 60:light on:box
+surf a:cont a 'y'
+
+subplot 2 2 1 '':title 'Flow + Dens':light off:box
+flow a b 'br':dens d
+
+subplot 2 2 2:title 'Mesh + Cont':rotate 50 60:box
+mesh a:cont a '_'
+
+subplot 2 2 3:title 'Surf3 + ContF3':rotate 50 60:light on
+box:contf3 v c 'z' 0:contf3 v c 'x':contf3 v c
+cut 0 -1 -1 1 0 1.1
+contf3 v c 'z' c.nz-1:surf3 c -0.5
+ at end verbatim
+
+ at pfig{combined, Example of ``combined'' plots}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Transparency and lighting, Types of transparency, ``Compound'' graphics, Hints
+ at subsection Transparency and lighting
+ at nav{}
+
+Here I want to show how transparency and lighting both and separately change the look of a surface. So, there is code and picture for that:
+ at verbatim
+call 'prepare2d'
+subplot 2 2 0:title 'default':rotate 50 60:box
+surf a
+
+subplot 2 2 1:title 'light on':rotate 50 60:box
+light on:surf a
+
+subplot 2 2 3:title 'light on; alpha on':rotate 50 60:box
+alpha on:surf a
+
+subplot 2 2 2:title 'alpha on':rotate 50 60:box
+light off:surf a
+ at end verbatim
+
+ at pfig{alpha, Example of transparency and lightings}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Types of transparency, Axis projection, Transparency and lighting, Hints
+ at subsection Types of transparency
+ at nav{}
+
+MathGL library has advanced features for setting and handling the surface transparency. The simplest way to add transparency is the using of command @ref{alpha}. As a result, all further surfaces (and isosurfaces, density plots and so on) become transparent. However, their  look can be additionally improved.
+
+The value of transparency can be different from surface to surface. To do it just use @code{SetAlphaDef} before the drawing of the surface, or use option @code{alpha} (see @ref{Command options}). If its value is close to 0 then the surface becomes more and more transparent. Contrary, if its value is close to 1 then the surface becomes practically non-transparent.
+
+Also you can change the way how the light goes through overlapped surfaces. The function @code{SetTranspType} defines it. By default the usual transparency is used (@samp{0}) -- surfaces below is less visible than the upper ones. A ``glass-like'' transparency (@samp{1}) has a different look -- each surface just decreases the background light (the surfaces are commutable in this case).
+
+A ``neon-like'' transparency (@samp{2}) has more interesting look. In this case a surface is the light source (like a lamp on the dark background) and just adds some intensity to the color. At this, the library sets automatically the black color for the background and changes the default line color to white.
+
+As example I shall show several plots for different types of transparency. The code is the same except the values of @code{SetTranspType} function:
+ at verbatim
+call 'prepare2d'
+alpha on:light on
+transptype 0:clf
+subplot 2 2 0:rotate 50 60:surf a:box
+subplot 2 2 1:rotate 50 60:dens a:box
+subplot 2 2 2:rotate 50 60:cont a:box
+subplot 2 2 3:rotate 50 60:axial a:box
+ at end verbatim
+
+ at pfig{type0, Example of @code{SetTranspType(0)}.}
+ at pfig{type1, Example of @code{SetTranspType(1)}.}
+ at pfig{type2, Example of @code{SetTranspType(2)}.}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Axis projection, Adding fog, Ternary axis, Hints
+ at subsection Axis projection
+ at nav{}
+
+You can easily make 3D plot and draw its x-,y-,z-projections (like in CAD) by using @ref{ternary} function with arguments: 4 for Cartesian, 5 for Ternary and 6 for Quaternary coordinates. The sample code is:
+ at verbatim
+ranges 0 1 0 1 0 1
+new x 50 '0.25*(1+cos(2*pi*x))'
+new y 50 '0.25*(1+sin(2*pi*x))'
+new z 50 'x'
+new a 20 30 '30*x*y*(1-x-y)^2*(x+y<1)'
+new rx 10 'rnd':new ry 10:fill ry '(1-v)*rnd' rx
+light on
+
+title 'Projection sample':ternary 4:rotate 50 60
+box:axis:grid
+plot x y z 'r2':surf a '#'
+xlabel 'X':ylabel 'Y':zlabel 'Z'
+ at end verbatim
+
+ at pfig{projection, Example of axis projections}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Adding fog, Lighting sample, Axis projection, Hints
+ at subsection Adding fog
+ at nav{}
+
+MathGL can add a fog to the image. Its switching on is rather simple -- just use @ref{fog} function. There is the only feature -- fog is applied for whole image. Not to particular subplot. The sample code is:
+ at verbatim
+call 'prepare2d'
+title 'Fog sample':rotate 50 60:light on
+fog 1
+box:surf a:cont a 'y'
+ at end verbatim
+
+ at pfig{fog, Example of @code{Fog()}.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Lighting sample, Using primitives, Adding fog, Hints
+ at subsection Lighting sample
+ at nav{}
+
+In contrast to the most of other programs, MathGL supports several (up to 10) light sources. Moreover, the color each of them can be different: white (this is usual), yellow, red, cyan, green and so on. The use of several light sources may be interesting for the highlighting of some peculiarities of the plot or just to make an amusing picture. Note, each light source can be switched on/off individually. The sample code is:
+ at verbatim
+call 'prepare2d'
+title 'Several light sources':rotate 50 60:light on
+light 1 0 1 0 'c':light 2 1 0 0 'y':light 3 0 -1 0 'm'
+box:surf a 'h'
+ at end verbatim
+
+ at pfig{several_light, Example of several light sources.}
+
+Additionally, you can use local light sources and set to use @ref{diffuse} reflection instead of specular one (by default) or both kinds. Note, I use @ref{attachlight} command to keep light settings relative to subplot.
+ at verbatim
+light on: attachlight on
+call 'prepare2d'
+subplot 2 2 0:title 'Default':rotate 50 60:box:surf a
+line -1 -0.7 1.7 -1 -0.7 0.7 'BA'
+
+subplot 2 2 1:title 'Local':rotate 50 60
+light 0 1 0 1 -2 -1 -1
+line 1 0 1 -1 -1 0 'BAO':box:surf a
+
+subplot 2 2 2:title 'no diffuse':rotate 50 60
+diffuse 0
+line 1 0 1 -1 -1 0 'BAO':box:surf a
+
+subplot 2 2 3:title 'diffusive only':rotate 50 60
+diffuse 0.5:light 0 1 0 1 -2 -1 -1 'w' 0
+line 1 0 1 -1 -1 0 'BAO':box:surf a
+ at end verbatim
+
+ at pfig{light, Example of different types of lighting.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Using primitives, STFA sample, Lighting sample, Hints
+ at subsection Using primitives
+ at nav{}
+
+MathGL provide a set of functions for drawing primitives (see @ref{Primitives}). Primitives are low level object, which used by most of plotting functions. Picture below demonstrate some of commonly used primitives.
+ at verbatim
+subplot 2 2 0 '':title 'Line, Curve, Rhomb, Ellipse' '' -1.5
+line -1 -1 -0.5 1 'qAI'
+curve -0.6 -1 1 1 0 1 1 1 'rA'
+ball 0 -0.5 '*':ball 1 -0.1 '*'
+rhomb 0 0.4 1 0.9 0.2 'b#'
+rhomb 0 0 1 0.4 0.2 'cg@'
+ellipse 0 -0.5 1 -0.1 0.2 'u#'
+ellipse 0 -1 1 -0.6 0.2 'm@'
+
+light on
+subplot 2 2 1:title 'Face[xyz]':rotate 50 60:box
+facex 1 0 -1 1 1 'r':facey -1 -1 -1 1 1 'g':facez 1 -1 -1 -1 1 'b'
+face -1 -1 1 -1 1 1 1 -1 0 1 1 1 'bmgr'
+
+subplot 2 2 3 '':title 'Cone'
+cone -0.7 -0.3 0 -0.7 0.7 0.5 0.2 0.1 'b':text -0.7 -0.7 'no edges\n(default)'
+cone 0 -0.3 0 0 0.7 0.5 0.2 0.1 'g@':text 0 -0.7 'with edges\n('\@' style)'
+cone 0.7 -0.3 0 0.7 0.7 0.5 0.2 0.1 'ry':text 0.7 -0.7 '"arrow" with\n{}gradient'
+
+subplot 2 2 2 '':title 'Sphere and Drop'
+line -0.9 0 1 0.9 0 1
+text -0.9 -0.7 'sh=0':drop -0.9 0 0 1 0.5 'r' 0:ball -0.9 0 1 'k'
+text -0.3 -0.7 'sh=0.33':drop -0.3 0 0 1 0.5 'r' 0.33:ball -0.3 0 1 'k'
+text 0.3 -0.7 'sh=0.67':drop 0.3 0 0 1 0.5 'r' 0.67:ball 0.3 0 1 'k'
+text 0.9 -0.7 'sh=1':drop 0.9 0 0 1 0.5 'r' 1:ball 0.9 0 1 'k'
+ at end verbatim
+
+ at pfig{primitives, Primitives in MathGL.}
+
+Generally, you can create arbitrary new kind of plot using primitives. For example, MathGL don't provide any special functions for drawing molecules. However, you can do it using only one type of primitives @ref{drop}. The sample code is:
+ at verbatim
+alpha on:light on
+subplot 2 2 0 '':title 'Methane, CH_4':rotate 60 120
+sphere 0 0 0 0.25 'k':drop 0 0 0 0 0 1 0.35 'h' 1 2:sphere 0 0 0.7 0.25 'g'
+drop 0 0 0 -0.94 0 -0.33 0.35 'h' 1 2:sphere -0.66 0 -0.23 0.25 'g'
+drop 0 0 0 0.47 0.82 -0.33 0.35 'h' 1 2:sphere 0.33 0.57 -0.23 0.25 'g'
+drop 0 0 0 0.47 -0.82 -0.33 0.35 'h' 1 2:sphere 0.33 -0.57 -0.23 0.25 'g'
+
+subplot 2 2 1 '':title 'Water, H{_2}O':rotate 60 100
+sphere 0 0 0 0.25 'r':drop 0 0 0 0.3 0.5 0 0.3 'm' 1 2:sphere 0.3 0.5 0 0.25 'g'
+drop 0 0 0 0.3 -0.5 0 0.3 'm' 1 2:sphere 0.3 -0.5 0 0.25 'g'
+
+subplot 2 2 2 '':title 'Oxygen, O_2':rotate 60 120
+drop 0 0.5 0 0 -0.3 0 0.3 'm' 1 2:sphere 0 0.5 0 0.25 'r'
+drop 0 -0.5 0 0 0.3 0 0.3 'm' 1 2:sphere 0 -0.5 0 0.25 'r'
+
+subplot 2 2 3 '':title 'Ammonia, NH_3':rotate 60 120
+sphere 0 0 0 0.25 'b':drop 0 0 0 0.33 0.57 0 0.32 'n' 1 2
+sphere 0.33 0.57 0 0.25 'g':drop 0 0 0 0.33 -0.57 0 0.32 'n' 1 2
+sphere 0.33 -0.57 0 0.25 'g':drop 0 0 0 -0.65 0 0 0.32 'n' 1 2
+sphere -0.65 0 0 0.25 'g'
+ at end verbatim
+
+ at pfig{molecule, Example of molecules drawing.}
+
+Moreover, some of special plots can be more easily produced by primitives rather than by specialized function. For example, Venn diagram can be produced by @code{Error} plot:
+ at verbatim
+list x -0.3 0 0.3:list y 0.3 -0.3 0.3:list e 0.7 0.7 0.7
+title 'Venn-like diagram':alpha on
+error x y e e '!rgb@#o'
+ at end verbatim
+You see that you have to specify and fill 3 data arrays. The same picture can be produced by just 3 calls of @ref{circle} function:
+ at verbatim
+title 'Venn-like diagram':alpha on
+circle -0.3 0.3 0.7 'rr@'
+circle 0 -0.3 0.7 'gg@'
+circle 0.3 0.3 0.7 'bb@'
+ at end verbatim
+Of course, the first variant is more suitable if you need to plot a lot of circles. But for few ones the usage of primitives looks easy.
+
+ at pfig{venn, Example of Venn diagram.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node STFA sample, Mapping visualization, Using primitives, Hints
+ at subsection STFA sample
+ at nav{}
+
+Short-time Fourier Analysis (@ref{stfa}) is one of informative method for analyzing long rapidly oscillating 1D data arrays. It is used to determine the sinusoidal frequency and phase content of local sections of a signal as it changes over time.
+
+MathGL can find and draw STFA result. Just to show this feature I give following sample. Initial data arrays is 1D arrays with step-like frequency. Exactly this you can see at bottom on the STFA plot. The sample code is:
+ at verbatim
+new a 2000:new b 2000
+fill a 'cos(50*pi*x)*(x<-.5)+cos(100*pi*x)*(x<0)*(x>-.5)+\
+cos(200*pi*x)*(x<.5)*(x>0)+cos(400*pi*x)*(x>.5)'
+
+subplot 1 2 0 '<_':title 'Initial signal'
+plot a:axis:xlabel '\i t'
+
+subplot 1 2 1 '<_':title 'STFA plot'
+stfa a b 64:axis:ylabel '\omega' 0:xlabel '\i t'
+ at end verbatim
+
+ at pfig{stfa, Example of STFA().}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Mapping visualization, Data interpolation, STFA sample, Hints
+ at subsection Mapping visualization
+ at nav{}
+
+Sometime ago I worked with mapping and have a question about its visualization. Let me remember you that mapping is some transformation rule for one set of number to another one. The 1d mapping is just an ordinary function -- it takes a number and transforms it to another one. The 2d mapping (which I used) is a pair of functions which take 2 numbers and transform them to another 2 ones. Except general plots (like @ref{surfc}, @ref{surfa}) there is a special plot -- Arnold diagram. It sho [...]
+
+I tried to make such plot in @ref{map}. It shows the set of points or set of faces, which final position is the result of mapping. At this, the color gives information about their initial position and the height describes Jacobian value of the transformation. Unfortunately, it looks good only for the simplest mapping but for the  real multivalent quasi-chaotic mapping it produces a confusion. So, use it if you like :).
+
+The sample code for mapping visualization is:
+ at verbatim
+new a 50 40 'x':new b 50 40 'y':zrange -2 2:text 0 0 '\to'
+subplot 2 1 0:text 0 1.1 '\{x, y\}' '' -2:box
+map a b 'brgk'
+
+subplot 2 1 1:box
+text 0 1.1 '\{\frac{x^3+y^3}{2}, \frac{x-y}{2}\}' '' -2
+fill a '(x^3+y^3)/2':fill b '(x-y)/2':map a b 'brgk'
+ at end verbatim
+
+ at pfig{map, Example of Map().}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Data interpolation, Making regular data, Mapping visualization, Hints
+ at subsection Data interpolation
+ at nav{}
+
+There are many functions to get interpolated values of a data array. Basically all of them can be divided by 3 categories:
+ at enumerate
+ at item functions which return single value at given point (see @ref{Interpolation} and @code{mglGSpline()} in @ref{Global functions});
+ at item functions @ref{subdata} and @ref{evaluate} for indirect access to data elements;
+ at item functions @ref{refill}, @ref{gspline} and @ref{datagrid} which fill regular (rectangular) data array by interpolated values.
+ at end enumerate
+
+The usage of first category is rather straightforward and don't need any special comments.
+
+There is difference in indirect access functions. Function @ref{subdata} use use step-like interpolation to handle correctly single @code{nan} values in the data array. Contrary, function @ref{evaluate} use local spline interpolation, which give smoother output but spread @code{nan} values. So, @ref{subdata} should be used for specific data elements (for example, for given column), and @ref{evaluate} should be used for distributed elements (i.e. consider data array as some field). Follow [...]
+ at verbatim
+subplot 1 1 0 '':title 'SubData vs Evaluate'
+new in 9 'x^3/1.1':plot in 'ko ':box
+new arg 99 '4*x+4'
+evaluate e in arg off:plot e 'b.'; legend 'Evaluate'
+subdata s in arg:plot s 'r.';legend 'SubData'
+legend 2
+ at end verbatim
+
+ at pfig{indirect, Example of indirect data access.}
+
+Example of @ref{datagrid} usage is done in @ref{Making regular data}. Here I want to show the peculiarities of @ref{refill} and @ref{gspline} functions. Both functions require argument(s) which provide coordinates of the data values, and return rectangular data array which equidistantly distributed in axis range. So, in opposite to @ref{evaluate} function, @ref{refill} and @ref{gspline} can interpolate non-equidistantly distributed data. At this both functions @ref{refill} and @ref{gspli [...]
+ at verbatim
+new x 10 '0.5+rnd':cumsum x 'x':norm x -1 1
+copy y sin(pi*x)/1.5
+subplot 2 2 0 '<_':title 'Refill sample'
+box:axis:plot x y 'o ':fplot 'sin(pi*x)/1.5' 'B:'
+new r 100:refill r x y:plot r 'r'
+
+subplot 2 2 1 '<_':title 'Global spline'
+box:axis:plot x y 'o ':fplot 'sin(pi*x)/1.5' 'B:'
+new r 100:gspline r x y:plot r 'r'
+
+new y 10 '0.5+rnd':cumsum y 'x':norm y -1 1
+copy xx x:extend xx 10
+copy yy y:extend yy 10:transpose yy
+copy z sin(pi*xx*yy)/1.5
+alpha on:light on
+subplot 2 2 2:title '2d regular':rotate 40 60
+box:axis:mesh xx yy z 'k'
+new rr 100 100:refill rr x y z:surf rr
+
+new xx 10 10 '(x+1)/2*cos(y*pi/2-1)'
+new yy 10 10 '(x+1)/2*sin(y*pi/2-1)'
+copy z sin(pi*xx*yy)/1.5
+subplot 2 2 3:title '2d non-regular':rotate 40 60
+box:axis:plot xx yy z 'ko '
+new rr 100 100:refill rr xx yy z:surf rr
+ at end verbatim
+
+ at pfig{refill, Example of non-equidistant data interpolation.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Making regular data, Making histogram, Data interpolation, Hints
+ at subsection Making regular data
+ at nav{}
+
+Sometimes, one have only unregular data, like as data on triangular grids, or experimental results and so on. Such kind of data cannot be used as simple as regular data (like matrices). Only few functions, like @ref{dots}, can handle unregular data as is.
+
+However, one can use built in triangulation functions for interpolating unregular data points to a regular data grids. There are 2 ways. First way, one can use @ref{triangulation} function to obtain list of vertexes for triangles. Later this list can be used in functions like @ref{triplot} or @ref{tricont}. Second way consist in usage of @ref{datagrid} function, which fill regular data grid by interpolated values, assuming that coordinates of the data grid is equidistantly distributed in [...]
+ at verbatim
+new x 100 '2*rnd-1':new y 100 '2*rnd-1':copy z x^2-y^2
+# first way - plot triangular surface for points
+triangulate d x y
+title 'Triangulation'
+rotate 50 60:box:light on
+triplot d x y z:triplot d x y z '#k'
+# second way - make regular data and plot it
+new g 30 30:datagrid g x y z:mesh g 'm'
+ at end verbatim
+
+ at pfig{triangulation, Example of triangulation.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Making histogram, Nonlinear fitting hints, Making regular data, Hints
+ at subsection Making histogram
+ at nav{}
+
+Using the @ref{hist} function(s) for making regular distributions is one of useful fast methods to process and plot irregular data. @code{Hist} can be used to find some momentum of set of points by specifying weight function. It is possible to create not only 1D distributions but also 2D and 3D ones. Below I place the simplest sample code which demonstrate @ref{hist} usage:
+ at verbatim
+new x 10000 '2*rnd-1':new y 10000 '2*rnd-1':copy z exp(-6*(x^2+y^2))
+hist xx x z:norm xx 0 1:hist yy y z:norm yy 0 1
+multiplot 3 3 3 2 2 '':ranges -1 1 -1 1 0 1:box:dots x y z 'wyrRk'
+multiplot 3 3 0 2 1 '':ranges -1 1 0 1:box:bars xx
+multiplot 3 3 5 1 2 '':ranges 0 1 -1 1:box:barh yy
+subplot 3 3 2:text 0.5 0.5 'Hist and\n{}MultiPlot\n{}sample' 'a' -3
+ at end verbatim
+
+ at pfig{hist, Example of Hist().}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Nonlinear fitting hints, PDE solving hints, Making histogram, Hints
+ at subsection Nonlinear fitting hints
+ at nav{}
+
+Nonlinear fitting is rather simple. All that you need is the data to fit, the approximation formula and the list of coefficients to fit (better with its initial guess values). Let me demonstrate it on the following simple example. First, let us use sin function with some random noise:
+ at verbatim
+new dat 100 '0.4*rnd+0.1+sin(2*pi*x)'
+new in 100 '0.3+sin(2*pi*x)'
+ at end verbatim
+and plot it to see that data we will fit
+ at verbatim
+title 'Fitting sample':yrange -2 2:box:axis:plot dat 'k. '
+ at end verbatim
+
+The next step is the fitting itself. For that let me specify an initial values @var{ini} for coefficients @samp{abc} and do the fitting for approximation formula @samp{a+b*sin(c*x)}
+ at verbatim
+list ini 1 1 3:fit res dat 'a+b*sin(c*x)' 'abc' ini
+ at end verbatim
+Now display it
+ at verbatim
+plot res 'r':plot in 'b'
+text -0.9 -1.3 'fitted:' 'r:L'
+putsfit 0 -1.8 'y = ' 'r'
+text 0 2.2 'initial: y = 0.3+sin(2\pi x)' 'b'
+ at end verbatim
+
+NOTE! the fitting results may have strong dependence on initial values for coefficients due to algorithm features. The problem is that in general case there are several local "optimums" for coefficients and the program returns only first found one! There are no guaranties that it will be the best. Try for example to set @code{ini[3] = @{0, 0, 0@}} in the code above.
+
+The full sample code for nonlinear fitting is:
+ at verbatim
+new dat 100 '0.4*rnd+0.1+sin(2*pi*x)'
+new in 100 '0.3+sin(2*pi*x)'
+list ini 1 1 3:fit res dat 'a+b*sin(c*x)' 'abc' ini
+title 'Fitting sample':yrange -2 2:box:axis:plot dat 'k. '
+plot res 'r':plot in 'b'
+text -0.9 -1.3 'fitted:' 'r:L'
+putsfit 0 -1.8 'y = ' 'r'
+text 0 2.2 'initial: y = 0.3+sin(2\pi x)' 'b'
+ at end verbatim
+
+ at pfig{fit, Example of nonlinear fitting.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node PDE solving hints, Drawing phase plain, Nonlinear fitting hints, Hints
+ at subsection PDE solving hints
+ at nav{}
+
+Solving of Partial Differential Equations (PDE, including beam tracing) and ray tracing (or finding particle trajectory) are more or less common task. So, MathGL have several functions for that. There are @ref{ray} for ray tracing, @ref{pde} for PDE solving, @ref{qo2d} for beam tracing in 2D case (see @ref{Global functions}). Note, that these functions take ``Hamiltonian'' or equations as string values. And I don't plan now to allow one to use user-defined functions. There are 2 reasons: [...]
+
+The ray tracing can be done by @ref{ray} function. Really ray tracing equation is Hamiltonian equation for 3D space. So, the function can be also used for finding a particle trajectory (i.e. solve Hamiltonian ODE) for 1D, 2D or 3D cases. The function have a set of arguments. First of all, it is Hamiltonian which defined the media (or the equation) you are planning to use. The Hamiltonian is defined by string which may depend on coordinates @samp{x}, @samp{y}, @samp{z}, time @samp{t} (for [...]
+ at verbatim
+  const char *ham = "p^2+q^2-x-1+i*0.5*(y+x)*(y>-x)";
+  mglData r = mglRay(ham, mglPoint(-0.7, -1), mglPoint(0, 0.5), 0.02, 2);
+ at end verbatim
+This example calculate the reflection from linear layer (media with Hamiltonian @samp{p^2+q^2-x-1}=@math{p_x^2+p_y^2-x-1}). This is parabolic curve. The resulting array have 7 columns which contain data for @{x,y,z,p,q,v,t@}.
+
+The solution of PDE is a bit more complicated. As previous you have to specify the equation as pseudo-differential operator @math{\hat H(x, \nabla)} which is called sometime as ``Hamiltonian'' (for example, in beam tracing). As previously, it is defined by string which may depend on coordinates @samp{x}, @samp{y}, @samp{z} (but not time!), momentums @samp{p}=@math{(d/dx)/i k_0}, @samp{q}=@math{(d/dy)/i k_0} and field amplitude @samp{u}=@math{|u|}. The evolutionary coordinate is @samp{z}  [...]
+
+Next step is specifying the initial conditions at @samp{z} equal to minimal z-axis value. The function need 2 arrays for real and for imaginary part. Note, that coordinates x,y,z are supposed to be in specified axis range. So, the data arrays should have corresponding scales. Finally, you may set the integration step and parameter k0=@math{k_0}. Also keep in mind, that internally the 2 times large box is used (for suppressing numerical reflection from boundaries) and the equation should  [...]
+
+Final comment is concerning the possible form of pseudo-differential operator @math{H}. At this moment, simplified form of operator @math{H} is supported -- all ``mixed'' terms (like @samp{x*p}->x*d/dx) are excluded. For example, in 2D case this operator is effectively @math{H = f(p,z) + g(x,z,u)}. However commutable combinations (like @samp{x*q}->x*d/dy) are allowed for 3D case.
+
+So, for example let solve the equation for beam deflected from linear layer and absorbed later. The operator will have the form @samp{"p^2+q^2-x-1+i*0.5*(z+x)*(z>-x)"} that correspond to equation @math{1/ik_0 * du/dz + d^2 u/dx^2 + d^2 u/dy^2 + x * u + i (x+z)/2 * u = 0}. This is typical equation for Electron Cyclotron (EC) absorption in magnetized plasmas. For initial conditions let me select the beam with plane phase front @math{exp(-48*(x+0.7)^2)}. The corresponding code looks like this:
+ at verbatim
+new re 128 'exp(-48*(x+0.7)^2)':new im 128
+pde a 'p^2+q^2-x-1+i*0.5*(z+x)*(z>-x)' re im 0.01 30
+transpose a
+subplot 1 1 0 '<_':title 'PDE solver'
+axis:xlabel '\i x':ylabel '\i z'
+crange 0 1:dens a 'wyrRk'
+fplot '-x' 'k|'
+text 0 0.95 'Equation: ik_0\partial_zu + \Delta u + x\cdot u +\
+ i \frac{x+z}{2}\cdot u = 0\n{}absorption: (x+z)/2 for x+z>0'
+ at end verbatim
+
+ at pfig{pde, Example of PDE solving.}
+
+The next example is example of beam tracing. Beam tracing equation is special kind of PDE equation written in coordinates accompanied to a ray. Generally this is the same parameters and limitation as for PDE solving but the coordinates are defined by the ray and by parameter of grid width @var{w} in direction transverse the ray. So, you don't need to specify the range of coordinates. @strong{BUT} there is limitation. The accompanied coordinates are well defined only for smooth enough ray [...]
+
+You may use following code for obtaining the same solution as in previous example:
+ at verbatim
+define $1 'p^2+q^2-x-1+i*0.5*(y+x)*(y>-x)'
+subplot 1 1 0 '<_':title 'Beam and ray tracing'
+ray r $1 -0.7 -1 0 0 0.5 0 0.02 2:plot r(0) r(1) 'k'
+axis:xlabel '\i x':ylabel '\i z'
+new re 128 'exp(-48*x^2)':new im 128
+new xx 1:new yy 1
+qo2d a $1 re im r 1 30 xx yy
+crange 0 1:dens xx yy a 'wyrRk':fplot '-x' 'k|'
+text 0 0.85 'absorption: (x+y)/2 for x+y>0'
+text 0.7 -0.05 'central ray'
+ at end verbatim
+
+ at pfig{qo2d, Example of beam tracing.}
+
+Note, the @ref{pde} is fast enough and suitable for many cases routine. However, there is situations then media have both together: strong spatial dispersion and spatial inhomogeneity. In this, case the @ref{pde} will produce incorrect result and you need to use advanced PDE solver @ref{apde}. For example, a wave beam, propagated in plasma, described by Hamiltonian @math{exp(-x^2-p^2)}, will have different solution for using of simplification and advanced PDE solver:
+ at verbatim
+ranges -1 1 0 2 0 2
+new ar 256 'exp(-2*(x+0.0)^2)':new ai 256
+
+apde res1 'exp(-x^2-p^2)' ar ai 0.01:transpose res1
+subplot 1 2 0 '_':title 'Advanced PDE solver'
+ranges 0 2 -1 1:crange res1
+dens res1:box                                                                     
+axis:xlabel '\i z':ylabel '\i x'                                                  
+text -0.5 0.2 'i\partial_z\i u = exp(-\i x^2+\partial_x^2)[\i u]' 'y'             
+                                                                                  
+pde res2 'exp(-x^2-p^2)' ar ai 0.01
+subplot 1 2 1 '_':title 'Simplified PDE solver'                                   
+dens res2:box                                                                     
+axis:xlabel '\i z':ylabel '\i x'                                                  
+text -0.5 0.2 'i\partial_z\i u \approx\ exp(-\i x^2)\i u+exp(\partial_x^2)[\i u]' 'y'
+ at end verbatim
+
+ at pfig{apde, Comparison of simplified and advanced PDE solvers.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Drawing phase plain, Pulse properties, PDE solving hints, Hints
+ at subsection Drawing phase plain
+ at nav{}
+
+Here I want say a few words of plotting phase plains. Phase plain is name for system of coordinates @math{x}, @math{x'}, i.e. a variable and its time derivative. Plot in phase plain is very useful for qualitative analysis of an ODE, because such plot is rude (it topologically the same for a range of ODE parameters). Most often the phase plain @{@math{x}, @math{x'}@} is used (due to its simplicity), that allows to analyze up to the 2nd order ODE (i.e. @math{x''+f(x,x')=0}).
+
+The simplest way to draw phase plain in MathGL is using @ref{flow} function(s), which automatically select several points and draw flow threads. If the ODE have an integral of motion (like Hamiltonian @math{H(x,x')=const} for dissipation-free case) then you can use @ref{cont} function for plotting isolines (contours). In fact. isolines are the same as flow threads, but without arrows on it. Finally, you can directly solve ODE using @ref{ode} function and plot its numerical solution.
+
+Let demonstrate this for ODE equation @math{x''-x+3*x^2=0}. This is nonlinear oscillator with square nonlinearity. It has integral @math{H=y^2+2*x^3-x^2=Const}. Also it have 2 typical stationary points: saddle at @{x=0, y=0@} and center at @{x=1/3, y=0@}. Motion at vicinity of center is just simple oscillations, and is stable to small variation of parameters. In opposite, motion around saddle point is non-stable to small variation of parameters, and is very slow. So, calculation around s [...]
+
+So, let draw this phase plain by 3 different methods. First, draw isolines for @math{H=y^2+2*x^3-x^2=Const} -- this is simplest for ODE without dissipation. Next, draw flow threads -- this is straightforward way, but the automatic choice of starting points is not always optimal. Finally, use @ref{ode} to check the above plots. At this we need to run @ref{ode} in both direction of time (in future and in the past) to draw whole plain. Alternatively, one can put starting points far from (or [...]
+ at verbatim
+subplot 2 2 0 '<_':title 'Cont':box
+axis:xlabel 'x':ylabel '\dot{x}'
+new f 100 100 'y^2+2*x^3-x^2-0.5':cont f
+
+subplot 2 2 1 '<_':title 'Flow':box
+axis:xlabel 'x':ylabel '\dot{x}'
+new fx 100 100 'x-3*x^2'
+new fy 100 100 'y'
+flow fy fx 'v';value 7
+
+subplot 2 2 2 '<_':title 'ODE':box
+axis:xlabel 'x':ylabel '\dot{x}'
+for $x -1 1 0.1
+  ode r 'y;x-3*x^2' 'xy' [$x,0]
+  plot r(0) r(1)
+  ode r '-y;-x+3*x^2' 'xy' [$x,0]
+  plot r(0) r(1)
+next
+ at end verbatim
+
+ at pfig{ode, Example of ODE solving and phase plain drawing.}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Pulse properties, Using MGL parser, Drawing phase plain, Hints
+ at subsection Pulse properties
+ at nav{}
+
+There is common task in optics to determine properties of wave pulses or wave beams. MathGL provide special function @ref{pulse} which return the pulse properties (maximal value, center of mass, width and so on). Its usage is rather simple. Here I just illustrate it on the example of Gaussian pulse, where all parameters are obvious.
+ at verbatim
+subplot 1 1 0 '<_':title 'Pulse sample'
+# first prepare pulse itself
+new a 100 'exp(-6*x^2)'
+
+# get pulse parameters
+pulse b a 'x'
+
+# positions and widths are normalized on the number of points. So, set proper axis scale.
+ranges 0 a.nx-1 0 1
+axis:plot a # draw pulse and axis
+
+# now visualize found pulse properties
+define m a.max # maximal amplitude
+# approximate position of maximum
+line b(1) 0 b(1) m 'r='
+# width at half-maximum (so called FWHM)
+line b(1)-b(3)/2 0  b(1)-b(3)/2 m 'm|'
+line b(1)+b(3)/2 0  b(1)+b(3)/2 m 'm|'
+line 0 0.5*m a.nx-1 0.5*m 'h'
+# parabolic approximation near maximum
+new x 100 'x'
+plot b(0)*(1-((x-b(1))/b(2))^2) 'g'
+ at end verbatim
+
+ at pfig{pulse, Example of determining of pulse properties.}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Using MGL parser, Using options, Pulse properties, Hints
+ at subsection Using MGL parser
+ at nav{}
+
+MGL scripts can contain loops, conditions and user-defined functions. Below I show very simple example of its usage:
+ at verbatim
+title 'MGL parser sample'
+call 'sample'
+stop
+
+func 'sample'
+new dat 100 'sin(2*pi*(x+1))'
+plot dat; xrange 0 1
+box:axis:xlabel 'x':ylabel 'y'
+for $0 -1 1 0.1
+if $0<0
+line 0 0 -1 $0 'r'
+else
+line 0 0 -1 $0 'r'
+endif
+next
+ at end verbatim
+
+ at pfig{parser, Example of MGL script parsing.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Using options, ``Templates'', Using MGL parser, Hints
+ at subsection Using options
+ at nav{}
+
+ at ref{Command options} allow the easy setup of the selected plot by changing global settings only for this plot. Often, options are used for specifying the range of automatic variables (coordinates). However, options allows easily change plot transparency, numbers of line or faces to be drawn, or add legend entries. The sample function for options usage is:
+ at verbatim
+new a 31 41 '-pi*x*exp(-(y+1)^2-4*x^2)'
+alpha on:light on
+subplot 2 2 0:title 'Options for coordinates':rotate 40 60:box
+surf a 'r';yrange 0 1
+surf a 'b';yrange 0 -1
+
+subplot 2 2 1:title 'Option "meshnum"':rotate 40 60:box
+mesh a 'r'; yrange 0 1
+mesh a 'b';yrange 0 -1; meshnum 5
+
+subplot 2 2 2:title 'Option "alpha"':rotate 40 60:box
+surf a 'r';yrange 0 1; alpha 0.7
+surf a 'b';yrange 0 -1; alpha 0.3
+
+subplot 2 2 3 '<_':title 'Option "legend"'
+fplot 'x^3' 'r'; legend 'y = x^3'
+fplot 'cos(pi*x)' 'b'; legend 'y = cos \pi x'
+box:axis:legend 2
+ at end verbatim
+
+ at pfig{mirror, Example of options usage.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ``Templates'', Nonlinear fitting hints, Using options, Hints
+ at subsection ``Templates''
+ at nav{}
+
+As I have noted before, the change of settings will influence only for the further plotting commands. This allows one to create ``template'' function which will contain settings and primitive drawing for often used plots. Correspondingly one may call this template-function for drawing simplification.
+
+For example, let one has a set of points (experimental or numerical) and wants to compare it with theoretical law (for example, with exponent law @math{\exp(-x/2), x \in [0, 20]}). The template-function for this task is:
+ at verbatim
+void template(mglGraph *gr)
+{
+  mglData  law(100);      // create the law
+  law.Modify("exp(-10*x)");
+  gr->SetRanges(0,20, 0.0001,1);
+  gr->SetFunc(0,"lg(y)",0);
+  gr->Plot(law,"r2");
+  gr->Puts(mglPoint(10,0.2),"Theoretical law: e^x","r:L");
+  gr->Label('x',"x val."); gr->Label('y',"y val.");
+  gr->Axis(); gr->Grid("xy","g;"); gr->Box();
+}
+ at end verbatim
+At this, one will only write a few lines for data drawing:
+ at verbatim
+  template(gr);     // apply settings and default drawing from template
+  mglData dat("fname.dat"); // load the data
+  // and draw it (suppose that data file have 2 columns)
+  gr->Plot(dat.SubData(0),dat.SubData(1),"bx ");
+ at end verbatim
+A template-function can also contain settings for font, transparency, lightning, color scheme and so on.
+
+I understand that this is obvious thing for any professional programmer, but I several times receive suggestion about ``templates'' ... So, I decide to point out it here.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Stereo image, Reduce memory usage, ``Templates'', Hints
+ at subsection Stereo image
+ at nav{}
+
+One can easily create stereo image in MathGL. Stereo image can be produced by making two subplots with slightly different rotation angles. The corresponding code looks like this:
+ at verbatim
+call 'prepare2d'
+light on
+subplot 2 1 0:rotate 50 60+1:box:surf a
+subplot 2 1 1:rotate 50 60-1:box:surf a
+ at end verbatim
+
+ at pfig{stereo, Example of stereo image.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Reduce memory usage, Saving and scanning file, Stereo image, Hints
+ at subsection Reduce memory usage
+ at nav{}
+
+By default MathGL save all primitives in memory, rearrange it and only later draw them on bitmaps. Usually, this speed up drawing, but may require a lot of memory for plots which contain a lot of faces (like @ref{cloud}, @ref{dew}). You can use @ref{quality} function for setting to use direct drawing on bitmap and bypassing keeping any primitives in memory. This function also allow you to decrease the quality of the resulting image but increase the speed of the drawing.
+
+The code for lower memory usage looks like this:
+ at verbatim
+quality 6  # firstly, set to draw directly on bitmap
+for $1 0 1000
+  sphere 2*rnd-1 2*rnd-1 0.05
+next
+ at end verbatim
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Saving and scanning file, Mixing bitmap and vector output, Reduce memory usage, Hints
+ at subsection Scanning file
+ at nav{}
+
+MathGL have possibilities to write textual information into file with variable values by help of @ref{save} command. This is rather useful for generating an ini-files or preparing human-readable textual files. For example, lets create some textual file
+ at verbatim
+subplot 1 1 0 '<_':title 'Save and scanfile sample'
+list a 1 -1 0
+save 'This is test: 0 -> ',a(0),' q' 'test.txt' 'w'
+save 'This is test: 1 -> ',a(1),' q' 'test.txt'
+save 'This is test: 2 -> ',a(2),' q' 'test.txt'
+ at end verbatim
+It contents look like
+ at verbatim
+This is test: 0 -> 1 q
+This is test: 1 -> -1 q
+This is test: 2 -> 0 q
+ at end verbatim
+Note, that I use option @samp{w} at first call of @code{save} to overwrite the contents of the file.
+
+Let assume now that you want to read this values (i.e. [[0,1],[1,-1],[2,0]]) from the file. You can use @ref{scanfile} for that. The desired values was written using template @samp{This is test: %g -> %g q}. So, just use
+ at verbatim
+scanfile a 'test.txt' 'This is test: %g -> %g'
+ at end verbatim
+and plot it to for assurance
+ at verbatim
+ranges a(0) a(1):axis:plot a(0) a(1) 'o'
+ at end verbatim
+
+Note, I keep only the leading part of template (i.e. @samp{This is test: %g -> %g} instead of @samp{This is test: %g -> %g q}), because there is no important for us information after the second number in the line.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Mixing bitmap and vector output, , Saving and scanning file, Hints
+ at subsection Mixing bitmap and vector output
+ at nav{}
+
+Sometimes output plots contain surfaces with a lot of points, and some vector primitives (like axis, text, curves, etc.). Using vector output formats (like EPS or SVG) will produce huge files with possible loss of smoothed lighting. Contrary, the bitmap output may cause the roughness of text and curves. Hopefully, MathGL have a possibility to combine bitmap output for surfaces and vector one for other primitives in the same EPS file, by using @ref{rasterize} command. 
+
+The idea is to prepare part of picture with surfaces or other "heavy" plots and produce the background image from them by help of @ref{rasterize} command. Next, we draw everything to be saved in vector form (text, curves, axis and etc.). Note, that you need to clear primitives (use @ref{clf} command) after @ref{rasterize} if you want to disable duplication of surfaces in output files (like EPS). Note, that some of output formats (like 3D ones, and TeX) don't support the background bitmap [...]
+
+The sample code is:
+ at verbatim
+# first draw everything to be in bitmap output
+fsurf 'x^2+y^2' '#';value 10
+
+rasterize   # set above plots as bitmap background
+clf         # clear primitives, to exclude them from file
+
+# now draw everything to be in vector output
+axis:box
+
+# and save file
+write 'fname.eps'
+ at end verbatim
+
+ at c ==================================================================
+
+ at external{}
+ at node FAQ, , Hints, Examples
+ at section FAQ
+ at nav{}
+
+ at table @strong
+ at item The plot does not appear
+Check that points of the plot are located inside the bounding box and resize the bounding box using @ref{ranges} function. Check that the data have correct dimensions for selected type of plot. Sometimes the light reflection from flat surfaces (like, @ref{dens}) can look as if the plot were absent.
+
+ at item I can not find some special kind of plot.
+Most ``new'' types of plots can be created by using the existing drawing functions. For example, the surface of curve rotation can be created by a special function @ref{torus}, or as a parametrically specified surface by @ref{surf}. See also, @ref{Hints}. If you can not find a specific type of plot, please e-mail me and this plot will appear in the next version of MathGL library.
+
+ at item How can I print in Russian/Spanish/Arabic/Japanese, and so on?
+The standard way is to use Unicode encoding for the text output. But the MathGL library also has interface for 8-bit (char *) strings with internal conversion to Unicode. This conversion depends on the current locale OS.
+
+ at item How can I exclude a point or a region of plot from the drawing?
+There are 3 general ways. First, the point with @code{nan} value as one of the coordinates (including color/alpha range) will never be plotted. Second, special functions define the condition when the points should be omitted (see @ref{Cutting}). Last, you may change the transparency of a part of the plot by the help of functions @ref{surfa}, @ref{surf3a} (see @ref{Dual plotting}). In last case the transparency is switched on smoothly.
+
+ at item How many people write this library?
+Most of the library was written by one person. This is a result of nearly a year of work (mostly in the evening and on holidays): I spent half a year to write the kernel and half a year to a year on extending, improving the library and writing documentation. This process continues now :). The build system (cmake files) was written mostly by D.Kulagin, and the export to PRC/PDF was written mostly by M.Vidassov.
+
+ at item How can I display a bitmap on the figure?
+You can import data by command @ref{import} and display it by @ref{dens} function. For example, for black-and-white bitmap you can use the code: @code{import bmp 'fname.png' 'wk':dens  bmp 'wk'}.
+
+
+ at item How can I create 3D in PDF?
+Just use command @code{write fname.pdf}, which create PDF file if enable-pdf=ON at MathGL configure.
+
+ at item How can I create TeX figure?
+Just use command @code{write fname.tex}, which create LaTeX files with figure itself @samp{@var{fname}.tex}, with MathGL colors @samp{mglcolors.tex} and main file @samp{mglmain.tex}. Last one can be used for viewing image by command like @code{pdflatex mglmain.tex}.
+
+
+ at item How I can change the font family?
+First, you should download new font files from @uref{http://mathgl.sourceforge.net/download.html, here} or from @uref{http://sourceforge.net/project/showfiles.php?group_id=152187&package_id=267177, here}. Next, you should load the font files into by the following command: @code{loadfont 'fontname'}. Here @var{fontname} is the base font name like @samp{STIX}. Use @code{loadfont ''} to start using the default font.
+
+ at item How can I draw tick out of a bounding box?
+Just set a negative value in @ref{ticklen}. For example, use @code{ticklen -0.1}.
+
+ at item How can I prevent text rotation?
+Just use @code{rotatetext off}. Also you can use axis style @samp{U} for disable only tick labels rotation.
+
+ at item How can I draw equal axis range even for rectangular image?
+Just use @code{aspect nan nan} for each subplot, or at the beginning of the drawing.
+
+ at item How I can set transparent background?
+Just use code like @code{clf 'r@{A5@}'} or prepare PNG file and set it as background image by call @code{background 'fname.png'}.
+
+ at item How I can reduce "white" edges around bounding box?
+The simplest way is to use @ref{subplot} style. However, you should be careful if you plan to add @ref{colorbar} or rotate plot -- part of plot can be invisible if you will use non-default @ref{subplot} style.
+
+ at item Can I combine bitmap and vector output in EPS?
+Yes. Sometimes you may have huge surface and a small set of curves and/or text on the plot. You can use function @ref{rasterize} just after making surface plot. This will put all plot to bitmap background. At this later plotting will be in vector format. For example, you can do something like following:
+ at verbatim
+surf x y z
+rasterize # make surface as bitmap
+axis
+write 'fname.eps'
+ at end verbatim
+
+ at end table
+
+ at external{}
diff --git a/texinfo/ex_mgl_ru.texi b/texinfo/ex_mgl_ru.texi
new file mode 100644
index 0000000..5cd8bf7
--- /dev/null
+++ b/texinfo/ex_mgl_ru.texi
@@ -0,0 +1,3249 @@
+ at c ------------------------------------------------------------------
+ at chapter MathGL examples
+ at nav{}
+
+This chapter contain information about basic and advanced MathGL, hints and samples for all types of graphics. I recommend you read first 2 sections one after another and at least look on @ref{Hints} section. Also I recommend you to look at @ref{General concepts} and @ref{FAQ}.
+
+Most of sample scripts placed below use a set of functions for preparing the data.
+ at verbatim
+func 'prepare1d'
+new y 50 3
+modify y '0.7*sin(2*pi*x)+0.5*cos(3*pi*x)+0.2*sin(pi*x)'
+modify y 'sin(2*pi*x)' 1
+modify y 'cos(2*pi*x)' 2
+new x1 50 'x'
+new x2 50 '0.05-0.03*cos(pi*x)'
+new y1 50 '0.5-0.3*cos(pi*x)'
+new y2 50 '-0.3*sin(pi*x)'
+return
+
+func 'prepare2d'
+new a 50 40 '0.6*sin(pi*(x+1))*sin(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'
+new b 50 40 '0.6*cos(pi*(x+1))*cos(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'
+return
+
+func 'prepare3d'
+new c 61 50 40 '-2*(x^2+y^2+z^4-z^2)+0.2'
+new d 61 50 40 '1-2*tanh((x+y)*(x+y))'
+return
+
+func 'prepare2v'
+new a 20 30 '0.6*sin(pi*(x+1))*sin(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'
+new b 20 30 '0.6*cos(pi*(x+1))*cos(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'
+return
+
+func 'prepare3v'
+define $1 pow(x*x+y*y+(z-0.3)*(z-0.3)+0.03,1.5)
+define $2 pow(x*x+y*y+(z+0.3)*(z+0.3)+0.03,1.5)
+new ex 10 10 10 '0.2*x/$1-0.2*x/$2'
+new ey 10 10 10 '0.2*y/$1-0.2*y/$2'
+new ez 10 10 10 '0.2*(z-0.3)/$1-0.2*(z+0.3)/$2'
+return
+ at end verbatim
+Basically, you can put this text after the script. Note, that you need to terminate main script by @ref{stop} command before defining a function.
+
+ at menu
+* Basic usage::
+* Advanced usage::
+* Data handling::
+* Data plotting::
+* 1D samples::
+* 2D samples::
+* 3D samples::
+* Vector field samples::
+* Hints::
+* FAQ::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Basic usage, Advanced usage, , Examples
+ at section Basic usage
+ at nav{}
+
+MGL script can be used by several manners. Each has positive and negative sides:
+ at itemize @bullet
+ at item
+ at emph{Using UDAV.}
+
+Positive sides are possibilities to view the plot at once and to modify it, rotate, zoom or switch on transparency or lighting by hands or by mouse. Negative side is the needness of the X-terminal. @c For more details, see @ref{UDAV}.
+
+ at item
+ at emph{Using command line tools.}
+
+Positive aspects are: batch processing of similar data set, for example, a set of resulting data files for different calculation parameters), running from the console program, including the cluster calculation), fast and automated drawing, saving pictures for further analysis, or demonstration). Negative sides are: the usage of the external program for picture viewing. Also, the data plotting is non-visual. So, you have to imagine the picture, view angles, lighting and so on) before the  [...]
+
+In this case you can use the program: @code{mglconv} or @code{mglview} for viewing.
+
+ at item
+ at emph{Using C/C++/... code.}
+
+You can easily execute MGL script within C/C++/Fortan code. This can be useful for fast data plotting, for example, in web applications, where textual string (MGL script) may contain all necessary information for plot. The basic C++ code may look as following
+ at verbatim
+const char *mgl_script; // script itself, can be of type const wchar_t*
+mglGraph gr;
+mglParse pr;
+pr.Execute(&gr, mgl_script);
+ at end verbatim
+ at end itemize
+
+The simplest script is
+ at verbatim
+box         # draw bounding box
+axis        # draw axis
+fplot 'x^3' # draw some function
+ at end verbatim
+
+Just type it in UDAV and press F5. Also you can save it in text file @samp{test.mgl} and type in the console @code{mglconv test.mgl} what produce file @samp{test.mgl.png} with resulting picture.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Advanced usage, Data handling, Basic usage, Examples
+ at section Advanced usage
+ at nav{}
+
+Now I show several non-obvious features of MGL: several subplots in a single picture, curvilinear coordinates, text printing and so on. Generally you may miss this section at first reading, but I don't recommend it.
+
+ at menu
+* Subplots::
+* Axis and ticks::
+* Curvilinear coordinates::
+* Colorbars::
+* Bounding box::
+* Ternary axis::
+* Text features::
+* Legend sample::
+* Cutting sample::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Subplots, Axis and ticks, , Advanced usage
+ at subsection Subplots
+ at nav{}
+
+Let me demonstrate possibilities of plot positioning and rotation. MathGL has a set of functions: @ref{subplot}, @ref{inplot}, @ref{title}, @ref{aspect} and @ref{rotate} and so on (see @ref{Subplots and rotation}). The order of their calling is strictly determined. First, one changes the position of plot in image area (functions @ref{subplot}, @ref{inplot} and @ref{multiplot}). Secondly, you can add the title of plot by @ref{title} function. After that one may rotate the plot (command @r [...]
+ at verbatim
+subplot 2 2 0
+box:text -1 1.1 'Just box' ':L'
+inplot 0.2 0.5 0.7 1 off
+box:text 0 1.2 'InPlot example'
+
+subplot 2 2 1:title 'Rotate only'
+rotate 50 60:box
+
+subplot 2 2 2:title 'Rotate and Aspect'
+rotate 50 60:aspect 1 1 2:box
+
+subplot 2 2 3:title 'Shear'
+box 'c':shear 0.2 0.1:box
+ at end verbatim
+Here I used function @code{Puts} for printing the text in arbitrary position of picture (see @ref{Text printing}). Text coordinates and size are connected with axes. However, text coordinates may be everywhere, including the outside the bounding box. I'll show its features later in @ref{Text features}.
+
+Note that several commands can be placed in a string if they are separated by @samp{:} symbol.
+
+ at pfig{aspect, Example of several subplots on the single picture.}
+
+More complicated sample show how to use most of positioning functions:
+ at verbatim
+subplot 3 2 0:title 'StickPlot'
+stickplot 3 0 20 30:box 'r':text 0 0 0 '0' 'r'
+stickplot 3 1 20 30:box 'g':text 0 0 0 '1' 'g'
+stickplot 3 2 20 30:box 'b':text 0 0 0 '2' 'b'
+
+subplot 3 2 3 '':title 'ColumnPlot'
+columnplot 3 0:box 'r':text 0 0 '0' 'r'
+columnplot 3 1:box 'g':text 0 0 '1' 'g'
+columnplot 3 2:box 'b':text 0 0 '2' 'b'
+
+subplot 3 2 4 '':title 'GridPlot'
+gridplot 2 2 0:box 'r':text 0 0 '0' 'r'
+gridplot 2 2 1:box 'g':text 0 0 '1' 'g'
+gridplot 2 2 2:box 'b':text 0 0 '2' 'b'
+gridplot 2 2 3:box 'm':text 0 0 '3' 'm'
+
+subplot 3 2 5 '':title 'InPlot':box
+inplot 0.4 1 0.6 1 on:box 'r'
+
+multiplot 3 2 1 2 1 '':title 'MultiPlot and ShearPlot':box
+shearplot 3 0 0.2 0.1:box 'r':text 0 0 '0' 'r'
+shearplot 3 1 0.2 0.1:box 'g':text 0 0 '1' 'g'
+shearplot 3 2 0.2 0.1:box 'b':text 0 0 '2' 'b'
+ at end verbatim
+
+ at pfig{inplot, Example for most of positioning functions.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Axis and ticks, Curvilinear coordinates, Subplots, Advanced usage
+ at subsection Axis and ticks
+ at nav{}
+
+MathGL library can draw not only the bounding box but also the axes, grids, labels and so on. The ranges of axes and their origin (the point of intersection) are determined by functions @code{SetRange()}, @code{SetRanges()}, @code{SetOrigin()} (see @ref{Ranges (bounding box)}). Ticks on axis are specified by function @code{SetTicks}, @code{SetTicksVal}, @code{SetTicksTime} (see @ref{Ticks}). But usually
+
+Command @ref{axis} draws axes. Its textual string shows in which directions the axis or axes will be drawn (by default @code{"xyz"}, function draws axes in all directions). Command @ref{grid} draws grid perpendicularly to specified directions. Example of axes and grid drawing is:
+ at verbatim
+subplot 2 2 0:title 'Axis origin, Grid'
+origin 0 0:axis:grid:fplot 'x^3'
+
+subplot 2 2 1:title '2 axis'
+ranges -1 1 -1 1:origin -1 -1:axis
+ylabel 'axis_1':fplot 'sin(pi*x)' 'r2'
+ranges 0 1 0 1:origin 1 1:axis
+ylabel 'axis_2':fplot 'cos(pi*x)'
+
+subplot 2 2 3:title 'More axis'
+origin nan nan:xrange -1 1:axis
+xlabel 'x' 0:ylabel 'y_1' 0:fplot 'x^2' 'k'
+yrange -1 1:origin -1.3 -1:axis 'y' 'r'
+ylabel '#r{y_2}' 0.2:fplot 'x^3' 'r'
+
+subplot 2 2 2:title '4 segments, inverted axis':origin 0 0:
+inplot 0.5 1 0.5 1 on:ranges 0 10 0 2:axis
+fplot 'sqrt(x/2)':xlabel 'W' 1:ylabel 'U' 1
+inplot 0 0.5 0.5 1 on:ranges 1 0 0 2:axis 'x'
+fplot 'sqrt(x)+x^3':xlabel '\tau' 1
+inplot 0.5 1 0 0.5 on:ranges 0 10 4 0:axis 'y'
+fplot 'x/4':ylabel 'L' -1
+inplot 0 0.5 0 0.5 on:ranges 1 0 4 0:fplot '4*x^2'
+ at end verbatim
+
+Note, that MathGL can draw not only single axis (which is default). But also several axis on the plot (see right plots). The idea is that the change of settings does not influence on the already drawn graphics. So, for 2-axes I setup the first axis and draw everything concerning it. Then I setup the second axis and draw things for the second axis. Generally, the similar idea allows one to draw rather complicated plot of 4 axis with different ranges (see bottom left plot).
+
+At this inverted axis can be created by 2 methods. First one is used in this sample -- just specify minimal axis value to be large than maximal one. This method work well for 2D axis, but can wrongly place labels in 3D case. Second method is more general and work in 3D case too -- just use @ref{aspect} function with negative arguments. For example, following code will produce exactly the same result for 2D case, but 2nd variant will look better in 3D.
+ at verbatim
+# variant 1
+ranges 0 10 4 0:axis
+
+# variant 2
+ranges 0 10 0 4:aspect 1 -1:axis
+ at end verbatim
+
+ at pfig{axis, Example of axis.}
+
+Another MathGL feature is fine ticks tunning. By default (if it is not changed by @code{SetTicks} function), MathGL try to adjust ticks positioning, so that they looks most human readable. At this, MathGL try to extract common factor for too large or too small axis ranges, as well as for too narrow ranges. Last one is non-common notation and can be disabled by @code{SetTuneTicks} function.
+
+Also, one can specify its own ticks with arbitrary labels by help of @code{SetTicksVal} function. Or one can set ticks in time format. In last case MathGL will try to select optimal format for labels with automatic switching between years, months/days, hours/minutes/seconds or microseconds. However, you can specify its own time representation using formats described in @url{http://www.manpagez.com/man/3/strftime/}. Most common variants are @samp{%X} for national representation of time, @ [...]
+
+The sample code, demonstrated ticks feature is
+ at verbatim
+subplot 3 3 0:title 'Usual axis'
+axis
+
+subplot 3 3 1:title 'Too big/small range'
+ranges -1000 1000 0 0.001:axis
+
+subplot 3 3 2:title 'LaTeX-like labels'
+axis 'F!'
+
+subplot 3 3 3:title 'Too narrow range'
+ranges 100 100.1 10 10.01:axis
+
+subplot 3 3 4:title 'No tuning, manual "+"'
+axis '+!'
+# for version <2.3 you can use
+#tuneticks off:axis
+
+subplot 3 3 5:title 'Template for ticks'
+xtick 'xxx:%g':ytick 'y:%g'
+axis
+
+xtick '':ytick '' # switch it off for other plots
+
+subplot 3 3 6:title 'No tuning, higher precision'
+axis '!4'
+
+subplot 3 3 7:title 'Manual ticks'
+ranges -pi pi 0 2
+xtick pi 3 '\pi'
+xtick 0.886 'x^*' on # note this will disable subticks drawing
+# or you can use
+#xtick -pi '\pi' -pi/2 '-\pi/2' 0 '0' 0.886 'x^*' pi/2 '\pi/2' pi 'pi'
+# or you can use
+#list v -pi -pi/2 0 0.886 pi/2 pi:xtick v '-\pi\n-\pi/2\n{}0\n{}x^*\n\pi/2\n\pi'
+axis:grid:fplot '2*cos(x^2)^2' 'r2'
+
+subplot 3 3 8:title 'Time ticks'
+xrange 0 3e5:ticktime 'x':axis
+ at end verbatim
+
+ at pfig{ticks, Features of axis ticks.}
+
+The last sample I want to show in this subsection is Log-axis. From MathGL's point of view, the log-axis is particular case of general curvilinear coordinates. So, we need first define new coordinates (see also @ref{Curvilinear coordinates}) by help of @code{SetFunc} or @code{SetCoor} functions. At this one should wary about proper axis range. So the code looks as following:
+ at verbatim
+subplot 2 2 0 '<_':title 'Semi-log axis'
+ranges 0.01 100 -1 1:axis 'lg(x)' '' ''
+axis:grid 'xy' 'g':fplot 'sin(1/x)'
+xlabel 'x' 0:ylabel 'y = sin 1/x' 0
+
+subplot 2 2 1 '<_':title 'Log-log axis'
+ranges 0.01 100 0.1 100:axis 'lg(x)' 'lg(y)' ''
+axis:grid '!' 'h=':grid:fplot 'sqrt(1+x^2)'
+xlabel 'x' 0:ylabel 'y = \sqrt{1+x^2}' 0
+
+subplot 2 2 2 '<_':title 'Minus-log axis'
+ranges -100 -0.01 -100 -0.1:axis '-lg(-x)' '-lg(-y)' ''
+axis:fplot '-sqrt(1+x^2)'
+xlabel 'x' 0:ylabel 'y = -\sqrt{1+x^2}' 0
+
+subplot 2 2 3 '<_':title 'Log-ticks'
+ranges 0.01 100 0 100:axis 'sqrt(x)' '' ''
+axis:fplot 'x'
+xlabel 'x' 1:ylabel 'y = x' 0
+ at end verbatim
+
+ at pfig{loglog, Features of axis ticks.}
+
+You can see that MathGL automatically switch to log-ticks as we define log-axis formula (in difference from v.1.*). Moreover, it switch to log-ticks for any formula if axis range will be large enough (see right bottom plot). Another interesting feature is that you not necessary define usual log-axis (i.e. when coordinates are positive), but you can define ``minus-log'' axis when coordinate is negative (see left bottom plot).
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Curvilinear coordinates, Colorbars, Axis and ticks, Advanced usage
+ at subsection Curvilinear coordinates
+ at nav{}
+
+As I noted in previous subsection, MathGL support curvilinear coordinates. In difference from other plotting programs and libraries, MathGL uses textual formulas for connection of the old (data) and new (output) coordinates. This allows one to plot in arbitrary coordinates. The following code plots the line @var{y}=0, @var{z}=0 in Cartesian, polar, parabolic and spiral coordinates:
+ at verbatim
+origin -1 1 -1
+subplot 2 2 0:title 'Cartesian':rotate 50 60
+fplot '2*t-1' '0.5' '0' '2r':axis:grid
+
+axis 'y*sin(pi*x)' 'y*cos(pi*x)' '':
+subplot 2 2 1:title 'Cylindrical':rotate 50 60
+fplot '2*t-1' '0.5' '0' '2r':axis:grid
+
+axis '2*y*x' 'y*y - x*x' ''
+subplot 2 2 2:title 'Parabolic':rotate 50 60
+fplot '2*t-1' '0.5' '0' '2r':axis:grid
+
+axis 'y*sin(pi*x)' 'y*cos(pi*x)' 'x+z'
+subplot 2 2 3:title 'Spiral':rotate 50 60
+fplot '2*t-1' '0.5' '0' '2r':axis:grid
+ at end verbatim
+
+ at pfig{curvcoor, Example of curvilinear coordinates}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Colorbars, Bounding box, Curvilinear coordinates, Advanced usage
+ at subsection Colorbars
+ at nav{}
+
+MathGL handle @ref{colorbar} as special kind of axis. So, most of functions for axis and ticks setup will work for colorbar too. Colorbars can be in log-scale, and generally as arbitrary function scale; common factor of colorbar labels can be separated; and so on.
+
+But of course, there are differences -- colorbars usually located out of bounding box. At this, colorbars can be at subplot boundaries (by default), or at bounding box (if symbol @samp{I} is specified). Colorbars can handle sharp colors. And they can be located at arbitrary position too. The sample code, which demonstrate colorbar features is:
+ at verbatim
+call 'prepare2d'
+new v 9 'x'
+
+subplot 2 2 0:title 'Colorbar out of box':box
+colorbar '<':colorbar '>':colorbar '_':colorbar '^'
+
+subplot 2 2 1:title 'Colorbar near box':box
+colorbar '<I':colorbar '>I':colorbar '_I':colorbar '^I'
+
+subplot 2 2 2:title 'manual colors':box:contd v a
+colorbar v '<':colorbar v '>':colorbar v '_':colorbar v '^'
+
+subplot 2 2 3:title '':text -0.5 1.55 'Color positions' ':C' -2
+
+colorbar 'bwr>' 0.25 0:text -0.9 1.2 'Default'
+colorbar 'b{w,0.3}r>' 0.5 0:text -0.1 1.2 'Manual'
+
+crange 0.01 1e3
+colorbar '>' 0.75 0:text 0.65 1.2 'Normal scale'
+colorbar '>':text 1.35 1.2 'Log scale'
+ at end verbatim
+
+ at pfig{colorbar, Example of colorbars}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Bounding box, Ternary axis, Colorbars, Advanced usage
+ at subsection Bounding box
+ at nav{}
+
+Box around the plot is rather useful thing because it allows one to: see the plot boundaries, and better estimate points position since box contain another set of ticks. MathGL provide special function for drawing such box -- @ref{box} function. By default, it draw black or white box with ticks (color depend on transparency type, see @ref{Types of transparency}). However, you can change the color of box, or add drawing of rectangles at rear faces of box. Also you can disable ticks drawin [...]
+ at verbatim
+subplot 2 2 0:title 'Box (default)':rotate 50 60:box
+
+subplot 2 2 1:title 'colored':rotate 50 60:box 'r'
+
+subplot 2 2 2:title 'with faces':rotate 50 60:box '@'
+
+subplot 2 2 3:title 'both':rotate 50 60:box '@cm'
+ at end verbatim
+
+ at pfig{box, Example of Box()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Ternary axis, Text features, Bounding box, Advanced usage
+ at subsection Ternary axis
+ at nav{}
+
+There are another unusual axis types which are supported by MathGL. These are ternary and quaternary axis. Ternary axis is special axis of 3 coordinates @var{a}, @var{b}, @var{c} which satisfy relation @var{a}+ at var{b}+ at var{c}=1. Correspondingly, quaternary axis is special axis of 4 coordinates @var{a}, @var{b}, @var{c}, @var{d} which satisfy relation @var{a}+ at var{b}+ at var{c}+ at var{d}=1.
+
+Generally speaking, only 2 of coordinates (3 for quaternary) are independent. So, MathGL just introduce some special transformation formulas which treat @var{a} as @samp{x}, @var{b} as @samp{y} (and @var{c} as @samp{z} for quaternary). As result, all plotting functions (curves, surfaces, contours and so on) work as usual, but in new axis. You should use @ref{ternary} function for switching to ternary/quaternary coordinates. The sample code is:
+ at verbatim
+ranges 0 1 0 1 0 1
+new x 50 '0.25*(1+cos(2*pi*x))'
+new y 50 '0.25*(1+sin(2*pi*x))'
+new z 50 'x'
+new a 20 30 '30*x*y*(1-x-y)^2*(x+y<1)'
+new rx 10 'rnd':copy ry (1-rx)*rnd
+light on
+
+subplot 2 2 0:title 'Ordinary axis 3D':rotate 50 60
+box:axis:grid
+plot x y z 'r2':surf a '#'
+xlabel 'B':ylabel 'C':zlabel 'Z'
+
+subplot 2 2 1:title 'Ternary axis (x+y+t=1)':ternary 1
+box:axis:grid 'xyz' 'B;'
+plot x y 'r2':plot rx ry 'q^ ':cont a:line 0.5 0 0 0.75 'g2'
+xlabel 'B':ylabel 'C':tlabel 'A'
+
+subplot 2 2 2:title 'Quaternary axis 3D':rotate 50 60:ternary 2
+box:axis:grid 'xyz' 'B;'
+plot x y z 'r2':surf a '#'
+xlabel 'B':ylabel 'C':tlabel 'A':zlabel 'D'
+
+subplot 2 2 3:title 'Ternary axis 3D':rotate 50 60:ternary 1
+box:axis:grid 'xyz' 'B;'
+plot x y z 'r2':surf a '#'
+xlabel 'B':ylabel 'C':tlabel 'A':zlabel 'Z'
+ at end verbatim
+
+ at pfig{ternary, Ternary and Quaternary axis}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Text features, Legend sample, Ternary axis, Advanced usage
+ at subsection Text features
+ at nav{}
+
+MathGL prints text by vector font. There are functions for manual specifying of text position (like @code{Puts}) and for its automatic selection (like @code{Label}, @code{Legend} and so on). MathGL prints text always in specified position even if it lies outside the bounding box. The default size of font is specified by functions @var{SetFontSize*} (see @ref{Font settings}). However, the actual size of output string depends on subplot size (depends on functions @code{SubPlot}, @code{InPl [...]
+
+Text can be printed as usual one (from left to right), along some direction (rotated text), or along a curve. Text can be printed on several lines, divided by new line symbol @samp{\n}.
+
+Example of MathGL font drawing is:
+ at verbatim
+call 'prepare1d'
+
+subplot 2 2 0 ''
+text 0 1 'Text can be in ASCII and in Unicode'
+text 0 0.6 'It can be \wire{wire}, \big{big} or #r{colored}'
+text 0 0.2 'One can change style in string: \b{bold}, \i{italic, \b{both}}'
+text 0 -0.2 'Easy to \a{overline} or \u{underline}'
+text 0 -0.6 'Easy to change indexes ^{up} _{down} @{center}'
+text 0 -1 'It parse TeX: \int \alpha \cdot \
+\sqrt3{sin(\pi x)^2 + \gamma_{i_k}} dx'
+
+subplot 2 2 1 ''
+ text 0 0.5 '\sqrt{\frac{\alpha^{\gamma^2}+\overset 1{\big\infty}}{\sqrt3{2+b}}}' '@' -2
+text 0 -0.5 'Text can be printed\n{}on several lines'
+
+subplot 2 2 2 '':box:plot y(:,0)
+text y 'This is very very long string drawn along a curve' 'k'
+text y 'Another string drawn under a curve' 'Tr'
+
+subplot 2 2 3 '':line -1 -1 1 -1 'rA':text 0 -1 1 -1 'Horizontal'
+line -1 -1 1 1 'rA':text 0 0 1 1 'At angle' '@'
+line -1 -1 -1 1 'rA':text -1 0 -1 1 'Vertical'
+ at end verbatim
+
+ at pfig{text, Example of text printing}
+
+You can change font faces by loading font files by function @ref{loadfont}. Note, that this is long-run procedure. Font faces can be downloaded from @uref{http://mathgl.sourceforge.net/download.html, MathGL website} or from @uref{http://sourceforge.net/project/showfiles.php?group_id=152187&package_id=267177, here}. The sample code is:
+ at verbatim
+define d 0.25
+loadfont 'STIX':text 0 1.1 'default font (STIX)'
+loadfont 'adventor':text 0 1.1-d 'adventor font'
+loadfont 'bonum':text 0 1.1-2*d 'bonum font'
+loadfont 'chorus':text 0 1.1-3*d 'chorus font'
+loadfont 'cursor':text 0 1.1-4*d 'cursor font'
+loadfont 'heros':text 0 1.1-5*d 'heros font'
+loadfont 'heroscn':text 0 1.1-6*d 'heroscn font'
+loadfont 'pagella':text 0 1.1-7*d 'pagella font'
+loadfont 'schola':text 0 1.1-8*d 'schola font'
+loadfont 'termes':text 0 1.1-9*d 'termes font'
+ at end verbatim
+
+ at pfig{fonts, Example of font faces}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Legend sample, Cutting sample, Text features, Advanced usage
+ at subsection Legend sample
+ at nav{}
+
+Legend is one of standard ways to show plot annotations. Basically you need to connect the plot style (line style, marker and color) with some text. In MathGL, you can do it by 2 methods: manually using @ref{addlegend} function; or use @samp{legend} option (see @ref{Command options}), which will use last plot style. In both cases, legend entries will be added into internal accumulator, which later used for legend drawing itself. @ref{clearlegend} function allow you to remove all saved le [...]
+
+There are 2 features. If plot style is empty then text will be printed without indent. If you want to plot the text with indent but without plot sample then you need to use space @samp{ } as plot style. Such style @samp{ } will draw a plot sample (line with marker(s)) which is invisible line (i.e. nothing) and print the text with indent as usual one.
+
+Command @ref{legend} draw legend on the plot. The position of the legend can be selected automatic or manually. You can change the size and style of text labels, as well as setup the plot sample. The sample code demonstrating legend features is:
+ at verbatim
+addlegend 'sin(\pi {x^2})' 'b'
+addlegend 'sin(\pi x)' 'g*'
+addlegend 'sin(\pi \sqrt{x})' 'rd'
+addlegend 'jsut text' ' '
+addlegend 'no indent for this' ''
+
+subplot 2 2 0 '':title 'Legend (default)':box
+legend
+
+text 0.75 0.65 'Absolute position' 'A'
+legend 3 'A#'
+
+subplot 2 2 2 '':title 'coloring':box
+legend 0 'r#':legend 1 'Wb#':legend 2 'ygr#'
+
+subplot 2 2 3 '':title 'manual position':box
+legend 0.5 1:text 0.5 0.55 'at x=0.5, y=1' 'a'
+legend 1 '#-':text 0.75 0.25 'Horizontal legend' 'a'
+ at end verbatim
+
+ at pfig{legend, Example of legend}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cutting sample, , Legend sample, Advanced usage
+ at subsection Cutting sample
+ at nav{}
+
+The last common thing which I want to show in this section is how one can cut off points from plot. There are 4 mechanism for that.
+ at itemize @bullet
+ at item
+You can set one of coordinate to NAN value. All points with NAN values will be omitted.
+
+ at item
+You can enable cutting at edges by @code{SetCut} function. As result all points out of bounding box will be omitted.
+
+ at item
+You can set cutting box by @code{SetCutBox} function. All points inside this box will be omitted.
+
+ at item
+You can define cutting formula by @code{SetCutOff} function. All points for which the value of formula is nonzero will be omitted. Note, that this is the slowest variant.
+ at end itemize
+
+Below I place the code which demonstrate last 3 possibilities:
+ at verbatim
+call 'prepare2d'
+call 'prepare3d'
+
+subplot 2 2 0:title 'Cut on (default)':rotate 50 60
+light on:box:surf a; zrange -1 0.5
+
+subplot 2 2 1:title 'Cut off':rotate 50 60
+box:surf a; zrange -1 0.5; cut off
+
+subplot 2 2 2:title 'Cut in box':rotate 50 60:box:alpha on
+cut 0 -1 -1 1 0 1.1:surf3 c
+cut 0 0 0 0 0 0	# restore back
+
+subplot 2 2 3:title 'Cut by formula':rotate 50 60:box
+cut '(z>(x+0.5*y-1)^2-1) & (z>(x-0.5*y-1)^2-1)':surf3 c
+ at end verbatim
+
+ at pfig{cut, Example of point cutting}
+
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Data handling, Data plotting, Advanced usage, Examples
+ at section Data handling
+ at nav{}
+
+Class @code{mglData} contains all functions for the data handling in MathGL (@pxref{Data processing}). There are several matters why I use class @code{mglData} but not a single array: it does not depend on type of data (mreal or double), sizes of data arrays are kept with data, memory working is simpler and safer.
+
+ at menu
+* Array creation::
+* Change data::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Array creation, Change data, , Data handling
+ at subsection Array creation
+ at nav{}
+
+One can put numbers into the data instance by several ways. Let us do it for square function:
+ at itemize @bullet
+ at item
+one can create array by @code{list} command
+ at verbatim
+list a 0 0.04 0.16 0.36 0.64 1
+ at end verbatim
+
+ at item
+another way is to copy from ``inline'' array
+ at verbatim
+copy a [0,0.04,0.16,0.36,0.64,1]
+ at end verbatim
+
+ at item
+next way is to fill the data by textual formula with the help of @code{modify} function
+ at verbatim
+new a 6
+modify a 'x^2'
+ at end verbatim
+
+ at item
+or one may fill the array in some interval and modify it later
+ at verbatim
+new a 6
+fill a 0 1
+modify a 'u^2'
+ at end verbatim
+
+ at item
+or fill the array using current axis range
+ at verbatim
+new a 6
+fill a '(x+1)^2/4'
+ at end verbatim
+or use single line
+ at verbatim
+new a 6 '(x+1)^2/4'
+ at end verbatim
+
+ at item
+finally it can be loaded from file
+ at verbatim
+new s 6 '(x+1)^2/4'
+save s 'sqr.dat'    # create file first
+read a 'sqr.dat'    # load it
+ at end verbatim
+
+ at item
+at this one can read only part of data
+ at verbatim
+new s 6 '(x+1)^2/4'
+save s 'sqr.dat'    # create file first
+read a 'sqr.dat' 5  # load it
+ at end verbatim
+ at end itemize
+
+Creation of 2d- and 3d-arrays is mostly the same. One can use direct data filling by @code{list} command
+ at verbatim
+list a 11 12 13 | 21 22 23 | 31 32 33
+ at end verbatim
+or by inline arrays
+ at verbatim
+copy a [[11,12,13],[21,22,23],[31,32,33]]
+ at end verbatim
+Also data can be filled by formula
+ at verbatim
+new z 30 40 'sin(pi*x)*cos(pi*y)'
+ at end verbatim
+or loaded from a file.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Change data, , Array creation, Data handling
+ at subsection Change data
+ at nav{}
+
+MathGL has functions for data processing: differentiating, integrating, smoothing and so on (for more detail, see @ref{Data processing}). Let us consider some examples. The simplest ones are integration and differentiation. The direction in which operation will be performed is specified by textual string, which may contain symbols @samp{x}, @samp{y} or @samp{z}. For example, the call of @code{diff 'x'} will differentiate data along @samp{x} direction; the call of @code{integrate 'xy'} pe [...]
+ at verbatim
+ranges 0 1 0 1 0 1:new a 30 40 'x*y'
+subplot 2 2 0:title 'a(x,y)':rotate 60 40
+surf a:box
+
+subplot 2 2 1:title 'da/dx':rotate 60 40
+diff a 'x':surf a:box
+
+subplot 2 2 2:title '\int da/dx dxdy':rotate 60 40
+integrate a 'xy':surf a:box
+
+subplot 2 2 3:title '\int {d^2}a/dxdy dx':rotate 60 40
+diff2 a 'y':surf a:box
+ at end verbatim
+
+ at pfig{dat_diff, Example of data differentiation and integration}
+
+Data smoothing (command @ref{smooth}) is more interesting and important. This function has single argument which define type of smoothing and its direction. Now 3 methods are supported: @samp{3} -- linear averaging by 3 points, @samp{5} -- linear averaging by 5 points, and default one -- quadratic averaging by 5 points.
+
+MathGL also have some amazing functions which is not so important for data processing as useful for data plotting. There are functions for finding envelope (useful for plotting rapidly oscillating data), for data sewing (useful to removing jumps on the phase), for data resizing (interpolation). Let me demonstrate it:
+ at verbatim
+subplot 2 2 0 '':title 'Envelop sample'
+new d1 1000 'exp(-8*x^2)*sin(10*pi*x)'
+axis:plot d1 'b'
+envelop d1 'x'
+plot d1 'r'
+
+subplot 2 2 1 '':title 'Smooth sample':ranges 0 1 0 1
+new y0 30 '0.4*sin(pi*x) + 0.3*cos(1.5*pi*x) - 0.4*sin(2*pi*x)+0.5*rnd'
+copy y1 y0:smooth y1 'x3':plot y1 'r';legend '"3" style'
+copy y2 y0:smooth y2 'x5':plot y2 'g';legend '"5" style'
+copy y3 y0:smooth y3 'x':plot y3 'b';legend 'default'
+plot y0 '{m7}:s';legend 'none':legend:box
+
+subplot 2 2 2:title 'Sew sample':rotate 50 60:light on:alpha on
+new d2 100 100 'mod((y^2-(1-x)^2)/2,0.1)'
+box:surf d2 'b'
+sew d2 'xy' 0.1
+surf d2 'r'
+
+subplot 2 2 3:title 'Resize sample (interpolation)'
+new x0 10 'rnd':new v0 10 'rnd'
+resize x1 x0 100:resize v1 v0 100
+plot x0 v0 'b+ ':plot x1 v1 'r-':label x0 v0 '%n'
+ at end verbatim
+
+ at pfig{dat_extra, Example of data smoothing}
+
+Finally one can create new data arrays on base of the existing one: extract slice, row or column of data (@ref{subdata}), summarize along a direction(s) (@ref{sum}), find distribution of data elements (@ref{hist}) and so on.
+
+ at anchor{Solve sample}
+Another interesting feature of MathGL is interpolation and root-finding. There are several functions for linear and cubic spline interpolation (see @ref{Interpolation}). Also there is a function @ref{evaluate} which do interpolation of data array for values of each data element of index data. It look as indirect access to the data elements.
+
+This function have inverse function @ref{solve} which find array of indexes at which data array is equal to given value (i.e. work as root finding). But @ref{solve} function have the issue -- usually multidimensional data (2d and 3d ones) have an infinite number of indexes which give some value. This is contour lines for 2d data, or isosurface(s) for 3d data. So, @ref{solve} function will return index only in given direction, assuming that other index(es) are the same as equidistant inde [...]
+
+ at verbatim
+zrange 0 1
+new x 20 30 '(x+2)/3*cos(pi*y)'
+new y 20 30 '(x+2)/3*sin(pi*y)'
+new z 20 30 'exp(-6*x^2-2*sin(pi*y)^2)'
+
+subplot 2 1 0:title 'Cartesian space':rotate 30 -40
+axis 'xyzU':box
+xlabel 'x':ylabel 'y'origin 1 1:grid 'xy'
+mesh x y z
+
+# section along 'x' direction
+solve u x 0.5 'x'
+var v u.nx 0 1
+evaluate yy y u v
+evaluate xx x u v
+evaluate zz z u v
+plot xx yy zz 'k2o'
+
+# 1st section along 'y' direction
+solve u1 x -0.5 'y'
+var v1 u1.nx 0 1
+evaluate yy y v1 u1
+evaluate xx x v1 u1
+evaluate zz z v1 u1
+plot xx yy zz 'b2^'
+
+# 2nd section along 'y' direction
+solve u2 x -0.5 'y' u1
+evaluate yy y v1 u2
+evaluate xx x v1 u2
+evaluate zz z v1 u2
+plot xx yy zz 'r2v'
+
+subplot 2 1 1:title 'Accompanied space'
+ranges 0 1 0 1:origin 0 0
+axis:box:xlabel 'i':ylabel 'j':grid2 z 'h'
+
+plot u v 'k2o':line 0.4 0.5 0.8 0.5 'kA'
+plot v1 u1 'b2^':line 0.5 0.15 0.5 0.3 'bA'
+plot v1 u2 'r2v':line 0.5 0.7 0.5 0.85 'rA'
+ at end verbatim
+
+ at pfig{solve, Example of data interpolation and root finding}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Data plotting, 1D samples, Data handling, Examples
+ at section Data plotting
+ at nav{}
+
+Let me now show how to plot the data. Next section will give much more examples for all plotting functions. Here I just show some basics. MathGL generally has 2 types of plotting functions. Simple variant requires a single data array for plotting, other data (coordinates) are considered uniformly distributed in axis range. Second variant requires data arrays for all coordinates. It allows one to plot rather complex multivalent curves and surfaces (in case of parametric dependencies). Usu [...]
+
+Note, that the call of drawing function adds something to picture but does not clear the previous plots (as it does in Matlab). Another difference from Matlab is that all setup (like transparency, lightning, axis borders and so on) must be specified @strong{before} plotting functions.
+
+Let start for plots for 1D data. Term ``1D data'' means that data depend on single index (parameter) like curve in parametric form @{x(i),y(i),z(i)@}, i=1...n. The textual argument allow you specify styles of line and marks (see @ref{Line styles}). If this parameter is empty @code{''} then solid line with color from palette is used (see @ref{Palette and colors}).
+
+Below I shall show the features of 1D plotting on base of @ref{plot} function. Let us start from sinus plot:
+ at verbatim
+new y0 50 'sin(pi*x)'
+subplot 2 2 0
+plot y0:box
+ at end verbatim
+Style of line is not specified in @ref{plot} function. So MathGL uses the solid line with first color of palette (this is blue). Next subplot shows array @var{y1} with 2 rows:
+ at verbatim
+subplot 2 2 1
+new y1 50 2
+fill y1 'cos(pi*(x+y/4))*2/(y+3)'
+plot y1:box
+ at end verbatim
+As previously I did not specify the style of lines. As a result, MathGL again uses solid line with next colors in palette (there are green and red). Now let us plot a circle on the same subplot. The circle is parametric curve @math{x=cos(\pi t), y=sin(\pi t)}. I will set the color of the circle (dark yellow, @samp{Y}) and put marks @samp{+} at point position:
+ at verbatim
+new x 50 'cos(pi*x)'
+plot x y0 'Y+'
+ at end verbatim
+Note that solid line is used because I did not specify the type of line. The same picture can be achieved by @ref{plot} and @ref{subdata} functions. Let us draw ellipse by orange dash line:
+ at verbatim
+plot y1(:,0) y1(:,1) 'q|'
+ at end verbatim
+
+Drawing in 3D space is mostly the same. Let us draw spiral with default line style. Now its color is 4-th color from palette (this is cyan):
+ at verbatim
+subplot 2 2 2:rotate 60 40
+new z 50 'x'
+plot x y0 z:box
+ at end verbatim
+Functions @ref{plot} and @ref{subdata} make 3D curve plot but for single array. Use it to put circle marks on the previous plot:
+ at verbatim
+new y2 10 3 'cos(pi*(x+y/2))'
+modify y2 '2*x-1' 2
+plot y2(:,0) y2(:,1) y2(:,2) 'bo '
+ at end verbatim
+Note that line style is empty @samp{ } here. Usage of other 1D plotting functions looks similar:
+ at verbatim
+subplot 2 2 3:rotate 60 40
+bars x y0 z 'r':box
+ at end verbatim
+
+Surfaces @ref{surf} and other 2D plots (@pxref{2D plotting}) are drown the same simpler as 1D one. The difference is that the string parameter specifies not the line style but the color scheme of the plot (see @ref{Color scheme}). Here I draw attention on 4 most interesting color schemes. There is gray scheme where color is changed from black to white (string @samp{kw}) or from white to black (string @samp{wk}). Another scheme is useful for accentuation of negative (by blue color) and po [...]
+
+Now I shall show the example of a surface drawing. At first let us switch lightning on
+ at verbatim
+light on
+ at end verbatim
+and draw the surface, considering coordinates x,y to be uniformly distributed in axis range
+ at verbatim
+new a0 50 40 '0.6*sin(pi*(x+1))*sin(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'
+subplot 2 2 0:rotate 60 40
+surf a0:box
+ at end verbatim
+Color scheme was not specified. So previous color scheme is used. In this case it is default color scheme (``jet'') for the first plot. Next example is a sphere. The sphere is parametrically specified surface:
+ at verbatim
+new x 50 40 '0.8*sin(pi*x)*cos(pi*y/2)'
+new y 50 40 '0.8*cos(pi*x)*cos(pi*y/2)'
+new z 50 40 '0.8*sin(pi*y/2)'
+subplot 2 2 1:rotate 60 40
+surf x y z 'BbwrR':box
+ at end verbatim
+I set color scheme to @code{"BbwrR"} that corresponds to red top and blue bottom of the sphere.
+
+Surfaces will be plotted for each of slice of the data if @var{nz}>1. Next example draws surfaces for data arrays with @var{nz}=3:
+ at verbatim
+new a1 50 40 3
+modify a1 '0.6*sin(2*pi*x)*sin(3*pi*y)+0.4*cos(3*pi*(x*y))'
+modify a1 '0.6*cos(2*pi*x)*cos(3*pi*y)+0.4*sin(3*pi*(x*y))' 1
+modify a1 '0.6*cos(2*pi*x)*cos(3*pi*y)+0.4*cos(3*pi*(x*y))' 2
+subplot 2 2 2:rotate 60 40
+alpha on
+surf a1:box
+ at end verbatim
+Note, that it may entail a confusion. However, if one will use density plot then the picture will look better:
+ at verbatim
+subplot 2 2 3:rotate 60 40
+dens a1:box
+ at end verbatim
+
+Drawing of other 2D plots is analogous. The only peculiarity is the usage of flag @samp{#}. By default this flag switches on the drawing of a grid on plot (@ref{grid} or @ref{mesh} for plots in plain or in volume). However, for isosurfaces (including surfaces of rotation @ref{axial}) this flag switches the  face drawing off and figure becomes wired.
+ at c ------------------------------------------------------------------
+ at external{}
+ at node 1D samples, 2D samples, Data plotting, Examples
+ at section 1D samples
+ at nav{}
+
+This section is devoted to visualization of 1D data arrays. 1D means the data which depend on single index (parameter) like curve in parametric form @{x(i),y(i),z(i)@}, i=1...n. Most of samples will use the same data for plotting. So, I put its initialization in separate function
+ at verbatim
+func 'prepare1d'
+new y 50 3
+modify y '0.7*sin(2*pi*x)+0.5*cos(3*pi*x)+0.2*sin(pi*x)'
+modify y 'sin(2*pi*x)' 1
+modify y 'cos(2*pi*x)' 2
+new x1 50 'x'
+new x2 50 '0.05-0.03*cos(pi*x)'
+new y1 50 '0.5-0.3*cos(pi*x)'
+new y2 50 '-0.3*sin(pi*x)'
+return
+ at end verbatim
+Basically, you can put this text after the script. Note, that you need to terminate main script by @ref{stop} command before defining a function.
+
+ at menu
+* Plot sample::
+* Radar sample::
+* Step sample::
+* Tens sample::
+* Area sample::
+* Region sample::
+* Stem sample::
+* Bars sample::
+* Barh sample::
+* Cones sample::
+* Chart sample::
+* BoxPlot sample::
+* Candle sample::
+* OHLC sample::
+* Error sample::
+* Mark sample::
+* TextMark sample::
+* Label sample::
+* Table sample::
+* Iris sample::
+* Tube sample::
+* Tape sample::
+* Torus sample::
+* Lamerey sample::
+* Bifurcation sample::
+* Pmap sample::
+ at end menu
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Plot sample, Radar sample, , 1D samples
+ at subsection Plot sample
+ at nav{}
+
+Command @ref{plot} is most standard way to visualize 1D data array. By default, @code{Plot} use colors from palette. However, you can specify manual color/palette, and even set to use new color for each points by using @samp{!} style. Another feature is @samp{ } style which draw only markers without line between points. The sample code is:
+ at verbatim
+call 'prepare1d'
+subplot 2 2 0 '':title 'Plot plot (default)':box
+plot y
+
+subplot 2 2 2 '':title ''!' style; 'rgb' palette':box
+plot y 'o!rgb'
+
+subplot 2 2 3 '':title 'just markers':box
+plot y ' +'
+
+new yc 30 'sin(pi*x)':new xc 30 'cos(pi*x)':new z 30 'x'
+subplot 2 2 1:title '3d variant':rotate 50 60:box
+plot xc yc z 'rs'
+ at end verbatim
+
+ at pfig{plot, Example of Plot()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Radar sample, Step sample, Plot sample, 1D samples
+ at subsection Radar sample
+ at nav{}
+
+Command @ref{radar} plot is variant of @code{Plot} one, which make plot in polar coordinates and draw radial rays in point directions. If you just need a plot in polar coordinates then I recommend to use @ref{Curvilinear coordinates} or @code{Plot} in parabolic form with @code{x=r*cos(fi); y=r*sin(fi);}. The sample code is:
+ at verbatim
+new yr 10 3 '0.4*sin(pi*(x+1.5+y/2)+0.1*rnd)'
+subplot 1 1 0 '':title 'Radar plot (with grid, "\#")'
+radar yr '#'
+ at end verbatim
+
+ at pfig{radar, Example of Radar()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Step sample, Tens sample, Radar sample, 1D samples
+ at subsection Step sample
+ at nav{}
+
+Command @ref{step} plot data as stairs. It have the same options as @code{Plot}. The sample code is:
+ at verbatim
+call 'prepare1d'
+origin 0 0 0:subplot 2 2 0 '':title 'Step plot (default)':box
+step y
+
+new yc 30 'sin(pi*x)':new xc 30 'cos(pi*x)':new z 30 'x'
+subplot 2 2 1:title '3d variant':rotate 50 60:box
+step xc yc z 'r'
+
+subplot 2 2 2 '':title '"!" style':box
+step y 's!rgb'
+ at end verbatim
+
+ at pfig{step, Example of Step()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Tens sample, Area sample, Step sample, 1D samples
+ at subsection Tens sample
+ at nav{}
+
+Command @ref{tens} is variant of @ref{plot} with smooth coloring along the curves. At this, color is determined as for surfaces (see @ref{Color scheme}). The sample code is:
+ at verbatim
+call 'prepare1d'
+subplot 2 2 0 '':title 'Tens plot (default)':box
+tens y(:,0) y(:,1)
+
+subplot 2 2 2 '':title ' style':box
+tens y(:,0) y(:,1) 'o '
+
+new yc 30 'sin(pi*x)':new xc 30 'cos(pi*x)':new z 30 'x'
+subplot 2 2 1:title '3d variant':rotate 50 60:box
+tens xc yc z z 's'
+ at end verbatim
+
+ at pfig{tens, Example of Tens()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Area sample, Region sample, Tens sample, 1D samples
+ at subsection Area sample
+ at nav{}
+
+Command @ref{area} fill the area between curve and axis plane. It support gradient filling if 2 colors per curve is specified. The sample code is:
+ at verbatim
+call 'prepare1d'
+origin 0 0 0
+subplot 2 2 0 '':title 'Area plot (default)':box
+area y
+
+subplot 2 2 1 '':title '2 colors':box
+area y 'cbgGyr'
+
+subplot 2 2 2 '':title '"!" style':box
+area y '!'
+
+new yc 30 'sin(pi*x)':new xc 30 'cos(pi*x)':new z 30 'x'
+subplot 2 2 3:title '3d variant':rotate 50 60:box
+area xc yc z 'r':area xc -yc z 'b#'
+ at end verbatim
+
+ at pfig{area, Example of Area()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Region sample, Stem sample, Area sample, 1D samples
+ at subsection Region sample
+ at nav{}
+
+Command @ref{region} fill the area between 2 curves. It support gradient filling if 2 colors per curve is specified. Also it can fill only the region y1<y<y2 if style @samp{i} is used. The sample code is:
+ at verbatim
+call 'prepare1d'
+copy y1 y(:,1):copy y2 y(:,2)
+
+subplot 2 2 0 '':title 'Region plot (default)':box
+region y1 y2:plot y1 'k2':plot y2 'k2'
+
+subplot 2 2 1 '':title '2 colors':box
+region y1 y2 'yr':plot y1 'k2':plot y2 'k2'
+
+subplot 2 2 2 '':title '"i" style':box
+region y1 y2 'ir':plot y1 'k2':plot y2 'k2'
+
+subplot 2 2 3 '^_':title '3d variant':rotate 40 60:box
+new x1 100 'sin(pi*x)':new y1 100 'cos(pi*x)':new z 100 'x'
+new x2 100 'sin(pi*x+pi/3)':new y2 100 'cos(pi*x+pi/3)'
+plot x1 y1 z 'r2':plot x2 y2 z 'b2'
+region x1 y1 z x2 y2 z 'cmy!'
+ at end verbatim
+
+ at pfig{region, Example of Region()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Stem sample, Bars sample, Region sample, 1D samples
+ at subsection Stem sample
+ at nav{}
+
+Command @ref{stem} draw vertical bars. It is most attractive if markers are drawn too. The sample code is:
+ at verbatim
+call 'prepare1d'
+origin 0 0 0:subplot 2 2 0 '':title 'Stem plot (default)':box
+stem y
+
+new yc 30 'sin(pi*x)':new xc 30 'cos(pi*x)':new z 30 'x'
+subplot 2 2 1:title '3d variant':rotate 50 60:box
+stem xc yc z 'rx'
+
+subplot 2 2 2 '':title '"!" style':box
+stem y 'o!rgb'
+ at end verbatim
+
+ at pfig{stem, Example of Stem()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Bars sample, Barh sample, Stem sample, 1D samples
+ at subsection Bars sample
+ at nav{}
+
+Command @ref{bars} draw vertical bars. It have a lot of options: bar-above-bar (@samp{a} style), fall like (@samp{f} style), 2 colors for positive and negative values, wired bars (@samp{#} style), 3D variant. The sample code is:
+ at verbatim
+new ys 10 3 '0.8*sin(pi*(x+y/4+1.25))+0.2*rnd':origin 0 0 0
+subplot 3 2 0 '':title 'Bars plot (default)':box
+bars ys
+
+subplot 3 2 1 '':title '2 colors':box
+bars ys 'cbgGyr'
+
+subplot 3 2 4 '':title '"\#" style':box
+bars ys '#'
+
+new yc 30 'sin(pi*x)':new xc 30 'cos(pi*x)':new z 30 'x'
+subplot 3 2 5:title '3d variant':rotate 50 60:box
+bars xc yc z 'r'
+
+subplot 3 2 2 '':title '"a" style':ranges -1 1 -3 3:box
+bars ys 'a'
+
+subplot 3 2 3 '':title '"f" style':box
+bars ys 'f'
+ at end verbatim
+
+ at pfig{bars, Example of Bars()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Barh sample, Cones sample, Bars sample, 1D samples
+ at subsection Barh sample
+ at nav{}
+
+Command @ref{barh} is the similar to @code{Bars} but draw horizontal bars. The sample code is:
+ at verbatim
+new ys 10 3 '0.8*sin(pi*(x+y/4+1.25))+0.2*rnd':origin 0 0 0
+subplot 2 2 0 '':title 'Barh plot (default)':box
+barh ys
+
+subplot 2 2 1 '':title '2 colors':box
+barh ys 'cbgGyr'
+
+ranges -3 3 -1 1:subplot 2 2 2 '':title '"a" style':box:barh ys 'a'
+subplot 2 2 3 '': title '"f" style':box
+barh ys 'f'
+ at end verbatim
+
+ at pfig{barh, Example of Barh()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cones sample, Chart sample, Bars sample, 1D samples
+ at subsection Cones sample
+ at nav{}
+
+Command @ref{cones} is similar to @code{Bars} but draw cones. The sample code is:
+ at verbatim
+new ys 10 3 '0.8*sin(pi*(x+y/4+1.25))+0.2*rnd'
+origin 0 0 0:light on
+subplot 3 2 0:title 'Cones plot':rotate 50 60:box
+cones ys
+
+subplot 3 2 1:title '2 colors':rotate 50 60:box
+cones ys 'cbgGyr'
+
+subplot 3 2 2:title '"\#" style':rotate 50 60:box
+cones ys '#'
+
+subplot 3 2 3:title '"a" style':rotate 50 60:zrange -2 2:box
+cones ys 'a'
+
+subplot 3 2 4:title '"t" style':rotate 50 60:box
+cones ys 't'
+
+subplot 3 2 5:title '"4" style':rotate 50 60:box
+cones ys '4'
+ at end verbatim
+
+ at pfig{cones, Example of Cones()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Chart sample, BoxPlot sample, Cones sample, 1D samples
+ at subsection Chart sample
+ at nav{}
+
+Command @ref{chart} draw colored boxes with width proportional to data values. Use @samp{ } for empty box. Plot looks most attractive in polar coordinates -- well known pie chart. The sample code is:
+ at verbatim
+new ch 7 2 'rnd+0.1':light on
+subplot 2 2 0:title 'Chart plot (default)':rotate 50 60:box
+chart ch
+
+subplot 2 2 1:title '"\#" style':rotate 50 60:box
+chart ch '#'
+
+subplot 2 2 2:title 'Pie chart; " " color':rotate 50 60:
+axis '(y+1)/2*cos(pi*x)' '(y+1)/2*sin(pi*x)' '':box
+chart ch 'bgr cmy#'
+
+subplot 2 2 3:title 'Ring chart; " " color':rotate 50 60:
+axis '(y+2)/3*cos(pi*x)' '(y+2)/3*sin(pi*x)' '':box
+chart ch 'bgr cmy#'
+ at end verbatim
+
+ at pfig{chart, Example of Chart()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node BoxPlot sample, Candle sample, Chart sample, 1D samples
+ at subsection BoxPlot sample
+ at nav{}
+
+Command @ref{boxplot} draw box-and-whisker diagram. The sample code is:
+ at verbatim
+new a 10 7 '(2*rnd-1)^3/2'
+subplot 1 1 0 '':title 'Boxplot plot':box
+boxplot a
+ at end verbatim
+
+ at pfig{boxplot, Example of BoxPlot()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Candle sample, OHLC sample, BoxPlot sample, 1D samples
+ at subsection Candle sample
+ at nav{}
+
+Command @ref{candle} draw candlestick chart. This is a combination of a line-chart and a bar-chart, in that each bar represents the range of price movement over a given time interval. The sample code is:
+ at verbatim
+new y 30 'sin(pi*x/2)^2':copy y1 y/2:copy y2 (y+1)/2
+subplot 1 1 0 '':title 'Candle plot (default)':yrange 0 1:box
+candle y y1 y2
+ at end verbatim
+
+ at pfig{candle, Example of Candle()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node OHLC sample, Error sample, Candle sample, 1D samples
+ at subsection OHLC sample
+ at nav{}
+
+Command @ref{ohlc} draw Open-High-Low-Close diagram. This diagram show vertical line for between maximal(high) and minimal(low) values, as well as horizontal lines before/after vertical line for initial(open)/final(close) values of some process. The sample code is:
+ at verbatim
+new o 10 '0.5*sin(pi*x)'
+new c 10 '0.5*sin(pi*(x+2/9))'
+new l 10 '0.3*rnd-0.8'
+new h 10 '0.3*rnd+0.5'
+subplot 1 1 0 '':title 'OHLC plot':box
+ohlc o h l c
+ at end verbatim
+
+ at pfig{ohlc, Example of OHLC()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Error sample, Mark sample, OHLC sample, 1D samples
+ at subsection Error sample
+ at nav{}
+
+Command @ref{error} draw error boxes around the points. You can draw default boxes or semi-transparent symbol (like marker, see @ref{Line styles}). Also you can set individual color for each box. The sample code is:
+ at verbatim
+call 'prepare1d'
+new y 50 '0.7*sin(pi*x-pi) + 0.5*cos(3*pi*(x+1)/2) + 0.2*sin(pi*(x+1)/2)'
+new x0 10 'x + 0.1*rnd-0.05':new ex 10 '0.1':new ey 10 '0.2'
+new y0 10 '0.7*sin(pi*x-pi) + 0.5*cos(3*pi*(x+1)/2) + 0.2*sin(pi*(x+1)/2) + 0.2*rnd-0.1'
+
+subplot 2 2 0 '':title 'Error plot (default)':box:plot y
+error x0 y0 ex ey 'k'
+
+subplot 2 2 1 '':title '"!" style; no e_x':box:plot y
+error x0 y0 ey 'o!rgb'
+
+subplot 2 2 2 '':title '"\@" style':box:plot y
+error x0 y0 ex ey '@'; alpha 0.5
+
+subplot 2 2 3:title '3d variant':rotate 50 60:axis
+for $1 0 9
+  errbox 2*rnd-1 2*rnd-1 2*rnd-1 0.2 0.2 0.2 'bo'
+next
+ at end verbatim
+
+ at pfig{error, Example of Error()}
+
+Additionally, you can use solid large "marks" instead of error boxes by selecting proper style.
+ at verbatim
+new x0 10 'rnd':new ex 10 '0.1'
+new y0 10 'rnd':new ey 10 '0.1'
+ranges 0 1 0 1
+subplot 4 3 0 '':box:error x0 y0 ex ey '#+@'
+subplot 4 3 1 '':box:error x0 y0 ex ey '#x@'
+subplot 4 3 2 '':box:error x0 y0 ex ey '#s@'; alpha 0.5
+subplot 4 3 3 '':box:error x0 y0 ex ey 's@'
+subplot 4 3 4 '':box:error x0 y0 ex ey 'd@'
+subplot 4 3 5 '':box:error x0 y0 ex ey '#d@'; alpha 0.5
+subplot 4 3 6 '':box:error x0 y0 ex ey '+@'
+subplot 4 3 7 '':box:error x0 y0 ex ey 'x@'
+subplot 4 3 8 '':box:error x0 y0 ex ey 'o@'
+subplot 4 3 9 '':box:error x0 y0 ex ey '#o@'; alpha 0.5
+subplot 4 3 10 '':box:error x0 y0 ex ey '#.@'
+subplot 4 3 11 '':box:error x0 y0 ex ey; alpha 0.5
+ at end verbatim
+
+ at pfig{error2, Example of Error() with marks}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Mark sample, TextMark sample, Error sample, 1D samples
+ at subsection Mark sample
+ at nav{}
+
+Command @ref{mark} draw markers at points. It is mostly the same as @code{Plot} but marker size can be variable. The sample code is:
+ at verbatim
+call 'prepare1d'
+subplot 1 1 0 '':title 'Mark plot (default)':box
+mark y y1 's'
+ at end verbatim
+
+ at pfig{mark, Example of Mark()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node TextMark sample, Label sample, Mark sample, 1D samples
+ at subsection TextMark sample
+ at nav{}
+
+Command @ref{textmark} like @code{Mark} but draw text instead of markers. The sample code is:
+ at verbatim
+call 'prepare1d'
+subplot 1 1 0 '':title 'TextMark plot (default)':box
+textmark y y1 '\gamma' 'r'
+ at end verbatim
+
+ at pfig{textmark, Example of TextMark()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Label sample, Table sample, TextMark sample, 1D samples
+ at subsection Label sample
+ at nav{}
+
+Command @ref{label} print text at data points. The string may contain @samp{%x}, @samp{%y}, @samp{%z} for x-, y-, z-coordinates of points, @samp{%n} for point index. The sample code is:
+ at verbatim
+new ys 10 '0.2*rnd-0.8*sin(pi*x)'
+subplot 1 1 0 '':title 'Label plot':box
+plot ys ' *':label ys 'y=%y'
+ at end verbatim
+
+ at pfig{label, Example of Label()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Table sample, Iris sample, Label sample, 1D samples
+ at subsection Table sample
+ at nav{}
+
+Command @ref{table} draw table with data values. The sample code is:
+ at verbatim
+new ys 10 3 '0.8*sin(pi*(x+y/4+1.25))+0.2*rnd'
+subplot 2 2 0:title 'Table sample':box
+table ys 'y_1\n{}y_2\n{}y_3'
+
+subplot 2 2 1:title 'no borders, colored'
+table ys 'y_1\n{}y_2\n{}y_3' 'r|'
+
+subplot 2 2 2:title 'no font decrease'
+table ys 'y_1\n{}y_2\n{}y_3' '#'
+
+subplot 2 2 3:title 'manual width and position':box
+table 0.5 0.95 ys 'y_1\n{}y_2\n{}y_3' '#';value 0.7
+ at end verbatim
+
+ at pfig{table, Example of Table()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Iris sample, Tube sample, Table sample, 1D samples
+ at subsection Iris sample
+ at nav{}
+
+Command @ref{iris} draw Iris plot for columns of data array. The sample code is:
+ at verbatim
+read a 'iris.dat'
+crop a 0 4 'x':rearrange a a.nx 50
+subplot 1 1 0 '':title 'Iris plot'
+iris a 'sepal\n length;sepal\n width;petal\n length;petal\n width' '. ';value -1.5;size -2
+ at end verbatim
+
+ at pfig{iris, Example of Iris()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Tube sample, Tape sample, Iris sample, 1D samples
+ at subsection Tube sample
+ at nav{}
+
+Command @ref{tube} draw tube with variable radius. The sample code is:
+ at verbatim
+light on:call 'prepare1d'
+new yc 50 'sin(pi*x)':new xc 50 'cos(pi*x)':new z 50 'x':divto y1 20
+
+subplot 2 2 0 '':title 'Tube plot (default)':box
+tube y 0.05
+
+subplot 2 2 1 '':title 'variable radius':box
+tube y y1
+
+subplot 2 2 2 '':title '"\#" style':box
+tube y 0.05 '#'
+
+subplot 2 2 3:title '3d variant':rotate 50 60:box
+tube xc yc z y2 'r'
+ at end verbatim
+
+ at pfig{tube, Example of Tube()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Tape sample, Torus sample, Tube sample, 1D samples
+ at subsection Tape sample
+ at nav{}
+
+Command @ref{tape} draw tapes which rotate around the curve as normal and binormal. The sample code is:
+ at verbatim
+call 'prepare1d'
+new yc 50 'sin(pi*x)':new xc 50 'cos(pi*x)':new z 50 'x'
+
+subplot 2 2 0 '':title 'Tape plot (default)':box
+tape y:plot y 'k'
+
+subplot 2 2 1:title '3d variant, 2 colors':rotate 50 60:light on:box
+plot xc yc z 'k':tape xc yc z 'rg'
+
+subplot 2 2 2:title '3d variant, x only':rotate 50 60:box
+plot xc yc z 'k':tape xc yc z 'xr':tape xc yc z 'xr#'
+
+subplot 2 2 3:title '3d variant, z only':rotate 50 60:box
+plot xc yc z 'k':tape xc yc z 'zg':tape xc yc z 'zg#'
+ at end verbatim
+
+ at pfig{tape, Example of Tape()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Torus sample, Lamerey sample, Tape sample, 1D samples
+ at subsection Torus sample
+ at nav{}
+
+Command @ref{torus} draw surface of the curve rotation. The sample code is:
+ at verbatim
+call 'prepare1d'
+subplot 2 2 0:title 'Torus plot (default)':light on:rotate 50 60:box
+torus y1 y2
+
+subplot 2 2 1:title '"x" style':light on:rotate 50 60:box
+torus y1 y2 'x'
+
+subplot 2 2 2:title '"z" style':light on:rotate 50 60:box
+torus y1 y2 'z'
+
+subplot 2 2 3:title '"\#" style':light on:rotate 50 60:box
+torus y1 y2 '#'
+ at end verbatim
+
+ at pfig{torus, Example of Torus()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Lamerey sample, Bifurcation sample, Torus sample, 1D samples
+ at subsection Lamerey sample
+ at nav{}
+
+Function @ref{lamerey} draw Lamerey diagram. The sample code is:
+ at verbatim
+subplot 1 1 0 '<_':title 'Lamerey sample'
+axis:xlabel '\i x':ylabel '\bar{\i x} = 2 \i{x}'
+fplot 'x' 'k='
+fplot '2*x' 'b'
+
+lamerey 0.00097 '2*x' 'rv~';size 2
+lamerey -0.00097 '2*x' 'rv~';size 2
+ at end verbatim
+
+ at pfig{lamerey, Example of Lamerey()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Bifurcation sample, Pmap sample, Lamerey sample, 1D samples
+ at subsection Bifurcation sample
+ at nav{}
+
+Function @ref{bifurcation} draw Bifurcation diagram for logistic map. The sample code is:
+ at verbatim
+subplot 1 1 0 '<_':title 'Bifurcation sample'
+ranges 0 4 0 1:axis
+bifurcation 0.005 'x*y*(1-y)' 'r'
+ at end verbatim
+
+ at pfig{bifurcation, Example of Bifurcation()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Pmap sample, , Bifurcation sample, 1D samples
+ at subsection Pmap sample
+ at nav{}
+
+Function @ref{pmap} draw Poincare map -- show intersections of the curve and the surface. The sample code is:
+ at verbatim
+subplot 1 1 0 '<_^':title 'Poincare map sample'
+ode r 'cos(y)+sin(z);cos(z)+sin(x);cos(x)+sin(y)' 'xyz' [0.1,0,0] 0.1 100
+rotate 40 60:copy x r(0):copy y r(1):copy z r(2)
+ranges x y z
+axis:plot x y z 'b':fsurf '0'
+xlabel '\i x' 0:ylabel '\i y' 0:zlabel '\i z'
+
+pmap x y z z 'b#o'
+ at end verbatim
+
+ at pfig{pmap, Example of Pmap()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node 2D samples, 3D samples, 1D samples, Examples
+ at section 2D samples
+ at nav{}
+
+This section is devoted to visualization of 2D data arrays. 2D means the data which depend on 2 indexes (parameters) like matrix z(i,j)=z(x(i),y(j)), i=1...n, j=1...m or in parametric form @{x(i,j),y(i,j),z(i,j)@}. Most of samples will use the same data for plotting. So, I put its initialization in separate function
+ at verbatim
+func 'prepare2d'
+new a 50 40 '0.6*sin(pi*(x+1))*sin(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'
+new b 50 40 '0.6*cos(pi*(x+1))*cos(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'
+return
+ at end verbatim
+Basically, you can put this text after the script. Note, that you need to terminate main script by @ref{stop} command before defining a function.
+
+ at menu
+* Surf sample::
+* SurfC sample::
+* SurfA sample::
+* SurfCA sample::
+* Mesh sample::
+* Fall sample::
+* Belt sample::
+* Boxs sample::
+* Tile sample::
+* TileS sample::
+* Dens sample::
+* Cont sample::
+* ContF sample::
+* ContD sample::
+* ContV sample::
+* Axial sample::
+* Grad sample::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Surf sample, SurfC sample, , 2D samples
+ at subsection Surf sample
+ at nav{}
+
+Command @ref{surf} is most standard way to visualize 2D data array. @code{Surf} use color scheme for coloring (see @ref{Color scheme}). You can use @samp{#} style for drawing black meshes on the surface. The sample code is:
+ at verbatim
+call 'prepare2d'
+subplot 2 2 0:title 'Surf plot (default)':rotate 50 60:light on:box:surf a
+
+subplot 2 2 1:title '"\#" style; meshnum 10':rotate 50 60:box
+surf a '#'; meshnum 10
+
+subplot 2 2 2:title '"." style':rotate 50 60:box
+surf a '.'
+
+new x 50 40 '0.8*sin(pi*x)*sin(pi*(y+1)/2)'
+new y 50 40 '0.8*cos(pi*x)*sin(pi*(y+1)/2)'
+new z 50 40 '0.8*cos(pi*(y+1)/2)'
+subplot 2 2 3:title 'parametric form':rotate 50 60:box
+surf x y z 'BbwrR'
+ at end verbatim
+
+ at pfig{surf, Example of Surf()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node SurfC sample, SurfA sample, Surf sample, 2D samples
+ at subsection SurfC sample
+ at nav{}
+
+Command @ref{surfc} is similar to @ref{surf} but its coloring is determined by another data. The sample code is:
+ at verbatim
+call 'prepare2d'
+title 'SurfC plot':rotate 50 60:light on:box
+surfc a b
+ at end verbatim
+
+ at pfig{surfc, Example of SurfC()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node SurfA sample, SurfCA sample, SurfC sample, 2D samples
+ at subsection SurfA sample
+ at nav{}
+
+Command @ref{surfa} is similar to @ref{surf} but its transparency is determined by another data. The sample code is:
+ at verbatim
+call 'prepare2d'
+title 'SurfA plot':rotate 50 60:light on:alpha on:box
+surfa a b
+ at end verbatim
+
+ at pfig{surfa, Example of SurfA()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node SurfCA sample, Mesh sample, SurfA sample, 2D samples
+ at subsection SurfCA sample
+ at nav{}
+
+Command @ref{surfca} is similar to @ref{surf} but its color and transparency is determined by another data. The sample code is:
+ at verbatim
+call 'prepare2d'
+title 'SurfCA plot':rotate 50 60:light on:alpha on:box
+surfa a b a
+ at end verbatim
+
+ at pfig{surfca, Example of SurfCA()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Mesh sample, Fall sample, SurfCA sample, 2D samples
+ at subsection Mesh sample
+ at nav{}
+
+Command @ref{mesh} draw wired surface. You can use @ref{meshnum} for changing number of lines to be drawn. The sample code is:
+ at verbatim
+call 'prepare2d'
+title 'Mesh plot':rotate 50 60:box
+mesh a
+ at end verbatim
+
+ at pfig{mesh, Example of Mesh()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Fall sample, Belt sample, Mesh sample, 2D samples
+ at subsection Fall sample
+ at nav{}
+
+Command @ref{fall} draw waterfall surface. You can use @ref{meshnum} for changing number of lines to be drawn. Also you can use @samp{x} style for drawing lines in other direction. The sample code is:
+ at verbatim
+call 'prepare2d'
+title 'Fall plot':rotate 50 60:box
+fall a
+ at end verbatim
+
+ at pfig{fall, Example of Fall()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Belt sample, Boxs sample, Fall sample, 2D samples
+ at subsection Belt sample
+ at nav{}
+
+Command @ref{belt} draw surface by belts. You can use @samp{x} style for drawing lines in other direction. The sample code is:
+ at verbatim
+call 'prepare2d'
+title 'Belt plot':rotate 50 60:box
+belt a
+ at end verbatim
+
+ at pfig{belt, Example of Belt()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Boxs sample, Tile sample, Fall sample, 2D samples
+ at subsection Boxs sample
+ at nav{}
+
+Command @ref{boxs} draw surface by boxes. You can use @samp{#} for drawing wire plot. The sample code is:
+ at verbatim
+call 'prepare2d'
+origin 0 0 0
+subplot 2 2 0:title 'Boxs plot (default)':rotate 40 60:light on:box
+boxs a
+
+subplot 2 2 1:title '"\@" style':rotate 50 60:box
+boxs a '@'
+
+subplot 2 2 2:title '"\#" style':rotate 50 60:box
+boxs a '#'
+
+subplot 2 2 3:title 'compare with Tile':rotate 50 60:box
+tile a
+ at end verbatim
+
+ at pfig{boxs, Example of Boxs()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Tile sample, TileS sample, Boxs sample, 2D samples
+ at subsection Tile sample
+ at nav{}
+
+Command @ref{tile} draw surface by tiles. The sample code is:
+ at verbatim
+call 'prepare2d'
+subplot 1 1 0 '':title 'Tiles plot':box
+tile a
+ at end verbatim
+
+ at pfig{tile, Example of Tile()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node TileS sample, Dens sample, Tile sample, 2D samples
+ at subsection TileS sample
+ at nav{}
+
+Command @ref{tiles} is similar to @ref{tile} but tile sizes is determined by another data. This allows one to simulate transparency of the plot. The sample code is:
+ at verbatim
+call 'prepare2d'
+subplot 1 1 0 '':title 'Tiles plot':box
+tiles a b
+ at end verbatim
+
+ at pfig{tiles, Example of TileS()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Dens sample, Cont sample, TileS sample, 2D samples
+ at subsection Dens sample
+ at nav{}
+
+Command @ref{dens} draw density plot for surface. The sample code is:
+ at verbatim
+call 'prepare2d'
+subplot 2 2 0 '':title 'Dens plot (default)':box
+dens a
+
+subplot 2 2 1:title '3d variant':rotate 50 60:box
+dens a
+
+subplot 2 2 2 '':title '"\#" style; meshnum 10':box
+dens a '#'; meshnum 10
+
+new a1 30 40 3 '0.6*sin(2*pi*x+pi*(z+1)/2)*sin(3*pi*y+pi*z) +\
+ 0.4*cos(3*pi*(x*y)+pi*(z+1)^2/2)'
+subplot 2 2 3:title 'several slices':rotate 50 60:box
+dens a1
+ at end verbatim
+
+ at pfig{dens, Example of Dens()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cont sample, ContF sample, Dens sample, 2D samples
+ at subsection Cont sample
+ at nav{}
+
+Command @ref{cont} draw contour lines for surface. You can select automatic (default) or manual levels for contours, print contour labels, draw it on the surface (default) or at plane (as @code{Dens}). The sample code is:
+ at verbatim
+call 'prepare2d'
+list v -0.5 -0.15 0 0.15 0.5
+subplot 2 2 0:title 'Cont plot (default)':rotate 50 60:box
+cont a
+
+subplot 2 2 1:title 'manual levels':rotate 50 60:box
+cont v a
+
+subplot 2 2 2:title '"\_" style':rotate 50 60:box
+cont a '_'
+
+subplot 2 2 3 '':title '"t" style':box
+cont a 't'
+ at end verbatim
+
+ at pfig{cont, Example of Cont()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ContF sample, ContD sample, Cont sample, 2D samples
+ at subsection ContF sample
+ at nav{}
+
+Command @ref{contf} draw filled contours.  You can select automatic (default) or manual levels for contours. The sample code is:
+ at verbatim
+call 'prepare2d'
+list v -0.5 -0.15 0 0.15 0.5
+subplot 2 2 0:title 'ContF plot (default)':rotate 50 60:box
+contf a
+
+subplot 2 2 1:title 'manual levels':rotate 50 60:box
+contf v a
+
+subplot 2 2 2:title '"\_" style':rotate 50 60:box
+contf a '_'
+
+new a1 30 40 3 '0.6*sin(2*pi*x+pi*(z+1)/2)*sin(3*pi*y+pi*z) +\
+ 0.4*cos(3*pi*(x*y)+pi*(z+1)^2/2)'
+subplot 2 2 3:title 'several slices':rotate 50 60:box
+contf a1
+ at end verbatim
+
+ at pfig{contf, Example of ContF()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ContD sample, ContV sample, ContF sample, 2D samples
+ at subsection ContD sample
+ at nav{}
+
+Command @ref{contd} is similar to @code{ContF} but with manual contour colors. The sample code is:
+ at verbatim
+call 'prepare2d'
+list v -0.5 -0.15 0 0.15 0.5
+subplot 2 2 0:title 'ContD plot (default)':rotate 50 60:box
+contd a
+
+subplot 2 2 1:title 'manual levels':rotate 50 60:box
+contd v a
+
+subplot 2 2 2:title '"\_" style':rotate 50 60:box
+contd a '_'
+
+new a1 30 40 3 '0.6*sin(2*pi*x+pi*(z+1)/2)*sin(3*pi*y+pi*z) +\
+ 0.4*cos(3*pi*(x*y)+pi*(z+1)^2/2)'
+subplot 2 2 3:title 'several slices':rotate 50 60:box
+contd a1
+ at end verbatim
+
+ at pfig{contd, Example of ContD()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ContV sample, Axial sample, ContD sample, 2D samples
+ at subsection ContV sample
+ at nav{}
+
+Command @ref{contv} draw vertical cylinders (belts) at contour lines. The sample code is:
+ at verbatim
+call 'prepare2d'
+list v -0.5 -0.15 0 0.15 0.5
+subplot 2 2 0:title 'ContV plot (default)':rotate 50 60:box
+contv a
+
+subplot 2 2 1:title 'manual levels':rotate 50 60:box
+contv v a
+
+subplot 2 2 2:title '"\_" style':rotate 50 60:box
+contv a '_'
+
+subplot 2 2 3:title 'ContV and ContF':rotate 50 60:light on:box
+contv a:contf a:cont a 'k'
+ at end verbatim
+
+ at pfig{contv, Example of ContV()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Axial sample, Grad sample, ContV sample, 2D samples
+ at subsection Axial sample
+ at nav{}
+
+Command @ref{axial} draw surfaces of rotation for contour lines. You can draw wire surfaces (@samp{#} style) or ones rotated in other directions (@samp{x}, @samp{z} styles). The sample code is:
+ at verbatim
+light on:alpha on:call 'prepare2d'
+subplot 2 2 0:title 'Axial plot (default)':rotate 50 60:box
+axial a
+
+subplot 2 2 1:title '"x" style;\".\" style':light on:rotate 50 60:box
+axial a 'x.'
+
+subplot 2 2 2:title '"z" style':light on:rotate 50 60:box
+axial a 'z'
+
+subplot 2 2 3:title '"\#" style':light on:rotate 50 60:box
+axial a '#'
+ at end verbatim
+
+ at pfig{axial, Example of Axial()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Grad sample, , Axial sample, 2D samples
+ at subsection Grad sample
+ at nav{}
+
+Command @ref{grad} draw gradient lines for matrix. The sample code is:
+ at verbatim
+call 'prepare2d'
+subplot 1 1 0 '':title 'Grad plot':box
+grad a:dens a '{u8}w{q8}'
+ at end verbatim
+
+ at pfig{grad, Example of Grad()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node 3D samples, Vector field samples, 2D samples, Examples
+ at section 3D samples
+ at nav{}
+
+This section is devoted to visualization of 3D data arrays. 3D means the data which depend on 3 indexes (parameters) like tensor a(i,j,k)=a(x(i),y(j),x(k)), i=1...n, j=1...m, k=1...l or in parametric form @{x(i,j,k),y(i,j,k),z(i,j,k),a(i,j,k)@}. Most of samples will use the same data for plotting. So, I put its initialization in separate function
+ at verbatim
+func 'prepare3d'
+new c 61 50 40 '-2*(x^2+y^2+z^4-z^2)+0.2'
+new d 61 50 40 '1-2*tanh((x+y)*(x+y))'
+return
+ at end verbatim
+Basically, you can put this text after the script. Note, that you need to terminate main script by @ref{stop} command before defining a function.
+
+ at menu
+* Surf3 sample::
+* Surf3C sample::
+* Surf3A sample::
+* Surf3CA sample::
+* Cloud sample::
+* Dens3 sample::
+* Cont3 sample::
+* ContF3 sample::
+* Dens projection sample::
+* Cont projection sample::
+* ContF projection sample::
+* TriPlot and QuadPlot::
+* Dots sample::
+* Fractal sample::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Surf3 sample, Surf3C sample, , 3D samples
+ at subsection Surf3 sample
+ at nav{}
+
+Command @ref{surf3} is one of most suitable (for my opinion) functions to visualize 3D data. It draw the isosurface(s) -- surface(s) of constant amplitude (3D analogue of contour lines). You can draw wired isosurfaces if specify @samp{#} style. The sample code is:
+ at verbatim
+call 'prepare3d'
+light on:alpha on
+subplot 2 2 0:title 'Surf3 plot':rotate 50 60:box
+surf3 c
+
+subplot 2 2 1:title '"\#" style':rotate 50 60:box
+surf3 c '#'
+
+subplot 2 2 2:title '"." style':rotate 50 60:box
+surf3 c '.'
+ at end verbatim
+
+ at pfig{surf3, Example of Surf3()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Surf3C sample, Surf3A sample, Surf3 sample, 3D samples
+ at subsection Surf3C sample
+ at nav{}
+
+Command @ref{surf3c} is similar to @ref{surf3} but its coloring is determined by another data. The sample code is:
+ at verbatim
+call 'prepare3d'
+title 'Surf3C plot':rotate 50 60:light on:alpha on:box
+surf3c c d
+ at end verbatim
+
+ at pfig{surf3c, Example of Surf3C()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Surf3A sample, Surf3CA sample, Surf3C sample, 3D samples
+ at subsection Surf3A sample
+ at nav{}
+
+Command @ref{surf3a} is similar to @ref{surf3} but its transparency is determined by another data. The sample code is:
+ at verbatim
+call 'prepare3d'
+title 'Surf3A plot':rotate 50 60:light on:alpha on:box
+surf3a c d
+ at end verbatim
+
+ at pfig{surf3a, Example of Surf3A()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Surf3CA sample, Cloud sample, Surf3A sample, 3D samples
+ at subsection Surf3CA sample
+ at nav{}
+
+Command @ref{surf3ca} is similar to @ref{surf3} but its color and transparency is determined by another data. The sample code is:
+ at verbatim
+call 'prepare3d'
+title 'Surf3CA plot':rotate 50 60:light on:alpha on:box
+surf3a c d c
+ at end verbatim
+
+ at pfig{surf3ca, Example of Surf3CA()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cloud sample, Dens3 sample, Surf3CA sample, 3D samples
+ at subsection Cloud sample
+ at nav{}
+
+Command @ref{cloud} draw cloud-like object which is less transparent for higher data values. Similar plot can be created using many (about 10-20) @code{Surf3A(a,a)} isosurfaces. The sample code is:
+ at verbatim
+call 'prepare3d'
+subplot 2 2 0:title 'Cloud plot':rotate 50 60:alpha on:box
+cloud c 'wyrRk'
+
+subplot 2 2 1:title '"i" style':rotate 50 60:box
+cloud c 'iwyrRk'
+
+subplot 2 2 2:title '"." style':rotate 50 60:box
+cloud c '.wyrRk'
+
+subplot 2 2 3:title 'meshnum 10':rotate 50 60:box
+cloud c 'wyrRk'; meshnum 10
+ at end verbatim
+
+ at pfig{cloud, Example of Cloud()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Dens3 sample, Cont3 sample, Cloud sample, 3D samples
+ at subsection Dens3 sample
+ at nav{}
+
+Command @ref{dens3} draw just usual density plot but at slices of 3D data. The sample code is:
+ at verbatim
+call 'prepare3d'
+title 'Dens3 sample':rotate 50 60:alpha on:alphadef 0.7
+origin 0 0 0:box:axis '_xyz'
+dens3 c 'x':dens3 c ':y':dens3 c 'z'
+ at end verbatim
+
+ at pfig{densa, Example of Dens3()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cont3 sample, ContF3 sample, Dens3 sample, 3D samples
+ at subsection Cont3 sample
+ at nav{}
+
+Command @ref{cont3} draw just usual contour lines but at slices of 3D data. The sample code is:
+ at verbatim
+call 'prepare3d'
+title 'Cont3 sample':rotate 50 60:box
+cont3 c 'x':cont3 c:cont3 c 'z'
+ at end verbatim
+
+ at pfig{conta, Example of Cont3()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ContF3 sample, Dens projection sample, Cont3 sample, 3D samples
+ at subsection ContF3 sample
+ at nav{}
+
+Command @ref{contf3} draw just usual filled contours but at slices of 3D data. The sample code is:
+ at verbatim
+call 'prepare3d'
+title 'Cont3 sample':rotate 50 60:box:light on
+contf3 c 'x':contf3 c:contf3 c 'z'
+cont3 c 'xk':cont3 c 'k':cont3 c 'zk'
+ at end verbatim
+
+ at pfig{contfa, Example of ContF3()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Dens projection sample, Cont projection sample, ContF3 sample, 3D samples
+ at subsection Dens projection sample
+ at nav{}
+
+Functions @ref{densz}, @ref{densy}, @ref{densx} draw density plot on plane perpendicular to corresponding axis. One of possible application is drawing projections of 3D field. The sample code is:
+ at verbatim
+call 'prepare3d'
+title 'Dens[XYZ] sample':rotate 50 60:box
+densx {sum c 'x'} '' -1
+densy {sum c 'y'} '' 1
+densz {sum c 'z'} '' -1
+ at end verbatim
+
+ at pfig{dens_xyz, Example of DensX() DensY() DensZ()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cont projection sample, ContF projection sample, Dens projection sample, 3D samples
+ at subsection Cont projection sample
+ at nav{}
+
+Functions @ref{contz}, @ref{conty}, @ref{contx} draw contour lines on plane perpendicular to corresponding axis. One of possible application is drawing projections of 3D field. The sample code is:
+ at verbatim
+call 'prepare3d'
+title 'Cont[XYZ] sample':rotate 50 60:box
+contx {sum c 'x'} '' -1
+conty {sum c 'y'} '' 1
+contz {sum c 'z'} '' -1
+ at end verbatim
+
+ at pfig{cont_xyz, Example of ContX() ContY() ContZ()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ContF projection sample, TriPlot and QuadPlot, Cont projection sample, 3D samples
+ at subsection ContF projection sample
+ at nav{}
+
+Functions @ref{contfz}, @ref{contfy}, @ref{contfx} draw filled contours on plane perpendicular to corresponding axis. One of possible application is drawing projections of 3D field. The sample code is:
+ at verbatim
+call 'prepare3d'
+title 'ContF[XYZ] sample':rotate 50 60:box
+contfx {sum c 'x'} '' -1
+contfy {sum c 'y'} '' 1
+contfz {sum c 'z'} '' -1
+ at end verbatim
+
+ at pfig{contf_xyz, Example of ContFX() ContFY() ContFZ()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node TriPlot and QuadPlot, Dots sample, ContF projection sample, 3D samples
+ at subsection TriPlot and QuadPlot
+ at nav{}
+
+Command @ref{triplot} and @ref{quadplot} draw set of triangles (or quadrangles for @code{QuadPlot}) for irregular data arrays. Note, that you have to provide not only vertexes, but also the indexes of triangles or quadrangles. I.e. perform triangulation by some other library. The sample code is:
+ at verbatim
+list q 0 1 2 3 | 4 5 6 7 | 0 2 4 6 | 1 3 5 7 | 0 4 1 5 | 2 6 3 7
+list xq -1 1 -1 1 -1 1 -1 1
+list yq -1 -1 1 1 -1 -1 1 1
+list zq -1 -1 -1 -1 1 1 1 1
+light on
+subplot 2 2 0:title 'QuadPlot sample':rotate 50 60
+quadplot q xq yq zq 'yr'
+quadplot q xq yq zq '#k'
+
+subplot 2 2 2:title 'QuadPlot coloring':rotate 50 60
+quadplot q xq yq zq yq 'yr'
+quadplot q xq yq zq '#k'
+
+list t 0 1 2 | 0 1 3 | 0 2 3 | 1 2 3
+list xt -1 1 0 0
+list yt -1 -1 1 0
+list zt -1 -1 -1 1
+subplot 2 2 1:title 'TriPlot sample':rotate 50 60
+triplot t xt yt zt 'b'
+triplot t xt yt zt '#k'
+
+subplot 2 2 3:title 'TriPlot coloring':rotate 50 60
+triplot t xt yt zt yt 'cb'
+triplot t xt yt zt '#k'
+tricont t xt yt zt 'B'
+ at end verbatim
+
+ at pfig{triplot, Example of TriPlot() and QuadPlot()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Dots sample, Fractal sample, TriPlot and QuadPlot, 3D samples
+ at subsection Dots sample
+ at nav{}
+
+Command @ref{dots} is another way to draw irregular points. @code{Dots} use color scheme for coloring (see @ref{Color scheme}). The sample code is:
+ at verbatim
+new t 2000 'pi*(rnd-0.5)':new f 2000 '2*pi*rnd'
+copy x 0.9*cos(t)*cos(f):copy y 0.9*cos(t)*sin(f):copy z 0.6*sin(t):copy c cos(2*t)
+subplot 2 2 0:title 'Dots sample':rotate 50 60
+box:dots x y z
+alpha on
+subplot 2 2 1:title 'add transparency':rotate 50 60
+box:dots x y z c
+subplot 2 2 2:title 'add colorings':rotate 50 60
+box:dots x y z x c
+subplot 2 2 3:title 'Only coloring':rotate 50 60
+box:tens x y z x ' .'
+ at end verbatim
+
+ at pfig{dots, Example of Dots()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Fractal sample, , Dots sample, 3D samples
+ at subsection Fractal sample
+ at nav{}
+
+Commands @ref{ifs2d} and @ref{ifs3d} generate points for fractals using iterated function system in 2d and 3d cases correspondingly. The sample codes are:
+ at verbatim
+list A [0.33,0,0,0.33,0,0,0.2] [0.33,0,0,0.33,0.67,0,0.2] [0.33,0,0,0.33,0.33,0.33,0.2]\
+       [0.33,0,0,0.33,0,0.67,0.2] [0.33,0,0,0.33,0.67,0.67,0.2]
+ifs2d fx fy A 100000
+subplot 1 1 0 '<_':title 'IFS 2d sample'
+ranges fx fy:axis
+plot fx fy 'r#o ';size 0.05
+ at end verbatim
+
+ at pfig{ifs2d, Example of IFS fractal (2d case).}
+
+ at verbatim
+list A [0,0,0,0,.18,0,0,0,0,0,0,0,.01] [.85,0,0,0,.85,.1,0,-0.1,0.85,0,1.6,0,.85]\
+        [.2,-.2,0,.2,.2,0,0,0,0.3,0,0.8,0,.07] [-.2,.2,0,.2,.2,0,0,0,0.3,0,0.8,0,.07]
+ifs3d f A 100000
+title 'IFS 3d sample':rotate 50 60
+ranges f(0) f(1) f(2):axis:box
+dots f(0) f(1) f(2) 'G#o';size 0.05
+ at end verbatim
+
+ at pfig{ifs3d, Example of IFS fractal (3d case).}
+
+
+Command @ref{flame2d} generate points for flame fractals in 2d case. The sample codes are:
+ at verbatim
+list A [0.33,0,0,0.33,0,0,0.2] [0.33,0,0,0.33,0.67,0,0.2] [0.33,0,0,0.33,0.33,0.33,0.2]\
+        [0.33,0,0,0.33,0,0.67,0.2] [0.33,0,0,0.33,0.67,0.67,0.2]
+new B 2 3 A.ny '0.3'
+put B 3 0 0 -1
+put B 3 0 1 -1
+put B 3 0 2 -1
+flame2d fx fy A B 1000000
+subplot 1 1 0 '<_':title 'Flame2d sample'
+ranges fx fy:box:axis
+plot fx fy 'r#o ';size 0.05
+ at end verbatim
+
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Vector field samples, Hints, 3D samples, Examples
+ at section Vector field samples
+ at nav{}
+
+Vector field visualization (especially in 3d case) is more or less complex task. MathGL provides 3 general types of plots: vector field itself (@code{Vect}), flow threads (@code{Flow}), and flow pipes with radius proportional to field amplitude (@code{Pipe}).
+
+However, the plot may look tangly -- there are too many overlapping lines. I may suggest 2 ways to solve this problem. The first one is to change @code{SetMeshNum} for decreasing the number of hachures. The second way is to use the flow thread chart @code{Flow}, or possible many flow thread from manual position (@code{FlowP}). Unfortunately, I don't know any other methods to visualize 3d vector field. If you know any, e-mail me and I shall add it to MathGL.
+
+Most of samples will use the same data for plotting. So, I put its initialization in separate function
+ at verbatim
+func 'prepare2v'
+new a 20 30 '0.6*sin(pi*(x+1))*sin(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'
+new b 20 30 '0.6*cos(pi*(x+1))*cos(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'
+return
+
+func 'prepare3v'
+define $1 pow(x*x+y*y+(z-0.3)*(z-0.3)+0.03,1.5)
+define $2 pow(x*x+y*y+(z+0.3)*(z+0.3)+0.03,1.5)
+new ex 10 10 10 '0.2*x/$1-0.2*x/$2'
+new ey 10 10 10 '0.2*y/$1-0.2*y/$2'
+new ez 10 10 10 '0.2*(z-0.3)/$1-0.2*(z+0.3)/$2'
+return
+ at end verbatim
+Basically, you can put this text after the script. Note, that you need to terminate main script by @ref{stop} command before defining a function.
+
+ at menu
+* Vect sample::
+* Vect3 sample::
+* Traj sample::
+* Flow sample::
+* Pipe sample::
+* Dew sample::
+ at end menu
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Vect sample, Vect3 sample, , Vector field samples
+ at subsection Vect sample
+ at nav{}
+
+Command @ref{vect} is most standard way to visualize vector fields -- it draw a lot of arrows or hachures for each data cell. It have a lot of options which can be seen on the figure (and in the sample code). @code{Vect} use color scheme for coloring (see @ref{Color scheme}). The sample code is:
+ at verbatim
+call 'prepare2v'
+subplot 3 2 0 '':title 'Vect plot (default)':box
+vect a b
+
+subplot 3 2 1 '':title '"." style; "=" style':box
+vect a b '.='
+
+subplot 3 2 2 '':title '"f" style':box
+vect a b 'f'
+
+subplot 3 2 3 '':title '">" style':box
+vect a b '>'
+
+subplot 3 2 4 '':title '"<" style':box
+vect a b '<'
+
+call 'prepare3v'
+subplot 3 2 5:title '3d variant':rotate 50 60:box
+vect ex ey ez
+ at end verbatim
+
+ at pfig{vect, Example of Vect()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Vect3 sample, Traj sample, Vect sample, Vector field samples
+ at subsection Vect3 sample
+ at nav{}
+
+Command @ref{vect3} draw just usual vector field plot but at slices of 3D data. The sample code is:
+ at verbatim
+origin 0 0 0:call 'prepare3v'
+subplot 2 1 0:title 'Vect3 sample':rotate 50 60
+box:axis '_xyz'
+vect3 ex ey ez 'x':vect3 ex ey ez:vect3 ex ey ez 'z'
+
+subplot 2 1 1:title '"f" style':rotate 50 60
+box:axis '_xyz'
+vect3 ex ey ez 'fx':vect3 ex ey ez 'f':vect3 ex ey ez 'fz'
+grid3 ex 'Wx':grid3 ex 'W':grid3 ex 'Wz'
+ at end verbatim
+
+ at pfig{vecta, Example of Vect3()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Traj sample, Flow sample, Vect3 sample, Vector field samples
+ at subsection Traj sample
+ at nav{}
+
+Command @ref{traj} is 1D analogue of @code{Vect}. It draw vectors from specified points. The sample code is:
+ at verbatim
+call 'prepare1d'
+subplot 1 1 0 '':title 'Traj plot':box
+plot x1 y:traj x1 y y1 y2
+ at end verbatim
+
+ at pfig{traj, Example of Traj()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Flow sample, Pipe sample, Traj sample, Vector field samples
+ at subsection Flow sample
+ at nav{}
+
+Command @ref{flow} is another standard way to visualize vector fields -- it draw lines (threads) which is tangent to local vector field direction. MathGL draw threads from edges of bounding box and from central slices. Sometimes it is not most appropriate variant -- you may want to use @code{FlowP} to specify manual position of threads. @code{Flow} use color scheme for coloring (see @ref{Color scheme}). At this warm color corresponds to normal flow (like attractor), cold one corresponds  [...]
+ at verbatim
+call 'prepare2v'
+subplot 2 2 0 '':title 'Flow plot (default)':box
+flow a b
+
+subplot 2 2 1 '':title '"v" style':box
+flow a b 'v'
+
+subplot 2 2 2 '':title 'from edges only':box
+flow a b '#'
+
+call 'prepare3v'
+subplot 2 2 3:title '3d variant':rotate 50 60:box
+flow ex ey ez
+ at end verbatim
+
+ at pfig{flow, Example of Flow()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Pipe sample, Dew sample, Flow sample, Vector field samples
+ at subsection Pipe sample
+ at nav{}
+
+Command @ref{pipe} is similar to @ref{flow} but draw pipes (tubes) which radius is proportional to the amplitude of vector field. @code{Pipe} use color scheme for coloring (see @ref{Color scheme}). At this warm color corresponds to normal flow (like attractor), cold one corresponds to inverse flow (like source). The sample code is:
+ at verbatim
+call 'prepare2v'
+subplot 2 2 0 '':title 'Pipe plot (default)':light on:box
+pipe a b
+
+subplot 2 2 1 '':title '"i" style':box
+pipe a b 'i'
+
+subplot 2 2 2 '':title 'from edges only':box
+pipe a b '#'
+
+call 'prepare3v'
+subplot 2 2 3:title '3d variant':rotate 50 60:box
+pipe ex ey ez '' 0.1
+ at end verbatim
+
+ at pfig{pipe, Example of Pipe()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Dew sample, , Pipe sample, Vector field samples
+ at subsection Dew sample
+ at nav{}
+
+Command @ref{dew} is similar to @code{Vect} but use drops instead of arrows. The sample code is:
+ at verbatim
+call 'prepare2v'
+subplot 1 1 0 '':title 'Dew plot':light on:box
+dew a b
+ at end verbatim
+
+ at pfig{dew, Example of Dew()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Hints, FAQ, Vector field samples, Examples
+ at section Hints
+ at nav{}
+
+In this section I've included some small hints and advices for the improving of the quality of plots and for the demonstration of some non-trivial features of MathGL library. In contrast to previous examples I showed mostly the idea but not the whole drawing function.
+
+ at menu
+* ``Compound'' graphics::
+* Transparency and lighting::
+* Types of transparency::
+* Axis projection::
+* Adding fog::
+* Lighting sample::
+* Using primitives::
+* STFA sample::
+* Mapping visualization::
+* Data interpolation::
+* Making regular data::
+* Making histogram::
+* Nonlinear fitting hints::
+* PDE solving hints::
+* Drawing phase plain::
+* Pulse properties::
+* Using MGL parser::
+* Using options::
+* ``Templates''::
+* Stereo image::
+* Reduce memory usage::
+* Saving and scanning file::
+* Mixing bitmap and vector output::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ``Compound'' graphics, Transparency and lighting, , Hints
+ at subsection ``Compound'' graphics
+ at nav{}
+
+As I noted above, MathGL functions (except the special one, like Clf()) do  not erase the previous plotting but just add the new one. It allows one to draw ``compound'' plots easily. For example, popular Matlab command @code{surfc} can be emulated in MathGL by 2 calls:
+ at verbatim
+  Surf(a);
+  Cont(a, "_");     // draw contours at bottom
+ at end verbatim
+Here @var{a} is 2-dimensional data for the plotting, @code{-1} is the value of z-coordinate at which the contour should be plotted (at the bottom in this example). Analogously, one can draw density plot instead of contour lines and so on.
+
+Another nice plot is contour lines plotted directly on the surface:
+ at verbatim
+  Light(true);       // switch on light for the surface
+  Surf(a, "BbcyrR"); // select 'jet' colormap for the surface
+  Cont(a, "y");      // and yellow color for contours
+ at end verbatim
+The possible difficulties arise in black&white case, when the color of the surface can be close to the color of a contour line. In that case I may suggest the following code:
+ at verbatim
+  Light(true);   // switch on light for the surface
+  Surf(a, "kw"); // select 'gray' colormap for the surface
+  CAxis(-1,0);   // first draw for darker surface colors
+  Cont(a, "w");  // white contours
+  CAxis(0,1);    // now draw for brighter surface colors
+  Cont(a, "k");  // black contours
+  CAxis(-1,1);   // return color range to original state
+ at end verbatim
+The idea is to divide the color range on 2 parts (dark and bright) and to select the contrasting color for contour lines for each of part.
+
+Similarly, one can plot flow thread over density plot of vector field amplitude (this is another amusing plot from Matlab) and so on. The list of compound graphics can be prolonged but I hope that the general idea is clear.
+
+Just for illustration I put here following sample code:
+ at verbatim
+call 'prepare2v'
+call 'prepare3d'
+new v 10:fill v -0.5 1:copy d sqrt(a^2+b^2)
+subplot 2 2 0:title 'Surf + Cont':rotate 50 60:light on:box
+surf a:cont a 'y'
+
+subplot 2 2 1 '':title 'Flow + Dens':light off:box
+flow a b 'br':dens d
+
+subplot 2 2 2:title 'Mesh + Cont':rotate 50 60:box
+mesh a:cont a '_'
+
+subplot 2 2 3:title 'Surf3 + ContF3':rotate 50 60:light on
+box:contf3 v c 'z' 0:contf3 v c 'x':contf3 v c
+cut 0 -1 -1 1 0 1.1
+contf3 v c 'z' c.nz-1:surf3 c -0.5
+ at end verbatim
+
+ at pfig{combined, Example of ``combined'' plots}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Transparency and lighting, Types of transparency, ``Compound'' graphics, Hints
+ at subsection Transparency and lighting
+ at nav{}
+
+Here I want to show how transparency and lighting both and separately change the look of a surface. So, there is code and picture for that:
+ at verbatim
+call 'prepare2d'
+subplot 2 2 0:title 'default':rotate 50 60:box
+surf a
+
+subplot 2 2 1:title 'light on':rotate 50 60:box
+light on:surf a
+
+subplot 2 2 3:title 'light on; alpha on':rotate 50 60:box
+alpha on:surf a
+
+subplot 2 2 2:title 'alpha on':rotate 50 60:box
+light off:surf a
+ at end verbatim
+
+ at pfig{alpha, Example of transparency and lightings}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Types of transparency, Axis projection, Transparency and lighting, Hints
+ at subsection Types of transparency
+ at nav{}
+
+MathGL library has advanced features for setting and handling the surface transparency. The simplest way to add transparency is the using of command @ref{alpha}. As a result, all further surfaces (and isosurfaces, density plots and so on) become transparent. However, their  look can be additionally improved.
+
+The value of transparency can be different from surface to surface. To do it just use @code{SetAlphaDef} before the drawing of the surface, or use option @code{alpha} (see @ref{Command options}). If its value is close to 0 then the surface becomes more and more transparent. Contrary, if its value is close to 1 then the surface becomes practically non-transparent.
+
+Also you can change the way how the light goes through overlapped surfaces. The function @code{SetTranspType} defines it. By default the usual transparency is used (@samp{0}) -- surfaces below is less visible than the upper ones. A ``glass-like'' transparency (@samp{1}) has a different look -- each surface just decreases the background light (the surfaces are commutable in this case).
+
+A ``neon-like'' transparency (@samp{2}) has more interesting look. In this case a surface is the light source (like a lamp on the dark background) and just adds some intensity to the color. At this, the library sets automatically the black color for the background and changes the default line color to white.
+
+As example I shall show several plots for different types of transparency. The code is the same except the values of @code{SetTranspType} function:
+ at verbatim
+call 'prepare2d'
+alpha on:light on
+transptype 0:clf
+subplot 2 2 0:rotate 50 60:surf a:box
+subplot 2 2 1:rotate 50 60:dens a:box
+subplot 2 2 2:rotate 50 60:cont a:box
+subplot 2 2 3:rotate 50 60:axial a:box
+ at end verbatim
+
+ at pfig{type0, Example of @code{SetTranspType(0)}.}
+ at pfig{type1, Example of @code{SetTranspType(1)}.}
+ at pfig{type2, Example of @code{SetTranspType(2)}.}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Axis projection, Adding fog, Ternary axis, Hints
+ at subsection Axis projection
+ at nav{}
+
+You can easily make 3D plot and draw its x-,y-,z-projections (like in CAD) by using @ref{ternary} function with arguments: 4 for Cartesian, 5 for Ternary and 6 for Quaternary coordinates. The sample code is:
+ at verbatim
+ranges 0 1 0 1 0 1
+new x 50 '0.25*(1+cos(2*pi*x))'
+new y 50 '0.25*(1+sin(2*pi*x))'
+new z 50 'x'
+new a 20 30 '30*x*y*(1-x-y)^2*(x+y<1)'
+new rx 10 'rnd':new ry 10:fill ry '(1-v)*rnd' rx
+light on
+
+title 'Projection sample':ternary 4:rotate 50 60
+box:axis:grid
+plot x y z 'r2':surf a '#'
+xlabel 'X':ylabel 'Y':zlabel 'Z'
+ at end verbatim
+
+ at pfig{projection, Example of axis projections}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Adding fog, Lighting sample, Axis projection, Hints
+ at subsection Adding fog
+ at nav{}
+
+MathGL can add a fog to the image. Its switching on is rather simple -- just use @ref{fog} function. There is the only feature -- fog is applied for whole image. Not to particular subplot. The sample code is:
+ at verbatim
+call 'prepare2d'
+title 'Fog sample':rotate 50 60:light on
+fog 1
+box:surf a:cont a 'y'
+ at end verbatim
+
+ at pfig{fog, Example of @code{Fog()}.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Lighting sample, Using primitives, Adding fog, Hints
+ at subsection Lighting sample
+ at nav{}
+
+In contrast to the most of other programs, MathGL supports several (up to 10) light sources. Moreover, the color each of them can be different: white (this is usual), yellow, red, cyan, green and so on. The use of several light sources may be interesting for the highlighting of some peculiarities of the plot or just to make an amusing picture. Note, each light source can be switched on/off individually. The sample code is:
+ at verbatim
+call 'prepare2d'
+title 'Several light sources':rotate 50 60:light on
+light 1 0 1 0 'c':light 2 1 0 0 'y':light 3 0 -1 0 'm'
+box:surf a 'h'
+ at end verbatim
+
+ at pfig{several_light, Example of several light sources.}
+
+Additionally, you can use local light sources and set to use @ref{diffuse} reflection instead of specular one (by default) or both kinds. Note, I use @ref{attachlight} command to keep light settings relative to subplot.
+ at verbatim
+light on: attachlight on
+call 'prepare2d'
+subplot 2 2 0:title 'Default':rotate 50 60:box:surf a
+line -1 -0.7 1.7 -1 -0.7 0.7 'BA'
+
+subplot 2 2 1:title 'Local':rotate 50 60
+light 0 1 0 1 -2 -1 -1
+line 1 0 1 -1 -1 0 'BAO':box:surf a
+
+subplot 2 2 2:title 'no diffuse':rotate 50 60
+diffuse 0
+line 1 0 1 -1 -1 0 'BAO':box:surf a
+
+subplot 2 2 3:title 'diffusive only':rotate 50 60
+diffuse 0.5:light 0 1 0 1 -2 -1 -1 'w' 0
+line 1 0 1 -1 -1 0 'BAO':box:surf a
+ at end verbatim
+
+ at pfig{light, Example of different types of lighting.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Using primitives, STFA sample, Lighting sample, Hints
+ at subsection Using primitives
+ at nav{}
+
+MathGL provide a set of functions for drawing primitives (see @ref{Primitives}). Primitives are low level object, which used by most of plotting functions. Picture below demonstrate some of commonly used primitives.
+ at verbatim
+subplot 2 2 0 '':title 'Line, Curve, Rhomb, Ellipse' '' -1.5
+line -1 -1 -0.5 1 'qAI'
+curve -0.6 -1 1 1 0 1 1 1 'rA'
+ball 0 -0.5 '*':ball 1 -0.1 '*'
+rhomb 0 0.4 1 0.9 0.2 'b#'
+rhomb 0 0 1 0.4 0.2 'cg@'
+ellipse 0 -0.5 1 -0.1 0.2 'u#'
+ellipse 0 -1 1 -0.6 0.2 'm@'
+
+light on
+subplot 2 2 1:title 'Face[xyz]':rotate 50 60:box
+facex 1 0 -1 1 1 'r':facey -1 -1 -1 1 1 'g':facez 1 -1 -1 -1 1 'b'
+face -1 -1 1 -1 1 1 1 -1 0 1 1 1 'bmgr'
+
+subplot 2 2 3 '':title 'Cone'
+cone -0.7 -0.3 0 -0.7 0.7 0.5 0.2 0.1 'b':text -0.7 -0.7 'no edges\n(default)'
+cone 0 -0.3 0 0 0.7 0.5 0.2 0.1 'g@':text 0 -0.7 'with edges\n('\@' style)'
+cone 0.7 -0.3 0 0.7 0.7 0.5 0.2 0.1 'ry':text 0.7 -0.7 '"arrow" with\n{}gradient'
+
+subplot 2 2 2 '':title 'Sphere and Drop'
+line -0.9 0 1 0.9 0 1
+text -0.9 -0.7 'sh=0':drop -0.9 0 0 1 0.5 'r' 0:ball -0.9 0 1 'k'
+text -0.3 -0.7 'sh=0.33':drop -0.3 0 0 1 0.5 'r' 0.33:ball -0.3 0 1 'k'
+text 0.3 -0.7 'sh=0.67':drop 0.3 0 0 1 0.5 'r' 0.67:ball 0.3 0 1 'k'
+text 0.9 -0.7 'sh=1':drop 0.9 0 0 1 0.5 'r' 1:ball 0.9 0 1 'k'
+ at end verbatim
+
+ at pfig{primitives, Primitives in MathGL.}
+
+Generally, you can create arbitrary new kind of plot using primitives. For example, MathGL don't provide any special functions for drawing molecules. However, you can do it using only one type of primitives @ref{drop}. The sample code is:
+ at verbatim
+alpha on:light on
+subplot 2 2 0 '':title 'Methane, CH_4':rotate 60 120
+sphere 0 0 0 0.25 'k':drop 0 0 0 0 0 1 0.35 'h' 1 2:sphere 0 0 0.7 0.25 'g'
+drop 0 0 0 -0.94 0 -0.33 0.35 'h' 1 2:sphere -0.66 0 -0.23 0.25 'g'
+drop 0 0 0 0.47 0.82 -0.33 0.35 'h' 1 2:sphere 0.33 0.57 -0.23 0.25 'g'
+drop 0 0 0 0.47 -0.82 -0.33 0.35 'h' 1 2:sphere 0.33 -0.57 -0.23 0.25 'g'
+
+subplot 2 2 1 '':title 'Water, H{_2}O':rotate 60 100
+sphere 0 0 0 0.25 'r':drop 0 0 0 0.3 0.5 0 0.3 'm' 1 2:sphere 0.3 0.5 0 0.25 'g'
+drop 0 0 0 0.3 -0.5 0 0.3 'm' 1 2:sphere 0.3 -0.5 0 0.25 'g'
+
+subplot 2 2 2 '':title 'Oxygen, O_2':rotate 60 120
+drop 0 0.5 0 0 -0.3 0 0.3 'm' 1 2:sphere 0 0.5 0 0.25 'r'
+drop 0 -0.5 0 0 0.3 0 0.3 'm' 1 2:sphere 0 -0.5 0 0.25 'r'
+
+subplot 2 2 3 '':title 'Ammonia, NH_3':rotate 60 120
+sphere 0 0 0 0.25 'b':drop 0 0 0 0.33 0.57 0 0.32 'n' 1 2
+sphere 0.33 0.57 0 0.25 'g':drop 0 0 0 0.33 -0.57 0 0.32 'n' 1 2
+sphere 0.33 -0.57 0 0.25 'g':drop 0 0 0 -0.65 0 0 0.32 'n' 1 2
+sphere -0.65 0 0 0.25 'g'
+ at end verbatim
+
+ at pfig{molecule, Example of molecules drawing.}
+
+Moreover, some of special plots can be more easily produced by primitives rather than by specialized function. For example, Venn diagram can be produced by @code{Error} plot:
+ at verbatim
+list x -0.3 0 0.3:list y 0.3 -0.3 0.3:list e 0.7 0.7 0.7
+title 'Venn-like diagram':alpha on
+error x y e e '!rgb@#o'
+ at end verbatim
+You see that you have to specify and fill 3 data arrays. The same picture can be produced by just 3 calls of @ref{circle} function:
+ at verbatim
+title 'Venn-like diagram':alpha on
+circle -0.3 0.3 0.7 'rr@'
+circle 0 -0.3 0.7 'gg@'
+circle 0.3 0.3 0.7 'bb@'
+ at end verbatim
+Of course, the first variant is more suitable if you need to plot a lot of circles. But for few ones the usage of primitives looks easy.
+
+ at pfig{venn, Example of Venn diagram.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node STFA sample, Mapping visualization, Using primitives, Hints
+ at subsection STFA sample
+ at nav{}
+
+Short-time Fourier Analysis (@ref{stfa}) is one of informative method for analyzing long rapidly oscillating 1D data arrays. It is used to determine the sinusoidal frequency and phase content of local sections of a signal as it changes over time.
+
+MathGL can find and draw STFA result. Just to show this feature I give following sample. Initial data arrays is 1D arrays with step-like frequency. Exactly this you can see at bottom on the STFA plot. The sample code is:
+ at verbatim
+new a 2000:new b 2000
+fill a 'cos(50*pi*x)*(x<-.5)+cos(100*pi*x)*(x<0)*(x>-.5)+\
+cos(200*pi*x)*(x<.5)*(x>0)+cos(400*pi*x)*(x>.5)'
+
+subplot 1 2 0 '<_':title 'Initial signal'
+plot a:axis:xlabel '\i t'
+
+subplot 1 2 1 '<_':title 'STFA plot'
+stfa a b 64:axis:ylabel '\omega' 0:xlabel '\i t'
+ at end verbatim
+
+ at pfig{stfa, Example of STFA().}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Mapping visualization, Data interpolation, STFA sample, Hints
+ at subsection Mapping visualization
+ at nav{}
+
+Sometime ago I worked with mapping and have a question about its visualization. Let me remember you that mapping is some transformation rule for one set of number to another one. The 1d mapping is just an ordinary function -- it takes a number and transforms it to another one. The 2d mapping (which I used) is a pair of functions which take 2 numbers and transform them to another 2 ones. Except general plots (like @ref{surfc}, @ref{surfa}) there is a special plot -- Arnold diagram. It sho [...]
+
+I tried to make such plot in @ref{map}. It shows the set of points or set of faces, which final position is the result of mapping. At this, the color gives information about their initial position and the height describes Jacobian value of the transformation. Unfortunately, it looks good only for the simplest mapping but for the  real multivalent quasi-chaotic mapping it produces a confusion. So, use it if you like :).
+
+The sample code for mapping visualization is:
+ at verbatim
+new a 50 40 'x':new b 50 40 'y':zrange -2 2:text 0 0 '\to'
+subplot 2 1 0:text 0 1.1 '\{x, y\}' '' -2:box
+map a b 'brgk'
+
+subplot 2 1 1:box
+text 0 1.1 '\{\frac{x^3+y^3}{2}, \frac{x-y}{2}\}' '' -2
+fill a '(x^3+y^3)/2':fill b '(x-y)/2':map a b 'brgk'
+ at end verbatim
+
+ at pfig{map, Example of Map().}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Data interpolation, Making regular data, Mapping visualization, Hints
+ at subsection Data interpolation
+ at nav{}
+
+There are many functions to get interpolated values of a data array. Basically all of them can be divided by 3 categories:
+ at enumerate
+ at item functions which return single value at given point (see @ref{Interpolation} and @code{mglGSpline()} in @ref{Global functions});
+ at item functions @ref{subdata} and @ref{evaluate} for indirect access to data elements;
+ at item functions @ref{refill}, @ref{gspline} and @ref{datagrid} which fill regular (rectangular) data array by interpolated values.
+ at end enumerate
+
+The usage of first category is rather straightforward and don't need any special comments.
+
+There is difference in indirect access functions. Function @ref{subdata} use use step-like interpolation to handle correctly single @code{nan} values in the data array. Contrary, function @ref{evaluate} use local spline interpolation, which give smoother output but spread @code{nan} values. So, @ref{subdata} should be used for specific data elements (for example, for given column), and @ref{evaluate} should be used for distributed elements (i.e. consider data array as some field). Follow [...]
+ at verbatim
+subplot 1 1 0 '':title 'SubData vs Evaluate'
+new in 9 'x^3/1.1':plot in 'ko ':box
+new arg 99 '4*x+4'
+evaluate e in arg off:plot e 'b.'; legend 'Evaluate'
+subdata s in arg:plot s 'r.';legend 'SubData'
+legend 2
+ at end verbatim
+
+ at pfig{indirect, Example of indirect data access.}
+
+Example of @ref{datagrid} usage is done in @ref{Making regular data}. Here I want to show the peculiarities of @ref{refill} and @ref{gspline} functions. Both functions require argument(s) which provide coordinates of the data values, and return rectangular data array which equidistantly distributed in axis range. So, in opposite to @ref{evaluate} function, @ref{refill} and @ref{gspline} can interpolate non-equidistantly distributed data. At this both functions @ref{refill} and @ref{gspli [...]
+ at verbatim
+new x 10 '0.5+rnd':cumsum x 'x':norm x -1 1
+copy y sin(pi*x)/1.5
+subplot 2 2 0 '<_':title 'Refill sample'
+box:axis:plot x y 'o ':fplot 'sin(pi*x)/1.5' 'B:'
+new r 100:refill r x y:plot r 'r'
+
+subplot 2 2 1 '<_':title 'Global spline'
+box:axis:plot x y 'o ':fplot 'sin(pi*x)/1.5' 'B:'
+new r 100:gspline r x y:plot r 'r'
+
+new y 10 '0.5+rnd':cumsum y 'x':norm y -1 1
+copy xx x:extend xx 10
+copy yy y:extend yy 10:transpose yy
+copy z sin(pi*xx*yy)/1.5
+alpha on:light on
+subplot 2 2 2:title '2d regular':rotate 40 60
+box:axis:mesh xx yy z 'k'
+new rr 100 100:refill rr x y z:surf rr
+
+new xx 10 10 '(x+1)/2*cos(y*pi/2-1)'
+new yy 10 10 '(x+1)/2*sin(y*pi/2-1)'
+copy z sin(pi*xx*yy)/1.5
+subplot 2 2 3:title '2d non-regular':rotate 40 60
+box:axis:plot xx yy z 'ko '
+new rr 100 100:refill rr xx yy z:surf rr
+ at end verbatim
+
+ at pfig{refill, Example of non-equidistant data interpolation.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Making regular data, Making histogram, Data interpolation, Hints
+ at subsection Making regular data
+ at nav{}
+
+Sometimes, one have only unregular data, like as data on triangular grids, or experimental results and so on. Such kind of data cannot be used as simple as regular data (like matrices). Only few functions, like @ref{dots}, can handle unregular data as is.
+
+However, one can use built in triangulation functions for interpolating unregular data points to a regular data grids. There are 2 ways. First way, one can use @ref{triangulation} function to obtain list of vertexes for triangles. Later this list can be used in functions like @ref{triplot} or @ref{tricont}. Second way consist in usage of @ref{datagrid} function, which fill regular data grid by interpolated values, assuming that coordinates of the data grid is equidistantly distributed in [...]
+ at verbatim
+new x 100 '2*rnd-1':new y 100 '2*rnd-1':copy z x^2-y^2
+# first way - plot triangular surface for points
+triangulate d x y
+title 'Triangulation'
+rotate 50 60:box:light on
+triplot d x y z:triplot d x y z '#k'
+# second way - make regular data and plot it
+new g 30 30:datagrid g x y z:mesh g 'm'
+ at end verbatim
+
+ at pfig{triangulation, Example of triangulation.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Making histogram, Nonlinear fitting hints, Making regular data, Hints
+ at subsection Making histogram
+ at nav{}
+
+Using the @ref{hist} function(s) for making regular distributions is one of useful fast methods to process and plot irregular data. @code{Hist} can be used to find some momentum of set of points by specifying weight function. It is possible to create not only 1D distributions but also 2D and 3D ones. Below I place the simplest sample code which demonstrate @ref{hist} usage:
+ at verbatim
+new x 10000 '2*rnd-1':new y 10000 '2*rnd-1':copy z exp(-6*(x^2+y^2))
+hist xx x z:norm xx 0 1:hist yy y z:norm yy 0 1
+multiplot 3 3 3 2 2 '':ranges -1 1 -1 1 0 1:box:dots x y z 'wyrRk'
+multiplot 3 3 0 2 1 '':ranges -1 1 0 1:box:bars xx
+multiplot 3 3 5 1 2 '':ranges 0 1 -1 1:box:barh yy
+subplot 3 3 2:text 0.5 0.5 'Hist and\n{}MultiPlot\n{}sample' 'a' -3
+ at end verbatim
+
+ at pfig{hist, Example of Hist().}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Nonlinear fitting hints, PDE solving hints, Making histogram, Hints
+ at subsection Nonlinear fitting hints
+ at nav{}
+
+Nonlinear fitting is rather simple. All that you need is the data to fit, the approximation formula and the list of coefficients to fit (better with its initial guess values). Let me demonstrate it on the following simple example. First, let us use sin function with some random noise:
+ at verbatim
+new dat 100 '0.4*rnd+0.1+sin(2*pi*x)'
+new in 100 '0.3+sin(2*pi*x)'
+ at end verbatim
+and plot it to see that data we will fit
+ at verbatim
+title 'Fitting sample':yrange -2 2:box:axis:plot dat 'k. '
+ at end verbatim
+
+The next step is the fitting itself. For that let me specify an initial values @var{ini} for coefficients @samp{abc} and do the fitting for approximation formula @samp{a+b*sin(c*x)}
+ at verbatim
+list ini 1 1 3:fit res dat 'a+b*sin(c*x)' 'abc' ini
+ at end verbatim
+Now display it
+ at verbatim
+plot res 'r':plot in 'b'
+text -0.9 -1.3 'fitted:' 'r:L'
+putsfit 0 -1.8 'y = ' 'r'
+text 0 2.2 'initial: y = 0.3+sin(2\pi x)' 'b'
+ at end verbatim
+
+NOTE! the fitting results may have strong dependence on initial values for coefficients due to algorithm features. The problem is that in general case there are several local "optimums" for coefficients and the program returns only first found one! There are no guaranties that it will be the best. Try for example to set @code{ini[3] = @{0, 0, 0@}} in the code above.
+
+The full sample code for nonlinear fitting is:
+ at verbatim
+new dat 100 '0.4*rnd+0.1+sin(2*pi*x)'
+new in 100 '0.3+sin(2*pi*x)'
+list ini 1 1 3:fit res dat 'a+b*sin(c*x)' 'abc' ini
+title 'Fitting sample':yrange -2 2:box:axis:plot dat 'k. '
+plot res 'r':plot in 'b'
+text -0.9 -1.3 'fitted:' 'r:L'
+putsfit 0 -1.8 'y = ' 'r'
+text 0 2.2 'initial: y = 0.3+sin(2\pi x)' 'b'
+ at end verbatim
+
+ at pfig{fit, Example of nonlinear fitting.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node PDE solving hints, Drawing phase plain, Nonlinear fitting hints, Hints
+ at subsection PDE solving hints
+ at nav{}
+
+Solving of Partial Differential Equations (PDE, including beam tracing) and ray tracing (or finding particle trajectory) are more or less common task. So, MathGL have several functions for that. There are @ref{ray} for ray tracing, @ref{pde} for PDE solving, @ref{qo2d} for beam tracing in 2D case (see @ref{Global functions}). Note, that these functions take ``Hamiltonian'' or equations as string values. And I don't plan now to allow one to use user-defined functions. There are 2 reasons: [...]
+
+The ray tracing can be done by @ref{ray} function. Really ray tracing equation is Hamiltonian equation for 3D space. So, the function can be also used for finding a particle trajectory (i.e. solve Hamiltonian ODE) for 1D, 2D or 3D cases. The function have a set of arguments. First of all, it is Hamiltonian which defined the media (or the equation) you are planning to use. The Hamiltonian is defined by string which may depend on coordinates @samp{x}, @samp{y}, @samp{z}, time @samp{t} (for [...]
+ at verbatim
+  const char *ham = "p^2+q^2-x-1+i*0.5*(y+x)*(y>-x)";
+  mglData r = mglRay(ham, mglPoint(-0.7, -1), mglPoint(0, 0.5), 0.02, 2);
+ at end verbatim
+This example calculate the reflection from linear layer (media with Hamiltonian @samp{p^2+q^2-x-1}=@math{p_x^2+p_y^2-x-1}). This is parabolic curve. The resulting array have 7 columns which contain data for @{x,y,z,p,q,v,t@}.
+
+The solution of PDE is a bit more complicated. As previous you have to specify the equation as pseudo-differential operator @math{\hat H(x, \nabla)} which is called sometime as ``Hamiltonian'' (for example, in beam tracing). As previously, it is defined by string which may depend on coordinates @samp{x}, @samp{y}, @samp{z} (but not time!), momentums @samp{p}=@math{(d/dx)/i k_0}, @samp{q}=@math{(d/dy)/i k_0} and field amplitude @samp{u}=@math{|u|}. The evolutionary coordinate is @samp{z}  [...]
+
+Next step is specifying the initial conditions at @samp{z} equal to minimal z-axis value. The function need 2 arrays for real and for imaginary part. Note, that coordinates x,y,z are supposed to be in specified axis range. So, the data arrays should have corresponding scales. Finally, you may set the integration step and parameter k0=@math{k_0}. Also keep in mind, that internally the 2 times large box is used (for suppressing numerical reflection from boundaries) and the equation should  [...]
+
+Final comment is concerning the possible form of pseudo-differential operator @math{H}. At this moment, simplified form of operator @math{H} is supported -- all ``mixed'' terms (like @samp{x*p}->x*d/dx) are excluded. For example, in 2D case this operator is effectively @math{H = f(p,z) + g(x,z,u)}. However commutable combinations (like @samp{x*q}->x*d/dy) are allowed for 3D case.
+
+So, for example let solve the equation for beam deflected from linear layer and absorbed later. The operator will have the form @samp{"p^2+q^2-x-1+i*0.5*(z+x)*(z>-x)"} that correspond to equation @math{1/ik_0 * du/dz + d^2 u/dx^2 + d^2 u/dy^2 + x * u + i (x+z)/2 * u = 0}. This is typical equation for Electron Cyclotron (EC) absorption in magnetized plasmas. For initial conditions let me select the beam with plane phase front @math{exp(-48*(x+0.7)^2)}. The corresponding code looks like this:
+ at verbatim
+new re 128 'exp(-48*(x+0.7)^2)':new im 128
+pde a 'p^2+q^2-x-1+i*0.5*(z+x)*(z>-x)' re im 0.01 30
+transpose a
+subplot 1 1 0 '<_':title 'PDE solver'
+axis:xlabel '\i x':ylabel '\i z'
+crange 0 1:dens a 'wyrRk'
+fplot '-x' 'k|'
+text 0 0.95 'Equation: ik_0\partial_zu + \Delta u + x\cdot u +\
+ i \frac{x+z}{2}\cdot u = 0\n{}absorption: (x+z)/2 for x+z>0'
+ at end verbatim
+
+ at pfig{pde, Example of PDE solving.}
+
+The next example is example of beam tracing. Beam tracing equation is special kind of PDE equation written in coordinates accompanied to a ray. Generally this is the same parameters and limitation as for PDE solving but the coordinates are defined by the ray and by parameter of grid width @var{w} in direction transverse the ray. So, you don't need to specify the range of coordinates. @strong{BUT} there is limitation. The accompanied coordinates are well defined only for smooth enough ray [...]
+
+You may use following code for obtaining the same solution as in previous example:
+ at verbatim
+define $1 'p^2+q^2-x-1+i*0.5*(y+x)*(y>-x)'
+subplot 1 1 0 '<_':title 'Beam and ray tracing'
+ray r $1 -0.7 -1 0 0 0.5 0 0.02 2:plot r(0) r(1) 'k'
+axis:xlabel '\i x':ylabel '\i z'
+new re 128 'exp(-48*x^2)':new im 128
+new xx 1:new yy 1
+qo2d a $1 re im r 1 30 xx yy
+crange 0 1:dens xx yy a 'wyrRk':fplot '-x' 'k|'
+text 0 0.85 'absorption: (x+y)/2 for x+y>0'
+text 0.7 -0.05 'central ray'
+ at end verbatim
+
+ at pfig{qo2d, Example of beam tracing.}
+
+Note, the @ref{pde} is fast enough and suitable for many cases routine. However, there is situations then media have both together: strong spatial dispersion and spatial inhomogeneity. In this, case the @ref{pde} will produce incorrect result and you need to use advanced PDE solver @ref{apde}. For example, a wave beam, propagated in plasma, described by Hamiltonian @math{exp(-x^2-p^2)}, will have different solution for using of simplification and advanced PDE solver:
+ at verbatim
+ranges -1 1 0 2 0 2
+new ar 256 'exp(-2*(x+0.0)^2)':new ai 256
+
+apde res1 'exp(-x^2-p^2)' ar ai 0.01:transpose res1
+subplot 1 2 0 '_':title 'Advanced PDE solver'
+ranges 0 2 -1 1:crange res1
+dens res1:box                                                                     
+axis:xlabel '\i z':ylabel '\i x'                                                  
+text -0.5 0.2 'i\partial_z\i u = exp(-\i x^2+\partial_x^2)[\i u]' 'y'             
+                                                                                  
+pde res2 'exp(-x^2-p^2)' ar ai 0.01
+subplot 1 2 1 '_':title 'Simplified PDE solver'                                   
+dens res2:box                                                                     
+axis:xlabel '\i z':ylabel '\i x'                                                  
+text -0.5 0.2 'i\partial_z\i u \approx\ exp(-\i x^2)\i u+exp(\partial_x^2)[\i u]' 'y'
+ at end verbatim
+
+ at pfig{apde, Comparison of simplified and advanced PDE solvers.}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Drawing phase plain, Pulse properties, PDE solving hints, Hints
+ at subsection Drawing phase plain
+ at nav{}
+
+Here I want say a few words of plotting phase plains. Phase plain is name for system of coordinates @math{x}, @math{x'}, i.e. a variable and its time derivative. Plot in phase plain is very useful for qualitative analysis of an ODE, because such plot is rude (it topologically the same for a range of ODE parameters). Most often the phase plain @{@math{x}, @math{x'}@} is used (due to its simplicity), that allows to analyze up to the 2nd order ODE (i.e. @math{x''+f(x,x')=0}).
+
+The simplest way to draw phase plain in MathGL is using @ref{flow} function(s), which automatically select several points and draw flow threads. If the ODE have an integral of motion (like Hamiltonian @math{H(x,x')=const} for dissipation-free case) then you can use @ref{cont} function for plotting isolines (contours). In fact. isolines are the same as flow threads, but without arrows on it. Finally, you can directly solve ODE using @ref{ode} function and plot its numerical solution.
+
+Let demonstrate this for ODE equation @math{x''-x+3*x^2=0}. This is nonlinear oscillator with square nonlinearity. It has integral @math{H=y^2+2*x^3-x^2=Const}. Also it have 2 typical stationary points: saddle at @{x=0, y=0@} and center at @{x=1/3, y=0@}. Motion at vicinity of center is just simple oscillations, and is stable to small variation of parameters. In opposite, motion around saddle point is non-stable to small variation of parameters, and is very slow. So, calculation around s [...]
+
+So, let draw this phase plain by 3 different methods. First, draw isolines for @math{H=y^2+2*x^3-x^2=Const} -- this is simplest for ODE without dissipation. Next, draw flow threads -- this is straightforward way, but the automatic choice of starting points is not always optimal. Finally, use @ref{ode} to check the above plots. At this we need to run @ref{ode} in both direction of time (in future and in the past) to draw whole plain. Alternatively, one can put starting points far from (or [...]
+ at verbatim
+subplot 2 2 0 '<_':title 'Cont':box
+axis:xlabel 'x':ylabel '\dot{x}'
+new f 100 100 'y^2+2*x^3-x^2-0.5':cont f
+
+subplot 2 2 1 '<_':title 'Flow':box
+axis:xlabel 'x':ylabel '\dot{x}'
+new fx 100 100 'x-3*x^2'
+new fy 100 100 'y'
+flow fy fx 'v';value 7
+
+subplot 2 2 2 '<_':title 'ODE':box
+axis:xlabel 'x':ylabel '\dot{x}'
+for $x -1 1 0.1
+  ode r 'y;x-3*x^2' 'xy' [$x,0]
+  plot r(0) r(1)
+  ode r '-y;-x+3*x^2' 'xy' [$x,0]
+  plot r(0) r(1)
+next
+ at end verbatim
+
+ at pfig{ode, Example of ODE solving and phase plain drawing.}
+
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Pulse properties, Using MGL parser, Drawing phase plain, Hints
+ at subsection Pulse properties
+ at nav{}
+
+There is common task in optics to determine properties of wave pulses or wave beams. MathGL provide special function @ref{pulse} which return the pulse properties (maximal value, center of mass, width and so on). Its usage is rather simple. Here I just illustrate it on the example of Gaussian pulse, where all parameters are obvious.
+ at verbatim
+subplot 1 1 0 '<_':title 'Pulse sample'
+# first prepare pulse itself
+new a 100 'exp(-6*x^2)'
+
+# get pulse parameters
+pulse b a 'x'
+
+# positions and widths are normalized on the number of points. So, set proper axis scale.
+ranges 0 a.nx-1 0 1
+axis:plot a # draw pulse and axis
+
+# now visualize found pulse properties
+define m a.max # maximal amplitude
+# approximate position of maximum
+line b(1) 0 b(1) m 'r='
+# width at half-maximum (so called FWHM)
+line b(1)-b(3)/2 0  b(1)-b(3)/2 m 'm|'
+line b(1)+b(3)/2 0  b(1)+b(3)/2 m 'm|'
+line 0 0.5*m a.nx-1 0.5*m 'h'
+# parabolic approximation near maximum
+new x 100 'x'
+plot b(0)*(1-((x-b(1))/b(2))^2) 'g'
+ at end verbatim
+
+ at pfig{pulse, Example of determining of pulse properties.}
+
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Using MGL parser, Using options, Pulse properties, Hints
+ at subsection Using MGL parser
+ at nav{}
+
+MGL scripts can contain loops, conditions and user-defined functions. Below I show very simple example of its usage:
+ at verbatim
+title 'MGL parser sample'
+call 'sample'
+stop
+
+func 'sample'
+new dat 100 'sin(2*pi*(x+1))'
+plot dat; xrange 0 1
+box:axis:xlabel 'x':ylabel 'y'
+for $0 -1 1 0.1
+if $0<0
+line 0 0 -1 $0 'r'
+else
+line 0 0 -1 $0 'r'
+endif
+next
+ at end verbatim
+
+ at pfig{parser, Example of MGL script parsing.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Using options, ``Templates'', Using MGL parser, Hints
+ at subsection Using options
+ at nav{}
+
+ at ref{Command options} allow the easy setup of the selected plot by changing global settings only for this plot. Often, options are used for specifying the range of automatic variables (coordinates). However, options allows easily change plot transparency, numbers of line or faces to be drawn, or add legend entries. The sample function for options usage is:
+ at verbatim
+new a 31 41 '-pi*x*exp(-(y+1)^2-4*x^2)'
+alpha on:light on
+subplot 2 2 0:title 'Options for coordinates':rotate 40 60:box
+surf a 'r';yrange 0 1
+surf a 'b';yrange 0 -1
+
+subplot 2 2 1:title 'Option "meshnum"':rotate 40 60:box
+mesh a 'r'; yrange 0 1
+mesh a 'b';yrange 0 -1; meshnum 5
+
+subplot 2 2 2:title 'Option "alpha"':rotate 40 60:box
+surf a 'r';yrange 0 1; alpha 0.7
+surf a 'b';yrange 0 -1; alpha 0.3
+
+subplot 2 2 3 '<_':title 'Option "legend"'
+fplot 'x^3' 'r'; legend 'y = x^3'
+fplot 'cos(pi*x)' 'b'; legend 'y = cos \pi x'
+box:axis:legend 2
+ at end verbatim
+
+ at pfig{mirror, Example of options usage.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ``Templates'', Nonlinear fitting hints, Using options, Hints
+ at subsection ``Templates''
+ at nav{}
+
+As I have noted before, the change of settings will influence only for the further plotting commands. This allows one to create ``template'' function which will contain settings and primitive drawing for often used plots. Correspondingly one may call this template-function for drawing simplification.
+
+For example, let one has a set of points (experimental or numerical) and wants to compare it with theoretical law (for example, with exponent law @math{\exp(-x/2), x \in [0, 20]}). The template-function for this task is:
+ at verbatim
+void template(mglGraph *gr)
+{
+  mglData  law(100);      // create the law
+  law.Modify("exp(-10*x)");
+  gr->SetRanges(0,20, 0.0001,1);
+  gr->SetFunc(0,"lg(y)",0);
+  gr->Plot(law,"r2");
+  gr->Puts(mglPoint(10,0.2),"Theoretical law: e^x","r:L");
+  gr->Label('x',"x val."); gr->Label('y',"y val.");
+  gr->Axis(); gr->Grid("xy","g;"); gr->Box();
+}
+ at end verbatim
+At this, one will only write a few lines for data drawing:
+ at verbatim
+  template(gr);     // apply settings and default drawing from template
+  mglData dat("fname.dat"); // load the data
+  // and draw it (suppose that data file have 2 columns)
+  gr->Plot(dat.SubData(0),dat.SubData(1),"bx ");
+ at end verbatim
+A template-function can also contain settings for font, transparency, lightning, color scheme and so on.
+
+I understand that this is obvious thing for any professional programmer, but I several times receive suggestion about ``templates'' ... So, I decide to point out it here.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Stereo image, Reduce memory usage, ``Templates'', Hints
+ at subsection Stereo image
+ at nav{}
+
+One can easily create stereo image in MathGL. Stereo image can be produced by making two subplots with slightly different rotation angles. The corresponding code looks like this:
+ at verbatim
+call 'prepare2d'
+light on
+subplot 2 1 0:rotate 50 60+1:box:surf a
+subplot 2 1 1:rotate 50 60-1:box:surf a
+ at end verbatim
+
+ at pfig{stereo, Example of stereo image.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Reduce memory usage, Saving and scanning file, Stereo image, Hints
+ at subsection Reduce memory usage
+ at nav{}
+
+By default MathGL save all primitives in memory, rearrange it and only later draw them on bitmaps. Usually, this speed up drawing, but may require a lot of memory for plots which contain a lot of faces (like @ref{cloud}, @ref{dew}). You can use @ref{quality} function for setting to use direct drawing on bitmap and bypassing keeping any primitives in memory. This function also allow you to decrease the quality of the resulting image but increase the speed of the drawing.
+
+The code for lower memory usage looks like this:
+ at verbatim
+quality 6  # firstly, set to draw directly on bitmap
+for $1 0 1000
+  sphere 2*rnd-1 2*rnd-1 0.05
+next
+ at end verbatim
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Saving and scanning file, Mixing bitmap and vector output, Reduce memory usage, Hints
+ at subsection Scanning file
+ at nav{}
+
+MathGL have possibilities to write textual information into file with variable values by help of @ref{save} command. This is rather useful for generating an ini-files or preparing human-readable textual files. For example, lets create some textual file
+ at verbatim
+subplot 1 1 0 '<_':title 'Save and scanfile sample'
+list a 1 -1 0
+save 'This is test: 0 -> ',a(0),' q' 'test.txt' 'w'
+save 'This is test: 1 -> ',a(1),' q' 'test.txt'
+save 'This is test: 2 -> ',a(2),' q' 'test.txt'
+ at end verbatim
+It contents look like
+ at verbatim
+This is test: 0 -> 1 q
+This is test: 1 -> -1 q
+This is test: 2 -> 0 q
+ at end verbatim
+Note, that I use option @samp{w} at first call of @code{save} to overwrite the contents of the file.
+
+Let assume now that you want to read this values (i.e. [[0,1],[1,-1],[2,0]]) from the file. You can use @ref{scanfile} for that. The desired values was written using template @samp{This is test: %g -> %g q}. So, just use
+ at verbatim
+scanfile a 'test.txt' 'This is test: %g -> %g'
+ at end verbatim
+and plot it to for assurance
+ at verbatim
+ranges a(0) a(1):axis:plot a(0) a(1) 'o'
+ at end verbatim
+
+Note, I keep only the leading part of template (i.e. @samp{This is test: %g -> %g} instead of @samp{This is test: %g -> %g q}), because there is no important for us information after the second number in the line.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Mixing bitmap and vector output, , Saving and scanning file, Hints
+ at subsection Mixing bitmap and vector output
+ at nav{}
+
+Sometimes output plots contain surfaces with a lot of points, and some vector primitives (like axis, text, curves, etc.). Using vector output formats (like EPS or SVG) will produce huge files with possible loss of smoothed lighting. Contrary, the bitmap output may cause the roughness of text and curves. Hopefully, MathGL have a possibility to combine bitmap output for surfaces and vector one for other primitives in the same EPS file, by using @ref{rasterize} command. 
+
+The idea is to prepare part of picture with surfaces or other "heavy" plots and produce the background image from them by help of @ref{rasterize} command. Next, we draw everything to be saved in vector form (text, curves, axis and etc.). Note, that you need to clear primitives (use @ref{clf} command) after @ref{rasterize} if you want to disable duplication of surfaces in output files (like EPS). Note, that some of output formats (like 3D ones, and TeX) don't support the background bitmap [...]
+
+The sample code is:
+ at verbatim
+# first draw everything to be in bitmap output
+fsurf 'x^2+y^2' '#';value 10
+
+rasterize   # set above plots as bitmap background
+clf         # clear primitives, to exclude them from file
+
+# now draw everything to be in vector output
+axis:box
+
+# and save file
+write 'fname.eps'
+ at end verbatim
+
+ at c ==================================================================
+
+ at external{}
+ at node FAQ, , Hints, Examples
+ at section FAQ
+ at nav{}
+
+ at table @strong
+ at item The plot does not appear
+Check that points of the plot are located inside the bounding box and resize the bounding box using @ref{ranges} function. Check that the data have correct dimensions for selected type of plot. Sometimes the light reflection from flat surfaces (like, @ref{dens}) can look as if the plot were absent.
+
+ at item I can not find some special kind of plot.
+Most ``new'' types of plots can be created by using the existing drawing functions. For example, the surface of curve rotation can be created by a special function @ref{torus}, or as a parametrically specified surface by @ref{surf}. See also, @ref{Hints}. If you can not find a specific type of plot, please e-mail me and this plot will appear in the next version of MathGL library.
+
+ at item How can I print in Russian/Spanish/Arabic/Japanese, and so on?
+The standard way is to use Unicode encoding for the text output. But the MathGL library also has interface for 8-bit (char *) strings with internal conversion to Unicode. This conversion depends on the current locale OS.
+
+ at item How can I exclude a point or a region of plot from the drawing?
+There are 3 general ways. First, the point with @code{nan} value as one of the coordinates (including color/alpha range) will never be plotted. Second, special functions define the condition when the points should be omitted (see @ref{Cutting}). Last, you may change the transparency of a part of the plot by the help of functions @ref{surfa}, @ref{surf3a} (see @ref{Dual plotting}). In last case the transparency is switched on smoothly.
+
+ at item How many people write this library?
+Most of the library was written by one person. This is a result of nearly a year of work (mostly in the evening and on holidays): I spent half a year to write the kernel and half a year to a year on extending, improving the library and writing documentation. This process continues now :). The build system (cmake files) was written mostly by D.Kulagin, and the export to PRC/PDF was written mostly by M.Vidassov.
+
+ at item How can I display a bitmap on the figure?
+You can import data by command @ref{import} and display it by @ref{dens} function. For example, for black-and-white bitmap you can use the code: @code{import bmp 'fname.png' 'wk':dens  bmp 'wk'}.
+
+
+ at item How can I create 3D in PDF?
+Just use command @code{write fname.pdf}, which create PDF file if enable-pdf=ON at MathGL configure.
+
+ at item How can I create TeX figure?
+Just use command @code{write fname.tex}, which create LaTeX files with figure itself @samp{@var{fname}.tex}, with MathGL colors @samp{mglcolors.tex} and main file @samp{mglmain.tex}. Last one can be used for viewing image by command like @code{pdflatex mglmain.tex}.
+
+
+ at item How I can change the font family?
+First, you should download new font files from @uref{http://mathgl.sourceforge.net/download.html, here} or from @uref{http://sourceforge.net/project/showfiles.php?group_id=152187&package_id=267177, here}. Next, you should load the font files into by the following command: @code{loadfont 'fontname'}. Here @var{fontname} is the base font name like @samp{STIX}. Use @code{loadfont ''} to start using the default font.
+
+ at item How can I draw tick out of a bounding box?
+Just set a negative value in @ref{ticklen}. For example, use @code{ticklen -0.1}.
+
+ at item How can I prevent text rotation?
+Just use @code{rotatetext off}. Also you can use axis style @samp{U} for disable only tick labels rotation.
+
+ at item How can I draw equal axis range even for rectangular image?
+Just use @code{aspect nan nan} for each subplot, or at the beginning of the drawing.
+
+ at item Как задать полупрозрачный фон?
+Просто используйте код типа @code{clf 'r@{A5@}'} или подготовьте PNG файл и задайте его в качестве фона рисунка @code{background 'fname.png'}.
+
+ at item Как уменьшить поля вокруг графика?
+Простейший путь состоит в использовании стилей @ref{subplot}. Однако, вы должны быть осторожны в изменении стиля @ref{subplot} если вы планируете добавлять @ref{colorbar} или вращать график -- часть графика может стать невидимой.
+
+ at item Can I combine bitmap and vector output in EPS?
+Yes. Sometimes you may have huge surface and a small set of curves and/or text on the plot. You can use function @ref{rasterize} just after making surface plot. This will put all plot to bitmap background. At this later plotting will be in vector format. For example, you can do something like following:
+ at verbatim
+surf x y z
+rasterize # make surface as bitmap
+axis
+write 'fname.eps'
+ at end verbatim
+
+ at end table
+
+ at external{}
diff --git a/texinfo/example_en.texi b/texinfo/example_en.texi
new file mode 100644
index 0000000..d7d6be7
--- /dev/null
+++ b/texinfo/example_en.texi
@@ -0,0 +1,4634 @@
+ at c ------------------------------------------------------------------
+ at chapter MathGL examples
+ at nav{}
+
+This chapter contain information about basic and advanced MathGL, hints and samples for all types of graphics. I recommend you read first 2 sections one after another and at least look on @ref{Hints} section. Also I recommend you to look at @ref{General concepts} and @ref{FAQ}.
+
+Note, that MathGL v.2.* have only 2 end-user interfaces: one for C/Fortran and similar languages which don't support classes, another one for C++/Python/Octave and similar languages which support classes. So, most of samples placed in this chapter can be run as is (after minor changes due to different syntaxes for different languages). For example, the C++ code
+ at verbatim
+#include <mgl2/mgl.h>
+int main()
+{
+  mglGraph gr;
+  gr.FPlot("sin(pi*x)");
+  gr.WriteFrame("test.png");
+}
+ at end verbatim
+in Python will be as
+ at verbatim
+from mathgl import *
+gr = mglGraph();
+gr.FPlot("sin(pi*x)");
+gr.WriteFrame("test.png");
+ at end verbatim
+in Octave will be as (you need first execute @code{mathgl;} in newer Octave versions)
+ at c (install MathGL package by command @code{octave:1> pkg install /usr/share/mathgl/octave/mathgl.tar.gz} from @code{sudo octave})
+ at verbatim
+gr = mglGraph();
+gr.FPlot("sin(pi*x)");
+gr.WriteFrame("test.png");
+ at end verbatim
+in C will be as
+ at verbatim
+#include <mgl2/mgl_cf.h>
+int main()
+{
+  HMGL gr = mgl_create_graph(600,400);
+  mgl_fplot(gr,"sin(pi*x)","","");
+  mgl_write_frame(gr,"test.png","");
+  mgl_delete_graph(gr);
+}
+ at end verbatim
+in Fortran will be as
+ at verbatim
+integer gr, mgl_create_graph
+gr = mgl_create_graph(600,400);
+call mgl_fplot(gr,'sin(pi*x)','','');
+call mgl_write_frame(gr,'test.png','');
+call mgl_delete_graph(gr);
+ at end verbatim
+and so on.
+
+
+
+ at menu
+* Basic usage::
+* Advanced usage::
+* Data handling::
+* Data plotting::
+* 1D samples::
+* 2D samples::
+* 3D samples::
+* Vector field samples::
+* Hints::
+* FAQ::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Basic usage, Advanced usage, , Examples
+ at section Basic usage
+ at nav{}
+
+MathGL library can be used by several manners. Each has positive and negative sides:
+ at itemize @bullet
+ at item
+ at emph{Using of MathGL library features for creating graphical window (requires FLTK, Qt or GLUT libraries).}
+
+Positive side is the possibility to view the plot at once and to modify it (rotate, zoom or switch on transparency or lighting) by hand or by mouse. Negative sides are: the need  of X-terminal and limitation consisting in working with the only one set of data at a time.
+
+ at item
+ at emph{Direct writing to file in bitmap or vector format without creation of graphical window.}
+
+Positive aspects are: batch processing of similar data set (for example, a set of resulting data files for different calculation parameters), running from the console program (including the cluster calculation), fast and automated drawing, saving pictures for further analysis (or demonstration). Negative sides are: the usage of the external program for picture viewing. Also, the data plotting is non-visual. So, you have to imagine the picture (view angles, lighting and so on) before the  [...]
+
+ at item
+ at emph{Drawing in memory with the following displaying by other graphical program.}
+
+In this case the programmer has more freedom in selecting the window libraries (not only FLTK, Qt or GLUT), in positioning and surroundings control and so on. I recommend to use such way for ``stand alone'' programs.
+
+ at item
+ at emph{Using FLTK or Qt widgets provided by MathGL}
+
+Here one can use a set of standard widgets which support export to many file formats, copying to clipboard, handle mouse and so on.
+ at end itemize
+
+MathGL drawing can be created not only by object oriented languages (like, C++ or Python), but also by pure C or Fortran-like languages. The usage of last one is mostly identical to usage of classes (except the different function names). But there are some differences. C functions must have argument HMGL (for graphics) and/or HMDT (for data arrays) which specifies the object for drawing or manipulating (changing). Fortran users may regard these variables as integer. So, firstly the user  [...]
+ at c Also, all arguments of C function have to be defined. So there are several functions with practically identical names doing practically the same. But some of them have simplified interface for the quick plotting and some of them have access to all plotting parameters for manual tunning.
+
+Let me consider the aforesaid in more detail.
+
+ at menu
+* Using MathGL window::
+* Drawing to file::
+* Animation::
+* Drawing in memory::
+* Draw and calculate::
+* Using QMathGL::
+* MathGL and PyQt::
+* MathGL and MPI::
+ at end menu
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Using MathGL window, Drawing to file, , Basic usage
+ at subsection Using MathGL window
+ at nav{}
+ at cindex window
+ at cindex widgets
+
+The ``interactive'' way of drawing in MathGL consists in window creation  with help of class @code{mglQT}, @code{mglFLTK} or @code{mglGLUT} (see @ref{Widget classes}) and the following drawing in this window. There is a corresponding code:
+ at verbatim
+#include <mgl2/qt.h>
+int sample(mglGraph *gr)
+{
+  gr->Rotate(60,40);
+  gr->Box();
+  return 0;
+}
+//-----------------------------------------------------
+int main(int argc,char **argv)
+{
+  mglQT gr(sample,"MathGL examples");
+  return gr.Run();
+}
+ at end verbatim
+Here callback function @code{sample} is defined. This function does all drawing. Other function @code{main} is entry point function for console program. For compilation, just execute the command
+ at verbatim
+gcc test.cpp -lmgl-qt5 -lmgl
+ at end verbatim
+You can use "-lmgl-qt4" instead of "-lmgl-qt5", if Qt4 is installed.
+
+Alternatively you can create yours own class inherited from @ref{mglDraw class} and re-implement the function @code{Draw()} in it:
+ at verbatim
+#include <mgl2/qt.h>
+class Foo : public mglDraw
+{
+public:
+  int Draw(mglGraph *gr);
+};
+//-----------------------------------------------------
+int Foo::Draw(mglGraph *gr)
+{
+  gr->Rotate(60,40);
+  gr->Box();
+  return 0;
+}
+//-----------------------------------------------------
+int main(int argc,char **argv)
+{
+  Foo foo;
+  mglQT gr(&foo,"MathGL examples");
+  return gr.Run();
+}
+ at end verbatim
+Or use pure C-functions:
+ at verbatim
+#include <mgl2/mgl_cf.h>
+int sample(HMGL gr, void *)
+{
+  mgl_rotate(gr,60,40,0);
+  mgl_box(gr);
+}
+int main(int argc,char **argv)
+{
+  HMGL gr;
+  gr = mgl_create_graph_qt(sample,"MathGL examples",0,0);
+  return mgl_qt_run();
+/* generally I should call mgl_delete_graph() here,
+ * but I omit it in main() function. */
+}
+ at end verbatim
+
+The similar code can be written for @code{mglGLUT} window (function @code{sample()} is the same):
+ at verbatim
+#include <mgl2/glut.h>
+int main(int argc,char **argv)
+{
+  mglGLUT gr(sample,"MathGL examples");
+  return 0;
+}
+ at end verbatim
+
+The rotation, shift, zooming, switching on/off transparency and lighting can be done with help of tool-buttons (for @code{mglQT, mglFLTK}) or by hot-keys: @samp{a}, @samp{d}, @samp{w}, @samp{s} for plot rotation, @samp{r} and @samp{f} switching on/off transparency and lighting. Press @samp{x} for exit (or closing the window).
+
+In this example function @code{sample} rotates axes (@code{Rotate()}, @pxref{Subplots and rotation}) and draws the bounding box (@code{Box()}). Drawing is placed in separate function since it will be used on demand when window canvas needs to be redrawn.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Drawing to file, Animation, Using MathGL window, Basic usage
+ at subsection Drawing to file
+ at nav{}
+
+Another way of using MathGL library is the direct writing of the picture to the file. It is most usable for plot creation during long calculation or for using of small programs (like Matlab or Scilab scripts) for visualizing repetitive sets of data. But the speed of drawing is much higher in comparison with a script language.
+
+The following code produces a bitmap PNG picture:
+ at verbatim
+#include <mgl2/mgl.h>
+int main(int ,char **)
+{
+  mglGraph gr;
+  gr.Alpha(true);   gr.Light(true);
+  sample(&gr);              // The same drawing function.
+  gr.WritePNG("test.png");  // Don't forget to save the result!
+  return 0;
+}
+ at end verbatim
+ For compilation, you need only libmgl library not the one with widgets
+ at verbatim
+gcc test.cpp -lmgl
+ at end verbatim
+This can be important if you create a console program in computer/cluster where X-server (and widgets) is inaccessible.
+
+The only difference from the previous variant (using windows) is manual switching on the transparency  @code{Alpha} and lightning @code{Light}, if you need it. The usage of frames (see @ref{Animation}) is not advisable since the whole image is prepared each time. If function @code{sample} contains frames then only last one will be saved to the file. In principle, one does not need to separate drawing functions in case of direct file writing in consequence of the single calling of this fu [...]
+
+The code for export into other formats (for example, into vector EPS file) looks the same:
+ at verbatim
+#include <mgl2/mgl.h>
+int main(int ,char **)
+{
+  mglGraph gr;
+  gr.Light(true);
+  sample(&gr);              // The same drawing function.
+  gr.WriteEPS("test.eps");  // Don't forget to save the result!
+  return 0;
+}
+ at end verbatim
+The difference from the previous one is using other function @code{WriteEPS()} for EPS format instead of function @code{WritePNG()}. Also, there is no switching on of the plot transparency @code{Alpha} since EPS format does not support it.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Animation, Drawing in memory, Drawing to file, Basic usage
+ at subsection Animation
+ at nav{}
+
+Widget classes (@code{mglWindow}, @code{mglGLUT}) support a delayed drawing, when all plotting functions are called once at the beginning of writing to memory lists. Further program displays the saved lists faster. Resulting redrawing will be faster but it requires sufficient memory. Several lists (frames) can be displayed one after another (by pressing @samp{,}, @samp{.}) or run as cinema. To switch these feature on one needs to modify function @code{sample}:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->NewFrame();             // the first frame
+  gr->Rotate(60,40);
+  gr->Box();
+  gr->EndFrame();             // end of the first frame
+  gr->NewFrame();             // the second frame
+  gr->Box();
+  gr->Axis("xy");
+  gr->EndFrame();             // end of the second frame
+  return gr->GetNumFrame();   // returns the frame number
+}
+ at end verbatim
+First, the function creates a frame by calling @code{NewFrame()} for rotated axes and draws the bounding box.  The function @code{EndFrame()} @strong{must be} called after the frame drawing! The second frame contains the bounding box and axes @code{Axis("xy")} in the initial (unrotated) coordinates. Function @code{sample} returns the number of created frames @code{GetNumFrame()}.
+
+Note, that animation can be also done as visualization of running calculations (see @ref{Draw and calculate}).
+
+Pictures with @strong{animation can be saved in file(s)} as well. You can: export in animated GIF, or save each frame in separate file (usually JPEG) and convert these files into the movie (for example, by help of ImageMagic). Let me show both methods.
+
+ at anchor{GIF}
+The simplest methods is making animated GIF. There are 3 steps: (1) open GIF file by @code{StartGIF()} function; (2) create the frames by calling @code{NewFrame()} before and @code{EndFrame()} after plotting; (3) close GIF by @code{CloseGIF()} function. So the simplest code for ``running'' sinusoid will look like this:
+ at verbatim
+#include <mgl2/mgl.h>
+int main(int ,char **)
+{
+  mglGraph gr;
+  mglData dat(100);
+  char str[32];
+  gr.StartGIF("sample.gif");
+  for(int i=0;i<40;i++)
+  {
+    gr.NewFrame();     // start frame
+    gr.Box();          // some plotting
+    for(int j=0;j<dat.nx;j++)
+      dat.a[j]=sin(M_PI*j/dat.nx+M_PI*0.05*i);
+    gr.Plot(dat,"b");
+    gr.EndFrame();     // end frame
+  }
+  gr.CloseGIF();
+  return 0;
+}
+ at end verbatim
+
+ at anchor{MPEG}
+The second way is saving each frame in separate file (usually JPEG) and later make the movie from them. MathGL have special function for saving frames -- it is @code{WriteFrame()}. This function save each frame with automatic name @samp{frame0001.jpg, frame0002.jpg} and so on. Here prefix @samp{frame} is defined by @var{PlotId} variable of @code{mglGraph} class. So the similar code will look like this:
+ at verbatim
+#include <mgl2/mgl.h>
+int main(int ,char **)
+{
+  mglGraph gr;
+  mglData dat(100);
+  char str[32];
+  for(int i=0;i<40;i++)
+  {
+    gr.NewFrame();     // start frame
+    gr.Box();          // some plotting
+    for(int j=0;j<dat.nx;j++)
+      dat.a[j]=sin(M_PI*j/dat.nx+M_PI*0.05*i);
+    gr.Plot(dat,"b");
+    gr.EndFrame();     // end frame
+    gr.WriteFrame();   // save frame
+  }
+  return 0;
+}
+ at end verbatim
+
+Created files can be converted to movie by help of a lot of programs. For example, you can use ImageMagic (command @samp{convert frame*.jpg movie.mpg}), MPEG library, GIMP and so on.
+
+Finally, you can use @code{mglconv} tool for doing the same with MGL scripts (@pxref{Utilities}).
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Drawing in memory, Draw and calculate, Animation, Basic usage
+ at subsection Drawing in memory
+ at nav{}
+
+The last way of MathGL using is the drawing in memory. Class @code{mglGraph} allows one  to create a bitmap picture in memory. Further this picture can be displayed in window by some window libraries (like wxWidgets, FLTK, Windows GDI and so on). For example, the code for drawing in wxWidget library looks like:
+ at verbatim
+void MyForm::OnPaint(wxPaintEvent& event)
+{
+  int w,h,x,y;
+  GetClientSize(&w,&h);   // size of the picture
+  mglGraph gr(w,h);
+
+  gr.Alpha(true);         // draws something using MathGL
+  gr.Light(true);
+  sample(&gr,NULL);
+
+  wxImage img(w,h,gr.GetRGB(),true);
+  ToolBar->GetSize(&x,&y);    // gets a height of the toolbar if any
+  wxPaintDC dc(this);         // and draws it
+  dc.DrawBitmap(wxBitmap(img),0,y);
+}
+ at end verbatim
+The drawing in other libraries is most the same.
+
+For example, FLTK code will look like
+ at verbatim
+void Fl_MyWidget::draw()
+{
+  mglGraph gr(w(),h());
+  gr.Alpha(true);         // draws something using MathGL
+  gr.Light(true);
+  sample(&gr,NULL);
+  fl_draw_image(gr.GetRGB(), x(), y(), gr.GetWidth(), gr.GetHeight(), 3);
+}
+ at end verbatim
+Qt code will look like
+ at verbatim
+void MyWidget::paintEvent(QPaintEvent *)
+{
+  mglGraph gr(w(),h());
+
+  gr.Alpha(true);         // draws something using MathGL
+  gr.Light(true);         gr.Light(0,mglPoint(1,0,-1));
+  sample(&gr,NULL);
+
+  // Qt don't support RGB format as is. So, let convert it to BGRN.
+  long w=gr.GetWidth(), h=gr.GetHeight();
+  unsigned char *buf = new uchar[4*w*h];
+  gr.GetBGRN(buf, 4*w*h)
+  QPixmap pic = QPixmap::fromImage(QImage(*buf, w, h, QImage::Format_RGB32));
+
+  QPainter paint;
+  paint.begin(this);  paint.drawPixmap(0,0,pic);  paint.end();
+  delete []buf;
+}
+ at end verbatim
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Draw and calculate, Using QMathGL, Drawing in memory, Basic usage
+ at subsection Draw and calculate
+ at nav{}
+
+MathGL can be used to draw plots in parallel with some external calculations. The simplest way for this is the usage of @ref{mglDraw class}. At this you should enable pthread for widgets by setting @code{enable-pthr-widget=ON} at configure stage (it is set by default).
+First, you need to inherit you class from @code{mglDraw} class, define virtual members @code{Draw()} and @code{Calc()} which will draw the plot and proceed calculations. You may want to add the pointer @code{mglWnd *wnd;} to window with plot for interacting with them. Finally, you may add any other data or member functions. The sample class is shown below
+ at verbatim
+class myDraw : public mglDraw
+{
+	mglPoint pnt;	// some variable for changeable data
+	long i;			// another variable to be shown
+	mglWnd *wnd;	// external window for plotting
+public:
+	myDraw(mglWnd *w=0) : mglDraw()	{	wnd=w;	}
+	void SetWnd(mglWnd *w)	{	wnd=w;	}
+	int Draw(mglGraph *gr)
+	{
+		gr->Line(mglPoint(),pnt,"Ar2");
+		char str[16];	snprintf(str,15,"i=%ld",i);
+		gr->Puts(mglPoint(),str);
+		return 0;
+	}
+	void Calc()
+	{
+		for(i=0;;i++)	// do calculation
+		{
+			long_calculations();// which can be very long
+			Check();	// check if need pause
+			pnt.Set(2*mgl_rnd()-1,2*mgl_rnd()-1);
+			if(wnd)	wnd->Update();
+		}
+	}
+} dr;
+ at end verbatim
+There is only one issue here. Sometimes you may want to pause calculations to view result carefully, or save state, or change something. So, you need to provide a mechanism for pausing. Class @code{mglDraw} provide function @code{Check();} which check if toolbutton with pause is pressed and wait until it will be released. This function should be called in a "safety" places, where you can pause the calculation (for example, at the end of time step). Also you may add call @code{exit(0);} a [...]
+Finally, you need to create a window itself and run calculations.
+ at verbatim
+int main(int argc,char **argv)
+{
+	mglFLTK gr(&dr,"Multi-threading test");	// create window
+	dr.SetWnd(&gr);	// pass window pointer to yours class
+	dr.Run();	// run calculations
+	gr.Run();	// run event loop for window
+	return 0;
+}
+ at end verbatim
+
+Note, that you can reach the similar functionality without using @code{mglDraw} class (i.e. even for pure C code).
+ at verbatim
+mglFLTK *gr=NULL;	// pointer to window
+void *calc(void *)	// function with calculations
+{
+	mglPoint pnt;	// some data for plot
+	for(long i=0;;i++)		// do calculation
+	{
+		long_calculations();	// which can be very long
+		pnt.Set(2*mgl_rnd()-1,2*mgl_rnd()-1);
+		if(gr)
+		{
+			gr->Clf();			// make new drawing
+			// draw something
+			gr->Line(mglPoint(),pnt,"Ar2");
+			char str[16];	snprintf(str,15,"i=%ld",i);
+			gr->Puts(mglPoint(),str);
+			// don't forgot to update window
+			gr->Update();
+		}
+	}
+}
+int main(int argc,char **argv)
+{
+	static pthread_t thr;
+	pthread_create(&thr,0,calc,0);	// create separate thread for calculations
+	pthread_detach(thr);			// and detach it
+	gr = new mglFLTK;	// now create window
+	gr->Run();			// and run event loop
+	return 0;
+}
+ at end verbatim
+This sample is exactly the same as one with @code{mglDraw} class, but it don't have functionality for pausing calculations. If you need it then you have to create global mutex (like @code{pthread_mutex_t *mutex = pthread_mutex_init(&mutex,NULL);}), set it to window (like @code{gr->SetMutex(mutex);}) and periodically check it at calculations (like @code{pthread_mutex_lock(&mutex); pthread_mutex_unlock(&mutex);}).
+
+Finally, you can put the event-handling loop in separate instead of yours code by using @code{RunThr()} function instead of @code{Run()} one. Unfortunately, such method work well only for FLTK windows and only if pthread support was enabled. Such limitation come from the Qt requirement to be run in the primary thread only. The sample code will be:
+ at verbatim
+int main(int argc,char **argv)
+{
+	mglFLTK gr("test");
+	gr.RunThr();	// <-- need MathGL version which use pthread for widgets
+	mglPoint pnt;	// some data
+	for(int i=0;i<10;i++)	// do calculation
+	{
+		long_calculations();// which can be very long
+		pnt.Set(2*mgl_rnd()-1,2*mgl_rnd()-1);
+		gr.Clf();			// make new drawing
+		gr.Line(mglPoint(),pnt,"Ar2");
+		char str[10] = "i=0";	str[3] = '0'+i;
+		gr->Puts(mglPoint(),str);
+		gr.Update();		// update window
+	}
+	return 0;	// finish calculations and close the window
+}
+ at end verbatim
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Using QMathGL, MathGL and PyQt, Draw and calculate, Basic usage
+ at subsection Using QMathGL
+ at nav{}
+
+MathGL have several interface widgets for different widget libraries. There are QMathGL for Qt, Fl_MathGL for FLTK. These classes provide control which display MathGL graphics. Unfortunately there is no uniform interface for widget classes because all libraries have slightly different set of functions, features and so on. However the usage of MathGL widgets is rather simple. Let me show it on the example of QMathGL.
+
+First of all you have to define the drawing function or inherit a class from @code{mglDraw} class. After it just create a window and setup QMathGL instance as any other Qt widget:
+ at verbatim
+#include <QApplication>
+#include <QMainWindow>
+#include <QScrollArea>
+#include <mgl2/qmathgl.h>
+int main(int argc,char **argv)
+{
+  QApplication a(argc,argv);
+  QMainWindow *Wnd = new QMainWindow;
+  Wnd->resize(810,610);  // for fill up the QMGL, menu and toolbars
+  Wnd->setWindowTitle("QMathGL sample");
+  // here I allow to scroll QMathGL -- the case
+  // then user want to prepare huge picture
+  QScrollArea *scroll = new QScrollArea(Wnd);
+
+  // Create and setup QMathGL
+  QMathGL *QMGL = new QMathGL(Wnd);
+//QMGL->setPopup(popup); // if you want to setup popup menu for QMGL
+  QMGL->setDraw(sample);
+  // or use QMGL->setDraw(foo); for instance of class Foo:public mglDraw
+  QMGL->update();
+
+  // continue other setup (menu, toolbar and so on)
+  scroll->setWidget(QMGL);
+  Wnd->setCentralWidget(scroll);
+  Wnd->show();
+  return a.exec();
+}
+ at end verbatim
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node MathGL and PyQt, MathGL and MPI, Using QMathGL, Basic usage
+ at subsection MathGL and PyQt
+ at nav{}
+
+Generally SWIG based classes (including the Python one) are the same as C++ classes. However, there are few tips for using MathGL with PyQt. Below I place a very simple python code which demonstrate how MathGL can be used with PyQt. This code is mostly written by Prof. Dr. Heino Falcke. You can just copy it to a file @code{mgl-pyqt-test.py} and execute it from python shell by command @code{execfile("mgl-pyqt-test.py")}
+
+ at verbatim
+from PyQt4 import QtGui,QtCore
+from mathgl import *
+import sys
+app = QtGui.QApplication(sys.argv)
+qpointf=QtCore.QPointF()
+
+class hfQtPlot(QtGui.QWidget):
+    def __init__(self, parent=None):
+        QtGui.QWidget.__init__(self, parent)
+        self.img=(QtGui.QImage())
+    def setgraph(self,gr):
+        self.buffer='\t'
+        self.buffer=self.buffer.expandtabs(4*gr.GetWidth()*gr.GetHeight())
+        gr.GetBGRN(self.buffer,len(self.buffer))
+        self.img=QtGui.QImage(self.buffer, gr.GetWidth(),gr.GetHeight(),QtGui.QImage.Format_ARGB32)
+        self.update()
+    def paintEvent(self, event):
+        paint = QtGui.QPainter()
+        paint.begin(self)
+        paint.drawImage(qpointf,self.img)
+        paint.end()
+
+BackgroundColor=[1.0,1.0,1.0]
+size=100
+gr=mglGraph()
+y=mglData(size)
+#y.Modify("((0.7*cos(2*pi*(x+.2)*500)+0.3)*(rnd*0.5+0.5)+362.135+10000.)")
+y.Modify("(cos(2*pi*x*10)+1.1)*1000.*rnd-501")
+x=mglData(size)
+x.Modify("x^2");
+
+def plotpanel(gr,x,y,n):
+    gr.SubPlot(2,2,n)
+    gr.SetXRange(x)
+    gr.SetYRange(y)
+    gr.AdjustTicks()
+    gr.Axis()
+    gr.Box()
+    gr.Label("x","x-Axis",1)
+    gr.Label("y","y-Axis",1)
+    gr.ClearLegend()
+    gr.AddLegend("Legend: "+str(n),"k")
+    gr.Legend()
+    gr.Plot(x,y)
+
+
+gr.Clf(BackgroundColor[0],BackgroundColor[1],BackgroundColor[2])
+gr.SetPlotFactor(1.5)
+plotpanel(gr,x,y,0)
+y.Modify("(cos(2*pi*x*10)+1.1)*1000.*rnd-501")
+plotpanel(gr,x,y,1)
+y.Modify("(cos(2*pi*x*10)+1.1)*1000.*rnd-501")
+plotpanel(gr,x,y,2)
+y.Modify("(cos(2*pi*x*10)+1.1)*1000.*rnd-501")
+plotpanel(gr,x,y,3)
+
+gr.WritePNG("test.png","Test Plot")
+
+qw = hfQtPlot()
+qw.show()
+qw.setgraph(gr)
+qw.raise_()
+ at end verbatim
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node MathGL and MPI, , MathGL and PyQt, Basic usage
+ at subsection MathGL and MPI
+ at nav{}
+
+For using MathGL in MPI program you just need to: (1) plot its own part of data for each running node; (2) collect resulting graphical information in a single program (for example, at node with rank=0); (3) save it. The sample code below demonstrate this for very simple sample of surface drawing.
+
+First you need to initialize MPI
+ at verbatim
+#include <stdio.h>
+#include <mgl2/mpi.h>
+#include <mpi.h>
+
+int main(int argc, char *argv[])
+{
+  // initialize MPI
+  int rank=0, numproc=1;
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD,&numproc);
+  MPI_Comm_rank(MPI_COMM_WORLD,&rank);
+  if(rank==0) printf("Use %d processes.\n", numproc);
+ at end verbatim
+
+Next step is data creation. For simplicity, I create data arrays with the same sizes for all nodes. At this, you have to create @code{mglGraph} object too.
+
+ at verbatim
+  // initialize data similarly for all nodes
+  mglData a(128,256);
+  mglGraphMPI gr;
+ at end verbatim
+
+Now, data should be filled by numbers. In real case, it should be some kind of calculations. But I just fill it by formula.
+
+ at verbatim
+  // do the same plot for its own range
+  char buf[64];
+  sprintf(buf,"xrange %g %g",2.*rank/numproc-1,2.*(rank+1)/numproc-1);
+  gr.Fill(a,"sin(2*pi*x)",buf);
+ at end verbatim
+
+It is time to plot the data. Don't forget to set proper axis range(s) by using parametric form or by using options (as in the sample).
+
+ at verbatim
+  // plot data in each node
+  gr.Clf();   // clear image before making the image
+  gr.Rotate(40,60);
+  gr.Surf(a,"",buf);
+ at end verbatim
+
+Finally, let send graphical information to node with rank=0.
+
+ at verbatim
+  // collect information
+  if(rank!=0) gr.MPI_Send(0);
+  else for(int i=1;i<numproc;i++)  gr.MPI_Recv(i);
+ at end verbatim
+
+Now, node with rank=0 have whole image. It is time to save the image to a file. Also, you can add a kind of annotations here -- I draw axis and bounding box in the sample.
+
+ at verbatim
+  if(rank==0)
+  {
+    gr.Box();   gr.Axis();   // some post processing
+    gr.WritePNG("test.png"); // save result
+  }
+ at end verbatim
+
+In my case the program is done, and I finalize MPI. In real program, you can repeat the loop of data calculation and data plotting as many times as you need.
+
+ at verbatim
+  MPI_Finalize();
+  return 0;
+}
+ at end verbatim
+
+You can type @samp{mpic++ test.cpp -lmgl-mpi -lmgl && mpirun -np 8 ./a.out} for compilation and running the sample program on 8 nodes. Note, that you have to set enable-mpi=ON at MathGL configure to use this feature.
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Advanced usage, Data handling, Basic usage, Examples
+ at section Advanced usage
+ at nav{}
+
+Now I show several non-obvious features of MathGL: several subplots in a single picture, curvilinear coordinates, text printing and so on. Generally you may miss this section at first reading.
+
+ at menu
+* Subplots::
+* Axis and ticks::
+* Curvilinear coordinates::
+* Colorbars::
+* Bounding box::
+* Ternary axis::
+* Text features::
+* Legend sample::
+* Cutting sample::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Subplots, Axis and ticks, , Advanced usage
+ at subsection Subplots
+ at nav{}
+
+Let me demonstrate possibilities of plot positioning and rotation. MathGL has a set of functions: @ref{subplot}, @ref{inplot}, @ref{title}, @ref{aspect} and @ref{rotate} and so on (see @ref{Subplots and rotation}). The order of their calling is strictly determined. First, one changes the position of plot in image area (functions @ref{subplot}, @ref{inplot} and @ref{multiplot}). Secondly, you can add the title of plot by @ref{title} function. After that one may rotate the plot (function @ [...]
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(2,2,0); gr->Box();
+  gr->Puts(mglPoint(-1,1.1),"Just box",":L");
+  gr->InPlot(0.2,0.5,0.7,1,false);  gr->Box();
+  gr->Puts(mglPoint(0,1.2),"InPlot example");
+  gr->SubPlot(2,2,1); gr->Title("Rotate only");
+  gr->Rotate(50,60);  gr->Box();
+  gr->SubPlot(2,2,2); gr->Title("Rotate and Aspect");
+  gr->Rotate(50,60);  gr->Aspect(1,1,2);  gr->Box();
+  gr->SubPlot(2,2,3); gr->Title("Shear");
+  gr->Box("c"); gr->Shear(0.2,0.1); gr->Box();
+  return 0;
+}
+ at end verbatim
+Here I used function @code{Puts} for printing the text in arbitrary position of picture (see @ref{Text printing}). Text coordinates and size are connected with axes. However, text coordinates may be everywhere, including the outside the bounding box. I'll show its features later in @ref{Text features}.
+
+ at pfig{aspect, Example of several subplots on the single picture.}
+
+More complicated sample show how to use most of positioning functions:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(3,2,0); gr->Title("StickPlot");
+  gr->StickPlot(3, 0, 20, 30);  gr->Box("r"); gr->Puts(mglPoint(0),"0","r");
+  gr->StickPlot(3, 1, 20, 30);  gr->Box("g"); gr->Puts(mglPoint(0),"1","g");
+  gr->StickPlot(3, 2, 20, 30);  gr->Box("b"); gr->Puts(mglPoint(0),"2","b");
+  gr->SubPlot(3,2,3,"");  gr->Title("ColumnPlot");
+  gr->ColumnPlot(3, 0); gr->Box("r"); gr->Puts(mglPoint(0),"0","r");
+  gr->ColumnPlot(3, 1); gr->Box("g"); gr->Puts(mglPoint(0),"1","g");
+  gr->ColumnPlot(3, 2); gr->Box("b"); gr->Puts(mglPoint(0),"2","b");
+  gr->SubPlot(3,2,4,"");  gr->Title("GridPlot");
+  gr->GridPlot(2, 2, 0);  gr->Box("r"); gr->Puts(mglPoint(0),"0","r");
+  gr->GridPlot(2, 2, 1);  gr->Box("g"); gr->Puts(mglPoint(0),"1","g");
+  gr->GridPlot(2, 2, 2);  gr->Box("b"); gr->Puts(mglPoint(0),"2","b");
+  gr->GridPlot(2, 2, 3);  gr->Box("m"); gr->Puts(mglPoint(0),"3","m");
+  gr->SubPlot(3,2,5,"");  gr->Title("InPlot");  gr->Box();
+  gr->InPlot(0.4, 1, 0.6, 1, true); gr->Box("r");
+  gr->MultiPlot(3,2,1, 2, 1,"");  gr->Title("MultiPlot and ShearPlot"); gr->Box();
+  gr->ShearPlot(3, 0, 0.2, 0.1);  gr->Box("r"); gr->Puts(mglPoint(0),"0","r");
+  gr->ShearPlot(3, 1, 0.2, 0.1);  gr->Box("g"); gr->Puts(mglPoint(0),"1","g");
+  gr->ShearPlot(3, 2, 0.2, 0.1);  gr->Box("b"); gr->Puts(mglPoint(0),"2","b");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{inplot, Example for most of positioning functions.}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Axis and ticks, Curvilinear coordinates, Subplots, Advanced usage
+ at subsection Axis and ticks
+ at nav{}
+
+MathGL library can draw not only the bounding box but also the axes, grids, labels and so on. The ranges of axes and their origin (the point of intersection) are determined by functions @code{SetRange()}, @code{SetRanges()}, @code{SetOrigin()} (see @ref{Ranges (bounding box)}). Ticks on axis are specified by function @code{SetTicks}, @code{SetTicksVal}, @code{SetTicksTime} (see @ref{Ticks}). But usually
+
+Function @ref{axis} draws axes. Its textual string shows in which directions the axis or axes will be drawn (by default @code{"xyz"}, function draws axes in all directions). Function @ref{grid} draws grid perpendicularly to specified directions. Example of axes and grid drawing is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(2,2,0); gr->Title("Axis origin, Grid"); gr->SetOrigin(0,0);
+  gr->Axis(); gr->Grid(); gr->FPlot("x^3");
+
+  gr->SubPlot(2,2,1); gr->Title("2 axis");
+  gr->SetRanges(-1,1,-1,1); gr->SetOrigin(-1,-1,-1);  // first axis
+  gr->Axis(); gr->Label('y',"axis 1",0);  gr->FPlot("sin(pi*x)");
+  gr->SetRanges(0,1,0,1);   gr->SetOrigin(1,1,1);   // second axis
+  gr->Axis(); gr->Label('y',"axis 2",0);  gr->FPlot("cos(pi*x)");
+
+  gr->SubPlot(2,2,3); gr->Title("More axis");
+  gr->SetOrigin(NAN,NAN); gr->SetRange('x',-1,1);
+  gr->Axis(); gr->Label('x',"x",0); gr->Label('y',"y_1",0);
+  gr->FPlot("x^2","k");
+  gr->SetRanges(-1,1,-1,1); gr->SetOrigin(-1.3,-1); // second axis
+  gr->Axis("y","r");  gr->Label('y',"#r{y_2}",0.2);
+  gr->FPlot("x^3","r");
+
+  gr->SubPlot(2,2,2); gr->Title("4 segments, inverted axis");
+  gr->SetOrigin(0,0);
+  gr->InPlot(0.5,1,0.5,1);  gr->SetRanges(0,10,0,2);  gr->Axis();
+  gr->FPlot("sqrt(x/2)");   gr->Label('x',"W",1); gr->Label('y',"U",1);
+  gr->InPlot(0,0.5,0.5,1);  gr->SetRanges(1,0,0,2); gr->Axis("x");
+  gr->FPlot("sqrt(x)+x^3"); gr->Label('x',"\\tau",-1);
+  gr->InPlot(0.5,1,0,0.5);  gr->SetRanges(0,10,4,0);  gr->Axis("y");
+  gr->FPlot("x/4"); gr->Label('y',"L",-1);
+  gr->InPlot(0,0.5,0,0.5);  gr->SetRanges(1,0,4,0); gr->FPlot("4*x^2");
+  return 0;
+}
+ at end verbatim
+
+Note, that MathGL can draw not only single axis (which is default). But also several axis on the plot (see right plots). The idea is that the change of settings does not influence on the already drawn graphics. So, for 2-axes I setup the first axis and draw everything concerning it. Then I setup the second axis and draw things for the second axis. Generally, the similar idea allows one to draw rather complicated plot of 4 axis with different ranges (see bottom left plot).
+
+At this inverted axis can be created by 2 methods. First one is used in this sample -- just specify minimal axis value to be large than maximal one. This method work well for 2D axis, but can wrongly place labels in 3D case. Second method is more general and work in 3D case too -- just use @ref{aspect} function with negative arguments. For example, following code will produce exactly the same result for 2D case, but 2nd variant will look better in 3D.
+ at verbatim
+// variant 1
+gr->SetRanges(0,10,4,0);  gr->Axis();
+
+// variant 2
+gr->SetRanges(0,10,0,4);  gr->Aspect(1,-1);   gr->Axis();
+ at end verbatim
+
+ at pfig{axis, Example of axis.}
+
+Another MathGL feature is fine ticks tunning. By default (if it is not changed by @code{SetTicks} function), MathGL try to adjust ticks positioning, so that they looks most human readable. At this, MathGL try to extract common factor for too large or too small axis ranges, as well as for too narrow ranges. Last one is non-common notation and can be disabled by @code{SetTuneTicks} function.
+
+Also, one can specify its own ticks with arbitrary labels by help of @code{SetTicksVal} function. Or one can set ticks in time format. In last case MathGL will try to select optimal format for labels with automatic switching between years, months/days, hours/minutes/seconds or microseconds. However, you can specify its own time representation using formats described in @url{http://www.manpagez.com/man/3/strftime/}. Most common variants are @samp{%X} for national representation of time, @ [...]
+
+The sample code, demonstrated ticks feature is
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(3,3,0); gr->Title("Usual axis");  gr->Axis();
+  gr->SubPlot(3,3,1); gr->Title("Too big/small range");
+  gr->SetRanges(-1000,1000,0,0.001);  gr->Axis();
+  gr->SubPlot(3,3,2); gr->Title("LaTeX-like labels");
+  gr->Axis("F!");
+  gr->SubPlot(3,3,3); gr->Title("Too narrow range");
+  gr->SetRanges(100,100.1,10,10.01);  gr->Axis();
+  gr->SubPlot(3,3,4); gr->Title("No tuning, manual '+'");
+  // for version<2.3 you need first call gr->SetTuneTicks(0);
+  gr->Axis("+!");
+  gr->SubPlot(3,3,5); gr->Title("Template for ticks");
+  gr->SetTickTempl('x',"xxx:%g"); gr->SetTickTempl('y',"y:%g");
+  gr->Axis();
+  // now switch it off for other plots
+  gr->SetTickTempl('x',"");   gr->SetTickTempl('y',"");
+  gr->SubPlot(3,3,6); gr->Title("No tuning, higher precision");
+  gr->Axis("!4");
+  gr->SubPlot(3,3,7); gr->Title("Manual ticks");  gr->SetRanges(-M_PI,M_PI, 0, 2);
+  gr->SetTicks('x',M_PI,0,0,"\\pi");  gr->AddTick('x',0.886,"x^*");
+  // alternatively you can use following lines
+  //double val[]={-M_PI, -M_PI/2, 0, 0.886, M_PI/2, M_PI};
+  //gr->SetTicksVal('x', mglData(6,val), "-\\pi\n-\\pi/2\n0\nx^*\n\\pi/2\n\\pi");
+  gr->Axis();  gr->Grid();  gr->FPlot("2*cos(x^2)^2", "r2");
+  gr->SubPlot(3,3,8); gr->Title("Time ticks");  gr->SetRange('x',0,3e5);
+  gr->SetTicksTime('x',0);  gr->Axis();
+}
+ at end verbatim
+
+ at pfig{ticks, Features of axis ticks.}
+
+The last sample I want to show in this subsection is Log-axis. From MathGL's point of view, the log-axis is particular case of general curvilinear coordinates. So, we need first define new coordinates (see also @ref{Curvilinear coordinates}) by help of @code{SetFunc} or @code{SetCoor} functions. At this one should wary about proper axis range. So the code looks as following:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(2,2,0,"<_");  gr->Title("Semi-log axis");
+  gr->SetRanges(0.01,100,-1,1); gr->SetFunc("lg(x)","");
+  gr->Axis(); gr->Grid("xy","g"); gr->FPlot("sin(1/x)");
+  gr->Label('x',"x",0); gr->Label('y', "y = sin 1/x",0);
+
+  gr->SubPlot(2,2,1,"<_");  gr->Title("Log-log axis");
+  gr->SetRanges(0.01,100,0.1,100);  gr->SetFunc("lg(x)","lg(y)");
+  gr->Axis(); gr->Grid("!","h=");   gr->Grid();
+  gr->FPlot("sqrt(1+x^2)"); gr->Label('x',"x",0);
+  gr->Label('y', "y = \\sqrt{1+x^2}",0);
+
+  gr->SubPlot(2,2,2,"<_");  gr->Title("Minus-log axis");
+  gr->SetRanges(-100,-0.01,-100,-0.1);  gr->SetFunc("-lg(-x)","-lg(-y)");
+  gr->Axis(); gr->FPlot("-sqrt(1+x^2)");
+  gr->Label('x',"x",0); gr->Label('y', "y = -\\sqrt{1+x^2}",0);
+
+  gr->SubPlot(2,2,3,"<_");  gr->Title("Log-ticks");
+  gr->SetRanges(0.1,100,0,100); gr->SetFunc("sqrt(x)","");
+  gr->Axis(); gr->FPlot("x");
+  gr->Label('x',"x",1); gr->Label('y', "y = x",0);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{loglog, Features of axis ticks.}
+
+You can see that MathGL automatically switch to log-ticks as we define log-axis formula (in difference from v.1.*). Moreover, it switch to log-ticks for any formula if axis range will be large enough (see right bottom plot). Another interesting feature is that you not necessary define usual log-axis (i.e. when coordinates are positive), but you can define ``minus-log'' axis when coordinate is negative (see left bottom plot).
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Curvilinear coordinates, Colorbars, Axis and ticks, Advanced usage
+ at subsection Curvilinear coordinates
+ at nav{}
+
+As I noted in previous subsection, MathGL support curvilinear coordinates. In difference from other plotting programs and libraries, MathGL uses textual formulas for connection of the old (data) and new (output) coordinates. This allows one to plot in arbitrary coordinates. The following code plots the line @var{y}=0, @var{z}=0 in Cartesian, polar, parabolic and spiral coordinates:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SetOrigin(-1,1,-1);
+
+  gr->SubPlot(2,2,0); gr->Title("Cartesian"); gr->Rotate(50,60);
+  gr->FPlot("2*t-1","0.5","0","r2");
+  gr->Axis(); gr->Grid();
+
+  gr->SetFunc("y*sin(pi*x)","y*cos(pi*x)",0);
+  gr->SubPlot(2,2,1); gr->Title("Cylindrical"); gr->Rotate(50,60);
+  gr->FPlot("2*t-1","0.5","0","r2");
+  gr->Axis(); gr->Grid();
+
+  gr->SetFunc("2*y*x","y*y - x*x",0);
+  gr->SubPlot(2,2,2); gr->Title("Parabolic"); gr->Rotate(50,60);
+  gr->FPlot("2*t-1","0.5","0","r2");
+  gr->Axis(); gr->Grid();
+
+  gr->SetFunc("y*sin(pi*x)","y*cos(pi*x)","x+z");
+  gr->SubPlot(2,2,3); gr->Title("Spiral");  gr->Rotate(50,60);
+  gr->FPlot("2*t-1","0.5","0","r2");
+  gr->Axis(); gr->Grid();
+  gr->SetFunc(0,0,0); // set to default Cartesian
+  return 0;
+}
+ at end verbatim
+
+ at pfig{curvcoor, Example of curvilinear coordinates}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Colorbars, Bounding box, Curvilinear coordinates, Advanced usage
+ at subsection Colorbars
+ at nav{}
+
+MathGL handle @ref{colorbar} as special kind of axis. So, most of functions for axis and ticks setup will work for colorbar too. Colorbars can be in log-scale, and generally as arbitrary function scale; common factor of colorbar labels can be separated; and so on.
+
+But of course, there are differences -- colorbars usually located out of bounding box. At this, colorbars can be at subplot boundaries (by default), or at bounding box (if symbol @samp{I} is specified). Colorbars can handle sharp colors. And they can be located at arbitrary position too. The sample code, which demonstrate colorbar features is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(2,2,0); gr->Title("Colorbar out of box"); gr->Box();
+  gr->Colorbar("<");  gr->Colorbar(">");
+  gr->Colorbar("_");  gr->Colorbar("^");
+
+  gr->SubPlot(2,2,1); gr->Title("Colorbar near box");   gr->Box();
+  gr->Colorbar("<I"); gr->Colorbar(">I");
+  gr->Colorbar("_I"); gr->Colorbar("^I");
+
+  gr->SubPlot(2,2,2); gr->Title("manual colors");
+  mglData a,v;  mgls_prepare2d(&a,0,&v);
+  gr->Box();  gr->ContD(v,a);
+  gr->Colorbar(v,"<");  gr->Colorbar(v,">");
+  gr->Colorbar(v,"_");  gr->Colorbar(v,"^");
+
+  gr->SubPlot(2,2,3);   gr->Title(" ");
+  gr->Puts(mglPoint(-0.5,1.55),"Color positions",":C",-2);
+  gr->Colorbar("bwr>",0.25,0);  gr->Puts(mglPoint(-0.9,1.2),"Default");
+  gr->Colorbar("b{w,0.3}r>",0.5,0); gr->Puts(mglPoint(-0.1,1.2),"Manual");
+
+  gr->Puts(mglPoint(1,1.55),"log-scale",":C",-2);
+  gr->SetRange('c',0.01,1e3);
+  gr->Colorbar(">",0.75,0);  gr->Puts(mglPoint(0.65,1.2),"Normal scale");
+  gr->SetFunc("","","","lg(c)");
+  gr->Colorbar(">");    gr->Puts(mglPoint(1.35,1.2),"Log scale");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{colorbar, Example of colorbars}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Bounding box, Ternary axis, Colorbars, Advanced usage
+ at subsection Bounding box
+ at nav{}
+
+Box around the plot is rather useful thing because it allows one to: see the plot boundaries, and better estimate points position since box contain another set of ticks. MathGL provide special function for drawing such box -- @ref{box} function. By default, it draw black or white box with ticks (color depend on transparency type, see @ref{Types of transparency}). However, you can change the color of box, or add drawing of rectangles at rear faces of box. Also you can disable ticks drawin [...]
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(2,2,0); gr->Title("Box (default)"); gr->Rotate(50,60);
+  gr->Box();
+  gr->SubPlot(2,2,1); gr->Title("colored");   gr->Rotate(50,60);
+  gr->Box("r");
+  gr->SubPlot(2,2,2); gr->Title("with faces");  gr->Rotate(50,60);
+  gr->Box("@");
+  gr->SubPlot(2,2,3); gr->Title("both");  gr->Rotate(50,60);
+  gr->Box("@cm");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{box, Example of Box()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Ternary axis, Text features, Bounding box, Advanced usage
+ at subsection Ternary axis
+ at nav{}
+
+There are another unusual axis types which are supported by MathGL. These are ternary and quaternary axis. Ternary axis is special axis of 3 coordinates @var{a}, @var{b}, @var{c} which satisfy relation @var{a}+ at var{b}+ at var{c}=1. Correspondingly, quaternary axis is special axis of 4 coordinates @var{a}, @var{b}, @var{c}, @var{d} which satisfy relation @var{a}+ at var{b}+ at var{c}+ at var{d}=1.
+
+Generally speaking, only 2 of coordinates (3 for quaternary) are independent. So, MathGL just introduce some special transformation formulas which treat @var{a} as @samp{x}, @var{b} as @samp{y} (and @var{c} as @samp{z} for quaternary). As result, all plotting functions (curves, surfaces, contours and so on) work as usual, but in new axis. You should use @ref{ternary} function for switching to ternary/quaternary coordinates. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SetRanges(0,1,0,1,0,1);
+  mglData x(50),y(50),z(50),rx(10),ry(10), a(20,30);
+  a.Modify("30*x*y*(1-x-y)^2*(x+y<1)");
+  x.Modify("0.25*(1+cos(2*pi*x))");
+  y.Modify("0.25*(1+sin(2*pi*x))");
+  rx.Modify("rnd"); ry.Modify("(1-v)*rnd",rx);
+  z.Modify("x");
+
+  gr->SubPlot(2,2,0); gr->Title("Ordinary axis 3D");
+  gr->Rotate(50,60);    gr->Light(true);
+  gr->Plot(x,y,z,"r2"); gr->Surf(a,"BbcyrR#");
+  gr->Axis(); gr->Grid(); gr->Box();
+  gr->Label('x',"B",1); gr->Label('y',"C",1); gr->Label('z',"Z",1);
+
+  gr->SubPlot(2,2,1); gr->Title("Ternary axis (x+y+t=1)");
+  gr->Ternary(1);
+  gr->Plot(x,y,"r2"); gr->Plot(rx,ry,"q^ ");  gr->Cont(a,"BbcyrR");
+  gr->Line(mglPoint(0.5,0), mglPoint(0,0.75), "g2");
+  gr->Axis(); gr->Grid("xyz","B;");
+  gr->Label('x',"B"); gr->Label('y',"C"); gr->Label('t',"A");
+
+  gr->SubPlot(2,2,2); gr->Title("Quaternary axis 3D");
+  gr->Rotate(50,60);    gr->Light(true);
+  gr->Ternary(2);
+  gr->Plot(x,y,z,"r2"); gr->Surf(a,"BbcyrR#");
+  gr->Axis(); gr->Grid(); gr->Box();
+  gr->Label('t',"A",1); gr->Label('x',"B",1);
+  gr->Label('y',"C",1); gr->Label('z',"D",1);
+
+  gr->SubPlot(2,2,3); gr->Title("Ternary axis 3D");
+  gr->Rotate(50,60);    gr->Light(true);
+  gr->Ternary(1);
+  gr->Plot(x,y,z,"r2"); gr->Surf(a,"BbcyrR#");
+  gr->Axis(); gr->Grid(); gr->Box();
+  gr->Label('t',"A",1); gr->Label('x',"B",1);
+  gr->Label('y',"C",1); gr->Label('z',"Z",1);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{ternary, Example of colorbars}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Text features, Legend sample, Ternary axis, Advanced usage
+ at subsection Text features
+ at nav{}
+
+MathGL prints text by vector font. There are functions for manual specifying of text position (like @code{Puts}) and for its automatic selection (like @code{Label}, @code{Legend} and so on). MathGL prints text always in specified position even if it lies outside the bounding box. The default size of font is specified by functions @var{SetFontSize*} (see @ref{Font settings}). However, the actual size of output string depends on subplot size (depends on functions @code{SubPlot}, @code{InPl [...]
+
+Text can be printed as usual one (from left to right), along some direction (rotated text), or along a curve. Text can be printed on several lines, divided by new line symbol @samp{\n}.
+
+Example of MathGL font drawing is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(2,2,0,"");
+  gr->Putsw(mglPoint(0,1),L"Text can be in ASCII and in Unicode");
+  gr->Puts(mglPoint(0,0.6),"It can be \\wire{wire}, \\big{big} or #r{colored}");
+  gr->Puts(mglPoint(0,0.2),"One can change style in string: "
+  "\\b{bold}, \\i{italic, \\b{both}}");
+  gr->Puts(mglPoint(0,-0.2),"Easy to \\a{overline} or "
+  "\\u{underline}");
+  gr->Puts(mglPoint(0,-0.6),"Easy to change indexes ^{up} _{down} @{center}");
+  gr->Puts(mglPoint(0,-1),"It parse TeX: \\int \\alpha \\cdot "
+  "\\sqrt3{sin(\\pi x)^2 + \\gamma_{i_k}} dx");
+
+  gr->SubPlot(2,2,1,"");
+  gr->Puts(mglPoint(0,0.5), "\\sqrt{\\frac{\\alpha^{\\gamma^2}+\\overset 1{\\big\\infty}}{\\sqrt3{2+b}}}", "@", -4);
+  gr->Puts(mglPoint(0,-0.5),"Text can be printed\non several lines");
+
+  gr->SubPlot(2,2,2,"");
+  mglData y;  mgls_prepare1d(&y);
+  gr->Box();  gr->Plot(y.SubData(-1,0));
+  gr->Text(y,"This is very very long string drawn along a curve",":k");
+  gr->Text(y,"Another string drawn under a curve","T:r");
+
+  gr->SubPlot(2,2,3,"");
+  gr->Line(mglPoint(-1,-1),mglPoint(1,-1),"rA");
+  gr->Puts(mglPoint(0,-1),mglPoint(1,-1),"Horizontal");
+  gr->Line(mglPoint(-1,-1),mglPoint(1,1),"rA");
+  gr->Puts(mglPoint(0,0),mglPoint(1,1),"At angle","@");
+  gr->Line(mglPoint(-1,-1),mglPoint(-1,1),"rA");
+  gr->Puts(mglPoint(-1,0),mglPoint(-1,1),"Vertical");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{text, Example of text printing}
+
+You can change font faces by loading font files by function @ref{loadfont}. Note, that this is long-run procedure. Font faces can be downloaded from @uref{http://mathgl.sourceforge.net/download.html, MathGL website} or from @uref{http://sourceforge.net/project/showfiles.php?group_id=152187&package_id=267177, here}. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  double h=1.1, d=0.25;
+  gr->LoadFont("STIX");     gr->Puts(mglPoint(0,h), "default font (STIX)");
+  gr->LoadFont("adventor"); gr->Puts(mglPoint(0,h-d), "adventor font");
+  gr->LoadFont("bonum");    gr->Puts(mglPoint(0,h-2*d), "bonum font");
+  gr->LoadFont("chorus");   gr->Puts(mglPoint(0,h-3*d), "chorus font");
+  gr->LoadFont("cursor");   gr->Puts(mglPoint(0,h-4*d), "cursor font");
+  gr->LoadFont("heros");    gr->Puts(mglPoint(0,h-5*d), "heros font");
+  gr->LoadFont("heroscn");  gr->Puts(mglPoint(0,h-6*d), "heroscn font");
+  gr->LoadFont("pagella");  gr->Puts(mglPoint(0,h-7*d), "pagella font");
+  gr->LoadFont("schola");   gr->Puts(mglPoint(0,h-8*d), "schola font");
+  gr->LoadFont("termes");   gr->Puts(mglPoint(0,h-9*d), "termes font");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{fonts, Example of font faces}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Legend sample, Cutting sample, Text features, Advanced usage
+ at subsection Legend sample
+ at nav{}
+
+Legend is one of standard ways to show plot annotations. Basically you need to connect the plot style (line style, marker and color) with some text. In MathGL, you can do it by 2 methods: manually using @ref{addlegend} function; or use @samp{legend} option (see @ref{Command options}), which will use last plot style. In both cases, legend entries will be added into internal accumulator, which later used for legend drawing itself. @ref{clearlegend} function allow you to remove all saved le [...]
+
+There are 2 features. If plot style is empty then text will be printed without indent. If you want to plot the text with indent but without plot sample then you need to use space @samp{ } as plot style. Such style @samp{ } will draw a plot sample (line with marker(s)) which is invisible line (i.e. nothing) and print the text with indent as usual one.
+
+Function @ref{legend} draw legend on the plot. The position of the legend can be selected automatic or manually. You can change the size and style of text labels, as well as setup the plot sample. The sample code demonstrating legend features is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->AddLegend("sin(\\pi {x^2})","b");
+  gr->AddLegend("sin(\\pi x)","g*");
+  gr->AddLegend("sin(\\pi \\sqrt{x})","rd");
+  gr->AddLegend("just text"," ");
+  gr->AddLegend("no indent for this","");
+
+  gr->SubPlot(2,2,0,""); gr->Title("Legend (default)");
+  gr->Box();  gr->Legend();
+
+  gr->Legend(3,"A#");
+  gr->Puts(mglPoint(0.75,0.65),"Absolute position","A");
+
+  gr->SubPlot(2,2,2,"");  gr->Title("coloring");  gr->Box();
+  gr->Legend(0,"r#"); gr->Legend(1,"Wb#");  gr->Legend(2,"ygr#");
+
+  gr->SubPlot(2,2,3,"");  gr->Title("manual position"); gr->Box();
+  gr->Legend(0.5,1);  gr->Puts(mglPoint(0.5,0.55),"at x=0.5, y=1","a");
+  gr->Legend(1,"#-"); gr->Puts(mglPoint(0.75,0.25),"Horizontal legend","a");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{legend, Example of legend}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cutting sample, , Legend sample, Advanced usage
+ at subsection Cutting sample
+ at nav{}
+
+The last common thing which I want to show in this section is how one can cut off points from plot. There are 4 mechanism for that.
+ at itemize @bullet
+ at item
+You can set one of coordinate to NAN value. All points with NAN values will be omitted.
+
+ at item
+You can enable cutting at edges by @code{SetCut} function. As result all points out of bounding box will be omitted.
+
+ at item
+You can set cutting box by @code{SetCutBox} function. All points inside this box will be omitted.
+
+ at item
+You can define cutting formula by @code{SetCutOff} function. All points for which the value of formula is nonzero will be omitted. Note, that this is the slowest variant.
+ at end itemize
+
+Below I place the code which demonstrate last 3 possibilities:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,c,v(1); mgls_prepare2d(&a); mgls_prepare3d(&c); v.a[0]=0.5;
+  gr->SubPlot(2,2,0); gr->Title("Cut on (default)");
+  gr->Rotate(50,60);  gr->Light(true);
+  gr->Box();  gr->Surf(a,"","zrange -1 0.5");
+
+  gr->SubPlot(2,2,1); gr->Title("Cut off");   gr->Rotate(50,60);
+  gr->Box();  gr->Surf(a,"","zrange -1 0.5; cut off");
+
+  gr->SubPlot(2,2,2); gr->Title("Cut in box");  gr->Rotate(50,60);
+  gr->SetCutBox(mglPoint(0,-1,-1), mglPoint(1,0,1.1));
+  gr->Alpha(true);  gr->Box();  gr->Surf3(c);
+  gr->SetCutBox(mglPoint(0), mglPoint(0));  // switch it off
+
+  gr->SubPlot(2,2,3); gr->Title("Cut by formula");  gr->Rotate(50,60);
+  gr->CutOff("(z>(x+0.5*y-1)^2-1) & (z>(x-0.5*y-1)^2-1)");
+  gr->Box();  gr->Surf3(c); gr->CutOff(""); // switch it off
+  return 0;
+}
+ at end verbatim
+
+ at pfig{cut, Example of point cutting}
+
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Data handling, Data plotting, Advanced usage, Examples
+ at section Data handling
+ at nav{}
+
+Class @code{mglData} contains all functions for the data handling in MathGL (@pxref{Data processing}). There are several matters why I use class @code{mglData} but not a single array: it does not depend on type of data (mreal or double), sizes of data arrays are kept with data, memory working is simpler and safer.
+
+ at menu
+* Array creation::
+* Linking array::
+* Change data::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Array creation, Linking array, , Data handling
+ at subsection Array creation
+ at nav{}
+
+There are many ways in MathGL how data arrays can be created and filled.
+
+One can put the data in @code{mglData} instance by several ways. Let us do it for sinus function:
+ at itemize @bullet
+ at item
+one can create external array, fill it and put to @code{mglData} variable
+ at verbatim
+  double *a = new double[50];
+  for(int i=0;i<50;i++)   a[i] = sin(M_PI*i/49.);
+
+  mglData y;
+  y.Set(a,50);
+ at end verbatim
+
+ at item
+another way is to create @code{mglData} instance of the desired size and then to work directly with data in this variable
+ at verbatim
+  mglData y(50);
+  for(int i=0;i<50;i++)   y.a[i] = sin(M_PI*i/49.);
+ at end verbatim
+
+ at item
+next way is to fill the data in @code{mglData} instance by textual formula with the help of @code{Modify()} function
+ at verbatim
+  mglData y(50);
+  y.Modify("sin(pi*x)");
+ at end verbatim
+
+ at item
+or one may fill the array in some interval and modify it later
+ at verbatim
+  mglData y(50);
+  y.Fill(0,M_PI);
+  y.Modify("sin(u)");
+ at end verbatim
+
+ at item
+finally it can be loaded from file
+ at verbatim
+  FILE *fp=fopen("sin.dat","wt");   // create file first
+  for(int i=0;i<50;i++)   fprintf(fp,"%g\n",sin(M_PI*i/49.));
+  fclose(fp);
+
+  mglData y("sin.dat");             // load it
+ at end verbatim
+At this you can use textual or HDF files, as well as import values from bitmap image (PNG is supported right now).
+
+ at item
+at this one can read only part of data
+ at verbatim
+  FILE *fp-fopen("sin.dat","wt");   // create large file first
+  for(int i=0;i<70;i++)   fprintf(fp,"%g\n",sin(M_PI*i/49.));
+  fclose(fp);
+
+  mglData y;
+  y.Read("sin.dat",50);             // load it
+ at end verbatim
+ at end itemize
+
+Creation of 2d- and 3d-arrays is mostly the same. But one should keep in mind that class @code{mglData} uses flat data representation. For example, matrix 30*40 is presented as flat (1d-) array with length 30*40=1200 (nx=30, ny=40). The element with indexes @{i,j@} is a[i+nx*j]. So for 2d array we have:
+ at verbatim
+  mglData z(30,40);
+  for(int i=0;i<30;i++)   for(int j=0;j<40;j++)
+    z.a[i+30*j] = sin(M_PI*i/29.)*sin(M_PI*j/39.);
+ at end verbatim
+or by using @code{Modify()} function
+ at verbatim
+  mglData z(30,40);
+  z.Modify("sin(pi*x)*cos(pi*y)");
+ at end verbatim
+
+The only non-obvious thing here is using multidimensional arrays in C/C++, i.e. arrays defined like @code{mreal dat[40][30];}. Since, formally these elements @code{dat[i]} can address the memory in arbitrary place you should use the proper function to convert such arrays to @code{mglData} object. For C++ this is functions like @code{mglData::Set(mreal **dat, int N1, int N2);}. For C this is functions like @code{mgl_data_set_mreal2(HMDT d, const mreal **dat, int N1, int N2);}. At this, yo [...]
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Linking array, Change data, Array creation, Data handling
+ at subsection Linking array
+ at nav{}
+
+Sometimes the data arrays are so large, that one couldn't' copy its values to another array (i.e. into mglData). In this case, he can define its own class derived from @code{mglDataA} (see @ref{mglDataA class}) or can use @code{Link} function.
+
+In last case, MathGL just save the link to an external data array, but not copy it. You should provide the existence of this data array for whole time during which MathGL can use it. Another point is that MathGL will automatically create new array if you'll try to modify data values by any of @code{mglData} functions. So, you should use only function with @code{const} modifier if you want still using link to the original data array.
+
+Creating the link is rather simple -- just the same as using @code{Set} function
+ at verbatim
+  double *a = new double[50];
+  for(int i=0;i<50;i++)   a[i] = sin(M_PI*i/49.);
+
+  mglData y;
+  y.Link(a,50);
+ at end verbatim
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Change data, , Linking array, Data handling
+ at subsection Change data
+ at nav{}
+
+MathGL has functions for data processing: differentiating, integrating, smoothing and so on (for more detail, see @ref{Data processing}). Let us consider some examples. The simplest ones are integration and differentiation. The direction in which operation will be performed is specified by textual string, which may contain symbols @samp{x}, @samp{y} or @samp{z}. For example, the call of @code{Diff("x")} will differentiate data along @samp{x} direction; the call of @code{Integral("xy")} p [...]
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SetRanges(0,1,0,1,0,1);
+  mglData a(30,40); a.Modify("x*y");
+  gr->SubPlot(2,2,0); gr->Rotate(60,40);
+  gr->Surf(a);    gr->Box();
+  gr->Puts(mglPoint(0.7,1,1.2),"a(x,y)");
+  gr->SubPlot(2,2,1); gr->Rotate(60,40);
+  a.Diff("x");    gr->Surf(a);  gr->Box();
+  gr->Puts(mglPoint(0.7,1,1.2),"da/dx");
+  gr->SubPlot(2,2,2); gr->Rotate(60,40);
+  a.Integral("xy"); gr->Surf(a);  gr->Box();
+  gr->Puts(mglPoint(0.7,1,1.2),"\\int da/dx dxdy");
+  gr->SubPlot(2,2,3); gr->Rotate(60,40);
+  a.Diff2("y"); gr->Surf(a);  gr->Box();
+  gr->Puts(mglPoint(0.7,1,1.2),"\\int {d^2}a/dxdy dx");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{dat_diff, Example of data differentiation and integration}
+
+Data smoothing (function @ref{smooth}) is more interesting and important. This function has single argument which define type of smoothing and its direction. Now 3 methods are supported: @samp{3} -- linear averaging by 3 points, @samp{5} -- linear averaging by 5 points, and default one -- quadratic averaging by 5 points.
+
+MathGL also have some amazing functions which is not so important for data processing as useful for data plotting. There are functions for finding envelope (useful for plotting rapidly oscillating data), for data sewing (useful to removing jumps on the phase), for data resizing (interpolation). Let me demonstrate it:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(2,2,0,"");  gr->Title("Envelop sample");
+  mglData d1(1000); gr->Fill(d1,"exp(-8*x^2)*sin(10*pi*x)");
+  gr->Axis();     gr->Plot(d1, "b");
+  d1.Envelop('x');  gr->Plot(d1, "r");
+
+  gr->SubPlot(2,2,1,"");  gr->Title("Smooth sample");
+  mglData y0(30),y1,y2,y3;
+  gr->SetRanges(0,1,0,1);
+  gr->Fill(y0, "0.4*sin(pi*x) + 0.3*cos(1.5*pi*x) - 0.4*sin(2*pi*x)+0.5*rnd");
+
+  y1=y0;  y1.Smooth("x3");
+  y2=y0;  y2.Smooth("x5");
+  y3=y0;  y3.Smooth("x");
+
+  gr->Plot(y0,"{m7}:s", "legend 'none'"); //gr->AddLegend("none","k");
+  gr->Plot(y1,"r", "legend ''3' style'");
+  gr->Plot(y2,"g", "legend ''5' style'");
+  gr->Plot(y3,"b", "legend 'default'");
+  gr->Legend();   gr->Box();
+
+  gr->SubPlot(2,2,2);   gr->Title("Sew sample");
+  mglData d2(100, 100); gr->Fill(d2, "mod((y^2-(1-x)^2)/2,0.1)");
+  gr->Rotate(50, 60);   gr->Light(true);  gr->Alpha(true);
+  gr->Box();            gr->Surf(d2, "b");
+  d2.Sew("xy", 0.1);  gr->Surf(d2, "r");
+
+  gr->SubPlot(2,2,3);   gr->Title("Resize sample (interpolation)");
+  mglData x0(10), v0(10), x1, v1;
+  gr->Fill(x0,"rnd");     gr->Fill(v0,"rnd");
+  x1 = x0.Resize(100);    v1 = v0.Resize(100);
+  gr->Plot(x0,v0,"b+ ");  gr->Plot(x1,v1,"r-");
+  gr->Label(x0,v0,"%n");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{dat_extra, Example of data manipulation}
+
+Also one can create new data arrays on base of the existing one: extract slice, row or column of data (@ref{subdata}), summarize along a direction(s) (@ref{sum}), find distribution of data elements (@ref{hist}) and so on.
+
+ at anchor{Solve sample}
+Another interesting feature of MathGL is interpolation and root-finding. There are several functions for linear and cubic spline interpolation (see @ref{Interpolation}). Also there is a function @ref{evaluate} which do interpolation of data array for values of each data element of index data. It look as indirect access to the data elements.
+
+This function have inverse function @ref{solve} which find array of indexes at which data array is equal to given value (i.e. work as root finding). But @ref{solve} function have the issue -- usually multidimensional data (2d and 3d ones) have an infinite number of indexes which give some value. This is contour lines for 2d data, or isosurface(s) for 3d data. So, @ref{solve} function will return index only in given direction, assuming that other index(es) are the same as equidistant inde [...]
+
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SetRange('z',0,1);
+  mglData x(20,30), y(20,30), z(20,30), xx,yy,zz;
+  gr->Fill(x,"(x+2)/3*cos(pi*y)");
+  gr->Fill(y,"(x+2)/3*sin(pi*y)");
+  gr->Fill(z,"exp(-6*x^2-2*sin(pi*y)^2)");
+
+  gr->SubPlot(2,1,0); gr->Title("Cartesian space");   gr->Rotate(30,-40);
+  gr->Axis("xyzU");   gr->Box();  gr->Label('x',"x"); gr->Label('y',"y");
+  gr->SetOrigin(1,1); gr->Grid("xy");
+  gr->Mesh(x,y,z);
+
+  // section along 'x' direction
+  mglData u = x.Solve(0.5,'x');
+  mglData v(u.nx);  v.Fill(0,1);
+  xx = x.Evaluate(u,v);   yy = y.Evaluate(u,v);   zz = z.Evaluate(u,v);
+  gr->Plot(xx,yy,zz,"k2o");
+
+  // 1st section along 'y' direction
+  mglData u1 = x.Solve(-0.5,'y');
+  mglData v1(u1.nx);  v1.Fill(0,1);
+  xx = x.Evaluate(v1,u1); yy = y.Evaluate(v1,u1); zz = z.Evaluate(v1,u1);
+  gr->Plot(xx,yy,zz,"b2^");
+
+  // 2nd section along 'y' direction
+  mglData u2 = x.Solve(-0.5,'y',u1);
+  xx = x.Evaluate(v1,u2); yy = y.Evaluate(v1,u2); zz = z.Evaluate(v1,u2);
+  gr->Plot(xx,yy,zz,"r2v");
+
+  gr->SubPlot(2,1,1); gr->Title("Accompanied space");
+  gr->SetRanges(0,1,0,1); gr->SetOrigin(0,0);
+  gr->Axis(); gr->Box();  gr->Label('x',"i"); gr->Label('y',"j");
+  gr->Grid(z,"h");
+
+  gr->Plot(u,v,"k2o");    gr->Line(mglPoint(0.4,0.5),mglPoint(0.8,0.5),"kA");
+  gr->Plot(v1,u1,"b2^");  gr->Line(mglPoint(0.5,0.15),mglPoint(0.5,0.3),"bA");
+  gr->Plot(v1,u2,"r2v");  gr->Line(mglPoint(0.5,0.7),mglPoint(0.5,0.85),"rA");
+}
+ at end verbatim
+
+ at pfig{solve, Example of data interpolation and root finding}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Data plotting, 1D samples, Data handling, Examples
+ at section Data plotting
+ at nav{}
+
+Let me now show how to plot the data. Next section will give much more examples for all plotting functions. Here I just show some basics. MathGL generally has 2 types of plotting functions. Simple variant requires a single data array for plotting, other data (coordinates) are considered uniformly distributed in axis range. Second variant requires data arrays for all coordinates. It allows one to plot rather complex multivalent curves and surfaces (in case of parametric dependencies). Usu [...]
+
+Note, that the call of drawing function adds something to picture but does not clear the previous plots (as it does in Matlab). Another difference from Matlab is that all setup (like transparency, lightning, axis borders and so on) must be specified @strong{before} plotting functions.
+
+Let start for plots for 1D data. Term ``1D data'' means that data depend on single index (parameter) like curve in parametric form @{x(i),y(i),z(i)@}, i=1...n. The textual argument allow you specify styles of line and marks (see @ref{Line styles}). If this parameter is @code{NULL} or empty then solid line with color from palette is used (see @ref{Palette and colors}).
+
+Below I shall show the features of 1D plotting on base of @ref{plot} function. Let us start from sinus plot:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y0(50); 	y0.Modify("sin(pi*(2*x-1))");
+  gr->SubPlot(2,2,0);
+  gr->Plot(y0);   	gr->Box();
+ at end verbatim
+Style of line is not specified in @ref{plot} function. So MathGL uses the solid line with first color of palette (this is blue). Next subplot shows array @var{y1} with 2 rows:
+ at verbatim
+  gr->SubPlot(2,2,1);
+  mglData y1(50,2);
+  y1.Modify("sin(pi*2*x-pi)");
+  y1.Modify("cos(pi*2*x-pi)/2",1);
+  gr->Plot(y1);   	gr->Box();
+ at end verbatim
+As previously I did not specify the style of lines. As a result, MathGL again uses solid line with next colors in palette (there are green and red). Now let us plot a circle on the same subplot. The circle is parametric curve @math{x=cos(\pi t), y=sin(\pi t)}. I will set the color of the circle (dark yellow, @samp{Y}) and put marks @samp{+} at point position:
+ at verbatim
+  mglData x(50);  	x.Modify("cos(pi*2*x-pi)");
+  gr->Plot(x,y0,"Y+");
+ at end verbatim
+Note that solid line is used because I did not specify the type of line. The same picture can be achieved by @ref{plot} and @ref{subdata} functions. Let us draw ellipse by orange dash line:
+ at verbatim
+  gr->Plot(y1.SubData(-1,0),y1.SubData(-1,1),"q|");
+ at end verbatim
+
+Drawing in 3D space is mostly the same. Let us draw spiral with default line style. Now its color is 4-th color from palette (this is cyan):
+ at verbatim
+  gr->SubPlot(2,2,2);	gr->Rotate(60,40);
+  mglData z(50);  	z.Modify("2*x-1");
+  gr->Plot(x,y0,z);	gr->Box();
+ at end verbatim
+Functions @ref{plot} and @ref{subdata} make 3D curve plot but for single array. Use it to put circle marks on the previous plot:
+ at verbatim
+  mglData y2(10,3);	y2.Modify("cos(pi*(2*x-1+y))");
+  y2.Modify("2*x-1",2);
+  gr->Plot(y2.SubData(-1,0),y2.SubData(-1,1),y2.SubData(-1,2),"bo ");
+ at end verbatim
+Note that line style is empty @samp{ } here. Usage of other 1D plotting functions looks similar:
+ at verbatim
+  gr->SubPlot(2,2,3);	gr->Rotate(60,40);
+  gr->Bars(x,y0,z,"r");	gr->Box();
+  return 0;
+}
+ at end verbatim
+
+Surfaces @ref{surf} and other 2D plots (@pxref{2D plotting}) are drown the same simpler as 1D one. The difference is that the string parameter specifies not the line style but the color scheme of the plot (see @ref{Color scheme}). Here I draw attention on 4 most interesting color schemes. There is gray scheme where color is changed from black to white (string @samp{kw}) or from white to black (string @samp{wk}). Another scheme is useful for accentuation of negative (by blue color) and po [...]
+
+Now I shall show the example of a surface drawing. At first let us switch lightning on
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->Light(true);	gr->Light(0,mglPoint(0,0,1));
+ at end verbatim
+and draw the surface, considering coordinates x,y to be uniformly distributed in axis range
+ at verbatim
+  mglData a0(50,40);
+  a0.Modify("0.6*sin(2*pi*x)*sin(3*pi*y)+0.4*cos(3*pi*(x*y))");
+  gr->SubPlot(2,2,0);	gr->Rotate(60,40);
+  gr->Surf(a0);		gr->Box();
+ at end verbatim
+Color scheme was not specified. So previous color scheme is used. In this case it is default color scheme (``jet'') for the first plot. Next example is a sphere. The sphere is parametrically specified surface:
+ at verbatim
+  mglData x(50,40),y(50,40),z(50,40);
+  x.Modify("0.8*sin(2*pi*x)*sin(pi*y)");
+  y.Modify("0.8*cos(2*pi*x)*sin(pi*y)");
+  z.Modify("0.8*cos(pi*y)");
+  gr->SubPlot(2,2,1);	gr->Rotate(60,40);
+  gr->Surf(x,y,z,"BbwrR");gr->Box();
+ at end verbatim
+I set color scheme to @code{"BbwrR"} that corresponds to red top and blue bottom of the sphere.
+
+Surfaces will be plotted for each of slice of the data if @var{nz}>1. Next example draws surfaces for data arrays with @var{nz}=3:
+ at verbatim
+  mglData a1(50,40,3);
+  a1.Modify("0.6*sin(2*pi*x)*sin(3*pi*y)+0.4*cos(3*pi*(x*y))");
+  a1.Modify("0.6*cos(2*pi*x)*cos(3*pi*y)+0.4*sin(3*pi*(x*y))",1);
+  a1.Modify("0.6*cos(2*pi*x)*cos(3*pi*y)+0.4*cos(3*pi*(x*y))",2);
+  gr->SubPlot(2,2,2);	gr->Rotate(60,40);
+  gr->Alpha(true);
+  gr->Surf(a1);		gr->Box();
+ at end verbatim
+Note, that it may entail a confusion. However, if one will use density plot then the picture will look better:
+ at verbatim
+  gr->SubPlot(2,2,3);	gr->Rotate(60,40);
+  gr->Dens(a1);		gr->Box();
+  return 0;
+}
+ at end verbatim
+
+Drawing of other 2D plots is analogous. The only peculiarity is the usage of flag @samp{#}. By default this flag switches on the drawing of a grid on plot (@ref{grid} or @ref{mesh} for plots in plain or in volume). However, for isosurfaces (including surfaces of rotation @ref{axial}) this flag switches the  face drawing off and figure becomes wired. The following code gives example of flag @samp{#} using (compare with normal function drawing as in its description):
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->Alpha(true);	gr->Light(true);	gr->Light(0,mglPoint(0,0,1));
+  mglData a(30,20);
+  a.Modify("0.6*sin(2*pi*x)*sin(3*pi*y) + 0.4*cos(3*pi*(x*y))");
+
+  gr->SubPlot(2,2,0);	gr->Rotate(40,60);
+  gr->Surf(a,"BbcyrR#");		gr->Box();
+  gr->SubPlot(2,2,1);	gr->Rotate(40,60);
+  gr->Dens(a,"BbcyrR#");		gr->Box();
+  gr->SubPlot(2,2,2);	gr->Rotate(40,60);
+  gr->Cont(a,"BbcyrR#");		gr->Box();
+  gr->SubPlot(2,2,3);	gr->Rotate(40,60);
+  gr->Axial(a,"BbcyrR#");		gr->Box();
+  return 0;
+}
+ at end verbatim
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node 1D samples, 2D samples, Data plotting, Examples
+ at section 1D samples
+ at nav{}
+
+This section is devoted to visualization of 1D data arrays. 1D means the data which depend on single index (parameter) like curve in parametric form @{x(i),y(i),z(i)@}, i=1...n. Most of samples will use the same data for plotting. So, I put its initialization in separate function
+ at verbatim
+void mgls_prepare1d(mglData *y, mglData *y1=0, mglData *y2=0, mglData *x1=0, mglData *x2=0)
+{
+  register long i,n=50;
+  if(y) y->Create(n,3);
+  if(x1)  x1->Create(n);    if(x2)  x2->Create(n);
+  if(y1)  y1->Create(n);    if(y2)  y2->Create(n);
+  mreal xx;
+  for(i=0;i<n;i++)
+  {
+    xx = i/(n-1.);
+    if(y)
+    {
+      y->a[i] = 0.7*sin(2*M_PI*xx) + 0.5*cos(3*M_PI*xx) + 0.2*sin(M_PI*xx);
+      y->a[i+n] = sin(2*M_PI*xx);
+      y->a[i+2*n] = cos(2*M_PI*xx);
+    }
+    if(y1)  y1->a[i] = 0.5+0.3*cos(2*M_PI*xx);
+    if(y2)  y2->a[i] = 0.3*sin(2*M_PI*xx);
+    if(x1)  x1->a[i] = xx*2-1;
+    if(x2)  x2->a[i] = 0.05+0.03*cos(2*M_PI*xx);
+  }
+}
+ at end verbatim
+or using C functions
+ at verbatim
+void mgls_prepare1d(HMDT y, HMDT y1=0, HMDT y2=0, HMDT x1=0, HMDT x2=0)
+{
+  register long i,n=50;
+  if(y)   mgl_data_create(y,n,3,1);
+  if(x1)  mgl_data_create(x1,n,1,1);
+  if(x2)  mgl_data_create(x2,n,1,1);
+  if(y1)  mgl_data_create(y1,n,1,1);
+  if(y2)  mgl_data_create(y2,n,1,1);
+  mreal xx;
+  for(i=0;i<n;i++)
+  {
+    xx = i/(n-1.);
+    if(y)
+    {
+      mgl_data_set_value(y, 0.7*sin(2*M_PI*xx) + 0.5*cos(3*M_PI*xx) + 0.2*sin(M_PI*xx), i,0,0);
+      mgl_data_set_value(y, sin(2*M_PI*xx), i,1,0);
+      mgl_data_set_value(y, cos(2*M_PI*xx), i,2,0);
+    }
+    if(y1)  mgl_data_set_value(y1, 0.5+0.3*cos(2*M_PI*xx), i,0,0);
+    if(y2)  mgl_data_set_value(y2, 0.3*sin(2*M_PI*xx), i,0,0);
+    if(x1)  mgl_data_set_value(x1, xx*2-1, i,0,0);
+    if(x2)  mgl_data_set_value(x2, 0.05+0.03*cos(2*M_PI*xx), i,0,0);
+  }
+}
+ at end verbatim
+
+ at menu
+* Plot sample::
+* Radar sample::
+* Step sample::
+* Tens sample::
+* Area sample::
+* Region sample::
+* Stem sample::
+* Bars sample::
+* Barh sample::
+* Cones sample::
+* Chart sample::
+* BoxPlot sample::
+* Candle sample::
+* OHLC sample::
+* Error sample::
+* Mark sample::
+* TextMark sample::
+* Label sample::
+* Table sample::
+* Iris sample::
+* Tube sample::
+* Tape sample::
+* Torus sample::
+* Lamerey sample::
+* Bifurcation sample::
+* Pmap sample::
+ at end menu
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Plot sample, Radar sample, , 1D samples
+ at subsection Plot sample
+ at nav{}
+
+Function @ref{plot} is most standard way to visualize 1D data array. By default, @code{Plot} use colors from palette. However, you can specify manual color/palette, and even set to use new color for each points by using @samp{!} style. Another feature is @samp{ } style which draw only markers without line between points. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y;  mgls_prepare1d(&y); gr->SetOrigin(0,0,0);
+  gr->SubPlot(2,2,0,"");  gr->Title("Plot plot (default)");
+  gr->Box();  gr->Plot(y);
+
+  gr->SubPlot(2,2,2,"");  gr->Title("'!' style; 'rgb' palette");
+  gr->Box();  gr->Plot(y,"o!rgb");
+
+  gr->SubPlot(2,2,3,"");  gr->Title("just markers");
+  gr->Box();  gr->Plot(y," +");
+
+  gr->SubPlot(2,2,1); gr->Title("3d variant");
+  gr->Rotate(50,60);  gr->Box();
+  mglData yc(30), xc(30), z(30);  z.Modify("2*x-1");
+  yc.Modify("sin(pi*(2*x-1))"); xc.Modify("cos(pi*2*x-pi)");
+  gr->Plot(xc,yc,z,"rs");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{plot, Example of Plot()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Radar sample, Step sample, Plot sample, 1D samples
+ at subsection Radar sample
+ at nav{}
+
+Function @ref{radar} plot is variant of @code{Plot} one, which make plot in polar coordinates and draw radial rays in point directions. If you just need a plot in polar coordinates then I recommend to use @ref{Curvilinear coordinates} or @code{Plot} in parabolic form with @code{x=r*cos(fi); y=r*sin(fi);}. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData yr(10,3); yr.Modify("0.4*sin(pi*(2*x+y))+0.1*rnd");
+  gr->SubPlot(1,1,0,"");  gr->Title("Radar plot (with grid, '\\#')");
+  gr->Radar(yr,"#");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{radar, Example of Radar()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Step sample, Tens sample, Radar sample, 1D samples
+ at subsection Step sample
+ at nav{}
+
+Function @ref{step} plot data as stairs. It have the same options as @code{Plot}. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y;  mgls_prepare1d(&y); gr->SetOrigin(0,0,0);
+  mglData yc(30), xc(30), z(30);  z.Modify("2*x-1");
+  yc.Modify("sin(pi*(2*x-1))"); xc.Modify("cos(pi*2*x-pi)");
+
+  gr->SubPlot(2,2,0,"");  gr->Title("Step plot (default)");
+  gr->Box();  gr->Step(y);
+
+  gr->SubPlot(2,2,1); gr->Title("3d variant");  gr->Rotate(50,60);
+  gr->Box();  gr->Step(xc,yc,z,"r");
+
+  gr->SubPlot(2,2,2,"");  gr->Title("'!' style");
+  gr->Box();  gr->Step(y,"s!rgb");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{step, Example of Step()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Tens sample, Area sample, Step sample, 1D samples
+ at subsection Tens sample
+ at nav{}
+
+Function @ref{tens} is variant of @ref{plot} with smooth coloring along the curves. At this, color is determined as for surfaces (see @ref{Color scheme}). The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y;  mgls_prepare1d(&y); gr->SetOrigin(0,0,0);
+  gr->SubPlot(2,2,0,"");  gr->Title("Tens plot (default)");
+  gr->Box();  gr->Tens(y.SubData(-1,0), y.SubData(-1,1));
+
+  gr->SubPlot(2,2,2,"");  gr->Title("' ' style");
+  gr->Box();  gr->Tens(y.SubData(-1,0), y.SubData(-1,1),"o ");
+
+  gr->SubPlot(2,2,1); gr->Title("3d variant");  gr->Rotate(50,60);  gr->Box();
+  mglData yc(30), xc(30), z(30);  z.Modify("2*x-1");
+  yc.Modify("sin(pi*(2*x-1))"); xc.Modify("cos(pi*2*x-pi)");
+  gr->Tens(xc,yc,z,z,"s");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{tens, Example of Tens()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Area sample, Region sample, Tens sample, 1D samples
+ at subsection Area sample
+ at nav{}
+
+Function @ref{area} fill the area between curve and axis plane. It support gradient filling if 2 colors per curve is specified. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y;  mgls_prepare1d(&y); gr->SetOrigin(0,0,0);
+  gr->SubPlot(2,2,0,"");  gr->Title("Area plot (default)");
+  gr->Box();  gr->Area(y);
+
+  gr->SubPlot(2,2,1,"");  gr->Title("2 colors");
+  gr->Box();  gr->Area(y,"cbgGyr");
+
+  gr->SubPlot(2,2,2,"");  gr->Title("'!' style");
+  gr->Box();  gr->Area(y,"!");
+
+  gr->SubPlot(2,2,3); gr->Title("3d variant");
+  gr->Rotate(50,60);  gr->Box();
+  mglData yc(30), xc(30), z(30);  z.Modify("2*x-1");
+  yc.Modify("sin(pi*(2*x-1))"); xc.Modify("cos(pi*2*x-pi)");
+  gr->Area(xc,yc,z,"r");
+  yc.Modify("-sin(pi*(2*x-1))");  gr->Area(xc,yc,z,"b#");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{area, Example of Area()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Region sample, Stem sample, Area sample, 1D samples
+ at subsection Region sample
+ at nav{}
+
+Function @ref{region} fill the area between 2 curves. It support gradient filling if 2 colors per curve is specified. Also it can fill only the region y1<y<y2 if style @samp{i} is used. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y;  mgls_prepare1d(&y);
+  mglData y1 = y.SubData(-1,1), y2 = y.SubData(-1,2);  gr->SetOrigin(0,0,0);
+
+  gr->SubPlot(2,2,0,"");  gr->Title("Region plot (default)"); gr->Box();
+  gr->Region(y1,y2);  gr->Plot(y1,"k2");  gr->Plot(y2,"k2");
+
+  gr->SubPlot(2,2,1,"");  gr->Title("2 colors");  gr->Box();
+  gr->Region(y1,y2,"yr"); gr->Plot(y1,"k2");  gr->Plot(y2,"k2");
+
+  gr->SubPlot(2,2,2,"");  gr->Title("'i' style");  gr->Box();
+  gr->Region(y1,y2,"ir"); gr->Plot(y1,"k2");  gr->Plot(y2,"k2");
+
+  gr->SubPlot(2,2,3,"^_");  gr->Title("3d variant");  gr->Rotate(40,60);  gr->Box();
+  gr->Fill(y1,"cos(pi*x)"); gr->Fill(y2,"cos(pi*x+pi/3)");
+  mglData x1(y1.nx), x2(y1.nx), z(y1.nx);
+  gr->Fill(x1,"sin(pi*x)"); gr->Fill(x2,"sin(pi*x+pi/3)");  gr->Fill(z,"x");
+  gr->Plot(x1,y1,z,"r2");   gr->Plot(x2,y2,z,"b2");
+  gr->Region(x1,y1,z,x2,y2,z,"cmy!");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{region, Example of Region()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Stem sample, Bars sample, Region sample, 1D samples
+ at subsection Stem sample
+ at nav{}
+
+Function @ref{stem} draw vertical bars. It is most attractive if markers are drawn too. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y;  mgls_prepare1d(&y); gr->SetOrigin(0,0,0);
+  mglData yc(30), xc(30), z(30);  z.Modify("2*x-1");
+  yc.Modify("sin(pi*(2*x-1))"); xc.Modify("cos(pi*2*x-pi)");
+  gr->SubPlot(2,2,0,"");  gr->Title("Stem plot (default)");
+  gr->Box();  gr->Stem(y);
+
+  gr->SubPlot(2,2,1); gr->Title("3d variant");  gr->Rotate(50,60);
+  gr->Box();  gr->Stem(xc,yc,z,"rx");
+
+  gr->SubPlot(2,2,2,"");  gr->Title("'!' style");
+  gr->Box();  gr->Stem(y,"o!rgb");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{stem, Example of Stem()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Bars sample, Barh sample, Stem sample, 1D samples
+ at subsection Bars sample
+ at nav{}
+
+Function @ref{bars} draw vertical bars. It have a lot of options: bar-above-bar (@samp{a} style), fall like (@samp{f} style), 2 colors for positive and negative values, wired bars (@samp{#} style), 3D variant. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData ys(10,3); ys.Modify("0.8*sin(pi*(2*x+y/2))+0.2*rnd");
+  gr->SetOrigin(0,0,0);
+  gr->SubPlot(3,2,0,"");  gr->Title("Bars plot (default)");
+  gr->Box();  gr->Bars(ys);
+
+  gr->SubPlot(3,2,1,"");  gr->Title("2 colors");
+  gr->Box();  gr->Bars(ys,"cbgGyr");
+
+  gr->SubPlot(3,2,4,"");  gr->Title("'\\#' style");
+  gr->Box();  gr->Bars(ys,"#");
+
+  gr->SubPlot(3,2,5); gr->Title("3d variant");
+  gr->Rotate(50,60);  gr->Box();
+  mglData yc(30), xc(30), z(30);  z.Modify("2*x-1");
+  yc.Modify("sin(pi*(2*x-1))"); xc.Modify("cos(pi*2*x-pi)");
+  gr->Bars(xc,yc,z,"r");
+
+  gr->SetRanges(-1,1,-3,3);
+  gr->SubPlot(3,2,2,"");  gr->Title("'a' style");
+  gr->Box();  gr->Bars(ys,"a");
+
+  gr->SubPlot(3,2,3,"");  gr->Title("'f' style");
+  gr->Box();  gr->Bars(ys,"f");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{bars, Example of Bars()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Barh sample, Cones sample, Bars sample, 1D samples
+ at subsection Barh sample
+ at nav{}
+
+Function @ref{barh} is the similar to @code{Bars} but draw horizontal bars. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData ys(10,3); ys.Modify("0.8*sin(pi*(2*x+y/2))+0.2*rnd");
+  gr->SetOrigin(0,0,0);
+  gr->SubPlot(2,2,0,"");  gr->Title("Barh plot (default)");
+  gr->Box();  gr->Barh(ys);
+
+  gr->SubPlot(2,2,1,"");  gr->Title("2 colors");
+  gr->Box();  gr->Barh(ys,"cbgGyr");
+
+  gr->SetRanges(-3,3,-1,1);
+  gr->SubPlot(2,2,2,"");  gr->Title("'a' style");
+  gr->Box();  gr->Barh(ys,"a");
+
+  gr->SubPlot(2,2,3,"");  gr->Title("'f' style");
+  gr->Box();  gr->Barh(ys,"f");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{barh, Example of Barh()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cones sample, Chart sample, Barh sample, 1D samples
+ at subsection Cones sample
+ at nav{}
+
+Function @ref{cones} is similar to @code{Bars} but draw cones. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData ys(10,3);   ys.Modify("0.8*sin(pi*(2*x+y/2))+0.2*rnd");
+  gr->Light(true);    gr->SetOrigin(0,0,0);
+  gr->SubPlot(3,2,0); gr->Title("Cones plot");
+  gr->Rotate(50,60);  gr->Box();  gr->Cones(ys);
+
+  gr->SubPlot(3,2,1); gr->Title("2 colors");
+  gr->Rotate(50,60);  gr->Box();  gr->Cones(ys,"cbgGyr");
+
+  gr->SubPlot(3,2,2); gr->Title("'#' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Cones(ys,"#");
+
+  gr->SubPlot(3,2,3); gr->Title("'a' style");
+  gr->SetRange('z',-2,2); // increase range since summation can exceed [-1,1]
+  gr->Rotate(50,60);  gr->Box();  gr->Cones(ys,"a");
+
+  gr->SubPlot(3,2,4); gr->Title("'t' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Cones(ys,"t");
+
+  gr->SubPlot(3,2,5); gr->Title("'4' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Cones(ys,"4");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{cones, Example of Cones()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Chart sample, BoxPlot sample, Cones sample, 1D samples
+ at subsection Chart sample
+ at nav{}
+
+Function @ref{chart} draw colored boxes with width proportional to data values. Use @samp{ } for empty box. Plot looks most attractive in polar coordinates -- well known pie chart. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData ch(7,2);  for(int i=0;i<7*2;i++)  ch.a[i]=mgl_rnd()+0.1;
+  gr->SubPlot(2,2,0); gr->Title("Chart plot (default)");
+  gr->Light(true);  gr->Rotate(50,60);  gr->Box();  gr->Chart(ch);
+
+  gr->SubPlot(2,2,1); gr->Title("'\\#' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Chart(ch,"#");
+
+  gr->SubPlot(2,2,2); gr->Title("Pie chart; ' ' color");
+  gr->SetFunc("(y+1)/2*cos(pi*x)","(y+1)/2*sin(pi*x)","");
+  gr->Rotate(50,60);  gr->Box();  gr->Chart(ch,"bgr cmy#");
+
+  gr->SubPlot(2,2,3); gr->Title("Ring chart; ' ' color");
+  gr->SetFunc("(y+2)/3*cos(pi*x)","(y+2)/3*sin(pi*x)","");
+  gr->Rotate(50,60);  gr->Box();  gr->Chart(ch,"bgr cmy#");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{chart, Example of Chart()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node BoxPlot sample, Candle sample, Chart sample, 1D samples
+ at subsection BoxPlot sample
+ at nav{}
+
+Function @ref{boxplot} draw box-and-whisker diagram. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a(10,7);  a.Modify("(2*rnd-1)^3/2");
+  gr->SubPlot(1,1,0,"");  gr->Title("Boxplot plot");
+  gr->Box();  gr->BoxPlot(a);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{boxplot, Example of BoxPlot()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Candle sample, OHLC sample, BoxPlot sample, 1D samples
+ at subsection Candle sample
+ at nav{}
+
+Function @ref{candle} draw candlestick chart. This is a combination of a line-chart and a bar-chart, in that each bar represents the range of price movement over a given time interval. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y(30);  gr->Fill(y,"sin(pi*x/2)^2");
+  mglData y1(30); gr->Fill(y1,"v/2",y);
+  mglData y2(30); gr->Fill(y2,"(1+v)/2",y);
+  gr->SubPlot(1,1,0,"");  gr->Title("Candle plot (default)");
+  gr->SetRange('y',0,1);  gr->Box();  gr->Candle(y,y1,y2);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{candle, Example of Candle()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node OHLC sample, Error sample, Candle sample, 1D samples
+ at subsection OHLC sample
+ at nav{}
+
+Function @ref{ohlc} draw Open-High-Low-Close diagram. This diagram show vertical line for between maximal(high) and minimal(low) values, as well as horizontal lines before/after vertical line for initial(open)/final(close) values of some process. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData o(10), h(10), l(10), c(10);
+  gr->Fill(o,"0.5*sin(pi*x)");  gr->Fill(c,"0.5*sin(pi*(x+2/9))");
+  gr->Fill(l,"0.3*rnd-0.8");    gr->Fill(h,"0.3*rnd+0.5");
+  gr->SubPlot(1,1,0,"");  gr->Title("OHLC plot");
+  gr->Box();  gr->OHLC(o,h,l,c);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{ohlc, Example of OHLC()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Error sample, Mark sample, OHLC sample, 1D samples
+ at subsection Error sample
+ at nav{}
+
+Function @ref{error} draw error boxes around the points. You can draw default boxes or semi-transparent symbol (like marker, see @ref{Line styles}). Also you can set individual color for each box. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y;  mgls_prepare1d(&y);
+  mglData x0(10), y0(10), ex0(10), ey0(10);
+  mreal x;
+  for(int i=0;i<10;i++)
+  {
+    x = i/9.;
+    x0.a[i] = 2*x-1 + 0.1*mgl_rnd()-0.05;
+    y0.a[i] = 0.7*sin(2*M_PI*x)+0.5*cos(3*M_PI*x)+0.2*sin(M_PI*x)+0.2*mgl_rnd()-0.1;
+    ey0.a[i]=0.2; ex0.a[i]=0.1;
+  }
+
+  gr->SubPlot(2,2,0,"");  gr->Title("Error plot (default)");
+  gr->Box();  gr->Plot(y.SubData(-1,0));  gr->Error(x0,y0,ex0,ey0,"ko");
+
+  gr->SubPlot(2,2,1,"");  gr->Title("'!' style; no e_x");
+  gr->Box();  gr->Plot(y.SubData(-1,0));  gr->Error(x0,y0,ey0,"o!rgb");
+
+  gr->SubPlot(2,2,2,"");  gr->Title("'\\@' style");
+  gr->Box();  gr->Plot(y.SubData(-1,0));  gr->Error(x0,y0,ex0,ey0,"@","alpha 0.5");
+
+  gr->SubPlot(2,2,3); gr->Title("3d variant");  gr->Rotate(50,60);
+  for(int i=0;i<10;i++)
+    gr->Error(mglPoint(2*mgl_rnd()-1,2*mgl_rnd()-1,2*mgl_rnd()-1),
+              mglPoint(0.2,0.2,0.2),"bo");
+  gr->Axis();
+  return 0;
+}
+ at end verbatim
+
+ at pfig{error, Example of Error()}
+
+Additionally, you can use solid large "marks" instead of error boxes by selecting proper style.
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData x0(10), y0(10), ex(10), ey(10);
+  for(int i=0;i<10;i++)
+  {  x0.a[i] = mgl_rnd(); y0.a[i] = mgl_rnd(); ey.a[i] = ex.a[i] = 0.1; }
+  gr->SetRanges(0,1,0,1); gr->Alpha(true);
+  gr->SubPlot(4,3,0,"");  gr->Box(); gr->Error(x0,y0,ex,ey,"#+@");
+  gr->SubPlot(4,3,1,"");  gr->Box(); gr->Error(x0,y0,ex,ey,"#x@");
+  gr->SubPlot(4,3,2,"");  gr->Box(); gr->Error(x0,y0,ex,ey,"#s@","alpha 0.5");
+  gr->SubPlot(4,3,3,"");  gr->Box(); gr->Error(x0,y0,ex,ey,"s@");
+  gr->SubPlot(4,3,4,"");  gr->Box(); gr->Error(x0,y0,ex,ey,"d@");
+  gr->SubPlot(4,3,5,"");  gr->Box(); gr->Error(x0,y0,ex,ey,"#d@","alpha 0.5");
+  gr->SubPlot(4,3,6,"");  gr->Box(); gr->Error(x0,y0,ex,ey,"+@");
+  gr->SubPlot(4,3,7,"");  gr->Box(); gr->Error(x0,y0,ex,ey,"x@");
+  gr->SubPlot(4,3,8,"");  gr->Box(); gr->Error(x0,y0,ex,ey,"o@");
+  gr->SubPlot(4,3,9,"");  gr->Box(); gr->Error(x0,y0,ex,ey,"#o@","alpha 0.5");
+  gr->SubPlot(4,3,10,""); gr->Box(); gr->Error(x0,y0,ex,ey,"#.@");
+  gr->SubPlot(4,3,11,""); gr->Box(); gr->Error(x0,y0,ex,ey);
+}
+ at end verbatim
+
+ at pfig{error2, Example of Error() with marks}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Mark sample, TextMark sample, Error sample, 1D samples
+ at subsection Mark sample
+ at nav{}
+
+Function @ref{mark} draw markers at points. It is mostly the same as @code{Plot} but marker size can be variable. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y,y1; mgls_prepare1d(&y,&y1);
+  gr->SubPlot(1,1,0,"");  gr->Title("Mark plot (default)");
+  gr->Box();  gr->Mark(y,y1,"s");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{mark, Example of Mark()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node TextMark sample, Label sample, Mark sample, 1D samples
+ at subsection TextMark sample
+ at nav{}
+
+Function @ref{textmark} like @code{Mark} but draw text instead of markers. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y,y1; mgls_prepare1d(&y,&y1);
+  gr->SubPlot(1,1,0,"");  gr->Title("TextMark plot (default)");
+  gr->Box();  gr->TextMark(y,y1,"\\gamma","r");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{textmark, Example of TextMark()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Label sample, Table sample, TextMark sample, 1D samples
+ at subsection Label sample
+ at nav{}
+
+Function @ref{label} print text at data points. The string may contain @samp{%x}, @samp{%y}, @samp{%z} for x-, y-, z-coordinates of points, @samp{%n} for point index. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData ys(10); ys.Modify("0.8*sin(pi*2*x)+0.2*rnd");
+  gr->SubPlot(1,1,0,"");  gr->Title("Label plot");
+  gr->Box();  gr->Plot(ys," *");  gr->Label(ys,"y=%y");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{label, Example of Label()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Table sample, Iris sample, Label sample, 1D samples
+ at subsection Table sample
+ at nav{}
+
+Function @ref{table} draw table with data values. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData ys(10,3); ys.Modify("0.8*sin(pi*(2*x+y/2))+0.2*rnd");
+  gr->SubPlot(2,2,0);  gr->Title("Table plot");
+  gr->Table(ys,"y_1\ny_2\ny_3");   gr->Box();
+  gr->SubPlot(2,2,1);  gr->Title("no borders, colored");
+  gr->Table(ys,"y_1\ny_2\ny_3","r|");
+  gr->SubPlot(2,2,2);  gr->Title("no font decrease");
+  gr->Table(ys,"y_1\ny_2\ny_3","#");
+  gr->SubPlot(2,2,3);  gr->Title("manual width, position");
+  gr->Table(0.5, 0.95, ys,"y_1\ny_2\ny_3","#", "value 0.7");  gr->Box();
+  return 0;
+}
+ at end verbatim
+
+ at pfig{table, Example of Table()}
+
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Iris sample, Tube sample, Table sample, 1D samples
+ at subsection Iris sample
+ at nav{}
+
+Command @ref{iris} draw Iris plot for columns of data array. The sample code is:
+ at verbatim
+  mglData a("iris.dat");  a.Crop(0,4,'x');  a.Rearrange(4,50);
+  gr->SubPlot(1,1,0,"");
+  if(big!=3)	gr->Title("Iris sample");
+  gr->Iris(a, "sepal\nlength;sepal\nwidth;petal\nlength;petal\nwidth", ". ", "value -1.5;size -2");
+ at end verbatim
+
+ at pfig{iris, Example of Iris()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Tube sample, Tape sample, Iris sample, 1D samples
+ at subsection Tube sample
+ at nav{}
+
+Function @ref{tube} draw tube with variable radius. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y,y1,y2;  mgls_prepare1d(&y,&y1,&y2); y1/=20;
+  gr->SubPlot(2,2,0,"");  gr->Title("Tube plot (default)");
+  gr->Light(true);  gr->Box();  gr->Tube(y,0.05);
+
+  gr->SubPlot(2,2,1,"");  gr->Title("variable radius");
+  gr->Box();  gr->Tube(y,y1);
+
+  gr->SubPlot(2,2,2,"");  gr->Title("'\\#' style");
+  gr->Box();  gr->Tube(y,0.05,"#");
+  mglData yc(50), xc(50), z(50);  z.Modify("2*x-1");
+  yc.Modify("sin(pi*(2*x-1))"); xc.Modify("cos(pi*2*x-pi)");
+
+  gr->SubPlot(2,2,3); gr->Title("3d variant");  gr->Rotate(50,60);
+  gr->Box();  gr->Tube(xc,yc,z,y2,"r");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{tube, Example of Tube()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Tape sample, Torus sample, Tube sample, 1D samples
+ at subsection Tape sample
+ at nav{}
+
+Function @ref{tape} draw tapes which rotate around the curve as normal and binormal. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y;  mgls_prepare1d(&y);
+  mglData xc(50), yc(50), z(50);
+  yc.Modify("sin(pi*(2*x-1))");
+  xc.Modify("cos(pi*2*x-pi)");  z.Fill(-1,1);
+  gr->SubPlot(2,2,0,"");  gr->Title("Tape plot (default)");
+  gr->Box();  gr->Tape(y);  gr->Plot(y,"k");
+
+  gr->SubPlot(2,2,1); gr->Title("3d variant, 2 colors");
+  gr->Rotate(50,60);  gr->Light(true);
+  gr->Box();  gr->Plot(xc,yc,z,"k");  gr->Tape(xc,yc,z,"rg");
+
+  gr->SubPlot(2,2,2); gr->Title("3d variant, x only");  gr->Rotate(50,60);
+  gr->Box();  gr->Plot(xc,yc,z,"k");
+  gr->Tape(xc,yc,z,"xr"); gr->Tape(xc,yc,z,"xr#");
+
+  gr->SubPlot(2,2,3); gr->Title("3d variant, z only");  gr->Rotate(50,60);
+  gr->Box();  gr->Plot(xc,yc,z,"k");
+  gr->Tape(xc,yc,z,"zg"); gr->Tape(xc,yc,z,"zg#");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{tape, Example of Tape()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Torus sample, Lamerey sample, Tape sample, 1D samples
+ at subsection Torus sample
+ at nav{}
+
+Function @ref{torus} draw surface of the curve rotation. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y1,y2;  mgls_prepare1d(0,&y1,&y2);
+  gr->SubPlot(2,2,0); gr->Title("Torus plot (default)");
+  gr->Light(true);  gr->Rotate(50,60);  gr->Box();  gr->Torus(y1,y2);
+  if(mini)  return;
+
+  gr->SubPlot(2,2,1); gr->Title("'x' style"); gr->Rotate(50,60);
+  gr->Box();  gr->Torus(y1,y2,"x");
+
+  gr->SubPlot(2,2,2); gr->Title("'z' style"); gr->Rotate(50,60);
+  gr->Box();  gr->Torus(y1,y2,"z");
+
+  gr->SubPlot(2,2,3); gr->Title("'\\#' style"); gr->Rotate(50,60);
+  gr->Box();  gr->Torus(y1,y2,"#");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{torus, Example of Torus()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Lamerey sample, Bifurcation sample, Torus sample, 1D samples
+ at subsection Lamerey sample
+ at nav{}
+
+Function @ref{lamerey} draw Lamerey diagram. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(1,1,0,"<_");
+  gr->Title("Lamerey sample");
+  gr->Axis(); gr->Label('x',"\\i x");
+  gr->Label('y',"\\bar{\\i x} = 2 \\i{x}");
+  gr->FPlot("x","k=");  gr->FPlot("2*x","b");
+  gr->Lamerey( 0.00097,"2*x","rv~");
+  gr->Lamerey(-0.00097,"2*x","rv~");
+}
+ at end verbatim
+
+ at pfig{lamerey, Example of Lamerey()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Bifurcation sample, Pmap sample, Lamerey sample, 1D samples
+ at subsection Bifurcation sample
+ at nav{}
+
+Function @ref{bifurcation} draw Bifurcation diagram for logistic map. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(1,1,0,"<_");
+  gr->Title("Bifurcation sample");
+  gr->SetRanges(0,4,0,1);   gr->Axis();
+  gr->Bifurcation(0.005,"x*y*(1-y)","r");
+}
+ at end verbatim
+
+ at pfig{bifurcation, Example of Bifurcation()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Pmap sample, , Bifurcation sample, 1D samples
+ at subsection Pmap sample
+ at nav{}
+
+Function @ref{pmap} draw Poincare map -- show intersections of the curve and the surface. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(1,1,0,"<_^");
+  gr->Title("Poincare map sample");
+  mglData ini(3);	ini[0]=0.1;
+  mglData r(mglODE("cos(y)+sin(z);cos(z)+sin(x);cos(x)+sin(y)","xyz",ini,0.1,100));
+  mglData x(r.SubData(0)),y(r.SubData(1)), z(r.SubData(2));
+  gr->Rotate(40,60);  gr->SetRanges(x,y,z);
+  gr->Axis(); gr->FSurf("0"); gr->Plot(x,y,z,"b");
+  gr->Label('x',"\\i x",0);   gr->Label('y',"\\i y",0);   gr->Label('z',"\\i z",0);
+  gr->Pmap(x,y,z,z, "b#o");
+}
+ at end verbatim
+
+ at pfig{pmap, Example of Pmap()}
+
+
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node 2D samples, 3D samples, 1D samples, Examples
+ at section 2D samples
+ at nav{}
+
+This section is devoted to visualization of 2D data arrays. 2D means the data which depend on 2 indexes (parameters) like matrix z(i,j)=z(x(i),y(j)), i=1...n, j=1...m or in parametric form @{x(i,j),y(i,j),z(i,j)@}. Most of samples will use the same data for plotting. So, I put its initialization in separate function
+ at verbatim
+void mgls_prepare2d(mglData *a, mglData *b=0, mglData *v=0)
+{
+  register long i,j,n=50,m=40,i0;
+  if(a) a->Create(n,m);   if(b) b->Create(n,m);
+  if(v) { v->Create(9); v->Fill(-1,1);  }
+  mreal x,y;
+  for(i=0;i<n;i++)  for(j=0;j<m;j++)
+  {
+    x = i/(n-1.); y = j/(m-1.); i0 = i+n*j;
+    if(a) a->a[i0] = 0.6*sin(2*M_PI*x)*sin(3*M_PI*y)+0.4*cos(3*M_PI*x*y);
+    if(b) b->a[i0] = 0.6*cos(2*M_PI*x)*cos(3*M_PI*y)+0.4*cos(3*M_PI*x*y);
+  }
+}
+ at end verbatim
+or using C functions
+ at verbatim
+void mgls_prepare2d(HMDT a, HMDT b=0, HMDT v=0)
+{
+  register long i,j,n=50,m=40,i0;
+  if(a) mgl_data_create(a,n,m,1);
+  if(b) mgl_data_create(b,n,m,1);
+  if(v) { mgl_data_create(v,9,1,1); mgl_data_fill(v,-1,1,'x');  }
+  mreal x,y;
+  for(i=0;i<n;i++)  for(j=0;j<m;j++)
+  {
+    x = i/(n-1.); y = j/(m-1.); i0 = i+n*j;
+    if(a) mgl_data_set_value(a, 0.6*sin(2*M_PI*x)*sin(3*M_PI*y)+0.4*cos(3*M_PI*x*y), i,j,0);
+    if(b) mgl_data_set_value(b, 0.6*cos(2*M_PI*x)*cos(3*M_PI*y)+0.4*cos(3*M_PI*x*y), i,j,0);
+  }
+}
+ at end verbatim
+
+ at menu
+* Surf sample::
+* SurfC sample::
+* SurfA sample::
+* SurfCA sample::
+* Mesh sample::
+* Fall sample::
+* Belt sample::
+* Boxs sample::
+* Tile sample::
+* TileS sample::
+* Dens sample::
+* Cont sample::
+* ContF sample::
+* ContD sample::
+* ContV sample::
+* Axial sample::
+* Grad sample::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Surf sample, SurfC sample, , 2D samples
+ at subsection Surf sample
+ at nav{}
+
+Function @ref{surf} is most standard way to visualize 2D data array. @code{Surf} use color scheme for coloring (see @ref{Color scheme}). You can use @samp{#} style for drawing black meshes on the surface. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->SubPlot(2,2,0); gr->Title("Surf plot (default)");
+  gr->Light(true);  gr->Rotate(50,60);  gr->Box();  gr->Surf(a);
+
+  gr->SubPlot(2,2,1); gr->Title("'\\#' style; meshnum 10");
+  gr->Rotate(50,60);  gr->Box();  gr->Surf(a,"#","meshnum 10");
+
+  gr->SubPlot(2,2,2); gr->Title("'.' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Surf(a,".");
+
+  gr->SubPlot(2,2,3); gr->Title("parametric form");
+  mglData x(50,40),y(50,40),z(50,40);
+  gr->Fill(x,"0.8*sin(pi*x)*sin(pi*(y+1)/2)");
+  gr->Fill(y,"0.8*cos(pi*x)*sin(pi*(y+1)/2)");
+  gr->Fill(z,"0.8*cos(pi*(y+1)/2)");
+  gr->Rotate(50,60);  gr->Box();  gr->Surf(x,y,z,"BbwrR");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{surf, Example of Surf()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node SurfC sample, SurfA sample, Surf sample, 2D samples
+ at subsection SurfC sample
+ at nav{}
+
+Function @ref{surfc} is similar to @ref{surf} but its coloring is determined by another data. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,b;  mgls_prepare2d(&a,&b);
+  gr->Title("SurfC plot");  gr->Rotate(50,60);
+  gr->Light(true);  gr->Box();  gr->SurfC(a,b);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{surfc, Example of SurfC()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node SurfA sample, SurfCA sample, SurfC sample, 2D samples
+ at subsection SurfA sample
+ at nav{}
+
+Function @ref{surfa} is similar to @ref{surf} but its transparency is determined by another data. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,b;  mgls_prepare2d(&a,&b);
+  gr->Title("SurfA plot");  gr->Rotate(50,60);
+  gr->Alpha(true);  gr->Light(true);
+  gr->Box();  gr->SurfA(a,b);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{surfa, Example of SurfA()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node SurfCA sample, Mesh sample, SurfA sample, 2D samples
+ at subsection SurfCA sample
+ at nav{}
+
+Function @ref{surfca} is similar to @ref{surf} but its color and transparency is determined by another data. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,b;  mgls_prepare2d(&a,&b);
+  gr->Title("SurfCA plot");  gr->Rotate(50,60);
+  gr->Alpha(true);  gr->Light(true);
+  gr->Box();  gr->SurfCA(a,b,a);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{surfca, Example of SurfCA()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Mesh sample, Fall sample, SurfCA sample, 2D samples
+ at subsection Mesh sample
+ at nav{}
+
+Function @ref{mesh} draw wired surface. You can use @ref{meshnum} for changing number of lines to be drawn. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->Title("Mesh plot"); gr->Rotate(50,60);
+  gr->Box();  gr->Mesh(a);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{mesh, Example of Mesh()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Fall sample, Belt sample, Mesh sample, 2D samples
+ at subsection Fall sample
+ at nav{}
+
+Function @ref{fall} draw waterfall surface. You can use @ref{meshnum} for changing number of lines to be drawn. Also you can use @samp{x} style for drawing lines in other direction. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->Title("Fall plot"); gr->Rotate(50,60);
+  gr->Box();  gr->Fall(a);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{fall, Example of Fall()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Belt sample, Boxs sample, Fall sample, 2D samples
+ at subsection Belt sample
+ at nav{}
+
+Function @ref{belt} draw surface by belts. You can use @samp{x} style for drawing lines in other direction. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->Title("Belt plot"); gr->Rotate(50,60);
+  gr->Box();  gr->Belt(a);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{belt, Example of Belt()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Boxs sample, Tile sample, Belt sample, 2D samples
+ at subsection Boxs sample
+ at nav{}
+
+Function @ref{boxs} draw surface by boxes. You can use @samp{#} for drawing wire plot. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->SetOrigin(0,0,0); gr->Light(true);
+  gr->SubPlot(2,2,0);  gr->Title("Boxs plot (default)");
+  gr->Rotate(40,60);  gr->Box();  gr->Boxs(a);
+
+  gr->SubPlot(2,2,1); gr->Title("'\\@' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Boxs(a,"@");
+
+  gr->SubPlot(2,2,2); gr->Title("'\\#' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Boxs(a,"#");
+
+  gr->SubPlot(2,2,3); gr->Title("compare with Tile");
+  gr->Rotate(50,60);  gr->Box();  gr->Tile(a);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{boxs, Example of Boxs()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Tile sample, TileS sample, Boxs sample, 2D samples
+ at subsection Tile sample
+ at nav{}
+
+Function @ref{tile} draw surface by tiles. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->Title("Tile plot");
+  gr->Rotate(40,60);  gr->Box();  gr->Tile(a);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{tile, Example of Tile()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node TileS sample, Dens sample, Tile sample, 2D samples
+ at subsection TileS sample
+ at nav{}
+
+Function @ref{tiles} is similar to @ref{tile} but tile sizes is determined by another data. This allows one to simulate transparency of the plot. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,b;  mgls_prepare2d(&a,&b);
+  gr->SubPlot(1,1,0,""); gr->Title("TileS plot");
+  gr->Box();  gr->TileS(a,b);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{tiles, Example of TileS()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Dens sample, Cont sample, TileS sample, 2D samples
+ at subsection Dens sample
+ at nav{}
+
+Function @ref{dens} draw density plot for surface. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,a1(30,40,3);  mgls_prepare2d(&a);
+  gr->Fill(a1,"0.6*sin(2*pi*x+pi*(z+1)/2)*sin(3*pi*y+pi*z) + 0.4*cos(3*pi*(x*y)+pi*(z+1)^2/2)");
+  gr->SubPlot(2,2,0,""); gr->Title("Dens plot (default)");
+  gr->Box();  gr->Dens(a);
+
+  gr->SubPlot(2,2,1); gr->Title("3d variant");
+  gr->Rotate(50,60);  gr->Box();  gr->Dens(a);
+
+  gr->SubPlot(2,2,2,"");  gr->Title("'\\#' style; meshnum 10");
+  gr->Box();  gr->Dens(a,"#","meshnum 10");
+
+  gr->SubPlot(2,2,3); gr->Title("several slices");
+  gr->Rotate(50,60);    gr->Box();  gr->Dens(a1);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{dens, Example of Dens()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cont sample, ContF sample, Dens sample, 2D samples
+ at subsection Cont sample
+ at nav{}
+
+Function @ref{cont} draw contour lines for surface. You can select automatic (default) or manual levels for contours, print contour labels, draw it on the surface (default) or at plane (as @code{Dens}). The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,v(5); mgls_prepare2d(&a); v.a[0]=-0.5;  v.a[1]=-0.15; v.a[2]=0; v.a[3]=0.15;  v.a[4]=0.5;
+  gr->SubPlot(2,2,0); gr->Title("Cont plot (default)");
+  gr->Rotate(50,60);  gr->Box();  gr->Cont(a);
+
+  gr->SubPlot(2,2,1); gr->Title("manual levels");
+  gr->Rotate(50,60);  gr->Box();  gr->Cont(v,a);
+
+  gr->SubPlot(2,2,2); gr->Title("'\\_' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Cont(a,"_");
+
+  gr->SubPlot(2,2,3,"");  gr->Title("'t' style");
+  gr->Box();  gr->Cont(a,"t");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{cont, Example of Cont()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ContF sample, ContD sample, Cont sample, 2D samples
+ at subsection ContF sample
+ at nav{}
+
+Function @ref{contf} draw filled contours.  You can select automatic (default) or manual levels for contours. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,v(5),a1(30,40,3); mgls_prepare2d(&a); v.a[0]=-0.5;
+  v.a[1]=-0.15; v.a[2]=0; v.a[3]=0.15;  v.a[4]=0.5;
+  gr->SubPlot(2,2,0); gr->Title("ContF plot (default)");
+  gr->Rotate(50,60);  gr->Box();  gr->ContF(a);
+
+  gr->SubPlot(2,2,1); gr->Title("manual levels");
+  gr->Rotate(50,60);  gr->Box();  gr->ContF(v,a);
+
+  gr->SubPlot(2,2,2); gr->Title("'\\_' style");
+  gr->Rotate(50,60);  gr->Box();  gr->ContF(a,"_");
+
+  gr->Fill(a1,"0.6*sin(2*pi*x+pi*(z+1)/2)*sin(3*pi*y+pi*z) +
+               0.4*cos(3*pi*(x*y)+pi*(z+1)^2/2)");
+  gr->SubPlot(2,2,3); gr->Title("several slices");
+  gr->Rotate(50,60);  gr->Box();  gr->ContF(a1);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{contf, Example of ContF()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ContD sample, ContV sample, ContF sample, 2D samples
+ at subsection ContD sample
+ at nav{}
+
+Function @ref{contd} is similar to @code{ContF} but with manual contour colors. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,v(5),a1(30,40,3); mgls_prepare2d(&a); v.a[0]=-0.5;
+  v.a[1]=-0.15; v.a[2]=0; v.a[3]=0.15;  v.a[4]=0.5;
+  gr->SubPlot(2,2,0); gr->Title("ContD plot (default)");
+  gr->Rotate(50,60);  gr->Box();  gr->ContD(a);
+
+  gr->SubPlot(2,2,1); gr->Title("manual levels");
+  gr->Rotate(50,60);  gr->Box();  gr->ContD(v,a);
+
+  gr->SubPlot(2,2,2); gr->Title("'\\_' style");
+  gr->Rotate(50,60);  gr->Box();  gr->ContD(a,"_");
+
+  gr->Fill(a1,"0.6*sin(2*pi*x+pi*(z+1)/2)*sin(3*pi*y+pi*z) + 0.4*cos(3*pi*(x*y)+pi*(z+1)^2/2)");
+  gr->SubPlot(2,2,3); gr->Title("several slices");
+  gr->Rotate(50,60);  gr->Box();  gr->ContD(a1);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{contd, Example of ContD()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ContV sample, Axial sample, ContD sample, 2D samples
+ at subsection ContV sample
+ at nav{}
+
+Function @ref{contv} draw vertical cylinders (belts) at contour lines. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,v(5); mgls_prepare2d(&a); v.a[0]=-0.5;
+  v.a[1]=-0.15; v.a[2]=0; v.a[3]=0.15;  v.a[4]=0.5;
+  gr->SubPlot(2,2,0); gr->Title("ContV plot (default)");
+  gr->Rotate(50,60);  gr->Box();  gr->ContV(a);
+
+  gr->SubPlot(2,2,1); gr->Title("manual levels");
+  gr->Rotate(50,60);  gr->Box();  gr->ContV(v,a);
+
+  gr->SubPlot(2,2,2); gr->Title("'\\_' style");
+  gr->Rotate(50,60);  gr->Box();  gr->ContV(a,"_");
+
+  gr->SubPlot(2,2,3); gr->Title("ContV and ContF");
+  gr->Rotate(50,60);  gr->Box();  gr->Light(true);
+  gr->ContV(a); gr->ContF(a); gr->Cont(a,"k");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{contv, Example of ContV()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Axial sample, Grad sample, ContV sample, 2D samples
+ at subsection Axial sample
+ at nav{}
+
+Function @ref{axial} draw surfaces of rotation for contour lines. You can draw wire surfaces (@samp{#} style) or ones rotated in other directions (@samp{x}, @samp{z} styles). The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->SubPlot(2,2,0); gr->Title("Axial plot (default)");
+  gr->Light(true);  gr->Alpha(true);  gr->Rotate(50,60);
+  gr->Box();  gr->Axial(a);
+
+  gr->SubPlot(2,2,1); gr->Title("'x' style;'.' style"); gr->Rotate(50,60);
+  gr->Box();  gr->Axial(a,"x.");
+
+  gr->SubPlot(2,2,2); gr->Title("'z' style"); gr->Rotate(50,60);
+  gr->Box();  gr->Axial(a,"z");
+
+  gr->SubPlot(2,2,3); gr->Title("'\\#' style"); gr->Rotate(50,60);
+  gr->Box();  gr->Axial(a,"#");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{axial, Example of Axial()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Grad sample, , Axial sample, 2D samples
+ at subsection Grad sample
+ at nav{}
+
+Function @ref{grad} draw gradient lines for matrix. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->SubPlot(1,1,0,""); gr->Title("Grad plot");
+  gr->Box();  gr->Grad(a);  gr->Dens(a,"{u8}w{q8}");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{grad, Example of Grad()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node 3D samples, Vector field samples, 2D samples, Examples
+ at section 3D samples
+ at nav{}
+
+This section is devoted to visualization of 3D data arrays. 3D means the data which depend on 3 indexes (parameters) like tensor a(i,j,k)=a(x(i),y(j),x(k)), i=1...n, j=1...m, k=1...l or in parametric form @{x(i,j,k),y(i,j,k),z(i,j,k),a(i,j,k)@}. Most of samples will use the same data for plotting. So, I put its initialization in separate function
+ at verbatim
+void mgls_prepare3d(mglData *a, mglData *b=0)
+{
+  register long i,j,k,n=61,m=50,l=40,i0;
+  if(a) a->Create(n,m,l);   if(b) b->Create(n,m,l);
+  mreal x,y,z;
+  for(i=0;i<n;i++)  for(j=0;j<m;j++)  for(k=0;k<l;k++)
+  {
+    x=2*i/(n-1.)-1; y=2*j/(m-1.)-1; z=2*k/(l-1.)-1; i0 = i+n*(j+m*k);
+    if(a) a->a[i0] = -2*(x*x + y*y + z*z*z*z - z*z - 0.1);
+    if(b) b->a[i0] = 1-2*tanh((x+y)*(x+y));
+  }
+}
+ at end verbatim
+or using C functions
+ at verbatim
+void mgls_prepare3d(HMDT a, HMDT b=0)
+{
+  register long i,j,k,n=61,m=50,l=40,i0;
+  if(a) mgl_data_create(a,n,m,l);
+  if(b) mgl_data_create(b,n,m,l);
+  mreal x,y,z;
+  for(i=0;i<n;i++)  for(j=0;j<m;j++)  for(k=0;k<l;k++)
+  {
+    x=2*i/(n-1.)-1; y=2*j/(m-1.)-1; z=2*k/(l-1.)-1; i0 = i+n*(j+m*k);
+    if(a) mgl_data_set_value(a, -2*(x*x + y*y + z*z*z*z - z*z - 0.1), i,j,k);
+    if(b) mgl_data_set_value(b, 1-2*tanh((x+y)*(x+y)), i,j,k);
+  }
+}
+ at end verbatim
+
+ at menu
+* Surf3 sample::
+* Surf3C sample::
+* Surf3A sample::
+* Surf3CA sample::
+* Cloud sample::
+* Dens3 sample::
+* Cont3 sample::
+* ContF3 sample::
+* Dens projection sample::
+* Cont projection sample::
+* ContF projection sample::
+* TriPlot and QuadPlot::
+* Dots sample::
+* Fractal sample::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Surf3 sample, Surf3C sample, , 3D samples
+ at subsection Surf3 sample
+ at nav{}
+
+Function @ref{surf3} is one of most suitable (for my opinion) functions to visualize 3D data. It draw the isosurface(s) -- surface(s) of constant amplitude (3D analogue of contour lines). You can draw wired isosurfaces if specify @samp{#} style. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData c;  mgls_prepare3d(&c);
+  gr->Light(true);    gr->Alpha(true);
+  gr->SubPlot(2,2,0); gr->Title("Surf3 plot (default)");
+  gr->Rotate(50,60);  gr->Box();  gr->Surf3(c);
+
+  gr->SubPlot(2,2,1); gr->Title("'\\#' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Surf3(c,"#");
+
+  gr->SubPlot(2,2,2); gr->Title("'.' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Surf3(c,".");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{surf3, Example of Surf3()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Surf3C sample, Surf3A sample, Surf3 sample, 3D samples
+ at subsection Surf3C sample
+ at nav{}
+
+Function @ref{surf3c} is similar to @ref{surf3} but its coloring is determined by another data. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData c,d;  mgls_prepare3d(&c,&d);
+  gr->Title("Surf3C plot"); gr->Rotate(50,60);
+  gr->Light(true);  gr->Alpha(true);
+  gr->Box();  gr->Surf3C(c,d);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{surf3c, Example of Surf3C()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Surf3A sample, Surf3CA sample, Surf3C sample, 3D samples
+ at subsection Surf3A sample
+ at nav{}
+
+Function @ref{surf3a} is similar to @ref{surf3} but its transparency is determined by another data. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData c,d;  mgls_prepare3d(&c,&d);
+  gr->Title("Surf3A plot"); gr->Rotate(50,60);
+  gr->Light(true);  gr->Alpha(true);
+  gr->Box();  gr->Surf3A(c,d);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{surf3a, Example of Surf3A()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Surf3CA sample, Cloud sample, Surf3A sample, 3D samples
+ at subsection Surf3CA sample
+ at nav{}
+
+Function @ref{surf3ca} is similar to @ref{surf3} but its color and transparency is determined by another data. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData c,d;  mgls_prepare3d(&c,&d);
+  gr->Title("Surf3CA plot"); gr->Rotate(50,60);
+  gr->Light(true);  gr->Alpha(true);
+  gr->Box();  gr->Surf3CA(c,d,c);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{surf3ca, Example of Surf3CA()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cloud sample, Dens3 sample, Surf3CA sample, 3D samples
+ at subsection Cloud sample
+ at nav{}
+
+Function @ref{cloud} draw cloud-like object which is less transparent for higher data values. Similar plot can be created using many (about 10-20) @code{Surf3A(a,a)} isosurfaces. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData c;  mgls_prepare3d(&c);
+  gr->SubPlot(2,2,0); gr->Title("Cloud plot");
+  gr->Rotate(50,60);  gr->Alpha(true);
+  gr->Box();  gr->Cloud(c,"wyrRk");
+
+  gr->SubPlot(2,2,1); gr->Title("'i' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Cloud(c,"iwyrRk");
+
+  gr->SubPlot(2,2,2); gr->Title("'.' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Cloud(c,".wyrRk");
+
+  gr->SubPlot(2,2,3); gr->Title("meshnum 10");
+  gr->Rotate(50,60);  gr->Box();  gr->Cloud(c,"wyrRk","meshnum 10");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{cloud, Example of Cloud()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Dens3 sample, Cont3 sample, Cloud sample, 3D samples
+ at subsection Dens3 sample
+ at nav{}
+
+Function @ref{dens3} draw just usual density plot but at slices of 3D data. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData c;  mgls_prepare3d(&c);
+  gr->Title("Dens3 sample");  gr->Rotate(50,60);
+  gr->Alpha(true);  gr->SetAlphaDef(0.7);
+  gr->SetOrigin(0,0,0); gr->Axis("_xyz"); gr->Box();
+  gr->Dens3(c,"x"); gr->Dens3(c); gr->Dens3(c,"z");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{densa, Example of Dens3()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cont3 sample, ContF3 sample, Dens3 sample, 3D samples
+ at subsection Cont3 sample
+ at nav{}
+
+Function @ref{cont3} draw just usual contour lines but at slices of 3D data. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData c;  mgls_prepare3d(&c);
+  gr->Title("Cont3 sample");  gr->Rotate(50,60);
+  gr->Alpha(true);  gr->SetAlphaDef(0.7);
+  gr->SetOrigin(0,0,0); gr->Axis("_xyz"); gr->Box();
+  gr->Cont3(c,"x"); gr->Cont3(c); gr->Cont3(c,"z");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{conta, Example of Cont3()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ContF3 sample, Dens projection sample, Cont3 sample, 3D samples
+ at subsection ContF3 sample
+ at nav{}
+
+Function @ref{contf3} draw just usual filled contours but at slices of 3D data. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData c;  mgls_prepare3d(&c);
+  gr->Title("ContF3 sample");  gr->Rotate(50,60);
+  gr->Alpha(true);  gr->SetAlphaDef(0.7);
+  gr->SetOrigin(0,0,0); gr->Axis("_xyz"); gr->Box();
+  gr->ContF3(c,"x");  gr->ContF3(c);    gr->ContF3(c,"z");
+  gr->Cont3(c,"kx");  gr->Cont3(c,"k"); gr->Cont3(c,"kz");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{contfa, Example of ContF3()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Dens projection sample, Cont projection sample, ContF3 sample, 3D samples
+ at subsection Dens projection sample
+ at nav{}
+
+Functions @ref{densz}, @ref{densy}, @ref{densx} draw density plot on plane perpendicular to corresponding axis. One of possible application is drawing projections of 3D field. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData c;  mgls_prepare3d(&c);
+  gr->Title("Dens[XYZ] sample");  gr->Rotate(50,60);
+  gr->Box();  gr->DensX(c.Sum("x"),0,-1);
+  gr->DensY(c.Sum("y"),0,1);  gr->DensZ(c.Sum("z"),0,-1);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{dens_xyz, Example of DensX() DensY() DensZ()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cont projection sample, ContF projection sample, Dens projection sample, 3D samples
+ at subsection Cont projection sample
+ at nav{}
+
+Functions @ref{contz}, @ref{conty}, @ref{contx} draw contour lines on plane perpendicular to corresponding axis. One of possible application is drawing projections of 3D field. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData c;  mgls_prepare3d(&c);
+  gr->Title("Cont[XYZ] sample");  gr->Rotate(50,60);
+  gr->Box();  gr->ContX(c.Sum("x"),"",-1);
+  gr->ContY(c.Sum("y"),"",1); gr->ContZ(c.Sum("z"),"",-1);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{cont_xyz, Example of ContX() ContY() ContZ()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ContF projection sample, TriPlot and QuadPlot, Cont projection sample, 3D samples
+ at subsection ContF projection sample
+ at nav{}
+
+Functions @ref{contfz}, @ref{contfy}, @ref{contfx}, draw filled contours on plane perpendicular to corresponding axis. One of possible application is drawing projections of 3D field. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData c;  mgls_prepare3d(&c);
+  gr->Title("Cont[XYZ] sample");  gr->Rotate(50,60);
+  gr->Box();  gr->ContFX(c.Sum("x"),"",-1);
+  gr->ContFY(c.Sum("y"),"",1);  gr->ContFZ(c.Sum("z"),"",-1);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{contf_xyz, Example of ContFX() ContFY() ContFZ()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node TriPlot and QuadPlot, Dots sample, ContF projection sample, 3D samples
+ at subsection TriPlot and QuadPlot
+ at nav{}
+
+Function @ref{triplot} and @ref{quadplot} draw set of triangles (or quadrangles for @code{QuadPlot}) for irregular data arrays. Note, that you have to provide not only vertexes, but also the indexes of triangles or quadrangles. I.e. perform triangulation by some other library. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mreal q[] = {0,1,2,3, 4,5,6,7, 0,2,4,6, 1,3,5,7, 0,4,1,5, 2,6,3,7};
+  mreal xc[] = {-1,1,-1,1,-1,1,-1,1}, yc[] = {-1,-1,1,1,-1,-1,1,1}, zc[] = {-1,-1,-1,-1,1,1,1,1};
+  mglData qq(6,4,q), xx(8,xc), yy(8,yc), zz(8,zc);
+  gr->Light(true);  //gr->Alpha(true);
+  gr->SubPlot(2,2,0); gr->Title("QuadPlot sample"); gr->Rotate(50,60);
+  gr->QuadPlot(qq,xx,yy,zz,"yr");
+  gr->QuadPlot(qq,xx,yy,zz,"k#");
+  gr->SubPlot(2,2,2); gr->Title("QuadPlot coloring"); gr->Rotate(50,60);
+  gr->QuadPlot(qq,xx,yy,zz,yy,"yr");
+  gr->QuadPlot(qq,xx,yy,zz,"k#");
+
+  mreal t[] = {0,1,2, 0,1,3, 0,2,3, 1,2,3};
+  mreal xt[] = {-1,1,0,0}, yt[] = {-1,-1,1,0}, zt[] = {-1,-1,-1,1};
+  mglData tt(4,3,t), uu(4,xt), vv(4,yt), ww(4,zt);
+  gr->SubPlot(2,2,1); gr->Title("TriPlot sample");  gr->Rotate(50,60);
+  gr->TriPlot(tt,uu,vv,ww,"b");
+  gr->TriPlot(tt,uu,vv,ww,"k#");
+  gr->SubPlot(2,2,3); gr->Title("TriPlot coloring");  gr->Rotate(50,60);
+  gr->TriPlot(tt,uu,vv,ww,vv,"cb");
+  gr->TriPlot(tt,uu,vv,ww,"k#");
+  gr->TriCont(tt,uu,vv,ww,"B");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{triplot, Example of TriPlot() and QuadPlot()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Dots sample, Fractal sample, TriPlot and QuadPlot, 3D samples
+ at subsection Dots sample
+ at nav{}
+
+Function @ref{dots} is another way to draw irregular points. @code{Dots} use color scheme for coloring (see @ref{Color scheme}). The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  int i, n=2000;
+  mglData x(n),y(n),z(n),c(n);
+  for(i=0;i<n;i++)
+  {
+    mreal t=M_PI*(mgl_rnd()-0.5), f=2*M_PI*mgl_rnd();
+    x.a[i] = 0.9*cos(t)*cos(f);
+    y.a[i] = 0.9*cos(t)*sin(f);
+    z.a[i] = 0.6*sin(t);
+    c.a[i] = cos(2*t);
+  }
+  gr->SubPlot(2,2,0); gr->Title("Dots sample");  gr->Rotate(50,60);
+  gr->Box();  gr->Dots(x,y,z);
+  gr->Alpha(true);
+  gr->SubPlot(2,2,1); gr->Title("add transparency"); gr->Rotate(50,60);
+  gr->Box();  gr->Dots(x,y,z,c);
+  gr->SubPlot(2,2,2); gr->Title("add coloring"); gr->Rotate(50,60);
+  gr->Box();  gr->Dots(x,y,z,x,c);
+  gr->SubPlot(2,2,3); gr->Title("Only coloring");gr->Rotate(50,60);
+  gr->Box();  gr->Tens(x,y,z,x," .");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{dots, Example of Dots()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Fractal sample, , Dots sample, 3D samples
+ at subsection Fractal sample
+ at nav{}
+
+Commands @ref{ifs2d} and @ref{ifs3d} generate points for fractals using iterated function system in 2d and 3d cases correspondingly. The sample codes are:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData A;
+  A.SetList(35, 0.33,0.,0.,0.33,0.,0.,0.2, 0.33,0.,0.,0.33,0.67,0.,0.2, 0.33,0.,0.,0.33,0.33,0.33,0.2,
+                0.33,0.,0.,0.33,0.,0.67,0.2, 0.33,0.,0.,0.33,0.67,0.67,0.2);
+  A.Rearrange(7);
+  mglData f(mglIFS2d(A,100000));
+  gr->SubPlot(1,1,0,"<_");
+  gr->Title("IFS 2d sample");
+  gr->SetRanges(f.SubData(0), f.SubData(1));
+  gr->Axis(); gr->Plot(f.SubData(0), f.SubData(1),"r#o ","size 0.05");
+}
+ at end verbatim
+
+ at pfig{ifs2d, Example of IFS fractal (2d case).}
+
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData A;
+  A.SetList(52, 0.,0.,0.,0.,.18,0.,0.,0.,0.,0.,0.,0.,.01, .85,0.,0.,0.,.85,.1,0.,-0.1,0.85,0.,1.6,0.,.85,
+                .2,-.2,0.,.2,.2,0.,0.,0.,0.3,0.,0.8,0.,.07, -.2,.2,0.,.2,.2,0.,0.,0.,0.3,0.,0.8,0.,.07);
+  A.Rearrange(13);
+  mglData f(mglIFS3d(A,100000));
+  gr->Title("IFS 3d sample");
+  gr->SetRanges(f.SubData(0), f.SubData(1), f.SubData(2));
+  gr->Rotate(50,60);  gr->Axis(); gr->Box();
+  gr->Dots(f.SubData(0), f.SubData(1), f.SubData(2),"G#o","size 0.05");
+}
+ at end verbatim
+
+ at pfig{ifs3d, Example of IFS fractal (3d case).}
+
+
+Command @ref{flame2d} generate points for flame fractals in 2d case. The sample codes are:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData A, B(2,3,5);
+  A.SetList(35, 0.33,0.,0.,0.33,0.,0.,0.2, 0.33,0.,0.,0.33,0.67,0.,0.2, 0.33,0.,0.,0.33,0.33,0.33,0.2,
+      0.33,0.,0.,0.33,0.,0.67,0.2, 0.33,0.,0.,0.33,0.67,0.67,0.2);
+  A.Rearrange(7);
+  for(long i=0;i<2*3*5;i++)	B.a[i] = 0.3;
+  for(long i=0;i<5;i++)	B.a[2*3*i] = B.a[2*3*i+1*2] = B.a[2*3*i+2*2] = 3;
+  mglData f(mglFlame2d(A,B,1000000));
+  gr->SubPlot(1,1,0,"<_");
+  if(big!=3)	gr->Title("Flame2d sample");
+  gr->SetRanges(f.SubData(0), f.SubData(1));
+  gr->Axis();	gr->Box();
+  gr->Plot(f.SubData(0), f.SubData(1),"r#o ","size 0.05");
+}
+ at end verbatim
+
+ at pfig{flame2d, Example of flame fractal (2d case).}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Vector field samples, Hints, 3D samples, Examples
+ at section Vector field samples
+ at nav{}
+
+Vector field visualization (especially in 3d case) is more or less complex task. MathGL provides 3 general types of plots: vector field itself (@code{Vect}), flow threads (@code{Flow}), and flow pipes with radius proportional to field amplitude (@code{Pipe}).
+
+However, the plot may look tangly -- there are too many overlapping lines. I may suggest 2 ways to solve this problem. The first one is to change @code{SetMeshNum} for decreasing the number of hachures. The second way is to use the flow thread chart @code{Flow}, or possible many flow thread from manual position (@code{FlowP}). Unfortunately, I don't know any other methods to visualize 3d vector field. If you know any, e-mail me and I shall add it to MathGL.
+
+Most of samples will use the same data for plotting. So, I put its initialization in separate function
+ at verbatim
+void mgls_prepare2v(mglData *a, mglData *b)
+{
+  register long i,j,n=20,m=30,i0;
+  if(a) a->Create(n,m);   if(b) b->Create(n,m);
+  mreal x,y;
+  for(i=0;i<n;i++)  for(j=0;j<m;j++)
+  {
+    x=i/(n-1.); y=j/(m-1.); i0 = i+n*j;
+    if(a) a->a[i0] = 0.6*sin(2*M_PI*x)*sin(3*M_PI*y)+0.4*cos(3*M_PI*x*y);
+    if(b) b->a[i0] = 0.6*cos(2*M_PI*x)*cos(3*M_PI*y)+0.4*cos(3*M_PI*x*y);
+  }
+}
+void mgls_prepare3v(mglData *ex, mglData *ey, mglData *ez)
+{
+  register long i,j,k,n=10,i0;
+  if(!ex || !ey || !ez) return;
+  ex->Create(n,n,n);  ey->Create(n,n,n);  ez->Create(n,n,n);
+  mreal x,y,z, r1,r2;
+  for(i=0;i<n;i++)  for(j=0;j<n;j++)  for(k=0;k<n;k++)
+  {
+    x=2*i/(n-1.)-1; y=2*j/(n-1.)-1; z=2*k/(n-1.)-1; i0 = i+n*(j+k*n);
+    r1 = pow(x*x+y*y+(z-0.3)*(z-0.3)+0.03,1.5);
+    r2 = pow(x*x+y*y+(z+0.3)*(z+0.3)+0.03,1.5);
+    ex->a[i0]=0.2*x/r1 - 0.2*x/r2;
+    ey->a[i0]=0.2*y/r1 - 0.2*y/r2;
+    ez->a[i0]=0.2*(z-0.3)/r1 - 0.2*(z+0.3)/r2;
+  }
+}
+ at end verbatim
+or using C functions
+ at verbatim
+void mgls_prepare2v(HMDT a, HMDT b)
+{
+  register long i,j,n=20,m=30,i0;
+  if(a) mgl_data_create(a,n,m,1);
+  if(b) mgl_data_create(b,n,m,1);
+  mreal x,y;
+  for(i=0;i<n;i++)  for(j=0;j<m;j++)
+  {
+    x=i/(n-1.); y=j/(m-1.); i0 = i+n*j;
+    if(a) mgl_data_set_value(a, 0.6*sin(2*M_PI*x)*sin(3*M_PI*y)+0.4*cos(3*M_PI*x*y), i,j,0);
+    if(b) mgl_data_set_value(b, 0.6*cos(2*M_PI*x)*cos(3*M_PI*y)+0.4*cos(3*M_PI*x*y), i,j,0);
+  }
+}
+void mgls_prepare3v(HMDT ex, HMDT ey, HMDT ez)
+{
+  register long i,j,k,n=10,i0;
+  if(!ex || !ey || !ez) return;
+  mgl_data_create(ex,n,n,n);
+  mgl_data_create(ey,n,n,n);
+  mgl_data_create(ez,n,n,n);
+  mreal x,y,z, r1,r2;
+  for(i=0;i<n;i++)  for(j=0;j<n;j++)  for(k=0;k<n;k++)
+  {
+    x=2*i/(n-1.)-1; y=2*j/(n-1.)-1; z=2*k/(n-1.)-1; i0 = i+n*(j+k*n);
+    r1 = pow(x*x+y*y+(z-0.3)*(z-0.3)+0.03,1.5);
+    r2 = pow(x*x+y*y+(z+0.3)*(z+0.3)+0.03,1.5);
+    mgl_data_set_value(ex, 0.2*x/r1 - 0.2*x/r2, i,j,k);
+    mgl_data_set_value(ey, 0.2*y/r1 - 0.2*y/r2, i,j,k);
+    mgl_data_set_value(ez, 0.2*(z-0.3)/r1 - 0.2*(z+0.3)/r2, i,j,k);
+  }
+}
+ at end verbatim
+
+ at menu
+* Vect sample::
+* Vect3 sample::
+* Traj sample::
+* Flow sample::
+* Pipe sample::
+* Dew sample::
+ at end menu
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Vect sample, Vect3 sample, , Vector field samples
+ at subsection Vect sample
+ at nav{}
+
+Function @ref{vect} is most standard way to visualize vector fields -- it draw a lot of arrows or hachures for each data cell. It have a lot of options which can be seen on the figure (and in the sample code). @code{Vect} use color scheme for coloring (see @ref{Color scheme}). The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,b;  mgls_prepare2v(&a,&b);
+  gr->SubPlot(3,2,0,""); gr->Title("Vect plot (default)");
+  gr->Box();  gr->Vect(a,b);
+
+  gr->SubPlot(3,2,1,"");  gr->Title("'.' style; '=' style");
+  gr->Box();  gr->Vect(a,b,"=.");
+
+  gr->SubPlot(3,2,2,"");  gr->Title("'f' style");
+  gr->Box();  gr->Vect(a,b,"f");
+
+  gr->SubPlot(3,2,3,"");  gr->Title("'>' style");
+  gr->Box();  gr->Vect(a,b,">");
+
+  gr->SubPlot(3,2,4,"");  gr->Title("'<' style");
+  gr->Box();  gr->Vect(a,b,"<");
+
+  mglData ex,ey,ez; mgls_prepare3v(&ex,&ey,&ez);
+  gr->SubPlot(3,2,5); gr->Title("3d variant");  gr->Rotate(50,60);
+  gr->Box();  gr->Vect(ex,ey,ez);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{vect, Example of Vect()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Vect3 sample, Traj sample, Vect sample, Vector field samples
+ at subsection Vect3 sample
+ at nav{}
+
+Function @ref{vect3} draw just usual vector field plot but at slices of 3D data. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData ex,ey,ez; mgls_prepare3v(&ex,&ey,&ez);
+  gr->SubPlot(2,1,0); gr->Title("Vect3 sample");    gr->SetOrigin(0,0,0);
+  gr->Rotate(50,60);    gr->Axis("_xyz");   gr->Box();
+  gr->Vect3(ex,ey,ez,"x");  gr->Vect3(ex,ey,ez);    gr->Vect3(ex,ey,ez,"z");
+
+  gr->SubPlot(2,1,1);   gr->Title("'f' style");
+  gr->Rotate(50,60);    gr->Axis("_xyz");   gr->Box();
+  gr->Vect3(ex,ey,ez,"fx"); gr->Vect3(ex,ey,ez,"f");gr->Vect3(ex,ey,ez,"fz");
+  gr->Grid3(ex,"Wx");   gr->Grid3(ex,"W");  gr->Grid3(ex,"Wz");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{vecta, Example of Vect3()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Traj sample, Flow sample, Vect3 sample, Vector field samples
+ at subsection Traj sample
+ at nav{}
+
+Function @ref{traj} is 1D analogue of @code{Vect}. It draw vectors from specified points. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData x,y,y1,y2;  mgls_prepare1d(&y,&y1,&y2,&x);
+  gr->SubPlot(1,1,0,""); gr->Title("Traj plot");
+  gr->Box();  gr->Plot(x,y);  gr->Traj(x,y,y1,y2);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{traj, Example of Traj()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Flow sample, Pipe sample, Traj sample, Vector field samples
+ at subsection Flow sample
+ at nav{}
+
+Function @ref{flow} is another standard way to visualize vector fields -- it draw lines (threads) which is tangent to local vector field direction. MathGL draw threads from edges of bounding box and from central slices. Sometimes it is not most appropriate variant -- you may want to use @code{FlowP} to specify manual position of threads. @code{Flow} use color scheme for coloring (see @ref{Color scheme}). At this warm color corresponds to normal flow (like attractor), cold one corresponds [...]
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,b;  mgls_prepare2v(&a,&b);
+  gr->SubPlot(2,2,0,""); gr->Title("Flow plot (default)");
+  gr->Box();  gr->Flow(a,b);
+
+  gr->SubPlot(2,2,1,"");  gr->Title("'v' style");
+  gr->Box();  gr->Flow(a,b,"v");
+
+  gr->SubPlot(2,2,2,"");  gr->Title("'\\#' style");
+  gr->Box();  gr->Flow(a,b,"#");
+
+  mglData ex,ey,ez; mgls_prepare3v(&ex,&ey,&ez);
+  gr->SubPlot(2,2,3); gr->Title("3d variant");  gr->Rotate(50,60);
+  gr->Box();  gr->Flow(ex,ey,ez);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{flow, Example of Flow()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Pipe sample, Dew sample, Flow sample, Vector field samples
+ at subsection Pipe sample
+ at nav{}
+
+Function @ref{pipe} is similar to @ref{flow} but draw pipes (tubes) which radius is proportional to the amplitude of vector field. @code{Pipe} use color scheme for coloring (see @ref{Color scheme}). At this warm color corresponds to normal flow (like attractor), cold one corresponds to inverse flow (like source). The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,b;  mgls_prepare2v(&a,&b);
+  gr->SubPlot(2,2,0,""); gr->Title("Pipe plot (default)");
+  gr->Light(true);  gr->Box();  gr->Pipe(a,b);
+
+  gr->SubPlot(2,2,1,"");  gr->Title("'i' style");
+  gr->Box();  gr->Pipe(a,b,"i");
+
+  gr->SubPlot(2,2,2,"");  gr->Title("'\\#' style");
+  gr->Box();  gr->Pipe(a,b,"#");
+
+  mglData ex,ey,ez; mgls_prepare3v(&ex,&ey,&ez);
+  gr->SubPlot(2,2,3); gr->Title("3d variant");  gr->Rotate(50,60);
+  gr->Box();  gr->Pipe(ex,ey,ez,"",0.1);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{pipe, Example of Pipe()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Dew sample, , Pipe sample, Vector field samples
+ at subsection Dew sample
+ at nav{}
+
+Function @ref{dew} is similar to @code{Vect} but use drops instead of arrows. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,b;  mgls_prepare2v(&a,&b);
+  gr->SubPlot(1,1,0,""); gr->Title("Dew plot");
+  gr->Box();  gr->Light(true);  gr->Dew(a,b);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{dew, Example of Dew()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Hints, FAQ, Vector field samples, Examples
+ at section Hints
+ at nav{}
+
+In this section I've included some small hints and advices for the improving of the quality of plots and for the demonstration of some non-trivial features of MathGL library. In contrast to previous examples I showed mostly the idea but not the whole drawing function.
+
+ at menu
+* ``Compound'' graphics::
+* Transparency and lighting::
+* Types of transparency::
+* Axis projection::
+* Adding fog::
+* Lighting sample::
+* Using primitives::
+* STFA sample::
+* Mapping visualization::
+* Data interpolation::
+* Making regular data::
+* Making histogram::
+* Nonlinear fitting hints::
+* PDE solving hints::
+* Drawing phase plain::
+* Pulse properties::
+* Using MGL parser::
+* Using options::
+* ``Templates''::
+* Stereo image::
+* Reduce memory usage::
+* Saving and scanning file::
+* Mixing bitmap and vector output::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ``Compound'' graphics, Transparency and lighting, , Hints
+ at subsection ``Compound'' graphics
+ at nav{}
+
+As I noted above, MathGL functions (except the special one, like Clf()) do  not erase the previous plotting but just add the new one. It allows one to draw ``compound'' plots easily. For example, popular Matlab command @code{surfc} can be emulated in MathGL by 2 calls:
+ at verbatim
+  Surf(a);
+  Cont(a, "_");     // draw contours at bottom
+ at end verbatim
+Here @var{a} is 2-dimensional data for the plotting, @code{-1} is the value of z-coordinate at which the contour should be plotted (at the bottom in this example). Analogously, one can draw density plot instead of contour lines and so on.
+
+Another nice plot is contour lines plotted directly on the surface:
+ at verbatim
+  Light(true);       // switch on light for the surface
+  Surf(a, "BbcyrR"); // select 'jet' colormap for the surface
+  Cont(a, "y");      // and yellow color for contours
+ at end verbatim
+The possible difficulties arise in black&white case, when the color of the surface can be close to the color of a contour line. In that case I may suggest the following code:
+ at verbatim
+  Light(true);   // switch on light for the surface
+  Surf(a, "kw"); // select 'gray' colormap for the surface
+  CAxis(-1,0);   // first draw for darker surface colors
+  Cont(a, "w");  // white contours
+  CAxis(0,1);    // now draw for brighter surface colors
+  Cont(a, "k");  // black contours
+  CAxis(-1,1);   // return color range to original state
+ at end verbatim
+The idea is to divide the color range on 2 parts (dark and bright) and to select the contrasting color for contour lines for each of part.
+
+Similarly, one can plot flow thread over density plot of vector field amplitude (this is another amusing plot from Matlab) and so on. The list of compound graphics can be prolonged but I hope that the general idea is clear.
+
+Just for illustration I put here following sample code:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,b,d;  mgls_prepare2v(&a,&b);  d = a;
+  for(int i=0;i<a.nx*a.ny;i++)  d.a[i] = hypot(a.a[i],b.a[i]);
+  mglData c;  mgls_prepare3d(&c);
+  mglData v(10);  v.Fill(-0.5,1);
+
+  gr->SubPlot(2,2,1,"");  gr->Title("Flow + Dens");
+  gr->Flow(a,b,"br"); gr->Dens(d,"BbcyrR"); gr->Box();
+
+  gr->SubPlot(2,2,0); gr->Title("Surf + Cont"); gr->Rotate(50,60);
+  gr->Light(true);  gr->Surf(a);  gr->Cont(a,"y");  gr->Box();
+
+  gr->SubPlot(2,2,2); gr->Title("Mesh + Cont"); gr->Rotate(50,60);
+  gr->Box();  gr->Mesh(a);  gr->Cont(a,"_");
+
+  gr->SubPlot(2,2,3); gr->Title("Surf3 + ContF3");gr->Rotate(50,60);
+  gr->Box();  gr->ContF3(v,c,"z",0);  gr->ContF3(v,c,"x");  gr->ContF3(v,c);
+  gr->SetCutBox(mglPoint(0,-1,-1), mglPoint(1,0,1.1));
+  gr->ContF3(v,c,"z",c.nz-1); gr->Surf3(-0.5,c);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{combined, Example of ``combined'' plots}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Transparency and lighting, Types of transparency, ``Compound'' graphics, Hints
+ at subsection Transparency and lighting
+ at nav{}
+
+Here I want to show how transparency and lighting both and separately change the look of a surface. So, there is code and picture for that:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->SubPlot(2,2,0); gr->Title("default"); gr->Rotate(50,60);
+  gr->Box();  gr->Surf(a);
+
+  gr->SubPlot(2,2,1); gr->Title("light on");  gr->Rotate(50,60);
+  gr->Box();  gr->Light(true);  gr->Surf(a);
+
+  gr->SubPlot(2,2,3); gr->Title("alpha on; light on");  gr->Rotate(50,60);
+  gr->Box();  gr->Alpha(true);  gr->Surf(a);
+
+  gr->SubPlot(2,2,2); gr->Title("alpha on");  gr->Rotate(50,60);
+  gr->Box();  gr->Light(false); gr->Surf(a);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{alpha, Example of transparency and lightings}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Types of transparency, Axis projection, Transparency and lighting, Hints
+ at subsection Types of transparency
+ at nav{}
+
+MathGL library has advanced features for setting and handling the surface transparency. The simplest way to add transparency is the using of function @ref{alpha}. As a result, all further surfaces (and isosurfaces, density plots and so on) become transparent. However, their  look can be additionally improved.
+
+The value of transparency can be different from surface to surface. To do it just use @code{SetAlphaDef} before the drawing of the surface, or use option @code{alpha} (see @ref{Command options}). If its value is close to 0 then the surface becomes more and more transparent. Contrary, if its value is close to 1 then the surface becomes practically non-transparent.
+
+Also you can change the way how the light goes through overlapped surfaces. The function @code{SetTranspType} defines it. By default the usual transparency is used (@samp{0}) -- surfaces below is less visible than the upper ones. A ``glass-like'' transparency (@samp{1}) has a different look -- each surface just decreases the background light (the surfaces are commutable in this case).
+
+A ``neon-like'' transparency (@samp{2}) has more interesting look. In this case a surface is the light source (like a lamp on the dark background) and just adds some intensity to the color. At this, the library sets automatically the black color for the background and changes the default line color to white.
+
+As example I shall show several plots for different types of transparency. The code is the same except the values of @code{SetTranspType} function:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->Alpha(true);  gr->Light(true);
+  mglData a;  mgls_prepare2d(&a);
+  gr->SetTranspType(0); gr->Clf();
+  gr->SubPlot(2,2,0); gr->Rotate(50,60);  gr->Surf(a);  gr->Box();
+  gr->SubPlot(2,2,1); gr->Rotate(50,60);  gr->Dens(a);  gr->Box();
+  gr->SubPlot(2,2,2); gr->Rotate(50,60);  gr->Cont(a);  gr->Box();
+  gr->SubPlot(2,2,3); gr->Rotate(50,60);  gr->Axial(a); gr->Box();
+  return 0;
+}
+ at end verbatim
+
+ at pfig{type0, Example of @code{SetTranspType(0)}.}
+ at pfig{type1, Example of @code{SetTranspType(1)}.}
+ at pfig{type2, Example of @code{SetTranspType(2)}.}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Axis projection, Adding fog, Types of transparency, Hints
+ at subsection Axis projection
+ at nav{}
+
+You can easily make 3D plot and draw its x-,y-,z-projections (like in CAD) by using @ref{ternary} function with arguments: 4 for Cartesian, 5 for Ternary and 6 for Quaternary coordinates. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SetRanges(0,1,0,1,0,1);
+  mglData x(50),y(50),z(50),rx(10),ry(10), a(20,30);
+  a.Modify("30*x*y*(1-x-y)^2*(x+y<1)");
+  x.Modify("0.25*(1+cos(2*pi*x))");
+  y.Modify("0.25*(1+sin(2*pi*x))");
+  rx.Modify("rnd"); ry.Modify("(1-v)*rnd",rx);
+  z.Modify("x");
+
+  gr->Title("Projection sample");
+  gr->Ternary(4);
+  gr->Rotate(50,60);      gr->Light(true);
+  gr->Plot(x,y,z,"r2");   gr->Surf(a,"#");
+  gr->Axis(); gr->Grid(); gr->Box();
+  gr->Label('x',"X",1);   gr->Label('y',"Y",1);   gr->Label('z',"Z",1);
+}
+ at end verbatim
+
+ at pfig{projection, Example of axis projections}
+ at pfig{projection5, Example of ternary axis projections}
+ at c @pfig{projection6, Example of quaternary axis projections}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Adding fog, Lighting sample, Axis projection, Hints
+ at subsection Adding fog
+ at nav{}
+
+MathGL can add a fog to the image. Its switching on is rather simple -- just use @ref{fog} function. There is the only feature -- fog is applied for whole image. Not to particular subplot. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->Title("Fog sample");
+  gr->Light(true);  gr->Rotate(50,60);  gr->Fog(1); gr->Box();
+  gr->Surf(a);  gr->Cont(a,"y");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{fog, Example of @code{Fog()}.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Lighting sample, Using primitives, Adding fog, Hints
+ at subsection Lighting sample
+ at nav{}
+
+In contrast to the most of other programs, MathGL supports several (up to 10) light sources. Moreover, the color each of them can be different: white (this is usual), yellow, red, cyan, green and so on. The use of several light sources may be interesting for the highlighting of some peculiarities of the plot or just to make an amusing picture. Note, each light source can be switched on/off individually. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->Title("Several light sources");
+  gr->Rotate(50,60);  gr->Light(true);
+  gr->AddLight(1,mglPoint(0,1,0),'c');
+  gr->AddLight(2,mglPoint(1,0,0),'y');
+  gr->AddLight(3,mglPoint(0,-1,0),'m');
+  gr->Box();  gr->Surf(a,"h");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{several_light, Example of several light sources.}
+
+Additionally, you can use local light sources and set to use @ref{diffuse} reflection instead of specular one (by default) or both kinds. Note, I use @ref{attachlight} command to keep light settings relative to subplot.
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->Light(true);  gr->AttachLight(true);
+  gr->SubPlot(2,2,0); gr->Title("Default"); gr->Rotate(50,60);
+  gr->Line(mglPoint(-1,-0.7,1.7),mglPoint(-1,-0.7,0.7),"BA"); gr->Box();  gr->Surf(a);
+
+  gr->SubPlot(2,2,1); gr->Title("Local");   gr->Rotate(50,60);
+  gr->AddLight(0,mglPoint(1,0,1),mglPoint(-2,-1,-1));
+  gr->Line(mglPoint(1,0,1),mglPoint(-1,-1,0),"BAO");  gr->Box();  gr->Surf(a);
+
+  gr->SubPlot(2,2,2); gr->Title("no diffuse"); gr->Rotate(50,60);
+  gr->SetDiffuse(0);
+  gr->Line(mglPoint(1,0,1),mglPoint(-1,-1,0),"BAO");  gr->Box();  gr->Surf(a);
+
+  gr->SubPlot(2,2,3); gr->Title("diffusive only");  gr->Rotate(50,60);
+  gr->SetDiffuse(0.5);
+  gr->AddLight(0,mglPoint(1,0,1),mglPoint(-2,-1,-1),'w',0);
+  gr->Line(mglPoint(1,0,1),mglPoint(-1,-1,0),"BAO");  gr->Box();  gr->Surf(a);
+}
+ at end verbatim
+
+ at pfig{light, Example of different types of lighting.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Using primitives, STFA sample, Lighting sample, Hints
+ at subsection Using primitives
+ at nav{}
+
+MathGL provide a set of functions for drawing primitives (see @ref{Primitives}). Primitives are low level object, which used by most of plotting functions. Picture below demonstrate some of commonly used primitives.
+
+ at pfig{primitives, Primitives in MathGL.}
+
+Generally, you can create arbitrary new kind of plot using primitives. For example, MathGL don't provide any special functions for drawing molecules. However, you can do it using only one type of primitives @ref{drop}. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->Alpha(true);  gr->Light(true);
+
+  gr->SubPlot(2,2,0,"");  gr->Title("Methane, CH_4");
+  gr->StartGroup("Methane");
+  gr->Rotate(60,120);
+  gr->Sphere(mglPoint(0,0,0),0.25,"k");
+  gr->Drop(mglPoint(0,0,0),mglPoint(0,0,1),0.35,"h",1,2);
+  gr->Sphere(mglPoint(0,0,0.7),0.25,"g");
+  gr->Drop(mglPoint(0,0,0),mglPoint(-0.94,0,-0.33),0.35,"h",1,2);
+  gr->Sphere(mglPoint(-0.66,0,-0.23),0.25,"g");
+  gr->Drop(mglPoint(0,0,0),mglPoint(0.47,0.82,-0.33),0.35,"h",1,2);
+  gr->Sphere(mglPoint(0.33,0.57,-0.23),0.25,"g");
+  gr->Drop(mglPoint(0,0,0),mglPoint(0.47,-0.82,-0.33),0.35,"h",1,2);
+  gr->Sphere(mglPoint(0.33,-0.57,-0.23),0.25,"g");
+  gr->EndGroup();
+
+  gr->SubPlot(2,2,1,"");  gr->Title("Water, H_{2}O");
+  gr->StartGroup("Water");
+  gr->Rotate(60,100);
+  gr->StartGroup("Water_O");
+  gr->Sphere(mglPoint(0,0,0),0.25,"r");
+  gr->EndGroup();
+  gr->StartGroup("Water_Bond_1");
+  gr->Drop(mglPoint(0,0,0),mglPoint(0.3,0.5,0),0.3,"m",1,2);
+  gr->EndGroup();
+  gr->StartGroup("Water_H_1");
+  gr->Sphere(mglPoint(0.3,0.5,0),0.25,"g");
+  gr->EndGroup();
+  gr->StartGroup("Water_Bond_2");
+  gr->Drop(mglPoint(0,0,0),mglPoint(0.3,-0.5,0),0.3,"m",1,2);
+  gr->EndGroup();
+  gr->StartGroup("Water_H_2");
+  gr->Sphere(mglPoint(0.3,-0.5,0),0.25,"g");
+  gr->EndGroup();
+  gr->EndGroup();
+
+  gr->SubPlot(2,2,2,"");  gr->Title("Oxygen, O_2");
+  gr->StartGroup("Oxygen");
+  gr->Rotate(60,120);
+  gr->Drop(mglPoint(0,0.5,0),mglPoint(0,-0.3,0),0.3,"m",1,2);
+  gr->Sphere(mglPoint(0,0.5,0),0.25,"r");
+  gr->Drop(mglPoint(0,-0.5,0),mglPoint(0,0.3,0),0.3,"m",1,2);
+  gr->Sphere(mglPoint(0,-0.5,0),0.25,"r");
+  gr->EndGroup();
+
+  gr->SubPlot(2,2,3,"");  gr->Title("Ammonia, NH_3");
+  gr->StartGroup("Ammonia");
+  gr->Rotate(60,120);
+  gr->Sphere(mglPoint(0,0,0),0.25,"b");
+  gr->Drop(mglPoint(0,0,0),mglPoint(0.33,0.57,0),0.32,"n",1,2);
+  gr->Sphere(mglPoint(0.33,0.57,0),0.25,"g");
+  gr->Drop(mglPoint(0,0,0),mglPoint(0.33,-0.57,0),0.32,"n",1,2);
+  gr->Sphere(mglPoint(0.33,-0.57,0),0.25,"g");
+  gr->Drop(mglPoint(0,0,0),mglPoint(-0.65,0,0),0.32,"n",1,2);
+  gr->Sphere(mglPoint(-0.65,0,0),0.25,"g");
+  gr->EndGroup();
+  return 0;
+}
+ at end verbatim
+
+ at pfig{molecule, Example of molecules drawing.}
+
+Moreover, some of special plots can be more easily produced by primitives rather than by specialized function. For example, Venn diagram can be produced by @code{Error} plot:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  double xx[3]={-0.3,0,0.3}, yy[3]={0.3,-0.3,0.3}, ee[3]={0.7,0.7,0.7};
+  mglData x(3,xx), y(3,yy), e(3,ee);
+  gr->Title("Venn-like diagram"); gr->Alpha(true);
+  gr->Error(x,y,e,e,"!rgb@#o");
+  return 0;
+}
+ at end verbatim
+You see that you have to specify and fill 3 data arrays. The same picture can be produced by just 3 calls of @ref{circle} function:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->Title("Venn-like diagram"); gr->Alpha(true);
+  gr->Circle(mglPoint(-0.3,0.3),0.7,"rr@");
+  gr->Circle(mglPoint(0,-0.3),0.7,"gg@");
+  gr->Circle(mglPoint( 0.3,0.3),0.7,"bb@");
+  return 0;
+}
+ at end verbatim
+Of course, the first variant is more suitable if you need to plot a lot of circles. But for few ones the usage of primitives looks easy.
+
+ at pfig{venn, Example of Venn diagram.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node STFA sample, Mapping visualization, Using primitives, Hints
+ at subsection STFA sample
+ at nav{}
+
+Short-time Fourier Analysis (@ref{stfa}) is one of informative method for analyzing long rapidly oscillating 1D data arrays. It is used to determine the sinusoidal frequency and phase content of local sections of a signal as it changes over time.
+
+MathGL can find and draw STFA result. Just to show this feature I give following sample. Initial data arrays is 1D arrays with step-like frequency. Exactly this you can see at bottom on the STFA plot. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a(2000), b(2000);
+  gr->Fill(a,"cos(50*pi*x)*(x<-.5)+cos(100*pi*x)*(x<0)*(x>-.5)+\
+  cos(200*pi*x)*(x<.5)*(x>0)+cos(400*pi*x)*(x>.5)");
+  gr->SubPlot(1, 2, 0,"<_");  gr->Title("Initial signal");
+  gr->Plot(a);
+  gr->Axis();
+  gr->Label('x', "\\i t");
+
+  gr->SubPlot(1, 2, 1,"<_");  gr->Title("STFA plot");
+  gr->STFA(a, b, 64);
+  gr->Axis();
+  gr->Label('x', "\\i t");
+  gr->Label('y', "\\omega", 0);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{stfa, Example of STFA().}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Mapping visualization, Data interpolation, STFA sample, Hints
+ at subsection Mapping visualization
+ at nav{}
+
+Sometime ago I worked with mapping and have a question about its visualization. Let me remember you that mapping is some transformation rule for one set of number to another one. The 1d mapping is just an ordinary function -- it takes a number and transforms it to another one. The 2d mapping (which I used) is a pair of functions which take 2 numbers and transform them to another 2 ones. Except general plots (like @ref{surfc}, @ref{surfa}) there is a special plot -- Arnold diagram. It sho [...]
+
+I tried to make such plot in @ref{map}. It shows the set of points or set of faces, which final position is the result of mapping. At this, the color gives information about their initial position and the height describes Jacobian value of the transformation. Unfortunately, it looks good only for the simplest mapping but for the  real multivalent quasi-chaotic mapping it produces a confusion. So, use it if you like :).
+
+The sample code for mapping visualization is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a(50, 40), b(50, 40);
+  gr->Puts(mglPoint(0, 0), "\\to", ":C", -1.4);
+  gr->SetRanges(-1,1,-1,1,-2,2);
+
+  gr->SubPlot(2, 1, 0);
+  gr->Fill(a,"x");  gr->Fill(b,"y");
+  gr->Puts(mglPoint(0, 1.1), "\\{x, y\\}", ":C", -2);   gr->Box();
+  gr->Map(a, b, "brgk");
+
+  gr->SubPlot(2, 1, 1);
+  gr->Fill(a,"(x^3+y^3)/2");  gr->Fill(b,"(x-y)/2");
+  gr->Puts(mglPoint(0, 1.1), "\\{\\frac{x^3+y^3}{2}, \\frac{x-y}{2}\\}", ":C", -2);
+  gr->Box();
+  gr->Map(a, b, "brgk");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{map, Example of Map().}
+
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Data interpolation, Making regular data, Mapping visualization, Hints
+ at subsection Data interpolation
+ at nav{}
+
+There are many functions to get interpolated values of a data array. Basically all of them can be divided by 3 categories:
+ at enumerate
+ at item functions which return single value at given point (see @ref{Interpolation} and @code{mglGSpline()} in @ref{Global functions});
+ at item functions @ref{subdata} and @ref{evaluate} for indirect access to data elements;
+ at item functions @ref{refill}, @ref{gspline} and @ref{datagrid} which fill regular (rectangular) data array by interpolated values.
+ at end enumerate
+
+The usage of first category is rather straightforward and don't need any special comments.
+
+There is difference in indirect access functions. Function @ref{subdata} use use step-like interpolation to handle correctly single @code{nan} values in the data array. Contrary, function @ref{evaluate} use local spline interpolation, which give smoother output but spread @code{nan} values. So, @ref{subdata} should be used for specific data elements (for example, for given column), and @ref{evaluate} should be used for distributed elements (i.e. consider data array as some field). Follow [...]
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(1,1,0,"");  gr->Title("SubData vs Evaluate");
+  mglData in(9), arg(99), e, s;
+  gr->Fill(in,"x^3/1.1"); gr->Fill(arg,"4*x+4");
+  gr->Plot(in,"ko ");     gr->Box();
+  e = in.Evaluate(arg,false); gr->Plot(e,"b.","legend 'Evaluate'");
+  s = in.SubData(arg);    gr->Plot(s,"r.","legend 'SubData'");
+  gr->Legend(2);
+}
+ at end verbatim
+
+ at pfig{indirect, Example of indirect data access.}
+
+Example of @ref{datagrid} usage is done in @ref{Making regular data}. Here I want to show the peculiarities of @ref{refill} and @ref{gspline} functions. Both functions require argument(s) which provide coordinates of the data values, and return rectangular data array which equidistantly distributed in axis range. So, in opposite to @ref{evaluate} function, @ref{refill} and @ref{gspline} can interpolate non-equidistantly distributed data. At this both functions @ref{refill} and @ref{gspli [...]
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData x(10), y(10), r(100);
+  x.Modify("0.5+rnd");  x.CumSum("x");  x.Norm(-1,1);
+  y.Modify("sin(pi*v)/1.5",x);
+  gr->SubPlot(2,2,0,"<_");  gr->Title("Refill sample");
+  gr->Axis();  gr->Box(); gr->Plot(x,y,"o ");
+  gr->Refill(r,x,y);  // or you can use r.Refill(x,y,-1,1);
+  gr->Plot(r,"r");  gr->FPlot("sin(pi*x)/1.5","B:");
+  gr->SubPlot(2,2,1,"<_");gr->Title("Global spline");
+  gr->Axis();  gr->Box(); gr->Plot(x,y,"o ");
+  r.RefillGS(x,y,-1,1);   gr->Plot(r,"r");
+  gr->FPlot("sin(pi*x)/1.5","B:");
+
+  gr->Alpha(true);  gr->Light(true);
+  mglData z(10,10), xx(10,10), yy(10,10), rr(100,100);
+  y.Modify("0.5+rnd");  y.CumSum("x");  y.Norm(-1,1);
+  for(int i=0;i<10;i++) for(int j=0;j<10;j++)
+    z.a[i+10*j] = sin(M_PI*x.a[i]*y.a[j])/1.5;
+  gr->SubPlot(2,2,2); gr->Title("2d regular");  gr->Rotate(40,60);
+  gr->Axis();  gr->Box(); gr->Mesh(x,y,z,"k");
+  gr->Refill(rr,x,y,z); gr->Surf(rr);
+
+  gr->Fill(xx,"(x+1)/2*cos(y*pi/2-1)");
+  gr->Fill(yy,"(x+1)/2*sin(y*pi/2-1)");
+  for(int i=0;i<10*10;i++)
+    z.a[i] = sin(M_PI*xx.a[i]*yy.a[i])/1.5;
+  gr->SubPlot(2,2,3); gr->Title("2d non-regular");  gr->Rotate(40,60);
+  gr->Axis();  gr->Box();  gr->Plot(xx,yy,z,"ko ");
+  gr->Refill(rr,xx,yy,z);  gr->Surf(rr);
+}
+ at end verbatim
+
+ at pfig{refill, Example of non-equidistant data interpolation.}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Making regular data, Making histogram, Data interpolation, Hints
+ at subsection Making regular data
+ at nav{}
+
+Sometimes, one have only unregular data, like as data on triangular grids, or experimental results and so on. Such kind of data cannot be used as simple as regular data (like matrices). Only few functions, like @ref{dots}, can handle unregular data as is.
+
+However, one can use built in triangulation functions for interpolating unregular data points to a regular data grids. There are 2 ways. First way, one can use @ref{triangulation} function to obtain list of vertexes for triangles. Later this list can be used in functions like @ref{triplot} or @ref{tricont}. Second way consist in usage of @ref{datagrid} function, which fill regular data grid by interpolated values, assuming that coordinates of the data grid is equidistantly distributed in [...]
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData x(100), y(100), z(100);
+  gr->Fill(x,"2*rnd-1"); gr->Fill(y,"2*rnd-1"); gr->Fill(z,"v^2-w^2",x,y);
+  // first way - plot triangular surface for points
+  mglData d = mglTriangulation(x,y);
+  gr->Title("Triangulation");
+  gr->Rotate(40,60);	gr->Box();	gr->Light(true);
+  gr->TriPlot(d,x,y,z);	gr->TriPlot(d,x,y,z,"#k");
+  // second way - make regular data and plot it
+  mglData g(30,30);
+  gr->DataGrid(g,x,y,z);	gr->Mesh(g,"m");
+}
+ at end verbatim
+
+ at pfig{triangulation, Example of triangulation.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Making histogram, Nonlinear fitting hints, Making regular data, Hints
+ at subsection Making histogram
+ at nav{}
+
+Using the @ref{hist} function(s) for making regular distributions is one of useful fast methods to process and plot irregular data. @code{Hist} can be used to find some momentum of set of points by specifying weight function. It is possible to create not only 1D distributions but also 2D and 3D ones. Below I place the simplest sample code which demonstrate @ref{hist} usage:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData x(10000), y(10000), z(10000);  gr->Fill(x,"2*rnd-1");
+  gr->Fill(y,"2*rnd-1"); gr->Fill(z,"exp(-6*(v^2+w^2))",x,y);
+  mglData xx=gr->Hist(x,z), yy=gr->Hist(y,z);	xx.Norm(0,1);
+  yy.Norm(0,1);
+  gr->MultiPlot(3,3,3,2,2,"");   gr->SetRanges(-1,1,-1,1,0,1);
+  gr->Box();  gr->Dots(x,y,z,"wyrRk");
+  gr->MultiPlot(3,3,0,2,1,"");   gr->SetRanges(-1,1,0,1);
+  gr->Box();  gr->Bars(xx);
+  gr->MultiPlot(3,3,5,1,2,"");   gr->SetRanges(0,1,-1,1);
+  gr->Box();  gr->Barh(yy);
+  gr->SubPlot(3,3,2);
+  gr->Puts(mglPoint(0.5,0.5),"Hist and\nMultiPlot\nsample","a",-6);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{hist, Example of Hist().}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Nonlinear fitting hints, PDE solving hints, Making histogram, Hints
+ at subsection Nonlinear fitting hints
+ at nav{}
+
+Nonlinear fitting is rather simple. All that you need is the data to fit, the approximation formula and the list of coefficients to fit (better with its initial guess values). Let me demonstrate it on the following simple example. First, let us use sin function with some random noise:
+ at verbatim
+  mglData dat(100), in(100); //data to be fitted and ideal data
+  gr->Fill(dat,"0.4*rnd+0.1+sin(2*pi*x)");
+  gr->Fill(in,"0.3+sin(2*pi*x)");
+ at end verbatim
+and plot it to see that data we will fit
+ at verbatim
+  gr->Title("Fitting sample");
+  gr->SetRange('y',-2,2); gr->Box();  gr->Plot(dat, "k. ");
+  gr->Axis(); gr->Plot(in, "b");
+  gr->Puts(mglPoint(0, 2.2), "initial: y = 0.3+sin(2\\pi x)", "b");
+ at end verbatim
+
+The next step is the fitting itself. For that let me specify an initial values @var{ini} for coefficients @samp{abc} and do the fitting for approximation formula @samp{a+b*sin(c*x)}
+ at verbatim
+  mreal ini[3] = {1,1,3};
+  mglData Ini(3,ini);
+  mglData res = gr->Fit(dat, "a+b*sin(c*x)", "abc", Ini);
+ at end verbatim
+Now display it
+ at verbatim
+  gr->Plot(res, "r");
+  gr->Puts(mglPoint(-0.9, -1.3), "fitted:", "r:L");
+  gr->PutsFit(mglPoint(0, -1.8), "y = ", "r");
+ at end verbatim
+
+NOTE! the fitting results may have strong dependence on initial values for coefficients due to algorithm features. The problem is that in general case there are several local "optimums" for coefficients and the program returns only first found one! There are no guaranties that it will be the best. Try for example to set @code{ini[3] = @{0, 0, 0@}} in the code above.
+
+The full sample code for nonlinear fitting is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData dat(100), in(100);
+  gr->Fill(dat,"0.4*rnd+0.1+sin(2*pi*x)");
+  gr->Fill(in,"0.3+sin(2*pi*x)");
+  mreal ini[3] = {1,1,3};
+  mglData Ini(3,ini);
+
+  mglData res = gr->Fit(dat, "a+b*sin(c*x)", "abc", Ini);
+
+  gr->Title("Fitting sample");
+  gr->SetRange('y',-2,2); gr->Box();  gr->Plot(dat, "k. ");
+  gr->Axis();   gr->Plot(res, "r"); gr->Plot(in, "b");
+  gr->Puts(mglPoint(-0.9, -1.3), "fitted:", "r:L");
+  gr->PutsFit(mglPoint(0, -1.8), "y = ", "r");
+  gr->Puts(mglPoint(0, 2.2), "initial: y = 0.3+sin(2\\pi x)", "b");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{fit, Example of nonlinear fitting.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node PDE solving hints, Drawing phase plain, Nonlinear fitting hints, Hints
+ at subsection PDE solving hints
+ at nav{}
+
+Solving of Partial Differential Equations (PDE, including beam tracing) and ray tracing (or finding particle trajectory) are more or less common task. So, MathGL have several functions for that. There are @ref{ray} for ray tracing, @ref{pde} for PDE solving, @ref{qo2d} for beam tracing in 2D case (see @ref{Global functions}). Note, that these functions take ``Hamiltonian'' or equations as string values. And I don't plan now to allow one to use user-defined functions. There are 2 reasons: [...]
+
+The ray tracing can be done by @ref{ray} function. Really ray tracing equation is Hamiltonian equation for 3D space. So, the function can be also used for finding a particle trajectory (i.e. solve Hamiltonian ODE) for 1D, 2D or 3D cases. The function have a set of arguments. First of all, it is Hamiltonian which defined the media (or the equation) you are planning to use. The Hamiltonian is defined by string which may depend on coordinates @samp{x}, @samp{y}, @samp{z}, time @samp{t} (for [...]
+ at verbatim
+  const char *ham = "p^2+q^2-x-1+i*0.5*(y+x)*(y>-x)";
+  mglData r = mglRay(ham, mglPoint(-0.7, -1), mglPoint(0, 0.5), 0.02, 2);
+ at end verbatim
+This example calculate the reflection from linear layer (media with Hamiltonian @samp{p^2+q^2-x-1}=@math{p_x^2+p_y^2-x-1}). This is parabolic curve. The resulting array have 7 columns which contain data for @{x,y,z,p,q,v,t@}.
+
+The solution of PDE is a bit more complicated. As previous you have to specify the equation as pseudo-differential operator @math{\hat H(x, \nabla)} which is called sometime as ``Hamiltonian'' (for example, in beam tracing). As previously, it is defined by string which may depend on coordinates @samp{x}, @samp{y}, @samp{z} (but not time!), momentums @samp{p}=@math{(d/dx)/i k_0}, @samp{q}=@math{(d/dy)/i k_0} and field amplitude @samp{u}=@math{|u|}. The evolutionary coordinate is @samp{z}  [...]
+
+Next step is specifying the initial conditions at @samp{z} equal to minimal z-axis value. The function need 2 arrays for real and for imaginary part. Note, that coordinates x,y,z are supposed to be in specified axis range. So, the data arrays should have corresponding scales. Finally, you may set the integration step and parameter k0=@math{k_0}. Also keep in mind, that internally the 2 times large box is used (for suppressing numerical reflection from boundaries) and the equation should  [...]
+
+Final comment is concerning the possible form of pseudo-differential operator @math{H}. At this moment, simplified form of operator @math{H} is supported -- all ``mixed'' terms (like @samp{x*p}->x*d/dx) are excluded. For example, in 2D case this operator is effectively @math{H = f(p,z) + g(x,z,u)}. However commutable combinations (like @samp{x*q}->x*d/dy) are allowed for 3D case.
+
+So, for example let solve the equation for beam deflected from linear layer and absorbed later. The operator will have the form @samp{"p^2+q^2-x-1+i*0.5*(z+x)*(z>-x)"} that correspond to equation @math{1/ik_0 * du/dz + d^2 u/dx^2 + d^2 u/dy^2 + x * u + i (x+z)/2 * u = 0}. This is typical equation for Electron Cyclotron (EC) absorption in magnetized plasmas. For initial conditions let me select the beam with plane phase front @math{exp(-48*(x+0.7)^2)}. The corresponding code looks like this:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,re(128),im(128);
+  gr->Fill(re,"exp(-48*(x+0.7)^2)");
+  a = gr->PDE("p^2+q^2-x-1+i*0.5*(z+x)*(z>-x)", re, im, 0.01, 30);
+  a.Transpose("yxz");
+  gr->SubPlot(1,1,0,"<_"); gr->Title("PDE solver");
+  gr->SetRange('c',0,1);  gr->Dens(a,"wyrRk");
+  gr->Axis(); gr->Label('x', "\\i x");  gr->Label('y', "\\i z");
+  gr->FPlot("-x", "k|");
+  gr->Puts(mglPoint(0, 0.85), "absorption: (x+z)/2 for x+z>0");
+  gr->Puts(mglPoint(0,1.1),"Equation: ik_0\\partial_zu + \\Delta u + x\\cdot u + i \\frac{x+z}{2}\\cdot u = 0");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{pde, Example of PDE solving.}
+
+The next example is the beam tracing. Beam tracing equation is special kind of PDE equation written in coordinates accompanied to a ray. Generally this is the same parameters and limitation as for PDE solving but the coordinates are defined by the ray and by parameter of grid width @var{w} in direction transverse the ray. So, you don't need to specify the range of coordinates. @strong{BUT} there is limitation. The accompanied coordinates are well defined only for smooth enough rays, i.e. [...]
+
+You may use following code for obtaining the same solution as in previous example:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData r, xx, yy, a, im(128), re(128);
+  const char *ham = "p^2+q^2-x-1+i*0.5*(y+x)*(y>-x)";
+  r = mglRay(ham, mglPoint(-0.7, -1), mglPoint(0, 0.5), 0.02, 2);
+  gr->SubPlot(1,1,0,"<_"); gr->Title("Beam and ray tracing");
+  gr->Plot(r.SubData(0), r.SubData(1), "k");
+  gr->Axis(); gr->Label('x', "\\i x");  gr->Label('y', "\\i z");
+
+  // now start beam tracing
+  gr->Fill(re,"exp(-48*x^2)");
+  a = mglQO2d(ham, re, im, r, xx, yy, 1, 30);
+  gr->SetRange('c',0, 1);
+  gr->Dens(xx, yy, a, "wyrRk");
+  gr->FPlot("-x", "k|");
+  gr->Puts(mglPoint(0, 0.85), "absorption: (x+y)/2 for x+y>0");
+  gr->Puts(mglPoint(0.7, -0.05), "central ray");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{qo2d, Example of beam tracing.}
+
+Note, the @ref{pde} is fast enough and suitable for many cases routine. However, there is situations then media have both together: strong spatial dispersion and spatial inhomogeneity. In this, case the @ref{pde} will produce incorrect result and you need to use advanced PDE solver @ref{apde}. For example, a wave beam, propagated in plasma, described by Hamiltonian @math{exp(-x^2-p^2)}, will have different solution for using of simplification and advanced PDE solver:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SetRanges(-1,1,0,2,0,2);
+  mglData ar(256), ai(256);	gr->Fill(ar,"exp(-2*x^2)");
+
+  mglData res1(gr->APDE("exp(-x^2-p^2)",ar,ai,0.01));	res1.Transpose();
+  gr->SubPlot(1,2,0,"_");	gr->Title("Advanced PDE solver");
+  gr->SetRanges(0,2,-1,1);	gr->SetRange('c',res1);
+  gr->Dens(res1);	gr->Axis();	gr->Box();
+  gr->Label('x',"\\i z");	gr->Label('y',"\\i x");
+  gr->Puts(mglPoint(-0.5,0.2),"i\\partial_z\\i u = exp(-\\i x^2+\\partial_x^2)[\\i u]","y");
+
+  mglData res2(gr->PDE("exp(-x^2-p^2)",ar,ai,0.01));
+  gr->SubPlot(1,2,1,"_");	gr->Title("Simplified PDE solver");
+  gr->Dens(res2);	gr->Axis();	gr->Box();
+  gr->Label('x',"\\i z");	gr->Label('y',"\\i x");
+  gr->Puts(mglPoint(-0.5,0.2),"i\\partial_z\\i u \\approx\\ exp(-\\i x^2)\\i u+exp(\\partial_x^2)[\\i u]","y");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{apde, Comparison of simplified and advanced PDE solvers.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Drawing phase plain, Pulse properties, PDE solving hints, Hints
+ at subsection Drawing phase plain
+ at nav{}
+
+Here I want say a few words of plotting phase plains. Phase plain is name for system of coordinates @math{x}, @math{x'}, i.e. a variable and its time derivative. Plot in phase plain is very useful for qualitative analysis of an ODE, because such plot is rude (it topologically the same for a range of ODE parameters). Most often the phase plain @{@math{x}, @math{x'}@} is used (due to its simplicity), that allows to analyze up to the 2nd order ODE (i.e. @math{x''+f(x,x')=0}).
+
+The simplest way to draw phase plain in MathGL is using @ref{flow} function(s), which automatically select several points and draw flow threads. If the ODE have an integral of motion (like Hamiltonian @math{H(x,x')=const} for dissipation-free case) then you can use @ref{cont} function for plotting isolines (contours). In fact. isolines are the same as flow threads, but without arrows on it. Finally, you can directly solve ODE using @ref{ode} function and plot its numerical solution.
+
+Let demonstrate this for ODE equation @math{x''-x+3*x^2=0}. This is nonlinear oscillator with square nonlinearity. It has integral @math{H=y^2+2*x^3-x^2=Const}. Also it have 2 typical stationary points: saddle at @{x=0, y=0@} and center at @{x=1/3, y=0@}. Motion at vicinity of center is just simple oscillations, and is stable to small variation of parameters. In opposite, motion around saddle point is non-stable to small variation of parameters, and is very slow. So, calculation around s [...]
+
+So, let draw this phase plain by 3 different methods. First, draw isolines for @math{H=y^2+2*x^3-x^2=Const} -- this is simplest for ODE without dissipation. Next, draw flow threads -- this is straightforward way, but the automatic choice of starting points is not always optimal. Finally, use @ref{ode} to check the above plots. At this we need to run @ref{ode} in both direction of time (in future and in the past) to draw whole plain. Alternatively, one can put starting points far from (or [...]
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(2,2,0,"<_");  gr->Title("Cont");  gr->Box();
+  gr->Axis();  gr->Label('x',"x");  gr->Label('y',"\\dot{x}");
+  mglData f(100,100);   gr->Fill(f,"y^2+2*x^3-x^2-0.5");
+  gr->Cont(f);
+  gr->SubPlot(2,2,1,"<_");  gr->Title("Flow");  gr->Box();
+  gr->Axis();  gr->Label('x',"x");  gr->Label('y',"\\dot{x}");
+  mglData fx(100,100), fy(100,100);
+  gr->Fill(fx,"x-3*x^2");  gr->Fill(fy,"y");
+  gr->Flow(fy,fx,"v","value 7");
+  gr->SubPlot(2,2,2,"<_");  gr->Title("ODE");   gr->Box();
+  gr->Axis();  gr->Label('x',"x");  gr->Label('y',"\\dot{x}");
+  for(double x=-1;x<1;x+=0.1)
+  {
+    mglData in(2), r;   in.a[0]=x;
+    r = mglODE("y;x-3*x^2","xy",in);
+    gr->Plot(r.SubData(0), r.SubData(1));
+    r = mglODE("-y;-x+3*x^2","xy",in);
+    gr->Plot(r.SubData(0), r.SubData(1));
+  }
+}
+ at end verbatim
+
+ at pfig{ode, Example of ODE solving and phase plain drawing.}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Pulse properties, Using MGL parser, Drawing phase plain, Hints
+ at subsection Pulse properties
+ at nav{}
+
+There is common task in optics to determine properties of wave pulses or wave beams. MathGL provide special function @ref{pulse} which return the pulse properties (maximal value, center of mass, width and so on). Its usage is rather simple. Here I just illustrate it on the example of Gaussian pulse, where all parameters are obvious.
+ at verbatim
+void sample(mglGraph *gr)
+{
+  gr->SubPlot(1,1,0,"<_");  gr->Title("Pulse sample");
+  // first prepare pulse itself
+  mglData a(100); gr->Fill(a,"exp(-6*x^2)");
+  // get pulse parameters
+  mglData b(a.Pulse('x'));
+  // positions and widths are normalized on the number of points. So, set proper axis scale.
+  gr->SetRanges(0, a.nx-1, 0, 1);
+  gr->Axis(); gr->Plot(a);  // draw pulse and axis
+  // now visualize found pulse properties
+  double m = b[0];  // maximal amplitude
+  // approximate position of maximum
+  gr->Line(mglPoint(b[1],0), mglPoint(b[1],m),"r=");
+  // width at half-maximum (so called FWHM)
+  gr->Line(mglPoint(b[1]-b[3]/2,0), mglPoint(b[1]-b[3]/2,m),"m|");
+  gr->Line(mglPoint(b[1]+b[3]/2,0), mglPoint(b[1]+b[3]/2,m),"m|");
+  gr->Line(mglPoint(0,m/2), mglPoint(a.nx-1,m/2),"h");
+  // parabolic approximation near maximum
+  char func[128];	sprintf(func,"%g*(1-((x-%g)/%g)^2)",b[0],b[1],b[2]);
+  gr->FPlot(func,"g");
+}
+ at end verbatim
+
+ at pfig{pulse, Example of determining of pulse properties.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Using MGL parser, Using options, Pulse properties, Hints
+ at subsection Using MGL parser
+ at nav{}
+
+Sometimes you may prefer to use MGL scripts in yours code. It is simpler (especially in comparison with C/Fortran interfaces) and provide faster way to plot the data with annotations, labels and so on. Class @code{mglParse} (@pxref{mglParse class} parse MGL scripts in C++. It have also the corresponding interface for C/Fortran.
+
+The key function here is @code{mglParse::Parse()} (or @code{mgl_parse()} for C/Fortran) which execute one command per string. At this the detailed information about the possible errors or warnings is passed as function value. Or you may execute the whole script as long string with lines separated by @samp{\n}. Functions @code{mglParse::Execute()} and @code{mgl_parse_text()} perform it. Also you may set the values of parameters @samp{$0}... at samp{$9} for the script by functions @code{mglPa [...]
+
+The only non-obvious thing is data transition between script and yours program. There are 2 stages: add or find variable; and set data to variable. In C++ you may use functions @code{mglParse::AddVar()} and @code{mglParse::FindVar()} which return pointer to @code{mglData}. In C/Fortran the corresponding functions are @code{mgl_add_var()}, @code{mgl_find_var()}. This data pointer is valid until next @code{Parse()} or @code{Execute()} call. Note, you @strong{must not delete or free} the da [...]
+
+So, some simple example at the end. Here I define a data array, create variable, put data into it and plot it. The C++ code looks like this:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->Title("MGL parser sample");
+  mreal a[100];   // let a_i = sin(4*pi*x), x=0...1
+  for(int i=0;i<100;i++)a[i]=sin(4*M_PI*i/99);
+  mglParse *parser = new mglParse;
+  mglData *d = parser->AddVar("dat");
+  d->Set(a,100); // set data to variable
+  parser->Execute(gr, "plot dat; xrange 0 1\nbox\naxis");
+  // you may break script at any line do something
+  // and continue after that
+  parser->Execute(gr, "xlabel 'x'\nylabel 'y'\nbox");
+  // also you may use cycles or conditions in script
+  parser->Execute(gr, "for $0 -1 1 0.1\nif $0<0\n"
+    "line 0 0 -1 $0 'r':else:line 0 0 -1 $0 'g'\n"
+    "endif\nnext");
+  delete parser;
+  return 0;
+}
+ at end verbatim
+The code in C/Fortran looks practically the same:
+ at verbatim
+int sample(HMGL gr)
+{
+  mgl_title(gr, "MGL parser sample", "", -2);
+  double a[100];   // let a_i = sin(4*pi*x), x=0...1
+  int i;
+  for(i=0;i<100;i++)  a[i]=sin(4*M_PI*i/99);
+  HMPR parser = mgl_create_parser();
+  HMDT d = mgl_parser_add_var(parser, "dat");
+  mgl_data_set_double(d,a,100,1,1);    // set data to variable
+  mgl_parse_text(gr, parser, "plot dat; xrange 0 1\nbox\naxis");
+  // you may break script at any line do something
+  // and continue after that
+  mgl_parse_text(gr, parser, "xlabel 'x'\nylabel 'y'");
+  // also you may use cycles or conditions in script
+  mgl_parse_text(gr, parser, "for $0 -1 1 0.1\nif $0<0\n"
+    "line 0 0 -1 $0 'r':else:line 0 0 -1 $0 'g'\n"
+    "endif\nnext");
+  mgl_write_png(gr, "test.png", "");  // don't forgot to save picture
+  return 0;
+}
+ at end verbatim
+
+ at pfig{parser, Example of MGL script parsing.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Using options, ``Templates'', Using MGL parser, Hints
+ at subsection Using options
+ at nav{}
+
+ at ref{Command options} allow the easy setup of the selected plot by changing global settings only for this plot. Often, options are used for specifying the range of automatic variables (coordinates). However, options allows easily change plot transparency, numbers of line or faces to be drawn, or add legend entries. The sample function for options usage is:
+ at verbatim
+void template(mglGraph *gr)
+{
+  mglData a(31,41);
+  gr->Fill(a,"-pi*x*exp(-(y+1)^2-4*x^2)");
+
+  gr->SubPlot(2,2,0);	gr->Title("Options for coordinates");
+  gr->Alpha(true);	gr->Light(true);
+  gr->Rotate(40,60);    gr->Box();
+  gr->Surf(a,"r","yrange 0 1"); gr->Surf(a,"b","yrange 0 -1");
+  if(mini)	return;
+  gr->SubPlot(2,2,1);   gr->Title("Option 'meshnum'");
+  gr->Rotate(40,60);    gr->Box();
+  gr->Mesh(a,"r","yrange 0 1"); gr->Mesh(a,"b","yrange 0 -1; meshnum 5");
+  gr->SubPlot(2,2,2);   gr->Title("Option 'alpha'");
+  gr->Rotate(40,60);    gr->Box();
+  gr->Surf(a,"r","yrange 0 1; alpha 0.7");
+  gr->Surf(a,"b","yrange 0 -1; alpha 0.3");
+  gr->SubPlot(2,2,3,"<_");  gr->Title("Option 'legend'");
+  gr->FPlot("x^3","r","legend 'y = x^3'");
+  gr->FPlot("cos(pi*x)","b","legend 'y = cos \\pi x'");
+  gr->Box();    gr->Axis(); gr->Legend(2,"");
+}
+ at end verbatim
+
+ at pfig{mirror, Example of options usage.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ``Templates'', Stereo image, Using options, Hints
+ at subsection ``Templates''
+ at nav{}
+
+As I have noted before, the change of settings will influence only for the further plotting commands. This allows one to create ``template'' function which will contain settings and primitive drawing for often used plots. Correspondingly one may call this template-function for drawing simplification.
+
+For example, let one has a set of points (experimental or numerical) and wants to compare it with theoretical law (for example, with exponent law @math{\exp(-x/2), x \in [0, 20]}). The template-function for this task is:
+ at verbatim
+void template(mglGraph *gr)
+{
+  mglData  law(100);      // create the law
+  law.Modify("exp(-10*x)");
+  gr->SetRanges(0,20, 0.0001,1);
+  gr->SetFunc(0,"lg(y)",0);
+  gr->Plot(law,"r2");
+  gr->Puts(mglPoint(10,0.2),"Theoretical law: e^x","r:L");
+  gr->Label('x',"x val."); gr->Label('y',"y val.");
+  gr->Axis(); gr->Grid("xy","g;"); gr->Box();
+}
+ at end verbatim
+At this, one will only write a few lines for data drawing:
+ at verbatim
+  template(gr);     // apply settings and default drawing from template
+  mglData dat("fname.dat"); // load the data
+  // and draw it (suppose that data file have 2 columns)
+  gr->Plot(dat.SubData(0),dat.SubData(1),"bx ");
+ at end verbatim
+A template-function can also contain settings for font, transparency, lightning, color scheme and so on.
+
+I understand that this is obvious thing for any professional programmer, but I several times receive suggestion about ``templates'' ... So, I decide to point out it here.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Stereo image, Reduce memory usage, ``Templates'', Hints
+ at subsection Stereo image
+ at nav{}
+
+One can easily create stereo image in MathGL. Stereo image can be produced by making two subplots with slightly different rotation angles. The corresponding code looks like this:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->Light(true);
+
+  gr->SubPlot(2,1,0); gr->Rotate(50,60+1);
+  gr->Box();  gr->Surf(a);
+
+  gr->SubPlot(2,1,1); gr->Rotate(50,60-1);
+  gr->Box();  gr->Surf(a);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{stereo, Example of stereo image.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Reduce memory usage, Saving and scanning file, Stereo image, Hints
+ at subsection Reduce memory usage
+ at nav{}
+
+By default MathGL save all primitives in memory, rearrange it and only later draw them on bitmaps. Usually, this speed up drawing, but may require a lot of memory for plots which contain a lot of faces (like @ref{cloud}, @ref{dew}). You can use @ref{quality} function for setting to use direct drawing on bitmap and bypassing keeping any primitives in memory. This function also allow you to decrease the quality of the resulting image but increase the speed of the drawing.
+
+The code for lowest memory usage looks like this:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SetQuality(6);   // firstly, set to draw directly on bitmap
+  for(i=0;i<1000;i++)
+    gr->Sphere(mglPoint(mgl_rnd()*2-1,mgl_rnd()*2-1),0.05);
+  return 0;
+}
+ at end verbatim
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Saving and scanning file, Mixing bitmap and vector output, Reduce memory usage, Hints
+ at subsection Scanning file
+ at nav{}
+
+MathGL have possibilities to write textual information into file with variable values. In MGL script you can use @ref{save} command for that. However, the usual @code{printf();} is simple in C/C++ code. For example, lets create some textual file
+ at verbatim
+FILE *fp=fopen("test.txt","w");
+fprintf(fp,"This is test: 0 -> 1 q\n");
+fprintf(fp,"This is test: 1 -> -1 q\n");
+fprintf(fp,"This is test: 2 -> 0 q\n");
+fclose(fp);
+ at end verbatim
+It contents look like
+ at verbatim
+This is test: 0 -> 1 q
+This is test: 1 -> -1 q
+This is test: 2 -> 0 q
+ at end verbatim
+
+Let assume now that you want to read this values (i.e. [[0,1],[1,-1],[2,0]]) from the file. You can use @ref{scanfile} for that. The desired values was written using template "This is test: %g -> %g q\n". So, just use
+ at verbatim
+mglData a;
+a.ScanFile("test.txt","This is test: %g -> %g");
+ at end verbatim
+and plot it to for assurance
+ at verbatim
+gr->SetRanges(a.SubData(0), a.SubData(1));
+gr->Axis();	gr->Plot(a.SubData(0),a.SubData(1),"o");
+ at end verbatim
+
+Note, I keep only the leading part of template (i.e. "This is test: %g -> %g" instead of "This is test: %g -> %g q\n"), because there is no important for us information after the second number in the line.
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Mixing bitmap and vector output, , Saving and scanning file, Hints
+ at subsection Mixing bitmap and vector output
+ at nav{}
+
+Sometimes output plots contain surfaces with a lot of points, and some vector primitives (like axis, text, curves, etc.). Using vector output formats (like EPS or SVG) will produce huge files with possible loss of smoothed lighting. Contrary, the bitmap output may cause the roughness of text and curves. Hopefully, MathGL have a possibility to combine bitmap output for surfaces and vector one for other primitives in the same EPS file, by using @ref{rasterize} command. 
+
+The idea is to prepare part of picture with surfaces or other "heavy" plots and produce the background image from them by help of @ref{rasterize} command. Next, we draw everything to be saved in vector form (text, curves, axis and etc.). Note, that you need to clear primitives (use @ref{clf} command) after @ref{rasterize} if you want to disable duplication of surfaces in output files (like EPS). Note, that some of output formats (like 3D ones, and TeX) don't support the background bitmap [...]
+
+The sample code is:
+ at verbatim
+// first draw everything to be in bitmap output
+gr->FSurf("x^2+y^2", "#", "value 10");
+
+gr->Rasterize();  // set above plots as bitmap background
+gr->Clf();        // clear primitives, to exclude them from file
+
+// now draw everything to be in vector output
+gr->Axis(); gr->Box();
+
+// and save file
+gr->WriteFrame("fname.eps");
+ at end verbatim
+
+
+ at c ==================================================================
+ at external{}
+ at node FAQ, , Hints, Examples
+ at section FAQ
+ at nav{}
+
+ at table @strong
+ at item The plot does not appear
+Check that points of the plot are located inside the bounding box and resize the bounding box using @ref{ranges} function. Check that the data have correct dimensions for selected type of plot. Be sure that  @code{Finish()} is called after the plotting functions (or be sure that the plot is saved to a file). Sometimes the light reflection from flat surfaces (like, @ref{dens}) can look as if the plot were absent.
+
+ at item I can not find some special kind of plot.
+Most ``new'' types of plots can be created by using the existing drawing functions. For example, the surface of curve rotation can be created by a special function @ref{torus}, or as a parametrically specified surface by @ref{surf}. See also, @ref{Hints}. If you can not find a specific type of plot, please e-mail me and this plot will appear in the next version of MathGL library.
+
+ at item Should I know some graphical libraries (like OpenGL) before using the MathGL library?
+No. The MathGL library is self-contained and does not require the knowledge of external libraries.
+
+ at item In which language is the library written? For which languages does it have an interface?
+The core of the MathGL library is written in C++. But there are interfaces for: pure C, Fortran, Pascal, Forth, and its own command language MGL. Also there is a large set of interpreted languages, which are supported (Python, Java,  ALLEGROCL, CHICKEN, Lisp, CFFI, C#, Guile, Lua, Modula 3, Mzscheme, Ocaml, Octave, Perl, PHP, Pike, R, Ruby, Tcl). These interfaces are written using SWIG (both pure C functions and classes) but only the interface for Python and Octave is included in the bui [...]
+
+ at item How can I use MathGL with Fortran?
+You can use MathGL as is with @code{gfortran} because it uses by default the AT&T notation for external functions. For other compilers (like Visual Fortran) you have to switch on the AT&T notation manually. The AT&T notation requires that the symbol @samp{_} is added at the end of each function name, function argument(s) is passed by pointers and the string length(s) is passed at the end of the argument list. For example:
+
+ at emph{C function} -- @code{void mgl_fplot(HMGL graph, const char *fy, const char *stl, int n);}
+
+ at emph{AT&T function} -- @code{void mgl_fplot_(uintptr_t *graph, const char *fy, const char *stl, int *n, int ly, int ls);}
+
+Fortran users also should add C++ library by the option @code{-lstdc++}. If library was built with @code{enable-double=ON} (this default for v.2.1 and later) then all real numbers must be @code{real*8}. You can make it automatic if use option @code{-fdefault-real-8}.
+
+ at item How can I print in Russian/Spanish/Arabic/Japanese, and so on?
+The standard way is to use Unicode encoding for the text output. But the MathGL library also has interface for 8-bit (char *) strings with internal conversion to Unicode. This conversion depends on the current locale OS. You may change it by @code{setlocale()} function. For example, for Russian text in CP1251 encoding you may use @code{setlocale(LC_CTYPE, "ru_RU.cp1251");} (under MS Windows the name of locale may differ -- @code{setlocale(LC_CTYPE, "russian_russia.1251")}). I strongly re [...]
+
+ at item How can I exclude a point or a region of plot from the drawing?
+There are 3 general ways. First, the point with @code{NAN} value as one of the coordinates (including color/alpha range) will never be plotted. Second, special functions @code{SetCutBox}() and @code{CutOff}() define the condition when the points should be omitted (see @ref{Cutting}). Last, you may change the transparency of a part of the plot by the help of functions @ref{surfa}, @ref{surf3a} (see @ref{Dual plotting}). In last case the transparency is switched on smoothly.
+
+ at item I use VisualStudio, CBuilder or some other compiler (not MinGW/gcc). How can I link the MathGL library?
+In version 2.0, main classes (@code{mglGraph} and @code{mglData}) contains only @code{inline} functions and are acceptable for any compiler with the same binary files. However, if you plan to use widget classes (QMathGL, Fl_MathGL, ...) or to access low-level features (mglBase, mglCanvas, ...) then you have to recompile MathGL by yours compiler.
+
+Note, that you have to make import library(-ies) *.lib for provided binary *.dll. This procedure depend on used compiler -- please read documentation for yours compiler. For VisualStudio, it can be done by command @code{lib.exe /DEF:libmgl.def /OUT:libmgl.lib}.
+
+ at item How make FLTK/GLUT/Qt window which will display result of my calculations?
+
+You need to put yours calculations or main event-handling loop in the separate thread. For static image you can give @code{NULL} as drawing function and call @code{Update()} function when you need to redraw it. For more details see @ref{Animation}.
+
+ at item How I can build MathGL under Windows?
+Generally, it is the same procedure as for Linux or MacOS -- see section @ref{Installation}. The simplest way is using the combination CMake+MinGW. Also you may need some extra libraries like GSL, PNG, JPEG and so on. All of them can be found at @url{http://gnuwin32.sourceforge.net/packages.html}. After installing all components, just run @uref{http://www.cmake.org/cmake/help/runningcmake.html, cmake-gui} configurator and build the MathGL itself.
+
+ at item How many people write this library?
+Most of the library was written by one person. This is a result of nearly a year of work (mostly in the evening and on holidays): I spent half a year to write the kernel and half a year to a year on extending, improving the library and writing documentation. This process continues now :). The build system (cmake files) was written mostly by D.Kulagin, and the export to PRC/PDF was written mostly by M.Vidassov.
+
+ at item How can I display a bitmap on the figure?
+You can import data into a @code{mglData} instance by function @ref{import} and display it by @ref{dens} function. For example, for black-and-white bitmap you can use the code: @code{mglData bmp; bmp.Import("fname.png","wk"); gr->Dens(bmp,"wk");}.
+
+ at item How can I use MathGL in Qt, FLTK, wxWidgets etc.?
+There are special classes (widgets) for these libraries: QMathGL for Qt, Fl_MathGL for FLTK and so on. If you don't find the appropriate class then you can create your own widget that displays a bitmap using mglCanvas::GetRGB().
+
+ at item How can I create 3D in PDF?
+Just use @code{WritePRC}() method which also create PDF file if enable-pdf=ON at MathGL configure.
+
+ at item How can I create TeX figure?
+Just use @code{WriteTEX}() method which create LaTeX files with figure itself @samp{@var{fname}.tex}, with MathGL colors @samp{mglcolors.tex} and main file @samp{mglmain.tex}. Last one can be used for viewing image by command like @code{pdflatex mglmain.tex}.
+
+ at item Can I use MathGL in JavaScript?
+Yes, sample JavaScript file is located in texinfo/ folder of sources. You should provide JSON data with 3d image for it (can be created by @code{WriteJSON}() method). Script allows basic manipulation with plot: zoom, rotation, shift. Sample of JavaScript pictures can be found in @url{http://mathgl.sf.net/json.html}.
+
+
+
+
+ at item How I can change the font family?
+First, you should download new font files from @uref{http://mathgl.sourceforge.net/download.html, here} or from @uref{http://sourceforge.net/project/showfiles.php?group_id=152187&package_id=267177, here}. Next, you should load the font files into mglGraph class instance @var{gr} by the following command: @code{gr->LoadFont(fontname,path);}. Here @var{fontname} is the base font name like @samp{STIX} and @var{path} sets the location of font files. Use @code{gr->RestoreFont();} to start usi [...]
+
+ at item How can I draw tick out of a bounding box?
+Just set a negative value in @ref{ticklen}. For example, use @code{gr->SetTickLen(-0.1);}.
+
+ at item How can I prevent text rotation?
+Just use @code{SetRotatedText(false)}. Also you can use axis style @samp{U} for disable only tick labels rotation.
+
+ at item What is @code{*.so}? What is @code{gcc}? How I can use @code{make}?
+They are standard GNU tools. There is special FAQ about its usage under Windows -- @uref{http://www.mingw.org/wiki/FAQ}.
+
+ at item How can I draw equal axis range even for rectangular image?
+Just use @code{Aspect(NAN,NAN)} for each subplot, or at the beginning of the drawing.
+
+ at item How I can set transparent background?
+Just use code like @code{Clf("r@{A5@}");} or prepare PNG file and set it as background image by call @code{LoadBackground("fname.png");}.
+
+ at item How I can reduce "white" edges around bounding box?
+The simplest way is to use @ref{subplot} style. However, you should be careful if you plan to add @ref{colorbar} or rotate plot -- part of plot can be invisible if you will use non-default @ref{subplot} style.
+
+ at item Can I combine bitmap and vector output in EPS?
+Yes. Sometimes you may have huge surface and a small set of curves and/or text on the plot. You can use function @ref{rasterize} just after making surface plot. This will put all plot to bitmap background. At this later plotting will be in vector format. For example, you can do something like following:
+ at verbatim
+gr->Surf(x, y, z);
+gr->Rasterize(); // make surface as bitmap
+gr->Axis();
+gr->WriteFrame("fname.eps");
+ at end verbatim
+
+ at item Why I couldn't use name @samp{I} for variable?
+MathGL support C99 standard, where @samp{I} is reserved for imaginary unit. If you still need this name, then just use
+ at verbatim
+#undef I
+ at end verbatim
+after including MathGL header files.
+
+ at item How I can create MPEG video from plots?
+You can save each frame into JPEG with names like @samp{frame0001.jpg}, @samp{frame0002.jpg}, ... Later you can use ImageMagic to convert them into MPEG video by command @code{convert frame*.jpg movie.mpg}. See also @ref{MPEG}.
+
+ at end table
+
+ at external{}
diff --git a/texinfo/example_ru.texi b/texinfo/example_ru.texi
new file mode 100644
index 0000000..49b3916
--- /dev/null
+++ b/texinfo/example_ru.texi
@@ -0,0 +1,4619 @@
+ at c ------------------------------------------------------------------
+ at chapter Примеры MathGL
+ at nav{}
+
+В данной главе рассмотрены базовые и продвинутые возможности MathGL, даны советы по использованию и примеры для всех типов графиков. Я рекомендую прочитать вначале первые 2 раздела и посмотреть на раздел @ref{Hints}. Также рекомендую прочитать @ref{General concepts} и @ref{FAQ}.
+
+Отмечу, что MathGL v.2.* имеет только пользовательских 2 интерфейса: один для языков подобных C или Fortran (не поддерживающих классы), другой для языков подобных C++/Python/Octave, которые поддерживают классы. При этом все классы являются "оберткой" С-ого интерфейсы, а функции-члены классов -- inline вызовами функций С. Поэтому, в большинстве примеров в этой главе я буду приводить только один вариант кода, который после минимальных изменений синтаксиса может быть применен для других язы [...]
+ at verbatim
+#include <mgl2/mgl.h>
+int main()
+{
+  mglGraph gr;
+  gr.FPlot("sin(pi*x)");
+  gr.WriteFrame("test.png");
+}
+ at end verbatim
+на Python будет выглядеть как
+ at verbatim
+from mathgl import *
+gr = mglGraph();
+gr.FPlot("sin(pi*x)");
+gr.WriteFrame("test.png");
+ at end verbatim
+в Octave он будет почти тем же (в новых версиях надо предварительно выполнить @code{mathgl;})
+ at verbatim
+gr = mglGraph();
+gr.FPlot("sin(pi*x)");
+gr.WriteFrame("test.png");
+ at end verbatim
+в C необходимо будет найти С-ые аналоги функций (из документации) и указать все их аргументы явно
+ at verbatim
+#include <mgl2/mgl_cf.h>
+int main()
+{
+  HMGL gr = mgl_create_graph(600,400);
+  mgl_fplot(gr,"sin(pi*x)","","");
+  mgl_write_frame(gr,"test.png","");
+  mgl_delete_graph(gr);
+}
+ at end verbatim
+в Fortran помимо этого придется определить функции возвращающие указатели на объекты как функции возвращающие целое
+ at verbatim
+integer gr, mgl_create_graph
+gr = mgl_create_graph(600,400);
+call mgl_fplot(gr,'sin(pi*x)','','');
+call mgl_write_frame(gr,'test.png','');
+call mgl_delete_graph(gr);
+ at end verbatim
+и т.д.
+
+
+
+ at menu
+* Basic usage::
+* Advanced usage::
+* Data handling::
+* Data plotting::
+* 1D samples::
+* 2D samples::
+* 3D samples::
+* Vector field samples::
+* Hints::
+* FAQ::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Basic usage, Advanced usage, , Examples
+ at section Основы использования
+ at nav{}
+
+Библиотеку MathGL можно использовать несколькими способами, каждый из которых имеет свои достоинства и недостатки:
+ at itemize @bullet
+ at item
+ at emph{Использовать возможности MathGL для создания графического окна (требуется FLTK, Qt или GLUT библиотеки).}
+
+Положительная сторона состоит в возможности сразу увидеть график и быстро его мышкой поправить (повернуть, приблизить, выключить прозрачность или освещение и т.д.). Однако, в этом случае требуется наличие графической системы (нельзя запускать на удаленной машине), и работать можно только с одним набором данных одновременно.
+
+ at item
+ at emph{Прямой вывод в файл в растровом или векторном формате, без создания графического окна.}
+
+Достоинства такого подхода: пакетная обработка похожих данных (например, набора расчетных файлов при различных условиях), возможность запуска из консольной программы (включая запуск на удаленном компьютере/сервере/кластере), более быстрая и автоматизированная отрисовка, сохранение графиков для последующего анализа непосредственно во время расчета. К недостаткам подхода можно отнести: использование внешней программы просмотра для построенных графиков, необходимость заранее представить кар [...]
+
+ at item
+ at emph{Рисовать график в памяти с последующим выводом на экран другой графической программой.}
+
+В этом случае программист имеет максимум свободы в выборе графической библиотеки (не только FLTK, Qt или GLUT), в расположении и выборе элементов управления графиком и т.д. Я рекомендую этот вариант для "самодостаточного" приложения.
+
+ at item
+ at emph{Использовать FLTK или Qt виджеты, предоставляемые MathGL}
+
+Вы также можете использовать ряд элементов управления (виджетов), которые позволяют отобразить график, сохранить его в файл в различных форматах или скопировать в буфер обмена, обработать движение/клики мышкой и пр.
+ at end itemize
+
+Графики MathGL могут быть созданы не только с помощью объектно-ориентированных языков (например, C++ или Python), но и на C или Fortran подобных языках. Использование последних в основном идентичны использованию классов (за исключением различных имен функций). Различие состоит в обязательном предварительном создании (и удалении после использования) объектов типа HMGL (для графики) и/или HMDT (для данных). Пользователи Fortran могут считать эти переменные целочисленными с достаточной разр [...]
+
+Рассмотрим вышесказанное подробно.
+
+ at menu
+* Using MathGL window::
+* Drawing to file::
+* Animation::
+* Drawing in memory::
+* Draw and calculate::
+* Using QMathGL::
+* MathGL and PyQt::
+* MathGL and MPI::
+ at end menu
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Using MathGL window, Drawing to file, , Basic usage
+ at subsection Использование окон MathGL
+ at nav{}
+ at cindex window
+ at cindex widgets
+
+``Интерактивный'' способ использования MathGL состоит в создании окна с помощью классов @code{mglQT}, @code{mglFLTK} или @code{mglGLUT} (см. @ref{Widget classes}) и последующем рисовании в этом окне. Соответствующий код выглядит так:
+ at verbatim
+#include <mgl2/qt.h>
+int sample(mglGraph *gr)
+{
+  gr->Rotate(60,40);
+  gr->Box();
+  return 0;
+}
+//-----------------------------------------------------
+int main(int argc,char **argv)
+{
+  mglQT gr(sample,"MathGL examples");
+  return gr.Run();
+}
+ at end verbatim
+Здесь используется callback функция @code{sample}, выполняющая собственно рисование. Функция @code{main} -- точка входа в программу -- создает окно (объект @var{gr} типа @code{mglQT}) и запускает цикл обработки сообщений (вызов @code{gr.Run()}). Для компиляции достаточно выполнить команду
+ at verbatim
+gcc test.cpp -lmgl-qt5 -lmgl
+ at end verbatim
+Вы можете использовать "-lmgl-qt4" вместо "-lmgl-qt5", если установлен Qt4.
+
+Альтернативный способ состоит в использовании класса, производного от @code{mglDraw} с переопределенной функцией @code{Draw()}:
+ at verbatim
+#include <mgl2/qt.h>
+class Foo : public mglDraw
+{
+public:
+  int Draw(mglGraph *gr);
+};
+//-----------------------------------------------------
+int Foo::Draw(mglGraph *gr)
+{
+  gr->Rotate(60,40);
+  gr->Box();
+  return 0;
+}
+//-----------------------------------------------------
+int main(int argc,char **argv)
+{
+  Foo foo;
+  mglQT gr(&foo,"MathGL examples");
+  return gr.Run();
+}
+ at end verbatim
+Или в использовании функций С:
+ at verbatim
+#include <mgl2/mgl_cf.h>
+int sample(HMGL gr, void *)
+{
+  mgl_rotate(gr,60,40,0);
+  mgl_box(gr);
+}
+int main(int argc,char **argv)
+{
+  HMGL gr;
+  gr = mgl_create_graph_qt(sample,"MathGL examples",0,0);
+  return mgl_qt_run();
+/* generally I should call mgl_delete_graph() here,
+ * but I omit it in main() function. */
+}
+ at end verbatim
+
+Похожий код получается и при использовании окон @code{mglFLTK}, @code{mglGLUT} (функция @code{sample()} та же):
+ at verbatim
+#include <mgl2/glut.h>
+int main(int argc,char **argv)
+{
+  mglGLUT gr(sample,"MathGL examples");
+  return 0;
+}
+ at end verbatim
+
+The rotation, shift, zooming, switching on/off transparency and lighting can be done with help of tool-buttons (for @code{mglWindow}) or by hot-keys: @samp{a}, @samp{d}, @samp{w}, @samp{s} for plot rotation, @samp{r} and @samp{f} switching on/off transparency and lighting. Press @samp{x} for exit (or closing the window).
+
+In this example function @code{sample} rotates axes (@code{Rotate()}, @pxref{Subplots and rotation}) and draws the bounding box (@code{Box()}). Drawing is placed in separate function since it will be used on demand when window canvas needs to be redrawn.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Drawing to file, Animation, Using MathGL window, Basic usage
+ at subsection Drawing to file
+ at nav{}
+
+Another way of using MathGL library is the direct writing of the picture to the file. It is most usable for plot creation during long calculation or for using of small programs (like Matlab or Scilab scripts) for visualizing repetitive sets of data. But the speed of drawing is much higher in comparison with a script language.
+
+The following code produces a bitmap PNG picture:
+ at verbatim
+#include <mgl2/mgl.h>
+int main(int ,char **)
+{
+  mglGraph gr;
+  gr.Alpha(true);   gr.Light(true);
+  sample(&gr);              // The same drawing function.
+  gr.WritePNG("test.png");  // Don't forget to save the result!
+  return 0;
+}
+ at end verbatim
+ For compilation, you need only libmgl library not the one with widgets
+ at verbatim
+gcc test.cpp -lmgl
+ at end verbatim
+This can be important if you create a console program in computer/cluster where X-server (and widgets) is inaccessible.
+
+The only difference from the previous variant (using windows) is manual switching on the transparency  @code{Alpha} and lightning @code{Light}, if you need it. The usage of frames (see @ref{Animation}) is not advisable since the whole image is prepared each time. If function @code{sample} contains frames then only last one will be saved to the file. In principle, one does not need to separate drawing functions in case of direct file writing in consequence of the single calling of this fu [...]
+
+The code for export into other formats (for example, into vector EPS file) looks the same:
+ at verbatim
+#include <mgl2/mgl.h>
+int main(int ,char **)
+{
+  mglGraph gr;
+  gr.Light(true);
+  sample(&gr);              // The same drawing function.
+  gr.WriteEPS("test.eps");  // Don't forget to save the result!
+  return 0;
+}
+ at end verbatim
+The difference from the previous one is using other function @code{WriteEPS()} for EPS format instead of function @code{WritePNG()}. Also, there is no switching on of the plot transparency @code{Alpha} since EPS format does not support it.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Animation, Drawing in memory, Drawing to file, Basic usage
+ at subsection Animation
+ at nav{}
+
+Widget classes (@code{mglWindow}, @code{mglGLUT}) support a delayed drawing, when all plotting functions are called once at the beginning of writing to memory lists. Further program displays the saved lists faster. Resulting redrawing will be faster but it requires sufficient memory. Several lists (frames) can be displayed one after another (by pressing @samp{,}, @samp{.}) or run as cinema. To switch these feature on one needs to modify function @code{sample}:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->NewFrame();             // the first frame
+  gr->Rotate(60,40);
+  gr->Box();
+  gr->EndFrame();             // end of the first frame
+  gr->NewFrame();             // the second frame
+  gr->Box();
+  gr->Axis("xy");
+  gr->EndFrame();             // end of the second frame
+  return gr->GetNumFrame();   // returns the frame number
+}
+ at end verbatim
+First, the function creates a frame by calling @code{NewFrame()} for rotated axes and draws the bounding box.  The function @code{EndFrame()} @strong{must be} called after the frame drawing! The second frame contains the bounding box and axes @code{Axis("xy")} in the initial (unrotated) coordinates. Function @code{sample} returns the number of created frames @code{GetNumFrame()}.
+
+Note, that animation can be also done as visualization of running calculations (see @ref{Draw and calculate}).
+
+Pictures with @strong{animation can be saved in file(s)} as well. You can: export in animated GIF, or save each frame in separate file (usually JPEG) and convert these files into the movie (for example, by help of ImageMagic). Let me show both methods.
+
+ at anchor{GIF}
+The simplest methods is making animated GIF. There are 3 steps: (1) open GIF file by @code{StartGIF()} function; (2) create the frames by calling @code{NewFrame()} before and @code{EndFrame()} after plotting; (3) close GIF by @code{CloseGIF()} function. So the simplest code for ``running'' sinusoid will look like this:
+ at verbatim
+#include <mgl2/mgl.h>
+int main(int ,char **)
+{
+  mglGraph gr;
+  mglData dat(100);
+  char str[32];
+  gr.StartGIF("sample.gif");
+  for(int i=0;i<40;i++)
+  {
+    gr.NewFrame();     // start frame
+    gr.Box();          // some plotting
+    for(int j=0;j<dat.nx;j++)
+      dat.a[j]=sin(M_PI*j/dat.nx+M_PI*0.05*i);
+    gr.Plot(dat,"b");
+    gr.EndFrame();     // end frame
+  }
+  gr.CloseGIF();
+  return 0;
+}
+ at end verbatim
+
+ at anchor{MPEG}
+The second way is saving each frame in separate file (usually JPEG) and later make the movie from them. MathGL have special function for saving frames -- it is @code{WriteFrame()}. This function save each frame with automatic name @samp{frame0001.jpg, frame0002.jpg} and so on. Here prefix @samp{frame} is defined by @var{PlotId} variable of @code{mglGraph} class. So the similar code will look like this:
+ at verbatim
+#include <mgl2/mgl.h>
+int main(int ,char **)
+{
+  mglGraph gr;
+  mglData dat(100);
+  char str[32];
+  for(int i=0;i<40;i++)
+  {
+    gr.NewFrame();     // start frame
+    gr.Box();          // some plotting
+    for(int j=0;j<dat.nx;j++)
+      dat.a[j]=sin(M_PI*j/dat.nx+M_PI*0.05*i);
+    gr.Plot(dat,"b");
+    gr.EndFrame();     // end frame
+    gr.WriteFrame();   // save frame
+  }
+  return 0;
+}
+ at end verbatim
+
+Created files can be converted to movie by help of a lot of programs. For example, you can use ImageMagic (command @samp{convert frame*.jpg movie.mpg}), MPEG library, GIMP and so on.
+
+Finally, you can use @code{mglconv} tool for doing the same with MGL scripts (@pxref{Utilities}).
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Drawing in memory, Draw and calculate, Animation, Basic usage
+ at subsection Drawing in memory
+ at nav{}
+
+The last way of MathGL using is the drawing in memory. Class @code{mglGraph} allows one  to create a bitmap picture in memory. Further this picture can be displayed in window by some window libraries (like wxWidgets, FLTK, Windows GDI and so on). For example, the code for drawing in wxWidget library looks like:
+ at verbatim
+void MyForm::OnPaint(wxPaintEvent& event)
+{
+  int w,h,x,y;
+  GetClientSize(&w,&h);   // size of the picture
+  mglGraph gr(w,h);
+
+  gr.Alpha(true);         // draws something using MathGL
+  gr.Light(true);
+  sample(&gr,NULL);
+
+  wxImage img(w,h,gr.GetRGB(),true);
+  ToolBar->GetSize(&x,&y);    // gets a height of the toolbar if any
+  wxPaintDC dc(this);         // and draws it
+  dc.DrawBitmap(wxBitmap(img),0,y);
+}
+ at end verbatim
+The drawing in other libraries is most the same.
+
+For example, FLTK code will look like
+ at verbatim
+void Fl_MyWidget::draw()
+{
+  mglGraph gr(w(),h());
+  gr.Alpha(true);         // draws something using MathGL
+  gr.Light(true);
+  sample(&gr,NULL);
+  fl_draw_image(gr.GetRGB(), x(), y(), gr.GetWidth(), gr.GetHeight(), 3);
+}
+ at end verbatim
+Qt code will look like
+ at verbatim
+void MyWidget::paintEvent(QPaintEvent *)
+{
+  mglGraph gr(w(),h());
+
+  gr.Alpha(true);         // draws something using MathGL
+  gr.Light(true);         gr.Light(0,mglPoint(1,0,-1));
+  sample(&gr,NULL);
+
+  // Qt don't support RGB format as is. So, let convert it to BGRN.
+  long w=gr.GetWidth(), h=gr.GetHeight();
+  unsigned char *buf = new uchar[4*w*h];
+  gr.GetBGRN(buf, 4*w*h)
+  QPixmap pic = QPixmap::fromImage(QImage(*buf, w, h, QImage::Format_RGB32));
+
+  QPainter paint;
+  paint.begin(this);  paint.drawPixmap(0,0,pic);  paint.end();
+  delete []buf;
+}
+ at end verbatim
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Draw and calculate, Using QMathGL, Drawing in memory, Basic usage
+ at subsection Draw and calculate
+ at nav{}
+
+MathGL can be used to draw plots in parallel with some external calculations. The simplest way for this is the usage of @ref{mglDraw class}. At this you should enable pthread for widgets by setting @code{enable-pthr-widget=ON} at configure stage (it is set by default).
+First, you need to inherit you class from @code{mglDraw} class, define virtual members @code{Draw()} and @code{Calc()} which will draw the plot and proceed calculations. You may want to add the pointer @code{mglWnd *wnd;} to window with plot for interacting with them. Finally, you may add any other data or member functions. The sample class is shown below
+ at verbatim
+class myDraw : public mglDraw
+{
+	mglPoint pnt;	// some variable for changeable data
+	long i;			// another variable to be shown
+	mglWnd *wnd;	// external window for plotting
+public:
+	myDraw(mglWnd *w=0) : mglDraw()	{	wnd=w;	}
+	void SetWnd(mglWnd *w)	{	wnd=w;	}
+	int Draw(mglGraph *gr)
+	{
+		gr->Line(mglPoint(),pnt,"Ar2");
+		char str[16];	snprintf(str,15,"i=%ld",i);
+		gr->Puts(mglPoint(),str);
+		return 0;
+	}
+	void Calc()
+	{
+		for(i=0;;i++)	// do calculation
+		{
+			long_calculations();// which can be very long
+			Check();	// check if need pause
+			pnt.Set(2*mgl_rnd()-1,2*mgl_rnd()-1);
+			if(wnd)	wnd->Update();
+		}
+	}
+} dr;
+ at end verbatim
+There is only one issue here. Sometimes you may want to pause calculations to view result carefully, or save state, or change something. So, you need to provide a mechanism for pausing. Class @code{mglDraw} provide function @code{Check();} which check if toolbutton with pause is pressed and wait until it will be released. This function should be called in a "safety" places, where you can pause the calculation (for example, at the end of time step). Also you may add call @code{exit(0);} a [...]
+Finally, you need to create a window itself and run calculations.
+ at verbatim
+int main(int argc,char **argv)
+{
+	mglFLTK gr(&dr,"Multi-threading test");	// create window
+	dr.SetWnd(&gr);	// pass window pointer to yours class
+	dr.Run();	// run calculations
+	gr.Run();	// run event loop for window
+	return 0;
+}
+ at end verbatim
+
+Note, that you can reach the similar functionality without using @code{mglDraw} class (i.e. even for pure C code).
+ at verbatim
+mglFLTK *gr=NULL;	// pointer to window
+void *calc(void *)	// function with calculations
+{
+	mglPoint pnt;	// some data for plot
+	for(long i=0;;i++)		// do calculation
+	{
+		long_calculations();	// which can be very long
+		pnt.Set(2*mgl_rnd()-1,2*mgl_rnd()-1);
+		if(gr)
+		{
+			gr->Clf();			// make new drawing
+			// draw something
+			gr->Line(mglPoint(),pnt,"Ar2");
+			char str[16];	snprintf(str,15,"i=%ld",i);
+			gr->Puts(mglPoint(),str);
+			// don't forgot to update window
+			gr->Update();
+		}
+	}
+}
+int main(int argc,char **argv)
+{
+	static pthread_t thr;
+	pthread_create(&thr,0,calc,0);	// create separate thread for calculations
+	pthread_detach(thr);			// and detach it
+	gr = new mglFLTK;	// now create window
+	gr->Run();			// and run event loop
+	return 0;
+}
+ at end verbatim
+This sample is exactly the same as one with @code{mglDraw} class, but it don't have functionality for pausing calculations. If you need it then you have to create global mutex (like @code{pthread_mutex_t *mutex = pthread_mutex_init(&mutex,NULL);}), set it to window (like @code{gr->SetMutex(mutex);}) and periodically check it at calculations (like @code{pthread_mutex_lock(&mutex); pthread_mutex_unlock(&mutex);}).
+
+Finally, you can put the event-handling loop in separate instead of yours code by using @code{RunThr()} function instead of @code{Run()} one. Unfortunately, such method work well only for FLTK windows and only if pthread support was enabled. Such limitation come from the Qt requirement to be run in the primary thread only. The sample code will be:
+ at verbatim
+int main(int argc,char **argv)
+{
+	mglFLTK gr("test");
+	gr.RunThr();	// <-- need MathGL version which use pthread for widgets
+	mglPoint pnt;	// some data
+	for(int i=0;i<10;i++)	// do calculation
+	{
+		long_calculations();// which can be very long
+		pnt.Set(2*mgl_rnd()-1,2*mgl_rnd()-1);
+		gr.Clf();			// make new drawing
+		gr.Line(mglPoint(),pnt,"Ar2");
+		char str[10] = "i=0";	str[3] = '0'+i;
+		gr->Puts(mglPoint(),str);
+		gr.Update();		// update window
+	}
+	return 0;	// finish calculations and close the window
+}
+ at end verbatim
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Using QMathGL, MathGL and PyQt, Draw and calculate, Basic usage
+ at subsection Using QMathGL
+ at nav{}
+
+MathGL have several interface widgets for different widget libraries. There are QMathGL for Qt, Fl_MathGL for FLTK. These classes provide control which display MathGL graphics. Unfortunately there is no uniform interface for widget classes because all libraries have slightly different set of functions, features and so on. However the usage of MathGL widgets is rather simple. Let me show it on the example of QMathGL.
+
+First of all you have to define the drawing function or inherit a class from @code{mglDraw} class. After it just create a window and setup QMathGL instance as any other Qt widget:
+ at verbatim
+#include <QApplication>
+#include <QMainWindow>
+#include <QScrollArea>
+#include <mgl2/qmathgl.h>
+int main(int argc,char **argv)
+{
+  QApplication a(argc,argv);
+  QMainWindow *Wnd = new QMainWindow;
+  Wnd->resize(810,610);  // for fill up the QMGL, menu and toolbars
+  Wnd->setWindowTitle("QMathGL sample");
+  // here I allow to scroll QMathGL -- the case
+  // then user want to prepare huge picture
+  QScrollArea *scroll = new QScrollArea(Wnd);
+
+  // Create and setup QMathGL
+  QMathGL *QMGL = new QMathGL(Wnd);
+//QMGL->setPopup(popup); // if you want to setup popup menu for QMGL
+  QMGL->setDraw(sample);
+  // or use QMGL->setDraw(foo); for instance of class Foo:public mglDraw
+  QMGL->update();
+
+  // continue other setup (menu, toolbar and so on)
+  scroll->setWidget(QMGL);
+  Wnd->setCentralWidget(scroll);
+  Wnd->show();
+  return a.exec();
+}
+ at end verbatim
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node MathGL and PyQt, MathGL and MPI, Using QMathGL, Basic usage
+ at subsection MathGL and PyQt
+ at nav{}
+
+Generally SWIG based classes (including the Python one) are the same as C++ classes. However, there are few tips for using MathGL with PyQt. Below I place a very simple python code which demonstrate how MathGL can be used with PyQt. This code is mostly written by Prof. Dr. Heino Falcke. You can just copy it to a file @code{mgl-pyqt-test.py} and execute it from python shell by command @code{execfile("mgl-pyqt-test.py")}
+
+ at verbatim
+from PyQt4 import QtGui,QtCore
+from mathgl import *
+import sys
+app = QtGui.QApplication(sys.argv)
+qpointf=QtCore.QPointF()
+
+class hfQtPlot(QtGui.QWidget):
+    def __init__(self, parent=None):
+        QtGui.QWidget.__init__(self, parent)
+        self.img=(QtGui.QImage())
+    def setgraph(self,gr):
+        self.buffer='\t'
+        self.buffer=self.buffer.expandtabs(4*gr.GetWidth()*gr.GetHeight())
+        gr.GetBGRN(self.buffer,len(self.buffer))
+        self.img=QtGui.QImage(self.buffer, gr.GetWidth(),gr.GetHeight(),QtGui.QImage.Format_ARGB32)
+        self.update()
+    def paintEvent(self, event):
+        paint = QtGui.QPainter()
+        paint.begin(self)
+        paint.drawImage(qpointf,self.img)
+        paint.end()
+
+BackgroundColor=[1.0,1.0,1.0]
+size=100
+gr=mglGraph()
+y=mglData(size)
+#y.Modify("((0.7*cos(2*pi*(x+.2)*500)+0.3)*(rnd*0.5+0.5)+362.135+10000.)")
+y.Modify("(cos(2*pi*x*10)+1.1)*1000.*rnd-501")
+x=mglData(size)
+x.Modify("x^2");
+
+def plotpanel(gr,x,y,n):
+    gr.SubPlot(2,2,n)
+    gr.SetXRange(x)
+    gr.SetYRange(y)
+    gr.AdjustTicks()
+    gr.Axis()
+    gr.Box()
+    gr.Label("x","x-Axis",1)
+    gr.Label("y","y-Axis",1)
+    gr.ClearLegend()
+    gr.AddLegend("Legend: "+str(n),"k")
+    gr.Legend()
+    gr.Plot(x,y)
+
+
+gr.Clf(BackgroundColor[0],BackgroundColor[1],BackgroundColor[2])
+gr.SetPlotFactor(1.5)
+plotpanel(gr,x,y,0)
+y.Modify("(cos(2*pi*x*10)+1.1)*1000.*rnd-501")
+plotpanel(gr,x,y,1)
+y.Modify("(cos(2*pi*x*10)+1.1)*1000.*rnd-501")
+plotpanel(gr,x,y,2)
+y.Modify("(cos(2*pi*x*10)+1.1)*1000.*rnd-501")
+plotpanel(gr,x,y,3)
+
+gr.WritePNG("test.png","Test Plot")
+
+qw = hfQtPlot()
+qw.show()
+qw.setgraph(gr)
+qw.raise_()
+ at end verbatim
+
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node MathGL and MPI, , MathGL and PyQt, Basic usage
+ at subsection MathGL and MPI
+ at nav{}
+
+For using MathGL in MPI program you just need to: (1) plot its own part of data for each running node; (2) collect resulting graphical information in a single program (for example, at node with rank=0); (3) save it. The sample code below demonstrate this for very simple sample of surface drawing.
+
+First you need to initialize MPI
+ at verbatim
+#include <stdio.h>
+#include <mgl2/mpi.h>
+#include <mpi.h>
+
+int main(int argc, char *argv[])
+{
+  // initialize MPI
+  int rank=0, numproc=1;
+  MPI_Init(&argc, &argv);
+  MPI_Comm_size(MPI_COMM_WORLD,&numproc);
+  MPI_Comm_rank(MPI_COMM_WORLD,&rank);
+  if(rank==0) printf("Use %d processes.\n", numproc);
+ at end verbatim
+
+Next step is data creation. For simplicity, I create data arrays with the same sizes for all nodes. At this, you have to create @code{mglGraph} object too.
+
+ at verbatim
+  // initialize data similarly for all nodes
+  mglData a(128,256);
+  mglGraphMPI gr;
+ at end verbatim
+
+Now, data should be filled by numbers. In real case, it should be some kind of calculations. But I just fill it by formula.
+
+ at verbatim
+  // do the same plot for its own range
+  char buf[64];
+  sprintf(buf,"xrange %g %g",2.*rank/numproc-1,2.*(rank+1)/numproc-1);
+  gr.Fill(a,"sin(2*pi*x)",buf);
+ at end verbatim
+
+It is time to plot the data. Don't forget to set proper axis range(s) by using parametric form or by using options (as in the sample).
+
+ at verbatim
+  // plot data in each node
+  gr.Clf();   // clear image before making the image
+  gr.Rotate(40,60);
+  gr.Surf(a,"",buf);
+ at end verbatim
+
+Finally, let send graphical information to node with rank=0.
+
+ at verbatim
+  // collect information
+  if(rank!=0) gr.MPI_Send(0);
+  else for(int i=1;i<numproc;i++)  gr.MPI_Recv(i);
+ at end verbatim
+
+Now, node with rank=0 have whole image. It is time to save the image to a file. Also, you can add a kind of annotations here -- I draw axis and bounding box in the sample.
+
+ at verbatim
+  if(rank==0)
+  {
+    gr.Box();   gr.Axis();   // some post processing
+    gr.WritePNG("test.png"); // save result
+  }
+ at end verbatim
+
+In my case the program is done, and I finalize MPI. In real program, you can repeat the loop of data calculation and data plotting as many times as you need.
+
+ at verbatim
+  MPI_Finalize();
+  return 0;
+}
+ at end verbatim
+
+You can type @samp{mpic++ test.cpp -lmgl-mpi -lmgl && mpirun -np 8 ./a.out} for compilation and running the sample program on 8 nodes. Note, that you have to set enable-mpi=ON at MathGL configure to use this feature.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Advanced usage, Data handling, Basic usage, Examples
+ at section Advanced usage
+ at nav{}
+
+Now I show several non-obvious features of MathGL: several subplots in a single picture, curvilinear coordinates, text printing and so on. Generally you may miss this section at first reading.
+
+ at menu
+* Subplots::
+* Axis and ticks::
+* Curvilinear coordinates::
+* Colorbars::
+* Bounding box::
+* Ternary axis::
+* Text features::
+* Legend sample::
+* Cutting sample::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Subplots, Axis and ticks, , Advanced usage
+ at subsection Subplots
+ at nav{}
+
+Let me demonstrate possibilities of plot positioning and rotation. MathGL has a set of functions: @ref{subplot}, @ref{inplot}, @ref{title}, @ref{aspect} and @ref{rotate} and so on (see @ref{Subplots and rotation}). The order of their calling is strictly determined. First, one changes the position of plot in image area (functions @ref{subplot}, @ref{inplot} and @ref{multiplot}). Secondly, you can add the title of plot by @ref{title} function. After that one may rotate the plot (function @ [...]
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(2,2,0); gr->Box();
+  gr->Puts(mglPoint(-1,1.1),"Just box",":L");
+  gr->InPlot(0.2,0.5,0.7,1,false);  gr->Box();
+  gr->Puts(mglPoint(0,1.2),"InPlot example");
+  gr->SubPlot(2,2,1); gr->Title("Rotate only");
+  gr->Rotate(50,60);  gr->Box();
+  gr->SubPlot(2,2,2); gr->Title("Rotate and Aspect");
+  gr->Rotate(50,60);  gr->Aspect(1,1,2);  gr->Box();
+  gr->SubPlot(2,2,3); gr->Title("Shear");
+  gr->Box("c"); gr->Shear(0.2,0.1); gr->Box();
+  return 0;
+}
+ at end verbatim
+Here I used function @code{Puts} for printing the text in arbitrary position of picture (see @ref{Text printing}). Text coordinates and size are connected with axes. However, text coordinates may be everywhere, including the outside the bounding box. I'll show its features later in @ref{Text features}.
+
+ at pfig{aspect, Example of several subplots on the single picture.}
+
+More complicated sample show how to use most of positioning functions:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(3,2,0); gr->Title("StickPlot");
+  gr->StickPlot(3, 0, 20, 30);  gr->Box("r"); gr->Puts(mglPoint(0),"0","r");
+  gr->StickPlot(3, 1, 20, 30);  gr->Box("g"); gr->Puts(mglPoint(0),"1","g");
+  gr->StickPlot(3, 2, 20, 30);  gr->Box("b"); gr->Puts(mglPoint(0),"2","b");
+  gr->SubPlot(3,2,3,"");  gr->Title("ColumnPlot");
+  gr->ColumnPlot(3, 0); gr->Box("r"); gr->Puts(mglPoint(0),"0","r");
+  gr->ColumnPlot(3, 1); gr->Box("g"); gr->Puts(mglPoint(0),"1","g");
+  gr->ColumnPlot(3, 2); gr->Box("b"); gr->Puts(mglPoint(0),"2","b");
+  gr->SubPlot(3,2,4,"");  gr->Title("GridPlot");
+  gr->GridPlot(2, 2, 0);  gr->Box("r"); gr->Puts(mglPoint(0),"0","r");
+  gr->GridPlot(2, 2, 1);  gr->Box("g"); gr->Puts(mglPoint(0),"1","g");
+  gr->GridPlot(2, 2, 2);  gr->Box("b"); gr->Puts(mglPoint(0),"2","b");
+  gr->GridPlot(2, 2, 3);  gr->Box("m"); gr->Puts(mglPoint(0),"3","m");
+  gr->SubPlot(3,2,5,"");  gr->Title("InPlot");  gr->Box();
+  gr->InPlot(0.4, 1, 0.6, 1, true); gr->Box("r");
+  gr->MultiPlot(3,2,1, 2, 1,"");  gr->Title("MultiPlot and ShearPlot"); gr->Box();
+  gr->ShearPlot(3, 0, 0.2, 0.1);  gr->Box("r"); gr->Puts(mglPoint(0),"0","r");
+  gr->ShearPlot(3, 1, 0.2, 0.1);  gr->Box("g"); gr->Puts(mglPoint(0),"1","g");
+  gr->ShearPlot(3, 2, 0.2, 0.1);  gr->Box("b"); gr->Puts(mglPoint(0),"2","b");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{inplot, Example for most of positioning functions.}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Axis and ticks, Curvilinear coordinates, Subplots, Advanced usage
+ at subsection Axis and ticks
+ at nav{}
+
+MathGL library can draw not only the bounding box but also the axes, grids, labels and so on. The ranges of axes and their origin (the point of intersection) are determined by functions @code{SetRange()}, @code{SetRanges()}, @code{SetOrigin()} (see @ref{Ranges (bounding box)}). Ticks on axis are specified by function @code{SetTicks}, @code{SetTicksVal}, @code{SetTicksTime} (see @ref{Ticks}). But usually
+
+Function @ref{axis} draws axes. Its textual string shows in which directions the axis or axes will be drawn (by default @code{"xyz"}, function draws axes in all directions). Function @ref{grid} draws grid perpendicularly to specified directions. Example of axes and grid drawing is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(2,2,0); gr->Title("Axis origin, Grid"); gr->SetOrigin(0,0);
+  gr->Axis(); gr->Grid(); gr->FPlot("x^3");
+
+  gr->SubPlot(2,2,1); gr->Title("2 axis");
+  gr->SetRanges(-1,1,-1,1); gr->SetOrigin(-1,-1,-1);  // first axis
+  gr->Axis(); gr->Label('y',"axis 1",0);  gr->FPlot("sin(pi*x)");
+  gr->SetRanges(0,1,0,1);   gr->SetOrigin(1,1,1);   // second axis
+  gr->Axis(); gr->Label('y',"axis 2",0);  gr->FPlot("cos(pi*x)");
+
+  gr->SubPlot(2,2,3); gr->Title("More axis");
+  gr->SetOrigin(NAN,NAN); gr->SetRange('x',-1,1);
+  gr->Axis(); gr->Label('x',"x",0); gr->Label('y',"y_1",0);
+  gr->FPlot("x^2","k");
+  gr->SetRanges(-1,1,-1,1); gr->SetOrigin(-1.3,-1); // second axis
+  gr->Axis("y","r");  gr->Label('y',"#r{y_2}",0.2);
+  gr->FPlot("x^3","r");
+
+  gr->SubPlot(2,2,2); gr->Title("4 segments, inverted axis");
+  gr->SetOrigin(0,0);
+  gr->InPlot(0.5,1,0.5,1);  gr->SetRanges(0,10,0,2);  gr->Axis();
+  gr->FPlot("sqrt(x/2)");   gr->Label('x',"W",1); gr->Label('y',"U",1);
+  gr->InPlot(0,0.5,0.5,1);  gr->SetRanges(1,0,0,2); gr->Axis("x");
+  gr->FPlot("sqrt(x)+x^3"); gr->Label('x',"\\tau",-1);
+  gr->InPlot(0.5,1,0,0.5);  gr->SetRanges(0,10,4,0);  gr->Axis("y");
+  gr->FPlot("x/4"); gr->Label('y',"L",-1);
+  gr->InPlot(0,0.5,0,0.5);  gr->SetRanges(1,0,4,0); gr->FPlot("4*x^2");
+  return 0;
+}
+ at end verbatim
+
+Note, that MathGL can draw not only single axis (which is default). But also several axis on the plot (see right plots). The idea is that the change of settings does not influence on the already drawn graphics. So, for 2-axes I setup the first axis and draw everything concerning it. Then I setup the second axis and draw things for the second axis. Generally, the similar idea allows one to draw rather complicated plot of 4 axis with different ranges (see bottom left plot).
+
+At this inverted axis can be created by 2 methods. First one is used in this sample -- just specify minimal axis value to be large than maximal one. This method work well for 2D axis, but can wrongly place labels in 3D case. Second method is more general and work in 3D case too -- just use @ref{aspect} function with negative arguments. For example, following code will produce exactly the same result for 2D case, but 2nd variant will look better in 3D.
+ at verbatim
+// variant 1
+gr->SetRanges(0,10,4,0);  gr->Axis();
+
+// variant 2
+gr->SetRanges(0,10,0,4);  gr->Aspect(1,-1);   gr->Axis();
+ at end verbatim
+
+ at pfig{axis, Example of axis.}
+
+Another MathGL feature is fine ticks tunning. By default (if it is not changed by @code{SetTicks} function), MathGL try to adjust ticks positioning, so that they looks most human readable. At this, MathGL try to extract common factor for too large or too small axis ranges, as well as for too narrow ranges. Last one is non-common notation and can be disabled by @code{SetTuneTicks} function.
+
+Also, one can specify its own ticks with arbitrary labels by help of @code{SetTicksVal} function. Or one can set ticks in time format. In last case MathGL will try to select optimal format for labels with automatic switching between years, months/days, hours/minutes/seconds or microseconds. However, you can specify its own time representation using formats described in @url{http://www.manpagez.com/man/3/strftime/}. Most common variants are @samp{%X} for national representation of time, @ [...]
+
+The sample code, demonstrated ticks feature is
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(3,2,0); gr->Title("Usual axis");  gr->Axis();
+  gr->SubPlot(3,2,1); gr->Title("Too big/small range");
+  gr->SetRanges(-1000,1000,0,0.001);  gr->Axis();
+  gr->SubPlot(3,2,3); gr->Title("Too narrow range");
+  gr->SetRanges(100,100.1,10,10.01);  gr->Axis();
+  gr->SubPlot(3,2,4); gr->Title("Disable ticks tuning");
+  gr->SetTuneTicks(0);  gr->Axis();
+
+  gr->SubPlot(3,2,2); gr->Title("Manual ticks");  gr->SetRanges(-M_PI,M_PI, 0, 2);
+  mreal val[]={-M_PI, -M_PI/2, 0, 0.886, M_PI/2, M_PI};
+  gr->SetTicksVal('x', mglData(6,val), "-\\pi\n-\\pi/2\n0\nx^*\n\\pi/2\n\\pi");
+  gr->Axis(); gr->Grid(); gr->FPlot("2*cos(x^2)^2", "r2");
+
+  gr->SubPlot(3,2,5); gr->Title("Time ticks");  gr->SetRange('x',0,3e5);
+  gr->SetTicksTime('x',0);  gr->Axis();
+  return 0;
+}
+ at end verbatim
+
+ at pfig{ticks, Features of axis ticks.}
+
+The last sample I want to show in this subsection is Log-axis. From MathGL's point of view, the log-axis is particular case of general curvilinear coordinates. So, we need first define new coordinates (see also @ref{Curvilinear coordinates}) by help of @code{SetFunc} or @code{SetCoor} functions. At this one should wary about proper axis range. So the code looks as following:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(2,2,0,"<_");  gr->Title("Semi-log axis");
+  gr->SetRanges(0.01,100,-1,1); gr->SetFunc("lg(x)","");
+  gr->Axis(); gr->Grid("xy","g"); gr->FPlot("sin(1/x)");
+  gr->Label('x',"x",0); gr->Label('y', "y = sin 1/x",0);
+
+  gr->SubPlot(2,2,1,"<_");  gr->Title("Log-log axis");
+  gr->SetRanges(0.01,100,0.1,100);  gr->SetFunc("lg(x)","lg(y)");
+  gr->Axis(); gr->Grid("!","h=");   gr->Grid();
+  gr->FPlot("sqrt(1+x^2)"); gr->Label('x',"x",0);
+  gr->Label('y', "y = \\sqrt{1+x^2}",0);
+
+  gr->SubPlot(2,2,2,"<_");  gr->Title("Minus-log axis");
+  gr->SetRanges(-100,-0.01,-100,-0.1);  gr->SetFunc("-lg(-x)","-lg(-y)");
+  gr->Axis(); gr->FPlot("-sqrt(1+x^2)");
+  gr->Label('x',"x",0); gr->Label('y', "y = -\\sqrt{1+x^2}",0);
+
+  gr->SubPlot(2,2,3,"<_");  gr->Title("Log-ticks");
+  gr->SetRanges(0.1,100,0,100); gr->SetFunc("sqrt(x)","");
+  gr->Axis(); gr->FPlot("x");
+  gr->Label('x',"x",1); gr->Label('y', "y = x",0);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{loglog, Features of axis ticks.}
+
+You can see that MathGL automatically switch to log-ticks as we define log-axis formula (in difference from v.1.*). Moreover, it switch to log-ticks for any formula if axis range will be large enough (see right bottom plot). Another interesting feature is that you not necessary define usual log-axis (i.e. when coordinates are positive), but you can define ``minus-log'' axis when coordinate is negative (see left bottom plot).
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Curvilinear coordinates, Colorbars, Axis and ticks, Advanced usage
+ at subsection Curvilinear coordinates
+ at nav{}
+
+As I noted in previous subsection, MathGL support curvilinear coordinates. In difference from other plotting programs and libraries, MathGL uses textual formulas for connection of the old (data) and new (output) coordinates. This allows one to plot in arbitrary coordinates. The following code plots the line @var{y}=0, @var{z}=0 in Cartesian, polar, parabolic and spiral coordinates:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SetOrigin(-1,1,-1);
+
+  gr->SubPlot(2,2,0); gr->Title("Cartesian"); gr->Rotate(50,60);
+  gr->FPlot("2*t-1","0.5","0","r2");
+  gr->Axis(); gr->Grid();
+
+  gr->SetFunc("y*sin(pi*x)","y*cos(pi*x)",0);
+  gr->SubPlot(2,2,1); gr->Title("Cylindrical"); gr->Rotate(50,60);
+  gr->FPlot("2*t-1","0.5","0","r2");
+  gr->Axis(); gr->Grid();
+
+  gr->SetFunc("2*y*x","y*y - x*x",0);
+  gr->SubPlot(2,2,2); gr->Title("Parabolic"); gr->Rotate(50,60);
+  gr->FPlot("2*t-1","0.5","0","r2");
+  gr->Axis(); gr->Grid();
+
+  gr->SetFunc("y*sin(pi*x)","y*cos(pi*x)","x+z");
+  gr->SubPlot(2,2,3); gr->Title("Spiral");  gr->Rotate(50,60);
+  gr->FPlot("2*t-1","0.5","0","r2");
+  gr->Axis(); gr->Grid();
+  gr->SetFunc(0,0,0); // set to default Cartesian
+  return 0;
+}
+ at end verbatim
+
+ at pfig{curvcoor, Example of curvilinear coordinates}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Colorbars, Bounding box, Curvilinear coordinates, Advanced usage
+ at subsection Colorbars
+ at nav{}
+
+MathGL handle @ref{colorbar} as special kind of axis. So, most of functions for axis and ticks setup will work for colorbar too. Colorbars can be in log-scale, and generally as arbitrary function scale; common factor of colorbar labels can be separated; and so on.
+
+But of course, there are differences -- colorbars usually located out of bounding box. At this, colorbars can be at subplot boundaries (by default), or at bounding box (if symbol @samp{I} is specified). Colorbars can handle sharp colors. And they can be located at arbitrary position too. The sample code, which demonstrate colorbar features is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(2,2,0); gr->Title("Colorbar out of box"); gr->Box();
+  gr->Colorbar("<");  gr->Colorbar(">");
+  gr->Colorbar("_");  gr->Colorbar("^");
+
+  gr->SubPlot(2,2,1); gr->Title("Colorbar near box");   gr->Box();
+  gr->Colorbar("<I"); gr->Colorbar(">I");
+  gr->Colorbar("_I"); gr->Colorbar("^I");
+
+  gr->SubPlot(2,2,2); gr->Title("manual colors");
+  mglData a,v;  mgls_prepare2d(&a,0,&v);
+  gr->Box();  gr->ContD(v,a);
+  gr->Colorbar(v,"<");  gr->Colorbar(v,">");
+  gr->Colorbar(v,"_");  gr->Colorbar(v,"^");
+
+  gr->SubPlot(2,2,3);   gr->Title(" ");
+  gr->Puts(mglPoint(-0.5,1.55),"Color positions",":C",-2);
+  gr->Colorbar("bwr>",0.25,0);  gr->Puts(mglPoint(-0.9,1.2),"Default");
+  gr->Colorbar("b{w,0.3}r>",0.5,0); gr->Puts(mglPoint(-0.1,1.2),"Manual");
+
+  gr->Puts(mglPoint(1,1.55),"log-scale",":C",-2);
+  gr->SetRange('c',0.01,1e3);
+  gr->Colorbar(">",0.75,0);  gr->Puts(mglPoint(0.65,1.2),"Normal scale");
+  gr->SetFunc("","","","lg(c)");
+  gr->Colorbar(">");    gr->Puts(mglPoint(1.35,1.2),"Log scale");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{colorbar, Example of colorbars}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Bounding box, Ternary axis, Colorbars, Advanced usage
+ at subsection Bounding box
+ at nav{}
+
+Box around the plot is rather useful thing because it allows one to: see the plot boundaries, and better estimate points position since box contain another set of ticks. MathGL provide special function for drawing such box -- @ref{box} function. By default, it draw black or white box with ticks (color depend on transparency type, see @ref{Types of transparency}). However, you can change the color of box, or add drawing of rectangles at rear faces of box. Also you can disable ticks drawin [...]
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(2,2,0); gr->Title("Box (default)"); gr->Rotate(50,60);
+  gr->Box();
+  gr->SubPlot(2,2,1); gr->Title("colored");   gr->Rotate(50,60);
+  gr->Box("r");
+  gr->SubPlot(2,2,2); gr->Title("with faces");  gr->Rotate(50,60);
+  gr->Box("@");
+  gr->SubPlot(2,2,3); gr->Title("both");  gr->Rotate(50,60);
+  gr->Box("@cm");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{box, Example of Box()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Ternary axis, Text features, Bounding box, Advanced usage
+ at subsection Ternary axis
+ at nav{}
+
+There are another unusual axis types which are supported by MathGL. These are ternary and quaternary axis. Ternary axis is special axis of 3 coordinates @var{a}, @var{b}, @var{c} which satisfy relation @var{a}+ at var{b}+ at var{c}=1. Correspondingly, quaternary axis is special axis of 4 coordinates @var{a}, @var{b}, @var{c}, @var{d} which satisfy relation @var{a}+ at var{b}+ at var{c}+ at var{d}=1.
+
+Generally speaking, only 2 of coordinates (3 for quaternary) are independent. So, MathGL just introduce some special transformation formulas which treat @var{a} as @samp{x}, @var{b} as @samp{y} (and @var{c} as @samp{z} for quaternary). As result, all plotting functions (curves, surfaces, contours and so on) work as usual, but in new axis. You should use @ref{ternary} function for switching to ternary/quaternary coordinates. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SetRanges(0,1,0,1,0,1);
+  mglData x(50),y(50),z(50),rx(10),ry(10), a(20,30);
+  a.Modify("30*x*y*(1-x-y)^2*(x+y<1)");
+  x.Modify("0.25*(1+cos(2*pi*x))");
+  y.Modify("0.25*(1+sin(2*pi*x))");
+  rx.Modify("rnd"); ry.Modify("(1-v)*rnd",rx);
+  z.Modify("x");
+
+  gr->SubPlot(2,2,0); gr->Title("Ordinary axis 3D");
+  gr->Rotate(50,60);    gr->Light(true);
+  gr->Plot(x,y,z,"r2"); gr->Surf(a,"BbcyrR#");
+  gr->Axis(); gr->Grid(); gr->Box();
+  gr->Label('x',"B",1); gr->Label('y',"C",1); gr->Label('z',"Z",1);
+
+  gr->SubPlot(2,2,1); gr->Title("Ternary axis (x+y+t=1)");
+  gr->Ternary(1);
+  gr->Plot(x,y,"r2"); gr->Plot(rx,ry,"q^ ");  gr->Cont(a,"BbcyrR");
+  gr->Line(mglPoint(0.5,0), mglPoint(0,0.75), "g2");
+  gr->Axis(); gr->Grid("xyz","B;");
+  gr->Label('x',"B"); gr->Label('y',"C"); gr->Label('t',"A");
+
+  gr->SubPlot(2,2,2); gr->Title("Quaternary axis 3D");
+  gr->Rotate(50,60);    gr->Light(true);
+  gr->Ternary(2);
+  gr->Plot(x,y,z,"r2"); gr->Surf(a,"BbcyrR#");
+  gr->Axis(); gr->Grid(); gr->Box();
+  gr->Label('t',"A",1); gr->Label('x',"B",1);
+  gr->Label('y',"C",1); gr->Label('z',"D",1);
+
+  gr->SubPlot(2,2,3); gr->Title("Ternary axis 3D");
+  gr->Rotate(50,60);    gr->Light(true);
+  gr->Ternary(1);
+  gr->Plot(x,y,z,"r2"); gr->Surf(a,"BbcyrR#");
+  gr->Axis(); gr->Grid(); gr->Box();
+  gr->Label('t',"A",1); gr->Label('x',"B",1);
+  gr->Label('y',"C",1); gr->Label('z',"Z",1);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{ternary, Example of colorbars}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Text features, Legend sample, Ternary axis, Advanced usage
+ at subsection Text features
+ at nav{}
+
+MathGL prints text by vector font. There are functions for manual specifying of text position (like @code{Puts}) and for its automatic selection (like @code{Label}, @code{Legend} and so on). MathGL prints text always in specified position even if it lies outside the bounding box. The default size of font is specified by functions @var{SetFontSize*} (see @ref{Font settings}). However, the actual size of output string depends on subplot size (depends on functions @code{SubPlot}, @code{InPl [...]
+
+Text can be printed as usual one (from left to right), along some direction (rotated text), or along a curve. Text can be printed on several lines, divided by new line symbol @samp{\n}.
+
+Example of MathGL font drawing is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(2,2,0,"");
+  gr->Putsw(mglPoint(0,1),L"Text can be in ASCII and in Unicode");
+  gr->Puts(mglPoint(0,0.6),"It can be \\wire{wire}, \\big{big} or #r{colored}");
+  gr->Puts(mglPoint(0,0.2),"One can change style in string: "
+  "\\b{bold}, \\i{italic, \\b{both}}");
+  gr->Puts(mglPoint(0,-0.2),"Easy to \\a{overline} or "
+  "\\u{underline}");
+  gr->Puts(mglPoint(0,-0.6),"Easy to change indexes ^{up} _{down} @{center}");
+  gr->Puts(mglPoint(0,-1),"It parse TeX: \\int \\alpha \\cdot "
+  "\\sqrt3{sin(\\pi x)^2 + \\gamma_{i_k}} dx");
+
+  gr->SubPlot(2,2,1,"");
+  gr->Puts(mglPoint(0,0.5), "\\sqrt{\\frac{\\alpha^{\\gamma^2}+\\overset 1{\\big\\infty}}{\\sqrt3{2+b}}}", "@", -4);
+  gr->Puts(mglPoint(0,-0.5),"Text can be printed\non several lines");
+
+  gr->SubPlot(2,2,2,"");
+  mglData y;  mgls_prepare1d(&y);
+  gr->Box();  gr->Plot(y.SubData(-1,0));
+  gr->Text(y,"This is very very long string drawn along a curve",":k");
+  gr->Text(y,"Another string drawn under a curve","T:r");
+
+  gr->SubPlot(2,2,3,"");
+  gr->Line(mglPoint(-1,-1),mglPoint(1,-1),"rA");
+  gr->Puts(mglPoint(0,-1),mglPoint(1,-1),"Horizontal");
+  gr->Line(mglPoint(-1,-1),mglPoint(1,1),"rA");
+  gr->Puts(mglPoint(0,0),mglPoint(1,1),"At angle","@");
+  gr->Line(mglPoint(-1,-1),mglPoint(-1,1),"rA");
+  gr->Puts(mglPoint(-1,0),mglPoint(-1,1),"Vertical");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{text, Example of text printing}
+
+You can change font faces by loading font files by function @ref{loadfont}. Note, that this is long-run procedure. Font faces can be downloaded from @uref{http://mathgl.sourceforge.net/download.html, MathGL website} or from @uref{http://sourceforge.net/project/showfiles.php?group_id=152187&package_id=267177, here}. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  double h=1.1, d=0.25;
+  gr->LoadFont("STIX");     gr->Puts(mglPoint(0,h), "default font (STIX)");
+  gr->LoadFont("adventor"); gr->Puts(mglPoint(0,h-d), "adventor font");
+  gr->LoadFont("bonum");    gr->Puts(mglPoint(0,h-2*d), "bonum font");
+  gr->LoadFont("chorus");   gr->Puts(mglPoint(0,h-3*d), "chorus font");
+  gr->LoadFont("cursor");   gr->Puts(mglPoint(0,h-4*d), "cursor font");
+  gr->LoadFont("heros");    gr->Puts(mglPoint(0,h-5*d), "heros font");
+  gr->LoadFont("heroscn");  gr->Puts(mglPoint(0,h-6*d), "heroscn font");
+  gr->LoadFont("pagella");  gr->Puts(mglPoint(0,h-7*d), "pagella font");
+  gr->LoadFont("schola");   gr->Puts(mglPoint(0,h-8*d), "schola font");
+  gr->LoadFont("termes");   gr->Puts(mglPoint(0,h-9*d), "termes font");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{fonts, Example of font faces}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Legend sample, Cutting sample, Text features, Advanced usage
+ at subsection Legend sample
+ at nav{}
+
+Legend is one of standard ways to show plot annotations. Basically you need to connect the plot style (line style, marker and color) with some text. In MathGL, you can do it by 2 methods: manually using @ref{addlegend} function; or use @samp{legend} option (see @ref{Command options}), which will use last plot style. In both cases, legend entries will be added into internal accumulator, which later used for legend drawing itself. @ref{clearlegend} function allow you to remove all saved le [...]
+
+There are 2 features. If plot style is empty then text will be printed without indent. If you want to plot the text with indent but without plot sample then you need to use space @samp{ } as plot style. Such style @samp{ } will draw a plot sample (line with marker(s)) which is invisible line (i.e. nothing) and print the text with indent as usual one.
+
+Function @ref{legend} draw legend on the plot. The position of the legend can be selected automatic or manually. You can change the size and style of text labels, as well as setup the plot sample. The sample code demonstrating legend features is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->AddLegend("sin(\\pi {x^2})","b");
+  gr->AddLegend("sin(\\pi x)","g*");
+  gr->AddLegend("sin(\\pi \\sqrt{x})","rd");
+  gr->AddLegend("just text"," ");
+  gr->AddLegend("no indent for this","");
+
+  gr->SubPlot(2,2,0,""); gr->Title("Legend (default)");
+  gr->Box();  gr->Legend();
+
+  gr->Legend(3,"A#");
+  gr->Puts(mglPoint(0.75,0.65),"Absolute position","A");
+
+  gr->SubPlot(2,2,2,"");  gr->Title("coloring");  gr->Box();
+  gr->Legend(0,"r#"); gr->Legend(1,"Wb#");  gr->Legend(2,"ygr#");
+
+  gr->SubPlot(2,2,3,"");  gr->Title("manual position"); gr->Box();
+  gr->Legend(0.5,1);  gr->Puts(mglPoint(0.5,0.55),"at x=0.5, y=1","a");
+  gr->Legend(1,"#-"); gr->Puts(mglPoint(0.75,0.25),"Horizontal legend","a");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{legend, Example of legend}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cutting sample, , Legend sample, Advanced usage
+ at subsection Cutting sample
+ at nav{}
+
+The last common thing which I want to show in this section is how one can cut off points from plot. There are 4 mechanism for that.
+ at itemize @bullet
+ at item
+You can set one of coordinate to NAN value. All points with NAN values will be omitted.
+
+ at item
+You can enable cutting at edges by @code{SetCut} function. As result all points out of bounding box will be omitted.
+
+ at item
+You can set cutting box by @code{SetCutBox} function. All points inside this box will be omitted.
+
+ at item
+You can define cutting formula by @code{SetCutOff} function. All points for which the value of formula is nonzero will be omitted. Note, that this is the slowest variant.
+ at end itemize
+
+Below I place the code which demonstrate last 3 possibilities:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,c,v(1); mgls_prepare2d(&a); mgls_prepare3d(&c); v.a[0]=0.5;
+  gr->SubPlot(2,2,0); gr->Title("Cut on (default)");
+  gr->Rotate(50,60);  gr->Light(true);
+  gr->Box();  gr->Surf(a,"","zrange -1 0.5");
+
+  gr->SubPlot(2,2,1); gr->Title("Cut off");   gr->Rotate(50,60);
+  gr->Box();  gr->Surf(a,"","zrange -1 0.5; cut off");
+
+  gr->SubPlot(2,2,2); gr->Title("Cut in box");  gr->Rotate(50,60);
+  gr->SetCutBox(mglPoint(0,-1,-1), mglPoint(1,0,1.1));
+  gr->Alpha(true);  gr->Box();  gr->Surf3(c);
+  gr->SetCutBox(mglPoint(0), mglPoint(0));  // switch it off
+
+  gr->SubPlot(2,2,3); gr->Title("Cut by formula");  gr->Rotate(50,60);
+  gr->CutOff("(z>(x+0.5*y-1)^2-1) & (z>(x-0.5*y-1)^2-1)");
+  gr->Box();  gr->Surf3(c); gr->CutOff(""); // switch it off
+  return 0;
+}
+ at end verbatim
+
+ at pfig{cut, Example of point cutting}
+
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Data handling, Data plotting, Advanced usage, Examples
+ at section Data handling
+ at nav{}
+
+Class @code{mglData} contains all functions for the data handling in MathGL (@pxref{Data processing}). There are several matters why I use class @code{mglData} but not a single array: it does not depend on type of data (mreal or double), sizes of data arrays are kept with data, memory working is simpler and safer.
+
+ at menu
+* Array creation::
+* Linking array::
+* Change data::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Array creation, Linking array, , Data handling
+ at subsection Array creation
+ at nav{}
+
+There are many ways in MathGL how data arrays can be created and filled.
+
+One can put the data in @code{mglData} instance by several ways. Let us do it for sinus function:
+ at itemize @bullet
+ at item
+one can create external array, fill it and put to @code{mglData} variable
+ at verbatim
+  double *a = new double[50];
+  for(int i=0;i<50;i++)   a[i] = sin(M_PI*i/49.);
+
+  mglData y;
+  y.Set(a,50);
+ at end verbatim
+
+ at item
+another way is to create @code{mglData} instance of the desired size and then to work directly with data in this variable
+ at verbatim
+  mglData y(50);
+  for(int i=0;i<50;i++)   y.a[i] = sin(M_PI*i/49.);
+ at end verbatim
+
+ at item
+next way is to fill the data in @code{mglData} instance by textual formula with the help of @code{Modify()} function
+ at verbatim
+  mglData y(50);
+  y.Modify("sin(pi*x)");
+ at end verbatim
+
+ at item
+or one may fill the array in some interval and modify it later
+ at verbatim
+  mglData y(50);
+  y.Fill(0,M_PI);
+  y.Modify("sin(u)");
+ at end verbatim
+
+ at item
+finally it can be loaded from file
+ at verbatim
+  FILE *fp=fopen("sin.dat","wt");   // create file first
+  for(int i=0;i<50;i++)   fprintf(fp,"%g\n",sin(M_PI*i/49.));
+  fclose(fp);
+
+  mglData y("sin.dat");             // load it
+ at end verbatim
+At this you can use textual or HDF files, as well as import values from bitmap image (PNG is supported right now).
+
+ at item
+at this one can read only part of data
+ at verbatim
+  FILE *fp-fopen("sin.dat","wt");   // create large file first
+  for(int i=0;i<70;i++)   fprintf(fp,"%g\n",sin(M_PI*i/49.));
+  fclose(fp);
+
+  mglData y;
+  y.Read("sin.dat",50);             // load it
+ at end verbatim
+ at end itemize
+
+Creation of 2d- and 3d-arrays is mostly the same. But one should keep in mind that class @code{mglData} uses flat data representation. For example, matrix 30*40 is presented as flat (1d-) array with length 30*40=1200 (nx=30, ny=40). The element with indexes @{i,j@} is a[i+nx*j]. So for 2d array we have:
+ at verbatim
+  mglData z(30,40);
+  for(int i=0;i<30;i++)   for(int j=0;j<40;j++)
+    z.a[i+30*j] = sin(M_PI*i/29.)*sin(M_PI*j/39.);
+ at end verbatim
+or by using @code{Modify()} function
+ at verbatim
+  mglData z(30,40);
+  z.Modify("sin(pi*x)*cos(pi*y)");
+ at end verbatim
+
+The only non-obvious thing here is using multidimensional arrays in C/C++, i.e. arrays defined like @code{mreal dat[40][30];}. Since, formally these elements @code{dat[i]} can address the memory in arbitrary place you should use the proper function to convert such arrays to @code{mglData} object. For C++ this is functions like @code{mglData::Set(mreal **dat, int N1, int N2);}. For C this is functions like @code{mgl_data_set_mreal2(HMDT d, const mreal **dat, int N1, int N2);}. At this, yo [...]
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Linking array, Change data, Array creation, Data handling
+ at subsection Linking array
+ at nav{}
+
+Sometimes the data arrays are so large, that one couldn't' copy its values to another array (i.e. into mglData). In this case, he can define its own class derived from @code{mglDataA} (see @ref{mglDataA class}) or can use @code{Link} function.
+
+In last case, MathGL just save the link to an external data array, but not copy it. You should provide the existence of this data array for whole time during which MathGL can use it. Another point is that MathGL will automatically create new array if you'll try to modify data values by any of @code{mglData} functions. So, you should use only function with @code{const} modifier if you want still using link to the original data array.
+
+Creating the link is rather simple -- just the same as using @code{Set} function
+ at verbatim
+  double *a = new double[50];
+  for(int i=0;i<50;i++)   a[i] = sin(M_PI*i/49.);
+
+  mglData y;
+  y.Link(a,50);
+ at end verbatim
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Change data, , Linking array, Data handling
+ at subsection Change data
+ at nav{}
+
+MathGL has functions for data processing: differentiating, integrating, smoothing and so on (for more detail, see @ref{Data processing}). Let us consider some examples. The simplest ones are integration and differentiation. The direction in which operation will be performed is specified by textual string, which may contain symbols @samp{x}, @samp{y} or @samp{z}. For example, the call of @code{Diff("x")} will differentiate data along @samp{x} direction; the call of @code{Integral("xy")} p [...]
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SetRanges(0,1,0,1,0,1);
+  mglData a(30,40); a.Modify("x*y");
+  gr->SubPlot(2,2,0); gr->Rotate(60,40);
+  gr->Surf(a);    gr->Box();
+  gr->Puts(mglPoint(0.7,1,1.2),"a(x,y)");
+  gr->SubPlot(2,2,1); gr->Rotate(60,40);
+  a.Diff("x");    gr->Surf(a);  gr->Box();
+  gr->Puts(mglPoint(0.7,1,1.2),"da/dx");
+  gr->SubPlot(2,2,2); gr->Rotate(60,40);
+  a.Integral("xy"); gr->Surf(a);  gr->Box();
+  gr->Puts(mglPoint(0.7,1,1.2),"\\int da/dx dxdy");
+  gr->SubPlot(2,2,3); gr->Rotate(60,40);
+  a.Diff2("y"); gr->Surf(a);  gr->Box();
+  gr->Puts(mglPoint(0.7,1,1.2),"\\int {d^2}a/dxdy dx");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{dat_diff, Example of data differentiation and integration}
+
+Data smoothing (function @ref{smooth}) is more interesting and important. This function has single argument which define type of smoothing and its direction. Now 3 methods are supported: @samp{3} -- linear averaging by 3 points, @samp{5} -- linear averaging by 5 points, and default one -- quadratic averaging by 5 points.
+
+MathGL also have some amazing functions which is not so important for data processing as useful for data plotting. There are functions for finding envelope (useful for plotting rapidly oscillating data), for data sewing (useful to removing jumps on the phase), for data resizing (interpolation). Let me demonstrate it:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(2,2,0,"");  gr->Title("Envelop sample");
+  mglData d1(1000); gr->Fill(d1,"exp(-8*x^2)*sin(10*pi*x)");
+  gr->Axis();     gr->Plot(d1, "b");
+  d1.Envelop('x');  gr->Plot(d1, "r");
+
+  gr->SubPlot(2,2,1,"");  gr->Title("Smooth sample");
+  mglData y0(30),y1,y2,y3;
+  gr->SetRanges(0,1,0,1);
+  gr->Fill(y0, "0.4*sin(pi*x) + 0.3*cos(1.5*pi*x) - 0.4*sin(2*pi*x)+0.5*rnd");
+
+  y1=y0;  y1.Smooth("x3");
+  y2=y0;  y2.Smooth("x5");
+  y3=y0;  y3.Smooth("x");
+
+  gr->Plot(y0,"{m7}:s", "legend 'none'"); //gr->AddLegend("none","k");
+  gr->Plot(y1,"r", "legend ''3' style'");
+  gr->Plot(y2,"g", "legend ''5' style'");
+  gr->Plot(y3,"b", "legend 'default'");
+  gr->Legend();   gr->Box();
+
+  gr->SubPlot(2,2,2);   gr->Title("Sew sample");
+  mglData d2(100, 100); gr->Fill(d2, "mod((y^2-(1-x)^2)/2,0.1)");
+  gr->Rotate(50, 60);   gr->Light(true);  gr->Alpha(true);
+  gr->Box();            gr->Surf(d2, "b");
+  d2.Sew("xy", 0.1);  gr->Surf(d2, "r");
+
+  gr->SubPlot(2,2,3);   gr->Title("Resize sample (interpolation)");
+  mglData x0(10), v0(10), x1, v1;
+  gr->Fill(x0,"rnd");     gr->Fill(v0,"rnd");
+  x1 = x0.Resize(100);    v1 = v0.Resize(100);
+  gr->Plot(x0,v0,"b+ ");  gr->Plot(x1,v1,"r-");
+  gr->Label(x0,v0,"%n");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{dat_extra, Example of data smoothing}
+
+Also one can create new data arrays on base of the existing one: extract slice, row or column of data (@ref{subdata}), summarize along a direction(s) (@ref{sum}), find distribution of data elements (@ref{hist}) and so on.
+
+ at anchor{Solve sample}
+Another interesting feature of MathGL is interpolation and root-finding. There are several functions for linear and cubic spline interpolation (see @ref{Interpolation}). Also there is a function @ref{evaluate} which do interpolation of data array for values of each data element of index data. It look as indirect access to the data elements.
+
+This function have inverse function @ref{solve} which find array of indexes at which data array is equal to given value (i.e. work as root finding). But @ref{solve} function have the issue -- usually multidimensional data (2d and 3d ones) have an infinite number of indexes which give some value. This is contour lines for 2d data, or isosurface(s) for 3d data. So, @ref{solve} function will return index only in given direction, assuming that other index(es) are the same as equidistant inde [...]
+
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SetRange('z',0,1);
+  mglData x(20,30), y(20,30), z(20,30), xx,yy,zz;
+  gr->Fill(x,"(x+2)/3*cos(pi*y)");
+  gr->Fill(y,"(x+2)/3*sin(pi*y)");
+  gr->Fill(z,"exp(-6*x^2-2*sin(pi*y)^2)");
+
+  gr->SubPlot(2,1,0); gr->Title("Cartesian space");   gr->Rotate(30,-40);
+  gr->Axis("xyzU");   gr->Box();  gr->Label('x',"x"); gr->Label('y',"y");
+  gr->SetOrigin(1,1); gr->Grid("xy");
+  gr->Mesh(x,y,z);
+
+  // section along 'x' direction
+  mglData u = x.Solve(0.5,'x');
+  mglData v(u.nx);  v.Fill(0,1);
+  xx = x.Evaluate(u,v);   yy = y.Evaluate(u,v);   zz = z.Evaluate(u,v);
+  gr->Plot(xx,yy,zz,"k2o");
+
+  // 1st section along 'y' direction
+  mglData u1 = x.Solve(-0.5,'y');
+  mglData v1(u1.nx);  v1.Fill(0,1);
+  xx = x.Evaluate(v1,u1); yy = y.Evaluate(v1,u1); zz = z.Evaluate(v1,u1);
+  gr->Plot(xx,yy,zz,"b2^");
+
+  // 2nd section along 'y' direction
+  mglData u2 = x.Solve(-0.5,'y',u1);
+  xx = x.Evaluate(v1,u2); yy = y.Evaluate(v1,u2); zz = z.Evaluate(v1,u2);
+  gr->Plot(xx,yy,zz,"r2v");
+
+  gr->SubPlot(2,1,1); gr->Title("Accompanied space");
+  gr->SetRanges(0,1,0,1); gr->SetOrigin(0,0);
+  gr->Axis(); gr->Box();  gr->Label('x',"i"); gr->Label('y',"j");
+  gr->Grid(z,"h");
+
+  gr->Plot(u,v,"k2o");    gr->Line(mglPoint(0.4,0.5),mglPoint(0.8,0.5),"kA");
+  gr->Plot(v1,u1,"b2^");  gr->Line(mglPoint(0.5,0.15),mglPoint(0.5,0.3),"bA");
+  gr->Plot(v1,u2,"r2v");  gr->Line(mglPoint(0.5,0.7),mglPoint(0.5,0.85),"rA");
+}
+ at end verbatim
+
+ at pfig{solve, Example of data interpolation and root finding}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Data plotting, 1D samples, Data handling, Examples
+ at section Data plotting
+ at nav{}
+
+Let me now show how to plot the data. Next section will give much more examples for all plotting functions. Here I just show some basics. MathGL generally has 2 types of plotting functions. Simple variant requires a single data array for plotting, other data (coordinates) are considered uniformly distributed in axis range. Second variant requires data arrays for all coordinates. It allows one to plot rather complex multivalent curves and surfaces (in case of parametric dependencies). Usu [...]
+
+Note, that the call of drawing function adds something to picture but does not clear the previous plots (as it does in Matlab). Another difference from Matlab is that all setup (like transparency, lightning, axis borders and so on) must be specified @strong{before} plotting functions.
+
+Let start for plots for 1D data. Term ``1D data'' means that data depend on single index (parameter) like curve in parametric form @{x(i),y(i),z(i)@}, i=1...n. The textual argument allow you specify styles of line and marks (see @ref{Line styles}). If this parameter is @code{NULL} or empty then solid line with color from palette is used (see @ref{Palette and colors}).
+
+Below I shall show the features of 1D plotting on base of @ref{plot} function. Let us start from sinus plot:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y0(50); 	y0.Modify("sin(pi*(2*x-1))");
+  gr->SubPlot(2,2,0);
+  gr->Plot(y0);   	gr->Box();
+ at end verbatim
+Style of line is not specified in @ref{plot} function. So MathGL uses the solid line with first color of palette (this is blue). Next subplot shows array @var{y1} with 2 rows:
+ at verbatim
+  gr->SubPlot(2,2,1);
+  mglData y1(50,2);
+  y1.Modify("sin(pi*2*x-pi)");
+  y1.Modify("cos(pi*2*x-pi)/2",1);
+  gr->Plot(y1);   	gr->Box();
+ at end verbatim
+As previously I did not specify the style of lines. As a result, MathGL again uses solid line with next colors in palette (there are green and red). Now let us plot a circle on the same subplot. The circle is parametric curve @math{x=cos(\pi t), y=sin(\pi t)}. I will set the color of the circle (dark yellow, @samp{Y}) and put marks @samp{+} at point position:
+ at verbatim
+  mglData x(50);  	x.Modify("cos(pi*2*x-pi)");
+  gr->Plot(x,y0,"Y+");
+ at end verbatim
+Note that solid line is used because I did not specify the type of line. The same picture can be achieved by @ref{plot} and @ref{subdata} functions. Let us draw ellipse by orange dash line:
+ at verbatim
+  gr->Plot(y1.SubData(-1,0),y1.SubData(-1,1),"q|");
+ at end verbatim
+
+Drawing in 3D space is mostly the same. Let us draw spiral with default line style. Now its color is 4-th color from palette (this is cyan):
+ at verbatim
+  gr->SubPlot(2,2,2);	gr->Rotate(60,40);
+  mglData z(50);  	z.Modify("2*x-1");
+  gr->Plot(x,y0,z);	gr->Box();
+ at end verbatim
+Functions @ref{plot} and @ref{subdata} make 3D curve plot but for single array. Use it to put circle marks on the previous plot:
+ at verbatim
+  mglData y2(10,3);	y2.Modify("cos(pi*(2*x-1+y))");
+  y2.Modify("2*x-1",2);
+  gr->Plot(y2.SubData(-1,0),y2.SubData(-1,1),y2.SubData(-1,2),"bo ");
+ at end verbatim
+Note that line style is empty @samp{ } here. Usage of other 1D plotting functions looks similar:
+ at verbatim
+  gr->SubPlot(2,2,3);	gr->Rotate(60,40);
+  gr->Bars(x,y0,z,"r");	gr->Box();
+  return 0;
+}
+ at end verbatim
+
+Surfaces @ref{surf} and other 2D plots (@pxref{2D plotting}) are drown the same simpler as 1D one. The difference is that the string parameter specifies not the line style but the color scheme of the plot (see @ref{Color scheme}). Here I draw attention on 4 most interesting color schemes. There is gray scheme where color is changed from black to white (string @samp{kw}) or from white to black (string @samp{wk}). Another scheme is useful for accentuation of negative (by blue color) and po [...]
+
+Now I shall show the example of a surface drawing. At first let us switch lightning on
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->Light(true);	gr->Light(0,mglPoint(0,0,1));
+ at end verbatim
+and draw the surface, considering coordinates x,y to be uniformly distributed in axis range
+ at verbatim
+  mglData a0(50,40);
+  a0.Modify("0.6*sin(2*pi*x)*sin(3*pi*y)+0.4*cos(3*pi*(x*y))");
+  gr->SubPlot(2,2,0);	gr->Rotate(60,40);
+  gr->Surf(a0);		gr->Box();
+ at end verbatim
+Color scheme was not specified. So previous color scheme is used. In this case it is default color scheme (``jet'') for the first plot. Next example is a sphere. The sphere is parametrically specified surface:
+ at verbatim
+  mglData x(50,40),y(50,40),z(50,40);
+  x.Modify("0.8*sin(2*pi*x)*sin(pi*y)");
+  y.Modify("0.8*cos(2*pi*x)*sin(pi*y)");
+  z.Modify("0.8*cos(pi*y)");
+  gr->SubPlot(2,2,1);	gr->Rotate(60,40);
+  gr->Surf(x,y,z,"BbwrR");gr->Box();
+ at end verbatim
+I set color scheme to @code{"BbwrR"} that corresponds to red top and blue bottom of the sphere.
+
+Surfaces will be plotted for each of slice of the data if @var{nz}>1. Next example draws surfaces for data arrays with @var{nz}=3:
+ at verbatim
+  mglData a1(50,40,3);
+  a1.Modify("0.6*sin(2*pi*x)*sin(3*pi*y)+0.4*cos(3*pi*(x*y))");
+  a1.Modify("0.6*cos(2*pi*x)*cos(3*pi*y)+0.4*sin(3*pi*(x*y))",1);
+  a1.Modify("0.6*cos(2*pi*x)*cos(3*pi*y)+0.4*cos(3*pi*(x*y))",2);
+  gr->SubPlot(2,2,2);	gr->Rotate(60,40);
+  gr->Alpha(true);
+  gr->Surf(a1);		gr->Box();
+ at end verbatim
+Note, that it may entail a confusion. However, if one will use density plot then the picture will look better:
+ at verbatim
+  gr->SubPlot(2,2,3);	gr->Rotate(60,40);
+  gr->Dens(a1);		gr->Box();
+  return 0;
+}
+ at end verbatim
+
+Drawing of other 2D plots is analogous. The only peculiarity is the usage of flag @samp{#}. By default this flag switches on the drawing of a grid on plot (@ref{grid} or @ref{mesh} for plots in plain or in volume). However, for isosurfaces (including surfaces of rotation @ref{axial}) this flag switches the  face drawing off. Figure becomes wired. The following code gives example of flag @samp{#} using (compare with normal function drawing as in its description):
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->Alpha(true);	gr->Light(true);	gr->Light(0,mglPoint(0,0,1));
+  mglData a(30,20);
+  a.Modify("0.6*sin(2*pi*x)*sin(3*pi*y) + 0.4*cos(3*pi*(x*y))");
+
+  gr->SubPlot(2,2,0);	gr->Rotate(40,60);
+  gr->Surf(a,"BbcyrR#");		gr->Box();
+  gr->SubPlot(2,2,1);	gr->Rotate(40,60);
+  gr->Dens(a,"BbcyrR#");		gr->Box();
+  gr->SubPlot(2,2,2);	gr->Rotate(40,60);
+  gr->Cont(a,"BbcyrR#");		gr->Box();
+  gr->SubPlot(2,2,3);	gr->Rotate(40,60);
+  gr->Axial(a,"BbcyrR#");		gr->Box();
+  return 0;
+}
+ at end verbatim
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node 1D samples, 2D samples, Data plotting, Examples
+ at section 1D samples
+ at nav{}
+
+This section is devoted to visualization of 1D data arrays. 1D means the data which depend on single index (parameter) like curve in parametric form @{x(i),y(i),z(i)@}, i=1...n. Most of samples will use the same data for plotting. So, I put its initialization in separate function
+ at verbatim
+void mgls_prepare1d(mglData *y, mglData *y1=0, mglData *y2=0, mglData *x1=0, mglData *x2=0)
+{
+  register long i,n=50;
+  if(y) y->Create(n,3);
+  if(x1)  x1->Create(n);    if(x2)  x2->Create(n);
+  if(y1)  y1->Create(n);    if(y2)  y2->Create(n);
+  mreal xx;
+  for(i=0;i<n;i++)
+  {
+    xx = i/(n-1.);
+    if(y)
+    {
+      y->a[i] = 0.7*sin(2*M_PI*xx) + 0.5*cos(3*M_PI*xx) + 0.2*sin(M_PI*xx);
+      y->a[i+n] = sin(2*M_PI*xx);
+      y->a[i+2*n] = cos(2*M_PI*xx);
+    }
+    if(y1)  y1->a[i] = 0.5+0.3*cos(2*M_PI*xx);
+    if(y2)  y2->a[i] = 0.3*sin(2*M_PI*xx);
+    if(x1)  x1->a[i] = xx*2-1;
+    if(x2)  x2->a[i] = 0.05+0.03*cos(2*M_PI*xx);
+  }
+}
+ at end verbatim
+or using C functions
+ at verbatim
+void mgls_prepare1d(HMDT y, HMDT y1=0, HMDT y2=0, HMDT x1=0, HMDT x2=0)
+{
+  register long i,n=50;
+  if(y)   mgl_data_create(y,n,3,1);
+  if(x1)  mgl_data_create(x1,n,1,1);
+  if(x2)  mgl_data_create(x2,n,1,1);
+  if(y1)  mgl_data_create(y1,n,1,1);
+  if(y2)  mgl_data_create(y2,n,1,1);
+  mreal xx;
+  for(i=0;i<n;i++)
+  {
+    xx = i/(n-1.);
+    if(y)
+    {
+      mgl_data_set_value(y, 0.7*sin(2*M_PI*xx) + 0.5*cos(3*M_PI*xx) + 0.2*sin(M_PI*xx), i,0,0);
+      mgl_data_set_value(y, sin(2*M_PI*xx), i,1,0);
+      mgl_data_set_value(y, cos(2*M_PI*xx), i,2,0);
+    }
+    if(y1)  mgl_data_set_value(y1, 0.5+0.3*cos(2*M_PI*xx), i,0,0);
+    if(y2)  mgl_data_set_value(y2, 0.3*sin(2*M_PI*xx), i,0,0);
+    if(x1)  mgl_data_set_value(x1, xx*2-1, i,0,0);
+    if(x2)  mgl_data_set_value(x2, 0.05+0.03*cos(2*M_PI*xx), i,0,0);
+  }
+}
+ at end verbatim
+
+ at menu
+* Plot sample::
+* Radar sample::
+* Step sample::
+* Tens sample::
+* Area sample::
+* Region sample::
+* Stem sample::
+* Bars sample::
+* Barh sample::
+* Cones sample::
+* Chart sample::
+* BoxPlot sample::
+* Candle sample::
+* OHLC sample::
+* Error sample::
+* Mark sample::
+* TextMark sample::
+* Label sample::
+* Table sample::
+* Iris sample::
+* Tube sample::
+* Tape sample::
+* Torus sample::
+* Lamerey sample::
+* Bifurcation sample::
+* Pmap sample::
+ at end menu
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Plot sample, Radar sample, , 1D samples
+ at subsection Plot sample
+ at nav{}
+
+Function @ref{plot} is most standard way to visualize 1D data array. By default, @code{Plot} use colors from palette. However, you can specify manual color/palette, and even set to use new color for each points by using @samp{!} style. Another feature is @samp{ } style which draw only markers without line between points. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y;  mgls_prepare1d(&y); gr->SetOrigin(0,0,0);
+  gr->SubPlot(2,2,0,"");  gr->Title("Plot plot (default)");
+  gr->Box();  gr->Plot(y);
+
+  gr->SubPlot(2,2,2,"");  gr->Title("'!' style; 'rgb' palette");
+  gr->Box();  gr->Plot(y,"o!rgb");
+
+  gr->SubPlot(2,2,3,"");  gr->Title("just markers");
+  gr->Box();  gr->Plot(y," +");
+
+  gr->SubPlot(2,2,1); gr->Title("3d variant");
+  gr->Rotate(50,60);  gr->Box();
+  mglData yc(30), xc(30), z(30);  z.Modify("2*x-1");
+  yc.Modify("sin(pi*(2*x-1))"); xc.Modify("cos(pi*2*x-pi)");
+  gr->Plot(xc,yc,z,"rs");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{plot, Example of Plot()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Radar sample, Step sample, Plot sample, 1D samples
+ at subsection Radar sample
+ at nav{}
+
+Function @ref{radar} plot is variant of @code{Plot} one, which make plot in polar coordinates and draw radial rays in point directions. If you just need a plot in polar coordinates then I recommend to use @ref{Curvilinear coordinates} or @code{Plot} in parabolic form with @code{x=r*cos(fi); y=r*sin(fi);}. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData yr(10,3); yr.Modify("0.4*sin(pi*(2*x+y))+0.1*rnd");
+  gr->SubPlot(1,1,0,"");  gr->Title("Radar plot (with grid, '\\#')");
+  gr->Radar(yr,"#");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{radar, Example of Radar()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Step sample, Tens sample, Radar sample, 1D samples
+ at subsection Step sample
+ at nav{}
+
+Function @ref{step} plot data as stairs. It have the same options as @code{Plot}. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y;  mgls_prepare1d(&y); gr->SetOrigin(0,0,0);
+  mglData yc(30), xc(30), z(30);  z.Modify("2*x-1");
+  yc.Modify("sin(pi*(2*x-1))"); xc.Modify("cos(pi*2*x-pi)");
+
+  gr->SubPlot(2,2,0,"");  gr->Title("Step plot (default)");
+  gr->Box();  gr->Step(y);
+
+  gr->SubPlot(2,2,1); gr->Title("3d variant");  gr->Rotate(50,60);
+  gr->Box();  gr->Step(xc,yc,z,"r");
+
+  gr->SubPlot(2,2,2,"");  gr->Title("'!' style");
+  gr->Box();  gr->Step(y,"s!rgb");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{step, Example of Step()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Tens sample, Area sample, Step sample, 1D samples
+ at subsection Tens sample
+ at nav{}
+
+Function @ref{tens} is variant of @ref{plot} with smooth coloring along the curves. At this, color is determined as for surfaces (see @ref{Color scheme}). The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y;  mgls_prepare1d(&y); gr->SetOrigin(0,0,0);
+  gr->SubPlot(2,2,0,"");  gr->Title("Tens plot (default)");
+  gr->Box();  gr->Tens(y.SubData(-1,0), y.SubData(-1,1));
+
+  gr->SubPlot(2,2,2,"");  gr->Title("' ' style");
+  gr->Box();  gr->Tens(y.SubData(-1,0), y.SubData(-1,1),"o ");
+
+  gr->SubPlot(2,2,1); gr->Title("3d variant");  gr->Rotate(50,60);  gr->Box();
+  mglData yc(30), xc(30), z(30);  z.Modify("2*x-1");
+  yc.Modify("sin(pi*(2*x-1))"); xc.Modify("cos(pi*2*x-pi)");
+  gr->Tens(xc,yc,z,z,"s");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{tens, Example of Tens()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Area sample, Region sample, Tens sample, 1D samples
+ at subsection Area sample
+ at nav{}
+
+Function @ref{area} fill the area between curve and axis plane. It support gradient filling if 2 colors per curve is specified. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y;  mgls_prepare1d(&y); gr->SetOrigin(0,0,0);
+  gr->SubPlot(2,2,0,"");  gr->Title("Area plot (default)");
+  gr->Box();  gr->Area(y);
+
+  gr->SubPlot(2,2,1,"");  gr->Title("2 colors");
+  gr->Box();  gr->Area(y,"cbgGyr");
+
+  gr->SubPlot(2,2,2,"");  gr->Title("'!' style");
+  gr->Box();  gr->Area(y,"!");
+
+  gr->SubPlot(2,2,3); gr->Title("3d variant");
+  gr->Rotate(50,60);  gr->Box();
+  mglData yc(30), xc(30), z(30);  z.Modify("2*x-1");
+  yc.Modify("sin(pi*(2*x-1))"); xc.Modify("cos(pi*2*x-pi)");
+  gr->Area(xc,yc,z,"r");
+  yc.Modify("-sin(pi*(2*x-1))");  gr->Area(xc,yc,z,"b#");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{area, Example of Area()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Region sample, Stem sample, Area sample, 1D samples
+ at subsection Region sample
+ at nav{}
+
+Function @ref{region} fill the area between 2 curves. It support gradient filling if 2 colors per curve is specified. Also it can fill only the region y1<y<y2 if style @samp{i} is used. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y;  mgls_prepare1d(&y);
+  mglData y1 = y.SubData(-1,1), y2 = y.SubData(-1,2);  gr->SetOrigin(0,0,0);
+
+  gr->SubPlot(2,2,0,"");  gr->Title("Region plot (default)"); gr->Box();
+  gr->Region(y1,y2);  gr->Plot(y1,"k2");  gr->Plot(y2,"k2");
+
+  gr->SubPlot(2,2,1,"");  gr->Title("2 colors");  gr->Box();
+  gr->Region(y1,y2,"yr"); gr->Plot(y1,"k2");  gr->Plot(y2,"k2");
+
+  gr->SubPlot(2,2,2,"");  gr->Title("'i' style");  gr->Box();
+  gr->Region(y1,y2,"ir"); gr->Plot(y1,"k2");  gr->Plot(y2,"k2");
+
+  gr->SubPlot(2,2,3,"^_");  gr->Title("3d variant");  gr->Rotate(40,60);  gr->Box();
+  gr->Fill(y1,"cos(pi*x)"); gr->Fill(y2,"cos(pi*x+pi/3)");
+  mglData x1(y1.nx), x2(y1.nx), z(y1.nx);
+  gr->Fill(x1,"sin(pi*x)"); gr->Fill(x2,"sin(pi*x+pi/3)");  gr->Fill(z,"x");
+  gr->Plot(x1,y1,z,"r2");   gr->Plot(x2,y2,z,"b2");
+  gr->Region(x1,y1,z,x2,y2,z,"cmy!");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{region, Example of Region()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Stem sample, Bars sample, Region sample, 1D samples
+ at subsection Stem sample
+ at nav{}
+
+Function @ref{stem} draw vertical bars. It is most attractive if markers are drawn too. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y;  mgls_prepare1d(&y); gr->SetOrigin(0,0,0);
+  mglData yc(30), xc(30), z(30);  z.Modify("2*x-1");
+  yc.Modify("sin(pi*(2*x-1))"); xc.Modify("cos(pi*2*x-pi)");
+  gr->SubPlot(2,2,0,"");  gr->Title("Stem plot (default)");
+  gr->Box();  gr->Stem(y);
+
+  gr->SubPlot(2,2,1); gr->Title("3d variant");  gr->Rotate(50,60);
+  gr->Box();  gr->Stem(xc,yc,z,"rx");
+
+  gr->SubPlot(2,2,2,"");  gr->Title("'!' style");
+  gr->Box();  gr->Stem(y,"o!rgb");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{stem, Example of Stem()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Bars sample, Barh sample, Stem sample, 1D samples
+ at subsection Bars sample
+ at nav{}
+
+Function @ref{bars} draw vertical bars. It have a lot of options: bar-above-bar (@samp{a} style), fall like (@samp{f} style), 2 colors for positive and negative values, wired bars (@samp{#} style), 3D variant. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData ys(10,3); ys.Modify("0.8*sin(pi*(2*x+y/2))+0.2*rnd");
+  gr->SetOrigin(0,0,0);
+  gr->SubPlot(3,2,0,"");  gr->Title("Bars plot (default)");
+  gr->Box();  gr->Bars(ys);
+
+  gr->SubPlot(3,2,1,"");  gr->Title("2 colors");
+  gr->Box();  gr->Bars(ys,"cbgGyr");
+
+  gr->SubPlot(3,2,4,"");  gr->Title("'\\#' style");
+  gr->Box();  gr->Bars(ys,"#");
+
+  gr->SubPlot(3,2,5); gr->Title("3d variant");
+  gr->Rotate(50,60);  gr->Box();
+  mglData yc(30), xc(30), z(30);  z.Modify("2*x-1");
+  yc.Modify("sin(pi*(2*x-1))"); xc.Modify("cos(pi*2*x-pi)");
+  gr->Bars(xc,yc,z,"r");
+
+  gr->SetRanges(-1,1,-3,3);
+  gr->SubPlot(3,2,2,"");  gr->Title("'a' style");
+  gr->Box();  gr->Bars(ys,"a");
+
+  gr->SubPlot(3,2,3,"");  gr->Title("'f' style");
+  gr->Box();  gr->Bars(ys,"f");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{bars, Example of Bars()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Barh sample, Cones sample, Bars sample, 1D samples
+ at subsection Barh sample
+ at nav{}
+
+Function @ref{barh} is the similar to @code{Bars} but draw horizontal bars. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData ys(10,3); ys.Modify("0.8*sin(pi*(2*x+y/2))+0.2*rnd");
+  gr->SetOrigin(0,0,0);
+  gr->SubPlot(2,2,0,"");  gr->Title("Barh plot (default)");
+  gr->Box();  gr->Barh(ys);
+
+  gr->SubPlot(2,2,1,"");  gr->Title("2 colors");
+  gr->Box();  gr->Barh(ys,"cbgGyr");
+
+  gr->SetRanges(-3,3,-1,1);
+  gr->SubPlot(2,2,2,"");  gr->Title("'a' style");
+  gr->Box();  gr->Barh(ys,"a");
+
+  gr->SubPlot(2,2,3,"");  gr->Title("'f' style");
+  gr->Box();  gr->Barh(ys,"f");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{barh, Example of Barh()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cones sample, Chart sample, Barh sample, 1D samples
+ at subsection Cones sample
+ at nav{}
+
+Function @ref{cones} is similar to @code{Bars} but draw cones. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData ys(10,3);   ys.Modify("0.8*sin(pi*(2*x+y/2))+0.2*rnd");
+  gr->Light(true);    gr->SetOrigin(0,0,0);
+  gr->SubPlot(3,2,0); gr->Title("Cones plot");
+  gr->Rotate(50,60);  gr->Box();  gr->Cones(ys);
+
+  gr->SubPlot(3,2,1); gr->Title("2 colors");
+  gr->Rotate(50,60);  gr->Box();  gr->Cones(ys,"cbgGyr");
+
+  gr->SubPlot(3,2,2); gr->Title("'#' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Cones(ys,"#");
+
+  gr->SubPlot(3,2,3); gr->Title("'a' style");
+  gr->SetRange('z',-2,2); // increase range since summation can exceed [-1,1]
+  gr->Rotate(50,60);  gr->Box();  gr->Cones(ys,"a");
+
+  gr->SubPlot(3,2,4); gr->Title("'t' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Cones(ys,"t");
+
+  gr->SubPlot(3,2,5); gr->Title("'4' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Cones(ys,"4");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{cones, Example of Cones()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Chart sample, BoxPlot sample, Cones sample, 1D samples
+ at subsection Chart sample
+ at nav{}
+
+Function @ref{chart} draw colored boxes with width proportional to data values. Use @samp{ } for empty box. Plot looks most attractive in polar coordinates -- well known pie chart. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData ch(7,2);  for(int i=0;i<7*2;i++)  ch.a[i]=mgl_rnd()+0.1;
+  gr->SubPlot(2,2,0); gr->Title("Chart plot (default)");
+  gr->Light(true);  gr->Rotate(50,60);  gr->Box();  gr->Chart(ch);
+
+  gr->SubPlot(2,2,1); gr->Title("'\\#' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Chart(ch,"#");
+
+  gr->SubPlot(2,2,2); gr->Title("Pie chart; ' ' color");
+  gr->SetFunc("(y+1)/2*cos(pi*x)","(y+1)/2*sin(pi*x)","");
+  gr->Rotate(50,60);  gr->Box();  gr->Chart(ch,"bgr cmy#");
+
+  gr->SubPlot(2,2,3); gr->Title("Ring chart; ' ' color");
+  gr->SetFunc("(y+2)/3*cos(pi*x)","(y+2)/3*sin(pi*x)","");
+  gr->Rotate(50,60);  gr->Box();  gr->Chart(ch,"bgr cmy#");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{chart, Example of Chart()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node BoxPlot sample, Candle sample, Chart sample, 1D samples
+ at subsection BoxPlot sample
+ at nav{}
+
+Function @ref{boxplot} draw box-and-whisker diagram. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a(10,7);  a.Modify("(2*rnd-1)^3/2");
+  gr->SubPlot(1,1,0,"");  gr->Title("Boxplot plot");
+  gr->Box();  gr->BoxPlot(a);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{boxplot, Example of BoxPlot()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Candle sample, OHLC sample, BoxPlot sample, 1D samples
+ at subsection Candle sample
+ at nav{}
+
+Function @ref{candle} draw candlestick chart. This is a combination of a line-chart and a bar-chart, in that each bar represents the range of price movement over a given time interval. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y(30);  gr->Fill(y,"sin(pi*x/2)^2");
+  mglData y1(30); gr->Fill(y1,"v/2",y);
+  mglData y2(30); gr->Fill(y2,"(1+v)/2",y);
+  gr->SubPlot(1,1,0,"");  gr->Title("Candle plot (default)");
+  gr->SetRange('y',0,1);  gr->Box();  gr->Candle(y,y1,y2);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{candle, Example of Candle()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node OHLC sample, Error sample, Candle sample, 1D samples
+ at subsection OHLC sample
+ at nav{}
+
+Function @ref{ohlc} draw Open-High-Low-Close diagram. This diagram show vertical line for between maximal(high) and minimal(low) values, as well as horizontal lines before/after vertical line for initial(open)/final(close) values of some process. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData o(10), h(10), l(10), c(10);
+  gr->Fill(o,"0.5*sin(pi*x)");  gr->Fill(c,"0.5*sin(pi*(x+2/9))");
+  gr->Fill(l,"0.3*rnd-0.8");    gr->Fill(h,"0.3*rnd+0.5");
+  gr->SubPlot(1,1,0,"");  gr->Title("OHLC plot");
+  gr->Box();  gr->OHLC(o,h,l,c);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{ohlc, Example of OHLC()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Error sample, Mark sample, OHLC sample, 1D samples
+ at subsection Error sample
+ at nav{}
+
+Function @ref{error} draw error boxes around the points. You can draw default boxes or semi-transparent symbol (like marker, see @ref{Line styles}). Also you can set individual color for each box. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y;  mgls_prepare1d(&y);
+  mglData x0(10), y0(10), ex0(10), ey0(10);
+  mreal x;
+  for(int i=0;i<10;i++)
+  {
+    x = i/9.;
+    x0.a[i] = 2*x-1 + 0.1*mgl_rnd()-0.05;
+    y0.a[i] = 0.7*sin(2*M_PI*x)+0.5*cos(3*M_PI*x)+0.2*sin(M_PI*x)+0.2*mgl_rnd()-0.1;
+    ey0.a[i]=0.2; ex0.a[i]=0.1;
+  }
+
+  gr->SubPlot(2,2,0,"");  gr->Title("Error plot (default)");
+  gr->Box();  gr->Plot(y.SubData(-1,0));  gr->Error(x0,y0,ex0,ey0,"ko");
+
+  gr->SubPlot(2,2,1,"");  gr->Title("'!' style; no e_x");
+  gr->Box();  gr->Plot(y.SubData(-1,0));  gr->Error(x0,y0,ey0,"o!rgb");
+
+  gr->SubPlot(2,2,2,"");  gr->Title("'\\@' style");
+  gr->Box();  gr->Plot(y.SubData(-1,0));  gr->Error(x0,y0,ex0,ey0,"@","alpha 0.5");
+
+  gr->SubPlot(2,2,3); gr->Title("3d variant");  gr->Rotate(50,60);
+  for(int i=0;i<10;i++)
+    gr->Error(mglPoint(2*mgl_rnd()-1,2*mgl_rnd()-1,2*mgl_rnd()-1),
+              mglPoint(0.2,0.2,0.2),"bo");
+  gr->Axis();
+  return 0;
+}
+ at end verbatim
+
+ at pfig{error, Example of Error()}
+
+Additionally, you can use solid large "marks" instead of error boxes by selecting proper style.
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData x0(10), y0(10), ex(10), ey(10);
+  for(int i=0;i<10;i++)
+  {  x0.a[i] = mgl_rnd(); y0.a[i] = mgl_rnd(); ey.a[i] = ex.a[i] = 0.1; }
+  gr->SetRanges(0,1,0,1); gr->Alpha(true);
+  gr->SubPlot(4,3,0,"");  gr->Box(); gr->Error(x0,y0,ex,ey,"#+@");
+  gr->SubPlot(4,3,1,"");  gr->Box(); gr->Error(x0,y0,ex,ey,"#x@");
+  gr->SubPlot(4,3,2,"");  gr->Box(); gr->Error(x0,y0,ex,ey,"#s@","alpha 0.5");
+  gr->SubPlot(4,3,3,"");  gr->Box(); gr->Error(x0,y0,ex,ey,"s@");
+  gr->SubPlot(4,3,4,"");  gr->Box(); gr->Error(x0,y0,ex,ey,"d@");
+  gr->SubPlot(4,3,5,"");  gr->Box(); gr->Error(x0,y0,ex,ey,"#d@","alpha 0.5");
+  gr->SubPlot(4,3,6,"");  gr->Box(); gr->Error(x0,y0,ex,ey,"+@");
+  gr->SubPlot(4,3,7,"");  gr->Box(); gr->Error(x0,y0,ex,ey,"x@");
+  gr->SubPlot(4,3,8,"");  gr->Box(); gr->Error(x0,y0,ex,ey,"o@");
+  gr->SubPlot(4,3,9,"");  gr->Box(); gr->Error(x0,y0,ex,ey,"#o@","alpha 0.5");
+  gr->SubPlot(4,3,10,""); gr->Box(); gr->Error(x0,y0,ex,ey,"#.@");
+  gr->SubPlot(4,3,11,""); gr->Box(); gr->Error(x0,y0,ex,ey);
+}
+ at end verbatim
+
+ at pfig{error2, Example of Error() with marks}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Mark sample, TextMark sample, Error sample, 1D samples
+ at subsection Mark sample
+ at nav{}
+
+Function @ref{mark} draw markers at points. It is mostly the same as @code{Plot} but marker size can be variable. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y,y1; mgls_prepare1d(&y,&y1);
+  gr->SubPlot(1,1,0,"");  gr->Title("Mark plot (default)");
+  gr->Box();  gr->Mark(y,y1,"s");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{mark, Example of Mark()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node TextMark sample, Label sample, Mark sample, 1D samples
+ at subsection TextMark sample
+ at nav{}
+
+Function @ref{textmark} like @code{Mark} but draw text instead of markers. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y,y1; mgls_prepare1d(&y,&y1);
+  gr->SubPlot(1,1,0,"");  gr->Title("TextMark plot (default)");
+  gr->Box();  gr->TextMark(y,y1,"\\gamma","r");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{textmark, Example of TextMark()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Label sample, Table sample, TextMark sample, 1D samples
+ at subsection Label sample
+ at nav{}
+
+Function @ref{label} print text at data points. The string may contain @samp{%x}, @samp{%y}, @samp{%z} for x-, y-, z-coordinates of points, @samp{%n} for point index. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData ys(10); ys.Modify("0.8*sin(pi*2*x)+0.2*rnd");
+  gr->SubPlot(1,1,0,"");  gr->Title("Label plot");
+  gr->Box();  gr->Plot(ys," *");  gr->Label(ys,"y=%y");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{label, Example of Label()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Table sample, Iris sample, Label sample, 1D samples
+ at subsection Table sample
+ at nav{}
+
+Function @ref{table} draw table with data values. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData ys(10,3); ys.Modify("0.8*sin(pi*(2*x+y/2))+0.2*rnd");
+  gr->SubPlot(2,2,0);  gr->Title("Table plot");
+  gr->Table(ys,"y_1\ny_2\ny_3");   gr->Box();
+  gr->SubPlot(2,2,1);  gr->Title("no borders, colored");
+  gr->Table(ys,"y_1\ny_2\ny_3","r|");
+  gr->SubPlot(2,2,2);  gr->Title("no font decrease");
+  gr->Table(ys,"y_1\ny_2\ny_3","#");
+  gr->SubPlot(2,2,3);  gr->Title("manual width, position");
+  gr->Table(0.5, 0.95, ys,"y_1\ny_2\ny_3","#", "value 0.7");  gr->Box();
+  return 0;
+}
+ at end verbatim
+
+ at pfig{table, Example of Table()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Iris sample, Tube sample, Table sample, 1D samples
+ at subsection Iris sample
+ at nav{}
+
+Command @ref{iris} draw Iris plot for columns of data array. The sample code is:
+ at verbatim
+  mglData a("iris.dat");  a.Crop(0,4,'x');  a.Rearrange(4,50);
+  gr->SubPlot(1,1,0,"");
+  if(big!=3)	gr->Title("Iris sample");
+  gr->Iris(a, "sepal\nlength;sepal\nwidth;petal\nlength;petal\nwidth", ". ", "value -1.5;size -2");
+ at end verbatim
+
+ at pfig{iris, Example of Iris()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Tube sample, Tape sample, Iris sample, 1D samples
+ at subsection Tube sample
+ at nav{}
+
+Function @ref{tube} draw tube with variable radius. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y,y1,y2;  mgls_prepare1d(&y,&y1,&y2); y1/=20;
+  gr->SubPlot(2,2,0,"");  gr->Title("Tube plot (default)");
+  gr->Light(true);  gr->Box();  gr->Tube(y,0.05);
+
+  gr->SubPlot(2,2,1,"");  gr->Title("variable radius");
+  gr->Box();  gr->Tube(y,y1);
+
+  gr->SubPlot(2,2,2,"");  gr->Title("'\\#' style");
+  gr->Box();  gr->Tube(y,0.05,"#");
+  mglData yc(50), xc(50), z(50);  z.Modify("2*x-1");
+  yc.Modify("sin(pi*(2*x-1))"); xc.Modify("cos(pi*2*x-pi)");
+
+  gr->SubPlot(2,2,3); gr->Title("3d variant");  gr->Rotate(50,60);
+  gr->Box();  gr->Tube(xc,yc,z,y2,"r");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{tube, Example of Tube()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Tape sample, Torus sample, Tube sample, 1D samples
+ at subsection Tape sample
+ at nav{}
+
+Function @ref{tape} draw tapes which rotate around the curve as normal and binormal. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y;  mgls_prepare1d(&y);
+  mglData xc(50), yc(50), z(50);
+  yc.Modify("sin(pi*(2*x-1))");
+  xc.Modify("cos(pi*2*x-pi)");  z.Fill(-1,1);
+  gr->SubPlot(2,2,0,"");  gr->Title("Tape plot (default)");
+  gr->Box();  gr->Tape(y);  gr->Plot(y,"k");
+
+  gr->SubPlot(2,2,1); gr->Title("3d variant, 2 colors");
+  gr->Rotate(50,60);  gr->Light(true);
+  gr->Box();  gr->Plot(xc,yc,z,"k");  gr->Tape(xc,yc,z,"rg");
+
+  gr->SubPlot(2,2,2); gr->Title("3d variant, x only");  gr->Rotate(50,60);
+  gr->Box();  gr->Plot(xc,yc,z,"k");
+  gr->Tape(xc,yc,z,"xr"); gr->Tape(xc,yc,z,"xr#");
+
+  gr->SubPlot(2,2,3); gr->Title("3d variant, z only");  gr->Rotate(50,60);
+  gr->Box();  gr->Plot(xc,yc,z,"k");
+  gr->Tape(xc,yc,z,"zg"); gr->Tape(xc,yc,z,"zg#");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{tape, Example of Tape()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Torus sample, Lamerey sample, Tape sample, 1D samples
+ at subsection Torus sample
+ at nav{}
+
+Function @ref{torus} draw surface of the curve rotation. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData y1,y2;  mgls_prepare1d(0,&y1,&y2);
+  gr->SubPlot(2,2,0); gr->Title("Torus plot (default)");
+  gr->Light(true);  gr->Rotate(50,60);  gr->Box();  gr->Torus(y1,y2);
+  if(mini)  return;
+
+  gr->SubPlot(2,2,1); gr->Title("'x' style"); gr->Rotate(50,60);
+  gr->Box();  gr->Torus(y1,y2,"x");
+
+  gr->SubPlot(2,2,2); gr->Title("'z' style"); gr->Rotate(50,60);
+  gr->Box();  gr->Torus(y1,y2,"z");
+
+  gr->SubPlot(2,2,3); gr->Title("'\\#' style"); gr->Rotate(50,60);
+  gr->Box();  gr->Torus(y1,y2,"#");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{torus, Example of Torus()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Lamerey sample, Bifurcation sample, Torus sample, 1D samples
+ at subsection Lamerey sample
+ at nav{}
+
+Function @ref{lamerey} draw Lamerey diagram. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(1,1,0,"<_");
+  gr->Title("Lamerey sample");
+  gr->Axis(); gr->Label('x',"\\i x");
+  gr->Label('y',"\\bar{\\i x} = 2 \\i{x}");
+  gr->FPlot("x","k=");  gr->FPlot("2*x","b");
+  gr->Lamerey( 0.00097,"2*x","rv~");
+  gr->Lamerey(-0.00097,"2*x","rv~");
+}
+ at end verbatim
+
+ at pfig{lamerey, Example of Lamerey()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Bifurcation sample, Pmap sample, Lamerey sample, 1D samples
+ at subsection Bifurcation sample
+ at nav{}
+
+Function @ref{bifurcation} draw Bifurcation diagram for logistic map. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(1,1,0,"<_");
+  gr->Title("Bifurcation sample");
+  gr->SetRanges(0,4,0,1);   gr->Axis();
+  gr->Bifurcation(0.005,"x*y*(1-y)","r");
+}
+ at end verbatim
+
+ at pfig{bifurcation, Example of Bifurcation()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Pmap sample, , Bifurcation sample, 1D samples
+ at subsection Pmap sample
+ at nav{}
+
+Function @ref{pmap} draw Poincare map -- show intersections of the curve and the surface. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(1,1,0,"<_^");
+  gr->Title("Poincare map sample");
+  mglData ini(3);	ini[0]=0.1;
+  mglData r(mglODE("cos(y)+sin(z);cos(z)+sin(x);cos(x)+sin(y)","xyz",ini,0.1,100));
+  mglData x(r.SubData(0)),y(r.SubData(1)), z(r.SubData(2));
+  gr->Rotate(40,60);  gr->SetRanges(x,y,z);
+  gr->Axis(); gr->FSurf("0"); gr->Plot(x,y,z,"b");
+  gr->Label('x',"\\i x",0);   gr->Label('y',"\\i y",0);   gr->Label('z',"\\i z",0);
+  gr->Pmap(x,y,z,z, "b#o");
+}
+ at end verbatim
+
+ at pfig{pmap, Example of Pmap()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node 2D samples, 3D samples, 1D samples, Examples
+ at section 2D samples
+ at nav{}
+
+This section is devoted to visualization of 2D data arrays. 2D means the data which depend on 2 indexes (parameters) like matrix z(i,j)=z(x(i),y(j)), i=1...n, j=1...m or in parametric form @{x(i,j),y(i,j),z(i,j)@}. Most of samples will use the same data for plotting. So, I put its initialization in separate function
+ at verbatim
+void mgls_prepare2d(mglData *a, mglData *b=0, mglData *v=0)
+{
+  register long i,j,n=50,m=40,i0;
+  if(a) a->Create(n,m);   if(b) b->Create(n,m);
+  if(v) { v->Create(9); v->Fill(-1,1);  }
+  mreal x,y;
+  for(i=0;i<n;i++)  for(j=0;j<m;j++)
+  {
+    x = i/(n-1.); y = j/(m-1.); i0 = i+n*j;
+    if(a) a->a[i0] = 0.6*sin(2*M_PI*x)*sin(3*M_PI*y)+0.4*cos(3*M_PI*x*y);
+    if(b) b->a[i0] = 0.6*cos(2*M_PI*x)*cos(3*M_PI*y)+0.4*cos(3*M_PI*x*y);
+  }
+}
+ at end verbatim
+or using C functions
+ at verbatim
+void mgls_prepare2d(HMDT a, HMDT b=0, HMDT v=0)
+{
+  register long i,j,n=50,m=40,i0;
+  if(a) mgl_data_create(a,n,m,1);
+  if(b) mgl_data_create(b,n,m,1);
+  if(v) { mgl_data_create(v,9,1,1); mgl_data_fill(v,-1,1,'x');  }
+  mreal x,y;
+  for(i=0;i<n;i++)  for(j=0;j<m;j++)
+  {
+    x = i/(n-1.); y = j/(m-1.); i0 = i+n*j;
+    if(a) mgl_data_set_value(a, 0.6*sin(2*M_PI*x)*sin(3*M_PI*y)+0.4*cos(3*M_PI*x*y), i,j,0);
+    if(b) mgl_data_set_value(b, 0.6*cos(2*M_PI*x)*cos(3*M_PI*y)+0.4*cos(3*M_PI*x*y), i,j,0);
+  }
+}
+ at end verbatim
+
+ at menu
+* Surf sample::
+* SurfC sample::
+* SurfA sample::
+* SurfCA sample::
+* Mesh sample::
+* Fall sample::
+* Belt sample::
+* Boxs sample::
+* Tile sample::
+* TileS sample::
+* Dens sample::
+* Cont sample::
+* ContF sample::
+* ContD sample::
+* ContV sample::
+* Axial sample::
+* Grad sample::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Surf sample, SurfC sample, , 2D samples
+ at subsection Surf sample
+ at nav{}
+
+Function @ref{surf} is most standard way to visualize 2D data array. @code{Surf} use color scheme for coloring (see @ref{Color scheme}). You can use @samp{#} style for drawing black meshes on the surface. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->SubPlot(2,2,0); gr->Title("Surf plot (default)");
+  gr->Light(true);  gr->Rotate(50,60);  gr->Box();  gr->Surf(a);
+
+  gr->SubPlot(2,2,1); gr->Title("'\\#' style; meshnum 10");
+  gr->Rotate(50,60);  gr->Box();  gr->Surf(a,"#","meshnum 10");
+
+  gr->SubPlot(2,2,2); gr->Title("'.' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Surf(a,".");
+
+  gr->SubPlot(2,2,3); gr->Title("parametric form");
+  mglData x(50,40),y(50,40),z(50,40);
+  gr->Fill(x,"0.8*sin(pi*x)*sin(pi*(y+1)/2)");
+  gr->Fill(y,"0.8*cos(pi*x)*sin(pi*(y+1)/2)");
+  gr->Fill(z,"0.8*cos(pi*(y+1)/2)");
+  gr->Rotate(50,60);  gr->Box();  gr->Surf(x,y,z,"BbwrR");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{surf, Example of Surf()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node SurfC sample, SurfA sample, Surf sample, 2D samples
+ at subsection SurfC sample
+ at nav{}
+
+Function @ref{surfc} is similar to @ref{surf} but its coloring is determined by another data. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,b;  mgls_prepare2d(&a,&b);
+  gr->Title("SurfC plot");  gr->Rotate(50,60);
+  gr->Light(true);  gr->Box();  gr->SurfC(a,b);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{surfc, Example of SurfC()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node SurfA sample, SurfCA sample, SurfC sample, 2D samples
+ at subsection SurfA sample
+ at nav{}
+
+Function @ref{surfa} is similar to @ref{surf} but its transparency is determined by another data. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,b;  mgls_prepare2d(&a,&b);
+  gr->Title("SurfA plot");  gr->Rotate(50,60);
+  gr->Alpha(true);  gr->Light(true);
+  gr->Box();  gr->SurfA(a,b);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{surfa, Example of SurfA()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node SurfCA sample, Mesh sample, SurfA sample, 2D samples
+ at subsection SurfCA sample
+ at nav{}
+
+Function @ref{surfca} is similar to @ref{surf} but its color and transparency is determined by another data. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,b;  mgls_prepare2d(&a,&b);
+  gr->Title("SurfCA plot");  gr->Rotate(50,60);
+  gr->Alpha(true);  gr->Light(true);
+  gr->Box();  gr->SurfCA(a,b,a);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{surfca, Example of SurfCA()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Mesh sample, Fall sample, SurfCA sample, 2D samples
+ at subsection Mesh sample
+ at nav{}
+
+Function @ref{mesh} draw wired surface. You can use @ref{meshnum} for changing number of lines to be drawn. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->Title("Mesh plot"); gr->Rotate(50,60);
+  gr->Box();  gr->Mesh(a);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{mesh, Example of Mesh()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Fall sample, Belt sample, Mesh sample, 2D samples
+ at subsection Fall sample
+ at nav{}
+
+Function @ref{fall} draw waterfall surface. You can use @ref{meshnum} for changing number of lines to be drawn. Also you can use @samp{x} style for drawing lines in other direction. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->Title("Fall plot"); gr->Rotate(50,60);
+  gr->Box();  gr->Fall(a);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{fall, Example of Fall()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Belt sample, Boxs sample, Fall sample, 2D samples
+ at subsection Belt sample
+ at nav{}
+
+Function @ref{belt} draw surface by belts. You can use @samp{x} style for drawing lines in other direction. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->Title("Belt plot"); gr->Rotate(50,60);
+  gr->Box();  gr->Belt(a);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{belt, Example of Belt()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Boxs sample, Tile sample, Belt sample, 2D samples
+ at subsection Boxs sample
+ at nav{}
+
+Function @ref{boxs} draw surface by boxes. You can use @samp{#} for drawing wire plot. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->SetOrigin(0,0,0); gr->Light(true);
+  gr->SubPlot(2,2,0);  gr->Title("Boxs plot (default)");
+  gr->Rotate(40,60);  gr->Box();  gr->Boxs(a);
+
+  gr->SubPlot(2,2,1); gr->Title("'\\@' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Boxs(a,"@");
+
+  gr->SubPlot(2,2,2); gr->Title("'\\#' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Boxs(a,"#");
+
+  gr->SubPlot(2,2,3); gr->Title("compare with Tile");
+  gr->Rotate(50,60);  gr->Box();  gr->Tile(a);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{boxs, Example of Boxs()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Tile sample, TileS sample, Boxs sample, 2D samples
+ at subsection Tile sample
+ at nav{}
+
+Function @ref{tile} draw surface by tiles. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->Title("Tile plot");
+  gr->Rotate(40,60);  gr->Box();  gr->Tile(a);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{tile, Example of Tile()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node TileS sample, Dens sample, Tile sample, 2D samples
+ at subsection TileS sample
+ at nav{}
+
+Function @ref{tiles} is similar to @code{Tile} but tile sizes is determined by another data. This allows one to simulate transparency of the plot. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,b;  mgls_prepare2d(&a,&b);
+  gr->SubPlot(1,1,0,""); gr->Title("TileS plot");
+  gr->Box();  gr->TileS(a,b);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{tiles, Example of TileS()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Dens sample, Cont sample, TileS sample, 2D samples
+ at subsection Dens sample
+ at nav{}
+
+Function @ref{dens} draw density plot for surface. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,a1(30,40,3);  mgls_prepare2d(&a);
+  gr->Fill(a1,"0.6*sin(2*pi*x+pi*(z+1)/2)*sin(3*pi*y+pi*z) + 0.4*cos(3*pi*(x*y)+pi*(z+1)^2/2)");
+  gr->SubPlot(2,2,0,""); gr->Title("Dens plot (default)");
+  gr->Box();  gr->Dens(a);
+
+  gr->SubPlot(2,2,1); gr->Title("3d variant");
+  gr->Rotate(50,60);  gr->Box();  gr->Dens(a);
+
+  gr->SubPlot(2,2,2,"");  gr->Title("'\\#' style; meshnum 10");
+  gr->Box();  gr->Dens(a,"#","meshnum 10");
+
+  gr->SubPlot(2,2,3); gr->Title("several slices");
+  gr->Rotate(50,60);    gr->Box();  gr->Dens(a1);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{dens, Example of Dens()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cont sample, ContF sample, Dens sample, 2D samples
+ at subsection Cont sample
+ at nav{}
+
+Function @ref{cont} draw contour lines for surface. You can select automatic (default) or manual levels for contours, print contour labels, draw it on the surface (default) or at plane (as @code{Dens}). The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,v(5); mgls_prepare2d(&a); v.a[0]=-0.5;  v.a[1]=-0.15; v.a[2]=0; v.a[3]=0.15;  v.a[4]=0.5;
+  gr->SubPlot(2,2,0); gr->Title("Cont plot (default)");
+  gr->Rotate(50,60);  gr->Box();  gr->Cont(a);
+
+  gr->SubPlot(2,2,1); gr->Title("manual levels");
+  gr->Rotate(50,60);  gr->Box();  gr->Cont(v,a);
+
+  gr->SubPlot(2,2,2); gr->Title("'\\_' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Cont(a,"_");
+
+  gr->SubPlot(2,2,3,"");  gr->Title("'t' style");
+  gr->Box();  gr->Cont(a,"t");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{cont, Example of Cont()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ContF sample, ContD sample, Cont sample, 2D samples
+ at subsection ContF sample
+ at nav{}
+
+Function @ref{contf} draw filled contours.  You can select automatic (default) or manual levels for contours. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,v(5),a1(30,40,3); mgls_prepare2d(&a); v.a[0]=-0.5;
+  v.a[1]=-0.15; v.a[2]=0; v.a[3]=0.15;  v.a[4]=0.5;
+  gr->SubPlot(2,2,0); gr->Title("ContF plot (default)");
+  gr->Rotate(50,60);  gr->Box();  gr->ContF(a);
+
+  gr->SubPlot(2,2,1); gr->Title("manual levels");
+  gr->Rotate(50,60);  gr->Box();  gr->ContF(v,a);
+
+  gr->SubPlot(2,2,2); gr->Title("'\\_' style");
+  gr->Rotate(50,60);  gr->Box();  gr->ContF(a,"_");
+
+  gr->Fill(a1,"0.6*sin(2*pi*x+pi*(z+1)/2)*sin(3*pi*y+pi*z) +
+               0.4*cos(3*pi*(x*y)+pi*(z+1)^2/2)");
+  gr->SubPlot(2,2,3); gr->Title("several slices");
+  gr->Rotate(50,60);  gr->Box();  gr->ContF(a1);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{contf, Example of ContF()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ContD sample, ContV sample, ContF sample, 2D samples
+ at subsection ContD sample
+ at nav{}
+
+Function @ref{contd} is similar to @code{ContF} but with manual contour colors. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,v(5),a1(30,40,3); mgls_prepare2d(&a); v.a[0]=-0.5;
+  v.a[1]=-0.15; v.a[2]=0; v.a[3]=0.15;  v.a[4]=0.5;
+  gr->SubPlot(2,2,0); gr->Title("ContD plot (default)");
+  gr->Rotate(50,60);  gr->Box();  gr->ContD(a);
+
+  gr->SubPlot(2,2,1); gr->Title("manual levels");
+  gr->Rotate(50,60);  gr->Box();  gr->ContD(v,a);
+
+  gr->SubPlot(2,2,2); gr->Title("'\\_' style");
+  gr->Rotate(50,60);  gr->Box();  gr->ContD(a,"_");
+
+  gr->Fill(a1,"0.6*sin(2*pi*x+pi*(z+1)/2)*sin(3*pi*y+pi*z) + 0.4*cos(3*pi*(x*y)+pi*(z+1)^2/2)");
+  gr->SubPlot(2,2,3); gr->Title("several slices");
+  gr->Rotate(50,60);  gr->Box();  gr->ContD(a1);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{contd, Example of ContD()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ContV sample, Axial sample, ContD sample, 2D samples
+ at subsection ContV sample
+ at nav{}
+
+Function @ref{contv} draw vertical cylinders (belts) at contour lines. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,v(5); mgls_prepare2d(&a); v.a[0]=-0.5;
+  v.a[1]=-0.15; v.a[2]=0; v.a[3]=0.15;  v.a[4]=0.5;
+  gr->SubPlot(2,2,0); gr->Title("ContV plot (default)");
+  gr->Rotate(50,60);  gr->Box();  gr->ContV(a);
+
+  gr->SubPlot(2,2,1); gr->Title("manual levels");
+  gr->Rotate(50,60);  gr->Box();  gr->ContV(v,a);
+
+  gr->SubPlot(2,2,2); gr->Title("'\\_' style");
+  gr->Rotate(50,60);  gr->Box();  gr->ContV(a,"_");
+
+  gr->SubPlot(2,2,3); gr->Title("ContV and ContF");
+  gr->Rotate(50,60);  gr->Box();  gr->Light(true);
+  gr->ContV(a); gr->ContF(a); gr->Cont(a,"k");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{contv, Example of ContV()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Axial sample, Grad sample, ContV sample, 2D samples
+ at subsection Axial sample
+ at nav{}
+
+Function @ref{axial} draw surfaces of rotation for contour lines. You can draw wire surfaces (@samp{#} style) or ones rotated in other directions (@samp{x}, @samp{z} styles). The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->SubPlot(2,2,0); gr->Title("Axial plot (default)");
+  gr->Light(true);  gr->Alpha(true);  gr->Rotate(50,60);
+  gr->Box();  gr->Axial(a);
+
+  gr->SubPlot(2,2,1); gr->Title("'x' style;'.' style"); gr->Rotate(50,60);
+  gr->Box();  gr->Axial(a,"x.");
+
+  gr->SubPlot(2,2,2); gr->Title("'z' style"); gr->Rotate(50,60);
+  gr->Box();  gr->Axial(a,"z");
+
+  gr->SubPlot(2,2,3); gr->Title("'\\#' style"); gr->Rotate(50,60);
+  gr->Box();  gr->Axial(a,"#");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{axial, Example of Axial()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Grad sample, , Axial sample, 2D samples
+ at subsection Grad sample
+ at nav{}
+
+Function @ref{grad} draw gradient lines for matrix. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->SubPlot(1,1,0,""); gr->Title("Grad plot");
+  gr->Box();  gr->Grad(a);  gr->Dens(a,"{u8}w{q8}");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{grad, Example of Grad()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node 3D samples, Vector field samples, 2D samples, Examples
+ at section 3D samples
+ at nav{}
+
+This section is devoted to visualization of 3D data arrays. 3D means the data which depend on 3 indexes (parameters) like tensor a(i,j,k)=a(x(i),y(j),x(k)), i=1...n, j=1...m, k=1...l or in parametric form @{x(i,j,k),y(i,j,k),z(i,j,k),a(i,j,k)@}. Most of samples will use the same data for plotting. So, I put its initialization in separate function
+ at verbatim
+void mgls_prepare3d(mglData *a, mglData *b=0)
+{
+  register long i,j,k,n=61,m=50,l=40,i0;
+  if(a) a->Create(n,m,l);   if(b) b->Create(n,m,l);
+  mreal x,y,z;
+  for(i=0;i<n;i++)  for(j=0;j<m;j++)  for(k=0;k<l;k++)
+  {
+    x=2*i/(n-1.)-1; y=2*j/(m-1.)-1; z=2*k/(l-1.)-1; i0 = i+n*(j+m*k);
+    if(a) a->a[i0] = -2*(x*x + y*y + z*z*z*z - z*z - 0.1);
+    if(b) b->a[i0] = 1-2*tanh((x+y)*(x+y));
+  }
+}
+ at end verbatim
+or using C functions
+ at verbatim
+void mgls_prepare3d(HMDT a, HMDT b=0)
+{
+  register long i,j,k,n=61,m=50,l=40,i0;
+  if(a) mgl_data_create(a,n,m,l);
+  if(b) mgl_data_create(b,n,m,l);
+  mreal x,y,z;
+  for(i=0;i<n;i++)  for(j=0;j<m;j++)  for(k=0;k<l;k++)
+  {
+    x=2*i/(n-1.)-1; y=2*j/(m-1.)-1; z=2*k/(l-1.)-1; i0 = i+n*(j+m*k);
+    if(a) mgl_data_set_value(a, -2*(x*x + y*y + z*z*z*z - z*z - 0.1), i,j,k);
+    if(b) mgl_data_set_value(b, 1-2*tanh((x+y)*(x+y)), i,j,k);
+  }
+}
+ at end verbatim
+
+ at menu
+* Surf3 sample::
+* Surf3C sample::
+* Surf3A sample::
+* Surf3CA sample::
+* Cloud sample::
+* Dens3 sample::
+* Cont3 sample::
+* ContF3 sample::
+* Dens projection sample::
+* Cont projection sample::
+* ContF projection sample::
+* TriPlot and QuadPlot::
+* Dots sample::
+* Fractal sample::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Surf3 sample, Surf3C sample, , 3D samples
+ at subsection Surf3 sample
+ at nav{}
+
+Function @ref{surf3} is one of most suitable (for my opinion) functions to visualize 3D data. It draw the isosurface(s) -- surface(s) of constant amplitude (3D analogue of contour lines). You can draw wired isosurfaces if specify @samp{#} style. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData c;  mgls_prepare3d(&c);
+  gr->Light(true);    gr->Alpha(true);
+  gr->SubPlot(2,2,0); gr->Title("Surf3 plot (default)");
+  gr->Rotate(50,60);  gr->Box();  gr->Surf3(c);
+
+  gr->SubPlot(2,2,1); gr->Title("'\\#' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Surf3(c,"#");
+
+  gr->SubPlot(2,2,2); gr->Title("'.' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Surf3(c,".");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{surf3, Example of Surf3()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Surf3C sample, Surf3A sample, Surf3 sample, 3D samples
+ at subsection Surf3C sample
+ at nav{}
+
+Function @ref{surf3c} is similar to @ref{surf3} but its coloring is determined by another data. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData c,d;  mgls_prepare3d(&c,&d);
+  gr->Title("Surf3C plot"); gr->Rotate(50,60);
+  gr->Light(true);  gr->Alpha(true);
+  gr->Box();  gr->Surf3C(c,d);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{surf3c, Example of Surf3C()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Surf3A sample, Surf3CA sample, Surf3C sample, 3D samples
+ at subsection Surf3A sample
+ at nav{}
+
+Function @ref{surf3a} is similar to @ref{surf3} but its transparency is determined by another data. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData c,d;  mgls_prepare3d(&c,&d);
+  gr->Title("Surf3A plot"); gr->Rotate(50,60);
+  gr->Light(true);  gr->Alpha(true);
+  gr->Box();  gr->Surf3A(c,d);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{surf3a, Example of Surf3A()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Surf3CA sample, Cloud sample, Surf3A sample, 3D samples
+ at subsection Surf3CA sample
+ at nav{}
+
+Function @ref{surf3ca} is similar to @ref{surf3} but its color and transparency is determined by another data. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData c,d;  mgls_prepare3d(&c,&d);
+  gr->Title("Surf3CA plot"); gr->Rotate(50,60);
+  gr->Light(true);  gr->Alpha(true);
+  gr->Box();  gr->Surf3CA(c,d,c);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{surf3ca, Example of Surf3CA()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cloud sample, Dens3 sample, Surf3CA sample, 3D samples
+ at subsection Cloud sample
+ at nav{}
+
+Function @ref{cloud} draw cloud-like object which is less transparent for higher data values. Similar plot can be created using many (about 10-20) @code{Surf3A(a,a)} isosurfaces. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData c;  mgls_prepare3d(&c);
+  gr->SubPlot(2,2,0); gr->Title("Cloud plot");
+  gr->Rotate(50,60);  gr->Alpha(true);
+  gr->Box();  gr->Cloud(c,"wyrRk");
+
+  gr->SubPlot(2,2,1); gr->Title("'i' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Cloud(c,"iwyrRk");
+
+  gr->SubPlot(2,2,2); gr->Title("'.' style");
+  gr->Rotate(50,60);  gr->Box();  gr->Cloud(c,".wyrRk");
+
+  gr->SubPlot(2,2,3); gr->Title("meshnum 10");
+  gr->Rotate(50,60);  gr->Box();  gr->Cloud(c,"wyrRk","meshnum 10");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{cloud, Example of Cloud()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Dens3 sample, Cont3 sample, Cloud sample, 3D samples
+ at subsection Dens3 sample
+ at nav{}
+
+Function @ref{dens3} draw just usual density plot but at slices of 3D data. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData c;  mgls_prepare3d(&c);
+  gr->Title("Dens3 sample");  gr->Rotate(50,60);
+  gr->Alpha(true);  gr->SetAlphaDef(0.7);
+  gr->SetOrigin(0,0,0); gr->Axis("_xyz"); gr->Box();
+  gr->Dens3(c,"x"); gr->Dens3(c); gr->Dens3(c,"z");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{densa, Example of Dens3()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cont3 sample, ContF3 sample, Dens3 sample, 3D samples
+ at subsection Cont3 sample
+ at nav{}
+
+Function @ref{cont3} draw just usual contour lines but at slices of 3D data. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData c;  mgls_prepare3d(&c);
+  gr->Title("Cont3 sample");  gr->Rotate(50,60);
+  gr->Alpha(true);  gr->SetAlphaDef(0.7);
+  gr->SetOrigin(0,0,0); gr->Axis("_xyz"); gr->Box();
+  gr->Cont3(c,"x"); gr->Cont3(c); gr->Cont3(c,"z");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{conta, Example of Cont3()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ContF3 sample, Dens projection sample, Cont3 sample, 3D samples
+ at subsection ContF3 sample
+ at nav{}
+
+Function @ref{contf3} draw just usual filled contours but at slices of 3D data. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData c;  mgls_prepare3d(&c);
+  gr->Title("ContF3 sample");  gr->Rotate(50,60);
+  gr->Alpha(true);  gr->SetAlphaDef(0.7);
+  gr->SetOrigin(0,0,0); gr->Axis("_xyz"); gr->Box();
+  gr->ContF3(c,"x");  gr->ContF3(c);    gr->ContF3(c,"z");
+  gr->Cont3(c,"kx");  gr->Cont3(c,"k"); gr->Cont3(c,"kz");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{contfa, Example of ContF3()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Dens projection sample, Cont projection sample, ContF3 sample, 3D samples
+ at subsection Dens projection sample
+ at nav{}
+
+Functions @ref{densz}, @ref{densy}, @ref{densx} draw density plot on plane perpendicular to corresponding axis. One of possible application is drawing projections of 3D field. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData c;  mgls_prepare3d(&c);
+  gr->Title("Dens[XYZ] sample");  gr->Rotate(50,60);
+  gr->Box();  gr->DensX(c.Sum("x"),0,-1);
+  gr->DensY(c.Sum("y"),0,1);  gr->DensZ(c.Sum("z"),0,-1);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{dens_xyz, Example of DensX() DensY() DensZ()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Cont projection sample, ContF projection sample, Dens projection sample, 3D samples
+ at subsection Cont projection sample
+ at nav{}
+
+Functions @ref{contz}, @ref{conty}, @ref{contx} draw contour lines on plane perpendicular to corresponding axis. One of possible application is drawing projections of 3D field. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData c;  mgls_prepare3d(&c);
+  gr->Title("Cont[XYZ] sample");  gr->Rotate(50,60);
+  gr->Box();  gr->ContX(c.Sum("x"),"",-1);
+  gr->ContY(c.Sum("y"),"",1); gr->ContZ(c.Sum("z"),"",-1);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{cont_xyz, Example of ContX() ContY() ContZ()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ContF projection sample, TriPlot and QuadPlot, Cont projection sample, 3D samples
+ at subsection ContF projection sample
+ at nav{}
+
+Functions @ref{contfz}, @ref{contfy}, @ref{contfx} draw filled contours on plane perpendicular to corresponding axis. One of possible application is drawing projections of 3D field. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData c;  mgls_prepare3d(&c);
+  gr->Title("Cont[XYZ] sample");  gr->Rotate(50,60);
+  gr->Box();  gr->ContFX(c.Sum("x"),"",-1);
+  gr->ContFY(c.Sum("y"),"",1);  gr->ContFZ(c.Sum("z"),"",-1);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{contf_xyz, Example of ContFX() ContFY() ContFZ()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node TriPlot and QuadPlot, Dots sample, ContF projection sample, 3D samples
+ at subsection TriPlot and QuadPlot
+ at nav{}
+
+Function @ref{triplot} and @ref{quadplot} draw set of triangles (or quadrangles for @code{QuadPlot}) for irregular data arrays. Note, that you have to provide not only vertexes, but also the indexes of triangles or quadrangles. I.e. perform triangulation by some other library. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mreal q[] = {0,1,2,3, 4,5,6,7, 0,2,4,6, 1,3,5,7, 0,4,1,5, 2,6,3,7};
+  mreal xc[] = {-1,1,-1,1,-1,1,-1,1}, yc[] = {-1,-1,1,1,-1,-1,1,1}, zc[] = {-1,-1,-1,-1,1,1,1,1};
+  mglData qq(6,4,q), xx(8,xc), yy(8,yc), zz(8,zc);
+  gr->Light(true);  //gr->Alpha(true);
+  gr->SubPlot(2,2,0); gr->Title("QuadPlot sample"); gr->Rotate(50,60);
+  gr->QuadPlot(qq,xx,yy,zz,"yr");
+  gr->QuadPlot(qq,xx,yy,zz,"k#");
+  gr->SubPlot(2,2,2); gr->Title("QuadPlot coloring"); gr->Rotate(50,60);
+  gr->QuadPlot(qq,xx,yy,zz,yy,"yr");
+  gr->QuadPlot(qq,xx,yy,zz,"k#");
+
+  mreal t[] = {0,1,2, 0,1,3, 0,2,3, 1,2,3};
+  mreal xt[] = {-1,1,0,0}, yt[] = {-1,-1,1,0}, zt[] = {-1,-1,-1,1};
+  mglData tt(4,3,t), uu(4,xt), vv(4,yt), ww(4,zt);
+  gr->SubPlot(2,2,1); gr->Title("TriPlot sample");  gr->Rotate(50,60);
+  gr->TriPlot(tt,uu,vv,ww,"b");
+  gr->TriPlot(tt,uu,vv,ww,"k#");
+  gr->SubPlot(2,2,3); gr->Title("TriPlot coloring");  gr->Rotate(50,60);
+  gr->TriPlot(tt,uu,vv,ww,vv,"cb");
+  gr->TriPlot(tt,uu,vv,ww,"k#");
+  gr->TriCont(tt,uu,vv,ww,"B");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{triplot, Example of TriPlot() and QuadPlot()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Dots sample, Fractal sample, TriPlot and QuadPlot, 3D samples
+ at subsection Dots sample
+ at nav{}
+
+Function @ref{dots} is another way to draw irregular points. @code{Dots} use color scheme for coloring (see @ref{Color scheme}). The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  int i, n=2000;
+  mglData x(n),y(n),z(n),c(n);
+  for(i=0;i<n;i++)
+  {
+    mreal t=M_PI*(mgl_rnd()-0.5), f=2*M_PI*mgl_rnd();
+    x.a[i] = 0.9*cos(t)*cos(f);
+    y.a[i] = 0.9*cos(t)*sin(f);
+    z.a[i] = 0.6*sin(t);
+    c.a[i] = cos(2*t);
+  }
+  gr->SubPlot(2,2,0); gr->Title("Dots sample");  gr->Rotate(50,60);
+  gr->Box();  gr->Dots(x,y,z);
+  gr->Alpha(true);
+  gr->SubPlot(2,2,1); gr->Title("add transparency"); gr->Rotate(50,60);
+  gr->Box();  gr->Dots(x,y,z,c);
+  gr->SubPlot(2,2,2); gr->Title("add coloring"); gr->Rotate(50,60);
+  gr->Box();  gr->Dots(x,y,z,x,c);
+  gr->SubPlot(2,2,3); gr->Title("Only coloring");gr->Rotate(50,60);
+  gr->Box();  gr->Tens(x,y,z,x," .");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{dots, Example of Dots()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Fractal sample, , Dots sample, 3D samples
+ at subsection Fractal sample
+ at nav{}
+
+Commands @ref{ifs2d} and @ref{ifs3d} generate points for fractals using iterated function system in 2d and 3d cases correspondingly. The sample codes are:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData A;
+  A.SetList(35, 0.33,0.,0.,0.33,0.,0.,0.2, 0.33,0.,0.,0.33,0.67,0.,0.2, 0.33,0.,0.,0.33,0.33,0.33,0.2,
+                0.33,0.,0.,0.33,0.,0.67,0.2, 0.33,0.,0.,0.33,0.67,0.67,0.2);
+  A.Rearrange(7);
+  mglData f(mglIFS2d(A,100000));
+  gr->SubPlot(1,1,0,"<_");
+  gr->Title("IFS 2d sample");
+  gr->SetRanges(f.SubData(0), f.SubData(1));
+  gr->Axis(); gr->Plot(f.SubData(0), f.SubData(1),"r#o ","size 0.05");
+}
+ at end verbatim
+
+ at pfig{ifs2d, Example of IFS fractal (2d case).}
+
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData A;
+  A.SetList(52, 0.,0.,0.,0.,.18,0.,0.,0.,0.,0.,0.,0.,.01, .85,0.,0.,0.,.85,.1,0.,-0.1,0.85,0.,1.6,0.,.85,
+                .2,-.2,0.,.2,.2,0.,0.,0.,0.3,0.,0.8,0.,.07, -.2,.2,0.,.2,.2,0.,0.,0.,0.3,0.,0.8,0.,.07);
+  A.Rearrange(13);
+  mglData f(mglIFS3d(A,100000));
+  gr->Title("IFS 3d sample");
+  gr->SetRanges(f.SubData(0), f.SubData(1), f.SubData(2));
+  gr->Rotate(50,60);  gr->Axis(); gr->Box();
+  gr->Dots(f.SubData(0), f.SubData(1), f.SubData(2),"G#o","size 0.05");
+}
+ at end verbatim
+
+ at pfig{ifs3d, Example of IFS fractal (3d case).}
+
+Command @ref{flame2d} generate points for flame fractals in 2d case. The sample codes are:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData A, B(2,3,5);
+  A.SetList(35, 0.33,0.,0.,0.33,0.,0.,0.2, 0.33,0.,0.,0.33,0.67,0.,0.2, 0.33,0.,0.,0.33,0.33,0.33,0.2,
+      0.33,0.,0.,0.33,0.,0.67,0.2, 0.33,0.,0.,0.33,0.67,0.67,0.2);
+  A.Rearrange(7);
+  for(long i=0;i<2*3*5;i++)	B.a[i] = 0.3;
+  for(long i=0;i<5;i++)	B.a[2*3*i] = B.a[2*3*i+1*2] = B.a[2*3*i+2*2] = 3;
+  mglData f(mglFlame2d(A,B,1000000));
+  gr->SubPlot(1,1,0,"<_");
+  if(big!=3)	gr->Title("Flame2d sample");
+  gr->SetRanges(f.SubData(0), f.SubData(1));
+  gr->Axis();	gr->Box();
+  gr->Plot(f.SubData(0), f.SubData(1),"r#o ","size 0.05");
+}
+ at end verbatim
+
+ at pfig{flame2d, Example of flame fractal (2d case).}
+
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Vector field samples, Hints, 3D samples, Examples
+ at section Vector field samples
+ at nav{}
+
+Vector field visualization (especially in 3d case) is more or less complex task. MathGL provides 3 general types of plots: vector field itself (@code{Vect}), flow threads (@code{Flow}), and flow pipes with radius proportional to field amplitude (@code{Pipe}).
+
+However, the plot may look tangly -- there are too many overlapping lines. I may suggest 2 ways to solve this problem. The first one is to change @code{SetMeshNum} for decreasing the number of hachures. The second way is to use the flow thread chart @code{Flow}, or possible many flow thread from manual position (@code{FlowP}). Unfortunately, I don't know any other methods to visualize 3d vector field. If you know any, e-mail me and I shall add it to MathGL.
+
+Most of samples will use the same data for plotting. So, I put its initialization in separate function
+ at verbatim
+void mgls_prepare2v(mglData *a, mglData *b)
+{
+  register long i,j,n=20,m=30,i0;
+  if(a) a->Create(n,m);   if(b) b->Create(n,m);
+  mreal x,y;
+  for(i=0;i<n;i++)  for(j=0;j<m;j++)
+  {
+    x=i/(n-1.); y=j/(m-1.); i0 = i+n*j;
+    if(a) a->a[i0] = 0.6*sin(2*M_PI*x)*sin(3*M_PI*y)+0.4*cos(3*M_PI*x*y);
+    if(b) b->a[i0] = 0.6*cos(2*M_PI*x)*cos(3*M_PI*y)+0.4*cos(3*M_PI*x*y);
+  }
+}
+void mgls_prepare3v(mglData *ex, mglData *ey, mglData *ez)
+{
+  register long i,j,k,n=10,i0;
+  if(!ex || !ey || !ez) return;
+  ex->Create(n,n,n);  ey->Create(n,n,n);  ez->Create(n,n,n);
+  mreal x,y,z, r1,r2;
+  for(i=0;i<n;i++)  for(j=0;j<n;j++)  for(k=0;k<n;k++)
+  {
+    x=2*i/(n-1.)-1; y=2*j/(n-1.)-1; z=2*k/(n-1.)-1; i0 = i+n*(j+k*n);
+    r1 = pow(x*x+y*y+(z-0.3)*(z-0.3)+0.03,1.5);
+    r2 = pow(x*x+y*y+(z+0.3)*(z+0.3)+0.03,1.5);
+    ex->a[i0]=0.2*x/r1 - 0.2*x/r2;
+    ey->a[i0]=0.2*y/r1 - 0.2*y/r2;
+    ez->a[i0]=0.2*(z-0.3)/r1 - 0.2*(z+0.3)/r2;
+  }
+}
+ at end verbatim
+or using C functions
+ at verbatim
+void mgls_prepare2v(HMDT a, HMDT b)
+{
+  register long i,j,n=20,m=30,i0;
+  if(a) mgl_data_create(a,n,m,1);
+  if(b) mgl_data_create(b,n,m,1);
+  mreal x,y;
+  for(i=0;i<n;i++)  for(j=0;j<m;j++)
+  {
+    x=i/(n-1.); y=j/(m-1.); i0 = i+n*j;
+    if(a) mgl_data_set_value(a, 0.6*sin(2*M_PI*x)*sin(3*M_PI*y)+0.4*cos(3*M_PI*x*y), i,j,0);
+    if(b) mgl_data_set_value(b, 0.6*cos(2*M_PI*x)*cos(3*M_PI*y)+0.4*cos(3*M_PI*x*y), i,j,0);
+  }
+}
+void mgls_prepare3v(HMDT ex, HMDT ey, HMDT ez)
+{
+  register long i,j,k,n=10,i0;
+  if(!ex || !ey || !ez) return;
+  mgl_data_create(ex,n,n,n);
+  mgl_data_create(ey,n,n,n);
+  mgl_data_create(ez,n,n,n);
+  mreal x,y,z, r1,r2;
+  for(i=0;i<n;i++)  for(j=0;j<n;j++)  for(k=0;k<n;k++)
+  {
+    x=2*i/(n-1.)-1; y=2*j/(n-1.)-1; z=2*k/(n-1.)-1; i0 = i+n*(j+k*n);
+    r1 = pow(x*x+y*y+(z-0.3)*(z-0.3)+0.03,1.5);
+    r2 = pow(x*x+y*y+(z+0.3)*(z+0.3)+0.03,1.5);
+    mgl_data_set_value(ex, 0.2*x/r1 - 0.2*x/r2, i,j,k);
+    mgl_data_set_value(ey, 0.2*y/r1 - 0.2*y/r2, i,j,k);
+    mgl_data_set_value(ez, 0.2*(z-0.3)/r1 - 0.2*(z+0.3)/r2, i,j,k);
+  }
+}
+ at end verbatim
+
+ at menu
+* Vect sample::
+* Vect3 sample::
+* Traj sample::
+* Flow sample::
+* Pipe sample::
+* Dew sample::
+ at end menu
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Vect sample, Vect3 sample, , Vector field samples
+ at subsection Vect sample
+ at nav{}
+
+Function @ref{vect} is most standard way to visualize vector fields -- it draw a lot of arrows or hachures for each data cell. It have a lot of options which can be seen on the figure (and in the sample code). @code{Vect} use color scheme for coloring (see @ref{Color scheme}). The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,b;  mgls_prepare2v(&a,&b);
+  gr->SubPlot(3,2,0,""); gr->Title("Vect plot (default)");
+  gr->Box();  gr->Vect(a,b);
+
+  gr->SubPlot(3,2,1,"");  gr->Title("'.' style; '=' style");
+  gr->Box();  gr->Vect(a,b,"=.");
+
+  gr->SubPlot(3,2,2,"");  gr->Title("'f' style");
+  gr->Box();  gr->Vect(a,b,"f");
+
+  gr->SubPlot(3,2,3,"");  gr->Title("'>' style");
+  gr->Box();  gr->Vect(a,b,">");
+
+  gr->SubPlot(3,2,4,"");  gr->Title("'<' style");
+  gr->Box();  gr->Vect(a,b,"<");
+
+  mglData ex,ey,ez; mgls_prepare3v(&ex,&ey,&ez);
+  gr->SubPlot(3,2,5); gr->Title("3d variant");  gr->Rotate(50,60);
+  gr->Box();  gr->Vect(ex,ey,ez);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{vect, Example of Vect()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Vect3 sample, Traj sample, Vect sample, Vector field samples
+ at subsection Vect3 sample
+ at nav{}
+
+Function @ref{vect3} draw just usual vector field plot but at slices of 3D data. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData ex,ey,ez; mgls_prepare3v(&ex,&ey,&ez);
+  gr->SubPlot(2,1,0); gr->Title("Vect3 sample");    gr->SetOrigin(0,0,0);
+  gr->Rotate(50,60);    gr->Axis("_xyz");   gr->Box();
+  gr->Vect3(ex,ey,ez,"x");  gr->Vect3(ex,ey,ez);    gr->Vect3(ex,ey,ez,"z");
+
+  gr->SubPlot(2,1,1);   gr->Title("'f' style");
+  gr->Rotate(50,60);    gr->Axis("_xyz");   gr->Box();
+  gr->Vect3(ex,ey,ez,"fx"); gr->Vect3(ex,ey,ez,"f");gr->Vect3(ex,ey,ez,"fz");
+  gr->Grid3(ex,"Wx");   gr->Grid3(ex,"W");  gr->Grid3(ex,"Wz");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{vecta, Example of Vect3()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Traj sample, Flow sample, Vect3 sample, Vector field samples
+ at subsection Traj sample
+ at nav{}
+
+Function @ref{traj} is 1D analogue of @code{Vect}. It draw vectors from specified points. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData x,y,y1,y2;  mgls_prepare1d(&y,&y1,&y2,&x);
+  gr->SubPlot(1,1,0,""); gr->Title("Traj plot");
+  gr->Box();  gr->Plot(x,y);  gr->Traj(x,y,y1,y2);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{traj, Example of Traj()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Flow sample, Pipe sample, Traj sample, Vector field samples
+ at subsection Flow sample
+ at nav{}
+
+Function @ref{flow} is another standard way to visualize vector fields -- it draw lines (threads) which is tangent to local vector field direction. MathGL draw threads from edges of bounding box and from central slices. Sometimes it is not most appropriate variant -- you may want to use @code{FlowP} to specify manual position of threads. @code{Flow} use color scheme for coloring (see @ref{Color scheme}). At this warm color corresponds to normal flow (like attractor), cold one corresponds [...]
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,b;  mgls_prepare2v(&a,&b);
+  gr->SubPlot(2,2,0,""); gr->Title("Flow plot (default)");
+  gr->Box();  gr->Flow(a,b);
+
+  gr->SubPlot(2,2,1,"");  gr->Title("'v' style");
+  gr->Box();  gr->Flow(a,b,"v");
+
+  gr->SubPlot(2,2,2,"");  gr->Title("'\\#' style");
+  gr->Box();  gr->Flow(a,b,"#");
+
+  mglData ex,ey,ez; mgls_prepare3v(&ex,&ey,&ez);
+  gr->SubPlot(2,2,3); gr->Title("3d variant");  gr->Rotate(50,60);
+  gr->Box();  gr->Flow(ex,ey,ez);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{flow, Example of Flow()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Pipe sample, Dew sample, Flow sample, Vector field samples
+ at subsection Pipe sample
+ at nav{}
+
+Function @ref{pipe} is similar to @ref{flow} but draw pipes (tubes) which radius is proportional to the amplitude of vector field. @code{Pipe} use color scheme for coloring (see @ref{Color scheme}). At this warm color corresponds to normal flow (like attractor), cold one corresponds to inverse flow (like source). The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,b;  mgls_prepare2v(&a,&b);
+  gr->SubPlot(2,2,0,""); gr->Title("Pipe plot (default)");
+  gr->Light(true);  gr->Box();  gr->Pipe(a,b);
+
+  gr->SubPlot(2,2,1,"");  gr->Title("'i' style");
+  gr->Box();  gr->Pipe(a,b,"i");
+
+  gr->SubPlot(2,2,2,"");  gr->Title("'\\#' style");
+  gr->Box();  gr->Pipe(a,b,"#");
+
+  mglData ex,ey,ez; mgls_prepare3v(&ex,&ey,&ez);
+  gr->SubPlot(2,2,3); gr->Title("3d variant");  gr->Rotate(50,60);
+  gr->Box();  gr->Pipe(ex,ey,ez,"",0.1);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{pipe, Example of Pipe()}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Dew sample, , Pipe sample, Vector field samples
+ at subsection Dew sample
+ at nav{}
+
+Function @ref{dew} is similar to @code{Vect} but use drops instead of arrows. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,b;  mgls_prepare2v(&a,&b);
+  gr->SubPlot(1,1,0,""); gr->Title("Dew plot");
+  gr->Box();  gr->Light(true);  gr->Dew(a,b);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{dew, Example of Dew()}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Hints, FAQ, Vector field samples, Examples
+ at section Hints
+ at nav{}
+
+In this section I've included some small hints and advices for the improving of the quality of plots and for the demonstration of some non-trivial features of MathGL library. In contrast to previous examples I showed mostly the idea but not the whole drawing function.
+
+ at menu
+* ``Compound'' graphics::
+* Transparency and lighting::
+* Types of transparency::
+* Axis projection::
+* Adding fog::
+* Lighting sample::
+* Using primitives::
+* STFA sample::
+* Mapping visualization::
+* Data interpolation::
+* Making regular data::
+* Making histogram::
+* Nonlinear fitting hints::
+* PDE solving hints::
+* Drawing phase plain::
+* Using MGL parser::
+* Pulse properties::
+* Using options::
+* ``Templates''::
+* Stereo image::
+* Reduce memory usage::
+* Saving and scanning file::
+* Mixing bitmap and vector output::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ``Compound'' graphics, Transparency and lighting, , Hints
+ at subsection ``Compound'' graphics
+ at nav{}
+
+As I noted above, MathGL functions (except the special one, like Clf()) do  not erase the previous plotting but just add the new one. It allows one to draw ``compound'' plots easily. For example, popular Matlab command @code{surfc} can be emulated in MathGL by 2 calls:
+ at verbatim
+  Surf(a);
+  Cont(a, "_");     // draw contours at bottom
+ at end verbatim
+Here @var{a} is 2-dimensional data for the plotting, @code{-1} is the value of z-coordinate at which the contour should be plotted (at the bottom in this example). Analogously, one can draw density plot instead of contour lines and so on.
+
+Another nice plot is contour lines plotted directly on the surface:
+ at verbatim
+  Light(true);       // switch on light for the surface
+  Surf(a, "BbcyrR"); // select 'jet' colormap for the surface
+  Cont(a, "y");      // and yellow color for contours
+ at end verbatim
+The possible difficulties arise in black&white case, when the color of the surface can be close to the color of a contour line. In that case I may suggest the following code:
+ at verbatim
+  Light(true);   // switch on light for the surface
+  Surf(a, "kw"); // select 'gray' colormap for the surface
+  CAxis(-1,0);   // first draw for darker surface colors
+  Cont(a, "w");  // white contours
+  CAxis(0,1);    // now draw for brighter surface colors
+  Cont(a, "k");  // black contours
+  CAxis(-1,1);   // return color range to original state
+ at end verbatim
+The idea is to divide the color range on 2 parts (dark and bright) and to select the contrasting color for contour lines for each of part.
+
+Similarly, one can plot flow thread over density plot of vector field amplitude (this is another amusing plot from Matlab) and so on. The list of compound graphics can be prolonged but I hope that the general idea is clear.
+
+Just for illustration I put here following sample code:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,b,d;  mgls_prepare2v(&a,&b);  d = a;
+  for(int i=0;i<a.nx*a.ny;i++)  d.a[i] = hypot(a.a[i],b.a[i]);
+  mglData c;  mgls_prepare3d(&c);
+  mglData v(10);  v.Fill(-0.5,1);
+
+  gr->SubPlot(2,2,1,"");  gr->Title("Flow + Dens");
+  gr->Flow(a,b,"br"); gr->Dens(d,"BbcyrR"); gr->Box();
+
+  gr->SubPlot(2,2,0); gr->Title("Surf + Cont"); gr->Rotate(50,60);
+  gr->Light(true);  gr->Surf(a);  gr->Cont(a,"y");  gr->Box();
+
+  gr->SubPlot(2,2,2); gr->Title("Mesh + Cont"); gr->Rotate(50,60);
+  gr->Box();  gr->Mesh(a);  gr->Cont(a,"_");
+
+  gr->SubPlot(2,2,3); gr->Title("Surf3 + ContF3");gr->Rotate(50,60);
+  gr->Box();  gr->ContF3(v,c,"z",0);  gr->ContF3(v,c,"x");  gr->ContF3(v,c);
+  gr->SetCutBox(mglPoint(0,-1,-1), mglPoint(1,0,1.1));
+  gr->ContF3(v,c,"z",c.nz-1); gr->Surf3(-0.5,c);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{combined, Example of ``combined'' plots}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Transparency and lighting, Types of transparency, ``Compound'' graphics, Hints
+ at subsection Transparency and lighting
+ at nav{}
+
+Here I want to show how transparency and lighting both and separately change the look of a surface. So, there is code and picture for that:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->SubPlot(2,2,0); gr->Title("default"); gr->Rotate(50,60);
+  gr->Box();  gr->Surf(a);
+
+  gr->SubPlot(2,2,1); gr->Title("light on");  gr->Rotate(50,60);
+  gr->Box();  gr->Light(true);  gr->Surf(a);
+
+  gr->SubPlot(2,2,3); gr->Title("alpha on; light on");  gr->Rotate(50,60);
+  gr->Box();  gr->Alpha(true);  gr->Surf(a);
+
+  gr->SubPlot(2,2,2); gr->Title("alpha on");  gr->Rotate(50,60);
+  gr->Box();  gr->Light(false); gr->Surf(a);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{alpha, Example of transparency and lightings}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Types of transparency, Axis projection, Transparency and lighting, Hints
+ at subsection Types of transparency
+ at nav{}
+
+MathGL library has advanced features for setting and handling the surface transparency. The simplest way to add transparency is the using of function @ref{alpha}. As a result, all further surfaces (and isosurfaces, density plots and so on) become transparent. However, their  look can be additionally improved.
+
+The value of transparency can be different from surface to surface. To do it just use @code{SetAlphaDef} before the drawing of the surface, or use option @code{alpha} (see @ref{Command options}). If its value is close to 0 then the surface becomes more and more transparent. Contrary, if its value is close to 1 then the surface becomes practically non-transparent.
+
+Also you can change the way how the light goes through overlapped surfaces. The function @code{SetTranspType} defines it. By default the usual transparency is used (@samp{0}) -- surfaces below is less visible than the upper ones. A ``glass-like'' transparency (@samp{1}) has a different look -- each surface just decreases the background light (the surfaces are commutable in this case).
+
+A ``neon-like'' transparency (@samp{2}) has more interesting look. In this case a surface is the light source (like a lamp on the dark background) and just adds some intensity to the color. At this, the library sets automatically the black color for the background and changes the default line color to white.
+
+As example I shall show several plots for different types of transparency. The code is the same except the values of @code{SetTranspType} function:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->Alpha(true);  gr->Light(true);
+  mglData a;  mgls_prepare2d(&a);
+  gr->SetTranspType(0); gr->Clf();
+  gr->SubPlot(2,2,0); gr->Rotate(50,60);  gr->Surf(a);  gr->Box();
+  gr->SubPlot(2,2,1); gr->Rotate(50,60);  gr->Dens(a);  gr->Box();
+  gr->SubPlot(2,2,2); gr->Rotate(50,60);  gr->Cont(a);  gr->Box();
+  gr->SubPlot(2,2,3); gr->Rotate(50,60);  gr->Axial(a); gr->Box();
+  return 0;
+}
+ at end verbatim
+
+ at pfig{type0, Example of @code{SetTranspType(0)}.}
+ at pfig{type1, Example of @code{SetTranspType(1)}.}
+ at pfig{type2, Example of @code{SetTranspType(2)}.}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Axis projection, Adding fog, Types of transparency, Hints
+ at subsection Axis projection
+ at nav{}
+
+You can easily make 3D plot and draw its x-,y-,z-projections (like in CAD) by using @ref{ternary} function with arguments: 4 for Cartesian, 5 for Ternary and 6 for Quaternary coordinates. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SetRanges(0,1,0,1,0,1);
+  mglData x(50),y(50),z(50),rx(10),ry(10), a(20,30);
+  a.Modify("30*x*y*(1-x-y)^2*(x+y<1)");
+  x.Modify("0.25*(1+cos(2*pi*x))");
+  y.Modify("0.25*(1+sin(2*pi*x))");
+  rx.Modify("rnd"); ry.Modify("(1-v)*rnd",rx);
+  z.Modify("x");
+
+  gr->Title("Projection sample");
+  gr->Ternary(4);
+  gr->Rotate(50,60);      gr->Light(true);
+  gr->Plot(x,y,z,"r2");   gr->Surf(a,"#");
+  gr->Axis(); gr->Grid(); gr->Box();
+  gr->Label('x',"X",1);   gr->Label('y',"Y",1);   gr->Label('z',"Z",1);
+}
+ at end verbatim
+
+ at pfig{projection, Example of axis projections}
+ at pfig{projection5, Example of ternary axis projections}
+ at c @pfig{projection6, Example of quaternary axis projections}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Adding fog, Lighting sample, Axis projection, Hints
+ at subsection Adding fog
+ at nav{}
+
+MathGL can add a fog to the image. Its switching on is rather simple -- just use @ref{fog} function. There is the only feature -- fog is applied for whole image. Not to particular subplot. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->Title("Fog sample");
+  gr->Light(true);  gr->Rotate(50,60);  gr->Fog(1); gr->Box();
+  gr->Surf(a);  gr->Cont(a,"y");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{fog, Example of @code{Fog()}.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Lighting sample, Using primitives, Adding fog, Hints
+ at subsection Lighting sample
+ at nav{}
+
+In contrast to the most of other programs, MathGL supports several (up to 10) light sources. Moreover, the color each of them can be different: white (this is usual), yellow, red, cyan, green and so on. The use of several light sources may be interesting for the highlighting of some peculiarities of the plot or just to make an amusing picture. Note, each light source can be switched on/off individually. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->Title("Several light sources");
+  gr->Rotate(50,60);  gr->Light(true);
+  gr->AddLight(1,mglPoint(0,1,0),'c');
+  gr->AddLight(2,mglPoint(1,0,0),'y');
+  gr->AddLight(3,mglPoint(0,-1,0),'m');
+  gr->Box();  gr->Surf(a,"h");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{several_light, Example of several light sources.}
+
+Additionally, you can use local light sources and set to use @ref{diffuse} reflection instead of specular one (by default) or both kinds. Note, I use @ref{attachlight} command to keep light settings relative to subplot.
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->Light(true);  gr->AttachLight(true);
+  gr->SubPlot(2,2,0); gr->Title("Default"); gr->Rotate(50,60);
+  gr->Line(mglPoint(-1,-0.7,1.7),mglPoint(-1,-0.7,0.7),"BA"); gr->Box();  gr->Surf(a);
+
+  gr->SubPlot(2,2,1); gr->Title("Local");   gr->Rotate(50,60);
+  gr->AddLight(0,mglPoint(1,0,1),mglPoint(-2,-1,-1));
+  gr->Line(mglPoint(1,0,1),mglPoint(-1,-1,0),"BAO");  gr->Box();  gr->Surf(a);
+
+  gr->SubPlot(2,2,2); gr->Title("no diffuse"); gr->Rotate(50,60);
+  gr->SetDiffuse(0);
+  gr->Line(mglPoint(1,0,1),mglPoint(-1,-1,0),"BAO");  gr->Box();  gr->Surf(a);
+
+  gr->SubPlot(2,2,3); gr->Title("diffusive only");  gr->Rotate(50,60);
+  gr->SetDiffuse(0.5);
+  gr->AddLight(0,mglPoint(1,0,1),mglPoint(-2,-1,-1),'w',0);
+  gr->Line(mglPoint(1,0,1),mglPoint(-1,-1,0),"BAO");  gr->Box();  gr->Surf(a);
+}
+ at end verbatim
+
+ at pfig{light, Example of different types of lighting.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Using primitives, STFA sample, Lighting sample, Hints
+ at subsection Using primitives
+ at nav{}
+
+MathGL provide a set of functions for drawing primitives (see @ref{Primitives}). Primitives are low level object, which used by most of plotting functions. Picture below demonstrate some of commonly used primitives.
+
+ at pfig{primitives, Primitives in MathGL.}
+
+Generally, you can create arbitrary new kind of plot using primitives. For example, MathGL don't provide any special functions for drawing molecules. However, you can do it using only one type of primitives @ref{drop}. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->Alpha(true);  gr->Light(true);
+
+  gr->SubPlot(2,2,0,"");  gr->Title("Methane, CH_4");
+  gr->StartGroup("Methane");
+  gr->Rotate(60,120);
+  gr->Sphere(mglPoint(0,0,0),0.25,"k");
+  gr->Drop(mglPoint(0,0,0),mglPoint(0,0,1),0.35,"h",1,2);
+  gr->Sphere(mglPoint(0,0,0.7),0.25,"g");
+  gr->Drop(mglPoint(0,0,0),mglPoint(-0.94,0,-0.33),0.35,"h",1,2);
+  gr->Sphere(mglPoint(-0.66,0,-0.23),0.25,"g");
+  gr->Drop(mglPoint(0,0,0),mglPoint(0.47,0.82,-0.33),0.35,"h",1,2);
+  gr->Sphere(mglPoint(0.33,0.57,-0.23),0.25,"g");
+  gr->Drop(mglPoint(0,0,0),mglPoint(0.47,-0.82,-0.33),0.35,"h",1,2);
+  gr->Sphere(mglPoint(0.33,-0.57,-0.23),0.25,"g");
+  gr->EndGroup();
+
+  gr->SubPlot(2,2,1,"");  gr->Title("Water, H_{2}O");
+  gr->StartGroup("Water");
+  gr->Rotate(60,100);
+  gr->StartGroup("Water_O");
+  gr->Sphere(mglPoint(0,0,0),0.25,"r");
+  gr->EndGroup();
+  gr->StartGroup("Water_Bond_1");
+  gr->Drop(mglPoint(0,0,0),mglPoint(0.3,0.5,0),0.3,"m",1,2);
+  gr->EndGroup();
+  gr->StartGroup("Water_H_1");
+  gr->Sphere(mglPoint(0.3,0.5,0),0.25,"g");
+  gr->EndGroup();
+  gr->StartGroup("Water_Bond_2");
+  gr->Drop(mglPoint(0,0,0),mglPoint(0.3,-0.5,0),0.3,"m",1,2);
+  gr->EndGroup();
+  gr->StartGroup("Water_H_2");
+  gr->Sphere(mglPoint(0.3,-0.5,0),0.25,"g");
+  gr->EndGroup();
+  gr->EndGroup();
+
+  gr->SubPlot(2,2,2,"");  gr->Title("Oxygen, O_2");
+  gr->StartGroup("Oxygen");
+  gr->Rotate(60,120);
+  gr->Drop(mglPoint(0,0.5,0),mglPoint(0,-0.3,0),0.3,"m",1,2);
+  gr->Sphere(mglPoint(0,0.5,0),0.25,"r");
+  gr->Drop(mglPoint(0,-0.5,0),mglPoint(0,0.3,0),0.3,"m",1,2);
+  gr->Sphere(mglPoint(0,-0.5,0),0.25,"r");
+  gr->EndGroup();
+
+  gr->SubPlot(2,2,3,"");  gr->Title("Ammonia, NH_3");
+  gr->StartGroup("Ammonia");
+  gr->Rotate(60,120);
+  gr->Sphere(mglPoint(0,0,0),0.25,"b");
+  gr->Drop(mglPoint(0,0,0),mglPoint(0.33,0.57,0),0.32,"n",1,2);
+  gr->Sphere(mglPoint(0.33,0.57,0),0.25,"g");
+  gr->Drop(mglPoint(0,0,0),mglPoint(0.33,-0.57,0),0.32,"n",1,2);
+  gr->Sphere(mglPoint(0.33,-0.57,0),0.25,"g");
+  gr->Drop(mglPoint(0,0,0),mglPoint(-0.65,0,0),0.32,"n",1,2);
+  gr->Sphere(mglPoint(-0.65,0,0),0.25,"g");
+  gr->EndGroup();
+  return 0;
+}
+ at end verbatim
+
+ at pfig{molecule, Example of molecules drawing.}
+
+Moreover, some of special plots can be more easily produced by primitives rather than by specialized function. For example, Venn diagram can be produced by @code{Error} plot:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  double xx[3]={-0.3,0,0.3}, yy[3]={0.3,-0.3,0.3}, ee[3]={0.7,0.7,0.7};
+  mglData x(3,xx), y(3,yy), e(3,ee);
+  gr->Title("Venn-like diagram"); gr->Alpha(true);
+  gr->Error(x,y,e,e,"!rgb@#o");
+  return 0;
+}
+ at end verbatim
+You see that you have to specify and fill 3 data arrays. The same picture can be produced by just 3 calls of @ref{circle} function:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->Title("Venn-like diagram"); gr->Alpha(true);
+  gr->Circle(mglPoint(-0.3,0.3),0.7,"rr@");
+  gr->Circle(mglPoint(0,-0.3),0.7,"gg@");
+  gr->Circle(mglPoint( 0.3,0.3),0.7,"bb@");
+  return 0;
+}
+ at end verbatim
+Of course, the first variant is more suitable if you need to plot a lot of circles. But for few ones the usage of primitives looks easy.
+
+ at pfig{venn, Example of Venn diagram.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node STFA sample, Mapping visualization, Using primitives, Hints
+ at subsection STFA sample
+ at nav{}
+
+Short-time Fourier Analysis (@ref{stfa}) is one of informative method for analyzing long rapidly oscillating 1D data arrays. It is used to determine the sinusoidal frequency and phase content of local sections of a signal as it changes over time.
+
+MathGL can find and draw STFA result. Just to show this feature I give following sample. Initial data arrays is 1D arrays with step-like frequency. Exactly this you can see at bottom on the STFA plot. The sample code is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a(2000), b(2000);
+  gr->Fill(a,"cos(50*pi*x)*(x<-.5)+cos(100*pi*x)*(x<0)*(x>-.5)+\
+  cos(200*pi*x)*(x<.5)*(x>0)+cos(400*pi*x)*(x>.5)");
+  gr->SubPlot(1, 2, 0,"<_");  gr->Title("Initial signal");
+  gr->Plot(a);
+  gr->Axis();
+  gr->Label('x', "\\i t");
+
+  gr->SubPlot(1, 2, 1,"<_");  gr->Title("STFA plot");
+  gr->STFA(a, b, 64);
+  gr->Axis();
+  gr->Label('x', "\\i t");
+  gr->Label('y', "\\omega", 0);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{stfa, Example of STFA().}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Mapping visualization, Data interpolation, STFA sample, Hints
+ at subsection Mapping visualization
+ at nav{}
+
+Sometime ago I worked with mapping and have a question about its visualization. Let me remember you that mapping is some transformation rule for one set of number to another one. The 1d mapping is just an ordinary function -- it takes a number and transforms it to another one. The 2d mapping (which I used) is a pair of functions which take 2 numbers and transform them to another 2 ones. Except general plots (like @ref{surfc}, @ref{surfa}) there is a special plot -- Arnold diagram. It sho [...]
+
+I tried to make such plot in @ref{map}. It shows the set of points or set of faces, which final position is the result of mapping. At this, the color gives information about their initial position and the height describes Jacobian value of the transformation. Unfortunately, it looks good only for the simplest mapping but for the  real multivalent quasi-chaotic mapping it produces a confusion. So, use it if you like :).
+
+The sample code for mapping visualization is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a(50, 40), b(50, 40);
+  gr->Puts(mglPoint(0, 0), "\\to", ":C", -1.4);
+  gr->SetRanges(-1,1,-1,1,-2,2);
+
+  gr->SubPlot(2, 1, 0);
+  gr->Fill(a,"x");  gr->Fill(b,"y");
+  gr->Puts(mglPoint(0, 1.1), "\\{x, y\\}", ":C", -2);   gr->Box();
+  gr->Map(a, b, "brgk");
+
+  gr->SubPlot(2, 1, 1);
+  gr->Fill(a,"(x^3+y^3)/2");  gr->Fill(b,"(x-y)/2");
+  gr->Puts(mglPoint(0, 1.1), "\\{\\frac{x^3+y^3}{2}, \\frac{x-y}{2}\\}", ":C", -2);
+  gr->Box();
+  gr->Map(a, b, "brgk");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{map, Example of Map().}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Data interpolation, Making regular data, Mapping visualization, Hints
+ at subsection Data interpolation
+ at nav{}
+
+There are many functions to get interpolated values of a data array. Basically all of them can be divided by 3 categories:
+ at enumerate
+ at item functions which return single value at given point (see @ref{Interpolation} and @code{mglGSpline()} in @ref{Global functions});
+ at item functions @ref{subdata} and @ref{evaluate} for indirect access to data elements;
+ at item functions @ref{refill}, @ref{gspline} and @ref{datagrid} which fill regular (rectangular) data array by interpolated values.
+ at end enumerate
+
+The usage of first category is rather straightforward and don't need any special comments.
+
+There is difference in indirect access functions. Function @ref{subdata} use use step-like interpolation to handle correctly single @code{nan} values in the data array. Contrary, function @ref{evaluate} use local spline interpolation, which give smoother output but spread @code{nan} values. So, @ref{subdata} should be used for specific data elements (for example, for given column), and @ref{evaluate} should be used for distributed elements (i.e. consider data array as some field). Follow [...]
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(1,1,0,"");  gr->Title("SubData vs Evaluate");
+  mglData in(9), arg(99), e, s;
+  gr->Fill(in,"x^3/1.1"); gr->Fill(arg,"4*x+4");
+  gr->Plot(in,"ko ");     gr->Box();
+  e = in.Evaluate(arg,false); gr->Plot(e,"b.","legend 'Evaluate'");
+  s = in.SubData(arg);    gr->Plot(s,"r.","legend 'SubData'");
+  gr->Legend(2);
+}
+ at end verbatim
+
+ at pfig{indirect, Example of indirect data access.}
+
+Example of @ref{datagrid} usage is done in @ref{Making regular data}. Here I want to show the peculiarities of @ref{refill} and @ref{gspline} functions. Both functions require argument(s) which provide coordinates of the data values, and return rectangular data array which equidistantly distributed in axis range. So, in opposite to @ref{evaluate} function, @ref{refill} and @ref{gspline} can interpolate non-equidistantly distributed data. At this both functions @ref{refill} and @ref{gspli [...]
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData x(10), y(10), r(100);
+  x.Modify("0.5+rnd");  x.CumSum("x");  x.Norm(-1,1);
+  y.Modify("sin(pi*v)/1.5",x);
+  gr->SubPlot(2,2,0,"<_");  gr->Title("Refill sample");
+  gr->Axis();  gr->Box(); gr->Plot(x,y,"o ");
+  gr->Refill(r,x,y);  // or you can use r.Refill(x,y,-1,1);
+  gr->Plot(r,"r");  gr->FPlot("sin(pi*x)/1.5","B:");
+  gr->SubPlot(2,2,1,"<_");gr->Title("Global spline");
+  gr->Axis();  gr->Box(); gr->Plot(x,y,"o ");
+  r.RefillGS(x,y,-1,1);   gr->Plot(r,"r");
+  gr->FPlot("sin(pi*x)/1.5","B:");
+
+  gr->Alpha(true);  gr->Light(true);
+  mglData z(10,10), xx(10,10), yy(10,10), rr(100,100);
+  y.Modify("0.5+rnd");  y.CumSum("x");  y.Norm(-1,1);
+  for(int i=0;i<10;i++) for(int j=0;j<10;j++)
+    z.a[i+10*j] = sin(M_PI*x.a[i]*y.a[j])/1.5;
+  gr->SubPlot(2,2,2); gr->Title("2d regular");  gr->Rotate(40,60);
+  gr->Axis();  gr->Box(); gr->Mesh(x,y,z,"k");
+  gr->Refill(rr,x,y,z); gr->Surf(rr);
+
+  gr->Fill(xx,"(x+1)/2*cos(y*pi/2-1)");
+  gr->Fill(yy,"(x+1)/2*sin(y*pi/2-1)");
+  for(int i=0;i<10*10;i++)
+    z.a[i] = sin(M_PI*xx.a[i]*yy.a[i])/1.5;
+  gr->SubPlot(2,2,3); gr->Title("2d non-regular");  gr->Rotate(40,60);
+  gr->Axis();  gr->Box();  gr->Plot(xx,yy,z,"ko ");
+  gr->Refill(rr,xx,yy,z);  gr->Surf(rr);
+}
+ at end verbatim
+
+ at pfig{refill, Example of non-equidistant data interpolation.}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Making regular data, Making histogram, Data interpolation, Hints
+ at subsection Making regular data
+ at nav{}
+
+Sometimes, one have only unregular data, like as data on triangular grids, or experimental results and so on. Such kind of data cannot be used as simple as regular data (like matrices). Only few functions, like @ref{dots}, can handle unregular data as is.
+
+However, one can use built in triangulation functions for interpolating unregular data points to a regular data grids. There are 2 ways. First way, one can use @ref{triangulation} function to obtain list of vertexes for triangles. Later this list can be used in functions like @ref{triplot} or @ref{tricont}. Second way consist in usage of @ref{datagrid} function, which fill regular data grid by interpolated values, assuming that coordinates of the data grid is equidistantly distributed in [...]
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData x(100), y(100), z(100);
+  gr->Fill(x,"2*rnd-1"); gr->Fill(y,"2*rnd-1"); gr->Fill(z,"v^2-w^2",x,y);
+  // first way - plot triangular surface for points
+  mglData d = mglTriangulation(x,y);
+  gr->Title("Triangulation");
+  gr->Rotate(40,60);	gr->Box();	gr->Light(true);
+  gr->TriPlot(d,x,y,z);	gr->TriPlot(d,x,y,z,"#k");
+  // second way - make regular data and plot it
+  mglData g(30,30);
+  gr->DataGrid(g,x,y,z);	gr->Mesh(g,"m");
+}
+ at end verbatim
+
+ at pfig{triangulation, Example of triangulation.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Making histogram, Nonlinear fitting hints, Making regular data, Hints
+ at subsection Making histogram
+ at nav{}
+
+Using the @ref{hist} function(s) for making regular distributions is one of useful fast methods to process and plot irregular data. @code{Hist} can be used to find some momentum of set of points by specifying weight function. It is possible to create not only 1D distributions but also 2D and 3D ones. Below I place the simplest sample code which demonstrate @ref{hist} usage:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData x(10000), y(10000), z(10000);  gr->Fill(x,"2*rnd-1");
+  gr->Fill(y,"2*rnd-1"); gr->Fill(z,"exp(-6*(v^2+w^2))",x,y);
+  mglData xx=gr->Hist(x,z), yy=gr->Hist(y,z);	xx.Norm(0,1);
+  yy.Norm(0,1);
+  gr->MultiPlot(3,3,3,2,2,"");   gr->SetRanges(-1,1,-1,1,0,1);
+  gr->Box();  gr->Dots(x,y,z,"wyrRk");
+  gr->MultiPlot(3,3,0,2,1,"");   gr->SetRanges(-1,1,0,1);
+  gr->Box();  gr->Bars(xx);
+  gr->MultiPlot(3,3,5,1,2,"");   gr->SetRanges(0,1,-1,1);
+  gr->Box();  gr->Barh(yy);
+  gr->SubPlot(3,3,2);
+  gr->Puts(mglPoint(0.5,0.5),"Hist and\nMultiPlot\nsample","a",-6);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{hist, Example of Hist().}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Nonlinear fitting hints, PDE solving hints, Making histogram, Hints
+ at subsection Nonlinear fitting hints
+ at nav{}
+
+Nonlinear fitting is rather simple. All that you need is the data to fit, the approximation formula and the list of coefficients to fit (better with its initial guess values). Let me demonstrate it on the following simple example. First, let us use sin function with some random noise:
+ at verbatim
+  mglData dat(100), in(100); //data to be fitted and ideal data
+  gr->Fill(dat,"0.4*rnd+0.1+sin(2*pi*x)");
+  gr->Fill(in,"0.3+sin(2*pi*x)");
+ at end verbatim
+and plot it to see that data we will fit
+ at verbatim
+  gr->Title("Fitting sample");
+  gr->SetRange('y',-2,2); gr->Box();  gr->Plot(dat, "k. ");
+  gr->Axis(); gr->Plot(in, "b");
+  gr->Puts(mglPoint(0, 2.2), "initial: y = 0.3+sin(2\\pi x)", "b");
+ at end verbatim
+
+The next step is the fitting itself. For that let me specify an initial values @var{ini} for coefficients @samp{abc} and do the fitting for approximation formula @samp{a+b*sin(c*x)}
+ at verbatim
+  mreal ini[3] = {1,1,3};
+  mglData Ini(3,ini);
+  mglData res = gr->Fit(dat, "a+b*sin(c*x)", "abc", Ini);
+ at end verbatim
+Now display it
+ at verbatim
+  gr->Plot(res, "r");
+  gr->Puts(mglPoint(-0.9, -1.3), "fitted:", "r:L");
+  gr->PutsFit(mglPoint(0, -1.8), "y = ", "r");
+ at end verbatim
+
+NOTE! the fitting results may have strong dependence on initial values for coefficients due to algorithm features. The problem is that in general case there are several local "optimums" for coefficients and the program returns only first found one! There are no guaranties that it will be the best. Try for example to set @code{ini[3] = @{0, 0, 0@}} in the code above.
+
+The full sample code for nonlinear fitting is:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData dat(100), in(100);
+  gr->Fill(dat,"0.4*rnd+0.1+sin(2*pi*x)");
+  gr->Fill(in,"0.3+sin(2*pi*x)");
+  mreal ini[3] = {1,1,3};
+  mglData Ini(3,ini);
+
+  mglData res = gr->Fit(dat, "a+b*sin(c*x)", "abc", Ini);
+
+  gr->Title("Fitting sample");
+  gr->SetRange('y',-2,2); gr->Box();  gr->Plot(dat, "k. ");
+  gr->Axis();   gr->Plot(res, "r"); gr->Plot(in, "b");
+  gr->Puts(mglPoint(-0.9, -1.3), "fitted:", "r:L");
+  gr->PutsFit(mglPoint(0, -1.8), "y = ", "r");
+  gr->Puts(mglPoint(0, 2.2), "initial: y = 0.3+sin(2\\pi x)", "b");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{fit, Example of nonlinear fitting.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node PDE solving hints, Drawing phase plain, Nonlinear fitting hints, Hints
+ at subsection PDE solving hints
+ at nav{}
+
+Solving of Partial Differential Equations (PDE, including beam tracing) and ray tracing (or finding particle trajectory) are more or less common task. So, MathGL have several functions for that. There are @ref{ray} for ray tracing, @ref{pde} for PDE solving, @ref{qo2d} for beam tracing in 2D case (see @ref{Global functions}). Note, that these functions take ``Hamiltonian'' or equations as string values. And I don't plan now to allow one to use user-defined functions. There are 2 reasons: [...]
+
+The ray tracing can be done by @ref{ray} function. Really ray tracing equation is Hamiltonian equation for 3D space. So, the function can be also used for finding a particle trajectory (i.e. solve Hamiltonian ODE) for 1D, 2D or 3D cases. The function have a set of arguments. First of all, it is Hamiltonian which defined the media (or the equation) you are planning to use. The Hamiltonian is defined by string which may depend on coordinates @samp{x}, @samp{y}, @samp{z}, time @samp{t} (for [...]
+ at verbatim
+  const char *ham = "p^2+q^2-x-1+i*0.5*(y+x)*(y>-x)";
+  mglData r = mglRay(ham, mglPoint(-0.7, -1), mglPoint(0, 0.5), 0.02, 2);
+ at end verbatim
+This example calculate the reflection from linear layer (media with Hamiltonian @samp{p^2+q^2-x-1}=@math{p_x^2+p_y^2-x-1}). This is parabolic curve. The resulting array have 7 columns which contain data for @{x,y,z,p,q,v,t@}.
+
+The solution of PDE is a bit more complicated. As previous you have to specify the equation as pseudo-differential operator @math{\hat H(x, \nabla)} which is called sometime as ``Hamiltonian'' (for example, in beam tracing). As previously, it is defined by string which may depend on coordinates @samp{x}, @samp{y}, @samp{z} (but not time!), momentums @samp{p}=@math{(d/dx)/i k_0}, @samp{q}=@math{(d/dy)/i k_0} and field amplitude @samp{u}=@math{|u|}. The evolutionary coordinate is @samp{z}  [...]
+
+Next step is specifying the initial conditions at @samp{z} equal to minimal z-axis value. The function need 2 arrays for real and for imaginary part. Note, that coordinates x,y,z are supposed to be in specified axis range. So, the data arrays should have corresponding scales. Finally, you may set the integration step and parameter k0=@math{k_0}. Also keep in mind, that internally the 2 times large box is used (for suppressing numerical reflection from boundaries) and the equation should  [...]
+
+Final comment is concerning the possible form of pseudo-differential operator @math{H}. At this moment, simplified form of operator @math{H} is supported -- all ``mixed'' terms (like @samp{x*p}->x*d/dx) are excluded. For example, in 2D case this operator is effectively @math{H = f(p,z) + g(x,z,u)}. However commutable combinations (like @samp{x*q}->x*d/dy) are allowed for 3D case.
+
+So, for example let solve the equation for beam deflected from linear layer and absorbed later. The operator will have the form @samp{"p^2+q^2-x-1+i*0.5*(z+x)*(z>-x)"} that correspond to equation @math{1/ik_0 * du/dz + d^2 u/dx^2 + d^2 u/dy^2 + x * u + i (x+z)/2 * u = 0}. This is typical equation for Electron Cyclotron (EC) absorption in magnetized plasmas. For initial conditions let me select the beam with plane phase front @math{exp(-48*(x+0.7)^2)}. The corresponding code looks like this:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a,re(128),im(128);
+  gr->Fill(re,"exp(-48*(x+0.7)^2)");
+  a = gr->PDE("p^2+q^2-x-1+i*0.5*(z+x)*(z>-x)", re, im, 0.01, 30);
+  a.Transpose("yxz");
+  gr->SubPlot(1,1,0,"<_"); gr->Title("PDE solver");
+  gr->SetRange('c',0,1);  gr->Dens(a,"wyrRk");
+  gr->Axis(); gr->Label('x', "\\i x");  gr->Label('y', "\\i z");
+  gr->FPlot("-x", "k|");
+  gr->Puts(mglPoint(0, 0.85), "absorption: (x+z)/2 for x+z>0");
+  gr->Puts(mglPoint(0,1.1),"Equation: ik_0\\partial_zu + \\Delta u + x\\cdot u + i \\frac{x+z}{2}\\cdot u = 0");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{pde, Example of PDE solving.}
+
+The next example is example of beam tracing. Beam tracing equation is special kind of PDE equation written in coordinates accompanied to a ray. Generally this is the same parameters and limitation as for PDE solving but the coordinates are defined by the ray and by parameter of grid width @var{w} in direction transverse the ray. So, you don't need to specify the range of coordinates. @strong{BUT} there is limitation. The accompanied coordinates are well defined only for smooth enough ray [...]
+
+You may use following code for obtaining the same solution as in previous example:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData r, xx, yy, a, im(128), re(128);
+  const char *ham = "p^2+q^2-x-1+i*0.5*(y+x)*(y>-x)";
+  r = mglRay(ham, mglPoint(-0.7, -1), mglPoint(0, 0.5), 0.02, 2);
+  gr->SubPlot(1,1,0,"<_"); gr->Title("Beam and ray tracing");
+  gr->Plot(r.SubData(0), r.SubData(1), "k");
+  gr->Axis(); gr->Label('x', "\\i x");  gr->Label('y', "\\i z");
+
+  // now start beam tracing
+  gr->Fill(re,"exp(-48*x^2)");
+  a = mglQO2d(ham, re, im, r, xx, yy, 1, 30);
+  gr->SetRange('c',0, 1);
+  gr->Dens(xx, yy, a, "wyrRk");
+  gr->FPlot("-x", "k|");
+  gr->Puts(mglPoint(0, 0.85), "absorption: (x+y)/2 for x+y>0");
+  gr->Puts(mglPoint(0.7, -0.05), "central ray");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{qo2d, Example of beam tracing.}
+
+Note, the @ref{pde} is fast enough and suitable for many cases routine. However, there is situations then media have both together: strong spatial dispersion and spatial inhomogeneity. In this, case the @ref{pde} will produce incorrect result and you need to use advanced PDE solver @ref{apde}. For example, a wave beam, propagated in plasma, described by Hamiltonian @math{exp(-x^2-p^2)}, will have different solution for using of simplification and advanced PDE solver:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SetRanges(-1,1,0,2,0,2);
+  mglData ar(256), ai(256);	gr->Fill(ar,"exp(-2*x^2)");
+
+  mglData res1(gr->APDE("exp(-x^2-p^2)",ar,ai,0.01));	res1.Transpose();
+  gr->SubPlot(1,2,0,"_");	gr->Title("Advanced PDE solver");
+  gr->SetRanges(0,2,-1,1);	gr->SetRange('c',res1);
+  gr->Dens(res1);	gr->Axis();	gr->Box();
+  gr->Label('x',"\\i z");	gr->Label('y',"\\i x");
+  gr->Puts(mglPoint(-0.5,0.2),"i\\partial_z\\i u = exp(-\\i x^2+\\partial_x^2)[\\i u]","y");
+
+  mglData res2(gr->PDE("exp(-x^2-p^2)",ar,ai,0.01));
+  gr->SubPlot(1,2,1,"_");	gr->Title("Simplified PDE solver");
+  gr->Dens(res2);	gr->Axis();	gr->Box();
+  gr->Label('x',"\\i z");	gr->Label('y',"\\i x");
+  gr->Puts(mglPoint(-0.5,0.2),"i\\partial_z\\i u \\approx\\ exp(-\\i x^2)\\i u+exp(\\partial_x^2)[\\i u]","y");
+  return 0;
+}
+ at end verbatim
+
+ at pfig{apde, Comparison of simplified and advanced PDE solvers.}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Drawing phase plain, Pulse properties, PDE solving hints, Hints
+ at subsection Drawing phase plain
+ at nav{}
+
+Here I want say a few words of plotting phase plains. Phase plain is name for system of coordinates @math{x}, @math{x'}, i.e. a variable and its time derivative. Plot in phase plain is very useful for qualitative analysis of an ODE, because such plot is rude (it topologically the same for a range of ODE parameters). Most often the phase plain @{@math{x}, @math{x'}@} is used (due to its simplicity), that allows to analyze up to the 2nd order ODE (i.e. @math{x''+f(x,x')=0}).
+
+The simplest way to draw phase plain in MathGL is using @ref{flow} function(s), which automatically select several points and draw flow threads. If the ODE have an integral of motion (like Hamiltonian @math{H(x,x')=const} for dissipation-free case) then you can use @ref{cont} function for plotting isolines (contours). In fact. isolines are the same as flow threads, but without arrows on it. Finally, you can directly solve ODE using @ref{ode} function and plot its numerical solution.
+
+Let demonstrate this for ODE equation @math{x''-x+3*x^2=0}. This is nonlinear oscillator with square nonlinearity. It has integral @math{H=y^2+2*x^3-x^2=Const}. Also it have 2 typical stationary points: saddle at @{x=0, y=0@} and center at @{x=1/3, y=0@}. Motion at vicinity of center is just simple oscillations, and is stable to small variation of parameters. In opposite, motion around saddle point is non-stable to small variation of parameters, and is very slow. So, calculation around s [...]
+
+So, let draw this phase plain by 3 different methods. First, draw isolines for @math{H=y^2+2*x^3-x^2=Const} -- this is simplest for ODE without dissipation. Next, draw flow threads -- this is straightforward way, but the automatic choice of starting points is not always optimal. Finally, use @ref{ode} to check the above plots. At this we need to run @ref{ode} in both direction of time (in future and in the past) to draw whole plain. Alternatively, one can put starting points far from (or [...]
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SubPlot(2,2,0,"<_");  gr->Title("Cont");  gr->Box();
+  gr->Axis();  gr->Label('x',"x");  gr->Label('y',"\\dot{x}");
+  mglData f(100,100);   gr->Fill(f,"y^2+2*x^3-x^2-0.5");
+  gr->Cont(f);
+  gr->SubPlot(2,2,1,"<_");  gr->Title("Flow");  gr->Box();
+  gr->Axis();  gr->Label('x',"x");  gr->Label('y',"\\dot{x}");
+  mglData fx(100,100), fy(100,100);
+  gr->Fill(fx,"x-3*x^2");  gr->Fill(fy,"y");
+  gr->Flow(fy,fx,"v","value 7");
+  gr->SubPlot(2,2,2,"<_");  gr->Title("ODE");   gr->Box();
+  gr->Axis();  gr->Label('x',"x");  gr->Label('y',"\\dot{x}");
+  for(double x=-1;x<1;x+=0.1)
+  {
+    mglData in(2), r;   in.a[0]=x;
+    r = mglODE("y;x-3*x^2","xy",in);
+    gr->Plot(r.SubData(0), r.SubData(1));
+    r = mglODE("-y;-x+3*x^2","xy",in);
+    gr->Plot(r.SubData(0), r.SubData(1));
+  }
+}
+ at end verbatim
+
+ at pfig{ode, Example of ODE solving and phase plain drawing.}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Pulse properties, Using MGL parser, Drawing phase plain, Hints
+ at subsection Pulse properties
+ at nav{}
+
+There is common task in optics to determine properties of wave pulses or wave beams. MathGL provide special function @ref{pulse} which return the pulse properties (maximal value, center of mass, width and so on). Its usage is rather simple. Here I just illustrate it on the example of Gaussian pulse, where all parameters are obvious.
+ at verbatim
+void sample(mglGraph *gr)
+{
+  gr->SubPlot(1,1,0,"<_");  gr->Title("Pulse sample");
+  // first prepare pulse itself
+  mglData a(100); gr->Fill(a,"exp(-6*x^2)");
+  // get pulse parameters
+  mglData b(a.Pulse('x'));
+  // positions and widths are normalized on the number of points. So, set proper axis scale.
+  gr->SetRanges(0, a.nx-1, 0, 1);
+  gr->Axis(); gr->Plot(a);  // draw pulse and axis
+  // now visualize found pulse properties
+  double m = b[0];  // maximal amplitude
+  // approximate position of maximum
+  gr->Line(mglPoint(b[1],0), mglPoint(b[1],m),"r=");
+  // width at half-maximum (so called FWHM)
+  gr->Line(mglPoint(b[1]-b[3]/2,0), mglPoint(b[1]-b[3]/2,m),"m|");
+  gr->Line(mglPoint(b[1]+b[3]/2,0), mglPoint(b[1]+b[3]/2,m),"m|");
+  gr->Line(mglPoint(0,m/2), mglPoint(a.nx-1,m/2),"h");
+  // parabolic approximation near maximum
+  char func[128];	sprintf(func,"%g*(1-((x-%g)/%g)^2)",b[0],b[1],b[2]);
+  gr->FPlot(func,"g");
+}
+ at end verbatim
+
+ at pfig{pulse, Example of determining of pulse properties.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Using MGL parser, Using options, Pulse properties, Hints
+ at subsection Using MGL parser
+ at nav{}
+
+Sometimes you may prefer to use MGL scripts in yours code. It is simpler (especially in comparison with C/Fortran interfaces) and provide faster way to plot the data with annotations, labels and so on. Class @code{mglParse} (@pxref{mglParse class} parse MGL scripts in C++. It have also the corresponding interface for C/Fortran.
+
+The key function here is @code{mglParse::Parse()} (or @code{mgl_parse()} for C/Fortran) which execute one command per string. At this the detailed information about the possible errors or warnings is passed as function value. Or you may execute the whole script as long string with lines separated by @samp{\n}. Functions @code{mglParse::Execute()} and @code{mgl_parse_text()} perform it. Also you may set the values of parameters @samp{$0}... at samp{$9} for the script by functions @code{mglPa [...]
+
+The only non-obvious thing is data transition between script and yours program. There are 2 stages: add or find variable; and set data to variable. In C++ you may use functions @code{mglParse::AddVar()} and @code{mglParse::FindVar()} which return pointer to @code{mglData}. In C/Fortran the corresponding functions are @code{mgl_add_var()}, @code{mgl_find_var()}. This data pointer is valid until next @code{Parse()} or @code{Execute()} call. Note, you @strong{must not delete or free} the da [...]
+
+So, some simple example at the end. Here I define a data array, create variable, put data into it and plot it. The C++ code looks like this:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->Title("MGL parser sample");
+  mreal a[100];   // let a_i = sin(4*pi*x), x=0...1
+  for(int i=0;i<100;i++)a[i]=sin(4*M_PI*i/99);
+  mglParse *parser = new mglParse;
+  mglData *d = parser->AddVar("dat");
+  d->Set(a,100); // set data to variable
+  parser->Execute(gr, "plot dat; xrange 0 1\nbox\naxis");
+  // you may break script at any line do something
+  // and continue after that
+  parser->Execute(gr, "xlabel 'x'\nylabel 'y'\nbox");
+  // also you may use cycles or conditions in script
+  parser->Execute(gr, "for $0 -1 1 0.1\nline 0 0 -1 $0 'r'\nnext");
+  delete parser;
+  return 0;
+}
+ at end verbatim
+The code in C/Fortran looks practically the same:
+ at verbatim
+int sample(HMGL gr)
+{
+  mgl_title(gr, "MGL parser sample", "", -2);
+  double a[100];   // let a_i = sin(4*pi*x), x=0...1
+  int i;
+  for(i=0;i<100;i++)  a[i]=sin(4*M_PI*i/99);
+  HMPR parser = mgl_create_parser();
+  HMDT d = mgl_parser_add_var(parser, "dat");
+  mgl_data_set_double(d,a,100,1,1);    // set data to variable
+  mgl_parse_text(gr, parser, "plot dat; xrange 0 1\nbox\naxis");
+  // you may break script at any line do something
+  // and continue after that
+  mgl_parse_text(gr, parser, "xlabel 'x'\nylabel 'y'");
+  // also you may use cycles or conditions in script
+  mgl_parse_text(gr, parser, "for $0 -1 1 0.1\nif $0<0\n"
+    "line 0 0 -1 $0 'r':else:line 0 0 -1 $0 'g'\n"
+    "endif\nnext");
+  mgl_write_png(gr, "test.png", "");  // don't forgot to save picture
+  return 0;
+}
+ at end verbatim
+
+ at pfig{parser, Example of MGL script parsing.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Using options, ``Templates'', Using MGL parser, Hints
+ at subsection Using options
+ at nav{}
+
+ at ref{Command options} allow the easy setup of the selected plot by changing global settings only for this plot. Often, options are used for specifying the range of automatic variables (coordinates). However, options allows easily change plot transparency, numbers of line or faces to be drawn, or add legend entries. The sample function for options usage is:
+ at verbatim
+void template(mglGraph *gr)
+{
+  mglData a(31,41);
+  gr->Fill(a,"-pi*x*exp(-(y+1)^2-4*x^2)");
+
+  gr->SubPlot(2,2,0);	gr->Title("Options for coordinates");
+  gr->Alpha(true);	gr->Light(true);
+  gr->Rotate(40,60);    gr->Box();
+  gr->Surf(a,"r","yrange 0 1"); gr->Surf(a,"b","yrange 0 -1");
+  if(mini)	return;
+  gr->SubPlot(2,2,1);   gr->Title("Option 'meshnum'");
+  gr->Rotate(40,60);    gr->Box();
+  gr->Mesh(a,"r","yrange 0 1"); gr->Mesh(a,"b","yrange 0 -1; meshnum 5");
+  gr->SubPlot(2,2,2);   gr->Title("Option 'alpha'");
+  gr->Rotate(40,60);    gr->Box();
+  gr->Surf(a,"r","yrange 0 1; alpha 0.7");
+  gr->Surf(a,"b","yrange 0 -1; alpha 0.3");
+  gr->SubPlot(2,2,3,"<_");  gr->Title("Option 'legend'");
+  gr->FPlot("x^3","r","legend 'y = x^3'");
+  gr->FPlot("cos(pi*x)","b","legend 'y = cos \\pi x'");
+  gr->Box();    gr->Axis(); gr->Legend(2,"");
+}
+ at end verbatim
+
+ at pfig{mirror, Example of options usage.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node ``Templates'', Stereo image, Using options, Hints
+ at subsection ``Templates''
+ at nav{}
+
+As I have noted before, the change of settings will influence only for the further plotting commands. This allows one to create ``template'' function which will contain settings and primitive drawing for often used plots. Correspondingly one may call this template-function for drawing simplification.
+
+For example, let one has a set of points (experimental or numerical) and wants to compare it with theoretical law (for example, with exponent law @math{\exp(-x/2), x \in [0, 20]}). The template-function for this task is:
+ at verbatim
+void template(mglGraph *gr)
+{
+  mglData  law(100);      // create the law
+  law.Modify("exp(-10*x)");
+  gr->SetRanges(0,20, 0.0001,1);
+  gr->SetFunc(0,"lg(y)",0);
+  gr->Plot(law,"r2");
+  gr->Puts(mglPoint(10,0.2),"Theoretical law: e^x","r:L");
+  gr->Label('x',"x val."); gr->Label('y',"y val.");
+  gr->Axis(); gr->Grid("xy","g;"); gr->Box();
+}
+ at end verbatim
+At this, one will only write a few lines for data drawing:
+ at verbatim
+  template(gr);     // apply settings and default drawing from template
+  mglData dat("fname.dat"); // load the data
+  // and draw it (suppose that data file have 2 columns)
+  gr->Plot(dat.SubData(0),dat.SubData(1),"bx ");
+ at end verbatim
+A template-function can also contain settings for font, transparency, lightning, color scheme and so on.
+
+I understand that this is obvious thing for any professional programmer, but I several times receive suggestion about ``templates'' ... So, I decide to point out it here.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Stereo image, Reduce memory usage, ``Templates'', Hints
+ at subsection Stereo image
+ at nav{}
+
+One can easily create stereo image in MathGL. Stereo image can be produced by making two subplots with slightly different rotation angles. The corresponding code looks like this:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  mglData a;  mgls_prepare2d(&a);
+  gr->Light(true);
+
+  gr->SubPlot(2,1,0); gr->Rotate(50,60+1);
+  gr->Box();  gr->Surf(a);
+
+  gr->SubPlot(2,1,1); gr->Rotate(50,60-1);
+  gr->Box();  gr->Surf(a);
+  return 0;
+}
+ at end verbatim
+
+ at pfig{stereo, Example of stereo image.}
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Reduce memory usage, Saving and scanning file, Stereo image, Hints
+ at subsection Reduce memory usage
+ at nav{}
+
+By default MathGL save all primitives in memory, rearrange it and only later draw them on bitmaps. Usually, this speed up drawing, but may require a lot of memory for plots which contain a lot of faces (like @ref{cloud}, @ref{dew}). You can use @ref{quality} function for setting to use direct drawing on bitmap and bypassing keeping any primitives in memory. This function also allow you to decrease the quality of the resulting image but increase the speed of the drawing.
+
+The code for lowest memory usage looks like this:
+ at verbatim
+int sample(mglGraph *gr)
+{
+  gr->SetQuality(6);   // firstly, set to draw directly on bitmap
+  for(i=0;i<1000;i++)
+    gr->Sphere(mglPoint(mgl_rnd()*2-1,mgl_rnd()*2-1),0.05);
+  return 0;
+}
+ at end verbatim
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Saving and scanning file, Mixing bitmap and vector output, Reduce memory usage, Hints
+ at subsection Scanning file
+ at nav{}
+
+MathGL have possibilities to write textual information into file with variable values. In MGL script you can use @ref{save} command for that. However, the usual @code{printf();} is simple in C/C++ code. For example, lets create some textual file
+ at verbatim
+FILE *fp=fopen("test.txt","w");
+fprintf(fp,"This is test: 0 -> 1 q\n");
+fprintf(fp,"This is test: 1 -> -1 q\n");
+fprintf(fp,"This is test: 2 -> 0 q\n");
+fclose(fp);
+ at end verbatim
+It contents look like
+ at verbatim
+This is test: 0 -> 1 q
+This is test: 1 -> -1 q
+This is test: 2 -> 0 q
+ at end verbatim
+
+Let assume now that you want to read this values (i.e. [[0,1],[1,-1],[2,0]]) from the file. You can use @ref{scanfile} for that. The desired values was written using template "This is test: %g -> %g q\n". So, just use
+ at verbatim
+mglData a;
+a.ScanFile("test.txt","This is test: %g -> %g");
+ at end verbatim
+and plot it to for assurance
+ at verbatim
+gr->SetRanges(a.SubData(0), a.SubData(1));
+gr->Axis();	gr->Plot(a.SubData(0),a.SubData(1),"o");
+ at end verbatim
+
+Note, I keep only the leading part of template (i.e. "This is test: %g -> %g" instead of "This is test: %g -> %g q\n"), because there is no important for us information after the second number in the line.
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Mixing bitmap and vector output, , Saving and scanning file, Hints
+ at subsection Mixing bitmap and vector output
+ at nav{}
+
+Sometimes output plots contain surfaces with a lot of points, and some vector primitives (like axis, text, curves, etc.). Using vector output formats (like EPS or SVG) will produce huge files with possible loss of smoothed lighting. Contrary, the bitmap output may cause the roughness of text and curves. Hopefully, MathGL have a possibility to combine bitmap output for surfaces and vector one for other primitives in the same EPS file, by using @ref{rasterize} command. 
+
+The idea is to prepare part of picture with surfaces or other "heavy" plots and produce the background image from them by help of @ref{rasterize} command. Next, we draw everything to be saved in vector form (text, curves, axis and etc.). Note, that you need to clear primitives (use @ref{clf} command) after @ref{rasterize} if you want to disable duplication of surfaces in output files (like EPS). Note, that some of output formats (like 3D ones, and TeX) don't support the background bitmap [...]
+
+The sample code is:
+ at verbatim
+// first draw everything to be in bitmap output
+gr->FSurf("x^2+y^2", "#", "value 10");
+
+gr->Rasterize();  // set above plots as bitmap background
+gr->Clf();        // clear primitives, to exclude them from file
+
+// now draw everything to be in vector output
+gr->Axis(); gr->Box();
+
+// and save file
+gr->WriteFrame("fname.eps");
+ at end verbatim
+
+ at c ==================================================================
+ at external{}
+ at node FAQ, , Hints, Examples
+ at section FAQ
+ at nav{}
+
+ at table @strong
+ at item График не рисуется?!
+Проверьте, что точки графика находятся внутри ограничивающего параллелепипеда, при необходимости увеличьте его с помощью функции @code{Axis()}. Проверьте, что размерность массива правильная для выбранного типа графика. Убедитесь, что функция  @code{Finish()} была вызвана после построения графика (или график был сохранен в файл). Иногда отражение света от плоских поверхностей (типа, @code{Dens()}) может выглядеть как отсутствие графика.
+
+ at item Не нашел нужного графика?!
+Многие ``новые'' графики можно строить, используя уже существующие функции. Например, поверхность вращения кривой относительно оси можно построить, используя специальную функцию @code{Torus()}, а можно построить как параметрически заданную поверхность @code{Surf()}. См. также @ref{Hints} и @ref{Examples} MathGL. Если же нужного типа графика все равно нет, то пишите мне @email{mathgl.abalakin@@gmail.com, e-mail} и в следующей версии этот график появится.
+
+ at item Требуется ли знание сторонних библиотек (например, OpenGL) для использования библиотеки MathGL?
+Нет. Библиотека MathGL самодостаточна и не требует знания сторонних библиотек.
+
+ at item На каком языке написана библиотека? Для каких языков у нее есть интерфейсы?
+Ядро библиотеки написано на С++. Кроме него, есть интерфейсы для чистого С, фортрана, паскаля, форта и собственный командный язык MGL. Также есть поддержка большого числа интерпретируемых языков (Python, Java,  ALLEGROCL, CHICKEN, Lisp, CFFI, C#, Guile, Lua, Modula 3, Mzscheme, Ocaml, Octave, Perl, PHP, Pike, R, Ruby, Tcl). Эти интерфейсы написаны с помощью SWIG (и функции чистого С и классы). Однако на данный момент только интерфейсы для Python и Octave включены в скрипты сборки. Причин [...]
+
+ at item Как мне использовать MathGL с Фортраном?
+Библиотеку MathGL можно использовать как есть с компилятором @code{gfortran} поскольку он использует по умолчанию AT&T нотацию для внешних функций. Для других компиляторов (например, Visual Fortran) необходимо включить использование AT&T нотации вручную. AT&T нотация требует, чтобы имя функции завершалось символом @samp{_}, аргументы функции передавались по указателю и длины строк передавались в конце списка аргументов. Например:
+
+ at emph{C функция} -- @code{void mgl_fplot(HMGL graph, const char *fy, const char *stl, int n);}
+
+ at emph{AT&T функция} -- @code{void mgl_fplot_(uintptr_t *graph, const char *fy, const char *stl, int *n, int ly, int ls);}
+
+При использовании фортрана необходимо также включить библиотеку @code{-lstdc++}. Кроме того, если библиотека была собрана с опцией @code{enable-double=ON} (по умолчанию в версии 2.1 и более поздних), то все вещественные числа должны быть типа @code{real*8}. Это можно включить по умолчанию опцией @code{-fdefault-real-8}.
+
+ at item У меня есть класс Foo и в нем метод рисования Foo::draw(mglGraph *gr). Как мне нарисовать что-то в окне FLTK, GLUT или Qt?
+Функции-члены класса в С++ имеют ``скрытый'' параметр -- указатель на экземпляр класса и их прямое использование невозможно. Решением будет определение интерфейсной функции:
+ at example
+int foo_draw(mglGraph *gr, void *par)
+@{   ((Foo *)foo)->draw(gr);    @}
+ at end example
+и подстановка именно ее в вызов функции @code{Window()}:
+ at example
+gr->Window(argc,argv,foo_draw,"Title",this);
+ at end example
+
+Можно также наследовать Ваш класс от класса @code{mglDraw} и использовать функцию типа @code{gr->Window(argc, argv, foo, "Title");}.
+
+ at item Как мне вывести текст на русском/испанском/арабском/японском и т.д.?
+Стандартный путь состоит в использовании кодировки UTF-8 для вывода текста. Кроме того, все функции вывода текста имеют интерфейс для 8-битных (char *) строк. Однако в последнем случае Вам может потребоваться установить используемую в исходном тексте локаль. Например, для русского языка в кодировке CP1251 можно использовать @code{setlocale(LC_CTYPE, "ru_RU.cp1251");} (под MS Windows имена локали другие --  @code{setlocale(LC_CTYPE, "russian_russia.1251")}). Настоятельно не рекомендую исп [...]
+
+ at item Как мне вырезать (исключить из рисования) точку или область на графике?
+Есть три основных способа. Во-первых, можно вырезать точку, задав одну из ее координат равной @code{NAN}. Во-вторых, можно воспользоваться функцией @code{SetCutBox()} или @code{CutOff()} для удаления точек из некоторой области (@pxref{Cutting}). Наконец, можно сделать эти точки прозрачными (невидимыми) с помощью функций @code{SurfA()}, @code{Surf3A()} (@pxref{Dual plotting}). В последнем случае обеспечивается еще и плавность включения прозрачности.
+
+ at item Я использую VisualStudio, CBuilder или другой компилятор (не MinGW/gcc). Как мне подключить библиотеку MathGL?
+Начиная с версии 2.0, рекомендуемый к использованию класс mglGraph (заголовочный файл @code{#include <mgl2/mgl.h>}) содержbn только с @code{inline} функции и может использоваться с любым компилятором без перекомпиляции бинарной версии библиотеки. Однако, если Вы планируете использовать низкоуровневые возможности (т.е. классы mglBase, mglCanvas и т.д.), то Вам следует перекомпилировать библиотеку MathGL с использованием Вашего компилятора.
+
+Отмечу, что использование предоставляемых динамических библиотек *.dll требует создания библиотек импорта (import library *.lib). Эта процедура зависит от используемого компилятора -- обратитесь к документации по Вашему компилятору. Например для VisualStudio это можно сделать командой @code{lib.exe /DEF:libmgl.def /OUT:libmgl.lib}.
+
+ at item Как мне собрать MathGL под Windows?
+Простейший путь -- использование комбинации CMake и MinGW. Также Вам может потребоваться дополнительные библиотеки, такие как GSL, PNG, JPEG и пр. Все они могут быть найдены на @url{http://gnuwin32.sourceforge.net/packages.html}. После установки всех компонент, просто запустите конфигуратор CMake и соберите MathGL командой make.
+
+ at item Как создать окно FLTK/GLUT/Qt с текущими результатами параллельно с выполнением основных вычислений?
+Следует создать отдельный поток для обработки сообщений в окно. Обновление данных в окне можно выполнить вызовом функции @code{Update()}. Подробнее см. @ref{Animation}.
+
+ at item Сколько человек участвовало в создании библиотеки?
+Большую часть библиотеки написал один человек. Это результат примерно года работы на написание ядра библиотеки и базовых функций (в основном вечерами и по выходным). Процесс усовершенствования продолжается и теперь :). Скрипты сборки в основном написаны Д.Кулагиным, а экспорт в PRC/PDF написан М.Видассовым.
+
+ at item Как мне показать растровую картинку на рисунке?
+Можно импортировать ее в экземпляр @code{mglData} и построить с помощью функции @code{Dens()}. Например, для черно-белого рисунка можно использовать код: @code{mglData bmp; bmp.Import("fname.png","wk"); gr->Dens(bmp,"wk");}.
+
+ at item Как использовать MathGL в Qt, FLTK, wxWidgets ...?
+Есть специальные классы (виджеты) для этих библиотек: QMathGL для Qt, Fl_MathGL для FLTK и т.д. Если Вы не нашли подходящий класс, то можете создать свой собственный виджет, рисующий растровое изображение из mglCanvas::GetBits().
+
+ at item Как мне создать 3D в PDF?
+Используйте функцию @code{WritePRC}(), которая создаст PDF файл если MathGL был собран с enable-pdf=ON.
+
+ at item Как мне создать TeX рисунок?
+Используйте функцию @code{WriteTEX}(), которая создаст LaTeX файлы с собственно рисунком @samp{@var{fname}.tex}, с цветами MathGL @samp{mglcolors.tex} и основной файл @samp{mglmain.tex}, который может использоваться для просмотра изображения и/или генерации PDF с помощью команды типа @code{pdflatex mglmain.tex}.
+
+ at item Можно ли использовать MathGL в JavaScript?
+Да, пример JavaScript файла находится в папке texinfo/ исходных текстов. Для его работы необходимо предоставить JSON данные с 3d изображением (можно создать с помощью @code{WriteJSON}() функции). Скрипт позволяет выполнять базовые операции: приближение/удаление, вращение и сдвиг. Примеры использования JavaScript можно найти в @url{http://mathgl.sf.net/json.html}.
+
+
+
+ at item Как сменить шрифт (семейство шрифтов)?
+Во-первых, надо загрузить файлы @uref{http://mathgl.sourceforge.net/download.html, отсюда} или @uref{http://sourceforge.net/project/showfiles.php?group_id=152187&package_id=267177, отсюда}. Далее, в экземпляре mglGraph загружаем шрифты: @code{gr->LoadFont(fontname,path);}. Здесь @var{fontname} -- базовое имя шрифта, например @samp{STIX}, и @var{path} -- путь к папке с файлами шрифтов. Вызовите @code{gr->RestoreFont();} для использования шрифта по умолчанию.
+
+ at item Как нарисовать метки оси снаружи от графика?
+Просто используйте отрицательные значения длины меток, например @code{gr->SetTickLen(-0.1);}.
+
+ at item Как нарисовать одинаковые оси координат для прямоугольного (не квадратного) рисунка?
+Просто используйте @code{Aspect(NAN,NAN)} для каждого подграфика, или в начале рисования.
+
+ at item Как задать полупрозрачный фон?
+Просто используйте код типа @code{Clf("r@{A5@}");} или подготовьте PNG файл и задайте его в качестве фона рисунка @code{LoadBackground("fname.png");}.
+
+ at item Как уменьшить поля вокруг графика?
+Простейший путь состоит в использовании стилей @ref{subplot}. Однако, вы должны быть осторожны в изменении стиля @ref{subplot} если вы планируете добавлять @ref{colorbar} или вращать график -- часть графика может стать невидимой.
+
+ at item Can I combine bitmap and vector output in EPS?
+Yes. Sometimes you may have huge surface and a small set of curves and/or text on the plot. You can use function @ref{rasterize} just after making surface plot. This will put all plot to bitmap background. At this later plotting will be in vector format. For example, you can do something like following:
+ at verbatim
+gr->Surf(x, y, z);
+gr->Rasterize(); // make surface as bitmap
+gr->Axis();
+gr->WriteFrame("fname.eps");
+ at end verbatim
+
+ at item Почему у меня не получается использовать имя @samp{I} для переменной?
+MathGL поддерживает стандарт C99, в котором имя @samp{I} зарезервированно для мнимой единицы. Если Вам все таки нужно это имя для переменной, то поместите
+ at verbatim
+#undef I
+ at end verbatim
+сразу после включения заголовочных файлов MathGL.
+
+ at item Как мне создать MPEG видео по графикам?
+Вам следует сохранить каждый кадр в файл JPEG с именем типа @samp{frame0001.jpg}, @samp{frame0002.jpg}, ... Далее используйте ImageMagic для конвертации этих файлов в видео формата MPEG с помощью команды @code{convert frame*.jpg movie.mpg}. См. также @ref{MPEG}.
+
+ at end table
+
+ at external{}
diff --git a/texinfo/fdl.texi b/texinfo/fdl.texi
new file mode 100644
index 0000000..96ce74e
--- /dev/null
+++ b/texinfo/fdl.texi
@@ -0,0 +1,451 @@
+ at c The GNU Free Documentation License.
+ at center Version 1.2, November 2002
+
+ at c This file is intended to be included within another document,
+ at c hence no sectioning command or @node.
+
+ at display
+Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc.
+51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+ at end display
+
+ at enumerate 0
+ at item
+PREAMBLE
+
+The purpose of this License is to make a manual, textbook, or other
+functional and useful document @dfn{free} in the sense of freedom: to
+assure everyone the effective freedom to copy and redistribute it,
+with or without modifying it, either commercially or noncommercially.
+Secondarily, this License preserves for the author and publisher a way
+to get credit for their work, while not being considered responsible
+for modifications made by others.
+
+This License is a kind of ``copyleft'', which means that derivative
+works of the document must themselves be free in the same sense.  It
+complements the GNU General Public License, which is a copyleft
+license designed for free software.
+
+We have designed this License in order to use it for manuals for free
+software, because free software needs free documentation: a free
+program should come with manuals providing the same freedoms that the
+software does.  But this License is not limited to software manuals;
+it can be used for any textual work, regardless of subject matter or
+whether it is published as a printed book.  We recommend this License
+principally for works whose purpose is instruction or reference.
+
+ at item
+APPLICABILITY AND DEFINITIONS
+
+This License applies to any manual or other work, in any medium, that
+contains a notice placed by the copyright holder saying it can be
+distributed under the terms of this License.  Such a notice grants a
+world-wide, royalty-free license, unlimited in duration, to use that
+work under the conditions stated herein.  The ``Document'', below,
+refers to any such manual or work.  Any member of the public is a
+licensee, and is addressed as ``you''.  You accept the license if you
+copy, modify or distribute the work in a way requiring permission
+under copyright law.
+
+A ``Modified Version'' of the Document means any work containing the
+Document or a portion of it, either copied verbatim, or with
+modifications and/or translated into another language.
+
+A ``Secondary Section'' is a named appendix or a front-matter section
+of the Document that deals exclusively with the relationship of the
+publishers or authors of the Document to the Document's overall
+subject (or to related matters) and contains nothing that could fall
+directly within that overall subject.  (Thus, if the Document is in
+part a textbook of mathematics, a Secondary Section may not explain
+any mathematics.)  The relationship could be a matter of historical
+connection with the subject or with related matters, or of legal,
+commercial, philosophical, ethical or political position regarding
+them.
+
+The ``Invariant Sections'' are certain Secondary Sections whose titles
+are designated, as being those of Invariant Sections, in the notice
+that says that the Document is released under this License.  If a
+section does not fit the above definition of Secondary then it is not
+allowed to be designated as Invariant.  The Document may contain zero
+Invariant Sections.  If the Document does not identify any Invariant
+Sections then there are none.
+
+The ``Cover Texts'' are certain short passages of text that are listed,
+as Front-Cover Texts or Back-Cover Texts, in the notice that says that
+the Document is released under this License.  A Front-Cover Text may
+be at most 5 words, and a Back-Cover Text may be at most 25 words.
+
+A ``Transparent'' copy of the Document means a machine-readable copy,
+represented in a format whose specification is available to the
+general public, that is suitable for revising the document
+straightforwardly with generic text editors or (for images composed of
+pixels) generic paint programs or (for drawings) some widely available
+drawing editor, and that is suitable for input to text formatters or
+for automatic translation to a variety of formats suitable for input
+to text formatters.  A copy made in an otherwise Transparent file
+format whose markup, or absence of markup, has been arranged to thwart
+or discourage subsequent modification by readers is not Transparent.
+An image format is not Transparent if used for any substantial amount
+of text.  A copy that is not ``Transparent'' is called ``Opaque''.
+
+Examples of suitable formats for Transparent copies include plain
+ at sc{ascii} without markup, Texinfo input format, La at TeX{} input
+format, @acronym{SGML} or @acronym{XML} using a publicly available
+ at acronym{DTD}, and standard-conforming simple @acronym{HTML},
+PostScript or @acronym{PDF} designed for human modification.  Examples
+of transparent image formats include @acronym{PNG}, @acronym{XCF} and
+ at acronym{JPG}.  Opaque formats include proprietary formats that can be
+read and edited only by proprietary word processors, @acronym{SGML} or
+ at acronym{XML} for which the @acronym{DTD} and/or processing tools are
+not generally available, and the machine-generated @acronym{HTML},
+PostScript or @acronym{PDF} produced by some word processors for
+output purposes only.
+
+The ``Title Page'' means, for a printed book, the title page itself,
+plus such following pages as are needed to hold, legibly, the material
+this License requires to appear in the title page.  For works in
+formats which do not have any title page as such, ``Title Page'' means
+the text near the most prominent appearance of the work's title,
+preceding the beginning of the body of the text.
+
+A section ``Entitled XYZ'' means a named subunit of the Document whose
+title either is precisely XYZ or contains XYZ in parentheses following
+text that translates XYZ in another language.  (Here XYZ stands for a
+specific section name mentioned below, such as ``Acknowledgements'',
+``Dedications'', ``Endorsements'', or ``History''.)  To ``Preserve the Title''
+of such a section when you modify the Document means that it remains a
+section ``Entitled XYZ'' according to this definition.
+
+The Document may include Warranty Disclaimers next to the notice which
+states that this License applies to the Document.  These Warranty
+Disclaimers are considered to be included by reference in this
+License, but only as regards disclaiming warranties: any other
+implication that these Warranty Disclaimers may have is void and has
+no effect on the meaning of this License.
+
+ at item
+VERBATIM COPYING
+
+You may copy and distribute the Document in any medium, either
+commercially or noncommercially, provided that this License, the
+copyright notices, and the license notice saying this License applies
+to the Document are reproduced in all copies, and that you add no other
+conditions whatsoever to those of this License.  You may not use
+technical measures to obstruct or control the reading or further
+copying of the copies you make or distribute.  However, you may accept
+compensation in exchange for copies.  If you distribute a large enough
+number of copies you must also follow the conditions in section 3.
+
+You may also lend copies, under the same conditions stated above, and
+you may publicly display copies.
+
+ at item
+COPYING IN QUANTITY
+
+If you publish printed copies (or copies in media that commonly have
+printed covers) of the Document, numbering more than 100, and the
+Document's license notice requires Cover Texts, you must enclose the
+copies in covers that carry, clearly and legibly, all these Cover
+Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
+the back cover.  Both covers must also clearly and legibly identify
+you as the publisher of these copies.  The front cover must present
+the full title with all words of the title equally prominent and
+visible.  You may add other material on the covers in addition.
+Copying with changes limited to the covers, as long as they preserve
+the title of the Document and satisfy these conditions, can be treated
+as verbatim copying in other respects.
+
+If the required texts for either cover are too voluminous to fit
+legibly, you should put the first ones listed (as many as fit
+reasonably) on the actual cover, and continue the rest onto adjacent
+pages.
+
+If you publish or distribute Opaque copies of the Document numbering
+more than 100, you must either include a machine-readable Transparent
+copy along with each Opaque copy, or state in or with each Opaque copy
+a computer-network location from which the general network-using
+public has access to download using public-standard network protocols
+a complete Transparent copy of the Document, free of added material.
+If you use the latter option, you must take reasonably prudent steps,
+when you begin distribution of Opaque copies in quantity, to ensure
+that this Transparent copy will remain thus accessible at the stated
+location until at least one year after the last time you distribute an
+Opaque copy (directly or through your agents or retailers) of that
+edition to the public.
+
+It is requested, but not required, that you contact the authors of the
+Document well before redistributing any large number of copies, to give
+them a chance to provide you with an updated version of the Document.
+
+ at item
+MODIFICATIONS
+
+You may copy and distribute a Modified Version of the Document under
+the conditions of sections 2 and 3 above, provided that you release
+the Modified Version under precisely this License, with the Modified
+Version filling the role of the Document, thus licensing distribution
+and modification of the Modified Version to whoever possesses a copy
+of it.  In addition, you must do these things in the Modified Version:
+
+ at enumerate A
+ at item
+Use in the Title Page (and on the covers, if any) a title distinct
+from that of the Document, and from those of previous versions
+(which should, if there were any, be listed in the History section
+of the Document).  You may use the same title as a previous version
+if the original publisher of that version gives permission.
+
+ at item
+List on the Title Page, as authors, one or more persons or entities
+responsible for authorship of the modifications in the Modified
+Version, together with at least five of the principal authors of the
+Document (all of its principal authors, if it has fewer than five),
+unless they release you from this requirement.
+
+ at item
+State on the Title page the name of the publisher of the
+Modified Version, as the publisher.
+
+ at item
+Preserve all the copyright notices of the Document.
+
+ at item
+Add an appropriate copyright notice for your modifications
+adjacent to the other copyright notices.
+
+ at item
+Include, immediately after the copyright notices, a license notice
+giving the public permission to use the Modified Version under the
+terms of this License, in the form shown in the Addendum below.
+
+ at item
+Preserve in that license notice the full lists of Invariant Sections
+and required Cover Texts given in the Document's license notice.
+
+ at item
+Include an unaltered copy of this License.
+
+ at item
+Preserve the section Entitled ``History'', Preserve its Title, and add
+to it an item stating at least the title, year, new authors, and
+publisher of the Modified Version as given on the Title Page.  If
+there is no section Entitled ``History'' in the Document, create one
+stating the title, year, authors, and publisher of the Document as
+given on its Title Page, then add an item describing the Modified
+Version as stated in the previous sentence.
+
+ at item
+Preserve the network location, if any, given in the Document for
+public access to a Transparent copy of the Document, and likewise
+the network locations given in the Document for previous versions
+it was based on.  These may be placed in the ``History'' section.
+You may omit a network location for a work that was published at
+least four years before the Document itself, or if the original
+publisher of the version it refers to gives permission.
+
+ at item
+For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve
+the Title of the section, and preserve in the section all the
+substance and tone of each of the contributor acknowledgements and/or
+dedications given therein.
+
+ at item
+Preserve all the Invariant Sections of the Document,
+unaltered in their text and in their titles.  Section numbers
+or the equivalent are not considered part of the section titles.
+
+ at item
+Delete any section Entitled ``Endorsements''.  Such a section
+may not be included in the Modified Version.
+
+ at item
+Do not retitle any existing section to be Entitled ``Endorsements'' or
+to conflict in title with any Invariant Section.
+
+ at item
+Preserve any Warranty Disclaimers.
+ at end enumerate
+
+If the Modified Version includes new front-matter sections or
+appendices that qualify as Secondary Sections and contain no material
+copied from the Document, you may at your option designate some or all
+of these sections as invariant.  To do this, add their titles to the
+list of Invariant Sections in the Modified Version's license notice.
+These titles must be distinct from any other section titles.
+
+You may add a section Entitled ``Endorsements'', provided it contains
+nothing but endorsements of your Modified Version by various
+parties---for example, statements of peer review or that the text has
+been approved by an organization as the authoritative definition of a
+standard.
+
+You may add a passage of up to five words as a Front-Cover Text, and a
+passage of up to 25 words as a Back-Cover Text, to the end of the list
+of Cover Texts in the Modified Version.  Only one passage of
+Front-Cover Text and one of Back-Cover Text may be added by (or
+through arrangements made by) any one entity.  If the Document already
+includes a cover text for the same cover, previously added by you or
+by arrangement made by the same entity you are acting on behalf of,
+you may not add another; but you may replace the old one, on explicit
+permission from the previous publisher that added the old one.
+
+The author(s) and publisher(s) of the Document do not by this License
+give permission to use their names for publicity for or to assert or
+imply endorsement of any Modified Version.
+
+ at item
+COMBINING DOCUMENTS
+
+You may combine the Document with other documents released under this
+License, under the terms defined in section 4 above for modified
+versions, provided that you include in the combination all of the
+Invariant Sections of all of the original documents, unmodified, and
+list them all as Invariant Sections of your combined work in its
+license notice, and that you preserve all their Warranty Disclaimers.
+
+The combined work need only contain one copy of this License, and
+multiple identical Invariant Sections may be replaced with a single
+copy.  If there are multiple Invariant Sections with the same name but
+different contents, make the title of each such section unique by
+adding at the end of it, in parentheses, the name of the original
+author or publisher of that section if known, or else a unique number.
+Make the same adjustment to the section titles in the list of
+Invariant Sections in the license notice of the combined work.
+
+In the combination, you must combine any sections Entitled ``History''
+in the various original documents, forming one section Entitled
+``History''; likewise combine any sections Entitled ``Acknowledgements'',
+and any sections Entitled ``Dedications''.  You must delete all
+sections Entitled ``Endorsements.''
+
+ at item
+COLLECTIONS OF DOCUMENTS
+
+You may make a collection consisting of the Document and other documents
+released under this License, and replace the individual copies of this
+License in the various documents with a single copy that is included in
+the collection, provided that you follow the rules of this License for
+verbatim copying of each of the documents in all other respects.
+
+You may extract a single document from such a collection, and distribute
+it individually under this License, provided you insert a copy of this
+License into the extracted document, and follow this License in all
+other respects regarding verbatim copying of that document.
+
+ at item
+AGGREGATION WITH INDEPENDENT WORKS
+
+A compilation of the Document or its derivatives with other separate
+and independent documents or works, in or on a volume of a storage or
+distribution medium, is called an ``aggregate'' if the copyright
+resulting from the compilation is not used to limit the legal rights
+of the compilation's users beyond what the individual works permit.
+When the Document is included in an aggregate, this License does not
+apply to the other works in the aggregate which are not themselves
+derivative works of the Document.
+
+If the Cover Text requirement of section 3 is applicable to these
+copies of the Document, then if the Document is less than one half of
+the entire aggregate, the Document's Cover Texts may be placed on
+covers that bracket the Document within the aggregate, or the
+electronic equivalent of covers if the Document is in electronic form.
+Otherwise they must appear on printed covers that bracket the whole
+aggregate.
+
+ at item
+TRANSLATION
+
+Translation is considered a kind of modification, so you may
+distribute translations of the Document under the terms of section 4.
+Replacing Invariant Sections with translations requires special
+permission from their copyright holders, but you may include
+translations of some or all Invariant Sections in addition to the
+original versions of these Invariant Sections.  You may include a
+translation of this License, and all the license notices in the
+Document, and any Warranty Disclaimers, provided that you also include
+the original English version of this License and the original versions
+of those notices and disclaimers.  In case of a disagreement between
+the translation and the original version of this License or a notice
+or disclaimer, the original version will prevail.
+
+If a section in the Document is Entitled ``Acknowledgements'',
+``Dedications'', or ``History'', the requirement (section 4) to Preserve
+its Title (section 1) will typically require changing the actual
+title.
+
+ at item
+TERMINATION
+
+You may not copy, modify, sublicense, or distribute the Document except
+as expressly provided for under this License.  Any other attempt to
+copy, modify, sublicense or distribute the Document 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.
+
+ at item
+FUTURE REVISIONS OF THIS LICENSE
+
+The Free Software Foundation may publish new, revised versions
+of the GNU Free Documentation 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.  See
+ at uref{http://www.gnu.org/copyleft/}.
+
+Each version of the License is given a distinguishing version number.
+If the Document specifies that a particular numbered version of this
+License ``or any later version'' applies to it, you have the option of
+following the terms and conditions either of that specified version or
+of any later version that has been published (not as a draft) by the
+Free Software Foundation.  If the Document does not specify a version
+number of this License, you may choose any version ever published (not
+as a draft) by the Free Software Foundation.
+ at end enumerate
+
+ at page
+ at heading ADDENDUM: How to use this License for your documents
+
+To use this License in a document you have written, include a copy of
+the License in the document and put the following copyright and
+license notices just after the title page:
+
+ at smallexample
+ at group
+  Copyright (C)  @var{year}  @var{your name}.
+  Permission is granted to copy, distribute and/or modify this document
+  under the terms of the GNU Free Documentation License, Version 1.2
+  or any later version published by the Free Software Foundation;
+  with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+  Texts.  A copy of the license is included in the section entitled ``GNU
+  Free Documentation License''.
+ at end group
+ at end smallexample
+
+If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
+replace the ``with at dots{}Texts.'' line with this:
+
+ at smallexample
+ at group
+    with the Invariant Sections being @var{list their titles}, with
+    the Front-Cover Texts being @var{list}, and with the Back-Cover Texts
+    being @var{list}.
+ at end group
+ at end smallexample
+
+If you have Invariant Sections without Cover Texts, or some other
+combination of the three, merge those two alternatives to suit the
+situation.
+
+If your document contains nontrivial examples of program code, we
+recommend releasing these examples in parallel under your choice of
+free software license, such as the GNU General Public License,
+to permit their use in free software.
+
+ at c Local Variables:
+ at c ispell-local-pdict: "ispell-dict"
+ at c End:
+
diff --git a/texinfo/filter.py b/texinfo/filter.py
new file mode 100755
index 0000000..b7bfa28
--- /dev/null
+++ b/texinfo/filter.py
@@ -0,0 +1,25 @@
+#!/usr/bin/python
+
+import os,string,re,glob
+
+print 'Tuning resulting html files for Qt\n'
+
+beginskip=0
+for filename in glob.glob('./*ru.html/*html'):
+    fpin=open(filename,'r')
+    fpout=open(filename+'.tmp','w')
+    for line in fpin.readlines():
+        if re.search('<html>',line): 
+            beginskip=1
+            fpout.write(line)
+            continue
+        if re.search('<head>',line): beginskip=0
+        if re.search('<meta name=\"keywords"\"',line): continue
+        if re.search('<meta name=\"description\"',line): continue
+        if re.search('<meta name=\"distribution\" content=\"global\">',line): continue
+        if re.search('<meta name=\"Generator\" content=\"texi2html',line): continue
+        if beginskip==0 : fpout.write(line)
+    fpin.close()
+    fpout.close()
+    os.remove(filename)
+    os.rename(filename+'.tmp', filename)
diff --git a/texinfo/fltk.png b/texinfo/fltk.png
new file mode 100644
index 0000000..3552b27
Binary files /dev/null and b/texinfo/fltk.png differ
diff --git a/texinfo/formats_en.texi b/texinfo/formats_en.texi
new file mode 100644
index 0000000..089d1a6
--- /dev/null
+++ b/texinfo/formats_en.texi
@@ -0,0 +1,141 @@
+ at nav{}
+
+This appendix contain description of file formats used by MathGL.
+
+ at menu
+* Font files::
+* MGLD format::
+* JSON format::
+* IFS format::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Font files, MGLD format, , File formats
+ at section Font files
+ at nav{}
+
+Starting from v.1.6 the MathGL library uses new font files. The font is defined in 4 files with suffixes @samp{*.vfm}, @samp{*_b.vfm}, @samp{*_i.vfm}, @samp{*_bi.vfm}. These files are text files containing the data for roman font, bold font, italic font and bold italic font. The files (or some symbols in the files) for bold, italic or bold italic fonts can be absent. In this case the roman glyph will be used for them. By analogy, if the bold italic font is absent but the bold font is pre [...]
+
+The format of font files (*.vfm -- vector font for MathGL) is the following.
+ at enumerate
+ at item
+First string contains human readable comment and is always ignored.
+ at item
+Second string contains 3 numbers, delimited by space or tabulation. The order of numbers is the following: @var{numg} -- the number of glyphs in the file (integer), @var{fact} -- the factor for glyph sizing (mreal), @var{size} -- the size of buffer for glyph description (integer).
+ at item
+After it @var{numg}-th strings with glyphs description are placed. Each string contains 6 positive numbers, delimited by space of tabulation. The order of numbers is the following: Unicode glyph ID, glyph width, number of lines in glyph, position of lines coordinates in the buffer (length is 2*number of lines), number of triangles in glyph, position of triangles coordinates in the buffer (length is 6*number of triangles).
+ at item
+The end of file contains the buffer with point coordinates at lines or triangles vertexes. The size of buffer (the number of integer) is @var{size}.
+ at end enumerate
+
+Each font file can be compressed by gzip.
+
+Note: the closing contour line  is done automatically (so the last segment may be absent). For starting new contour use a point with coordinates @code{@{0x3fff, 0x3fff@}}.
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node MGLD format, JSON format, Font files, File formats
+ at section MGLD format
+ at nav{}
+
+MGLD is textual file, which contain all required information for drawing 3D image, i.e. it contain vertexes with colors and normales, primitives with all properties, textures, and glyph descriptions. MGLD file can be imported or viewed separately, without parsing data files itself.
+
+MGLD file start from string
+ at verbatim
+MGLD npnts nprim ntxtr nglfs # optional description
+ at end verbatim
+which contain signature @samp{MGLD} and number of points @var{npnts}, number of primitives @var{nprim}, number of textures @var{ntxtr}, number of glyph descriptions @var{nglfs}, and optional description. Empty strings and string with @samp{#} are ignored.
+
+Next, file contain @var{npnts} strings with points coordinates and colors. The format of each string is
+ at verbatim
+x y z c t ta u v w r g b a
+ at end verbatim
+Here @var{x}, @var{y}, @var{z} are coordinates, @var{c}, @var{t} are color indexes in texture, @var{ta} is normalized @var{t} according to current alpha setting, @var{u}, @var{v}, @var{w} are coordinates of normal vector (can be @code{NAN} if disabled), @var{r}, @var{g}, @var{b}, @var{a} are RGBA color values.
+
+Next, file contain @var{nprim} strings with properties of primitives. The format of each string is
+ at verbatim
+type n1 n2 n3 n4 id s w p
+ at end verbatim
+Here @var{type} is kind of primitive (0 - mark, 1 - line, 2 - triangle, 3 - quadrangle, 4 - glyph), @var{n1}... at var{n4} is index of point for vertexes,  @var{id} is primitive identification number, @var{s} and @var{w} are size and width if applicable, @var{p} is scaling factor for glyphs.
+
+Next, file contain @var{ntxtr} strings with descriptions of textures. The format of each string is
+ at verbatim
+smooth alpha colors
+ at end verbatim
+Here @var{smooth} set to enable smoothing between colors, @var{alpha} set to use half-transparent texture, @var{colors} contain color scheme itself as it described in @ref{Color scheme}.
+
+Finally, file contain @var{nglfs} entries with description of each glyph used in the figure. The format of entries are
+ at verbatim
+nT nL
+xA yA xB yB xC yC ...
+xP yP ...
+ at end verbatim
+Here nT is the number of triangles; nL is the number of line vertexes; xA, yA, xB, yB, xC, yC are coordinates of triangles; and xP, yP, xQ, yQ are coordinates of lines. Line coordinate xP=0x3fff, yP=0x3fff denote line breaking.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node JSON format, IFS format, MGLD format, File formats
+ at section JSON format
+ at nav{}
+
+MathGL can save points and primitives of 3D object. It contain a set of variables listed below.
+
+ at table @samp
+ at item width
+width of the image;
+ at item height
+height of the image
+ at item depth
+depth of the image, usually =sqrt(width*height);
+
+ at item npnts
+number of points (vertexes);
+ at item pnts
+array of coordinates of points (vertexes), each element is array in form [x, y, z];
+
+ at item nprim
+number of primitives;
+ at item prim
+array of primitives, each element is array in form [type, n1, n2, n3, n4, id, s, w, p, z, color].
+
+Here @var{type} is kind of primitive (0 - mark, 1 - line, 2 - triangle, 3 - quadrangle, 4 - glyph), @var{n1}... at var{n4} is index of point for vertexes and @var{n2} can be index of glyph coordinate, @var{s} and @var{w} are size and width if applicable, @var{z} is average z-coordinate, @var{id} is primitive identification number, @var{p} is scaling factor for glyphs.
+
+ at item ncoor
+number of glyph positions
+ at item coor
+array of glyph positions, each element is array in form [dx,dy]
+
+ at item nglfs
+number of glyph descriptions
+ at item glfs
+array of glyph descriptions, each element is array in form @code{[nL, [xP0, yP0, xP1, yP1 ...]]}. Here @code{nL} is the number of line vertexes; and @code{xP, yP, xQ, yQ} are coordinates of lines. Line coordinate xP=0x3fff, yP=0x3fff denote line breaking.
+
+ at end table
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node IFS format, , JSON format, File formats
+ at section IFS format
+ at nav{}
+
+MathGL can read IFS fractal parameters (see @ref{ifsfile}) from a IFS file. Let remind IFS file format. File may contain several records. Each record contain the name of fractal (@samp{binary} in the example below) and the body of fractal, which is enclosed in curly braces @{@}. Symbol @samp{;} start the comment. If the name of fractal contain @samp{(3D)} or @samp{(3d)} then the 3d IFS fractal is specified. The sample below contain two fractals: @samp{binary} -- usual 2d fractal, and @sa [...]
+
+ at verbatim
+ binary
+ { ; comment allowed here
+  ; and here
+  .5  .0 .0 .5 -2.563477 -0.000003 .333333   ; also comment allowed here
+  .5  .0 .0 .5  2.436544 -0.000003 .333333
+  .0 -.5 .5 .0  4.873085  7.563492 .333333
+  }
+
+ 3dfern (3D) {
+   .00  .00 0 .0 .18 .0 0  0.0 0.00 0 0.0 0 .01
+   .85  .00 0 .0 .85 .1 0 -0.1 0.85 0 1.6 0 .85
+   .20 -.20 0 .2 .20 .0 0  0.0 0.30 0 0.8 0 .07
+  -.20  .20 0 .2 .20 .0 0  0.0 0.30 0 0.8 0 .07
+  }
+ at end verbatim
+ at external{}
diff --git a/texinfo/formats_ru.texi b/texinfo/formats_ru.texi
new file mode 100644
index 0000000..089d1a6
--- /dev/null
+++ b/texinfo/formats_ru.texi
@@ -0,0 +1,141 @@
+ at nav{}
+
+This appendix contain description of file formats used by MathGL.
+
+ at menu
+* Font files::
+* MGLD format::
+* JSON format::
+* IFS format::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Font files, MGLD format, , File formats
+ at section Font files
+ at nav{}
+
+Starting from v.1.6 the MathGL library uses new font files. The font is defined in 4 files with suffixes @samp{*.vfm}, @samp{*_b.vfm}, @samp{*_i.vfm}, @samp{*_bi.vfm}. These files are text files containing the data for roman font, bold font, italic font and bold italic font. The files (or some symbols in the files) for bold, italic or bold italic fonts can be absent. In this case the roman glyph will be used for them. By analogy, if the bold italic font is absent but the bold font is pre [...]
+
+The format of font files (*.vfm -- vector font for MathGL) is the following.
+ at enumerate
+ at item
+First string contains human readable comment and is always ignored.
+ at item
+Second string contains 3 numbers, delimited by space or tabulation. The order of numbers is the following: @var{numg} -- the number of glyphs in the file (integer), @var{fact} -- the factor for glyph sizing (mreal), @var{size} -- the size of buffer for glyph description (integer).
+ at item
+After it @var{numg}-th strings with glyphs description are placed. Each string contains 6 positive numbers, delimited by space of tabulation. The order of numbers is the following: Unicode glyph ID, glyph width, number of lines in glyph, position of lines coordinates in the buffer (length is 2*number of lines), number of triangles in glyph, position of triangles coordinates in the buffer (length is 6*number of triangles).
+ at item
+The end of file contains the buffer with point coordinates at lines or triangles vertexes. The size of buffer (the number of integer) is @var{size}.
+ at end enumerate
+
+Each font file can be compressed by gzip.
+
+Note: the closing contour line  is done automatically (so the last segment may be absent). For starting new contour use a point with coordinates @code{@{0x3fff, 0x3fff@}}.
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node MGLD format, JSON format, Font files, File formats
+ at section MGLD format
+ at nav{}
+
+MGLD is textual file, which contain all required information for drawing 3D image, i.e. it contain vertexes with colors and normales, primitives with all properties, textures, and glyph descriptions. MGLD file can be imported or viewed separately, without parsing data files itself.
+
+MGLD file start from string
+ at verbatim
+MGLD npnts nprim ntxtr nglfs # optional description
+ at end verbatim
+which contain signature @samp{MGLD} and number of points @var{npnts}, number of primitives @var{nprim}, number of textures @var{ntxtr}, number of glyph descriptions @var{nglfs}, and optional description. Empty strings and string with @samp{#} are ignored.
+
+Next, file contain @var{npnts} strings with points coordinates and colors. The format of each string is
+ at verbatim
+x y z c t ta u v w r g b a
+ at end verbatim
+Here @var{x}, @var{y}, @var{z} are coordinates, @var{c}, @var{t} are color indexes in texture, @var{ta} is normalized @var{t} according to current alpha setting, @var{u}, @var{v}, @var{w} are coordinates of normal vector (can be @code{NAN} if disabled), @var{r}, @var{g}, @var{b}, @var{a} are RGBA color values.
+
+Next, file contain @var{nprim} strings with properties of primitives. The format of each string is
+ at verbatim
+type n1 n2 n3 n4 id s w p
+ at end verbatim
+Here @var{type} is kind of primitive (0 - mark, 1 - line, 2 - triangle, 3 - quadrangle, 4 - glyph), @var{n1}... at var{n4} is index of point for vertexes,  @var{id} is primitive identification number, @var{s} and @var{w} are size and width if applicable, @var{p} is scaling factor for glyphs.
+
+Next, file contain @var{ntxtr} strings with descriptions of textures. The format of each string is
+ at verbatim
+smooth alpha colors
+ at end verbatim
+Here @var{smooth} set to enable smoothing between colors, @var{alpha} set to use half-transparent texture, @var{colors} contain color scheme itself as it described in @ref{Color scheme}.
+
+Finally, file contain @var{nglfs} entries with description of each glyph used in the figure. The format of entries are
+ at verbatim
+nT nL
+xA yA xB yB xC yC ...
+xP yP ...
+ at end verbatim
+Here nT is the number of triangles; nL is the number of line vertexes; xA, yA, xB, yB, xC, yC are coordinates of triangles; and xP, yP, xQ, yQ are coordinates of lines. Line coordinate xP=0x3fff, yP=0x3fff denote line breaking.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node JSON format, IFS format, MGLD format, File formats
+ at section JSON format
+ at nav{}
+
+MathGL can save points and primitives of 3D object. It contain a set of variables listed below.
+
+ at table @samp
+ at item width
+width of the image;
+ at item height
+height of the image
+ at item depth
+depth of the image, usually =sqrt(width*height);
+
+ at item npnts
+number of points (vertexes);
+ at item pnts
+array of coordinates of points (vertexes), each element is array in form [x, y, z];
+
+ at item nprim
+number of primitives;
+ at item prim
+array of primitives, each element is array in form [type, n1, n2, n3, n4, id, s, w, p, z, color].
+
+Here @var{type} is kind of primitive (0 - mark, 1 - line, 2 - triangle, 3 - quadrangle, 4 - glyph), @var{n1}... at var{n4} is index of point for vertexes and @var{n2} can be index of glyph coordinate, @var{s} and @var{w} are size and width if applicable, @var{z} is average z-coordinate, @var{id} is primitive identification number, @var{p} is scaling factor for glyphs.
+
+ at item ncoor
+number of glyph positions
+ at item coor
+array of glyph positions, each element is array in form [dx,dy]
+
+ at item nglfs
+number of glyph descriptions
+ at item glfs
+array of glyph descriptions, each element is array in form @code{[nL, [xP0, yP0, xP1, yP1 ...]]}. Here @code{nL} is the number of line vertexes; and @code{xP, yP, xQ, yQ} are coordinates of lines. Line coordinate xP=0x3fff, yP=0x3fff denote line breaking.
+
+ at end table
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node IFS format, , JSON format, File formats
+ at section IFS format
+ at nav{}
+
+MathGL can read IFS fractal parameters (see @ref{ifsfile}) from a IFS file. Let remind IFS file format. File may contain several records. Each record contain the name of fractal (@samp{binary} in the example below) and the body of fractal, which is enclosed in curly braces @{@}. Symbol @samp{;} start the comment. If the name of fractal contain @samp{(3D)} or @samp{(3d)} then the 3d IFS fractal is specified. The sample below contain two fractals: @samp{binary} -- usual 2d fractal, and @sa [...]
+
+ at verbatim
+ binary
+ { ; comment allowed here
+  ; and here
+  .5  .0 .0 .5 -2.563477 -0.000003 .333333   ; also comment allowed here
+  .5  .0 .0 .5  2.436544 -0.000003 .333333
+  .0 -.5 .5 .0  4.873085  7.563492 .333333
+  }
+
+ 3dfern (3D) {
+   .00  .00 0 .0 .18 .0 0  0.0 0.00 0 0.0 0 .01
+   .85  .00 0 .0 .85 .1 0 -0.1 0.85 0 1.6 0 .85
+   .20 -.20 0 .2 .20 .0 0  0.0 0.30 0 0.8 0 .07
+  -.20  .20 0 .2 .20 .0 0  0.0 0.30 0 0.8 0 .07
+  }
+ at end verbatim
+ at external{}
diff --git a/texinfo/glut.png b/texinfo/glut.png
new file mode 100644
index 0000000..48d0718
Binary files /dev/null and b/texinfo/glut.png differ
diff --git a/texinfo/gpl-2.0.texi b/texinfo/gpl-2.0.texi
new file mode 100644
index 0000000..8391c38
--- /dev/null
+++ b/texinfo/gpl-2.0.texi
@@ -0,0 +1,389 @@
+ at c The GNU General Public License.
+ at center Version 2, June 1991
+
+ at c This file is intended to be included within another document,
+ at c hence no sectioning command or @node.  
+
+ at display
+Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc.
+51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+ at end display
+
+ at heading 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 Lesser 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.
+
+ at heading TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ at enumerate 0
+ at item
+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.
+
+ at item
+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.
+
+ at item
+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:
+
+ at enumerate a
+ at item
+You must cause the modified files to carry prominent notices
+stating that you changed the files and the date of any change.
+
+ at item
+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.
+
+ at item
+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.)
+ at end enumerate
+
+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.
+
+ at item
+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:
+
+ at enumerate a
+ at item
+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,
+
+ at item
+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,
+
+ at item
+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.)
+ at end enumerate
+
+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.
+
+ at item
+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.
+
+ at item
+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.
+
+ at item
+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.
+
+ at item
+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.
+
+ at item
+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.
+
+ at item
+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.
+
+ at item
+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.
+
+ at iftex
+ at heading NO WARRANTY
+ at end iftex
+ at ifinfo
+ at center NO WARRANTY
+
+ at end ifinfo
+
+ at item
+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.
+
+ at item
+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.
+ at end enumerate
+
+ at iftex
+ at heading END OF TERMS AND CONDITIONS
+ at end iftex
+ at ifinfo
+ at center END OF TERMS AND CONDITIONS
+
+ at end ifinfo
+
+ at page
+ at heading Appendix: 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.
+
+ at smallexample
+ at var{one line to give the program's name and a brief idea of what it does.}
+Copyright (C) @var{yyyy}  @var{name of author}
+
+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.
+ at end smallexample
+
+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:
+
+ at smallexample
+Gnomovision version 69, Copyright (C) @var{year} @var{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.
+ at end smallexample
+
+The hypothetical commands @samp{show w} and @samp{show c} should show
+the appropriate parts of the General Public License.  Of course, the
+commands you use may be called something other than @samp{show w} and
+ at samp{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:
+
+ at example
+Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+`Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ at var{signature of Ty Coon}, 1 April 1989
+Ty Coon, President of Vice
+ at end example
+
+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 Lesser General
+Public License instead of this License.
diff --git a/texinfo/gpl-3.0.texi b/texinfo/gpl-3.0.texi
new file mode 100644
index 0000000..97a17e1
--- /dev/null
+++ b/texinfo/gpl-3.0.texi
@@ -0,0 +1,717 @@
+ at c The GNU General Public License.
+ at center Version 3, 29 June 2007
+
+ at c This file is intended to be included within another document,
+ at c hence no sectioning command or @node.
+
+ at display
+Copyright @copyright{} 2007 Free Software Foundation, Inc. @url{http://fsf.org/}
+
+Everyone is permitted to copy and distribute verbatim copies of this
+license document, but changing it is not allowed.
+ at end display
+
+ at heading Preamble
+
+The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom
+to share and change all versions of a program---to make sure it remains
+free software for all its users.  We, the Free Software Foundation,
+use the GNU General Public License for most of our software; it
+applies also to any other work released this way by its authors.  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
+them 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 prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you
+have certain responsibilities if you distribute copies of the
+software, or if you modify it: responsibilities to respect the freedom
+of others.
+
+For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  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.
+
+Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the
+manufacturer can do so.  This is fundamentally incompatible with the
+aim of protecting users' freedom to change the software.  The
+systematic pattern of such abuse occurs in the area of products for
+individuals to use, which is precisely where it is most unacceptable.
+Therefore, we have designed this version of the GPL to prohibit the
+practice for those products.  If such problems arise substantially in
+other domains, we stand ready to extend this provision to those
+domains in future versions of the GPL, as needed to protect the
+freedom of users.
+
+Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish
+to avoid the special danger that patents applied to a free program
+could make it effectively proprietary.  To prevent this, the GPL
+assures that patents cannot be used to render the program non-free.
+
+The precise terms and conditions for copying, distribution and
+modification follow.
+
+ at heading TERMS AND CONDITIONS
+
+ at enumerate 0
+ at item Definitions.
+
+``This License'' refers to version 3 of the GNU General Public License.
+
+``Copyright'' also means copyright-like laws that apply to other kinds
+of works, such as semiconductor masks.
+
+``The Program'' refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as ``you''.  ``Licensees'' and
+``recipients'' may be individuals or organizations.
+
+To ``modify'' a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of
+an exact copy.  The resulting work is called a ``modified version'' of
+the earlier work or a work ``based on'' the earlier work.
+
+A ``covered work'' means either the unmodified Program or a work based
+on the Program.
+
+To ``propagate'' a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+To ``convey'' a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user
+through a computer network, with no transfer of a copy, is not
+conveying.
+
+An interactive user interface displays ``Appropriate Legal Notices'' to
+the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ at item Source Code.
+
+The ``source code'' for a work means the preferred form of the work for
+making modifications to it.  ``Object code'' means any non-source form
+of a work.
+
+A ``Standard Interface'' means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+The ``System Libraries'' of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+``Major Component'', in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+The ``Corresponding Source'' for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+The Corresponding Source need not include anything that users can
+regenerate automatically from other parts of the Corresponding Source.
+
+The Corresponding Source for a work in source code form is that same
+work.
+
+ at item Basic Permissions.
+
+All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+You may make, run and propagate covered works that you do not convey,
+without conditions so long as your license otherwise remains in force.
+You may convey covered works to others for the sole purpose of having
+them make modifications exclusively for you, or provide you with
+facilities for running those works, provided that you comply with the
+terms of this License in conveying all material for which you do not
+control copyright.  Those thus making or running the covered works for
+you must do so exclusively on your behalf, under your direction and
+control, on terms that prohibit them from making any copies of your
+copyrighted material outside their relationship with you.
+
+Conveying under any other circumstances is permitted solely under the
+conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ at item Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such
+circumvention is effected by exercising rights under this License with
+respect to the covered work, and you disclaim any intention to limit
+operation or modification of the work as a means of enforcing, against
+the work's users, your or third parties' legal rights to forbid
+circumvention of technological measures.
+
+ at item Conveying Verbatim Copies.
+
+You may convey 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;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ at item Conveying Modified Source Versions.
+
+You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these
+conditions:
+
+ at enumerate a
+ at item
+The work must carry prominent notices stating that you modified it,
+and giving a relevant date.
+
+ at item
+The work must carry prominent notices stating that it is released
+under this License and any conditions added under section 7.  This
+requirement modifies the requirement in section 4 to ``keep intact all
+notices''.
+
+ at item
+You must license the entire work, as a whole, under this License to
+anyone who comes into possession of a copy.  This License will
+therefore apply, along with any applicable section 7 additional terms,
+to the whole of the work, and all its parts, regardless of how they
+are packaged.  This License gives no permission to license the work in
+any other way, but it does not invalidate such permission if you have
+separately received it.
+
+ at item
+If the work has interactive user interfaces, each must display
+Appropriate Legal Notices; however, if the Program has interactive
+interfaces that do not display Appropriate Legal Notices, your work
+need not make them do so.
+ at end enumerate
+
+A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+``aggregate'' if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ at item  Conveying Non-Source Forms.
+
+You may convey a covered work in object code form under the terms of
+sections 4 and 5, provided that you also convey the machine-readable
+Corresponding Source under the terms of this License, in one of these
+ways:
+
+ at enumerate a
+ at item
+Convey the object code in, or embodied in, a physical product
+(including a physical distribution medium), accompanied by the
+Corresponding Source fixed on a durable physical medium customarily
+used for software interchange.
+
+ at item
+Convey the object code in, or embodied in, a physical product
+(including a physical distribution medium), accompanied by a written
+offer, valid for at least three years and valid for as long as you
+offer spare parts or customer support for that product model, to give
+anyone who possesses the object code either (1) a copy of the
+Corresponding Source for all the software in the product that is
+covered by this License, on a durable physical medium customarily used
+for software interchange, for a price no more than your reasonable
+cost of physically performing this conveying of source, or (2) access
+to copy the Corresponding Source from a network server at no charge.
+
+ at item
+Convey individual copies of the object code with a copy of the written
+offer to provide the Corresponding Source.  This alternative is
+allowed only occasionally and noncommercially, and only if you
+received the object code with such an offer, in accord with subsection
+6b.
+
+ at item
+Convey the object code by offering access from a designated place
+(gratis or for a charge), and offer equivalent access to the
+Corresponding Source in the same way through the same place at no
+further charge.  You need not require recipients to copy the
+Corresponding Source along with the object code.  If the place to copy
+the object code is a network server, the Corresponding Source may be
+on a different server (operated by you or a third party) that supports
+equivalent copying facilities, provided you maintain clear directions
+next to the object code saying where to find the Corresponding Source.
+Regardless of what server hosts the Corresponding Source, you remain
+obligated to ensure that it is available for as long as needed to
+satisfy these requirements.
+
+ at item
+Convey the object code using peer-to-peer transmission, provided you
+inform other peers where the object code and Corresponding Source of
+the work are being offered to the general public at no charge under
+subsection 6d.
+
+ at end enumerate
+
+A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+A ``User Product'' is either (1) a ``consumer product'', which means any
+tangible personal property which is normally used for personal,
+family, or household purposes, or (2) anything designed or sold for
+incorporation into a dwelling.  In determining whether a product is a
+consumer product, doubtful cases shall be resolved in favor of
+coverage.  For a particular product received by a particular user,
+``normally used'' refers to a typical or common use of that class of
+product, regardless of the status of the particular user or of the way
+in which the particular user actually uses, or expects or is expected
+to use, the product.  A product is a consumer product regardless of
+whether the product has substantial commercial, industrial or
+non-consumer uses, unless such uses represent the only significant
+mode of use of the product.
+
+``Installation Information'' for a User Product means any methods,
+procedures, authorization keys, or other information required to
+install and execute modified versions of a covered work in that User
+Product from a modified version of its Corresponding Source.  The
+information must suffice to ensure that the continued functioning of
+the modified object code is in no case prevented or interfered with
+solely because modification has been made.
+
+If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or
+updates for a work that has been modified or installed by the
+recipient, or for the User Product in which it has been modified or
+installed.  Access to a network may be denied when the modification
+itself materially and adversely affects the operation of the network
+or violates the rules and protocols for communication across the
+network.
+
+Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ at item Additional Terms.
+
+``Additional permissions'' are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders
+of that material) supplement the terms of this License with terms:
+
+ at enumerate a
+ at item
+Disclaiming warranty or limiting liability differently from the terms
+of sections 15 and 16 of this License; or
+
+ at item
+Requiring preservation of specified reasonable legal notices or author
+attributions in that material or in the Appropriate Legal Notices
+displayed by works containing it; or
+
+ at item
+Prohibiting misrepresentation of the origin of that material, or
+requiring that modified versions of such material be marked in
+reasonable ways as different from the original version; or
+
+ at item
+Limiting the use for publicity purposes of names of licensors or
+authors of the material; or
+
+ at item
+Declining to grant rights under trademark law for use of some trade
+names, trademarks, or service marks; or
+
+ at item
+Requiring indemnification of licensors and authors of that material by
+anyone who conveys the material (or modified versions of it) with
+contractual assumptions of liability to the recipient, for any
+liability that these contractual assumptions directly impose on those
+licensors and authors.
+ at end enumerate
+
+All other non-permissive additional terms are considered ``further
+restrictions'' within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions; the
+above requirements apply either way.
+
+ at item Termination.
+
+You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+However, if you cease all violation of this License, then your license
+from a particular copyright holder is reinstated (a) provisionally,
+unless and until the copyright holder explicitly and finally
+terminates your license, and (b) permanently, if the copyright holder
+fails to notify you of the violation by some reasonable means prior to
+60 days after the cessation.
+
+Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ at item Acceptance Not Required for Having Copies.
+
+You are not required to accept this License in order to receive or run
+a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ at item Automatic Licensing of Downstream Recipients.
+
+Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+An ``entity transaction'' is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ at item Patents.
+
+A ``contributor'' is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's ``contributor version''.
+
+A contributor's ``essential patent claims'' are all patent claims owned
+or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, ``control'' includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+In the following three paragraphs, a ``patent license'' is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To ``grant'' such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  ``Knowingly relying'' means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+A patent license is ``discriminatory'' if it does not include within the
+scope of its coverage, prohibits the exercise of, or is conditioned on
+the non-exercise of one or more of the rights that are specifically
+granted under this License.  You may not convey a covered work if you
+are a party to an arrangement with a third party that is in the
+business of distributing software, under which you make payment to the
+third party based on the extent of your activity of conveying the
+work, and under which the third party grants, to any of the parties
+who would receive the covered work from you, a discriminatory patent
+license (a) in connection with copies of the covered work conveyed by
+you (or copies made from those copies), or (b) primarily for and in
+connection with specific products or compilations that contain the
+covered work, unless you entered into that arrangement, or that patent
+license was granted, prior to 28 March 2007.
+
+Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ at item No Surrender of Others' Freedom.
+
+If 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 convey
+a covered work so as to satisfy simultaneously your obligations under
+this License and any other pertinent obligations, then as a
+consequence you may not convey it at all.  For example, if you agree
+to terms that obligate you to collect a royalty for further conveying
+from those to whom you convey the Program, the only way you could
+satisfy both those terms and this License would be to refrain entirely
+from conveying the Program.
+
+ at item Use with the GNU Affero General Public License.
+
+Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ at item Revised Versions of this License.
+
+The Free Software Foundation may publish revised and/or new versions
+of the GNU 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 that a certain numbered version of the GNU General Public
+License ``or any later version'' applies to it, you have the option of
+following the terms and conditions either of that numbered version or
+of any later version published by the Free Software Foundation.  If
+the Program does not specify a version number of the GNU General
+Public License, you may choose any version ever published by the Free
+Software Foundation.
+
+If the Program specifies that a proxy can decide which future versions
+of the GNU General Public License can be used, that proxy's public
+statement of acceptance of a version permanently authorizes you to
+choose that version for the Program.
+
+Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ at item Disclaimer of Warranty.
+
+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.
+
+ at item Limitation of Liability.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR
+CONVEYS 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.
+
+ at item Interpretation of Sections 15 and 16.
+
+If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ at end enumerate
+
+ at heading END OF TERMS AND CONDITIONS
+
+ at heading 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
+state the exclusion of warranty; and each file should have at least
+the ``copyright'' line and a pointer to where the full notice is found.
+
+ at smallexample
+ at var{one line to give the program's name and a brief idea of what it does.}
+Copyright (C) @var{year} @var{name of author}
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see @url{http://www.gnu.org/licenses/}.
+ at end smallexample
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ at smallexample
+ at var{program} Copyright (C) @var{year} @var{name of author}
+This program comes with ABSOLUTELY NO WARRANTY; for details type @samp{show w}.
+This is free software, and you are welcome to redistribute it
+under certain conditions; type @samp{show c} for details.
+ at end smallexample
+
+The hypothetical commands @samp{show w} and @samp{show c} should show
+the appropriate parts of the General Public License.  Of course, your
+program's commands might be different; for a GUI interface, you would
+use an ``about box''.
+
+You should also get your employer (if you work as a programmer) or school,
+if any, to sign a ``copyright disclaimer'' for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+ at url{http://www.gnu.org/licenses/}.
+
+The GNU 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 Lesser General Public License instead of this License.  But
+first, please read @url{http://www.gnu.org/philosophy/why-not-lgpl.html}.
diff --git a/texinfo/gplv3-127x51.png b/texinfo/gplv3-127x51.png
new file mode 100644
index 0000000..fe37532
Binary files /dev/null and b/texinfo/gplv3-127x51.png differ
diff --git a/texinfo/index.html b/texinfo/index.html
new file mode 100644
index 0000000..ddffc89
--- /dev/null
+++ b/texinfo/index.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html lang="en-US">
+<head>
+	<meta charset="UTF-8">
+	<meta http-equiv="refresh" content="0;url=doc_en/Main.html">
+	<title>Page Redirection</title>
+</head>
+<body>
+	If you are not redirected automatically, follow the link to <a href='doc_en/Main.html'>English</a> or <a href='doc_ru/Main.html'>Russian</a> version.
+</body>
+</html>
\ No newline at end of file
diff --git a/texinfo/json.html b/texinfo/json.html
new file mode 100644
index 0000000..43bdc56
--- /dev/null
+++ b/texinfo/json.html
@@ -0,0 +1,124 @@
+<!DOCTYPE html>
+
+<html>
+
+<head>
+	<script type="text/javascript" src="mathgl.js"></script>
+<!--	<script type="text/javascript" src="inflate.min.js"></script>-->
+</head>
+
+<!-- Use "chromium-browser --disable-web-security json.html" for debug -->
+
+<body onload="main();">
+
+Select sample
+
+<select id="select" onchange="mglChange()">
+	<option value="alpha">alpha</option>
+	<option value="area">area</option>
+	<option value="aspect">aspect</option>
+	<option value="axial">axial</option>
+	<option value="axis">axis</option>
+	<option value="barh">barh</option>
+	<option value="bars">bars</option>
+	<option value="belt">belt</option>
+	<option value="box">box</option>
+	<option value="boxplot">boxplot</option>
+	<option value="boxs">boxs</option>
+	<option value="candle">candle</option>
+	<option value="chart">chart</option>
+	<option value="cloud">cloud</option>
+	<option value="colorbar">colorbar</option>
+	<option value="combined">combined</option>
+	<option value="cones">cones</option>
+	<option value="conta">conta</option>
+	<option value="contd">contd</option>
+	<option value="contfa">contfa</option>
+	<option value="contf">contf</option>
+	<option value="contf_xyz">contf_xyz</option>
+	<option value="cont">cont</option>
+	<option value="contv">contv</option>
+	<option value="cont_xyz">cont_xyz</option>
+	<option value="curvcoor">curvcoor</option>
+	<option value="cut">cut</option>
+	<option value="dat_diff">dat_diff</option>
+	<option value="dat_extra">dat_extra</option>
+	<option value="densa">densa</option>
+	<option value="dens">dens</option>
+	<option value="dens_xyz">dens_xyz</option>
+	<option value="dew">dew</option>
+	<option value="dots">dots</option>
+	<option value="error">error</option>
+	<option value="fall">fall</option>
+	<option value="fit">fit</option>
+	<option value="flow">flow</option>
+	<option value="fog">fog</option>
+	<option value="fonts">fonts</option>
+	<option value="grad">grad</option>
+	<option value="hist">hist</option>
+	<option value="inplot">inplot</option>
+	<option value="label">label</option>
+	<option value="legend">legend</option>
+	<option value="loglog">loglog</option>
+	<option value="map">map</option>
+	<option value="mark">mark</option>
+	<option value="mesh">mesh</option>
+	<option value="mirror">mirror</option>
+	<option value="molecule">molecule</option>
+	<option value="parser">parser</option>
+	<option value="pde">pde</option>
+	<option value="pipe">pipe</option>
+	<option value="plot">plot</option>
+	<option value="primitives">primitives</option>
+	<option value="projection5">projection5</option>
+	<option value="projection">projection</option>
+	<option value="qo2d">qo2d</option>
+	<option value="radar">radar</option>
+	<option value="region">region</option>
+	<option value="schemes">schemes</option>
+	<option value="several_light">several_light</option>
+	<option value="solve">solve</option>
+	<option value="stem">stem</option>
+	<option value="step">step</option>
+	<option value="stereo">stereo</option>
+	<option value="stfa">stfa</option>
+	<option value="style">style</option>
+	<option value="surf3a">surf3a</option>
+	<option value="surf3c">surf3c</option>
+	<option value="surf3">surf3</option>
+	<option value="surfa">surfa</option>
+	<option value="surfc">surfc</option>
+	<option value="surf">surf</option>
+	<option value="table">table</option>
+	<option value="tape">tape</option>
+	<option value="tens">tens</option>
+	<option value="ternary">ternary</option>
+	<option value="text">text</option>
+	<option value="textmark">textmark</option>
+	<option value="ticks">ticks</option>
+	<option value="tile">tile</option>
+	<option value="tiles">tiles</option>
+	<option value="torus">torus</option>
+	<option value="traj">traj</option>
+	<option value="triangulation">triangulation</option>
+	<option value="triplot">triplot</option>
+	<option value="tube">tube</option>
+	<option value="vecta">vecta</option>
+	<option value="vect">vect</option>
+	<option value="venn">venn</option>
+</select> 
+
+<p>You can use mouse with pressed left button for rotation; with pressed middle button for shift; mouse wheel for zoom in/out. Double click will restore original view.</p>
+<center>
+<canvas id="canvas" width="800" height="600"
+	style="border:1px solid #d3d3d3;" onmousemove="mglMouseMove(event)"
+	onmousedown="mglMouseDown(event)" onmouseup="mglMouseUp(event)"
+	onmouseout="mglMouseUp(event)" onmousewheel="mglMouseWheel(event)"
+	ondblclick="mglRestore(event)"></canvas>
+</center>
+
+<p id="time"></p>
+
+</body>
+
+</html>
diff --git a/texinfo/lgplv3-147x51.png b/texinfo/lgplv3-147x51.png
new file mode 100644
index 0000000..b7dc74d
Binary files /dev/null and b/texinfo/lgplv3-147x51.png differ
diff --git a/texinfo/mathgl.js b/texinfo/mathgl.js
new file mode 100644
index 0000000..b16a4a9
--- /dev/null
+++ b/texinfo/mathgl.js
@@ -0,0 +1,557 @@
+/***************************************************************************
+ * mathgl.js is part of Math Graphic Library
+ * Copyright (C) 2012 Alexey Balakin <balakin at appl.sci-nnov.ru>            *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+var obj;
+var ctx;
+var cw,ch;
+var deg = Math.PI/180;  //0.017453293;
+
+var main = function()
+{
+	ctx = document.getElementById("canvas").getContext("2d");
+	cw = document.getElementById("canvas").width;
+	ch = document.getElementById("canvas").height;
+	ctx.lineCap="round";	// global setting
+
+	mgl_init("json/alpha.json");
+//	mgl_init("json/alpha.jsonz");
+	var t1 = new Date();
+	mgl_draw_good(obj, ctx);
+//	draw_fast(obj, ctx);
+	var t2 = new Date();
+	document.getElementById("time").innerHTML = "Drawing time is "+(t2.getTime()-t1.getTime())+" ms. Number of primitives is "+obj.nprim+". Canvas size is "+obj.width+"*"+obj.height+" points.";
+};
+
+var mglChange = function()
+{
+	var name = document.getElementById("select").value;
+	mgl_init("json/"+name+".json");
+	var t1 = new Date();
+	ctx.clearRect(0,0,cw,ch);
+	mgl_draw_good(obj, ctx);
+//	draw_fast(obj, ctx);
+	var t2 = new Date();
+	document.getElementById("time").innerHTML = "Drawing time is "+(t2.getTime()-t1.getTime())+" ms. Number of primitives is "+obj.nprim;
+}
+
+// mouse handling functions
+var mglMouseUp = function()
+{	obj.button = 0;	obj.good = 0;
+	ctx.clearRect(0,0,cw,ch);
+	mgl_draw_good(obj, ctx);	}
+var mglMouseDown = function(event)
+{
+	obj.good = 1;
+	obj.mouseX = event.clientX;
+	obj.mouseY = event.clientY;
+	obj.button = event.button+1;
+}
+var mglMouseMove = function(event)
+{
+	var x = event.clientX-obj.mouseX;
+	var y = event.clientY-obj.mouseY;
+	switch(obj.button)
+	{
+	case 1: // rotate
+		mgl_rotate_down(obj, y*180/ch);
+		mgl_rotate_left(obj, x*180/cw);	break;
+	case 2: // shift
+		mgl_shift_down(obj, y/ch);
+		mgl_shift_right(obj, x/cw);		break;
+	case 3: // zoom
+		mgl_zoom_in(obj, Math.pow(1.003,x));	break;
+	 }
+	if(obj.button)
+	{
+		obj.mouseX += x;	obj.mouseY += y;
+		mgl_draw(obj, ctx);
+	}
+}
+var mglMouseWheel = function(event)
+{
+//	var e = window.event;
+	var d = event.wheelDelta? event.wheelDelta:event.detail*(-120);
+	mgl_zoom_in(obj, Math.pow(1.002,d));
+	mgl_draw(obj, ctx);
+}
+var mglRestore = function()
+{
+	mgl_restore(obj);
+	ctx.clearRect(0,0,cw,ch);
+	mgl_draw_good(obj,ctx);
+}
+
+// The function load data and set up rotation/zoom state
+var mgl_init = function(name)
+{
+	// now obtain JSON data
+	var req = new XMLHttpRequest(), txt;
+	req.open( "GET", name, false );
+	req.overrideMimeType('text\/plain; charset=x-user-defined');
+/*	req.responseType = "arraybuffer";
+	req.onload = function (oEvent) {
+		var arrayBuffer = req.response; // Note: not oReq.responseText
+		console.debug("arrayBuffer=",arrayBuffer);
+		if (arrayBuffer) {
+			var compressed = new Uint8Array(arrayBuffer);
+			console.debug("compressed=",compressed);
+//			var gunzip = new Zlib.Gunzip(compressed);
+//			txt = gunzip.decompress();
+			var inflate = new Zlib.Inflate(arrayBuffer);
+			txt = inflate.decompress();
+		}
+	};*/
+	req.send(null);
+//	if(name[name.length-1]!='z')
+		txt = req.responseText;
+// 	else
+// 	{
+// console.debug("compressed=",req.responseText);
+// 		var inflate = new Zlib.Inflate(req.responseText);
+// 		txt = inflate.decompress();
+// 	}
+	obj = JSON.parse(txt);
+
+	// copy original data for transformation
+	obj.pp = new Array();
+	for(var i=0;i<obj.npnts;i++)	// copy original data for transformation
+		obj.pp[i] = [obj.pnts[i][0],obj.pnts[i][1],obj.pnts[i][2]];
+	// and set other variables
+	obj.pf = 0;		// perspective should be |pf|<1
+	obj.z  = [0,1, 0,1];	// current zoom/shift
+	obj.tet= 0;		// current tet-angle for rotation
+	obj.phi= 0;		// current phi-angle for rotation
+	obj.bet= 0;		// current beta-angle for rotation
+	obj.button = 0;	// pressed mouse buttons (0-none, 1-left, 2-right)
+	obj.mouseX=0;	obj.mouseY=0;
+	obj.fast = 0;	obj.good = 0;
+	obj.dx = cw/obj.width;
+	obj.dy = ch/obj.height;
+}
+
+// Functions for rotation, shifting and zooming of the picture as whole
+// Basically it redefine obj properties by user-friendly manner
+var mgl_rotate_left = function(obj,val)	{	obj.tet += val; }
+var mgl_rotate_right = function(obj,val){	obj.tet -= val; }
+var mgl_rotate_up = function(obj,val)	{	obj.bet += val; }
+var mgl_rotate_down = function(obj,val)	{	obj.bet -= val; }
+var mgl_restore = function(obj)		// restore transformation state
+{	obj.tet=obj.phi=obj.bet=0;	obj.z=[0,1,0,1];	obj.pf=0;	}
+var mgl_perspective = function(obj,val) // add perspective, def.value=0.1
+{
+	var x = obj.pf/(1-obj.pf) + val;
+	obj.pf = x/(1+x);	// let use this formula for "smooth" changing
+}
+var mgl_zoom_in = function(obj,factor)		// zoom in picture
+{	if(factor)	mgl_zoom_out(obj,1/factor);	}
+var mgl_zoom_out = function(obj,factor)	// zoom out picture
+{
+	var d, c;
+	d=(obj.z[3]-obj.z[2])*factor/2; c=(obj.z[3]+obj.z[2])/2;
+	obj.z[2] = c-d; obj.z[3] = c+d;
+	d=(obj.z[1]-obj.z[0])*factor/2; c=(obj.z[1]+obj.z[0])/2;
+	obj.z[0] = c-d; obj.z[1] = c+d;
+}
+var mgl_shift_up = function(obj,val)	// shift up
+{	mgl_shift_down(obj,-val);	}
+var mgl_shift_down = function(obj,val)	// shift down
+{
+	var d=val/(obj.z[3]-obj.z[2]);
+	obj.z[2] -= d; obj.z[3] -= d;
+}
+var mgl_shift_left = function(obj,val)	// shift left
+{	mgl_shift_right(obj,-val);	}
+var mgl_shift_right = function(obj,val)	// shift right
+{
+	var d=val/(obj.z[1]-obj.z[0]);
+	obj.z[0] -= d; obj.z[1] -= d;
+}
+
+// This function make drawing itself
+var mgl_draw = function(obj, ctx)
+{
+	ctx.clearRect(0,0,cw,ch);
+	if(obj.good==0)
+	{
+		obj.good = 1;
+		setTimeout(function(){mgl_draw_good(obj, ctx);},300);
+	}
+	else if(obj.fast==0)
+	{
+		obj.fast = 1;
+		setTimeout(function(){mgl_draw_fast(obj, ctx);},0);
+	}
+/*	var t1 = new Date();
+	draw_good(obj, ctx);
+//	draw_fast(obj, ctx);
+	var t2 = new Date();
+	console.debug("execution time is ", t2.getTime()-t1.getTime());*/
+}
+
+
+// This function make fast drawing
+var mgl_draw_fast = function(obj, ctx, skip)
+{
+	if(obj.fast==0)	return;
+	mgl_prepare(obj,skip);	// update coordinates
+	// for each primitive skipping superfluous
+	for(var i=0;i<obj.nprim;i ++)
+	{
+		var prim = obj.prim[i];
+		var n1 = prim[1], nn = obj.pp[n1];
+		if(prim[0]==1 || obj.pnts[n1][3]<0)
+			mgl_draw_prim(obj,ctx,prim,Math.abs(obj.b[12]));
+		else if(obj.prim[i][0]<4)
+		{
+			ctx.fillStyle = obj.prim[i][10];
+			ctx.fillRect(nn[0], nn[1], 2, 2);
+		}
+	}
+	obj.fast = 0;
+}
+
+// This function make high-quality drawing
+var mgl_draw_good = function(obj, ctx, skip)
+{
+	obj.fast = 0;
+	mgl_prepare(obj,skip);	// update coordinates
+	// NOTE: this valid only for current zoom/view. In general case it should be more complicated
+	var s1 = Math.sqrt(obj.b[0]*obj.b[0]+obj.b[1]*obj.b[1]+obj.b[2]*obj.b[2]), s2 = Math.abs(obj.b[12]);
+	for(var i=0;i<obj.nprim;i++)	// for each primitive
+	{
+		var prim = obj.prim[i];
+		mgl_draw_prim(obj,ctx,prim,obj.pnts[prim[1]][3]<0?s2:s1);
+	}
+	obj.good = 0;
+}
+
+/** perform high-quality drawing */
+var mgl_draw_prim = function(obj, ctx, prim, scl)
+{
+	var n1 = prim[1], n2 = prim[2];
+	var n3 = prim[3], n4 = prim[4];
+	var pp = obj.pp;
+	var deg = Math.PI/180;  //0.017453293;
+
+	ctx.strokeStyle = prim[10];
+	ctx.fillStyle = prim[10];
+	ctx.lineWidth = 1;
+	switch(prim[0])		// draw it depending on its type
+	{
+	case 0: // marks
+		ctx.lineWidth = prim[7]*prim[6]*5e-4;
+		mgl_draw_mark(ctx, obj.pp[n1][0], obj.pp[n1][1], n4, prim[6]/100, scl);
+		break;
+	case 1: // lines
+		ctx.beginPath();
+		ctx.moveTo(obj.pp[n1][0],obj.pp[n1][1]);
+		ctx.lineTo(obj.pp[n2][0],obj.pp[n2][1]);
+		ctx.lineWidth = prim[7]/100;
+		ctx.stroke();	break;
+	case 2: // triangles
+		ctx.beginPath();
+		ctx.moveTo(obj.pp[n1][0],obj.pp[n1][1]);
+		ctx.lineTo(obj.pp[n2][0],obj.pp[n2][1]);
+		ctx.lineTo(obj.pp[n3][0],obj.pp[n3][1]);
+		ctx.closePath();	ctx.fill();	break;
+	case 3: // quadrangles
+		ctx.beginPath();
+		ctx.moveTo(obj.pp[n1][0],obj.pp[n1][1]);
+		ctx.lineTo(obj.pp[n2][0],obj.pp[n2][1]);
+		ctx.lineTo(obj.pp[n4][0],obj.pp[n4][1]);
+		ctx.lineTo(obj.pp[n3][0],obj.pp[n3][1]);
+		ctx.closePath();
+		// NOTE: look as alpha is disabled for lines
+		// So, next code should be only for the case alpha=false
+		if(prim[10].charAt(0)=='#')	ctx.stroke();
+		ctx.fill();	break;
+	case 4: // glyphs
+		var t=prim[7]*deg/100;
+		var xx=obj.coor[n2][2]/100,yy=-obj.coor[n2][3]/100,zz=obj.coor[n2][4]/100;
+		var xc = obj.b[0]*xx + obj.b[1]*yy + obj.b[2]*zz;
+		var yc = obj.b[3]*xx + obj.b[4]*yy + obj.b[5]*zz;
+		var zc = obj.b[6]*xx + obj.b[7]*yy + obj.b[8]*zz;
+
+		var dv = (1-obj.pf/1.37)/(1-obj.pf*obj.pp[i][2]/obj.depth);
+		var cv = obj.pf/(1-obj.pf/1.37)/obj.depth;
+		xc += (obj.pp[n1][0]-obj.b[9])*zc*cv;//*dv;
+		yc += (obj.pp[n1][1]-obj.b[10])*zc*cv;//*dv;
+		if(obj.pnts[n1][3]<0)	{	xc=xx;	yc=yy;	}
+
+		var ll = xc*xc+yc*yc;
+		if(ll < 1e-10)	break;
+		if(ll<1e10 && t/deg<1e4)
+		{
+			t = Math.atan2(yc,xc);
+			if(Math.abs(t)>Math.PI/2)	t += Math.PI;
+		}
+		else t=0;
+		var c=Math.cos(t), s=Math.sin(t), d=prim[6]/200;
+
+		var b=[d*c, d*s, d*s, -d*c, obj.pp[n1][0],obj.pp[n1][1]];
+		var x=obj.coor[n2][0]*scl/100, y=obj.coor[n2][1]*scl/100, f=prim[8]*scl/1e5;
+		if(n3&8)
+		{
+			if(!(n3&4))	mgl_line_glyph(ctx, x,y, f,1,b);
+			else	mgl_line_glyph(ctx, x,y, f,0,b);
+		}
+		else
+		{
+			if(!(n3&4)) mgl_fill_glyph(ctx, x,y, f,obj.glfs[n4],b);
+			else	mgl_wire_glyph(ctx, x,y, f,obj.glfs[n4],b);
+		}
+		break;
+	}
+}
+
+// This function change coordinates according current transformations
+// Usually this Function is called internally by draw()
+var mgl_prepare = function(obj, skip)
+{
+	// fill transformation matrix
+	if(!skip)
+	{
+		var dx = 1/Math.abs(obj.z[1]-obj.z[0]);
+		var dy = 1/Math.abs(obj.z[3]-obj.z[2]);
+		var cx=Math.cos(obj.tet*deg), sx=Math.sin(obj.tet*deg);	// tetx
+		var cy=Math.cos(obj.phi*deg), sy=Math.sin(obj.phi*deg);	// tety
+		var cz=Math.cos(obj.bet*deg), sz=Math.sin(obj.bet*deg);	// tetz
+		obj.b = [obj.dx*dx*cx*cy, -obj.dx*dx*cy*sx, obj.dx*dx*sy,
+				obj.dy*dy*(cx*sy*sz+cz*sx), obj.dy*dy*(cx*cz-sx*sy*sz), -obj.dy*dy*cy*sz,
+				sx*sz-cx*cz*sy, cx*sz+cz*sx*sy, cy*cz,
+				cw/2*(1+dx-obj.z[1]-obj.z[0])/dx,
+				ch/2*(1+dy-obj.z[3]-obj.z[2])/dy, obj.depth/2, obj.dx*dx,obj.dy*dy,1];
+	}
+	// now transform points for found transformation matrix
+	var b = obj.b, i;
+	for(i=0;i<obj.npnts;i++)
+	{
+		var x = obj.pnts[i][0]-obj.width/2;
+		var y = obj.pnts[i][1]-obj.height/2;
+		var z = obj.pnts[i][2]-obj.depth/2;
+		if(obj.pnts[i][3]>=0)	// TODO: check later when mglInPlot will be ready
+			obj.pp[i] = [b[9]  + b[0]*x + b[1]*y + b[2]*z,
+						b[10] + b[3]*x + b[4]*y + b[5]*z,
+						b[11] + b[6]*x + b[7]*y + b[8]*z];
+		else
+			obj.pp[i] = [b[9]+b[12]*x,b[10]+b[13]*y,b[11]+b[14]*z];
+	}
+	if(obj.pf)	for(var i=0;i<obj.npnts;i++)	// perspective
+	{	// NOTE: it is not supported for coordinate determining now
+		var d = (1-obj.pf/1.37)/(1-obj.pf*obj.pp[i][2]/obj.depth);
+		if(obj.pnts[i][3]>=0)	// TODO: check later when mglInPlot will be ready
+		{
+			obj.pp[i][0] = d*obj.pp[i][0] + (1-d)/2*obj.width;
+			obj.pp[i][1] = d*obj.pp[i][1] + (1-d)/2*obj.height;
+		}
+	}
+	// fill z-coordinates for primitives
+	if(!obj.fast)
+	{
+		for(i=0;i<obj.nprim;i++)
+		{
+			var n1 = obj.prim[i][1], n2 = obj.prim[i][2], n3 = obj.prim[i][3], n4 = obj.prim[i][4];
+			switch(obj.prim[i][0])
+			{
+			case 1: // lines
+				obj.prim[i][9] = (obj.pp[n1][2]+obj.pp[n2][2])/2;	break;
+			case 2: // triangles
+				obj.prim[i][9] = (obj.pp[n1][2]+obj.pp[n2][2]+obj.pp[n3][2])/3;	break;
+			case 3: // quadrangles
+				obj.prim[i][9] = (obj.pp[n1][2]+obj.pp[n2][2]+obj.pp[n3][2]+obj.pp[n4][2])/4;	break;
+			default:
+				obj.prim[i][9] = obj.pp[n1][2];	break;
+			}
+		}
+		obj.prim.sort(mgl_cmp);	// more accurate sorting
+	}
+}
+
+var mgl_cmp = function(a,b)
+{
+	var tt = [0,2,4,5, 1,3,6, 7];
+	if(a[9]!=b[9])	return a[9] - b[9];
+	if(a[0]!=b[0])	return tt[b[0]]-tt[a[0]];
+	if(a[8]!=b[8])	return a[8] - b[8];
+	return a[3]-b[3];
+}
+
+// Function for drawing markers of type st with given size at position {x,y}
+// Usually this function is called internally, but it can be called by user as well
+var mgl_draw_mark = function(ctx,x,y,st,size,d)
+{
+	if(size<=0) {	st = 46;	size=1; }
+	var s = size*d;
+	ctx.beginPath();
+	switch(st)
+	{
+	case 111:	// 'o'
+		ctx.arc(x,y,s,0,Math.PI*2);	 ctx.stroke();	break;
+	case 79:	// 'O'
+		ctx.arc(x,y,s,0,Math.PI*2);	 ctx.fill();	 break;
+	case 67:	// 'C'
+		ctx.arc(x,y,s,0,Math.PI*2);	 ctx.stroke();
+		ctx.arc(x,y,0.1*s,0,Math.PI*2); ctx.fill();	 break;
+	case 80:	// 'P'
+		ctx.moveTo(x-s,y-s);	ctx.lineTo(x+s,y-s);
+		ctx.lineTo(x+s,y+s);	ctx.lineTo(x-s,y+s);	ctx.lineTo(x-s,y-s);
+		ctx.moveTo(x-s,y);		ctx.lineTo(x+s,y);
+		ctx.moveTo(x,y-s);		ctx.lineTo(x,y+s);
+		ctx.stroke();	break;
+	case 43:	// '+'
+		ctx.moveTo(x-s,y);		ctx.lineTo(x+s,y);
+		ctx.moveTo(x,y-s);		ctx.lineTo(x,y+s);
+		ctx.stroke();	break;
+	case 88:	// 'X'
+		ctx.moveTo(x-s,y-s);	ctx.lineTo(x+s,y-s);
+		ctx.lineTo(x+s,y+s);	ctx.lineTo(x-s,y+s);	ctx.lineTo(x-s,y-s);
+		ctx.moveTo(x-s,y-s);	ctx.lineTo(x+s,y+s);
+		ctx.moveTo(x+s,y-s);	ctx.lineTo(x-s,y+s);
+		ctx.stroke();	break;
+	case 120:	// 'x'
+		ctx.moveTo(x-s,y-s);	ctx.lineTo(x+s,y+s);
+		ctx.moveTo(x+s,y-s);	ctx.lineTo(x-s,y+s);
+		ctx.stroke();	break;
+	case 115:	// 's'
+		ctx.moveTo(x-s,y-s);	ctx.lineTo(x+s,y-s);
+		ctx.lineTo(x+s,y+s);	ctx.lineTo(x-s,y+s);
+		ctx.closePath();		ctx.stroke();	break;
+	case 83:	// 'S'
+		ctx.moveTo(x-s,y-s);	ctx.lineTo(x+s,y-s);
+		ctx.lineTo(x+s,y+s);	ctx.lineTo(x-s,y+s);
+		ctx.closePath();		ctx.fill();	 break;
+	case 100:	// 'd'
+		ctx.moveTo(x-s,y);		ctx.lineTo(x,y-s);
+		ctx.lineTo(x+s,y);		ctx.lineTo(x,y+s);
+		ctx.closePath();		ctx.stroke();	break;
+	case 68:	// 'D'
+		ctx.moveTo(x-s,y);		ctx.lineTo(x,y-s);
+		ctx.lineTo(x+s,y);		ctx.lineTo(x,y+s);
+		ctx.closePath();		ctx.fill();	 break;
+	case 42:	// '*'
+		ctx.moveTo(x-s,y);		ctx.lineTo(x+s,y);
+		ctx.moveTo(x-0.6*s,y-0.8*s);	ctx.lineTo(x+0.6*s,y+0.8*s);
+		ctx.moveTo(x+0.6*s,y-0.8*s);	ctx.lineTo(x-0.6*s,y+0.8*s);
+		ctx.stroke();	break;
+	case 89:	// 'Y'
+		ctx.moveTo(x,y-s);		ctx.lineTo(x,y);
+		ctx.moveTo(x-0.8*s,y+0.6*s);	ctx.lineTo(x,y);
+		ctx.moveTo(x+0.8*s,y+0.6*s);	ctx.lineTo(x,y);
+		ctx.stroke();	break;
+	case 86:	// 'T'
+		ctx.moveTo(x-s,y-s/2);	ctx.lineTo(x+s,y-s/2);
+		ctx.lineTo(x,y+s);		ctx.closePath();
+		ctx.fill();	 break;
+	case 118:	// '^'
+		ctx.moveTo(x-s,y-s/2);	ctx.lineTo(x+s,y-s/2);
+		ctx.lineTo(x,y+s);		ctx.closePath();
+		ctx.stroke();	break;
+	case 84:	// 'V'
+		ctx.moveTo(x-s,y+s/2);	ctx.lineTo(x+s,y+s/2);
+		ctx.lineTo(x,y-s);		ctx.closePath();
+		ctx.fill();	 break;
+	case 94:	// 'v'
+		ctx.moveTo(x-s,y+s/2);	ctx.lineTo(x+s,y+s/2);
+		ctx.lineTo(x,y-s);		ctx.closePath();
+		ctx.stroke();	break;
+	case 76:	// 'L'
+		ctx.moveTo(x+s/2,y-s);	ctx.lineTo(x+s/2,y+s);
+		ctx.lineTo(x-s,y);		ctx.closePath();
+		ctx.fill();	 break;
+	case 60:	// '<'
+		ctx.moveTo(x+s/2,y-s);	ctx.lineTo(x+s/2,y+s);
+		ctx.lineTo(x-s,y);		ctx.closePath();
+		ctx.stroke();	break;
+	case 82:	// 'R'
+		ctx.moveTo(x-s/2,y-s);	ctx.lineTo(x-s/2,y+s);
+		ctx.lineTo(x+s,y);		ctx.closePath();
+		ctx.fill();	 break;
+	case 62:	// '>'
+		ctx.moveTo(x-s/2,y-s);	ctx.lineTo(x-s/2,y+s);
+		ctx.lineTo(x+s,y);		ctx.closePath();
+		ctx.stroke();	break;
+//	case 46:	// '.'
+	default:
+		ctx.rect(x,y,1,1); ctx.fill();	 break;
+	}
+}
+
+// This function for internal use only!!!
+var mgl_fill_glyph = function(ctx, x,y, f,g,b)
+{
+	var xx,yy,j;
+	var np=0;	ctx.beginPath();
+	for(j=0;j<g[0];j++)
+	{
+		xx = g[1][2*j]; yy = g[1][2*j+1];
+		if(xx==16383 && yy==16383)
+		{
+			ctx.closePath();	np = 1;
+		}
+		else if(np)
+		{
+			xx = x+f*xx;	yy = y+f*yy;	np = 0;
+			ctx.moveTo(b[4]+b[0]*xx+b[1]*yy, b[5]+b[2]*xx+b[3]*yy);
+		}
+		else
+		{
+			xx = x+f*xx;	yy = y+f*yy;
+			ctx.lineTo(b[4]+b[0]*xx+b[1]*yy, b[5]+b[2]*xx+b[3]*yy);
+		}
+	}
+	ctx.closePath();	ctx.fill('evenodd');
+}
+// This function for internal use only!!!
+var mgl_wire_glyph = function(ctx, x,y, f,g,b)
+{
+	var xx,yy,j;
+	var np=0;	ctx.beginPath();
+	for(j=0;j<g[0];j++)
+	{
+		xx = g[1][2*j]; yy = g[1][2*j+1];
+		if(xx==16383 && yy==16383)
+		{
+			ctx.closePath();	np = 1;
+		}
+		else if(np)
+		{
+			xx = x+f*xx;	yy = y+f*yy;	np = 0;
+			ctx.moveTo(b[4]+b[0]*xx+b[1]*yy, b[5]+b[2]*xx+b[3]*yy);
+		}
+		else
+		{
+			xx = x+f*xx;	yy = y+f*yy;
+			ctx.lineTo(b[4]+b[0]*xx+b[1]*yy, b[5]+b[2]*xx+b[3]*yy);
+		}
+	}
+	ctx.closePath();	ctx.stroke();
+}
+// This function for internal use only!!!
+var mgl_line_glyph = function(ctx, x,y, f,solid,b)
+{
+	var xx,yy,j,xs,ys;
+	var dy = 0.004;
+	ctx.moveTo(b[4]+b[0]*x+b[1]*(y-dy), b[5]+b[2]*x+b[3]*(y-dy));
+	ctx.lineTo(b[4]+b[0]*x+b[1]*(y+dy), b[5]+b[2]*x+b[3]*(y+dy));
+	ctx.lineTo(b[4]+b[0]*(x+f)+b[1]*(y+dy), b[5]+b[2]*(x+f)+b[3]*(y+dy));
+	ctx.lineTo(b[4]+b[0]*(x+f)+b[1]*(y-dy), b[5]+b[2]*(x+f)+b[3]*(y-dy));
+	ctx.closePath();
+	if(solid)	ctx.fill();
+	else		ctx.stroke();
+}
diff --git a/texinfo/mathgl.texi b/texinfo/mathgl.texi
new file mode 100644
index 0000000..e69de29
diff --git a/texinfo/mathgl_en.texi b/texinfo/mathgl_en.texi
new file mode 100644
index 0000000..63e269a
--- /dev/null
+++ b/texinfo/mathgl_en.texi
@@ -0,0 +1,153 @@
+\input texinfo
+ at documentencoding UTF-8
+ at documentlanguage en
+
+ at setfilename mathgl_en.info
+ at include version.texi
+ at settitle MathGL @value{VERSION}
+ at syncodeindex pg cp
+ at comment %**end of header
+
+ at copying
+This manual is for MathGL (version @value{VERSION}), a collection of classes and routines for scientific plotting. Please report any errors in this manual to @email{mathgl.abalakin@@gmail.org}.
+
+ at include copyright.texi
+ at end copying
+
+ at dircategory MathGL documentation system
+ at direntry
+* MathGL: (mathgl). The library for scientific graphics.
+ at end direntry
+
+ at titlepage
+ at title MathGL
+ at subtitle for version @value{VERSION}
+ at author A.A. Balakin (@uref{http://mathgl.sourceforge.net/})
+ at page
+ at vskip 0pt plus 1filll
+ at insertcopying
+ at end titlepage
+
+ at contents
+
+ at ifnottex
+ at node Top
+ at top MathGL
+
+This file documents the Mathematical Graphic Library (MathGL), a collection of classes and routines for scientific plotting. It corresponds to release @value{VERSION} of the library. Please report any errors in this manual to @email{mathgl.abalakin@@gmail.org}. More information about MathGL can be found at the project homepage, @uref{http://mathgl.sourceforge.net/}.
+
+ at include copyright.texi
+
+ at end ifnottex
+
+ at menu
+* Overview::
+* Examples::
+* General concepts::
+* MathGL core::
+* Widget classes::
+* Data processing::
+* MGL scripts::
+* UDAV::
+* Other classes::
+* Symbols and hot-keys::
+* File formats::
+ at ifhtml
+* TeX-like symbols::
+ at end ifhtml
+* Plotting time::
+* Copying This Manual::
+* Index::
+ at end menu
+
+ at macro external {}
+ at end macro
+ at macro nav {}
+ at end macro
+
+ at macro fig {fname,text}
+ at center @image{\fname\, 11cm, , \text\, png}
+ at end macro
+ at macro pfig {fname,text}
+ at center @image{png/\fname\, 11cm, , \text\, png}
+ at c @center @image{../png/\fname\, 11cm, , \text\. See also @uref{../pdf/\fname\.pdf, U3D PDF} sample, .png}
+ at end macro
+ at macro ufig {fname,width,text}
+ at center @image{udav/\fname\, \width\cm, , \text\, png}
+ at end macro
+
+ at macro sref {arg}
+ at xref{\arg\}, for sample code and picture.
+ at end macro
+
+ at node Overview, Examples, Top, Top
+ at include overview_en.texi
+
+ at node Examples, General concepts, Overview, Top
+ at include example_en.texi
+
+ at node General concepts, MathGL core, Examples, Top
+ at include concept_en.texi
+
+ at node MathGL core, Widget classes, General concepts, Top
+ at include core_en.texi
+
+ at node Widget classes, Data processing, MathGL core, Top
+ at include widget_en.texi
+
+ at node Data processing, MGL scripts, Widget classes, Top
+ at include data_en.texi
+
+ at node MGL scripts, UDAV, Data processing, Top
+ at include parse_en.texi
+
+ at node UDAV, Other classes, MGL scripts, Top
+ at include udav_en.texi
+
+ at node Other classes, Symbols and hot-keys, UDAV, Top
+ at include other_en.texi
+
+ at node Symbols and hot-keys, File formats, Other classes, Top
+ at appendix Symbols and hot-keys
+ at include symbols_en.texi
+
+ at node File formats, Plotting time, Symbols and hot-keys, Top
+ at appendix File formats
+ at include formats_en.texi
+
+ at ifhtml
+ at node Plotting time, TeX-like symbols, File formats, Top
+ at end ifhtml
+ at ifnothtml
+ at node Plotting time, Copying This Manual, File formats, Top
+ at end ifnothtml
+ at appendix Plotting time
+
+Table below show plotting time in seconds for all samples in file @uref{http://sourceforge.net/p/mathgl/code/HEAD/tree/mathgl-2x/examples/samples.cpp, examples/samples.cpp}. The test was done in my laptop (i5-2430M) with 64-bit Debian.
+
+Few words about the speed. Firstly, direct bitmap drawing (Quality=4,5,6) is faster than buffered one (Quality=0,1,2), but sometimes it give incorrect result (see @ref{cloud}) and don't allow to export in vector or 3d formats (like EPS, SVG, PDF ...). Secondly, lower quality is faster than high one generally, i.e. Quality=1 is faster than Quality=2, and Quality=0 is faster than Quality=1. However, if plot contain a lot of faces (like @ref{cloud}, @ref{surf3}, @ref{pipe}, @ref{dew}) then  [...]
+
+Results for image size 800*600 (default one).
+ at include time.texi
+
+Results for image size 1920*1440 (print quality)
+ at include time_big.texi
+
+ at ifhtml
+ at node TeX-like symbols, Copying This Manual, Plotting time, Top
+ at appendix TeX-like symbols
+ at include appendix_en.texi
+ at node Copying This Manual, Index, TeX-like symbols, Top
+ at end ifhtml
+ at ifnothtml
+ at node Copying This Manual, Index, Plotting time, Top
+ at end ifnothtml
+ at appendix GNU Free Documentation License
+ at include fdl.texi
+
+ at node Index, , Copying This Manual, Top
+ at unnumbered Index
+
+ at printindex cp
+
+ at bye
diff --git a/texinfo/mathgl_ru.texi b/texinfo/mathgl_ru.texi
new file mode 100644
index 0000000..078911f
--- /dev/null
+++ b/texinfo/mathgl_ru.texi
@@ -0,0 +1,152 @@
+\input texinfo
+ at c @documentencoding UTF-8
+ at documentlanguage ru
+
+ at setfilename mathgl_ru.info
+ at documentencoding UTF-8
+ at include version.texi
+ at settitle MathGL @value{VERSION}
+ at syncodeindex pg cp
+
+ at copying
+Это документация для MathGL (версии @value{VERSION}) -- библиотеки классов и функций для построения научной графики. Пожалуйста сообщайте о любых ошибках в этом руководстве на @email{mathgl.abalakin@@gmail.org}.
+
+ at include copyright.texi
+ at end copying
+
+ at dircategory MathGL documentation system
+ at direntry
+* MathGL: (mathgl). The library for scientific graphics.
+ at end direntry
+
+ at titlepage
+ at title MathGL
+ at subtitle версия @value{VERSION}
+ at author А.А. Балакин (@uref{http://mathgl.sourceforge.net/})
+ at page
+ at vskip 0pt plus 1filll
+ at insertcopying
+ at end titlepage
+
+ at contents
+
+ at ifnottex
+ at node Top
+ at top MathGL
+
+Это документация для MathGL (версии @value{VERSION}) -- библиотеки классов и функций для построения научной графики. Пожалуйста сообщайте о любых ошибках в этом руководстве на @email{mathgl.abalakin@@gmail.org}. Дополнительную информацию о MathGL можно найти на домашней странице проекта @uref{http://mathgl.sourceforge.net/}.
+
+ at include copyright.texi
+
+ at end ifnottex
+
+ at menu
+* Overview::
+* Examples::
+* General concepts::
+* MathGL core::
+* Widget classes::
+* Data processing::
+* MGL scripts::
+* UDAV::
+* Other classes::
+* Symbols and hot-keys::
+* File formats::
+ at ifhtml
+* TeX-like symbols::
+ at end ifhtml
+* Plotting time::
+* Copying This Manual::
+* Index::
+ at end menu
+
+ at macro external {}
+ at end macro
+ at macro nav {}
+ at end macro
+
+ at macro fig {fname,text}
+ at center @image{\fname\, 11cm, , \text\, png}
+ at end macro
+ at macro pfig {fname,text}
+ at center @image{png/\fname\, 11cm, , \text\, png}
+ at end macro
+ at macro ufig {fname,width,text}
+ at center @image{udav/\fname\, \width\cm, , \text\, png}
+ at end macro
+
+ at macro sref {arg}
+См. раздел @ref{\arg\}, для примеров кода и графика.
+ at end macro
+
+ at node Overview, Examples, Top, Top
+ at include overview_ru.texi
+
+ at node Examples, General concepts, Overview, Top
+ at include example_ru.texi
+
+ at node General concepts, MathGL core, Examples, Top
+ at include concept_ru.texi
+
+ at node MathGL core, Widget classes, General concepts, Top
+ at include core_ru.texi
+
+ at node Widget classes, Data processing, MathGL core, Top
+ at include widget_ru.texi
+
+ at node Data processing, MGL scripts, Widget classes, Top
+ at include data_ru.texi
+
+ at node MGL scripts, UDAV, Data processing, Top
+ at include parse_ru.texi
+
+ at node UDAV, Other classes, MGL scripts, Top
+ at include udav_ru.texi
+
+ at node Other classes, Symbols and hot-keys, UDAV, Top
+ at include other_ru.texi
+
+ at node Symbols and hot-keys, File formats, Other classes, Top
+ at appendix Symbols and hot-keys
+ at include symbols_ru.texi
+
+ at node File formats, Plotting time, Symbols and hot-keys, Top
+ at appendix File formats
+ at include formats_ru.texi
+
+ at ifhtml
+ at node Plotting time, TeX-like symbols, File formats, Top
+ at end ifhtml
+ at ifnothtml
+ at node Plotting time, Copying This Manual, File formats, Top
+ at end ifnothtml
+ at appendix Время отрисовки
+
+В таблице показаны времена создания графика для всех примеров из файла @uref{http://sourceforge.net/p/mathgl/code/HEAD/tree/mathgl-2x/examples/samples.cpp, examples/samples.cpp}. Тест выполнен на моем ноутбуке (i5-2430M) с 64-bit Debian.
+
+Несколько слов о скорости. Во-первых, прямое рисование в память (Quality=4,5,6) быстрее буферизованного (Quality=0,1,2), но иногда результат некоректен (см. @ref{cloud}) и пропадает возможность экспорта в векторные и 3d форматы (например, EPS, SVG, PDF, ...). Во-вторых, обычно картинка худшего качества рисуется быстрее, т.е. Quality=1 быстрее Quality=2, и Quality=0 быстрее Quality=1. Однако, если график содержит множество граней (например @ref{cloud}, @ref{surf3}, @ref{pipe}, @ref{dew}), [...]
+
+Результаты для изображения размером 800*600 (по умолчанию).
+ at include time.texi
+
+Результаты для изображения размером 1920*1440 (для печати)
+ at include time_big.texi
+
+ at ifhtml
+ at node TeX-like symbols, Copying This Manual, Plotting time, Top
+ at appendix Символы TeX
+ at include appendix_en.texi
+ at node Copying This Manual, Index, TeX-like symbols, Top
+ at end ifhtml
+ at ifnothtml
+ at node Copying This Manual, Index, Plotting time, Top
+ at end ifnothtml
+ at appendix GNU Free Documentation License
+ at include fdl.texi
+
+ at node Index, , Copying This Manual, Top
+ at unnumbered Индекс
+
+ at printindex cp
+
+ at bye
diff --git a/texinfo/mgl.5 b/texinfo/mgl.5
new file mode 100644
index 0000000..e359a7d
--- /dev/null
+++ b/texinfo/mgl.5
@@ -0,0 +1,18 @@
+.\" Process this file with
+.\" groff -man -Tascii mgl.5
+.\"
+.TH MGL 5 "MARCH 2012" MathGL "User Manuals"
+.SH NAME
+MGL \- MathGL script.
+.SH DESCRIPTION
+.B MGL
+script is textual file which contain commands for making scientific graphics using MathGL library. Is is primarily designed for quick viewing or processing data files as well as produce high-quality plots as output. MGL support animation by defining special comments in file.
+
+For a full description of MGL script language please see the MathGL manual.
+.SH AVAILABILITY
+http://mathgl.sourceforge.net/
+.SH AUTHOR
+Alexey Balakin http://mathgl.sourceforge.net/
+.SH "SEE ALSO"
+.BR mglview (1),
+.BR mglconv (1)
diff --git a/texinfo/mgl.cgi.1 b/texinfo/mgl.cgi.1
new file mode 100644
index 0000000..c251ecc
--- /dev/null
+++ b/texinfo/mgl.cgi.1
@@ -0,0 +1,17 @@
+.\" Process this file with
+.\" groff -man -Tascii mgl.cgi.1
+.\"
+.TH MGLCONV 1 "APRIL 2013" MathGL "User Manuals"
+.SH NAME
+mgl.cgi \- Execute MathGL scripts to produce PNG image.
+.SH SYNOPSIS
+.B mgl.cgi
+[CGI_of_MGL]
+.SH DESCRIPTION
+.B mgl.cgi
+reads CGI query with MGL script from standard input and put resulting PNG image into standard output.
+.SH AUTHOR
+mgl.cgi was written by Alexey Balakin, http://mathgl.sourceforge.net/
+.SH "SEE ALSO"
+.BR mglview (1),
+.BR mgl (5)
diff --git a/texinfo/mgl_en.texi b/texinfo/mgl_en.texi
new file mode 100644
index 0000000..78d32bc
--- /dev/null
+++ b/texinfo/mgl_en.texi
@@ -0,0 +1,101 @@
+\input texinfo
+ at documentencoding UTF-8
+ at documentlanguage en
+
+ at setfilename mgl_en.info
+ at include version.texi
+ at settitle MGL script language for version @value{VERSION}
+ at syncodeindex pg cp
+ at comment %**end of header
+
+ at copying
+This manual is for MathGL (version @value{VERSION}), a collection of classes and routines for scientific plotting. Please report any errors in this manual to @email{mathgl.abalakin@@gmail.org}.
+
+ at include copyright.texi
+ at end copying
+
+ at dircategory MathGL documentation system
+ at direntry
+* MathGL: (mathgl). The library for scientific graphics.
+ at end direntry
+
+ at titlepage
+ at title MGL script language
+ at subtitle for version @value{VERSION}
+ at author A.A. Balakin (@uref{http://mathgl.sourceforge.net/})
+ at page
+ at vskip 0pt plus 1filll
+ at insertcopying
+ at end titlepage
+
+ at contents
+
+ at ifnottex
+ at node Top
+ at top MGL script language
+
+This file documents the MGL script language. It corresponds to release @value{VERSION} of the MathGL library. Please report any errors in this manual to @email{mathgl.abalakin@@gmail.org}. More information about MGL and MathGL can be found at the project homepage, @uref{http://mathgl.sourceforge.net/}.
+
+ at include copyright.texi
+
+ at end ifnottex
+
+ at menu
+ at c * Overview::
+* MGL scripts::
+* General concepts::
+* MathGL core::
+* Data processing::
+* Examples::
+* Symbols and hot-keys::
+* Copying This Manual::
+* Index::
+ at end menu
+
+ at macro external {}
+ at end macro
+ at macro nav {}
+ at end macro
+
+ at macro fig {fname,text}
+ at center @image{\fname\, 11cm, , \text\, png}
+ at end macro
+ at macro pfig {fname,text}
+ at center @image{png/\fname\, 11cm, , \text\, png}
+ at end macro
+
+ at macro sref {arg}
+ at xref{\arg\}, for sample code and picture.
+ at end macro
+ at set UDAV
+
+
+ at node MGL scripts, General concepts, , Top
+ at include parse_en.texi
+
+ at node General concepts, MathGL core, MGL scripts, Top
+ at include concept_en.texi
+
+ at node MathGL core, Data processing, General concepts, Top
+ at include core_en.texi
+
+ at node Data processing, Examples, MathGL core, Top
+ at include data_en.texi
+
+ at node Examples, Symbols and hot-keys, Data processing, Top
+ at include ex_mgl_en.texi
+
+ at node Symbols and hot-keys, Copying This Manual, Examples, Top
+ at appendix Symbols and hot-keys
+ at include symbols_en.texi
+
+ at node Copying This Manual, Index, Symbols and hot-keys, Top
+ at appendix GNU Free Documentation License
+ at include fdl.texi
+
+ at node Index, , Copying This Manual, Top
+ at unnumbered Index
+
+ at printindex cp
+
+ at bye
diff --git a/texinfo/mgl_ru.texi b/texinfo/mgl_ru.texi
new file mode 100644
index 0000000..3246535
--- /dev/null
+++ b/texinfo/mgl_ru.texi
@@ -0,0 +1,103 @@
+\input texinfo
+ at documentencoding UTF-8
+ at c @documentlanguage ru
+
+ at setfilename mgl_ru.info
+ at documentencoding UTF-8
+ at include version.texi
+ at settitle Язык MGL для версии @value{VERSION}
+ at syncodeindex pg cp
+
+ at copying
+Это документация для MathGL (версии @value{VERSION}) -- библиотеки классов и функций для построения научной графики. Пожалуйста сообщайте о любых ошибках в этом руководстве на @email{mathgl.abalakin@@gmail.org}.
+
+ at include copyright.texi
+ at end copying
+
+ at dircategory MathGL documentation system
+ at direntry
+* MathGL: (mathgl). The library for scientific graphics.
+ at end direntry
+
+ at titlepage
+ at title Язык MGL
+ at subtitle версия @value{VERSION}
+ at author А.А. Балакин (@uref{http://mathgl.sourceforge.net/})
+ at page
+ at vskip 0pt plus 1filll
+ at insertcopying
+ at end titlepage
+
+ at contents
+
+ at ifnottex
+ at node Top
+ at top Язык MGL
+
+Это документация для языка MGL (версии @value{VERSION}). Пожалуйста сообщайте о любых ошибках в этом руководстве на @email{mathgl.abalakin@@gmail.org}. Дополнительную информацию о MGL и MathGL можно найти на домашней странице проекта @uref{http://mathgl.sourceforge.net/}.
+
+ at include copyright.texi
+
+ at end ifnottex
+
+ at menu
+ at c * Overview::
+* MGL scripts::
+* General concepts::
+* MathGL core::
+* Data processing::
+* Examples::
+* Symbols and hot-keys::
+* Copying This Manual::
+* Index::
+ at end menu
+
+ at macro external {}
+ at end macro
+ at macro nav {}
+ at end macro
+
+ at macro fig {fname,text}
+ at center @image{\fname\, 11cm, , \text\, png}
+ at end macro
+ at macro pfig {fname,text}
+ at center @image{png/\fname\, 11cm, , \text\, png}
+ at end macro
+
+ at macro sref {arg}
+См. @ref{\arg\}, для примеров кода и графика.
+ at end macro
+ at set UDAV
+
+ at c @node Overview, Examples, , Top
+ at c @include overview_ru.texi
+
+ at node MGL scripts, General concepts, , Top
+ at include parse_ru.texi
+
+ at node General concepts, MathGL core, MGL scripts, Top
+ at include concept_ru.texi
+
+ at node MathGL core, Data processing, General concepts, Top
+ at include core_ru.texi
+
+ at node Data processing, Examples, MathGL core, Top
+ at include data_ru.texi
+
+ at node Examples, Symbols and hot-keys, Data processing, Top
+ at include ex_mgl_ru.texi
+
+ at node Symbols and hot-keys, Copying This Manual, Examples, Top
+ at appendix Symbols and hot-keys
+ at include symbols_ru.texi
+
+ at node Copying This Manual, Index, Symbols and hot-keys, Top
+ at appendix GNU Free Documentation License
+ at include fdl.texi
+
+ at node Index, , Copying This Manual, Top
+ at unnumbered Index
+
+ at printindex cp
+
+ at bye
diff --git a/texinfo/mglconv.1 b/texinfo/mglconv.1
new file mode 100644
index 0000000..b5cdc8e
--- /dev/null
+++ b/texinfo/mglconv.1
@@ -0,0 +1,48 @@
+.\" Process this file with
+.\" groff -man -Tascii mglconv.1
+.\"
+.TH MGLCONV 1 "MARCH 2012" MathGL "User Manuals"
+.SH NAME
+mglconv \- Execute MathGL scripts to generate graphical output.
+.SH SYNOPSIS
+.B mglconv
+[parameters] scriptfile
+.SH DESCRIPTION
+.B mglconv
+reads MGL scripts from
+.I scriptfile
+to produce plots of specified functions or data. Result can be saved in bitmap (PNG/JPEG/GIF/BMP) or vector (EPS/SVG/LaTeX/OFF/STL/OBJ/X3D) format. You can use
+.B -
+as file name for reading script from standard input.
+.SH OPTIONS
+.IP "\fB-1 string\fP"
+Set
+.I string
+as argument $1 for script.
+.IP "\fB...\fP"
+.IP "\fB-9 string\fP"
+Set
+.I string
+as argument $9 for script.
+.IP "\fB-A value\fP"
+Add
+.I value
+into the list of animation parameters.
+.IP "\fB-C v1:v2[:dv]\fP"
+Add values in range
+.I v1:v2
+with step
+.I dv
+(default is 1) into the list of animation parameters.
+.IP "\fB-L locname\fP"
+Set the locale to
+.I locname.
+.IP "\fB-o name\fP"
+Set output file name.
+.IP "\fB-h\fP"
+Print help message.
+.SH AUTHOR
+mglconv was written by Alexey Balakin, http://mathgl.sourceforge.net/
+.SH "SEE ALSO"
+.BR mglview (1),
+.BR mgl (5)
diff --git a/texinfo/mglview.1 b/texinfo/mglview.1
new file mode 100644
index 0000000..e8d0722
--- /dev/null
+++ b/texinfo/mglview.1
@@ -0,0 +1,37 @@
+.\" Process this file with
+.\" groff -man -Tascii mglview.1
+.\"
+.TH MGLVIEW 1 "MARCH 2012" MathGL "User Manuals"
+.SH NAME
+mglview \- Execute MathGL scripts and show in an window
+.SH SYNOPSIS
+.B mglview
+[parameters] scriptfile
+.SH DESCRIPTION
+.B mglview
+reads MGL scripts from
+.I scriptfile
+to produce plots of specified functions or data. The program will create a GUI window showing the script result. You can use
+.B -
+as file name for reading script from standard input. Another option is using *.mgld files for quick viewing 3d pictures.
+.SH OPTIONS
+.IP "\fB-1 string\fP"
+Set
+.I string
+as argument $1 for script.
+.IP "\fB...\fP"
+.IP "\fB-9 string\fP"
+Set
+.I string
+as argument $9 for script.
+.IP "\fB-L locname\fP"
+Set the locale to
+.I locname.
+.IP "\fB-h\fP"
+Print help message.
+.SH AUTHOR
+mglview was written by Alexey Balakin, http://mathgl.sourceforge.net/
+.SH "SEE ALSO"
+.BR mglconv (1),
+.BR udav (1),
+.BR mgl (5)
diff --git a/texinfo/other_en.texi b/texinfo/other_en.texi
new file mode 100644
index 0000000..87d8df7
--- /dev/null
+++ b/texinfo/other_en.texi
@@ -0,0 +1,565 @@
+ at c ------------------------------------------------------------------
+ at chapter Other classes
+ at nav{}
+
+There are few end-user classes: @code{mglGraph} (see @ref{MathGL core}), @code{mglWindow} and @code{mglGLUT} (see @ref{Widget classes}), @code{mglData} (see @ref{Data processing}), @code{mglParse} (see @ref{MGL scripts}). Exactly these classes I recommend to use in most of user programs. All methods in all of these classes are inline and have exact C/Fortran analogue functions. This give compiler independent binary libraries for MathGL.
+
+However, sometimes you may need to extend MathGL by writing yours own plotting functions or handling yours own data structures. In these cases you may need to use low-level API. This chapter describes it.
+
+ at fig{classes, Class diagram for MathGL}
+
+The internal structure of MathGL is rather complicated. There are C++ classes @code{mglBase}, @code{mglCanvas}, ... for drawing primitives and positioning the plot (blue ones in the figure). There is a layer of C functions, which include interface for most important methods of these classes. Also most of plotting functions are implemented as C functions. After it, there are ``inline'' front-end classes which are created for user convenience (yellow ones in the figure). Also there are wid [...]
+
+Below I show how this internal classes can be used.
+
+ at menu
+* mglBase class::
+* mglDataA class::
+* mglColor class::
+* mglPoint class::
+ at end menu
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node mglBase class, mglDataA class, , Other classes
+ at section Define new kind of plot (mglBase class)
+ at nav{}
+
+Basically most of new kinds of plot can be created using just MathGL primitives (see @ref{Primitives}). However the usage of @code{mglBase} methods can give you higher speed of drawing and better control of plot settings. 
+
+All plotting functions should use a pointer to @code{mglBase} class (or @code{HMGL} type in C functions) due to compatibility issues. Exactly such type of pointers are used in front-end classes (@code{mglGraph, mglWindow}) and in widgets (@code{QMathGL, Fl_MathGL}).
+
+MathGL tries to remember all vertexes and all primitives and plot creation stage, and to use them for making final picture by demand. Basically for making plot, you need to add vertexes by @code{AddPnt()} function, which return index for new vertex, and call one of primitive drawing function (like @code{mark_plot(), arrow_plot(), line_plot(), trig_plot(), quad_plot(), text_plot()}), using vertex indexes as argument(s). @code{AddPnt()} function use 2 mreal numbers for color specification. [...]
+
+I don't want to put here detailed description of @code{mglBase} class. It was rather well documented in @code{mgl2/base.h} file. I just show and example of its usage on the base of circle drawing.
+
+First, we should prototype new function @code{circle()} as C function.
+ at verbatim
+#ifdef __cplusplus
+extern "C" {
+#endif
+void circle(HMGL gr, mreal x, mreal y, mreal z, mreal r, const char *stl, const char *opt);
+#ifdef __cplusplus
+}
+#endif
+ at end verbatim
+This is done for generating compiler independent binary. Because only C-functions have standard naming mechanism, the same for any compilers.
+
+Now, we create a C++ file and put the code of function. I'll write it line by line and try to comment all important points.
+ at verbatim
+void circle(HMGL gr, mreal x, mreal y, mreal z, mreal r, const char *stl, const char *opt)
+{
+ at end verbatim
+First, we need to check all input arguments and send warnings if something is wrong. In our case it is negative value of @var{r} argument. We just send warning, since it is not critical situation -- other plot still can be drawn.
+ at verbatim
+  if(r<=0)  { gr->SetWarn(mglWarnNeg,"Circle"); return; }
+ at end verbatim
+Next step is creating a group. Group keep some general setting for plot (like options) and useful for export in 3d files.
+ at verbatim
+  static int cgid=1;  gr->StartGroup("Circle",cgid++);
+ at end verbatim
+Now let apply options. Options are rather useful things, generally, which allow one easily redefine axis range(s), transparency and other settings (see @ref{Command options}).
+ at verbatim
+  gr->SaveState(opt);
+ at end verbatim
+I use global setting for determining the number of points in circle approximation. Note, that user can change @code{MeshNum} by options easily.
+ at verbatim
+  const int n = gr->MeshNum>1?gr->MeshNum : 41;
+ at end verbatim
+Let try to determine plot specific flags. MathGL functions expect that most of flags will be sent in string. In our case it is symbol @samp{@@} which set to draw filled circle instead of border only (last will be default). Note, you have to handle @code{NULL} as string pointer.
+ at verbatim
+  bool fill = mglchr(stl,'@');
+ at end verbatim
+Now, time for coloring. I use palette mechanism because circle have few colors: one for filling and another for border. @code{SetPenPal()} function parse input string and write resulting texture index in @var{pal}. Function return the character for marker, which can be specified in string @var{str}. Marker will be plotted at the center of circle. I'll show on next sample how you can use color schemes (smooth colors) too.
+ at verbatim
+  long pal=0;
+  char mk=gr->SetPenPal(stl,&pal);
+ at end verbatim
+Next step, is determining colors for filling and for border. First one for filling.
+ at verbatim
+  mreal c=gr->NextColor(pal), d;
+ at end verbatim
+Second one for border. I use black color (call @code{gr->AddTexture('k')}) if second color is not specified.
+ at verbatim
+  mreal k=(gr->GetNumPal(pal)>1)?gr->NextColor(pal):gr->AddTexture('k');
+ at end verbatim
+If user want draw only border (@code{fill=false}) then I use first color for border.
+ at verbatim
+  if(!fill) k=c;
+ at end verbatim
+Now we should reserve space for vertexes. This functions need @code{n} for border, @code{n+1} for filling and @code{1} for marker. So, maximal number of vertexes is @code{2*n+2}. Note, that such reservation is not required for normal work but can sufficiently speed up the plotting.
+ at verbatim
+  gr->Reserve(2*n+2);
+ at end verbatim
+We've done with setup and ready to start drawing. First, we need to add vertex(es). Let define NAN as normals, since I don't want handle lighting for this plot,
+ at verbatim
+  mglPoint q(NAN,NAN);
+ at end verbatim
+and start adding vertexes. First one for central point of filling. I use @code{-1} if I don't need this point. The arguments of @code{AddPnt()} function is: @code{mglPoint(x,y,z)} -- coordinate of vertex, @code{c} -- vertex color, @code{q} -- normal at vertex, @code{-1} -- vertex transparency (@code{-1} for default), @code{3} bitwise flag which show that coordinates will be scaled (@code{0x1}) and will not be cutted (@code{0x2}).
+ at verbatim
+  long n0,n1,n2,m1,m2,i;
+  n0 = fill ? gr->AddPnt(mglPoint(x,y,z),c,q,-1,3):-1;
+ at end verbatim
+Similar for marker, but we use different color @var{k}.
+ at verbatim
+  n2 = mk ? gr->AddPnt(mglPoint(x,y,z),k,q,-1,3):-1;
+ at end verbatim
+Draw marker.
+ at verbatim
+  if(mk)  gr->mark_plot(n2,mk);
+ at end verbatim
+Time for drawing circle itself. I use @code{-1} for @var{m1}, @var{n1} as sign that primitives shouldn't be drawn for first point @code{i=0}.
+ at verbatim
+  for(i=0,m1=n1=-1;i<n;i++)
+  {
+ at end verbatim
+Each function should check @code{Stop} variable and return if it is non-zero. It is done for interrupting drawing for system which don't support multi-threading.
+ at verbatim
+    if(gr->Stop)  return;
+ at end verbatim
+Let find coordinates of vertex.
+ at verbatim
+    mreal t = i*2*M_PI/(n-1.);
+    mglPoint p(x+r*cos(t), y+r*sin(t), z);
+ at end verbatim
+Save previous vertex and add next one
+ at verbatim
+    n2 = n1;  n1 = gr->AddPnt(p,c,q,-1,3);
+ at end verbatim
+and copy it for border but with different color. Such copying is much faster than adding new vertex using @code{AddPnt()}.
+ at verbatim
+    m2 = m1;  m1 = gr->CopyNtoC(n1,k);
+ at end verbatim
+Now draw triangle for filling internal part
+ at verbatim
+    if(fill)  gr->trig_plot(n0,n1,n2);
+ at end verbatim
+and draw line for border.
+ at verbatim
+    gr->line_plot(m1,m2);
+  }
+ at end verbatim
+Drawing is done. Let close group and return.
+ at verbatim
+  gr->EndGroup();
+}
+ at end verbatim
+
+Another sample I want to show is exactly the same function but with smooth coloring using color scheme. So, I'll add comments only in the place of difference.
+
+ at verbatim
+void circle_cs(HMGL gr, mreal x, mreal y, mreal z, mreal r, const char *stl, const char *opt)
+{
+ at end verbatim
+In this case let allow negative radius too. Formally it is not the problem for plotting (formulas the same) and this allow us to handle all color range.
+ at verbatim
+//if(r<=0)  { gr->SetWarn(mglWarnNeg,"Circle"); return; }
+
+  static int cgid=1;  gr->StartGroup("CircleCS",cgid++);
+  gr->SaveState(opt);
+  const int n = gr->MeshNum>1?gr->MeshNum : 41;
+  bool fill = mglchr(stl,'@');
+ at end verbatim
+Here is main difference. We need to create texture for color scheme specified by user
+ at verbatim
+  long ss = gr->AddTexture(stl);
+ at end verbatim
+But we need also get marker and color for it (if filling is enabled). Let suppose that marker and color is specified after @samp{:}. This is standard delimiter which stop color scheme entering. So, just lets find it and use for setting pen.
+ at verbatim
+  const char *pen=0;
+  if(stl) pen = strchr(stl,':');
+  if(pen) pen++;
+ at end verbatim
+The substring is placed in @var{pen} and it will be used as line style.
+ at verbatim
+  long pal=0;
+  char mk=gr->SetPenPal(pen,&pal);
+ at end verbatim
+Next step, is determining colors for filling and for border. First one for filling.
+ at verbatim
+  mreal c=gr->GetC(ss,r);
+ at end verbatim
+Second one for border.
+ at verbatim
+  mreal k=gr->NextColor(pal);
+ at end verbatim
+The rest part is the same as in previous function.
+ at verbatim
+  if(!fill) k=c;
+
+  gr->Reserve(2*n+2);
+  mglPoint q(NAN,NAN);
+  long n0,n1,n2,m1,m2,i;
+  n0 = fill ? gr->AddPnt(mglPoint(x,y,z),c,q,-1,3):-1;
+  n2 = mk ? gr->AddPnt(mglPoint(x,y,z),k,q,-1,3):-1;
+  if(mk)  gr->mark_plot(n2,mk);
+  for(i=0,m1=n1=-1;i<n;i++)
+  {
+    if(gr->Stop)  return;
+    mreal t = i*2*M_PI/(n-1.);
+    mglPoint p(x+r*cos(t), y+r*sin(t), z);
+    n2 = n1;  n1 = gr->AddPnt(p,c,q,-1,3);
+    m2 = m1;  m1 = gr->CopyNtoC(n1,k);
+    if(fill)  gr->trig_plot(n0,n1,n2);
+    gr->line_plot(m1,m2);
+  }
+  gr->EndGroup();
+}
+ at end verbatim
+
+The last thing which we can do is derive our own class with new plotting functions. Good idea is to derive it from @code{mglGraph} (if you don't need extended window), or from @code{mglWindow} (if you need to extend window). So, in our case it will be
+ at verbatim
+class MyGraph : public mglGraph
+{
+public:
+  inline void Circle(mglPoint p, mreal r, const char *stl="", const char *opt="")
+  { circle(p.x,p.y,p.z, r, stl, opt); }
+  inline void CircleCS(mglPoint p, mreal r, const char *stl="", const char *opt="")
+  { circle_cs(p.x,p.y,p.z, r, stl, opt); }
+};
+ at end verbatim
+Note, that I use @code{inline} modifier for using the same binary code with different compilers. 
+
+So, the complete sample will be
+ at verbatim
+#include <mgl2/mgl.h>
+//---------------------------------------------------------
+#ifdef __cplusplus
+extern "C" {
+#endif
+void circle(HMGL gr, mreal x, mreal y, mreal z, mreal r, const char *stl, const char *opt);
+void circle_cs(HMGL gr, mreal x, mreal y, mreal z, mreal r, const char *stl, const char *opt);
+#ifdef __cplusplus
+}
+#endif
+//---------------------------------------------------------
+class MyGraph : public mglGraph
+{
+public:
+  inline void CircleCF(mglPoint p, mreal r, const char *stl="", const char *opt="")
+  { circle(p.x,p.y,p.z, r, stl, opt); }
+  inline void CircleCS(mglPoint p, mreal r, const char *stl="", const char *opt="")
+  { circle_cs(p.x,p.y,p.z, r, stl, opt); }
+};
+//---------------------------------------------------------
+void circle(HMGL gr, mreal x, mreal y, mreal z, mreal r, const char *stl, const char *opt)
+{
+  if(r<=0)  { gr->SetWarn(mglWarnNeg,"Circle"); return; }
+  static int cgid=1;  gr->StartGroup("Circle",cgid++);
+  gr->SaveState(opt);
+  const int n = gr->MeshNum>1?gr->MeshNum : 41;
+  bool fill = mglchr(stl,'@');
+  long pal=0;
+  char mk=gr->SetPenPal(stl,&pal);
+  mreal c=gr->NextColor(pal), d;
+  mreal k=(gr->GetNumPal(pal)>1)?gr->NextColor(pal):gr->AddTexture('k');
+  if(!fill) k=c;
+  gr->Reserve(2*n+2);
+  mglPoint q(NAN,NAN);
+  long n0,n1,n2,m1,m2,i;
+  n0 = fill ? gr->AddPnt(mglPoint(x,y,z),c,q,-1,3):-1;
+  n2 = mk ? gr->AddPnt(mglPoint(x,y,z),k,q,-1,3):-1;
+  if(mk)  gr->mark_plot(n2,mk);
+  for(i=0,m1=n1=-1;i<n;i++)
+  {
+    if(gr->Stop)  return;
+    mreal t = i*2*M_PI/(n-1.);
+    mglPoint p(x+r*cos(t), y+r*sin(t), z);
+    n2 = n1;  n1 = gr->AddPnt(p,c,q,-1,3);
+    m2 = m1;  m1 = gr->CopyNtoC(n1,k);
+    if(fill)  gr->trig_plot(n0,n1,n2);
+    gr->line_plot(m1,m2);
+  }
+  gr->EndGroup();
+}
+//---------------------------------------------------------
+void circle_cs(HMGL gr, mreal x, mreal y, mreal z, mreal r, const char *stl, const char *opt)
+{
+  static int cgid=1;  gr->StartGroup("CircleCS",cgid++);
+  gr->SaveState(opt);
+  const int n = gr->MeshNum>1?gr->MeshNum : 41;
+  bool fill = mglchr(stl,'@');
+  long ss = gr->AddTexture(stl);
+  const char *pen=0;
+  if(stl) pen = strchr(stl,':');
+  if(pen) pen++;
+  long pal=0;
+  char mk=gr->SetPenPal(pen,&pal);
+  mreal c=gr->GetC(ss,r);
+  mreal k=gr->NextColor(pal);
+  if(!fill) k=c;
+
+  gr->Reserve(2*n+2);
+  mglPoint q(NAN,NAN);
+  long n0,n1,n2,m1,m2,i;
+  n0 = fill ? gr->AddPnt(mglPoint(x,y,z),c,q,-1,3):-1;
+  n2 = mk ? gr->AddPnt(mglPoint(x,y,z),k,q,-1,3):-1;
+  if(mk)  gr->mark_plot(n2,mk);
+  for(i=0,m1=n1=-1;i<n;i++)
+  {
+    if(gr->Stop)  return;
+    mreal t = i*2*M_PI/(n-1.);
+    mglPoint p(x+r*cos(t), y+r*sin(t), z);
+    n2 = n1;  n1 = gr->AddPnt(p,c,q,-1,3);
+    m2 = m1;  m1 = gr->CopyNtoC(n1,k);
+    if(fill)  gr->trig_plot(n0,n1,n2);
+    gr->line_plot(m1,m2);
+  }
+  gr->EndGroup();
+}
+//---------------------------------------------------------
+int main()
+{
+  MyGraph gr;
+  gr.Box();
+  // first let draw circles with fixed colors
+  for(int i=0;i<10;i++)
+    gr.CircleCF(mglPoint(2*mgl_rnd()-1, 2*mgl_rnd()-1), mgl_rnd());
+  // now let draw circles with color scheme
+  for(int i=0;i<10;i++)
+    gr.CircleCS(mglPoint(2*mgl_rnd()-1, 2*mgl_rnd()-1), 2*mgl_rnd()-1);
+}
+ at end verbatim
+
+
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node mglDataA class, mglColor class, mglBase class, Other classes
+ at section User defined types (mglDataA class)
+ at nav{}
+
+ at code{mglData} class have abstract predecessor class @code{mglDataA}. Exactly the pointers to @code{mglDataA} instances are used in all plotting functions and some of data processing functions. This was done for taking possibility to define yours own class, which will handle yours own data (for example, complex numbers, or differently organized data). And this new class will be almost the same as @code{mglData} for plotting purposes.
+
+However, the most of data processing functions will be slower as if you used @code{mglData} instance. This is more or less understandable -- I don't know how data in yours particular class will be organized, and couldn't optimize the these functions generally.
+
+There are few virtual functions which must be provided in derived classes. This functions give:
+ at itemize @bullet
+ at item
+the sizes of the data (@code{GetNx}, @code{GetNy}, @code{GetNz}),
+ at item
+give data value and numerical derivatives for selected cell (@code{v}, @code{dvx}, @code{dvy}, @code{dvz}),
+ at item
+give maximal and minimal values (@code{Maximal}, @code{Minimal}) -- you can use provided functions (like @code{mgl_data_max} and @code{mgl_data_min}), but yours own realization can be more efficient,
+ at item
+give access to all element as in single array (@code{vthr}) -- you need this only if you want using MathGL's data processing functions.
+ at end itemize
+
+Let me, for example define class @code{mglComplex} which will handle complex number and draw its amplitude or phase, depending on flag @var{use_abs}:
+ at verbatim
+#include <complex>
+#include <mgl2/mgl.h>
+#define dual std::complex<double>
+class mglComplex : public mglDataA
+{
+public:
+  long nx;      ///< number of points in 1st dimensions ('x' dimension)
+  long ny;      ///< number of points in 2nd dimensions ('y' dimension)
+  long nz;      ///< number of points in 3d dimensions ('z' dimension)
+  dual *a;      ///< data array
+  bool use_abs; ///< flag to use abs() or arg()
+
+  inline mglComplex(long xx=1,long yy=1,long zz=1)
+  { a=0;  use_abs=true; Create(xx,yy,zz); }
+  virtual ~mglComplex()  { if(a)  delete []a; }
+
+  /// Get sizes
+  inline long GetNx() const { return nx;  }
+  inline long GetNy() const { return ny;  }
+  inline long GetNz() const { return nz;  }
+  /// Create or recreate the array with specified size and fill it by zero
+  inline void Create(long mx,long my=1,long mz=1)
+  { nx=mx;  ny=my;  nz=mz;  if(a) delete []a;
+  a = new dual[nx*ny*nz]; }
+  /// Get maximal value of the data
+  inline mreal Maximal() const  { return mgl_data_max(this);  }
+  /// Get minimal value of the data
+  inline mreal Minimal() const  { return mgl_data_min(this);  }
+
+protected:
+  inline mreal v(long i,long j=0,long k=0) const
+  { return use_abs ? abs(a[i+nx*(j+ny*k)]) : arg(a[i+nx*(j+ny*k)]);  }
+  inline mreal vthr(long i) const
+  { return use_abs ? abs(a[i]) : arg(a[i]);  }
+  inline mreal dvx(long i,long j=0,long k=0) const
+  { register long i0=i+nx*(j+ny*k);
+    std::complex<double> res=i>0? (i<nx-1? (a[i0+1]-a[i0-1])/2.:a[i0]-a[i0-1]) : a[i0+1]-a[i0];
+    return use_abs? abs(res) : arg(res);  }
+  inline mreal dvy(long i,long j=0,long k=0) const
+  { register long i0=i+nx*(j+ny*k);
+    std::complex<double> res=j>0? (j<ny-1? (a[i0+nx]-a[i0-nx])/2.:a[i0]-a[i0-nx]) : a[i0+nx]-a[i0];
+    return use_abs? abs(res) : arg(res);  }
+  inline mreal dvz(long i,long j=0,long k=0) const
+  { register long i0=i+nx*(j+ny*k), n=nx*ny;
+    std::complex<double> res=k>0? (k<nz-1? (a[i0+n]-a[i0-n])/2.:a[i0]-a[i0-n]) : a[i0+n]-a[i0];
+    return use_abs? abs(res) : arg(res);  }
+};
+int main()
+{
+  mglComplex dat(20);
+  for(long i=0;i<20;i++)
+    dat.a[i] = 3*exp(-0.05*(i-10)*(i-10))*dual(cos(M_PI*i*0.3), sin(M_PI*i*0.3));
+  mglGraph gr;
+  gr.SetRange('y', -M_PI, M_PI);  gr.Box();
+
+  gr.Plot(dat,"r","legend 'abs'");
+  dat.use_abs=false;
+  gr.Plot(dat,"b","legend 'arg'");
+  gr.Legend();
+  gr.WritePNG("complex.png");
+  return 0;
+}
+ at end verbatim
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node mglColor class, mglPoint class, mglDataA class, Other classes
+ at section mglColor class
+ at nav{}
+ at cindex mglColor
+
+Structure for working with colors. This structure is defined in @code{#include <mgl2/type.h>}.
+
+There are two ways to set the color in MathGL. First one is using of mreal values of red, green and blue channels for precise color definition. The second way is the using of character id. There are a set of characters specifying frequently used colors. Normally capital letter gives more dark color than lowercase one. @xref{Line styles}.
+
+ at deftypecv {Parameter} mglColor @code{mreal} {r, g, b, a}
+Reg, green and blue component of color.
+ at end deftypecv
+
+ at deftypemethod mglColor @code{} mglColor (@code{mreal} R, @code{mreal} G, @code{mreal} B, @code{mreal} A=@code{1})
+Constructor sets the color by mreal values of Red, Green, Blue and Alpha channels. These values should be in interval [0,1].
+ at end deftypemethod
+ at deftypemethod mglColor @code{} mglColor (@code{char} c=@code{'k'}, @code{mreal} bright=@code{1})
+Constructor sets the color from character id. The black color is used by default. Parameter @var{br} set additional ``lightness'' of color.
+ at end deftypemethod
+ at deftypemethod mglColor @code{void} Set (@code{mreal} R, @code{mreal} G, @code{mreal} B, @code{mreal} A=@code{1})
+Sets color from values of Red, Green, Blue and Alpha channels. These values should be in interval [0,1].
+ at end deftypemethod
+ at deftypemethod mglColor @code{void} Set (@code{mglColor} c, @code{mreal} bright=@code{1})
+Sets color as ``lighted'' version of color @var{c}.
+ at end deftypemethod
+ at deftypemethod mglColor @code{void} Set (@code{char} p, @code{mreal} bright=@code{1})
+Sets color from symbolic id.
+ at end deftypemethod
+ at deftypemethod mglColor @code{bool} Valid ()
+Checks correctness of the color.
+ at end deftypemethod
+ at deftypemethod mglColor @code{mreal} Norm ()
+Gets maximal of spectral component.
+ at end deftypemethod
+ at deftypemethod mglColor @code{bool} operator== (@code{const mglColor &}c)
+ at deftypemethodx mglColor @code{bool} operator!= (@code{const mglColor &}c)
+Compare with another color
+ at end deftypemethod
+
+ at deftypemethod mglColor @code{bool} operator*= (@code{mreal} v)
+Multiplies color components by number @var{v}.
+ at end deftypemethod
+
+ at deftypemethod mglColor @code{bool} operator+= (@code{const mglColor &}c)
+Adds color @var{c} component by component.
+ at end deftypemethod
+
+ at deftypemethod mglColor @code{bool} operator-= (@code{const mglColor &}c)
+Subtracts color @var{c} component by component.
+ at end deftypemethod
+
+
+ at deftypefn {Library Function} {mglColor} operator+ (@code{const mglColor &}a, @code{const mglColor &}b)
+Adds colors by its RGB values.
+ at end deftypefn
+ at deftypefn {Library Function} @code{mglColor} operator- (@code{const mglColor &}a, @code{const mglColor &}b)
+Subtracts colors by its RGB values.
+ at end deftypefn
+ at deftypefn {Library Function} @code{mglColor} operator* (@code{const mglColor &}a, @code{mreal} b)
+ at deftypefnx {Library Function} @code{mglColor} operator* (@code{mreal} a, @code{const mglColor &}b)
+Multiplies color by number.
+ at end deftypefn
+ at deftypefn {Library Function} @code{mglColor} operator/ (@code{const mglColor &}a, @code{mreal} b)
+Divide color by number.
+ at end deftypefn
+ at deftypefn {Library Function} @code{mglColor} operator! (@code{const mglColor &}a)
+Return inverted color.
+ at end deftypefn
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node mglPoint class, , mglColor class, Other classes
+ at section mglPoint class
+ at nav{}
+ at cindex mglPoint
+
+Structure describes point in space. This structure is defined in @code{#include <mgl2/type.h>}
+
+ at deftypecv {Parameter} mglPoint @code{mreal} {x, y, z, c}
+Point coordinates @{x,y,z@} and one extra value @var{c} used for amplitude, transparency and so on. By default all values are zero.
+ at end deftypecv
+
+ at deftypemethod mglPoint @code{} mglPoint (@code{mreal} X=@code{0}, @code{mreal} Y=@code{0}, @code{mreal} Z=@code{0}, @code{mreal} C=@code{0})
+Constructor sets the color by mreal values of Red, Green, Blue and Alpha channels. These values should be in interval [0,1].
+ at end deftypemethod
+
+ at deftypemethod mglPoint @code{bool} IsNAN ()
+Returns @code{true} if point contain NAN values.
+ at end deftypemethod
+ at deftypemethod mglPoint @code{mreal} norm ()
+Returns the norm @math{\sqrt@{x^2+y^2+z^2@}} of vector.
+ at end deftypemethod
+ at deftypemethod mglPoint @code{void} Normalize ()
+Normalizes vector to be unit vector.
+ at end deftypemethod
+ at deftypemethod mglPoint @code{mreal} val (@code{int} i)
+Returns point component: @var{x} for @var{i}=0, @var{y} for @var{i}=1, @var{z} for @var{i}=2, @var{c} for @var{i}=3.
+ at end deftypemethod
+
+
+ at deftypefn {Library Function} @code{mglPoint} operator+ (@code{const mglPoint &}a, @code{const mglPoint &}b)
+Point of summation (summation of vectors).
+ at end deftypefn
+ at deftypefn {Library Function} @code{mglPoint} operator- (@code{const mglPoint &}a, @code{const mglPoint &}b)
+Point of difference (difference of vectors).
+ at end deftypefn
+ at deftypefn {Library Function} @code{mglPoint} operator* (@code{mreal} a, @code{const mglPoint &}b)
+ at deftypefnx {Library Function} @code{mglPoint} operator* (@code{const mglPoint &}a, @code{mreal} b)
+Multiplies (scale) points by number.
+ at end deftypefn
+ at deftypefn {Library Function} @code{mglPoint} operator/ (@code{const mglPoint &}a, @code{mreal} b)
+Multiplies (scale) points by number 1/b.
+ at end deftypefn
+ at deftypefn {Library Function} @code{mreal} operator* (@code{const mglPoint &}a, @code{const mglPoint &}b)
+Scalar product of vectors.
+ at end deftypefn
+
+ at deftypefn {Library Function} @code{mglPoint} operator/ (@code{const mglPoint &}a, @code{const mglPoint &}b)
+Return vector of element-by-element product.
+ at end deftypefn
+
+ at deftypefn {Library Function} @code{mglPoint} operator^ (@code{const mglPoint &}a, @code{const mglPoint &}b)
+Cross-product of vectors.
+ at end deftypefn
+ at deftypefn {Library Function} @code{mglPoint} operator& (@code{const mglPoint &}a, @code{const mglPoint &}b)
+The part of @var{a} which is perpendicular to vector @var{b}.
+ at end deftypefn
+ at deftypefn {Library Function} @code{mglPoint} operator| (@code{const mglPoint &}a, @code{const mglPoint &}b)
+The part of @var{a} which is parallel to vector @var{b}.
+ at end deftypefn
+
+ at deftypefn {Library Function} @code{mglPoint} operator! (@code{const mglPoint &}a)
+Return vector perpendicular to vector @var{a}.
+ at end deftypefn
+ at deftypefn {Library Function} @code{mreal} mgl_norm (@code{const mglPoint &}a)
+Return the norm sqrt(|@var{a}|^2) of vector @var{a}.
+ at end deftypefn
+
+ at deftypefn {Library Function} @code{bool} operator== (@code{const mglPoint &}a, @code{const mglPoint &}b)
+Return true if points are the same.
+ at end deftypefn
+ at deftypefn {Library Function} @code{bool} operator!= (@code{const mglPoint &}a, @code{const mglPoint &}b)
+Return true if points are different.
+ at end deftypefn
+
+ at external{}
+
diff --git a/texinfo/other_ru.texi b/texinfo/other_ru.texi
new file mode 100644
index 0000000..038903f
--- /dev/null
+++ b/texinfo/other_ru.texi
@@ -0,0 +1,565 @@
+ at c ------------------------------------------------------------------
+ at chapter Other classes
+ at nav{}
+
+There are few end-user classes: @code{mglGraph} (see @ref{MathGL core}), @code{mglWindow} and @code{mglGLUT} (see @ref{Widget classes}), @code{mglData} (see @ref{Data processing}), @code{mglParse} (see @ref{MGL scripts}). Exactly these classes I recommend to use in most of user programs. All methods in all of these classes are inline and have exact C/Fortran analogue functions. This give compiler independent binary libraries for MathGL.
+
+However, sometimes you may need to extend MathGL by writing yours own plotting functions or handling yours own data structures. In these cases you may need to use low-level API. This chapter describes it.
+
+ at fig{classes, Class diagram for MathGL}
+
+The internal structure of MathGL is rather complicated. There are C++ classes @code{mglBase}, @code{mglCanvas}, ... for drawing primitives and positioning the plot (blue ones in the figure). There is a layer of C functions, which include interface for most important methods of these classes. Also most of plotting functions are implemented as C functions. After it, there are ``inline'' front-end classes which are created for user convenience (yellow ones in the figure). Also there are wid [...]
+
+Below I show how this internal classes can be used.
+
+ at menu
+* mglBase class::
+* mglDataA class::
+* mglColor class::
+* mglPoint class::
+ at end menu
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node mglBase class, mglDataA class, , Other classes
+ at section Define new kind of plot (mglBase class)
+ at nav{}
+
+Basically most of new kinds of plot can be created using just MathGL primitives (see @ref{Primitives}). However the usage of @code{mglBase} methods can give you higher speed of drawing and better control of plot settings. 
+
+All plotting functions should use a pointer to @code{mglBase} class (or @code{HMGL} type in C functions) due to compatibility issues. Exactly such type of pointers are used in front-end classes (@code{mglGraph, mglWindow}) and in widgets (@code{QMathGL, Fl_MathGL}).
+
+MathGL tries to remember all vertexes and all primitives and plot creation stage, and to use them for making final picture by demand. Basically for making plot, you need to add vertexes by @code{AddPnt()} function, which return index for new vertex, and call one of primitive drawing function (like @code{mark_plot(), arrow_plot(), line_plot(), trig_plot(), quad_plot(), text_plot()}), using vertex indexes as argument(s). @code{AddPnt()} function use 2 mreal numbers for color specification. [...]
+
+I don't want to put here detailed description of @code{mglBase} class. It was rather well documented in @code{mgl2/base.h} file. I just show and example of its usage on the base of circle drawing.
+
+First, we should prototype new function @code{circle()} as C function.
+ at verbatim
+#ifdef __cplusplus
+extern "C" {
+#endif
+void circle(HMGL gr, mreal x, mreal y, mreal z, mreal r, const char *stl, const char *opt);
+#ifdef __cplusplus
+}
+#endif
+ at end verbatim
+This is done for generating compiler independent binary. Because only C-functions have standard naming mechanism, the same for any compilers.
+
+Now, we create a C++ file and put the code of function. I'll write it line by line and try to comment all important points.
+ at verbatim
+void circle(HMGL gr, mreal x, mreal y, mreal z, mreal r, const char *stl, const char *opt)
+{
+ at end verbatim
+First, we need to check all input arguments and send warnings if something is wrong. In our case it is negative value of @var{r} argument. We just send warning, since it is not critical situation -- other plot still can be drawn.
+ at verbatim
+  if(r<=0)  { gr->SetWarn(mglWarnNeg,"Circle"); return; }
+ at end verbatim
+Next step is creating a group. Group keep some general setting for plot (like options) and useful for export in 3d files.
+ at verbatim
+  static int cgid=1;  gr->StartGroup("Circle",cgid++);
+ at end verbatim
+Now let apply options. Options are rather useful things, generally, which allow one easily redefine axis range(s), transparency and other settings (see @ref{Command options}).
+ at verbatim
+  gr->SaveState(opt);
+ at end verbatim
+I use global setting for determining the number of points in circle approximation. Note, that user can change @code{MeshNum} by options easily.
+ at verbatim
+  const int n = gr->MeshNum>1?gr->MeshNum : 41;
+ at end verbatim
+Let try to determine plot specific flags. MathGL functions expect that most of flags will be sent in string. In our case it is symbol @samp{@@} which set to draw filled circle instead of border only (last will be default). Note, you have to handle @code{NULL} as string pointer.
+ at verbatim
+  bool fill = mglchr(stl,'@');
+ at end verbatim
+Now, time for coloring. I use palette mechanism because circle have few colors: one for filling and another for border. @code{SetPenPal()} function parse input string and write resulting texture index in @var{pal}. Function return the character for marker, which can be specified in string @var{str}. Marker will be plotted at the center of circle. I'll show on next sample how you can use color schemes (smooth colors) too.
+ at verbatim
+  long pal=0;
+  char mk=gr->SetPenPal(stl,&pal);
+ at end verbatim
+Next step, is determining colors for filling and for border. First one for filling.
+ at verbatim
+  mreal c=gr->NextColor(pal), d;
+ at end verbatim
+Second one for border. I use black color (call @code{gr->AddTexture('k')}) if second color is not specified.
+ at verbatim
+  mreal k=(gr->GetNumPal(pal)>1)?gr->NextColor(pal):gr->AddTexture('k');
+ at end verbatim
+If user want draw only border (@code{fill=false}) then I use first color for border.
+ at verbatim
+  if(!fill) k=c;
+ at end verbatim
+Now we should reserve space for vertexes. This functions need @code{n} for border, @code{n+1} for filling and @code{1} for marker. So, maximal number of vertexes is @code{2*n+2}. Note, that such reservation is not required for normal work but can sufficiently speed up the plotting.
+ at verbatim
+  gr->Reserve(2*n+2);
+ at end verbatim
+We've done with setup and ready to start drawing. First, we need to add vertex(es). Let define NAN as normals, since I don't want handle lighting for this plot,
+ at verbatim
+  mglPoint q(NAN,NAN);
+ at end verbatim
+and start adding vertexes. First one for central point of filling. I use @code{-1} if I don't need this point. The arguments of @code{AddPnt()} function is: @code{mglPoint(x,y,z)} -- coordinate of vertex, @code{c} -- vertex color, @code{q} -- normal at vertex, @code{-1} -- vertex transparency (@code{-1} for default), @code{3} bitwise flag which show that coordinates will be scaled (@code{0x1}) and will not be cutted (@code{0x2}).
+ at verbatim
+  long n0,n1,n2,m1,m2,i;
+  n0 = fill ? gr->AddPnt(mglPoint(x,y,z),c,q,-1,3):-1;
+ at end verbatim
+Similar for marker, but we use different color @var{k}.
+ at verbatim
+  n2 = mk ? gr->AddPnt(mglPoint(x,y,z),k,q,-1,3):-1;
+ at end verbatim
+Draw marker.
+ at verbatim
+  if(mk)  gr->mark_plot(n2,mk);
+ at end verbatim
+Time for drawing circle itself. I use @code{-1} for @var{m1}, @var{n1} as sign that primitives shouldn't be drawn for first point @code{i=0}.
+ at verbatim
+  for(i=0,m1=n1=-1;i<n;i++)
+  {
+ at end verbatim
+Each function should check @code{Stop} variable and return if it is non-zero. It is done for interrupting drawing for system which don't support multi-threading.
+ at verbatim
+    if(gr->Stop)  return;
+ at end verbatim
+Let find coordinates of vertex.
+ at verbatim
+    mreal t = i*2*M_PI/(n-1.);
+    mglPoint p(x+r*cos(t), y+r*sin(t), z);
+ at end verbatim
+Save previous vertex and add next one
+ at verbatim
+    n2 = n1;  n1 = gr->AddPnt(p,c,q,-1,3);
+ at end verbatim
+and copy it for border but with different color. Such copying is much faster than adding new vertex using @code{AddPnt()}.
+ at verbatim
+    m2 = m1;  m1 = gr->CopyNtoC(n1,k);
+ at end verbatim
+Now draw triangle for filling internal part
+ at verbatim
+    if(fill)  gr->trig_plot(n0,n1,n2);
+ at end verbatim
+and draw line for border.
+ at verbatim
+    gr->line_plot(m1,m2);
+  }
+ at end verbatim
+Drawing is done. Let close group and return.
+ at verbatim
+  gr->EndGroup();
+}
+ at end verbatim
+
+Another sample I want to show is exactly the same function but with smooth coloring using color scheme. So, I'll add comments only in the place of difference.
+
+ at verbatim
+void circle_cs(HMGL gr, mreal x, mreal y, mreal z, mreal r, const char *stl, const char *opt)
+{
+ at end verbatim
+In this case let allow negative radius too. Formally it is not the problem for plotting (formulas the same) and this allow us to handle all color range.
+ at verbatim
+//if(r<=0)  { gr->SetWarn(mglWarnNeg,"Circle"); return; }
+
+  static int cgid=1;  gr->StartGroup("CircleCS",cgid++);
+  gr->SaveState(opt);
+  const int n = gr->MeshNum>1?gr->MeshNum : 41;
+  bool fill = mglchr(stl,'@');
+ at end verbatim
+Here is main difference. We need to create texture for color scheme specified by user
+ at verbatim
+  long ss = gr->AddTexture(stl);
+ at end verbatim
+But we need also get marker and color for it (if filling is enabled). Let suppose that marker and color is specified after @samp{:}. This is standard delimiter which stop color scheme entering. So, just lets find it and use for setting pen.
+ at verbatim
+  const char *pen=0;
+  if(stl) pen = strchr(stl,':');
+  if(pen) pen++;
+ at end verbatim
+The substring is placed in @var{pen} and it will be used as line style.
+ at verbatim
+  long pal=0;
+  char mk=gr->SetPenPal(pen,&pal);
+ at end verbatim
+Next step, is determining colors for filling and for border. First one for filling.
+ at verbatim
+  mreal c=gr->GetC(ss,r);
+ at end verbatim
+Second one for border.
+ at verbatim
+  mreal k=gr->NextColor(pal);
+ at end verbatim
+The rest part is the same as in previous function.
+ at verbatim
+  if(!fill) k=c;
+
+  gr->Reserve(2*n+2);
+  mglPoint q(NAN,NAN);
+  long n0,n1,n2,m1,m2,i;
+  n0 = fill ? gr->AddPnt(mglPoint(x,y,z),c,q,-1,3):-1;
+  n2 = mk ? gr->AddPnt(mglPoint(x,y,z),k,q,-1,3):-1;
+  if(mk)  gr->mark_plot(n2,mk);
+  for(i=0,m1=n1=-1;i<n;i++)
+  {
+    if(gr->Stop)  return;
+    mreal t = i*2*M_PI/(n-1.);
+    mglPoint p(x+r*cos(t), y+r*sin(t), z);
+    n2 = n1;  n1 = gr->AddPnt(p,c,q,-1,3);
+    m2 = m1;  m1 = gr->CopyNtoC(n1,k);
+    if(fill)  gr->trig_plot(n0,n1,n2);
+    gr->line_plot(m1,m2);
+  }
+  gr->EndGroup();
+}
+ at end verbatim
+
+The last thing which we can do is derive our own class with new plotting functions. Good idea is to derive it from @code{mglGraph} (if you don't need extended window), or from @code{mglWindow} (if you need to extend window). So, in our case it will be
+ at verbatim
+class MyGraph : public mglGraph
+{
+public:
+  inline void Circle(mglPoint p, mreal r, const char *stl="", const char *opt="")
+  { circle(p.x,p.y,p.z, r, stl, opt); }
+  inline void CircleCS(mglPoint p, mreal r, const char *stl="", const char *opt="")
+  { circle_cs(p.x,p.y,p.z, r, stl, opt); }
+};
+ at end verbatim
+Note, that I use @code{inline} modifier for using the same binary code with different compilers. 
+
+So, the complete sample will be
+ at verbatim
+#include <mgl2/mgl.h>
+//---------------------------------------------------------
+#ifdef __cplusplus
+extern "C" {
+#endif
+void circle(HMGL gr, mreal x, mreal y, mreal z, mreal r, const char *stl, const char *opt);
+void circle_cs(HMGL gr, mreal x, mreal y, mreal z, mreal r, const char *stl, const char *opt);
+#ifdef __cplusplus
+}
+#endif
+//---------------------------------------------------------
+class MyGraph : public mglGraph
+{
+public:
+  inline void CircleCF(mglPoint p, mreal r, const char *stl="", const char *opt="")
+  { circle(p.x,p.y,p.z, r, stl, opt); }
+  inline void CircleCS(mglPoint p, mreal r, const char *stl="", const char *opt="")
+  { circle_cs(p.x,p.y,p.z, r, stl, opt); }
+};
+//---------------------------------------------------------
+void circle(HMGL gr, mreal x, mreal y, mreal z, mreal r, const char *stl, const char *opt)
+{
+  if(r<=0)  { gr->SetWarn(mglWarnNeg,"Circle"); return; }
+  static int cgid=1;  gr->StartGroup("Circle",cgid++);
+  gr->SaveState(opt);
+  const int n = gr->MeshNum>1?gr->MeshNum : 41;
+  bool fill = mglchr(stl,'@');
+  long pal=0;
+  char mk=gr->SetPenPal(stl,&pal);
+  mreal c=gr->NextColor(pal), d;
+  mreal k=(gr->GetNumPal(pal)>1)?gr->NextColor(pal):gr->AddTexture('k');
+  if(!fill) k=c;
+  gr->Reserve(2*n+2);
+  mglPoint q(NAN,NAN);
+  long n0,n1,n2,m1,m2,i;
+  n0 = fill ? gr->AddPnt(mglPoint(x,y,z),c,q,-1,3):-1;
+  n2 = mk ? gr->AddPnt(mglPoint(x,y,z),k,q,-1,3):-1;
+  if(mk)  gr->mark_plot(n2,mk);
+  for(i=0,m1=n1=-1;i<n;i++)
+  {
+    if(gr->Stop)  return;
+    mreal t = i*2*M_PI/(n-1.);
+    mglPoint p(x+r*cos(t), y+r*sin(t), z);
+    n2 = n1;  n1 = gr->AddPnt(p,c,q,-1,3);
+    m2 = m1;  m1 = gr->CopyNtoC(n1,k);
+    if(fill)  gr->trig_plot(n0,n1,n2);
+    gr->line_plot(m1,m2);
+  }
+  gr->EndGroup();
+}
+//---------------------------------------------------------
+void circle_cs(HMGL gr, mreal x, mreal y, mreal z, mreal r, const char *stl, const char *opt)
+{
+  static int cgid=1;  gr->StartGroup("CircleCS",cgid++);
+  gr->SaveState(opt);
+  const int n = gr->MeshNum>1?gr->MeshNum : 41;
+  bool fill = mglchr(stl,'@');
+  long ss = gr->AddTexture(stl);
+  const char *pen=0;
+  if(stl) pen = strchr(stl,':');
+  if(pen) pen++;
+  long pal=0;
+  char mk=gr->SetPenPal(pen,&pal);
+  mreal c=gr->GetC(ss,r);
+  mreal k=gr->NextColor(pal);
+  if(!fill) k=c;
+
+  gr->Reserve(2*n+2);
+  mglPoint q(NAN,NAN);
+  long n0,n1,n2,m1,m2,i;
+  n0 = fill ? gr->AddPnt(mglPoint(x,y,z),c,q,-1,3):-1;
+  n2 = mk ? gr->AddPnt(mglPoint(x,y,z),k,q,-1,3):-1;
+  if(mk)  gr->mark_plot(n2,mk);
+  for(i=0,m1=n1=-1;i<n;i++)
+  {
+    if(gr->Stop)  return;
+    mreal t = i*2*M_PI/(n-1.);
+    mglPoint p(x+r*cos(t), y+r*sin(t), z);
+    n2 = n1;  n1 = gr->AddPnt(p,c,q,-1,3);
+    m2 = m1;  m1 = gr->CopyNtoC(n1,k);
+    if(fill)  gr->trig_plot(n0,n1,n2);
+    gr->line_plot(m1,m2);
+  }
+  gr->EndGroup();
+}
+//---------------------------------------------------------
+int main()
+{
+  MyGraph gr;
+  gr.Box();
+  // first let draw circles with fixed colors
+  for(int i=0;i<10;i++)
+    gr.CircleCF(mglPoint(2*mgl_rnd()-1, 2*mgl_rnd()-1), mgl_rnd());
+  // now let draw circles with color scheme
+  for(int i=0;i<10;i++)
+    gr.CircleCS(mglPoint(2*mgl_rnd()-1, 2*mgl_rnd()-1), 2*mgl_rnd()-1);
+}
+ at end verbatim
+
+
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node mglDataA class, mglColor class, mglBase class, Other classes
+ at section User defined types (mglDataA class)
+ at nav{}
+
+ at code{mglData} class have abstract predecessor class @code{mglDataA}. Exactly the pointers to @code{mglDataA} instances are used in all plotting functions and some of data processing functions. This was done for taking possibility to define yours own class, which will handle yours own data (for example, complex numbers, or differently organized data). And this new class will be almost the same as @code{mglData} for plotting purposes.
+
+However, the most of data processing functions will be slower as if you used @code{mglData} instance. This is more or less understandable -- I don't know how data in yours particular class will be organized, and couldn't optimize the these functions generally.
+
+There are few virtual functions which must be provided in derived classes. This functions give:
+ at itemize @bullet
+ at item
+the sizes of the data (@code{GetNx}, @code{GetNy}, @code{GetNz}),
+ at item
+give data value and numerical derivatives for selected cell (@code{v}, @code{dvx}, @code{dvy}, @code{dvz}),
+ at item
+give maximal and minimal values (@code{Maximal}, @code{Minimal}) -- you can use provided functions (like @code{mgl_data_max} and @code{mgl_data_min}), but yours own realization can be more efficient,
+ at item
+give access to all element as in single array (@code{vthr}) -- you need this only if you want using MathGL's data processing functions.
+ at end itemize
+
+Let me, for example define class @code{mglComplex} which will handle complex number and draw its amplitude or phase, depending on flag @var{use_abs}:
+ at verbatim
+#include <complex>
+#include <mgl2/mgl.h>
+#define dual std::complex<double>
+class mglComplex : public mglDataA
+{
+public:
+  long nx;      ///< number of points in 1st dimensions ('x' dimension)
+  long ny;      ///< number of points in 2nd dimensions ('y' dimension)
+  long nz;      ///< number of points in 3d dimensions ('z' dimension)
+  dual *a;      ///< data array
+  bool use_abs; ///< flag to use abs() or arg()
+
+  inline mglComplex(long xx=1,long yy=1,long zz=1)
+  { a=0;  use_abs=true; Create(xx,yy,zz); }
+  virtual ~mglComplex()  { if(a)  delete []a; }
+
+  /// Get sizes
+  inline long GetNx() const { return nx;  }
+  inline long GetNy() const { return ny;  }
+  inline long GetNz() const { return nz;  }
+  /// Create or recreate the array with specified size and fill it by zero
+  inline void Create(long mx,long my=1,long mz=1)
+  { nx=mx;  ny=my;  nz=mz;  if(a) delete []a;
+  a = new dual[nx*ny*nz]; }
+  /// Get maximal value of the data
+  inline mreal Maximal() const  { return mgl_data_max(this);  }
+  /// Get minimal value of the data
+  inline mreal Minimal() const  { return mgl_data_min(this);  }
+
+protected:
+  inline mreal v(long i,long j=0,long k=0) const
+  { return use_abs ? abs(a[i+nx*(j+ny*k)]) : arg(a[i+nx*(j+ny*k)]);  }
+  inline mreal vthr(long i) const
+  { return use_abs ? abs(a[i]) : arg(a[i]);  }
+  inline mreal dvx(long i,long j=0,long k=0) const
+  { register long i0=i+nx*(j+ny*k);
+    std::complex<double> res=i>0? (i<nx-1? (a[i0+1]-a[i0-1])/2.:a[i0]-a[i0-1]) : a[i0+1]-a[i0];
+    return use_abs? abs(res) : arg(res);  }
+  inline mreal dvy(long i,long j=0,long k=0) const
+  { register long i0=i+nx*(j+ny*k);
+    std::complex<double> res=j>0? (j<ny-1? (a[i0+nx]-a[i0-nx])/2.:a[i0]-a[i0-nx]) : a[i0+nx]-a[i0];
+    return use_abs? abs(res) : arg(res);  }
+  inline mreal dvz(long i,long j=0,long k=0) const
+  { register long i0=i+nx*(j+ny*k), n=nx*ny;
+    std::complex<double> res=k>0? (k<nz-1? (a[i0+n]-a[i0-n])/2.:a[i0]-a[i0-n]) : a[i0+n]-a[i0];
+    return use_abs? abs(res) : arg(res);  }
+};
+int main()
+{
+  mglComplex dat(20);
+  for(long i=0;i<20;i++)
+    dat.a[i] = 3*exp(-0.05*(i-10)*(i-10))*dual(cos(M_PI*i*0.3), sin(M_PI*i*0.3));
+  mglGraph gr;
+  gr.SetRange('y', -M_PI, M_PI);  gr.Box();
+
+  gr.Plot(dat,"r","legend 'abs'");
+  dat.use_abs=false;
+  gr.Plot(dat,"b","legend 'arg'");
+  gr.Legend();
+  gr.WritePNG("complex.png");
+  return 0;
+}
+ at end verbatim
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node mglColor class, mglPoint class, mglDataA class, Other classes
+ at section mglColor class
+ at nav{}
+ at cindex mglColor
+
+Structure for working with colors. This structure is defined in @code{#include <mgl2/type.h>}.
+
+There are two ways to set the color in MathGL. First one is using of mreal values of red, green and blue channels for precise color definition. The second way is the using of character id. There are a set of characters specifying frequently used colors. Normally capital letter gives more dark color than lowercase one. @xref{Line styles}.
+
+ at deftypecv {Parameter} mglColor @code{mreal} {r, g, b, a}
+Reg, green and blue component of color.
+ at end deftypecv
+
+ at deftypemethod mglColor @code{} mglColor (@code{mreal} R, @code{mreal} G, @code{mreal} B, @code{mreal} A=@code{1})
+Constructor sets the color by mreal values of Red, Green, Blue and Alpha channels. These values should be in interval [0,1].
+ at end deftypemethod
+ at deftypemethod mglColor @code{} mglColor (@code{char} c=@code{'k'}, @code{mreal} bright=@code{1})
+Constructor sets the color from character id. The black color is used by default. Parameter @var{br} set additional ``lightness'' of color.
+ at end deftypemethod
+ at deftypemethod mglColor @code{void} Set (@code{mreal} R, @code{mreal} G, @code{mreal} B, @code{mreal} A=@code{1})
+Sets color from values of Red, Green, Blue and Alpha channels. These values should be in interval [0,1].
+ at end deftypemethod
+ at deftypemethod mglColor @code{void} Set (@code{mglColor} c, @code{mreal} bright=@code{1})
+Sets color as ``lighted'' version of color @var{c}.
+ at end deftypemethod
+ at deftypemethod mglColor @code{void} Set (@code{char} p, @code{mreal} bright=@code{1})
+Sets color from symbolic id.
+ at end deftypemethod
+ at deftypemethod mglColor @code{bool} Valid ()
+Checks correctness of the color.
+ at end deftypemethod
+ at deftypemethod mglColor @code{mreal} Norm ()
+Gets maximal of spectral component.
+ at end deftypemethod
+ at deftypemethod mglColor @code{bool} operator== (@code{const mglColor &}c)
+ at deftypemethodx mglColor @code{bool} operator!= (@code{const mglColor &}c)
+Compare with another color
+ at end deftypemethod
+
+ at deftypemethod mglColor @code{bool} operator*= (@code{mreal} v)
+Multiplies color components by number @var{v}.
+ at end deftypemethod
+
+ at deftypemethod mglColor @code{bool} operator+= (@code{const mglColor &}c)
+Adds color @var{c} component by component.
+ at end deftypemethod
+
+ at deftypemethod mglColor @code{bool} operator-= (@code{const mglColor &}c)
+Subtracts color @var{c} component by component.
+ at end deftypemethod
+
+
+ at deftypefn {Library Function} {mglColor} operator+ (@code{const mglColor &}a, @code{const mglColor &}b)
+Adds colors by its RGB values.
+ at end deftypefn
+ at deftypefn {Library Function} @code{mglColor} operator- (@code{const mglColor &}a, @code{const mglColor &}b)
+Subtracts colors by its RGB values.
+ at end deftypefn
+ at deftypefn {Library Function} @code{mglColor} operator* (@code{const mglColor &}a, @code{mreal} b)
+ at deftypefnx {Library Function} @code{mglColor} operator* (@code{mreal} a, @code{const mglColor &}b)
+Multiplies color by number.
+ at end deftypefn
+ at deftypefn {Library Function} @code{mglColor} operator/ (@code{const mglColor &}a, @code{mreal} b)
+Divide color by number.
+ at end deftypefn
+ at deftypefn {Library Function} @code{mglColor} operator! (@code{const mglColor &}a)
+Return inverted color.
+ at end deftypefn
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node mglPoint class, , mglColor class, Other classes
+ at section mglPoint class
+ at nav{}
+ at cindex mglPoint
+
+Structure describes point in space. This structure is defined in @code{#include <mgl2/type.h>}
+
+ at deftypecv {Parameter} mglPoint @code{mreal} {x, y, z, c}
+Point coordinates @{x,y,z@} and one extra value @var{c} used for amplitude, transparency and so on. By default all values are zero.
+ at end deftypecv
+
+ at deftypemethod mglPoint @code{} mglPoint (@code{mreal} X=@code{0}, @code{mreal} Y=@code{0}, @code{mreal} Z=@code{0}, @code{mreal} C=@code{0})
+Constructor sets the color by mreal values of Red, Green, Blue and Alpha channels. These values should be in interval [0,1].
+ at end deftypemethod
+
+ at deftypemethod mglPoint @code{bool} IsNAN ()
+Returns @code{true} if point contain NAN values.
+ at end deftypemethod
+ at deftypemethod mglPoint @code{mreal} norm ()
+Returns the norm @math{\sqrt@{x^2+y^2+z^2@}} of vector.
+ at end deftypemethod
+ at deftypemethod mglPoint @code{void} Normalize ()
+Normalizes vector to be unit vector.
+ at end deftypemethod
+ at deftypemethod mglPoint @code{mreal} val (@code{int} i)
+Returns point component: @var{x} for @var{i}=0, @var{y} for @var{i}=1, @var{z} for @var{i}=2, @var{c} for @var{i}=3.
+ at end deftypemethod
+
+
+ at deftypefn {Library Function} @code{mglPoint} operator+ (@code{const mglPoint &}a, @code{const mglPoint &}b)
+Point of summation (summation of vectors).
+ at end deftypefn
+ at deftypefn {Library Function} @code{mglPoint} operator- (@code{const mglPoint &}a, @code{const mglPoint &}b)
+Point of difference (difference of vectors).
+ at end deftypefn
+ at deftypefn {Library Function} @code{mglPoint} operator* (@code{mreal} a, @code{const mglPoint &}b)
+ at deftypefnx {Library Function} @code{mglPoint} operator* (@code{const mglPoint &}a, @code{mreal} b)
+Multiplies (scale) points by number.
+ at end deftypefn
+ at deftypefn {Library Function} @code{mglPoint} operator/ (@code{const mglPoint &}a, @code{mreal} b)
+Multiplies (scale) points by number 1/b.
+ at end deftypefn
+ at deftypefn {Library Function} @code{mreal} operator* (@code{const mglPoint &}a, @code{const mglPoint &}b)
+Scalar product of vectors.
+ at end deftypefn
+
+ at deftypefn {Library Function} @code{mglPoint} operator/ (@code{const mglPoint &}a, @code{const mglPoint &}b)
+Return vector of element-by-element product.
+ at end deftypefn
+
+ at deftypefn {Library Function} @code{mglPoint} operator^ (@code{const mglPoint &}a, @code{const mglPoint &}b)
+Cross-product of vectors.
+ at end deftypefn
+ at deftypefn {Library Function} @code{mglPoint} operator& (@code{const mglPoint &}a, @code{const mglPoint &}b)
+The part of @var{a} which is perpendicular to vector @var{b}.
+ at end deftypefn
+ at deftypefn {Library Function} @code{mglPoint} operator| (@code{const mglPoint &}a, @code{const mglPoint &}b)
+The part of @var{a} which is parallel to vector @var{b}.
+ at end deftypefn
+
+ at deftypefn {Library Function} @code{mglPoint} operator! (@code{const mglPoint &}a)
+Return vector perpendicular to vector @var{a}.
+ at end deftypefn
+ at deftypefn {Library Function} @code{mreal} mgl_norm (@code{const mglPoint &}a)
+Return the norm sqrt(|@var{a}|^2) of vector @var{a}.
+ at end deftypefn
+
+ at deftypefn {Library Function} @code{bool} operator== (@code{const mglPoint &}a, @code{const mglPoint &}b)
+Return true if points are the same.
+ at end deftypefn
+ at deftypefn {Library Function} @code{bool} operator!= (@code{const mglPoint &}a, @code{const mglPoint &}b)
+Return true if points are different.
+ at end deftypefn
+
+ at external{}
+
diff --git a/texinfo/overview_en.texi b/texinfo/overview_en.texi
new file mode 100644
index 0000000..9416ac8
--- /dev/null
+++ b/texinfo/overview_en.texi
@@ -0,0 +1,248 @@
+ at chapter Overview
+ at nav{}
+
+ at cindex MathGL overview
+
+MathGL is ...
+ at itemize @bullet
+ at item
+a library for making high-quality scientific graphics under Linux and Windows;
+ at item
+a library for the fast data plotting and handling of large data arrays;
+ at item
+a library for working in window and console modes and for easy embedding into other programs;
+ at item
+a library with large and growing set of graphics.
+ at end itemize
+
+ at menu
+* What is MathGL?::
+* MathGL features::
+* Installation::
+* Quick guide::
+* Changes from v.1::
+* Utilities::
+* Thanks::
+ at end menu
+
+ at external{}
+ at node What is MathGL?, MathGL features, , Overview
+ at section What is MathGL?
+ at nav{}
+
+A code for making high-quality scientific graphics under Linux and Windows. A  code for the fast handling and plotting of large data arrays. A code for working in window and console regimes and for easy including into another program. A code with large and renewal set of graphics. Exactly such a code I tried to put in MathGL library.
+
+At this version (@value{VERSION}) MathGL has more than 50 general types of graphics for 1d, 2d and 3d data arrays. It can export graphics to bitmap and vector (EPS or SVG) files. It has OpenGL interface and can be used from console programs. It has functions for data handling and script MGL language for simplification of data plotting. It also has several types of transparency and smoothed lighting, vector fonts and TeX-like symbol parsing, arbitrary curvilinear coordinate system and man [...]
+
+ at external{}
+ at node MathGL features, Installation, What is MathGL?, Overview
+ at section MathGL features
+ at nav{}
+
+MathGL can plot a wide range of graphics. It includes:
+ at itemize @bullet
+ at item
+one-dimensional (Plot, Area, Bars, Step, Stem, Torus, Chart, Error, Tube, Mark, @pxref{1D plotting});
+
+ at item
+two-dimensional plots (Mesh, Surf, Dens, Cont, ContF, Boxs, Axial, Fall, Belt, Tile, @pxref{2D plotting});
+
+ at item
+three-dimensional plots (Surf3, Dens3, Cont3, ContF3, Cloud-like, @pxref{3D plotting});
+
+ at item
+dual data plots: vector fields Vect, flow threads Flow, mapping chart Map, surfaces and isosurfaces, transparent or colored (i.e. with transparency or color varied) by other data SurfA, SurfC, Surf3A, Surf3C (@pxref{Dual plotting});
+
+ at item
+and so on. For details see @pxref{MathGL core}.
+ at end itemize
+
+In fact, I created the functions for drawing of all the types of scientific plots that I know. The list of plots is growing; if you need some special type of a plot then please email me @email{mathgl.abalakin@@gmail.com, e-mail} and it will appear in the new version.
+
+I tried to make plots as nice looking as possible: e.g., a surface can be transparent and highlighted by several (up to 10) light sources. Most of the drawing functions have 2 variants: simple one for the fast plotting of data, complex one for specifying of the exact position of the plot (including parametric representation). Resulting image can be saved in bitmap PNG, JPEG, GIF, TGA, BMP format, or in vector EPS, SVG or TeX format, or in 3D formats OBJ, OFF, STL, or in PRC format which  [...]
+
+All texts are drawn by vector fonts, which allows for high scalability and portability. Texts may contain commands for: some of the TeX-like symbols, changing index (upper or lower indexes) and the style of font inside the text string (@pxref{Font styles}). Texts of ticks are rotated with axis rotation. It is possible to create a legend of plot and put text in an arbitrary position on the plot. Arbitrary text encoding (by the help of function @code{setlocale()}) and UTF-16 encoding are s [...]
+
+Special class mglData is used for data encapsulation (@pxref{Data processing}). In addition to a safe creation and deletion of data arrays it includes functions for data processing (smoothing, differentiating, integrating, interpolating and so on) and reading of data files with automatic size determination. Class mglData can handle arrays with up to three dimensions (arrays which depend on up to 3 independent indexes @math{a_@{ijk@}}). Using an array with higher number of dimensions is n [...]
+
+There is fast evaluation of a textual mathematical expression (@pxref{Textual formulas}). It is based on string precompilation to tree-like code at the creation of class instance. At evaluation stage code performs only fast tree-walk and returns the value of the expression. In addition to changing data values, textual formulas are also used for drawing in @emph{arbitrary} curvilinear coordinates. A set of such curvilinear coordinates is limited only by user's imagination rather than a fi [...]
+
+ at external{}
+ at node Installation, Quick guide, MathGL features, Overview
+ at section Installation
+ at nav{}
+
+MathGL can be installed in 4 different ways.
+ at enumerate
+ at item
+Compile from sources. The cmake build system is useded in the library. To run it, one should execute commands: @code{cmake .} twice, after it @code{make} and @code{make install} with root/sudo rights. Sometimes after installation you may need to update the library list -- just execute @code{ldconfig} with root/sudo rights.
+
+There are several additional options which are switched off by default. They are: @code{enable-fltk, enable-glut, enable-qt4, enable-qt5} for ebabling FLTK, GLUT and/or Qt windows; @code{enable-jpeg, enable-gif, enable-hdf5} and so on for enabling corresponding file formats; @code{enable-all} for enabling all additional features. For using @code{double} as base internal data type use option @code{enable-double}. For enabling language interfaces use @code{enable-python, enable-octave} or  [...]
+
+There is known bug for building in MinGW -- you need to manually add linker option @code{-fopenmp} (i.e. @code{CMAKE_EXE_LINKER_FLAGS:STRING='-fopenmp'} and @code{CMAKE_SHARED_LINKER_FLAGS:STRING='-fopenmp'}) if you enable OpenMP support (i.e. if @code{enable-openmp=ON}).
+
+ at item
+Use a precompiled binary. There are binaries for MinGW (platform Win32). For a precompiled variant one needs only to unpack the archive to the location of the compiler (i.e. mathgl/lib in mingw/lib, mathgl/include in mingw/include and so on) or in arbitrary other folder and setup paths in compiler. By default, precompiled versions include the support of GSL (www.gsl.org) and PNG. So, one needs to have these libraries installed on system (it can be found, for example, at @uref{http://gnuw [...]
+
+ at item
+Install precompiled versions from standard packages (RPM, deb, DevPak and so on).
+ at end enumerate
+
+Note, you can download the latest sources (which can be not stable) from sourceforge.net SVN by command
+ at verbatim
+svn checkout http://svn.code.sf.net/p/mathgl/code/mathgl-2x mathgl-code
+ at end verbatim
+
+ at strong{IMPORTANT!} MathGL use a set of defines, which were determined at configure stage and may differ if used with non-default compiler (like using MathGL binaries compiled by MinGW in VisualStudio). There are @code{MGL_SYS_NAN, MGL_HAVE_TYPEOF, MGL_HAVE_PTHREAD, MGL_HAVE_ATTRIBUTE, MGL_HAVE_C99_COMPLEX, MGL_HAVE_RVAL}. I specially set them to @code{0} for Borland and Microsoft compilers due to compatibility reasons. Also default setting are good for GNU (gcc, mingw) and clang compile [...]
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node  Quick guide, Changes from v.1, Installation, Overview
+ at section Quick guide
+ at nav{}
+
+There are 3 steps to prepare the plot in MathGL: (1) prepare data to be plotted, (2) setup plot, (3) plot data. Let me show this on the example of surface plotting.
+
+First we need the data. MathGL use its own class @code{mglData} to handle data arrays (see @ref{Data processing}). This class give ability to handle data arrays by more or less format independent way. So, create it
+ at verbatim
+    int main()
+    {
+        mglData dat(30,40);	// data to for plotting
+        for(long i=0;i<30;i++)   for(long j=0;j<40;j++)
+            dat.a[i+30*j] = 1/(1+(i-15)*(i-15)/225.+(j-20)*(j-20)/400.);
+ at end verbatim
+Here I create matrix 30*40 and initialize it by formula. Note, that I use @code{long} type for indexes @var{i}, @var{j} because data arrays can be really large and @code{long} type will automatically provide proper indexing.
+
+Next step is setup of the plot. The only setup I need is axis rotation and lighting.
+ at verbatim
+        mglGraph gr;		// class for plot drawing
+        gr.Rotate(50,60);	// rotate axis
+        gr.Light(true);		// enable lighting
+ at end verbatim
+
+Everything is ready. And surface can be plotted.
+ at verbatim
+        gr.Surf(dat);		// plot surface
+ at end verbatim
+Basically plot is done. But I decide to add yellow (@samp{y} color, see @ref{Color styles}) contour lines on the surface. To do it I can just add:
+ at verbatim
+        gr.Cont(dat,"y");	// plot yellow contour lines
+ at end verbatim
+This demonstrate one of base MathGL concept (see, @ref{General concepts}) -- ``new drawing never clears things drawn already''. So, you can just consequently call different plotting functions to obtain ``combined'' plot. For example, if one need to draw axis then he can just call one more plotting function
+ at verbatim
+        gr.Axis();			// draw axis
+ at end verbatim
+
+Now picture is ready and we can save it in a file.
+ at verbatim
+        gr.WriteFrame("sample.png");	// save it
+    }
+ at end verbatim
+
+To compile your program, you need to specify the linker option @code{-lmgl}.
+
+This is enough for a compilation of console program or with external (non-MathGL) window library. If you want to use FLTK or Qt windows provided by MathGL then you need to add the option @code{-lmgl-wnd}.
+
+Fortran users also should add C++ library by the option @code{-lstdc++}. If library was built with @code{enable-double=ON} (this default for v.2.1 and later) then all real numbers must be real*8. You can make it automatic if use option @code{-fdefault-real-8}.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node  Changes from v.1, Utilities, Quick guide, Overview
+ at section Changes from v.1.*
+ at nav{}
+
+There are a lot of changes for v.2. Here I denote only main of them.
+ at itemize @bullet
+ at item
+mglGraph class is single plotter class instead of mglGraphZB, mglGraphPS and so on.
+ at item
+Text style and text color positions are swapped. I.e. text style @samp{r:C} give red centered text, but not roman dark cyan text as for v.1.*.
+ at item
+ColumnPlot() indexing is reverted.
+ at item
+Move most of arguments of plotting functions into the string parameter and/or options.
+ at item
+``Bright'' colors (like @{b8@}) can be used in color schemes and line styles.
+ at item
+Intensively use pthread internally for parallelization of drawing and data processing.
+ at item
+Add tick labels rotation and skipping. Add ticks in time/date format.
+ at item
+New kinds of plots (Tape(), Label(), Cones(), ContV()). Extend existing plots. New primitives (Circle(), Ellipse(), Rhomb(), ...). New plot positioning (MultiPlot(), GridPlot())
+ at item
+Improve MGL scripts. Add 'ask' command and allow string concatenation from different lines.
+ at item
+Export to LaTeX and to 3D formats (OBJ, OFF, STL).
+ at item
+Add pipes support in utilities (@code{mglconv, mglview}).
+ at end itemize
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node  Utilities, Thanks, Changes from v.1, Overview
+ at section Utilities for parsing MGL
+ at nav{}
+
+MathGL library provides several tools for parsing MGL scripts. There is tools saving it to bitmap or vectorial images (@code{mglconv}). Tool @code{mglview} show MGL script and allow to rotate and setup the image. Another feature of @code{mglview} is loading *.mgld files (see @code{ExportMGLD()}) for quick viewing 3d pictures.
+
+Both tools have similar set of arguments. They can be name of script file or options. You can use @samp{-} as script name for using standard input (i.e. pipes). Options are:
+ at itemize
+ at item @strong{-1} @var{str}
+set @var{str} as argument $1 for script;
+ at item ...
+...
+ at item @strong{-9} @var{str}
+set @var{str} as argument $9 for script;
+ at item @strong{-L} @var{loc}
+set locale to @var{loc};
+ at item @strong{-s} @var{fname}
+set MGL script for setting up the plot;
+ at item @strong{-h}
+print help message.
+ at end itemize
+Additionally @code{mglconv} have following options:
+ at itemize
+ at item @strong{-A} @var{val}
+add @var{val} into the list of animation parameters;
+ at item @strong{-C} @var{v1}:@var{v2}[:@var{dv}]
+add values from @var{v1} ot @var{v2} with step @var{dv} (default is 1) into the list of animation parameters;
+ at item @strong{-o} @var{name}
+set output file name;
+ at item @strong{-n}
+disable default output (script should save results by itself);
+ at item @strong{-S} @var{val}
+set set scaling factor for @ref{setsize};
+ at item @strong{-q} @var{val}
+set @ref{quality} for output (val=0...9).
+ at end itemize
+
+Also you can create animated GIF file or a set of JPEG files with names @samp{frameNNNN.jpg} (here @samp{NNNN} is frame index). Values of the parameter @code{$0} for making animation can be specified inside the script by comment @code{##a val} for each value @code{val} (one comment for one value) or by option(s) @samp{-A val}. Also you can specify a cycle for animation by comment @code{##c v1 v2 dv} or by option @code{-C v1:v2:dv}. In the case of found/specified animation parameters, too [...]
+
+
+MathGL also provide another simple tool @code{mgl.cgi} which parse MGL script from CGI request and send back produced PNG file. Usually this program should be placed in @code{/usr/lib/cgi-bin/}. But you need to put this program by yourself due to possible security issues and difference of Apache server settings.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Thanks, , Utilities, Overview
+ at section Thanks
+ at nav{}
+
+ at itemize @bullet
+ at item
+My special thanks to my wife for the patience during the writing of this library and for the help in documentation writing and spelling.
+ at item
+I'm thankful to my coauthors D. Kulagin and M. Vidassov for help in developing MathGL.
+ at item
+I'm thankful to Diego Sejas Viscarra for developing mgltex, contribution to fractal generation and fruitful suggestions.
+ at item
+I'm thankful to D. Eftaxiopoulos, D. Haley, V. Lipatov and S.M. Plis for making binary packages for Linux.
+ at item
+I'm thankful to S. Skobelev, C. Mikhailenko, M. Veysman, A. Prokhorov, A. Korotkevich, V. Onuchin, S.M. Plis, R. Kiselev, A. Ivanov, N. Troickiy and V. Lipatov for fruitful comments.
+ at item
+I'm thankful to sponsors M. Veysman (@uref{http://jiht.ru/en/about/structure.php?set_filter_structure=Y&structure_UF_DEPARTMENT=241&filter=Y&set_filter=Y, IHED RAS}) and A. Prokhorov (@url{www.datadvance.net, DATADVANCE}).
+ at end itemize
+
+Javascript interface was developed with support of @url{www.datadvance.net, DATADVANCE} company.
+
+ at external{}
diff --git a/texinfo/overview_ru.texi b/texinfo/overview_ru.texi
new file mode 100644
index 0000000..4d998fe
--- /dev/null
+++ b/texinfo/overview_ru.texi
@@ -0,0 +1,252 @@
+ at chapter Обзор MathGL
+ at nav{}
+
+ at cindex Обзор MathGL
+
+MathGL это ...
+ at itemize @bullet
+ at item
+библиотека для создания высококачественной научной графики под Linux и Windows;
+ at item
+библиотека для быстрого обработки и отображения больших массивов данных;
+ at item
+библиотека для работы в оконном и консольном режимах;
+ at item
+библиотека с большим набором базовых типов графиков.
+ at end itemize
+
+ at menu
+* What is MathGL?::
+* MathGL features::
+* Installation::
+* Quick guide::
+* Changes from v.1::
+* Utilities::
+* Thanks::
+ at end menu
+
+ at external{}
+ at node What is MathGL?, MathGL features, , Overview
+ at section Что такое MathGL?
+ at nav{}
+
+Код для создания качественной научной графики на различных платформах. Код для быстрой обработки и отображения больших массивов данных. Код для работы в графическом и консольном режимах и легкого интегрирования в другие программы. Код с большим обновляемым набором графиков и инструментами обработки данных. Именно такого кода мне не хватало в последние годы при работе на персональных компьютерах и на кластерах. И именно такой код я постарался создать в библиотеке MathGL.
+
+На данный момент (версия @value{VERSION}) MathGL это более 50 основных типов графиков для одно-, двух- и трехмерных массивов, возможность экспорта в растровые и векторные (EPS или SVG) файлы, интерфейс для OpenGL и возможность запуска в консольном режиме, функции для обработки данных и даже простейший командный (интерпретируемый) язык MGL для упрощения построения графиков. Кроме того, есть несколько типов прозрачности, гладкое освещение, векторные шрифты, TeX-ие команды в надписях, произ [...]
+
+ at external{}
+ at node MathGL features, Installation, What is MathGL?, Overview
+ at section Возможности MathGL
+ at nav{}
+
+Библиотека MathGL позволяет строить широкий класс графиков, включая:
+ at itemize @bullet
+ at item
+рисование одномерных массивов (Plot, Area, Bars, Step, Stem, Torus, Chart, Error, Tube, Mark, @pxref{1D plotting});
+
+ at item
+рисование двумерных массивов (Mesh, Surf, Dens, Cont, ContF, Boxs, Axial, Fall, Belt, Tile, @pxref{2D plotting});
+
+ at item
+рисование трехмерных массивов (Surf3, Dens3, Cont3, ContF3, Cloud-like, @pxref{3D plotting});
+
+ at item
+рисование нескольких связанных массивов: векторные поля Vect, линии тока Flow, точечное отображение Map, поверхности с прозрачностью или цветом, определяемым другим массивом SurfA, SurfC, Surf3A, Surf3C (@pxref{Dual plotting});
+
+ at item
+и другие (см. @pxref{MathGL core}).
+ at end itemize
+
+Фактически, я постарался реализовать все известные мне типы научных графиков. Список графиков постоянно пополняется, и если Вам нужен какой-то новый вариант, пишите на @email{mathgl.abalakin@@gmail.com, e-mail}, и в новой версии библиотеки этот график появится.
+
+Я постарался сделать графики максимально красивыми -- поверхности могут быть прозрачными и освещены произвольно расположенными источниками света (максимальное их количество 10). Большинство функций рисования имеет два варианта: простой для быстрого построения картинки и более сложный для детальной настройки отображения, включающего в том числе возможность параметрического задания всех массивов. Получившееся изображение можно сохранить в растровом формате PNG, JPEG, GIF, TGA или BMP; в ве [...]
+
+Все надписи выводятся векторным шрифтом, что обеспечивает их хорошую масштабируемость и переносимость. Текст может содержать команды для большинства ТеХ-их символов, изменения положения (верхний и нижний индексы) и стиля шрифта внутри строки текста (@pxref{Font styles}). Текст меток поворачивается вместе с осями. На график можно вывести описание кривых (легенду) и поместить надпись в произвольную точку экрана или пустить ее вдоль кривой. Поддерживаются произвольные кодировки текста (с по [...]
+
+Для представления данных используется специальный класс mglData (@pxref{Data processing}). Помимо безопасного создания и удаления массивов, он включает функции по их обработке (дифференцированию, интегрированию, сглаживанию, интерполяции и т.д.) и чтению текстового файла с автоматическим определением размеров данных. Класс mglData позволяет работать с массивами размерности вплоть до 3 (массивы, зависящие от трех независимых индексов @math{a_@{ijk@}}). Использование массивов с большим чис [...]
+
+Для @emph{быстрого} вычисления значения выражения, заданного текстовой строкой (@pxref{Textual formulas}). Он основан на компиляции строки в древоподобную структуру при создании экземпляра класса. На этапе вычисления происходит быстрый обход дерева с выдачей результата для конкретных значений переменных. Помимо изменения значений массива данных, текстовые формулы используются для рисования в @emph{произвольной} криволинейной системе координат. Набор таких координат ограничивается только  [...]
+
+ at external{}
+ at node Installation, Quick guide, MathGL features, Overview
+ at section Установка MathGL
+ at nav{}
+
+Установка библиотеки возможна 4-мя способами.
+ at enumerate
+ at item
+Скомпилировать библиотеку непосредственно из исходных файлов. С библиотекой поставляется файлы для системы сборки CMake. Для его запуска достаточно в командной строке выполнить 3 команды: сначала @code{cmake .} дважды, далее @code{make} и, наконец, с правами суперпользователя @code{make install}. Иногда после компиляции библиотеки может потребоваться обновление списка библиотека в системе -- выполните команду @code{ldconfig} с правами суперпользователя.
+
+Есть несколько дополнительных опций, которые по умолчанию отключены. К их числу относятся: @code{enable-fltk, enable-glut, enable-qt4, enable-qt5} для поддержки FLTK, GLUT и/или Qt окон; @code{enable-jpeg, enable-gif, enable-hdf5} для поддержки соответствующих форматов; @code{enable-all} для включения всех возможностей. Для использования типа @code{double} для внутреннего хранения данных используйте опцию @code{enable-double}. Для создания интерфейсов к другим языкам (кроме С/Фортран/MGL [...]
+
+При сборке с помощью MinGW необходимо дополнительно установить опцию сборки @code{-fopenmp} (т.е. @code{CMAKE_EXE_LINKER_FLAGS:STRING='-fopenmp'} и @code{CMAKE_SHARED_LINKER_FLAGS:STRING='-fopenmp'}) если включена поддержка OpenMP (@code{enable-openmp=ON}).
+
+
+ at item
+Использовать предварительно скомпилированные файлы -- с библиотекой поставляются файлы для MinGW (платформа Win32). В скомпилированной версии достаточно распаковать заголовочные файлы в папку с заголовочными файлами и библиотеку libmgl.a в папку с библиотеками. По умолчанию, скомпилированная версия включают поддержку GSL (www.gsl.org), PNG, GIF и JPEG. Соответственно, при сборке программы эти библиотеки должны быть установлены (их можно найти на @uref{http://gnuwin32.sourceforge.net/pack [...]
+ at item
+Установить из стандартных пакетов (RPM, deb, DevPak и пр.).
+ at end enumerate
+
+Последнюю версию (которая может быть не стабильна) можно загрузить с  sourceforge.net SVN с помощью команды
+ at verbatim
+svn checkout http://svn.code.sf.net/p/mathgl/code/mathgl-2x mathgl-code
+ at end verbatim
+
+ at strong{ВАЖНО!} MathGL использует набор defines, определяемых на этапе конфигурирования библиотеки. Это @code{MGL_SYS_NAN, MGL_HAVE_TYPEOF, MGL_HAVE_PTHREAD, MGL_HAVE_ATTRIBUTE, MGL_HAVE_C99_COMPLEX, MGL_HAVE_RVAL}. Они могут отличаться при использовании бинарников скомпилированных другим компилятором (например при использовании скомпилированных MinGW бинарников в VisualStudio). Я специально устанавливаю их в @code{0} для компиляторов Borland и Microsoft из соображений совместимости. Кро [...]
+
+
+ at c TODO Translate it!
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node  Quick guide, Changes from v.1, Installation, Overview
+ at section Quick guide
+ at nav{}
+
+There are 3 steps to prepare the plot in MathGL: (1) prepare data to be plotted, (2) setup plot, (3) plot data. Let me show this on the example of surface plotting.
+
+First we need the data. MathGL use its own class @code{mglData} to handle data arrays (see @ref{Data processing}). This class give ability to handle data arrays by more or less format independent way. So, create it
+ at verbatim
+    int main()
+    {
+        mglData dat(30,40);	// data to for plotting
+        for(long i=0;i<30;i++)   for(long j=0;j<40;j++)
+            dat.a[i+30*j] = 1/(1+(i-15)*(i-15)/225.+(j-20)*(j-20)/400.);
+ at end verbatim
+Here I create matrix 30*40 and initialize it by formula. Note, that I use @code{long} type for indexes @var{i}, @var{j} because data arrays can be really large and @code{long} type will automatically provide proper indexing.
+
+Next step is setup of the plot. The only setup I need is axis rotation and lighting.
+ at verbatim
+        mglGraph gr;		// class for plot drawing
+        gr.Rotate(50,60);	// rotate axis
+        gr.Light(true);		// enable lighting
+ at end verbatim
+
+Everything is ready. And surface can be plotted.
+ at verbatim
+        gr.Surf(dat);		// plot surface
+ at end verbatim
+Basically plot is done. But I decide to add yellow (@samp{y} color, see @ref{Color styles}) contour lines on the surface. To do it I can just add:
+ at verbatim
+        gr.Cont(dat,"y");	// plot yellow contour lines
+ at end verbatim
+This demonstrate one of base MathGL concept (see, @ref{General concepts}) -- ``new drawing never clears things drawn already''. So, you can just consequently call different plotting functions to obtain ``combined'' plot. For example, if one need to draw axis then he can just call one more plotting function
+ at verbatim
+        gr.Axis();			// draw axis
+ at end verbatim
+
+Now picture is ready and we can save it in a file.
+ at verbatim
+        gr.WriteFrame("sample.png");	// save it
+    }
+ at end verbatim
+
+To compile your program, you need to specify the linker option @code{-lmgl}.
+
+This is enough for a compilation of console program or with external (non-MathGL) window library. If you want to use FLTK or Qt windows provided by MathGL then you need to add the option @code{-lmgl-wnd}.
+
+При использовании фортрана необходимо также включить библиотеку @code{-lstdc++}. Кроме того, если библиотека была собрана с опцией @code{enable-double=ON} (по умолчанию в версии 2.1 и более поздних), то все вещественные числа должны быть типа real*8. Это можно включить по умолчанию опцией @code{-fdefault-real-8}.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node  Changes from v.1, Utilities, Quick guide, Overview
+ at section Changes from v.1.*
+ at nav{}
+
+There are a lot of changes for v.2. Here I denote only main of them.
+ at itemize @bullet
+ at item
+mglGraph class is single plotter class instead of mglGraphZB, mglGraphPS and so on.
+ at item
+Text style and text color positions are swapped. I.e. text style @samp{r:C} give red centered text, but not roman dark cyan text as for v.1.*.
+ at item
+ColumnPlot() indexing is reverted.
+ at item
+Move most of arguments of plotting functions into the string parameter and/or options.
+ at item
+``Bright'' colors (like @{b8@}) can be used in color schemes and line styles.
+ at item
+Intensively use pthread internally for parallelization of drawing and data processing.
+ at item
+Add tick labels rotation and skipping. Add ticks in time/date format.
+ at item
+New kinds of plots (Tape(), Label(), Cones(), ContV()). Extend existing plots. New primitives (Circle(), Ellipse(), Rhomb(), ...). New plot positioning (MultiPlot(), GridPlot())
+ at item
+Improve MGL scripts. Add 'ask' command and allow string concatenation from different lines.
+ at item
+Export to LaTeX and to 3D formats (OBJ, OFF, STL).
+ at item
+Add pipes support in utilities (@code{mglconv, mglview}).
+ at end itemize
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node  Utilities, Thanks, Changes from v.1, Overview
+ at section Utilities for parsing MGL
+ at nav{}
+
+MathGL library provides several tools for parsing MGL scripts. There is tools saving it to bitmap or vectorial images (@code{mglconv}). Tool @code{mglview} show MGL script and allow to rotate and setup the image. Another feature of @code{mglview} is loading *.mgld files (see @code{ExportMGLD()}) for quick viewing 3d pictures.
+
+Both tools have similar set of arguments. They can be name of script file or options. You can use @samp{-} as script name for using standard input (i.e. pipes). Options are:
+ at itemize
+ at item @strong{-1} @var{str}
+set @var{str} as argument $1 for script;
+ at item ...
+...
+ at item @strong{-9} @var{str}
+set @var{str} as argument $9 for script;
+ at item @strong{-L} @var{loc}
+set locale to @var{loc};
+ at item @strong{-s} @var{fname}
+set MGL script for setting up the plot;
+ at item @strong{-h}
+print help message.
+ at end itemize
+Additionally @code{mglconv} have following options:
+ at itemize
+ at item @strong{-A} @var{val}
+add @var{val} into the list of animation parameters;
+ at item @strong{-C} @var{v1}:@var{v2}[:@var{dv}]
+add values from @var{v1} ot @var{v2} with step @var{dv} (default is 1) into the list of animation parameters;
+ at item @strong{-o} @var{name}
+set output file name;
+ at item @strong{-n}
+disable default output (script should save results by itself);
+ at item @strong{-S} @var{val}
+set set scaling factor for @ref{setsize};
+ at item @strong{-q} @var{val}
+set @ref{quality} for output (val=0...9).
+ at end itemize
+
+Also you can create animated GIF file or a set of JPEG files with names @samp{frameNNNN.jpg} (here @samp{NNNN} is frame index). Values of the parameter @code{$0} for making animation can be specified inside the script by comment @code{##a val} for each value @code{val} (one comment for one value) or by option(s) @samp{-A val}. Also you can specify a cycle for animation by comment @code{##c v1 v2 dv} or by option @code{-C v1:v2:dv}. In the case of found/specified animation parameters, too [...]
+
+
+MathGL also provide another simple tool @code{mgl.cgi} which parse MGL script from CGI request and send back produced PNG file. Usually this program should be placed in @code{/usr/lib/cgi-bin/}. But you need to put this program by yourself due to possible security issues and difference of Apache server settings.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Thanks, , Utilities, Overview
+ at section Благодарности
+ at nav{}
+
+
+ at itemize @bullet
+ at item
+Моя специальная благодарность моей жене за терпение во время написания библиотеки.
+ at item
+Я благодарен моим соавторам Д. Кулагину и М. Видассову за помощь в разработке MathGL.
+ at item
+Я благодарен Diego Sejas Viscarra за разработку mgltex, вклад в генерацию фракталов и продуктивные предложения и обсуждения.
+ at item
+Я благодарен D. Eftaxiopoulos, D. Haley, В. Липатову и С. Плису за создание бинарных пакетов для Linux.
+ at item
+Я благодарен С. Скобелеву, К. Михайленко, М. Вейсману, A. Прохорову, A. Короткевичу, В. Онучину, С. Плису, Р. Киселеву, A. Иванову, Н. Троицкому and В. Липатову за продуктивные предложения и обсуждения.
+ at item
+Я благодарен спонсорам М. Вейсману (@url{http://www.jiht.ru/about/structure.php?set_filter_structure=Y&structure_UF_DEPARTMENT=241&filter=Y&set_filter=Y, ОИВТ РАН}) и A. Прохорову (@url{www.datadvance.net, DATADVANCE}).
+ at end itemize
+
+Javascript интерфейс был разработан при поддержке компании @url{www.datadvance.net, DATADVANCE}.
+
+
+ at external{}
diff --git a/texinfo/parse_en.texi b/texinfo/parse_en.texi
new file mode 100644
index 0000000..58de41e
--- /dev/null
+++ b/texinfo/parse_en.texi
@@ -0,0 +1,505 @@
+
+ at c ------------------------------------------------------------------
+ at chapter MGL scripts
+ at nav{}
+
+MathGL library supports the simplest scripts for data handling and plotting. These scripts can be used independently (with the help of UDAV, mglconv, mglview programs and others
+ at ifclear UDAV
+, @pxref{Utilities}) or in the frame of the library using.
+ at end ifclear
+
+ at menu
+* MGL definition::
+* Program flow commands::
+* LaTeX package::
+ at ifclear UDAV
+* mglParse class::
+ at end ifclear
+ at end menu
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node MGL definition, Program flow commands, , MGL scripts
+ at section MGL definition
+ at nav{}
+
+MGL script language is rather simple. Each string is a command. First word of string is the name of command. Other words are command arguments. Words are separated from each other by space or tabulation symbol. The upper or lower case of words is important, i.e. variables @var{a} and @var{A} are different variables. Symbol @samp{#} starts the comment (all characters after # will be ignored). The exception is situation when @samp{#} is a part of some string. Also options can be specified  [...]
+
+If string contain references to external parameters (substrings @samp{$0}, @samp{$1} ... @samp{$9}) or definitions (substrings @samp{$a}, @samp{$b} ... @samp{$z}) then before execution the values of parameter/definition will be substituted instead of reference. It allows to use the same MGL script for different parameters (filenames, paths, condition and so on).
+
+Argument can be a string, a variable (data arrays) or a number (scalars).
+ at itemize @bullet
+ at item
+The string is any symbols between ordinary marks @samp{'}. Long strings can be concatenated from several lines by @samp{\} symbol. I.e. the string @samp{'a +\<br> b'} will give string @samp{'a + b'} (here @samp{<br>} is newline). There are several operations which can be performed with string:
+ at itemize @bullet
+ at item Concatenation of strings and numbers using @samp{,} with out spaces (for example, @samp{'max(u)=',u.max,' a.u.'} or @samp{'u=',!(1+i2)} for complex numbers);
+ at item Getting n-th symbol of the string using @samp{[]} (for example, @samp{'abc'[1]} will give @code{'b'});
+ at item Adding value to the last character of the string using @samp{+} (for example, @samp{'abc'+3} will give @code{'abf'}).
+ at end itemize
+
+ at item
+Usually variable have a name which is arbitrary combination of symbols (except spaces and @samp{'}) started from a letter. Note, you can start an expression with @samp{!} symbol if you want to use complex values. For example, the code @code{new x 100 'x':copy !b !exp(1i*x)} will create real valued data @var{x} and complex data @var{b}, which is equal to @math{exp(I*x)}, where @math{I^2=-1}. A temporary array can be used as variable too:
+ at itemize @bullet
+ at item
+sub-arrays (like in @ref{subdata} command) as command argument. For example, @code{a(1)} or @code{a(1,:)} or @code{a(1,:,:)} is second row, @code{a(:,2)} or @code{a(:,2,:)} is third column, @code{a(:,:,0)} is first slice and so on. Also you can extract a part of array from m-th to n-th element by code @code{a(m:n,:,:)} or just @code{a(m:n)}.
+
+ at item
+any column combinations defined by formulas, like @code{a('n*w^2/exp(t)')} if names for data columns was specified (by @ref{idset} command or in the file at string started with @code{##}).
+
+ at item
+any expression (without spaces) of existed variables produce temporary variable. For example, @samp{sqrt(dat(:,5)+1)} will produce temporary variable with data values equal to @code{tmp[i,j] = sqrt(dat[i,5,j]+1)}.
+
+ at item
+temporary variable of higher dimensions by help of []. For example, @samp{[1,2,3]} will produce a temporary vector of 3 elements @{1, 2, 3@}; @samp{[[11,12],[21,22]]} will produce matrix 2*2 and so on. Here you can join even an arrays of the same dimensions by construction like @samp{[v1,v2,...,vn]}.
+
+ at item
+result of code for making new data (@pxref{Make another data}) inside @{@}. For example, @samp{@{sum dat 'x'@}} produce temporary variable which contain result of summation of @var{dat} along direction 'x'. This is the same array @var{tmp} as produced by command @samp{sum tmp dat 'x'}. You can use nested constructions, like @samp{@{sum @{max dat 'z'@} 'x'@}}.
+ at end itemize
+Temporary variables can not be used as 1st argument for commands which create (return) the data (like @samp{new}, @samp{read}, @samp{hist} and so on).
+
+ at item
+Special names @code{nan=#QNAN, inf=INFINITY, rnd=random value, pi=3.1415926..., on=1, off=0, all=-1, :=-1}, variables with suffixes (@pxref{Data information}), names defined by @ref{define} command, time values (in format "hh-mm-ss_DD.MM.YYYY", "hh-mm-ss" or "DD.MM.YYYY") are treated as number. Also results of formulas with sizes 1x1x1 are treated as number (for example, @samp{pi/dat.nx}). 
+ at end itemize
+Before the first using all variables must be defined with the help of commands, like, @ref{new}, @ref{var}, @ref{list}, @ref{copy}, @ref{read}, @ref{hist}, @ref{sum} and so on (see sections @ref{Data constructor}, @ref{Data filling} and @ref{Make another data}).
+
+Command may have several set of possible arguments (for example, @code{plot ydat} and @code{plot xdat ydat}). All command arguments for a selected set must be specified. However, some arguments can have default values. These argument are printed in [], like @code{text ydat ['stl'='']} or @code{text x y 'txt' ['fnt'='' size=-1]}. At this, the record @code{[arg1 arg2 arg3 ...]} means @code{[arg1 [arg2 [arg3 ...]]]}, i.e. you can omit only tailing arguments if you agree with its default val [...]
+
+You can provide several variants of arguments for a command by using @samp{?} symbol for separating them. The actual argument being used is set by @ref{variant}. At this, the last argument is used if the value of @ref{variant} is large than the number of provided variants. By default the first argument is used (i.e. as for @code{variant 0}). For example, the first plot will be drawn by blue (default is the first argument @samp{b}), but the plot after @code{variant 1} will be drawn by red [...]
+ at verbatim
+fplot 'x' 'b'?'r'
+variant 1
+fplot 'x^3' 'b'?'r|'
+ at end verbatim
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Program flow commands, LaTeX package, MGL definition, MGL scripts
+ at section Program flow commands
+ at nav{}
+
+Below I show commands to control program flow, like, conditions, loops, define script arguments and so on. Other commands can be found in chapters @ref{MathGL core} and @ref{Data processing}. Note, that some of program flow commands (like @ref{define}, @ref{ask}, @ref{call}, @ref{for}, @ref{func}) should be placed alone in the string.
+
+ at cindex chdir
+ at anchor{chdir}
+ at deftypefn {MGL command} {} chdir 'path'
+Changes the current directory to @var{path}.
+ at end deftypefn
+
+ at cindex ask
+ at anchor{ask}
+ at deftypefn {MGL command} {} ask $N 'question'
+Sets @var{N}-th script argument to answer which give the user on the @var{question}. Usually this show dialog with question where user can enter some text as answer. Here @var{N} is digit (0...9) or alpha (a...z).
+ at end deftypefn
+
+ at cindex define
+ at anchor{define}
+ at deftypefn {MGL command} {} define $N smth
+Sets @var{N}-th script argument to @var{smth}. Note, that @var{smth} is used as is (with @samp{'} symbols if present). Here @var{N} is digit (0...9) or alpha (a...z).
+ at end deftypefn
+ at deftypefn {MGL command} {} define name smth
+Create scalar variable @code{name} which have the numeric value of @code{smth}. Later you can use this variable as usual number.
+ at end deftypefn
+ at cindex defchr
+ at anchor{defchr}
+ at deftypefn {MGL command} {} defchr $N smth
+Sets @var{N}-th script argument to character with value evaluated from @var{smth}. Here @var{N} is digit (0...9) or alpha (a...z).
+ at end deftypefn
+ at cindex defnum
+ at anchor{defnum}
+ at deftypefn {MGL command} {} defnum $N smth
+Sets @var{N}-th script argument to number with value evaluated from @var{smth}. Here @var{N} is digit (0...9) or alpha (a...z).
+ at end deftypefn
+
+ at comment  @cindex defpal
+ at comment  @anchor{defpal}
+ at comment  @deftypefn {MGL command} {} defpal $N smth
+ at comment  Sets @var{N}-th script argument to palette character at position evaluated from @var{smth}. Here @var{N} is digit (0...9) or alpha (a...z).
+ at comment  @end deftypefn
+
+ at cindex call
+ at anchor{call}
+ at deftypefn {MGL command} {} call 'funcname' [ARG1 ARG2 ... ARG9]
+Executes function @var{fname} (or script if function is not found). Optional arguments will be passed to functions. See also @ref{func}.
+ at end deftypefn
+ at cindex func
+ at anchor{func}
+ at deftypefn {MGL command} {} func 'funcname' [narg=0]
+Define the function @var{fname} and number of required arguments. The arguments will be placed in script parameters $1, $2, ... $9. Note, script execution is stopped at @code{func} keyword, similarly to @ref{stop} command. See also @ref{return}.
+ at end deftypefn
+ at cindex return
+ at anchor{return}
+ at deftypefn {MGL command} {} return
+Return from the function. See also @ref{func}.
+ at end deftypefn
+
+ at cindex load
+ at anchor{load}
+ at deftypefn {MGL command} {} load 'filename'
+Load additional MGL command from external module (DLL or .so), located in file @var{filename}. This module have to contain array with name @code{mgl_cmd_extra} of type  @code{mglCommand}, which describe provided commands.
+ at end deftypefn
+
+
+ at cindex if
+ at anchor{if}
+ at deftypefn {MGL command} {} if dat 'cond'
+Starts block which will be executed if @var{dat} satisfy to @var{cond}.
+ at end deftypefn
+ at deftypefn {MGL command} {} if @code{val}
+Starts block which will be executed if @code{val} is nonzero.
+ at end deftypefn
+ at cindex elseif
+ at anchor{elseif}
+ at deftypefn {MGL command} {} elseif dat 'cond'
+Starts block which will be executed if previous @code{if} or @code{elseif} is false and @var{dat} satisfy to @var{cond}.
+ at end deftypefn
+ at deftypefn {MGL command} {} elseif @code{val}
+Starts block which will be executed if previous @code{if} or @code{elseif} is false and @code{val} is nonzero.
+ at end deftypefn
+ at cindex else
+ at anchor{else}
+ at deftypefn {MGL command} {} else
+Starts block which will be executed if previous @code{if} or @code{elseif} is false.
+ at end deftypefn
+ at cindex endif
+ at anchor{endif}
+ at deftypefn {MGL command} {} endif
+Finishes @code{if/elseif/else} block.
+ at end deftypefn
+
+ at cindex for
+ at anchor{for}
+ at deftypefn {MGL command} {} for $N @code{v1 v2 [dv=1]}
+Starts cycle with $@var{N}-th argument changing from @var{v1} to @var{v2} with the step @var{dv}. Here @var{N} is digit (0...9) or alpha (a...z).
+ at end deftypefn
+ at deftypefn {MGL command} {} for $N dat
+Starts cycle with $@var{N}-th argument changing for @var{dat} values. Here @var{N} is digit (0...9) or alpha (a...z).
+ at end deftypefn
+ at cindex next
+ at anchor{next}
+ at deftypefn {MGL command} {} next
+Finishes @code{for} cycle.
+ at end deftypefn
+
+ at cindex once
+ at anchor{once}
+ at deftypefn {MGL command} {} once @code{val}
+The code between @code{once on} and @code{once off} will be executed only once. Useful for large data manipulation in programs like UDAV.
+ at end deftypefn
+ at cindex stop
+ at anchor{stop}
+ at deftypefn {MGL command} {} stop
+Terminate execution.
+ at end deftypefn
+
+ at cindex variant
+ at anchor{variant}
+ at deftypefn {MGL command} {} variant @code{val}
+Set variant of argument(s) separated by @samp{?} symbol to be used in further commands.
+ at end deftypefn
+
+
+ at cindex rkstep
+ at anchor{rkstep}
+ at deftypefn {MGL command} {} rkstep eq1;... var1;... [@code{dt=1}]
+Make one step for ordinary differential equation(s) @{var1' = eq1, ... @} with time-step @var{dt}. Here variable(s) @samp{var1}, ... are the ones, defined in MGL script previously. The Runge-Kutta 4-th order method is used for solution.
+ at end deftypefn
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at ifclear UDAV
+ at node LaTeX package, mglParse class, Program flow commands, MGL scripts
+ at end ifclear
+ at ifset UDAV
+ at node LaTeX package, , Program flow commands, MGL scripts
+ at end ifset
+ at section LaTeX package
+ at nav{}
+
+There is LaTeX package @code{mgltex} (was made by Diego Sejas Viscarra) which allow one to make figures directly from MGL script located in LaTeX file.
+
+For using this package you need to specify @code{--shell-escape} option for @emph{latex/pdflatex} or manually run @emph{mglconv} tool with produced MGL scripts for generation of images. Don't forgot to run @emph{latex/pdflatex} second time to insert generated images into the output document. Also you need to run @emph{pdflatex} third time to update converted from EPS images if you are using vector EPS output (default).
+
+The package may have following options: @code{draft}, @code{final} --- the same as in the @emph{graphicx} package; @code{on}, @code{off} --- to activate/deactivate the creation of scripts and graphics; @code{comments}, @code{nocomments} --- to make visible/invisible commentaries contained inside @code{mglcomment} environments; @code{jpg}, @code{jpeg}, @code{png} --- to export graphics as JPEG/PNG images; @code{eps}, @code{epsz} --- to export to uncompressed/compressed EPS format as primi [...]
+
+The package defines the following environments:
+ at table @samp
+ at item mgl
+	It writes its contents to a general script which has the same name as the LaTeX document, but its extension is @emph{.mgl}. The code in this environment is compiled and the image produced is included. It takes exactly the same optional arguments as the @code{\includegraphics} command, plus an additional argument @var{imgext}, which specifies the extension to save the image.
+
+An example of usage of @samp{mgl} environment would be:
+ at verbatim
+\begin{mglfunc}{prepare2d}
+  new a 50 40 '0.6*sin(pi*(x+1))*sin(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'
+  new b 50 40 '0.6*cos(pi*(x+1))*cos(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'
+\end{mglfunc}
+
+\begin{figure}[!ht]
+  \centering
+  \begin{mgl}[width=0.85\textwidth,height=7.5cm]
+    fog 0.5
+    call 'prepare2d'
+    subplot 2 2 0 : title 'Surf plot (default)' : rotate 50 60 : light on : box : surf a
+
+    subplot 2 2 1 : title '"\#" style; meshnum 10' : rotate 50 60 : box
+    surf a '#'; meshnum 10
+
+    subplot 2 2 2 : title 'Mesh plot' : rotate 50 60 : box
+    mesh a
+
+    new x 50 40 '0.8*sin(pi*x)*sin(pi*(y+1)/2)'
+    new y 50 40 '0.8*cos(pi*x)*sin(pi*(y+1)/2)'
+    new z 50 40 '0.8*cos(pi*(y+1)/2)'
+    subplot 2 2 3 : title 'parametric form' : rotate 50 60 : box
+    surf x y z 'BbwrR'
+  \end{mgl}
+\end{figure}
+ at end verbatim
+
+ at item mgladdon
+	It adds its contents to the general script, without producing any image.
+ at item mglcode
+	Is exactly the same as @samp{mgl}, but it writes its contents verbatim to its own file, whose name is specified as a mandatory argument.
+ at item mglscript
+	Is exactly the same as @samp{mglcode}, but it doesn't produce any image, nor accepts optional arguments. It is useful, for example, to create a MGL script, which can later be post processed by another package like "listings".
+ at item mglblock
+	It writes its contents verbatim to a file, specified as a mandatory argument, and to the LaTeX document, and numerates each line of code.
+
+ at c This last three environments will test if the user is overwriting some file, and will issue a warning in that case.
+ at item mglverbatim
+	Exactly the same as @samp{mglblock}, but it doesn't write to a file. This environment doesn't have arguments.
+ at item mglfunc
+	Is used to define MGL functions. It takes one mandatory argument, which is the name of the function, plus one additional argument, which specifies the number of arguments of the function. The environment needs to contain only the body of the function, since the first and last lines are appended automatically, and the resulting code is written at the end of the general script, after the @ref{stop} command, which is also written automatically. The warning is produced if 2 or more function [...]
+ at item mglcomment
+	Is used to contain multiline commentaries. This commentaries will be visible/invisible in the output document, depending on the use of the package options @code{comments} and @code{nocomments} (see above), or the @code{\mglcomments} and @code{\mglnocomments} commands (see bellow).
+ at item mglsetup
+	If many scripts with the same code are to be written, the repetitive code can be written inside this environment only once, then this code will be used automatically every time the @samp{\mglplot} command is used (see below). It takes one optional argument, which is a name to be associated to the corresponding contents of the environment; this name can be passed to the @samp{\mglplot} command to use the corresponding block of code automatically (see below).
+ at end table
+
+The package also defines the following commands:
+ at table @samp
+ at item \mglplot
+	It takes one mandatory argument, which is MGL instructions separated by the symbol @samp{:} this argument can be more than one line long. It takes the same optional arguments as the @samp{mgl} environment, plus an additional argument @var{setup}, which indicates the name associated to a block of code inside a @samp{mglsetup} environment. The code inside the mandatory argument will be appended to the block of code specified, and the resulting code will be written to the general script.
+
+An example of usage of @samp{\mglplot} command would be:
+ at verbatim
+\begin{mglsetup}
+    box '@{W9}' : axis
+\end{mglsetup}
+\begin{mglsetup}[2d]
+  box : axis
+  grid 'xy' ';k'
+\end{mglsetup}
+\begin{mglsetup}[3d]
+  rotate 50 60
+  box : axis : grid 'xyz' ';k'
+\end{mglsetup}
+\begin{figure}[!ht]
+  \centering
+  \mglplot[scale=0.5]{new a 200 'sin(pi*x)' : plot a '2B'}
+\end{figure}
+\begin{figure}[!ht]
+  \centering
+  \mglplot[scale=0.5,setup=2d]{
+    fplot 'sin(pi*x)' '2B' :
+    fplot 'cos(pi*x^2)' '2R'
+  }
+\end{figure}
+\begin{figure}[!ht]
+  \centering
+  \mglplot[setup=3d]{fsurf 'sin(pi*x)+cos(pi*y)'}
+\end{figure}
+ at end verbatim
+
+ at item \mglgraphics
+	This command takes the same optional arguments as the @samp{mgl} environment, and one mandatory argument, which is the name of a MGL script. This command will compile the corresponding script and include the resulting image. It is useful when you have a script outside the LaTeX document, and you want to include the image, but you don't want to type the script again.
+ at item \mglinclude
+	This is like @samp{\mglgraphics} but, instead of creating/including the corresponding image, it writes the contents of the MGL script to the LaTeX document, and numerates the lines.
+ at item \mgldir
+	This command can be used in the preamble of the document to specify a directory where LaTeX will save the MGL scripts and generate the corresponding images. This directory is also where @samp{\mglgraphics} and @samp{\mglinclude} will look for scripts.
+ at item \mglquality
+	Adjust the quality of the MGL graphics produced similarly to @ref{quality}.
+ at item \mgltexon, \mgltexoff
+	Activate/deactivate the creation of MGL scripts and images. Notice these commands have local behavior in the sense that their effect is from the point they are called on.
+ at item \mglcomment, \mglnocomment
+	Make visible/invisible the contents of the @code{mglcomment} environments. These commands have local effect too.
+ at item \mglTeX
+	It just pretty prints the name of the package.
+ at end table
+
+As an additional feature, when an image is not found or cannot be included, instead of issuing an error, @code{mgltex} prints a box with the word @samp{MGL image not found} in the LaTeX document.
+
+
+
+ at ifclear UDAV
+ at c ------------------------------------------------------------------
+ at external{}
+ at node mglParse class, , LaTeX package, MGL scripts
+ at section mglParse class
+ at nav{}
+ at cindex mglParse
+
+Class for parsing and executing MGL script. This class is defined in @code{#include <mgl2/mgl.h>}.
+
+The main function of mglParse class is @code{Execute()}. Exactly this function parses and executes the script string-by-string. Also there are subservient functions for the finding and creation of a variable (object derived from @code{mglDataA}). These functions can be useful for displaying values of variables (arrays) in some external object (like, window) or for providing access to internal data. Function @code{AllowSetSize()} allows one to prevent changing the size of the  picture ins [...]
+
+ at c Note an important feature -- if user defines function @var{func} in variable then it will be called before the destroying of this variable (@pxref{mglVar class}).
+
+ at deftypefn {Constructor on @code{mglParse}} @code{} mglParse (@code{bool} setsize=@code{false})
+ at deftypefnx {Constructor on @code{mglParse}} @code{} mglParse (@code{HMPR} pr)
+ at deftypefnx {Constructor on @code{mglParse}} @code{} mglParse (@code{mglParse &}pr)
+ at deftypefnx {C function} @code{HMPR} mgl_create_parser ()
+Constructor initializes all values with zero and set @var{AllowSetSize} value.
+ at end deftypefn
+
+ at deftypefn {Destructor on @code{mglParse}} @code{} ~mglParse ()
+ at deftypefnx {C function} @code{void} mgl_delete_parser (@code{HMPR} p)
+Destructor delete parser
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglParse}} @code{HMPR} Self ()
+Returns the pointer to internal object of type @code{HMPR}.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglParse}} @code{void} Execute (@code{mglGraph *}gr, @code{const char *}text)
+ at deftypefnx{Method on @code{mglParse}} @code{void} Execute (@code{mglGraph *}gr, @code{const wchar_t *}text)
+ at deftypefnx {C function} @code{void} mgl_parse_text (@code{HMGL} gr, @code{HMPR} p, @code{const char *}text)
+ at deftypefnx {C function} @code{void} mgl_parse_textw (@code{HMGL} gr, @code{HMPR} p, @code{const wchar_t *}text)
+Main function in the class. Function parse and execute line-by-line MGL script in array @var{text}. Lines are separated by newline symbol @samp{\n} as usual.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglParse}} @code{void} Execute (@code{mglGraph *}gr, @code{FILE *}fp, @code{bool} print=@code{false})
+ at deftypefnx {C function} @code{void} mgl_parse_file (@code{HMGL} gr, @code{HMPR} p, @code{FILE *}fp, @code{int} print)
+The same as previous but read script from the file @var{fp}. If @var{print}=@code{true} then all warnings and information will be printed in stdout.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglParse}} @code{int} Parse (@code{mglGraph *}gr, @code{const char *}str, @code{long} pos=@code{0})
+ at deftypefnx {Method on @code{mglParse}} @code{int} Parse (@code{mglGraph *}gr, @code{const wchar_t *}str, @code{long} pos=@code{0})
+ at deftypefnx {C function} @code{int} mgl_parse_line (@code{HMGL} gr, @code{HMPR} p, @code{const char *}str, @code{int} pos)
+ at deftypefnx {C function} @code{int} mgl_parse_linew (@code{HMGL} gr, @code{HMPR} p, @code{const wchar_t *}str, @code{int} pos)
+Function parses the string @var{str} and executes it by  using @var{gr} as a graphics plotter. Returns the value depending on an error presence in the string @var{str}: 0 -- no error, 1 -- wrong command argument(s), 2 -- unknown command, 3 -- string is too long, 4 -- strings is not closed. Optional argument @var{pos} allows to save the string position in the document (or file) for using @code{for|next} command.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglParse}} @code{mglData} Calc (@code{const char *}formula)
+ at deftypefnx {Method on @code{mglParse}} @code{mglData} Calc (@code{const wchar_t *}formula)
+ at deftypefnx {C function} @code{HMDT} mgl_parser_calc (@code{HMPR} p, @code{const char *}formula)
+ at deftypefnx {C function} @code{HMDT} mgl_parser_calcw (@code{HMPR} p, @code{const wchar_t *}formula)
+Function parses the string @var{formula} and return resulting data array. In difference to @code{AddVar()} or @code{FindVar()}, it is usual data array which should be deleted after usage.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglParse}} @code{mglDataC} CalcComplex (@code{const char *}formula)
+ at deftypefnx {Method on @code{mglParse}} @code{mglDataC} CalcComplex (@code{const wchar_t *}formula)
+ at deftypefnx {C function} @code{HADT} mgl_parser_calc_complex (@code{HMPR} p, @code{const char *}formula)
+ at deftypefnx {C function} @code{HADT} mgl_parser_calc_complexw (@code{HMPR} p, @code{const wchar_t *}formula)
+Function parses the string @var{formula} and return resulting data array with complex values. In difference to @code{AddVar()} or @code{FindVar()}, it is usual data array which should be deleted after usage.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglParse}} @code{void} AddParam (@code{int} n, @code{const char *}str)
+ at deftypefnx {Method on @code{mglParse}} @code{void} AddParam (@code{int} n, @code{const wchar_t *}str)
+ at deftypefnx {C function} @code{void} mgl_parser_add_param (@code{HMPR} p, @code{int} id, @code{const char *}val)
+ at deftypefnx {C function} @code{void} mgl_parser_add_paramw (@code{HMPR} p, @code{int} id, @code{const wchar_t *}val)
+Function set the value of @var{n}-th parameter as string @var{str} (@var{n}=0, 1 ... 'z'-'a'+10). String @var{str} shouldn't contain @samp{$} symbol.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglParse}} @code{mglVar *} FindVar (@code{const char *}name)
+ at deftypefnx {Method on @code{mglParse}} @code{mglVar *} FindVar (@code{const wchar_t *}name)
+ at deftypefnx {C function} @code{HMDT} mgl_parser_find_var  (@code{HMPR} p, @code{const char *}name)
+ at deftypefnx {C function} @code{HMDT} mgl_parser_find_varw  (@code{HMPR} p, @code{const wchar_t *}name)
+Function returns the pointer to variable with name @var{name} or zero if variable is absent. Use this function to put external data array to the script or get the data from the script. You must @strong{not delete} obtained data arrays!
+ at end deftypefn
+ at deftypefn {Method on @code{mglParse}} @code{mglVar *} AddVar (@code{const char *}name)
+ at deftypefnx {Method on @code{mglParse}} @code{mglVar *} AddVar (@code{const wchar_t *}name)
+ at deftypefnx {C function} @code{HMDT} mgl_parser_add_var (@code{HMPR} p, @code{const char *}name)
+ at deftypefnx {C function} @code{HMDT} mgl_parser_add_varw (@code{HMPR} p, @code{const wchar_t *}name)
+Function returns the pointer to variable with name @var{name}. If variable is absent then new variable is created with name @var{name}. Use this function to put external data array to the script or get the data from the script. You must @strong{not delete} obtained data arrays!
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglParse}} @code{void} OpenHDF (@code{const char *}fname)
+ at deftypefnx {C function} @code{void} mgl_parser_openhdf (@code{HMPR} pr, @code{const char *}fname)
+Reads all data array from HDF5 file @var{fname} and create MGL variables with names of data names in HDF file. Complex variables will be created if data name starts with @samp{!}.
+ at end deftypefn
+
+ at deftypefn{Method on @code{mglParse} (C++)} @code{void} DeleteVar (@code{const char *}name)
+ at deftypefnx{Method on @code{mglParse} (C++)} @code{void} DeleteVar (@code{const wchar_t *}name)
+ at deftypefnx {C function} @code{void} mgl_parser_del_var (@code{HMPR} p, @code{const char *}name)
+ at deftypefnx {C function} @code{void} mgl_parser_del_varw (@code{HMPR} p, @code{const wchar_t *}name)
+Function delete the variable with given @var{name}.
+ at end deftypefn
+
+ at deftypefn{Method on @code{mglParse} (C++)} @code{void} DeleteAll ()
+ at deftypefnx {C function} @code{void} mgl_parser_del_all (@code{HMPR} p)
+Function delete all variables and reset list of commands to default one in this parser.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglParse}} @code{void} RestoreOnce ()
+ at deftypefnx {C function} @code{void} mgl_parser_restore_once (@code{HMPR} p)
+Restore Once flag.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglParse}} @code{void} AllowSetSize (@code{bool} a)
+ at deftypefnx {C function} @code{void} mgl_parser_allow_setsize (@code{HMPR} p, @code{int} a)
+Allow to parse @ref{setsize} command or not.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglParse}} @code{void} AllowFileIO (@code{bool} a)
+ at deftypefnx {C function} @code{void} mgl_parser_allow_file_io (@code{HMPR} p, @code{int} a)
+Allow reading/saving files or not.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglParse}} @code{void} AllowDllCall (@code{bool} a)
+ at deftypefnx {C function} @code{void} mgl_parser_allow_dll_call (@code{HMPR} p, @code{int} a)
+Allow to parse @ref{load} command or not.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglParse}} @code{void} Stop ()
+ at deftypefnx {C function} @code{void} mgl_parser_stop (@code{HMPR} p)
+Sends stop signal which terminate execution at next command.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglParse}} @code{void} SetVariant (@code{int} var=@code{0})
+ at deftypefnx {C function} @code{void} mgl_parser_variant (@code{HMPR} p, @code{int} var)
+Sets variant of argument(s) separated by @samp{?} symbol to be used in further commands.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglParse}} @code{void} StartID (@code{int} id=@code{0})
+ at deftypefnx {C function} @code{void} mgl_parser_start_id (@code{HMPR} p, @code{int} id)
+Sets id (like, line number) of first line in further script parsing.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglParse}} @code{long} GetCmdNum ()
+ at deftypefnx {C function} @code{long} mgl_parser_cmd_num (@code{HMPR} p)
+Return the number of registered MGL commands.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglParse}} @code{const char *} GetCmdName (@code{long} id)
+ at deftypefnx {C function} @code{const char *} mgl_parser_cmd_name (@code{HMPR} p, @code{long} id)
+Return the name of command with given @var{id}.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglParse}} @code{int} CmdType (@code{const char *}name)
+ at deftypefnx {C function} @code{int} mgl_parser_cmd_type (@code{HMPR} p, @code{const char *}name)
+Return the type of MGL command @var{name}. Type of commands are: 0 -- not the command, 1 - data plot, 2 - other plot, 3 - setup, 4 - data handle, 5 - data create, 6 - subplot, 7 - program, 8 - 1d plot, 9 - 2d plot, 10 - 3d plot, 11 - dd plot, 12 - vector plot, 13 - axis, 14 - primitives, 15 - axis setup, 16 - text/legend, 17 - data transform.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglParse}} @code{const char *} CmdFormat (@code{const char *}name)
+ at deftypefnx {C function} @code{const char *} mgl_parser_cmd_frmt (@code{HMPR} p, @code{const char *}name)
+Return the format of arguments for MGL command @var{name}.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglParse}} @code{const char *} CmdDesc (@code{const char *}name)
+ at deftypefnx {C function} @code{const char *} mgl_parser_cmd_desc (@code{HMPR} p, @code{const char *}name)
+Return the description of MGL command @var{name}.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglParse}} @code{void} RK_Step (@code{const char *}eqs, @code{const char *}vars, @code{mreal} dt=@code{1})
+ at deftypefnx {Method on @code{mglParse}} @code{void} RK_Step (@code{const wchar_t *}eqs, @code{const wchar_t *}vars, @code{mreal} dt=@code{1})
+ at deftypefnx {C function} @code{void} mgl_rk_step (@code{HMPR} p, @code{const char *}eqs, @code{const char *}vars, @code{mreal} dt)
+ at deftypefnx {C function} @code{void} mgl_rk_step_w (@code{HMPR} p, @code{const wchar_t *}eqs, @code{const wchar_t *}vars, @code{mreal} dt)
+Make one step for ordinary differential equation(s) @{var1' = eq1, ... @} with time-step @var{dt}. Here strings @var{eqs} and @var{vars} contain the equations and variable names separated by symbol @samp{;}. The variable(s) @samp{var1}, ... are the ones, defined in MGL script previously. The Runge-Kutta 4-th order method is used.
+ at end deftypefn
+
+ at end ifclear
+
+ at external{}
+
diff --git a/texinfo/parse_ru.texi b/texinfo/parse_ru.texi
new file mode 100644
index 0000000..f05afbe
--- /dev/null
+++ b/texinfo/parse_ru.texi
@@ -0,0 +1,517 @@
+
+ at c ------------------------------------------------------------------
+ at chapter Скрипты MGL
+ at nav{}
+
+MathGL имеет встроенный скриптовый язык MGL для обработки и отображения данных. Скрипты MGL могут быть выполнены независимо (с помощью программ UDAV, mglconv, mglview и др.
+ at ifclear UDAV
+, см. @ref{Utilities}) или с использованием вызовов библиотеки.
+ at end ifclear
+
+ at menu
+* MGL definition::
+* Program flow commands::
+* LaTeX package::
+ at ifclear UDAV
+* mglParse class::
+ at end ifclear
+ at end menu
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node MGL definition, Program flow commands, , MGL scripts
+ at section Основы MGL
+ at nav{}
+
+Язык MGL достаточно простой. Каждая строка -- отдельная команда. Первое слово -- имя команды, а все остальные ее аргументы. Команда может иметь до 1000 аргументов (по крайней мере сейчас). Слова разделяются одно от другого пробелом или символом табуляции. Различий между верхним и нижним индексом нет, т.е. переменные @var{a} и @var{A} идентичны. Символ @samp{#} начинает комментарий -- все символы после него игнорируются до конца строки. Исключением является случай, когда @samp{#} входит в [...]
+
+Если строка содержит ссылки на внешние параметры (@samp{$0}, @samp{$1} ... @samp{$9}) или макроопределения (@samp{$a}, @samp{$b} ... @samp{$z}), то текущие значения параметров/макроопределений подставляются в строку вместо ссылки до выполнением команды. Это позволяет использовать один и тот же скрипт при различных входных параметрах командной строки или вводить макроопределения по ходу исполнения команд скрипта.
+
+Аргументы команды могут быть строками, переменными или числами.
+ at itemize @bullet
+ at item
+Строка -- произвольный набор символов между метками @samp{'}. Длинные строки могут быть соединены из нескольких линий файла символом @samp{\}. Т.е. строки файла @samp{'a +'\<br>' b'} дадут строку @samp{'a + b'} (здесь @samp{<br>} -- перевод строки). MGL поддерживает несколько операций над строками:
+ at itemize @bullet
+ at item Соединение строк и чисел, используя @samp{,} без пробелов (например, @samp{'max(u)=',u.max,' a.u.'} или @samp{'u=',!(1+i2)} для комплексных чисел);
+ at item Получение n-го символа строки, используя @samp{[]} (например, @samp{'abc'[1]} даст @code{'b'});
+ at item Инкремент последнего символа строки, используя @samp{+} (например, @samp{'abc'+3} даст @code{'abf'}).
+ at end itemize
+
+ at item
+Обычно переменная имеет имя, состоящее из букв и чисел (должно начинаться с буквы и не быть длиннее 64 символов). Если выражение или переменная начинается с символа @samp{!}, то будут использованы комплексные значения. Например, код @code{new x 100 'x':copy !b !exp(1i*x)} создаст массив действительных чисел @var{x} и массив комплексных чисел @var{b}, который будет равен @math{exp(I*x)}, где @math{I^2=-1}. 
+В качестве переменной можно использовать также и временные массивы, включающие в себя:
+ at itemize @bullet
+ at item
+срезы (``подмассивы'') массивов данных (подобно команде @ref{subdata}). Например, @code{a(1)} или @code{a(1,:)} или @code{a(1,:,:)} -- вторая строка массива @var{a}, @code{a(:,2)} или @code{a(:,2,:)} -- третий столбец, @code{a(:,:,0)} -- первый срез и т.д. Также можно выделить часть массива с m-го по n-ый элемент @code{a(m:n,:,:)} или просто @code{a(m:n)}.
+
+ at item
+произвольные комбинации столбцов данных (например, @code{a('n*w^2/exp(t)')}), если столбцы данных были именованы командой @ref{idset} или в файле данных (в строке начинающейся с @code{##}).
+
+ at item
+произвольное выражение из существующих переменных и констант. Например, @samp{sqrt(dat(:,5)+1)} даст временный массив данных с элементами равными @code{tmp[i,j] = sqrt(dat[i,5,j]+1)}.
+
+ at item
+массивы с элементами заданными в квадратных скобках [], разделенные @samp{,}. При этом внутри выражения не должно быть пробелов! Например, @samp{[1,2,3]} даст временный массив из 3 элементов @{1, 2, 3@}; @samp{[[11,12],[21,22]]} даст матрицу 2*2 и т.д. Элементами такой конструкции могут быть и массивы если их размерности одинаковые, например @samp{[v1,v2,...,vn]}.
+
+ at item
+результат команд построения новых данных (@pxref{Make another data}), если они заключены в фигурные скобки @{@}. Например, @samp{@{sum dat 'x'@}} даст временный массив, который есть результат суммирования @var{dat} вдоль 'x'. Это такой же массив как и @var{tmp}, полученный командой @samp{sum tmp dat 'x'}. При этом можно использовать вложенные конструкции, например @samp{@{sum @{max dat 'z'@} 'x'@}}.
+ at end itemize
+Временные массивы не могут стоять в качестве первого аргумента команд, создающих массивы (например, @samp{new}, @samp{read}, @samp{hist} и т.д.).
+
+ at item
+К скалярным переменным, кроме собственно чисел, относятся: специальные переменные @code{nan=#QNAN, inf=бесконечность, rnd=случайное число, pi=3.1415926..., on=1, off=0, all=-1, :=-1}, переменные с суффиксами (@pxref{Data information}), переменные определенные командой @ref{define}, значения времени (в формате "hh-mm-ss_DD.MM.YYYY", "hh-mm-ss" или "DD.MM.YYYY") . Также массивы размером 1x1x1 считаются скалярами (например, @samp{pi/dat.nx}).
+ at end itemize
+Перед первым использованием все переменные должны быть определены с помощью команд, создающих массивы (@ref{new}, @ref{var}, @ref{list}, @ref{copy}, @ref{read}, @ref{hist}, @ref{sum} и др., см. @ref{Data constructor}, @ref{Data filling} и @ref{Make another data}).
+
+Команды могут иметь несколько наборов аргументов (например, @code{plot ydat} и @code{plot xdat ydat}). Все аргументы команды для выбранного набора должны быть указаны, однако часть из них могут иметь значения по умолчанию. Такие аргументы в описании команд будут помещены в квадратные скобки [], например @code{plot ydat ['stl'='' zval=nan]}. При этом запись @code{[arg1 arg2 arg3 ...]} подразумевает @code{[arg1 [arg2 [arg3 ...]]]}, т.е. опускать можно только аргументы с конца, если вы согл [...]
+
+Можно предоставить несколько вариантов аргументов комманд при использовании символа @samp{?} для их разделения. Конкретный вариант аргумента, используемый при выполнении команды, задается значением команды @ref{variant}. При этом будет использован последний вариант, если задано слишком большое значение. По умолчанию используется первый вариант (т.е. как при @code{variant 0}). Например в следующем коде будет сначала нарисован график синим цветом (первый аргумент @samp{b}), а затем красным [...]
+ at verbatim
+fplot 'x' 'b'?'r'
+variant 1
+fplot 'x^3' 'b'?'r|'
+ at end verbatim
+
+
+
+ at c TODO Translate it!
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Program flow commands, LaTeX package, MGL definition, MGL scripts
+ at section Управление ходом выполнения
+ at nav{}
+
+Ниже собраны команды, управляющие порядком выполнения других команд (условия, циклы, подпрограммы), (пере-)определяют аргументы скрипта и пр. Прочие команды могут быть найдены в главах @ref{MathGL core} и @ref{Data processing}. Отмечу, что некоторые из команд (например, @ref{define}, @ref{ask}, @ref{call}, @ref{for}, @ref{func}) должны быть расположены на отдельной строке.
+
+ at cindex chdir
+ at anchor{chdir}
+ at deftypefn {Команда MGL} {} chdir 'path'
+Переходит в папку @var{path}.
+ at end deftypefn
+
+ at cindex ask
+ at anchor{ask}
+ at deftypefn {Команда MGL} {} ask $N 'question'
+Задает @var{N}-ый аргумент скрипта равным ответу пользователя на вопрос @var{question}. Обычно команда показывает диалог с вопросом и полем ввода текста ответа. Здесь @var{N} это цифра (0...9) или буква (a...z).
+ at end deftypefn
+
+ at cindex define
+ at anchor{define}
+ at deftypefn {Команда MGL} {} define $N smth
+Задает @var{N}-ый аргумент скрипта равным @var{smth}. Отмечу, что @var{smth} используется как есть (с символами @samp{'} если присутствуют). Выполняется только подстановка других макроопределений $0...$9, $a...$z. Здесь @var{N} это цифра (0...9) или буква (a...z).
+ at end deftypefn
+ at deftypefn {Команда MGL} {} define name smth
+Определяет константу (скаляр) с именем @code{name} и числовым значением @code{smth}. Позднее она может быть использована как обычное число.
+ at end deftypefn
+ at cindex defchr
+ at anchor{defchr}
+ at deftypefn {Команда MGL} {} defchr $N smth
+Задает @var{N}-ый аргумент скрипта равным символу с UTF кодом @var{smth}. Здесь @var{N} это цифра (0...9) или буква (a...z).
+ at end deftypefn
+ at cindex defnum
+ at anchor{defnum}
+ at deftypefn {Команда MGL} {} defnum $N smth
+Задает @var{N}-ый аргумент скрипта равным числовому значению @var{smth}. Здесь @var{N} это цифра (0...9) или буква (a...z).
+ at end deftypefn
+
+ at comment  @cindex defpal
+ at comment  @anchor{defpal}
+ at comment  @deftypefn {Команда MGL} {} defpal $N smth
+ at comment  Задает @var{N}-ый аргумент скрипта равным символу палитры с индексом, найденным из @var{smth}. Здесь @var{N} это цифра (0...9) или буква (a...z).
+ at comment  @end deftypefn
+
+ at cindex call
+ at anchor{call}
+ at deftypefn {Команда MGL} {} call 'fname' [ARG1 ARG2 ... ARG9]
+Переходит к выполнению (вызывает) подпрограммы @var{fname} (или внешнего скрипта, если функция не была найдена). Опциональные аргументы передаются в подпрограмму. См. также @ref{func}.
+ at end deftypefn
+
+ at cindex func
+ at anchor{func}
+ at deftypefn {Команда MGL} {} func 'fname' [narg=0]
+Определяет подпрограмму с именем @var{fname} и задает число требуемых аргументов. Аргументы будут помещены в параметры скрипта $1, $2, ... $9. Отмечу, что выполнение основной программы будет остановлено при встрече @code{func} -- действует аналогично комманде @ref{stop}. См. также @ref{return}.
+
+ at end deftypefn
+ at cindex return
+ at anchor{return}
+ at deftypefn {Команда MGL} {} return
+Возвращается из подпрограммы. См. также @ref{func}.
+ at end deftypefn
+
+ at cindex load
+ at anchor{load}
+ at deftypefn {Команда MGL} {} load 'filename'
+Загружает дополнительные команды MGL из внешней динамической библиотеки @var{filename}. Данная библиотека должна содержать массив с именем @code{mgl_cmd_extra} типа  @code{mglCommand}, который содержит описание новых комманд.
+ at end deftypefn
+
+
+ at cindex if
+ at anchor{if}
+ at deftypefn {Команда MGL} {} if dat 'cond'
+Начинает блок команд, выполняемый если каждый элемент @var{dat} удовлетворяет условию @var{cond}.
+ at end deftypefn
+ at deftypefn {Команда MGL} {} if @code{val}
+Начинает блок команд, выполняемый если @code{val} не ноль.
+ at end deftypefn
+ at cindex elseif
+ at anchor{elseif}
+ at deftypefn {Команда MGL} {} elseif dat 'cond'
+Начинает блок команд, выполняемый если предыдущий @code{if} или @code{elseif} не был выполнен и каждый элемент @var{dat} удовлетворяет условию @var{cond}.
+ at end deftypefn
+ at deftypefn {Команда MGL} {} elseif @code{val}
+Начинает блок команд, выполняемый если предыдущий @code{if} или @code{elseif} не был выполнен и @code{val} не ноль.
+ at end deftypefn
+ at cindex else
+ at anchor{else}
+ at deftypefn {Команда MGL} {} else
+Начинает блок команд, выполняемый если предыдущий @code{if} или @code{elseif} не был выполнен.
+ at end deftypefn
+ at cindex endif
+ at anchor{endif}
+ at deftypefn {Команда MGL} {} endif
+Заканчивает определение блока @code{if/elseif/else}.
+ at end deftypefn
+
+ at cindex for
+ at anchor{for}
+ at deftypefn {Команда MGL} {} for $N @code{v1 v2 [dv=1]}
+Начинает блок команд, выполняемый в цикле с $@var{N}-ым аргументом изменяющимся от @var{v1} до @var{v2} с шагом @var{dv}. Здесь @var{N} это цифра (0...9) или буква (a...z).
+ at end deftypefn
+ at deftypefn {Команда MGL} {} for $N dat
+Начинает блок команд, выполняемый в цикле с $@var{N}-ым аргументом пробегающим значения массива @var{dat}. Здесь @var{N} это цифра (0...9) или буква (a...z).
+ at end deftypefn
+ at cindex next
+ at anchor{next}
+ at deftypefn {Команда MGL} {} next
+Заканчивает блок цикла @code{for}.
+ at end deftypefn
+
+ at cindex once
+ at anchor{once}
+ at deftypefn {Команда MGL} {} once @code{val}
+Определяет код (между @code{once on} и @code{once off}) который будет выполнен только один раз. Полезно для работы с большими данными в программах типа UDAV.
+ at end deftypefn
+ at cindex stop
+ at anchor{stop}
+ at deftypefn {Команда MGL} {} stop
+Останавливает выполнение скрипта.
+ at end deftypefn
+
+
+ at cindex variant
+ at anchor{variant}
+ at deftypefn {Команда MGL} {} variant @code{val}
+Задает вариант аргумента(ов), разделенных символом @samp{?}, для всех последующих комманд.
+ at end deftypefn
+
+
+
+ at cindex rkstep
+ at anchor{rkstep}
+ at deftypefn {Команда MGL} {} rkstep eq1;... var1;... [@code{dt=1}]
+Выполняет один шаг решения системы обыкновенных дифференциальных уравнений @{var1' = eq1, ... @} с временным шагом @var{dt}. Здесь переменные @samp{var1}, ... -- переменные, определенные в MGL скрипте ранее. При решении используется метод Рунге-Кутта 4-го порядка.
+ at end deftypefn
+
+
+ at c TODO Translate it!
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at ifclear UDAV
+ at node LaTeX package, mglParse class, Program flow commands, MGL scripts
+ at end ifclear
+ at ifset UDAV
+ at node LaTeX package, , Program flow commands, MGL scripts
+ at end ifset
+ at section LaTeX package
+ at nav{}
+
+There is LaTeX package @code{mgltex} (was made by Diego Sejas Viscarra) which allow one to make figures directly from MGL script located in LaTeX file.
+
+For using this package you need to specify @code{--shell-escape} option for @emph{latex/pdflatex} or manually run @emph{mglconv} tool with produced MGL scripts for generation of images. Don't forgot to run @emph{latex/pdflatex} second time to insert generated images into the output document. Also you need to run @emph{pdflatex} third time to update converted from EPS images if you are using vector EPS output (default).
+
+The package may have following options: @code{draft}, @code{final} --- the same as in the @emph{graphicx} package; @code{on}, @code{off} --- to activate/deactivate the creation of scripts and graphics; @code{comments}, @code{nocomments} --- to make visible/invisible commentaries contained inside @code{mglcomment} environments; @code{jpg}, @code{jpeg}, @code{png} --- to export graphics as JPEG/PNG images; @code{eps}, @code{epsz} --- to export to uncompressed/compressed EPS format as primi [...]
+
+The package defines the following environments:
+ at table @samp
+ at item mgl
+	It writes its contents to a general script which has the same name as the LaTeX document, but its extension is @emph{.mgl}. The code in this environment is compiled and the image produced is included. It takes exactly the same optional arguments as the @code{\includegraphics} command, plus an additional argument @var{imgext}, which specifies the extension to save the image.
+
+An example of usage of @samp{mgl} environment would be:
+ at verbatim
+\begin{mglfunc}{prepare2d}
+  new a 50 40 '0.6*sin(pi*(x+1))*sin(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'
+  new b 50 40 '0.6*cos(pi*(x+1))*cos(1.5*pi*(y+1))+0.4*cos(0.75*pi*(x+1)*(y+1))'
+\end{mglfunc}
+
+\begin{figure}[!ht]
+  \centering
+  \begin{mgl}[width=0.85\textwidth,height=7.5cm]
+    fog 0.5
+    call 'prepare2d'
+    subplot 2 2 0 : title 'Surf plot (default)' : rotate 50 60 : light on : box : surf a
+
+    subplot 2 2 1 : title '"\#" style; meshnum 10' : rotate 50 60 : box
+    surf a '#'; meshnum 10
+
+    subplot 2 2 2 : title 'Mesh plot' : rotate 50 60 : box
+    mesh a
+
+    new x 50 40 '0.8*sin(pi*x)*sin(pi*(y+1)/2)'
+    new y 50 40 '0.8*cos(pi*x)*sin(pi*(y+1)/2)'
+    new z 50 40 '0.8*cos(pi*(y+1)/2)'
+    subplot 2 2 3 : title 'parametric form' : rotate 50 60 : box
+    surf x y z 'BbwrR'
+  \end{mgl}
+\end{figure}
+ at end verbatim
+
+ at item mgladdon
+	It adds its contents to the general script, without producing any image.
+ at item mglcode
+	Is exactly the same as @samp{mgl}, but it writes its contents verbatim to its own file, whose name is specified as a mandatory argument.
+ at item mglscript
+	Is exactly the same as @samp{mglcode}, but it doesn't produce any image, nor accepts optional arguments. It is useful, for example, to create a MGL script, which can later be post processed by another package like "listings".
+ at item mglblock
+	It writes its contents verbatim to a file, specified as a mandatory argument, and to the LaTeX document, and numerates each line of code.
+
+ at c This last three environments will test if the user is overwriting some file, and will issue a warning in that case.
+ at item mglverbatim
+	Exactly the same as @samp{mglblock}, but it doesn't write to a file. This environment doesn't have arguments.
+ at item mglfunc
+	Is used to define MGL functions. It takes one mandatory argument, which is the name of the function, plus one additional argument, which specifies the number of arguments of the function. The environment needs to contain only the body of the function, since the first and last lines are appended automatically, and the resulting code is written at the end of the general script, after the @ref{stop} command, which is also written automatically. The warning is produced if 2 or more function [...]
+ at item mglcomment
+	Is used to contain multiline commentaries. This commentaries will be visible/invisible in the output document, depending on the use of the package options @code{comments} and @code{nocomments} (see above), or the @code{\mglcomments} and @code{\mglnocomments} commands (see bellow).
+ at item mglsetup
+	If many scripts with the same code are to be written, the repetitive code can be written inside this environment only once, then this code will be used automatically every time the @samp{\mglplot} command is used (see below). It takes one optional argument, which is a name to be associated to the corresponding contents of the environment; this name can be passed to the @samp{\mglplot} command to use the corresponding block of code automatically (see below).
+ at end table
+
+The package also defines the following commands:
+ at table @samp
+ at item \mglplot
+	It takes one mandatory argument, which is MGL instructions separated by the symbol @samp{:} this argument can be more than one line long. It takes the same optional arguments as the @samp{mgl} environment, plus an additional argument @var{setup}, which indicates the name associated to a block of code inside a @samp{mglsetup} environment. The code inside the mandatory argument will be appended to the block of code specified, and the resulting code will be written to the general script.
+
+An example of usage of @samp{\mglplot} command would be:
+ at verbatim
+\begin{mglsetup}
+    box '@{W9}' : axis
+\end{mglsetup}
+\begin{mglsetup}[2d]
+  box : axis
+  grid 'xy' ';k'
+\end{mglsetup}
+\begin{mglsetup}[3d]
+  rotate 50 60
+  box : axis : grid 'xyz' ';k'
+\end{mglsetup}
+\begin{figure}[!ht]
+  \centering
+  \mglplot[scale=0.5]{new a 200 'sin(pi*x)' : plot a '2B'}
+\end{figure}
+\begin{figure}[!ht]
+  \centering
+  \mglplot[scale=0.5,setup=2d]{
+    fplot 'sin(pi*x)' '2B' :
+    fplot 'cos(pi*x^2)' '2R'
+  }
+\end{figure}
+\begin{figure}[!ht]
+  \centering
+  \mglplot[setup=3d]{fsurf 'sin(pi*x)+cos(pi*y)'}
+\end{figure}
+ at end verbatim
+
+ at item \mglgraphics
+	This command takes the same optional arguments as the @samp{mgl} environment, and one mandatory argument, which is the name of a MGL script. This command will compile the corresponding script and include the resulting image. It is useful when you have a script outside the LaTeX document, and you want to include the image, but you don't want to type the script again.
+ at item \mglinclude
+	This is like @samp{\mglgraphics} but, instead of creating/including the corresponding image, it writes the contents of the MGL script to the LaTeX document, and numerates the lines.
+ at item \mgldir
+	This command can be used in the preamble of the document to specify a directory where LaTeX will save the MGL scripts and generate the corresponding images. This directory is also where @samp{\mglgraphics} and @samp{\mglinclude} will look for scripts.
+ at item \mglquality
+	Adjust the quality of the MGL graphics produced similarly to @ref{quality}.
+ at item \mgltexon, \mgltexoff
+	Activate/deactivate the creation of MGL scripts and images. Notice these commands have local behavior in the sense that their effect is from the point they are called on.
+ at item \mglcomment, \mglnocomment
+	Make visible/invisible the contents of the @code{mglcomment} environments. These commands have local effect too.
+ at item \mglTeX
+	It just pretty prints the name of the package.
+ at end table
+
+As an additional feature, when an image is not found or cannot be included, instead of issuing an error, @code{mgltex} prints a box with the word @samp{MGL image not found} in the LaTeX document.
+
+
+
+ at ifclear UDAV
+ at c ------------------------------------------------------------------
+ at external{}
+ at node mglParse class, , LaTeX package, MGL scripts
+ at section mglParse class
+ at nav{}
+ at cindex mglParse
+
+Класс разбирает и выполняет скрипты MGL. Он определен в @code{#include <mgl2/mgl.h>}.
+
+Основная функция класса mglParse -- @code{Execute()}, выполняющая построчный разбор скрипта. Также есть вспомогательные функции для поиска и создания переменных MGL (объектов, производных от @code{mglDataA}). Эти функции полезны для отображения значений массивов во внешних объектах (например, в отдельном окне) или для предоставления доступа к внутренним массивам. Функция @code{AllowSetSize()} позволяет запретить изменение размера картинки (запрещает команду @code{setsize}). Функция @code [...]
+
+ at c Note an important feature -- if user defines function @var{func} in variable then it will be called before the destroying of this variable (@pxref{mglVar class}).
+
+ at deftypefn {Конструктор класса @code{mglParse}} @code{} mglParse (@code{bool} setsize=@code{false})
+ at deftypefnx {Конструктор класса @code{mglParse}} @code{} mglParse (@code{HMPR} pr)
+ at deftypefnx {Конструктор класса @code{mglParse}} @code{} mglParse (@code{mglParse &}pr)
+ at deftypefnx {Функция С} @code{HMPR} mgl_create_parser ()
+Создает экземпляр класса @code{mglParse} и устанавливает значение @var{AllowSetSize}.
+ at end deftypefn
+
+ at deftypefn {Деструктор класса @code{mglParse}} @code{} ~mglParse ()
+ at deftypefnx {Функция С} @code{void} mgl_delete_parser (@code{HMPR} p)
+Удаляет экземпляр класса.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglParse}} @code{HMPR} Self ()
+Возвращает указатель на используемый объект типа @code{HMPR}.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglParse}} @code{void} Execute (@code{mglGraph *}gr, @code{const char *}text)
+ at deftypefnx{Метод класса @code{mglParse}} @code{void} Execute (@code{mglGraph *}gr, @code{const wchar_t *}text)
+ at deftypefnx {Функция С} @code{void} mgl_parse_text (@code{HMGL} gr, @code{HMPR} p, @code{const char *}text)
+ at deftypefnx {Функция С} @code{void} mgl_parse_textw (@code{HMGL} gr, @code{HMPR} p, @code{const wchar_t *}text)
+Выполняет построчно скрипт MGL, содержащийся в @var{text}. Строки считаются разделенными символом @samp{\n}. Это основная функция класса.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglParse}} @code{void} Execute (@code{mglGraph *}gr, @code{FILE *}fp, @code{bool} print=@code{false})
+ at deftypefnx {Функция С} @code{void} mgl_parse_file (@code{HMGL} gr, @code{HMPR} p, @code{FILE *}fp, @code{int} print)
+Аналогично предыдущему, но скрипт читается из файла @var{fp}. Если @var{print}=@code{true}, то предупреждения и информационные сообщения печатаются в stdout.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglParse}} @code{int} Parse (@code{mglGraph *}gr, @code{const char *}str, @code{long} pos=@code{0})
+ at deftypefnx {Метод класса @code{mglParse}} @code{int} Parse (@code{mglGraph *}gr, @code{const wchar_t *}str, @code{long} pos=@code{0})
+ at deftypefnx {Функция С} @code{int} mgl_parse_line (@code{HMGL} gr, @code{HMPR} p, @code{const char *}str, @code{int} pos)
+ at deftypefnx {Функция С} @code{int} mgl_parse_linew (@code{HMGL} gr, @code{HMPR} p, @code{const wchar_t *}str, @code{int} pos)
+Выполняет строку @var{str} с выводом графики на @var{gr}. Возвращает код ошибки: 0 -- нет ошибок, 1 -- неправильные аргументы, 2 -- неизвестная команда, 3 -- строка слишком длинная, 4 -- нет закрывающей скобки или @samp{'}. Аргумент @var{pos} задает позицию строки в документе/файле для использования в команде @ref{for}.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglParse}} @code{mglData} Calc (@code{const char *}formula)
+ at deftypefnx {Метод класса @code{mglParse}} @code{mglData} Calc (@code{const wchar_t *}formula)
+ at deftypefnx {Функция С} @code{HMDT} mgl_parser_calc (@code{HMPR} p, @code{const char *}formula)
+ at deftypefnx {Функция С} @code{HMDT} mgl_parser_calcw (@code{HMPR} p, @code{const wchar_t *}formula)
+Разбирает строку @var{formula} и возвращает полученный массив. В отличие от @code{AddVar()} или @code{FindVar()}, это обычный массив данных, который следует удалить после использования.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglParse}} @code{mglDataC} CalcComplex (@code{const char *}formula)
+ at deftypefnx {Метод класса @code{mglParse}} @code{mglDataC} CalcComplex (@code{const wchar_t *}formula)
+ at deftypefnx {Функция С} @code{HADT} mgl_parser_calc_complex (@code{HMPR} p, @code{const char *}formula)
+ at deftypefnx {Функция С} @code{HADT} mgl_parser_calc_complexw (@code{HMPR} p, @code{const wchar_t *}formula)
+Разбирает строку @var{formula} и возвращает полученный массив с комплексными значениями. В отличие от @code{AddVar()} или @code{FindVar()}, это обычный массив данных, который следует удалить после использования.
+ at end deftypefn
+
+
+ at deftypefn {Метод класса @code{mglParse}} @code{void} AddParam (@code{int} n, @code{const char *}str)
+ at deftypefnx {Метод класса @code{mglParse}} @code{void} AddParam (@code{int} n, @code{const wchar_t *}str)
+ at deftypefnx {Функция С} @code{void} mgl_parser_add_param (@code{HMPR} p, @code{int} id, @code{const char *}val)
+ at deftypefnx {Функция С} @code{void} mgl_parser_add_paramw (@code{HMPR} p, @code{int} id, @code{const wchar_t *}val)
+Устанавливает значение @var{n}-го параметра строкой @var{str} (@var{n}=0, 1 ... 'z'-'a'+10). Строка @var{str} не должна содержать символ @samp{$}.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglParse}} @code{mglVar *} FindVar (@code{const char *}name)
+ at deftypefnx {Метод класса @code{mglParse}} @code{mglVar *} FindVar (@code{const wchar_t *}name)
+ at deftypefnx {Функция С} @code{HMDT} mgl_parser_find_var  (@code{HMPR} p, @code{const char *}name)
+ at deftypefnx {Функция С} @code{HMDT} mgl_parser_find_varw  (@code{HMPR} p, @code{const wchar_t *}name)
+Возвращает указатель на переменную с именем @var{name} или @code{NULL} если переменная отсутствует. Используйте эту функцию для добавления внешних массивов в скрипт. @strong{Не удаляйте} полученный массив!
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglParse}} @code{mglVar *} AddVar (@code{const char *}name)
+ at deftypefnx {Метод класса @code{mglParse}} @code{mglVar *} AddVar (@code{const wchar_t *}name)
+ at deftypefnx {Функция С} @code{HMDT} mgl_parser_add_var (@code{HMPR} p, @code{const char *}name)
+ at deftypefnx {Функция С} @code{HMDT} mgl_parser_add_varw (@code{HMPR} p, @code{const wchar_t *}name)
+Возвращает указатель на переменную с именем @var{name}. Если переменная отсутствует, то она будет создана. Используйте эту функцию для добавления внешних массивов в скрипт. @strong{Не удаляйте} полученный массив!
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglParse}} @code{void} OpenHDF (@code{const char *}fname)
+ at deftypefnx {Функция С} @code{void} mgl_parser_openhdf (@code{HMPR} pr, @code{const char *}fname)
+Читает все массивы данных из HDF5 файла @var{fname} и создает переменные MGL с соответствующими именами. Если имя данных начинается с @samp{!}, то будут созданы комплексные массивы.
+ at end deftypefn
+
+ at deftypefn{Метод класса @code{mglParse} (C++)} @code{void} DeleteVar (@code{const char *}name)
+ at deftypefnx{Метод класса @code{mglParse} (C++)} @code{void} DeleteVar (@code{const wchar_t *}name)
+ at deftypefnx {Функция С} @code{void} mgl_parser_del_var (@code{HMPR} p, @code{const char *}name)
+ at deftypefnx {Функция С} @code{void} mgl_parser_del_varw (@code{HMPR} p, @code{const wchar_t *}name)
+Удаляет переменную по имени @var{name}.
+ at end deftypefn
+
+ at deftypefn{Метод класса @code{mglParse} (C++)} @code{void} DeleteAll ()
+ at deftypefnx {Функция С} @code{void} mgl_parser_del_all (@code{HMPR} p)
+Удаляет все переменные и сбрасывает список команд к списку по умолчанию в данном классе.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglParse}} @code{void} RestoreOnce ()
+ at deftypefnx {Функция С} @code{void} mgl_parser_restore_once (@code{HMPR} p)
+Восстанавливает состояние флага Once.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglParse}} @code{void} AllowSetSize (@code{bool} a)
+ at deftypefnx {Функция С} @code{void} mgl_parser_allow_setsize (@code{HMPR} p, @code{int} a)
+Разрешает/запрещает команду @ref{setsize}.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglParse}} @code{void} AllowFileIO (@code{bool} a)
+ at deftypefnx {Функция С} @code{void} mgl_parser_allow_file_io (@code{HMPR} p, @code{int} a)
+Разрешает/запрещает команды чтения файлов.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglParse}} @code{void} AllowDllCall (@code{bool} a)
+ at deftypefnx {Функция С} @code{void} mgl_parser_allow_dll_call (@code{HMPR} p, @code{int} a)
+Разрешает/запрещает команду @ref{load}.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglParse}} @code{void} Stop ()
+ at deftypefnx {Функция С} @code{void} mgl_parser_stop (@code{HMPR} p)
+Посылает сигнал завершения выполнения для следующей команды.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglParse}} @code{void} SetVariant (@code{int} var=@code{0})
+ at deftypefnx {Функция С} @code{void} mgl_parser_variant (@code{HMPR} p, @code{int} var=@code{0})
+Задает вариант аргумента(ов), разделенных символом @samp{?}, для всех последующих комманд.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglParse}} @code{void} StartID (@code{int} id=@code{0})
+ at deftypefnx {Функция С} @code{void} mgl_parser_start_id (@code{HMPR} p, @code{int} id)
+Задает начальный id (обычно это номер строки) первой строки при последующем выполнении скрипта.
+ at end deftypefn
+
+
+ at deftypefn {Метод класса @code{mglParse}} @code{long} GetCmdNum ()
+ at deftypefnx {Функция С} @code{long} mgl_parser_cmd_num (@code{HMPR} p)
+Возвращает число зарегистрированных команд MGL.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglParse}} @code{const char *} GetCmdName (@code{long} id)
+ at deftypefnx {Функция С} @code{const char *} mgl_parser_cmd_name (@code{HMPR} p, @code{long} id)
+Возвращает имя команды MGL с заданным номером @var{id}.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglParse}} @code{int} CmdType (@code{const char *}name)
+ at deftypefnx {Функция С} @code{int} mgl_parser_cmd_type (@code{HMPR} p, @code{const char *}name)
+Возвращает тип команды MGL с именем @var{name}. Типы команд: 0 -- не команда, 1 - графики по данным, 2 - прочие графики, 3 - настройка, 4 - обработка данных, 5 - создание данных, 6 - трансформация, 7 - ход выполнения, 8 - 1d графики, 9 - 2d графики, 10 - 3d графики, 11 - двойные графики, 12 - векторные поля, 13 - оси координат, 14 - примитивы, 15 - настройка осей, 16 - текст/легенда, 17 - изменение данных.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglParse}} @code{const char *} CmdFormat (@code{const char *}name)
+ at deftypefnx {Функция С} @code{const char *} mgl_parser_cmd_frmt (@code{HMPR} p, @code{const char *}name)
+Возвращает формат аргументов команды MGL с именем @var{name}.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglParse}} @code{const char *} CmdDesc (@code{const char *}name)
+ at deftypefnx {Функция С} @code{const char *} mgl_parser_cmd_desc (@code{HMPR} p, @code{const char *}name)
+Возвращает описание команды MGL с именем @var{name}.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglParse}} @code{void} RK_Step (@code{const char *}eqs, @code{const char *}vars, @code{mreal} dt=@code{1})
+ at deftypefnx {Метод класса @code{mglParse}} @code{void} RK_Step (@code{const wchar_t *}eqs, @code{const wchar_t *}vars, @code{mreal} dt=@code{1})
+ at deftypefnx {Функция С} @code{void} mgl_rk_step (@code{HMPR} p, @code{const char *}eqs, @code{const char *}vars, @code{mreal} dt)
+ at deftypefnx {Функция С} @code{void} mgl_rk_step_w (@code{HMPR} p, @code{const wchar_t *}eqs, @code{const wchar_t *}vars, @code{mreal} dt)
+Make one step for ordinary differential equation(s) @{var1' = eq1, ... @} with time-step @var{dt}. Here strings @var{eqs} and @var{vars} contain the equations and variable names separated by symbol @samp{;}. The variable(s) @samp{var1}, ... are the ones, defined in MGL script previously. The Runge-Kutta 4-th order method is used.
+ at end deftypefn
+
+ at end ifclear
+
+ at external{}
diff --git a/texinfo/qt.png b/texinfo/qt.png
new file mode 100644
index 0000000..0fc0f8e
Binary files /dev/null and b/texinfo/qt.png differ
diff --git a/texinfo/symbols_en.texi b/texinfo/symbols_en.texi
new file mode 100644
index 0000000..c0f4a2c
--- /dev/null
+++ b/texinfo/symbols_en.texi
@@ -0,0 +1,800 @@
+ at nav{}
+
+This appendix contain the full list of symbols (characters) used by MathGL for setting up plot. Also it contain sections for full list of hot-keys supported by mglview tool and by UDAV program.
+
+ at menu
+* Symbols for styles::
+* Hot-keys for mglview::
+* Hot-keys for UDAV::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Symbols for styles, Hot-keys for mglview, , Symbols and hot-keys
+ at section Symbols for styles
+ at nav{}
+
+Below is full list of all characters (symbols) which MathGL use for setting up the plot.
+
+ at table @samp
+ at item space ' '
+empty line style (see @ref{Line styles});
+
+empty color in @ref{chart}.
+
+ at item !
+set to use new color from palette for each point (not for each curve, as default) in @ref{1D plotting};
+
+set to disable ticks tuning in @ref{axis} and @ref{colorbar};
+
+set to draw @ref{grid} lines at subticks coordinates too;
+
+define complex variable/expression in MGL script if placed at beginning.
+
+ at item #
+set to use solid marks (see @ref{Line styles}) or solid @ref{error} boxes;
+
+set to draw wired plot for @ref{axial}, @ref{surf3}, @ref{surf3a}, @ref{surf3c}, @ref{triplot}, @ref{quadplot}, @ref{area}, @ref{region}, @ref{bars}, @ref{barh}, @ref{tube}, @ref{tape}, @ref{cone}, @ref{boxs} and draw boundary only for @ref{circle}, @ref{ellipse}, @ref{rhomb};
+
+set to draw also mesh lines for @ref{surf}, @ref{surfc}, @ref{surfa}, @ref{dens}, @ref{densx}, @ref{densy}, @ref{densz}, @ref{dens3}, or boundary for @ref{chart}, @ref{facex}, @ref{facey}, @ref{facez}, @ref{rect};
+
+set to draw boundary and box for @ref{legend}, @ref{title}, or grid lines for @ref{table};
+
+set to draw grid for @ref{radar};
+
+set to start flow threads and pipes from edges only for @ref{flow}, @ref{pipe};
+
+set to use whole are for axis range in @ref{subplot}, @ref{inplot};
+
+change text color inside a string (see @ref{Font styles});
+
+start comment in @ref{MGL scripts} or in @ref{Command options}.
+
+ at item $
+denote parameter of @ref{MGL scripts}.
+
+ at item %
+set color scheme along 2 coordinates @ref{Color scheme}.
+
+ at item &
+
+set to pass long integer number in tick template @ref{xtick}, @ref{ytick}, @ref{ztick}, @ref{ctick};
+
+specifier of drawing user-defined symbols as mark (see @ref{Line styles});
+
+operation in @ref{Textual formulas}.
+
+ at item @quoteright{}
+denote string in @ref{MGL scripts} or in @ref{Command options}.
+
+ at item *
+one of marks (see @ref{Line styles});
+
+one of mask for face filling (see @ref{Color scheme});
+
+set to start flow threads from 2d array inside data (see @ref{flow});
+
+operation in @ref{Textual formulas}.
+
+ at item +
+one of marks (see @ref{Line styles}) or kind of @ref{error} boxes;
+
+one of mask for face filling (see @ref{Color scheme});
+
+set to print @samp{+} for positive numbers in @ref{axis}, @ref{label}, @ref{table};
+
+operation of increasing last character value in MGL strings;
+
+operation in @ref{Textual formulas}.
+
+ at item ,
+separator for color positions (see @ref{Color styles}) or items in a list
+
+concatenation of MGL string with another string or numerical value.
+
+ at item -
+solid line style (see @ref{Line styles});
+
+one of mask for face filling (see @ref{Color scheme});
+
+place entries horizontally in @ref{legend};
+
+set to use usual @samp{-} for negative numbers in @ref{axis}, @ref{label}, @ref{table};
+
+operation in @ref{Textual formulas}.
+
+ at item .
+one of marks (see @ref{Line styles}) or kind of @ref{error} boxes;
+
+set to draw hachures instead of arrows for @ref{vect}, @ref{vect3};
+
+set to use dots instead of faces for @ref{cloud}, @ref{torus}, @ref{axial}, @ref{surf3}, @ref{surf3a}, @ref{surf3c}, @ref{surf}, @ref{surfa}, @ref{surfc}, @ref{dens}, @ref{map};
+
+delimiter of fractional parts for numbers.
+
+ at item /
+operation in @ref{Textual formulas}.
+
+ at item :
+line dashing style (see @ref{Line styles});
+
+stop color scheme parsing (see @ref{Color scheme});
+
+range operation in @ref{MGL scripts};
+
+separator of commands in @ref{MGL scripts}.
+
+ at item ;
+line dashing style (see @ref{Line styles});
+
+one of mask for face filling (see @ref{Color scheme});
+
+start of an option in @ref{MGL scripts} or in @ref{Command options};
+
+separator of equations in @ref{ode};
+
+separator of labels in @ref{iris}.
+
+ at item <
+one of marks (see @ref{Line styles});
+
+one of mask for face filling (see @ref{Color scheme});
+
+style of @ref{subplot} and @ref{inplot};
+
+set position of @ref{colorbar};
+
+style of @ref{vect}, @ref{vect3};
+
+align left in @ref{bars}, @ref{barh}, @ref{boxplot}, @ref{cones}, @ref{candle}, @ref{ohlc};
+
+operation in @ref{Textual formulas}.
+
+
+ at item >
+one of marks (see @ref{Line styles});
+
+one of mask for face filling (see @ref{Color scheme});
+
+style of @ref{subplot} and @ref{inplot};
+
+set position of @ref{colorbar};
+
+style of @ref{vect}, @ref{vect3};
+
+align right in @ref{bars}, @ref{barh}, @ref{boxplot}, @ref{cones}, @ref{candle}, @ref{ohlc};
+
+operation in @ref{Textual formulas}.
+
+ at item =
+line dashing style (see @ref{Line styles});
+
+one of mask for face filling (see @ref{Color scheme});
+
+set to use equidistant columns for @ref{table};
+
+set to use color gradient for @ref{vect}, @ref{vect3};
+
+operation in @ref{Textual formulas}.
+
+ at item @@
+set to draw box around text for @ref{text} and similar functions;
+
+set to draw boundary and fill it for @ref{circle}, @ref{ellipse}, @ref{rhomb};
+
+set to fill faces for @ref{box};
+
+set to draw large semitransparent mark instead of error box for @ref{error};
+
+set to draw edges for @ref{cone};
+
+set to draw filled boxes for @ref{boxs};
+
+reduce text size inside a string (see @ref{Font styles});
+
+operation in @ref{Textual formulas}.
+
+ at item ^
+one of marks (see @ref{Line styles});
+
+one of mask for face filling (see @ref{Color scheme});
+
+style of @ref{subplot} and @ref{inplot};
+
+set position of @ref{colorbar};
+
+set outer position for @ref{legend};
+
+inverse default position for @ref{axis};
+
+switch to upper index inside a string (see @ref{Font styles});
+
+align center in @ref{bars}, @ref{barh}, @ref{boxplot}, @ref{cones}, @ref{candle}, @ref{ohlc};
+
+operation in @ref{Textual formulas}.
+
+ at item _
+empty arrow style (see @ref{Line styles});
+
+disable drawing of tick labels for @ref{axis};
+
+style of @ref{subplot} and @ref{inplot};
+
+set position of @ref{colorbar};
+
+set to draw contours at bottom for @ref{cont}, @ref{contf}, @ref{contd}, @ref{contv}, @ref{tricont};
+
+switch to lower index inside a string (see @ref{Font styles}).
+
+ at item []
+contain symbols excluded from color scheme parsing (see @ref{Color scheme});
+
+operation of getting n-th character from MGL string.
+
+ at item @{@}
+contain extended specification of color (see @ref{Color styles}), dashing (see @ref{Line styles}) or mask (see @ref{Color scheme});
+
+denote special operation in @ref{MGL scripts};
+
+denote 'meta-symbol' for LaTeX like string parsing (see @ref{Font styles}).
+
+ at item |
+line dashing style (see @ref{Line styles});
+
+set to use sharp color scheme (see @ref{Color scheme});
+
+set to limit width by subplot width for @ref{table};
+
+delimiter in @ref{list} command;
+
+operation in @ref{Textual formulas}.
+
+ at item \
+string continuation symbol on next line for @ref{MGL scripts}.
+
+ at item ~
+disable drawing of tick labels for @ref{axis} and @ref{colorbar};
+
+disable first segment in @ref{lamerey};
+
+one of mask for face filling (see @ref{Color scheme}).
+
+ at item 0,1,2,3,4,5,6,7,8,9
+line width (see @ref{Line styles});
+
+brightness of a color (see @ref{Color styles});
+
+precision of numbers in @ref{axis}, @ref{label}, @ref{table};
+
+kind of smoothing (for digits 1,3,5) in @ref{smooth};
+
+digits for a value.
+
+ at item 4,6,8
+set to draw square, hex- or octo-pyramids instead of cones in @ref{cone}, @ref{cones}.
+
+ at item A,B,C,D,E,F,a,b,c,d,e,f
+can be hex-digit for color specification if placed inside @{@} (see @ref{Color styles}).
+
+ at item A
+arrow style (see @ref{Line styles});
+
+set to use absolute position in whole picture for @ref{text}, @ref{colorbar}, @ref{legend}.
+
+ at item a
+set to use absolute position in subplot for @ref{text};
+
+style of @ref{plot}, @ref{radar}, @ref{tens}, @ref{area}, @ref{region} to draw segments between points outside of axis range;
+
+style of @ref{bars}, @ref{barh}, @ref{cones}.
+
+ at item B
+dark blue color (see @ref{Color styles}).
+
+ at item b
+blue color (see @ref{Color styles});
+
+bold font face if placed after @samp{:} (see @ref{Font styles}).
+
+ at item C
+dark cyan color (see @ref{Color styles});
+
+align text to center if placed after @samp{:} (see @ref{Font styles}).
+
+ at item c
+cyan color (see @ref{Color styles});
+
+name of color axis;
+
+cosine transform for @ref{transform}.
+
+ at item D
+arrow style (see @ref{Line styles});
+
+one of mask for face filling (see @ref{Color scheme}).
+
+ at item d
+one of marks (see @ref{Line styles}) or kind of @ref{error} boxes;
+
+one of mask for face filling (see @ref{Color scheme});
+
+start hex-dash description if placed inside @{@} (see @ref{Line styles}).
+
+ at item E
+dark green-yellow color (see @ref{Color styles}).
+
+ at item e
+green-yellow color (see @ref{Color styles}).
+
+ at item F
+
+set fixed bar widths in @ref{bars}, @ref{barh};
+
+set LaTeX-like format for numbers in @ref{axis}, @ref{label}, @ref{table}.
+
+ at item f
+style of @ref{bars}, @ref{barh};
+
+style of @ref{vect}, @ref{vect3};
+
+set fixed format for numbers in @ref{axis}, @ref{label}, @ref{table};
+
+Fourier transform for @ref{transform}.
+
+ at item G
+dark green color (see @ref{Color styles}).
+
+ at item g
+green color (see @ref{Color styles}).
+
+ at item H
+dark gray color (see @ref{Color styles}).
+
+ at item h
+gray color (see @ref{Color styles});
+
+Hankel transform for @ref{transform}.
+
+ at item I
+arrow style (see @ref{Line styles});
+
+set @ref{colorbar} position near boundary.
+
+ at item i
+line dashing style (see @ref{Line styles});
+
+italic font face if placed after @samp{:} (see @ref{Font styles}).
+
+set to use inverse values for @ref{cloud}, @ref{pipe}, @ref{dew};
+
+set to fill only area with y1<y<y2 for @ref{region};
+
+inverse Fourier transform for @ref{transform}, @ref{transforma}, @ref{fourier}.
+
+ at item j
+line dashing style (see @ref{Line styles});
+
+one of mask for face filling (see @ref{Color scheme}).
+
+ at item K
+arrow style (see @ref{Line styles}).
+
+ at item k
+black color (see @ref{Color styles}).
+
+ at item L
+dark green-blue color (see @ref{Color styles});
+
+align text to left if placed after @samp{:} (see @ref{Font styles}).
+
+ at item l
+green-blue color (see @ref{Color styles}).
+
+ at item M
+dark magenta color (see @ref{Color styles}).
+
+ at item m
+magenta color (see @ref{Color styles}).
+
+ at item N
+dark sky-blue color (see @ref{Color styles}).
+
+ at item n
+sky-blue color (see @ref{Color styles}).
+
+ at item O
+arrow style (see @ref{Line styles});
+
+one of mask for face filling (see @ref{Color scheme}).
+
+ at item o
+one of marks (see @ref{Line styles}) or kind of @ref{error} boxes;
+
+one of mask for face filling (see @ref{Color scheme});
+
+over-line text if placed after @samp{:} (see @ref{Font styles}).
+
+ at item P
+dark purple color (see @ref{Color styles}).
+
+ at item p
+purple color (see @ref{Color styles}).
+
+ at item Q
+dark orange or brown color (see @ref{Color styles}).
+
+ at item q
+orange color (see @ref{Color styles}).
+
+ at item R
+dark red color (see @ref{Color styles});
+
+align text to right if placed after @samp{:} (see @ref{Font styles}).
+
+ at item r
+red color (see @ref{Color styles}).
+
+ at item S
+arrow style (see @ref{Line styles});
+
+one of mask for face filling (see @ref{Color scheme}).
+
+ at item s
+one of marks (see @ref{Line styles}) or kind of @ref{error} boxes;
+
+one of mask for face filling (see @ref{Color scheme});
+
+start hex-mask description if placed inside @{@} (see @ref{Color scheme});
+
+sine transform for @ref{transform}.
+
+ at item t
+draw tubes instead of cones in @ref{cone}, @ref{cones};
+
+ at item T
+arrow style (see @ref{Line styles});
+
+place text under the curve for @ref{text}, @ref{cont}, @ref{cont3}.
+
+ at item t
+set to draw text labels for @ref{cont}, @ref{cont3};
+
+name of t-axis (one of ternary axis);
+
+variable in @ref{Textual formulas}, which usually is varied in range [0,1].
+
+ at item U
+dark blue-violet color (see @ref{Color styles});
+
+disable rotation of tick labels for @ref{axis}.
+
+ at item u
+blue-violet color (see @ref{Color styles});
+
+under-line text if placed after @samp{:} (see @ref{Font styles});
+
+name of u-axis (one of ternary axis);
+
+variable in @ref{Textual formulas}, which usually denote array itself.
+
+ at item V
+arrow style (see @ref{Line styles});
+
+place text centering on vertical direction for @ref{text}.
+
+ at item v
+one of marks (see @ref{Line styles});
+
+set to draw vectors on flow threads for @ref{flow} and on segments for @ref{lamerey}.
+
+ at item W
+bright gray color (see @ref{Color styles}).
+
+ at item w
+white color (see @ref{Color styles});
+
+wired text if placed after @samp{:} (see @ref{Font styles});
+
+name of w-axis (one of ternary axis);
+
+ at item X
+arrow style (see @ref{Line styles}).
+
+ at item x
+
+name of x-axis or x-direction or 1st dimension of a data array;
+
+start hex-color description if placed inside @{@} (see @ref{Color styles});
+
+one of marks (see @ref{Line styles}) or kind of @ref{error} boxes;
+
+tiles orientation perpendicular to x-axis in @ref{tile}, @ref{tiles};
+
+style of @ref{tape}.
+
+ at item Y
+dark yellow or gold color (see @ref{Color styles}).
+
+ at item y
+yellow color (see @ref{Color styles});
+
+name of y-axis or y-direction or 2nd dimension of a data array;
+
+tiles orientation perpendicular to y-axis in @ref{tile}, @ref{tiles}.
+
+ at item z
+
+name of z-axis or z-direction or 3d dimension of a data array;
+
+style of @ref{tape}.
+
+ at end table
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Hot-keys for mglview, Hot-keys for UDAV, Symbols for styles, Symbols and hot-keys
+ at section Hot-keys for mglview
+ at nav{}
+
+ at multitable @columnfractions .3 .7
+ at headitem Key @tab Description
+ at item @key{Ctrl-P}
+ at tab Open printer dialog and print graphics.
+
+ at item @key{Ctrl-W}
+ at tab Close window.
+
+ at item @key{Ctrl-T}
+ at tab Switch on/off transparency for the graphics.
+
+ at item @key{Ctrl-L}
+ at tab Switch on/off additional lightning for the graphics.
+
+ at item @key{Ctrl-Space}
+ at tab Restore default graphics rotation, zoom and perspective.
+
+ at item @key{F5}
+ at tab Execute script and redraw graphics.
+
+ at item @key{F6}
+ at tab Change canvas size to fill whole region.
+
+ at item @key{F7}
+ at tab Stop drawing and script execution.
+
+ at item @key{Ctrl-F5}
+ at tab Run slideshow. If no parameter specified then the dialog with slideshow options will appear.
+
+ at item @key{Ctrl-Comma}, @key{Ctrl-Period}
+ at tab Show next/previous slide. If no parameter specified then the dialog with slideshow options will appear.
+
+
+ at item @key{Ctrl-Shift-G}
+ at tab Copy graphics to clipboard.
+
+
+
+ at item @key{Alt-P}
+ at tab Export as semitransparent PNG.
+
+ at item @key{Alt-F}
+ at tab Export as solid PNG.
+
+ at item @key{Alt-J}
+ at tab Export as JPEG.
+
+ at item @key{Alt-E}
+ at tab Export as vector EPS.
+
+ at item @key{Alt-S}
+ at tab Export as vector SVG.
+
+ at item @key{Alt-L}
+ at tab Export as LaTeX/Tikz image.
+
+ at item @key{Alt-M}
+ at tab Export as MGLD.
+
+ at item @key{Alt-D}
+ at tab Export as PRC/PDF.
+
+ at item @key{Alt-O}
+ at tab Export as OBJ.
+
+ at c @item @key{Alt-X}
+ at c @tab Export as X3D.
+ at end multitable
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Hot-keys for UDAV, , Hot-keys for mglview, Symbols and hot-keys
+ at section Hot-keys for UDAV
+ at nav{}
+
+ at multitable @columnfractions .3 .7
+ at headitem Key @tab Description
+ at item @key{Ctrl-N}
+ at tab Create new window with empty script. Note, all scripts share variables. So, second window can be used to see some additional information of existed variables.
+
+ at item @key{Ctrl-O}
+ at tab Open and execute/show script or data from file. You may switch off automatic exection in UDAV properties
+
+ at item @key{Ctrl-S}
+ at tab Save script to a file.
+
+ at item @key{Ctrl-P}
+ at tab Open printer dialog and print graphics.
+
+ at item @key{Ctrl-Z}
+ at tab Undo changes in script editor.
+
+ at item @key{Ctrl-Shift-Z}
+ at tab Redo changes in script editor.
+
+ at item @key{Ctrl-X}
+ at tab Cut selected text into clipboard.
+
+ at item @key{Ctrl-C}
+ at tab Copy selected text into clipboard.
+
+ at item @key{Ctrl-V}
+ at tab Paste selected text from clipboard.
+
+ at item @key{Ctrl-A}
+ at tab Select all text in editor.
+
+ at item @key{Ctrl-F}
+ at tab Show dialog for text finding.
+
+ at item @key{F3}
+ at tab Find next occurrence of the text.
+
+
+ at item @key{Win-C} or @key{Meta-C}
+ at tab Show dialog for new command and put it into the script.
+
+ at item @key{Win-F} or @key{Meta-F}
+ at tab Insert last fitted formula with found coefficients.
+
+ at item @key{Win-S} or @key{Meta-S}
+ at tab Show dialog for styles and put it into the script. Styles define the plot view (color scheme, marks, dashing and so on).
+
+ at item @key{Win-O} or @key{Meta-O}
+ at tab Show dialog for options and put it into the script. Options are used for additional setup the plot.
+
+ at item @key{Win-N} or @key{Meta-N}
+ at tab Replace selected expression by its numerical value.
+
+ at item @key{Win-P} or @key{Meta-P}
+ at tab Select file and insert its file name into the script.
+
+ at item @key{Win-G} or @key{Meta-G}
+ at tab Show dialog for plot setup and put resulting code into the script. This dialog setup axis, labels, lighting and other general things.
+
+
+
+ at item @key{Ctrl-Shift-O}
+ at tab Load data from file. Data will be deleted only at exit but UDAV will not ask to save it.
+
+ at item @key{Ctrl-Shift-S}
+ at tab Save data to a file.
+
+ at item @key{Ctrl-Shift-C}
+ at tab Copy range of numbers to clipboard.
+
+ at item @key{Ctrl-Shift-V}
+ at tab Paste range of numbers from clipboard.
+
+ at item @key{Ctrl-Shift-N}
+ at tab Recreate the data with new sizes and fill it by zeros.
+
+ at item @key{Ctrl-Shift-R}
+ at tab Resize (interpolate) the data to specified sizes.
+
+ at item @key{Ctrl-Shift-T}
+ at tab Transform data along dimension(s).
+
+ at item @key{Ctrl-Shift-M}
+ at tab Make another data.
+
+ at item @key{Ctrl-Shift-H}
+ at tab Find histogram of data.
+
+
+
+ at item @key{Ctrl-T}
+ at tab Switch on/off transparency for the graphics.
+
+ at item @key{Ctrl-L}
+ at tab Switch on/off additional lightning for the graphics.
+
+ at item @key{Ctrl-G}
+ at tab Switch on/off grid of absolute coordinates.
+
+ at item @key{Ctrl-Space}
+ at tab Restore default graphics rotation, zoom and perspective.
+
+ at item @key{F5}
+ at tab Execute script and redraw graphics.
+
+ at item @key{F6}
+ at tab Change canvas size to fill whole region.
+
+ at item @key{F7}
+ at tab Stop script execution and drawing.
+
+ at item @key{F8}
+ at tab Show/hide tool window with list of hidden plots.
+
+ at item @key{F9}
+ at tab Restore status for 'once' command and reload data.
+
+ at item @key{Ctrl-F5}
+ at tab Run slideshow. If no parameter specified then the dialog with slideshow options will appear.
+
+ at item @key{Ctrl-Comma}, @key{Ctrl-Period}
+ at tab Show next/previous slide. If no parameter specified then the dialog with slideshow options will appear.
+
+ at item @key{Ctrl-W}
+ at tab Open dialog with slideshow options.
+
+ at item @key{Ctrl-Shift-G}
+ at tab Copy graphics to clipboard.
+
+
+ at item @key{F1}
+ at tab Show help on MGL commands
+
+ at item @key{F2}
+ at tab Show/hide tool window with messages and information.
+
+ at item @key{F4}
+ at tab Show/hide calculator which evaluate and help to type textual formulas. Textual formulas may contain data variables too.
+
+
+ at item @key{Meta-Shift-Up}, @key{Meta-Shift-Down}
+ at tab Change view angle @math{\theta}.
+
+ at item @key{Meta-Shift-Left}, @key{Meta-Shift-Right}
+ at tab Change view angle @math{\phi}.
+
+ at item @key{Alt-Minus}, @key{Alt-Equal}
+ at tab Zoom in/out whole image.
+
+ at item @key{Alt-Up}, @key{Alt-Down}, @key{Alt-Right}, @key{Alt-Left}
+ at tab Shift whole image.
+
+ at item @key{Alt-P}
+ at tab Export as semitransparent PNG.
+
+ at item @key{Alt-F}
+ at tab Export as solid PNG.
+
+ at item @key{Alt-J}
+ at tab Export as JPEG.
+
+ at item @key{Alt-E}
+ at tab Export as vector EPS.
+
+ at item @key{Alt-S}
+ at tab Export as vector SVG.
+
+ at item @key{Alt-L}
+ at tab Export as LaTeX/Tikz image.
+
+ at item @key{Alt-M}
+ at tab Export as MGLD.
+
+ at item @key{Alt-D}
+ at tab Export as PRC/PDF.
+
+ at item @key{Alt-O}
+ at tab Export as OBJ.
+
+ at c @item @key{Alt-X}
+ at c @tab Export as X3D.
+
+ at end multitable
+
+ at external{}
diff --git a/texinfo/symbols_ru.texi b/texinfo/symbols_ru.texi
new file mode 100644
index 0000000..c0f4a2c
--- /dev/null
+++ b/texinfo/symbols_ru.texi
@@ -0,0 +1,800 @@
+ at nav{}
+
+This appendix contain the full list of symbols (characters) used by MathGL for setting up plot. Also it contain sections for full list of hot-keys supported by mglview tool and by UDAV program.
+
+ at menu
+* Symbols for styles::
+* Hot-keys for mglview::
+* Hot-keys for UDAV::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Symbols for styles, Hot-keys for mglview, , Symbols and hot-keys
+ at section Symbols for styles
+ at nav{}
+
+Below is full list of all characters (symbols) which MathGL use for setting up the plot.
+
+ at table @samp
+ at item space ' '
+empty line style (see @ref{Line styles});
+
+empty color in @ref{chart}.
+
+ at item !
+set to use new color from palette for each point (not for each curve, as default) in @ref{1D plotting};
+
+set to disable ticks tuning in @ref{axis} and @ref{colorbar};
+
+set to draw @ref{grid} lines at subticks coordinates too;
+
+define complex variable/expression in MGL script if placed at beginning.
+
+ at item #
+set to use solid marks (see @ref{Line styles}) or solid @ref{error} boxes;
+
+set to draw wired plot for @ref{axial}, @ref{surf3}, @ref{surf3a}, @ref{surf3c}, @ref{triplot}, @ref{quadplot}, @ref{area}, @ref{region}, @ref{bars}, @ref{barh}, @ref{tube}, @ref{tape}, @ref{cone}, @ref{boxs} and draw boundary only for @ref{circle}, @ref{ellipse}, @ref{rhomb};
+
+set to draw also mesh lines for @ref{surf}, @ref{surfc}, @ref{surfa}, @ref{dens}, @ref{densx}, @ref{densy}, @ref{densz}, @ref{dens3}, or boundary for @ref{chart}, @ref{facex}, @ref{facey}, @ref{facez}, @ref{rect};
+
+set to draw boundary and box for @ref{legend}, @ref{title}, or grid lines for @ref{table};
+
+set to draw grid for @ref{radar};
+
+set to start flow threads and pipes from edges only for @ref{flow}, @ref{pipe};
+
+set to use whole are for axis range in @ref{subplot}, @ref{inplot};
+
+change text color inside a string (see @ref{Font styles});
+
+start comment in @ref{MGL scripts} or in @ref{Command options}.
+
+ at item $
+denote parameter of @ref{MGL scripts}.
+
+ at item %
+set color scheme along 2 coordinates @ref{Color scheme}.
+
+ at item &
+
+set to pass long integer number in tick template @ref{xtick}, @ref{ytick}, @ref{ztick}, @ref{ctick};
+
+specifier of drawing user-defined symbols as mark (see @ref{Line styles});
+
+operation in @ref{Textual formulas}.
+
+ at item @quoteright{}
+denote string in @ref{MGL scripts} or in @ref{Command options}.
+
+ at item *
+one of marks (see @ref{Line styles});
+
+one of mask for face filling (see @ref{Color scheme});
+
+set to start flow threads from 2d array inside data (see @ref{flow});
+
+operation in @ref{Textual formulas}.
+
+ at item +
+one of marks (see @ref{Line styles}) or kind of @ref{error} boxes;
+
+one of mask for face filling (see @ref{Color scheme});
+
+set to print @samp{+} for positive numbers in @ref{axis}, @ref{label}, @ref{table};
+
+operation of increasing last character value in MGL strings;
+
+operation in @ref{Textual formulas}.
+
+ at item ,
+separator for color positions (see @ref{Color styles}) or items in a list
+
+concatenation of MGL string with another string or numerical value.
+
+ at item -
+solid line style (see @ref{Line styles});
+
+one of mask for face filling (see @ref{Color scheme});
+
+place entries horizontally in @ref{legend};
+
+set to use usual @samp{-} for negative numbers in @ref{axis}, @ref{label}, @ref{table};
+
+operation in @ref{Textual formulas}.
+
+ at item .
+one of marks (see @ref{Line styles}) or kind of @ref{error} boxes;
+
+set to draw hachures instead of arrows for @ref{vect}, @ref{vect3};
+
+set to use dots instead of faces for @ref{cloud}, @ref{torus}, @ref{axial}, @ref{surf3}, @ref{surf3a}, @ref{surf3c}, @ref{surf}, @ref{surfa}, @ref{surfc}, @ref{dens}, @ref{map};
+
+delimiter of fractional parts for numbers.
+
+ at item /
+operation in @ref{Textual formulas}.
+
+ at item :
+line dashing style (see @ref{Line styles});
+
+stop color scheme parsing (see @ref{Color scheme});
+
+range operation in @ref{MGL scripts};
+
+separator of commands in @ref{MGL scripts}.
+
+ at item ;
+line dashing style (see @ref{Line styles});
+
+one of mask for face filling (see @ref{Color scheme});
+
+start of an option in @ref{MGL scripts} or in @ref{Command options};
+
+separator of equations in @ref{ode};
+
+separator of labels in @ref{iris}.
+
+ at item <
+one of marks (see @ref{Line styles});
+
+one of mask for face filling (see @ref{Color scheme});
+
+style of @ref{subplot} and @ref{inplot};
+
+set position of @ref{colorbar};
+
+style of @ref{vect}, @ref{vect3};
+
+align left in @ref{bars}, @ref{barh}, @ref{boxplot}, @ref{cones}, @ref{candle}, @ref{ohlc};
+
+operation in @ref{Textual formulas}.
+
+
+ at item >
+one of marks (see @ref{Line styles});
+
+one of mask for face filling (see @ref{Color scheme});
+
+style of @ref{subplot} and @ref{inplot};
+
+set position of @ref{colorbar};
+
+style of @ref{vect}, @ref{vect3};
+
+align right in @ref{bars}, @ref{barh}, @ref{boxplot}, @ref{cones}, @ref{candle}, @ref{ohlc};
+
+operation in @ref{Textual formulas}.
+
+ at item =
+line dashing style (see @ref{Line styles});
+
+one of mask for face filling (see @ref{Color scheme});
+
+set to use equidistant columns for @ref{table};
+
+set to use color gradient for @ref{vect}, @ref{vect3};
+
+operation in @ref{Textual formulas}.
+
+ at item @@
+set to draw box around text for @ref{text} and similar functions;
+
+set to draw boundary and fill it for @ref{circle}, @ref{ellipse}, @ref{rhomb};
+
+set to fill faces for @ref{box};
+
+set to draw large semitransparent mark instead of error box for @ref{error};
+
+set to draw edges for @ref{cone};
+
+set to draw filled boxes for @ref{boxs};
+
+reduce text size inside a string (see @ref{Font styles});
+
+operation in @ref{Textual formulas}.
+
+ at item ^
+one of marks (see @ref{Line styles});
+
+one of mask for face filling (see @ref{Color scheme});
+
+style of @ref{subplot} and @ref{inplot};
+
+set position of @ref{colorbar};
+
+set outer position for @ref{legend};
+
+inverse default position for @ref{axis};
+
+switch to upper index inside a string (see @ref{Font styles});
+
+align center in @ref{bars}, @ref{barh}, @ref{boxplot}, @ref{cones}, @ref{candle}, @ref{ohlc};
+
+operation in @ref{Textual formulas}.
+
+ at item _
+empty arrow style (see @ref{Line styles});
+
+disable drawing of tick labels for @ref{axis};
+
+style of @ref{subplot} and @ref{inplot};
+
+set position of @ref{colorbar};
+
+set to draw contours at bottom for @ref{cont}, @ref{contf}, @ref{contd}, @ref{contv}, @ref{tricont};
+
+switch to lower index inside a string (see @ref{Font styles}).
+
+ at item []
+contain symbols excluded from color scheme parsing (see @ref{Color scheme});
+
+operation of getting n-th character from MGL string.
+
+ at item @{@}
+contain extended specification of color (see @ref{Color styles}), dashing (see @ref{Line styles}) or mask (see @ref{Color scheme});
+
+denote special operation in @ref{MGL scripts};
+
+denote 'meta-symbol' for LaTeX like string parsing (see @ref{Font styles}).
+
+ at item |
+line dashing style (see @ref{Line styles});
+
+set to use sharp color scheme (see @ref{Color scheme});
+
+set to limit width by subplot width for @ref{table};
+
+delimiter in @ref{list} command;
+
+operation in @ref{Textual formulas}.
+
+ at item \
+string continuation symbol on next line for @ref{MGL scripts}.
+
+ at item ~
+disable drawing of tick labels for @ref{axis} and @ref{colorbar};
+
+disable first segment in @ref{lamerey};
+
+one of mask for face filling (see @ref{Color scheme}).
+
+ at item 0,1,2,3,4,5,6,7,8,9
+line width (see @ref{Line styles});
+
+brightness of a color (see @ref{Color styles});
+
+precision of numbers in @ref{axis}, @ref{label}, @ref{table};
+
+kind of smoothing (for digits 1,3,5) in @ref{smooth};
+
+digits for a value.
+
+ at item 4,6,8
+set to draw square, hex- or octo-pyramids instead of cones in @ref{cone}, @ref{cones}.
+
+ at item A,B,C,D,E,F,a,b,c,d,e,f
+can be hex-digit for color specification if placed inside @{@} (see @ref{Color styles}).
+
+ at item A
+arrow style (see @ref{Line styles});
+
+set to use absolute position in whole picture for @ref{text}, @ref{colorbar}, @ref{legend}.
+
+ at item a
+set to use absolute position in subplot for @ref{text};
+
+style of @ref{plot}, @ref{radar}, @ref{tens}, @ref{area}, @ref{region} to draw segments between points outside of axis range;
+
+style of @ref{bars}, @ref{barh}, @ref{cones}.
+
+ at item B
+dark blue color (see @ref{Color styles}).
+
+ at item b
+blue color (see @ref{Color styles});
+
+bold font face if placed after @samp{:} (see @ref{Font styles}).
+
+ at item C
+dark cyan color (see @ref{Color styles});
+
+align text to center if placed after @samp{:} (see @ref{Font styles}).
+
+ at item c
+cyan color (see @ref{Color styles});
+
+name of color axis;
+
+cosine transform for @ref{transform}.
+
+ at item D
+arrow style (see @ref{Line styles});
+
+one of mask for face filling (see @ref{Color scheme}).
+
+ at item d
+one of marks (see @ref{Line styles}) or kind of @ref{error} boxes;
+
+one of mask for face filling (see @ref{Color scheme});
+
+start hex-dash description if placed inside @{@} (see @ref{Line styles}).
+
+ at item E
+dark green-yellow color (see @ref{Color styles}).
+
+ at item e
+green-yellow color (see @ref{Color styles}).
+
+ at item F
+
+set fixed bar widths in @ref{bars}, @ref{barh};
+
+set LaTeX-like format for numbers in @ref{axis}, @ref{label}, @ref{table}.
+
+ at item f
+style of @ref{bars}, @ref{barh};
+
+style of @ref{vect}, @ref{vect3};
+
+set fixed format for numbers in @ref{axis}, @ref{label}, @ref{table};
+
+Fourier transform for @ref{transform}.
+
+ at item G
+dark green color (see @ref{Color styles}).
+
+ at item g
+green color (see @ref{Color styles}).
+
+ at item H
+dark gray color (see @ref{Color styles}).
+
+ at item h
+gray color (see @ref{Color styles});
+
+Hankel transform for @ref{transform}.
+
+ at item I
+arrow style (see @ref{Line styles});
+
+set @ref{colorbar} position near boundary.
+
+ at item i
+line dashing style (see @ref{Line styles});
+
+italic font face if placed after @samp{:} (see @ref{Font styles}).
+
+set to use inverse values for @ref{cloud}, @ref{pipe}, @ref{dew};
+
+set to fill only area with y1<y<y2 for @ref{region};
+
+inverse Fourier transform for @ref{transform}, @ref{transforma}, @ref{fourier}.
+
+ at item j
+line dashing style (see @ref{Line styles});
+
+one of mask for face filling (see @ref{Color scheme}).
+
+ at item K
+arrow style (see @ref{Line styles}).
+
+ at item k
+black color (see @ref{Color styles}).
+
+ at item L
+dark green-blue color (see @ref{Color styles});
+
+align text to left if placed after @samp{:} (see @ref{Font styles}).
+
+ at item l
+green-blue color (see @ref{Color styles}).
+
+ at item M
+dark magenta color (see @ref{Color styles}).
+
+ at item m
+magenta color (see @ref{Color styles}).
+
+ at item N
+dark sky-blue color (see @ref{Color styles}).
+
+ at item n
+sky-blue color (see @ref{Color styles}).
+
+ at item O
+arrow style (see @ref{Line styles});
+
+one of mask for face filling (see @ref{Color scheme}).
+
+ at item o
+one of marks (see @ref{Line styles}) or kind of @ref{error} boxes;
+
+one of mask for face filling (see @ref{Color scheme});
+
+over-line text if placed after @samp{:} (see @ref{Font styles}).
+
+ at item P
+dark purple color (see @ref{Color styles}).
+
+ at item p
+purple color (see @ref{Color styles}).
+
+ at item Q
+dark orange or brown color (see @ref{Color styles}).
+
+ at item q
+orange color (see @ref{Color styles}).
+
+ at item R
+dark red color (see @ref{Color styles});
+
+align text to right if placed after @samp{:} (see @ref{Font styles}).
+
+ at item r
+red color (see @ref{Color styles}).
+
+ at item S
+arrow style (see @ref{Line styles});
+
+one of mask for face filling (see @ref{Color scheme}).
+
+ at item s
+one of marks (see @ref{Line styles}) or kind of @ref{error} boxes;
+
+one of mask for face filling (see @ref{Color scheme});
+
+start hex-mask description if placed inside @{@} (see @ref{Color scheme});
+
+sine transform for @ref{transform}.
+
+ at item t
+draw tubes instead of cones in @ref{cone}, @ref{cones};
+
+ at item T
+arrow style (see @ref{Line styles});
+
+place text under the curve for @ref{text}, @ref{cont}, @ref{cont3}.
+
+ at item t
+set to draw text labels for @ref{cont}, @ref{cont3};
+
+name of t-axis (one of ternary axis);
+
+variable in @ref{Textual formulas}, which usually is varied in range [0,1].
+
+ at item U
+dark blue-violet color (see @ref{Color styles});
+
+disable rotation of tick labels for @ref{axis}.
+
+ at item u
+blue-violet color (see @ref{Color styles});
+
+under-line text if placed after @samp{:} (see @ref{Font styles});
+
+name of u-axis (one of ternary axis);
+
+variable in @ref{Textual formulas}, which usually denote array itself.
+
+ at item V
+arrow style (see @ref{Line styles});
+
+place text centering on vertical direction for @ref{text}.
+
+ at item v
+one of marks (see @ref{Line styles});
+
+set to draw vectors on flow threads for @ref{flow} and on segments for @ref{lamerey}.
+
+ at item W
+bright gray color (see @ref{Color styles}).
+
+ at item w
+white color (see @ref{Color styles});
+
+wired text if placed after @samp{:} (see @ref{Font styles});
+
+name of w-axis (one of ternary axis);
+
+ at item X
+arrow style (see @ref{Line styles}).
+
+ at item x
+
+name of x-axis or x-direction or 1st dimension of a data array;
+
+start hex-color description if placed inside @{@} (see @ref{Color styles});
+
+one of marks (see @ref{Line styles}) or kind of @ref{error} boxes;
+
+tiles orientation perpendicular to x-axis in @ref{tile}, @ref{tiles};
+
+style of @ref{tape}.
+
+ at item Y
+dark yellow or gold color (see @ref{Color styles}).
+
+ at item y
+yellow color (see @ref{Color styles});
+
+name of y-axis or y-direction or 2nd dimension of a data array;
+
+tiles orientation perpendicular to y-axis in @ref{tile}, @ref{tiles}.
+
+ at item z
+
+name of z-axis or z-direction or 3d dimension of a data array;
+
+style of @ref{tape}.
+
+ at end table
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Hot-keys for mglview, Hot-keys for UDAV, Symbols for styles, Symbols and hot-keys
+ at section Hot-keys for mglview
+ at nav{}
+
+ at multitable @columnfractions .3 .7
+ at headitem Key @tab Description
+ at item @key{Ctrl-P}
+ at tab Open printer dialog and print graphics.
+
+ at item @key{Ctrl-W}
+ at tab Close window.
+
+ at item @key{Ctrl-T}
+ at tab Switch on/off transparency for the graphics.
+
+ at item @key{Ctrl-L}
+ at tab Switch on/off additional lightning for the graphics.
+
+ at item @key{Ctrl-Space}
+ at tab Restore default graphics rotation, zoom and perspective.
+
+ at item @key{F5}
+ at tab Execute script and redraw graphics.
+
+ at item @key{F6}
+ at tab Change canvas size to fill whole region.
+
+ at item @key{F7}
+ at tab Stop drawing and script execution.
+
+ at item @key{Ctrl-F5}
+ at tab Run slideshow. If no parameter specified then the dialog with slideshow options will appear.
+
+ at item @key{Ctrl-Comma}, @key{Ctrl-Period}
+ at tab Show next/previous slide. If no parameter specified then the dialog with slideshow options will appear.
+
+
+ at item @key{Ctrl-Shift-G}
+ at tab Copy graphics to clipboard.
+
+
+
+ at item @key{Alt-P}
+ at tab Export as semitransparent PNG.
+
+ at item @key{Alt-F}
+ at tab Export as solid PNG.
+
+ at item @key{Alt-J}
+ at tab Export as JPEG.
+
+ at item @key{Alt-E}
+ at tab Export as vector EPS.
+
+ at item @key{Alt-S}
+ at tab Export as vector SVG.
+
+ at item @key{Alt-L}
+ at tab Export as LaTeX/Tikz image.
+
+ at item @key{Alt-M}
+ at tab Export as MGLD.
+
+ at item @key{Alt-D}
+ at tab Export as PRC/PDF.
+
+ at item @key{Alt-O}
+ at tab Export as OBJ.
+
+ at c @item @key{Alt-X}
+ at c @tab Export as X3D.
+ at end multitable
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Hot-keys for UDAV, , Hot-keys for mglview, Symbols and hot-keys
+ at section Hot-keys for UDAV
+ at nav{}
+
+ at multitable @columnfractions .3 .7
+ at headitem Key @tab Description
+ at item @key{Ctrl-N}
+ at tab Create new window with empty script. Note, all scripts share variables. So, second window can be used to see some additional information of existed variables.
+
+ at item @key{Ctrl-O}
+ at tab Open and execute/show script or data from file. You may switch off automatic exection in UDAV properties
+
+ at item @key{Ctrl-S}
+ at tab Save script to a file.
+
+ at item @key{Ctrl-P}
+ at tab Open printer dialog and print graphics.
+
+ at item @key{Ctrl-Z}
+ at tab Undo changes in script editor.
+
+ at item @key{Ctrl-Shift-Z}
+ at tab Redo changes in script editor.
+
+ at item @key{Ctrl-X}
+ at tab Cut selected text into clipboard.
+
+ at item @key{Ctrl-C}
+ at tab Copy selected text into clipboard.
+
+ at item @key{Ctrl-V}
+ at tab Paste selected text from clipboard.
+
+ at item @key{Ctrl-A}
+ at tab Select all text in editor.
+
+ at item @key{Ctrl-F}
+ at tab Show dialog for text finding.
+
+ at item @key{F3}
+ at tab Find next occurrence of the text.
+
+
+ at item @key{Win-C} or @key{Meta-C}
+ at tab Show dialog for new command and put it into the script.
+
+ at item @key{Win-F} or @key{Meta-F}
+ at tab Insert last fitted formula with found coefficients.
+
+ at item @key{Win-S} or @key{Meta-S}
+ at tab Show dialog for styles and put it into the script. Styles define the plot view (color scheme, marks, dashing and so on).
+
+ at item @key{Win-O} or @key{Meta-O}
+ at tab Show dialog for options and put it into the script. Options are used for additional setup the plot.
+
+ at item @key{Win-N} or @key{Meta-N}
+ at tab Replace selected expression by its numerical value.
+
+ at item @key{Win-P} or @key{Meta-P}
+ at tab Select file and insert its file name into the script.
+
+ at item @key{Win-G} or @key{Meta-G}
+ at tab Show dialog for plot setup and put resulting code into the script. This dialog setup axis, labels, lighting and other general things.
+
+
+
+ at item @key{Ctrl-Shift-O}
+ at tab Load data from file. Data will be deleted only at exit but UDAV will not ask to save it.
+
+ at item @key{Ctrl-Shift-S}
+ at tab Save data to a file.
+
+ at item @key{Ctrl-Shift-C}
+ at tab Copy range of numbers to clipboard.
+
+ at item @key{Ctrl-Shift-V}
+ at tab Paste range of numbers from clipboard.
+
+ at item @key{Ctrl-Shift-N}
+ at tab Recreate the data with new sizes and fill it by zeros.
+
+ at item @key{Ctrl-Shift-R}
+ at tab Resize (interpolate) the data to specified sizes.
+
+ at item @key{Ctrl-Shift-T}
+ at tab Transform data along dimension(s).
+
+ at item @key{Ctrl-Shift-M}
+ at tab Make another data.
+
+ at item @key{Ctrl-Shift-H}
+ at tab Find histogram of data.
+
+
+
+ at item @key{Ctrl-T}
+ at tab Switch on/off transparency for the graphics.
+
+ at item @key{Ctrl-L}
+ at tab Switch on/off additional lightning for the graphics.
+
+ at item @key{Ctrl-G}
+ at tab Switch on/off grid of absolute coordinates.
+
+ at item @key{Ctrl-Space}
+ at tab Restore default graphics rotation, zoom and perspective.
+
+ at item @key{F5}
+ at tab Execute script and redraw graphics.
+
+ at item @key{F6}
+ at tab Change canvas size to fill whole region.
+
+ at item @key{F7}
+ at tab Stop script execution and drawing.
+
+ at item @key{F8}
+ at tab Show/hide tool window with list of hidden plots.
+
+ at item @key{F9}
+ at tab Restore status for 'once' command and reload data.
+
+ at item @key{Ctrl-F5}
+ at tab Run slideshow. If no parameter specified then the dialog with slideshow options will appear.
+
+ at item @key{Ctrl-Comma}, @key{Ctrl-Period}
+ at tab Show next/previous slide. If no parameter specified then the dialog with slideshow options will appear.
+
+ at item @key{Ctrl-W}
+ at tab Open dialog with slideshow options.
+
+ at item @key{Ctrl-Shift-G}
+ at tab Copy graphics to clipboard.
+
+
+ at item @key{F1}
+ at tab Show help on MGL commands
+
+ at item @key{F2}
+ at tab Show/hide tool window with messages and information.
+
+ at item @key{F4}
+ at tab Show/hide calculator which evaluate and help to type textual formulas. Textual formulas may contain data variables too.
+
+
+ at item @key{Meta-Shift-Up}, @key{Meta-Shift-Down}
+ at tab Change view angle @math{\theta}.
+
+ at item @key{Meta-Shift-Left}, @key{Meta-Shift-Right}
+ at tab Change view angle @math{\phi}.
+
+ at item @key{Alt-Minus}, @key{Alt-Equal}
+ at tab Zoom in/out whole image.
+
+ at item @key{Alt-Up}, @key{Alt-Down}, @key{Alt-Right}, @key{Alt-Left}
+ at tab Shift whole image.
+
+ at item @key{Alt-P}
+ at tab Export as semitransparent PNG.
+
+ at item @key{Alt-F}
+ at tab Export as solid PNG.
+
+ at item @key{Alt-J}
+ at tab Export as JPEG.
+
+ at item @key{Alt-E}
+ at tab Export as vector EPS.
+
+ at item @key{Alt-S}
+ at tab Export as vector SVG.
+
+ at item @key{Alt-L}
+ at tab Export as LaTeX/Tikz image.
+
+ at item @key{Alt-M}
+ at tab Export as MGLD.
+
+ at item @key{Alt-D}
+ at tab Export as PRC/PDF.
+
+ at item @key{Alt-O}
+ at tab Export as OBJ.
+
+ at c @item @key{Alt-X}
+ at c @tab Export as X3D.
+
+ at end multitable
+
+ at external{}
diff --git a/texinfo/time.texi b/texinfo/time.texi
new file mode 100644
index 0000000..80a9a9e
--- /dev/null
+++ b/texinfo/time.texi
@@ -0,0 +1,133 @@
+ at multitable @columnfractions .16 .12 .12 .12 .12 .12 .12 .12
+ at headitem Name @tab q=0 @tab q=1 @tab q=2 @tab q=4 @tab q=5 @tab q=6 @tab q=8
+ at item 3wave @tab 0.0447 @tab 0.0932 @tab 0.0975 @tab 0.038 @tab 0.0758 @tab 0.0879 @tab 0.0241
+ at item alpha @tab 0.0833 @tab 0.142 @tab 0.131 @tab 0.0256 @tab 0.0494 @tab 0.0562 @tab 0.0294
+ at item apde @tab 85.7 @tab 86.1 @tab 86 @tab 85.7 @tab 85.4 @tab 85.9 @tab 85.8
+ at item area @tab 0.0419 @tab 0.0876 @tab 0.104 @tab 0.0239 @tab 0.0631 @tab 0.081 @tab 0.0163
+ at item aspect @tab 0.0382 @tab 0.0748 @tab 0.0797 @tab 0.0197 @tab 0.0461 @tab 0.0482 @tab 0.0155
+ at item axial @tab 0.756 @tab 1.2 @tab 1.13 @tab 0.2 @tab 0.573 @tab 0.597 @tab 0.131
+ at item axis @tab 0.0691 @tab 0.163 @tab 0.153 @tab 0.0204 @tab 0.0717 @tab 0.0665 @tab 0.0201
+ at item barh @tab 0.0363 @tab 0.0668 @tab 0.0659 @tab 0.019 @tab 0.0432 @tab 0.0412 @tab 0.00942
+ at item bars @tab 0.0436 @tab 0.0855 @tab 0.0982 @tab 0.0378 @tab 0.0574 @tab 0.0709 @tab 0.0172
+ at item belt @tab 0.0398 @tab 0.052 @tab 0.0577 @tab 0.0251 @tab 0.0285 @tab 0.0359 @tab 0.0232
+ at item bifurcation @tab 0.58 @tab 0.657 @tab 0.662 @tab 0.619 @tab 0.668 @tab 0.659 @tab 0.566
+ at item box @tab 0.0572 @tab 0.103 @tab 0.105 @tab 0.024 @tab 0.0446 @tab 0.0537 @tab 0.0419
+ at item boxplot @tab 0.0437 @tab 0.158 @tab 0.149 @tab 0.083 @tab 0.091 @tab 0.0985 @tab 0.103
+ at item boxs @tab 0.267 @tab 0.516 @tab 0.494 @tab 0.0499 @tab 0.17 @tab 0.188 @tab 0.0469
+ at item candle @tab 0.0275 @tab 0.0531 @tab 0.0622 @tab 0.0282 @tab 0.0399 @tab 0.0489 @tab 0.0131
+ at item chart @tab 0.421 @tab 0.797 @tab 0.812 @tab 0.124 @tab 0.301 @tab 0.458 @tab 0.0935
+ at item cloud @tab 0.0415 @tab 5.25 @tab 4.1 @tab 0.0366 @tab 0.618 @tab 0.838 @tab 0.0216
+ at item colorbar @tab 0.123 @tab 0.23 @tab 0.244 @tab 0.0901 @tab 0.231 @tab 0.231 @tab 0.0461
+ at item combined @tab 0.416 @tab 0.413 @tab 0.387 @tab 0.202 @tab 0.276 @tab 0.299 @tab 0.176
+ at item cones @tab 0.185 @tab 0.21 @tab 0.19 @tab 0.0694 @tab 0.11 @tab 0.134 @tab 0.0577
+ at item cont @tab 0.0727 @tab 0.146 @tab 0.15 @tab 0.0482 @tab 0.188 @tab 0.16 @tab 0.0438
+ at item cont_xyz @tab 0.0408 @tab 0.0712 @tab 0.0748 @tab 0.0306 @tab 0.0619 @tab 0.0785 @tab 0.0302
+ at item conta @tab 0.0419 @tab 0.0775 @tab 0.0761 @tab 0.0321 @tab 0.0651 @tab 0.0584 @tab 0.0289
+ at item contd @tab 0.206 @tab 0.258 @tab 0.251 @tab 0.114 @tab 0.145 @tab 0.158 @tab 0.0892
+ at item contf @tab 0.159 @tab 0.245 @tab 0.207 @tab 0.0796 @tab 0.133 @tab 0.144 @tab 0.0759
+ at item contf_xyz @tab 0.1 @tab 0.109 @tab 0.108 @tab 0.0589 @tab 0.078 @tab 0.0812 @tab 0.0495
+ at item contfa @tab 0.152 @tab 0.195 @tab 0.17 @tab 0.083 @tab 0.105 @tab 0.143 @tab 0.0596
+ at item contv @tab 0.119 @tab 0.162 @tab 0.161 @tab 0.0706 @tab 0.117 @tab 0.143 @tab 0.0475
+ at item correl @tab 0.0319 @tab 0.0791 @tab 0.0791 @tab 0.0293 @tab 0.0519 @tab 0.0546 @tab 0.0144
+ at item curvcoor @tab 0.0734 @tab 0.151 @tab 0.153 @tab 0.0374 @tab 0.0922 @tab 0.091 @tab 0.0326
+ at item cut @tab 0.826 @tab 0.718 @tab 0.544 @tab 0.356 @tab 0.338 @tab 0.383 @tab 0.318
+ at item dat_diff @tab 0.0712 @tab 0.109 @tab 0.106 @tab 0.0457 @tab 0.0664 @tab 0.0825 @tab 0.0285
+ at item dat_extra @tab 0.216 @tab 0.32 @tab 0.241 @tab 0.0643 @tab 0.131 @tab 0.22 @tab 0.0508
+ at item data1 @tab 2.7 @tab 1.99 @tab 1.78 @tab 1.4 @tab 1.4 @tab 1.49 @tab 1.28
+ at item data2 @tab 1.56 @tab 1.34 @tab 1.26 @tab 1.17 @tab 1.3 @tab 1.24 @tab 1.09
+ at item dens @tab 0.0815 @tab 0.145 @tab 0.147 @tab 0.0282 @tab 0.0668 @tab 0.0834 @tab 0.0259
+ at item dens_xyz @tab 0.0693 @tab 0.105 @tab 0.116 @tab 0.0566 @tab 0.0659 @tab 0.0751 @tab 0.0311
+ at item densa @tab 0.0709 @tab 0.0963 @tab 0.111 @tab 0.0562 @tab 0.0598 @tab 0.0835 @tab 0.0438
+ at item detect @tab 0.138 @tab 0.175 @tab 0.17 @tab 0.082 @tab 0.1 @tab 0.116 @tab 0.0695
+ at item dew @tab 1.82 @tab 1.8 @tab 0.838 @tab 0.14 @tab 0.142 @tab 0.123 @tab 0.0846
+ at item diffract @tab 0.0745 @tab 0.157 @tab 0.171 @tab 0.0584 @tab 0.125 @tab 0.146 @tab 0.0351
+ at item dilate @tab 0.078 @tab 0.179 @tab 0.199 @tab 0.0343 @tab 0.103 @tab 0.112 @tab 0.031
+ at item dots @tab 0.0694 @tab 0.104 @tab 0.11 @tab 0.0285 @tab 0.0503 @tab 0.0571 @tab 0.0166
+ at item earth @tab 31.5 @tab 34.8 @tab 22.7 @tab 12.4 @tab 13 @tab 12.4 @tab 12.1
+ at item error @tab 0.0383 @tab 0.0944 @tab 0.0927 @tab 0.0301 @tab 0.0791 @tab 0.0704 @tab 0.016
+ at item error2 @tab 0.0371 @tab 0.0927 @tab 0.0951 @tab 0.019 @tab 0.0571 @tab 0.0583 @tab 0.0297
+ at item export @tab 0.128 @tab 0.201 @tab 0.179 @tab 0.0842 @tab 0.0948 @tab 0.115 @tab 0.079
+ at item fall @tab 0.041 @tab 0.0523 @tab 0.0598 @tab 0.0162 @tab 0.0384 @tab 0.0412 @tab 0.0129
+ at item fit @tab 0.0348 @tab 0.091 @tab 0.0833 @tab 0.0237 @tab 0.0465 @tab 0.048 @tab 0.0159
+ at item flame2d @tab 5.63 @tab 5.88 @tab 5.75 @tab 3.1 @tab 3.27 @tab 3.13 @tab 0.984
+ at item flow @tab 0.341 @tab 0.416 @tab 0.42 @tab 0.315 @tab 0.41 @tab 0.402 @tab 0.322
+ at item fog @tab 0.0453 @tab 0.0778 @tab 0.0943 @tab 0.0156 @tab 0.0546 @tab 0.0768 @tab 0.0153
+ at item fonts @tab 0.0589 @tab 0.1 @tab 0.099 @tab 0.035 @tab 0.0651 @tab 0.0678 @tab 0.0391
+ at item grad @tab 0.072 @tab 0.11 @tab 0.135 @tab 0.0729 @tab 0.0929 @tab 0.11 @tab 0.0593
+ at item hist @tab 0.15 @tab 0.154 @tab 0.154 @tab 0.0614 @tab 0.0863 @tab 0.0862 @tab 0.0386
+ at item ifs2d @tab 0.635 @tab 0.645 @tab 0.637 @tab 0.305 @tab 0.336 @tab 0.321 @tab 0.106
+ at item ifs3d @tab 0.794 @tab 0.794 @tab 0.793 @tab 0.325 @tab 0.312 @tab 0.344 @tab 0.0855
+ at item indirect @tab 0.034 @tab 0.0656 @tab 0.0643 @tab 0.024 @tab 0.0675 @tab 0.0626 @tab 0.00264
+ at item inplot @tab 0.0533 @tab 0.131 @tab 0.121 @tab 0.0251 @tab 0.0678 @tab 0.0697 @tab 0.0269
+ at item iris @tab 0.0653 @tab 0.161 @tab 0.175 @tab 0.0368 @tab 0.0872 @tab 0.105 @tab 0.0187
+ at item label @tab 0.0273 @tab 0.054 @tab 0.0605 @tab 0.0259 @tab 0.045 @tab 0.0455 @tab 0.0024
+ at item lamerey @tab 0.0299 @tab 0.0548 @tab 0.0575 @tab 0.0159 @tab 0.0336 @tab 0.0277 @tab 0.0132
+ at item legend @tab 0.102 @tab 0.262 @tab 0.27 @tab 0.0259 @tab 0.131 @tab 0.133 @tab 0.0167
+ at item light @tab 0.127 @tab 0.163 @tab 0.13 @tab 0.0295 @tab 0.0487 @tab 0.0743 @tab 0.0237
+ at item loglog @tab 0.066 @tab 0.192 @tab 0.191 @tab 0.0352 @tab 0.0903 @tab 0.1 @tab 0.0292
+ at item map @tab 0.0413 @tab 0.0949 @tab 0.0855 @tab 0.0314 @tab 0.0655 @tab 0.0766 @tab 0.0162
+ at item mark @tab 0.0164 @tab 0.0338 @tab 0.0469 @tab 0.022 @tab 0.0235 @tab 0.0318 @tab 0.0123
+ at item mask @tab 0.0639 @tab 0.125 @tab 0.125 @tab 0.0227 @tab 0.0711 @tab 0.0694 @tab 0.00337
+ at item mesh @tab 0.0311 @tab 0.0894 @tab 0.0981 @tab 0.0252 @tab 0.0506 @tab 0.0637 @tab 0.016
+ at item mirror @tab 0.0988 @tab 0.179 @tab 0.177 @tab 0.0369 @tab 0.0799 @tab 0.0871 @tab 0.0251
+ at item molecule @tab 0.1 @tab 0.129 @tab 0.112 @tab 0.0198 @tab 0.0416 @tab 0.0599 @tab 0.0173
+ at item ode @tab 0.217 @tab 0.323 @tab 0.303 @tab 0.191 @tab 0.309 @tab 0.321 @tab 0.175
+ at item ohlc @tab 0.0154 @tab 0.0286 @tab 0.0411 @tab 0.0175 @tab 0.0286 @tab 0.0368 @tab 0.0104
+ at item param1 @tab 0.177 @tab 0.381 @tab 0.323 @tab 0.0653 @tab 0.17 @tab 0.196 @tab 0.0374
+ at item param2 @tab 0.569 @tab 0.711 @tab 0.547 @tab 0.169 @tab 0.221 @tab 0.25 @tab 0.135
+ at item param3 @tab 2.2 @tab 3.25 @tab 2.54 @tab 0.802 @tab 0.936 @tab 0.937 @tab 0.689
+ at item paramv @tab 1.2 @tab 1.45 @tab 1.32 @tab 0.635 @tab 0.789 @tab 0.787 @tab 0.629
+ at item parser @tab 0.0412 @tab 0.0635 @tab 0.0632 @tab 0.0284 @tab 0.0566 @tab 0.0707 @tab 0.0165
+ at item pde @tab 0.327 @tab 0.406 @tab 0.395 @tab 0.333 @tab 0.282 @tab 0.293 @tab 0.26
+ at item pendelta @tab 0.0435 @tab 0.0435 @tab 0.0483 @tab 0.0468 @tab 0.0449 @tab 0.0453 @tab 0.0442
+ at item pipe @tab 0.8 @tab 1.19 @tab 0.797 @tab 0.378 @tab 0.474 @tab 0.487 @tab 0.344
+ at item plot @tab 0.0541 @tab 0.0884 @tab 0.0983 @tab 0.0217 @tab 0.0555 @tab 0.0517 @tab 0.0199
+ at item pmap @tab 0.103 @tab 0.139 @tab 0.136 @tab 0.0491 @tab 0.0767 @tab 0.0922 @tab 0.0473
+ at item primitives @tab 0.0747 @tab 0.145 @tab 0.153 @tab 0.02 @tab 0.065 @tab 0.0892 @tab 0.0178
+ at item projection @tab 0.116 @tab 0.301 @tab 0.315 @tab 0.0267 @tab 0.17 @tab 0.183 @tab 0.0282
+ at item projection5 @tab 0.12 @tab 0.255 @tab 0.256 @tab 0.0356 @tab 0.143 @tab 0.159 @tab 0.021
+ at item pulse @tab 0.0254 @tab 0.0448 @tab 0.0563 @tab 0.0174 @tab 0.049 @tab 0.0557 @tab 0.0144
+ at item qo2d @tab 0.294 @tab 0.275 @tab 0.286 @tab 0.188 @tab 0.218 @tab 0.233 @tab 0.196
+ at item radar @tab 0.0195 @tab 0.0323 @tab 0.0427 @tab 0.00979 @tab 0.0518 @tab 0.0431 @tab 0.0118
+ at item refill @tab 0.193 @tab 0.286 @tab 0.215 @tab 0.074 @tab 0.133 @tab 0.13 @tab 0.0559
+ at item region @tab 0.0539 @tab 0.0867 @tab 0.0868 @tab 0.0232 @tab 0.0709 @tab 0.0724 @tab 0.0164
+ at item scanfile @tab 0.0302 @tab 0.0559 @tab 0.0555 @tab 0.0152 @tab 0.046 @tab 0.0569 @tab 0.0121
+ at item schemes @tab 0.0686 @tab 0.132 @tab 0.133 @tab 0.0317 @tab 0.0632 @tab 0.0779 @tab 0.0179
+ at item section @tab 0.0291 @tab 0.0632 @tab 0.0614 @tab 0.0265 @tab 0.0478 @tab 0.056 @tab 0.00308
+ at item several_light @tab 0.0623 @tab 0.0793 @tab 0.108 @tab 0.0262 @tab 0.0423 @tab 0.0676 @tab 0.015
+ at item solve @tab 0.0616 @tab 0.186 @tab 0.15 @tab 0.038 @tab 0.0907 @tab 0.101 @tab 0.017
+ at item stem @tab 0.0409 @tab 0.0826 @tab 0.0797 @tab 0.0153 @tab 0.0553 @tab 0.0546 @tab 0.0155
+ at item step @tab 0.0417 @tab 0.0657 @tab 0.0722 @tab 0.018 @tab 0.0448 @tab 0.0467 @tab 0.0158
+ at item stereo @tab 0.0714 @tab 0.0817 @tab 0.0735 @tab 0.0187 @tab 0.0316 @tab 0.06 @tab 0.0161
+ at item stfa @tab 0.0534 @tab 0.124 @tab 0.14 @tab 0.0295 @tab 0.0843 @tab 0.0965 @tab 0.0168
+ at item style @tab 0.105 @tab 0.256 @tab 0.256 @tab 0.0333 @tab 0.134 @tab 0.138 @tab 0.017
+ at item surf @tab 0.119 @tab 0.19 @tab 0.169 @tab 0.0383 @tab 0.0857 @tab 0.102 @tab 0.0258
+ at item surf3 @tab 2.28 @tab 3.29 @tab 3.25 @tab 0.975 @tab 2.8 @tab 2.94 @tab 0.508
+ at item surf3a @tab 0.531 @tab 0.391 @tab 0.362 @tab 0.247 @tab 0.246 @tab 0.301 @tab 0.254
+ at item surf3c @tab 0.546 @tab 0.389 @tab 0.345 @tab 0.217 @tab 0.214 @tab 0.298 @tab 0.176
+ at item surf3ca @tab 0.554 @tab 0.395 @tab 0.343 @tab 0.219 @tab 0.219 @tab 0.317 @tab 0.178
+ at item surfa @tab 0.0426 @tab 0.0691 @tab 0.082 @tab 0.016 @tab 0.0355 @tab 0.0564 @tab 0.0161
+ at item surfc @tab 0.0441 @tab 0.0606 @tab 0.0713 @tab 0.0259 @tab 0.0383 @tab 0.0459 @tab 0.0199
+ at item surfca @tab 0.0429 @tab 0.0601 @tab 0.0702 @tab 0.0233 @tab 0.0256 @tab 0.0524 @tab 0.016
+ at item table @tab 0.124 @tab 0.301 @tab 0.29 @tab 0.0257 @tab 0.145 @tab 0.154 @tab 0.0165
+ at item tape @tab 0.0428 @tab 0.089 @tab 0.0966 @tab 0.0214 @tab 0.0583 @tab 0.0539 @tab 0.0184
+ at item tens @tab 0.0337 @tab 0.06 @tab 0.0624 @tab 0.0289 @tab 0.0533 @tab 0.0551 @tab 0.0131
+ at item ternary @tab 0.113 @tab 0.275 @tab 0.269 @tab 0.0507 @tab 0.155 @tab 0.171 @tab 0.0316
+ at item text @tab 0.0832 @tab 0.226 @tab 0.218 @tab 0.035 @tab 0.116 @tab 0.127 @tab 0.00324
+ at item text2 @tab 0.073 @tab 0.161 @tab 0.163 @tab 0.0435 @tab 0.0997 @tab 0.111 @tab 0.0184
+ at item textmark @tab 0.044 @tab 0.112 @tab 0.112 @tab 0.0288 @tab 0.0632 @tab 0.0652 @tab 0.0136
+ at item ticks @tab 0.0983 @tab 0.265 @tab 0.261 @tab 0.0263 @tab 0.126 @tab 0.139 @tab 0.0275
+ at item tile @tab 0.0371 @tab 0.0569 @tab 0.064 @tab 0.0256 @tab 0.0321 @tab 0.0397 @tab 0.0227
+ at item tiles @tab 0.0377 @tab 0.0619 @tab 0.0687 @tab 0.0298 @tab 0.0194 @tab 0.0459 @tab 0.019
+ at item torus @tab 0.108 @tab 0.225 @tab 0.226 @tab 0.0269 @tab 0.102 @tab 0.124 @tab 0.0242
+ at item traj @tab 0.0145 @tab 0.0485 @tab 0.0451 @tab 0.0272 @tab 0.0286 @tab 0.0314 @tab 0.0131
+ at item triangulation @tab 0.0402 @tab 0.0847 @tab 0.111 @tab 0.0276 @tab 0.0648 @tab 0.0761 @tab 0.0156
+ at item triplot @tab 0.0294 @tab 0.0799 @tab 0.125 @tab 0.0157 @tab 0.0715 @tab 0.0863 @tab 0.0126
+ at item tube @tab 0.0844 @tab 0.214 @tab 0.203 @tab 0.0311 @tab 0.0878 @tab 0.105 @tab 0.0259
+ at item type0 @tab 0.228 @tab 0.274 @tab 0.229 @tab 0.0692 @tab 0.111 @tab 0.141 @tab 0.0619
+ at item type1 @tab 0.217 @tab 0.292 @tab 0.261 @tab 0.0715 @tab 0.106 @tab 0.152 @tab 0.0564
+ at item type2 @tab 0.221 @tab 0.276 @tab 0.231 @tab 0.0676 @tab 0.111 @tab 0.142 @tab 0.0649
+ at item vect @tab 0.0907 @tab 0.226 @tab 0.216 @tab 0.0601 @tab 0.139 @tab 0.166 @tab 0.045
+ at item vecta @tab 0.0318 @tab 0.0941 @tab 0.104 @tab 0.0334 @tab 0.117 @tab 0.118 @tab 0.0292
+ at item venn @tab 0.0156 @tab 0.0632 @tab 0.0922 @tab 0.0156 @tab 0.0367 @tab 0.0644 @tab 0.00185
+ at end multitable
diff --git a/texinfo/time_big.texi b/texinfo/time_big.texi
new file mode 100644
index 0000000..e2a1cbf
--- /dev/null
+++ b/texinfo/time_big.texi
@@ -0,0 +1,133 @@
+ at multitable @columnfractions .16 .12 .12 .12 .12 .12 .12 .12
+ at headitem Name @tab q=0 @tab q=1 @tab q=2 @tab q=4 @tab q=5 @tab q=6 @tab q=8
+ at item 3wave @tab 0.11 @tab 0.151 @tab 0.193 @tab 0.0729 @tab 0.133 @tab 0.188 @tab 0.0457
+ at item alpha @tab 0.105 @tab 0.223 @tab 0.306 @tab 0.0591 @tab 0.109 @tab 0.192 @tab 0.0559
+ at item apde @tab 86.3 @tab 86 @tab 86.1 @tab 85.6 @tab 85.9 @tab 85.8 @tab 85.6
+ at item area @tab 0.0781 @tab 0.196 @tab 0.291 @tab 0.0532 @tab 0.141 @tab 0.221 @tab 0.0452
+ at item aspect @tab 0.0629 @tab 0.13 @tab 0.164 @tab 0.0483 @tab 0.0851 @tab 0.107 @tab 0.0425
+ at item axial @tab 0.806 @tab 1.74 @tab 1.95 @tab 0.291 @tab 0.938 @tab 1.31 @tab 0.167
+ at item axis @tab 0.0949 @tab 0.196 @tab 0.231 @tab 0.0589 @tab 0.111 @tab 0.141 @tab 0.0417
+ at item barh @tab 0.063 @tab 0.128 @tab 0.176 @tab 0.0499 @tab 0.0851 @tab 0.121 @tab 0.0348
+ at item bars @tab 0.0778 @tab 0.156 @tab 0.219 @tab 0.0646 @tab 0.127 @tab 0.155 @tab 0.0493
+ at item belt @tab 0.0754 @tab 0.118 @tab 0.173 @tab 0.0501 @tab 0.0933 @tab 0.127 @tab 0.045
+ at item bifurcation @tab 0.602 @tab 0.728 @tab 0.755 @tab 0.635 @tab 0.711 @tab 0.746 @tab 0.575
+ at item box @tab 0.0904 @tab 0.164 @tab 0.209 @tab 0.0542 @tab 0.0995 @tab 0.164 @tab 0.0515
+ at item boxplot @tab 0.0454 @tab 0.0816 @tab 0.116 @tab 0.0449 @tab 0.0831 @tab 0.102 @tab 0.0327
+ at item boxs @tab 0.256 @tab 0.704 @tab 0.905 @tab 0.083 @tab 0.324 @tab 0.522 @tab 0.077
+ at item candle @tab 0.0599 @tab 0.107 @tab 0.148 @tab 0.0841 @tab 0.0872 @tab 0.126 @tab 0.0378
+ at item chart @tab 0.468 @tab 1.31 @tab 2.14 @tab 0.178 @tab 0.63 @tab 1.45 @tab 0.119
+ at item cloud @tab 0.0711 @tab 6.62 @tab 7.17 @tab 0.0517 @tab 1.45 @tab 2.83 @tab 0.0446
+ at item colorbar @tab 0.158 @tab 0.328 @tab 0.501 @tab 0.137 @tab 0.293 @tab 0.346 @tab 0.0733
+ at item combined @tab 0.462 @tab 0.552 @tab 0.611 @tab 0.253 @tab 0.389 @tab 0.518 @tab 0.201
+ at item cones @tab 0.216 @tab 0.309 @tab 0.375 @tab 0.117 @tab 0.192 @tab 0.269 @tab 0.0738
+ at item cont @tab 0.0959 @tab 0.22 @tab 0.242 @tab 0.0798 @tab 0.227 @tab 0.259 @tab 0.0616
+ at item cont_xyz @tab 0.0733 @tab 0.129 @tab 0.148 @tab 0.0589 @tab 0.111 @tab 0.133 @tab 0.0549
+ at item conta @tab 0.075 @tab 0.11 @tab 0.143 @tab 0.0597 @tab 0.11 @tab 0.132 @tab 0.0603
+ at item contd @tab 0.25 @tab 0.355 @tab 0.393 @tab 0.149 @tab 0.229 @tab 0.288 @tab 0.119
+ at item contf @tab 0.188 @tab 0.297 @tab 0.363 @tab 0.139 @tab 0.199 @tab 0.273 @tab 0.0952
+ at item contf_xyz @tab 0.123 @tab 0.18 @tab 0.234 @tab 0.0896 @tab 0.136 @tab 0.192 @tab 0.0852
+ at item contfa @tab 0.205 @tab 0.255 @tab 0.355 @tab 0.118 @tab 0.204 @tab 0.37 @tab 0.0739
+ at item contv @tab 0.142 @tab 0.248 @tab 0.303 @tab 0.112 @tab 0.21 @tab 0.297 @tab 0.079
+ at item correl @tab 0.0623 @tab 0.134 @tab 0.168 @tab 0.058 @tab 0.0907 @tab 0.13 @tab 0.0406
+ at item curvcoor @tab 0.0994 @tab 0.244 @tab 0.262 @tab 0.0688 @tab 0.14 @tab 0.175 @tab 0.0559
+ at item cut @tab 0.877 @tab 0.733 @tab 0.775 @tab 0.406 @tab 0.451 @tab 0.685 @tab 0.373
+ at item dat_diff @tab 0.1 @tab 0.174 @tab 0.221 @tab 0.0739 @tab 0.132 @tab 0.177 @tab 0.0577
+ at item dat_extra @tab 0.244 @tab 0.389 @tab 0.349 @tab 0.101 @tab 0.193 @tab 0.25 @tab 0.0777
+ at item data1 @tab 2.73 @tab 2.14 @tab 2.03 @tab 1.45 @tab 1.64 @tab 1.72 @tab 1.27
+ at item data2 @tab 1.55 @tab 1.41 @tab 1.5 @tab 1.2 @tab 1.29 @tab 1.38 @tab 1.11
+ at item dens @tab 0.117 @tab 0.272 @tab 0.396 @tab 0.0659 @tab 0.158 @tab 0.236 @tab 0.0522
+ at item dens_xyz @tab 0.0974 @tab 0.212 @tab 0.269 @tab 0.086 @tab 0.135 @tab 0.209 @tab 0.0576
+ at item densa @tab 0.104 @tab 0.18 @tab 0.266 @tab 0.092 @tab 0.135 @tab 0.21 @tab 0.0606
+ at item detect @tab 0.172 @tab 0.321 @tab 0.431 @tab 0.119 @tab 0.2 @tab 0.285 @tab 0.0936
+ at item dew @tab 1.85 @tab 1.91 @tab 1.21 @tab 0.177 @tab 0.209 @tab 0.272 @tab 0.108
+ at item diffract @tab 0.11 @tab 0.312 @tab 0.415 @tab 0.0894 @tab 0.204 @tab 0.273 @tab 0.0561
+ at item dilate @tab 0.112 @tab 0.27 @tab 0.408 @tab 0.0561 @tab 0.192 @tab 0.28 @tab 0.058
+ at item dots @tab 0.107 @tab 0.168 @tab 0.2 @tab 0.0547 @tab 0.101 @tab 0.12 @tab 0.0428
+ at item earth @tab 32.2 @tab 35.9 @tab 23.9 @tab 12.5 @tab 14.9 @tab 13.2 @tab 12.1
+ at item error @tab 0.0756 @tab 0.138 @tab 0.192 @tab 0.0735 @tab 0.115 @tab 0.158 @tab 0.0436
+ at item error2 @tab 0.0684 @tab 0.188 @tab 0.224 @tab 0.053 @tab 0.124 @tab 0.158 @tab 0.051
+ at item export @tab 0.18 @tab 0.329 @tab 0.426 @tab 0.111 @tab 0.191 @tab 0.279 @tab 0.1
+ at item fall @tab 0.0495 @tab 0.114 @tab 0.148 @tab 0.0421 @tab 0.0834 @tab 0.11 @tab 0.0456
+ at item fit @tab 0.0744 @tab 0.133 @tab 0.17 @tab 0.0488 @tab 0.0926 @tab 0.124 @tab 0.0452
+ at item flame2d @tab 6.3 @tab 6.61 @tab 6.46 @tab 3.71 @tab 3.89 @tab 3.77 @tab 1.04
+ at item flow @tab 0.364 @tab 0.53 @tab 0.526 @tab 0.35 @tab 0.495 @tab 0.508 @tab 0.328
+ at item fog @tab 0.0789 @tab 0.169 @tab 0.269 @tab 0.0601 @tab 0.129 @tab 0.243 @tab 0.043
+ at item fonts @tab 0.0976 @tab 0.149 @tab 0.168 @tab 0.0693 @tab 0.0898 @tab 0.136 @tab 0.0596
+ at item grad @tab 0.11 @tab 0.252 @tab 0.363 @tab 0.0929 @tab 0.203 @tab 0.286 @tab 0.0792
+ at item hist @tab 0.191 @tab 0.246 @tab 0.284 @tab 0.122 @tab 0.151 @tab 0.182 @tab 0.0648
+ at item ifs2d @tab 0.725 @tab 0.756 @tab 0.809 @tab 0.405 @tab 0.435 @tab 0.45 @tab 0.12
+ at item ifs3d @tab 0.857 @tab 0.875 @tab 0.918 @tab 0.368 @tab 0.389 @tab 0.44 @tab 0.11
+ at item indirect @tab 0.0616 @tab 0.105 @tab 0.137 @tab 0.0611 @tab 0.103 @tab 0.147 @tab 0.0334
+ at item inplot @tab 0.0825 @tab 0.187 @tab 0.203 @tab 0.0511 @tab 0.121 @tab 0.148 @tab 0.0496
+ at item iris @tab 0.0963 @tab 0.243 @tab 0.274 @tab 0.0651 @tab 0.148 @tab 0.183 @tab 0.0559
+ at item label @tab 0.0482 @tab 0.106 @tab 0.135 @tab 0.0474 @tab 0.104 @tab 0.116 @tab 0.0353
+ at item lamerey @tab 0.0499 @tab 0.0916 @tab 0.119 @tab 0.0422 @tab 0.0708 @tab 0.103 @tab 0.0325
+ at item legend @tab 0.139 @tab 0.364 @tab 0.395 @tab 0.0578 @tab 0.198 @tab 0.239 @tab 0.0452
+ at item light @tab 0.148 @tab 0.245 @tab 0.371 @tab 0.0578 @tab 0.114 @tab 0.252 @tab 0.0426
+ at item loglog @tab 0.109 @tab 0.244 @tab 0.292 @tab 0.0681 @tab 0.165 @tab 0.2 @tab 0.0496
+ at item map @tab 0.0669 @tab 0.157 @tab 0.237 @tab 0.0728 @tab 0.136 @tab 0.199 @tab 0.0463
+ at item mark @tab 0.0617 @tab 0.0833 @tab 0.111 @tab 0.0602 @tab 0.0638 @tab 0.0986 @tab 0.0367
+ at item mask @tab 0.106 @tab 0.25 @tab 0.249 @tab 0.0428 @tab 0.148 @tab 0.161 @tab 0.0418
+ at item mesh @tab 0.0618 @tab 0.152 @tab 0.195 @tab 0.0507 @tab 0.117 @tab 0.157 @tab 0.0463
+ at item mirror @tab 0.131 @tab 0.269 @tab 0.325 @tab 0.0622 @tab 0.144 @tab 0.206 @tab 0.041
+ at item molecule @tab 0.126 @tab 0.204 @tab 0.312 @tab 0.0563 @tab 0.0954 @tab 0.234 @tab 0.045
+ at item ode @tab 0.23 @tab 0.386 @tab 0.414 @tab 0.222 @tab 0.396 @tab 0.427 @tab 0.204
+ at item ohlc @tab 0.0487 @tab 0.0735 @tab 0.116 @tab 0.0484 @tab 0.0702 @tab 0.0948 @tab 0.0419
+ at item param1 @tab 0.222 @tab 0.479 @tab 0.536 @tab 0.0829 @tab 0.26 @tab 0.362 @tab 0.0677
+ at item param2 @tab 0.597 @tab 0.909 @tab 0.882 @tab 0.21 @tab 0.352 @tab 0.51 @tab 0.299
+ at item param3 @tab 2.26 @tab 3.58 @tab 3.31 @tab 0.899 @tab 1.15 @tab 1.33 @tab 0.697
+ at item paramv @tab 1.25 @tab 1.63 @tab 1.52 @tab 0.664 @tab 0.873 @tab 0.943 @tab 0.644
+ at item parser @tab 0.0729 @tab 0.142 @tab 0.166 @tab 0.0555 @tab 0.139 @tab 0.168 @tab 0.0428
+ at item pde @tab 0.377 @tab 0.522 @tab 0.581 @tab 0.294 @tab 0.36 @tab 0.459 @tab 0.364
+ at item pendelta @tab 0.103 @tab 0.103 @tab 0.0974 @tab 0.106 @tab 0.103 @tab 0.123 @tab 0.1
+ at item pipe @tab 0.87 @tab 1.39 @tab 1.18 @tab 0.435 @tab 0.6 @tab 0.833 @tab 0.376
+ at item plot @tab 0.0781 @tab 0.135 @tab 0.17 @tab 0.0525 @tab 0.103 @tab 0.138 @tab 0.0452
+ at item pmap @tab 0.121 @tab 0.212 @tab 0.254 @tab 0.0869 @tab 0.144 @tab 0.195 @tab 0.0671
+ at item primitives @tab 0.109 @tab 0.243 @tab 0.401 @tab 0.0751 @tab 0.135 @tab 0.277 @tab 0.0456
+ at item projection @tab 0.15 @tab 0.51 @tab 0.592 @tab 0.0726 @tab 0.327 @tab 0.423 @tab 0.0504
+ at item projection5 @tab 0.131 @tab 0.41 @tab 0.479 @tab 0.0533 @tab 0.271 @tab 0.359 @tab 0.0422
+ at item pulse @tab 0.058 @tab 0.0867 @tab 0.117 @tab 0.0499 @tab 0.0795 @tab 0.111 @tab 0.0389
+ at item qo2d @tab 0.263 @tab 0.396 @tab 0.523 @tab 0.227 @tab 0.311 @tab 0.397 @tab 0.203
+ at item radar @tab 0.0462 @tab 0.0789 @tab 0.107 @tab 0.0545 @tab 0.0798 @tab 0.118 @tab 0.0329
+ at item refill @tab 0.226 @tab 0.357 @tab 0.343 @tab 0.109 @tab 0.189 @tab 0.238 @tab 0.081
+ at item region @tab 0.0774 @tab 0.188 @tab 0.246 @tab 0.0596 @tab 0.124 @tab 0.176 @tab 0.0417
+ at item scanfile @tab 0.0475 @tab 0.0924 @tab 0.12 @tab 0.0457 @tab 0.0809 @tab 0.119 @tab 0.0332
+ at item schemes @tab 0.128 @tab 0.254 @tab 0.334 @tab 0.0724 @tab 0.146 @tab 0.218 @tab 0.0515
+ at item section @tab 0.0611 @tab 0.106 @tab 0.135 @tab 0.0553 @tab 0.1 @tab 0.127 @tab 0.0378
+ at item several_light @tab 0.095 @tab 0.159 @tab 0.394 @tab 0.0565 @tab 0.0946 @tab 0.347 @tab 0.0477
+ at item solve @tab 0.0972 @tab 0.241 @tab 0.266 @tab 0.072 @tab 0.168 @tab 0.2 @tab 0.042
+ at item stem @tab 0.0637 @tab 0.152 @tab 0.189 @tab 0.0552 @tab 0.101 @tab 0.136 @tab 0.0376
+ at item step @tab 0.0634 @tab 0.123 @tab 0.141 @tab 0.141 @tab 0.0798 @tab 0.116 @tab 0.0464
+ at item stereo @tab 0.0897 @tab 0.149 @tab 0.26 @tab 0.053 @tab 0.098 @tab 0.212 @tab 0.046
+ at item stfa @tab 0.102 @tab 0.272 @tab 0.365 @tab 0.0665 @tab 0.206 @tab 0.27 @tab 0.0483
+ at item style @tab 0.139 @tab 0.347 @tab 0.414 @tab 0.0583 @tab 0.207 @tab 0.249 @tab 0.0454
+ at item surf @tab 0.151 @tab 0.288 @tab 0.38 @tab 0.0754 @tab 0.156 @tab 0.257 @tab 0.0569
+ at item surf3 @tab 2.35 @tab 4.26 @tab 4.16 @tab 1.45 @tab 4.03 @tab 4.18 @tab 0.539
+ at item surf3a @tab 0.618 @tab 0.502 @tab 0.655 @tab 0.27 @tab 0.39 @tab 0.885 @tab 0.195
+ at item surf3c @tab 0.607 @tab 0.501 @tab 0.643 @tab 0.266 @tab 0.377 @tab 0.832 @tab 0.206
+ at item surf3ca @tab 0.613 @tab 0.511 @tab 0.665 @tab 0.281 @tab 0.391 @tab 0.878 @tab 0.198
+ at item surfa @tab 0.0777 @tab 0.137 @tab 0.235 @tab 0.0478 @tab 0.0916 @tab 0.205 @tab 0.047
+ at item surfc @tab 0.0658 @tab 0.134 @tab 0.239 @tab 0.0497 @tab 0.0845 @tab 0.208 @tab 0.0388
+ at item surfca @tab 0.0774 @tab 0.126 @tab 0.238 @tab 0.0612 @tab 0.0847 @tab 0.201 @tab 0.0403
+ at item table @tab 0.145 @tab 0.387 @tab 0.401 @tab 0.0592 @tab 0.196 @tab 0.251 @tab 0.0454
+ at item tape @tab 0.0733 @tab 0.158 @tab 0.205 @tab 0.0476 @tab 0.117 @tab 0.152 @tab 0.0453
+ at item tens @tab 0.061 @tab 0.0914 @tab 0.131 @tab 0.0661 @tab 0.0965 @tab 0.132 @tab 0.0367
+ at item ternary @tab 0.151 @tab 0.419 @tab 0.501 @tab 0.0744 @tab 0.267 @tab 0.342 @tab 0.0543
+ at item text @tab 0.123 @tab 0.283 @tab 0.332 @tab 0.0588 @tab 0.167 @tab 0.207 @tab 0.0359
+ at item text2 @tab 0.102 @tab 0.224 @tab 0.254 @tab 0.0707 @tab 0.151 @tab 0.181 @tab 0.0419
+ at item textmark @tab 0.0771 @tab 0.16 @tab 0.183 @tab 0.055 @tab 0.108 @tab 0.141 @tab 0.0338
+ at item ticks @tab 0.139 @tab 0.331 @tab 0.36 @tab 0.0597 @tab 0.178 @tab 0.207 @tab 0.0445
+ at item tile @tab 0.0615 @tab 0.112 @tab 0.172 @tab 0.0456 @tab 0.0817 @tab 0.132 @tab 0.0449
+ at item tiles @tab 0.0611 @tab 0.132 @tab 0.186 @tab 0.0598 @tab 0.082 @tab 0.134 @tab 0.05
+ at item torus @tab 0.135 @tab 0.367 @tab 0.491 @tab 0.0662 @tab 0.203 @tab 0.342 @tab 0.0506
+ at item traj @tab 0.0463 @tab 0.105 @tab 0.126 @tab 0.0445 @tab 0.072 @tab 0.102 @tab 0.0434
+ at item triangulation @tab 0.0616 @tab 0.175 @tab 0.294 @tab 0.056 @tab 0.148 @tab 0.237 @tab 0.0412
+ at item triplot @tab 0.0496 @tab 0.202 @tab 0.5 @tab 0.0519 @tab 0.118 @tab 0.358 @tab 0.0329
+ at item tube @tab 0.132 @tab 0.349 @tab 0.473 @tab 0.0673 @tab 0.17 @tab 0.291 @tab 0.0515
+ at item type0 @tab 0.282 @tab 0.456 @tab 0.62 @tab 0.131 @tab 0.234 @tab 0.486 @tab 0.112
+ at item type1 @tab 0.284 @tab 0.441 @tab 0.628 @tab 0.135 @tab 0.242 @tab 0.503 @tab 0.107
+ at item type2 @tab 0.296 @tab 0.445 @tab 0.605 @tab 0.128 @tab 0.25 @tab 0.472 @tab 0.124
+ at item vect @tab 0.114 @tab 0.306 @tab 0.341 @tab 0.102 @tab 0.22 @tab 0.247 @tab 0.0755
+ at item vecta @tab 0.0637 @tab 0.161 @tab 0.2 @tab 0.0751 @tab 0.178 @tab 0.213 @tab 0.047
+ at item venn @tab 0.0527 @tab 0.201 @tab 0.269 @tab 0.0406 @tab 0.148 @tab 0.233 @tab 0.027
+ at end multitable
diff --git a/texinfo/udav.1 b/texinfo/udav.1
new file mode 100644
index 0000000..5598f5c
--- /dev/null
+++ b/texinfo/udav.1
@@ -0,0 +1,20 @@
+.\" Process this file with
+.\" groff -man -Tascii udav.1
+.\"
+.TH UDAV 1 "MARCH 2012" MathGL "User Manuals"
+.SH NAME
+udav \- program for data visualization based on MathGL library
+.SH SYNOPSIS
+.B udav
+[scriptfile]
+.SH DESCRIPTION
+.B udav
+reads MGL scripts from
+.I scriptfile
+to produce plots of specified functions or data. The program will create a GUI window which show the script result and allow to edit the script itself.
+.SH AUTHOR
+mglview was written by Alexey Balakin, http://mathgl.sourceforge.net/
+.SH "SEE ALSO"
+.BR mglview (1),
+.BR mglconv (1),
+.BR mgl (5)
diff --git a/texinfo/udav/udav_anim.png b/texinfo/udav/udav_anim.png
new file mode 100644
index 0000000..0941539
Binary files /dev/null and b/texinfo/udav/udav_anim.png differ
diff --git a/texinfo/udav/udav_arg.png b/texinfo/udav/udav_arg.png
new file mode 100644
index 0000000..4dca6b8
Binary files /dev/null and b/texinfo/udav/udav_arg.png differ
diff --git a/texinfo/udav/udav_calc.png b/texinfo/udav/udav_calc.png
new file mode 100644
index 0000000..3ff37df
Binary files /dev/null and b/texinfo/udav/udav_calc.png differ
diff --git a/texinfo/udav/udav_cmd.png b/texinfo/udav/udav_cmd.png
new file mode 100644
index 0000000..16c1ec9
Binary files /dev/null and b/texinfo/udav/udav_cmd.png differ
diff --git a/texinfo/udav/udav_data.png b/texinfo/udav/udav_data.png
new file mode 100644
index 0000000..3b3383d
Binary files /dev/null and b/texinfo/udav/udav_data.png differ
diff --git a/texinfo/udav/udav_gen_set.png b/texinfo/udav/udav_gen_set.png
new file mode 100644
index 0000000..c633082
Binary files /dev/null and b/texinfo/udav/udav_gen_set.png differ
diff --git a/texinfo/udav/udav_help.png b/texinfo/udav/udav_help.png
new file mode 100644
index 0000000..b95c59a
Binary files /dev/null and b/texinfo/udav/udav_help.png differ
diff --git a/texinfo/udav/udav_inplot.png b/texinfo/udav/udav_inplot.png
new file mode 100644
index 0000000..66c0e10
Binary files /dev/null and b/texinfo/udav/udav_inplot.png differ
diff --git a/texinfo/udav/udav_light.png b/texinfo/udav/udav_light.png
new file mode 100644
index 0000000..40be014
Binary files /dev/null and b/texinfo/udav/udav_light.png differ
diff --git a/texinfo/udav/udav_main.png b/texinfo/udav/udav_main.png
new file mode 100644
index 0000000..8c5af02
Binary files /dev/null and b/texinfo/udav/udav_main.png differ
diff --git a/texinfo/udav/udav_mask.png b/texinfo/udav/udav_mask.png
new file mode 100644
index 0000000..80dcc35
Binary files /dev/null and b/texinfo/udav/udav_mask.png differ
diff --git a/texinfo/udav/udav_opt.png b/texinfo/udav/udav_opt.png
new file mode 100644
index 0000000..fe89ab9
Binary files /dev/null and b/texinfo/udav/udav_opt.png differ
diff --git a/texinfo/udav/udav_pen.png b/texinfo/udav/udav_pen.png
new file mode 100644
index 0000000..a387ce8
Binary files /dev/null and b/texinfo/udav/udav_pen.png differ
diff --git a/texinfo/udav/udav_prop.png b/texinfo/udav/udav_prop.png
new file mode 100644
index 0000000..fba154b
Binary files /dev/null and b/texinfo/udav/udav_prop.png differ
diff --git a/texinfo/udav/udav_sch.png b/texinfo/udav/udav_sch.png
new file mode 100644
index 0000000..9895a48
Binary files /dev/null and b/texinfo/udav/udav_sch.png differ
diff --git a/texinfo/udav/udav_txt.png b/texinfo/udav/udav_txt.png
new file mode 100644
index 0000000..09dee81
Binary files /dev/null and b/texinfo/udav/udav_txt.png differ
diff --git a/texinfo/udav/udav_var.png b/texinfo/udav/udav_var.png
new file mode 100644
index 0000000..25d03b6
Binary files /dev/null and b/texinfo/udav/udav_var.png differ
diff --git a/texinfo/udav_en.texi b/texinfo/udav_en.texi
new file mode 100644
index 0000000..74621d9
--- /dev/null
+++ b/texinfo/udav_en.texi
@@ -0,0 +1,146 @@
+ at chapter UDAV
+ at nav{}
+
+UDAV (Universal Data Array Visualizator) is cross-platform program for data arrays visualization based on MathGL library. It support wide spectrum of graphics, simple script language and visual data handling and editing. It has window interface for data viewing, changing and plotting. Also it can execute MGL scripts, setup and rotate graphics and so on. UDAV hot-keys can be found in the appendix @ref{Hot-keys for UDAV}.
+
+ at menu
+* UDAV overview::
+* UDAV dialogs::
+* UDAV hints::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node UDAV overview, UDAV dialogs, , UDAV
+ at section UDAV overview
+ at nav{}
+
+UDAV have main window divided by 2 parts in general case and optional bottom panel(s). Left side contain tabs for MGL script and data arrays. Right side contain tabs with graphics itself, with list of variables and with help on MGL. Bottom side may contain the panel with MGL messages and warnings, and the panel with calculator.
+
+ at ufig{udav_main,11, Main window}
+
+Main window is shown on the figure above. You can see the script (at left) with current line highlighted by light-yellow, and result of its execution at right. Each panel have its own set of toolbuttons.
+
+Editor toolbuttons allow: open and save script from/to file; undo and redo changes; cut, copy and paste selection; find/replace text; show dialogs for command arguments and for plot setup; show calculator at bottom.
+
+Graphics toolbuttons allow: enable/disable additional transparency and lighting; show grid of absolute coordinates; enable mouse rotation; restore image view; refresh graphics (execute the script); stop calculation; copy graphics into clipboard; add primitives (line, curve, box, rhombus, ellipse, mark, text) to the image; change view angles manually. Vertical toolbuttons allow: shift and zoom in/out of image as whole; show next and previous frame of animation, or start animation (if one  [...]
+
+Graphics panel support plot editing by mouse.
+ at itemize
+ at item
+Axis range can be changed by mouse wheel or by dragging image by middle mouse button. Right button show popup menu. Left button show the coordinates of mouse click. At this double click will highlight plot under mouse and jump to the corresponded string of the MGL script.
+ at item
+Pressing "mouse rotation" toolbutton will change mouse actions: dragging by left button will rotate plot, middle button will shift the plot as whole, right button will zoom in/out plot as whole and add perspective, mouse wheel will zoom in/out plot as whole.
+ at item
+Manual primitives can be added by pressing corresponding toolbutton. They can be shifted as whole at any time by mouse dragging. At this double click open dialog with its properties. If toolbutton "grid of absolute coordinates" is pressed then editing of active points for primitives is enabled.
+ at end itemize
+
+ at ufig{udav_help,11, Main window - help panel}
+
+Short command description and list of its arguments are shown at the status-bar, when you move cursor to the new line of code. You can press @key{F1} to see more detailed help on special panel.
+
+ at ufig{udav_data,11, Main window - data viewing}
+
+Also you can look the current list of variables, its dimensions and its size in the memory (right side of above figure). Toolbuttons allow: create new variable, edit variable, delete variable, preview variable plot and its properties, refresh list of variables. Pressing on any column will sort table according its contents. Double click on a variable will open panel with data cells of the variable, where you can view/edit each cell independently or apply a set of transformations.
+
+ at ufig{udav_calc,11, Main window - calculator and messages}
+
+Finally, pressing @key{F2} or @key{F4} you can show/hide windows with messages/warnings and with calculator. Double click on a warning in message window will jump to corresponding line in editor. Calculator allow you type expression by keyboard as well as by toolbuttons. It know about all current variables, so you can use them in formulas.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node UDAV dialogs, UDAV hints, UDAV overview, UDAV
+ at section UDAV dialogs
+ at nav{}
+
+There are a set of dialogs, which allow change/add a command, setup global plot properties, or setup UDAV itself.
+
+ at ufig{udav_cmd,8, New command dialog}
+
+One of most interesting dialog (hotkey @key{Meta-C} or @key{Win-C}) is dialog which help to enter new command or change arguments of existed one. It allows consequently select the category of command, command name in category and appropriate set of command arguments. At this right side show detailed command description. Required argument(s) are denoted by bold text. Strings are placed in apostrophes, like @code{'txt'}. Buttons below table allow to call dialogs for changing style of comma [...]
+
+ at ufig{udav_pen,5, Style dialog - pen style}
+ at ufig{udav_sch,5, Style dialog - color scheme}
+ at ufig{udav_txt,5, Style dialog - text style}
+ at ufig{udav_mask,5, Style dialog - manual mask}
+
+Dialog for changing style can be called independently, but usually is called from @emph{New command} dialog or by double click on primitive. It contain 3 tabs: one for pen style, one for color scheme, one for text style. You should select appropriate one. Resulting string of style and sample picture are shown at bottom of dialog. Usually it can be called from New command dialog.
+
+ at ufig{udav_var,3, Variable dialog}
+
+Dialog for entering variable allow to select variable or expression which can be used as argument of a command. Here you can select the variable name; range of indexes in each directions; operation which will be applied (like, summation, finding minimal/maximal values and so on). Usually it can be called from New command dialog.
+
+ at ufig{udav_opt,7.5, Dialog for options of a command}
+
+Dialog for command options allow to change @ref{Command options}. Usually it can be called from New command dialog.
+
+
+
+ at ufig{udav_inplot,8, New inplot dialog}
+
+Another interesting dialog, which help to select and properly setup a @ref{subplot}, @ref{inplot}, @ref{columnplot}, @ref{stickplot} and similar commands.
+
+
+ at ufig{udav_gen_set,9, Dialog for general properties}
+ at ufig{udav_light,9, Dialog for light properties}
+
+There is dialog for setting general plot properties, including tab for setting lighting properties. It can be called by called by hotkey @key{???} and put setup commands at the beginning of MGL script.
+
+ at ufig{udav_arg,3.2, Dialog for script parameters}
+
+Also you can set or change script parameters (@samp{$0} ... @samp{$9}, see @ref{MGL definition}).
+
+ at ufig{udav_prop,5, Dialog for UDAV settings}
+
+Finally, there is dialog for UDAV settings. It allow to change most of things in UDAV appearance and working, including colors of keywords and numbers, default font and image size, and so on (see figure above).
+
+There are also a set of dialogs for data handling, but they are too simple and clear. So, I will not put them here.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node UDAV hints, , UDAV dialogs, UDAV
+ at section UDAV hints
+ at nav{}
+
+ at itemize
+ at item
+You can shift axis range by pressing middle button and moving mouse. Also, you can zoom in/out axis range by using mouse wheel.
+ at item
+You can rotate/shift/zoom whole plot by mouse. Just press 'Rotate' toolbutton, click image and hold a mouse button: left button for rotation, right button for zoom/perspective, middle button for shift.
+ at item
+You may quickly draw the data from file. Just use: udav 'filename.dat' in command line.
+ at item
+You can copy the current image to clipboard by pressing @key{Ctrl-Shift-C}. Later you can paste it directly into yours document or presentation.
+ at item
+You can export image into a set of format (EPS, SVG, PNG, JPEG) by pressing right mouse button inside image and selecting 'Export as ...'.
+ at item
+You can setup colors for script highlighting in Property dialog. Just select menu item 'Settings/Properties'.
+ at item
+You can save the parameter of animation inside MGL script by using comment started from '##a ' or '##c ' for loops.
+ at item
+New drawing never clears things drawn already. For example, you can make a surface with contour lines by calling commands 'surf' and 'cont' one after another (in any order).
+ at item
+You can put several plots in the same image by help of commands 'subplot' or 'inplot'.
+ at item
+All indexes (of data arrays, subplots and so on) are always start from 0.
+ at item
+You can edit MGL file in any text editor. Also you can run it in console by help of commands: @code{mglconv}, @code{mglview}.
+ at item
+You can use command 'once on|off' for marking the block which should be executed only once. For example, this can be the block of large data reading/creating/handling. Press @key{F9} (or menu item 'Graphics/Reload') to re-execute this block.
+ at item
+You can use command 'stop' for terminating script parsing. It is useful if you don't want to execute a part of script.
+ at item
+You can type arbitrary expression as input argument for data or number. In last case (for numbers), the first value of data array is used.
+ at item
+There is powerful calculator with a lot of special functions. You can use buttons or keyboard to type the expression. Also you can use existed variables in the expression.
+ at item
+The calculator can help you to put complex expression in the script. Just type the expression (which may depend on coordinates x,y,z and so on) and put it into the script.
+ at item
+You can easily insert file or folder names, last fitted formula or numerical value of selection by using menu Edit|Insert.
+ at item
+The special dialog (Edit|Insert|New Command) help you select the command, fill its arguments and put it into the script.
+ at item
+You can put several plotting commands in the same line or in separate function, for highlighting all of them simultaneously.
+ at end itemize
+
+ at external{}
\ No newline at end of file
diff --git a/texinfo/udav_ru.texi b/texinfo/udav_ru.texi
new file mode 100644
index 0000000..74621d9
--- /dev/null
+++ b/texinfo/udav_ru.texi
@@ -0,0 +1,146 @@
+ at chapter UDAV
+ at nav{}
+
+UDAV (Universal Data Array Visualizator) is cross-platform program for data arrays visualization based on MathGL library. It support wide spectrum of graphics, simple script language and visual data handling and editing. It has window interface for data viewing, changing and plotting. Also it can execute MGL scripts, setup and rotate graphics and so on. UDAV hot-keys can be found in the appendix @ref{Hot-keys for UDAV}.
+
+ at menu
+* UDAV overview::
+* UDAV dialogs::
+* UDAV hints::
+ at end menu
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node UDAV overview, UDAV dialogs, , UDAV
+ at section UDAV overview
+ at nav{}
+
+UDAV have main window divided by 2 parts in general case and optional bottom panel(s). Left side contain tabs for MGL script and data arrays. Right side contain tabs with graphics itself, with list of variables and with help on MGL. Bottom side may contain the panel with MGL messages and warnings, and the panel with calculator.
+
+ at ufig{udav_main,11, Main window}
+
+Main window is shown on the figure above. You can see the script (at left) with current line highlighted by light-yellow, and result of its execution at right. Each panel have its own set of toolbuttons.
+
+Editor toolbuttons allow: open and save script from/to file; undo and redo changes; cut, copy and paste selection; find/replace text; show dialogs for command arguments and for plot setup; show calculator at bottom.
+
+Graphics toolbuttons allow: enable/disable additional transparency and lighting; show grid of absolute coordinates; enable mouse rotation; restore image view; refresh graphics (execute the script); stop calculation; copy graphics into clipboard; add primitives (line, curve, box, rhombus, ellipse, mark, text) to the image; change view angles manually. Vertical toolbuttons allow: shift and zoom in/out of image as whole; show next and previous frame of animation, or start animation (if one  [...]
+
+Graphics panel support plot editing by mouse.
+ at itemize
+ at item
+Axis range can be changed by mouse wheel or by dragging image by middle mouse button. Right button show popup menu. Left button show the coordinates of mouse click. At this double click will highlight plot under mouse and jump to the corresponded string of the MGL script.
+ at item
+Pressing "mouse rotation" toolbutton will change mouse actions: dragging by left button will rotate plot, middle button will shift the plot as whole, right button will zoom in/out plot as whole and add perspective, mouse wheel will zoom in/out plot as whole.
+ at item
+Manual primitives can be added by pressing corresponding toolbutton. They can be shifted as whole at any time by mouse dragging. At this double click open dialog with its properties. If toolbutton "grid of absolute coordinates" is pressed then editing of active points for primitives is enabled.
+ at end itemize
+
+ at ufig{udav_help,11, Main window - help panel}
+
+Short command description and list of its arguments are shown at the status-bar, when you move cursor to the new line of code. You can press @key{F1} to see more detailed help on special panel.
+
+ at ufig{udav_data,11, Main window - data viewing}
+
+Also you can look the current list of variables, its dimensions and its size in the memory (right side of above figure). Toolbuttons allow: create new variable, edit variable, delete variable, preview variable plot and its properties, refresh list of variables. Pressing on any column will sort table according its contents. Double click on a variable will open panel with data cells of the variable, where you can view/edit each cell independently or apply a set of transformations.
+
+ at ufig{udav_calc,11, Main window - calculator and messages}
+
+Finally, pressing @key{F2} or @key{F4} you can show/hide windows with messages/warnings and with calculator. Double click on a warning in message window will jump to corresponding line in editor. Calculator allow you type expression by keyboard as well as by toolbuttons. It know about all current variables, so you can use them in formulas.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node UDAV dialogs, UDAV hints, UDAV overview, UDAV
+ at section UDAV dialogs
+ at nav{}
+
+There are a set of dialogs, which allow change/add a command, setup global plot properties, or setup UDAV itself.
+
+ at ufig{udav_cmd,8, New command dialog}
+
+One of most interesting dialog (hotkey @key{Meta-C} or @key{Win-C}) is dialog which help to enter new command or change arguments of existed one. It allows consequently select the category of command, command name in category and appropriate set of command arguments. At this right side show detailed command description. Required argument(s) are denoted by bold text. Strings are placed in apostrophes, like @code{'txt'}. Buttons below table allow to call dialogs for changing style of comma [...]
+
+ at ufig{udav_pen,5, Style dialog - pen style}
+ at ufig{udav_sch,5, Style dialog - color scheme}
+ at ufig{udav_txt,5, Style dialog - text style}
+ at ufig{udav_mask,5, Style dialog - manual mask}
+
+Dialog for changing style can be called independently, but usually is called from @emph{New command} dialog or by double click on primitive. It contain 3 tabs: one for pen style, one for color scheme, one for text style. You should select appropriate one. Resulting string of style and sample picture are shown at bottom of dialog. Usually it can be called from New command dialog.
+
+ at ufig{udav_var,3, Variable dialog}
+
+Dialog for entering variable allow to select variable or expression which can be used as argument of a command. Here you can select the variable name; range of indexes in each directions; operation which will be applied (like, summation, finding minimal/maximal values and so on). Usually it can be called from New command dialog.
+
+ at ufig{udav_opt,7.5, Dialog for options of a command}
+
+Dialog for command options allow to change @ref{Command options}. Usually it can be called from New command dialog.
+
+
+
+ at ufig{udav_inplot,8, New inplot dialog}
+
+Another interesting dialog, which help to select and properly setup a @ref{subplot}, @ref{inplot}, @ref{columnplot}, @ref{stickplot} and similar commands.
+
+
+ at ufig{udav_gen_set,9, Dialog for general properties}
+ at ufig{udav_light,9, Dialog for light properties}
+
+There is dialog for setting general plot properties, including tab for setting lighting properties. It can be called by called by hotkey @key{???} and put setup commands at the beginning of MGL script.
+
+ at ufig{udav_arg,3.2, Dialog for script parameters}
+
+Also you can set or change script parameters (@samp{$0} ... @samp{$9}, see @ref{MGL definition}).
+
+ at ufig{udav_prop,5, Dialog for UDAV settings}
+
+Finally, there is dialog for UDAV settings. It allow to change most of things in UDAV appearance and working, including colors of keywords and numbers, default font and image size, and so on (see figure above).
+
+There are also a set of dialogs for data handling, but they are too simple and clear. So, I will not put them here.
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node UDAV hints, , UDAV dialogs, UDAV
+ at section UDAV hints
+ at nav{}
+
+ at itemize
+ at item
+You can shift axis range by pressing middle button and moving mouse. Also, you can zoom in/out axis range by using mouse wheel.
+ at item
+You can rotate/shift/zoom whole plot by mouse. Just press 'Rotate' toolbutton, click image and hold a mouse button: left button for rotation, right button for zoom/perspective, middle button for shift.
+ at item
+You may quickly draw the data from file. Just use: udav 'filename.dat' in command line.
+ at item
+You can copy the current image to clipboard by pressing @key{Ctrl-Shift-C}. Later you can paste it directly into yours document or presentation.
+ at item
+You can export image into a set of format (EPS, SVG, PNG, JPEG) by pressing right mouse button inside image and selecting 'Export as ...'.
+ at item
+You can setup colors for script highlighting in Property dialog. Just select menu item 'Settings/Properties'.
+ at item
+You can save the parameter of animation inside MGL script by using comment started from '##a ' or '##c ' for loops.
+ at item
+New drawing never clears things drawn already. For example, you can make a surface with contour lines by calling commands 'surf' and 'cont' one after another (in any order).
+ at item
+You can put several plots in the same image by help of commands 'subplot' or 'inplot'.
+ at item
+All indexes (of data arrays, subplots and so on) are always start from 0.
+ at item
+You can edit MGL file in any text editor. Also you can run it in console by help of commands: @code{mglconv}, @code{mglview}.
+ at item
+You can use command 'once on|off' for marking the block which should be executed only once. For example, this can be the block of large data reading/creating/handling. Press @key{F9} (or menu item 'Graphics/Reload') to re-execute this block.
+ at item
+You can use command 'stop' for terminating script parsing. It is useful if you don't want to execute a part of script.
+ at item
+You can type arbitrary expression as input argument for data or number. In last case (for numbers), the first value of data array is used.
+ at item
+There is powerful calculator with a lot of special functions. You can use buttons or keyboard to type the expression. Also you can use existed variables in the expression.
+ at item
+The calculator can help you to put complex expression in the script. Just type the expression (which may depend on coordinates x,y,z and so on) and put it into the script.
+ at item
+You can easily insert file or folder names, last fitted formula or numerical value of selection by using menu Edit|Insert.
+ at item
+The special dialog (Edit|Insert|New Command) help you select the command, fill its arguments and put it into the script.
+ at item
+You can put several plotting commands in the same line or in separate function, for highlighting all of them simultaneously.
+ at end itemize
+
+ at external{}
\ No newline at end of file
diff --git a/texinfo/version.texi.in b/texinfo/version.texi.in
new file mode 100644
index 0000000..8ac338c
--- /dev/null
+++ b/texinfo/version.texi.in
@@ -0,0 +1,4 @@
+ at set VERSION ${MathGL_VERSION_MAJOR}.${MathGL_VERSION_MINOR}
+ at set MINVER 
+ at c @set MINVER .1
+ at set NIGHT ${MGL_NIGHT}
diff --git a/texinfo/version_hist.txt b/texinfo/version_hist.txt
new file mode 100644
index 0000000..5a71907
--- /dev/null
+++ b/texinfo/version_hist.txt
@@ -0,0 +1,53 @@
+2.3.5.1 Released 30 May 2015
+2.3.5 Released 16 May 2015
+2.3.4 Released 11 February 2015
+2.3.3 Released 01 June 2015
+2.3.2 Released 2 February 2015
+2.3.1 Released 21 October 2014
+2.3 Released 7 August 2014
+2.2.2.1 Released 19 March 2014
+2.2.2 Released 10 March 2014
+2.2.1 Released 22 January 2014
+2.2 Released 11 November 2013
+2.1.3.1 Released 8 May 2013
+2.1.3 Released 2 May 2013
+2.1.2	Released 28 January 2013
+2.1.1	Released 24 December 2012
+2.1 	Released 13 December 2012
+2.0.3	Released 27 July 2012
+2.0.2	Released 24 May 2012
+2.0.1	Released 23 May 2012
+2.0 	Released 12 April 2012
+2.0.b	Released 23 August 2011
+
+1.11.3	Released 23 November 2012
+1.11.2	Released 30 May 2011
+1.11.1	Released 28 March 2011
+1.11	Released 8 November 2010
+1.10.2.1 Released 27 March 2010
+1.10.2	Released 22 March 2010
+1.10.1	Released 8 March 2010
+1.10	Released 28 December 2009
+1.9 	Released 8 July 2009
+1.8.1	Released 4 March 2009
+1.8 	Released 27 November 2008
+1.7 	Released 5 June 2008
+1.6.2	Released 5 April 2008
+1.6.1	Released 2 April 2008
+1.6 	Released 17 March 2008
+1.5 	Released 11 January 2008
+1.4.3.1	Released 24 December 2008
+1.4.3	Released 18 December 2008
+1.4.2	Released 27 November 2007
+1.4.1	Released 14 November 2007
+1.4 	Released 30 October 2007
+1.3 	Released 15 October 2007
+1.2.2	Released 26 September 2007
+1.2.1	Released 14 September 2007
+1.2 	Released 10 September 2007
+1.1 	Released 23 May 2007
+1.0 	Released 2 April 2007
+
+0.9		Last beta version of the MathGL library. Released 2 March 2007
+0.8.1	Released 19 February 2007
+0.8.0	First public release (24 January 2007)
diff --git a/texinfo/web_en.texi b/texinfo/web_en.texi
new file mode 100644
index 0000000..7b5330c
--- /dev/null
+++ b/texinfo/web_en.texi
@@ -0,0 +1,412 @@
+ at c ------------------------------------------------------------------
+ at chapter Website
+ at nav{}
+
+ at menu
+* Main::
+* News::
+* Features::
+* Pictures::
+ at c * MGL scripts::
+* Download::
+* Other projects::
+ at end menu
+
+ at external{}
+
+ at node Main, News, , Website
+ at section MathGL is ...
+ at nav{}
+
+ at ifhtml
+ at html
+<a href="Adding-fog.html"><img border="0" align="right" hspace="30" vspace="20" alt="Surface in fog" src="../small/fog-sm.png"></a>
+ at end html
+ at end ifhtml
+ at itemize @bullet
+ at item
+a library for making high-quality scientific graphics under Linux and Windows;
+ at item
+a library for the fast data plotting and data processing of large data arrays;
+ at item
+a library for working in window and console modes and for easy embedding into other programs;
+ at item
+a library with large and growing set of graphics.
+ at end itemize
+
+Now MathGL has more than 35000 lines of code, more than 55 general types of graphics for 1d, 2d and 3d data arrays, including special ones for chemical and statistical graphics. It can export graphics to raster and vector (EPS or SVG) formats. It has Qt, FLTK, OpenGL interfaces and can be used even from console programs. It has functions for data processing and script MGL language for simplification of data plotting. Also it has several types of transparency and smoothed lightning, vecto [...]
+
+There is a @uref{http://sourceforge.net/forum/?group_id=152187, forum} where you can ask a question or suggest an improvement. However the @uref{http://groups.google.com/group/mathgl, MathGL group} is preferable for quicker answer.
+
+For subscribing to @uref{http://groups.google.com/group/mathgl, MathGL group} you can use form below
+ at ifhtml
+ at html
+<form action="http://groups.google.com/group/mathgl/boxsubscribe">
+Email: <input type=text name=email> <input type=submit name="sub" value="Subscribe">
+</form>
+ at end html
+ at end ifhtml
+
+ at strong{About LGPL and GPL licenses.}
+Generally, MathGL is GPL library. However, you can use LGPL license for MathGL core and widgets if you don't use SWIG-based interfaces and disable GSL features. This can be done by using @code{lgpl} option at build time. According this, I've added the LGPL win32 binaries into @ref{Download} page.
+
+ at strong{Latest news}
+ at itemize
+
+ at item @emph{17 May 2017.}
+New version (v.2.4) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are @code{mgllab} executable, string manipulation in MGL, new functions, plot types and styles, translation to Russian using @code{gettext} and bugfixes, which denoted @ref{News, here}.
+ at end itemize
+
+There is detailed @ref{News, news list}. Sourceforge project page @uref{http://sourceforge.net/projects/mathgl/, here}.
+
+ at ifhtml
+ at html
+<a href="http://www.datadvance.net"><img border="0" align="right" hspace="10" alt="DATADVANCE" src="../datadvance.png"></a>
+ at end html
+ at end ifhtml
+Javascript interface was developed with support of @url{http://www.datadvance.net, DATADVANCE} company.
+
+ at external{}
+
+ at node News, Features, Main, Website
+ at section News
+ at nav{}
+
+ at itemize
+
+ at item @strong{17 May 2017.}
+New version (v.2.4) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are @code{mgllab} executable, string manipulation in MGL, new functions, plot types and styles, translation to Russian using @code{gettext} and bugfixes:
+ at itemize @bullet
+
+ at item Add @code{mgllab} executable, which is FLTK based version of @code{UDAV}. So, most things @code{mgllab} do faster.
+ at item Add string manipulation in MGL language:
+ at itemize @bullet
+	@item 'str'[n] -- get string of only n-th symbol;
+	@item 'str'+v -- add value v to the last character of the string;
+	@item 'str',val or 'str',!val -- append numeric value to the string (as before).
+ at end itemize
+ at item Add time value to MGL language in format: @samp{hh-mm-ss_DD.MM.YYYY} or @samp{hh-mm-ss} or @samp{DD.MM.YYYY}.
+ at item Add @ref{iris} plot to show cross-dependencies of several data arrays.
+ at item Add @ref{flame2d} to draw flame fractals.
+ at item Add @ref{bbox} to set bounding box for 2D output.
+ at item Add @ref{section} to get part of data between specified values.
+ at item Add @ref{detect} to found curves along data maximums.
+ at item Add @ref{dilate} to extend the region of 1-th value.
+ at item Add @ref{erode} to narrow the region of 1-th value.
+ at item Add @ref{apde} to solve PDE equation in inhomogeneous nonlinear media with spatial dispersion.
+ at item Add @ref{symbol} to draw the glyphs defined by @ref{addsymbol}.
+ at item Add @ref{addsymbol} to declare user-defined symbol (or glyph), which can be used as markers for plot (with style '&') or drawn itself by @ref{symbol} command.
+ at item Add @ref{openhdf} to open all data arrays from HDF file.
+ at item Extend @ref{crop} to cut to optimal size for FFT (i.e. to closest of 2^n*3^m*5^l).
+ at item Add function mgl_data_max_first() and data suffixes .m[xyz][fl] to find first/last maximum along direction (see @ref{Data information}).
+ at item Add function mgl_datac_diff_par() to parametric derivative of complex data (see @ref{diff}).
+ at item Add style @samp{F} for @ref{bars} and @ref{barh} to set fixed bar widths.
+ at item Add style @samp{a} for @ref{plot}, @ref{tens}, @ref{area} and @ref{region} to accurate drawing of data, which partially lie out of axis range.
+ at item Add style @samp{#} for @ref{region} to draw wired plot.
+ at item Add possibility of manual shift in @ref{multiplot}.
+ at item Add parsing arguments of options for MGL commands.
+ at item MGL command @ref{correl} now can perform 2d and 3d correlations.
+ at item Option @ref{meshnum} now change the number of drawn markers for @ref{plot}, @ref{tens}, @ref{step}, @ref{mark} and @ref{textmark}.
+ at item Function @ref{step} handle data with x.nx>y.nx similarly to @ref{bars}.
+ at item Extend @ref{tile} and @ref{tiles} by adding manual coloring and face orientation.
+ at item Add variant of MGL command @ref{copy} to copy data with "incorrect" names.
+ at item Improve tick labels drawing.
+ at item Improve time-ticks (add weeks) and add subticks to its.
+ at item Improve @ref{fplot} to handle several singularities.
+ at item Add LaTeX command \dfrac@{@}@{@}. This is full-sized version of \frac@{@}@{@}. Unfortunately, there is no support of nesting. Contrary, \frac allow nesting.
+ at item Add mglODEc() -- ODE solver for complex variables (see @ref{ode}).
+ at item Add cmplx(a,b)=a+i*b to the list of known functions in formula parsing
+ at item Update CMake find_package to find MathGL.
+ at item Increase line width for wired text.
+ at item Update documentation: add description of new commands, add hint @ref{Mixing bitmap and vector output}.
+ at item Add translation to Russian for most of labels and messages.
+ at item Name @code{all} are reserved in MGL scripts now as synonym of -1.
+
+ at item INCOMPATIBLE: Replace libmgl-qt by libmgl-qt4 and libmgl-qt5 for resolving conflicts of simultaneously installed both Qt4 and Qt5.
+ at item Minor bugfixes.
+
+ at end itemize
+
+ at item @strong{20 June 2016.} Version 2.3.5.1 was released.
+ at item @strong{16 May 2016.} Version 2.3.5 was released.
+ at item @strong{13 February 2016.} Version 2.3.4 was released.
+ at item @strong{1 June 2015.} Version 2.3.3 was released.
+ at item @strong{2 February 2015.} Version 2.3.2 was released.
+ at item @strong{21 October 2014.} Version 2.3.1 was released.
+ at item @strong{7 August 2014.} Version 2.3 was released.
+ at item @strong{19 March 2014.} Version 2.2.2.1 was released.
+ at item @strong{10 March 2014.} Version 2.2.2 was released.
+ at item @strong{22 January 2014.} Version 2.2.1 was released.
+ at item @strong{11 November 2013.} Version 2.2 was released.
+ at item @strong{8 May 2013.} Version 2.1.3.1 was released.
+ at item @strong{2 May 2013.} Version 2.1.3 was released.
+ at item @strong{28 January 2013.} Version 2.1.2 was released.
+ at item @strong{24 December 2012.} Version 2.1.1 was released.
+ at item @strong{13 December 2012.} Version 2.1 was released.
+ at item @strong{23 August 2011.} Version 2.0.beta was released.
+ at item @strong{30 May 2011.} Version 1.11.2 was released.
+ at item @strong{8 November 2010.} Version 1.11 was released.
+ at item @strong{28 December 2009.} Version 1.10 was released.
+ at item @strong{8 July 2009.} Version 1.9 was released.
+ at item @strong{27 November 2008.} Version 1.8 was released.
+ at item @strong{5 June 2008.} Version 1.7 was released.
+ at item @strong{17 March 2008.} Version 1.6 was released.
+ at item @strong{11 January 2008.} Version 1.5 was released.
+ at item @strong{30 October 2007.} Version 1.4 was released.
+ at item @strong{15 October 2007.} Version 1.3 was released.
+ at item @strong{10 September 2007.} Version 1.2 was released.
+ at item @strong{23 May 2007.} Version 1.1 was released.
+ at item @strong{2 April 2007.} Version 1.0 was released.
+ at item @strong{24 January 2007.} First public release (v.0.8).
+ at end itemize
+
+ at external{}
+
+
+ at node Features, Pictures, News, Website
+ at section Features
+ at nav{}
+
+MathGL can plot a wide range of graphics. It includes:
+ at itemize @bullet
+ at item
+one-dimensional: Plot, Area, Bars, Step, Stem, Torus, Chart, Error, Tube, Mark, (@ref{1D plotting});
+
+ at item
+two-dimensional plots: Mesh, Surf, Dens, Cont, ContF, Boxs, Axial, Fall, Belt, Tile, including surfaces transparent (SurfA) or colored (SurfC) by another data (@ref{2D plotting});
+
+ at item
+three-dimensional plots: Surf3, Dens3, Cont3, ContF3, Cloud-like, including isosurfaces transparent (Surf3A) or colored (Surf3C) by another data (@ref{3D plotting});
+
+ at item
+vector fields plots: vector fields Vect, Vect3 and Traj, flow threads Flow, flow pipes Pipe, mapping chart Map, and so on (@ref{Vector fields});
+
+ at item
+and so on. See also @ref{Extra samples}.
+ at end itemize
+
+In fact, I created the functions for drawing of all the types of scientific plots that I know. The list of plots is growing; if you need some special type of a plot then please email me @email{mathgl.abalakin@@gmail.com, e-mail} and it will appear in the new version.
+
+I tried to make plots as nice looking as possible: e.g., a surface can be transparent and highlighted by several (up to 10) light sources. Most of the drawing functions have 2 variants: simple one for the fast plotting of data, complex one for specifying of the exact position of the plot (including parametric representation). Resulting image can be saved in bitmap PNG, JPEG, TGA, BMP format, or in vector EPS, SVG or TeX format, or in 3D formats OBJ, OFF, STL or in PRC format.
+
+All texts are drawn by vector fonts, which allows for high scalability and portability. Texts may contain commands for: some of the TeX-like symbols, changing index (upper or lower indexes) and the style of font inside the text string. Texts of ticks are rotated with axis rotation. It is possible to create a legend of plot and put text in an arbitrary position on the plot. Arbitrary text encoding (by the help of function @code{setlocale()}) and UTF-16 encoding are supported.
+
+Special class mglData is used for data encapsulation. In addition to a safe creation and deletion of data arrays it includes functions for data processing (smoothing, differentiating, integrating, interpolating and so on) and reading of data files with automatic size determination. Class mglData can handle arrays with up to three dimensions (arrays which depend on up to 3 independent indexes @math{a_@{ijk@}}). Using an array with higher number of dimensions is not meaningful, because I d [...]
+
+There is fast evaluation of a textual mathematical expression. It is based on string precompilation to tree-like code at the creation of class instance. At evaluation stage code performs only fast tree-walk and returns the value of the expression. In addition to changing data values, textual formulas are also used for drawing in @emph{arbitrary} curvilinear coordinates. A set of such curvilinear coordinates is limited only by user's imagination rather than a fixed list like: polar, parab [...]
+
+ at external{}
+
+ at node Pictures, Download, Features, Website
+ at section Pictures
+ at nav{}
+
+There are samples for @ref{1D data plotting, 1D arrays}, @ref{2D data plotting, 2D arrays}, @ref{3D data plotting, 3D arrays}, @ref{Vector fields plotting} and some @ref{Extra samples}.
+
+ at anchor{1D data plotting}
+ at subheading Examples of graphics for 1d arrays
+
+ at sfig{plot, Plot sample}
+ at sfig{radar, Radar sample}
+ at sfig{step, Step sample}
+ at sfig{tens, Tens sample}
+
+ at sfig{area, Area sample}
+ at sfig{region,Region sample}
+ at sfig{stem, Stem sample}
+ at sfig{torus,Torus sample}
+
+ at sfig{bars, Bars sample}
+ at sfig{barh, Barh sample}
+ at sfig{cones,Cones sample}
+ at sfig{chart,Chart sample}
+
+ at sfig{boxplot,BoxPlot sample}
+ at sfig{candle, Candle sample}
+ at sfig{tube, Tube sample}
+ at sfig{tape, Tape sample}
+
+ at sfig{error,Error sample}
+ at sfig{mark, Mark sample}
+ at sfig{textmark, TextMark sample}
+ at sfig{label,Label sample}
+
+ at anchor{2D data plotting}
+ at subheading Examples of graphics for 2d arrays
+
+ at sfig{surf, Surf sample}
+ at sfig{surfc,SurfC sample}
+ at sfig{surfa,SurfA sample}
+ at sfig{mesh, Mesh sample}
+
+ at sfig{fall, Fall sample}
+ at sfig{belt, Belt sample}
+ at sfig{boxs, Boxs sample}
+ at sfig{axial,Axial sample}
+
+ at sfig{dens, Dens sample}
+ at sfig{tile, Tile sample}
+ at sfig{tiles,TileS sample}
+ at sfig{grad, Grad sample}
+
+ at sfig{cont, Cont sample}
+ at sfig{contf,ContF sample}
+ at sfig{contd,ContD sample}
+ at sfig{contv,ContV sample}
+
+ at anchor{3D data plotting}
+ at subheading Examples of graphics for 3d arrays
+
+ at sfig{surf3, Surf3 sample}
+ at sfig{surf3c,Surf3C sample}
+ at sfig{surf3a,Surf3A sample}
+ at sfig{cloud, Cloud sample}
+
+ at sfig{densa, Dens3 sample}
+ at sfig{conta, Cont3 sample}
+ at sfig{contfa,ContF3 sample}
+ at sfig{dots,  Dots sample}
+
+ at sfig{dens_xyz, Dens projection sample}
+ at sfig{cont_xyz, Cont projection sample}
+ at sfig{contf_xyz,ContF projection sample}
+ at sfig{triplot, TriPlot and QuadPlot}
+
+ at anchor{Vector fields plotting}
+ at subheading Examples of graphics for vector fields
+
+ at sfig{vect, Vect sample}
+ at sfig{vecta,Vect3 sample}
+ at sfig{flow, Flow sample}
+ at sfig{pipe, Pipe sample}
+
+ at sfig{traj, Traj sample}
+ at sfig{dew, Dew sample}
+
+ at anchor{Extra samples}
+ at subheading Examples of additional features
+
+ at sfig{inplot, Subplots}
+ at sfig{axis, Axis and ticks}
+ at sfig{ticks, Axis and ticks}
+ at sfig{loglog, Axis and ticks}
+
+ at sfig{curvcoor, Curvilinear coordinates}
+ at sfig{colorbar, Colorbars}
+ at sfig{box, Bounding box}
+ at sfig{ternary, Ternary axis}
+
+ at sfig{text, Text features}
+ at sfig{legend, Legend sample}
+ at sfig{cut, Cutting sample}
+ at sfig{alpha, Transparency and lighting}
+
+ at sfig{type0, Types of transparency}
+ at sfig{type1, Types of transparency}
+ at sfig{type2, Types of transparency}
+ at sfig{fog, Adding fog}
+
+ at sfig{combined, ``Compound'' graphics}
+ at sfig{several_light, Lighting sample}
+ at sfig{stereo, Stereo image}
+ at sfig{primitives, Using primitives}
+
+ at sfig{stfa, STFA sample}
+ at sfig{dat_diff, Change data}
+ at sfig{dat_extra, Change data}
+ at sfig{map, Mapping visualization}
+
+ at sfig{hist, Making histogram}
+ at sfig{fit, Nonlinear fitting hints}
+ at sfig{pde, PDE solving hints}
+ at sfig{parser, Using MGL parser}
+
+ at external{}
+
+ at node Download, Other projects, Pictures, Website
+ at section Download
+ at nav{}
+
+ at strong{Stable version (v. at value{VERSION})}
+
+You may download current version of MathGL for following configurations:
+ at itemize @bullet
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mathgl-@value{VERSION}@value{MINVER}.tar.gz, Source} file with cmake build system.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mathgl-@value{VERSION}@value{MINVER}-mingw.win32.7z,GPL} or @uref{http://downloads.sourceforge.net/mathgl/mathgl-@value{VERSION}@value{MINVER}.LGPL-mingw.win32.7z,LGPL} binaries for MinGW, 32-bit build for Pentium IV.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mathgl-@value{VERSION}@value{MINVER}-mingw.win64.7z,GPL} or @uref{http://downloads.sourceforge.net/mathgl/mathgl-@value{VERSION}@value{MINVER}.LGPL-mingw.win64.7z,LGPL} binaries for MinGW, 64-bit build.
+ at item
+MathGL utilities with all required DLL files for @uref{http://downloads.sourceforge.net/mathgl/mgl_scripts-@value{VERSION}.win32.7z,32-bit} and @uref{http://downloads.sourceforge.net/mathgl/mgl_scripts-@value{VERSION}.win32.7z,64-bit} versions of MS Windows.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mathgl-@value{VERSION}@value{MINVER}.eng.pdf,PDF} documentation in English.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mathgl-doc-html-@value{VERSION}@value{MINVER}.7z, Archive} with HTML documentation and figures.
+ at c @item
+ at c @uref{http://downloads.sourceforge.net/mathgl/mathgl_slides-1.9.pdf,PDF} slideshow of main features
+ at end itemize
+
+ at strong{Font files}
+
+There are a set of @uref{http://sourceforge.net/project/showfiles.php?group_id=152187&package_id=267177,font files} for MathGL with following typefaces. Note, that the set of glyphs can be less than in default font. As result not all TeX symbols can be displayed.
+ at itemize @bullet
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/STIX_font.tgz,STIX} font -- default font for MathGL.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/adventor_font.tgz,Adventor font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} sansserif font based on the URW Gothic L family (like Avant Garde Gothic).
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/bonum_font.tgz,Bonum font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} serif font based on the URW Bookman L family.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/chorus_font.tgz,Chorus font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} font based on the URW Chancery L Medium Italic.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/cursor_font.tgz,Cursor font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} monospaced serif font based on the URW Nimbus Mono L (like Courier).
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/heros_font.tgz,Heros font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} sansserif font based on the URW Nimbus Sans L (like Helvetica).
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/heroscn_font.tgz,HerosCN font} -- the "compressed" version of previous one.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/pagella_font.tgz,Pagella font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} serif font based on the URW Palladio L (like Palatino).
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/schola_font.tgz,Schola font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} serif fonts is based on the URW Century Schoolbook L.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/termes_font.tgz,Termes font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} serif fonts is based on the Nimbus Roman No9 L (like Times).
+ at end itemize
+
+ at external{}
+
+ at node Other projects, , Download, Website
+ at section Other projects
+ at nav{}
+
+Except scientific (non public) projects I also have some general interest projects:
+ at itemize @bullet
+ at item
+ at uref{http://sourceforge.net/projects/pocketmk/, PocketMK} is small program for PocketPC which simulate famous Russian calculators MK-61 and slightly extend it.
+ at item
+ at uref{http://udav.sourceforge.net/,UDAV} is front-end for MGL scripts. It has windows interface for data viewing, changing and plotting. Also it can execute MGL scripts, setup and rotating graphics and so on.
+ at end itemize
+
+Also I recommend to look at:
+ at itemize @bullet
+ at item
+ at uref{http://englab.bugfest.net/,EngLab} is a cross-compile mathematical platform with a C like syntax intended to be used both by engineers and users with small programming knowledge. It is extremely scalable and allows users and the community to easily compile their own functions as shared objects.
+ at item
+ at uref{http://threedepict.sourceforge.net/,3Depict} is software for analysis of scientific datasets commonly encountered in atom probe tomography. You can manipulate, interact with and analyse point based datasets.
+ at item
+ at uref{http://www.sourceforge.net/projects/graphplot/,Graphplot} is function plotter based on MathGL.
+ at item
+ at uref{http://www.sourceforge.net/projects/graphplot/,OscillViewer} is oscilloscope monitoring program. Working with L-Card 14-140 AD-Convertor. Based on Qt and MathGL libraries.
+ at end itemize
+
+Finally, few links to free software and libraries:
+ at itemize @bullet
+ at item
+ at uref{http://www.thefreecountry.com/,thefreecountry.com} have a lot of Free Programmers', Webmasters' and Security Resources
+ at item
+ at uref{http://gnuwin32.sourceforge.net/,GnuWin} provides ports of tools with a GNU or similar open source license, to modern MS-Windows.
+ at item
+ at uref{http://loll.sourceforge.net/,LLoL} is project collecting, organising, classifying, and maintaining important URLs about Linux and the Open Source movement for all levels of Linux users. The LoLL project now has 4000+ links which are updated usually on a daily basis.
+ at end itemize
+
+ at external{}
diff --git a/texinfo/web_fr.texi b/texinfo/web_fr.texi
new file mode 100644
index 0000000..a0829e7
--- /dev/null
+++ b/texinfo/web_fr.texi
@@ -0,0 +1,614 @@
+\input texinfo
+ at setfilename mgl_web_en.info
+ at include version.texi
+ at settitle MathGL @value{VERSION}
+ at syncodeindex pg cp
+ at comment %**end of header
+
+ at copying
+This website demonstrates the Mathematical Graphic Library (MathGL) version @value{VERSION}, a collection of classes and routines for scientific plotting. Please report any errors in this manual to @email{mathgl.abalakin@@gmail.org}.
+
+ at include copyright.texi
+ at end copying
+
+ at titlepage
+ at title MathGL website
+ at subtitle for version @value{VERSION}
+ at author A.A. Balakin (@uref{http://mathgl.sourceforge.net/})
+ at page
+ at vskip 0pt plus 1filll
+ at insertcopying
+ at end titlepage
+
+ at contents
+
+ at ifnottex
+ at node Top
+ at top MathGL
+
+This website demonstrates the Mathematical Graphic Library (MathGL), a collection of classes and routines for scientific plotting. It corresponds to release @value{VERSION} of the library. Please report any errors in this manual to @email{mathgl.abalakin@@gmail.org}. More information about MathGL can be found at the project homepage, @uref{http://mathgl.sourceforge.net/}.
+
+ at include copyright.texi
+
+ at end ifnottex
+
+ at menu
+* Main::
+* News::
+* Features::
+* Pictures::
+* MGL scripts::
+* Download::
+* Other projects::
+ at end menu
+
+ at ifhtml
+ at macro external {}
+ at comment  @html
+ at comment  <script type="text/javascript"><!--
+ at comment  google_ad_client = "ca-pub-1128070552722622";
+ at comment  /* 728x90, создано 23.12.09 */
+ at comment  google_ad_slot = "9958083480";
+ at comment  google_ad_width = 728;
+ at comment  google_ad_height = 90;
+ at comment  //-->
+ at comment  </script>
+ at comment  <script type="text/javascript"
+ at comment  src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
+ at comment  </script>
+ at comment  <br/>
+ at html
+<!--LiveInternet counter--><script type="text/javascript"><!--
+document.write("<a href='http://www.liveinternet.ru/click' "+
+"target=_blank><img src='http://counter.yadro.ru/hit?t12.2;r"+
+escape(document.referrer)+((typeof(screen)=="undefined")?"":
+";s"+screen.width+"*"+screen.height+"*"+(screen.colorDepth?
+screen.colorDepth:screen.pixelDepth))+";u"+escape(document.URL)+
+";"+Math.random()+
+"' alt='' title='LiveInternet: number of views during 24"+
+" hours, number of visitors during 24 hours and during today' "+
+"border=0 width=88 height=31><\/a>")//--></script><!--/LiveInternet-->
+
+<a target=_blank href="http://sourceforge.net"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=152187&type=2" alt="SourceForge.net Logo" border="0" height="37" width="125"></a>
+
+<a target=_blank href="http://www.thefreecountry.com/"> <img src="http://www.thefreecountry.com/images/tfc88x31green.gif" alt="thefreecountry.com: Free Programmers' Resources, Free Webmasters' Resources, Free Security Resources, Free Software" border="0" height="31" width="88"></a>
+
+<a target=_blank href="http://sourceforge.net/donate/index.php?group_id=152187"><img src="http://images.sourceforge.net/images/project-support.jpg" width="88" height="32" border="0" alt="Support This Project" /> </a>
+ at end html
+ at end macro
+
+ at macro fig {plot,text}
+ at uref{../\text\, @image{../small/\plot\-sm,3cm, , , .png}}
+ at end macro
+ at end ifhtml
+
+ at ifnothtml
+ at macro external {}
+ at end macro
+ at macro fig {plot,text}
+ at uref{http://mathgl.sourceforge.net/\text\, @image{small/\plot\-sm,3cm, , , .png}}
+ at end macro
+ at end ifnothtml
+
+ at node Main, News, , Top
+ at section MathGL is ...
+
+ at ifhtml
+ at html
+<a href="surf_cont_fog.html"><img border="0" align="right" hspace="30" vspace="20" alt="Surface in fog" src="../surf_cont_fog_g.png"></a>
+ at end html
+ at end ifhtml
+ at itemize @bullet
+ at item
+a library for making high-quality scientific graphics under Linux and Windows;
+ at item
+a library for the fast data plotting and data processing of large data arrays;
+ at item
+a library for working in window and console modes and for easy embedding into other programs;
+ at item
+a library with large and growing set of graphics.
+ at end itemize
+
+Now MathGL has more than 35000 lines of code, more than 55 general types of graphics for 1d, 2d and 3d data arrays, including special ones for chemical and statistical graphics. It can export graphics to raster and vector (EPS or SVG) formats. It has Qt, FLTK, OpenGL interfaces and can be used even from console programs. It has functions for data processing and script MGL language for simplification of data plotting. Also it has several types of transparency and smoothed lightning, vecto [...]
+
+There is a @uref{http://sourceforge.net/forum/?group_id=152187, forum} where you can ask a question or suggest an improvement. However the @uref{http://groups.google.com/group/mathgl, MathGL group} is preferable for quicker answer.
+
+For subscribing to @uref{http://groups.google.com/group/mathgl, MathGL group} you can use form below
+ at ifhtml
+ at html
+<form action="http://groups.google.com/group/mathgl/boxsubscribe">
+Email: <input type=text name=email> <input type=submit name="sub" value="Subscribe">
+</form>
+ at end html
+ at end ifhtml
+
+ at strong{About LGPL and GPL licenses.}
+Generally, MathGL is GPL library. However, you can use LGPL license for MathGL core and widgets if you don't use SWIG-based interfaces and disable GSL features. This can be done by using @code{lgpl} option at build time. According this, I've added the LGPL win32 binaries into @ref{Download} page.
+
+ at strong{Latest news}
+ at itemize
+ at item @emph{13 December 2012.}
+New version (v. at value{VERSION}) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are new plots, advanced color schemes, @uref{../json.html, JavaScript drawing}, and many other improvements in both MathGL core and UDAV, which partially denoted @ref{News, here}. Note, there are @strong{incompatible with v.2.0.* changes} in the arguments of some functions.
+ at item @emph{I'm sorry for making incompatible changes in v.2.1. It was done for introducing unified interface for all functions. I promise that I will not break API for v.2.* later, i.e. I'll only add new features or bug fixes.}
+ at end itemize
+
+There is detailed @ref{News, news list}. Sourceforge project page @uref{http://sourceforge.net/projects/mathgl/, here}.
+
+ at ifhtml
+ at html
+<a href="http://www.datadvance.net"><img border="0" align="right" hspace="10" alt="DATADVANCE" src="../datadvance.png"></a>
+ at end html
+ at end ifhtml
+Javascript interface was developed with support of @url{http://www.datadvance.net, DATADVANCE} company.
+
+ at external{}
+
+ at node News, Features, Main, Top
+ at section News
+
+ at itemize
+
+ at item
+ at strong{13 December 2012.}
+New version (v.2.1) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are speeding up and many improvements and bugfixes:
+ at itemize @bullet
+ at item
+Add class mglDataC for complex data arrays.
+ at item
+Add Vect3() plot for drawing vectors on slice of 3d vector field. See @url{../doc_en/doc_en_17.html#Vect3-sample, sample}.
+ at item
+Add Table() function for drawing table with data values. See @url{../doc_en/doc_en_14.html#Table-sample, sample}.
+ at item
+Add ZoomAxis() for zooming/shifting axis range as whole.
+ at item
+Add WriteJSON() function for exporting in JSON format suitable for later drawing by JavaScript
+ at item
+Add JavaScript code for visualizing JSON data. See @uref{../json.html, samples}.
+ at item
+Add mgl.cgi tool which return PNG image for CGI request in form of MGL script.
+ at item
+Add mglData::Solve() for finding x-value where dat(x)=val. See @url{../doc_en/doc_en_12.html#Solve-sample, sample}.
+ at item
+Add mglData::Clean() for removing rows with duplicate values for given column.
+ at item
+Add MGL commands 'errbox', 'face'
+
+ at item
+Color can be specified as its RGB[A] values, i.e. like @samp{@{xFFFFFF@}} or @samp{@{xFFFFFFFF@}}. See @url{../doc_en/doc_en_23.html#Line-styles, sample}.
+ at item
+Color in color scheme  may have position in range [0,1]. Format is @samp{@{CN,pos@}} or @samp{@{xFFFFFF,pos@}}. See @url{../doc_en/doc_en_24.html#Color-scheme, sample}.
+ at item
+Now pen width for marks is proportional to pen width of line multiplied by size of marks.
+ at item
+Now you can use different font-faces in the plot simultaneously. See @url{../doc_en/doc_en_11.html#Text-features, sample}.
+ at item
+Now Legend() automatically use several columns if it contain too many legend entries.
+ at item
+Add style '-' for legend for drawing them horizontally. See @url{../doc_en/doc_en_11.html#Legend-sample, sample}.
+ at item
+Vectors is drawn now even if only starting or ending points are placed in bounding box.
+ at item
+Strongly rewrite the algorithm of vector field plotting.
+
+ at item
+Grid lines for NAN origin values are always located at far-away edges.
+ at item
+Try correctly place axis and tick labels even for axis with inverse range (i.e. for v2<v1). Note, it work well for 2D axis. One should use Aspect() with negative values to do it correctly in general case.
+ at item
+Axis style 'XYZ' draw corresponding axis with ticks labels on opposite side. This also influence on following Label() calls.
+ at item
+Text is drawn for initially invisible axis (like z-axis) too.
+
+ at item
+Frames now save 3D information if MGL_VECT_FRAME is set (by default).
+ at item
+Add functions GetFrame(), DelFrame(), SetFrame(), ShowFrame() for replacing or showing data from given frame. It can be use to hide/show a set of plot(s) quickly. Work if MGL_VECT_FRAME is set on (by default is on).
+ at item
+CalcXYZ() function now use data from z-buffer for better determining @{x,y,z@} coordinates.
+
+ at item
+Add dialog for data arguments in "New command" dialog of UDAV. See @url{../doc_en/doc_en_71.html#UDAV-dialogs, UDAV dialogs}.
+ at item
+Value of arguments are saved while the kind of command is changed in "New command" dialog of UDAV.
+ at item
+Extend classification of commands in "New command" dialog of UDAV and make it automatic.
+ at item
+Mouse position at an object click now is displayed on the image itself.
+ at item
+Add zoom in/out by mouse wheel.
+ at item
+Add zoom in/out of axis range by mouse wheel, and shift of axis range by middle button.
+ at item
+Text editor in UDAV now highlight current line.
+ at item
+Completer can be switched off correctly now.
+ at item
+Multi-line strings (i.e. separated by "\" symbol) are highlighted correctly now.
+ at item
+Add option to enable/disable selected plot in UDAV.
+ at item
+Rearrange hot-keys in UDAV and in QMathGL.
+
+ at item
+Make code compilable by Borland compiler too.
+ at item
+Improve output in OpenGL mode.
+ at item
+Add fog at export in EPS/SVG formats.
+ at item
+Add mglParse::AllowFileIO() for enable/disable I/O commands in MGL scripts.
+
+ at item
+Export functions now can write in stdout if file name is "-".
+ at item
+Picture drawing now use multi-threading for each stage.
+
+ at item
+Functions mglData::Spline*, mglData::Linear* now can return gradient at the point.
+ at item
+mglFourier now make true inverse transform.
+
+ at item
+Add annotation for all pure C functions.
+ at item
+Update list of built-in glyphs.
+ at item
+Update samples.
+ at item
+Update documentation.
+ at item
+Different bugfixes.
+
+ at item
+ at strong{INCOMPATIBLE CHANGES:} in the arguments of functions: mgl_axis, mgl_axis_grid, mgl_label, mgl_labelw, mgl_legend_pos, mgl_legend; and in functions for MGL parsing.
+ at item
+ at strong{MINOR INCOMPATIBLE:} plotting functions now use double argument always.
+ at end itemize
+
+ at item 
+ at strong{23 August 2011.} Version 2.0.beta was released.
+ at item 
+ at strong{30 May 2011.} Version 1.11.2 was released.
+ at item 
+ at strong{8 November 2010.} Version 1.11 was released.
+ at item 
+ at strong{28 December 2009.} Version 1.10 was released.
+ at item 
+ at strong{8 July 2009.} Version 1.9 was released.
+ at item 
+ at strong{27 November 2008.} Version 1.8 was released.
+ at item 
+ at strong{5 June 2008.} Version 1.7 was released.
+ at item 
+ at strong{17 March 2008.} Version 1.6 was released.
+ at item 
+ at strong{11 January 2008.} Version 1.5 was released.
+ at item 
+ at strong{30 October 2007.} Version 1.4 was released.
+ at item 
+ at strong{15 October 2007.} Version 1.3 was released.
+ at item 
+ at strong{10 September 2007.} Version 1.2 was released.
+ at item 
+ at strong{23 May 2007.} Version 1.1 was released.
+ at item 
+ at strong{2 April 2007.} Version 1.0 was released.
+ at item 
+ at strong{24 January 2007.} First public release (v.0.8).
+ at end itemize
+
+ at external{}
+
+
+ at node Features, Pictures, News, Top
+ at section Features
+
+MathGL can plot a wide range of graphics. It includes:
+ at itemize @bullet
+ at item
+one-dimensional: Plot, Area, Bars, Step, Stem, Torus, Chart, Error, Tube, Mark, (@ref{1D plotting});
+
+ at item
+two-dimensional plots: Mesh, Surf, Dens, Cont, ContF, Boxs, Axial, Fall, Belt, Tile, including surfaces transparent (SurfA) or colored (SurfC) by another data (@ref{2D plotting});
+
+ at item
+three-dimensional plots: Surf3, Dens3, Cont3, ContF3, Cloud-like, including isosurfaces transparent (Surf3A) or colored (Surf3C) by another data (@ref{3D plotting});
+
+ at item
+vector fields plots: vector fields Vect, Vect3 and Traj, flow threads Flow, flow pipes Pipe, mapping chart Map, and so on (@ref{Vector fields});
+
+ at item
+and so on. See also @ref{Extra samples}.
+ at end itemize
+
+In fact, I created the functions for drawing of all the types of scientific plots that I know. The list of plots is growing; if you need some special type of a plot then please email me @email{mathgl.abalakin@@gmail.com, e-mail} and it will appear in the new version.
+
+I tried to make plots as nice looking as possible: e.g., a surface can be transparent and highlighted by several (up to 10) light sources. Most of the drawing functions have 2 variants: simple one for the fast plotting of data, complex one for specifying of the exact position of the plot (including parametric representation). Resulting image can be saved in bitmap PNG, JPEG, TGA, BMP format, or in vector EPS, SVG or TeX format, or in 3D formats OBJ, OFF, STL or in PRC format.
+
+All texts are drawn by vector fonts, which allows for high scalability and portability. Texts may contain commands for: some of the TeX-like symbols, changing index (upper or lower indexes) and the style of font inside the text string. Texts of ticks are rotated with axis rotation. It is possible to create a legend of plot and put text in an arbitrary position on the plot. Arbitrary text encoding (by the help of function @code{setlocale()}) and UTF-16 encoding are supported.
+
+Special class mglData is used for data encapsulation. In addition to a safe creation and deletion of data arrays it includes functions for data processing (smoothing, differentiating, integrating, interpolating and so on) and reading of data files with automatic size determination. Class mglData can handle arrays with up to three dimensions (arrays which depend on up to 3 independent indexes @math{a_@{ijk@}}). Using an array with higher number of dimensions is not meaningful, because I d [...]
+
+There is fast evaluation of a textual mathematical expression. It is based on string precompilation to tree-like code at the creation of class instance. At evaluation stage code performs only fast tree-walk and returns the value of the expression. In addition to changing data values, textual formulas are also used for drawing in @emph{arbitrary} curvilinear coordinates. A set of such curvilinear coordinates is limited only by user's imagination rather than a fixed list like: polar, parab [...]
+
+ at external{}
+
+ at node Pictures, MGL scripts, Features, Top
+ at section Pictures
+
+There are samples for @ref{1D plotting, 1D arrays}, @ref{2D plotting, 2D arrays}, @ref{3D plotting, 3D arrays}, @ref{Vector fields} and some @ref{Extra samples}.
+
+ at anchor{1D plotting}
+ at subsection Examples of graphics for 1d arrays
+
+ at fig{plot, doc_en/doc_en_14.html#Plot-sample}
+ at fig{radar,doc_en/doc_en_14.html#Radar-sample}
+ at fig{step, doc_en/doc_en_14.html#Step-sample}
+ at fig{tens, doc_en/doc_en_14.html#Tens-sample}
+
+ at fig{area, doc_en/doc_en_14.html#Area-sample}
+ at fig{region,doc_en/doc_en_14.html#Region-sample}
+ at fig{stem, doc_en/doc_en_14.html#Stem-sample}
+ at fig{torus,doc_en/doc_en_14.html#Torus-sample}
+
+ at fig{bars, doc_en/doc_en_14.html#Bars-sample}
+ at fig{barh, doc_en/doc_en_14.html#Barh-sample}
+ at fig{cones,doc_en/doc_en_14.html#Cones-sample}
+ at fig{chart,doc_en/doc_en_14.html#Chart-sample}
+
+ at fig{boxplot,doc_en/doc_en_14.html#BoxPlot-sample}
+ at fig{candle, doc_en/doc_en_14.html#Candle-sample}
+ at fig{tube, doc_en/doc_en_14.html#Tube-sample}
+ at fig{tape, doc_en/doc_en_14.html#Tape-sample}
+
+ at fig{error,doc_en/doc_en_14.html#Error-sample}
+ at fig{mark, doc_en/doc_en_14.html#Mark-sample}
+ at fig{textmark, doc_en/doc_en_14.html#TextMark-sample}
+ at fig{label,doc_en/doc_en_14.html#Label-sample}
+
+ at anchor{2D plotting}
+ at subsection Examples of graphics for 2d arrays
+
+ at fig{surf, doc_en/doc_en_15.html#Surf-sample}
+ at fig{surfc,doc_en/doc_en_15.html#SurfC-sample}
+ at fig{surfa,doc_en/doc_en_15.html#SurfA-sample}
+ at fig{mesh, doc_en/doc_en_15.html#Mesh-sample}
+
+ at fig{fall, doc_en/doc_en_15.html#Fall-sample}
+ at fig{belt, doc_en/doc_en_15.html#Belt-sample}
+ at fig{boxs, doc_en/doc_en_15.html#Boxs-sample}
+ at fig{axial,doc_en/doc_en_15.html#Axial-sample}
+
+ at fig{dens, doc_en/doc_en_15.html#Dens-sample}
+ at fig{tile, doc_en/doc_en_15.html#Tile-sample}
+ at fig{tiles,doc_en/doc_en_15.html#TileS-sample}
+ at fig{grad, doc_en/doc_en_15.html#Grad-sample}
+
+ at fig{cont, doc_en/doc_en_15.html#Cont-sample}
+ at fig{contf,doc_en/doc_en_15.html#ContF-sample}
+ at fig{contd,doc_en/doc_en_15.html#ContD-sample}
+ at fig{contv,doc_en/doc_en_15.html#ContV-sample}
+
+ at anchor{3D plotting}
+ at subsection Examples of graphics for 3d arrays
+
+ at fig{surf3, doc_en/doc_en_16.html#Surf3-sample}
+ at fig{surf3c,doc_en/doc_en_16.html#Surf3C-sample}
+ at fig{surf3a,doc_en/doc_en_16.html#Surf3A-sample}
+ at fig{cloud, doc_en/doc_en_16.html#Cloud-sample}
+
+ at fig{densa, doc_en/doc_en_16.html#Dens3-sample}
+ at fig{conta, doc_en/doc_en_16.html#Cont3-sample}
+ at fig{contfa,doc_en/doc_en_16.html#ContF3-sample}
+ at fig{dots,  doc_en/doc_en_16.html#Dots-sample}
+
+ at fig{dens_xyz, doc_en/doc_en_16.html#Dens-projection-sample}
+ at fig{cont_xyz, doc_en/doc_en_16.html#Cont-projection-sample}
+ at fig{contf_xyz,doc_en/doc_en_16.html#ContF-projection-sample}
+ at fig{triplot,  doc_en/doc_en_16.html#TriPlot-and-QuadPlot}
+
+ at anchor{Vector fields}
+ at subsection Examples of graphics for vector fields
+
+ at fig{vect, doc_en/doc_en_17.html#Vect-sample}
+ at fig{vecta,doc_en/doc_en_17.html#Vect3-sample}
+ at fig{flow, doc_en/doc_en_17.html#Flow-sample}
+ at fig{pipe, doc_en/doc_en_17.html#Pipe-sample}
+
+ at fig{traj, doc_en/doc_en_17.html#Traj-sample}
+ at fig{dew, doc_en/doc_en_17.html#Dew-sample}
+
+ at anchor{Extra samples}
+ at subsection Examples of additional features
+
+ at fig{inplot, doc_en/doc_en_11.html#Subplots}
+ at fig{axis, doc_en/doc_en_11.html#Axis-and-ticks}
+ at fig{ticks, doc_en/doc_en_11.html#Axis-and-ticks}
+ at fig{loglog, doc_en/doc_en_11.html#Axis-and-ticks}
+
+ at fig{curvcoor, doc_en/doc_en_11.html#Curvilinear-coordinates}
+ at fig{colorbar, doc_en/doc_en_11.html#Colorbars}
+ at fig{box, doc_en/doc_en_11.html#Bounding-box}
+ at fig{ternary, doc_en/doc_en_11.html#Ternary-axis}
+
+ at fig{text, doc_en/doc_en_11.html#Text-features}
+ at fig{legend, doc_en/doc_en_11.html#Legend-sample}
+ at fig{cut, doc_en/doc_en_11.html#Cutting-sample}
+ at fig{alpha, doc_en/doc_en_18.html#Transparency-and-lighting}
+
+ at fig{type0, doc_en/doc_en_18.html#Types-of-transparency}
+ at fig{type1, doc_en/doc_en_18.html#Types-of-transparency}
+ at fig{type2, doc_en/doc_en_18.html#Types-of-transparency}
+ at fig{fog, doc_en/doc_en_18.html#Adding-fog}
+
+ at fig{combined, doc_en/doc_en_18.html#g_t_0060_0060Compound_0027_0027-graphics}
+ at fig{several_light, doc_en/doc_en_18.html#Several-light-sources}
+ at fig{stereo, doc_en/doc_en_18.html#Stereo-image}
+ at fig{primitives, doc_en/doc_en_18.html#Using-primitives}
+
+ at fig{stfa, doc_en/doc_en_18.html#STFA-sample}
+ at fig{dat_diff, doc_en/doc_en_12.html#Change-data}
+ at fig{dat_extra, doc_en/doc_en_12.html#Change-data}
+ at fig{map, doc_en/doc_en_18.html#Mapping-visualization}
+
+ at fig{hist, doc_en/doc_en_18.html#Making-histogram}
+ at fig{fit, doc_en/doc_en_18.html#Nonlinear-fitting-sample}
+ at fig{pde, doc_en/doc_en_18.html#PDE-solving-hints}
+ at fig{parser, doc_en/doc_en_18.html#MGL-parser-using}
+
+ at external{}
+
+ at node MGL scripts, Download, Pictures, Top
+ at section MGL scripts
+
+MGL script language is rather simple. Each string is a command. First word of string is the name of command. Other words are command arguments. Command may have up to 1000 arguments (at least for now). Words are separated from each other by space or tabulation symbol. The upper or lower case of words is important, i.e. variables @var{a} and @var{A} are different variables. Symbol @samp{#} starts the comment (all characters after # will be ignored). The exception is situation when @samp{# [...]
+
+If string contain references to external parameters (substrings @samp{$0}, @samp{$1} ... @samp{$9}) or definitions (substrings @samp{$a}, @samp{$b} ... @samp{$z}) then before execution the values of parameter/definition will be substituted instead of reference. It allows to use the same MGL script for different parameters (file names, paths, condition and so on).
+
+Argument can be a string, a variable (data arrays) or a number (scalars).
+ at itemize @bullet
+ at item
+The string is any symbols between ordinary marks @samp{'}. Long strings can be concatenated from several lines by @samp{\} symbol. I.e. the string @samp{'a +'\<br>' b'} will give string @samp{'a + b'} (here @samp{<br>} is newline).
+
+ at item
+Usually variable have a name which is arbitrary combination of symbols (except spaces and @samp{'}) started from a letter and with length less than 64. A temporary array can be used as variable:
+ at itemize @bullet
+ at item
+sub-arrays (like in @code{subdata} command) as command argument. For example, @code{a(1)} or @code{a(1,:)} or @code{a(1,:,:)} is second row, @code{a(:,2)} or @code{a(:,2,:)} is third column, @code{a(:,:,0)} is first slice and so on. Also you can extract a part of array from m-th to n-th element by code @code{a(m:n,:,:)} or just @code{a(m:n)}.
+
+ at item
+any column combinations defined by formulas, like @code{a('n*w^2/exp(t)')} if names for data columns was specified (by @code{idset} command or in the file at string started with @code{##}).
+
+ at item
+any expression (without spaces) of existed variables produce temporary variable. For example, @samp{sqrt(dat(:,5)+1)} will produce temporary variable with data values equal to @code{tmp[i,j] = sqrt(dat[i,5,j]+1)}.
+
+ at item
+temporary variable of higher dimensions by help of []. For example, @samp{[1,2,3]} will produce a temporary vector of 3 elements @{1, 2, 3@}; @samp{[[11,12],[21,22]]} will produce matrix 2*2 and so on. Here you can join even an arrays of the same dimensions by construction like @samp{[v1,v2,...,vn]}.
+
+ at item
+result of code for making new data inside @{@}. For example, @samp{@{sum dat 'x'@}} produce temporary variable which contain result of summation of @var{dat} along direction 'x'. This is the same array @var{tmp} as produced by command @samp{sum tmp dat 'x'}. You can use nested constructions, like @samp{@{sum @{max dat 'z'@} 'x'@}}.
+ at end itemize
+Temporary variables can not be used as 1st argument for commands which create (return) the data (like @samp{new}, @samp{read}, @samp{hist} and so on).
+
+ at item
+Special names @code{nan=#QNAN, pi=3.1415926..., on=1, off=0, :=-1} are treated as number if they were not redefined by user. Variables with suffixes are treated as numbers. Names defined by @code{define} command are treated as number. Also results of formulas with sizes 1x1x1 are treated as number (for example, @samp{pi/dat.nx}).
+ at end itemize
+Before the first using all variables must be defined with the help of commands, like, @code{new}, @code{var}, @code{list}, @code{copy}, @code{read}, @code{hist}, @code{sum} and so on.
+
+Command may have several set of possible arguments (for example, @code{plot ydat} and @code{plot xdat ydat}). All command arguments for a selected set must be specified. However, some arguments can have default values. These argument are printed in [], like @code{text ydat ['stl'='']} or @code{text x y 'txt' ['fnt'='' size=-1]}. At this, the record @code{[arg1 arg2 arg3 ...]} means @code{[arg1 [arg2 [arg3 ...]]]}, i.e. you can omit only tailing arguments if you agree with its default val [...]
+
+For more details see @uref{../doc_en/doc_en_64.html#MGL-scripts, MathGL documentation}
+
+ at external{}
+
+ at node Download, Other projects, MGL scripts, Top
+ at section Download
+
+ at strong{Stable version (v. at value{VERSION})}
+
+You may download current version of MathGL for following configurations:
+ at itemize @bullet
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mathgl-@value{VERSION}.tar.gz,source} file with cmake build system.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mathgl-@value{VERSION}-mingw.i686.7z,Win32 GPL} binaries for MinGW (build for i686)
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mathgl-@value{VERSION}.LGPL-mingw.i686.7z,Win32 LGPL} binaries for MinGW (build for i686, no GSL and HDF5 support)
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mathgl-@value{VERSION}.LGPL-win64.7z,Win64 LGPL} binaries for MSVS 2010 (no GSL and HDF5 support)
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mathgl-@value{VERSION}-1.DevPack,DevPak} package for Dev-C++ or Code::Blocks (GPL version)
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mathgl-@value{VERSION}.eng.pdf,PDF} documentation in English
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mgl_scripts-@value{VERSION}.7z,utilities} with all required DLL files (build for i686)
+ at c HTML documentation in English
+ at c HTML documentation in Russian
+ at c @item
+ at c @uref{http://downloads.sourceforge.net/mathgl/mathgl_slides-1.9.pdf,PDF} slideshow of main features
+ at end itemize
+
+ at strong{Previous version (v.1.11.2)}
+
+You may download current version of MathGL for following configurations:
+ at itemize @bullet
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mathgl-1.11.2.tar.gz,source} file with autoconf/automake script.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mathgl-1.11.2-mingw.i686.zip,Win32 GPL} binaries for MinGW (build for i686)
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mathgl-1.11.1.1.LGPL-mingw.i686.zip,Win32 LGPL} binaries for MinGW (build for i686, no GSL and HDF5 support)
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mathgl-1.11.2-1.DevPack,DevPak} package for Dev-C++ or Code::Blocks (GPL version)
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mathgl-1.11.2.eng.pdf,PDF} documentation in English
+ at c HTML documentation in English
+ at c HTML documentation in Russian
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mathgl_slides-1.9.pdf,PDF} slideshow of main features
+ at end itemize
+
+ at strong{Font files}
+
+There are a set of @uref{http://sourceforge.net/project/showfiles.php?group_id=152187&package_id=267177,font files} for MathGL with following typefaces. Note, that the set of glyphs can be less than in default font. As result not all TeX symbols can be displayed.
+ at itemize @bullet
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/STIX_font.tgz,STIX} font -- default font for MathGL.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/adventor_font.tgz,Adventor font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} sansserif font based on the URW Gothic L family (like Avant Garde Gothic).
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/bonum_font.tgz,Bonum font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} serif font based on the URW Bookman L family.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/chorus_font.tgz,Chorus font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} font based on the URW Chancery L Medium Italic.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/cursor_font.tgz,Cursor font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} monospaced serif font based on the URW Nimbus Mono L (like Courier).
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/heros_font.tgz,Heros font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} sansserif font based on the URW Nimbus Sans L (like Helvetica).
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/heroscn_font.tgz,HerosCN font} -- the "compressed" version of previous one.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/pagella_font.tgz,Pagella font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} serif font based on the URW Palladio L (like Palatino).
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/schola_font.tgz,Schola font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} serif fonts is based on the URW Century Schoolbook L.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/termes_font.tgz,Termes font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} serif fonts is based on the Nimbus Roman No9 L (like Times).
+ at end itemize
+
+ at external{}
+
+ at node Other projects, , Download, Top
+ at section Other projects
+
+Except scientific (non public) projects I also have some general interest projects:
+ at itemize @bullet
+ at item
+ at uref{http://sourceforge.net/projects/pocketmk/, PocketMK} is small program for PocketPC which simulate famous Russian calculators MK-61 and slightly extend it.
+ at item
+ at uref{http://udav.sourceforge.net/,UDAV} is front-end for MGL scripts. It has windows interface for data viewing, changing and plotting. Also it can execute MGL scripts, setup and rotating graphics and so on.
+ at end itemize
+
+Also I recommend to look at:
+ at itemize @bullet
+ at item
+ at uref{http://englab.bugfest.net/,EngLab} is a cross-compile mathematical platform with a C like syntax intended to be used both by engineers and users with small programming knowledge. It is extremely scalable and allows users and the community to easily compile their own functions as shared objects.
+ at item
+ at uref{http://threedepict.sourceforge.net/,3Depict} is software for analysis of scientific datasets commonly encountered in atom probe tomography. You can manipulate, interact with and analyse point based datasets.
+ at item
+ at uref{http://www.sourceforge.net/projects/graphplot/,Graphplot} is function plotter based on MathGL.
+ at item
+ at uref{http://www.sourceforge.net/projects/graphplot/,OscillViewer} is oscilloscope monitoring program. Working with L-Card 14-140 AD-Convertor. Based on Qt and MathGL libraries.
+ at end itemize
+
+Finally, few links to free software and libraries:
+ at itemize @bullet
+ at item
+ at uref{http://www.thefreecountry.com/,thefreecountry.com} have a lot of Free Programmers', Webmasters' and Security Resources
+ at item
+ at uref{http://gnuwin32.sourceforge.net/,GnuWin} provides ports of tools with a GNU or similar open source license, to modern MS-Windows.
+ at item
+ at uref{http://loll.sourceforge.net/,LLoL} is project collecting, organising, classifying, and maintaining important URLs about Linux and the Open Source movement for all levels of Linux users. The LoLL project now has 4000+ links which are updated usually on a daily basis.
+ at end itemize
+
+ at external{}
+
+ at bye
diff --git a/texinfo/web_ru.texi b/texinfo/web_ru.texi
new file mode 100644
index 0000000..9d6fd6d
--- /dev/null
+++ b/texinfo/web_ru.texi
@@ -0,0 +1,412 @@
+ at c ------------------------------------------------------------------
+ at chapter Website
+ at nav{}
+
+ at menu
+* Main::
+* News::
+* Features::
+* Pictures::
+ at c * MGL scripts::
+* Download::
+* Other projects::
+ at end menu
+
+ at external{}
+
+ at node Main, News, , Website
+ at section MathGL is ...
+ at nav{}
+
+ at ifhtml
+ at html
+<a href="Adding-fog.html"><img border="0" align="right" hspace="30" vspace="20" alt="Surface in fog" src="../small/fog-sm.png"></a>
+ at end html
+ at end ifhtml
+ at itemize @bullet
+ at item
+a library for making high-quality scientific graphics under Linux and Windows;
+ at item
+a library for the fast data plotting and data processing of large data arrays;
+ at item
+a library for working in window and console modes and for easy embedding into other programs;
+ at item
+a library with large and growing set of graphics.
+ at end itemize
+
+Now MathGL has more than 35000 lines of code, more than 55 general types of graphics for 1d, 2d and 3d data arrays, including special ones for chemical and statistical graphics. It can export graphics to raster and vector (EPS or SVG) formats. It has Qt, FLTK, OpenGL interfaces and can be used even from console programs. It has functions for data processing and script MGL language for simplification of data plotting. Also it has several types of transparency and smoothed lightning, vecto [...]
+
+There is a @uref{http://sourceforge.net/forum/?group_id=152187, forum} where you can ask a question or suggest an improvement. However the @uref{http://groups.google.com/group/mathgl, MathGL group} is preferable for quicker answer.
+
+For subscribing to @uref{http://groups.google.com/group/mathgl, MathGL group} you can use form below
+ at ifhtml
+ at html
+<form action="http://groups.google.com/group/mathgl/boxsubscribe">
+Email: <input type=text name=email> <input type=submit name="sub" value="Subscribe">
+</form>
+ at end html
+ at end ifhtml
+
+ at strong{About LGPL and GPL licenses.}
+Generally, MathGL is GPL library. However, you can use LGPL license for MathGL core and widgets if you don't use SWIG-based interfaces and disable GSL features. This can be done by using @code{lgpl} option at build time. According this, I've added the LGPL win32 binaries into @ref{Download} page.
+
+ at strong{Latest news}
+ at itemize
+
+ at item @emph{16 May 2017.}
+New version (v.2.4) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are @code{mgllab} executable, string manipulation in MGL, new functions, plot types and styles, translation to Russian using @code{gettext} and bugfixes, which denoted @ref{News, here}.
+ at end itemize
+
+There is detailed @ref{News, news list}. Sourceforge project page @uref{http://sourceforge.net/projects/mathgl/, here}.
+
+ at ifhtml
+ at html
+<a href="http://www.datadvance.net"><img border="0" align="right" hspace="10" alt="DATADVANCE" src="../datadvance.png"></a>
+ at end html
+ at end ifhtml
+Javascript interface was developed with support of @url{http://www.datadvance.net, DATADVANCE} company.
+
+ at external{}
+
+ at node News, Features, Main, Website
+ at section News
+ at nav{}
+
+ at itemize
+
+ at item @strong{16 May 2017.}
+New version (v.2.4) of @uref{http://sourceforge.net/projects/mathgl, MathGL} is released. There are @code{mgllab} executable, string manipulation in MGL, new functions, plot types and styles, translation to Russian using @code{gettext} and bugfixes:
+ at itemize @bullet
+
+ at item Add @code{mgllab} executable, which is FLTK based version of @code{UDAV}. So, most things @code{mgllab} do faster.
+ at item Add string manipulation in MGL language:
+ at itemize @bullet
+	@item 'str'[n] -- get string of only n-th symbol;
+	@item 'str'+v -- add value v to the last character of the string;
+	@item 'str',val or 'str',!val -- append numeric value to the string (as before).
+ at end itemize
+ at item Add time value to MGL language in format: @samp{hh-mm-ss_DD.MM.YYYY} or @samp{hh-mm-ss} or @samp{DD.MM.YYYY}.
+ at item Add @ref{iris} plot to show cross-dependencies of several data arrays.
+ at item Add @ref{flame2d} to draw flame fractals.
+ at item Add @ref{bbox} to set bounding box for 2D output.
+ at item Add @ref{section} to get part of data between specified values.
+ at item Add @ref{detect} to found curves along data maximums.
+ at item Add @ref{dilate} to extend the region of 1-th value.
+ at item Add @ref{erode} to narrow the region of 1-th value.
+ at item Add @ref{apde} to solve PDE equation in inhomogeneous nonlinear media with spatial dispersion.
+ at item Add @ref{symbol} to draw the glyphs defined by @ref{addsymbol}.
+ at item Add @ref{addsymbol} to declare user-defined symbol (or glyph), which can be used as markers for plot (with style '&') or drawn itself by @ref{symbol} command.
+ at item Add @ref{openhdf} to open all data arrays from HDF file.
+ at item Extend @ref{crop} to cut to optimal size for FFT (i.e. to closest of 2^n*3^m*5^l).
+ at item Add function mgl_data_max_first() and data suffixes .m[xyz][fl] to find first/last maximum along direction (see @ref{Data information}).
+ at item Add function mgl_datac_diff_par() to parametric derivative of complex data (see @ref{diff}).
+ at item Add style @samp{F} for @ref{bars} and @ref{barh} to set fixed bar widths.
+ at item Add style @samp{a} for @ref{plot}, @ref{tens}, @ref{area} and @ref{region} to accurate drawing of data, which partially lie out of axis range.
+ at item Add style @samp{#} for @ref{region} to draw wired plot.
+ at item Add possibility of manual shift in @ref{multiplot}.
+ at item Add parsing arguments of options for MGL commands.
+ at item MGL command @ref{correl} now can perform 2d and 3d correlations.
+ at item Option @ref{meshnum} now change the number of drawn markers for @ref{plot}, @ref{tens}, @ref{step}, @ref{mark} and @ref{textmark}.
+ at item Function @ref{step} handle data with x.nx>y.nx similarly to @ref{bars}.
+ at item Extend @ref{tile} and @ref{tiles} by adding manual coloring and face orientation.
+ at item Add variant of MGL command @ref{copy} to copy data with "incorrect" names.
+ at item Improve tick labels drawing.
+ at item Improve time-ticks (add weeks) and add subticks to its.
+ at item Improve @ref{fplot} to handle several singularities.
+ at item Add LaTeX command \dfrac@{@}@{@}. This is full-sized version of \frac@{@}@{@}. Unfortunately, there is no support of nesting. Contrary, \frac allow nesting.
+ at item Add mglODEc() -- ODE solver for complex variables (see @ref{ode}).
+ at item Add cmplx(a,b)=a+i*b to the list of known functions in formula parsing
+ at item Update CMake find_package to find MathGL.
+ at item Increase line width for wired text.
+ at item Update documentation: add description of new commands, add hint @ref{Mixing bitmap and vector output}.
+ at item Add translation to Russian for most of labels and messages.
+ at item Name @code{all} are reserved in MGL scripts now as synonym of -1.
+
+ at item INCOMPATIBLE: Replace libmgl-qt by libmgl-qt4 and libmgl-qt5 for resolving conflicts of simultaneously installed both Qt4 and Qt5.
+ at item Minor bugfixes.
+
+ at end itemize
+
+ at item @strong{20 June 2016.} Version 2.3.5.1 was released.
+ at item @strong{16 May 2016.} Version 2.3.5 was released.
+ at item @strong{13 February 2016.} Version 2.3.4 was released.
+ at item @strong{1 June 2015.} Version 2.3.3 was released.
+ at item @strong{2 February 2015.} Version 2.3.2 was released.
+ at item @strong{21 October 2014.} Version 2.3.1 was released.
+ at item @strong{7 August 2014.} Version 2.3 was released.
+ at item @strong{19 March 2014.} Version 2.2.2.1 was released.
+ at item @strong{10 March 2014.} Version 2.2.2 was released.
+ at item @strong{22 January 2014.} Version 2.2.1 was released.
+ at item @strong{11 November 2013.} Version 2.2 was released.
+ at item @strong{8 May 2013.} Version 2.1.3.1 was released.
+ at item @strong{2 May 2013.} Version 2.1.3 was released.
+ at item @strong{28 January 2013.} Version 2.1.2 was released.
+ at item @strong{24 December 2012.} Version 2.1.1 was released.
+ at item @strong{13 December 2012.} Version 2.1 was released.
+ at item @strong{23 August 2011.} Version 2.0.beta was released.
+ at item @strong{30 May 2011.} Version 1.11.2 was released.
+ at item @strong{8 November 2010.} Version 1.11 was released.
+ at item @strong{28 December 2009.} Version 1.10 was released.
+ at item @strong{8 July 2009.} Version 1.9 was released.
+ at item @strong{27 November 2008.} Version 1.8 was released.
+ at item @strong{5 June 2008.} Version 1.7 was released.
+ at item @strong{17 March 2008.} Version 1.6 was released.
+ at item @strong{11 January 2008.} Version 1.5 was released.
+ at item @strong{30 October 2007.} Version 1.4 was released.
+ at item @strong{15 October 2007.} Version 1.3 was released.
+ at item @strong{10 September 2007.} Version 1.2 was released.
+ at item @strong{23 May 2007.} Version 1.1 was released.
+ at item @strong{2 April 2007.} Version 1.0 was released.
+ at item @strong{24 January 2007.} First public release (v.0.8).
+ at end itemize
+
+ at external{}
+
+
+ at node Features, Pictures, News, Website
+ at section Features
+ at nav{}
+
+MathGL can plot a wide range of graphics. It includes:
+ at itemize @bullet
+ at item
+one-dimensional: Plot, Area, Bars, Step, Stem, Torus, Chart, Error, Tube, Mark, (@ref{1D plotting});
+
+ at item
+two-dimensional plots: Mesh, Surf, Dens, Cont, ContF, Boxs, Axial, Fall, Belt, Tile, including surfaces transparent (SurfA) or colored (SurfC) by another data (@ref{2D plotting});
+
+ at item
+three-dimensional plots: Surf3, Dens3, Cont3, ContF3, Cloud-like, including isosurfaces transparent (Surf3A) or colored (Surf3C) by another data (@ref{3D plotting});
+
+ at item
+vector fields plots: vector fields Vect, Vect3 and Traj, flow threads Flow, flow pipes Pipe, mapping chart Map, and so on (@ref{Vector fields});
+
+ at item
+and so on. See also @ref{Extra samples}.
+ at end itemize
+
+In fact, I created the functions for drawing of all the types of scientific plots that I know. The list of plots is growing; if you need some special type of a plot then please email me @email{mathgl.abalakin@@gmail.com, e-mail} and it will appear in the new version.
+
+I tried to make plots as nice looking as possible: e.g., a surface can be transparent and highlighted by several (up to 10) light sources. Most of the drawing functions have 2 variants: simple one for the fast plotting of data, complex one for specifying of the exact position of the plot (including parametric representation). Resulting image can be saved in bitmap PNG, JPEG, TGA, BMP format, or in vector EPS, SVG or TeX format, or in 3D formats OBJ, OFF, STL or in PRC format.
+
+All texts are drawn by vector fonts, which allows for high scalability and portability. Texts may contain commands for: some of the TeX-like symbols, changing index (upper or lower indexes) and the style of font inside the text string. Texts of ticks are rotated with axis rotation. It is possible to create a legend of plot and put text in an arbitrary position on the plot. Arbitrary text encoding (by the help of function @code{setlocale()}) and UTF-16 encoding are supported.
+
+Special class mglData is used for data encapsulation. In addition to a safe creation and deletion of data arrays it includes functions for data processing (smoothing, differentiating, integrating, interpolating and so on) and reading of data files with automatic size determination. Class mglData can handle arrays with up to three dimensions (arrays which depend on up to 3 independent indexes @math{a_@{ijk@}}). Using an array with higher number of dimensions is not meaningful, because I d [...]
+
+There is fast evaluation of a textual mathematical expression. It is based on string precompilation to tree-like code at the creation of class instance. At evaluation stage code performs only fast tree-walk and returns the value of the expression. In addition to changing data values, textual formulas are also used for drawing in @emph{arbitrary} curvilinear coordinates. A set of such curvilinear coordinates is limited only by user's imagination rather than a fixed list like: polar, parab [...]
+
+ at external{}
+
+ at node Pictures, Download, Features, Website
+ at section Pictures
+ at nav{}
+
+There are samples for @ref{1D data plotting, 1D arrays}, @ref{2D data plotting, 2D arrays}, @ref{3D data plotting, 3D arrays}, @ref{Vector fields plotting} and some @ref{Extra samples}.
+
+ at anchor{1D data plotting}
+ at subheading Examples of graphics for 1d arrays
+
+ at sfig{plot, Plot sample}
+ at sfig{radar, Radar sample}
+ at sfig{step, Step sample}
+ at sfig{tens, Tens sample}
+
+ at sfig{area, Area sample}
+ at sfig{region,Region sample}
+ at sfig{stem, Stem sample}
+ at sfig{torus,Torus sample}
+
+ at sfig{bars, Bars sample}
+ at sfig{barh, Barh sample}
+ at sfig{cones,Cones sample}
+ at sfig{chart,Chart sample}
+
+ at sfig{boxplot,BoxPlot sample}
+ at sfig{candle, Candle sample}
+ at sfig{tube, Tube sample}
+ at sfig{tape, Tape sample}
+
+ at sfig{error,Error sample}
+ at sfig{mark, Mark sample}
+ at sfig{textmark, TextMark sample}
+ at sfig{label,Label sample}
+
+ at anchor{2D data plotting}
+ at subheading Examples of graphics for 2d arrays
+
+ at sfig{surf, Surf sample}
+ at sfig{surfc,SurfC sample}
+ at sfig{surfa,SurfA sample}
+ at sfig{mesh, Mesh sample}
+
+ at sfig{fall, Fall sample}
+ at sfig{belt, Belt sample}
+ at sfig{boxs, Boxs sample}
+ at sfig{axial,Axial sample}
+
+ at sfig{dens, Dens sample}
+ at sfig{tile, Tile sample}
+ at sfig{tiles,TileS sample}
+ at sfig{grad, Grad sample}
+
+ at sfig{cont, Cont sample}
+ at sfig{contf,ContF sample}
+ at sfig{contd,ContD sample}
+ at sfig{contv,ContV sample}
+
+ at anchor{3D data plotting}
+ at subheading Examples of graphics for 3d arrays
+
+ at sfig{surf3, Surf3 sample}
+ at sfig{surf3c,Surf3C sample}
+ at sfig{surf3a,Surf3A sample}
+ at sfig{cloud, Cloud sample}
+
+ at sfig{densa, Dens3 sample}
+ at sfig{conta, Cont3 sample}
+ at sfig{contfa,ContF3 sample}
+ at sfig{dots,  Dots sample}
+
+ at sfig{dens_xyz, Dens projection sample}
+ at sfig{cont_xyz, Cont projection sample}
+ at sfig{contf_xyz,ContF projection sample}
+ at sfig{triplot, TriPlot and QuadPlot}
+
+ at anchor{Vector fields plotting}
+ at subheading Examples of graphics for vector fields
+
+ at sfig{vect, Vect sample}
+ at sfig{vecta,Vect3 sample}
+ at sfig{flow, Flow sample}
+ at sfig{pipe, Pipe sample}
+
+ at sfig{traj, Traj sample}
+ at sfig{dew, Dew sample}
+
+ at anchor{Extra samples}
+ at subheading Examples of additional features
+
+ at sfig{inplot, Subplots}
+ at sfig{axis, Axis and ticks}
+ at sfig{ticks, Axis and ticks}
+ at sfig{loglog, Axis and ticks}
+
+ at sfig{curvcoor, Curvilinear coordinates}
+ at sfig{colorbar, Colorbars}
+ at sfig{box, Bounding box}
+ at sfig{ternary, Ternary axis}
+
+ at sfig{text, Text features}
+ at sfig{legend, Legend sample}
+ at sfig{cut, Cutting sample}
+ at sfig{alpha, Transparency and lighting}
+
+ at sfig{type0, Types of transparency}
+ at sfig{type1, Types of transparency}
+ at sfig{type2, Types of transparency}
+ at sfig{fog, Adding fog}
+
+ at sfig{combined, ``Compound'' graphics}
+ at sfig{several_light, Lighting sample}
+ at sfig{stereo, Stereo image}
+ at sfig{primitives, Using primitives}
+
+ at sfig{stfa, STFA sample}
+ at sfig{dat_diff, Change data}
+ at sfig{dat_extra, Change data}
+ at sfig{map, Mapping visualization}
+
+ at sfig{hist, Making histogram}
+ at sfig{fit, Nonlinear fitting hints}
+ at sfig{pde, PDE solving hints}
+ at sfig{parser, Using MGL parser}
+
+ at external{}
+
+ at node Download, Other projects, Pictures, Website
+ at section Download
+ at nav{}
+
+ at strong{Stable version (v. at value{VERSION})}
+
+You may download current version of MathGL for following configurations:
+ at itemize @bullet
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mathgl-@value{VERSION}@value{MINVER}.tar.gz, Source} file with cmake build system.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mathgl-@value{VERSION}@value{MINVER}-mingw.win32.7z,GPL} or @uref{http://downloads.sourceforge.net/mathgl/mathgl-@value{VERSION}@value{MINVER}.LGPL-mingw.win32.7z,LGPL} binaries for MinGW, 32-bit build for Pentium IV.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mathgl-@value{VERSION}@value{MINVER}-mingw.win64.7z,GPL} or @uref{http://downloads.sourceforge.net/mathgl/mathgl-@value{VERSION}@value{MINVER}.LGPL-mingw.win64.7z,LGPL} binaries for MinGW, 64-bit build.
+ at item
+MathGL utilities with all required DLL files for @uref{http://downloads.sourceforge.net/mathgl/mgl_scripts-@value{VERSION}.win32.7z,32-bit} and @uref{http://downloads.sourceforge.net/mathgl/mgl_scripts-@value{VERSION}.win32.7z,64-bit} versions of MS Windows.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mathgl-@value{VERSION}@value{MINVER}.eng.pdf,PDF} documentation in English.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/mathgl-doc-html-@value{VERSION}@value{MINVER}.7z, Archive} with HTML documentation and figures.
+ at c @item
+ at c @uref{http://downloads.sourceforge.net/mathgl/mathgl_slides-1.9.pdf,PDF} slideshow of main features
+ at end itemize
+
+ at strong{Font files}
+
+There are a set of @uref{http://sourceforge.net/project/showfiles.php?group_id=152187&package_id=267177,font files} for MathGL with following typefaces. Note, that the set of glyphs can be less than in default font. As result not all TeX symbols can be displayed.
+ at itemize @bullet
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/STIX_font.tgz,STIX} font -- default font for MathGL.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/adventor_font.tgz,Adventor font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} sansserif font based on the URW Gothic L family (like Avant Garde Gothic).
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/bonum_font.tgz,Bonum font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} serif font based on the URW Bookman L family.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/chorus_font.tgz,Chorus font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} font based on the URW Chancery L Medium Italic.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/cursor_font.tgz,Cursor font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} monospaced serif font based on the URW Nimbus Mono L (like Courier).
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/heros_font.tgz,Heros font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} sansserif font based on the URW Nimbus Sans L (like Helvetica).
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/heroscn_font.tgz,HerosCN font} -- the "compressed" version of previous one.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/pagella_font.tgz,Pagella font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} serif font based on the URW Palladio L (like Palatino).
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/schola_font.tgz,Schola font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} serif fonts is based on the URW Century Schoolbook L.
+ at item
+ at uref{http://downloads.sourceforge.net/mathgl/termes_font.tgz,Termes font} -- the @uref{http://www.gust.org.pl/projects/e-foundry/tex-gyre/index_html,TeX Gyre} serif fonts is based on the Nimbus Roman No9 L (like Times).
+ at end itemize
+
+ at external{}
+
+ at node Other projects, , Download, Website
+ at section Other projects
+ at nav{}
+
+Except scientific (non public) projects I also have some general interest projects:
+ at itemize @bullet
+ at item
+ at uref{http://sourceforge.net/projects/pocketmk/, PocketMK} is small program for PocketPC which simulate famous Russian calculators MK-61 and slightly extend it.
+ at item
+ at uref{http://udav.sourceforge.net/,UDAV} is front-end for MGL scripts. It has windows interface for data viewing, changing and plotting. Also it can execute MGL scripts, setup and rotating graphics and so on.
+ at end itemize
+
+Also I recommend to look at:
+ at itemize @bullet
+ at item
+ at uref{http://englab.bugfest.net/,EngLab} is a cross-compile mathematical platform with a C like syntax intended to be used both by engineers and users with small programming knowledge. It is extremely scalable and allows users and the community to easily compile their own functions as shared objects.
+ at item
+ at uref{http://threedepict.sourceforge.net/,3Depict} is software for analysis of scientific datasets commonly encountered in atom probe tomography. You can manipulate, interact with and analyse point based datasets.
+ at item
+ at uref{http://www.sourceforge.net/projects/graphplot/,Graphplot} is function plotter based on MathGL.
+ at item
+ at uref{http://www.sourceforge.net/projects/graphplot/,OscillViewer} is oscilloscope monitoring program. Working with L-Card 14-140 AD-Convertor. Based on Qt and MathGL libraries.
+ at end itemize
+
+Finally, few links to free software and libraries:
+ at itemize @bullet
+ at item
+ at uref{http://www.thefreecountry.com/,thefreecountry.com} have a lot of Free Programmers', Webmasters' and Security Resources
+ at item
+ at uref{http://gnuwin32.sourceforge.net/,GnuWin} provides ports of tools with a GNU or similar open source license, to modern MS-Windows.
+ at item
+ at uref{http://loll.sourceforge.net/,LLoL} is project collecting, organising, classifying, and maintaining important URLs about Linux and the Open Source movement for all levels of Linux users. The LoLL project now has 4000+ links which are updated usually on a daily basis.
+ at end itemize
+
+ at external{}
diff --git a/texinfo/widget_en.texi b/texinfo/widget_en.texi
new file mode 100644
index 0000000..0414293
--- /dev/null
+++ b/texinfo/widget_en.texi
@@ -0,0 +1,723 @@
+
+ at c ------------------------------------------------------------------
+ at chapter Widget classes
+ at nav{}
+ at cindex mglWnd
+ at cindex mglGLUT
+ at cindex Fl_MathGL
+ at cindex QMathGL
+ at cindex window
+ at cindex widgets
+
+There are set of ``window'' classes for making a window with MathGL graphics: @code{mglWindow}, @code{mglFLTK}, @code{mglQT} and @code{mglGLUT} for whole window, @code{Fl_MathGL} and @code{QMathGL} as widgets. All these classes allow user to show, rotate, export, and change view of the plot using keyboard. Most of them (except @code{mglGLUT}) also have toolbar and menu for simplifying plot manipulation. All window classes have mostly the same set of functions derived from @ref{mglWnd class}.
+
+For drawing you can use: @code{NULL} pointer if you'll update plot manually, global callback function of type @code{int draw(@code{HMGL} gr, @code{void *}p)} or @code{int draw(@code{mglGraph *}gr)}, or instance of class derived from @ref{mglDraw class}. Basically, this class have 2 main virtual methods:
+ at verbatim
+class mglDraw
+{
+public:
+    virtual int Draw(mglGraph *) { return 0; };
+    virtual void Reload() {};
+};
+ at end verbatim
+You should inherit yours class from @code{mglDraw} and re-implement one or both functions for drawing.
+
+The window can be constructed using one of following classes (see @ref{Using MathGL window} for examples).
+
+ at deftypefn {Constructor on @code{mglFLTK}} {} mglFLTK (@code{const char *}title=@code{"MathGL"})
+ at deftypefnx {Constructor on @code{mglFLTK}} {} mglFLTK (@code{int} (*draw)(@code{HMGL} gr, @code{void *}p), @code{const char *}title=@code{"MathGL"}, @code{void *}par=@code{NULL}, @code{void} (*reload)(@code{HMGL} gr, @code{void *}p)=0)
+ at deftypefnx {Constructor on @code{mglFLTK}} {} mglFLTK (@code{int} (*draw)(@code{mglGraph *}gr), @code{const char *}title=@code{"MathGL"})
+ at deftypefnx {Constructor on @code{mglFLTK}} {} mglFLTK (@code{mglDraw *}draw, @code{const char *}title=@code{"MathGL"})
+ at deftypefnx {C function} @code{HMGL} mgl_create_graph_fltk (@code{int} (*draw)(@code{HMGL} gr, @code{void *}p), @code{const char *}title, @code{void *}par, @code{void} (*reload)(@code{HMGL} gr, @code{void *}p))
+
+Creates a FLTK-based window for plotting. Parameter @var{draw} sets a pointer to drawing function (this is the name of function) or instance of @ref{mglDraw class}. There is support of a list of plots (frames). So as one can prepare a set of frames at first and redraw it fast later (but it requires more memory). Function should return positive number of frames for the list or zero if it will plot directly. Note, that @var{draw} can be @code{NULL} for displaying static bitmaps only (no an [...]
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglFLTK}} @code{int} RunThr ()
+ at deftypefnx {C function} @code{int} mgl_fltk_thr ()
+Run main loop for event handling in separate thread. Note, right now it work for FLTK windows only.
+ at end deftypefn
+
+
+ at deftypefn {Constructor on @code{mglQT}} {} mglQT (@code{const char *}title=@code{"MathGL"})
+ at deftypefnx {Constructor on @code{mglQT}} {} mglQT (@code{int} (*draw)(@code{HMGL} gr, @code{void *}p), @code{const char *}title=@code{"MathGL"}, @code{void *}par=@code{NULL}, @code{void} (*reload)(@code{HMGL} gr, @code{void *}p)=0)
+ at deftypefnx {Constructor on @code{mglQT}} {} mglQT (@code{int} (*draw)(@code{mglGraph *}gr), @code{const char *}title=@code{"MathGL"})
+ at deftypefnx {Constructor on @code{mglQT}} {} mglQT (@code{mglDraw *}draw, @code{const char *}title=@code{"MathGL"})
+ at deftypefnx {C function} @code{HMGL} mgl_create_graph_qt (@code{int} (*draw)(@code{HMGL} gr, @code{void *}p), @code{const char *}title, @code{void *}par, @code{void} (*reload)(@code{HMGL} gr, @code{void *}p))
+
+Creates a FLTK-based window for plotting. Parameter @var{draw} sets a pointer to drawing function (this is the name of function) or instance of @ref{mglDraw class}. There is support of a list of plots (frames). So as one can prepare a set of frames at first and redraw it fast later (but it requires more memory). Function should return positive number of frames for the list or zero if it will plot directly. Note, that @var{draw} can be @code{NULL} for displaying static bitmaps only (no an [...]
+ at end deftypefn
+
+
+ at deftypefn {Constructor on @code{mglGLUT}} {} mglGLUT (@code{const char *}title=@code{"MathGL"})
+ at deftypefnx {Constructor on @code{mglGLUT}} {} mglGLUT (@code{int} (*draw)(@code{HMGL} gr, @code{void *}p), @code{const char *}title=@code{"MathGL"}, @code{void *}par=@code{NULL}, @code{void} (*reload)(@code{HMGL} gr, @code{void *}p)=0)
+ at deftypefnx {Constructor on @code{mglGLUT}} {} mglGLUT (@code{int} (*draw)(@code{mglGraph *}gr), @code{const char *}title=@code{"MathGL"})
+ at deftypefnx {Constructor on @code{mglGLUT}} {} mglGLUT (@code{mglDraw *}draw, @code{const char *}title=@code{"MathGL"})
+ at deftypefnx {C function} @code{HMGL} mgl_create_graph_glut (@code{int} (*draw)(@code{HMGL} gr, @code{void *}p), @code{const char *}title, @code{void *}par, @code{void} (*reload)(@code{HMGL} gr, @code{void *}p))
+
+Creates a GLUT-based window for plotting. Parameter @var{draw} sets a pointer to drawing function (this is the name of function) or instance of @code{mglDraw} class. There is support of a list of plots (frames). So as one can prepare a set of frames at first and redraw it fast later (but it requires more memory). Function should return positive number of frames for the list or zero if it will plot directly. Note, that @var{draw} can be @code{NULL} for displaying static bitmaps only (no a [...]
+
+There are some keys handles for manipulating by the plot: 'a', 'd', 'w', 's' for the rotating; ',', '.' for viewing of the previous or next frames in the list; 'r' for the switching of transparency; 'f' for the switching of lightning; 'x' for hiding (closing) the window.
+ at end deftypefn
+
+ at menu
+* mglWnd class::
+* mglDraw class::
+* Fl_MathGL class::
+* QMathGL class::
+* wxMathGL class::
+ at end menu
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node mglWnd class, mglDraw class, , Widget classes
+ at section mglWnd class
+ at nav{}
+ at cindex mglWnd
+ at cindex window
+ at c @cindex mglDraw
+
+This class is abstract class derived from mglGraph class (see @ref{MathGL core}). It is defined in @code{#include <mgl2/wnd.h>} and provide base methods for handling window with MathGL graphics. Inherited classes are exist for QT and FLTK widget libraries: @code{mglQT} in @code{#include <mgl2/qt.h>}, @code{mglFLTK} in @code{#include <mgl2/fltk.h>}.
+
+
+ at deftypefn {Method on @code{mglWnd}} @code{int} Run ()
+ at deftypefnx {C function} @code{int} mgl_qt_run ()
+ at deftypefnx {C function} @code{int} mgl_fltk_run ()
+Run main loop for event handling. Usually it should be called in a separate thread or as last function call in @code{main()}.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglWnd}} @code{void} SetDrawFunc (@code{int} (*draw)(@code{HMGL} gr, @code{void *}p), @code{void *}par=@code{NULL}, @code{void} (*reload)(@code{void *}p)=@code{NULL})
+ at deftypefnx {Method on @code{mglWnd}} @code{void} SetDrawFunc (@code{int} (*draw)(@code{mglGraph *}gr))
+ at deftypefnx {Method on @code{mglWnd}} @code{void} SetDrawFunc (@code{mglDraw *}obj)
+ at deftypefnx {C function} @code{void} mgl_wnd_set_func (@code{HMGL} gr, @code{int} (*draw)(@code{HMGL} gr, @code{void *}p), @code{void *}par, @code{void} (*reload)(@code{void *}p))
+Set callback functions for drawing (@var{draw}) and data reloading (@var{reload}), or instance @var{obj} of a class derived from @code{mglDraw}.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglWnd}} @code{void} SetClickFunc (@code{void} (*func)(@code{HMGL} gr, @code{void *}p))
+ at deftypefnx {C function} @code{void} mgl_set_click_func (@code{void} (*func)(@code{HMGL} gr, @code{void *}p))
+Set callback function @var{func} which will be called on mouse click.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglWnd}} @code{void} SetMutex(@code{pthread_mutex_t *}mutex)
+ at deftypefnx {C function} @code{void} mgl_wnd_set_mutex(@code{HMGL} gr, @code{pthread_mutex_t *}mutex)
+Set external mutex for lock/unlock external calculations by widget. This functions is called automatically at using @ref{mglDraw class}.
+ at end deftypefn
+
+
+ at deftypefn {Method on @code{mglWnd}} @code{void} ToggleAlpha ()
+ at deftypefnx {C function} @code{void} mgl_wnd_toggle_alpha (@code{HMGL} gr)
+Switch on/off transparency but do not overwrite switches in user drawing function.
+ at end deftypefn
+ at deftypefn {Method on @code{mglWnd}} @code{void} ToggleLight ()
+ at deftypefnx {C function} @code{void} mgl_wnd_toggle_light (@code{HMGL} gr)
+Switch on/off lighting but do not overwrite switches in user drawing function.
+ at end deftypefn
+ at deftypefn {Method on @code{mglWnd}} @code{void} ToggleRotate ()
+ at deftypefnx {C function} @code{void} mgl_wnd_toggle_rotate (@code{HMGL} gr)
+Switch on/off rotation by mouse. Usually, left button is used for rotation, middle button for shift, right button for zoom/perspective.
+ at end deftypefn
+ at deftypefn {Method on @code{mglWnd}} @code{void} ToggleZoom ()
+ at deftypefnx {C function} @code{void} mgl_wnd_toggle_zoom (@code{HMGL} gr)
+Switch on/off zooming by mouse. Just select rectangular region by mouse and it will be zoomed in.
+ at end deftypefn
+ at deftypefn {Method on @code{mglWnd}} @code{void} ToggleNo ()
+ at deftypefnx {C function} @code{void} mgl_wnd_toggle_no (@code{HMGL} gr)
+Switch off all zooming and rotation and restore initial state.
+ at end deftypefn
+ at deftypefn {Method on @code{mglWnd}} @code{void} Update ()
+ at deftypefnx {C function} @code{void} mgl_wnd_update (@code{HMGL} gr)
+Update window contents. This is very useful function for manual updating the plot while long calculation was running in parallel thread.
+ at end deftypefn
+ at deftypefn {Method on @code{mglWnd}} @code{void} ReLoad ()
+ at deftypefnx {C function} @code{void} mgl_wnd_reload (@code{HMGL} gr)
+Reload user data and update picture. This function also update number of frames which drawing function can create.
+ at end deftypefn
+ at deftypefn {Method on @code{mglWnd}} @code{void} Adjust ()
+ at deftypefnx {C function} @code{void} mgl_wnd_adjust (@code{HMGL} gr)
+Adjust size of bitmap to window size.
+ at end deftypefn
+ at deftypefn {Method on @code{mglWnd}} @code{void} NextFrame ()
+ at deftypefnx {C function} @code{void} mgl_wnd_next_frame (@code{HMGL} gr)
+Show next frame if one.
+ at end deftypefn
+ at deftypefn {Method on @code{mglWnd}} @code{void} PrevFrame ()
+ at deftypefnx {C function} @code{void} mgl_wnd_prev_frame (@code{HMGL} gr)
+Show previous frame if one.
+ at end deftypefn
+ at deftypefn {Method on @code{mglWnd}} @code{void} Animation ()
+ at deftypefnx {C function} @code{void} mgl_wnd_animation (@code{HMGL} gr)
+Run/stop slideshow (animation) of frames.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglWnd}} @code{void} SetDelay (@code{double} dt)
+ at deftypefnx {C function} @code{void} mgl_wnd_set_delay (@code{HMGL} gr, @code{double} dt)
+Sets delay for animation in seconds. Default value is 1 sec.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglWnd}} @code{double} GetDelay ()
+ at deftypefnx {C function} @code{double} mgl_wnd_get_delay (@code{HMGL} gr)
+Gets delay for animation in seconds.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglWnd}} @code{void} Setup (@code{bool} clfupd=@code{true}, @code{bool} showpos=@code{false})
+ at deftypefnx {C function} @code{void} mgl_setup_window (@code{HMGL} gr, @code{bool} clfupd, @code{bool} showpos)
+Enable/disable flags for:
+ at itemize @bullet
+ at item
+clearing plot before Update();
+ at item
+showing the last mouse click position in the widget.
+ at end itemize
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglWnd}} @code{mglPoint} LastMousePos ()
+ at deftypefnx {C function} @code{void} mgl_get_last_mouse_pos (@code{HMGL} gr, @code{mreal *}x, @code{mreal *}y, @code{mreal *}z)
+Gets last position of mouse click.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglWnd}} @code{void *} Widget ()
+ at deftypefnx {C function} @code{void *} mgl_fltk_widget (@code{HMGL} gr)
+ at deftypefnx {C function} @code{void *} mgl_qt_widget (@code{HMGL} gr)
+Return pointer to widget (@ref{Fl_MathGL class} or @ref{QMathGL class}) used for plotting.
+ at end deftypefn
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node mglDraw class, Fl_MathGL class, mglWnd class, Widget classes
+ at section mglDraw class
+ at nav{}
+ at cindex mglDraw
+
+This class provide base functionality for callback drawing and running calculation in separate thread. It is defined in @code{#include <mgl2/wnd.h>}. You should make inherited class and implement virtual functions if you need it.
+
+ at deftypefn {Virtual method on @code{mglDraw}} @code{int} Draw (@code{mglGraph *}gr)
+This is callback drawing function, which will be called when any redrawing is required for the window. There is support of a list of plots (frames). So as one can prepare a set of frames at first and redraw it fast later (but it requires more memory). Function should return positive number of frames for the list or zero if it will plot directly. 
+ at end deftypefn
+
+ at deftypefn {Virtual method on @code{mglDraw}} @code{void} Reload ()
+This is callback function, which will be called if user press menu or toolbutton to reload data. 
+ at end deftypefn
+
+ at deftypefn {Virtual method on @code{mglDraw}} @code{void} Click ()
+This is callback function, which will be called if user click mouse. 
+ at end deftypefn
+
+ at deftypefn {Virtual method on @code{mglDraw}} @code{void} Calc ()
+This is callback function, which will be called if user start calculations in separate thread by calling @code{mglDraw::Run()} function. It should periodically call @code{mglDraw::Check()} function to check if calculations should be paused. 
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglDraw}} @code{void} Run ()
+Runs @code{mglDraw::Calc()} function in separate thread. It also initialize @code{mglDraw::thr} variable and unlock @code{mglDraw::mutex}. Function is present only if FLTK support for widgets was enabled.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglDraw}} @code{void} Cancel ()
+Cancels thread with calculations. Function is present only if FLTK support for widgets was enabled.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglDraw}} @code{void} Pause ()
+Pauses thread with calculations by locking @code{mglDraw::mutex}. You should call @code{mglDraw::Continue()} to continue calculations. Function is present only if FLTK support for widgets was enabled.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglDraw}} @code{void} Continue ()
+Continues calculations by unlocking @code{mglDraw::mutex}. Function is present only if FLTK support for widgets was enabled.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglDraw}} @code{void} Continue ()
+Checks if calculations should be paused and pause it. Function is present only if FLTK support for widgets was enabled.
+ at end deftypefn
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Fl_MathGL class, QMathGL class, mglDraw class, Widget classes
+ at section Fl_MathGL class
+ at nav{}
+ at cindex Fl_MathGL
+ at cindex widgets
+
+Class is FLTK widget which display MathGL graphics. It is defined in @code{#include <mgl2/Fl_MathGL.h>}.
+
+ at fig{fltk, Example of FLTK window with MathGL plot.}
+
+ at deftypemethod Fl_MathGL @code{void} set_draw (@code{int} (*draw)(@code{HMGL} gr, @code{void *}p))
+ at deftypemethodx Fl_MathGL @code{void} set_draw (@code{int} (*draw)(@code{mglGraph *}gr))
+ at deftypemethodx Fl_MathGL @code{void} set_draw (@code{mglDraw *}draw)
+Sets drawing function as global function or as one from a class @code{mglDraw}. There is support of a list of plots (frames). So as one can prepare a set of frames at first and redraw it fast later (but it requires more memory). Function should return positive number of frames for the list or zero if it will plot directly. Parameter @var{par} contains pointer to data for the plotting function @var{draw}.
+ at end deftypemethod
+ at deftypemethod Fl_MathGL @code{mglDraw *}get_class ()
+Get pointer to @code{mglDraw} class or @code{NULL} if absent.
+ at end deftypemethod
+
+ at deftypemethod Fl_MathGL @code{void} update ()
+Update (redraw) plot.
+ at end deftypemethod
+ at deftypemethod Fl_MathGL @code{void} set_angle (@code{mreal} t, @code{mreal} p)
+Set angles for additional plot rotation
+ at end deftypemethod
+ at deftypemethod Fl_MathGL @code{void} set_flag (@code{int} f)
+Set bitwise flags for general state (1-Alpha, 2-Light)
+ at end deftypemethod
+ at deftypemethod Fl_MathGL @code{void} set_state (@code{bool} r, @code{bool} z)
+Set flags for handling mouse:
+ at var{z}=@code{true} allow zooming,
+ at var{r}=@code{true} allow rotation/shifting/perspective and so on.
+ at end deftypemethod
+
+ at deftypemethod Fl_MathGL @code{void} set_zoom (@code{mreal} X1, @code{mreal} Y1, @code{mreal} X2, @code{mreal} Y2)
+Set zoom in/out region
+ at end deftypemethod
+ at deftypemethod Fl_MathGL @code{void} get_zoom (@code{mreal *}X1, @code{mreal *}Y1, @code{mreal *}X2, @code{mreal *}Y2)
+Get zoom in/out region
+ at end deftypemethod
+
+ at deftypemethod Fl_MathGL @code{void} set_popup (@code{const Fl_Menu_Item *}pmenu, @code{Fl_Widget *}w, @code{void *}v)
+Set popup menu pointer
+ at end deftypemethod
+
+ at deftypemethod Fl_MathGL @code{void} set_graph (@code{HMGL} gr)
+ at deftypemethodx Fl_MathGL @code{void} set_graph (@code{mglGraph *}gr)
+Set new grapher instead of built-in one. Note that Fl_MathGL will automatically delete this object at destruction or at new @code{set_graph()} call.
+ at end deftypemethod
+ at deftypemethod Fl_MathGL @code{HMGL} get_graph ()
+Get pointer to grapher.
+ at end deftypemethod
+
+ at deftypemethod Fl_MathGL @code{void} set_show_warn (@code{bool} val)
+Show window with warnings after script parsing.
+ at end deftypemethod
+ at deftypemethod Fl_MathGL @code{void} stop (@code{bool} stop=@code{true})
+Ask to stop of script parsing.
+ at end deftypemethod
+ at deftypemethod Fl_MathGL @code{void} set_handle_key (@code{bool} val)
+Enable/disable key handling as in mglview (default is false).
+ at end deftypemethod
+ at deftypemethod Fl_MathGL @code{int} get_last_id ()
+Get id of last clicked object.
+ at end deftypemethod
+ at deftypemethod Fl_MathGL @code{bool} running ()
+Check if script is parsing now or not.
+ at end deftypemethod
+
+ at deftypecv {Fl_MathGL option} Fl_MathGL @code{Fl_Valuator *} tet_val
+Pointer to external tet-angle validator.
+ at end deftypecv
+ at deftypecv {Fl_MathGL option} Fl_MathGL @code{Fl_Valuator *} phi_val
+Pointer to external phi-angle validator.
+ at end deftypecv
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node QMathGL class, wxMathGL class, Fl_MathGL class, Widget classes
+ at section QMathGL class
+ at nav{}
+ at cindex QMathGL
+ at cindex widgets
+
+Class is Qt widget which display MathGL graphics. It is defined in @code{#include <mgl2/qt.h>}.
+
+ at fig{qt, Example of Qt window with MathGL plot.}
+
+ at deftypemethod QMathGL @code{void} setDraw (@code{mglDraw *}dr)
+Sets drawing functions from a class inherited from @code{mglDraw}.
+ at end deftypemethod
+ at deftypemethod QMathGL @code{void} setDraw (@code{int (*}draw at code{)(mglBase *}gr, @code{void *}p at code{)}, @code{void *}par=@code{NULL})
+ at deftypemethodx QMathGL @code{void} setDraw (@code{int (*}draw at code{)(mglGraph *}gr at code{)})
+Sets the drawing function @var{draw}. There is support of a list of plots (frames). So as one can prepare a set of frames at first and redraw it fast later (but it requires more memory). Function should return positive number of frames for the list or zero if it will plot directly. Parameter @var{par} contains pointer to data for the plotting function @var{draw}.
+ at end deftypemethod
+
+ at deftypemethod QMathGL @code{void} setGraph (@code{HMGL} gr)
+ at deftypemethodx QMathGL @code{void} setGraph (@code{mglGraph *}gr)
+Set pointer to external grapher (instead of built-in one). Note that QMathGL will automatically delete this object at destruction or at new @code{setGraph()} call.
+ at end deftypemethod
+ at deftypemethod QMathGL @code{HMGL} getGraph ()
+Get pointer to grapher.
+ at end deftypemethod
+
+ at deftypemethod QMathGL @code{void} setPopup (@code{QMenu *}p)
+Set popup menu pointer.
+ at end deftypemethod
+ at deftypemethod QMathGL @code{void} setSize (@code{int} w, @code{int} h)
+Set widget/picture sizes
+ at end deftypemethod
+ at deftypemethod QMathGL @code{double} getRatio ()
+Return aspect ratio of the picture.
+ at end deftypemethod
+
+ at deftypemethod QMathGL @code{int} getPer ()
+Get perspective value in percents.
+ at end deftypemethod
+ at deftypemethod QMathGL @code{int} getPhi ()
+Get Phi-angle value in degrees.
+ at end deftypemethod
+ at deftypemethod QMathGL @code{int} getTet ()
+Get Theta-angle value in degrees.
+ at end deftypemethod
+ at deftypemethod QMathGL @code{bool} getAlpha ()
+Get transparency state.
+ at end deftypemethod
+ at deftypemethod QMathGL @code{bool} getLight ()
+Get lightning state.
+ at end deftypemethod
+ at deftypemethod QMathGL @code{bool} getZoom ()
+Get mouse zooming state.
+ at end deftypemethod
+ at deftypemethod QMathGL @code{bool} getRotate ()
+Get mouse rotation state.
+ at end deftypemethod
+
+
+ at deftypefn {Slot on @code{QMathGL}} @code{void} refresh ()
+Redraw saved bitmap without executing drawing function.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} update ()
+Update picture by executing drawing function.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} copy ()
+Copy graphics to clipboard.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} copyClickCoor ()
+Copy coordinates of click (as text).
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} print ()
+Print current picture.
+ at end deftypefn
+
+ at deftypefn {Slot on @code{QMathGL}} @code{void} stop ()
+Send signal to stop drawing.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} adjust ()
+Adjust image size to fit whole widget.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} nextSlide ()
+Show next slide.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} prevSlide ()
+Show previous slide.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} animation (@code{bool} st=@code{true})
+Start/stop animation.
+ at end deftypefn
+
+ at deftypefn {Slot on @code{QMathGL}} @code{void} setPer (@code{int} val)
+Set perspective value.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} setPhi (@code{int} val)
+Set Phi-angle value.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} setTet (@code{int} val)
+Set Theta-angle value.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} setAlpha (@code{bool} val)
+Switch on/off transparency.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} setLight (@code{bool} val)
+Switch on/off lightning.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} setGrid (@code{bool} val)
+Switch on/off drawing of grid for absolute coordinates.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} setZoom (@code{bool} val)
+Switch on/off mouse zooming.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} setRotate (@code{bool} val)
+Switch on/off mouse rotation.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} zoomIn ()
+Zoom in graphics.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} zoomOut ()
+Zoom out graphics.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} shiftLeft ()
+Shift graphics to left direction.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} shiftRight ()
+Shift graphics to right direction.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} shiftUp ()
+Shift graphics to up direction.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} shiftDown ()
+Shift graphics to down direction.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} restore ()
+Restore zoom and rotation to default values.
+ at end deftypefn
+ at c @deftypefn {Slot on @code{QMathGL}} @code{void} reload ()
+ at c Reload data and redraw graphics.
+ at c @end deftypefn
+
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportPNG (@code{QString} fname=@code{""})
+Export current picture to PNG file.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportPNGs (@code{QString} fname=@code{""})
+Export current picture to PNG file (no transparency).
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportJPG (@code{QString} fname=@code{""})
+Export current picture to JPEG file.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportBPS (@code{QString} fname=@code{""})
+Export current picture to bitmap EPS file.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportEPS (@code{QString} fname=@code{""})
+Export current picture to vector EPS file.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportSVG (@code{QString} fname=@code{""})
+Export current picture to SVG file.
+ at end deftypefn
+
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportGIF (@code{QString} fname=@code{""})
+Export current picture to GIF file.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportTEX (@code{QString} fname=@code{""})
+Export current picture to LaTeX/Tikz file.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportTGA (@code{QString} fname=@code{""})
+Export current picture to TGA file.
+ at end deftypefn
+
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportXYZ (@code{QString} fname=@code{""})
+Export current picture to XYZ/XYZL/XYZF file.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportOBJ (@code{QString} fname=@code{""})
+Export current picture to OBJ/MTL file.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportSTL (@code{QString} fname=@code{""})
+Export current picture to STL file.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportOFF (@code{QString} fname=@code{""})
+Export current picture to OFF file.
+ at end deftypefn
+ at c @deftypefn {Slot on @code{QMathGL}} @code{void} exportX3D (@code{QString} fname=@code{""})
+ at c Export current picture to X3D file.
+ at c @end deftypefn
+
+ at deftypefn {Slot on @code{QMathGL}} @code{void}setUsePrimitives (@code{bool} use)
+Enable using list of primitives for frames. This allows frames transformation/zoom but requires much more memory. Default value is @code{true}.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} setMGLFont (@code{QString} path)
+Restore (@var{path}=@code{""}) or load font for graphics.
+ at end deftypefn
+
+ at deftypefn {Slot on @code{QMathGL}} @code{void} about ()
+Show about information.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} aboutQt ()
+Show information about Qt version.
+ at end deftypefn
+
+ at deftypefn {Signal on @code{QMathGL}} @code{void} phiChanged (@code{int} val)
+Phi angle changed (by mouse or by toolbar).
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} tetChanged (@code{int} val)
+Tet angle changed (by mouse or by toolbar).
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} perChanged (@code{int} val)
+Perspective changed (by mouse or by toolbar).
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} alphaChanged (@code{bool} val)
+Transparency changed (by toolbar).
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} lightChanged (@code{bool} val)
+Lighting changed (by toolbar).
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} gridChanged (@code{bool} val)
+Grid drawing changed (by toolbar).
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} zoomChanged (@code{bool} val)
+Zooming changed (by toolbar).
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} rotateChanged (@code{bool} val)
+Rotation changed (by toolbar).
+ at end deftypefn
+
+ at deftypefn {Signal on @code{QMathGL}} @code{void} mouseClick (@code{mreal} x, @code{mreal} y, @code{mreal} z)
+Mouse click take place at position @{x,y,z@}.
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} frameChanged (@code{int} val)
+Need another frame to show.
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} showWarn (@code{QString} warn)
+Need to show warning.
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} posChanged (@code{QString} pos)
+Position of mouse click is changed.
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} objChanged (@code{int} id)
+Object id is changed (due to mouse click).
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} refreshData ()
+Data can be changed (drawing is finished).
+ at end deftypefn
+
+
+ at deftypecv {QMathGL option} QMathGL @code{QString} appName
+Application name for message boxes.
+ at end deftypecv
+ at deftypecv {QMathGL option} QMathGL @code{bool} autoResize
+Allow auto resizing (default is false).
+ at end deftypecv
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node wxMathGL class, , QMathGL class, Widget classes
+ at section wxMathGL class
+ at nav{}
+ at cindex wxMathGL
+ at cindex widgets
+
+Class is WX widget which display MathGL graphics. It is defined in @code{#include <mgl2/wx.h>}.
+
+ at deftypemethod wxMathGL @code{void} SetDraw (@code{mglDraw *}dr)
+Sets drawing functions from a class inherited from @code{mglDraw}.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} SetDraw (@code{int (*}draw at code{)(mglBase *}gr, @code{void *}p at code{)}, @code{void *}par=@code{NULL})
+ at deftypemethodx wxMathGL @code{void} SetDraw (@code{int (*}draw at code{)(mglGraph *}gr at code{)})
+Sets the drawing function @var{draw}. There is support of a list of plots (frames). So as one can prepare a set of frames at first and redraw it fast later (but it requires more memory). Function should return positive number of frames for the list or zero if it will plot directly. Parameter @var{par} contains pointer to data for the plotting function @var{draw}.
+ at end deftypemethod
+
+ at deftypemethod wxMathGL @code{void} SetGraph (@code{HMGL} gr)
+ at deftypemethodx wxMathGL @code{void} SetGraph (@code{mglGraph *}gr)
+Set pointer to external grapher (instead of built-in one). Note that wxMathGL will automatically delete this object at destruction or at new @code{setGraph()} call.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{HMGL} GetGraph ()
+Get pointer to grapher.
+ at end deftypemethod
+
+ at deftypemethod wxMathGL @code{void} SetPopup (@code{wxMenu *}p)
+Set popup menu pointer.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} SetSize (@code{int} w, @code{int} h)
+Set widget/picture sizes
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{double} GetRatio ()
+Return aspect ratio of the picture.
+ at end deftypemethod
+
+ at deftypemethod wxMathGL @code{int} GetPer ()
+Get perspective value in percents.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{int} GetPhi ()
+Get Phi-angle value in degrees.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{int} GetTet ()
+Get Theta-angle value in degrees.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{bool} GetAlpha ()
+Get transparency state.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{bool} GetLight ()
+Get lightning state.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{bool} GetZoom ()
+Get mouse zooming state.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{bool} GetRotate ()
+Get mouse rotation state.
+ at end deftypemethod
+
+
+ at deftypemethod wxMathGL @code{void} Repaint ()
+Redraw saved bitmap without executing drawing function.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} Update ()
+Update picture by executing drawing function.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} Copy ()
+Copy graphics to clipboard.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} Print ()
+Print current picture.
+ at end deftypemethod
+
+ at comment  @deftypemethod wxMathGL @code{void} Stop ()
+ at comment  Send signal to stop drawing.
+ at comment  @end deftypemethod
+ at deftypemethod wxMathGL @code{void} Adjust ()
+Adjust image size to fit whole widget.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} NextSlide ()
+Show next slide.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} PrevSlide ()
+Show previous slide.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} Animation (@code{bool} st=@code{true})
+Start/stop animation.
+ at end deftypemethod
+
+ at deftypemethod wxMathGL @code{void} SetPer (@code{int} val)
+Set perspective value.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} SetPhi (@code{int} val)
+Set Phi-angle value.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} SetTet (@code{int} val)
+Set Theta-angle value.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} SetAlpha (@code{bool} val)
+Switch on/off transparency.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} SetLight (@code{bool} val)
+Switch on/off lightning.
+ at end deftypemethod
+ at comment  @deftypemethod wxMathGL @code{void} SetGrid (@code{bool} val)
+ at comment  Switch on/off drawing of grid for absolute coordinates.
+ at comment  @end deftypemethod
+ at deftypemethod wxMathGL @code{void} SetZoom (@code{bool} val)
+Switch on/off mouse zooming.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} SetRotate (@code{bool} val)
+Switch on/off mouse rotation.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} ZoomIn ()
+Zoom in graphics.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} ZoomOut ()
+Zoom out graphics.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} ShiftLeft ()
+Shift graphics to left direction.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} ShiftRight ()
+Shift graphics to right direction.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} ShiftUp  ()
+Shift graphics to up direction.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} ShiftDown ()
+Shift graphics to down direction.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} Restore ()
+Restore zoom and rotation to default values.
+ at end deftypemethod
+ at c @deftypemethod wxMathGL @code{void} reload ()
+ at c Reload data and redraw graphics.
+ at c @end deftypemethod
+
+ at deftypemethod wxMathGL @code{void} About ()
+Show about information.
+ at end deftypemethod
+
+ at deftypemethod wxMathGL @code{void} ExportPNG (@code{QString} fname=@code{""})
+Export current picture to PNG file.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} ExportPNGs (@code{QString} fname=@code{""})
+Export current picture to PNG file (no transparency).
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} ExportJPG (@code{QString} fname=@code{""})
+Export current picture to JPEG file.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} ExportBPS (@code{QString} fname=@code{""})
+Export current picture to bitmap EPS file.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} ExportEPS (@code{QString} fname=@code{""})
+Export current picture to vector EPS file.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} ExportSVG (@code{QString} fname=@code{""})
+Export current picture to SVG file.
+ at end deftypemethod
+
+ at external{}
+
diff --git a/texinfo/widget_ru.texi b/texinfo/widget_ru.texi
new file mode 100644
index 0000000..ac1fe0a
--- /dev/null
+++ b/texinfo/widget_ru.texi
@@ -0,0 +1,727 @@
+
+ at c ------------------------------------------------------------------
+ at chapter ``Оконные'' классы
+ at nav{}
+ at cindex mglWnd
+ at cindex mglGLUT
+ at cindex Fl_MathGL
+ at cindex QMathGL
+ at cindex window
+ at cindex widgets
+
+Есть целый набор ``оконных'' классов для создания окон с графикой MathGL: @code{mglWnd} и @code{mglGLUT} для окон целиком, @code{Fl_MathGL} и @code{QMathGL} для виджетов. Все эти классы позволяют пользователю просмотривать, вращать, экспортировать рисунок. Большинство из них (кроме @code{mglGLUT}) имеют панель инструментов для упрощения изменения графика. Все оконные классы имеют схожий набор функций. Ниже приведен список классов с краткими комментариями.
+
+Для рисования можно использовать: указатель @code{NULL} если планируется обновлять график вручную, глобальную функцию типа @code{int draw(@code{HMGL} gr, @code{void *}p)} или @code{int draw(@code{mglGraph *}gr)}, или экземпляр класса, производного от @ref{mglDraw class}. Этот класс определен в @code{#include <mgl2/wnd.h>} и имеет 2 основных виртуальных метода:
+ at verbatim
+class mglDraw
+{
+public:
+    virtual int Draw(mglGraph *) { return 0; };
+    virtual void Reload() {};
+};
+ at end verbatim
+Вам следует наследовать свой класс от @code{mglDraw} и определить один или оба метода.
+
+Непосредственно окна можно создать используя один из следующих классов (см. @ref{Using MathGL window} для примеров).
+
+
+ at deftypefn {Конструктор класса @code{mglFLTK}} {} mglFLTK (@code{const char *}title=@code{"MathGL"})
+ at deftypefnx {Конструктор класса @code{mglFLTK}} {} mglFLTK (@code{int} (*draw)(@code{HMGL} gr, @code{void *}p), @code{const char *}title=@code{"MathGL"}, @code{void *}par=@code{NULL}, @code{void} (*reload)(@code{HMGL} gr, @code{void *}p)=0)
+ at deftypefnx {Конструктор класса @code{mglFLTK}} {} mglFLTK (@code{int} (*draw)(@code{mglGraph *}gr), @code{const char *}title=@code{"MathGL"})
+ at deftypefnx {Конструктор класса @code{mglFLTK}} {} mglFLTK (@code{mglDraw *}draw, @code{const char *}title=@code{"MathGL"})
+ at deftypefnx {Функция С} @code{HMGL} mgl_create_graph_fltk (@code{int} (*draw)(@code{HMGL} gr, @code{void *}p), @code{const char *}title, @code{void *}par, @code{void} (*reload)(@code{HMGL} gr, @code{void *}p))
+
+Создает FLTK окно для вывода графика. Параметр @var{draw} -- указатель (имя) функции рисования. Есть возможность создания нескольких кадров вначале (требует больше памяти) и их быстрая анимации в дальнейшем. В этом случае функция @var{draw} должна возвращать число кадров или ноль для рисования по запросу. Замечу, что @var{draw} может быть равна @code{NULL} для отображения статической (текущей) картинки. Параметр @var{title} задает заголовок окна. Параметр @var{par} содержит указатель на  [...]
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglWnd}} @code{int} RunThr ()
+ at deftypefnx {Функция С} @code{int} mgl_fltk_thr ()
+Запускает цикл обработки сообщений в отдельном потоке. В данный момент работает только для окон FLTK.
+ at end deftypefn
+
+
+ at deftypefn {Конструктор класса @code{mglQT}} {} mglQT (@code{const char *}title=@code{"MathGL"})
+ at deftypefnx {Конструктор класса @code{mglQT}} {} mglQT (@code{int} (*draw)(@code{HMGL} gr, @code{void *}p), @code{const char *}title=@code{"MathGL"}, @code{void *}par=@code{NULL}, @code{void} (*reload)(@code{HMGL} gr, @code{void *}p)=0)
+ at deftypefnx {Конструктор класса @code{mglQT}} {} mglQT (@code{int} (*draw)(@code{mglGraph *}gr), @code{const char *}title=@code{"MathGL"})
+ at deftypefnx {Конструктор класса @code{mglQT}} {} mglQT (@code{mglDraw *}draw, @code{const char *}title=@code{"MathGL"})
+ at deftypefnx {Функция С} @code{HMGL} mgl_create_graph_qt (@code{int} (*draw)(@code{HMGL} gr, @code{void *}p), @code{const char *}title, @code{void *}par, @code{void} (*reload)(@code{HMGL} gr, @code{void *}p))
+
+Создает Qt окно для вывода графика. Параметр @var{draw} -- указатель (имя) функции рисования. Есть возможность создания нескольких кадров вначале (требует больше памяти) и их быстрая анимации в дальнейшем. В этом случае функция @var{draw} должна возвращать число кадров или ноль для рисования по запросу. Замечу, что @var{draw} может быть равна @code{NULL} для отображения статической (текущей) картинки. Параметр @var{title} задает заголовок окна. Параметр @var{par} содержит указатель на да [...]
+ at end deftypefn
+
+
+ at deftypefn {Конструктор класса @code{mglGLUT}} {} mglGLUT (@code{const char *}title=@code{"MathGL"})
+ at deftypefnx {Конструктор класса @code{mglGLUT}} {} mglGLUT (@code{int} (*draw)(@code{HMGL} gr, @code{void *}p), @code{const char *}title=@code{"MathGL"}, @code{void *}par=@code{NULL}, @code{void} (*reload)(@code{HMGL} gr, @code{void *}p)=0)
+ at deftypefnx {Конструктор класса @code{mglGLUT}} {} mglGLUT (@code{int} (*draw)(@code{mglGraph *}gr), @code{const char *}title=@code{"MathGL"})
+ at deftypefnx {Конструктор класса @code{mglGLUT}} {} mglGLUT (@code{mglDraw *}draw, @code{const char *}title=@code{"MathGL"})
+ at deftypefnx {Функция С} @code{HMGL} mgl_create_graph_glut (@code{int} (*draw)(@code{HMGL} gr, @code{void *}p), @code{const char *}title, @code{void *}par, @code{void} (*reload)(@code{HMGL} gr, @code{void *}p))
+
+Создает окно для вывода графика. Параметр @var{draw} -- указатель (имя) функции рисования. Есть возможность создания нескольких кадров вначале (требует больше памяти) и их быстрая анимации в дальнейшем. В этом случае функция @var{draw} должна возвращать число кадров или ноль для рисования по запросу. Замечу, что @var{draw} может быть равна @code{NULL} для отображения статической (текущей) картинки. Параметр @var{title} задает заголовок окна. Параметр @var{par} содержит указатель на данны [...]
+
+В окне просмотра можно использовать клавиши: 'a', 'd', 'w', 's' для вращения; ',', '.' для просмотра предыдущего и следующего кадров; 'r' для переключения прозрачности; 'f' для переключения оспещенности; 'x' для закрытия окна.
+ at end deftypefn
+
+
+
+ at menu
+* mglWnd class::
+* mglDraw class::
+* Fl_MathGL class::
+* QMathGL class::
+* wxMathGL class::
+ at end menu
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node mglWnd class, Fl_MathGL class, , Widget classes
+ at section Класс mglWnd
+ at nav{}
+ at cindex mglWnd
+ at cindex window
+ at c @cindex mglDraw
+
+Это абстрактный класс производный от класса mglGraph (см. @ref{MathGL core}). Он определен в @code{#include <mgl2/wnd.h>}. Класс содержит методы для создания и управления окном, содержащим графику MathGL. Производные от него классы существует отдельно для каждой библиотеки виджетов: @code{mglQT} в @code{#include <mgl2/qt.h>}, @code{mglFLTK} в @code{#include <mgl2/fltk.h>}.
+
+ at deftypefn {Метод класса @code{mglWnd}} @code{int} Run ()
+ at deftypefnx {Функция С} @code{int} mgl_qt_run ()
+ at deftypefnx {Функция С} @code{int} mgl_fltk_run ()
+Запускает цикл обработки сообщений. Обычно эта функция должна вызываться в отдельном потоке или последней функцией в @code{main()}.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglWnd}} @code{void} SetDrawFunc (@code{int} (*draw)(@code{HMGL} gr, @code{void *}p), @code{void *}par=@code{NULL}, @code{void} (*reload)(@code{void *}p)=@code{NULL})
+ at deftypefnx {Метод класса @code{mglWnd}} @code{void} SetDrawFunc (@code{int} (*draw)(@code{mglGraph *}gr))
+ at deftypefnx {Метод класса @code{mglWnd}} @code{void} SetDrawFunc (@code{mglDraw *}obj)
+ at deftypefnx {Функция С} @code{void} mgl_wnd_set_func (@code{HMGL} gr, @code{int} (*draw)(@code{HMGL} gr, @code{void *}p), @code{void *}par, @code{void} (*reload)(@code{void *}p))
+Устанавливает функцию, которая будет вызвана при перерисовке (@var{draw}) и при повторной загрузке данных (@var{reload}), или объект @var{obj} класса, производного от @code{mglDraw}.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglWnd}} @code{void} SetClickFunc (@code{void} (*func)(@code{HMGL} gr, @code{void *}p))
+ at deftypefnx {Функция С} @code{void} mgl_set_click_func (@code{void} (*func)(@code{HMGL} gr, @code{void *}p))
+Устанавливает функцию, которая будет вызвана при щелчке мышью.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglWnd}} @code{void} SetMutex(@code{pthread_mutex_t *}mutex)
+ at deftypefnx {C function} @code{void} mgl_wnd_set_mutex(@code{HMGL} gr, @code{pthread_mutex_t *}mutex)
+Устанавливает внешний mutex для блокировки/разблокировки внешних вычислений с помощью меню или кнопок окна. Функция вызывается автоматически при использовании @ref{mglDraw class}.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglWnd}} @code{void} ToggleAlpha ()
+ at deftypefnx {Функция С} @code{void} mgl_wnd_toggle_alpha (@code{HMGL} gr)
+Включает/выключает прозрачность, но не перекрывает ее включение в пользовательской функции рисования.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglWnd}} @code{void} ToggleLight ()
+ at deftypefnx {Функция С} @code{void} mgl_wnd_toggle_light (@code{HMGL} gr)
+Включает/выключает освещение, но не перекрывает его включение в пользовательской функции рисования.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglWnd}} @code{void} ToggleRotate ()
+ at deftypefnx {Функция С} @code{void} mgl_wnd_toggle_rotate (@code{HMGL} gr)
+Включает/выключает вращение мышкой. Нажатая левая кнопка используется для вращения, средняя для сдвига, правая для приближения/перспективы.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglWnd}} @code{void} ToggleZoom ()
+ at deftypefnx {Функция С} @code{void} mgl_wnd_toggle_zoom (@code{HMGL} gr)
+Включает/выключает приближение мышкой. Выделите прямоугольную область и она будет приближена.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglWnd}} @code{void} ToggleNo ()
+ at deftypefnx {Функция С} @code{void} mgl_wnd_toggle_no (@code{HMGL} gr)
+Выключает вращение и приближение мышкой, а также восстанавливает исходный вид графика.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglWnd}} @code{void} Update ()
+ at deftypefnx {Функция С} @code{void} mgl_wnd_update (@code{HMGL} gr)
+Обновляет содержимое окна. Функция полезна при ручном обновлении содержимого, пока долгий расчет идет в параллельном потоке.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglWnd}} @code{void} ReLoad ()
+ at deftypefnx {Функция С} @code{void} mgl_wnd_reload (@code{HMGL} gr)
+Перегружает данные и обновляет рисунок. Функция также обновляет число кадров, которое создает функция рисования.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglWnd}} @code{void} Adjust ()
+ at deftypefnx {Функция С} @code{void} mgl_wnd_adjust (@code{HMGL} gr)
+Подгоняет размер рисунка под размер окна.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglWnd}} @code{void} NextFrame ()
+ at deftypefnx {Функция С} @code{void} mgl_wnd_next_frame (@code{HMGL} gr)
+Показывает следующий кадр, если он есть.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglWnd}} @code{void} PrevFrame ()
+ at deftypefnx {Функция С} @code{void} mgl_wnd_prev_frame (@code{HMGL} gr)
+Показывает предыдущий кадр, если он есть.
+ at end deftypefn
+ at deftypefn {Метод класса @code{mglWnd}} @code{void} Animation ()
+ at deftypefnx {Функция С} @code{void} mgl_wnd_animation (@code{HMGL} gr)
+Запускает/останавливает анимацию кадров.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglWnd}} @code{void} SetDelay (@code{double} dt)
+ at deftypefnx {Функция С} @code{void} mgl_wnd_set_delay (@code{HMGL} gr, @code{double} dt)
+Задает задержку при анимации в секундах. По умолчанию интервал -- 1 секунда.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglWnd}} @code{double} GetDelay ()
+ at deftypefnx {Функция С} @code{double} mgl_wnd_get_delay (@code{HMGL} gr)
+Возвращает задержку при анимации в секундах.
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglWnd}} @code{void} Setup (@code{bool} clfupd=@code{true}, @code{bool} showpos=@code{false})
+ at deftypefnx {Функция С} @code{void} mgl_setup_window (@code{HMGL} gr, @code{bool} clfupd, @code{bool} showpos)
+Включает/выключает:
+ at itemize @bullet
+ at item
+очистку рисунка перед Update();
+ at item
+показ позиции щелчка мыши на рисунке.
+ at end itemize
+ at end deftypefn
+
+ at deftypefn {Метод класса @code{mglWnd}} @code{mglPoint} LastMousePos ()
+ at deftypefnx {Функция С} @code{void} mgl_get_last_mouse_pos (@code{HMGL} gr, @code{mreal *}x, @code{mreal *}y, @code{mreal *}z)
+Возвращает положение щелчка мыши.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglWnd}} @code{void *} Widget ()
+ at deftypefnx {C function} @code{void *} mgl_fltk_widget (@code{HMGL} gr)
+ at deftypefnx {C function} @code{void *} mgl_qt_widget (@code{HMGL} gr)
+Возвращает указатель на виджет (@ref{Fl_MathGL class} or @ref{QMathGL class}), используемый для рисования.
+ at end deftypefn
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node mglDraw class, Fl_MathGL class, mglWnd class, Widget classes
+ at section mglDraw class
+ at nav{}
+ at cindex mglDraw
+
+This class provide base functionality for callback drawing and running calculation in separate thread. It is defined in @code{#include <mgl2/wnd.h>}. You should make inherited class and implement virtual functions if you need it.
+
+ at deftypefn {Virtual method on @code{mglDraw}} @code{int} Draw (@code{mglGraph *}gr)
+This is callback drawing function, which will be called when any redrawing is required for the window. There is support of a list of plots (frames). So as one can prepare a set of frames at first and redraw it fast later (but it requires more memory). Function should return positive number of frames for the list or zero if it will plot directly. 
+ at end deftypefn
+
+ at deftypefn {Virtual method on @code{mglDraw}} @code{void} Reload ()
+This is callback function, which will be called if user press menu or toolbutton to reload data. 
+ at end deftypefn
+
+ at deftypefn {Virtual method on @code{mglDraw}} @code{void} Click ()
+This is callback function, which will be called if user click mouse. 
+ at end deftypefn
+
+ at deftypefn {Virtual method on @code{mglDraw}} @code{void} Calc ()
+This is callback function, which will be called if user start calculations in separate thread by calling @code{mglDraw::Run()} function. It should periodically call @code{mglDraw::Check()} function to check if calculations should be paused. 
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglDraw}} @code{void} Run ()
+Runs @code{mglDraw::Calc()} function in separate thread. It also initialize @code{mglDraw::thr} variable and unlock @code{mglDraw::mutex}. Function is present only if FLTK support for widgets was enabled.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglDraw}} @code{void} Cancel ()
+Cancels thread with calculations. Function is present only if FLTK support for widgets was enabled.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglDraw}} @code{void} Pause ()
+Pauses thread with calculations by locking @code{mglDraw::mutex}. You should call @code{mglDraw::Continue()} to continue calculations. Function is present only if FLTK support for widgets was enabled.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglDraw}} @code{void} Continue ()
+Continues calculations by unlocking @code{mglDraw::mutex}. Function is present only if FLTK support for widgets was enabled.
+ at end deftypefn
+
+ at deftypefn {Method on @code{mglDraw}} @code{void} Continue ()
+Checks if calculations should be paused and pause it. Function is present only if FLTK support for widgets was enabled.
+ at end deftypefn
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node Fl_MathGL class, QMathGL class, mglDraw class, Widget classes
+ at section Класс Fl_MathGL
+ at nav{}
+ at cindex Fl_MathGL
+ at cindex widgets
+
+Класс реализует элемент интерфейса FLTK для отображения графики MathGL. Он определен в @code{#include <mgl2/Fl_MathGL.h>}.
+
+ at fig{fltk, Пример окна FLTK с графикой MathGL.}
+
+ at deftypemethod Fl_MathGL @code{void} set_draw (@code{int} (*draw)(@code{HMGL} gr, @code{void *}p))
+ at deftypemethodx Fl_MathGL @code{void} set_draw (@code{int} (*draw)(@code{mglGraph *}gr))
+ at deftypemethodx Fl_MathGL @code{void} set_draw (@code{mglDraw *}draw)
+Устанавливает функцию рисования как глобальную функцию или как функцию член класса, производного от @code{mglDraw}. Поддерживается список графиков (кадров), так что можно вначале их нарисовать (требует довольно много памяти), а потом достаточно быстро отображать. Функция должна возвращать положительное число создаваемых кадров или ноль для непосредственного рисования. Параметр @var{par} содержит указатель на данные пользователя, передаваемый функции рисования @var{draw}.
+ at end deftypemethod
+ at deftypemethod Fl_MathGL @code{mglDraw *}get_class ()
+Указатель на экземпляр класса @code{mglDraw} или @code{NULL} если отсутствует.
+ at end deftypemethod
+
+ at deftypemethod Fl_MathGL @code{void} update ()
+Обновляет (перерисовывает) график.
+ at end deftypemethod
+ at deftypemethod Fl_MathGL @code{void} set_angle (@code{mreal} t, @code{mreal} p)
+Задает углы для дополнительного вращения графика.
+ at end deftypemethod
+ at deftypemethod Fl_MathGL @code{void} set_flag (@code{int} f)
+Задает битовые флаги для: 1 - прозрачности, 2 - освещения.
+ at end deftypemethod
+ at deftypemethod Fl_MathGL @code{void} set_state (@code{bool} z, @code{bool} r)
+Задает флаги обработки движений мыши: @var{z}=@code{true} -- разрешает приближение выделения, @var{r}=@code{true} разрешает вращение/сдвиг/приближение/перспективу.
+ at end deftypemethod
+
+ at deftypemethod Fl_MathGL @code{void} set_zoom (@code{mreal} X1, @code{mreal} Y1, @code{mreal} X2, @code{mreal} Y2)
+Задает область приближения.
+ at end deftypemethod
+ at deftypemethod Fl_MathGL @code{void} get_zoom (@code{mreal *}X1, @code{mreal *}Y1, @code{mreal *}X2, @code{mreal *}Y2)
+Возвращает область приближения.
+ at end deftypemethod
+
+ at deftypemethod Fl_MathGL @code{void} set_popup (@code{const Fl_Menu_Item *}pmenu, @code{Fl_Widget *}w, @code{void *}v)
+Задает указатель на всплывающее меню.
+ at end deftypemethod
+
+ at deftypemethod Fl_MathGL @code{void} set_graph (@code{mglCanvas *}gr)
+ at deftypemethodx Fl_MathGL @code{void} set_graph (@code{mglGraph *}gr)
+Задает экземпляр класс для рисования вместо встроеного. Fl_MathGL автоматически удалит его при удалении виджета и при новом вызове @code{set_graph()}.
+ at end deftypemethod
+ at deftypemethod Fl_MathGL @code{mglGraph *} get_graph ()
+Возвращает указатель на объект, строящий графики.
+ at end deftypemethod
+
+ at deftypemethod Fl_MathGL @code{void} set_show_warn (@code{bool} val)
+Флаг показа окна с сообщениями после выполнения скрипта.
+ at end deftypemethod
+ at deftypemethod Fl_MathGL @code{void} stop (@code{bool} stop=@code{true})
+Запрос на остановку рисования.
+ at end deftypemethod
+ at deftypemethod Fl_MathGL @code{void} set_handle_key (@code{bool} val)
+Вкл/выкл обработку нажатий клавиш (как в mglview, по умолчанию выкл).
+ at end deftypemethod
+ at deftypemethod Fl_MathGL @code{int} get_last_id ()
+Вернуть id последнего выделенного объекта.
+ at end deftypemethod
+ at deftypemethod Fl_MathGL @code{bool} running ()
+Проверяет выполняется ли сейчас скрипт или нет.
+ at end deftypemethod
+
+ at deftypecv {Widget option} Fl_MathGL @code{Fl_Valuator *} tet_val
+Указатель на внешний элемент управления для изменения угла tet.
+ at end deftypecv
+ at deftypecv {Widget option} Fl_MathGL @code{Fl_Valuator *} phi_val
+Указатель на внешний элемент управления для изменения угла phi.
+ at end deftypecv
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node QMathGL class, wxMathGL class, Fl_MathGL class, Widget classes
+ at section Класс QMathGL
+ at nav{}
+ at cindex QMathGL
+ at cindex widgets
+
+Класс реализует элемент интерфейса Qt для отображения графики MathGL. Он определен в @code{#include <mgl2/qt.h>}.
+
+ at fig{qt, Пример окна Qt с графикой MathGL.}
+
+ at deftypemethod QMathGL @code{void} setDraw (@code{mglDraw *}dr)
+Задает функцию рисования из класса производного от @code{mglDraw}.
+ at end deftypemethod
+ at deftypemethod QMathGL @code{void} setDraw (@code{int (*}draw at code{)(mglBase *}gr, @code{void *}p at code{)}, @code{void *}par=@code{NULL})
+ at deftypemethodx QMathGL @code{void} setDraw (@code{int (*}draw at code{)(mglGraph *}gr at code{)})
+Задает функцию рисования @var{draw}. Поддерживается список графиков (кадров), так что можно вначале их нарисовать (требует довольно много памяти), а потом достаточно быстро отображать. Функция должна возвращать положительное число создаваемых кадров или ноль для непосредственного рисования. Параметр @var{par} содержит указатель на данные пользователя, передаваемый функции рисования @var{draw}.
+ at end deftypemethod
+
+ at deftypemethod QMathGL @code{void} setGraph (@code{mglCanvas *}gr)
+ at deftypemethodx QMathGL @code{void} setGraph (@code{mglGraph *}gr)
+Устанавливает указатель на внешний экземпляр класса для рисования (вместо встроенного). Отмечу, что QMathGL автоматически удалит этот объект при удалении элемента интерфейса или при новом вызове @code{setGraph()}.
+ at end deftypemethod
+ at deftypemethod QMathGL @code{HMGL} getGraph ()
+Возвращает указатель на объект, строящий графики.
+ at end deftypemethod
+
+ at deftypemethod QMathGL @code{void} setPopup (@code{QMenu *}p)
+Задает указатель на всплывающее меню.
+ at end deftypemethod
+ at deftypemethod QMathGL @code{void} setSize (@code{int} w, @code{int} h)
+Задает размеры элемента управления и картинки.
+ at end deftypemethod
+ at deftypemethod QMathGL @code{double} getRatio ()
+Возвращает соотношение сторон рисунка.
+ at end deftypemethod
+
+ at deftypemethod QMathGL @code{int} getPer ()
+Возвращает величину перспективы в процентах.
+ at end deftypemethod
+ at deftypemethod QMathGL @code{int} getPhi ()
+Возвращает величину угла Phi в градусах.
+ at end deftypemethod
+ at deftypemethod QMathGL @code{int} getTet ()
+Возвращает величину угла Theta в градусах.
+ at end deftypemethod
+ at deftypemethod QMathGL @code{bool} getAlpha ()
+Возвращает состояние переключателя прозрачности.
+ at end deftypemethod
+ at deftypemethod QMathGL @code{bool} getLight ()
+Возвращает состояние переключателя освещения.
+ at end deftypemethod
+ at deftypemethod QMathGL @code{bool} getZoom ()
+Возвращает состояние переключателя приближения мышью.
+ at end deftypemethod
+ at deftypemethod QMathGL @code{bool} getRotate ()
+Возвращает состояние переключателя вращения мышью.
+ at end deftypemethod
+
+
+ at deftypefn {Slot on @code{QMathGL}} @code{void} refresh ()
+Перерисовывает (обновляет) элемент управления без вызова функции рисования.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} update ()
+Обновляет рисунок путем вызова функции рисования.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} copy ()
+Копирует график в буфер обмена.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} copyClickCoor ()
+Копирует координаты щелчка мышью (как текст).
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} print ()
+Печатает текущий рисунок.
+ at end deftypefn
+
+ at deftypefn {Slot on @code{QMathGL}} @code{void} stop ()
+Посылает сигнал остановки рисования.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} adjust ()
+Подгоняет размер картинки под размер окна.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} nextSlide ()
+Показывает следующий кадр.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} prevSlide ()
+Показывает предыдущий кадр.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} animation (@code{bool} st=@code{true})
+Запускает анимацию.
+ at end deftypefn
+
+ at deftypefn {Slot on @code{QMathGL}} @code{void} setPer (@code{int} val)
+Задает величину перспективы.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} setPhi (@code{int} val)
+Задает величину угла Phi.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} setTet (@code{int} val)
+Задает величину угла Theta.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} setAlpha (@code{bool} val)
+Включает/выключает прозрачность.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} setLight (@code{bool} val)
+Включает/выключает освещение.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} setGrid (@code{bool} val)
+Включает/выключает рисование сетки абсолютных координат на графике.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} setZoom (@code{bool} val)
+Включает/выключает приближение мышью.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} setRotate (@code{bool} val)
+Включает/выключает вращение мышью.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} zoomIn ()
+Приблиажет график.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} zoomOut ()
+Отдаляет график.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} shiftLeft ()
+Сдвигает график влево.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} shiftRight ()
+Сдвигает график вправо.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} shiftUp  ()
+Сдвигает график вверх.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} shiftDown ()
+Сдвигает график вниз.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} restore ()
+Восстанавливает приближение и поворот графика в значения по умолчанию.
+ at end deftypefn
+ at c @deftypefn {Slot on @code{QMathGL}} @code{void} reload ()
+ at c Обновляет данные и перерисовывает график.
+ at c @end deftypefn
+
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportPNG (@code{QString} fname=@code{""})
+Сохраняет текущий рисунок в PNG файл.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportPNGs (@code{QString} fname=@code{""})
+Сохраняет текущий рисунок в PNG файл без прозрачности.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportJPG (@code{QString} fname=@code{""})
+Сохраняет текущий рисунок в JPEG файл.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportBPS (@code{QString} fname=@code{""})
+Сохраняет текущий рисунок в растровый EPS файл.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportEPS (@code{QString} fname=@code{""})
+Сохраняет текущий рисунок в векторный EPS файл.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportSVG (@code{QString} fname=@code{""})
+Сохраняет текущий рисунок в векторный SVG файл.
+ at end deftypefn
+
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportGIF (@code{QString} fname=@code{""})
+Сохраняет текущий рисунок в GIF файл.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportTEX (@code{QString} fname=@code{""})
+Сохраняет текущий рисунок в векторный LaTeX/Tikz файл.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportTGA (@code{QString} fname=@code{""})
+Сохраняет текущий рисунок в TGA файл.
+ at end deftypefn
+
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportXYZ (@code{QString} fname=@code{""})
+Сохраняет текущий рисунок в векторный XYZ/XYZL/XYZF файл.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportOBJ (@code{QString} fname=@code{""})
+Сохраняет текущий рисунок в векторный OBJ/MTL файл.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportSTL (@code{QString} fname=@code{""})
+Сохраняет текущий рисунок в векторный STL файл.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} exportOFF (@code{QString} fname=@code{""})
+Сохраняет текущий рисунок в векторный OFF файл.
+ at end deftypefn
+ at c @deftypefn {Slot on @code{QMathGL}} @code{void} exportX3D (@code{QString} fname=@code{""})
+ at c Сохраняет текущий рисунок в векторный X3D файл.
+ at c @end deftypefn
+
+ at deftypefn {Slot on @code{QMathGL}} @code{void} setUsePrimitives (@code{bool} use)
+Разрешает использовать список примитивов для кадров. Это позволяет вращать/масштабировать кадры, но требует значительно больше памяти. По умолчанию разрешено (=@code{true}).
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} setMGLFont (@code{QString} path)
+Восстанавливает (@var{path}=@code{""}) или загружает файлы шрифтов.
+ at end deftypefn
+
+ at deftypefn {Slot on @code{QMathGL}} @code{void} about ()
+Показывает информацию о программе.
+ at end deftypefn
+ at deftypefn {Slot on @code{QMathGL}} @code{void} aboutQt ()
+Показывает информацию о версии Qt.
+ at end deftypefn
+
+ at deftypefn {Signal on @code{QMathGL}} @code{void} phiChanged (@code{int} val)
+Угол Phi изменен.
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} tetChanged (@code{int} val)
+Угол Tet изменен.
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} perChanged (@code{int} val)
+Перспектива изменена.
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} alphaChanged (@code{bool} val)
+Прозрачность изменена.
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} lightChanged (@code{bool} val)
+Освещение изменено.
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} gridChanged (@code{bool} val)
+Рисование сетки изменено.
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} zoomChanged (@code{bool} val)
+Режим приближения мышью изменен.
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} rotateChanged (@code{bool} val)
+Режим вращения мышью изменен.
+ at end deftypefn
+
+ at deftypefn {Signal on @code{QMathGL}} @code{void} mouseClick (@code{mreal} x, @code{mreal} y, @code{mreal} z)
+Был щелчок мышью в точке @{x,y,z@}.
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} frameChanged (@code{int} val)
+Требуется новый кадр для отображения.
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} showWarn (@code{QString} warn)
+Есть предупреждения.
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} posChanged (@code{QString} pos)
+Положение щелчка мышью изменилось.
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} objChanged (@code{int} id)
+Изменился id объекта на графике (из-за щелчка мышью).
+ at end deftypefn
+ at deftypefn {Signal on @code{QMathGL}} @code{void} refreshData ()
+Данные могли измениться (рисование завершено).
+ at end deftypefn
+
+
+ at deftypecv {QMathGL option} QMathGL @code{QString} appName
+Имя приложения для окон сообщений.
+ at end deftypecv
+ at deftypecv {QMathGL option} QMathGL @code{bool} autoResize
+Разрешить изменять размер рисунка (по умолчанию false).
+ at end deftypecv
+
+ at external{}
+
+
+ at c ------------------------------------------------------------------
+ at external{}
+ at node wxMathGL class, , QMathGL class, Widget classes
+ at section Класс wxMathGL
+ at nav{}
+ at cindex wxMathGL
+ at cindex widgets
+
+Класс реализует элемент интерфейса WX для отображения графики MathGL. Он определен в @code{#include <mgl2/wx.h>}.
+
+ at deftypemethod wxMathGL @code{void} SetDraw (@code{mglDraw *}dr)
+Задает функцию рисования из класса производного от @code{mglDraw}.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} SetDraw (@code{int (*}draw at code{)(mglBase *}gr, @code{void *}p at code{)}, @code{void *}par=@code{NULL})
+ at deftypemethodx wxMathGL @code{void} SetDraw (@code{int (*}draw at code{)(mglGraph *}gr at code{)})
+Задает функцию рисования @var{draw}. Поддерживается список графиков (кадров), так что можно вначале их нарисовать (требует довольно много памяти), а потом достаточно быстро отображать. Функция должна возвращать положительное число создаваемых кадров или ноль для непосредственного рисования. Параметр @var{par} содержит указатель на данные пользователя, передаваемый функции рисования @var{draw}.
+ at end deftypemethod
+
+ at deftypemethod wxMathGL @code{void} SetGraph (@code{mglCanvas *}gr)
+ at deftypemethodx wxMathGL @code{void} SetGraph (@code{mglGraph *}gr)
+Устанавливает указатель на внешний экземпляр класса для рисования (вместо встроенного). Отмечу, что wxMathGL автоматически удалит этот объект при удалении элемента интерфейса или при новом вызове @code{setGraph()}.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{HMGL} GetGraph ()
+Возвращает указатель на объект, строящий графики.
+ at end deftypemethod
+
+ at deftypemethod wxMathGL @code{void} SetPopup (@code{QMenu *}p)
+Задает указатель на всплывающее меню.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} SetSize (@code{int} w, @code{int} h)
+Задает размеры элемента управления и картинки.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{double} GetRatio ()
+Возвращает соотношение сторон рисунка.
+ at end deftypemethod
+
+ at deftypemethod wxMathGL @code{int} GetPer ()
+Возвращает величину перспективы в процентах.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{int} GetPhi ()
+Возвращает величину угла Phi в градусах.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{int} GetTet ()
+Возвращает величину угла Theta в градусах.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{bool} GetAlpha ()
+Возвращает состояние переключателя прозрачности.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{bool} GetLight ()
+Возвращает состояние переключателя освещения.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{bool} GetZoom ()
+Возвращает состояние переключателя приближения мышью.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{bool} GetRotate ()
+Возвращает состояние переключателя вращения мышью.
+ at end deftypemethod
+
+
+ at deftypemethod wxMathGL @code{void} Repaint ()
+Перерисовывает (обновляет) элемент управления без вызова функции рисования.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} Update ()
+Обновляет рисунок путем вызова функции рисования.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} Copy ()
+Копирует график в буфер обмена.
+ at end deftypemethod
+ at comment  @deftypemethod wxMathGL @code{void} copyClickCoor ()
+ at comment  Копирует координаты щелчка мышью (как текст).
+ at comment  @end deftypemethod
+ at deftypemethod wxMathGL @code{void} Print ()
+Печатает текущий рисунок.
+ at end deftypemethod
+
+ at comment  @deftypemethod wxMathGL @code{void} Stop ()
+ at comment  Посылает сигнал остановки рисования.
+ at comment  @end deftypemethod
+ at deftypemethod wxMathGL @code{void} Adjust ()
+Подгоняет размер картинки под размер окна.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} NextSlide ()
+Показывает следующий кадр.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} PrevSlide ()
+Показывает предыдущий кадр.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} Animation (@code{bool} st=@code{true})
+Запускает анимацию.
+ at end deftypemethod
+
+ at deftypemethod wxMathGL @code{void} SetPer (@code{int} val)
+Задает величину перспективы.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} SetPhi (@code{int} val)
+Задает величину угла Phi.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} SetTet (@code{int} val)
+Задает величину угла Theta.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} SetAlpha (@code{bool} val)
+Включает/выключает прозрачность.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} SetLight (@code{bool} val)
+Включает/выключает освещение.
+ at end deftypemethod
+ at comment  @deftypemethod wxMathGL @code{void} SetGrid (@code{bool} val)
+ at comment  Включает/выключает рисование сетки абсолютных координат на графике.
+ at comment  @end deftypemethod
+ at deftypemethod wxMathGL @code{void} SetZoom (@code{bool} val)
+Включает/выключает приближение мышью.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} SetRotate (@code{bool} val)
+Включает/выключает вращение мышью.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} ZoomIn ()
+Приблиажет график.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} ZoomOut ()
+Отдаляет график.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} ShiftLeft ()
+Сдвигает график влево.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} ShiftRight ()
+Сдвигает график вправо.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} ShiftUp  ()
+Сдвигает график вверх.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} ShiftDown ()
+Сдвигает график вниз.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} Restore ()
+Восстанавливает приближение и поворот графика в значения по умолчанию.
+ at end deftypemethod
+ at c @deftypemethod wxMathGL @code{void} reload ()
+ at c Обновляет данные и перерисовывает график.
+ at c @end deftypemethod
+
+ at deftypemethod wxMathGL @code{void} About ()
+Показывает информацию о программе.
+ at end deftypemethod
+
+ at deftypemethod wxMathGL @code{void} ExportPNG (@code{QString} fname=@code{""})
+Сохраняет текущий рисунок в PNG файл.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} ExportPNGs (@code{QString} fname=@code{""})
+Сохраняет текущий рисунок в PNG файл без прозрачности.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} ExportJPG (@code{QString} fname=@code{""})
+Сохраняет текущий рисунок в JPEG файл.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} ExportBPS (@code{QString} fname=@code{""})
+Сохраняет текущий рисунок в растровый EPS файл.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} ExportEPS (@code{QString} fname=@code{""})
+Сохраняет текущий рисунок в векторный EPS файл.
+ at end deftypemethod
+ at deftypemethod wxMathGL @code{void} ExportSVG (@code{QString} fname=@code{""})
+Сохраняет текущий рисунок в векторный SVG файл.
+ at end deftypemethod
+
+ at external{}
+
diff --git a/todo.txt b/todo.txt
new file mode 100644
index 0000000..dada0d5
--- /dev/null
+++ b/todo.txt
@@ -0,0 +1,114 @@
+-Wall -Wsuggest-attribute=pure -Wsuggest-attribute=const
+
+============= FAR FUTURE ================
+
+1. Export to COLLADA or X3D !!!
+2. Use mglDataV in 'var' ?!?
+
+3. Contour lines for bilinear interpolation (strong saddle-like faces) -- best way by adding curve primitive (type=5)?!?
+4. 3D text (with depth), and text along 3D curve (for Quality=3) ???
+5. Get true coordinates in CalcXYZ for curved equations too.
+6. Extra markers for '&' and '&#' signs ?!? or user-defined signs
+
+7. Improve z-order for rapidly oscillating surfaces (сравнение проекций центров на грань -- too slow)
+
+8. Enable consecutive (as multiplication of matrices instead of single summary one) rotation of axis + the same in JS. Problem with widgets?!?
+
+9. Export background image to svg ???
+
+10. Frames by mouse in UDAV ???
+	A. мысли о frame??? для группы графиков -- не "удалять" их, а запихивать в отдельный кадр -- вопрос что с анимацией???
+	B. как делать анимацию (кадры) для мышиной версии ... список кадров, кнопки добавить в кадры + вставить из кадра
+
+11. Parallel drawing in QMathGL (looks to complicated -- FLTK is better!)
+12. \overline{\overline{a}} ???
+13. Manual AddPnt() with specified id + openmp ?!? -- possible memory overuse
+
+
+============= NEW FEATURES =============
+
+1. Centered curved text (see text2)
+2. Read MAT files ?!!
+3. Read WFM files ?!!
+4. "latex on" option ?!?
+
+5. Add 'goto' or 'do|while' command
+6. Extend 'ask' as:
+	ask $N1 'text|kind:arg1:arg2:...' $N2 'text|kind:arg1:arg2:...' ...
+	where kind={default=edit,spin,choice,check,slider,float?}
+7. Add ##d comment(s) -- analogue of 'ask' but update figure after each change ???
+8. Add "mgl_zoomview(int x, int y)" for zoom circle around image point {x,y}
+9. Mask in EPS/SVG
+
+ZZ. Update *.i for new functions {before release!!!}
+
+
+============= DOCUMENTATION =============
+
+A. Paper about MathGL!!!
+B. Add chapter with real samples
+C. Translate to Russian everything
+D. Docs about JS interface
+
+1. Update Qt and UDAV figures
+
+2. Sample about PDE -- add 'tridmat' + 'diffract'
+3. Sample about complex 'ode' (like Raman scattering)
+4. Sample about earth map
+5. Sample about 'erode' and 'dilate'
+7. Sample about 'detect'
+8. Sample about 'section'
+
+26. Update installation (dll from mgl_script + Qt plugins/ + Win10)
+
+ZZ. Update time.texi {before release!!!}
+
+как начать пользоваться (quickstart)
+как скомпилировать и установить (building & installing)
+как запустить (running)
+как протестировать свои правки (testing)
+как настроить (configuration)
+какие есть примеры использования (examples)
+
+============= mgllab ===========
+
+* Manual data changing should be written into script ?!?
+* Check: "You can shift axis range by pressing middle button and moving mouse. Also, you can zoom in/out axis range by using mouse wheel."
+* Shift/Zoom/Perspective by mouse!!!
+* Hint about string manipulation
+* Progress bar for external loop ?!!
+* 1d view -- over longer size + y-size for current slice only
+
+X. Own file-chooser dialog -- separate path and fname fields + add sorting by date|size
+Y. Window with Zoom/Hidden ???
+Z. Flat toolbuttons ???
+
+
+
+============= UDAV =============
+
+1. Zoom rectangle after mouse selection
+
+3. Manual data changing should be written into script
+	a. Suggest to save into HDF5 if data changed manually
+	b. Each manual change in cell produce command like 'put dat val i j k'
+	c. Add command to insert as 'list'
+	d. Reset script after saving to HDF5 or putting to main script
+	e. Ask about script changes before closing data tab
+4. List of constants into the list of data?!
+5. Add color cycle ???
+6. Color position in color scheme dialog
+7. Select 'bbox' by mouse
+9. Save data from the summary panel
+10. Select subdata section (between NAN in curve) by mouse + adding it to script ?!!
+11. Zoom in a region by middle mouse (if not in rotation mode)
+12. Extend 'ask' by adding multiple questions simultaneously (+ set/get default values from file ???)
+
+============= UNSURE ===========
+
+1. GTK window/widgets ???
+2. "Cut off" curves if text is printed inside it (for contour labels) ?!?
+4. Read DICOM files
+5. Check RunThr() in python/octave
+6. Auto axis range for formulas, like AutoRange("y(x)") or AutoRange('x',"x(t)").
+7. Use Hershey as built-in font ??? -- for smaller size only
diff --git a/translations/mathgl_en.mo b/translations/mathgl_en.mo
new file mode 100644
index 0000000..c1f2e9a
Binary files /dev/null and b/translations/mathgl_en.mo differ
diff --git a/translations/mathgl_es.mo b/translations/mathgl_es.mo
new file mode 100644
index 0000000..4d9d0ef
Binary files /dev/null and b/translations/mathgl_es.mo differ
diff --git a/translations/mathgl_ru.mo b/translations/mathgl_ru.mo
new file mode 100644
index 0000000..55f510b
Binary files /dev/null and b/translations/mathgl_ru.mo differ
diff --git a/udav/CMakeLists.txt b/udav/CMakeLists.txt
new file mode 100644
index 0000000..3b4480b
--- /dev/null
+++ b/udav/CMakeLists.txt
@@ -0,0 +1,59 @@
+if(QT_ENABLED)
+
+configure_file(${MathGL2_SOURCE_DIR}/udav/mgl.xml.in ${MathGL2_BINARY_DIR}/udav/mgl.xml)
+
+#set(mgl_wnd_src window.cpp)
+set(udav_src anim_dlg.cpp find_dlg.cpp mem_pnl.cpp prop_dlg.cpp textedit.cpp args_dlg.cpp
+	help_pnl.cpp newcmd_dlg.cpp text_pnl.cpp calc_dlg.cpp hint_dlg.cpp
+	open_dlg.cpp qmglsyntax.cpp udav_wnd.cpp dat_pnl.cpp info_dlg.cpp opt_dlg.cpp setup_dlg.cpp
+	files_dlg.cpp plot_pnl.cpp style_dlg.cpp data_dlg.cpp subplot_dlg.cpp )
+
+set(udav_moc_hdr anim_dlg.h files_dlg.h info_dlg.h opt_dlg.h text_pnl.h args_dlg.h
+	find_dlg.h mem_pnl.h plot_pnl.h setup_dlg.h udav_wnd.h calc_dlg.h help_pnl.h newcmd_dlg.h
+	prop_dlg.h style_dlg.h dat_pnl.h open_dlg.h textedit.h hint_dlg.h data_dlg.h subplot_dlg.h )
+
+set(udav_rc udav.qrc)
+
+if(WIN32)
+	set(udav_src ${udav_src} udav.rc)
+endif(WIN32)
+
+if(enable-qt5)
+	include(../cmake-qt5.txt)
+	qt5_add_resources(udav_rc_src ${udav_rc} )
+else(enable-qt5)
+	include(../cmake-qt4.txt)
+	qt4_add_resources(udav_rc_src ${udav_rc} )
+endif(enable-qt5)
+add_executable(udav ${udav_src} ${udav_moc_hdr} ${udav_rc_src})
+#set_target_properties(udav PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
+if(enable-qt5)
+	target_link_libraries(udav mgl-qt5 ${MGL_QT5_LIBS})
+else(enable-qt5)
+	target_link_libraries(udav mgl-qt4 ${MGL_QT4_LIBS})
+endif(enable-qt5)
+
+mgl_po_src(${udav_src} ${udav_hdr})
+
+if(MGL_HAVE_PTHREAD)
+	target_link_libraries(udav ${CMAKE_THREAD_LIBS_INIT})
+endif(MGL_HAVE_PTHREAD)
+
+install(
+	TARGETS udav
+	EXPORT MathGLTargets
+	RUNTIME DESTINATION ${MathGL_INSTALL_BIN_DIR}
+)
+install(FILES udav.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps/)
+install(FILES udav_ru.qm DESTINATION ${CMAKE_INSTALL_PREFIX}/share/udav/)
+find_program(findupddb update-desktop-database)
+if(findupddb)
+	install(FILES udav.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications/)
+	install(CODE "execute_process(COMMAND \"${findupddb}\" \"${CMAKE_INSTALL_PREFIX}/share/applications\")")
+endif(findupddb)
+find_program(findupmdb update-mime-database)
+if(findupmdb)
+	install(FILES ${CMAKE_BINARY_DIR}/udav/mgl.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mime/packages/)
+	install(CODE "execute_process(COMMAND \"${findupmdb}\" \"${CMAKE_INSTALL_PREFIX}/share/mime\")")
+endif(findupmdb)
+endif(QT_ENABLED)
diff --git a/udav/anim_dlg.cpp b/udav/anim_dlg.cpp
new file mode 100644
index 0000000..eea9c78
--- /dev/null
+++ b/udav/anim_dlg.cpp
@@ -0,0 +1,141 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <QLabel>
+#include <QLayout>
+#include <QLineEdit>
+#include <QTextEdit>
+#include <QPushButton>
+#include <QRadioButton>
+#include <QMessageBox>
+#include <QCheckBox>
+//-----------------------------------------------------------------------------
+#include "anim_dlg.h"
+#undef sprintf	// fix libintl bug of defining sprintf
+extern int animDelay;
+//-----------------------------------------------------------------------------
+AnimParam::AnimParam(QWidget *parent) : QDialog(parent)
+{
+	setWindowTitle(_("UDAV - Animation setup"));
+	QHBoxLayout *a;
+	QVBoxLayout *o, *g;
+	QLabel *lbl;
+	QPushButton *b;
+	o = new QVBoxLayout(this);
+	lbl = new QLabel(_("Redraw picture for $0 equal to"),this);
+	o->addWidget(lbl);
+	a = new QHBoxLayout();		o->addLayout(a);
+	g = new QVBoxLayout();		a->addLayout(g);
+	rbt = new QRadioButton(_("strings"),this);
+	connect(rbt, SIGNAL(clicked()),this, SLOT(setRBT()));
+	g->addWidget(rbt);
+	text = new QTextEdit(this);	g->addWidget(text);
+	connect(text,SIGNAL(textChanged()),this,SLOT(setRBT()));
+
+	g = new QVBoxLayout();		a->addLayout(g);
+	rbf = new QRadioButton(_("values"),this);
+	connect(rbf, SIGNAL(clicked()),this, SLOT(setRBF()));
+	g->addWidget(rbf);
+	lbl = new QLabel(_("from"),this);
+	g->addWidget(lbl, Qt::AlignLeft);
+	p1 = new QLineEdit(this);	g->addWidget(p1);
+	connect(p1,SIGNAL(textChanged(QString)),this,SLOT(setRBF()));
+	lbl = new QLabel(_("to"),this);
+	g->addWidget(lbl, Qt::AlignLeft);
+	p2 = new QLineEdit(this);	g->addWidget(p2);
+	connect(p2,SIGNAL(textChanged(QString)),this,SLOT(setRBF()));
+	lbl = new QLabel(_("with step"),this);
+	g->addWidget(lbl, Qt::AlignLeft);
+	dp = new QLineEdit(this);	g->addWidget(dp);	dp->setText("1");
+	connect(dp,SIGNAL(textChanged(QString)),this,SLOT(setRBF()));
+	b = new QPushButton(_("Cancel"), this);	g->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(reject()));
+	b = new QPushButton(_("OK"), this);	g->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(fillRes()));
+	b->setDefault(true);
+	// general
+	a = new QHBoxLayout();		o->addLayout(a);
+	b = new QPushButton(_("Put to script"), this);	a->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(putTxt()));
+	lbl = new QLabel(_("Delay (in ms)"),this);	a->addWidget(lbl);
+	delay = new QLineEdit(this);	a->addWidget(delay);
+	QString s;	s.sprintf("%d",animDelay);	delay->setText(s);
+	// export to gif/jpeg
+	a = new QHBoxLayout();		o->addLayout(a);
+//	fname = new QLineEdit(this);	a->addWidget(fname);
+	gif = new QCheckBox(_("Export to GIF"), this);		a->addWidget(gif);
+	jpg = new QCheckBox(_("Save JPEG frames"), this);	a->addWidget(jpg);
+}
+//-----------------------------------------------------------------------------
+AnimParam::~AnimParam()	{}
+//-----------------------------------------------------------------------------
+void AnimParam::fillRes()
+{
+//	gifName = fname->text();
+	gifOn = gif->isChecked();
+	jpgOn = jpg->isChecked();
+	animDelay = delay->text().toInt();
+	if(rbt->isChecked())	{	res = text->toPlainText();	accept();	}
+	else if(rbf->isChecked())
+	{
+		res = "";
+		QString s;
+		double x, x2=p2->text().toDouble(), dx=dp->text().toDouble();
+		for(x=p1->text().toDouble();x<x2;x+=dx)
+			res = res+QString::number(x,'g',4)+"\n";
+		accept();
+	}
+	else	QMessageBox::warning(this,_("UDAV - animation"),
+								 _("You should select one of case"));
+}
+//-----------------------------------------------------------------------------
+void AnimParam::putTxt()
+{
+	QString s, t;
+	if(!p1->text().isEmpty() && !p2->text().isEmpty() && !dp->text().isEmpty())
+	{
+		s = "##c "+p1->text()+" "+p2->text()+" "+dp->text()+"\n";
+		emit putText(s);
+	}
+	if(text->toPlainText().isEmpty())	return;
+	int i, n = text->toPlainText().count('\n')+1;
+	for(i=0;i<n;i++)
+	{
+		t = text->toPlainText().section('\n',i,i);
+		if(!t.isEmpty())	s = s+"##a "+t+"\n";
+	}
+	emit putText(s);
+}
+//-----------------------------------------------------------------------------
+void AnimParam::setRBF()	{	rbt->setChecked(false);	rbf->setChecked(true);	}
+//-----------------------------------------------------------------------------
+void AnimParam::setRBT()	{	rbf->setChecked(false);	rbt->setChecked(true);	}
+//-----------------------------------------------------------------------------
+void AnimParam::setResult(const QString &s)
+{	text->setText(s);	rbf->setChecked(false);	rbt->setChecked(true);	}
+//-----------------------------------------------------------------------------
+void AnimParam::setResult(double a1, double a2, double da)
+{
+	p1->setText(QString::number(a1));
+	p2->setText(QString::number(a2));
+	dp->setText(QString::number(da));
+	rbt->setChecked(false);	rbf->setChecked(true);
+}
+//-----------------------------------------------------------------------------
+
diff --git a/udav/anim_dlg.h b/udav/anim_dlg.h
new file mode 100644
index 0000000..60f7c98
--- /dev/null
+++ b/udav/anim_dlg.h
@@ -0,0 +1,58 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef ANIMPARAM_H
+#define ANIMPARAM_H
+//-----------------------------------------------------------------------------
+#include <QDialog>
+#include "mgl2/define.h"
+//-----------------------------------------------------------------------------
+class QLineEdit;
+class QTextEdit;
+class QRadioButton;
+class QCheckBox;
+/// Setup animation parqmeters
+class AnimParam : public QDialog
+{
+Q_OBJECT
+public:
+	bool gifOn, jpgOn;
+	/// string with resulting animation parameters
+	const QString &getResult()	{	return res;	}
+	void setResult(const QString &s);
+	void setResult(double a1,double a2,double da);
+	AnimParam(QWidget *parent=0);
+	~AnimParam();
+signals:
+	void putText(const QString &par);
+private slots:
+	void fillRes();
+	void putTxt();
+	void setRBF();
+	void setRBT();
+private:
+	QString res;
+	QLineEdit *p1, *p2, *dp, *delay;//, *fname;
+	QTextEdit *text;
+	QRadioButton *rbt, *rbf;
+	QCheckBox *gif, *jpg;
+};
+//-----------------------------------------------------------------------------
+#endif
+//-----------------------------------------------------------------------------
diff --git a/udav/args_dlg.cpp b/udav/args_dlg.cpp
new file mode 100644
index 0000000..f00ae64
--- /dev/null
+++ b/udav/args_dlg.cpp
@@ -0,0 +1,89 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <QLabel>
+#include <QLayout>
+#include <QLineEdit>
+#include <QPushButton>
+#include <mgl2/mgl.h>
+#include "args_dlg.h"
+extern mglParse parser;
+//-----------------------------------------------------------------------------
+QDialog *createArgsDlg(QWidget *p)	{	return new ArgsDialog(p);	}
+//-----------------------------------------------------------------------------
+ArgsDialog::ArgsDialog(QWidget *parent) : QDialog(parent)
+{
+	setWindowTitle(_("UDAV - Set script arguments"));
+	QHBoxLayout *h;
+	QVBoxLayout *v;
+	QGridLayout *g;
+	QLabel *l;
+	QPushButton *b;
+
+	v = new QVBoxLayout(this);
+	g = new QGridLayout();		v->addLayout(g);
+	l = new QLabel(_("String for $1"), this);	g->addWidget(l, 0, 0);
+	a[1] = new QLineEdit(this);					g->addWidget(a[1], 1, 0);
+	l = new QLabel(_("String for $2"), this);	g->addWidget(l, 0, 1);
+	a[2] = new QLineEdit(this);					g->addWidget(a[2], 1, 1);
+	l = new QLabel(_("String for $3"), this);	g->addWidget(l, 2, 0);
+	a[3] = new QLineEdit(this);					g->addWidget(a[3], 3, 0);
+	l = new QLabel(_("String for $4"), this);	g->addWidget(l, 2, 1);
+	a[4] = new QLineEdit(this);					g->addWidget(a[4], 3, 1);
+	l = new QLabel(_("String for $5"), this);	g->addWidget(l, 4, 0);
+	a[5] = new QLineEdit(this);					g->addWidget(a[5], 5, 0);
+	l = new QLabel(_("String for $6"), this);	g->addWidget(l, 4, 1);
+	a[6] = new QLineEdit(this);					g->addWidget(a[6], 5, 1);
+	l = new QLabel(_("String for $7"), this);	g->addWidget(l, 6, 0);
+	a[7] = new QLineEdit(this);					g->addWidget(a[7], 7, 0);
+	l = new QLabel(_("String for $8"), this);	g->addWidget(l, 6, 1);
+	a[8] = new QLineEdit(this);					g->addWidget(a[8], 7, 1);
+	l = new QLabel(_("String for $9"), this);	g->addWidget(l, 8, 0);
+	a[9] = new QLineEdit(this);					g->addWidget(a[9], 9, 0);
+	l = new QLabel(_("String for $0"), this);	g->addWidget(l, 8, 1);
+	a[0] = new QLineEdit(this);					g->addWidget(a[0], 9, 1);
+
+	h = new QHBoxLayout();	h->addStretch(1);	v->addLayout(h);
+	b = new QPushButton(_("Cancel"), this);	h->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(reject()));
+	b = new QPushButton(_("OK"), this);		h->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(putArguments()));
+	b->setDefault(true);
+}
+//-----------------------------------------------------------------------------
+ArgsDialog::~ArgsDialog()	{}
+//-----------------------------------------------------------------------------
+void ArgsDialog::putArguments()
+{
+	int len=0, i, j, n;
+	for(i=0;i<10;i++)
+			if(a[i]->text().length()>len)
+				len = a[i]->text().length();
+	wchar_t *str = new wchar_t[len+2];
+	QString s;
+	for(i=0;i<10;i++)
+	{
+		s = a[i]->text();	n = s.length();
+		for(j=0;j<n;j++)	str[j] = (s[j]).unicode();
+		str[j] = 0;
+		parser.AddParam(i, str);
+	}
+	accept();
+}
+//-----------------------------------------------------------------------------
diff --git a/udav/args_dlg.h b/udav/args_dlg.h
new file mode 100644
index 0000000..f6dbf05
--- /dev/null
+++ b/udav/args_dlg.h
@@ -0,0 +1,41 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef ARGS_DLG_H
+#define ARGS_DLG_H
+//-----------------------------------------------------------------------------
+#include <QDialog>
+class QLineEdit;
+//-----------------------------------------------------------------------------
+/// Dialog for enetring script arguments $0...$9
+class ArgsDialog : public QDialog
+{
+Q_OBJECT
+public:
+	ArgsDialog(QWidget *parent=0);
+	~ArgsDialog();
+
+private slots:
+	void putArguments();
+private:
+	QLineEdit *a[10];
+};
+//-----------------------------------------------------------------------------
+#endif
+//-----------------------------------------------------------------------------
diff --git a/udav/calc_dlg.cpp b/udav/calc_dlg.cpp
new file mode 100644
index 0000000..b891668
--- /dev/null
+++ b/udav/calc_dlg.cpp
@@ -0,0 +1,264 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <QLabel>
+#include <QLayout>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QListView>
+#include <QComboBox>
+#include <QTextEdit>
+#include <mgl2/mgl.h>
+#include "calc_dlg.h"
+extern mglParse parser;
+//-----------------------------------------------------------------------------
+//
+//	Calc dialog
+//
+//-----------------------------------------------------------------------------
+QWidget *createCalcDlg(QWidget *p, QTextEdit *e)
+{
+	CalcDialog *c = new CalcDialog(p);
+	QObject::connect(c, SIGNAL(putNumber(QString)),e,SLOT(insertPlainText(QString)));
+	return c;
+}
+//-----------------------------------------------------------------------------
+CalcDialog::CalcDialog(QWidget *parent) : QWidget(parent)
+{
+	QPushButton *b;
+	QHBoxLayout *m=new QHBoxLayout(this);
+	QVBoxLayout *o=new QVBoxLayout;	m->addLayout(o);	m->setStretchFactor(o,1);
+//	QStandardItem *it;
+
+	text = new QLineEdit(this);	o->addWidget(text);
+	connect(text,SIGNAL(textChanged(QString)),this,SLOT(evaluate()));
+	connect(text,SIGNAL(returnPressed()),this,SLOT(addResult()));
+	hist = new QStandardItemModel(this);
+//	it = new QStandardItem(_("Formula"));	hist->setHorizontalHeaderItem(0,it);
+//	it = new QStandardItem(_("Result"));	hist->setHorizontalHeaderItem(1,it);
+	prev = new QListView(this);	o->addWidget(prev);
+	connect(prev,SIGNAL(clicked(QModelIndex)),this,SLOT(putText(QModelIndex)));
+	QFont f(font());	f.setPointSize(f.pointSize()*0.75);
+	prev->setModel(hist);	prev->setFont(f);
+	prev->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Ignored);
+
+
+	o = new QVBoxLayout;		m->addLayout(o);
+	QLabel *l = new QLabel(_("Result"),this);	o->addWidget(l);
+	result=new QLineEdit(this);	result->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
+	result->setReadOnly(true);	o->addWidget(result);
+	b = new QPushButton(_("To script"), this);	o->addWidget(b);
+	connect(b, SIGNAL(clicked()), this, SLOT(keyPut()));
+	b = new QPushButton(_("Clear"), this);	o->addWidget(b);
+	connect(b, SIGNAL(clicked()), this, SLOT(clear()));
+
+	QGridLayout *g = new QGridLayout;	m->addLayout(g);	m->setStretchFactor(g,0);
+	b = new QPushButton("7", this);	g->addWidget(b, 0, 0);
+	int minw=b->height();	b->setMaximumWidth(minw);
+	connect(b, SIGNAL(clicked()), this, SLOT(key7()));
+	b = new QPushButton("8", this);	g->addWidget(b, 0, 1);	b->setMaximumWidth(minw);
+	connect(b, SIGNAL(clicked()), this, SLOT(key8()));
+	b = new QPushButton("9", this);	g->addWidget(b, 0, 2);	b->setMaximumWidth(minw);
+	connect(b, SIGNAL(clicked()), this, SLOT(key9()));
+	b = new QPushButton("+", this);	g->addWidget(b, 0, 3);	b->setMaximumWidth(minw);
+	connect(b, SIGNAL(clicked()), this, SLOT(keyAdd()));
+	b = new QPushButton(QString::fromWCharArray(L"\u03c0"), this);	g->addWidget(b, 0, 4);
+	connect(b, SIGNAL(clicked()), this, SLOT(keyPi()));		b->setMaximumWidth(minw);
+
+	b = new QPushButton("4", this);	g->addWidget(b, 1, 0);	b->setMaximumWidth(minw);
+	connect(b, SIGNAL(clicked()), this, SLOT(key4()));
+	b = new QPushButton("5", this);	g->addWidget(b, 1, 1);	b->setMaximumWidth(minw);
+	connect(b, SIGNAL(clicked()), this, SLOT(key5()));
+	b = new QPushButton("6", this);	g->addWidget(b, 1, 2);	b->setMaximumWidth(minw);
+	connect(b, SIGNAL(clicked()), this, SLOT(key6()));
+	b = new QPushButton("-", this);	g->addWidget(b, 1, 3);	b->setMaximumWidth(minw);
+	connect(b, SIGNAL(clicked()), this, SLOT(keySub()));
+	b = new QPushButton(QString::fromWCharArray(L"x\xb2"), this);	g->addWidget(b, 1, 4);
+	connect(b, SIGNAL(clicked()), this, SLOT(keyX2()));		b->setMaximumWidth(minw);
+
+	b = new QPushButton("1", this);	g->addWidget(b, 2, 0);	b->setMaximumWidth(minw);
+	connect(b, SIGNAL(clicked()), this, SLOT(key1()));
+	b = new QPushButton("2", this);	g->addWidget(b, 2, 1);	b->setMaximumWidth(minw);
+	connect(b, SIGNAL(clicked()), this, SLOT(key2()));
+	b = new QPushButton("3", this);	g->addWidget(b, 2, 2);	b->setMaximumWidth(minw);
+	connect(b, SIGNAL(clicked()), this, SLOT(key3()));
+	b = new QPushButton("*", this);	g->addWidget(b, 2, 3);	b->setMaximumWidth(minw);
+	connect(b, SIGNAL(clicked()), this, SLOT(keyMul()));
+	b = new QPushButton("(", this);	g->addWidget(b, 2, 4);	b->setMaximumWidth(minw);
+	connect(b, SIGNAL(clicked()), this, SLOT(keyBrO()));
+
+	b = new QPushButton("0", this);	g->addWidget(b, 3, 0);	b->setMaximumWidth(minw);
+	connect(b, SIGNAL(clicked()), this, SLOT(key0()));
+	b = new QPushButton(".", this);	g->addWidget(b, 3, 1);	b->setMaximumWidth(minw);
+	connect(b, SIGNAL(clicked()), this, SLOT(keyDot()));
+	b = new QPushButton("E", this);	g->addWidget(b, 3, 2);	b->setMaximumWidth(minw);
+	connect(b, SIGNAL(clicked()), this, SLOT(keyE()));
+	b = new QPushButton("/", this);	g->addWidget(b, 3, 3);	b->setMaximumWidth(minw);
+	connect(b, SIGNAL(clicked()), this, SLOT(keyDiv()));
+	b = new QPushButton(")", this);	g->addWidget(b, 3, 4);	b->setMaximumWidth(minw);
+	connect(b, SIGNAL(clicked()), this, SLOT(keyBrC()));
+
+	fillFuncName();
+	o=new QVBoxLayout;	m->addLayout(o);	m->setStretchFactor(o,0);
+	type = new QComboBox(this);		o->addWidget(type);
+	type->addItems(names);	type->setCurrentIndex(0);
+	func = new QComboBox(this);		o->addWidget(func);
+	func->addItems(funcName[0]);	type->setCurrentIndex(0);
+	descr= new QLabel(this);		o->addWidget(descr);	o->setStretchFactor(descr,0);
+	descr->setText(funcInfo[0].at(0));
+	connect(type, SIGNAL(currentIndexChanged(int)), this, SLOT(typeUpdate(int)));
+	connect(func, SIGNAL(currentIndexChanged(int)), this, SLOT(funcUpdate(int)));
+	b = new QPushButton(_("Put function"), this);	o->addWidget(b);
+	connect(b, SIGNAL(clicked()), this, SLOT(keyFnc()));
+}
+//-----------------------------------------------------------------------------
+CalcDialog::~CalcDialog()	{}
+void CalcDialog::foc()	{	text->setFocus(Qt::ActiveWindowFocusReason);	}
+//-----------------------------------------------------------------------------
+void CalcDialog::key1()		{	text->insert("1");	foc();	}
+void CalcDialog::key2()		{	text->insert("2");	foc();	}
+void CalcDialog::key3()		{	text->insert("3");	foc();	}
+void CalcDialog::key4()		{	text->insert("4");	foc();	}
+void CalcDialog::key5()		{	text->insert("5");	foc();	}
+void CalcDialog::key6()		{	text->insert("6");	foc();	}
+void CalcDialog::key7()		{	text->insert("7");	foc();	}
+void CalcDialog::key8()		{	text->insert("8");	foc();	}
+void CalcDialog::key9()		{	text->insert("9");	foc();	}
+void CalcDialog::key0()		{	text->insert("0");	foc();	}
+void CalcDialog::keyE()		{	text->insert("E");	foc();	}
+void CalcDialog::keyPi()	{	text->insert("pi");	foc();	}
+void CalcDialog::keyX2()	{	text->insert("^2");	foc();	}
+void CalcDialog::keyAdd()	{	text->insert("+");	foc();	}
+void CalcDialog::keyMul()	{	text->insert("*");	foc();	}
+void CalcDialog::keySub()	{	text->insert("-");	foc();	}
+void CalcDialog::keyDiv()	{	text->insert("/");	foc();	}
+void CalcDialog::keyBrO()	{	text->insert("(");	foc();	}
+void CalcDialog::keyBrC()	{	text->insert(")");	foc();	}
+void CalcDialog::keyDot()	{	text->insert(".");	foc();	}
+void CalcDialog::clear()	{	text->clear();	foc();	}
+//-----------------------------------------------------------------------------
+void CalcDialog::keyFnc()
+{
+	text->insert(func->currentText());
+	text->setCursorPosition(text->cursorPosition()-1);	foc();
+}
+//-----------------------------------------------------------------------------
+void CalcDialog::keyPut()	{	emit putNumber(result->text());	}
+//-----------------------------------------------------------------------------
+void CalcDialog::putText(QModelIndex ind)
+{	text->setText(hist->data(ind).toString());	}
+//-----------------------------------------------------------------------------
+void CalcDialog::addResult()
+{
+	QStandardItem *it;
+	QFont f(prev->font());	f.setBold(true);
+	hist->insertRows(0,2);
+	it = new QStandardItem(text->text());	it->setFont(f);	hist->setItem(0,it);
+	it = new QStandardItem(result->text());	hist->setItem(1,it);
+}
+//-----------------------------------------------------------------------------
+void CalcDialog::evaluate()
+{
+	QString sel=text->text();
+	if(sel.isEmpty())	return;
+	wchar_t *txt=new wchar_t[sel.length()+1];
+	sel.toWCharArray(txt);	txt[sel.length()]=0;
+	setlocale(LC_NUMERIC, "C");
+	mglData res=parser.Calc(txt);
+	setlocale(LC_NUMERIC, "");
+//	result->setText(QString::fromWCharArray(txt));
+	delete []txt;
+	result->setText(QString::number(res.GetVal(0)));
+}
+//-----------------------------------------------------------------------------
+void CalcDialog::fillFuncName()
+{
+	names<<_("Basic")<<_("Exp and log")<<_("Trigonometric")<<_("Hyperbolic")
+			<<_("Bessel")<<_("Elliptic")<<_("Jacobi")<<_("Airy and Gamma")
+			<<_("Exp-integrals")<<_("Special");
+	// basic
+	funcName[0]<<"abs()"<<"sign()"<<"step()"<<"sqrt()"<<"mod(,)"<<"arg(,)";
+	funcInfo[0]<<"Absolute value"<<"Sign of number"<<"Step function"
+			<<"Square root"<<"x modulo y"<<"Argument of complex number";
+	// exp and logarithms
+	funcName[1]<<"exp()"<<"pow(,)"<<"ln()"<<"lg()"<<"log(,)";
+	funcInfo[1]<<"Exponential function e^x"<<"Power x^y"<<"Logarithm of x"
+			<<"Decimal logarithm of x"<<"Logarithm of x on base a";
+	// trigonometric
+	funcName[2]<<"sin()"<<"cos()"<<"tan()"<<"sinc()"<<"asin()"<<"acos()"<<"atan()";
+	funcInfo[2]<<"Sine function"<<"Cosine function"<<"Tangent function"<<"sin(x)/x"
+			<<"Inverse sine function"<<"Inverse cosine function"<<"Inverse tangent function";
+	// hyperbolic
+	funcName[3]<<"sinh()"<<"cosh()"<<"tanh()"<<"asinh()"<<"acosh()"<<"atanh()";
+	funcInfo[3]<<"Hyperbolic sine function"<<"Hyperbolic cosine function"
+			<<"Hyperbolic tangent function"<<"Inverse hyperbolic sine function"
+			<<"Inverse hyperbolic cosine function"<<"Inverse hyperbolic tangent function";
+	// bessel
+	funcName[4]<<"bessel_j(,)"<<"bessel_y(,)"<<"bessel_i(,)"<<"bessel_k(,)";
+	funcInfo[4]<<"Regular cylindrical Bessel function"<<"Irregular cylindrical Bessel function"
+			<<"Regular modified Bessel function"<<"Irregular modified Bessel function";
+	// elliptic
+	funcName[5]<<"elliptic_e(,)"<<"elliptic_f(,)"<<"elliptic_ec()"<<"elliptic_kc()";
+	funcInfo[5]<<"Elliptic integral E(phi,k)"<<"Elliptic integral F(phi,k)"
+			<<"Complete elliptic integral E(k)"<<"Complete elliptic integral K(k)";
+	// jacobi
+	funcName[6]<<"sn(,)"<<"cn(,)"<<"dn(,)"<<"sc(,)"<<"dc(,)"<<"nc(,)"<<"cs(,)"
+			<<"ds(,)"<<"ns(,)"<<"sd(,)"<<"cd(,)"<<"nd(,)";
+	funcInfo[6]<<"Jacobi function sn(u|m)"<<"Jacobi function cn(u|m)"
+			<<"Jacobi function dn(u|m)"<<"Jacobi function sn(u|m)/cn(u|m)"
+			<<"Jacobi function dn(u|m)/cn(u|m)"<<"Jacobi function 1/cn(u|m)"
+			<<"Jacobi function cn(u|m)/sn(u|m)"<<"Jacobi function dn(u|m)/sn(u|m)"
+			<<"Jacobi function 1/sn(u|m)"<<"Jacobi function sn(u|m)/dn(u|m)"
+			<<"Jacobi function cn(u|m)/dn(u|m)"<<"Jacobi function 1/dn(u|m)";
+	// airy and gamma
+	funcName[7]<<"airy_ai()"<<"airy_bi()"<<"airy_dai()"<<"airy_dbi()"<<"gamma()"<<"psi()"<<"beta(,)";
+	funcInfo[7]<<"Airy function Ai(x)"<<"Airy function Bi(x)"
+			<<"Derivative of Airy function Ai'(x)"<<"Derivative of Airy function Bi'(x)"
+			<<QString::fromWCharArray(L"Gamma function \u0393(x)")
+			<<QString::fromWCharArray(L"Digamma function \u0393'(x)/\u0393(x)")
+			<<QString::fromWCharArray(L"Beta function \u0393(x)*\u0393(y)/\u0393(x+y)");
+	// exp integrals
+	funcName[8]<<"ci()"<<"si()"<<"ei()"<<"e1()"<<"e2()"<<"ei3()";
+	funcInfo[8]<<QString::fromWCharArray(L"Cosine integral \u222bdt cos(t)/t")
+			<<QString::fromWCharArray(L"Sine integral \u222bdt sin(t)/t")
+			<<QString::fromWCharArray(L"Integral -\u222bdt exp(-t)/t")
+			<<QString::fromWCharArray(L"Integral Re \u222bdt exp(-xt)/t")
+			<<QString::fromWCharArray(L"Integral Re\u222bdt exp(-xt)/t^2")
+			<<QString::fromWCharArray(L"Integral \u222bdt exp(-t^3)");
+	// special
+	funcName[9]<<"erf()"<<"z()"<<"legendre(,)"<<"dilog()"<<"eta()"<<"zeta()"<<"w0()"<<"w1()";
+	funcInfo[9]<<QString::fromWCharArray(L"Error function 2/√π \u222bdt exp(-t^2)")<<"Dawson function"
+			<<"Legendre polynomial P_l(x)"<<QString::fromWCharArray(L"Dilogarithm -Re\u222bds ln(1-s)/s")
+			<<"Eta function (1-2/2^s)*zeta(s)"<<"Riemann zeta function"
+			<<"Lambert W function W_0(x)"<<"Lambert W function W_{-1}(x)";
+}
+//-----------------------------------------------------------------------------
+void CalcDialog::typeUpdate(int s)
+{
+	if(s<0 || s>9)	return;
+	func->clear();	func->addItems(funcName[s]);	func->setCurrentIndex(0);
+}
+//-----------------------------------------------------------------------------
+void CalcDialog::funcUpdate(int f)
+{
+	int s=type->currentIndex();
+	if(s<0 || s>9 || f<0)	return;	// wrong index
+	descr->setText(funcInfo[s].at(f));
+}
+//-----------------------------------------------------------------------------
diff --git a/udav/calc_dlg.h b/udav/calc_dlg.h
new file mode 100644
index 0000000..b3d429e
--- /dev/null
+++ b/udav/calc_dlg.h
@@ -0,0 +1,87 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef CALC_DLG_H
+#define CALC_DLG_H
+//-----------------------------------------------------------------------------
+#include <QDialog>
+#include <QStringList>
+#include <QStandardItemModel>
+class QLabel;
+class QLineEdit;
+class QTextEdit;
+class QComboBox;
+class QListView;
+class QPushButton;
+//-----------------------------------------------------------------------------
+/// Dialog for finding something in text
+class CalcDialog : public QWidget
+{
+Q_OBJECT
+public:
+	CalcDialog(QWidget *parent = 0);
+	~CalcDialog();
+public slots:
+	void evaluate();
+signals:
+	void putNumber(const QString &str);
+private slots:
+	void keyPut();
+	void key1();
+	void key2();
+	void key3();
+	void key4();
+	void key5();
+	void key6();
+	void key7();
+	void key8();
+	void key9();
+	void key0();
+	void keyE();
+	void keyDot();
+	void keyMul();
+	void keyDiv();
+	void keyAdd();
+	void keySub();
+	void keyBrO();
+	void keyBrC();
+	void keyFnc();
+	void keyPi();
+	void keyX2();
+	void typeUpdate(int s);
+	void funcUpdate(int s);
+	void foc();
+	void clear();
+	void putText(QModelIndex ind);
+	void addResult();
+
+private:
+	QLineEdit *text;
+	QLineEdit *result;
+	QComboBox *type, *func;
+	QLabel *descr;
+	QListView *prev;
+	QStringList names, funcName[10], funcInfo[10];
+	QStandardItemModel *hist;
+
+	void fillFuncName();
+};
+//-----------------------------------------------------------------------------
+#endif
+//-----------------------------------------------------------------------------
diff --git a/udav/dat_pnl.cpp b/udav/dat_pnl.cpp
new file mode 100644
index 0000000..3856190
--- /dev/null
+++ b/udav/dat_pnl.cpp
@@ -0,0 +1,840 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <QTableWidget>
+#include <QLabel>
+#include <QAction>
+#include <QLayout>
+#include <QMenuBar>
+#include <QLineEdit>
+#include <QMenu>
+#include <QClipboard>
+#include <QStatusBar>
+#include <QFileDialog>
+#include <QPushButton>
+#include <QApplication>
+#include <QInputDialog>
+#include <QToolButton>
+#include <QSpinBox>
+#include <QComboBox>
+#include <QCheckBox>
+#include <QMessageBox>
+#include <mgl2/mgl.h>
+//-----------------------------------------------------------------------------
+#include "dat_pnl.h"
+#include "info_dlg.h"
+#include "xpm/table.xpm"
+#undef sprintf	// fix libintl bug of defining sprintf
+//-----------------------------------------------------------------------------
+extern mglParse parser;
+void updateDataItems();
+void addDataPanel(QWidget *wnd, QWidget *w, QString name);
+void deleteDat(void *o)		{	if(o)	delete ((DatPanel *)o);	}
+void refreshData(QWidget *w)	{	((DatPanel *)w)->refresh();	}
+//-----------------------------------------------------------------------------
+QWidget *newDataWnd(InfoDialog *inf, QWidget *wnd, mglDataA *v)
+{
+	DatPanel *t = new DatPanel(inf);
+	if(v)	t->setVar(v);
+	addDataPanel(wnd,t,t->dataName());
+	return t;
+}
+//-----------------------------------------------------------------------------
+DatPanel::DatPanel(InfoDialog *inf, QWidget *parent) : QWidget(parent)
+{
+	setAttribute(Qt::WA_DeleteOnClose);
+	kz = nx = ny = nz = 0;	var = 0;
+	ready = false;	infoDlg = inf;
+	QBoxLayout *v,*h,*m;
+
+	menu = new QMenu(_("Data"),this);
+	v = new QVBoxLayout(this);
+	h = new QHBoxLayout();	v->addLayout(h);	toolTop(h);
+	h = new QHBoxLayout();	v->addLayout(h);
+	m = new QVBoxLayout();	h->addLayout(m);	toolLeft(m);
+	tab = new QTableWidget(this);	h->addWidget(tab);
+	connect(tab, SIGNAL(cellChanged(int,int)), this, SLOT(putValue(int, int)));
+
+	setWindowIcon(QPixmap(table_xpm));
+}
+//-----------------------------------------------------------------------------
+DatPanel::~DatPanel()	{	if(var && var->o==this)	var->o = 0;	}
+//-----------------------------------------------------------------------------
+void DatPanel::refresh()
+{
+	bool rc = false;
+	if(!var)	return;
+	infoDlg->allowRefresh=false;
+	if(nx!=var->GetNx())	{	nx = var->GetNx();	tab->setColumnCount(nx);	rc=true;	}
+	if(ny!=var->GetNy())	{	ny = var->GetNy();	tab->setRowCount(ny);	rc=true;	}
+	if(kz>=var->GetNz())	{	kz = 0;	emit sliceChanged(0);	}
+	if(nz!=var->GetNz())	{	nz = var->GetNz();	emit nzChanged(nz);		}
+	const mglData *dd = dynamic_cast<const mglData *>(var);	if(dd)	id = QString(dd->id.c_str());
+	const mglDataC *dc = dynamic_cast<const mglDataC *>(var);	if(dc)	id = QString(dc->id.c_str());
+	if(nz==1 && ny>1 && !id.isEmpty())
+	{
+		QStringList head;
+		QString s;
+		for(int i=0;i<ny;i++)
+		{
+			s = QString("%1").arg(i);
+			if(id[i]>='a' && id[i]<='z')	s=s+" ("+id[i]+")";
+			head<<s;
+		}
+		tab->setHorizontalHeaderLabels(head);
+	}
+	long m=var->s.length();
+	QString s,d;
+	if(rc)
+	{
+		QStringList sh,sv;
+		for(long i=0;i<nx;i++)	sh<<QString::number(i);
+		tab->setHorizontalHeaderLabels(sh);
+		for(long i=0;i<ny;i++)	sv<<QString::number(i);
+		tab->setVerticalHeaderLabels(sv);
+		for(long i=0;i<nx;i++)	for(long j=0;j<ny;j++)
+			tab->setItem(j,i,new QTableWidgetItem);
+	}
+	mglDataC *cc = dynamic_cast<mglDataC*>(var);
+	if(cc)	for(long i=0;i<nx;i++)	for(long j=0;j<ny;j++)
+	{
+		dual f = cc->a[i+nx*(j+ny*kz)];
+		if(mgl_isnan(f))	s = "nan";
+		else if(mgl_isbad(f))	s="inf";
+		else if(imag(f)>0)	s.sprintf("%.15g+%.15gi",real(f),imag(f));
+		else if(imag(f)<0)	s.sprintf("%.15g-%.15gi",real(f),-imag(f));
+		else	s.sprintf("%15g",real(f));
+		tab->item(j,i)->setText(s);
+	}
+	else	for(long i=0;i<nx;i++)	for(long j=0;j<ny;j++)
+	{
+		double f = var->v(i,j,kz);
+		if(mgl_isnan(f))	s = "nan";
+		else if(mgl_isbad(f))	s=f>0?"inf":"-inf";
+		else	s.sprintf("%.15g",f);
+		tab->item(j,i)->setText(s);
+	}
+	infoDlg->allowRefresh=true;	infoDlg->refresh();
+	QChar *ss = new QChar[m+1];
+	for(long i=0;i<m;i++)	ss[i] = var->s[i];
+	s = QString(ss, m);	delete []ss;
+	d.sprintf("%d * %d * %d", nx, ny, nz);
+	ready = true;
+}
+//-----------------------------------------------------------------------------
+void DatPanel::setVar(mglDataA *v)
+{
+	ready = false;
+	if(var)	var->o = 0;
+	var = v;	infoDlg->setVar(v);
+	nx = ny = nz = kz = 0;
+	if(v)
+	{
+		QString s = QString::fromWCharArray(v->s.c_str());
+		v->o = this;	v->func = deleteDat;
+		refresh();
+		setWindowTitle(s + _(" - UDAV variable"));
+		infoDlg->setWindowTitle(s + _(" - UDAV preview"));
+	}
+	else
+	{	tab->setColumnCount(0);	tab->setRowCount(0);	emit nzChanged(nz);	}
+	emit sliceChanged(0);
+}
+//-----------------------------------------------------------------------------
+void DatPanel::setSlice(int k)
+{
+	if(k>=nz)	k=nz-1;
+	if(k<0)	k=0;
+	if(k!=kz)
+	{
+		infoDlg->setSlice(k);
+		emit sliceChanged(k);
+		kz = k;		refresh();
+	}
+}
+//-----------------------------------------------------------------------------
+dual mgl_str2dual(const char *s)
+{
+	setlocale(LC_NUMERIC, "C");
+	double re=0,im=0;	size_t ll=strlen(s);
+	while(s[ll]<=' ')	ll--;
+	if(*s=='(')		sscanf(s,"(%lg,%lg)",&re,&im);
+	else if(*s=='i')	{	re=0;	im=atof(s+1);	}
+	else if(*s=='[')	sscanf(s,"[%lg,%lg]",&re,&im);
+	else if(*s=='{')	sscanf(s,"{%lg,%lg}",&re,&im);
+	else if(s[ll]=='i')
+	{
+		double a,b;
+		int s1=sscanf(s,"%lg+%lgi",&re,&im);
+		int s2=sscanf(s,"%lg-%lgi",&a,&b);
+		if(s1<2)
+		{
+		if(s2==2)	{	re=a;	im=-b;	}
+		else	{	im=atof(s);	re=0;	}
+		}
+	}
+	else
+	{
+		double a,b;
+		int s1=sscanf(s,"%lg+i%lg",&re,&im);
+		int s2=sscanf(s,"%lg-i%lg",&a,&b);
+		if(s1<2)
+		{
+		if(s2==2)	{	re=a;	im=-b;	}
+		else	{	re=atof(s);	im=0;	}
+		}
+	}
+	setlocale(LC_NUMERIC, "");
+	return dual(re,im);
+}
+//-----------------------------------------------------------------------------
+void DatPanel::putValue(int r, int c)
+{
+	if(!var || r<0 || c<0 || r>=ny || c>=nx || !ready)	return;
+	QString s = tab->item(r,c)->text().toLower();
+	mreal f;
+	dual g;
+	if(s=="nan")	f=NAN;
+	else if(s=="inf")	f=INFINITY;
+	else if(s=="-inf")	f=-INFINITY;
+	else
+	{	g = mgl_str2dual(s.toLocal8Bit().constData());	f = real(g);	}
+	mglDataC *cc = dynamic_cast<mglDataC*>(var);
+	if(cc)
+	{
+		if(g!=cc->a[c+nx*(r+ny*kz)])
+		{
+			if(mgl_isnan(g))	s="nan";
+			else if(mgl_isbad(g))	s="inf";
+			else if(imag(g)>0)	s.sprintf("%g+%gi",real(g),imag(g));
+			else if(imag(g)<0)	s.sprintf("%g-%gi",real(g),-imag(g));
+			else	s.sprintf("%g",real(g));
+			tab->item(r,c)->setText(s);
+		}
+		cc->a[c+nx*(r+ny*kz)] = g;
+	}
+	else
+	{
+		if(f!=var->v(c,r,kz))
+		{
+			if(mgl_isnan(f))	s="nan";
+			else if(mgl_isbad(f))	s=f>0?"inf":"-inf";
+			else	s.sprintf("%g", f);
+			tab->item(r,c)->setText(s);
+		}
+		var->set_v(f,c,r,kz);
+	}
+	infoDlg->refresh();
+}
+//-----------------------------------------------------------------------------
+void DatPanel::save()
+{
+	QString fn = QFileDialog::getSaveFileName(this, _("UDAV - Save/export data"), "",
+				_("Data files (*.dat)\nHDF5 files (*.h5 *.hdf)\nPNG files (*.png)\nAll files (*.*)"));
+	if(fn.isEmpty())	return;
+	QString ext = fn.section(".",-1);
+	if(ext=="png")
+	{
+		bool ok;
+		QString s = QInputDialog::getText(this, _("UDAV - Export to PNG"), _("Enter color scheme"), QLineEdit::Normal, MGL_DEF_SCH, &ok);
+		if(ok)	var->Export(fn.toLocal8Bit().constData(), s.toLocal8Bit().constData());
+	}
+	else if(ext=="h5" || ext=="hdf")
+	{
+		bool ok;
+		QString s = QInputDialog::getText(this, _("UDAV - Save to HDF"), _("Enter data name"), QLineEdit::Normal, QString::fromWCharArray(var->s.c_str()), &ok);
+		if(ok)	var->SaveHDF(fn.toLocal8Bit().constData(), s.toLocal8Bit().constData());
+	}
+	else 	var->Save(fn.toLocal8Bit().constData());
+}
+//-----------------------------------------------------------------------------
+void DatPanel::load()
+{
+	mglData *d = dynamic_cast<mglData *>(var);	if(!d)	return;
+	QString fn = QFileDialog::getOpenFileName(this, _("UDAV - Load data"), "",
+				_("Data files (*.dat)\nHDF5 files (*.h5 *.hdf)\nPNG files (*.png)\nAll files (*.*)"));
+	if(fn.isEmpty())	return;
+	QString ext = fn.section(".",-1);
+	if(ext=="png")
+	{
+		bool ok;
+		QString s = QInputDialog::getText(this, _("UDAV - Import PNG"), _("Enter color scheme"), QLineEdit::Normal, MGL_DEF_SCH, &ok);
+		if(ok)	d->Import(fn.toLocal8Bit().constData(), s.toLocal8Bit().constData());
+	}
+	else if(ext=="h5" || ext=="hdf")
+	{
+		bool ok;
+		QString s = QInputDialog::getText(this, _("UDAV - Read from HDF"), _("Enter data name"), QLineEdit::Normal, QString::fromWCharArray(var->s.c_str()), &ok);
+		if(ok)	d->ReadHDF(fn.toLocal8Bit().constData(), s.toLocal8Bit().constData());
+	}
+	else 	d->Read(fn.toLocal8Bit().constData());
+	refresh();
+}
+//-----------------------------------------------------------------------------
+void DatPanel::copy()
+{
+	QTableWidgetSelectionRange ts = tab->selectedRanges().first();
+	QString res, s;
+	for(long j=ts.topRow();j<=ts.bottomRow();j++)
+	{
+		for(long i=ts.leftColumn();i<=ts.rightColumn();i++)
+		{
+			res = res + tab->item(j,i)->text();
+			if(i<ts.rightColumn())	res = res + "\t";
+		}
+		res = res + "\n";
+	}
+	QApplication::clipboard()->setText(res, QClipboard::Clipboard);
+}
+//-----------------------------------------------------------------------------
+void DatPanel::paste()
+{
+	QString txt = QApplication::clipboard()->text(QClipboard::Clipboard);
+	QString s, t;
+	int r = tab->currentRow(), c = tab->currentColumn(), i, j;
+	for(i=0;i<ny-r;i++)
+	{
+		s = txt.section('\n',i,i,QString::SectionSkipEmpty);
+		if(s.isEmpty())	break;
+		for(j=0;j<nx-c;j++)
+		{
+			t = s.section('\t',j,j,QString::SectionSkipEmpty);
+			if(t.isEmpty())	{	j=nx;	continue;	}
+			var->set_v(t.toDouble(),j+c,i+r,kz);
+		}
+	}
+	refresh();
+}
+//-----------------------------------------------------------------------------
+void DatPanel::plot()	// TODO: plot dialog
+{
+
+}
+//-----------------------------------------------------------------------------
+void DatPanel::list()	// TODO: in which script insert ???
+{
+/*	if(nx*ny+ny > 1020)
+	{	QMessageBox::warning(this, _("UDAV - To list conversion"), _("Too many numbers (>1000) on slice"), QMessageBox::Ok, 0, 0);	return;	}
+	if(nz > 1)
+		QMessageBox::information(this, _("UDAV - To list conversion"), _("Only current slice will be inserted"), QMessageBox::Ok, 0, 0);
+	QString res = "list\t", s;
+	for(long j=0;j<ny;j++)
+	{
+	for(long i=0;i<nx;i++)
+		{
+			s.sprintf("%g\t",d->a[i+nx*(j+kz*ny)]);
+			res += s;
+		}
+		if(j<ny-1)	res = res + "|\t";
+	}*/
+}
+//-----------------------------------------------------------------------------
+void DatPanel::inrange()
+{
+	QString v1("-1"), v2("1"), dir("x");
+	if(sizesDialog(_("UDAV - Fill data"), _("Enter range for data and direction of filling"), _("From"), _("To"), _("Direction"), v1, v2, dir))
+	{
+		mglData *d = dynamic_cast<mglData *>(var);
+		if(d)	d->Fill(v1.toDouble(), v2.toDouble(), dir[0].toLatin1());
+		mglDataC *dc = dynamic_cast<mglDataC *>(var);
+		if(dc)	dc->Fill(v1.toDouble(), v2.toDouble(), dir[0].toLatin1());
+		mglDataV *dv = dynamic_cast<mglDataV *>(var);
+		if(dv)	dv->Fill(v1.toDouble(), v2.toDouble(), dir[0].toLatin1());
+		refresh();
+	}
+}
+//-----------------------------------------------------------------------------
+void DatPanel::norm()
+{
+	QString v1("0"), v2("1"), how;
+	if(sizesDialog(_("UDAV - Normalize data"), _("Enter range for final data"), _("From"), _("To"), _("Symmetrical?"), v1, v2, how))
+	{
+		mglData *d = dynamic_cast<mglData *>(var);
+		if(d)	d->Norm(v1.toDouble(), v2.toDouble(), (how=="on" || how.contains('s')));
+		refresh();
+	}
+}
+//-----------------------------------------------------------------------------
+void DatPanel::normsl()
+{
+	QString v1("0"), v2("1"), dir("z");
+	if(sizesDialog(_("UDAV - Normalize by slice"), _("Enter range for final data"), _("From"), _("To"), _("Direction"), v1, v2, dir))
+	{
+		mglData *d = dynamic_cast<mglData *>(var);
+		if(d)	d->NormSl(v1.toDouble(), v2.toDouble(), dir[0].toLatin1());
+		refresh();
+	}
+}
+//-----------------------------------------------------------------------------
+void DatPanel::create()
+{
+	QString mx, my("1"), mz("1");
+	if(sizesDialog(_("UDAV - Clear data"), _("Enter new data sizes"), _("X-size"), _("Y-size"), _("Z-size"), mx, my, mz))
+	{
+		mglData *d = dynamic_cast<mglData *>(var);
+		if(d)	d->Create(mx.toInt(), my.toInt(), mz.toInt());
+		mglDataC *c = dynamic_cast<mglDataC *>(var);
+		if(c)	c->Create(mx.toInt(), my.toInt(), mz.toInt());
+		refresh();	updateDataItems();
+	}
+}
+//-----------------------------------------------------------------------------
+void DatPanel::reSize()
+{
+	QString mx, my, mz;
+	mx.sprintf("%d",nx);	my.sprintf("%d",ny);	mz.sprintf("%d",nz);
+	if(sizesDialog(_("UDAV - Resize data"), _("Enter new data sizes"), _("X-size"), _("Y-size"), _("Z-size"), mx, my, mz))
+	{
+		mglData *d = dynamic_cast<mglData *>(var);
+		if(d)	d->Set(d->Resize(mx.toInt(), my.toInt(), mz.toInt()));
+		refresh();	updateDataItems();
+	}
+}
+//-----------------------------------------------------------------------------
+void DatPanel::squize()
+{
+	QString mx("1"), my("1"), mz("1");
+	if(sizesDialog(_("UDAV - Squeeze data"), _("Enter step of saved points. For example, '1' save all, '2' save each 2nd point, '3' save each 3d and so on."), _("X-direction"), _("Y-direction"), _("Z-direction"), mx, my, mz))
+	{
+		mglData *d = dynamic_cast<mglData *>(var);
+		if(d)	d->Squeeze(mx.toInt(), my.toInt(), mz.toInt());
+		refresh();	updateDataItems();
+	}
+}
+//-----------------------------------------------------------------------------
+void DatPanel::crop()
+{
+	QString n1("1"), n2("1"), dir;
+	if(sizesDialog(_("UDAV - Crop data"), _("Enter range of saved date."), _("From"), _("To"), _("Direction"), n1, n2, dir))
+	{
+		mglData *d = dynamic_cast<mglData *>(var);
+		if(d)	d->Squeeze(n1.toInt(), n2.toInt(), dir[0].toLatin1());
+		refresh();	updateDataItems();
+	}
+}
+//-----------------------------------------------------------------------------
+void DatPanel::rearrange()
+{
+	QString mx, my, mz;
+	mx.sprintf("%d",nx);	my.sprintf("%d",ny);	mz.sprintf("%d",nz);
+	if(sizesDialog(_("UDAV - Rearrange data"), _("Enter new data sizes"), _("X-size"), _("Y-size"), _("Z-size"), mx, my, mz))
+	{
+		mglData *d = dynamic_cast<mglData *>(var);
+		if(d)	d->Rearrange(mx.toInt(), my.toInt(), mz.toInt());
+		refresh();	updateDataItems();
+	}
+}
+//-----------------------------------------------------------------------------
+void DatPanel::hist()
+{
+	QLabel *l;
+	QLineEdit *id, *v1, *v2;
+	QSpinBox *nm;
+	QPushButton *b;
+	QDialog *d = new QDialog(this);	d->setWindowTitle(_("UDAV - Make histogram"));
+	QGridLayout *g = new QGridLayout(d);
+	l = new QLabel(_("From"), d);	g->addWidget(l,0,0);
+	l = new QLabel(_("To"), d);	g->addWidget(l,0,1);
+	v1 = new QLineEdit(d);	g->addWidget(v1,1,0);
+	v2 = new QLineEdit(d);	g->addWidget(v2,1,1);
+	l = new QLabel(_("Number of points"), d);	g->addWidget(l,2,0);
+	l = new QLabel(_("Put in variable"), d);	g->addWidget(l,2,1);
+	nm = new QSpinBox(d);	nm->setRange(2,8192);	g->addWidget(nm,3,0);
+	id = new QLineEdit(d);	nm->setSingleStep(10);	g->addWidget(id,3,1);
+	b = new QPushButton(_("Cancel"), d);	g->addWidget(b,4,0);
+	connect(b, SIGNAL(clicked()), d, SLOT(reject()));
+	b = new QPushButton(_("OK"), d);		g->addWidget(b,4,1);
+	connect(b, SIGNAL(clicked()), d, SLOT(accept()));	b->setDefault(true);
+	// now execute dialog and get values
+	bool res = d->exec();
+	if(res && !v1->text().isEmpty() && !v2->text().isEmpty() && !id->text().isEmpty())
+	{
+		mglData *vv = dynamic_cast<mglData*>(parser.AddVar(id->text().toLocal8Bit().constData()));
+		if(vv)	vv->Set(mgl_data_hist(var, nm->value(), v1->text().toDouble(), v2->text().toDouble(),0));
+		updateDataItems();
+	}
+}
+//-----------------------------------------------------------------------------
+void DatPanel::first()	{	setSlice(0);	}
+//-----------------------------------------------------------------------------
+void DatPanel::last()	{	setSlice(nz-1);	}
+//-----------------------------------------------------------------------------
+void DatPanel::next()	{	setSlice(kz+1);	}
+//-----------------------------------------------------------------------------
+void DatPanel::prev()	{	setSlice(kz-1);	}
+//-----------------------------------------------------------------------------
+void DatPanel::gosl()
+{
+	bool ok;
+	QString s = QInputDialog::getText(this, _("UDAV - Go to slice"), _("Enter slice id:"), QLineEdit::Normal, "0", &ok);
+	if(ok)	setSlice(s.toInt());
+}
+//-----------------------------------------------------------------------------
+void DatPanel::setNz(int nz)	{	sb->setMaximum(nz-1);	}
+//-----------------------------------------------------------------------------
+bool DatPanel::sizesDialog(const QString &cap, const QString &lab, const QString &desc1, const QString &desc2, const QString &desc3, QString &val1, QString &val2, QString &val3)
+{
+	QLabel *l;
+	QLineEdit *f1, *f2, *f3;
+	QPushButton *b;
+	QDialog *d = new QDialog(this);
+	d->setWindowTitle(cap);
+	QVBoxLayout *v = new QVBoxLayout(d);
+	l = new QLabel(lab, d);	v->addWidget(l);
+	l = new QLabel(_("NOTE: All fields must be filled!"), d);	v->addWidget(l);
+	QGridLayout *g = new QGridLayout();	v->addLayout(g);
+	l = new QLabel(desc1, d);		g->addWidget(l, 0, 0);
+	l = new QLabel(desc2, d);		g->addWidget(l, 0, 1);
+	l = new QLabel(desc3, d);		g->addWidget(l, 0, 2);
+	f1 = new QLineEdit(val1, d);	g->addWidget(f1, 1, 0);
+	f2 = new QLineEdit(val2, d);	g->addWidget(f2, 1, 1);
+	f3 = new QLineEdit(val3, d);	g->addWidget(f3, 1, 2);
+	QHBoxLayout *h = new QHBoxLayout();	v->addLayout(h);
+	h->addStretch(1);
+	b = new QPushButton(_("Cancel"), d);	h->addWidget(b);
+	connect(b, SIGNAL(clicked()), d, SLOT(reject()));
+	b = new QPushButton(_("OK"), d);		h->addWidget(b);
+	connect(b, SIGNAL(clicked()), d, SLOT(accept()));
+	b->setDefault(true);
+	// now execute dialog and get values
+	bool res = d->exec();
+	val1 = f1->text();	val2 = f2->text();	val3 = f3->text();
+	if(val1.isEmpty() || val2.isEmpty() || val3.isEmpty())	res = false;
+	delete d;
+	return res;
+}
+//-----------------------------------------------------------------------------
+#include "xpm/size.xpm"
+#include "xpm/crop.xpm"
+#include "xpm/squize.xpm"
+#include "xpm/hist.xpm"
+#include "xpm/oper_dir.xpm"
+#include "xpm/oper_of.xpm"
+//-----------------------------------------------------------------------------
+void DatPanel::newdat()
+{
+	QLabel *l;
+	QLineEdit *f1, *f2;
+	QPushButton *b;
+	QDialog *d = new QDialog(this);
+	d->setWindowTitle(_("UDAV - make new data"));
+	QVBoxLayout *v = new QVBoxLayout(d);
+	QComboBox *c = new QComboBox(d);	v->addWidget(c);
+	c->addItem(_("Sum along direction(s)"));
+	c->addItem(_("Min along direction(s)"));
+	c->addItem(_("Max along direction(s)"));
+	c->addItem(_("Momentum along 'x' for function"));
+	c->addItem(_("Momentum along 'y' for function"));
+	c->addItem(_("Momentum along 'z' for function"));
+	c->setCurrentIndex(0);
+
+	f1 = new QLineEdit("z",d);	v->addWidget(f1);
+	QCheckBox *cb = new QCheckBox(_("Put into this data array"), d);	v->addWidget(cb);
+	l = new QLabel(_("or enter name for new variable"), d);	v->addWidget(l);
+	f2 = new QLineEdit(d);		v->addWidget(f2);
+	QHBoxLayout *h = new QHBoxLayout();	v->addLayout(h);	h->addStretch(1);
+	b = new QPushButton(_("Cancel"), d);	h->addWidget(b);
+	connect(b, SIGNAL(clicked()), d, SLOT(reject()));
+	b = new QPushButton(_("OK"), d);		h->addWidget(b);
+	connect(b, SIGNAL(clicked()), d, SLOT(accept()));
+	b->setDefault(true);
+	// now execute dialog and get values
+	bool res = d->exec();
+	QString 	val = f1->text(), mgl;
+	int k = c->currentIndex();
+	QString self = QString::fromWCharArray(var->s.c_str());
+	if(res)
+	{
+		if(k<0)
+		{
+			QMessageBox::warning(d, _("UDAV - make new data"),
+				_("No action is selected. Do nothing."));
+			return;
+		}
+		if(val.isEmpty())
+		{
+			QMessageBox::warning(d, _("UDAV - make new data"),
+				_("No direction/formula is entered. Do nothing."));
+			return;
+		}
+		if(cb->isChecked())	k += 6;
+		QString name = f2->text();
+		switch(k)
+		{
+		case 0:	mgl = "sum "+name+" "+self+" '"+val+"'";	break;
+		case 1:	mgl = "min "+name+" "+self+" '"+val+"'";	break;
+		case 2:	mgl = "max "+name+" "+self+" '"+val+"'";	break;
+		case 3:	mgl = "momentum "+name+" "+self+" 'x' '"+val+"'";	break;
+		case 4:	mgl = "momentum "+name+" "+self+" 'y' '"+val+"'";	break;
+		case 5:	mgl = "momentum "+name+" "+self+" 'z' '"+val+"'";	break;
+		case 6:	mgl = "copy "+self+" {sum "+self+" '"+val+"'}";	break;
+		case 7:	mgl = "copy "+self+" {min "+self+" '"+val+"'}";	break;
+		case 8:	mgl = "copy "+self+" {max "+self+" '"+val+"'}";	break;
+		case 9:	mgl = "copy "+self+" {momentum "+self+" 'x' '"+val+"'}";	break;
+		case 10:	mgl = "copy "+self+" {momentum "+self+" 'y' '"+val+"'}";	break;
+		case 11:	mgl = "copy "+self+" {momentum "+self+" 'z' '"+val+"'}";	break;
+		}
+	}
+	if(!mgl.isEmpty())
+	{
+		mglGraph gr;
+		parser.Execute(&gr,mgl.toLocal8Bit().constData());
+		if(k>=6)	opers += mgl+"\n";
+		updateDataItems();
+	}
+}
+//-----------------------------------------------------------------------------
+void DatPanel::oper()
+{
+	QLineEdit *f1;
+	QPushButton *b;
+	QDialog *d = new QDialog(this);
+	d->setWindowTitle(_("UDAV - change data"));
+	QVBoxLayout *v = new QVBoxLayout(d);
+	QComboBox *c = new QComboBox(d);	v->addWidget(c);
+	c->addItem(_("Fill data by formula"));
+	c->addItem(_("Transpose data with new dimensions"));
+	c->addItem(_("Smooth data along direction(s)"));
+	c->addItem(_("Summarize data along direction(s)"));
+	c->addItem(_("Integrate data along direction(s)"));
+	c->addItem(_("Differentiate data along direction(s)"));
+	c->addItem(_("Laplace transform along direction(s)"));
+	c->addItem(_("Swap data along direction(s)"));
+	c->addItem(_("Mirror data along direction(s)"));
+	c->addItem(_("Sin-Fourier transform along direction(s)"));
+	c->addItem(_("Cos-Fourier transform along direction(s)"));
+	c->addItem(_("Hankel transform along direction(s)"));
+	c->addItem(_("Sew data along direction(s)"));
+	c->addItem(_("Find envelope along direction(s)"));
+	c->setCurrentIndex(0);
+
+	f1 = new QLineEdit("z",d);	v->addWidget(f1);
+	QHBoxLayout *h = new QHBoxLayout();	v->addLayout(h);	h->addStretch(1);
+	b = new QPushButton(_("Cancel"), d);	h->addWidget(b);
+	connect(b, SIGNAL(clicked()), d, SLOT(reject()));
+	b = new QPushButton(_("OK"), d);		h->addWidget(b);
+	connect(b, SIGNAL(clicked()), d, SLOT(accept()));
+	b->setDefault(true);
+	// now execute dialog and get values
+	bool res = d->exec();
+	QString 	val = f1->text(), mgl;
+	int k = c->currentIndex();
+	QString self = QString::fromWCharArray(var->s.c_str());
+	if(res)
+	{
+		if(k<0)
+		{
+			QMessageBox::warning(d, _("UDAV - make new data"),
+				_("No action is selected. Do nothing."));
+			return;
+		}
+		switch(k)
+		{
+		case 0:	mgl = "modify "+self+" '"+val+"'";	break;
+		case 1:	mgl = "transpose "+self+" '"+val+"'";	break;
+		case 2:	mgl = "smooth "+self+" '"+val+"'";	break;
+		case 3:	mgl = "cumsum "+self+" '"+val+"'";	break;
+		case 4:	mgl = "integrate "+self+" '"+val+"'";	break;
+		case 5:	mgl = "diff "+self+" '"+val+"'";	break;
+		case 6:	mgl = "diff2 "+self+" '"+val+"'";	break;
+		case 7:	mgl = "swap "+self+" '"+val+"'";	break;
+		case 8:	mgl = "mirror "+self+" '"+val+"'";	break;
+		case 9:	mgl = "sinfft "+self+" '"+val+"'";	break;
+		case 10:	mgl = "cosfft "+self+" '"+val+"'";	break;
+		case 11:	mgl = "hankel "+self+" '"+val+"'";	break;
+		case 12:	mgl = "sew "+self+" '"+val+"'";	break;
+		case 13:	mgl = "envelop "+self+" '"+val+"'";	break;
+		}
+	}
+	if(!mgl.isEmpty())
+	{
+		mglGraph gr;
+		parser.Execute(&gr,mgl.toLocal8Bit().constData());
+		opers += mgl+"\n";
+		updateDataItems();
+	}
+}
+//-----------------------------------------------------------------------------
+void DatPanel::toolTop(QBoxLayout *l)
+{
+	QAction *a;
+	QMenu *o;
+	QToolButton *bb;
+
+	// file menu
+	o = menu->addMenu(_("File"));
+	a = new QAction(QPixmap(":/png/document-open.png"), _("Load data"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(load()));
+	a->setToolTip(_("Load data from file. Data will be deleted only\nat exit but UDAV will not ask to save it (Ctrl+Shift+O)."));
+	a->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_O);	o->addAction(a);
+	bb = new QToolButton(this);	l->addWidget(bb);	bb->setDefaultAction(a);
+
+	a = new QAction(QPixmap(":/png/document-save.png"), _("Save data"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(save()));
+	a->setToolTip(_("Save data to a file (Ctrl+Shift+S)."));
+	a->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_S);	o->addAction(a);
+	bb = new QToolButton(this);	l->addWidget(bb);	bb->setDefaultAction(a);
+
+//	o->addSeparator();	bb->addSeparator();
+//	a = new QAction(QPixmap(insert_xpm), _("Insert as list"), this);
+//	connect(a, SIGNAL(triggered()), this, SLOT(list()));
+//	o->addAction(a);
+//	bb = new QToolButton(this);	l->addWidget(bb);	bb->setDefaultAction(a);
+
+
+	a = new QAction(QPixmap(":/png/office-chart-line.png"), _("Plot data"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(plot()));
+	a->setToolTip(_("Plot data in new script window. You may select the kind\nof plot, its style and so on."));
+	o->addAction(a);
+	bb = new QToolButton(this);	l->addWidget(bb);	bb->setDefaultAction(a);
+
+	a = new QAction(QPixmap(":/png/edit-copy.png"), _("Copy data"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(copy()));
+	a->setToolTip(_("Copy range of numbers to clipboard (Ctrl+Shift+C)."));
+	a->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_C);	o->addAction(a);
+	bb = new QToolButton(this);	l->addWidget(bb);	bb->setDefaultAction(a);
+
+	a = new QAction(QPixmap(":/png/edit-paste.png"), _("Paste data"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(copy()));
+	a->setToolTip(_("Paste range of numbers from clipboard (Ctrl+Shift+P)."));
+	a->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_V);	o->addAction(a);
+	bb = new QToolButton(this);	l->addWidget(bb);	bb->setDefaultAction(a);
+
+	// navigation menu
+	o = menu->addMenu(_("Navigation"));
+	a = new QAction(QPixmap(":/png/go-first.png"), _("First slice"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(first()));
+	a->setToolTip(_("Go to first slice for 3D data (Ctrl-F1)."));
+	a->setShortcut(Qt::CTRL+Qt::Key_F1);	o->addAction(a);
+	bb = new QToolButton(this);	l->addWidget(bb);	bb->setDefaultAction(a);
+
+	a = new QAction(QPixmap(":/png/go-previous.png"), _("Prev slice"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(prev()));
+	a->setToolTip(_("Go to the previous slice for 3D data."));
+	o->addAction(a);
+	bb = new QToolButton(this);	l->addWidget(bb);	bb->setDefaultAction(a);
+
+	sb = new QSpinBox(this);
+	l->addWidget(sb);	sb->setRange(0,0);
+	sb->setToolTip(_("Go to the specified slice for 3D data."));
+	connect(sb, SIGNAL(valueChanged(int)), this, SLOT(setSlice(int)));
+	connect(this, SIGNAL(sliceChanged(int)), sb, SLOT(setValue(int)));
+	connect(this, SIGNAL(nzChanged(int)), this, SLOT(setNz(int)));
+
+	a = new QAction(_("Go to slice"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(gosl()));
+	a->setToolTip(_("Go to the specified slice for 3D data."));
+	o->addAction(a);
+
+	a = new QAction(QPixmap(":/png/go-next.png"), _("Next slice"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(next()));
+	a->setToolTip(_("Go to the next slice for 3D data."));
+	o->addAction(a);
+	bb = new QToolButton(this);	l->addWidget(bb);	bb->setDefaultAction(a);
+
+	a = new QAction(QPixmap(":/png/go-last.png"), _("Last slice"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(last()));
+	a->setToolTip(_("Go to last slice for 3D data (Ctrl-F4)."));
+	a->setShortcut(Qt::CTRL+Qt::Key_F4);	o->addAction(a);
+	bb = new QToolButton(this);	l->addWidget(bb);	bb->setDefaultAction(a);
+}
+//-----------------------------------------------------------------------------
+void DatPanel::toolLeft(QBoxLayout *l)
+{
+	QAction *a;
+	QMenu *o;
+	QToolButton *bb;
+
+	// size menu
+	o = menu->addMenu(_("Sizes"));
+	a = new QAction(QPixmap(":/png/document-new.png"), _("Create new"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(create()));
+	a->setToolTip(_("Recreate the data with new sizes and fill it by zeros (Ctrl+Shift+N)."));
+	a->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_N);	o->addAction(a);
+	bb = new QToolButton(this);	l->addWidget(bb);	bb->setDefaultAction(a);
+
+	a = new QAction(QPixmap(size_xpm), _("Resize"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(reSize()));
+	a->setToolTip(_("Resize (interpolate) the data to specified sizes (Ctrl+Shift+R)."));
+	a->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_R);	o->addAction(a);
+	bb = new QToolButton(this);	l->addWidget(bb);	bb->setDefaultAction(a);
+
+	a = new QAction(QPixmap(squize_xpm), _("Squeeze"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(squize()));
+	a->setToolTip(_("Keep only each n-th element of the data array."));
+	o->addAction(a);
+	bb = new QToolButton(this);	l->addWidget(bb);	bb->setDefaultAction(a);
+
+	a = new QAction(QPixmap(crop_xpm), _("Crop"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(crop()));
+	a->setToolTip(_("Crop the data edges. Useful to cut off the zero-filled area."));
+	o->addAction(a);
+	bb = new QToolButton(this);	l->addWidget(bb);	bb->setDefaultAction(a);
+
+	a = new QAction(QPixmap(oper_of_xpm), _("Transform"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(newdat()));
+	a->setToolTip(_("Transform data along dimension(s) (Ctrl+Shift+T)."));
+	a->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_T);	o->addAction(a);
+	bb = new QToolButton(this);	l->addWidget(bb);	bb->setDefaultAction(a);
+
+	a = new QAction(QPixmap(oper_dir_xpm), _("Make new (Ctrl+Shift+M)"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(oper()));
+	a->setToolTip(_("Make another data."));
+	a->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_M);	o->addAction(a);
+	bb = new QToolButton(this);	l->addWidget(bb);	bb->setDefaultAction(a);
+
+	a = new QAction(QPixmap(hist_xpm), _("Histogram (Ctrl+Shift+H)"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(hist()));
+	a->setToolTip(_("Find histogram of data."));
+	a->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_H);	o->addAction(a);
+	bb = new QToolButton(this);	l->addWidget(bb);	bb->setDefaultAction(a);
+
+/*	a = new QAction(QPixmap(":/png/view-refresh.png"), _("Refresh"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(refresh()));
+	a->setToolTip(_("Refresh data values."));
+	o->addAction(a);
+	bb = new QToolButton(this);	l->addWidget(bb);	bb->setDefaultAction(a);*/
+
+/*	a = new QAction(_("Rearrange"), this);	// TODO: move in generalized dialog
+	connect(a, SIGNAL(triggered()), this, SLOT(rearrange()));
+	a->setToolTip(_("Rearrange data sizes without changing data values."));
+	o->addAction(a);
+	a = new QAction(_("Fill in range"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(inrange()));
+	a->setToolTip(_("Fill data equidistantly from one value to another."));
+	o->addAction(a);
+	a = new QAction(_("Normalize"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(norm()));
+	a->setToolTip(_("Normalize data so that its minimal\nand maximal values be in specified range."));
+	o->addAction(a);
+	a = new QAction(_("Norm. slices"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(normsl()));
+	a->setToolTip(_("Normalize each data slice perpendicular to some direction\nso that its minimal and maximal values be in specified range."));
+	o->addAction(a);*/
+
+	l->addStretch(1);
+
+	a = new QAction(QPixmap(":/png/tab-close.png"), _("Close tab"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(close()));
+	a->setToolTip(_("Close this data tab."));
+	bb = new QToolButton(this);	l->addWidget(bb);	bb->setDefaultAction(a);
+}
+//-----------------------------------------------------------------------------
+QString DatPanel::dataName()	{	return QString::fromWCharArray(var->s.c_str());	}
+//-----------------------------------------------------------------------------
diff --git a/udav/dat_pnl.h b/udav/dat_pnl.h
new file mode 100644
index 0000000..1ddd32a
--- /dev/null
+++ b/udav/dat_pnl.h
@@ -0,0 +1,104 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef DAT_PNL_H
+#define DAT_PNL_H
+//-----------------------------------------------------------------------------
+#include <QWidget>
+//-----------------------------------------------------------------------------
+class mglDataA;
+class QMenu;
+class QBoxLayout;
+class QTableWidget;
+class QSpinBox;
+class InfoDialog;
+//-----------------------------------------------------------------------------
+/// Window for viewing, handling and editing the data array
+class DatPanel : public QWidget
+{
+Q_OBJECT
+public:
+	QMenu *menu;
+	InfoDialog *infoDlg;	///< Reference to dialog !!!
+	DatPanel(InfoDialog *inf, QWidget *parent = 0);
+	~DatPanel();
+
+	void setVar(mglDataA *v);
+	inline long GetNz()	{	return nz;	}	///< Get number of slices
+	QString dataName();
+
+public slots:
+	QString dataOper()	{	return opers;	}
+	void refresh();		///< Refresh table with new data values
+
+signals:
+	void sliceChanged(int);
+	void nzChanged(int);
+
+private slots:
+	void setSlice(int k);
+	void putValue(int r, int c);
+	// menu genereal
+	void load();
+	void save();
+	void copy();
+	void paste();
+	void plot();
+	void list();
+	// menu fill
+	void inrange();
+	void norm();
+	void normsl();
+	// menu resize
+	void create();
+	void reSize();
+	void squize();
+	void crop();
+	void rearrange();
+	// menu change
+	void oper();
+	// menu another
+	void newdat();
+	void hist();
+	// menu navigation
+	void first();
+	void last();
+	void next();
+	void prev();
+	void gosl();
+	void setNz(int nz);
+
+private:
+	int nx,ny,nz;	///< Data sizes
+	QString id;
+	QString opers;	///< MGL script of all operations done on data
+	QTableWidget *tab;	///< Table itself
+	int kz;			///< Current z-slice
+	mglDataA *var;	///< Variable with data
+//	QSpinBox *sb;	///< SpinBox for selecting slice
+	bool ready;		///< Data is refreshed
+	QSpinBox *sb;
+
+	bool sizesDialog(const QString &cap, const QString &lab, const QString &desc1, const QString &desc2, const QString &desc3, QString &val1, QString &val2, QString &val3);
+	void toolTop(QBoxLayout *l);
+	void toolLeft(QBoxLayout *l);
+};
+//-----------------------------------------------------------------------------
+#endif // DAT_PNL_H
+//-----------------------------------------------------------------------------
diff --git a/udav/data_dlg.cpp b/udav/data_dlg.cpp
new file mode 100644
index 0000000..7fcf7a5
--- /dev/null
+++ b/udav/data_dlg.cpp
@@ -0,0 +1,145 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <QPushButton>
+#include <QComboBox>
+#include <QSpinBox>
+#include <QLayout>
+#include <QLabel>
+#include <QLineEdit>
+//-----------------------------------------------------------------------------
+#include <mgl2/mgl.h>
+extern mglParse parser;
+#include "data_dlg.h"
+//-----------------------------------------------------------------------------
+DataDialog::DataDialog(QWidget* parent): QDialog(parent)
+{
+	setWindowTitle(_("UDAV - Insert style/scheme"));
+	QHBoxLayout *h;
+	QVBoxLayout *v;
+	QGridLayout *g;
+	QLabel *l;
+	QPushButton *b;
+
+	v = new QVBoxLayout(this);
+	h = new QHBoxLayout();	v->addLayout(h);
+	l = new QLabel(_("Data name"), this);	h->addWidget(l);
+	name = new QComboBox(this);	h->addWidget(name);
+	
+	g = new QGridLayout();	v->addLayout(g);
+
+	l = new QLabel("x1", this);	g->addWidget(l, 0, 0);
+	x1 = new QSpinBox(this);	x1->setMinimum(-1);	g->addWidget(x1, 0, 1);
+	l = new QLabel("x2", this);	g->addWidget(l, 0, 2);
+	x2 = new QSpinBox(this);	x2->setMinimum(-1);	g->addWidget(x2, 0, 3);
+	
+	l = new QLabel("y1", this);	g->addWidget(l, 1, 0);
+	y1 = new QSpinBox(this);	y1->setMinimum(-1);	g->addWidget(y1, 1, 1);
+	l = new QLabel("y2", this);	g->addWidget(l, 1, 2);
+	y2 = new QSpinBox(this);	y2->setMinimum(-1);	g->addWidget(y2, 1, 3);
+	
+	l = new QLabel("z1", this);	g->addWidget(l, 2, 0);
+	z1 = new QSpinBox(this);	z1->setMinimum(-1);	g->addWidget(z1, 2, 1);
+	l = new QLabel("z2", this);	g->addWidget(l, 2, 2);
+	z2 = new QSpinBox(this);	z2->setMinimum(-1);	g->addWidget(z2, 2, 3);
+
+	x1->setValue(-1);	y1->setValue(-1);	z1->setValue(-1);
+	x2->setValue(-1);	y2->setValue(-1);	z2->setValue(-1);
+	
+	l = new QLabel(_("Operation"));	g->addWidget(l, 3, 0);
+	oper = new QComboBox(this);		g->addWidget(oper, 3, 1);
+	oper->addItem(_("none"));		oper->addItem(_("sum"));
+	oper->addItem(_("min"));	oper->addItem(_("max"));
+	l = new QLabel("along", this);	g->addWidget(l, 3, 2);
+	dirs = new QComboBox(this);		g->addWidget(dirs, 3, 3);
+	dirs->addItem("xyz");
+	dirs->addItem("x");	dirs->addItem("y");	dirs->addItem("z");
+	dirs->addItem("xy");	dirs->addItem("xz");	dirs->addItem("yz");
+
+	connect(name, SIGNAL(currentIndexChanged(int)), this, SLOT(nameChanged()));
+	connect(x1, SIGNAL(valueChanged(int)), this, SLOT(updateRes()));
+	connect(x2, SIGNAL(valueChanged(int)), this, SLOT(updateRes()));
+	connect(y1, SIGNAL(valueChanged(int)), this, SLOT(updateRes()));
+	connect(y2, SIGNAL(valueChanged(int)), this, SLOT(updateRes()));
+	connect(z1, SIGNAL(valueChanged(int)), this, SLOT(updateRes()));
+	connect(z2, SIGNAL(valueChanged(int)), this, SLOT(updateRes()));
+	connect(oper, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRes()));
+	connect(dirs, SIGNAL(currentIndexChanged(int)), this, SLOT(updateRes()));
+
+	sizes = new QLabel(_("Result"));	v->addWidget(sizes);
+	res = new QLineEdit(this);		v->addWidget(res);
+	connect(res, SIGNAL(textChanged(QString)), this, SLOT(userRes()));
+	
+	h = new QHBoxLayout();	v->addLayout(h);	h->addStretch(1);
+	b = new QPushButton(_("Cancel"), this);	h->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(reject()));
+	b = new QPushButton(_("OK"), this);		h->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(accept()));
+	b->setDefault(true);
+}
+//-----------------------------------------------------------------------------
+void DataDialog::nameChanged()
+{
+	QString var = name->currentText();
+	wchar_t *txt=new wchar_t[var.length()+1];
+	var.toWCharArray(txt);	txt[var.length()]=0;
+	mglData dat=parser.Calc(txt);	delete []txt;
+	x1->setMaximum(dat.nx-1);	x1->setValue(-1);
+	x2->setMaximum(dat.nx-1);	x2->setValue(-1);
+	y1->setMaximum(dat.ny-1);	y1->setValue(-1);
+	y2->setMaximum(dat.ny-1);	y2->setValue(-1);
+	z1->setMaximum(dat.nz-1);	z1->setValue(-1);
+	z2->setMaximum(dat.nz-1);	z2->setValue(-1);
+}
+//-----------------------------------------------------------------------------
+void DataDialog::updateRes()
+{
+	result = name->currentText();
+	int nx1 = x1->value(), nx2 = x2->value(), ny1 = y1->value(), ny2 = y2->value(), nz1 = z1->value(), nz2 = z2->value();
+	if(nx1>=0 || ny1>=0 || nz1>=0 || nx2>=0 || ny2>=0 || nz2>=0)
+		result += "(" + (nx1<0?"":QString::number(nx1)) + ":" + (nx2<0?"":QString::number(nx2)) + "," +
+						(ny1<0?"":QString::number(ny1)) + ":" + (ny2<0?"":QString::number(ny2)) + "," +
+						(nz1<0?"":QString::number(nz1)) + ":" + (nz2<0?"":QString::number(nz2)) + ")";
+	if(oper->currentIndex()>0)
+		result = "{" + oper->currentText() + " " + result + " '" + dirs->currentText() + "'}";
+	wchar_t *txt=new wchar_t[result.length()+1];
+	result.toWCharArray(txt);	txt[result.length()]=0;
+	mglData dat=parser.Calc(txt);	delete []txt;
+	sizes->setText(_("Result (will have sizes ") + QString::number(dat.nx)+"*"+QString::number(dat.ny)+"*"+QString::number(dat.nz)+")"	);
+	res->setText(result);
+}
+//-----------------------------------------------------------------------------
+void DataDialog::updateNames()
+{
+	name->clear();
+	long i, n = parser.GetNumVar();
+	for(i=0;i<n;i++)
+	{
+		const mglDataA *v = parser.GetVar(i);
+		if(v)	name->addItem(QString::fromWCharArray(v->s.c_str()));
+	}
+}
+//-----------------------------------------------------------------------------
+void DataDialog::userRes()
+{
+	QString txt = res->text();
+	if(txt != result)
+	{	result = txt;	sizes->setText(_("Result"));	}
+}
+//-----------------------------------------------------------------------------
diff --git a/udav/data_dlg.h b/udav/data_dlg.h
new file mode 100644
index 0000000..048da95
--- /dev/null
+++ b/udav/data_dlg.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef DATADIALOG_H
+#define DATADIALOG_H
+//-----------------------------------------------------------------------------
+#include <qdialog.h>
+class QComboBox;
+class QLineEdit;
+class QSpinBox;
+class QLabel;
+class QShowEvent;
+//-----------------------------------------------------------------------------
+/// Selecting styles of command (like line style, color scheme, font style, axis style)
+class DataDialog : public QDialog
+{
+	Q_OBJECT
+public:
+	QString getData()	{	return result;	};
+	void updateNames();
+	DataDialog(QWidget *parent = 0);
+	~DataDialog(){};
+protected:
+	virtual void showEvent(QShowEvent *ev)
+	{	updateNames();	QDialog::showEvent(ev);	}
+private slots:
+	void nameChanged();
+	void updateRes();
+	void userRes();
+private:
+	QString result;
+	QComboBox *name, *suffix, *oper, *dirs;
+	QLineEdit *res, *func;
+	QSpinBox  *x1, *y1, *z1, *x2, *y2, *z2;
+	QLabel *sizes;
+};
+//-----------------------------------------------------------------------------
+#endif
+//-----------------------------------------------------------------------------
diff --git a/udav/files_dlg.cpp b/udav/files_dlg.cpp
new file mode 100644
index 0000000..7c6855b
--- /dev/null
+++ b/udav/files_dlg.cpp
@@ -0,0 +1,96 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <QLabel>
+#include <QLayout>
+#include <QLineEdit>
+#include <QPushButton>
+#include "files_dlg.h"
+#include "mgl2/define.h"
+//-----------------------------------------------------------------------------
+FilesDialog::FilesDialog(QWidget *parent) : QDialog(parent)
+{
+	setWindowTitle(_("UDAV - Set template parameters"));
+	QHBoxLayout *h;
+	QVBoxLayout *v;
+	QGridLayout *g;
+	QLabel *l;
+	QPushButton *b;
+
+	v = new QVBoxLayout(this);
+	g = new QGridLayout();		v->addLayout(g);
+	l = new QLabel(_("String for %1"), this);	g->addWidget(l, 0, 0);
+	a[0] = new QLineEdit(this);					g->addWidget(a[0], 1, 0);
+	l = new QLabel(_("String for %2"), this);	g->addWidget(l, 0, 1);
+	a[1] = new QLineEdit(this);					g->addWidget(a[1], 1, 1);
+	l = new QLabel(_("String for %3"), this);	g->addWidget(l, 2, 0);
+	a[2] = new QLineEdit(this);					g->addWidget(a[2], 3, 0);
+	l = new QLabel(_("String for %4"), this);	g->addWidget(l, 2, 1);
+	a[3] = new QLineEdit(this);					g->addWidget(a[3], 3, 1);
+	l = new QLabel(_("String for %5"), this);	g->addWidget(l, 4, 0);
+	a[4] = new QLineEdit(this);					g->addWidget(a[4], 5, 0);
+	l = new QLabel(_("String for %6"), this);	g->addWidget(l, 4, 1);
+	a[5] = new QLineEdit(this);					g->addWidget(a[5], 5, 1);
+	l = new QLabel(_("String for %7"), this);	g->addWidget(l, 6, 0);
+	a[6] = new QLineEdit(this);					g->addWidget(a[6], 7, 0);
+	l = new QLabel(_("String for %8"), this);	g->addWidget(l, 6, 1);
+	a[7] = new QLineEdit(this);					g->addWidget(a[7], 7, 1);
+	l = new QLabel(_("String for %9"), this);	g->addWidget(l, 8, 0);
+	a[8] = new QLineEdit(this);					g->addWidget(a[8], 9, 0);
+
+	h = new QHBoxLayout();	h->addStretch(1);	v->addLayout(h);
+	b = new QPushButton(_("Cancel"), this);	h->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(reject()));
+	b = new QPushButton(_("OK"), this);		h->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(putArguments()));
+	b->setDefault(true);
+}
+//-----------------------------------------------------------------------------
+FilesDialog::~FilesDialog()	{}
+//-----------------------------------------------------------------------------
+void FilesDialog::putArguments()
+{
+	for(int i=0;i<9;i++)	s[i] = a[i]->text();
+	accept();
+}
+//-----------------------------------------------------------------------------
+void FilesDialog::setNumFiles(int n)
+{
+	for(int i=0;i<9;i++)	a[i]->setEnabled(i<n);
+	narg = n;	if(narg>9)	narg=9;
+}
+//-----------------------------------------------------------------------------
+QString FilesDialog::putFiles(const QString &str)
+{
+	QString res=str;
+	switch(narg)
+	{
+	case 1:	res = str.arg(s[0]);	break;
+	case 2:	res = str.arg(s[0],s[1]);	break;
+	case 3:	res = str.arg(s[0],s[1],s[2]);	break;
+	case 4:	res = str.arg(s[0],s[1],s[2],s[3]);	break;
+	case 5:	res = str.arg(s[0],s[1],s[2],s[3],s[4]);	break;
+	case 6:	res = str.arg(s[0],s[1],s[2],s[3],s[4],s[5]);	break;
+	case 7:	res = str.arg(s[0],s[1],s[2],s[3],s[4],s[5],s[6]);	break;
+	case 8:	res = str.arg(s[0],s[1],s[2],s[3],s[4],s[5],s[6],s[7]);	break;
+	case 9:	res = str.arg(s[0],s[1],s[2],s[3],s[4],s[5],s[6],s[7],s[8]);	break;
+	}
+	return res;
+}
+//-----------------------------------------------------------------------------
diff --git a/udav/files_dlg.h b/udav/files_dlg.h
new file mode 100644
index 0000000..1db3a5a
--- /dev/null
+++ b/udav/files_dlg.h
@@ -0,0 +1,50 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef FILES_DLG_H
+#define FILES_DLG_H
+//-----------------------------------------------------------------------------
+#include <QDialog>
+#if defined(_MSC_VER)
+#include <mgl2/define.h>
+#endif
+class QLineEdit;
+class QComboBox;
+class QRadioButton;
+//-----------------------------------------------------------------------------
+/// Dialog for enetring script arguments $0...$9
+class FilesDialog : public QDialog
+{
+Q_OBJECT
+public:
+	FilesDialog(QWidget *parent=0);
+	~FilesDialog();
+	QString putFiles(const QString &str);
+	void setNumFiles(int n);
+
+private slots:
+	void putArguments();
+private:
+	QLineEdit *a[9];
+	QString s[9];
+	int narg;
+};
+//-----------------------------------------------------------------------------
+#endif
+//-----------------------------------------------------------------------------
diff --git a/udav/find_dlg.cpp b/udav/find_dlg.cpp
new file mode 100644
index 0000000..d6b397d
--- /dev/null
+++ b/udav/find_dlg.cpp
@@ -0,0 +1,76 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <QLabel>
+#include <QLayout>
+#include <QLineEdit>
+#include <QCheckBox>
+#include <QPushButton>
+#include <QCloseEvent>
+#include "mgl2/define.h"
+#include "find_dlg.h"
+//-----------------------------------------------------------------------------
+FindDialog::FindDialog(QWidget *parent) : QDialog(parent)
+{
+	QLabel *lbl;
+	QHBoxLayout *a;
+	setWindowTitle(_("UDAV - Find"));
+	QVBoxLayout *o = new QVBoxLayout;
+	a = new QHBoxLayout;	o->addLayout(a);
+	lbl = new QLabel(_("Find what:"), this);			a->addWidget(lbl);
+	line = new QLineEdit(this);	lbl->setBuddy(line);	a->addWidget(line);
+	a = new QHBoxLayout;	o->addLayout(a);
+	lbl = new QLabel(_("Replace by:"), this);			a->addWidget(lbl);
+	text = new QLineEdit(this);	lbl->setBuddy(text);	a->addWidget(text);
+
+	caseUse = new QCheckBox(_("Match case"), this);	o->addWidget(caseUse);
+	backward = new QCheckBox(_("Search backward"), this);	o->addWidget(backward);
+
+	a = new QHBoxLayout(this);	a->setMargin(11);
+	a->setSpacing(6);			a->addLayout(o);
+	o = new QVBoxLayout;		a->addLayout(o);
+	find = new QPushButton(_("Find"), this);		o->addWidget(find);
+	find->setDefault(true);	find->setEnabled(false);
+	repl= new QPushButton(_("Replace"), this);	o->addWidget(repl);
+	repl->setEnabled(false);
+	cancel = new QPushButton(_("Close"), this);	o->addWidget(cancel);
+	o->addStretch(1);
+	connect(line, SIGNAL(textChanged(const QString &)), this, SLOT(enableFind(const QString &)));
+	connect(find, SIGNAL(clicked()), this, SLOT(findClicked()));
+	connect(repl, SIGNAL(clicked()), this, SLOT(replClicked()));
+	connect(cancel, SIGNAL(clicked()),this, SLOT(close()));
+}
+//-----------------------------------------------------------------------------
+FindDialog::~FindDialog()	{}
+//-----------------------------------------------------------------------------
+void FindDialog::findClicked()
+{	emit findText(line->text(), caseUse->isChecked(), backward->isChecked());	}
+//-----------------------------------------------------------------------------
+void FindDialog::replClicked()
+{	emit replText(line->text(), text->text(), caseUse->isChecked(), backward->isChecked());	}
+//-----------------------------------------------------------------------------
+void FindDialog::enableFind(const QString &txt)
+{	find->setEnabled(!txt.isEmpty());	repl->setEnabled(!txt.isEmpty());	}
+//-----------------------------------------------------------------------------
+void FindDialog::closeEvent(QCloseEvent *event)
+{
+	emit replText("", "", false, false);
+	event->accept();
+}
+//-----------------------------------------------------------------------------
diff --git a/udav/find_dlg.h b/udav/find_dlg.h
new file mode 100644
index 0000000..221901c
--- /dev/null
+++ b/udav/find_dlg.h
@@ -0,0 +1,58 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef FIND_DLG_H
+#define FIND_DLG_H
+//-----------------------------------------------------------------------------
+#include <QDialog>
+class QCheckBox;
+class QLineEdit;
+class QPushButton;
+#if defined(_MSC_VER)
+#include <mgl2/define.h>
+#endif
+//-----------------------------------------------------------------------------
+/// Dialog for finding something in text
+class FindDialog : public QDialog
+{
+Q_OBJECT
+public:
+	FindDialog(QWidget *parent = 0);
+	~FindDialog();
+signals:
+	void findText(const QString &str, bool cs, bool fw);
+	void replText(const QString &str, const QString &txt, bool cs, bool fw);
+protected:
+	void closeEvent(QCloseEvent *event);
+private slots:
+	void findClicked();
+	void replClicked();
+	void enableFind(const QString &text);
+private:
+	QLineEdit *line;
+	QLineEdit *text;
+	QCheckBox *caseUse;
+	QCheckBox *backward;
+	QPushButton *find;
+	QPushButton *repl;
+	QPushButton *cancel;
+};
+//-----------------------------------------------------------------------------
+#endif
+//-----------------------------------------------------------------------------
diff --git a/udav/help_pnl.cpp b/udav/help_pnl.cpp
new file mode 100644
index 0000000..0cac496
--- /dev/null
+++ b/udav/help_pnl.cpp
@@ -0,0 +1,86 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <QLayout>
+#include <QLineEdit>
+#include <QToolBar>
+#include <QPushButton>
+#include <QTextBrowser>
+#include <QToolButton>
+#include <stdio.h>
+//-----------------------------------------------------------------------------
+#include "mgl2/define.h"
+#include "help_pnl.h"
+extern QString pathHelp;
+void raisePanel(QWidget *w);
+//-----------------------------------------------------------------------------
+QWidget *createHlpPanel(QWidget *p)		{	return new HelpPanel(p);	}
+void showHelpMGL(QWidget *p,QString s)
+{
+	HelpPanel *hlp = dynamic_cast<HelpPanel *>(p);
+	if(hlp)	hlp->showHelp(s);
+}
+//void showExMGL(QWidget *hlp)			{	((HelpPanel *)hlp)->showExamples();	}
+//-----------------------------------------------------------------------------
+HelpPanel::HelpPanel(QWidget *parent) : QWidget(parent)
+{
+
+	QToolBar *t = new QToolBar(this);	t->setMovable(false);
+	QVBoxLayout *v = new QVBoxLayout(this);	v->addWidget(t);
+	help = new QTextBrowser(this);	v->addWidget(help);	help->setOpenExternalLinks(false);
+
+	t->addAction(QPixmap(":/png/go-previous.png"), _("Backward"), help, SLOT(backward()));
+	entry = new QLineEdit(this);	t->addWidget(entry);
+	connect(entry, SIGNAL(textChanged(const QString &)), this, SLOT(showHelp(const QString &)));
+	connect(entry, SIGNAL(returnPressed()), this, SLOT(showHelp()));
+	t->addAction(QPixmap(":/png/go-next.png"), _("Forward"), help, SLOT(forward()));
+	t->addSeparator();
+//	t->addAction(QPixmap(":/png/help-faq.png"), _("Examples"), this, SLOT(showExamples()));
+	t->addAction(QPixmap(":/png/zoom-in.png"), _("Zoom in text"), this, SLOT(zoomIn()));
+	t->addAction(QPixmap(":/png/zoom-out.png"), _("Zoom out text"), this, SLOT(zoomOut()));
+	setWindowTitle(_("Help"));
+}
+//-----------------------------------------------------------------------------
+// void HelpPanel::showExamples()
+// {
+// 	QStringList s;	s<<(pathHelp);
+// 	help->setSearchPaths(s);
+// 	setWindowTitle("Examples");	raisePanel(this);
+// 	help->setSource("mgl_en"+"_2.html");
+// }
+//-----------------------------------------------------------------------------
+void HelpPanel::showHelp(const QString &txt)
+{
+	QString cmd=txt;
+	raisePanel(this);
+	QStringList s;	s<<(pathHelp);
+	help->setSearchPaths(s);
+	if(cmd.isEmpty())	cmd = entry->text().trimmed();
+	// NOTE disable other translations for help files due to Qt bug
+	if(cmd.isEmpty())	help->setSource("mgl_en"+QString(".html"));
+	else	help->setSource("mgl_en"+QString(".html#")+cmd);
+	setWindowTitle("Help");
+}
+//-----------------------------------------------------------------------------
+void HelpPanel::zoomIn()
+{	QFont f(help->font());	f.setPointSize(f.pointSize()+1);	help->setFont(f);	}
+//-----------------------------------------------------------------------------
+void HelpPanel::zoomOut()
+{	QFont f(help->font());	f.setPointSize(f.pointSize()-1);	help->setFont(f);	}
+//-----------------------------------------------------------------------------
diff --git a/udav/help_pnl.h b/udav/help_pnl.h
new file mode 100644
index 0000000..c6e4a1d
--- /dev/null
+++ b/udav/help_pnl.h
@@ -0,0 +1,46 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef HELP_PNL_H
+#define HELP_PNL_H
+//-----------------------------------------------------------------------------
+#include <QWidget>
+#if defined(_MSC_VER)
+#include <mgl2/define.h>
+#endif
+class QTextBrowser;
+class QLineEdit;
+//-----------------------------------------------------------------------------
+class HelpPanel : public QWidget
+{
+Q_OBJECT
+public:
+	HelpPanel(QWidget *parent = 0);
+public slots:
+//	void showExamples();
+	void showHelp(const QString &cmd=QString::null);
+	void zoomIn();
+	void zoomOut();
+private:
+	QTextBrowser *help;
+	QLineEdit *entry;
+};
+//-----------------------------------------------------------------------------
+#endif // HELP_PNL_H
+//-----------------------------------------------------------------------------
diff --git a/udav/hint_dlg.cpp b/udav/hint_dlg.cpp
new file mode 100644
index 0000000..2ef75ea
--- /dev/null
+++ b/udav/hint_dlg.cpp
@@ -0,0 +1,85 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <QSettings>
+#include <QCheckBox>
+#include <QLayout>
+#include <QPushButton>
+#include "hint_dlg.h"
+#include "mgl2/data_cf.h"
+//-----------------------------------------------------------------------------
+//
+//	Hint dialog
+//
+//-----------------------------------------------------------------------------
+HintDialog::HintDialog(QWidget *parent) : QDialog(parent)
+{
+	hints.append(_("You can shift axis range by pressing middle button and moving mouse. Also, you can zoom in/out axis range by using mouse wheel."));
+	hints.append(_("You can rotate/shift/zoom whole plot by mouse. Just press 'Rotate' toolbutton, click image and hold a mouse button: left button for rotation, right button for zoom/perspective, middle button for shift."));
+	hints.append(_("You may quickly draw the data from file. Just use: udav 'filename.dat' in command line."));
+	hints.append(_("You can copy the current image to clipboard by pressing Ctrl-Shift-C. Later you can paste it directly into yours document or presentation."));
+	hints.append(_("You can export image into a set of format (EPS, SVG, PNG, JPEG) by pressing right mouse button inside image and selecting 'Export as ...'."));
+	hints.append(_("You can setup colors for script highlighting in Property dialog. Just select menu item 'Settings/Properties'."));
+	hints.append(_("You can save the parameter of animation inside MGL script by using comment started from '##a ' or '##c ' for loops."));
+	hints.append(_("New drawing never clears things drawn already. For example, you can make a surface with contour lines by calling commands 'surf' and 'cont' one after another (in any order). "));
+	hints.append(_("You can put several plots in the same image by help of commands 'subplot' or 'inplot'."));
+	hints.append(_("All indexes (of data arrays, subplots and so on) are always start from 0."));
+	hints.append(_("You can edit MGL file in any text editor. Also you can run it in console by help of commands: mglconv, mglview."));
+	hints.append(_("You can use command 'once on|off' for marking the block which should be executed only once. For example, this can be the block of large data reading/creating/handling. Press F9 (or menu item 'Graphics/Reload') to re-execute this block."));
+	hints.append(_("You can use command 'stop' for terminating script parsing. It is useful if you don't want to execute a part of script."));
+	hints.append(_("You can type arbitrary expression as input argument for data or number. In last case (for numbers), the first value of data array is used."));
+	hints.append(_("There is powerful calculator with a lot of special functions. You can use buttons or keyboard to type the expression. Also you can use existed variables in the expression."));
+	hints.append(_("The calculator can help you to put complex expression in the script. Just type the expression (which may depend on coordinates x,y,z and so on) and put it into the script."));
+	hints.append(_("You can easily insert file or folder names, last fitted formula or numerical value of selection by using menu Edit|Insert."));
+	hints.append(_("The special dialog (Edit|Insert|New Command) help you select the command, fill its arguments and put it into the script."));
+	hints.append(_("You can put several plotting commands in the same line or in separate function, for highlighting all of them simultaneously."));
+
+	numHints=hints.size();
+	cur = int(mgl_rnd()*numHints);
+	setWindowTitle(_("UDAV - Hint"));
+	QHBoxLayout *a;
+	QPushButton *b;
+	QVBoxLayout *o = new QVBoxLayout(this);
+	text = new QTextEdit(this);	o->addWidget(text);
+	text->setReadOnly(true);	text->setText(hints[cur]);
+
+	start = new QCheckBox(_("Show at startup"), this);	o->addWidget(start);
+	start->setChecked(true);
+
+	a = new QHBoxLayout;	o->addLayout(a);
+	b = new QPushButton(_("Prev"), this);		a->addWidget(b);
+	connect(b, SIGNAL(clicked()), this, SLOT(prevClicked()));
+	b = new QPushButton(_("Next"), this);		a->addWidget(b);
+	connect(b, SIGNAL(clicked()), this, SLOT(nextClicked()));
+	b = new QPushButton(_("Close"), this);	a->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(close()));
+}
+//-----------------------------------------------------------------------------
+void HintDialog::closeEvent(QCloseEvent *)
+{
+	QSettings settings("udav","UDAV");
+	settings.setPath(QSettings::IniFormat, QSettings::UserScope, "UDAV");
+	settings.beginGroup("/UDAV");
+	settings.setValue("/showHint", start->isChecked());
+	settings.endGroup();
+}
+//-----------------------------------------------------------------------------
+void udavShowHint(QWidget *p)
+{	HintDialog *hd = new HintDialog(p);	hd->exec();	}
+//-----------------------------------------------------------------------------
diff --git a/udav/hint_dlg.h b/udav/hint_dlg.h
new file mode 100644
index 0000000..8bb2a66
--- /dev/null
+++ b/udav/hint_dlg.h
@@ -0,0 +1,50 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef HINT_DLG_H
+#define HINT_DLG_H
+//-----------------------------------------------------------------------------
+#include <QTextEdit>
+#include <QDialog>
+class QCheckBox;
+//-----------------------------------------------------------------------------
+/// Dialog for showing hints
+class HintDialog : public QDialog
+{
+Q_OBJECT
+public:
+	HintDialog(QWidget *parent = 0);
+	~HintDialog()	{}
+protected:
+	void closeEvent(QCloseEvent *event);
+private slots:
+	void nextClicked()
+	{	cur = (cur+1)%numHints;	text->setText(hints[cur]);	}
+	void prevClicked()
+	{	cur = (cur+numHints-1)%numHints;	text->setText(hints[cur]);	}
+private:
+	int cur;
+	int numHints;
+	QVector<QString> hints;
+	QTextEdit *text;
+	QCheckBox *start;
+};
+//-----------------------------------------------------------------------------
+#endif
+//-----------------------------------------------------------------------------
diff --git a/udav/info_dlg.cpp b/udav/info_dlg.cpp
new file mode 100644
index 0000000..dc6426c
--- /dev/null
+++ b/udav/info_dlg.cpp
@@ -0,0 +1,84 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <QLabel>
+#include <QLayout>
+#include <QComboBox>
+#include <QTextEdit>
+#include <QTabWidget>
+#include "mgl2/qmathgl.h"
+#include "info_dlg.h"
+extern mglParse parser;
+//-----------------------------------------------------------------------------
+InfoDialog::InfoDialog(QWidget *parent) : QDialog(parent)
+{
+	var = 0;	kz = 0;		allowRefresh = true;
+	QWidget *p;
+	QVBoxLayout *v, *u;
+	QLabel *l;
+	QTabWidget *tab = new QTabWidget(this);
+	u = new QVBoxLayout(this);	u->addWidget(tab);
+	// graphics
+	p = new QWidget(this);	v = new QVBoxLayout(p);
+	l = new QLabel(_("Select kind of plot"),this);	v->addWidget(l);
+	kind = new QComboBox(this);	v->addWidget(kind);
+	mgl = new QMathGL(this);	v->addWidget(mgl,1);
+	mgl->autoResize = true;		mgl->appName = _("Data preview");
+	mgl->setToolTip(_("Data preview for current slice."));
+
+	draw = new mglDrawScript(parser.Self());	mgl->setDraw(draw);
+
+	kind->addItem(_("1D plot"));	kind->addItem(_("2D plot"));
+	kind->setCurrentIndex(0);	//	kind->addItem(_("3D plot"));
+	connect(kind, SIGNAL(currentIndexChanged(int)), this, SLOT(refresh()));
+	kind->setToolTip(_("Kind of plots: lines for 1D, density for 2D."));
+	tab->addTab(p, _("Preview"));
+	// information
+	info = new QTextEdit(this);
+	info->setToolTip(_("Short information about the data."));
+	tab->addTab(info, _("Information"));
+	connect(mgl,SIGNAL(showWarn(QString)),info,SLOT(setText(QString)));
+}
+//-----------------------------------------------------------------------------
+InfoDialog::~InfoDialog()	{}
+//-----------------------------------------------------------------------------
+#include <QMessageBox>
+void InfoDialog::refresh(bool force)
+{
+	if(!var || (!force && (!allowRefresh || !isVisible())))	return;
+	QString text, name, sub;
+	name = QString::fromWCharArray(var->s.c_str());
+	sub = "(:,:,"+QString::number(kz)+")\n";
+	int i = kind->currentIndex();
+	if(i<1)	text = "yrange "+name+"\nplot "+name + sub;
+	else	text = "crange "+name+"\ndens "+name + sub;
+	text = "zoom 0.15 0.15 0.85 0.85\nbox\n" + text + "\ninfo "+name;
+	draw->text = text;	mgl->update();
+}
+//-----------------------------------------------------------------------------
+void InfoDialog::setVar(mglDataA *v)
+{
+	var=v;
+	if(v)	kind->setCurrentIndex(v->GetNy()>1 ? 1:0);
+	refresh();
+}
+//-----------------------------------------------------------------------------
+void InfoDialog::showEvent(QShowEvent *)
+{	refresh(true);	}
+//-----------------------------------------------------------------------------
diff --git a/udav/info_dlg.h b/udav/info_dlg.h
new file mode 100644
index 0000000..3389f5d
--- /dev/null
+++ b/udav/info_dlg.h
@@ -0,0 +1,58 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef INFODIALOG_H
+#define INFODIALOG_H
+//-----------------------------------------------------------------------------
+#include <QDialog>
+#include <QMainWindow>
+//-----------------------------------------------------------------------------
+class QMathGL;
+class mglDrawScript;
+class mglDataA;
+class QComboBox;
+class QTextEdit;
+//-----------------------------------------------------------------------------
+/// Display picture and short information about variable
+class InfoDialog : public QDialog
+{
+Q_OBJECT
+public:
+	InfoDialog(QWidget *parent = 0);
+	virtual ~InfoDialog();
+	void setVar(mglDataA *v);
+	void setSlice(int k)	{	kz=k;	refresh();	}
+	bool allowRefresh;
+//	void setName(QString &name);
+	void showEvent(QShowEvent *ev);
+
+public slots:
+	void refresh(bool force=false);
+
+private:
+	int kz;
+	mglDataA *var;
+	QMathGL *mgl;
+	QTextEdit *info;
+	QComboBox *kind;
+	mglDrawScript *draw;
+};
+//-----------------------------------------------------------------------------
+#endif
+//-----------------------------------------------------------------------------
diff --git a/udav/mem_pnl.cpp b/udav/mem_pnl.cpp
new file mode 100644
index 0000000..e9cd4fd
--- /dev/null
+++ b/udav/mem_pnl.cpp
@@ -0,0 +1,188 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <QLayout>
+#include <QTableWidget>
+#include <QToolBar>
+#include <QInputDialog>
+#include <QMessageBox>
+#include <mgl2/mgl.h>
+//-----------------------------------------------------------------------------
+#include "mem_pnl.h"
+#include "info_dlg.h"
+#undef sprintf	// fix libintl bug of defining sprintf
+//-----------------------------------------------------------------------------
+#include "xpm/table.xpm"
+#include "xpm/preview.xpm"
+//-----------------------------------------------------------------------------
+extern bool mglAutoSave;
+extern mglParse parser;
+QWidget *newDataWnd(InfoDialog *inf, QWidget *wnd, mglDataA *v);
+void refreshData(QWidget *w);
+//-----------------------------------------------------------------------------
+QWidget *createMemPanel(QWidget *p)	// NOTE: parent should be MainWindow
+{
+	MemPanel *m = new MemPanel(p);
+	m->wnd = p;	return m;
+}
+//-----------------------------------------------------------------------------
+void refreshMemPanel(QWidget *p)
+{
+	MemPanel *m = dynamic_cast<MemPanel *>(p);
+	if(m)	m->refresh();
+}
+//-----------------------------------------------------------------------------
+MemPanel::MemPanel(QWidget *parent) : QWidget(parent)
+{
+	infoDlg = new InfoDialog(this);
+	infoDlg->setModal(true);	infoDlg->allowRefresh=false;
+
+	QToolBar *t = new QToolBar(this);	t->setMovable(false);
+	QVBoxLayout *v = new QVBoxLayout(this);	v->addWidget(t);
+	t->addAction(QPixmap(":/png/document-new.png"), _("Create new data array"), this, SLOT(newTable()));
+	t->addAction(QPixmap(table_xpm), _("Edit selected data array"), this, SLOT(editData()));
+	t->addAction(QPixmap(":/png/edit-delete.png"), _("Delete selected data array"), this, SLOT(delData()));
+	t->addAction(QPixmap(preview_xpm), _("Properties of selected data array"), this, SLOT(infoData()));
+	t->addAction(QPixmap(":/png/view-refresh.png"), _("Update list of data arrays"), this, SLOT(refresh()));
+	t->addSeparator();
+	t->addAction(QPixmap(":/png/edit-clear.png"), _("Delete ALL data arrays"), this, SLOT(delAllData()));
+
+	colSort = 0;
+	tab = new QTableWidget(this);	tab->setColumnCount(3);	v->addWidget(tab);
+	QStringList sl;	sl<<_("Name")<<_("Sizes")<<_("Memory");
+	tab->setHorizontalHeaderLabels(sl);
+	connect(tab, SIGNAL(cellClicked(int,int)), this, SLOT(tableClicked(int,int)));
+	connect(tab, SIGNAL(cellDoubleClicked(int,int)), this, SLOT(tableDClicked(int,int)));
+
+	setWindowTitle(_("Memory"));
+}
+//-----------------------------------------------------------------------------
+void MemPanel::tableClicked(int, int col)
+{	colSort = col;	tab->sortItems(col);	}
+//-----------------------------------------------------------------------------
+void MemPanel::tableDClicked(int row, int)	{	editData(row);	}
+//-----------------------------------------------------------------------------
+void MemPanel::newTable()
+{
+	bool ok;
+	QString name = QInputDialog::getText(this, _("UDAV - New variable"),
+				_("Enter name for new variable"), QLineEdit::Normal, "", &ok);
+	if(!ok || name.isEmpty())	return;
+	mglDataA *v = parser.AddVar(name.toLocal8Bit().constData());
+	QWidget *t;
+	if(v->o)	t = (QWidget *)v->o;
+	else		t = newDataWnd(infoDlg,wnd,v);
+	t->showMaximized();	t->activateWindow();
+	refresh();
+}
+//-----------------------------------------------------------------------------
+void MemPanel::editData(int n)
+{
+	if(tab->rowCount()<1)	return;
+	if(n<0)	n = tab->currentRow();
+	if(n<0)	n = 0;
+	mglDataA *v = parser.FindVar(tab->item(n,0)->text().toLocal8Bit().constData());
+	if(!v)	return;
+	QWidget *t;
+	if(v->o)	t = (QWidget *)v->o;
+	else		t = newDataWnd(infoDlg,wnd,v);
+	t->showMaximized();	t->activateWindow();
+}
+//-----------------------------------------------------------------------------
+void MemPanel::delData()
+{
+	if(tab->rowCount()<1)	return;
+	int	n = tab->currentRow();
+	if(n<0)	n = 0;
+	mglDataA *v = parser.FindVar(tab->item(n,0)->text().toLocal8Bit().constData());
+	if(v && v->o)	((QWidget *)v->o)->close();
+	parser.DeleteVar(tab->item(n,0)->text().toLocal8Bit().constData());
+	refresh();
+}
+//-----------------------------------------------------------------------------
+void MemPanel::delAllData()
+{
+	if(QMessageBox::information(this, _("UDAV - delete all data"),
+			_("Do you want to delete all data?"), QMessageBox::No,
+			QMessageBox::Yes)!=QMessageBox::Yes)	return;
+	parser.DeleteAll();	refresh();
+}
+//-----------------------------------------------------------------------------
+void MemPanel::infoData()
+{
+	if(tab->rowCount()<1)	return;
+	int	n = tab->currentRow();
+	if(n<0)	n = 0;
+	mglDataA *v = parser.FindVar(tab->item(n,0)->text().toLocal8Bit().constData());
+	if(!v)	return;
+	infoDlg->setVar(v);
+	QString s = QString::fromWCharArray(v->s.c_str());
+	infoDlg->setWindowTitle(s + _(" - UDAV preview"));
+	infoDlg->refresh();
+	infoDlg->show();
+}
+//-----------------------------------------------------------------------------
+void MemPanel::refresh()
+{
+	long n = parser.GetNumVar(), m=0;
+	for(long i=0;i<n;i++)	if(parser.GetVar(i))	m++;
+	tab->setRowCount(m);
+	QString s;
+	QTableWidgetItem *it;
+	Qt::ItemFlags flags=Qt::ItemIsSelectable|Qt::ItemIsEnabled;
+	for(long i=m=0;i<n;i++)
+	{
+		mglDataA *v = parser.GetVar(i);
+		if(!v)	continue;
+		s = QString::fromWCharArray(v->s.c_str());
+		it = new QTableWidgetItem(s);
+		tab->setItem(m,0,it);	it->setFlags(flags);
+		s.sprintf("%ld * %ld * %ld", v->GetNx(), v->GetNy(), v->GetNz());
+		it = new QTableWidgetItem(s);
+		tab->setItem(m,1,it);	it->setFlags(flags);
+		it->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
+		long sv = 0;
+		if(dynamic_cast<mglData*>(v))	sv = v->GetNN()*sizeof(mreal)+sizeof(mglData);
+		else if(dynamic_cast<mglDataC*>(v))	sv = v->GetNN()*sizeof(dual)+sizeof(mglDataC);
+		else if(dynamic_cast<mglDataV*>(v))	sv = sizeof(mglDataV);
+		else if(dynamic_cast<mglDataW*>(v))	sv = sizeof(mglDataW);
+		else if(dynamic_cast<mglDataF*>(v))	sv = sizeof(mglDataF);
+		else if(dynamic_cast<mglDataR*>(v))	sv = sizeof(mglDataR);
+		else if(dynamic_cast<mglDataT*>(v))	sv = sizeof(mglDataT);
+		if(sv==0)	s = _("unknown");
+#if MGL_SIZEOF_LONG>4
+//		else if((sv>>80L)>0)	s.sprintf("%ld Yb",sv>>80L);
+//		else if((sv>>70L)>0)	s.sprintf("%ld Zb",sv>>70L);
+		else if((sv>>60L)>0)	s.sprintf("%ld Eb",sv>>60L);
+		else if((sv>>50L)>0)	s.sprintf("%ld Pb",sv>>50L);
+		else if((sv>>40L)>0)	s.sprintf("%ld Tb",sv>>40L);
+#endif
+		else if((sv>>30L)>0)	s.sprintf("%ld Gb",sv>>30L);
+		else if((sv>>20L)>0)	s.sprintf("%ld Mb",sv>>20L);
+		else if((sv>>10L)>0)	s.sprintf("%ld Kb",sv>>10L);
+		else	s.sprintf("%ld b",sv);
+		it = new QTableWidgetItem(s);
+		tab->setItem(m,2,it);	it->setFlags(flags);
+		it->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+		if(v->o)	refreshData((QWidget *)v->o);
+		m++;
+	}
+	tab->sortItems(colSort);
+}
+//-----------------------------------------------------------------------------
diff --git a/udav/mem_pnl.h b/udav/mem_pnl.h
new file mode 100644
index 0000000..59ffe79
--- /dev/null
+++ b/udav/mem_pnl.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef MEM_PNL_H
+#define MEM_PNL_H
+#include <QWidget>
+class InfoDialog;
+class QTableWidget;
+//-----------------------------------------------------------------------------
+class MemPanel : public QWidget
+{
+Q_OBJECT
+public:
+	QWidget *wnd;
+	MemPanel(QWidget *parent = 0);
+public slots:
+	void refresh();		///< refresh list of variables
+private slots:
+	void newTable();
+	void editData(int n=-1);
+	void infoData();
+	void delAllData();
+	void delData();
+	void tableClicked(int row, int col);
+	void tableDClicked(int row, int col);
+private:
+	InfoDialog *infoDlg;	///< Data preview and information
+	QTableWidget *tab;
+	int colSort;
+};
+//-----------------------------------------------------------------------------
+#endif // MEM_PNL_H
+//-----------------------------------------------------------------------------
diff --git a/udav/mgl.xml.in b/udav/mgl.xml.in
new file mode 100644
index 0000000..325aaac
--- /dev/null
+++ b/udav/mgl.xml.in
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
+  <mime-type type="text/mgl">
+    <alias type="text/x.mgl"/>
+    <alias type="text/x-mgl"/>
+    <comment>MGL script</comment>
+    <icon name="${CMAKE_INSTALL_PREFIX}/share/pixmaps/udav.png"/>
+    <glob pattern="*.mgl"/>
+  </mime-type>
+</mime-info>
diff --git a/udav/newcmd_dlg.cpp b/udav/newcmd_dlg.cpp
new file mode 100644
index 0000000..fa08dd5
--- /dev/null
+++ b/udav/newcmd_dlg.cpp
@@ -0,0 +1,393 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <QLabel>
+#include <QLayout>
+#include <QLineEdit>
+#include <QComboBox>
+#include <QTableWidget>
+#include <QPushButton>
+#include <QMessageBox>
+#include <QTextBrowser>
+#include <QToolButton>
+#include <QFileDialog>
+#include <mgl2/mgl.h>
+
+#include "newcmd_dlg.h"
+#include "opt_dlg.h"
+#include "style_dlg.h"
+#include "data_dlg.h"
+extern mglParse parser;
+extern QString pathHelp;
+//-----------------------------------------------------------------------------
+NewCmdDialog::NewCmdDialog(QWidget *p) : QDialog(p,Qt::WindowStaysOnTopHint)
+{
+	replace = false;
+	QPushButton *b;
+	QToolButton *t;
+	QHBoxLayout *m = new QHBoxLayout(this), *a;
+	QVBoxLayout *o = new QVBoxLayout;	m->addLayout(o);
+	optDialog = new OptionDialog(this);
+	stlDialog = new StyleDialog(this);
+	datDialog = new DataDialog(this);
+	type = new QComboBox(this);		o->addWidget(type);
+	type->setToolTip(_("Groups of MGL commands"));
+	fillList();
+	name = new QComboBox(this);		o->addWidget(name);
+	name->setToolTip(_("MGL commands for selected group"));
+	name->addItems(argn[0]);
+	info = new QLabel(this);		o->addWidget(info);
+	info->setToolTip(_("Short description of selected command"));
+	kind= new QComboBox(this);		o->addWidget(kind);	kind->addItem("");
+	kind->setToolTip(_("Kind of command argument order. The notation is:\n"
+						" * Capital arguments are data (like, Ydat);\n"
+						" * Argument in '' are strings (like, 'fmt');\n"
+						" * Other arguments are numbers (like, zval);\n"
+						" * Arguments in [] are optional arguments."));
+	args = new QTableWidget(this);	o->addWidget(args);
+	args->setToolTip(_("Command arguments. Bold ones are required arguments.\n"
+						"Other are optional arguments but its order is required.\n"
+						"You can use '' for default format. See help at right\nfor default values."));
+	QStringList sl;	sl<<_("Argument")<<_("Value");
+	args->setHorizontalHeaderLabels(sl);
+	connect(args,SIGNAL(cellDoubleClicked(int,int)), this, SLOT(insertData()));
+
+	a = new QHBoxLayout;	o->addLayout(a);
+	b = new QPushButton(_("Options"),this);	a->addWidget(b);
+	b->setToolTip(_("Here you can specify command options.\nOptions are used for additional plot tunning."));
+	connect(b, SIGNAL(clicked()),this,SLOT(insertOpt()));
+	opt = new QLineEdit(this);	a->addWidget(opt);
+
+	a = new QHBoxLayout;	o->addLayout(a);
+	b = new QPushButton(_("Cancel"),this);	a->addWidget(b);
+	connect(b, SIGNAL(clicked()), this, SLOT(reject()));
+	b = new QPushButton(_("OK"),this);	a->addWidget(b);
+	connect(b, SIGNAL(clicked()), this, SLOT(finish()));
+
+	o = new QVBoxLayout;	m->addLayout(o,1);
+	a = new QHBoxLayout;	o->addLayout(a);
+	help = new QTextBrowser(this);		help->setMinimumWidth(500);
+	help->setOpenExternalLinks(false);	o->addWidget(help);
+	t = new QToolButton(p);	t->setIcon(QPixmap(":/png/go-previous.png"));
+	connect(t, SIGNAL(clicked()), help, SLOT(backward()));	a->addWidget(t);
+	t = new QToolButton(p);	t->setIcon(QPixmap(":/png/go-next.png"));
+	connect(t, SIGNAL(clicked()), help, SLOT(forward()));	a->addWidget(t);
+	a->addStretch(1);
+	t = new QToolButton(p);	t->setIcon(QPixmap(":/png/zoom-in.png"));
+	connect(t, SIGNAL(clicked()), this, SLOT(zoomIn()));	a->addWidget(t);
+	t = new QToolButton(p);	t->setIcon(QPixmap(":/png/zoom-out.png"));
+	connect(t, SIGNAL(clicked()), this, SLOT(zoomOut()));	a->addWidget(t);
+
+	connect(type, SIGNAL(currentIndexChanged(int)),this,SLOT(typeChanged(int)));
+	connect(name, SIGNAL(currentIndexChanged(int)),this,SLOT(nameChanged(int)));
+	connect(kind, SIGNAL(currentIndexChanged(int)),this,SLOT(kindChanged(int)));
+	type->setCurrentIndex(0);	typeChanged(0);
+	setWindowTitle(_("New command"));
+}
+//-----------------------------------------------------------------------------
+void NewCmdDialog::zoomIn()
+{	QFont f(help->font());	f.setPointSize(f.pointSize()+1);	help->setFont(f);	}
+//-----------------------------------------------------------------------------
+void NewCmdDialog::zoomOut()
+{	QFont f(help->font());	f.setPointSize(f.pointSize()-1);	help->setFont(f);	}
+//-----------------------------------------------------------------------------
+void NewCmdDialog::parseCmd(const QString &txt)
+{
+	QString str = txt.trimmed().section(':',0,0);
+	QRegExp sep("[ \t]");
+	QString cmd = str.section(sep,0,0),a,b;
+	bool opt,var,chr;
+	replace = false;
+	for(int i=0;i<17;i++)
+	{
+		if(cmds[i].contains(cmd))	// find command first
+		{
+			typeChanged(i);
+			name->setCurrentIndex(cmds[i].indexOf(cmd));
+			int j0=-1,k0=-1,k;
+			for(int j=0;j<NUM_CH;j++)		// determine set of arguments
+			{
+				if(argn[j].isEmpty())	break;
+				bool ok=true;
+				for(k=0;k<argn[j].count();k++)
+				{
+					a = argn[j].at(k);		opt = (a[0]=='_'  || a[0]=='+');
+					chr = (a[0]=='\'' || (opt && a[1]=='\''));
+					var = (a[0].isUpper() || (opt && a[1].isUpper()));
+					b = str.section(sep,k+1,k+1).trimmed();
+					if(b.isEmpty())	break;
+					if(b[0].isDigit() && (chr || var))	{	ok=false;	break;	}
+					if(b[0]=='\'' && !chr)	{	ok=false;	break;	}
+				}
+				if(ok && (j0<0 || k>k0))	{	j0=j;	k0=k;	}
+			}
+			if(j0>=0)	// best choice
+			{
+				kind->setCurrentIndex(j0);
+				for(int k=0;k<argn[j0].count();k++)
+					args->item(k,1)->setText(str.section(sep,k+1,k+1).trimmed());
+			}
+			replace = true;	return;		// selection is done
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+#include "xpm/preview.xpm"
+#include "xpm/text.xpm"
+#include "xpm/table.xpm"
+#include "xpm/oper_dir.xpm"
+#include "xpm/axis.xpm"
+#include "xpm/axis_sh.xpm"
+#include "xpm/plot.xpm"
+#include "xpm/box.xpm"
+#include "xpm/curve.xpm"
+#include "xpm/other.xpm"
+#include "xpm/vect.xpm"
+#include "xpm/tiles.xpm"
+//-----------------------------------------------------------------------------
+void NewCmdDialog::fillList()
+{
+	type->addItem(QPixmap(plot_xpm), _("1D plots"));
+	type->addItem(QPixmap(preview_xpm), _("2D plots"));
+	type->addItem(QPixmap(":/png/weather-clouds.png"), _("3D plots"));
+	type->addItem(QPixmap(tiles_xpm), _("Dual plots"));
+	type->addItem(QPixmap(vect_xpm), _("Vector plots"));
+	type->addItem(QPixmap(other_xpm), _("Other plots"));
+	type->addItem(QPixmap(text_xpm), _("Text and legend"));
+	type->addItem(QPixmap(table_xpm), _("Create data and I/O"));
+	type->addItem(QPixmap(oper_dir_xpm), _("Data transform"));
+	type->addItem(QPixmap(oper_dir_xpm), _("Data handling"));
+	type->addItem(QPixmap(axis_xpm), _("Axis and colorbar"));
+	type->addItem(QPixmap(axis_sh_xpm), _("Axis setup"));
+	type->addItem(QPixmap(":/png/preferences-system.png"), _("General setup"));
+	type->addItem(QPixmap(box_xpm), _("Scale and rotate"));
+	type->addItem(QPixmap(":/png/media-playback-start.png"), _("Program flow"));
+	type->addItem(QPixmap(curve_xpm), _("Primitives"));
+
+	// now fill it automatically from parser for all categories
+	long i, n = parser.GetCmdNum();
+	for(i=0;i<n;i++)
+	{
+		const char *name = parser.GetCmdName(i);
+		switch(parser.CmdType(name))
+		{
+		case 1:	cmds[5]<<name;	break;
+		case 2:	cmds[5]<<name;	break;
+		case 3:	cmds[12]<<name;	break;
+		case 4:	cmds[9]<<name;	break;
+		case 5:	cmds[7]<<name;	break;
+		case 6:	cmds[13]<<name;	break;
+		case 7:	cmds[14]<<name;	break;
+		case 8:	cmds[0]<<name;	break;
+		case 9:	cmds[1]<<name;	break;
+		case 10:	cmds[2]<<name;	break;
+		case 11:	cmds[3]<<name;	break;
+		case 12:	cmds[4]<<name;	break;
+		case 13:	cmds[10]<<name;	break;
+		case 14:	cmds[15]<<name;	break;
+		case 15:	cmds[11]<<name;	break;
+		case 16:	cmds[6]<<name;	break;
+		case 17:	cmds[8]<<name;	break;
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void NewCmdDialog::typeChanged(int s)
+{
+	if(s<0 || s>16)	return;
+	name->clear();	name->addItems(cmds[s]);	name->setCurrentIndex(0);
+}
+//-----------------------------------------------------------------------------
+void parse(QStringList &sl, const QString &s)
+{
+	sl.clear();
+	int i, ex=0, i1=0;
+	bool op=false, sp=true;
+	for(i=0;i<s.length();i++)
+	{
+		if(s[i].isLetterOrNumber() || s[i]=='\'' || s[i]=='(' || s[i]==')' || s[i]=='_')
+		{	if(sp)	i1=i;	sp = false;	}
+		else
+		{
+			QString p;
+			if(op)	p="_";	else if(ex)	p="+";
+			if(!sp)	sl<<p+s.mid(i1,i-i1);
+			sp = true;
+			if(s[i]=='{')	ex++;
+			if(s[i]=='}')	ex--;
+			if(s[i]=='[')	op=true;
+		}
+	}
+	if(!sp)	sl<<s.mid(i1);
+}
+//-----------------------------------------------------------------------------
+void NewCmdDialog::nameChanged(int s)
+{
+	QString n=name->itemText(s), par, a;
+	int k;
+	if(n.isEmpty())	return;
+	QStringList ss;	ss<<(pathHelp);
+	help->setSearchPaths(ss);
+	help->setSource(_("mgl_en")+QString(".html#")+n);
+	// clear old
+	kind->clear();	kinds.clear();	for(k=0;k<NUM_CH;k++)	argn[k].clear();
+	// try to find the keyword
+	QByteArray qcmd = n.toLatin1();
+	const char *cmd = qcmd.constData();
+	if(!parser.CmdType(cmd))	return;
+	info->setText(parser.CmdDesc(cmd));
+
+	par = parser.CmdFormat(cmd);
+	int i0 = par.indexOf(' ');	// first space if present
+	if(i0<0)	{	kind->addItem(par);	return;	}	// no arguments
+	// parse kind of arguments
+	par = par.mid(i0);
+	for(k=0;k<NUM_CH;k++)
+	{
+		a = par.section('|',k,k);
+		if(a.isEmpty())	break;
+		a=a.trimmed();
+		kinds<<n+" "+a;
+		parse(argn[k],a);
+	}
+	kind->addItems(kinds);	kind->setCurrentIndex(0);	replace = false;
+}
+//-----------------------------------------------------------------------------
+void NewCmdDialog::kindChanged(int s)
+{
+	if(s<0 || s>NUM_CH-1)	return;
+	cmd="";
+	int nn = argn[s].count();
+	QStringList lst;
+	for(int i=0;i<args->rowCount();i++)
+		lst<<args->item(i,0)->text()+"~ "+args->item(i,1)->text();
+//return;
+	args->setRowCount(nn);	args->setColumnCount(2);
+	QTableWidgetItem *it;
+	QString a;
+	QFont f;
+	bool optional;
+	for(int i=0;i<nn;i++)
+	{
+		it = new QTableWidgetItem;	args->setItem(i,0,it);
+		it = new QTableWidgetItem;	args->setItem(i,1,it);
+		a = argn[s].at(i);
+		optional = (a[0]=='_' || a[0]=='+');	if(optional)	a=a.mid(1);
+		f.setItalic(a[0].isUpper());	f.setBold(!optional);
+		args->item(i,0)->setText(a);	args->item(i,0)->setFont(f);
+		args->item(i,0)->setFlags(Qt::ItemIsEnabled);
+		args->item(i,1)->setFlags(Qt::ItemIsEditable|Qt::ItemIsEnabled);
+		for(int j=0;j<lst.count();j++)
+			if(lst[j].section('~',0,0)==a)
+				args->item(i,1)->setText(lst[j].section('~',1).trimmed());
+	}
+}
+//-----------------------------------------------------------------------------
+void NewCmdDialog::insertOpt()
+{	if(optDialog->exec())	opt->setText(optDialog->getOption());	}
+//-----------------------------------------------------------------------------
+void NewCmdDialog::insertData()
+{
+	int row = args->currentRow();
+	if(row<0)
+	{
+		QMessageBox::warning(this,_("New command"), _("No argument is selected"));
+		return;
+	}
+	QString a = args->item(row,0)->text();
+	if(a[0].isUpper())
+	{
+		if(datDialog->exec())	args->item(row,1)->setText(datDialog->getData());
+	}
+	else if(a=="'fmt'" || a=="_'fmt'")
+	{
+		if(stlDialog->exec())	args->item(row,1)->setText(stlDialog->getStyle());
+	}
+	else if(a=="'file'")
+	{
+		QString str = QFileDialog::getOpenFileName(this, _("UDAV - Insert filename"));
+		if(!str.isEmpty())	args->item(row,1)->setText(str);
+	}
+	else if(a=="'path'")
+	{
+		QString str = QFileDialog::getExistingDirectory(this, _("UDAV - Insert path"));
+		if(!str.isEmpty())	args->item(row,1)->setText(str);
+	}
+}
+//-----------------------------------------------------------------------------
+void NewCmdDialog::insertStl()
+{
+	int s=kind->currentIndex();
+	if(s<0 || s>4)
+	{	QMessageBox::warning(this,_("New command"),
+			_("Select first the proper kind of arguments"));
+		return;	}
+	if(!argn[s].contains("'fmt'") && !argn[s].contains("_'fmt'"))
+	{	QMessageBox::warning(this,_("New command"),
+			_("There is no 'fmt' argument for this command"));
+		return;	}
+	int i;
+	i = argn[s].indexOf("'fmt'");
+	if(i<0)	i = argn[s].indexOf("_'fmt'");
+	if(!stlDialog->exec())	args->item(i,1)->setText(stlDialog->getStyle());
+}
+//-----------------------------------------------------------------------------
+void NewCmdDialog::finish()
+{
+	QString txt,cur;
+	int s = kind->currentIndex();
+	if(s<0 || s>4)
+	{	QMessageBox::warning(this,_("New command"),
+			_("Select first the proper kind of arguments"));
+		cmd="";	return;	}
+	cmd = name->currentText();
+	int n = argn[s].count(), i;
+	bool op=false;
+	for(i=0;i<n;i++)
+	{
+		cur = argn[s].at(i);
+		txt = args->item(i,1)->text();
+		if(txt.isEmpty())
+		{
+			if(cur[0]!='_' && cur[0]!='+')
+			{	QMessageBox::warning(this,_("New command"),
+					_("You should specify required argument ")+cur);
+				cmd="";	return;	}
+			if(argn[s].at(i)[0]=='_')	op = true;
+		}
+		else
+		{
+			if(cur[0]=='\'' && txt[0]!='\'')
+			{	QMessageBox::warning(this,_("New command"),
+					_("You should put text inside ' ' for argument ")+cur);
+				cmd="";	return;	}
+			if(cur[1]=='\'' && txt[0]!='\'')
+			{	QMessageBox::warning(this,_("New command"),
+					_("You should put text inside ' ' for argument ")+cur.mid(1));
+				cmd="";	return;	}
+			if(cur[0]=='_' && op)
+			{	QMessageBox::warning(this,_("New command"),
+					_("You should specify all optional arguments before ")+cur.mid(1));
+				cmd="";	return;	}
+			cmd = cmd + ' ' + txt;
+		}
+	}
+	cmd = cmd + opt->text();	accept();	emit result(cmd, replace);
+}
+//-----------------------------------------------------------------------------
diff --git a/udav/newcmd_dlg.h b/udav/newcmd_dlg.h
new file mode 100644
index 0000000..7c80d92
--- /dev/null
+++ b/udav/newcmd_dlg.h
@@ -0,0 +1,76 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef NEWCMDDIALOG_H
+#define NEWCMDDIALOG_H
+//-----------------------------------------------------------------------------
+#include <QDialog>
+#include <QStringList>
+#define NUM_CH	16		// number of argument sets for a command
+class QComboBox;
+class QLabel;
+class QLineEdit;
+class QTableWidget;
+class QTextBrowser;
+class OptionDialog;
+class StyleDialog;
+class DataDialog;
+//-----------------------------------------------------------------------------
+class NewCmdDialog : public QDialog
+{
+Q_OBJECT
+public:
+	NewCmdDialog(QWidget *p);
+	const QString &getCommand()	{	return cmd;	}
+
+private slots:
+	void typeChanged(int);
+	void nameChanged(int);
+	void kindChanged(int);
+	void insertData();
+	void insertOpt();
+	void insertStl();
+	void finish();
+	void zoomIn();
+	void zoomOut();
+
+public slots:
+	void parseCmd(const QString &txt);
+
+signals:
+	void result(const QString &txt, bool replace);
+
+private:
+	QTextBrowser *help;
+	QComboBox *type, *name, *kind;
+	QLineEdit *opt;
+	QLabel *info;
+	QTableWidget *args;
+	QString cmd;
+	QStringList types, cmds[17], argn[NUM_CH], kinds;
+	OptionDialog *optDialog;
+	StyleDialog *stlDialog;
+	DataDialog *datDialog;
+	bool replace;	// flag to be used in result() signal
+
+	void fillList();
+};
+//-----------------------------------------------------------------------------
+#endif // NEWCMDDIALOG_H
+//-----------------------------------------------------------------------------
diff --git a/udav/open_dlg.cpp b/udav/open_dlg.cpp
new file mode 100644
index 0000000..a82b2cc
--- /dev/null
+++ b/udav/open_dlg.cpp
@@ -0,0 +1,179 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <QLabel>
+#include <QLayout>
+#include <QSettings>
+#include <QLineEdit>
+#include <QComboBox>
+#include <QPushButton>
+#include <QFileDialog>
+#include <QTextStream>
+#include <QRadioButton>
+#include <mgl2/mgl.h>
+#include "open_dlg.h"
+int numDataOpened=0;
+extern mglParse parser;
+QStringList dataScr;
+//-----------------------------------------------------------------------------
+QWidget *createDataOpenDlg(QWidget *p)	{	return new DataOpenDialog(p);	}
+QString getOpenDataFile(QWidget *w, QString filename)
+{
+	DataOpenDialog *d = dynamic_cast<DataOpenDialog *>(w);
+	if(d)
+	{
+		d->setFile(filename);
+		if(d->exec())	return d->getCode();
+	}
+	return QString();
+}
+//-----------------------------------------------------------------------------
+DataOpenDialog::DataOpenDialog(QWidget *parent) : QDialog(parent)
+{
+	setWindowTitle(_("UDAV - Open data file"));
+	QHBoxLayout *a;
+	QLabel *l;
+	QPushButton *b;
+	QVBoxLayout *o=new QVBoxLayout(this);
+
+	a = new QHBoxLayout;	o->addLayout(a);
+	l = new QLabel(_("Data name"));	a->addWidget(l);
+	char buf[32];	snprintf(buf,32,"mgl_%d",numDataOpened);	buf[31]=0;
+	name = new QLineEdit(buf,this);		a->addWidget(name);
+
+	rA = new QRadioButton(_("Auto detect data sizes"), this);
+	rA->setChecked(true);	o->addWidget(rA);
+	rM = new QRadioButton(_("Set data sizes manually"), this);
+	o->addWidget(rM);	a = new QHBoxLayout;	o->addLayout(a);
+	l = new QLabel(_("Nx"));	a->addWidget(l);
+	nx = new QLineEdit("1",this);	a->addWidget(nx);
+	l = new QLabel(_("Ny"));	a->addWidget(l);
+	ny = new QLineEdit("1",this);	a->addWidget(ny);
+	l = new QLabel(_("Nz"));	a->addWidget(l);
+	nz = new QLineEdit("1",this);	a->addWidget(nz);
+	r2 = new QRadioButton(_("Matrix with sizes from file"), this);	o->addWidget(r2);
+	r3 = new QRadioButton(_("3D data with sizes from file"), this);o->addWidget(r3);
+
+
+	QSettings settings("udav","UDAV");
+	settings.setPath(QSettings::IniFormat, QSettings::UserScope, "UDAV");
+	settings.beginGroup("/UDAV");
+	dataScr = settings.value("/dataScr").toStringList().mid(0,10);
+	dataScr.removeDuplicates();
+	settings.endGroup();
+
+	a = new QHBoxLayout;		o->addLayout(a);
+	l = new QLabel(_("Template"));	a->addWidget(l,0);
+	scr = new QComboBox(this);		a->addWidget(scr,1);
+	scr->setEditable(true);			scr->lineEdit()->setText("");
+	scr->addItem(_("default"));	scr->addItems(dataScr);
+	b = new QPushButton("...", this);	a->addWidget(b,0);
+	connect(b, SIGNAL(clicked()),this, SLOT(selectScr()));
+
+	a = new QHBoxLayout;	o->addLayout(a);	a->addStretch(1);
+	b = new QPushButton(_("Cancel"),this);	a->addWidget(b);
+	connect(b,SIGNAL(clicked()),this,SLOT(reject()));
+	b = new QPushButton(_("OK"), this);	a->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(prepareResult()));
+	b->setDefault(true);
+}
+//-----------------------------------------------------------------------------
+DataOpenDialog::~DataOpenDialog(){}
+//-----------------------------------------------------------------------------
+void DataOpenDialog::selectScr()
+{
+	QString str = QFileDialog::getOpenFileName(this, _("UDAV - Insert filename"),
+					scr->lineEdit()->text(), _("MGL files (*.mgl)"));
+	if(!str.isEmpty())
+	{
+		scr->lineEdit()->setText(str);
+		scr->insertItem(1,str);
+		dataScr.insert(0,str);
+		dataScr.removeDuplicates();
+	}
+}
+
+//-----------------------------------------------------------------------------
+void DataOpenDialog::prepareResult()
+{
+	code = "";	numDataOpened++;	data = name->text();
+	// prepare unique value of name for next time
+	char buf[32];	snprintf(buf,32,"mgl_%d",numDataOpened);
+	buf[31]=0;	name->setText(buf);
+	mglData *v = dynamic_cast<mglData*>(parser.AddVar(data.toLocal8Bit().constData()));
+	if(!v)	return;
+	int dd=0;
+	if(rA->isChecked())	//	auto sizes
+	{
+		v->Read(file.toLocal8Bit().constData());
+		if(v->nx==1)	{	v->nx = v->ny;	v->ny = v->nz;	}
+		code=QString("#read %1 '%2'\n").arg(data).arg(file);
+	}
+	else if(rM->isChecked())	//	manual sizes
+	{
+		int x=nx->text().toInt(), y=ny->text().toInt(), z=nz->text().toInt();
+		v->Read(file.toLocal8Bit().constData(),x,y,z);
+		code=QString("#read %1 '%2' %3 %4 %5\n").arg(data).arg(file).arg(x).arg(y).arg(z);
+	}
+	else if(r2->isChecked())	//	matrix
+	{
+		v->ReadMat(file.toLocal8Bit().constData());
+		code=QString("#readmat %1 '%2'\n").arg(data).arg(file);		dd=1;
+	}
+	else if(r3->isChecked())	//	3d-data
+	{
+		v->ReadMat(file.toLocal8Bit().constData(),3);
+		code=QString("#readmat %1 '%2' 3\n").arg(data).arg(file);	dd=2;
+	}
+	if(scr->lineEdit()->text().isEmpty() || scr->lineEdit()->text()==_("default"))
+	{
+		if(v->nz>1 || dd==2)
+			code+=QString("rotate 40 60\ncrange %1:box\nsurf3 %1\n").arg(data);
+		else if(v->ny>1 || dd==1)
+			code+=QString("rotate 40 60\ncrange %1:zrange %1:box\nsurf %1\n").arg(data);
+		else	code+=QString("yrange %1:box\nplot %1\n").arg(data);
+	}
+	else
+	{
+		QString str;
+		QFile fp(scr->lineEdit()->text());
+		if(fp.open(QFile::ReadOnly | QIODevice::Text))
+		{
+			QTextStream in(&fp);
+			str = in.readAll();
+			code += str.arg(data);
+		}
+	}
+
+	QSettings settings("udav","UDAV");
+	settings.setPath(QSettings::IniFormat, QSettings::UserScope, "UDAV");
+	settings.beginGroup("/UDAV");
+	settings.setValue("/dataScr", dataScr);
+	settings.endGroup();
+
+	accept();
+}
+//-----------------------------------------------------------------------------
+void DataOpenDialog::setFile(const QString &fname)
+{
+	file=fname;
+	mglData d(file.toLocal8Bit().constData());
+	rA->setText(QString(_("Auto detect data sizes (%1 x %2 x %3)")).arg(d.nx).arg(d.ny).arg(d.nz));
+}
+//-----------------------------------------------------------------------------
diff --git a/udav/open_dlg.h b/udav/open_dlg.h
new file mode 100644
index 0000000..9f74c9a
--- /dev/null
+++ b/udav/open_dlg.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef OPEN_DLG_H
+#define OPEN_DLG_H
+//-----------------------------------------------------------------------------
+#include <QDialog>
+class QLineEdit;
+class QComboBox;
+class QRadioButton;
+//-----------------------------------------------------------------------------
+/// Dialog for selecting command options
+class DataOpenDialog : public QDialog
+{
+Q_OBJECT
+public:
+	DataOpenDialog(QWidget *parent=0);
+	~DataOpenDialog();
+	inline const QString getCode()	{	return code;	}
+	inline const QString getName()	{	return data;	}
+	void setFile(const QString &fname);
+private slots:
+	void prepareResult();
+	void selectScr();
+private:
+	QString code, data, file;
+	QLineEdit *nx, *ny, *nz, *name;
+	QRadioButton *rA, *rM, *r2, *r3;
+	QComboBox *scr;
+};
+//-----------------------------------------------------------------------------
+#endif
+//-----------------------------------------------------------------------------
diff --git a/udav/opt_dlg.cpp b/udav/opt_dlg.cpp
new file mode 100644
index 0000000..27c5af6
--- /dev/null
+++ b/udav/opt_dlg.cpp
@@ -0,0 +1,131 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <QLabel>
+#include <QLayout>
+#include <QLineEdit>
+#include <QComboBox>
+#include <QPushButton>
+#include <QMessageBox>
+#include "opt_dlg.h"
+#include "mgl2/define.h"
+//-----------------------------------------------------------------------------
+OptionDialog::OptionDialog(QWidget *parent) : QDialog(parent)
+{
+	setWindowTitle(_("UDAV - Add options"));
+	QHBoxLayout *a;
+	QGridLayout *g;
+	QLabel *lbl;
+	QPushButton *b;
+	QVBoxLayout *o = new QVBoxLayout(this);	//o->setSpacing(6);
+	g = new QGridLayout();		o->addLayout(g);
+	lbl = new QLabel(_("X-range"),this);	g->addWidget(lbl,0,0);
+	x1 = new QLineEdit(this);	g->addWidget(x1,0,1);
+	x2 = new QLineEdit(this);	g->addWidget(x2,0,2);
+	lbl = new QLabel(_("Y-range"),this);	g->addWidget(lbl,0,3);
+	y1 = new QLineEdit(this);	g->addWidget(y1,0,4);
+	y2 = new QLineEdit(this);	g->addWidget(y2,0,5);
+	lbl = new QLabel(_("Z-range"),this);	g->addWidget(lbl,1,0);
+	z1 = new QLineEdit(this);	g->addWidget(z1,1,1);
+	z2 = new QLineEdit(this);	g->addWidget(z2,1,2);
+	lbl = new QLabel(_("C-range"),this);	g->addWidget(lbl,1,3);
+	c1 = new QLineEdit(this);	g->addWidget(c1,1,4);
+	c2 = new QLineEdit(this);	g->addWidget(c2,1,5);
+
+	lbl = new QLabel(_("Alpha"),this);		g->addWidget(lbl,2,0);
+	alpha = new QLineEdit(this);	g->addWidget(alpha,2,1);
+	lbl = new QLabel(_("Mesh num"),this);	g->addWidget(lbl,2,3);
+	mn = new QLineEdit(this);		g->addWidget(mn,2,4);
+
+	lbl = new QLabel(_("Ambient"),this);	g->addWidget(lbl,3,0);
+	amb = new QLineEdit(this);		g->addWidget(amb,3,1);
+	lbl = new QLabel(_("Diffuse"),this);	g->addWidget(lbl,3,3);
+	dif = new QLineEdit(this);		g->addWidget(dif,3,4);
+
+	lbl = new QLabel(_("Cutting"),this);	g->addWidget(lbl,4,0);
+	cut = new QComboBox(this);		g->addWidget(cut,4,1);
+	cut->insertItem(0,_("default"));	cut->insertItem(1,_("on"));	cut->insertItem(2,_("off"));
+	lbl = new QLabel(_("Light"),this);	g->addWidget(lbl,4,3);
+	lig = new QComboBox(this);		g->addWidget(lig,4,4);
+	lig->insertItem(0,_("default"));	lig->insertItem(1,_("on"));	lig->insertItem(2,_("off"));
+	
+	lbl = new QLabel(_("Value"),this);	g->addWidget(lbl,5,0);
+	val = new QLineEdit(this);		g->addWidget(val,5,1);
+	lbl = new QLabel(_("Size"),this);	g->addWidget(lbl,5,3);
+	fs = new QLineEdit(this);		g->addWidget(fs,5,4);
+	
+	a = new QHBoxLayout();	o->addLayout(a);
+	lbl = new QLabel(_("Legend"),this);	a->addWidget(lbl);
+	leg = new QLineEdit(this);	a->addWidget(leg);
+	a = new QHBoxLayout();	o->addLayout(a);
+	a->addStretch(1);
+	b = new QPushButton(_("Cancel"), this);	a->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(reject()));
+	b = new QPushButton(_("OK"), this);		a->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(prepareResult()));
+	b->setDefault(true);
+}
+//-----------------------------------------------------------------------------
+OptionDialog::~OptionDialog()	{}
+//-----------------------------------------------------------------------------
+void OptionDialog::prepareResult()
+{
+	result = "";
+	if(!x1->text().isEmpty() && !x2->text().isEmpty())
+		result = result + "; xrange "+x1->text()+" "+x2->text();
+	if((x1->text().isEmpty()) ^ (x2->text().isEmpty()))
+	{
+		QMessageBox::warning(this,_("UDAV - command options"), _("Both fields in xrange must be filled"));
+		return;
+	}
+	if(!y1->text().isEmpty() && !y2->text().isEmpty())
+		result = result + "; yrange "+y1->text()+" "+y2->text();
+	if((y1->text().isEmpty()) ^ (y2->text().isEmpty()))
+	{
+		QMessageBox::warning(this,_("UDAV - command options"), _("Both fields in yrange must be filled"));
+		return;
+	}
+	if(!z1->text().isEmpty() && !z2->text().isEmpty())
+		result = result + "; zrange "+z1->text()+" "+z2->text();
+	if((z1->text().isEmpty()) ^ (z2->text().isEmpty()))
+	{
+		QMessageBox::warning(this,_("UDAV - command options"), _("Both fields in zrange must be filled"));
+		return;
+	}
+	if(!c1->text().isEmpty() && !c2->text().isEmpty())
+		result = result + "; crange "+c1->text()+" "+c2->text();
+	if((c1->text().isEmpty()) ^ (c2->text().isEmpty()))
+	{
+		QMessageBox::warning(this,_("UDAV - command options"), _("Both fields in crange must be filled"));
+		return;
+	}
+	if(!val->text().isEmpty())	result = result+"; value "+val->text();
+	if(!alpha->text().isEmpty())result = result+"; alpha "+alpha->text();
+	if(!amb->text().isEmpty())	result = result+"; ambient "+amb->text();
+	if(!dif->text().isEmpty())	result = result+"; diffuse "+dif->text();
+	if(!mn->text().isEmpty())	result = result+"; meshnum "+mn->text();
+	if(!fs->text().isEmpty())	result = result+"; size "+fs->text();
+	if(cut->currentIndex()==1)	result = result+"; cut on";
+	if(cut->currentIndex()==2)	result = result+"; cut off";
+	if(lig->currentIndex()==1)	result = result+"; light on";
+	if(lig->currentIndex()==2)	result = result+"; light off";
+	if(!leg->text().isEmpty())	result = result+"; legend '"+leg->text()+"'";
+	accept();
+}
+//-----------------------------------------------------------------------------
diff --git a/udav/opt_dlg.h b/udav/opt_dlg.h
new file mode 100644
index 0000000..796c1e1
--- /dev/null
+++ b/udav/opt_dlg.h
@@ -0,0 +1,50 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef OPTION_DLG_H
+#define OPTION_DLG_H
+//-----------------------------------------------------------------------------
+#include <QDialog>
+#if defined(_MSC_VER)
+#include <mgl2/define.h>
+#endif
+class QLineEdit;
+class QComboBox;
+class QRadioButton;
+//-----------------------------------------------------------------------------
+/// Dialog for selecting command options
+class OptionDialog : public QDialog
+{
+Q_OBJECT
+public:
+	OptionDialog(QWidget *parent=0);
+	~OptionDialog();
+	
+	QString getOption()	{	return result;	}
+private slots:
+	void prepareResult();
+private:
+	QString result;
+	QLineEdit *x1, *x2, *y1, *y2, *z1, *z2, *c1, *c2;
+	QLineEdit *alpha, *amb, *dif, *val, *mn, *fs, *leg;
+	QComboBox *cut, *lig;
+};
+//-----------------------------------------------------------------------------
+#endif
+//-----------------------------------------------------------------------------
diff --git a/udav/plot_pnl.cpp b/udav/plot_pnl.cpp
new file mode 100644
index 0000000..430d35f
--- /dev/null
+++ b/udav/plot_pnl.cpp
@@ -0,0 +1,686 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <QTime>
+#include <QMenu>
+#include <QPrinter>
+#include <QTimer>
+#include <QScrollArea>
+#include <QPainter>
+#include <QPrintDialog>
+#include <QToolButton>
+#include <QToolBar>
+#include <QSpinBox>
+#include <QBoxLayout>
+#include <QMenuBar>
+#include <QMessageBox>
+#include <QTextEdit>
+#include <QTextBlock>
+
+#include <QMdiArea>
+#include "udav_wnd.h"
+#include "mgl2/qmathgl.h"
+#include "plot_pnl.h"
+#include "anim_dlg.h"
+#include "style_dlg.h"
+#include "newcmd_dlg.h"
+#include "subplot_dlg.h"
+#undef sprintf
+extern bool mglAutoSave;
+extern bool mglHighlight;
+extern bool mglDotsRefr;
+extern mglParse parser;
+int animDelay=500;
+void raisePanel(QWidget *w);
+//-----------------------------------------------------------------------------
+PlotPanel::PlotPanel(QWidget *parent) : QWidget(parent)
+{
+	gifOn = jpgOn = false;
+	animDialog = new AnimParam(this);	animPos = -1;
+	stlDialog = new StyleDialog(this);
+	newCmdDlg = new NewCmdDialog(this);
+	subplotDlg = new SubplotDialog(this);
+	printer = new QPrinter;		curPos = subId = -1;
+	timer = new QTimer(this);
+	connect(timer, SIGNAL(timeout()), this, SLOT(next()));
+	connect(animDialog, SIGNAL(putText(const QString &)), this, SLOT(animText(const QString &)));
+	connect(newCmdDlg, SIGNAL(result(const QString&, bool)), this, SLOT(putCmd(const QString&)));
+	connect(subplotDlg, SIGNAL(result(const QString&)), this, SLOT(insCmd(const QString&)));
+
+	menu = new QMenu(_("Graphics"),this);
+	popup = new QMenu(this);
+	mgl = new QMathGL(this);
+	draw = new mglDrawScript(parser.Self());
+	mgl_set_flag(mgl->getGraph(),1,MGL_SHOW_POS);	mgl->setDraw(draw);
+	connect(mgl,SIGNAL(askStyle(int)),this,SLOT(setStyle(int)));
+	connect(mgl,SIGNAL(objChanged(int)),this,SLOT(setCurPos(int)));
+
+	QBoxLayout *v = new QVBoxLayout(this);	toolTop(v);
+	QBoxLayout *h = new QHBoxLayout();	v->addLayout(h);	toolLeft(h);
+	mgl->setPopup(popup);
+
+	sv = new QScrollArea(this);	h->addWidget(sv);	sv->setWidget(mgl);
+	emit giveFocus();
+}
+//-----------------------------------------------------------------------------
+PlotPanel::~PlotPanel()	{	delete printer;	}
+//-----------------------------------------------------------------------------
+void PlotPanel::setStyle(int id)
+{	if(stlDialog->exec())	mgl->setStyle(id, stlDialog->getStyle());	}
+//-----------------------------------------------------------------------------
+void PlotPanel::setSubId(int id)	{	subId = id;	}
+//-----------------------------------------------------------------------------
+void PlotPanel::animText(const QString &txt)	{	animPutText(txt);	}
+//-----------------------------------------------------------------------------
+void PlotPanel::setCurPos(int pos)
+{
+	if(!mglHighlight)	pos = -1;
+	if(curPos!=pos)	{	curPos = pos;	execute();	}
+}
+//-----------------------------------------------------------------------------
+void PlotPanel::stop()	{	parser.Stop();	mgl->stop();	}
+//-----------------------------------------------------------------------------
+void PlotPanel::execute()
+{
+	if(mglAutoSave)	save();
+	mgl->setDotsPreview(mglDotsRefr);
+	raisePanel(this);
+	objId = subId = -1;
+	emit clearWarn();
+	QTime t;	t.start();
+	mgl_set_facenum(mgl->getGraph(),0);
+	draw->text=textMGL->toPlainText();
+	draw->line=curPos;
+	mgl->update();
+	setStatus(QString(_("Drawing time %1 ms")).arg(t.elapsed()*1e-3));
+	emit giveFocus();
+}
+//-----------------------------------------------------------------------------
+void PlotPanel::pressF9()
+{
+	int l=animParam.length(), i;
+	wchar_t *str = new wchar_t[l+2];
+	animPos = 0;	curPos = -1;
+	QString cur = animParam.section('\n',animPos,animPos);
+	for(i=0;i<l;i++)	str[i] = (cur[i]).unicode();
+	str[i] = 0;
+	parser.AddParam(0,str);
+	delete []str;
+
+	QTime t;	t.start();
+	parser.RestoreOnce();
+	draw->text=textMGL->toPlainText();
+	draw->line=curPos;	mgl->update();
+	setStatus(QString(_("Drawing time %1 ms")).arg(t.elapsed()*1e-3));
+	emit giveFocus();
+}
+//-----------------------------------------------------------------------------
+void PlotPanel::animStart(bool st)
+{
+	if(!st)
+	{	timer->stop();	if(gifOn)	mgl_close_gif(mgl->getGraph());	return;	}
+	if(animParam.isEmpty())
+	{
+		if(animDialog->exec())
+		{
+			animParam = animDialog->getResult();
+			gifOn = animDialog->gifOn;
+			jpgOn = animDialog->jpgOn;
+		}
+		else	return;
+	}
+	timer->start(animDelay);
+	if(gifOn)
+	{
+		mglGraph gr(mgl->getGraph());
+		gr.StartGIF("", animDelay);
+		gr.ResetFrames();
+	}
+	raisePanel(this);
+}
+//-----------------------------------------------------------------------------
+void PlotPanel::nextSlide()
+{
+	animSwitch(false);
+	next();
+	emit giveFocus();
+}
+//-----------------------------------------------------------------------------
+void PlotPanel::next()
+{
+	if(animParam.isEmpty())
+	{
+		if(animDialog->exec())
+		{
+			animParam = animDialog->getResult();
+			gifOn = animDialog->gifOn;
+			jpgOn = animDialog->jpgOn;
+		}
+		else	return;
+	}
+	int l=animParam.length(), n=animParam.count('\n') + (animParam[l-1]=='\n' ? 0:1), i;
+	wchar_t *str = new wchar_t[l+2];
+	animPos = (animPos+1)%n;
+	QString cur = animParam.section('\n',animPos,animPos);
+	for(i=0;i<l;i++)	str[i] = (cur[i]).unicode();
+	str[i] = 0;
+	parser.AddParam(0,str);
+	delete []str;
+	mglGraph gr(mgl->getGraph());
+	if(gr.GetNumFrame() >= n)	execute();
+	else
+	{
+		gr.NewFrame();	execute();	gr.EndFrame();
+		if(jpgOn)	gr.WriteFrame();
+		QString s;	s.sprintf(_("%d - %d of %d"),gr.GetNumFrame(),animPos,n);
+		setStatus(QString(_("Frame %1 of %2")).arg(animPos).arg(n));
+	}
+}
+//-----------------------------------------------------------------------------
+void PlotPanel::prevSlide()
+{
+	if(animParam.isEmpty())
+	{
+		if(animDialog->exec())
+		{
+			animParam = animDialog->getResult();
+			gifOn = animDialog->gifOn;
+			jpgOn = animDialog->jpgOn;
+		}
+		else	return;
+	}
+	animSwitch(false);
+	int l=animParam.length(), n=animParam.count('\n') + (animParam[l-1]=='\n' ? 0:1), i;
+	wchar_t *str = new wchar_t[l+2];
+	animPos = (animPos-1+n)%n;
+	QString cur = animParam.section('\n',animPos,animPos);
+	for(i=0;i<l;i++)	str[i] = (cur[i]).unicode();
+	str[i] = 0;
+	parser.AddParam(0,str);
+	delete []str;
+	execute();
+	emit giveFocus();
+}
+//-----------------------------------------------------------------------------
+void PlotPanel::animSetup()
+{
+	if(animDialog->exec())
+	{
+		animParam = animDialog->getResult();
+		gifOn = animDialog->gifOn;
+		jpgOn = animDialog->jpgOn;
+		animPos = -1;
+	}
+}
+//-----------------------------------------------------------------------------
+void PlotPanel::adjust()
+{
+	mgl->setSize(sv->width()-5, sv->height()-5);
+	raisePanel(this);	emit giveFocus();
+}
+//-----------------------------------------------------------------------------
+void PlotPanel::setMGLFont(const QString &path)	{	mgl->setMGLFont(path);	}
+//-----------------------------------------------------------------------------
+void PlotPanel::animParseText(const QString &txt)
+{
+	int i, n = txt.count('\n')+1;
+	double a1=0,a2=0,da=0;
+	QString s, all;
+	for(i=0;i<n;i++)
+	{
+		s = txt.section('\n',i,i);
+		if(s[0]=='#' && s[1]=='#' && s[2]=='a' && s[3].isSpace())
+			all = all + s.mid(4) + "\n";
+		if(s[0]=='#' && s[1]=='#' && s[2]=='c' && s[3].isSpace())
+		{
+			s = s.mid(4);
+			a1 = s.section(' ',0,0).toDouble();
+			a2 = s.section(' ',1,1).toDouble();
+			da = s.section(' ',2,2).toDouble();
+			animDialog->setResult(a1,a2,da);
+		}
+	}
+	if(!all.isEmpty())
+	{
+		animDialog->setResult(all);
+		animParam = all;
+	}
+	else if(a1!=a2 && da!=0)
+	{
+		for(double a=a1;a<=a2;a+=da)	all = all + QString::number(a)+"\n";
+		animParam = all;
+	}
+}
+//-----------------------------------------------------------------------------
+//#include "xpm/wire.xpm"
+#include "xpm/text.xpm"
+#include "xpm/line.xpm"
+#include "xpm/curve.xpm"
+#include "xpm/mark_o.xpm"
+#include "xpm/mark_s.xpm"
+#include "xpm/mark_a.xpm"
+#include "xpm/mark_d.xpm"
+#include "xpm/arc.xpm"
+#include "xpm/polygon.xpm"
+#include "xpm/box.xpm"
+//-----------------------------------------------------------------------------
+void PlotPanel::toolTop(QBoxLayout *v)
+{
+	QAction *a, *aa;
+	QMenu *o=menu, *oo;
+	QToolBar *t = new QToolBar(this);	v->addWidget(t);	t->setMovable(false);
+
+	// graphics menu
+	a = new QAction(QPixmap(":/png/alpha.png"), _("Alpha"), this);
+	a->setShortcut(Qt::CTRL+Qt::Key_T);	a->setCheckable(true);
+	connect(a, SIGNAL(toggled(bool)), mgl, SLOT(setAlpha(bool)));
+	connect(mgl, SIGNAL(alphaChanged(bool)), a, SLOT(setChecked(bool)));
+	a->setToolTip(_("Switch on/off transparency for the graphics (Ctrl+T)."));
+	o->addAction(a);	t->addAction(a);
+
+	a = new QAction(QPixmap(":/png/weather-clear.png"), _("Light"), this);
+	a->setShortcut(Qt::CTRL+Qt::Key_L);	a->setCheckable(true);
+	connect(a, SIGNAL(toggled(bool)), mgl, SLOT(setLight(bool)));
+	connect(mgl, SIGNAL(lightChanged(bool)), a, SLOT(setChecked(bool)));
+	a->setToolTip(_("Switch on/off lightning for the graphics (Ctrl+L)."));
+	o->addAction(a);	t->addAction(a);
+
+	a = new QAction(QPixmap(":/png/view-grid.png"), _("Grid"), this);
+	a->setShortcut(Qt::CTRL+Qt::Key_G);	a->setCheckable(true);
+	connect(a, SIGNAL(toggled(bool)), mgl, SLOT(setGrid(bool)));
+	a->setToolTip(_("Switch on/off grid of absolute coordinates (Ctrl+G)."));
+	o->addAction(a);	t->addAction(a);
+
+	a = new QAction(QPixmap(":/png/transform-move.png"), _("Rotate by mouse"), this);
+	a->setCheckable(true);
+	connect(a, SIGNAL(toggled(bool)), mgl, SLOT(setRotate(bool)));
+	connect(mgl, SIGNAL(rotateChanged(bool)), a, SLOT(setChecked(bool)));
+	a->setToolTip(_("Switch on/off mouse handling of the graphics\n(rotation, shifting, zooming and perspective)."));
+	t->addAction(a);
+
+/*	a = new QAction(QPixmap(":/png/zoom-fit-best.png"), _("Zoom by mouse"), this);
+	a->setCheckable(true);
+	connect(a, SIGNAL(toggled(bool)), mgl, SLOT(setZoom(bool)));
+	connect(mgl, SIGNAL(zoomChanged(bool)), a, SLOT(setChecked(bool)));
+	a->setToolTip(_("Switch on/off mouse zoom of selected region."));
+	t->addAction(a);*/
+
+	o->addSeparator();
+	a = new QAction(QPixmap(":/png/zoom-original.png"), _("Restore"), this);
+	connect(a, SIGNAL(triggered()), mgl, SLOT(restore()));
+	a->setToolTip(_("Restore default graphics rotation, zoom and perspective (Ctrl+Space)."));
+	a->setShortcut(Qt::CTRL+Qt::Key_Space);
+	o->addAction(a);	popup->addAction(a);	t->addAction(a);
+
+	a = new QAction(QPixmap(":/png/view-refresh.png"), _("Redraw"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(execute()));
+	a->setToolTip(_("Execute script and redraw graphics (F5)."));
+	a->setShortcut(Qt::Key_F5);
+	o->addAction(a);	popup->addAction(a);	t->addAction(a);
+
+	a = new QAction(QPixmap(":/png/view-fullscreen.png"), _("Adjust size"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(adjust()));
+	a->setToolTip(_("Change canvas size to fill whole region (F6)."));
+	a->setShortcut(Qt::Key_F6);		o->addAction(a);
+
+	a = new QAction(QPixmap(":/png/document-revert.png"), _("Reload"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(pressF9()));
+	a->setToolTip(_("Restore status for 'once' command and reload data (F9)."));
+	a->setShortcut(Qt::Key_F9);	o->addAction(a);	popup->addAction(a);
+
+	a = new QAction(QPixmap(":/png/process-stop.png"), _("Stop"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(stop()));
+	a->setToolTip(_("Stop script execution (F7)."));
+	a->setShortcut(Qt::Key_F7);	o->addAction(a);	t->addAction(a);
+
+	a = new QAction(QPixmap(":/png/edit-copy.png"), _("Copy plot"), this);
+	connect(a, SIGNAL(triggered()), mgl, SLOT(copy()));
+	a->setToolTip(_("Copy graphics to clipboard (Ctrl+Shift+G)."));
+	a->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_G);
+	o->addAction(a);	popup->addAction(a);	t->addAction(a);
+
+	a = new QAction(QPixmap(":/png/edit-copy.png"), _("Copy click coor."), this);
+	connect(a, SIGNAL(triggered()), mgl, SLOT(copyClickCoor()));
+	a->setToolTip(_("Copy coordinates of last mouse click to clipboard."));
+	o->addAction(a);	popup->addAction(a);
+
+//	l->addStretch(1);
+	{
+		oo = new QMenu(_("Primitives ..."),this);
+		aa=a = new QAction(QPixmap(line_xpm), _("Add line"), this);
+		connect(a, SIGNAL(triggered()), mgl, SLOT(addLine()));
+		connect(mgl, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
+		a->setToolTip(_("Add line which properties can be changed later by mouse."));
+		oo->addAction(a);
+
+		a = new QAction(QPixmap(arc_xpm), _("Add arc"), this);
+		connect(a, SIGNAL(triggered()), mgl, SLOT(addArc()));
+		connect(mgl, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
+		a->setToolTip(_("Add arc which properties can be changed later by mouse."));
+		oo->addAction(a);
+
+		a = new QAction(QPixmap(curve_xpm), _("Add curve"), this);
+		connect(a, SIGNAL(triggered()), mgl, SLOT(addCurve()));
+		connect(mgl, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
+		a->setToolTip(_("Add curve which properties can be changed later by mouse."));
+		oo->addAction(a);
+
+		a = new QAction(QPixmap(mark_s_xpm), _("Add rect"), this);
+		connect(a, SIGNAL(triggered()), mgl, SLOT(addRect()));
+		connect(mgl, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
+		a->setToolTip(_("Add rectangle which properties can be changed later by mouse."));
+		oo->addAction(a);
+
+		a = new QAction(QPixmap(mark_d_xpm), _("Add rhombus"), this);
+		connect(a, SIGNAL(triggered()), mgl, SLOT(addRhomb()));
+		connect(mgl, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
+		a->setToolTip(_("Add rhombus which properties can be changed later by mouse."));
+		oo->addAction(a);
+
+		a = new QAction(QPixmap(mark_o_xpm), _("Add ellipse"), this);
+		connect(a, SIGNAL(triggered()), mgl, SLOT(addEllipse()));
+		connect(mgl, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
+		a->setToolTip(_("Add ellipse which properties can be changed later by mouse."));
+		oo->addAction(a);
+
+		a = new QAction(QPixmap(polygon_xpm), _("Add polygon"), this);
+		connect(a, SIGNAL(triggered()), mgl, SLOT(addPolygon()));
+		connect(mgl, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
+		a->setToolTip(_("Add ellipse which properties can be changed later by mouse."));
+		oo->addAction(a);
+
+		a = new QAction(QPixmap(mark_a_xpm), _("Add mark"), this);
+		connect(a, SIGNAL(triggered()), mgl, SLOT(addMark()));
+		connect(mgl, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
+		a->setToolTip(_("Add marker which properties can be changed later by mouse."));
+		oo->addAction(a);
+
+		a = new QAction(QPixmap(text_xpm), _("Add text"), this);
+		connect(a, SIGNAL(triggered()), mgl, SLOT(addText()));
+		connect(mgl, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
+		a->setToolTip(_("Add text which properties can be changed later by mouse."));
+		oo->addAction(a);
+
+		QToolButton *bb = new QToolButton(this);
+		bb->setDefaultAction(aa);	bb->setMenu(oo);
+		bb->setPopupMode(QToolButton::MenuButtonPopup);
+		t->addWidget(bb);
+	}
+
+	a = new QAction(QPixmap(":/png/edit-delete.png"), _("Delete selected"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(deleteSelected()));
+	a->setToolTip(_("Delete selected plot."));
+	o->addAction(a);	popup->addAction(a);	t->addAction(a);
+
+	a = new QAction(QPixmap(":/png/layer-visible-off.png"), _("Hide selected"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(hideSelected()));
+	a->setToolTip(_("Hide selected plots."));
+	o->addAction(a);	popup->addAction(a);	t->addAction(a);
+
+	const MainWindow *mw=findMain(this);
+	if(mw)	t->addAction(mw->ahide);
+
+	a = new QAction(QPixmap(":/png/format-indent-more.png"), _("New command"), this);
+	connect(a, SIGNAL(triggered()), newCmdDlg, SLOT(show()));
+	a->setToolTip(_("Show dialog for new command or edit arguments of existed one."));
+	o->addAction(a);	popup->addAction(a);	t->addAction(a);
+
+	a = new QAction(QPixmap(box_xpm), _("New inplot"), this);
+	connect(a, SIGNAL(triggered()), subplotDlg, SLOT(show()));
+	a->setToolTip(_("Show dialog for new inplot and put it into the script."));
+	o->addAction(a);	popup->addAction(a);	t->addAction(a);
+
+	a = new QAction(QPixmap(":/png/object-order-lower.png"), _("Move plot up"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(movePlotUp()));
+	a->setToolTip(_("Move selected plot up to previous subplot."));
+	o->addAction(a);	popup->addAction(a);	t->addAction(a);
+
+	a = new QAction(QPixmap(":/png/object-order-raise.png"), _("Move plot down"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(movePlotDown()));
+	a->setToolTip(_("Move selected plot down to next subplot."));
+	o->addAction(a);	popup->addAction(a);	t->addAction(a);
+
+
+	o->addMenu(oo);	//t->addSeparator();
+
+	tet = new QSpinBox(this);	tet->setWrapping(true);
+	t->addWidget(tet);	tet->setRange(-180, 180);	tet->setSingleStep(10);
+	connect(tet, SIGNAL(valueChanged(int)), mgl, SLOT(setTet(int)));
+	connect(mgl, SIGNAL(tetChanged(int)), tet, SLOT(setValue(int)));
+	tet->setToolTip(_("Set value of \\theta angle.\nYou can use keys (Shift+Meta+Up or Shift+Meta+Down)."));
+
+	phi = new QSpinBox(this);	phi->setWrapping(true);
+	t->addWidget(phi);	phi->setRange(-180, 180);	phi->setSingleStep(10);
+	connect(phi, SIGNAL(valueChanged(int)), mgl, SLOT(setPhi(int)));
+	connect(mgl, SIGNAL(phiChanged(int)), phi, SLOT(setValue(int)));
+	phi->setToolTip(_("Set value of \\phi angle.\nYou can use keys (Shift+Meta+Left or Shift+Meta+Right)."));
+
+	oo = new QMenu(_("Export as 2D ..."),this);
+	oo->addAction(_("PNG"), mgl, SLOT(exportPNG()),Qt::ALT+Qt::Key_P);
+	oo->addAction(_("solid PNG"), mgl, SLOT(exportPNGs()),Qt::ALT+Qt::Key_F);
+	oo->addAction(_("JPEG"), mgl, SLOT(exportJPG()),Qt::ALT+Qt::Key_J);
+	oo->addAction(_("bitmap EPS"), mgl, SLOT(exportBPS()));
+	oo->addAction(_("vector EPS"), mgl, SLOT(exportEPS()),Qt::ALT+Qt::Key_E);
+	oo->addAction(_("SVG"), mgl, SLOT(exportSVG()),Qt::ALT+Qt::Key_S);
+	oo->addAction(_("LaTeX"), mgl, SLOT(exportTEX()),Qt::ALT+Qt::Key_L);
+
+	o->addMenu(oo);		popup->addMenu(oo);
+	oo = new QMenu(_("Export as 3D ..."),this);
+	oo->addAction(_("MGLD"), mgl, SLOT(exportMGLD()),Qt::ALT+Qt::Key_M);
+	oo->addAction(_("PRC"), mgl, SLOT(exportPRC()),Qt::ALT+Qt::Key_D);
+	oo->addAction(_("OBJ"), mgl, SLOT(exportOBJ()),Qt::ALT+Qt::Key_O);
+	oo->addAction(_("STL"), mgl, SLOT(exportSTL()));
+	oo->addAction(_("XYZ"), mgl, SLOT(exportXYZ()));
+//	oo->addAction(_("X3D"), QMGL, SLOT(exportX3D()),Qt::ALT+Qt::Key_X);	// TODO: Add later
+	o->addMenu(oo);		popup->addMenu(oo);
+}
+//-----------------------------------------------------------------------------
+void PlotPanel::toolLeft(QBoxLayout *h)
+{
+	QAction *a;
+	QMenu *o=menu, *oo;
+	QToolBar *t = new QToolBar(this);	h->addWidget(t);	t->setMovable(false);
+	t->setAllowedAreas(Qt::LeftToolBarArea);	t->setOrientation(Qt::Vertical);
+
+	// zooming menu
+	oo = o->addMenu(_("Zoom/move"));
+	a = new QAction(QPixmap(":/png/arrow-left.png"), _("Move left"), this);
+	connect(a, SIGNAL(triggered()), mgl, SLOT(shiftLeft()));
+	a->setShortcut(Qt::ALT+Qt::Key_Left);
+	a->setToolTip(_("Move graphics left by 1/3 of its width."));
+	oo->addAction(a);	t->addAction(a);
+
+	a = new QAction(QPixmap(":/png/arrow-up.png"), _("Move up"), this);
+	connect(a, SIGNAL(triggered()), mgl, SLOT(shiftUp()));
+	a->setShortcut(Qt::ALT+Qt::Key_Up);
+	a->setToolTip(_("Move graphics up by 1/3 of its height."));
+	oo->addAction(a);	t->addAction(a);
+
+	a = new QAction(QPixmap(":/png/zoom-in.png"), _("Zoom in"), this);
+	connect(a, SIGNAL(triggered()), mgl, SLOT(zoomIn()));
+	a->setShortcut(Qt::ALT+Qt::Key_Equal);
+	a->setToolTip(_("Zoom in graphics."));
+	oo->addAction(a);	t->addAction(a);
+
+	a = new QAction(QPixmap(":/png/zoom-out.png"), _("Zoom out"), this);
+	connect(a, SIGNAL(triggered()), mgl, SLOT(zoomOut()));
+	a->setShortcut(Qt::ALT+Qt::Key_Minus);
+	a->setToolTip(_("Zoom out graphics."));
+	oo->addAction(a);	t->addAction(a);
+
+	a = new QAction(QPixmap(":/png/arrow-down.png"), _("Move down"), this);
+	connect(a, SIGNAL(triggered()), mgl, SLOT(shiftDown()));
+	a->setShortcut(Qt::ALT+Qt::Key_Down);
+	a->setToolTip(_("Move graphics up down 1/3 of its height."));
+	oo->addAction(a);	t->addAction(a);
+
+	a = new QAction(QPixmap(":/png/arrow-right.png"), _("Move right"), this);
+	connect(a, SIGNAL(triggered()), mgl, SLOT(shiftRight()));
+	a->setShortcut(Qt::ALT+Qt::Key_Right);
+	a->setToolTip(_("Move graphics right by 1/3 of its width."));
+	oo->addAction(a);	t->addAction(a);
+
+	// rotate menu
+	oo = o->addMenu(_("Rotate"));
+	a = new QAction(QPixmap(":/png/object-rotate-up.png"), _("Rotate up"), this);
+	a->setShortcut(Qt::SHIFT+Qt::META+Qt::Key_Up);
+	connect(a, SIGNAL(triggered()), tet, SLOT(stepUp()));	oo->addAction(a);
+	a->setToolTip(_("Increase \\theta angle by 10 degrees."));
+	a = new QAction(QPixmap(":/png/object-rotate-down.png"), _("Rotate down"), this);
+	a->setShortcut(Qt::SHIFT+Qt::META+Qt::Key_Down);
+	connect(a, SIGNAL(triggered()), tet, SLOT(stepDown()));	oo->addAction(a);
+	a->setToolTip(_("Decrease \\theta angle by 10 degrees."));
+	a = new QAction(QPixmap(":/png/object-rotate-left.png"), _("Rotate left"), this);
+	a->setShortcut(Qt::SHIFT+Qt::META+Qt::Key_Right);
+	connect(a, SIGNAL(triggered()), phi, SLOT(stepUp()));	oo->addAction(a);
+	a->setToolTip(_("Increase \\phi angle by 10 degrees."));
+	a = new QAction(QPixmap(":/png/object-rotate-right.png"), _("Rotate right"), this);
+	a->setShortcut(Qt::SHIFT+Qt::META+Qt::Key_Left);
+	connect(a, SIGNAL(triggered()), phi, SLOT(stepDown()));	oo->addAction(a);
+	a->setToolTip(_("Decrease \\phi angle by 10 degrees."));
+
+	// animation menu
+	oo = o->addMenu(_("Animation"));
+	a = new QAction(QPixmap(":/png/media-seek-forward.png"), _("Next slide"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(nextSlide()));
+	a->setShortcut(Qt::CTRL+Qt::Key_Period);
+	a->setToolTip(_("Show next slide (Ctrl+.)."));
+	oo->addAction(a);	t->addAction(a);
+
+	a = new QAction(QPixmap(":/png/media-playback-start.png"), _("Slideshow"), this);
+	a->setCheckable(true);
+	connect(a, SIGNAL(toggled(bool)), this, SLOT(animStart(bool)));
+	connect(this, SIGNAL(animSwitch(bool)),a,SLOT(setChecked(bool)));
+	a->setToolTip(_("Run slideshow (Ctrl+F5). If no parameter specified\nthen the dialog with slideshow options will appear."));
+	a->setShortcut(Qt::CTRL+Qt::Key_F5);	oo->addAction(a);	t->addAction(a);
+
+	oo->addAction(_("Setup show"), this, SLOT(animSetup()), Qt::CTRL+Qt::Key_W);
+
+	a = new QAction(QPixmap(":/png/media-seek-backward.png"), _("Prev slide"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(prevSlide()));
+	a->setShortcut(Qt::CTRL+Qt::Key_Comma);
+	a->setToolTip(_("Show previous slide (Ctrl+,)."));
+	oo->addAction(a);	t->addAction(a);
+}
+//-----------------------------------------------------------------------------
+QString PlotPanel::getFit()	{	return QString(mgl_get_fit(mgl->getGraph()));	}
+//-----------------------------------------------------------------------------
+void PlotPanel::deleteSelected()
+{
+	if(curPos>=0)
+	{
+		textMGL->moveCursor(QTextCursor::Start);
+		for(int i=0;i<curPos;i++)	textMGL->moveCursor(QTextCursor::NextBlock);
+		QTextCursor tc= textMGL->textCursor();
+		tc.select(QTextCursor::LineUnderCursor);
+		tc.removeSelectedText();
+		tc.deleteChar();
+		curPos = -1;	execute();
+	}
+	else emit setStatus("No selection.");
+}
+//-----------------------------------------------------------------------------
+void PlotPanel::hideSelected()
+{
+	if(curPos>=0)
+	{
+		textMGL->moveCursor(QTextCursor::Start);
+		for(int i=0;i<curPos;i++)	textMGL->moveCursor(QTextCursor::NextBlock);
+		textMGL->insertPlainText("#h ");
+		curPos = -1;	execute();
+	}
+	else emit setStatus("No selection.");
+}
+//-----------------------------------------------------------------------------
+void PlotPanel::putCmd(const QString &cmd)
+{
+	textMGL->moveCursor(QTextCursor::Start);
+	if(curPos>=0)	for(int i=0;i<curPos;i++)
+		textMGL->moveCursor(QTextCursor::NextBlock);
+	textMGL->insertPlainText(cmd+"\n");
+	curPos = -1;	execute();
+}
+//-----------------------------------------------------------------------------
+void PlotPanel::insCmd(const QString &cmd)
+{
+	textMGL->moveCursor(QTextCursor::EndOfBlock);
+	textMGL->insertPlainText("\n"+cmd);
+	curPos = -1;	execute();
+}
+//-----------------------------------------------------------------------------
+void PlotPanel::movePlotUp()
+{
+	if(curPos>0)
+	{
+		QTextCursor tc = textMGL->textCursor();
+		tc.movePosition(QTextCursor::Start);
+		tc.movePosition(QTextCursor::NextBlock,QTextCursor::MoveAnchor,curPos);
+		tc.select(QTextCursor::BlockUnderCursor);
+		QString s = tc.selectedText();
+		tc.deleteChar();
+		bool ins=true;
+
+		while(tc.movePosition(QTextCursor::PreviousBlock))
+		{
+			QString q = tc.block().text();
+			if(q.startsWith("subplot ") || q.startsWith("inplot ") || q.startsWith("multiplot ") || q.startsWith("gridplot ") || q.startsWith("columnplot ") || q.startsWith("stickplot "))
+			{
+				tc.movePosition(QTextCursor::EndOfBlock);
+				tc.insertText(s);	ins=false;	break;
+			}
+		}
+		if(ins)
+		{
+			tc.movePosition(QTextCursor::Start);	tc.insertText(s+"\n");
+			tc.movePosition(QTextCursor::Start);	tc.deleteChar();
+		}
+		curPos = tc.block().blockNumber();	execute();
+	}
+	else if(curPos<0)	emit setStatus("No selection.");
+}
+//-----------------------------------------------------------------------------
+void PlotPanel::movePlotDown()
+{
+	if(curPos>=0)
+	{
+		QTextCursor tc = textMGL->textCursor();
+		tc.movePosition(QTextCursor::Start);
+		tc.movePosition(QTextCursor::NextBlock,QTextCursor::MoveAnchor,curPos);
+		tc.select(QTextCursor::BlockUnderCursor);
+		QString s = tc.selectedText();
+		if(curPos==0)	s = "\n"+s;
+		tc.deleteChar();
+		bool ins=true;
+
+		while(tc.movePosition(QTextCursor::NextBlock))
+		{
+			QString q = tc.block().text();
+			if(q.startsWith("subplot ") || q.startsWith("inplot ") || q.startsWith("multiplot ") || q.startsWith("gridplot ") || q.startsWith("columnplot ") || q.startsWith("stickplot "))
+			{
+				tc.movePosition(QTextCursor::EndOfBlock);
+				tc.insertText(s);	ins=false;	break;
+			}
+		}
+		if(ins)	{	tc.movePosition(QTextCursor::End);	tc.insertText(s);	}
+		curPos = tc.block().blockNumber();	execute();
+	}
+	else emit setStatus("No selection.");
+}
+//-----------------------------------------------------------------------------
+
diff --git a/udav/plot_pnl.h b/udav/plot_pnl.h
new file mode 100644
index 0000000..dd03f9e
--- /dev/null
+++ b/udav/plot_pnl.h
@@ -0,0 +1,110 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef PLOT_PNL_H
+#define PLOT_PNL_H
+//-----------------------------------------------------------------------------
+#include <QWidget>
+#include <qabstractitemmodel.h>
+//-----------------------------------------------------------------------------
+class QMenu;
+class QTimer;
+class QSpinBox;
+class QPopupMenu;
+class QScrollArea;
+class QBoxLayout;
+class QTextEdit;
+class QMathGL;
+class mglDrawScript;
+class InfoDialog;
+class AnimParam;
+class DatPanel;
+class StyleDialog;
+class QPrinter;
+class NewCmdDialog;
+class SubplotDialog;
+//-----------------------------------------------------------------------------
+class PlotPanel : public QWidget
+{
+Q_OBJECT
+public:
+	QMenu *menu;
+	QMathGL *mgl;
+	mglDrawScript *draw;	///< Class for drawing MGL script
+	QTextEdit *textMGL;		///< Editor with MGL script body
+	NewCmdDialog *newCmdDlg;
+	SubplotDialog *subplotDlg;
+	PlotPanel(QWidget *wp=0);
+	~PlotPanel();
+	void setMGLFont(const QString &path);
+	QString getFit();
+
+public slots:
+	void animParseText(const QString &txt);
+	void setCurPos(int pos=-1);
+	void execute();
+
+signals:
+	void save();
+	void animPutText(const QString &);
+	void setStatus(const QString &);
+	void animSwitch(bool);
+	void giveFocus();
+	void clearWarn();
+
+private slots:
+	void animText(const QString &);
+	void next();
+	void nextSlide();
+	void prevSlide();
+	void animStart(bool st);
+	void animSetup();
+	void adjust();
+	void pressF9();
+	void stop();
+	void setStyle(int id);
+	void setSubId(int id);
+	void deleteSelected();
+	void hideSelected();
+	void putCmd(const QString &cmd);
+	void insCmd(const QString &cmd);
+	void movePlotUp();
+	void movePlotDown();
+
+private:
+	bool gifOn, jpgOn;
+	QScrollArea* sv;
+	QSpinBox *tet, *phi;
+	// animation
+	QString animParam;
+	int animPos;
+	int curPos;
+	QTimer *timer;
+	AnimParam *animDialog;
+	QMenu *popup;
+	QPrinter *printer;
+	StyleDialog *stlDialog;
+	int objId;
+	int subId;
+	
+	void toolTop(QBoxLayout *l);
+	void toolLeft(QBoxLayout *l);
+};
+//-----------------------------------------------------------------------------
+#endif // PLOT_PNL_H
diff --git a/udav/png/accessories-calculator.png b/udav/png/accessories-calculator.png
new file mode 100644
index 0000000..acc5ce0
Binary files /dev/null and b/udav/png/accessories-calculator.png differ
diff --git a/udav/png/alpha.png b/udav/png/alpha.png
new file mode 100644
index 0000000..fdb8836
Binary files /dev/null and b/udav/png/alpha.png differ
diff --git a/udav/png/arrow-down-double.png b/udav/png/arrow-down-double.png
new file mode 100644
index 0000000..bb5b211
Binary files /dev/null and b/udav/png/arrow-down-double.png differ
diff --git a/udav/png/arrow-down.png b/udav/png/arrow-down.png
new file mode 100644
index 0000000..bf8cc2a
Binary files /dev/null and b/udav/png/arrow-down.png differ
diff --git a/udav/png/arrow-left-double.png b/udav/png/arrow-left-double.png
new file mode 100644
index 0000000..6fb6b1f
Binary files /dev/null and b/udav/png/arrow-left-double.png differ
diff --git a/udav/png/arrow-left.png b/udav/png/arrow-left.png
new file mode 100644
index 0000000..4f2ad45
Binary files /dev/null and b/udav/png/arrow-left.png differ
diff --git a/udav/png/arrow-right-double.png b/udav/png/arrow-right-double.png
new file mode 100644
index 0000000..0a52981
Binary files /dev/null and b/udav/png/arrow-right-double.png differ
diff --git a/udav/png/arrow-right.png b/udav/png/arrow-right.png
new file mode 100644
index 0000000..3dc5c5a
Binary files /dev/null and b/udav/png/arrow-right.png differ
diff --git a/udav/png/arrow-up-double.png b/udav/png/arrow-up-double.png
new file mode 100644
index 0000000..91f48ac
Binary files /dev/null and b/udav/png/arrow-up-double.png differ
diff --git a/udav/png/arrow-up.png b/udav/png/arrow-up.png
new file mode 100644
index 0000000..afca099
Binary files /dev/null and b/udav/png/arrow-up.png differ
diff --git a/udav/png/dialog-information.png b/udav/png/dialog-information.png
new file mode 100644
index 0000000..8851b99
Binary files /dev/null and b/udav/png/dialog-information.png differ
diff --git a/udav/png/document-export.png b/udav/png/document-export.png
new file mode 100644
index 0000000..eb82440
Binary files /dev/null and b/udav/png/document-export.png differ
diff --git a/udav/png/document-import.png b/udav/png/document-import.png
new file mode 100644
index 0000000..82140be
Binary files /dev/null and b/udav/png/document-import.png differ
diff --git a/udav/png/document-new.png b/udav/png/document-new.png
new file mode 100644
index 0000000..a956a80
Binary files /dev/null and b/udav/png/document-new.png differ
diff --git a/udav/png/document-open-folder.png b/udav/png/document-open-folder.png
new file mode 100644
index 0000000..8f3ef6d
Binary files /dev/null and b/udav/png/document-open-folder.png differ
diff --git a/udav/png/document-open.png b/udav/png/document-open.png
new file mode 100644
index 0000000..17076a3
Binary files /dev/null and b/udav/png/document-open.png differ
diff --git a/udav/png/document-print.png b/udav/png/document-print.png
new file mode 100644
index 0000000..5977b3d
Binary files /dev/null and b/udav/png/document-print.png differ
diff --git a/udav/png/document-properties.png b/udav/png/document-properties.png
new file mode 100644
index 0000000..ab0e8ea
Binary files /dev/null and b/udav/png/document-properties.png differ
diff --git a/udav/png/document-revert.png b/udav/png/document-revert.png
new file mode 100644
index 0000000..47d7415
Binary files /dev/null and b/udav/png/document-revert.png differ
diff --git a/udav/png/document-save.png b/udav/png/document-save.png
new file mode 100644
index 0000000..22ff495
Binary files /dev/null and b/udav/png/document-save.png differ
diff --git a/udav/png/edit-clear.png b/udav/png/edit-clear.png
new file mode 100644
index 0000000..78d183f
Binary files /dev/null and b/udav/png/edit-clear.png differ
diff --git a/udav/png/edit-copy.png b/udav/png/edit-copy.png
new file mode 100644
index 0000000..54eaf77
Binary files /dev/null and b/udav/png/edit-copy.png differ
diff --git a/udav/png/edit-cut.png b/udav/png/edit-cut.png
new file mode 100644
index 0000000..f4a55e3
Binary files /dev/null and b/udav/png/edit-cut.png differ
diff --git a/udav/png/edit-delete.png b/udav/png/edit-delete.png
new file mode 100644
index 0000000..184f762
Binary files /dev/null and b/udav/png/edit-delete.png differ
diff --git a/udav/png/edit-find.png b/udav/png/edit-find.png
new file mode 100644
index 0000000..ee69755
Binary files /dev/null and b/udav/png/edit-find.png differ
diff --git a/udav/png/edit-paste.png b/udav/png/edit-paste.png
new file mode 100644
index 0000000..3f71b1c
Binary files /dev/null and b/udav/png/edit-paste.png differ
diff --git a/udav/png/edit-redo.png b/udav/png/edit-redo.png
new file mode 100644
index 0000000..c03bba0
Binary files /dev/null and b/udav/png/edit-redo.png differ
diff --git a/udav/png/edit-select-all.png b/udav/png/edit-select-all.png
new file mode 100644
index 0000000..2276ddc
Binary files /dev/null and b/udav/png/edit-select-all.png differ
diff --git a/udav/png/edit-undo.png b/udav/png/edit-undo.png
new file mode 100644
index 0000000..f123942
Binary files /dev/null and b/udav/png/edit-undo.png differ
diff --git a/udav/png/folder.png b/udav/png/folder.png
new file mode 100644
index 0000000..13c1962
Binary files /dev/null and b/udav/png/folder.png differ
diff --git a/udav/png/format-indent-more.png b/udav/png/format-indent-more.png
new file mode 100644
index 0000000..00309ea
Binary files /dev/null and b/udav/png/format-indent-more.png differ
diff --git a/udav/png/format-stroke-color.png b/udav/png/format-stroke-color.png
new file mode 100644
index 0000000..9523c25
Binary files /dev/null and b/udav/png/format-stroke-color.png differ
diff --git a/udav/png/go-bottom.png b/udav/png/go-bottom.png
new file mode 100644
index 0000000..37ea459
Binary files /dev/null and b/udav/png/go-bottom.png differ
diff --git a/udav/png/go-down.png b/udav/png/go-down.png
new file mode 100644
index 0000000..67e91ec
Binary files /dev/null and b/udav/png/go-down.png differ
diff --git a/udav/png/go-first-view.png b/udav/png/go-first-view.png
new file mode 100644
index 0000000..baee851
Binary files /dev/null and b/udav/png/go-first-view.png differ
diff --git a/udav/png/go-first.png b/udav/png/go-first.png
new file mode 100644
index 0000000..84119c6
Binary files /dev/null and b/udav/png/go-first.png differ
diff --git a/udav/png/go-jump-locationbar.png b/udav/png/go-jump-locationbar.png
new file mode 100644
index 0000000..637c1cf
Binary files /dev/null and b/udav/png/go-jump-locationbar.png differ
diff --git a/udav/png/go-last-view.png b/udav/png/go-last-view.png
new file mode 100644
index 0000000..c90d919
Binary files /dev/null and b/udav/png/go-last-view.png differ
diff --git a/udav/png/go-last.png b/udav/png/go-last.png
new file mode 100644
index 0000000..ebe69bd
Binary files /dev/null and b/udav/png/go-last.png differ
diff --git a/udav/png/go-next-view-page.png b/udav/png/go-next-view-page.png
new file mode 100644
index 0000000..3b8784b
Binary files /dev/null and b/udav/png/go-next-view-page.png differ
diff --git a/udav/png/go-next-view.png b/udav/png/go-next-view.png
new file mode 100644
index 0000000..8a9ff0a
Binary files /dev/null and b/udav/png/go-next-view.png differ
diff --git a/udav/png/go-next.png b/udav/png/go-next.png
new file mode 100644
index 0000000..8cbb81e
Binary files /dev/null and b/udav/png/go-next.png differ
diff --git a/udav/png/go-previous-view-page.png b/udav/png/go-previous-view-page.png
new file mode 100644
index 0000000..0a391d6
Binary files /dev/null and b/udav/png/go-previous-view-page.png differ
diff --git a/udav/png/go-previous-view.png b/udav/png/go-previous-view.png
new file mode 100644
index 0000000..d75f1e4
Binary files /dev/null and b/udav/png/go-previous-view.png differ
diff --git a/udav/png/go-previous.png b/udav/png/go-previous.png
new file mode 100644
index 0000000..87d0994
Binary files /dev/null and b/udav/png/go-previous.png differ
diff --git a/udav/png/go-top.png b/udav/png/go-top.png
new file mode 100644
index 0000000..803e432
Binary files /dev/null and b/udav/png/go-top.png differ
diff --git a/udav/png/go-up.png b/udav/png/go-up.png
new file mode 100644
index 0000000..5fafd13
Binary files /dev/null and b/udav/png/go-up.png differ
diff --git a/udav/png/help-contents.png b/udav/png/help-contents.png
new file mode 100644
index 0000000..b3ae2c3
Binary files /dev/null and b/udav/png/help-contents.png differ
diff --git a/udav/png/help-faq.png b/udav/png/help-faq.png
new file mode 100644
index 0000000..f6bc721
Binary files /dev/null and b/udav/png/help-faq.png differ
diff --git a/udav/png/layer-visible-off.png b/udav/png/layer-visible-off.png
new file mode 100644
index 0000000..74a4f07
Binary files /dev/null and b/udav/png/layer-visible-off.png differ
diff --git a/udav/png/layer-visible-on.png b/udav/png/layer-visible-on.png
new file mode 100644
index 0000000..ead7d91
Binary files /dev/null and b/udav/png/layer-visible-on.png differ
diff --git a/udav/png/list-add.png b/udav/png/list-add.png
new file mode 100644
index 0000000..eefb01e
Binary files /dev/null and b/udav/png/list-add.png differ
diff --git a/udav/png/list-remove.png b/udav/png/list-remove.png
new file mode 100644
index 0000000..f1f0dee
Binary files /dev/null and b/udav/png/list-remove.png differ
diff --git a/udav/png/media-playback-start.png b/udav/png/media-playback-start.png
new file mode 100644
index 0000000..80ff3a1
Binary files /dev/null and b/udav/png/media-playback-start.png differ
diff --git a/udav/png/media-seek-backward.png b/udav/png/media-seek-backward.png
new file mode 100644
index 0000000..6b76327
Binary files /dev/null and b/udav/png/media-seek-backward.png differ
diff --git a/udav/png/media-seek-forward.png b/udav/png/media-seek-forward.png
new file mode 100644
index 0000000..6c3b1c4
Binary files /dev/null and b/udav/png/media-seek-forward.png differ
diff --git a/udav/png/object-group.png b/udav/png/object-group.png
new file mode 100644
index 0000000..5238c12
Binary files /dev/null and b/udav/png/object-group.png differ
diff --git a/udav/png/object-order-lower.png b/udav/png/object-order-lower.png
new file mode 100644
index 0000000..7289dee
Binary files /dev/null and b/udav/png/object-order-lower.png differ
diff --git a/udav/png/object-order-raise.png b/udav/png/object-order-raise.png
new file mode 100644
index 0000000..8819a31
Binary files /dev/null and b/udav/png/object-order-raise.png differ
diff --git a/udav/png/object-rotate-down.png b/udav/png/object-rotate-down.png
new file mode 100644
index 0000000..b62a39c
Binary files /dev/null and b/udav/png/object-rotate-down.png differ
diff --git a/udav/png/object-rotate-left.png b/udav/png/object-rotate-left.png
new file mode 100644
index 0000000..facad55
Binary files /dev/null and b/udav/png/object-rotate-left.png differ
diff --git a/udav/png/object-rotate-right.png b/udav/png/object-rotate-right.png
new file mode 100644
index 0000000..6b6a518
Binary files /dev/null and b/udav/png/object-rotate-right.png differ
diff --git a/udav/png/object-rotate-up.png b/udav/png/object-rotate-up.png
new file mode 100644
index 0000000..08e5d44
Binary files /dev/null and b/udav/png/object-rotate-up.png differ
diff --git a/udav/png/object-ungroup.png b/udav/png/object-ungroup.png
new file mode 100644
index 0000000..e343ff4
Binary files /dev/null and b/udav/png/object-ungroup.png differ
diff --git a/udav/png/office-chart-bar.png b/udav/png/office-chart-bar.png
new file mode 100644
index 0000000..3be1013
Binary files /dev/null and b/udav/png/office-chart-bar.png differ
diff --git a/udav/png/office-chart-line.png b/udav/png/office-chart-line.png
new file mode 100644
index 0000000..501b078
Binary files /dev/null and b/udav/png/office-chart-line.png differ
diff --git a/udav/png/office-chart-scatter.png b/udav/png/office-chart-scatter.png
new file mode 100644
index 0000000..0ecfbf3
Binary files /dev/null and b/udav/png/office-chart-scatter.png differ
diff --git a/udav/png/package-x-generic.png b/udav/png/package-x-generic.png
new file mode 100644
index 0000000..9015426
Binary files /dev/null and b/udav/png/package-x-generic.png differ
diff --git a/udav/png/preferences-system.png b/udav/png/preferences-system.png
new file mode 100644
index 0000000..39587d0
Binary files /dev/null and b/udav/png/preferences-system.png differ
diff --git a/udav/png/process-stop.png b/udav/png/process-stop.png
new file mode 100644
index 0000000..3ff0409
Binary files /dev/null and b/udav/png/process-stop.png differ
diff --git a/udav/png/system-file-manager.png b/udav/png/system-file-manager.png
new file mode 100644
index 0000000..60cade4
Binary files /dev/null and b/udav/png/system-file-manager.png differ
diff --git a/udav/png/tab-close.png b/udav/png/tab-close.png
new file mode 100644
index 0000000..24f36f0
Binary files /dev/null and b/udav/png/tab-close.png differ
diff --git a/udav/png/table.png b/udav/png/table.png
new file mode 100644
index 0000000..bdebe96
Binary files /dev/null and b/udav/png/table.png differ
diff --git a/udav/png/text-csv.png b/udav/png/text-csv.png
new file mode 100644
index 0000000..e7a6cdd
Binary files /dev/null and b/udav/png/text-csv.png differ
diff --git a/udav/png/text-field.png b/udav/png/text-field.png
new file mode 100644
index 0000000..f997cbd
Binary files /dev/null and b/udav/png/text-field.png differ
diff --git a/udav/png/text-plain.png b/udav/png/text-plain.png
new file mode 100644
index 0000000..91b7da5
Binary files /dev/null and b/udav/png/text-plain.png differ
diff --git a/udav/png/text-x-generic.png b/udav/png/text-x-generic.png
new file mode 100644
index 0000000..2d7f2d6
Binary files /dev/null and b/udav/png/text-x-generic.png differ
diff --git a/udav/png/tools-wizard.png b/udav/png/tools-wizard.png
new file mode 100644
index 0000000..403714a
Binary files /dev/null and b/udav/png/tools-wizard.png differ
diff --git a/udav/png/transform-crop.png b/udav/png/transform-crop.png
new file mode 100644
index 0000000..bfd639b
Binary files /dev/null and b/udav/png/transform-crop.png differ
diff --git a/udav/png/transform-move.png b/udav/png/transform-move.png
new file mode 100644
index 0000000..6bba036
Binary files /dev/null and b/udav/png/transform-move.png differ
diff --git a/udav/png/transform-rotate.png b/udav/png/transform-rotate.png
new file mode 100644
index 0000000..8bfa17f
Binary files /dev/null and b/udav/png/transform-rotate.png differ
diff --git a/udav/png/transform-scale.png b/udav/png/transform-scale.png
new file mode 100644
index 0000000..34a1140
Binary files /dev/null and b/udav/png/transform-scale.png differ
diff --git a/udav/png/udav.png b/udav/png/udav.png
new file mode 100644
index 0000000..76ba7d9
Binary files /dev/null and b/udav/png/udav.png differ
diff --git a/udav/png/view-filter.png b/udav/png/view-filter.png
new file mode 100644
index 0000000..9cabc5a
Binary files /dev/null and b/udav/png/view-filter.png differ
diff --git a/udav/png/view-fullscreen.png b/udav/png/view-fullscreen.png
new file mode 100644
index 0000000..75f8a59
Binary files /dev/null and b/udav/png/view-fullscreen.png differ
diff --git a/udav/png/view-grid.png b/udav/png/view-grid.png
new file mode 100644
index 0000000..12e55ad
Binary files /dev/null and b/udav/png/view-grid.png differ
diff --git a/udav/png/view-group.png b/udav/png/view-group.png
new file mode 100644
index 0000000..e9aab73
Binary files /dev/null and b/udav/png/view-group.png differ
diff --git a/udav/png/view-refresh.png b/udav/png/view-refresh.png
new file mode 100644
index 0000000..3fd71d6
Binary files /dev/null and b/udav/png/view-refresh.png differ
diff --git a/udav/png/weather-clear.png b/udav/png/weather-clear.png
new file mode 100644
index 0000000..0704477
Binary files /dev/null and b/udav/png/weather-clear.png differ
diff --git a/udav/png/weather-clear_old.png b/udav/png/weather-clear_old.png
new file mode 100644
index 0000000..7dc15ea
Binary files /dev/null and b/udav/png/weather-clear_old.png differ
diff --git a/udav/png/weather-clouds.png b/udav/png/weather-clouds.png
new file mode 100644
index 0000000..c0bdffa
Binary files /dev/null and b/udav/png/weather-clouds.png differ
diff --git a/udav/png/zoom-draw.png b/udav/png/zoom-draw.png
new file mode 100644
index 0000000..393e752
Binary files /dev/null and b/udav/png/zoom-draw.png differ
diff --git a/udav/png/zoom-in.png b/udav/png/zoom-in.png
new file mode 100644
index 0000000..0e1fc37
Binary files /dev/null and b/udav/png/zoom-in.png differ
diff --git a/udav/png/zoom-original.png b/udav/png/zoom-original.png
new file mode 100644
index 0000000..f7bae85
Binary files /dev/null and b/udav/png/zoom-original.png differ
diff --git a/udav/png/zoom-out.png b/udav/png/zoom-out.png
new file mode 100644
index 0000000..7d4d55c
Binary files /dev/null and b/udav/png/zoom-out.png differ
diff --git a/udav/prop_dlg.cpp b/udav/prop_dlg.cpp
new file mode 100644
index 0000000..b119340
--- /dev/null
+++ b/udav/prop_dlg.cpp
@@ -0,0 +1,293 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <QApplication>
+#include <QPushButton>
+#include <QMessageBox>
+#include <QCheckBox>
+#include <QButtonGroup>
+#include <QLayout>
+#include <QLabel>
+#include <QLineEdit>
+#include <QColorDialog>
+#include <QFontDialog>
+#include <QFileDialog>
+#include <QComboBox>
+#include <QSettings>
+#include <QDir>
+//-----------------------------------------------------------------------------
+#include <mgl2/qmathgl.h>
+#include "prop_dlg.h"
+#include "udav_wnd.h"
+#include "plot_pnl.h"
+#include "text_pnl.h"
+//-----------------------------------------------------------------------------
+extern QColor mglColorScheme[10];
+extern QString defFontFamily;
+extern int defFontSize;
+extern QString pathHelp;
+extern bool mglAutoExecute;
+extern bool mglAutoSave;
+// extern bool mglAutoPure;
+extern bool mglCompleter;
+extern bool editPosBottom;
+extern bool loadInNewWnd;
+extern bool mglHighlight;
+extern bool mglDotsRefr;
+extern bool mglWheelZoom;
+int defWidth, defHeight;
+QString pathFont;
+QString lang[]={"en","ru","es"};
+//-----------------------------------------------------------------------------
+PropDialog::PropDialog(QWidget *parent) : QDialog(parent)
+{
+	setWindowTitle(_("UDAV - Properties"));
+	QHBoxLayout *h;
+	QVBoxLayout *v;
+	QLabel *l;
+	QPushButton *b;
+
+	v = new QVBoxLayout(this);
+	h = new QHBoxLayout();		v->addLayout(h);
+	lbl = new QLabel(_("Current font"), this);	h->addWidget(lbl);
+	lbl->setFont(QFont(defFontFamily, defFontSize));
+	h->addStretch(1);	defFont = QFont(defFontFamily, defFontSize);
+	b = new QPushButton(_("Change font"), this);	h->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(setF()));
+
+	cc[0]=mglColorScheme[0];	cc[1]=mglColorScheme[1];
+	cc[2]=mglColorScheme[2];	cc[3]=mglColorScheme[3];
+	cc[4]=mglColorScheme[4];	cc[5]=mglColorScheme[5];
+	cc[6]=mglColorScheme[6];	cc[7]=mglColorScheme[7];
+	cc[8]=mglColorScheme[8];	cc[9]=mglColorScheme[9];
+	QPixmap pic(16,16);
+	l = new QLabel(_("Setup colors for:"), this);	v->addWidget(l, Qt::AlignHCenter);
+	QGridLayout *g = new QGridLayout();		v->addLayout(g);
+	pic.fill(cc[0]);	cb[0] = new QPushButton(pic, _("Comments"), this);
+	connect(cb[0], SIGNAL(clicked()),this, SLOT(setC0()));
+	g->addWidget(cb[0], 0, 0);
+	pic.fill(cc[1]);	cb[1] = new QPushButton(pic, _("Strings"), this);
+	connect(cb[1], SIGNAL(clicked()),this, SLOT(setC1()));
+	g->addWidget(cb[1], 0, 1);
+	pic.fill(cc[2]);	cb[2] = new QPushButton(pic, _("Keywords"), this);
+	connect(cb[2], SIGNAL(clicked()),this, SLOT(setC2()));
+	g->addWidget(cb[2], 0, 2);
+	pic.fill(cc[3]);	cb[3] = new QPushButton(pic, _("Options"), this);
+	connect(cb[3], SIGNAL(clicked()),this, SLOT(setC3()));
+	g->addWidget(cb[3], 1, 0);
+	pic.fill(cc[4]);	cb[4] = new QPushButton(pic, _("Suffixes"), this);
+	connect(cb[4], SIGNAL(clicked()),this, SLOT(setC4()));
+	g->addWidget(cb[4], 1, 1);
+	pic.fill(cc[5]);	cb[5] = new QPushButton(pic, _("Numbers"), this);
+	connect(cb[5], SIGNAL(clicked()),this, SLOT(setC5()));
+	g->addWidget(cb[5], 1, 2);
+	pic.fill(cc[6]);	cb[6] = new QPushButton(pic, _("AutoKey"), this);
+	connect(cb[6], SIGNAL(clicked()),this, SLOT(setC6()));
+	g->addWidget(cb[6], 2, 0);
+	pic.fill(cc[7]);	cb[7] = new QPushButton(pic, _("FlowKey"), this);
+	connect(cb[7], SIGNAL(clicked()),this, SLOT(setC7()));
+	g->addWidget(cb[7], 2, 1);
+	pic.fill(cc[9]);	cb[9] = new QPushButton(pic, _("CurrLine"), this);
+	connect(cb[9], SIGNAL(clicked()),this, SLOT(setC9()));
+	g->addWidget(cb[9], 2, 2);
+
+	l = new QLabel(_("Path for help files"), this);	v->addWidget(l);
+	h = new QHBoxLayout();		v->addLayout(h);
+	hlp = new QLineEdit(pathHelp, this);	h->addWidget(hlp,1);
+	b = new QPushButton("...", this);		h->addWidget(b,0);
+	connect(b,SIGNAL(clicked()),this,SLOT(getPathH()));
+
+	QStringList paths, files, filter;
+	paths << "." << QDir::homePath() << QDir::rootPath()
+		<< QCoreApplication::applicationDirPath()+"/fonts";
+	filter << "*.vfm";
+#ifndef WIN32
+	paths << "/usr/local/share/mathgl/fonts/" << "/usr/local/mathgl/fonts/";
+#endif
+	QFileInfoList info;
+	for(int i=0;i<paths.count();i++)
+		info << QDir(paths.at(i)).entryInfoList(filter);
+	for(int i=0;i<info.count();i++)
+		if(!info.at(i).fileName().contains('_'))
+			files << info.at(i).absoluteFilePath();
+
+	l = new QLabel(_("Path for user MathGL font files"), this);	v->addWidget(l);
+	h = new QHBoxLayout();		v->addLayout(h);
+	fnt = new QComboBox(this);	h->addWidget(fnt,1);
+	fnt->addItems(files);	fnt->setEditable(true);
+	fnt->lineEdit()->setText(pathFont);
+	b = new QPushButton("...", this);		h->addWidget(b,0);
+	connect(b,SIGNAL(clicked()),this,SLOT(getPathF()));
+
+	h = new QHBoxLayout();		v->addLayout(h);
+	l = new QLabel(_("Language for UDAV"), this);	h->addWidget(l,0);
+	lng = new QComboBox(this);		h->addWidget(lng,1);
+	lng->addItem(_("English"));	lng->addItem(_("Russian"));	lng->addItem(_("Spanish"));
+
+	QSettings settings("udav","UDAV");
+	settings.setPath(QSettings::IniFormat, QSettings::UserScope, "UDAV");
+	settings.beginGroup("/UDAV");
+	QString prev = settings.value("/udavLang", "").toString();
+	if(prev==lang[1])	lng->setCurrentIndex(1);
+	if(prev==lang[2])	lng->setCurrentIndex(2);
+	defWidth = settings.value("/defWidth", 640).toInt();
+	defHeight = settings.value("/defHeight", 480).toInt();
+	settings.endGroup();
+
+	h = new QHBoxLayout();		v->addLayout(h);
+	l = new QLabel(_("Image size"), this);	h->addWidget(l,0);
+	defW = new QLineEdit(QString::number(defWidth),this);	h->addWidget(defW,1);
+	l = new QLabel("x", this);	h->addWidget(l,0);
+	defH = new QLineEdit(QString::number(defHeight),this);	h->addWidget(defH,1);
+
+	run = new QCheckBox(_("Automatically execute script after loading"), this);
+	run->setChecked(mglAutoExecute);	v->addWidget(run);
+	edt = new QCheckBox(_("Place editor at top"), this);
+	edt->setChecked(editPosBottom);	v->addWidget(edt);
+	load = new QCheckBox(_("Load script to new window"), this);
+	load->setChecked(loadInNewWnd);	v->addWidget(load);
+	save = new QCheckBox(_("Automatically save before redrawing (F5)"), this);
+	save->setChecked(mglAutoSave);	v->addWidget(save);
+//	pure = new QCheckBox(_("Disable face drawing (faster) for mouse rotation/shift/zoom."), this);
+//	pure->setChecked(mglAutoPure);	v->addWidget(pure);	pure->setEnabled(false);
+	wheel = new QCheckBox(_("Enable mouse wheel for zooming"), this);
+	wheel->setChecked(mglWheelZoom);	v->addWidget(wheel);
+	cmpl = new QCheckBox(_("Enable keywords completion"), this);
+	cmpl->setChecked(mglCompleter);	v->addWidget(cmpl);
+	high = new QCheckBox(_("Highlight current object(s)"), this);
+	high->setChecked(mglHighlight);	v->addWidget(high);
+	dots = new QCheckBox(_("Use dots plot for preview"), this);
+	dots->setChecked(mglDotsRefr);	v->addWidget(dots);
+
+	h = new QHBoxLayout();		v->addLayout(h);
+	h->addStretch(1);
+	b = new QPushButton(_("Cancel"), this);	h->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(reject()));
+	b = new QPushButton(_("OK"), this);		h->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(applyChanges()));
+	b->setDefault(true);
+}
+//-----------------------------------------------------------------------------
+PropDialog::~PropDialog()	{}
+//-----------------------------------------------------------------------------
+void PropDialog::getPathH()
+{
+	QString str = QFileDialog::getExistingDirectory(this,
+				_("UDAV - Insert filename"), hlp->text());
+	if(!str.isEmpty())	hlp->setText(str+'/');
+}
+//-----------------------------------------------------------------------------
+void PropDialog::getPathF()
+{
+	QString str = QFileDialog::getOpenFileName(this, _("UDAV - Insert filename"),
+					fnt->lineEdit()->text(), _("Font files (*.vfm)"));
+//	if(str.contains(".vfm"))	str = str.left(str.length()-4);
+	if(!str.isEmpty())	fnt->lineEdit()->setText(str);
+}
+//-----------------------------------------------------------------------------
+void PropDialog::setC(int k)
+{
+	if(k<0 || k>9)	return;
+	QColor c = QColorDialog::getColor(cc[k], this);
+	if(c.isValid())
+	{
+		QPixmap p(16,16);	p.fill(c);
+		cb[k]->setIcon(p);	cc[k] = c;
+	}
+}
+//-----------------------------------------------------------------------------
+void PropDialog::setF()
+{
+	bool ok;
+	QFont f = QFontDialog::getFont(&ok, defFont, this);
+	if(ok)	{	defFont = f;	lbl->setFont(f);	}
+}
+//-----------------------------------------------------------------------------
+void PropDialog::applyChanges()
+{
+	// defFont editPosBottom pathFont
+	mglColorScheme[0]=cc[0];	mglColorScheme[1]=cc[1];
+	mglColorScheme[2]=cc[2];	mglColorScheme[3]=cc[3];
+	mglColorScheme[4]=cc[4];	mglColorScheme[5]=cc[5];
+	mglColorScheme[6]=cc[6];	mglColorScheme[7]=cc[7];
+	mglColorScheme[8]=cc[8];	mglColorScheme[9]=cc[9];
+	mglAutoExecute = run->isChecked();
+	editPosBottom = edt->isChecked();
+	pathHelp = hlp->text();	pathFont = fnt->lineEdit()->text();
+	if(pathHelp.isEmpty())	pathHelp=MGL_DOC_DIR;
+	defFontFamily = defFont.family();
+	defFontSize = defFont.pointSize();
+	loadInNewWnd = load->isChecked();
+	mglAutoSave = save->isChecked();
+	mglHighlight = high->isChecked();
+// 	mglAutoPure = pure->isChecked();
+	mglCompleter = cmpl->isChecked();
+	mglDotsRefr = dots->isChecked();
+	mglWheelZoom = wheel->isChecked();
+
+	// apply changes for all windows
+#ifdef WIN32
+	pathFont = pathFont.replace('/','\\');
+#endif
+	bool ok=true;
+	foreach(QWidget *w, QApplication::topLevelWidgets())
+	{
+		if(w->inherits("MainWindow"))
+		{
+			MainWindow *s = (MainWindow *)w;
+			if(ok)	{	s->writeSettings();	ok = false;	}
+			s->edit->setEditorFont();
+			s->graph->setMGLFont(pathFont);
+			s->graph->mgl->enableWheel = mglWheelZoom;
+			s->setEditPos(editPosBottom);
+			s->edit->setCompleter(mglCompleter);
+			s->update();
+		}
+	}
+
+	if(defWidth!=defW->text().toInt() || defHeight!=defH->text().toInt())
+	{
+		defWidth = defW->text().toInt();
+		defHeight = defH->text().toInt();
+		sizeChanged(defWidth, defHeight);
+	}
+
+	QSettings settings("udav","UDAV");
+	settings.setPath(QSettings::IniFormat, QSettings::UserScope, "UDAV");
+	settings.beginGroup("/UDAV");
+	QString prev = settings.value("/udavLang", "").toString();
+	int cur=lng->currentIndex();
+	if(cur>=0 && prev!=lang[cur])
+	{
+		settings.setValue("/udavLang", lang[lng->currentIndex()]);
+#if WIN32
+		const char *loc[]={"C.UTF8",	"ru_RU.cp1251",	"es_ES.utf8",	""};
+#else
+		const char *loc[]={"C.UTF8",	"ru_RU.utf8",	"es_ES.utf8",	""};
+#endif
+		mgl_textdomain(NULL,loc[cur]);
+		QMessageBox::critical(this,_("UDAV - Properties"),_("You need to restart UDAV for applying the changes."));
+	}
+	settings.setValue("/defWidth", defWidth);
+	settings.setValue("/defHeight", defHeight);
+	settings.endGroup();
+
+	accept();	emit propUpdated();
+}
+//-----------------------------------------------------------------------------
diff --git a/udav/prop_dlg.h b/udav/prop_dlg.h
new file mode 100644
index 0000000..193aaef
--- /dev/null
+++ b/udav/prop_dlg.h
@@ -0,0 +1,67 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef PROPDIALOG_H
+#define PROPDIALOG_H
+//-----------------------------------------------------------------------------
+#include <qdialog.h>
+class QLabel;
+class QPushButton;
+class QCheckBox;
+class QLineEdit;
+class QComboBox;
+//-----------------------------------------------------------------------------
+/// Set UDAV general properties
+class PropDialog : public QDialog
+{
+Q_OBJECT
+public:
+	PropDialog(QWidget *parent = 0);
+	~PropDialog();
+signals:
+	void sizeChanged(int w, int h);
+	void propUpdated();
+private slots:
+	void applyChanges();
+	void setC0()	{	setC(0);	}
+	void setC1()	{	setC(1);	}
+	void setC2()	{	setC(2);	}
+	void setC3()	{	setC(3);	}
+	void setC4()	{	setC(4);	}
+	void setC5()	{	setC(5);	}
+	void setC6()	{	setC(6);	}
+	void setC7()	{	setC(7);	}
+	void setC8()	{	setC(8);	}
+	void setC9()	{	setC(9);	}
+	void setF();
+	void getPathH();
+	void getPathF();
+private:
+	void setC(int k);
+	QLabel *lbl;
+	QPushButton *cb[10];
+	QCheckBox *run, *edt, *load, *save, *cmpl, *high, *dots, *wheel;	//, *pure;
+	QLineEdit *hlp, *defW, *defH;
+	QFont defFont;
+	QColor cc[10];
+	QComboBox *lng, *fnt;
+};
+//-----------------------------------------------------------------------------
+#endif
+//-----------------------------------------------------------------------------
diff --git a/udav/qmglsyntax.cpp b/udav/qmglsyntax.cpp
new file mode 100644
index 0000000..8426e9d
--- /dev/null
+++ b/udav/qmglsyntax.cpp
@@ -0,0 +1,121 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <QPushButton>
+#include <QLabel>
+#include <QLayout>
+#include "qmglsyntax.h"
+#include <mgl2/mgl.h>
+mglParse parser;
+int mgl_cmd_cmp(const void *a, const void *b);
+// comment string keyword option suffix number
+QColor mglColorScheme[10] = {QColor(0,127,0), QColor(255,0,0), QColor(0,0,127), QColor(127,0,0), QColor(127,0,0), QColor(0,0,255), QColor(127,0,127), QColor(0,127,127), QColor(0,0,127), QColor(255,255,204)};
+//-----------------------------------------------------------------------------
+QMGLSyntax::QMGLSyntax(QTextEdit *textEdit) : QSyntaxHighlighter(textEdit)	{}
+//-----------------------------------------------------------------------------
+void QMGLSyntax::highlightBlock(const QString &text)
+{
+	int i, j, m = text.length(),s=0;
+	bool arg = false, nl = true;
+	QString num("+-.0123456789:");
+	i=0;
+	setCurrentBlockState(-1);
+	if(previousBlockState()==1)
+	{
+		bool cont=false;
+		j=i;	i++;
+		for(;i<m && text[i]!='\'';i++)
+		{
+			if(text[i]>' ')		cont=false;
+			if(text[i]=='\\')	cont=true;
+		}
+		setFormat(j,i-j+1,mglColorScheme[1]);
+		if(cont && i==m)	setCurrentBlockState(1);
+	}
+	for(;i<m;i++)				// highlight paragraph
+	{
+		if(text[i]=='(')	s++;
+		if(text[i]==')')	s--;
+		if(text[i]==' ' || text[i]=='\t')	continue;
+		else if(text[i]=='#')	// comment
+		{	setFormat(i,m-i,mglColorScheme[0]);	break;	}
+		else if(text[i]=='\'')	// string
+		{
+			bool cont=false;
+			j=i;	i++;
+			for(;i<m && text[i]!='\'';i++)
+			{
+				if(text[i]>' ')		cont=false;
+				if(text[i]=='\\')	cont=true;
+			}
+			setFormat(j,i-j+1,mglColorScheme[1]);
+			if(cont && i==m)	setCurrentBlockState(1);
+		}
+		else if(nl)				// keyword
+		{
+			char *s = new char[m+1];
+			for(j=i;j<text.length() && !text[j].isSpace() && text[j]!=':';j++)
+				s[j-i] = text[j].toLatin1();
+			s[j-i]=0;
+			int type = parser.CmdType(s);
+			if(type)	setFormat(i,j-i+1,type!=7 ? (type==5 ? mglColorScheme[6] : mglColorScheme[2]) : mglColorScheme[7]);
+			delete []s;
+		}
+		else if(text[i]==';')	{	arg = true;	nl = false;	continue;	}
+		else if(text[i]==':' && s==0)	{	nl=true;	continue;	}
+		else if(arg)			// option
+		{
+			const char *o[13]={"xrange","yrange","zrange","cut","meshnum","alpha","light","ambient","diffuse","size","legend","number","value"};
+			unsigned l;
+			for(j=0;j<13;j++)
+			{
+				l = strlen(o[j]);
+				if(text.indexOf(o[j],i)==i && (i+l==long(text.length()) || text[i+l].isSpace()))
+					setFormat(i,l,mglColorScheme[3]);
+			}
+		}
+		else if(text[i]=='.' && i+1<text.length() && text[i+1].isLetter())	// suffix
+		{
+			for(j=i;j<text.length() && !text[j].isSpace();j++){};
+			setFormat(i,j-i+1,mglColorScheme[4]);
+		}
+		else if(num.contains(text[i]))	// number
+			setFormat(i,1,mglColorScheme[5]);
+		else if((text[i]=='e' || text[i]=='E') && i+1<text.length() && num.contains(text[i-1]) && num.contains(text[i+1]) )
+			setFormat(i,1,mglColorScheme[5]);
+		else		// number as its symbolic id
+		{
+			const char *o[6]={"nan","inf","pi","on","off","all"};
+			int l[6] = {3, 3, 2, 2, 3, 3};
+			for(j=0;j<6;j++)
+				if(text.indexOf(o[j],i)==i && (i+l[j]==text.length() || text[i+l[j]].isSpace()))
+					setFormat(i,l[j],mglColorScheme[5]);
+		}
+		arg = nl = false;
+	}
+}
+//-----------------------------------------------------------------------------
+MessSyntax::MessSyntax(QTextEdit *textEdit) : QSyntaxHighlighter(textEdit)	{}
+//-----------------------------------------------------------------------------
+void MessSyntax::highlightBlock(const QString &text)
+{
+	if(text.contains("in line "))
+		setFormat(0, text.length(), QColor(255,0,0));
+}
+//-----------------------------------------------------------------------------
diff --git a/udav/qmglsyntax.h b/udav/qmglsyntax.h
new file mode 100644
index 0000000..325edb3
--- /dev/null
+++ b/udav/qmglsyntax.h
@@ -0,0 +1,45 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef QMGLSYNTAX_H
+#define QMGLSYNTAX_H
+//-----------------------------------------------------------------------------
+#include <QSyntaxHighlighter>
+#include <QDialog>
+#include <QLineEdit>
+#include <QTextEdit>
+//-----------------------------------------------------------------------------
+///Syntax highlighter for MGL script language.
+class QMGLSyntax : public QSyntaxHighlighter
+{
+public:
+	QMGLSyntax(QTextEdit *textEdit);
+	void highlightBlock(const QString &text);
+};
+//-----------------------------------------------------------------------------
+///Syntax highlighter for messages window.
+class MessSyntax : public QSyntaxHighlighter
+{
+public:
+	MessSyntax(QTextEdit *textEdit);
+	void highlightBlock(const QString &text);
+};
+//-----------------------------------------------------------------------------
+#endif
+//-----------------------------------------------------------------------------
diff --git a/udav/setup_dlg.cpp b/udav/setup_dlg.cpp
new file mode 100644
index 0000000..0494c8f
--- /dev/null
+++ b/udav/setup_dlg.cpp
@@ -0,0 +1,300 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <QPushButton>
+#include <QMessageBox>
+#include <QTabWidget>
+#include <QComboBox>
+#include <QCheckBox>
+#include <QLineEdit>
+#include <QSpinBox>
+#include <QLayout>
+#include <QLabel>
+#include <QFile>
+#include <QTextStream>
+//-----------------------------------------------------------------------------
+#include "setup_dlg.h"
+#include "mgl2/define.h"
+#undef sprintf	// fix libintl bug of defining sprintf
+void fillColors(QComboBox *cb);
+//-----------------------------------------------------------------------------
+SetupDialog::SetupDialog(QWidget *parent) : QDialog(parent)
+{
+	setWindowTitle(_("UDAV - Setup plot"));
+	QWidget *p;
+	QGridLayout *g;
+	QLabel *l;
+	QPushButton *b;
+	QTabWidget *tab = new QTabWidget(this);
+	// line style
+	p = new QWidget(this);
+	g = new QGridLayout(p);	g->setAlignment(Qt::AlignTop);
+	l = new QLabel(_("X axis"), p);	g->addWidget(l,0,1);
+	l = new QLabel(_("Y axis"), p);	g->addWidget(l,0,2);
+	l = new QLabel(_("Z axis"), p);	g->addWidget(l,0,3);
+	l = new QLabel(_("C axis"), p);	g->addWidget(l,0,4);
+	l = new QLabel(_("Minimal"), p);	g->addWidget(l,1,0);
+	xmin = new QLineEdit(p);	g->addWidget(xmin,1,1);
+	ymin = new QLineEdit(p);	g->addWidget(ymin,1,2);
+	zmin = new QLineEdit(p);	g->addWidget(zmin,1,3);
+	cmin = new QLineEdit(p);	g->addWidget(cmin,1,4);
+	l = new QLabel(_("Maximal"), p);	g->addWidget(l,2,0);
+	xmax = new QLineEdit(p);	g->addWidget(xmax,2,1);
+	ymax = new QLineEdit(p);	g->addWidget(ymax,2,2);
+	zmax = new QLineEdit(p);	g->addWidget(zmax,2,3);
+	cmax = new QLineEdit(p);	g->addWidget(cmax,2,4);
+	l = new QLabel(_("Origin"), p);	g->addWidget(l,3,0);
+	xorg = new QLineEdit(p);	g->addWidget(xorg,3,1);
+	yorg = new QLineEdit(p);	g->addWidget(yorg,3,2);
+	zorg = new QLineEdit(p);	g->addWidget(zorg,3,3);
+	l = new QLabel(_("Label"), p);	g->addWidget(l,4,0);
+	xlbl = new QLineEdit(p);	g->addWidget(xlbl,4,1);
+	ylbl = new QLineEdit(p);	g->addWidget(ylbl,4,2);
+	zlbl = new QLineEdit(p);	g->addWidget(zlbl,4,3);
+	l = new QLabel(_("at position"), p);	g->addWidget(l,5,0);
+	QStringList lpos;
+	lpos.append(_("at minimum"));	lpos += _("at center");	lpos += _("at maximum");
+	xpos = new QComboBox(p);	g->addWidget(xpos,5,1);	xpos->addItems(lpos);
+	ypos = new QComboBox(p);	g->addWidget(ypos,5,2);	ypos->addItems(lpos);
+	zpos = new QComboBox(p);	g->addWidget(zpos,5,3);	zpos->addItems(lpos);
+	l = new QLabel(_("Ticks"), p);	g->addWidget(l,6,0);
+	xtck = new QLineEdit(p);	g->addWidget(xtck,6,1);
+	ytck = new QLineEdit(p);	g->addWidget(ytck,6,2);
+	ztck = new QLineEdit(p);	g->addWidget(ztck,6,3);
+	l = new QLabel(_("SubTicks"), p);	g->addWidget(l,7,0);
+	xsub = new QLineEdit(p);	g->addWidget(xsub,7,1);
+	ysub = new QLineEdit(p);	g->addWidget(ysub,7,2);
+	zsub = new QLineEdit(p);	g->addWidget(zsub,7,3);
+	l = new QLabel(_("Start"), p);	g->addWidget(l,8,0);
+	xort = new QLineEdit(p);	g->addWidget(xort,8,1);
+	yort = new QLineEdit(p);	g->addWidget(yort,8,2);
+	zort = new QLineEdit(p);	g->addWidget(zort,8,3);
+	l = new QLabel(_("Template"), p);	g->addWidget(l,9,0);
+	xtt = new QLineEdit(p);	g->addWidget(xtt,9,1);
+	ytt = new QLineEdit(p);	g->addWidget(ytt,9,2);
+	ztt = new QLineEdit(p);	g->addWidget(ztt,9,3);
+	ctt = new QLineEdit(p);	g->addWidget(ctt,9,4);
+	l = new QLabel(_("AlphaDef"), p);	g->addWidget(l,10,0);
+	aldef = new QLineEdit(p);	g->addWidget(aldef,11,0);
+	l = new QLabel(_("Ambient"), p);	g->addWidget(l,10,1);
+	amb = new QLineEdit(p);	g->addWidget(amb,11,1);
+	l = new QLabel(_("BaseWidth"), p);	g->addWidget(l,10,2);
+	basew = new QLineEdit(p);	g->addWidget(basew,11,2);
+	l = new QLabel(_("MeshNum"), p);	g->addWidget(l,10,3);
+	mesh = new QLineEdit(p);	g->addWidget(mesh,11,3);
+	l = new QLabel(_("AxialDir"), p);	g->addWidget(l,10,4);
+	axial = new QComboBox(p);	g->addWidget(axial,11,4);
+	axial->addItem("none");	axial->addItem("x");
+	axial->addItem("y");	axial->addItem("z");
+	l = new QLabel(_("Font"), p);	g->addWidget(l,12,0);
+	font = new QLineEdit(p);	g->addWidget(font,13,0);
+	l = new QLabel(_("FontSize"), p);	g->addWidget(l,12,1);
+	fsize = new QLineEdit(p);	g->addWidget(fsize,13,1);
+	alpha = new QCheckBox(_("Alpha"),p);	g->addWidget(alpha, 13,2);
+	light = new QCheckBox(_("Light"),p);	g->addWidget(light, 13,3);
+	rotate = new QCheckBox(_("No text rotation"),p);	g->addWidget(rotate, 13,4);
+	tab->addTab(p, _("General setup"));
+
+	p = new QWidget(this);
+	g = new QGridLayout(p);	g->setAlignment(Qt::AlignTop);
+	l = new QLabel(_("ID"), p);	g->addWidget(l,0,0);
+	l = new QLabel(_("State"), p);	g->addWidget(l,0,1);
+	l = new QLabel(_("X pos"), p);	g->addWidget(l,0,2);
+	l = new QLabel(_("Y pos"), p);	g->addWidget(l,0,3);
+	l = new QLabel(_("Z pos"), p);	g->addWidget(l,0,4);
+	l = new QLabel(_("Color"), p);	g->addWidget(l,0,5);
+	l = new QLabel(_("Brightness"), p);	g->addWidget(l,0,6);
+	char s[3] = "0:";
+	for(int i=0;i<10;i++)
+	{
+		s[0] = char(i+'0');
+		l = new QLabel(s, p);	g->addWidget(l,i+1,0);
+		slight[i] = new QCheckBox(_("on"),p);	g->addWidget(slight[i], i+1, 1);
+		xlight[i] = new QLineEdit(p);	g->addWidget(xlight[i], i+1, 2);
+		ylight[i] = new QLineEdit(p);	g->addWidget(ylight[i], i+1, 3);
+		zlight[i] = new QLineEdit(p);	g->addWidget(zlight[i], i+1, 4);
+		clight[i] = new QComboBox(p);	g->addWidget(clight[i], i+1, 5);
+		fillColors(clight[i]);
+		blight[i] = new QLineEdit(p);	g->addWidget(blight[i], i+1, 6);
+	}
+	tab->addTab(p, _("Light settings"));
+
+	QVBoxLayout *v = new QVBoxLayout(this);	v->addWidget(tab);
+	QHBoxLayout *h = new QHBoxLayout();		v->addLayout(h);
+	l = new QLabel(_("Template name"), this);		h->addWidget(l);
+	fname = new QLineEdit("template.mgl", this);	h->addWidget(fname);
+	h->addStretch(1);
+	b = new QPushButton(_("Save"), this);		h->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(saveTmpl()));
+	b = new QPushButton(_("Cancel"), this);	h->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(reject()));
+	b = new QPushButton(_("To script"), this);	h->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(toScript()));
+	b->setDefault(true);
+}
+//-----------------------------------------------------------------------------
+SetupDialog::~SetupDialog()	{}
+//-----------------------------------------------------------------------------
+void SetupDialog::saveTmpl()
+{
+	if(!convert())	return;
+	QFile f(fname->text());
+	if(!f.open(QIODevice::WriteOnly))
+		QMessageBox::warning(this, _("UDAV - Save template"), _("Could not write to file"), QMessageBox::Ok, 0);
+	else
+	{
+		QTextStream t(&f);	t << res;	f.close();
+		QMessageBox::information(this, _("UDAV - Save template"), _("Template saved"), QMessageBox::Ok);
+		emit putText(QString("#call %1").arg(fname->text()));
+	}
+
+}
+//-----------------------------------------------------------------------------
+void SetupDialog::toScript()
+{
+	if(!convert())	return;
+	emit putText(res);
+	accept();
+}
+//-----------------------------------------------------------------------------
+bool SetupDialog::convert()
+{
+	// TODO: add error (missing values) parsing
+	int i,j;
+	double x1=0,y1=0,z1=0,x2=0,y2=0,z2=0;
+	bool u1,v1,w1,u2,v2,w2;
+
+	QString s, col="wwbgrcmylenuqphkWBGRCMYLENUQPH";
+	res = "";
+	for(i=0;i<10;i++)	// set light sources
+	{
+		if(!slight[i]->isChecked())	continue;
+		if(xlight[i]->text().isEmpty() || ylight[i]->text().isEmpty() || zlight[i]->text().isEmpty())
+		{
+			QMessageBox::information(this, _("UDAV - Setup plot"), _("Light position should be filled. Ignore it."), QMessageBox::Ok);
+			continue;
+		}
+		x1=xlight[i]->text().toDouble();	y1=ylight[i]->text().toDouble();
+		z1=zlight[i]->text().toDouble();	j = clight[i]->currentIndex();
+		if(blight[i]->text().isEmpty())
+			s.sprintf("light %d %g %g %g '%c'\n", i,x1,y1,z1, col[j].toLatin1());
+		else
+			s.sprintf("light %d %g %g %g '%c' %g\n", i,x1,y1,z1, col[j].toLatin1(), blight[i]->text().toDouble());
+		res += s;
+	}
+	u1 = !xmin->text().isEmpty();	if(u1)	x1 = xmin->text().toDouble();
+	u2 = !xmax->text().isEmpty();	if(u2)	x2 = xmax->text().toDouble();
+	v1 = !ymin->text().isEmpty();	if(v1)	y1 = ymin->text().toDouble();
+	v2 = !ymin->text().isEmpty();	if(v2)	y2 = ymax->text().toDouble();
+	w1 = !zmin->text().isEmpty();	if(w1)	z1 = zmin->text().toDouble();
+	w2 = !zmin->text().isEmpty();	if(w2)	z2 = zmax->text().toDouble();
+	if(u1&&v1&&w1&&u2&&v2&&w2)
+	{	s.sprintf("axis %g %g %g %g %g %g\n",x1,y1,z1,x2,y2,z2);	res += s;	}
+	else
+	{
+		if(u1 && u2)	{s.sprintf("xrange %g %g\n",x1,x2);	res += s;}
+		if(v1 && v2)	{s.sprintf("yrange %g %g\n",y1,y2);	res += s;}
+		if(w1 && w2)	{s.sprintf("zrange %g %g\n",z1,z2);	res += s;}
+	}
+	u1 = !cmin->text().isEmpty();	if(u1)	x1 = cmin->text().toDouble();
+	u2 = !cmax->text().isEmpty();	if(u2)	x2 = cmax->text().toDouble();
+	if(u1&&u2)	{s.sprintf("crange %g %g\n",x1,x2);	res += s;}
+
+	u1 = !xmin->text().isEmpty();	if(u1)	x1 = xorg->text().toDouble();
+	v1 = !yorg->text().isEmpty();	if(v1)	y1 = yorg->text().toDouble();
+	w1 = !zorg->text().isEmpty();	if(w1)	z1 = zorg->text().toDouble();
+	if(u1&&v1&&w1)	{s.sprintf("origin %g %g %g\n",x1,y1,z1);	res += s;}
+
+	u1 = !xtck->text().isEmpty();	if(u1)	x1 = xtck->text().toDouble();
+	u2 = !xsub->text().isEmpty();	if(u2)	x2 = xsub->text().toDouble();
+	v1 = !ytck->text().isEmpty();	if(v1)	y1 = ytck->text().toDouble();
+	v2 = !ysub->text().isEmpty();	if(v2)	y2 = ysub->text().toDouble();
+	w1 = !ztck->text().isEmpty();	if(w1)	z1 = ztck->text().toDouble();
+	w2 = !zsub->text().isEmpty();	if(w2)	z2 = zsub->text().toDouble();
+	if(u1 && u2)
+	{
+		if(xort->text().isEmpty())	s.sprintf("xtick %g %g\n",x1,x2);
+		else	s.sprintf("xtick %g %g %g\n",x1,x2,xort->text().toDouble());
+		res += s;
+	}
+	if(v1 && v2)
+	{
+		if(yort->text().isEmpty())	s.sprintf("ytick %g %g\n",y1,y2);
+		else	s.sprintf("ytick %g %g %g\n",y1,y2,yort->text().toDouble());
+		res += s;
+	}
+	if(w1 && w2)
+	{
+		if(zort->text().isEmpty())	s.sprintf("ztick %g %g\n",z1,z2);
+		else	s.sprintf("ztick %g %g %g\n",z1,z2,zort->text().toDouble());
+		res += s;
+	}
+	if(u1 && !u2)	{s.sprintf("xtick %g\n",x1);	res += s;}
+	if(v1 && !v2)	{s.sprintf("ytick %g\n",y1);	res += s;}
+	if(w1 && !w2)	{s.sprintf("ztick %g\n",z1);	res += s;}
+	if(!xtt->text().isEmpty())	res = res + "xtick '" + xtt->text() + "'\n";
+	if(!ytt->text().isEmpty())	res = res + "ytick '" + ytt->text() + "'\n";
+	if(!ztt->text().isEmpty())	res = res + "ztick '" + ztt->text() + "'\n";
+	if(!ctt->text().isEmpty())	res = res + "ctick '" + ctt->text() + "'\n";
+
+	if(!xlbl->text().isEmpty())
+	{
+		s.sprintf("' %d\n",	xpos->currentIndex()-1);
+		res = res + "xlabel '"+ xlbl->text() + s;
+	}
+	if(!ylbl->text().isEmpty())
+	{
+		s.sprintf("' %d\n",	ypos->currentIndex()-1);
+		res = res + "ylabel '"+ ylbl->text() + s;
+	}
+	if(!zlbl->text().isEmpty())
+	{
+		s.sprintf("' %d\n",	zpos->currentIndex()-1);
+		res = res + "zlabel '"+ zlbl->text() + s;
+	}
+
+	if(!aldef->text().isEmpty())
+	{	s.sprintf("alphadef %g\n",aldef->text().toDouble());	res += s;	}
+	if(!amb->text().isEmpty())
+	{	s.sprintf("ambient %g\n",amb->text().toDouble());		res += s;	}
+
+	if(!basew->text().isEmpty())
+	{	s.sprintf("baselinewidth %g\n",basew->text().toDouble());	res += s;	}
+	if(!mesh->text().isEmpty())
+	{	s.sprintf("meshnum %d\n",mesh->text().toInt());	res += s;	}
+	if(axial->currentIndex()>0)
+	{
+		s.sprintf("axialdir '%c'\n",char('x'+axial->currentIndex()-1));
+		res += s;
+	}
+
+	if(!font->text().isEmpty())
+	{
+		res = res + "font '" + font->text();
+		if(!fsize->text().isEmpty())	s.sprintf("' %g\n",fsize->text().toDouble());
+		else	s.sprintf("'\n");
+		res += s;
+	}
+	if(rotate->isChecked())	res = res + "rotatetext off\n";
+
+	if(alpha->isChecked())	res = res + "alpha on\n";
+	if(light->isChecked())	res = res + "light on\n";
+	return true;
+}
+//-----------------------------------------------------------------------------
diff --git a/udav/setup_dlg.h b/udav/setup_dlg.h
new file mode 100644
index 0000000..6e365a4
--- /dev/null
+++ b/udav/setup_dlg.h
@@ -0,0 +1,60 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef SETUPDIALOG_H
+#define SETUPDIALOG_H
+//-----------------------------------------------------------------------------
+#include <qdialog.h>
+#if defined(_MSC_VER)
+#include <mgl2/define.h>
+#endif
+class QLineEdit;
+class QCheckBox;
+class QComboBox;
+//-----------------------------------------------------------------------------
+/// Add setup code to script or save it to file (template)
+class SetupDialog : public QDialog
+{
+Q_OBJECT
+public:
+	SetupDialog(QWidget *parent = 0);
+	~SetupDialog();
+
+signals:
+	void putText(const QString &par);
+
+private slots:
+	void saveTmpl();
+	void toScript();
+
+private:
+	QString res;
+	QLineEdit *xmin, *xmax, *xorg, *xlbl, *xtck, *xsub, *xort, *xtt;
+	QLineEdit *ymin, *ymax, *yorg, *ylbl, *ytck, *ysub, *yort, *ytt;
+	QLineEdit *zmin, *zmax, *zorg, *zlbl, *ztck, *zsub, *zort, *ztt;
+	QLineEdit *cmin, *cmax, *aldef,*amb,  *basew,*mesh, *font, *fsize, *fname, *ctt;
+	QLineEdit *xlight[10], *ylight[10], *zlight[10], *blight[10];
+	QCheckBox *slight[10], *alpha, *light, *rotate;
+	QComboBox *clight[10], *xpos, *ypos, *zpos, *axial;
+	
+	bool convert();
+};
+//-----------------------------------------------------------------------------
+#endif
+//-----------------------------------------------------------------------------
diff --git a/udav/style_dlg.cpp b/udav/style_dlg.cpp
new file mode 100644
index 0000000..1dc52c5
--- /dev/null
+++ b/udav/style_dlg.cpp
@@ -0,0 +1,550 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <QPushButton>
+#include <QMessageBox>
+#include <QComboBox>
+#include <QCheckBox>
+#include <QRadioButton>
+#include <QGroupBox>
+#include <QTabWidget>
+#include <QSlider>
+#include <QSpinBox>
+#include <QLayout>
+#include <QLabel>
+#include <QLineEdit>
+#include <QToolButton>
+#include <mgl2/mgl.h>
+//-----------------------------------------------------------------------------
+#include "style_dlg.h"
+#include "mgl2/define.h"
+void fillColors(QComboBox *cb);
+void fillArrows(QComboBox *cb);
+void fillBArrows(QComboBox *cb);
+void fillDashes(QComboBox *cb);
+void fillMarkers(QComboBox *cb);
+void fillMasks(QComboBox *cb);
+void convertFromGraph(QPixmap &pic, mglGraph *gr, uchar **buf);
+//-----------------------------------------------------------------------------
+StyleDialog::StyleDialog(QWidget *parent) : QDialog(parent)
+{
+	grBuf = 0;
+	setWindowTitle(_("UDAV - Insert style/scheme"));
+	QWidget *p;
+	QHBoxLayout *h;
+	QVBoxLayout *v, *u, *vv;
+	QGridLayout *g;
+	QLabel *l;
+	QPushButton *b;
+	tab = new QTabWidget(this);
+
+	// line style
+	p = new QWidget(this);	v = new QVBoxLayout(p);
+	g = new QGridLayout;	g->setAlignment(Qt::AlignTop);	v->addLayout(g);
+//	g->setColStretch(0, 1);	g->setColStretch(1, 1);	g->setColStretch(2, 1);
+	l = new QLabel(_("Arrow at start"), p);	g->addWidget(l, 0, 0);
+	l = new QLabel(_("Dashing"), p);		g->addWidget(l, 0, 1);
+	l = new QLabel(_("Arrow at end"), p);	g->addWidget(l, 0, 2);
+	a1 = new QComboBox(p);	g->addWidget(a1, 1, 0);	fillArrows(a1);
+	dash = new QComboBox(p);	g->addWidget(dash, 1, 1);	fillDashes(dash);
+	a2 = new QComboBox(p);	g->addWidget(a2, 1, 2);	fillBArrows(a2);
+	l = new QLabel(_("Color"), p);	g->addWidget(l, 2, 0, Qt::AlignRight);
+	cline=new QComboBox(p);	g->addWidget(cline, 2, 1);	fillColors(cline);
+
+	nline = new QSlider(p);		g->addWidget(nline, 2, 2);
+	nline->setRange(1, 9);		nline->setValue(5);
+	nline->setTickPosition(QSlider::TicksBothSides);
+	nline->setTickInterval(1);	nline->setPageStep(2);
+	nline->setOrientation(Qt::Horizontal);
+
+	l = new QLabel(_("Marks"), p);	g->addWidget(l, 3, 0, Qt::AlignRight);
+	mark = new QComboBox(p);	g->addWidget(mark, 3, 1);	fillMarkers(mark);
+	l = new QLabel(_("Line width"), p);	g->addWidget(l, 4, 0, Qt::AlignRight);
+	width = new QSpinBox(p);	g->addWidget(width, 4, 1);
+	width->setRange(1,9);	width->setValue(1);
+
+	v->addStretch(1);
+	l = new QLabel(_("Manual dashing"), p);	v->addWidget(l);
+	h = new QHBoxLayout;	v->addLayout(h);	h->setSpacing(1);
+	for(int i=0;i<16;i++)
+	{
+		dash_bit[i] = new QToolButton(this);
+		dash_bit[i]->setCheckable(true);
+		h->addWidget(dash_bit[i]);
+		connect(dash_bit[i],SIGNAL(toggled(bool)), this, SLOT(updatePic()));
+	}
+	connect(a1,SIGNAL(activated(int)), this, SLOT(updatePic()));
+	connect(a2,SIGNAL(activated(int)), this, SLOT(updatePic()));
+	connect(dash,SIGNAL(activated(int)), this, SLOT(updatePic()));
+	connect(mark,SIGNAL(activated(int)), this, SLOT(updatePic()));
+	connect(cline,SIGNAL(activated(int)), this, SLOT(updatePic()));
+	connect(nline,SIGNAL(valueChanged(int)), this, SLOT(updatePic()));
+	connect(width,SIGNAL(valueChanged(int)), this, SLOT(updatePic()));
+	tab->addTab(p, _("Line style"));
+
+	// color scheme
+	p = new QWidget(this);
+	v = new QVBoxLayout(p);	v->setAlignment(Qt::AlignTop);
+	g = new QGridLayout();	v->addLayout(g);
+//	g->setColStretch(0, 1);			g->setColStretch(1, 1);
+	l = new QLabel(_("Color order"), p);	g->addWidget(l, 0, 0);
+	l = new QLabel(_("Saturation"),p);		g->addWidget(l, 0, 1);
+	for(int i=0;i<7;i++)
+	{
+		cc[i] = new QComboBox(p);	g->addWidget(cc[i], i+1, 0);
+		fillColors(cc[i]);
+		nn[i] = new QSlider(p);		g->addWidget(nn[i], i+1, 1);
+		nn[i]->setRange(1, 9);		nn[i]->setValue(5);
+		nn[i]->setTickPosition(QSlider::TicksBothSides);
+		nn[i]->setTickInterval(1);	nn[i]->setPageStep(2);
+		nn[i]->setOrientation(Qt::Horizontal);
+		connect(cc[i],SIGNAL(activated(int)), this, SLOT(updatePic()));
+		connect(nn[i],SIGNAL(valueChanged(int)), this, SLOT(updatePic()));
+	}
+	swire = new QCheckBox(_("Wire or mesh plot"),p);	v->addWidget(swire);
+	g = new QGridLayout();	v->addLayout(g);
+	l = new QLabel(_("Axial direction"), p);	g->addWidget(l, 0, 0, Qt::AlignRight);
+	l = new QLabel(_("Text on contours"), p);	g->addWidget(l, 1, 0, Qt::AlignRight);
+	l = new QLabel(_("Mask for bitmap coloring"), p);	g->addWidget(l, 2, 0, Qt::AlignRight);
+	l = new QLabel(_("Mask rotation angle"), p);	g->addWidget(l, 3, 0, Qt::AlignRight);
+	l = new QLabel(_("Mask size"), p);	g->addWidget(l, 4, 0, Qt::AlignRight);
+	axial = new QComboBox(p);	g->addWidget(axial, 0, 1);
+	axial->addItem(_("none"));	axial->addItem("x");
+	axial->addItem("y");	axial->addItem("z");
+	ctext = new QComboBox(p);	g->addWidget(ctext, 1, 1);
+	ctext->addItem(_("none"));	ctext->addItem(_("under"));	ctext->addItem(_("above"));
+	mask = new QComboBox(p);	g->addWidget(mask, 2, 1);	fillMasks(mask);
+	angle = new QComboBox(p);	g->addWidget(angle, 3, 1);
+	angle->addItem(_("none"));
+	angle->addItem(QString::fromWCharArray(L"+45\xb0"));
+	angle->addItem(QString::fromWCharArray(L"-45\xb0"));
+	angle->addItem(QString::fromWCharArray(L"90\xb0"));	// \xb0 <-> °
+	msize = new QSlider(p);		g->addWidget(msize, 4, 1);
+	msize->setRange(1, 9);		msize->setValue(1);
+	msize->setTickPosition(QSlider::TicksBothSides);
+	msize->setTickInterval(1);	msize->setPageStep(2);
+	msize->setOrientation(Qt::Horizontal);
+
+	connect(axial,SIGNAL(activated(int)), this, SLOT(updatePic()));
+	connect(ctext,SIGNAL(activated(int)), this, SLOT(updatePic()));
+	connect(swire,SIGNAL(toggled(bool)), this, SLOT(updatePic()));
+	connect(mask,SIGNAL(activated(int)), this, SLOT(updatePic()));
+	connect(angle,SIGNAL(activated(int)), this, SLOT(updatePic()));
+	connect(msize,SIGNAL(valueChanged(int)), this, SLOT(updatePic()));
+	tab->addTab(p, _("Color scheme"));
+
+	// font style
+	p = new QWidget(this);
+	v = new QVBoxLayout(p);	v->setAlignment(Qt::AlignTop);
+	h = new QHBoxLayout();	v->addLayout(h);
+	u = new QVBoxLayout();	h->addLayout(u);
+	bold = new QCheckBox(_("Bold style"), p);	u->addWidget(bold);
+	ital = new QCheckBox(_("Italic style"), p);u->addWidget(ital);
+	wire = new QCheckBox(_("Wire style"), p);	u->addWidget(wire);
+	uline = new QCheckBox(_("Underline"), p);	u->addWidget(uline);
+	oline = new QCheckBox(_("Overline"), p);	u->addWidget(oline);
+	font_sch = new QCheckBox(_("Use color scheme"), p);	u->addWidget(font_sch);
+	u = new QVBoxLayout();	h->addLayout(u);
+	l = new QLabel(_("Text color"), p);		u->addWidget(l);
+	cfont = new QComboBox(p);	fillColors(cfont);	u->addWidget(cfont);
+	u->addSpacing(6);
+	align = new QGroupBox(_("Text align"), p);	u->addWidget(align);
+	vv = new QVBoxLayout(align);		//vv->addSpacing(11);
+	rbL = new QRadioButton(_("left"), align);	vv->addWidget(rbL);
+	rbC = new QRadioButton(_("at center"), align);
+	vv->addWidget(rbC);	rbC->setChecked(true);
+	rbR = new QRadioButton(_("right"), align);	vv->addWidget(rbR);
+	connect(bold,SIGNAL(toggled(bool)), this, SLOT(updatePic()));
+	connect(ital,SIGNAL(toggled(bool)), this, SLOT(updatePic()));
+	connect(wire,SIGNAL(toggled(bool)), this, SLOT(updatePic()));
+	connect(uline,SIGNAL(toggled(bool)), this, SLOT(updatePic()));
+	connect(oline,SIGNAL(toggled(bool)), this, SLOT(updatePic()));
+	connect(font_sch,SIGNAL(toggled(bool)), this, SLOT(updatePic()));
+	connect(cfont,SIGNAL(activated(int)), this, SLOT(updatePic()));
+	connect(rbL,SIGNAL(toggled(bool)), this, SLOT(updatePic()));
+	connect(rbC,SIGNAL(toggled(bool)), this, SLOT(updatePic()));
+	connect(rbR,SIGNAL(toggled(bool)), this, SLOT(updatePic()));
+	tab->addTab(p, _("Font style"));
+	connect(tab,SIGNAL(currentChanged(int)), this, SLOT(updatePic()));
+
+	// hex-mask
+	p = new QWidget(this);
+	g = new QGridLayout(p);	g->setAlignment(Qt::AlignTop);
+	for(int i=0;i<64;i++)
+	{
+		mask_bit[i] = new QToolButton(this);
+		mask_bit[i]->setCheckable(true);
+		g->addWidget(mask_bit[i],7-i/8,i%8);
+		connect(mask_bit[i],SIGNAL(toggled(bool)), this, SLOT(updatePic()));
+	}
+	tab->addTab(p, _("Manual mask"));
+
+	// dialog itself
+	v = new QVBoxLayout(this);	v->addWidget(tab);
+	h = new QHBoxLayout();		v->addLayout(h);
+	l = new QLabel(_("Resulting string"), this);	h->addWidget(l);	h->addStretch(1);
+	pic = new QLabel(this);	pic->setMinimumSize(QSize(128,30));	h->addWidget(pic);
+	res = new QLineEdit(this);	res->setReadOnly(true);	v->addWidget(res);
+
+	h = new QHBoxLayout();	v->addLayout(h);	h->addStretch(1);
+	b = new QPushButton(_("Cancel"), this);	h->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(reject()));
+	b = new QPushButton(_("OK"), this);		h->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(accept()));
+	b->setDefault(true);
+}
+//-----------------------------------------------------------------------------
+StyleDialog::~StyleDialog()	{	if(grBuf)	delete []grBuf;	grBuf = 0;	}
+//-----------------------------------------------------------------------------
+#include "xpm/none.xpm"
+void fillColors(QComboBox *cb)
+{
+//	string id : 	"wbgrcmylenuqphkWBGRCMYLENUQPH"
+	QPixmap pic(16,16);
+	cb->addItem(QPixmap(none_xpm), _("none or default"));
+	pic.fill(QColor(255,255,255));	cb->addItem(pic, _("w - white"));
+	pic.fill(QColor(0,0,255));		cb->addItem(pic, _("b - blue"));
+	pic.fill(QColor(0,255,0));		cb->addItem(pic, _("g - lime"));
+	pic.fill(QColor(255,0,0));		cb->addItem(pic, _("r - red"));
+	pic.fill(QColor(0,255,255));	cb->addItem(pic, _("c - cyan"));
+	pic.fill(QColor(255,0,255));	cb->addItem(pic, _("m - magenta"));
+	pic.fill(QColor(255,255,0));	cb->addItem(pic, _("y - yellow"));
+	pic.fill(QColor(0,255,127));	cb->addItem(pic, _("l - springgreen"));
+	pic.fill(QColor(127,255,0));	cb->addItem(pic, _("e - lawngreen"));
+	pic.fill(QColor(0,127,255));	cb->addItem(pic, _("n - skyblue"));
+	pic.fill(QColor(127,0,255));	cb->addItem(pic, _("u - blueviolet"));
+	pic.fill(QColor(255,127,0));	cb->addItem(pic, _("q - orange"));
+	pic.fill(QColor(255,0,127));	cb->addItem(pic, _("p - deeppink"));
+	pic.fill(QColor(127,127,127));	cb->addItem(pic, _("h - gray"));
+	pic.fill(QColor(0,0,0));		cb->addItem(pic, _("k - black"));
+	pic.fill(QColor(179,179,179));	cb->addItem(pic, _("W - lightgray"));
+	pic.fill(QColor(0,0,127));		cb->addItem(pic, _("B - navy"));
+	pic.fill(QColor(0,127,0));		cb->addItem(pic, _("G - green"));
+	pic.fill(QColor(127,0,0));		cb->addItem(pic, _("R - maroon"));
+	pic.fill(QColor(0,127,127));	cb->addItem(pic, _("C - teal"));
+	pic.fill(QColor(127,0,127));	cb->addItem(pic, _("M - purple"));
+	pic.fill(QColor(127,127,0));	cb->addItem(pic, _("Y - olive"));
+	pic.fill(QColor(0,127,77));		cb->addItem(pic, _("L - seagreen"));
+	pic.fill(QColor(77,127,0));		cb->addItem(pic, _("E - darklawn"));
+	pic.fill(QColor(0,77,127));		cb->addItem(pic, _("N - darkskyblue"));
+	pic.fill(QColor(77,0,127));		cb->addItem(pic, _("U - indigo"));
+	pic.fill(QColor(127,77,0));		cb->addItem(pic, _("Q - brown"));
+	pic.fill(QColor(127,0,77));		cb->addItem(pic, _("P - darkpink"));
+	pic.fill(QColor(77,77,77));		cb->addItem(pic, _("H - darkgray"));
+}
+//-----------------------------------------------------------------------------
+#include "xpm/arrow_n.xpm"
+#include "xpm/arrow_a.xpm"
+#include "xpm/arrow_v.xpm"
+#include "xpm/arrow_i.xpm"
+#include "xpm/arrow_k.xpm"
+#include "xpm/arrow_t.xpm"
+#include "xpm/arrow_s.xpm"
+#include "xpm/arrow_d.xpm"
+#include "xpm/arrow_o.xpm"
+void fillArrows(QComboBox *cb)
+{
+	// "AVIKTSDO"
+	cb->addItem(QPixmap(arrow_n_xpm), _("'_' none"));
+	cb->addItem(QPixmap(arrow_a_xpm), _("'A' arrow"));
+	cb->addItem(QPixmap(arrow_v_xpm), _("'V' back arrow"));
+	cb->addItem(QPixmap(arrow_i_xpm), _("'I' stop"));
+	cb->addItem(QPixmap(arrow_k_xpm), _("'K' size"));
+	cb->addItem(QPixmap(arrow_t_xpm), _("'T' triangle"));
+	cb->addItem(QPixmap(arrow_s_xpm), _("'S' square"));
+	cb->addItem(QPixmap(arrow_d_xpm), _("'D' rhomb"));
+	cb->addItem(QPixmap(arrow_o_xpm), _("'O' circle"));
+}
+//-----------------------------------------------------------------------------
+#include "xpm/barrow_n.xpm"
+#include "xpm/barrow_a.xpm"
+#include "xpm/barrow_v.xpm"
+#include "xpm/barrow_i.xpm"
+#include "xpm/barrow_k.xpm"
+#include "xpm/barrow_t.xpm"
+#include "xpm/barrow_s.xpm"
+#include "xpm/barrow_d.xpm"
+#include "xpm/barrow_o.xpm"
+void fillBArrows(QComboBox *cb)
+{
+	// "AVIKTSDO"
+	cb->addItem(QPixmap(barrow_n_xpm), _("'_' none"));
+	cb->addItem(QPixmap(barrow_a_xpm), _("'A' arrow"));
+	cb->addItem(QPixmap(barrow_v_xpm), _("'V' back arrow"));
+	cb->addItem(QPixmap(barrow_i_xpm), _("'I' stop"));
+	cb->addItem(QPixmap(barrow_k_xpm), _("'K' size"));
+	cb->addItem(QPixmap(barrow_t_xpm), _("'T' triangle"));
+	cb->addItem(QPixmap(barrow_s_xpm), _("'S' square"));
+	cb->addItem(QPixmap(barrow_d_xpm), _("'D' rhomb"));
+	cb->addItem(QPixmap(barrow_o_xpm), _("'O' circle"));
+}
+//-----------------------------------------------------------------------------
+#include "xpm/dash_e.xpm"
+#include "xpm/dash_s.xpm"
+#include "xpm/dash_l.xpm"
+#include "xpm/dash_m.xpm"
+#include "xpm/dash_d.xpm"
+#include "xpm/dash_i.xpm"
+#include "xpm/dash_j.xpm"
+#include "xpm/mark_n.xpm"
+void fillDashes(QComboBox *cb)
+{
+	// "-|;=ji: "
+	cb->addItem(QPixmap(dash_s_xpm), _("'-' solid"));
+	cb->addItem(QPixmap(dash_l_xpm), _("'|' long dash"));
+	cb->addItem(QPixmap(dash_m_xpm), _("';' dash"));
+	cb->addItem(QPixmap(dash_e_xpm), _("'=' small dash"));
+	cb->addItem(QPixmap(dash_j_xpm), _("'j' dash dot"));
+	cb->addItem(QPixmap(dash_i_xpm), _("'i' small dash dot"));
+	cb->addItem(QPixmap(dash_d_xpm), _("':' dots"));
+	cb->addItem(QPixmap(mark_n_xpm), _("' ' none"));
+	cb->addItem(QPixmap(":/png/tools-wizard.png"), _("manual"));
+}
+//-----------------------------------------------------------------------------
+#include "xpm/mask_a.xpm"
+#include "xpm/mask_d.xpm"
+#include "xpm/mask_d_.xpm"
+#include "xpm/mask_e.xpm"
+#include "xpm/mask_i.xpm"
+#include "xpm/mask_j.xpm"
+#include "xpm/mask_l.xpm"
+#include "xpm/mask_m.xpm"
+#include "xpm/mask_o.xpm"
+#include "xpm/mask_o_.xpm"
+#include "xpm/mask_p.xpm"
+#include "xpm/mask_r.xpm"
+#include "xpm/mask_s.xpm"
+#include "xpm/mask_s_.xpm"
+#include "xpm/mask_t.xpm"
+#include "xpm/mask_u.xpm"
+void fillMasks(QComboBox *cb)
+{
+	// "-+=;oOsS~<>jdD*^"
+	cb->addItem(QPixmap(none_xpm), _("none"));
+	cb->addItem(QPixmap(mask_m_xpm), _("'-' lines"));
+	cb->addItem(QPixmap(mask_p_xpm), _("'+' plus"));
+	cb->addItem(QPixmap(mask_e_xpm), _("'=' double lines"));
+	cb->addItem(QPixmap(mask_i_xpm), _("';' dash"));
+	cb->addItem(QPixmap(mask_o_xpm), _("'o' circle"));
+	cb->addItem(QPixmap(mask_O_xpm), _("'O' solid circle"));
+	cb->addItem(QPixmap(mask_s_xpm), _("'s' square"));
+	cb->addItem(QPixmap(mask_S_xpm), _("'S' solid square"));
+	cb->addItem(QPixmap(mask_t_xpm), _("'~' waves"));
+	cb->addItem(QPixmap(mask_l_xpm), _("'<' left sign"));
+	cb->addItem(QPixmap(mask_r_xpm), _("'>' right sign"));
+	cb->addItem(QPixmap(mask_j_xpm), _("'j' dash dot"));
+	cb->addItem(QPixmap(mask_d_xpm), _("'d' rhomb"));
+	cb->addItem(QPixmap(mask_D_xpm), _("'D' solid rhomb"));
+	cb->addItem(QPixmap(mask_a_xpm), _("'*' cross"));
+	cb->addItem(QPixmap(mask_u_xpm), _("'^' hats"));
+	cb->addItem(QPixmap(":/png/tools-wizard.png"), _("manual"));
+}
+//-----------------------------------------------------------------------------
+#include "xpm/mark_.xpm"
+#include "xpm/mark_cf.xpm"
+#include "xpm/mark_x.xpm"
+#include "xpm/mark_p.xpm"
+#include "xpm/mark_pf.xpm"
+#include "xpm/mark_o.xpm"
+#include "xpm/mark_of.xpm"
+#include "xpm/mark_s.xpm"
+#include "xpm/mark_sf.xpm"
+#include "xpm/mark_d.xpm"
+#include "xpm/mark_df.xpm"
+#include "xpm/mark_v.xpm"
+#include "xpm/mark_vf.xpm"
+#include "xpm/mark_t.xpm"
+#include "xpm/mark_tf.xpm"
+#include "xpm/mark_l.xpm"
+#include "xpm/mark_lf.xpm"
+#include "xpm/mark_r.xpm"
+#include "xpm/mark_rf.xpm"
+#include "xpm/mark_y.xpm"
+#include "xpm/mark_a.xpm"
+void fillMarkers(QComboBox *cb)
+{
+	// ".+x*sdv^<>o.*+xsdv^<>o" : nf = 10
+	cb->addItem(QPixmap(mark_n_xpm), _("none"));
+	cb->addItem(QPixmap(mark__xpm), _("'.' dot"));
+	cb->addItem(QPixmap(mark_p_xpm), _("'+' plus"));
+	cb->addItem(QPixmap(mark_x_xpm), _("'x' skew cross"));
+	cb->addItem(QPixmap(mark_a_xpm), _("'*' star"));
+	cb->addItem(QPixmap(mark_s_xpm), _("'s' square"));
+	cb->addItem(QPixmap(mark_d_xpm), _("'d' rhomb"));
+	cb->addItem(QPixmap(mark_v_xpm), _("'v' triangle down"));
+	cb->addItem(QPixmap(mark_t_xpm), _("'^' triangle up"));
+	cb->addItem(QPixmap(mark_l_xpm), _("'<' triangle left"));
+	cb->addItem(QPixmap(mark_r_xpm), _("'>' triangle right"));
+	cb->addItem(QPixmap(mark_o_xpm), _("'o' circle"));
+
+	cb->addItem(QPixmap(mark_cf_xpm), _("'#.' circled dot"));
+	cb->addItem(QPixmap(mark_y_xpm),  _("'#*' Y-sign"));
+	cb->addItem(QPixmap(mark_pf_xpm), _("'#+' squared plus"));
+	cb->addItem(QPixmap(none_xpm),	  _("'#x' squared cross"));
+
+	cb->addItem(QPixmap(mark_sf_xpm), _("'#s' solid square"));
+	cb->addItem(QPixmap(mark_df_xpm), _("'#d' solid rhomb"));
+	cb->addItem(QPixmap(mark_vf_xpm), _("'#v' solid triangle down"));
+	cb->addItem(QPixmap(mark_tf_xpm), _("'#^' solid triangle up"));
+	cb->addItem(QPixmap(mark_lf_xpm), _("'#<' solid triangle left"));
+	cb->addItem(QPixmap(mark_rf_xpm), _("'#>' solid triangle right"));
+	cb->addItem(QPixmap(mark_of_xpm), _("'#o' solid circle"));
+}
+//-----------------------------------------------------------------------------
+void StyleDialog::updatePic()
+{
+	static mglGraph gr(0,128,30);
+	static bool f = true;
+	mglData x(3), y(3), a(32,2);
+	x.Fill(-1,1);	a.Fill(-1,1);
+	if(!f)	gr.Clf();
+	if(f)
+	{
+		gr.SubPlot(1,1,0,"");
+		gr.SetMarkSize(15);
+		gr.SetArrowSize(20);
+		f = false;
+	}
+	result = "";
+	int i,j;
+	QString col="wbgrcmylenuqphkWBGRCMYLENUQPH", mrk=".+x*sdv^<>o.*+xsdv^<>o", dsh="|;=ji: ", arw="AVIKTSDO", s;
+	QString msk="-+=;oOsS~<>jdD*^", dir="/\\I";
+	switch(tab->currentIndex())
+	{
+	case 0:	// line style
+		i = a2->currentIndex();		if(i>0)	result += arw[i-1];
+		j = a1->currentIndex();		if(j>0)
+		{
+			if(i==0)	result += '_';
+			result += arw[j-1];
+		}
+		i = dash->currentIndex();
+		if(i>0 && i<8)	result += dsh[i-1];
+		else if(i==8)	// manual
+		{
+			int d=0;
+			for(int i=0;i<16;i++)	if(dash_bit[i]->isChecked())	d += 1<<i;
+			result += "{d"+QString::number(d,16)+"}";
+		}
+		i = mark->currentIndex();	if(i>0)	result += mrk[i-1];
+		if(i>11)	result += '#';
+		i = cline->currentIndex();
+		if(i>0)
+		{
+			j = nline->value();
+			if(j!=5)	result += "{"+col[i-1]+char('0'+j)+"}";
+			else		result += col[i-1];
+		}
+		i = width->value();		if(i>1)	result += char('0'+i);
+		gr.Plot(x,y,result.toLocal8Bit().constData());
+		break;
+	case 1: // color sceheme
+	case 3: // manual mask
+		for(j=0;j<7;j++)
+		{
+			i = cc[j]->currentIndex();
+			if(i<1)	break;
+			QCharRef c = col[i-1];
+			i = nn[j]->value();
+			if(i!=5)	result += "{"+c+char('0'+i)+"}";
+			else		result += c;
+		}
+		if(swire->isChecked())	result += '#';
+		i = ctext->currentIndex();
+		if(i==1)	result += 't';
+		if(i==2)	result += 'T';
+		i = mask->currentIndex();
+		if(i>0 && i<17)
+		{
+			result += msk[i-1];
+			i = angle->currentIndex();
+			if(i>0)	result += dir[i-1];
+			i = msize->value();
+			if(i>1)	result += char('0'+i);
+		}
+		else if(i==17)
+		{
+			uint64_t t=0;
+			for(int j=0;j<64;j++)	if(mask_bit[j]->isChecked())	t += uint64_t(1)<<j;
+			result += "{s"+QString::number(t,16)+"}";
+			// TODO get hex-mask
+			i = angle->currentIndex();
+			if(i>0)	result += dir[i-1];
+			i = msize->value();
+			if(i>1)	result += char('0'+i);
+		}
+
+
+		i = axial->currentIndex();
+		if(i>0)	result = result+':'+char('x'+i-1);
+		gr.Surf(a,result.toLocal8Bit().constData());
+		break;
+	case 2: // text style
+		if(font_sch->isChecked())	for(j=0;j<7;j++)
+		{
+			i = cc[j]->currentIndex();
+			if(i<1)	break;
+			QCharRef c = col[i-1];
+			i = nn[j]->value();
+			if(i!=5)	result += "{"+c+char('0'+i)+"}";
+			else		result += c;
+		}
+		else
+		{
+			i = cfont->currentIndex();
+			if(i>1)	result += col[i-1];
+		}
+		result += ':';
+		if(bold->isChecked())	result += 'b';
+		if(ital->isChecked())	result += 'i';
+		if(wire->isChecked())	result += 'w';
+		if(uline->isChecked())	result += 'u';
+		if(oline->isChecked())	result += 'o';
+		if(rbL->isChecked())	result += 'L';
+		if(rbC->isChecked())	result += 'C';
+		if(rbR->isChecked())	result += 'R';
+		gr.Puts(mglPoint(0,-0.5),"Font test",result.toLocal8Bit().constData(),-10);
+		break;
+	}
+	result = "'" + result + "'";
+	res->setText(result);
+	QPixmap p;
+	convertFromGraph(p, &gr, &grBuf);
+	pic->setPixmap(p);
+}
+//-----------------------------------------------------------------------------
+void convertFromGraph(QPixmap &pic, mglGraph *gr, uchar **buf)
+{
+	long w=gr->GetWidth(), h=gr->GetHeight();
+	if(*buf)	delete [](*buf);
+	*buf = new uchar[4*w*h];
+	gr->GetBGRN(*buf,4*w*h);
+	QImage img(*buf, w, h, QImage::Format_RGB32);
+	pic = QPixmap::fromImage(img);
+}
+//-----------------------------------------------------------------------------
+void StyleDialog::showFontPage()
+{	tab->setCurrentIndex(2);	}
+//-----------------------------------------------------------------------------
+void StyleDialog::showPenPage()
+{	tab->setCurrentIndex(0);	}
+//-----------------------------------------------------------------------------
+void StyleDialog::showSchPage()
+{	tab->setCurrentIndex(1);	}
+//-----------------------------------------------------------------------------
diff --git a/udav/style_dlg.h b/udav/style_dlg.h
new file mode 100644
index 0000000..348632c
--- /dev/null
+++ b/udav/style_dlg.h
@@ -0,0 +1,73 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef STYLEDIALOG_H
+#define STYLEDIALOG_H
+//-----------------------------------------------------------------------------
+#include <qdialog.h>
+class QComboBox;
+class QSlider;
+class QSpinBox;
+class QGroupBox;
+class QTabWidget;
+class QCheckBox;
+class QLabel;
+class QLineEdit;
+class QRadioButton;
+class QToolButton;
+//-----------------------------------------------------------------------------
+/// Selecting styles of command (like line style, color scheme, font style, axis style)
+class StyleDialog : public QDialog
+{
+Q_OBJECT
+public:
+	QString getStyle()	{	return result;	};
+	StyleDialog(QWidget *parent = 0);
+	~StyleDialog();
+	
+	void showFontPage();
+	void showPenPage();
+	void showSchPage();
+private slots:
+	void updatePic();
+private:
+	QString result;
+	QComboBox *cc[8], *cline, *cfont;
+	QSlider *nn[8], *nline;
+	QComboBox *axial, *ctext, *a1, *a2, *dash, *mark;
+	QCheckBox *swire, *upd;
+	QCheckBox *ital, *bold, *wire, *uline, *oline;
+	QSpinBox *width;
+	QGroupBox *align;
+	QTabWidget *tab;
+	QLabel *box, *pic;
+	QLineEdit *res;
+	QRadioButton *rbL, *rbC, *rbR;
+	uchar *grBuf;
+	QCheckBox *font_sch;
+	QComboBox *mask;
+	QComboBox *angle;
+	QSlider *msize;
+
+	QToolButton *dash_bit[16];	// 8 buttons for dashing
+	QToolButton *mask_bit[64];	// 8*8 buttons for mask
+};
+//-----------------------------------------------------------------------------
+#endif
+//-----------------------------------------------------------------------------
diff --git a/udav/subplot_dlg.cpp b/udav/subplot_dlg.cpp
new file mode 100644
index 0000000..dd164ac
--- /dev/null
+++ b/udav/subplot_dlg.cpp
@@ -0,0 +1,358 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <QPushButton>
+#include <QCheckBox>
+#include <QRadioButton>
+#include <QSpinBox>
+#include <QLayout>
+#include <QLabel>
+#include <QLineEdit>
+#include <mgl2/qmathgl.h>
+#include "subplot_dlg.h"
+#include "style_dlg.h"
+#undef sprintf
+//-----------------------------------------------------------------------------
+void convertFromGraph(QPixmap &pic, mglGraph *gr, uchar **buf);
+//-----------------------------------------------------------------------------
+SubplotDialog::SubplotDialog(QWidget *parent) : QDialog(parent)
+{
+	grBuf = 0;
+	setWindowTitle(_("UDAV - Setup inplot"));
+	QLabel *l;
+	QPushButton *b;
+	QVBoxLayout *v = new QVBoxLayout(this), *u;
+	QGridLayout *g = new QGridLayout;	v->addLayout(g);
+	g->setColumnStretch(2, 1);	g->setColumnStretch(4, 1);
+	g->setColumnStretch(6, 1);	g->setColumnStretch(8, 1);
+	g->setColumnStretch(10, 1);	g->setAlignment(Qt::AlignTop);
+	// SubPlot section
+	cb = new QRadioButton("SubPlot",this);	g->addWidget(cb,0,0);
+	cb->setToolTip(_("Set drawing area as cell of matrix nx*ny."));
+	connect(cb,SIGNAL(toggled(bool)),this,SLOT(updatePic()));
+	l = new QLabel("nx",this);	g->addWidget(l,0,1);
+	bn = new QSpinBox(this);	g->addWidget(bn,0,2);
+	bn->setMinimum(1);	bn->setToolTip(_("Horizontal size"));
+	connect(bn,SIGNAL(valueChanged(QString)),this,SLOT(updatePic()));
+	l = new QLabel("ny",this);	g->addWidget(l,0,3);
+	bm = new QSpinBox(this);	g->addWidget(bm,0,4);
+	bm->setMinimum(1);	bm->setToolTip(_("Vertical size"));
+	connect(bm,SIGNAL(valueChanged(QString)),this,SLOT(updatePic()));
+	l = new QLabel("ind",this);	g->addWidget(l,0,5);
+	bk = new QSpinBox(this);	g->addWidget(bk,0,6);
+	bk->setMinimum(0);	bk->setToolTip(_("Cell index"));
+	connect(bk,SIGNAL(valueChanged(QString)),this,SLOT(updatePic()));
+
+	// MultiPlot section
+	cm = new QRadioButton("MultiPlot",this);	g->addWidget(cm,1,0);
+	cm->setToolTip(_("Set drawing area as cells of matrix nx*ny."));
+	connect(cm,SIGNAL(toggled(bool)),this,SLOT(updatePic()));
+	l = new QLabel("nx",this);	g->addWidget(l,1,1);
+	mn = new QSpinBox(this);	g->addWidget(mn,1,2);
+	mn->setMinimum(1);	mn->setToolTip(_("Horizontal size"));
+	connect(mn,SIGNAL(valueChanged(QString)),this,SLOT(updatePic()));
+	l = new QLabel("ny",this);	g->addWidget(l,1,3);
+	mm = new QSpinBox(this);	g->addWidget(mm,1,4);
+	mm->setMinimum(1);	mm->setToolTip(_("Vertical size"));
+	connect(mm,SIGNAL(valueChanged(QString)),this,SLOT(updatePic()));
+	l = new QLabel("ind",this);	g->addWidget(l,1,5);
+	mk = new QSpinBox(this);	g->addWidget(mk,1,6);
+	mk->setMinimum(0);	mk->setToolTip(_("Starting cell index"));
+	connect(mk,SIGNAL(valueChanged(QString)),this,SLOT(updatePic()));
+	l = new QLabel("dx",this);	g->addWidget(l,1,7);
+	mx = new QSpinBox(this);	g->addWidget(mx,1,8);
+	mx->setMinimum(1);	mx->setToolTip(_("Width of selected cells"));
+	connect(mx,SIGNAL(valueChanged(QString)),this,SLOT(updatePic()));
+	l = new QLabel("dy",this);	g->addWidget(l,1,9);
+	my = new QSpinBox(this);	g->addWidget(my,1,10);
+	my->setMinimum(1);	my->setToolTip(_("Height of selected cells"));
+	connect(my,SIGNAL(valueChanged(QString)),this,SLOT(updatePic()));
+
+	// GridPlot section
+	cg = new QRadioButton("GridPlot",this);	g->addWidget(cg,2,0);
+	cg->setToolTip(_("Set drawing area as cell of matrix nx*ny."));
+	connect(cg,SIGNAL(toggled(bool)),this,SLOT(updatePic()));
+	l = new QLabel("nx",this);	g->addWidget(l,2,1);
+	gn = new QSpinBox(this);	g->addWidget(gn,2,2);
+	gn->setMinimum(1);	gn->setToolTip(_("Horizontal size"));
+	connect(gn,SIGNAL(valueChanged(QString)),this,SLOT(updatePic()));
+	l = new QLabel("ny",this);	g->addWidget(l,2,3);
+	gm = new QSpinBox(this);	g->addWidget(gm,2,4);
+	gm->setMinimum(1);	gm->setToolTip(_("Vertical size"));
+	connect(gm,SIGNAL(valueChanged(QString)),this,SLOT(updatePic()));
+	l = new QLabel("ind",this);	g->addWidget(l,2,5);
+	gk = new QSpinBox(this);	g->addWidget(gk,2,6);
+	gk->setMinimum(0);	gk->setToolTip(_("Cell index"));
+	connect(gk,SIGNAL(valueChanged(QString)),this,SLOT(updatePic()));
+	l = new QLabel("d",this);	g->addWidget(l,2,7);
+	gd = new QLineEdit(this);	g->addWidget(gd,2,8);
+	gd->setToolTip(_("Distance between cells"));
+	connect(gd,SIGNAL(textChanged(QString)),this,SLOT(updatePic()));
+
+	// ColumnPlot section
+	cc = new QRadioButton("ColumnPlot",this);	g->addWidget(cc,3,0);
+	cc->setToolTip(_("Set drawing area as cells of column."));
+	connect(cc,SIGNAL(toggled(bool)),this,SLOT(updatePic()));
+	l = new QLabel("num",this);	g->addWidget(l,3,1);
+	cn = new QSpinBox(this);	g->addWidget(cn,3,2);
+	cn->setMinimum(1);	cn->setToolTip(_("Size of column"));
+	connect(cn,SIGNAL(valueChanged(QString)),this,SLOT(updatePic()));
+	l = new QLabel("ind",this);	g->addWidget(l,3,5);
+	ck = new QSpinBox(this);	g->addWidget(ck,3,6);
+	ck->setMinimum(0);	ck->setToolTip(_("Cell index"));
+	connect(ck,SIGNAL(valueChanged(QString)),this,SLOT(updatePic()));
+	l = new QLabel("d",this);	g->addWidget(l,3,7);
+	cd = new QLineEdit(this);	g->addWidget(cd,3,8);
+	cd->setToolTip(_("Distance between cells"));
+	connect(cd,SIGNAL(textChanged(QString)),this,SLOT(updatePic()));
+
+	// StickPlot section
+	cs = new QRadioButton("StickPlot",this);	g->addWidget(cs,4,0);
+	cs->setToolTip(_("Set drawing area as cells of stick."));
+	connect(cc,SIGNAL(toggled(bool)),this,SLOT(updatePic()));
+	l = new QLabel("num",this);	g->addWidget(l,4,1);
+	sn = new QSpinBox(this);	g->addWidget(sn,4,2);
+	sn->setMinimum(1);	sn->setToolTip(_("Size of stick"));
+	connect(sn,SIGNAL(valueChanged(QString)),this,SLOT(updatePic()));
+	l = new QLabel("ind",this);	g->addWidget(l,4,5);
+	sk = new QSpinBox(this);	g->addWidget(sk,4,6);
+	sk->setMinimum(0);	sk->setToolTip(_("Cell index"));
+	connect(sk,SIGNAL(valueChanged(QString)),this,SLOT(updatePic()));
+
+	// InPlot section
+	ci = new QRadioButton("InPlot",this);	g->addWidget(ci,5,0);
+	ci->setToolTip(_("Set drawing area as cells of matrix nx*ny."));
+	connect(ci,SIGNAL(toggled(bool)),this,SLOT(updatePic()));
+	l = new QLabel("x1",this);	g->addWidget(l,5,1);
+	x1 = new QLineEdit(this);	g->addWidget(x1,5,2);
+	x1->setText("0");	x1->setToolTip(_("Left bottom edge"));
+	connect(x1,SIGNAL(textChanged(QString)),this,SLOT(updatePic()));
+	l = new QLabel("x2",this);	g->addWidget(l,5,3);
+	x2 = new QLineEdit(this);	g->addWidget(x2,5,4);
+	x2->setText("1");	x2->setToolTip(_("Right bottom edge"));
+	connect(x2,SIGNAL(textChanged(QString)),this,SLOT(updatePic()));
+	l = new QLabel("y1",this);	g->addWidget(l,5,5);
+	y1 = new QLineEdit(this);	g->addWidget(y1,5,6);
+	y1->setText("0");	y1->setToolTip(_("Left top edge"));
+	connect(y1,SIGNAL(textChanged(QString)),this,SLOT(updatePic()));
+	l = new QLabel("y2",this);	g->addWidget(l,5,7);
+	y2 = new QLineEdit(this);	g->addWidget(y2,5,8);
+	y2->setText("1");	y2->setToolTip(_("Right top edge"));
+	connect(y2,SIGNAL(textChanged(QString)),this,SLOT(updatePic()));
+
+	QHBoxLayout *h, *H;
+	h = new QHBoxLayout;	v->addLayout(h);
+	u = new QVBoxLayout;	h->addLayout(u);
+
+	H = new QHBoxLayout;	u->addLayout(H);
+	l = new QLabel(_("Rotate on"),this);	H->addWidget(l);
+	l = new QLabel(QString::fromWCharArray(L"\u03b8"),this);	H->addWidget(l);
+	tet = new QSpinBox(this);	H->addWidget(tet,1);	tet->setValue(0);	tet->setSingleStep(5);
+	tet->setToolTip(_("Angle around x axis (in degrees)"));
+	connect(tet,SIGNAL(valueChanged(QString)),this,SLOT(updatePic()));
+	l = new QLabel(QString::fromWCharArray(L"\u03c6"),this);	H->addWidget(l);
+	phi = new QSpinBox(this);	H->addWidget(phi,1);	phi->setValue(0);	phi->setSingleStep(5);
+	phi->setToolTip(_("Angle around z axis (in degrees)"));
+	connect(phi,SIGNAL(valueChanged(QString)),this,SLOT(updatePic()));
+
+	H = new QHBoxLayout;	u->addLayout(H);
+	l = new QLabel(_("Aspect"),this);	H->addWidget(l);
+	l = new QLabel(_("X/Z"),this);	H->addWidget(l);
+	axz = new QLineEdit(this);	H->addWidget(axz);	axz->setText("1");
+	axz->setToolTip(_("Aspect ratio of x-scale to z-scale"));
+	connect(axz,SIGNAL(textChanged(QString)),this,SLOT(updatePic()));
+	l = new QLabel(_("Y/Z"),this);	H->addWidget(l);
+	ayz = new QLineEdit(this);	H->addWidget(ayz);	ayz->setText("1");
+	ayz->setToolTip(_("Aspect ratio of y-scale to z-scale"));
+	connect(ayz,SIGNAL(textChanged(QString)),this,SLOT(updatePic()));
+
+	H = new QHBoxLayout;	u->addLayout(H);
+	l = new QLabel(_("Reserve at"),this);	H->addWidget(l);
+	rl = new QCheckBox(_("left"),this);	H->addWidget(rl);	rl->setChecked(true);
+	rl->setToolTip(_("Reserve space for labels at left side (style '<')"));
+	rb = new QCheckBox(_("bottom"),this);	H->addWidget(rb);	rb->setChecked(true);
+	rb->setToolTip(_("Reserve space for labels at bottom side (style '_')"));
+	rt = new QCheckBox(_("top"),this);		H->addWidget(rt);	rt->setChecked(true);
+	rt->setToolTip(_("Reserve space for labels at top side (style '^')"));
+	rr = new QCheckBox(_("right"),this);	H->addWidget(rr);	rr->setChecked(true);
+	rr->setToolTip(_("Reserve space for labels at right side (style '>')"));
+	rw = new QCheckBox(_("Whole area"),this);	H->addWidget(rw);
+	rw->setToolTip(_("Set to use whole area (style '#')"));
+	connect(rl,SIGNAL(toggled(bool)),this,SLOT(updatePic()));
+	connect(rr,SIGNAL(toggled(bool)),this,SLOT(updatePic()));
+	connect(rt,SIGNAL(toggled(bool)),this,SLOT(updatePic()));
+	connect(rb,SIGNAL(toggled(bool)),this,SLOT(updatePic()));
+	connect(rw,SIGNAL(toggled(bool)),this,SLOT(updatePic()));
+
+	H = new QHBoxLayout;	u->addLayout(H);
+	l = new QLabel(_("Title"),this);	H->addWidget(l);
+	title = new QLineEdit(this);		H->addWidget(title);
+	title->setToolTip(_("Title for plot. Can be used in SubPlot or MultiPlot only."));
+	connect(title,SIGNAL(textChanged(QString)),this,SLOT(updatePic()));
+	b = new QPushButton(_("Style"),this);	H->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(titleStl()));
+
+	H = new QHBoxLayout;	u->addLayout(H);
+	l = new QLabel(_("Result"),this);	H->addWidget(l);
+	res = new QLineEdit(this);		H->addWidget(res);	res->setReadOnly(true);
+	res->setToolTip(_("Resulting string"));
+
+	pic = new QLabel(this);	h->addWidget(pic,1);
+
+	h = new QHBoxLayout;	v->addLayout(h);	h->addStretch(1);
+	b = new QPushButton(_("Cancel"),this);	h->addWidget(b);
+	connect(b, SIGNAL(clicked()),this, SLOT(reject()));
+	b = new QPushButton(_("OK"), this);	h->addWidget(b);	b->setDefault(true);
+	connect(b, SIGNAL(clicked()),this, SLOT(finish()));
+	
+	stlDialog = new StyleDialog(this);
+}
+//-----------------------------------------------------------------------------
+SubplotDialog::~SubplotDialog()	{	if(grBuf)	delete []grBuf;	}
+//-----------------------------------------------------------------------------
+void SubplotDialog::finish()	{	accept();	emit result(cmd);	}
+//-----------------------------------------------------------------------------
+void SubplotDialog::updatePic()
+{
+	static mglGraph gr;	gr.SetSize(pic->width(),pic->height());
+	mglParse par;
+	wchar_t *wcmd;
+
+	setlocale(LC_NUMERIC, "C");
+	QString stl="'";	// style for subplot
+	if(rb->isChecked())	stl+='_';
+	if(rl->isChecked())	stl+='<';
+	if(rr->isChecked())	stl+='>';
+	if(rt->isChecked())	stl+='^';
+	if(rw->isChecked())	stl+='#';
+	stl += '\'';
+	if(stl=="'_<>^'")	stl="";
+	int Tet = tet->value(), Phi = phi->value();
+	int Ax = 1, Ay = 1;
+	if(!axz->text().isEmpty())	Ax = axz->text().toDouble();
+	if(!ayz->text().isEmpty())	Ay = ayz->text().toDouble();
+
+	if(cb->isChecked())	// subplot
+	{
+		int n=bn->value(), m=bm->value(), k=bk->value();
+		for(int i=0;i<n*m;i++)	if(i!=k)	{	gr.SubPlot(n,m,i);	gr.Box("h");	}
+		cmd = "subplot "+QString::number(n)+" "+QString::number(m)+" "+QString::number(k)+" "+stl;
+		if(!title->text().isEmpty())
+		{	cmd += ":title '"+title->text()+"'";	if(!fmt.isEmpty())	cmd += fmt;	}
+		if(Tet || Phi)	cmd += ":rotate "+QString::number(Tet)+" "+QString::number(Phi);
+		if(Ax!=1 || Ay!=1)	cmd += ":aspect "+QString::number(Ax)+" "+QString::number(Ay);
+		wcmd = new wchar_t[cmd.size()+1];
+		cmd.toWCharArray(wcmd);
+		wcmd[cmd.size()] = 0;
+		par.Execute(&gr, wcmd);	gr.Box();
+		delete[] wcmd;
+		res->setText(cmd);
+	}
+	else if(cm->isChecked())	// multiplot
+	{
+		int n=mn->value(), m=mm->value(), k=mk->value(), dx=mx->value(), dy=my->value();
+		for(int i=0;i<n*m;i++)	if(i!=k)	{	gr.SubPlot(n,m,i);	gr.Box("h");	}
+		cmd = "multiplot "+QString::number(n)+" "+QString::number(m)+" "+QString::number(k)+" "+QString::number(dx)+" "+QString::number(dy)+" "+stl;
+		if(!title->text().isEmpty())
+		{	cmd += ":title '"+title->text()+"'";	if(!fmt.isEmpty())	cmd += fmt;	}
+		if(Tet || Phi)	cmd += ":rotate "+QString::number(Tet)+" "+QString::number(Phi);
+		if(Ax!=1 || Ay!=1)	cmd += ":aspect "+QString::number(Ax)+" "+QString::number(Ay);
+		wcmd = new wchar_t[cmd.size() + 1];
+		cmd.toWCharArray(wcmd);
+		wcmd[cmd.size()] = 0;
+		par.Execute(&gr, wcmd);	gr.Box();
+		delete[] wcmd;
+		res->setText(cmd);
+	}
+	else if(cg->isChecked())	// gridplot
+	{
+		int n=gn->value(), m=gm->value(), k=gk->value();
+		double d = gd->text().isEmpty()?0:gd->text().toDouble();
+		for(int i=0;i<n*m;i++)	if(i!=k)	{	gr.GridPlot(n,m,i,d);	gr.Box("h");	}
+		cmd = "gridplot "+QString::number(n)+" "+QString::number(m)+" "+QString::number(k)+" "+QString::number(d);
+		if(Ax!=1 || Ay!=1)	cmd += ":aspect "+QString::number(Ax)+" "+QString::number(Ay);
+		wcmd = new wchar_t[cmd.size() + 1];
+		cmd.toWCharArray(wcmd);
+		wcmd[cmd.size()] = 0;
+		par.Execute(&gr, wcmd);	gr.Box();
+		delete[] wcmd;
+		res->setText(cmd);
+	}
+	else if(cs->isChecked())	// stickplot
+	{
+		int n=sn->value(), k=sk->value();
+		for(int i=0;i<n;i++)	if(i!=k)	{	gr.StickPlot(n,i,Tet,Phi);	gr.Box("h");	}
+		cmd = "stickplot "+QString::number(n)+" "+QString::number(k)+" "+QString::number(Tet)+" "+QString::number(Phi);
+		if(Ax!=1 || Ay!=1)	cmd += ":aspect "+QString::number(Ax)+" "+QString::number(Ay);
+		wcmd = new wchar_t[cmd.size() + 1];
+		cmd.toWCharArray(wcmd);
+		wcmd[cmd.size()] = 0;
+		par.Execute(&gr, wcmd);	gr.Box();
+		delete[] wcmd;
+		res->setText(cmd);
+	}
+	else if(cc->isChecked())	// columnplot	// TODO add angles
+	{
+		int n=cn->value(), k=ck->value();
+		double d = cd->text().isEmpty()?0:cd->text().toDouble();
+		for(int i=0;i<n;i++)	if(i!=k)	{	gr.ColumnPlot(n,i,d);	gr.Rotate(Tet,Phi);	gr.Box("h");	}
+		cmd = "columnplot "+QString::number(n)+" "+QString::number(k)+" "+QString::number(d);
+		if(Tet || Phi)	cmd += ":rotate "+QString::number(Tet)+" "+QString::number(Phi);
+		if(Ax!=1 || Ay!=1)	cmd += ":aspect "+QString::number(Ax)+" "+QString::number(Ay);
+		wcmd = new wchar_t[cmd.size() + 1];
+		cmd.toWCharArray(wcmd);
+		wcmd[cmd.size()] = 0;
+		par.Execute(&gr, wcmd);	gr.Box();
+		delete[] wcmd;
+		res->setText(cmd);
+	}
+	else if(ci->isChecked())	// inplot
+	{
+		{	gr.SubPlot(1,1,0);	gr.Box("h");	}
+		cmd = "inplot "+x1->text()+" "+x2->text()+" "+y1->text()+" "+y2->text();
+		if(!title->text().isEmpty())
+		{	cmd += ":title '"+title->text()+"'";	if(!fmt.isEmpty())	cmd += fmt;	}
+		if(Tet || Phi)	cmd += ":rotate "+QString::number(Tet)+" "+QString::number(Phi);
+		if(Ax!=1 || Ay!=1)	cmd += ":aspect "+QString::number(Ax)+" "+QString::number(Ay);
+		wcmd = new wchar_t[cmd.size() + 1];
+		cmd.toWCharArray(wcmd);
+		wcmd[cmd.size()] = 0;
+		par.Execute(&gr, wcmd);	gr.Box();
+		delete[] wcmd;
+		res->setText(cmd);
+	}
+	setlocale(LC_NUMERIC, "");
+
+	
+	QPixmap p;
+	convertFromGraph(p, &gr, &grBuf);
+	pic->setPixmap(p);
+}
+//-----------------------------------------------------------------------------
+void SubplotDialog::titleStl()
+{
+	stlDialog->showFontPage();
+	if(stlDialog->exec())	{	fmt = " "+stlDialog->getStyle();	updatePic();	}
+}
+//-----------------------------------------------------------------------------
+void SubplotDialog::parseCmd(const QString& txt, bool final)
+{
+
+}
+//-----------------------------------------------------------------------------
diff --git a/udav/subplot_dlg.h b/udav/subplot_dlg.h
new file mode 100644
index 0000000..942c933
--- /dev/null
+++ b/udav/subplot_dlg.h
@@ -0,0 +1,68 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef SUBPLOTDIALOG_H
+#define SUBPLOTDIALOG_H
+//-----------------------------------------------------------------------------
+#include <QDialog>
+class QRadioButton;
+class QSpinBox;
+class QCheckBox;
+class QLabel;
+class QLineEdit;
+class StyleDialog;
+//-----------------------------------------------------------------------------
+class SubplotDialog : public QDialog
+{
+Q_OBJECT
+public:
+	SubplotDialog(QWidget *p);
+	~SubplotDialog();
+	const QString &getCommand()	{	return cmd;	}
+public slots:
+	void parseCmd(const QString &txt, bool final=true);
+	void finish();
+signals:
+	void result(const QString &txt);
+private slots:
+	void updatePic();
+	void titleStl();
+private:
+	QRadioButton *cb, *ci, *cm, *cg, *cc, *cs;
+	QSpinBox *tet, *phi;
+	QLineEdit *axz, *ayz;
+	QLineEdit *title, *res;
+	QSpinBox *bn,*bm,*bk;			// subplot
+	QLineEdit *x1,*x2,*y1,*y2;		// inplot
+	QSpinBox *sn,*sk;				// stickplot
+	QSpinBox *mn,*mm,*mk,*mx,*my;	// multiplot
+	QSpinBox *gm,*gn,*gk;			// gridplot
+	QSpinBox *cn,*ck;				// columnplot
+	QLineEdit *cd, *gd;
+	QCheckBox *rb,*rr,*rl,*rt,*rw;	// style (where reserve)
+	QString cmd;	// resulting command
+	QString fmt;	// format for title
+	QLabel *pic;	// resulting image
+//	bool replace;	// flag to be used in result() signal
+	uchar *grBuf;
+	StyleDialog *stlDialog;
+};
+//-----------------------------------------------------------------------------
+#endif // SUBPLOTDIALOG_H
+//-----------------------------------------------------------------------------
diff --git a/udav/text_pnl.cpp b/udav/text_pnl.cpp
new file mode 100644
index 0000000..26f6973
--- /dev/null
+++ b/udav/text_pnl.cpp
@@ -0,0 +1,601 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <QPrintDialog>
+#include <QMessageBox>
+#include <QTextStream>
+#include <QFileDialog>
+#include <QToolButton>
+#include <QToolBar>
+#include <QCompleter>
+#include <QBoxLayout>
+#include <QPrinter>
+#include <QMenu>
+#include "mgl2/qmathgl.h"
+//-----------------------------------------------------------------------------
+#include "udav_wnd.h"
+#include "qmglsyntax.h"
+#include "find_dlg.h"
+#include "opt_dlg.h"
+#include "style_dlg.h"
+#include "files_dlg.h"
+#include "newcmd_dlg.h"
+#include "setup_dlg.h"
+#include "text_pnl.h"
+#include "plot_pnl.h"
+#include "subplot_dlg.h"
+//-----------------------------------------------------------------------------
+FilesDialog *files_dlg=0;
+QString defFontFamily;
+int defFontSize;
+bool mglAutoExecute = true;
+extern mglParse parser;
+extern bool mglCompleter;
+QWidget *createDataOpenDlg(QWidget *p);
+QString getOpenDataFile(QWidget *w, QString filename);
+//-----------------------------------------------------------------------------
+TextPanel::TextPanel(QWidget *parent) : QWidget(parent)
+{
+	printer = new QPrinter;
+	findDialog = new FindDialog(this);
+	optDialog = new OptionDialog(this);
+	stlDialog = new StyleDialog(this);
+	newCmdDlg = new NewCmdDialog(this);
+	subplotDlg = new SubplotDialog(this);
+	setupDlg = new SetupDialog(this);
+	dataOpenDlg = createDataOpenDlg(this);
+	if(!files_dlg)	files_dlg= new FilesDialog;
+
+	int n=parser.GetCmdNum();
+	for(int i=0;i<n;i++) 	words<<QString::fromLatin1(parser.GetCmdName(i));
+	vars = words;
+
+	connect(setupDlg, SIGNAL(putText(const QString &)), this, SLOT(animPutText(const QString &)));
+	connect(newCmdDlg, SIGNAL(result(const QString&, bool)), this, SLOT(putLine(const QString&, bool)));
+	connect(subplotDlg, SIGNAL(result(const QString&)), this, SLOT(putLine(const QString&)));
+	connect(findDialog, SIGNAL(findText(const QString &, bool, bool)), this, SLOT(findText(const QString &, bool, bool)));
+	connect(findDialog, SIGNAL(replText(const QString &, const QString &, bool, bool)), this, SLOT(replText(const QString &, const QString &, bool, bool)));
+
+	edit = new TextEdit(this);	edit->setAcceptRichText(false);
+	new QMGLSyntax(edit);
+	defFontFamily = edit->fontFamily();
+	defFontSize = int(edit->fontPointSize());
+	edit->setLineWrapMode(QTextEdit::NoWrap);
+	setCompleter(mglCompleter);
+	QFontMetrics metrics(edit->currentFont());
+	edit->setTabStopWidth(4 * metrics.width(' '));
+
+	menu = new QMenu(_("Edit"),this);
+	QBoxLayout *v = new QVBoxLayout(this);
+	toolTop(v);	v->addWidget(edit);
+}
+//-----------------------------------------------------------------------------
+TextPanel::~TextPanel()	{	delete printer;	}
+//-----------------------------------------------------------------------------
+void TextPanel::setCompleter(bool en)
+{
+	if(en)
+	{
+		QCompleter *completer = new QCompleter(vars, this);
+		completer->setCaseSensitivity(Qt::CaseInsensitive);
+		completer->setCompletionMode(QCompleter::PopupCompletion);
+		edit->setCompleter(completer);
+	}
+	else	edit->setCompleter(0);
+//	completer->setCompletionMode(en ? QCompleter::PopupCompletion : QCompleter::InlineCompletion);
+}
+//-----------------------------------------------------------------------------
+void TextPanel::insNVal()
+{
+	QString sel=edit->textCursor().selectedText();
+	if(sel.isEmpty())
+	{
+		QMessageBox::warning(this,_("UDAV"),_("There is no selection to evaluate."));
+		return;
+	}
+	wchar_t *txt=new wchar_t[sel.length()+1];
+	sel.toWCharArray(txt);	txt[sel.length()]=0;
+	mglData res=parser.Calc(txt);
+	delete []txt;
+	edit->textCursor().insertText(QString::number(res.GetVal(0)));
+}
+//-----------------------------------------------------------------------------
+void TextPanel::insPrim()
+{
+	QString str(graph->mgl->primitives);
+	if(str.isEmpty())
+	{
+		QMessageBox::warning(this,_("UDAV"),_("There is manual primitives."));
+		return;
+	}
+	edit->moveCursor(QTextCursor::Start);
+	edit->insertPlainText("subplot 1 1 0 '#'\n"+str+"subplot 1 1 0\n#----------\n");
+	graph->mgl->primitives = "";
+}
+//-----------------------------------------------------------------------------
+void TextPanel::insFitF()
+{
+	QString str(graph->getFit());
+	if(str.isEmpty())
+	{
+		QMessageBox::warning(this,_("UDAV"),_("There is no fitted formula."));
+		return;
+	}
+	edit->textCursor().insertText("'"+str+"'");
+}
+//-----------------------------------------------------------------------------
+void TextPanel::insFile()
+{
+	QString str = QFileDialog::getOpenFileName(this, _("UDAV - Insert filename"));
+	if(str.isEmpty())	return;
+	edit->textCursor().insertText("'"+str+"'");
+}
+//-----------------------------------------------------------------------------
+void TextPanel::insPath()
+{
+	QString str = QFileDialog::getExistingDirectory(this, _("UDAV - Insert path"));
+	if(str.isEmpty())	return;
+	edit->textCursor().insertText("'"+str+"'");
+}
+//-----------------------------------------------------------------------------
+void TextPanel::refreshData()
+{
+	vars=words;
+	long i,n=parser.GetNumVar();
+	for(i=0;i<n;i++)
+	{
+		const mglDataA *v=parser.GetVar(i);
+		if(v && v->s.length()>2)	vars<<QString::fromWCharArray(v->s.c_str());
+	}
+	setCompleter(mglCompleter);
+}
+//-----------------------------------------------------------------------------
+void TextPanel::printText()
+{
+	QPrintDialog printDlg(printer, this);
+	if (printDlg.exec() == QDialog::Accepted)
+	{
+		setStatus(_("Printing..."));
+		edit->print(printer);
+		setStatus(_("Printing completed"));
+	}
+	else	setStatus(_("Printing aborted"));
+}
+//-----------------------------------------------------------------------------
+void TextPanel::find()
+{
+	findDialog->show();
+	findDialog->raise();
+	findDialog->activateWindow();
+}
+//-----------------------------------------------------------------------------
+bool TextPanel::findText(const QString &str, bool cs, bool fw)
+{
+//	static int para=0, index=0;
+	static QTextDocument::FindFlags f;
+	static QString stri="";
+	if(!str.isEmpty())
+	{
+		stri = str;
+		f = QTextDocument::FindFlags();
+		if(fw)	f = f|QTextDocument::FindBackward;
+		if(cs)	f = f|QTextDocument::FindCaseSensitively;
+	}
+	bool res = edit->find(stri, f);
+	if(!res)
+		QMessageBox::information(this, _("UDAV - find text"), _("No string occurrence is found"));
+	return res;
+}
+//-----------------------------------------------------------------------------
+void TextPanel::replText(const QString &str, const QString &txt, bool cs, bool fw)
+{
+	static bool res=false;
+	if(str.isEmpty())	{	res = false;	return;	}
+	if(res)	edit->textCursor().insertText(txt);
+	res = findText(str, cs, fw);
+}
+//-----------------------------------------------------------------------------
+void TextPanel::addOptions()
+{
+	if(optDialog->exec()==QDialog::Accepted)
+	{
+		edit->moveCursor(QTextCursor::EndOfLine);
+		edit->insertPlainText(optDialog->getOption());
+	}
+}
+//-----------------------------------------------------------------------------
+void TextPanel::animPutText(const QString &s)
+{	edit->moveCursor(QTextCursor::Start);	edit->insertPlainText(s);	}
+//-----------------------------------------------------------------------------
+//void TextPanel::putText(const QString &txt)	{	edit->insertPlainText(txt);	}
+//-----------------------------------------------------------------------------
+void TextPanel::putLine(const QString &txt, bool replace)
+{
+	edit->moveCursor(QTextCursor::StartOfLine);
+	if(replace)
+	{
+		QTextCursor c = edit->textCursor();
+		c.select(QTextCursor::BlockUnderCursor);
+		c.removeSelectedText();
+		edit->setTextCursor(c);
+		if(c.atStart())	edit->insertPlainText(txt);
+		else	edit->insertPlainText("\n"+txt);
+	}
+	else	edit->insertPlainText(txt+"\n");
+}
+//-----------------------------------------------------------------------------
+void TextPanel::addStyle()
+{
+	if(stlDialog->exec()==QDialog::Accepted)
+	{
+		QString s = edit->textCursor().block().text();
+		int i = s.indexOf(';');
+		if(i<0)	edit->moveCursor(QTextCursor::EndOfLine);
+		else
+		{
+			edit->moveCursor(QTextCursor::StartOfBlock);
+			// foolish way :(
+			for(;i>0;i--)	edit->moveCursor(QTextCursor::Left);
+		}
+		edit->insertPlainText(stlDialog->getStyle());
+	}
+}
+//-----------------------------------------------------------------------------
+void TextPanel::setEditorFont(QFont *f)
+{
+	QFont d(defFontFamily, defFontSize);
+	edit->setFont(f ? *f : d);
+	QFontMetrics metrics(f ? *f : d);
+	edit->setTabStopWidth(4 * metrics.width(' '));
+}
+//-----------------------------------------------------------------------------
+QString TextPanel::selection()
+{	return edit->textCursor().block().text();	}
+//-----------------------------------------------------------------------------
+void TextPanel::setCursorPosition(int n)
+{
+	if(n<0)	return;
+	edit->moveCursor(QTextCursor::Start);
+	for(int i=0;i<n;i++)	edit->moveCursor(QTextCursor::NextBlock);
+	edit->setFocus();
+}
+//-----------------------------------------------------------------------------
+void TextPanel::newCmd(int n)
+{
+	if(n>0)	setCursorPosition(n-1);
+	else if(n==0)	return;
+	newCmdDlg->parseCmd(edit->textCursor().block().text());
+	newCmdDlg->show();
+}
+//-----------------------------------------------------------------------------
+#if MGL_HAVE_HDF5
+#define H5_USE_16_API
+#include <hdf5.h>
+void TextPanel::loadHDF5(const QString &fileName)
+{
+	// H5T_C_S1 - C string
+	hid_t hf,hg,hd,hs,ht;
+	hsize_t dims[3];
+	long rank;
+	hf = H5Fopen(fileName.toLocal8Bit().constData(), H5F_ACC_RDONLY, H5P_DEFAULT);
+	if(!hf)	return;
+	hg = H5Gopen(hf, "/");
+	hsize_t num, nx, ny, nz, i;
+	char name[256];
+	H5Gget_num_objs(hg, &num);
+	for(i=0;i<num;i++)
+	{
+		if(H5Gget_objtype_by_idx(hg, i)!=H5G_DATASET)	continue;
+		H5Gget_objname_by_idx(hg, i, name, 256);
+		hd = H5Dopen(hg,name);	hs = H5Dget_space(hd);
+		ht = H5Dget_type(hd);
+		rank = H5Sget_simple_extent_ndims(hs);
+		if(H5Tget_class(ht)==H5T_STRING)	// load script
+		{
+			H5Sget_simple_extent_dims(hs,dims,0);
+			char *buf = new char[dims[0]+1];
+			H5Dread(hd, H5T_C_S1, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf);
+			buf[dims[0]]=0;		// to be sure :)
+			QString str = buf;
+			if(str.contains("subplot 1 1 0\n#----- End of QMathGL block -----\n"))
+			{
+				graph->mgl->primitives = str.section("subplot 1 1 0\n#----- End of QMathGL block -----\n",0,0).section("subplot 1 1 0 '#'\n",1);
+				str = str.section("subplot 1 1 0\n#----- End of QMathGL block -----\n",1);
+			}
+			edit->setText(str);
+			graph->animParseText(edit->toPlainText());
+			setCurrentFile(fileName);
+			delete []buf;
+			setStatus(QString(_("Loaded document %1")).arg(fileName));
+			if(mglAutoExecute)	graph->execute();
+		}
+		else if(H5Tget_class(ht)==H5T_FLOAT || H5Tget_class(ht)==H5T_INTEGER)
+		{
+			for(int j=0;name[j];j++)	if(!isalnum(name[j]))	name[j]='_';
+			mglData *v = (mglData*) parser.AddVar(name);
+			nx = ny = nz = 1;
+			if(rank>0 && rank<=3)
+			{
+				H5Sget_simple_extent_dims(hs,dims,0);
+				switch(rank)
+				{
+					case 1:	nx=dims[0];	break;
+					case 2:	nx=dims[1];	ny=dims[0];	break;
+					case 3:	nx=dims[2];	ny=dims[1];	nz=dims[0];	break;
+				}
+				v->Create(nx, ny, nz);
+#if MGL_USE_DOUBLE
+				H5Dread(hd, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, v->a);
+#else
+				H5Dread(hd, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, v->a);
+#endif
+			}
+		}
+		H5Dclose(hd);	H5Sclose(hs);	H5Tclose(ht);
+	}
+	H5Gclose(hg);	H5Fclose(hf);
+}
+//-----------------------------------------------------------------------------
+void TextPanel::saveHDF5(const QString &fileName)
+{
+	hid_t hf,hd,hs;
+	hsize_t dims[3];
+	long rank = 3;
+
+	H5Eset_auto(0,0);
+	hf = H5Fcreate(fileName.toLocal8Bit().constData(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+	if(hf<0)
+	{
+		setStatus(QString(_("Could not write to %1")).arg(fileName));
+		return;
+	}
+	{	// save script
+		QString txt;
+		if(!graph->mgl->primitives.isEmpty())
+			txt += "subplot 1 1 0 '#'\n"+graph->mgl->primitives + "subplot 1 1 0\n#----- End of QMathGL block -----\n";
+		txt += edit->toPlainText();
+		dims[0] = txt.length()+1;
+		char *buf = new char[dims[0]+1];
+		memcpy(buf, txt.toLocal8Bit().constData(), dims[0]);
+		buf[dims[0]]=0;
+		hs = H5Screate_simple(1, dims, 0);
+		hd = H5Dcreate(hf, "mgl_script", H5T_C_S1, hs, H5P_DEFAULT);
+		H5Dwrite(hd, H5T_C_S1, hs, hs, H5P_DEFAULT, buf);
+		H5Dclose(hd);	H5Sclose(hs);
+		delete []buf;
+	}
+	long n = parser.GetNumVar();
+	char name[256];
+	for(long i=0;i<n;i++)
+	{
+		const mglData *v = dynamic_cast<const mglData *>(parser.GetVar(i));
+		mglData tmp;
+		if(!v)	{	tmp.Set(parser.GetVar(i));	v = &tmp;	}
+		wcstombs(name,v->s.c_str(),v->s.length()+1);
+		if(v->nz==1 && v->ny == 1)
+		{	rank = 1;	dims[0] = v->nx;	}
+		else if(v->nz==1)
+		{	rank = 2;	dims[0] = v->ny;	dims[1] = v->nx;	}
+		else
+		{	rank = 3;	dims[0] = v->nz;	dims[1] = v->ny;	dims[2] = v->nx;	}
+		hs = H5Screate_simple(rank, dims, 0);
+		hd = H5Dcreate(hf, name, H5T_IEEE_F32LE, hs, H5P_DEFAULT);
+
+		H5Dwrite(hd, H5T_NATIVE_FLOAT, hs, hs, H5P_DEFAULT, v->a);
+		H5Dclose(hd);	H5Sclose(hs);
+	}
+	H5Fclose(hf);
+	setCurrentFile(fileName);
+	setStatus(QString(_("File %1 saved")).arg(fileName));
+	return;
+}
+#else
+void TextPanel::saveHDF5(const QString &fileName){}
+void TextPanel::loadHDF5(const QString &fileName){}
+#endif
+//-----------------------------------------------------------------------------
+void TextPanel::load(const QString &fileName)
+{
+	if(fileName.right(4).toLower()==".dat")
+	{
+		QString code = getOpenDataFile(dataOpenDlg, fileName);
+		if(!code.isEmpty())
+		{
+			setCurrentFile(fileName.left(fileName.length()-3)+"mgl");
+			edit->setText(code);
+		}
+	}
+	else if(fileName.right(4).toLower()==".hdf" || fileName.right(3).toLower()==".h5")
+		loadHDF5(fileName);
+	else
+	{
+		QFile f(fileName);
+		if(!f.open(QIODevice::ReadOnly))
+		{
+			QMessageBox::warning(this,_("UDAV - open file"), _("Couldn't open file ") + QString("'") + fileName+"'", QMessageBox::Ok,0,0);
+			return;
+		}
+
+		QTextStream ts(&f);
+		ts.setAutoDetectUnicode(true);
+//		ts.setCodec(QTextCodec::codecForLocale());
+
+		QString str=ts.readAll();
+		int narg=0,i=-1;
+		if(str.contains('%'))
+		{
+			while((i = str.indexOf('%',i+1))>0)
+			{
+				char ch = str.at(i+1).toLatin1();
+				if(ch>='1' && ch<='9' && ch-'0'>narg)
+					narg = ch-'0';
+			}
+			if(narg>0)
+			{
+				files_dlg->setNumFiles(narg);
+				if(!files_dlg->exec())	return;	// nothing to do
+				str = files_dlg->putFiles(str);
+			}
+		}
+		if(str.contains("#----- End of QMathGL block -----\n"))
+		{
+			graph->mgl->primitives = str.section("#----- End of QMathGL block -----\n",0,0);
+			str = str.section("#----- End of QMathGL block -----\n",1);
+		}
+
+		if(narg>0)	setCurrentFile(fileName.left(fileName.length()-3)+"mgl");
+		edit->setText(str);
+		graph->animParseText(edit->toPlainText());
+		if(narg==0)	setCurrentFile(fileName);
+	}
+	setStatus(_("Loaded document ")+fileName);
+	if(mglAutoExecute)	graph->execute();
+}
+//-----------------------------------------------------------------------------
+void TextPanel::save(const QString &fileName)
+{
+	if(fileName.right(4)==".hdf" || fileName.right(3)==".h5")
+	{	saveHDF5(fileName);	return;	}
+	QString text;
+	if(!graph->mgl->primitives.isEmpty())
+		text += graph->mgl->primitives + "#----- End of QMathGL block -----\n";
+	text += edit->toPlainText();
+	QFile f(fileName);
+	if(!f.open(QIODevice::WriteOnly))
+	{
+		setStatus(QString(_("Could not write to %1")).arg(fileName));
+		return;
+	}
+	QTextStream t(&f);
+	t.setAutoDetectUnicode(true);
+	t << text;	f.close();
+	setCurrentFile(fileName);
+	setStatus(QString(_("File %1 saved")).arg(fileName));
+}
+//-----------------------------------------------------------------------------
+void TextPanel::addSetup()	{	setupDlg->exec();	}
+//-----------------------------------------------------------------------------
+#include "xpm/option.xpm"
+#include "xpm/style.xpm"
+#include "xpm/curve.xpm"
+#include "xpm/box.xpm"
+//-----------------------------------------------------------------------------
+void TextPanel::toolTop(QBoxLayout *v)
+{
+	QToolBar *t = new QToolBar(this);	v->addWidget(t);	t->setMovable(false);
+	QAction *a, *aa;
+	QMenu *o=menu, *oo;
+	const MainWindow *mw=findMain(this);
+
+	// general buttons
+	if(mw)
+	{
+		t->addAction(mw->aload);	t->addAction(mw->asave);	t->addAction(mw->acalc);
+	}
+	QToolButton *bb = new QToolButton(this);
+	bb->setPopupMode(QToolButton::MenuButtonPopup);
+	t->addWidget(bb);
+
+	// edit menu
+	a = new QAction(QPixmap(":/png/edit-undo.png"), _("Undo"), this);
+	connect(a, SIGNAL(triggered()), edit, SLOT(undo()));
+	a->setToolTip(_("Undo editor change (Ctrl+Z)."));
+	a->setShortcut(Qt::CTRL+Qt::Key_Z);	o->addAction(a);	t->addAction(a);
+
+	a = new QAction(QPixmap(":/png/edit-redo.png"), _("Redo"), this);
+	connect(a, SIGNAL(triggered()), edit, SLOT(redo()));
+	a->setToolTip(_("Redo editor change (Ctrl+Shift+Z)."));
+	a->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_Z);	o->addAction(a);	t->addAction(a);
+
+	o->addSeparator();
+	o->addAction(_("Clear all"), edit, SLOT(clear()));
+	a = new QAction(QPixmap(":/png/edit-cut.png"), _("Cut text"), this);
+	connect(a, SIGNAL(triggered()), edit, SLOT(cut()));
+	a->setToolTip(_("Cut selected text to clipboard (Ctrl+X)."));
+	a->setShortcut(Qt::CTRL+Qt::Key_X);	o->addAction(a);	t->addAction(a);
+
+	a = new QAction(QPixmap(":/png/edit-copy.png"), _("Copy text"), this);
+	connect(a, SIGNAL(triggered()), edit, SLOT(copy()));
+	a->setToolTip(_("Copy selected text or data to clipboard (Ctrl+C)."));
+	a->setShortcut(Qt::CTRL+Qt::Key_C);	o->addAction(a);	t->addAction(a);
+
+	a = new QAction(QPixmap(":/png/edit-paste.png"), _("Paste text"), this);
+	connect(a, SIGNAL(triggered()), edit, SLOT(paste()));
+	a->setToolTip(_("Paste text or data from clipboard (Ctrl+V)."));
+	a->setShortcut(Qt::CTRL+Qt::Key_V);	o->addAction(a);	t->addAction(a);
+
+	o->addAction(QPixmap(":/png/edit-select-all.png"), _("Select all"), edit, SLOT(selectAll()), Qt::CTRL+Qt::Key_A);
+	o->addSeparator();
+
+	a = new QAction(QPixmap(":/png/edit-find.png"), _("Find/Replace"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(find()));
+	a->setToolTip(_("Show dialog for text finding (Ctrl+F)."));
+	a->setShortcut(Qt::CTRL+Qt::Key_F);	o->addAction(a);	t->addAction(a);
+
+	a = new QAction(_("Find next"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(findText()));
+	a->setShortcut(Qt::Key_F3);	o->addAction(a);
+	o->addSeparator();
+
+	// insert menu
+	oo = o->addMenu(_("Insert"));
+	aa=a = new QAction(QPixmap(":/png/format-indent-more.png"), _("New command"), this);
+	a->setShortcut(Qt::META+Qt::Key_C);	connect(a, SIGNAL(triggered()), this, SLOT(newCmd()));
+	a->setToolTip(_("Show dialog for new command or edit arguments of existed one."));
+	oo->addAction(a);
+	a = new QAction(QPixmap(box_xpm), _("New inplot"), this);
+	a->setShortcut(Qt::META+Qt::Key_C);	connect(a, SIGNAL(triggered()), subplotDlg, SLOT(show()));
+	a->setToolTip(_("Show dialog for new inplot and put it into the script."));
+	oo->addAction(a);
+
+	a = new QAction(_("Fitted formula"), this);
+	a->setShortcut(Qt::META+Qt::Key_F);	connect(a, SIGNAL(triggered()), this, SLOT(insFitF()));
+	a->setToolTip(_("Insert last fitted formula with found coefficients."));
+	oo->addAction(a);
+	a = new QAction(QPixmap(style_xpm), _("Plot style"), this);
+	a->setShortcut(Qt::META+Qt::Key_S);	connect(a, SIGNAL(triggered()), this, SLOT(addStyle()));
+	a->setToolTip(_("Show dialog for styles and put it into the script.\nStyles define the plot view (color scheme, marks, dashing and so on)."));
+	oo->addAction(a);
+	a = new QAction(QPixmap(option_xpm), _("Command options"), this);
+	a->setShortcut(Qt::META+Qt::Key_O);	connect(a, SIGNAL(triggered()), this, SLOT(addOptions()));
+	a->setToolTip(_("Show dialog for options and put it into the script.\nOptions are used for additional setup the plot."));
+	oo->addAction(a);
+	a = new QAction(_("Numeric value"), this);
+	a->setShortcut(Qt::META+Qt::Key_N);	connect(a, SIGNAL(triggered()), this, SLOT(insNVal()));
+	a->setToolTip(_("Replace expression by its numerical value."));
+	oo->addAction(a);
+	a = new QAction(QPixmap(":/png/text-csv.png"), _("File name"), this);
+	a->setShortcut(Qt::META+Qt::Key_P);	connect(a, SIGNAL(triggered()), this, SLOT(insFile()));
+	a->setToolTip(_("Select and insert file name."));
+	oo->addAction(a);
+	a = new QAction(QPixmap(":/png/folder.png"), _("Folder path"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(insPath()));
+	a->setToolTip(_("Select and insert folder name."));
+	oo->addAction(a);
+	a = new QAction(QPixmap(curve_xpm), _("Manual primitives"), this);
+	a->setShortcut(Qt::META+Qt::Key_P);	connect(a, SIGNAL(triggered()), this, SLOT(insPrim()));
+	a->setToolTip(_("Move mouse-handled primitives to script."));
+	oo->addAction(a);	bb->setMenu(oo);	bb->setDefaultAction(aa);
+
+	a = new QAction(QPixmap(":/png/document-properties.png"), _("Graphics setup"), this);
+	a->setShortcut(Qt::META+Qt::Key_G);	connect(a, SIGNAL(triggered()), this, SLOT(addSetup()));
+	a->setToolTip(_("Show dialog for plot setup and put code into the script.\nThis dialog setup axis, labels, lighting and other general things."));
+	o->addAction(a);	t->addAction(a);
+}
+//-----------------------------------------------------------------------------
diff --git a/udav/text_pnl.h b/udav/text_pnl.h
new file mode 100644
index 0000000..213a5f1
--- /dev/null
+++ b/udav/text_pnl.h
@@ -0,0 +1,106 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef TEXT_PNL_H
+#define TEXT_PNL_H
+//-----------------------------------------------------------------------------
+#include <QWidget>
+#include <QStringList>
+#include "textedit.h"
+//-----------------------------------------------------------------------------
+class QMenu;
+class QPrinter;
+class QBoxLayout;
+class FindDialog;
+class OptionDialog;
+class StyleDialog;
+class SetupDialog;
+class NewCmdDialog;
+class PlotPanel;
+class SubplotDialog;
+//-----------------------------------------------------------------------------
+class TextPanel : public QWidget
+{
+Q_OBJECT
+public:
+	QMenu *menu;
+	TextEdit *edit;		///< script itself
+	PlotPanel *graph;	///< NOTE: have to be filled!!!
+	NewCmdDialog *newCmdDlg;
+	SubplotDialog *subplotDlg;
+
+	TextPanel(QWidget *parent = 0);
+	~TextPanel();
+	void load(const QString &fileName);
+	void save(const QString &fileName);
+	inline bool isModified()	{	return edit->document()->isModified();	}
+	inline void setModified(bool m)	{	edit->document()->setModified(m);	}
+	inline void moveCursor(QTextCursor::MoveOperation c)
+	{	edit->moveCursor(c);	}
+	void setCompleter(bool en);
+	QString selection();
+
+signals:
+	void setCurrentFile(const QString &s);
+	void setStatus(const QString &s);
+
+public slots:
+	void setEditorFont(QFont *f=0);
+//	void setEditPos(bool bottom);
+	void animPutText(const QString &);
+//	void putText(const QString &txt);
+	void putLine(const QString &txt, bool replace=false);
+	void setCursorPosition(int);
+
+	void addOptions();
+	void addStyle();
+	void insNVal();
+	void insFile();
+	void insPath();
+	void insFitF();
+	void insPrim();
+	void newCmd(int n=-1);
+	void addSetup();
+
+	void refreshData();
+	void printText();
+	void find();
+	bool findText(const QString &str="", bool cs=false, bool fw=true);
+	void replText(const QString &str, const QString &txt, bool cs=false, bool fw=true);
+
+private:
+
+	QStringList words, vars;
+	QPrinter *printer;
+
+	FindDialog *findDialog;
+	OptionDialog *optDialog;
+	StyleDialog *stlDialog;
+	QWidget *dataOpenDlg;
+	SetupDialog *setupDlg;
+
+	void toolTop(QBoxLayout *l);
+//	void toolLeft(QBoxLayout *l);
+
+	void saveHDF5(const QString &fileName);
+	void loadHDF5(const QString &fileName);
+};
+//-----------------------------------------------------------------------------
+#endif // TEXT_PNL_H
+//-----------------------------------------------------------------------------
diff --git a/udav/textedit.cpp b/udav/textedit.cpp
new file mode 100644
index 0000000..846f54f
--- /dev/null
+++ b/udav/textedit.cpp
@@ -0,0 +1,326 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ ** All rights reserved.
+ ** Contact: Nokia Corporation (qt-info at nokia.com)
+ **
+ ** This file is part of the examples of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:BSD$
+ ** You may use this file under the terms of the BSD license as follows:
+ **
+ ** "Redistribution and use in source and binary forms, with or without
+ ** modification, are permitted provided that the following conditions are
+ ** met:
+ **   * Redistributions of source code must retain the above copyright
+ **     notice, this list of conditions and the following disclaimer.
+ **   * Redistributions in binary form must reproduce the above copyright
+ **     notice, this list of conditions and the following disclaimer in
+ **     the documentation and/or other materials provided with the
+ **     distribution.
+ **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+ **     the names of its contributors may be used to endorse or promote
+ **     products derived from this software without specific prior written
+ **     permission.
+ **
+ ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include "textedit.h"
+#include <string.h>
+#include <QCompleter>
+#include <QKeyEvent>
+#include <QAbstractItemView>
+#include <QtDebug>
+#include <QApplication>
+#include <QModelIndex>
+#include <QAbstractItemModel>
+#include <QScrollBar>
+#include <QPainter>
+#include <QTextBlock>
+#include <QAbstractTextDocumentLayout>
+
+extern QColor mglColorScheme[10];
+//-----------------------------------------------------------------------------
+TextEdit::TextEdit(QWidget *parent) : QTextEdit(parent)
+{
+	c=0;
+	connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlight()));
+	// Line numbers
+	lineNumberArea = new LineNumberArea(this);
+	connect(document(), SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
+	connect(document(), SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberArea(int)));
+	connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(updateLineNumberArea(int)));
+	connect(this, SIGNAL(textChanged()), this, SLOT(updateLineNumberArea()));
+	connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(updateLineNumberArea()));
+	updateLineNumberAreaWidth(0);
+}
+//-----------------------------------------------------------------------------
+void TextEdit::highlight()
+{
+	QList<QTextEdit::ExtraSelection> extraSelections;
+	if (!isReadOnly())
+	{
+		QTextEdit::ExtraSelection selection;
+		selection.format.setBackground(mglColorScheme[9]);
+		selection.format.setProperty(QTextFormat::FullWidthSelection, true);
+		selection.cursor = textCursor();
+		selection.cursor.clearSelection();
+		extraSelections.append(selection);
+	}
+	setExtraSelections(extraSelections);
+}
+//-----------------------------------------------------------------------------
+void TextEdit::setCompleter(QCompleter *completer)
+{
+	if(c && c!=completer)
+	{	QObject::disconnect(c);	c->setWidget(0);	delete c;	c=0;	}
+	if(!completer)	return;
+	c = completer;
+	c->setWidget(this);
+	c->setCompletionMode(QCompleter::PopupCompletion);
+	c->setCaseSensitivity(Qt::CaseInsensitive);
+	QObject::connect(c, SIGNAL(activated(QString)), this, SLOT(insertCompletion(QString)));
+}
+//-----------------------------------------------------------------------------
+void TextEdit::insertCompletion(const QString& completion)
+{
+	if (!c || c->widget() != this)	return;
+	QTextCursor tc = textCursor();
+	int extra = completion.length() - c->completionPrefix().length();
+	tc.movePosition(QTextCursor::Left);
+	tc.movePosition(QTextCursor::EndOfWord);
+	tc.insertText(completion.right(extra));
+	setTextCursor(tc);
+}
+//-----------------------------------------------------------------------------
+QString TextEdit::textUnderCursor() const
+{
+	QTextCursor tc = textCursor();
+	tc.select(QTextCursor::WordUnderCursor);
+	return tc.selectedText();
+}
+//-----------------------------------------------------------------------------
+void TextEdit::focusInEvent(QFocusEvent *e)
+{	if (c)	c->setWidget(this);	QTextEdit::focusInEvent(e);	}
+//-----------------------------------------------------------------------------
+void TextEdit::keyPressEvent(QKeyEvent *e)
+{
+	if (c && c->popup()->isVisible())
+	{
+		// The following keys are forwarded by the completer to the widget
+		switch (e->key())
+		{
+		case Qt::Key_Enter:
+		case Qt::Key_Return:
+		case Qt::Key_Escape:
+		case Qt::Key_Tab:
+		case Qt::Key_Backtab:
+			e->ignore();	return; // let the completer do default behavior
+		default:
+			break;
+		}
+	}
+
+	bool isShortcut = ((e->modifiers() & Qt::ControlModifier) && e->key() == Qt::Key_E); // CTRL+E
+	if (!c || !isShortcut) // do not process the shortcut when we have a completer
+		QTextEdit::keyPressEvent(e);
+
+	const bool ctrlOrShift = e->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier);
+	if (!c || (ctrlOrShift && e->text().isEmpty()))
+		return;
+
+	static QString eow("~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-="); // end of word
+	bool hasModifier = (e->modifiers() != Qt::NoModifier) && !ctrlOrShift;
+	QString completionPrefix = textUnderCursor();
+
+	if (!isShortcut && (hasModifier || e->text().isEmpty()|| completionPrefix.length() < 3
+						|| eow.contains(e->text().right(1))))
+	{	c->popup()->hide();		return;	}
+
+	if (completionPrefix != c->completionPrefix())
+	{
+		c->setCompletionPrefix(completionPrefix);
+		c->popup()->setCurrentIndex(c->completionModel()->index(0, 0));
+	}
+	QRect cr = cursorRect();
+	cr.setWidth(c->popup()->sizeHintForColumn(0) + c->popup()->verticalScrollBar()->sizeHint().width());
+	c->complete(cr); // popup it up!
+}
+//-----------------------------------------------------------------------------
+//
+//	Line numbering (slightly modified code of Gauthier Boaglio)
+//	Original: https://stackoverflow.com/questions/2443358/how-to-add-lines-numbers-to-qtextedit/
+//
+//-----------------------------------------------------------------------------
+int TextEdit::lineNumberAreaWidth()
+{
+	int digits = 1;
+	int max = qMax(1, document()->blockCount());
+	while (max >= 10)	{	max /= 10;	++digits;	}
+	int space = 13 +  fontMetrics().width(QLatin1Char('9')) * (digits);
+	return space;
+}
+//-----------------------------------------------------------------------------
+void TextEdit::updateLineNumberAreaWidth(int /* newBlockCount */)
+{	setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);	}
+//-----------------------------------------------------------------------------
+void TextEdit::updateLineNumberArea(QRectF /*rect_f*/)
+{	TextEdit::updateLineNumberArea();	}
+//-----------------------------------------------------------------------------
+void TextEdit::updateLineNumberArea(int /*slider_pos*/)
+{	TextEdit::updateLineNumberArea();	}
+//-----------------------------------------------------------------------------
+void TextEdit::updateLineNumberArea()
+{
+	/* When the signal is emitted, the sliderPosition has been adjusted according to the action,
+	 * but the value has not yet been propagated (meaning the valueChanged() signal was not yet emitted),
+	 * and the visual display has not been updated. In slots connected to this signal you can thus safely
+	 * adjust any action by calling setSliderPosition() yourself, based on both the action and the
+	 * slider's value. */
+	// Make sure the sliderPosition triggers one last time the valueChanged() signal with the actual value !!!!
+	verticalScrollBar()->setSliderPosition(verticalScrollBar()->sliderPosition());
+
+	// Since "QTextEdit" does not have an "updateRequest(...)" signal, we chose
+	// to grab the imformations from "sliderPosition()" and "contentsRect()".
+	// See the necessary connections used (Class constructor implementation part).
+
+	QRect rect =  contentsRect();
+	lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height());
+	updateLineNumberAreaWidth(0);
+	//----------
+	int dy = verticalScrollBar()->sliderPosition();
+	if (dy > -1) {
+		lineNumberArea->scroll(0, dy);
+	}
+
+	// Addjust slider to alway see the number of the currently being edited line...
+	int first_block_id = getFirstVisibleBlockId();
+	if (first_block_id == 0 || textCursor().block().blockNumber() == first_block_id-1)
+		verticalScrollBar()->setSliderPosition(dy-document()->documentMargin());
+}
+//-----------------------------------------------------------------------------
+void TextEdit::resizeEvent(QResizeEvent *e)
+{
+	QTextEdit::resizeEvent(e);
+	QRect cr = contentsRect();
+	lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
+}
+//-----------------------------------------------------------------------------
+int TextEdit::getFirstVisibleBlockId()
+{
+	// Detect the first block for which bounding rect - once translated
+	// in absolute coordinated - is contained by the editor's text area
+
+	// Costly way of doing but since "blockBoundingGeometry(...)" doesn't
+	// exists for "QTextEdit"...
+
+	QTextCursor curs = QTextCursor(document());
+	curs.movePosition(QTextCursor::Start);
+	for(int i=0; i < document()->blockCount(); ++i)
+	{
+		QTextBlock block = curs.block();
+
+		QRect r1 = viewport()->geometry();
+		QRect r2 = document()->documentLayout()->blockBoundingRect(block).translated(
+					viewport()->geometry().x(), viewport()->geometry().y() - (
+						verticalScrollBar()->sliderPosition()
+						) ).toRect();
+
+		if (r1.contains(r2, true)) { return i; }
+
+		curs.movePosition(QTextCursor::NextBlock);
+	}
+
+	return 0;
+}
+//-----------------------------------------------------------------------------
+void TextEdit::lineNumberAreaPaintEvent(QPaintEvent *event)
+{
+	verticalScrollBar()->setSliderPosition(verticalScrollBar()->sliderPosition());
+
+	QPainter painter(lineNumberArea);
+	painter.fillRect(event->rect(), Qt::lightGray);
+	int blockNumber = getFirstVisibleBlockId();
+
+	QTextBlock block = document()->findBlockByNumber(blockNumber);
+	QTextBlock prev_block = (blockNumber > 0) ? document()->findBlockByNumber(blockNumber-1) : block;
+	int translate_y = (blockNumber > 0) ? -verticalScrollBar()->sliderPosition() : 0;
+
+	int top = viewport()->geometry().top();
+
+	// Adjust text position according to the previous "non entirely visible" block
+	// if applicable. Also takes in consideration the document's margin offset.
+	int additional_margin;
+	if (blockNumber == 0)	// Simply adjust to document's margin
+		additional_margin = (int) document()->documentMargin() -1 - verticalScrollBar()->sliderPosition();
+	else	// Getting the height of the visible part of the previous "non entirely visible" block
+		additional_margin = (int) document()->documentLayout()->blockBoundingRect(prev_block)
+				.translated(0, translate_y).intersected(viewport()->geometry()).height();
+	top += additional_margin;	// Shift the starting point
+
+	int bottom = top + (int) document()->documentLayout()->blockBoundingRect(block).height();
+
+	QColor colErr(255, 0, 0);	// Error line
+	QColor colCur(0, 128, 255);	// Current line
+	QColor colDef(0,0,0);		// Other lines
+
+	// Draw the numbers (displaying the current line number in green)
+	while (block.isValid() && top <= event->rect().bottom())
+	{
+		if (block.isVisible() && bottom >= event->rect().top())
+		{
+			QString number = QString::number(blockNumber + 1);
+			painter.setPen(QColor(120, 120, 120));
+			painter.setPen((textCursor().blockNumber() == blockNumber) ? colCur :
+										(isErrLine(blockNumber+1)?colErr:colDef) );
+			painter.drawText(-5, top, lineNumberArea->width(), fontMetrics().height(), Qt::AlignRight, number);
+		}
+
+		block = block.next();
+		top = bottom;
+		bottom = top + (int) document()->documentLayout()->blockBoundingRect(block).height();
+		blockNumber++;
+	}
+}
+//-----------------------------------------------------------------------------
+bool TextEdit::isErrLine(int line) const
+{
+	for(size_t i=0;i<err.size();i++)	if(err[i]==line)	return true;
+	return false;
+}
+//-----------------------------------------------------------------------------
+void TextEdit::setErrMessage(const QString &mess)
+{
+	err.clear();
+	QByteArray qs = mess.toLatin1();
+	const char *s = qs.constData();
+	s = strstr(s,"in line ");
+	while(s)
+	{
+		err.push_back(atoi(s+8));
+		s = strstr(s+8,"in line ");
+	}
+}
+//-----------------------------------------------------------------------------
+LineNumberArea::LineNumberArea(TextEdit *editor) : QWidget(editor)
+{	codeEditor = editor;	}
+//-----------------------------------------------------------------------------
+QSize LineNumberArea::sizeHint() const
+{	return QSize(codeEditor->lineNumberAreaWidth(), 0);	}
+//-----------------------------------------------------------------------------
+void LineNumberArea::paintEvent(QPaintEvent *event)
+{	codeEditor->lineNumberAreaPaintEvent(event);	}
+//-----------------------------------------------------------------------------
diff --git a/udav/textedit.h b/udav/textedit.h
new file mode 100644
index 0000000..080cafd
--- /dev/null
+++ b/udav/textedit.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info at nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+**     the names of its contributors may be used to endorse or promote
+**     products derived from this software without specific prior written
+**     permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef TEXTEDIT_H
+#define TEXTEDIT_H
+//-----------------------------------------------------------------------------
+#include <QTextEdit>
+#if defined(_MSC_VER)
+#include <mgl2/define.h>
+#endif
+//-----------------------------------------------------------------------------
+class QCompleter;
+class Numb;
+//-----------------------------------------------------------------------------
+class TextEdit : public QTextEdit
+{
+	Q_OBJECT
+public:
+	TextEdit(QWidget *parent = 0);
+	void setCompleter(QCompleter *c);
+	QCompleter *completer() const {	return c;	}
+	int getFirstVisibleBlockId();
+	void lineNumberAreaPaintEvent(QPaintEvent *event);
+	int lineNumberAreaWidth();
+
+public slots:
+	void resizeEvent(QResizeEvent *e);
+	void setErrMessage(const QString &s);
+
+protected:
+	void keyPressEvent(QKeyEvent *e);
+	void focusInEvent(QFocusEvent *e);
+	bool isErrLine(int line) const;
+
+private slots:
+	void insertCompletion(const QString &completion);
+	void highlight();
+	void updateLineNumberAreaWidth(int newBlockCount);
+	void updateLineNumberArea(QRectF /*rect_f*/);
+	void updateLineNumberArea(int /*slider_pos*/);
+	void updateLineNumberArea();
+
+private:
+	QString textUnderCursor() const;
+	QCompleter *c;
+	QWidget *lineNumberArea;
+	std::vector<int> err;
+};
+//-----------------------------------------------------------------------------
+class LineNumberArea : public QWidget
+{
+	Q_OBJECT
+public:
+	LineNumberArea(TextEdit *editor);
+	QSize sizeHint() const;
+protected:
+	void paintEvent(QPaintEvent *event);
+private:
+	TextEdit *codeEditor;
+};
+
+//-----------------------------------------------------------------------------
+#endif // TEXTEDIT_H
+//-----------------------------------------------------------------------------
diff --git a/udav/tree_pnl.cpp b/udav/tree_pnl.cpp
new file mode 100644
index 0000000..e69de29
diff --git a/udav/tree_pnl.h b/udav/tree_pnl.h
new file mode 100644
index 0000000..26a1186
--- /dev/null
+++ b/udav/tree_pnl.h
@@ -0,0 +1,57 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef TREE_PNL_H
+#define TREE_PNL_H
+//-----------------------------------------------------------------------------
+#include <QWidget>
+#include <QStringList>
+//-----------------------------------------------------------------------------
+class QMenu;
+class QBoxLayout;
+class OptionDialog;
+class NewCmdDialog;
+class PlotPanel;
+class TextEdit;
+//-----------------------------------------------------------------------------
+class TreePanel : public QWidget
+{
+Q_OBJECT
+public:
+	// NOTE: these 3 pointers have to be filled!!!
+	TextEdit *edit;		///< script itself
+	PlotPanel *graph;	
+	NewCmdDialog *newCmdDlg;
+
+	TreePanel(QWidget *parent = 0);
+	~TreePanel();
+
+public slots:
+	void refresh();			///< refresh tree according new script
+	void setPosition(int);	///< select item for given line number
+	void hidePlot(int);		///< hide plot for given item
+	void annotatePlot(int);	///< add annotation for given item
+	void newCmd();			///< add new command + refresh tree
+
+private:
+	void toolTop(QBoxLayout *l);
+};
+//-----------------------------------------------------------------------------
+#endif // TREE_PNL_H
+//-----------------------------------------------------------------------------
diff --git a/udav/udav.desktop b/udav/udav.desktop
new file mode 100755
index 0000000..4c06fe3
--- /dev/null
+++ b/udav/udav.desktop
@@ -0,0 +1,13 @@
+[Desktop Entry]
+Version=1.0
+Type=Application
+Terminal=false
+Icon=udav
+Name=UDAV
+Exec=udav %f
+MimeType=text/mgl;
+Comment=Data handling and plotting tool
+Comment[en_US]=Data handling and plotting tool
+Comment[ru_RU]=Обработка и отображение данных
+Categories=Education;Science;Math;
+Keywords=Visualization;Data;Array;
\ No newline at end of file
diff --git a/udav/udav.ico b/udav/udav.ico
new file mode 100644
index 0000000..27423de
Binary files /dev/null and b/udav/udav.ico differ
diff --git a/udav/udav.png b/udav/udav.png
new file mode 100644
index 0000000..76ba7d9
Binary files /dev/null and b/udav/udav.png differ
diff --git a/udav/udav.qrc b/udav/udav.qrc
new file mode 100644
index 0000000..a7b2237
--- /dev/null
+++ b/udav/udav.qrc
@@ -0,0 +1,67 @@
+<RCC>
+	<qresource prefix="/">
+		<file>udav.png</file>
+		<file>png/document-new.png</file>
+		<file>png/document-open.png</file>
+		<file>png/document-print.png</file>
+		<file>png/document-save.png</file>
+		<file>png/document-properties.png</file>
+		<file>png/document-export.png</file>
+		<file>png/document-import.png</file>
+		<file>png/document-revert.png</file>
+		<file>png/alpha.png</file>
+		<file>png/preferences-system.png</file>
+		<file>png/edit-clear.png</file>
+		<file>png/edit-cut.png</file>
+		<file>png/edit-copy.png</file>
+		<file>png/edit-delete.png</file>
+		<file>png/edit-paste.png</file>
+		<file>png/edit-select-all.png</file>
+		<file>png/edit-find.png</file>
+		<file>png/edit-redo.png</file>
+		<file>png/edit-undo.png</file>
+		<file>png/process-stop.png</file>
+		<file>png/zoom-out.png</file>
+		<file>png/zoom-in.png</file>
+		<file>png/zoom-original.png</file>
+		<file>png/zoom-draw.png</file>
+		<file>png/view-refresh.png</file>
+		<file>png/weather-clear.png</file>
+		<file>png/weather-clouds.png</file>
+		<file>png/help-contents.png</file>
+		<file>png/help-faq.png</file>
+		<file>png/go-first.png</file>
+		<file>png/go-last.png</file>
+		<file>png/go-previous.png</file>
+		<file>png/go-next.png</file>
+		<file>png/go-down.png</file>
+		<file>png/go-up.png</file>
+		<file>png/arrow-down.png</file>
+		<file>png/arrow-up.png</file>
+		<file>png/arrow-left.png</file>
+		<file>png/arrow-right.png</file>
+		<file>png/media-seek-backward.png</file>
+		<file>png/media-seek-forward.png</file>
+		<file>png/media-playback-start.png</file>
+		<file>png/transform-move.png</file>
+		<file>png/accessories-calculator.png</file>
+		<file>png/format-indent-more.png</file>
+		<file>png/text-csv.png</file>
+		<file>png/folder.png</file>
+		<file>png/text-plain.png</file>
+		<file>png/office-chart-line.png</file>
+		<file>png/system-file-manager.png</file>
+		<file>png/view-grid.png</file>
+		<file>png/view-fullscreen.png</file>
+		<file>png/tab-close.png</file>
+		<file>png/layer-visible-off.png</file>
+		<file>png/layer-visible-on.png</file>
+		<file>png/object-order-lower.png</file>
+		<file>png/object-order-raise.png</file>
+		<file>png/object-rotate-up.png</file>
+		<file>png/object-rotate-down.png</file>
+		<file>png/object-rotate-left.png</file>
+		<file>png/object-rotate-right.png</file>
+		<file>png/tools-wizard.png</file>
+	</qresource>
+</RCC>
diff --git a/udav/udav.rc b/udav/udav.rc
new file mode 100644
index 0000000..d12f614
--- /dev/null
+++ b/udav/udav.rc
@@ -0,0 +1 @@
+IDI_ICON1               ICON    DISCARDABLE     "udav.ico"
diff --git a/udav/udav_ru.qm b/udav/udav_ru.qm
new file mode 100644
index 0000000..7319dfd
Binary files /dev/null and b/udav/udav_ru.qm differ
diff --git a/udav/udav_ru.ts b/udav/udav_ru.ts
new file mode 100644
index 0000000..529a9fc
--- /dev/null
+++ b/udav/udav_ru.ts
@@ -0,0 +1,4425 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="ru_RU">
+<context>
+    <name>AnimParam</name>
+    <message>
+        <source>UDAV - Animation setup</source>
+        <translation>UDAV - Параметры анимации</translation>
+    </message>
+    <message>
+        <source>Redraw picture for $0 equal to</source>
+        <translation>Перерисовать для $0 равного</translation>
+    </message>
+    <message>
+        <source>strings</source>
+        <oldsource>strings in lines</oldsource>
+        <translation>строкам</translation>
+    </message>
+    <message>
+        <source>values</source>
+        <translation>числам</translation>
+    </message>
+    <message>
+        <source>from</source>
+        <translation>от</translation>
+    </message>
+    <message>
+        <source>to</source>
+        <translation>до</translation>
+    </message>
+    <message>
+        <source>with step</source>
+        <translation>с шагом</translation>
+    </message>
+    <message>
+        <source>Cancel</source>
+        <translation>Отмена</translation>
+    </message>
+    <message>
+        <source>OK</source>
+        <translation>OK</translation>
+    </message>
+    <message>
+        <source>Put to script</source>
+        <translation>Вставить в код</translation>
+    </message>
+    <message>
+        <source>Delay (in ms)</source>
+        <translation>Задержка (в мсек)</translation>
+    </message>
+    <message>
+        <source>Export to GIF</source>
+        <translation>Экспорт в GIF</translation>
+    </message>
+    <message>
+        <source>Save JPEG frames</source>
+        <translation>Сохранить кадры в JPEG</translation>
+    </message>
+    <message>
+        <source>UDAV - animation</source>
+        <translation>UDAV - анимация</translation>
+    </message>
+    <message>
+        <source>You should select one of case</source>
+        <translation>Вы должны выбрать строки или числа</translation>
+    </message>
+</context>
+<context>
+    <name>ArgsDialog</name>
+    <message>
+        <source>UDAV - Set script arguments</source>
+        <translation>UDAV - Аргументы программы</translation>
+    </message>
+    <message>
+        <source>String for $1</source>
+        <translation>Строка для $1</translation>
+    </message>
+    <message>
+        <source>String for $2</source>
+        <translation>Строка для $2</translation>
+    </message>
+    <message>
+        <source>String for $3</source>
+        <translation>Строка для $3</translation>
+    </message>
+    <message>
+        <source>String for $4</source>
+        <translation>Строка для $4</translation>
+    </message>
+    <message>
+        <source>String for $5</source>
+        <translation>Строка для $5</translation>
+    </message>
+    <message>
+        <source>String for $6</source>
+        <translation>Строка для $6</translation>
+    </message>
+    <message>
+        <source>String for $7</source>
+        <translation>Строка для $7</translation>
+    </message>
+    <message>
+        <source>String for $8</source>
+        <translation>Строка для $8</translation>
+    </message>
+    <message>
+        <source>String for $9</source>
+        <translation>Строка для $9</translation>
+    </message>
+    <message>
+        <source>String for $0</source>
+        <translation>Строка для $0</translation>
+    </message>
+    <message>
+        <source>Cancel</source>
+        <translation>Отмена</translation>
+    </message>
+    <message>
+        <source>OK</source>
+        <translation>OK</translation>
+    </message>
+</context>
+<context>
+    <name>CalcDialog</name>
+    <message>
+        <source>Result</source>
+        <translation>Результат</translation>
+    </message>
+    <message>
+        <source>To script</source>
+        <translation>В код</translation>
+    </message>
+    <message>
+        <source>Clear</source>
+        <translation>Очистить</translation>
+    </message>
+    <message>
+        <source>Put function</source>
+        <translation>Вставить функцию</translation>
+    </message>
+    <message>
+        <source>Basic</source>
+        <translation>Базовые</translation>
+    </message>
+    <message>
+        <source>Exp and log</source>
+        <translation>Exp и log</translation>
+    </message>
+    <message>
+        <source>Trigonometric</source>
+        <translation>Тригонометрические</translation>
+    </message>
+    <message>
+        <source>Hyperbolic</source>
+        <translation>Гиперболические</translation>
+    </message>
+    <message>
+        <source>Bessel</source>
+        <translation>Бесселя</translation>
+    </message>
+    <message>
+        <source>Elliptic</source>
+        <translation>Эллиптические</translation>
+    </message>
+    <message>
+        <source>Jacobi</source>
+        <translation>Якоби</translation>
+    </message>
+    <message>
+        <source>Airy and Gamma</source>
+        <translation>Airy и Gamma</translation>
+    </message>
+    <message>
+        <source>Exp-integrals</source>
+        <translation>Exp-интегралы</translation>
+    </message>
+    <message>
+        <source>Special</source>
+        <translation>Специальные</translation>
+    </message>
+</context>
+<context>
+    <name>DatPanel</name>
+    <message>
+        <source>&Data</source>
+        <translation>&Данные</translation>
+    </message>
+    <message>
+        <source> - UDAV variable</source>
+        <translation> - UDAV переменная</translation>
+    </message>
+    <message>
+        <source> - UDAV preview</source>
+        <translation> - UDAV просмотр</translation>
+    </message>
+    <message>
+        <source>UDAV - Import PNG</source>
+        <translation>UDAV - Импорт PNG</translation>
+    </message>
+    <message>
+        <source>Data files (*.dat)
+All files (*.*)</source>
+        <translation>Файлы данных (*.dat)
+Все файлы (*.*)</translation>
+    </message>
+    <message>
+        <source>UDAV - Export to PNG</source>
+        <translation>UDAV - Экспорт в PNG</translation>
+    </message>
+    <message>
+        <source>Enter color scheme for picture.
+Note that data will be normalized in range [0,1].</source>
+        <translation>Введите цветовую схему рисунка.
+Данные будут нормированы в [0,1].</translation>
+    </message>
+    <message>
+        <source>PNG files (*.png)
+All files (*.*)</source>
+        <translation>PNG файлы (*.png)
+Все файлы (*.*)</translation>
+    </message>
+    <message>
+        <source>Enter color scheme for picture</source>
+        <translation>Введите цветовую схему рисунка</translation>
+    </message>
+    <message>
+        <source>UDAV - Save data</source>
+        <translation>UDAV - Сохранить данные</translation>
+    </message>
+    <message>
+        <source>UDAV - Load data</source>
+        <translation>UDAV - Загрузить данные</translation>
+    </message>
+    <message>
+        <source>UDAV - Fill data</source>
+        <translation>UDAV - Заполнить данные</translation>
+    </message>
+    <message>
+        <source>Enter formula for data filling.
+Note that variables x,y,z supposed to be in range [0,1].</source>
+        <translation>Введите формулу для данных.
+Переменные x,y,z меняются в интервале [0,1].</translation>
+    </message>
+    <message>
+        <source>Enter range for data and direction of filling</source>
+        <translation>Введите диапазон и направление заполнения</translation>
+    </message>
+    <message>
+        <source>From</source>
+        <translation>От</translation>
+    </message>
+    <message>
+        <source>To</source>
+        <translation>До</translation>
+    </message>
+    <message>
+        <source>Direction</source>
+        <translation>Направление</translation>
+    </message>
+    <message>
+        <source>UDAV - Normalize data</source>
+        <translation>UDAV - Нормировать данные</translation>
+    </message>
+    <message>
+        <source>Enter range for final data</source>
+        <translation>Введите диапазон результата</translation>
+    </message>
+    <message>
+        <source>Symmetrical?</source>
+        <translation>Симметрично?</translation>
+    </message>
+    <message>
+        <source>UDAV - Normalize by slice</source>
+        <translation>UDAV - Нормировать по срезам</translation>
+    </message>
+    <message>
+        <source>UDAV - Clear data</source>
+        <translation>UDAV - Очистить данные</translation>
+    </message>
+    <message>
+        <source>Enter new data sizes</source>
+        <translation>Введите новые размеры</translation>
+    </message>
+    <message>
+        <source>X-size</source>
+        <translation>Размер по X</translation>
+    </message>
+    <message>
+        <source>Y-size</source>
+        <translation>Размер по Y</translation>
+    </message>
+    <message>
+        <source>Z-size</source>
+        <translation>Размер по Z</translation>
+    </message>
+    <message>
+        <source>UDAV - Resize data</source>
+        <translation>UDAV - Изменить размер данных</translation>
+    </message>
+    <message>
+        <source>UDAV - Squeeze data</source>
+        <translation>UDAV - Сжать данные</translation>
+    </message>
+    <message>
+        <source>Enter step of saved points. For example, '1' save all, '2' save each 2nd point, '3' save each 3d and so on.</source>
+        <translation>Введите шаг сохраняемых точек. Например, '1' сохранить все, '2' каждую вторую точку, '3' каждую третью и т.д.</translation>
+    </message>
+    <message>
+        <source>X-direction</source>
+        <translation>X направление</translation>
+    </message>
+    <message>
+        <source>Y-direction</source>
+        <translation>Y направление</translation>
+    </message>
+    <message>
+        <source>Z-direction</source>
+        <translation>Z направление</translation>
+    </message>
+    <message>
+        <source>UDAV - Crop data</source>
+        <translation>UDAV - Обрезать данные</translation>
+    </message>
+    <message>
+        <source>Enter range of saved date.</source>
+        <translation>Введите интервал сохраняемых данных.</translation>
+    </message>
+    <message>
+        <source>UDAV - Rearrange data</source>
+        <translation>UDAV - Поменять размеры данных</translation>
+    </message>
+    <message>
+        <source>UDAV - Transpose data</source>
+        <translation>UDAV - Транспонировать данные</translation>
+    </message>
+    <message>
+        <source>Enter new order of dimensions.
+For example, 'yx' or 'yxz' for transpose x-y, 'zyx' for transposing x-z and so on.</source>
+        <translation>Введите новый порядок размерностей.
+Например, 'yx' или 'yxz' для транспонирования x-y, 'zyx' для транспонирования x-z и т.д.</translation>
+    </message>
+    <message>
+        <source>UDAV - Smooth data</source>
+        <translation>UDAV - Сгладить данные</translation>
+    </message>
+    <message>
+        <source>Enter direction(s) for smoothing.
+Optionally you may enter the kind of smoothing by 3 or by 5 points. For example 'xy3' - smooth only in x and y directions and use 3-points scheme.</source>
+        <translation>Введите направление(я) сглаживания.
+Можно также ввести тип сглаживания по 3 или по 5 точкам. Например 'xy3' - сгладит только в x и y направлениях по 3-точечной схеме.</translation>
+    </message>
+    <message>
+        <source>UDAV - Summarize data</source>
+        <translation>UDAV - Суммировать данные</translation>
+    </message>
+    <message>
+        <source>Enter direction(s) for cumulative summation.
+For example 'xy' - summate along x and y directions.</source>
+        <translation>Введите направление(я) для суммирования.
+Например 'xy' - суммировать вдоль x и y направлений.</translation>
+    </message>
+    <message>
+        <source>UDAV - Integrate data</source>
+        <translation>UDAV - Интегрировать данные</translation>
+    </message>
+    <message>
+        <source>Enter direction(s) for integration.
+For example 'xy' - integrate along x and y directions.</source>
+        <translation>Введите направление(я) для инткгрирования.
+Например 'xy' - интегрировать вдоль x и y направлений.</translation>
+    </message>
+    <message>
+        <source>UDAV - Differentiate data</source>
+        <translation>UDAV - Дифференцировать данные</translation>
+    </message>
+    <message>
+        <source>Enter direction(s) for differentiation.
+For example 'xy' - differentiate along x and y directions.</source>
+        <translation>Введите направление(я) для дифференцирования.
+Например 'xy' - дифференцировать вдоль x и y направлений.</translation>
+    </message>
+    <message>
+        <source>UDAV - Laplace transform</source>
+        <translation>UDAV - Преобразование Лапласа</translation>
+    </message>
+    <message>
+        <source>Enter direction(s) for laplace transform.
+For example 'xy' - do transform along x and y directions.</source>
+        <translation>Введите направление(я) для преобразования Лапласа.
+Например 'xy' - преобразовать вдоль x и y направлений.</translation>
+    </message>
+    <message>
+        <source>UDAV - Swap data</source>
+        <translation>UDAV - Поменять местами</translation>
+    </message>
+    <message>
+        <source>Enter direction(s) for swapping (exchange left and right parts).
+For example 'xy' - swap along x and y directions. Useful for Fourier spectrum.</source>
+        <translation>Введите направление(я) для обмена левой и правой частями данных.
+Например 'xy' - меняет вдоль x и y направлений. Полезно для Фурье спектров.</translation>
+    </message>
+    <message>
+        <source>UDAV - Mirror data</source>
+        <translation>UDAV - Отразить данные</translation>
+    </message>
+    <message>
+        <source>Enter direction(s) for mirroring.
+For example 'xy' - mirror along x and y directions.</source>
+        <translation>Введите направление(я) для отражения.
+Например 'xy' - отразить по x и y направлениям.</translation>
+    </message>
+    <message>
+        <source>UDAV - Sum along ...</source>
+        <translation>UDAV - Сумма по ...</translation>
+    </message>
+    <message>
+        <source>Specify direction(s) of summation</source>
+        <translation>Введите направление(я) суммирования</translation>
+    </message>
+    <message>
+        <source>UDAV - Max along ...</source>
+        <translation>UDAV - Максимум по ...</translation>
+    </message>
+    <message>
+        <source>Specify direction(s) of maximal values</source>
+        <translation>Введите направление(я) поиска максимумов</translation>
+    </message>
+    <message>
+        <source>UDAV - Min along ...</source>
+        <translation>UDAV - Минимум по ...</translation>
+    </message>
+    <message>
+        <source>Specify direction(s) of minimal values</source>
+        <translation>Введите направление(я) поиска минимумов</translation>
+    </message>
+    <message>
+        <source>UDAV - Momentum along 'x'</source>
+        <translation>UDAV - Момент по 'x'</translation>
+    </message>
+    <message>
+        <source>Specify which momentum evaluate.
+The momentum is res_i = sum_jk how(x_i,y_j,z_k) a_jk/ sum_jk a_jk.
+Coordinates x, y, z are data indexes normalized in range [0,1].</source>
+        <translation>Укажите какой момент вычислять.
+Момент равен res_i = Σ_jk how(x_i,y_j,z_k) a_jk/ Σ_jk a_jk.
+Координаты x, y, z находятся в диапазоне [0,1].</translation>
+    </message>
+    <message>
+        <source>UDAV - Momentum along 'y'</source>
+        <translation>UDAV - Момент по 'y'</translation>
+    </message>
+    <message>
+        <source>Specify which momentum evaluate.
+The momentum is res_j = sum_ik how(x_i,y_j,z_k) a_ik/ sum_ik a_ik.
+Coordinates x, y, z are data indexes normalized in range [0,1].</source>
+        <translation>Укажите какой момент вычислять.
+Момент равен res_j = Σ_ik how(x_i,y_j,z_k) a_ik/ Σ_ik a_ik.
+Координаты x, y, z находятся в диапазоне [0,1].</translation>
+    </message>
+    <message>
+        <source>UDAV - Momentum along 'z'</source>
+        <translation>UDAV - Момент по 'z'</translation>
+    </message>
+    <message>
+        <source>Specify which momentum evaluate.
+The momentum is res_k = sum_ij how(x_i,y_j,z_k) a_ij/ sum_ij a_ij.
+Coordinates x, y, z are data indexes normalized in range [0,1].</source>
+        <translation>Укажите какой момент вычислять.
+Момент равен res_k = Σ_ij how(x_i,y_j,z_k) a_ij/ Σ_ij a_ij.
+Координаты x, y, z находятся в диапазоне [0,1].</translation>
+    </message>
+    <message>
+        <source>UDAV - Make histogram</source>
+        <translation>UDAV - Найти гистограмму</translation>
+    </message>
+    <message>
+        <source>Number of points</source>
+        <translation>Число точек</translation>
+    </message>
+    <message>
+        <source>Put in variable</source>
+        <translation>Поместить в переменную</translation>
+    </message>
+    <message>
+        <source>Cancel</source>
+        <translation>Отмена</translation>
+    </message>
+    <message>
+        <source>OK</source>
+        <translation>OK</translation>
+    </message>
+    <message>
+        <source>UDAV - Change data</source>
+        <translation>UDAV - Изменить данные</translation>
+    </message>
+    <message>
+        <source>Enter number for adding to data elements:</source>
+        <translation>Введите число для добавления к элементам массива:</translation>
+    </message>
+    <message>
+        <source>Enter number for subtraction from data elements:</source>
+        <translation>Введите число для вычитания из элементов массива:</translation>
+    </message>
+    <message>
+        <source>Enter number for division of data elements:</source>
+        <translation>Введите число для деления элементов массива:</translation>
+    </message>
+    <message>
+        <source>Enter number for multiplication of data elements:</source>
+        <translation>Введите число для умножения элементов массива:</translation>
+    </message>
+    <message>
+        <source>UDAV - Go to slice</source>
+        <translation>UDAV - Перейти к срезу</translation>
+    </message>
+    <message>
+        <source>Enter slice id:</source>
+        <translation>Введите номер среза:</translation>
+    </message>
+    <message>
+        <source>NOTE: All fields must be filled!</source>
+        <translation>Все поля должны быть заполнены!</translation>
+    </message>
+    <message>
+        <source>Enter the name for new variable</source>
+        <translation>Введите имя новой переменной</translation>
+    </message>
+    <message>
+        <source>&File</source>
+        <translation>&Файл</translation>
+    </message>
+    <message>
+        <source>&Load data</source>
+        <translation>&Загрузить данные</translation>
+    </message>
+    <message>
+        <source>Load data from file. Data will be deleted only
+at exit but UDAV will not ask to save it.</source>
+        <translation>Загрузить данные из файла. Данные будут удалены при
+выходе, но UDAV не спросит об их сохранении.</translation>
+    </message>
+    <message>
+        <source>&Import PNG</source>
+        <translation>&Импорт PNG</translation>
+    </message>
+    <message>
+        <source>Import data from PNG picture with specified color scheme.
+Data will be deleted only at exit but UDAV will not ask it saving.</source>
+        <translation>Импортировать данные из PNG рисунка с заданной цветовой схемой.
+Данные будут удалены при выходе, но UDAV не спросит об их сохранении.</translation>
+    </message>
+    <message>
+        <source>&Save data</source>
+        <translation>Сохранить &данные</translation>
+    </message>
+    <message>
+        <source>Save data to tab-separeted file.</source>
+        <translation>Сохранить данные в текстовый файл с разделителем табуляцией.</translation>
+    </message>
+    <message>
+        <source>&Export PNG</source>
+        <translation>&Экспорт PNG</translation>
+    </message>
+    <message>
+        <source>Export data to PNG picture. The colors defined by 
+specified color scheme. The same as in 'dens' command.</source>
+        <translation>Экспортирует данные в PNG рисунок. Цвета определяются
+указанной цветовой схемой. Рисунок аналогичен команде 'dens'.</translation>
+    </message>
+    <message>
+        <source>Plot &data</source>
+        <translation>&Отобразить данные</translation>
+    </message>
+    <message>
+        <source>Plot data in new script window. You may select the kind
+of plot, its style and so on.</source>
+        <translation>Отобразить данные в новом окне. Вы можете
+выбрать тип графика, его стиль и т.д.</translation>
+    </message>
+    <message>
+        <source>Copy &data</source>
+        <translation>Копировать &данные</translation>
+    </message>
+    <message>
+        <source>Copy range of numbers to clipboard.</source>
+        <translation>Копировать диапазон чисел в буфер обмена.</translation>
+    </message>
+    <message>
+        <source>Paste &data</source>
+        <translation>Вставить &данные</translation>
+    </message>
+    <message>
+        <source>Paste range of numbers from clipboard.</source>
+        <translation>Вставить диапазон чисел из буфера обмена.</translation>
+    </message>
+    <message>
+        <source>&Navigate</source>
+        <translation>Пере&ход</translation>
+    </message>
+    <message>
+        <source>&First slice</source>
+        <translation>&Первый срез</translation>
+    </message>
+    <message>
+        <source>Go to the first data slice for 3D data.</source>
+        <translation>Перейти к первому срезу 3D данных.</translation>
+    </message>
+    <message>
+        <source>&Prev. slice</source>
+        <translation>&Предыдущий срез</translation>
+    </message>
+    <message>
+        <source>Go to the previous data slice for 3D data.</source>
+        <translation>Перейти к предыдущему срезу 3D данных.</translation>
+    </message>
+    <message>
+        <source>Go to the specified data slice for 3D data.</source>
+        <translation>Перейти к указанному срезу 3D данных.</translation>
+    </message>
+    <message>
+        <source>Go to slice</source>
+        <translation>Перейти к срезу</translation>
+    </message>
+    <message>
+        <source>Next slice</source>
+        <translation>Следующий срез</translation>
+    </message>
+    <message>
+        <source>Go to the next data slice for 3D data.</source>
+        <translation>Перейти к следующему срезу 3D данных.</translation>
+    </message>
+    <message>
+        <source>Last slice</source>
+        <translation>Последний срез</translation>
+    </message>
+    <message>
+        <source>Go to the last data slice for 3D data.</source>
+        <translation>Перейти к последнему срезу 3D данных.</translation>
+    </message>
+    <message>
+        <source>&Sizes</source>
+        <translation>&Размеры</translation>
+    </message>
+    <message>
+        <source>&Create new</source>
+        <translation>&Создать новые</translation>
+    </message>
+    <message>
+        <source>Recreate the data with new sizes and fill it by zeros (Ctrl+N).</source>
+        <translation>Создает заново данные нового размера и заполняет их нулями (Ctrl+N).</translation>
+    </message>
+    <message>
+        <source>&Resize</source>
+        <translation>&Изменить размер</translation>
+    </message>
+    <message>
+        <source>Resize (interpolate) the data to specified sizes (Ctrl+R).</source>
+        <translation>Изменяет размер (интерполирует) данных в указанному (Ctrl+R).</translation>
+    </message>
+    <message>
+        <source>&Squeeze</source>
+        <translation>С&жать</translation>
+    </message>
+    <message>
+        <source>Keep only each n-th element of the data array.</source>
+        <translation>Сохраняет каждый n-ый элемент массива данных.</translation>
+    </message>
+    <message>
+        <source>Cro&p</source>
+        <translation>О&брезать</translation>
+    </message>
+    <message>
+        <source>Crop the data edges. Useful to cut off the zero-filled area.</source>
+        <translation>Обрезает края данных. Полезно для удаления заполненных нулями областей.</translation>
+    </message>
+    <message>
+        <source>&Transpose</source>
+        <translation>&Транспонировать</translation>
+    </message>
+    <message>
+        <source>Transpose data dimensions, like x<->y or x<->z and so on.</source>
+        <translation>Транспонирует массив данных, типа x<->y или x<->z и т.д.</translation>
+    </message>
+    <message>
+        <source>Re&arrange</source>
+        <translation>По&менять размеры</translation>
+    </message>
+    <message>
+        <source>Rearrange data sizes without changing data values.</source>
+        <translation>Меняет размеры данных без изменения самого массива данных.</translation>
+    </message>
+    <message>
+        <source>&Modify</source>
+        <translation>&Изменить</translation>
+    </message>
+    <message>
+        <source>By &formula</source>
+        <translation>По &формуле</translation>
+    </message>
+    <message>
+        <source>Change data values according to formula depended on 'x', 'y' and 'z'
+variables. A set of special function is availible also.</source>
+        <translation>Изменяет данные по формуле, зависяещей от переменных 'x', 'y' и 'z'.
+Поддерживаются также многие специальные функции.</translation>
+    </message>
+    <message>
+        <source>Fill in &range</source>
+        <translation>&Распределить</translation>
+    </message>
+    <message>
+        <source>Fill data equidistantly from one value to another.</source>
+        <translation>Распределить равномерно данные от одного значения до другого.</translation>
+    </message>
+    <message>
+        <source>&Normalize</source>
+        <translation>&Нормировать</translation>
+    </message>
+    <message>
+        <source>Normalize data so that its minimal
+and maximal values be in specified range.</source>
+        <translation>Нормирует данные так, что их максимальное и
+минимальное значения равны заданным.</translation>
+    </message>
+    <message>
+        <source>Norm. s&lices</source>
+        <translation>Норм. по &срезам</translation>
+    </message>
+    <message>
+        <source>Normalize each data slice perpendicular to some direction
+so that its minimal and maximal values be in specified range.</source>
+        <translation>Нормирует данные по срезам перпендикулярно 
+заданному направлению так, что их максимальное
+и минимальное значения равны заданным.</translation>
+    </message>
+    <message>
+        <source>&Smooth data</source>
+        <translation>С&гладить</translation>
+    </message>
+    <message>
+        <source>Smooth data by one of 4 methods along specified direction(s).</source>
+        <translation>Сглаживает данные одним из 4-х методов вдоль заданного направления(ий).</translation>
+    </message>
+    <message>
+        <source>&Operators</source>
+        <translation>&Опраторы</translation>
+    </message>
+    <message>
+        <source>&Cum. sum</source>
+        <translation>&Суммировать</translation>
+    </message>
+    <message>
+        <source>Summate data values along specified direction(s).</source>
+        <translation>Суммирует данные вдоль указанного направления(ий).</translation>
+    </message>
+    <message>
+        <source>&Integrate</source>
+        <translation>&Интегрировать</translation>
+    </message>
+    <message>
+        <source>Integrate data values along specified direction(s).</source>
+        <translation>Интегрирует данные по заданному направлению(ям).</translation>
+    </message>
+    <message>
+        <source>&Differentiate</source>
+        <translation>&Дифференцировать</translation>
+    </message>
+    <message>
+        <source>Differentiate data values along specified direction(s).</source>
+        <translation>Дифференцирует данные по заданному направлению(ям).</translation>
+    </message>
+    <message>
+        <source>&Laplace</source>
+        <translation>&Лаплас</translation>
+    </message>
+    <message>
+        <source>Double differentiate data values along specified direction(s).</source>
+        <translation>Дважды дифференцирует данные по заданному направлению(ям).</translation>
+    </message>
+    <message>
+        <source>&Swap</source>
+        <translation>&Поменять местами</translation>
+    </message>
+    <message>
+        <source>Swap left and right data part along specified direction(s).
+This operation is useful for data after Fourier transform.</source>
+        <translation>Меняет местами левую и правую часть данных вдоль указанного направления(ий).
+Операция полезна для данных после Фурье преобразования.</translation>
+    </message>
+    <message>
+        <source>&Mirror</source>
+        <translation>&Отразить</translation>
+    </message>
+    <message>
+        <source>Mirror left and right data part along specified direction(s).
+This operation do like index change from 'i' to 'n-i'.</source>
+        <translation>Отражает данные относительно указанного направления(ий).
+Действует как замена индекса 'i' на 'n-i'.</translation>
+    </message>
+    <message>
+        <source>&Algebraic</source>
+        <translation>&Алгебраические</translation>
+    </message>
+    <message>
+        <source>&Add</source>
+        <translation>&Добавить</translation>
+    </message>
+    <message>
+        <source>Add a number to all data values.</source>
+        <translation>Добавляет число к элементам массива данных.</translation>
+    </message>
+    <message>
+        <source>&Subtract</source>
+        <translation>&Вычесть</translation>
+    </message>
+    <message>
+        <source>Subtract a number to all data values.</source>
+        <translation>Вычитает из элементов массива данных число.</translation>
+    </message>
+    <message>
+        <source>&Multiply</source>
+        <translation>&Умножить</translation>
+    </message>
+    <message>
+        <source>Multiply all data values by a number.</source>
+        <translation>Умножает элементы массива данных на число.</translation>
+    </message>
+    <message>
+        <source>&Divide</source>
+        <translation>&Разделить</translation>
+    </message>
+    <message>
+        <source>Divide all data values by a number.</source>
+        <translation>Делит элементы массива данных на число.</translation>
+    </message>
+    <message>
+        <source>A&nother data</source>
+        <translation>&Новые данные</translation>
+    </message>
+    <message>
+        <source>&Sum of</source>
+        <translation>&Сумма по</translation>
+    </message>
+    <message>
+        <source>M&in of</source>
+        <translation>М&инимум по</translation>
+    </message>
+    <message>
+        <source>M&ax of</source>
+        <translation>М&аксимум по</translation>
+    </message>
+    <message>
+        <source>Momentum along &x</source>
+        <translation>Момент вдоль &x</translation>
+    </message>
+    <message>
+        <source>Momentum along &y</source>
+        <translation>Момент вдоль &y</translation>
+    </message>
+    <message>
+        <source>Momentum along &z</source>
+        <translation>Момент вдоль &z</translation>
+    </message>
+    <message>
+        <source>&Histogram</source>
+        <translation>&Гистограмма</translation>
+    </message>
+</context>
+<context>
+    <name>DataOpenDialog</name>
+    <message>
+        <source>UDAV - Open data file</source>
+        <translation>UDAV - Открыть файл данных</translation>
+    </message>
+    <message>
+        <source>Data name</source>
+        <translation>Имя данных</translation>
+    </message>
+    <message>
+        <source>Auto detect data sizes</source>
+        <translation>Автом. определение размеров</translation>
+    </message>
+    <message>
+        <source>Set data sizes manually</source>
+        <translation>Задать размеры вручную</translation>
+    </message>
+    <message>
+        <source>Nx</source>
+        <translation>Nx</translation>
+    </message>
+    <message>
+        <source>Ny</source>
+        <translation>Ny</translation>
+    </message>
+    <message>
+        <source>Nz</source>
+        <translation>Nz</translation>
+    </message>
+    <message>
+        <source>Matrix with sizes from file</source>
+        <translation>Матрица с размерами из файла</translation>
+    </message>
+    <message>
+        <source>3D data with sizes from file</source>
+        <translation>3D данные с размерами из файла</translation>
+    </message>
+    <message>
+        <source>Cancel</source>
+        <translation>Отмена</translation>
+    </message>
+    <message>
+        <source>OK</source>
+        <translation>OK</translation>
+    </message>
+    <message>
+        <source>Auto detect data sizes (%1 x %2 x %3)</source>
+        <translation>Определить размер автоматически (%1 x %2 x %3)</translation>
+    </message>
+    <message>
+        <source>default</source>
+        <translation>по умолчанию</translation>
+    </message>
+    <message>
+        <source>UDAV - Insert filename</source>
+        <translation>UDAV - Вставить имя файла</translation>
+    </message>
+    <message>
+        <source>MGL files (*.mgl)</source>
+        <translation>Файлы MGL (*.mgl)</translation>
+    </message>
+    <message>
+        <source>Template</source>
+        <translation>Шаблон</translation>
+    </message>
+</context>
+<context>
+    <name>FilesDialog</name>
+    <message>
+        <source>UDAV - Set script arguments</source>
+        <translation type="obsolete">UDAV - Аргументы программы</translation>
+    </message>
+    <message>
+        <source>String for %1</source>
+        <translation>Строка для %1</translation>
+    </message>
+    <message>
+        <source>String for %2</source>
+        <translation>Строка для %2</translation>
+    </message>
+    <message>
+        <source>String for %3</source>
+        <translation>Строка для %3</translation>
+    </message>
+    <message>
+        <source>String for %4</source>
+        <translation>Строка для %4</translation>
+    </message>
+    <message>
+        <source>String for %5</source>
+        <translation>Строка для %5</translation>
+    </message>
+    <message>
+        <source>String for %6</source>
+        <translation>Строка для %6</translation>
+    </message>
+    <message>
+        <source>String for %7</source>
+        <translation>Строка для %7</translation>
+    </message>
+    <message>
+        <source>String for %8</source>
+        <translation>Строка для %8</translation>
+    </message>
+    <message>
+        <source>String for %9</source>
+        <translation>Строка для %9</translation>
+    </message>
+    <message>
+        <source>Cancel</source>
+        <translation>Отмена</translation>
+    </message>
+    <message>
+        <source>OK</source>
+        <translation>OK</translation>
+    </message>
+    <message>
+        <source>UDAV - Set template parameters</source>
+        <translation>UDAV - Параметры шаблона</translation>
+    </message>
+</context>
+<context>
+    <name>FindDialog</name>
+    <message>
+        <source>UDAV - Find</source>
+        <translation>UDAV - Найти</translation>
+    </message>
+    <message>
+        <source>Find &what:</source>
+        <translation>&Что найти:</translation>
+    </message>
+    <message>
+        <source>Replace &by:</source>
+        <translation>З&аменить на:</translation>
+    </message>
+    <message>
+        <source>Match &case</source>
+        <translation>Учитывать &регистр</translation>
+    </message>
+    <message>
+        <source>Search &backward</source>
+        <translation>Искать на&зад</translation>
+    </message>
+    <message>
+        <source>&Find</source>
+        <translation>&Найти</translation>
+    </message>
+    <message>
+        <source>&Replace</source>
+        <translation>&Заменить</translation>
+    </message>
+    <message>
+        <source>Close</source>
+        <translation>Закрыть</translation>
+    </message>
+</context>
+<context>
+    <name>GraphWindow</name>
+    <message>
+        <source>Printing...</source>
+        <translation type="obsolete">Печатаю...</translation>
+    </message>
+    <message>
+        <source>Printing completed</source>
+        <translation type="obsolete">Печать завершена</translation>
+    </message>
+    <message>
+        <source>Printing aborted</source>
+        <translation type="obsolete">Печать прервана</translation>
+    </message>
+    <message>
+        <source>Drawing time %1 ms</source>
+        <translation type="obsolete">Время рисования %1 мсек</translation>
+    </message>
+    <message>
+        <source>Frame %1 of %2</source>
+        <translation type="obsolete">Кадр %1 из %2</translation>
+    </message>
+    <message>
+        <source>Graphics</source>
+        <translation type="obsolete">График</translation>
+    </message>
+    <message>
+        <source>&Graphics</source>
+        <translation type="obsolete">&График</translation>
+    </message>
+    <message>
+        <source>&Alpha</source>
+        <translation type="obsolete">&Прозрачность</translation>
+    </message>
+    <message>
+        <source>Switch on/off transparency for the graphics (Alt+T).</source>
+        <translation type="obsolete">Включить/выключить прозрачность графика (Alt+T).</translation>
+    </message>
+    <message>
+        <source>&Light</source>
+        <translation type="obsolete">&Освещение</translation>
+    </message>
+    <message>
+        <source>Switch on/off lightning for the graphics (Alt+L).</source>
+        <translation type="obsolete">Включить/выключить освещение графика (Alt+L).</translation>
+    </message>
+    <message>
+        <source>&Grid</source>
+        <translation type="obsolete">&Сетка</translation>
+    </message>
+    <message>
+        <source>Switch on/off grid drawing for absolute coordinates (Alt+G).</source>
+        <translation type="obsolete">Включить/выключить сетку абсолютных координат (Alt+G).</translation>
+    </message>
+    <message>
+        <source>&Rotate by mouse</source>
+        <translation type="obsolete">&Вращать мышкой</translation>
+    </message>
+    <message>
+        <source>Switch on/off mouse handling of the graphics
+(rotation, shifting, zooming and perspective).</source>
+        <translation type="obsolete">Включить/выключить изменение графика мышью
+(вращение, сдвиг, приближение и перспектива).</translation>
+    </message>
+    <message>
+        <source>&Zoom by mouse</source>
+        <translation type="obsolete">&Приближение мышью</translation>
+    </message>
+    <message>
+        <source>Switch on/off mouse zoom of selected region.</source>
+        <translation type="obsolete">Включить/выключить приближение выбранного региона.</translation>
+    </message>
+    <message>
+        <source>Res&tore</source>
+        <translation type="obsolete">В&осстановить</translation>
+    </message>
+    <message>
+        <source>Restore default graphics rotation, zoom and perspective (Alt+Space).</source>
+        <translation type="obsolete">Восстановить вращение, масштаб и перспективу по умолчанию (Alt+Space).</translation>
+    </message>
+    <message>
+        <source>Re&draw</source>
+        <translation type="obsolete">Пе&рерисовать</translation>
+    </message>
+    <message>
+        <source>Execute script and redraw graphics (F5).</source>
+        <translation type="obsolete">Выполнить код и перерисовать график (F5).</translation>
+    </message>
+    <message>
+        <source>&Adjust size</source>
+        <translation type="obsolete">&Подобрать размер</translation>
+    </message>
+    <message>
+        <source>Change canvas size to fill whole region (F6).</source>
+        <translation type="obsolete">Изменить размер рисунка так, чтобы он заполнял всю область (F6).</translation>
+    </message>
+    <message>
+        <source>Re&load</source>
+        <translation type="obsolete">Пере&грузить</translation>
+    </message>
+    <message>
+        <source>Restore status for 'once' command and reload data (F9).</source>
+        <translation type="obsolete">Восстановить статус команды 'once' и перегрузить данные (F9).</translation>
+    </message>
+    <message>
+        <source>&Stop</source>
+        <translation type="obsolete">&Остановить</translation>
+    </message>
+    <message>
+        <source>Stop script execution (F7).</source>
+        <translation type="obsolete">Остановить выполенение кода (F7).</translation>
+    </message>
+    <message>
+        <source>&Copy plot</source>
+        <translation type="obsolete">&Копировать график</translation>
+    </message>
+    <message>
+        <source>Copy graphics to clipboard (Ctrl+Shift+C).</source>
+        <translation type="obsolete">Копировать график в буфер обмена (Ctrl+Shift+C).</translation>
+    </message>
+    <message>
+        <source>Set value of \theta angle.</source>
+        <translation type="obsolete">Установить значение угла \theta.</translation>
+    </message>
+    <message>
+        <source>Set value of \phi angle.</source>
+        <translation type="obsolete">Установить значение угла \phi.</translation>
+    </message>
+    <message>
+        <source>&Export as ...</source>
+        <translation type="obsolete">&Экспорт в ...</translation>
+    </message>
+    <message>
+        <source>bitmap EPS</source>
+        <translation type="obsolete">растровый EPS</translation>
+    </message>
+    <message>
+        <source>vector EPS</source>
+        <translation type="obsolete">векторный EPS</translation>
+    </message>
+    <message>
+        <source>Zoom/move</source>
+        <translation type="obsolete">Масштаб/сдвиг</translation>
+    </message>
+    <message>
+        <source>Zoom graphics</source>
+        <translation type="obsolete">Приближение графика</translation>
+    </message>
+    <message>
+        <source>Move &left</source>
+        <translation type="obsolete">Сдвиг в&лево</translation>
+    </message>
+    <message>
+        <source>Move graphics left by 1/3 of its width.</source>
+        <translation type="obsolete">Сдвиг графика влево на 1/3 его ширины.</translation>
+    </message>
+    <message>
+        <source>Move &up</source>
+        <translation type="obsolete">Сдвиг &вверх</translation>
+    </message>
+    <message>
+        <source>Move graphics up by 1/3 of its height.</source>
+        <translation type="obsolete">Сдвиг графика вверх на 1/3 его высоты.</translation>
+    </message>
+    <message>
+        <source>Zoom &in</source>
+        <translation type="obsolete">&Приблизить</translation>
+    </message>
+    <message>
+        <source>Zoom in graphics.</source>
+        <translation type="obsolete">Приблизить график.</translation>
+    </message>
+    <message>
+        <source>Zoom &out</source>
+        <translation type="obsolete">&Отдалить</translation>
+    </message>
+    <message>
+        <source>Zoom out graphics.</source>
+        <translation type="obsolete">Отдалить график.</translation>
+    </message>
+    <message>
+        <source>Move &down</source>
+        <translation type="obsolete">Сдвиг в&низ</translation>
+    </message>
+    <message>
+        <source>Move graphics up down 1/3 of its height.</source>
+        <translation type="obsolete">Сдвиг графика вниз на 1/3 его высоты.</translation>
+    </message>
+    <message>
+        <source>Move &right</source>
+        <translation type="obsolete">Сдвиг вп&раво</translation>
+    </message>
+    <message>
+        <source>Move graphics right by 1/3 of its width.</source>
+        <translation type="obsolete">Сдвиг графика вправо на 1/3 его ширины.</translation>
+    </message>
+    <message>
+        <source>&Animation</source>
+        <translation type="obsolete">&Анимация</translation>
+    </message>
+    <message>
+        <source>Animation</source>
+        <translation type="obsolete">Анимация</translation>
+    </message>
+    <message>
+        <source>&Next slide</source>
+        <translation type="obsolete">&Следующий кадр</translation>
+    </message>
+    <message>
+        <source>Show next slide (Alt+Right).</source>
+        <translation type="obsolete">Показать следующий кадр (Alt+Right).</translation>
+    </message>
+    <message>
+        <source>&Prev slide</source>
+        <translation type="obsolete">&Предыдущий кадр</translation>
+    </message>
+    <message>
+        <source>Show previous slide (Alt+Left).</source>
+        <translation type="obsolete">Показать предыдущий кадр (Alt+Left).</translation>
+    </message>
+    <message>
+        <source>&Slideshow</source>
+        <translation type="obsolete">&Запустить</translation>
+    </message>
+    <message>
+        <source>Run slideshow (Ctrl+F5). If no parameter specified
+then the dialog with slideshow options will appear.</source>
+        <translation type="obsolete">Запустить анимацию (Ctrl+F5). Если параметры не были указаны,
+то показывается диалог с параметрами анимации.</translation>
+    </message>
+    <message>
+        <source>Se&tup show</source>
+        <translation type="obsolete">&Настроить анимацию</translation>
+    </message>
+    <message>
+        <source>Switch on/off transparency for the graphics (Ctrl+T).</source>
+        <translation type="obsolete">Включить/выключить прозрачность графика (Ctrl+T).</translation>
+    </message>
+    <message>
+        <source>Switch on/off lightning for the graphics (Ctrl+L).</source>
+        <translation type="obsolete">Включить/выключить освещение графика (Ctrl+L).</translation>
+    </message>
+    <message>
+        <source>Switch on/off grid drawing for absolute coordinates (Ctrl+G).</source>
+        <translation type="obsolete">Включить/выключить рисование сетки абсолютных координат (Ctrl+G).</translation>
+    </message>
+    <message>
+        <source>Restore default graphics rotation, zoom and perspective (Ctrl+Space).</source>
+        <translation type="obsolete">Восстановить вращение, масштаб и перспективу по умолчанию (Ctrl+Space).</translation>
+    </message>
+    <message>
+        <source>&Copy click coor.</source>
+        <translation type="obsolete">&Копировать коор.</translation>
+    </message>
+    <message>
+        <source>Copy coordinates of last mouse click to clipboard.</source>
+        <translation type="obsolete">Копировать в буфер обмена координаты последнего щелчка мыши.</translation>
+    </message>
+    <message>
+        <source>Show next slide (Meta+Right).</source>
+        <translation type="obsolete">Показать следующий кадр (Meta+Right).</translation>
+    </message>
+    <message>
+        <source>Show previous slide (Meta+Left).</source>
+        <translation type="obsolete">Показать предыдущий кадр (Meta+Left).</translation>
+    </message>
+    <message>
+        <source>Set value of \theta angle.
+You can use keys (Shift+Meta+Up or Shift+Meta+Down).</source>
+        <translation type="obsolete">Изменить значение угла \theta.
+Можно использовать клавиши (Shift+Meta+Up или Shift+Meta+Down).</translation>
+    </message>
+    <message>
+        <source>Set value of \phi angle.
+You can use keys (Shift+Meta+Left or Shift+Meta+Right).</source>
+        <translation type="obsolete">Изменить значение угла \phi.
+Можно использовать клавиши (Shift+Meta+Left или Shift+Meta+Right).</translation>
+    </message>
+    <message>
+        <source>Rotate</source>
+        <translation type="obsolete">Вращать</translation>
+    </message>
+    <message>
+        <source>Rotate up</source>
+        <translation type="obsolete">Вращать вверх</translation>
+    </message>
+    <message>
+        <source>Increase \theta angle by 10 degrees.</source>
+        <translation type="obsolete">Увеличить угол \theta на 10 градусов.</translation>
+    </message>
+    <message>
+        <source>Rotate down</source>
+        <translation type="obsolete">Вращать вниз</translation>
+    </message>
+    <message>
+        <source>Decrease \theta angle by 10 degrees.</source>
+        <translation type="obsolete">Уменьшить угол \theta на 10 градусов.</translation>
+    </message>
+    <message>
+        <source>Rotate left</source>
+        <translation type="obsolete">Вращать влево</translation>
+    </message>
+    <message>
+        <source>Increase \phi angle by 10 degrees.</source>
+        <translation type="obsolete">Увеличить угол \phi на 10 градусов.</translation>
+    </message>
+    <message>
+        <source>Rotate right</source>
+        <translation type="obsolete">Вращать вправо</translation>
+    </message>
+    <message>
+        <source>Decrease \phi angle by 10 degrees.</source>
+        <translation type="obsolete">Уменьшить угол \phi на 10 градусов.</translation>
+    </message>
+</context>
+<context>
+    <name>HelpPanel</name>
+    <message>
+        <source>Backward</source>
+        <translation>Назад</translation>
+    </message>
+    <message>
+        <source>Forward</source>
+        <translation>Вперед</translation>
+    </message>
+    <message>
+        <source>&Examples</source>
+        <translation>&Примеры</translation>
+    </message>
+    <message>
+        <source>Help</source>
+        <translation>Помощь</translation>
+    </message>
+    <message>
+        <source>mgl_en</source>
+        <translation>mgl_ru</translation>
+    </message>
+</context>
+<context>
+    <name>HelpWindow</name>
+    <message>
+        <source>Backward</source>
+        <translation type="obsolete">Назад</translation>
+    </message>
+    <message>
+        <source>Forward</source>
+        <translation type="obsolete">Вперед</translation>
+    </message>
+    <message>
+        <source>&Examples</source>
+        <translation type="obsolete">&Примеры</translation>
+    </message>
+    <message>
+        <source>Help</source>
+        <translation type="obsolete">Помощь</translation>
+    </message>
+    <message>
+        <source>mgl_en</source>
+        <translation type="obsolete">mgl_ru</translation>
+    </message>
+</context>
+<context>
+    <name>HintDialog</name>
+    <message>
+        <source>UDAV - Hint</source>
+        <translation>UDAV - Советы</translation>
+    </message>
+    <message>
+        <source>&Show at startup</source>
+        <translation>Показывать при з&апуске</translation>
+    </message>
+    <message>
+        <source>&Prev</source>
+        <translation>&Предыдущий</translation>
+    </message>
+    <message>
+        <source>&Next</source>
+        <translation>&Следующий</translation>
+    </message>
+    <message>
+        <source>&Close</source>
+        <translation>&Закрыть</translation>
+    </message>
+</context>
+<context>
+    <name>InfoDialog</name>
+    <message>
+        <source>Select kind of plot</source>
+        <translation>Выберите тип графика</translation>
+    </message>
+    <message>
+        <source>Data preview for current slice.</source>
+        <translation>Просмотр для текущего среза.</translation>
+    </message>
+    <message>
+        <source>1D plot</source>
+        <translation>1D график</translation>
+    </message>
+    <message>
+        <source>2D plot</source>
+        <translation>2D график</translation>
+    </message>
+    <message>
+        <source>Kind of plots: lines for 1D, density for 2D.</source>
+        <translation>Тип графика: линии для 1D, график плотности для 2D.</translation>
+    </message>
+    <message>
+        <source>Preview</source>
+        <translation>Просмотр</translation>
+    </message>
+    <message>
+        <source>Short information about the data.</source>
+        <translation>Краткая информация о данных.</translation>
+    </message>
+    <message>
+        <source>Information</source>
+        <translation>Информация</translation>
+    </message>
+</context>
+<context>
+    <name>MGLThread</name>
+    <message>
+        <source>In line </source>
+        <translation>В линии </translation>
+    </message>
+    <message>
+        <source> -- wrong argument(s):	</source>
+        <translation> -- неправильный аргумент(ы):	</translation>
+    </message>
+    <message>
+        <source> -- wrong command:	</source>
+        <translation> -- неправильная команда:	</translation>
+    </message>
+    <message>
+        <source> -- string too long:	</source>
+        <translation> -- строка слишком длинная:	</translation>
+    </message>
+    <message>
+        <source> -- unbalanced ' :	</source>
+        <translation> -- не хватает ' :	</translation>
+    </message>
+</context>
+<context>
+    <name>MainWindow</name>
+    <message>
+        <source>untitled - UDAV</source>
+        <translation>без имени - UDAV</translation>
+    </message>
+    <message>
+        <source>Messages and warnings</source>
+        <translation>Сообщения и предупреждения</translation>
+    </message>
+    <message>
+        <source>Calculator</source>
+        <translation>Калькулятор</translation>
+    </message>
+    <message>
+        <source>&Open file</source>
+        <translation>&Открыть файл</translation>
+    </message>
+    <message>
+        <source>Open and execute/show script or data from file (Ctrl+O).
+You may switch off automatic exection in UDAV properties.</source>
+        <translation>Открыть и выполнить/показать код или данные из файла (Ctrl+O).
+Вы можете выключить автоматическое выполнение в настройках UDAV.</translation>
+    </message>
+    <message>
+        <source>&Save script</source>
+        <translation>&Сохранить код</translation>
+    </message>
+    <message>
+        <source>Save script to a file (Ctrl+S)</source>
+        <translation>Сохранить код в файл (Ctrl+S)</translation>
+    </message>
+    <message>
+        <source>Show calculator which evaluate and help to type textual formulas.
+Textual formulas may contain data variables too.</source>
+        <translation>Показывает калькулятор, который вычисляет и помогает набрать текстовые формулы.
+Текстовые формулы могут содержать также и определенные в коде данные.</translation>
+    </message>
+    <message>
+        <source>Show info</source>
+        <translation>Окно сообщений</translation>
+    </message>
+    <message>
+        <source>Canvas</source>
+        <translation>График</translation>
+    </message>
+    <message>
+        <source>Help</source>
+        <translation>Помощь</translation>
+    </message>
+    <message>
+        <source>Info</source>
+        <translation>Информация</translation>
+    </message>
+    <message>
+        <source>Script</source>
+        <translation>Код</translation>
+    </message>
+    <message>
+        <source>Ready</source>
+        <translation>Готово</translation>
+    </message>
+    <message>
+        <source>&File</source>
+        <translation>&Файл</translation>
+    </message>
+    <message>
+        <source>&New script</source>
+        <translation>&Новый код</translation>
+    </message>
+    <message>
+        <source>Create new empty script window (Ctrl+N).</source>
+        <translation>Создать новое пустое окно для кода (Ctrl+N).</translation>
+    </message>
+    <message>
+        <source>Save &As ...</source>
+        <translation>Сохранить &как ...</translation>
+    </message>
+    <message>
+        <source>&Print script</source>
+        <translation>Печатать &код</translation>
+    </message>
+    <message>
+        <source>Print &graphics</source>
+        <translation>&Печатать график</translation>
+    </message>
+    <message>
+        <source>Open printer dialog and print graphics	(Ctrl+P)</source>
+        <translation>Открыть диалог принтера и напечатать график (Ctrl+P)</translation>
+    </message>
+    <message>
+        <source>Recent files</source>
+        <translation>Последние файлы</translation>
+    </message>
+    <message>
+        <source>&Quit</source>
+        <translation>В&ыход</translation>
+    </message>
+    <message>
+        <source>&Settings</source>
+        <translation>&Настройки</translation>
+    </message>
+    <message>
+        <source>Properties</source>
+        <translation>Настройки UDAV</translation>
+    </message>
+    <message>
+        <source>Show dialog for UDAV properties.</source>
+        <translation>Показать диалог настроек программы UDAV.</translation>
+    </message>
+    <message>
+        <source>Set ar&guments</source>
+        <translation>&Аргументы кода</translation>
+    </message>
+    <message>
+        <source>&Help</source>
+        <translation>&Справка</translation>
+    </message>
+    <message>
+        <source>MGL &help</source>
+        <translation>MGL &справка</translation>
+    </message>
+    <message>
+        <source>Show help on MGL commands (F1).</source>
+        <translation>Показывает справку по текущей команде MGL (F1).</translation>
+    </message>
+    <message>
+        <source>&Examples</source>
+        <translation>&Примеры</translation>
+    </message>
+    <message>
+        <source>Show examples of MGL usage (Shift+F1).</source>
+        <translation>Показывает примеры использования MGL (Shift+F1).</translation>
+    </message>
+    <message>
+        <source>H&ints</source>
+        <translation>С&оветы</translation>
+    </message>
+    <message>
+        <source>Show hints of MGL usage.</source>
+        <translation>Показывает советы по использованию MGL.</translation>
+    </message>
+    <message>
+        <source>&About</source>
+        <translation>О &программе</translation>
+    </message>
+    <message>
+        <source>About &Qt</source>
+        <translation>О библиотеке &Qt</translation>
+    </message>
+    <message>
+        <source>UDAV</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Do you want to save the changes to the document?</source>
+        <translation>Вы хотите сохранить изменения в коде?</translation>
+    </message>
+    <message>
+        <source>Not recognized</source>
+        <translation>Не распознано</translation>
+    </message>
+    <message>
+        <source>UDAV v. 0.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>
+(c) Alexey Balakin, 2008
+http://udav.sf.net/</source>
+        <translation>
+(c) Алексей Балакин, 2008
+http://udav.sf.net/</translation>
+    </message>
+    <message>
+        <source>UDAV - about</source>
+        <translation>UDAV - о программе</translation>
+    </message>
+    <message>
+        <source>About Qt</source>
+        <translation>О библиотеке Qt</translation>
+    </message>
+    <message>
+        <source> - UDAV</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>UDAV - save current</source>
+        <translation>UDAV - сохранить текущий код</translation>
+    </message>
+    <message>
+        <source>Couldn't change to folder </source>
+        <translation>Не могу перейти в папку </translation>
+    </message>
+    <message>
+        <source>UDAV - Open file</source>
+        <translation>UDAV - Открыть файл</translation>
+    </message>
+    <message>
+        <source>MGL scripts (*.mgl)
+HDF5 files (*.hdf *.h5)
+Text files (*.txt)
+Data files (*.dat)
+All files (*.*)</source>
+        <translation>MGL код (*.mgl)
+HDF5 файлы (*.hdf *.h5)
+Текст (*.txt)
+Файлы данных (*.dat)
+Все файлы (*.*)</translation>
+    </message>
+    <message>
+        <source>Loading aborted</source>
+        <translation>Загрузка прервана</translation>
+    </message>
+    <message>
+        <source>UDAV - save file</source>
+        <translation>UDAV - сохранить файл</translation>
+    </message>
+    <message>
+        <source>MGL scripts (*.mgl)
+HDF5 files (*.hdf *.h5)
+All files (*.*)</source>
+        <translation>MGL код (*.mgl)
+HDF5 файлы (*.hdf *.h5)
+Все файлы (*.*)</translation>
+    </message>
+    <message>
+        <source>Saving aborted</source>
+        <translation>Сохранение прервано</translation>
+    </message>
+    <message>
+        <source>untitled* - UDAV</source>
+        <translation>без имени* - UDAV</translation>
+    </message>
+    <message>
+        <source>* - UDAV</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>MemPanel</name>
+    <message>
+        <source>Create new data array</source>
+        <translation>Создать новый массив данных</translation>
+    </message>
+    <message>
+        <source>Edit selected data array</source>
+        <translation>Редактировать выбранный массив данных</translation>
+    </message>
+    <message>
+        <source>Delete selected data array</source>
+        <translation>Удалить выбранный массив данных</translation>
+    </message>
+    <message>
+        <source>Properties of selected data array</source>
+        <translation>Свойства выбранного массива данных</translation>
+    </message>
+    <message>
+        <source>Update list of data arrays</source>
+        <translation>Обновить список массивов данных</translation>
+    </message>
+    <message>
+        <source>Delete ALL data arrays</source>
+        <translation>Удалить ВСЕ массивы данных</translation>
+    </message>
+    <message>
+        <source>Name</source>
+        <translation>Имя</translation>
+    </message>
+    <message>
+        <source>Sizes</source>
+        <translation>Размеры</translation>
+    </message>
+    <message>
+        <source>Memory</source>
+        <translation>Память</translation>
+    </message>
+    <message>
+        <source>UDAV - New variable</source>
+        <translation>UDAV - Новая переменная</translation>
+    </message>
+    <message>
+        <source>Enter name for new variable</source>
+        <translation>Введите имя для новой переменной</translation>
+    </message>
+    <message>
+        <source>UDAV - delete all data</source>
+        <translation>UDAV - Удалить все данные</translation>
+    </message>
+    <message>
+        <source>Do you want to delete all data?</source>
+        <translation>Вы хотите удалить все данные?</translation>
+    </message>
+    <message>
+        <source> - UDAV preview</source>
+        <translation> - UDAV просмотр</translation>
+    </message>
+</context>
+<context>
+    <name>MemoryWindow</name>
+    <message>
+        <source>New</source>
+        <translation type="obsolete">Новый</translation>
+    </message>
+    <message>
+        <source>Edit</source>
+        <translation type="obsolete">Правка</translation>
+    </message>
+    <message>
+        <source>Delete</source>
+        <translation type="obsolete">Удалить</translation>
+    </message>
+    <message>
+        <source>Info</source>
+        <translation type="obsolete">Информация</translation>
+    </message>
+    <message>
+        <source>Update</source>
+        <translation type="obsolete">Обновить</translation>
+    </message>
+    <message>
+        <source>Delete All</source>
+        <translation type="obsolete">Удалить все</translation>
+    </message>
+    <message>
+        <source>Name</source>
+        <translation type="obsolete">Имя</translation>
+    </message>
+    <message>
+        <source>Sizes</source>
+        <translation type="obsolete">Размеры</translation>
+    </message>
+    <message>
+        <source>Memory</source>
+        <translation type="obsolete">Память</translation>
+    </message>
+    <message>
+        <source>UDAV - New variable</source>
+        <translation type="obsolete">UDAV - Новая переменная</translation>
+    </message>
+    <message>
+        <source>Enter name for new variable</source>
+        <translation type="obsolete">Введите имя для новой переменной</translation>
+    </message>
+    <message>
+        <source>UDAV - delete all data</source>
+        <translation type="obsolete">UDAV - Удалить все данные</translation>
+    </message>
+    <message>
+        <source>Do you want to delete all data?</source>
+        <translation type="obsolete">Вы хотите удалить все данные?</translation>
+    </message>
+    <message>
+        <source> - UDAV preview</source>
+        <translation type="obsolete"> - UDAV просмотр</translation>
+    </message>
+</context>
+<context>
+    <name>NewCmdDialog</name>
+    <message>
+        <source>Argument</source>
+        <translation>Аргумент</translation>
+    </message>
+    <message>
+        <source>Value</source>
+        <translation>Значение</translation>
+    </message>
+    <message>
+        <source>Add style</source>
+        <translation>Добавить стиль</translation>
+    </message>
+    <message>
+        <source>Add data</source>
+        <translation>Добавить данные</translation>
+    </message>
+    <message>
+        <source>Options</source>
+        <translation>Опции</translation>
+    </message>
+    <message>
+        <source>Cancel</source>
+        <translation>Отмена</translation>
+    </message>
+    <message>
+        <source>OK</source>
+        <translation>OK</translation>
+    </message>
+    <message>
+        <source>1D plots</source>
+        <translation>1D графики</translation>
+    </message>
+    <message>
+        <source>2D plots</source>
+        <translation>2D графики</translation>
+    </message>
+    <message>
+        <source>3D plots</source>
+        <translation>3D графики</translation>
+    </message>
+    <message>
+        <source>Dual plots</source>
+        <translation>Парные графики</translation>
+    </message>
+    <message>
+        <source>Vector plots</source>
+        <translation>Векторные графики</translation>
+    </message>
+    <message>
+        <source>Other plots</source>
+        <translation>Прочие графики</translation>
+    </message>
+    <message>
+        <source>Text and legend</source>
+        <translation>Текст и легенда</translation>
+    </message>
+    <message>
+        <source>Create data and I/O</source>
+        <translation>Создание данных и I/O</translation>
+    </message>
+    <message>
+        <source>Data handling</source>
+        <translation>Обработка данных</translation>
+    </message>
+    <message>
+        <source>Data extraction</source>
+        <translation>Выделение данных</translation>
+    </message>
+    <message>
+        <source>Axis and colorbar</source>
+        <translation>Оси координат</translation>
+    </message>
+    <message>
+        <source>General setup</source>
+        <translation>Настройка графика</translation>
+    </message>
+    <message>
+        <source>Axis setup</source>
+        <translation>Настройка осей</translation>
+    </message>
+    <message>
+        <source>Scale and rotate</source>
+        <translation>Положение и поворот</translation>
+    </message>
+    <message>
+        <source>Program flow</source>
+        <translation>Условия и циклы</translation>
+    </message>
+    <message>
+        <source>Nonlinear fitting</source>
+        <translation>Подбор функции</translation>
+    </message>
+    <message>
+        <source>Primitives</source>
+        <translation>Примитивы</translation>
+    </message>
+    <message>
+        <source>New command</source>
+        <translation>Новая команда</translation>
+    </message>
+    <message>
+        <source>Select first the proper kind of arguments</source>
+        <translation>Сначала выберите тип аргументов</translation>
+    </message>
+    <message>
+        <source>There is no 'fmt' argument for this command</source>
+        <translation>Нет аргумента 'fmt' для данной команды</translation>
+    </message>
+    <message>
+        <source>You should specify required argument </source>
+        <translation>Вы должны ввести все обязательные аргументы</translation>
+    </message>
+    <message>
+        <source>You should put text inside ' ' for argument </source>
+        <translation>Вы должны вводить текст внутри ' '</translation>
+    </message>
+    <message>
+        <source>You should specify all optional arguments before </source>
+        <translation>Вы должны ввести все опциональные аргументы перед </translation>
+    </message>
+    <message>
+        <source>Groups of MGL commands</source>
+        <translation>Группы команд MGL</translation>
+    </message>
+    <message>
+        <source>MGL commands for selected group</source>
+        <translation>Команды MGL для выбранной группы</translation>
+    </message>
+    <message>
+        <source>Short description of selected command</source>
+        <translation>Краткое описание выбранной команды</translation>
+    </message>
+    <message>
+        <source>Kind of command argument order. The notation is:
+ * Capital arguments are data (like, Ydat);
+ * Argument in '' are strings (like, 'fmt');
+ * Other arguments are numbers (like, zval);
+ * Arguments in [] are optional arguments.</source>
+        <translation>Тип аргументов команды. Используются обозначения:
+ * Заглавными обозначены данные (например, Ydat);
+ * Аргументы в '' означают строки (например, 'fmt');
+ * Прочие аргументы -- числа (например, zval);
+ * Аргументы в [] опциональны (могут не указываться).</translation>
+    </message>
+    <message>
+        <source>Command arguments. Bold ones are required arguments.
+Other are optional arguments but its order is required.
+You can use '' for default format. See help at right
+for default values.</source>
+        <translation>Аргументы команды. Жирным обозначены обязательные аргументы.
+Все прочие аргументы опциональны, но их порядок должен соблюдаться.
+Можно использовать '' для формата по умолчанию. Справка справа дает
+подробное описание команды и значения аргументов по умолчанию.</translation>
+    </message>
+    <message>
+        <source>Here you can select the plot style.
+The result will be placed in 'fmt' argument.</source>
+        <translation>Здесь можно выбрать стиль графика.
+Результат будет помещен в аргумент 'fmt'.</translation>
+    </message>
+    <message>
+        <source>Here you can specify command options.
+Options are used for additional plot tunning.</source>
+        <translation>Здесь можно выбрать опции команд.
+Опции используются для дополнительной
+настройки вида графика.</translation>
+    </message>
+    <message>
+        <source>mgl_en</source>
+        <translation>mgl_ru</translation>
+    </message>
+</context>
+<context>
+    <name>OptionDialog</name>
+    <message>
+        <source>UDAV - Add options</source>
+        <translation>UDAV - Добавить опцию</translation>
+    </message>
+    <message>
+        <source>X-range</source>
+        <translation>Диапазон по X</translation>
+    </message>
+    <message>
+        <source>Y-range</source>
+        <translation>Диапазон по Y</translation>
+    </message>
+    <message>
+        <source>Z-range</source>
+        <translation>Диапазон по Z</translation>
+    </message>
+    <message>
+        <source>C-range</source>
+        <translation>Диапазон по C</translation>
+    </message>
+    <message>
+        <source>Alpha</source>
+        <translation>Прозрачность</translation>
+    </message>
+    <message>
+        <source>Ambient</source>
+        <translation>Фоновое освещение</translation>
+    </message>
+    <message>
+        <source>Mesh num</source>
+        <translation>Число линий сетки</translation>
+    </message>
+    <message>
+        <source>Font size</source>
+        <translation>Размер шрифта</translation>
+    </message>
+    <message>
+        <source>Cutting</source>
+        <translation>Обрезание</translation>
+    </message>
+    <message>
+        <source>Legend</source>
+        <translation>Легенда</translation>
+    </message>
+    <message>
+        <source>Cancel</source>
+        <translation>Отмена</translation>
+    </message>
+    <message>
+        <source>OK</source>
+        <translation>OK</translation>
+    </message>
+    <message>
+        <source>UDAV - command options</source>
+        <translation>UDAV - опции команд</translation>
+    </message>
+    <message>
+        <source>Both fields in xrange must be filled</source>
+        <translation>Оба поля в xrange должны быть заполнены</translation>
+    </message>
+    <message>
+        <source>Both fields in yrange must be filled</source>
+        <translation>Оба поля в yrange должны быть заполнены</translation>
+    </message>
+    <message>
+        <source>Both fields in zrange must be filled</source>
+        <translation>Оба поля в zrange должны быть заполнены</translation>
+    </message>
+    <message>
+        <source>Both fields in crange must be filled</source>
+        <translation>Оба поля в crange должны быть заполнены</translation>
+    </message>
+    <message>
+        <source>on</source>
+        <translation>вкл</translation>
+    </message>
+    <message>
+        <source>off</source>
+        <translation>выкл</translation>
+    </message>
+</context>
+<context>
+    <name>PlotPanel</name>
+    <message>
+        <source>&Graphics</source>
+        <translation>&График</translation>
+    </message>
+    <message>
+        <source>Printing...</source>
+        <translation>Печатаю...</translation>
+    </message>
+    <message>
+        <source>Printing completed</source>
+        <translation>Печать завершена</translation>
+    </message>
+    <message>
+        <source>Printing aborted</source>
+        <translation>Печать прервана</translation>
+    </message>
+    <message>
+        <source>Drawing time %1 ms</source>
+        <translation>Время рисования %1 мсек</translation>
+    </message>
+    <message>
+        <source>Frame %1 of %2</source>
+        <translation>Кадр %1 из %2</translation>
+    </message>
+    <message>
+        <source>&Alpha</source>
+        <translation>&Прозрачность</translation>
+    </message>
+    <message>
+        <source>Switch on/off transparency for the graphics (Ctrl+T).</source>
+        <translation>Включить/выключить прозрачность графика (Ctrl+T).</translation>
+    </message>
+    <message>
+        <source>&Light</source>
+        <translation>&Освещение</translation>
+    </message>
+    <message>
+        <source>Switch on/off lightning for the graphics (Ctrl+L).</source>
+        <translation>Включить/выключить освещение графика (Ctrl+L).</translation>
+    </message>
+    <message>
+        <source>&Grid</source>
+        <translation>&Сетка</translation>
+    </message>
+    <message>
+        <source>Switch on/off grid drawing for absolute coordinates (Ctrl+G).</source>
+        <translation>Включить/выключить рисование сетки абсолютных координат (Ctrl+G).</translation>
+    </message>
+    <message>
+        <source>&Rotate by mouse</source>
+        <translation>&Вращать мышкой</translation>
+    </message>
+    <message>
+        <source>Switch on/off mouse handling of the graphics
+(rotation, shifting, zooming and perspective).</source>
+        <translation>Включить/выключить изменение графика мышью
+(вращение, сдвиг, приближение и перспектива).</translation>
+    </message>
+    <message>
+        <source>&Zoom by mouse</source>
+        <translation>&Приближение мышью</translation>
+    </message>
+    <message>
+        <source>Switch on/off mouse zoom of selected region.</source>
+        <translation>Включить/выключить приближение выбранного региона.</translation>
+    </message>
+    <message>
+        <source>Res&tore</source>
+        <translation>В&осстановить</translation>
+    </message>
+    <message>
+        <source>Restore default graphics rotation, zoom and perspective (Ctrl+Space).</source>
+        <translation>Восстановить вращение, масштаб и перспективу по умолчанию (Ctrl+Space).</translation>
+    </message>
+    <message>
+        <source>Re&draw</source>
+        <translation>Пе&рерисовать</translation>
+    </message>
+    <message>
+        <source>Execute script and redraw graphics (F5).</source>
+        <translation>Выполнить код и перерисовать график (F5).</translation>
+    </message>
+    <message>
+        <source>&Adjust size</source>
+        <translation>&Подобрать размер</translation>
+    </message>
+    <message>
+        <source>Change canvas size to fill whole region (F6).</source>
+        <translation>Изменить размер рисунка так, чтобы он заполнял всю область (F6).</translation>
+    </message>
+    <message>
+        <source>Re&load</source>
+        <translation>Пере&грузить</translation>
+    </message>
+    <message>
+        <source>Restore status for 'once' command and reload data (F9).</source>
+        <translation>Восстановить статус команды 'once' и перегрузить данные (F9).</translation>
+    </message>
+    <message>
+        <source>&Stop</source>
+        <translation>&Остановить</translation>
+    </message>
+    <message>
+        <source>Stop script execution (F7).</source>
+        <translation>Остановить выполенение кода (F7).</translation>
+    </message>
+    <message>
+        <source>&Copy plot</source>
+        <translation>&Копировать график</translation>
+    </message>
+    <message>
+        <source>Copy graphics to clipboard (Ctrl+Shift+C).</source>
+        <translation>Копировать график в буфер обмена (Ctrl+Shift+C).</translation>
+    </message>
+    <message>
+        <source>&Copy click coor.</source>
+        <translation>&Копировать коор.</translation>
+    </message>
+    <message>
+        <source>Copy coordinates of last mouse click to clipboard.</source>
+        <translation>Копировать в буфер обмена координаты последнего щелчка мыши.</translation>
+    </message>
+    <message>
+        <source>Set value of \theta angle.
+You can use keys (Shift+Meta+Up or Shift+Meta+Down).</source>
+        <translation>Изменить значение угла \theta.
+Можно использовать клавиши (Shift+Meta+Up или Shift+Meta+Down).</translation>
+    </message>
+    <message>
+        <source>Set value of \phi angle.
+You can use keys (Shift+Meta+Left or Shift+Meta+Right).</source>
+        <translation>Изменить значение угла \phi.
+Можно использовать клавиши (Shift+Meta+Left или Shift+Meta+Right).</translation>
+    </message>
+    <message>
+        <source>&Export as ...</source>
+        <translation>&Экспорт в ...</translation>
+    </message>
+    <message>
+        <source>PNG</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>solid PNG</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>JPEG</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>GIF</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>bitmap EPS</source>
+        <translation>растровый EPS</translation>
+    </message>
+    <message>
+        <source>vector EPS</source>
+        <translation>векторный EPS</translation>
+    </message>
+    <message>
+        <source>SVG</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>C++</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>IDTF</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <source>Zoom/move</source>
+        <translation>Масштаб/сдвиг</translation>
+    </message>
+    <message>
+        <source>Move &left</source>
+        <translation>Сдвиг в&лево</translation>
+    </message>
+    <message>
+        <source>Move graphics left by 1/3 of its width.</source>
+        <translation>Сдвиг графика влево на 1/3 его ширины.</translation>
+    </message>
+    <message>
+        <source>Move &up</source>
+        <translation>Сдвиг &вверх</translation>
+    </message>
+    <message>
+        <source>Move graphics up by 1/3 of its height.</source>
+        <translation>Сдвиг графика вверх на 1/3 его высоты.</translation>
+    </message>
+    <message>
+        <source>Zoom &in</source>
+        <translation>&Приблизить</translation>
+    </message>
+    <message>
+        <source>Zoom in graphics.</source>
+        <translation>Приблизить график.</translation>
+    </message>
+    <message>
+        <source>Zoom &out</source>
+        <translation>&Отдалить</translation>
+    </message>
+    <message>
+        <source>Zoom out graphics.</source>
+        <translation>Отдалить график.</translation>
+    </message>
+    <message>
+        <source>Move &down</source>
+        <translation>Сдвиг в&низ</translation>
+    </message>
+    <message>
+        <source>Move graphics up down 1/3 of its height.</source>
+        <translation>Сдвиг графика вниз на 1/3 его высоты.</translation>
+    </message>
+    <message>
+        <source>Move &right</source>
+        <translation>Сдвиг вп&раво</translation>
+    </message>
+    <message>
+        <source>Move graphics right by 1/3 of its width.</source>
+        <translation>Сдвиг графика вправо на 1/3 его ширины.</translation>
+    </message>
+    <message>
+        <source>Rotate</source>
+        <translation>Вращать</translation>
+    </message>
+    <message>
+        <source>Rotate up</source>
+        <translation>Вращать вверх</translation>
+    </message>
+    <message>
+        <source>Increase \theta angle by 10 degrees.</source>
+        <translation>Увеличить угол \theta на 10 градусов.</translation>
+    </message>
+    <message>
+        <source>Rotate down</source>
+        <translation>Вращать вниз</translation>
+    </message>
+    <message>
+        <source>Decrease \theta angle by 10 degrees.</source>
+        <translation>Уменьшить угол \theta на 10 градусов.</translation>
+    </message>
+    <message>
+        <source>Rotate left</source>
+        <translation>Вращать влево</translation>
+    </message>
+    <message>
+        <source>Increase \phi angle by 10 degrees.</source>
+        <translation>Увеличить угол \phi на 10 градусов.</translation>
+    </message>
+    <message>
+        <source>Rotate right</source>
+        <translation>Вращать вправо</translation>
+    </message>
+    <message>
+        <source>Decrease \phi angle by 10 degrees.</source>
+        <translation>Уменьшить угол \phi на 10 градусов.</translation>
+    </message>
+    <message>
+        <source>&Animation</source>
+        <translation>&Анимация</translation>
+    </message>
+    <message>
+        <source>&Next slide</source>
+        <translation>&Следующий кадр</translation>
+    </message>
+    <message>
+        <source>Show next slide (Meta+Right).</source>
+        <translation>Показать следующий кадр (Meta+Right).</translation>
+    </message>
+    <message>
+        <source>&Prev slide</source>
+        <translation>&Предыдущий кадр</translation>
+    </message>
+    <message>
+        <source>Show previous slide (Meta+Left).</source>
+        <translation>Показать предыдущий кадр (Meta+Left).</translation>
+    </message>
+    <message>
+        <source>&Slideshow</source>
+        <translation>&Запустить</translation>
+    </message>
+    <message>
+        <source>Run slideshow (Ctrl+F5). If no parameter specified
+then the dialog with slideshow options will appear.</source>
+        <translation>Запустить анимацию (Ctrl+F5). Если параметры не были указаны,
+то показывается диалог с параметрами анимации.</translation>
+    </message>
+    <message>
+        <source>Se&tup show</source>
+        <translation>&Настроить анимацию</translation>
+    </message>
+</context>
+<context>
+    <name>PropDialog</name>
+    <message>
+        <source>UDAV - Properties</source>
+        <translation>UDAV - Настройки</translation>
+    </message>
+    <message>
+        <source>Select font</source>
+        <translation type="obsolete">Выбрать шрифт</translation>
+    </message>
+    <message>
+        <source>Current font</source>
+        <translation>Текущий шрифт</translation>
+    </message>
+    <message>
+        <source>Change font</source>
+        <translation>Изменить шрифт</translation>
+    </message>
+    <message>
+        <source>Setup colors for:</source>
+        <translation>Настроить цвета для:</translation>
+    </message>
+    <message>
+        <source>Comments</source>
+        <translation>Коментарии</translation>
+    </message>
+    <message>
+        <source>Strings</source>
+        <translation>Строки</translation>
+    </message>
+    <message>
+        <source>Keywords</source>
+        <translation>Команды</translation>
+    </message>
+    <message>
+        <source>Options</source>
+        <translation>Опции</translation>
+    </message>
+    <message>
+        <source>Suffixes</source>
+        <translation>Суффиксы</translation>
+    </message>
+    <message>
+        <source>Numbers</source>
+        <translation>Числа</translation>
+    </message>
+    <message>
+        <source>AutoKey</source>
+        <translation>Созд.данных</translation>
+    </message>
+    <message>
+        <source>FlowKey</source>
+        <translation>Упр.команды</translation>
+    </message>
+    <message>
+        <source>Path for help files</source>
+        <translation>Путь к файлам справки</translation>
+    </message>
+    <message>
+        <source>Path for user MathGL font files</source>
+        <translation>Путь к шрифтам MathGL</translation>
+    </message>
+    <message>
+        <source>Language for UDAV</source>
+        <translation>Язык для UDAV</translation>
+    </message>
+    <message>
+        <source>Russian</source>
+        <translation>Русский</translation>
+    </message>
+    <message>
+        <source>Automatically execute script after loading</source>
+        <translation>Автоматически выполнять после загрузки</translation>
+    </message>
+    <message>
+        <source>Place editor at top</source>
+        <translation>Поместить редактор сверху</translation>
+    </message>
+    <message>
+        <source>Load script to new window</source>
+        <translation>Загружать скрипт в новое окно</translation>
+    </message>
+    <message>
+        <source>Automatical save before redrawing (F5)</source>
+        <translation type="obsolete">Автоматически сохранять перед перерисовкой (F5)</translation>
+    </message>
+    <message>
+        <source>Cancel</source>
+        <translation>Отмена</translation>
+    </message>
+    <message>
+        <source>OK</source>
+        <translation>OK</translation>
+    </message>
+    <message>
+        <source>UDAV - Insert filename</source>
+        <translation>UDAV - Вставить имя файла</translation>
+    </message>
+    <message>
+        <source>You have to restart UDAV for applying the cahnges.</source>
+        <translation>Вы должны перезапустить UDAV для применения изменений.</translation>
+    </message>
+    <message>
+        <source>English</source>
+        <translation></translation>
+    </message>
+    <message>
+        <source>Image size</source>
+        <translation>Размер рисунка</translation>
+    </message>
+    <message>
+        <source>Font files (*.vfm)</source>
+        <translation>Файлы шрифтов (*.vfm)</translation>
+    </message>
+    <message>
+        <source>Disable face drawing (faster) for mouse rotation/shift/zoom.</source>
+        <translation>Не рисовать грани (быстрее) при вращении мышью.</translation>
+    </message>
+    <message>
+        <source>Automatically save before redrawing (F5)</source>
+        <translation>Автоматически сохранять перед перерисовкой (F5)</translation>
+    </message>
+    <message>
+        <source>Enable keywords completition</source>
+        <translation>Включить дополнение ключевых слов</translation>
+    </message>
+</context>
+<context>
+    <name>QMGLCanvas</name>
+    <message>
+        <source>No filename. Please save script first.</source>
+        <translation>Нет имени файла. Сохраните сначала код.</translation>
+    </message>
+    <message>
+        <source>UDAV</source>
+        <translation></translation>
+    </message>
+    <message>
+        <source>Not initialized!</source>
+        <translation>Не инициализировано!</translation>
+    </message>
+</context>
+<context>
+    <name>QObject</name>
+    <message>
+        <source>none or default</source>
+        <translation>нет или по-умолчанию</translation>
+    </message>
+    <message>
+        <source>w - white</source>
+        <translation>w - белый</translation>
+    </message>
+    <message>
+        <source>b - blue</source>
+        <translation>b - синий</translation>
+    </message>
+    <message>
+        <source>g - lime</source>
+        <translation>g - ярко-зеленый</translation>
+    </message>
+    <message>
+        <source>r - red</source>
+        <translation>r - красный</translation>
+    </message>
+    <message>
+        <source>c - cyan</source>
+        <translation>c - голубой</translation>
+    </message>
+    <message>
+        <source>m - magenta</source>
+        <translation>m - малиновый</translation>
+    </message>
+    <message>
+        <source>y - yellow</source>
+        <translation>y - желтый</translation>
+    </message>
+    <message>
+        <source>l - springgreen</source>
+        <translation>l - сине-зеленый</translation>
+    </message>
+    <message>
+        <source>e - lawngreen</source>
+        <translation>e - желто-зеленый</translation>
+    </message>
+    <message>
+        <source>n - skyblue</source>
+        <translation>n - небесно-голубой</translation>
+    </message>
+    <message>
+        <source>u - blueviolet</source>
+        <translation>u - сине-фиолетовый</translation>
+    </message>
+    <message>
+        <source>q - orange</source>
+        <translation>q - оранжевый</translation>
+    </message>
+    <message>
+        <source>p - deeppink</source>
+        <translation>p - фиолетовый</translation>
+    </message>
+    <message>
+        <source>h - gray</source>
+        <translation>h - серый</translation>
+    </message>
+    <message>
+        <source>k - black</source>
+        <translation>k - черный</translation>
+    </message>
+    <message>
+        <source>W - lightgray</source>
+        <translation>W - светло-серый</translation>
+    </message>
+    <message>
+        <source>B - navy</source>
+        <translation>B - темно синий</translation>
+    </message>
+    <message>
+        <source>G - green</source>
+        <translation>G - зеленый</translation>
+    </message>
+    <message>
+        <source>R - maroon</source>
+        <translation>R - темно красный</translation>
+    </message>
+    <message>
+        <source>C - teal</source>
+        <translation>C - темно голубой</translation>
+    </message>
+    <message>
+        <source>M - purple</source>
+        <oldsource>M -purple</oldsource>
+        <translation>M - пурпурный</translation>
+    </message>
+    <message>
+        <source>Y - olive</source>
+        <translation>Y - оливковый</translation>
+    </message>
+    <message>
+        <source>L - seagreen</source>
+        <translation>L - темно сине-зеленый</translation>
+    </message>
+    <message>
+        <source>E - darklawn</source>
+        <translation>E - темно желто-зеленый</translation>
+    </message>
+    <message>
+        <source>N - darkskyblue</source>
+        <translation>N - темно небесно-голубой</translation>
+    </message>
+    <message>
+        <source>U - indigo</source>
+        <translation>U - индиго</translation>
+    </message>
+    <message>
+        <source>Q - brown</source>
+        <translation>Q - коричневый</translation>
+    </message>
+    <message>
+        <source>P - darkpink</source>
+        <translation>P - темно фиолетовый</translation>
+    </message>
+    <message>
+        <source>H - darkgray</source>
+        <translation>H - темно серый</translation>
+    </message>
+    <message>
+        <source>none</source>
+        <translation>нет</translation>
+    </message>
+    <message>
+        <source>arrow</source>
+        <translation>стрелка</translation>
+    </message>
+    <message>
+        <source>back arrow</source>
+        <translation>обратная стрелка</translation>
+    </message>
+    <message>
+        <source>stop</source>
+        <translation>стоп</translation>
+    </message>
+    <message>
+        <source>size</source>
+        <translation>размер</translation>
+    </message>
+    <message>
+        <source>triangle</source>
+        <translation>треугольник</translation>
+    </message>
+    <message>
+        <source>square</source>
+        <translation>квадрат</translation>
+    </message>
+    <message>
+        <source>rhomb</source>
+        <translation>ромб</translation>
+    </message>
+    <message>
+        <source>circle</source>
+        <translation>окружность</translation>
+    </message>
+    <message>
+        <source>solid</source>
+        <translation>сплошная</translation>
+    </message>
+    <message>
+        <source>dash</source>
+        <translation>пунктир</translation>
+    </message>
+    <message>
+        <source>dash dot</source>
+        <translation>пунктир-точка</translation>
+    </message>
+    <message>
+        <source>small dash</source>
+        <translation>мелкий пунктир</translation>
+    </message>
+    <message>
+        <source>small dash dot</source>
+        <translation>мелкий пунктир-точка</translation>
+    </message>
+    <message>
+        <source>dots</source>
+        <translation>точки</translation>
+    </message>
+    <message>
+        <source>dot</source>
+        <translation>точка</translation>
+    </message>
+    <message>
+        <source>cross</source>
+        <translation type="obsolete">крест</translation>
+    </message>
+    <message>
+        <source>skew cross</source>
+        <translation>косой крест</translation>
+    </message>
+    <message>
+        <source>asterix</source>
+        <translation>звездочка</translation>
+    </message>
+    <message>
+        <source>triangle down</source>
+        <translation>треугольник вниз</translation>
+    </message>
+    <message>
+        <source>triangle up</source>
+        <translation>треугольник вверх</translation>
+    </message>
+    <message>
+        <source>filled square</source>
+        <translation type="obsolete">закрашенный квадрат</translation>
+    </message>
+    <message>
+        <source>filled rhomb</source>
+        <translation type="obsolete">закрашенный ромб</translation>
+    </message>
+    <message>
+        <source>filled triangle down</source>
+        <translation type="obsolete">закрашенный треугольник вниз</translation>
+    </message>
+    <message>
+        <source>filled triangle up</source>
+        <translation type="obsolete">закрашенный треугольник вверх</translation>
+    </message>
+    <message>
+        <source>filled circle</source>
+        <translation type="obsolete">круг</translation>
+    </message>
+    <message>
+        <source>long dash</source>
+        <translation>длинный пунктир</translation>
+    </message>
+    <message>
+        <source>plus</source>
+        <translation>плюс</translation>
+    </message>
+    <message>
+        <source>triangle left</source>
+        <translation>треугольник влево</translation>
+    </message>
+    <message>
+        <source>triangle right</source>
+        <translation>треугольник вправо</translation>
+    </message>
+    <message>
+        <source>circled dot</source>
+        <translation>точка в окружности</translation>
+    </message>
+    <message>
+        <source>Y-sign</source>
+        <translation>знак Y</translation>
+    </message>
+    <message>
+        <source>squared plus</source>
+        <translation>плюс в квадрате</translation>
+    </message>
+    <message>
+        <source>squared cross</source>
+        <translation>косой крест в квадрате</translation>
+    </message>
+    <message>
+        <source>solid square</source>
+        <translation>закрашенный квадрат</translation>
+    </message>
+    <message>
+        <source>solid rhomb</source>
+        <translation>закрашенный ромб</translation>
+    </message>
+    <message>
+        <source>solid triangle down</source>
+        <translation>закрашенный треугольник вниз</translation>
+    </message>
+    <message>
+        <source>solid triangle up</source>
+        <translation>закрашенный треугольник вверх</translation>
+    </message>
+    <message>
+        <source>solid triangle left</source>
+        <translation>закрашенный треугольник влево</translation>
+    </message>
+    <message>
+        <source>solid triangle right</source>
+        <translation>закрашенный треугольник вправо</translation>
+    </message>
+    <message>
+        <source>solid circle</source>
+        <translation>круг</translation>
+    </message>
+</context>
+<context>
+    <name>ScriptWindow</name>
+    <message>
+        <source>
+(c) Alexey Balakin, 2008
+http://udav.sf.net/</source>
+        <translation type="obsolete">
+(c) Алексей Балакин, 2008
+http://udav.sf.net/</translation>
+    </message>
+    <message>
+        <source>UDAV - about</source>
+        <translation type="obsolete">UDAV - о программе</translation>
+    </message>
+    <message>
+        <source>File/Edit Operations</source>
+        <translation type="obsolete">Файл/Правка</translation>
+    </message>
+    <message>
+        <source>&File</source>
+        <translation type="obsolete">&Файл</translation>
+    </message>
+    <message>
+        <source>&New script</source>
+        <translation type="obsolete">&Новый код</translation>
+    </message>
+    <message>
+        <source>Create new empty script window (Ctrl+N).</source>
+        <translation type="obsolete">Создать новое пустое окно для кода (Ctrl+N).</translation>
+    </message>
+    <message>
+        <source>&Open file</source>
+        <translation type="obsolete">&Открыть файл</translation>
+    </message>
+    <message>
+        <source>Open and execute/show script or data from file (Ctrl+O).
+You may switch off automatic exection in UDAV properties.</source>
+        <translation type="obsolete">Открыть и выполнить/показать код или данные из файла (Ctrl+O).
+Вы можете выключить автоматическое выполнение в настройках UDAV.</translation>
+    </message>
+    <message>
+        <source>&Save script</source>
+        <translation type="obsolete">&Сохранить файл</translation>
+    </message>
+    <message>
+        <source>Save script to a file (Ctrl+S)</source>
+        <translation type="obsolete">Сохранить код в файл (Ctrl+S)</translation>
+    </message>
+    <message>
+        <source>Save &As ...</source>
+        <translation type="obsolete">Сохранить &как ...</translation>
+    </message>
+    <message>
+        <source>&Print script</source>
+        <translation type="obsolete">Печатать &код</translation>
+    </message>
+    <message>
+        <source>Print &graphics</source>
+        <translation type="obsolete">&Печатать график</translation>
+    </message>
+    <message>
+        <source>Open printer dialog and print graphics	(Ctrl+P)</source>
+        <translation type="obsolete">Открыть диалог принтера и напечатать график (Ctrl+P)</translation>
+    </message>
+    <message>
+        <source>Recent files</source>
+        <translation type="obsolete">Последние файлы</translation>
+    </message>
+    <message>
+        <source>&Quit</source>
+        <translation type="obsolete">В&ыход</translation>
+    </message>
+    <message>
+        <source>&Edit</source>
+        <translation type="obsolete">&Правка</translation>
+    </message>
+    <message>
+        <source>&Undo</source>
+        <translation type="obsolete">&Отменить</translation>
+    </message>
+    <message>
+        <source>Undo editor change (Ctrl+Z).</source>
+        <translation type="obsolete">Отменить изменения в редакторе (Ctrl+Z).</translation>
+    </message>
+    <message>
+        <source>&Redo</source>
+        <translation type="obsolete">&Вернуть</translation>
+    </message>
+    <message>
+        <source>Redo editor change (Ctrl+Shift+Z).</source>
+        <translation type="obsolete">Вернуть изменения в редакторе (Ctrl+Shift+Z).</translation>
+    </message>
+    <message>
+        <source>Clear all</source>
+        <translation type="obsolete">Очистить все</translation>
+    </message>
+    <message>
+        <source>Cu&t text</source>
+        <translation type="obsolete">В&ырезать</translation>
+    </message>
+    <message>
+        <source>Cut selected text to clipboard (Ctrl+X).</source>
+        <translation type="obsolete">Вырезать выделенный текст в буфер обмена (Ctrl+X).</translation>
+    </message>
+    <message>
+        <source>&Copy</source>
+        <translation type="obsolete">&Копировать</translation>
+    </message>
+    <message>
+        <source>Copy selected text or data to clipboard (Ctrl+C).</source>
+        <translation type="obsolete">Копировать выделенный текст в буфер обмена (Ctrl+C).</translation>
+    </message>
+    <message>
+        <source>&Paste</source>
+        <translation type="obsolete">&Вставить</translation>
+    </message>
+    <message>
+        <source>Paste text or data from clipboard (Ctrl+V).</source>
+        <translation type="obsolete">Вставить текст или данные из буфера обмена (Ctrl+V).</translation>
+    </message>
+    <message>
+        <source>Select &all</source>
+        <translation type="obsolete">Выделить вс&е</translation>
+    </message>
+    <message>
+        <source>&Find/Replace</source>
+        <translation type="obsolete">&Найти/заменить</translation>
+    </message>
+    <message>
+        <source>Show dialog for text finding (Ctrl+F).</source>
+        <translation type="obsolete">Показать диалог поиска текста (Ctrl+F).</translation>
+    </message>
+    <message>
+        <source>Find next</source>
+        <translation type="obsolete">Найти текст</translation>
+    </message>
+    <message>
+        <source>Insert</source>
+        <translation type="obsolete">Вставить</translation>
+    </message>
+    <message>
+        <source>New command</source>
+        <translation type="obsolete">Новая команда</translation>
+    </message>
+    <message>
+        <source>Show dialog for new command and put it into the script.</source>
+        <translation type="obsolete">Показать диалог вставки новой команды.</translation>
+    </message>
+    <message>
+        <source>Fitted formula</source>
+        <translation type="obsolete">Найденная формула</translation>
+    </message>
+    <message>
+        <source>Insert last fitted formula with found coefficients.</source>
+        <translation type="obsolete">Вставить последнюю найденную формулу в текст.</translation>
+    </message>
+    <message>
+        <source>Plot style</source>
+        <translation type="obsolete">Стиль графика</translation>
+    </message>
+    <message>
+        <source>Show dialog for styles and put it into the script.
+Styles define the plot view (color scheme, marks, dashing and so on).</source>
+        <translation type="obsolete">Показать диалог стиля графика и вставить его в код.
+Стиль определяет вид графика (цвет, маркеры, пунктир и пр).</translation>
+    </message>
+    <message>
+        <source>Command options</source>
+        <translation type="obsolete">Опции команды</translation>
+    </message>
+    <message>
+        <source>Show dialog for options and put it into the script.
+Options are used for additional setup the plot.</source>
+        <translation type="obsolete">Показать диалог выбора опций команды. Опции используются 
+для дополнительной настройки выбранного графика.</translation>
+    </message>
+    <message>
+        <source>Numeric value</source>
+        <translation type="obsolete">Численное значение</translation>
+    </message>
+    <message>
+        <source>Replace expression by its numerical value.</source>
+        <translation type="obsolete">Заменить выделенное выражение его числовым значением.</translation>
+    </message>
+    <message>
+        <source>File path</source>
+        <translation type="obsolete">Путь файла</translation>
+    </message>
+    <message>
+        <source>Select and insert file name.</source>
+        <translation type="obsolete">Выбрать и вставить путь файла.</translation>
+    </message>
+    <message>
+        <source>Folder path</source>
+        <translation type="obsolete">Путь папки</translation>
+    </message>
+    <message>
+        <source>Select and insert folder name.</source>
+        <translation type="obsolete">Выбрать и вставить путь папки.</translation>
+    </message>
+    <message>
+        <source>Graphics setup</source>
+        <translation type="obsolete">Настройка графика</translation>
+    </message>
+    <message>
+        <source>Show dialog for plot setup and put code into the script.
+This dialog setup axis, labels, lighting and other general things.</source>
+        <translation type="obsolete">Показать диалог настройки графика и вставить ее в код.
+Диалог позволяет настроить оси, подписи, освещение и пр.</translation>
+    </message>
+    <message>
+        <source>Properties</source>
+        <translation type="obsolete">Настройки UDAV</translation>
+    </message>
+    <message>
+        <source>Show dialog for UDAV properties.</source>
+        <translation type="obsolete">Показать диалог настроек программы UDAV.</translation>
+    </message>
+    <message>
+        <source>Set ar&guments</source>
+        <translation type="obsolete">&Аргументы кода</translation>
+    </message>
+    <message>
+        <source>Calculator</source>
+        <translation type="obsolete">Калькулятор</translation>
+    </message>
+    <message>
+        <source>Show calculator which evaluate and help to type textual formulas.
+Textual formulas may contain data variables too.</source>
+        <translation type="obsolete">Показывает калькулятор, который вычисляет и помогает набрать текстовые формулы.
+Текстовые формулы могут содержать также и определенные в коде данные.</translation>
+    </message>
+    <message>
+        <source>Show info</source>
+        <translation type="obsolete">Окно сообщений</translation>
+    </message>
+    <message>
+        <source>&Window</source>
+        <translation type="obsolete">&Окна</translation>
+    </message>
+    <message>
+        <source>Tile</source>
+        <translation type="obsolete">Плиткой</translation>
+    </message>
+    <message>
+        <source>Cascade</source>
+        <translation type="obsolete">Каскадом</translation>
+    </message>
+    <message>
+        <source>Close all</source>
+        <translation type="obsolete">Закрыть все</translation>
+    </message>
+    <message>
+        <source>UDAV Help</source>
+        <translation type="obsolete">Справка по UDAV</translation>
+    </message>
+    <message>
+        <source>&Help</source>
+        <translation type="obsolete">&Справка</translation>
+    </message>
+    <message>
+        <source>MGL &help</source>
+        <translation type="obsolete">MGL &справка</translation>
+    </message>
+    <message>
+        <source>Show help on MGL commands (F1).</source>
+        <translation type="obsolete">Показывает справку по текущей команде MGL (F1).</translation>
+    </message>
+    <message>
+        <source>&Examples</source>
+        <translation type="obsolete">&Примеры</translation>
+    </message>
+    <message>
+        <source>Show examples of MGL usage (Shift+F1).</source>
+        <translation type="obsolete">Показывает примеры использования MGL (Shift+F1).</translation>
+    </message>
+    <message>
+        <source>H&ints</source>
+        <translation type="obsolete">С&оветы</translation>
+    </message>
+    <message>
+        <source>Show hints of MGL usage.</source>
+        <translation type="obsolete">Показывает советы по использованию MGL.</translation>
+    </message>
+    <message>
+        <source>&About</source>
+        <translation type="obsolete">О &программе</translation>
+    </message>
+    <message>
+        <source>untitled - UDAV</source>
+        <translation type="obsolete">без имени - UDAV</translation>
+    </message>
+    <message>
+        <source>UDAV - save current</source>
+        <translation type="obsolete">UDAV - сохранить текущий код</translation>
+    </message>
+    <message>
+        <source>Do you want to save the changes to the document?</source>
+        <translation type="obsolete">Вы хотите сохранить изменения в коде?</translation>
+    </message>
+    <message>
+        <source>UDAV - Open file</source>
+        <translation type="obsolete">UDAV - Открыть файл</translation>
+    </message>
+    <message>
+        <source>MGL scripts (*.mgl)
+HDF5 files (*.hdf *.h5)
+Text files (*.txt)
+Data files (*.dat)
+All files (*.*)</source>
+        <translation type="obsolete">MGL код (*.mgl)
+HDF5 файлы (*.hdf *.h5)
+Текст (*.txt)
+Файлы данных (*.dat)
+Все файлы (*.*)</translation>
+    </message>
+    <message>
+        <source>Loading aborted</source>
+        <translation type="obsolete">Загрузка прервана</translation>
+    </message>
+    <message>
+        <source>UDAV - open file</source>
+        <translation type="obsolete">UDAV - открыть файл</translation>
+    </message>
+    <message>
+        <source>Couldn't open file</source>
+        <translation type="obsolete">Не могу открыть файл</translation>
+    </message>
+    <message>
+        <source>Loaded document </source>
+        <translation type="obsolete">Загружен документ </translation>
+    </message>
+    <message>
+        <source>Could not write to %1</source>
+        <translation type="obsolete">Не могу записать в %1</translation>
+    </message>
+    <message>
+        <source>File %1 saved</source>
+        <translation type="obsolete">Файл %1 сохранен</translation>
+    </message>
+    <message>
+        <source>UDAV - save file</source>
+        <translation type="obsolete">UDAV - сохранить файл</translation>
+    </message>
+    <message>
+        <source>MGL scripts (*.mgl)
+HDF5 files (*.hdf *.h5)
+All files (*.*)</source>
+        <translation type="obsolete">MGL код (*.mgl)
+HDF5 файлы (*.hdf *.h5)
+Все файлы (*.*)</translation>
+    </message>
+    <message>
+        <source>Saving aborted</source>
+        <translation type="obsolete">Сохранение прервано</translation>
+    </message>
+    <message>
+        <source>untitled* - UDAV</source>
+        <translation type="obsolete">без имени* - UDAV</translation>
+    </message>
+    <message>
+        <source>UDAV - Insert filename</source>
+        <translation type="obsolete">UDAV - Вставить имя файла</translation>
+    </message>
+    <message>
+        <source>Messages and warnings</source>
+        <translation type="obsolete">Сообщения и предупреждения</translation>
+    </message>
+    <message>
+        <source>Ready</source>
+        <translation type="obsolete">Готово</translation>
+    </message>
+    <message>
+        <source>Printing...</source>
+        <translation type="obsolete">Печатаю...</translation>
+    </message>
+    <message>
+        <source>Printing completed</source>
+        <translation type="obsolete">Печать завершена</translation>
+    </message>
+    <message>
+        <source>Printing aborted</source>
+        <translation type="obsolete">Печать прервана</translation>
+    </message>
+    <message>
+        <source>UDAV - find text</source>
+        <translation type="obsolete">UDAV - поиск текста</translation>
+    </message>
+    <message>
+        <source>No string occurrence is found</source>
+        <translation type="obsolete">Строка не найдена</translation>
+    </message>
+    <message>
+        <source>Not recognized</source>
+        <translation type="obsolete">Не распознано</translation>
+    </message>
+    <message>
+        <source>Loaded document %1</source>
+        <translation type="obsolete">Загружен документ %1</translation>
+    </message>
+    <message>
+        <source>&Data</source>
+        <translation type="obsolete">&Данные</translation>
+    </message>
+    <message>
+        <source>File Operations</source>
+        <translation type="obsolete">Работа с файлами</translation>
+    </message>
+    <message>
+        <source>&Load data</source>
+        <translation type="obsolete">&Загрузить данные</translation>
+    </message>
+    <message>
+        <source>Load data from file. Data will be deleted only
+at exit but UDAV will not ask to save it.</source>
+        <translation type="obsolete">Загрузить данные из файла. Данные будут удалены при
+выходе, но UDAV не спросит об их сохранении.</translation>
+    </message>
+    <message>
+        <source>&Import PNG</source>
+        <translation type="obsolete">&Импорт PNG</translation>
+    </message>
+    <message>
+        <source>Import data from PNG picture with specified color scheme.
+Data will be deleted only at exit but UDAV will not ask it saving.</source>
+        <translation type="obsolete">Импортировать данные из PNG рисунка с заданной цветовой схемой.
+Данные будут удалены при выходе, но UDAV не спросит об их сохранении.</translation>
+    </message>
+    <message>
+        <source>&Save data</source>
+        <translation type="obsolete">Сохранить &данные</translation>
+    </message>
+    <message>
+        <source>Save data to tab-separeted file.</source>
+        <translation type="obsolete">Сохранить данные в текстовый файл с разделителем табуляцией.</translation>
+    </message>
+    <message>
+        <source>&Export PNG</source>
+        <translation type="obsolete">&Экспорт PNG</translation>
+    </message>
+    <message>
+        <source>Export data to PNG picture. The colors defined by 
+specified color scheme. The same as in 'dens' command.</source>
+        <translation type="obsolete">Экспортирует данные в PNG рисунок. Цвета определяются
+указанной цветовой схемой. Рисунок аналогичен команде 'dens'.</translation>
+    </message>
+    <message>
+        <source>Plot &data</source>
+        <translation type="obsolete">&Отобразить данные</translation>
+    </message>
+    <message>
+        <source>Plot data in new script window. You may select the kind
+of plot, its style and so on.</source>
+        <translation type="obsolete">Отобразить данные в новом окне. Вы можете
+выбрать тип графика, его стиль и т.д.</translation>
+    </message>
+    <message>
+        <source>Resize data</source>
+        <translation type="obsolete">Размеры данных</translation>
+    </message>
+    <message>
+        <source>&Sizes</source>
+        <translation type="obsolete">&Размеры</translation>
+    </message>
+    <message>
+        <source>&Create new</source>
+        <translation type="obsolete">&Создать новые</translation>
+    </message>
+    <message>
+        <source>Recreate the data with new sizes and fill it by zeros (Ctrl+N).</source>
+        <translation type="obsolete">Создает заново данные нового размера и заполняет их нулями (Ctrl+N).</translation>
+    </message>
+    <message>
+        <source>&Resize</source>
+        <translation type="obsolete">&Изменить размер</translation>
+    </message>
+    <message>
+        <source>Resize (interpolate) the data to specified sizes (Ctrl+R).</source>
+        <translation type="obsolete">Изменяет размер (интерполирует) данных в указанному (Ctrl+R).</translation>
+    </message>
+    <message>
+        <source>&Squeeze</source>
+        <translation type="obsolete">С&жать</translation>
+    </message>
+    <message>
+        <source>Keep only each n-th element of the data array.</source>
+        <translation type="obsolete">Сохраняет каждый n-ый элемент массива данных.</translation>
+    </message>
+    <message>
+        <source>Cro&p</source>
+        <translation type="obsolete">О&брезать</translation>
+    </message>
+    <message>
+        <source>Crop the data edges. Useful to cut off the zero-filled area.</source>
+        <translation type="obsolete">Обрезает края данных. Полезно для удаления заполненных нулями областей.</translation>
+    </message>
+    <message>
+        <source>&Transpose</source>
+        <translation type="obsolete">&Транспонировать</translation>
+    </message>
+    <message>
+        <source>Transpose data dimensions, like x<->y or x<->z and so on.</source>
+        <translation type="obsolete">Транспонирует массив данных, типа x<->y или x<->z и т.д.</translation>
+    </message>
+    <message>
+        <source>Re&arrange</source>
+        <translation type="obsolete">По&менять размеры</translation>
+    </message>
+    <message>
+        <source>Rearrange data sizes without changing data values.</source>
+        <translation type="obsolete">Меняет размеры данных без изменения самого массива данных.</translation>
+    </message>
+    <message>
+        <source>Modify data</source>
+        <translation type="obsolete">Изменить данные</translation>
+    </message>
+    <message>
+        <source>&Modify</source>
+        <translation type="obsolete">&Изменить</translation>
+    </message>
+    <message>
+        <source>By &formula</source>
+        <translation type="obsolete">По &формуле</translation>
+    </message>
+    <message>
+        <source>Change data values according to formula depended on 'x', 'y' and 'z'
+variables. A set of special function is availible also.</source>
+        <translation type="obsolete">Изменяет данные по формуле, зависяещей от переменных 'x', 'y' и 'z'.
+Поддерживаются также многие специальные функции.</translation>
+    </message>
+    <message>
+        <source>Fill in &range</source>
+        <translation type="obsolete">&Распределить</translation>
+    </message>
+    <message>
+        <source>Fill data equidistantly from one value to another.</source>
+        <translation type="obsolete">Распределить равномерно данные от одного значения до другого.</translation>
+    </message>
+    <message>
+        <source>&Normalize</source>
+        <translation type="obsolete">&Нормировать</translation>
+    </message>
+    <message>
+        <source>Normalize data so that its minimal
+and maximal values be in specified range.</source>
+        <translation type="obsolete">Нормирует данные так, что их максимальное и
+минимальное значения равны заданным.</translation>
+    </message>
+    <message>
+        <source>Norm. s&lices</source>
+        <translation type="obsolete">Норм. по &срезам</translation>
+    </message>
+    <message>
+        <source>Normalize each data slice perpendicular to some direction
+so that its minimal and maximal values be in specified range.</source>
+        <translation type="obsolete">Нормирует данные по срезам перпендикулярно 
+заданному направлению так, что их максимальное
+и минимальное значения равны заданным.</translation>
+    </message>
+    <message>
+        <source>&Smooth data</source>
+        <translation type="obsolete">С&гладить</translation>
+    </message>
+    <message>
+        <source>Smooth data by one of 4 methods along specified direction(s).</source>
+        <translation type="obsolete">Сглаживает данные одним из 4-х методов вдоль заданного направления(ий).</translation>
+    </message>
+    <message>
+        <source>&Operators</source>
+        <translation type="obsolete">&Опраторы</translation>
+    </message>
+    <message>
+        <source>&Cum. sum</source>
+        <translation type="obsolete">&Суммировать</translation>
+    </message>
+    <message>
+        <source>Summate data values along specified direction(s).</source>
+        <translation type="obsolete">Суммирует данные вдоль указанного направления(ий).</translation>
+    </message>
+    <message>
+        <source>&Integrate</source>
+        <translation type="obsolete">&Интегрировать</translation>
+    </message>
+    <message>
+        <source>Integrate data values along specified direction(s).</source>
+        <translation type="obsolete">Интегрирует данные по заданному направлению(ям).</translation>
+    </message>
+    <message>
+        <source>&Differentiate</source>
+        <translation type="obsolete">&Дифференцировать</translation>
+    </message>
+    <message>
+        <source>Differentiate data values along specified direction(s).</source>
+        <translation type="obsolete">Дифференцирует данные по заданному направлению(ям).</translation>
+    </message>
+    <message>
+        <source>&Laplace</source>
+        <translation type="obsolete">&Лаплас</translation>
+    </message>
+    <message>
+        <source>Double differentiate data values along specified direction(s).</source>
+        <translation type="obsolete">Дважды дифференцирует данные по заданному направлению(ям).</translation>
+    </message>
+    <message>
+        <source>&Swap</source>
+        <translation type="obsolete">&Поменять местами</translation>
+    </message>
+    <message>
+        <source>Swap left and right data part along specified direction(s).
+This operation is useful for data after Fourier transform.</source>
+        <translation type="obsolete">Меняет местами левую и правую часть данных вдоль указанного направления(ий).
+Операция полезна для данных после Фурье преобразования.</translation>
+    </message>
+    <message>
+        <source>&Mirror</source>
+        <translation type="obsolete">&Отразить</translation>
+    </message>
+    <message>
+        <source>Mirror left and right data part along specified direction(s).
+This operation do like index change from 'i' to 'n-i'.</source>
+        <translation type="obsolete">Отражает данные относительно указанного направления(ий).
+Действует как замена индекса 'i' на 'n-i'.</translation>
+    </message>
+    <message>
+        <source>&Algebraic</source>
+        <translation type="obsolete">&Алгебраические</translation>
+    </message>
+    <message>
+        <source>&Add</source>
+        <translation type="obsolete">&Добавить</translation>
+    </message>
+    <message>
+        <source>Add a number to all data values.</source>
+        <translation type="obsolete">Добавляет число к элементам массива данных.</translation>
+    </message>
+    <message>
+        <source>&Subtract</source>
+        <translation type="obsolete">&Вычесть</translation>
+    </message>
+    <message>
+        <source>Subtract a number to all data values.</source>
+        <translation type="obsolete">Вычитает из элементов массива данных число.</translation>
+    </message>
+    <message>
+        <source>&Multiply</source>
+        <translation type="obsolete">&Умножить</translation>
+    </message>
+    <message>
+        <source>Multiply all data values by a number.</source>
+        <translation type="obsolete">Умножает элементы массива данных на число.</translation>
+    </message>
+    <message>
+        <source>&Divide</source>
+        <translation type="obsolete">&Разделить</translation>
+    </message>
+    <message>
+        <source>Divide all data values by a number.</source>
+        <translation type="obsolete">Делит элементы массива данных на число.</translation>
+    </message>
+    <message>
+        <source>A&nother data</source>
+        <translation type="obsolete">&Новые данные</translation>
+    </message>
+    <message>
+        <source>&Sum of</source>
+        <translation type="obsolete">&Сумма по</translation>
+    </message>
+    <message>
+        <source>M&in of</source>
+        <translation type="obsolete">М&инимум по</translation>
+    </message>
+    <message>
+        <source>M&ax of</source>
+        <translation type="obsolete">М&аксимум по</translation>
+    </message>
+    <message>
+        <source>Momentum along &x</source>
+        <translation type="obsolete">Момент вдоль &x</translation>
+    </message>
+    <message>
+        <source>Momentum along &y</source>
+        <translation type="obsolete">Момент вдоль &y</translation>
+    </message>
+    <message>
+        <source>Momentum along &z</source>
+        <translation type="obsolete">Момент вдоль &z</translation>
+    </message>
+    <message>
+        <source>&Histogram</source>
+        <translation type="obsolete">&Гистограмма</translation>
+    </message>
+    <message>
+        <source>Navigate data</source>
+        <translation type="obsolete">Переход к срезам</translation>
+    </message>
+    <message>
+        <source>&Navigate</source>
+        <translation type="obsolete">Пере&ход</translation>
+    </message>
+    <message>
+        <source>&First slice</source>
+        <translation type="obsolete">&Первый срез</translation>
+    </message>
+    <message>
+        <source>Go to the first data slice for 3D data.</source>
+        <translation type="obsolete">Перейти к первому срезу 3D данных.</translation>
+    </message>
+    <message>
+        <source>&Prev. slice</source>
+        <translation type="obsolete">&Предыдущий срез</translation>
+    </message>
+    <message>
+        <source>Go to the previous data slice for 3D data.</source>
+        <translation type="obsolete">Перейти к предыдущему срезу 3D данных.</translation>
+    </message>
+    <message>
+        <source>Go to the specified data slice for 3D data.</source>
+        <translation type="obsolete">Перейти к указанному срезу 3D данных.</translation>
+    </message>
+    <message>
+        <source>Go to slice</source>
+        <translation type="obsolete">Перейти к срезу</translation>
+    </message>
+    <message>
+        <source>Next slice</source>
+        <translation type="obsolete">Следующий срез</translation>
+    </message>
+    <message>
+        <source>Go to the next data slice for 3D data.</source>
+        <translation type="obsolete">Перейти к следующему срезу 3D данных.</translation>
+    </message>
+    <message>
+        <source>Last slice</source>
+        <translation type="obsolete">Последний срез</translation>
+    </message>
+    <message>
+        <source>Go to the last data slice for 3D data.</source>
+        <translation type="obsolete">Перейти к последнему срезу 3D данных.</translation>
+    </message>
+    <message>
+        <source>About Qt</source>
+        <translation type="obsolete">О библиотеке Qt</translation>
+    </message>
+    <message>
+        <source>About &Qt</source>
+        <translation type="obsolete">О библиотеке &Qt</translation>
+    </message>
+    <message>
+        <source>Couldn't change to folder </source>
+        <translation type="obsolete">Не могу перейти в папку </translation>
+    </message>
+    <message>
+        <source>Couldn't open file </source>
+        <translation type="obsolete">Не могу открыть файл </translation>
+    </message>
+    <message>
+        <source>&Copy text</source>
+        <translation type="obsolete">&Копировать текст</translation>
+    </message>
+    <message>
+        <source>&Paste text</source>
+        <translation type="obsolete">&Вставить текст</translation>
+    </message>
+    <message>
+        <source>File name</source>
+        <translation type="obsolete">Имя файла</translation>
+    </message>
+</context>
+<context>
+    <name>SetupDialog</name>
+    <message>
+        <source>UDAV - Setup plot</source>
+        <translation>UDAV - Настройка графика</translation>
+    </message>
+    <message>
+        <source>X axis</source>
+        <translation>Ось X</translation>
+    </message>
+    <message>
+        <source>Y axis</source>
+        <translation>Ось Y</translation>
+    </message>
+    <message>
+        <source>Z axis</source>
+        <translation>Ось Z</translation>
+    </message>
+    <message>
+        <source>C axis</source>
+        <translation>Ось C</translation>
+    </message>
+    <message>
+        <source>Minimal</source>
+        <translation>Минимум</translation>
+    </message>
+    <message>
+        <source>Maximal</source>
+        <translation>Максимум</translation>
+    </message>
+    <message>
+        <source>Origin</source>
+        <translation>Начало осей</translation>
+    </message>
+    <message>
+        <source>Label</source>
+        <translation>Подпись</translation>
+    </message>
+    <message>
+        <source>at position</source>
+        <translation>в позиции</translation>
+    </message>
+    <message>
+        <source>at minimum</source>
+        <translation>минимума</translation>
+    </message>
+    <message>
+        <source>at center</source>
+        <translation>по центру</translation>
+    </message>
+    <message>
+        <source>at maximum</source>
+        <translation>максимума</translation>
+    </message>
+    <message>
+        <source>Ticks</source>
+        <translation>Метки</translation>
+    </message>
+    <message>
+        <source>SubTicks</source>
+        <translation>Под-метки</translation>
+    </message>
+    <message>
+        <source>Start</source>
+        <translation>Начало меток</translation>
+    </message>
+    <message>
+        <source>Template</source>
+        <translation>Шаблон</translation>
+    </message>
+    <message>
+        <source>AlphaDef</source>
+        <translation>Базовая прозрачность</translation>
+    </message>
+    <message>
+        <source>Ambient</source>
+        <translation>Фоновый свет</translation>
+    </message>
+    <message>
+        <source>BaseWidth</source>
+        <translation>Базовая ширина</translation>
+    </message>
+    <message>
+        <source>MeshNum</source>
+        <translation>Число линий сетки</translation>
+    </message>
+    <message>
+        <source>AxialDir</source>
+        <translation>Ось вращения</translation>
+    </message>
+    <message>
+        <source>Font</source>
+        <translation>Стиль текста</translation>
+    </message>
+    <message>
+        <source>FontSize</source>
+        <translation>Размер текста</translation>
+    </message>
+    <message>
+        <source>Alpha on</source>
+        <translation>Прозрачность</translation>
+    </message>
+    <message>
+        <source>Light on</source>
+        <translation>Освещение</translation>
+    </message>
+    <message>
+        <source>No text rotation</source>
+        <translation>Запрет вращения текста</translation>
+    </message>
+    <message>
+        <source>General settings</source>
+        <translation>Общие настройки</translation>
+    </message>
+    <message>
+        <source>State</source>
+        <translation>Состояние</translation>
+    </message>
+    <message>
+        <source>Color</source>
+        <translation>Цвет</translation>
+    </message>
+    <message>
+        <source>Brightness</source>
+        <translation>Яркость</translation>
+    </message>
+    <message>
+        <source>Light settings</source>
+        <translation>Настройки освещения</translation>
+    </message>
+    <message>
+        <source>Template name</source>
+        <translation>Имя шаблона</translation>
+    </message>
+    <message>
+        <source>Save</source>
+        <translation>Сохранить</translation>
+    </message>
+    <message>
+        <source>Cancel</source>
+        <translation>Отмена</translation>
+    </message>
+    <message>
+        <source>To script</source>
+        <translation>В код</translation>
+    </message>
+    <message>
+        <source>UDAV - Save template</source>
+        <translation>UDAV - Сохранить шаблон</translation>
+    </message>
+    <message>
+        <source>Could not write to file</source>
+        <translation>Не могу записать в файл</translation>
+    </message>
+    <message>
+        <source>Template saved</source>
+        <translation>Шаблон сохранен</translation>
+    </message>
+    <message>
+        <source>Light position should be filled. Ignore it.</source>
+        <translation>Положение источника должно быть заполнено. Игнорирую.</translation>
+    </message>
+    <message>
+        <source>ID</source>
+        <translation></translation>
+    </message>
+    <message>
+        <source>X pos</source>
+        <translation></translation>
+    </message>
+    <message>
+        <source>Y pos</source>
+        <translation></translation>
+    </message>
+    <message>
+        <source>Z pos</source>
+        <translation></translation>
+    </message>
+    <message>
+        <source>on</source>
+        <translation>вкл</translation>
+    </message>
+</context>
+<context>
+    <name>StyleDialog</name>
+    <message>
+        <source>UDAV - Insert style/scheme</source>
+        <translation>UDAV - Вставить стиль/схему</translation>
+    </message>
+    <message>
+        <source>Arrow at start</source>
+        <translation>Стрелка в начале</translation>
+    </message>
+    <message>
+        <source>Dashing</source>
+        <translation>Пунктир</translation>
+    </message>
+    <message>
+        <source>Arrow at end</source>
+        <translation>Стрелка в конце</translation>
+    </message>
+    <message>
+        <source>Color</source>
+        <translation>Цвет</translation>
+    </message>
+    <message>
+        <source>Marks</source>
+        <translation>Маркер</translation>
+    </message>
+    <message>
+        <source>Line width</source>
+        <translation>Толщина</translation>
+    </message>
+    <message>
+        <source>Line style</source>
+        <translation>Стиль линии</translation>
+    </message>
+    <message>
+        <source>Color order</source>
+        <translation>Порядок цветов</translation>
+    </message>
+    <message>
+        <source>Saturation</source>
+        <translation>Насыщенность</translation>
+    </message>
+    <message>
+        <source>Colors along coordinates</source>
+        <translation>Цвет вдоль координат</translation>
+    </message>
+    <message>
+        <source>Wire or mesh plot</source>
+        <translation>Сетчатый график</translation>
+    </message>
+    <message>
+        <source>Axial direction</source>
+        <translation>Ось вращения</translation>
+    </message>
+    <message>
+        <source>Text on contours</source>
+        <translation>Текст на контурах</translation>
+    </message>
+    <message>
+        <source>none</source>
+        <translation>нет</translation>
+    </message>
+    <message>
+        <source>under</source>
+        <translation>под</translation>
+    </message>
+    <message>
+        <source>above</source>
+        <translation>над</translation>
+    </message>
+    <message>
+        <source>Color scheme</source>
+        <translation>Цветовая схема</translation>
+    </message>
+    <message>
+        <source>Bold style</source>
+        <translation>Жирный</translation>
+    </message>
+    <message>
+        <source>Italic style</source>
+        <translation>Курсив</translation>
+    </message>
+    <message>
+        <source>Wire style</source>
+        <translation>Контур</translation>
+    </message>
+    <message>
+        <source>Underline</source>
+        <translation>Подчеркнутый</translation>
+    </message>
+    <message>
+        <source>Overline</source>
+        <translation>Надчеркнутый</translation>
+    </message>
+    <message>
+        <source>Text color</source>
+        <translation>Цвет текста</translation>
+    </message>
+    <message>
+        <source>Text align</source>
+        <translation>Выравнивание</translation>
+    </message>
+    <message>
+        <source>left</source>
+        <translation>влево</translation>
+    </message>
+    <message>
+        <source>at center</source>
+        <translation>по центру</translation>
+    </message>
+    <message>
+        <source>right</source>
+        <translation>вправо</translation>
+    </message>
+    <message>
+        <source>Font style</source>
+        <translation>Стиль текста</translation>
+    </message>
+    <message>
+        <source>Resulting string</source>
+        <translation>Результат</translation>
+    </message>
+    <message>
+        <source>Cancel</source>
+        <translation>Отмена</translation>
+    </message>
+    <message>
+        <source>OK</source>
+        <translation>OK</translation>
+    </message>
+</context>
+<context>
+    <name>TableWindow</name>
+    <message>
+        <source> - UDAV variable</source>
+        <translation type="obsolete"> - UDAV переменная</translation>
+    </message>
+    <message>
+        <source> - UDAV preview</source>
+        <translation type="obsolete"> - UDAV просмотр</translation>
+    </message>
+    <message>
+        <source>UDAV - Import PNG</source>
+        <translation type="obsolete">UDAV - Импорт PNG</translation>
+    </message>
+    <message>
+        <source>Data files (*.dat)
+All files (*.*)</source>
+        <translation type="obsolete">Файлы данных (*.dat)
+Все файлы (*.*)</translation>
+    </message>
+    <message>
+        <source>UDAV - Export to PNG</source>
+        <translation type="obsolete">UDAV - Экспорт в PNG</translation>
+    </message>
+    <message>
+        <source>Enter color scheme for picture.
+Note that data will be normalized in range [0,1].</source>
+        <translation type="obsolete">Введите цветовую схему рисунка.
+Данные будут нормированы в [0,1].</translation>
+    </message>
+    <message>
+        <source>PNG files (*.png)
+All files (*.*)</source>
+        <translation type="obsolete">PNG файлы (*.png)
+Все файлы (*.*)</translation>
+    </message>
+    <message>
+        <source>Enter color scheme for picture</source>
+        <translation type="obsolete">Введите цветовую схему рисунка</translation>
+    </message>
+    <message>
+        <source>UDAV - Save data</source>
+        <translation type="obsolete">UDAV - Сохранить данные</translation>
+    </message>
+    <message>
+        <source>UDAV - Load data</source>
+        <translation type="obsolete">UDAV - Загрузить данные</translation>
+    </message>
+    <message>
+        <source>UDAV - Fill data</source>
+        <translation type="obsolete">UDAV - Заполнить данные</translation>
+    </message>
+    <message>
+        <source>Enter formula for data filling.
+Note that variables x,y,z supposed to be in range [0,1].</source>
+        <translation type="obsolete">Введите формулу для данных.
+Переменные x,y,z меняются в интервале [0,1].</translation>
+    </message>
+    <message>
+        <source>Enter range for data and direction of filling</source>
+        <translation type="obsolete">Введите диапазон и направление заполнения</translation>
+    </message>
+    <message>
+        <source>From</source>
+        <translation type="obsolete">От</translation>
+    </message>
+    <message>
+        <source>To</source>
+        <translation type="obsolete">До</translation>
+    </message>
+    <message>
+        <source>Direction</source>
+        <translation type="obsolete">Направление</translation>
+    </message>
+    <message>
+        <source>UDAV - Normalize data</source>
+        <translation type="obsolete">UDAV - Нормировать данные</translation>
+    </message>
+    <message>
+        <source>Enter range for final data</source>
+        <translation type="obsolete">Введите диапазон результата</translation>
+    </message>
+    <message>
+        <source>Symmetrical?</source>
+        <translation type="obsolete">Симметрично?</translation>
+    </message>
+    <message>
+        <source>UDAV - Normalize by slice</source>
+        <translation type="obsolete">UDAV - Нормировать по срезам</translation>
+    </message>
+    <message>
+        <source>UDAV - Clear data</source>
+        <translation type="obsolete">UDAV - Очистить данные</translation>
+    </message>
+    <message>
+        <source>Enter new data sizes</source>
+        <translation type="obsolete">Введите новые размеры</translation>
+    </message>
+    <message>
+        <source>X-size</source>
+        <translation type="obsolete">Размер по X</translation>
+    </message>
+    <message>
+        <source>Y-size</source>
+        <translation type="obsolete">Размер по Y</translation>
+    </message>
+    <message>
+        <source>Z-size</source>
+        <translation type="obsolete">Размер по Z</translation>
+    </message>
+    <message>
+        <source>UDAV - Resize data</source>
+        <translation type="obsolete">UDAV - Изменить размер данных</translation>
+    </message>
+    <message>
+        <source>UDAV - Squeeze data</source>
+        <translation type="obsolete">UDAV - Сжать данные</translation>
+    </message>
+    <message>
+        <source>Enter step of saved points. For example, '1' save all, '2' save each 2nd point, '3' save each 3d and so on.</source>
+        <translation type="obsolete">Введите шаг сохраняемых точек. Например, '1' сохранить все, '2' каждую вторую точку, '3' каждую третью и т.д.</translation>
+    </message>
+    <message>
+        <source>X-direction</source>
+        <translation type="obsolete">X направление</translation>
+    </message>
+    <message>
+        <source>Y-direction</source>
+        <translation type="obsolete">Y направление</translation>
+    </message>
+    <message>
+        <source>Z-direction</source>
+        <translation type="obsolete">Z направление</translation>
+    </message>
+    <message>
+        <source>UDAV - Crop data</source>
+        <translation type="obsolete">UDAV - Обрезать данные</translation>
+    </message>
+    <message>
+        <source>Enter range of saved date.</source>
+        <translation type="obsolete">Введите интервал сохраняемых данных.</translation>
+    </message>
+    <message>
+        <source>UDAV - Rearrange data</source>
+        <translatorcomment>Не знаю хорошего русского термина</translatorcomment>
+        <translation type="obsolete">UDAV - Поменять размеры данных</translation>
+    </message>
+    <message>
+        <source>UDAV - Transpose data</source>
+        <translation type="obsolete">UDAV - Транспонировать данные</translation>
+    </message>
+    <message>
+        <source>Enter new order of dimensions.
+For example, 'yx' or 'yxz' for transpose x-y, 'zyx' for transposing x-z and so on.</source>
+        <translation type="obsolete">Введите новый порядок размерностей.
+Например, 'yx' или 'yxz' для транспонирования x-y, 'zyx' для транспонирования x-z и т.д.</translation>
+    </message>
+    <message>
+        <source>UDAV - Smooth data</source>
+        <translation type="obsolete">UDAV - Сгладить данные</translation>
+    </message>
+    <message>
+        <source>Enter direction(s) for smoothing.
+Optionally you may enter the kind of smoothing by 3 or by 5 points. For example 'xy3' - smooth only in x and y directions and use 3-points scheme.</source>
+        <translation type="obsolete">Введите направление(я) сглаживания.
+Можно также ввести тип сглаживания по 3 или по 5 точкам. Например 'xy3' - сгладит только в x и y направлениях по 3-точечной схеме.</translation>
+    </message>
+    <message>
+        <source>UDAV - Summarize data</source>
+        <translation type="obsolete">UDAV - Суммировать данные</translation>
+    </message>
+    <message>
+        <source>Enter direction(s) for cumulative summation.
+For example 'xy' - summate along x and y directions.</source>
+        <translation type="obsolete">Введите направление(я) для суммирования.
+Например 'xy' - суммировать вдоль x и y направлений.</translation>
+    </message>
+    <message>
+        <source>UDAV - Integrate data</source>
+        <translation type="obsolete">UDAV - Интегрировать данные</translation>
+    </message>
+    <message>
+        <source>Enter direction(s) for integration.
+For example 'xy' - integrate along x and y directions.</source>
+        <translation type="obsolete">Введите направление(я) для инткгрирования.
+Например 'xy' - интегрировать вдоль x и y направлений.</translation>
+    </message>
+    <message>
+        <source>UDAV - Differentiate data</source>
+        <translation type="obsolete">UDAV - Дифференцировать данные</translation>
+    </message>
+    <message>
+        <source>Enter direction(s) for differentiation.
+For example 'xy' - differentiate along x and y directions.</source>
+        <translation type="obsolete">Введите направление(я) для дифференцирования.
+Например 'xy' - дифференцировать вдоль x и y направлений.</translation>
+    </message>
+    <message>
+        <source>UDAV - Laplace transform</source>
+        <translation type="obsolete">UDAV - Преобразование Лапласа</translation>
+    </message>
+    <message>
+        <source>Enter direction(s) for laplace transform.
+For example 'xy' - do transform along x and y directions.</source>
+        <translation type="obsolete">Введите направление(я) для преобразования Лапласа.
+Например 'xy' - преобразовать вдоль x и y направлений.</translation>
+    </message>
+    <message>
+        <source>UDAV - Swap data</source>
+        <translation type="obsolete">UDAV - Поменять местами</translation>
+    </message>
+    <message>
+        <source>Enter direction(s) for swapping (exchange left and right parts).
+For example 'xy' - swap along x and y directions. Useful for Fourier spectrum.</source>
+        <translation type="obsolete">Введите направление(я) для обмена левой и правой частями данных.
+Например 'xy' - меняет вдоль x и y направлений. Полезно для Фурье спектров.</translation>
+    </message>
+    <message>
+        <source>UDAV - Mirror data</source>
+        <translation type="obsolete">UDAV - Отразить данные</translation>
+    </message>
+    <message>
+        <source>Enter direction(s) for mirroring.
+For example 'xy' - mirror along x and y directions.</source>
+        <translation type="obsolete">Введите направление(я) для отражения.
+Например 'xy' - отразить по x и y направлениям.</translation>
+    </message>
+    <message>
+        <source>UDAV - Sum along ...</source>
+        <translation type="obsolete">UDAV - Сумма по ...</translation>
+    </message>
+    <message>
+        <source>Specify direction(s) of summation</source>
+        <translation type="obsolete">Введите направление(я) суммирования</translation>
+    </message>
+    <message>
+        <source>UDAV - Max along ...</source>
+        <translation type="obsolete">UDAV - Максимум по ...</translation>
+    </message>
+    <message>
+        <source>Specify direction(s) of maximal values</source>
+        <translation type="obsolete">Введите направление(я) поиска максимумов</translation>
+    </message>
+    <message>
+        <source>UDAV - Min along ...</source>
+        <translation type="obsolete">UDAV - Минимум по ...</translation>
+    </message>
+    <message>
+        <source>Specify direction(s) of minimal values</source>
+        <translation type="obsolete">Введите направление(я) поиска минимумов</translation>
+    </message>
+    <message>
+        <source>UDAV - Momentum along 'x'</source>
+        <translation type="obsolete">UDAV - Момент по 'x'</translation>
+    </message>
+    <message>
+        <source>Specify which momentum evaluate.
+The momentum is res_i = sum_jk how(x_i,y_j,z_k) a_jk/ sum_jk a_jk.
+Coordinates x, y, z are data indexes normalized in range [0,1].</source>
+        <translation type="obsolete">Укажите какой момент вычислять.
+Момент равен res_i = Σ_jk how(x_i,y_j,z_k) a_jk/ Σ_jk a_jk.
+Координаты x, y, z находятся в диапазоне [0,1].</translation>
+    </message>
+    <message>
+        <source>Specify which momentum evaluate.
+The momentum is res_j = sum_ik how(x_i,y_j,z_k) a_ik/ sum_ik a_ik.
+Coordinates x, y, z are data indexes normalized in range [0,1].</source>
+        <translation type="obsolete">Укажите какой момент вычислять.
+Момент равен res_j = Σ_ik how(x_i,y_j,z_k) a_ik/ Σ_ik a_ik.
+Координаты x, y, z находятся в диапазоне [0,1].</translation>
+    </message>
+    <message>
+        <source>Specify which momentum evaluate.
+The momentum is res_k = sum_ij how(x_i,y_j,z_k) a_ij/ sum_ij a_ij.
+Coordinates x, y, z are data indexes normalized in range [0,1].</source>
+        <translation type="obsolete">Укажите какой момент вычислять.
+Момент равен res_k = Σ_ij how(x_i,y_j,z_k) a_ij/ Σ_ij a_ij.
+Координаты x, y, z находятся в диапазоне [0,1].</translation>
+    </message>
+    <message>
+        <source>UDAV - Momentum along 'y'</source>
+        <translation type="obsolete">UDAV - Момент по 'y'</translation>
+    </message>
+    <message>
+        <source>UDAV - Momentum along 'z'</source>
+        <translation type="obsolete">UDAV - Момент по 'z'</translation>
+    </message>
+    <message>
+        <source>UDAV - Make histogram</source>
+        <translation type="obsolete">UDAV - Найти гистограмму</translation>
+    </message>
+    <message>
+        <source>Number of points</source>
+        <translation type="obsolete">Число точек</translation>
+    </message>
+    <message>
+        <source>Put in variable</source>
+        <translation type="obsolete">Поместить в переменную</translation>
+    </message>
+    <message>
+        <source>Cancel</source>
+        <translation type="obsolete">Отмена</translation>
+    </message>
+    <message>
+        <source>OK</source>
+        <translation type="obsolete">OK</translation>
+    </message>
+    <message>
+        <source>UDAV - Change data</source>
+        <translation type="obsolete">UDAV - Изменить данные</translation>
+    </message>
+    <message>
+        <source>Enter number for adding to data elements:</source>
+        <translation type="obsolete">Введите число для добавления к элементам массива:</translation>
+    </message>
+    <message>
+        <source>Enter number for subtraction from data elements:</source>
+        <translation type="obsolete">Введите число для вычитания из элементов массива:</translation>
+    </message>
+    <message>
+        <source>Enter number for division of data elements:</source>
+        <translation type="obsolete">Введите число для деления элементов массива:</translation>
+    </message>
+    <message>
+        <source>Enter number for multiplication of data elements:</source>
+        <translation type="obsolete">Введите число для умножения элементов массива:</translation>
+    </message>
+    <message>
+        <source>UDAV - Go to slice</source>
+        <translation type="obsolete">UDAV - Перейти к срезу</translation>
+    </message>
+    <message>
+        <source>Enter slice id:</source>
+        <translation type="obsolete">Введите номер среза:</translation>
+    </message>
+    <message>
+        <source>NOTE: All fields must be filled!</source>
+        <translation type="obsolete">Все поля должны быть заполнены!</translation>
+    </message>
+    <message>
+        <source>Enter the name for new variable</source>
+        <translation type="obsolete">Введите имя новой переменной</translation>
+    </message>
+</context>
+<context>
+    <name>TextPanel</name>
+    <message>
+        <source>&Edit</source>
+        <translation>&Правка</translation>
+    </message>
+    <message>
+        <source>UDAV - Insert filename</source>
+        <translation>UDAV - Вставить имя файла</translation>
+    </message>
+    <message>
+        <source>Printing...</source>
+        <translation>Печатаю...</translation>
+    </message>
+    <message>
+        <source>Printing completed</source>
+        <translation>Печать завершена</translation>
+    </message>
+    <message>
+        <source>Printing aborted</source>
+        <translation>Печать прервана</translation>
+    </message>
+    <message>
+        <source>UDAV - find text</source>
+        <translation>UDAV - поиск текста</translation>
+    </message>
+    <message>
+        <source>No string occurrence is found</source>
+        <translation>Строка не найдена</translation>
+    </message>
+    <message>
+        <source>Loaded document %1</source>
+        <translation>Загружен документ %1</translation>
+    </message>
+    <message>
+        <source>Could not write to %1</source>
+        <translation>Не могу записать в %1</translation>
+    </message>
+    <message>
+        <source>File %1 saved</source>
+        <translation>Файл %1 сохранен</translation>
+    </message>
+    <message>
+        <source>UDAV - open file</source>
+        <translation>UDAV - открыть файл</translation>
+    </message>
+    <message>
+        <source>Couldn't open file </source>
+        <translation>Не могу открыть файл </translation>
+    </message>
+    <message>
+        <source>Loaded document </source>
+        <translation>Загружен документ </translation>
+    </message>
+    <message>
+        <source>&Undo</source>
+        <translation>&Отменить</translation>
+    </message>
+    <message>
+        <source>Undo editor change (Ctrl+Z).</source>
+        <translation>Отменить изменения в редакторе (Ctrl+Z).</translation>
+    </message>
+    <message>
+        <source>&Redo</source>
+        <translation>&Вернуть</translation>
+    </message>
+    <message>
+        <source>Redo editor change (Ctrl+Shift+Z).</source>
+        <translation>Вернуть изменения в редакторе (Ctrl+Shift+Z).</translation>
+    </message>
+    <message>
+        <source>Clear all</source>
+        <translation>Очистить все</translation>
+    </message>
+    <message>
+        <source>Cu&t text</source>
+        <translation>В&ырезать</translation>
+    </message>
+    <message>
+        <source>Cut selected text to clipboard (Ctrl+X).</source>
+        <translation>Вырезать выделенный текст в буфер обмена (Ctrl+X).</translation>
+    </message>
+    <message>
+        <source>&Copy text</source>
+        <translation>&Копировать текст</translation>
+    </message>
+    <message>
+        <source>Copy selected text or data to clipboard (Ctrl+C).</source>
+        <translation>Копировать выделенный текст в буфер обмена (Ctrl+C).</translation>
+    </message>
+    <message>
+        <source>&Paste text</source>
+        <translation>&Вставить текст</translation>
+    </message>
+    <message>
+        <source>Paste text or data from clipboard (Ctrl+V).</source>
+        <translation>Вставить текст или данные из буфера обмена (Ctrl+V).</translation>
+    </message>
+    <message>
+        <source>Select &all</source>
+        <translation>Выделить вс&е</translation>
+    </message>
+    <message>
+        <source>&Find/Replace</source>
+        <translation>&Найти/заменить</translation>
+    </message>
+    <message>
+        <source>Show dialog for text finding (Ctrl+F).</source>
+        <translation>Показать диалог поиска текста (Ctrl+F).</translation>
+    </message>
+    <message>
+        <source>Find next</source>
+        <translation>Найти текст</translation>
+    </message>
+    <message>
+        <source>Insert</source>
+        <translation>Вставить</translation>
+    </message>
+    <message>
+        <source>New command</source>
+        <translation>Новая команда</translation>
+    </message>
+    <message>
+        <source>Show dialog for new command and put it into the script.</source>
+        <translation>Показать диалог вставки новой команды.</translation>
+    </message>
+    <message>
+        <source>Fitted formula</source>
+        <translation>Найденная формула</translation>
+    </message>
+    <message>
+        <source>Insert last fitted formula with found coefficients.</source>
+        <translation>Вставить последнюю найденную формулу в текст.</translation>
+    </message>
+    <message>
+        <source>Plot style</source>
+        <translation>Стиль графика</translation>
+    </message>
+    <message>
+        <source>Show dialog for styles and put it into the script.
+Styles define the plot view (color scheme, marks, dashing and so on).</source>
+        <translation>Показать диалог стиля графика и вставить его в код.
+Стиль определяет вид графика (цвет, маркеры, пунктир и пр).</translation>
+    </message>
+    <message>
+        <source>Command options</source>
+        <translation>Опции команды</translation>
+    </message>
+    <message>
+        <source>Show dialog for options and put it into the script.
+Options are used for additional setup the plot.</source>
+        <translation>Показать диалог выбора опций команды. Опции используются 
+для дополнительной настройки выбранного графика.</translation>
+    </message>
+    <message>
+        <source>Numeric value</source>
+        <translation>Численное значение</translation>
+    </message>
+    <message>
+        <source>Replace expression by its numerical value.</source>
+        <translation>Заменить выделенное выражение его числовым значением.</translation>
+    </message>
+    <message>
+        <source>File name</source>
+        <translation>Имя файла</translation>
+    </message>
+    <message>
+        <source>Select and insert file name.</source>
+        <translation>Выбрать и вставить путь файла.</translation>
+    </message>
+    <message>
+        <source>Folder path</source>
+        <translation>Путь папки</translation>
+    </message>
+    <message>
+        <source>Select and insert folder name.</source>
+        <translation>Выбрать и вставить путь папки.</translation>
+    </message>
+    <message>
+        <source>Graphics setup</source>
+        <translation>Настройка графика</translation>
+    </message>
+    <message>
+        <source>Show dialog for plot setup and put code into the script.
+This dialog setup axis, labels, lighting and other general things.</source>
+        <translation>Показать диалог настройки графика и вставить ее в код.
+Диалог позволяет настроить оси, подписи, освещение и пр.</translation>
+    </message>
+</context>
+</TS>
diff --git a/udav/udav_wnd.cpp b/udav/udav_wnd.cpp
new file mode 100644
index 0000000..893bb55
--- /dev/null
+++ b/udav/udav_wnd.cpp
@@ -0,0 +1,779 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifdef WIN32
+#include <io.h>
+#include <direct.h>
+#else
+#include <unistd.h>
+#endif
+#include <QMenuBar>
+#include <QMessageBox>
+#include <QApplication>
+#include <QSettings>
+#include <QSplitter>
+#include <QFileDialog>
+#include <QStatusBar>
+#include <QDockWidget>
+#include <QCloseEvent>
+#include <QTextCodec>
+#include <QTranslator>
+#include <QMimeData>
+#include <QUrl>
+//-----------------------------------------------------------------------------
+#include <mgl2/qmathgl.h>
+#include "udav_wnd.h"
+#include "text_pnl.h"
+#include "plot_pnl.h"
+#include "prop_dlg.h"
+#include "qmglsyntax.h"
+//-----------------------------------------------------------------------------
+extern bool mglAutoExecute;
+PropDialog *propDlg=0;
+int MainWindow::num_wnd=0;
+QStringList recentFiles;
+int MaxRecentFiles=5;
+bool editPosBottom = false;
+bool mglAutoSave = false;
+bool mglHighlight = true;
+bool mglDotsRefr = true;
+// bool mglAutoPure = true;
+bool mglCompleter = true;
+bool loadInNewWnd = false;
+bool mglWheelZoom = false;
+QString pathHelp;
+extern mglParse parser;
+extern QColor mglColorScheme[10];
+extern QString defFontFamily;
+extern int defFontSize;
+extern QString pathFont;
+extern int defWidth, defHeight;
+//-----------------------------------------------------------------------------
+QWidget *createCalcDlg(QWidget *p, QTextEdit *e);
+QDialog *createArgsDlg(QWidget *p);
+QWidget *createMemPanel(QWidget *p);
+QWidget *createHlpPanel(QWidget *p);
+void showHelpMGL(QWidget *hlp, QString s);
+void addDataPanel(QWidget *p, QWidget *w, QString name)
+{
+	MainWindow *wnd = dynamic_cast<MainWindow *>(p);
+	if(wnd)	wnd->addPanel(w, name);
+}
+//-----------------------------------------------------------------------------
+#ifndef UDAV_DIR
+#ifdef WIN32
+#define UDAV_DIR ""
+#else
+#define UDAV_DIR "/usr/local/share/udav/"
+#endif
+#endif
+//-----------------------------------------------------------------------------
+int mgl_cmd_cmp(const void *a, const void *b);
+void udavLoadDefCommands();
+void udavShowHint(QWidget *);
+void mgl_ask_qt(const wchar_t *quest, wchar_t *res);
+//-----------------------------------------------------------------------------
+int main(int argc, char **argv)
+{
+	QString lang="";
+	QSettings settings("udav","UDAV");
+	settings.setPath(QSettings::IniFormat, QSettings::UserScope, "UDAV");
+	settings.beginGroup("/UDAV");
+	pathHelp = settings.value("/helpPath", MGL_DOC_DIR).toString();
+	pathFont = settings.value("/userFont", "").toString();
+	lang = settings.value("/udavLang", "").toString();
+	
+	const char *loc="";
+	if(lang=="en")	loc = "C.UTF8";
+#if WIN32
+	if(lang=="ru")	loc = "ru_RU.cp1251";
+#else
+	if(lang=="ru")	loc = "ru_RU.utf8";
+#endif
+	if(lang=="es")	{	loc = "es_ES.utf8";	lang="en";	}	// TODO remove lang="en"; then Spanish translation is ready !
+	mgl_textdomain(argv?argv[0]:NULL,loc);
+	
+	bool showHint = settings.value("/showHint", true).toBool();
+	mglCompleter = settings.value("/completer",  true).toBool();
+	settings.endGroup();
+
+	mgl_suppress_warn(true);
+	QCoreApplication::setAttribute(Qt::AA_X11InitThreads);
+#ifdef WIN32
+	char buf[512];	getcwd(buf,500);	strcat(buf,"\\plugins\\");
+	QCoreApplication::addLibraryPath(buf);
+	QCoreApplication::addLibraryPath("c:\\plugins\\");
+#endif
+	mgl_ask_func = mgl_ask_qt;
+	QApplication a(argc, argv);
+	QTranslator translator;
+//QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
+#if defined(WIN32)
+	if(pathHelp.isEmpty())	pathHelp = a.applicationDirPath()+"\\";
+#else
+	if(pathHelp.isEmpty())	pathHelp=MGL_DOC_DIR;
+#endif
+
+	if(!lang.isEmpty())
+	{
+		if(!translator.load("udav_"+lang, UDAV_DIR))
+			translator.load("udav_"+lang, pathHelp);
+		a.installTranslator(&translator);
+	}
+
+	udavLoadDefCommands();
+	parser.AllowSetSize(true);
+	MainWindow *mw = new MainWindow();
+	if(argc>1)
+	{
+		QTextCodec *codec = QTextCodec::codecForLocale();
+		mw->load(codec->toUnicode(argv[1]), true);
+	}
+	mw->show();
+	mw->edit->edit->setFocus();
+	a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
+	if(showHint)	udavShowHint(mw);
+	return a.exec();
+}
+//-----------------------------------------------------------------------------
+//
+//		mgl addon
+//
+//-----------------------------------------------------------------------------
+void udavLoadDefCommands()	{}	//{	udavAddCommands(udav_base_cmd);	}
+//-----------------------------------------------------------------------------
+//
+//	Class MainWindow
+//
+//-----------------------------------------------------------------------------
+MainWindow::MainWindow(QWidget *wp) : QMainWindow(wp)
+{
+	QAction *a;
+	setWindowTitle(_("untitled - UDAV"));
+	setAttribute(Qt::WA_DeleteOnClose);
+
+	split = new QSplitter(this);
+	ltab = new QTabWidget(split);
+	ltab->setMovable(true);	ltab->setTabPosition(QTabWidget::South);
+//	ltab->setTabsClosable(true);
+	rtab = new QTabWidget(split);
+	rtab->setMovable(true);	rtab->setTabPosition(QTabWidget::South);
+
+	messWnd = new QDockWidget(_("Messages and warnings"),this);
+	mess = new QTextEdit(this);	messWnd->setWidget(mess);
+	messWnd->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
+	addDockWidget(Qt::BottomDockWidgetArea, messWnd);
+	messWnd->resize(size().width(), 0);	new MessSyntax(mess);
+//	connect(mess,SIGNAL(cursorPositionChanged()),this,SLOT(messClicked()));
+	connect(mess,SIGNAL(selectionChanged()),this,SLOT(messClicked()));
+
+	hideWnd = new QDockWidget(_("Hidden plots"),this);
+	hidden = new TextEdit(this);	hideWnd->setWidget(hidden);
+	hideWnd->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
+	addDockWidget(Qt::BottomDockWidgetArea, hideWnd);
+	hideWnd->resize(size().width(), 0);	hidden->setReadOnly(true);
+	connect(hidden,SIGNAL(selectionChanged()),this,SLOT(hiddenClicked()));	// TODO
+//	connect(hidden,SIGNAL(cursorPositionChanged()),this,SLOT(hiddenClicked()));
+
+	calcWnd = new QDockWidget(_("Calculator"),this);
+
+	aload = a = new QAction(QPixmap(":/png/document-open.png"), _("Open file"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(choose()));
+	a->setToolTip(_("Open and execute/show script or data from file (Ctrl+O).\nYou may switch off automatic exection in UDAV properties."));
+	a->setShortcut(Qt::CTRL+Qt::Key_O);
+
+	asave = a = new QAction(QPixmap(":/png/document-save.png"), _("Save script"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(save()));
+	a->setToolTip(_("Save script to a file (Ctrl+S)"));
+	a->setShortcut(Qt::CTRL+Qt::Key_S);
+
+	acalc = a = new QAction(QPixmap(":/png/accessories-calculator.png"), _("Calculator"), this);
+	a->setShortcut(Qt::Key_F4);	a->setCheckable(true);
+	connect(a, SIGNAL(toggled(bool)), calcWnd, SLOT(setVisible(bool)));
+	connect(calcWnd, SIGNAL(visibilityChanged(bool)), a, SLOT(setChecked(bool)));
+	a->setToolTip(_("Show calculator which evaluate and help to type textual formulas.\nTextual formulas may contain data variables too."));
+	a->setChecked(false);	calcWnd->setVisible(false);
+
+	ainfo = a = new QAction(_("Show info"), this);
+	a->setShortcut(Qt::Key_F2);	a->setCheckable(true);
+	connect(a, SIGNAL(toggled(bool)), messWnd, SLOT(setVisible(bool)));
+	connect(messWnd, SIGNAL(visibilityChanged(bool)), a, SLOT(setChecked(bool)));
+	a->setChecked(false);	messWnd->setVisible(false);
+
+	ahide = a = new QAction(QPixmap(":/png/layer-visible-on.png"), _("Show hidden plots"), this);
+	a->setShortcut(Qt::Key_F8);	a->setCheckable(true);
+	connect(a, SIGNAL(toggled(bool)), hideWnd, SLOT(setVisible(bool)));
+	connect(hideWnd, SIGNAL(visibilityChanged(bool)), a, SLOT(setChecked(bool)));
+	a->setChecked(false);	hideWnd->setVisible(false);
+
+	graph = new PlotPanel(this);
+	rtab->addTab(graph,QPixmap(":/png/office-chart-line.png"),_("Canvas"));
+	//	connect(info,SIGNAL(addPanel(QWidget*)),this,SLOT(addPanel(QWidget*)));
+	info = createMemPanel(this);
+	rtab->addTab(info,QPixmap(":/png/system-file-manager.png"),_("Info"));
+	hlp = createHlpPanel(this);
+	rtab->addTab(hlp,QPixmap(":/png/help-contents.png"),_("Help"));
+	edit = new TextPanel(this);	edit->graph = graph;
+	graph->textMGL = edit->edit;
+	connect(graph->mgl,SIGNAL(showWarn(QString)),mess,SLOT(setText(QString)));
+	connect(graph->mgl,SIGNAL(showWarn(QString)),edit->edit,SLOT(setErrMessage(QString)));
+	connect(graph,SIGNAL(clearWarn()),mess,SLOT(clear()));
+	ltab->addTab(edit,QPixmap(":/png/text-plain.png"),_("Script"));
+
+	calcWnd->setWidget(createCalcDlg(this, edit->edit));
+	calcWnd->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
+	addDockWidget(Qt::BottomDockWidgetArea, calcWnd);
+	calcWnd->resize(size().width(), 200);
+
+	makeMenu();
+	setCentralWidget(split);
+	setWindowIcon(QIcon(":/udav.png"));
+	readSettings();
+	if(!propDlg)	propDlg = new PropDialog;
+
+	connect(graph, SIGNAL(save()), this, SLOT(save()));
+	connect(graph, SIGNAL(setStatus(const QString &)), this, SLOT(setStatus(const QString &)));
+	connect(graph, SIGNAL(animPutText(const QString &)), edit, SLOT(animPutText(const QString &)));
+	connect(graph,SIGNAL(giveFocus()),edit->edit,SLOT(setFocus()));
+	connect(graph->mgl, SIGNAL(objChanged(int)), edit, SLOT(setCursorPosition(int)));
+//	connect(graph->mgl, SIGNAL(posChanged(QString)), statusBar(), SLOT(showMessage(QString)));
+	connect(graph->mgl, SIGNAL(refreshData()), this, SLOT(refresh()));
+	connect(graph->mgl, SIGNAL(refreshData()), edit, SLOT(refreshData()));
+	connect(graph->mgl,SIGNAL(doubleClick(int)),edit,SLOT(newCmd(int)));
+
+	connect(edit->edit,SIGNAL(textChanged()),this,SLOT(updateHidden()));
+	connect(mess, SIGNAL(textChanged()), this, SLOT(warnChanged()));
+	connect(propDlg, SIGNAL(sizeChanged(int,int)), graph->mgl, SLOT(imgSize(int,int)));
+	connect(edit->edit,SIGNAL(textChanged()), this, SLOT(setAsterix()));
+	connect(edit->edit, SIGNAL(cursorPositionChanged()), this, SLOT(editPosChanged()));
+	connect(edit,SIGNAL(setCurrentFile(QString)),this,SLOT(setCurrentFile(QString)));
+	connect(edit,SIGNAL(setStatus(QString)),this,SLOT(setStatus(QString)));
+
+	setStatus(_("Ready"));
+	num_wnd++;
+	edit->setAcceptDrops(false);	// for disabling default action by 'edit'
+	setAcceptDrops(true);
+}
+//-----------------------------------------------------------------------------
+void MainWindow::makeMenu()
+{
+	QAction *a;
+	QMenu *o;
+
+	// file menu
+	{
+	o = menuBar()->addMenu(_("File"));
+	a = new QAction(QPixmap(":/png/document-new.png"), _("New script"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(newDoc()));
+	a->setToolTip(_("Create new empty script window (Ctrl+N)."));
+	a->setShortcut(Qt::CTRL+Qt::Key_N);	o->addAction(a);
+
+	o->addAction(aload);
+	o->addAction(asave);
+
+	a = new QAction(_("Save as ..."), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(saveAs()));
+	o->addAction(a);
+
+	o->addSeparator();
+	o->addAction(_("Print script"), edit, SLOT(printText()));
+	a = new QAction(QPixmap(":/png/document-print.png"), _("Print graphics"), this);
+	connect(a, SIGNAL(triggered()), graph->mgl, SLOT(print()));
+	a->setToolTip(_("Open printer dialog and print graphics (Ctrl+P)"));
+	a->setShortcut(Qt::CTRL+Qt::Key_P);	o->addAction(a);
+	o->addSeparator();
+	fileMenu = o->addMenu(_("Recent files"));
+	o->addSeparator();
+	o->addAction(_("Quit"), qApp, SLOT(closeAllWindows()));
+	}
+
+	menuBar()->addMenu(edit->menu);
+	menuBar()->addMenu(graph->menu);
+
+	// settings menu
+	{
+	o = menuBar()->addMenu(_("Settings"));
+	a = new QAction(QPixmap(":/png/preferences-system.png"), _("Properties"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(properties()));
+	a->setToolTip(_("Show dialog for UDAV properties."));	o->addAction(a);
+	o->addAction(_("Set arguments"), createArgsDlg(this), SLOT(exec()));
+
+	o->addAction(acalc);
+	o->addAction(ainfo);
+	o->addAction(ahide);
+	}
+
+	menuBar()->addSeparator();
+	o = menuBar()->addMenu(_("Help"));
+	a = new QAction(QPixmap(":/png/help-contents.png"), _("MGL help"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(showHelp()));
+	a->setToolTip(_("Show help on MGL commands (F1)."));
+	a->setShortcut(Qt::Key_F1);	o->addAction(a);
+	a = new QAction(QPixmap(":/png/help-faq.png"), _("Hints"), this);
+	connect(a, SIGNAL(triggered()), this, SLOT(showHint()));
+	a->setToolTip(_("Show hints of MGL usage."));	o->addAction(a);
+	o->addAction(_("About"), this, SLOT(about()));
+	o->addAction(_("About Qt"), this, SLOT(aboutQt()));
+}
+//-----------------------------------------------------------------------------
+void MainWindow::closeEvent(QCloseEvent* ce)
+{
+	bool ok=true;
+	writeSettings();
+	if(edit->isModified())
+		switch(QMessageBox::information(this, _("UDAV"),
+				_("Do you want to save the changes to the document?"),
+				QMessageBox::Yes, QMessageBox::No, QMessageBox::Cancel))
+		{
+			case QMessageBox::Yes:	save();	break;
+			case QMessageBox::No:	break;
+			default:	ok=false;	break;
+		}
+	if(ok)
+	{
+		num_wnd--;
+		ce->accept();
+		if(num_wnd==0)	QApplication::quit();
+	}
+	else	ce->ignore();
+}
+//-----------------------------------------------------------------------------
+void MainWindow::dropEvent(QDropEvent * de)
+{
+	// Linux Qt send "text/plain" mime data in drop event
+	// Windows version send "text/uri-list"
+	QTextCodec *codec = QTextCodec::codecForLocale();
+	QString filename;
+	if ( de->mimeData()->hasFormat("text/plain") )
+	{
+		// Under linux just convert the text from the local encodig to Qt's unicode
+		filename = codec->toUnicode(de->mimeData()->data("text/plain"));
+		if (filename.indexOf("file:") == 0)
+			load(filename.remove("file://").trimmed(), false);
+	}else
+	if ( de->mimeData()->hasUrls() )
+	{
+		// Under win - parse the dropped data and find the path to local file
+		QList<QUrl> UrlList;
+		QFileInfo finfo;
+		UrlList = de->mimeData()->urls();
+		if ( UrlList.size() > 0) // if at least one QUrl is present in list
+		{
+			filename = UrlList[0].toLocalFile(); // convert first QUrl to local path
+			finfo.setFile( filename );
+			if ( finfo.isFile() )
+			{
+				load(filename, false);
+			}
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void MainWindow::dragEnterEvent(QDragEnterEvent *event)
+{
+	QTextCodec *codec = QTextCodec::codecForLocale();
+	QString filename = codec->toUnicode(event->mimeData()->data("text/plain"));
+	/*if ( event->provides("text/plain") )
+	{
+		QTextCodec *codec = QTextCodec::codecForLocale();
+		QString instring = codec->toUnicode(event->mimeData()->data("text/plain"));
+		if ( instring.indexOf("file://") >= 0)
+		{
+			event->acceptProposedAction();
+			setStatus(instring);
+		}
+	}
+	else */
+	if(event->mimeData()->hasUrls())
+	{
+		QList<QUrl> UrlList;
+		QFileInfo finfo;
+		UrlList = event->mimeData()->urls();
+		if ( UrlList.size() > 0) // if at least one QUrl is present in list
+		{
+			filename = UrlList[0].toLocalFile(); // convert first QUrl to local path
+			finfo.setFile(filename);
+			if ( finfo.isFile() )
+			{
+				event->acceptProposedAction();
+				setStatus(filename);
+			}
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+void MainWindow::showHelp()
+{
+	QString s = edit->selection(), dlm(" #;:\t");
+	int i, n = s.length();
+	for(i=0;i<n;i++)	if(dlm.contains(s[i]))	break;
+	s.truncate(i);
+//	s = s.section(' ',0);
+	showHelpMGL(hlp,s);
+}
+//-----------------------------------------------------------------------------
+int mgl_cmd_cmp(const void *a, const void *b);
+void MainWindow::editPosChanged()
+{
+	QString text = edit->selection(), dlm(" #;:\t");
+	int n = text.length(), i;
+	for(i=0;i<n;i++)	if(dlm.contains(text[i]))	break;
+	text.truncate(i);
+
+	QByteArray qxtext = text.toLatin1();
+	const char *ctext = qxtext.constData();
+	const char *desc = parser.CmdDesc(ctext);
+	const char *form = parser.CmdFormat(ctext);
+	if(form)	setStatus(QString(desc)+": "+QString(form));
+	else	setStatus(_("Not recognized"));
+}
+//-----------------------------------------------------------------------------
+void MainWindow::setEditPos(bool bottom)
+{	split->setOrientation(bottom ? Qt::Vertical : Qt::Horizontal);	}
+//-----------------------------------------------------------------------------
+void MainWindow::properties()	{	propDlg->exec();	}
+//-----------------------------------------------------------------------------
+void MainWindow::about()
+{
+	QString s = "<a href='http://mathgl.sourceforge.net/doc_en/UDAV-overview.html'>UDAV</a> v. 2."+QString::number(MGL_VER2)+
+	_("<br>(c) Alexey Balakin, 2007-present<br><br><a href='http://www.gnu.org/copyleft/gpl.html'>License is GPL v.2 or later.</a>");
+	QMessageBox::about(this, _("UDAV - about"), s);
+}
+//-----------------------------------------------------------------------------
+void MainWindow::aboutQt()
+{	QMessageBox::aboutQt(this, _("About Qt"));	}
+//-----------------------------------------------------------------------------
+void MainWindow::writeSettings()
+{
+	QSettings settings("udav","UDAV");
+	settings.setPath(QSettings::IniFormat, QSettings::UserScope, "UDAV");
+	settings.beginGroup("/UDAV");
+	settings.setValue("/animDelay", animDelay);
+	settings.setValue("/geometry/size", size());
+//	settings.setValue("/geometry/dock", messWnd->size());
+	settings.setValue("/geometry/split_e/w1", split->sizes().at(0));
+	settings.setValue("/geometry/split_e/w2", split->sizes().at(1));
+
+	settings.setValue("/recentFiles", recentFiles);
+	settings.setValue("/recentFilesMax", MaxRecentFiles);
+	settings.setValue("/helpPath", pathHelp);
+	settings.setValue("/userFont", pathFont);
+	settings.setValue("/colComment",mglColorScheme[0].name());
+	settings.setValue("/colString", mglColorScheme[1].name());
+	settings.setValue("/colKeyword",mglColorScheme[2].name());
+	settings.setValue("/colOption", mglColorScheme[3].name());
+	settings.setValue("/colSuffix", mglColorScheme[4].name());
+	settings.setValue("/colNumber", mglColorScheme[5].name());
+	settings.setValue("/colACKeyword", mglColorScheme[6].name());
+	settings.setValue("/colFCKeyword", mglColorScheme[7].name());
+	settings.setValue("/colReserved", mglColorScheme[8].name());
+	settings.setValue("/colCurrLine", mglColorScheme[9].name());
+	settings.setValue("/autoExec",  mglAutoExecute);
+	settings.setValue("/autoSave",  mglAutoSave);
+	settings.setValue("/highlight",  mglHighlight);
+	settings.setValue("/dotsRefresh", mglDotsRefr);
+// 	settings.setValue("/autoPure",  mglAutoPure);
+	settings.setValue("/editAtTop", editPosBottom);
+	settings.setValue("/fontFamily", defFontFamily);
+	settings.setValue("/fontSize", defFontSize);
+	settings.setValue("/loadInNewWnd", loadInNewWnd);
+	settings.setValue("/completer",  mglCompleter);
+	settings.setValue("/wheelZoom",  mglWheelZoom);
+	settings.endGroup();
+}
+//-----------------------------------------------------------------------------
+void MainWindow::readSettings()
+{
+	QSettings settings("udav","UDAV");
+	settings.setPath(QSettings::IniFormat, QSettings::UserScope, "UDAV");
+	settings.beginGroup("/UDAV");
+	pathHelp = settings.value("/helpPath", MGL_DOC_DIR).toString();
+	if(pathHelp.isEmpty())	pathHelp=MGL_DOC_DIR;
+	MaxRecentFiles = settings.value("/recentFilesMax", 5).toInt();
+	animDelay = settings.value("/animDelay", 500).toInt();
+	resize(settings.value("/geometry/size", QSize(880,720)).toSize());
+	QList<int> le;
+	le.append(settings.value("/geometry/split_e/w1", 230).toInt());
+	le.append(settings.value("/geometry/split_e/w2", 604).toInt());
+	split->setSizes(le);
+
+	pathFont = settings.value("/userFont", "").toString();
+	mglColorScheme[0] = QColor(settings.value("/colComment","#007F00").toString());
+	mglColorScheme[1] = QColor(settings.value("/colString", "#FF0000").toString());
+	mglColorScheme[2] = QColor(settings.value("/colKeyword","#00007F").toString());
+	mglColorScheme[3] = QColor(settings.value("/colOption", "#7F0000").toString());
+	mglColorScheme[4] = QColor(settings.value("/colSuffix", "#7F0000").toString());
+	mglColorScheme[5] = QColor(settings.value("/colNumber", "#0000FF").toString());
+	mglColorScheme[6] = QColor(settings.value("/colACKeyword","#7F007F").toString());
+	mglColorScheme[7] = QColor(settings.value("/colFCKeyword","#007F7F").toString());
+	mglColorScheme[8] = QColor(settings.value("/colReserved", "#0000FF").toString());
+	mglColorScheme[9] = QColor(settings.value("/colCurrLine", "#FFFFCC").toString());
+	mglAutoSave = settings.value("/autoSave", false).toBool();
+	mglHighlight = settings.value("/highlight", true).toBool();
+// 	mglAutoPure = settings.value("/autoPure", true).toBool();
+	mglAutoExecute = settings.value("/autoExec", true).toBool();
+	editPosBottom = settings.value("/editAtTop", false).toBool();
+	mglCompleter = settings.value("/completer", true).toBool();
+	mglWheelZoom = settings.value("/wheelZoom", false).toBool();
+	loadInNewWnd = settings.value("/loadInNewWnd", false).toBool();
+	mglDotsRefr = settings.value("/dotsRefresh", true).toBool();
+	defFontFamily = settings.value("/fontFamily", "Georgia").toString();
+	defFontSize = settings.value("/fontSize", 10).toInt();
+	edit->setEditorFont();	setEditPos(editPosBottom);
+	graph->setMGLFont(pathFont);
+	graph->mgl->enableWheel = mglWheelZoom;
+
+	defWidth = settings.value("/defWidth", 640).toInt();
+	defHeight = settings.value("/defHeight", 480).toInt();
+	graph->mgl->setSize(defWidth, defHeight);
+
+	recentFiles = settings.value("/recentFiles").toStringList();
+	settings.endGroup();
+	updateRecentFileItems();
+}
+//-----------------------------------------------------------------------------
+void MainWindow::setStatus(const QString &txt)
+{	statusBar()->showMessage(txt, 5000);	}
+//-----------------------------------------------------------------------------
+void MainWindow::setCurrentFile(const QString &fileName)
+{
+	filename = fileName;
+	mgl_set_plotid(graph->mgl->getGraph(), fileName.toLocal8Bit().constData());
+	edit->setModified(false);
+	if(filename.isEmpty())
+		setWindowTitle(_("untitled - UDAV"));
+	else
+	{
+		setWindowTitle(QFileInfo(filename).fileName()+" - UDAV");
+		int i = recentFiles.indexOf(filename);
+		if(i>=0)	recentFiles.removeAt(i);
+		recentFiles.push_front(filename);
+		updateRecentFileItems();
+		if(chdir(qPrintable(QFileInfo(filename).path())))
+			QMessageBox::warning(this, _("UDAV - save current"),
+				_("Couldn't change to folder ")+QFileInfo(filename).path());
+	}
+}
+//-----------------------------------------------------------------------------
+void MainWindow::openRecentFile()
+{
+	QAction *a = qobject_cast<QAction *>(sender());
+	if(!a)	return;
+	if(edit->isModified())
+		switch(QMessageBox::information(this, _("UDAV - save current"),
+				_("Do you want to save the changes to the document?"),
+				QMessageBox::Yes, QMessageBox::No, QMessageBox::Cancel))
+		{
+			case QMessageBox::Yes:	save();	break;
+			case QMessageBox::No:	break;
+			default:	return;
+		}
+	QString fn = recentFiles[a->data().toInt()];
+	if(!fn.isEmpty())	load(fn);
+}
+//-----------------------------------------------------------------------------
+void MainWindow::updateRecentFileItems()
+{
+	foreach(QWidget *w, QApplication::topLevelWidgets())
+	{
+		MainWindow *wnd = qobject_cast<MainWindow *>(w);
+		if(wnd)	wnd->updateRecent();
+	}
+}
+//-----------------------------------------------------------------------------
+void MainWindow::updateRecent()
+{
+	QAction *a;
+	fileMenu->clear();	qApp->processEvents();
+	for(int i=0; i<recentFiles.size() && i<MaxRecentFiles; i++)
+	{
+		QString text="&"+QString::number(i+1)+" "+QFileInfo(recentFiles[i]).fileName();
+		a = fileMenu->addAction(text, this, SLOT(openRecentFile()));
+		a->setData(i);
+	}
+}
+//-----------------------------------------------------------------------------
+void MainWindow::newDoc()
+{
+	MainWindow *ed = new MainWindow;
+	ed->show();	ed->activateWindow();
+}
+//-----------------------------------------------------------------------------
+void MainWindow::choose()
+{
+	if(edit->isModified())
+		switch(QMessageBox::information(this, _("UDAV - save current"),
+				_("Do you want to save the changes to the document?"),
+				QMessageBox::Yes, QMessageBox::No, QMessageBox::Cancel))
+		{
+			case QMessageBox::Yes:	save();	break;
+			case QMessageBox::No:	break;
+			default:	return;
+		}
+	QSettings settings("udav","UDAV");
+	settings.setPath(QSettings::IniFormat, QSettings::UserScope, "UDAV");
+	settings.beginGroup("/UDAV");
+	QString fn = QFileDialog::getOpenFileName(this,
+			_("UDAV - Open file"),
+			settings.value("/filePath", MGL_DOC_DIR).toString(),
+			_("MGL scripts (*.mgl)\nHDF5 files (*.hdf *.h5)\nText files (*.txt)\nData files (*.dat)\nAll files (*.*)"));
+	settings.endGroup();
+	if(!fn.isEmpty())	load(fn);
+	else	setStatus(_("Loading aborted"));
+}
+//-----------------------------------------------------------------------------
+void MainWindow::load(const QString &fileName, bool noNewWnd)
+{
+	// save current path
+	QFileInfo fi(fileName);		filename = fileName;
+	QSettings settings("udav","UDAV");
+	settings.setPath(QSettings::IniFormat, QSettings::UserScope, "UDAV");
+	settings.beginGroup("/UDAV");
+	settings.setValue("/filePath", fi.absolutePath());
+	settings.endGroup();
+	// open new window if it is required
+	if(loadInNewWnd && !noNewWnd)
+	{
+		MainWindow *mw = new MainWindow;
+		mw->edit->load(fileName);
+		mw->show();	//ed->activateWindow();
+	}
+	else	edit->load(fileName);
+}
+//-----------------------------------------------------------------------------
+void MainWindow::save()
+{
+	if(filename.isEmpty())	saveAs();
+	else	edit->save(filename);
+}
+//-----------------------------------------------------------------------------
+void MainWindow::saveAs()
+{
+	QString fn;
+	fn = QFileDialog::getSaveFileName(this, _("UDAV - save file"), "",
+			_("MGL scripts (*.mgl)\nHDF5 files (*.hdf *.h5)\nAll files (*.*)"));
+	if(fn.isEmpty())
+	{	setStatus(_("Saving aborted"));	return;	}
+	else
+	{
+		int nn=fn.length();
+		if(fn[nn-4]!='.' && fn[nn-3]!='.')	fn = fn + ".mgl";
+		filename = fn;		save();
+	}
+}
+//-----------------------------------------------------------------------------
+void MainWindow::setAsterix()
+{
+	if(edit->isModified())
+	{
+		if(filename.isEmpty())
+			setWindowTitle(_("untitled* - UDAV"));
+		else
+			setWindowTitle(QFileInfo(filename).fileName()+"* - UDAV");
+	}
+	else
+	{
+		if(filename.isEmpty())
+			setWindowTitle(_("untitled - UDAV"));
+		else
+			setWindowTitle(QFileInfo(filename).fileName()+" - UDAV");
+	}
+}
+//-----------------------------------------------------------------------------
+void updateDataItems()
+{
+	foreach (QWidget *w, QApplication::topLevelWidgets())
+		if(w->inherits("MainWindow"))	((MainWindow *)w)->refresh();
+}
+//-----------------------------------------------------------------------------
+void MainWindow::addPanel(QWidget *w, QString name)
+{
+	ltab->addTab(w,QPixmap(":/png/text-csv.png"),name);
+	ltab->setCurrentWidget(w);
+}
+//-----------------------------------------------------------------------------
+MGL_LOCAL_PURE MainWindow *findMain(QWidget *wnd)
+{
+	MainWindow *mw=0;
+	QObject *w=wnd;
+
+	while(w && !mw)
+	{
+		mw = dynamic_cast<MainWindow *>(w);
+		w = w->parent();
+	}
+	return mw;
+}
+//-----------------------------------------------------------------------------
+void raisePanel(QWidget *w)
+{
+	MainWindow *mw=findMain(w);
+	if(mw)	mw->rtab->setCurrentWidget(w);
+}
+//-----------------------------------------------------------------------------
+void MainWindow::updateHidden()
+{
+	QTextCursor tc = edit->edit->textCursor();
+	long pos = tc.position(), i=0;
+	hidden->clear();
+	tc.movePosition(QTextCursor::Start);
+	do {
+		i++;
+		if(tc.block().text().startsWith("#h "))
+			hidden->append("Line "+QString::number(i)+QString::fromWCharArray(L" \u2192 ")+tc.block().text().mid(3)+"\n");
+	} while(tc.movePosition(QTextCursor::NextBlock));
+	tc.setPosition(pos);
+}
+//-----------------------------------------------------------------------------
+void MainWindow::hiddenClicked()
+{
+	QString q = hidden->textCursor().block().text();
+	if(q.contains("Line "))
+	{
+		int n = q.section(' ',1,1).toInt()-1;
+		edit->edit->moveCursor(QTextCursor::Start);
+		for(int i=0;i<n;i++)	edit->edit->moveCursor(QTextCursor::NextBlock);
+		edit->edit->textCursor().deleteChar();
+		edit->edit->textCursor().deleteChar();
+		edit->edit->textCursor().deleteChar();
+	}
+	graph->execute();
+}
+//-----------------------------------------------------------------------------
+void MainWindow::messClicked()
+{
+	QString q = mess->textCursor().block().text();
+	if(q.contains("in line "))
+	{
+		QString s = q.section(' ',-1);
+		int n = q.section(' ',-1).toInt()-1;	if(n<0)	return;
+		edit->moveCursor(QTextCursor::Start);
+		for(int i=0;i<n;i++)	edit->moveCursor(QTextCursor::NextBlock);
+	}
+	edit->setFocus();
+}
+//-----------------------------------------------------------------------------
+void MainWindow::warnChanged()
+{
+	if(mess->toPlainText().isEmpty())
+	{	messWnd->hide();	ainfo->setChecked(false);	}
+	else
+	{	messWnd->show();	ainfo->setChecked(true);	}
+}
+//-----------------------------------------------------------------------------
diff --git a/udav/udav_wnd.h b/udav/udav_wnd.h
new file mode 100644
index 0000000..d101f13
--- /dev/null
+++ b/udav/udav_wnd.h
@@ -0,0 +1,121 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Alexey Balakin                                  *
+ *   mathgl.abalakin at gmail.com                                             *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#ifndef UDAV_WND_H
+#define UDAV_WND_H
+//-----------------------------------------------------------------------------
+#include <QMainWindow>
+//-----------------------------------------------------------------------------
+#ifndef MGL_DOC_DIR
+#ifdef WIN32
+#define MGL_DOC_DIR ""
+#else
+#define MGL_DOC_DIR "/usr/local/share/doc/mathgl/"
+#endif
+#endif
+//-----------------------------------------------------------------------------
+class QSplitter;
+class QTabWidget;
+class QMenu;
+class QDockWidget;
+class QTextEdit;
+class TextPanel;
+class PlotPanel;
+//-----------------------------------------------------------------------------
+extern int MaxRecentFiles;
+extern int animDelay;
+void udavShowHint(QWidget *);
+void refreshMemPanel(QWidget *p);
+void showExMGL(QWidget *hlp);
+//-----------------------------------------------------------------------------
+class MainWindow : public QMainWindow
+{
+friend void raisePanel(QWidget *w);
+Q_OBJECT
+public:
+	QAction *ainfo, *acalc, *asave, *aload, *ahide;
+	TextPanel *edit;
+	PlotPanel *graph;
+	QWidget *info;
+	QWidget *hlp;
+	MainWindow(QWidget *wp=0);
+	void load(const QString &fileName, bool noNewWnd=false);
+	void writeSettings();
+
+public slots:
+	void setEditPos(bool bottom);
+	void editPosChanged();
+	void refresh()	{	refreshMemPanel(info);	}
+	void addPanel(QWidget *w, QString name);
+
+signals:
+	void gotoLine(int n,int i);
+
+protected:
+	void closeEvent ( QCloseEvent* );
+	void dropEvent ( QDropEvent* );
+	void dragEnterEvent( QDragEnterEvent* );
+
+private slots:
+	void newDoc();
+	void choose();
+	void save();
+	void saveAs();
+
+	void about();
+	void aboutQt();
+	void openRecentFile();
+	void showHelp();
+	void updateHidden();
+	void hiddenClicked();
+
+	void messClicked();
+	void properties();
+	void setAsterix();
+	void warnChanged();
+	void showHint()	{	udavShowHint(this);	}
+//	void showExamples()	{	showExMGL(hlp);	}
+
+	void setCurrentFile(const QString &);
+	void setStatus(const QString &txt);
+//	void animParse(const QString &txt);
+
+private:
+	static int num_wnd;
+	QTabWidget *ltab, *rtab;
+	QSplitter *split;
+	QTextEdit *mess;	///< messages and warnings
+	QTextEdit *hidden;	///< commented(hidden) lines
+	QString filename;
+	QMenu *fileMenu;
+	QDockWidget *messWnd, *hideWnd, *calcWnd;
+
+	void makeMenu();
+	void makeDataMenu();
+	void readSettings();
+	QWidget *setupInfo(QWidget *par);
+	void updateRecentFileItems();
+	void updateRecent();
+};
+//-----------------------------------------------------------------------------
+MainWindow *findMain(QWidget *w);
+void raisePanel(QWidget *w);
+//-----------------------------------------------------------------------------
+#endif
+//-----------------------------------------------------------------------------
diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt
new file mode 100644
index 0000000..72015b9
--- /dev/null
+++ b/utils/CMakeLists.txt
@@ -0,0 +1,54 @@
+add_executable(make_pas make_pas.cpp)
+
+add_executable(mglconv mglconv.cpp)
+if(MSVC)
+set(link_type -static)
+else(MSVC)
+set(link_type)
+endif(MSVC)
+target_link_libraries(mglconv mgl${link_type} ${getopt_lib-static})
+install(
+	TARGETS mglconv
+	EXPORT MathGLTargets
+	RUNTIME DESTINATION ${MathGL_INSTALL_BIN_DIR}
+)
+
+add_executable(mgl.cgi mglcgi.cpp)
+target_link_libraries(mgl.cgi mgl${link_type})
+install(
+	TARGETS mgl.cgi
+	EXPORT MathGLTargets
+# should be /usr/lib/cgi-bin/
+	RUNTIME DESTINATION ${MGL_CGI_PATH}
+)
+
+mgl_po_src(mglconv.cpp mglview.cpp mglcgi.cpp)
+
+if(MGL_HAVE_FLTK)
+	add_definitions(-DUSE_FLTK)
+	add_executable(mglview mglview.cpp)
+	target_link_libraries(mglview mgl-fltk ${getopt_lib-static} ${FLTK_LIBRARIES})
+	install(
+		TARGETS mglview
+		EXPORT MathGLTargets
+		RUNTIME DESTINATION ${MathGL_INSTALL_BIN_DIR}
+	)
+
+else(MGL_HAVE_FLTK)
+	if(QT_ENABLED)
+		add_executable(mglview mglview.cpp)
+		if(enable-qt5)
+			include(../cmake-qt5.txt)
+			target_link_libraries(mglview mgl-qt5${link_type} ${getopt_lib-static} ${MGL_QT5_LIBS})
+		else(enable-qt5)
+			include(../cmake-qt4.txt)
+			target_link_libraries(mglview mgl-qt4${link_type} ${getopt_lib-static} ${MGL_QT4_LIBS})
+		endif(enable-qt5)
+
+		install(
+			TARGETS mglview
+			EXPORT MathGLTargets
+			RUNTIME DESTINATION ${MathGL_INSTALL_BIN_DIR}
+		)
+	endif(QT_ENABLED)
+endif(MGL_HAVE_FLTK)
diff --git a/utils/make_forth.cpp b/utils/make_forth.cpp
new file mode 100644
index 0000000..cbe888e
--- /dev/null
+++ b/utils/make_forth.cpp
@@ -0,0 +1,168 @@
+#include <stdio.h>
+#include <string.h>
+
+const char *files[]={"../include/mgl2/base_cf.h","../include/mgl2/data_cf.h", "../include/mgl2/datac_cf.h", "../include/mgl2/cont.h", "../include/mgl2/fit.h", "../include/mgl2/plot.h", "../include/mgl2/surf.h", "../include/mgl2/volume.h", "../include/mgl2/vect.h", "../include/mgl2/prim.h", "../include/mgl2/other.h", "../include/mgl2/canvas_cf.h", "../include/mgl2/addon.h", ""};
+
+const char *head="\\ Mathgl library wrapper\n\
+\\ Copyright (C) 2008-2013, Sergey Plis, Alexey Balakin\n\\\n\
+\\ This program is free software; you can redistribute it and/or modify\n\
+\\ it under the terms of the GNU General Public License as published by\n\
+\\ the Free Software Foundation; either version 2 of the License, or\n\
+\\ (at your option) any later version.\n\\\n\
+\\ This program is distributed in the hope that it will be useful,\n\
+\\ but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
+\\ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\
+\\ GNU General Public License for more details.\n\n\
+Module mathgl\n\
+library libmgl      libmgl.so\n\
+library libmgl-glut libmgl-glut.so\n\
+library libmgl-fltk libmgl-fltk.so\n\
+library libmgl-qt   libmgl-qt.so\n\
+library libmgl-wx   libmgl-wx.so\n\
+legacy off\n\n\
+libmgl mgl_create_graph_gl\t\t(ptr)\tmgl_create_graph_gl\n\
+libmgl-glut mgl_create_graph_glut\tptr ptr ptr\t(ptr)\tmgl_create_graph_glut\n\
+libmgl-fltk mgl_create_graph_fltk\tptr ptr ptr\t(ptr)\tmgl_create_graph_fltk\n\
+libmgl-fltk mgl_fltk_run\t\t(void)\tmgl_fltk_run\n\
+libmgl-qt   mgl_create_graph_qt\tptr ptr ptr\t(ptr)\tmgl_create_graph_qt\n\
+libmgl-qt   mgl_qt_run\t\t\t(void)\tmgl_qt_run\n";
+
+const char *parse_name(char *name, char *fnc)
+{
+	static char res[1024];	memset(res,0,1024);
+	char *ptr,*arg[20],nul=0;	// TODO check if 20 arguments is enough
+	unsigned i;
+	for(i=0;name[i]!='(';i++)	res[i]=name[i];
+	memcpy(fnc,res,i);	fnc[i]=0;	// copy name for later
+	res[i]='\t';	i++;
+	for(int j=1;j<=(25-i)/4;j++)	res[i+j-1]='\t';
+
+/*	static char res[1024];
+	char *ptr,*arg[20],nul=0;	// TODO check if 20 arguments is enough
+	unsigned i;
+	for(i=0;name[i]!='(';i++)	res[i]=name[i];
+	memcpy(fnc,res,i);	fnc[i]=0;	// copy name for later
+	res[i]='\t';	res[i+1]=0;	i++;*/
+	
+	while(name[i]<=' ')	i++;
+	for(int j=0;j<20;j++)	arg[j]=&nul;
+	for(int j=0;j<20;j++)
+	{
+		arg[j]= name[i]<=' ' ? name+i+1 : name+i;
+		ptr=strchr(name+i,',');
+		if(!ptr)	break;
+		*ptr=0;	i=ptr-name+1;
+	}
+	ptr=strchr(name+i,')');	if(ptr) *ptr=0;
+	for(int j=19;j>=0;j--)
+	{
+		if(arg[j][0]==0)	continue;
+		if(!strncmp(arg[j],"HMGL ",5))	strcat(res, "ptr ");
+		else if(!strncmp(arg[j],"HADT ",5))	strcat(res, "ptr ");
+		else if(!strncmp(arg[j],"HCDT ",5))	strcat(res, "ptr ");
+		else if(!strncmp(arg[j],"HMDT ",5))	strcat(res, "ptr ");
+		else if(!strncmp(arg[j],"HMPR ",5))	strcat(res, "ptr ");
+		else if(!strncmp(arg[j],"HMEX ",5))	strcat(res, "ptr ");
+		else if(!strncmp(arg[j],"const float *",13))	strcat(res, "ptr ");
+		else if(!strncmp(arg[j],"const double *",14))	strcat(res, "ptr ");
+		else if(!strncmp(arg[j],"mreal *",7))	strcat(res, "ptr ");
+		else if(!strncmp(arg[j],"double *",8))	strcat(res, "ptr ");
+		else if(!strncmp(arg[j],"char *",6))	strcat(res, "ptr ");
+		else if(!strncmp(arg[j],"int *",5)) 	strcat(res, "ptr ");
+		else if(!strncmp(arg[j],"long *",6))	strcat(res, "ptr ");
+		else if(!strncmp(arg[j],"const char *",12))	strcat(res, "ptr ");
+		else if(!strncmp(arg[j],"const wchar_t *",15))	strcat(res, "ptr ");
+		else if(!strncmp(arg[j],"char ",5)) 	strcat(res, "char ");
+		else if(!strncmp(arg[j],"long ",5)) 	strcat(res, "int ");
+		else if(!strncmp(arg[j],"uint32_t ",9))	strcat(res, "int ");
+		else if(!strncmp(arg[j],"int ",4))		strcat(res, "int ");
+		else if(!strncmp(arg[j],"mreal ",6))	strcat(res, "sf ");
+		else if(!strncmp(arg[j],"double ",7))	strcat(res, "double ");
+		else if(!strncmp(arg[j],"gsl_vector *",12))	strcat(res, "ptr ");
+		else if(!strncmp(arg[j],"gsl_matrix *",12))	strcat(res, "ptr ");
+		else	sprintf(res, " !!! %s;", arg[j]);	// NOTE should be never here
+	}
+	return res;
+}
+
+bool parse_file(const char *fname, FILE *out)
+{
+	if(!fname || fname[0]==0)	return false;
+	FILE *fp=fopen(fname,"rt");
+	if(!fp)	return false;
+	
+	char buf[1024], *ptr, fnc[128]="";
+	while(!feof(fp))
+	{
+		fgets(buf,1024,fp);
+		// first filter unwanted strings
+		if(buf[0]==0 || buf[0]=='\n' || buf[1]=='\n')	continue;
+		if(buf[0]=='#' || buf[0]=='}')	continue;
+		if(!strncmp(buf, "extern",6))	continue;
+		if(!strncmp(buf, "class",5))	continue;
+		if(!strncmp(buf, "struct",6))	continue;
+		if(!strncmp(buf, "typedef",7))	continue;
+		if(strstr(buf, "void *"))	continue;
+		if(strstr(buf, "_("))	continue;
+		if(strstr(buf, "FILE"))	continue;
+		if(strstr(buf, "TODO"))	continue;
+		if(strstr(buf, "//"))	continue;
+		if(strstr(buf, "...)"))	continue;
+
+		// TODO following 5 lines enable later
+		if(strstr(buf, "* const *"))	continue;
+		if(strstr(buf, "uint64_t"))	continue;
+		if(strstr(buf, "dual"))	continue;
+		if(strstr(buf, "HADT"))	continue;
+		if(strstr(buf, "HAEX"))	continue;
+
+		// now filter comments
+		if(buf[0]=='/' && buf[1]=='*')
+		{
+			do fgets(buf,1024,fp);	while(!strstr(buf,"*/"));
+			continue;
+		}
+		ptr = strchr(buf,';');	if(ptr)	*ptr=' ';
+		for(unsigned i=strlen(buf)-1;buf[i]<=' ';i--)	buf[i]=0;
+		if(buf[0]=='/' && buf[1]=='/')
+			fprintf(out,"%s\n",buf);
+		else if(!strncmp(buf,"void MGL_EXPORT",15))
+			fprintf(out,"libmgl %s\t(void)\t%s\n",parse_name(buf+16,fnc),fnc);
+		else if(!strncmp(buf,"int MGL_EXPORT",14))
+			fprintf(out,"libmgl %s\t(int)\t%s\n",parse_name(buf+15,fnc),fnc);
+		else if(!strncmp(buf,"double MGL_EXPORT",17))
+			fprintf(out,"libmgl %s\t(double)\t%s\n",parse_name(buf+18,fnc),fnc);
+		else if(!strncmp(buf,"mreal MGL_EXPORT",16))
+			fprintf(out,"libmgl %s\t(sf)\t%s\n",parse_name(buf+17,fnc),fnc);
+		else if(!strncmp(buf,"long MGL_EXPORT",15))
+			fprintf(out,"libmgl %s\t(int)\t%s\n",parse_name(buf+16,fnc),fnc);
+		else if(!strncmp(buf,"HMDT MGL_EXPORT",15))
+			fprintf(out,"libmgl %s\t(ptr)\t%s\n",parse_name(buf+16,fnc),fnc);
+		else if(!strncmp(buf,"HMGL MGL_EXPORT",15))
+			fprintf(out,"libmgl %s\t(ptr)\t%s\n",parse_name(buf+16,fnc),fnc);
+		else if(!strncmp(buf,"MGL_EXPORT const char *",23))
+			fprintf(out,"libmgl %s\t(ptr)\t%s\n",parse_name(buf+24,fnc),fnc);
+		else if(!strncmp(buf,"MGL_EXPORT mreal *",18))
+			fprintf(out,"libmgl %s\t(ptr)\t%s\n",parse_name(buf+19,fnc),fnc);
+		else if(!strncmp(buf,"MGL_EXPORT const unsigned char *",32))
+			fprintf(out,"libmgl %s\t(ptr)\t%s\n",parse_name(buf+33,fnc),fnc);
+		else if(!strncmp(buf,"HMPR MGL_EXPORT",15))
+			fprintf(out,"libmgl %s\t(ptr)\t%s\n",parse_name(buf+16,fnc),fnc);
+		else if(!strncmp(buf,"HMEX MGL_EXPORT",15))
+			fprintf(out,"libmgl %s\t(ptr)\t%s\n",parse_name(buf+16,fnc),fnc);
+		else if(!strncmp(buf,"HADT MGL_EXPORT",15))
+			fprintf(out,"libmgl %s\t(ptr)\t%s\n",parse_name(buf+16,fnc),fnc);
+		else	fprintf(out,"!!!!\t%s\n",buf);	// NOTE should be never here!
+	}
+	fclose(fp);
+	return true;
+}
+
+int main()
+{
+	FILE *fout = fopen("../include/mgl2/mgl.fs","wt");
+	fprintf(fout,"%s\n",head);
+	for(int i=0;parse_file(files[i],fout);i++);
+	fclose(fout);
+	return 0;
+}
diff --git a/utils/make_pas.cpp b/utils/make_pas.cpp
new file mode 100644
index 0000000..eb67790
--- /dev/null
+++ b/utils/make_pas.cpp
@@ -0,0 +1,511 @@
+#include <stdio.h>
+#include <string.h>
+#include<mgl2/define.h>
+
+
+const char *files[] =
+{
+	"../../include/mgl2/abstract.h",
+	"../../include/mgl2/base_cf.h",
+	"../../include/mgl2/data_cf.h",
+	"../../include/mgl2/datac_cf.h",
+	"../../include/mgl2/cont.h",
+	"../../include/mgl2/fit.h",
+	"../../include/mgl2/plot.h",
+	"../../include/mgl2/surf.h",
+	"../../include/mgl2/volume.h",
+	"../../include/mgl2/vect.h",
+	"../../include/mgl2/prim.h",
+	"../../include/mgl2/other.h",
+	"../../include/mgl2/canvas_cf.h",
+	"../../include/mgl2/addon.h",
+	"" };
+
+const char *head =
+		"//**************************************************************************\n\
+// mgl_pas.pas is part of Math Graphic Library                             *\n\
+// Copyright (C) 2008-2013 Mikhail Barg, Alexey Balakin                    *\n\
+//                                                                         *\n\
+//   This program is free software; you can redistribute it and/or modify  *\n\
+//   it under the terms of the GNU Library General Public License as       *\n\
+//   published by the Free Software Foundation; either version 2 of the    *\n\
+//   License, or (at your option) any later version.                       *\n\
+//                                                                         *\n\
+//   This program is distributed in the hope that it will be useful,       *\n\
+//   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\n\
+//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\n\
+//   GNU General Public License for more details.                          *\n\
+//                                                                         *\n\
+//   You should have received a copy of the GNU Library General Public     *\n\
+//   License along with this program; if not, write to the                 *\n\
+//   Free Software Foundation, Inc.,                                       *\n\
+//   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *\n\
+//**************************************************************************\n\n\
+unit mgl_pas;\n\n\
+{$IFDEF FPC}\n\
+{$MODE DELPHI }\n\
+{$PACKENUM 4}    (* use 4-byte enums *)\n\
+{$PACKRECORDS C} (* C/C++-compatible record packing *)\n\
+{$ELSE}\n\
+{$MINENUMSIZE 4} (* use 4-byte enums *)\n\
+{$ENDIF}\n\n\
+{$IFDEF DARWIN}\n\
+{$linklib libmgl}\n\
+{$ENDIF}\n\n\
+interface\n\n\
+uses\n\
+{$IFDEF MSWINDOWS}\n\
+Windows, Graphics,\n\
+{$ENDIF}\n\
+Math;\n\n\
+const MGL_VER2 = 2.2;\n\
+//* This define enables double precision in MathGL */\n\
+MGL_USE_DOUBLE = 1;\n\n\
+const\n\
+{$IFDEF MSWINDOWS}\n\
+//win - .dll\n\
+libmgl = 'libmgl.dll';\n\
+libmglglut = 'libmgl-glut.dll';\n\
+libmglfltk = 'libmgl-fltk.dll';\n\
+libmglqt   = 'libmgl-qt.dll';\n\
+{$ELSE}\n\
+{$IFDEF LINUX}\n\
+//linux - .so\n\
+libmgl = 'libmgl.so';\n\
+libmglglut = 'libmgl-glut.so';\n\
+libmglfltk = 'libmgl-fltk.so';\n\
+libmglqt   = 'libmgl-qt.so';\n\
+{$ELSE}\n\
+{$IFDEF DARWIN}\n\
+//darwin - .dylib\n\
+libmgl = 'libmgl.dylib';\n\
+libmglglut = 'libmgl-glut.dylib';\n\
+libmglfltk = 'libmgl-fltk.dylib';\n\
+libmglqt   = 'libmgl-qt.dylib';\n\
+{$ELSE}\n\
+// other platforms?\n\n\
+{$ENDIF}\n\
+{$ENDIF}\n\
+{$ENDIF}\n\n\
+{$IF (MGL_USE_DOUBLE = 0)}\n\
+type mreal = double;\n\
+{$ELSE}\n\
+type mreal = real;\n\
+{$IFEND}\n\
+{$IFDEF FPC}\n\
+{$ELSE}\n\
+type QWord = Int64;\n\
+{$ENDIF}\n\n\
+Pmreal = ^mreal;\n\n\
+type TNGLDraw = record\n\
+end;\n\
+type TMGLGraph = record\n\
+end;\n\
+type TMGLData = record\n\
+end;\n\
+type TMGLParse = record\n\
+end;\n\
+type TMGLFormula = record\n\
+end;\n\
+type TMGLFormulaC = record\n\
+end;\n\
+type TMGLDataC = record\n\
+end;\n\
+type HMDR = ^TNGLDraw;\n\
+type HMGL = ^TMGLGraph;\n\
+type HMDT = ^TMGLData;\n\
+type HMPR = ^TMGLParse;\n\
+type PPChar = ^PChar;\n\
+type HMEX = ^TMGLFormula;\n\
+type HAEX = ^TMGLFormulaC;\n\
+type HADT = ^TMGLDataC;\n\n\
+type Preal = ^single;\n\
+type Pdouble = ^double;\n\
+type Pint = ^integer;\n\
+type dual = record\n\
+re, im: mreal;\n\
+end;\n\
+type Pdual = ^dual;\n\
+type TGSLVector = record\n\
+end;\n\
+type TGSLMatrix = record\n\
+end;\n\
+type PGSLVector = ^TGSLVector;\n\
+type PGSLMatrix = ^TGSLMatrix;\n\n\
+type TMglDrawFunction = function (gr: HMGL; p: pointer): integer; cdecl;\n\
+function mgl_create_graph_gl(): HMGL; cdecl; external libmgl;\n\
+function mgl_create_graph_glut(draw: TMglDrawFunction; const title: PChar; par: pointer): HMGL; cdecl; external libmglglut;\n\
+function mgl_create_graph_fltk(draw: TMglDrawFunction; const title: PChar; par: pointer): HMGL; cdecl; external libmglfltk;\n\
+procedure mgl_fltk_run(); cdecl; external libmglfltk;\n\
+function mgl_create_graph_qt(draw: TMglDrawFunction; const title: PChar; par: pointer): HMGL; cdecl; external libmglqt;\n\
+procedure mgl_qt_run(); cdecl; external libmglqt;\n";
+
+
+const char *footer =
+"\n\
+\n\
+{$IFDEF MSWINDOWS}\n\
+//*****************************************************************************/\n\
+// Delphi - specific\n\
+//*****************************************************************************/\n\
+procedure mgl_begin();\n\
+procedure mgl_end();\n\
+\n\
+procedure mgl_draw_on_canvas(gr: HMGL; width, height: integer; canvas: TCanvas; switchXY: boolean = false);\n\
+\n\
+implementation\n\
+\n\
+var _FPUCW: word;\n\
+\n\
+procedure mgl_begin();\n\
+ begin\n\
+  _FPUCW := Get8087CW();     // backup current FPU CW\n\
+  Set8087CW(_FPUCW or $3F); // masking all FPU exceptions\n\
+ end;\n\
+\n\
+procedure mgl_end();\n\
+ begin\n\
+  Set8087CW(_FPUCW);         // restore old FPU CW\n\
+ end;\n\
+\n\
+procedure mgl_draw_on_canvas(gr: HMGL; width, height: integer; canvas: TCanvas; switchXY: boolean = false);\n\
+  var i, j: integer;\n\
+      bytes: PByte;\n\
+      col: TColor;\n\
+ begin\n\
+  bytes := mgl_get_rgb(gr);\n\
+\n\
+  if (not switchXY) then\n\
+   for j := 0 to height - 1 do\n\
+    for i := 0 to width - 1 do\n\
+     begin\n\
+      col := 0;\n\
+      col := col or (bytes^);\n\
+      inc(bytes);\n\
+      col := col or (bytes^) shl 8;\n\
+      inc(bytes);\n\
+       col := col or (bytes^) shl 16;\n\
+      inc(bytes);\n\
+      canvas.Pixels[i, j] := col;\n\
+    end\n\
+  else\n\
+   for j := height - 1 downto 0 do\n\
+    for i := 0 to width - 1 do\n\
+     begin\n\
+      col := 0;\n\
+      col := col or (bytes^);\n\
+      inc(bytes);\n\
+      col := col or (bytes^) shl 8;\n\
+      inc(bytes);\n\
+       col := col or (bytes^) shl 16;\n\
+      inc(bytes);\n\
+      canvas.Pixels[j, i] := col;\n\
+     end;\n\
+ end;\n\
+\n\
+{$ENDIF}\n\
+end.\n";
+
+
+bool processArgument(char *dest, const char *arg, const char *prefix, const char *format)
+{
+	const int prefixLen = strlen(prefix);
+	if ( strncmp(arg, prefix, prefixLen) == 0 )
+	{
+		char argname[32];
+		strcpy(argname, arg + prefixLen);
+		if (strcmp(argname, "to") == 0)
+		{
+			int argNameLen = strlen(argname);
+			argname[argNameLen] = '_';
+			argname[argNameLen + 1] = 0;
+		}
+		sprintf(dest, format, argname);
+		return true;
+	}
+	return false;
+}
+
+const char *parse_name(char *name, bool &needOverload)
+{
+	const int MAX_ARG = 20; // TODO check if 20 arguments is enough
+	static char res[1024];
+	char *ptr, *arg[MAX_ARG], nul = 0;	
+	unsigned i, j;
+	needOverload = false;
+	for ( i = 0; name[i] != '('; ++i )
+	{
+		res[i] = name[i];
+	}
+
+//	res[i] = 0;
+//	printf("'%s'\n", res);
+	
+	//TODO: special case, invent some general way to handle overloads, i.e. functions with same names. Still would require re-doing whole parser..
+	if (strncmp(res, " mgl_expi", i - 1) == 0)
+	{
+		needOverload = true;
+	}
+	res[i] = '(';
+	res[i + 1] = 0;
+	++i;
+	while ( name[i] <= ' ' )
+	{
+		++i;
+	}
+	for ( j = 0; j < MAX_ARG; ++j )
+	{
+		arg[j] = &nul;
+	}
+	for ( j = 0; j < MAX_ARG; ++j )
+	{
+		arg[j] = (name[i] <= ' ' ? name + i + 1 : name + i);
+		ptr = strchr(name + i, ',');
+		if ( !ptr )
+		{
+			break;
+		}
+		*ptr = 0;
+		i = ptr - name + 1;
+	}
+	ptr = strchr(name + i, ')');
+	if ( ptr )
+	{
+		*ptr = 0;
+	}
+	if ( arg[0][0] == 0 )
+	{
+		strcat(res, " ");
+	}
+	for ( j = 0; j < MAX_ARG; ++j )
+	{
+		if ( arg[j][0] == 0 )
+		{
+			break;
+		}
+		ptr = res + strlen(res);
+		if ( 		processArgument(ptr, arg[j], "HMGL ", "%s: HMGL;")
+				||  processArgument(ptr, arg[j], "HCDT ",  "const %s: HMDT;")
+				||	processArgument(ptr, arg[j], "HMDT ",  "%s: HMDT;")
+				||	processArgument(ptr, arg[j], "mglDataA *",  "%s: HMDT;")
+				||	processArgument(ptr, arg[j], "HADT ",  "%s: HADT;")
+				||	processArgument(ptr, arg[j], "HAEX ",  "%s: HAEX;")
+				||	processArgument(ptr, arg[j], "HMPR ",  "%s: HMPR;")
+				||	processArgument(ptr, arg[j], "HMEX ",  "%s: HMEX;")
+				||	processArgument(ptr, arg[j], "const float *",  "const %s: Preal;")
+				||	processArgument(ptr, arg[j], "const double *",  "const %s: Pdouble;")
+				||	processArgument(ptr, arg[j], "mreal *",  "%s: Pmreal;")
+				||	processArgument(ptr, arg[j], "double *",  "%s: Pdouble;")
+				||	processArgument(ptr, arg[j], "char *",  "%s: PChar;")
+				||	processArgument(ptr, arg[j], "unsigned char *",  "%s: PByte;")
+				||	processArgument(ptr, arg[j], "int *", "%s: Pint;")
+				||	processArgument(ptr, arg[j], "long *",  "%s: Pint;")
+				||	processArgument(ptr, arg[j], "const char *",  "const %s: PChar;")
+				||	processArgument(ptr, arg[j], "const unsigned char *",  "const %s: PByte;")
+				||	processArgument(ptr, arg[j], "const wchar_t *",  "const %s: PWideChar;")
+				||	processArgument(ptr, arg[j], "char ",  "%s: char;")
+				||	processArgument(ptr, arg[j], "long ",  "%s: integer;")
+				||	processArgument(ptr, arg[j], "uint32_t ",  "%s: LongWord;")
+				||	processArgument(ptr, arg[j], "uint64_t ",  "%s: QWord;")
+				||	processArgument(ptr, arg[j], "int ",  "%s: integer;")
+				||	processArgument(ptr, arg[j], "mreal ",  "%s: mreal;")
+				||	processArgument(ptr, arg[j], "const dual *",  "const %s: Pdual;")
+				||	processArgument(ptr, arg[j], "dual *",  "%s: Pdual;")
+				||	processArgument(ptr, arg[j], "dual ",  "%s: dual;")
+				||	processArgument(ptr, arg[j], "double ",  "%s: double;")
+				||	processArgument(ptr, arg[j], "gsl_vector *",  "%s: PGSLVector;")
+				||	processArgument(ptr, arg[j], "gsl_matrix *",  "%s: PGSLMatrix;")
+			)
+		{
+			//already procedded in processArgument
+		}
+		else
+		{
+			sprintf(ptr, " !!! %s;", arg[j]);
+		}
+	}
+	
+	i = strlen(res);
+	res[i - 1] = ')';
+	return res;
+}
+
+bool processDeclaration(FILE *out, char *declaration, const char *prefix, const char *format)
+{
+	const int prefixLen = strlen(prefix);
+	if ( strncmp(declaration, prefix, prefixLen) == 0 )
+	{
+		bool needOverload = false;
+		fprintf(out, format, parse_name(declaration + prefixLen, needOverload));
+		if (needOverload)
+		{
+			fprintf(out, "overload;\n");
+		}
+		return true;
+	}
+	return false;
+}
+
+bool parse_file(const char *fname, FILE *out)
+{
+	if ( !fname || fname[0] == 0 )
+	{
+		return false;
+	}
+	FILE *fp = fopen(fname, "rt");
+	if ( !fp )
+	{
+		return false;
+	}
+	
+	fprintf(out, "{== %s ==}\n", fname);
+	
+	char buf[1024], *ptr;
+	while ( !feof(fp) )
+	{
+		fgets(buf, 1024, fp);
+		// first filter unwanted strings
+		if ( buf[0] == 0 || buf[0] == '\n' || buf[1] == '\n' )
+		{
+			continue;
+		}
+		if ( buf[0] == '#' || buf[0] == '}' )
+		{
+			continue;
+		}
+		if ( !strncmp(buf, "extern", 6) )
+		{
+			continue;
+		}
+		if ( !strncmp(buf, "class", 5) )
+		{
+			continue;
+		}
+		if ( !strncmp(buf, "struct", 6) )
+		{
+			continue;
+		}
+		if ( !strncmp(buf, "typedef", 7) )
+		{
+			continue;
+		}
+		if ( strstr(buf, "void *") )
+		{
+			continue;
+		}
+		if ( strstr(buf, "_(") )
+		{
+			continue;
+		}
+		if ( strstr(buf, "FILE") )
+		{
+			continue;
+		}
+		if ( strstr(buf, "TODO") )
+		{
+			continue;
+		}
+		if ( strstr(buf, "...)") )
+		{
+			continue;
+		}
+		
+		// TODO enable later
+		if ( strstr(buf, "* const *") )
+		{
+			continue;
+		}
+		
+		// now filter comments
+		if ( buf[0] == '/' && buf[1] == '*' )
+		{
+			do
+			{
+				fgets(buf, 1024, fp);
+			}
+			while ( !strstr(buf, "*/") );
+			continue;
+		}
+		ptr = strchr(buf, ';');
+		if ( ptr )
+		{
+			*ptr = ' ';
+		}
+		for ( unsigned i = strlen(buf) - 1; buf[i] <= ' '; i-- )
+		{
+			buf[i] = 0;
+		}
+		if ( buf[0] == '/' && buf[1] == '/' )
+		{
+			fprintf(out, "%s\n", buf);
+		}
+		else if (	   processDeclaration(out, buf, "void MGL_EXPORT_PURE", 	"procedure %s; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "int MGL_EXPORT_PURE", 		"function %s: integer; cdecl; external libmgl;\n") 
+					|| processDeclaration(out, buf, "double MGL_EXPORT_PURE", 	"function %s: double; cdecl; external libmgl;\n") 
+					|| processDeclaration(out, buf, "mreal MGL_EXPORT_PURE", 	"function %s: mreal; cdecl; external libmgl;\n") 
+					|| processDeclaration(out, buf, "long MGL_EXPORT_PURE", 	"function %s: integer; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "mdual MGL_EXPORT_PURE", 	"function %s: dual; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "MGL_EXPORT_PURE dual *", 	"function %s: PDual; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "HMDT MGL_EXPORT_PURE", 	"function %s: HMDT; cdecl; external libmgl;\n") 
+					|| processDeclaration(out, buf, "HMGL MGL_EXPORT_PURE", 	"function %s: HMGL; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "MGL_EXPORT_PURE const char *", "function %s: PChar; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "MGL_EXPORT_PURE mreal *", 	"function %s: Pmreal; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "MGL_EXPORT_PURE const unsigned char *", "function %s: PByte; cdecl; external libmgl;\n") 
+					|| processDeclaration(out, buf, "HMPR MGL_EXPORT_PURE", 	"function %s: HMPR; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "HMEX MGL_EXPORT_PURE", 	"function %s: HMEX; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "HADT MGL_EXPORT_PURE", 	"function %s: HADT; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "HAEX MGL_EXPORT_PURE", 	"function %s: HAEX; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "void MGL_EXPORT_CONST", 		"procedure %s; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "int MGL_EXPORT_CONST", 		"function %s: integer; cdecl; external libmgl;\n") 
+					|| processDeclaration(out, buf, "double MGL_EXPORT_CONST", 	"function %s: double; cdecl; external libmgl;\n") 
+					|| processDeclaration(out, buf, "mreal MGL_EXPORT_CONST", 	"function %s: mreal; cdecl; external libmgl;\n") 
+					|| processDeclaration(out, buf, "long MGL_EXPORT_CONST", 		"function %s: integer; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "mdual MGL_EXPORT_CONST", 	"function %s: dual; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "MGL_EXPORT_CONST dual *", 	"function %s: PDual; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "HMDT MGL_EXPORT_CONST", 		"function %s: HMDT; cdecl; external libmgl;\n") 
+					|| processDeclaration(out, buf, "HMGL MGL_EXPORT_CONST", 		"function %s: HMGL; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "MGL_EXPORT_CONST const char *", "function %s: PChar; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "MGL_EXPORT_CONST mreal *", 	"function %s: Pmreal; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "MGL_EXPORT_CONST const unsigned char *", "function %s: PByte; cdecl; external libmgl;\n") 
+					|| processDeclaration(out, buf, "HMPR MGL_EXPORT_CONST", 		"function %s: HMPR; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "HMEX MGL_EXPORT_CONST", 		"function %s: HMEX; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "HADT MGL_EXPORT_CONST", 		"function %s: HADT; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "HAEX MGL_EXPORT_CONST", 		"function %s: HAEX; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "void MGL_EXPORT", 		"procedure %s; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "int MGL_EXPORT", 		"function %s: integer; cdecl; external libmgl;\n") 
+					|| processDeclaration(out, buf, "double MGL_EXPORT", 	"function %s: double; cdecl; external libmgl;\n") 
+					|| processDeclaration(out, buf, "mreal MGL_EXPORT", 	"function %s: mreal; cdecl; external libmgl;\n") 
+					|| processDeclaration(out, buf, "long MGL_EXPORT", 		"function %s: integer; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "mdual MGL_EXPORT", 	"function %s: dual; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "MGL_EXPORT dual *", 	"function %s: PDual; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "HMDT MGL_EXPORT", 		"function %s: HMDT; cdecl; external libmgl;\n") 
+					|| processDeclaration(out, buf, "HMGL MGL_EXPORT", 		"function %s: HMGL; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "MGL_EXPORT const char *", "function %s: PChar; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "MGL_EXPORT mreal *", 	"function %s: Pmreal; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "MGL_EXPORT const unsigned char *", "function %s: PByte; cdecl; external libmgl;\n") 
+					|| processDeclaration(out, buf, "HMPR MGL_EXPORT", 		"function %s: HMPR; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "HMEX MGL_EXPORT", 		"function %s: HMEX; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "HADT MGL_EXPORT", 		"function %s: HADT; cdecl; external libmgl;\n")
+					|| processDeclaration(out, buf, "HAEX MGL_EXPORT", 		"function %s: HAEX; cdecl; external libmgl;\n")
+				)
+		{
+			//already processed by processDeclaration
+		}
+/*		else	// comment this -- it looks as it hangs on classes only, which should be omitted by anyway
+		{
+			fprintf(out, "{!!!!\t%s}\n", buf);	// NOTE should be never here!
+		}*/
+	}
+	fclose(fp);
+	return true;
+}
+
+int main()
+{
+	FILE *fout = fopen("../../include/mgl2/mgl_pas.pas", "wt");
+	fprintf(fout, "%s\n", head);
+	for ( int i = 0; parse_file(files[i], fout); i++ ) {}
+	fprintf(fout, "%s\n", footer);
+	fclose(fout);
+	return 0;
+}
diff --git a/utils/mgl_test.html b/utils/mgl_test.html
new file mode 100644
index 0000000..24edd50
--- /dev/null
+++ b/utils/mgl_test.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta content="text/html; charset=utf-8" http-equiv="content-type">
+	<title>MathGL - library for scientific graphics</title><script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
+</head><body>
+
+
+<p>Enter script below</p>
+<form action='http://balakin.appl.sci-nnov.ru/cgi-bin/mgl.cgi' method='POST' target='result'>
+<textarea name='mgl' rows='18' cols='80'>box</textarea><br/>
+<button type='submit'> Submit </button></form><br>
+
+</body></html>
diff --git a/utils/mglcgi.cpp b/utils/mglcgi.cpp
new file mode 100644
index 0000000..907c1d8
--- /dev/null
+++ b/utils/mglcgi.cpp
@@ -0,0 +1,91 @@
+/***************************************************************************
+ * mglcgi.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <locale.h>
+#include "mgl2/mgl.h"
+//-----------------------------------------------------------------------------
+int MGL_LOCAL_CONST mgl_hex(char ch)
+{
+	int res=-1;
+	if(ch>='0' && ch<='9')	res = ch-'0';
+	if(ch>='a' && ch<='f')	res = ch-'a'+10;
+	if(ch>='A' && ch<='F')	res = ch-'A'+10;
+	return res;
+}
+//-----------------------------------------------------------------------------
+/// Parse CGI string buf and return usual string as val for given name.
+/// The size of val should be the same as size of buf.
+void mgl_get_value(const char *buf, const char *name, char *val)
+{
+	const char *pos = strstr(buf,name);
+	memset(val,0,strlen(buf)+1);
+	if(pos && (pos==buf || pos[-1]=='&'))
+	{
+		pos+=4;	// shift for "mgl="
+		size_t l=strlen(pos);
+		for(size_t i=0, j=0;i<l;i++,j++)
+		{
+			char ch=pos[i];
+			if(ch=='&')	break;
+			else if(ch=='+')	val[j]=' ';
+			else if(ch=='%' && i+2<l)
+			{	val[j] = 16*mgl_hex(pos[i+1]) + mgl_hex(pos[i+2]);	i+=2;	}
+			else		val[j]=ch;
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+int main(int argc, char **argv)
+{
+	mgl_textdomain(argv?argv[0]:NULL,"");
+	mgl_suppress_warn(true);
+	mglGraph gr;
+	mglParse p(true);
+
+	mgl_ask_func = 0;
+	// read script
+	char *str, *buf;
+	const char *method = getenv("REQUEST_METHOD");
+	bool alloc=false;
+	if(method && strcmp(method,"GET"))
+	{
+		long len=atol(getenv("CONTENT_LENGTH"));
+		buf = new char[len+1];
+		if(!fread(buf,len,1,stdin))	len=0;
+		buf[len]=0;	alloc=true;
+	}
+	else		buf = getenv("QUERY_STRING");
+	if(buf==0)	{	printf(_("There is no query. Exit.\n"));	return 0;	}
+	str = new char[strlen(buf)+1];
+	mgl_get_value(buf,"mgl",str);
+
+	p.Execute(&gr,str);
+
+/*	printf("Content-Type: text/html\n\n");
+	printf("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd\">\n");
+	printf("<html><head><meta content=\"text/html; charset=utf-8\" http-equiv=\"content-type\">\n");
+	printf("<title>MathGL - library for scientific graphics</title></head><body>\n<img>\n");
+	gr.WriteSVG("-");	fflush(stdout);
+	printf("</img></body></html>\n");*/
+
+	printf("Content-Type: image/png\n\n");	gr.WritePNG("-");
+	if(alloc)	delete []buf;
+	return 0;
+}
+//-----------------------------------------------------------------------------
diff --git a/utils/mglconv.cpp b/utils/mglconv.cpp
new file mode 100644
index 0000000..4f4d869
--- /dev/null
+++ b/utils/mglconv.cpp
@@ -0,0 +1,164 @@
+/***************************************************************************
+ * mglconv.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <locale.h>
+#include <getopt.h>
+#include "mgl2/mgl.h"
+
+#ifdef _MSC_VER
+#define mnpos (std::basic_string<wchar_t>::size_type)-1
+#else
+#define mnpos std::wstring::npos
+#endif
+void mgl_error_print(const char *Message, void *par);
+void mgl_ask_gets(const wchar_t *quest, wchar_t *res);
+//-----------------------------------------------------------------------------
+int main(int argc, char *argv[])
+{
+	mgl_textdomain(argv?argv[0]:NULL,"");
+	mgl_suppress_warn(true);
+	mglGraph gr;
+	mglParse p(true);
+	char buf[2048], iname[256]="", oname[256]="";
+	std::vector<std::wstring> var;
+	std::wstring str;
+	bool none=false;
+
+	while(1)
+	{
+		int ch = getopt(argc, argv, "1:2:3:4:5:6:7:8:9:hno:L:C:A:s:S:q:v:g:");
+		if(ch>='1' && ch<='9')	p.AddParam(ch-'0', optarg);
+		else if(ch=='s')
+		{
+			FILE *fp = fopen(optarg,"r");
+			if(fp)
+			{
+				wchar_t ch;
+				while(!feof(fp) && size_t(ch=fgetwc(fp))!=WEOF)	str.push_back(ch);
+				fclose(fp);	str += L"\n";
+			}
+		}
+		else if(ch=='n')	none = true;
+		else if(ch=='L')
+		{	setlocale(LC_ALL, optarg);	setlocale(LC_NUMERIC, "C");	}
+		else if(ch=='S')	mgl_set_size_scl(atof(optarg));
+		else if(ch=='q')	gr.SetQuality(atoi(optarg));
+		else if(ch=='v')	p.SetVariant(atoi(optarg));
+		else if(ch=='g')	gr.Gray(atoi(optarg));
+		else if(ch=='A')
+		{
+			std::wstring str;
+			for(size_t i=0;optarg[i];i++)	str.push_back(optarg[i]);
+			var.push_back(str);
+		}
+		else if(ch=='C')
+		{
+			double v1,v2,dv=1,v;
+			int res=sscanf(optarg,"%lg:%lg:%lg",&v1,&v2,&dv);
+			if(res<3)	dv=1;
+			wchar_t num[64];
+			for(v=v1;v<=v2;v+=dv)
+			{
+				mglprintf(num,64,L"%g",v);
+				var.push_back(num);
+			}
+		}
+		else if(ch=='h' || (ch==-1 && optind>=argc))
+		{
+			printf(_("mglconv convert mgl script to image file (default PNG).\nCurrent version is 2.%g\n"),MGL_VER2);
+			printf(_("Usage:\tmglconv [parameter(s)] scriptfile\n"));
+			printf(
+				_("\t-1 str       set str as argument $1 for script\n"
+				"\t...          ...\n"
+				"\t-9 str       set str as argument $9 for script\n"
+				"\t-L loc       set locale to loc\n"
+				"\t-s fname     set MGL script for setting up the plot\n"
+				"\t-S val       set scaling factor for images\n"
+				"\t-q val       set quality for output (val=0...9)\n"
+				"\t-g val       set gray-scale mode (val=0|1)\n"
+				"\t-v val       set variant of arguments\n"
+				"\t-o name      set output file name\n"
+				"\t-n           no default output (script should save results by itself)\n"
+				"\t-A val       add animation value val\n"
+				"\t-C n1:n2:dn  add animation value in range [n1,n2] with step dn\n"
+				"\t-C n1:n2     add animation value in range [n1,n2] with step 1\n"
+				"\t-            get script from standard input\n"
+				"\t-h           print this message\n") );
+			return 0;
+		}
+		else if(ch=='o')	strncpy(oname, optarg,256);
+		else if(ch==-1 && optind<argc)
+		{	strncpy(iname, argv[optind][0]=='-'?"":argv[optind],256);	break;	}
+	}
+	if(*oname==0)	{	strncpy(oname,*iname?iname:"out",250);	strcat(oname,".png");	}
+	else	none = false;
+
+	mgl_ask_func = mgl_ask_gets;
+	// prepare for animation
+	FILE *fp = *iname?fopen(iname,"r"):stdin;
+	if(!fp)	{	printf("No file for MGL script\n");	return 0;	}
+	wchar_t cw;
+	while(!feof(fp) && size_t(cw=fgetwc(fp))!=WEOF)	str.push_back(cw);
+	if(*iname)	fclose(fp);
+
+	size_t n;
+	for(size_t i=0;;)	// collect exact values
+	{
+		n = str.find(L"##a ",i);
+		if (n == mnpos)	break;
+		i = n+4;	var.push_back(str.substr(i,str.find('\n',i)));
+	}
+	n = str.find(L"##c ");
+	if (n != mnpos)
+		{
+		double v1,v2,dv,v;
+		wscanf(str.c_str()+n+4,L"%lg%lg%lg",&v1,&v2,&dv);
+		wchar_t ss[64];
+		for(v=v1;v<=v2;v+=dv)
+		{	mglprintf(ss,64,L"%g",v);	var.push_back(ss);	}
+	}
+	bool gif = !strcmp(oname+strlen(oname)-4,".gif");
+	gr.SetSize(600,400);	// specially call for "S" option
+	if(var.size()>1)	// there is animation
+	{
+		if(gif)	gr.StartGIF(oname);
+		for(size_t i=0;i<var.size();i++)
+		{
+			gr.NewFrame();
+			printf("frame %zu for $0 = \"%ls\"\n",i,var[i].c_str());
+			p.AddParam(0,var[i].c_str());
+			p.Execute(&gr,str.c_str());
+			if(gr.Message()[0])	printf("%s\n",gr.Message());
+			gr.EndFrame();
+			snprintf(buf,2048,"%s-%zu",oname,i);	buf[2047]=0;
+			if(!gif)	gr.WriteFrame(buf);
+		}
+		if(gif)	gr.CloseGIF();
+	}
+	else
+	{
+		p.Execute(&gr,str.c_str());
+		if(gr.Message()[0])	printf("%s\n",gr.Message());
+		if(!none)	gr.WriteFrame(oname);
+	}
+	if(!mglGlobalMess.empty())	printf("%s",mglGlobalMess.c_str());
+	if(!none || gif)	printf("Write output to %s\n",oname);
+	return 0;
+}
+//-----------------------------------------------------------------------------
diff --git a/utils/mglview.cpp b/utils/mglview.cpp
new file mode 100644
index 0000000..0faed5b
--- /dev/null
+++ b/utils/mglview.cpp
@@ -0,0 +1,131 @@
+/***************************************************************************
+ * mglview.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+#include <locale.h>
+#include <getopt.h>
+
+#include "mgl2/mgl.h"
+#if USE_FLTK
+	#include "mgl2/fltk.h"
+	#include <Fl/Fl.H>
+	#include <Fl/Fl_Preferences.H>
+#else
+	#include "mgl2/qt.h"
+#endif
+//-----------------------------------------------------------------------------
+std::wstring str, opt;
+mglParse p(true);
+//-----------------------------------------------------------------------------
+int show(mglGraph *gr)
+{
+	p.Execute(gr,str.c_str());
+	printf("%s\n",gr->Message());
+	return 0;
+}
+//-----------------------------------------------------------------------------
+int main(int argc, char **argv)
+{
+	mgl_textdomain(argv?argv[0]:NULL,"");
+	char iname[256]="";
+	mgl_suppress_warn(true);
+	bool gray = false;
+	while(1)
+	{
+		int ch = getopt(argc, argv, "1:2:3:4:5:6:7:8:9:hL:s:g:v:");
+		if(ch>='1' && ch<='9')	p.AddParam(ch-'0', optarg);
+		else if(ch=='s')
+		{
+			FILE *fp = fopen(optarg,"r");
+			if(fp)
+			{
+				wchar_t ch;
+				while(!feof(fp) && size_t(ch=fgetwc(fp))!=WEOF)	opt.push_back(ch);
+				fclose(fp);
+			}
+		}
+		else if(ch=='v')	p.SetVariant(atoi(optarg));
+		else if(ch=='g')	gray= atoi(optarg);
+		else if(ch=='L')
+		{	setlocale(LC_ALL, optarg);	setlocale(LC_NUMERIC, "C");	}
+		else if(ch=='h' || (ch==-1 && optind>=argc))
+		{
+			printf(_("mglview show plot from MGL script or MGLD file.\nCurrent version is 2.%g\n"),MGL_VER2);
+			printf(_("Usage:\tmglview [parameter(s)] scriptfile\n"));
+			printf(
+				_("\t-1 str       set str as argument $1 for script\n"
+				"\t...          ...\n"
+				"\t-9 str       set str as argument $9 for script\n"
+				"\t-g val       set gray-scale mode (val=0|1)\n"
+				"\t-v val       set variant of arguments\n"
+				"\t-s opt       set MGL script for setting up the plot\n"
+				"\t-L loc       set locale to loc\n"
+				"\t-            get script from standard input\n"
+				"\t-h           print this message\n") );
+			return 0;
+		}
+		else if(ch==-1 && optind<argc)
+		{	strncpy(iname, argv[optind][0]=='-'?"":argv[optind],256);	break;	}
+	}
+
+	bool mgld=(*iname && iname[strlen(iname)-1]=='d');
+	if(!mgld)
+	{
+		str = opt + L"\n";
+		FILE *fp = *iname?fopen(iname,"r"):stdin;
+		if(fp)
+		{
+			wchar_t ch;
+			while(!feof(fp) && size_t(ch=fgetwc(fp))!=WEOF)	str.push_back(ch);
+			fclose(fp);
+		}
+		else	{	printf("No file for MGL script\n");	return 0;	}
+	}
+
+#if USE_FLTK
+	mgl_ask_func = mgl_ask_fltk;
+	Fl_Preferences pref(Fl_Preferences::USER,"abalakin","mgllab");
+	static const char *sch[4]={"base","gtk+","plastic","gleam"};
+	int scheme;	pref.get("scheme",scheme,2);
+	Fl::scheme(sch[scheme]);
+	mglFLTK gr(mgld?NULL:show, *iname?iname:"mglview");
+#else
+	mgl_ask_func = mgl_ask_qt;
+	mglQT gr(mgld?NULL:show, *iname?iname:"mglview");
+#endif
+	if(gray)	gr.Gray(gray);
+
+	if(mgld)
+	{
+		gr.Setup(false);
+		gr.NewFrame();
+		const std::string loc = setlocale(LC_NUMERIC, "C");
+		if(!opt.empty())
+		{
+			p.Execute(&gr,opt.c_str());
+			printf("Setup script: %s\n",gr.Message());
+			gr.ImportMGLD(iname,true);
+		}
+		else	gr.ImportMGLD(iname);
+		setlocale(LC_NUMERIC, loc.c_str());
+		gr.EndFrame();	gr.Update();
+	}
+	if(!mglGlobalMess.empty())	printf("%s",mglGlobalMess.c_str());
+	return gr.Run();
+}
+//-----------------------------------------------------------------------------
diff --git a/widgets/CMakeLists.txt b/widgets/CMakeLists.txt
new file mode 100644
index 0000000..1b5ceb2
--- /dev/null
+++ b/widgets/CMakeLists.txt
@@ -0,0 +1,29 @@
+include(GenerateExportHeader)
+
+if(MGL_HAVE_FLTK)
+	mgl_add_lib(fltk fltk.cpp  image.cpp  image.h ../include/mgl2/fltk.h ../include/mgl2/Fl_MathGL.h)
+	target_include_directories(mgl-fltk SYSTEM PUBLIC ${FLTK_INCLUDE_DIR})
+	target_include_directories(mgl-fltk-static SYSTEM PUBLIC ${FLTK_INCLUDE_DIR})
+	target_link_libraries(mgl-fltk mgl ${FLTK_LIBRARIES})
+	target_link_libraries(mgl-fltk-static mgl-static ${FLTK_LIBRARIES})
+endif(MGL_HAVE_FLTK)
+
+if(MGL_HAVE_GLUT)
+	mgl_add_lib(glut glut.cpp ../include/mgl2/glut.h)
+	target_include_directories(mgl-glut SYSTEM PUBLIC ${GLUT_INCLUDE_DIR})
+	target_include_directories(mgl-glut-static SYSTEM PUBLIC ${GLUT_INCLUDE_DIR})
+	target_link_libraries(mgl-glut mgl ${GLUT_LIBRARIES} ${OPENGL_LIBRARIES})
+	target_link_libraries(mgl-glut-static mgl-static ${GLUT_LIBRARIES} ${OPENGL_LIBRARIES})
+endif(MGL_HAVE_GLUT)
+
+if(MGL_HAVE_WX)
+	mgl_add_lib(wx wx.cpp ../include/mgl2/wx.h)
+	include(${wxWidgets_USE_FILE})
+	target_link_libraries(mgl-wx mgl ${wxWidgets_LIBRARIES})
+	target_link_libraries(mgl-wx-static mgl-static ${wxWidgets_LIBRARIES})
+endif(MGL_HAVE_WX)
+
+add_subdirectory( qt4 )
+add_subdirectory( qt5 )
+
+mgl_po_src(fltk.cpp ../include/mgl2/fltk.h ../include/mgl2/Fl_MathGL.h glut.cpp ../include/mgl2/glut.h wx.cpp ../include/mgl2/wx.h qt.cpp ../include/mgl2/qt.h  ../include/mgl2/qmathgl.h)
diff --git a/widgets/fltk.cpp b/widgets/fltk.cpp
new file mode 100644
index 0000000..03e0632
--- /dev/null
+++ b/widgets/fltk.cpp
@@ -0,0 +1,1035 @@
+/***************************************************************************
+ * fltk.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <FL/Fl_Pixmap.H>
+#include <FL/fl_ask.H>
+#include <FL/Fl_Double_Window.H>
+#include <FL/fl_draw.H>
+#include <FL/Fl_Native_File_Chooser.H>
+//-----------------------------------------------------------------------------
+#include "mgl2/canvas_wnd.h"
+#include "mgl2/Fl_MathGL.h"
+#include <limits.h>
+//-----------------------------------------------------------------------------
+#define MGL_MAX_LINES	(INT_MAX-1000)
+//-----------------------------------------------------------------------------
+/// Class allows the window creation for displaying plot bitmap with the help of FLTK library
+/** NOTE!!! All frames are saved in memory. So animation with many frames require a lot memory and CPU time (for example, for mouse rotation).*/
+class mglCanvasFL : public mglCanvasWnd
+{
+public:
+using mglCanvasWnd::Window;
+	Fl_Window *Wnd;		///< Pointer to window
+	Fl_MGLView *mgl;	///< Pointer to MGL widget with buttons
+
+	mglCanvasFL();
+	virtual ~mglCanvasFL();
+
+	/// Create a window for plotting. Now implemeted only for GLUT.
+	void Window(int argc, char **argv, int (*draw)(mglBase *gr, void *p), const char *title,
+						void *par=NULL, void (*reload)(void *p)=NULL, bool maximize=false);
+	/// Switch on/off transparency (do not overwrite switches in user drawing function)
+	void ToggleAlpha();
+	/// Switch on/off lighting (do not overwrite switches in user drawing function)
+	void ToggleLight();
+	void ToggleRotate();	///< Switch on/off rotation by mouse
+	void ToggleZoom();		///< Switch on/off zooming by mouse
+	void ToggleNo();		///< Switch off all zooming and rotation
+	void Update();			///< Update picture by calling user drawing function
+	void Adjust();			///< Adjust size of bitmap to window size
+	void GotoFrame(int d);	///< Show arbitrary frame (use relative step)
+	void Animation();	///< Run animation (I'm too lasy to change it)
+};
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_ask_fltk(const wchar_t *quest, wchar_t *res)
+{
+	static char buf[1024];	*res=0;	// TODO
+#if FL_MINOR_VERSION>=3
+	fl_utf8fromwc(buf, 1024, quest, mgl_wcslen(quest)+1);
+	const char *str = fl_input("%s",buf,"");
+	if(str)	fl_utf8towc(str, strlen(str)+1, res, 1024);
+#else
+	wcstombs(buf,quest,mgl_wcslen(quest)+1);
+	const char *str = fl_input("%s",buf,"");
+	MGL_TO_WCS(str,wcscpy(res,str));
+#endif
+}
+//-----------------------------------------------------------------------------
+//
+//		class Fl_MathGL
+//
+//-----------------------------------------------------------------------------
+MGL_EXPORT const char *mgl_file_chooser(const char *mess, const char *filter, bool save)
+{
+	static Fl_Native_File_Chooser fnfc;
+	fnfc.title(mess);
+	fnfc.type(save ? Fl_Native_File_Chooser::BROWSE_SAVE_FILE : Fl_Native_File_Chooser::BROWSE_FILE);
+	fnfc.filter(filter);
+//	fnfc.directory("/var/tmp");           // default directory to use
+	fnfc.show();
+	return fnfc.filename();
+}
+MGL_EXPORT const char *mgl_dir_chooser(const char *mess, const char *path)
+{
+	static Fl_Native_File_Chooser fnfc;
+	fnfc.title(mess);
+	fnfc.type(Fl_Native_File_Chooser::BROWSE_DIRECTORY);
+	fnfc.directory(path);           // default directory to use
+	fnfc.show();
+	return fnfc.filename();
+}
+//-----------------------------------------------------------------------------
+Fl_MathGL::Fl_MathGL(int xx, int yy, int ww, int hh, const char *lbl) : Fl_Widget(xx,yy,ww,hh,lbl)
+{
+	gr = new mglCanvas;	use_pthr = true;
+	tet=phi=x1=y1=0;	x2=y2=1;	img = 0;
+	zoom = rotate = handle_keys = grid = false;
+	flag=x0=y0=xe=ye=0;	show_warn=true;
+	tet_val = phi_val = 0;
+	draw_par = 0;	draw_func = 0;	draw_cl = 0;
+	last_id = -1;	run = false;
+}
+//-----------------------------------------------------------------------------
+Fl_MathGL::~Fl_MathGL()	{	if(mgl_use_graph(gr,-1)<1)	mgl_delete_graph(gr);	}
+//-----------------------------------------------------------------------------
+void Fl_MathGL::stop(bool stop)	{	gr->AskStop(stop);	}
+//-----------------------------------------------------------------------------
+void mgl_fltk_event_func(void *)	{	Fl::awake();	}
+//-----------------------------------------------------------------------------
+void Fl_MathGL::set_graph(HMGL GR)
+{
+	mglCanvas *gg = dynamic_cast<mglCanvas *>(GR);
+	if(!gg)	return;
+	if(gr && mgl_use_graph(gr,-1)<1)	mgl_delete_graph(gr);
+	gr=gg;	mgl_use_graph(gg,1);
+	gr->SetEventFunc(mgl_fltk_event_func, NULL);
+}
+//-----------------------------------------------------------------------------
+void Fl_MathGL::draw()
+{
+	if(!img)	img = mgl_get_rgb(gr);
+	int ww=mgl_get_width(gr), hh=mgl_get_height(gr);
+	if(img)	fl_draw_image(img, x(), y(), ww, hh, 3);
+	if(grid)
+	{
+		char str[5]="0.0";
+		fl_color(192,192,192);
+		for(int i=1;i<10;i++)
+		{
+			str[2] = '0'+10-i;	fl_draw(str, x(), y()+i*hh/10);
+			fl_line(x(), y()+i*hh/10, x()+ww, y()+i*hh/10);
+			str[2] = '0'+i;	fl_draw(str, x()+i*ww/10, y()+hh);
+			fl_line(x()+i*ww/10, y(), x()+i*ww/10, y()+hh);
+		}
+		int d = (hh>ww?ww:hh)/100;
+		for(size_t i=0;i<gr->Act.size();i++)
+		{
+			const mglActivePos &p=gr->Act[i];
+			fl_rectf(x()+p.x-d/2, y()+p.y-d/2-1, d,d, fl_rgb_color(127,255,63));
+			fl_rect(x()+p.x-d/2, y()+p.y-d/2-1, d,d, FL_BLACK);
+		}
+		mgl_set_flag(gr,1,MGL_SHOW_POS);
+	}
+	else	mgl_set_flag(gr,0,MGL_SHOW_POS);
+}
+//-----------------------------------------------------------------------------
+inline void Fl_MathGL::draw_plot()	// drawing itself
+{
+	if(draw_func || draw_cl)
+	{
+		mgl_set_def_param(gr);		mgl_reset_frames(gr);
+		if(mgl_get_flag(gr,MGL_CLF_ON_UPD))	mgl_set_def_param(gr);
+		mgl_set_alpha(gr,flag&1);	mgl_set_light(gr,flag&2);
+		if(tet_val)	tet = tet_val->value();
+		if(phi_val)	phi = phi_val->value();
+		mgl_zoom(gr,x1,y1,x2,y2);	mgl_view(gr,-phi,-tet,0);
+		const std::string loc = setlocale(LC_NUMERIC, "C");
+		// use frames for quickly redrawing while adding/changing primitives
+		if(mgl_is_frames(gr))	mgl_new_frame(gr);
+
+		if(draw_func)	draw_func(gr, draw_par);
+		else	if(draw_cl)	{	mglGraph g(gr);	draw_cl->Draw(&g);	}
+
+		if(mgl_is_frames(gr))	mgl_end_frame(gr);
+		setlocale(LC_NUMERIC, loc.c_str());
+		const char *buf = mgl_get_mess(gr);
+		if(show_warn && *buf)	fl_message("%s",buf);
+		if(!prim.empty())	// manual primitives
+		{
+			const std::string loc = setlocale(LC_NUMERIC, "C");
+			mgl_subplot(gr,1,1,0,"#");
+			mgl_set_ranges(gr, -1,1, -1,1, -1,1);
+			mglParse pr;	pr.StartID(MGL_MAX_LINES);
+			mgl_parse_text(gr,pr.Self(),prim.c_str());
+			setlocale(LC_NUMERIC, loc.c_str());
+		}
+	}
+	else if(mgl_get_num_frame(gr)>0)
+	{
+		mgl_set_alpha(gr,flag&1);	mgl_set_light(gr,flag&2);
+		if(tet_val)	tet = tet_val->value();
+		if(phi_val)	phi = phi_val->value();
+		mgl_zoom(gr,x1,y1,x2,y2);	mgl_view(gr,-phi,-tet,0);
+		mgl_get_frame(gr,0);
+	}
+	mgl_finish(gr);	img = mgl_get_rgb(gr);
+	run = false;	Fl::awake();
+}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *draw_plot_thr(void *v)
+{	((Fl_MathGL*)v)->draw_plot();	return 0;	}
+//-----------------------------------------------------------------------------
+void Fl_MathGL::update()
+{
+	if(run)	return;
+//	Fl::lock();
+	run = true;
+#if MGL_HAVE_FL_COPY
+	top_window()->cursor(FL_CURSOR_WAIT);
+#endif
+#if MGL_HAVE_PTHR_WIDGET
+	if(use_pthr)
+	{
+		pthread_create(&thr,0,draw_plot_thr,this);
+		while(run)	Fl::wait();
+		pthread_join(thr,0);
+	}
+	else
+#endif
+		draw_plot();
+//	Fl::unlock();
+
+	if(mgl_get_width(gr)!=w() || mgl_get_height(gr)!=h())
+		size(mgl_get_width(gr), mgl_get_height(gr));
+	gr->AskStop(false);	redraw();
+#if MGL_HAVE_FL_COPY
+	top_window()->cursor(FL_CURSOR_DEFAULT);
+#endif
+	Fl::flush();
+}
+//-----------------------------------------------------------------------------
+void Fl_MathGL::resize(int xx, int yy, int ww, int hh)
+{	Fl_Widget::resize(xx,yy,ww,hh);	}
+//-----------------------------------------------------------------------------
+int Fl_MathGL::handle(int code)
+{
+	static bool busy=false;
+	static int last_pos=-1;
+	if(handle_keys && code==FL_KEYUP && Fl::event_button()!=FL_LEFT_MOUSE)
+	{
+		int key=Fl::event_key();
+		if(!strchr(" .,wasdrfx",key))	return 0;
+		if(key==' ')	{	update();	return 1;	}
+		if(key=='w')
+		{
+			tet += 10;
+			if(tet_val)	tet_val->value(tet);
+			update();	return 1;
+		}
+		if(key=='s')
+		{
+			tet -= 10;
+			if(tet_val)	tet_val->value(tet);
+			update();	return 1;
+		}
+		if(key=='a')
+		{
+			phi += 10;
+			if(phi_val)	phi_val->value(phi);
+			update();	return 1;
+		}
+		if(key=='d')
+		{
+			phi -= 10;
+			if(phi_val)	phi_val->value(phi);
+			update();	return 1;
+		}
+		if(key=='x')
+		{
+			mglCanvasFL *g=dynamic_cast<mglCanvasFL *>(gr);
+			if(g && g->mgl->FMGL==this)
+			{	g->Wnd->hide();	return 1;	}
+			else	return 0;
+			//				exit(0);
+		}
+		if(key==',')
+		{
+			mglCanvasFL *g=dynamic_cast<mglCanvasFL *>(gr);
+			if(g && g->mgl->FMGL==this)
+			{	g->PrevFrame();	return 1;	}
+			else	return 0;
+		}
+		if(key=='.')
+		{
+			mglCanvasFL *g=dynamic_cast<mglCanvasFL *>(gr);
+			if(g && g->mgl->FMGL==this)
+			{	g->NextFrame();	return 1;	}
+			else	return 0;
+		}
+		if(key=='r')
+		{	flag = (flag&2) + ((~(flag&1))&1);	update();	return 1;	}
+		if(key=='f')
+		{	flag = (flag&1) + ((~(flag&2))&2);	update();	return 1;	}
+	}
+	else if(code==FL_PUSH)
+	{
+		last_pos=-1;	xe=x0=Fl::event_x();	ye=y0=Fl::event_y();
+		if(popup && Fl::event_button()==FL_RIGHT_MOUSE)
+		{
+			const Fl_Menu_Item *m = popup->popup(Fl::event_x(), Fl::event_y(), 0, 0, 0);
+			if(m)	m->do_callback(wpar, vpar);
+		}
+		else if(!zoom && !rotate && Fl::event_button()==FL_LEFT_MOUSE)
+		{
+			int xx = x0-x(), yy = y0-y();
+			last_id = mgl_get_obj_id(gr,xx, yy);
+			if(last_id>=MGL_MAX_LINES)	last_id=-1;
+			mglCanvasWnd *g=dynamic_cast<mglCanvasWnd *>(gr);
+			if(g && g->ClickFunc)	g->ClickFunc(draw_par);
+			if(mgl_get_flag(gr,MGL_SHOW_POS))
+			{
+				mglPoint p = gr->CalcXYZ(xx, yy);
+				if(g)	g->LastMousePos = p;
+				char s[128];
+				snprintf(s,128,"x=%g, y=%g, z=%g",p.x,p.y,p.z);	s[127]=0;
+				draw();	fl_color(FL_BLACK);		fl_draw(s,40,70);
+			}
+			if(Fl::event_clicks())
+			{
+				int id = mgl_get_obj_id(gr,x0-x(), y0-y()) - MGL_MAX_LINES-1;
+				if(grid && id>=0)	// delete manual primitive
+				{
+					prim = (id>0?mgl_str_arg(prim, '\n', 0,id-1)+'\n':"") + mgl_str_arg(prim, '\n', id+1,INT_MAX);
+					update();
+				}
+				else if(draw_cl)	draw_cl->Click();
+				else	update();
+			}
+		}
+		return 1;
+	}
+	else if(code==FL_DRAG)
+	{
+		if(busy)	return 1;	// remove possible conflicts of too often events
+		busy = true;	xe=Fl::event_x();	ye=Fl::event_y();
+		mreal ff = 240./sqrt(mreal(w()*h()));
+		// handle primitives
+		int id = mgl_get_obj_id(gr,x0-x(), y0-y()) - MGL_MAX_LINES-1;
+		int ww=mgl_get_width(gr), hh=mgl_get_height(gr), d=(hh>ww?ww:hh)/100;
+		long pos = mgl_is_active(gr,x0-x(),y0-y(),d);
+		if(grid && pos<0)	pos=last_pos;
+		if(grid && pos>=0)
+		{
+//			Fl::lock();
+			last_pos=pos;
+			const mglActivePos &p = gr->Act[pos];
+			id = long(p.id)-MGL_MAX_LINES-1;
+			if(id<0)	return 0;
+			std::string line = mgl_str_arg(prim, '\n', id), res;
+			if(line.empty())	return 0;	// NOTE stupid check (never should be here)
+			std::vector<std::string> arg = mgl_str_args(line,' ');
+			// try "attract" mouse
+			for(size_t i=0;i<=10;i++)
+			{
+				int tt = i*(w()/10);	if(abs(xe-tt)<2*d)	xe = tt;
+				tt = i*(h()/10);	if(abs(ye-tt)<2*d)	ye = tt;
+			}
+			for(size_t i=0;i<gr->Act.size();i++)
+			{
+				const mglActivePos &q = gr->Act[i];
+				if(abs(xe-q.x)<2*d && abs(ye-q.y)<2*d)	{	xe=q.x;	ye=q.y;	}
+			}
+			// now move point
+			float dx = 2*(xe-x0)/float(w()), dy = 2*(y0-ye)/float(h());
+			float xx=atof(arg[1].c_str()), yy=atof(arg[2].c_str());
+			if(p.n==0)	{	arg[1]=mgl_str_num(xx+dx);	arg[2]=mgl_str_num(yy+dy);	}
+			else if(arg[0]=="rect")
+			{
+				float x_=atof(arg[3].c_str()), y_=atof(arg[4].c_str());
+				if(p.n==1)	{	xx+=dx;	y_+=dy;	}
+				if(p.n==2)	{	x_+=dx;	yy+=dy;	}
+				if(p.n==3)	{	x_+=dx;	y_+=dy;	}
+				arg[1]=mgl_str_num(xx);	arg[2]=mgl_str_num(yy);
+				arg[3]=mgl_str_num(x_);	arg[4]=mgl_str_num(y_);
+			}
+			else if(p.n==1)
+			{
+				float xx=atof(arg[3].c_str()), yy=atof(arg[4].c_str());
+				arg[3]=mgl_str_num(xx+dx);	arg[4]=mgl_str_num(yy+dy);
+			}
+			else if(arg[0]=="rhomb" || arg[0]=="ellipse")
+			{
+				float x_=atof(arg[3].c_str())-xx, y_=atof(arg[4].c_str())-yy;
+				float r_=atof(arg[5].c_str()), dr=0;
+				if(x_*x_+y_*y_>0)
+				{	dr = (dx*x_+dy*y_)/(x_*x_+y_*y_);	dr = hypot(dx-dr*x_,dy-dr*y_);	}
+				else	dr = hypot(dx,dy);
+				arg[5]=mgl_str_num(r_+dr);
+			}
+			else if(arg[0]=="arc")
+			{
+				float x_=atof(arg[3].c_str())-xx, y_=atof(arg[4].c_str())-yy;
+				float a_=atof(arg[5].c_str());
+				double c=cos(M_PI*a_/180), s=sin(M_PI*a_/180);
+				double a = atan2(x_,y_) - atan2(x_*c-y_*s+dx,x_*s+y_*c+dy);
+				arg[5]=mgl_str_num(a*180/M_PI);
+			}
+			else if(p.n==2)
+			{
+				float xx=atof(arg[5].c_str()), yy=atof(arg[6].c_str());
+				arg[5]=mgl_str_num(xx+dx);	arg[6]=mgl_str_num(yy+dy);
+			}
+			else if(p.n==3)
+			{
+				float xx=atof(arg[7].c_str()), yy=atof(arg[8].c_str());
+				if(arg[0]=="curve")	{	dx*=-1;	dy*=-1;	}
+				arg[7]=mgl_str_num(xx+dx);	arg[8]=mgl_str_num(yy+dy);
+			}
+			res = arg[0];	for(size_t i=1;i<arg.size();i++)	res += ' '+arg[i];
+			prim = (id>0?mgl_str_arg(prim, '\n', 0,id-1)+'\n':"") + res+'\n' + mgl_str_arg(prim, '\n', id+1,INT_MAX);
+//			Fl::unlock();
+			x0 = xe;	y0 = ye;	update();
+		}
+		else if(grid && id>=0)
+		{
+//			Fl::lock();
+			std::string line = mgl_str_arg(prim, '\n', id), res;
+			if(line.empty())	return 0;	// NOTE stupid check (never should be here)
+			std::vector<std::string> arg = mgl_str_args(line,' ');
+
+			float dx = 2*(xe-x0)/float(w()), dy = 2*(y0-ye)/float(h());
+			float x1=atof(arg[1].c_str()), y1=atof(arg[2].c_str());
+			arg[1] = mgl_str_num(x1+dx);	arg[2] = mgl_str_num(y1+dy);
+			if(arg[0]=="curve")
+			{
+				float x2=atof(arg[5].c_str()), y2=atof(arg[6].c_str());
+				arg[5]=mgl_str_num(x2+dx);	arg[6]=mgl_str_num(y2+dy);
+			}
+			else if(arg[0]!="ball")
+			{
+				float x2=atof(mgl_str_arg(line,' ',3).c_str()), y2=atof(mgl_str_arg(line,' ',4).c_str());
+				arg[3]=mgl_str_num(x2+dx);	arg[4]=mgl_str_num(y2+dy);
+			}
+			res = arg[0];	for(size_t i=1;i<arg.size();i++)	res += ' '+arg[i];
+			prim = (id>0?mgl_str_arg(prim, '\n', 0,id-1)+'\n':"") + res+'\n' + mgl_str_arg(prim, '\n', id+1,INT_MAX);
+//			Fl::unlock();
+			x0 = xe;	y0 = ye;	update();
+		}
+		else if(rotate)
+		{
+			phi += (x0-xe)*ff;
+			tet += (y0-ye)*ff;
+			if(phi>180)		phi-=360;
+			if(phi<-180)	phi+=360;
+			if(tet>180)		tet-=360;
+			if(tet<-180)	tet+=360;
+			if(tet_val)	tet_val->value(tet);
+			if(phi_val)	phi_val->value(phi);
+			x0 = xe;	y0 = ye;	update();
+		}
+		busy = false;	redraw();	return 1;
+	}
+	else if(code==FL_RELEASE)
+	{
+		last_pos=-1;
+		if(zoom)
+		{
+			int w1=w(),h1=h();
+			mreal _x1,_x2,_y1,_y2;
+			_x1 = x1+(x2-x1)*(x0-x())/mreal(w1);
+			_y1 = y2-(y2-y1)*(ye-y())/mreal(h1);
+			_x2 = x1+(x2-x1)*(xe-x())/mreal(w1);
+			_y2 = y2-(y2-y1)*(y0-y())/mreal(h1);
+			x1=_x1;		x2=_x2;		y1=_y1;		y2=_y2;
+			if(x1>x2)	{	_x1=x1;	x1=x2;	x2=_x1;	}
+			if(y1>y2)	{	_x1=y1;	y1=y2;	y2=_x1;	}
+			update();
+		}
+		else if(rotate)
+		{
+			if(tet_val)	tet_val->value(tet);
+			if(phi_val)	phi_val->value(phi);
+		}
+		redraw();	return 1;
+	}
+	return 0;
+}
+//-----------------------------------------------------------------------------
+//
+//		class Fl_MGLView
+//
+//-----------------------------------------------------------------------------
+void Fl_MGLView::toggle(int &val, Fl_Button *b, const char *txt)
+{
+	val = 1-val;	b->value(val);
+	if(menu && txt && *txt)
+	{
+		Fl_Menu_Item *m = (Fl_Menu_Item *)menu->find_item(_(txt));
+		if(m && val)	m->set();
+		if(m && !val)	m->clear();
+	}
+	update();
+}
+//-----------------------------------------------------------------------------
+void Fl_MGLView::setoff(int &val, Fl_Button *b, const char *txt)
+{
+	val = 0;	b->value(val);
+	if(menu && txt && *txt)
+	{
+		Fl_Menu_Item *m = (Fl_Menu_Item *)menu->find_item(_(txt));
+		if(m && val)	m->set();
+		if(m && !val)	m->clear();
+	}
+	//update();
+}
+//-----------------------------------------------------------------------------
+void Fl_MGLView::exec_pause()
+{
+#if MGL_HAVE_PTHR_WIDGET
+	pthread_mutex_t *mutex=0;
+	mglCanvasWnd *g=dynamic_cast<mglCanvasWnd *>(FMGL->gr);
+	if(g && g->mutex)	mutex = g->mutex;
+	else
+	{
+		mglDraw *d=FMGL->get_class();
+		if(d)	mutex = &(d->mutex);
+	}
+	if(mutex)
+	{
+		pthread_mutex_trylock(mutex);
+		if(!pauseC)	pthread_mutex_unlock(mutex);
+	}
+#endif
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_pause_cb(Fl_Widget*, void* v)
+{	if(v)	((Fl_MGLView*)v)->toggle_pause();	}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_grid_cb(Fl_Widget*, void* v)
+{	if(v)	((Fl_MGLView*)v)->toggle_grid();	}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_alpha_cb(Fl_Widget*, void* v)
+{	if(v)	((Fl_MGLView*)v)->toggle_alpha();	}
+void mglCanvasFL::ToggleAlpha()	{	mgl->toggle_alpha();	}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_light_cb(Fl_Widget*, void* v)
+{	if(v)	((Fl_MGLView*)v)->toggle_light();	}
+void mglCanvasFL::ToggleLight()	{	mgl->toggle_light();	}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_norm_cb(Fl_Widget*, void* v)
+{
+	Fl_MGLView *e = (Fl_MGLView*)v;	if(!e)	return;
+	e->setoff_rotate();			e->setoff_zoom();
+	e->FMGL->tet_val->value(0);	e->FMGL->phi_val->value(0);
+	e->FMGL->set_zoom(0,0,1,1);
+	e->update();
+}
+void mglCanvasFL::ToggleNo()	{	mgl_norm_cb(0,mgl);	}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_zoom_cb(Fl_Widget*, void* v)
+{
+	Fl_MGLView *e = (Fl_MGLView*)v;	if(!e)	return;
+	e->setoff_rotate();	e->toggle_zoom();
+}
+void mglCanvasFL::ToggleZoom()	{	mgl_zoom_cb(0,mgl);	}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_rotate_cb(Fl_Widget*, void* v)
+{
+	Fl_MGLView *e = (Fl_MGLView*)v;	if(!e)	return;
+	e->setoff_zoom();	e->toggle_rotate();
+}
+void mglCanvasFL::ToggleRotate()	{	mgl_rotate_cb(0,mgl);	}
+//-----------------------------------------------------------------------------
+void Fl_MGLView::update()
+{
+	FMGL->set_state(zoom_bt->value(), rotate_bt->value(), grid_bt->value());
+	FMGL->set_flag(alpha + 2*light);
+	FMGL->update();
+}
+void MGL_NO_EXPORT mgl_draw_cb(Fl_Widget*, void* v)
+{	if(v)	((Fl_MGLView*)v)->update();	}
+void mglCanvasFL::Update()		{	mgl->update();	Wnd->show();	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT const char *mgl_save_name(const char *ext)
+{
+	static std::string fname;
+	fname = mgl_file_chooser(_("Save File As?"), ext, true);
+	if(fname.empty())	return NULL;
+	if(fname.find(ext+1)==std::string::npos)	fname += ext+1;
+	return fname.c_str();
+}
+#define _FGR_	((Fl_MGLView*)v)->FMGL->get_graph()
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_export_png_cb(Fl_Widget*, void* v)
+{
+	const char *fname = mgl_save_name("*.png");
+	if(fname)	mgl_write_png(_FGR_,fname,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_export_bps_cb(Fl_Widget*, void* v)
+{
+	const char *fname = mgl_save_name("*.eps");
+	if(fname)	mgl_write_bps(_FGR_,fname,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_export_pngn_cb(Fl_Widget*, void* v)
+{
+	const char *fname = mgl_save_name("*.png");
+	if(fname)	mgl_write_png_solid(_FGR_,fname,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_export_jpeg_cb(Fl_Widget*, void* v)
+{
+	const char *fname = mgl_save_name("*.jpg");
+	if(fname)	mgl_write_jpg(_FGR_,fname,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_export_svg_cb(Fl_Widget*, void* v)
+{
+	const char *fname = mgl_save_name("*.svg");
+	if(fname)	mgl_write_svg(_FGR_,fname,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_export_eps_cb(Fl_Widget*, void* v)
+{
+	const char *fname = mgl_save_name("*.eps");
+	if(fname)	mgl_write_eps(_FGR_,fname,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_export_gif_cb(Fl_Widget*, void* v)
+{
+	const char *fname = mgl_save_name("*.gif");
+	if(fname)	mgl_write_gif(_FGR_,fname,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_export_bmp_cb(Fl_Widget*, void* v)
+{
+	const char *fname = mgl_save_name("*.bmp");
+	if(fname)	mgl_write_bmp(_FGR_,fname,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_export_prc_cb(Fl_Widget*, void* v)
+{
+	const char *fname = mgl_save_name("*.prc");
+	if(fname)	mgl_write_prc(_FGR_,fname,0,1);
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_export_tex_cb(Fl_Widget*, void* v)
+{
+	const char *fname = mgl_save_name("*.tex");
+	if(fname)	mgl_write_tex(_FGR_,fname,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_export_obj_cb(Fl_Widget*, void* v)
+{
+	const char *fname = mgl_save_name("*.obj");
+	if(fname)	mgl_write_obj(_FGR_,fname,0,1);
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_export_off_cb(Fl_Widget*, void* v)
+{
+	const char *fname = mgl_save_name("*.off");
+	if(fname)	mgl_write_off(_FGR_,fname,0,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_export_stl_cb(Fl_Widget*, void* v)
+{
+	const char *fname = mgl_save_name("*.stl");
+	if(fname)	mgl_write_stl(_FGR_,fname,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_export_xyz_cb(Fl_Widget*, void* v)
+{
+	const char *fname = mgl_save_name("*.xyz");
+	if(fname)	mgl_write_xyz(_FGR_,fname,0);
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_su_cb(Fl_Widget*, void* v)
+{
+	Fl_MGLView *e = (Fl_MGLView*)v;	if(!e)	return;
+	mreal x1,x2,y1,y2,d;
+	e->FMGL->get_zoom(&x1,&y1,&x2,&y2);
+	d = (y2-y1)/3;	y1 -= d;	y2 -= d;
+	e->FMGL->set_zoom(x1,y1,x2,y2);
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_sd_cb(Fl_Widget*, void* v)
+{
+	Fl_MGLView *e = (Fl_MGLView*)v;	if(!e)	return;
+	mreal x1,x2,y1,y2,d;
+	e->FMGL->get_zoom(&x1,&y1,&x2,&y2);
+	d = (y2-y1)/3;	y1 += d;	y2 += d;
+	e->FMGL->set_zoom(x1,y1,x2,y2);
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_sr_cb(Fl_Widget*, void* v)
+{
+	Fl_MGLView *e = (Fl_MGLView*)v;	if(!e)	return;
+	mreal x1,x2,y1,y2,d;
+	e->FMGL->get_zoom(&x1,&y1,&x2,&y2);
+	d = (x2-x1)/3;	x1 -= d;	x2 -= d;
+	e->FMGL->set_zoom(x1,y1,x2,y2);
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_sl_cb(Fl_Widget*, void* v)
+{
+	Fl_MGLView *e = (Fl_MGLView*)v;	if(!e)	return;
+	mreal x1,x2,y1,y2,d;
+	e->FMGL->get_zoom(&x1,&y1,&x2,&y2);
+	d = (x2-x1)/3;	x1 += d;	x2 += d;
+	e->FMGL->set_zoom(x1,y1,x2,y2);
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_sz_cb(Fl_Widget*, void* v)
+{
+	Fl_MGLView *e = (Fl_MGLView*)v;	if(!e)	return;
+	mreal x1,x2,y1,y2,d;
+	e->FMGL->get_zoom(&x1,&y1,&x2,&y2);
+	d = (y2-y1)/4;	y1 += d;	y2 -= d;
+	d = (x2-x1)/4;	x1 += d;	x2 -= d;
+	e->FMGL->set_zoom(x1,y1,x2,y2);
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_so_cb(Fl_Widget*, void* v)
+{
+	Fl_MGLView *e = (Fl_MGLView*)v;	if(!e)	return;
+	mreal x1,x2,y1,y2,d;
+	e->FMGL->get_zoom(&x1,&y1,&x2,&y2);
+	d = (y2-y1)/2;	y1 -= d;	y2 += d;
+	d = (x2-x1)/2;	x1 -= d;	x2 += d;
+	e->FMGL->set_zoom(x1,y1,x2,y2);
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_adjust_cb(Fl_Widget*, void*v)
+{	Fl_MGLView *e = (Fl_MGLView*)v;	if(e)	e->adjust();	}
+void mglCanvasFL::Adjust()	{	mgl_adjust_cb(0,mgl);	}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_oncemore_cb(Fl_Widget*, void*v)
+{	Fl_MGLView *e = (Fl_MGLView*)v;	if(e && e->reload)	e->reload(e->par);	}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_quit_cb(Fl_Widget*, void*)	{	Fl::first_window()->hide();	}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_snext_cb(Fl_Widget*, void* v)
+{	Fl_MGLView *e = (Fl_MGLView*)v;	if(e && e->next)	e->next(e->par);	}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_sprev_cb(Fl_Widget*, void* v)
+{	Fl_MGLView *e = (Fl_MGLView*)v;	if(e && e->prev)	e->prev(e->par);	}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_time_cb(void *v)
+{
+	Fl_MGLView *e = (Fl_MGLView*)v;
+	if(!e || !e->is_sshow() || !e->next || !e->delay)	return;
+	e->next(e->par);
+	Fl::repeat_timeout(e->delay(e->par), mgl_time_cb, v);
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_sshow_cb(Fl_Widget *, void *v)
+{
+	Fl_MGLView *e = (Fl_MGLView*)v;
+	if(!e || !e->delay || !e->next)	return;
+	e->toggle_sshow();
+	if(e->is_sshow())	Fl::add_timeout(e->delay(e->par), mgl_time_cb, v);
+}
+void mglCanvasFL::Animation()	{	mgl_sshow_cb(0,mgl);	}
+void MGL_LOCAL_CONST mgl_no_cb(Fl_Widget *, void *)	{}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_stop_cb(Fl_Widget*, void* v)
+{
+	Fl_MGLView *e = (Fl_MGLView*)v;
+	if(e)	e->FMGL->stop();
+}
+//-----------------------------------------------------------------------------
+void MGL_NO_EXPORT mgl_fl_next(void *v)	{	((mglCanvasWnd*)v)->NextFrame();	}	///< Callback function for next frame
+void MGL_NO_EXPORT mgl_fl_prev(void *v)	{	((mglCanvasWnd*)v)->PrevFrame();	}	///< Callback function for prev frame
+void MGL_NO_EXPORT mgl_fl_reload(void *v)	{	((mglCanvasWnd*)v)->ReLoad();	}		///< Callback function for reloading
+mreal MGL_LOCAL_PURE mgl_fl_delay(void *v)	{	return ((mglCanvasWnd*)v)->GetDelay();	}	///< Callback function for delay
+//-----------------------------------------------------------------------------
+void copy_coor_cb(Fl_Widget *,void *v)
+{
+	HMGL gr = ((Fl_MGLView*)v)->get_graph();
+	mreal x,y,z;	mgl_get_last_mouse_pos(gr,&x,&y,&z);
+	static char buf[256];
+	snprintf(buf,255,_("click at %g, %g, %g"),x,y,z);
+	Fl::copy(buf,strlen(buf),1);
+}
+//-----------------------------------------------------------------------------
+#if MGL_HAVE_FL_COPY
+#include <FL/Fl_Copy_Surface.H>
+void mgl_copyimg_cb(Fl_Widget *,void *v)
+{
+	Fl_MathGL *g = ((Fl_MGLView*)v)->FMGL;
+	Fl_Copy_Surface *copy_surf = new Fl_Copy_Surface(g->w(), g->h());	// create an Fl_Copy_Surface object
+	copy_surf->set_current();							// direct graphics requests to the clipboard
+	fl_color(FL_WHITE);	fl_rectf(0, 0, g->w(), g->h());	// draw a white background
+	copy_surf->draw(g);									// draw the g widget in the clipboard
+	delete copy_surf;									// after this, the clipboard is loaded
+	Fl_Display_Device::display_device()->set_current();	// direct graphics requests back to the display
+}
+#else
+void mgl_copyimg_cb(Fl_Widget *,void *v)	{}
+#endif
+//-----------------------------------------------------------------------------
+Fl_Menu_Item pop_graph[] = {
+	{ _("Export as ..."), 0, mgl_no_cb, 0, FL_SUBMENU},
+#if MGL_HAVE_PNG
+		{ "PNG",	0, mgl_export_png_cb},
+		{ "PNG (solid)",	0, mgl_export_pngn_cb},
+#endif
+#if MGL_HAVE_JPEG
+		{ "JPEG",	0, mgl_export_jpeg_cb},
+#endif
+#if MGL_HAVE_GIF
+		{ "GIF",	0, mgl_export_gif_cb},
+#endif
+		{ "BMP",	0, mgl_export_bmp_cb},
+		{ "SVG",	0, mgl_export_svg_cb},
+		{ "vector EPS",	0, mgl_export_eps_cb},
+		{ "bitmap EPS",	0, mgl_export_bps_cb},
+		{ "TeX",	0, mgl_export_tex_cb,0, FL_MENU_DIVIDER},
+		{ "OBJ",	0, mgl_export_obj_cb},
+		{ "PRC",	0, mgl_export_prc_cb},
+		{ "OFF",	0, mgl_export_off_cb},
+		{ "STL",	0, mgl_export_stl_cb},
+		{ "XYZ",	0, mgl_export_xyz_cb},
+		{0},
+	{ _("Copy graphics"),	0, mgl_copyimg_cb, 0, FL_MENU_INACTIVE|FL_MENU_DIVIDER},
+	{ _("Normal view"),	0, mgl_norm_cb},
+	{ _("Redraw plot"),	0, mgl_draw_cb},
+	{ _("Adjust size"),	0, mgl_adjust_cb},
+	{ _("Reload data"),	0, mgl_oncemore_cb},
+	{0}
+};
+//-----------------------------------------------------------------------------
+#include "image.h"
+#include "xpm/wire.xpm"
+Fl_MGLView::Fl_MGLView(int xx, int yy, int ww, int hh, const char *lbl) : Fl_Window(xx,yy,ww,hh,lbl)
+{
+	Fl_Button *o;
+	grid = alpha = light = sshow = pauseC = rotate = zoom = 0;
+	menu = NULL;	next = prev = reload = NULL;	delay = NULL;
+
+	Fl_Group *g = new Fl_Group(0,0,480,30);
+	alpha_bt = new Fl_Button(0, 1, 25, 25);	alpha_bt->type(FL_TOGGLE_BUTTON);
+	alpha_bt->image(img_alpha);	alpha_bt->callback(mgl_alpha_cb,this);
+	alpha_bt->tooltip(_("Switch on/off transparency in the picture"));
+	light_bt = new Fl_Button(25, 1, 25, 25);	light_bt->type(FL_TOGGLE_BUTTON);
+	light_bt->image(img_light);	light_bt->callback(mgl_light_cb,this);
+	light_bt->tooltip(_("Switch on/off lightning in the picture"));
+	grid_bt = new Fl_Button(50, 1, 25, 25);	grid_bt->type(FL_TOGGLE_BUTTON);
+	grid_bt->image(new Fl_Pixmap(wire_xpm));	grid_bt->callback(mgl_grid_cb,this);
+	grid_bt->tooltip(_("Switch on/off grid drawing"));
+
+	rotate_bt = new Fl_Button(80, 1, 25, 25);rotate_bt->type(FL_TOGGLE_BUTTON);
+	rotate_bt->image(img_move);	rotate_bt->callback(mgl_rotate_cb,this);
+	rotate_bt->tooltip(_("Rotate picture by holding left mouse button"));
+	zoom_bt = new Fl_Button(105, 1, 25, 25);	zoom_bt->type(FL_TOGGLE_BUTTON);
+	zoom_bt->image(img_zoomIn);	zoom_bt->callback(mgl_zoom_cb,this);
+	zoom_bt->tooltip(_("Zoom in selected region of the picture"));
+	o = new Fl_Button(130, 1, 25, 25);		o->tooltip(_("Restore default graphics rotation, zoom and perspective"));
+	o->image(img_orig);	o->callback(mgl_norm_cb,this);
+
+	o = new Fl_Button(160, 1, 25, 25);	o->tooltip(_("Refresh the picture"));
+	o->image(img_update);	o->callback(mgl_draw_cb,this);
+	o = new Fl_Button(185, 1, 25, 25);	o->tooltip(_("Stop drawing"));
+	o->image(img_stop);	o->callback(mgl_stop_cb,this);
+	o = new Fl_Button(210, 1, 25, 25);	o->tooltip(_("Adjust picture size to fill drawing area"));
+	o->image(img_adjust);	o->callback(mgl_adjust_cb,this);
+	o = new Fl_Button(235, 1, 25, 25);	o->tooltip(_("Reload data and refresh the picture"));
+	o->image(img_reload);	o->callback(mgl_oncemore_cb,this);
+	o = new Fl_Button(265, 1, 25, 25);	o->tooltip(_("Copy image to clipboard"));
+	o->image(img_copy);	o->callback(mgl_copyimg_cb,this);
+
+	Fl_Counter *tet, *phi;
+	tet = new Fl_Counter(295, 1, 90, 25, 0);	tet->callback(mgl_draw_cb,this);
+	phi = new Fl_Counter(390, 1, 90, 25, 0);	phi->callback(mgl_draw_cb,this);
+	tet->lstep(10);	tet->step(1);	tet->range(-180,180);
+	tet->tooltip(_("Theta angle (tilt z-axis)"));
+	phi->lstep(10);	phi->step(1);	phi->range(-180,180);
+	phi->tooltip(_("Phi angle (rotate in x*y plane)"));
+	g->end();	g->resizable(0);
+
+	g = new Fl_Group(0,0,30,285);
+	o = new Fl_Button(1, 30, 25, 25);		o->tooltip(_("Shift the picture up"));
+	o->image(img_goU);		o->callback(mgl_su_cb,this);
+	o = new Fl_Button(1, 55, 25, 25);		o->tooltip(_("Shift the picture left"));
+	o->image(img_goL);	o->callback(mgl_sl_cb,this);
+	o = new Fl_Button(1, 80, 25, 25);		o->tooltip(_("Zoom in the picture"));
+	o->image(img_plus);	o->callback(mgl_sz_cb,this);
+	o = new Fl_Button(1, 105, 25, 25);		o->tooltip(_("Zoom out the picture"));
+	o->image(img_minus);	o->callback(mgl_so_cb,this);
+	o = new Fl_Button(1, 130, 25, 25);		o->tooltip(_("Shift the picture right"));
+	o->image(img_goR);	o->callback(mgl_sr_cb,this);
+	o = new Fl_Button(1, 155, 25, 25);		o->tooltip(_("Shift the picture down"));
+	o->image(img_goD);	o->callback(mgl_sd_cb,this);
+
+	o = new Fl_Button(1, 185, 25, 25);		o->tooltip(_("Show previous frame in slideshow"));
+	o->image(img_prev);	o->callback(mgl_sprev_cb,this);
+	anim_bt = new Fl_Button(1, 210, 25, 25);	anim_bt->type(FL_TOGGLE_BUTTON);
+	anim_bt->image(img_play);	anim_bt->callback(mgl_sshow_cb,this);
+	anim_bt->tooltip(_("Run/Stop slideshow (graphics animation)"));
+	o = new Fl_Button(1, 235, 25, 25);		o->tooltip(_("Show next frame in slideshow"));
+	o->image(img_next);	o->callback(mgl_snext_cb,this);
+#if MGL_HAVE_PTHR_WIDGET
+	pause_bt = new Fl_Button(1, 260, 25, 25);	pause_bt->type(FL_TOGGLE_BUTTON);
+	pause_bt->image(img_pause);	pause_bt->callback(mgl_pause_cb,this);
+	pause_bt->tooltip(_("Pause on/off external calculations"));
+#endif
+	g->end();	g->resizable(0);
+
+	scroll = new Fl_Scroll(30, 30, ww-30, hh-30);
+	FMGL = new Fl_MathGL(30, 30, 800, 600);
+	FMGL->tet_val = tet;
+	FMGL->phi_val = phi;
+	FMGL->set_popup(pop_graph,FMGL,this);
+	scroll->end();	resizable(scroll);	end();
+}
+Fl_MGLView::~Fl_MGLView()	{}
+//-----------------------------------------------------------------------------
+//
+//		class mglCanvasFL
+//
+//-----------------------------------------------------------------------------
+mglCanvasFL::mglCanvasFL() : mglCanvasWnd()	{	Wnd=0;	}
+mglCanvasFL::~mglCanvasFL()		{	if(Wnd)	{	mgl->FMGL->gr=0;	delete Wnd;	}	}
+//-----------------------------------------------------------------------------
+void mglCanvasFL::GotoFrame(int d)
+{
+	int f = GetCurFig()+d;
+	if(f>=GetNumFig())	f = 0;
+	if(f<0)	f = GetNumFig()-1;
+	if(GetNumFig()>0 && d)	{	SetCurFig(f);	mgl->FMGL->redraw();	}
+}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_makemenu_fltk(Fl_Menu_ *m, Fl_MGLView *w)
+{
+	m->add(_("Graphics/Alpha"), "^t", mgl_alpha_cb, w, FL_MENU_TOGGLE);
+	m->add(_("Graphics/Light"), "^l", mgl_light_cb, w, FL_MENU_TOGGLE);
+	m->add(_("Graphics/Grid"), "^g", mgl_grid_cb, w, FL_MENU_TOGGLE|FL_MENU_DIVIDER);
+
+	m->add(_("Graphics/Restore"), "^ ", mgl_norm_cb, w);
+	m->add(_("Graphics/Redraw"), FL_F+5, mgl_draw_cb, w);
+	m->add(_("Graphics/Adjust size"), FL_F+6, mgl_adjust_cb, w);
+	m->add(_("Graphics/Reload data"), FL_F+9, mgl_oncemore_cb, w);
+	m->add(_("Graphics/Stop"), FL_F+7, mgl_stop_cb, w);
+	m->add(_("Graphics/Copy graphics"), "+^c", mgl_copyimg_cb, w);
+	m->add(_("Graphics/Copy click coor."), 0, copy_coor_cb, w);
+	m->add(_("Graphics/Pause calc"), "^t", mgl_pause_cb, w, FL_MENU_TOGGLE);
+
+#if MGL_HAVE_PNG
+	m->add(_("Graphics/Export/as PNG"), "#p", mgl_export_png_cb, w);
+	m->add(_("Graphics/Export/as solid PNG"), "#f", mgl_export_pngn_cb, w);
+#endif
+#if MGL_HAVE_JPEG
+	m->add(_("Graphics/Export/as JPEG"), "#j", mgl_export_jpeg_cb, w);
+#endif
+#if MGL_HAVE_GIF
+	m->add(_("Graphics/Export/as GIF"), "#g", mgl_export_gif_cb, w);
+#endif
+	m->add(_("Graphics/Export/as BMP"), 0, mgl_export_bmp_cb, w);
+	m->add(_("Graphics/Export/as SVG"), "#s", mgl_export_svg_cb, w);
+	m->add(_("Graphics/Export/as vector EPS"), "#e", mgl_export_eps_cb, w);
+	m->add(_("Graphics/Export/as bitmap EPS"), 0, mgl_export_bps_cb, w);
+	m->add(_("Graphics/Export/as TeX"), "#l", mgl_export_tex_cb, w, FL_MENU_DIVIDER);
+	m->add(_("Graphics/Export/as PRC"), "#d", mgl_export_prc_cb, w);
+	m->add(_("Graphics/Export/as OBJ"), "#o", mgl_export_obj_cb, w);
+	m->add(_("Graphics/Export/as OFF"), 0, mgl_export_off_cb, w);
+	m->add(_("Graphics/Export/as STL"), 0, mgl_export_stl_cb, w);
+	m->add(_("Graphics/Export/as XYZ"), 0, mgl_export_xyz_cb, w);
+
+	m->add(_("Graphics/Animation/Slideshow"), FL_CTRL+FL_F+5, mgl_sshow_cb, w, FL_MENU_TOGGLE);
+	m->add(_("Graphics/Animation/Next frame"), "#<", mgl_snext_cb, w);
+	m->add(_("Graphics/Animation/Prev frame"), "#>", mgl_sprev_cb, w);
+
+	m->add(_("Graphics/Transform/Move left"), FL_ALT+FL_Left, mgl_sl_cb, w);
+	m->add(_("Graphics/Transform/Move up"), FL_ALT+FL_Up, mgl_su_cb, w);
+	m->add(_("Graphics/Transform/Zoom in"), "#=", mgl_sz_cb, w);
+	m->add(_("Graphics/Transform/Zoom out"), "#-", mgl_so_cb, w);
+	m->add(_("Graphics/Transform/Move down"), FL_ALT+FL_Down, mgl_sd_cb, w);
+	m->add(_("Graphics/Transform/Move right"), FL_ALT+FL_Right, mgl_sr_cb, w);
+}
+//-----------------------------------------------------------------------------
+void mglCanvasFL::Window(int argc, char **argv, int (*draw)(mglBase *gr, void *p), const char *title, void *par, void (*reload)(void *p), bool maximize)
+{
+	static bool first=true;
+	if(first)	{	Fl::lock();	first=false;	}
+
+	SetDrawFunc(draw, par, reload);
+	if(Wnd)	{	Wnd->label(title);	Wnd->show();	return;	}
+
+	Wnd = new Fl_Double_Window(830,660,title);
+	mgl = new Fl_MGLView(0,30,830,630);		mgl->par = this;
+	mgl->menu = new Fl_Menu_Bar(0, 0, 830, 30);
+	mgl_makemenu_fltk(mgl->menu, mgl);
+
+	mgl->next = mgl_fl_next;	mgl->reload = mgl_fl_reload;
+	mgl->prev = mgl_fl_prev;	mgl->delay= mgl_fl_delay;
+	mgl->FMGL->set_graph(this);
+	mgl->FMGL->set_draw(draw, par);
+
+	Wnd->end();
+	Wnd->resizable(mgl);
+
+	if(maximize)
+	{
+		int x,y,w,h;
+		Fl::screen_xywh(x,y,w,h);
+		Wnd->resize(x,y,w,h);
+		Adjust();
+	}
+
+	static char ctmp[1];	ctmp[0]=0;
+	static char *tmp[1];	tmp[0]=ctmp;
+	Wnd->show(argv ? argc:0, argv ? argv:tmp);
+}
+//-----------------------------------------------------------------------------
+HMGL MGL_EXPORT mgl_create_graph_fltk(int (*draw)(HMGL gr, void *p), const char *title, void *par, void (*load)(void *p))
+{
+	mglCanvasFL *g = new mglCanvasFL;
+	g->Window(0,0,draw,title,par,load);
+	g->mgl->FMGL->set_handle_key(true);
+	return g;
+}
+void* mgl_fltk_widget(HMGL gr)
+{
+	mglCanvasFL *g = dynamic_cast<mglCanvasFL *>(gr);
+	return g?g->mgl:NULL;
+}
+int MGL_EXPORT mgl_fltk_run()		{	return Fl::run();	}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_create_graph_fltk_(const char *title, int l)
+{
+	char *s = new char[l+1];	memcpy(s,title,l);	s[l]=0;
+	uintptr_t t = uintptr_t(mgl_create_graph_fltk(0,s,0,0));
+	delete []s;	return t;
+}
+int MGL_EXPORT mgl_fltk_run_()	{	return mgl_fltk_run();	}
+//-----------------------------------------------------------------------------
+MGL_NO_EXPORT void *mgl_fltk_tmp(void *)
+{	mgl_fltk_run();	return 0;	}
+//-----------------------------------------------------------------------------
+int MGL_EXPORT mgl_fltk_thr()		// NOTE: Qt couldn't be running in non-primary thread
+{
+#if MGL_HAVE_PTHR_WIDGET
+	static pthread_t thr;
+	pthread_create(&thr,0,mgl_fltk_tmp,0);
+	pthread_detach(thr);
+#endif
+	return 0;	// stupid, but I don't want keep result returned by Fl::Run()
+}
+//-----------------------------------------------------------------------------
diff --git a/widgets/glut.cpp b/widgets/glut.cpp
new file mode 100644
index 0000000..ca8bff8
--- /dev/null
+++ b/widgets/glut.cpp
@@ -0,0 +1,277 @@
+/***************************************************************************
+ * glut.cpp is part of Math Graphic Library
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#define GLUT_NO_LIB_PRAGMA
+#define GLUT_NO_WARNING_DISABLE
+
+#ifdef __APPLE__
+	#include <OpenGL/gl.h>
+	#include <GLUT/glut.h>
+#else
+	#if defined(_MSC_VER) || defined(__BORLANDC__)
+		#include <windows.h>
+		#include <GL/gl.h>
+		#include "glut.h"
+	#else
+		#include <GL/gl.h>
+		#include <GL/glut.h>
+	#endif
+#endif
+
+#include "mgl2/opengl.h"
+#include "mgl2/glut.h"
+
+void _mgl_key_up(unsigned char ch,int ,int );
+//-----------------------------------------------------------------------------
+/// Class allows the window creation under OpenGL with the help of GLUT library
+class mglCanvasGLUT : public mglCanvasGL
+{
+friend void _mgl_display();
+friend void _mgl_key_up(unsigned char ch,int ,int );
+friend void _mgl_timer(int);
+public:
+	mglCanvasGLUT();
+	virtual ~mglCanvasGLUT();
+	/// Create a window for plotting. Now implemeted only for GLUT.
+	void Window(int argc, char **argv, int (*draw)(mglBase *gr, void *p),
+						const char *title,void *par=NULL,
+			   			void (*reload)(void *p)=NULL, bool maximize=false);
+	void Window(int argc, char **argv, int (*draw)(mglGraph *gr),
+				const char *title, bool maximize=false)
+	{	Window(argc,argv,draw?mgl_draw_graph:0,title,(void*)draw,0,maximize);	}
+	/// Create a window for plotting based on class mglDraw.
+	void Window(int argc, char **argv, const char *title, mglDraw *draw, bool maximize=false)
+	{	Window(argc, argv, draw?mgl_draw_class:0, title, draw, mgl_reload_class, maximize);	}
+	/// Switch on/off transparency (do not overwrite switches in user drawing function)
+	void ToggleAlpha()	{	_mgl_key_up('r',0,0);	}
+	/// Switch on/off lighting (do not overwrite switches in user drawing function)
+	void ToggleLight()	{	_mgl_key_up('f',0,0);	}
+	void ToggleNo()		{	_mgl_key_up('n',0,0);	}	///< Switch off all zooming and rotation
+	void Update()		{	_mgl_key_up(' ',0,0);	}	///< Update picture by calling user drawing function
+	void ReLoad()		{	_mgl_key_up('[',0,0);	}	///< Reload user data and update picture
+	void NextFrame()	{	_mgl_key_up('.',0,0);	}	///< Show next frame (if one)
+	void PrevFrame()	{	_mgl_key_up(',',0,0);	}	///< Show previous frame (if one)
+	void Animation()	{	_mgl_key_up('m',0,0);	}	///< Run slideshow (animation) of frames
+private:
+	void (*LoadFunc)(void *par);
+	void *FuncPar;		///< Parameters for drawing function mglCanvas::DrawFunc.
+	/// Drawing function for window procedure. It should return the number of frames.
+	int (*DrawFunc)(mglBase *gr, void *par);
+	int NumFig;		///< Number of figures in the list. If 0 then no list and mglCanvas::DrawFunc will called for each drawing.
+	int curr_fig;	///< Current figure in the list.
+	int tt;			///< Temporal variable
+} *_mgl_glwnd;
+//-----------------------------------------------------------------------------
+void _mgl_timer(int)
+{
+	if(!_mgl_glwnd)	return;
+	if(_mgl_glwnd->tt)
+	{
+		_mgl_glwnd->curr_fig++;
+		if(_mgl_glwnd->curr_fig > _mgl_glwnd->NumFig)
+			_mgl_glwnd->curr_fig = 1;
+		glutPostRedisplay();
+	}
+	glutTimerFunc(int(_mgl_glwnd->Delay*1000),_mgl_timer,0);
+}
+//-----------------------------------------------------------------------------
+void _mgl_key_up(unsigned char ch,int ,int )
+{
+	if(!_mgl_glwnd)	return;
+	static bool Alpha=false;
+	static bool Light=false;
+	static mreal rL=3,tL=0,pL=0;
+
+	if(ch=='h')
+	{
+		printf(_("Use 'a', 'd', 'w', 's', 'q', 'e' for changing view angles\n"
+		"Use 'j', 'l', 'i', 'k' for changing light angles\n"
+		"Use 'u', 'o' for changing distance to light\n"
+		"Use 'r' for switching transparency\nUse 'f' for switching lightning\n"
+		"Use 'E' for exporting to EPS file\nUse 'S' for exporting to SVG file\n"
+		"Use 'J' for exporting to JPEG file\nUse 'P' for exporting to PNG file\n"
+		"Use ',', '.' for show other frames\nUse 'm' for view movie\n"
+		"Use 'h' for view this text\nUse 'x' for exit\n") );
+
+	}
+	if(ch=='w')	_mgl_glwnd->View(-10,0,0);
+	if(ch=='s')	_mgl_glwnd->View(10,0,0);
+	if(ch=='a')	_mgl_glwnd->View(0,0,-10);
+	if(ch=='d')	_mgl_glwnd->View(0,0,10);
+	if(ch=='q')	_mgl_glwnd->View(0,-10,0);
+	if(ch=='e')	_mgl_glwnd->View(0,10,0);
+	if(ch=='n')	_mgl_glwnd->Restore();
+	if(ch==',')
+		_mgl_glwnd->curr_fig = _mgl_glwnd->curr_fig == 0 ? _mgl_glwnd->NumFig-1 : _mgl_glwnd->curr_fig-1;
+	if(ch=='.')
+		_mgl_glwnd->curr_fig = _mgl_glwnd->curr_fig == _mgl_glwnd->NumFig-1 ? 0 : _mgl_glwnd->curr_fig+1;
+	if(ch=='r')	Alpha = !Alpha;
+	if(ch=='f')	Light = !Light;
+	if(ch=='u')	rL += 0.1;
+	if(ch=='o')	rL -= 0.1;
+	if(ch=='i')	tL += M_PI*0.1;
+	if(ch=='k')	tL -= M_PI*0.1;
+	if(ch=='l')	pL += 2*M_PI*0.1;
+	if(ch=='j')	pL -= 2*M_PI*0.1;
+	if(ch=='[' && _mgl_glwnd->LoadFunc)
+	{
+		glDeleteLists(1,_mgl_glwnd->NumFig);
+		_mgl_glwnd->LoadFunc(_mgl_glwnd->FuncPar);
+		if(_mgl_glwnd->DrawFunc)
+		{
+			_mgl_glwnd->ResetFrames();
+			(_mgl_glwnd->DrawFunc)(_mgl_glwnd,_mgl_glwnd->FuncPar);
+		}
+		_mgl_glwnd->Finish();
+	}
+	if(ch=='P')
+	{
+		char str[128];
+		snprintf(str,128,"%s_%d.png",_mgl_glwnd->PlotId.c_str(),_mgl_glwnd->curr_fig);
+		str[127]=0;	mgl_write_png(_mgl_glwnd, str, "MathGL");
+	}
+	if(ch=='J')
+	{
+		char str[128];
+		snprintf(str,128,"%s_%d.jpg",_mgl_glwnd->PlotId.c_str(),_mgl_glwnd->curr_fig);
+		str[127]=0;	mgl_write_jpg(_mgl_glwnd, str, "MathGL");
+	}
+	if(ch=='E')
+	{
+		char str[128];
+		snprintf(str,128,"%s_%d.eps",_mgl_glwnd->PlotId.c_str(),_mgl_glwnd->curr_fig);
+		str[127]=0;	mgl_write_eps(_mgl_glwnd, str, "MathGL");
+	}
+	if(ch=='S')
+	{
+		char str[128];
+		snprintf(str,128,"%s_%d.svg",_mgl_glwnd->PlotId.c_str(),_mgl_glwnd->curr_fig);
+		str[127]=0;	mgl_write_svg(_mgl_glwnd, str, "MathGL");
+	}
+	if(ch==' ')	_mgl_glwnd->Clf();
+	if(ch=='m')	_mgl_glwnd->tt = 1-_mgl_glwnd->tt;
+	rL = rL<0 ? 0 : (rL>5 ? 5 : rL);
+	_mgl_glwnd->AddLight(0,mglPoint(rL*cos(pL)*sin(tL), rL*sin(pL)*sin(tL), rL*cos(tL)),false);
+	_mgl_glwnd->Alpha(Alpha);
+	_mgl_glwnd->Light(Light);
+//	glEnable(GL_BLEND);
+	if(strchr("ijkl",ch))
+		printf("Light: %g, %g, %g\n",rL*cos(pL)*sin(tL), rL*sin(pL)*sin(tL), rL*cos(tL));
+
+	if(ch=='x')	exit(0);
+	else		glutPostRedisplay();
+}
+//-----------------------------------------------------------------------------
+void _mgl_display()
+{
+	if(!_mgl_glwnd)	return;
+//	glEnable(GL_LINE_SMOOTH);
+//	_mgl_glwnd->CurFrameId = 1;
+//	if(_mgl_glwnd->get(MGL_CLF_ON_UPD))
+	_mgl_glwnd->Clf();
+//	_mgl_glwnd->gl_clf();
+	_mgl_glwnd->InPlot(0,1,0,1,false);
+	if(_mgl_glwnd->NumFig>0)
+	{
+		_mgl_glwnd->GetFrame(_mgl_glwnd->curr_fig);
+		_mgl_glwnd->Finish();
+//		glCallList(_mgl_glwnd->curr_fig);
+	}
+	else
+	{
+		if(_mgl_glwnd->DrawFunc)
+		{
+			_mgl_glwnd->ResetFrames();
+			(_mgl_glwnd->DrawFunc)(_mgl_glwnd,_mgl_glwnd->FuncPar);
+		}
+		_mgl_glwnd->Finish();
+	}
+	glFinish();
+}
+//-----------------------------------------------------------------------------
+mglCanvasGLUT::~mglCanvasGLUT()	{	_mgl_glwnd = 0;	}
+//-----------------------------------------------------------------------------
+void mglCanvasGLUT::Window(int argc, char **argv,int (*draw)(mglBase *gr, void *p),const char *title, void *par, void (*reload)(void *p), bool /*maximize*/)
+{
+	NumFig=0;	curr_fig=1;	tt=0;
+	_mgl_glwnd = this;
+	CurFrameId = 1;
+
+	char *tmp[1];	tmp[0]=new char[1];	tmp[0][0]=0;
+	glutInit(&argc, argv ? argv:tmp);
+	delete []tmp[0];
+	glutInitDisplayMode(GLUT_RGB);
+	glutInitWindowSize(600, 600);
+	glutCreateWindow("MathGL");
+
+	AddLight(0,mglPoint(0,0,3),false);
+	if(draw)
+	{
+		NumFig = draw(this,par)-1;	Finish();
+		DrawFunc = draw;	FuncPar = par;
+	}
+	else
+	{	NumFig = 0;	DrawFunc=0;	FuncPar=0;	}
+	LoadFunc = reload;
+	glutSetWindowTitle(title);
+
+	glutDisplayFunc(_mgl_display);
+	glutKeyboardUpFunc(_mgl_key_up);
+	glutTimerFunc(int(1000*Delay),_mgl_timer,0);
+
+	// TODO Add window maximazing at start up ???
+
+	glutMainLoop();
+	if(NumFig>0)	glDeleteLists(1,NumFig);
+}
+//-----------------------------------------------------------------------------
+HMGL MGL_EXPORT mgl_create_graph_glut(int (*draw)(HMGL gr, void *p), const char *title, void *par, void (*load)(void *p))
+{
+	mglCanvasGLUT *g = new mglCanvasGLUT;
+	g->Window(0,0,draw,title,par, load);
+	return g;
+}
+//-----------------------------------------------------------------------------
+mglCanvasGLUT::mglCanvasGLUT() : mglCanvasGL()	{}
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_glut_toggle_alpha(HMGL gr)
+{	mglCanvasGLUT *g = dynamic_cast<mglCanvasGLUT*>(gr);
+	if(g)	g->ToggleAlpha();	}
+void MGL_EXPORT mgl_glut_toggle_light(HMGL gr)
+{	mglCanvasGLUT *g = dynamic_cast<mglCanvasGLUT*>(gr);
+	if(g)	g->ToggleLight();	}
+void MGL_EXPORT mgl_glut_toggle_no(HMGL gr)
+{	mglCanvasGLUT *g = dynamic_cast<mglCanvasGLUT*>(gr);
+	if(g)	g->ToggleNo();	}
+void MGL_EXPORT mgl_glut_update(HMGL gr)
+{	mglCanvasGLUT *g = dynamic_cast<mglCanvasGLUT*>(gr);
+	if(g)	g->Update();	}
+void MGL_EXPORT mgl_glut_reload(HMGL gr)
+{	mglCanvasGLUT *g = dynamic_cast<mglCanvasGLUT*>(gr);
+	if(g)	g->ReLoad();	}
+void MGL_EXPORT mgl_glut_next_frame(HMGL gr)
+{	mglCanvasGLUT *g = dynamic_cast<mglCanvasGLUT*>(gr);
+	if(g)	g->NextFrame();	}
+void MGL_EXPORT mgl_glut_prev_frame(HMGL gr)
+{	mglCanvasGLUT *g = dynamic_cast<mglCanvasGLUT*>(gr);
+	if(g)	g->PrevFrame();	}
+void MGL_EXPORT mgl_glut_animation(HMGL gr)
+{	mglCanvasGLUT *g = dynamic_cast<mglCanvasGLUT*>(gr);
+	if(g)	g->Animation();	}
+//-----------------------------------------------------------------------------
diff --git a/widgets/image.cpp b/widgets/image.cpp
new file mode 100644
index 0000000..15d1201
--- /dev/null
+++ b/widgets/image.cpp
@@ -0,0 +1,2877 @@
+/* image.cpp is part of UDAV
+ * Copyright (C) 2007-2014 Alexey Balakin <mathgl.abalakin at gmail.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License
+ * as published by the Free Software Foundation
+ *
+ * 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
+ */
+
+#include "mgl2/define.h"
+#include "image.h"
+
+static const unsigned char idata_load[] =
+{0,0,0,0,0,0,0,3,0,0,0,73,0,0,0,75,0,0,0,75,0,0,0,75,0,0,0,75,0,0,0,75,0,0,
+0,61,9,9,9,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,127,181,201,
+40,76,118,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,232,231,231,255,42,42,41,150,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,84,127,181,0,74,115,167,255,81,114,155,255,255,255,255,
+255,246,246,246,255,248,248,248,255,249,248,248,255,245,244,244,255,235,235,235,
+255,196,196,196,254,255,255,254,255,59,81,106,255,81,126,184,255,84,131,188,255,
+84,129,187,255,88,135,194,213,0,0,0,0,61,100,146,255,74,106,144,255,255,255,
+255,255,248,248,248,255,248,248,248,255,249,249,249,255,246,246,246,255,239,238,
+238,255,160,160,160,255,255,255,255,255,228,225,222,255,78,97,119,255,120,162,
+215,255,124,169,225,255,73,118,173,255,0,0,0,0,47,82,122,255,62,94,135,255,255,
+255,255,255,248,247,247,255,249,249,249,255,249,249,249,255,247,247,247,255,242,
+242,242,255,154,154,154,255,255,255,255,255,241,239,239,255,225,221,219,255,55,
+79,109,255,104,148,205,255,48,82,123,255,0,0,0,0,43,75,113,255,47,82,122,255,
+255,255,255,255,248,247,247,255,249,249,249,255,249,249,249,255,248,248,248,255,
+245,245,245,255,161,160,160,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,252,250,255,70,93,121,255,42,75,115,255,0,0,0,0,37,70,106,255,33,67,109,255,
+255,255,255,255,247,247,247,255,248,248,248,255,250,249,249,255,251,251,250,255,
+250,249,249,255,235,235,235,255,184,184,184,255,180,179,179,255,173,172,172,255,
+178,176,176,255,244,242,240,255,14,42,74,255,0,0,0,0,34,65,100,255,17,52,94,255,
+255,255,255,255,248,248,248,255,251,250,250,255,250,249,250,255,223,225,229,255,
+207,211,216,255,206,210,214,255,204,207,213,255,201,205,209,255,198,200,206,255,
+193,196,202,255,224,226,229,255,0,20,49,255,0,0,0,0,24,57,91,255,0,30,69,255,
+232,232,234,255,206,209,213,255,208,210,214,255,181,187,195,255,135,162,190,255,
+167,205,235,255,168,205,234,255,169,205,235,255,168,205,235,255,168,205,235,255,
+168,205,235,255,170,206,235,255,188,224,252,255,147,177,203,186,79,118,159,255,
+188,224,251,255,167,204,234,255,166,203,233,255,166,204,234,255,168,206,235,255,
+170,206,234,255,133,171,218,255,130,166,215,255,128,166,215,255,127,166,215,255,
+130,166,215,255,128,166,215,255,128,166,215,255,135,173,225,255,72,93,120,255,
+80,121,169,255,131,169,220,255,124,163,214,255,125,163,214,255,125,163,214,255,
+126,163,214,255,126,163,214,255,129,166,216,255,128,167,216,255,128,167,216,255,
+128,167,216,255,130,167,216,255,129,167,216,255,129,167,216,255,135,174,225,255,
+73,95,123,255,81,122,170,255,138,174,224,255,131,169,219,255,131,169,219,255,
+134,169,219,255,131,169,219,255,135,169,219,255,133,169,219,255,132,169,219,255,
+131,169,219,255,134,169,219,255,131,169,219,255,134,169,219,255,132,169,218,255,
+137,177,228,255,74,95,124,255,57,103,155,255,64,118,180,255,63,116,176,255,63,
+116,176,255,63,116,176,255,63,116,176,255,64,116,176,255,63,116,176,255,64,116,
+176,255,63,116,176,255,63,116,176,255,63,116,176,255,63,116,176,255,63,116,176,
+255,67,122,185,255,39,68,102,255,88,127,173,255,135,173,223,255,132,169,218,255,
+133,169,218,255,134,169,218,255,133,169,218,255,132,169,218,255,132,169,218,255,
+133,169,218,255,134,169,218,255,133,169,218,255,131,169,218,255,133,169,218,255,
+132,169,218,255,138,176,227,255,80,100,129,255,74,117,166,185,129,168,221,255,
+125,163,216,255,126,164,216,255,124,163,216,255,120,163,217,255,124,163,217,255,
+126,164,217,255,126,164,217,255,126,163,217,255,121,163,217,255,122,163,216,255,
+126,164,216,255,126,163,216,255,129,169,224,255,69,95,128,175,0,24,56,65,0,19,
+51,122,0,20,51,123,0,19,50,124,0,19,50,125,0,19,49,126,0,19,49,127,0,18,48,129,
+0,18,48,129,0,18,49,127,0,19,49,126,0,19,50,125,0,19,50,124,0,20,51,123,0,19,
+51,122,0,27,61,66};
+MGL_EXPORT Fl_RGB_Image img_load(idata_load, 16, 16, 4, 0);
+
+static const unsigned char idata_save[] =
+{108,133,119,124,77,121,145,126,56,103,139,111,56,103,139,140,56,103,139,
+212,56,103,139,255,61,105,138,248,74,113,128,229,88,120,122,133,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66,112,146,94,98,150,187,126,129,173,
+209,93,177,206,230,205,208,223,239,255,197,219,236,255,155,194,223,255,104,139,
+160,253,67,110,136,253,106,127,90,27,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,107,127,136,150,102,113,115,255,98,112,117,255,74,109,133,255,65,116,
+154,255,68,120,159,255,158,191,217,255,193,217,235,255,81,134,175,255,78,106,
+125,255,110,112,107,255,110,112,107,255,110,112,107,255,110,112,107,255,110,112,
+107,255,110,112,107,128,107,113,110,255,226,230,221,255,255,255,255,255,221,225,
+214,255,201,214,221,255,110,153,182,255,56,103,139,255,171,203,226,255,146,183,
+211,255,84,125,155,255,213,223,229,255,255,255,255,255,255,255,255,255,255,255,
+255,255,244,244,244,255,110,112,107,255,114,117,107,255,253,253,253,255,238,238,
+238,255,237,237,237,255,223,226,222,255,119,152,176,255,56,103,139,255,121,167,
+202,255,143,179,206,255,61,107,142,255,172,188,195,255,237,237,238,255,237,238,
+238,255,237,238,237,255,243,244,243,255,110,112,107,255,110,112,107,255,252,251,
+252,255,235,236,236,255,56,103,139,255,56,103,139,255,56,103,139,255,56,103,139,
+255,121,167,202,255,88,146,189,255,56,103,139,255,56,103,139,255,56,103,139,255,
+56,103,139,255,236,236,236,255,243,243,243,255,110,112,107,255,110,112,107,255,
+250,250,250,255,233,233,234,255,202,207,196,255,56,103,139,255,152,191,220,255,
+113,159,191,255,113,159,191,255,113,159,191,255,115,159,192,255,150,187,216,255,
+56,103,139,255,149,169,175,255,234,233,234,255,242,242,242,255,110,112,107,255,
+110,112,107,255,249,249,249,255,250,250,250,255,228,228,228,255,197,203,191,255,
+56,103,139,255,152,191,220,255,115,159,192,255,115,159,192,255,171,200,223,255,
+56,103,139,255,146,166,172,255,228,228,228,255,244,244,244,255,241,241,241,255,
+110,112,107,255,110,112,107,255,249,249,249,255,238,238,238,255,250,250,250,255,
+228,228,228,255,197,203,191,255,56,103,139,255,172,203,227,255,152,191,220,255,
+59,107,143,255,146,166,172,255,228,228,228,255,250,250,250,255,238,238,238,255,
+241,241,241,255,110,112,107,255,110,112,107,255,247,247,247,255,227,227,227,255,
+238,238,238,255,250,250,250,255,250,250,250,255,206,212,200,255,63,108,142,255,
+56,103,139,255,154,174,180,255,250,250,250,255,252,252,252,255,238,238,238,255,
+227,227,227,255,240,240,240,255,110,112,107,255,110,112,107,255,254,254,254,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,244,244,244,255,244,244,244,255,235,235,235,255,
+235,235,235,255,227,227,227,255,240,240,240,255,110,112,107,255,110,112,107,255,
+206,206,206,255,201,201,201,255,201,201,201,255,201,201,201,255,201,201,201,255,
+197,197,197,255,201,201,201,255,201,201,201,255,197,197,197,255,197,197,197,255,
+197,197,197,255,197,197,197,255,197,197,197,255,214,214,214,255,110,112,107,255,
+110,112,107,255,206,206,206,255,197,197,197,255,159,159,159,255,175,175,175,255,
+188,188,188,255,196,196,196,255,200,200,200,255,208,208,208,255,169,169,169,255,
+210,210,210,255,169,169,169,255,210,210,210,255,185,185,185,255,202,202,202,255,
+110,112,107,255,110,112,107,255,205,205,205,255,195,195,195,255,170,170,169,255,
+180,180,180,255,194,194,194,255,196,196,196,255,200,200,200,255,203,203,203,255,
+168,167,168,255,209,209,209,255,168,167,167,255,209,209,209,255,183,182,182,255,
+202,202,202,255,110,112,107,255,110,112,107,255,221,221,221,255,220,220,220,255,
+220,220,220,255,220,220,220,255,213,213,213,255,213,213,213,255,207,207,207,255,
+207,207,207,255,207,207,207,255,207,207,207,255,207,207,207,255,207,207,207,255,
+207,207,207,255,202,202,202,255,110,112,107,255,110,112,107,128,110,112,107,255,
+110,112,107,255,110,112,107,255,110,112,107,255,110,112,107,255,110,112,107,255,
+110,112,107,255,110,112,107,255,110,112,107,255,110,112,107,255,110,112,107,255,
+110,112,107,255,110,112,107,255,110,112,107,255,110,112,107,128};
+MGL_EXPORT Fl_RGB_Image img_save(idata_save, 16, 16, 4, 0);
+
+static const unsigned char idata_calc[] =
+{255,255,255,0,255,255,255,0,0,0,0,7,69,69,69,138,121,121,121,185,124,124,
+124,187,122,122,122,188,121,121,121,187,118,118,118,187,118,118,118,187,118,118,
+118,186,119,119,119,185,77,77,77,136,0,0,0,3,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,0,0,0,81,206,206,206,255,119,119,119,255,114,115,113,
+255,116,118,116,255,117,119,116,255,116,118,116,255,104,106,103,255,73,75,72,
+255,77,77,76,255,195,195,195,255,0,0,0,66,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,0,0,0,96,211,211,211,255,105,105,105,255,192,204,183,255,
+189,202,181,255,191,203,183,255,179,194,169,255,157,173,146,255,155,171,144,255,
+103,105,101,255,195,195,195,255,0,0,0,81,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,0,0,0,96,206,206,206,255,75,75,75,255,77,77,77,255,66,67,66,
+255,54,55,54,255,49,50,49,255,49,50,49,255,60,60,60,255,61,61,61,255,190,190,
+190,255,0,0,0,81,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,0,0,0,
+96,224,224,224,255,196,196,196,255,200,200,200,255,198,198,198,255,193,193,193,
+255,193,193,193,255,193,193,193,255,194,194,194,255,199,199,199,255,228,228,228,
+255,0,0,0,82,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,0,0,0,96,
+223,223,223,255,62,62,62,255,62,62,62,255,238,238,238,255,62,62,62,255,59,59,59,
+255,224,224,224,255,62,62,62,255,62,62,62,255,234,234,234,255,0,0,0,82,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,0,0,0,96,219,219,219,255,237,
+237,237,255,242,242,242,255,235,235,235,255,231,231,231,255,231,231,231,255,231,
+231,231,255,234,234,234,255,240,240,240,255,232,232,232,255,0,0,0,83,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,0,0,0,96,215,215,215,255,62,62,
+62,255,62,62,62,255,230,230,230,255,61,61,61,255,59,59,59,255,219,219,219,255,
+62,62,62,255,62,62,62,255,229,229,229,255,0,0,0,83,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,0,0,0,96,212,212,212,255,234,234,234,255,238,238,
+238,255,227,227,227,255,226,226,226,255,226,226,226,255,226,226,226,255,232,232,
+232,255,236,236,236,255,227,227,227,255,0,0,0,83,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,0,0,0,96,209,209,209,255,62,62,62,255,62,62,62,255,
+224,224,224,255,61,61,61,255,59,59,59,255,216,216,216,255,62,62,62,255,62,62,62,
+255,225,225,225,255,0,0,0,83,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,0,0,0,96,207,207,207,255,231,231,231,255,225,225,225,255,222,222,222,255,
+222,222,222,255,222,222,222,255,223,223,223,255,229,229,229,255,232,232,232,255,
+223,223,223,255,0,0,0,83,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,
+0,0,0,0,96,204,204,204,255,62,62,62,255,62,62,62,255,219,219,219,255,62,62,62,
+255,60,60,60,255,213,213,213,255,65,65,65,255,65,65,65,255,220,220,220,255,0,0,
+0,83,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,0,0,0,96,202,202,
+202,255,218,218,218,255,213,213,213,255,217,217,217,255,213,213,213,255,211,211,
+211,255,220,220,220,255,54,54,54,255,56,56,56,255,218,218,218,255,0,0,0,83,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,0,0,0,96,200,200,200,255,61,
+61,61,255,61,61,61,255,215,215,215,255,61,61,61,255,60,60,60,255,212,212,212,
+255,49,49,49,255,49,49,49,255,216,216,216,255,0,0,0,83,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,0,0,0,91,184,184,184,255,213,213,213,255,213,
+213,213,255,213,213,213,255,213,213,213,255,214,214,214,255,217,217,217,255,223,
+223,223,255,223,223,223,255,204,204,204,255,0,0,0,79,255,255,255,0,255,255,255,
+0,255,255,255,0,255,255,255,0,0,0,0,21,71,71,71,224,101,101,101,243,101,101,
+101,243,101,101,101,243,101,101,101,243,102,102,102,243,105,105,105,243,109,109,
+109,244,108,108,108,244,71,71,71,226,0,0,0,12,255,255,255,0,255,255,255,0};
+MGL_EXPORT Fl_RGB_Image img_calc(idata_calc, 16, 16, 4, 0);
+
+static const unsigned char idata_undo[] =
+{166,127,0,27,166,127,0,33,255,255,255,0,255,255,255,0,166,127,0,34,169,131,
+2,129,180,146,16,192,195,169,53,239,200,173,68,243,183,147,25,198,167,129,1,
+136,166,127,0,43,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,173,
+138,12,220,185,156,29,245,166,127,0,85,168,131,2,108,196,169,36,247,235,211,84,
+255,243,222,100,255,249,236,113,255,249,236,114,255,244,223,105,255,238,209,89,
+255,200,163,33,245,168,128,1,126,166,127,0,4,255,255,255,0,255,255,255,0,176,
+145,13,243,241,217,103,255,197,172,39,249,221,197,72,250,245,223,103,255,247,
+229,103,255,247,229,103,255,247,229,103,255,247,229,103,255,247,229,103,255,247,
+229,103,255,245,224,105,255,224,185,63,249,170,131,3,205,166,127,0,6,255,255,
+255,0,176,145,13,243,243,217,105,255,243,217,105,255,243,220,104,255,243,219,
+102,255,243,218,101,255,239,204,95,255,232,183,62,255,232,183,58,255,238,200,84,
+255,243,217,102,255,243,217,101,255,243,218,104,255,201,162,53,249,166,127,1,
+137,255,255,255,0,176,145,13,244,238,209,100,255,239,211,99,255,239,212,99,255,
+235,205,85,255,222,170,33,255,213,156,14,255,200,150,20,254,197,144,25,254,205,
+136,6,255,226,162,39,255,238,202,92,255,239,204,95,255,234,198,91,255,158,120,
+18,246,166,127,0,55,177,145,13,244,235,203,93,255,235,207,92,255,233,206,86,
+255,218,179,22,255,195,157,17,254,149,120,13,246,163,125,2,177,160,123,3,166,
+133,103,8,247,153,101,5,249,224,156,31,250,236,193,86,253,236,193,85,255,174,
+136,51,254,165,126,0,149,176,144,13,244,227,187,64,255,230,200,80,255,231,207,
+78,255,225,201,46,255,215,186,17,255,171,137,14,244,166,127,0,81,255,255,255,0,
+166,127,0,21,165,126,6,243,202,132,3,214,227,167,51,227,232,180,72,243,195,147,
+54,254,156,118,3,212,169,133,5,239,194,156,22,248,196,159,23,253,202,170,38,
+253,208,178,40,254,213,185,32,254,209,178,24,252,169,130,3,232,166,127,0,42,255,
+255,255,0,168,129,1,156,197,139,7,202,222,150,26,174,228,168,57,197,214,157,52,
+223,140,104,3,250,166,127,0,60,166,127,0,180,166,127,0,252,166,127,0,255,166,
+127,1,255,166,127,0,255,166,127,0,255,166,127,0,233,166,127,0,42,255,255,255,0,
+168,128,1,159,193,136,6,184,219,139,4,137,220,143,11,159,199,130,8,184,142,105,
+2,249,255,255,255,0,255,255,255,0,255,255,255,0,199,129,3,1,201,132,4,5,141,
+117,22,3,255,255,255,0,255,255,255,0,255,255,255,0,166,127,0,27,173,133,4,239,
+208,142,8,108,218,137,0,111,218,137,0,123,162,107,3,171,159,120,1,204,255,255,
+255,0,255,255,255,0,255,255,255,0,218,141,4,1,217,148,9,6,174,132,20,5,145,126,
+26,1,166,127,0,17,166,127,0,152,167,128,1,235,185,143,8,146,216,150,11,73,217,
+143,5,84,218,137,0,95,151,107,4,168,166,127,0,146,255,255,255,0,255,255,255,0,
+255,255,255,0,217,148,9,1,215,156,16,1,255,255,255,0,206,165,29,1,184,152,28,4,
+177,143,15,19,202,163,29,22,214,164,23,42,215,158,17,52,216,150,11,60,196,135,7,
+73,158,119,2,235,166,127,0,51,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,214,162,22,1,255,255,255,0,255,255,255,0,211,181,37,1,211,181,38,4,
+212,178,35,10,213,172,30,26,214,165,23,32,215,155,17,29,165,124,5,115,166,127,0,
+106,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,209,192,46,1,210,187,42,4,
+211,179,36,12,215,171,32,11,201,149,24,12,163,109,5,2,255,255,255,0,255,255,255,
+0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,215,188,46,1,213,167,25,2,
+220,162,23,1,213,128,0,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,
+0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0};
+MGL_EXPORT Fl_RGB_Image img_undo(idata_undo, 16, 16, 4, 0);
+
+static const unsigned char idata_redo[] =
+{255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,0,140,0,37,1,141,1,
+128,7,145,4,189,8,145,6,238,10,146,9,240,15,149,11,193,3,142,2,123,0,140,0,29,
+255,255,255,0,255,255,255,0,0,140,0,27,0,140,0,25,255,255,255,0,255,255,255,0,0,
+140,0,2,1,141,1,118,4,144,3,245,50,174,41,255,88,196,72,255,134,219,110,255,133,
+219,110,255,93,198,78,255,53,174,43,255,5,144,3,247,5,142,3,102,0,140,0,78,2,
+142,2,244,3,142,2,219,255,255,255,0,0,140,0,5,1,141,1,198,23,156,17,248,114,215,
+94,255,127,223,103,255,127,223,103,255,127,223,103,255,127,223,103,255,127,223,
+103,255,127,223,103,255,105,208,88,255,20,154,15,251,4,143,2,249,92,198,76,255,
+2,141,1,244,255,255,255,0,0,140,0,131,20,152,16,248,103,214,88,255,101,212,85,
+255,102,212,86,255,85,207,73,255,58,198,49,255,60,200,52,255,94,210,84,255,100,
+211,84,255,101,212,85,255,102,212,86,255,102,210,88,255,101,209,87,255,2,141,1,
+244,0,140,0,51,2,141,2,245,72,194,63,255,77,203,67,255,76,203,67,255,35,190,32,
+255,15,176,10,255,16,159,9,254,24,164,17,254,20,181,13,255,20,185,18,255,64,199,
+55,255,77,203,67,255,77,203,67,255,80,202,70,255,2,141,1,244,0,140,0,147,25,
+153,22,254,56,196,51,255,56,196,51,255,24,187,23,255,14,151,10,253,2,139,1,246,
+2,140,1,173,1,140,1,184,2,140,1,244,25,161,16,253,5,181,5,255,51,193,46,255,
+56,196,51,255,62,195,54,255,1,141,1,244,1,140,1,207,32,166,27,253,38,189,36,
+248,30,187,29,236,18,173,13,221,1,140,1,244,0,140,0,26,255,255,255,0,0,140,0,78,
+3,141,1,244,23,175,15,255,18,184,17,255,35,188,34,255,38,189,36,255,39,189,34,
+255,1,141,1,244,0,140,0,249,29,180,25,215,22,185,22,196,11,181,11,178,13,153,8,
+203,1,141,0,159,255,255,255,0,0,140,0,42,0,140,0,234,57,189,33,250,50,188,32,
+254,54,186,36,254,54,184,37,253,51,182,31,253,50,178,29,249,1,140,0,240,0,140,0,
+249,15,175,10,176,3,181,3,156,1,180,1,141,11,151,6,184,1,141,0,159,255,255,255,
+0,0,140,0,45,0,140,0,237,0,140,0,255,0,140,0,255,0,138,0,248,0,134,0,234,0,
+131,0,220,0,127,0,204,0,124,0,104,0,140,0,204,17,157,9,164,0,180,0,121,0,180,0,
+108,23,174,12,107,1,134,1,219,0,129,0,21,255,255,255,0,255,255,255,0,255,255,
+255,0,67,170,35,4,41,186,21,5,32,183,16,1,255,255,255,0,255,255,255,0,255,255,
+255,0,0,124,0,111,16,138,10,149,0,180,0,90,0,180,0,80,10,182,5,69,28,146,15,101,
+3,107,2,104,0,100,0,59,0,96,0,8,67,172,36,1,62,183,33,5,27,187,14,8,18,184,9,
+1,255,255,255,0,255,255,255,0,255,255,255,0,0,98,0,18,11,111,6,96,19,173,12,
+67,8,182,4,55,21,185,11,47,33,188,17,38,66,200,37,16,56,188,31,9,59,183,31,5,
+67,196,36,1,255,255,255,0,41,190,22,2,30,187,16,1,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,0,153,0,0,49,165,28,37,19,186,10,34,30,187,16,28,44,
+191,23,22,56,194,30,8,65,196,35,4,70,198,37,2,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,12,140,6,2,58,183,32,15,54,195,29,14,52,193,28,10,67,197,35,3,79,
+200,42,1,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,0,191,0,0,54,196,29,2,39,190,20,2,86,206,46,1,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0};
+MGL_EXPORT Fl_RGB_Image img_redo(idata_redo, 16, 16, 4, 0);
+
+static const unsigned char idata_copy[] =
+{0,0,0,18,0,0,0,75,0,0,0,76,0,0,0,76,0,0,0,76,0,0,0,76,0,0,0,76,0,0,0,76,0,
+0,0,76,0,0,0,76,0,0,0,75,0,0,0,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,76,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+0,0,0,77,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,77,255,255,255,255,234,235,235,
+255,236,237,237,255,238,238,238,255,239,240,240,255,240,241,241,255,241,242,242,
+255,242,242,242,255,242,242,242,255,255,255,255,255,0,0,0,78,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,77,255,255,255,255,237,238,238,255,239,240,240,255,226,
+226,226,255,176,176,176,255,176,176,176,255,176,177,177,255,177,177,177,255,177,
+177,177,255,184,184,184,255,0,0,0,128,0,0,0,71,0,0,0,71,0,0,0,70,0,0,0,16,0,0,0,
+77,255,255,255,255,240,240,240,255,242,243,243,255,177,177,177,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,72,0,
+0,0,77,255,255,255,255,243,243,243,255,245,245,245,255,177,178,178,255,255,
+255,255,255,235,236,236,255,238,238,238,255,240,240,240,255,242,242,242,255,243,
+244,244,255,244,245,245,255,245,245,245,255,245,245,245,255,255,255,255,255,0,0,
+0,74,0,0,0,77,255,255,255,255,245,245,245,255,248,248,248,255,179,179,179,255,
+255,255,255,255,238,238,238,255,240,241,241,255,243,243,243,255,245,245,245,255,
+246,246,246,255,247,248,248,255,248,248,248,255,248,248,248,255,255,255,255,255,
+0,0,0,74,0,0,0,77,255,255,255,255,247,247,247,255,250,250,250,255,180,180,180,
+255,255,255,255,255,240,240,240,255,243,243,243,255,245,246,246,255,248,248,248,
+255,249,249,249,255,250,250,250,255,250,250,250,255,250,250,250,255,255,255,255,
+255,0,0,0,74,0,0,0,77,255,255,255,255,249,249,249,255,251,251,251,255,181,181,
+181,255,255,255,255,255,242,242,242,255,245,245,245,255,248,248,248,255,250,250,
+250,255,251,251,251,255,251,251,251,255,252,252,252,255,252,252,252,255,255,255,
+255,255,0,0,0,74,0,0,0,77,255,255,255,255,250,250,250,255,251,251,251,255,181,
+181,181,255,255,255,255,255,244,244,244,255,247,247,247,255,250,250,250,255,251,
+251,251,255,252,252,252,255,252,252,252,255,253,253,253,255,253,253,253,255,255,
+255,255,255,0,0,0,74,0,0,0,77,255,255,255,255,250,250,250,255,252,252,252,255,
+181,181,181,255,255,255,255,255,245,246,246,255,249,249,249,255,251,251,251,255,
+252,252,252,255,248,248,248,255,228,228,228,255,234,234,233,255,243,243,243,255,
+241,243,244,254,0,0,0,70,0,0,0,75,251,251,251,254,255,255,255,255,255,255,255,
+255,183,183,183,255,255,255,255,255,247,247,247,255,250,250,250,255,251,251,251,
+255,253,253,253,255,228,228,228,255,254,254,254,255,254,254,254,255,244,244,243,
+255,111,111,111,185,0,0,0,20,0,0,0,20,0,0,0,93,0,0,0,98,0,0,0,98,0,0,0,142,255,
+255,255,255,248,248,248,255,250,250,250,255,252,252,252,255,253,253,253,255,231,
+232,231,255,254,254,254,255,243,243,243,255,108,109,108,203,0,0,0,52,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,255,255,255,255,249,249,249,255,251,
+251,251,255,252,252,252,255,254,254,254,255,234,235,234,255,243,243,243,255,115,
+115,114,208,0,0,0,78,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,
+251,251,251,254,255,255,255,255,255,255,255,255,255,255,255,255,250,252,253,255,
+230,234,235,255,121,122,121,206,0,0,0,71,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,18,0,0,0,87,0,0,0,91,0,0,0,91,0,0,0,91,0,0,0,91,0,0,0,
+90,0,0,0,40,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0};
+MGL_EXPORT Fl_RGB_Image img_copy(idata_copy, 16, 16, 4, 0);
+
+static const unsigned char idata_paste[] =
+{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,74,227,227,227,255,218,218,218,255,218,218,
+218,255,230,230,230,255,0,0,0,79,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,37,37,37,65,58,58,58,248,12,12,12,255,213,213,213,255,133,133,133,
+254,255,255,255,255,255,255,255,255,132,132,132,254,213,213,213,255,7,7,7,255,
+59,59,59,244,43,43,43,69,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,35,35,35,233,75,75,75,
+254,20,20,20,255,255,255,255,255,243,243,243,255,236,236,236,255,236,236,236,
+255,243,243,243,255,255,255,255,255,31,31,31,255,74,74,74,254,37,37,37,249,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,35,35,35,255,38,38,38,255,204,204,204,255,175,175,
+175,255,176,176,176,255,176,176,176,255,176,176,176,255,176,176,176,255,176,176,
+176,255,206,206,206,255,26,26,26,255,34,34,34,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,34,34,34,255,34,34,34,255,255,255,255,255,243,243,243,255,245,245,245,255,
+246,246,246,255,228,228,228,255,182,182,182,255,182,182,182,255,205,205,205,255,
+7,7,7,255,17,17,17,255,0,0,0,97,0,0,0,106,0,0,0,106,1,1,1,66,31,31,31,255,37,
+37,37,255,255,255,255,255,240,240,240,255,242,242,242,255,243,243,243,255,174,
+174,174,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,254,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,111,30,30,30,
+255,37,37,37,255,255,255,255,255,241,241,241,255,243,243,243,255,245,245,245,
+255,176,176,176,255,255,255,255,255,221,222,223,255,226,227,227,255,229,230,231,
+255,232,233,233,255,234,235,235,255,235,236,236,255,248,249,249,255,0,0,0,111,
+27,27,27,255,38,38,38,255,255,255,255,255,241,241,241,255,244,244,244,255,245,
+245,245,255,177,177,177,255,255,255,255,255,227,229,229,255,233,234,234,255,236,
+237,237,255,238,239,239,255,240,241,241,255,241,242,242,255,255,255,255,255,0,0,
+0,111,23,23,23,255,38,38,38,255,255,255,255,255,243,243,243,255,244,244,244,
+255,246,246,246,255,179,179,179,255,255,255,255,255,233,234,234,255,237,238,238,
+255,240,241,241,255,243,243,243,255,245,245,245,255,246,246,246,255,255,255,255,
+255,0,0,0,111,22,22,22,255,37,37,37,255,255,255,255,255,243,243,243,255,245,245,
+245,255,248,248,248,255,181,181,181,255,255,255,255,255,237,237,237,255,241,241,
+241,255,244,244,244,255,247,247,247,255,249,249,249,255,250,250,250,255,255,255,
+255,255,0,0,0,111,24,24,24,255,36,36,36,255,255,255,255,255,244,244,244,255,246,
+246,246,255,249,249,249,255,182,182,182,255,255,255,255,255,240,241,241,255,244,
+245,245,255,248,248,248,255,251,251,251,255,253,253,253,255,254,254,254,255,255,
+255,255,255,0,0,0,111,28,28,28,255,33,33,33,255,255,255,255,255,243,243,243,255,
+246,246,246,255,250,250,250,255,183,183,183,255,255,255,255,255,242,243,243,255,
+247,247,247,255,225,225,225,255,179,180,179,255,179,179,179,255,184,184,184,255,
+218,218,218,255,0,0,0,112,35,35,35,255,30,30,30,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,197,197,197,255,255,255,255,255,244,245,245,
+255,250,250,250,255,222,222,222,255,202,202,202,255,255,255,255,254,255,255,255,
+255,102,103,102,225,0,0,0,49,39,39,39,255,57,57,57,255,49,49,49,255,62,62,62,
+255,69,69,69,255,73,73,73,255,40,40,40,255,255,255,255,255,246,246,246,255,251,
+251,251,255,220,220,221,255,200,200,200,255,252,252,251,255,76,77,76,216,0,0,0,
+49,0,0,0,0,104,109,109,247,46,46,46,255,50,50,50,255,49,49,49,255,48,48,48,255,
+49,49,49,255,22,22,22,255,255,255,255,255,255,255,255,255,255,255,255,255,227,
+229,229,255,187,187,187,255,53,53,53,215,0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,44,0,0,0,111,0,0,0,110,0,0,0,110,0,0,
+0,110,0,0,0,110,0,0,0,29,0,0,0,0,0,0,0,0,0,0,0,0};
+MGL_EXPORT Fl_RGB_Image img_paste(idata_paste, 16, 16, 4, 0);
+
+static const unsigned char idata_find[] =
+{255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,0,0,0,98,0,0,0,204,0,0,0,129,255,255,255,0,
+255,255,255,0,0,0,0,129,0,0,0,204,0,0,0,98,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,0,0,0,25,31,31,31,
+252,106,106,106,255,36,36,36,255,0,0,0,41,0,0,0,38,36,36,36,255,106,106,106,255,
+31,31,31,252,0,0,0,25,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,0,0,0,71,0,0,0,209,44,44,44,255,45,45,45,255,22,22,22,255,18,18,
+18,246,18,18,18,246,22,22,22,255,43,43,43,255,44,44,44,255,0,0,0,209,0,0,0,71,
+255,255,255,0,255,255,255,0,255,255,255,0,0,0,0,36,27,27,27,251,115,115,115,255,
+43,43,43,255,74,74,74,255,23,23,23,255,105,105,105,255,86,86,86,255,23,23,23,
+255,74,74,74,255,43,43,43,255,115,115,115,255,27,27,27,251,0,0,0,36,255,255,255,
+0,255,255,255,0,0,0,0,165,54,54,54,255,77,77,77,255,105,105,105,255,50,50,50,
+255,78,78,78,255,19,19,19,255,1,1,1,255,77,77,77,255,50,50,50,255,105,105,105,
+255,77,77,77,255,54,54,54,255,0,0,0,165,255,255,255,0,0,0,0,71,21,21,21,255,104,
+104,104,255,129,126,125,255,120,120,120,255,35,35,35,255,39,39,39,255,24,24,24,
+255,24,24,24,255,39,39,39,255,35,35,35,255,120,120,120,255,129,126,125,255,104,
+104,104,255,21,21,21,255,0,0,0,71,0,0,0,190,85,83,82,255,54,42,36,255,56,40,31,
+255,89,72,61,255,114,112,111,255,28,28,28,255,40,40,40,255,40,40,40,255,27,27,
+27,255,114,112,111,255,89,72,61,255,56,40,31,255,54,42,36,255,85,83,82,255,0,0,
+0,190,10,10,10,236,60,48,40,255,83,51,28,255,144,97,61,255,135,91,59,255,104,
+88,77,255,23,23,23,255,1,1,1,207,1,1,1,207,23,23,23,255,104,88,77,255,132,87,
+52,255,145,98,63,255,83,51,28,255,57,44,37,255,4,4,4,235,0,0,0,237,54,40,31,
+255,72,33,0,255,134,67,11,255,144,73,11,255,118,98,82,255,14,14,14,246,0,0,0,19,
+0,0,0,19,14,14,14,246,118,98,82,255,144,73,11,255,132,64,7,255,78,41,9,255,54,
+40,30,255,0,0,0,237,0,0,0,142,38,37,35,255,105,87,70,255,149,114,84,255,171,
+145,122,255,69,66,64,255,0,0,0,147,255,255,255,0,255,255,255,0,0,0,0,147,69,66,
+64,255,171,145,122,255,149,114,84,255,105,87,70,255,38,37,35,255,0,0,0,142,0,0,
+0,8,0,0,0,152,17,17,17,243,52,50,49,255,11,11,11,244,0,0,0,157,0,0,0,10,255,
+255,255,0,255,255,255,0,0,0,0,10,0,0,0,157,11,11,11,244,52,50,49,255,16,16,16,
+243,0,0,0,152,0,0,0,8,255,255,255,0,255,255,255,0,0,0,0,1,0,0,0,20,0,0,0,1,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+0,0,0,1,0,0,0,20,0,0,0,1,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0};
+MGL_EXPORT Fl_RGB_Image img_find(idata_find, 16, 16, 4, 0);
+
+static const unsigned char idata_prop[] =
+{0,0,0,0,153,153,153,172,129,129,129,255,129,129,129,255,129,129,129,255,
+129,129,129,255,129,129,129,255,129,129,129,255,129,129,129,255,129,129,129,255,
+129,129,129,255,129,129,129,255,129,129,129,255,129,129,129,255,129,129,129,86,
+0,0,0,0,0,0,0,0,129,129,129,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,129,129,129,
+255,0,0,0,0,0,0,0,0,129,129,129,255,255,255,255,255,236,236,236,255,234,234,234,
+255,234,234,234,255,235,235,235,255,235,235,235,255,235,235,235,255,236,236,236,
+255,236,236,236,255,237,237,237,255,240,240,240,255,255,255,255,255,129,129,129,
+255,0,0,0,0,0,0,0,0,129,129,129,255,255,255,255,255,234,234,234,255,196,196,196,
+255,197,197,197,255,197,197,197,255,198,198,198,255,198,198,198,255,198,198,198,
+255,198,198,198,255,199,199,199,255,240,240,240,255,255,255,255,255,129,129,129,
+255,0,0,0,0,0,0,0,0,129,129,129,255,255,255,255,255,234,234,234,255,235,235,235,
+255,235,235,235,255,105,105,105,255,105,105,105,255,105,105,105,255,210,210,210,
+255,237,237,237,255,238,238,238,255,240,240,240,255,255,255,255,255,129,129,129,
+255,0,0,0,0,0,0,0,0,129,129,129,255,255,255,255,255,235,235,235,255,197,197,197,
+255,198,198,198,255,176,176,176,255,88,88,88,255,88,88,88,255,88,88,88,255,198,
+198,198,255,199,199,199,255,240,240,240,255,255,255,255,255,129,129,129,255,0,0,
+0,0,0,0,0,0,129,129,129,255,255,255,255,255,235,235,235,255,105,105,105,255,
+210,210,210,255,236,236,236,255,210,210,210,255,105,105,105,255,105,105,102,255,
+236,236,236,255,238,238,238,255,240,240,240,255,255,255,255,255,129,129,129,255,
+0,0,0,0,0,0,0,0,129,129,129,255,255,255,255,255,235,235,235,255,88,88,88,255,
+88,88,88,255,176,176,176,255,88,88,88,255,106,106,106,255,106,106,106,255,210,
+210,204,255,238,238,238,255,240,240,240,255,255,255,255,255,129,129,129,255,0,0,
+0,0,0,0,0,0,129,129,129,255,255,255,255,255,236,236,236,255,105,105,105,255,
+105,105,105,255,105,105,105,255,106,106,106,255,106,106,106,255,106,106,106,255,
+106,106,106,255,214,214,214,255,240,240,240,255,255,255,255,255,129,129,129,255,
+0,0,0,0,0,0,0,0,129,129,129,255,255,255,255,255,236,236,236,255,176,176,176,
+255,88,88,88,255,88,88,88,255,88,88,88,255,88,88,88,255,89,89,89,255,98,98,98,
+255,108,108,108,255,220,220,220,255,255,255,255,255,129,129,129,255,0,0,0,0,0,0,
+0,0,129,129,129,255,255,255,255,255,236,236,236,255,237,237,237,255,238,238,
+238,255,238,238,238,255,239,239,239,255,212,212,212,255,119,119,119,255,133,133,
+133,255,144,144,144,255,157,157,157,255,255,255,255,255,129,129,129,255,0,0,0,0,
+0,0,0,0,129,129,129,255,255,255,255,255,237,237,237,255,198,198,198,255,199,
+199,199,255,199,199,199,255,200,200,200,255,200,200,200,255,181,181,181,255,146,
+146,146,255,158,158,158,255,171,171,171,255,255,255,255,255,129,129,129,255,0,0,
+0,0,0,0,0,0,129,129,129,255,255,255,255,255,237,237,237,255,237,237,237,255,
+238,238,238,255,239,239,239,255,239,239,239,255,240,240,240,255,240,240,240,255,
+224,224,224,255,173,173,173,255,186,186,186,255,255,255,255,255,129,129,129,255,
+0,0,0,0,0,0,0,0,129,129,129,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,129,129,129,
+255,0,0,0,0,0,0,0,0,149,149,149,180,129,129,129,255,129,129,129,255,129,129,129,
+255,129,129,129,255,129,129,129,255,129,129,129,255,129,129,129,255,129,129,129,
+255,129,129,129,255,129,129,129,255,129,129,129,255,129,129,129,255,149,149,149,
+168,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+MGL_EXPORT Fl_RGB_Image img_prop(idata_prop, 16, 16, 4, 0);
+
+static const unsigned char idata_alpha[] =
+{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,71,101,107,40,57,81,85,160,58,81,
+85,153,58,81,85,153,56,79,84,160,81,111,117,36,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,76,106,113,219,104,146,156,254,184,
+255,255,255,177,249,255,255,177,249,255,255,183,255,255,255,107,147,156,254,17,
+63,74,171,0,0,0,19,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,54,76,81,75,124,173,
+185,255,180,252,255,254,132,186,200,255,81,88,91,255,120,136,140,255,121,137,
+141,255,77,77,77,255,23,176,214,254,44,224,255,255,29,153,184,250,9,48,57,62,0,
+0,0,4,0,0,0,0,0,0,0,8,31,40,43,141,161,226,243,253,171,240,255,255,172,242,
+255,255,101,129,135,255,225,255,255,255,215,248,255,255,215,249,255,255,215,247,
+255,255,66,132,148,255,40,214,255,255,42,214,255,255,38,195,234,250,26,136,162,
+186,0,0,0,12,0,0,0,10,52,105,116,225,123,184,198,254,159,222,238,255,151,212,
+227,255,194,226,233,255,214,248,255,255,215,248,255,255,215,248,255,255,214,248,
+255,255,197,230,237,255,45,183,218,255,42,209,251,255,35,191,230,254,11,106,129,
+249,0,44,55,38,0,0,0,0,6,20,24,74,66,176,204,255,77,176,200,254,58,87,92,255,
+123,135,138,255,125,138,142,255,125,138,142,255,125,138,142,255,125,138,142,255,
+125,138,141,255,59,74,78,255,5,134,165,255,0,190,237,255,0,90,112,172,6,0,0,0,0,
+0,0,0,0,0,0,0,49,127,147,138,86,223,255,255,71,174,199,255,122,221,246,255,
+129,236,255,255,129,236,255,255,129,236,255,255,129,236,255,255,132,240,255,255,
+47,126,144,255,0,219,255,255,0,148,185,255,0,0,0,19,0,0,0,0,0,0,0,0,38,99,115,
+0,0,0,0,16,63,164,188,232,76,197,228,254,114,209,231,255,127,228,254,255,128,
+229,255,255,128,229,255,255,128,229,255,255,120,209,232,255,14,171,209,255,0,
+187,234,255,0,86,107,86,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,38,44,111,81,
+212,244,255,58,120,136,254,133,238,255,255,127,228,254,255,128,229,255,255,128,
+229,255,255,96,192,216,255,0,183,230,255,0,150,187,215,0,0,0,15,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,81,213,245,0,0,0,0,0,33,87,100,194,63,167,192,255,112,198,220,
+255,128,229,255,255,128,229,255,255,131,236,255,255,55,133,153,254,0,177,222,
+255,0,0,0,61,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,23,27,23,
+74,197,228,243,68,123,137,254,130,232,255,255,128,229,255,255,132,228,253,255,
+0,118,150,255,0,85,106,181,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,10,26,30,130,79,197,226,255,117,209,232,255,129,231,255,
+255,89,139,152,254,0,177,223,244,0,0,0,27,0,56,71,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,35,92,105,241,107,196,218,255,130,
+230,255,254,20,128,153,255,0,40,48,121,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,55,64,49,44,91,101,251,116,
+214,240,255,7,79,97,240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,19,53,63,182,103,184,201,251,
+6,0,0,26,0,63,79,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,25,28,144,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+MGL_EXPORT Fl_RGB_Image img_alpha(idata_alpha, 16, 16, 4, 0);
+
+static const unsigned char idata_light[] =
+{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,36,0,242,236,7,1,
+252,199,57,2,204,204,0,0,248,246,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,230,7,2,0,0,0,0,254,201,68,7,253,218,31,9,
+253,207,49,17,255,200,59,4,251,234,19,12,255,230,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,255,246,0,0,255,204,38,1,254,218,34,13,253,207,37,19,
+254,199,43,40,253,204,30,62,253,203,33,68,254,200,42,51,253,220,20,23,253,199,
+68,8,255,200,69,4,252,214,35,1,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,250,203,62,
+3,251,213,35,18,254,196,48,44,253,204,26,107,240,182,37,162,240,188,75,212,
+240,189,79,211,241,185,49,188,250,198,22,99,254,199,36,38,254,204,57,27,251,215,
+38,7,255,247,0,0,0,0,0,0,0,0,0,0,255,248,0,1,254,238,15,10,254,198,50,48,248,
+193,26,135,235,176,68,232,244,210,126,255,246,219,125,255,246,220,125,255,245,
+215,127,255,237,188,89,239,245,186,25,153,254,203,41,62,251,228,20,15,248,240,0,
+2,0,0,0,0,0,0,0,0,255,197,62,3,254,193,54,14,254,207,22,81,230,154,14,226,243,
+207,91,255,247,223,99,255,249,230,104,255,249,231,105,255,248,226,101,255,244,
+213,93,255,232,166,32,242,250,205,15,97,252,226,9,17,252,220,39,13,249,247,6,1,
+255,255,64,0,253,201,67,6,254,195,55,43,243,181,24,155,231,160,3,255,245,214,60,
+255,249,231,78,255,251,238,82,255,251,238,83,255,250,234,80,255,247,222,69,255,
+236,182,14,255,237,172,14,182,254,195,52,63,254,198,69,18,253,197,51,2,255,255,
+0,0,253,225,22,5,253,206,30,39,235,164,11,174,236,178,6,255,245,217,28,255,
+250,235,46,255,252,242,54,255,252,243,55,255,251,237,49,255,247,224,33,255,240,
+195,13,255,233,164,9,205,254,198,39,54,251,196,58,3,255,0,0,0,252,196,86,1,253,
+198,66,13,254,202,43,50,236,168,12,172,236,179,6,255,246,219,28,255,250,236,44,
+255,253,246,63,255,253,249,66,255,251,240,49,255,248,225,33,255,240,196,13,255,
+234,167,11,206,253,194,46,65,253,187,70,17,251,181,61,3,255,255,0,1,252,233,18,
+9,253,210,41,40,247,193,25,144,231,162,3,253,244,210,24,255,250,236,75,255,
+253,247,114,255,253,248,117,255,251,240,84,255,246,219,34,255,236,181,7,255,240,
+180,20,176,254,211,37,68,253,223,35,20,253,248,0,3,248,248,3,1,253,225,30,13,
+254,206,48,21,254,199,36,63,232,161,8,194,237,184,11,255,248,226,80,255,253,246,
+150,255,253,247,155,255,249,232,93,255,240,198,21,255,231,164,7,222,253,202,31,
+97,253,205,50,39,252,218,41,16,248,235,15,3,0,0,0,0,255,128,0,0,254,201,66,3,
+254,194,51,21,252,198,39,114,233,165,8,195,233,173,17,253,242,204,61,255,243,
+208,66,255,236,182,24,254,232,167,7,213,250,192,36,123,254,191,58,51,252,212,42,
+6,251,229,23,7,255,255,0,0,0,0,0,0,0,0,0,0,255,203,80,2,254,204,61,24,253,208,
+39,28,254,205,32,72,247,195,24,131,237,171,19,171,236,170,16,166,245,190,26,
+154,254,204,36,103,255,192,53,35,254,195,68,20,253,196,65,7,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,255,204,82,0,255,236,19,2,253,218,40,6,252,221,28,20,254,200,54,
+47,254,193,56,45,254,191,46,35,254,206,49,57,253,206,44,36,254,216,46,15,255,
+186,57,2,255,219,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,253,236,
+13,3,251,231,17,8,254,198,66,7,254,198,74,9,255,188,53,2,254,223,34,17,250,214,
+41,12,252,233,28,6,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,251,243,0,1,255,210,78,1,255,170,85,0,0,0,0,0,247,238,5,2,255,
+255,0,0,255,255,0,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+MGL_EXPORT Fl_RGB_Image img_light(idata_light, 16, 16, 4, 0);
+
+static const unsigned char idata_grid[] =
+{0,0,0,0,21,21,21,11,0,0,0,51,0,0,0,50,0,0,0,50,0,0,0,50,0,0,0,50,0,0,0,50,
+0,0,0,50,0,0,0,50,0,0,0,50,0,0,0,50,0,0,0,50,0,0,0,51,21,21,21,11,0,0,0,0,0,0,
+0,0,0,0,0,63,255,255,255,255,255,255,255,255,244,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,244,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,244,255,255,255,255,255,255,255,0,0,0,63,0,0,0,0,0,0,0,0,0,0,0,
+62,255,255,255,255,225,224,220,255,170,199,233,255,223,223,224,255,224,225,226,
+255,232,229,227,255,174,203,236,255,230,231,231,255,231,232,232,255,238,237,232,
+255,176,206,238,255,255,255,255,255,0,0,0,62,0,0,0,0,0,0,0,0,0,0,0,62,255,255,
+255,255,236,231,226,255,223,232,243,255,237,235,232,255,236,234,230,255,246,241,
+235,255,226,237,247,255,245,242,238,255,243,240,237,255,251,245,240,255,228,237,
+246,255,255,255,255,255,0,0,0,62,0,0,0,0,0,0,0,0,0,0,0,61,244,255,255,255,220,
+230,241,255,0,98,255,255,226,235,244,255,178,207,239,255,227,237,246,255,0,98,
+255,255,229,238,247,255,183,212,243,255,230,238,248,255,0,97,255,255,250,255,
+255,255,0,0,0,62,0,0,0,0,0,0,0,0,0,0,0,61,255,255,255,255,235,232,230,255,226,
+235,244,255,239,238,236,255,237,237,237,255,246,243,239,255,229,238,248,255,245,
+244,242,255,242,242,242,255,251,248,244,255,231,240,250,255,255,255,255,255,0,0,
+0,62,0,0,0,0,0,0,0,0,0,0,0,61,255,255,255,255,234,232,228,255,179,208,240,255,
+236,236,236,255,238,239,239,255,246,242,239,255,184,213,245,255,244,243,243,255,
+244,244,244,255,252,249,245,255,187,215,248,255,255,255,255,255,0,0,0,62,0,0,0,
+0,0,0,0,0,0,0,0,61,255,255,255,255,243,240,233,255,227,237,247,255,246,244,
+240,255,246,243,240,255,255,248,243,255,231,240,250,255,254,250,246,255,254,251,
+246,255,255,255,248,255,233,242,252,255,255,255,255,255,0,0,0,62,0,0,0,0,0,0,0,
+0,0,0,0,61,244,255,255,255,225,235,245,255,0,98,255,255,230,238,248,255,184,
+213,245,255,231,240,250,255,0,97,255,255,233,242,252,255,189,217,250,255,234,
+243,252,255,0,96,255,255,250,255,255,255,0,0,0,62,0,0,0,0,0,0,0,0,0,0,0,61,255,
+255,255,255,243,240,236,255,229,238,248,255,246,245,243,255,244,244,244,255,255,
+250,246,255,233,242,252,255,253,252,250,255,251,250,250,255,255,255,251,255,235,
+243,253,255,255,255,255,255,0,0,0,62,0,0,0,0,0,0,0,0,0,0,0,61,255,255,255,255,
+243,240,236,255,183,212,244,255,244,243,243,255,244,245,245,255,254,252,247,255,
+190,218,251,255,251,250,250,255,251,251,251,255,255,255,252,255,193,221,253,255,
+255,255,255,255,0,0,0,62,0,0,0,0,0,0,0,0,0,0,0,61,255,255,255,255,250,246,239,
+255,230,239,249,255,252,249,245,255,253,251,246,255,255,255,249,255,234,243,253,
+255,255,255,251,255,255,255,252,255,255,255,253,255,236,244,254,255,255,255,255,
+255,0,0,0,62,0,0,0,0,0,0,0,0,0,0,0,61,243,255,255,255,228,237,247,255,0,97,255,
+255,232,241,251,255,189,218,249,255,234,243,252,255,0,96,255,255,235,244,254,
+255,193,221,253,255,236,244,254,255,0,96,255,255,250,255,255,255,0,0,0,62,0,0,0,
+0,0,0,0,0,0,0,0,61,255,255,255,255,246,244,240,255,231,239,250,255,250,248,
+246,255,249,248,248,255,255,254,250,255,235,243,253,255,255,254,253,255,254,254,
+253,255,255,255,254,255,233,241,251,255,255,255,255,255,0,0,0,62,0,0,0,0,0,0,0,
+0,0,0,0,62,255,255,255,255,255,255,255,255,211,240,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,210,239,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,209,239,255,255,255,255,255,255,0,0,0,63,0,0,0,0,0,0,0,0,16,16,
+16,15,0,0,0,64,0,0,0,62,0,0,0,62,0,0,0,62,0,0,0,62,0,0,0,62,0,0,0,62,0,0,0,62,
+0,0,0,62,0,0,0,61,0,0,0,61,0,0,0,62,16,16,16,13,0,0,0,0};
+MGL_EXPORT Fl_RGB_Image img_grid(idata_grid, 16, 16, 4, 0);
+
+static const unsigned char idata_move[] =
+{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,6,5,0,8,9,8,1,10,11,10,0,7,7,7,67,7,7,7,
+89,13,14,13,0,10,10,10,2,8,8,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,1,2,1,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,4,100,101,100,206,114,114,114,
+243,0,0,0,30,0,0,0,0,0,0,0,1,1,1,1,0,2,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,42,43,42,0,45,46,45,2,21,22,22,0,12,12,12,113,190,192,188,255,223,225,
+221,255,45,45,45,170,220,221,220,0,251,253,250,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,33,35,33,0,21,22,21,0,0,0,0,3,0,0,0,0,0,0,0,35,126,127,124,239,236,
+239,232,254,233,237,230,249,165,166,164,255,0,0,0,95,0,0,0,0,20,21,19,5,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,51,50,2,17,18,17,2,0,0,0,0,0,0,0,64,70,72,
+69,235,185,187,183,253,216,218,215,255,102,103,101,241,13,14,13,106,23,24,23,0,
+33,35,33,2,87,87,87,1,13,13,13,2,39,40,39,0,16,17,16,1,41,42,41,2,10,10,10,0,4,
+4,4,61,7,7,7,93,0,0,0,0,0,0,0,11,51,51,50,145,71,72,71,172,0,0,0,24,0,0,0,0,
+11,11,11,69,12,12,12,114,0,0,0,1,0,0,0,0,19,19,19,2,0,0,0,0,0,0,0,8,18,19,18,
+133,139,140,138,253,105,107,105,235,0,0,0,26,0,0,0,0,0,0,0,37,0,0,0,73,181,183,
+179,3,255,255,255,0,68,69,68,187,165,167,164,255,63,64,63,195,0,0,0,45,0,0,0,0,
+0,0,0,57,90,90,90,219,196,198,194,255,246,249,244,250,220,221,219,255,68,69,
+68,179,0,0,0,17,101,103,100,228,163,165,162,255,22,23,22,112,18,19,19,112,184,
+185,183,255,242,245,239,248,224,227,222,255,138,139,138,252,12,13,12,131,0,0,0,
+67,100,101,100,229,202,204,200,255,238,241,235,251,211,213,210,255,62,63,62,
+181,0,0,0,20,108,110,108,231,172,174,170,255,24,25,24,119,2,3,2,93,157,159,156,
+255,243,246,239,251,206,208,203,255,130,130,129,237,12,13,12,112,0,0,0,0,0,0,0,
+11,25,26,25,132,139,141,137,248,95,97,94,242,0,0,0,33,0,0,0,0,0,0,0,47,0,0,0,
+88,94,96,93,4,251,255,248,0,52,53,52,183,136,138,135,255,47,48,47,155,0,0,0,23,
+0,0,0,0,16,16,16,1,38,38,38,2,10,11,10,0,4,5,4,49,8,8,8,96,0,0,0,0,0,0,0,19,
+58,58,58,160,82,82,82,186,0,0,0,34,0,0,0,0,4,5,4,54,2,2,2,65,8,8,8,0,60,61,60,
+1,33,34,33,2,0,0,0,0,0,0,0,0,64,65,64,2,20,21,20,2,0,0,0,0,0,0,0,69,79,81,78,
+246,195,197,194,254,224,226,222,254,113,114,112,251,13,14,13,116,24,25,24,0,45,
+47,45,2,78,79,78,2,0,0,0,1,0,0,0,0,98,104,97,0,29,31,29,0,21,22,21,0,0,0,0,3,0,
+0,0,0,0,0,0,28,121,123,120,232,233,236,230,255,232,236,229,249,160,161,159,
+255,0,0,0,85,0,0,0,0,8,9,8,4,24,26,24,0,59,63,58,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,32,33,32,0,33,34,33,2,6,7,7,0,3,3,3,104,186,187,184,255,220,221,218,255,
+36,37,37,160,132,133,132,0,160,162,160,1,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,1,2,1,0,18,23,18,0,0,0,0,0,255,255,255,0,0,0,0,0,92,93,92,199,
+104,104,104,237,0,0,0,23,0,0,0,0,0,0,0,1,0,0,0,0,3,4,3,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,4,4,4,1,4,5,4,0,3,3,3,56,3,3,3,75,6,6,6,0,4,
+5,4,1,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+MGL_EXPORT Fl_RGB_Image img_move(idata_move, 16, 16, 4, 0);
+
+static const unsigned char idata_orig[] =
+{0,0,0,0,0,0,0,0,0,0,0,0,236,236,236,46,233,233,231,171,179,182,185,231,161,
+165,170,246,175,178,181,222,205,205,202,157,197,196,195,24,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,244,243,240,135,168,173,182,255,
+163,174,186,237,226,233,241,240,243,249,255,238,207,217,230,233,151,163,183,231,
+150,155,161,255,177,178,173,90,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+236,236,232,112,154,164,179,245,221,232,245,232,228,237,249,225,228,238,249,219,
+227,237,249,215,225,236,250,213,219,232,249,214,198,215,237,219,140,148,157,251,
+175,175,172,64,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,205,208,208,5,181,186,192,
+252,198,212,234,222,218,231,247,211,236,249,255,195,226,239,251,190,226,240,251,
+183,224,240,250,180,231,249,255,176,209,226,246,196,160,183,216,207,185,187,189,
+233,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,207,207,204,101,149,166,188,229,204,222,245,
+204,233,250,255,177,51,73,104,255,250,255,255,147,250,255,255,135,255,255,255,
+128,53,74,105,255,245,255,255,181,196,218,246,189,127,143,164,231,124,125,119,
+55,0,0,0,0,0,0,0,0,0,0,0,0,197,196,191,156,106,138,187,195,195,218,247,178,137,
+160,180,184,106,132,168,245,255,255,255,101,61,82,111,232,126,153,168,129,102,
+130,166,239,216,255,255,87,164,203,242,139,103,130,168,201,106,107,99,110,0,0,0,
+0,0,0,0,0,0,0,0,0,184,183,178,158,92,132,188,184,114,169,230,125,254,255,255,
+176,93,121,157,238,211,255,255,31,255,255,255,141,255,255,255,148,94,122,159,
+236,214,255,255,47,161,209,245,111,114,142,178,197,93,92,84,113,0,0,0,0,0,0,0,0,
+0,0,0,0,169,169,164,112,111,139,180,203,124,176,232,133,173,243,255,68,97,124,
+159,244,255,255,255,19,50,72,102,219,0,0,0,0,100,127,164,243,227,255,255,39,182,
+222,249,119,110,128,150,221,81,83,77,61,0,0,0,0,0,0,0,0,0,0,0,0,137,138,137,13,
+147,156,168,248,145,185,233,163,179,235,255,87,91,118,154,248,243,255,255,18,
+255,255,255,151,0,0,0,0,95,121,159,247,244,255,255,51,176,213,253,146,100,105,
+106,239,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,201,199,195,136,174,192,214,223,
+135,187,239,125,255,255,255,168,179,245,251,38,176,249,255,14,0,136,184,1,255,
+255,255,158,214,244,255,119,125,140,156,225,78,78,72,84,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,136,137,134,0,0,0,0,0,146,146,140,170,102,123,146,221,118,174,237,128,
+179,231,255,91,215,255,255,75,225,255,255,86,186,221,251,127,117,129,141,231,
+126,126,121,235,121,123,120,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,118,
+115,0,0,0,0,0,101,102,96,76,91,92,88,207,93,103,112,245,100,112,125,233,99,107,
+114,246,93,94,88,193,56,57,51,39,205,205,205,208,191,191,190,255,104,107,102,89,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,87,89,83,0,0,0,0,0,0,0,0,0,85,
+87,83,11,0,0,0,0,0,0,0,0,122,123,122,0,87,87,87,36,216,217,216,255,173,174,171,
+255,93,94,91,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,115,115,115,69,223,224,223,255,158,
+159,156,255,72,74,71,23,102,104,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,134,134,134,110,226,227,
+226,255,145,147,144,237,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,156,156,156,142,204,
+205,204,241,56,59,55,9};
+MGL_EXPORT Fl_RGB_Image img_orig(idata_orig, 16, 16, 4, 0);
+
+static const unsigned char idata_update[] =
+{255,255,255,0,255,255,255,0,255,255,255,0,52,101,164,29,58,105,167,159,58,
+106,167,222,54,103,165,246,57,105,167,229,58,106,167,188,52,101,164,83,52,101,
+164,5,255,255,255,0,255,255,255,0,255,255,255,0,52,101,164,121,52,101,164,16,
+255,255,255,0,255,255,255,0,53,101,164,80,56,104,166,246,104,144,192,250,143,
+176,211,255,168,194,223,255,168,193,222,255,147,177,212,255,95,135,185,244,55,
+103,165,240,52,101,164,88,255,255,255,0,53,102,164,102,52,101,164,255,52,101,
+164,15,255,255,255,0,52,101,164,41,57,105,166,245,140,173,211,255,157,189,220,
+255,161,190,221,255,180,203,229,255,191,211,233,255,204,221,238,255,213,226,240,
+255,191,210,231,255,75,119,175,245,54,103,165,192,67,113,171,247,53,102,164,252,
+52,101,164,14,255,255,255,0,57,105,167,155,105,144,192,253,114,152,197,255,60,
+107,168,255,53,102,164,255,58,106,167,252,93,133,183,243,161,187,217,254,216,
+228,241,255,219,230,242,255,221,232,243,255,136,167,206,253,200,216,234,255,58,
+106,167,249,52,101,164,13,255,255,255,0,56,104,166,243,65,112,171,255,60,108,
+169,254,58,106,167,245,52,101,164,117,52,101,164,25,52,101,164,69,56,105,166,
+205,97,136,185,245,205,219,235,255,226,235,245,255,230,238,246,255,230,238,246,
+255,58,106,167,250,52,101,164,11,255,255,255,0,53,101,164,254,58,106,167,251,
+104,145,199,157,55,103,165,230,52,101,164,35,255,255,255,0,255,255,255,0,255,
+255,255,0,52,101,164,96,53,102,164,255,199,215,233,255,198,216,235,255,227,236,
+245,255,58,106,166,250,52,101,164,10,255,255,255,0,52,101,164,252,76,121,179,
+126,118,157,207,43,87,131,187,19,52,101,164,2,255,255,255,0,255,255,255,0,52,
+101,164,4,56,104,166,196,143,172,208,250,231,238,246,255,219,230,242,255,230,
+238,246,255,58,106,166,251,52,101,164,9,255,255,255,0,52,101,164,13,255,255,255,
+0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,52,
+101,164,160,52,101,164,255,71,116,173,248,76,119,175,247,76,119,175,247,76,120,
+175,247,52,101,164,255,52,101,164,8,255,255,255,0,52,101,164,249,52,101,164,254,
+52,101,164,254,52,101,164,253,52,101,164,252,52,101,164,251,52,101,164,185,52,
+101,164,29,52,101,164,24,52,101,164,24,52,101,164,24,52,101,164,24,52,101,164,
+24,52,101,164,28,255,255,255,0,255,255,255,0,52,101,164,252,229,237,245,255,
+229,237,246,255,228,236,245,255,156,183,215,253,55,104,166,224,52,101,164,16,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,126,164,213,26,114,153,
+205,57,52,101,164,252,52,101,164,12,255,255,255,0,53,102,164,252,230,238,246,
+255,196,215,235,255,201,217,234,255,52,101,164,254,52,101,164,106,255,255,255,0,
+255,255,255,0,255,255,255,0,52,101,164,11,53,102,165,233,108,149,201,141,83,127,
+183,194,52,101,164,255,52,101,164,5,255,255,255,0,55,103,165,253,230,238,246,
+255,227,236,245,255,228,237,245,255,193,210,230,255,77,121,176,245,56,105,166,
+202,52,101,164,54,255,255,255,0,52,101,164,106,60,107,169,237,79,124,182,255,58,
+106,167,254,55,104,165,250,255,255,255,0,255,255,255,0,56,104,166,253,216,228,
+241,255,149,178,212,254,224,233,244,255,221,232,243,255,204,220,237,255,143,173,
+210,254,76,120,176,245,53,102,165,251,57,105,166,255,57,105,166,254,61,109,169,
+255,76,120,176,255,58,106,167,168,255,255,255,0,255,255,255,0,55,103,165,254,91,
+132,183,247,54,103,165,212,78,122,177,244,180,202,227,255,201,218,236,255,188,
+209,231,255,176,201,227,255,160,190,222,255,136,171,210,255,130,165,206,255,142,
+174,211,255,56,104,166,245,52,101,164,42,255,255,255,0,255,255,255,0,52,101,164,
+255,54,103,165,147,255,255,255,0,52,101,164,84,55,103,166,238,85,128,181,243,
+132,166,206,255,151,182,216,255,153,185,219,255,138,172,211,255,109,148,194,252,
+56,104,166,246,53,102,164,91,255,255,255,0,255,255,255,0,255,255,255,0,52,101,
+164,162,52,101,164,1,255,255,255,0,255,255,255,0,52,101,164,5,52,101,164,83,58,
+106,167,190,56,105,166,233,53,102,164,250,58,106,167,228,59,107,167,170,52,101,
+164,36,255,255,255,0,255,255,255,0,255,255,255,0};
+MGL_EXPORT Fl_RGB_Image img_update(idata_update, 16, 16, 4, 0);
+
+static const unsigned char idata_stop[] =
+{255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,222,0,0,46,205,0,0,214,211,36,
+36,225,218,72,72,230,223,95,95,233,218,72,72,230,212,32,32,217,222,0,0,46,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,222,0,0,46,201,30,30,243,226,164,163,255,233,182,181,255,234,183,
+183,255,234,185,185,255,233,181,180,255,227,167,167,255,201,30,30,243,222,0,0,
+46,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,222,0,
+0,46,193,28,27,243,224,154,154,255,230,143,142,255,229,140,139,255,229,136,
+135,255,227,133,132,255,225,128,127,255,222,126,125,255,221,144,144,255,193,27,
+26,243,222,0,0,46,255,255,255,0,255,255,255,0,255,255,255,0,222,0,0,46,189,24,
+23,244,224,157,155,255,227,134,133,255,231,140,139,255,232,137,136,255,230,122,
+121,255,230,119,118,255,229,126,125,255,226,125,124,255,220,109,108,255,223,147,
+145,255,190,24,24,244,222,0,0,46,255,255,255,0,255,255,255,0,189,4,4,215,221,
+149,146,255,226,126,125,255,230,132,131,255,251,232,232,255,251,230,229,255,233,
+120,118,255,233,116,114,255,250,226,226,255,251,230,230,255,226,110,108,255,218,
+96,94,255,222,148,144,255,189,4,4,215,255,255,255,0,255,255,255,0,180,0,0,224,
+209,95,90,255,225,111,110,255,231,117,116,255,251,226,226,255,255,255,255,255,
+251,227,226,255,250,226,225,255,255,255,255,255,250,223,222,255,229,93,91,255,
+222,79,77,255,211,93,88,255,180,0,0,224,255,255,255,0,255,255,255,0,174,0,0,225,
+209,85,78,255,227,97,95,255,234,94,92,255,233,103,100,255,250,225,224,255,255,
+255,255,255,255,255,255,255,250,226,225,255,235,114,112,255,237,122,120,255,235,
+122,120,255,215,96,89,255,174,0,0,225,255,255,255,0,255,255,255,0,170,0,0,226,
+191,26,13,255,216,30,26,255,224,41,37,255,227,71,67,255,249,222,221,255,255,255,
+255,255,255,255,255,255,249,221,220,255,224,66,62,255,220,18,13,255,217,5,0,255,
+199,14,0,255,170,0,0,226,255,255,255,0,255,255,255,0,164,0,0,226,190,16,0,255,
+216,5,0,255,219,26,21,255,248,211,210,255,255,255,255,255,247,211,210,255,247,
+211,210,255,255,255,255,255,247,211,210,255,218,27,21,255,218,5,0,255,201,17,0,
+255,164,0,0,226,255,255,255,0,255,255,255,0,163,0,0,219,181,19,0,255,216,5,0,
+255,219,26,21,255,248,211,210,255,248,211,210,255,218,27,21,255,216,25,19,255,
+247,208,207,255,249,214,213,255,217,27,21,255,218,5,0,255,187,20,0,255,163,0,0,
+219,255,255,255,0,255,255,255,0,206,0,0,47,145,5,0,246,191,18,0,255,218,5,0,255,
+220,27,21,255,220,27,21,255,224,7,0,255,225,7,0,255,220,25,18,255,220,28,23,255,
+220,6,0,255,192,18,0,255,145,5,0,246,206,0,0,47,255,255,255,0,255,255,255,0,255,
+255,255,0,206,0,0,47,140,6,0,246,191,20,0,255,220,6,0,255,221,6,0,255,223,7,0,
+255,224,7,0,255,223,7,0,255,221,6,0,255,193,22,1,255,140,6,0,246,206,0,0,47,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,206,0,0,47,
+137,6,0,246,176,4,0,255,203,16,11,255,208,24,19,255,211,28,23,255,208,24,19,255,
+188,24,20,255,137,6,0,246,206,0,0,47,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,206,0,0,47,149,0,0,222,
+154,23,23,231,162,41,41,233,164,47,47,233,162,41,41,233,158,20,20,224,206,0,0,
+47,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0};
+MGL_EXPORT Fl_RGB_Image img_stop(idata_stop, 16, 16, 4, 0);
+
+static const unsigned char idata_insert[] =
+{0,0,0,0,78,143,204,170,73,141,199,255,73,141,199,255,73,141,199,255,73,141,
+199,255,73,141,199,255,73,141,199,255,73,141,199,255,73,141,199,255,73,141,199,
+255,73,141,199,255,73,141,199,255,73,141,199,255,78,143,204,170,0,0,0,0,0,0,0,0,
+73,141,199,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,75,144,203,255,0,0,0,0,0,0,0,0,
+73,141,199,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,254,254,254,255,75,144,203,255,0,0,0,0,0,0,0,0,
+73,141,199,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,75,144,203,255,75,144,203,255,75,144,203,255,75,144,203,255,75,
+144,203,255,255,255,255,255,254,254,254,255,75,144,203,255,0,0,0,0,0,0,0,0,73,
+141,199,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,250,191,186,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,254,254,254,255,75,144,203,255,0,0,0,0,0,0,0,0,73,
+141,199,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,162,35,32,255,249,183,179,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,75,144,203,255,0,0,0,0,0,0,0,0,73,
+141,199,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,162,35,32,255,146,27,24,255,249,181,177,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,75,144,203,255,0,0,0,0,0,0,0,0,73,141,
+199,255,252,210,210,255,244,154,154,255,230,118,116,255,213,86,83,255,190,57,54,
+255,162,35,32,255,146,27,24,255,146,27,24,255,248,179,176,255,255,255,255,255,
+255,255,255,255,255,255,255,255,75,144,203,255,0,0,0,0,0,0,0,0,73,141,199,255,
+252,210,210,255,244,154,152,255,230,118,116,255,212,85,82,255,190,57,54,255,162,
+35,32,255,146,27,24,255,146,27,24,255,146,27,24,255,248,178,174,255,255,255,
+255,255,254,254,254,255,75,144,203,255,0,0,0,0,0,0,0,0,73,141,199,255,252,210,
+210,255,243,157,153,255,230,117,114,255,212,85,82,255,190,57,54,255,162,35,32,
+255,146,27,24,255,146,27,24,255,146,27,24,255,146,27,24,255,248,176,172,255,254,
+254,254,255,75,144,203,255,0,0,0,0,0,0,0,0,73,141,199,255,252,210,210,255,243,
+155,151,255,230,119,114,255,211,86,83,255,190,57,54,255,162,35,32,255,146,27,24,
+255,146,27,24,255,146,27,24,255,248,174,170,255,255,255,255,255,254,254,254,255,
+75,144,203,255,0,0,0,0,0,0,0,0,73,141,199,255,252,210,210,255,243,151,149,255,
+229,116,113,255,211,84,81,255,190,57,54,255,162,35,32,255,146,27,24,255,146,27,
+24,255,248,174,172,255,255,255,255,255,255,255,255,255,255,255,255,255,75,144,
+203,255,0,0,0,0,0,0,0,0,73,141,199,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,162,35,32,255,146,27,24,255,248,177,172,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,75,144,203,
+255,0,0,0,0,0,0,0,0,73,141,199,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,162,35,32,255,248,177,172,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,75,144,203,
+255,0,0,0,0,0,0,0,0,73,141,199,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,251,202,199,255,254,254,254,255,254,254,254,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,75,144,203,
+255,0,0,0,0,0,0,0,0,78,143,204,170,75,144,203,255,75,144,203,255,75,144,203,255,
+75,144,203,255,75,144,203,255,75,144,203,255,75,144,203,255,75,144,203,255,75,
+144,203,255,75,144,203,255,75,144,203,255,75,144,203,255,76,142,204,170,0,0,0,0};
+MGL_EXPORT Fl_RGB_Image img_insert(idata_insert, 16, 16, 4, 0);
+
+static const unsigned char idata_print[] =
+{255,255,255,0,255,255,255,0,255,255,255,0,0,0,0,10,0,0,0,28,0,0,0,28,0,0,0,
+28,0,0,0,28,0,0,0,28,0,0,0,28,0,0,0,28,0,0,0,28,0,0,0,11,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,0,0,0,79,170,170,
+170,192,171,171,171,191,171,171,171,191,171,171,171,191,171,171,171,191,171,171,
+171,191,171,171,171,191,170,170,170,192,0,0,0,78,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,0,0,0,93,253,253,253,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,0,0,0,93,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,0,0,0,93,245,245,246,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,0,0,0,93,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,136,136,136,232,229,229,232,255,
+243,243,244,255,251,251,251,255,255,255,255,255,255,255,255,255,255,255,255,255,
+251,251,251,255,243,243,244,255,136,136,136,232,255,255,255,0,255,255,255,0,255,
+255,255,0,136,136,136,53,136,136,136,255,147,147,147,255,145,145,145,255,211,
+211,215,255,225,225,228,255,235,235,237,255,241,241,242,255,243,243,244,255,241,
+241,242,255,235,235,237,255,225,225,228,255,145,145,145,255,164,164,164,255,147,
+147,147,255,136,136,136,53,136,136,136,159,145,145,145,255,164,164,164,255,135,
+135,135,255,189,189,194,255,203,203,207,255,214,214,217,255,220,220,223,255,222,
+222,225,255,220,220,223,255,214,214,217,255,203,203,207,255,136,136,136,255,183,
+183,183,255,164,164,164,255,145,145,145,159,180,180,180,227,239,239,239,255,239,
+239,239,255,116,116,116,255,91,91,91,255,91,91,91,255,89,89,89,255,87,87,87,255,
+87,87,87,255,89,89,89,255,91,91,91,255,91,91,91,255,119,119,119,255,239,239,
+239,255,239,239,239,255,180,180,180,227,183,183,183,231,248,248,248,255,248,248,
+248,255,116,116,116,255,78,78,78,255,78,78,78,255,96,96,96,255,98,98,98,255,98,
+98,98,255,96,96,96,255,78,78,78,255,78,78,78,255,119,119,119,255,248,248,248,
+255,248,248,248,255,183,183,183,231,169,169,169,246,202,202,202,255,202,202,202,
+255,172,172,172,255,175,175,175,255,175,175,175,255,156,156,156,255,149,149,149,
+255,149,149,149,255,156,156,156,255,175,175,175,255,175,175,175,255,172,172,172,
+255,202,202,202,255,202,202,202,255,169,169,169,246,174,174,174,231,229,229,229,
+255,226,226,226,255,197,197,197,255,193,193,193,255,192,192,192,255,191,191,191,
+255,190,190,190,255,190,190,190,255,191,191,191,255,192,192,192,255,193,193,193,
+255,197,197,197,255,226,226,226,255,193,193,193,255,174,174,174,231,164,164,164,
+231,204,204,204,255,153,153,153,255,9,9,9,255,7,7,7,255,7,7,7,255,7,7,7,255,7,7,
+7,255,7,7,7,255,7,7,7,255,7,7,7,255,7,7,7,255,9,9,9,255,153,153,153,255,178,
+178,177,255,164,164,164,231,136,136,136,223,136,136,136,255,100,100,100,255,90,
+90,90,255,102,102,106,255,173,173,179,255,182,182,188,255,188,188,193,255,190,
+190,195,255,188,188,193,255,182,182,188,255,110,110,113,255,90,90,90,255,100,
+100,100,255,136,136,136,255,136,136,136,223,255,255,255,0,255,255,255,0,255,255,
+255,0,121,121,121,255,158,158,161,255,216,216,219,255,226,226,228,255,231,231,
+233,255,233,233,235,255,231,231,233,255,226,226,228,255,169,169,171,255,121,121,
+121,255,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,122,122,122,255,222,222,224,255,245,245,246,255,252,252,253,255,
+255,255,255,255,255,255,255,255,255,255,255,255,252,252,253,255,235,235,236,255,
+122,122,122,255,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,0,0,0,32,0,0,0,83,0,0,0,83,0,0,0,83,0,0,0,83,0,0,0,83,0,0,0,
+83,0,0,0,83,0,0,0,83,0,0,0,32,255,255,255,0,255,255,255,0,255,255,255,0};
+MGL_EXPORT Fl_RGB_Image img_print(idata_print, 16, 16, 4, 0);
+
+static const unsigned char idata_goL[] =
+{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,39,90,167,0,37,89,164,90,36,86,161,125,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,37,87,161,14,35,82,153,164,32,77,144,255,31,74,138,255,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+38,89,165,55,34,82,152,221,71,111,161,255,150,183,211,255,24,58,108,255,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,38,89,166,2,
+37,88,164,121,41,89,161,250,111,148,188,255,173,205,227,255,174,205,227,255,18,
+43,82,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,
+89,165,27,37,87,163,189,60,106,170,255,140,173,206,255,162,193,218,255,163,194,
+219,255,163,195,220,255,12,30,58,255,14,36,68,255,17,44,84,255,21,54,103,255,22,
+57,110,255,20,54,105,240,0,0,0,0,0,0,0,0,37,88,163,78,38,88,161,235,86,126,177,
+255,143,175,203,255,149,180,208,255,152,183,212,255,154,185,214,255,154,186,215,
+255,154,186,215,255,153,184,213,255,150,181,210,255,145,176,204,255,139,169,196,
+255,18,49,96,255,0,0,0,0,35,84,157,145,44,90,156,254,102,136,175,255,128,159,
+189,255,134,166,197,255,139,171,203,255,143,176,208,255,146,179,212,255,148,181,
+213,255,148,181,213,255,146,179,212,255,142,174,207,255,130,162,196,255,90,122,
+162,255,15,45,88,255,0,0,0,0,33,79,147,145,40,81,141,254,85,117,157,255,108,139,
+175,255,122,154,189,255,130,163,199,255,136,169,206,255,139,173,209,255,138,172,
+210,255,133,167,208,255,122,157,202,255,103,140,189,255,76,113,166,255,55,89,
+140,255,13,40,80,255,0,0,0,0,0,0,0,0,28,68,127,76,26,63,119,234,39,74,126,255,
+68,104,157,255,84,121,175,255,95,133,187,255,104,141,194,255,109,146,199,255,
+111,148,201,255,108,145,199,255,100,137,191,255,83,121,175,255,58,93,145,255,10,
+35,72,255,0,0,0,0,0,0,0,0,0,0,0,0,23,57,108,24,21,53,101,184,32,64,112,255,78,
+114,167,255,100,137,191,255,111,148,201,255,119,155,208,255,6,16,32,255,7,21,41,
+255,8,26,53,255,10,32,65,255,10,34,69,255,8,31,64,240,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,18,49,93,1,17,46,88,114,20,46,86,248,71,103,149,255,116,153,205,255,128,
+163,215,255,7,20,40,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,38,74,48,11,32,64,214,49,74,110,255,122,
+155,204,255,7,23,46,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,31,62,10,9,28,56,152,7,26,52,255,7,
+24,50,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,26,54,78,7,27,55,160,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0};
+MGL_EXPORT Fl_RGB_Image img_goL(idata_goL, 16, 16, 4, 0);
+
+static const unsigned char idata_goU[] =
+{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,36,85,159,133,33,
+80,149,130,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,88,164,72,50,96,162,254,46,88,147,253,
+28,68,129,68,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,38,89,166,23,38,87,161,232,138,172,202,255,136,169,198,
+255,27,65,121,230,23,58,111,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,39,91,169,1,37,88,163,183,89,127,174,255,152,183,205,
+255,152,183,205,255,86,118,156,255,21,54,103,178,18,48,92,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,89,165,113,54,99,163,255,135,
+166,192,255,139,168,194,255,138,168,194,255,135,164,190,255,45,76,118,255,18,46,
+89,108,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,88,164,49,38,
+87,158,248,110,142,178,255,128,158,188,255,130,160,189,255,129,160,189,255,126,
+156,186,255,110,140,171,255,22,50,90,246,15,40,79,44,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,33,77,143,13,30,72,135,218,74,110,154,255,117,148,182,255,121,
+152,187,255,123,154,189,255,123,154,189,255,120,151,186,255,115,146,180,255,75,
+104,140,255,14,39,76,210,12,36,72,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27,63,116,
+164,42,74,119,255,102,135,172,255,111,144,182,255,117,150,189,255,120,153,192,
+255,118,152,192,255,104,138,182,255,83,117,164,255,56,89,139,255,21,49,89,255,
+11,34,68,144,0,0,0,0,0,0,0,0,0,0,0,0,25,60,111,85,21,48,90,255,56,87,130,255,
+80,115,163,255,89,125,176,255,96,132,184,255,98,135,188,255,95,132,187,255,90,
+127,182,255,79,116,170,255,64,100,152,255,42,75,123,255,9,32,65,254,7,29,60,68,
+0,0,0,0,0,0,0,0,22,53,99,118,16,39,73,255,12,27,50,255,8,18,32,255,7,12,20,
+255,103,140,194,255,110,146,200,255,111,148,200,255,105,142,195,255,16,40,74,
+255,14,40,77,255,12,37,73,255,8,30,62,255,8,29,59,152,0,0,0,0,0,0,0,0,25,60,111,
+0,21,52,97,18,18,44,83,20,15,38,72,21,4,10,20,255,115,151,204,255,125,161,213,
+255,127,163,214,255,118,154,207,255,11,33,66,255,12,35,71,13,10,35,69,12,8,29,
+62,12,8,29,60,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,24,47,255,
+122,158,210,255,138,173,224,255,143,178,228,255,129,165,216,255,11,34,68,255,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+14,37,71,255,122,158,210,255,141,176,226,255,150,184,234,255,130,166,216,255,
+11,36,72,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,18,48,93,255,110,146,200,255,124,160,212,255,127,163,215,255,
+114,151,204,255,10,34,69,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,54,104,242,21,54,101,255,19,50,94,255,18,45,
+86,255,15,40,77,255,8,31,64,242,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,51,99,6,17,47,93,12,15,42,84,12,11,38,76,
+12,9,33,68,12,8,30,62,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+MGL_EXPORT Fl_RGB_Image img_goU(idata_goU, 16, 16, 4, 0);
+
+static const unsigned char idata_zoomIn[] =
+{0,0,0,0,0,0,0,0,0,0,0,0,236,236,236,46,233,233,231,171,179,182,185,231,161,
+165,170,246,175,178,181,222,205,205,202,157,197,196,195,24,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,236,235,233,135,169,174,183,255,
+167,177,189,237,224,231,240,240,250,255,255,236,205,215,229,233,154,166,185,231,
+151,156,162,255,172,173,169,90,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+228,228,225,112,156,166,180,245,220,230,243,232,227,236,248,225,239,248,255,217,
+60,82,112,255,235,246,255,211,218,231,247,214,197,213,235,219,141,149,158,251,
+171,171,169,64,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,205,208,208,5,180,185,192,
+252,198,212,233,222,217,230,246,211,222,235,249,200,233,246,255,187,124,149,179,
+240,232,246,255,177,216,233,249,183,208,225,245,196,162,184,215,207,182,185,187,
+233,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,207,207,204,101,152,168,190,229,200,218,242,
+203,223,242,255,180,234,252,255,162,255,255,255,141,115,142,172,231,255,255,255,
+126,237,255,255,136,240,254,255,181,193,215,243,188,127,143,165,231,120,121,116,
+55,0,0,0,0,0,0,0,0,0,0,0,0,197,196,191,156,108,141,188,194,217,240,255,196,49,
+65,86,233,79,102,131,209,71,94,123,201,148,168,192,255,59,83,115,189,59,85,117,
+187,34,52,73,216,209,240,255,164,103,130,167,199,104,105,98,110,0,0,0,0,0,0,0,0,
+0,0,0,0,184,183,178,158,93,132,188,183,168,206,239,161,231,255,255,162,238,
+255,255,146,253,255,255,131,113,141,172,229,255,255,255,126,241,255,255,135,243,
+255,255,142,194,228,247,146,113,140,176,195,91,91,84,113,0,0,0,0,0,0,0,0,0,0,0,
+0,169,169,164,112,113,141,181,203,123,174,230,131,160,220,245,79,182,245,251,
+48,224,255,255,25,103,132,165,210,255,255,255,11,187,246,252,29,184,246,252,45,
+179,219,246,116,110,128,150,221,79,81,76,61,0,0,0,0,0,0,0,0,0,0,0,0,137,138,137,
+13,146,156,168,248,146,185,232,163,166,216,245,97,189,247,252,54,239,255,255,
+26,92,121,157,205,255,255,255,5,199,248,253,24,209,251,253,63,175,211,248,146,
+100,105,107,239,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,195,193,190,136,171,189,
+211,223,143,190,238,130,179,236,249,70,160,240,249,29,254,255,255,255,0,0,0,0,
+227,253,254,49,214,242,255,125,127,141,157,225,78,79,74,84,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,136,137,134,0,0,0,0,0,143,144,139,170,104,124,147,221,127,177,235,
+134,177,228,255,92,198,248,255,59,219,252,255,86,185,219,246,133,120,132,142,
+231,127,127,123,235,120,122,119,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,
+118,115,0,0,0,0,0,99,100,95,76,91,93,90,207,93,104,113,245,101,113,126,233,100,
+108,115,246,94,95,90,193,60,62,56,39,200,200,200,208,187,187,186,255,104,106,
+102,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,87,89,83,0,0,0,0,0,0,0,0,
+0,82,84,80,11,0,0,0,0,0,0,0,0,122,123,122,0,89,89,89,36,210,211,210,255,170,
+171,169,255,93,94,91,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,114,114,114,69,217,218,217,
+255,156,157,154,255,73,75,72,23,102,104,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,132,132,132,110,
+220,221,220,255,143,145,142,237,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,156,156,156,
+142,204,205,204,241,56,59,55,9};
+MGL_EXPORT Fl_RGB_Image img_zoomIn(idata_zoomIn, 16, 16, 4, 0);
+
+static const unsigned char idata_zoomOut[] =
+{0,0,0,0,0,0,0,0,227,228,227,0,0,0,0,0,238,237,235,74,225,226,225,185,172,
+176,180,237,161,165,171,245,182,185,186,214,204,203,200,139,194,196,195,7,255,
+255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,221,221,220,0,0,0,0,0,236,235,
+233,181,156,164,175,249,172,181,194,237,234,241,249,240,240,245,255,238,195,205,
+220,231,147,158,178,233,154,158,162,248,170,171,168,52,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,231,231,227,167,142,154,173,234,233,242,253,232,229,
+237,249,224,229,238,249,219,227,237,249,215,224,235,249,214,220,233,249,215,182,
+199,223,219,149,154,159,252,150,152,148,24,143,145,142,0,0,0,0,0,0,0,0,0,204,
+204,203,0,219,219,217,44,166,174,186,251,215,228,247,222,218,231,246,209,222,
+236,250,198,226,239,250,189,226,241,251,183,223,238,250,180,214,231,248,184,207,
+225,245,199,141,163,195,211,204,204,200,189,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,213,
+211,205,152,146,167,197,217,202,220,243,199,229,247,255,177,240,255,255,159,249,
+255,255,144,253,255,255,135,250,255,255,132,241,255,255,142,244,255,255,188,173,
+201,239,183,132,142,153,249,0,4,0,6,0,0,0,0,0,0,0,0,0,0,0,0,194,195,191,208,105,
+143,199,184,224,247,255,193,38,54,77,231,72,95,126,208,68,91,122,204,63,87,118,
+199,55,81,113,192,50,77,111,186,26,43,65,219,205,238,255,168,97,116,143,223,105,
+106,100,59,0,0,0,0,0,0,0,0,0,0,0,0,182,181,179,209,79,129,198,166,175,213,244,
+155,239,255,255,159,245,255,255,144,246,255,255,135,247,255,255,131,248,255,255,
+132,247,255,255,136,247,255,255,145,193,228,250,156,102,120,145,220,91,92,86,61,
+0,0,0,0,0,0,0,0,0,0,0,0,174,172,165,165,95,136,193,182,127,180,234,122,166,
+228,247,71,182,244,252,47,184,246,252,33,185,246,252,23,185,246,252,22,185,246,
+252,31,183,246,252,50,171,211,248,132,99,111,123,244,73,75,71,9,0,0,0,0,0,0,0,0,
+165,166,164,0,157,156,153,60,138,155,178,231,160,195,239,157,168,223,246,85,191,
+247,252,51,196,247,252,34,203,249,254,20,204,250,253,15,198,248,253,28,214,251,
+253,77,163,198,240,162,93,93,89,203,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,202,
+202,199,190,163,186,218,205,142,193,239,117,186,244,252,63,195,248,253,40,202,
+249,254,19,225,252,255,9,232,255,255,62,202,233,255,136,112,121,129,242,77,78,
+74,38,85,87,83,0,0,0,0,0,0,0,0,0,0,0,0,0,139,140,138,0,0,0,0,0,140,140,138,208,
+103,128,161,202,135,190,249,123,186,235,255,86,216,255,255,74,219,253,255,91,
+177,208,236,147,109,117,122,244,138,139,135,198,110,112,108,67,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,119,121,118,0,0,0,0,0,101,101,94,106,91,94,92,220,95,
+105,116,243,100,113,125,234,99,106,111,244,91,91,85,175,0,0,0,15,215,215,215,
+255,169,170,168,255,88,90,84,44,155,157,158,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,86,81,10,0,0,0,0,0,0,0,0,0,0,0,0,120,120,120,
+78,227,227,227,255,153,154,152,252,64,65,61,18,101,103,99,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+138,138,138,121,230,230,228,255,142,143,140,233,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,152,152,152,166,225,226,225,255,132,133,130,190,153,154,151,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,93,
+93,93,0,0,0,0,0,179,179,179,185,190,191,188,206};
+MGL_EXPORT Fl_RGB_Image img_zoomOut(idata_zoomOut, 16, 16, 4, 0);
+
+static const unsigned char idata_goD[] =
+{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,34,82,153,1,34,82,154,226,34,81,152,243,33,80,151,243,33,79,149,243,
+32,78,147,243,31,77,144,223,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,32,78,146,2,32,78,145,255,133,162,188,255,134,163,189,
+255,135,164,190,255,135,164,190,255,29,72,135,253,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29,72,136,2,29,72,135,255,125,154,
+180,255,126,155,181,255,126,156,182,255,127,156,182,255,26,66,126,253,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,67,127,2,26,
+66,126,255,110,139,167,255,111,140,168,255,112,141,169,255,112,141,169,255,23,
+61,116,253,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,23,60,115,2,23,60,114,255,95,124,155,255,96,125,155,255,97,126,156,255,98,
+126,156,255,21,55,107,253,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22,59,
+113,116,22,57,110,243,21,55,105,244,20,53,102,244,20,52,101,255,82,111,145,255,
+85,114,147,255,86,115,148,255,85,114,147,255,18,50,97,255,17,49,95,243,17,48,
+93,243,16,46,91,243,15,45,89,146,0,0,0,0,0,0,0,0,20,53,103,96,18,50,97,255,52,
+81,120,255,65,94,131,255,74,104,141,255,83,114,151,255,88,118,156,255,89,120,
+158,255,87,118,155,255,80,110,147,255,68,98,135,255,46,75,114,255,13,41,82,255,
+13,41,82,81,0,0,0,0,0,0,0,0,17,48,93,0,15,43,85,175,27,54,94,255,56,87,130,255,
+71,104,148,255,81,115,161,255,87,121,168,255,85,120,167,255,76,111,159,255,59,
+93,142,255,38,70,119,255,17,45,87,255,11,36,73,156,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,13,38,75,19,11,34,68,228,37,68,112,255,68,104,156,255,83,120,175,255,92,
+129,184,255,93,131,185,255,86,124,178,255,73,110,163,255,44,75,122,255,9,32,65,
+217,9,33,67,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,29,59,65,12,32,60,253,
+76,112,163,255,102,140,194,255,115,152,204,255,117,154,206,255,108,144,198,255,
+84,120,172,255,14,36,68,250,8,30,62,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,5,19,39,136,30,50,78,255,114,151,203,255,136,171,222,255,140,
+175,226,255,122,158,210,255,36,57,88,255,6,23,48,122,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,18,39,6,4,14,29,203,68,92,128,255,131,
+167,218,255,137,172,223,255,75,99,135,255,4,15,31,194,6,21,44,3,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,13,27,38,7,14,24,
+243,84,116,162,255,86,118,164,255,7,14,23,240,4,13,27,32,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,9,19,97,
+15,25,39,255,14,23,37,255,2,9,17,91,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,11,24,164,3,
+11,24,160,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+MGL_EXPORT Fl_RGB_Image img_goD(idata_goD, 16, 16, 4, 0);
+
+static const unsigned char idata_goR[] =
+{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,255,255,255,3,193,207,228,170,41,92,167,88,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,44,85,146,255,67,107,165,255,35,82,153,164,37,87,162,14,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,24,59,111,255,185,213,231,255,135,167,200,255,49,93,158,220,37,89,
+165,54,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,18,45,84,255,166,196,218,255,160,191,215,255,151,181,
+209,255,75,118,176,250,37,88,164,120,38,90,167,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,78,104,142,240,22,57,110,255,21,56,107,255,18,46,89,255,15,38,72,255,13,32,
+61,255,150,180,208,255,147,178,207,255,145,176,205,255,144,174,202,255,101,138,
+184,255,43,92,165,189,37,88,165,26,0,0,0,0,0,0,0,0,0,0,0,0,19,50,97,255,138,164,
+190,255,135,164,193,255,138,168,199,255,139,170,202,255,139,171,203,255,138,170,
+204,255,137,169,202,255,134,166,199,255,130,162,194,255,125,156,188,255,110,143,
+180,255,56,101,166,235,37,88,163,78,0,0,0,0,0,0,0,0,20,49,92,255,110,140,173,
+255,116,148,184,255,124,157,194,255,128,162,200,255,131,165,203,255,131,165,203,
+255,129,162,201,255,125,158,196,255,119,152,190,255,113,145,182,255,107,137,173,
+255,87,116,154,255,39,79,139,254,35,84,157,143,0,0,0,0,20,48,87,255,81,113,156,
+255,99,133,177,255,111,146,191,255,117,152,198,255,119,154,200,255,117,153,199,
+255,112,148,195,255,104,140,189,255,92,128,177,255,76,111,160,255,53,88,138,255,
+43,76,125,255,31,68,125,254,33,79,147,143,223,255,255,0,23,50,85,255,62,99,147,
+255,85,124,176,255,100,141,193,255,110,150,200,255,114,153,203,255,109,146,199,
+255,104,141,195,255,95,133,187,255,84,122,176,255,73,110,162,255,58,94,143,255,
+31,67,121,234,28,68,128,77,0,0,0,0,204,235,247,12,41,65,94,237,11,35,70,255,11,
+34,68,255,10,29,56,255,8,23,43,255,16,33,48,255,120,157,208,255,112,149,202,
+255,101,139,192,255,92,133,185,255,54,90,137,255,23,55,104,186,23,58,109,25,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,39,59,255,128,
+166,216,255,118,156,208,255,96,139,185,255,35,66,106,249,18,46,89,116,19,49,95,
+2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,
+46,69,255,129,179,225,255,77,117,155,255,17,39,71,216,14,37,73,50,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,225,245,
+255,2,30,63,87,255,24,48,76,255,9,27,55,154,10,32,62,11,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154,240,255,3,
+36,71,96,158,7,26,54,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+MGL_EXPORT Fl_RGB_Image img_goR(idata_goR, 16, 16, 4, 0);
+
+static const unsigned char idata_next[] =
+{255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,0,0,0,1,0,78,0,135,0,68,0,18,255,255,255,0,0,0,0,1,0,78,0,135,0,66,0,18,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,0,80,0,9,60,115,60,255,44,104,
+44,238,0,76,0,52,0,80,0,9,69,129,69,255,51,113,51,237,0,72,0,50,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,0,80,0,9,57,117,57,255,112,166,112,254,61,124,61,249,0,79,0,
+104,64,130,64,255,131,193,131,254,69,131,69,249,0,78,0,96,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,0,
+80,0,9,45,117,45,255,88,150,88,255,93,159,93,255,73,144,73,252,57,133,57,255,
+107,178,107,255,112,181,112,255,82,148,82,252,8,84,8,154,0,128,0,1,255,255,255,
+0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,0,80,0,9,35,119,35,
+255,64,136,64,255,68,148,68,255,73,156,73,255,78,163,78,255,82,167,82,255,87,
+169,87,255,91,169,91,255,80,153,80,252,15,95,15,203,0,68,0,18,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,0,80,0,9,27,123,27,255,39,127,39,255,43,
+141,43,255,48,151,48,255,52,158,52,255,58,162,58,255,62,163,62,255,67,160,67,
+255,71,156,71,255,70,146,70,252,22,105,23,235,0,82,0,50,255,255,255,0,255,255,
+255,0,255,255,255,0,0,80,0,9,19,125,19,255,17,121,17,255,21,137,21,255,24,150,
+24,255,27,157,27,255,31,161,31,255,37,161,37,255,43,156,43,255,48,149,48,255,
+52,139,52,255,58,131,58,254,31,110,31,249,0,89,0,82,255,255,255,0,255,255,255,
+0,0,80,0,9,9,128,10,255,0,123,0,255,0,140,0,255,0,154,0,255,0,163,0,255,0,163,
+0,255,0,157,0,255,0,144,0,255,1,128,1,255,1,111,1,255,3,92,3,254,13,101,14,
+248,0,94,3,85,255,255,255,0,255,255,255,0,0,80,0,9,12,135,13,255,0,133,0,255,0,
+153,0,255,0,171,0,255,0,183,0,255,0,184,0,255,0,174,0,255,0,157,0,255,0,138,0,
+255,9,123,9,251,14,118,16,237,0,97,5,54,255,255,255,0,255,255,255,0,255,255,255,
+0,0,80,0,9,15,139,17,255,0,137,0,255,0,160,0,255,0,182,0,255,7,202,7,255,0,
+204,0,255,0,187,0,255,0,165,0,255,16,148,17,251,13,127,15,212,0,113,0,20,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,0,80,0,9,19,141,21,255,0,
+135,0,255,0,158,0,255,0,165,2,252,23,182,25,255,0,208,0,255,1,186,1,255,25,162,
+27,252,9,130,12,167,0,128,0,1,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,0,80,0,9,22,139,24,255,6,130,6,254,0,146,2,250,0,133,2,
+119,22,170,24,255,7,184,7,254,30,163,31,251,2,128,4,111,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,0,
+80,0,9,40,148,43,255,24,150,28,242,0,134,4,61,0,80,0,9,40,164,43,255,26,156,30,
+242,0,128,4,58,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,0,0,0,1,3,148,6,147,0,130,0,21,
+255,255,255,0,0,0,0,1,3,142,6,147,0,130,0,21,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0};
+MGL_EXPORT Fl_RGB_Image img_next(idata_next, 16, 16, 4, 0);
+
+static const unsigned char idata_play[] =
+{255,0,255,0,255,0,255,0,133,38,131,129,129,181,127,231,127,231,129,181,131,
+129,133,38,255,0,255,0,255,0,255,0,255,0,255,0,127,1,125,113,121,246,114,255,
+116,255,127,255,127,255,116,255,114,255,121,246,125,113,127,1,255,0,255,0,255,0,
+122,1,121,182,111,255,119,255,186,255,208,255,217,255,219,255,212,255,186,255,
+118,255,111,255,121,182,122,1,255,0,255,0,115,113,107,255,142,255,211,255,232,
+255,239,255,242,255,243,255,241,255,234,255,221,255,141,255,107,255,115,113,255,
+0,113,38,108,246,115,255,213,255,237,255,246,255,178,255,242,255,253,255,252,
+255,250,255,241,255,226,255,116,255,108,246,113,38,106,129,97,255,190,255,236,
+255,246,255,253,255,141,255,134,255,207,255,255,255,255,255,252,255,241,255,208,
+255,97,255,106,128,101,181,102,255,206,255,241,255,252,255,255,255,125,255,102,
+255,88,255,143,255,242,255,255,255,250,255,233,255,104,255,101,181,96,231,115,
+255,208,255,239,255,252,255,255,255,102,255,81,255,64,255,64,255,94,255,204,255,
+252,255,239,255,123,255,96,231,93,231,114,255,213,255,241,255,253,255,255,255,
+54,255,23,255,7,255,37,255,83,255,203,255,253,255,241,255,124,255,93,231,91,
+181,96,255,208,255,239,255,252,255,255,255,59,255,33,255,24,255,114,255,240,255,
+255,255,252,255,239,255,100,255,91,181,91,129,84,255,184,255,233,255,250,255,
+255,255,74,255,72,255,187,255,255,255,255,255,255,255,250,255,219,255,84,255,91,
+128,89,38,85,246,103,255,221,255,241,255,252,255,148,255,241,255,255,255,255,
+255,255,255,252,255,241,255,115,255,85,246,89,38,255,0,86,113,80,255,134,255,
+226,255,241,255,250,255,252,255,253,255,252,255,250,255,241,255,154,255,80,255,
+86,113,255,0,255,0,87,1,86,182,79,255,104,255,208,255,233,255,239,255,241,255,
+239,255,219,255,114,255,79,255,86,182,87,1,255,0,255,0,255,0,86,1,84,113,82,246,
+79,255,93,255,118,255,120,255,95,255,79,255,82,246,84,113,86,1,255,0,255,0,255,
+0,255,0,255,0,255,0,85,38,84,129,82,181,81,231,81,231,82,181,84,129,85,38,255,
+0,255,0,255,0,255,0};
+MGL_EXPORT Fl_RGB_Image img_play(idata_play, 16, 16, 2, 0);
+
+static const unsigned char idata_prev[] =
+{255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,0,66,0,18,0,78,0,135,0,0,0,1,255,255,255,0,0,68,0,18,0,
+78,0,135,0,0,0,1,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,0,72,0,50,51,113,51,237,69,
+129,69,255,0,80,0,9,0,76,0,52,44,106,44,238,60,116,60,255,0,80,0,9,255,255,255,
+0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,0,78,0,96,69,130,69,249,131,192,131,254,64,130,64,255,0,79,0,104,61,
+126,61,249,112,170,112,254,57,121,57,255,0,80,0,9,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,0,128,0,1,8,84,8,154,82,144,82,252,
+112,179,112,255,107,177,107,255,57,133,57,255,73,145,73,252,93,163,93,255,88,
+155,88,255,45,121,45,255,0,80,0,9,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,0,68,0,18,15,92,15,203,80,147,80,252,91,164,91,255,87,165,87,255,82,
+165,82,255,78,164,78,255,73,159,73,255,68,153,68,255,64,144,64,255,35,125,35,
+255,0,80,0,9,255,255,255,0,255,255,255,0,255,255,255,0,0,82,0,50,22,101,23,235,
+70,135,70,252,71,148,71,255,67,153,67,255,62,157,62,255,58,159,58,255,52,159,
+52,255,48,155,48,255,43,148,43,255,39,137,39,255,27,129,27,255,0,80,0,9,255,
+255,255,0,255,255,255,0,0,89,0,82,31,103,31,249,58,119,58,254,52,127,52,255,48,
+136,48,255,43,146,43,255,37,152,37,255,31,157,31,255,27,158,27,255,24,155,24,
+255,21,147,21,255,17,134,17,255,19,133,19,255,0,80,0,9,255,255,255,0,255,255,
+255,0,0,94,3,85,13,92,14,248,3,71,3,254,1,91,1,255,1,110,1,255,0,127,0,255,0,
+144,0,255,0,157,0,255,0,163,0,255,0,163,0,255,0,154,0,255,0,140,0,255,9,137,10,
+255,0,80,0,9,255,255,255,0,255,255,255,0,255,255,255,0,0,97,5,54,14,112,16,237,
+9,104,9,251,0,117,0,255,0,138,0,255,0,157,0,255,0,174,0,255,0,184,0,255,0,183,
+0,255,0,171,0,255,0,153,0,255,12,146,13,255,0,80,0,9,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,0,113,0,20,13,125,15,212,16,130,17,251,0,143,
+0,255,0,165,0,255,0,187,0,255,7,205,7,255,0,201,0,255,0,182,0,255,0,160,0,255,
+15,150,17,255,0,80,0,9,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,0,128,0,1,9,130,12,167,25,151,27,252,1,164,1,255,0,186,0,255,23,
+184,25,255,0,179,2,252,0,181,0,255,0,158,0,255,19,152,21,255,0,80,0,9,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,2,128,4,111,30,157,31,251,7,173,7,254,22,171,24,255,0,133,2,119,0,154,
+2,250,6,151,6,254,22,149,24,255,0,80,0,9,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,0,
+128,4,58,26,154,30,242,41,165,44,255,0,80,0,9,0,134,4,61,24,155,28,242,41,156,
+44,255,0,80,0,9,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,0,130,0,21,3,
+142,6,147,0,0,0,1,255,255,255,0,0,130,0,21,3,148,6,147,0,0,0,1,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0};
+MGL_EXPORT Fl_RGB_Image img_prev(idata_prev, 16, 16, 4, 0);
+
+static const unsigned char idata_plot[] =
+{0,0,0,0,121,121,121,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,121,121,121,39,
+123,123,123,157,125,125,125,39,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,126,180,255,69,133,185,255,48,0,0,0,0,121,121,
+121,118,123,123,123,157,125,125,125,118,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,103,165,254,25,110,169,250,168,120,175,251,220,131,
+183,255,50,0,0,0,0,0,0,0,0,125,125,125,157,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,156,251,75,96,160,249,234,107,167,250,133,116,
+174,255,9,0,0,0,0,0,0,0,0,0,0,0,0,127,127,127,157,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,77,150,252,7,83,152,248,224,92,158,251,64,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,126,126,126,157,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,73,145,247,109,79,149,248,178,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,120,120,120,157,125,125,125,217,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,184,42,77,62,184,38,78,51,59,140,249,11,68,142,247,230,76,149,252,47,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,126,126,126,157,0,0,0,0,0,0,0,0,184,
+43,74,3,181,42,76,128,180,39,79,233,180,35,84,224,66,125,230,135,63,141,248,
+167,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,124,125,125,157,0,0,
+0,0,182,43,73,24,180,41,75,189,180,39,80,189,181,38,83,24,183,33,94,154,131,
+70,156,251,58,140,250,38,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,120,
+120,120,157,122,124,123,217,181,40,71,52,181,42,76,229,181,40,81,128,184,38,84,
+3,0,0,0,0,52,117,233,133,167,38,124,254,185,25,119,69,0,0,0,0,0,0,0,0,0,0,0,0,
+188,14,158,56,189,13,162,42,0,0,0,0,0,0,0,0,123,125,124,157,182,39,76,48,184,39,
+80,62,0,0,0,0,0,0,0,0,28,119,245,23,35,124,247,236,141,55,157,99,184,23,130,
+224,185,21,138,14,0,0,0,0,186,14,158,65,185,13,160,233,189,12,165,53,0,0,0,0,0,
+0,0,0,124,124,123,157,0,0,0,0,0,0,0,0,8,107,246,28,13,108,243,121,24,114,242,
+218,32,121,245,139,0,0,0,0,184,20,139,153,183,17,144,153,183,13,156,64,185,12,
+161,233,187,11,166,62,0,0,0,0,0,0,0,0,120,120,120,157,125,124,122,217,6,105,246,
+49,9,105,243,184,9,105,243,236,11,106,243,152,20,114,245,57,29,121,250,0,0,0,0,
+0,188,18,150,14,183,14,154,224,184,12,162,235,186,10,166,63,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,124,123,121,157,4,103,244,47,6,103,242,88,6,104,244,9,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,186,8,163,51,186,7,166,56,0,0,0,0,123,125,123,
+118,125,125,125,39,0,0,0,0,0,0,0,0,127,126,125,157,125,124,122,157,125,123,120,
+157,125,124,122,217,126,125,124,157,126,126,126,157,125,125,125,217,126,126,126,
+157,124,126,124,157,122,124,122,217,123,125,123,157,123,125,123,157,123,123,123,
+157,123,123,123,157,121,121,121,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,120,120,120,
+157,0,0,0,0,0,0,0,0,120,120,120,157,0,0,0,0,0,0,0,0,120,120,120,157,0,0,0,0,0,0,
+0,0,121,121,121,118,121,121,121,39,0,0,0,0};
+MGL_EXPORT Fl_RGB_Image img_plot(idata_plot, 16, 16, 4, 0);
+
+static const unsigned char idata_system[] =
+{103,98,38,0,103,98,38,93,104,99,38,255,104,99,38,255,104,99,38,255,104,99,
+38,255,104,99,38,255,104,99,38,255,104,99,38,255,104,99,38,255,104,99,38,255,
+104,99,38,255,104,99,38,255,104,99,38,255,103,98,38,93,103,98,38,0,103,98,38,93,
+104,99,38,255,233,209,166,255,228,204,158,255,227,204,158,255,227,203,157,255,
+227,203,157,255,227,203,157,255,227,203,157,255,227,203,157,255,227,203,157,255,
+227,203,157,255,227,203,157,255,228,204,159,255,104,99,38,255,103,98,38,93,104,
+99,38,255,221,197,150,255,223,199,150,255,223,199,150,255,223,199,150,255,223,
+199,150,255,223,199,150,255,223,199,150,255,227,192,130,255,223,198,150,255,223,
+198,150,255,223,198,150,255,223,198,150,255,223,198,150,255,226,191,130,255,104,
+99,38,255,104,99,38,255,221,197,150,255,126,105,32,255,104,99,38,255,104,99,38,
+255,104,99,38,255,104,99,38,255,104,99,38,255,104,99,38,255,104,99,38,255,104,
+99,38,255,104,99,38,255,104,99,38,255,126,105,32,255,221,197,150,255,104,99,38,
+255,104,99,38,255,221,197,150,255,104,99,38,255,193,125,17,255,193,125,17,255,
+193,125,17,255,193,125,17,255,193,125,17,255,193,125,17,255,193,125,17,255,193,
+125,17,255,193,125,17,255,193,125,17,255,104,99,38,255,213,188,136,255,108,103,
+43,255,104,99,38,255,221,197,150,255,104,99,38,255,193,125,17,255,193,125,17,
+255,193,125,17,255,193,125,17,255,193,125,17,255,193,125,17,255,193,125,17,255,
+193,125,17,255,193,125,17,255,193,125,17,255,104,99,38,255,215,191,140,255,108,
+103,43,255,104,99,38,255,221,197,150,255,104,99,38,255,193,125,17,255,193,125,
+17,255,193,125,17,255,193,125,17,255,104,99,38,255,104,99,38,255,193,125,17,
+255,193,125,17,255,193,125,17,255,193,125,17,255,104,99,38,255,215,191,140,255,
+108,103,43,255,104,99,38,255,221,197,150,255,126,105,32,255,104,99,38,255,104,
+99,38,255,104,99,38,255,104,99,38,255,104,99,38,255,104,99,38,255,104,99,38,
+255,104,99,38,255,104,99,38,255,104,99,38,255,115,102,34,255,213,188,136,255,
+104,99,38,255,104,99,38,255,221,197,150,255,193,125,17,255,193,125,17,255,193,
+125,17,255,193,125,17,255,193,125,17,255,193,125,17,255,193,125,17,255,193,125,
+17,255,193,125,17,255,193,125,17,255,193,125,17,255,193,125,17,255,213,188,136,
+255,104,99,38,255,104,99,38,255,215,191,140,255,126,105,32,255,104,99,38,255,
+104,99,38,255,104,99,38,255,104,99,38,255,104,99,38,255,104,99,38,255,104,99,38,
+255,104,99,38,255,104,99,38,255,104,99,38,255,126,105,32,255,213,188,136,255,
+104,99,38,255,104,99,38,255,215,191,140,255,104,99,38,255,193,125,17,255,193,
+125,17,255,193,125,17,255,193,125,17,255,193,125,17,255,193,125,17,255,193,125,
+17,255,193,125,17,255,193,125,17,255,193,125,17,255,104,99,38,255,210,186,133,
+255,104,99,38,255,104,99,38,255,215,191,140,255,104,99,38,255,193,125,17,255,
+193,125,17,255,193,125,17,255,193,125,17,255,193,125,17,255,193,125,17,255,193,
+125,17,255,193,125,17,255,193,125,17,255,193,125,17,255,104,99,38,255,210,186,
+133,255,104,99,38,255,104,99,38,255,213,188,136,255,104,99,38,255,193,125,17,
+255,193,125,17,255,193,125,17,255,193,125,17,255,104,99,38,255,104,99,38,255,
+193,125,17,255,193,125,17,255,193,125,17,255,193,125,17,255,104,99,38,255,210,
+186,133,255,104,99,38,255,104,99,38,255,213,188,136,255,126,105,32,255,104,99,
+38,255,104,99,38,255,104,99,38,255,104,99,38,255,104,99,38,255,104,99,38,255,
+104,99,38,255,104,99,38,255,104,99,38,255,104,99,38,255,104,99,38,255,210,186,
+133,255,104,99,38,255,104,99,38,255,219,182,118,255,210,186,133,255,210,186,133,
+255,210,186,133,255,210,186,133,255,208,183,130,255,210,186,133,255,208,183,130,
+255,208,183,130,255,208,183,130,255,208,183,130,255,210,186,133,255,208,183,130,
+255,210,186,133,255,104,99,38,255,95,91,41,141,104,99,38,255,108,103,43,255,108,
+103,43,255,108,103,43,255,108,103,43,255,108,103,43,255,108,103,43,255,104,99,
+38,255,104,99,38,255,104,99,38,255,104,99,38,255,104,99,38,255,104,99,38,255,
+104,99,38,255,104,99,38,255};
+MGL_EXPORT Fl_RGB_Image img_system(idata_system, 16, 16, 4, 0);
+
+static const unsigned char idata_info[] =
+{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,75,119,134,58,74,119,225,56,73,
+120,252,56,74,121,253,58,75,119,227,61,76,118,141,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,56,73,119,33,59,76,120,226,164,173,195,255,
+237,239,244,255,252,252,253,255,247,249,251,255,226,231,239,255,154,165,190,255,
+62,78,121,233,61,77,118,38,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,60,
+77,120,230,208,213,224,255,245,248,250,213,232,239,244,170,226,234,243,164,217,
+227,238,168,211,223,235,178,216,226,237,217,185,196,214,255,65,81,123,240,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,61,77,118,142,164,173,195,255,245,248,250,
+214,239,243,247,160,244,247,250,159,235,240,246,162,223,232,242,166,212,224,237,
+170,194,211,228,167,197,213,229,211,141,156,184,255,67,81,119,162,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,64,80,122,237,237,239,244,255,232,239,245,172,243,247,250,
+159,250,252,253,157,236,241,247,161,223,231,242,164,208,221,235,164,193,210,228,
+165,120,157,196,138,197,210,225,255,70,85,127,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,57,74,121,253,250,251,253,255,224,233,242,165,238,243,248,178,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,193,204,215,193,89,136,185,
+123,206,219,233,255,57,75,122,254,97,100,113,2,0,0,0,0,0,0,0,0,0,0,0,0,58,75,
+122,254,244,247,250,255,214,225,237,167,222,231,241,167,255,255,255,255,235,240,
+245,201,224,230,236,204,210,218,226,200,145,174,205,145,83,130,182,125,201,214,
+231,255,57,75,122,254,97,100,113,11,0,0,0,0,0,0,0,0,0,0,0,0,69,84,126,244,224,
+229,237,255,203,217,232,173,200,215,232,158,255,255,255,255,192,208,227,151,181,
+202,224,150,157,185,214,144,92,137,186,123,96,142,188,140,181,199,219,255,72,88,
+131,249,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,74,87,122,186,152,164,189,255,212,224,
+236,215,166,190,216,147,255,255,255,255,165,190,216,148,135,168,204,135,91,137,
+185,122,75,126,178,128,170,193,217,214,126,145,177,255,84,96,131,215,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,97,100,113,10,71,87,128,247,183,194,213,255,195,211,228,
+211,119,157,197,138,255,255,255,255,82,129,181,126,94,141,186,141,169,192,217,
+214,155,174,200,255,73,89,133,250,97,100,113,27,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,79,88,115,77,71,87,128,249,140,155,184,255,194,208,224,255,204,217,
+232,255,199,214,229,255,181,198,218,255,126,144,178,255,74,90,134,251,89,98,124,
+106,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,97,100,113,19,88,99,
+131,221,75,91,131,252,166,172,152,255,167,173,152,255,171,177,152,255,94,104,
+128,243,97,100,113,31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,89,89,66,12,94,94,62,255,235,237,193,255,245,248,202,255,221,
+223,171,255,94,94,62,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,89,89,66,7,94,94,62,255,128,128,92,255,168,170,132,
+255,138,139,102,255,94,94,62,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,94,94,62,255,227,230,186,254,243,
+246,201,255,211,213,176,254,94,94,62,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,94,94,62,76,57,57,54,165,70,
+70,70,236,48,48,48,169,94,94,62,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+MGL_EXPORT Fl_RGB_Image img_info(idata_info, 16, 16, 4, 0);
+
+static const unsigned char idata_help[] =
+{0,0,0,0,141,143,138,137,137,139,134,252,136,138,133,255,136,138,133,255,
+136,138,133,255,136,138,133,255,136,138,133,255,136,138,133,255,136,138,133,255,
+136,138,133,255,136,138,133,255,136,138,133,255,137,139,134,252,143,145,140,137,
+0,0,0,0,0,0,0,0,137,139,134,252,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,138,140,135,
+252,0,0,0,0,0,0,0,0,136,138,133,255,255,255,255,255,222,225,219,255,192,195,188,
+255,186,189,182,255,186,189,182,255,186,189,182,255,186,189,182,255,186,189,182,
+255,186,189,182,255,194,196,190,255,234,236,232,255,255,255,255,255,136,138,133,
+255,0,0,0,0,0,0,0,0,136,138,133,255,255,255,255,255,223,226,220,255,227,229,224,
+255,230,233,228,255,234,236,232,255,237,238,235,255,239,240,237,255,240,241,239,
+255,240,241,238,255,238,240,237,255,236,237,234,255,255,255,255,255,136,138,133,
+255,0,0,0,0,0,0,0,0,136,138,133,255,255,255,255,255,224,227,221,255,228,230,225,
+255,197,171,168,255,163,122,119,255,141,143,138,255,141,143,138,255,164,126,123,
+255,202,177,174,255,240,241,239,255,237,239,236,255,255,255,255,255,136,138,133,
+255,0,0,0,0,0,0,0,0,136,138,133,255,255,255,255,255,225,227,222,255,177,121,119,
+255,163,40,39,255,214,147,146,255,238,238,236,255,238,238,237,255,215,156,155,
+255,165,41,39,255,181,125,123,255,239,240,237,255,255,255,255,255,136,138,133,
+255,0,0,0,0,0,0,0,0,136,138,133,255,255,255,255,255,198,171,168,255,163,40,39,
+255,240,134,134,255,235,87,87,255,186,166,162,255,186,166,162,255,235,92,92,255,
+240,159,159,255,166,42,41,255,208,180,178,255,255,255,255,255,136,138,133,255,0,
+0,0,0,0,0,0,0,136,138,133,255,255,255,255,255,162,131,127,255,215,143,142,255,
+236,87,87,255,171,16,16,255,185,147,144,255,185,147,144,255,171,16,16,255,237,
+95,95,255,219,164,162,255,166,130,126,255,255,255,255,255,136,138,133,255,0,0,
+0,0,0,0,0,0,136,138,133,255,255,255,255,255,141,143,138,255,240,240,238,255,
+186,169,166,255,182,136,133,255,244,245,243,255,248,248,247,255,189,152,150,255,
+187,166,163,255,242,242,241,255,141,143,138,255,255,255,255,255,136,138,133,255,
+0,0,0,0,0,0,0,0,136,138,133,255,255,255,255,255,141,143,138,255,242,242,241,
+255,186,168,165,255,183,150,147,255,244,245,243,255,248,249,248,255,186,141,139,
+255,188,174,171,255,245,245,244,255,141,143,138,255,255,255,255,255,136,138,133,
+255,0,0,0,0,0,0,0,0,136,138,133,255,255,255,255,255,164,127,123,255,224,147,146,
+255,236,140,140,255,162,27,27,255,184,148,144,255,186,150,148,255,161,28,27,255,
+237,167,167,255,227,158,157,255,166,132,129,255,255,255,255,255,136,138,133,255,
+0,0,0,0,0,0,0,0,136,138,133,255,255,255,255,255,198,172,168,255,178,28,28,255,
+246,144,144,255,238,152,151,255,191,174,171,255,192,175,172,255,239,178,177,255,
+249,177,177,255,179,32,32,255,208,181,179,255,255,255,255,255,136,138,133,255,0,
+0,0,0,0,0,0,0,136,138,133,255,255,255,255,255,226,229,224,255,178,119,116,255,
+179,34,33,255,230,170,169,255,248,248,248,255,250,250,249,255,234,184,183,255,
+181,38,38,255,183,123,121,255,242,243,240,255,255,255,255,255,136,138,133,255,0,
+0,0,0,0,0,0,0,136,138,133,255,255,255,255,255,226,228,223,255,230,232,228,255,
+197,173,169,255,164,124,121,255,141,143,138,255,141,143,138,255,165,123,120,255,
+205,179,177,255,244,245,243,255,241,242,240,255,255,255,255,255,136,138,133,255,
+0,0,0,0,0,0,0,0,137,139,134,252,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,138,140,135,
+252,0,0,0,0,0,0,0,0,141,143,138,137,137,139,134,252,136,138,133,255,136,138,133,
+255,136,138,133,255,136,138,133,255,136,138,133,255,136,138,133,255,136,138,133,
+255,136,138,133,255,136,138,133,255,136,138,133,255,137,139,134,252,143,145,140,
+137,0,0,0,0};
+MGL_EXPORT Fl_RGB_Image img_help(idata_help, 16, 16, 4, 0);
+
+static const unsigned char idata_delete[] =
+{0,0,0,0,0,0,0,0,0,0,0,0,46,52,54,17,46,52,54,75,46,52,54,255,46,52,54,255,
+46,52,54,255,46,52,54,255,46,52,54,255,46,52,54,255,46,52,54,62,46,52,54,33,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,46,52,54,58,46,52,54,255,100,105,106,
+255,144,152,148,255,233,234,227,255,238,239,236,255,239,240,238,255,210,213,211,
+255,191,193,193,255,151,154,155,255,46,52,54,255,46,52,54,75,0,0,0,0,0,0,0,0,0,
+0,0,0,46,52,54,62,66,71,73,255,217,219,214,255,199,202,196,255,110,118,114,
+255,66,71,69,255,36,39,39,255,49,52,50,255,122,131,126,255,179,184,179,255,203,
+206,203,255,203,207,203,255,46,52,54,255,46,52,54,33,0,0,0,0,0,0,0,0,46,52,54,
+255,214,217,211,255,210,213,205,255,218,220,214,255,174,179,173,255,92,99,98,
+255,53,57,57,255,55,58,56,255,88,94,91,255,141,148,143,255,170,175,167,255,210,
+214,210,255,181,186,181,255,46,52,54,255,0,0,0,0,0,0,0,0,46,52,54,255,229,229,
+225,255,240,240,237,255,236,237,233,255,227,229,224,255,221,222,217,255,203,206,
+199,255,182,187,179,255,162,168,160,255,179,184,176,255,186,191,183,255,171,176,
+168,255,203,206,205,255,46,52,54,255,0,0,0,0,0,0,0,0,46,52,54,255,224,226,226,
+255,230,230,221,255,244,244,239,255,244,243,241,255,244,244,241,255,243,244,240,
+255,240,240,235,255,229,230,224,255,214,217,210,255,145,152,148,255,139,143,141,
+255,137,141,141,255,46,52,54,255,0,0,0,0,0,0,0,0,46,52,54,194,154,156,156,255,
+194,197,196,255,188,192,191,255,217,219,210,255,223,224,216,255,217,219,212,255,
+204,208,207,255,132,140,137,255,150,156,153,255,134,137,138,255,83,88,90,255,46,
+52,54,255,46,52,54,130,0,0,0,0,0,0,0,0,46,52,54,68,46,52,54,255,90,95,96,255,
+139,143,143,255,173,175,176,255,228,229,229,255,227,229,229,255,227,229,228,255,
+161,164,164,255,104,109,110,255,60,64,65,255,76,80,82,255,46,52,54,255,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,46,52,54,255,107,113,113,255,50,56,56,255,46,52,52,
+255,43,49,50,255,43,49,51,255,41,46,48,255,40,45,47,255,39,44,46,255,57,61,60,
+255,147,149,148,255,46,52,54,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,46,52,54,255,
+175,181,179,255,176,182,180,255,105,112,110,255,151,159,155,255,106,113,109,255,
+57,62,59,255,95,103,100,255,51,55,52,255,97,104,102,255,152,155,153,255,46,52,
+54,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,46,52,54,255,183,187,187,255,213,216,
+214,255,129,138,136,255,209,212,210,255,126,135,133,255,81,87,86,255,137,146,
+144,255,67,72,68,255,110,119,116,255,160,163,161,255,46,52,54,255,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,46,52,54,255,183,187,187,255,214,217,215,255,133,141,138,
+255,216,219,216,255,162,168,163,255,85,91,89,255,151,158,156,255,69,75,71,255,
+111,120,117,255,160,163,161,255,46,52,54,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,46,
+52,54,255,183,187,187,255,212,215,213,255,131,140,137,255,216,219,215,255,162,
+168,163,255,85,91,89,255,151,158,156,255,69,75,71,255,110,119,116,255,155,157,
+155,255,46,52,54,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,46,52,54,255,175,177,176,
+255,204,207,207,255,185,187,187,255,221,223,220,255,162,168,163,255,85,91,89,
+255,160,167,164,255,135,139,136,255,146,149,149,255,114,115,115,255,46,52,54,
+255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,46,52,54,75,46,52,54,255,87,92,94,255,155,
+156,155,255,213,216,215,255,207,210,208,255,191,192,191,255,190,193,191,255,135,
+135,135,255,84,89,90,255,46,52,54,255,46,52,54,62,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,46,52,54,78,46,52,54,187,46,52,54,230,46,52,54,255,46,52,54,
+255,46,52,54,230,46,52,54,187,46,52,54,68,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+MGL_EXPORT Fl_RGB_Image img_delete(idata_delete, 16, 16, 4, 0);
+
+static const unsigned char idata_objectU[] =
+{255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,186,186,190,173,179,179,184,191,172,172,178,191,166,166,170,191,159,159,
+164,191,151,151,156,191,143,143,147,191,134,134,138,191,125,125,130,191,116,116,
+121,173,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,186,186,190,191,229,229,229,254,230,230,230,255,231,231,231,255,
+232,232,232,255,233,233,233,255,234,234,234,255,239,239,239,255,243,243,243,254,
+117,117,120,191,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,186,186,190,191,238,238,238,255,231,231,231,255,229,229,229,
+255,231,231,231,255,235,235,235,255,240,240,240,255,243,243,243,255,245,245,245,
+255,117,117,120,191,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,186,186,190,191,249,249,249,255,243,243,243,255,237,237,
+237,255,234,234,234,255,236,236,236,255,239,239,239,255,241,241,241,255,242,242,
+242,255,117,117,120,191,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,186,186,190,191,255,255,255,255,253,253,253,255,246,
+246,246,255,241,241,241,255,237,237,237,255,236,236,236,255,237,237,237,255,232,
+232,232,255,124,124,127,239,143,143,147,191,134,134,138,191,125,125,130,191,116,
+116,121,173,255,255,255,0,255,255,255,0,186,186,190,191,255,255,255,255,255,255,
+255,255,255,255,255,255,250,250,250,255,245,245,245,255,239,239,239,255,230,230,
+230,255,229,229,229,255,131,140,153,255,172,206,252,255,158,197,253,255,138,185,
+254,255,117,117,120,191,255,255,255,0,255,255,255,0,186,186,190,191,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,254,254,254,255,247,247,247,
+255,241,241,241,255,234,234,234,255,126,137,153,255,136,183,255,255,129,179,255,
+255,128,179,255,255,117,117,120,191,255,255,255,0,255,255,255,0,186,186,190,191,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,252,252,252,255,245,245,245,255,122,134,154,255,134,182,255,255,
+132,181,255,255,133,182,255,255,117,117,120,191,255,255,255,0,255,255,255,0,186,
+186,190,191,254,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,253,253,253,255,123,134,154,255,137,
+184,255,255,141,186,254,255,167,203,252,255,117,117,120,191,255,255,255,0,255,
+255,255,0,186,186,190,173,179,179,184,191,172,172,178,191,166,166,170,191,167,
+167,172,239,145,158,181,255,140,152,174,255,134,146,167,255,129,140,161,255,125,
+139,164,255,150,191,254,255,169,203,252,255,172,205,252,255,117,117,120,191,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+200,200,204,191,128,179,255,255,131,180,255,255,134,182,255,255,138,184,255,255,
+156,195,253,255,170,204,252,255,171,205,252,255,172,206,252,255,117,117,120,191,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,200,200,204,191,128,179,255,255,129,180,255,255,146,190,254,255,167,203,
+252,255,171,205,252,255,171,205,252,255,172,205,252,255,173,206,252,255,117,117,
+120,191,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,200,200,204,191,141,187,254,255,165,201,253,255,173,206,252,255,
+172,206,252,255,172,206,252,255,172,206,252,255,173,206,252,255,173,205,250,254,
+117,117,120,191,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,200,200,205,173,190,190,194,191,180,180,186,191,170,170,175,
+191,160,160,166,191,151,151,156,191,143,143,147,191,134,134,138,191,125,125,130,
+191,116,116,121,173,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0};
+MGL_EXPORT Fl_RGB_Image img_objectU(idata_objectU, 16, 16, 4, 0);
+
+static const unsigned char idata_objectD[] =
+{255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,186,186,190,173,179,179,184,191,172,172,178,191,166,166,170,191,159,159,
+164,191,151,151,156,191,143,143,147,191,134,134,138,191,125,125,130,191,116,116,
+121,173,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,186,186,190,191,229,229,229,254,230,230,230,255,231,231,231,255,
+232,232,232,255,233,233,233,255,234,234,234,255,239,239,239,255,243,243,243,254,
+117,117,120,191,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,186,186,190,191,238,238,238,255,231,231,231,255,229,229,229,
+255,231,231,231,255,235,235,235,255,240,240,240,255,243,243,243,255,245,245,245,
+255,117,117,120,191,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,186,186,190,191,249,249,249,255,243,243,243,255,237,237,
+237,255,234,234,234,255,236,236,236,255,239,239,239,255,241,241,241,255,242,242,
+242,255,117,117,120,191,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,186,186,190,191,255,255,255,255,253,253,253,255,246,
+246,246,255,213,213,216,255,201,201,204,255,194,194,198,255,186,186,190,255,178,
+178,182,255,144,144,149,239,143,143,147,191,134,134,138,191,125,125,130,191,116,
+116,121,173,255,255,255,0,255,255,255,0,186,186,190,191,255,255,255,255,255,255,
+255,255,255,255,255,255,213,213,216,255,174,206,251,255,173,206,252,255,173,206,
+252,255,173,206,252,255,173,206,252,255,172,206,252,255,158,197,253,255,138,185,
+254,255,117,117,120,191,255,255,255,0,255,255,255,0,186,186,190,191,255,255,255,
+255,255,255,255,255,255,255,255,255,214,214,217,255,173,206,252,255,173,206,252,
+255,172,206,252,255,165,201,253,255,153,194,253,255,136,183,255,255,129,179,255,
+255,128,179,255,255,117,117,120,191,255,255,255,0,255,255,255,0,186,186,190,191,
+255,255,255,255,255,255,255,255,255,255,255,255,214,214,217,255,149,192,254,255,
+139,185,254,255,134,182,255,255,134,182,255,255,135,183,255,255,134,182,255,255,
+132,181,255,255,133,182,255,255,117,117,120,191,255,255,255,0,255,255,255,0,186,
+186,190,191,254,254,254,254,255,255,255,255,255,255,255,255,214,214,217,255,128,
+179,255,255,131,180,255,255,134,182,255,255,137,184,255,255,139,185,255,255,137,
+184,255,255,141,186,254,255,167,203,252,255,117,117,120,191,255,255,255,0,255,
+255,255,0,186,186,190,173,179,179,184,191,172,172,178,191,166,166,170,191,192,
+192,196,239,128,179,255,255,131,181,255,255,135,183,255,255,139,185,255,255,143,
+188,255,255,150,191,254,255,169,203,252,255,172,205,252,255,117,117,120,191,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+200,200,204,191,128,179,255,255,131,180,255,255,134,182,255,255,138,184,255,255,
+156,195,253,255,170,204,252,255,171,205,252,255,172,206,252,255,117,117,120,191,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,200,200,204,191,128,179,255,255,129,180,255,255,146,190,254,255,167,203,
+252,255,171,205,252,255,171,205,252,255,172,205,252,255,173,206,252,255,117,117,
+120,191,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,200,200,204,191,141,187,254,255,165,201,253,255,173,206,252,255,
+172,206,252,255,172,206,252,255,172,206,252,255,173,206,252,255,173,205,250,254,
+117,117,120,191,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,200,200,205,173,190,190,194,191,180,180,186,191,170,170,175,
+191,160,160,166,191,151,151,156,191,143,143,147,191,134,134,138,191,125,125,130,
+191,116,116,121,173,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0};
+MGL_EXPORT Fl_RGB_Image img_objectD(idata_objectD, 16, 16, 4, 0);
+
+static const unsigned char idata_layer[] =
+{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+255,255,255,0,0,0,0,0,149,149,149,35,153,153,153,100,160,160,160,88,114,114,114,
+12,0,0,0,0,226,226,226,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,61,61,61,8,135,135,135,184,111,111,111,255,87,87,87,255,97,97,97,
+255,125,125,125,255,142,142,142,141,0,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,101,101,101,10,118,118,118,233,57,57,57,153,13,13,
+13,67,1,1,1,37,13,13,13,65,52,52,52,143,91,91,91,251,145,145,145,205,0,0,0,1,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,101,101,101,175,0,0,0,31,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,68,68,68,172,143,143,143,204,0,0,0,
+0,126,126,126,0,0,0,0,0,0,0,0,0,0,0,0,0,66,66,66,80,0,0,0,10,0,0,0,0,0,0,0,0,
+0,0,0,0,49,49,49,32,60,60,60,35,0,0,0,0,0,0,0,0,0,0,0,0,61,61,61,120,136,136,
+136,145,0,0,0,0,2,2,2,0,0,0,0,0,19,19,19,1,65,65,65,11,0,0,0,0,0,0,0,0,119,119,
+119,116,115,114,114,240,106,106,106,255,110,108,108,255,119,119,119,243,126,126,
+126,119,0,0,0,0,0,0,0,0,79,79,79,122,104,104,104,56,0,0,0,0,0,0,0,0,0,0,0,0,255,
+255,255,0,0,0,0,12,128,128,128,205,87,87,87,255,99,102,108,254,128,139,157,255,
+118,127,143,255,86,86,88,254,108,108,108,255,134,133,133,209,18,18,18,16,0,0,0,
+0,72,72,72,116,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,132,132,132,222,100,100,100,
+255,195,198,202,255,177,209,247,255,156,209,245,255,156,192,240,255,173,204,238,
+255,96,102,116,255,106,106,106,254,139,139,139,232,41,41,41,19,0,0,0,2,70,70,70,
+51,0,0,0,0,0,0,0,0,138,138,138,191,110,110,110,255,223,223,222,255,172,189,218,
+255,130,182,240,255,172,184,182,255,123,133,134,255,114,175,210,255,119,137,171,
+255,208,206,205,255,114,114,114,254,146,146,146,224,0,0,0,8,68,68,68,5,0,0,0,0,
+0,0,0,0,120,120,120,213,149,149,149,254,240,238,238,255,160,181,211,255,56,
+124,169,255,110,102,99,255,72,58,55,255,50,166,206,255,113,147,182,255,226,224,
+224,255,208,208,208,255,126,126,126,255,150,150,150,186,0,0,0,0,0,0,0,0,102,102,
+102,0,50,50,50,39,114,114,114,255,210,210,209,254,170,180,199,255,81,181,236,
+255,19,73,80,255,14,86,100,255,68,177,226,255,91,120,150,255,244,242,240,255,
+234,234,234,255,192,192,192,255,140,140,140,255,139,139,139,112,0,0,0,0,0,0,0,0,
+74,74,74,0,52,52,52,49,109,109,108,237,200,199,198,255,88,124,174,254,62,143,
+220,255,49,119,189,255,68,128,177,255,142,149,162,255,238,238,236,255,230,230,
+230,255,210,210,210,255,155,155,155,254,153,153,153,255,0,0,0,2,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,6,78,78,77,126,132,134,137,237,90,111,144,255,65,92,135,255,136,
+146,163,254,244,243,241,255,236,236,236,255,216,216,216,255,167,167,167,255,141,
+141,141,239,78,78,78,59,26,26,26,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,80,77,72,58,214,210,206,124,199,199,197,163,170,170,170,178,140,140,140,
+175,109,109,109,153,92,92,92,91,0,0,0,4,141,141,141,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+MGL_EXPORT Fl_RGB_Image img_layer(idata_layer, 16, 16, 4, 0);
+
+static const unsigned char idata_new[] =
+{0,0,0,16,0,0,0,58,0,0,0,58,0,0,0,58,0,0,0,58,0,0,0,58,0,0,0,58,0,0,0,58,0,
+0,0,58,0,0,0,58,0,117,0,136,41,168,41,231,91,195,91,249,42,170,42,226,0,159,0,
+104,255,255,255,0,0,0,0,58,234,234,234,255,232,233,233,255,234,235,235,255,236,
+237,237,255,237,238,238,255,238,239,239,255,239,240,240,255,240,241,241,255,143,
+207,143,255,54,191,54,255,120,213,120,255,255,255,255,255,122,213,120,255,53,
+192,53,253,0,157,0,103,0,0,0,58,232,233,234,255,232,233,233,255,234,235,235,255,
+236,237,237,255,237,238,238,255,238,239,239,255,239,240,240,255,240,241,241,255,
+33,166,33,255,29,182,29,255,63,180,41,255,255,255,255,255,90,188,41,255,51,188,
+29,255,0,155,0,220,0,0,0,58,235,236,236,255,235,236,236,255,236,237,237,255,
+238,239,239,255,239,240,240,255,241,241,241,255,242,242,242,255,243,243,243,255,
+9,149,9,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,0,147,0,246,0,0,0,58,237,238,238,255,237,237,237,255,238,239,
+239,255,240,241,241,255,242,242,242,255,243,244,244,255,245,245,245,255,246,246,
+246,255,33,180,33,255,3,160,0,255,52,160,0,255,255,255,255,255,100,176,0,255,50,
+175,0,255,0,168,0,220,0,0,0,58,238,239,239,255,238,239,239,255,240,241,241,255,
+242,243,243,255,244,244,244,255,246,246,246,255,247,247,247,255,248,248,248,255,
+149,221,149,255,2,173,2,255,26,163,0,255,255,255,255,255,54,176,0,255,3,173,0,
+253,0,178,0,102,0,0,0,58,240,241,241,255,240,241,241,255,242,243,243,255,244,
+245,245,255,246,246,246,255,248,248,248,255,249,249,249,255,250,250,250,255,250,
+250,250,255,149,223,149,255,35,196,35,255,10,175,10,255,0,179,0,227,0,184,0,102,
+255,255,255,0,0,0,0,58,242,242,242,255,242,242,242,255,244,244,244,255,246,246,
+246,255,248,248,248,255,250,250,250,255,250,250,250,255,251,251,251,255,251,251,
+251,255,252,252,252,255,252,252,252,255,252,252,252,255,0,0,0,58,255,255,255,0,
+255,255,255,0,0,0,0,58,243,244,244,255,243,244,244,255,246,246,246,255,248,248,
+248,255,250,250,250,255,251,251,251,255,251,251,251,255,252,252,252,255,252,252,
+252,255,253,253,253,255,253,253,253,255,253,253,253,255,0,0,0,58,255,255,255,0,
+255,255,255,0,0,0,0,58,244,244,244,255,245,245,245,255,247,247,247,255,250,250,
+250,255,250,250,250,255,251,251,251,255,252,252,252,255,253,253,253,255,253,253,
+253,255,254,254,254,255,254,254,254,255,254,254,254,255,0,0,0,58,255,255,255,0,
+255,255,255,0,0,0,0,58,244,245,245,255,246,246,246,255,249,249,249,255,250,250,
+250,255,251,251,251,255,252,252,252,255,253,253,253,255,254,254,254,255,254,254,
+254,255,252,252,252,255,250,250,250,255,239,239,240,254,0,0,0,53,255,255,255,0,
+255,255,255,0,0,0,0,58,245,246,246,255,247,247,247,255,250,250,250,255,251,251,
+251,255,252,252,252,255,253,253,253,255,254,254,254,255,254,254,254,255,224,224,
+224,255,198,198,198,255,206,207,207,255,132,134,136,199,0,0,0,5,255,255,255,0,
+255,255,255,0,0,0,0,58,246,246,246,255,248,248,248,255,250,250,250,255,251,251,
+251,255,252,252,252,255,253,253,253,255,254,254,254,255,251,251,251,255,196,196,
+196,255,253,253,253,255,128,133,133,213,0,0,0,10,255,255,255,0,255,255,255,0,
+255,255,255,0,0,0,0,58,246,247,247,255,248,248,248,255,250,250,250,255,251,251,
+251,255,252,252,252,255,253,253,253,255,254,254,254,255,244,244,244,255,204,204,
+204,255,126,131,131,213,0,0,0,18,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,0,0,0,57,246,247,247,254,249,249,249,255,251,251,251,255,251,251,251,
+255,252,252,252,255,253,253,253,255,255,255,255,255,233,233,234,254,126,129,129,
+199,0,0,0,10,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,0,0,0,7,0,0,0,57,0,0,0,58,0,0,0,58,0,0,0,58,0,0,0,58,0,0,0,58,0,0,0,58,0,
+0,0,53,0,0,0,5,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0};
+MGL_EXPORT Fl_RGB_Image img_new(idata_new, 16, 16, 4, 0);
+
+static const unsigned char idata_clear[] =
+{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+183,165,137,107,182,156,121,213,76,67,57,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,179,158,
+125,207,200,175,140,166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,193,179,155,54,185,160,124,
+255,197,175,145,66,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,141,120,95,18,171,155,130,188,185,159,123,
+219,99,88,74,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,83,68,52,3,146,127,102,126,172,144,110,255,151,127,99,
+177,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,141,117,85,19,173,147,110,203,184,157,119,255,159,133,103,255,154,
+108,86,184,174,0,0,4,0,0,0,0,0,0,0,0,174,1,1,24,178,58,58,68,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,43,43,0,0,159,132,95,185,192,165,127,255,179,155,119,
+255,172,138,98,255,182,130,102,246,185,43,39,152,154,0,0,4,160,0,0,25,199,64,59,
+194,223,110,105,224,172,13,10,83,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,140,122,98,87,
+173,145,107,255,183,155,116,255,179,148,109,255,170,136,94,255,180,121,94,245,
+216,104,100,226,138,35,30,160,171,55,49,196,221,103,102,226,222,107,104,226,178,
+40,36,158,0,0,0,0,0,0,0,0,0,0,0,0,130,104,71,12,141,113,78,221,163,141,110,255,
+165,142,110,255,165,131,91,255,167,134,93,255,175,96,71,239,203,67,65,226,198,
+75,70,226,206,79,76,226,206,89,85,226,171,33,26,167,154,0,0,9,0,0,0,0,0,0,0,0,
+0,0,0,0,151,119,79,166,161,132,92,255,175,145,105,255,155,127,90,255,145,117,
+85,255,141,117,86,255,143,66,50,134,182,44,31,226,189,18,18,226,189,24,23,226,
+166,32,19,210,144,0,0,13,0,0,0,0,0,0,0,0,0,0,0,0,160,126,82,117,155,124,83,255,
+179,145,101,255,163,129,90,255,154,122,82,255,168,131,87,255,160,129,88,255,163,
+44,30,217,206,16,10,227,192,22,15,227,203,9,7,226,204,20,13,226,153,23,17,152,
+131,0,0,4,0,0,0,0,158,124,80,88,180,143,93,251,157,123,84,255,168,132,89,255,
+176,138,93,255,161,125,81,255,178,142,94,255,164,129,87,254,217,46,32,233,208,
+47,35,232,108,49,36,187,132,45,36,211,231,10,9,226,224,23,19,226,163,51,49,147,
+127,98,65,50,170,135,87,204,143,112,72,255,187,148,99,254,179,136,92,255,167,
+132,86,255,186,145,94,255,178,142,92,255,181,137,92,252,206,76,58,235,137,65,49,
+191,162,119,81,52,114,53,36,55,159,41,38,206,216,42,39,226,142,23,21,102,169,
+135,94,36,170,135,88,202,188,143,98,254,190,145,97,254,187,144,95,252,181,144,
+93,255,197,153,97,255,184,145,94,255,189,150,100,209,149,80,54,153,166,123,83,
+53,176,141,95,15,183,144,96,2,148,35,35,37,140,15,15,87,0,0,0,0,171,140,94,10,
+169,137,91,68,170,136,91,151,176,136,92,185,180,143,93,214,186,148,95,242,184,
+142,90,254,184,140,93,247,178,143,96,149,175,140,97,24,170,136,98,4,85,85,85,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,180,143,94,3,179,141,95,10,176,139,96,
+24,175,140,94,53,170,137,92,94,159,125,81,129,183,140,93,120,146,119,84,58,170,
+170,85,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+MGL_EXPORT Fl_RGB_Image img_clear(idata_clear, 16, 16, 4, 0);
+
+static const unsigned char idata_plus[] =
+{255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,124,
+201,112,164,64,177,40,247,67,180,39,237,161,217,144,149,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,87,184,72,254,
+160,217,142,255,154,214,134,255,107,195,82,251,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,36,161,19,255,158,222,
+134,255,161,223,138,255,66,179,38,255,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,31,159,16,255,145,215,124,255,
+146,217,126,255,60,176,35,255,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,1,255,255,255,4,255,
+255,255,0,255,255,255,0,255,255,255,0,27,156,14,255,131,209,115,255,132,209,116,
+255,55,172,32,255,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,4,255,
+255,255,1,255,255,255,0,255,255,255,0,98,182,98,136,65,168,65,251,6,143,4,255,
+12,146,8,255,18,150,11,255,23,153,13,255,121,204,107,255,123,205,108,255,48,
+169,27,255,55,173,30,255,64,178,35,255,73,184,40,255,124,205,97,251,154,219,128,
+136,255,255,255,0,255,255,255,0,4,134,4,236,104,186,99,255,104,189,96,255,103,
+192,94,255,104,194,95,255,109,197,97,255,99,195,83,255,101,196,84,255,117,200,
+100,255,119,202,104,255,126,202,116,255,107,191,101,255,93,181,83,255,88,192,49,
+236,255,255,255,0,255,255,255,0,0,130,0,236,70,167,66,255,74,173,70,255,79,181,
+73,255,93,188,85,255,98,190,86,255,87,187,71,255,90,189,71,255,106,195,89,255,
+96,189,79,255,57,170,44,255,42,161,35,255,59,167,48,255,79,187,42,236,255,255,
+255,0,255,255,255,0,0,128,0,106,0,131,0,250,0,135,0,255,0,139,0,255,5,143,2,255,
+11,146,5,255,67,177,46,255,78,183,52,255,32,159,17,255,40,164,21,255,47,168,25,
+255,55,173,29,255,64,179,34,250,75,183,38,106,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,7,144,4,255,
+69,179,45,255,86,189,53,255,28,156,14,255,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,4,142,2,255,64,176,40,255,
+88,190,53,255,23,154,12,255,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,1,140,0,255,42,164,25,255,63,177,38,255,
+19,151,10,255,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,128,2,31,152,16,254,14,147,8,255,25,153,20,255,31,147,25,251,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,86,171,29,160,14,147,8,247,51,163,50,239,45,145,39,125,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0};
+MGL_EXPORT Fl_RGB_Image img_plus(idata_plus, 16, 16, 4, 0);
+
+static const unsigned char idata_minus[] =
+{255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,1,255,255,255,4,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,4,255,255,255,1,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,199,100,100,132,191,65,65,250,176,0,0,255,183,0,0,
+255,190,0,0,255,196,0,0,255,203,0,0,255,210,0,0,255,216,0,0,255,223,0,0,255,236,
+65,65,251,246,98,98,136,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,
+0,161,4,4,228,204,103,103,255,207,90,90,255,215,90,90,255,220,90,90,255,225,
+90,90,255,228,90,90,255,228,90,90,255,226,100,100,255,209,87,87,255,199,69,69,
+255,234,4,4,236,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,155,0,0,
+228,193,82,82,255,200,77,77,255,210,81,81,255,217,80,80,255,222,77,77,255,225,
+73,73,255,223,73,73,255,208,40,40,255,190,28,28,255,190,34,34,255,229,0,0,236,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,150,0,0,100,158,0,0,249,
+165,0,0,255,171,0,0,255,178,0,0,255,185,0,0,255,191,0,0,255,198,0,0,255,205,0,0,
+255,211,0,0,255,218,0,0,250,226,0,0,106,255,255,255,0,255,255,255,0,255,255,255,
+0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0};
+MGL_EXPORT Fl_RGB_Image img_minus(idata_minus, 16, 16, 4, 0);
+
+static const unsigned char idata_udav[] =
+{255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,
+255,0,1,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,1,255,255,0,2,255,
+255,0,3,255,255,0,3,255,255,0,3,255,255,0,3,255,255,0,4,255,255,0,4,255,255,0,4,
+255,255,0,3,255,255,0,3,255,255,0,2,255,255,0,2,255,255,0,1,255,255,0,1,255,255,
+0,1,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,1,255,
+255,0,2,255,255,0,3,255,255,0,4,255,255,0,5,255,255,0,6,255,255,0,7,255,255,0,7,
+255,255,0,8,255,255,0,8,255,255,0,8,255,255,0,8,255,255,0,9,255,255,0,8,255,255,
+0,7,255,255,0,6,255,255,0,6,255,255,0,5,255,255,0,4,255,255,0,3,255,255,0,2,
+255,255,0,1,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,
+0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,0,1,255,255,0,3,255,255,0,4,255,255,0,5,255,255,0,7,
+255,255,0,8,255,255,0,9,255,255,0,11,255,255,0,13,255,255,0,13,255,255,0,13,255,
+255,0,14,255,255,0,14,255,255,0,15,255,255,0,15,255,255,0,14,255,255,0,13,255,
+255,0,12,255,255,0,11,255,255,0,10,255,255,0,9,255,255,0,7,255,255,0,5,255,255,
+0,4,255,255,0,3,255,255,0,1,255,255,0,1,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,3,
+255,255,0,4,255,255,0,7,255,255,0,9,255,255,0,10,255,255,0,12,255,255,0,14,255,
+255,0,16,255,255,0,18,255,255,0,20,255,255,0,20,255,255,0,21,255,255,0,21,255,
+255,0,22,255,255,0,22,255,255,0,22,255,255,0,21,255,255,0,20,255,255,0,18,255,
+255,0,17,255,255,0,16,255,255,0,15,255,255,0,12,255,255,0,10,255,255,0,8,255,
+255,0,6,255,255,0,4,255,255,0,3,255,255,0,2,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,0,1,255,255,0,3,255,255,0,4,255,255,0,6,255,255,0,9,255,
+255,0,11,255,255,0,14,255,255,0,17,255,255,0,19,255,255,0,21,255,255,0,23,255,
+255,0,25,255,255,0,28,255,255,0,29,255,255,0,29,255,255,0,30,255,255,0,30,255,
+255,0,31,255,255,0,31,255,255,0,29,255,255,0,28,255,255,0,26,255,255,0,25,255,
+255,0,24,255,255,0,22,255,255,0,19,255,255,0,16,255,255,0,14,255,255,0,11,255,
+255,0,9,255,255,0,7,255,255,0,4,255,255,0,3,255,255,0,1,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,2,
+255,255,0,4,255,255,0,6,255,255,0,8,255,255,0,11,255,255,0,14,255,255,0,17,255,
+255,0,21,255,255,0,24,255,255,0,27,255,255,0,29,255,255,0,31,255,255,0,34,255,
+255,0,36,255,255,0,38,255,255,0,38,255,255,0,39,255,255,0,40,255,255,0,40,255,
+255,0,40,255,255,0,39,255,255,0,37,255,255,0,35,255,255,0,34,255,255,0,32,255,
+255,0,30,255,255,0,26,255,255,0,23,255,255,0,20,255,255,0,17,255,255,0,15,255,
+255,0,12,255,255,0,8,255,255,0,6,255,255,0,3,255,255,0,2,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,0,1,255,255,0,2,255,255,0,4,255,255,0,8,255,255,
+0,11,255,255,0,14,255,255,0,17,255,255,0,21,255,255,0,24,255,255,0,28,255,255,
+0,33,255,255,0,35,255,255,0,38,255,255,0,41,255,255,0,43,255,255,0,46,255,255,
+0,48,255,255,0,49,255,255,0,49,171,44,44,255,201,73,73,255,193,65,65,255,153,
+26,26,255,255,255,0,47,255,255,0,45,255,255,0,44,255,255,0,42,255,255,0,38,255,
+255,0,35,255,255,0,31,255,255,0,28,255,255,0,25,255,255,0,22,255,255,0,17,255,
+255,0,14,255,255,0,10,255,255,0,7,255,255,0,4,255,255,0,2,255,255,0,1,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,0,1,255,255,0,3,255,255,0,5,255,255,0,8,255,255,0,12,255,255,0,16,255,255,0,
+20,255,255,0,24,255,255,0,28,255,255,0,32,255,255,0,36,255,255,0,41,255,255,0,
+45,255,255,0,48,255,255,0,51,255,255,0,54,255,255,0,56,255,255,0,59,153,26,26,
+255,232,105,105,255,255,179,179,255,255,206,206,255,255,191,191,255,255,134,134,
+255,188,60,60,255,255,255,0,56,255,255,0,54,255,255,0,52,255,255,0,48,255,255,0,
+44,255,255,0,40,255,255,0,37,255,255,0,33,255,255,0,29,255,255,0,24,255,255,0,
+19,255,255,0,15,255,255,0,12,255,255,0,8,255,255,0,6,255,255,0,3,255,255,0,1,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,3,
+255,255,0,6,255,255,0,9,255,255,0,13,255,255,0,17,255,255,0,22,255,255,0,27,255,
+255,0,32,255,255,0,36,255,255,0,41,255,255,0,45,255,255,0,50,255,255,0,55,255,
+255,0,58,255,255,0,61,255,255,0,64,255,255,0,67,139,11,11,255,202,74,74,255,255,
+149,149,255,255,217,217,255,255,248,248,255,255,232,232,255,255,176,176,255,230,
+102,102,255,167,40,40,255,255,255,0,65,255,255,0,62,255,255,0,58,255,255,0,54,
+255,255,0,50,255,255,0,46,255,255,0,42,255,255,0,36,255,255,0,31,255,255,0,26,
+255,255,0,21,255,255,0,17,255,255,0,13,255,255,0,9,255,255,0,6,255,255,0,3,255,
+255,0,1,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,3,255,255,0,6,255,
+255,0,9,255,255,0,13,255,255,0,18,255,255,0,23,255,255,0,29,255,255,0,34,255,
+255,0,40,255,255,0,45,255,255,0,50,255,255,0,55,255,255,0,60,255,255,0,65,255,
+255,0,69,255,255,0,72,255,255,0,76,255,255,0,79,155,27,27,255,193,66,66,255,237,
+109,109,255,255,146,146,255,255,165,165,255,255,157,157,255,255,127,127,255,212,
+85,85,255,172,44,44,255,142,14,14,255,255,255,0,73,255,255,0,69,255,255,0,64,
+255,255,0,60,255,255,0,56,255,255,0,51,255,255,0,45,255,255,0,39,255,255,0,33,
+255,255,0,28,255,255,0,24,255,255,0,19,255,255,0,14,255,255,0,9,255,255,0,6,255,
+255,0,3,255,255,0,1,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,0,1,255,255,0,3,255,255,0,6,255,255,0,10,255,255,0,
+14,255,255,0,19,255,255,0,24,255,255,0,30,255,255,0,35,255,255,0,42,255,255,0,
+49,255,255,0,54,255,255,0,59,255,255,0,65,255,255,0,70,255,255,0,76,255,255,0,
+81,255,255,0,84,255,255,0,87,255,255,0,91,147,20,20,255,163,36,36,255,180,53,
+53,255,195,67,67,255,203,75,75,255,201,73,73,255,190,63,63,255,175,47,47,255,
+157,30,30,255,142,14,14,255,255,255,0,84,255,255,0,80,255,255,0,75,255,255,0,71,
+255,255,0,66,255,255,0,60,255,255,0,53,255,255,0,47,255,255,0,42,255,255,0,36,
+255,255,0,31,255,255,0,24,255,255,0,19,255,255,0,14,255,255,0,9,255,255,0,5,255,
+255,0,3,255,255,0,1,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,0,2,255,255,0,5,255,255,0,9,255,255,0,14,255,255,0,20,255,255,0,
+25,255,255,0,31,255,255,0,37,255,255,0,43,255,255,0,50,255,255,0,57,255,255,0,
+64,255,255,0,70,255,255,0,75,255,255,0,81,255,255,0,86,255,255,0,92,255,255,0,
+96,255,255,0,99,255,255,0,102,138,10,10,255,143,15,15,255,147,20,20,255,152,24,
+24,255,154,27,27,255,154,27,27,255,152,24,24,255,148,20,20,255,142,15,15,255,
+137,10,10,255,255,255,0,95,255,255,0,91,255,255,0,86,255,255,0,82,255,255,0,76,
+255,255,0,69,255,255,0,63,255,255,0,56,255,255,0,50,255,255,0,44,255,255,0,37,
+255,255,0,31,255,255,0,24,255,255,0,18,255,255,0,13,255,255,0,9,255,255,0,5,255,
+255,0,3,255,255,0,1,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,2,255,255,0,4,
+255,255,0,8,255,255,0,13,255,255,0,18,255,255,0,24,255,255,0,32,255,255,0,38,
+255,255,0,44,255,255,0,51,255,255,0,58,255,255,0,66,255,255,0,73,255,255,0,80,
+255,255,0,86,255,255,0,92,255,255,0,97,255,255,0,103,255,255,0,108,255,255,0,
+111,255,255,0,114,132,5,5,255,133,6,6,255,134,7,7,255,135,8,8,255,136,8,8,255,
+136,8,8,255,136,8,8,255,135,8,8,255,134,7,7,255,133,6,6,255,255,255,0,107,255,
+255,0,102,255,255,0,98,255,255,0,93,255,255,0,86,255,255,0,79,255,255,0,72,255,
+255,0,66,255,255,0,59,255,255,0,52,255,255,0,44,255,255,0,37,255,255,0,30,255,
+255,0,24,255,255,0,18,255,255,0,13,255,255,0,9,255,255,0,5,255,255,0,2,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,0,1,255,255,0,4,255,255,0,7,255,255,0,12,255,255,0,17,255,
+255,0,23,255,255,0,30,255,255,0,37,255,255,0,45,255,255,0,52,255,255,0,60,255,
+255,0,67,255,255,0,75,255,255,0,82,255,255,0,90,255,255,0,97,255,255,0,102,255,
+255,0,108,255,255,0,114,255,255,0,120,255,255,0,123,255,255,0,126,130,2,2,255,
+129,2,2,255,130,2,2,255,130,2,2,255,130,2,2,255,130,2,2,255,130,3,3,255,130,3,3,
+255,131,3,3,255,132,5,5,255,255,255,0,119,255,255,0,114,255,255,0,109,255,255,0,
+103,255,255,0,96,255,255,0,89,255,255,0,82,255,255,0,75,255,255,0,68,255,255,0,
+60,255,255,0,52,255,255,0,44,255,255,0,37,255,255,0,30,255,255,0,24,255,255,0,
+18,255,255,0,12,255,255,0,7,255,255,0,3,255,255,0,1,255,255,255,0,255,255,255,
+0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,3,255,
+255,0,6,255,255,0,10,255,255,0,15,255,255,0,21,255,255,0,28,255,255,0,35,255,
+255,0,43,255,255,0,52,255,255,0,61,255,255,0,68,255,255,0,76,255,255,0,84,255,
+255,0,92,255,255,0,100,255,255,0,108,255,255,0,113,255,255,0,119,255,255,0,125,
+255,255,0,131,255,255,0,135,255,255,0,138,255,255,0,142,128,1,1,255,128,1,1,255,
+128,1,1,255,128,1,1,255,128,1,1,255,128,1,1,255,129,1,1,255,130,2,2,255,255,255,
+0,135,255,255,0,130,255,255,0,125,255,255,0,120,255,255,0,113,255,255,0,106,
+255,255,0,99,255,255,0,92,255,255,0,85,255,255,0,76,255,255,0,67,255,255,0,59,
+255,255,0,51,255,255,0,43,255,255,0,36,255,255,0,29,255,255,0,22,255,255,0,16,
+255,255,0,10,255,255,0,6,255,255,0,2,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,0,2,255,255,0,4,255,255,0,9,255,255,0,
+14,255,255,0,20,255,255,0,26,255,255,0,34,255,255,0,41,255,255,0,50,255,255,0,
+58,255,255,0,68,255,255,0,77,255,255,0,85,255,255,0,93,255,255,0,101,255,255,0,
+109,255,255,0,117,255,255,0,124,255,255,0,130,255,255,0,136,255,255,0,142,255,
+255,0,147,255,255,0,150,255,255,0,153,255,255,0,156,128,0,0,255,128,0,0,255,128,
+0,0,255,128,0,0,255,128,0,0,255,129,1,1,255,255,255,0,150,255,255,0,146,255,
+255,0,141,255,255,0,137,255,255,0,130,255,255,0,123,255,255,0,116,255,255,0,110,
+255,255,0,102,255,255,0,93,255,255,0,84,255,255,0,76,255,255,0,67,255,255,0,59,
+255,255,0,51,255,255,0,43,255,255,0,34,255,255,0,26,255,255,0,19,255,255,0,13,
+255,255,0,8,255,255,0,4,255,255,0,1,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,0,3,255,255,0,7,255,255,0,11,255,255,0,18,255,255,0,
+25,255,255,0,32,255,255,0,40,255,255,0,48,255,255,0,56,255,255,0,65,255,255,0,
+75,255,255,0,84,255,255,0,94,255,255,0,102,255,255,0,110,255,255,0,119,255,255,
+0,127,255,255,0,135,255,255,0,141,255,255,0,147,255,255,0,152,255,255,0,158,
+255,255,0,161,255,255,0,164,255,255,0,167,255,255,0,169,121,121,249,255,24,24,
+151,255,129,1,1,255,255,255,0,167,255,255,0,165,255,255,0,161,255,255,0,157,255,
+255,0,153,255,255,0,147,255,255,0,141,255,255,0,134,255,255,0,127,255,255,0,120,
+255,255,0,111,255,255,0,102,255,255,0,93,255,255,0,84,255,255,0,75,255,255,0,67,
+255,255,0,57,255,255,0,48,255,255,0,39,255,255,0,31,255,255,0,23,255,255,0,17,
+255,255,0,11,255,255,0,7,255,255,0,3,255,255,0,1,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,0,1,255,255,0,4,255,255,0,9,255,255,0,14,255,255,0,21,255,255,0,
+28,255,255,0,37,255,255,0,46,255,255,0,54,255,255,0,63,255,255,0,72,255,255,0,
+82,255,255,0,92,255,255,0,101,255,255,0,111,255,255,0,120,255,255,0,128,255,
+255,0,136,255,255,0,144,255,255,0,152,255,255,0,157,255,255,0,163,255,255,0,168,
+255,255,0,172,255,255,0,175,255,255,0,178,93,93,221,255,43,43,170,255,3,3,131,
+255,255,255,0,180,255,255,0,178,255,255,0,176,255,255,0,172,255,255,0,168,255,
+255,0,164,255,255,0,157,255,255,0,151,255,255,0,144,255,255,0,137,255,255,0,128,
+255,255,0,119,255,255,0,110,255,255,0,101,255,255,0,92,255,255,0,83,255,255,0,
+73,255,255,0,63,255,255,0,53,255,255,0,44,255,255,0,36,255,255,0,28,255,255,0,
+21,255,255,0,14,255,255,0,9,255,255,0,5,255,255,0,2,255,255,255,0,255,255,255,
+0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,0,3,255,255,0,6,255,255,0,11,255,255,0,17,255,255,0,24,255,
+255,0,32,255,255,0,41,255,255,0,50,255,255,0,60,255,255,0,70,255,255,0,80,255,
+255,0,89,255,255,0,99,255,255,0,109,255,255,0,119,255,255,0,129,255,255,0,137,
+255,255,0,145,255,255,0,153,255,255,0,161,255,255,0,167,255,255,0,173,255,255,0,
+178,255,255,0,183,255,255,0,186,104,104,232,255,39,39,166,255,3,3,131,255,255,
+255,0,192,255,255,0,190,255,255,0,188,255,255,0,186,255,255,0,182,255,255,0,178,
+255,255,0,173,255,255,0,167,255,255,0,160,255,255,0,154,255,255,0,146,255,255,0,
+137,255,255,0,128,255,255,0,119,255,255,0,110,255,255,0,100,255,255,0,90,255,
+255,0,79,255,255,0,69,255,255,0,59,255,255,0,50,255,255,0,41,255,255,0,33,255,
+255,0,25,255,255,0,18,255,255,0,12,255,255,0,7,255,255,0,3,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,0,1,255,255,0,4,255,255,0,8,255,255,0,14,255,255,0,20,255,255,0,28,255,
+255,0,36,255,255,0,45,255,255,0,55,255,255,0,65,255,255,0,76,255,255,0,87,255,
+255,0,97,255,255,0,107,255,255,0,116,255,255,0,126,255,255,0,136,255,255,0,146,
+255,255,0,154,255,255,0,162,255,255,0,169,255,255,0,177,255,255,0,182,255,255,0,
+187,10,10,138,255,89,89,217,255,19,19,146,255,2,2,130,255,255,255,0,201,255,255,
+0,201,255,255,0,200,255,255,0,198,255,255,0,196,255,255,0,192,255,255,0,188,
+255,255,0,182,255,255,0,176,255,255,0,170,255,255,0,162,255,255,0,154,255,255,0,
+145,255,255,0,136,255,255,0,127,255,255,0,117,255,255,0,106,255,255,0,96,255,
+255,0,85,255,255,0,75,255,255,0,65,255,255,0,55,255,255,0,46,255,255,0,37,255,
+255,0,29,255,255,0,21,255,255,0,14,255,255,0,8,255,255,0,4,255,255,0,1,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,0,2,255,255,0,6,255,255,0,11,255,255,0,16,255,255,0,24,255,255,0,32,255,255,
+0,40,255,255,0,50,255,255,0,60,255,255,0,70,255,255,0,81,255,255,0,92,255,255,
+0,103,255,255,0,114,255,255,0,124,255,255,0,134,255,255,0,144,255,255,0,153,
+255,255,0,163,255,255,0,171,255,255,0,178,255,255,0,185,45,45,173,255,71,71,198,
+255,28,28,156,255,5,5,132,255,1,1,128,255,255,255,0,210,255,255,0,210,255,255,0,
+211,255,255,0,209,255,255,0,208,255,255,0,205,255,255,0,201,255,255,0,197,255,
+255,0,191,255,255,0,185,255,255,0,178,255,255,0,170,255,255,0,162,255,255,0,153,
+255,255,0,145,255,255,0,134,255,255,0,124,255,255,0,113,255,255,0,102,255,255,0,
+92,255,255,0,81,255,255,0,71,255,255,0,61,255,255,0,51,255,255,0,41,255,255,0,
+32,255,255,0,23,255,255,0,16,255,255,0,10,255,255,0,5,255,255,0,2,255,255,255,
+0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,0,3,255,255,0,7,255,255,0,13,255,255,0,20,255,255,0,27,255,255,0,35,255,255,
+0,45,255,255,0,54,255,255,0,64,255,255,0,75,255,255,0,86,255,255,0,97,255,255,
+0,108,255,255,0,120,255,255,0,131,255,255,0,141,255,255,0,151,255,255,0,160,
+255,255,0,169,22,22,150,255,32,32,159,255,28,28,155,255,14,14,141,255,4,4,132,
+255,1,1,128,255,0,0,128,255,38,38,165,255,255,255,0,218,255,255,0,219,255,255,0,
+219,255,255,0,218,255,255,0,216,255,255,0,213,255,255,0,210,255,255,0,205,255,
+255,0,199,255,255,0,193,255,255,0,186,255,255,0,178,255,255,0,170,255,255,0,161,
+255,255,0,151,255,255,0,140,255,255,0,130,255,255,0,119,255,255,0,109,255,255,0,
+98,255,255,0,87,255,255,0,76,255,255,0,65,255,255,0,54,255,255,0,44,255,255,0,
+34,255,255,0,26,255,255,0,18,255,255,0,12,255,255,0,7,255,255,0,3,255,255,255,
+0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,1,255,255,
+0,4,255,255,0,8,255,255,0,14,255,255,0,21,255,255,0,30,255,255,0,39,255,255,0,
+49,255,255,0,59,255,255,0,69,255,255,0,80,255,255,0,91,255,255,0,102,255,255,0,
+114,255,255,0,125,255,255,0,136,255,255,0,147,255,255,0,158,255,255,0,167,7,7,
+134,255,6,6,133,255,4,4,131,255,2,2,129,255,0,0,128,255,0,0,128,255,4,4,132,255,
+56,56,184,255,76,76,203,255,132,132,255,255,113,113,240,255,42,42,170,255,255,
+255,0,225,255,255,0,223,255,255,0,221,255,255,0,217,255,255,0,212,255,255,0,207,
+255,255,0,200,255,255,0,193,255,255,0,185,255,255,0,176,255,255,0,167,255,255,0,
+157,255,255,0,147,255,255,0,136,255,255,0,126,255,255,0,115,255,255,0,103,255,
+255,0,91,255,255,0,80,255,255,0,68,255,255,0,58,255,255,0,47,255,255,0,38,255,
+255,0,29,255,255,0,21,255,255,0,14,255,255,0,8,255,255,0,4,255,255,0,1,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,4,255,255,
+0,9,255,255,0,15,255,255,0,23,255,255,0,31,255,255,0,41,255,255,0,51,255,255,
+0,62,255,255,0,73,255,255,0,85,255,255,0,96,255,255,0,108,255,255,0,119,255,
+255,0,130,255,255,0,141,255,255,0,152,255,255,0,163,255,255,0,173,255,255,0,183,
+1,1,129,255,1,1,128,255,0,0,128,255,4,4,132,255,4,4,131,255,6,6,133,255,12,12,
+140,255,27,27,155,255,61,61,188,255,121,121,248,255,148,148,255,255,152,152,255,
+255,57,57,185,255,255,255,0,227,255,255,0,223,255,255,0,219,255,255,0,213,255,
+255,0,206,255,255,0,200,255,255,0,191,255,255,0,182,255,255,0,173,255,255,0,163,
+255,255,0,153,255,255,0,142,255,255,0,130,255,255,0,119,255,255,0,107,255,255,0,
+95,255,255,0,83,255,255,0,72,255,255,0,61,255,255,0,51,255,255,0,41,255,255,0,
+32,255,255,0,23,255,255,0,16,255,255,0,10,255,255,0,5,255,255,0,2,255,255,255,
+0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,2,255,255,0,6,255,255,0,
+11,255,255,0,17,255,255,0,25,255,255,0,33,255,255,0,43,255,255,0,53,255,255,0,
+64,255,255,0,76,255,255,0,88,255,255,0,100,255,255,0,112,255,255,0,124,255,255,
+0,135,255,255,0,146,255,255,0,157,255,255,0,168,255,255,0,178,255,255,0,188,
+255,255,0,197,4,4,131,255,2,2,129,255,1,1,128,255,1,1,128,255,1,1,128,255,1,1,
+129,255,4,4,131,255,11,11,138,255,32,32,159,255,83,83,210,255,165,165,255,255,
+197,197,255,255,134,134,255,255,25,25,152,255,255,255,0,224,255,255,0,219,255,
+255,0,212,255,255,0,204,255,255,0,196,255,255,0,188,255,255,0,178,255,255,0,168,
+255,255,0,157,255,255,0,146,255,255,0,134,255,255,0,123,255,255,0,111,255,255,0,
+99,255,255,0,87,255,255,0,76,255,255,0,65,255,255,0,54,255,255,0,44,255,255,0,
+35,255,255,0,26,255,255,0,18,255,255,0,11,255,255,0,6,255,255,0,2,255,255,255,
+0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,3,255,255,0,7,255,255,0,
+12,255,255,0,19,255,255,0,27,255,255,0,35,255,255,0,45,255,255,0,56,255,255,0,
+67,255,255,0,78,255,255,0,90,255,255,0,102,255,255,0,114,255,255,0,127,255,255,
+0,139,255,255,0,150,255,255,0,162,255,255,0,172,255,255,0,182,255,255,0,192,
+255,255,0,201,255,255,0,209,255,255,0,217,255,255,0,223,255,255,0,229,0,0,128,
+255,0,0,128,255,0,0,128,255,1,1,129,255,5,5,133,255,19,19,146,255,62,62,189,255,
+149,149,255,255,223,223,255,255,181,181,255,255,54,54,182,255,255,255,0,223,255,
+255,0,217,255,255,0,209,255,255,0,201,255,255,0,192,255,255,0,182,255,255,0,172,
+255,255,0,161,255,255,0,150,255,255,0,138,255,255,0,127,255,255,0,115,255,255,0,
+103,255,255,0,91,255,255,0,80,255,255,0,68,255,255,0,57,255,255,0,46,255,255,0,
+36,255,255,0,27,255,255,0,19,255,255,0,12,255,255,0,6,255,255,0,2,255,255,255,
+0,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,3,255,255,0,8,255,255,0,
+13,255,255,0,20,255,255,0,28,255,255,0,38,255,255,0,47,255,255,0,58,255,255,0,
+69,255,255,0,81,255,255,0,93,255,255,0,105,255,255,0,117,255,255,0,129,255,255,
+0,141,255,255,0,153,255,255,0,164,255,255,0,175,255,255,0,186,255,255,0,196,
+255,255,0,205,255,255,0,213,255,255,0,220,255,255,0,227,255,255,0,233,255,255,0,
+238,255,255,0,242,1,1,128,255,0,0,128,255,1,1,128,255,4,4,131,255,15,15,143,255,
+57,57,184,255,152,152,255,255,240,240,255,255,194,194,255,255,62,62,189,255,
+255,255,0,221,255,255,0,213,255,255,0,204,255,255,0,195,255,255,0,186,255,255,0,
+175,255,255,0,165,255,255,0,154,255,255,0,142,255,255,0,130,255,255,0,118,255,
+255,0,105,255,255,0,93,255,255,0,81,255,255,0,69,255,255,0,58,255,255,0,47,255,
+255,0,37,255,255,0,28,255,255,0,20,255,255,0,13,255,255,0,7,255,255,0,3,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,3,255,255,0,8,255,255,0,
+14,255,255,0,21,255,255,0,30,255,255,0,39,255,255,0,50,255,255,0,61,255,255,0,
+72,255,255,0,84,255,255,0,95,255,255,0,108,255,255,0,120,255,255,0,132,255,255,
+0,144,255,255,0,155,255,255,0,167,255,255,0,178,255,255,0,188,255,255,0,198,
+255,255,0,207,255,255,0,216,255,255,0,224,255,255,0,230,255,255,0,236,255,255,0,
+241,255,255,0,245,255,255,0,248,255,255,0,250,1,1,128,255,1,1,128,255,4,4,131,
+255,18,18,145,255,69,69,196,255,174,174,255,255,251,251,255,255,177,177,255,255,
+48,48,176,255,255,255,0,216,255,255,0,207,255,255,0,199,255,255,0,189,255,255,
+0,178,255,255,0,167,255,255,0,156,255,255,0,144,255,255,0,131,255,255,0,119,
+255,255,0,107,255,255,0,94,255,255,0,82,255,255,0,70,255,255,0,59,255,255,0,48,
+255,255,0,38,255,255,0,29,255,255,0,20,255,255,0,13,255,255,0,7,255,255,0,3,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,3,255,255,0,8,255,
+255,0,14,255,255,0,21,255,255,0,30,255,255,0,39,255,255,0,50,255,255,0,61,255,
+255,0,72,255,255,0,84,255,255,0,96,255,255,0,109,255,255,0,121,255,255,0,134,
+255,255,0,146,255,255,0,158,255,255,0,169,255,255,0,180,255,255,0,190,255,255,0,
+200,255,255,0,209,255,255,0,218,255,255,0,225,255,255,0,232,255,255,0,238,255,
+255,0,243,255,255,0,247,255,255,0,250,255,255,0,252,255,255,0,253,255,255,0,253,
+1,1,129,255,6,6,133,255,28,28,155,255,102,102,230,255,218,218,255,255,254,254,
+255,255,130,130,255,255,24,24,151,255,255,255,0,209,255,255,0,200,255,255,0,190,
+255,255,0,179,255,255,0,168,255,255,0,157,255,255,0,145,255,255,0,133,255,255,0,
+121,255,255,0,108,255,255,0,96,255,255,0,84,255,255,0,72,255,255,0,60,255,255,0,
+49,255,255,0,39,255,255,0,30,255,255,0,21,255,255,0,14,255,255,0,8,255,255,0,3,
+255,255,0,1,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,3,255,255,0,8,255,
+255,0,14,255,255,0,21,255,255,0,30,255,255,0,39,255,255,0,50,255,255,0,61,255,
+255,0,72,255,255,0,84,255,255,0,96,255,255,0,109,255,255,0,121,255,255,0,134,
+255,255,0,146,255,255,0,158,255,255,0,169,255,255,0,180,255,255,0,191,255,255,0,
+201,255,255,0,210,255,255,0,219,255,255,0,226,255,255,0,233,255,255,0,239,255,
+255,0,244,255,255,0,248,255,255,0,251,255,255,0,253,255,255,0,255,255,255,0,255,
+255,255,0,253,2,2,130,255,12,12,140,255,58,58,186,255,163,163,255,255,253,253,
+255,255,195,195,255,255,69,69,196,255,6,6,133,255,255,255,0,201,255,255,0,191,
+255,255,0,181,255,255,0,170,255,255,0,158,255,255,0,146,255,255,0,134,255,255,0,
+122,255,255,0,109,255,255,0,97,255,255,0,85,255,255,0,73,255,255,0,61,255,255,0,
+51,255,255,0,40,255,255,0,31,255,255,0,22,255,255,0,15,255,255,0,9,255,255,0,4,
+255,255,0,1,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,3,255,255,0,8,255,
+255,0,14,255,255,0,21,255,255,0,30,255,255,0,39,255,255,0,50,255,255,0,61,255,
+255,0,72,255,255,0,84,255,255,0,96,255,255,0,109,255,255,0,121,255,255,0,134,
+255,255,0,146,255,255,0,158,255,255,0,169,255,255,0,180,255,255,0,191,255,255,0,
+201,255,255,0,210,255,255,0,219,255,255,0,226,255,255,0,233,255,255,0,239,255,
+255,0,244,255,255,0,248,255,255,0,251,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,253,255,255,0,251,6,6,134,255,35,35,163,255,123,123,250,255,236,236,
+255,255,252,252,255,255,110,110,238,255,23,23,151,255,255,255,0,201,255,255,0,
+191,255,255,0,181,255,255,0,170,255,255,0,158,255,255,0,146,255,255,0,134,255,
+255,0,122,255,255,0,109,255,255,0,97,255,255,0,85,255,255,0,73,255,255,0,61,255,
+255,0,50,255,255,0,40,255,255,0,31,255,255,0,22,255,255,0,15,255,255,0,9,255,
+255,0,4,255,255,0,1,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,3,255,255,
+0,8,255,255,0,14,255,255,0,21,255,255,0,30,255,255,0,39,255,255,0,50,255,255,
+0,61,255,255,0,72,255,255,0,84,255,255,0,96,255,255,0,109,255,255,0,121,255,
+255,0,134,255,255,0,146,255,255,0,158,255,255,0,169,255,255,0,180,255,255,0,190,
+255,255,0,200,255,255,0,209,255,255,0,218,255,255,0,225,255,255,0,232,255,255,0,
+238,255,255,0,243,255,255,0,247,255,255,0,250,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,252,255,255,0,250,4,4,132,255,24,24,151,255,101,101,228,255,
+221,221,255,255,250,250,255,255,134,134,255,255,40,40,167,255,255,255,0,200,255,
+255,0,190,255,255,0,179,255,255,0,168,255,255,0,157,255,255,0,145,255,255,0,133,
+255,255,0,120,255,255,0,108,255,255,0,96,255,255,0,84,255,255,0,72,255,255,0,60,
+255,255,0,49,255,255,0,39,255,255,0,30,255,255,0,21,255,255,0,14,255,255,0,8,
+255,255,0,3,255,255,0,1,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,3,255,
+255,0,8,255,255,0,14,255,255,0,21,255,255,0,30,255,255,0,39,255,255,0,50,255,
+255,0,60,255,255,0,72,255,255,0,83,255,255,0,95,255,255,0,108,255,255,0,120,255,
+255,0,132,255,255,0,144,255,255,0,155,255,255,0,167,255,255,0,178,255,255,0,188,
+255,255,0,198,255,255,0,207,255,255,0,216,255,255,0,224,5,5,132,255,8,8,135,255,
+255,255,0,241,255,255,0,245,255,255,0,248,255,255,0,250,255,255,0,251,255,255,0,
+251,255,255,0,250,255,255,0,248,255,255,0,245,20,20,147,255,98,98,225,255,219,
+219,255,255,249,249,255,255,142,142,255,255,47,47,174,255,8,8,135,255,255,255,0,
+189,255,255,0,178,255,255,0,167,255,255,0,156,255,255,0,144,255,255,0,131,255,
+255,0,119,255,255,0,107,255,255,0,94,255,255,0,82,255,255,0,70,255,255,0,59,255,
+255,0,48,255,255,0,38,255,255,0,29,255,255,0,20,255,255,0,13,255,255,0,7,255,
+255,0,3,255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,3,255,
+255,0,8,255,255,0,13,255,255,0,20,255,255,0,28,255,255,0,38,255,255,0,47,255,
+255,0,58,255,255,0,69,255,255,0,81,255,255,0,93,255,255,0,105,255,255,0,117,255,
+255,0,129,255,255,0,141,6,6,134,255,21,21,149,255,35,35,163,255,47,47,174,255,
+63,63,190,255,74,74,202,255,85,85,213,255,98,98,226,255,105,105,232,255,110,
+110,238,255,113,113,241,255,111,111,239,255,109,109,236,255,100,100,228,255,86,
+86,213,255,72,72,200,255,56,56,183,255,35,35,163,255,20,20,148,255,23,23,150,
+255,115,115,243,255,231,231,255,255,249,249,255,255,131,131,255,255,45,45,172,
+255,10,10,137,255,255,255,0,186,255,255,0,175,255,255,0,165,255,255,0,153,255,
+255,0,142,255,255,0,130,255,255,0,118,255,255,0,105,255,255,0,93,255,255,0,81,
+255,255,0,69,255,255,0,58,255,255,0,47,255,255,0,37,255,255,0,28,255,255,0,20,
+255,255,0,13,255,255,0,7,255,255,0,3,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,0,3,255,255,0,7,255,255,0,12,255,255,0,19,255,255,0,26,
+255,255,0,35,255,255,0,45,255,255,0,56,255,255,0,67,255,255,0,78,255,255,0,90,
+255,255,0,102,9,9,136,255,26,26,154,255,42,42,170,255,60,60,187,255,76,76,203,
+255,92,92,220,255,108,108,236,255,122,122,249,255,136,136,255,255,147,147,255,
+255,158,158,255,255,167,167,255,255,177,177,255,255,185,185,255,255,192,192,255,
+255,199,199,255,255,203,203,255,255,203,203,255,255,200,200,255,255,190,190,255,
+255,174,174,255,255,152,152,255,255,39,39,166,255,158,158,255,255,247,247,255,
+255,208,208,255,255,107,107,234,255,37,37,165,255,9,9,137,255,255,255,0,182,255,
+255,0,172,255,255,0,161,255,255,0,150,255,255,0,138,255,255,0,126,255,255,0,115,
+255,255,0,103,255,255,0,91,255,255,0,80,255,255,0,68,255,255,0,57,255,255,0,46,
+255,255,0,36,255,255,0,27,255,255,0,19,255,255,0,12,255,255,0,6,255,255,0,2,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,2,255,255,0,5,255,
+255,0,11,255,255,0,17,255,255,0,25,255,255,0,33,255,255,0,43,255,255,0,53,255,
+255,0,64,255,255,0,76,10,10,138,255,28,28,156,255,44,44,172,255,57,57,184,255,
+69,69,197,255,81,81,209,255,92,92,219,255,101,101,228,255,108,108,236,255,115,
+115,242,255,120,120,247,255,124,124,251,255,128,128,255,255,133,133,255,255,140,
+140,255,255,146,146,255,255,157,157,255,255,167,167,255,255,179,179,255,255,193,
+193,255,255,206,206,255,255,220,220,255,255,231,231,255,255,237,237,255,255,94,
+94,222,255,218,218,255,255,251,251,255,255,165,165,255,255,76,76,204,255,26,26,
+154,255,8,8,135,255,8,8,136,255,255,255,0,168,255,255,0,157,255,255,0,146,255,
+255,0,134,255,255,0,123,255,255,0,111,255,255,0,99,255,255,0,87,255,255,0,76,
+255,255,0,65,255,255,0,54,255,255,0,44,255,255,0,35,255,255,0,26,255,255,0,18,
+255,255,0,11,255,255,0,6,255,255,0,2,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,0,1,255,255,0,4,255,255,0,9,255,255,0,15,255,255,0,23,255,
+255,0,31,255,255,0,41,255,255,0,51,255,255,0,62,20,20,148,255,35,35,162,255,46,
+46,174,255,53,53,181,255,58,58,185,255,63,63,190,255,68,68,195,255,71,71,199,
+255,73,73,200,255,73,73,201,255,72,72,200,255,72,72,199,255,70,70,198,255,71,71,
+198,255,71,71,198,255,74,74,201,255,76,76,203,255,82,82,209,255,88,88,216,255,
+98,98,225,255,110,110,238,255,123,123,250,255,142,142,255,255,163,163,255,255,
+63,63,191,255,191,191,255,255,253,253,255,255,201,201,255,255,112,112,240,255,
+47,47,174,255,16,16,144,255,6,6,134,255,108,108,236,255,58,58,185,255,22,22,
+149,255,255,255,0,142,255,255,0,130,255,255,0,119,255,255,0,107,255,255,0,95,
+255,255,0,83,255,255,0,72,255,255,0,61,255,255,0,51,255,255,0,41,255,255,0,32,
+255,255,0,23,255,255,0,16,255,255,0,10,255,255,0,5,255,255,0,2,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,4,255,255,0,8,
+255,255,0,14,255,255,0,21,255,255,0,29,255,255,0,39,255,255,0,49,21,21,148,255,
+36,36,164,255,45,45,173,255,46,46,174,255,43,43,171,255,42,42,170,255,43,43,
+170,255,44,44,172,255,44,44,172,255,42,42,170,255,40,40,167,255,37,37,164,255,
+34,34,162,255,32,32,159,255,31,31,158,255,29,29,157,255,30,30,157,255,30,30,
+157,255,32,32,160,255,35,35,162,255,39,39,167,255,45,45,173,255,52,52,180,255,
+64,64,192,255,65,65,192,255,190,190,255,255,254,254,255,255,214,214,255,255,
+133,133,255,255,63,63,190,255,25,25,153,255,9,9,137,255,251,251,255,255,228,228,
+255,255,188,188,255,255,127,127,254,255,68,68,195,255,25,25,152,255,255,255,0,
+115,255,255,0,103,255,255,0,91,255,255,0,80,255,255,0,68,255,255,0,57,255,255,0,
+47,255,255,0,38,255,255,0,29,255,255,0,21,255,255,0,14,255,255,0,8,255,255,0,4,
+255,255,0,1,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,
+0,255,255,0,3,255,255,0,7,255,255,0,13,255,255,0,20,255,255,0,27,255,255,0,35,
+15,15,143,255,33,33,161,255,47,47,174,255,50,50,177,255,42,42,169,255,31,31,
+159,255,26,26,153,255,26,26,153,255,26,26,154,255,25,25,153,255,23,23,150,255,
+19,19,147,255,17,17,144,255,15,15,142,255,13,13,140,255,12,12,139,255,11,11,
+138,255,10,10,138,255,10,10,138,255,11,11,138,255,12,12,139,255,13,13,141,255,
+15,15,143,255,18,18,146,255,107,107,235,255,214,214,255,255,254,254,255,255,
+209,209,255,255,133,133,255,255,68,68,195,255,31,31,158,255,12,12,140,255,6,6,
+133,255,223,223,255,255,246,246,255,255,253,253,255,255,232,232,255,255,186,186,
+255,255,126,126,253,255,66,66,193,255,22,22,149,255,255,255,0,87,255,255,0,76,
+255,255,0,65,255,255,0,54,255,255,0,44,255,255,0,34,255,255,0,26,255,255,0,18,
+255,255,0,12,255,255,0,7,255,255,0,3,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,2,255,255,0,6,255,255,0,11,
+255,255,0,16,255,255,0,23,255,255,0,31,22,22,150,255,41,41,169,255,56,56,184,
+255,60,60,187,255,49,49,177,255,30,30,158,255,16,16,143,255,14,14,142,255,15,15,
+143,255,14,14,142,255,12,12,139,255,9,9,137,255,7,7,135,255,6,6,133,255,5,5,132,
+255,4,4,132,255,4,4,131,255,3,3,131,255,3,3,131,255,3,3,131,255,3,3,131,255,4,4,
+131,255,76,76,204,255,183,183,255,255,246,246,255,255,251,251,255,255,185,185,
+255,255,115,115,243,255,62,62,189,255,29,29,157,255,13,13,141,255,6,6,134,255,5,
+5,133,255,136,136,255,255,177,177,255,255,219,219,255,255,245,245,255,255,250,
+250,255,255,223,223,255,255,169,169,255,255,104,104,231,255,46,46,173,255,9,9,
+137,255,255,255,0,61,255,255,0,51,255,255,0,41,255,255,0,32,255,255,0,23,255,
+255,0,16,255,255,0,10,255,255,0,5,255,255,0,2,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,4,255,
+255,0,8,255,255,0,14,255,255,0,20,11,11,138,255,24,24,152,255,43,43,170,255,61,
+61,189,255,75,75,202,255,75,75,203,255,61,61,189,255,37,37,165,255,13,13,140,
+255,10,10,137,255,8,8,136,255,6,6,134,255,4,4,132,255,3,3,131,255,2,2,130,255,2,
+2,129,255,1,1,129,255,1,1,129,255,1,1,129,255,1,1,128,255,37,37,164,255,114,
+114,241,255,194,194,255,255,242,242,255,255,242,242,255,255,246,246,255,255,142,
+142,255,255,86,86,214,255,48,48,176,255,24,24,151,255,11,11,139,255,6,6,133,255,
+4,4,131,255,44,44,171,255,65,65,192,255,98,98,225,255,138,138,255,255,180,180,
+255,255,223,223,255,255,246,246,255,255,239,239,255,255,200,200,255,255,136,136,
+255,255,69,69,197,255,23,23,150,255,255,255,0,46,255,255,0,37,255,255,0,29,255,
+255,0,21,255,255,0,14,255,255,0,8,255,255,0,4,255,255,0,1,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,0,3,255,255,0,6,255,255,0,11,255,255,0,17,10,10,138,255,28,28,155,255,35,35,
+163,255,55,55,183,255,75,75,203,255,92,92,220,255,101,101,229,255,100,100,228,
+255,90,90,217,255,73,73,200,255,56,56,184,255,40,40,168,255,30,30,158,255,24,24,
+151,255,29,29,156,255,42,42,169,255,64,64,192,255,100,100,228,255,144,144,255,
+255,191,191,255,255,225,225,255,255,237,237,255,255,228,228,255,255,234,234,255,
+255,139,139,255,255,91,91,219,255,56,56,183,255,31,31,158,255,16,16,144,255,8,8,
+136,255,4,4,132,255,3,3,131,255,10,10,138,255,16,16,144,255,27,27,155,255,45,45,
+172,255,70,70,197,255,106,106,234,255,153,153,255,255,198,198,255,255,232,232,
+255,255,241,241,255,255,211,211,255,255,152,152,255,255,85,85,213,255,33,33,160,
+255,255,255,0,32,255,255,0,25,255,255,0,18,255,255,0,12,255,255,0,7,255,255,0,3,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,4,255,255,0,9,255,255,0,
+14,8,8,135,255,14,14,142,255,25,25,152,255,45,45,173,255,55,55,183,255,75,75,
+202,255,96,96,223,255,114,114,241,255,130,130,255,255,141,141,255,255,150,150,
+255,255,157,157,255,255,165,165,255,255,173,173,255,255,184,184,255,255,196,196,
+255,255,206,206,255,255,212,212,255,255,210,210,255,255,202,202,255,255,211,211,
+255,255,141,141,255,255,109,109,236,255,75,75,202,255,50,50,177,255,30,30,157,
+255,17,17,145,255,10,10,137,255,5,5,133,255,3,3,131,255,2,2,130,255,6,6,134,255,
+3,3,131,255,6,6,133,255,10,10,138,255,18,18,146,255,31,31,158,255,54,54,181,
+255,86,86,213,255,127,127,254,255,178,178,255,255,220,220,255,255,236,236,255,
+255,218,218,255,255,163,163,255,255,94,94,221,255,38,38,165,255,7,7,134,255,255,
+255,0,14,255,255,0,9,255,255,0,5,255,255,0,2,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,0,3,255,255,0,6,255,255,0,11,6,6,133,255,9,9,136,255,13,
+13,141,255,21,21,148,255,30,30,158,255,65,65,192,255,72,72,200,255,81,81,208,
+255,90,90,217,255,102,102,230,255,114,114,242,255,127,127,254,255,134,134,255,
+255,140,140,255,255,150,150,255,255,161,161,255,255,171,171,255,255,181,181,255,
+255,103,103,231,255,84,84,212,255,67,67,195,255,48,48,176,255,34,34,161,255,22,
+22,150,255,14,14,141,255,9,9,136,255,5,5,133,255,3,3,131,255,2,2,129,255,2,2,
+129,255,6,6,134,255,1,1,128,255,1,1,129,255,2,2,130,255,4,4,131,255,7,7,134,255,
+13,13,141,255,24,24,152,255,42,42,169,255,73,73,200,255,115,115,243,255,163,
+163,255,255,208,208,255,255,230,230,255,255,212,212,255,255,159,159,255,255,92,
+92,219,255,38,38,165,255,5,5,133,255,255,255,0,6,255,255,0,3,255,255,0,1,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,4,255,255,0,9,5,
+5,132,255,5,5,132,255,7,7,134,255,10,10,137,255,13,13,141,255,18,18,146,255,
+24,24,151,255,30,30,158,255,37,37,164,255,43,43,171,255,48,48,176,255,54,54,
+181,255,55,55,183,255,56,56,184,255,54,54,182,255,51,51,178,255,45,45,173,255,
+38,38,166,255,32,32,159,255,24,24,152,255,18,18,146,255,13,13,140,255,9,9,136,
+255,6,6,133,255,4,4,131,255,2,2,130,255,2,2,129,255,1,1,129,255,1,1,129,255,255,
+255,0,146,1,1,128,255,0,0,128,255,0,0,128,255,1,1,128,255,1,1,129,255,3,3,130,
+255,5,5,133,255,10,10,138,255,20,20,147,255,38,38,165,255,65,65,193,255,107,107,
+235,255,159,159,255,255,204,204,255,255,223,223,255,255,205,205,255,255,150,150,
+255,255,84,84,212,255,34,34,161,255,255,255,0,4,255,255,0,1,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,3,255,255,0,6,
+255,255,0,10,3,3,131,255,3,3,131,255,4,4,132,255,5,5,133,255,7,7,134,255,9,9,
+136,255,10,10,138,255,12,12,140,255,14,14,142,255,15,15,143,255,16,16,144,255,
+16,16,144,255,16,16,144,255,15,15,143,255,14,14,141,255,12,12,139,255,10,10,
+137,255,8,8,135,255,6,6,133,255,4,4,132,255,3,3,131,255,2,2,130,255,2,2,129,255,
+1,1,129,255,1,1,128,255,1,1,128,255,2,2,129,255,255,255,0,139,255,255,0,134,
+255,255,0,130,255,255,0,125,4,4,132,255,1,1,128,255,1,1,128,255,1,1,129,255,2,2,
+130,255,4,4,132,255,9,9,136,255,18,18,146,255,35,35,162,255,65,65,193,255,108,
+108,235,255,157,157,255,255,203,203,255,255,216,216,255,255,189,189,255,255,132,
+132,255,255,70,70,198,255,25,25,152,255,255,255,255,0,255,255,255,0,255,255,255,
+0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,3,255,
+255,0,7,255,255,0,11,2,2,130,255,2,2,130,255,2,2,130,255,3,3,130,255,3,3,130,
+255,3,3,131,255,4,4,131,255,4,4,132,255,4,4,132,255,4,4,132,255,4,4,132,255,4,4,
+132,255,4,4,131,255,3,3,131,255,3,3,130,255,2,2,130,255,2,2,129,255,1,1,129,255,
+1,1,128,255,1,1,128,255,1,1,128,255,0,0,128,255,1,1,128,255,1,1,129,255,255,
+255,0,131,255,255,0,129,255,255,0,127,255,255,0,123,255,255,0,118,255,255,0,114,
+255,255,0,109,255,255,0,103,255,255,0,96,1,1,129,255,1,1,129,255,2,2,129,255,4,
+4,132,255,9,9,136,255,19,19,146,255,37,37,165,255,68,68,195,255,116,116,244,
+255,168,168,255,255,204,204,255,255,208,208,255,255,185,185,255,255,149,149,255,
+255,82,82,209,255,17,17,144,255,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,2,255,255,0,4,255,255,0,8,
+255,255,0,13,2,2,129,255,1,1,129,255,1,1,129,255,1,1,129,255,1,1,129,255,1,1,
+129,255,1,1,129,255,1,1,129,255,1,1,129,255,1,1,129,255,1,1,128,255,1,1,128,255,
+1,1,128,255,1,1,128,255,0,0,128,255,0,0,128,255,0,0,128,255,0,0,128,255,0,0,
+128,255,0,0,128,255,1,1,129,255,255,255,0,122,255,255,0,121,255,255,0,119,255,
+255,0,117,255,255,0,115,255,255,0,111,255,255,0,107,255,255,0,102,255,255,0,97,
+255,255,0,92,255,255,0,85,255,255,0,79,255,255,0,72,1,1,129,255,2,2,130,255,4,4,
+132,255,10,10,137,255,20,20,148,255,43,43,171,255,81,81,209,255,129,129,255,255,
+190,190,255,255,244,244,255,255,250,250,255,255,208,208,255,255,137,137,255,255,
+63,63,191,255,19,19,147,255,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,0,2,255,255,0,5,255,255,0,9,255,
+255,0,14,3,3,130,255,1,1,129,255,1,1,128,255,1,1,128,255,0,0,128,255,0,0,128,
+255,0,0,128,255,0,0,128,255,0,0,128,255,0,0,128,255,0,0,128,255,0,0,128,255,0,0,
+128,255,0,0,128,255,0,0,128,255,0,0,128,255,1,1,128,255,3,3,130,255,255,255,0,
+108,255,255,0,109,255,255,0,109,255,255,0,109,255,255,0,107,255,255,0,105,255,
+255,0,103,255,255,0,100,255,255,0,95,255,255,0,91,255,255,0,86,255,255,0,82,255,
+255,0,76,255,255,0,69,255,255,0,62,255,255,0,56,2,2,129,255,2,2,130,255,5,5,133,
+255,11,11,139,255,27,27,154,255,54,54,181,255,95,95,222,255,142,142,255,255,176,
+176,255,255,182,182,255,255,158,158,255,255,114,114,241,255,65,65,193,255,27,27,
+154,255,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,0,1,255,255,0,3,255,255,0,6,255,255,0,10,255,255,0,
+14,255,255,0,19,255,255,0,24,3,3,130,255,1,1,129,255,1,1,128,255,1,1,128,255,1,
+1,128,255,0,0,128,255,0,0,128,255,0,0,128,255,1,1,128,255,1,1,129,255,2,2,130,
+255,255,255,0,87,255,255,0,90,255,255,0,93,255,255,0,95,255,255,0,96,255,255,0,
+96,255,255,0,97,255,255,0,96,255,255,0,94,255,255,0,92,255,255,0,90,255,255,0,
+88,255,255,0,84,255,255,0,79,255,255,0,75,255,255,0,70,255,255,0,66,255,255,0,
+59,255,255,0,53,255,255,0,47,255,255,0,41,255,255,0,36,3,3,130,255,7,7,134,255,
+16,16,144,255,31,31,159,255,51,51,179,255,70,70,198,255,84,84,211,255,87,87,
+214,255,80,80,207,255,62,62,190,255,42,42,170,255,23,23,150,255,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,0,1,255,255,0,3,255,255,0,6,255,255,0,9,255,255,0,13,255,255,
+0,18,255,255,0,23,255,255,0,28,255,255,0,34,255,255,0,40,255,255,0,45,255,255,
+0,50,255,255,0,55,255,255,0,60,255,255,0,65,255,255,0,69,255,255,0,72,255,255,
+0,75,255,255,0,79,255,255,0,82,255,255,0,83,255,255,0,83,255,255,0,84,255,255,
+0,85,255,255,0,84,255,255,0,82,255,255,0,80,255,255,0,78,255,255,0,77,255,255,
+0,73,255,255,0,68,255,255,0,64,255,255,0,60,255,255,0,56,255,255,0,50,255,255,
+0,44,255,255,0,39,255,255,0,33,255,255,0,28,255,255,0,23,4,4,132,255,10,10,
+137,255,15,15,142,255,21,21,148,255,27,27,154,255,31,31,158,255,32,32,160,255,
+30,30,158,255,26,26,154,255,20,20,147,255,13,13,141,255,7,7,135,255,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,0,1,255,255,0,3,255,255,0,5,255,255,0,9,255,255,0,13,255,
+255,0,17,255,255,0,22,255,255,0,27,255,255,0,31,255,255,0,36,255,255,0,40,255,
+255,0,45,255,255,0,50,255,255,0,55,255,255,0,58,255,255,0,61,255,255,0,64,255,
+255,0,67,255,255,0,70,255,255,0,71,255,255,0,71,255,255,0,72,255,255,0,73,255,
+255,0,72,255,255,0,71,255,255,0,69,255,255,0,67,255,255,0,65,255,255,0,62,255,
+255,0,58,255,255,0,54,255,255,0,50,255,255,0,46,255,255,0,42,255,255,0,36,255,
+255,0,31,255,255,0,26,255,255,0,21,255,255,0,17,255,255,0,13,6,6,133,255,6,6,
+133,255,7,7,135,255,9,9,136,255,10,10,137,255,10,10,138,255,10,10,138,255,9,9,
+137,255,8,8,136,255,7,7,134,255,7,7,134,255,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,0,1,255,255,0,3,255,255,0,5,255,255,0,8,255,255,0,12,255,255,0,16,255,
+255,0,20,255,255,0,24,255,255,0,28,255,255,0,32,255,255,0,36,255,255,0,41,255,
+255,0,45,255,255,0,47,255,255,0,50,255,255,0,53,255,255,0,56,255,255,0,59,255,
+255,0,59,255,255,0,60,255,255,0,61,255,255,0,61,255,255,0,61,255,255,0,59,255,
+255,0,57,255,255,0,56,255,255,0,54,255,255,0,52,255,255,0,48,255,255,0,44,255,
+255,0,40,255,255,0,36,255,255,0,33,255,255,0,28,255,255,0,24,255,255,0,19,255,
+255,0,15,255,255,0,11,255,255,0,8,4,4,132,255,2,2,130,255,2,2,130,255,3,3,130,
+255,3,3,130,255,3,3,130,255,3,3,131,255,3,3,131,255,3,3,131,255,4,4,131,255,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,1,255,
+255,0,2,255,255,0,4,255,255,0,8,255,255,0,11,255,255,0,14,255,255,0,17,255,255,
+0,20,255,255,0,24,255,255,0,28,255,255,0,32,255,255,0,35,255,255,0,38,255,255,
+0,40,255,255,0,43,255,255,0,46,255,255,0,48,255,255,0,48,255,255,0,49,255,255,
+0,50,255,255,0,50,255,255,0,50,255,255,0,48,255,255,0,47,255,255,0,45,255,255,
+0,43,255,255,0,42,255,255,0,38,255,255,0,34,255,255,0,31,255,255,0,28,255,255,
+0,24,255,255,0,22,255,255,0,17,255,255,0,13,255,255,0,10,255,255,0,7,255,255,
+0,4,255,255,0,2,1,1,129,255,1,1,128,255,1,1,128,255,1,1,128,255,1,1,128,255,1,
+1,128,255,1,1,129,255,2,2,129,255,4,4,131,255,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,2,255,
+255,0,4,255,255,0,6,255,255,0,8,255,255,0,11,255,255,0,14,255,255,0,17,255,255,
+0,21,255,255,0,24,255,255,0,26,255,255,0,29,255,255,0,31,255,255,0,34,255,255,
+0,36,255,255,0,38,255,255,0,38,255,255,0,39,255,255,0,39,255,255,0,40,255,255,
+0,40,255,255,0,38,255,255,0,37,255,255,0,35,255,255,0,34,255,255,0,32,255,255,
+0,29,255,255,0,26,255,255,0,23,255,255,0,20,255,255,0,17,255,255,0,15,255,255,
+0,12,255,255,0,8,255,255,0,6,255,255,0,3,255,255,0,2,255,255,255,0,255,255,
+255,0,1,1,128,255,0,0,128,255,0,0,128,255,0,0,128,255,0,0,128,255,1,1,128,255,2,
+2,130,255,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,
+0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,3,
+255,255,0,4,255,255,0,6,255,255,0,9,255,255,0,11,255,255,0,14,255,255,0,16,255,
+255,0,19,255,255,0,21,255,255,0,23,255,255,0,25,255,255,0,27,255,255,0,28,255,
+255,0,29,255,255,0,29,255,255,0,30,255,255,0,30,255,255,0,31,255,255,0,29,255,
+255,0,28,255,255,0,26,255,255,0,25,255,255,0,23,255,255,0,22,255,255,0,19,255,
+255,0,16,255,255,0,13,255,255,0,11,255,255,0,9,255,255,0,7,255,255,0,4,255,255,
+0,2,255,255,0,1,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,1,1,128,255,1,1,128,255,1,1,129,255,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,1,
+255,255,0,3,255,255,0,4,255,255,0,6,255,255,0,9,255,255,0,10,255,255,0,12,255,
+255,0,14,255,255,0,15,255,255,0,17,255,255,0,19,255,255,0,20,255,255,0,20,255,
+255,0,21,255,255,0,21,255,255,0,22,255,255,0,22,255,255,0,21,255,255,0,20,255,
+255,0,18,255,255,0,17,255,255,0,16,255,255,0,15,255,255,0,12,255,255,0,10,255,
+255,0,8,255,255,0,6,255,255,0,4,255,255,0,3,255,255,0,2,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,0,1,255,255,0,3,255,255,0,4,255,255,0,5,255,255,0,7,255,255,0,8,
+255,255,0,9,255,255,0,11,255,255,0,13,255,255,0,13,255,255,0,13,255,255,0,14,
+255,255,0,14,255,255,0,14,255,255,0,15,255,255,0,14,255,255,0,13,255,255,0,12,
+255,255,0,11,255,255,0,9,255,255,0,9,255,255,0,7,255,255,0,5,255,255,0,4,255,
+255,0,2,255,255,0,1,255,255,0,1,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,0,1,255,255,0,2,255,255,0,3,255,255,0,4,255,255,
+0,5,255,255,0,6,255,255,0,7,255,255,0,7,255,255,0,7,255,255,0,8,255,255,0,8,
+255,255,0,8,255,255,0,9,255,255,0,8,255,255,0,7,255,255,0,6,255,255,0,5,255,255,
+0,5,255,255,0,4,255,255,0,3,255,255,0,2,255,255,0,1,255,255,255,0,255,255,255,
+0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,1,255,
+255,0,2,255,255,0,3,255,255,0,3,255,255,0,3,255,255,0,3,255,255,0,3,255,255,0,4,
+255,255,0,4,255,255,0,3,255,255,0,3,255,255,0,2,255,255,0,2,255,255,0,1,255,255,
+0,1,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,0,1,255,255,0,1,255,255,
+0,1,255,255,0,1,255,255,0,1,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0};
+MGL_EXPORT Fl_RGB_Image img_udav(idata_udav, 64, 64, 4, 0);
+
+static const unsigned char idata_fname[] =
+{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,127,180,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,137,0,83,64,180,65,216,91,195,91,253,64,180,65,217,0,137,0,83,0,0,
+0,0,84,127,181,201,81,128,183,255,81,127,183,255,82,127,183,255,82,126,184,
+255,86,132,187,212,0,0,0,0,0,0,0,0,0,0,0,0,0,146,0,80,69,198,69,255,135,219,120,
+254,255,255,255,255,135,220,120,254,69,198,69,255,0,140,0,83,73,114,166,255,143,
+185,239,255,142,182,234,255,144,184,235,255,147,187,239,255,75,121,177,254,81,
+127,183,255,81,128,185,255,88,125,200,255,1,154,14,255,45,182,26,254,61,170,0,
+255,255,255,255,255,61,170,0,255,45,182,26,254,0,158,0,216,61,99,146,255,134,
+175,225,255,86,140,205,255,88,140,207,255,121,163,216,255,138,175,224,255,136,
+175,225,255,135,175,225,255,145,174,246,255,0,136,0,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,139,0,253,47,81,122,
+255,119,162,214,255,82,131,194,255,85,133,194,255,82,132,194,255,79,127,191,255,
+58,106,163,255,46,91,147,255,51,87,160,255,0,160,0,255,0,151,0,255,11,134,0,
+255,255,255,255,255,11,134,0,255,0,151,0,255,0,172,0,215,32,61,96,255,73,112,
+159,255,39,83,138,255,42,85,139,255,42,85,140,255,34,76,127,255,109,143,177,255,
+190,221,244,255,191,219,246,255,124,206,162,255,0,176,0,255,0,151,0,255,255,255,
+255,255,0,151,0,255,0,178,0,255,84,180,114,194,84,121,159,255,199,228,248,255,
+186,218,241,255,188,220,242,255,188,220,242,255,187,219,243,255,180,212,237,255,
+142,177,220,255,137,173,219,255,145,173,229,255,95,185,150,255,5,183,12,255,0,
+158,0,255,6,184,12,255,101,193,159,255,80,97,126,255,83,124,169,255,139,176,223,
+255,135,170,217,255,135,170,217,255,134,170,217,255,134,170,217,255,136,171,218,
+255,135,174,218,255,140,174,218,255,139,174,219,255,140,174,223,255,149,173,236,
+255,153,173,242,255,149,173,235,255,147,181,232,255,78,99,125,255,82,123,170,
+255,141,177,223,255,135,172,218,255,135,172,218,255,137,172,218,255,134,172,218,
+255,135,172,218,255,135,172,218,255,134,172,218,255,138,172,218,255,134,172,218,
+255,135,172,218,255,135,172,218,255,135,172,217,255,140,179,228,255,78,98,125,
+255,81,122,170,255,137,175,222,255,132,170,217,255,133,170,217,255,131,170,217,
+255,133,170,217,255,131,169,217,255,132,170,217,255,133,170,217,255,132,170,217,
+255,131,170,217,255,133,170,217,255,132,170,217,255,132,169,217,255,139,177,227,
+255,74,97,124,255,80,121,169,255,135,172,221,255,128,167,216,255,129,167,216,
+255,129,167,216,255,130,167,216,255,129,167,216,255,130,167,216,255,128,167,216,
+255,128,167,216,255,128,167,216,255,130,167,216,255,129,167,216,255,129,167,216,
+255,135,174,225,255,73,95,123,255,81,122,170,255,137,174,224,255,131,169,219,
+255,131,169,219,255,134,169,219,255,133,169,219,255,135,169,219,255,133,169,219,
+255,132,169,219,255,133,169,219,255,134,169,219,255,132,169,219,255,134,169,219,
+255,132,169,218,255,137,177,228,255,75,95,124,255,57,103,155,255,64,118,180,255,
+63,116,176,255,63,116,176,255,63,116,176,255,62,116,176,255,64,116,176,255,63,
+116,176,255,64,116,176,255,63,116,176,255,63,116,176,255,63,116,176,255,63,116,
+176,255,63,116,176,255,67,122,185,255,39,68,102,255,88,127,173,255,135,173,223,
+255,132,169,218,255,133,169,218,255,134,169,218,255,133,169,218,255,132,169,218,
+255,132,169,218,255,133,169,218,255,134,169,218,255,133,169,218,255,131,169,218,
+255,133,169,218,255,132,169,218,255,138,176,227,255,80,100,129,255,74,117,167,
+185,129,168,221,255,125,163,217,255,126,164,217,255,124,163,217,255,120,163,217,
+255,125,163,217,255,126,164,217,255,126,164,217,255,126,163,217,255,121,163,217,
+255,122,163,217,255,126,164,217,255,126,163,216,255,129,169,224,255,70,95,128,
+174,0,22,53,68,0,18,48,129,0,18,48,130,0,17,47,132,0,18,47,133,0,17,46,134,0,17,
+46,136,0,17,46,137,0,16,45,137,0,17,46,136,0,17,46,134,0,17,47,133,0,17,47,132,
+0,18,48,130,0,17,48,129,0,25,58,69};
+MGL_EXPORT Fl_RGB_Image img_fname(idata_fname, 16, 16, 4, 0);
+
+static const unsigned char idata_curve[] =
+{255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,117,171,247,9,117,171,247,113,117,171,247,175,117,171,247,221,117,171,
+247,207,117,171,247,173,117,171,247,78,255,255,255,0,255,255,255,0,255,255,255,
+0,246,0,0,162,246,0,0,169,255,255,255,0,255,255,255,0,255,255,255,0,102,162,
+246,68,102,162,246,223,102,162,246,163,102,162,246,83,102,162,246,32,102,162,
+246,44,102,162,246,89,102,162,246,214,102,162,246,185,102,162,246,17,255,255,
+255,0,246,0,0,178,215,0,16,213,0,0,116,11,255,255,255,0,87,153,245,37,87,153,
+245,234,87,153,245,63,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,87,153,245,5,87,153,245,159,87,153,245,156,255,255,255,0,255,255,
+255,0,0,0,121,21,6,0,127,131,255,255,255,0,72,143,244,151,72,143,244,128,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,72,143,244,13,5,7,53,255,5,7,53,255,255,255,255,0,255,255,255,0,
+255,255,255,0,7,0,126,71,53,125,234,172,57,134,242,87,255,255,255,0,255,255,255,
+0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,5,7,53,255,5,7,53,255,255,255,255,0,255,255,255,0,255,255,255,0,11,0,
+122,23,16,34,157,198,43,124,240,169,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,19,
+76,202,12,235,5,11,253,244,1,2,250,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,244,
+1,2,250,246,0,0,255,8,68,193,20,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,8,95,229,
+160,9,84,217,164,0,0,128,10,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,9,104,239,14,8,94,228,227,6,
+17,145,175,0,0,128,10,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,9,104,239,89,9,92,226,190,11,0,
+122,23,0,0,128,10,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,9,104,239,44,9,104,239,216,11,0,122,23,5,0,127,147,
+0,0,128,10,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
+255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,9,104,239,106,9,104,239,174,255,255,255,0,12,0,128,22,215,0,17,199,
+246,0,0,188,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,
+0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,9,104,239,87,9,104,
+239,230,9,104,239,48,255,255,255,0,255,255,255,0,246,0,0,188,246,0,0,203,255,0,
+0,1,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,9,5,
+53,255,9,5,53,255,9,104,239,223,9,104,239,224,9,104,239,43,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,0,0,1,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,9,5,53,255,9,5,53,255,9,104,
+239,36,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
+255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0};
+MGL_EXPORT Fl_RGB_Image img_curve(idata_curve, 16, 16, 4, 0);
+
+static const unsigned char idata_svn[] =
+{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,248,248,248,93,250,250,250,167,251,251,251,
+212,252,252,252,235,252,252,252,239,252,252,252,224,250,250,250,189,249,249,249,
+129,248,248,248,29,0,0,0,0,239,239,239,0,0,0,0,0,0,0,0,0,0,0,0,0,235,235,235,74,
+238,238,238,253,242,242,242,255,244,244,244,254,247,247,247,255,249,249,249,255,
+249,249,249,255,248,248,248,255,246,246,246,255,243,243,243,255,240,240,240,255,
+237,237,237,170,0,0,0,0,225,225,225,0,125,125,125,0,222,222,222,41,226,226,226,
+255,226,226,226,254,230,230,230,255,238,238,238,255,240,240,240,255,242,242,242,
+255,243,243,243,255,242,242,242,255,239,239,239,255,235,235,235,255,229,229,229,
+255,225,225,225,255,225,225,225,165,0,0,0,0,0,0,0,0,196,196,196,112,212,212,212,
+255,210,210,210,255,217,217,217,255,223,223,223,255,226,226,226,255,228,228,228,
+255,229,229,229,255,227,227,227,255,225,225,225,255,221,221,221,255,213,213,213,
+255,212,212,212,255,204,204,204,233,0,0,0,0,0,0,0,0,150,150,150,116,178,178,178,
+255,198,198,198,255,196,196,196,255,196,196,196,255,200,200,200,255,202,202,202,
+255,202,202,202,255,202,202,202,255,198,198,198,255,197,197,197,255,198,198,198,
+255,191,191,191,255,155,155,155,237,0,0,0,0,0,0,0,0,136,136,136,116,135,135,135,
+255,180,180,180,255,194,194,194,255,195,195,195,255,196,196,196,255,196,196,196,
+255,197,197,197,255,197,197,197,255,197,197,197,255,192,192,192,255,188,188,188,
+255,173,173,173,255,113,113,113,236,0,0,0,0,0,0,0,0,147,147,147,118,118,118,118,
+255,115,115,115,255,163,163,163,255,225,225,225,255,206,206,206,255,212,211,212,
+255,214,214,214,255,204,204,204,255,221,221,221,255,209,209,209,255,105,105,105,
+255,125,125,125,255,135,135,135,239,0,0,0,0,0,0,0,0,140,140,140,114,131,131,131,
+255,151,151,151,255,130,130,130,255,170,170,170,255,154,158,163,255,94,118,155,
+255,99,122,159,255,122,139,165,255,166,166,165,255,144,144,144,255,133,133,133,
+255,167,167,167,255,113,113,113,235,0,0,0,0,0,0,0,0,141,141,141,119,125,125,125,
+255,111,111,111,255,152,152,152,255,231,231,231,255,100,123,156,255,152,178,196,
+255,144,171,192,255,75,110,153,255,229,227,223,255,208,208,208,255,98,98,98,255,
+127,127,127,255,134,134,134,239,0,0,0,0,0,0,0,0,94,94,94,47,125,125,125,255,157,
+156,155,254,80,101,133,255,114,139,176,255,61,102,165,255,101,128,156,255,98,
+127,157,255,66,107,164,255,116,140,177,255,84,108,145,255,123,129,138,255,165,
+165,165,255,89,89,89,168,0,0,0,0,0,0,0,0,0,0,0,0,71,71,71,80,113,112,111,249,42,
+62,92,255,73,100,133,254,84,112,146,255,85,116,155,255,86,118,158,255,84,114,
+152,255,79,107,140,255,69,93,126,255,87,93,102,255,106,106,106,171,0,0,0,0,61,
+61,61,0,0,0,0,0,59,59,59,0,0,0,0,0,0,0,0,1,68,68,69,92,28,53,86,243,74,108,157,
+254,92,125,175,255,98,132,180,255,91,124,171,255,69,98,141,255,15,30,52,173,55,
+53,49,35,0,0,0,0,61,61,61,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,59,59,0,0,0,0,0,
+0,13,40,56,65,98,140,255,106,143,196,255,112,149,202,255,102,140,195,254,26,
+47,75,216,0,0,0,0,77,77,82,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,7,23,42,143,123,161,207,255,144,179,230,254,65,93,122,
+255,0,0,5,19,7,24,49,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,6,22,45,0,0,0,0,0,32,53,68,222,112,154,190,255,0,0,0,87,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,2,10,21,0,0,0,0,27,28,53,60,157,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0};
+MGL_EXPORT Fl_RGB_Image img_svn(idata_svn, 16, 16, 4, 0);
+
+static const unsigned char idata_adjust[] =
+{0,0,0,24,0,0,0,51,0,0,0,51,0,0,0,51,0,0,0,51,0,0,0,51,0,0,0,51,0,0,0,51,0,
+0,0,51,0,0,0,51,0,0,0,51,0,0,0,51,0,0,0,51,0,0,0,51,0,0,0,51,0,0,0,24,0,0,0,
+51,243,243,244,255,243,243,244,255,243,243,244,255,243,243,244,255,243,243,244,
+255,243,243,244,255,243,243,244,255,243,243,244,255,243,243,244,255,243,243,244,
+255,243,243,244,255,243,243,244,255,243,243,244,255,243,243,244,255,0,0,0,51,0,
+0,0,51,222,222,224,255,222,222,224,255,222,222,224,255,222,222,224,255,222,
+222,224,255,222,222,224,255,222,222,224,255,222,222,224,255,222,222,224,255,222,
+222,224,255,222,222,224,255,222,222,224,255,222,222,224,255,222,222,224,255,0,0,
+0,51,0,0,0,51,207,207,209,255,207,207,209,255,207,207,209,255,207,207,209,255,
+207,207,209,255,207,207,209,255,207,207,209,255,207,207,209,255,207,207,209,255,
+207,207,209,255,207,207,209,255,207,207,209,255,207,207,209,255,207,207,209,255,
+0,0,0,51,0,0,0,51,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,0,0,0,51,0,0,0,51,255,255,255,255,185,60,60,255,198,94,94,255,222,161,161,
+255,254,254,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,254,253,253,255,221,160,160,255,197,94,94,255,186,62,62,255,255,255,255,255,
+0,0,0,51,0,0,0,51,255,255,255,255,197,93,93,255,164,0,0,255,221,159,159,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,220,156,156,255,164,0,0,255,198,96,96,255,255,255,255,255,0,0,0,
+51,0,0,0,51,255,255,255,255,221,160,160,255,220,158,158,255,193,82,82,255,247,
+231,231,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,246,
+230,230,255,193,82,82,255,220,157,157,255,222,162,162,255,255,255,255,255,0,0,0,
+51,0,0,0,51,255,255,255,255,254,253,253,255,255,255,255,255,246,231,231,255,
+247,233,233,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+247,232,232,255,247,232,232,255,255,255,255,255,254,253,253,255,255,255,255,255,
+0,0,0,51,0,0,0,51,255,255,255,255,254,253,253,255,255,255,255,255,247,233,233,
+255,246,229,229,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,245,228,228,255,248,234,234,255,255,255,255,255,254,253,253,255,255,255,255,
+255,0,0,0,51,0,0,0,51,255,255,255,255,223,165,165,255,219,153,153,255,193,82,82,
+255,246,229,229,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,245,228,228,255,193,82,82,255,218,152,152,255,224,168,168,255,255,255,255,
+255,0,0,0,51,0,0,0,51,255,255,255,255,200,100,100,255,164,0,0,255,218,151,151,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,216,147,147,255,164,0,0,255,201,103,103,255,255,255,255,255,
+0,0,0,51,0,0,0,51,255,255,255,255,188,67,67,255,198,94,94,255,221,160,160,255,
+254,253,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+254,252,252,255,221,159,159,255,197,94,94,255,189,70,70,255,255,255,255,255,0,0,
+0,51,0,0,0,51,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+0,0,0,51,0,0,0,24,0,0,0,51,0,0,0,51,0,0,0,51,0,0,0,51,0,0,0,51,0,0,0,51,0,0,0,
+51,0,0,0,51,0,0,0,51,0,0,0,51,0,0,0,51,0,0,0,51,0,0,0,51,0,0,0,51,0,0,0,24,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+MGL_EXPORT Fl_RGB_Image img_adjust(idata_adjust, 16, 16, 4, 0);
+
+static const unsigned char idata_reload[] =
+{255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,0,77,0,35,0,79,0,
+126,3,91,3,192,36,118,36,241,55,130,55,243,22,104,22,201,0,80,0,133,0,77,0,36,
+255,255,255,0,255,255,255,0,0,77,0,28,0,77,0,32,255,255,255,0,255,255,255,0,0,
+77,0,2,0,78,0,115,19,112,19,247,94,165,94,255,121,186,121,255,146,206,146,255,
+149,208,149,255,134,193,134,255,99,168,99,255,18,110,18,247,0,79,0,122,0,77,0,
+69,15,104,14,242,8,89,7,234,255,255,255,0,0,77,0,2,2,84,1,193,59,140,57,250,
+124,189,124,255,126,195,126,255,126,195,126,255,126,195,126,255,126,195,126,255,
+126,195,126,255,126,195,126,255,123,189,123,255,65,143,63,250,18,114,15,251,115,
+182,114,255,4,95,2,255,255,255,255,0,1,79,0,116,50,124,45,250,112,180,112,255,
+109,179,109,255,110,179,110,255,91,160,91,255,64,135,64,255,65,134,65,255,100,
+163,100,255,109,179,109,255,109,179,109,255,111,180,111,255,111,178,111,255,113,
+181,113,255,6,95,3,255,0,77,0,39,21,101,16,247,87,156,87,255,93,164,93,255,90,
+160,90,255,40,111,40,255,3,78,2,255,10,75,7,255,19,81,16,255,5,79,3,255,22,106,
+22,255,76,157,76,255,93,171,93,255,93,170,93,255,96,169,96,255,8,96,5,255,1,78,
+0,132,48,116,44,254,76,148,76,255,76,148,76,255,31,104,31,255,10,82,5,254,14,
+86,7,248,4,80,2,180,3,79,2,177,13,81,7,248,6,98,3,254,6,125,6,255,68,167,68,
+255,76,166,76,255,77,160,77,255,11,97,6,255,8,88,5,197,47,113,44,255,58,132,58,
+255,44,117,44,255,4,76,2,255,14,86,7,245,0,77,0,36,255,255,255,0,0,77,0,49,13,
+82,7,246,5,143,4,255,28,174,28,255,55,178,55,255,59,166,59,255,44,143,44,255,
+12,95,6,254,13,95,7,245,39,110,39,255,43,117,43,255,21,97,21,255,7,73,4,255,3,
+80,2,176,255,255,255,0,255,255,255,0,12,86,8,69,18,100,10,255,18,160,16,255,24,
+151,21,255,24,136,21,255,11,113,8,255,10,102,6,255,6,87,3,182,10,91,5,250,8,80,
+8,255,8,84,8,255,3,91,3,255,8,86,4,255,2,80,1,185,255,255,255,0,255,255,255,0,
+255,255,255,0,0,77,0,8,0,77,0,23,5,77,3,24,5,78,2,21,3,79,1,18,0,78,0,13,255,
+255,255,0,4,84,2,196,8,70,4,255,0,89,0,255,0,110,0,255,7,120,4,255,9,88,4,247,0,
+77,0,39,255,255,255,0,255,255,255,0,0,77,0,34,2,78,1,185,6,123,4,44,2,126,0,25,
+8,108,4,13,13,92,7,5,255,255,255,0,0,78,0,122,12,76,7,254,0,107,0,255,0,130,0,
+255,5,143,2,255,26,134,7,254,10,92,6,244,1,78,0,169,1,79,1,170,7,83,4,244,22,
+112,12,189,18,151,10,108,11,146,5,76,3,141,1,50,11,100,6,26,0,96,0,0,0,77,0,41,
+9,85,5,247,9,118,5,255,3,142,1,255,13,147,7,255,24,154,13,255,43,158,23,255,
+38,139,20,254,41,139,21,254,50,163,25,250,40,164,21,220,32,159,17,175,22,153,
+11,134,17,140,9,103,8,101,4,32,255,255,255,0,255,255,255,0,0,77,0,116,19,101,
+10,250,11,146,6,255,22,153,11,255,35,161,18,255,47,168,24,255,49,177,26,255,44,
+185,23,255,44,184,23,255,51,174,27,255,44,166,23,217,37,159,21,174,10,94,6,220,
+0,77,0,64,255,255,255,0,255,255,255,0,0,77,0,1,0,77,0,184,27,112,14,248,38,
+155,20,255,43,166,23,255,48,179,25,255,35,199,18,255,27,211,14,255,28,209,15,
+255,38,195,20,255,58,170,30,252,28,115,15,238,0,78,0,178,0,77,0,1,255,255,255,0,
+255,255,255,0,255,255,255,0,0,77,0,1,0,77,0,109,13,95,8,244,22,129,12,253,49,
+169,26,255,41,207,22,255,30,226,16,255,33,198,18,255,13,143,7,254,10,89,5,244,0,
+77,0,122,0,77,0,6,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0,255,255,255,0,0,77,0,31,0,77,0,127,0,77,0,186,3,79,1,237,2,78,1,238,0,
+77,0,192,0,77,0,133,0,77,0,29,255,255,255,0,255,255,255,0,255,255,255,0,255,
+255,255,0};
+MGL_EXPORT Fl_RGB_Image img_reload(idata_reload, 16, 16, 4, 0);
+
+static const unsigned char idata_zoom12[] =
+{0,0,0,0,230,230,229,0,0,0,0,0,238,238,236,104,214,215,215,199,168,171,176,
+241,162,165,170,242,191,193,193,202,202,202,199,115,0,0,0,0,177,178,176,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,223,224,223,0,232,233,234,9,218,219,219,220,
+152,161,173,243,185,193,205,238,239,245,254,240,235,242,252,236,180,192,210,230,
+144,155,172,237,164,166,166,230,165,166,165,20,158,159,157,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,215,214,215,218,150,164,184,229,235,244,254,231,229,238,
+248,223,228,238,249,218,226,237,249,214,221,233,248,213,220,232,249,216,161,177,
+202,221,157,160,160,234,0,0,0,0,131,133,130,0,0,0,0,0,0,0,0,0,0,0,0,0,217,216,
+214,104,156,169,187,237,220,232,249,220,234,246,255,202,223,236,250,197,226,240,
+250,187,226,241,251,182,237,253,255,174,226,244,255,180,207,224,247,203,139,157,
+183,222,210,209,204,131,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,195,196,196,198,156,177,
+211,210,223,241,255,190,43,64,93,255,243,255,255,156,246,255,255,141,253,255,
+255,133,51,70,100,255,58,79,111,255,255,255,255,184,138,173,219,182,142,146,147,
+231,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,161,169,177,239,145,180,228,181,135,159,183,
+195,108,135,170,246,255,255,255,110,70,90,116,229,249,255,255,86,255,255,255,
+165,255,255,255,145,58,79,109,255,152,198,251,142,102,112,123,251,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,154,162,171,240,92,146,215,153,237,255,255,187,96,124,159,
+240,210,255,255,41,255,255,255,162,171,255,255,23,187,202,211,173,63,84,116,255,
+122,161,179,108,153,198,246,137,99,110,121,248,78,80,75,3,0,0,0,0,0,0,0,0,0,0,0,
+0,159,162,162,207,94,143,209,164,137,198,248,101,100,127,161,244,220,255,255,
+40,255,255,255,16,255,255,255,15,67,87,114,255,0,0,0,0,240,255,255,52,158,199,
+245,148,96,101,103,235,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,165,164,159,120,126,153,
+189,204,172,212,249,137,94,120,157,247,255,255,255,25,91,109,132,255,255,255,
+255,1,92,115,137,67,67,89,120,255,63,85,114,255,152,181,216,176,85,85,78,145,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,199,201,201,235,147,179,222,182,239,255,
+255,184,163,239,248,45,255,255,255,155,148,227,237,8,255,255,255,4,255,255,255,
+167,249,255,255,197,96,102,104,236,75,78,77,4,85,87,83,0,0,0,0,0,0,0,0,0,0,0,0,
+0,165,166,164,0,121,125,121,21,129,133,133,235,100,134,179,177,146,202,254,
+114,187,239,255,75,218,255,255,75,213,248,255,98,158,185,211,160,104,108,110,
+253,146,148,144,169,90,92,89,41,111,112,110,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+121,122,119,0,0,0,0,0,98,97,90,136,90,96,96,231,95,107,119,240,100,112,123,236,
+99,104,107,237,87,86,80,150,73,74,73,33,229,228,228,255,148,149,146,245,38,41,
+35,10,98,100,96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,83,
+84,80,4,80,82,78,6,0,0,0,0,0,0,0,0,0,0,0,0,143,143,143,140,231,232,231,255,136,
+137,134,223,0,0,0,0,91,93,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,91,91,91,0,0,0,0,0,158,158,158,183,223,224,
+223,255,126,127,124,192,0,0,0,0,85,85,81,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,101,101,101,0,0,0,0,0,174,175,174,
+215,209,211,209,255,120,121,118,139,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,111,112,111,0,0,0,0,6,197,
+198,197,221,175,176,174,159,0,0,0,0};
+MGL_EXPORT Fl_RGB_Image img_zoom12(idata_zoom12, 16, 16, 4, 0);
+
+static const unsigned char idata_zoom21[] =
+{0,0,0,0,0,0,0,0,0,0,0,0,233,235,234,13,238,238,236,148,192,194,197,221,162,
+166,171,246,168,171,175,233,203,203,200,178,198,198,196,59,0,0,0,0,168,169,167,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,238,237,236,69,189,192,197,
+255,159,168,181,238,210,218,227,239,243,248,255,239,221,229,241,234,161,174,192,
+229,143,151,163,250,177,176,171,159,0,0,0,0,148,149,147,0,0,0,0,0,0,0,0,0,0,0,0,
+0,214,214,213,0,226,227,226,42,181,187,193,255,196,207,224,231,230,239,250,
+227,228,238,250,221,227,237,249,216,226,236,250,213,221,232,247,214,215,228,248,
+218,132,146,164,234,174,174,170,139,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,206,
+207,207,213,167,184,207,223,228,241,255,211,234,247,255,198,224,238,251,193,227,
+240,251,185,225,240,250,181,219,236,250,182,225,243,255,186,196,216,241,208,165,
+174,185,250,117,118,115,22,0,0,0,0,0,0,0,0,0,0,0,0,202,201,200,27,158,167,182,
+249,215,233,255,205,50,70,97,255,56,79,110,255,255,255,255,141,231,249,252,145,
+247,255,255,132,254,255,255,130,44,64,93,255,229,245,255,192,111,139,176,202,
+157,156,151,129,0,0,0,0,0,0,0,0,0,0,0,0,196,196,191,85,124,146,178,219,177,204,
+240,180,249,255,255,206,255,255,255,179,57,78,110,255,255,255,255,90,69,89,116,
+221,115,146,162,123,107,134,168,239,190,227,254,123,107,150,207,170,110,109,101,
+185,0,0,0,0,0,0,0,0,0,0,0,0,183,183,178,88,121,144,177,215,113,167,231,135,181,
+199,212,194,60,81,112,255,123,155,172,98,184,255,255,30,254,255,255,153,255,255,
+255,149,95,123,158,236,180,238,255,81,123,165,221,165,101,100,92,187,0,0,0,0,0,
+0,0,0,0,0,0,0,169,170,167,38,132,148,168,236,125,178,242,135,66,84,108,255,
+255,255,255,22,255,255,255,27,193,243,249,34,255,255,255,6,255,255,255,14,101,
+127,162,243,204,252,255,84,131,160,198,186,84,84,76,135,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,162,165,164,227,123,165,219,171,127,161,191,142,65,85,116,255,67,87,
+117,255,0,0,0,0,94,112,135,255,0,0,0,0,93,121,157,245,211,245,255,119,109,121,
+135,238,80,81,76,33,85,87,83,0,0,0,0,0,0,0,0,0,169,172,169,0,177,178,174,60,189,
+196,207,249,142,188,242,144,251,255,255,166,255,255,255,153,129,225,238,14,255,
+255,255,141,200,242,247,19,255,255,255,186,145,171,201,184,88,88,81,162,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154,153,148,97,109,121,133,242,107,
+157,215,146,159,215,255,93,206,249,255,77,218,255,255,72,198,235,255,117,132,
+150,169,200,119,120,116,255,126,128,125,117,0,0,0,0,85,86,82,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,100,101,95,36,93,94,88,183,91,99,106,243,100,111,124,
+234,101,110,119,244,98,100,97,215,78,78,73,90,181,182,181,130,222,222,221,255,
+119,120,118,168,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,92,94,90,0,0,0,
+0,0,0,0,0,0,84,86,82,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,187,188,187,232,202,
+203,202,255,112,113,109,123,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,118,118,118,0,55,55,55,17,200,201,
+200,251,183,184,182,255,102,103,100,79,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,192,192,0,96,96,
+96,43,211,211,211,255,166,167,166,255,94,96,91,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+119,120,119,75,214,215,214,249,143,145,142,61};
+MGL_EXPORT Fl_RGB_Image img_zoom21(idata_zoom21, 16, 16, 4, 0);
+
+static const unsigned char idata_pause[] =
+{255,0,255,0,255,0,255,0,133,38,131,129,129,181,127,231,127,231,129,181,131,
+129,133,38,255,0,255,0,255,0,255,0,255,0,255,0,127,1,125,113,121,246,114,255,
+116,255,127,255,127,255,116,255,114,255,121,246,125,113,127,1,255,0,255,0,255,0,
+122,1,121,182,111,255,119,255,186,255,208,255,217,255,219,255,212,255,186,255,
+118,255,111,255,121,182,122,1,255,0,255,0,115,113,107,255,142,255,211,255,232,
+255,239,255,242,255,243,255,241,255,234,255,221,255,141,255,107,255,115,113,255,
+0,113,38,108,246,115,255,213,255,237,255,246,255,251,255,253,255,253,255,252,
+255,250,255,241,255,226,255,116,255,108,246,113,38,106,129,97,255,190,255,236,
+255,246,255,152,255,133,255,255,255,255,255,119,255,97,255,252,255,241,255,208,
+255,97,255,106,128,101,181,102,255,206,255,241,255,252,255,146,255,108,255,255,
+255,255,255,111,255,64,255,255,255,250,255,233,255,104,255,101,181,96,231,115,
+255,208,255,239,255,252,255,119,255,75,255,255,255,255,255,96,255,34,255,255,
+255,252,255,239,255,123,255,96,231,93,231,114,255,213,255,241,255,253,255,77,
+255,0,255,255,255,255,255,77,255,0,255,255,255,253,255,241,255,124,255,93,231,
+91,181,96,255,208,255,239,255,252,255,82,255,27,255,255,255,255,255,82,255,27,
+255,255,255,252,255,239,255,100,255,91,181,91,129,84,255,184,255,233,255,250,
+255,94,255,54,255,255,255,255,255,94,255,54,255,255,255,250,255,219,255,84,255,
+91,128,89,38,85,246,103,255,221,255,241,255,252,255,255,255,255,255,255,255,
+255,255,255,255,252,255,241,255,115,255,85,246,89,38,255,0,86,113,80,255,134,
+255,226,255,241,255,250,255,252,255,253,255,252,255,250,255,241,255,154,255,80,
+255,86,113,255,0,255,0,87,1,86,182,79,255,104,255,208,255,233,255,239,255,241,
+255,239,255,219,255,114,255,79,255,86,182,87,1,255,0,255,0,255,0,86,1,84,113,82,
+246,79,255,93,255,118,255,120,255,95,255,79,255,82,246,84,113,86,1,255,0,255,0,
+255,0,255,0,255,0,255,0,85,38,84,129,82,181,81,231,81,231,82,181,84,129,85,38,
+255,0,255,0,255,0,255,0};
+MGL_EXPORT Fl_RGB_Image img_pause(idata_pause, 16, 16, 2, 0);
diff --git a/widgets/image.h b/widgets/image.h
new file mode 100644
index 0000000..ca161e4
--- /dev/null
+++ b/widgets/image.h
@@ -0,0 +1,71 @@
+/* image.h is part of UDAV
+ * Copyright (C) 2007-2014 Alexey Balakin <mathgl.abalakin at gmail.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License
+ * as published by the Free Software Foundation
+ *
+ * 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
+ */
+//-----------------------------------------------------------------------------
+#ifndef IMAGE_H
+#define IMAGE_H
+//-----------------------------------------------------------------------------
+#include <Fl/Fl_RGB_Image.H>
+
+extern MGL_EXPORT Fl_RGB_Image img_load;
+extern MGL_EXPORT Fl_RGB_Image img_save;
+extern MGL_EXPORT Fl_RGB_Image img_calc;
+extern MGL_EXPORT Fl_RGB_Image img_undo;
+extern MGL_EXPORT Fl_RGB_Image img_redo;
+extern MGL_EXPORT Fl_RGB_Image img_copy;
+extern MGL_EXPORT Fl_RGB_Image img_paste;
+extern MGL_EXPORT Fl_RGB_Image img_find;
+extern MGL_EXPORT Fl_RGB_Image img_prop;
+extern MGL_EXPORT Fl_RGB_Image img_alpha;
+extern MGL_EXPORT Fl_RGB_Image img_light;
+extern MGL_EXPORT Fl_RGB_Image img_grid;
+extern MGL_EXPORT Fl_RGB_Image img_move;
+extern MGL_EXPORT Fl_RGB_Image img_orig;
+extern MGL_EXPORT Fl_RGB_Image img_update;
+extern MGL_EXPORT Fl_RGB_Image img_stop;
+extern MGL_EXPORT Fl_RGB_Image img_insert;
+extern MGL_EXPORT Fl_RGB_Image img_print;
+extern MGL_EXPORT Fl_RGB_Image img_goL;
+extern MGL_EXPORT Fl_RGB_Image img_goU;
+extern MGL_EXPORT Fl_RGB_Image img_zoomIn;
+extern MGL_EXPORT Fl_RGB_Image img_zoomOut;
+extern MGL_EXPORT Fl_RGB_Image img_goD;
+extern MGL_EXPORT Fl_RGB_Image img_goR;
+extern MGL_EXPORT Fl_RGB_Image img_next;
+extern MGL_EXPORT Fl_RGB_Image img_play;
+extern MGL_EXPORT Fl_RGB_Image img_prev;
+extern MGL_EXPORT Fl_RGB_Image img_plot;
+extern MGL_EXPORT Fl_RGB_Image img_system;
+extern MGL_EXPORT Fl_RGB_Image img_info;
+extern MGL_EXPORT Fl_RGB_Image img_help;
+extern MGL_EXPORT Fl_RGB_Image img_delete;
+extern MGL_EXPORT Fl_RGB_Image img_objectU;
+extern MGL_EXPORT Fl_RGB_Image img_objectD;
+extern MGL_EXPORT Fl_RGB_Image img_layer;
+extern MGL_EXPORT Fl_RGB_Image img_new;
+extern MGL_EXPORT Fl_RGB_Image img_clear;
+extern MGL_EXPORT Fl_RGB_Image img_plus;
+extern MGL_EXPORT Fl_RGB_Image img_minus;
+extern MGL_EXPORT Fl_RGB_Image img_udav;
+extern MGL_EXPORT Fl_RGB_Image img_fname;
+extern MGL_EXPORT Fl_RGB_Image img_curve;
+extern MGL_EXPORT Fl_RGB_Image img_svn;
+extern MGL_EXPORT Fl_RGB_Image img_adjust;
+extern MGL_EXPORT Fl_RGB_Image img_reload;
+extern MGL_EXPORT Fl_RGB_Image img_zoom12;
+extern MGL_EXPORT Fl_RGB_Image img_zoom21;
+extern MGL_EXPORT Fl_RGB_Image img_pause;
+#endif
diff --git a/widgets/qt.cpp b/widgets/qt.cpp
new file mode 100644
index 0000000..c4bd394
--- /dev/null
+++ b/widgets/qt.cpp
@@ -0,0 +1,1302 @@
+/***************************************************************************
+ * qt.cpp is part of Math Graphic Library                              *
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+#include <QTimer>
+#include <QApplication>
+#include <QMouseEvent>
+#include <QMessageBox>
+#include <QMenu>
+#include <QClipboard>
+#include <QTextEdit>
+#include <QPainter>
+#include <QCursor>
+#include <QImage>
+#include <QScrollArea>
+#include <QMainWindow>
+#include <QToolBar>
+#include <QMenuBar>
+#include <QSpinBox>
+#include <QPrinter>
+#include <QPrintDialog>
+#include <QFileDialog>
+#include <QInputDialog>
+#include <QThread>
+#include <limits.h>
+
+#include "mgl2/canvas_wnd.h"
+#include "mgl2/qmathgl.h"
+#include "mgl2/qt.h"
+#undef sprintf	// fix libintl bug of defining sprintf
+//-----------------------------------------------------------------------------
+#define MGL_MAX_LINES	(INT_MAX-1000)
+//-----------------------------------------------------------------------------
+/// Base class for windows containing MathGL graphics
+class mglCanvasQT : public mglCanvasWnd
+{
+public:
+using mglCanvasWnd::Window;
+	int sshow;		///< Current state of animation switch (toggle button)
+	QMathGL *QMGL;	///< Control which draw graphics
+	QMainWindow *Wnd;	///< Pointer to window
+
+	mglCanvasQT();
+    virtual ~mglCanvasQT();
+
+	/// Create a window for plotting. Now implemeted only for GLUT.
+	void Window(int argc, char **argv, int (*draw)(mglBase *gr, void *p),const char *title,
+						void *par=NULL, void (*reload)(void *p)=NULL, bool maximize=false);
+	/// Switch on/off transparency (do not overwrite switches in user drawing function)
+	void ToggleAlpha();
+	/// Switch on/off lighting (do not overwrite switches in user drawing function)
+	void ToggleLight();
+	void ToggleRotate();///< Switch on/off rotation by mouse
+	void ToggleZoom();	///< Switch on/off zooming by mouse
+	void ToggleNo();	///< Switch off all zooming and rotation
+	void Update();		///< Update picture by calling user drawing function
+	void Adjust();		///< Adjust size of bitmap to window size
+	void GotoFrame(int d);	///< Show arbitrary frame (use relative step)
+	void Animation();		///< Run slideshow (animation) of frames
+
+protected:
+	QScrollArea *scroll;	///< Scrolling area
+	QMenu *popup;			///< Popup menu
+	QSpinBox *tet, *phi;	///< Spin box for angles
+};
+//-----------------------------------------------------------------------------
+void MGL_EXPORT mgl_ask_qt(const wchar_t *quest, wchar_t *res)
+{	QInputDialog::getText(QApplication::activeWindow(), "MathGL",
+						QString::fromWCharArray(quest)).toWCharArray(res);	}
+//-----------------------------------------------------------------------------
+/*void mglTask::doWork()
+{
+	setlocale(LC_NUMERIC, "C");
+	if(mgl_is_frames(gr))	mgl_new_frame(gr);
+	if(draw_func)	draw_func(gr, draw_par);
+	else if(draw)	{	mglGraph g(gr);	draw->Draw(&g);	}
+	if(mgl_is_frames(gr))	mgl_end_frame(gr);
+	setlocale(LC_NUMERIC, "");
+	gr->Finish();
+	emit plotDone();
+}*/
+//-----------------------------------------------------------------------------
+QMathGL::QMathGL(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f)
+{
+	autoResize = false;	draw_par = 0;	draw_func = 0;
+	dotsRefr = true;
+	gr = new mglCanvas;	appName = "MathGL";
+	popup = 0;	grBuf = 0;	draw = 0;
+	phi = tet = per = 0;
+	x1 = y1 = ax1 = ay1 = 0;	x2 = y2 = ax2 = ay2 = 1;
+	alpha = light = zoom = rotate = grid = viewYZ = custZoom = custDraw = pause = false;
+	resize(600, 400);	mgl_set_flag(gr, true, MGL_CLF_ON_UPD);
+	timer = new QTimer(this);
+	timerRefr = new QTimer(this);	timerRefr->setInterval(100);
+	timerRefr->setSingleShot(true);
+	enableWheel = enableMouse = true;
+	connect(timer, SIGNAL(timeout()), this, SLOT(nextSlide()));
+	connect(timerRefr, SIGNAL(timeout()), this, SLOT(refreshHQ()));
+	sclS = 0.25;	sclZ = 0.5;
+
+/*	thread = new QThread();
+	task = new mglTask();	task->moveToThread(thread);
+	connect(thread, SIGNAL(started()), task, SLOT(doWork()));
+	connect(task, SIGNAL(plotDone()), thread, SLOT(quit()));
+	connect(thread, SIGNAL(finished()), this, SLOT(afterPlot()));*/
+}
+//-----------------------------------------------------------------------------
+QMathGL::~QMathGL()
+{
+	timer->stop();	timerRefr->stop();
+	if(gr && mgl_use_graph(gr,-1)<1)	mgl_delete_graph(gr);
+	if(grBuf)	delete []grBuf;
+	if(draw)	delete draw;
+}
+//-----------------------------------------------------------------------------
+void QMathGL::setDotsPreview(bool d)
+{	dotsRefr = d;	}
+//-----------------------------------------------------------------------------
+void QMathGL::setDraw(int (*func)(mglBase *gr, void *par), void *par)
+{
+	if(draw)	delete draw;
+	draw = 0;	draw_func = func;	draw_par = par;
+	emit usePrimChanged(draw_func || draw);
+}
+//-----------------------------------------------------------------------------
+void QMathGL::setDraw(mglDraw *dr)
+{
+	if(draw)	delete draw;
+	draw = dr;	draw_func = 0;
+	emit usePrimChanged(draw_func || draw);
+}
+//-----------------------------------------------------------------------------
+double QMathGL::getRatio()	{	return double(mgl_get_width(gr))/mgl_get_height(gr);	}
+void mgl_qt_event_func(void *)	{	QApplication::processEvents();	}
+//-----------------------------------------------------------------------------
+void QMathGL::setGraph(HMGL GR)	///< Set grapher object
+{
+	mglCanvas *gg = dynamic_cast<mglCanvas *>(GR);
+	if(!gg)	return;
+	if(mgl_use_graph(gr,-1)<1)	mgl_delete_graph(gr);
+	gr=gg;	mgl_use_graph(gg,1);
+	gr->SetEventFunc(mgl_qt_event_func, NULL);
+}
+//-----------------------------------------------------------------------------
+void QMathGL::paintEvent(QPaintEvent *)
+{
+	QPainter paint;
+	paint.begin(this);
+	paint.drawPixmap(0,0,pic);
+	if(zoom)	paint.drawRect(x0,y0,xe-x0,ye-y0);
+	if(mgl_get_flag(gr,MGL_SHOW_POS) && !mousePos.isEmpty())
+		paint.drawText(0,12,mousePos);
+	if(grid)
+	{
+		long d, h=pic.height(), w=pic.width();
+		paint.setPen(QColor(192,192,192));
+		for(long i=1;i<10;i++)
+		{
+			paint.drawText(0,i*h/10,QString::number(1-i*0.1));
+			paint.drawLine(0,i*h/10,w,i*h/10);
+			paint.drawText(i*w/10,h,QString::number(i*0.1));
+			paint.drawLine(i*w/10,0,i*w/10,h);
+		}
+		paint.setPen(QColor(0,0,0));
+		d = (h>w?w:h)/100;
+		if(mgl_is_frames(gr))
+			for(size_t i=0;i<gr->Act.size();i++)
+			{
+				const mglActivePos &p=gr->Act[i];
+				QRect rf(p.x-d/2,p.y-d/2-1,d,d);
+				paint.drawRect(rf);
+				paint.fillRect(rf,QBrush(QColor(127,255,63)));
+			}
+	}
+	paint.end();
+}
+//-----------------------------------------------------------------------------
+void QMathGL::resizeEvent(QResizeEvent *ev)
+{
+	if(autoResize && ev->size().width()>0 && ev->size().height()>0)
+	{	mgl_set_size(gr, ev->size().width(), ev->size().height());	update();	}
+//	else	resize(graph->GetWidth(), graph->GetHeight());
+}
+//-----------------------------------------------------------------------------
+void QMathGL::setPer(int p)
+{
+	if(per!=p && p>=0 && p<100)
+	{	per = 100*p;	emit perChanged(p);	refresh();	}
+}
+//-----------------------------------------------------------------------------
+void QMathGL::setPhi(int p)
+{	if(phi!=p)	{	phi = p;	emit phiChanged(p);	refresh();	}	}
+//-----------------------------------------------------------------------------
+void QMathGL::setTet(int t)
+{	if(tet!=t)	{	tet = t;	emit tetChanged(t);	refresh();	}	}
+//-----------------------------------------------------------------------------
+void QMathGL::setAlpha(bool a)
+{	if(alpha!=a)	{	alpha = a;	emit alphaChanged(a);	update();	}	}
+//-----------------------------------------------------------------------------
+void QMathGL::setLight(bool l)
+{	if(light!=l)	{	light = l;	emit lightChanged(l);	update();	}	}
+//-----------------------------------------------------------------------------
+void QMathGL::setGrid(bool g)
+{	if(grid!=g)	{	grid = g;	emit gridChanged(g); 	refresh();	}	}
+//-----------------------------------------------------------------------------
+void QMathGL::setViewYZ(bool a)
+{	if(viewYZ!=a)	{	viewYZ = a;	emit viewYZChanged(a);	refresh();	}	}
+//-----------------------------------------------------------------------------
+void QMathGL::setPause(bool p)
+{
+#if MGL_HAVE_PTHR_WIDGET
+	if(pause!=p)
+	{
+		pthread_mutex_t *mutex=0;
+		mglCanvasWnd *g=dynamic_cast<mglCanvasWnd *>(gr);
+		if(g && g->mutex)	mutex = g->mutex;
+		else
+		{
+			mglDraw *d=getClass();
+			if(d)	mutex = &(d->mutex);
+		}
+		if(mutex)
+		{
+			if(p)	pthread_mutex_lock(mutex);
+			else	pthread_mutex_unlock(mutex);
+		}
+		pause=p;
+		emit pauseChanged(p);
+	}
+#endif
+}
+//-----------------------------------------------------------------------------
+void QMathGL::setRotate(bool r)
+{
+	if(rotate!=r)
+	{	zoom=false;	rotate=r;	refresh();	emit rotateChanged(r);	}
+}
+//-----------------------------------------------------------------------------
+void QMathGL::setZoom(bool z)
+{
+	if(zoom!=z)
+	{	zoom=z;	rotate=false;	refresh();
+	emit zoomChanged(z);	emit rotateChanged(false);	}
+}
+//-----------------------------------------------------------------------------
+void QMathGL::setCustZoom(bool z)	{	custZoom = z;	}
+//-----------------------------------------------------------------------------
+void QMathGL::setCustDraw(bool z)	{	custDraw = z;	}
+//-----------------------------------------------------------------------------
+void QMathGL::setZoomScl(double s)	{	if(s>0)	sclZ = s;	}
+//-----------------------------------------------------------------------------
+void QMathGL::setShiftScl(double s)	{	if(s)	sclS = s;	}
+//-----------------------------------------------------------------------------
+void QMathGL::shiftDown()
+{	mreal d=(y2-y1)*sclS;	y1+=d;	y2+=d;	refresh();	}
+//-----------------------------------------------------------------------------
+void QMathGL::shiftUp()
+{	mreal d=(y2-y1)*sclS;	y1-=d;	y2-=d;	refresh();	}
+//-----------------------------------------------------------------------------
+void QMathGL::shiftRight()
+{	mreal d=(x2-x1)*sclS;	x1-=d;	x2-=d;	refresh();	}
+//-----------------------------------------------------------------------------
+void QMathGL::shiftLeft()
+{	mreal d=(x2-x1)*sclS;	x1+=d;	x2+=d;	refresh();	}
+//-----------------------------------------------------------------------------
+void QMathGL::zoomIn()
+{
+	mreal d,c;
+	d = (y2-y1)*sclZ/2;	c = (y2+y1)/2;	y1 = c-d;	y2 = c+d;
+	d = (x2-x1)*sclZ/2;	c = (x2+x1)/2;	x1 = c-d;	x2 = c+d;
+	refresh();
+}
+//-----------------------------------------------------------------------------
+void QMathGL::zoomOut()
+{
+	mreal d,c;
+	d = (y2-y1)/sclZ/2;	c = (y2+y1)/2;	y1 = c-d;	y2 = c+d;
+	d = (x2-x1)/sclZ/2;	c = (x2+x1)/2;	x1 = c-d;	x2 = c+d;
+	refresh();
+}
+//-----------------------------------------------------------------------------
+void QMathGL::restore()
+{
+	setPhi(0);	setTet(0);	setPer(0);
+	x1=y1=0; 	x2=y2=1;		zoom=rotate=false;
+	emit zoomChanged(false);	emit rotateChanged(false);
+	if(ax1!=0 || ay1!=0 || ax2!=1 || ay2!=1)
+	{
+		ax1=ay1=0;		ax2=ay2=1;
+		mgl_zoom_axis(gr,0,0,0,0,1,1,1,1);
+		update();
+	}
+	else refresh();
+}
+//-----------------------------------------------------------------------------
+void QMathGL::stop()	{	gr->AskStop(true);	}
+//-----------------------------------------------------------------------------
+void QMathGL::update()
+{
+	if(draw_func || draw)
+	{
+		mgl_reset_frames(gr);	// remove previous frames
+		if(mgl_get_flag(gr,MGL_CLF_ON_UPD))	mgl_set_def_param(gr);
+		mgl_set_alpha(gr,alpha);	mgl_set_light(gr,light);
+		// use frames for quickly redrawing while adding/changing primitives
+		if(custDraw)	emit customDraw(x1,y1,x2,y2,true);
+
+		if(!isHidden())	QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+/*		task->gr = gr;	task->draw = draw;
+		task->draw_func = draw_func;
+		task->draw_par = draw_par;
+		thread->start();*/
+		const std::string loc = setlocale(LC_NUMERIC, "C");
+		if(mgl_is_frames(gr))	mgl_new_frame(gr);
+		if(draw_func)	draw_func(gr, draw_par);
+		else if(draw)	{	mglGraph g(gr);	draw->Draw(&g);	}
+		if(mgl_is_frames(gr))	mgl_end_frame(gr);
+		setlocale(LC_NUMERIC, loc.c_str());
+		gr->AskStop(false);
+	}
+	else if(mgl_get_num_frame(gr)>0)
+	{
+		mgl_set_alpha(gr,alpha);	mgl_set_light(gr,light);
+//		mgl_zoom(gr,x1,y1,x2,y2);	mgl_view(gr,-phi,-tet,0);
+		mgl_get_frame(gr,0);
+	}
+	afterPlot();
+}
+//-----------------------------------------------------------------------------
+void QMathGL::afterPlot()
+{
+	emit refreshData();
+	emit showWarn(mgl_get_mess(gr));
+	mousePos="";
+	if(!isHidden())	QApplication::restoreOverrideCursor();
+	refresh();
+}
+//-----------------------------------------------------------------------------
+void QMathGL::drawPrim()
+{
+	if(!gr)	return;
+	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);
+	mgl_get_frame(gr, g?g->GetCurFig():mgl_get_num_frame(gr)-1);
+	mglParse pr;
+	long i, n=primitives.count('\n');
+	mglGraph gg(gr);
+	const std::string loc = setlocale(LC_NUMERIC, "C");
+	gg.Push();	gg.SubPlot(1,1,0,"#");
+	mglPoint ox1=gr->Min, ox2=gr->Max;
+	gg.SetRanges(mglPoint(-1,-1,-1),mglPoint(1,1,1));
+	for(i=0;i<n;i++)
+	{
+		mgl_set_obj_id(gr,i+MGL_MAX_LINES);
+		QString tst = primitives.section('\n',i,i);
+		pr.Parse(&gg,primitives.section('\n',i,i).toLocal8Bit().constData(),i+MGL_MAX_LINES);
+	}
+	gg.SetRanges(ox1,ox2);	gg.Pop();	setlocale(LC_NUMERIC, loc.c_str());
+}
+//-----------------------------------------------------------------------------
+void QMathGL::refresh()
+{
+	if(dotsRefr)
+	{
+		timerRefr->start();
+		int q = gr->GetQuality();
+		prevQuality = q!=MGL_DRAW_DOTS?q:prevQuality;
+		gr->SetQuality(MGL_DRAW_DOTS);
+	}
+	if(mgl_is_frames(gr) && mgl_get_num_frame(gr)>0)
+	{
+		drawPrim();
+		if(custZoom)	emit customZoom(x1,y1,x2,y2,tet,phi,per);
+		else
+		{	mgl_zoom(gr,x1,y1,x2,y2);
+			mgl_ask_perspective(gr,per);
+			if(viewYZ)	mgl_view(gr,0,-tet,-phi);
+			else 		mgl_view(gr,-phi,-tet,0);
+		}
+	}
+	mglConvertFromGraph(pic, gr, &grBuf);
+	if(pic.size()!=size())	setSize(pic.width(), pic.height());
+	repaint();
+}
+//-----------------------------------------------------------------------------
+void QMathGL::refreshHQ()
+{
+	gr->SetQuality(prevQuality);
+	if(mgl_is_frames(gr) && mgl_get_num_frame(gr)>0)
+	{
+		drawPrim();
+		if(custZoom)	emit customZoom(x1,y1,x2,y2,tet,phi,per);
+		else
+		{	mgl_zoom(gr,x1,y1,x2,y2);
+			mgl_ask_perspective(gr,per);
+			if(viewYZ)	mgl_view(gr,0,-tet,-phi);
+			else 		mgl_view(gr,-phi,-tet,0);
+		}
+	}
+	mglConvertFromGraph(pic, gr, &grBuf, &img);
+	if(pic.size()!=size())	setSize(pic.width(), pic.height());
+	repaint();
+}
+//-----------------------------------------------------------------------------
+void QMathGL::mousePressEvent(QMouseEvent *ev)
+{
+	if(!zoom && !rotate && ev->button()&Qt::LeftButton)
+	{
+		mglPoint p = gr->CalcXYZ(ev->x(), ev->y());
+		mglCanvasWnd *g=dynamic_cast<mglCanvasWnd *>(gr);
+		if(g)	g->LastMousePos = p;
+		if(g && g->ClickFunc)	g->ClickFunc(draw_par);
+		emit mouseClick(p.x,p.y,p.z);
+		int id = mgl_get_obj_id(gr,ev->x(),ev->y());
+		if(id<MGL_MAX_LINES)	emit objChanged(id-1);
+
+		p = gr->CalcXYZ(ev->x(), ev->y(), true);
+		if(mgl_isnan(p.x))	mousePos = "";
+		else	mousePos.sprintf("x=%g, y=%g, z=%g",p.x,p.y,p.z);
+		emit posChanged(mousePos);
+		repaint();
+	}
+	xe=x0=ev->x();	ye=y0=ev->y();	ev->accept();
+}
+//-----------------------------------------------------------------------------
+void QMathGL::mouseReleaseEvent(QMouseEvent *ev)
+{
+	if(ev->button()&Qt::LeftButton && enableMouse)
+	{
+		if(zoom)
+		{
+			int w1=width(),h1=height();
+			mreal _x1,_x2,_y1,_y2;
+			_x1 = x1+(x2-x1)*(x0-x())/mreal(w1);	_y1 = y2-(y2-y1)*(ye-y())/mreal(h1);
+			_x2 = x1+(x2-x1)*(xe-x())/mreal(w1);	_y2 = y2-(y2-y1)*(y0-y())/mreal(h1);
+			x1=_x1;		x2=_x2;		y1=_y1;		y2=_y2;
+			if(x1>x2)	{	_x1=x1;	x1=x2;	x2=_x1;	}
+			if(y1>y2)	{	_x1=y1;	y1=y2;	y2=_x1;	}
+			x0 = xe;	y0 = ye;
+			if(custDraw)
+			{
+				emit customDraw(x1,y1,x2,y2,false);
+				update();
+			}
+			else	refresh();
+		}
+	}
+	if(ev->button()&Qt::RightButton && popup && !rotate)	// popup menu
+		popup->popup(QCursor::pos());
+	ev->accept();
+}
+//-----------------------------------------------------------------------------
+void QMathGL::mouseMoveEvent(QMouseEvent *ev)
+{
+	if(!enableMouse)	{	ev->ignore();	return;	}
+	xe=ev->x();	ye=ev->y();
+	if(rotate)
+	{
+		if(ev->buttons()&Qt::LeftButton)	// rotate
+		{
+			mreal ff = 240/sqrt(mreal(width()*height()));
+			phi += int((x0-xe)*ff);
+			tet -= int((y0-ye)*ff);
+			if(phi>180)		phi-=360;
+			if(phi<-180)	phi+=360;
+			if(tet>180)		tet-=360;
+			if(tet<-180)	tet+=360;
+			emit tetChanged(int(tet));		emit phiChanged(int(phi));
+			refresh();
+		}
+		if(ev->buttons()&Qt::RightButton)	// zoom and perspective
+		{
+			mreal ff = 2.*(y0-ye)/width(), gg = 0.5*(xe-x0)/height();
+			mreal cx = (x1+x2)/2, cy = (y1+y2)/2;
+			x1 = cx+(x1-cx)*exp(-ff);	x2 = cx+(x2-cx)*exp(-ff);
+			y1 = cy+(y1-cy)*exp(-ff);	y2 = cy+(y2-cy)*exp(-ff);
+			per = per + gg;
+			if(per<0)	per = 0;
+			if(per>=1)	per = 0.9999;
+			if(gg)	emit perChanged(int(per));
+			refresh();
+		}
+		if(ev->buttons()&Qt::MidButton)	// shift
+		{
+			mreal ff = 1./sqrt(mreal(width()*height()));
+			mreal dx = (x0-xe)*ff*(x2-x1), dy = (y0-ye)*ff*(y2-y1);
+			x1 += dx;	x2 += dx;	y1 -= dy;	y2 -= dy;
+		}
+		x0 = xe;	y0 = ye;
+		refresh();
+	}
+	else if(zoom)	refresh();
+	else if(ev->buttons()&Qt::MidButton)	// shift axis
+	{
+		mreal ff = 1./sqrt(mreal(width()*height()));
+		mreal dx = (x0-xe)*ff*(ax2-ax1), dy = (y0-ye)*ff*(ay2-ay1);
+		ax1 += dx;	ax2 += dx;	ay1 -= dy;	ay2 -= dy;
+		mgl_zoom_axis(gr,ax1,ay1,0,0,ax2,ay2,0,0);
+		update();	x0 = xe;	y0 = ye;
+	}
+	else if(ev->buttons()&Qt::LeftButton)	// move primitives
+	{
+		long h=pic.height(), w=pic.width(), d=(h>w?w:h)/100;
+		long pos = mgl_is_active(gr,x0,y0,d);
+		long id = long(mgl_get_obj_id(gr,x0,y0))-MGL_MAX_LINES;
+		if(grid && pos>=0)	// this active point
+		{
+			const mglActivePos &p = gr->Act[pos];
+			id = long(p.id)-MGL_MAX_LINES;
+			if(id>=0)	// this is our primitive
+			{
+				// try "attract" mouse
+				for(size_t i=0;i<=10;i++)
+				{
+					int tt = i*(w/10);	if(abs(xe-tt)<2*d)	xe = tt;
+					tt = i*(h/10);	if(abs(ye-tt)<2*d)	ye = tt;
+				}
+				for(size_t i=0;i<gr->Act.size();i++)
+				{
+					const mglActivePos &q = gr->Act[i];
+					if(abs(xe-q.x)<2*d && abs(ye-q.y)<2*d)	{	xe=q.x;	ye=q.y;	}
+				}
+				// now move point
+				QString tst = primitives.section('\n',id,id), cmd=tst.section(' ',0,0), res;
+				float dx = 2*(xe-x0)/float(w), dy = 2*(y0-ye)/float(h);
+				float xx=tst.section(' ',1,1).toFloat(), yy=tst.section(' ',2,2).toFloat();
+				if(p.n==0)
+					res = cmd+" "+QString::number(xx+dx)+" "+QString::number(yy+dy)+" "+tst.section(' ',3);
+				else if(cmd=="rect")
+				{
+					float x_=tst.section(' ',3,3).toFloat(), y_=tst.section(' ',4,4).toFloat();
+					if(p.n==1)	{	xx+=dx;	y_+=dy;	}
+					if(p.n==2)	{	x_+=dx;	yy+=dy;	}
+					if(p.n==3)	{	x_+=dx;	y_+=dy;	}
+					res = "rect "+QString::number(xx)+" "+QString::number(yy)+" "+
+						QString::number(x_)+" "+QString::number(y_)+" "+tst.section(' ',5);
+				}
+				else if(p.n==1)
+				{
+					xx=tst.section(' ',3,3).toFloat();	yy=tst.section(' ',4,4).toFloat();
+					res = tst.section(' ',0,2)+" "+QString::number(xx+dx)+" "+QString::number(yy+dy)+" "+tst.section(' ',5);
+				}
+				else if(cmd=="rhomb" || cmd=="ellipse")
+				{
+					float x_=tst.section(' ',3,3).toFloat()-xx, y_=tst.section(' ',4,4).toFloat()-yy, dr=0;
+					if(x_*x_+y_*y_>0)
+					{
+						dr = (dx*x_+dy*y_)/(x_*x_+y_*y_);
+						dr = hypot(dx-dr*x_,dy-dr*y_);
+					}
+					else	dr = hypot(dx,dy);
+					res = tst.section(' ',0,4)+" "+QString::number(tst.section(' ',5,5).toFloat()+dr)+" "+tst.section(' ',6);
+				}
+				else if(cmd=="arc")
+				{
+					double x_=tst.section(' ',3,3).toFloat()-xx, y_=tst.section(' ',4,4).toFloat()-yy, a_=tst.section(' ',5,5).toFloat();
+					double c=cos(M_PI*a_/180), s=sin(M_PI*a_/180);
+					double a = atan2(x_,y_) - atan2(x_*c-y_*s+dx,x_*s+y_*c+dy);
+					res = tst.section(' ',0,4)+" "+QString::number(a*180/M_PI)+" "+tst.section(' ',6);
+				}
+				else if(p.n==2)
+				{
+					xx=tst.section(' ',5,5).toFloat();	yy=tst.section(' ',6,6).toFloat();
+					res = tst.section(' ',0,4)+" "+QString::number(xx+dx)+" "+QString::number(yy+dy)+" "+tst.section(' ',7);
+				}
+				else if(p.n==3)
+				{
+					xx=tst.section(' ',7,7).toFloat();	yy=tst.section(' ',8,8).toFloat();
+					if(cmd=="curve")	{	dx*=-1;	dy*=-1;	}
+					res = tst.section(' ',0,6)+" "+QString::number(xx+dx)+" "+QString::number(yy+dy)+" "+tst.section(' ',9);
+				}
+				if(id>0) 	res = primitives.section('\n',0,id-1) + "\n" + res;
+				primitives = res + "\n" + primitives.section('\n',id+1);
+				refresh();	x0 = xe;	y0 = ye;
+			}
+		}
+		else if(id>=0)	// this is primitive
+		{
+			QString tst = primitives.section('\n',id,id), cmd=tst.section(' ',0,0), res;
+			float dx = 2*(xe-x0)/float(w), dy = 2*(y0-ye)/float(h);
+			float x1=tst.section(' ',1,1).toFloat(), y1=tst.section(' ',2,2).toFloat(),x2,y2;
+			if(cmd=="ball")
+				res = cmd+" "+QString::number(x1+dx)+" "+QString::number(y1+dy)+" "+tst.section(' ',3);
+			else if(cmd=="curve")
+			{
+				x2=tst.section(' ',5,5).toFloat();	y2=tst.section(' ',6,6).toFloat();
+				res = cmd+" "+QString::number(x1+dx)+" "+QString::number(y1+dy)+" "+tst.section(' ',3,4)+
+						" "+QString::number(x2+dx)+" "+QString::number(y2+dy)+" "+tst.section(' ',7);
+			}
+			else
+			{
+				x2=tst.section(' ',3,3).toFloat();	y2=tst.section(' ',4,4).toFloat();
+				res = cmd+" "+QString::number(x1+dx)+" "+QString::number(y1+dy)+" "+
+						QString::number(x2+dx)+" "+QString::number(y2+dy)+" "+tst.section(' ',5);
+			}
+			if(id>0) 	res = primitives.section('\n',0,id-1) + "\n" + res;
+			primitives = res + "\n" + primitives.section('\n',id+1);
+			refresh();	x0 = xe;	y0 = ye;
+		}
+	}
+	ev->accept();
+}
+//-----------------------------------------------------------------------------
+void QMathGL::mouseDoubleClickEvent(QMouseEvent *ev)
+{
+	long h=pic.height(), w=pic.width(), d=(h>w?w:h)/100;
+	long pos = mgl_is_active(gr,x0,y0,d);
+	long id = long(mgl_get_obj_id(gr,x0,y0));
+	if(grid && pos>=0)	// this active point -> delete primitive
+	{
+		const mglActivePos &p = gr->Act[pos];
+		id = long(p.id)-MGL_MAX_LINES;
+		QString res;
+		if(id>0) 	res = primitives.section('\n',0,id-1) + "\n";
+		if(id>=0)	primitives = res + primitives.section('\n',id+1);
+		refresh();	x0 = xe;	y0 = ye;
+	}
+	else if(id>=MGL_MAX_LINES)	// option for primitives
+		emit askStyle(id-MGL_MAX_LINES);
+	else	emit doubleClick(id);
+	ev->accept();
+}
+//-----------------------------------------------------------------------------
+void QMathGL::setStyle(int id, QString stl)
+{
+	QString tst = primitives.section('\n',id,id), res;
+	res = tst.section(' ',0,-2) + " " + stl;
+	if(id>0) 	res = primitives.section('\n',0,id-1) + "\n" + res;
+	primitives = res + "\n" + primitives.section('\n',id+1);
+	refresh();	x0 = xe;	y0 = ye;
+}
+//-----------------------------------------------------------------------------
+void QMathGL::wheelEvent(QWheelEvent *ev)
+{
+	if(!enableWheel)	{	ev->ignore();	return;	}
+	if(rotate)	// zoom
+	{
+		mreal d,c,f=exp(0.001*ev->delta())/2;
+		d = (y2-y1)*f;	c = (y2+y1)/2;	y1 = c-d;	y2 = c+d;
+		d = (x2-x1)*f;	c = (x2+x1)/2;	x1 = c-d;	x2 = c+d;
+		refresh();	ev->accept();
+	}
+	else 		// zoom axis
+	{
+		mreal d,c,f=exp(0.001*ev->delta())/2;
+		d = (ay2-ay1)*f;	c = (ay2+ay1)/2;	ay1 = c-d;	ay2 = c+d;
+		d = (ax2-ax1)*f;	c = (ax2+ax1)/2;	ax1 = c-d;	ax2 = c+d;
+		mgl_zoom_axis(gr,ax1,ay1,0,0,ax2,ay2,0,0);
+		update();	ev->accept();
+	}
+}
+//-----------------------------------------------------------------------------
+void QMathGL::imgSize(int w, int h)
+{	if(w>0 && h>0)	{	mgl_set_size(gr,w,h);	update();	}	}
+//-----------------------------------------------------------------------------
+QString setExtension(const QString &fname, const char *ext)
+{
+	QString oname=fname;
+	if(fname.right(4)!="."+QString(ext))	oname = fname+"."+QString(ext);
+	return oname;
+}
+//-----------------------------------------------------------------------------
+void QMathGL::exportGIF(QString fname)
+{
+	if(fname.isEmpty())	fname = mgl_get_plotid(gr);
+	if(fname.isEmpty())	QMessageBox::critical(this, appName, _("No filename."),QMessageBox::Ok,0,0);
+	else
+#if MGL_HAVE_GIF
+		mgl_write_gif(gr,setExtension(fname,"png").toLocal8Bit().constData(), appName.toLocal8Bit().constData());
+#else
+		img.save(setExtension(fname,"gif"));
+#endif
+}
+//-----------------------------------------------------------------------------
+void QMathGL::exportPNG(QString fname)
+{
+	if(fname.isEmpty())	fname = mgl_get_plotid(gr);
+	if(fname.isEmpty())	QMessageBox::critical(this, appName, _("No filename."),QMessageBox::Ok,0,0);
+	else
+#if MGL_HAVE_PNG
+		mgl_write_png(gr,setExtension(fname,"png").toLocal8Bit().constData(), appName.toLocal8Bit().constData());
+#else
+		img.save(setExtension(fname,"png"));
+#endif
+}
+//-----------------------------------------------------------------------------
+void QMathGL::exportPNGs(QString fname)
+{
+	if(fname.isEmpty())	fname = mgl_get_plotid(gr);
+	if(fname.isEmpty())	QMessageBox::critical(this, appName, _("No filename."),QMessageBox::Ok,0,0);
+	else
+#if MGL_HAVE_PNG
+		mgl_write_png_solid(gr,setExtension(fname,"png").toLocal8Bit().constData(), appName.toLocal8Bit().constData());
+#else
+		img.save(setExtension(fname,"png"));
+#endif
+}
+//-----------------------------------------------------------------------------
+void QMathGL::exportJPG(QString fname)
+{
+	if(fname.isEmpty())	fname = mgl_get_plotid(gr);
+	if(fname.isEmpty())	QMessageBox::critical(this, appName, _("No filename."),QMessageBox::Ok,0,0);
+	else
+#if MGL_HAVE_JPEG
+		mgl_write_jpg(gr,setExtension(fname,"jpg").toLocal8Bit().constData(), appName.toLocal8Bit().constData());
+#else
+		img.save(setExtension(fname,"jpg"));
+#endif
+}
+//-----------------------------------------------------------------------------
+void QMathGL::exportBPS(QString fname)
+{
+	if(fname.isEmpty())	fname = mgl_get_plotid(gr);
+	if(fname.isEmpty())	QMessageBox::critical(this, appName, _("No filename."),QMessageBox::Ok,0,0);
+	else
+		mgl_write_bps(gr,setExtension(fname,"eps").toLocal8Bit().constData(), appName.toLocal8Bit().constData());
+}
+//-----------------------------------------------------------------------------
+void QMathGL::exportEPS(QString fname)
+{
+	if(fname.isEmpty())	fname = mgl_get_plotid(gr);
+	if(fname.isEmpty())	QMessageBox::critical(this, appName, _("No filename."),QMessageBox::Ok,0,0);
+	else
+		mgl_write_eps(gr,setExtension(fname,"eps").toLocal8Bit().constData(), appName.toLocal8Bit().constData());
+}
+//-----------------------------------------------------------------------------
+void QMathGL::exportSVG(QString fname)
+{
+	if(fname.isEmpty())	fname = mgl_get_plotid(gr);
+	if(fname.isEmpty())	QMessageBox::critical(this, appName, _("No filename."),QMessageBox::Ok,0,0);
+	else
+		mgl_write_svg(gr,setExtension(fname,"svg").toLocal8Bit().constData(), appName.toLocal8Bit().constData());
+}
+//-----------------------------------------------------------------------------
+void QMathGL::exportXYZ(QString fname)
+{
+	if(fname.isEmpty())	fname = mgl_get_plotid(gr);
+	if(fname.isEmpty())	QMessageBox::critical(this, appName, _("No filename."),QMessageBox::Ok,0,0);
+	else
+		mgl_write_xyz(gr,setExtension(fname,"xyz").toLocal8Bit().constData(), appName.toLocal8Bit().constData());
+}
+//-----------------------------------------------------------------------------
+void QMathGL::exportTEX(QString fname)
+{
+	if(fname.isEmpty())	fname = mgl_get_plotid(gr);
+	if(fname.isEmpty())	QMessageBox::critical(this, appName, _("No filename."),QMessageBox::Ok,0,0);
+	else
+		mgl_write_tex(gr,setExtension(fname,"tex").toLocal8Bit().constData(), appName.toLocal8Bit().constData());
+}
+//-----------------------------------------------------------------------------
+void QMathGL::exportOFF(QString fname)
+{
+	if(fname.isEmpty())	fname = mgl_get_plotid(gr);
+	if(fname.isEmpty())	QMessageBox::critical(this, appName, _("No filename."),QMessageBox::Ok,0,0);
+	else
+		mgl_write_off(gr,setExtension(fname,"off").toLocal8Bit().constData(), appName.toLocal8Bit().constData(),0);
+}
+//-----------------------------------------------------------------------------
+void QMathGL::exportOBJ(QString fname)
+{
+	if(fname.isEmpty())	fname = mgl_get_plotid(gr);
+	if(fname.isEmpty())	QMessageBox::critical(this, appName, _("No filename."),QMessageBox::Ok,0,0);
+	else
+		mgl_write_obj(gr,setExtension(fname,"obj").toLocal8Bit().constData(), appName.toLocal8Bit().constData(),1);
+}
+//-----------------------------------------------------------------------------
+void QMathGL::exportSTL(QString fname)
+{
+	if(fname.isEmpty())	fname = mgl_get_plotid(gr);
+	if(fname.isEmpty())	QMessageBox::critical(this, appName, _("No filename."),QMessageBox::Ok,0,0);
+	else
+		mgl_write_stl(gr,setExtension(fname,"stl").toLocal8Bit().constData(), appName.toLocal8Bit().constData());
+}
+//-----------------------------------------------------------------------------
+/*void QMathGL::exportX3D(QString fname)
+{
+	if(fname.isEmpty())	fname = mgl_get_plotid(gr);
+	if(fname.isEmpty())	QMessageBox::critical(this, appName, _("No filename."),QMessageBox::Ok,0,0);
+	else
+		mgl_write_x3d(gr,setExtension(fname,"x3d").toLocal8Bit().constData(), appName.toLocal8Bit().constData());
+}*/
+//-----------------------------------------------------------------------------
+void QMathGL::exportTGA(QString fname)
+{
+	if(fname.isEmpty())	fname = mgl_get_plotid(gr);
+	if(fname.isEmpty())	QMessageBox::critical(this, appName, _("No filename."),QMessageBox::Ok,0,0);
+	else
+		mgl_write_tga(gr,setExtension(fname,"tga").toLocal8Bit().constData(), appName.toLocal8Bit().constData());
+}
+//-----------------------------------------------------------------------------
+void QMathGL::exportPRC(QString fname)
+{
+	if(fname.isEmpty())	fname = mgl_get_plotid(gr);
+	if(fname.isEmpty())	QMessageBox::critical(this, appName, _("No filename."),QMessageBox::Ok,0,0);
+	else
+		mgl_write_prc(gr,setExtension(fname,"prc").toLocal8Bit().constData(), appName.toLocal8Bit().constData(),1);
+}
+//-----------------------------------------------------------------------------
+void QMathGL::exportMGLD(QString fname)
+{
+	if(fname.isEmpty())	fname = mgl_get_plotid(gr);
+	if(fname.isEmpty())	QMessageBox::critical(this, appName, _("No filename."),QMessageBox::Ok,0,0);
+	else
+		mgl_export_mgld(gr,setExtension(fname,"mgld").toLocal8Bit().constData(), appName.toLocal8Bit().constData());
+}
+//-----------------------------------------------------------------------------
+void mglConvertFromGraph(QPixmap &pic, mglCanvas *gr, uchar **buf, QImage *out)
+{
+	const uchar *bb = mgl_get_rgb(gr);
+	long w=mgl_get_width(gr), h=mgl_get_height(gr);
+	if(*buf)	delete [](*buf);
+	*buf = new uchar[4*w*h];
+	for(long i=0;i<w*h;i++)
+	{
+		(*buf)[4*i]   = bb[3*i+2];
+		(*buf)[4*i+1] = bb[3*i+1];
+		(*buf)[4*i+2] = bb[3*i];
+		(*buf)[4*i+3] = 255;
+	}
+	QImage img(*buf, w, h, QImage::Format_RGB32);
+	if(out)	*out = img;
+	pic = QPixmap::fromImage(img);
+}
+//-----------------------------------------------------------------------------
+void QMathGL::copy()
+{	QClipboard *cb = QApplication::clipboard();
+	cb->setPixmap(pic, QClipboard::Clipboard);		}
+//-----------------------------------------------------------------------------
+void QMathGL::copyClickCoor()
+{	QApplication::clipboard()->setText(mousePos);	}
+//-----------------------------------------------------------------------------
+void QMathGL::setMGLFont(QString path)
+{	if(path.isEmpty())	mgl_restore_font(gr);
+	else 	mgl_load_font(gr,path.toLocal8Bit().constData(),0);	}
+//-----------------------------------------------------------------------------
+void QMathGL::setSize(int w, int h)
+{
+	resize(w, h);
+	if(w!=pic.width() || h!=pic.height())	// update only when image size is changed
+	{	mgl_set_size(gr,w,h);	update();	}
+}
+//-----------------------------------------------------------------------------
+void QMathGL::about()
+{
+	QString s = _("MathGL v. 2.") + QString::number(MGL_VER2) + _("\n(c) Alexey Balakin, 2007\nhttp://mathgl.sourceforge.net/");
+	QMessageBox::about(this, _("MathGL - about"), s);
+}
+//-----------------------------------------------------------------------------
+void QMathGL::aboutQt()	{	QMessageBox::aboutQt(this, _("About Qt"));	}
+//-----------------------------------------------------------------------------
+void QMathGL::print()
+{
+	QPrinter *printer = new QPrinter;
+	printer->setOrientation(getRatio()>1 ? QPrinter::Landscape : QPrinter::Portrait);
+	QPrintDialog printDlg(printer, this);
+	if (printDlg.exec() == QDialog::Accepted)
+	{
+		QRectF r = printer->pageRect(QPrinter::Inch);
+		int d1 = int(pic.width()/r.width()), d2 = int(pic.height()/r.height());
+		int dpi = printer->resolution();
+		if(dpi<d1)	dpi=d1;
+		if(dpi<d2)	dpi=d2;
+		printer->setResolution(dpi);
+
+		QPainter p;
+		if(!p.begin(printer))	return;	// paint on printer
+		p.drawPixmap(0,0,pic);
+	}
+	delete printer;
+}
+//-----------------------------------------------------------------------------
+void QMathGL::nextSlide()
+{
+	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);
+	if(g && g->GetNumFig()>1)	g->NextFrame();
+	emit frameChanged(+1);
+}
+void QMathGL::prevSlide()
+{
+	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);
+	if(g && g->GetNumFig()>1)	g->PrevFrame();
+	emit frameChanged(-1);
+}
+//-----------------------------------------------------------------------------
+void QMathGL::animation(bool st)
+{
+	if(!st)	timer->stop();
+	else	timer->start(int(mgl_wnd_get_delay(gr)*1000));
+}
+//-----------------------------------------------------------------------------
+void QMathGL::adjust()
+{
+	mgl_set_size(gr, parentWidget()->width()-3, parentWidget()->height()-3);
+	setSize(parentWidget()->width()-3, parentWidget()->height()-3);
+	update();	// TODO replace to refresh ?!?
+}
+//-----------------------------------------------------------------------------
+void QMathGL::addMark()
+{	primitives += "ball 0 0 'r*'\n";	refresh();	}
+//-----------------------------------------------------------------------------
+void QMathGL::addLine()
+{	primitives += "line -0.2 0 0.2 0 'r2'\n";	refresh();	}
+//-----------------------------------------------------------------------------
+void QMathGL::addRect()
+{	primitives += "rect -0.2 -0.2 0.2 0.2 'r'\n";	refresh();	}
+//-----------------------------------------------------------------------------
+void QMathGL::addCurve()
+{	primitives += "curve -0.2 0 0 0.5 0.2 0 0 0.5 'r2'\n";	refresh();	}
+//-----------------------------------------------------------------------------
+void QMathGL::addRhomb()
+{	primitives += "rhomb -0.2 0 0.2 0 0.1 'r'\n";	refresh();	}
+//-----------------------------------------------------------------------------
+void QMathGL::addEllipse()
+{	primitives += "ellipse -0.2 0 0.2 0 0.1 'r'\n";	refresh();	}
+//-----------------------------------------------------------------------------
+void QMathGL::addArc()
+{	primitives += "arc 0 0 0.2 0 60 'r2'\n";	refresh();	}
+//-----------------------------------------------------------------------------
+void QMathGL::addPolygon(int n)
+{
+	if(n<3)
+		n = QInputDialog::getText(QApplication::activeWindow(), "MathGL", _("Enter number of vertexes")).toInt();
+	if(n>=3)
+	{	primitives += "polygon 0 0 0 0.2 "+QString::number(n)+" 'r'\n";	refresh();	}
+}
+//{	primitives += "arc -0.2 0 0.2 0 0.1 'r'\n";	refresh();	}
+//-----------------------------------------------------------------------------
+void QMathGL::addText(QString txt)
+{
+	if(txt.isEmpty())
+		txt = QInputDialog::getText(QApplication::activeWindow(), "MathGL", _("Enter text"));
+	if(!txt.isEmpty())
+	{	primitives += "text 0 0 0.1 0 '"+txt+"' ''\n";	refresh();	}
+}
+//-----------------------------------------------------------------------------
+//
+//		class mglCanvasQT
+//
+//-----------------------------------------------------------------------------
+mglCanvasQT::mglCanvasQT() : mglCanvasWnd()
+{	Wnd = 0;	}
+mglCanvasQT::~mglCanvasQT()
+{	if(Wnd)	{	QMGL->gr=0;	delete Wnd;	}	}
+//-----------------------------------------------------------------------------
+void mglCanvasQT::GotoFrame(int d)
+{
+	int f = GetCurFig()+d;
+	if(f>=GetNumFig())	f = 0;
+	if(f<0)	f = GetNumFig()-1;
+	if(GetNumFig()>0 && d)	{	SetCurFig(f);	QMGL->refresh();	}
+}
+//-----------------------------------------------------------------------------
+void mglCanvasQT::Animation()
+{
+	static bool start=true;
+	QMGL->animation(start);
+	start = !start;
+}
+//-----------------------------------------------------------------------------
+void mglCanvasQT::ToggleAlpha()	{	QMGL->setAlpha(!QMGL->getAlpha());	}
+//-----------------------------------------------------------------------------
+void mglCanvasQT::ToggleLight()	{	QMGL->setLight(!QMGL->getLight());	}
+//-----------------------------------------------------------------------------
+void mglCanvasQT::ToggleNo()	{	QMGL->restore();	}
+//-----------------------------------------------------------------------------
+void mglCanvasQT::ToggleZoom()	{	QMGL->setZoom(!QMGL->getZoom());	}
+//-----------------------------------------------------------------------------
+void mglCanvasQT::ToggleRotate(){	QMGL->setRotate(!QMGL->getRotate());}
+//-----------------------------------------------------------------------------
+void mglCanvasQT::Update()		{	SetCurFig(0);	QMGL->update();	Wnd->show();	}
+//-----------------------------------------------------------------------------
+void mglCanvasQT::Adjust()		{	QMGL->adjust();	}
+//-----------------------------------------------------------------------------
+void mglCanvasQT::Window(int argc, char **argv, int (*draw)(mglBase *gr, void *p), const char *title, void *par, void (*reload)(void *p), bool maximize)
+{
+	static char arg=0, *parg=&arg, **argv_=&parg;
+	static int argc_=0;
+	SetDrawFunc(draw, par, reload);
+	if(Wnd)
+	{
+		Wnd->setWindowTitle(title);
+		if(maximize)
+		{	Wnd->showMaximized();	}
+		else	Wnd->show();
+		return;
+	}
+
+	if(!qApp)
+	{
+		QCoreApplication::setAttribute(Qt::AA_X11InitThreads);
+		if(!argv)	{	argc_ = 0;	argv_=&parg;	}
+		else		{	argc_ = argc;	argv_=argv;	}
+		QApplication *a = new QApplication(argc_, argv_);
+		a->connect(a, SIGNAL(lastWindowClosed()), a, SLOT(quit()));
+	}
+
+	Wnd = new QMainWindow;	Wnd->resize(850,680);
+	Wnd->setWindowTitle(title);
+	scroll = new QScrollArea(Wnd);
+
+	QMGL = new QMathGL(Wnd);
+	popup = mglMakeMenu(Wnd, QMGL, tet, phi);
+	QMGL->setPopup(popup);	QMGL->setGraph(this);
+	QMGL->setDraw(draw, par);
+	QMGL->appName = title;
+	qApp->processEvents();
+	scroll->setWidget(QMGL);
+	Wnd->setCentralWidget(scroll);
+	QMGL->refresh();
+	if(!maximize)	Wnd->show();
+	else	Wnd->showMaximized();
+}
+//-----------------------------------------------------------------------------
+#include "xpm/alpha.xpm"
+#include "xpm/arc.xpm"
+#include "xpm/copy.xpm"
+#include "xpm/curve.xpm"
+#include "xpm/down_1.xpm"
+#include "xpm/fileprint.xpm"
+#include "xpm/left_1.xpm"
+#include "xpm/light.xpm"
+#include "xpm/line.xpm"
+#include "xpm/mark_a.xpm"
+#include "xpm/mark_d.xpm"
+#include "xpm/mark_o.xpm"
+#include "xpm/mark_s.xpm"
+#include "xpm/right_1.xpm"
+#include "xpm/next_sl.xpm"
+#include "xpm/norm_1.xpm"
+#include "xpm/ok.xpm"
+#include "xpm/prev_sl.xpm"
+#include "xpm/rotate.xpm"
+#include "xpm/show_sl.xpm"
+#include "xpm/text.xpm"
+#include "xpm/polygon.xpm"
+#include "xpm/zoom_1.xpm"
+#include "xpm/zoom_in.xpm"
+#include "xpm/zoom_out.xpm"
+#include "xpm/up_1.xpm"
+#include "xpm/stop.xpm"
+#include "xpm/pause.xpm"
+//-----------------------------------------------------------------------------
+MGL_EXPORT QMenu *mglMakeMenu(QMainWindow *Wnd, QMathGL *QMGL, QSpinBox *&tet, QSpinBox *&phi)
+{
+	QAction *a;
+	QMenu *o, *oo, *f;
+	QToolBar *bb;
+
+	QMenu *popup = new QMenu(Wnd);
+	// file menu
+	{
+		f = o = Wnd->menuBar()->addMenu(_("File"));
+		oo = new QMenu(_("Export as 2D ..."),Wnd);
+		oo->addAction(_("PNG"), QMGL, SLOT(exportPNG()),Qt::ALT+Qt::Key_P);
+		oo->addAction(_("solid PNG"), QMGL, SLOT(exportPNGs()),Qt::ALT+Qt::Key_F);
+		oo->addAction(_("JPEG"), QMGL, SLOT(exportJPG()),Qt::ALT+Qt::Key_J);
+		oo->addAction(_("bitmap EPS"), QMGL, SLOT(exportBPS()));
+		oo->addAction(_("vector EPS"), QMGL, SLOT(exportEPS()),Qt::ALT+Qt::Key_E);
+		oo->addAction(_("SVG"), QMGL, SLOT(exportSVG()),Qt::ALT+Qt::Key_S);
+		oo->addAction(_("LaTeX"), QMGL, SLOT(exportTEX()),Qt::ALT+Qt::Key_L);
+		o->addMenu(oo);		popup->addMenu(oo);
+		oo = new QMenu(_("Export as 3D ..."),Wnd);
+		oo->addAction(_("MGLD"), QMGL, SLOT(exportMGLD()),Qt::ALT+Qt::Key_M);
+		oo->addAction(_("PRC"), QMGL, SLOT(exportPRC()),Qt::ALT+Qt::Key_D);
+		oo->addAction(_("OBJ"), QMGL, SLOT(exportOBJ()),Qt::ALT+Qt::Key_O);
+		oo->addAction(_("STL"), QMGL, SLOT(exportSTL()));
+		oo->addAction(_("XYZ"), QMGL, SLOT(exportXYZ()));
+//		oo->addAction(_("X3D"), QMGL, SLOT(exportX3D()),Qt::ALT+Qt::Key_X);
+		o->addMenu(oo);		popup->addMenu(oo);
+
+		o->addSeparator();
+		a = new QAction(QPixmap(fileprint), _("Print graphics"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(print()));
+		a->setToolTip(_("Open printer dialog and print graphics (Ctrl+P)"));
+		a->setShortcut(Qt::CTRL+Qt::Key_P);	o->addAction(a);
+		o->addSeparator();
+		o->addAction(_("Close"), Wnd, SLOT(close()), Qt::CTRL+Qt::Key_W);
+	}
+	// graphics menu
+	{
+		bb = new QToolBar(_("Graphics"),Wnd);
+		Wnd->addToolBar(Qt::TopToolBarArea, bb);
+		o = Wnd->menuBar()->addMenu(_("Graphics"));
+		a = new QAction(QPixmap(alpha_xpm), _("Alpha"), Wnd);
+		a->setShortcut(Qt::ALT+Qt::Key_T);	a->setCheckable(true);
+		Wnd->connect(a, SIGNAL(toggled(bool)), QMGL, SLOT(setAlpha(bool)));
+		Wnd->connect(QMGL, SIGNAL(alphaChanged(bool)), a, SLOT(setChecked(bool)));
+		a->setToolTip(_("Switch on/off transparency for the graphics (Alt+T)."));
+		o->addAction(a);		bb->addAction(a);
+		a = new QAction(QPixmap(light_xpm), _("Light"), Wnd);
+		a->setShortcut(Qt::ALT+Qt::Key_L);	a->setCheckable(true);
+		Wnd->connect(a, SIGNAL(toggled(bool)), QMGL, SLOT(setLight(bool)));
+		Wnd->connect(QMGL, SIGNAL(lightChanged(bool)), a, SLOT(setChecked(bool)));
+		a->setToolTip(_("Switch on/off lightning for the graphics (Alt+L)."));
+		o->addAction(a);		bb->addAction(a);
+		a = new QAction(QPixmap(rotate_xpm), _("Rotate by mouse"), Wnd);
+		a->setCheckable(true);
+		Wnd->connect(a, SIGNAL(toggled(bool)), QMGL, SLOT(setRotate(bool)));
+		Wnd->connect(QMGL, SIGNAL(rotateChanged(bool)), a, SLOT(setChecked(bool)));
+		a->setToolTip(_("Switch on/off mouse handling of the graphics\n(rotation, shifting, zooming and perspective)."));
+		bb->addAction(a);
+		a = new QAction(QPixmap(zoom_in_xpm), _("Zoom by mouse"), Wnd);
+		a->setCheckable(true);
+		Wnd->connect(a, SIGNAL(toggled(bool)), QMGL, SLOT(setZoom(bool)));
+		Wnd->connect(QMGL, SIGNAL(zoomChanged(bool)), a, SLOT(setChecked(bool)));
+		a->setToolTip(_("Switch on/off mouse zoom of selected region."));
+		bb->addAction(a);
+		o->addSeparator();
+		a = new QAction(QPixmap(zoom_out_xpm), _("Restore"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(restore()));
+		a->setToolTip(_("Restore default graphics rotation, zoom and perspective (Alt+Space)."));
+		a->setShortcut(Qt::ALT+Qt::Key_Space);
+		o->addAction(a);	bb->addAction(a);	popup->addAction(a);
+		bb->addSeparator();
+		o->addAction(a);	bb->addAction(a);	popup->addAction(a);
+		a = new QAction(QPixmap(ok_xpm), _("Redraw"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(update()));
+		a->setToolTip(_("Execute script and redraw graphics (F5)."));
+		a->setShortcut(Qt::Key_F5);
+		o->addAction(a);	bb->addAction(a);	popup->addAction(a);
+		a = new QAction(QPixmap(stop_xpm), _("Stop"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(stop()));
+		a->setToolTip(_("Ask to stop plot drawing (F7)."));
+		a->setShortcut(Qt::Key_F7);
+		a = new QAction(_("Adjust size"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(adjust()));
+		a->setToolTip(_("Change canvas size to fill whole region (F6)."));
+		a->setShortcut(Qt::Key_F6);		o->addAction(a);
+		a = new QAction(QPixmap(copy_xpm), _("Copy plot"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(copy()));
+		a->setToolTip(_("Copy graphics to clipboard (Ctrl+Shift+G)."));
+		a->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_G);
+		o->addAction(a);		bb->addAction(a);	popup->addAction(a);
+
+		bb->addSeparator();
+		oo = new QMenu(_("Primitives ..."),Wnd);
+		a = new QAction(QPixmap(line_xpm), _("Add line"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(addLine()));
+		Wnd->connect(QMGL, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
+		a->setToolTip(_("Add line which properties can be changed later by mouse."));
+		bb->addAction(a);	oo->addAction(a);
+		a = new QAction(QPixmap(arc_xpm), _("Add arc"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(addArc()));
+		Wnd->connect(QMGL, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
+		a->setToolTip(_("Add arc which properties can be changed later by mouse."));
+		bb->addAction(a);	oo->addAction(a);
+		a = new QAction(QPixmap(curve_xpm), _("Add curve"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(addCurve()));
+		Wnd->connect(QMGL, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
+		a->setToolTip(_("Add curve which properties can be changed later by mouse."));
+		bb->addAction(a);	oo->addAction(a);
+		a = new QAction(QPixmap(mark_s_xpm), _("Add rect"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(addRect()));
+		Wnd->connect(QMGL, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
+		a->setToolTip(_("Add rectangle which properties can be changed later by mouse."));
+		bb->addAction(a);	oo->addAction(a);
+		a = new QAction(QPixmap(mark_d_xpm), _("Add rhombus"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(addRhomb()));
+		Wnd->connect(QMGL, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
+		a->setToolTip(_("Add rhombus which properties can be changed later by mouse."));
+		bb->addAction(a);	oo->addAction(a);
+		a = new QAction(QPixmap(mark_o_xpm), _("Add ellipse"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(addEllipse()));
+		Wnd->connect(QMGL, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
+		a->setToolTip(_("Add ellipse which properties can be changed later by mouse."));
+		bb->addAction(a);	oo->addAction(a);
+		a = new QAction(QPixmap(polygon_xpm), _("Add polygon"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(addPolygon()));
+		Wnd->connect(QMGL, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
+		a->setToolTip(_("Add polygon which properties can be changed later by mouse."));
+		bb->addAction(a);	oo->addAction(a);
+		a = new QAction(QPixmap(mark_a_xpm), _("Add mark"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(addMark()));
+		Wnd->connect(QMGL, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
+		a->setToolTip(_("Add marker which properties can be changed later by mouse."));
+		bb->addAction(a);	oo->addAction(a);
+		a = new QAction(QPixmap(text_xpm), _("Add text"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(addText()));
+		Wnd->connect(QMGL, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
+		a->setToolTip(_("Add text which properties can be changed later by mouse."));
+		bb->addAction(a);	oo->addAction(a);
+		o->addMenu(oo);
+
+		bb->addSeparator();
+		tet = new QSpinBox(Wnd);	tet->setWrapping(true);
+		bb->addWidget(tet);	tet->setRange(-180, 180);	tet->setSingleStep(10);
+		Wnd->connect(tet, SIGNAL(valueChanged(int)), QMGL, SLOT(setTet(int)));
+		Wnd->connect(QMGL, SIGNAL(tetChanged(int)), tet, SLOT(setValue(int)));
+		tet->setToolTip(_("Set value of \\theta angle."));
+		bb->addSeparator();
+		phi = new QSpinBox(Wnd);	phi->setWrapping(true);
+		bb->addWidget(phi);	phi->setRange(-180, 180);	phi->setSingleStep(10);
+		Wnd->connect(phi, SIGNAL(valueChanged(int)), QMGL, SLOT(setPhi(int)));
+		Wnd->connect(QMGL, SIGNAL(phiChanged(int)), phi, SLOT(setValue(int)));
+		phi->setToolTip(_("Set value of \\phi angle."));
+//	bb->addSeparator();
+	}
+	// zooming menu
+	{
+		oo = o->addMenu(_("Zoom/move"));
+		bb = new QToolBar(_("Zoom graphics"),Wnd);
+		Wnd->addToolBar(Qt::LeftToolBarArea, bb);
+		a = new QAction(QPixmap(left_1_xpm), _("Move left"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(shiftLeft()));
+		a->setToolTip(_("Move graphics left by 1/3 of its width."));
+		bb->addAction(a);		oo->addAction(a);
+		a = new QAction(QPixmap(up_1_xpm), _("Move up"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(shiftUp()));
+		a->setToolTip(_("Move graphics up by 1/3 of its height."));
+		bb->addAction(a);		oo->addAction(a);
+		a = new QAction(QPixmap(zoom_1_xpm), _("Zoom in"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(zoomIn()));
+		a->setToolTip(_("Zoom in graphics."));
+		bb->addAction(a);		oo->addAction(a);
+		a = new QAction(QPixmap(norm_1_xpm), _("Zoom out"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(zoomOut()));
+		a->setToolTip(_("Zoom out graphics."));
+		bb->addAction(a);		oo->addAction(a);
+		a = new QAction(QPixmap(down_1_xpm), _("Move down"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(shiftDown()));
+		a->setToolTip(_("Move graphics up down 1/3 of its height."));
+		bb->addAction(a);		oo->addAction(a);
+		a = new QAction(QPixmap(right_1_xpm), _("Move right"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(shiftRight()));
+		a->setToolTip(_("Move graphics right by 1/3 of its width."));
+		bb->addAction(a);		oo->addAction(a);
+	}
+	// animation menu
+	{
+		o = Wnd->menuBar()->addMenu(_("Animation"));
+		bb = new QToolBar(_("Animation"),Wnd);
+		Wnd->addToolBar(Qt::LeftToolBarArea, bb);
+		a = new QAction(QPixmap(next_sl_xpm), _("Next slide"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(nextSlide()));
+		a->setToolTip(_("Show next slide (Ctrl+.)."));
+		a->setShortcut(Qt::CTRL+Qt::Key_Period);	o->addAction(a);		bb->addAction(a);
+		a = new QAction(QPixmap(show_sl_xpm), _("Slideshow"), Wnd);
+		a->setCheckable(true);
+		Wnd->connect(a, SIGNAL(toggled(bool)), QMGL, SLOT(animation(bool)));
+		a->setToolTip(_("Run slideshow (CTRl+F5)."));
+		a->setShortcut(Qt::CTRL+Qt::Key_F5);	o->addAction(a);		bb->addAction(a);
+		a = new QAction(QPixmap(prev_sl_xpm), _("Prev slide"), Wnd);
+		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(prevSlide()));
+		a->setToolTip(_("Show previous slide (Ctrl+,)."));
+		a->setShortcut(Qt::CTRL+Qt::Key_Comma);	o->addAction(a);		bb->addAction(a);
+	}
+#if MGL_HAVE_PTHR_WIDGET
+	{
+		bb = new QToolBar(_("Calculations"),Wnd);
+		Wnd->addToolBar(Qt::LeftToolBarArea, bb);
+		a = new QAction(QPixmap(pause_xpm), _("Pause calculation"), Wnd);
+		a->setCheckable(true);
+		Wnd->connect(a, SIGNAL(toggled(bool)), QMGL, SLOT(setPause(bool)));
+		Wnd->connect(QMGL, SIGNAL(pauseChanged(bool)), a, SLOT(setChecked(bool)));
+//		Wnd->connect(a, SIGNAL(triggered()), QMGL, SLOT(setPause()));
+		a->setToolTip(_("Pause on/off external calculations"));
+		f->addSeparator();	f->addAction(a);	bb->addAction(a);
+	}
+#endif
+
+	Wnd->menuBar()->addSeparator();
+	o = Wnd->menuBar()->addMenu(_("Help"));
+	o->addAction(_("About"), QMGL, SLOT(about()));
+	o->addAction(_("About Qt"), QMGL, SLOT(aboutQt()));
+	return popup;
+}
+//-----------------------------------------------------------------------------
+HMGL MGL_EXPORT mgl_create_graph_qt(int (*draw)(HMGL gr, void *p), const char *title, void *par, void (*load)(void *p))
+{
+	mglCanvasQT *g = new mglCanvasQT;
+	g->Window(0,0,draw,title,par,load);
+	return g;
+}
+void* mgl_qt_widget(HMGL gr)
+{
+	mglCanvasQT *g = dynamic_cast<mglCanvasQT *>(gr);
+	return g?g->QMGL:NULL;
+}
+int MGL_EXPORT mgl_qt_run()	{	return (qApp)?qApp->exec():-1;	}
+//-----------------------------------------------------------------------------
+uintptr_t MGL_EXPORT mgl_create_graph_qt_(const char *title, int l)
+{
+	char *s = new char[l+1];	memcpy(s,title,l);	s[l]=0;
+	uintptr_t t = uintptr_t(mgl_create_graph_qt(0,s,0,0));
+	delete []s;	return t;
+}
+int MGL_EXPORT mgl_qt_run_()	{	return mgl_qt_run();	}
+//-----------------------------------------------------------------------------
diff --git a/widgets/qt4/CMakeLists.txt b/widgets/qt4/CMakeLists.txt
new file mode 100644
index 0000000..74f117c
--- /dev/null
+++ b/widgets/qt4/CMakeLists.txt
@@ -0,0 +1,22 @@
+include(GenerateExportHeader)
+
+if(enable-qt4)
+	include(../../cmake-qt4.txt)
+	set(MGL_QT4_FILES ../qt.cpp ../../include/mgl2/qt.h ../../include/mgl2/qmathgl.h)
+	mgl_add_lib(qt4 ${MGL_QT4_FILES})
+	target_link_libraries(mgl-qt4 mgl ${MGL_QT4_LIBS})
+	target_link_libraries(mgl-qt4-static mgl-static ${MGL_QT4_LIBS})
+	if(enable-qt4asqt)
+		mgl_add_lib(qt ${MGL_QT4_FILES})
+		target_link_libraries(mgl-qt mgl ${MGL_QT4_LIBS})
+		target_link_libraries(mgl-qt-static mgl-static ${MGL_QT4_LIBS})
+	endif(enable-qt4asqt)
+
+	if(MGL_HAVE_FLTK AND NOT enable-qt5)
+		mgl_add_lib(wnd ${MGL_QT4_FILES} ../fltk.cpp ../../include/mgl2/fltk.h ../image.cpp ../image.h)
+		target_include_directories(mgl-wnd SYSTEM PUBLIC ${FLTK_INCLUDE_DIR})
+		target_include_directories(mgl-wnd-static SYSTEM PUBLIC ${FLTK_INCLUDE_DIR})
+		target_link_libraries(mgl-wnd mgl ${FLTK_LIBRARIES} ${MGL_QT4_LIBS})
+		target_link_libraries(mgl-wnd-static mgl-static ${FLTK_LIBRARIES} ${MGL_QT4_LIBS})
+	endif(MGL_HAVE_FLTK AND  NOT enable-qt5)
+endif(enable-qt4)
diff --git a/widgets/qt5/CMakeLists.txt b/widgets/qt5/CMakeLists.txt
new file mode 100644
index 0000000..70e1787
--- /dev/null
+++ b/widgets/qt5/CMakeLists.txt
@@ -0,0 +1,21 @@
+include(GenerateExportHeader)
+
+if(enable-qt5)
+	include(../../cmake-qt5.txt)
+	set(MGL_QT5_FILES ../qt.cpp ../../include/mgl2/qt.h ../../include/mgl2/qmathgl.h)
+	mgl_add_lib(qt5 ${MGL_QT5_FILES})
+	target_link_libraries(mgl-qt5 mgl ${MGL_QT5_LIBS})
+	target_link_libraries(mgl-qt5-static mgl-static ${MGL_QT5_LIBS})
+	if(enable-qt5asqt)
+		mgl_add_lib(qt ${MGL_QT5_FILES})
+		target_link_libraries(mgl-qt mgl ${MGL_QT5_LIBS})
+		target_link_libraries(mgl-qt-static mgl-static ${MGL_QT5_LIBS})
+	endif(enable-qt5asqt)
+	if(MGL_HAVE_FLTK)
+		mgl_add_lib(wnd ${MGL_QT5_FILES} ../fltk.cpp ../../include/mgl2/fltk.h ../image.cpp ../image.h)
+		target_include_directories(mgl-wnd SYSTEM PUBLIC ${FLTK_INCLUDE_DIR})
+		target_include_directories(mgl-wnd-static SYSTEM PUBLIC ${FLTK_INCLUDE_DIR})
+		target_link_libraries(mgl-wnd mgl ${FLTK_LIBRARIES} ${MGL_QT5_LIBS})
+		target_link_libraries(mgl-wnd-static mgl-static ${FLTK_LIBRARIES} ${MGL_QT5_LIBS})
+	endif(MGL_HAVE_FLTK)
+endif(enable-qt5)
diff --git a/widgets/wx.cpp b/widgets/wx.cpp
new file mode 100644
index 0000000..94a155e
--- /dev/null
+++ b/widgets/wx.cpp
@@ -0,0 +1,421 @@
+/***************************************************************************
+ * wx.cpp is part of Math Graphic Library                              *
+ * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin at gmail.ru>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library 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.             *
+ ***************************************************************************/
+//-----------------------------------------------------------------------------
+#include <wx/dcclient.h>
+#include <wx/msgdlg.h>
+#include <wx/clipbrd.h>
+#include <wx/dataobj.h>
+#include <wx/menu.h>
+#include <wx/scrolwin.h>
+
+#undef _
+
+#include "mgl2/canvas_wnd.h"
+#include "mgl2/wx.h"
+//-----------------------------------------------------------------------------
+class MGL_EXPORT mglCanvasWX : public mglCanvasWnd
+{
+friend class wxMathGL;
+public:
+	int sshow;			///< Current state of animation switch (toggle button)
+	wxMathGL *WMGL;		///< Control which draw graphics
+	wxWindow *Wnd;		///< Pointer to window
+
+	mglCanvasWX();
+	virtual ~mglCanvasWX();
+
+	/// Create a window for plotting. Now implemeted only for GLUT.
+	void Window(int argc, char **argv, int (*draw)(mglBase *gr, void *p), const char *title,
+				void *par=NULL, void (*reload)(void *p)=NULL, bool maximize=false);
+	/// Switch on/off transparency (do not overwrite switches in user drawing function)
+	void ToggleAlpha();
+	/// Switch on/off lighting (do not overwrite switches in user drawing function)
+	void ToggleLight();
+	void ToggleRotate();	///< Switch on/off rotation by mouse
+	void ToggleZoom();		///< Switch on/off zooming by mouse
+	void ToggleNo();		///< Switch off all zooming and rotation
+	void Update();			///< Update picture by calling user drawing function
+	void Adjust();			///< Adjust size of bitmap to window size
+	void GotoFrame(int d);	///< Show arbitrary frame (use relative step)
+	void Animation();	///< Run animation (I'm too lasy to change it)
+
+protected:
+	wxScrolledWindow *scroll;	///< Scrolling area
+	wxMenu *popup;			///< Popup menu
+//	wxSpinCtrl *tet, *phi;	///< Spin box for angles // TODO
+
+	void MakeMenu();		///< Create menu, toolbar and popup menu
+};
+//-----------------------------------------------------------------------------
+const wxString ScriptName(L"default");
+enum
+{
+	TIMER_ID=1000,
+	LAST_ID
+};
+BEGIN_EVENT_TABLE(wxMathGL, wxWindow)
+	EVT_TIMER	(TIMER_ID,	wxMathGL::OnNextSlide)
+	EVT_PAINT	(wxMathGL::OnPaint)
+	EVT_SIZE	(wxMathGL::OnSize)
+	EVT_LEFT_DOWN	(wxMathGL::OnMouseLeftDown)
+	EVT_RIGHT_DOWN	(wxMathGL::OnMouseDown)
+	EVT_MIDDLE_DOWN	(wxMathGL::OnMouseDown)
+	EVT_LEFT_UP		(wxMathGL::OnMouseLeftUp)
+	EVT_RIGHT_UP	(wxMathGL::OnMouseRightUp)
+	EVT_MOTION		(wxMathGL::OnMouseMove)
+END_EVENT_TABLE()
+//-----------------------------------------------------------------------------
+//
+//		class wxMathGL
+//
+//-----------------------------------------------------------------------------
+wxMathGL::wxMathGL(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name) : wxWindow(parent,id,pos,size,style,name)
+{
+	AutoResize = false;	draw_par = 0;	draw_func = 0;
+	gr = new mglCanvas;	popup = 0;
+	phi = tet = per = 0;
+	x1 = y1 = 0;	x2 = y2 = 1;
+	alpha = light = zoom = rotate = false;
+//	SetSize(600, 400);
+	timer = new wxTimer(this,TIMER_ID);
+}
+//-----------------------------------------------------------------------------
+wxMathGL::~wxMathGL()	{	if(mgl_use_graph(gr,-1)<1)	mgl_delete_graph(gr);	}
+//-----------------------------------------------------------------------------
+double wxMathGL::GetRatio()	{	return double(mgl_get_width(gr))/mgl_get_height(gr);	}
+//-----------------------------------------------------------------------------
+void wxMathGL::SetGraph(HMGL GR)
+{
+	mglCanvas *gg = dynamic_cast<mglCanvas *>(GR);
+	if(!gg)	return;
+	if(mgl_use_graph(gr,-1)<1)	mgl_delete_graph(gr);
+	gr=gg;	mgl_use_graph(gg,1);
+}
+//-----------------------------------------------------------------------------
+void wxMathGL::OnPaint(wxPaintEvent& )
+{
+	wxPaintDC dc(this);
+	dc.DrawBitmap(pic,0,0);
+//	if(zoom)	dc.DrawRectangle(x0,y0,xe-x0,ye-y0);
+	if(mgl_get_flag(gr,MGL_SHOW_POS) && !MousePos.IsEmpty())
+		dc.DrawText(MousePos,0,12);
+	// TODO: add grid drawing here (from Qt)
+	// TODO: add active points drawing here (from Qt)
+}
+//-----------------------------------------------------------------------------
+void wxMathGL::OnSize(wxSizeEvent& event)
+{
+	wxSize ev = event.GetSize();
+	if(mgl_get_width(gr)==ev.GetWidth() && mgl_get_height(gr)==ev.GetHeight())
+		return;
+	if(AutoResize && ev.GetWidth()>0 && ev.GetHeight()>0)
+	{	mgl_set_size(gr, ev.GetWidth(), ev.GetHeight());	Update();	}
+	else 	SetSize(mgl_get_width(gr), mgl_get_height(gr));
+}
+//-----------------------------------------------------------------------------
+void wxMathGL::OnNextSlide(wxTimerEvent& )	{	NextSlide();	}
+//-----------------------------------------------------------------------------
+void wxMathGL::SetPer(int p)
+{	if(100*per!=p && p>=0 && p<100)	{	per = 0.01*p;	Repaint();	}	}
+//-----------------------------------------------------------------------------
+void wxMathGL::SetPhi(int p)
+{	if(phi!=p)	{	phi = p; 	Repaint();	}	}
+//-----------------------------------------------------------------------------
+void wxMathGL::SetTet(int t)
+{	if(tet!=t)	{	tet = t; 	Repaint();	}	}
+//-----------------------------------------------------------------------------
+void wxMathGL::SetAlpha(bool a)
+{	if(alpha!=a)	{	alpha = a;	Update();	}	}
+//-----------------------------------------------------------------------------
+void wxMathGL::SetLight(bool l)
+{	if(light!=l)	{	light = l;	Update();	}	}
+//-----------------------------------------------------------------------------
+void wxMathGL::SetZoom(bool z)
+{	if(zoom!=z)	{	zoom=z;	rotate=false;	Repaint();	}	}
+//-----------------------------------------------------------------------------
+void wxMathGL::SetRotate(bool r)
+{	if(rotate!=r)	{	zoom=false;	rotate=r;	Repaint();	}	}
+//-----------------------------------------------------------------------------
+void wxMathGL::ShiftDown()
+{	mreal d=(y2-y1)/3;	y1+=d;	y2+=d;	Repaint();	}
+//-----------------------------------------------------------------------------
+void wxMathGL::ShiftUp()
+{	mreal d=(y2-y1)/3;	y1-=d;	y2-=d;	Repaint();	}
+//-----------------------------------------------------------------------------
+void wxMathGL::ShiftRight()
+{	mreal d=(x2-x1)/3;	x1-=d;	x2-=d;	Repaint();	}
+//-----------------------------------------------------------------------------
+void wxMathGL::ShiftLeft()
+{	mreal d=(x2-x1)/3;	x1+=d;	x2+=d;	Repaint();	}
+//-----------------------------------------------------------------------------
+void wxMathGL::Restore()
+{
+	SetPhi(0);	SetTet(0);	SetPer(0);
+	x1=y1=0;	x2=y2=1;	zoom=rotate=false;
+	Repaint();
+}
+//-----------------------------------------------------------------------------
+void wxMathGL::ZoomIn()
+{
+	mreal d;
+	d = (y2-y1)/4;	y1 += d;	y2 -= d;
+	d = (x2-x1)/4;	x1 += d;	x2 -= d;
+	Repaint();
+}
+//-----------------------------------------------------------------------------
+void wxMathGL::ZoomOut()
+{
+	mreal d;
+	d = (y2-y1)/2;	y1 -= d;	y2 += d;
+	d = (x2-x1)/2;	x1 -= d;	x2 += d;
+	Repaint();
+}
+//-----------------------------------------------------------------------------
+void wxMathGL::Update()
+{
+	if(draw_func || draw_cl)
+	{
+		if(mgl_get_flag(gr,MGL_CLF_ON_UPD))	mgl_set_def_param(gr);
+		mgl_set_def_param(gr);		mgl_reset_frames(gr);
+		mgl_set_alpha(gr,alpha);	mgl_set_light(gr,light);
+		if(draw_func)	draw_func(gr, draw_par);	// drawing itself
+		else 	if(draw_cl)	{	mglGraph g(gr);	draw_cl->Draw(&g);	}
+		const char *buf = mgl_get_mess(gr);
+		if(*buf)
+		{
+			wxMessageDialog dlg(this, wxString(buf,wxConvLocal), appName, wxOK);
+			dlg.ShowModal();
+		}
+	}
+	else if(mgl_get_num_frame(gr)>0)
+	{
+		mgl_set_alpha(gr,alpha);	mgl_set_light(gr,light);
+//		mgl_zoom(gr,x1,y1,x2,y2);	mgl_view(gr,-phi,-tet,0);
+		mgl_get_frame(gr,0);
+	}
+	MousePos.Empty();	Repaint();
+}
+//-----------------------------------------------------------------------------
+wxBitmap MGL_EXPORT ConvertFromGraph(HMGL gr)
+{
+	const unsigned char *bb = mgl_get_rgb(gr);
+	int w=mgl_get_width(gr), h=mgl_get_height(gr);
+	unsigned char *tmp = (unsigned char *)malloc(3*w*h);
+	memcpy(tmp,bb,3*w*h);
+	wxImage img(w, h);	img.SetData(tmp);
+	return wxBitmap(img);
+}
+//-----------------------------------------------------------------------------
+void wxMathGL::Repaint()
+{
+	mgl_zoom(gr,x1,y1,x2,y2);	mgl_view(gr,-phi,-tet,0);	mgl_ask_perspective(gr, per);
+	pic = ConvertFromGraph(gr);
+	wxSize sz=GetSize();
+	if(pic.GetWidth()!=sz.GetWidth() || pic.GetHeight()!=sz.GetHeight())
+		SetSize(pic.GetWidth(), pic.GetHeight());
+	Refresh();
+}
+//-----------------------------------------------------------------------------
+void wxMathGL::OnMouseLeftDown(wxMouseEvent &ev)
+{
+	long x=ev.GetX(), y=ev.GetY();
+	if(!zoom && !rotate)
+	{
+		mglPoint p = gr->CalcXYZ(x, y);
+		MousePos.Printf(wxT("x=%g, y=%g, z=%g"),p.x,p.y,p.z);
+		Refresh();
+//		emit mouseClick(p.x,p.y,p.z);
+	}
+	xe=x0=x;	ye=y0=y;	ev.Skip();
+}
+//-----------------------------------------------------------------------------
+void wxMathGL::OnMouseDown(wxMouseEvent &ev)
+{	xe=x0=ev.GetX();	ye=y0=ev.GetY();	ev.Skip();	}
+//-----------------------------------------------------------------------------
+void wxMathGL::OnMouseLeftUp(wxMouseEvent &)
+{
+	if(zoom)
+	{
+		int w1=GetSize().GetWidth(),h1=GetSize().GetHeight();
+		mreal _x1,_x2,_y1,_y2;
+		_x1 = x1+(x2-x1)*(x0-GetPosition().x)/mreal(w1);
+		_y1 = y2-(y2-y1)*(ye-GetPosition().y)/mreal(h1);
+		_x2 = x1+(x2-x1)*(xe-GetPosition().x)/mreal(w1);
+		_y2 = y2-(y2-y1)*(y0-GetPosition().y)/mreal(h1);
+		x1=_x1;		x2=_x2;		y1=_y1;		y2=_y2;
+		if(x1>x2)	{	_x1=x1;	x1=x2;	x2=_x1;	}
+		if(y1>y2)	{	_x1=y1;	y1=y2;	y2=_x1;	}
+		x0 = xe;	y0 = ye;
+		Update();
+	}
+}
+//-----------------------------------------------------------------------------
+void wxMathGL::OnMouseRightUp(wxMouseEvent &ev)
+{	if(popup && !rotate)	PopupMenu(popup, ev.GetPosition());	}
+//-----------------------------------------------------------------------------
+void wxMathGL::OnMouseMove(wxMouseEvent &ev)
+{
+	long w=GetSize().GetWidth(), h=GetSize().GetHeight();
+	xe=ev.GetX();	ye=ev.GetY();
+	if(rotate)
+	{
+		if(ev.ButtonDown(wxMOUSE_BTN_LEFT))	// rotate
+		{
+			mreal ff = 240/sqrt(mreal(w*h));
+			phi += int((x0-xe)*ff);
+			tet += int((y0-ye)*ff);
+			if(phi>180)		phi-=360;
+			if(phi<-180)	phi+=360;
+			if(tet>180)		tet-=360;
+			if(tet<-180)	tet+=360;
+//			Update();
+		}
+		if(ev.ButtonDown(wxMOUSE_BTN_RIGHT))	// zoom and perspective
+		{
+			mreal ff = 2.*(y0-ye)/w, gg = 0.5*(xe-x0)/h;
+			mreal cx = (x1+x2)/2, cy = (y1+y2)/2;
+			x1 = cx+(x1-cx)*exp(-ff);	x2 = cx+(x2-cx)*exp(-ff);
+			y1 = cy+(y1-cy)*exp(-ff);	y2 = cy+(y2-cy)*exp(-ff);
+			per = per + gg;
+			if(per<0)	per = 0;
+			if(per>=1)	per = 0.9999;
+//			Update();
+		}
+		if(ev.ButtonDown(wxMOUSE_BTN_MIDDLE))	// shift
+		{
+			mreal ff = 1./sqrt(mreal(w*h));
+			mreal dx = (x0-xe)*ff*(x2-x1), dy = (y0-ye)*ff*(y2-y1);
+			x1 += dx;	x2 += dx;	y1 -= dy;	y2 -= dy;
+		}
+		x0 = xe;	y0 = ye;
+		Update();
+	}
+//	if(zoom)	Update();
+	if(zoom)	Refresh(0);
+}
+//-----------------------------------------------------------------------------
+wxString mglSetExtension(wxString &fname, const char *ext)
+{
+	wxString oname;
+	if(fname.Right(4)!=wxChar('.')+wxString(ext,*wxConvCurrent))
+		oname = fname+wxChar('.')+wxString(ext,*wxConvCurrent);
+	return oname;
+}
+//-----------------------------------------------------------------------------
+// NOTE: this is replacement for wxString::char_str() which is for v.2.8 or later
+const char *mglw_str(const wxString &str)
+{
+	static char *buf=0;
+	if(buf)	delete []buf;
+	size_t i, n=str.Len();
+	buf = new char[n+1];	buf[n]=0;
+	for(i=0;i<n;i++)	buf[i] = str.GetChar(i);
+	return buf;
+}
+//-----------------------------------------------------------------------------
+void wxMathGL::ExportPNG(wxString fname)
+{
+	if(fname.IsEmpty())	fname = ScriptName;
+	if(fname.IsEmpty())	wxMessageBox(appName, wxT("No filename."),wxOK|wxICON_ERROR ,this);
+	else	mgl_write_png(gr,mglw_str(mglSetExtension(fname,"png")), mglw_str(appName));
+}
+//-----------------------------------------------------------------------------
+void wxMathGL::ExportPNGs(wxString fname)
+{
+	if(fname.IsEmpty())	fname = ScriptName;
+	if(fname.IsEmpty())	wxMessageBox(appName, wxT("No filename."),wxOK|wxICON_ERROR ,this);
+	else	mgl_write_png_solid(gr,mglw_str(mglSetExtension(fname,"png")), mglw_str(appName));
+}
+//-----------------------------------------------------------------------------
+void wxMathGL::ExportJPG(wxString fname)
+{
+	if(fname.IsEmpty())	fname = ScriptName;
+	if(fname.IsEmpty())	wxMessageBox(appName, wxT("No filename."),wxOK|wxICON_ERROR ,this);
+	else	mgl_write_jpg(gr,mglw_str(mglSetExtension(fname,"jpg")), mglw_str(appName));
+}
+//-----------------------------------------------------------------------------
+void wxMathGL::ExportBPS(wxString fname)
+{
+	if(fname.IsEmpty())	fname = ScriptName;
+	if(fname.IsEmpty())	wxMessageBox(appName, wxT("No filename."),wxOK|wxICON_ERROR ,this);
+	else
+		mgl_write_bps(gr,mglw_str(mglSetExtension(fname,"eps")), mglw_str(appName));
+}
+//-----------------------------------------------------------------------------
+void wxMathGL::ExportEPS(wxString fname)
+{
+	if(fname.IsEmpty())	fname = ScriptName;
+	if(fname.IsEmpty())	wxMessageBox(appName, wxT("No filename."),wxOK|wxICON_ERROR ,this);
+	else
+		mgl_write_eps(gr,mglw_str(mglSetExtension(fname,"eps")), mglw_str(appName));
+}
+//-----------------------------------------------------------------------------
+void wxMathGL::ExportSVG(wxString fname)
+{
+	if(fname.IsEmpty())	fname = ScriptName;
+	if(fname.IsEmpty())	wxMessageBox(appName, wxT("No filename."),wxOK|wxICON_ERROR ,this);
+	else
+		mgl_write_svg(gr,mglw_str(mglSetExtension(fname,"eps")), mglw_str(appName));
+}
+//-----------------------------------------------------------------------------
+void wxMathGL::Copy()
+{
+	if (wxTheClipboard->Open())
+	{
+		wxTheClipboard->SetData( new wxBitmapDataObject(pic) );
+		wxTheClipboard->Close();
+	}
+}
+//-----------------------------------------------------------------------------
+void wxMathGL::SetSize(int w, int h)
+{	mgl_set_size(gr,w,h);	wxWindow::SetSize(w, h);	Update();	}
+//-----------------------------------------------------------------------------
+void wxMathGL::Adjust()
+{
+	wxSize sz=GetSize();
+	mgl_set_size(gr,sz.GetWidth(),sz.GetHeight());
+	Repaint();
+}
+//-----------------------------------------------------------------------------
+void wxMathGL::NextSlide()
+{
+	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);
+	if(g && g->GetNumFig()>1)	g->NextFrame();
+}
+//-----------------------------------------------------------------------------
+void wxMathGL::PrevSlide()
+{
+	mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);
+	if(g && g->GetNumFig()>1)	g->PrevFrame();
+}
+//-----------------------------------------------------------------------------
+void wxMathGL::Animation(bool st)
+{
+	if(st)	timer->Start(int(mgl_wnd_get_delay(gr)*1000));
+	else	timer->Stop();
+}
+//-----------------------------------------------------------------------------
+void wxMathGL::About()
+{
+	wxString s = wxT("MathGL v. 2.") + wxString::Format(wxT("%g"),MGL_VER2) +
+		wxT("\n(c) Alexey Balakin, 2007\nhttp://mathgl.sourceforge.net/");
+	wxMessageBox(s, wxT("MathGL - about"), wxOK|wxICON_INFORMATION, this);
+}
+//-----------------------------------------------------------------------------
diff --git a/win32-install-deps/CMakeLists.txt b/win32-install-deps/CMakeLists.txt
new file mode 100644
index 0000000..2824d13
--- /dev/null
+++ b/win32-install-deps/CMakeLists.txt
@@ -0,0 +1,10 @@
+if(enable-qt5)
+	find_package(Qt5Gui QUIET)
+	if(Qt5Gui_FOUND)
+		get_target_property(mgl_qt_loc Qt5::QWindowsIntegrationPlugin LOCATION)
+	endif(Qt5Gui_FOUND)
+endif(enable-qt5)
+
+install(CODE "SET(mgl_qt_loc \"${mgl_qt_loc}\")")
+install(CODE "SET(CMAKE_INSTALL_PREFIX \"${CMAKE_INSTALL_PREFIX}\")")
+install(SCRIPT install-deps.txt)
diff --git a/win32-install-deps/install-deps.txt b/win32-install-deps/install-deps.txt
new file mode 100644
index 0000000..9bab2f7
--- /dev/null
+++ b/win32-install-deps/install-deps.txt
@@ -0,0 +1,36 @@
+include(GetPrerequisites)
+
+message("\nInstalling depended libraries to ${CMAKE_INSTALL_PREFIX}/bin:\n")
+
+file(GLOB_RECURSE exe_list "${CMAKE_INSTALL_PREFIX}/*.exe")
+file(GLOB_RECURSE dll_list "${CMAKE_INSTALL_PREFIX}/*.dll")
+
+if(NOT (exe_list OR dll_list))
+	message("Exe and dll files not found, cannot generate dependency list")
+	return()
+endif(NOT (exe_list OR dll_list))
+
+set(mgl_all_dep)
+foreach(exe_file ${exe_list} ${dll_list})
+	get_prerequisites(${exe_file} DEPENDENCIES 1 1 "" "${CMAKE_INSTALL_PREFIX}/bin")
+	foreach(DEPENDENCY_FILE ${DEPENDENCIES})
+		gp_resolve_item("${exe_file}" "${DEPENDENCY_FILE}" "" "${CMAKE_INSTALL_PREFIX}/bin" resolved_file)
+		if(NOT resolved_file MATCHES ".*libmgl.*")
+			list(APPEND mgl_all_dep ${resolved_file})
+		endif(NOT resolved_file MATCHES ".*libmgl.*")
+	endforeach(DEPENDENCY_FILE ${DEPENDENCIES})
+endforeach(exe_file ${exe_list})
+
+list(REMOVE_DUPLICATES mgl_all_dep)
+list(SORT mgl_all_dep)
+
+foreach(dll_file ${mgl_all_dep})
+	message("Installing: ${dll_file}")
+endforeach(dll_file ${mgl_all_dep})
+
+file(COPY ${mgl_all_dep} DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
+
+if(mgl_qt_loc)
+	message("Installing: ${mgl_qt_loc}")
+	file(COPY ${mgl_qt_loc} DESTINATION "${CMAKE_INSTALL_PREFIX}/bin/plugins/platforms")
+endif(mgl_qt_loc)

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/mathgl.git



More information about the debian-science-commits mailing list